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
02/01/15 - PW - Fixed for Lazarus 1.2.6
9
20/05/10 - Yar - Fixes for Linux x64
10
18/05/10 - Yar - Fixed for Lazarus-0.9.29-25483 (thanks Predator)
11
26/03/10 - Yar - Added Expand and Collapse buttons, fix for Unix-based systems
12
(thanks to Rustam Asmandiarov aka Predator)
13
14/03/09 - DanB - Removed Cameras node, instead cameras are now placed into scene
14
19/03/08 - mrqzzz - Little change to "stay on top" (references self, not GLSceneEditorForm )
15
17/03/08 - mrqzzz - By dAlex: Added "stay on top" button
16
12/07/07 - DaStr - Improved cross-platform compatibility
17
(BugTrackerID=1684432)
18
29/03/07 - DaStr - Renamed LINUX to KYLIX (BugTrackerID=1681585)
19
25/03/07 - DaStr - Abstracted IsSubComponent for Delphi5 compatibility
20
17/03/07 - DaStr - Dropped Kylix support in favor of FPC (BugTrackerID=1681585)
21
07/02/07 - DaStr - TGLSceneEditorForm.ACDeleteObjectExecute bugfixed
22
TGLSceneEditorForm.AddNodes - removed warning
23
(all for proper Subcomponent support)
24
20/01/07 - DaStr - TGLSceneEditorForm.ACCutExecute bugfixed
25
19/12/06 - DaStr - TGLSceneEditorForm.AddNodes bugfixed - SubComponents are
26
no longer displayed in the Editor (BugTraker ID = 1585913)
27
24/06/06 - PvD - Fixed bug with DELETE key when editing name in Treeview
28
03/07/04 - LR - Updated for Linux
29
18/12/04 - PhP - Added support for deleting objects/effects/behaviours by pressing "Delete"
30
03/07/04 - LR - Make change for Linux
31
14/12/03 - EG - Paste fix (Mrqzzz)
32
31/06/03 - EG - Cosmetic changes, form position/state now saved to the registry
33
21/06/03 - DanB - Added behaviours/effects listviews
34
22/01/02 - EG - Fixed controls state after drag/drop (Anton Zhuchkov)
35
06/08/00 - EG - Added basic Clipboard support
36
14/05/00 - EG - Added workaround for VCL DesignInfo bug (thx Nelson Chu)
37
28/04/00 - EG - Fixed new objects not being immediately reco by IDE
38
26/04/00 - EG - Added support for objects categories
39
17/04/00 - EG - Added access to TInfoForm
40
16/04/00 - EG - Fixed occasionnal crash when rebuilding GLScene dpk
41
while GLSceneEdit is visible
42
10/04/00 - EG - Minor Create/Release change
43
24/03/00 - EG - Fixed SetScene not updating enablings
44
13/03/00 - EG - Object names (ie. node text) is now properly adjusted
45
when a GLScene object is renamed,
46
Added Load/Save whole scene
47
07/02/00 - EG - Fixed notification logic
48
06/02/00 - EG - DragDrop now starts after moving the mouse a little,
49
Form is now auto-creating, fixed Notification,
50
Added actionlist and moveUp/moveDown
51
05/02/00 - EG - Fixed DragDrop, added root nodes auto-expansion
66
GLXCollection, GLScene, Classes, SysUtils,
67
Controls, Forms, ComCtrls,
68
Dialogs, Menus, ActnList, ExtCtrls, StdCtrls,
69
propedits, componenteditors,
82
BEHAVIOURS_SELECTED=1;
85
TSetSubItemsEvent = procedure(Sender:TObject) of object;
87
{ TGLSceneEditorForm }
89
TGLSceneEditorForm = class(TForm)
92
ToolButton10: TToolButton;
93
ToolButton11: TToolButton;
94
ToolButton12: TToolButton;
95
ToolButton13: TToolButton;
96
ToolButton14: TToolButton;
97
ToolButton15: TToolButton;
98
ToolButton2: TToolButton;
99
ToolButton3: TToolButton;
100
ToolButton4: TToolButton;
101
ToolButton5: TToolButton;
102
ToolButton6: TToolButton;
103
ToolButton7: TToolButton;
105
PopupMenu: TPopupMenu;
106
MIAddCamera: TMenuItem;
107
MIAddObject: TMenuItem;
109
MIDelObject: TMenuItem;
111
ActionList: TActionList;
112
ToolButton1: TToolButton;
113
TBAddObjects: TToolButton;
114
PMToolBar: TPopupMenu;
115
ACAddCamera: TAction;
116
ACAddObject: TAction;
117
ImageList: TImageList;
118
ACDeleteObject: TAction;
122
Moveobjectup1: TMenuItem;
123
Moveobjectdown1: TMenuItem;
124
ACSaveScene: TAction;
125
ACLoadScene: TAction;
126
OpenDialog: TOpenDialog;
127
SaveDialog: TSaveDialog;
128
ToolButton8: TToolButton;
129
ToolButton9: TToolButton;
137
PABehaviours: TPanel;
138
BehavioursListView: TListView;
139
Splitter3: TSplitter;
140
EffectsListView: TListView;
142
PMBehavioursToolbar: TPopupMenu;
143
ACAddBehaviour: TAction;
144
MIAddBehaviour: TMenuItem;
145
MIAddEffect: TMenuItem;
146
MIBehaviourSeparator: TMenuItem;
147
ACDeleteBehaviour: TAction;
148
BehavioursPopupMenu: TPopupMenu;
151
MoveDown1: TMenuItem;
155
PMEffectsToolbar: TPopupMenu;
156
ACAddEffect: TAction;
158
TBAddBehaviours: TToolButton;
159
TBAddEffects: TToolButton;
160
TBEffectsPanel: TToolButton;
161
TBStayOnTop: TToolButton;
162
ACStayOnTop: TAction;
163
procedure BehavioursListViewClick(Sender: TObject);
164
procedure EffectsListViewClick(Sender: TObject);
165
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
166
procedure FormCreate(Sender: TObject);
167
procedure ToolButton10Click(Sender: TObject);
168
procedure ToolButton15Click(Sender: TObject);
169
procedure TreeEditing(Sender: TObject; Node: TTreeNode; var AllowEdit: Boolean);
170
procedure TreeDragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
171
procedure TreeDragDrop(Sender, Source: TObject; X, Y: Integer);
172
procedure TreeChange(Sender: TObject; Node: TTreeNode);
173
procedure TreeMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
174
procedure TreeEnter(Sender: TObject);
175
procedure TreeMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
176
procedure ACAddCameraExecute(Sender: TObject);
177
procedure ACDeleteObjectExecute(Sender: TObject);
178
procedure ACMoveUpExecute(Sender: TObject);
179
procedure ACMoveDownExecute(Sender: TObject);
180
procedure ACAddObjectExecute(Sender: TObject);
181
procedure ACSaveSceneExecute(Sender: TObject);
182
procedure ACLoadSceneExecute(Sender: TObject);
183
procedure FormDestroy(Sender: TObject);
184
procedure ACInfoExecute(Sender: TObject);
185
procedure ACCopyExecute(Sender: TObject);
186
procedure ACCutExecute(Sender: TObject);
187
procedure ACPasteExecute(Sender: TObject);
189
procedure ACAddBehaviourExecute(Sender: TObject);
190
procedure DeleteBaseBehaviour(ListView:TListView);
191
procedure PMBehavioursToolbarPopup(Sender: TObject);
192
procedure PMEffectsToolbarPopup(Sender: TObject);
193
procedure BehavioursListViewSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
194
procedure ACAddEffectExecute(Sender: TObject);
195
procedure PopupMenuPopup(Sender: TObject);
196
procedure TBEffectsPanelClick(Sender: TObject);
197
procedure TreeKeyDown(Sender: TObject; var Key: Word;
199
procedure ACStayOnTopExecute(Sender: TObject);
202
FSelectedItems:Integer; //
205
FObjectNode: TTreeNode;
206
FCurrentDesigner: TComponentEditorDesigner;
207
FLastMouseDownPos: TPoint;
208
FObjectList: TStringList;
212
// adds the given scene object as well as its children to the tree structure and returns
213
// the last add node (e.g. for selection)
214
function AddNodes(ANode: TTreeNode; AObject: TGLBaseSceneObject): TTreeNode;
215
procedure AddObjectClick(Sender: TObject);
216
procedure AddBehaviourClick(Sender: TObject);
217
procedure AddEffectClick(Sender: TObject);
218
procedure SetObjectsSubItems(parent : TMenuItem);
219
procedure SetXCollectionSubItems(parent : TMenuItem ; XCollection: TGLXCollection; Event:TSetSubItemsEvent);
220
procedure SetBehavioursSubItems(parent : TMenuItem; XCollection: TGLXCollection);
221
procedure SetEffectsSubItems(parent : TMenuItem; XCollection: TGLXCollection);
222
procedure OnBaseSceneObjectNameChanged(Sender : TObject);
223
function IsValidClipBoardNode : Boolean;
224
function IsPastePossible : Boolean;
225
procedure ShowBehaviours(BaseSceneObject:TGLBaseSceneObject);
226
procedure ShowEffects(BaseSceneObject:TGLBaseSceneObject);
227
procedure ShowBehavioursAndEffects(BaseSceneObject:TGLBaseSceneObject);
228
procedure EnableAndDisableActions();
229
procedure TreeEdited(Sender: TObject; Node: TTreeNode; var S: String);
232
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
235
procedure SetScene(AScene : TGLScene; ADesigner : TComponentEditorDesigner);
239
function GLSceneEditorForm : TGLSceneEditorForm;
240
procedure ReleaseGLSceneEditorForm;
242
// ------------------------------------------------------------------
243
// ------------------------------------------------------------------
244
// ------------------------------------------------------------------
246
// ------------------------------------------------------------------
247
// ------------------------------------------------------------------
248
// ------------------------------------------------------------------
251
cGLSceneEditor = 'GLScene Editor';
254
vGLSceneEditorForm : TGLSceneEditorForm;
256
function GLSceneEditorForm : TGLSceneEditorForm;
258
if not Assigned(vGLSceneEditorForm) then
259
vGLSceneEditorForm:=TGLSceneEditorForm.Create(nil);
260
Result:=vGLSceneEditorForm;
263
procedure ReleaseGLSceneEditorForm;
265
if Assigned(vGLSceneEditorForm) then begin
266
vGLSceneEditorForm.Free;
267
vGLSceneEditorForm:=nil;
273
cRegistryKey = 'Software\GLScene\GLSceneEditor';
275
function ReadRegistryInteger(reg : TRegistry; const name : String;
276
defaultValue : Integer) : Integer;
278
if reg.ValueExists(name) then
279
Result:=reg.ReadInteger(name)
280
else Result:=defaultValue;
286
function FindNodeByData(treeNodes : TTreeNodes; data : Pointer;
287
baseNode : TTreeNode = nil) : TTreeNode;
292
if Assigned(baseNode) then begin
293
n:=baseNode.getFirstChild;
294
while Assigned(n) do begin
295
if n.Data=data then begin
297
end else if n.HasChildren then begin
298
Result:=FindNodeByData(treeNodes, data, n);
299
if Assigned(Result) then Break;
301
n:=baseNode.GetNextChild(n);
304
n:=treeNodes.GetFirstNode;
305
while Assigned(n) do begin
306
if n.Data=data then begin
308
end else if n.HasChildren then begin
309
Result:=FindNodeByData(treeNodes, data, n);
310
if Assigned(Result) then Break;
317
//----------------- TGLSceneEditorForm ---------------------------------------------------------------------------------
321
procedure TGLSceneEditorForm.SetScene(AScene : TGLScene; ADesigner : TComponentEditorDesigner);
323
if Assigned(FScene) then begin
324
FScene.RemoveFreeNotification(Self);
327
FCurrentDesigner:=ADesigner;
329
BehavioursListView.Items.Clear;
330
EffectsListView.Items.Clear;
332
if Assigned(FScene) then begin
333
FScene.FreeNotification(Self);
335
Caption:=cGLSceneEditor+' : '+FScene.Name;
336
end else Caption:=cGLSceneEditor;
337
TreeChange(Self, nil);
338
if Assigned(FScene) then begin
340
BehavioursListView.Enabled:=true;
341
EffectsListView.Enabled:=true;
342
ACLoadScene.Enabled:=True;
343
ACSaveScene.Enabled:=True;
344
FSelectedItems:=SCENE_SELECTED;
345
EnableAndDisableActions;
348
BehavioursListView.Enabled:=False;
349
EffectsListView.Enabled:=False;
350
ACLoadScene.Enabled:=False;
351
ACSaveScene.Enabled:=False;
352
ACAddCamera.Enabled:=False;
353
ACAddObject.Enabled:=False;
354
ACAddBehaviour.Enabled:=False;
355
ACAddEffect.Enabled:=False;
356
ACDeleteObject.Enabled:=False;
357
ACMoveUp.Enabled:=False;
358
ACMoveDown.Enabled:=False;
359
ACCut.Enabled:=False;
360
ACCopy.Enabled:=False;
361
ACPaste.Enabled:=False;
364
ShowBehavioursAndEffects(nil);
369
procedure TGLSceneEditorForm.FormCreate(Sender: TObject);
371
CurrentNode: TTreeNode;
376
FObjectList := TStringList.Create;
377
RegisterGLBaseSceneObjectNameChangeEvent(OnBaseSceneObjectNameChanged);
378
Tree.Images:=ObjectManager.ObjectIcons;
379
Tree.Indent:=ObjectManager.ObjectIcons.Width;
380
with Tree.Items do begin
381
// first add the scene root
382
CurrentNode:=Add(nil, glsSceneRoot);
383
with CurrentNode do begin
384
ImageIndex:=ObjectManager.SceneRootIndex;
385
SelectedIndex:=ImageIndex;
387
// and the root for all objects
388
FObjectNode:=AddChild(CurrentNode, glsObjectRoot);
389
with FObjectNode do begin
390
ImageIndex:=ObjectManager.ObjectRootIndex;
391
SelectedIndex:=ObjectManager.ObjectRootIndex;
395
SetObjectsSubItems(MIAddObject);
396
MIAddObject.SubMenuImages:=ObjectManager.ObjectIcons;
397
SetObjectsSubItems(PMToolBar.Items);
398
PMToolBar.Images:=ObjectManager.ObjectIcons;
400
SetBehavioursSubItems(MIAddBehaviour, nil);
401
SetBehavioursSubItems(PMBehavioursToolBar.Items, nil);
402
SetEffectsSubItems(MIAddEffect, nil);
403
SetEffectsSubItems(PMEffectsToolBar.Items, nil);
406
reg:=TRegistry.Create;
408
if reg.OpenKey(cRegistryKey, True) then begin
409
if reg.ValueExists('EffectsPanel') then
410
TBEffectsPanel.Down:=reg.ReadBool('EffectsPanel');
411
TBEffectsPanelClick(Self);
412
Left:=ReadRegistryInteger(reg, 'Left', Left);
413
Top:=ReadRegistryInteger(reg, 'Top', Top);
414
Width:=ReadRegistryInteger(reg, 'Width', 250);
415
Height:=ReadRegistryInteger(reg, 'Height', Height);
422
// Trigger the event OnEdited manualy
423
Tree.OnEdited := TreeEdited;
426
procedure TGLSceneEditorForm.ToolButton10Click(Sender: TObject);
431
procedure TGLSceneEditorForm.ToolButton15Click(Sender: TObject);
433
if FObjectNode <> nil then try
434
Tree.Items.BeginUpdate;
435
FObjectNode.Collapse(true);
436
FObjectNode.Expand(false);
438
Tree.Items.EndUpdate;
444
procedure TGLSceneEditorForm.FormClose(Sender: TObject;
445
var CloseAction: TCloseAction);
448
CloseAction :=CloseAction;
453
procedure TGLSceneEditorForm.FormDestroy(Sender: TObject);
460
DeRegisterGLBaseSceneObjectNameChangeEvent(OnBaseSceneObjectNameChanged);
464
reg:=TRegistry.Create;
466
if reg.OpenKey(cRegistryKey, True) then begin
467
reg.WriteBool('EffectsPanel', TBEffectsPanel.Down);
468
reg.WriteInteger('Left', Left);
469
reg.WriteInteger('Top', Top);
470
reg.WriteInteger('Width', Width);
471
reg.WriteInteger('Height', Height);
479
//----------------------------------------------------------------------------------------------------------------------
481
procedure TGLSceneEditorForm.ReadScene;
487
Tree.Items.BeginUpdate;
490
if Assigned(Objects) then
492
FObjectNode.Data:=Objects;
494
for I:=0 to Count - 1 do AddNodes(FObjectNode, Children[I]);
495
FObjectNode.Expand(False);
498
Tree.Items.EndUpdate;
501
//----------------------------------------------------------------------------------------------------------------------
503
procedure TGLSceneEditorForm.ResetTree;
505
// delete all subtrees (empty tree)
506
Tree.Items.BeginUpdate;
508
with FObjectNode do begin
514
Tree.Items.EndUpdate;
518
//----------------------------------------------------------------------------------------------------------------------
520
function TGLSceneEditorForm.AddNodes(ANode: TTreeNode; AObject: TGLBaseSceneObject): TTreeNode;
523
CurrentNode: TTreeNode;
525
if IsSubComponent(AObject) then
527
Result := Tree.Selected;
532
Result := Tree.Items.AddChildObject(ANode, AObject.Name, AObject);
533
Result.ImageIndex := ObjectManager.GetImageIndex(TGLSceneObjectClass(AObject.ClassType));
534
Result.SelectedIndex := Result.ImageIndex;
535
CurrentNode := Result;
536
for I := 0 to AObject.Count - 1 do
537
Result := AddNodes(CurrentNode, AObject[I]);
541
procedure TGLSceneEditorForm.SetObjectsSubItems(parent : TMenuItem);
544
item, currentParent : TMenuItem;
545
currentCategory : String;
546
soc : TGLSceneObjectClass;
548
ObjectManager.GetRegisteredSceneObjects(FObjectList);
550
for i:=0 to FObjectList.Count-1 do
552
if FObjectList[i]<>'' then
554
with ObjectManager do
555
currentCategory:=GetCategory(TGLSceneObjectClass(FObjectList.Objects[i]));
556
if currentCategory='' then
557
currentParent:=parent
559
currentParent:=NewItem(currentCategory, 0, False, True, nil, 0, '');
560
parent.Add(currentParent);
563
for j := i to FObjectList.Count-1 do
565
if FObjectList[j]<>'' then
566
with ObjectManager do
568
soc:=TGLSceneObjectClass(FObjectList.Objects[j]);
569
if currentCategory=GetCategory(soc) then
571
item := NewItem(FObjectList[j], 0, False, True, AddObjectClick, 0, '');
572
item.ImageIndex := GetImageIndex(soc);
573
item.GlyphShowMode:= gsmAlways;
575
currentParent.Add(item);
576
FObjectList[j] := '';
577
if currentCategory='' then
587
procedure TGLSceneEditorForm.SetXCollectionSubItems(parent : TMenuItem ; XCollection: TGLXCollection; Event:TSetSubItemsEvent);
590
XCollectionItemClass : TGLXCollectionItemClass;
594
if Assigned(XCollection) then
596
FXObjectList := GetXCollectionItemClassesList(XCollection.ItemsClass);
597
for I:=0 to FXObjectList.Count-1 do begin
598
XCollectionItemClass:=TGLXCollectionItemClass(FXObjectList[i]);
599
mi:=TMenuItem.Create(owner);
600
mi.Caption:=XCollectionItemClass.FriendlyName;
603
if Assigned(XCollection) then
604
mi.Enabled:=XCollection.CanAdd(XCollectionItemClass)
606
mi.Enabled:=TBAddBehaviours.Enabled;
614
// SetBehavioursSubItems
616
procedure TGLSceneEditorForm.SetBehavioursSubItems(parent : TMenuItem ; XCollection: TGLXCollection);
618
SetXCollectionSubItems(parent, GLXCollection, AddBehaviourClick);
623
procedure TGLSceneEditorForm.SetEffectsSubItems(parent : TMenuItem ; XCollection: TGLXCollection);
625
SetXCollectionSubItems(parent, GLXCollection, AddEffectClick);
629
procedure TGLSceneEditorForm.AddObjectClick(Sender: TObject);
631
AParent, AObject: TGLBaseSceneObject;
635
if Assigned(FCurrentDesigner) then with Tree do
636
if Assigned(Selected) and (Selected.Level > 0) then
638
AParent:=TGLBaseSceneObject(Selected.Data);
639
I := TMenuItem(Sender).Tag;
640
AObject:=TGLBaseSceneObject(TGLSceneObjectClass(FObjectList.Objects[I]).Create(FScene.Owner));
641
AObject.Name:=FCurrentDesigner.CreateUniqueComponentName(AObject.ClassName);
642
TComponent(AObject).DesignInfo:=0;
643
AParent.AddChild(AObject);
644
Node:=AddNodes(Selected, AObject);
646
FCurrentDesigner.PropertyEditorHook.PersistentAdded(AObject,True);
647
FCurrentDesigner.Modified;
648
FCurrentDesigner.SelectOnlyThisComponent(AObject);
652
procedure TGLSceneEditorForm.AddBehaviourClick(Sender: TObject);
655
XCollectionItemClass : TGLXCollectionItemClass;
656
AParent: TGLBaseSceneObject;
657
XCollectionItem : TGLXCollectionItem;
659
if Assigned(Tree.Selected) then
661
AParent:=TGLBaseSceneObject(Tree.Selected.Data);
662
I := (Sender as TMenuItem).Tag;
664
FXObjectList := GetXCollectionItemClassesList(AParent.Behaviours.ItemsClass);
666
XCollectionItemClass:=TGLXCollectionItemClass(FXObjectList[I]);
667
XCollectionItem:=XCollectionItemClass.Create(AParent.Behaviours);
668
ShowBehaviours(AParent);
669
BehavioursListView.Selected:=BehavioursListView.Items.FindData(XCollectionItem);
670
GlobalDesignHook.Modified(Sender);
676
procedure TGLSceneEditorForm.AddEffectClick(Sender: TObject);
679
XCollectionItemClass : TGLXCollectionItemClass;
680
AParent: TGLBaseSceneObject;
681
XCollectionItem : TGLXCollectionItem;
683
if Assigned(Tree.Selected) then
685
AParent:=TGLBaseSceneObject(Tree.Selected.Data);
686
I := (Sender as TMenuItem).Tag;
688
FXObjectList := GetXCollectionItemClassesList(AParent.Effects.ItemsClass);
690
XCollectionItemClass:=TGLXCollectionItemClass(FXObjectList[I]);
691
XCollectionItem:=XCollectionItemClass.Create(AParent.Effects);
692
ShowEffects(AParent);
693
EffectsListView.Selected:=EffectsListView.Items.FindData(XCollectionItem);
694
GlobalDesignHook.Modified(Sender);
699
procedure TGLSceneEditorForm.TreeDragOver(Sender, Source: TObject; X, Y: Integer;
700
State: TDragState; var Accept: Boolean);
705
if Source=Tree then with Tree do begin
706
Target:=Tree.GetNodeAt(X, Y); //Tree.DropTarget; buged result=nil
707
Accept:=Assigned(Target) and (Selected <> Target)
708
and Assigned(Target.Data) and
709
(not Target.HasAsParent(Selected));
714
procedure TGLSceneEditorForm.TreeDragDrop(Sender, Source: TObject; X, Y: Integer);
716
SourceNode, DestinationNode: TTreeNode;
717
SourceObject, DestinationObject: TGLBaseSceneObject;
719
if Assigned(FCurrentDesigner) then
721
DestinationNode:=Tree.GetNodeAt(X, Y); //Tree.DropTarget; buged result=nil
722
if Assigned(DestinationNode) and (Source = Tree) then
724
SourceNode:=TTreeView(Source).Selected;
725
SourceObject:=SourceNode.Data;
726
DestinationObject:=DestinationNode.Data;
727
DestinationObject.Insert(0, SourceObject);
728
SourceNode.MoveTo(DestinationNode, naAddChildFirst);
729
TreeChange(Self, nil);
730
FCurrentDesigner.Modified;
737
procedure TGLSceneEditorForm.Notification(AComponent: TComponent; Operation: TOperation);
739
if (FScene=AComponent) and (Operation=opRemove) then begin
746
// OnBaseSceneObjectNameChanged
748
procedure TGLSceneEditorForm.OnBaseSceneObjectNameChanged(Sender : TObject);
752
n:=FindNodeByData(Tree.Items, Sender);
754
n.Text:=(Sender as TGLBaseSceneObject).Name;
759
procedure TGLSceneEditorForm.TreeChange(Sender: TObject; Node: TTreeNode);
761
// selNode : TTreeNode;
762
BaseSceneObject1:TGLBaseSceneObject;
764
if Assigned(FCurrentDesigner) then begin
768
BaseSceneObject1:=TGLBaseSceneObject(Node.Data);
769
if BaseSceneObject1<>nil then
771
ShowBehavioursAndEffects(BaseSceneObject1);
775
EnableAndDisableActions();
781
procedure TGLSceneEditorForm.TreeEditing(Sender: TObject; Node: TTreeNode;
782
var AllowEdit: Boolean);
784
AllowEdit:=(Node.Level>1);
787
procedure TGLSceneEditorForm.ShowBehaviours(BaseSceneObject:TGLBaseSceneObject);
791
BehavioursListView.Items.Clear;
792
BehavioursListView.Items.BeginUpdate;
793
if Assigned(BaseSceneObject) then
795
for i:=0 to BaseSceneObject.Behaviours.Count-1 do
797
with BehavioursListView.Items.Add do
799
Caption:=IntToStr(i)+' - '+BaseSceneObject.Behaviours[i].Name;
800
Data:=BaseSceneObject.Behaviours[i];
804
BehavioursListView.Items.EndUpdate;
807
procedure TGLSceneEditorForm.ShowEffects(BaseSceneObject:TGLBaseSceneObject);
811
EffectsListView.Items.Clear;
812
EffectsListView.Items.BeginUpdate;
813
if Assigned(BaseSceneObject) then
815
for i:=0 to BaseSceneObject.Effects.Count-1 do
817
with EffectsListView.Items.Add do
819
caption:=IntToStr(i)+' - '+BaseSceneObject.Effects[i].Name;
820
Data:=BaseSceneObject.Effects[i];
824
EffectsListView.Items.EndUpdate;
828
procedure TGLSceneEditorForm.ShowBehavioursAndEffects(BaseSceneObject:TGLBaseSceneObject);
830
ShowBehaviours(BaseSceneObject);
831
ShowEffects(BaseSceneObject);
837
procedure TGLSceneEditorForm.TreeEdited(Sender: TObject; Node: TTreeNode; var S: String);
840
BaseSceneObject1:TGLBaseSceneObject;
842
if Assigned(FCurrentDesigner) then begin
843
// renaming a node means renaming a scene object
844
BaseSceneObject1:=TGLBaseSceneObject(Node.Data);
845
if FScene.FindSceneObject(S)=nil then
846
BaseSceneObject1.Name:=S
849
// Messagedlg('A component named '+S+' already exists',mtWarning,[mbok],0);
850
S:=BaseSceneObject1.Name;
852
ShowBehavioursAndEffects(BaseSceneObject1);
854
FCurrentDesigner.Modified;
860
procedure TGLSceneEditorForm.TreeMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
862
FLastMouseDownPos:=Point(X, Y);
869
procedure TGLSceneEditorForm.TreeMouseMove(Sender: TObject;
870
Shift: TShiftState; X, Y: Integer);
874
if Shift=[ssLeft] then begin
876
if Assigned(node) and (node.Level>1) then
877
if (Abs(FLastMouseDownPos.x-x)>4) or (Abs(FLastMouseDownPos.y-y)>4) then
878
Tree.BeginDrag(False);
884
procedure TGLSceneEditorForm.TreeEnter(Sender: TObject);
886
if Assigned(FCurrentDesigner) and Assigned(Tree.Selected) then
887
FCurrentDesigner.SelectOnlyThisComponent(TGLBaseSceneObject(Tree.Selected.Data));
888
FSelectedItems:=SCENE_SELECTED;
889
EnableAndDisableActions();
894
procedure TGLSceneEditorForm.ACAddCameraExecute(Sender: TObject);
896
AObject: TGLBaseSceneObject;
899
if Assigned(FCurrentDesigner) then begin
900
AObject:=TGLBaseSceneObject(TGLCamera.Create(FCurrentDesigner.Form));
901
AObject.Name:=FCurrentDesigner.CreateUniqueComponentName(AObject.ClassName);
902
FScene.Objects.AddChild(AObject);
903
Node:=AddNodes(FObjectNode, AObject);
905
FCurrentDesigner.PropertyEditorHook.PersistentAdded(AObject,True);
906
FCurrentDesigner.Modified;
907
FCurrentDesigner.SelectOnlyThisComponent(AObject);
911
// ACDeleteObjectExecute
913
procedure TGLSceneEditorForm.ACDeleteObjectExecute(Sender: TObject);
915
anObject : TGLBaseSceneObject;
916
allowed, keepChildren : Boolean;
918
buttons : TMsgDlgButtons;
920
if FSelectedItems=BEHAVIOURS_SELECTED then begin
921
DeleteBaseBehaviour(BehavioursListView);
923
FCurrentDesigner.SelectOnlyThisComponent(TGLBaseSceneObject(Tree.Selected.data));
925
ShowBehaviours(TGLBaseSceneObject(Tree.Selected.data));
926
end else if FSelectedItems=EFFECTS_SELECTED then begin
927
DeleteBaseBehaviour(EffectsListView);
929
FCurrentDesigner.SelectOnlyThisComponent(TGLBaseSceneObject(Tree.Selected.data));
931
ShowEffects(TGLBaseSceneObject(Tree.Selected.data));
932
end else if FSelectedItems=SCENE_SELECTED then begin
933
if Assigned(Tree.Selected) and (Tree.Selected.Level > 1) then begin
934
anObject:=TGLBaseSceneObject(Tree.Selected.Data);
935
// ask for confirmation
936
if anObject.Name<>'' then
937
ConfirmMsg:='Delete '+anObject.Name
938
else ConfirmMsg:='Delete the marked object';
939
buttons:=[mbOK, mbCancel];
940
// are there children to care for?
941
// mbAll exist only on Windows ...
943
if (anObject.Count > 0) and (not anObject.HasSubChildren) then
945
confirmMsg:=ConfirmMsg+' only or with ALL its children?';
946
buttons:=[mbAll]+Buttons;
947
end else confirmMsg:=confirmMsg+'?';
949
case MessageDlg(confirmMsg, mtConfirmation, buttons, 0) of
969
if allowed then begin
970
if keepChildren=true then
971
while Tree.Selected.Count>0 do
972
Tree.Selected.Items[0].MoveTo(Tree.Selected,naAdd);
973
//previous line should be "naInsert" if children are to remain in position of parent
974
// (would require changes to TGLBaseSceneObject.Remove)
976
GlobalDesignHook.Unselect(anObject);
977
anObject.Parent.Remove(anObject, keepChildren);
978
FCurrentDesigner.Modified;
979
GlobalDesignHook.DeletePersistent(TPersistent(anObject));
985
function FindListViewData(list : TListView; data : Pointer) : TListItem;
990
for i:=0 to list.Items.Count-1 do
991
if list.Items[i].Data = data then begin
992
Result:=list.Items[i];
999
procedure TGLSceneEditorForm.ACMoveUpExecute(Sender: TObject);
1004
if FSelectedItems=BEHAVIOURS_SELECTED then
1006
PrevData:=BehavioursListView.Selected.Data;
1007
TGLBaseBehaviour(PrevData).MoveUp;
1008
ShowBehaviours(TGLBaseSceneObject(Tree.Selected.Data));
1009
BehavioursListView.Selected:=FindListViewData(BehavioursListView, PrevData);
1010
FCurrentDesigner.Modified;
1012
else if FSelectedItems=EFFECTS_SELECTED then
1014
PrevData:=EffectsListView.Selected.Data;
1015
TGLBaseBehaviour(PrevData).MoveUp;
1016
ShowEffects(TGLBaseSceneObject(Tree.Selected.Data));
1017
EffectsListView.Selected:=FindListViewData(EffectsListView, PrevData);
1018
FCurrentDesigner.Modified;
1020
else if FSelectedItems=SCENE_SELECTED then
1022
if ACMoveUp.Enabled then begin
1023
node:=Tree.Selected;
1024
if Assigned(node) then begin
1025
node.MoveTo(node.GetPrevSibling, naInsert);
1026
with TGLBaseSceneObject(node.Data) do begin
1030
TreeChange(Self, node);
1031
FCurrentDesigner.Modified;
1039
procedure TGLSceneEditorForm.ACMoveDownExecute(Sender: TObject);
1044
if FSelectedItems=BEHAVIOURS_SELECTED then
1046
PrevData:=BehavioursListView.Selected.Data;
1047
TGLBaseBehaviour(PrevData).MoveDown;
1048
ShowBehaviours(TGLBaseSceneObject(Tree.Selected.Data));
1049
BehavioursListView.Selected:=FindListViewData(BehavioursListView, PrevData);
1050
FCurrentDesigner.Modified;
1052
else if FSelectedItems=EFFECTS_SELECTED then
1054
PrevData:=EffectsListView.Selected.Data;
1055
TGLBaseBehaviour(PrevData).MoveDown;
1056
ShowEffects(TGLBaseSceneObject(Tree.Selected.Data));
1057
EffectsListView.Selected:=FindListViewData(EffectsListView, PrevData);
1058
FCurrentDesigner.Modified;
1060
else if FSelectedItems=SCENE_SELECTED then
1062
if ACMoveDown.Enabled then begin
1063
node:=Tree.Selected;
1064
if Assigned(node) then begin
1065
node.GetNextSibling.MoveTo(node, naInsert);
1066
with TGLBaseSceneObject(node.Data) do begin
1070
TreeChange(Self, node);
1071
FCurrentDesigner.Modified;
1077
// ACAddObjectExecute
1079
procedure TGLSceneEditorForm.ACAddObjectExecute(Sender: TObject);
1081
TBAddObjects.CheckMenuDropdown;
1084
procedure TGLSceneEditorForm.ACStayOnTopExecute(Sender: TObject);
1086
if TBStayOnTop.Down then
1087
FormStyle := fsStayOnTop
1089
FormStyle := fsNormal;
1092
// ACSaveSceneExecute
1094
procedure TGLSceneEditorForm.ACSaveSceneExecute(Sender: TObject);
1096
if SaveDialog.Execute then
1097
FScene.SaveToFile(SaveDialog.FileName);
1100
// ACLoadSceneExecute
1102
procedure TGLSceneEditorForm.ACLoadSceneExecute(Sender: TObject);
1104
if OpenDialog.Execute then begin
1105
FScene.LoadFromFile(OpenDialog.FileName);
1108
ShowBehavioursAndEffects(nil);
1114
procedure TGLSceneEditorForm.ACInfoExecute(Sender: TObject);
1116
AScene: TGLSceneViewer;
1118
AScene:=TGLSceneViewer.Create(Self);
1119
AScene.Name:='GLSceneEditor';
1122
AScene.Parent:=Self;
1124
AScene.Buffer.ShowInfo;
1130
// IsValidClipBoardNode
1132
function TGLSceneEditorForm.IsValidClipBoardNode : Boolean;
1134
selNode : TTreeNode;
1136
selNode:=Tree.Selected;
1137
Result:=((selNode<>nil) and (selNode.Parent<>nil)
1138
and (selNode.Parent.Parent<>nil));
1143
function TGLSceneEditorForm.IsPastePossible : Boolean;
1144
{$IFDEF GLS_DELPHI_6_UP}
1146
function PossibleStream(const S: string): Boolean;
1151
for I := 1 to Length(S) - 6 do begin
1152
if (S[I] in ['O','o']) and (CompareText(Copy(S, I, 6), 'OBJECT') = 0) then Exit;
1153
if not (S[I] in [' ',#9, #13, #10]) then Break;
1159
selNode : TTreeNode;
1160
anObject, destination : TGLBaseSceneObject;
1161
ComponentList: IDesignerSelections;
1162
TmpContainer : TComponent;
1164
selNode:=Tree.Selected;
1166
if (selNode<>nil) and (selNode.Parent<>nil)
1168
and (ClipBoard.HasFormat(CF_COMPONENT) or (Clipboard.HasFormat(CF_TEXT) and
1169
PossibleStream(Clipboard.AsText))) {$ENDIF} then
1171
TmpContainer := TComponent.Create(self);
1173
ComponentList := TDesignerSelections.Create;
1174
PasteComponents(TmpContainer, TmpContainer, ComponentList);
1175
if (ComponentList.Count>0) and (ComponentList[0] is TGLBaseSceneObject) then begin
1176
anObject:=TGLBaseSceneObject(ComponentList[0]);
1177
destination:=TGLBaseSceneObject(selNode.Data);
1178
Result:=CanPaste(anObject, destination);
1179
end else Result:=False;
1183
end else Result:=False;
1192
{$IFDEF GLS_DELPHI_6_UP}
1193
function TGLSceneEditorForm.CanPaste(obj, destination : TGLBaseSceneObject) : Boolean;
1195
Result:= Assigned(obj) and Assigned(destination);
1201
procedure TGLSceneEditorForm.ACCopyExecute(Sender: TObject);
1202
{$IFDEF GLS_DELPHI_6_UP}
1204
ComponentList: IDesignerSelections;
1206
ComponentList := TDesignerSelections.Create;
1207
ComponentList.Add(TGLBaseSceneObject(Tree.Selected.Data));
1208
CopyComponents(FScene.Owner, ComponentList);
1209
ACPaste.Enabled:=IsPastePossible;
1217
procedure TGLSceneEditorForm.ACCutExecute(Sender: TObject);
1218
{$IFDEF GLS_DELPHI_6_UP}
1220
AObject: TGLBaseSceneObject;
1221
ComponentList: IDesignerSelections;
1223
if IsValidClipBoardNode then
1225
AObject := TGLBaseSceneObject(Tree.Selected.Data);
1226
ComponentList := TDesignerSelections.Create;
1227
ComponentList.Add(TGLBaseSceneObject(Tree.Selected.Data));
1229
CopyComponents(FScene.Owner, ComponentList);
1230
AObject.Parent.Remove(AObject, False);
1233
ACPaste.Enabled:=IsPastePossible;
1243
procedure TGLSceneEditorForm.ACPasteExecute(Sender: TObject);
1244
{$IFDEF GLS_DELPHI_6_UP}
1246
selNode : TTreeNode;
1247
destination : TGLBaseSceneObject;
1248
ComponentList: IDesignerSelections;
1251
selNode:=Tree.Selected;
1252
if (selNode<>nil) and (selNode.Parent<>nil) then begin
1253
destination:=TGLBaseSceneObject(selNode.Data);
1254
ComponentList := TDesignerSelections.Create;
1255
PasteComponents(FScene.Owner, destination, ComponentList);
1256
if (ComponentList.count>0) and (CanPaste(TGLBaseSCeneObject(ComponentList[0]), destination)) then begin
1257
for t :=0 to ComponentList.Count-1 do
1258
AddNodes(selNode, TGLBaseSCeneObject(ComponentList[t]) );
1259
selNode.Expand(False);
1261
FCurrentDesigner.Modified;
1268
{$IFDEF GLS_DELPHI_6_UP}
1271
procedure TGLSceneEditorForm.CopyComponents(Root: TComponent; const Components: IDesignerSelections);
1277
S := TMemoryStream.Create;
1279
W := TWriter.Create(S, 1024);
1282
for I := 0 to Components.Count - 1 do
1285
W.WriteComponent(TComponent(Components[I]));
1291
CopyStreamToClipboard(S);
1297
procedure TGLSceneEditorForm.MethodError(Reader: TReader;
1298
const MethodName: String; var Address: Pointer; var Error: Boolean);
1300
// error is true because Address is nil in csDesigning
1304
procedure TGLSceneEditorForm.PasteComponents(AOwner, AParent: TComponent;const Components: IDesignerSelections);
1309
S := GetClipboardStream;
1311
R := TReader.Create(S, 1024);
1313
R.OnSetName := ReaderSetName;
1314
R.OnFindMethod := MethodError;
1315
FPasteOwner := AOwner;
1316
FPasteSelection := Components;
1317
R.ReadComponents(AOwner, AParent, ComponentRead);
1326
procedure TGLSceneEditorForm.ReaderSetName(Reader: TReader; Component: TComponent; var Name: string);
1328
if (Reader.Root = FPasteOwner) and (FPasteOwner.FindComponent(Name) <> nil) then
1329
Name := UniqueName(Component);
1332
function TGLSceneEditorForm.UniqueName(Component: TComponent): string;
1334
Result := FCurrentDesigner.CreateUniqueComponentName(Component.ClassName);
1337
procedure TGLSceneEditorForm.ComponentRead(Component: TComponent);
1339
FPasteSelection.Add(Component);
1343
procedure TGLSceneEditorForm.BehavioursListViewClick(Sender: TObject);
1345
if Assigned(FCurrentDesigner) and Assigned(BehavioursListView.Selected) then
1346
GlobalDesignHook.SelectOnlyThis(TGLBaseBehaviour(BehavioursListView.Selected.Data));
1347
FSelectedItems:=BEHAVIOURS_SELECTED;
1348
EnableAndDisableActions();
1351
procedure TGLSceneEditorForm.EffectsListViewClick(Sender: TObject);
1353
if Assigned(FCurrentDesigner) and Assigned(EffectsListView.Selected) then
1354
GlobalDesignHook.SelectOnlyThis(TGLXCollectionItem(EffectsListView.Selected.Data));
1355
FSelectedItems:=EFFECTS_SELECTED;
1356
EnableAndDisableActions();
1359
procedure TGLSceneEditorForm.ACAddBehaviourExecute(Sender: TObject);
1361
TBAddBehaviours.CheckMenuDropdown
1364
procedure TGLSceneEditorForm.DeleteBaseBehaviour(ListView:TListView);
1366
if ListView.Selected<>nil then
1369
GlobalDesignHook.SelectOnlyThis(nil);
1371
TGLXCollectionItem(ListView.Selected.Data).Free;
1372
ListView.Selected.Free;
1373
// ListViewChange(Self, nil, ctState);
1374
FCurrentDesigner.Modified;
1375
ShowBehavioursAndEffects(TGLBaseSceneObject(Tree.Selected.Data));
1379
procedure TGLSceneEditorForm.PMBehavioursToolbarPopup(Sender: TObject);
1381
object1:TGLBaseSceneObject;
1383
if (Tree.Selected)<>nil then
1385
object1:=TGLBaseSceneObject(Tree.Selected.Data);
1386
SetBehavioursSubItems(PMBehavioursToolbar.Items, object1.Behaviours);
1390
procedure TGLSceneEditorForm.PMEffectsToolbarPopup(Sender: TObject);
1392
object1:TGLBaseSceneObject;
1394
if (Tree.Selected)<>nil then
1396
object1:=TGLBaseSceneObject(Tree.Selected.Data);
1397
SetEffectsSubItems(PMEffectsToolbar.Items, object1.Effects);
1402
procedure TGLSceneEditorForm.BehavioursListViewSelectItem(Sender: TObject;
1403
Item: TListItem; Selected: Boolean);
1405
EnableAndDisableActions();
1410
procedure TGLSceneEditorForm.ACAddEffectExecute(Sender: TObject);
1412
TBAddEffects.CheckMenuDropdown;
1415
procedure TGLSceneEditorForm.EnableAndDisableActions();
1419
if FSelectedItems=SCENE_SELECTED then
1421
selNode:=Tree.Selected;
1422
// select in Delphi IDE
1423
if Assigned(selNode) then
1425
if Assigned(selNode.Data) then
1426
FCurrentDesigner.SelectOnlyThisComponent(TGLBaseSceneObject(selNode.Data))
1427
else FCurrentDesigner.SelectOnlyThisComponent(FScene);
1429
ACAddCamera.Enabled:=((selNode=FObjectNode) or selNode.HasAsParent(FObjectNode));
1430
ACAddObject.Enabled:=((selNode=FObjectNode) or selNode.HasAsParent(FObjectNode));
1431
ACAddBehaviour.Enabled:=(selNode.HasAsParent(FObjectNode));
1432
ACAddEffect.Enabled:=(selNode.HasAsParent(FObjectNode));
1433
ACDeleteObject.Enabled:=(selNode.Level>1);
1434
ACMoveUp.Enabled:=((selNode.Index>0)and(selNode.Level>1));
1435
ACMoveDown.Enabled:=((selNode.GetNextSibling<>nil)and(selNode.Level>1));
1436
ACCut.Enabled:=IsValidClipBoardNode;
1437
ACPaste.Enabled:=IsPastePossible;
1442
ACAddCamera.Enabled:=False;
1443
ACAddObject.Enabled:=False;
1444
ACAddBehaviour.Enabled:=False;
1445
ACAddEffect.Enabled:=False;
1446
ACDeleteObject.Enabled:=False;
1447
ACMoveUp.Enabled:=False;
1448
ACMoveDown.Enabled:=False;
1449
ACCut.Enabled:=False;
1450
ACPaste.Enabled:=False;
1453
ACCopy.Enabled:=ACCut.Enabled;
1456
else if FSelectedItems=BEHAVIOURS_SELECTED then
1458
if (BehavioursListView.Selected<>nil) then
1460
GlobalDesignHook.SelectOnlyThis(TGLBaseBehaviour(BehavioursListView.Selected.Data));
1461
//Writeln('BehavioursListView.Selected.data=',hexStr(BehavioursListView.Selected.data));
1462
ACDeleteObject.Enabled:=True;
1463
ACMoveUp.Enabled:=(BehavioursListView.Selected.Index>0);
1464
ACMoveDown.Enabled:=(BehavioursListView.Selected.Index<BehavioursListView.Selected.Owner.Count-1);
1465
ACCut.Enabled:=False;
1466
ACCopy.Enabled:=false;
1467
ACPaste.Enabled:=False;
1471
ACDeleteObject.Enabled:=false;
1472
ACMoveUp.Enabled:=false;
1473
ACMoveDown.Enabled:=false;
1474
ACCut.Enabled:=false;
1475
ACCopy.Enabled:=false;
1476
ACPaste.Enabled:=false;
1479
else if FSelectedItems=EFFECTS_SELECTED then
1481
if (EffectsListView.Selected<>nil)then
1483
GlobalDesignHook.SelectOnlyThis(TGLXCollectionItem(EffectsListView.Selected.Data));
1484
ACDeleteObject.Enabled:=True;
1485
ACMoveUp.Enabled:=(EffectsListView.Selected.Index>0);
1486
ACMoveDown.Enabled:=(EffectsListView.Selected.Index<EffectsListView.Selected.Owner.Count-1);
1487
ACCut.Enabled:=False;
1488
ACCopy.Enabled:=false;
1489
ACPaste.Enabled:=False;
1493
ACDeleteObject.Enabled:=false;
1494
ACMoveUp.Enabled:=false;
1495
ACMoveDown.Enabled:=false;
1496
ACCut.Enabled:=false;
1497
ACCopy.Enabled:=false;
1498
ACPaste.Enabled:=false;
1504
procedure TGLSceneEditorForm.PopupMenuPopup(Sender: TObject);
1507
sceneObj : TGLBaseSceneObject;
1509
if (Tree.Selected)<>nil then begin
1510
obj:=TObject(Tree.Selected.Data);
1511
if Assigned(obj) and (obj is TGLBaseSceneObject) then begin
1512
sceneObj:=TGLBaseSceneObject(obj);
1513
SetBehavioursSubItems(MIAddBehaviour, sceneObj.Behaviours);
1514
SetEffectsSubItems(MIAddEffect, sceneObj.Effects);
1516
SetBehavioursSubItems(MIAddBehaviour, nil);
1517
SetEffectsSubItems(MIAddEffect, nil);
1522
procedure TGLSceneEditorForm.TBEffectsPanelClick(Sender: TObject);
1524
PABehaviours.Visible:=TBEffectsPanel.Down;
1525
Splitter.Visible:=TBEffectsPanel.Down;
1526
if PABehaviours.Visible then
1527
Width:=Width+PABehaviours.Width
1528
else Width:=Width-PABehaviours.Width;
1531
procedure TGLSceneEditorForm.TreeKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
1533
if (Key = glKey_DELETE) and not Tree.IsEditing then begin
1535
ACDeleteObject.Execute;
1542
{$I GLSceneEditLCL.lrs}
1545
ReleaseGLSceneEditorForm;