diff --git a/Source/Editor/Gizmo/GizmoBase.cs b/Source/Editor/Gizmo/GizmoBase.cs
index a44c677dd..5dfa742bd 100644
--- a/Source/Editor/Gizmo/GizmoBase.cs
+++ b/Source/Editor/Gizmo/GizmoBase.cs
@@ -80,6 +80,13 @@ namespace FlaxEditor.Gizmo
{
}
+ ///
+ /// Performs scene objects snapping to the ground.
+ ///
+ public virtual void SnapToGround()
+ {
+ }
+
///
/// Draws the gizmo.
///
diff --git a/Source/Editor/Gizmo/IGizmoOwner.cs b/Source/Editor/Gizmo/IGizmoOwner.cs
index d3dc6cbc0..54983b3b8 100644
--- a/Source/Editor/Gizmo/IGizmoOwner.cs
+++ b/Source/Editor/Gizmo/IGizmoOwner.cs
@@ -89,5 +89,10 @@ namespace FlaxEditor.Gizmo
/// Gets a object used by the gizmo owner.
///
Undo Undo { get; }
+
+ ///
+ /// Gets the root tree node for the scene graph.
+ ///
+ SceneGraph.RootNode SceneGraphRoot { get; }
}
}
diff --git a/Source/Editor/Gizmo/TransformGizmo.cs b/Source/Editor/Gizmo/TransformGizmo.cs
index f490de430..6d7a2ccd3 100644
--- a/Source/Editor/Gizmo/TransformGizmo.cs
+++ b/Source/Editor/Gizmo/TransformGizmo.cs
@@ -218,6 +218,12 @@ namespace FlaxEditor.Gizmo
}
}
+ ///
+ protected override bool IsSelected(SceneGraphNode obj)
+ {
+ return _selection.Contains(obj);
+ }
+
///
protected override void OnApplyTransformation(ref Vector3 translationDelta, ref Quaternion rotationDelta, ref Vector3 scaleDelta)
{
diff --git a/Source/Editor/Gizmo/TransformGizmoBase.cs b/Source/Editor/Gizmo/TransformGizmoBase.cs
index 768fa0617..60fc7b816 100644
--- a/Source/Editor/Gizmo/TransformGizmoBase.cs
+++ b/Source/Editor/Gizmo/TransformGizmoBase.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using FlaxEditor.SceneGraph;
using FlaxEngine;
namespace FlaxEditor.Gizmo
@@ -398,15 +399,7 @@ namespace FlaxEditor.Gizmo
// Snap to ground
if (_activeAxis == Axis.None && SelectionCount != 0 && Owner.SnapToGround)
{
- if (Physics.RayCast(Position, Vector3.Down, out var hit, float.MaxValue, uint.MaxValue, false))
- {
- StartTransforming();
- var translationDelta = hit.Point - Position;
- var rotationDelta = Quaternion.Identity;
- var scaleDelta = Vector3.Zero;
- OnApplyTransformation(ref translationDelta, ref rotationDelta, ref scaleDelta);
- EndTransforming();
- }
+ SnapToGround();
}
// Only when is active
else if (_isActive)
@@ -517,6 +510,39 @@ namespace FlaxEditor.Gizmo
UpdateMatrices();
}
+ ///
+ public override void SnapToGround()
+ {
+ if (Owner.SceneGraphRoot == null)
+ return;
+ var ray = new Ray(Position, Vector3.Down);
+ while (true)
+ {
+ var view = new Ray(Owner.ViewPosition, Owner.ViewDirection);
+ var rayCastFlags = SceneGraphNode.RayCastData.FlagTypes.SkipEditorPrimitives;
+ var hit = Owner.SceneGraphRoot.RayCast(ref ray, ref view, out var distance, out _, rayCastFlags);
+ if (hit != null)
+ {
+ // Skip snapping selection to itself
+ if (IsSelected(hit))
+ {
+ GetSelectedObjectsBounds(out var selectionBounds, out _);
+ ray.Position = ray.GetPoint(selectionBounds.Size.Y * 0.5f);
+ continue;
+ }
+
+ // Snap
+ StartTransforming();
+ var translationDelta = ray.GetPoint(distance) - Position;
+ var rotationDelta = Quaternion.Identity;
+ var scaleDelta = Vector3.Zero;
+ OnApplyTransformation(ref translationDelta, ref rotationDelta, ref scaleDelta);
+ EndTransforming();
+ }
+ break;
+ }
+ }
+
///
/// Gets a value indicating whether this tool can transform objects.
///
@@ -545,6 +571,13 @@ namespace FlaxEditor.Gizmo
/// True if editing the selected objects transformations marks the navigation system area dirty (for auto-rebuild), otherwise skip update.
protected abstract void GetSelectedObjectsBounds(out BoundingBox bounds, out bool navigationDirty);
+ ///
+ /// Checks if the specified object is selected.
+ ///
+ /// The object to check.
+ /// True if it's selected, otherwise false.
+ protected abstract bool IsSelected(SceneGraphNode obj);
+
///
/// Called when user starts transforming selected objects.
///
diff --git a/Source/Editor/Tools/Foliage/EditFoliageGizmo.cs b/Source/Editor/Tools/Foliage/EditFoliageGizmo.cs
index 7443b52ad..5401000c9 100644
--- a/Source/Editor/Tools/Foliage/EditFoliageGizmo.cs
+++ b/Source/Editor/Tools/Foliage/EditFoliageGizmo.cs
@@ -2,6 +2,7 @@
using System;
using FlaxEditor.Gizmo;
+using FlaxEditor.SceneGraph;
using FlaxEditor.Tools.Foliage.Undo;
using FlaxEngine;
@@ -87,6 +88,12 @@ namespace FlaxEditor.Tools.Foliage
navigationDirty = false;
}
+ ///
+ protected override bool IsSelected(SceneGraphNode obj)
+ {
+ return false;
+ }
+
///
protected override void OnStartTransforming()
{
@@ -231,6 +238,21 @@ namespace FlaxEditor.Tools.Foliage
Owner.Undo?.AddAction(action);
}
+ ///
+ public override void SnapToGround()
+ {
+ if (Physics.RayCast(Position, Vector3.Down, out var hit, float.MaxValue, uint.MaxValue, false))
+ {
+ // Snap
+ StartTransforming();
+ var translationDelta = hit.Point - Position;
+ var rotationDelta = Quaternion.Identity;
+ var scaleDelta = Vector3.Zero;
+ OnApplyTransformation(ref translationDelta, ref rotationDelta, ref scaleDelta);
+ EndTransforming();
+ }
+ }
+
///
public override void OnActivated()
{
diff --git a/Source/Editor/Viewport/EditorGizmoViewport.cs b/Source/Editor/Viewport/EditorGizmoViewport.cs
index 5c9fcf034..0e81292a3 100644
--- a/Source/Editor/Viewport/EditorGizmoViewport.cs
+++ b/Source/Editor/Viewport/EditorGizmoViewport.cs
@@ -21,10 +21,12 @@ namespace FlaxEditor.Viewport
///
/// The task.
/// The undo.
- public EditorGizmoViewport(SceneRenderTask task, Undo undo)
+ /// The scene graph root.
+ public EditorGizmoViewport(SceneRenderTask task, Undo undo, SceneGraph.RootNode sceneGraphRoot)
: base(task, new FPSCamera(), true)
{
Undo = undo;
+ SceneGraphRoot = sceneGraphRoot;
SetUpdate(ref _update, OnUpdate);
}
@@ -73,6 +75,9 @@ namespace FlaxEditor.Viewport
///
public Undo Undo { get; }
+ ///
+ public SceneGraph.RootNode SceneGraphRoot { get; }
+
///
protected override bool IsControllingMouse => Gizmos.Active?.IsControllingMouse ?? false;
diff --git a/Source/Editor/Viewport/MainEditorGizmoViewport.cs b/Source/Editor/Viewport/MainEditorGizmoViewport.cs
index 0c759c950..e29b97dc7 100644
--- a/Source/Editor/Viewport/MainEditorGizmoViewport.cs
+++ b/Source/Editor/Viewport/MainEditorGizmoViewport.cs
@@ -184,7 +184,7 @@ namespace FlaxEditor.Viewport
///
/// Editor instance.
public MainEditorGizmoViewport(Editor editor)
- : base(Object.New(), editor.Undo)
+ : base(Object.New(), editor.Undo, editor.Scene.Root)
{
_editor = editor;
_dragAssets = new DragAssets(ValidateDragItem);
diff --git a/Source/Editor/Viewport/PrefabWindowViewport.cs b/Source/Editor/Viewport/PrefabWindowViewport.cs
index 4e71677b2..9b2c9b189 100644
--- a/Source/Editor/Viewport/PrefabWindowViewport.cs
+++ b/Source/Editor/Viewport/PrefabWindowViewport.cs
@@ -336,6 +336,9 @@ namespace FlaxEditor.Viewport
///
public Undo Undo { get; }
+ ///
+ public RootNode SceneGraphRoot => _window.Graph.Root;
+
///
public EditorViewport Viewport => this;