unit uMeForm;

{$mode delphi}

interface

uses
  Classes, SysUtils, zglHeader, uScene, Math;
type
  TMeForm = class;

  { TMeDrawRect }

  TMeDrawRect = class
    X, Y, W, H, NUM : Integer;
    R : array of zglTRect;
    Texture : zglPTexture;
    constructor Create(pTexture : zglPTexture; pW, pH: Integer); overload;
    constructor Create(Src : TMeDrawRect); overload;

    procedure Add(pX, pY : Integer);
    procedure Draw(pX, pY, pA, pT : Integer; pAlpha : Byte); overload;
  end;

  { TMeFormDrawRect }

  TMeFormDrawRect = class(TMeDrawRect)
    procedure Draw(pEnable, pChecked : Boolean; pX, pY, pA : Integer; pAlpha, pGlow : Byte);
  end;

  { TMeFormShape }

  TMeFormShape = class
    procedure SizeAdd(pW, pH : Integer); virtual;
    function PointIn(pX, pY : Integer; Angle : Integer = 0) : Boolean; virtual;
    procedure Draw(pX, pY, pA : Integer); virtual;
  end;
  { TMeFormShapeRect }

  { TShapeRect }

  TShapeRect = class(TMeFormShape)
    R : zglTRect;
    constructor Create(pW, pH : Integer); overload;
    procedure SizeAdd(pW, pH : Integer); override;
    function PointIn(pX, pY : Integer; Angle : Integer = 0) : Boolean; override;
    procedure Draw(pX, pY, pA : Integer); override;
  end;

  { TMeFormShapeCircle }

  { TShapeCircle }

  TShapeCircle = class(TMeFormShape)
    C : zglTCircle;
    constructor Create(pD : Integer); overload;
    procedure SizeAdd(pW, pH : Integer); override;
    function PointIn(pX, pY : Integer; Angle : Integer = 0) : Boolean; override;
    procedure Draw(pX, pY, pA : Integer); override;
  end;

  { TMeFormObject }

  TMeFormObject = class
    Text : String;
    X, Y, Angle  : Integer;
    CheckedTime,
    Glow  : Byte;
    Form  : TMeForm;
    Shape : TMeFormShape;
    DrawRect : TMeFormDrawRect;
    Checked,
    Clicked, MouseIn,
    Enabled, Visible : Boolean;

    constructor Create(pX, pY : Integer; PShape : TMeFormShape; PDrawRect : TMeFormDrawRect; PForm : TMeForm);
    procedure Click; virtual;
    procedure Draw(pX, pY : Integer; pAlpha : Byte); virtual;
    function  TestChecked : boolean; virtual;
    function  Update(pX, pY : Integer) : Boolean;
    destructor Free;
  end;

  { TMeFormObject2 }

  TMeFormObject2 = class(TMeFormObject)
    DrawRect2 : TMeDrawRect;
    DrawN : Integer;
    constructor Create(pX, pY : Integer; PShape : TMeFormShape; PDrawRect : TMeFormDrawRect; PDrawRect2 : TMeDrawRect; pDrawN : Integer; PForm : TMeForm); overload;
    procedure Draw(pX, pY : Integer; pAlpha : Byte); override;
  end;

  { TMeForm }

  TMeForm = class
    Scene : TScene;
    Obj : array of TMeFormObject;
    X, Y  : Integer;
    Alpha : Byte;

    constructor Create(pX, pY : Integer; pAlpha : Byte; PScene : TScene); virtual;
    procedure AddObject(PObj : TMeFormObject);
    procedure Draw; virtual;
    function Update(pX, pY : Integer) : Boolean; virtual;
  end;



implementation
uses
  uGlobal;
{ TMeFormObject2 }

constructor TMeFormObject2.Create(pX, pY: Integer; PShape: TMeFormShape;
  PDrawRect: TMeFormDrawRect; PDrawRect2: TMeDrawRect; pDrawN: Integer;
  PForm: TMeForm);
begin
  Create(pX, pY, PShape, PDrawRect, PForm);
  DrawRect2 := PDrawRect2;
  DrawN := pDrawN;
end;

procedure TMeFormObject2.Draw(pX, pY: Integer; pAlpha: Byte);
begin
  DrawRect.Draw(Enabled, Checked, X + pX, Y + pY, Angle, pAlpha, Glow);
  if DrawRect2 <> nil then
  DrawRect2.Draw(X + pX, Y + pY, Angle, DrawN, pAlpha);
