diff --git a/Source/Editor/Surface/Archetypes/Function.cs b/Source/Editor/Surface/Archetypes/Function.cs index cffb2ad6f..d027dd8f1 100644 --- a/Source/Editor/Surface/Archetypes/Function.cs +++ b/Source/Editor/Surface/Archetypes/Function.cs @@ -2228,6 +2228,7 @@ 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[] { @@ -2247,6 +2248,7 @@ 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[] { @@ -2265,6 +2267,7 @@ 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[] { @@ -2279,6 +2282,7 @@ namespace FlaxEditor.Surface.Archetypes Create = (id, context, arch, groupArch) => new InvokeMethodNode(id, context, arch, groupArch), Title = string.Empty, Flags = NodeFlags.VisualScriptGraph | NodeFlags.NoSpawnViaGUI, + NodeTypeHint = NodeTypeHint.FunctionNode, Size = new Float2(240, 60), DefaultValues = new object[] { @@ -2302,6 +2306,7 @@ 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[] { @@ -2320,6 +2325,7 @@ 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[] { @@ -2332,6 +2338,7 @@ 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[] { @@ -2347,6 +2354,7 @@ 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[] { @@ -2363,6 +2371,7 @@ 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[] { @@ -2385,6 +2394,7 @@ 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/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs index 7b0ce6c85..f8b7d9d51 100644 --- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs +++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs @@ -3,11 +3,13 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; using FlaxEditor.Scripting; using FlaxEditor.Surface.Elements; using FlaxEditor.Utilities; using FlaxEngine; using FlaxEngine.GUI; +using FlaxEngine.Utilities; namespace FlaxEditor.Surface.ContextMenu { @@ -121,13 +123,70 @@ namespace FlaxEditor.Surface.ContextMenu Visible = true; return true; } - - if (_archetype?.Elements == null) + + if (_archetype == null) { Visible = false; return false; } - + + bool isCompatible = false; + if (_archetype.Elements != null) + { + isCompatible = CheckElementsCompatibility(startBox); + } + + if (_archetype.NodeTypeHint == NodeTypeHint.FunctionNode) + { + isCompatible = false; + ScriptMemberInfo memberInfo = ScriptMemberInfo.Null; + + if (_archetype.Tag is ScriptMemberInfo info) + { + memberInfo = info; + } + else if(_archetype.DefaultValues is { Length: > 1 }) + { + var eventName = (string)_archetype.DefaultValues[1]; + var eventType = TypeUtils.GetType((string)_archetype.DefaultValues[0]); + memberInfo = eventType.GetMember(eventName, MemberTypes.Event, BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance); + } + + if (memberInfo != ScriptMemberInfo.Null) + { + if (startBox.IsOutput) + { + var parameters = memberInfo.GetParameters(); + ScriptType outType = startBox.CurrentType; + + if (!memberInfo.IsStatic) + { + var scriptType = TypeUtils.GetType((string)_archetype.DefaultValues[0]); + isCompatible |= CanCastToType(scriptType, outType, _archetype.ConnectionsHints); + } + + if (!memberInfo.IsEvent) + { + for (int i = 0; i < parameters.Length; i++) + { + ScriptType inType = parameters[i].Type; + isCompatible |= CanCastToType(inType, outType, _archetype.ConnectionsHints); + } + } + } + else + { + + } + } + } + + Visible = isCompatible; + return isCompatible; + } + + private bool CheckElementsCompatibility(Box startBox) + { bool isCompatible = false; foreach (NodeElementArchetype element in _archetype.Elements) { @@ -153,15 +212,12 @@ namespace FlaxEditor.Surface.ContextMenu hint = startBox.ParentNode.Archetype.ConnectionsHints; } - bool checkCompatibility = CanCastToType(inType, outType, hint); - isCompatible |= checkCompatibility; + isCompatible |= CanCastToType(inType, outType, hint); } - - Visible = isCompatible; - + return isCompatible; } - + private bool CanCastToType(ScriptType currentType, ScriptType type, ConnectionsHint hint) { if (VisjectSurface.CanUseDirectCastStatic(type, currentType, false)) diff --git a/Source/Editor/Surface/NodeArchetype.cs b/Source/Editor/Surface/NodeArchetype.cs index 6dc923ce2..1cdaee2d2 100644 --- a/Source/Editor/Surface/NodeArchetype.cs +++ b/Source/Editor/Surface/NodeArchetype.cs @@ -73,6 +73,20 @@ namespace FlaxEditor.Surface All = Scalar | Vector | Enum | Anything | Value | Array | Dictionary, } + [HideInEditor] + public enum NodeTypeHint + { + /// + /// Is Node. + /// + Default = 0, + + /// + /// Is Function Node. + /// + FunctionNode = 1, + } + /// /// Surface node archetype description. /// @@ -152,6 +166,11 @@ namespace FlaxEditor.Surface /// public ConnectionsHint ConnectionsHints; + /// + /// Node Type hints. + /// + public NodeTypeHint NodeTypeHint; + /// /// Array with independent boxes IDs. /// @@ -193,6 +212,7 @@ 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/VisualScriptSurface.cs b/Source/Editor/Surface/VisualScriptSurface.cs index e961f686d..b6c0112a9 100644 --- a/Source/Editor/Surface/VisualScriptSurface.cs +++ b/Source/Editor/Surface/VisualScriptSurface.cs @@ -370,7 +370,7 @@ namespace FlaxEditor.Surface bindNode.Description = SurfaceUtils.GetVisualScriptMemberInfoDescription(member); bindNode.SubTitle = string.Format(" (in {0})", scriptTypeName); ((IList)group.Archetypes).Add(bindNode); - + // Add Unbind event node var unbindNode = (NodeArchetype)Archetypes.Function.Nodes[9].Clone(); unbindNode.DefaultValues[0] = scriptTypeTypeName; @@ -589,6 +589,7 @@ namespace FlaxEditor.Surface node.DefaultValues[0] = name; node.DefaultValues[1] = parameters.Length; node.Title = "Override " + name; + node.Tag = member; nodes.Add(node); } }