Add API_INTERFACE to scripting API bindings for implementing interfaces
This commit is contained in:
@@ -44,6 +44,7 @@
|
|||||||
// Scripting API defines (see C++ scripting documentation for more info)
|
// Scripting API defines (see C++ scripting documentation for more info)
|
||||||
#define API_ENUM(...)
|
#define API_ENUM(...)
|
||||||
#define API_CLASS(...)
|
#define API_CLASS(...)
|
||||||
|
#define API_INTERFACE(...)
|
||||||
#define API_STRUCT(...)
|
#define API_STRUCT(...)
|
||||||
#define API_FUNCTION(...)
|
#define API_FUNCTION(...)
|
||||||
#define API_PROPERTY(...)
|
#define API_PROPERTY(...)
|
||||||
@@ -52,3 +53,4 @@
|
|||||||
#define API_PARAM(...)
|
#define API_PARAM(...)
|
||||||
#define API_INJECT_CPP_CODE(...)
|
#define API_INJECT_CPP_CODE(...)
|
||||||
#define API_AUTO_SERIALIZATION(...) public: void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
|
#define API_AUTO_SERIALIZATION(...) public: void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
|
||||||
|
#define DECLARE_SCRIPTING_TYPE_MINIMAL(type) public: friend class type##Internal; static struct ScriptingTypeInitializer TypeInitializer;
|
||||||
|
|||||||
@@ -108,7 +108,5 @@ class Dictionary;
|
|||||||
inline T& operator&= (T& a, T b) { return (T&)((int&)a &= (int)b); } \
|
inline T& operator&= (T& a, T b) { return (T&)((int&)a &= (int)b); } \
|
||||||
inline T& operator^= (T& a, T b) { return (T&)((int&)a ^= (int)b); }
|
inline T& operator^= (T& a, T b) { return (T&)((int&)a ^= (int)b); }
|
||||||
|
|
||||||
#define DECLARE_SCRIPTING_TYPE_MINIMAL(type) \
|
// Returns byte offset from the object pointer in vtable to the begin of the given inherited type implementation
|
||||||
public: \
|
#define VTABLE_OFFSET(type, baseType) (((intptr)static_cast<baseType*>((type*)1))-1)
|
||||||
friend class type##Internal; \
|
|
||||||
static struct ScriptingTypeInitializer TypeInitializer;
|
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ ScriptingType::ScriptingType()
|
|||||||
, Fullname(nullptr, 0)
|
, Fullname(nullptr, 0)
|
||||||
, Type(ScriptingTypes::Script)
|
, Type(ScriptingTypes::Script)
|
||||||
, BaseTypePtr(nullptr)
|
, BaseTypePtr(nullptr)
|
||||||
|
, Interfaces(nullptr)
|
||||||
{
|
{
|
||||||
Script.Spawn = nullptr;
|
Script.Spawn = nullptr;
|
||||||
Script.VTable = nullptr;
|
Script.VTable = nullptr;
|
||||||
@@ -72,7 +73,7 @@ ScriptingType::ScriptingType()
|
|||||||
Script.DefaultInstance = nullptr;
|
Script.DefaultInstance = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, SpawnHandler spawn, const ScriptingTypeHandle& baseType, SetupScriptVTableHandler setupScriptVTable, SetupScriptObjectVTableHandler setupScriptObjectVTable)
|
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, SpawnHandler spawn, const ScriptingTypeHandle& baseType, SetupScriptVTableHandler setupScriptVTable, SetupScriptObjectVTableHandler setupScriptObjectVTable, const InterfaceImplementation* interfaces)
|
||||||
: ManagedClass(nullptr)
|
: ManagedClass(nullptr)
|
||||||
, Module(module)
|
, Module(module)
|
||||||
, InitRuntime(initRuntime)
|
, InitRuntime(initRuntime)
|
||||||
@@ -80,6 +81,7 @@ ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* modul
|
|||||||
, Type(ScriptingTypes::Script)
|
, Type(ScriptingTypes::Script)
|
||||||
, BaseTypeHandle(baseType)
|
, BaseTypeHandle(baseType)
|
||||||
, BaseTypePtr(nullptr)
|
, BaseTypePtr(nullptr)
|
||||||
|
, Interfaces(interfaces)
|
||||||
, Size(size)
|
, Size(size)
|
||||||
{
|
{
|
||||||
Script.Spawn = spawn;
|
Script.Spawn = spawn;
|
||||||
@@ -91,13 +93,14 @@ ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* modul
|
|||||||
Script.DefaultInstance = nullptr;
|
Script.DefaultInstance = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, SpawnHandler spawn, ScriptingTypeInitializer* baseType, SetupScriptVTableHandler setupScriptVTable, SetupScriptObjectVTableHandler setupScriptObjectVTable)
|
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, SpawnHandler spawn, ScriptingTypeInitializer* baseType, SetupScriptVTableHandler setupScriptVTable, SetupScriptObjectVTableHandler setupScriptObjectVTable, const InterfaceImplementation* interfaces)
|
||||||
: ManagedClass(nullptr)
|
: ManagedClass(nullptr)
|
||||||
, Module(module)
|
, Module(module)
|
||||||
, InitRuntime(initRuntime)
|
, InitRuntime(initRuntime)
|
||||||
, Fullname(fullname)
|
, Fullname(fullname)
|
||||||
, Type(ScriptingTypes::Script)
|
, Type(ScriptingTypes::Script)
|
||||||
, BaseTypePtr(baseType)
|
, BaseTypePtr(baseType)
|
||||||
|
, Interfaces(interfaces)
|
||||||
, Size(size)
|
, Size(size)
|
||||||
{
|
{
|
||||||
Script.Spawn = spawn;
|
Script.Spawn = spawn;
|
||||||
@@ -109,26 +112,28 @@ ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* modul
|
|||||||
Script.DefaultInstance = nullptr;
|
Script.DefaultInstance = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, ScriptingTypeInitializer* baseType)
|
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, ScriptingTypeInitializer* baseType, const InterfaceImplementation* interfaces)
|
||||||
: ManagedClass(nullptr)
|
: ManagedClass(nullptr)
|
||||||
, Module(module)
|
, Module(module)
|
||||||
, InitRuntime(initRuntime)
|
, InitRuntime(initRuntime)
|
||||||
, Fullname(fullname)
|
, Fullname(fullname)
|
||||||
, Type(ScriptingTypes::Class)
|
, Type(ScriptingTypes::Class)
|
||||||
, BaseTypePtr(baseType)
|
, BaseTypePtr(baseType)
|
||||||
|
, Interfaces(interfaces)
|
||||||
, Size(size)
|
, Size(size)
|
||||||
{
|
{
|
||||||
Class.Ctor = ctor;
|
Class.Ctor = ctor;
|
||||||
Class.Dtor = dtor;
|
Class.Dtor = dtor;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, Copy copy, Box box, Unbox unbox, GetField getField, SetField setField, ScriptingTypeInitializer* baseType)
|
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, Copy copy, Box box, Unbox unbox, GetField getField, SetField setField, ScriptingTypeInitializer* baseType, const InterfaceImplementation* interfaces)
|
||||||
: ManagedClass(nullptr)
|
: ManagedClass(nullptr)
|
||||||
, Module(module)
|
, Module(module)
|
||||||
, InitRuntime(initRuntime)
|
, InitRuntime(initRuntime)
|
||||||
, Fullname(fullname)
|
, Fullname(fullname)
|
||||||
, Type(ScriptingTypes::Structure)
|
, Type(ScriptingTypes::Structure)
|
||||||
, BaseTypePtr(baseType)
|
, BaseTypePtr(baseType)
|
||||||
|
, Interfaces(interfaces)
|
||||||
, Size(size)
|
, Size(size)
|
||||||
{
|
{
|
||||||
Struct.Ctor = ctor;
|
Struct.Ctor = ctor;
|
||||||
@@ -140,6 +145,18 @@ ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* modul
|
|||||||
Struct.SetField = setField;
|
Struct.SetField = setField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, InitRuntimeHandler initRuntime, ScriptingTypeInitializer* baseType, const InterfaceImplementation* interfaces)
|
||||||
|
: ManagedClass(nullptr)
|
||||||
|
, Module(module)
|
||||||
|
, InitRuntime(initRuntime)
|
||||||
|
, Fullname(fullname)
|
||||||
|
, Type(ScriptingTypes::Interface)
|
||||||
|
, BaseTypePtr(baseType)
|
||||||
|
, Interfaces(interfaces)
|
||||||
|
, Size(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
ScriptingType::ScriptingType(const ScriptingType& other)
|
ScriptingType::ScriptingType(const ScriptingType& other)
|
||||||
: ManagedClass(other.ManagedClass)
|
: ManagedClass(other.ManagedClass)
|
||||||
, Module(other.Module)
|
, Module(other.Module)
|
||||||
@@ -148,6 +165,7 @@ ScriptingType::ScriptingType(const ScriptingType& other)
|
|||||||
, Type(other.Type)
|
, Type(other.Type)
|
||||||
, BaseTypeHandle(other.BaseTypeHandle)
|
, BaseTypeHandle(other.BaseTypeHandle)
|
||||||
, BaseTypePtr(other.BaseTypePtr)
|
, BaseTypePtr(other.BaseTypePtr)
|
||||||
|
, Interfaces(other.Interfaces)
|
||||||
, Size(other.Size)
|
, Size(other.Size)
|
||||||
{
|
{
|
||||||
switch (other.Type)
|
switch (other.Type)
|
||||||
@@ -176,6 +194,8 @@ ScriptingType::ScriptingType(const ScriptingType& other)
|
|||||||
break;
|
break;
|
||||||
case ScriptingTypes::Enum:
|
case ScriptingTypes::Enum:
|
||||||
break;
|
break;
|
||||||
|
case ScriptingTypes::Interface:
|
||||||
|
break;
|
||||||
default: ;
|
default: ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,6 +208,7 @@ ScriptingType::ScriptingType(ScriptingType&& other)
|
|||||||
, Type(other.Type)
|
, Type(other.Type)
|
||||||
, BaseTypeHandle(other.BaseTypeHandle)
|
, BaseTypeHandle(other.BaseTypeHandle)
|
||||||
, BaseTypePtr(other.BaseTypePtr)
|
, BaseTypePtr(other.BaseTypePtr)
|
||||||
|
, Interfaces(other.Interfaces)
|
||||||
, Size(other.Size)
|
, Size(other.Size)
|
||||||
{
|
{
|
||||||
switch (other.Type)
|
switch (other.Type)
|
||||||
@@ -220,6 +241,8 @@ ScriptingType::ScriptingType(ScriptingType&& other)
|
|||||||
break;
|
break;
|
||||||
case ScriptingTypes::Enum:
|
case ScriptingTypes::Enum:
|
||||||
break;
|
break;
|
||||||
|
case ScriptingTypes::Interface:
|
||||||
|
break;
|
||||||
default: ;
|
default: ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,6 +263,8 @@ ScriptingType::~ScriptingType()
|
|||||||
break;
|
break;
|
||||||
case ScriptingTypes::Enum:
|
case ScriptingTypes::Enum:
|
||||||
break;
|
break;
|
||||||
|
case ScriptingTypes::Interface:
|
||||||
|
break;
|
||||||
default: ;
|
default: ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -269,16 +294,40 @@ ScriptingObject* ScriptingType::GetDefaultInstance() const
|
|||||||
return Script.DefaultInstance;
|
return Script.DefaultInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ScriptingType::InterfaceImplementation* ScriptingType::GetInterface(const ScriptingTypeInitializer* interfaceType) const
|
||||||
|
{
|
||||||
|
const InterfaceImplementation* interfaces = Interfaces;
|
||||||
|
if (interfaces)
|
||||||
|
{
|
||||||
|
while (interfaces->InterfaceType)
|
||||||
|
{
|
||||||
|
if (interfaces->InterfaceType == interfaceType)
|
||||||
|
return interfaces;
|
||||||
|
interfaces++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (BaseTypeHandle)
|
||||||
|
{
|
||||||
|
return BaseTypeHandle.GetType().GetInterface(interfaceType);
|
||||||
|
}
|
||||||
|
if (BaseTypePtr)
|
||||||
|
{
|
||||||
|
return BaseTypePtr->GetType().GetInterface(interfaceType);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
String ScriptingType::ToString() const
|
String ScriptingType::ToString() const
|
||||||
{
|
{
|
||||||
return String(Fullname.Get(), Fullname.Length());
|
return String(Fullname.Get(), Fullname.Length());
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::SpawnHandler spawn, ScriptingTypeInitializer* baseType, ScriptingType::SetupScriptVTableHandler setupScriptVTable, ScriptingType::SetupScriptObjectVTableHandler setupScriptObjectVTable)
|
ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::SpawnHandler spawn, ScriptingTypeInitializer* baseType, ScriptingType::SetupScriptVTableHandler setupScriptVTable, ScriptingType::SetupScriptObjectVTableHandler setupScriptObjectVTable, const ScriptingType::InterfaceImplementation* interfaces)
|
||||||
: ScriptingTypeHandle(module, module->Types.Count())
|
: ScriptingTypeHandle(module, module->Types.Count())
|
||||||
{
|
{
|
||||||
|
// Script
|
||||||
module->Types.AddUninitialized();
|
module->Types.AddUninitialized();
|
||||||
new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, size, initRuntime, spawn, baseType, setupScriptVTable, setupScriptObjectVTable);
|
new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, size, initRuntime, spawn, baseType, setupScriptVTable, setupScriptObjectVTable, interfaces);
|
||||||
const MString typeName(fullname.Get(), fullname.Length());
|
const MString typeName(fullname.Get(), fullname.Length());
|
||||||
#if BUILD_DEBUG
|
#if BUILD_DEBUG
|
||||||
if (module->TypeNameToTypeIndex.ContainsKey(typeName))
|
if (module->TypeNameToTypeIndex.ContainsKey(typeName))
|
||||||
@@ -289,11 +338,12 @@ ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const S
|
|||||||
module->TypeNameToTypeIndex[typeName] = TypeIndex;
|
module->TypeNameToTypeIndex[typeName] = TypeIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingTypeInitializer* baseType)
|
ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingTypeInitializer* baseType, const ScriptingType::InterfaceImplementation* interfaces)
|
||||||
: ScriptingTypeHandle(module, module->Types.Count())
|
: ScriptingTypeHandle(module, module->Types.Count())
|
||||||
{
|
{
|
||||||
|
// Class
|
||||||
module->Types.AddUninitialized();
|
module->Types.AddUninitialized();
|
||||||
new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, size, initRuntime, ctor, dtor, baseType);
|
new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, size, initRuntime, ctor, dtor, baseType, interfaces);
|
||||||
const MString typeName(fullname.Get(), fullname.Length());
|
const MString typeName(fullname.Get(), fullname.Length());
|
||||||
#if BUILD_DEBUG
|
#if BUILD_DEBUG
|
||||||
if (module->TypeNameToTypeIndex.ContainsKey(typeName))
|
if (module->TypeNameToTypeIndex.ContainsKey(typeName))
|
||||||
@@ -304,11 +354,28 @@ ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const S
|
|||||||
module->TypeNameToTypeIndex[typeName] = TypeIndex;
|
module->TypeNameToTypeIndex[typeName] = TypeIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingType::Copy copy, ScriptingType::Box box, ScriptingType::Unbox unbox, ScriptingType::GetField getField, ScriptingType::SetField setField, ScriptingTypeInitializer* baseType)
|
ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingType::Copy copy, ScriptingType::Box box, ScriptingType::Unbox unbox, ScriptingType::GetField getField, ScriptingType::SetField setField, ScriptingTypeInitializer* baseType, const ScriptingType::InterfaceImplementation* interfaces)
|
||||||
: ScriptingTypeHandle(module, module->Types.Count())
|
: ScriptingTypeHandle(module, module->Types.Count())
|
||||||
{
|
{
|
||||||
|
// Structure
|
||||||
module->Types.AddUninitialized();
|
module->Types.AddUninitialized();
|
||||||
new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, size, initRuntime, ctor, dtor, copy, box, unbox, getField, setField, baseType);
|
new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, size, initRuntime, ctor, dtor, copy, box, unbox, getField, setField, baseType, interfaces);
|
||||||
|
const MString typeName(fullname.Get(), fullname.Length());
|
||||||
|
#if BUILD_DEBUG
|
||||||
|
if (module->TypeNameToTypeIndex.ContainsKey(typeName))
|
||||||
|
{
|
||||||
|
LOG(Error, "Duplicated native typename {0} from module {1}.", String(fullname), String(module->GetName()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
module->TypeNameToTypeIndex[typeName] = TypeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, ScriptingType::InitRuntimeHandler initRuntime, ScriptingTypeInitializer* baseType, const ScriptingType::InterfaceImplementation* interfaces)
|
||||||
|
: ScriptingTypeHandle(module, module->Types.Count())
|
||||||
|
{
|
||||||
|
// Interface
|
||||||
|
module->Types.AddUninitialized();
|
||||||
|
new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, initRuntime, baseType, interfaces);
|
||||||
const MString typeName(fullname.Get(), fullname.Length());
|
const MString typeName(fullname.Get(), fullname.Length());
|
||||||
#if BUILD_DEBUG
|
#if BUILD_DEBUG
|
||||||
if (module->TypeNameToTypeIndex.ContainsKey(typeName))
|
if (module->TypeNameToTypeIndex.ContainsKey(typeName))
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ enum class ScriptingTypes
|
|||||||
Structure = 1,
|
Structure = 1,
|
||||||
Enum = 2,
|
Enum = 2,
|
||||||
Class = 3,
|
Class = 3,
|
||||||
|
Interface = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -116,6 +117,15 @@ struct FLAXENGINE_API ScriptingType
|
|||||||
typedef void (*GetField)(void* ptr, const String& name, Variant& value);
|
typedef void (*GetField)(void* ptr, const String& name, Variant& value);
|
||||||
typedef void (*SetField)(void* ptr, const String& name, const Variant& value);
|
typedef void (*SetField)(void* ptr, const String& name, const Variant& value);
|
||||||
|
|
||||||
|
struct InterfaceImplementation
|
||||||
|
{
|
||||||
|
// Pointer to the type of the implemented interface.
|
||||||
|
const ScriptingTypeInitializer* InterfaceType;
|
||||||
|
|
||||||
|
// The offset (in bytes) from the object pointer to the interface implementation. Used for casting object to the interface.
|
||||||
|
int16 VTableOffset;
|
||||||
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The managed class (cached, can be null if missing).
|
/// The managed class (cached, can be null if missing).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -151,6 +161,11 @@ struct FLAXENGINE_API ScriptingType
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
const ScriptingTypeInitializer* BaseTypePtr;
|
const ScriptingTypeInitializer* BaseTypePtr;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of interfaces implemented by this type (null if unused, list ends with null entry).
|
||||||
|
/// </summary>
|
||||||
|
const InterfaceImplementation* Interfaces;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The native size of the type value (in bytes).
|
/// The native size of the type value (in bytes).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -196,15 +211,6 @@ struct FLAXENGINE_API ScriptingType
|
|||||||
mutable ScriptingObject* DefaultInstance;
|
mutable ScriptingObject* DefaultInstance;
|
||||||
} Script;
|
} Script;
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
// Class constructor method pointer
|
|
||||||
Ctor Ctor;
|
|
||||||
|
|
||||||
// Class destructor method pointer
|
|
||||||
Dtor Dtor;
|
|
||||||
} Class;
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
// Structure constructor method pointer
|
// Structure constructor method pointer
|
||||||
@@ -228,13 +234,23 @@ struct FLAXENGINE_API ScriptingType
|
|||||||
// Structure field value setter
|
// Structure field value setter
|
||||||
SetField SetField;
|
SetField SetField;
|
||||||
} Struct;
|
} Struct;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
// Class constructor method pointer
|
||||||
|
Ctor Ctor;
|
||||||
|
|
||||||
|
// Class destructor method pointer
|
||||||
|
Dtor Dtor;
|
||||||
|
} Class;
|
||||||
};
|
};
|
||||||
|
|
||||||
ScriptingType();
|
ScriptingType();
|
||||||
ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, SpawnHandler spawn, const ScriptingTypeHandle& baseType, SetupScriptVTableHandler setupScriptVTable = nullptr, SetupScriptObjectVTableHandler setupScriptObjectVTable = nullptr);
|
ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, SpawnHandler spawn, const ScriptingTypeHandle& baseType, SetupScriptVTableHandler setupScriptVTable = nullptr, SetupScriptObjectVTableHandler setupScriptObjectVTable = nullptr, const InterfaceImplementation* interfaces = nullptr);
|
||||||
ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime = DefaultInitRuntime, SpawnHandler spawn = DefaultSpawn, ScriptingTypeInitializer* baseType = nullptr, SetupScriptVTableHandler setupScriptVTable = nullptr, SetupScriptObjectVTableHandler setupScriptObjectVTable = nullptr);
|
ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime = DefaultInitRuntime, SpawnHandler spawn = DefaultSpawn, ScriptingTypeInitializer* baseType = nullptr, SetupScriptVTableHandler setupScriptVTable = nullptr, SetupScriptObjectVTableHandler setupScriptObjectVTable = nullptr, const InterfaceImplementation* interfaces = nullptr);
|
||||||
ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, ScriptingTypeInitializer* baseType);
|
ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, ScriptingTypeInitializer* baseType, const InterfaceImplementation* interfaces = nullptr);
|
||||||
ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, Copy copy, Box box, Unbox unbox, GetField getField, SetField setField, ScriptingTypeInitializer* baseType);
|
ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, Copy copy, Box box, Unbox unbox, GetField getField, SetField setField, ScriptingTypeInitializer* baseType, const InterfaceImplementation* interfaces = nullptr);
|
||||||
|
ScriptingType(const StringAnsiView& fullname, BinaryModule* module, InitRuntimeHandler initRuntime, ScriptingTypeInitializer* baseType, const InterfaceImplementation* interfaces = nullptr);
|
||||||
ScriptingType(const ScriptingType& other);
|
ScriptingType(const ScriptingType& other);
|
||||||
ScriptingType(ScriptingType&& other);
|
ScriptingType(ScriptingType&& other);
|
||||||
ScriptingType& operator=(ScriptingType&& other) = delete;
|
ScriptingType& operator=(ScriptingType&& other) = delete;
|
||||||
@@ -270,6 +286,11 @@ struct FLAXENGINE_API ScriptingType
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
ScriptingObject* GetDefaultInstance() const;
|
ScriptingObject* GetDefaultInstance() const;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the pointer to the implementation of the given interface type for this scripting type (including base types). Returns null if given interface is not implemented.
|
||||||
|
/// </summary>
|
||||||
|
const InterfaceImplementation* GetInterface(const ScriptingTypeInitializer* interfaceType) const;
|
||||||
|
|
||||||
String ToString() const;
|
String ToString() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -278,9 +299,10 @@ struct FLAXENGINE_API ScriptingType
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
struct FLAXENGINE_API ScriptingTypeInitializer : ScriptingTypeHandle
|
struct FLAXENGINE_API ScriptingTypeInitializer : ScriptingTypeHandle
|
||||||
{
|
{
|
||||||
ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime = ScriptingType::DefaultInitRuntime, ScriptingType::SpawnHandler spawn = ScriptingType::DefaultSpawn, ScriptingTypeInitializer* baseType = nullptr, ScriptingType::SetupScriptVTableHandler setupScriptVTable = nullptr, ScriptingType::SetupScriptObjectVTableHandler setupScriptObjectVTable = nullptr);
|
ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime = ScriptingType::DefaultInitRuntime, ScriptingType::SpawnHandler spawn = ScriptingType::DefaultSpawn, ScriptingTypeInitializer* baseType = nullptr, ScriptingType::SetupScriptVTableHandler setupScriptVTable = nullptr, ScriptingType::SetupScriptObjectVTableHandler setupScriptObjectVTable = nullptr, const ScriptingType::InterfaceImplementation* interfaces = nullptr);
|
||||||
ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingTypeInitializer* baseType = nullptr);
|
ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingTypeInitializer* baseType = nullptr, const ScriptingType::InterfaceImplementation* interfaces = nullptr);
|
||||||
ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingType::Copy copy, ScriptingType::Box box, ScriptingType::Unbox unbox, ScriptingType::GetField getField, ScriptingType::SetField setField, ScriptingTypeInitializer* baseType = nullptr);
|
ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingType::Copy copy, ScriptingType::Box box, ScriptingType::Unbox unbox, ScriptingType::GetField getField, ScriptingType::SetField setField, ScriptingTypeInitializer* baseType = nullptr, const ScriptingType::InterfaceImplementation* interfaces = nullptr);
|
||||||
|
ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, ScriptingType::InitRuntimeHandler initRuntime, ScriptingTypeInitializer* baseType = nullptr, const ScriptingType::InterfaceImplementation* interfaces = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ namespace Flax.Build.Bindings
|
|||||||
public virtual bool IsClass => false;
|
public virtual bool IsClass => false;
|
||||||
public virtual bool IsStruct => false;
|
public virtual bool IsStruct => false;
|
||||||
public virtual bool IsEnum => false;
|
public virtual bool IsEnum => false;
|
||||||
|
public virtual bool IsInterface => false;
|
||||||
public virtual bool IsValueType => false;
|
public virtual bool IsValueType => false;
|
||||||
public virtual bool IsScriptingObject => false;
|
public virtual bool IsScriptingObject => false;
|
||||||
public virtual bool IsPod => false;
|
public virtual bool IsPod => false;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace Flax.Build.Bindings
|
|||||||
{
|
{
|
||||||
public static readonly string Enum = "API_ENUM";
|
public static readonly string Enum = "API_ENUM";
|
||||||
public static readonly string Class = "API_CLASS";
|
public static readonly string Class = "API_CLASS";
|
||||||
|
public static readonly string Interface = "API_INTERFACE";
|
||||||
public static readonly string Struct = "API_STRUCT";
|
public static readonly string Struct = "API_STRUCT";
|
||||||
public static readonly string Function = "API_FUNCTION";
|
public static readonly string Function = "API_FUNCTION";
|
||||||
public static readonly string Property = "API_PROPERTY";
|
public static readonly string Property = "API_PROPERTY";
|
||||||
@@ -27,6 +28,7 @@ namespace Flax.Build.Bindings
|
|||||||
Enum,
|
Enum,
|
||||||
Class,
|
Class,
|
||||||
Struct,
|
Struct,
|
||||||
|
Interface,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -947,9 +947,7 @@ namespace Flax.Build.Bindings
|
|||||||
var classInfo = typeInfo as ClassInfo;
|
var classInfo = typeInfo as ClassInfo;
|
||||||
var structureInfo = typeInfo as StructureInfo;
|
var structureInfo = typeInfo as StructureInfo;
|
||||||
var baseType = classInfo?.BaseType ?? structureInfo?.BaseType;
|
var baseType = classInfo?.BaseType ?? structureInfo?.BaseType;
|
||||||
if (baseType != null && baseType.Type == "ISerializable")
|
if (classInfo != null && classInfo.IsBaseTypeHidden)
|
||||||
baseType = null;
|
|
||||||
else if (classInfo != null && classInfo.IsBaseTypeHidden)
|
|
||||||
baseType = null;
|
baseType = null;
|
||||||
CppAutoSerializeFields.Clear();
|
CppAutoSerializeFields.Clear();
|
||||||
CppAutoSerializeProperties.Clear();
|
CppAutoSerializeProperties.Clear();
|
||||||
@@ -1038,6 +1036,25 @@ namespace Flax.Build.Bindings
|
|||||||
contents.Append('}').AppendLine();
|
contents.Append('}').AppendLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GenerateCppInterfaceInheritanceTable(BuildData buildData, StringBuilder contents, ModuleInfo moduleInfo, ClassStructInfo typeInfo, string typeNameNative)
|
||||||
|
{
|
||||||
|
var interfacesPtr = "nullptr";
|
||||||
|
var interfaces = typeInfo.Interfaces;
|
||||||
|
if (interfaces != null)
|
||||||
|
{
|
||||||
|
interfacesPtr = typeNameNative + "_Interfaces";
|
||||||
|
contents.Append("static const ScriptingType::InterfaceImplementation ").Append(interfacesPtr).AppendLine("[] = {");
|
||||||
|
for (int i = 0; i < interfaces.Count; i++)
|
||||||
|
{
|
||||||
|
var interfaceInfo = interfaces[i];
|
||||||
|
contents.Append(" { &").Append(interfaceInfo.NativeName).Append("::TypeInitializer, (int16)VTABLE_OFFSET(").Append(typeInfo.NativeName).Append(", ").Append(interfaceInfo.NativeName).AppendLine(") },");
|
||||||
|
}
|
||||||
|
contents.AppendLine(" { nullptr, 0 },");
|
||||||
|
contents.AppendLine("};");
|
||||||
|
}
|
||||||
|
return interfacesPtr;
|
||||||
|
}
|
||||||
|
|
||||||
private static void GenerateCppClass(BuildData buildData, StringBuilder contents, ModuleInfo moduleInfo, ClassInfo classInfo)
|
private static void GenerateCppClass(BuildData buildData, StringBuilder contents, ModuleInfo moduleInfo, ClassInfo classInfo)
|
||||||
{
|
{
|
||||||
var classTypeNameNative = classInfo.FullNameNative;
|
var classTypeNameNative = classInfo.FullNameNative;
|
||||||
@@ -1311,6 +1328,9 @@ namespace Flax.Build.Bindings
|
|||||||
contents.Append('}').Append(';').AppendLine();
|
contents.Append('}').Append(';').AppendLine();
|
||||||
contents.AppendLine();
|
contents.AppendLine();
|
||||||
|
|
||||||
|
// Interfaces
|
||||||
|
var interfacesTable = GenerateCppInterfaceInheritanceTable(buildData, contents, moduleInfo, classInfo, classTypeNameNative);
|
||||||
|
|
||||||
// Type initializer
|
// Type initializer
|
||||||
contents.Append($"ScriptingTypeInitializer {classTypeNameNative}::TypeInitializer((BinaryModule*)GetBinaryModule{moduleInfo.Name}(), ");
|
contents.Append($"ScriptingTypeInitializer {classTypeNameNative}::TypeInitializer((BinaryModule*)GetBinaryModule{moduleInfo.Name}(), ");
|
||||||
contents.Append($"StringAnsiView(\"{classTypeNameManaged}\", {classTypeNameManaged.Length}), ");
|
contents.Append($"StringAnsiView(\"{classTypeNameManaged}\", {classTypeNameManaged.Length}), ");
|
||||||
@@ -1330,8 +1350,9 @@ namespace Flax.Build.Bindings
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
contents.Append($"&{classTypeNameInternal}Internal::Ctor, &{classTypeNameInternal}Internal::Dtor");
|
contents.Append($"&{classTypeNameInternal}Internal::Ctor, &{classTypeNameInternal}Internal::Dtor, nullptr");
|
||||||
}
|
}
|
||||||
|
contents.Append(", ").Append(interfacesTable);
|
||||||
contents.Append(");");
|
contents.Append(");");
|
||||||
contents.AppendLine();
|
contents.AppendLine();
|
||||||
|
|
||||||
@@ -1526,6 +1547,42 @@ namespace Flax.Build.Bindings
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void GenerateCppInterface(BuildData buildData, StringBuilder contents, ModuleInfo moduleInfo, InterfaceInfo interfaceInfo)
|
||||||
|
{
|
||||||
|
var interfaceTypeNameNative = interfaceInfo.FullNameNative;
|
||||||
|
var interfaceTypeNameManaged = interfaceInfo.FullNameManaged;
|
||||||
|
var interfaceTypeNameManagedInternalCall = interfaceTypeNameManaged.Replace('+', '/');
|
||||||
|
var interfaceTypeNameInternal = interfaceInfo.NativeName;
|
||||||
|
if (interfaceInfo.Parent != null && !(interfaceInfo.Parent is FileInfo))
|
||||||
|
interfaceTypeNameInternal = interfaceInfo.Parent.FullNameNative + '_' + interfaceTypeNameInternal;
|
||||||
|
|
||||||
|
contents.AppendLine();
|
||||||
|
contents.AppendFormat("class {0}Internal", interfaceTypeNameInternal).AppendLine();
|
||||||
|
contents.Append('{').AppendLine();
|
||||||
|
contents.AppendLine("public:");
|
||||||
|
|
||||||
|
// Runtime initialization (internal methods binding)
|
||||||
|
contents.AppendLine(" static void InitRuntime()");
|
||||||
|
contents.AppendLine(" {");
|
||||||
|
contents.AppendLine(" }").AppendLine();
|
||||||
|
|
||||||
|
contents.Append('}').Append(';').AppendLine();
|
||||||
|
contents.AppendLine();
|
||||||
|
|
||||||
|
// Type initializer
|
||||||
|
contents.Append($"ScriptingTypeInitializer {interfaceTypeNameNative}::TypeInitializer((BinaryModule*)GetBinaryModule{moduleInfo.Name}(), ");
|
||||||
|
contents.Append($"StringAnsiView(\"{interfaceTypeNameManaged}\", {interfaceTypeNameManaged.Length}), ");
|
||||||
|
contents.Append($"&{interfaceTypeNameInternal}Internal::InitRuntime");
|
||||||
|
contents.Append(");");
|
||||||
|
contents.AppendLine();
|
||||||
|
|
||||||
|
// Nested types
|
||||||
|
foreach (var apiTypeInfo in interfaceInfo.Children)
|
||||||
|
{
|
||||||
|
GenerateCppType(buildData, contents, moduleInfo, apiTypeInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static bool GenerateCppType(BuildData buildData, StringBuilder contents, ModuleInfo moduleInfo, object type)
|
private static bool GenerateCppType(BuildData buildData, StringBuilder contents, ModuleInfo moduleInfo, object type)
|
||||||
{
|
{
|
||||||
if (type is ApiTypeInfo apiTypeInfo && apiTypeInfo.IsInBuild)
|
if (type is ApiTypeInfo apiTypeInfo && apiTypeInfo.IsInBuild)
|
||||||
@@ -1537,6 +1594,8 @@ namespace Flax.Build.Bindings
|
|||||||
GenerateCppClass(buildData, contents, moduleInfo, classInfo);
|
GenerateCppClass(buildData, contents, moduleInfo, classInfo);
|
||||||
else if (type is StructureInfo structureInfo)
|
else if (type is StructureInfo structureInfo)
|
||||||
GenerateCppStruct(buildData, contents, moduleInfo, structureInfo);
|
GenerateCppStruct(buildData, contents, moduleInfo, structureInfo);
|
||||||
|
else if (type is InterfaceInfo interfaceInfo)
|
||||||
|
GenerateCppInterface(buildData, contents, moduleInfo, interfaceInfo);
|
||||||
else if (type is InjectCppCodeInfo injectCppCodeInfo)
|
else if (type is InjectCppCodeInfo injectCppCodeInfo)
|
||||||
contents.AppendLine(injectCppCodeInfo.Code);
|
contents.AppendLine(injectCppCodeInfo.Code);
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -383,6 +383,95 @@ namespace Flax.Build.Bindings
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ParseInheritance(ref ParsingContext context, ClassStructInfo desc, out bool isFinal)
|
||||||
|
{
|
||||||
|
desc.BaseType = null;
|
||||||
|
desc.BaseTypeInheritance = AccessLevel.Private;
|
||||||
|
|
||||||
|
var token = context.Tokenizer.NextToken();
|
||||||
|
isFinal = token.Value == "final";
|
||||||
|
if (isFinal)
|
||||||
|
token = context.Tokenizer.NextToken();
|
||||||
|
|
||||||
|
if (token.Type == TokenType.Colon)
|
||||||
|
{
|
||||||
|
while (token.Type != TokenType.LeftCurlyBrace)
|
||||||
|
{
|
||||||
|
var accessToken = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
||||||
|
switch (accessToken.Value)
|
||||||
|
{
|
||||||
|
case "public":
|
||||||
|
desc.BaseTypeInheritance = AccessLevel.Public;
|
||||||
|
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
||||||
|
break;
|
||||||
|
case "protected":
|
||||||
|
desc.BaseTypeInheritance = AccessLevel.Protected;
|
||||||
|
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
||||||
|
break;
|
||||||
|
case "private":
|
||||||
|
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
token = accessToken;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var baseTypeInfo = new TypeInfo
|
||||||
|
{
|
||||||
|
Type = token.Value,
|
||||||
|
};
|
||||||
|
if (token.Value.Length > 2 && token.Value[0] == 'I' && char.IsUpper(token.Value[1]))
|
||||||
|
{
|
||||||
|
// Interface
|
||||||
|
if (desc.InterfaceNames == null)
|
||||||
|
desc.InterfaceNames = new List<TypeInfo>();
|
||||||
|
desc.InterfaceNames.Add(baseTypeInfo);
|
||||||
|
token = context.Tokenizer.NextToken();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc.BaseType != null)
|
||||||
|
{
|
||||||
|
// Allow for multiple base classes, just the first one needs to be a valid base type
|
||||||
|
break;
|
||||||
|
throw new Exception($"Invalid '{desc.Name}' inheritance (only single base class is allowed for scripting types, excluding interfaces).");
|
||||||
|
}
|
||||||
|
desc.BaseType = baseTypeInfo;
|
||||||
|
token = context.Tokenizer.NextToken();
|
||||||
|
if (token.Type == TokenType.LeftCurlyBrace)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (token.Type == TokenType.LeftAngleBracket)
|
||||||
|
{
|
||||||
|
var genericType = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
||||||
|
token = context.Tokenizer.ExpectToken(TokenType.RightAngleBracket);
|
||||||
|
desc.BaseType.GenericArgs = new List<TypeInfo>
|
||||||
|
{
|
||||||
|
new TypeInfo
|
||||||
|
{
|
||||||
|
Type = genericType.Value,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: find better way to resolve this (custom base type attribute?)
|
||||||
|
if (desc.BaseType.Type == "ShaderAssetTypeBase")
|
||||||
|
{
|
||||||
|
desc.BaseType = desc.BaseType.GenericArgs[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
token = context.Tokenizer.NextToken();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
token = context.Tokenizer.PreviousToken();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No base type
|
||||||
|
token = context.Tokenizer.PreviousToken();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static ClassInfo ParseClass(ref ParsingContext context)
|
private static ClassInfo ParseClass(ref ParsingContext context)
|
||||||
{
|
{
|
||||||
var desc = new ClassInfo
|
var desc = new ClassInfo
|
||||||
@@ -410,64 +499,8 @@ namespace Flax.Build.Bindings
|
|||||||
// Read name
|
// Read name
|
||||||
desc.Name = desc.NativeName = ParseName(ref context);
|
desc.Name = desc.NativeName = ParseName(ref context);
|
||||||
|
|
||||||
// Read class inheritance
|
// Read inheritance
|
||||||
token = context.Tokenizer.NextToken();
|
ParseInheritance(ref context, desc, out var isFinal);
|
||||||
var isFinal = token.Value == "final";
|
|
||||||
if (isFinal)
|
|
||||||
token = context.Tokenizer.NextToken();
|
|
||||||
if (token.Type == TokenType.Colon)
|
|
||||||
{
|
|
||||||
// Current class does have inheritance defined
|
|
||||||
var accessToken = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
|
||||||
switch (accessToken.Value)
|
|
||||||
{
|
|
||||||
case "public":
|
|
||||||
desc.BaseTypeInheritance = AccessLevel.Public;
|
|
||||||
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
|
||||||
break;
|
|
||||||
case "protected":
|
|
||||||
desc.BaseTypeInheritance = AccessLevel.Protected;
|
|
||||||
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
|
||||||
break;
|
|
||||||
case "private":
|
|
||||||
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
desc.BaseType = new TypeInfo
|
|
||||||
{
|
|
||||||
Type = token.Value,
|
|
||||||
};
|
|
||||||
token = context.Tokenizer.NextToken();
|
|
||||||
if (token.Type == TokenType.LeftAngleBracket)
|
|
||||||
{
|
|
||||||
var genericType = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
|
||||||
context.Tokenizer.ExpectToken(TokenType.RightAngleBracket);
|
|
||||||
desc.BaseType.GenericArgs = new List<TypeInfo>
|
|
||||||
{
|
|
||||||
new TypeInfo
|
|
||||||
{
|
|
||||||
Type = genericType.Value,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: find better way to resolve this (custom base type attribute?)
|
|
||||||
if (desc.BaseType.Type == "ShaderAssetTypeBase")
|
|
||||||
{
|
|
||||||
desc.BaseType = desc.BaseType.GenericArgs[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
token = context.Tokenizer.PreviousToken();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No base type
|
|
||||||
token = context.Tokenizer.PreviousToken();
|
|
||||||
desc.BaseType = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process tag parameters
|
// Process tag parameters
|
||||||
foreach (var tag in tagParams)
|
foreach (var tag in tagParams)
|
||||||
@@ -523,6 +556,68 @@ namespace Flax.Build.Bindings
|
|||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static InterfaceInfo ParseInterface(ref ParsingContext context)
|
||||||
|
{
|
||||||
|
var desc = new InterfaceInfo
|
||||||
|
{
|
||||||
|
Children = new List<ApiTypeInfo>(),
|
||||||
|
Access = context.CurrentAccessLevel,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read the documentation comment
|
||||||
|
desc.Comment = ParseComment(ref context);
|
||||||
|
|
||||||
|
// Read parameters from the tag
|
||||||
|
var tagParams = ParseTagParameters(ref context);
|
||||||
|
|
||||||
|
// Read 'class' keyword
|
||||||
|
var token = context.Tokenizer.NextToken();
|
||||||
|
if (token.Value != "class")
|
||||||
|
throw new Exception($"Invalid API_INTERFACE usage (expected 'class' keyword but got '{token.Value} {context.Tokenizer.NextToken().Value}').");
|
||||||
|
|
||||||
|
// Read name
|
||||||
|
desc.Name = desc.NativeName = ParseName(ref context);
|
||||||
|
if (desc.Name.Length < 2 || desc.Name[0] != 'I' || !char.IsUpper(desc.Name[1]))
|
||||||
|
throw new Exception($"Invalid API_INTERFACE name '{desc.Name}' (it must start with 'I' character followed by the uppercase character).");
|
||||||
|
|
||||||
|
// Read inheritance
|
||||||
|
ParseInheritance(ref context, desc, out _);
|
||||||
|
|
||||||
|
// Process tag parameters
|
||||||
|
foreach (var tag in tagParams)
|
||||||
|
{
|
||||||
|
switch (tag.Tag.ToLower())
|
||||||
|
{
|
||||||
|
case "public":
|
||||||
|
desc.Access = AccessLevel.Public;
|
||||||
|
break;
|
||||||
|
case "protected":
|
||||||
|
desc.Access = AccessLevel.Protected;
|
||||||
|
break;
|
||||||
|
case "private":
|
||||||
|
desc.Access = AccessLevel.Private;
|
||||||
|
break;
|
||||||
|
case "inbuild":
|
||||||
|
desc.IsInBuild = true;
|
||||||
|
break;
|
||||||
|
case "attributes":
|
||||||
|
desc.Attributes = tag.Value;
|
||||||
|
break;
|
||||||
|
case "name":
|
||||||
|
desc.Name = tag.Value;
|
||||||
|
break;
|
||||||
|
case "namespace":
|
||||||
|
desc.Namespace = tag.Value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.Warning($"Unknown or not supported tag parameter {tag} used on interface {desc.Name} at line {context.Tokenizer.CurrentLine}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
private static FunctionInfo ParseFunction(ref ParsingContext context)
|
private static FunctionInfo ParseFunction(ref ParsingContext context)
|
||||||
{
|
{
|
||||||
var desc = new FunctionInfo
|
var desc = new FunctionInfo
|
||||||
@@ -875,55 +970,8 @@ namespace Flax.Build.Bindings
|
|||||||
// Read name
|
// Read name
|
||||||
desc.Name = desc.NativeName = ParseName(ref context);
|
desc.Name = desc.NativeName = ParseName(ref context);
|
||||||
|
|
||||||
// Read structure inheritance
|
// Read inheritance
|
||||||
token = context.Tokenizer.NextToken();
|
ParseInheritance(ref context, desc, out _);
|
||||||
if (token.Type == TokenType.Colon)
|
|
||||||
{
|
|
||||||
// Current class does have inheritance defined
|
|
||||||
var accessToken = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
|
||||||
switch (accessToken.Value)
|
|
||||||
{
|
|
||||||
case "public":
|
|
||||||
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
|
||||||
break;
|
|
||||||
case "protected":
|
|
||||||
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
|
||||||
break;
|
|
||||||
case "private":
|
|
||||||
token = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
token = accessToken;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
desc.BaseType = new TypeInfo
|
|
||||||
{
|
|
||||||
Type = token.Value,
|
|
||||||
};
|
|
||||||
token = context.Tokenizer.NextToken();
|
|
||||||
if (token.Type == TokenType.LeftAngleBracket)
|
|
||||||
{
|
|
||||||
var genericType = context.Tokenizer.ExpectToken(TokenType.Identifier);
|
|
||||||
context.Tokenizer.ExpectToken(TokenType.RightAngleBracket);
|
|
||||||
desc.BaseType.GenericArgs = new List<TypeInfo>
|
|
||||||
{
|
|
||||||
new TypeInfo
|
|
||||||
{
|
|
||||||
Type = genericType.Value,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
token = context.Tokenizer.PreviousToken();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No base type
|
|
||||||
token = context.Tokenizer.PreviousToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process tag parameters
|
// Process tag parameters
|
||||||
foreach (var tag in tagParams)
|
foreach (var tag in tagParams)
|
||||||
|
|||||||
@@ -254,6 +254,16 @@ namespace Flax.Build.Bindings
|
|||||||
var injectCppCodeInfo = ParseInjectCppCode(ref context);
|
var injectCppCodeInfo = ParseInjectCppCode(ref context);
|
||||||
fileInfo.AddChild(injectCppCodeInfo);
|
fileInfo.AddChild(injectCppCodeInfo);
|
||||||
}
|
}
|
||||||
|
else if (string.Equals(token.Value, ApiTokens.Interface, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
if (!(context.ScopeInfo is FileInfo))
|
||||||
|
throw new NotImplementedException("TODO: add support for nested interfaces in scripting API");
|
||||||
|
|
||||||
|
var interfaceInfo = ParseInterface(ref context);
|
||||||
|
scopeType = interfaceInfo;
|
||||||
|
context.ScopeInfo.AddChild(scopeType);
|
||||||
|
context.CurrentAccessLevel = AccessLevel.Public;
|
||||||
|
}
|
||||||
else if (string.Equals(token.Value, ApiTokens.AutoSerialization, StringComparison.Ordinal))
|
else if (string.Equals(token.Value, ApiTokens.AutoSerialization, StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
if (context.ScopeInfo is ClassInfo classInfo)
|
if (context.ScopeInfo is ClassInfo classInfo)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -8,7 +8,7 @@ namespace Flax.Build.Bindings
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The native class information for bindings generator.
|
/// The native class information for bindings generator.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ClassInfo : ApiTypeInfo
|
public class ClassInfo : ClassStructInfo
|
||||||
{
|
{
|
||||||
private static readonly HashSet<string> InBuildScriptingObjectTypes = new HashSet<string>
|
private static readonly HashSet<string> InBuildScriptingObjectTypes = new HashSet<string>
|
||||||
{
|
{
|
||||||
@@ -22,9 +22,6 @@ namespace Flax.Build.Bindings
|
|||||||
"Actor",
|
"Actor",
|
||||||
};
|
};
|
||||||
|
|
||||||
public AccessLevel Access;
|
|
||||||
public TypeInfo BaseType;
|
|
||||||
public AccessLevel BaseTypeInheritance;
|
|
||||||
public bool IsBaseTypeHidden;
|
public bool IsBaseTypeHidden;
|
||||||
public bool IsStatic;
|
public bool IsStatic;
|
||||||
public bool IsSealed;
|
public bool IsSealed;
|
||||||
@@ -52,7 +49,7 @@ namespace Flax.Build.Bindings
|
|||||||
base.Init(buildData);
|
base.Init(buildData);
|
||||||
|
|
||||||
// Internal base types are usually hidden from bindings (used in core-only internally)
|
// Internal base types are usually hidden from bindings (used in core-only internally)
|
||||||
IsBaseTypeHidden = BaseTypeInheritance == AccessLevel.Private || BaseType.Type == "ISerializable";
|
IsBaseTypeHidden = BaseTypeInheritance == AccessLevel.Private || BaseType == null;
|
||||||
|
|
||||||
// Cache if it it Scripting Object type
|
// Cache if it it Scripting Object type
|
||||||
if (InBuildScriptingObjectTypes.Contains(Name))
|
if (InBuildScriptingObjectTypes.Contains(Name))
|
||||||
|
|||||||
40
Source/Tools/Flax.Build/Bindings/ClassStructInfo.cs
Normal file
40
Source/Tools/Flax.Build/Bindings/ClassStructInfo.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Flax.Build.Bindings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The native class/structure information for bindings generator.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class ClassStructInfo : ApiTypeInfo
|
||||||
|
{
|
||||||
|
public AccessLevel Access;
|
||||||
|
public AccessLevel BaseTypeInheritance;
|
||||||
|
public TypeInfo BaseType;
|
||||||
|
public List<InterfaceInfo> Interfaces; // Optional
|
||||||
|
public List<TypeInfo> InterfaceNames; // Optional
|
||||||
|
|
||||||
|
public override void Init(Builder.BuildData buildData)
|
||||||
|
{
|
||||||
|
base.Init(buildData);
|
||||||
|
|
||||||
|
if (Interfaces == null && InterfaceNames != null && InterfaceNames.Count != 0)
|
||||||
|
{
|
||||||
|
Interfaces = new List<InterfaceInfo>();
|
||||||
|
for (var i = 0; i < InterfaceNames.Count; i++)
|
||||||
|
{
|
||||||
|
var interfaceName = InterfaceNames[i];
|
||||||
|
var apiTypeInfo = BindingsGenerator.FindApiTypeInfo(buildData, interfaceName, this);
|
||||||
|
if (apiTypeInfo is InterfaceInfo interfaceInfo)
|
||||||
|
{
|
||||||
|
Interfaces.Add(interfaceInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Interfaces.Count == 0)
|
||||||
|
Interfaces = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Source/Tools/Flax.Build/Bindings/InterfaceInfo.cs
Normal file
24
Source/Tools/Flax.Build/Bindings/InterfaceInfo.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
namespace Flax.Build.Bindings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The native class/structure interface information for bindings generator.
|
||||||
|
/// </summary>
|
||||||
|
public class InterfaceInfo : ClassStructInfo
|
||||||
|
{
|
||||||
|
public override bool IsInterface => true;
|
||||||
|
|
||||||
|
public override void AddChild(ApiTypeInfo apiTypeInfo)
|
||||||
|
{
|
||||||
|
apiTypeInfo.Namespace = null;
|
||||||
|
|
||||||
|
base.AddChild(apiTypeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return "interface " + Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,10 +8,8 @@ namespace Flax.Build.Bindings
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The native structure information for bindings generator.
|
/// The native structure information for bindings generator.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class StructureInfo : ApiTypeInfo
|
public class StructureInfo : ClassStructInfo
|
||||||
{
|
{
|
||||||
public AccessLevel Access;
|
|
||||||
public TypeInfo BaseType;
|
|
||||||
public List<FieldInfo> Fields;
|
public List<FieldInfo> Fields;
|
||||||
public List<FunctionInfo> Functions;
|
public List<FunctionInfo> Functions;
|
||||||
public bool IsAutoSerialization;
|
public bool IsAutoSerialization;
|
||||||
@@ -27,7 +25,7 @@ namespace Flax.Build.Bindings
|
|||||||
{
|
{
|
||||||
base.Init(buildData);
|
base.Init(buildData);
|
||||||
|
|
||||||
if (ForceNoPod)
|
if (ForceNoPod || (InterfaceNames != null && InterfaceNames.Count != 0))
|
||||||
{
|
{
|
||||||
_isPod = false;
|
_isPod = false;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -69,12 +69,14 @@
|
|||||||
<Compile Include="Bindings\BindingsGenerator.CSharp.cs" />
|
<Compile Include="Bindings\BindingsGenerator.CSharp.cs" />
|
||||||
<Compile Include="Bindings\BindingsGenerator.Parsing.cs" />
|
<Compile Include="Bindings\BindingsGenerator.Parsing.cs" />
|
||||||
<Compile Include="Bindings\ClassInfo.cs" />
|
<Compile Include="Bindings\ClassInfo.cs" />
|
||||||
|
<Compile Include="Bindings\ClassStructInfo.cs" />
|
||||||
<Compile Include="Bindings\EnumInfo.cs" />
|
<Compile Include="Bindings\EnumInfo.cs" />
|
||||||
<Compile Include="Bindings\EventInfo.cs" />
|
<Compile Include="Bindings\EventInfo.cs" />
|
||||||
<Compile Include="Bindings\FieldInfo.cs" />
|
<Compile Include="Bindings\FieldInfo.cs" />
|
||||||
<Compile Include="Bindings\FileInfo.cs" />
|
<Compile Include="Bindings\FileInfo.cs" />
|
||||||
<Compile Include="Bindings\InheritanceInfo.cs" />
|
<Compile Include="Bindings\InheritanceInfo.cs" />
|
||||||
<Compile Include="Bindings\InjectCppCodeInfo.cs" />
|
<Compile Include="Bindings\InjectCppCodeInfo.cs" />
|
||||||
|
<Compile Include="Bindings\InterfaceInfo.cs" />
|
||||||
<Compile Include="Bindings\LangType.cs" />
|
<Compile Include="Bindings\LangType.cs" />
|
||||||
<Compile Include="Bindings\MemberInfo.cs" />
|
<Compile Include="Bindings\MemberInfo.cs" />
|
||||||
<Compile Include="Bindings\FunctionInfo.cs" />
|
<Compile Include="Bindings\FunctionInfo.cs" />
|
||||||
|
|||||||
Reference in New Issue
Block a user