GLS.Gizmo.pas 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845
  1. //
  2. // The graphics engine GLXEngine. The unit of GLScene for Delphi
  3. //
  4. unit GLS.Gizmo;
  5. (*
  6. Invisible component for helping to Move, Rotate and Scale an Object
  7. under GLScene (usefull for an Editor).
  8. *)
  9. // ------------------------------------------------------------------------------
  10. // Description :
  11. // Invisible component for helping to Move, Rotate and Scale an Object
  12. // under GLScene (usefull for an Editor)
  13. // ------------------------------------------------------------------------------
  14. // Features :
  15. // - Interaction When All Gizmo parts are Invisible
  16. // - Add "gpMoveGizmo and gpRotateGizmo" operations and use Like a "Pivot"
  17. // or use RootGizmo As "Pivot"
  18. // - Add Interactive Camera Movements
  19. // - Adding Extended Controls with Keys
  20. // - Maybe An Undo Function
  21. // ------------------------------------------------------------------------------
  22. // Bugs Known :
  23. // - When you change the BoundingBoxColor and LabelInfosColor
  24. // The New Color is not Updated immediately, only after a new Click
  25. // (see in UpdateGizmo, SetBoundingBoxColor
  26. // and SetLabelInfosColor Procedures)
  27. // - Bounding Box is not always drawn correctly because it does not
  28. // use objects' BarryCenter. For Example, if you select Space Text.
  29. // ------------------------------------------------------------------------------
  30. interface
  31. {$I Stage.Defines.inc}
  32. uses
  33. System.Classes,
  34. System.SysUtils,
  35. Vcl.StdCtrls,
  36. Stage.VectorTypes,
  37. Stage.VectorGeometry,
  38. Stage.Strings,
  39. GLS.Scene,
  40. GLS.PersistentClasses,
  41. GLS.Color,
  42. GLS.Objects,
  43. GLS.Material,
  44. GLS.GeomObjects,
  45. GLS.BitmapFont,
  46. GLS.SceneViewer,
  47. GLS.VectorFileObjects,
  48. GLS.Coordinates,
  49. GLS.RenderContextInfo,
  50. GLS.State,
  51. GLS.Selection;
  52. type
  53. TGLGizmoUndoCollection = class;
  54. TGLGizmo = class;
  55. TGLGizmoUndoItem = class(TCollectionItem)
  56. private
  57. FOldLibMaterialName: string;
  58. FOldAutoScaling: TGLCoordinates;
  59. FEffectedObject: TGLCustomSceneObject;
  60. FOldMatr: TGLMatrix;
  61. FOldMatrix: TGLMatrix;
  62. procedure SetEffectedObject(const Value: TGLCustomSceneObject);
  63. procedure SetOldAutoScaling(const Value: TGLCoordinates);
  64. procedure SetOldMatrix(const Value: TGLMatrix);
  65. protected
  66. procedure DoUndo; virtual;
  67. function GetParent: TGLGizmoUndoCollection;
  68. function GetGizmo: TGLGizmo;
  69. public
  70. constructor Create(AOwner: TCollection); override;
  71. destructor Destroy; override;
  72. procedure Notification(AComponent: TComponent;
  73. Operation: TOperation); virtual;
  74. procedure AssignFromObject(const AObject: TGLCustomSceneObject);
  75. // TODO: create a special type for Matrix.
  76. property OldMatrix: TGLMatrix read FOldMatrix write SetOldMatrix;
  77. published
  78. property EffectedObject: TGLCustomSceneObject read FEffectedObject
  79. write SetEffectedObject;
  80. property OldAutoScaling: TGLCoordinates read FOldAutoScaling
  81. write SetOldAutoScaling;
  82. property OldLibMaterialName: string read FOldLibMaterialName
  83. write FOldLibMaterialName;
  84. end;
  85. TGLGizmoUndoCollection = class(TOwnedCollection)
  86. private
  87. function GetItems(const Index: Integer): TGLGizmoUndoItem;
  88. procedure SetItems(const Index: Integer; const Value: TGLGizmoUndoItem);
  89. protected
  90. function GetParent: TGLGizmo;
  91. public
  92. procedure Notification(AComponent: TComponent; Operation: TOperation);
  93. procedure RemoveByObject(const AObject: TGLCustomSceneObject);
  94. function Add: TGLGizmoUndoItem;
  95. property Items[const Index: Integer]: TGLGizmoUndoItem read GetItems
  96. write SetItems; default;
  97. end;
  98. TGLGizmoElement = (geMove, geRotate, geScale, geAxisLabel, geObjectInfos,
  99. geBoundingBox);
  100. TGLGizmoElements = set of TGLGizmoElement;
  101. TGLGizmoVisibleInfoLabel = (vliName, vliOperation, vliCoords);
  102. TGLGizmoVisibleInfoLabels = set of TGLGizmoVisibleInfoLabel;
  103. TGLGizmoAxis = (gaNone, gaX, gaY, gaZ, gaXY, gaXZ, gaYZ);
  104. TGLGizmoOperation = (gopMove, gopRotate, gopScale, gopNone, gpMoveGizmo,
  105. gpRotateGizmo);
  106. TGLGizmoAcceptEvent = procedure(Sender: TObject; var Obj: TGLBaseSceneObject;
  107. var Accept: Boolean; var Dimensions: TGLVector) of object;
  108. TGLGizmoUpdateEvent = procedure(Sender: TObject; Obj: TGLBaseSceneObject;
  109. Axis: TGLGizmoAxis; Operation: TGLGizmoOperation; var Vector: TGLVector)
  110. of object;
  111. TGLGizmoPickMode = (pmGetPickedObjects, pmRayCast);
  112. TGLGizmoRayCastHitData = class(TPersistent)
  113. public
  114. Obj: TGLBaseSceneObject;
  115. Point: TGLVector;
  116. end;
  117. TGLGizmoPickCube = class(TGLCube)
  118. end;
  119. TGLGizmoPickTorus = class(TGLTorus)
  120. end;
  121. TGLGizmo = class(TComponent)
  122. private
  123. _GZObaseGizmo: TGLBaseSceneObject;
  124. _GZOBoundingcube: TGLCube;
  125. _GZOrootHelpers: TGLBaseSceneObject;
  126. _GZOrootLines: TGLBaseSceneObject;
  127. _GZOrootTorus: TGLBaseSceneObject;
  128. _GZOrootCubes: TGLBaseSceneObject;
  129. _GZORootAxisLabel: TGLBaseSceneObject;
  130. _GZORootVisibleInfoLabels: TGLBaseSceneObject;
  131. _GZOlineX, _GZOlineY, _GZOlineZ, _GZOplaneXY, _GZOplaneXZ,
  132. _GZOplaneYZ: TGLLines; // For Move
  133. _GZOTorusX, _GZOTorusY, _GZOTorusZ: TGLGizmoPickTorus; // For Rotate
  134. _GZOCubeX, _GZOCubeY, _GZOCubeZ: TGLGizmoPickCube; // For Scale
  135. _GZOAxisLabelX, _GZOAxisLabelY, _GZOAxisLabelZ: TGLFlatText;
  136. _GZOVisibleInfoLabels: TGLFlatText;
  137. FRootGizmo: TGLBaseSceneObject;
  138. FSelectedObj: TGLBaseSceneObject;
  139. // FLastOperation,
  140. FOperation: TGLGizmoOperation;
  141. FSelAxis: TGLGizmoAxis;
  142. FBoundingBoxColor: TGLColor;
  143. FSelectedColor: TGLColor;
  144. FVisibleInfoLabelsColor: TGLColor;
  145. FBoundingBoxColorChanged: Boolean;
  146. FVisibleInfoLabelsColorChanged: Boolean;
  147. FForceOperation: Boolean;
  148. FForceAxis: Boolean;
  149. FForceUniformScale: Boolean;
  150. FAutoZoom: Boolean;
  151. FExcludeObjects: Boolean;
  152. FNoZWrite: Boolean;
  153. FEnabled: Boolean;
  154. FAutoZoomFactor: Single;
  155. FZoomFactor: Single;
  156. FMoveCoef: Single;
  157. FRotationCoef: Single;
  158. FViewer: TGLSceneViewer;
  159. FGizmoElements: TGLGizmoElements;
  160. FVisibleVisibleInfoLabels: TGLGizmoVisibleInfoLabels;
  161. FExcludeObjectsList: TStrings;
  162. Moving: Boolean;
  163. Mx, My: Integer;
  164. Rx, Ry: Integer;
  165. dglEnable, dglDisable, dgtEnable, dgtDisable, dgcEnable, dgcDisable,
  166. dglaEnable, dglaDisable, dgliEnable, dgliDisable: TGLDirectOpenGL;
  167. LastMousePos: TGLVector;
  168. ObjDimensions: TGLVector;
  169. FOnBeforeSelect: TGLGizmoAcceptEvent;
  170. FOnBeforeUpdate: TGLGizmoUpdateEvent;
  171. FOnSelectionLost: TNotifyEvent;
  172. FScaleCoef: Single;
  173. FGizmoThickness: Single;
  174. FPickMode: TGLGizmoPickMode;
  175. FInternalRaycastHitData: TList;
  176. FUndoHistory: TGLGizmoUndoCollection;
  177. FLabelFont: TGLCustomBitmapFont;
  178. procedure SetRootGizmo(const AValue: TGLBaseSceneObject);
  179. procedure SetGizmoElements(const AValue: TGLGizmoElements);
  180. procedure SeTGLGizmoVisibleInfoLabels(const AValue: TGLGizmoVisibleInfoLabels);
  181. procedure SetBoundingBoxColor(const AValue: TGLColor);
  182. procedure SetSelectedColor(const AValue: TGLColor);
  183. procedure SetVisibleInfoLabelsColor(const AValue: TGLColor);
  184. procedure SetExcludeObjectsList(const AValue: TStrings);
  185. procedure DirectGlDisable(Sender: TObject; var Rci: TGLRenderContextInfo);
  186. procedure DirectGlEnable(Sender: TObject; var Rci: TGLRenderContextInfo);
  187. function MouseWorldPos(const X, Y: Integer): TGLVector;
  188. function CheckObjectInExcludeList(const Obj: TGLBaseSceneObject): Boolean;
  189. procedure UpdateVisibleInfoLabels;
  190. procedure SetGLGizmoThickness(const Value: Single);
  191. function InternalGetPickedObjects(const X1, Y1, X2, Y2: Integer;
  192. const GuessCount: Integer = 8): TGLPickList;
  193. procedure ClearInternalRaycastHitData;
  194. procedure SetViewer(const Value: TGLSceneViewer);
  195. procedure SetLabelFont(const Value: TGLCustomBitmapFont);
  196. procedure SetSelectedObj(const Value: TGLBaseSceneObject);
  197. public
  198. PickableObjectsWithRayCast: TList;
  199. constructor Create(AOwner: TComponent); override;
  200. destructor Destroy; override;
  201. procedure Loaded; override;
  202. procedure Notification(AComponent: TComponent;
  203. Operation: TOperation); override;
  204. procedure ViewerMouseMove(const X, Y: Integer);
  205. procedure ViewerMouseDown(const X, Y: Integer);
  206. procedure ViewerMouseUp(const X, Y: Integer);
  207. procedure UpdateGizmo; overload;
  208. procedure UpdateGizmo(const NewDimensions: TGLVector); overload;
  209. procedure SetVisible(const AValue: Boolean);
  210. function GetPickedObjectPoint(const Obj: TGLBaseSceneObject): TGLVector;
  211. procedure LooseSelection; virtual;
  212. procedure UndoAdd(const AObject: TGLCustomSceneObject);
  213. property RootGizmo: TGLBaseSceneObject read FRootGizmo write SetRootGizmo;
  214. // --------------------------------------------------------------------
  215. published
  216. property Viewer: TGLSceneViewer read FViewer write SetViewer;
  217. property GizmoElements: TGLGizmoElements read FGizmoElements
  218. write SetGizmoElements;
  219. property BoundingBoxColor: TGLColor read FBoundingBoxColor
  220. write SetBoundingBoxColor;
  221. property SelectedColor: TGLColor read FSelectedColor write SetSelectedColor;
  222. property SelAxis: TGLGizmoAxis read FSelAxis write FSelAxis;
  223. property ForceAxis: Boolean read FForceAxis write FForceAxis;
  224. property SelectedObj: TGLBaseSceneObject read FSelectedObj
  225. write SetSelectedObj;
  226. property Operation: TGLGizmoOperation read FOperation write FOperation;
  227. property ForceOperation: Boolean read FForceOperation write FForceoperation;
  228. property ForceUniformScale: Boolean read FForceUniformScale
  229. write FForceUniformScale;
  230. property ExcludeObjects: Boolean read FExcludeObjects write FExcludeObjects;
  231. property ExcludeObjectsList: TStrings read FExcludeObjectsList
  232. write SetExcludeObjectsList;
  233. property VisibleInfoLabels: TGLGizmoVisibleInfoLabels
  234. read FVisibleVisibleInfoLabels write SeTGLGizmoVisibleInfoLabels;
  235. property VisibleInfoLabelsColor: TGLColor read FVisibleInfoLabelsColor
  236. write SetVisibleInfoLabelsColor;
  237. property AutoZoom: Boolean read FAutoZoom write FAutoZoom;
  238. property AutoZoomFactor: Single read FAutoZoomFactor write FAutoZoomFactor;
  239. property ZoomFactor: Single read FZoomFactor write FZoomFactor;
  240. property MoveCoef: Single read FMoveCoef write FMoveCoef;
  241. property RotationCoef: Single read FRotationCoef write FRotationCoef;
  242. property ScaleCoef: Single read FScaleCoef write FScaleCoef;
  243. property NoZWrite: Boolean read FNoZWrite write FNoZWrite;
  244. property GizmoThickness: Single read FGizmoThickness
  245. write SeTGLGizmoThickness;
  246. (* Indicates whether the gizmo is enabled or not.
  247. WARNING: When loading/editing (possibly whenever a structureChanged
  248. call is made) a model, sometimes the gizmo will trigger a
  249. bug if the mouse is inside the glscene Viewer. To prevent that,
  250. remember to disable the gizmo before loading, then process windows
  251. messages (i.e. application.processMessage) and then enable the gizmo again.
  252. Warning Enable is ReadOnly property if you set to False, Gizmo is not Hidden
  253. use Visible instead if you want to Hide, if you want to Hide but keep enabled
  254. see the VisibleGizmo property *)
  255. property Enabled: Boolean read FEnabled write FEnabled default False;
  256. property LabelFont: TGLCustomBitmapFont read FLabelFont write SetLabelFont
  257. default nil;
  258. property OnBeforeSelect: TGLGizmoAcceptEvent read FOnBeforeSelect
  259. write FOnBeforeSelect;
  260. property OnSelectionLost: TNotifyEvent read FOnSelectionLost
  261. write FOnSelectionLost;
  262. (* Called before an Update is applied. The "vector" parameter is the difference
  263. that will be applied to the object, according to the axis and operation selected. *)
  264. property OnBeforeUpdate: TGLGizmoUpdateEvent read FOnBeforeUpdate
  265. write FOnBeforeUpdate;
  266. property PickMode: TGLGizmoPickMode read FPickMode write FPickMode
  267. default PmGetPickedObjects;
  268. end;
  269. //=========================================================
  270. implementation
  271. //=========================================================
  272. procedure RotateAroundArbitraryAxis(const AnObject: TGLBaseSceneObject;
  273. const Axis, Origin: TAffineVector; const Angle: Single);
  274. var
  275. M, M1, M2, M3: TGLMatrix;
  276. begin
  277. M1 := CreateTranslationMatrix(VectorNegate(Origin));
  278. M2 := CreateRotationMatrix(Axis, Angle * PI / 180);
  279. M3 := CreateTranslationMatrix(Origin);
  280. M := MatrixMultiply(M1, M2);
  281. M := MatrixMultiply(M, M3);
  282. AnObject.SetMatrix(MatrixMultiply(AnObject.Matrix^, M));
  283. // Just a workarround to Update angles...
  284. AnObject.Roll(0);
  285. AnObject.Pitch(0);
  286. AnObject.Turn(0);
  287. end;
  288. // ------------------------------------------------------------------------------
  289. procedure TGLGizmo.ClearInternalRaycastHitData;
  290. var
  291. T: Integer;
  292. begin
  293. for T := FInternalRaycastHitData.Count - 1 downto 0 do
  294. begin
  295. TGLGizmoRayCastHitData(FInternalRaycastHitData[T]).Free;
  296. end;
  297. FInternalRaycastHitData.Clear;
  298. end;
  299. constructor TGLGizmo.Create(AOwner: TComponent);
  300. var
  301. Cub: TGLCube;
  302. begin
  303. inherited Create(AOwner);
  304. FUndoHistory := TGLGizmoUndoCollection.Create(Self, TGLGizmoUndoItem);
  305. FPickMode := PmGetPickedObjects;
  306. PickableObjectsWithRayCast := TList.Create;
  307. FRotationCoef := 1;
  308. FMoveCoef := 0.1;
  309. FScaleCoef := 0.1;
  310. FGizmoThickness := 1;
  311. FInternalRaycastHitData := TList.Create;
  312. FBoundingBoxColor := TGLColor.Create(Self);
  313. FBoundingBoxColor.Color := ClrWhite;
  314. FBoundingBoxColorChanged := False;
  315. FSelectedColor := TGLColor.Create(Self);
  316. FSelectedColor.Color := ClrYellow;
  317. FVisibleInfoLabelsColor := TGLColor.Create(Self);
  318. FVisibleInfoLabelsColor.Color := ClrYellow;
  319. FVisibleInfoLabelsColorChanged := False;
  320. _GZObaseGizmo := TGLDummyCube.Create(Self);
  321. _GZORootHelpers := TGLDummyCube(_GZObaseGizmo.AddNewChild(TGLDummyCube));
  322. _GZOBoundingcube := TGLCube(_GZORootHelpers.AddNewChild(TGLCube));
  323. _GZORootLines := _GZORootHelpers.AddNewChild(TGLDummyCube);
  324. _GZORootTorus := _GZORootHelpers.AddNewChild(TGLDummyCube);
  325. _GZORootCubes := _GZORootHelpers.AddNewChild(TGLDummyCube);
  326. _GZORootAxisLabel := _GZORootHelpers.AddNewChild(TGLDummyCube);
  327. _GZORootVisibleInfoLabels := _GZORootHelpers.AddNewChild(TGLDummyCube);
  328. DglDisable := TGLDirectOpenGL(_GZORootLines.AddNewChild(TGLDirectOpenGL));
  329. DglDisable.OnRender := DirectGlDisable;
  330. DgtDisable := TGLDirectOpenGL(_GZORootTorus.AddNewChild(TGLDirectOpenGL));
  331. DgtDisable.OnRender := DirectGlDisable;
  332. DgcDisable := TGLDirectOpenGL(_GZORootCubes.AddNewChild(TGLDirectOpenGL));
  333. DgcDisable.OnRender := DirectGlDisable;
  334. DglaDisable := TGLDirectOpenGL
  335. (_GZORootAxisLabel.AddNewChild(TGLDirectOpenGL));
  336. DglaDisable.OnRender := DirectGlDisable;
  337. DgliDisable := TGLDirectOpenGL(_GZORootVisibleInfoLabels.AddNewChild
  338. (TGLDirectOpenGL));
  339. DgliDisable.OnRender := DirectGlDisable;
  340. with _GZOBoundingcube.Material do
  341. begin
  342. FaceCulling := FcNoCull;
  343. PolygonMode := PmLines;
  344. with FrontProperties do
  345. begin
  346. Diffuse.Color := FBoundingBoxColor.Color;
  347. Ambient.Color := FBoundingBoxColor.Color;
  348. Emission.Color := FBoundingBoxColor.Color;
  349. end;
  350. with BackProperties do
  351. begin
  352. Diffuse.Color := FBoundingBoxColor.Color;
  353. Ambient.Color := FBoundingBoxColor.Color;
  354. Emission.Color := FBoundingBoxColor.Color;
  355. end;
  356. end;
  357. _GZOlinex := TGLLines(_GZORootLines.AddnewChild(TGLLines));
  358. with _GZOlinex do
  359. begin
  360. LineColor.Color := clrRed;
  361. LineWidth := 3;
  362. NodesAspect := LnaInvisible;
  363. AddNode(0, 0, 0);
  364. AddNode(1, 0, 0);
  365. AddNode(0.9, 0, -0.1);
  366. AddNode(1, 0, 0);
  367. AddNode(0.9, 0, 0.1);
  368. // Raycast pickable object
  369. Cub := TGLGizmoPickCube(AddNewChild(TGLGizmoPickCube));
  370. Cub.Up.SetVector(1, 0, 0);
  371. Cub.CubeWidth := 0.1;
  372. Cub.CubeHeight := 1;
  373. Cub.CubeDepth := 0.1;
  374. Cub.Position.SetPoint(0.5, 0, 0);
  375. Cub.Visible := False;
  376. end;
  377. _GZOliney := TGLLines(_GZORootLines.AddnewChild(TGLLines));
  378. with _GZOliney do
  379. begin
  380. LineColor.Color := clrLime;
  381. LineWidth := 3;
  382. NodesAspect := LnaInvisible;
  383. AddNode(0, 0, 0);
  384. AddNode(0, 1, 0);
  385. AddNode(0.1, 0.9, 0);
  386. AddNode(0, 1, 0);
  387. AddNode(-0.1, 0.9, 0);
  388. // Raycast pickable object
  389. Cub := TGLGizmoPickCube(AddNewChild(TGLGizmoPickCube));
  390. Cub.Up.SetVector(0, 1, 0);
  391. Cub.CubeWidth := 0.1;
  392. Cub.CubeHeight := 1;
  393. Cub.CubeDepth := 0.1;
  394. Cub.Position.SetPoint(0, 0.5, 0);
  395. Cub.Visible := False;
  396. end;
  397. _GZOlinez := TGLLines(_GZORootLines.AddnewChild(TGLLines));
  398. with _GZOlinez do
  399. begin
  400. LineColor.Color := clrBlue;
  401. LineWidth := 3;
  402. NodesAspect := LnaInvisible;
  403. AddNode(0, 0, 0);
  404. AddNode(0, 0, 1);
  405. AddNode(0.1, 0, 0.9);
  406. AddNode(0, 0, 1);
  407. AddNode(-0.1, 0, 0.9);
  408. // Raycast pickable object
  409. Cub := TGLGizmoPickCube(AddNewChild(TGLGizmoPickCube));
  410. Cub.Up.SetVector(0, 0, 1);
  411. Cub.CubeWidth := 0.1;
  412. Cub.CubeHeight := 1;
  413. Cub.CubeDepth := 0.1;
  414. Cub.Position.SetPoint(0, 0, 0.5);
  415. Cub.Visible := False;
  416. end;
  417. _GZOplaneXY := TGLLines(_GZORootLines.AddnewChild(TGLLines));
  418. with _GZOplaneXY do
  419. begin
  420. LineWidth := 3;
  421. Options := [LoUseNodeColorForLines];
  422. NodesAspect := LnaInvisible;
  423. SplineMode := LsmSegments;
  424. AddNode(0.8, 1, 0);
  425. TGLLinesNode(Nodes[0]).Color.Color := clrRed;
  426. AddNode(1, 1, 0);
  427. TGLLinesNode(Nodes[1]).Color.Color := clrRed;
  428. AddNode(1, 1, 0);
  429. TGLLinesNode(Nodes[2]).Color.Color := clrLime;
  430. AddNode(1, 0.8, 0);
  431. TGLLinesNode(Nodes[3]).Color.Color := clrLime;
  432. // Raycast pickable object
  433. Cub := TGLGizmoPickCube(AddNewChild(TGLGizmoPickCube));
  434. Cub.Up.SetVector(1, 0, 0);
  435. Cub.CubeWidth := 0.2;
  436. Cub.CubeHeight := 0.2;
  437. Cub.CubeDepth := 0.1;
  438. Cub.Position.SetPoint(0.9, 0.9, 0);
  439. Cub.Visible := False;
  440. end;
  441. _GZOplaneXZ := TGLLines(_GZORootLines.AddnewChild(TGLLines));
  442. with _GZOplaneXZ do
  443. begin
  444. LineWidth := 3;
  445. Options := [LoUseNodeColorForLines];
  446. NodesAspect := LnaInvisible;
  447. SplineMode := LsmSegments;
  448. AddNode(1, 0, 0.8);
  449. TGLLinesNode(Nodes[0]).Color.Color := clrBlue;
  450. AddNode(1, 0, 1);
  451. TGLLinesNode(Nodes[1]).Color.Color := clrBlue;
  452. AddNode(1, 0, 1);
  453. TGLLinesNode(Nodes[2]).Color.Color := clrRed;
  454. AddNode(0.8, 0, 1);
  455. TGLLinesNode(Nodes[3]).Color.Color := clrRed;
  456. // Raycast pickable object
  457. Cub := TGLGizmoPickCube(AddNewChild(TGLGizmoPickCube));
  458. Cub.Up.SetVector(1, 0, 0);
  459. Cub.CubeWidth := 0.1;
  460. Cub.CubeHeight := 0.2;
  461. Cub.CubeDepth := 0.2;
  462. Cub.Position.SetPoint(0.9, 0, 0.9);
  463. Cub.Visible := False;
  464. end;
  465. _GZOplaneYZ := TGLLines(_GZORootLines.AddnewChild(TGLLines));
  466. with _GZOplaneYZ do
  467. begin
  468. LineWidth := 3;
  469. Options := [LoUseNodeColorForLines];
  470. NodesAspect := LnaInvisible;
  471. SplineMode := LsmSegments;
  472. AddNode(0, 0.8, 1);
  473. TGLLinesNode(Nodes[0]).Color.Color := clrLime;
  474. AddNode(0, 1, 1);
  475. TGLLinesNode(Nodes[1]).Color.Color := clrLime;
  476. AddNode(0, 1, 1);
  477. TGLLinesNode(Nodes[2]).Color.Color := clrBlue;
  478. AddNode(0, 1, 0.8);
  479. TGLLinesNode(Nodes[3]).Color.Color := clrBlue;
  480. // Raycast pickable object
  481. Cub := TGLGizmoPickCube(AddNewChild(TGLGizmoPickCube));
  482. Cub.Up.SetVector(0, 0, 1);
  483. Cub.CubeWidth := 0.2;
  484. Cub.CubeHeight := 0.2;
  485. Cub.CubeDepth := 0.1;
  486. Cub.Position.SetPoint(0, 0.9, 0.9);
  487. Cub.Visible := False;
  488. end;
  489. _GZOTorusX := TGLGizmoPickTorus(_GZORootTorus.AddnewChild(TGLGizmoPickTorus));
  490. with _GZOTorusX do
  491. begin
  492. Rings := 16;
  493. Sides := 4;
  494. MajorRadius := 0.6;
  495. MinorRadius := 0.03;
  496. PitchAngle := 90;
  497. TurnAngle := 90;
  498. with Material do
  499. begin
  500. // FaceCulling:= fcNoCull;
  501. PolygonMode := PmFill;
  502. // BackProperties.PolygonMode:= pmFill;
  503. FrontProperties.Emission.Color := clrBlue;
  504. end;
  505. end;
  506. _GZOTorusY := TGLGizmoPickTorus(_GZORootTorus.AddnewChild(TGLGizmoPickTorus));
  507. with _GZOTorusY do
  508. begin
  509. Rings := 16;
  510. Sides := 4;
  511. MajorRadius := 0.6;
  512. MinorRadius := 0.03;
  513. PitchAngle := 90;
  514. with Material do
  515. begin
  516. // FaceCulling:= fcNoCull;
  517. PolygonMode := PmFill;
  518. // BackProperties.PolygonMode:= pmFill;
  519. FrontProperties.Emission.Color := clrRed;
  520. end;
  521. end;
  522. _GZOTorusZ := TGLGizmoPickTorus(_GZORootTorus.AddnewChild(TGLGizmoPickTorus));
  523. with _GZOTorusZ do
  524. begin
  525. Rings := 16;
  526. Sides := 4;
  527. MajorRadius := 0.6;
  528. MinorRadius := 0.03;
  529. with Material do
  530. begin
  531. // FaceCulling:= fcNoCull;
  532. PolygonMode := PmFill;
  533. // BackProperties.PolygonMode:= pmFill;
  534. FrontProperties.Emission.Color := clrLime;
  535. end;
  536. end;
  537. _GZOCubeX := TGLGizmoPickCube(_GZORootCubes.AddnewChild(TGLGizmoPickCube));
  538. with _GZOCubeX do
  539. begin
  540. CubeDepth := 0.1;
  541. CubeHeight := 0.1;
  542. CubeWidth := 0.1;
  543. Position.X := 1.15;
  544. with Material do
  545. begin
  546. FaceCulling := FcNoCull;
  547. PolygonMode := PmFill;
  548. FrontProperties.Emission.Color := clrRed;
  549. end;
  550. end;
  551. _GZOCubeY := TGLGizmoPickCube(_GZORootCubes.AddnewChild(TGLGizmoPickCube));
  552. with _GZOCubeY do
  553. begin
  554. CubeDepth := 0.1;
  555. CubeHeight := 0.1;
  556. CubeWidth := 0.1;
  557. Position.Y := 1.15;
  558. with Material do
  559. begin
  560. FaceCulling := FcNoCull;
  561. PolygonMode := PmFill;
  562. FrontProperties.Emission.Color := clrLime;
  563. end;
  564. end;
  565. _GZOCubeZ := TGLGizmoPickCube(_GZORootCubes.AddnewChild(TGLGizmoPickCube));
  566. with _GZOCubeZ do
  567. begin
  568. CubeDepth := 0.1;
  569. CubeHeight := 0.1;
  570. CubeWidth := 0.1;
  571. Position.Z := 1.15;
  572. with Material do
  573. begin
  574. FaceCulling := FcNoCull;
  575. PolygonMode := PmFill;
  576. FrontProperties.Emission.Color := clrBlue;
  577. end;
  578. end;
  579. _GZOAxisLabelX := TGLFlatText(_GZORootAxisLabel.AddNewChild(TGLFlatText));
  580. with _GZOAxisLabelX do
  581. begin
  582. ModulateColor.Color := ClrRed;
  583. Alignment := TaCenter;
  584. Layout := TTextLayout.tlCenter;
  585. Options := Options + [FtoTwoSided];
  586. Position.X := 1.5;
  587. Scale.X := 0.02;
  588. Scale.Y := 0.02;
  589. Text := 'X';
  590. end;
  591. _GZOAxisLabelY := TGLFlatText(_GZORootAxisLabel.AddNewChild(TGLFlatText));
  592. with _GZOAxisLabelY do
  593. begin
  594. ModulateColor.Color := clrLime;
  595. Alignment := TaCenter;
  596. Layout := TlCenter;
  597. Options := Options + [FtoTwoSided];
  598. Position.Y := 1.5;
  599. Scale.X := 0.02;
  600. Scale.Y := 0.02;
  601. Text := 'Y';
  602. end;
  603. _GZOAxisLabelZ := TGLFlatText(_GZORootAxisLabel.AddNewChild(TGLFlatText));
  604. with _GZOAxisLabelZ do
  605. begin
  606. ModulateColor.Color := ClrBlue;
  607. Alignment := TaCenter;
  608. Layout := TlCenter;
  609. Options := Options + [FtoTwoSided];
  610. Position.Z := 1.5;
  611. Scale.X := 0.02;
  612. Scale.Y := 0.02;
  613. Text := 'Z';
  614. end;
  615. _GZOVisibleInfoLabels :=
  616. TGLFlatText(_GZORootVisibleInfoLabels.AddNewChild(TGLFlatText));
  617. with _GZOVisibleInfoLabels do
  618. begin
  619. ModulateColor.Color := clrYellow;
  620. Alignment := TaCenter;
  621. Layout := TlCenter;
  622. Options := Options + [FtoTwoSided];
  623. Position.Y := 1.8;
  624. Position.X := 0;
  625. Scale.X := 0.01;
  626. Scale.Y := 0.01;
  627. Text := '';
  628. end;
  629. DglEnable := TGLDirectOpenGL(_GZORootLines.AddNewChild(TGLDirectOpenGL));
  630. DglEnable.OnRender := DirectGlEnable;
  631. DgtEnable := TGLDirectOpenGL(_GZORootTorus.AddNewChild(TGLDirectOpenGL));
  632. DgtEnable.OnRender := DirectGlEnable;
  633. DgcEnable := TGLDirectOpenGL(_GZORootCubes.AddNewChild(TGLDirectOpenGL));
  634. DgcEnable.OnRender := DirectGlEnable;
  635. DglaEnable := TGLDirectOpenGL(_GZORootAxisLabel.AddNewChild(TGLDirectOpenGL));
  636. DglaEnable.OnRender := DirectGlEnable;
  637. DgliEnable := TGLDirectOpenGL(_GZORootVisibleInfoLabels.AddNewChild
  638. (TGLDirectOpenGL));
  639. DgliEnable.OnRender := DirectGlEnable;
  640. _GZObaseGizmo.Visible := False;
  641. FGizmoElements := FGizmoElements + [GeMove, GeRotate, GeScale, GeAxisLabel,
  642. GeObjectInfos, GeBoundingBox];
  643. FVisibleVisibleInfoLabels := FVisibleVisibleInfoLabels +
  644. [VliName, VliOperation, VliCoords];
  645. AutoZoom := True;
  646. AutoZoomFactor := 5.0;
  647. ZoomFactor := 0.35;
  648. ForceOperation := False;
  649. ForceAxis := False;
  650. ForceUniformScale := False;
  651. Enabled := True;
  652. FNoZWrite := True;
  653. FExcludeObjectsList := TStringList.Create;
  654. end;
  655. destructor TGLGizmo.Destroy;
  656. begin
  657. if Assigned(FRootGizmo) then
  658. FRootGizmo.DeleteChildren
  659. else
  660. begin
  661. _GZOBaseGizmo.DeleteChildren;
  662. _GZOBaseGizmo.Free;
  663. end;
  664. FBoundingBoxColor.Free;
  665. FSelectedColor.Free;
  666. FVisibleInfoLabelsColor.Free;
  667. PickableObjectsWithRayCast.Free;
  668. FExcludeObjectsList.Free;
  669. ClearInternalRaycastHitData;
  670. FInternalRaycastHitData.Free;
  671. // FUndoHistory has to be nil before Notification() is called.
  672. FreeAndNil(FUndoHistory);
  673. inherited Destroy;
  674. end;
  675. procedure TGLGizmo.SetVisible(const AValue: Boolean);
  676. begin
  677. _GZObaseGizmo.Visible := AValue;
  678. end;
  679. procedure TGLGizmo.SetGizmoElements(const AValue: TGLGizmoElements);
  680. begin
  681. if AValue <> FGizmoElements then
  682. begin
  683. FGizmoElements := AValue;
  684. _GZORootLines.Visible := GeMove in FGizmoElements;
  685. _GZORootTorus.Visible := GeRotate in FGizmoElements;
  686. _GZORootCubes.Visible := GeScale in FGizmoElements;
  687. _GZORootAxisLabel.Visible := GeAxisLabel in FGizmoElements;
  688. _GZORootVisibleInfoLabels.Visible := GeObjectInfos in FGizmoElements;
  689. _GZOBoundingcube.Visible := GeBoundingBox in FGizmoElements;
  690. end;
  691. end;
  692. procedure TGLGizmo.SetBoundingBoxColor(const AValue: TGLColor);
  693. begin
  694. // Bug Here New Color is not Updated
  695. if AValue <> FBoundingBoxColor then
  696. begin
  697. FBoundingBoxColor.Color := AValue.Color;
  698. with _GZOBoundingcube.Material do
  699. begin
  700. with FrontProperties do
  701. begin
  702. Diffuse.Color := FBoundingBoxColor.Color;
  703. Ambient.Color := FBoundingBoxColor.Color;
  704. Emission.Color := FBoundingBoxColor.Color;
  705. end;
  706. with BackProperties do
  707. begin
  708. Diffuse.Color := FBoundingBoxColor.Color;
  709. Ambient.Color := FBoundingBoxColor.Color;
  710. Emission.Color := FBoundingBoxColor.Color;
  711. end;
  712. end;
  713. FBoundingBoxColorChanged := True;
  714. end;
  715. end;
  716. procedure TGLGizmo.SetSelectedColor(const AValue: TGLColor);
  717. begin
  718. if AValue <> FSelectedColor then
  719. begin
  720. FSelectedColor.Color := AValue.Color;
  721. end;
  722. end;
  723. procedure TGLGizmo.SetVisibleInfoLabelsColor(const AValue: TGLColor);
  724. begin
  725. // Bug Here New Color is not Updated
  726. if AValue <> FSelectedColor then
  727. begin
  728. FVisibleInfoLabelsColor.Color := AValue.Color;
  729. _GZOVisibleInfoLabels.ModulateColor.Color := AValue.Color;
  730. FVisibleInfoLabelsColorChanged := True;
  731. end;
  732. end;
  733. procedure TGLGizmo.SeTGLGizmoVisibleInfoLabels(const AValue
  734. : TGLGizmoVisibleInfoLabels);
  735. begin
  736. if AValue <> FVisibleVisibleInfoLabels then
  737. begin
  738. FVisibleVisibleInfoLabels := AValue;
  739. if not(CsDesigning in ComponentState) then
  740. UpdateGizmo;
  741. end;
  742. end;
  743. procedure TGLGizmo.UndoAdd(const AObject: TGLCustomSceneObject);
  744. begin
  745. if AObject <> nil then
  746. begin
  747. FUndoHistory.Add.AssignFromObject(AObject)
  748. end;
  749. end;
  750. procedure TGLGizmo.SetRootGizmo(const AValue: TGLBaseSceneObject);
  751. begin
  752. if FRootGizmo <> AValue then
  753. begin
  754. if FRootGizmo <> nil then
  755. FRootGizmo.RemoveFreeNotification(Self);
  756. FRootGizmo := AValue;
  757. if FRootGizmo <> nil then
  758. FRootGizmo.FreeNotification(Self);
  759. _GZObaseGizmo.MoveTo(AValue);
  760. end;
  761. end;
  762. procedure TGLGizmo.SetExcludeObjectsList(const AValue: TStrings);
  763. begin
  764. FExcludeObjectsList.Clear;
  765. FExcludeObjectsList.AddStrings(AValue);
  766. end;
  767. procedure TGLGizmo.SetGLGizmoThickness(const Value: Single);
  768. var
  769. Thk: Single;
  770. begin
  771. if FGizmoThickness <> Value then
  772. begin
  773. Thk := MaxInteger(1, Round(3 * Value));
  774. _GZOlinex.LineWidth := Thk;
  775. _GZOliney.LineWidth := Thk;
  776. _GZOlinez.LineWidth := Thk;
  777. _GZOplaneXY.LineWidth := Thk;
  778. _GZOplaneXZ.LineWidth := Thk;
  779. _GZOplaneYZ.LineWidth := Thk;
  780. _GZOTorusX.MinorRadius := 0.03 * Value;
  781. _GZOTorusY.MinorRadius := 0.03 * Value;
  782. _GZOTorusZ.MinorRadius := 0.03 * Value;
  783. with _GZOCubeX do
  784. begin
  785. CubeDepth := 0.1 * Value;
  786. CubeHeight := 0.1 * Value;
  787. CubeWidth := 0.1 * Value;
  788. end;
  789. with _GZOCubeY do
  790. begin
  791. CubeDepth := 0.1 * Value;
  792. CubeHeight := 0.1 * Value;
  793. CubeWidth := 0.1 * Value;
  794. end;
  795. with _GZOCubeZ do
  796. begin
  797. CubeDepth := 0.1 * Value;
  798. CubeHeight := 0.1 * Value;
  799. CubeWidth := 0.1 * Value;
  800. end;
  801. FGizmoThickness := Value;
  802. end;
  803. end;
  804. // ------------------------------------------------------------------------------
  805. procedure TGLGizmo.DirectGlDisable(Sender: TObject;
  806. var Rci: TGLRenderContextInfo);
  807. begin
  808. if FNoZWrite then
  809. Rci.GLStates.Disable(StDepthTest);
  810. end;
  811. procedure TGLGizmo.SetLabelFont(const Value: TGLCustomBitmapFont);
  812. begin
  813. if FLabelFont <> Value then
  814. begin
  815. if FLabelFont <> nil then
  816. FLabelFont.RemoveFreeNotification(Self);
  817. FLabelFont := Value;
  818. if FLabelFont <> nil then
  819. FLabelFont.FreeNotification(Self);
  820. _GZOAxisLabelX.BitmapFont := Value;
  821. _GZOAxisLabelY.BitmapFont := Value;
  822. _GZOAxisLabelZ.BitmapFont := Value;
  823. _GZOVisibleInfoLabels.BitmapFont := Value;
  824. end;
  825. end;
  826. procedure TGLGizmo.DirectGlEnable(Sender: TObject; var Rci: TGLRenderContextInfo);
  827. begin
  828. if FNoZWrite then
  829. Rci.GLStates.Enable(StDepthTest);
  830. end;
  831. function TGLGizmo.GetPickedObjectPoint(const Obj: TGLBaseSceneObject): TGLVector;
  832. var
  833. T: Integer;
  834. R: TGLGizmoRayCastHitData;
  835. begin
  836. for T := 0 to FInternalRaycastHitData.Count - 1 do
  837. begin
  838. R := TGLGizmoRayCastHitData(FInternalRaycastHitData[T]);
  839. if R.Obj = Obj then
  840. begin
  841. Result := R.Point;
  842. Break;
  843. end;
  844. end;
  845. end;
  846. function TGLGizmo.InternalGetPickedObjects(const X1, Y1, X2, Y2: Integer;
  847. const GuessCount: Integer): TGLPickList;
  848. var
  849. T: Integer;
  850. RayStart, RayVector, IPoint, INormal: TGLVector;
  851. O: TGLBaseSceneObject;
  852. Dist: Single;
  853. HitData: TGLGizmoRayCastHitData;
  854. procedure AddGizmosToPicklListRecurse(const Root: TGLBaseSceneObject);
  855. var
  856. U: Integer;
  857. begin
  858. for U := 0 to Root.Count - 1 do
  859. begin
  860. if ((Root[U] is TGLGizmoPickTorus) or (Root[U] is TGLGizmoPickCube)) then
  861. PickableObjectsWithRayCast.Add(Root[U]);
  862. AddGizmosToPicklListRecurse(Root[U]);
  863. end;
  864. end;
  865. begin
  866. case FPickMode of
  867. PmGetPickedObjects:
  868. begin
  869. Result := Viewer.Buffer.GetPickedObjects(Rect(X1, Y1, X2, Y2),
  870. GuessCount);
  871. end;
  872. PmRayCast:
  873. begin
  874. Result := TGLPickList.Create(PsMinDepth);
  875. ClearInternalRaycastHitData;
  876. SetVector(RayStart, Viewer.Camera.AbsolutePosition);
  877. SetVector(RayVector, Viewer.Buffer.ScreenToVector
  878. (AffineVectorMake((X1 + X2) * 0.5,
  879. Viewer.Height - ((Y1 + Y2) * 0.5), 0)));
  880. NormalizeVector(RayVector);
  881. // Add gizmos
  882. if (RootGizmo <> nil) and (SelectedObj <> nil) then
  883. AddGizmosToPicklListRecurse(RootGizmo);
  884. // pick
  885. for T := 0 to PickableObjectsWithRayCast.Count - 1 do
  886. begin
  887. O := TGLBaseSceneObject(PickableObjectsWithRayCast[T]);
  888. if (O.RayCastIntersect(RayStart, RayVector, @IPoint, @INormal)) and
  889. (VectorDotProduct(RayVector, INormal) < 0) then
  890. begin
  891. try
  892. Dist := VectorLength(VectorSubtract(IPoint, RayStart));
  893. Result.AddHit(O, nil, Dist, 0);
  894. HitData := TGLGizmoRayCastHitData.Create;
  895. HitData.Obj := O;
  896. MakeVector(HitData.Point, IPoint);
  897. FInternalRaycastHitData.Add(HitData);
  898. except
  899. //
  900. end;
  901. end;
  902. end;
  903. end;
  904. else
  905. begin
  906. Result := nil;
  907. Assert(False, strErrorEx + strUnknownType);
  908. end;
  909. end;
  910. end;
  911. procedure TGLGizmo.Loaded;
  912. begin
  913. inherited;
  914. SeTGLGizmoThickness(GizmoThickness);
  915. end;
  916. // ------------------------------------------------------------------------------
  917. procedure TGLGizmo.UpdateVisibleInfoLabels;
  918. var
  919. T: string;
  920. X, Y, Z: Single;
  921. begin
  922. T := '';
  923. if not(Assigned(SelectedObj)) then
  924. Exit;
  925. if VliName in FVisibleVisibleInfoLabels then
  926. T := SelectedObj.Name;
  927. if VliOperation in FVisibleVisibleInfoLabels then
  928. begin
  929. if (Operation <> GopNone) then
  930. begin
  931. if Length(T) > 0 then
  932. T := T + ' - ';
  933. case Operation of
  934. GopMove:
  935. T := T + 'Move';
  936. GopRotate:
  937. T := T + 'Rotate';
  938. GopScale:
  939. T := T + 'Scale';
  940. end;
  941. end;
  942. end;
  943. if VliCoords in FVisibleVisibleInfoLabels then
  944. begin
  945. if (Operation <> GopNone) then
  946. begin
  947. if Length(T) > 0 then
  948. T := T + ' - ';
  949. case Operation of
  950. GopMove:
  951. begin
  952. X := SelectedObj.Position.X;
  953. Y := SelectedObj.Position.Y;
  954. Z := SelectedObj.Position.Z;
  955. T := T + 'X : ' + Format('%2.3f', [X]);
  956. T := T + ' Y : ' + Format('%2.3f', [Y]);
  957. T := T + ' Z : ' + Format('%2.3f', [Z]);
  958. end;
  959. GopRotate:
  960. begin
  961. X := SelectedObj.Rotation.X;
  962. Y := SelectedObj.Rotation.Y;
  963. Z := SelectedObj.Rotation.Z;
  964. T := T + 'X : ' + Format('%2.3f', [X]);
  965. T := T + ' Y : ' + Format('%2.3f', [Y]);
  966. T := T + ' Z : ' + Format('%2.3f', [Z]);
  967. end;
  968. GopScale:
  969. begin
  970. X := SelectedObj.Scale.X;
  971. Y := SelectedObj.Scale.Y;
  972. Z := SelectedObj.Scale.Z;
  973. T := T + 'X : ' + Format('%2.3f', [X]);
  974. T := T + ' Y : ' + Format('%2.3f', [Y]);
  975. T := T + ' Z : ' + Format('%2.3f', [Z]);
  976. end;
  977. end;
  978. end;
  979. end;
  980. _GZOVisibleInfoLabels.Text := T;
  981. _GZOVisibleInfoLabels.StructureChanged;
  982. end;
  983. // ------------------------------------------------------------------------------
  984. function TGLGizmo.CheckObjectInExcludeList
  985. (const Obj: TGLBaseSceneObject): Boolean;
  986. var
  987. I: Integer;
  988. begin
  989. Result := False;
  990. if FExcludeObjects then
  991. begin
  992. for I := 0 to FExcludeObjectsList.Count - 1 do
  993. begin
  994. if UpperCase(Obj.Name) = UpperCase(FExcludeObjectsList[I]) then
  995. begin
  996. Result := True;
  997. Exit;
  998. end;
  999. end;
  1000. end;
  1001. end;
  1002. function TGLGizmo.MouseWorldPos(const X, Y: Integer): TGLVector;
  1003. var
  1004. V: TGLVector;
  1005. InvertedY: Integer;
  1006. begin
  1007. InvertedY := Viewer.Height - Y;
  1008. if Assigned(SelectedObj) then
  1009. begin
  1010. SetVector(V, X, InvertedY, 0);
  1011. case SelAxis of
  1012. GaX:
  1013. if not Viewer.Buffer.ScreenVectorIntersectWithPlaneXZ(V,
  1014. SelectedObj.AbsolutePosition.Y, Result) then
  1015. MakeVector(Result, X / 5, 0, 0);
  1016. GaY:
  1017. if not Viewer.Buffer.ScreenVectorIntersectWithPlaneYZ(V,
  1018. SelectedObj.AbsolutePosition.X, Result) then
  1019. MakeVector(Result, 0, InvertedY / 5, 0);
  1020. GaZ:
  1021. if not Viewer.Buffer.ScreenVectorIntersectWithPlaneYZ(V,
  1022. SelectedObj.AbsolutePosition.X, Result) then
  1023. MakeVector(Result, 0, 0, -InvertedY / 5);
  1024. GaXY:
  1025. begin
  1026. Viewer.Buffer.ScreenVectorIntersectWithPlaneXY(V,
  1027. SelectedObj.AbsolutePosition.Z, Result);
  1028. end;
  1029. GaXZ:
  1030. begin
  1031. Viewer.Buffer.ScreenVectorIntersectWithPlaneXZ(V,
  1032. SelectedObj.AbsolutePosition.Y, Result);
  1033. end;
  1034. GaYZ:
  1035. begin
  1036. Viewer.Buffer.ScreenVectorIntersectWithPlaneYZ(V,
  1037. SelectedObj.AbsolutePosition.X, Result);
  1038. end;
  1039. end;
  1040. end
  1041. else
  1042. SetVector(Result, NullVector);
  1043. end;
  1044. procedure TGLGizmo.ViewerMouseMove(const X, Y: Integer);
  1045. var
  1046. PickList: TGLPickList;
  1047. MousePos: TGLVector;
  1048. function IndexOf(Obj: TGLBaseSceneObject): Integer;
  1049. var
  1050. I: Integer;
  1051. begin
  1052. Result := -1;
  1053. for I := 0 to PickList.Count - 1 do
  1054. if PickList.Hit[I] = Obj then
  1055. begin
  1056. Result := I;
  1057. Break;
  1058. end;
  1059. end;
  1060. function LightLine(const Line: TGLLines; const Dark: TGLVector;
  1061. const Axis: TGLGizmoAxis; AlterStyle: Boolean = False): Boolean;
  1062. var
  1063. PickObj: TGLBaseSceneObject;
  1064. begin
  1065. case FPickMode of
  1066. PmGetPickedObjects:
  1067. PickObj := Line;
  1068. PmRayCast:
  1069. PickObj := Line;
  1070. else
  1071. begin
  1072. PickObj := nil;
  1073. Assert(False, strErrorEx + strUnknownType);
  1074. end;
  1075. end;
  1076. if IndexOf(PickObj) > -1 then
  1077. begin
  1078. Line.LineColor.Color := FSelectedColor.Color;
  1079. if not(FForceOperation) then
  1080. if Operation <> GopMove then
  1081. Operation := GopMove;
  1082. Line.Options := [];
  1083. if not(FForceAxis) then
  1084. SelAxis := Axis;
  1085. Result := True;
  1086. end
  1087. else
  1088. begin
  1089. Line.LineColor.Color := Dark;
  1090. if not(FForceOperation) then
  1091. Operation := GopNone;
  1092. if AlterStyle then
  1093. Line.Options := [LoUseNodeColorForLines];
  1094. if not(FForceAxis) then
  1095. if SelAxis = Axis then
  1096. SelAxis := GaNone;
  1097. Result := False;
  1098. end;
  1099. end;
  1100. function LightTorus(const Torus: TGLGizmoPickTorus; const Dark: TGLVector;
  1101. const Axis: TGLGizmoAxis; AlterStyle: Boolean = False): Boolean;
  1102. begin
  1103. if IndexOf(Torus) > -1 then
  1104. begin
  1105. Torus.Material.FrontProperties.Emission.Color := FSelectedColor.Color;
  1106. if not(FForceOperation) then
  1107. if Operation <> GopRotate then
  1108. Operation := GopRotate;
  1109. if not(FForceAxis) then
  1110. SelAxis := Axis;
  1111. Result := True;
  1112. end
  1113. else
  1114. begin
  1115. Torus.Material.FrontProperties.Emission.Color := Dark;
  1116. if not(FForceOperation) then
  1117. Operation := GopNone;
  1118. if not(FForceAxis) then
  1119. if SelAxis = Axis then
  1120. SelAxis := GaNone;
  1121. Result := False;
  1122. end;
  1123. end;
  1124. function LightCube(const Cube: TGLCube; const Dark: TGLVector;
  1125. const Axis: TGLGizmoAxis; AlterStyle: Boolean = False): Boolean;
  1126. begin
  1127. if IndexOf(Cube) > -1 then
  1128. begin
  1129. Cube.Material.FrontProperties.Emission.Color := FSelectedColor.Color;
  1130. if not(FForceOperation) then
  1131. if Operation <> GopScale then
  1132. Operation := GopScale;
  1133. if not(FForceAxis) then
  1134. SelAxis := Axis;
  1135. Result := True;
  1136. end
  1137. else
  1138. begin
  1139. Cube.Material.FrontProperties.Emission.Color := Dark;
  1140. if not(FForceOperation) then
  1141. Operation := GopNone;
  1142. if not(FForceAxis) then
  1143. if SelAxis = Axis then
  1144. SelAxis := GaNone;
  1145. Result := False;
  1146. end;
  1147. end;
  1148. procedure OpeMove(MousePos: TGLVector);
  1149. var
  1150. Vec1, Vec2: TGLVector;
  1151. QuantizedMousePos, QuantizedMousePos2: TGLVector;
  1152. T: Integer;
  1153. begin
  1154. for T := 0 to 3 do
  1155. begin
  1156. QuantizedMousePos.V[T] := (Round(MousePos.V[T] / MoveCoef)) * MoveCoef;
  1157. QuantizedMousePos2.V[T] := (Round(LastMousePos.V[T] / MoveCoef)) * MoveCoef;
  1158. end;
  1159. case SelAxis of
  1160. GaX:
  1161. begin
  1162. MakeVector(Vec1, QuantizedMousePos.X, 0, 0);
  1163. MakeVector(Vec2, QuantizedMousePos2.X, 0, 0);
  1164. end;
  1165. GaY:
  1166. begin
  1167. MakeVector(Vec1, 0, QuantizedMousePos.Y, 0);
  1168. MakeVector(Vec2, 0, QuantizedMousePos2.Y, 0);
  1169. end;
  1170. GaZ:
  1171. begin
  1172. MakeVector(Vec1, 0, 0, QuantizedMousePos.Z);
  1173. MakeVector(Vec2, 0, 0, QuantizedMousePos2.Z);
  1174. end;
  1175. else
  1176. begin
  1177. Vec1 := QuantizedMousePos;
  1178. Vec2 := QuantizedMousePos2;
  1179. end;
  1180. end;
  1181. SubtractVector(Vec1, Vec2);
  1182. if Assigned(OnBeforeUpdate) then
  1183. OnBeforeUpdate(Self, SelectedObj, SelAxis, Operation, Vec1);
  1184. Vec1 := SelectedObj.Parent.AbsoluteToLocal(Vec1);
  1185. if (VectorLength(Vec1) > 0) then // prevents NAN problems
  1186. begin
  1187. SelectedObj.Position.Translate(Vec1);
  1188. end;
  1189. end;
  1190. procedure OpeRotate(const X, Y: Integer);
  1191. var
  1192. Vec1: TGLVector;
  1193. RotV: TAffineVector;
  1194. Pmat: TGLMatrix;
  1195. begin
  1196. Vec1.X := 0;
  1197. Vec1.Y := 0;
  1198. if Abs(X - Rx) >= RotationCoef then
  1199. begin
  1200. if RotationCoef > 1 then
  1201. Vec1.X := RotationCoef * (Round((X - Rx) / (RotationCoef)))
  1202. else
  1203. Vec1.X := RotationCoef * (X - Rx);
  1204. Rx := X;
  1205. end;
  1206. if Abs(Y - Ry) >= RotationCoef then
  1207. begin
  1208. if RotationCoef > 1 then
  1209. Vec1.Y := RotationCoef * (Round((Y - Ry) / (RotationCoef)))
  1210. else
  1211. Vec1.Y := RotationCoef * (Y - Ry);
  1212. Ry := Y;
  1213. end;
  1214. Vec1.Z := 0;
  1215. Vec1.W := 0;
  1216. if Assigned(OnBeforeUpdate) then
  1217. OnBeforeUpdate(Self, SelectedObj, SelAxis, Operation, Vec1);
  1218. Pmat := SelectedObj.Parent.InvAbsoluteMatrix;
  1219. SetVector(Pmat.V[3], NullHmgPoint);
  1220. case SelAxis of
  1221. GaX:
  1222. begin
  1223. RotV := VectorTransform(XVector, Pmat);
  1224. RotateAroundArbitraryAxis(SelectedObj, RotV,
  1225. AffineVectorMake(SelectedObj.Position.AsVector), Vec1.Y);
  1226. end;
  1227. GaY:
  1228. begin
  1229. RotV := VectorTransform(YVector, Pmat);
  1230. RotateAroundArbitraryAxis(SelectedObj, RotV,
  1231. AffineVectorMake(SelectedObj.Position.AsVector), Vec1.X);
  1232. end;
  1233. GaZ:
  1234. begin
  1235. RotV := VectorTransform(ZVector, Pmat);
  1236. RotateAroundArbitraryAxis(SelectedObj, RotV,
  1237. AffineVectorMake(SelectedObj.Position.AsVector), Vec1.Y);
  1238. end;
  1239. GaXY:
  1240. begin
  1241. RotV := VectorTransform(XVector, Pmat);
  1242. RotateAroundArbitraryAxis(SelectedObj, RotV,
  1243. AffineVectorMake(SelectedObj.Position.AsVector), Vec1.Y);
  1244. RotV := VectorTransform(YVector, Pmat);
  1245. RotateAroundArbitraryAxis(SelectedObj, RotV,
  1246. AffineVectorMake(SelectedObj.Position.AsVector), Vec1.X);
  1247. end;
  1248. GaXZ:
  1249. begin
  1250. RotV := VectorTransform(XVector, Pmat);
  1251. RotateAroundArbitraryAxis(SelectedObj, RotV,
  1252. AffineVectorMake(SelectedObj.Position.AsVector), Vec1.Y);
  1253. RotV := VectorTransform(ZVector, Pmat);
  1254. RotateAroundArbitraryAxis(SelectedObj, RotV,
  1255. AffineVectorMake(SelectedObj.Position.AsVector), Vec1.X);
  1256. end;
  1257. GaYZ:
  1258. begin
  1259. RotV := VectorTransform(YVector, Pmat);
  1260. RotateAroundArbitraryAxis(SelectedObj, RotV,
  1261. AffineVectorMake(SelectedObj.Position.AsVector), Vec1.Y);
  1262. RotV := VectorTransform(ZVector, Pmat);
  1263. RotateAroundArbitraryAxis(SelectedObj, RotV,
  1264. AffineVectorMake(SelectedObj.Position.AsVector), Vec1.X);
  1265. end;
  1266. end;
  1267. end;
  1268. procedure OpeScale(const MousePos: TGLVector);
  1269. var
  1270. Vec1, Vec2: TGLVector;
  1271. QuantizedMousePos, QuantizedMousePos2: TGLVector;
  1272. T: Integer;
  1273. begin
  1274. for T := 0 to 3 do
  1275. begin
  1276. QuantizedMousePos.V[T] := (Round(MousePos.V[T] / ScaleCoef)) * FScaleCoef;
  1277. QuantizedMousePos2.V[T] := (Round(LastMousePos.V[T] / FScaleCoef)) *
  1278. FScaleCoef;
  1279. end;
  1280. case SelAxis of
  1281. GaX:
  1282. begin
  1283. if FForceUniformScale then
  1284. begin
  1285. MakeVector(Vec1, QuantizedMousePos.X, QuantizedMousePos.X,
  1286. QuantizedMousePos.X);
  1287. MakeVector(Vec2, QuantizedMousePos2.X, QuantizedMousePos2.X,
  1288. QuantizedMousePos2.X);
  1289. end
  1290. else
  1291. begin
  1292. MakeVector(Vec1, QuantizedMousePos.X, 0, 0);
  1293. MakeVector(Vec2, QuantizedMousePos2.X, 0, 0);
  1294. end;
  1295. end;
  1296. GaY:
  1297. begin
  1298. if FForceUniformScale then
  1299. begin
  1300. MakeVector(Vec1, QuantizedMousePos.Y, QuantizedMousePos.Y,
  1301. QuantizedMousePos.Y);
  1302. MakeVector(Vec2, QuantizedMousePos2.Y, QuantizedMousePos2.Y,
  1303. QuantizedMousePos2.Y);
  1304. end
  1305. else
  1306. begin
  1307. MakeVector(Vec1, 0, QuantizedMousePos.Y, 0);
  1308. MakeVector(Vec2, 0, QuantizedMousePos2.Y, 0);
  1309. end;
  1310. end;
  1311. GaZ:
  1312. begin
  1313. if FForceUniformScale then
  1314. begin
  1315. MakeVector(Vec1, QuantizedMousePos.Z, QuantizedMousePos.Z,
  1316. QuantizedMousePos.Z);
  1317. MakeVector(Vec2, QuantizedMousePos2.Z, QuantizedMousePos2.Z,
  1318. QuantizedMousePos2.Z);
  1319. end
  1320. else
  1321. begin
  1322. MakeVector(Vec1, 0, 0, QuantizedMousePos.Z);
  1323. MakeVector(Vec2, 0, 0, QuantizedMousePos2.Z);
  1324. end;
  1325. end;
  1326. else
  1327. begin
  1328. Vec1 := QuantizedMousePos;
  1329. Vec2 := QuantizedMousePos2;
  1330. end;
  1331. end;
  1332. SubtractVector(Vec1, Vec2);
  1333. if Assigned(OnBeforeUpdate) then
  1334. OnBeforeUpdate(Self, SelectedObj, SelAxis, Operation, Vec1);
  1335. SelectedObj.Scale.Translate(Vec1);
  1336. UpdateGizmo;
  1337. end;
  1338. begin
  1339. if not Enabled then
  1340. Exit;
  1341. if Assigned(SelectedObj) and (SelAxis <> GaNone) and Moving then
  1342. begin
  1343. MousePos := MouseWorldPos(X, Y);
  1344. // moving object...
  1345. if Operation = GopMove then
  1346. begin
  1347. // FLastOperation = gopMove;
  1348. OpeMove(MousePos);
  1349. end
  1350. else if Operation = GopRotate then
  1351. begin
  1352. // FLastOperation = gopRotate;
  1353. OpeRotate(X, Y);
  1354. end
  1355. else if Operation = GopScale then
  1356. begin
  1357. // FLastOperation = gopScale;
  1358. OpeScale(MousePos);
  1359. end;
  1360. UpdateGizmo;
  1361. Mx := X;
  1362. My := Y;
  1363. LastMousePos := MousePos;
  1364. Exit;
  1365. end;
  1366. Assert(FViewer <> nil, 'Viewer not Assigned to gizmo');
  1367. Picklist := InternalGetPickedObjects(X - 1, Y - 1, X + 1, Y + 1, 8);
  1368. // Viewer.buffer.GetPickedObjects(rect(x-1, y-1, x+1, y+1), 8);
  1369. if not LightLine(_GZOlinex, ClrRed, GaX) and not LightLine(_GZOliney, ClrLime,
  1370. GaY) and not LightLine(_GZOlinez, ClrBlue, GaZ) and
  1371. not LightTorus(_GZOTorusX, ClrRed, GaX) and
  1372. not LightTorus(_GZOTorusY, ClrLime, GaY) and
  1373. not LightTorus(_GZOTorusz, ClrBlue, GaZ) and
  1374. not LightCube(_GZOCubeX, ClrRed, GaX) and not LightCube(_GZOCubeY, ClrLime,
  1375. GaY) and not LightCube(_GZOCubeZ, ClrBlue, GaZ) and
  1376. not LightLine(_GZOplaneXY, ClrWhite, GaXY, True) and
  1377. not LightLine(_GZOplaneXZ, ClrWhite, GaXZ, True) and
  1378. not LightLine(_GZOplaneYZ, ClrWhite, GaYZ, True) then
  1379. begin
  1380. if not(FForceAxis) then
  1381. SelAxis := GaNone;
  1382. if not(FForceOperation) then
  1383. Operation := GopNone;
  1384. end;
  1385. Picklist.Free;
  1386. Mx := X;
  1387. My := Y;
  1388. end;
  1389. procedure TGLGizmo.ViewerMouseDown(const X, Y: Integer);
  1390. var
  1391. Pick: TGLPickList;
  1392. I: Integer;
  1393. Accept: Boolean;
  1394. Dimensions: TGLVector;
  1395. GotPick: Boolean;
  1396. PickedObj: TGLBaseSceneObject;
  1397. begin
  1398. Mx := X;
  1399. My := Y;
  1400. Rx := X;
  1401. Ry := Y;
  1402. if not Enabled then
  1403. Exit;
  1404. Pick := InternalGetPickedObjects(X - 1, Y - 1, X + 1, Y + 1);
  1405. // Viewer.Buffer.GetPickedObjects(rect(x-1, y-1, x+1, y+1));
  1406. GotPick := False;
  1407. Accept := False;
  1408. case FPickMode of
  1409. PmGetPickedObjects:
  1410. begin
  1411. // primeiro, ver se é uma das linhas/planos
  1412. for I := 0 to Pick.Count - 1 do
  1413. if (_GZOrootLines.IndexOfChild(TGLBaseSceneObject(Pick.Hit[I])) > -1)
  1414. or (_GZOrootTorus.IndexOfChild(TGLBaseSceneObject(Pick.Hit[I])) >
  1415. -1) or (_GZOrootCubes.IndexOfChild(TGLBaseSceneObject(Pick.Hit[I]))
  1416. > -1) then
  1417. GotPick := True;
  1418. end;
  1419. PmRayCast:
  1420. begin
  1421. for I := 0 to Pick.Count - 1 do
  1422. begin
  1423. if (Pick.Hit[I] is TGLGizmoPickCube) or
  1424. (Pick.Hit[I] is TGLGizmoPickTorus) then
  1425. GotPick := True;
  1426. end;
  1427. end;
  1428. else
  1429. begin
  1430. Assert(False, strErrorEx + strUnknownType);
  1431. end;
  1432. end;
  1433. if not GotPick then
  1434. begin
  1435. for I := 0 to Pick.Count - 1 do
  1436. if (Pick.Hit[I] <> _GZOBoundingcube) and (Pick.Hit[I] <> _GZOAxisLabelX)
  1437. and (Pick.Hit[I] <> _GZOAxisLabelY) and (Pick.Hit[I] <> _GZOAxisLabelZ)
  1438. and (Pick.Hit[I] <> _GZOVisibleInfoLabels) and
  1439. not(CheckObjectInExcludeList(TGLBaseSceneObject(Pick.Hit[I]))) then
  1440. begin
  1441. Accept := True;
  1442. PickedObj := TGLBaseSceneObject(Pick.Hit[I]);
  1443. Dimensions := PickedObj.AxisAlignedDimensions;
  1444. if Assigned(OnBeforeSelect) then
  1445. OnBeforeSelect(Self, PickedObj, Accept, Dimensions);
  1446. Break;
  1447. end;
  1448. if Accept then
  1449. SetSelectedObj(PickedObj)
  1450. else
  1451. SetSelectedObj(nil);
  1452. end
  1453. else
  1454. UpdateVisibleInfoLabels();
  1455. Pick.Free;
  1456. Moving := True;
  1457. LastMousePos := MouseWorldPos(X, Y);
  1458. end;
  1459. procedure TGLGizmo.ViewerMouseUp(const X, Y: Integer);
  1460. begin
  1461. Moving := False;
  1462. end;
  1463. // ------------------------------------------------------------------------------
  1464. procedure TGLGizmo.UpdateGizmo;
  1465. var
  1466. D: Single;
  1467. begin
  1468. if SelectedObj = nil then
  1469. begin
  1470. _GZObaseGizmo.Visible := False;
  1471. Exit;
  1472. end;
  1473. _GZObaseGizmo.Position.AsVector := SelectedObj.AbsolutePosition;
  1474. if GeObjectInfos in FGizmoElements then
  1475. UpdateVisibleInfoLabels;
  1476. _GZOBoundingcube.SetMatrix(SelectedObj.AbsoluteMatrix);
  1477. _GZOBoundingcube.Position.SetPoint(0, 0, 0);
  1478. // We must Update Color Of the BoundingBox And VisibleInfoLabels Here
  1479. // If not Color is not Updated;
  1480. // if FBoundingBoxColorChanged then
  1481. // Begin
  1482. with _GZOBoundingcube.Material do
  1483. begin
  1484. with FrontProperties do
  1485. begin
  1486. Diffuse.Color := FBoundingBoxColor.Color;
  1487. Ambient.Color := FBoundingBoxColor.Color;
  1488. Emission.Color := FBoundingBoxColor.Color;
  1489. end;
  1490. with BackProperties do
  1491. begin
  1492. Diffuse.Color := FBoundingBoxColor.Color;
  1493. Ambient.Color := FBoundingBoxColor.Color;
  1494. Emission.Color := FBoundingBoxColor.Color;
  1495. end;
  1496. end;
  1497. // FBoundingBoxColorChanged:=False;
  1498. // End;
  1499. // If FVisibleInfoLabelsColorChanged then
  1500. // Begin
  1501. _GZOVisibleInfoLabels.ModulateColor.Color := FVisibleInfoLabelsColor.Color;
  1502. // FVisibleInfoLabelsColorChanged:=False;
  1503. // End;
  1504. ObjDimensions := SelectedObj.AxisAlignedDimensions;
  1505. _GZOBoundingcube.Scale.AsVector := VectorScale(ObjDimensions, 2);
  1506. Assert(Viewer <> nil, 'Viewer not Assigned to gizmo');
  1507. _GZOAxisLabelX.PointTo(Viewer.Camera.Position.AsVector,
  1508. Viewer.Camera.Up.AsVector);
  1509. _GZOAxisLabelX.StructureChanged;
  1510. _GZOAxisLabelY.PointTo(Viewer.Camera.Position.AsVector,
  1511. Viewer.Camera.Up.AsVector);
  1512. _GZOAxisLabelY.StructureChanged;
  1513. _GZOAxisLabelZ.PointTo(Viewer.Camera.Position.AsVector,
  1514. Viewer.Camera.Up.AsVector);
  1515. _GZOAxisLabelZ.StructureChanged;
  1516. _GZOVisibleInfoLabels.PointTo(Viewer.Camera.Position.AsVector,
  1517. Viewer.Camera.Up.AsVector);
  1518. _GZOVisibleInfoLabels.StructureChanged;
  1519. if FAutoZoom then
  1520. D := Viewer.Camera.DistanceTo(SelectedObj) / FAutoZoomFactor
  1521. else
  1522. D := FZoomFactor;
  1523. _GZOrootLines.Scale.AsVector := VectorMake(D, D, D);
  1524. _GZOrootTorus.Scale.AsVector := VectorMake(D, D, D);
  1525. _GZOrootCubes.Scale.AsVector := VectorMake(D, D, D);
  1526. _GZOrootAxisLabel.Scale.AsVector := VectorMake(D, D, D);
  1527. _GZOrootVisibleInfoLabels.Scale.AsVector := VectorMake(D, D, D);
  1528. end;
  1529. procedure TGLGizmo.UpdateGizmo(const NewDimensions: TGLVector);
  1530. begin
  1531. ObjDimensions := NewDimensions;
  1532. UpdateGizmo;
  1533. end;
  1534. procedure TGLGizmo.LooseSelection;
  1535. begin
  1536. SelectedObj := nil;
  1537. UpdateGizmo;
  1538. if Assigned(OnSelectionLost) then
  1539. OnSelectionLost(Self);
  1540. end;
  1541. procedure TGLGizmo.SetViewer(const Value: TGLSceneViewer);
  1542. begin
  1543. if FViewer <> Value then
  1544. begin
  1545. if FViewer <> nil then
  1546. FViewer.RemoveFreeNotification(Self);
  1547. FViewer := Value;
  1548. if FViewer <> nil then
  1549. FViewer.FreeNotification(Self);
  1550. end;
  1551. end;
  1552. procedure TGLGizmo.Notification(AComponent: TComponent; Operation: TOperation);
  1553. begin
  1554. inherited;
  1555. if Operation = OpRemove then
  1556. begin
  1557. if AComponent = FViewer then
  1558. FViewer := nil;
  1559. if AComponent = FRootGizmo then
  1560. FRootGizmo := nil;
  1561. end;
  1562. if FUndoHistory <> nil then
  1563. FUndoHistory.Notification(AComponent, Operation);
  1564. end;
  1565. procedure TGLGizmoUndoItem.AssignFromObject(const AObject
  1566. : TGLCustomSceneObject);
  1567. begin
  1568. SetEffectedObject(AObject);
  1569. SetOldMatrix(AObject.Matrix^);
  1570. if AObject is TGLFreeForm then
  1571. begin
  1572. FOldAutoScaling.Assign(TGLFreeForm(AObject).AutoScaling);
  1573. end;
  1574. FOldLibMaterialName := AObject.Material.LibMaterialName;
  1575. end;
  1576. constructor TGLGizmoUndoItem.Create(AOwner: TCollection);
  1577. begin
  1578. inherited;
  1579. FOldAutoScaling := TGLCoordinates.CreateInitialized(Self,
  1580. NullHmgVector, CsPoint);
  1581. end;
  1582. destructor TGLGizmoUndoItem.Destroy;
  1583. begin
  1584. FOldAutoScaling.Free;
  1585. inherited;
  1586. end;
  1587. procedure TGLGizmoUndoItem.DoUndo;
  1588. begin
  1589. FEffectedObject.SetMatrix(FOldMatr);
  1590. if FEffectedObject is TGLFreeForm then
  1591. TGLFreeForm(FEffectedObject).AutoScaling.Assign(FOldAutoScaling);
  1592. FEffectedObject.Material.LibMaterialName := FOldLibMaterialName;
  1593. end;
  1594. function TGLGizmoUndoItem.GetGizmo: TGLGizmo;
  1595. begin
  1596. if GetParent <> nil then
  1597. Result := GetPArent.GetParent
  1598. else
  1599. Result := nil;
  1600. end;
  1601. function TGLGizmoUndoItem.GetParent: TGLGizmoUndoCollection;
  1602. begin
  1603. Result := TGLGizmoUndoCollection(GetOwner);
  1604. end;
  1605. procedure TGLGizmoUndoItem.Notification(AComponent: TComponent;
  1606. Operation: TOperation);
  1607. begin
  1608. inherited;
  1609. if Operation = OpRemove then
  1610. begin
  1611. if AComponent = FEffectedObject then
  1612. FEffectedObject := nil;
  1613. end;
  1614. end;
  1615. procedure TGLGizmoUndoItem.SetEffectedObject(const Value: TGLCustomSceneObject);
  1616. begin
  1617. if FEffectedObject <> nil then
  1618. FEffectedObject.RemoveFreeNotification(GetGizmo);
  1619. FEffectedObject := Value;
  1620. if FEffectedObject <> nil then
  1621. FEffectedObject.FreeNotification(GetGizmo);
  1622. end;
  1623. procedure TGLGizmoUndoItem.SetOldAutoScaling(const Value: TGLCoordinates);
  1624. begin
  1625. FOldAutoScaling.Assign(Value);
  1626. end;
  1627. procedure TGLGizmoUndoItem.SetOldMatrix(const Value: TGLMatrix);
  1628. begin
  1629. FOldMatrix := Value;
  1630. end;
  1631. { TGLGizmoUndoCollection }
  1632. function TGLGizmoUndoCollection.Add: TGLGizmoUndoItem;
  1633. begin
  1634. Result := TGLGizmoUndoItem(inherited Add);
  1635. end;
  1636. function TGLGizmoUndoCollection.GetItems(const Index: Integer)
  1637. : TGLGizmoUndoItem;
  1638. begin
  1639. Result := TGLGizmoUndoItem(inherited GetItem(Index));
  1640. end;
  1641. function TGLGizmoUndoCollection.GetParent: TGLGizmo;
  1642. begin
  1643. Result := TGLGizmo(GetOwner);
  1644. end;
  1645. procedure TGLGizmoUndoCollection.Notification(AComponent: TComponent;
  1646. Operation: TOperation);
  1647. var
  1648. I: Integer;
  1649. begin
  1650. if Count <> 0 then
  1651. for I := 0 to Count - 1 do
  1652. GetItems(I).Notification(AComponent, Operation);
  1653. end;
  1654. procedure TGLGizmoUndoCollection.RemoveByObject(const AObject
  1655. : TGLCustomSceneObject);
  1656. var
  1657. I: Integer;
  1658. begin
  1659. for I := Count - 1 downto 0 do
  1660. if GetItems(I).FEffectedObject = AObject then
  1661. GetItems(I).Free;
  1662. end;
  1663. procedure TGLGizmoUndoCollection.SetItems(const Index: Integer;
  1664. const Value: TGLGizmoUndoItem);
  1665. begin
  1666. GetItems(Index).Assign(Value);
  1667. end;
  1668. procedure TGLGizmo.SetSelectedObj(const Value: TGLBaseSceneObject);
  1669. begin
  1670. if FSelectedObj <> Value then
  1671. begin
  1672. FSelectedObj := Value;
  1673. if Value <> nil then
  1674. begin
  1675. SetVisible(True);
  1676. UpdateVisibleInfoLabels();
  1677. UpdateGizmo();
  1678. end
  1679. else
  1680. begin
  1681. LooseSelection();
  1682. SetVisible(False);
  1683. end;
  1684. end;
  1685. end;
  1686. end.