Merge branch 'Zode-absolutesnap'
This commit is contained in:
@@ -75,6 +75,11 @@ namespace FlaxEditor.Gizmo
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ScaleSnapEnabled = false;
|
public bool ScaleSnapEnabled = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if enable absolute grid snapping (snaps objects to world-space grid, not the one relative to gizmo location)
|
||||||
|
/// </summary>
|
||||||
|
public bool AbsoluteSnapEnabled = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Translation snap value
|
/// Translation snap value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -2,8 +2,10 @@
|
|||||||
|
|
||||||
#if USE_LARGE_WORLDS
|
#if USE_LARGE_WORLDS
|
||||||
using Real = System.Double;
|
using Real = System.Double;
|
||||||
|
using Mathr = FlaxEngine.Mathd;
|
||||||
#else
|
#else
|
||||||
using Real = System.Single;
|
using Real = System.Single;
|
||||||
|
using Mathr = FlaxEngine.Mathf;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
@@ -40,6 +42,7 @@ namespace FlaxEditor.Gizmo
|
|||||||
private Vector3 _intersectPosition;
|
private Vector3 _intersectPosition;
|
||||||
private bool _isActive;
|
private bool _isActive;
|
||||||
private bool _isDuplicating;
|
private bool _isDuplicating;
|
||||||
|
private bool _hasAbsoluteSnapped;
|
||||||
|
|
||||||
private bool _isTransforming;
|
private bool _isTransforming;
|
||||||
private bool _isSelected;
|
private bool _isSelected;
|
||||||
@@ -366,6 +369,7 @@ namespace FlaxEditor.Gizmo
|
|||||||
if ((isScaling ? ScaleSnapEnabled : TranslationSnapEnable) || Owner.UseSnapping)
|
if ((isScaling ? ScaleSnapEnabled : TranslationSnapEnable) || Owner.UseSnapping)
|
||||||
{
|
{
|
||||||
var snapValue = new Vector3(isScaling ? ScaleSnapValue : TranslationSnapValue);
|
var snapValue = new Vector3(isScaling ? ScaleSnapValue : TranslationSnapValue);
|
||||||
|
|
||||||
_translationScaleSnapDelta += delta;
|
_translationScaleSnapDelta += delta;
|
||||||
if (!isScaling && snapValue.X < 0.0f)
|
if (!isScaling && snapValue.X < 0.0f)
|
||||||
{
|
{
|
||||||
@@ -384,11 +388,29 @@ namespace FlaxEditor.Gizmo
|
|||||||
else
|
else
|
||||||
snapValue.Z = (Real)b.Minimum.Z - b.Maximum.Z;
|
snapValue.Z = (Real)b.Minimum.Z - b.Maximum.Z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector3 absoluteDelta = Vector3.Zero;
|
||||||
|
if (!_hasAbsoluteSnapped && AbsoluteSnapEnabled && ActiveTransformSpace == TransformSpace.World)
|
||||||
|
{
|
||||||
|
// Remove delta to offset local-space grid into the world-space grid
|
||||||
|
_hasAbsoluteSnapped = true;
|
||||||
|
Vector3 currentTranslationScale = isScaling ? GetSelectedTransform(0).Scale : GetSelectedTransform(0).Translation;
|
||||||
|
absoluteDelta = currentTranslationScale - new Vector3(
|
||||||
|
Mathr.Round(currentTranslationScale.X / snapValue.X) * snapValue.X,
|
||||||
|
Mathr.Round(currentTranslationScale.Y / snapValue.Y) * snapValue.Y,
|
||||||
|
Mathr.Round(currentTranslationScale.Z / snapValue.Z) * snapValue.Z);
|
||||||
|
}
|
||||||
|
|
||||||
delta = new Vector3(
|
delta = new Vector3(
|
||||||
(int)(_translationScaleSnapDelta.X / snapValue.X) * snapValue.X,
|
(int)(_translationScaleSnapDelta.X / snapValue.X) * snapValue.X,
|
||||||
(int)(_translationScaleSnapDelta.Y / snapValue.Y) * snapValue.Y,
|
(int)(_translationScaleSnapDelta.Y / snapValue.Y) * snapValue.Y,
|
||||||
(int)(_translationScaleSnapDelta.Z / snapValue.Z) * snapValue.Z);
|
(int)(_translationScaleSnapDelta.Z / snapValue.Z) * snapValue.Z);
|
||||||
_translationScaleSnapDelta -= delta;
|
_translationScaleSnapDelta -= delta;
|
||||||
|
delta -= absoluteDelta;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_hasAbsoluteSnapped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_activeMode == Mode.Translate)
|
if (_activeMode == Mode.Translate)
|
||||||
@@ -418,12 +440,33 @@ namespace FlaxEditor.Gizmo
|
|||||||
if (RotationSnapEnabled || Owner.UseSnapping)
|
if (RotationSnapEnabled || Owner.UseSnapping)
|
||||||
{
|
{
|
||||||
float snapValue = RotationSnapValue * Mathf.DegreesToRadians;
|
float snapValue = RotationSnapValue * Mathf.DegreesToRadians;
|
||||||
|
|
||||||
|
float absoluteDelta = 0.0f;
|
||||||
|
if (!_hasAbsoluteSnapped && AbsoluteSnapEnabled && ActiveTransformSpace == TransformSpace.World)
|
||||||
|
{
|
||||||
|
// Remove delta to offset world-space grid into the local-space grid
|
||||||
|
_hasAbsoluteSnapped = true;
|
||||||
|
float currentAngle = 0.0f;
|
||||||
|
switch (_activeAxis)
|
||||||
|
{
|
||||||
|
case Axis.X: currentAngle = GetSelectedTransform(0).Orientation.EulerAngles.X; break;
|
||||||
|
case Axis.Y: currentAngle = GetSelectedTransform(0).Orientation.EulerAngles.Y; break;
|
||||||
|
case Axis.Z: currentAngle = GetSelectedTransform(0).Orientation.EulerAngles.Z; break;
|
||||||
|
}
|
||||||
|
absoluteDelta = currentAngle - (Mathf.Round(currentAngle / RotationSnapValue) * RotationSnapValue);
|
||||||
|
}
|
||||||
|
|
||||||
_rotationSnapDelta += delta;
|
_rotationSnapDelta += delta;
|
||||||
|
|
||||||
float snapped = Mathf.Round(_rotationSnapDelta / snapValue) * snapValue;
|
float snapped = Mathf.Round(_rotationSnapDelta / snapValue) * snapValue;
|
||||||
_rotationSnapDelta -= snapped;
|
_rotationSnapDelta -= snapped;
|
||||||
|
|
||||||
delta = snapped;
|
delta = snapped;
|
||||||
|
delta -= absoluteDelta * Mathf.DegreesToRadians;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_hasAbsoluteSnapped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (_activeAxis)
|
switch (_activeAxis)
|
||||||
|
|||||||
@@ -138,7 +138,9 @@ namespace FlaxEditor.Viewport
|
|||||||
if (useProjectCache)
|
if (useProjectCache)
|
||||||
{
|
{
|
||||||
// Initialize snapping enabled from cached values
|
// Initialize snapping enabled from cached values
|
||||||
if (editor.ProjectCache.TryGetCustomData("TranslateSnapState", out bool cachedBool))
|
if (editor.ProjectCache.TryGetCustomData("AbsoluteSnapState", out bool cachedBool))
|
||||||
|
transformGizmo.AbsoluteSnapEnabled = cachedBool;
|
||||||
|
if (editor.ProjectCache.TryGetCustomData("TranslateSnapState", out cachedBool))
|
||||||
transformGizmo.TranslationSnapEnable = cachedBool;
|
transformGizmo.TranslationSnapEnable = cachedBool;
|
||||||
if (editor.ProjectCache.TryGetCustomData("RotationSnapState", out cachedBool))
|
if (editor.ProjectCache.TryGetCustomData("RotationSnapState", out cachedBool))
|
||||||
transformGizmo.RotationSnapEnabled = cachedBool;
|
transformGizmo.RotationSnapEnabled = cachedBool;
|
||||||
@@ -162,13 +164,31 @@ namespace FlaxEditor.Viewport
|
|||||||
TooltipText = $"Gizmo transform space (world or local) ({inputOptions.ToggleTransformSpace})",
|
TooltipText = $"Gizmo transform space (world or local) ({inputOptions.ToggleTransformSpace})",
|
||||||
Parent = transformSpaceWidget
|
Parent = transformSpaceWidget
|
||||||
};
|
};
|
||||||
|
transformSpaceWidget.Parent = viewport;
|
||||||
|
|
||||||
|
// Absolute snapping widget
|
||||||
|
var absoluteSnappingWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight);
|
||||||
|
var enableAbsoluteSnapping = new ViewportWidgetButton("A", SpriteHandle.Invalid, null, true)
|
||||||
|
{
|
||||||
|
Checked = transformGizmo.AbsoluteSnapEnabled,
|
||||||
|
TooltipText = "Enable absolute grid snapping (world-space absolute grid, rather than object-relative grid)",
|
||||||
|
Parent = absoluteSnappingWidget
|
||||||
|
};
|
||||||
|
enableAbsoluteSnapping.Toggled += _ =>
|
||||||
|
{
|
||||||
|
transformGizmo.AbsoluteSnapEnabled = !transformGizmo.AbsoluteSnapEnabled;
|
||||||
|
if (useProjectCache)
|
||||||
|
editor.ProjectCache.SetCustomData("AbsoluteSnapState", transformGizmo.AbsoluteSnapEnabled);
|
||||||
|
};
|
||||||
|
absoluteSnappingWidget.Parent = viewport;
|
||||||
|
|
||||||
transformSpaceToggle.Toggled += _ =>
|
transformSpaceToggle.Toggled += _ =>
|
||||||
{
|
{
|
||||||
transformGizmo.ToggleTransformSpace();
|
transformGizmo.ToggleTransformSpace();
|
||||||
if (useProjectCache)
|
if (useProjectCache)
|
||||||
editor.ProjectCache.SetCustomData("TransformSpaceState", transformGizmo.ActiveTransformSpace.ToString());
|
editor.ProjectCache.SetCustomData("TransformSpaceState", transformGizmo.ActiveTransformSpace.ToString());
|
||||||
|
absoluteSnappingWidget.Visible = transformGizmo.ActiveTransformSpace == TransformGizmoBase.TransformSpace.World;
|
||||||
};
|
};
|
||||||
transformSpaceWidget.Parent = viewport;
|
|
||||||
|
|
||||||
// Scale snapping widget
|
// Scale snapping widget
|
||||||
var scaleSnappingWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight);
|
var scaleSnappingWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight);
|
||||||
@@ -383,17 +403,17 @@ namespace FlaxEditor.Viewport
|
|||||||
gizmoModeRotate.Checked = mode == TransformGizmoBase.Mode.Rotate;
|
gizmoModeRotate.Checked = mode == TransformGizmoBase.Mode.Rotate;
|
||||||
gizmoModeScale.Checked = mode == TransformGizmoBase.Mode.Scale;
|
gizmoModeScale.Checked = mode == TransformGizmoBase.Mode.Scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Setup input actions
|
// Setup input actions
|
||||||
viewport.InputActions.Add(options => options.TranslateMode, () =>
|
viewport.InputActions.Add(options => options.TranslateMode, () =>
|
||||||
{
|
{
|
||||||
viewport.GetInput(out var input);
|
viewport.GetInput(out var input);
|
||||||
if (input.IsMouseRightDown)
|
if (input.IsMouseRightDown)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
transformGizmo.ActiveMode = TransformGizmoBase.Mode.Translate;
|
transformGizmo.ActiveMode = TransformGizmoBase.Mode.Translate;
|
||||||
});
|
});
|
||||||
viewport.InputActions.Add(options => options.RotateMode, () =>
|
viewport.InputActions.Add(options => options.RotateMode, () =>
|
||||||
{
|
{
|
||||||
viewport.GetInput(out var input);
|
viewport.GetInput(out var input);
|
||||||
if (input.IsMouseRightDown)
|
if (input.IsMouseRightDown)
|
||||||
|
|||||||
Reference in New Issue
Block a user