diff --git a/Source/Editor/Viewport/EditorGizmoViewport.cs b/Source/Editor/Viewport/EditorGizmoViewport.cs index 25dcd76e7..856ae20da 100644 --- a/Source/Editor/Viewport/EditorGizmoViewport.cs +++ b/Source/Editor/Viewport/EditorGizmoViewport.cs @@ -1,9 +1,12 @@ // Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. +using System; using System.Collections.Generic; using FlaxEditor.Gizmo; +using FlaxEditor.GUI.ContextMenu; using FlaxEditor.SceneGraph; using FlaxEditor.Viewport.Cameras; +using FlaxEditor.Viewport.Widgets; using FlaxEngine; using FlaxEngine.GUI; @@ -126,6 +129,249 @@ namespace FlaxEditor.Viewport base.OnDestroy(); } + internal static void AddGizmoViewportWidgets(EditorViewport viewport, TransformGizmo transformGizmo, bool useProjectCache = false) + { + var editor = Editor.Instance; + var inputOptions = editor.Options.Options.Input; + + if (useProjectCache) + { + // Initialize snapping enabled from cached values + if (editor.ProjectCache.TryGetCustomData("TranslateSnapState", out var cachedState)) + transformGizmo.TranslationSnapEnable = bool.Parse(cachedState); + if (editor.ProjectCache.TryGetCustomData("RotationSnapState", out cachedState)) + transformGizmo.RotationSnapEnabled = bool.Parse(cachedState); + if (editor.ProjectCache.TryGetCustomData("ScaleSnapState", out cachedState)) + transformGizmo.ScaleSnapEnabled = bool.Parse(cachedState); + if (editor.ProjectCache.TryGetCustomData("TranslateSnapValue", out cachedState)) + transformGizmo.TranslationSnapValue = float.Parse(cachedState); + if (editor.ProjectCache.TryGetCustomData("RotationSnapValue", out cachedState)) + transformGizmo.RotationSnapValue = float.Parse(cachedState); + if (editor.ProjectCache.TryGetCustomData("ScaleSnapValue", out cachedState)) + transformGizmo.ScaleSnapValue = float.Parse(cachedState); + if (editor.ProjectCache.TryGetCustomData("TransformSpaceState", out cachedState) && Enum.TryParse(cachedState, out TransformGizmoBase.TransformSpace space)) + transformGizmo.ActiveTransformSpace = space; + } + + // Transform space widget + var transformSpaceWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); + var transformSpaceToggle = new ViewportWidgetButton(string.Empty, editor.Icons.Globe32, null, true) + { + Checked = transformGizmo.ActiveTransformSpace == TransformGizmoBase.TransformSpace.World, + TooltipText = $"Gizmo transform space (world or local) ({inputOptions.ToggleTransformSpace})", + Parent = transformSpaceWidget + }; + transformSpaceToggle.Toggled += _ => + { + transformGizmo.ToggleTransformSpace(); + if (useProjectCache) + editor.ProjectCache.SetCustomData("TransformSpaceState", transformGizmo.ActiveTransformSpace.ToString()); + }; + transformSpaceWidget.Parent = viewport; + + // Scale snapping widget + var scaleSnappingWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); + var enableScaleSnapping = new ViewportWidgetButton(string.Empty, editor.Icons.ScaleSnap32, null, true) + { + Checked = transformGizmo.ScaleSnapEnabled, + TooltipText = "Enable scale snapping", + Parent = scaleSnappingWidget + }; + enableScaleSnapping.Toggled += _ => + { + transformGizmo.ScaleSnapEnabled = !transformGizmo.ScaleSnapEnabled; + if (useProjectCache) + editor.ProjectCache.SetCustomData("ScaleSnapState", transformGizmo.ScaleSnapEnabled.ToString()); + }; + var scaleSnappingCM = new ContextMenu(); + var scaleSnapping = new ViewportWidgetButton(transformGizmo.ScaleSnapValue.ToString(), SpriteHandle.Invalid, scaleSnappingCM) + { + TooltipText = "Scale snapping values" + }; + for (int i = 0; i < ScaleSnapValues.Length; i++) + { + var v = ScaleSnapValues[i]; + var button = scaleSnappingCM.AddButton(v.ToString()); + button.Tag = v; + } + scaleSnappingCM.ButtonClicked += button => + { + var v = (float)button.Tag; + transformGizmo.ScaleSnapValue = v; + scaleSnapping.Text = v.ToString(); + if (useProjectCache) + editor.ProjectCache.SetCustomData("ScaleSnapValue", transformGizmo.ScaleSnapValue.ToString("N")); + }; + scaleSnappingCM.VisibleChanged += control => + { + if (control.Visible == false) + return; + var ccm = (ContextMenu)control; + foreach (var e in ccm.Items) + { + if (e is ContextMenuButton b) + { + var v = (float)b.Tag; + b.Icon = Mathf.Abs(transformGizmo.ScaleSnapValue - v) < 0.001f ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; + } + } + }; + scaleSnapping.Parent = scaleSnappingWidget; + scaleSnappingWidget.Parent = viewport; + + // Rotation snapping widget + var rotateSnappingWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); + var enableRotateSnapping = new ViewportWidgetButton(string.Empty, editor.Icons.RotateSnap32, null, true) + { + Checked = transformGizmo.RotationSnapEnabled, + TooltipText = "Enable rotation snapping", + Parent = rotateSnappingWidget + }; + enableRotateSnapping.Toggled += _ => + { + transformGizmo.RotationSnapEnabled = !transformGizmo.RotationSnapEnabled; + if (useProjectCache) + editor.ProjectCache.SetCustomData("RotationSnapState", transformGizmo.RotationSnapEnabled.ToString()); + }; + var rotateSnappingCM = new ContextMenu(); + var rotateSnapping = new ViewportWidgetButton(transformGizmo.RotationSnapValue.ToString(), SpriteHandle.Invalid, rotateSnappingCM) + { + TooltipText = "Rotation snapping values" + }; + for (int i = 0; i < RotateSnapValues.Length; i++) + { + var v = RotateSnapValues[i]; + var button = rotateSnappingCM.AddButton(v.ToString()); + button.Tag = v; + } + rotateSnappingCM.ButtonClicked += button => + { + var v = (float)button.Tag; + transformGizmo.RotationSnapValue = v; + rotateSnapping.Text = v.ToString(); + if (useProjectCache) + editor.ProjectCache.SetCustomData("RotationSnapValue", transformGizmo.RotationSnapValue.ToString("N")); + }; + rotateSnappingCM.VisibleChanged += control => + { + if (control.Visible == false) + return; + var ccm = (ContextMenu)control; + foreach (var e in ccm.Items) + { + if (e is ContextMenuButton b) + { + var v = (float)b.Tag; + b.Icon = Mathf.Abs(transformGizmo.RotationSnapValue - v) < 0.001f ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; + } + } + }; + rotateSnapping.Parent = rotateSnappingWidget; + rotateSnappingWidget.Parent = viewport; + + // Translation snapping widget + var translateSnappingWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); + var enableTranslateSnapping = new ViewportWidgetButton(string.Empty, editor.Icons.Grid32, null, true) + { + Checked = transformGizmo.TranslationSnapEnable, + TooltipText = "Enable position snapping", + Parent = translateSnappingWidget + }; + enableTranslateSnapping.Toggled += _ => + { + transformGizmo.TranslationSnapEnable = !transformGizmo.TranslationSnapEnable; + if (useProjectCache) + editor.ProjectCache.SetCustomData("TranslateSnapState", transformGizmo.TranslationSnapEnable.ToString()); + }; + var translateSnappingCM = new ContextMenu(); + var translateSnapping = new ViewportWidgetButton(transformGizmo.TranslationSnapValue.ToString(), SpriteHandle.Invalid, translateSnappingCM) + { + TooltipText = "Position snapping values" + }; + if (transformGizmo.TranslationSnapValue < 0.0f) + translateSnapping.Text = "Bounding Box"; + for (int i = 0; i < TranslateSnapValues.Length; i++) + { + var v = TranslateSnapValues[i]; + var button = translateSnappingCM.AddButton(v.ToString()); + button.Tag = v; + } + var buttonBB = translateSnappingCM.AddButton("Bounding Box").LinkTooltip("Snaps the selection based on it's bounding volume"); + buttonBB.Tag = -1.0f; + translateSnappingCM.ButtonClicked += button => + { + var v = (float)button.Tag; + transformGizmo.TranslationSnapValue = v; + if (v < 0.0f) + translateSnapping.Text = "Bounding Box"; + else + translateSnapping.Text = v.ToString(); + if (useProjectCache) + editor.ProjectCache.SetCustomData("TranslateSnapValue", transformGizmo.TranslationSnapValue.ToString("N")); + }; + translateSnappingCM.VisibleChanged += control => + { + if (control.Visible == false) + return; + var ccm = (ContextMenu)control; + foreach (var e in ccm.Items) + { + if (e is ContextMenuButton b) + { + var v = (float)b.Tag; + b.Icon = Mathf.Abs(transformGizmo.TranslationSnapValue - v) < 0.001f ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; + } + } + }; + translateSnapping.Parent = translateSnappingWidget; + translateSnappingWidget.Parent = viewport; + + // Gizmo mode widget + var gizmoMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); + var gizmoModeTranslate = new ViewportWidgetButton(string.Empty, editor.Icons.Translate32, null, true) + { + Tag = TransformGizmoBase.Mode.Translate, + TooltipText = $"Translate gizmo mode ({inputOptions.TranslateMode})", + Checked = true, + Parent = gizmoMode + }; + gizmoModeTranslate.Toggled += _ => transformGizmo.ActiveMode = TransformGizmoBase.Mode.Translate; + var gizmoModeRotate = new ViewportWidgetButton(string.Empty, editor.Icons.Rotate32, null, true) + { + Tag = TransformGizmoBase.Mode.Rotate, + TooltipText = $"Rotate gizmo mode ({inputOptions.RotateMode})", + Parent = gizmoMode + }; + gizmoModeRotate.Toggled += _ => transformGizmo.ActiveMode = TransformGizmoBase.Mode.Rotate; + var gizmoModeScale = new ViewportWidgetButton(string.Empty, editor.Icons.Scale32, null, true) + { + Tag = TransformGizmoBase.Mode.Scale, + TooltipText = $"Scale gizmo mode ({inputOptions.ScaleMode})", + Parent = gizmoMode + }; + gizmoModeScale.Toggled += _ => transformGizmo.ActiveMode = TransformGizmoBase.Mode.Scale; + gizmoMode.Parent = viewport; + transformGizmo.ModeChanged += () => + { + var mode = transformGizmo.ActiveMode; + gizmoModeTranslate.Checked = mode == TransformGizmoBase.Mode.Translate; + gizmoModeRotate.Checked = mode == TransformGizmoBase.Mode.Rotate; + gizmoModeScale.Checked = mode == TransformGizmoBase.Mode.Scale; + }; + + // Setup input actions + viewport.InputActions.Add(options => options.TranslateMode, () => transformGizmo.ActiveMode = TransformGizmoBase.Mode.Translate); + viewport.InputActions.Add(options => options.RotateMode, () => transformGizmo.ActiveMode = TransformGizmoBase.Mode.Rotate); + viewport.InputActions.Add(options => options.ScaleMode, () => transformGizmo.ActiveMode = TransformGizmoBase.Mode.Scale); + viewport.InputActions.Add(options => options.ToggleTransformSpace, () => + { + transformGizmo.ToggleTransformSpace(); + if (useProjectCache) + editor.ProjectCache.SetCustomData("TransformSpaceState", transformGizmo.ActiveTransformSpace.ToString()); + transformSpaceToggle.Checked = !transformSpaceToggle.Checked; + }); + } + internal static readonly float[] TranslateSnapValues = { 0.1f, diff --git a/Source/Editor/Viewport/EditorViewport.cs b/Source/Editor/Viewport/EditorViewport.cs index a53f95ea8..2eeb1e8c0 100644 --- a/Source/Editor/Viewport/EditorViewport.cs +++ b/Source/Editor/Viewport/EditorViewport.cs @@ -704,9 +704,9 @@ namespace FlaxEditor.Viewport // Camera Viewpoints { var cameraView = cameraCM.AddChildMenu("Viewpoints").ContextMenu; - for (int i = 0; i < EditorViewportCameraViewpointValues.Length; i++) + for (int i = 0; i < CameraViewpointValues.Length; i++) { - var co = EditorViewportCameraViewpointValues[i]; + var co = CameraViewpointValues[i]; var button = cameraView.AddButton(co.Name); button.Tag = co.Orientation; } @@ -899,9 +899,9 @@ namespace FlaxEditor.Viewport viewFlags.AddButton("Reset flags", () => Task.ViewFlags = ViewFlags.DefaultEditor).Icon = Editor.Instance.Icons.Rotate32; viewFlags.AddButton("Disable flags", () => Task.ViewFlags = ViewFlags.None).Icon = Editor.Instance.Icons.Rotate32; viewFlags.AddSeparator(); - for (int i = 0; i < EditorViewportViewFlagsValues.Length; i++) + for (int i = 0; i < ViewFlagsValues.Length; i++) { - var v = EditorViewportViewFlagsValues[i]; + var v = ViewFlagsValues[i]; var button = viewFlags.AddButton(v.Name); button.CloseMenuOnClick = false; button.Tag = v.Mode; @@ -933,9 +933,9 @@ namespace FlaxEditor.Viewport } }); debugView.AddSeparator(); - for (int i = 0; i < EditorViewportViewModeValues.Length; i++) + for (int i = 0; i < ViewModeValues.Length; i++) { - ref var v = ref EditorViewportViewModeValues[i]; + ref var v = ref ViewModeValues[i]; if (v.Options != null) { var childMenu = debugView.AddChildMenu(v.Name).ContextMenu; @@ -989,12 +989,12 @@ namespace FlaxEditor.Viewport #endregion View mode widget } - InputActions.Add(options => options.ViewpointTop, () => OrientViewport(Quaternion.Euler(EditorViewportCameraViewpointValues.First(vp => vp.Name == "Top").Orientation))); - InputActions.Add(options => options.ViewpointBottom, () => OrientViewport(Quaternion.Euler(EditorViewportCameraViewpointValues.First(vp => vp.Name == "Bottom").Orientation))); - InputActions.Add(options => options.ViewpointFront, () => OrientViewport(Quaternion.Euler(EditorViewportCameraViewpointValues.First(vp => vp.Name == "Front").Orientation))); - InputActions.Add(options => options.ViewpointBack, () => OrientViewport(Quaternion.Euler(EditorViewportCameraViewpointValues.First(vp => vp.Name == "Back").Orientation))); - InputActions.Add(options => options.ViewpointRight, () => OrientViewport(Quaternion.Euler(EditorViewportCameraViewpointValues.First(vp => vp.Name == "Right").Orientation))); - InputActions.Add(options => options.ViewpointLeft, () => OrientViewport(Quaternion.Euler(EditorViewportCameraViewpointValues.First(vp => vp.Name == "Left").Orientation))); + InputActions.Add(options => options.ViewpointTop, () => OrientViewport(Quaternion.Euler(CameraViewpointValues.First(vp => vp.Name == "Top").Orientation))); + InputActions.Add(options => options.ViewpointBottom, () => OrientViewport(Quaternion.Euler(CameraViewpointValues.First(vp => vp.Name == "Bottom").Orientation))); + InputActions.Add(options => options.ViewpointFront, () => OrientViewport(Quaternion.Euler(CameraViewpointValues.First(vp => vp.Name == "Front").Orientation))); + InputActions.Add(options => options.ViewpointBack, () => OrientViewport(Quaternion.Euler(CameraViewpointValues.First(vp => vp.Name == "Back").Orientation))); + InputActions.Add(options => options.ViewpointRight, () => OrientViewport(Quaternion.Euler(CameraViewpointValues.First(vp => vp.Name == "Right").Orientation))); + InputActions.Add(options => options.ViewpointLeft, () => OrientViewport(Quaternion.Euler(CameraViewpointValues.First(vp => vp.Name == "Left").Orientation))); InputActions.Add(options => options.CameraToggleRotation, () => _isVirtualMouseRightDown = !_isVirtualMouseRightDown); InputActions.Add(options => options.CameraIncreaseMoveSpeed, () => AdjustCameraMoveSpeed(1)); InputActions.Add(options => options.CameraDecreaseMoveSpeed, () => AdjustCameraMoveSpeed(-1)); @@ -1870,7 +1870,7 @@ namespace FlaxEditor.Viewport } } - private readonly CameraViewpoint[] EditorViewportCameraViewpointValues = + private readonly CameraViewpoint[] CameraViewpointValues = { new CameraViewpoint("Front", new Float3(0, 180, 0)), new CameraViewpoint("Back", new Float3(0, 0, 0)), @@ -1901,7 +1901,7 @@ namespace FlaxEditor.Viewport } } - private static readonly ViewModeOptions[] EditorViewportViewModeValues = + private static readonly ViewModeOptions[] ViewModeValues = { new ViewModeOptions(ViewMode.Default, "Default"), new ViewModeOptions(ViewMode.Unlit, "Unlit"), @@ -1973,7 +1973,7 @@ namespace FlaxEditor.Viewport } } - private static readonly ViewFlagOptions[] EditorViewportViewFlagsValues = + private static readonly ViewFlagOptions[] ViewFlagsValues = { new ViewFlagOptions(ViewFlags.AntiAliasing, "Anti Aliasing"), new ViewFlagOptions(ViewFlags.Shadows, "Shadows"), @@ -2008,16 +2008,13 @@ namespace FlaxEditor.Viewport { if (cm.Visible == false) return; - var ccm = (ContextMenu)cm; foreach (var e in ccm.Items) { if (e is ContextMenuButton b && b.Tag != null) { var v = (ViewFlags)b.Tag; - b.Icon = (Task.View.Flags & v) != 0 - ? Style.Current.CheckBoxTick - : SpriteHandle.Invalid; + b.Icon = (Task.View.Flags & v) != 0 ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; } } } @@ -2026,7 +2023,6 @@ namespace FlaxEditor.Viewport { if (cm.Visible == false) return; - var ccm = (ContextMenu)cm; var layersMask = Task.ViewLayersMask; foreach (var e in ccm.Items) diff --git a/Source/Editor/Viewport/MainEditorGizmoViewport.cs b/Source/Editor/Viewport/MainEditorGizmoViewport.cs index c9bb4c88a..7d08213fa 100644 --- a/Source/Editor/Viewport/MainEditorGizmoViewport.cs +++ b/Source/Editor/Viewport/MainEditorGizmoViewport.cs @@ -7,9 +7,7 @@ using FlaxEditor.Gizmo; using FlaxEditor.GUI.ContextMenu; using FlaxEditor.SceneGraph; using FlaxEditor.Scripting; -using FlaxEditor.Viewport.Cameras; using FlaxEditor.Viewport.Modes; -using FlaxEditor.Viewport.Widgets; using FlaxEditor.Windows; using FlaxEngine; using FlaxEngine.GUI; @@ -27,13 +25,6 @@ namespace FlaxEditor.Viewport private readonly ContextMenuButton _showGridButton; private readonly ContextMenuButton _showNavigationButton; - private readonly ViewportWidgetButton _gizmoModeTranslate; - private readonly ViewportWidgetButton _gizmoModeRotate; - private readonly ViewportWidgetButton _gizmoModeScale; - - private readonly ViewportWidgetButton _translateSnapping; - private readonly ViewportWidgetButton _rotateSnapping; - private readonly ViewportWidgetButton _scaleSnapping; private SelectionOutline _customSelectionOutline; @@ -195,7 +186,6 @@ namespace FlaxEditor.Viewport { _editor = editor; DragHandlers = new ViewportDragHandlers(this, this, ValidateDragItem, ValidateDragActorType, ValidateDragScriptItem); - var inputOptions = editor.Options.Options.Input; // Prepare rendering task Task.ActorsSource = ActorsSources.Scenes; @@ -221,7 +211,6 @@ namespace FlaxEditor.Viewport // Add transformation gizmo TransformGizmo = new TransformGizmo(this); TransformGizmo.ApplyTransformation += ApplyTransform; - TransformGizmo.ModeChanged += OnGizmoModeChanged; TransformGizmo.Duplicate += _editor.SceneEditing.Duplicate; Gizmos.Active = TransformGizmo; @@ -231,137 +220,8 @@ namespace FlaxEditor.Viewport editor.SceneEditing.SelectionChanged += OnSelectionChanged; - // Initialize snapping enabled from cached values - if (_editor.ProjectCache.TryGetCustomData("TranslateSnapState", out var cachedState)) - TransformGizmo.TranslationSnapEnable = bool.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("RotationSnapState", out cachedState)) - TransformGizmo.RotationSnapEnabled = bool.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("ScaleSnapState", out cachedState)) - TransformGizmo.ScaleSnapEnabled = bool.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("TranslateSnapValue", out cachedState)) - TransformGizmo.TranslationSnapValue = float.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("RotationSnapValue", out cachedState)) - TransformGizmo.RotationSnapValue = float.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("ScaleSnapValue", out cachedState)) - TransformGizmo.ScaleSnapValue = float.Parse(cachedState); - if (_editor.ProjectCache.TryGetCustomData("TransformSpaceState", out cachedState) && Enum.TryParse(cachedState, out TransformGizmoBase.TransformSpace space)) - TransformGizmo.ActiveTransformSpace = space; - - // Transform space widget - var transformSpaceWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); - var transformSpaceToggle = new ViewportWidgetButton(string.Empty, editor.Icons.Globe32, null, true) - { - Checked = TransformGizmo.ActiveTransformSpace == TransformGizmoBase.TransformSpace.World, - TooltipText = $"Gizmo transform space (world or local) ({inputOptions.ToggleTransformSpace})", - Parent = transformSpaceWidget - }; - transformSpaceToggle.Toggled += OnTransformSpaceToggle; - transformSpaceWidget.Parent = this; - - // Scale snapping widget - var scaleSnappingWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); - var enableScaleSnapping = new ViewportWidgetButton(string.Empty, editor.Icons.ScaleSnap32, null, true) - { - Checked = TransformGizmo.ScaleSnapEnabled, - TooltipText = "Enable scale snapping", - Parent = scaleSnappingWidget - }; - enableScaleSnapping.Toggled += OnScaleSnappingToggle; - var scaleSnappingCM = new ContextMenu(); - _scaleSnapping = new ViewportWidgetButton(TransformGizmo.ScaleSnapValue.ToString(), SpriteHandle.Invalid, scaleSnappingCM) - { - TooltipText = "Scale snapping values" - }; - for (int i = 0; i < ScaleSnapValues.Length; i++) - { - var v = ScaleSnapValues[i]; - var button = scaleSnappingCM.AddButton(v.ToString()); - button.Tag = v; - } - scaleSnappingCM.ButtonClicked += OnWidgetScaleSnapClick; - scaleSnappingCM.VisibleChanged += OnWidgetScaleSnapShowHide; - _scaleSnapping.Parent = scaleSnappingWidget; - scaleSnappingWidget.Parent = this; - - // Rotation snapping widget - var rotateSnappingWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); - var enableRotateSnapping = new ViewportWidgetButton(string.Empty, editor.Icons.RotateSnap32, null, true) - { - Checked = TransformGizmo.RotationSnapEnabled, - TooltipText = "Enable rotation snapping", - Parent = rotateSnappingWidget - }; - enableRotateSnapping.Toggled += OnRotateSnappingToggle; - var rotateSnappingCM = new ContextMenu(); - _rotateSnapping = new ViewportWidgetButton(TransformGizmo.RotationSnapValue.ToString(), SpriteHandle.Invalid, rotateSnappingCM) - { - TooltipText = "Rotation snapping values" - }; - for (int i = 0; i < RotateSnapValues.Length; i++) - { - var v = RotateSnapValues[i]; - var button = rotateSnappingCM.AddButton(v.ToString()); - button.Tag = v; - } - rotateSnappingCM.ButtonClicked += OnWidgetRotateSnapClick; - rotateSnappingCM.VisibleChanged += OnWidgetRotateSnapShowHide; - _rotateSnapping.Parent = rotateSnappingWidget; - rotateSnappingWidget.Parent = this; - - // Translation snapping widget - var translateSnappingWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); - var enableTranslateSnapping = new ViewportWidgetButton(string.Empty, editor.Icons.Grid32, null, true) - { - Checked = TransformGizmo.TranslationSnapEnable, - TooltipText = "Enable position snapping", - Parent = translateSnappingWidget - }; - enableTranslateSnapping.Toggled += OnTranslateSnappingToggle; - var translateSnappingCM = new ContextMenu(); - _translateSnapping = new ViewportWidgetButton(TransformGizmo.TranslationSnapValue.ToString(), SpriteHandle.Invalid, translateSnappingCM) - { - TooltipText = "Position snapping values" - }; - if (TransformGizmo.TranslationSnapValue < 0.0f) - _translateSnapping.Text = "Bounding Box"; - for (int i = 0; i < TranslateSnapValues.Length; i++) - { - var v = TranslateSnapValues[i]; - var button = translateSnappingCM.AddButton(v.ToString()); - button.Tag = v; - } - var buttonBB = translateSnappingCM.AddButton("Bounding Box").LinkTooltip("Snaps the selection based on it's bounding volume"); - buttonBB.Tag = -1.0f; - translateSnappingCM.ButtonClicked += OnWidgetTranslateSnapClick; - translateSnappingCM.VisibleChanged += OnWidgetTranslateSnapShowHide; - _translateSnapping.Parent = translateSnappingWidget; - translateSnappingWidget.Parent = this; - - // Gizmo mode widget - var gizmoMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); - _gizmoModeTranslate = new ViewportWidgetButton(string.Empty, editor.Icons.Translate32, null, true) - { - Tag = TransformGizmoBase.Mode.Translate, - TooltipText = $"Translate gizmo mode ({inputOptions.TranslateMode})", - Checked = true, - Parent = gizmoMode - }; - _gizmoModeTranslate.Toggled += OnGizmoModeToggle; - _gizmoModeRotate = new ViewportWidgetButton(string.Empty, editor.Icons.Rotate32, null, true) - { - Tag = TransformGizmoBase.Mode.Rotate, - TooltipText = $"Rotate gizmo mode ({inputOptions.RotateMode})", - Parent = gizmoMode - }; - _gizmoModeRotate.Toggled += OnGizmoModeToggle; - _gizmoModeScale = new ViewportWidgetButton(string.Empty, editor.Icons.Scale32, null, true) - { - Tag = TransformGizmoBase.Mode.Scale, - TooltipText = $"Scale gizmo mode ({inputOptions.ScaleMode})", - Parent = gizmoMode - }; - _gizmoModeScale.Toggled += OnGizmoModeToggle; - gizmoMode.Parent = this; + // Gizmo widgets + AddGizmoViewportWidgets(this, TransformGizmo); // Show grid widget _showGridButton = ViewWidgetShowMenu.AddButton("Grid", () => Grid.Enabled = !Grid.Enabled); @@ -392,14 +252,6 @@ namespace FlaxEditor.Viewport } // Setup input actions - InputActions.Add(options => options.TranslateMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Translate); - InputActions.Add(options => options.RotateMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Rotate); - InputActions.Add(options => options.ScaleMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Scale); - InputActions.Add(options => options.ToggleTransformSpace, () => - { - OnTransformSpaceToggle(transformSpaceToggle); - transformSpaceToggle.Checked = !transformSpaceToggle.Checked; - }); InputActions.Add(options => options.LockFocusSelection, LockFocusSelection); InputActions.Add(options => options.FocusSelection, FocusSelection); InputActions.Add(options => options.RotateSelection, RotateSelection); @@ -573,119 +425,6 @@ namespace FlaxEditor.Viewport } } - private void OnGizmoModeToggle(ViewportWidgetButton button) - { - TransformGizmo.ActiveMode = (TransformGizmoBase.Mode)(int)button.Tag; - } - - private void OnTranslateSnappingToggle(ViewportWidgetButton button) - { - TransformGizmo.TranslationSnapEnable = !TransformGizmo.TranslationSnapEnable; - _editor.ProjectCache.SetCustomData("TranslateSnapState", TransformGizmo.TranslationSnapEnable.ToString()); - } - - private void OnRotateSnappingToggle(ViewportWidgetButton button) - { - TransformGizmo.RotationSnapEnabled = !TransformGizmo.RotationSnapEnabled; - _editor.ProjectCache.SetCustomData("RotationSnapState", TransformGizmo.RotationSnapEnabled.ToString()); - } - - private void OnScaleSnappingToggle(ViewportWidgetButton button) - { - TransformGizmo.ScaleSnapEnabled = !TransformGizmo.ScaleSnapEnabled; - _editor.ProjectCache.SetCustomData("ScaleSnapState", TransformGizmo.ScaleSnapEnabled.ToString()); - } - - private void OnTransformSpaceToggle(ViewportWidgetButton button) - { - TransformGizmo.ToggleTransformSpace(); - _editor.ProjectCache.SetCustomData("TransformSpaceState", TransformGizmo.ActiveTransformSpace.ToString()); - } - - private void OnGizmoModeChanged() - { - // Update all viewport widgets status - var mode = TransformGizmo.ActiveMode; - _gizmoModeTranslate.Checked = mode == TransformGizmoBase.Mode.Translate; - _gizmoModeRotate.Checked = mode == TransformGizmoBase.Mode.Rotate; - _gizmoModeScale.Checked = mode == TransformGizmoBase.Mode.Scale; - } - - private void OnWidgetScaleSnapClick(ContextMenuButton button) - { - var v = (float)button.Tag; - TransformGizmo.ScaleSnapValue = v; - _scaleSnapping.Text = v.ToString(); - _editor.ProjectCache.SetCustomData("ScaleSnapValue", TransformGizmo.ScaleSnapValue.ToString("N")); - } - - private void OnWidgetScaleSnapShowHide(Control control) - { - if (control.Visible == false) - return; - - var ccm = (ContextMenu)control; - foreach (var e in ccm.Items) - { - if (e is ContextMenuButton b) - { - var v = (float)b.Tag; - b.Icon = Mathf.Abs(TransformGizmo.ScaleSnapValue - v) < 0.001f ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; - } - } - } - - private void OnWidgetRotateSnapClick(ContextMenuButton button) - { - var v = (float)button.Tag; - TransformGizmo.RotationSnapValue = v; - _rotateSnapping.Text = v.ToString(); - _editor.ProjectCache.SetCustomData("RotationSnapValue", TransformGizmo.RotationSnapValue.ToString("N")); - } - - private void OnWidgetRotateSnapShowHide(Control control) - { - if (control.Visible == false) - return; - - var ccm = (ContextMenu)control; - foreach (var e in ccm.Items) - { - if (e is ContextMenuButton b) - { - var v = (float)b.Tag; - b.Icon = Mathf.Abs(TransformGizmo.RotationSnapValue - v) < 0.001f ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; - } - } - } - - private void OnWidgetTranslateSnapClick(ContextMenuButton button) - { - var v = (float)button.Tag; - TransformGizmo.TranslationSnapValue = v; - if (v < 0.0f) - _translateSnapping.Text = "Bounding Box"; - else - _translateSnapping.Text = v.ToString(); - _editor.ProjectCache.SetCustomData("TranslateSnapValue", TransformGizmo.TranslationSnapValue.ToString("N")); - } - - private void OnWidgetTranslateSnapShowHide(Control control) - { - if (control.Visible == false) - return; - - var ccm = (ContextMenu)control; - foreach (var e in ccm.Items) - { - if (e is ContextMenuButton b) - { - var v = (float)b.Tag; - b.Icon = Mathf.Abs(TransformGizmo.TranslationSnapValue - v) < 0.001f ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; - } - } - } - private void OnSelectionChanged() { var selection = _editor.SceneEditing.Selection; diff --git a/Source/Editor/Viewport/PrefabWindowViewport.cs b/Source/Editor/Viewport/PrefabWindowViewport.cs index 252981555..081c1d4f1 100644 --- a/Source/Editor/Viewport/PrefabWindowViewport.cs +++ b/Source/Editor/Viewport/PrefabWindowViewport.cs @@ -5,12 +5,10 @@ using System.Collections.Generic; using System.Linq; using FlaxEditor.Content; using FlaxEditor.Gizmo; -using FlaxEditor.GUI.ContextMenu; using FlaxEditor.SceneGraph; using FlaxEditor.Scripting; using FlaxEditor.Viewport.Cameras; using FlaxEditor.Viewport.Previews; -using FlaxEditor.Viewport.Widgets; using FlaxEditor.Windows.Assets; using FlaxEngine; using FlaxEngine.GUI; @@ -63,14 +61,6 @@ namespace FlaxEditor.Viewport private readonly PrefabWindow _window; private UpdateDelegate _update; - private readonly ViewportWidgetButton _gizmoModeTranslate; - private readonly ViewportWidgetButton _gizmoModeRotate; - private readonly ViewportWidgetButton _gizmoModeScale; - - private ViewportWidgetButton _translateSnappng; - private ViewportWidgetButton _rotateSnapping; - private ViewportWidgetButton _scaleSnapping; - private readonly ViewportDebugDrawData _debugDrawData = new ViewportDebugDrawData(32); private PrefabSpritesRenderer _spritesRenderer; private IntPtr _tempDebugDrawContext; @@ -129,7 +119,6 @@ namespace FlaxEditor.Viewport // Add transformation gizmo TransformGizmo = new TransformGizmo(this); TransformGizmo.ApplyTransformation += ApplyTransform; - TransformGizmo.ModeChanged += OnGizmoModeChanged; TransformGizmo.Duplicate += _window.Duplicate; Gizmos.Active = TransformGizmo; @@ -138,127 +127,9 @@ namespace FlaxEditor.Viewport _uiRoot.IndexInParent = 0; // Move viewport down below other widgets in the viewport _uiParentLink = _uiRoot.UIRoot; - // Transform space widget - var transformSpaceWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); - var transformSpaceToggle = new ViewportWidgetButton(string.Empty, window.Editor.Icons.Globe32, null, true) - { - Checked = TransformGizmo.ActiveTransformSpace == TransformGizmoBase.TransformSpace.World, - TooltipText = $"Gizmo transform space (world or local) ({inputOptions.ToggleTransformSpace})", - Parent = transformSpaceWidget - }; - transformSpaceToggle.Toggled += OnTransformSpaceToggle; - transformSpaceWidget.Parent = this; - - // Scale snapping widget - var scaleSnappingWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); - var enableScaleSnapping = new ViewportWidgetButton(string.Empty, window.Editor.Icons.ScaleSnap32, null, true) - { - Checked = TransformGizmo.ScaleSnapEnabled, - TooltipText = "Enable scale snapping", - Parent = scaleSnappingWidget - }; - enableScaleSnapping.Toggled += OnScaleSnappingToggle; - var scaleSnappingCM = new ContextMenu(); - _scaleSnapping = new ViewportWidgetButton(TransformGizmo.ScaleSnapValue.ToString(), SpriteHandle.Invalid, scaleSnappingCM) - { - TooltipText = "Scale snapping values" - }; - for (int i = 0; i < EditorGizmoViewport.ScaleSnapValues.Length; i++) - { - var v = EditorGizmoViewport.ScaleSnapValues[i]; - var button = scaleSnappingCM.AddButton(v.ToString()); - button.Tag = v; - } - scaleSnappingCM.ButtonClicked += OnWidgetScaleSnapClick; - scaleSnappingCM.VisibleChanged += OnWidgetScaleSnapShowHide; - _scaleSnapping.Parent = scaleSnappingWidget; - scaleSnappingWidget.Parent = this; - - // Rotation snapping widget - var rotateSnappingWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); - var enableRotateSnapping = new ViewportWidgetButton(string.Empty, window.Editor.Icons.RotateSnap32, null, true) - { - Checked = TransformGizmo.RotationSnapEnabled, - TooltipText = "Enable rotation snapping", - Parent = rotateSnappingWidget - }; - enableRotateSnapping.Toggled += OnRotateSnappingToggle; - var rotateSnappingCM = new ContextMenu(); - _rotateSnapping = new ViewportWidgetButton(TransformGizmo.RotationSnapValue.ToString(), SpriteHandle.Invalid, rotateSnappingCM) - { - TooltipText = "Rotation snapping values" - }; - for (int i = 0; i < EditorGizmoViewport.RotateSnapValues.Length; i++) - { - var v = EditorGizmoViewport.RotateSnapValues[i]; - var button = rotateSnappingCM.AddButton(v.ToString()); - button.Tag = v; - } - rotateSnappingCM.ButtonClicked += OnWidgetRotateSnapClick; - rotateSnappingCM.VisibleChanged += OnWidgetRotateSnapShowHide; - _rotateSnapping.Parent = rotateSnappingWidget; - rotateSnappingWidget.Parent = this; - - // Translation snapping widget - var translateSnappingWidget = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); - var enableTranslateSnapping = new ViewportWidgetButton(string.Empty, window.Editor.Icons.Grid32, null, true) - { - Checked = TransformGizmo.TranslationSnapEnable, - TooltipText = "Enable position snapping", - Parent = translateSnappingWidget - }; - enableTranslateSnapping.Toggled += OnTranslateSnappingToggle; - var translateSnappingCM = new ContextMenu(); - _translateSnappng = new ViewportWidgetButton(TransformGizmo.TranslationSnapValue.ToString(), SpriteHandle.Invalid, translateSnappingCM) - { - TooltipText = "Position snapping values" - }; - for (int i = 0; i < EditorGizmoViewport.TranslateSnapValues.Length; i++) - { - var v = EditorGizmoViewport.TranslateSnapValues[i]; - var button = translateSnappingCM.AddButton(v.ToString()); - button.Tag = v; - } - translateSnappingCM.ButtonClicked += OnWidgetTranslateSnapClick; - translateSnappingCM.VisibleChanged += OnWidgetTranslateSnapShowHide; - _translateSnappng.Parent = translateSnappingWidget; - translateSnappingWidget.Parent = this; - - // Gizmo mode widget - var gizmoMode = new ViewportWidgetsContainer(ViewportWidgetLocation.UpperRight); - _gizmoModeTranslate = new ViewportWidgetButton(string.Empty, window.Editor.Icons.Translate32, null, true) - { - Tag = TransformGizmoBase.Mode.Translate, - TooltipText = $"Translate gizmo mode ({inputOptions.TranslateMode})", - Checked = true, - Parent = gizmoMode - }; - _gizmoModeTranslate.Toggled += OnGizmoModeToggle; - _gizmoModeRotate = new ViewportWidgetButton(string.Empty, window.Editor.Icons.Rotate32, null, true) - { - Tag = TransformGizmoBase.Mode.Rotate, - TooltipText = $"Rotate gizmo mode ({inputOptions.RotateMode})", - Parent = gizmoMode - }; - _gizmoModeRotate.Toggled += OnGizmoModeToggle; - _gizmoModeScale = new ViewportWidgetButton(string.Empty, window.Editor.Icons.Scale32, null, true) - { - Tag = TransformGizmoBase.Mode.Scale, - TooltipText = $"Scale gizmo mode ({inputOptions.ScaleMode})", - Parent = gizmoMode - }; - _gizmoModeScale.Toggled += OnGizmoModeToggle; - gizmoMode.Parent = this; + EditorGizmoViewport.AddGizmoViewportWidgets(this, TransformGizmo); // Setup input actions - InputActions.Add(options => options.TranslateMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Translate); - InputActions.Add(options => options.RotateMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Rotate); - InputActions.Add(options => options.ScaleMode, () => TransformGizmo.ActiveMode = TransformGizmoBase.Mode.Scale); - InputActions.Add(options => options.ToggleTransformSpace, () => - { - OnTransformSpaceToggle(transformSpaceToggle); - transformSpaceToggle.Checked = !transformSpaceToggle.Checked; - }); InputActions.Add(options => options.FocusSelection, ShowSelectedActors); SetUpdate(ref _update, OnUpdate); @@ -472,109 +343,6 @@ namespace FlaxEditor.Viewport root.UpdateCallbacksToRemove.Add(_update); } - private void OnGizmoModeToggle(ViewportWidgetButton button) - { - TransformGizmo.ActiveMode = (TransformGizmoBase.Mode)(int)button.Tag; - } - - private void OnTranslateSnappingToggle(ViewportWidgetButton button) - { - TransformGizmo.TranslationSnapEnable = !TransformGizmo.TranslationSnapEnable; - } - - private void OnRotateSnappingToggle(ViewportWidgetButton button) - { - TransformGizmo.RotationSnapEnabled = !TransformGizmo.RotationSnapEnabled; - } - - private void OnScaleSnappingToggle(ViewportWidgetButton button) - { - TransformGizmo.ScaleSnapEnabled = !TransformGizmo.ScaleSnapEnabled; - } - - private void OnTransformSpaceToggle(ViewportWidgetButton button) - { - TransformGizmo.ToggleTransformSpace(); - } - - private void OnGizmoModeChanged() - { - // Update all viewport widgets status - var mode = TransformGizmo.ActiveMode; - _gizmoModeTranslate.Checked = mode == TransformGizmoBase.Mode.Translate; - _gizmoModeRotate.Checked = mode == TransformGizmoBase.Mode.Rotate; - _gizmoModeScale.Checked = mode == TransformGizmoBase.Mode.Scale; - } - - private void OnWidgetScaleSnapClick(ContextMenuButton button) - { - var v = (float)button.Tag; - TransformGizmo.ScaleSnapValue = v; - _scaleSnapping.Text = v.ToString(); - } - - private void OnWidgetScaleSnapShowHide(Control control) - { - if (control.Visible == false) - return; - - var ccm = (ContextMenu)control; - foreach (var e in ccm.Items) - { - if (e is ContextMenuButton b) - { - var v = (float)b.Tag; - b.Icon = Mathf.Abs(TransformGizmo.ScaleSnapValue - v) < 0.001f ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; - } - } - } - - private void OnWidgetRotateSnapClick(ContextMenuButton button) - { - var v = (float)button.Tag; - TransformGizmo.RotationSnapValue = v; - _rotateSnapping.Text = v.ToString(); - } - - private void OnWidgetRotateSnapShowHide(Control control) - { - if (control.Visible == false) - return; - - var ccm = (ContextMenu)control; - foreach (var e in ccm.Items) - { - if (e is ContextMenuButton b) - { - var v = (float)b.Tag; - b.Icon = Mathf.Abs(TransformGizmo.RotationSnapValue - v) < 0.001f ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; - } - } - } - - private void OnWidgetTranslateSnapClick(ContextMenuButton button) - { - var v = (float)button.Tag; - TransformGizmo.TranslationSnapValue = v; - _translateSnappng.Text = v.ToString(); - } - - private void OnWidgetTranslateSnapShowHide(Control control) - { - if (control.Visible == false) - return; - - var ccm = (ContextMenu)control; - foreach (var e in ccm.Items) - { - if (e is ContextMenuButton b) - { - var v = (float)b.Tag; - b.Icon = Mathf.Abs(TransformGizmo.TranslationSnapValue - v) < 0.001f ? Style.Current.CheckBoxTick : SpriteHandle.Invalid; - } - } - } - private void OnSelectionChanged() { Gizmos.ForEach(x => x.OnSelectionChanged(_window.Selection));