GXS.Gizmo.pas 52 KB

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