end;

{ TMeDrawRect }

constructor TMeDrawRect.Create(pTexture: zglPTexture; pW, pH: Integer);
begin
  X := - pW div 2;
  Y := - pH div 2;
  W := pW;
  H := pH;
  Texture := pTexture;
//  tex_SetFrameSize(PTexture, W, H);
end;

constructor TMeDrawRect.Create(Src: TMeDrawRect);
begin

end;

procedure TMeDrawRect.Add(pX, pY: Integer);
var
  I : Integer;
begin
  I := Length(R);
  SetLength(R, I + 1);
  R[I].X := pX;
  R[I].Y := pY;
  R[I].W := W;
  R[I].H := H;
end;

procedure TMeDrawRect.Draw(pX, pY, pA, pT: Integer; pAlpha: Byte);
begin
  csprite2d_Draw(Texture, pX + X, pY + Y, W, H, pA, R[pT], pAlpha);
end;



{ TMeFormDrawRect }

procedure TMeFormDrawRect.Draw(pEnable, pChecked : Boolean; pX, pY, pA : Integer; pAlpha, pGlow : Byte);
var
  Glow : Integer;
begin
  pX := pX + X;
  pY := pY + Y;

  if pEnable then
  begin
    if pChecked then
      csprite2d_Draw(Texture, pX, pY, W, H, pA, R[2], pAlpha)
    else
    begin
      csprite2d_Draw(Texture, pX, pY, W, H, pA, R[0], pAlpha);
      Glow := pGlow + pAlpha - 255;
      if Glow > 0 then
      begin
        if Glow > 255 then
          pGlow := 255
        else
          pGlow := Glow;
        csprite2d_Draw(Texture, pX, pY, W, H, pA, R[1], pGlow);
      end;
    end;
  end
  else
     csprite2d_Draw(Texture, pX, pY, W, H, pA, R[3], pAlpha);
end;

{ TMeFormShape }

procedure TMeFormShape.SizeAdd(pW, pH: Integer);
begin
  //writeln('0 size add ', pW, ' ', pH);
end;

function TMeFormShape.PointIn(pX, pY: Integer; Angle : Integer = 0): Boolean;
begin
  result := false;//(pX = X) and (pY = Y);
end;

procedure TMeFormShape.Draw(pX, pY, pA: Integer);
begin

end;

{ TShapeRect }

constructor TShapeRect.Create(pW, pH: Integer);
begin
  R.X := - pW div 2;
  R.Y := - pH div 2;
  R.W := pW;
  R.H := pH;
end;

procedure TShapeRect.SizeAdd(pW, pH: Integer);
begin
  R.X := R.X - pW div 2;
  R.Y := R.Y - pH div 2;
  R.W := R.W + pW;
  R.H := R.H + pH;
end;

function TShapeRect.PointIn(pX, pY: Integer; Angle : Integer = 0): Boolean;
var
  v2X, v2Y, vAX, vAY, vA : Single;
begin
  if Angle <> 0 then
  begin
    vA := Angle * deg2rad;

    v2X := pX;// - R.X;
    v2Y := pY;// - R.Y;

    vAX := cos(-vA);
    vAY := sin(-vA);

    pX := trunc({R.X} + v2X * vAX - v2Y * vAY);
    pY := trunc({R.Y} + v2X * vAY + v2Y * vAX);
  end;
  result := col2d_PointInRect(pX, pY, R);
end;

procedure TShapeRect.Draw(pX, pY, pA: Integer);
var
  w2, h2, X1, Y1, X2, Y2, X3, Y3, X4, Y4, t, L, angle : Single;
begin
  pr2d_Circle(pX, pY, 4);

  angle := -pA * deg2rad;
  w2 := R.W/2;
  h2 := R.H/2;

  t := arctan2(-w2, -h2);

  L := sqrt(w2 * w2 + h2 * h2) + 5;

  X1 := px + L * sin(angle + t);
  Y1 := py + L * cos(angle + t);
  pr2d_Circle(X1, Y1, 3);

  X2 := px + L * sin(angle - t);
  Y2 := py + L * cos(angle - t);
  pr2d_Circle(X2, Y2, 3);

  X3 := px + L * sin(angle + Pi + t);
  Y3 := py + L * cos(angle + Pi + t);
  pr2d_Circle(X3, Y3, 3);

  X4 := px + L * sin(angle + Pi - t);
  Y4 := py + L * cos(angle + Pi - t);
  pr2d_Circle(X4, Y4, 3);

  pr2d_Line(X1, Y1, X2, Y2);
  pr2d_Line(X2, Y2, X3, Y3);
  pr2d_Line(X3, Y3, X4, Y4);
  pr2d_Line(X4, Y4, X1, Y1);
