From 3d404294ab27d24683b695518cc6d81f9ac09710 Mon Sep 17 00:00:00 2001 From: ouczbs Date: Tue, 11 Feb 2025 11:16:46 +0800 Subject: [PATCH] support scene serialize --- .vscode/settings.json | 3 +- README.md | 7 +- engine/assets/logo.png | Bin 0 -> 11639 bytes engine/assets/scene/entry.scene | 12 ++ engine/assets/scene/entry/main.level | 13 ++ engine/include/engine/app.h | 12 ++ engine/modules/engine/app/impl/app_impl.inl | 7 +- .../engine/app/impl/scene_system_impl.inl | 163 ++++++++++++++++++ engine/modules/engine/app/include/app.inl | 25 --- .../app/include/{app.h => app_module.h} | 11 +- .../engine/app/include/data/editor_config.h | 9 + .../engine/app/include/data/engine_config.h | 4 - .../modules/engine/app/include/data/global.h | 9 +- .../engine/app/include/data/project_config.h | 3 + .../app/include/object/component/transform.h | 7 + .../engine/app/include/object/game_object.h | 31 ++++ .../modules/engine/app/include/scene/level.h | 26 +++ .../app/include/scene/level_blueprint.h | 11 ++ .../modules/engine/app/include/scene/scene.h | 31 ++++ .../engine/app/include/scene/scene_system.h | 25 +++ .../app/src/{app.cpp => app_module.cpp} | 5 +- .../app/src/object/component/transform.cpp | 0 .../engine/app/src/object/game_object.cpp | 0 engine/modules/engine/app/src/scene/level.cpp | 16 ++ .../engine/app/src/scene/level_blueprint.cpp | 28 +++ engine/modules/engine/app/src/scene/scene.cpp | 31 ++++ engine/modules/engine/app/xmake.lua | 5 +- .../engine/core/include/archive/json.h | 18 +- .../core/include/archive/json/serde.inl | 8 +- .../core/include/archive/json/serialize.inl | 2 +- .../engine/core/include/archive/reflect.h | 77 +++++++++ .../engine/core/include/archive/type.h | 9 + .../engine/core/include/archive/yaml.h | 18 +- .../core/include/archive/yaml/serde.inl | 16 +- .../core/include/archive/yaml/serialize.inl | 14 +- .../engine/core/include/os/file_system.h | 1 + .../modules/engine/core/src/module/module.cpp | 4 + .../engine/core/src/os/file_handle.cpp | 2 + .../engine/core/src/os/file_system.cpp | 11 ++ engine/modules/engine/zlib/include/pmr/name.h | 1 + .../modules/engine/zlib/include/pmr/name.inl | 19 ++ .../engine/zlib/include/refl/detail/any.h | 14 +- .../zlib/include/refl/detail/container.inl | 2 +- .../zlib/include/refl/detail/uclass.inl | 5 + .../render/vulkan/src/vulkan_ui_system.cpp | 6 +- .../src/editor/window/editor_main_window.cpp | 4 +- engine/src/engine/app.cpp | 54 ++++++ engine/src/engine/plugin.cpp | 2 + engine/xmake/rule_api/package_api.lua | 3 + game/zworld/src/zworld.cpp | 8 +- 50 files changed, 700 insertions(+), 92 deletions(-) create mode 100644 engine/assets/logo.png create mode 100644 engine/assets/scene/entry.scene create mode 100644 engine/assets/scene/entry/main.level create mode 100644 engine/include/engine/app.h create mode 100644 engine/modules/engine/app/impl/scene_system_impl.inl delete mode 100644 engine/modules/engine/app/include/app.inl rename engine/modules/engine/app/include/{app.h => app_module.h} (55%) create mode 100644 engine/modules/engine/app/include/data/editor_config.h create mode 100644 engine/modules/engine/app/include/object/component/transform.h create mode 100644 engine/modules/engine/app/include/object/game_object.h create mode 100644 engine/modules/engine/app/include/scene/level.h create mode 100644 engine/modules/engine/app/include/scene/level_blueprint.h create mode 100644 engine/modules/engine/app/include/scene/scene.h create mode 100644 engine/modules/engine/app/include/scene/scene_system.h rename engine/modules/engine/app/src/{app.cpp => app_module.cpp} (66%) create mode 100644 engine/modules/engine/app/src/object/component/transform.cpp create mode 100644 engine/modules/engine/app/src/object/game_object.cpp create mode 100644 engine/modules/engine/app/src/scene/level.cpp create mode 100644 engine/modules/engine/app/src/scene/level_blueprint.cpp create mode 100644 engine/modules/engine/app/src/scene/scene.cpp create mode 100644 engine/modules/engine/core/include/archive/reflect.h create mode 100644 engine/src/engine/app.cpp diff --git a/.vscode/settings.json b/.vscode/settings.json index 4114250..5081ccf 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,6 +4,7 @@ "bitmap.c": "cpp", "heap.c": "cpp", "init.c": "cpp", - "random.c": "cpp" + "random.c": "cpp", + "type_traits": "cpp" } } \ No newline at end of file diff --git a/README.md b/README.md index 235870f..e59a55d 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,16 @@ +![Logo](engine/assets/logo.png) # 个人游戏引擎 +原始项目: http://175.24.226.114:3000/ouczbs/zengine.git + 这是一个模块化的 C++ 游戏引擎,旨在帮助学习和实现基本的游戏引擎系统。它包括多个模块,如渲染、资源管理、UI 等,并使用 Vulkan 作为主要的渲染 API。该引擎的结构被拆分为多个静态库和动态链接库(DLL),通过 `xmake` 管理。 ## 功能 - **模块化架构**:将引擎拆分成多个独立模块,提高了可维护性和可扩展性。 - **渲染**:使用 Vulkan 实现,且有抽象层支持未来扩展到 OpenGL、DirectX 和 Metal 等其他渲染 API。 - **资源管理**:包括基础的资源管理、加载和序列化功能。 -- **UI**:集成了 NoesisGUI 进行 XAML UI 元素的渲染。 -- **全局变量管理**:通过 `engine.dll` 集中管理全局状态,避免模块间不一致。 +- **UI**:初步集成了 NoesisGUI 和 ImGui 进行 XAML UI 元素的渲染。 +- **接口导出**:通过 `engine.dll` 集中管理全局状态,避免模块间不一致。 - **高效内存管理**:通过 `pmr` 内存资源和模板元编程优化内存分配。 - **编辑器支持**:为编辑器功能提供基本的集成,未来计划使用 ImGui 和 NoesisGUI 开发完整的编辑器工具。 diff --git a/engine/assets/logo.png b/engine/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..956cea21eb9593dff79b0e561452699097d27622 GIT binary patch literal 11639 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 scenes; + table pathTable; + public: + void LoadScene(PackagePath path, bool switchNow = true); + void SwitchScene(Name name); + void DeleteScene(Name name); + void DeleteAllScene(); + void ReloadScene(); + void Render(); + void Update(); + Scene* GetCurScene(); + Scene* GetScene(Name name); + Scene* FindScene(PackagePath path); + }; + Scene* SceneSystemImpl::GetScene(Name name) + { + auto iter = scenes.find(name); + if (iter != scenes.end()) + return iter->second; + return nullptr; + } + Scene* SceneSystemImpl::FindScene(PackagePath path) + { + Name name = Name::Find(path.path); + auto it = pathTable.find(name); + if (it != pathTable.end()) { + return GetScene(it->second); + } + return nullptr; + } + void SceneSystemImpl::LoadScene(PackagePath path, bool switchNow) + { + Scene* pScene = FindScene(path); + if (pScene) { + curScene = pScene; + return; + } + FileHandle handle(path); + if (!handle.Open(FILE_OP::READ)) { + return; + } + pmr::string text = handle.ReadAll(); + pScene = new Scene(); + if (!TextDeserialize(text, pScene)) _UNLIKELY{ + delete pScene; + return; + }; + pScene->mPath = path(); + pathTable.emplace(pScene->mPath, pScene->mName); + scenes.emplace(pScene->mName, pScene); + curScene = pScene; + curScene->OnLoad(); + } + void SceneSystemImpl::SwitchScene(Name name) + { + auto scene = GetScene(name); + if (scene == nullptr) _UNLIKELY + { + zlog::error("Switch to invalid scene: {}", name.data()); + return; + } + curScene = scene; + } + void SceneSystemImpl::DeleteScene(Name name) + { + auto iter = scenes.find(name); + if (iter == scenes.end()) _UNLIKELY + { + zlog::info("Attempt to delete a nonexistent scene: {}", name.ToStringView()); + return; + } + delete iter->second; + scenes.erase(iter); + } + void SceneSystemImpl::DeleteAllScene() + { + for (auto& iter : scenes) + { + delete iter.second; + } + scenes.clear(); + } + void SceneSystemImpl::ReloadScene() + { + if (!curScene)_UNLIKELY{ + return; + } + Name path = curScene->mPath; + DeleteScene(curScene->mName); + LoadScene(path, true); + } + void SceneSystemImpl::Render() + { + if(curScene) _LIKELY + curScene->Render(); + } + void SceneSystemImpl::Update() + { + if(curScene) _LIKELY + curScene->Update(); + } + Scene* SceneSystemImpl::GetCurScene() + { + return curScene; + } + SINGLETON_DEFINE(SceneSystem) + SceneSystem::SceneSystem() + { + SINGLETON_PTR(); + impl = new (GlobalPool())SceneSystemImpl(); + } + void SceneSystem::Initialize() + { + + } + void SceneSystem::Finalize() + { + + } + void SceneSystem::LoadScene(PackagePath path, bool switchNow) + { + impl->LoadScene(path, switchNow); + } + void SceneSystem::SwitchScene(Name name) + { + impl->SwitchScene(name); + } + void SceneSystem::DeleteScene(Name name) + { + impl->DeleteScene(name); + } + void SceneSystem::DeleteAllScene() + { + impl->DeleteAllScene(); + } + void SceneSystem::ReloadScene() + { + impl->ReloadScene(); + } + void SceneSystem::Render() + { + impl->Render(); + } + void SceneSystem::Update() + { + impl->Update(); + } + Scene* SceneSystem::GetCurScene() + { + return impl->GetCurScene(); + } + Scene* SceneSystem::GetScene(Name name) + { + return impl->GetScene(name); + } +} \ No newline at end of file diff --git a/engine/modules/engine/app/include/app.inl b/engine/modules/engine/app/include/app.inl deleted file mode 100644 index c9c6410..0000000 --- a/engine/modules/engine/app/include/app.inl +++ /dev/null @@ -1,25 +0,0 @@ -namespace api { - template - class AppImpl { - void Setup() { - static_cast(this)->Setup(); - } - void CleanUp() { - static_cast(this)->CleanUp(); - } - void ImGui() { - static_cast(this)->ImGui(); - } - void PreRender() { - static_cast(this)->PreRender(); - } - void PostRender() { - static_cast(this)->PostRender(); - } - }; - template - inline void App::Run(EngineConfig config, AppImpl& impl) - { - impl.Setup(); - } -} \ No newline at end of file diff --git a/engine/modules/engine/app/include/app.h b/engine/modules/engine/app/include/app_module.h similarity index 55% rename from engine/modules/engine/app/include/app.h rename to engine/modules/engine/app/include/app_module.h index ff1281d..20c1bfc 100644 --- a/engine/modules/engine/app/include/app.h +++ b/engine/modules/engine/app/include/app_module.h @@ -1,6 +1,5 @@ #pragma once #include "module/module.h" -#include "data/engine_config.h" namespace api{ class APP_API AppModule : public IStaticModule { @@ -9,12 +8,4 @@ namespace api{ void OnUnload() override; void InitMetaData(void) override {}; }; - template - class AppImpl; - class App { - public: - template - void Run(EngineConfig config, AppImpl& impl); - }; -} -#include "app.inl" \ No newline at end of file +} \ No newline at end of file diff --git a/engine/modules/engine/app/include/data/editor_config.h b/engine/modules/engine/app/include/data/editor_config.h new file mode 100644 index 0000000..4738a53 --- /dev/null +++ b/engine/modules/engine/app/include/data/editor_config.h @@ -0,0 +1,9 @@ +#pragma once +#include "render/type.h" +namespace api{ + struct EditorConfig { + bool IsRenderEditorSurface = false; + bool IsGameStart = false; + bool isGamePause = false; + }; +} \ No newline at end of file diff --git a/engine/modules/engine/app/include/data/engine_config.h b/engine/modules/engine/app/include/data/engine_config.h index e590e22..84da196 100644 --- a/engine/modules/engine/app/include/data/engine_config.h +++ b/engine/modules/engine/app/include/data/engine_config.h @@ -3,9 +3,5 @@ namespace api{ struct EngineConfig { GraphicsAPI API = GraphicsAPI::Vulkan; -#ifdef WITH_EDITOR - bool IsRenderEditorSurface = false; -#endif // WITH_EDITOR - }; } \ No newline at end of file diff --git a/engine/modules/engine/app/include/data/global.h b/engine/modules/engine/app/include/data/global.h index 7a8a3a2..d8f6ab8 100644 --- a/engine/modules/engine/app/include/data/global.h +++ b/engine/modules/engine/app/include/data/global.h @@ -8,4 +8,11 @@ namespace api { constexpr const char* CFileMountName = "/work/assets/file_mount.meta"; extern APP_API EngineConfig gEngineConfig; -} \ No newline at end of file + extern APP_API ProjectConfig gProjectConfig; +} +#ifdef WITH_EDITOR +#include "editor_config.h" +namespace api{ + extern APP_API EditorConfig gEditorConfig; +} +#endif \ No newline at end of file diff --git a/engine/modules/engine/app/include/data/project_config.h b/engine/modules/engine/app/include/data/project_config.h index a92349d..5f2160d 100644 --- a/engine/modules/engine/app/include/data/project_config.h +++ b/engine/modules/engine/app/include/data/project_config.h @@ -1,5 +1,8 @@ #pragma once +#include "pmr/name.h" namespace api{ + using pmr::Name; struct ProjectConfig { + Name EntryScene; }; } \ No newline at end of file diff --git a/engine/modules/engine/app/include/object/component/transform.h b/engine/modules/engine/app/include/object/component/transform.h new file mode 100644 index 0000000..11614af --- /dev/null +++ b/engine/modules/engine/app/include/object/component/transform.h @@ -0,0 +1,7 @@ +#pragma once +#include "object/game_object.h" +namespace api { + class Transform : public Component { + + }; +} \ No newline at end of file diff --git a/engine/modules/engine/app/include/object/game_object.h b/engine/modules/engine/app/include/object/game_object.h new file mode 100644 index 0000000..54d5127 --- /dev/null +++ b/engine/modules/engine/app/include/object/game_object.h @@ -0,0 +1,31 @@ +#pragma once +#include "archive/reflect.h" +namespace api { + using pmr::Name; + using refl::TAny; + using std::vector; + class Component; + class GameObject { + private: + GENERATED_BODY() + UPROPERTY() + Name mName; + UPROPERTY() + vector> mChildrens; + UPROPERTY() + vector> mComponents; + public: + + }; + class Component { + private: + GENERATED_BODY() + UPROPERTY() + Name mName; + GameObject* mOwner; + + public: + + }; +} +#include ".app/game_object_gen.inl" \ No newline at end of file diff --git a/engine/modules/engine/app/include/scene/level.h b/engine/modules/engine/app/include/scene/level.h new file mode 100644 index 0000000..0228a7c --- /dev/null +++ b/engine/modules/engine/app/include/scene/level.h @@ -0,0 +1,26 @@ +#pragma once +#include "object/game_object.h" +#include "math/vector3.h" +namespace api { + using refl::TAny; + struct LevelInfo { + UPROPERTY() + Name mName; + UPROPERTY() + Name mPath; + UPROPERTY() + Vector3 mOffset; + }; + class Level : public LevelInfo{ + protected: + GENERATED_BODY() + UPROPERTY() + vector> mObjects; + public: + Level(const LevelInfo& info) : LevelInfo(info) {}; + Level(); + ~Level(); + void AddObject(TAny object); + }; +} +#include ".app/level_gen.inl" \ No newline at end of file diff --git a/engine/modules/engine/app/include/scene/level_blueprint.h b/engine/modules/engine/app/include/scene/level_blueprint.h new file mode 100644 index 0000000..8af3b41 --- /dev/null +++ b/engine/modules/engine/app/include/scene/level_blueprint.h @@ -0,0 +1,11 @@ +#pragma once +#include "object/game_object.h" +namespace api { + class Scene; + class LevelBlueprint { + public: + LevelBlueprint(); + ~LevelBlueprint(); + void LoadScene(Scene* scene); + }; +} \ No newline at end of file diff --git a/engine/modules/engine/app/include/scene/scene.h b/engine/modules/engine/app/include/scene/scene.h new file mode 100644 index 0000000..341467c --- /dev/null +++ b/engine/modules/engine/app/include/scene/scene.h @@ -0,0 +1,31 @@ +#pragma once +#include "level.h" +namespace api { + class LevelBlueprint; + struct SceneInfo { + UPROPERTY() + Name mName; + Name mPath; + UPROPERTY() + TAny mLevelBlueprint; + UPROPERTY() + vector mLevelInfos; + }; + class Scene : public SceneInfo{ + protected: + GENERATED_BODY() + + vector mLevels; + vector mObjects; + public: + Scene(const SceneInfo& info) : SceneInfo(info) {}; + Scene(); + ~Scene(); + void OnLoad(); + void Update(); + void Render(); + void AddLevel(Level* level); + void AddGameObject(GameObject* object); + }; +} +#include ".app/scene_gen.inl" \ No newline at end of file diff --git a/engine/modules/engine/app/include/scene/scene_system.h b/engine/modules/engine/app/include/scene/scene_system.h new file mode 100644 index 0000000..6316198 --- /dev/null +++ b/engine/modules/engine/app/include/scene/scene_system.h @@ -0,0 +1,25 @@ +#pragma once +#include "module/module.h" +namespace api { + class Scene; + class SceneSystemImpl; + class APP_API SceneSystem : public ISystem { + SINGLETON_IMPL(SceneSystem) + private: + SceneSystemImpl* impl; + public: + SceneSystem(); + void Initialize() override; + void Finalize() override; + public: + void LoadScene(PackagePath path, bool switchNow = true); + void SwitchScene(Name name); + void DeleteScene(Name name); + void DeleteAllScene(); + void ReloadScene(); + void Render(); + void Update(); + Scene* GetCurScene(); + Scene* GetScene(Name name); + }; +} \ No newline at end of file diff --git a/engine/modules/engine/app/src/app.cpp b/engine/modules/engine/app/src/app_module.cpp similarity index 66% rename from engine/modules/engine/app/src/app.cpp rename to engine/modules/engine/app/src/app_module.cpp index 89f8e39..16f1366 100644 --- a/engine/modules/engine/app/src/app.cpp +++ b/engine/modules/engine/app/src/app_module.cpp @@ -1,10 +1,11 @@ -#include "data/engine_config.h" #include "event/event_system.h" -#include "app.h" +#include "scene/scene_system.h" +#include "app_module.h" namespace api { void AppModule::OnLoad(int argc, char** argv) { AddSystem(); + AddSystem(); } void AppModule::OnUnload() { diff --git a/engine/modules/engine/app/src/object/component/transform.cpp b/engine/modules/engine/app/src/object/component/transform.cpp new file mode 100644 index 0000000..e69de29 diff --git a/engine/modules/engine/app/src/object/game_object.cpp b/engine/modules/engine/app/src/object/game_object.cpp new file mode 100644 index 0000000..e69de29 diff --git a/engine/modules/engine/app/src/scene/level.cpp b/engine/modules/engine/app/src/scene/level.cpp new file mode 100644 index 0000000..f4d8802 --- /dev/null +++ b/engine/modules/engine/app/src/scene/level.cpp @@ -0,0 +1,16 @@ +#include "scene/level.h" + +namespace api { + Level::Level() + { + + } + Level::~Level() + { + + } + void Level::AddObject(TAny object) + { + mObjects.push_back(object); + } +} diff --git a/engine/modules/engine/app/src/scene/level_blueprint.cpp b/engine/modules/engine/app/src/scene/level_blueprint.cpp new file mode 100644 index 0000000..9418371 --- /dev/null +++ b/engine/modules/engine/app/src/scene/level_blueprint.cpp @@ -0,0 +1,28 @@ +#include "scene/level_blueprint.h" +#include "scene/scene.h" +#include "os/file_handle.h" +#include "archive/pch.h" +namespace api { + LevelBlueprint::LevelBlueprint() + { + } + LevelBlueprint::~LevelBlueprint() + { + } + void LevelBlueprint::LoadScene(Scene* scene) + { + for (auto& levelInfo : scene->mLevelInfos) { + FileHandle handle(levelInfo.mPath); + if (!handle.Open(FILE_OP::READ)) { + continue; + } + Level* pLevel = new Level(levelInfo); + pmr::string text = handle.ReadAll(); + if (!TextDeserialize(text, pLevel)) { + delete pLevel; + continue; + } + scene->AddLevel(pLevel); + } + } +} diff --git a/engine/modules/engine/app/src/scene/scene.cpp b/engine/modules/engine/app/src/scene/scene.cpp new file mode 100644 index 0000000..d5b5bf7 --- /dev/null +++ b/engine/modules/engine/app/src/scene/scene.cpp @@ -0,0 +1,31 @@ +#include "scene/scene.h" +#include "scene/level_blueprint.h" +namespace api { + Scene::Scene() + { + + } + Scene::~Scene() + { + } + void Scene::OnLoad() + { + if (mLevelBlueprint) { + mLevelBlueprint->LoadScene(this); + } + } + void Scene::Update() + { + } + void Scene::Render() + { + } + void Scene::AddLevel(Level* level) + { + mLevels.push_back(level); + } + void Scene::AddGameObject(GameObject* object) + { + mObjects.push_back(object); + } +} diff --git a/engine/modules/engine/app/xmake.lua b/engine/modules/engine/app/xmake.lua index 81c3785..a15c5a9 100644 --- a/engine/modules/engine/app/xmake.lua +++ b/engine/modules/engine/app/xmake.lua @@ -1,4 +1,7 @@ static_component("app","engine") - add_headerfiles("include/**.h", "include/**.inl") + add_rules("c++.codegen",{ + files = {"include/object/**.h", "include/scene/*.h"} + }) + add_headerfiles("include/**.h") add_files("src/**.cpp") add_deps("core", "asset", "zlib", "render") \ No newline at end of file diff --git a/engine/modules/engine/core/include/archive/json.h b/engine/modules/engine/core/include/archive/json.h index 8d591a9..1c189c4 100644 --- a/engine/modules/engine/core/include/archive/json.h +++ b/engine/modules/engine/core/include/archive/json.h @@ -7,15 +7,15 @@ #define JSON_WRITE_FLAGS YYJSON_WRITE_NOFLAG #endif namespace gen { - template<> - inline bool JsonRead(yyjson_val* node, const refl::Any& t) { - if (!node) return false; - return api::JsonArchive::Deserialize(node, t); - } - template<> - inline yyjson_mut_val* JsonWrite(yyjson_mut_doc* doc, const refl::Any& t) { - return api::JsonArchive::Serialize(doc, t); - } + template + struct JsonSerde { + inline static bool Read(yyjson_val* val, const void* ptr) { + return api::JsonArchive::Deserialize(val, refl::Any{ ptr, refl::meta_info() }); + } + inline static yyjson_mut_val* Write(yyjson_mut_doc* doc, const void* ptr) { + return api::JsonArchive::Serialize(doc, refl::Any{ ptr, refl::meta_info() }); + } + }; } namespace api { namespace detail { diff --git a/engine/modules/engine/core/include/archive/json/serde.inl b/engine/modules/engine/core/include/archive/json/serde.inl index c0efb3e..1e23dde 100644 --- a/engine/modules/engine/core/include/archive/json/serde.inl +++ b/engine/modules/engine/core/include/archive/json/serde.inl @@ -37,8 +37,8 @@ namespace gen { for (size_t i = 0; i < length; ++i) { yyjson_val* obj_i = yyjson_arr_get(val, i); if constexpr (refl::is_map_v) { - JsonRead(yyjson_obj_get(obj_i, "#k"), it.first); - JsonRead(yyjson_obj_get(obj_i, "#v"), it.second); + JsonRead(yyjson_obj_get(obj_i, MAP_KEY_NAME), it.first); + JsonRead(yyjson_obj_get(obj_i, MAP_VALUE_NAME), it.second); docker[it.first] = it.second; } else { @@ -54,8 +54,8 @@ namespace gen { if constexpr (refl::is_map_v) { for (auto& it : docker) { yyjson_mut_val* obj = yyjson_mut_obj(doc); - yyjson_mut_obj_add_val(doc, obj, "#k", JsonWrite(doc, it.first)); - yyjson_mut_obj_add_val(doc, obj, "#v", JsonWrite(doc, it.second)); + yyjson_mut_obj_add_val(doc, obj, MAP_KEY_NAME, JsonWrite(doc, it.first)); + yyjson_mut_obj_add_val(doc, obj, MAP_VALUE_NAME, JsonWrite(doc, it.second)); yyjson_mut_arr_add_val(arr, obj); } } diff --git a/engine/modules/engine/core/include/archive/json/serialize.inl b/engine/modules/engine/core/include/archive/json/serialize.inl index 6efc93b..3bad3be 100644 --- a/engine/modules/engine/core/include/archive/json/serialize.inl +++ b/engine/modules/engine/core/include/archive/json/serialize.inl @@ -66,7 +66,7 @@ namespace api { } yyjson_mut_val* obj = yyjson_mut_obj(doc); if (auto p = any.Parent()) { - yyjson_mut_obj_add_val(doc, obj, "__parent__", Serialize(doc, p)); + yyjson_mut_obj_add_val(doc, obj, PARENT_KEY_NAME, Serialize(doc, p)); } auto fieldList = any.cls->GetFields(refl::FIND_ALL_MEMBER, pmr::Name("")); for (auto& field : fieldList) { diff --git a/engine/modules/engine/core/include/archive/reflect.h b/engine/modules/engine/core/include/archive/reflect.h new file mode 100644 index 0000000..66534ee --- /dev/null +++ b/engine/modules/engine/core/include/archive/reflect.h @@ -0,0 +1,77 @@ +#pragma once +#include "refl/pch.h" +#include "math/vector2.h" +#include "math/vector3.h" +#include "math/vector4.h" +namespace refl { + template<> struct Meta { + using T = api::Vector2; + using Impl = gen::MetaImpl; + }; +} +namespace refl { + template<> struct Meta { + using T = api::Vector3; + using Impl = gen::MetaImpl; + }; +} +namespace refl { + template<> struct Meta { + using T = api::Vector4; + using Impl = gen::MetaImpl; + }; +} +namespace gen { + template<> struct MetaImpl : public refl::MetaHelp { + using T = api::Vector2; + consteval static int MemberCount() { return 2; }; + consteval static int StaticMemberCount() { return 0; }; + consteval static int CtorCount() { return 0; }; + consteval static auto Fields() { + return std::make_tuple(FProperty(&T::x, "x"), FProperty(&T::y, "y")); + } + static auto MakeFields() { + return std::array{ + MemberField(&T::x, "x", {}), + MemberField(&T::y, "y", {}), + }; + }; + }; +} +namespace gen { + template<> struct MetaImpl : public refl::MetaHelp { + using T = api::Vector3; + consteval static int MemberCount() { return 3; }; + consteval static int StaticMemberCount() { return 0; }; + consteval static int CtorCount() { return 0; }; + consteval static auto Fields() { + return std::make_tuple(FProperty(&T::x, "x"), FProperty(&T::y, "y"), FProperty(&T::z, "z")); + } + static auto MakeFields() { + return std::array{ + MemberField(&T::x, "x", {}), + MemberField(&T::y, "y", {}), + MemberField(&T::z, "z", {}), + }; + }; + }; +} +namespace gen { + template<> struct MetaImpl : public refl::MetaHelp { + using T = api::Vector4; + consteval static int MemberCount() { return 4; }; + consteval static int StaticMemberCount() { return 0; }; + consteval static int CtorCount() { return 0; }; + consteval static auto Fields() { + return std::make_tuple(FProperty(&T::x, "x"), FProperty(&T::y, "y"), FProperty(&T::z, "z"), FProperty(&T::w, "w")); + } + static auto MakeFields() { + return std::array{ + MemberField(&T::x, "x", {}), + MemberField(&T::y, "y", {}), + MemberField(&T::z, "z", {}), + MemberField(&T::w, "w", {}), + }; + }; + }; +} \ No newline at end of file diff --git a/engine/modules/engine/core/include/archive/type.h b/engine/modules/engine/core/include/archive/type.h index 132144c..53912c4 100644 --- a/engine/modules/engine/core/include/archive/type.h +++ b/engine/modules/engine/core/include/archive/type.h @@ -1,6 +1,12 @@ #pragma once #include "meta/result.h" #include "refl/pch.h" +#define PARENT_KEY_NAME "__parent__" +#define CLASS_KEY_NAME "__class__" +#define DATA_KEY_NAME "__data__" +#define MAP_KEY_NAME "#k" +#define MAP_VALUE_NAME "#v" + namespace gen { template struct Meta {}; @@ -15,6 +21,9 @@ namespace gen { template concept is_serde_v = std::is_same_v || std::is_integral_v || std::is_floating_point_v || is_string_v || std::is_enum_v || is_string_view_v; + + template + concept is_any_v = std::is_base_of_v; } namespace api { using meta::result; diff --git a/engine/modules/engine/core/include/archive/yaml.h b/engine/modules/engine/core/include/archive/yaml.h index c55c568..1ad6732 100644 --- a/engine/modules/engine/core/include/archive/yaml.h +++ b/engine/modules/engine/core/include/archive/yaml.h @@ -1,15 +1,15 @@ #include "yaml/serde.inl" #include "yaml/serialize.inl" namespace gen { - template<> - inline bool YamlRead(const YAML::Node& node, const refl::Any& t) { - if (!node) return false; - return api::YamlArchive::Deserialize(node, refl::Any{ &t, refl::meta_info() }); - } - template<> - inline YAML::Node YamlWrite(const refl::Any& t) { - return api::YamlArchive::Serialize(refl::Any{&t, refl::meta_info()}); - } + template + struct YamlSerde { + inline static bool Read(const YAML::Node& node, const void* ptr) { + return api::YamlArchive::Deserialize(node, refl::Any{ ptr, refl::meta_info() }); + } + inline static YAML::Node Write(const void* ptr) { + return api::YamlArchive::Serialize(refl::Any{ ptr, refl::meta_info() }); + } + }; } namespace YAML { inline Node APILoad(std::string_view text) { diff --git a/engine/modules/engine/core/include/archive/yaml/serde.inl b/engine/modules/engine/core/include/archive/yaml/serde.inl index 299d533..cba7aa9 100644 --- a/engine/modules/engine/core/include/archive/yaml/serde.inl +++ b/engine/modules/engine/core/include/archive/yaml/serde.inl @@ -13,6 +13,10 @@ namespace gen { struct YamlSerde>> { inline static bool Read(const YAML::Node& node, const void* ptr) { T& v = *(T*)ptr; + if constexpr (refl::has_parent_v) { + using P = refl::parent_t; + YamlRead>(node[PARENT_KEY_NAME], *(P*)ptr); + } for_each_field([&](std::string_view name, auto&& value) { YamlRead(node[name], value); }, v); @@ -21,6 +25,10 @@ namespace gen { inline static YAML::Node Write(const void* ptr) { T& v = *(T*)ptr; YAML::Node node; + if constexpr (refl::has_parent_v) { + using P = refl::parent_t; + node[PARENT_KEY_NAME] = YamlWrite

