Add support for basic classes to Scripting Type (without scripting object as a base)

This commit is contained in:
Wojtek Figat
2020-12-22 12:55:57 +01:00
parent f25064fae8
commit 4665e8fbdb
8 changed files with 150 additions and 110 deletions

View File

@@ -1290,11 +1290,11 @@ Asset::LoadResult VisualScript::load()
// Hack vtable similarly to VisualScriptObjectSpawn
ScriptingType& visualScriptType = (ScriptingType&)object->GetType();
if (visualScriptType.Class.ScriptVTable)
if (visualScriptType.Script.ScriptVTable)
{
// Override object vtable with hacked one that has Visual Script functions calls
ASSERT(visualScriptType.Class.VTable);
*(void**)object = visualScriptType.Class.VTable;
ASSERT(visualScriptType.Script.VTable);
*(void**)object = visualScriptType.Script.VTable;
}
}
const int32 oldCount = _oldParamsLayout.Count();
@@ -1361,10 +1361,10 @@ void VisualScript::unload(bool isReloading)
if (_scriptingTypeHandle)
{
auto& type = VisualScriptingModule.Types[_scriptingTypeHandle.TypeIndex];
if (type.Class.DefaultInstance)
if (type.Script.DefaultInstance)
{
Delete(type.Class.DefaultInstance);
type.Class.DefaultInstance = nullptr;
Delete(type.Script.DefaultInstance);
type.Script.DefaultInstance = nullptr;
}
VisualScriptingModule.TypeNameToTypeIndex.RemoveValue(_scriptingTypeHandle.TypeIndex);
VisualScriptingModule.Scripts[_scriptingTypeHandle.TypeIndex] = nullptr;
@@ -1389,7 +1389,7 @@ void VisualScript::CacheScriptingType()
{
// Find first native base C++ class of this Visual Script class
ScriptingTypeHandle nativeType = baseType;
while (nativeType && nativeType.GetType().Class.ScriptVTable)
while (nativeType && nativeType.GetType().Script.ScriptVTable)
{
nativeType = nativeType.GetType().GetBaseType();
}
@@ -1437,14 +1437,14 @@ void VisualScript::CacheScriptingType()
for (ScriptingTypeHandle e = nativeType; e;)
{
const ScriptingType& eType = e.GetType();
if (eType.Class.SetupScriptVTable)
if (eType.Script.SetupScriptVTable)
{
ASSERT(eType.ManagedClass);
eType.Class.SetupScriptVTable(eType.ManagedClass, type.Class.ScriptVTable, type.Class.ScriptVTableBase);
eType.Script.SetupScriptVTable(eType.ManagedClass, type.Script.ScriptVTable, type.Script.ScriptVTableBase);
}
e = eType.GetBaseType();
}
MMethod** scriptVTable = (MMethod**)type.Class.ScriptVTable;
MMethod** scriptVTable = (MMethod**)type.Script.ScriptVTable;
while (scriptVTable && *scriptVTable)
{
const MMethod* referenceMethod = *scriptVTable;
@@ -1498,12 +1498,12 @@ ScriptingObject* VisualScriptingBinaryModule::VisualScriptObjectSpawn(const Scri
ScriptingType& visualScriptType = (ScriptingType&)params.Type.GetType();
ScriptingTypeHandle baseTypeHandle = visualScriptType.GetBaseType();
const ScriptingType* baseTypePtr = &baseTypeHandle.GetType();
while (baseTypePtr->Class.Spawn == &VisualScriptObjectSpawn)
while (baseTypePtr->Script.Spawn == &VisualScriptObjectSpawn)
{
baseTypeHandle = baseTypePtr->GetBaseType();
baseTypePtr = &baseTypeHandle.GetType();
}
ScriptingObject* object = baseTypePtr->Class.Spawn(params);
ScriptingObject* object = baseTypePtr->Script.Spawn(params);
if (!object)
{
return nullptr;
@@ -1514,9 +1514,9 @@ ScriptingObject* VisualScriptingBinaryModule::VisualScriptObjectSpawn(const Scri
// We create a custom vtable for the Visual Script objects that use a native class object with virtual functions overrides.
// To make it easy to use in C++ we inject custom wrapper methods into C++ object vtable to execute Visual Script graph from them.
// Because virtual member functions calls are C++ ABI and impl-defined this is quite hard. But works.
if (visualScriptType.Class.ScriptVTable)
if (visualScriptType.Script.ScriptVTable)
{
if (!visualScriptType.Class.VTable)
if (!visualScriptType.Script.VTable)
{
// Duplicate vtable
void** vtable = *(void***)object;
@@ -1525,21 +1525,21 @@ ScriptingObject* VisualScriptingBinaryModule::VisualScriptObjectSpawn(const Scri
while (vtable[entriesCount] && entriesCount < 200)
entriesCount++;
const int32 size = entriesCount * sizeof(void*);
visualScriptType.Class.VTable = (void**)((byte*)Platform::Allocate(prefixSize + size, 16) + prefixSize);
Platform::MemoryCopy((byte*)visualScriptType.Class.VTable - prefixSize, (byte*)vtable - prefixSize, prefixSize + size);
visualScriptType.Script.VTable = (void**)((byte*)Platform::Allocate(prefixSize + size, 16) + prefixSize);
Platform::MemoryCopy((byte*)visualScriptType.Script.VTable - prefixSize, (byte*)vtable - prefixSize, prefixSize + size);
// Override vtable entries by the class
for (ScriptingTypeHandle e = baseTypeHandle; e;)
{
const ScriptingType& eType = e.GetType();
if (eType.Class.SetupScriptObjectVTable)
eType.Class.SetupScriptObjectVTable(visualScriptType.Class.ScriptVTable, visualScriptType.Class.ScriptVTableBase, visualScriptType.Class.VTable, entriesCount, 1);
if (eType.Script.SetupScriptObjectVTable)
eType.Script.SetupScriptObjectVTable(visualScriptType.Script.ScriptVTable, visualScriptType.Script.ScriptVTableBase, visualScriptType.Script.VTable, entriesCount, 1);
e = eType.GetBaseType();
}
}
// Override object vtable with hacked one that has Visual Script functions calls
*(void**)object = visualScriptType.Class.VTable;
*(void**)object = visualScriptType.Script.VTable;
}
// Mark as custom scripting type
@@ -1573,10 +1573,10 @@ void VisualScriptingBinaryModule::OnScriptsReloading()
if (script->_scriptingTypeHandle)
{
auto& type = VisualScriptingModule.Types[script->_scriptingTypeHandle.TypeIndex];
if (type.Class.DefaultInstance)
if (type.Script.DefaultInstance)
{
Delete(type.Class.DefaultInstance);
type.Class.DefaultInstance = nullptr;
Delete(type.Script.DefaultInstance);
type.Script.DefaultInstance = nullptr;
}
VisualScriptingModule.TypeNameToTypeIndex.RemoveValue(script->_scriptingTypeHandle.TypeIndex);
script->_scriptingTypeHandleCached = script->_scriptingTypeHandle;
@@ -1862,7 +1862,7 @@ ScriptingTypeHandle VisualScript::GetScriptingType()
ScriptingObject* VisualScript::CreateInstance()
{
const auto scriptingTypeHandle = GetScriptingType();
return scriptingTypeHandle ? scriptingTypeHandle.GetType().Class.Spawn(ScriptingObjectSpawnParams(Guid::New(), scriptingTypeHandle)) : nullptr;
return scriptingTypeHandle ? scriptingTypeHandle.GetType().Script.Spawn(ScriptingObjectSpawnParams(Guid::New(), scriptingTypeHandle)) : nullptr;
}
Variant VisualScript::GetScriptInstanceParameterValue(const StringView& name, ScriptingObject* instance) const

View File

@@ -79,7 +79,7 @@ SceneObject* SceneObjectsFactory::Spawn(ISerializable::DeserializeStream& stream
if (type)
{
const ScriptingObjectSpawnParams params(id, type);
obj = (SceneObject*)type.GetType().Class.Spawn(params);
obj = (SceneObject*)type.GetType().Script.Spawn(params);
if (obj == nullptr)
{
LOG(Warning, "Failed to spawn object of type {0}.", type.ToString(true));
@@ -109,7 +109,7 @@ SceneObject* SceneObjectsFactory::Spawn(ISerializable::DeserializeStream& stream
if (type)
{
const ScriptingObjectSpawnParams params(id, type);
obj = (SceneObject*)type.GetType().Class.Spawn(params);
obj = (SceneObject*)type.GetType().Script.Spawn(params);
if (obj == nullptr)
{
LOG(Warning, "Failed to spawn object of type {0}.", type.ToString(true));
@@ -384,7 +384,7 @@ Actor* SceneObjectsFactory::CreateActor(int32 typeId, const Guid& id)
if (type)
{
const ScriptingObjectSpawnParams params(id, type);
const auto result = dynamic_cast<Actor*>(type.GetType().Class.Spawn(params));
const auto result = dynamic_cast<Actor*>(type.GetType().Script.Spawn(params));
if (result == nullptr)
{
LOG(Warning, "Failed to spawn object of type {0}.", type.ToString(true));

View File

@@ -60,16 +60,16 @@ ScriptingType::ScriptingType()
, Module(nullptr)
, InitRuntime(nullptr)
, Fullname(nullptr, 0)
, Type(ScriptingTypes::Class)
, Type(ScriptingTypes::Script)
, BaseTypePtr(nullptr)
{
Class.Spawn = nullptr;
Class.VTable = nullptr;
Class.ScriptVTable = nullptr;
Class.ScriptVTableBase = nullptr;
Class.SetupScriptVTable = nullptr;
Class.SetupScriptObjectVTable = nullptr;
Class.DefaultInstance = nullptr;
Script.Spawn = nullptr;
Script.VTable = nullptr;
Script.ScriptVTable = nullptr;
Script.ScriptVTableBase = nullptr;
Script.SetupScriptVTable = nullptr;
Script.SetupScriptObjectVTable = nullptr;
Script.DefaultInstance = nullptr;
}
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, SpawnHandler spawn, const ScriptingTypeHandle& baseType, SetupScriptVTableHandler setupScriptVTable, SetupScriptObjectVTableHandler setupScriptObjectVTable)
@@ -77,21 +77,39 @@ ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* modul
, Module(module)
, InitRuntime(initRuntime)
, Fullname(fullname)
, Type(ScriptingTypes::Class)
, Type(ScriptingTypes::Script)
, BaseTypeHandle(baseType)
, BaseTypePtr(nullptr)
, Size(size)
{
Class.Spawn = spawn;
Class.VTable = nullptr;
Class.ScriptVTable = nullptr;
Class.ScriptVTableBase = nullptr;
Class.SetupScriptVTable = setupScriptVTable;
Class.SetupScriptObjectVTable = setupScriptObjectVTable;
Class.DefaultInstance = nullptr;
Script.Spawn = spawn;
Script.VTable = nullptr;
Script.ScriptVTable = nullptr;
Script.ScriptVTableBase = nullptr;
Script.SetupScriptVTable = setupScriptVTable;
Script.SetupScriptObjectVTable = setupScriptObjectVTable;
Script.DefaultInstance = nullptr;
}
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, SpawnHandler spawn, ScriptingTypeInitializer* baseType, SetupScriptVTableHandler setupScriptVTable, SetupScriptObjectVTableHandler setupScriptObjectVTable)
: ManagedClass(nullptr)
, Module(module)
, InitRuntime(initRuntime)
, Fullname(fullname)
, Type(ScriptingTypes::Script)
, BaseTypePtr(baseType)
, Size(size)
{
Script.Spawn = spawn;
Script.VTable = nullptr;
Script.ScriptVTable = nullptr;
Script.ScriptVTableBase = nullptr;
Script.SetupScriptVTable = setupScriptVTable;
Script.SetupScriptObjectVTable = setupScriptObjectVTable;
Script.DefaultInstance = nullptr;
}
ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* module, int32 size, InitRuntimeHandler initRuntime, Ctor ctor, Dtor dtor, ScriptingTypeInitializer* baseType)
: ManagedClass(nullptr)
, Module(module)
, InitRuntime(initRuntime)
@@ -100,13 +118,8 @@ ScriptingType::ScriptingType(const StringAnsiView& fullname, BinaryModule* modul
, BaseTypePtr(baseType)
, Size(size)
{
Class.Spawn = spawn;
Class.VTable = nullptr;
Class.ScriptVTable = nullptr;
Class.ScriptVTableBase = nullptr;
Class.SetupScriptVTable = setupScriptVTable;
Class.SetupScriptObjectVTable = setupScriptObjectVTable;
Class.DefaultInstance = nullptr;
Class.Ctor = ctor;
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)
@@ -139,14 +152,14 @@ ScriptingType::ScriptingType(const ScriptingType& other)
{
switch (other.Type)
{
case ScriptingTypes::Class:
Class.Spawn = other.Class.Spawn;
Class.VTable = nullptr;
Class.ScriptVTable = nullptr;
Class.ScriptVTableBase = nullptr;
Class.SetupScriptVTable = other.Class.SetupScriptVTable;
Class.SetupScriptObjectVTable = other.Class.SetupScriptObjectVTable;
Class.DefaultInstance = nullptr;
case ScriptingTypes::Script:
Script.Spawn = other.Script.Spawn;
Script.VTable = nullptr;
Script.ScriptVTable = nullptr;
Script.ScriptVTableBase = nullptr;
Script.SetupScriptVTable = other.Script.SetupScriptVTable;
Script.SetupScriptObjectVTable = other.Script.SetupScriptObjectVTable;
Script.DefaultInstance = nullptr;
break;
case ScriptingTypes::Structure:
Struct.Ctor = other.Struct.Ctor;
@@ -175,18 +188,18 @@ ScriptingType::ScriptingType(ScriptingType&& other)
{
switch (other.Type)
{
case ScriptingTypes::Class:
Class.Spawn = other.Class.Spawn;
Class.VTable = other.Class.VTable;
other.Class.VTable = nullptr;
Class.ScriptVTable = other.Class.ScriptVTable;
other.Class.ScriptVTable = nullptr;
Class.ScriptVTableBase = other.Class.ScriptVTableBase;
other.Class.ScriptVTableBase = nullptr;
Class.SetupScriptVTable = other.Class.SetupScriptVTable;
Class.SetupScriptObjectVTable = other.Class.SetupScriptObjectVTable;
Class.DefaultInstance = other.Class.DefaultInstance;
other.Class.DefaultInstance = nullptr;
case ScriptingTypes::Script:
Script.Spawn = other.Script.Spawn;
Script.VTable = other.Script.VTable;
other.Script.VTable = nullptr;
Script.ScriptVTable = other.Script.ScriptVTable;
other.Script.ScriptVTable = nullptr;
Script.ScriptVTableBase = other.Script.ScriptVTableBase;
other.Script.ScriptVTableBase = nullptr;
Script.SetupScriptVTable = other.Script.SetupScriptVTable;
Script.SetupScriptObjectVTable = other.Script.SetupScriptObjectVTable;
Script.DefaultInstance = other.Script.DefaultInstance;
other.Script.DefaultInstance = nullptr;
break;
case ScriptingTypes::Structure:
Struct.Ctor = other.Struct.Ctor;
@@ -207,13 +220,13 @@ ScriptingType::~ScriptingType()
{
switch (Type)
{
case ScriptingTypes::Class:
if (Class.DefaultInstance)
Delete(Class.DefaultInstance);
if (Class.VTable)
Platform::Free((byte*)Class.VTable - GetVTablePrefix());
Platform::Free(Class.ScriptVTable);
Platform::Free(Class.ScriptVTableBase);
case ScriptingTypes::Script:
if (Script.DefaultInstance)
Delete(Script.DefaultInstance);
if (Script.VTable)
Platform::Free((byte*)Script.VTable - GetVTablePrefix());
Platform::Free(Script.ScriptVTable);
Platform::Free(Script.ScriptVTableBase);
break;
case ScriptingTypes::Structure:
break;
@@ -235,17 +248,17 @@ ScriptingTypeHandle ScriptingType::GetHandle() const
ScriptingObject* ScriptingType::GetDefaultInstance() const
{
ASSERT(Type == ScriptingTypes::Class);
if (!Class.DefaultInstance)
ASSERT(Type == ScriptingTypes::Script);
if (!Script.DefaultInstance)
{
const ScriptingObjectSpawnParams params(Guid::New(), GetHandle());
Class.DefaultInstance = Class.Spawn(params);
if (!Class.DefaultInstance)
Script.DefaultInstance = Script.Spawn(params);
if (!Script.DefaultInstance)
{
LOG(Error, "Failed to create default instance of type {0}", ToString());
}
}
return Class.DefaultInstance;
return Script.DefaultInstance;
}
String ScriptingType::ToString() const
@@ -268,6 +281,21 @@ ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const S
module->TypeNameToTypeIndex[typeName] = TypeIndex;
}
ScriptingTypeInitializer::ScriptingTypeInitializer(BinaryModule* module, const StringAnsiView& fullname, int32 size, ScriptingType::InitRuntimeHandler initRuntime, ScriptingType::Ctor ctor, ScriptingType::Dtor dtor, ScriptingTypeInitializer* baseType)
: ScriptingTypeHandle(module, module->Types.Count())
{
module->Types.AddUninitialized();
new(module->Types.Get() + TypeIndex)ScriptingType(fullname, module, size, initRuntime, ctor, dtor, baseType);
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, 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)
: ScriptingTypeHandle(module, module->Types.Count())
{
@@ -368,7 +396,7 @@ ScriptingObject* ManagedBinaryModule::ManagedObjectSpawn(const ScriptingObjectSp
// Create native object
ScriptingTypeHandle managedTypeHandle = params.Type;
const ScriptingType* managedTypePtr = &managedTypeHandle.GetType();
while (managedTypePtr->Class.Spawn != &ManagedObjectSpawn)
while (managedTypePtr->Script.Spawn != &ManagedObjectSpawn)
{
managedTypeHandle = managedTypePtr->GetBaseType();
managedTypePtr = &managedTypeHandle.GetType();
@@ -376,12 +404,12 @@ ScriptingObject* ManagedBinaryModule::ManagedObjectSpawn(const ScriptingObjectSp
ScriptingType& managedType = (ScriptingType&)*managedTypePtr;
ScriptingTypeHandle nativeTypeHandle = managedType.GetBaseType();
const ScriptingType* nativeTypePtr = &nativeTypeHandle.GetType();
while (nativeTypePtr->Class.Spawn == &ManagedObjectSpawn)
while (nativeTypePtr->Script.Spawn == &ManagedObjectSpawn)
{
nativeTypeHandle = nativeTypePtr->GetBaseType();
nativeTypePtr = &nativeTypeHandle.GetType();
}
ScriptingObject* object = nativeTypePtr->Class.Spawn(params);
ScriptingObject* object = nativeTypePtr->Script.Spawn(params);
if (!object)
{
return nullptr;
@@ -392,9 +420,9 @@ ScriptingObject* ManagedBinaryModule::ManagedObjectSpawn(const ScriptingObjectSp
// We create a custom vtable for the C# objects that use a native class object with virtual functions overrides.
// To make it easy to use in C++ we inject custom wrapper methods into C++ object vtable to call C# code from them.
// Because virtual member functions calls are C++ ABI and impl-defined this is quite hard. But works.
if (managedType.Class.ScriptVTable)
if (managedType.Script.ScriptVTable)
{
if (!managedType.Class.VTable)
if (!managedType.Script.VTable)
{
// Duplicate vtable
void** vtable = *(void***)object;
@@ -403,23 +431,23 @@ ScriptingObject* ManagedBinaryModule::ManagedObjectSpawn(const ScriptingObjectSp
while (vtable[entriesCount] && entriesCount < 200)
entriesCount++;
const int32 size = entriesCount * sizeof(void*);
managedType.Class.VTable = (void**)((byte*)Platform::Allocate(prefixSize + size, 16) + prefixSize);
Platform::MemoryCopy((byte*)managedType.Class.VTable - prefixSize, (byte*)vtable - prefixSize, prefixSize + size);
managedType.Script.VTable = (void**)((byte*)Platform::Allocate(prefixSize + size, 16) + prefixSize);
Platform::MemoryCopy((byte*)managedType.Script.VTable - prefixSize, (byte*)vtable - prefixSize, prefixSize + size);
// Override vtable entries by the class
for (ScriptingTypeHandle e = nativeTypeHandle; e;)
{
const ScriptingType& eType = e.GetType();
if (eType.Class.SetupScriptObjectVTable)
if (eType.Script.SetupScriptObjectVTable)
{
eType.Class.SetupScriptObjectVTable(managedType.Class.ScriptVTable, managedType.Class.ScriptVTableBase, managedType.Class.VTable, entriesCount, 0);
eType.Script.SetupScriptObjectVTable(managedType.Script.ScriptVTable, managedType.Script.ScriptVTableBase, managedType.Script.VTable, entriesCount, 0);
}
e = eType.GetBaseType();
}
}
// Override object vtable with hacked one that has C# functions calls
*(void**)object = managedType.Class.VTable;
*(void**)object = managedType.Script.VTable;
}
// Mark as managed type
@@ -557,7 +585,7 @@ void ManagedBinaryModule::OnLoaded(MAssembly* assembly)
if (baseClassModule->TypeNameToTypeIndex.TryGet(baseClass->GetFullName(), typeIndex))
{
nativeType = ScriptingTypeHandle(baseClassModule, typeIndex);
if (nativeType.GetType().Class.Spawn != &ManagedObjectSpawn)
if (nativeType.GetType().Script.Spawn != &ManagedObjectSpawn)
break;
}
baseClass = baseClass->GetBaseClass();
@@ -592,14 +620,14 @@ void ManagedBinaryModule::OnLoaded(MAssembly* assembly)
for (ScriptingTypeHandle e = nativeType; e;)
{
const ScriptingType& eType = e.GetType();
if (eType.Class.SetupScriptVTable)
if (eType.Script.SetupScriptVTable)
{
ASSERT(eType.ManagedClass);
eType.Class.SetupScriptVTable(eType.ManagedClass, type.Class.ScriptVTable, type.Class.ScriptVTableBase);
eType.Script.SetupScriptVTable(eType.ManagedClass, type.Script.ScriptVTable, type.Script.ScriptVTableBase);
}
e = eType.GetBaseType();
}
MMethod** scriptVTable = (MMethod**)type.Class.ScriptVTable;
MMethod** scriptVTable = (MMethod**)type.Script.ScriptVTable;
while (scriptVTable && *scriptVTable)
{
const MMethod* referenceMethod = *scriptVTable;
@@ -657,10 +685,10 @@ void ManagedBinaryModule::OnUnloading(MAssembly* assembly)
for (ScriptingType& type : Types)
{
type.ManagedClass = nullptr;
if (type.Type == ScriptingTypes::Class && type.Class.ScriptVTable)
if (type.Type == ScriptingTypes::Script && type.Script.ScriptVTable)
{
Platform::Free(type.Class.ScriptVTable);
type.Class.ScriptVTable = nullptr;
Platform::Free(type.Script.ScriptVTable);
type.Script.ScriptVTable = nullptr;
}
}
ClassToTypeIndex.Clear();

View File

@@ -186,9 +186,9 @@ void Script::SetupType()
while (typeHandle != Script::TypeInitializer)
{
auto& type = typeHandle.GetType();
_tickUpdate |= type.Class.ScriptVTable[8] != nullptr;
_tickLateUpdate |= type.Class.ScriptVTable[9] != nullptr;
_tickFixedUpdate |= type.Class.ScriptVTable[10] != nullptr;
_tickUpdate |= type.Script.ScriptVTable[8] != nullptr;
_tickLateUpdate |= type.Script.ScriptVTable[9] != nullptr;
_tickFixedUpdate |= type.Script.ScriptVTable[10] != nullptr;
typeHandle = type.GetBaseType();
}
}

View File

@@ -371,7 +371,7 @@ public:
// Create unmanaged object
const ScriptingObjectSpawnParams params(Guid::New(), ScriptingTypeHandle(module, typeIndex));
ScriptingObject* obj = scriptingType.Class.Spawn(params);
ScriptingObject* obj = scriptingType.Script.Spawn(params);
if (obj == nullptr)
{
LOG(Error, "Failed to spawn object of type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));
@@ -414,7 +414,7 @@ public:
// Create unmanaged object
const ScriptingObjectSpawnParams params(Guid::New(), type);
ScriptingObject* obj = type.GetType().Class.Spawn(params);
ScriptingObject* obj = type.GetType().Script.Spawn(params);
if (obj == nullptr)
{
LOG(Error, "Failed to spawn object of type \'{0}\'.", String(typeName));
@@ -468,7 +468,7 @@ public:
// Create unmanaged object
const ScriptingObjectSpawnParams params(Guid::New(), ScriptingTypeHandle(module, typeIndex));
ScriptingObject* obj = scriptingType.Class.Spawn(params);
ScriptingObject* obj = scriptingType.Script.Spawn(params);
if (obj == nullptr)
{
LOG(Error, "Failed to spawn object of type \'{0}.{1}\'.", String(mono_class_get_namespace(typeClass)), String(mono_class_get_name(typeClass)));

View File

@@ -93,9 +93,10 @@ inline uint32 GetHash(const ScriptingTypeHandle& key)
/// </summary>
enum class ScriptingTypes
{
Class = 0,
Script = 0,
Structure = 1,
Enum = 2,
Class = 3,
};
/// <summary>
@@ -193,6 +194,15 @@ struct FLAXENGINE_API ScriptingType
/// The default instance of the scripting type. Used by serialization system for comparision to save only modified properties of the object.
/// </summary>
mutable ScriptingObject* DefaultInstance;
} Script;
struct
{
// Class constructor method pointer
Ctor Ctor;
// Class destructor method pointer
Dtor Dtor;
} Class;
struct
@@ -223,6 +233,7 @@ struct FLAXENGINE_API 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 = DefaultInitRuntime, SpawnHandler spawn = DefaultSpawn, ScriptingTypeInitializer* baseType = nullptr, SetupScriptVTableHandler setupScriptVTable = nullptr, SetupScriptObjectVTableHandler setupScriptObjectVTable = 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, Copy copy, Box box, Unbox unbox, GetField getField, SetField setField, ScriptingTypeInitializer* baseType);
ScriptingType(const ScriptingType& other);
ScriptingType(ScriptingType&& other);
@@ -268,6 +279,7 @@ struct FLAXENGINE_API ScriptingType
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::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, ScriptingType::Copy copy, ScriptingType::Box box, ScriptingType::Unbox unbox, ScriptingType::GetField getField, ScriptingType::SetField setField, ScriptingTypeInitializer* baseType = nullptr);
};

View File

@@ -818,7 +818,7 @@ namespace Flax.Build.Bindings
contents.AppendLine(" ScriptingTypeHandle managedTypeHandle = object->GetTypeHandle();");
contents.AppendLine(" const ScriptingType* managedTypePtr = &managedTypeHandle.GetType();");
contents.AppendLine(" while (managedTypePtr->Class.Spawn != &ManagedBinaryModule::ManagedObjectSpawn)");
contents.AppendLine(" while (managedTypePtr->Script.Spawn != &ManagedBinaryModule::ManagedObjectSpawn)");
contents.AppendLine(" {");
contents.AppendLine(" managedTypeHandle = managedTypePtr->GetBaseType();");
contents.AppendLine(" managedTypePtr = &managedTypeHandle.GetType();");
@@ -827,7 +827,7 @@ namespace Flax.Build.Bindings
contents.AppendLine(" if (IsDuringWrapperCall)");
contents.AppendLine(" {");
contents.AppendLine(" // Prevent stack overflow by calling native base method");
contents.AppendLine(" const auto scriptVTableBase = managedTypePtr->Class.ScriptVTableBase;");
contents.AppendLine(" const auto scriptVTableBase = managedTypePtr->Script.ScriptVTableBase;");
contents.Append($" return (object->**({functionInfo.UniqueName}_Signature*)&scriptVTableBase[{scriptVTableIndex} + 2])(");
separator = false;
for (var i = 0; i < functionInfo.Parameters.Count; i++)
@@ -840,7 +840,7 @@ namespace Flax.Build.Bindings
}
contents.AppendLine(");");
contents.AppendLine(" }");
contents.AppendLine(" auto scriptVTable = (MMethod**)managedTypePtr->Class.ScriptVTable;");
contents.AppendLine(" auto scriptVTable = (MMethod**)managedTypePtr->Script.ScriptVTable;");
contents.AppendLine($" ASSERT(scriptVTable && scriptVTable[{scriptVTableIndex}]);");
contents.AppendLine($" auto method = scriptVTable[{scriptVTableIndex}];");
contents.AppendLine(" MonoObject* exception = nullptr;");

View File

@@ -48,7 +48,7 @@ namespace Flax.Build.Plugins
contents.AppendLine(" if (IsDuringWrapperCall)");
contents.AppendLine(" {");
contents.AppendLine(" // Prevent stack overflow by calling base method");
contents.AppendLine(" const auto scriptVTableBase = object->GetType().Class.ScriptVTableBase;");
contents.AppendLine(" const auto scriptVTableBase = object->GetType().Script.ScriptVTableBase;");
contents.Append($" return (object->**({functionInfo.UniqueName}_Signature*)&scriptVTableBase[{scriptVTableIndex} + 2])(");
separator = false;
for (var i = 0; i < functionInfo.Parameters.Count; i++)
@@ -61,7 +61,7 @@ namespace Flax.Build.Plugins
}
contents.AppendLine(");");
contents.AppendLine(" }");
contents.AppendLine(" auto scriptVTable = (VisualScript::Method**)object->GetType().Class.ScriptVTable;");
contents.AppendLine(" auto scriptVTable = (VisualScript::Method**)object->GetType().Script.ScriptVTable;");
contents.AppendLine($" ASSERT(scriptVTable && scriptVTable[{scriptVTableIndex}]);");
if (functionInfo.Parameters.Count != 0)