From 9e0a2963e8761c12d5420f6e1c15b3c477d2e5bc Mon Sep 17 00:00:00 2001 From: Atdunbg <979541498@qq.com> Date: Mon, 27 Oct 2025 12:35:51 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=96=B0=E5=B0=81=E8=A3=85=E4=BA=8C?= =?UTF-8?q?=E8=BF=9B=E5=88=B6=E6=96=87=E4=BB=B6=E8=AF=BB=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Hazel/src/Hazel/Core/Buffer.h | 103 +++++++++++++++++++++ Hazel/src/Hazel/Core/FileSystem.cpp | 39 ++++++++ Hazel/src/Hazel/Core/FileSystem.h | 22 +++++ Hazel/src/Hazel/Scene/SceneSerializer.cpp | 88 +++++++++--------- Hazel/src/Hazel/Scripting/ScriptEngine.cpp | 58 +++++++----- Hazel/src/Hazel/Scripting/ScriptEngine.h | 4 +- 6 files changed, 246 insertions(+), 68 deletions(-) create mode 100644 Hazel/src/Hazel/Core/Buffer.h create mode 100644 Hazel/src/Hazel/Core/FileSystem.cpp create mode 100644 Hazel/src/Hazel/Core/FileSystem.h diff --git a/Hazel/src/Hazel/Core/Buffer.h b/Hazel/src/Hazel/Core/Buffer.h new file mode 100644 index 0000000..8f3b52d --- /dev/null +++ b/Hazel/src/Hazel/Core/Buffer.h @@ -0,0 +1,103 @@ +// +// Created by sfd on 25-10-26. +// + +#ifndef BUFFER_H +#define BUFFER_H +#include + +namespace Hazel +{ + struct Buffer + { + uint8_t* Data = nullptr; + uint64_t Size = 0; + + Buffer() = default; + + Buffer(const uint64_t size) + { + Allocate(size); + } + + Buffer(const Buffer&) = default; + + static Buffer Copy(const Buffer other) + { + const Buffer result(other.Size); + memcpy(result.Data, other.Data, other.Size); + return result; + } + + void Allocate(uint64_t size) + { + Release(); + + Data = new uint8_t[size]; + Size = size; + } + + void Release() + { + if (Data != nullptr) + delete[] Data; + Data = nullptr; + Size = 0; + } + + template + T* As() + { + return reinterpret_cast(Data); + } + + explicit operator bool() const + { + return static_cast(Data); + } + }; + + struct ScopedBuffer + { + ScopedBuffer(Buffer buffer) + : m_Buffer(buffer) + { + } + + ScopedBuffer(uint64_t size) + : m_Buffer(size) + { + } + + ~ScopedBuffer() + { + m_Buffer.Release(); + } + + uint8_t* Data() const + { + return m_Buffer.Data; + } + + uint64_t Size() const + { + return m_Buffer.Size; + } + + template + T* As() + { + return m_Buffer.As(); + } + + explicit operator bool() const + { + return static_cast(m_Buffer); + } + + private: + Buffer m_Buffer; + }; +} + +#endif //BUFFER_H diff --git a/Hazel/src/Hazel/Core/FileSystem.cpp b/Hazel/src/Hazel/Core/FileSystem.cpp new file mode 100644 index 0000000..4147347 --- /dev/null +++ b/Hazel/src/Hazel/Core/FileSystem.cpp @@ -0,0 +1,39 @@ +// +// Created by sfd on 25-10-26. +// + +#include "FileSystem.h" + +#include + +#include "Log.h" + +namespace Hazel +{ + Buffer FileSystem::ReadFileBinary(const std::filesystem::path& filePath) + { + std::ifstream file(filePath, std::ios::binary | std::ios::ate); + + if (!file) + { + HZ_CORE_WARN("could not open file '{0}'", filePath.string()); + return {}; + } + + std::streampos end = file.tellg(); + file.seekg(0, std::ios::beg); + uint64_t size = end - file.tellg(); + + if (size == 0) + { + HZ_CORE_WARN("file is empty"); + return {}; + } + + Buffer buffer(size); + file.read(buffer.As(), size); + file.close(); + return buffer; + } + +} diff --git a/Hazel/src/Hazel/Core/FileSystem.h b/Hazel/src/Hazel/Core/FileSystem.h new file mode 100644 index 0000000..102b5f9 --- /dev/null +++ b/Hazel/src/Hazel/Core/FileSystem.h @@ -0,0 +1,22 @@ +// +// Created by sfd on 25-10-26. +// + +#ifndef FILESYSTEM_H +#define FILESYSTEM_H +#include + +#include "Buffer.h" +#include "Core.h" + + +namespace Hazel +{ + class HAZEL_API FileSystem + { + public: + static Buffer ReadFileBinary(const std::filesystem::path& filePath); + }; +} + +#endif //FILESYSTEM_H diff --git a/Hazel/src/Hazel/Scene/SceneSerializer.cpp b/Hazel/src/Hazel/Scene/SceneSerializer.cpp index 634b8e4..8af2579 100644 --- a/Hazel/src/Hazel/Scene/SceneSerializer.cpp +++ b/Hazel/src/Hazel/Scene/SceneSerializer.cpp @@ -148,6 +148,18 @@ namespace YAML namespace Hazel { +#define WRITE_FIELD_TYPE(FieldType, Type) \ + case ScriptFieldType::FieldType: \ + out << scriptField.GetValue();break + + +#define READ_FIELD_TYPE(FieldType, Type) \ + case ScriptFieldType::FieldType: \ + { \ + Type valueData = scriptField["Data"].as(); \ + fieldInstance.SetValue(valueData); \ + break; \ + } @@ -252,9 +264,7 @@ namespace Hazel out << YAML::Key << "Data" << YAML::Value; ScriptFieldInstance& scriptField = entityFields.at(name); -#define WRITE_FIELD_TYPE(FieldType, Type) case ScriptFieldType::FieldType:\ - out << scriptField.GetValue();\ - break + switch (field.Type) { @@ -279,7 +289,6 @@ namespace Hazel } out << YAML::EndMap; -#undef WRITE_FIELD_TYPE } out << YAML::EndSeq; @@ -483,51 +492,44 @@ namespace Hazel if (scriptFields) { Ref entityClass = ScriptEngine::GetEntityClass(sc.ClassName); - const auto& fields = entityClass->GetFields(); - auto& entityFields = ScriptEngine::GetScriptFieldMap(deserializedEntity); - - for (auto scriptField: scriptFields) + if (entityClass) { - std::string name = scriptField["Name"].as(); - std::string typeName = scriptField["Type"].as(); - ScriptFieldType type = Utils::ScriptFieldTypeFromString(typeName); - ScriptFieldInstance& fieldInstance = entityFields[name]; + const auto& fields = entityClass->GetFields(); + auto& entityFields = ScriptEngine::GetScriptFieldMap(deserializedEntity); - fieldInstance.Field = fields.at(name); - - -#define READ_FIELD_TYPE(FieldType, Type) \ - case ScriptFieldType::FieldType: \ - { \ - Type valueData = scriptField["Data"].as(); \ - fieldInstance.SetValue(valueData); \ - break; \ - } - - - switch (type) + for (auto scriptField: scriptFields) { - READ_FIELD_TYPE(Float, float); - READ_FIELD_TYPE(Double, double); - READ_FIELD_TYPE(Boolean, bool); - READ_FIELD_TYPE(Char, char); - READ_FIELD_TYPE(Byte, int8_t); - READ_FIELD_TYPE(Short, int16_t); - READ_FIELD_TYPE(Int, int32_t); - READ_FIELD_TYPE(Long, int64_t); - READ_FIELD_TYPE(UByte, uint8_t); - READ_FIELD_TYPE(UShort, uint16_t); - READ_FIELD_TYPE(UInt, uint32_t); - READ_FIELD_TYPE(ULong, uint64_t); + std::string name = scriptField["Name"].as(); + std::string typeName = scriptField["Type"].as(); + ScriptFieldType type = Utils::ScriptFieldTypeFromString(typeName); + ScriptFieldInstance& fieldInstance = entityFields[name]; - READ_FIELD_TYPE(Vector2, glm::vec2); - READ_FIELD_TYPE(Vector3, glm::vec3); - READ_FIELD_TYPE(Vector4, glm::vec4); + fieldInstance.Field = fields.at(name); - READ_FIELD_TYPE(Entity, UUID); + + + switch (type) + { + READ_FIELD_TYPE(Float, float); + READ_FIELD_TYPE(Double, double); + READ_FIELD_TYPE(Boolean, bool); + READ_FIELD_TYPE(Char, char); + READ_FIELD_TYPE(Byte, int8_t); + READ_FIELD_TYPE(Short, int16_t); + READ_FIELD_TYPE(Int, int32_t); + READ_FIELD_TYPE(Long, int64_t); + READ_FIELD_TYPE(UByte, uint8_t); + READ_FIELD_TYPE(UShort, uint16_t); + READ_FIELD_TYPE(UInt, uint32_t); + READ_FIELD_TYPE(ULong, uint64_t); + + READ_FIELD_TYPE(Vector2, glm::vec2); + READ_FIELD_TYPE(Vector3, glm::vec3); + READ_FIELD_TYPE(Vector4, glm::vec4); + + READ_FIELD_TYPE(Entity, UUID); + } } - -#undef READ_FIELD_TYPE } } } diff --git a/Hazel/src/Hazel/Scripting/ScriptEngine.cpp b/Hazel/src/Hazel/Scripting/ScriptEngine.cpp index 8838436..29c7191 100644 --- a/Hazel/src/Hazel/Scripting/ScriptEngine.cpp +++ b/Hazel/src/Hazel/Scripting/ScriptEngine.cpp @@ -10,6 +10,8 @@ #include "FileWatch.h" #include "ScriptGlue.h" #include "Hazel/Core/Application.h" +#include "Hazel/Core/Buffer.h" +#include "Hazel/Core/FileSystem.h" #include "mono/jit/jit.h" #include "mono/metadata/assembly.h" #include "mono/metadata/attrdefs.h" @@ -46,6 +48,7 @@ namespace Hazel namespace Utils { + /* char* ReadBytes(const std::filesystem::path& filePath, uint32_t* outSize) { std::ifstream stream(filePath, std::ios::binary | std::ios::ate); @@ -73,16 +76,15 @@ namespace Hazel *outSize = (uint32_t)size; return buffer; } + */ MonoAssembly* LoadMonoAssembly(const std::filesystem::path& assemblyPath, bool loadPDB = false) { HZ_CORE_DEBUG("Load Assemble: {0}", assemblyPath.string().c_str()); - uint32_t fileSize = 0; - - char* fileData = ReadBytes(assemblyPath, &fileSize); + ScopedBuffer fileData = FileSystem::ReadFileBinary(assemblyPath); MonoImageOpenStatus status; - MonoImage* image = mono_image_open_from_data_full(fileData, fileSize, 1, &status, 0); + MonoImage* image = mono_image_open_from_data_full(fileData.As(), fileData.Size(), 1, &status, 0); if (status != MONO_IMAGE_OK) { const char* errorMessage = mono_image_strerror(status); @@ -98,13 +100,10 @@ namespace Hazel if (std::filesystem::exists(pdbPath)) { - uint32_t pdbFileSize = 0; - char* pdbFileData = ReadBytes(pdbPath, &pdbFileSize); - mono_debug_open_image_from_memory(image, (const mono_byte*)pdbFileData, fileSize); + ScopedBuffer pdbFileData = FileSystem::ReadFileBinary(pdbPath); + mono_debug_open_image_from_memory(image, pdbFileData.As(), fileData.Size()); HZ_CORE_INFO("loaded pdb file: {0}", pdbPath.string()); - HZ_CORE_INFO(" size: {0}", pdbFileSize); - - delete[] pdbFileData; + HZ_CORE_INFO(" size: {0}", pdbFileData.Size()); } } @@ -112,8 +111,6 @@ namespace Hazel MonoAssembly* assembly = mono_assembly_load_from_full(image, string.c_str(), &status, 0); mono_image_close(image); - delete[] fileData; - return assembly; } @@ -200,8 +197,20 @@ namespace Hazel InitMono(); ScriptGlue::RegisterFunctions(); - LoadAssemble("Resources/Scripts/Hazel-ScriptCore.dll"); - LoadAppAssemble("Resources/Scripts/Sandbox.dll"); + bool status = LoadAssemble("Resources/Scripts/Hazel-ScriptCore.dll"); + if (!status) + { + HZ_CORE_ERROR("[ScriptEngine] Could not load Hazel-ScriptCore assembly."); + return; + } + + status = LoadAppAssemble("Resources/Scripts/Sandbox.dll"); + if (!status) + { + HZ_CORE_ERROR("[ScriptEngine] Could not load app assembly."); + return; + } + LoadAssemblyClass(); Utils::PrintAssemblyTypes(s_Data->CoreAssembly); ScriptGlue::RegisterComponents(); @@ -249,32 +258,36 @@ namespace Hazel delete s_Data; } - void ScriptEngine::LoadAssemble(const std::filesystem::path& assemblePath) + bool ScriptEngine::LoadAssemble(const std::filesystem::path& assemblePath) { // Create an Domain App char monoDomainName[] = "HazelScriptRuntime"; s_Data->AppDomain = mono_domain_create_appdomain(monoDomainName, nullptr); mono_domain_set(s_Data->AppDomain, true); - // TODO: move this later s_Data->CoreAssemblyFilePath = assemblePath; s_Data->CoreAssembly = Utils::LoadMonoAssembly(assemblePath, s_Data->EnableDebugging); - s_Data->CoreAssemblyImage = mono_assembly_get_image(s_Data->CoreAssembly); + if (s_Data->CoreAssembly == nullptr) + return false; - // Utils::PrintAssemblyTypes(s_Data->CoreAssembly); + s_Data->CoreAssemblyImage = mono_assembly_get_image(s_Data->CoreAssembly); + return true; } - void ScriptEngine::LoadAppAssemble(const std::filesystem::path& assemblePath) + bool ScriptEngine::LoadAppAssemble(const std::filesystem::path& assemblePath) { // TODO: move this later s_Data->AppAssemblyFilePath = assemblePath; s_Data->AppAssembly = Utils::LoadMonoAssembly(assemblePath, s_Data->EnableDebugging); + if (s_Data->AppAssembly == nullptr) + return false; + s_Data->AppAssemblyImage = mono_assembly_get_image(s_Data->AppAssembly); s_Data->AppAssemblyFileWatcher = CreateScope>(assemblePath.string(), OnAssemblyFileSystemEvent); - auto& b = s_Data; s_Data->AssemblyReloading = false; - // Utils::PrintAssemblyTypes(s_Data->CoreAssembly); + + return true; } void ScriptEngine::ReloadAssemble() @@ -402,8 +415,7 @@ namespace Hazel UUID entityUUID = entity.GetUUID(); if (!s_Data->EntityInstances.contains(entityUUID)) { - HZ_CORE_FATAL("script cannot get"); - assert(1); + HZ_CORE_ERROR("Could not find ScriptInstance for entity {}", (uint64_t)entityUUID); } const Ref instance = s_Data->EntityInstances[entityUUID]; diff --git a/Hazel/src/Hazel/Scripting/ScriptEngine.h b/Hazel/src/Hazel/Scripting/ScriptEngine.h index e24c799..89681d6 100644 --- a/Hazel/src/Hazel/Scripting/ScriptEngine.h +++ b/Hazel/src/Hazel/Scripting/ScriptEngine.h @@ -145,8 +145,8 @@ namespace Hazel static void Init(); static void Shutdown(); - static void LoadAssemble(const std::filesystem::path& assemblePath); - static void LoadAppAssemble(const std::filesystem::path& assemblePath); + static bool LoadAssemble(const std::filesystem::path& assemblePath); + static bool LoadAppAssemble(const std::filesystem::path& assemblePath); static void ReloadAssemble();