- Removed NodeTypeHint

- Added delegates to check compatiblity with custom archetypes
- Added compatibility check to InvokeMethod archetype
This commit is contained in:
Nils Hausfeld
2023-09-30 13:20:04 +02:00
parent 3befe4bb4a
commit 35f641955b
5 changed files with 92 additions and 67 deletions

View File

@@ -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[]
{

View File

@@ -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[]
{

View File

@@ -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);
}
/// <summary>
/// Updates the filter.
/// </summary>

View File

@@ -72,28 +72,6 @@ namespace FlaxEditor.Surface
/// </summary>
All = Scalar | Vector | Enum | Anything | Value | Array | Dictionary,
}
/// <summary>
/// Node type hint. Helps to distinguish special archetypes
/// </summary>
[HideInEditor]
public enum NodeTypeHint
{
/// <summary>
/// Is Node.
/// </summary>
Default = 0,
/// <summary>
/// Is Function Node.
/// </summary>
FunctionNode = 1,
/// <summary>
/// Is custom Packing Node.
/// </summary>
PackingNode = 2,
}
/// <summary>
/// Surface node archetype description.
@@ -111,6 +89,11 @@ namespace FlaxEditor.Surface
/// <returns>The created node object.</returns>
public delegate SurfaceNode CreateCustomNodeFunc(uint id, VisjectSurfaceContext context, NodeArchetype nodeArch, GroupArchetype groupArch);
/// <summary>
/// Checks if the given type is compatible with the given node archetype. Used for custom nodes
/// </summary>
public delegate bool IsCompatible(NodeArchetype nodeArch, ScriptType portType, ConnectionsHint hint);
/// <summary>
/// Unique node type ID within a single group.
/// </summary>
@@ -121,6 +104,16 @@ namespace FlaxEditor.Surface
/// </summary>
public CreateCustomNodeFunc Create;
/// <summary>
/// Function for asynchronously loaded nodes to check if input ports are compatible, for filtering.
/// </summary>
public IsCompatible IsInputCompatible;
/// <summary>
/// Function for asynchronously loaded nodes to check if output ports are compatible, for filtering.
/// </summary>
public IsCompatible IsOutputCompatible;
/// <summary>
/// Default initial size of the node.
/// </summary>
@@ -130,7 +123,7 @@ namespace FlaxEditor.Surface
/// Custom set of flags.
/// </summary>
public NodeFlags Flags;
/// <summary>
/// Title text.
/// </summary>
@@ -173,11 +166,6 @@ namespace FlaxEditor.Surface
/// Connections hints.
/// </summary>
public ConnectionsHint ConnectionsHints;
/// <summary>
/// Node Type hints.
/// </summary>
public NodeTypeHint NodeTypeHint;
/// <summary>
/// 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(),

View File

@@ -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);
}
/// <summary>
/// Checks if can use direct conversion from one type to another.