end;

{ TShapeCircle }

constructor TShapeCircle.Create(pD: Integer);
begin
  C.cX := 0;
  C.cY := 0;
  C.Radius := pD div 2;
end;

procedure TShapeCircle.SizeAdd(pW, pH: Integer);
begin
  C.Radius := C.Radius + pW;
end;

function TShapeCircle.PointIn(pX, pY: Integer; Angle : Integer = 0): Boolean;
begin
  result := col2d_PointInCircle(pX, pY, C);
end;

procedure TShapeCircle.Draw(pX, pY, pA: Integer);
begin
  pr2d_Circle(pX + C.cX, pY + C.cY, C.Radius + 5);
  pr2d_Circle(pX + C.cX, pY + C.cY, 4);
end;

{ TMeFormObject }

constructor TMeFormObject.Create(pX, pY : Integer; PShape: TMeFormShape; PDrawRect : TMeFormDrawRect; PForm: TMeForm);
begin
  X := pX;
  Y := pY;
  Visible := true;
  Enabled := true;
  Glow := 0;

  Shape := PShape;
  DrawRect := PDrawRect;
  Form := PForm;
  if PForm <> nil then
    PForm.AddObject(Self);
end;

procedure TMeFormObject.Click;
begin
  //writeln('!');
end;

procedure TMeFormObject.Draw(pX, pY : Integer; pAlpha : Byte);
begin
  DrawRect.Draw(Enabled, Checked, X + pX, Y + pY, Angle, pAlpha, Glow);
  text_DrawEx(mFont, pX + X, pY + Y, 1, 0, Text, pAlpha, $050505, TEXT_VALIGN_CENTER or TEXT_HALIGN_CENTER);
//  pr2d_Circle(X + TShapeCircle(Shape).C.cX, Y + TShapeCircle(Shape).C.cY, TShapeCircle(Shape).C.Radius);
end;

function TMeFormObject.TestChecked: boolean;
begin
  if CheckedTime > 0 then
    CheckedTime := CheckedTime - 1;

  result := CheckedTime > 0;
end;

function TMeFormObject.Update(pX, pY: Integer): Boolean;
begin
  pX := pX - X;
  pY := pY - Y;

  if Shape.PointIn(pX, pY) then
  begin

    MouseIn := True;

    if Glow < 245 then
      Glow := Glow + 7
    else
      Glow := 255;

    if (mouse_Click(M_BLEFT)) then
    begin
      Click;
      Result := True;
      Clicked := True;
      Checked := True;
      CheckedTime := 7;
    end
    else
      Result := False;
  end
  else
  begin
    if Glow > 7 then
      Glow := Glow - 7
    else
      Glow := 0;

    MouseIn := False;
    Result := False;
    Clicked := False;
  end;


  Checked := TestChecked;
end;

destructor TMeFormObject.Free;
begin

end;

{ TMeForm }

constructor TMeForm.Create(pX, pY: Integer; pAlpha: Byte; PScene: TScene);
begin
  X := pX;
  Y := pY;
  Alpha := pAlpha;
  Scene := PScene;
end;

procedure TMeForm.AddObject(PObj: TMeFormObject);
var
  I : Integer;
begin
  I := Length(Obj);
  SetLength(Obj, I + 1);
  Obj[I] := PObj;
end;

procedure TMeForm.Draw;
var
  I : Integer;
begin
  for I := 0 to Length(Obj) - 1 do
  if Obj[I].Visible then
    Obj[I].Draw(X, Y, Alpha);
end;

function TMeForm.Update(pX, pY : Integer) : Boolean;
var
  I : Integer;
begin
  pX := pX - X;
  pY := pY - Y;

  Result := false;

  for I := 0 to Length(Obj) - 1 do
  if Obj[I].Enabled and Obj[I].Visible then
  if Obj[I].Update(pX, pY) then
    Result := true;
end;

end.

