support scene serialize
This commit is contained in:
parent
cb1c7ad1e5
commit
3d404294ab
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -4,6 +4,7 @@
|
||||
"bitmap.c": "cpp",
|
||||
"heap.c": "cpp",
|
||||
"init.c": "cpp",
|
||||
"random.c": "cpp"
|
||||
"random.c": "cpp",
|
||||
"type_traits": "cpp"
|
||||
}
|
||||
}
|
||||
@ -1,13 +1,16 @@
|
||||

|
||||
# 个人游戏引擎
|
||||
|
||||
原始项目: 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 开发完整的编辑器工具。
|
||||
|
||||
|
||||
BIN
engine/assets/logo.png
Normal file
BIN
engine/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
12
engine/assets/scene/entry.scene
Normal file
12
engine/assets/scene/entry.scene
Normal file
@ -0,0 +1,12 @@
|
||||
__parent__:
|
||||
mName: entry
|
||||
mLevelBlueprint:
|
||||
__class__: api::LevelBlueprint
|
||||
__data__: ~
|
||||
mLevelInfos:
|
||||
- mName: main
|
||||
mPath: /scene/entry/main.level
|
||||
mOffset:
|
||||
x: 0
|
||||
y: 255
|
||||
z: 0
|
||||
13
engine/assets/scene/entry/main.level
Normal file
13
engine/assets/scene/entry/main.level
Normal file
@ -0,0 +1,13 @@
|
||||
__parent__:
|
||||
mName: main
|
||||
mPath: /scene/entry/main.level
|
||||
mOffset:
|
||||
x: 0
|
||||
y: 255
|
||||
z: 0
|
||||
mObjects:
|
||||
- __class__: api::GameObject
|
||||
__data__:
|
||||
mName: ""
|
||||
mChildrens: ~
|
||||
mComponents: ~
|
||||
12
engine/include/engine/app.h
Normal file
12
engine/include/engine/app.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "data/global.h"
|
||||
namespace api{
|
||||
class ENGINE_API App {
|
||||
public:
|
||||
void* operator new(size_t size) {
|
||||
return ::operator new(size, GlobalPool());
|
||||
}
|
||||
virtual bool Launch();
|
||||
virtual void Update();
|
||||
};
|
||||
}
|
||||
@ -1,5 +1,8 @@
|
||||
#include "app.h"
|
||||
#include "data/global.h"
|
||||
namespace api {
|
||||
APP_API EngineConfig gEngineConfig{};
|
||||
APP_API EngineConfig gEngineConfig{};
|
||||
APP_API ProjectConfig gProjectConfig{};
|
||||
#ifdef WITH_EDITOR
|
||||
APP_API EditorConfig gEditorConfig{};
|
||||
#endif
|
||||
}
|
||||
163
engine/modules/engine/app/impl/scene_system_impl.inl
Normal file
163
engine/modules/engine/app/impl/scene_system_impl.inl
Normal file
@ -0,0 +1,163 @@
|
||||
#include "scene/scene_system.h"
|
||||
#include "scene/scene.h"
|
||||
namespace api {
|
||||
class SceneSystemImpl
|
||||
{
|
||||
public:
|
||||
Scene* curScene = nullptr;
|
||||
table<Name, Scene*> scenes;
|
||||
table<Name, Name> 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<pmr::string>();
|
||||
pScene = new Scene();
|
||||
if (!TextDeserialize<Scene>(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);
|
||||
}
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
namespace api {
|
||||
template<typename T>
|
||||
class AppImpl {
|
||||
void Setup() {
|
||||
static_cast<T*>(this)->Setup();
|
||||
}
|
||||
void CleanUp() {
|
||||
static_cast<T*>(this)->CleanUp();
|
||||
}
|
||||
void ImGui() {
|
||||
static_cast<T*>(this)->ImGui();
|
||||
}
|
||||
void PreRender() {
|
||||
static_cast<T*>(this)->PreRender();
|
||||
}
|
||||
void PostRender() {
|
||||
static_cast<T*>(this)->PostRender();
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
inline void App::Run(EngineConfig config, AppImpl<T>& impl)
|
||||
{
|
||||
impl.Setup();
|
||||
}
|
||||
}
|
||||
@ -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<typename T>
|
||||
class AppImpl;
|
||||
class App {
|
||||
public:
|
||||
template<typename T>
|
||||
void Run(EngineConfig config, AppImpl<T>& impl);
|
||||
};
|
||||
}
|
||||
#include "app.inl"
|
||||
}
|
||||
9
engine/modules/engine/app/include/data/editor_config.h
Normal file
9
engine/modules/engine/app/include/data/editor_config.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include "render/type.h"
|
||||
namespace api{
|
||||
struct EditorConfig {
|
||||
bool IsRenderEditorSurface = false;
|
||||
bool IsGameStart = false;
|
||||
bool isGamePause = false;
|
||||
};
|
||||
}
|
||||
@ -3,9 +3,5 @@
|
||||
namespace api{
|
||||
struct EngineConfig {
|
||||
GraphicsAPI API = GraphicsAPI::Vulkan;
|
||||
#ifdef WITH_EDITOR
|
||||
bool IsRenderEditorSurface = false;
|
||||
#endif // WITH_EDITOR
|
||||
|
||||
};
|
||||
}
|
||||
@ -8,4 +8,11 @@ namespace api {
|
||||
constexpr const char* CFileMountName = "/work/assets/file_mount.meta";
|
||||
|
||||
extern APP_API EngineConfig gEngineConfig;
|
||||
}
|
||||
extern APP_API ProjectConfig gProjectConfig;
|
||||
}
|
||||
#ifdef WITH_EDITOR
|
||||
#include "editor_config.h"
|
||||
namespace api{
|
||||
extern APP_API EditorConfig gEditorConfig;
|
||||
}
|
||||
#endif
|
||||
@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
#include "pmr/name.h"
|
||||
namespace api{
|
||||
using pmr::Name;
|
||||
struct ProjectConfig {
|
||||
Name EntryScene;
|
||||
};
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "object/game_object.h"
|
||||
namespace api {
|
||||
class Transform : public Component {
|
||||
|
||||
};
|
||||
}
|
||||
31
engine/modules/engine/app/include/object/game_object.h
Normal file
31
engine/modules/engine/app/include/object/game_object.h
Normal file
@ -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<TAny<GameObject>> mChildrens;
|
||||
UPROPERTY()
|
||||
vector<TAny<Component>> mComponents;
|
||||
public:
|
||||
|
||||
};
|
||||
class Component {
|
||||
private:
|
||||
GENERATED_BODY()
|
||||
UPROPERTY()
|
||||
Name mName;
|
||||
GameObject* mOwner;
|
||||
|
||||
public:
|
||||
|
||||
};
|
||||
}
|
||||
#include ".app/game_object_gen.inl"
|
||||
26
engine/modules/engine/app/include/scene/level.h
Normal file
26
engine/modules/engine/app/include/scene/level.h
Normal file
@ -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<TAny<GameObject>> mObjects;
|
||||
public:
|
||||
Level(const LevelInfo& info) : LevelInfo(info) {};
|
||||
Level();
|
||||
~Level();
|
||||
void AddObject(TAny<GameObject> object);
|
||||
};
|
||||
}
|
||||
#include ".app/level_gen.inl"
|
||||
11
engine/modules/engine/app/include/scene/level_blueprint.h
Normal file
11
engine/modules/engine/app/include/scene/level_blueprint.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "object/game_object.h"
|
||||
namespace api {
|
||||
class Scene;
|
||||
class LevelBlueprint {
|
||||
public:
|
||||
LevelBlueprint();
|
||||
~LevelBlueprint();
|
||||
void LoadScene(Scene* scene);
|
||||
};
|
||||
}
|
||||
31
engine/modules/engine/app/include/scene/scene.h
Normal file
31
engine/modules/engine/app/include/scene/scene.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "level.h"
|
||||
namespace api {
|
||||
class LevelBlueprint;
|
||||
struct SceneInfo {
|
||||
UPROPERTY()
|
||||
Name mName;
|
||||
Name mPath;
|
||||
UPROPERTY()
|
||||
TAny<LevelBlueprint> mLevelBlueprint;
|
||||
UPROPERTY()
|
||||
vector<LevelInfo> mLevelInfos;
|
||||
};
|
||||
class Scene : public SceneInfo{
|
||||
protected:
|
||||
GENERATED_BODY()
|
||||
|
||||
vector<Level*> mLevels;
|
||||
vector<GameObject*> 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"
|
||||
25
engine/modules/engine/app/include/scene/scene_system.h
Normal file
25
engine/modules/engine/app/include/scene/scene_system.h
Normal file
@ -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);
|
||||
};
|
||||
}
|
||||
@ -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<EventSystem>();
|
||||
AddSystem<SceneSystem>();
|
||||
}
|
||||
void AppModule::OnUnload()
|
||||
{
|
||||
16
engine/modules/engine/app/src/scene/level.cpp
Normal file
16
engine/modules/engine/app/src/scene/level.cpp
Normal file
@ -0,0 +1,16 @@
|
||||
#include "scene/level.h"
|
||||
|
||||
namespace api {
|
||||
Level::Level()
|
||||
{
|
||||
|
||||
}
|
||||
Level::~Level()
|
||||
{
|
||||
|
||||
}
|
||||
void Level::AddObject(TAny<GameObject> object)
|
||||
{
|
||||
mObjects.push_back(object);
|
||||
}
|
||||
}
|
||||
28
engine/modules/engine/app/src/scene/level_blueprint.cpp
Normal file
28
engine/modules/engine/app/src/scene/level_blueprint.cpp
Normal file
@ -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<pmr::string>();
|
||||
if (!TextDeserialize<Level>(text, pLevel)) {
|
||||
delete pLevel;
|
||||
continue;
|
||||
}
|
||||
scene->AddLevel(pLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
engine/modules/engine/app/src/scene/scene.cpp
Normal file
31
engine/modules/engine/app/src/scene/scene.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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")
|
||||
@ -7,15 +7,15 @@
|
||||
#define JSON_WRITE_FLAGS YYJSON_WRITE_NOFLAG
|
||||
#endif
|
||||
namespace gen {
|
||||
template<>
|
||||
inline bool JsonRead<refl::Any>(yyjson_val* node, const refl::Any& t) {
|
||||
if (!node) return false;
|
||||
return api::JsonArchive::Deserialize(node, t);
|
||||
}
|
||||
template<>
|
||||
inline yyjson_mut_val* JsonWrite<refl::Any>(yyjson_mut_doc* doc, const refl::Any& t) {
|
||||
return api::JsonArchive::Serialize(doc, t);
|
||||
}
|
||||
template<is_any_v T>
|
||||
struct JsonSerde<T> {
|
||||
inline static bool Read(yyjson_val* val, const void* ptr) {
|
||||
return api::JsonArchive::Deserialize(val, refl::Any{ ptr, refl::meta_info<refl::Any>() });
|
||||
}
|
||||
inline static yyjson_mut_val* Write(yyjson_mut_doc* doc, const void* ptr) {
|
||||
return api::JsonArchive::Serialize(doc, refl::Any{ ptr, refl::meta_info<refl::Any>() });
|
||||
}
|
||||
};
|
||||
}
|
||||
namespace api {
|
||||
namespace detail {
|
||||
|
||||
@ -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<T>) {
|
||||
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<T>) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
77
engine/modules/engine/core/include/archive/reflect.h
Normal file
77
engine/modules/engine/core/include/archive/reflect.h
Normal file
@ -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<api::Vector2> {
|
||||
using T = api::Vector2;
|
||||
using Impl = gen::MetaImpl<T, string_hash("Meta")>;
|
||||
};
|
||||
}
|
||||
namespace refl {
|
||||
template<> struct Meta<api::Vector3> {
|
||||
using T = api::Vector3;
|
||||
using Impl = gen::MetaImpl<T, string_hash("Meta")>;
|
||||
};
|
||||
}
|
||||
namespace refl {
|
||||
template<> struct Meta<api::Vector4> {
|
||||
using T = api::Vector4;
|
||||
using Impl = gen::MetaImpl<T, string_hash("Meta")>;
|
||||
};
|
||||
}
|
||||
namespace gen {
|
||||
template<> struct MetaImpl<api::Vector2, string_hash("Meta")> : 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<api::Vector3, string_hash("Meta")> : 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<api::Vector4, string_hash("Meta")> : 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", {}),
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@ -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<typename T>
|
||||
struct Meta {};
|
||||
@ -15,6 +21,9 @@ namespace gen {
|
||||
template<typename T>
|
||||
concept is_serde_v = std::is_same_v<T, bool> || std::is_integral_v<T> || std::is_floating_point_v<T> || is_string_v<T> || std::is_enum_v<T>
|
||||
|| is_string_view_v<T>;
|
||||
|
||||
template<typename T>
|
||||
concept is_any_v = std::is_base_of_v<refl::Any, T>;
|
||||
}
|
||||
namespace api {
|
||||
using meta::result;
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
#include "yaml/serde.inl"
|
||||
#include "yaml/serialize.inl"
|
||||
namespace gen {
|
||||
template<>
|
||||
inline bool YamlRead<refl::Any>(const YAML::Node& node, const refl::Any& t) {
|
||||
if (!node) return false;
|
||||
return api::YamlArchive::Deserialize(node, refl::Any{ &t, refl::meta_info<refl::Any>() });
|
||||
}
|
||||
template<>
|
||||
inline YAML::Node YamlWrite<refl::Any>(const refl::Any& t) {
|
||||
return api::YamlArchive::Serialize(refl::Any{&t, refl::meta_info<refl::Any>()});
|
||||
}
|
||||
template<is_any_v T>
|
||||
struct YamlSerde<T> {
|
||||
inline static bool Read(const YAML::Node& node, const void* ptr) {
|
||||
return api::YamlArchive::Deserialize(node, refl::Any{ ptr, refl::meta_info<refl::Any>() });
|
||||
}
|
||||
inline static YAML::Node Write(const void* ptr) {
|
||||
return api::YamlArchive::Serialize(refl::Any{ ptr, refl::meta_info<refl::Any>() });
|
||||
}
|
||||
};
|
||||
}
|
||||
namespace YAML {
|
||||
inline Node APILoad(std::string_view text) {
|
||||
|
||||
@ -13,6 +13,10 @@ namespace gen {
|
||||
struct YamlSerde<T, std::enable_if_t<refl::is_meta_v<T>>> {
|
||||
inline static bool Read(const YAML::Node& node, const void* ptr) {
|
||||
T& v = *(T*)ptr;
|
||||
if constexpr (refl::has_parent_v<T>) {
|
||||
using P = refl::parent_t<T>;
|
||||
YamlRead<refl::parent_t<T>>(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<T>) {
|
||||
using P = refl::parent_t<T>;
|
||||
node[PARENT_KEY_NAME] = YamlWrite<P>(*(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<T>) {
|
||||
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<T>) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,11 +36,11 @@ namespace api {
|
||||
return Serialize(any.Parent());
|
||||
}
|
||||
YAML::Node result;
|
||||
if (any.cls == meta_info<Any>()) {
|
||||
if (any.Check(meta_info<Any>())) {
|
||||
Any obj = any.CastTo<Any>();
|
||||
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<Any>() && res) {
|
||||
auto __class = res["__class__"];
|
||||
if (any.Check(meta_info<Any>()) && 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<Any*>() = obj;
|
||||
return Deserialize(res["__data__"], obj);
|
||||
return Deserialize(res[DATA_KEY_NAME], obj);
|
||||
}
|
||||
*any.CastTo<Any*>() = {};
|
||||
return false;
|
||||
|
||||
@ -2,4 +2,5 @@
|
||||
namespace fs {
|
||||
std::string GetExecutablePath();
|
||||
std::string GetWorkPath();
|
||||
void EnsurePathExists(std::string_view path);
|
||||
}
|
||||
@ -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<Vector2>();
|
||||
TextArchive::Register<Vector3>();
|
||||
TextArchive::Register<Vector4>();
|
||||
}
|
||||
void CoreModule::OnUnload()
|
||||
{
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
#include "os/file_handle.h"
|
||||
#include "os/file_system.h"
|
||||
#include <algorithm>
|
||||
#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:
|
||||
|
||||
@ -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); // 如果目录不存在,则创建它
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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 {
|
||||
|
||||
@ -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<std::mutex> lock(slotPool.mutex);
|
||||
Name::Slot& slot = slotPool.FindUnusedOrTargetSlot(hashInfo);
|
||||
if (slot.IsUsed())
|
||||
{
|
||||
result.flag3_memory29 = slot.GetSlotValue();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -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<is_not_any_v T>
|
||||
constexpr Any(T&& v) noexcept : ptr(&v), cls(meta_info<T>()) {}
|
||||
constexpr Any(T&& v) noexcept : ptr(&v), cls(meta_info<std::remove_reference_t<T>>()) {}
|
||||
template<is_not_any_v T>
|
||||
constexpr Any(T* v) noexcept : ptr(v), cls(meta_info<T>()) {}
|
||||
template<typename T>//参数 T* => T*
|
||||
@ -63,4 +63,16 @@ namespace refl {
|
||||
Destruct();
|
||||
}
|
||||
};
|
||||
template<typename T>
|
||||
class TAny : public Any{
|
||||
public:
|
||||
TAny() : Any(){}
|
||||
TAny(T* t) : Any(t){}
|
||||
T* operator->() {
|
||||
return (T*)ptr;
|
||||
}
|
||||
};
|
||||
template<typename T> struct Meta<TAny<T>> {
|
||||
using Parent = Any;
|
||||
};
|
||||
}
|
||||
@ -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<const FieldPtr> GetFields() {
|
||||
return cls->parent->GetFields(EFieldFind::FIND_ALL_MEMBER, Name(""));
|
||||
|
||||
@ -26,6 +26,10 @@ namespace refl {
|
||||
flag = CLASS_ENUM_FLAG;
|
||||
parent = meta_info<std::underlying_type_t<T>>();
|
||||
}
|
||||
else if constexpr (has_parent_v<T>) {
|
||||
flag |= CLASS_PARENT_FLAG;
|
||||
parent = meta_info<parent_t<T>>();
|
||||
}
|
||||
vtable.AddConstruct(&UClass::Construct<T>);
|
||||
vtable.AddDestruct(&UClass::Destruct<T>);
|
||||
}
|
||||
@ -170,6 +174,7 @@ namespace refl {
|
||||
FieldsType Fields{ MetaImpl::MakeFields() };
|
||||
UClass_Meta() : UClass(meta_name<T>(), sizeof(T)) {
|
||||
if constexpr (has_parent_v<T>) {
|
||||
flag |= CLASS_PARENT_FLAG;
|
||||
parent = meta_info<parent_t<T>>();
|
||||
}
|
||||
vtable.AddGetFields(&UClass_Meta::GetFields);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
54
engine/src/engine/app.cpp
Normal file
54
engine/src/engine/app.cpp
Normal file
@ -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<LevelBlueprint>(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
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user