diff --git a/Source/Editor/Content/Items/VisualScriptItem.cs b/Source/Editor/Content/Items/VisualScriptItem.cs
index c1ccf5d73..32b12d232 100644
--- a/Source/Editor/Content/Items/VisualScriptItem.cs
+++ b/Source/Editor/Content/Items/VisualScriptItem.cs
@@ -338,6 +338,9 @@ namespace FlaxEditor.Content
///
public bool IsClass => true;
+ ///
+ public bool IsInterface => false;
+
///
public bool IsArray => false;
@@ -371,6 +374,12 @@ namespace FlaxEditor.Content
return Object.New(TypeName);
}
+ ///
+ public bool ImplementInterface(ScriptType c)
+ {
+ return BaseType.ImplementInterface(c);
+ }
+
///
public bool HasAttribute(Type attributeType, bool inherit)
{
diff --git a/Source/Editor/Content/Proxy/VisualScriptProxy.cs b/Source/Editor/Content/Proxy/VisualScriptProxy.cs
index 207527da0..5f44d0880 100644
--- a/Source/Editor/Content/Proxy/VisualScriptProxy.cs
+++ b/Source/Editor/Content/Proxy/VisualScriptProxy.cs
@@ -79,6 +79,18 @@ namespace FlaxEditor.Content
return ScriptType.Null;
}
+ ///
+ public void GetTypes(List result, Func checkFunc)
+ {
+ var visualScripts = VisualScriptItem.VisualScripts;
+ for (var i = 0; i < visualScripts.Count; i++)
+ {
+ var t = visualScripts[i].ScriptType;
+ if (checkFunc(t))
+ result.Add(t);
+ }
+ }
+
///
public void GetDerivedTypes(ScriptType baseType, List result, Func checkFunc)
{
diff --git a/Source/Editor/Modules/SourceCodeEditing/CachedTypesCollection.cs b/Source/Editor/Modules/SourceCodeEditing/CachedTypesCollection.cs
index fe0c565e5..86a4e8d6b 100644
--- a/Source/Editor/Modules/SourceCodeEditing/CachedTypesCollection.cs
+++ b/Source/Editor/Modules/SourceCodeEditing/CachedTypesCollection.cs
@@ -76,9 +76,14 @@ namespace FlaxEditor.Modules.SourceCodeEditing
///
protected virtual void Search()
{
- // Special case for attributes
- if (_type.Type != null && new ScriptType(typeof(Attribute)).IsAssignableFrom(_type))
+ if (_type == ScriptType.Null)
{
+ // Special case for all types
+ TypeUtils.GetTypes(_list, _checkFunc, _checkAssembly);
+ }
+ else if (_type.Type != null && new ScriptType(typeof(Attribute)).IsAssignableFrom(_type))
+ {
+ // Special case for attributes
TypeUtils.GetTypesWithAttributeDefined(_type.Type, _list, _checkFunc, _checkAssembly);
}
else
diff --git a/Source/Editor/Modules/SourceCodeEditing/CodeEditingModule.cs b/Source/Editor/Modules/SourceCodeEditing/CodeEditingModule.cs
index 254006e5f..30f1a64a1 100644
--- a/Source/Editor/Modules/SourceCodeEditing/CodeEditingModule.cs
+++ b/Source/Editor/Modules/SourceCodeEditing/CodeEditingModule.cs
@@ -157,7 +157,7 @@ namespace FlaxEditor.Modules.SourceCodeEditing
///
/// The all types collection from all assemblies (excluding C# system libraries). Includes only primitive and basic types from std lib.
///
- public readonly CachedTypesCollection All = new CachedAllTypesCollection(8096, new ScriptType(typeof(object)), type => true, HasAssemblyValidAnyTypes);
+ public readonly CachedTypesCollection All = new CachedAllTypesCollection(8096, ScriptType.Null, type => true, HasAssemblyValidAnyTypes);
///
/// The all valid types collection for the Visual Script property types (includes basic types like int/float, structures, object references).
diff --git a/Source/Editor/Scripting/ScriptType.cs b/Source/Editor/Scripting/ScriptType.cs
index bfe3ca250..ada049c08 100644
--- a/Source/Editor/Scripting/ScriptType.cs
+++ b/Source/Editor/Scripting/ScriptType.cs
@@ -775,6 +775,11 @@ namespace FlaxEditor.Scripting
///
public bool IsClass => _managed != null ? _managed.IsClass : _custom != null && _custom.IsClass;
+ ///
+ /// Gets a value indicating whether the type is an interface.
+ ///
+ public bool IsInterface => _managed != null ? _managed.IsInterface : _custom != null && _custom.IsInterface;
+
///
/// Gets a value indicating whether the type is an array.
///
@@ -995,6 +1000,20 @@ namespace FlaxEditor.Scripting
return false;
}
+ ///
+ /// Determines whether the current type implements the specified interface type. Checks this type, its base classes and implemented interfaces base interfaces too.
+ ///
+ /// The type of the interface to check.
+ /// True if this type implements the given interface, otherwise false.
+ public bool ImplementInterface(ScriptType c)
+ {
+ if (c._managed != null && _managed != null)
+ return c._managed.IsAssignableFrom(_managed);
+ if (_custom != null)
+ return _custom.ImplementInterface(c);
+ return false;
+ }
+
///
/// Determines whether the specified object is an instance of the current type.
///
@@ -1014,6 +1033,8 @@ namespace FlaxEditor.Scripting
/// false if none of these conditions are true, or if is .
public bool IsAssignableFrom(ScriptType c)
{
+ if (IsInterface)
+ return c.ImplementInterface(this);
while (c != Null)
{
if (c == this)
@@ -1377,6 +1398,11 @@ namespace FlaxEditor.Scripting
///
bool IsClass { get; }
+ ///
+ /// Gets a value indicating whether the type is an interface.
+ ///
+ bool IsInterface { get; }
+
///
/// Gets a value indicating whether the type is an array.
///
@@ -1428,6 +1454,13 @@ namespace FlaxEditor.Scripting
/// The created instance of the object.
object CreateInstance();
+ ///
+ /// Determines whether the current type implements the specified interface type. Checks this type, its base classes and implemented interfaces base interfaces too.
+ ///
+ /// The type of the interface to check.
+ /// True if this type implements the given interface, otherwise false.
+ bool ImplementInterface(ScriptType c);
+
///
/// Determines whether the specified attribute was defined for this type.
///
@@ -1613,6 +1646,13 @@ namespace FlaxEditor.Scripting
/// The type or null if failed.
ScriptType GetType(string typeName);
+ ///
+ /// Gets all the types within all the loaded assemblies.
+ ///
+ /// The result collection. Elements will be added to it. Clear it before usage.
+ /// Additional callback used to check if the given type is valid. Returns true if add type, otherwise false.
+ void GetTypes(List result, Func checkFunc);
+
///
/// Gets all the derived types from the given base type (excluding that type) within all the loaded assemblies.
///
diff --git a/Source/Editor/Scripting/TypeUtils.cs b/Source/Editor/Scripting/TypeUtils.cs
index 5a49814dd..aaa0cc3db 100644
--- a/Source/Editor/Scripting/TypeUtils.cs
+++ b/Source/Editor/Scripting/TypeUtils.cs
@@ -151,6 +151,44 @@ namespace FlaxEditor.Scripting
customTypesInfo.GetDerivedTypes(baseType, result, checkFunc);
}
+ ///
+ /// Gets all the types within the given assembly.
+ ///
+ /// The target assembly to check its types.
+ /// The result collection. Elements will be added to it. Clear it before usage.
+ /// Additional callback used to check if the given type is valid. Returns true if add type, otherwise false.
+ public static void GetTypes(Assembly assembly, List result, Func checkFunc)
+ {
+ var types = assembly.GetTypes();
+ for (int i = 0; i < types.Length; i++)
+ {
+ var t = new ScriptType(types[i]);
+ if (checkFunc(t))
+ result.Add(t);
+ }
+ }
+
+ ///
+ /// Gets all the types from all the loaded assemblies.
+ ///
+ /// The result collection. Elements will be added to it. Clear it before usage.
+ /// Additional callback used to check if the given type is valid. Returns true if add type, otherwise false.
+ /// Additional callback used to check if the given assembly is valid. Returns true if search for types in the given assembly, otherwise false.
+ public static void GetTypes(List result, Func checkFunc, Func checkAssembly)
+ {
+ // C#/C++ types
+ var assemblies = AppDomain.CurrentDomain.GetAssemblies();
+ for (int i = 0; i < assemblies.Length; i++)
+ {
+ if (checkAssembly(assemblies[i]))
+ GetTypes(assemblies[i], result, checkFunc);
+ }
+
+ // Custom types
+ foreach (var customTypesInfo in CustomTypes)
+ customTypesInfo.GetTypes(result, checkFunc);
+ }
+
///
/// Gets all the types that have the given attribute defined within the given assembly.
///
diff --git a/Source/Editor/Surface/SurfaceStyle.cs b/Source/Editor/Surface/SurfaceStyle.cs
index db25b9f09..198fd7c67 100644
--- a/Source/Editor/Surface/SurfaceStyle.cs
+++ b/Source/Editor/Surface/SurfaceStyle.cs
@@ -178,7 +178,7 @@ namespace FlaxEditor.Surface
color = Colors.Enum;
else if (type.IsValueType)
color = Colors.Structures;
- else if (new ScriptType(typeof(FlaxEngine.Object)).IsAssignableFrom(type))
+ else if (new ScriptType(typeof(FlaxEngine.Object)).IsAssignableFrom(type) || type.IsInterface)
color = Colors.Object;
else if (hint == ConnectionsHint.Vector)
color = Colors.Vector;
diff --git a/Source/Engine/Scripting/BinaryModule.cpp b/Source/Engine/Scripting/BinaryModule.cpp
index ef444afd9..3b9d5a620 100644
--- a/Source/Engine/Scripting/BinaryModule.cpp
+++ b/Source/Engine/Scripting/BinaryModule.cpp
@@ -1060,13 +1060,14 @@ bool ManagedBinaryModule::InvokeMethod(void* method, const Variant& instance, Sp
// Get instance object
void* mInstance = nullptr;
+ const bool withInterfaces = !mMethod->IsStatic() && mMethod->GetParentClass()->IsInterface();
if (!mMethod->IsStatic())
{
// Box instance into C# object
MonoObject* instanceObject = MUtils::BoxVariant(instance);
// Validate instance
- if (!instanceObject || !mono_class_is_subclass_of(mono_object_get_class(instanceObject), mMethod->GetParentClass()->GetNative(), false))
+ if (!instanceObject || !mono_class_is_subclass_of(mono_object_get_class(instanceObject), mMethod->GetParentClass()->GetNative(), withInterfaces))
{
if (!instanceObject)
LOG(Error, "Failed to call method '{0}.{1}' (args count: {2}) without object instance", String(mMethod->GetParentClass()->GetFullName()), String(mMethod->GetName()), parametersCount);
@@ -1101,7 +1102,7 @@ bool ManagedBinaryModule::InvokeMethod(void* method, const Variant& instance, Sp
// Invoke the method
MonoObject* exception = nullptr;
- MonoObject* resultObject = mMethod->Invoke(mInstance, params, &exception);
+ MonoObject* resultObject = withInterfaces ? mMethod->InvokeVirtual((MonoObject*)mInstance, params, &exception) : mMethod->Invoke(mInstance, params, &exception);
if (exception)
{
MException ex(exception);