2
// This unit is part of the GLScene Engine https://github.com/glscene
5
Scene Editor, for adding + removing scene objects within the Delphi IDE.
8
05/02/00 - EG - Fixed DragDrop, added root nodes auto-expansion
49
BEHAVIOURS_SELECTED=1;
52
TSetSubItemsEvent = procedure(Sender:TObject) of object;
54
{ TGLSceneEditorForm }
56
TGLSceneEditorForm = class(TForm)
59
ToolButton10: TToolButton;
60
ToolButton11: TToolButton;
61
ToolButton12: TToolButton;
62
ToolButton13: TToolButton;
63
ToolButton14: TToolButton;
64
ToolButton15: TToolButton;
65
ToolButton2: TToolButton;
66
ToolButton3: TToolButton;
67
ToolButton4: TToolButton;
68
ToolButton5: TToolButton;
69
ToolButton6: TToolButton;
70
ToolButton7: TToolButton;
72
PopupMenu: TPopupMenu;
73
MIAddCamera: TMenuItem;
74
MIAddObject: TMenuItem;
76
MIDelObject: TMenuItem;
78
ActionList: TActionList;
79
ToolButton1: TToolButton;
80
TBAddObjects: TToolButton;
81
PMToolBar: TPopupMenu;
84
ImageList: TImageList;
85
ACDeleteObject: TAction;
89
Moveobjectup1: TMenuItem;
90
Moveobjectdown1: TMenuItem;
93
OpenDialog: TOpenDialog;
94
SaveDialog: TSaveDialog;
95
ToolButton8: TToolButton;
96
ToolButton9: TToolButton;
104
PABehaviours: TPanel;
105
BehavioursListView: TListView;
106
Splitter3: TSplitter;
107
EffectsListView: TListView;
109
PMBehavioursToolbar: TPopupMenu;
110
ACAddBehaviour: TAction;
111
MIAddBehaviour: TMenuItem;
112
MIAddEffect: TMenuItem;
113
MIBehaviourSeparator: TMenuItem;
114
ACDeleteBehaviour: TAction;
115
BehavioursPopupMenu: TPopupMenu;
118
MoveDown1: TMenuItem;
122
PMEffectsToolbar: TPopupMenu;
123
ACAddEffect: TAction;
125
TBAddBehaviours: TToolButton;
126
TBAddEffects: TToolButton;
127
TBEffectsPanel: TToolButton;
128
TBStayOnTop: TToolButton;
129
ACStayOnTop: TAction;
130
procedure BehavioursListViewClick(Sender: TObject);
131
procedure EffectsListViewClick(Sender: TObject);
132
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
133
procedure FormCreate(Sender: TObject);
134
procedure ToolButton10Click(Sender: TObject);
135
procedure ToolButton15Click(Sender: TObject);
136
procedure TreeEditing(Sender: TObject; Node: TTreeNode; var AllowEdit: Boolean);
137
procedure TreeDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
138
procedure TreeDragDrop(Sender, Source: TObject; X, Y: Integer);
139
procedure TreeChange(Sender: TObject; Node: TTreeNode);
140
procedure TreeMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
141
procedure TreeEnter(Sender: TObject);
142
procedure TreeMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
143
procedure ACAddCameraExecute(Sender: TObject);
144
procedure ACDeleteObjectExecute(Sender: TObject);
145
procedure ACMoveUpExecute(Sender: TObject);
146
procedure ACMoveDownExecute(Sender: TObject);
147
procedure ACAddObjectExecute(Sender: TObject);
148
procedure ACSaveSceneExecute(Sender: TObject);
149
procedure ACLoadSceneExecute(Sender: TObject);
150
procedure FormDestroy(Sender: TObject);
151
procedure ACInfoExecute(Sender: TObject);
152
procedure ACCopyExecute(Sender: TObject);
153
procedure ACCutExecute(Sender: TObject);
154
procedure ACPasteExecute(Sender: TObject);
156
procedure ACAddBehaviourExecute(Sender: TObject);
157
procedure DeleteBaseBehaviour(ListView:TListView);
158
procedure PMBehavioursToolbarPopup(Sender: TObject);
159
procedure PMEffectsToolbarPopup(Sender: TObject);
160
procedure BehavioursListViewSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
161
procedure ACAddEffectExecute(Sender: TObject);
162
procedure PopupMenuPopup(Sender: TObject);
163
procedure TBEffectsPanelClick(Sender: TObject);
164
procedure TreeKeyDown(Sender: TObject; var Key: Word;
166
procedure ACStayOnTopExecute(Sender: TObject);
169
FSelectedItems:Integer; //
172
FObjectNode: TTreeNode;
173
FCurrentDesigner: TComponentEditorDesigner;
174
FLastMouseDownPos: TPoint;
175
FObjectList: TStringList;
179
// adds the given scene object as well as its children to the tree structure and returns
180
// the last add node (e.g. for selection)
181
function AddNodes(ANode: TTreeNode; AObject: TGLBaseSceneObject): TTreeNode;
182
procedure AddObjectClick(Sender: TObject);
183
procedure AddBehaviourClick(Sender: TObject);
184
procedure AddEffectClick(Sender: TObject);
185
procedure SetObjectsSubItems(parent : TMenuItem);
186
procedure SetXCollectionSubItems(parent : TMenuItem ; XCollection: TGLXCollection; Event:TSetSubItemsEvent);
187
procedure SetBehavioursSubItems(parent : TMenuItem; XCollection: TGLXCollection);
188
procedure SetEffectsSubItems(parent : TMenuItem; XCollection: TGLXCollection);
189
procedure OnBaseSceneObjectNameChanged(Sender : TObject);
190
function IsValidClipBoardNode : Boolean;
191
function IsPastePossible : Boolean;
192
procedure ShowBehaviours(BaseSceneObject:TGLBaseSceneObject);
193
procedure ShowEffects(BaseSceneObject:TGLBaseSceneObject);
194
procedure ShowBehavioursAndEffects(BaseSceneObject:TGLBaseSceneObject);
195
procedure EnableAndDisableActions();
196
procedure TreeEdited(Sender: TObject; Node: TTreeNode; var S: String);
199
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
202
procedure SetScene(AScene : TGLScene; ADesigner : TComponentEditorDesigner);
206
function GLSceneEditorForm : TGLSceneEditorForm;
207
procedure ReleaseGLSceneEditorForm;
209
// ------------------------------------------------------------------
210
// ------------------------------------------------------------------
211
// ------------------------------------------------------------------
213
// ------------------------------------------------------------------
214
// ------------------------------------------------------------------
215
// ------------------------------------------------------------------
218
cGLSceneEditor = 'GLScene Editor';
221
vGLSceneEditorForm : TGLSceneEditorForm;
223
function GLSceneEditorForm : TGLSceneEditorForm;
225
if not Assigned(vGLSceneEditorForm) then
226
vGLSceneEditorForm:=TGLSceneEditorForm.Create(nil);
227
Result:=vGLSceneEditorForm;
230
procedure ReleaseGLSceneEditorForm;
232
if Assigned(vGLSceneEditorForm) then begin
233
vGLSceneEditorForm.Free;
234
vGLSceneEditorForm:=nil;
240
cRegistryKey = 'Software\GLScene\GLSceneEditor';
242
function ReadRegistryInteger(reg : TRegistry; const name : String;
243
defaultValue : Integer) : Integer;
245
if reg.ValueExists(name) then
246
Result:=reg.ReadInteger(name)
247
else Result:=defaultValue;
253
function FindNodeByData(treeNodes : TTreeNodes; data : Pointer;
254
baseNode : TTreeNode = nil) : TTreeNode;
259
if Assigned(baseNode) then begin
260
n:=baseNode.getFirstChild;
261
while Assigned(n) do begin
262
if n.Data=data then begin
264
end else if n.HasChildren then begin
265
Result:=FindNodeByData(treeNodes, data, n);
266
if Assigned(Result) then Break;
268
n:=baseNode.GetNextChild(n);
271
n:=treeNodes.GetFirstNode;
272
while Assigned(n) do begin
273
if n.Data=data then begin
275
end else if n.HasChildren then begin
276
Result:=FindNodeByData(treeNodes, data, n);
277
if Assigned(Result) then Break;
284
//----------------- TGLSceneEditorForm ---------------------------------------------------------------------------------
288
procedure TGLSceneEditorForm.SetScene(AScene : TGLScene; ADesigner : TComponentEditorDesigner);
290
if Assigned(FScene) then begin
291
FScene.RemoveFreeNotification(Self);
294
FCurrentDesigner:=ADesigner;
296
BehavioursListView.Items.Clear;
297
EffectsListView.Items.Clear;
299
if Assigned(FScene) then begin
300
FScene.FreeNotification(Self);
302
Caption:=cGLSceneEditor+' : '+FScene.Name;
303
end else Caption:=cGLSceneEditor;
304
TreeChange(Self, nil);
305
if Assigned(FScene) then begin
307
BehavioursListView.Enabled:=true;
308
EffectsListView.Enabled:=true;
309
ACLoadScene.Enabled:=True;
310
ACSaveScene.Enabled:=True;
311
FSelectedItems:=SCENE_SELECTED;
312
EnableAndDisableActions;
315
BehavioursListView.Enabled:=False;
316
EffectsListView.Enabled:=False;
317
ACLoadScene.Enabled:=False;
318
ACSaveScene.Enabled:=False;
319
ACAddCamera.Enabled:=False;
320
ACAddObject.Enabled:=False;
321
ACAddBehaviour.Enabled:=False;
322
ACAddEffect.Enabled:=False;
323
ACDeleteObject.Enabled:=False;
324
ACMoveUp.Enabled:=False;
325
ACMoveDown.Enabled:=False;
326
ACCut.Enabled:=False;
327
ACCopy.Enabled:=False;
328
ACPaste.Enabled:=False;
331
ShowBehavioursAndEffects(nil);
336
procedure TGLSceneEditorForm.FormCreate(Sender: TObject);
338
CurrentNode: TTreeNode;
343
FObjectList := TStringList.Create;
344
RegisterGLBaseSceneObjectNameChangeEvent(OnBaseSceneObjectNameChanged);
345
Tree.Images:=ObjectManager.ObjectIcons;
346
Tree.Indent:=ObjectManager.ObjectIcons.Width;
347
with Tree.Items do begin
348
// first add the scene root
349
CurrentNode:=Add(nil, glsSceneRoot);
350
with CurrentNode do begin
351
ImageIndex:=ObjectManager.SceneRootIndex;
352
SelectedIndex:=ImageIndex;
354
// and the root for all objects
355
FObjectNode:=AddChild(CurrentNode, glsObjectRoot);
356
with FObjectNode do begin
357
ImageIndex:=ObjectManager.ObjectRootIndex;
358
SelectedIndex:=ObjectManager.ObjectRootIndex;
362
SetObjectsSubItems(MIAddObject);
363
MIAddObject.SubMenuImages:=ObjectManager.ObjectIcons;
364
SetObjectsSubItems(PMToolBar.Items);
365
PMToolBar.Images:=ObjectManager.ObjectIcons;
367
SetBehavioursSubItems(MIAddBehaviour, nil);
368
SetBehavioursSubItems(PMBehavioursToolBar.Items, nil);
369
SetEffectsSubItems(MIAddEffect, nil);
370
SetEffectsSubItems(PMEffectsToolBar.Items, nil);
373
reg:=TRegistry.Create;
375
if reg.OpenKey(cRegistryKey, True) then begin
376
if reg.ValueExists('EffectsPanel') then
377
TBEffectsPanel.Down:=reg.ReadBool('EffectsPanel');
378
TBEffectsPanelClick(Self);
379
Left:=ReadRegistryInteger(reg, 'Left', Left);
380
Top:=ReadRegistryInteger(reg, 'Top', Top);
381
Width:=ReadRegistryInteger(reg, 'Width', 250);
382
Height:=ReadRegistryInteger(reg, 'Height', Height);
389
// Trigger the event OnEdited manualy
390
Tree.OnEdited := TreeEdited;
393
procedure TGLSceneEditorForm.ToolButton10Click(Sender: TObject);
398
procedure TGLSceneEditorForm.ToolButton15Click(Sender: TObject);
400
if FObjectNode <> nil then try
401
Tree.Items.BeginUpdate;
402
FObjectNode.Collapse(true);
403
FObjectNode.Expand(false);
405
Tree.Items.EndUpdate;
411
procedure TGLSceneEditorForm.FormClose(Sender: TObject;
412
var CloseAction: TCloseAction);
415
CloseAction :=CloseAction;
420
procedure TGLSceneEditorForm.FormDestroy(Sender: TObject);
427
DeRegisterGLBaseSceneObjectNameChangeEvent(OnBaseSceneObjectNameChanged);
431
reg:=TRegistry.Create;
433
if reg.OpenKey(cRegistryKey, True) then begin
434
reg.WriteBool('EffectsPanel', TBEffectsPanel.Down);
435
reg.WriteInteger('Left', Left);
436
reg.WriteInteger('Top', Top);
437
reg.WriteInteger('Width', Width);
438
reg.WriteInteger('Height', Height);
446
//----------------------------------------------------------------------------------------------------------------------
448
procedure TGLSceneEditorForm.ReadScene;
454
Tree.Items.BeginUpdate;
457
if Assigned(Objects) then
459
FObjectNode.Data:=Objects;
461
for I:=0 to Count - 1 do AddNodes(FObjectNode, Children[I]);
462
FObjectNode.Expand(False);
465
Tree.Items.EndUpdate;
468
//----------------------------------------------------------------------------------------------------------------------
470
procedure TGLSceneEditorForm.ResetTree;
472
// delete all subtrees (empty tree)
473
Tree.Items.BeginUpdate;
475
with FObjectNode do begin
481
Tree.Items.EndUpdate;
485
//----------------------------------------------------------------------------------------------------------------------
487
function TGLSceneEditorForm.AddNodes(ANode: TTreeNode; AObject: TGLBaseSceneObject): TTreeNode;
490
CurrentNode: TTreeNode;
492
if IsSubComponent(AObject) then
494
Result := Tree.Selected;
499
Result := Tree.Items.AddChildObject(ANode, AObject.Name, AObject);
500
Result.ImageIndex := ObjectManager.GetImageIndex(TGLSceneObjectClass(AObject.ClassType));
501
Result.SelectedIndex := Result.ImageIndex;
502
CurrentNode := Result;
503
for I := 0 to AObject.Count - 1 do
504
Result := AddNodes(CurrentNode, AObject[I]);
508
procedure TGLSceneEditorForm.SetObjectsSubItems(parent : TMenuItem);
511
item, currentParent : TMenuItem;
512
currentCategory : String;
513
soc : TGLSceneObjectClass;
515
ObjectManager.GetRegisteredSceneObjects(FObjectList);
517
for i:=0 to FObjectList.Count-1 do
519
if FObjectList[i]<>'' then
521
with ObjectManager do
522
currentCategory:=GetCategory(TGLSceneObjectClass(FObjectList.Objects[i]));
523
if currentCategory='' then
524
currentParent:=parent
526
currentParent:=NewItem(currentCategory, 0, False, True, nil, 0, '');
527
parent.Add(currentParent);
530
for j := i to FObjectList.Count-1 do
532
if FObjectList[j]<>'' then
533
with ObjectManager do
535
soc:=TGLSceneObjectClass(FObjectList.Objects[j]);
536
if currentCategory=GetCategory(soc) then
538
item := NewItem(FObjectList[j], 0, False, True, AddObjectClick, 0, '');
539
item.ImageIndex := GetImageIndex(soc);
540
item.GlyphShowMode:= gsmAlways;
542
currentParent.Add(item);
543
FObjectList[j] := '';
544
if currentCategory='' then
554
procedure TGLSceneEditorForm.SetXCollectionSubItems(parent : TMenuItem ; XCollection: TGLXCollection; Event:TSetSubItemsEvent);
557
XCollectionItemClass : TGLXCollectionItemClass;
561
if Assigned(XCollection) then
563
FXObjectList := GetXCollectionItemClassesList(XCollection.ItemsClass);
564
for I:=0 to FXObjectList.Count-1 do begin
565
XCollectionItemClass:=TGLXCollectionItemClass(FXObjectList[i]);
566
mi:=TMenuItem.Create(owner);
567
mi.Caption:=XCollectionItemClass.FriendlyName;
570
if Assigned(XCollection) then
571
mi.Enabled:=XCollection.CanAdd(XCollectionItemClass)
573
mi.Enabled:=TBAddBehaviours.Enabled;
581
// SetBehavioursSubItems
583
procedure TGLSceneEditorForm.SetBehavioursSubItems(parent : TMenuItem ; XCollection: TGLXCollection);
585
SetXCollectionSubItems(parent, XCollection, AddBehaviourClick);
590
procedure TGLSceneEditorForm.SetEffectsSubItems(parent : TMenuItem ; XCollection: TGLXCollection);
592
SetXCollectionSubItems(parent, XCollection, AddEffectClick);
596
procedure TGLSceneEditorForm.AddObjectClick(Sender: TObject);
598
AParent, AObject: TGLBaseSceneObject;
602
if Assigned(FCurrentDesigner) then with Tree do
603
if Assigned(Selected) and (Selected.Level > 0) then
605
AParent:=TGLBaseSceneObject(Selected.Data);
606
I := TMenuItem(Sender).Tag;
607
AObject:=TGLBaseSceneObject(TGLSceneObjectClass(FObjectList.Objects[I]).Create(FScene.Owner));
608
AObject.Name:=FCurrentDesigner.CreateUniqueComponentName(AObject.ClassName);
609
TComponent(AObject).DesignInfo:=0;
610
AParent.AddChild(AObject);
611
Node:=AddNodes(Selected, AObject);
613
FCurrentDesigner.PropertyEditorHook.PersistentAdded(AObject,True);
614
FCurrentDesigner.Modified;
615
FCurrentDesigner.SelectOnlyThisComponent(AObject);
619
procedure TGLSceneEditorForm.AddBehaviourClick(Sender: TObject);
622
XCollectionItemClass : TGLXCollectionItemClass;
623
AParent: TGLBaseSceneObject;
624
XCollectionItem : TGLXCollectionItem;
626
if Assigned(Tree.Selected) then
628
AParent:=TGLBaseSceneObject(Tree.Selected.Data);
629
I := (Sender as TMenuItem).Tag;
631
FXObjectList := GetXCollectionItemClassesList(AParent.Behaviours.ItemsClass);
633
XCollectionItemClass:=TGLXCollectionItemClass(FXObjectList[I]);
634
XCollectionItem:=XCollectionItemClass.Create(AParent.Behaviours);
635
ShowBehaviours(AParent);
636
BehavioursListView.Selected:=BehavioursListView.Items.FindData(XCollectionItem);
637
GlobalDesignHook.Modified(Sender);
643
procedure TGLSceneEditorForm.AddEffectClick(Sender: TObject);
646
XCollectionItemClass : TGLXCollectionItemClass;
647
AParent: TGLBaseSceneObject;
648
XCollectionItem : TGLXCollectionItem;
650
if Assigned(Tree.Selected) then
652
AParent:=TGLBaseSceneObject(Tree.Selected.Data);
653
I := (Sender as TMenuItem).Tag;
655
FXObjectList := GetXCollectionItemClassesList(AParent.Effects.ItemsClass);
657
XCollectionItemClass:=TGLXCollectionItemClass(FXObjectList[I]);
658
XCollectionItem:=XCollectionItemClass.Create(AParent.Effects);
659
ShowEffects(AParent);
660
EffectsListView.Selected:=EffectsListView.Items.FindData(XCollectionItem);
661
GlobalDesignHook.Modified(Sender);
666
procedure TGLSceneEditorForm.TreeDragOver(Sender, Source: TObject; X, Y: Integer;
667
State: TDragState; var Accept: Boolean);
672
if Source=Tree then with Tree do begin
673
Target:=Tree.GetNodeAt(X, Y); //Tree.DropTarget; buged result=nil
674
Accept:=Assigned(Target) and (Selected <> Target)
675
and Assigned(Target.Data) and
676
(not Target.HasAsParent(Selected));
681
procedure TGLSceneEditorForm.TreeDragDrop(Sender, Source: TObject; X, Y: Integer);
683
SourceNode, DestinationNode: TTreeNode;
684
SourceObject, DestinationObject: TGLBaseSceneObject;
686
if Assigned(FCurrentDesigner) then
688
DestinationNode:=Tree.GetNodeAt(X, Y); //Tree.DropTarget; buged result=nil
689
if Assigned(DestinationNode) and (Source = Tree) then
691
SourceNode:=TTreeView(Source).Selected;
692
SourceObject:=SourceNode.Data;
693
DestinationObject:=DestinationNode.Data;
694
DestinationObject.Insert(0, SourceObject);
695
SourceNode.MoveTo(DestinationNode, naAddChildFirst);
696
TreeChange(Self, nil);
697
FCurrentDesigner.Modified;
704
procedure TGLSceneEditorForm.Notification(AComponent: TComponent; Operation: TOperation);
706
if (FScene=AComponent) and (Operation=opRemove) then begin
713
// OnBaseSceneObjectNameChanged
715
procedure TGLSceneEditorForm.OnBaseSceneObjectNameChanged(Sender : TObject);
719
n:=FindNodeByData(Tree.Items, Sender);
721
n.Text:=(Sender as TGLBaseSceneObject).Name;
726
procedure TGLSceneEditorForm.TreeChange(Sender: TObject; Node: TTreeNode);
728
// selNode : TTreeNode;
729
BaseSceneObject1:TGLBaseSceneObject;
731
if Assigned(FCurrentDesigner) then begin
735
BaseSceneObject1:=TGLBaseSceneObject(Node.Data);
736
if BaseSceneObject1<>nil then
738
ShowBehavioursAndEffects(BaseSceneObject1);
742
EnableAndDisableActions();
748
procedure TGLSceneEditorForm.TreeEditing(Sender: TObject; Node: TTreeNode;
749
var AllowEdit: Boolean);
751
AllowEdit:=(Node.Level>1);
754
procedure TGLSceneEditorForm.ShowBehaviours(BaseSceneObject:TGLBaseSceneObject);
758
BehavioursListView.Items.Clear;
759
BehavioursListView.Items.BeginUpdate;
760
if Assigned(BaseSceneObject) then
762
for i:=0 to BaseSceneObject.Behaviours.Count-1 do
764
with BehavioursListView.Items.Add do
766
Caption:=IntToStr(i)+' - '+BaseSceneObject.Behaviours[i].Name;
767
Data:=BaseSceneObject.Behaviours[i];
771
BehavioursListView.Items.EndUpdate;
774
procedure TGLSceneEditorForm.ShowEffects(BaseSceneObject:TGLBaseSceneObject);
778
EffectsListView.Items.Clear;
779
EffectsListView.Items.BeginUpdate;
780
if Assigned(BaseSceneObject) then
782
for i:=0 to BaseSceneObject.Effects.Count-1 do
784
with EffectsListView.Items.Add do
786
caption:=IntToStr(i)+' - '+BaseSceneObject.Effects[i].Name;
787
Data:=BaseSceneObject.Effects[i];
791
EffectsListView.Items.EndUpdate;
795
procedure TGLSceneEditorForm.ShowBehavioursAndEffects(BaseSceneObject:TGLBaseSceneObject);
797
ShowBehaviours(BaseSceneObject);
798
ShowEffects(BaseSceneObject);
804
procedure TGLSceneEditorForm.TreeEdited(Sender: TObject; Node: TTreeNode; var S: String);
807
BaseSceneObject1:TGLBaseSceneObject;
809
if Assigned(FCurrentDesigner) then begin
810
// renaming a node means renaming a scene object
811
BaseSceneObject1:=TGLBaseSceneObject(Node.Data);
812
if FScene.FindSceneObject(S)=nil then
813
BaseSceneObject1.Name:=S
816
// Messagedlg('A component named '+S+' already exists',mtWarning,[mbok],0);
817
S:=BaseSceneObject1.Name;
819
ShowBehavioursAndEffects(BaseSceneObject1);
821
FCurrentDesigner.Modified;
827
procedure TGLSceneEditorForm.TreeMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
829
FLastMouseDownPos:=Point(X, Y);
836
procedure TGLSceneEditorForm.TreeMouseMove(Sender: TObject;
837
Shift: TShiftState; X, Y: Integer);
841
if Shift=[ssLeft] then begin
843
if Assigned(node) and (node.Level>1) then
844
if (Abs(FLastMouseDownPos.x-x)>4) or (Abs(FLastMouseDownPos.y-y)>4) then
845
Tree.BeginDrag(False);
851
procedure TGLSceneEditorForm.TreeEnter(Sender: TObject);
853
if Assigned(FCurrentDesigner) and Assigned(Tree.Selected) then
854
FCurrentDesigner.SelectOnlyThisComponent(TGLBaseSceneObject(Tree.Selected.Data));
855
FSelectedItems:=SCENE_SELECTED;
856
EnableAndDisableActions();
861
procedure TGLSceneEditorForm.ACAddCameraExecute(Sender: TObject);
863
AObject: TGLBaseSceneObject;
866
if Assigned(FCurrentDesigner) then begin
867
AObject:=TGLBaseSceneObject(TGLCamera.Create(FCurrentDesigner.Form));
868
AObject.Name:=FCurrentDesigner.CreateUniqueComponentName(AObject.ClassName);
869
FScene.Objects.AddChild(AObject);
870
Node:=AddNodes(FObjectNode, AObject);
872
FCurrentDesigner.PropertyEditorHook.PersistentAdded(AObject,True);
873
FCurrentDesigner.Modified;
874
FCurrentDesigner.SelectOnlyThisComponent(AObject);
878
// ACDeleteObjectExecute
880
procedure TGLSceneEditorForm.ACDeleteObjectExecute(Sender: TObject);
882
anObject : TGLBaseSceneObject;
883
allowed, keepChildren : Boolean;
885
buttons : TMsgDlgButtons;
887
if FSelectedItems=BEHAVIOURS_SELECTED then begin
888
DeleteBaseBehaviour(BehavioursListView);
890
FCurrentDesigner.SelectOnlyThisComponent(TGLBaseSceneObject(Tree.Selected.data));
892
ShowBehaviours(TGLBaseSceneObject(Tree.Selected.data));
893
end else if FSelectedItems=EFFECTS_SELECTED then begin
894
DeleteBaseBehaviour(EffectsListView);
896
FCurrentDesigner.SelectOnlyThisComponent(TGLBaseSceneObject(Tree.Selected.data));
898
ShowEffects(TGLBaseSceneObject(Tree.Selected.data));
899
end else if FSelectedItems=SCENE_SELECTED then begin
900
if Assigned(Tree.Selected) and (Tree.Selected.Level > 1) then begin
901
anObject:=TGLBaseSceneObject(Tree.Selected.Data);
902
// ask for confirmation
903
if anObject.Name<>'' then
904
ConfirmMsg:='Delete '+anObject.Name
905
else ConfirmMsg:='Delete the marked object';
906
buttons:=[mbOK, mbCancel];
907
// are there children to care for?
908
// mbAll exist only on Windows ...
910
if (anObject.Count > 0) and (not anObject.HasSubChildren) then
912
confirmMsg:=ConfirmMsg+' only or with ALL its children?';
913
buttons:=[mbAll]+Buttons;
914
end else confirmMsg:=confirmMsg+'?';
916
case MessageDlg(confirmMsg, mtConfirmation, buttons, 0) of
936
if allowed then begin
937
if keepChildren=true then
938
while Tree.Selected.Count>0 do
939
Tree.Selected.Items[0].MoveTo(Tree.Selected,naAdd);
940
//previous line should be "naInsert" if children are to remain in position of parent
941
// (would require changes to TGLBaseSceneObject.Remove)
943
GlobalDesignHook.Unselect(anObject);
944
anObject.Parent.Remove(anObject, keepChildren);
945
FCurrentDesigner.Modified;
946
GlobalDesignHook.DeletePersistent(TPersistent(anObject));
952
function FindListViewData(list : TListView; data : Pointer) : TListItem;
957
for i:=0 to list.Items.Count-1 do
958
if list.Items[i].Data = data then begin
959
Result:=list.Items[i];
966
procedure TGLSceneEditorForm.ACMoveUpExecute(Sender: TObject);
971
if FSelectedItems=BEHAVIOURS_SELECTED then
973
PrevData:=BehavioursListView.Selected.Data;
974
TGLBaseBehaviour(PrevData).MoveUp;
975
ShowBehaviours(TGLBaseSceneObject(Tree.Selected.Data));
976
BehavioursListView.Selected:=FindListViewData(BehavioursListView, PrevData);
977
FCurrentDesigner.Modified;
979
else if FSelectedItems=EFFECTS_SELECTED then
981
PrevData:=EffectsListView.Selected.Data;
982
TGLBaseBehaviour(PrevData).MoveUp;
983
ShowEffects(TGLBaseSceneObject(Tree.Selected.Data));
984
EffectsListView.Selected:=FindListViewData(EffectsListView, PrevData);
985
FCurrentDesigner.Modified;
987
else if FSelectedItems=SCENE_SELECTED then
989
if ACMoveUp.Enabled then begin
991
if Assigned(node) then begin
992
node.MoveTo(node.GetPrevSibling, naInsert);
993
with TGLBaseSceneObject(node.Data) do begin
997
TreeChange(Self, node);
998
FCurrentDesigner.Modified;
1006
procedure TGLSceneEditorForm.ACMoveDownExecute(Sender: TObject);
1011
if FSelectedItems=BEHAVIOURS_SELECTED then
1013
PrevData:=BehavioursListView.Selected.Data;
1014
TGLBaseBehaviour(PrevData).MoveDown;
1015
ShowBehaviours(TGLBaseSceneObject(Tree.Selected.Data));
1016
BehavioursListView.Selected:=FindListViewData(BehavioursListView, PrevData);
1017
FCurrentDesigner.Modified;
1019
else if FSelectedItems=EFFECTS_SELECTED then
1021
PrevData:=EffectsListView.Selected.Data;
1022
TGLBaseBehaviour(PrevData).MoveDown;
1023
ShowEffects(TGLBaseSceneObject(Tree.Selected.Data));
1024
EffectsListView.Selected:=FindListViewData(EffectsListView, PrevData);
1025
FCurrentDesigner.Modified;
1027
else if FSelectedItems=SCENE_SELECTED then
1029
if ACMoveDown.Enabled then begin
1030
node:=Tree.Selected;
1031
if Assigned(node) then begin
1032
node.GetNextSibling.MoveTo(node, naInsert);
1033
with TGLBaseSceneObject(node.Data) do begin
1037
TreeChange(Self, node);
1038
FCurrentDesigner.Modified;
1044
// ACAddObjectExecute
1046
procedure TGLSceneEditorForm.ACAddObjectExecute(Sender: TObject);
1048
TBAddObjects.CheckMenuDropdown;
1051
procedure TGLSceneEditorForm.ACStayOnTopExecute(Sender: TObject);
1053
if TBStayOnTop.Down then
1054
FormStyle := fsStayOnTop
1056
FormStyle := fsNormal;
1059
// ACSaveSceneExecute
1061
procedure TGLSceneEditorForm.ACSaveSceneExecute(Sender: TObject);
1063
if SaveDialog.Execute then
1064
FScene.SaveToFile(SaveDialog.FileName);
1067
// ACLoadSceneExecute
1069
procedure TGLSceneEditorForm.ACLoadSceneExecute(Sender: TObject);
1071
if OpenDialog.Execute then begin
1072
FScene.LoadFromFile(OpenDialog.FileName);
1075
ShowBehavioursAndEffects(nil);
1081
procedure TGLSceneEditorForm.ACInfoExecute(Sender: TObject);
1083
AScene: TGLSceneViewer;
1085
AScene:=TGLSceneViewer.Create(Self);
1086
AScene.Name:='GLSceneEditor';
1089
AScene.Parent:=Self;
1091
AScene.Buffer.ShowInfo;
1097
// IsValidClipBoardNode
1099
function TGLSceneEditorForm.IsValidClipBoardNode : Boolean;
1101
selNode : TTreeNode;
1103
selNode:=Tree.Selected;
1104
Result:=((selNode<>nil) and (selNode.Parent<>nil)
1105
and (selNode.Parent.Parent<>nil));
1110
function TGLSceneEditorForm.IsPastePossible : Boolean;
1111
{$IFDEF GLS_DELPHI_6_UP}
1113
function PossibleStream(const S: string): Boolean;
1118
for I := 1 to Length(S) - 6 do begin
1119
if (S[I] in ['O','o']) and (CompareText(Copy(S, I, 6), 'OBJECT') = 0) then Exit;
1120
if not (S[I] in [' ',#9, #13, #10]) then Break;
1126
selNode : TTreeNode;
1127
anObject, destination : TGLBaseSceneObject;
1128
ComponentList: IDesignerSelections;
1129
TmpContainer : TComponent;
1131
selNode:=Tree.Selected;
1133
if (selNode<>nil) and (selNode.Parent<>nil)
1135
and (ClipBoard.HasFormat(CF_COMPONENT) or (Clipboard.HasFormat(CF_TEXT) and
1136
PossibleStream(Clipboard.AsText))) {$ENDIF} then
1138
TmpContainer := TComponent.Create(self);
1140
ComponentList := TDesignerSelections.Create;
1141
PasteComponents(TmpContainer, TmpContainer, ComponentList);
1142
if (ComponentList.Count>0) and (ComponentList[0] is TGLBaseSceneObject) then begin
1143
anObject:=TGLBaseSceneObject(ComponentList[0]);
1144
destination:=TGLBaseSceneObject(selNode.Data);
1145
Result:=CanPaste(anObject, destination);
1146
end else Result:=False;
1150
end else Result:=False;
1159
{$IFDEF GLS_DELPHI_6_UP}
1160
function TGLSceneEditorForm.CanPaste(obj, destination : TGLBaseSceneObject) : Boolean;
1162
Result:= Assigned(obj) and Assigned(destination);
1168
procedure TGLSceneEditorForm.ACCopyExecute(Sender: TObject);
1169
{$IFDEF GLS_DELPHI_6_UP}
1171
ComponentList: IDesignerSelections;
1173
ComponentList := TDesignerSelections.Create;
1174
ComponentList.Add(TGLBaseSceneObject(Tree.Selected.Data));
1175
CopyComponents(FScene.Owner, ComponentList);
1176
ACPaste.Enabled:=IsPastePossible;
1184
procedure TGLSceneEditorForm.ACCutExecute(Sender: TObject);
1185
{$IFDEF GLS_DELPHI_6_UP}
1187
AObject: TGLBaseSceneObject;
1188
ComponentList: IDesignerSelections;
1190
if IsValidClipBoardNode then
1192
AObject := TGLBaseSceneObject(Tree.Selected.Data);
1193
ComponentList := TDesignerSelections.Create;
1194
ComponentList.Add(TGLBaseSceneObject(Tree.Selected.Data));
1196
CopyComponents(FScene.Owner, ComponentList);
1197
AObject.Parent.Remove(AObject, False);
1200
ACPaste.Enabled:=IsPastePossible;
1210
procedure TGLSceneEditorForm.ACPasteExecute(Sender: TObject);
1211
{$IFDEF GLS_DELPHI_6_UP}
1213
selNode : TTreeNode;
1214
destination : TGLBaseSceneObject;
1215
ComponentList: IDesignerSelections;
1218
selNode:=Tree.Selected;
1219
if (selNode<>nil) and (selNode.Parent<>nil) then begin
1220
destination:=TGLBaseSceneObject(selNode.Data);
1221
ComponentList := TDesignerSelections.Create;
1222
PasteComponents(FScene.Owner, destination, ComponentList);
1223
if (ComponentList.count>0) and (CanPaste(TGLBaseSCeneObject(ComponentList[0]), destination)) then begin
1224
for t :=0 to ComponentList.Count-1 do
1225
AddNodes(selNode, TGLBaseSCeneObject(ComponentList[t]) );
1226
selNode.Expand(False);
1228
FCurrentDesigner.Modified;
1235
{$IFDEF GLS_DELPHI_6_UP}
1238
procedure TGLSceneEditorForm.CopyComponents(Root: TComponent; const Components: IDesignerSelections);
1244
S := TMemoryStream.Create;
1246
W := TWriter.Create(S, 1024);
1249
for I := 0 to Components.Count - 1 do
1252
W.WriteComponent(TComponent(Components[I]));
1258
CopyStreamToClipboard(S);
1264
procedure TGLSceneEditorForm.MethodError(Reader: TReader;
1265
const MethodName: String; var Address: Pointer; var Error: Boolean);
1267
// error is true because Address is nil in csDesigning
1271
procedure TGLSceneEditorForm.PasteComponents(AOwner, AParent: TComponent;const Components: IDesignerSelections);
1276
S := GetClipboardStream;
1278
R := TReader.Create(S, 1024);
1280
R.OnSetName := ReaderSetName;
1281
R.OnFindMethod := MethodError;
1282
FPasteOwner := AOwner;
1283
FPasteSelection := Components;
1284
R.ReadComponents(AOwner, AParent, ComponentRead);
1293
procedure TGLSceneEditorForm.ReaderSetName(Reader: TReader; Component: TComponent; var Name: string);
1295
if (Reader.Root = FPasteOwner) and (FPasteOwner.FindComponent(Name) <> nil) then
1296
Name := UniqueName(Component);
1299
function TGLSceneEditorForm.UniqueName(Component: TComponent): string;
1301
Result := FCurrentDesigner.CreateUniqueComponentName(Component.ClassName);
1304
procedure TGLSceneEditorForm.ComponentRead(Component: TComponent);
1306
FPasteSelection.Add(Component);
1310
procedure TGLSceneEditorForm.BehavioursListViewClick(Sender: TObject);
1312
if Assigned(FCurrentDesigner) and Assigned(BehavioursListView.Selected) then
1313
GlobalDesignHook.SelectOnlyThis(TGLBaseBehaviour(BehavioursListView.Selected.Data));
1314
FSelectedItems:=BEHAVIOURS_SELECTED;
1315
EnableAndDisableActions();
1318
procedure TGLSceneEditorForm.EffectsListViewClick(Sender: TObject);
1320
if Assigned(FCurrentDesigner) and Assigned(EffectsListView.Selected) then
1321
GlobalDesignHook.SelectOnlyThis(TGLXCollectionItem(EffectsListView.Selected.Data));
1322
FSelectedItems:=EFFECTS_SELECTED;
1323
EnableAndDisableActions();
1326
procedure TGLSceneEditorForm.ACAddBehaviourExecute(Sender: TObject);
1328
TBAddBehaviours.CheckMenuDropdown
1331
procedure TGLSceneEditorForm.DeleteBaseBehaviour(ListView:TListView);
1333
if ListView.Selected<>nil then
1336
GlobalDesignHook.SelectOnlyThis(nil);
1338
TGLXCollectionItem(ListView.Selected.Data).Free;
1339
ListView.Selected.Free;
1340
// ListViewChange(Self, nil, ctState);
1341
FCurrentDesigner.Modified;
1342
ShowBehavioursAndEffects(TGLBaseSceneObject(Tree.Selected.Data));
1346
procedure TGLSceneEditorForm.PMBehavioursToolbarPopup(Sender: TObject);
1348
object1:TGLBaseSceneObject;
1350
if (Tree.Selected)<>nil then
1352
object1:=TGLBaseSceneObject(Tree.Selected.Data);
1353
SetBehavioursSubItems(PMBehavioursToolbar.Items, object1.Behaviours);
1357
procedure TGLSceneEditorForm.PMEffectsToolbarPopup(Sender: TObject);
1359
object1:TGLBaseSceneObject;
1361
if (Tree.Selected)<>nil then
1363
object1:=TGLBaseSceneObject(Tree.Selected.Data);
1364
SetEffectsSubItems(PMEffectsToolbar.Items, object1.Effects);
1369
procedure TGLSceneEditorForm.BehavioursListViewSelectItem(Sender: TObject;
1370
Item: TListItem; Selected: Boolean);
1372
EnableAndDisableActions();
1377
procedure TGLSceneEditorForm.ACAddEffectExecute(Sender: TObject);
1379
TBAddEffects.CheckMenuDropdown;
1382
procedure TGLSceneEditorForm.EnableAndDisableActions();
1386
if FSelectedItems=SCENE_SELECTED then
1388
selNode:=Tree.Selected;
1389
// select in Delphi IDE
1390
if Assigned(selNode) then
1392
if Assigned(selNode.Data) then
1393
FCurrentDesigner.SelectOnlyThisComponent(TGLBaseSceneObject(selNode.Data))
1394
else FCurrentDesigner.SelectOnlyThisComponent(FScene);
1396
ACAddCamera.Enabled:=((selNode=FObjectNode) or selNode.HasAsParent(FObjectNode));
1397
ACAddObject.Enabled:=((selNode=FObjectNode) or selNode.HasAsParent(FObjectNode));
1398
ACAddBehaviour.Enabled:=(selNode.HasAsParent(FObjectNode));
1399
ACAddEffect.Enabled:=(selNode.HasAsParent(FObjectNode));
1400
ACDeleteObject.Enabled:=(selNode.Level>1);
1401
ACMoveUp.Enabled:=((selNode.Index>0)and(selNode.Level>1));
1402
ACMoveDown.Enabled:=((selNode.GetNextSibling<>nil)and(selNode.Level>1));
1403
ACCut.Enabled:=IsValidClipBoardNode;
1404
ACPaste.Enabled:=IsPastePossible;
1409
ACAddCamera.Enabled:=False;
1410
ACAddObject.Enabled:=False;
1411
ACAddBehaviour.Enabled:=False;
1412
ACAddEffect.Enabled:=False;
1413
ACDeleteObject.Enabled:=False;
1414
ACMoveUp.Enabled:=False;
1415
ACMoveDown.Enabled:=False;
1416
ACCut.Enabled:=False;
1417
ACPaste.Enabled:=False;
1420
ACCopy.Enabled:=ACCut.Enabled;
1423
else if FSelectedItems=BEHAVIOURS_SELECTED then
1425
if (BehavioursListView.Selected<>nil) then
1427
GlobalDesignHook.SelectOnlyThis(TGLBaseBehaviour(BehavioursListView.Selected.Data));
1428
//Writeln('BehavioursListView.Selected.data=',hexStr(BehavioursListView.Selected.data));
1429
ACDeleteObject.Enabled:=True;
1430
ACMoveUp.Enabled:=(BehavioursListView.Selected.Index>0);
1431
ACMoveDown.Enabled:=(BehavioursListView.Selected.Index<BehavioursListView.Selected.Owner.Count-1);
1432
ACCut.Enabled:=False;
1433
ACCopy.Enabled:=false;
1434
ACPaste.Enabled:=False;
1438
ACDeleteObject.Enabled:=false;
1439
ACMoveUp.Enabled:=false;
1440
ACMoveDown.Enabled:=false;
1441
ACCut.Enabled:=false;
1442
ACCopy.Enabled:=false;
1443
ACPaste.Enabled:=false;
1446
else if FSelectedItems=EFFECTS_SELECTED then
1448
if (EffectsListView.Selected<>nil)then
1450
GlobalDesignHook.SelectOnlyThis(TGLXCollectionItem(EffectsListView.Selected.Data));
1451
ACDeleteObject.Enabled:=True;
1452
ACMoveUp.Enabled:=(EffectsListView.Selected.Index>0);
1453
ACMoveDown.Enabled:=(EffectsListView.Selected.Index<EffectsListView.Selected.Owner.Count-1);
1454
ACCut.Enabled:=False;
1455
ACCopy.Enabled:=false;
1456
ACPaste.Enabled:=False;
1460
ACDeleteObject.Enabled:=false;
1461
ACMoveUp.Enabled:=false;
1462
ACMoveDown.Enabled:=false;
1463
ACCut.Enabled:=false;
1464
ACCopy.Enabled:=false;
1465
ACPaste.Enabled:=false;
1471
procedure TGLSceneEditorForm.PopupMenuPopup(Sender: TObject);
1474
sceneObj : TGLBaseSceneObject;
1476
if (Tree.Selected)<>nil then begin
1477
obj:=TObject(Tree.Selected.Data);
1478
if Assigned(obj) and (obj is TGLBaseSceneObject) then begin
1479
sceneObj:=TGLBaseSceneObject(obj);
1480
SetBehavioursSubItems(MIAddBehaviour, sceneObj.Behaviours);
1481
SetEffectsSubItems(MIAddEffect, sceneObj.Effects);
1483
SetBehavioursSubItems(MIAddBehaviour, nil);
1484
SetEffectsSubItems(MIAddEffect, nil);
1489
procedure TGLSceneEditorForm.TBEffectsPanelClick(Sender: TObject);
1491
PABehaviours.Visible:=TBEffectsPanel.Down;
1492
Splitter.Visible:=TBEffectsPanel.Down;
1493
if PABehaviours.Visible then
1494
Width:=Width+PABehaviours.Width
1495
else Width:=Width-PABehaviours.Width;
1498
procedure TGLSceneEditorForm.TreeKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
1500
if (Key = glKey_DELETE) and not Tree.IsEditing then begin
1502
ACDeleteObject.Execute;
1509
{$I FGLSceneEdit.lrs}
1512
ReleaseGLSceneEditorForm;