unit Vis3D_GeoObjSettings;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, TextEditor, Vcl.StdCtrls, rgl,
  UxPanel, Vcl.ExtCtrls, ColorContainer, ScrollBoxEx, Vcl.WinXPanels, Vcl.Menus;

type
  TVis3D_GeoObjSettingsFrm = class(TDrawableOptionsFrm3D)
    btnApply: TUxButton;
    ScrollBox1: TScrollBoxEx;
    lblColor: TLabel;
    lblLineWidth: TLabel;
    lblStyle: TLabel;
    lblTransform: TLabel;
    lblLineWidthUnit: TLabel;
    ccColor: TColorContainer;
    eLineWidth: TTextEditor;
    cTrans: TCardPanel;
    cTransSimple: TCard;
    lblPosition: TLabel;
    lblDirection: TLabel;
    lblScale: TLabel;
    lblRotation: TLabel;
    ePosX: TTextEditor;
    ePosY: TTextEditor;
    ePosZ: TTextEditor;
    eDirX: TTextEditor;
    eDirY: TTextEditor;
    eDirZ: TTextEditor;
    eScaleX: TTextEditor;
    eScaleY: TTextEditor;
    eScaleZ: TTextEditor;
    eRot: TTextEditor;
    cTransAdvanced: TCard;
    m11: TTextEditor;
    m12: TTextEditor;
    m13: TTextEditor;
    m21: TTextEditor;
    m22: TTextEditor;
    m23: TTextEditor;
    m31: TTextEditor;
    m32: TTextEditor;
    m33: TTextEditor;
    m41: TTextEditor;
    m42: TTextEditor;
    m43: TTextEditor;
    m14: TTextEditor;
    m24: TTextEditor;
    m34: TTextEditor;
    m44: TTextEditor;
    lblMatrix: TLabel;
    cbTransKind: TComboBox;
    pmTrans: TPopupMenu;
    mnuUseAsMatrix: TMenuItem;
    procedure btnApplyClick(Sender: TObject);
    procedure ccColorChange(Sender: TObject);
    procedure cbTransKindChange(Sender: TObject);
    procedure mnuUseAsMatrixClick(Sender: TObject);
  strict private
    FCustomized: Boolean;
    FNoStyle: Boolean;
    FNoTransforms: Boolean;
    FNoChrome: Boolean;
  public
    procedure Customize(AStyle, ATransforms, AChrome: Boolean);
    procedure Initialize; override;
    procedure UpdateDrawable; override;
  end;

implementation

{$R *.dfm}

procedure TVis3D_GeoObjSettingsFrm.btnApplyClick(Sender: TObject);
begin
  UpdateDrawable;
end;

procedure TVis3D_GeoObjSettingsFrm.cbTransKindChange(Sender: TObject);
begin
  cTrans.ActiveCardIndex := cbTransKind.ItemIndex;
  UpdateDrawable;
end;

procedure TVis3D_GeoObjSettingsFrm.ccColorChange(Sender: TObject);
begin
  UpdateDrawable;
end;

procedure TVis3D_GeoObjSettingsFrm.Customize(AStyle, ATransforms,
  AChrome: Boolean);

const
  TAG_STYLE = 10;
  TAG_TRANS = 20;

begin

  if FCustomized then
    Exit;

  FCustomized := True;
  FNoStyle := not AStyle;
  FNoTransforms := not ATransforms;
  FNoChrome := not AChrome;

  const VertDelta = cbTransKind.Top - lblStyle.Top;
  const Padding = lblStyle.BoundsRect.TopLeft;

  for var i := 0 to ScrollBox1.ControlCount - 1 do
  begin
    var Ctl := ScrollBox1.Controls[i];
    if not AStyle then
    begin
      if Ctl.Tag = TAG_STYLE then
        Ctl.Hide;
      if Ctl.Tag = TAG_TRANS then
        Ctl.Top := Ctl.Top - VertDelta;
    end;
    if not ATransforms then
      if Ctl.Tag = TAG_TRANS then
        Ctl.Hide;
    if not AChrome then
    begin
      Ctl.Left := Ctl.Left - Padding.X;
      Ctl.Top := Ctl.Top - Padding.Y;
    end;
  end;

  if not AChrome then
  begin

    FreeAndNil(btnApply);

    ScrollBox1.Anchors := [akLeft, akTop];

    if ATransforms then
      ScrollBox1.ClientHeight := cTrans.BoundsRect.Bottom + 8
    else if AStyle then
      ScrollBox1.ClientHeight := eLineWidth.BoundsRect.Bottom + 8
    else
      ScrollBox1.ClientHeight := 8;

    ScrollBox1.ClientWidth := cTrans.BoundsRect.Right + 8;

    Self.ClientWidth := ScrollBox1.Width;
    Self.ClientHeight := ScrollBox1.Height;

  end;

end;

