// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using FlaxEditor.Scripting;
using FlaxEngine;
using FlaxEngine.Json;
using Object = FlaxEngine.Object;
namespace FlaxEditor.Content
{
sealed class VisualScriptParameterInfo : IScriptMemberInfo
{
private readonly VisualScriptType _type;
private readonly VisjectGraphParameter _parameter;
internal VisualScriptParameterInfo(VisualScriptType type, VisjectGraphParameter parameter)
{
_type = type;
_parameter = parameter;
}
///
public string Name => _parameter.Name;
///
public bool IsPublic => _parameter.IsPublic;
///
public bool IsStatic => false;
///
public bool IsVirtual => false;
///
public bool IsAbstract => false;
///
public bool IsGeneric => false;
///
public bool IsField => true;
///
public bool IsProperty => false;
///
public bool IsMethod => false;
///
public bool IsEvent => false;
///
public bool HasGet => true;
///
public bool HasSet => true;
///
public int ParametersCount => 0;
///
public ScriptType DeclaringType => new ScriptType(_type);
///
public ScriptType ValueType
{
get
{
var type = TypeUtils.GetType(_parameter.TypeTypeName);
return type ? type : new ScriptType(_parameter.Type);
}
}
///
public int MetadataToken => 0;
///
public bool HasAttribute(Type attributeType, bool inherit)
{
return Surface.SurfaceMeta.HasAttribute(_parameter, attributeType);
}
///
public object[] GetAttributes(bool inherit)
{
return Surface.SurfaceMeta.GetAttributes(_parameter);
}
///
public ScriptMemberInfo.Parameter[] GetParameters()
{
return null;
}
///
public object GetValue(object obj)
{
return _type.Asset.GetScriptInstanceParameterValue(_parameter.Name, (Object)obj);
}
///
public void SetValue(object obj, object value)
{
_type.Asset.SetScriptInstanceParameterValue(_parameter.Name, (Object)obj, value);
}
}
sealed class VisualScriptMethodInfo : IScriptMemberInfo
{
[Flags]
private enum Flags
{
None = 0,
Static = 1,
Virtual = 2,
Override = 4,
}
private readonly VisualScriptType _type;
private readonly int _index;
private readonly string _name;
private readonly byte _flags;
private readonly ScriptType _returnType;
private readonly ScriptMemberInfo.Parameter[] _parameters;
private object[] _attributes;
internal VisualScriptMethodInfo(VisualScriptType type, int index)
{
_type = type;
_index = index;
type.Asset.GetMethodSignature(index, out _name, out _flags, out var returnTypeName, out var paramNames, out var paramTypeNames, out var paramOuts);
_returnType = TypeUtils.GetType(returnTypeName);
if (paramNames.Length != 0)
{
_parameters = new ScriptMemberInfo.Parameter[paramNames.Length];
for (int i = 0; i < _parameters.Length; i++)
{
_parameters[i] = new ScriptMemberInfo.Parameter
{
Name = paramNames[i],
Type = TypeUtils.GetType(paramTypeNames[i]),
IsOut = paramOuts[i],
};
}
}
else
{
_parameters = Utils.GetEmptyArray();
}
}
///
public string Name => _name;
///
public bool IsPublic => true;
///
public bool IsStatic => (_flags & (byte)Flags.Static) != 0;
///
public bool IsVirtual => (_flags & (byte)Flags.Virtual) != 0;
///
public bool IsAbstract => false;
///
public bool IsGeneric => false;
///
public bool IsField => false;
///
public bool IsProperty => false;
///
public bool IsMethod => true;
///
public bool IsEvent => false;
///
public bool HasGet => false;
///
public bool HasSet => false;
///
public int ParametersCount => _parameters.Length;
///
public ScriptType DeclaringType => (_flags & (byte)Flags.Override) != 0 ? _type.BaseType : new ScriptType(_type);
///
public ScriptType ValueType => _returnType;
public int MetadataToken => 0;
///
public bool HasAttribute(Type attributeType, bool inherit)
{
return GetAttributes(inherit).Any(x => x.GetType() == attributeType);
}
///
public object[] GetAttributes(bool inherit)
{
if (_attributes == null)
{
var data = _type.Asset.GetMethodMetaData(_index, Surface.SurfaceMeta.AttributeMetaTypeID);
_attributes = Surface.SurfaceMeta.GetAttributes(data);
}
return _attributes;
}
///
public ScriptMemberInfo.Parameter[] GetParameters()
{
return _parameters;
}
///
public object GetValue(object obj)
{
throw new NotSupportedException();
}
///
public void SetValue(object obj, object value)
{
throw new NotSupportedException();
}
}
///
/// The implementation of the
///
///
[HideInEditor]
public sealed class VisualScriptType : IScriptType
{
private VisualScript _asset;
private ScriptMemberInfo[] _parameters;
private ScriptMemberInfo[] _methods;
private object[] _attributes;
///
/// Gets the Visual Script asset that contains this type.
///
public VisualScript Asset => _asset;
internal VisualScriptType(VisualScript asset)
{
_asset = asset;
}
private void CacheData()
{
if (_parameters != null)
return;
if (_asset.WaitForLoaded())
return;
FlaxEngine.Content.AssetReloading += OnAssetReloading;
// Cache Visual Script parameters info
var parameters = _asset.Parameters;
if (parameters.Length != 0)
{
_parameters = new ScriptMemberInfo[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
_parameters[i] = new ScriptMemberInfo(new VisualScriptParameterInfo(this, parameters[i]));
}
else
_parameters = Utils.GetEmptyArray();
// Cache Visual Script methods info
var methodsCount = _asset.GetMethodsCount();
if (methodsCount != 0)
{
_methods = new ScriptMemberInfo[methodsCount];
for (int i = 0; i < methodsCount; i++)
_methods[i] = new ScriptMemberInfo(new VisualScriptMethodInfo(this, i));
}
else
_methods = Utils.GetEmptyArray();
// Cache Visual Script attributes
var attributesData = _asset.GetMetaData(Surface.SurfaceMeta.AttributeMetaTypeID);
if (attributesData != null && attributesData.Length != 0)
{
_attributes = Surface.SurfaceMeta.GetAttributes(attributesData);
}
else
_attributes = Utils.GetEmptyArray