unit _Camera;

interface

uses
  QuadEngine,
  _Forms,
  _Geometry;

type
TCamera = class   
  private
    FQuad: IQuadRender;    
    FQuadDevice: IQuadDevice;
    FBorder: Array [0..1] of TVector2;
    FScale: Single;
    FNeedScale: Single;
    FShift: TVector2;
    FNeedShift: TVector2;
    FCenter: TVector2;
  public            
    AddShift: TVector2;
    constructor Create(QuadEngine: IQuadRender);
    function  GetX(X: Extended): Extended;
    function  GetY(Y: Extended): Extended;  
    function  GetPos(Position: TVector2): TVector2;
    procedure Move(X, Y: Single);
    procedure MoveTo(Position: TVector2);
    procedure ScaleUp();
    procedure ScaleDown();             
    procedure Update(dt: single);
    property Shift:  TVector2    read FShift;
    property Scale:  Single      read FScale;
    property Center: TVector2    read FCenter;
    property Quad:   IQuadRender read FQuad;    
    property Device: IQuadDevice read FQuadDevice;
end;

var
  Camera: TCamera;

implementation

constructor TCamera.Create(QuadEngine: IQuadRender);
begin
  FQuad:= QuadEngine;
  FCenter:= Vector2(Window.Width / 2, Window.Height / 2);
  FScale:= 1;
  FNeedScale:= 0.2;
  FBorder[0]:= Vector2(-10000, -10000);
  FBorder[1]:= Vector2( 10000,  10000);
end;

function  TCamera.GetX(X: Extended): Extended;
begin
  Result:= (X - FShift.X + AddShift.X) * FScale + FCenter.X;
end;

function  TCamera.GetY(Y: Extended): Extended;
begin
  Result:= (Y - FShift.Y + AddShift.Y) * FScale + FCenter.Y;
end;

function  TCamera.GetPos(Position: TVector2): TVector2;
begin                                                  
  Result:= Vector2(
    (Position.X - FShift.X + AddShift.X) * FScale + FCenter.X,
    (Position.Y - FShift.Y + AddShift.Y) * FScale + FCenter.Y);
end;

procedure TCamera.Move(X, Y: Single);
begin
  FNeedShift:= FNeedShift - Vector2(X, Y) / FScale;
  If (FNeedShift.X < FBorder[0].X) then
    FNeedShift.X:= FBorder[0].X;               
  If (FNeedShift.Y < FBorder[0].Y) then
    FNeedShift.Y:= FBorder[0].Y;
  If (FNeedShift.X > FBorder[1].X) then
    FNeedShift.X:= FBorder[1].X;
  If (FNeedShift.Y > FBorder[1].Y) then
    FNeedShift.Y:= FBorder[1].Y;
end;

procedure TCamera.MoveTo(Position: TVector2);
begin
  FNeedShift:= Position;
end;

procedure TCamera.ScaleUp();
begin
  FNeedScale:= FNeedScale * 1.1;
  if FNeedScale > 1 then
    FNeedScale:= 1;
end;

procedure TCamera.ScaleDown();
begin                  
  FNeedScale:= FNeedScale * 0.95;
  if FNeedScale < 0.2 then
    FNeedScale:= 0.2;
end;

procedure TCamera.Update(dt: single);
begin
  FScale:= FScale * (0.95 - dt * 10) + FNeedScale * (0.05 + dt * 10);
  FShift:= FShift * (0.96)  + FNeedShift * (0.04);
end;

end.
