Add support for array of Visual Script objects

This commit is contained in:
Wojtek Figat
2022-05-01 20:42:05 +02:00
parent c5bfdc66a4
commit 74b23d0e00
20 changed files with 221 additions and 62 deletions

View File

@@ -0,0 +1,148 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
using System;
using System.Reflection;
using FlaxEditor.Content;
using FlaxEngine;
namespace FlaxEditor.Scripting
{
/// <summary>
/// The implementation of the <see cref="IScriptType"/> for array of custom script type.
/// </summary>
[HideInEditor]
internal sealed class ScriptTypeArray : IScriptType
{
/// <summary>
/// The array element type.
/// </summary>
public readonly ScriptType ElementType;
/// <summary>
/// Initializes a new instance of the <see cref="ScriptTypeArray"/> class.
/// </summary>
/// <param name="elementType">Type of the array element.</param>
public ScriptTypeArray(ScriptType elementType)
{
ElementType = elementType;
}
/// <inheritdoc />
public string Name => ElementType + "[]";
/// <inheritdoc />
public string Namespace => ElementType.Namespace;
/// <inheritdoc />
public string TypeName
{
get
{
var result = ElementType + "[]";
var nameSpace = ElementType.Namespace;
if (nameSpace.Length != 0)
result = nameSpace + '.';
return result;
}
}
/// <inheritdoc />
public bool IsPublic => ElementType.IsPublic;
/// <inheritdoc />
public bool IsAbstract => false;
/// <inheritdoc />
public bool IsSealed => true;
/// <inheritdoc />
public bool IsEnum => false;
/// <inheritdoc />
public bool IsClass => true;
/// <inheritdoc />
public bool IsInterface => false;
/// <inheritdoc />
public bool IsArray => true;
/// <inheritdoc />
public bool IsValueType => false;
/// <inheritdoc />
public bool IsGenericType => false;
/// <inheritdoc />
public bool IsReference => false;
/// <inheritdoc />
public bool IsPointer => false;
/// <inheritdoc />
public bool IsStatic => false;
/// <inheritdoc />
public bool CanCreateInstance => false;
/// <inheritdoc />
public ScriptType BaseType => new ScriptType(typeof(Array));
/// <inheritdoc />
public ContentItem ContentItem => null;
/// <inheritdoc />
public object CreateInstance()
{
return null;
}
/// <inheritdoc />
public bool HasInterface(ScriptType c)
{
return false;
}
/// <inheritdoc />
public bool HasAttribute(Type attributeType, bool inherit)
{
return false;
}
/// <inheritdoc />
public object[] GetAttributes(bool inherit)
{
return Utils.GetEmptyArray<object>();
}
/// <inheritdoc />
public ScriptMemberInfo[] GetMembers(string name, MemberTypes type, BindingFlags bindingAttr)
{
return Utils.GetEmptyArray<ScriptMemberInfo>();
}
/// <inheritdoc />
public ScriptMemberInfo[] GetMembers(BindingFlags bindingAttr)
{
return Utils.GetEmptyArray<ScriptMemberInfo>();
}
/// <inheritdoc />
public ScriptMemberInfo[] GetFields(BindingFlags bindingAttr)
{
return Utils.GetEmptyArray<ScriptMemberInfo>();
}
/// <inheritdoc />
public ScriptMemberInfo[] GetProperties(BindingFlags bindingAttr)
{
return Utils.GetEmptyArray<ScriptMemberInfo>();
}
/// <inheritdoc />
public ScriptMemberInfo[] GetMethods(BindingFlags bindingAttr)
{
return Utils.GetEmptyArray<ScriptMemberInfo>();
}
}
}

View File

@@ -113,7 +113,7 @@ namespace FlaxEditor.Scripting
/// </summary>
/// <param name="c">The type of the interface to check.</param>
/// <returns>True if this type implements the given interface, otherwise false.</returns>
bool ImplementInterface(ScriptType c);
bool HasInterface(ScriptType c);
/// <summary>
/// Determines whether the specified attribute was defined for this type.

View File

