diff --git a/Source/Editor/Gizmo/TransformGizmo.cs b/Source/Editor/Gizmo/TransformGizmo.cs index 4918743ce..64f969990 100644 --- a/Source/Editor/Gizmo/TransformGizmo.cs +++ b/Source/Editor/Gizmo/TransformGizmo.cs @@ -263,6 +263,8 @@ namespace FlaxEditor.Gizmo // Note: because selection may contain objects and their children we have to split them and get only parents. // Later during transformation we apply translation/scale/rotation only on them (children inherit transformations) SceneGraphTools.BuildNodesParents(_selection, _selectionParents); + + base.OnSelectionChanged(newSelection); } /// diff --git a/Source/Editor/Gizmo/TransformGizmoBase.cs b/Source/Editor/Gizmo/TransformGizmoBase.cs index 99b1c8122..290795fa0 100644 --- a/Source/Editor/Gizmo/TransformGizmoBase.cs +++ b/Source/Editor/Gizmo/TransformGizmoBase.cs @@ -85,6 +85,7 @@ namespace FlaxEditor.Gizmo { InitDrawing(); ModeChanged += ResetTranslationScale; + } /// @@ -437,8 +438,6 @@ namespace FlaxEditor.Gizmo { case Mode.Translate: UpdateTranslateScale(); - if (Owner.SnapToVertex) - UpdateVertexSnapping(); break; case Mode.Scale: UpdateTranslateScale(); @@ -447,6 +446,8 @@ namespace FlaxEditor.Gizmo UpdateRotate(dt); break; } + if (Owner.SnapToVertex) + UpdateVertexSnapping(); } else { @@ -553,43 +554,23 @@ namespace FlaxEditor.Gizmo for (int i = 0; i < SelectionCount; i++) { var obj = GetSelectedObject(i); - if (obj.CanVertexSnap && obj.RayCastSelf(ref ray, out var distance, out _) && distance < closestDistance) + if (obj.RayCastSelf(ref ray, out var distance, out _) && distance < closestDistance) { closestDistance = distance; closestObject = obj; } } if (closestObject == null) - { - // Find the closest object in selection (in case ray didn't hit anything) - for (int i = 0; i < SelectionCount; i++) - { - var obj = GetSelectedObject(i); - if (obj.CanVertexSnap) - { - GetSelectedObjectsBounds(out var bounds, out _); - CollisionsHelper.ClosestPointBoxPoint(ref bounds, ref ray.Ray.Position, out var point); - var distance = Vector3.Distance(ref point, ref ray.Ray.Position); - if (distance < closestDistance) - { - closestDistance = distance; - closestObject = obj; - } - } - } - } + return; // ignore it if there is nothing under the mouse closestObject is only null if ray caster missed everything or Selection Count == 0 + _vertexSnapObject = closestObject; - if (closestObject == null) - return; - // Find the closest vertex to bounding box point (collision detection approximation) - var closestPoint = ray.Ray.GetPoint(closestDistance); - if (!closestObject.OnVertexSnap(ref closestPoint, out _vertexSnapPoint)) + if (!closestObject.OnVertexSnap(ref ray.Ray, closestDistance, out _vertexSnapPoint)) { - // Failed to get the closest point - _vertexSnapPoint = closestPoint; + //The OnVertexSnap is unimplemented or failed to get point return because there is nothing to do + _vertexSnapPoint = Vector3.Zero; + return; } - // Transform back to the local space of the object to work when moving it _vertexSnapPoint = closestObject.Transform.WorldToLocal(_vertexSnapPoint); } @@ -619,10 +600,9 @@ namespace FlaxEditor.Gizmo for (int i = 0; i < SelectionCount; i++) rayCast.ExcludeObjects.Add(GetSelectedObject(i)); var hit = Owner.SceneGraphRoot.RayCast(ref rayCast, out var distance, out var _); - if (hit != null && hit.CanVertexSnap) + if (hit != null) { - var point = rayCast.Ray.GetPoint(distance); - if (hit.OnVertexSnap(ref point, out var pointSnapped) + if (hit.OnVertexSnap(ref rayCast.Ray, distance, out var pointSnapped) //&& Vector3.Distance(point, pointSnapped) <= 25.0f ) { @@ -712,5 +692,11 @@ namespace FlaxEditor.Gizmo protected virtual void OnDuplicate() { } + /// + public override void OnSelectionChanged(List newSelection) + { + EndVertexSnapping(); + UpdateGizmoPosition(); + } } } diff --git a/Source/Editor/SceneGraph/Actors/StaticModelNode.cs b/Source/Editor/SceneGraph/Actors/StaticModelNode.cs index f1ab36041..0a8fd48bb 100644 --- a/Source/Editor/SceneGraph/Actors/StaticModelNode.cs +++ b/Source/Editor/SceneGraph/Actors/StaticModelNode.cs @@ -23,20 +23,23 @@ namespace FlaxEditor.SceneGraph.Actors : base(actor) { } + /// - public override bool OnVertexSnap(ref Vector3 point, out Vector3 result) + public override bool OnVertexSnap(ref Ray ray, float hitDistance, out Vector3 result) { - result = point; + // Find the closest vertex to bounding box point (collision detection approximation) + + result = ray.GetPoint(hitDistance); var model = ((StaticModel)Actor).Model; if (model && !model.WaitForLoaded()) { // TODO: move to C++ and use cached vertex buffer internally inside the Mesh if (_vertices == null) _vertices = new(); - var pointLocal = (Float3)Actor.Transform.WorldToLocal(point); + var pointLocal = (Float3)Actor.Transform.WorldToLocal(result); var minDistance = float.MaxValue; - foreach (var lod in model.LODs) + foreach (var lod in model.LODs) //[ToDo] fix it [Nori_SC note] this is wrong it should get current lod level going it throw all lods will create ghost snaping points { var hit = false; foreach (var mesh in lod.Meshes) diff --git a/Source/Editor/SceneGraph/SceneGraphNode.cs b/Source/Editor/SceneGraph/SceneGraphNode.cs index 5cf28af37..e9020592d 100644 --- a/Source/Editor/SceneGraph/SceneGraphNode.cs +++ b/Source/Editor/SceneGraph/SceneGraphNode.cs @@ -94,18 +94,6 @@ namespace FlaxEditor.SceneGraph /// public virtual bool CanTransform => true; - /// - /// Gets a value indicating whether this node can be used for the vertex snapping feature. - /// - public bool CanVertexSnap - { - get - { - var v = Vector3.Zero; - return OnVertexSnap(ref v, out _); - } - } - /// /// Gets a value indicating whether this is active. /// @@ -365,14 +353,15 @@ namespace FlaxEditor.SceneGraph } /// - /// Performs the vertex snapping of a given point on the object surface that is closest to a given location. + /// Performs the vertex snapping for a given ray and hitDistance. /// - /// The position to snap. + /// Raycasted ray + /// Hit distance from ray to object bounding box /// The result point on the object mesh that is closest to the specified location. /// True if got a valid result value, otherwise false (eg. if missing data or not initialized). - public virtual bool OnVertexSnap(ref Vector3 point, out Vector3 result) + public virtual bool OnVertexSnap(ref Ray ray,float hitDistance, out Vector3 result) // [NoriSC note] ray and hit Distance will be needed for a future use, in mesh types for proper collision detection { - result = point; + result = Vector3.Zero; return false; }