unit uMeForm;

{$mode delphi}

interface

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

  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;
    procedure Draw(pX, pY, Color : Integer; pAlpha : Byte); virtual;
    procedure DrawGlow(pX, pY, Color : Integer; pAlpha : Byte); virtual;
    function GetMaxSize : Single; virtual; abstract;
  end;

  { 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, Color : Integer; pAlpha : Byte); override;
    procedure DrawGlow(pX, pY, Color : Integer; pAlpha : Byte); override;
    function GetMaxSize : Single; override;
  end;

  { 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, Color : Integer; pAlpha : Byte); override;
    procedure DrawGlow(pX, pY, Color : Integer; pAlpha : Byte); override;
    function GetMaxSize : Single; override;
  end;

  { TMeFormObject }

  TMeFormObject = class
    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; PForm : TMeForm);
    procedure Click; virtual;
    function  ClickTest : Boolean; virtual;
    procedure Draw(pX, pY : Integer; pAlpha : Byte); virtual;
    function  TestChecked : boolean; virtual;
    function  Update(pX, pY : Integer) : Boolean;
    destructor Free;
  end;

  { TMeFormObjectText }

  TMeFormObjectText = class(TMeFormObject)
    Text : string;
    TextX, TextY : Integer;
    constructor Create(pX, pY : Integer; pSText : string; PShape : TMeFormShape; PForm : TMeForm); overload; virtual;
    procedure Draw(pX, pY : Integer; pAlpha : Byte); override;
  end;


  { TMeForm }

  TMeForm = class
    private
      fVisible : Boolean;
      function  getVisible : Boolean;
      procedure setVisible(Value: Boolean);
    public
    Scene : TScene;
    Obj : array of TMeFormObject;
    dAlpha, X, Y  : Integer;
    Alpha : Byte;

    property    Visible   : Boolean read getVisible write setVisible;
    function    IsActive : Boolean;
    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;

    TButtonEMClose = class(TMeFormObjectText)
    procedure Click; override;
  end;




  TMeRect = record
    X, Y, W, H : Integer;
  end;

  var
    vFormFont : zglPFont;

implementation
uses
  GSound;

const
  TEXT_ALIGN_CENTER = TEXT_HALIGN_CENTER or TEXT_VALIGN_CENTER;
  cGlowBord = 5;
  cGlowBord2 = cGlowBord * 2;

{ TMeFormObjectText }

procedure TButtonEMClose.Click;
begin
  Form.Visible := False;
end;


constructor TMeFormObjectText.Create(pX, pY: Integer; pSText: string;
  PShape: TMeFormShape; PForm: TMeForm);
begin
  Create(pX, pY, PShape, PForm);
  Text := pSText;
  TextX := 0;
  TextY := 0;
end;

procedure TMeFormObjectText.Draw(pX, pY: Integer; pAlpha: Byte);
var
  vGlow : Integer;
begin
  pX := pX + X;
  pY := pY + Y;

  if Enabled then
  begin
    if Checked then
      Shape.Draw(pX, pY, $AFAFFF, pAlpha)
    else
    begin
      vGlow := Glow + pAlpha - 255;
      if vGlow > 0 then
      begin
        if vGlow > 255 then
          vGlow := 255
        else
          vGlow := Glow;
        Shape.DrawGlow(pX, pY, $F0A050, vGlow);
      end;
      Shape.Draw(pX, pY, $7FBFFF, pAlpha);
    end;
  end
  else
    Shape.Draw(pX, pY, $5F5F5F, pAlpha);

  text_DrawEx(vFormFont, pX + TextX, pY + TextY, 1, 0, Text, pAlpha, $000000, TEXT_ALIGN_CENTER);
end;

{ TMeFormDrawRect }

{ 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, Color: Integer; pAlpha : Byte);
begin

end;

procedure TMeFormShape.DrawGlow(pX, pY, Color: Integer; pAlpha: Byte);
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, Color: Integer; pAlpha : Byte);
{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); }
begin
  pr2d_Rect(pX + R.X, pY + R.Y, R.W, R.H, Color, pAlpha, PR2D_FILL);
end;

procedure TShapeRect.DrawGlow(pX, pY, Color: Integer; pAlpha: Byte);
begin
  pr2d_Rect(pX + R.X - cGlowBord, pY + R.Y - cGlowBord, R.W + cGlowBord2, R.H + cGlowBord2, Color, pAlpha, PR2D_FILL);
end;

function TShapeRect.GetMaxSize: Single;
begin
  result := Max(R.W, R.H);
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 div 2;
end;

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

procedure TShapeCircle.Draw(pX, pY, Color : Integer; pAlpha : Byte);
begin
  pr2d_Circle(pX + C.cX, pY + C.cY, C.Radius + 5, Color, pAlpha, PR2D_FILL);
end;

procedure TShapeCircle.DrawGlow(pX, pY, Color: Integer; pAlpha: Byte);
begin
  pr2d_Circle(pX + C.cX, pY + C.cY, C.Radius + 5 + cGlowBord, Color, pAlpha, PR2D_FILL);
end;

function TShapeCircle.GetMaxSize: Single;
begin
  result := C.Radius*2;
end;

{ TMeFormObject }

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

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

procedure TMeFormObject.Click;
begin

end;

function TMeFormObject.ClickTest: Boolean;
begin
  if (mouse_Click(M_BLEFT)) then
  begin
    PlaySound(1);
    Click;
    Result := True;
    Clicked := True;
    Checked := True;
    CheckedTime := 7;
  end
  else
    Result := False;
end;

procedure TMeFormObject.Draw(pX, pY : Integer; pAlpha : Byte);
begin
  Shape.Draw(X + pX, Y + pY, $FFFFFF, pAlpha);


//  DrawRect.Draw(Enabled, Checked, X + pX, Y + pY, Angle, pAlpha, Glow);
//  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;

    Result := ClickTest;

  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 }

function TMeForm.IsActive : Boolean;
var
  I : Integer;
begin

  if (Alpha > 0) or (Alpha < 255) then
  begin
    I := Alpha + dAlpha;
    if I < 0 then I := 0 else if I > 255 then I := 255;
    Alpha := I;
  end;

  if fVisible then
  begin
    result := true;
  end
  else
    result := Alpha > 250;
end;

function TMeForm.getVisible: Boolean;
begin
  result := {fVisible and} (Alpha > 1);
end;

procedure TMeForm.setVisible(Value: Boolean);
begin
  fVisible := Value;

  if fVisible then
  begin
    Alpha := 5;
    dAlpha := + 8
  end
  else
  begin
    Alpha := 254;
    dAlpha := - 8;
  end;
end;

constructor TMeForm.Create(pX, pY: Integer; pAlpha: Byte; PScene: TScene);
begin
  X := pX;
  Y := pY;
  Alpha := pAlpha;
  Scene := PScene;
  //Visible := true;
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
  Result := false;

  if Alpha >= 250 then
  begin
    pX := pX - X;
    pY := pY - Y;

    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;

end.

