Compare commits

..

1 Commits

Author SHA1 Message Date
75184d9a6e add c# debugging support 2025-10-26 16:08:38 +08:00
6 changed files with 69 additions and 248 deletions

View File

@ -1,103 +0,0 @@
//
// Created by sfd on 25-10-26.
//
#ifndef BUFFER_H
#define BUFFER_H
#include <cstdint>
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<typename T>
T* As()
{
return reinterpret_cast<T*>(Data);
}
explicit operator bool() const
{
return static_cast<bool>(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<typename T>
T* As()
{
return m_Buffer.As<T>();
}
explicit operator bool() const
{
return static_cast<bool>(m_Buffer);
}
private:
Buffer m_Buffer;
};
}
#endif //BUFFER_H

View File

@ -1,39 +0,0 @@
//
// Created by sfd on 25-10-26.
//
#include "FileSystem.h"
#include <fstream>
#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<char>(), size);
file.close();
return buffer;
}
}

View File

@ -1,22 +0,0 @@
//
// Created by sfd on 25-10-26.
//
#ifndef FILESYSTEM_H
#define FILESYSTEM_H
#include <filesystem>
#include "Buffer.h"
#include "Core.h"
namespace Hazel
{
class HAZEL_API FileSystem
{
public:
static Buffer ReadFileBinary(const std::filesystem::path& filePath);
};
}
#endif //FILESYSTEM_H

View File

@ -148,18 +148,6 @@ namespace YAML
namespace Hazel namespace Hazel
{ {
#define WRITE_FIELD_TYPE(FieldType, Type) \
case ScriptFieldType::FieldType: \
out << scriptField.GetValue<Type>();break
#define READ_FIELD_TYPE(FieldType, Type) \
case ScriptFieldType::FieldType: \
{ \
Type valueData = scriptField["Data"].as<Type>(); \
fieldInstance.SetValue(valueData); \
break; \
}
@ -264,7 +252,9 @@ namespace Hazel
out << YAML::Key << "Data" << YAML::Value; out << YAML::Key << "Data" << YAML::Value;
ScriptFieldInstance& scriptField = entityFields.at(name); ScriptFieldInstance& scriptField = entityFields.at(name);
#define WRITE_FIELD_TYPE(FieldType, Type) case ScriptFieldType::FieldType:\
out << scriptField.GetValue<Type>();\
break
switch (field.Type) switch (field.Type)
{ {
@ -289,6 +279,7 @@ namespace Hazel
} }
out << YAML::EndMap; out << YAML::EndMap;
#undef WRITE_FIELD_TYPE
} }
out << YAML::EndSeq; out << YAML::EndSeq;
@ -492,44 +483,51 @@ namespace Hazel
if (scriptFields) if (scriptFields)
{ {
Ref<ScriptClass> entityClass = ScriptEngine::GetEntityClass(sc.ClassName); Ref<ScriptClass> entityClass = ScriptEngine::GetEntityClass(sc.ClassName);
if (entityClass) const auto& fields = entityClass->GetFields();
auto& entityFields = ScriptEngine::GetScriptFieldMap(deserializedEntity);
for (auto scriptField: scriptFields)
{ {
const auto& fields = entityClass->GetFields(); std::string name = scriptField["Name"].as<std::string>();
auto& entityFields = ScriptEngine::GetScriptFieldMap(deserializedEntity); std::string typeName = scriptField["Type"].as<std::string>();
ScriptFieldType type = Utils::ScriptFieldTypeFromString(typeName);
ScriptFieldInstance& fieldInstance = entityFields[name];
for (auto scriptField: scriptFields) fieldInstance.Field = fields.at(name);
#define READ_FIELD_TYPE(FieldType, Type) \
case ScriptFieldType::FieldType: \
{ \
Type valueData = scriptField["Data"].as<Type>(); \
fieldInstance.SetValue(valueData); \
break; \
}
switch (type)
{ {
std::string name = scriptField["Name"].as<std::string>(); READ_FIELD_TYPE(Float, float);
std::string typeName = scriptField["Type"].as<std::string>(); READ_FIELD_TYPE(Double, double);
ScriptFieldType type = Utils::ScriptFieldTypeFromString(typeName); READ_FIELD_TYPE(Boolean, bool);
ScriptFieldInstance& fieldInstance = entityFields[name]; 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);
fieldInstance.Field = fields.at(name); READ_FIELD_TYPE(Vector2, glm::vec2);
READ_FIELD_TYPE(Vector3, glm::vec3);
READ_FIELD_TYPE(Vector4, glm::vec4);
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
} }
} }
} }

