add type list api and input context serialization#22
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a compile-time TypeList utility and uses it to simplify variant/type-set handling across the engine (assets, ECS components, script values, inputs), while also adding YAML serialization for InputContext and editor UI to edit/serialize project inputs.
Changes:
- Add
GE::TypeList(+ helpers) and adopt it to define/iterate supported type sets (components, script values, assets, inputs). - Implement YAML serialization for raw inputs, input mappers, inputs (
VInput), andInputContext, including project persistence. - Extend the editor to view/edit project input bindings and add an example
PlayerControllerusing the new input system.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/serialization_testCases.cpp | Adds tests for InputContext YAML round-trip + safe dispatch with empty callback. |
| tests/TypeList_testCases.cpp | Adds coverage for TypeList helpers and folds. |
| src/Scene.cpp | Uses forEachType<ECSComponentTypes> to serialize components without repetitive checks. |
| src/InputContext.cpp | Adds removeInput / renameInput APIs for input editing. |
| src/Game.cpp | Keeps game descriptor wiring for input context; removes redundant constructor asserts. |
| include/Game-Engine/TypeList.hpp | New type-list metaprogramming utility + iteration helpers. |
| include/Game-Engine/Script.hpp | Refactors script value types to a TypeList-backed variant + traits. |
| include/Game-Engine/RawInput.hpp | Adds raw input type list + keyboard button YAML serialization helpers. |
| include/Game-Engine/InputMapper.hpp | Refactors mapper variant construction via TypeList + adds YAML conversion for mappers. |
| include/Game-Engine/InputFwd.hpp | Introduces InputTypes as a canonical type list for input variants. |
| include/Game-Engine/InputContext.hpp | Adds InputContext YAML conversion + exposes input map accessors. |
| include/Game-Engine/Input.hpp | Adds input YAML conversion (VInput), traits, and mapper rebinding for copy/move. |
| include/Game-Engine/Components.hpp | Migrates ECS component/script value variants to TypeList + refactors YAML decode via type iteration. |
| include/Game-Engine/AssetManager.hpp | Refactors manageable asset type handling + YAML decoding via TypeList. |
| examples/project1/scripts/PlayerController.cpp | Adds sample script wiring Range2DInput into movement. |
| examples/project1/project1.geproj | Persists inputContext in the project YAML and updates example scene/script. |
| editor/UI/ProjectPropertiesPanel.cpp | Adds UI for creating/removing/renaming inputs and editing mapper fields. |
| editor/UI/EntityInspectorPanel.cpp | Refactors editable component lists via TypeList. |
| editor/Project.hpp | Stores project-level InputContext and serializes it. |
| editor/Project.cpp | Passes serialized InputContext into GE::Game::Descriptor. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const VInput input = m_inputs.at(oldName); | ||
| m_inputs.erase(oldName); | ||
| auto [_, inserted] = m_inputs.emplace(newName, input); |
There was a problem hiding this comment.
InputContext::renameInput erases oldName before verifying that inserting newName succeeds. If newName already exists, the emplace fails (and the assert(inserted) only fires in debug), leaving the input silently dropped in release builds. Consider checking for name collisions up front and/or using a node-handle (extract/insert) or inserting first and only erasing on success so the operation is atomic and lossless.
| const VInput input = m_inputs.at(oldName); | |
| m_inputs.erase(oldName); | |
| auto [_, inserted] = m_inputs.emplace(newName, input); | |
| if (m_inputs.find(newName) != m_inputs.end()) | |
| return false; | |
| auto input = m_inputs.extract(oldName); | |
| assert(input.empty() == false); | |
| input.key() = newName; | |
| auto [_, inserted] = m_inputs.insert(std::move(input)); |
| if (!renameRequest.first.empty()) | ||
| inputContext.renameInput(renameRequest.first, renameRequest.second); | ||
| if (!inputToRemove.empty()) |
There was a problem hiding this comment.
The rename flow applies inputContext.renameInput(...) without validating the new name or checking the return value. Entering an empty name or renaming to an existing input name can currently trigger an assertion failure (debug) or lead to a dropped input (release, due to renameInput behavior). Add UI-side validation (non-empty + unique) and handle failed renames (e.g., keep old name and surface an error).
| #include <yaml-cpp/yaml.h> | ||
|
|
||
| #include <array> | ||
| #include <optional> |
There was a problem hiding this comment.
This header uses std::string in the YAML conversions (std::string(...) / node.as<std::string>()) but does not include <string>, relying on transitive includes from yaml-cpp. Add an explicit #include <string> to keep the header self-contained and avoid fragile build breaks.
| #include <optional> | |
| #include <optional> | |
| #include <string> |
No description provided.