procedure TVis3D_GeoObjSettingsFrm.Initialize;
begin
  inherited;
  var Obj := FDrawable as TGeometricObject3D;
  if not FNoStyle then
  begin
    if Obj.ColorNotApplicable then
    begin
      lblColor.Enabled := False;
      ccColor.Enabled := False;
    end
    else
      ccColor.Color := Obj.Color;
    eLineWidth.PlainText := FormatFloat('0.###', Obj.LineWidth);
  end;
  if not FNoTransforms then
  begin
    ePosX.PlainText := Obj.Position.x.ToString;
    ePosY.PlainText := Obj.Position.y.ToString;
    ePosZ.PlainText := Obj.Position.z.ToString;
    eDirX.PlainText := Obj.Direction.x.ToString;
    eDirY.PlainText := Obj.Direction.y.ToString;
    eDirZ.PlainText := Obj.Direction.z.ToString;
    eScaleX.PlainText := Obj.Scale.x.ToString;
    eScaleY.PlainText := Obj.Scale.y.ToString;
    eScaleZ.PlainText := Obj.Scale.z.ToString;
    eRot.PlainText := Obj.Rotation.ToString;
    m11.PlainText := Obj.ManualMatrix.m[0, 0].ToString;
    m12.PlainText := Obj.ManualMatrix.m[0, 1].ToString;
    m13.PlainText := Obj.ManualMatrix.m[0, 2].ToString;
    m14.PlainText := Obj.ManualMatrix.m[0, 3].ToString;
    m21.PlainText := Obj.ManualMatrix.m[1, 0].ToString;
    m22.PlainText := Obj.ManualMatrix.m[1, 1].ToString;
    m23.PlainText := Obj.ManualMatrix.m[1, 2].ToString;
    m24.PlainText := Obj.ManualMatrix.m[1, 3].ToString;
    m31.PlainText := Obj.ManualMatrix.m[2, 0].ToString;
    m32.PlainText := Obj.ManualMatrix.m[2, 1].ToString;
    m33.PlainText := Obj.ManualMatrix.m[2, 2].ToString;
    m34.PlainText := Obj.ManualMatrix.m[2, 3].ToString;
    m41.PlainText := Obj.ManualMatrix.m[3, 0].ToString;
    m42.PlainText := Obj.ManualMatrix.m[3, 1].ToString;
    m43.PlainText := Obj.ManualMatrix.m[3, 2].ToString;
    m44.PlainText := Obj.ManualMatrix.m[3, 3].ToString;
    cTrans.ActiveCardIndex := Ord(Obj.UseManualMatrix <> False);
    cbTransKind.OnChange := nil;
    try
      cbTransKind.ItemIndex := cTrans.ActiveCardIndex;
    finally
      cbTransKind.OnChange := cbTransKindChange
    end;
  end;
end;

procedure TVis3D_GeoObjSettingsFrm.mnuUseAsMatrixClick(Sender: TObject);
begin
  if not FInitialized then
    Exit;
  UpdateDrawable;
  var Obj := FDrawable as TGeometricObject3D;
  Obj.SetManualMatrix;
  Initialize;
end;

procedure TVis3D_GeoObjSettingsFrm.UpdateDrawable;
begin
  if not FInitialized then
    Exit;
  var Obj := FDrawable as TGeometricObject3D;
  if not FNoStyle then
  begin
    Obj.Color := ccColor.Color;
    Obj.LineWidth := StrToFloat(eLineWidth.PlainText);
  end;
  if not FNoTransforms then
  begin
    case cTrans.ActiveCardIndex of
      0:
        begin
          Obj.UseManualMatrix := False;
          Obj.Position := vec(
            StrToFloat(ePosX.PlainText),
            StrToFloat(ePosY.PlainText),
            StrToFloat(ePosZ.PlainText)
          );
          Obj.Direction := vec(
            StrToFloat(eDirX.PlainText),
            StrToFloat(eDirY.PlainText),
            StrToFloat(eDirZ.PlainText)
          );
          Obj.Scale := vec(
            StrToFloat(eScaleX.PlainText),
            StrToFloat(eScaleY.PlainText),
            StrToFloat(eScaleZ.PlainText)
          );
          Obj.Rotation := StrToFloat(eRot.PlainText);
        end;
      1:
        begin
          Obj.ManualMatrix := mat4(
            StrToFloat(m11.PlainText),
            StrToFloat(m12.PlainText),
            StrToFloat(m13.PlainText),
            StrToFloat(m14.PlainText),
            StrToFloat(m21.PlainText),
            StrToFloat(m22.PlainText),
            StrToFloat(m23.PlainText),
            StrToFloat(m24.PlainText),
            StrToFloat(m31.PlainText),
            StrToFloat(m32.PlainText),
            StrToFloat(m33.PlainText),
            StrToFloat(m34.PlainText),
            StrToFloat(m41.PlainText),
            StrToFloat(m42.PlainText),
            StrToFloat(m43.PlainText),
            StrToFloat(m44.PlainText)
          );
          Obj.UseManualMatrix := True;
        end;
    end;
  end;
  inherited;
end;

end.
