{*************************************************************************
                Copyright (c) PilotLogic Software House

  Package pl_ORCA
  This file is part of CodeTyphon Studio (https://www.pilotlogic.com/)

 ***** BEGIN LICENSE BLOCK *****
 * Version: LGPL-2.1 with link exception (Modified LGPL)
 *
 * The contents of this file are subject to the 
 * GNU LIBRARY GENERAL PUBLIC LICENSE Version 2.1 (the "License")
 * with the following modification:
 * 
 * As a special exception, the copyright holders of this library give you
 * permission to link this library with independent modules to produce an
 * executable, regardless of the license terms of these independent modules,
 * and to copy and distribute the resulting executable under terms of your choice,
 * provided that you also meet, for each linked independent module, the terms
 * and conditions of the license of that module. An independent module is a
 * module which is not derived from or based on this library. If you modify this
 * library, you may extend this exception to your version of the library, but
 * you are not obligated to do so. If you do not wish to do so, delete this
 * exception statement from your version.
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * ***** END LICENSE BLOCK *****
 
***************************************************************************}

Unit orca_editor_brush;

{$mode objfpc}{$H+}

Interface

Uses
   LCLProc, LCLIntf, LCLType, LMessages, LResources, LazUtf8,
   Math, typinfo, IntfGraphics,
   Classes, Variants, SysUtils, Contnrs, Forms, Controls, Dialogs, Graphics,
   StdCtrls, DB, DBCtrls, ExtCtrls, Menus, Clipbrd, ActnList, ImgList,
   orca_scene2d,
   orca_editor_bitmap;

Type

   { TD2BrushDesign }

   TD2BrushDesign = Class(TForm)
      LabelGradR: TD2Label;
      panelSolid: TD2Rectangle;
      panelGradient: TD2Rectangle;
      solidQuad: TD2ColorQuad;
      solidPicker: TD2ColorPicker;
      gradQuad: TD2ColorQuad;
      d2BrushDesigner: TD2Scene;
      solidCont: TD2Rectangle;
      gradEditor: TD2GradientEdit;
      dsgnRoot: TD2Background;
      Layout1: TD2Layout;
      cnTextR: TD2Label;
      Layout2: TD2Layout;
      Layout3: TD2Layout;
      gradPicker: TD2ColorPicker;
      brushTabControl: TD2TabControl;
      tabNone: TD2TabItem;
      tabSolid: TD2TabItem;
      tabGradient: TD2TabItem;
      cbTextG: TD2Label;
      cbTextB: TD2Label;
      cbTextA: TD2Label;
      brushList: TD2ListBox;
      textSolidR: TD2NumberBox;
      textSolidG: TD2NumberBox;
      textSolidB: TD2NumberBox;
      textSolidA: TD2NumberBox;
      textGradR: TD2NumberBox;
      textGradG: TD2NumberBox;
      textGradB: TD2NumberBox;
      textGradA: TD2NumberBox;
      textSolidHex: TD2TextBox;
      textGradHex: TD2TextBox;
      gradColorRect: TD2ColorBox;
      solidColorRect: TD2ColorBox;
      tabBitmap: TD2TabItem;
      panelBitmap: TD2Layout;
      tabRes: TD2TabItem;
      panerRes: TD2Layout;
      bitmapImage: TD2Image;
      Layout5: TD2Layout;
      btnSelectBitmap: TD2Button;
      resList: TD2ListBox;
      Layout6: TD2Layout;
      btnMakeRes: TD2Button;
      cnLabel1: TD2Label;
      Rectangle1: TD2Rectangle;
      puptileModeList: TD2PopupBox;
      btnCancel: TD2Button;
      btnOK: TD2Button;
      makeResLayout: TD2Layout;
      cbgradAngle: TD2AngleButton;
      LabelGradA: TD2Label;
      cbgradKind: TD2PopupBox;
      gradAngleLabel: TD2Label;
      HudWindow1: TD2HudWindow;
      Procedure FormClose(Sender: TObject; Var anAction: TCloseAction);
      Procedure solidQuadChange(Sender: TObject);
      Procedure FormCreate(Sender: TObject);
      Procedure gradEditorChange(Sender: TObject);
      Procedure gradQuadChange(Sender: TObject);
      Procedure brushListChange(Sender: TObject);
      Procedure brushTabControlChange(Sender: TObject);
      Procedure textGradRChange(Sender: TObject);
      Procedure textGradHexChange(Sender: TObject);
      Procedure textSolidHexChange(Sender: TObject);
      Procedure btnSelectBitmapClick(Sender: TObject);
      Procedure btnMakeResClick(Sender: TObject);
      Procedure resListChange(Sender: TObject);
      Procedure puptileModeListChange(Sender: TObject);
      Procedure btnOKClick(Sender: TObject);
      Procedure btnCancelClick(Sender: TObject);
      Procedure textSolidRChange(Sender: TObject);
      Procedure cbgradAngleChange(Sender: TObject);
      Procedure cbgradKindChange(Sender: TObject);
   Protected
      Procedure Notification(AComponent: TComponent; Operation: TOperation);
      Function UniqueName(S: String): String;
   Private
      FBrush: TD2Brush;
      FScene: Id2Scene;
      FComp: TPersistent;
      Procedure SetBrush(Const Value: TD2Brush);
      Procedure SetComp(Const Value: TPersistent);
      Procedure rebuilResList;
   Public
      Property Comp: TPersistent read FComp write SetComp;
      Property Brush: TD2Brush read FBrush write SetBrush;
   End;

   TD2BrushDialog = Class(TD2CustomBrushDialog)
   Protected
      FShowBrushList: Boolean;
      FShowMakeResource: Boolean;
      FComponent: TComponent;
      FTitle: WideString;
   Public
      Constructor Create(AOwner: TComponent); Override;
      Destructor Destroy; Override;
      Function Execute: Boolean; Override;
      Property Component: TComponent read FComponent write FComponent;
   Published
      Property ShowBrushList: Boolean read FShowBrushList write FShowBrushList Default True;
      Property ShowMakeResource: Boolean read FShowMakeResource write FShowMakeResource;
      Property Title: WideString read FTitle write FTitle;
   End;

Procedure SelectInDesign(AObject: TObject; AComp: TPersistent);
Procedure ShowBrushDialog(Const Brush: TD2Brush; Const ShowStyles: TD2BrushStyles; Const ShowBrushList: Boolean);
Procedure ShowGradientDialog(Const Gradient: TD2Gradient);
Function ShowColorDialog(Const Color: String): String;

Function fnCreateABrushDialog(Sender: TObject): TD2BrushDialog;

Var
   GvarD2BrushDesign: TD2BrushDesign;

Implementation

{$R *.lfm}

//========================================================
Function fnCreateABrushDialog(Sender: TObject): TD2BrushDialog;
Var
   xDlg: TD2BrushDialog;
Begin
   xDlg := TD2BrushDialog.Create(nil);
   Result := xDlg;
End;

Procedure ShowBrushDialog(Const Brush: TD2Brush; Const ShowStyles: TD2BrushStyles; Const ShowBrushList: Boolean);
Var
   xDlg: TD2BrushDialog;
Begin
   xDlg := TD2BrushDialog.Create(nil);
   xDlg.Brush := Brush;
   xDlg.ShowStyles := ShowStyles;
   xDlg.ShowBrushList := ShowBrushList;

   If xDlg.Execute Then
   Begin
      Brush.Assign(xDlg.Brush);
   End;

   xDlg.Free;
End;

Procedure ShowGradientDialog(Const Gradient: TD2Gradient);
Var
   xDlg: TD2BrushDialog;
Begin
   xDlg := TD2BrushDialog.Create(nil);
   xDlg.Brush.Style := d2BrushGradient;
   xDlg.Brush.Gradient := Gradient;
   xDlg.ShowStyles := [d2BrushGradient];
   xDlg.ShowBrushList := False;

   If xDlg.Execute Then
   Begin
      Gradient.Assign(xDlg.Brush.Gradient);
   End;

   xDlg.Free;
End;

Function ShowColorDialog(Const Color: String): String;
Var
   xDlg: TD2BrushDialog;
Begin
   xDlg := TD2BrushDialog.Create(nil);
   xDlg.Brush.Style := d2BrushSolid;
   xDlg.Brush.Color := Color;
   xDlg.ShowStyles := [d2BrushSolid];
   xDlg.ShowBrushList := False;

   If xDlg.Execute Then
   Begin
      Result := xDlg.Brush.Color;
   End;

   xDlg.Free;
End;

Procedure SelectInDesign(AObject: TObject; AComp: TPersistent);
Begin
   If GvarD2BrushDesign = nil Then
   Begin
      GvarD2BrushDesign := TD2BrushDesign.Create(Application);
      Try
      Except
         GvarD2BrushDesign.Free;
         GvarD2BrushDesign := nil;
         Raise;
      End;
   End;

   If AObject = nil Then
   Begin
      GvarD2BrushDesign.Comp := nil;
      GvarD2BrushDesign.Brush := nil;
   End;
   If AObject Is TD2Brush Then
   Begin
      GvarD2BrushDesign.Comp := AComp;
      GvarD2BrushDesign.Brush := TD2Brush(AObject);
   End;
   If AObject Is TD2Object Then
   Begin
      GvarD2BrushDesign.Comp := TPersistent(AObject);
      GvarD2BrushDesign.Brush := nil;
   End;

   GvarD2BrushDesign.Show;
End;

//=============== TD2BrushDesign ====================================================

Procedure TD2BrushDesign.FormCreate(Sender: TObject);
Begin
   //---
End;

Procedure TD2BrushDesign.FormClose(Sender: TObject; Var anAction: TCloseAction);
Begin
   anAction := caFree;
   GvarD2BrushDesign := nil;
End;

Procedure TD2BrushDesign.Notification(AComponent: TComponent; Operation: TOperation);
Begin
   Inherited;
   If (Operation = opRemove) And (AComponent = FComp) Then
   Begin
      Brush := nil;
      Comp := nil;
   End;
End;

Procedure TD2BrushDesign.SetBrush(Const Value: TD2Brush);
Var
   i: Integer;
Begin
   FBrush := Value;
   If FBrush <> nil Then
   Begin
      Case FBrush.Style Of
         d2BrushNone:
         Begin
            brushTabControl.ItemIndex := tabNone.Index;
         End;
         d2BrushSolid:
         Begin
            solidPicker.Color := FBrush.SolidColor;
            gradEditor.Gradient.Assign(FBrush.Gradient);
            brushTabControl.ItemIndex := tabSolid.Index;
         End;
         d2BrushGradient:
         Begin
            solidPicker.Color := FBrush.SolidColor;
            gradEditor.Gradient.Assign(FBrush.Gradient);
            cbgradKind.ItemIndex := Integer(gradEditor.Gradient.Style);
            If gradEditor.Gradient.StopPosition.X - gradEditor.Gradient.StartPosition.X <> 0 Then
            Begin
               If gradEditor.Gradient.StopPosition.X - gradEditor.Gradient.StartPosition.X > 0 Then
                  cbgradAngle.Value := -d2RadToDeg(ArcTan((gradEditor.Gradient.StopPosition.Y - gradEditor.Gradient.StartPosition.Y) / (gradEditor.Gradient.StopPosition.X - gradEditor.Gradient.StartPosition.X)))
               Else
                  cbgradAngle.Value := -d2RadToDeg(ArcTan((gradEditor.Gradient.StopPosition.Y - gradEditor.Gradient.StartPosition.Y) / (gradEditor.Gradient.StopPosition.X - gradEditor.Gradient.StartPosition.X))) - 180;
            End;
            cbgradAngle.Visible := gradEditor.Gradient.Style = d2LinearGradient;
            gradQuadChange(Self);
            brushTabControl.ItemIndex := tabGradient.Index;
         End;
         d2BrushVisual: ;
         d2BrushBitmap:
         Begin
            brushTabControl.ItemIndex := tabBitmap.Index;
            bitmapImage.Bitmap.Assign(FBrush.Bitmap.Bitmap);
            puptileModeList.ItemIndex := Integer(FBrush.Bitmap.WrapMode);
         End;
         d2BrushResource:
         Begin
            brushTabControl.ItemIndex := tabRes.Index;
            rebuilResList;
         End;
      End;
      For i := 0 To brushList.Count - 1 Do
         If (brushList.ItemByIndex(i) <> nil) And (TD2Brush(brushList.ItemByIndex(i).Tag) = Brush) Then
            brushList.ItemIndex := i;
   End;
End;

Procedure TD2BrushDesign.SetComp(Const Value: TPersistent);
Var
   i: Integer;
   BrushButton: TD2ListBoxItem;
   BrushText: TD2TextControl;
   PropCount: Integer;
   PropList: PPropList;
   PropType: PTypeData;
Begin
   FComp := Value;
   If (FComp <> nil) And (FComp Is TD2Scene) Then
      FScene := TD2Scene(FComp);

   If (FComp <> nil) And (FComp Is TD2Object) Then
      FScene := TD2Object(FComp).Scene;

   Brush := nil;
   brushList.Clear;
   brushList.Height := 4;

   PropCount := GetPropList(FComp.ClassInfo, PropList);

   For i := 0 To PropCount - 1 Do
   Begin
      If PropList^[i]^.PropType^.Kind <> tkClass Then
         Continue;
      PropType := GetTypeData(PropList^[i]^.PropType);
      If PropType = nil Then
         Continue;
      If Not (PropType^.ClassType.ClassName = 'TD2Brush') Then
         Continue;
      BrushButton := TD2ListBoxItem.Create(Self);
      BrushButton.Parent := brushList;
      BrushButton.Height := 23;
      BrushButton.Tag := PtrInt(GetObjectProp(FComp, PropList^[i]^.Name));
      BrushText := TD2Label.Create(Self);
      BrushText.Parent := BrushButton;
      BrushText.Align := vaClient;
      BrushText.HitTest := False;
      BrushText.TextW := PropList^[i]^.Name;
      brushList.Height := brushList.Height + BrushButton.Height;
      If Brush = nil Then
         Brush := TD2Brush(GetObjectProp(FComp, PropList^[i]^.Name));
   End;
   brushList.ItemIndex := 0;
   FreeMem(PropList, SizeOf(PPropInfo) * PropCount);
End;

Function TD2BrushDesign.UniqueName(S: String): String;
Begin
   If (FComp <> nil) And (FComp Is TComponent) And (TComponent(FComp).Owner <> nil) And (TComponent(FComp).Owner Is TCustomForm) And (TCustomForm(TComponent(FComp).Owner).Designer <> nil) Then
      Result := TCustomForm(TComponent(FComp).Owner).Designer.UniqueName(S)
   Else
   If Designer <> nil Then
      Result := Designer.UniqueName(S)
   Else Begin
      Tag := Tag + 1;
      Result := S + IntToStr(Tag);
   End;
End;

Procedure TD2BrushDesign.solidQuadChange(Sender: TObject);
Begin
   If FBrush = nil Then
      Exit;
   solidQuad.Alpha := ((FBrush.SolidColor And $FF000000) Shr 24) / $FF;
   FBrush.SolidColor := (FBrush.SolidColor And Not $FFFFFF) Or ($00FFFFFF And d2HSLtoRGB(solidQuad.Hue, solidQuad.Sat, solidQuad.Lum));
   textSolidR.Value := TD2ColorRec(FBrush.SolidColor).R;
   textSolidG.Value := TD2ColorRec(FBrush.SolidColor).G;
   textSolidB.Value := TD2ColorRec(FBrush.SolidColor).B;
   textSolidA.Value := TD2ColorRec(FBrush.SolidColor).A;
   textSolidHex.TextW := d2ColorToStr(FBrush.SolidColor);
End;

Procedure TD2BrushDesign.textSolidHexChange(Sender: TObject);
Begin
   If FBrush = nil Then
      Exit;
   FBrush.SolidColor := d2StrToColor(textSolidHex.TextW);
   solidPicker.Color := FBrush.SolidColor;
End;

Procedure TD2BrushDesign.textSolidRChange(Sender: TObject);
Var
   xColor: TD2Color;
Begin
   If FBrush = nil Then
      Exit;
   xColor := FBrush.SolidColor;
   TD2ColorRec(xColor).R := trunc(textSolidR.Value);
   TD2ColorRec(xColor).G := trunc(textSolidG.Value);
   TD2ColorRec(xColor).B := trunc(textSolidB.Value);
   TD2ColorRec(xColor).A := trunc(textSolidA.Value);
   FBrush.SolidColor := xColor;
   solidPicker.Color := FBrush.SolidColor;
End;

Procedure TD2BrushDesign.gradEditorChange(Sender: TObject);
Begin
   If FBrush = nil Then
      Exit;
   FBrush.Gradient.Assign(gradEditor.Gradient);
End;

Procedure TD2BrushDesign.gradQuadChange(Sender: TObject);
Begin
   If FBrush = nil Then
      Exit;
   gradEditor.Gradient.Points[gradEditor.CurrentPoint].IntColor :=
      (gradEditor.Gradient.Points[gradEditor.CurrentPoint].IntColor And $FF000000) Or ($00FFFFFF And d2HSLtoRGB(gradQuad.Hue, gradQuad.Sat, gradQuad.Lum));
   FBrush.Gradient.Assign(gradEditor.Gradient);
   textGradR.Value := TD2ColorRec(gradColorRect.Color).R;
   textGradG.Value := TD2ColorRec(gradColorRect.Color).G;
   textGradB.Value := TD2ColorRec(gradColorRect.Color).B;
   textGradA.Value := TD2ColorRec(gradColorRect.Color).A;
   textGradHex.TextW := d2ColorToStr(gradColorRect.Color);
   gradEditor.Repaint;
End;

Procedure TD2BrushDesign.brushListChange(Sender: TObject);
Begin
   If FScene = nil Then
      Exit;
   If FComp = nil Then
      Exit;
   If Sender <> nil Then
      Brush := TD2Brush(TD2ListBoxItem(Sender).Tag);
End;

Procedure TD2BrushDesign.brushTabControlChange(Sender: TObject);
Begin
   If FBrush = nil Then
      Exit;
   If brushTabControl.ItemIndex = tabNone.Index Then
      FBrush.Style := d2BrushNone;
   If brushTabControl.ItemIndex = tabSolid.Index Then
      FBrush.Style := d2BrushSolid;
   If brushTabControl.ItemIndex = tabGradient.Index Then
   Begin
      FBrush.Style := d2BrushGradient;
      gradQuadChange(Sender);
      gradAngleLabel.TextW := IntToStr(Trunc(cbgradAngle.Value));
   End;
   If brushTabControl.ItemIndex = tabBitmap.Index Then
      FBrush.Style := d2BrushBitmap;
   If brushTabControl.ItemIndex = tabRes.Index Then
      FBrush.Style := d2BrushResource;

   btnMakeRes.Visible := (brushTabControl.ItemIndex <> tabRes.Index) And (brushTabControl.ItemIndex <> tabNone.Index);
   If Not btnMakeRes.Visible Then
      rebuilResList;
End;

Procedure TD2BrushDesign.textGradRChange(Sender: TObject);
Var
   xColor: TD2Color;
Begin
   If FBrush = nil Then
      Exit;
   xColor := gradEditor.Gradient.Points[gradEditor.CurrentPoint].IntColor;
   TD2ColorRec(xColor).R := trunc(textGradR.Value);
   TD2ColorRec(xColor).G := trunc(textGradG.Value);
   TD2ColorRec(xColor).B := trunc(textGradB.Value);
   TD2ColorRec(xColor).A := trunc(textGradA.Value);
   gradEditor.Gradient.Points[gradEditor.CurrentPoint].IntColor := xColor;
   gradEditor.UpdateGradient;
End;

Procedure TD2BrushDesign.cbgradKindChange(Sender: TObject);
Begin
   If FBrush = nil Then
      Exit;
   gradEditor.Gradient.Style := TD2GradientStyle(cbgradKind.ItemIndex);
   gradEditor.UpdateGradient;
   cbgradAngle.Visible := gradEditor.Gradient.Style = d2LinearGradient;
End;

Procedure TD2BrushDesign.cbgradAngleChange(Sender: TObject);
Var
   X, Y, Koef: Single;
Begin
   If FBrush = nil Then
      Exit;
   If (Cos(d2DegToRad(cbgradAngle.Value)) <> 0) And (Abs(1 / Cos(d2DegToRad(cbgradAngle.Value))) >= 1) And (Abs(1 / Cos(d2DegToRad(cbgradAngle.Value))) <= 1.42) Then
      X := Abs(1 / Cos(d2DegToRad(cbgradAngle.Value)))
   Else
      X := 1;
   If (Sin(d2DegToRad(cbgradAngle.Value)) <> 0) And (Abs(1 / Sin(d2DegToRad(cbgradAngle.Value))) >= 1) And (Abs(1 / Sin(d2DegToRad(cbgradAngle.Value))) <= 1.42) Then
      Y := Abs(1 / Sin(d2DegToRad(cbgradAngle.Value)))
   Else
      Y := 1;
   Koef := d2MaxFloat(X, Y);
   Koef := Koef * 0.5;
   gradEditor.Gradient.StartPosition.Point := d2Point(0.5 - (Cos(d2DegToRad(cbgradAngle.Value)) * Koef), 0.5 + (Sin(d2DegToRad(cbgradAngle.Value)) * Koef));
   gradEditor.Gradient.StopPosition.Point := d2Point(0.5 + (Cos(d2DegToRad(cbgradAngle.Value)) * Koef), 0.5 - (Sin(d2DegToRad(cbgradAngle.Value)) * Koef));
   gradEditor.UpdateGradient;
   gradAngleLabel.TextW := IntToStr(Trunc(cbgradAngle.Value));
End;

Procedure TD2BrushDesign.textGradHexChange(Sender: TObject);
Begin
   If FBrush = nil Then
      Exit;
   gradEditor.Gradient.Points[gradEditor.CurrentPoint].IntColor := d2StrToColor(textGradHex.TextW);
   gradEditor.UpdateGradient;
End;


Procedure TD2BrushDesign.resListChange(Sender: TObject);
Begin
   If FScene = nil Then
      Exit;
   If FScene.GetRoot = nil Then
      Exit;
   If FBrush = nil Then
      Exit;
   If Sender = nil Then
      Exit;

   FBrush.Assign(TD2BrushObject(TD2ListBoxItem(Sender).Tag).Brush);
   FBrush.Resource.Resource := TD2BrushObject(TD2ListBoxItem(Sender).Tag);
   FBrush.Style := d2BrushResource;
End;

Procedure TD2BrushDesign.btnSelectBitmapClick(Sender: TObject);
Begin
   If FBrush = nil Then
      Exit;
   GvarD2BitmapEditor := TD2BitmapEditor.Create(nil);
   GvarD2BitmapEditor.AssignFromBitmap(bitmapImage.Bitmap);
   If GvarD2BitmapEditor.ShowModal = mrOk Then
   Begin
      GvarD2BitmapEditor.AssignToBitmap(bitmapImage.Bitmap);
      FBrush.Bitmap.Bitmap.Assign(bitmapImage.Bitmap);
      If (FComp <> nil) And (FComp Is TD2VisualObject) Then
         TD2VisualObject(FComp).Repaint;
      bitmapImage.Repaint;
   End;
   GvarD2BitmapEditor.Free;
End;

Procedure TD2BrushDesign.btnMakeResClick(Sender: TObject);
Var
   S: String;
   B: TD2BrushObject;
Begin
   If FBrush = nil Then
      Exit;
   If FScene = nil Then
      Exit;
   If FScene.GetRoot = nil Then
      Exit;


   S := UniqueName('Brush');
   If InputQuery('New TD2BrushObject', 'Enter resource name:', S) Then
   Begin
      B := TD2BrushObject.Create(FScene.GetOwner);
      B.Parent := FScene.GetRoot;
      B.ResourceName := S;
      B.Name := B.ResourceName;
      B.ResourceName := S;
      B.Brush.Assign(FBrush);

      rebuilResList;
   End;
End;

Procedure TD2BrushDesign.puptileModeListChange(Sender: TObject);
Begin
   If FBrush = nil Then
      Exit;
   FBrush.Bitmap.WrapMode := TD2WrapMode(puptileModeList.ItemIndex);

   If (FComp <> nil) And (FComp Is TD2VisualObject) Then
      TD2VisualObject(FComp).Repaint;
End;

Procedure TD2BrushDesign.btnOKClick(Sender: TObject);
Begin
   ModalResult := mrOk;
   Close;
End;

Procedure TD2BrushDesign.btnCancelClick(Sender: TObject);
Begin
   ModalResult := mrCancel;
   Close;
End;

Procedure TD2BrushDesign.rebuilResList;
Var
   i: Integer;
   L: TList;
   item: TD2ListBoxItem;
   itemText: TD2TextControl;
   rect: TD2Rectangle;
Begin
   If FScene = nil Then
      Exit;
   If FScene.GetRoot = nil Then
      Exit;
   If FBrush = nil Then
      Exit;

   resList.Clear;

   L := TList.Create;
   FScene.GetRoot.AddObjectsToList(L);
   For i := 0 To L.Count - 1 Do
      If TD2Object(L[i]) Is TD2BrushObject Then
      Begin
         item := TD2ListBoxItem.Create(Self);
         item.Tag := PtrInt(L[i]);
         item.Parent := resList;
         itemText := TD2Label.Create(Self);
         itemText.Parent := item;
         itemText.Align := vaClient;
         itemText.HitTest := False;
         itemText.TextW := TD2Object(L[i]).ResourceName;
         rect := TD2Rectangle.Create(Self);
         rect.Parent := item;
         rect.Align := vaLeft;
         rect.HitTest := False;
         rect.Padding.Rect := d2Rect(2, 2, 2, 2);
         rect.Fill.Style := d2BrushResource;
         rect.Fill.Resource.Resource := TD2BrushObject(L[i]);
         rect.Stroke.Color := '#80FFFFFF';
         If FBrush.Resource.Resource = TD2BrushObject(L[i]) Then
            resList.ItemIndex := resList.Count - 1;
      End;
   L.Free;
End;

//=============== TD2BrushDialog =================================================

Constructor TD2BrushDialog.Create(AOwner: TComponent);
Begin
   Inherited;
   FShowBrushList := True;
   FShowMakeResource := False;
   FTitle := 'Brush';
End;

Destructor TD2BrushDialog.Destroy;
Begin
   Inherited;
End;

Function TD2BrushDialog.Execute: Boolean;
Var
   Dialog: TD2BrushDesign;
Begin
   Dialog := TD2BrushDesign.Create(Application);
   Dialog.brushList.Visible := ShowBrushList;
   If FComponent <> nil Then
      Dialog.Comp := FComponent
   Else
      Dialog.brushList.Visible := False;

   Dialog.HudWindow1.TextW := FTitle;
   Dialog.brushTabControl.ItemIndex := -1;
   Dialog.tabNone.Visible := d2BrushNone In ShowStyles;
   Dialog.tabSolid.Visible := d2BrushSolid In ShowStyles;
   Dialog.tabGradient.Visible := d2BrushGradient In ShowStyles;
   Dialog.tabBitmap.Visible := d2BrushBitmap In ShowStyles;
   Dialog.tabRes.Visible := d2BrushResource In ShowStyles;
   Dialog.brushTabControl.Realign;
   Dialog.btnOK.Visible := True;
   Dialog.btnCancel.Visible := True;

   Dialog.Brush := FBrush;
   Dialog.makeResLayout.Visible := ShowMakeResource;
   Dialog.dsgnRoot.Height := Dialog.dsgnRoot.Height - 1;
   Dialog.ClientHeight := Trunc(Dialog.Layout6.Position.Y + Dialog.Layout6.Height + Dialog.HudWindow1.Margins.Top + Dialog.HudWindow1.Margins.Bottom);
   Result := Dialog.ShowModal = mrOk;
   Dialog.Free;
End;


//===========================================

Initialization
   VarCreateABrushDialog := TD2CreateACustomBrushDialog(@fnCreateABrushDialog);
   VarSelectInDesign := @SelectInDesign;
   VarShowGradientDialog := @ShowGradientDialog;
End.
