From 64cdddea961b4f8619a7bb4c5d96795bcc72774a Mon Sep 17 00:00:00 2001 From: Martin Felis Date: Thu, 24 Apr 2025 19:01:24 +0200 Subject: [PATCH] Minor serialization refactoring. --- src/AnimGraph/AnimLibrary.h | 2 +- src/SkinnedMeshResource.cc | 55 +------ src/SkinnedMeshResource.h | 4 +- src/main.cc | 316 ++++++++++++------------------------ 4 files changed, 110 insertions(+), 267 deletions(-) diff --git a/src/AnimGraph/AnimLibrary.h b/src/AnimGraph/AnimLibrary.h index 71ad607..5693d3d 100644 --- a/src/AnimGraph/AnimLibrary.h +++ b/src/AnimGraph/AnimLibrary.h @@ -14,7 +14,7 @@ /** Manage a set of animations used for an AnimGraph. * - * By default it behaves like a resource that allows to resolve animation names to + * By default, it behaves like a resource that allows to resolve animation names to * AnimationResources. However, it can also trigger loading of the referenced resources from their * filenames. This only happens on-demand. */ diff --git a/src/SkinnedMeshResource.cc b/src/SkinnedMeshResource.cc index 05f2546..5706197 100644 --- a/src/SkinnedMeshResource.cc +++ b/src/SkinnedMeshResource.cc @@ -9,52 +9,11 @@ #include "3rdparty/json/json.hpp" -inline void to_json( - nlohmann::json& j, - const SkinnedMeshResource& skinnedMeshResource) { - j["type"] = "SkinnedMeshResource"; - j["skeleton"]["file"] = skinnedMeshResource.m_skeleton_file; - for (int i = 0; i < skinnedMeshResource.m_animation_files.size(); i++) { - j["animations"][i]["file"] = skinnedMeshResource.m_animation_files[i]; - j["animations"][i]["sync_track"] = skinnedMeshResource.m_sync_tracks[i]; - } -} - -inline void from_json( - const nlohmann::json& j, - SkinnedMeshResource& skinnedMeshResource) { - if (!j.contains("type") || j["type"] != "SkinnedMeshResource") { - std::cerr << "Unable to parse SkinnedMeshResource: wrong json type!" - << std::endl; - return; - } - - if (!j.contains("skeleton") || !j["skeleton"].contains("file")) { - std::cerr << "Unable to parse SkinnedMeshResource: no skeleton file found!" - << std::endl; - } - - skinnedMeshResource.m_skeleton_file = j["skeleton"]["file"]; - - if (j.contains("animations")) { - int num_animations = j["animations"].size(); - - for (int i = 0; i < num_animations; i++) { - if (!j["animations"][i].contains("file") - || !j["animations"][i].contains("sync_track")) { - std::cerr << "Unable to parse SkinnedMeshResource: invalid animation " - "definition" - << std::endl; - return; - } - - skinnedMeshResource.m_animation_files.push_back( - j["animations"][i]["file"]); - skinnedMeshResource.m_sync_tracks.push_back( - j["animations"][i]["sync_track"].get()); - } - } -} +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( + SkinnedMeshResource, + m_type, + m_resource_file, + m_skeleton_file); bool SkinnedMeshResource::saveToFile(const char* filename) const { nlohmann::json j = *this; @@ -87,8 +46,4 @@ bool SkinnedMeshResource::loadFromFile(const char* filename) { void SkinnedMeshResource::createInstance(SkinnedMesh& skinnedMesh) const { skinnedMesh.LoadSkeleton(m_skeleton_file.c_str()); - for (int i = 0; i < m_animation_files.size(); i++) { - skinnedMesh.LoadAnimation(m_animation_files[i].c_str()); - skinnedMesh.m_animation_sync_track.back() = m_sync_tracks[i]; - } } diff --git a/src/SkinnedMeshResource.h b/src/SkinnedMeshResource.h index f96cbfc..96547f2 100644 --- a/src/SkinnedMeshResource.h +++ b/src/SkinnedMeshResource.h @@ -12,10 +12,10 @@ #include "SkinnedMesh.h" struct SkinnedMeshResource { + constexpr static char TypeStr[] = "SkinnedMeshResource"; + std::string m_type = TypeStr; std::string m_resource_file; std::string m_skeleton_file; - std::vector m_animation_files; - std::vector m_sync_tracks; bool saveToFile(const char* filename) const; bool loadFromFile(const char* filename); diff --git a/src/main.cc b/src/main.cc index 0fba704..87a1892 100644 --- a/src/main.cc +++ b/src/main.cc @@ -254,7 +254,6 @@ static void draw_imgui(ImDrawData*); #include "ozz/animation/runtime/skeleton.h" #include "ozz/base/containers/vector.h" #include "ozz/base/io/archive.h" -#include "ozz/base/io/stream.h" #include "ozz/base/log.h" #include "ozz/base/maths/soa_transform.h" @@ -366,191 +365,80 @@ struct Viewport { }; struct ApplicationConfig { - int window_position[2] = {100, 30}; - int window_size[2] = {1000, 600}; + constexpr static char TypeStr[] = "ApplicationConfig"; + std::string type = TypeStr; + struct ScreenRect { + int position[2]; + int size[2]; + }; + NLOHMANN_DEFINE_TYPE_INTRUSIVE(ScreenRect, position, size); + ScreenRect window = {.position = {100, 30}, .size = {1000, 600}}; struct GraphEditor { + ScreenRect rect = {.position = {20, 20}, .size = {800, 500}}; bool visible = false; - int position[2] = {20, 20}; - int size[2] = {800, 500}; ax::NodeEditor::Config config = {}; ax::NodeEditor::EditorContext* context = nullptr; }; + NLOHMANN_DEFINE_TYPE_INTRUSIVE(GraphEditor, rect, visible); GraphEditor graph_editor; - struct SkinnedMeshWidget { + struct WidgetRect { + ScreenRect rect; bool visible = false; - int position[2] = {20, 20}; - int size[2] = {800, 500}; }; - SkinnedMeshWidget skinned_mesh_widget; + NLOHMANN_DEFINE_TYPE_INTRUSIVE(WidgetRect, rect, visible); + WidgetRect skinned_mesh_widget = { + .rect = {.position = {20, 20}, .size = {800, 500}}, + .visible = false}; - struct AnimationPlayerWidget { - bool visible = false; - int position[2] = {20, 20}; - int size[2] = {800, 500}; - }; - AnimationPlayerWidget animation_player_widget; + WidgetRect animation_player_widget = { + .rect = {.position = {20, 20}, .size = {800, 500}}, + .visible = false}; - struct ViewportWidget { - bool visible = true; - int position[2] = {20, 20}; - int size[2] = {800, 500}; - }; - ViewportWidget viewport_widget; + WidgetRect viewport_widget; bool show_imgui_demo_window = false; bool show_another_window = false; bool show_camera_widget = false; }; -void to_json(nlohmann::json& j, const ApplicationConfig& config) { - j["type"] = "AnimTestbedConfig"; +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( + ApplicationConfig, + type, + window, + graph_editor, + skinned_mesh_widget, + animation_player_widget, + viewport_widget, + show_imgui_demo_window, + show_another_window, + show_camera_widget); - j["main_window"]["position"][0] = config.window_position[0]; - j["main_window"]["position"][1] = config.window_position[1]; +struct ProjectConfig { + static constexpr char TypeStr[] = "ProjectConfig"; + std::string type = TypeStr; + std::string animation_library_file = ""; + std::string skeleton_file = ""; + std::string graph_resource_file = ""; + struct ViewConfig { + int pos[2]; + }; + ViewConfig view_config = {.pos = {300, 200}}; +}; - j["main_window"]["size"][0] = config.window_size[0]; - j["main_window"]["size"][1] = config.window_size[1]; +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(ProjectConfig::ViewConfig, pos); - j["graph_editor"]["visible"] = config.graph_editor.visible; - j["graph_editor"]["position"][0] = config.graph_editor.position[0]; - j["graph_editor"]["position"][1] = config.graph_editor.position[1]; - j["graph_editor"]["size"][0] = config.graph_editor.size[0]; - j["graph_editor"]["size"][1] = config.graph_editor.size[1]; - - j["skinned_mesh_widget"]["visible"] = config.skinned_mesh_widget.visible; - j["skinned_mesh_widget"]["position"][0] = - config.skinned_mesh_widget.position[0]; - j["skinned_mesh_widget"]["position"][1] = - config.skinned_mesh_widget.position[1]; - j["skinned_mesh_widget"]["size"][0] = config.skinned_mesh_widget.size[0]; - j["skinned_mesh_widget"]["size"][1] = config.skinned_mesh_widget.size[1]; - - j["animation_player_widget"]["visible"] = - config.animation_player_widget.visible; - j["animation_player_widget"]["position"][0] = - config.animation_player_widget.position[0]; - j["animation_player_widget"]["position"][1] = - config.animation_player_widget.position[1]; - j["animation_player_widget"]["size"][0] = - config.animation_player_widget.size[0]; - j["animation_player_widget"]["size"][1] = - config.animation_player_widget.size[1]; - - j["viewport_widget"]["visible"] = config.viewport_widget.visible; - j["viewport_widget"]["position"][0] = config.viewport_widget.position[0]; - j["viewport_widget"]["position"][1] = config.viewport_widget.position[1]; - j["viewport_widget"]["size"][0] = config.viewport_widget.size[0]; - j["viewport_widget"]["size"][1] = config.viewport_widget.size[1]; - - j["camera_widget"]["visible"] = config.show_camera_widget; -} - -void from_json(const nlohmann::json& j, ApplicationConfig& config) { - if (j.contains("main_window")) { - if (j["main_window"].contains("position") - and j["main_window"]["position"].size() == 2) { - config.window_position[0] = j["main_window"]["position"].at(0); - config.window_position[1] = j["main_window"]["position"].at(1); - } - - if (j["main_window"].contains("size") - and j["main_window"]["size"].size() == 2) { - config.window_size[0] = j["main_window"]["size"].at(0); - config.window_size[1] = j["main_window"]["size"].at(1); - } - } - - if (j.contains("graph_editor")) { - if (j["graph_editor"].contains("visible")) { - config.graph_editor.visible = j["graph_editor"]["visible"]; - } - - if (j["graph_editor"].contains("position") - and j["graph_editor"]["position"].size() == 2) { - config.graph_editor.position[0] = j["graph_editor"]["position"].at(0); - config.graph_editor.position[1] = j["graph_editor"]["position"].at(1); - } - - if (j["graph_editor"].contains("size") - and j["graph_editor"]["size"].size() == 2) { - config.graph_editor.size[0] = j["graph_editor"]["size"].at(0); - config.graph_editor.size[1] = j["graph_editor"]["size"].at(1); - } - } - - if (j.contains("skinned_mesh_widget")) { - if (j["skinned_mesh_widget"].contains("visible")) { - config.skinned_mesh_widget.visible = j["skinned_mesh_widget"]["visible"]; - } - - if (j["skinned_mesh_widget"].contains("position") - and j["skinned_mesh_widget"]["position"].size() == 2) { - config.skinned_mesh_widget.position[0] = - j["skinned_mesh_widget"]["position"].at(0); - config.skinned_mesh_widget.position[1] = - j["skinned_mesh_widget"]["position"].at(1); - } - - if (j["skinned_mesh_widget"].contains("size") - and j["skinned_mesh_widget"]["size"].size() == 2) { - config.skinned_mesh_widget.size[0] = - j["skinned_mesh_widget"]["size"].at(0); - config.skinned_mesh_widget.size[1] = - j["skinned_mesh_widget"]["size"].at(1); - } - } - - if (j.contains("animation_player_widget")) { - if (j["animation_player_widget"].contains("visible")) { - config.animation_player_widget.visible = - j["animation_player_widget"]["visible"]; - } - - if (j["animation_player_widget"].contains("position") - and j["animation_player_widget"]["position"].size() == 2) { - config.animation_player_widget.position[0] = - j["animation_player_widget"]["position"].at(0); - config.animation_player_widget.position[1] = - j["animation_player_widget"]["position"].at(1); - } - - if (j["animation_player_widget"].contains("size") - and j["animation_player_widget"]["size"].size() == 2) { - config.animation_player_widget.size[0] = - j["animation_player_widget"]["size"].at(0); - config.animation_player_widget.size[1] = - j["animation_player_widget"]["size"].at(1); - } - } - - if (j.contains("viewport_widget")) { - if (j["viewport_widget"].contains("visible")) { - config.viewport_widget.visible = j["viewport_widget"]["visible"]; - } - - if (j["viewport_widget"].contains("position") - and j["viewport_widget"]["position"].size() == 2) { - config.viewport_widget.position[0] = - j["viewport_widget"]["position"].at(0); - config.viewport_widget.position[1] = - j["viewport_widget"]["position"].at(1); - } - - if (j["viewport_widget"].contains("size") - and j["viewport_widget"]["size"].size() == 2) { - config.viewport_widget.size[0] = j["viewport_widget"]["size"].at(0); - config.viewport_widget.size[1] = j["viewport_widget"]["size"].at(1); - } - } - - if (j.contains("camera_widget") and j["camera_widget"].contains("visible")) { - config.show_camera_widget = j["camera_widget"]["visible"]; - } -} +NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( + ProjectConfig, + type, + animation_library_file, + skeleton_file, + graph_resource_file, + view_config); ApplicationConfig gApplicationConfig; +ProjectConfig gProjectConfig; static void draw_grid(); @@ -592,9 +480,9 @@ void load_application_config(const char* filename) { } if (application_config.value("type", "undefined") != "AnimTestbedConfig") { - std::cerr - << "Invalid json object. Expected type 'AnimTestbedConfig' but got '" - << application_config["type"] << "'." << std::endl; + std::cerr << "Invalid json object. Expected type '" + << ApplicationConfig::TypeStr << "' but got '" + << application_config["type"] << "'." << std::endl; application_config["type"] = "AnimTestbedConfig"; } @@ -640,20 +528,20 @@ int main() { glfwSwapInterval(1); load_application_config("animtestbed_config.json"); - if (gApplicationConfig.window_position[0] != 0 - || gApplicationConfig.window_position[1] != 0) { + if (gApplicationConfig.window.position[0] != 0 + || gApplicationConfig.window.position[1] != 0) { glfwSetWindowPos( window, - gApplicationConfig.window_position[0], - gApplicationConfig.window_position[1]); + gApplicationConfig.window.position[0], + gApplicationConfig.window.position[1]); } - if (gApplicationConfig.window_size[0] != 0 - || gApplicationConfig.window_size[1] != 0) { + if (gApplicationConfig.window.size[0] != 0 + || gApplicationConfig.window.size[1] != 0) { glfwSetWindowSize( window, - gApplicationConfig.window_size[0], - gApplicationConfig.window_size[1]); + gApplicationConfig.window.size[0], + gApplicationConfig.window.size[1]); } NFD_Init(); @@ -673,15 +561,11 @@ int main() { sgl_setup(&sgldesc); sgl_defaults(); - // sgl_context_desc_t sgl_context_desc = {}; - // sgl_context ctx = sgl_make_context(&sgl_context_desc); - SkinnedMeshResource skinned_mesh_resource; skinned_mesh_resource.loadFromFile("../media/SampleSkinnedMesh.json"); SkinnedMesh skinned_mesh; skinned_mesh_resource.createInstance(skinned_mesh); - skinned_mesh.SetCurrentAnimation(0); AnimGraphBlendTree anim_graph; AnimGraphContext anim_graph_context; @@ -726,13 +610,13 @@ int main() { // Update window state glfwGetWindowPos( window, - &gApplicationConfig.window_position[0], - &gApplicationConfig.window_position[1]); + &gApplicationConfig.window.position[0], + &gApplicationConfig.window.position[1]); glfwGetWindowSize( window, - &gApplicationConfig.window_size[0], - &gApplicationConfig.window_size[1]); + &gApplicationConfig.window.size[0], + &gApplicationConfig.window.size[1]); int cur_width, cur_height; glfwGetFramebufferSize(window, &cur_width, &cur_height); @@ -860,14 +744,16 @@ int main() { ImGui::SetNextWindowPos( ImVec2( static_cast( - gApplicationConfig.viewport_widget.position[0]), + gApplicationConfig.viewport_widget.rect.position[0]), static_cast( - gApplicationConfig.viewport_widget.position[1])), + gApplicationConfig.viewport_widget.rect.position[1])), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize( ImVec2( - static_cast(gApplicationConfig.viewport_widget.size[0]), - static_cast(gApplicationConfig.viewport_widget.size[1])), + static_cast( + gApplicationConfig.viewport_widget.rect.size[0]), + static_cast( + gApplicationConfig.viewport_widget.rect.size[1])), ImGuiCond_FirstUseEver); ImGui::Begin("Viewport", &gApplicationConfig.viewport_widget.visible); @@ -882,9 +768,9 @@ int main() { } ImVec2 viewport_widget_size = ImGui::GetWindowSize(); - gApplicationConfig.viewport_widget.size[0] = + gApplicationConfig.viewport_widget.rect.size[0] = static_cast(viewport_widget_size.x); - gApplicationConfig.viewport_widget.size[1] = + gApplicationConfig.viewport_widget.rect.size[1] = static_cast(viewport_widget_size.y); ImGui::Text( @@ -932,16 +818,16 @@ int main() { ImGui::SetNextWindowPos( ImVec2( static_cast( - gApplicationConfig.skinned_mesh_widget.position[0]), + gApplicationConfig.skinned_mesh_widget.rect.position[0]), static_cast( - gApplicationConfig.skinned_mesh_widget.position[1])), + gApplicationConfig.skinned_mesh_widget.rect.position[1])), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize( ImVec2( static_cast( - gApplicationConfig.skinned_mesh_widget.size[0]), + gApplicationConfig.skinned_mesh_widget.rect.size[0]), static_cast( - gApplicationConfig.skinned_mesh_widget.size[1])), + gApplicationConfig.skinned_mesh_widget.rect.size[1])), ImGuiCond_FirstUseEver); ImGui::Begin( @@ -949,15 +835,15 @@ int main() { &gApplicationConfig.skinned_mesh_widget.visible); ImVec2 skinned_mesh_widget_position = ImGui::GetWindowPos(); - gApplicationConfig.skinned_mesh_widget.position[0] = + gApplicationConfig.skinned_mesh_widget.rect.position[0] = static_cast(skinned_mesh_widget_position.x); - gApplicationConfig.skinned_mesh_widget.position[1] = + gApplicationConfig.skinned_mesh_widget.rect.position[1] = static_cast(skinned_mesh_widget_position.y); ImVec2 skinned_mesh_widget_size = ImGui::GetWindowSize(); - gApplicationConfig.skinned_mesh_widget.size[0] = + gApplicationConfig.skinned_mesh_widget.rect.size[0] = static_cast(skinned_mesh_widget_size.x); - gApplicationConfig.skinned_mesh_widget.size[1] = + gApplicationConfig.skinned_mesh_widget.rect.size[1] = static_cast(skinned_mesh_widget_size.y); SkinnedMeshWidget(&skinned_mesh); @@ -968,17 +854,17 @@ int main() { if (gApplicationConfig.animation_player_widget.visible) { ImGui::SetNextWindowPos( ImVec2( - static_cast( - gApplicationConfig.animation_player_widget.position[0]), - static_cast( - gApplicationConfig.animation_player_widget.position[1])), + static_cast(gApplicationConfig.animation_player_widget + .rect.position[0]), + static_cast(gApplicationConfig.animation_player_widget + .rect.position[1])), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize( ImVec2( static_cast( - gApplicationConfig.animation_player_widget.size[0]), + gApplicationConfig.animation_player_widget.rect.size[0]), static_cast( - gApplicationConfig.animation_player_widget.size[1])), + gApplicationConfig.animation_player_widget.rect.size[1])), ImGuiCond_FirstUseEver); ImGui::Begin( @@ -986,15 +872,15 @@ int main() { &gApplicationConfig.animation_player_widget.visible); ImVec2 animation_player_widget_position = ImGui::GetWindowPos(); - gApplicationConfig.animation_player_widget.position[0] = + gApplicationConfig.animation_player_widget.rect.position[0] = static_cast(animation_player_widget_position.x); - gApplicationConfig.animation_player_widget.position[1] = + gApplicationConfig.animation_player_widget.rect.position[1] = static_cast(animation_player_widget_position.y); ImVec2 animation_player_widget_size = ImGui::GetWindowSize(); - gApplicationConfig.animation_player_widget.size[0] = + gApplicationConfig.animation_player_widget.rect.size[0] = static_cast(animation_player_widget_size.x); - gApplicationConfig.animation_player_widget.size[1] = + gApplicationConfig.animation_player_widget.rect.size[1] = static_cast(animation_player_widget_size.y); if (anim_graph.m_nodes.size() > 0) { @@ -1096,13 +982,13 @@ int main() { if (gApplicationConfig.graph_editor.visible) { ImGui::SetNextWindowPos( ImVec2( - gApplicationConfig.graph_editor.position[0], - gApplicationConfig.graph_editor.position[1]), + gApplicationConfig.graph_editor.rect.position[0], + gApplicationConfig.graph_editor.rect.position[1]), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize( ImVec2( - gApplicationConfig.graph_editor.size[0], - gApplicationConfig.graph_editor.size[1]), + gApplicationConfig.graph_editor.rect.size[0], + gApplicationConfig.graph_editor.rect.size[1]), ImGuiCond_FirstUseEver); ImGui::Begin( @@ -1111,12 +997,14 @@ int main() { ImGuiWindowFlags_MenuBar); ImVec2 graph_editor_position = ImGui::GetWindowPos(); - gApplicationConfig.graph_editor.position[0] = graph_editor_position.x; - gApplicationConfig.graph_editor.position[1] = graph_editor_position.y; + gApplicationConfig.graph_editor.rect.position[0] = + graph_editor_position.x; + gApplicationConfig.graph_editor.rect.position[1] = + graph_editor_position.y; ImVec2 graph_editor_size = ImGui::GetWindowSize(); - gApplicationConfig.graph_editor.size[0] = graph_editor_size.x; - gApplicationConfig.graph_editor.size[1] = graph_editor_size.y; + gApplicationConfig.graph_editor.rect.size[0] = graph_editor_size.x; + gApplicationConfig.graph_editor.rect.size[1] = graph_editor_size.y; AnimGraphEditorUpdate(gApplicationConfig.graph_editor.context);