unit utest18;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, utest, Graphics, BGRABitmap, BGRABitmapTypes;

const
  nbPoints = 3;

type
  { TTest18 }

  TTest18 = class(TTest)
  protected
    virtualScreen,texture,backgroundTile,background: TBGRABitmap;
    pts: array of TPointF;
    dirs: array of TPointF;
    angle: single;

  public
    constructor Create;
    destructor Destroy; override;
    procedure OnPaint(Canvas: TCanvas; Left,Top,Width,Height: Integer); override;
    procedure OnTimer(Width,Height: Integer; ElapsedSec: Double); override;
  end;

implementation

{ TTest18 }

constructor TTest18.Create;
begin
  inherited Create;
  Name := 'Affine image transformation';
  texture := TBGRABitmap.Create(ResourceDir+'pac_d1.bmp');
  texture.ReplaceColor(texture.GetPixel(0,0),BGRAPixelTransparent);
  backgroundTile := TBGRABitmap.Create(ResourceDir+'diamondback.png');
  randomize;
  virtualScreen := nil;
  background := nil;
end;

destructor TTest18.Destroy;
begin
  texture.free;
  virtualScreen.Free;
  backgroundTile.Free;
  background.Free;
  inherited Destroy;
end;

procedure TTest18.OnPaint(Canvas: TCanvas; Left,Top,Width, Height: Integer);
begin
  if pts = nil then exit;

  if (virtualscreen <> nil) and ((virtualscreen.width <> width) or (virtualscreen.Height <> height)) then
  begin
    FreeAndNil(virtualScreen);
    FreeAndNil(background);
  end;

  if virtualscreen = nil then
  begin
    virtualscreen := TBGRABitmap.Create(Width,Height);
    background := backgroundTile.GetPart(rect(0,0,Width,Height));
  end;

  virtualScreen.PutImage(0,0,background,dmSet);
  virtualScreen.PutImageAffine(pts[1],pts[0],pts[2],texture);

  virtualScreen.DrawPolyLineAntialias(pts,BGRAWhite,3);
  virtualScreen.DrawPolyLineAntialias(pts,BGRABlack,1);

  virtualScreen.PutImageAngle(virtualScreen.Width div 2,virtualScreen.Height div 2,texture,angle,texture.Width/2,texture.Height/2);

  virtualScreen.draw(Canvas,Left,Top);
end;

procedure TTest18.OnTimer(Width, Height: Integer; ElapsedSec: Double);
var i: integer;
    moveFactor: single;
begin
  angle += ElapsedSec*20;
  if pts = nil then
  begin
    setlength(pts,nbPoints);
    setlength(dirs,nbPoints);
    for i := 0 to NbPoints-1 do
    begin
      pts[i] := pointf(random(Width),random(Height));
      dirs[i] := pointf((random(Width)-width/2)/20,(random(Height)-height/2)/20);
    end;
  end;
  moveFactor := ElapsedSec*20;
  for i := 0 to NbPoints-1 do
  begin
    pts[i].x := pts[i].x+dirs[i].x*moveFactor;
    if pts[i].x < 0 then
    begin
      pts[i].x := 0;
      dirs[i].x := abs(dirs[i].x);
    end;
    if pts[i].x > width-1 then
    begin
      pts[i].x := width-1;
      dirs[i].x := -abs(dirs[i].x);
    end;
    pts[i].y := pts[i].y+dirs[i].y*moveFactor;
    if pts[i].y < 0 then
    begin
      pts[i].y := 0;
      dirs[i].y := abs(dirs[i].y);
    end;
    if pts[i].y > height-1 then
    begin
      pts[i].y := height-1;
      dirs[i].y := -abs(dirs[i].y);
    end;
  end;
end;

end.

