123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827 |
- //
- // The graphics engine GLXEngine. The unit of GXScene for Delphi
- //
- unit GXS.Gizmo;
- (*
- Invisible component for helping to Move, Rotate and Scale an Object
- (usefull for an Editor).
- *)
- interface
- {$I Stage.Defines.inc}
- uses
- System.Classes,
- System.SysUtils,
- FMX.TextLayout,
- GXS.PersistentClasses,
- Stage.VectorGeometry,
- Stage.VectorTypes,
- Stage.Strings,
- GXS.Scene,
- GXS.Color,
- GXS.Objects,
- GXS.Material,
- GXS.GeomObjects,
- GXS.BitmapFont,
- GXS.SceneViewer,
- GXS.VectorFileObjects,
- GXS.ImageUtils,
- GXS.Coordinates,
- GXS.RenderContextInfo,
- GXS.State,
- GXS.Selection;
- type
- TgxGizmoUndoCollection = class;
- TgxGizmo = class;
- TgxGizmoUndoItem = class(TCollectionItem)
- private
- FOldLibMaterialName: string;
- FOldAutoScaling: TgxCoordinates;
- FEffectedObject: TgxCustomSceneObject;
- FOldMatr: TMatrix4f;
- FOldMatrix: TMatrix4f;
- procedure SetEffectedObject(const Value: TgxCustomSceneObject);
- procedure SetOldAutoScaling(const Value: TgxCoordinates);
- procedure SetOldMatrix(const Value: TMatrix4f);
- protected
- procedure DoUndo; virtual;
- function GetParent: TgxGizmoUndoCollection;
- function GetGizmo: TgxGizmo;
- public
- constructor Create(AOwner: TCollection); override;
- destructor Destroy; override;
- procedure Notification(AComponent: TComponent;
- Operation: TOperation); virtual;
- procedure AssignFromObject(const AObject: TgxCustomSceneObject);
- // TODO: create a special type for Matrix.
- property OldMatrix: TMatrix4f read FOldMatrix write SetOldMatrix;
- published
- property EffectedObject: TgxCustomSceneObject read FEffectedObject
- write SetEffectedObject;
- property OldAutoScaling: TgxCoordinates read FOldAutoScaling
- write SetOldAutoScaling;
- property OldLibMaterialName: string read FOldLibMaterialName
- write FOldLibMaterialName;
- end;
- TgxGizmoUndoCollection = class(TOwnedCollection)
- private
- function GetItems(const Index: Integer): TgxGizmoUndoItem;
- procedure SetItems(const Index: Integer; const Value: TgxGizmoUndoItem);
- protected
- function GetParent: TgxGizmo;
- public
- procedure Notification(AComponent: TComponent; Operation: TOperation);
- procedure RemoveByObject(const AObject: TgxCustomSceneObject);
- function Add: TgxGizmoUndoItem;
- property Items[const Index: Integer]: TgxGizmoUndoItem read GetItems
- write SetItems; default;
- end;
- TgxGizmoElement = (geMove, geRotate, geScale, geAxisLabel, geObjectInfos,
- geBoundingBox);
- TgxGizmoElements = set of TgxGizmoElement;
- TgxGizmoVisibleInfoLabel = (vliName, vliOperation, vliCoords);
- TgxGizmoVisibleInfoLabels = set of TgxGizmoVisibleInfoLabel;
- TgxGizmoAxis = (gaNone, gaX, gaY, gaZ, gaXY, gaXZ, gaYZ);
- TgxGizmoOperation = (gopMove, gopRotate, gopScale, gopNone, gpMoveGizmo,
- gpRotateGizmo);
- TgxGizmoAcceptEvent = procedure(Sender: TObject; var Obj: TgxBaseSceneObject;
- var Accept: Boolean; var Dimensions: TVector4f) of object;
- TgxGizmoUpdateEvent = procedure(Sender: TObject; Obj: TgxBaseSceneObject;
- Axis: TgxGizmoAxis; Operation: TgxGizmoOperation; var Vector: TVector4f)
- of object;
- TgxGizmoPickMode = (pmGetPickedObjects, pmRayCast);
- TgxGizmoRayCastHitData = class(TPersistent)
- public
- Obj: TgxBaseSceneObject;
- Point: TVector4f;
- end;
- TgxGizmoPickCube = class(TgxCube)
- end;
- TgxGizmoPickTorus = class(TgxTorus)
- end;
- TgxGizmo = class(TComponent)
- private
- _GZObaseGizmo: TgxBaseSceneObject;
- _GZOBoundingcube: TgxCube;
- _GZOrootHelpers: TgxBaseSceneObject;
- _GZOrootLines: TgxBaseSceneObject;
- _GZOrootTorus: TgxBaseSceneObject;
- _GZOrootCubes: TgxBaseSceneObject;
- _GZORootAxisLabel: TgxBaseSceneObject;
- _GZORootVisibleInfoLabels: TgxBaseSceneObject;
- _GZOlineX, _GZOlineY, _GZOlineZ, _GZOplaneXY, _GZOplaneXZ,
- _GZOplaneYZ: TgxLines; // For Move
- _GZOTorusX, _GZOTorusY, _GZOTorusZ: TgxGizmoPickTorus; // For Rotate
- _GZOCubeX, _GZOCubeY, _GZOCubeZ: TgxGizmoPickCube; // For Scale
- _GZOAxisLabelX, _GZOAxisLabelY, _GZOAxisLabelZ: TgxFlatText;
- _GZOVisibleInfoLabels: TgxFlatText;
- FRootGizmo: TgxBaseSceneObject;
- FSelectedObj: TgxBaseSceneObject;
- // FLastOperation,
- FOperation: TgxGizmoOperation;
- FSelAxis: TgxGizmoAxis;
- FBoundingBoxColor: TgxColor;
- FSelectedColor: TgxColor;
- FVisibleInfoLabelsColor: TgxColor;
- 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: TgxSceneViewer;
- FGizmoElements: TgxGizmoElements;
- FVisibleVisibleInfoLabels: TgxGizmoVisibleInfoLabels;
- FExcludeObjectsList: TStrings;
- Moving: Boolean;
- Mx, My: Integer;
- Rx, Ry: Integer;
- dglEnable, dglDisable, dgtEnable, dgtDisable, dgcEnable, dgcDisable,
- dglaEnable, dglaDisable, dgliEnable, dgliDisable: TgxDirectOpenGL;
- LastMousePos: TVector4f;
- ObjDimensions: TVector4f;
- FOnBeforeSelect: TgxGizmoAcceptEvent;
- FOnBeforeUpdate: TgxGizmoUpdateEvent;
- FOnSelectionLost: TNotifyEvent;
- FScaleCoef: Single;
- FGizmoThickness: Single;
- FPickMode: TgxGizmoPickMode;
- FInternalRaycastHitData: TList;
- FUndoHistory: TgxGizmoUndoCollection;
- FLabelFont: TgxCustomBitmapFont;
- procedure SetRootGizmo(const AValue: TgxBaseSceneObject);
- procedure SetGizmoElements(const AValue: TgxGizmoElements);
- procedure SetGizmoVisibleInfoLabels(const AValue
- : TgxGizmoVisibleInfoLabels);
- procedure SetBoundingBoxColor(const AValue: TgxColor);
- procedure SetSelectedColor(const AValue: TgxColor);
- procedure SetVisibleInfoLabelsColor(const AValue: TgxColor);
- procedure SetExcludeObjectsList(const AValue: TStrings);
- procedure DirectGLDisable(Sender: TObject; var Rci: TgxRenderContextInfo);
- procedure DirectGLEnable(Sender: TObject; var Rci: TgxRenderContextInfo);
- function MouseWorldPos(const X, Y: Integer): TVector4f;
- function CheckObjectInExcludeList(const Obj: TgxBaseSceneObject): Boolean;
- procedure UpdateVisibleInfoLabels;
- procedure SetGizmoThickness(const Value: Single);
- function InternalGetPickedObjects(const X1, Y1, X2, Y2: Integer;
- const GuessCount: Integer = 8): TgxPickList;
- procedure ClearInternalRaycastHitData;
- procedure SetViewer(const Value: TgxSceneViewer);
- procedure SetLabelFont(const Value: TgxCustomBitmapFont);
- procedure SetSelectedObj(const Value: TgxBaseSceneObject);
- 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: TVector4f); overload;
- procedure SetVisible(const AValue: Boolean);
- function GetPickedObjectPoint(const Obj: TgxBaseSceneObject): TVector4f;
- procedure LooseSelection; virtual;
- procedure UndoAdd(const AObject: TgxCustomSceneObject);
- property RootGizmo: TgxBaseSceneObject read FRootGizmo write SetRootGizmo;
- // --------------------------------------------------------------------
- published
- property Viewer: TgxSceneViewer read FViewer write SetViewer;
- property GizmoElements: TgxGizmoElements read FGizmoElements
- write SetGizmoElements;
- property BoundingBoxColor: TgxColor read FBoundingBoxColor
- write SetBoundingBoxColor;
- property SelectedColor: TgxColor read FSelectedColor write SetSelectedColor;
- property SelAxis: TgxGizmoAxis read FSelAxis write FSelAxis;
- property ForceAxis: Boolean read FForceAxis write FForceAxis;
- property SelectedObj: TgxBaseSceneObject read FSelectedObj
- write SetSelectedObj;
- property Operation: TgxGizmoOperation 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: TgxGizmoVisibleInfoLabels
- read FVisibleVisibleInfoLabels write SetGizmoVisibleInfoLabels;
- property VisibleInfoLabelsColor: TgxColor 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 SetGizmoThickness;
- (* 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 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: TgxCustomBitmapFont read FLabelFont write SetLabelFont
- default nil;
- property OnBeforeSelect: TgxGizmoAcceptEvent 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: TgxGizmoUpdateEvent read FOnBeforeUpdate
- write FOnBeforeUpdate;
- property PickMode: TgxGizmoPickMode read FPickMode write FPickMode
- default PmGetPickedObjects;
- end;
- //=========================================================
- implementation
- //=========================================================
- procedure RotateAroundArbitraryAxis(const AnObject: TgxBaseSceneObject;
- const Axis, Origin: TAffineVector; const Angle: Single);
- var
- M, M1, M2, M3: TMatrix4f;
- 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 TgxGizmo.ClearInternalRaycastHitData;
- var
- T: Integer;
- begin
- for T := FInternalRaycastHitData.Count - 1 downto 0 do
- begin
- TgxGizmoRayCastHitData(FInternalRaycastHitData[T]).Free;
- end;
- FInternalRaycastHitData.Clear;
- end;
- constructor TgxGizmo.Create(AOwner: TComponent);
- var
- Cub: TgxCube;
- begin
- inherited Create(AOwner);
- FUndoHistory := TgxGizmoUndoCollection.Create(Self, TgxGizmoUndoItem);
- FPickMode := PmGetPickedObjects;
- PickableObjectsWithRayCast := TList.Create;
- FRotationCoef := 1;
- FMoveCoef := 0.1;
- FScaleCoef := 0.1;
- FGizmoThickness := 1;
- FInternalRaycastHitData := TList.Create;
- FBoundingBoxColor := TgxColor.Create(Self);
- FBoundingBoxColor.Color := ClrWhite;
- FBoundingBoxColorChanged := False;
- FSelectedColor := TgxColor.Create(Self);
- FSelectedColor.Color := ClrYellow;
- FVisibleInfoLabelsColor := TgxColor.Create(Self);
- FVisibleInfoLabelsColor.Color := ClrYellow;
- FVisibleInfoLabelsColorChanged := False;
- _GZObaseGizmo := TgxDummyCube.Create(Self);
- _GZORootHelpers := TgxDummyCube(_GZObaseGizmo.AddNewChild(TgxDummyCube));
- _GZOBoundingcube := TgxCube(_GZORootHelpers.AddNewChild(TgxCube));
- _GZORootLines := _GZORootHelpers.AddNewChild(TgxDummyCube);
- _GZORootTorus := _GZORootHelpers.AddNewChild(TgxDummyCube);
- _GZORootCubes := _GZORootHelpers.AddNewChild(TgxDummyCube);
- _GZORootAxisLabel := _GZORootHelpers.AddNewChild(TgxDummyCube);
- _GZORootVisibleInfoLabels := _GZORootHelpers.AddNewChild(TgxDummyCube);
- DglDisable := TgxDirectOpenGL(_GZORootLines.AddNewChild(TgxDirectOpenGL));
- DglDisable.OnRender := DirectGlDisable;
- DgtDisable := TgxDirectOpenGL(_GZORootTorus.AddNewChild(TgxDirectOpenGL));
- DgtDisable.OnRender := DirectGlDisable;
- DgcDisable := TgxDirectOpenGL(_GZORootCubes.AddNewChild(TgxDirectOpenGL));
- DgcDisable.OnRender := DirectGlDisable;
- DglaDisable := TgxDirectOpenGL
- (_GZORootAxisLabel.AddNewChild(TgxDirectOpenGL));
- DglaDisable.OnRender := DirectGlDisable;
- DgliDisable := TgxDirectOpenGL(_GZORootVisibleInfoLabels.AddNewChild
- (TgxDirectOpenGL));
- 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 := TgxLines(_GZORootLines.AddnewChild(TgxLines));
- 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 := TgxGizmoPickCube(AddNewChild(TgxGizmoPickCube));
- 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 := TgxLines(_GZORootLines.AddnewChild(TgxLines));
- 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 := TgxGizmoPickCube(AddNewChild(TgxGizmoPickCube));
- 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 := TgxLines(_GZORootLines.AddnewChild(TgxLines));
- 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 := TgxGizmoPickCube(AddNewChild(TgxGizmoPickCube));
- 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 := TgxLines(_GZORootLines.AddnewChild(TgxLines));
- with _GZOplaneXY do
- begin
- LineWidth := 3;
- Options := [LoUseNodeColorForLines];
- NodesAspect := LnaInvisible;
- SplineMode := LsmSegments;
- AddNode(0.8, 1, 0);
- TgxLinesNode(Nodes[0]).Color.Color := clrRed;
- AddNode(1, 1, 0);
- TgxLinesNode(Nodes[1]).Color.Color := clrRed;
- AddNode(1, 1, 0);
- TgxLinesNode(Nodes[2]).Color.Color := clrLime;
- AddNode(1, 0.8, 0);
- TgxLinesNode(Nodes[3]).Color.Color := clrLime;
- // Raycast pickable object
- Cub := TgxGizmoPickCube(AddNewChild(TgxGizmoPickCube));
- 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 := TgxLines(_GZORootLines.AddnewChild(TgxLines));
- with _GZOplaneXZ do
- begin
- LineWidth := 3;
- Options := [LoUseNodeColorForLines];
- NodesAspect := LnaInvisible;
- SplineMode := LsmSegments;
- AddNode(1, 0, 0.8);
- TgxLinesNode(Nodes[0]).Color.Color := clrBlue;
- AddNode(1, 0, 1);
- TgxLinesNode(Nodes[1]).Color.Color := clrBlue;
- AddNode(1, 0, 1);
- TgxLinesNode(Nodes[2]).Color.Color := clrRed;
- AddNode(0.8, 0, 1);
- TgxLinesNode(Nodes[3]).Color.Color := clrRed;
- // Raycast pickable object
- Cub := TgxGizmoPickCube(AddNewChild(TgxGizmoPickCube));
- 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 := TgxLines(_GZORootLines.AddnewChild(TgxLines));
- with _GZOplaneYZ do
- begin
- LineWidth := 3;
- Options := [LoUseNodeColorForLines];
- NodesAspect := LnaInvisible;
- SplineMode := LsmSegments;
- AddNode(0, 0.8, 1);
- TgxLinesNode(Nodes[0]).Color.Color := clrLime;
- AddNode(0, 1, 1);
- TgxLinesNode(Nodes[1]).Color.Color := clrLime;
- AddNode(0, 1, 1);
- TgxLinesNode(Nodes[2]).Color.Color := clrBlue;
- AddNode(0, 1, 0.8);
- TgxLinesNode(Nodes[3]).Color.Color := clrBlue;
- // Raycast pickable object
- Cub := TgxGizmoPickCube(AddNewChild(TgxGizmoPickCube));
- 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 := TgxGizmoPickTorus(_GZORootTorus.AddnewChild(TgxGizmoPickTorus));
- 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 := TgxGizmoPickTorus(_GZORootTorus.AddnewChild(TgxGizmoPickTorus));
- 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 := TgxGizmoPickTorus(_GZORootTorus.AddnewChild(TgxGizmoPickTorus));
- 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 := TgxGizmoPickCube(_GZORootCubes.AddnewChild(TgxGizmoPickCube));
- 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 := TgxGizmoPickCube(_GZORootCubes.AddnewChild(TgxGizmoPickCube));
- 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 := TgxGizmoPickCube(_GZORootCubes.AddnewChild(TgxGizmoPickCube));
- 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 := TgxFlatText(_GZORootAxisLabel.AddNewChild(TgxFlatText));
- with _GZOAxisLabelX do
- begin
- ModulateColor.Color := ClrRed;
- Alignment := TaCenter;
- Layout := TlCenter;
- Options := Options + [FtoTwoSided];
- Position.X := 1.5;
- Scale.X := 0.02;
- Scale.Y := 0.02;
- Text := 'X';
- end;
- _GZOAxisLabelY := TgxFlatText(_GZORootAxisLabel.AddNewChild(TgxFlatText));
- 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 := TgxFlatText(_GZORootAxisLabel.AddNewChild(TgxFlatText));
- 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 :=
- TgxFlatText(_GZORootVisibleInfoLabels.AddNewChild(TgxFlatText));
- 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 := TgxDirectOpenGL(_GZORootLines.AddNewChild(TgxDirectOpenGL));
- DglEnable.OnRender := DirectGlEnable;
- DgtEnable := TgxDirectOpenGL(_GZORootTorus.AddNewChild(TgxDirectOpenGL));
- DgtEnable.OnRender := DirectGlEnable;
- DgcEnable := TgxDirectOpenGL(_GZORootCubes.AddNewChild(TgxDirectOpenGL));
- DgcEnable.OnRender := DirectGlEnable;
- DglaEnable := TgxDirectOpenGL(_GZORootAxisLabel.AddNewChild(TgxDirectOpenGL));
- DglaEnable.OnRender := DirectGlEnable;
- DgliEnable := TgxDirectOpenGL(_GZORootVisibleInfoLabels.AddNewChild
- (TgxDirectOpenGL));
- 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 TgxGizmo.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 TgxGizmo.SetVisible(const AValue: Boolean);
- begin
- _GZObaseGizmo.Visible := AValue;
- end;
- procedure TgxGizmo.SetGizmoElements(const AValue: TgxGizmoElements);
- 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 TgxGizmo.SetBoundingBoxColor(const AValue: TgxColor);
- 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 TgxGizmo.SetSelectedColor(const AValue: TgxColor);
- begin
- if AValue <> FSelectedColor then
- begin
- FSelectedColor.Color := AValue.Color;
- end;
- end;
- procedure TgxGizmo.SetVisibleInfoLabelsColor(const AValue: TgxColor);
- 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 TgxGizmo.SetGizmoVisibleInfoLabels(const AValue
- : TgxGizmoVisibleInfoLabels);
- begin
- if AValue <> FVisibleVisibleInfoLabels then
- begin
- FVisibleVisibleInfoLabels := AValue;
- if not(CsDesigning in ComponentState) then
- UpdateGizmo;
- end;
- end;
- procedure TgxGizmo.UndoAdd(const AObject: TgxCustomSceneObject);
- begin
- if AObject <> nil then
- begin
- FUndoHistory.Add.AssignFromObject(AObject)
- end;
- end;
- procedure TgxGizmo.SetRootGizmo(const AValue: TgxBaseSceneObject);
- 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 TgxGizmo.SetExcludeObjectsList(const AValue: TStrings);
- begin
- FExcludeObjectsList.Clear;
- FExcludeObjectsList.AddStrings(AValue);
- end;
- procedure TgxGizmo.SetGizmoThickness(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 TgxGizmo.DirectGlDisable(Sender: TObject;
- var Rci: TgxRenderContextInfo);
- begin
- if FNoZWrite then
- Rci.gxStates.Disable(StDepthTest);
- end;
- procedure TgxGizmo.SetLabelFont(const Value: TgxCustomBitmapFont);
- 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 TgxGizmo.DirectGlEnable(Sender: TObject; var Rci: TgxRenderContextInfo);
- begin
- if FNoZWrite then
- Rci.gxStates.Enable(StDepthTest);
- end;
- function TgxGizmo.GetPickedObjectPoint(const Obj: TgxBaseSceneObject): TVector4f;
- var
- T: Integer;
- R: TgxGizmoRayCastHitData;
- begin
- for T := 0 to FInternalRaycastHitData.Count - 1 do
- begin
- R := TgxGizmoRayCastHitData(FInternalRaycastHitData[T]);
- if R.Obj = Obj then
- begin
- Result := R.Point;
- Break;
- end;
- end;
- end;
- function TgxGizmo.InternalGetPickedObjects(const X1, Y1, X2, Y2: Integer;
- const GuessCount: Integer): TgxPickList;
- var
- T: Integer;
- RayStart, RayVector, IPoint, INormal: TVector4f;
- O: TgxBaseSceneObject;
- Dist: Single;
- HitData: TgxGizmoRayCastHitData;
- procedure AddGizmosToPicklListRecurse(const Root: TgxBaseSceneObject);
- var
- U: Integer;
- begin
- for U := 0 to Root.Count - 1 do
- begin
- if ((Root[U] is TgxGizmoPickTorus) or (Root[U] is TgxGizmoPickCube)) 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 := TgxPickList.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 := TgxBaseSceneObject(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 := TgxGizmoRayCastHitData.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 TgxGizmo.Loaded;
- begin
- inherited;
- SetGizmoThickness(GizmoThickness);
- end;
- // ------------------------------------------------------------------------------
- procedure TgxGizmo.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 TgxGizmo.CheckObjectInExcludeList
- (const Obj: TgxBaseSceneObject): 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 TgxGizmo.MouseWorldPos(const X, Y: Integer): TVector4f;
- var
- V: TVector4f;
- InvertedY: Integer;
- begin
- InvertedY := Round(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 TgxGizmo.ViewerMouseMove(const X, Y: Integer);
- var
- PickList: TgxPickList;
- MousePos: TVector4f;
- function IndexOf(Obj: TgxBaseSceneObject): 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: TgxLines; const Dark: TVector4f;
- const Axis: TgxGizmoAxis; AlterStyle: Boolean = False): Boolean;
- var
- PickObj: TgxBaseSceneObject;
- 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: TgxGizmoPickTorus; const Dark: TVector4f;
- const Axis: TgxGizmoAxis; 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: TgxCube; const Dark: TVector4f;
- const Axis: TgxGizmoAxis; 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: TVector4f);
- var
- Vec1, Vec2: TVector4f;
- QuantizedMousePos, QuantizedMousePos2: TVector4f;
- 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: TVector4f;
- RotV: TAffineVector;
- Pmat: TMatrix4f;
- 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.W, 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: TVector4f);
- var
- Vec1, Vec2: TVector4f;
- QuantizedMousePos, QuantizedMousePos2: TVector4f;
- 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 TgxGizmo.ViewerMouseDown(const X, Y: Integer);
- var
- Pick: TgxPickList;
- I: Integer;
- Accept: Boolean;
- Dimensions: TVector4f;
- GotPick: Boolean;
- PickedObj: TgxBaseSceneObject;
- 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(TgxBaseSceneObject(Pick.Hit[I])) > -1)
- or (_GZOrootTorus.IndexOfChild(TgxBaseSceneObject(Pick.Hit[I])) >
- -1) or (_GZOrootCubes.IndexOfChild(TgxBaseSceneObject(Pick.Hit[I]))
- > -1) then
- GotPick := True;
- end;
- PmRayCast:
- begin
- for I := 0 to Pick.Count - 1 do
- begin
- if (Pick.Hit[I] is TgxGizmoPickCube) or
- (Pick.Hit[I] is TgxGizmoPickTorus) 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(TgxBaseSceneObject(Pick.Hit[I]))) then
- begin
- Accept := True;
- PickedObj := TgxBaseSceneObject(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 TgxGizmo.ViewerMouseUp(const X, Y: Integer);
- begin
- Moving := False;
- end;
- // ------------------------------------------------------------------------------
- procedure TgxGizmo.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 TgxGizmo.UpdateGizmo(const NewDimensions: TVector4f);
- begin
- ObjDimensions := NewDimensions;
- UpdateGizmo;
- end;
- procedure TgxGizmo.LooseSelection;
- begin
- SelectedObj := nil;
- UpdateGizmo;
- if Assigned(OnSelectionLost) then
- OnSelectionLost(Self);
- end;
- procedure TgxGizmo.SetViewer(const Value: TgxSceneViewer);
- 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 TgxGizmo.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 TgxGizmoUndoItem.AssignFromObject(const AObject
- : TgxCustomSceneObject);
- begin
- SetEffectedObject(AObject);
- SetOldMatrix(AObject.Matrix^);
- if AObject is TgxFreeForm then
- begin
- FOldAutoScaling.Assign(TgxFreeForm(AObject).AutoScaling);
- end;
- FOldLibMaterialName := AObject.Material.LibMaterialName;
- end;
- constructor TgxGizmoUndoItem.Create(AOwner: TCollection);
- begin
- inherited;
- FOldAutoScaling := TgxCoordinates.CreateInitialized(Self,
- NullHmgVector, CsPoint);
- end;
- destructor TgxGizmoUndoItem.Destroy;
- begin
- FOldAutoScaling.Free;
- inherited;
- end;
- procedure TgxGizmoUndoItem.DoUndo;
- begin
- FEffectedObject.SetMatrix(FOldMatr);
- if FEffectedObject is TgxFreeForm then
- TgxFreeForm(FEffectedObject).AutoScaling.Assign(FOldAutoScaling);
- FEffectedObject.Material.LibMaterialName := FOldLibMaterialName;
- end;
- function TgxGizmoUndoItem.GetGizmo: TgxGizmo;
- begin
- if GetParent <> nil then
- Result := GetPArent.GetParent
- else
- Result := nil;
- end;
- function TgxGizmoUndoItem.GetParent: TgxGizmoUndoCollection;
- begin
- Result := TgxGizmoUndoCollection(GetOwner);
- end;
- procedure TgxGizmoUndoItem.Notification(AComponent: TComponent;
- Operation: TOperation);
- begin
- inherited;
- if Operation = OpRemove then
- begin
- if AComponent = FEffectedObject then
- FEffectedObject := nil;
- end;
- end;
- procedure TgxGizmoUndoItem.SetEffectedObject(const Value: TgxCustomSceneObject);
- begin
- if FEffectedObject <> nil then
- FEffectedObject.RemoveFreeNotification(GetGizmo);
- FEffectedObject := Value;
- if FEffectedObject <> nil then
- FEffectedObject.FreeNotification(GetGizmo);
- end;
- procedure TgxGizmoUndoItem.SetOldAutoScaling(const Value: TgxCoordinates);
- begin
- FOldAutoScaling.Assign(Value);
- end;
- procedure TgxGizmoUndoItem.SetOldMatrix(const Value: TMatrix4f);
- begin
- FOldMatrix := Value;
- end;
- { TgxGizmoUndoCollection }
- function TgxGizmoUndoCollection.Add: TgxGizmoUndoItem;
- begin
- Result := TgxGizmoUndoItem(inherited Add);
- end;
- function TgxGizmoUndoCollection.GetItems(const Index: Integer)
- : TgxGizmoUndoItem;
- begin
- Result := TgxGizmoUndoItem(inherited GetItem(Index));
- end;
- function TgxGizmoUndoCollection.GetParent: TgxGizmo;
- begin
- Result := TgxGizmo(GetOwner);
- end;
- procedure TgxGizmoUndoCollection.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 TgxGizmoUndoCollection.RemoveByObject(const AObject
- : TgxCustomSceneObject);
- var
- I: Integer;
- begin
- for I := Count - 1 downto 0 do
- if GetItems(I).FEffectedObject = AObject then
- GetItems(I).Free;
- end;
- procedure TgxGizmoUndoCollection.SetItems(const Index: Integer;
- const Value: TgxGizmoUndoItem);
- begin
- GetItems(Index).Assign(Value);
- end;
- procedure TgxGizmo.SetSelectedObj(const Value: TgxBaseSceneObject);
- 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.
|