From d33829f5eb073fe36425311bad03b0129e9ba516 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Tue, 16 Nov 2021 20:44:18 +0100 Subject: [PATCH] Add option to change Visual Script parameter type --- Source/Editor/Scripting/ScriptType.cs | 11 ++ .../Windows/Assets/VisualScriptWindow.cs | 141 ++++++++++++++++++ 2 files changed, 152 insertions(+) diff --git a/Source/Editor/Scripting/ScriptType.cs b/Source/Editor/Scripting/ScriptType.cs index ada049c08..10956e9ba 100644 --- a/Source/Editor/Scripting/ScriptType.cs +++ b/Source/Editor/Scripting/ScriptType.cs @@ -1106,6 +1106,17 @@ namespace FlaxEditor.Scripting throw new NotImplementedException("TODO: Script.Type.GetGenericTypeDefinition for custom types"); } + /// + /// Returns a type object that represents an array of the current type. + /// + /// A type object representing a one-dimensional array of the current type. + public ScriptType MakeArrayType() + { + if (_managed != null) + return new ScriptType(_managed.MakeArrayType()); + throw new NotImplementedException("TODO: Script.Type.MakeArrayType for custom types"); + } + /// /// Searches for the specified members of the specified member type, using the specified binding constraints. /// diff --git a/Source/Editor/Windows/Assets/VisualScriptWindow.cs b/Source/Editor/Windows/Assets/VisualScriptWindow.cs index 729fc71cd..76e0b8797 100644 --- a/Source/Editor/Windows/Assets/VisualScriptWindow.cs +++ b/Source/Editor/Windows/Assets/VisualScriptWindow.cs @@ -70,6 +70,83 @@ namespace FlaxEditor.Windows.Assets } } + private sealed class EditParamTypeAction : IUndoAction + { + private struct BrokenConnection + { + public uint ANode; + public int ABox; + public uint BNode; + public int BBox; + } + + private List _connectionsToRestore = new List(); + private List _connectionsToRestorePrev = new List(); + + public IVisjectSurfaceWindow Window; + public int Index; + public ScriptType BeforeType; + public object BeforeValue; + public ScriptType AfterType; + public object AfterValue; + + public string ActionString => "Edit parameter type"; + + public void Do() + { + Set(AfterType, AfterValue); + } + + public void Undo() + { + Set(BeforeType, BeforeValue); + } + + private void Set(ScriptType type, object value) + { + _connectionsToRestore.Clear(); + Window.VisjectSurface.NodesDisconnected += OnNodesDisconnected; + var param = Window.VisjectSurface.Parameters[Index]; + param.Type = type; + param.Value = value; + Window.VisjectSurface.OnParamEdited(param); + Window.VisjectSurface.NodesDisconnected -= OnNodesDisconnected; + + // Restore connections broken previously + foreach (var connection in _connectionsToRestorePrev) + { + var aNode = Window.VisjectSurface.FindNode(connection.ANode); + var bNode = Window.VisjectSurface.FindNode(connection.BNode); + var aBox = aNode?.GetBox(connection.ABox) ?? null; + var bBox = bNode?.GetBox(connection.BBox) ?? null; + if (aBox != null && bBox != null) + aBox.CreateConnection(bBox); + } + _connectionsToRestorePrev.Clear(); + _connectionsToRestorePrev.AddRange(_connectionsToRestore); + } + + private void OnNodesDisconnected(IConnectionInstigator a, IConnectionInstigator b) + { + // Capture any auto-disconnected boxes after parameter type change to restore them back on undo + if (a is Surface.Elements.Box aBox && b is Surface.Elements.Box bBox) + { + _connectionsToRestore.Add(new BrokenConnection + { + ANode = aBox.ParentNode.ID, ABox = aBox.ID, + BNode = bBox.ParentNode.ID, BBox = bBox.ID, + }); + } + } + + public void Dispose() + { + _connectionsToRestore = null; + _connectionsToRestorePrev = null; + Window = null; + } + } + private sealed class VisualParametersEditor : ParametersEditor { public VisualParametersEditor() @@ -88,9 +165,55 @@ namespace FlaxEditor.Windows.Assets var b = cmAccess.ContextMenu.AddButton("Public", () => window.SetParamAccess(index, true)); b.Checked = param.IsPublic; b.Enabled = window._canEdit; + b.TooltipText = "Sets the parameter access level to Public. It will be accessible and visible everywhere."; b = cmAccess.ContextMenu.AddButton("Private", () => window.SetParamAccess(index, false)); b.Checked = !param.IsPublic; b.Enabled = window._canEdit; + b.TooltipText = "Sets the parameter access level to Private. It will be accessible only within this script and won't be visible outside (eg. in script properties panel)."; + } + + // Parameter type editing + var cmType = menu.AddChildMenu("Type"); + { + var b = cmType.ContextMenu.AddButton(window.Surface.GetTypeName(param.Type) + "...", () => + { + // Show context menu with list of parameter types to use + var cm = new ItemsListContextMenu(180); + var newParameterTypes = window.NewParameterTypes; + foreach (var newParameterType in newParameterTypes) + { + var item = new TypeSearchPopup.TypeItemView(newParameterType); + if (newParameterType.Type != null) + item.Name = window.VisjectSurface.GetTypeName(newParameterType); + cm.AddItem(item); + } + cm.ItemClicked += (ItemsListContextMenu.Item item) => window.SetParamType(index, (ScriptType)item.Tag); + cm.SortChildren(); + cm.Show(window, window.PointFromScreen(Input.MouseScreenPosition)); + }); + b.Enabled = window._canEdit; + b.TooltipText = "Opens the type picker window to change the parameter type."; + cmType.ContextMenu.AddSeparator(); + + ScriptType singleValueType, arrayType; + if (param.Type.IsArray) + { + singleValueType = new ScriptType(param.Type.GetElementType()); + arrayType = param.Type; + } + else + { + singleValueType = param.Type; + arrayType = param.Type.MakeArrayType(); + } + b = cmType.ContextMenu.AddButton("Value", () => window.SetParamType(index, singleValueType)); + b.Checked = param.Type == singleValueType; + b.Enabled = window._canEdit; + b.TooltipText = "Changes parameter type to a single value."; + b = cmType.ContextMenu.AddButton("Array", () => window.SetParamType(index, arrayType)); + b.Checked = param.Type == arrayType; + b.Enabled = window._canEdit; + b.TooltipText = "Changes parameter type to an array."; } } } @@ -1064,6 +1187,24 @@ namespace FlaxEditor.Windows.Assets action.Do(); } + private void SetParamType(int index, ScriptType type) + { + var param = Surface.Parameters[index]; + if (param.Type == type) + return; + var action = new EditParamTypeAction + { + Window = this, + Index = index, + BeforeType = param.Type, + BeforeValue = param.Value, + AfterType = type, + AfterValue = TypeUtils.GetDefaultValue(type), + }; + _undo.AddAction(action); + action.Do(); + } + /// public override void OnPlayBeginning() {