diff --git a/Source/Editor/Surface/ContextMenu/VisjectCM.cs b/Source/Editor/Surface/ContextMenu/VisjectCM.cs
index 9955f0434..c07173aec 100644
--- a/Source/Editor/Surface/ContextMenu/VisjectCM.cs
+++ b/Source/Editor/Surface/ContextMenu/VisjectCM.cs
@@ -5,7 +5,6 @@ using System.Collections.Generic;
using System.Linq;
using FlaxEditor.GUI.ContextMenu;
using FlaxEditor.GUI.Input;
-using FlaxEditor.Scripting;
using FlaxEngine;
using FlaxEngine.GUI;
using FlaxEngine.Utilities;
diff --git a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
index 4aa5c6ce8..b0ff74272 100644
--- a/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
+++ b/Source/Editor/Surface/ContextMenu/VisjectCMItem.cs
@@ -80,7 +80,7 @@ namespace FlaxEditor.Surface.ContextMenu
if (!Visible)
return;
- if (selectedBox != null && CanConnectTo(selectedBox, NodeArchetype))
+ if (selectedBox != null && CanConnectTo(selectedBox))
SortScore += 1;
if (Data != null)
SortScore += 1;
@@ -95,29 +95,14 @@ namespace FlaxEditor.Surface.ContextMenu
textRect = new Rectangle(22, 0, Width - 24, Height);
}
- private bool CanConnectTo(Box startBox, NodeArchetype nodeArchetype)
- {
- if (startBox == null)
- return false;
- if (!startBox.IsOutput)
- return false; // For now, I'm only handing the output box case
-
- if (nodeArchetype.Elements != null)
- {
- for (int i = 0; i < nodeArchetype.Elements.Length; i++)
- {
- if (nodeArchetype.Elements[i].Type == NodeElementType.Input &&
- startBox.CanUseType(nodeArchetype.Elements[i].ConnectionsType))
- {
- return true;
- }
- }
- }
- return false;
- }
-
+ ///
+ /// Checks if this context menu item can be connected to a given box, before a node is actually spawned.
+ ///
+ /// The connected box
+ /// True if the connected box is compatible with this item
public bool CanConnectTo(Box startBox)
{
+ // Is compatible if box is null for reset reasons
if (startBox == null)
{
Visible = true;
@@ -131,15 +116,20 @@ namespace FlaxEditor.Surface.ContextMenu
}
bool isCompatible = false;
+
+ // Check compatibility based on the defined elements in the archetype. This handles all the default groups and items
if (_archetype.Elements != null)
{
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 == NodeTypeHint.FunctionNode)
{
ScriptMemberInfo memberInfo = ScriptMemberInfo.Null;
+ // Check if the archetype tag already has a member info otherwise try to fetch it via the archetype type and name
+ // Only really the InvokeMethod Nodes have a member info in their tag
if (_archetype.Tag is ScriptMemberInfo info)
{
memberInfo = info;
@@ -155,22 +145,29 @@ namespace FlaxEditor.Surface.ContextMenu
{
if(memberInfo.IsEvent)
isCompatible = false;
-
+
+ // Box was dragged from an impulse port and the member info can be invoked so it is compatible
if (startBox.CurrentType.IsVoid && memberInfo.ValueType.IsVoid)
- isCompatible = true;
+ {
+ isCompatible = true;
+ }
else
{
+ // When the startBox is output we only need to check the input parameters
if (startBox.IsOutput)
{
var parameters = memberInfo.GetParameters();
ScriptType outType = startBox.CurrentType;
-
+
+ // non static members have an instance input parameter
if (!memberInfo.IsStatic)
{
var scriptType = memberInfo.DeclaringType;
isCompatible |= CanCastToType(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 (!memberInfo.IsEvent)
{
for (int i = 0; i < parameters.Length; i++)
@@ -182,6 +179,7 @@ namespace FlaxEditor.Surface.ContextMenu
}
else
{
+ // When the startBox is input we only have to check the output type of the method
ScriptType inType = startBox.CurrentType;
ScriptType outType = memberInfo.ValueType;
@@ -232,60 +230,10 @@ namespace FlaxEditor.Surface.ContextMenu
{
if (VisjectSurface.CanUseDirectCastStatic(type, currentType, false))
return true;
-
- var connectionsHints = hint;
- if (currentType == ScriptType.Null && connectionsHints != ConnectionsHint.None)
- {
- if ((connectionsHints & ConnectionsHint.Anything) == ConnectionsHint.Anything)
- return true;
- if ((connectionsHints & ConnectionsHint.Value) == ConnectionsHint.Value && type.Type != typeof(void))
- return true;
- if ((connectionsHints & ConnectionsHint.Enum) == ConnectionsHint.Enum && type.IsEnum)
- return true;
- if ((connectionsHints & ConnectionsHint.Array) == ConnectionsHint.Array && type.IsArray)
- return true;
- if ((connectionsHints & ConnectionsHint.Dictionary) == ConnectionsHint.Dictionary && type.IsDictionary)
- return true;
- if ((connectionsHints & ConnectionsHint.Vector) == ConnectionsHint.Vector)
- {
- var t = type.Type;
- if (t == typeof(Vector2) ||
- t == typeof(Vector3) ||
- t == typeof(Vector4) ||
- t == typeof(Float2) ||
- t == typeof(Float3) ||
- t == typeof(Float4) ||
- t == typeof(Double2) ||
- t == typeof(Double3) ||
- t == typeof(Double4) ||
- t == typeof(Int2) ||
- t == typeof(Int3) ||
- t == typeof(Int4) ||
- t == typeof(Color))
- {
- return true;
- }
- }
- if ((connectionsHints & ConnectionsHint.Scalar) == ConnectionsHint.Scalar)
- {
- var t = type.Type;
- if (t == typeof(bool) ||
- t == typeof(char) ||
- t == typeof(byte) ||
- t == typeof(short) ||
- t == typeof(ushort) ||
- t == typeof(int) ||
- t == typeof(uint) ||
- t == typeof(long) ||
- t == typeof(ulong) ||
- t == typeof(float) ||
- t == typeof(double))
- {
- return true;
- }
- }
- }
-
+
+ if(VisjectSurface.IsTypeCompatible(currentType, type, hint))
+ return true;
+
return CanCast(type, currentType);
}
diff --git a/Source/Editor/Surface/Elements/Box.cs b/Source/Editor/Surface/Elements/Box.cs
index e771fa71c..5032b6048 100644
--- a/Source/Editor/Surface/Elements/Box.cs
+++ b/Source/Editor/Surface/Elements/Box.cs
@@ -231,58 +231,8 @@ namespace FlaxEditor.Surface.Elements
}
// Check using connection hints
- var connectionsHints = ParentNode.Archetype.ConnectionsHints;
- if (Archetype.ConnectionsType == ScriptType.Null && connectionsHints != ConnectionsHint.None)
- {
- if ((connectionsHints & ConnectionsHint.Anything) == ConnectionsHint.Anything)
- return true;
- if ((connectionsHints & ConnectionsHint.Value) == ConnectionsHint.Value && type.Type != typeof(void))
- return true;
- if ((connectionsHints & ConnectionsHint.Enum) == ConnectionsHint.Enum && type.IsEnum)
- return true;
- if ((connectionsHints & ConnectionsHint.Array) == ConnectionsHint.Array && type.IsArray)
- return true;
- if ((connectionsHints & ConnectionsHint.Dictionary) == ConnectionsHint.Dictionary && type.IsDictionary)
- return true;
- if ((connectionsHints & ConnectionsHint.Vector) == ConnectionsHint.Vector)
- {
- var t = type.Type;
- if (t == typeof(Vector2) ||
- t == typeof(Vector3) ||
- t == typeof(Vector4) ||
- t == typeof(Float2) ||
- t == typeof(Float3) ||
- t == typeof(Float4) ||
- t == typeof(Double2) ||
- t == typeof(Double3) ||
- t == typeof(Double4) ||
- t == typeof(Int2) ||
- t == typeof(Int3) ||
- t == typeof(Int4) ||
- t == typeof(Color))
- {
- return true;
- }
- }
- if ((connectionsHints & ConnectionsHint.Scalar) == ConnectionsHint.Scalar)
- {
- var t = type.Type;
- if (t == typeof(bool) ||
- t == typeof(char) ||
- t == typeof(byte) ||
- t == typeof(short) ||
- t == typeof(ushort) ||
- t == typeof(int) ||
- t == typeof(uint) ||
- t == typeof(long) ||
- t == typeof(ulong) ||
- t == typeof(float) ||
- t == typeof(double))
- {
- return true;
- }
- }
- }
+ if(VisjectSurface.IsTypeCompatible(Archetype.ConnectionsType, type, ParentNode.Archetype.ConnectionsHints))
+ return true;
// Check independent and if there is box with bigger potential because it may block current one from changing type
var parentArch = ParentNode.Archetype;
diff --git a/Source/Editor/Surface/VisjectSurface.Connecting.cs b/Source/Editor/Surface/VisjectSurface.Connecting.cs
index 2fbff7cb8..449f88f8c 100644
--- a/Source/Editor/Surface/VisjectSurface.Connecting.cs
+++ b/Source/Editor/Surface/VisjectSurface.Connecting.cs
@@ -136,6 +136,70 @@ namespace FlaxEditor.Surface
return result;
}
+ ///
+ /// Checks if a type is compatible with another type and can be casted by using a connection hint
+ ///
+ /// Source type
+ /// Type to check compatibility with
+ /// Hint to check if casting is possible
+ /// True if the source type is compatible with the target type
+ public static bool IsTypeCompatible(ScriptType from, ScriptType to, ConnectionsHint hint)
+ {
+ if (from == ScriptType.Null && hint != ConnectionsHint.None)
+ {
+ if ((hint & ConnectionsHint.Anything) == ConnectionsHint.Anything)
+ return true;
+ if ((hint & ConnectionsHint.Value) == ConnectionsHint.Value && to.Type != typeof(void))
+ return true;
+ if ((hint & ConnectionsHint.Enum) == ConnectionsHint.Enum && to.IsEnum)
+ return true;
+ if ((hint & ConnectionsHint.Array) == ConnectionsHint.Array && to.IsArray)
+ return true;
+ if ((hint & ConnectionsHint.Dictionary) == ConnectionsHint.Dictionary && to.IsDictionary)
+ return true;
+ if ((hint & ConnectionsHint.Vector) == ConnectionsHint.Vector)
+ {
+ var t = to.Type;
+ if (t == typeof(Vector2) ||
+ t == typeof(Vector3) ||
+ t == typeof(Vector4) ||
+ t == typeof(Float2) ||
+ t == typeof(Float3) ||
+ t == typeof(Float4) ||
+ t == typeof(Double2) ||
+ t == typeof(Double3) ||
+ t == typeof(Double4) ||
+ t == typeof(Int2) ||
+ t == typeof(Int3) ||
+ t == typeof(Int4) ||
+ t == typeof(Color))
+ {
+ return true;
+ }
+ }
+ if ((hint & ConnectionsHint.Scalar) == ConnectionsHint.Scalar)
+ {
+ var t = to.Type;
+ if (t == typeof(bool) ||
+ t == typeof(char) ||
+ t == typeof(byte) ||
+ t == typeof(short) ||
+ t == typeof(ushort) ||
+ t == typeof(int) ||
+ t == typeof(uint) ||
+ t == typeof(long) ||
+ t == typeof(ulong) ||
+ t == typeof(float) ||
+ t == typeof(double))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
///
/// Checks if can use direct conversion from one type to another.
///