(*(P*)ptr); + } for_each_field([&](std::string_view name, auto&& value) { node[name] = YamlWrite(value); }, v); @@ -35,8 +43,8 @@ namespace gen { value_type_t it;//构造失败怎么办? for (auto node_i : node) { if constexpr (refl::is_map_v) { - YamlRead(node_i["#k"], it.first); - YamlRead(node_i["#v"], it.second); + YamlRead(node_i[MAP_KEY_NAME], it.first); + YamlRead(node_i[MAP_VALUE_NAME], it.second); docker[it.first] = it.second; } else { @@ -52,8 +60,8 @@ namespace gen { if constexpr (refl::is_map_v) { for (auto& it : docker) { YAML::Node node_i; - node_i["#k"] = YamlWrite(it.first); - node_i["#v"] = YamlWrite(it.second); + node_i[MAP_KEY_NAME] = YamlWrite(it.first); + node_i[MAP_VALUE_NAME] = YamlWrite(it.second); node.push_back(node_i); } } diff --git a/engine/modules/engine/core/include/archive/yaml/serialize.inl b/engine/modules/engine/core/include/archive/yaml/serialize.inl index 88ef307..40a96d8 100644 --- a/engine/modules/engine/core/include/archive/yaml/serialize.inl +++ b/engine/modules/engine/core/include/archive/yaml/serialize.inl @@ -36,11 +36,11 @@ namespace api { return Serialize(any.Parent()); } YAML::Node result; - if (any.cls == meta_info()) { + if (any.Check(meta_info())) { Any obj = any.CastTo(); if (obj) { - result["__class__"] = obj.cls->name.ToStringView(); - result["__data__"] = Serialize(obj); + result[CLASS_KEY_NAME] = obj.cls->name.ToStringView(); + result[DATA_KEY_NAME] = Serialize(obj); } return result; } @@ -68,7 +68,7 @@ namespace api { return result; } if (Any p = any.Parent()) { - result["__parent__"] = Serialize(p); + result[PARENT_KEY_NAME] = Serialize(p); } auto fieldList = any.cls->GetFields(refl::FIND_ALL_MEMBER, Name("")); for (auto& field : fieldList) { @@ -89,8 +89,8 @@ namespace api { if (any.IsEnum()) { return Deserialize(res, any.Parent()); } - if (any.cls == meta_info() && res) { - auto __class = res["__class__"]; + if (any.Check(meta_info()) && res) { + auto __class = res[CLASS_KEY_NAME]; if (!__class) { return false; } @@ -99,7 +99,7 @@ namespace api { if (cls) { Any obj = cls->New(FramePool()); *any.CastTo() = obj; - return Deserialize(res["__data__"], obj); + return Deserialize(res[DATA_KEY_NAME], obj); } *any.CastTo() = {}; return false; diff --git a/engine/modules/engine/core/include/os/file_system.h b/engine/modules/engine/core/include/os/file_system.h index a25dac0..54ba337 100644 --- a/engine/modules/engine/core/include/os/file_system.h +++ b/engine/modules/engine/core/include/os/file_system.h @@ -2,4 +2,5 @@ namespace fs { std::string GetExecutablePath(); std::string GetWorkPath(); + void EnsurePathExists(std::string_view path); } \ No newline at end of file diff --git a/engine/modules/engine/core/src/module/module.cpp b/engine/modules/engine/core/src/module/module.cpp index e983582..4fdcf24 100644 --- a/engine/modules/engine/core/src/module/module.cpp +++ b/engine/modules/engine/core/src/module/module.cpp @@ -1,10 +1,14 @@ #include "module/module_manager.h" #include "os/file_manager.h" #include "archive/pch.h" +#include "archive/reflect.h" namespace api { void CoreModule::OnLoad(int argc, char** argv) { TextArchive::InitSerde(); + TextArchive::Register(); + TextArchive::Register(); + TextArchive::Register(); } void CoreModule::OnUnload() { diff --git a/engine/modules/engine/core/src/os/file_handle.cpp b/engine/modules/engine/core/src/os/file_handle.cpp index 574651b..d0565d8 100644 --- a/engine/modules/engine/core/src/os/file_handle.cpp +++ b/engine/modules/engine/core/src/os/file_handle.cpp @@ -1,4 +1,5 @@ #include "os/file_handle.h" +#include "os/file_system.h" #include #define READ_DATA_SIZE 100 #define TOKEN_SIZE 100 @@ -24,6 +25,7 @@ namespace api { break; } case api::FILE_OP::WRITE: + fs::EnsurePathExists(file_path); vfile = std::ofstream(file_path.c_str(), is_binarry ? std::ios::binary : 0); break; case api::FILE_OP::APPEND: diff --git a/engine/modules/engine/core/src/os/file_system.cpp b/engine/modules/engine/core/src/os/file_system.cpp index 6b811be..efbeb7e 100644 --- a/engine/modules/engine/core/src/os/file_system.cpp +++ b/engine/modules/engine/core/src/os/file_system.cpp @@ -44,4 +44,15 @@ namespace fs { return path.string(); } + void EnsurePathExists(std::string_view path) + { + size_t pos = path.find_last_of("\\/"); + if (std::string::npos != pos){ + std::string_view dir = path.substr(0, pos); + if (!std::filesystem::exists(dir)) { + std::filesystem::create_directories(dir); // Ŀ¼ڣ򴴽 + } + } + } + } \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/pmr/name.h b/engine/modules/engine/zlib/include/pmr/name.h index 85fb623..2812982 100644 --- a/engine/modules/engine/zlib/include/pmr/name.h +++ b/engine/modules/engine/zlib/include/pmr/name.h @@ -209,6 +209,7 @@ namespace pmr { const StringEntry* stringEntry = UNIQUER_VAL(stringEntryMemoryManager).GetStringEntry(StringEntryHandle(flag3_memory29)); return std::string(stringEntry->GetData(), stringEntry->GetSize()); } + static Name Find(std::string_view view); }; class Tag { diff --git a/engine/modules/engine/zlib/include/pmr/name.inl b/engine/modules/engine/zlib/include/pmr/name.inl index 873b751..97eddf5 100644 --- a/engine/modules/engine/zlib/include/pmr/name.inl +++ b/engine/modules/engine/zlib/include/pmr/name.inl @@ -152,4 +152,23 @@ namespace pmr { } return slotValue; } + inline Name Name::Find(std::string_view view) { + Name result{}; + if (!view.empty()) { + HashInfo hashInfo(view); + auto& stringEntryMemoryManager = UNIQUER_VAL(stringEntryMemoryManager); + auto& slotPool = stringEntryMemoryManager.slotPoolArray[hashInfo.GetSlotPoolIndex()]; + uint32_t slotValue = 0u; + { + std::unique_lock lock(slotPool.mutex); + Name::Slot& slot = slotPool.FindUnusedOrTargetSlot(hashInfo); + if (slot.IsUsed()) + { + result.flag3_memory29 = slot.GetSlotValue(); + return result; + } + } + } + return result; + } } \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/refl/detail/any.h b/engine/modules/engine/zlib/include/refl/detail/any.h index 1d8faf7..d00bb42 100644 --- a/engine/modules/engine/zlib/include/refl/detail/any.h +++ b/engine/modules/engine/zlib/include/refl/detail/any.h @@ -15,7 +15,7 @@ namespace refl { constexpr Any() noexcept: ptr(nullptr), cls(nullptr) {} constexpr Any(const void* ptr, const UClass* cls) noexcept : ptr(ptr), cls(cls) {} template - constexpr Any(T&& v) noexcept : ptr(&v), cls(meta_info()) {} + constexpr Any(T&& v) noexcept : ptr(&v), cls(meta_info>()) {} template constexpr Any(T* v) noexcept : ptr(v), cls(meta_info()) {} template//参数 T* => T* @@ -63,4 +63,16 @@ namespace refl { Destruct(); } }; + template + class TAny : public Any{ + public: + TAny() : Any(){} + TAny(T* t) : Any(t){} + T* operator->() { + return (T*)ptr; + } + }; + template struct Meta> { + using Parent = Any; + }; } \ No newline at end of file diff --git a/engine/modules/engine/zlib/include/refl/detail/container.inl b/engine/modules/engine/zlib/include/refl/detail/container.inl index a26b627..f717799 100644 --- a/engine/modules/engine/zlib/include/refl/detail/container.inl +++ b/engine/modules/engine/zlib/include/refl/detail/container.inl @@ -15,7 +15,7 @@ namespace refl { Any malloc(pmr::memory_resource* alloc)const { void* it = alloc->allocate(cls->parent->size); cls->Construct(it); - return Any{ it, cls }; + return Any{ it, cls->parent }; } span GetFields() { return cls->parent->GetFields(EFieldFind::FIND_ALL_MEMBER, Name("")); diff --git a/engine/modules/engine/zlib/include/refl/detail/uclass.inl b/engine/modules/engine/zlib/include/refl/detail/uclass.inl index 427e0f5..614def9 100644 --- a/engine/modules/engine/zlib/include/refl/detail/uclass.inl +++ b/engine/modules/engine/zlib/include/refl/detail/uclass.inl @@ -26,6 +26,10 @@ namespace refl { flag = CLASS_ENUM_FLAG; parent = meta_info>(); } + else if constexpr (has_parent_v) { + flag |= CLASS_PARENT_FLAG; + parent = meta_info>(); + } vtable.AddConstruct(&UClass::Construct); vtable.AddDestruct(&UClass::Destruct); } @@ -170,6 +174,7 @@ namespace refl { FieldsType Fields{ MetaImpl::MakeFields() }; UClass_Meta() : UClass(meta_name(), sizeof(T)) { if constexpr (has_parent_v) { + flag |= CLASS_PARENT_FLAG; parent = meta_info>(); } vtable.AddGetFields(&UClass_Meta::GetFields); diff --git a/engine/modules/render/vulkan/src/vulkan_ui_system.cpp b/engine/modules/render/vulkan/src/vulkan_ui_system.cpp index 42da507..fa1099b 100644 --- a/engine/modules/render/vulkan/src/vulkan_ui_system.cpp +++ b/engine/modules/render/vulkan/src/vulkan_ui_system.cpp @@ -16,8 +16,8 @@ namespace vkn { void vkn::VulkanUISystem::OnBeginRenderFrame(FrameGraph& graph, uint32_t frame) { #ifdef WITH_EDITOR - graph.mIsRenderEditorSurface = gEngineConfig.IsRenderEditorSurface; - if (gEngineConfig.IsRenderEditorSurface) { + graph.mIsRenderEditorSurface = gEditorConfig.IsRenderEditorSurface; + if (gEditorConfig.IsRenderEditorSurface) { graph.mEditorSurfaceID = graph.mSurfaceID; graph.mSurfaceID = graph.GetTextureID(FrameGraph::NameEditorSurface, frame); } @@ -38,7 +38,7 @@ namespace vkn { .Type(RenderPassNodeType::Imgui, RenderPassNodeFlag::Output) .Write(graph.GetRenderSurface(), ResourceState::COLOR_ATTACHMENT) .Write(stencil, ResourceState::DEPTH_ATTACHMENT); - if (gEngineConfig.IsRenderEditorSurface) { + if (gEditorConfig.IsRenderEditorSurface) { builder.Read(graph.GetSurface(), ResourceState::READ_ONLY); } } diff --git a/engine/src/editor/window/editor_main_window.cpp b/engine/src/editor/window/editor_main_window.cpp index c895920..4fddbad 100644 --- a/engine/src/editor/window/editor_main_window.cpp +++ b/engine/src/editor/window/editor_main_window.cpp @@ -75,7 +75,7 @@ namespace api { ImGui::Begin("MainWindow", NULL, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar); ImGui::Text("This is some useful text."); ImGui::SliderFloat("float", &my_float, 0.0f, 1.0f); - if (gEngineConfig.IsRenderEditorSurface) { + if (gEditorConfig.IsRenderEditorSurface) { TextureDesc surface = graph.GetSurface(); if (!TextureIDList[ctx.frame]) { TextureIDList[ctx.frame] = ctx->AddTexture(graph, surface, sampler); @@ -84,7 +84,7 @@ namespace api { ImGui::Image(TextureIDList[ctx.frame], ImVec2(surface.width, surface.height)); } else { - gEngineConfig.IsRenderEditorSurface = true; + gEditorConfig.IsRenderEditorSurface = true; InitRenderSurface(graph, ctx.frameCount); } ImGui::End(); diff --git a/engine/src/engine/app.cpp b/engine/src/engine/app.cpp new file mode 100644 index 0000000..b63afcf --- /dev/null +++ b/engine/src/engine/app.cpp @@ -0,0 +1,54 @@ +#include "engine/app.h" +#include "scene/scene_system.h" +#include "os/file_manager.h" + +#include "scene/scene.h" +#include "scene/level_blueprint.h" +#include "object/component/transform.h" +#include "os/file_handle.h" +#include "archive/pch.h" +namespace api{ + void CreateDemoScene() { + LevelInfo levelInfo{ "main", "/scene/entry/main.level", Vector3(0, 255, 0) }; + SceneInfo sceneInfo{}; + sceneInfo.mName = "entry"; + sceneInfo.mPath = "/scene/entry.scene"; + sceneInfo.mLevelBlueprint = TAny(new LevelBlueprint()); + sceneInfo.mLevelInfos.push_back(levelInfo); + + Level level{ levelInfo }; + GameObject* obj1 = new GameObject(); + level.AddObject(obj1); + { + FileHandle handle(levelInfo.mPath); + handle.Open(FILE_OP::WRITE); + handle.Write(TextSerialize(level)); + } + Scene scene{ sceneInfo }; + scene.AddLevel(&level); + { + FileHandle handle(sceneInfo.mPath); + handle.Open(FILE_OP::WRITE); + handle.Write(TextSerialize(scene)); + } + } + bool App::Launch() + { + PackagePath scenePath{ "/engine/assets/scene" }; + FileManager::Ptr()->Mount("scene", scenePath.RealPath().c_str()); + CreateDemoScene(); + gProjectConfig.EntryScene = "/scene/entry.scene"; + SceneSystem::Ptr()->LoadScene(gProjectConfig.EntryScene); + return true; + } + void App::Update() + { +#ifdef WITH_EDITOR + gEditorConfig.IsGameStart = true; + if(gEditorConfig.IsGameStart && !gEditorConfig.isGamePause) + SceneSystem::Ptr()->Update(); +#else + SceneSystem::Ptr()->Update(); +#endif // WITH_EDITOR + } +} \ No newline at end of file diff --git a/engine/src/engine/plugin.cpp b/engine/src/engine/plugin.cpp index d65dbae..ba1f02f 100644 --- a/engine/src/engine/plugin.cpp +++ b/engine/src/engine/plugin.cpp @@ -29,8 +29,10 @@ IMPLEMENT_STATIC_MODULE(RENDER_API, api::RenderModule, render); #ifndef APP_API_VAL #define APP_API_VAL 1 +#include "app_module.h" #include "app_impl.inl" #include "event_system_impl.inl" +#include "scene_system_impl.inl" IMPLEMENT_STATIC_MODULE(APP_API, api::AppModule, app) #endif // !APP_API_VAL diff --git a/engine/xmake/rule_api/package_api.lua b/engine/xmake/rule_api/package_api.lua index ef7ea56..f91d8cf 100644 --- a/engine/xmake/rule_api/package_api.lua +++ b/engine/xmake/rule_api/package_api.lua @@ -5,6 +5,9 @@ function main(target) local link = pkg:get("links") local targetdir = target:targetdir() link = link[1] or link + if is_mode("debug") and not os.isdir(targetdir) then + os.mkdir(targetdir) + end if link and os.isdir(targetdir) and not os.isfile(path.join(targetdir, link .. ".lib")) then local linkdirs = pkg:get("linkdirs") os.trycp(linkdirs.."/*", targetdir) diff --git a/game/zworld/src/zworld.cpp b/game/zworld/src/zworld.cpp index 520d154..d56ecde 100644 --- a/game/zworld/src/zworld.cpp +++ b/game/zworld/src/zworld.cpp @@ -1,10 +1,10 @@ #include "zlog.h" #include "zworld.h" -#include "data/global.h" #include "event/event_system.h" #include "vkn/vulkan_window.h" #include "vkn/vulkan_api.h" #include "render/pass/demo_pass.h" +#include "engine/app.h" #ifdef WITH_EDITOR #include "imgui/imgui_impl_sdl2.h" #endif @@ -48,8 +48,9 @@ void ZWorldModule::OnUnload() void ZWorldModule::MainLoop() { - bool running = true; SDL_Event event_; + App app; + bool running = app.Launch(); while (running) { // 处理事件 while (SDL_PollEvent(&event_)) { @@ -59,7 +60,8 @@ void ZWorldModule::MainLoop() if (event_.type == SDL_QUIT) { running = false; } - } + } + app.Update(); API->BeginFrame(); API->Render(); API->EndFrame();