123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869 |
- //
- // The multimedia graphics platform GLScene https://github.com/glscene
- //
- unit GLS.Gizmo;
- (*
- Invisible component for helping to Move, Rotate and Scale an Object
- under GLScene (usefull for an Editor).
- *)
- //
- // Original Header:
- //
- // ------------------------------------------------------------------------------
- // Unit : GLS.Gizmo RC 1.0
- // ------------------------------------------------------------------------------
- // Original Author : ??????? (GLS.Gizmo In an ODEEditor)
- // ------------------------------------------------------------------------------
- // Modified by : J.Delauney
- // Web Site : http://KheopsInteractive.cjb.net
- // EMail : [email protected]
- // Date : 08/05/2005
- //
- // Modified by : Marcus Oblak (8/3/2007)
- // - Corrected moving/rotating for children objects
- // - Better quantization for mouse operations (MoveCoef,RotationCoef)
- // - Added ScaleCoef
- // - Added GizmoThickness
- //
- // If you make some changes, please send your new version. Thanks
- // ------------------------------------------------------------------------------
- // Description :
- // Invisible component for helping to Move, Rotate and Scale an Object
- // under GLScene (usefull for an Editor)
- // ------------------------------------------------------------------------------
- // Features :
- // - Interaction When All Gizmo parts are Invisible
- // - Add "gpMoveGizmo and gpRotateGizmo" operations and use Like a "Pivot"
- // or use RootGizmo As "Pivot"
- // - Add Interactive Camera Movements
- // - Adding Extended Controls with Keys
- // - Maybe An Undo Function
- // - Others Ideas ???
- // ------------------------------------------------------------------------------
- // Bugs Known :
- // - When you change the BoundingBoxColor and LabelInfosColor
- // The New Color is not Updated immediately, only after a new Click
- // (see in UpdateGizmo, SetBoundingBoxColor
- // and SetLabelInfosColor Procedures)
- // - DaStr: Bounding Box is not always drawn correctly because it does not
- // use objects' BarryCenter. For Example, if you select Space Text.
- // ------------------------------------------------------------------------------
- interface
- {$I GLScene.inc}
- uses
- System.Classes,
- System.SysUtils,
- Vcl.StdCtrls,
- GLS.Scene,
- GLS.PersistentClasses,
- GLS.Color,
- GLS.Objects,
- GLS.VectorGeometry,
- GLS.Material,
- GLS.Strings,
- GLS.GeomObjects,
- GLS.BitmapFont,
- GLS.SceneViewer,
- GLS.VectorFileObjects,
- GLS.Coordinates,
- GLS.RenderContextInfo,
- GLS.State,
- GLS.Selection,
- GLS.VectorTypes;
- type
- TGLGizmoUndoCollection = class;
- TGLGizmo = class;
- TGLGizmoUndoItem = class(TCollectionItem)
- private
- FOldLibMaterialName: string;
- FOldAutoScaling: TGLCoordinates;
- FEffectedObject: TGLCustomSceneObject;
- FOldMatr: TGLMatrix;
- FOldMatrix: TGLMatrix;
- procedure SetEffectedObject(const Value: TGLCustomSceneObject);
- procedure SetOldAutoScaling(const Value: TGLCoordinates);
- procedure SetOldMatrix(const Value: TGLMatrix);
- protected
- procedure DoUndo; virtual;
- function GetParent: TGLGizmoUndoCollection;
- function GetGizmo: TGLGizmo;
- public
- constructor Create(AOwner: TCollection); override;
- destructor Destroy; override;
- procedure Notification(AComponent: TComponent;
- Operation: TOperation); virtual;
- procedure AssignFromObject(const AObject: TGLCustomSceneObject);
- // TODO: create a special type for Matrix.
- property OldMatrix: TGLMatrix read FOldMatrix write SetOldMatrix;
- published
- property EffectedObject: TGLCustomSceneObject read FEffectedObject
- write SetEffectedObject;
- property OldAutoScaling: TGLCoordinates read FOldAutoScaling
- write SetOldAutoScaling;
- property OldLibMaterialName: string read FOldLibMaterialName
- write FOldLibMaterialName;
- end;
- TGLGizmoUndoCollection = class(TOwnedCollection)
- private
- function GetItems(const Index: Integer): TGLGizmoUndoItem;
- procedure SetItems(const Index: Integer; const Value: TGLGizmoUndoItem);
- protected
- function GetParent: TGLGizmo;
- public
- procedure Notification(AComponent: TComponent; Operation: TOperation);
- procedure RemoveByObject(const AObject: TGLCustomSceneObject);
- function Add: TGLGizmoUndoItem;
- property Items[const Index: Integer]: TGLGizmoUndoItem read GetItems
- write SetItems; default;
- end;
- TGLGizmoElement = (geMove, geRotate, geScale, geAxisLabel, geObjectInfos,
- geBoundingBox);
- TGLGizmoElements = set of TGLGizmoElement;
- TGLGizmoVisibleInfoLabel = (vliName, vliOperation, vliCoords);
- TGLGizmoVisibleInfoLabels = set of TGLGizmoVisibleInfoLabel;
- TGLGizmoAxis = (gaNone, gaX, gaY, gaZ, gaXY, gaXZ, gaYZ);
- TGLGizmoOperation = (gopMove, gopRotate, gopScale, gopNone, gpMoveGizmo,
- gpRotateGizmo);
- TGLGizmoAcceptEvent = procedure(Sender: TObject; var Obj: TGLBaseSceneObject;
- var Accept: Boolean; var Dimensions: TGLVector) of object;
- TGLGizmoUpdateEvent = procedure(Sender: TObject; Obj: TGLBaseSceneObject;
- Axis: TGLGizmoAxis; Operation: TGLGizmoOperation; var Vector: TGLVector)
- of object;
- TGLGizmoPickMode = (pmGetPickedObjects, pmRayCast);
- TGLGizmoRayCastHitData = class(TPersistent)
- public
- Obj: TGLBaseSceneObject;
- Point: TGLVector;
- end;
- TGLGizmoPickCube = class(TGLCube)
- end;
- TGLGizmoPickTorus = class(TGLTorus)
- end;
- TGLGizmo = class(TComponent)
- private
- _GZObaseGizmo: TGLBaseSceneObject;
- _GZOBoundingcube: TGLCube;
- _GZOrootHelpers: TGLBaseSceneObject;
- _GZOrootLines: TGLBaseSceneObject;
- _GZOrootTorus: TGLBaseSceneObject;
- _GZOrootCubes: TGLBaseSceneObject;
- _GZORootAxisLabel: TGLBaseSceneObject;
- _GZORootVisibleInfoLabels: TGLBaseSceneObject;
- _GZOlineX, _GZOlineY, _GZOlineZ, _GZOplaneXY, _GZOplaneXZ,
- _GZOplaneYZ: TGLLines; // For Move
- _GZOTorusX, _GZOTorusY, _GZOTorusZ: TGLGizmoPickTorus; // For Rotate
- _GZOCubeX, _GZOCubeY, _GZOCubeZ: TGLGizmoPickCube; // For Scale
- _GZOAxisLabelX, _GZOAxisLabelY, _GZOAxisLabelZ: TGLFlatText;
- _GZOVisibleInfoLabels: TGLFlatText;
- FRootGizmo: TGLBaseSceneObject;
- FSelectedObj: TGLBaseSceneObject;
- // FLastOperation,
- FOperation: TGLGizmoOperation;
- FSelAxis: TGLGizmoAxis;
- FBoundingBoxColor: TGLColor;
- FSelectedColor: TGLColor;
- FVisibleInfoLabelsColor: TGLColor;
- FBoundingBoxColorChanged: Boolean;
- FVisibleInfoLabelsColorChanged: Boolean;
- FForceOperation: Boolean;
- FForceAxis: Boolean;
- FForceUniformScale: Boolean;
- FAutoZoom: Boolean;
- FExcludeObjects: Boolean;
- FNoZWrite: Boolean;
- FEnabled: Boolean;
- FAutoZoomFactor: Single;
- FZoomFactor: Single;
- FMoveCoef: Single;
- FRotationCoef: Single;
- FViewer: TGLSceneViewer;
- FGizmoElements: TGLGizmoElements;
- FVisibleVisibleInfoLabels: TGLGizmoVisibleInfoLabels;
- FExcludeObjectsList: TStrings;
- Moving: Boolean;
- Mx, My: Integer;
- Rx, Ry: Integer;
- dglEnable, dglDisable, dgtEnable, dgtDisable, dgcEnable, dgcDisable,
- dglaEnable, dglaDisable, dgliEnable, dgliDisable: TGLDirectOpenGL;
- LastMousePos: TGLVector;
- ObjDimensions: TGLVector;
- FOnBeforeSelect: TGLGizmoAcceptEvent;
- FOnBeforeUpdate: TGLGizmoUpdateEvent;
- FOnSelectionLost: TNotifyEvent;
- FScaleCoef: Single;
- FGizmoThickness: Single;
- FPickMode: TGLGizmoPickMode;
- FInternalRaycastHitData: TList;
- FUndoHistory: TGLGizmoUndoCollection;
- FLabelFont: TGLCustomBitmapFont;
- procedure SetRootGizmo(const AValue: TGLBaseSceneObject);
- procedure SetGizmoElements(const AValue: TGLGizmoElements);
- procedure SeTGLGizmoVisibleInfoLabels(const AValue
- : TGLGizmoVisibleInfoLabels);
- procedure SetBoundingBoxColor(const AValue: TGLColor);
- procedure SetSelectedColor(const AValue: TGLColor);
- procedure SetVisibleInfoLabelsColor(const AValue: TGLColor);
- procedure SetExcludeObjectsList(const AValue: TStrings);
- procedure DirectGlDisable(Sender: TObject; var Rci: TGLRenderContextInfo);
- procedure DirectGlEnable(Sender: TObject; var Rci: TGLRenderContextInfo);
- function MouseWorldPos(const X, Y: Integer): TGLVector;
- function CheckObjectInExcludeList(const Obj: TGLBaseSceneObject): Boolean;
- procedure UpdateVisibleInfoLabels;
- procedure SetGLGizmoThickness(const Value: Single);
- function InternalGetPickedObjects(const X1, Y1, X2, Y2: Integer;
- const GuessCount: Integer = 8): TGLPickList;
- procedure ClearInternalRaycastHitData;
- procedure SetViewer(const Value: TGLSceneViewer);
- procedure SetLabelFont(const Value: TGLCustomBitmapFont);
- procedure SetSelectedObj(const Value: TGLBaseSceneObject);
- public
- PickableObjectsWithRayCast: TList;
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- procedure Loaded; override;
- procedure Notification(AComponent: TComponent;
- Operation: TOperation); override;
- procedure ViewerMouseMove(const X, Y: Integer);
- procedure ViewerMouseDown(const X, Y: Integer);
- procedure ViewerMouseUp(const X, Y: Integer);
- procedure UpdateGizmo; overload;
- procedure UpdateGizmo(const NewDimensions: TGLVector); overload;
- procedure SetVisible(const AValue: Boolean);
- function GetPickedObjectPoint(const Obj: TGLBaseSceneObject): TGLVector;
- procedure LooseSelection; virtual;
- procedure UndoAdd(const AObject: TGLCustomSceneObject);
- property RootGizmo: TGLBaseSceneObject read FRootGizmo write SetRootGizmo;
- // --------------------------------------------------------------------
- published
- property Viewer: TGLSceneViewer read FViewer write SetViewer;
- property GizmoElements: TGLGizmoElements read FGizmoElements
- write SetGizmoElements;
- property BoundingBoxColor: TGLColor read FBoundingBoxColor
- write SetBoundingBoxColor;
- property SelectedColor: TGLColor read FSelectedColor write SetSelectedColor;
- property SelAxis: TGLGizmoAxis read FSelAxis write FSelAxis;
- property ForceAxis: Boolean read FForceAxis write FForceAxis;
- property SelectedObj: TGLBaseSceneObject read FSelectedObj
- write SetSelectedObj;
- property Operation: TGLGizmoOperation read FOperation write FOperation;
- property ForceOperation: Boolean read FForceOperation write FForceoperation;
- property ForceUniformScale: Boolean read FForceUniformScale
- write FForceUniformScale;
- property ExcludeObjects: Boolean read FExcludeObjects write FExcludeObjects;
- property ExcludeObjectsList: TStrings read FExcludeObjectsList
- write SetExcludeObjectsList;
- property VisibleInfoLabels: TGLGizmoVisibleInfoLabels
- read FVisibleVisibleInfoLabels write SeTGLGizmoVisibleInfoLabels;
- property VisibleInfoLabelsColor: TGLColor read FVisibleInfoLabelsColor
- write SetVisibleInfoLabelsColor;
- property AutoZoom: Boolean read FAutoZoom write FAutoZoom;
- property AutoZoomFactor: Single read FAutoZoomFactor write FAutoZoomFactor;
- property ZoomFactor: Single read FZoomFactor write FZoomFactor;
- property MoveCoef: Single read FMoveCoef write FMoveCoef;
- property RotationCoef: Single read FRotationCoef write FRotationCoef;
- property ScaleCoef: Single read FScaleCoef write FScaleCoef;
- property NoZWrite: Boolean read FNoZWrite write FNoZWrite;
- property GizmoThickness: Single read FGizmoThickness
- write SeTGLGizmoThickness;
- { Indicates whether the gizmo is enabled or not.
- WARNING: When loading/editing (possibly whenever a structureChanged
- call is made) a model, sometimes the gizmo will trigger a
- bug if the mouse is inside the glscene Viewer. To prevent that,
- remember to disable the gizmo before loading, then process windows
- messages (i.e. application.processMessage) and then enable the gizmo
- again. }
- { Warning Enable is ReadOnly property if you set to False, Gizmo is not Hidden
- use Visible instead if you want to Hide, if you want to Hide but keep enabled
- see the VisibleGizmo property }
- property Enabled: Boolean read FEnabled write FEnabled default False;
- property LabelFont: TGLCustomBitmapFont read FLabelFont write SetLabelFont
- default nil;
- property OnBeforeSelect: TGLGizmoAcceptEvent read FOnBeforeSelect
- write FOnBeforeSelect;
- property OnSelectionLost: TNotifyEvent read FOnSelectionLost
- write FOnSelectionLost;
- { Called before an Update is applied. The "vector" parameter is the difference
- that will be applied to the object, according to the axis and
- operation selected. }
- property OnBeforeUpdate: TGLGizmoUpdateEvent read FOnBeforeUpdate
- write FOnBeforeUpdate;
- property PickMode: TGLGizmoPickMode read FPickMode write FPickMode
- default PmGetPickedObjects;
- end;
- //=========================================================
- implementation
- //=========================================================
- procedure RotateAroundArbitraryAxis(const AnObject: TGLBaseSceneObject;
- const Axis, Origin: TAffineVector; const Angle: Single);
- var
- M, M1, M2, M3: TGLMatrix;
- begin
- M1 := CreateTranslationMatrix(VectorNegate(Origin));
- M2 := CreateRotationMatrix(Axis, Angle * PI / 180);
- M3 := CreateTranslationMatrix(Origin);
- M := MatrixMultiply(M1, M2);
- M := MatrixMultiply(M, M3);
- AnObject.SetMatrix(MatrixMultiply(AnObject.Matrix^, M));
- // Just a workarround to Update angles...
- AnObject.Roll(0);
- AnObject.Pitch(0);
- AnObject.Turn(0);
- end;
- // ------------------------------------------------------------------------------
- procedure TGLGizmo.ClearInternalRaycastHitData;
- var
- T: Integer;
- begin
- for T := FInternalRaycastHitData.Count - 1 downto 0 do
- begin
- TGLGizmoRayCastHitData(FInternalRaycastHitData[T]).Free;
- end;
- FInternalRaycastHitData.Clear;
- end;
- constructor TGLGizmo.Create(AOwner: TComponent);
- var
- Cub: TGLCube;
- begin
- inherited Create(AOwner);
- FUndoHistory := TGLGizmoUndoCollection.Create(Self, TGLGizmoUndoItem);
- FPickMode := PmGetPickedObjects;
- PickableObjectsWithRayCast := TList.Create;
- FRotationCoef := 1;
- FMoveCoef := 0.1;
- FScaleCoef := 0.1;
- FGizmoThickness := 1;
- FInternalRaycastHitData := TList.Create;
- FBoundingBoxColor := TGLColor.Create(Self);
- FBoundingBoxColor.Color := ClrWhite;
- FBoundingBoxColorChanged := False;
- FSelectedColor := TGLColor.Create(Self);
- FSelectedColor.Color := ClrYellow;
- FVisibleInfoLabelsColor := TGLColor.Create(Self);
- FVisibleInfoLabelsColor.Color := ClrYellow;
- FVisibleInfoLabelsColorChanged := False;
- _GZObaseGizmo := TGLDummyCube.Create(Self);
- _GZORootHelpers := TGLDummyCube(_GZObaseGizmo.AddNewChild(TGLDummyCube));
- _GZOBoundingcube := TGLCube(_GZORootHelpers.AddNewChild(TGLCube));
- _GZORootLines := _GZORootHelpers.AddNewChild(TGLDummyCube);
- _GZORootTorus := _GZORootHelpers.AddNewChild(TGLDummyCube);
- _GZORootCubes := _GZORootHelpers.AddNewChild(TGLDummyCube);
- _GZORootAxisLabel := _GZORootHelpers.AddNewChild(TGLDummyCube);
- _GZORootVisibleInfoLabels := _GZORootHelpers.AddNewChild(TGLDummyCube);
- DglDisable := TGLDirectOpenGL(_GZORootLines.AddNewChild(TGLDirectOpenGL));
- DglDisable.OnRender := DirectGlDisable;
- DgtDisable := TGLDirectOpenGL(_GZORootTorus.AddNewChild(TGLDirectOpenGL));
- DgtDisable.OnRender := DirectGlDisable;
- DgcDisable := TGLDirectOpenGL(_GZORootCubes.AddNewChild(TGLDirectOpenGL));
- DgcDisable.OnRender := DirectGlDisable;
- DglaDisable := TGLDirectOpenGL
- (_GZORootAxisLabel.AddNewChild(TGLDirectOpenGL));
- DglaDisable.OnRender := DirectGlDisable;
- DgliDisable := TGLDirectOpenGL(_GZORootVisibleInfoLabels.AddNewChild
- (TGLDirectOpenGL));
- DgliDisable.OnRender := DirectGlDisable;
- with _GZOBoundingcube.Material do
- begin
- FaceCulling := FcNoCull;
- PolygonMode := PmLines;
- with FrontProperties do
- begin
- Diffuse.Color := FBoundingBoxColor.Color;
- Ambient.Color := FBoundingBoxColor.Color;
- Emission.Color := FBoundingBoxColor.Color;
- end;
- with BackProperties do
- begin
- Diffuse.Color := FBoundingBoxColor.Color;
- Ambient.Color := FBoundingBoxColor.Color;
- Emission.Color := FBoundingBoxColor.Color;
- end;
- end;
- _GZOlinex := TGLLines(_GZORootLines.AddnewChild(TGLLines));
- with _GZOlinex do
- begin
- LineColor.Color := clrRed;
- LineWidth := 3;
- NodesAspect := LnaInvisible;
- AddNode(0, 0, 0);
- AddNode(1, 0, 0);
- AddNode(0.9, 0, -0.1);
- AddNode(1, 0, 0);
- AddNode(0.9, 0, 0.1);
- // Raycast pickable object
- Cub := TGLGizmoPickCube(AddNewChild(TGLGizmoPickCube));
- Cub.Up.SetVector(1, 0, 0);
- Cub.CubeWidth := 0.1;
- Cub.CubeHeight := 1;
- Cub.CubeDepth := 0.1;
- Cub.Position.SetPoint(0.5, 0, 0);
- Cub.Visible := False;
- end;
- _GZOliney := TGLLines(_GZORootLines.AddnewChild(TGLLines));
- with _GZOliney do
- begin
- LineColor.Color := clrLime;
- LineWidth := 3;
- NodesAspect := LnaInvisible;
- AddNode(0, 0, 0);
- AddNode(0, 1, 0);
- AddNode(0.1, 0.9, 0);
- AddNode(0, 1, 0);
- AddNode(-0.1, 0.9, 0);
- // Raycast pickable object
- Cub := TGLGizmoPickCube(AddNewChild(TGLGizmoPickCube));
- Cub.Up.SetVector(0, 1, 0);
- Cub.CubeWidth := 0.1;
- Cub.CubeHeight := 1;
- Cub.CubeDepth := 0.1;
- Cub.Position.SetPoint(0, 0.5, 0);
- Cub.Visible := False;
- end;
- _GZOlinez := TGLLines(_GZORootLines.AddnewChild(TGLLines));
- with _GZOlinez do
- begin
- LineColor.Color := clrBlue;
- LineWidth := 3;
- NodesAspect := LnaInvisible;
- AddNode(0, 0, 0);
- AddNode(0, 0, 1);
- AddNode(0.1, 0, 0.9);
- AddNode(0, 0, 1);
- AddNode(-0.1, 0, 0.9);
- // Raycast pickable object
- Cub := TGLGizmoPickCube(AddNewChild(TGLGizmoPickCube));
- Cub.Up.SetVector(0, 0, 1);
- Cub.CubeWidth := 0.1;
- Cub.CubeHeight := 1;
- Cub.CubeDepth := 0.1;
- Cub.Position.SetPoint(0, 0, 0.5);
- Cub.Visible := False;
- end;
- _GZOplaneXY := TGLLines(_GZORootLines.AddnewChild(TGLLines));
- with _GZOplaneXY do
- begin
- LineWidth := 3;
- Options := [LoUseNodeColorForLines];
- NodesAspect := LnaInvisible;
- SplineMode := LsmSegments;
- AddNode(0.8, 1, 0);
- TGLLinesNode(Nodes[0]).Color.Color := clrRed;
- AddNode(1, 1, 0);
- TGLLinesNode(Nodes[1]).Color.Color := clrRed;
- AddNode(1, 1, 0);
- TGLLinesNode(Nodes[2]).Color.Color := clrLime;
- AddNode(1, 0.8, 0);
- TGLLinesNode(Nodes[3]).Color.Color := clrLime;
- // Raycast pickable object
- Cub := TGLGizmoPickCube(AddNewChild(TGLGizmoPickCube));
- Cub.Up.SetVector(1, 0, 0);
- Cub.CubeWidth := 0.2;
- Cub.CubeHeight := 0.2;
- Cub.CubeDepth := 0.1;
- Cub.Position.SetPoint(0.9, 0.9, 0);
- Cub.Visible := False;
- end;
- _GZOplaneXZ := TGLLines(_GZORootLines.AddnewChild(TGLLines));
- with _GZOplaneXZ do
- begin
- LineWidth := 3;
- Options := [LoUseNodeColorForLines];
- NodesAspect := LnaInvisible;
- SplineMode := LsmSegments;
- AddNode(1, 0, 0.8);
- TGLLinesNode(Nodes[0]).Color.Color := clrBlue;
- AddNode(1, 0, 1);
- TGLLinesNode(Nodes[1]).Color.Color := clrBlue;
- AddNode(1, 0, 1);
- TGLLinesNode(Nodes[2]).Color.Color := clrRed;
- AddNode(0.8, 0, 1);
- TGLLinesNode(Nodes[3]).Color.Color := clrRed;
- // Raycast pickable object
- Cub := TGLGizmoPickCube(AddNewChild(TGLGizmoPickCube));
- Cub.Up.SetVector(1, 0, 0);
- Cub.CubeWidth := 0.1;
- Cub.CubeHeight := 0.2;
- Cub.CubeDepth := 0.2;
- Cub.Position.SetPoint(0.9, 0, 0.9);
- Cub.Visible := False;
- end;
- _GZOplaneYZ := TGLLines(_GZORootLines.AddnewChild(TGLLines));
- with _GZOplaneYZ do
- begin
- LineWidth := 3;
- Options := [LoUseNodeColorForLines];
- NodesAspect := LnaInvisible;
- SplineMode := LsmSegments;
- AddNode(0, 0.8, 1);
- TGLLinesNode(Nodes[0]).Color.Color := clrLime;
- AddNode(0, 1, 1);
- TGLLinesNode(Nodes[1]).Color.Color := clrLime;
- AddNode(0, 1, 1);
- TGLLinesNode(Nodes[2]).Color.Color := clrBlue;
- AddNode(0, 1, 0.8);
- TGLLinesNode(Nodes[3]).Color.Color := clrBlue;
- // Raycast pickable object
- Cub := TGLGizmoPickCube(AddNewChild(TGLGizmoPickCube));
- Cub.Up.SetVector(0, 0, 1);
- Cub.CubeWidth := 0.2;
- Cub.CubeHeight := 0.2;
- Cub.CubeDepth := 0.1;
- Cub.Position.SetPoint(0, 0.9, 0.9);
- Cub.Visible := False;
- end;
- _GZOTorusX := TGLGizmoPickTorus(_GZORootTorus.AddnewChild(TGLGizmoPickTorus));
- with _GZOTorusX do
- begin
- Rings := 16;
- Sides := 4;
- MajorRadius := 0.6;
- MinorRadius := 0.03;
- PitchAngle := 90;
- TurnAngle := 90;
- with Material do
- begin
- // FaceCulling:= fcNoCull;
- PolygonMode := PmFill;
- // BackProperties.PolygonMode:= pmFill;
- FrontProperties.Emission.Color := clrBlue;
- end;
- end;
- _GZOTorusY := TGLGizmoPickTorus(_GZORootTorus.AddnewChild(TGLGizmoPickTorus));
- with _GZOTorusY do
- begin
- Rings := 16;
- Sides := 4;
- MajorRadius := 0.6;
- MinorRadius := 0.03;
- PitchAngle := 90;
- with Material do
- begin
- // FaceCulling:= fcNoCull;
- PolygonMode := PmFill;
- // BackProperties.PolygonMode:= pmFill;
- FrontProperties.Emission.Color := clrRed;
- end;
- end;
- _GZOTorusZ := TGLGizmoPickTorus(_GZORootTorus.AddnewChild(TGLGizmoPickTorus));
- with _GZOTorusZ do
- begin
- Rings := 16;
- Sides := 4;
- MajorRadius := 0.6;
- MinorRadius := 0.03;
- with Material do
- begin
- // FaceCulling:= fcNoCull;
- PolygonMode := PmFill;
- // BackProperties.PolygonMode:= pmFill;
- FrontProperties.Emission.Color := clrLime;
- end;
- end;
- _GZOCubeX := TGLGizmoPickCube(_GZORootCubes.AddnewChild(TGLGizmoPickCube));
- with _GZOCubeX do
- begin
- CubeDepth := 0.1;
- CubeHeight := 0.1;
- CubeWidth := 0.1;
- Position.X := 1.15;
- with Material do
- begin
- FaceCulling := FcNoCull;
- PolygonMode := PmFill;
- FrontProperties.Emission.Color := clrRed;
- end;
- end;
- _GZOCubeY := TGLGizmoPickCube(_GZORootCubes.AddnewChild(TGLGizmoPickCube));
- with _GZOCubeY do
- begin
- CubeDepth := 0.1;
- CubeHeight := 0.1;
- CubeWidth := 0.1;
- Position.Y := 1.15;
- with Material do
- begin
- FaceCulling := FcNoCull;
- PolygonMode := PmFill;
- FrontProperties.Emission.Color := clrLime;
- end;
- end;
- _GZOCubeZ := TGLGizmoPickCube(_GZORootCubes.AddnewChild(TGLGizmoPickCube));
- with _GZOCubeZ do
- begin
- CubeDepth := 0.1;
- CubeHeight := 0.1;
- CubeWidth := 0.1;
- Position.Z := 1.15;
- with Material do
- begin
- FaceCulling := FcNoCull;
- PolygonMode := PmFill;
- FrontProperties.Emission.Color := clrBlue;
- end;
- end;
- _GZOAxisLabelX := TGLFlatText(_GZORootAxisLabel.AddNewChild(TGLFlatText));
- with _GZOAxisLabelX do
- begin
- ModulateColor.Color := ClrRed;
- Alignment := TaCenter;
- Layout := TTextLayout.tlCenter;
- Options := Options + [FtoTwoSided];
- Position.X := 1.5;
- Scale.X := 0.02;
- Scale.Y := 0.02;
- Text := 'X';
- end;
- _GZOAxisLabelY := TGLFlatText(_GZORootAxisLabel.AddNewChild(TGLFlatText));
- with _GZOAxisLabelY do
- begin
- ModulateColor.Color := clrLime;
- Alignment := TaCenter;
- Layout := TlCenter;
- Options := Options + [FtoTwoSided];
- Position.Y := 1.5;
- Scale.X := 0.02;
- Scale.Y := 0.02;
- Text := 'Y';
- end;
- _GZOAxisLabelZ := TGLFlatText(_GZORootAxisLabel.AddNewChild(TGLFlatText));
- with _GZOAxisLabelZ do
- begin
- ModulateColor.Color := ClrBlue;
- Alignment := TaCenter;
- Layout := TlCenter;
- Options := Options + [FtoTwoSided];
- Position.Z := 1.5;
- Scale.X := 0.02;
- Scale.Y := 0.02;
- Text := 'Z';
- end;
- _GZOVisibleInfoLabels :=
- TGLFlatText(_GZORootVisibleInfoLabels.AddNewChild(TGLFlatText));
- with _GZOVisibleInfoLabels do
- begin
- ModulateColor.Color := clrYellow;
- Alignment := TaCenter;
- Layout := TlCenter;
- Options := Options + [FtoTwoSided];
- Position.Y := 1.8;
- Position.X := 0;
- Scale.X := 0.01;
- Scale.Y := 0.01;
- Text := '';
- end;
- DglEnable := TGLDirectOpenGL(_GZORootLines.AddNewChild(TGLDirectOpenGL));
- DglEnable.OnRender := DirectGlEnable;
- DgtEnable := TGLDirectOpenGL(_GZORootTorus.AddNewChild(TGLDirectOpenGL));
- DgtEnable.OnRender := DirectGlEnable;
- DgcEnable := TGLDirectOpenGL(_GZORootCubes.AddNewChild(TGLDirectOpenGL));
- DgcEnable.OnRender := DirectGlEnable;
- DglaEnable := TGLDirectOpenGL(_GZORootAxisLabel.AddNewChild(TGLDirectOpenGL));
- DglaEnable.OnRender := DirectGlEnable;
- DgliEnable := TGLDirectOpenGL(_GZORootVisibleInfoLabels.AddNewChild
- (TGLDirectOpenGL));
- DgliEnable.OnRender := DirectGlEnable;
- _GZObaseGizmo.Visible := False;
- FGizmoElements := FGizmoElements + [GeMove, GeRotate, GeScale, GeAxisLabel,
- GeObjectInfos, GeBoundingBox];
- FVisibleVisibleInfoLabels := FVisibleVisibleInfoLabels +
- [VliName, VliOperation, VliCoords];
- AutoZoom := True;
- AutoZoomFactor := 5.0;
- ZoomFactor := 0.35;
- ForceOperation := False;
- ForceAxis := False;
- ForceUniformScale := False;
- Enabled := True;
- FNoZWrite := True;
- FExcludeObjectsList := TStringList.Create;
- end;
- destructor TGLGizmo.Destroy;
- begin
- if Assigned(FRootGizmo) then
- FRootGizmo.DeleteChildren
- else
- begin
- _GZOBaseGizmo.DeleteChildren;
- _GZOBaseGizmo.Free;
- end;
- FBoundingBoxColor.Free;
- FSelectedColor.Free;
- FVisibleInfoLabelsColor.Free;
- PickableObjectsWithRayCast.Free;
- FExcludeObjectsList.Free;
- ClearInternalRaycastHitData;
- FInternalRaycastHitData.Free;
- // FUndoHistory has to be nil before Notification() is called.
- FreeAndNil(FUndoHistory);
- inherited Destroy;
- end;
- procedure TGLGizmo.SetVisible(const AValue: Boolean);
- begin
- _GZObaseGizmo.Visible := AValue;
- end;
- procedure TGLGizmo.SetGizmoElements(const AValue: TGLGizmoElements);
- begin
- if AValue <> FGizmoElements then
- begin
- FGizmoElements := AValue;
- _GZORootLines.Visible := GeMove in FGizmoElements;
- _GZORootTorus.Visible := GeRotate in FGizmoElements;
- _GZORootCubes.Visible := GeScale in FGizmoElements;
- _GZORootAxisLabel.Visible := GeAxisLabel in FGizmoElements;
- _GZORootVisibleInfoLabels.Visible := GeObjectInfos in FGizmoElements;
- _GZOBoundingcube.Visible := GeBoundingBox in FGizmoElements;
- end;
- end;
- procedure TGLGizmo.SetBoundingBoxColor(const AValue: TGLColor);
- begin
- // Bug Here New Color is not Updated
- if AValue <> FBoundingBoxColor then
- begin
- FBoundingBoxColor.Color := AValue.Color;
- with _GZOBoundingcube.Material do
- begin
- with FrontProperties do
- begin
- Diffuse.Color := FBoundingBoxColor.Color;
- Ambient.Color := FBoundingBoxColor.Color;
- Emission.Color := FBoundingBoxColor.Color;
- end;
- with BackProperties do
- begin
- Diffuse.Color := FBoundingBoxColor.Color;
- Ambient.Color := FBoundingBoxColor.Color;
- Emission.Color := FBoundingBoxColor.Color;
- end;
- end;
- FBoundingBoxColorChanged := True;
- end;
- end;
- procedure TGLGizmo.SetSelectedColor(const AValue: TGLColor);
- begin
- if AValue <> FSelectedColor then
- begin
- FSelectedColor.Color := AValue.Color;
- end;
- end;
- procedure TGLGizmo.SetVisibleInfoLabelsColor(const AValue: TGLColor);
- begin
- // Bug Here New Color is not Updated
- if AValue <> FSelectedColor then
- begin
- FVisibleInfoLabelsColor.Color := AValue.Color;
- _GZOVisibleInfoLabels.ModulateColor.Color := AValue.Color;
- FVisibleInfoLabelsColorChanged := True;
- end;
- end;
- procedure TGLGizmo.SeTGLGizmoVisibleInfoLabels(const AValue
- : TGLGizmoVisibleInfoLabels);
- begin
- if AValue <> FVisibleVisibleInfoLabels then
- begin
- FVisibleVisibleInfoLabels := AValue;
- if not(CsDesigning in ComponentState) then
- UpdateGizmo;
- end;
- end;
- procedure TGLGizmo.UndoAdd(const AObject: TGLCustomSceneObject);
- begin
- if AObject <> nil then
- begin
- FUndoHistory.Add.AssignFromObject(AObject)
- end;
- end;
- procedure TGLGizmo.SetRootGizmo(const AValue: TGLBaseSceneObject);
- begin
- if FRootGizmo <> AValue then
- begin
- if FRootGizmo <> nil then
- FRootGizmo.RemoveFreeNotification(Self);
- FRootGizmo := AValue;
- if FRootGizmo <> nil then
- FRootGizmo.FreeNotification(Self);
- _GZObaseGizmo.MoveTo(AValue);
- end;
- end;
- procedure TGLGizmo.SetExcludeObjectsList(const AValue: TStrings);
- begin
- FExcludeObjectsList.Clear;
- FExcludeObjectsList.AddStrings(AValue);
- end;
- procedure TGLGizmo.SetGLGizmoThickness(const Value: Single);
- var
- Thk: Single;
- begin
- if FGizmoThickness <> Value then
- begin
- Thk := MaxInteger(1, Round(3 * Value));
- _GZOlinex.LineWidth := Thk;
- _GZOliney.LineWidth := Thk;
- _GZOlinez.LineWidth := Thk;
- _GZOplaneXY.LineWidth := Thk;
- _GZOplaneXZ.LineWidth := Thk;
- _GZOplaneYZ.LineWidth := Thk;
- _GZOTorusX.MinorRadius := 0.03 * Value;
- _GZOTorusY.MinorRadius := 0.03 * Value;
- _GZOTorusZ.MinorRadius := 0.03 * Value;
- with _GZOCubeX do
- begin
- CubeDepth := 0.1 * Value;
- CubeHeight := 0.1 * Value;
- CubeWidth := 0.1 * Value;
- end;
- with _GZOCubeY do
- begin
- CubeDepth := 0.1 * Value;
- CubeHeight := 0.1 * Value;
- CubeWidth := 0.1 * Value;
- end;
- with _GZOCubeZ do
- begin
- CubeDepth := 0.1 * Value;
- CubeHeight := 0.1 * Value;
- CubeWidth := 0.1 * Value;
- end;
- FGizmoThickness := Value;
- end;
- end;
- // ------------------------------------------------------------------------------
- procedure TGLGizmo.DirectGlDisable(Sender: TObject;
- var Rci: TGLRenderContextInfo);
- begin
- if FNoZWrite then
- Rci.GLStates.Disable(StDepthTest);
- end;
- procedure TGLGizmo.SetLabelFont(const Value: TGLCustomBitmapFont);
- begin
- if FLabelFont <> Value then
- begin
- if FLabelFont <> nil then
- FLabelFont.RemoveFreeNotification(Self);
- FLabelFont := Value;
- if FLabelFont <> nil then
- FLabelFont.FreeNotification(Self);
- _GZOAxisLabelX.BitmapFont := Value;
- _GZOAxisLabelY.BitmapFont := Value;
- _GZOAxisLabelZ.BitmapFont := Value;
- _GZOVisibleInfoLabels.BitmapFont := Value;
- end;
- end;
- procedure TGLGizmo.DirectGlEnable(Sender: TObject; var Rci: TGLRenderContextInfo);
- begin
- if FNoZWrite then
- Rci.GLStates.Enable(StDepthTest);
- end;
- function TGLGizmo.GetPickedObjectPoint(const Obj: TGLBaseSceneObject): TGLVector;
- var
- T: Integer;
- R: TGLGizmoRayCastHitData;
- begin
- for T := 0 to FInternalRaycastHitData.Count - 1 do
- begin
- R := TGLGizmoRayCastHitData(FInternalRaycastHitData[T]);
- if R.Obj = Obj then
- begin
- Result := R.Point;
- Break;
- end;
- end;
- end;
- function TGLGizmo.InternalGetPickedObjects(const X1, Y1, X2, Y2: Integer;
- const GuessCount: Integer): TGLPickList;
- var
- T: Integer;
- RayStart, RayVector, IPoint, INormal: TGLVector;
- O: TGLBaseSceneObject;
- Dist: Single;
- HitData: TGLGizmoRayCastHitData;
- procedure AddGizmosToPicklListRecurse(const Root: TGLBaseSceneObject);
- var
- U: Integer;
- begin
- for U := 0 to Root.Count - 1 do
- begin
- if ((Root[U] is TGLGizmoPickTorus) or (Root[U] is TGLGizmoPickCube)) then
- PickableObjectsWithRayCast.Add(Root[U]);
- AddGizmosToPicklListRecurse(Root[U]);
- end;
- end;
- begin
- case FPickMode of
- PmGetPickedObjects:
- begin
- Result := Viewer.Buffer.GetPickedObjects(Rect(X1, Y1, X2, Y2),
- GuessCount);
- end;
- PmRayCast:
- begin
- Result := TGLPickList.Create(PsMinDepth);
- ClearInternalRaycastHitData;
- SetVector(RayStart, Viewer.Camera.AbsolutePosition);
- SetVector(RayVector, Viewer.Buffer.ScreenToVector
- (AffineVectorMake((X1 + X2) * 0.5,
- Viewer.Height - ((Y1 + Y2) * 0.5), 0)));
- NormalizeVector(RayVector);
- // Add gizmos
- if (RootGizmo <> nil) and (SelectedObj <> nil) then
- AddGizmosToPicklListRecurse(RootGizmo);
- // pick
- for T := 0 to PickableObjectsWithRayCast.Count - 1 do
- begin
- O := TGLBaseSceneObject(PickableObjectsWithRayCast[T]);
- if (O.RayCastIntersect(RayStart, RayVector, @IPoint, @INormal)) and
- (VectorDotProduct(RayVector, INormal) < 0) then
- begin
- try
- Dist := VectorLength(VectorSubtract(IPoint, RayStart));
- Result.AddHit(O, nil, Dist, 0);
- HitData := TGLGizmoRayCastHitData.Create;
- HitData.Obj := O;
- MakeVector(HitData.Point, IPoint);
- FInternalRaycastHitData.Add(HitData);
- except
- //
- end;
- end;
- end;
- end;
- else
- begin
- Result := nil;
- Assert(False, strErrorEx + strUnknownType);
- end;
- end;
- end;
- procedure TGLGizmo.Loaded;
- begin
- inherited;
- SeTGLGizmoThickness(GizmoThickness);
- end;
- // ------------------------------------------------------------------------------
- procedure TGLGizmo.UpdateVisibleInfoLabels;
- var
- T: string;
- X, Y, Z: Single;
- begin
- T := '';
- if not(Assigned(SelectedObj)) then
- Exit;
- if VliName in FVisibleVisibleInfoLabels then
- T := SelectedObj.Name;
- if VliOperation in FVisibleVisibleInfoLabels then
- begin
- if (Operation <> GopNone) then
- begin
- if Length(T) > 0 then
- T := T + ' - ';
- case Operation of
- GopMove:
- T := T + 'Move';
- GopRotate:
- T := T + 'Rotate';
- GopScale:
- T := T + 'Scale';
- end;
- end;
- end;
- if VliCoords in FVisibleVisibleInfoLabels then
- begin
- if (Operation <> GopNone) then
- begin
- if Length(T) > 0 then
- T := T + ' - ';
- case Operation of
- GopMove:
- begin
- X := SelectedObj.Position.X;
- Y := SelectedObj.Position.Y;
- Z := SelectedObj.Position.Z;
- T := T + 'X : ' + Format('%2.3f', [X]);
- T := T + ' Y : ' + Format('%2.3f', [Y]);
- T := T + ' Z : ' + Format('%2.3f', [Z]);
- end;
- GopRotate:
- begin
- X := SelectedObj.Rotation.X;
- Y := SelectedObj.Rotation.Y;
- Z := SelectedObj.Rotation.Z;
- T := T + 'X : ' + Format('%2.3f', [X]);
- T := T + ' Y : ' + Format('%2.3f', [Y]);
- T := T + ' Z : ' + Format('%2.3f', [Z]);
- end;
- GopScale:
- begin
- X := SelectedObj.Scale.X;
- Y := SelectedObj.Scale.Y;
- Z := SelectedObj.Scale.Z;
- T := T + 'X : ' + Format('%2.3f', [X]);
- T := T + ' Y : ' + Format('%2.3f', [Y]);
- T := T + ' Z : ' + Format('%2.3f', [Z]);
- end;
- end;
- end;
- end;
- _GZOVisibleInfoLabels.Text := T;
- _GZOVisibleInfoLabels.StructureChanged;
- end;
- // ------------------------------------------------------------------------------
- function TGLGizmo.CheckObjectInExcludeList
- (const Obj: TGLBaseSceneObject): Boolean;
- var
- I: Integer;
- begin
- Result := False;
- if FExcludeObjects then
- begin
- for I := 0 to FExcludeObjectsList.Count - 1 do
- begin
- if UpperCase(Obj.Name) = UpperCase(FExcludeObjectsList[I]) then
- begin
- Result := True;
- Exit;
- end;
- end;
- end;
- end;
- function TGLGizmo.MouseWorldPos(const X, Y: Integer): TGLVector;
- var
- V: TGLVector;
- InvertedY: Integer;
- begin
- InvertedY := Viewer.Height - Y;
- if Assigned(SelectedObj) then
- begin
- SetVector(V, X, InvertedY, 0);
- case SelAxis of
- GaX:
- if not Viewer.Buffer.ScreenVectorIntersectWithPlaneXZ(V,
- SelectedObj.AbsolutePosition.Y, Result) then
- MakeVector(Result, X / 5, 0, 0);
- GaY:
- if not Viewer.Buffer.ScreenVectorIntersectWithPlaneYZ(V,
- SelectedObj.AbsolutePosition.X, Result) then
- MakeVector(Result, 0, InvertedY / 5, 0);
- GaZ:
- if not Viewer.Buffer.ScreenVectorIntersectWithPlaneYZ(V,
- SelectedObj.AbsolutePosition.X, Result) then
- MakeVector(Result, 0, 0, -InvertedY / 5);
- GaXY:
- begin
- Viewer.Buffer.ScreenVectorIntersectWithPlaneXY(V,
- SelectedObj.AbsolutePosition.Z, Result);
- end;
- GaXZ:
- begin
- Viewer.Buffer.ScreenVectorIntersectWithPlaneXZ(V,
- SelectedObj.AbsolutePosition.Y, Result);
- end;
- GaYZ:
- begin
- Viewer.Buffer.ScreenVectorIntersectWithPlaneYZ(V,
- SelectedObj.AbsolutePosition.X, Result);
- end;
- end;
- end
- else
- SetVector(Result, NullVector);
- end;
- procedure TGLGizmo.ViewerMouseMove(const X, Y: Integer);
- var
- PickList: TGLPickList;
- MousePos: TGLVector;
- function IndexOf(Obj: TGLBaseSceneObject): Integer;
- var
- I: Integer;
- begin
- Result := -1;
- for I := 0 to PickList.Count - 1 do
- if PickList.Hit[I] = Obj then
- begin
- Result := I;
- Break;
- end;
- end;
- function LightLine(const Line: TGLLines; const Dark: TGLVector;
- const Axis: TGLGizmoAxis; AlterStyle: Boolean = False): Boolean;
- var
- PickObj: TGLBaseSceneObject;
- begin
- case FPickMode of
- PmGetPickedObjects:
- PickObj := Line;
- PmRayCast:
- PickObj := Line;
- else
- begin
- PickObj := nil;
- Assert(False, strErrorEx + strUnknownType);
- end;
- end;
- if IndexOf(PickObj) > -1 then
- begin
- Line.LineColor.Color := FSelectedColor.Color;
- if not(FForceOperation) then
- if Operation <> GopMove then
- Operation := GopMove;
- Line.Options := [];
- if not(FForceAxis) then
- SelAxis := Axis;
- Result := True;
- end
- else
- begin
- Line.LineColor.Color := Dark;
- if not(FForceOperation) then
- Operation := GopNone;
- if AlterStyle then
- Line.Options := [LoUseNodeColorForLines];
- if not(FForceAxis) then
- if SelAxis = Axis then
- SelAxis := GaNone;
- Result := False;
- end;
- end;
- function LightTorus(const Torus: TGLGizmoPickTorus; const Dark: TGLVector;
- const Axis: TGLGizmoAxis; AlterStyle: Boolean = False): Boolean;
- begin
- if IndexOf(Torus) > -1 then
- begin
- Torus.Material.FrontProperties.Emission.Color := FSelectedColor.Color;
- if not(FForceOperation) then
- if Operation <> GopRotate then
- Operation := GopRotate;
- if not(FForceAxis) then
- SelAxis := Axis;
- Result := True;
- end
- else
- begin
- Torus.Material.FrontProperties.Emission.Color := Dark;
- if not(FForceOperation) then
- Operation := GopNone;
- if not(FForceAxis) then
- if SelAxis = Axis then
- SelAxis := GaNone;
- Result := False;
- end;
- end;
- function LightCube(const Cube: TGLCube; const Dark: TGLVector;
- const Axis: TGLGizmoAxis; AlterStyle: Boolean = False): Boolean;
- begin
- if IndexOf(Cube) > -1 then
- begin
- Cube.Material.FrontProperties.Emission.Color := FSelectedColor.Color;
- if not(FForceOperation) then
- if Operation <> GopScale then
- Operation := GopScale;
- if not(FForceAxis) then
- SelAxis := Axis;
- Result := True;
- end
- else
- begin
- Cube.Material.FrontProperties.Emission.Color := Dark;
- if not(FForceOperation) then
- Operation := GopNone;
- if not(FForceAxis) then
- if SelAxis = Axis then
- SelAxis := GaNone;
- Result := False;
- end;
- end;
- procedure OpeMove(MousePos: TGLVector);
- var
- Vec1, Vec2: TGLVector;
- QuantizedMousePos, QuantizedMousePos2: TGLVector;
- T: Integer;
- begin
- for T := 0 to 3 do
- begin
- QuantizedMousePos.V[T] := (Round(MousePos.V[T] / MoveCoef)) * MoveCoef;
- QuantizedMousePos2.V[T] := (Round(LastMousePos.V[T] / MoveCoef)) * MoveCoef;
- end;
- case SelAxis of
- GaX:
- begin
- MakeVector(Vec1, QuantizedMousePos.X, 0, 0);
- MakeVector(Vec2, QuantizedMousePos2.X, 0, 0);
- end;
- GaY:
- begin
- MakeVector(Vec1, 0, QuantizedMousePos.Y, 0);
- MakeVector(Vec2, 0, QuantizedMousePos2.Y, 0);
- end;
- GaZ:
- begin
- MakeVector(Vec1, 0, 0, QuantizedMousePos.Z);
- MakeVector(Vec2, 0, 0, QuantizedMousePos2.Z);
- end;
- else
- begin
- Vec1 := QuantizedMousePos;
- Vec2 := QuantizedMousePos2;
- end;
- end;
- SubtractVector(Vec1, Vec2);
- if Assigned(OnBeforeUpdate) then
- OnBeforeUpdate(Self, SelectedObj, SelAxis, Operation, Vec1);
- Vec1 := SelectedObj.Parent.AbsoluteToLocal(Vec1);
- if (VectorLength(Vec1) > 0) then // prevents NAN problems
- begin
- SelectedObj.Position.Translate(Vec1);
- end;
- end;
- procedure OpeRotate(const X, Y: Integer);
- var
- Vec1: TGLVector;
- RotV: TAffineVector;
- Pmat: TGLMatrix;
- begin
- Vec1.X := 0;
- Vec1.Y := 0;
- if Abs(X - Rx) >= RotationCoef then
- begin
- if RotationCoef > 1 then
- Vec1.X := RotationCoef * (Round((X - Rx) / (RotationCoef)))
- else
- Vec1.X := RotationCoef * (X - Rx);
- Rx := X;
- end;
- if Abs(Y - Ry) >= RotationCoef then
- begin
- if RotationCoef > 1 then
- Vec1.Y := RotationCoef * (Round((Y - Ry) / (RotationCoef)))
- else
- Vec1.Y := RotationCoef * (Y - Ry);
- Ry := Y;
- end;
- Vec1.Z := 0;
- Vec1.W := 0;
- if Assigned(OnBeforeUpdate) then
- OnBeforeUpdate(Self, SelectedObj, SelAxis, Operation, Vec1);
- Pmat := SelectedObj.Parent.InvAbsoluteMatrix;
- SetVector(Pmat.V[3], NullHmgPoint);
- case SelAxis of
- GaX:
- begin
- RotV := VectorTransform(XVector, Pmat);
- RotateAroundArbitraryAxis(SelectedObj, RotV,
- AffineVectorMake(SelectedObj.Position.AsVector), Vec1.Y);
- end;
- GaY:
- begin
- RotV := VectorTransform(YVector, Pmat);
- RotateAroundArbitraryAxis(SelectedObj, RotV,
- AffineVectorMake(SelectedObj.Position.AsVector), Vec1.X);
- end;
- GaZ:
- begin
- RotV := VectorTransform(ZVector, Pmat);
- RotateAroundArbitraryAxis(SelectedObj, RotV,
- AffineVectorMake(SelectedObj.Position.AsVector), Vec1.Y);
- end;
- GaXY:
- begin
- RotV := VectorTransform(XVector, Pmat);
- RotateAroundArbitraryAxis(SelectedObj, RotV,
- AffineVectorMake(SelectedObj.Position.AsVector), Vec1.Y);
- RotV := VectorTransform(YVector, Pmat);
- RotateAroundArbitraryAxis(SelectedObj, RotV,
- AffineVectorMake(SelectedObj.Position.AsVector), Vec1.X);
- end;
- GaXZ:
- begin
- RotV := VectorTransform(XVector, Pmat);
- RotateAroundArbitraryAxis(SelectedObj, RotV,
- AffineVectorMake(SelectedObj.Position.AsVector), Vec1.Y);
- RotV := VectorTransform(ZVector, Pmat);
- RotateAroundArbitraryAxis(SelectedObj, RotV,
- AffineVectorMake(SelectedObj.Position.AsVector), Vec1.X);
- end;
- GaYZ:
- begin
- RotV := VectorTransform(YVector, Pmat);
- RotateAroundArbitraryAxis(SelectedObj, RotV,
- AffineVectorMake(SelectedObj.Position.AsVector), Vec1.Y);
- RotV := VectorTransform(ZVector, Pmat);
- RotateAroundArbitraryAxis(SelectedObj, RotV,
- AffineVectorMake(SelectedObj.Position.AsVector), Vec1.X);
- end;
- end;
- end;
- procedure OpeScale(const MousePos: TGLVector);
- var
- Vec1, Vec2: TGLVector;
- QuantizedMousePos, QuantizedMousePos2: TGLVector;
- T: Integer;
- begin
- for T := 0 to 3 do
- begin
- QuantizedMousePos.V[T] := (Round(MousePos.V[T] / ScaleCoef)) * FScaleCoef;
- QuantizedMousePos2.V[T] := (Round(LastMousePos.V[T] / FScaleCoef)) *
- FScaleCoef;
- end;
- case SelAxis of
- GaX:
- begin
- if FForceUniformScale then
- begin
- MakeVector(Vec1, QuantizedMousePos.X, QuantizedMousePos.X,
- QuantizedMousePos.X);
- MakeVector(Vec2, QuantizedMousePos2.X, QuantizedMousePos2.X,
- QuantizedMousePos2.X);
- end
- else
- begin
- MakeVector(Vec1, QuantizedMousePos.X, 0, 0);
- MakeVector(Vec2, QuantizedMousePos2.X, 0, 0);
- end;
- end;
- GaY:
- begin
- if FForceUniformScale then
- begin
- MakeVector(Vec1, QuantizedMousePos.Y, QuantizedMousePos.Y,
- QuantizedMousePos.Y);
- MakeVector(Vec2, QuantizedMousePos2.Y, QuantizedMousePos2.Y,
- QuantizedMousePos2.Y);
- end
- else
- begin
- MakeVector(Vec1, 0, QuantizedMousePos.Y, 0);
- MakeVector(Vec2, 0, QuantizedMousePos2.Y, 0);
- end;
- end;
- GaZ:
- begin
- if FForceUniformScale then
- begin
- MakeVector(Vec1, QuantizedMousePos.Z, QuantizedMousePos.Z,
- QuantizedMousePos.Z);
- MakeVector(Vec2, QuantizedMousePos2.Z, QuantizedMousePos2.Z,
- QuantizedMousePos2.Z);
- end
- else
- begin
- MakeVector(Vec1, 0, 0, QuantizedMousePos.Z);
- MakeVector(Vec2, 0, 0, QuantizedMousePos2.Z);
- end;
- end;
- else
- begin
- Vec1 := QuantizedMousePos;
- Vec2 := QuantizedMousePos2;
- end;
- end;
- SubtractVector(Vec1, Vec2);
- if Assigned(OnBeforeUpdate) then
- OnBeforeUpdate(Self, SelectedObj, SelAxis, Operation, Vec1);
- SelectedObj.Scale.Translate(Vec1);
- UpdateGizmo;
- end;
- begin
- if not Enabled then
- Exit;
- if Assigned(SelectedObj) and (SelAxis <> GaNone) and Moving then
- begin
- MousePos := MouseWorldPos(X, Y);
- // moving object...
- if Operation = GopMove then
- begin
- // FLastOperation = gopMove;
- OpeMove(MousePos);
- end
- else if Operation = GopRotate then
- begin
- // FLastOperation = gopRotate;
- OpeRotate(X, Y);
- end
- else if Operation = GopScale then
- begin
- // FLastOperation = gopScale;
- OpeScale(MousePos);
- end;
- UpdateGizmo;
- Mx := X;
- My := Y;
- LastMousePos := MousePos;
- Exit;
- end;
- Assert(FViewer <> nil, 'Viewer not Assigned to gizmo');
- Picklist := InternalGetPickedObjects(X - 1, Y - 1, X + 1, Y + 1, 8);
- // Viewer.buffer.GetPickedObjects(rect(x-1, y-1, x+1, y+1), 8);
- if not LightLine(_GZOlinex, ClrRed, GaX) and not LightLine(_GZOliney, ClrLime,
- GaY) and not LightLine(_GZOlinez, ClrBlue, GaZ) and
- not LightTorus(_GZOTorusX, ClrRed, GaX) and
- not LightTorus(_GZOTorusY, ClrLime, GaY) and
- not LightTorus(_GZOTorusz, ClrBlue, GaZ) and
- not LightCube(_GZOCubeX, ClrRed, GaX) and not LightCube(_GZOCubeY, ClrLime,
- GaY) and not LightCube(_GZOCubeZ, ClrBlue, GaZ) and
- not LightLine(_GZOplaneXY, ClrWhite, GaXY, True) and
- not LightLine(_GZOplaneXZ, ClrWhite, GaXZ, True) and
- not LightLine(_GZOplaneYZ, ClrWhite, GaYZ, True) then
- begin
- if not(FForceAxis) then
- SelAxis := GaNone;
- if not(FForceOperation) then
- Operation := GopNone;
- end;
- Picklist.Free;
- Mx := X;
- My := Y;
- end;
- procedure TGLGizmo.ViewerMouseDown(const X, Y: Integer);
- var
- Pick: TGLPickList;
- I: Integer;
- Accept: Boolean;
- Dimensions: TGLVector;
- GotPick: Boolean;
- PickedObj: TGLBaseSceneObject;
- begin
- Mx := X;
- My := Y;
- Rx := X;
- Ry := Y;
- if not Enabled then
- Exit;
- Pick := InternalGetPickedObjects(X - 1, Y - 1, X + 1, Y + 1);
- // Viewer.Buffer.GetPickedObjects(rect(x-1, y-1, x+1, y+1));
- GotPick := False;
- Accept := False;
- case FPickMode of
- PmGetPickedObjects:
- begin
- // primeiro, ver se é uma das linhas/planos
- for I := 0 to Pick.Count - 1 do
- if (_GZOrootLines.IndexOfChild(TGLBaseSceneObject(Pick.Hit[I])) > -1)
- or (_GZOrootTorus.IndexOfChild(TGLBaseSceneObject(Pick.Hit[I])) >
- -1) or (_GZOrootCubes.IndexOfChild(TGLBaseSceneObject(Pick.Hit[I]))
- > -1) then
- GotPick := True;
- end;
- PmRayCast:
- begin
- for I := 0 to Pick.Count - 1 do
- begin
- if (Pick.Hit[I] is TGLGizmoPickCube) or
- (Pick.Hit[I] is TGLGizmoPickTorus) then
- GotPick := True;
- end;
- end;
- else
- begin
- Assert(False, strErrorEx + strUnknownType);
- end;
- end;
- if not GotPick then
- begin
- for I := 0 to Pick.Count - 1 do
- if (Pick.Hit[I] <> _GZOBoundingcube) and (Pick.Hit[I] <> _GZOAxisLabelX)
- and (Pick.Hit[I] <> _GZOAxisLabelY) and (Pick.Hit[I] <> _GZOAxisLabelZ)
- and (Pick.Hit[I] <> _GZOVisibleInfoLabels) and
- not(CheckObjectInExcludeList(TGLBaseSceneObject(Pick.Hit[I]))) then
- begin
- Accept := True;
- PickedObj := TGLBaseSceneObject(Pick.Hit[I]);
- Dimensions := PickedObj.AxisAlignedDimensions;
- if Assigned(OnBeforeSelect) then
- OnBeforeSelect(Self, PickedObj, Accept, Dimensions);
- Break;
- end;
- if Accept then
- SetSelectedObj(PickedObj)
- else
- SetSelectedObj(nil);
- end
- else
- UpdateVisibleInfoLabels();
- Pick.Free;
- Moving := True;
- LastMousePos := MouseWorldPos(X, Y);
- end;
- procedure TGLGizmo.ViewerMouseUp(const X, Y: Integer);
- begin
- Moving := False;
- end;
- // ------------------------------------------------------------------------------
- procedure TGLGizmo.UpdateGizmo;
- var
- D: Single;
- begin
- if SelectedObj = nil then
- begin
- _GZObaseGizmo.Visible := False;
- Exit;
- end;
- _GZObaseGizmo.Position.AsVector := SelectedObj.AbsolutePosition;
- if GeObjectInfos in FGizmoElements then
- UpdateVisibleInfoLabels;
- _GZOBoundingcube.SetMatrix(SelectedObj.AbsoluteMatrix);
- _GZOBoundingcube.Position.SetPoint(0, 0, 0);
- // We must Update Color Of the BoundingBox And VisibleInfoLabels Here
- // If not Color is not Updated;
- // if FBoundingBoxColorChanged then
- // Begin
- with _GZOBoundingcube.Material do
- begin
- with FrontProperties do
- begin
- Diffuse.Color := FBoundingBoxColor.Color;
- Ambient.Color := FBoundingBoxColor.Color;
- Emission.Color := FBoundingBoxColor.Color;
- end;
- with BackProperties do
- begin
- Diffuse.Color := FBoundingBoxColor.Color;
- Ambient.Color := FBoundingBoxColor.Color;
- Emission.Color := FBoundingBoxColor.Color;
- end;
- end;
- // FBoundingBoxColorChanged:=False;
- // End;
- // If FVisibleInfoLabelsColorChanged then
- // Begin
- _GZOVisibleInfoLabels.ModulateColor.Color := FVisibleInfoLabelsColor.Color;
- // FVisibleInfoLabelsColorChanged:=False;
- // End;
- ObjDimensions := SelectedObj.AxisAlignedDimensions;
- _GZOBoundingcube.Scale.AsVector := VectorScale(ObjDimensions, 2);
- Assert(Viewer <> nil, 'Viewer not Assigned to gizmo');
- _GZOAxisLabelX.PointTo(Viewer.Camera.Position.AsVector,
- Viewer.Camera.Up.AsVector);
- _GZOAxisLabelX.StructureChanged;
- _GZOAxisLabelY.PointTo(Viewer.Camera.Position.AsVector,
- Viewer.Camera.Up.AsVector);
- _GZOAxisLabelY.StructureChanged;
- _GZOAxisLabelZ.PointTo(Viewer.Camera.Position.AsVector,
- Viewer.Camera.Up.AsVector);
- _GZOAxisLabelZ.StructureChanged;
- _GZOVisibleInfoLabels.PointTo(Viewer.Camera.Position.AsVector,
- Viewer.Camera.Up.AsVector);
- _GZOVisibleInfoLabels.StructureChanged;
- if FAutoZoom then
- D := Viewer.Camera.DistanceTo(SelectedObj) / FAutoZoomFactor
- else
- D := FZoomFactor;
- _GZOrootLines.Scale.AsVector := VectorMake(D, D, D);
- _GZOrootTorus.Scale.AsVector := VectorMake(D, D, D);
- _GZOrootCubes.Scale.AsVector := VectorMake(D, D, D);
- _GZOrootAxisLabel.Scale.AsVector := VectorMake(D, D, D);
- _GZOrootVisibleInfoLabels.Scale.AsVector := VectorMake(D, D, D);
- end;
- procedure TGLGizmo.UpdateGizmo(const NewDimensions: TGLVector);
- begin
- ObjDimensions := NewDimensions;
- UpdateGizmo;
- end;
- procedure TGLGizmo.LooseSelection;
- begin
- SelectedObj := nil;
- UpdateGizmo;
- if Assigned(OnSelectionLost) then
- OnSelectionLost(Self);
- end;
- procedure TGLGizmo.SetViewer(const Value: TGLSceneViewer);
- begin
- if FViewer <> Value then
- begin
- if FViewer <> nil then
- FViewer.RemoveFreeNotification(Self);
- FViewer := Value;
- if FViewer <> nil then
- FViewer.FreeNotification(Self);
- end;
- end;
- procedure TGLGizmo.Notification(AComponent: TComponent; Operation: TOperation);
- begin
- inherited;
- if Operation = OpRemove then
- begin
- if AComponent = FViewer then
- FViewer := nil;
- if AComponent = FRootGizmo then
- FRootGizmo := nil;
- end;
- if FUndoHistory <> nil then
- FUndoHistory.Notification(AComponent, Operation);
- end;
- procedure TGLGizmoUndoItem.AssignFromObject(const AObject
- : TGLCustomSceneObject);
- begin
- SetEffectedObject(AObject);
- SetOldMatrix(AObject.Matrix^);
- if AObject is TGLFreeForm then
- begin
- FOldAutoScaling.Assign(TGLFreeForm(AObject).AutoScaling);
- end;
- FOldLibMaterialName := AObject.Material.LibMaterialName;
- end;
- constructor TGLGizmoUndoItem.Create(AOwner: TCollection);
- begin
- inherited;
- FOldAutoScaling := TGLCoordinates.CreateInitialized(Self,
- NullHmgVector, CsPoint);
- end;
- destructor TGLGizmoUndoItem.Destroy;
- begin
- FOldAutoScaling.Free;
- inherited;
- end;
- procedure TGLGizmoUndoItem.DoUndo;
- begin
- FEffectedObject.SetMatrix(FOldMatr);
- if FEffectedObject is TGLFreeForm then
- TGLFreeForm(FEffectedObject).AutoScaling.Assign(FOldAutoScaling);
- FEffectedObject.Material.LibMaterialName := FOldLibMaterialName;
- end;
- function TGLGizmoUndoItem.GetGizmo: TGLGizmo;
- begin
- if GetParent <> nil then
- Result := GetPArent.GetParent
- else
- Result := nil;
- end;
- function TGLGizmoUndoItem.GetParent: TGLGizmoUndoCollection;
- begin
- Result := TGLGizmoUndoCollection(GetOwner);
- end;
- procedure TGLGizmoUndoItem.Notification(AComponent: TComponent;
- Operation: TOperation);
- begin
- inherited;
- if Operation = OpRemove then
- begin
- if AComponent = FEffectedObject then
- FEffectedObject := nil;
- end;
- end;
- procedure TGLGizmoUndoItem.SetEffectedObject(const Value: TGLCustomSceneObject);
- begin
- if FEffectedObject <> nil then
- FEffectedObject.RemoveFreeNotification(GetGizmo);
- FEffectedObject := Value;
- if FEffectedObject <> nil then
- FEffectedObject.FreeNotification(GetGizmo);
- end;
- procedure TGLGizmoUndoItem.SetOldAutoScaling(const Value: TGLCoordinates);
- begin
- FOldAutoScaling.Assign(Value);
- end;
- procedure TGLGizmoUndoItem.SetOldMatrix(const Value: TGLMatrix);
- begin
- FOldMatrix := Value;
- end;
- { TGLGizmoUndoCollection }
- function TGLGizmoUndoCollection.Add: TGLGizmoUndoItem;
- begin
- Result := TGLGizmoUndoItem(inherited Add);
- end;
- function TGLGizmoUndoCollection.GetItems(const Index: Integer)
- : TGLGizmoUndoItem;
- begin
- Result := TGLGizmoUndoItem(inherited GetItem(Index));
- end;
- function TGLGizmoUndoCollection.GetParent: TGLGizmo;
- begin
- Result := TGLGizmo(GetOwner);
- end;
- procedure TGLGizmoUndoCollection.Notification(AComponent: TComponent;
- Operation: TOperation);
- var
- I: Integer;
- begin
- if Count <> 0 then
- for I := 0 to Count - 1 do
- GetItems(I).Notification(AComponent, Operation);
- end;
- procedure TGLGizmoUndoCollection.RemoveByObject(const AObject
- : TGLCustomSceneObject);
- var
- I: Integer;
- begin
- for I := Count - 1 downto 0 do
- if GetItems(I).FEffectedObject = AObject then
- GetItems(I).Free;
- end;
- procedure TGLGizmoUndoCollection.SetItems(const Index: Integer;
- const Value: TGLGizmoUndoItem);
- begin
- GetItems(Index).Assign(Value);
- end;
- procedure TGLGizmo.SetSelectedObj(const Value: TGLBaseSceneObject);
- begin
- if FSelectedObj <> Value then
- begin
- FSelectedObj := Value;
- if Value <> nil then
- begin
- SetVisible(True);
- UpdateVisibleInfoLabels();
- UpdateGizmo();
- end
- else
- begin
- LooseSelection();
- SetVisible(False);
- end;
- end;
- end;
- end.
|