diff --git a/Source/Engine/Content/Assets/VisualScript.cpp b/Source/Engine/Content/Assets/VisualScript.cpp index 857e288fc..616fbe91a 100644 --- a/Source/Engine/Content/Assets/VisualScript.cpp +++ b/Source/Engine/Content/Assets/VisualScript.cpp @@ -1522,12 +1522,16 @@ void VisualScript::unload(bool isReloading) if (_scriptingTypeHandle) { VisualScriptingBinaryModule::Locker.Lock(); - auto& type = VisualScriptingModule.Types[_scriptingTypeHandle.TypeIndex]; + ScriptingType& type = VisualScriptingModule.Types[_scriptingTypeHandle.TypeIndex]; if (type.Script.DefaultInstance) { Delete(type.Script.DefaultInstance); type.Script.DefaultInstance = nullptr; } + char* typeName = (char*)Allocator::Allocate(sizeof(_typenameChars)); + Platform::MemoryCopy(typeName, _typenameChars, sizeof(_typenameChars)); + ((StringAnsiView&)type.Fullname) = StringAnsiView(typeName, 32); + VisualScriptingModule._unloadedScriptTypeNames.Add(typeName); VisualScriptingModule.TypeNameToTypeIndex.RemoveValue(_scriptingTypeHandle.TypeIndex); VisualScriptingModule.Scripts[_scriptingTypeHandle.TypeIndex] = nullptr; _scriptingTypeHandleCached = _scriptingTypeHandle; @@ -1653,6 +1657,8 @@ VisualScriptingBinaryModule::VisualScriptingBinaryModule() ScriptingObject* VisualScriptingBinaryModule::VisualScriptObjectSpawn(const ScriptingObjectSpawnParams& params) { // Create native object (base type can be C++ or C#) + if (params.Type.Module == nullptr) + return nullptr; ScriptingType& visualScriptType = (ScriptingType&)params.Type.GetType(); ScriptingTypeHandle baseTypeHandle = visualScriptType.GetBaseType(); const ScriptingType* baseTypePtr = &baseTypeHandle.GetType(); @@ -1663,9 +1669,7 @@ ScriptingObject* VisualScriptingBinaryModule::VisualScriptObjectSpawn(const Scri } ScriptingObject* object = baseTypePtr->Script.Spawn(params); if (!object) - { return nullptr; - } // Beware! Hacking vtables incoming! Undefined behaviors exploits! Low-level programming! visualScriptType.HackObjectVTable(object, baseTypeHandle, 1); @@ -2060,6 +2064,11 @@ void VisualScriptingBinaryModule::Destroy(bool isReloading) return; BinaryModule::Destroy(isReloading); + + // Free cached script typenames table + for (char* str : _unloadedScriptTypeNames) + Allocator::Free(str); + _unloadedScriptTypeNames.Clear(); } ScriptingTypeHandle VisualScript::GetScriptingType() diff --git a/Source/Engine/Content/Assets/VisualScript.h b/Source/Engine/Content/Assets/VisualScript.h index dc63609a6..4fda11fef 100644 --- a/Source/Engine/Content/Assets/VisualScript.h +++ b/Source/Engine/Content/Assets/VisualScript.h @@ -305,6 +305,7 @@ class FLAXENGINE_API VisualScriptingBinaryModule : public BinaryModule friend VisualScript; private: StringAnsi _name; + Array _unloadedScriptTypeNames; public: /// diff --git a/Source/Engine/Scripting/BinaryModule.h b/Source/Engine/Scripting/BinaryModule.h index fa7540cf2..6d9baf5ce 100644 --- a/Source/Engine/Scripting/BinaryModule.h +++ b/Source/Engine/Scripting/BinaryModule.h @@ -118,7 +118,7 @@ public: /// /// Tries to find a method in a given scripting type by the method name and parameters count. /// - /// If the the type contains more than one method of the given name and parameters count the returned value can be non-deterministic (one of the matching methods). + /// If the type contains more than one method of the given name and parameters count the returned value can be non-deterministic (one of the matching methods). /// The type to find method inside it. /// The method name. /// The method parameters count. @@ -182,7 +182,7 @@ public: /// Gets the value of a given scripting field. /// /// The field. - /// The object instance to get it's member field. Unused for static fields. + /// The object instance to get its member field. Unused for static fields. /// The output field value. /// True if failed, otherwise false. virtual bool GetFieldValue(void* field, const Variant& instance, Variant& result) @@ -194,7 +194,7 @@ public: /// Sets the value of a given scripting field. /// /// The field. - /// The object instance to set it's member field. Unused for static fields. + /// The object instance to set its member field. Unused for static fields. /// The field value to assign. /// True if failed, otherwise false. virtual bool SetFieldValue(void* field, const Variant& instance, Variant& value) @@ -242,7 +242,7 @@ public: /// /// Unloads the module (native library and C# assembly and any other scripting data). Unregisters the module. /// - /// If true module is during reloading and should force release the runtime data. Used for C# assembly to cleanup it's runtime data in Mono (or other scripting runtime). + /// If true module is during reloading and should force release the runtime data. Used for C# assembly to clean up it's runtime data in Mono (or other scripting runtime). virtual void Destroy(bool isReloading); };