diff --git a/Source/Editor/Surface/Archetypes/Function.cs b/Source/Editor/Surface/Archetypes/Function.cs index d027dd8f1..422ebf35b 100644 --- a/Source/Editor/Surface/Archetypes/Function.cs +++ b/Source/Editor/Surface/Archetypes/Function.cs @@ -773,7 +773,7 @@ namespace FlaxEditor.Surface.Archetypes Values[4] = GetSignatureData(memberInfo, memberInfo.GetParameters()); } } - + private SignatureInfo LoadSignature() { var signature = new SignatureInfo(); @@ -1151,6 +1151,45 @@ namespace FlaxEditor.Surface.Archetypes base.OnDestroy(); } + + internal static bool IsInputCompatible(NodeArchetype nodeArch, ScriptType outputType, ConnectionsHint hint) + { + if (nodeArch.Tag is not ScriptMemberInfo memberInfo) + return false; + if(memberInfo.ValueType.IsVoid && outputType.IsVoid) + return true; + if (!memberInfo.IsStatic) + { + if (VisjectSurface.FullCastCheck(memberInfo.DeclaringType, outputType, hint)) + return true; + } + foreach (var param in memberInfo.GetParameters()) + { + if(param.IsOut) + continue; + if (VisjectSurface.FullCastCheck(param.Type, outputType, hint)) + return true; + } + return false; + } + + internal static bool IsOutputCompatible(NodeArchetype nodeArch, ScriptType inputType, ConnectionsHint hint) + { + if (nodeArch.Tag is not ScriptMemberInfo memberInfo) + return false; + if(memberInfo.ValueType.IsVoid && inputType.IsVoid) + return true; + if (VisjectSurface.FullCastCheck(memberInfo.ValueType, inputType, hint)) + return true; + foreach (var param in memberInfo.GetParameters()) + { + if(!param.IsOut) + continue; + if (VisjectSurface.FullCastCheck(param.Type, inputType, hint)) + return true; + } + return false; + } } private sealed class ReturnNode : SurfaceNode @@ -2228,7 +2267,6 @@ namespace FlaxEditor.Surface.Archetypes Title = "Function Input", Description = "The graph function input data", Flags = NodeFlags.MaterialGraph | NodeFlags.ParticleEmitterGraph | NodeFlags.AnimGraph | NodeFlags.NoSpawnViaPaste, - NodeTypeHint = NodeTypeHint.FunctionNode, Size = new Float2(240, 60), DefaultValues = new object[] { @@ -2248,7 +2286,6 @@ namespace FlaxEditor.Surface.Archetypes Title = "Function Output", Description = "The graph function output data", Flags = NodeFlags.MaterialGraph | NodeFlags.ParticleEmitterGraph | NodeFlags.AnimGraph | NodeFlags.NoSpawnViaPaste, - NodeTypeHint = NodeTypeHint.FunctionNode, Size = new Float2(240, 60), DefaultValues = new object[] { @@ -2267,7 +2304,6 @@ namespace FlaxEditor.Surface.Archetypes Title = string.Empty, Description = "Overrides the base class method with custom implementation", Flags = NodeFlags.VisualScriptGraph | NodeFlags.NoSpawnViaGUI | NodeFlags.NoSpawnViaPaste, - NodeTypeHint = NodeTypeHint.FunctionNode, Size = new Float2(240, 60), DefaultValues = new object[] { @@ -2280,9 +2316,10 @@ namespace FlaxEditor.Surface.Archetypes { TypeID = 4, Create = (id, context, arch, groupArch) => new InvokeMethodNode(id, context, arch, groupArch), + IsInputCompatible = InvokeMethodNode.IsInputCompatible, + IsOutputCompatible = InvokeMethodNode.IsOutputCompatible, Title = string.Empty, Flags = NodeFlags.VisualScriptGraph | NodeFlags.NoSpawnViaGUI, - NodeTypeHint = NodeTypeHint.FunctionNode, Size = new Float2(240, 60), DefaultValues = new object[] { @@ -2306,7 +2343,6 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new ReturnNode(id, context, arch, groupArch), Title = "Return", Flags = NodeFlags.VisualScriptGraph | NodeFlags.NoSpawnViaGUI, - NodeTypeHint = NodeTypeHint.FunctionNode, Size = new Float2(100, 40), DefaultValues = new object[] { @@ -2325,7 +2361,6 @@ namespace FlaxEditor.Surface.Archetypes Title = "New Function", Description = "Adds a new function to the script", Flags = NodeFlags.VisualScriptGraph, - NodeTypeHint = NodeTypeHint.FunctionNode, Size = new Float2(240, 20), DefaultValues = new object[] { @@ -2338,7 +2373,6 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new GetFieldNode(id, context, arch, groupArch), Title = string.Empty, Flags = NodeFlags.VisualScriptGraph | NodeFlags.NoSpawnViaGUI, - NodeTypeHint = NodeTypeHint.FunctionNode, Size = new Float2(240, 60), DefaultValues = new object[] { @@ -2354,7 +2388,6 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new SetFieldNode(id, context, arch, groupArch), Title = string.Empty, Flags = NodeFlags.VisualScriptGraph | NodeFlags.NoSpawnViaGUI, - NodeTypeHint = NodeTypeHint.FunctionNode, Size = new Float2(240, 60), DefaultValues = new object[] { @@ -2371,7 +2404,6 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new BindEventNode(id, context, arch, groupArch), Title = string.Empty, Flags = NodeFlags.VisualScriptGraph | NodeFlags.NoSpawnViaGUI, - NodeTypeHint = NodeTypeHint.FunctionNode, Size = new Float2(260, 60), DefaultValues = new object[] { @@ -2394,7 +2426,6 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new UnbindEventNode(id, context, arch, groupArch), Title = string.Empty, Flags = NodeFlags.VisualScriptGraph | NodeFlags.NoSpawnViaGUI, - NodeTypeHint = NodeTypeHint.FunctionNode, Size = new Float2(260, 60), DefaultValues = new object[] { diff --git a/Source/Editor/Surface/Archetypes/Packing.cs b/Source/Editor/Surface/Archetypes/Packing.cs index 54524dc13..5a5e9cd5b 100644 --- a/Source/Editor/Surface/Archetypes/Packing.cs +++ b/Source/Editor/Surface/Archetypes/Packing.cs @@ -353,7 +353,6 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new PackStructureNode(id, context, arch, groupArch), Description = "Makes the structure data to from the components.", Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph | NodeFlags.NoSpawnViaGUI, - NodeTypeHint = NodeTypeHint.PackingNode, Size = new Float2(180, 20), DefaultValues = new object[] { @@ -464,7 +463,6 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new UnpackStructureNode(id, context, arch, groupArch), Description = "Breaks the structure data to allow extracting components from it.", Flags = NodeFlags.VisualScriptGraph | NodeFlags.AnimGraph | NodeFlags.NoSpawnViaGUI, - NodeTypeHint = NodeTypeHint.PackingNode, Size = new Float2(180, 20), DefaultValues = new object[] { diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs index 65ba19909..1d645a94e 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs @@ -109,9 +109,23 @@ namespace FlaxEditor.Surface.ContextMenu return false; bool isCompatible = false; + + if (startBox.IsOutput && _archetype.IsInputCompatible != null) + { + isCompatible |= _archetype.IsInputCompatible.Invoke(_archetype, startBox.CurrentType, _archetype.ConnectionsHints); + } + else if (!startBox.IsOutput && _archetype.IsOutputCompatible != null) + { + isCompatible |= _archetype.IsOutputCompatible.Invoke(_archetype, startBox.CurrentType, startBox.ParentNode.Archetype.ConnectionsHints); + } + else if (_archetype.Elements != null) + { + // Check compatibility based on the defined elements in the archetype. This handles all the default groups and items + isCompatible = CheckElementsCompatibility(startBox); + } // Check compatibility based on the archetype tag or name. This handles custom groups and items, mainly function nodes for visual scripting - if (_archetype.NodeTypeHint is NodeTypeHint.FunctionNode) + /*if (_archetype.NodeTypeHint is NodeTypeHint.FunctionNode) { ScriptMemberInfo memberInfo = ScriptMemberInfo.Null; @@ -135,12 +149,8 @@ namespace FlaxEditor.Surface.ContextMenu { isCompatible |= CheckMemberInfoCompatibility(startBox, memberInfo); } - } - else if (_archetype.Elements != null) - { - // Check compatibility based on the defined elements in the archetype. This handles all the default groups and items - isCompatible = CheckElementsCompatibility(startBox); - } + }*/ + /*else */ return isCompatible; } @@ -165,17 +175,16 @@ namespace FlaxEditor.Surface.ContextMenu if (!info.IsStatic) { var scriptType = info.DeclaringType; - isCompatible |= CanCastType(scriptType, outType, _archetype.ConnectionsHints); + isCompatible |= VisjectSurface.FullCastCheck(scriptType, outType, _archetype.ConnectionsHints); } // We ignore event members here since they only have output parameters, which are currently not declared as such - // TODO: Fix bug where event member parameters 'IsOut' is set to false and not true if (!info.IsEvent) { for (int i = 0; i < parameters.Length; i++) { ScriptType inType = parameters[i].Type; - isCompatible |= CanCastType(inType, outType, _archetype.ConnectionsHints); + isCompatible |= VisjectSurface.FullCastCheck(inType, outType, _archetype.ConnectionsHints); } } } @@ -185,7 +194,7 @@ namespace FlaxEditor.Surface.ContextMenu ScriptType inType = startBox.CurrentType; ScriptType outType = info.ValueType; - isCompatible |= CanCastType(inType, outType, _archetype.ConnectionsHints); + isCompatible |= VisjectSurface.FullCastCheck(inType, outType, _archetype.ConnectionsHints); } } return isCompatible; @@ -220,25 +229,12 @@ namespace FlaxEditor.Surface.ContextMenu hint = startBox.ParentNode.Archetype.ConnectionsHints; } - isCompatible |= CanCastType(fromType, toType, hint); + isCompatible |= VisjectSurface.FullCastCheck(fromType, toType, hint); } return isCompatible; } - private bool CanCastType(ScriptType from, ScriptType to, ConnectionsHint hint) - { - // Yes, from and to are switched on purpose - if (VisjectSurface.CanUseDirectCastStatic(to, from, false)) - return true; - - if(VisjectSurface.IsTypeCompatible(from, to, hint)) - return true; - - // Same here - return to.CanCastTo(from); - } - /// /// Updates the filter. /// diff --git a/Source/Editor/Surface/NodeArchetype.cs b/Source/Editor/Surface/NodeArchetype.cs index 146618ae7..1a7f88f20 100644 --- a/Source/Editor/Surface/NodeArchetype.cs +++ b/Source/Editor/Surface/NodeArchetype.cs @@ -72,28 +72,6 @@ namespace FlaxEditor.Surface /// All = Scalar | Vector | Enum | Anything | Value | Array | Dictionary, } - - /// - /// Node type hint. Helps to distinguish special archetypes - /// - [HideInEditor] - public enum NodeTypeHint - { - /// - /// Is Node. - /// - Default = 0, - - /// - /// Is Function Node. - /// - FunctionNode = 1, - - /// - /// Is custom Packing Node. - /// - PackingNode = 2, - } /// /// Surface node archetype description. @@ -111,6 +89,11 @@ namespace FlaxEditor.Surface /// The created node object. public delegate SurfaceNode CreateCustomNodeFunc(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch); + /// + /// Checks if the given type is compatible with the given node archetype. Used for custom nodes + /// + public delegate bool IsCompatible(NodeArchetype nodeArch, ScriptType portType, ConnectionsHint hint); + /// /// Unique node type ID within a single group. /// @@ -121,6 +104,16 @@ namespace FlaxEditor.Surface /// public CreateCustomNodeFunc Create; + /// + /// Function for asynchronously loaded nodes to check if input ports are compatible, for filtering. + /// + public IsCompatible IsInputCompatible; + + /// + /// Function for asynchronously loaded nodes to check if output ports are compatible, for filtering. + /// + public IsCompatible IsOutputCompatible; + /// /// Default initial size of the node. /// @@ -130,7 +123,7 @@ namespace FlaxEditor.Surface /// Custom set of flags. /// public NodeFlags Flags; - + /// /// Title text. /// @@ -173,11 +166,6 @@ namespace FlaxEditor.Surface /// Connections hints. /// public ConnectionsHint ConnectionsHints; - - /// - /// Node Type hints. - /// - public NodeTypeHint NodeTypeHint; /// /// Array with independent boxes IDs. @@ -211,6 +199,8 @@ namespace FlaxEditor.Surface { TypeID = TypeID, Create = Create, + IsInputCompatible = IsInputCompatible, + IsOutputCompatible = IsOutputCompatible, Size = Size, Flags = Flags, Title = Title, @@ -220,7 +210,6 @@ namespace FlaxEditor.Surface DefaultValues = (object[])DefaultValues?.Clone(), DefaultType = DefaultType, ConnectionsHints = ConnectionsHints, - NodeTypeHint = NodeTypeHint, IndependentBoxes = (int[])IndependentBoxes?.Clone(), DependentBoxes = (int[])DependentBoxes?.Clone(), Elements = (NodeElementArchetype[])Elements?.Clone(), diff --git a/Source/Editor/Surface/VisjectSurface.Connecting.cs b/Source/Editor/Surface/VisjectSurface.Connecting.cs index 449f88f8c..9ca4f82e8 100644 --- a/Source/Editor/Surface/VisjectSurface.Connecting.cs +++ b/Source/Editor/Surface/VisjectSurface.Connecting.cs @@ -199,6 +199,17 @@ namespace FlaxEditor.Surface return false; } + + public static bool FullCastCheck(ScriptType from, ScriptType to, ConnectionsHint hint) + { + // Yes, from and to are switched on purpose + if (CanUseDirectCastStatic(to, from, false)) + return true; + if(IsTypeCompatible(from, to, hint)) + return true; + // Same here + return to.CanCastTo(from); + } /// /// Checks if can use direct conversion from one type to another.