@@ -703,6 +703,11 @@ namespace FlaxEditor.Scripting
/// </summary>
public static readonly ScriptType Object = new ScriptType(typeof(object));
/// <summary>
/// A <see cref="ScriptType" /> that is FlaxEngine.Object.
/// </summary>
public static readonly ScriptType FlaxObject = new ScriptType(typeof(FlaxEngine.Object));
/// <summary>
/// Gets the type of the script as <see cref="System.Type"/>.
/// </summary>
@@ -827,7 +832,7 @@ namespace FlaxEditor.Scripting
{
if (_managed != null)
return _managed.GetConstructor(Type.EmptyTypes) != null;
return _custom.CanCreateInstance;
return _custom?.CanCreateInstance ?? false;
}
}
@@ -1003,12 +1008,12 @@ namespace FlaxEditor.Scripting
/// </summary>
/// <param name="c">The type of the interface to check.</param>
/// <returns>True if this type implements the given interface, otherwise false.</returns>
public bool ImplementInterface(ScriptType c)
public bool HasInterface(ScriptType c)
{
if (c._managed != null && _managed != null)
return c._managed.IsAssignableFrom(_managed);
if (_custom != null)
return _custom.ImplementInterface(c);
return _custom.HasInterface(c);
return false;
}
@@ -1032,7 +1037,7 @@ namespace FlaxEditor.Scripting
public bool IsAssignableFrom(ScriptType c)
{
if (IsInterface)
return c.ImplementInterface(this);
return c.HasInterface(this);
while (c != Null)
{
if (c == this)
@@ -1075,11 +1080,13 @@ namespace FlaxEditor.Scripting
/// When overridden in a derived class, returns the type of the object encompassed or referred to by the current array, pointer or reference type.
/// </summary>
/// <returns>The type of the object encompassed or referred to by the current array, pointer, or reference type, or <see langword="null" /> if the current type is not an array or a pointer, or is not passed by reference, or represents a generic type or a type parameter in the definition of a generic type or generic method.</returns>
public Type GetElementType()
public ScriptType GetElementType()
{
if (_managed != null)
return _managed.GetElementType();
throw new NotImplementedException("TODO: Script.Type.GetElementType for custom types");
return new ScriptType(_managed.GetElementType());
if (_custom is ScriptTypeArray array)
return array.ElementType;
return Null;
}
/// <summary>
@@ -1112,7 +1119,9 @@ namespace FlaxEditor.Scripting
{
if (_managed != null)
return new ScriptType(_managed.MakeArrayType());
throw new NotImplementedException("TODO: Script.Type.MakeArrayType for custom types");
if (_custom != null)
return new ScriptType(new ScriptTypeArray(this));
return Null;
}
/// <summary>

View File

@@ -335,9 +335,7 @@ namespace FlaxEditor.Scripting
{
var type = assembly.GetType(typeName);
if (type != null)
{
return new ScriptType(type);
}
}
}
@@ -346,8 +344,18 @@ namespace FlaxEditor.Scripting
{
var type = customTypesInfo.GetType(typeName);
if (type)
{
return type;
}
if (typeName.EndsWith("[]"))
{
if (typeName[0] == '.')
typeName = typeName.Substring(1);
typeName = typeName.Substring(0, typeName.Length - 2);
foreach (var customTypesInfo in CustomTypes)
{
var type = customTypesInfo.GetType(typeName);
if (type)
return type.MakeArrayType();
}
}
@@ -361,10 +369,10 @@ namespace FlaxEditor.Scripting
/// <returns>The created object or null if failed.</returns>
public static object CreateInstance(string typeName)
{
var type = GetType(typeName);
if (type)
object obj = null;
ScriptType type = GetType(typeName);
if (type && type.CanCreateInstance)
{
object obj = null;
try
{
return obj = type.CreateInstance();
@@ -373,11 +381,19 @@ namespace FlaxEditor.Scripting
{
Debug.LogException(ex);
}
return obj;
}
return obj;
}
return null;
/// <summary>
/// Creates a one-dimensional <see cref="T:System.Array" /> of the specified type and length.
/// </summary>
/// <param name="elementType">The type of the array to create.</param>
/// <param name="size">The length of the array to create.</param>
/// <returns>The created object or null if failed.</returns>
public static Array CreateArrayInstance(ScriptType elementType, int size)
{
return Array.CreateInstance(GetType(elementType), size);
}
/// <summary>
@@ -402,6 +418,8 @@ namespace FlaxEditor.Scripting
/// <returns>The managed type.</returns>
public static Type GetType(ScriptType type)
{
if (type == ScriptType.Null)
return null;
while (type.Type == null)
type = type.BaseType;
return type.Type;