Merge branch 'Menotdan-visject_grid_snap'

This commit is contained in:
Wojtek Figat
2024-09-11 20:11:48 +02:00
12 changed files with 144 additions and 62 deletions

View File

@@ -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;
/// <summary>
/// Gets or sets the surface grid snapping option.
/// </summary>
[DefaultValue(false)]
[EditorDisplay("Visject", "Grid Snapping"), EditorOrder(551), Tooltip("Toggles grid snapping when moving nodes.")]
public bool SurfaceGridSnapping { get; set; } = false;
/// <summary>
/// Gets or sets the surface grid snapping option.
/// </summary>
[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<FontAsset>(EditorAssets.PrimaryFont);
private static FontAsset ConsoleFont => FlaxEngine.Content.LoadAsyncInternal<FontAsset>(EditorAssets.InconsolataRegularFont);

View File

@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
@@ -10,9 +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;
namespace FlaxEditor.Surface
{
@@ -556,5 +555,33 @@ namespace FlaxEditor.Surface
return true;
return AreScriptTypesEqualInner(left, right) || AreScriptTypesEqualInner(right, left);
}
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, 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, 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
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);
}
}
}

View File

@@ -1,5 +1,6 @@
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using System.Linq;
using FlaxEditor.Options;
@@ -24,6 +25,7 @@ namespace FlaxEditor.Surface
private string _currentInputText = string.Empty;
private Float2 _movingNodesDelta;
private Float2 _gridRoundingDelta;
private HashSet<SurfaceNode> _movingNodes;
private readonly Stack<InputBracket> _inputBrackets = new Stack<InputBracket>();
@@ -189,6 +191,22 @@ namespace FlaxEditor.Surface
}
}
/// <summary>
/// Snaps a coordinate point to the grid.
/// </summary>
/// <param name="point">The point to be rounded.</param>
/// <param name="ceil">Round to ceiling instead?</param>
/// <returns>Rounded coordinate.</returns>
public Float2 SnapToGrid(Float2 point, bool ceil = false)
{
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;
}
/// <inheritdoc />
public override void OnMouseEnter(Float2 location)
{
@@ -256,18 +274,39 @@ namespace FlaxEditor.Surface
// Moving
else if (_isMovingSelection)
{
var gridSnap = GridSnappingEnabled;
if (!gridSnap)
_gridRoundingDelta = Float2.Zero; // Reset in case user toggled option between frames.
// Calculate delta (apply view offset)
var viewDelta = _rootControl.Location - _movingSelectionViewPos;
_movingSelectionViewPos = _rootControl.Location;
var delta = location - _leftMouseDownPos - viewDelta;
if (delta.LengthSquared > 0.01f)
var delta = location - _leftMouseDownPos - viewDelta + _gridRoundingDelta;
var deltaLengthSquared = delta.LengthSquared;
delta /= _targetScale;
if ((!gridSnap || Mathf.Abs(delta.X) >= GridSnappingSize || (Mathf.Abs(delta.Y) >= GridSnappingSize))
&& deltaLengthSquared > 0.01f)
{
// Move selected nodes
delta /= _targetScale;
if (gridSnap)
{
Float2 unroundedDelta = delta;
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 (gridSnap)
{
Float2 unroundedLocation = node.Location;
node.Location = SnapToGrid(unroundedLocation);
}
node.Location += delta;
}
_leftMouseDownPos = location;
_movingNodesDelta += delta;
_movingNodesDelta += delta; // TODO: Figure out how to handle undo for differing values of _gridRoundingDelta between selected nodes. For now it will be a small error in undo.
if (_movingNodes.Count > 0)
{
Cursor = CursorType.SizeAll;

View File

@@ -31,11 +31,29 @@ namespace FlaxEditor.Surface
/// </summary>
protected SurfaceRootControl _rootControl;
/// <summary>
/// Is grid snapping enabled for this surface?
/// </summary>
public bool GridSnappingEnabled
{
get => _gridSnappingEnabled;
set
{
_gridSnappingEnabled = value;
_gridRoundingDelta = Float2.Zero;
}
}
/// <summary>
/// The size of the snapping grid.
/// </summary>
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<NodeArchetype> _customNodes;
@@ -632,6 +650,11 @@ namespace FlaxEditor.Surface
SelectionChanged?.Invoke();
}
internal void ToggleGridSnapping()
{
GridSnappingEnabled = !GridSnappingEnabled;
}
/// <summary>
/// Selects all the nodes.
/// </summary>

View File

@@ -891,9 +891,21 @@ namespace FlaxEditor.Surface
/// </summary>
protected Tabs _tabs;
private readonly ToolStripButton _saveButton;
private readonly ToolStripButton _undoButton;
private readonly ToolStripButton _redoButton;
/// <summary>
/// Save button on a toolstrip.
/// </summary>
protected ToolStripButton _saveButton;
/// <summary>
/// Undo button on a toolstrip.
/// </summary>
protected ToolStripButton _undoButton;
/// <summary>
/// Redo button on a toolstrip.
/// </summary>
protected ToolStripButton _redoButton;
private bool _showWholeGraphOnLoad = true;
/// <summary>
@@ -950,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;
@@ -998,20 +1008,6 @@ namespace FlaxEditor.Surface
_propertiesEditor.Panel.Parent = _split2.Panel2;
}
_propertiesEditor.Modified += OnPropertyEdited;
// Toolstrip
_saveButton = (ToolStripButton)_toolstrip.AddButton(Editor.Icons.Save64, 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");
// 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);
}
private void OnUndoRedo(IUndoAction action)

View File

@@ -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");

View File

@@ -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;
}

View File

@@ -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");
}

