diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs index 8f786362d..f7cc7107a 100644 --- a/Source/Editor/Options/InterfaceOptions.cs +++ b/Source/Editor/Options/InterfaceOptions.cs @@ -382,6 +382,20 @@ namespace FlaxEditor.Options [EditorDisplay("Visject"), EditorOrder(550), Tooltip("Shows/hides the description panel in the visual scripting context menu.")] public bool VisualScriptingDescriptionPanel { get; set; } = true; + /// + /// Gets or sets the surface grid snapping option. + /// + [DefaultValue(false)] + [EditorDisplay("Visject", "Grid Snapping"), EditorOrder(551), Tooltip("Toggles grid snapping when moving nodes.")] + public bool SurfaceGridSnapping { get; set; } = false; + + /// + /// Gets or sets the surface grid snapping option. + /// + [DefaultValue(20.0f)] + [EditorDisplay("Visject", "Grid Snapping Size"), EditorOrder(551), Tooltip("Defines the size of the grid for nodes snapping."), VisibleIf(nameof(SurfaceGridSnapping))] + public float SurfaceGridSnappingSize { get; set; } = 20.0f; + private static FontAsset DefaultFont => FlaxEngine.Content.LoadAsyncInternal(EditorAssets.PrimaryFont); private static FontAsset ConsoleFont => FlaxEngine.Content.LoadAsyncInternal(EditorAssets.InconsolataRegularFont); diff --git a/Source/Editor/Surface/NodeArchetype.cs b/Source/Editor/Surface/NodeArchetype.cs index 32d75c71c..609b7b5f7 100644 --- a/Source/Editor/Surface/NodeArchetype.cs +++ b/Source/Editor/Surface/NodeArchetype.cs @@ -109,7 +109,6 @@ namespace FlaxEditor.Surface /// public CreateCustomNodeFunc Create; - private Float2 _size; /// /// Function for asynchronously loaded nodes to check if input ports are compatible, for filtering. /// @@ -123,17 +122,7 @@ namespace FlaxEditor.Surface /// /// Default initial size of the node. /// - public Float2 Size - { - get - { - return _size; - } - set - { - _size = VisjectSurface.RoundToGrid(value, true); - } - } + public Float2 Size; /// /// Custom set of flags. diff --git a/Source/Editor/Surface/SurfaceUtils.cs b/Source/Editor/Surface/SurfaceUtils.cs index a6fc82d55..c1f966812 100644 --- a/Source/Editor/Surface/SurfaceUtils.cs +++ b/Source/Editor/Surface/SurfaceUtils.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Reflection; using System.Text; @@ -10,12 +9,9 @@ using FlaxEditor.CustomEditors; using FlaxEditor.CustomEditors.Elements; using FlaxEditor.Options; using FlaxEditor.Scripting; -using FlaxEditor.Utilities; using FlaxEngine.Utilities; using FlaxEngine; using FlaxEditor.GUI; -using FlaxEngine.GUI; -using FlaxEditor.Options; namespace FlaxEditor.Surface { @@ -560,41 +556,32 @@ namespace FlaxEditor.Surface return AreScriptTypesEqualInner(left, right) || AreScriptTypesEqualInner(right, left); } - // This might not be the greatest place to put this but I couldn't find anything better yet. - public static void VisjectCommonToolstripSetup(Editor editor, ToolStrip toolStrip, FlaxEditor.Undo undo, - Action save, Action showWholeGraph, Action toggleGridSnap, InputActionsContainer actionsContainer, - out ToolStripButton saveButton, out ToolStripButton undoButton, out ToolStripButton redoButton, out ToolStripButton gridSnapButton) + internal static void PerformCommonSetup(Windows.Assets.AssetEditorWindow window, ToolStrip toolStrip, VisjectSurface surface, + out ToolStripButton saveButton, out ToolStripButton undoButton, out ToolStripButton redoButton) { + var editor = window.Editor; + var interfaceOptions = editor.Options.Options.Interface; var inputOptions = editor.Options.Options.Input; + var undo = surface.Undo; // Toolstrip - saveButton = (ToolStripButton)toolStrip.AddButton(editor.Icons.Save64, save).LinkTooltip("Save"); + saveButton = (ToolStripButton)toolStrip.AddButton(editor.Icons.Save64, window.Save).LinkTooltip("Save"); toolStrip.AddSeparator(); undoButton = (ToolStripButton)toolStrip.AddButton(editor.Icons.Undo64, undo.PerformUndo).LinkTooltip($"Undo ({inputOptions.Undo})"); redoButton = (ToolStripButton)toolStrip.AddButton(editor.Icons.Redo64, undo.PerformRedo).LinkTooltip($"Redo ({inputOptions.Redo})"); toolStrip.AddSeparator(); toolStrip.AddButton(editor.Icons.Search64, editor.ContentFinding.ShowSearch).LinkTooltip($"Open content search tool ({inputOptions.Search})"); - toolStrip.AddButton(editor.Icons.CenterView64, showWholeGraph).LinkTooltip("Show whole graph"); - gridSnapButton = (ToolStripButton)toolStrip.AddButton(editor.Icons.Stop64, toggleGridSnap).LinkTooltip("Toggle grid snapping for nodes."); - gridSnapButton.BackgroundColor = Style.Current.Background; // Default color for grid snap button. + toolStrip.AddButton(editor.Icons.CenterView64, surface.ShowWholeGraph).LinkTooltip("Show whole graph"); + var gridSnapButton = toolStrip.AddButton(editor.Icons.Grid32, surface.ToggleGridSnapping); + gridSnapButton.LinkTooltip("Toggle grid snapping for nodes."); + gridSnapButton.AutoCheck = true; + gridSnapButton.Checked = surface.GridSnappingEnabled = interfaceOptions.SurfaceGridSnapping; + surface.GridSnappingSize = interfaceOptions.SurfaceGridSnappingSize; // Setup input actions - actionsContainer.Add(options => options.Undo, undo.PerformUndo); - actionsContainer.Add(options => options.Redo, undo.PerformRedo); - actionsContainer.Add(options => options.Search, editor.ContentFinding.ShowSearch); - } - - public static void ToggleSurfaceGridSnap(VisjectSurface surface, ToolStripButton gridSnapButton) - { - surface.GridSnappingEnabled = !surface.GridSnappingEnabled; - if (surface.GridSnappingEnabled) - { - gridSnapButton.BackgroundColor = Style.Current.BackgroundSelected; - } - else - { - gridSnapButton.BackgroundColor = Style.Current.Background; - } + window.InputActions.Add(options => options.Undo, undo.PerformUndo); + window.InputActions.Add(options => options.Redo, undo.PerformRedo); + window.InputActions.Add(options => options.Search, editor.ContentFinding.ShowSearch); } } } diff --git a/Source/Editor/Surface/VisjectSurface.Input.cs b/Source/Editor/Surface/VisjectSurface.Input.cs index c540a2bd1..416f0152e 100644 --- a/Source/Editor/Surface/VisjectSurface.Input.cs +++ b/Source/Editor/Surface/VisjectSurface.Input.cs @@ -192,26 +192,19 @@ namespace FlaxEditor.Surface } /// - /// Round a visject coordinate point to the grid. + /// Snaps a coordinate point to the grid. /// /// The point to be rounded. /// Round to ceiling instead? - /// - public static Float2 RoundToGrid(Float2 point, bool ceil = false) + /// Rounded coordinate. + public Float2 SnapToGrid(Float2 point, bool ceil = false) { - Func round = x => - { - double pointGridUnits = Math.Abs((double)x) / GridSize; - pointGridUnits = ceil ? Math.Ceiling(pointGridUnits) : Math.Floor(pointGridUnits); - - return (float)Math.CopySign(pointGridUnits * GridSize, x); - }; - - Float2 pointToRound = point; - pointToRound.X = round(pointToRound.X); - pointToRound.Y = round(pointToRound.Y); - - return pointToRound; + float gridSize = GridSnappingSize; + Float2 snapped = point.Absolute / gridSize; + snapped = ceil ? Float2.Ceil(snapped) : Float2.Floor(snapped); + snapped.X = (float)Math.CopySign(snapped.X * gridSize, point.X); + snapped.Y = (float)Math.CopySign(snapped.Y * gridSize, point.Y); + return snapped; } /// @@ -281,7 +274,8 @@ namespace FlaxEditor.Surface // Moving else if (_isMovingSelection) { - if (!GridSnappingEnabled) + var gridSnap = GridSnappingEnabled; + if (!gridSnap) _gridRoundingDelta = Float2.Zero; // Reset in case user toggled option between frames. // Calculate delta (apply view offset) @@ -291,25 +285,23 @@ namespace FlaxEditor.Surface var deltaLengthSquared = delta.LengthSquared; delta /= _targetScale; - if ((!GridSnappingEnabled || Math.Abs(delta.X) >= GridSize || (Math.Abs(delta.Y) >= GridSize)) + if ((!gridSnap || Mathf.Abs(delta.X) >= GridSnappingSize || (Mathf.Abs(delta.Y) >= GridSnappingSize)) && deltaLengthSquared > 0.01f) { - if (GridSnappingEnabled) + if (gridSnap) { Float2 unroundedDelta = delta; - - delta = RoundToGrid(unroundedDelta); + delta = SnapToGrid(unroundedDelta); _gridRoundingDelta = (unroundedDelta - delta) * _targetScale; // Standardize unit of the rounding delta, in case user zooms between node movements. } foreach (var node in _movingNodes) { - if (GridSnappingEnabled) + if (gridSnap) { Float2 unroundedLocation = node.Location; - node.Location = RoundToGrid(unroundedLocation); + node.Location = SnapToGrid(unroundedLocation); } - node.Location += delta; } diff --git a/Source/Editor/Surface/VisjectSurface.cs b/Source/Editor/Surface/VisjectSurface.cs index e4eb3269b..28ec17d53 100644 --- a/Source/Editor/Surface/VisjectSurface.cs +++ b/Source/Editor/Surface/VisjectSurface.cs @@ -34,18 +34,26 @@ namespace FlaxEditor.Surface /// /// Is grid snapping enabled for this surface? /// - public bool GridSnappingEnabled = false; + public bool GridSnappingEnabled + { + get => _gridSnappingEnabled; + set + { + _gridSnappingEnabled = value; + _gridRoundingDelta = Float2.Zero; + } + } /// /// The size of the snapping grid. /// - public static readonly float GridSize = 20f; + public float GridSnappingSize = 20f; private float _targetScale = 1.0f; private float _moveViewWithMouseDragSpeed = 1.0f; private bool _canEdit = true; private readonly bool _supportsDebugging; - private bool _isReleasing; + private bool _isReleasing, _gridSnappingEnabled; private VisjectCM _activeVisjectCM; private GroupArchetype _customNodesGroup; private List _customNodes; @@ -642,6 +650,11 @@ namespace FlaxEditor.Surface SelectionChanged?.Invoke(); } + internal void ToggleGridSnapping() + { + GridSnappingEnabled = !GridSnappingEnabled; + } + /// /// Selects all the nodes. /// diff --git a/Source/Editor/Surface/VisjectSurfaceWindow.cs b/Source/Editor/Surface/VisjectSurfaceWindow.cs index ec3db7a9d..16e4f303b 100644 --- a/Source/Editor/Surface/VisjectSurfaceWindow.cs +++ b/Source/Editor/Surface/VisjectSurfaceWindow.cs @@ -891,10 +891,21 @@ namespace FlaxEditor.Surface /// protected Tabs _tabs; - private readonly ToolStripButton _saveButton; - private readonly ToolStripButton _undoButton; - private readonly ToolStripButton _redoButton; - private readonly ToolStripButton _gridSnapButton; + /// + /// Save button on a toolstrip. + /// + protected ToolStripButton _saveButton; + + /// + /// Undo button on a toolstrip. + /// + protected ToolStripButton _undoButton; + + /// + /// Redo button on a toolstrip. + /// + protected ToolStripButton _redoButton; + private bool _showWholeGraphOnLoad = true; /// @@ -951,8 +962,6 @@ namespace FlaxEditor.Surface protected VisjectSurfaceWindow(Editor editor, AssetItem item, bool useTabs = false) : base(editor, item) { - var inputOptions = Editor.Options.Options.Input; - // Undo _undo = new FlaxEditor.Undo(); _undo.UndoDone += OnUndoRedo; @@ -999,10 +1008,6 @@ namespace FlaxEditor.Surface _propertiesEditor.Panel.Parent = _split2.Panel2; } _propertiesEditor.Modified += OnPropertyEdited; - - SurfaceUtils.VisjectCommonToolstripSetup(editor, _toolstrip, _undo, - Save, ShowWholeGraph, ToggleGridSnap, InputActions, - out _saveButton, out _undoButton, out _redoButton, out _gridSnapButton); } private void OnUndoRedo(IUndoAction action) @@ -1041,11 +1046,6 @@ namespace FlaxEditor.Surface _surface.ShowWholeGraph(); } - private void ToggleGridSnap() - { - SurfaceUtils.ToggleSurfaceGridSnap(_surface, _gridSnapButton); - } - /// /// Refreshes temporary asset to see changes live when editing the surface. /// diff --git a/Source/Editor/Windows/Assets/AnimationGraphWindow.cs b/Source/Editor/Windows/Assets/AnimationGraphWindow.cs index e75becf72..1cf03f062 100644 --- a/Source/Editor/Windows/Assets/AnimationGraphWindow.cs +++ b/Source/Editor/Windows/Assets/AnimationGraphWindow.cs @@ -206,6 +206,7 @@ namespace FlaxEditor.Windows.Assets _surface.ContextChanged += OnSurfaceContextChanged; // Toolstrip + SurfaceUtils.PerformCommonSetup(this, _toolstrip, _surface, out _saveButton, out _undoButton, out _redoButton); _showNodesButton = (ToolStripButton)_toolstrip.AddButton(editor.Icons.Bone64, () => _preview.ShowNodes = !_preview.ShowNodes).LinkTooltip("Show animated model nodes debug view"); _toolstrip.AddSeparator(); _toolstrip.AddButton(editor.Icons.Docs64, () => Platform.OpenUrl(Utilities.Constants.DocsUrl + "manual/animation/anim-graph/index.html")).LinkTooltip("See documentation to learn more"); diff --git a/Source/Editor/Windows/Assets/BehaviorTreeWindow.cs b/Source/Editor/Windows/Assets/BehaviorTreeWindow.cs index 47d6f2840..f4e7a4f6a 100644 --- a/Source/Editor/Windows/Assets/BehaviorTreeWindow.cs +++ b/Source/Editor/Windows/Assets/BehaviorTreeWindow.cs @@ -172,13 +172,8 @@ namespace FlaxEditor.Windows.Assets _knowledgePropertiesEditor.Panel.Parent = _split2.Panel2; // Toolstrip - _saveButton = (ToolStripButton)_toolstrip.AddButton(Editor.Icons.Save64, Save).LinkTooltip("Save"); + SurfaceUtils.PerformCommonSetup(this, _toolstrip, _surface, out _saveButton, out _undoButton, out _redoButton); _toolstrip.AddSeparator(); - _undoButton = (ToolStripButton)_toolstrip.AddButton(Editor.Icons.Undo64, _undo.PerformUndo).LinkTooltip($"Undo ({inputOptions.Undo})"); - _redoButton = (ToolStripButton)_toolstrip.AddButton(Editor.Icons.Redo64, _undo.PerformRedo).LinkTooltip($"Redo ({inputOptions.Redo})"); - _toolstrip.AddSeparator(); - _toolstrip.AddButton(Editor.Icons.Search64, Editor.ContentFinding.ShowSearch).LinkTooltip($"Open content search tool ({inputOptions.Search})"); - _toolstrip.AddButton(editor.Icons.CenterView64, _surface.ShowWholeGraph).LinkTooltip("Show whole graph"); _toolstrip.AddButton(editor.Icons.Docs64, () => Platform.OpenUrl(Utilities.Constants.DocsUrl + "manual/scripting/ai/behavior-trees/index.html")).LinkTooltip("See documentation to learn more"); // Debug behavior picker @@ -206,11 +201,6 @@ namespace FlaxEditor.Windows.Assets _behaviorPicker.CheckValid = OnBehaviorPickerCheckValid; _behaviorPicker.ValueChanged += OnBehaviorPickerValueChanged; - // Setup input actions - InputActions.Add(options => options.Undo, _undo.PerformUndo); - InputActions.Add(options => options.Redo, _undo.PerformRedo); - InputActions.Add(options => options.Search, Editor.ContentFinding.ShowSearch); - SetCanEdit(!Editor.IsPlayMode); ScriptsBuilder.ScriptsReloadBegin += OnScriptsReloadBegin; } diff --git a/Source/Editor/Windows/Assets/MaterialWindow.cs b/Source/Editor/Windows/Assets/MaterialWindow.cs index ef37fbe67..ad72c92d9 100644 --- a/Source/Editor/Windows/Assets/MaterialWindow.cs +++ b/Source/Editor/Windows/Assets/MaterialWindow.cs @@ -257,8 +257,9 @@ namespace FlaxEditor.Windows.Assets }; // Toolstrip - _toolstrip.AddSeparator(); + SurfaceUtils.PerformCommonSetup(this, _toolstrip, _surface, out _saveButton, out _undoButton, out _redoButton); _toolstrip.AddButton(editor.Icons.Code64, ShowSourceCode).LinkTooltip("Show generated shader source code"); + _toolstrip.AddSeparator(); _toolstrip.AddButton(editor.Icons.Docs64, () => Platform.OpenUrl(Utilities.Constants.DocsUrl + "manual/graphics/materials/index.html")).LinkTooltip("See documentation to learn more"); } diff --git a/Source/Editor/Windows/Assets/ParticleEmitterWindow.cs b/Source/Editor/Windows/Assets/ParticleEmitterWindow.cs index 93dce7034..c373b4cdc 100644 --- a/Source/Editor/Windows/Assets/ParticleEmitterWindow.cs +++ b/Source/Editor/Windows/Assets/ParticleEmitterWindow.cs @@ -141,8 +141,9 @@ namespace FlaxEditor.Windows.Assets }; // Toolstrip - _toolstrip.AddSeparator(); + SurfaceUtils.PerformCommonSetup(this, _toolstrip, _surface, out _saveButton, out _undoButton, out _redoButton); _toolstrip.AddButton(editor.Icons.Code64, ShowSourceCode).LinkTooltip("Show generated shader source code"); + _toolstrip.AddSeparator(); _toolstrip.AddButton(editor.Icons.Docs64, () => Platform.OpenUrl(Utilities.Constants.DocsUrl + "manual/particles/index.html")).LinkTooltip("See documentation to learn more"); } diff --git a/Source/Editor/Windows/Assets/VisjectFunctionSurfaceWindow.cs b/Source/Editor/Windows/Assets/VisjectFunctionSurfaceWindow.cs index 1cdd07611..24b3e3f9b 100644 --- a/Source/Editor/Windows/Assets/VisjectFunctionSurfaceWindow.cs +++ b/Source/Editor/Windows/Assets/VisjectFunctionSurfaceWindow.cs @@ -30,7 +30,6 @@ namespace FlaxEditor.Windows.Assets private readonly ToolStripButton _saveButton; private readonly ToolStripButton _undoButton; private readonly ToolStripButton _redoButton; - private readonly ToolStripButton _gridSnapButton; private bool _showWholeGraphOnLoad = true; /// @@ -71,9 +70,7 @@ namespace FlaxEditor.Windows.Assets _undo.ActionDone += OnUndoRedo; // Toolstrip - SurfaceUtils.VisjectCommonToolstripSetup(editor, _toolstrip, _undo, - Save, ShowWholeGraph, ToggleGridSnap, InputActions, - out _saveButton, out _undoButton, out _redoButton, out _gridSnapButton); + SurfaceUtils.PerformCommonSetup(this, _toolstrip, _surface, out _saveButton, out _undoButton, out _redoButton); // Panel _panel = new Panel(ScrollBars.None) @@ -98,11 +95,6 @@ namespace FlaxEditor.Windows.Assets _surface.ShowWholeGraph(); } - private void ToggleGridSnap() - { - SurfaceUtils.ToggleSurfaceGridSnap(_surface, _gridSnapButton); - } - /// /// Refreshes temporary asset to see changes live when editing the surface. /// diff --git a/Source/Editor/Windows/Assets/VisualScriptWindow.cs b/Source/Editor/Windows/Assets/VisualScriptWindow.cs index 3f742e09d..b424ecffc 100644 --- a/Source/Editor/Windows/Assets/VisualScriptWindow.cs +++ b/Source/Editor/Windows/Assets/VisualScriptWindow.cs @@ -533,7 +533,6 @@ namespace FlaxEditor.Windows.Assets private readonly ToolStripButton _saveButton; private readonly ToolStripButton _undoButton; private readonly ToolStripButton _redoButton; - private readonly ToolStripButton _gridSnapButton; private Control[] _debugToolstripControls; private bool _showWholeGraphOnLoad = true; private bool _tmpAssetIsDirty; @@ -598,11 +597,7 @@ namespace FlaxEditor.Windows.Assets _propertiesEditor.Select(_properties); // Toolstrip - SurfaceUtils.VisjectCommonToolstripSetup(editor, _toolstrip, _undo, - Save, ShowWholeGraph, ToggleGridSnap, InputActions, - out _saveButton, out _undoButton, out _redoButton, out _gridSnapButton); - - // The rest of the toolstrip + SurfaceUtils.PerformCommonSetup(this, _toolstrip, _surface, out _saveButton, out _undoButton, out _redoButton); _toolstrip.AddSeparator(); _toolstrip.AddButton(editor.Icons.Docs64, () => Platform.OpenUrl(Utilities.Constants.DocsUrl + "manual/scripting/visual/index.html")).LinkTooltip("See documentation to learn more"); _debugToolstripControls = new[] @@ -683,11 +678,6 @@ namespace FlaxEditor.Windows.Assets _surface.ShowWholeGraph(); } - private void ToggleGridSnap() - { - SurfaceUtils.ToggleSurfaceGridSnap(_surface, _gridSnapButton); - } - /// /// Refreshes temporary asset to see changes live when editing the surface. /// diff --git a/Source/Engine/Core/Math/Float2.cs b/Source/Engine/Core/Math/Float2.cs index adbe61508..92247d865 100644 --- a/Source/Engine/Core/Math/Float2.cs +++ b/Source/Engine/Core/Math/Float2.cs @@ -865,6 +865,16 @@ namespace FlaxEngine return new Float2(Mathf.Ceil(v.X), Mathf.Ceil(v.Y)); } + /// + /// Returns the vector with components containing the smallest integer smaller to or equal to the original value. + /// + /// The value. + /// The result. + public static Float2 Floor(Float2 v) + { + return new Float2(Mathf.Floor(v.X), Mathf.Floor(v.Y)); + } + /// /// Breaks the components of the vector into an integral and a fractional part. Returns vector made of fractional parts. ///