View File

@ -10,8 +10,6 @@
#include "FileWatch.h" #include "FileWatch.h"
#include "ScriptGlue.h" #include "ScriptGlue.h"
#include "Hazel/Core/Application.h" #include "Hazel/Core/Application.h"
#include "Hazel/Core/Buffer.h"
#include "Hazel/Core/FileSystem.h"
#include "mono/jit/jit.h" #include "mono/jit/jit.h"
#include "mono/metadata/assembly.h" #include "mono/metadata/assembly.h"
#include "mono/metadata/attrdefs.h" #include "mono/metadata/attrdefs.h"
@ -48,7 +46,6 @@ namespace Hazel
namespace Utils namespace Utils
{ {
/*
char* ReadBytes(const std::filesystem::path& filePath, uint32_t* outSize) char* ReadBytes(const std::filesystem::path& filePath, uint32_t* outSize)
{ {
std::ifstream stream(filePath, std::ios::binary | std::ios::ate); std::ifstream stream(filePath, std::ios::binary | std::ios::ate);
@ -76,15 +73,16 @@ namespace Hazel
*outSize = (uint32_t)size; *outSize = (uint32_t)size;
return buffer; return buffer;
} }
*/
MonoAssembly* LoadMonoAssembly(const std::filesystem::path& assemblyPath, bool loadPDB = false) MonoAssembly* LoadMonoAssembly(const std::filesystem::path& assemblyPath, bool loadPDB = false)
{ {
HZ_CORE_DEBUG("Load Assemble: {0}", assemblyPath.string().c_str()); HZ_CORE_DEBUG("Load Assemble: {0}", assemblyPath.string().c_str());
ScopedBuffer fileData = FileSystem::ReadFileBinary(assemblyPath); uint32_t fileSize = 0;
char* fileData = ReadBytes(assemblyPath, &fileSize);
MonoImageOpenStatus status; MonoImageOpenStatus status;
MonoImage* image = mono_image_open_from_data_full(fileData.As<char>(), fileData.Size(), 1, &status, 0); MonoImage* image = mono_image_open_from_data_full(fileData, fileSize, 1, &status, 0);
if (status != MONO_IMAGE_OK) if (status != MONO_IMAGE_OK)
{ {
const char* errorMessage = mono_image_strerror(status); const char* errorMessage = mono_image_strerror(status);
@ -100,10 +98,13 @@ namespace Hazel
if (std::filesystem::exists(pdbPath)) if (std::filesystem::exists(pdbPath))
{ {
ScopedBuffer pdbFileData = FileSystem::ReadFileBinary(pdbPath); uint32_t pdbFileSize = 0;
mono_debug_open_image_from_memory(image, pdbFileData.As<mono_byte>(), fileData.Size()); char* pdbFileData = ReadBytes(pdbPath, &pdbFileSize);
mono_debug_open_image_from_memory(image, (const mono_byte*)pdbFileData, fileSize);
HZ_CORE_INFO("loaded pdb file: {0}", pdbPath.string()); HZ_CORE_INFO("loaded pdb file: {0}", pdbPath.string());
HZ_CORE_INFO(" size: {0}", pdbFileData.Size()); HZ_CORE_INFO(" size: {0}", pdbFileSize);
delete[] pdbFileData;
} }
} }
@ -111,6 +112,8 @@ namespace Hazel
MonoAssembly* assembly = mono_assembly_load_from_full(image, string.c_str(), &status, 0); MonoAssembly* assembly = mono_assembly_load_from_full(image, string.c_str(), &status, 0);
mono_image_close(image); mono_image_close(image);
delete[] fileData;
return assembly; return assembly;
} }
@ -169,8 +172,7 @@ namespace Hazel
Scope<filewatch::FileWatch<std::string>> AppAssemblyFileWatcher; Scope<filewatch::FileWatch<std::string>> AppAssemblyFileWatcher;
bool AssemblyReloading = false; bool AssemblyReloading = false;
// Mono C# debug bool EnableDebugging = false;
bool EnableDebugging = true;
// runtime // runtime
Scene* SceneContext = nullptr; Scene* SceneContext = nullptr;
@ -197,20 +199,8 @@ namespace Hazel
InitMono(); InitMono();
ScriptGlue::RegisterFunctions(); ScriptGlue::RegisterFunctions();
bool status = LoadAssemble("Resources/Scripts/Hazel-ScriptCore.dll"); LoadAssemble("Resources/Scripts/Hazel-ScriptCore.dll");
if (!status) LoadAppAssemble("Resources/Scripts/Sandbox.dll");
{
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(); LoadAssemblyClass();
Utils::PrintAssemblyTypes(s_Data->CoreAssembly); Utils::PrintAssemblyTypes(s_Data->CoreAssembly);
ScriptGlue::RegisterComponents(); ScriptGlue::RegisterComponents();
@ -258,36 +248,32 @@ namespace Hazel
delete s_Data; delete s_Data;
} }
bool ScriptEngine::LoadAssemble(const std::filesystem::path& assemblePath) void ScriptEngine::LoadAssemble(const std::filesystem::path& assemblePath)
{ {
// Create an Domain App // Create an Domain App
char monoDomainName[] = "HazelScriptRuntime"; char monoDomainName[] = "HazelScriptRuntime";
s_Data->AppDomain = mono_domain_create_appdomain(monoDomainName, nullptr); s_Data->AppDomain = mono_domain_create_appdomain(monoDomainName, nullptr);
mono_domain_set(s_Data->AppDomain, true); mono_domain_set(s_Data->AppDomain, true);
// TODO: move this later
s_Data->CoreAssemblyFilePath = assemblePath; s_Data->CoreAssemblyFilePath = assemblePath;
s_Data->CoreAssembly = Utils::LoadMonoAssembly(assemblePath, s_Data->EnableDebugging); s_Data->CoreAssembly = Utils::LoadMonoAssembly(assemblePath, s_Data->EnableDebugging);
if (s_Data->CoreAssembly == nullptr)
return false;
s_Data->CoreAssemblyImage = mono_assembly_get_image(s_Data->CoreAssembly); s_Data->CoreAssemblyImage = mono_assembly_get_image(s_Data->CoreAssembly);
return true;
// Utils::PrintAssemblyTypes(s_Data->CoreAssembly);
} }
bool ScriptEngine::LoadAppAssemble(const std::filesystem::path& assemblePath) void ScriptEngine::LoadAppAssemble(const std::filesystem::path& assemblePath)
{ {
// TODO: move this later // TODO: move this later
s_Data->AppAssemblyFilePath = assemblePath; s_Data->AppAssemblyFilePath = assemblePath;
s_Data->AppAssembly = Utils::LoadMonoAssembly(assemblePath, s_Data->EnableDebugging); 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->AppAssemblyImage = mono_assembly_get_image(s_Data->AppAssembly);
s_Data->AppAssemblyFileWatcher = CreateScope<filewatch::FileWatch<std::string>>(assemblePath.string(), OnAssemblyFileSystemEvent); s_Data->AppAssemblyFileWatcher = CreateScope<filewatch::FileWatch<std::string>>(assemblePath.string(), OnAssemblyFileSystemEvent);
auto& b = s_Data;
s_Data->AssemblyReloading = false; s_Data->AssemblyReloading = false;
// Utils::PrintAssemblyTypes(s_Data->CoreAssembly);
return true;
} }
void ScriptEngine::ReloadAssemble() void ScriptEngine::ReloadAssemble()
@ -415,7 +401,8 @@ namespace Hazel
UUID entityUUID = entity.GetUUID(); UUID entityUUID = entity.GetUUID();
if (!s_Data->EntityInstances.contains(entityUUID)) if (!s_Data->EntityInstances.contains(entityUUID))
{ {
HZ_CORE_ERROR("Could not find ScriptInstance for entity {}", (uint64_t)entityUUID); HZ_CORE_FATAL("script cannot get");
assert(1);
} }
const Ref<ScriptInstance> instance = s_Data->EntityInstances[entityUUID]; const Ref<ScriptInstance> instance = s_Data->EntityInstances[entityUUID];

View File

@ -145,8 +145,8 @@ namespace Hazel
static void Init(); static void Init();
static void Shutdown(); static void Shutdown();
static bool LoadAssemble(const std::filesystem::path& assemblePath); static void LoadAssemble(const std::filesystem::path& assemblePath);
static bool LoadAppAssemble(const std::filesystem::path& assemblePath); static void LoadAppAssemble(const std::filesystem::path& assemblePath);
static void ReloadAssemble(); static void ReloadAssemble();