View File

@@ -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");
}

View File

@@ -70,13 +70,7 @@ namespace FlaxEditor.Windows.Assets
_undo.ActionDone += OnUndoRedo;
// Toolstrip
_saveButton = (ToolStripButton)_toolstrip.AddButton(Editor.Icons.Save64, 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");
SurfaceUtils.PerformCommonSetup(this, _toolstrip, _surface, out _saveButton, out _undoButton, out _redoButton);
// Panel
_panel = new Panel(ScrollBars.None)
@@ -85,11 +79,6 @@ namespace FlaxEditor.Windows.Assets
Offsets = new Margin(0, 0, _toolstrip.Bottom, 0),
Parent = this
};
// 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);
}
private void OnUndoRedo(IUndoAction action)

View File

@@ -597,13 +597,7 @@ namespace FlaxEditor.Windows.Assets
_propertiesEditor.Select(_properties);
// Toolstrip
_saveButton = (ToolStripButton)_toolstrip.AddButton(Editor.Icons.Save64, 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");
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[]
@@ -643,9 +637,6 @@ namespace FlaxEditor.Windows.Assets
debugObjectPickerContainer.Parent = _toolstrip;
// 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);
InputActions.Add(options => options.DebuggerContinue, OnDebuggerContinue);
InputActions.Add(options => options.DebuggerStepOver, OnDebuggerStepOver);
InputActions.Add(options => options.DebuggerStepOut, OnDebuggerStepOut);

View File

@@ -865,6 +865,16 @@ namespace FlaxEngine
return new Float2(Mathf.Ceil(v.X), Mathf.Ceil(v.Y));
}
/// <summary>
/// Returns the vector with components containing the smallest integer smaller to or equal to the original value.
/// </summary>
/// <param name="v">The value.</param>
/// <returns>The result.</returns>
public static Float2 Floor(Float2 v)
{
return new Float2(Mathf.Floor(v.X), Mathf.Floor(v.Y));
}
/// <summary>
/// Breaks the components of the vector into an integral and a fractional part. Returns vector made of fractional parts.
/// </summary>