From f51baeeb7744fa49a049ff394360f027d724e3a1 Mon Sep 17 00:00:00 2001 From: Ricardo Antunes Date: Tue, 24 Sep 2024 16:24:41 +0200 Subject: [PATCH 1/7] refactor(tools): move most tools to the engine --- CHANGELOG.md | 1 + engine/CMakeLists.txt | 16 +++ .../engine/tools/collider_gizmos/plugin.hpp | 23 +++++ .../cubos/engine/tools/console/plugin.hpp | 22 +++++ .../engine/tools/debug_camera/plugin.hpp | 22 +++++ .../engine/tools/ecs_statistics/plugin.hpp | 22 +++++ .../engine/tools/entity_inspector/plugin.hpp | 22 +++++ .../engine/tools/metrics_panel/plugin.hpp | 22 +++++ .../cubos/engine/tools/play_pause/plugin.hpp | 22 +++++ engine/include/cubos/engine/tools/plugin.hpp | 24 +++++ .../cubos/engine/tools/selection/plugin.hpp | 28 ++++++ .../engine/tools/selection/selection.hpp | 19 ++++ .../tools/settings_inspector/plugin.hpp | 22 +++++ .../cubos/engine/tools/toolbox/plugin.hpp | 26 +++++ .../cubos/engine/tools/toolbox/toolbox.hpp | 34 ++----- .../engine/tools}/transform_gizmo/plugin.hpp | 18 ++-- .../engine/tools/world_inspector/plugin.hpp | 22 +++++ engine/samples/collisions/main.cpp | 2 +- .../cubosurfers/assets/scenes/main.cubos | 3 +- engine/samples/games/cubosurfers/main.cpp | 4 + engine/samples/games/cubosurfers/obstacle.cpp | 2 +- engine/samples/games/cubosurfers/player.cpp | 2 +- engine/samples/games/cubosurfers/spawner.cpp | 2 +- .../src/tools}/collider_gizmos/plugin.cpp | 29 +++--- .../src/tools}/console/plugin.cpp | 17 ++-- .../src/tools}/debug_camera/plugin.cpp | 34 ++----- .../src/tools}/ecs_statistics/plugin.cpp | 40 +++----- .../src/tools}/entity_inspector/plugin.cpp | 24 ++--- .../src/tools}/metrics_panel/plugin.cpp | 15 ++- engine/src/tools/play_pause/plugin.cpp | 66 +++++++++++++ engine/src/tools/plugin.cpp | 36 +++++++ engine/src/tools/selection/plugin.cpp | 53 ++++++++++ engine/src/tools/selection/selection.cpp | 10 ++ .../src/tools}/settings_inspector/plugin.cpp | 20 ++-- engine/src/tools/toolbox/plugin.cpp | 30 ++++++ engine/src/tools/toolbox/toolbox.cpp | 35 +++++++ .../src/tools}/transform_gizmo/plugin.cpp | 57 ++++------- .../src/tools}/world_inspector/plugin.cpp | 62 +++++------- tools/tesseratos/CMakeLists.txt | 12 --- .../src/tesseratos/asset_explorer/plugin.cpp | 6 +- .../src/tesseratos/asset_explorer/plugin.hpp | 5 - .../src/tesseratos/collider_gizmos/plugin.hpp | 27 ----- .../src/tesseratos/console/plugin.hpp | 26 ----- .../src/tesseratos/debug_camera/plugin.hpp | 27 ----- .../src/tesseratos/debugger/plugin.cpp | 3 +- .../src/tesseratos/ecs_statistics/plugin.hpp | 27 ----- .../tesseratos/entity_inspector/plugin.hpp | 30 ------ .../src/tesseratos/entity_selector/plugin.cpp | 99 ------------------- .../src/tesseratos/entity_selector/plugin.hpp | 47 --------- tools/tesseratos/src/tesseratos/main.cpp | 26 +---- .../src/tesseratos/metrics_panel/plugin.hpp | 26 ----- .../src/tesseratos/play_pause/plugin.cpp | 75 -------------- .../src/tesseratos/play_pause/plugin.hpp | 26 ----- .../src/tesseratos/scene_editor/plugin.cpp | 26 ++--- .../src/tesseratos/scene_editor/plugin.hpp | 8 +- .../tesseratos/settings_inspector/plugin.hpp | 27 ----- .../src/tesseratos/toolbox/plugin.cpp | 68 ------------- .../voxel_palette_editor/plugin.cpp | 5 +- .../voxel_palette_editor/plugin.hpp | 3 - .../src/tesseratos/world_inspector/plugin.hpp | 30 ------ 60 files changed, 705 insertions(+), 832 deletions(-) create mode 100644 engine/include/cubos/engine/tools/collider_gizmos/plugin.hpp create mode 100644 engine/include/cubos/engine/tools/console/plugin.hpp create mode 100644 engine/include/cubos/engine/tools/debug_camera/plugin.hpp create mode 100644 engine/include/cubos/engine/tools/ecs_statistics/plugin.hpp create mode 100644 engine/include/cubos/engine/tools/entity_inspector/plugin.hpp create mode 100644 engine/include/cubos/engine/tools/metrics_panel/plugin.hpp create mode 100644 engine/include/cubos/engine/tools/play_pause/plugin.hpp create mode 100644 engine/include/cubos/engine/tools/plugin.hpp create mode 100644 engine/include/cubos/engine/tools/selection/plugin.hpp create mode 100644 engine/include/cubos/engine/tools/selection/selection.hpp create mode 100644 engine/include/cubos/engine/tools/settings_inspector/plugin.hpp create mode 100644 engine/include/cubos/engine/tools/toolbox/plugin.hpp rename tools/tesseratos/src/tesseratos/toolbox/plugin.hpp => engine/include/cubos/engine/tools/toolbox/toolbox.hpp (56%) rename {tools/tesseratos/src/tesseratos => engine/include/cubos/engine/tools}/transform_gizmo/plugin.hpp (52%) create mode 100644 engine/include/cubos/engine/tools/world_inspector/plugin.hpp rename {tools/tesseratos/src/tesseratos => engine/src/tools}/collider_gizmos/plugin.cpp (59%) rename {tools/tesseratos/src/tesseratos => engine/src/tools}/console/plugin.cpp (96%) rename {tools/tesseratos/src/tesseratos => engine/src/tools}/debug_camera/plugin.cpp (85%) rename {tools/tesseratos/src/tesseratos => engine/src/tools}/ecs_statistics/plugin.cpp (95%) rename {tools/tesseratos/src/tesseratos => engine/src/tools}/entity_inspector/plugin.cpp (93%) rename {tools/tesseratos/src/tesseratos => engine/src/tools}/metrics_panel/plugin.cpp (92%) create mode 100644 engine/src/tools/play_pause/plugin.cpp create mode 100644 engine/src/tools/plugin.cpp create mode 100644 engine/src/tools/selection/plugin.cpp create mode 100644 engine/src/tools/selection/selection.cpp rename {tools/tesseratos/src/tesseratos => engine/src/tools}/settings_inspector/plugin.cpp (72%) create mode 100644 engine/src/tools/toolbox/plugin.cpp create mode 100644 engine/src/tools/toolbox/toolbox.cpp rename {tools/tesseratos/src/tesseratos => engine/src/tools}/transform_gizmo/plugin.cpp (89%) rename {tools/tesseratos/src/tesseratos => engine/src/tools}/world_inspector/plugin.cpp (75%) delete mode 100644 tools/tesseratos/src/tesseratos/collider_gizmos/plugin.hpp delete mode 100644 tools/tesseratos/src/tesseratos/console/plugin.hpp delete mode 100644 tools/tesseratos/src/tesseratos/debug_camera/plugin.hpp delete mode 100644 tools/tesseratos/src/tesseratos/ecs_statistics/plugin.hpp delete mode 100644 tools/tesseratos/src/tesseratos/entity_inspector/plugin.hpp delete mode 100644 tools/tesseratos/src/tesseratos/entity_selector/plugin.cpp delete mode 100644 tools/tesseratos/src/tesseratos/entity_selector/plugin.hpp delete mode 100644 tools/tesseratos/src/tesseratos/metrics_panel/plugin.hpp delete mode 100644 tools/tesseratos/src/tesseratos/play_pause/plugin.cpp delete mode 100644 tools/tesseratos/src/tesseratos/play_pause/plugin.hpp delete mode 100644 tools/tesseratos/src/tesseratos/settings_inspector/plugin.hpp delete mode 100644 tools/tesseratos/src/tesseratos/toolbox/plugin.cpp delete mode 100644 tools/tesseratos/src/tesseratos/world_inspector/plugin.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 27d79e3e1..fee7ea5af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Moved Glad and stb-image libs to another repositories, cubos-glad and cubos-stb, respectively (#1323, **@kuukitenshi**). +- Moved most tools from Tesseratos to the engine (#1322, **@RiscadoA**). ### Fixed diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 001549789..127bb350d 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -164,6 +164,22 @@ set(CUBOS_ENGINE_SOURCE "src/render/shadow_atlas/shadow_atlas.cpp" "src/render/shadow_atlas_rasterizer/plugin.cpp" "src/render/shadow_atlas_rasterizer/shadow_atlas_rasterizer.cpp" + + "src/tools/settings_inspector/plugin.cpp" + "src/tools/selection/plugin.cpp" + "src/tools/selection/selection.cpp" + "src/tools/world_inspector/plugin.cpp" + "src/tools/entity_inspector/plugin.cpp" + "src/tools/debug_camera/plugin.cpp" + "src/tools/toolbox/plugin.cpp" + "src/tools/toolbox/toolbox.cpp" + "src/tools/transform_gizmo/plugin.cpp" + "src/tools/metrics_panel/plugin.cpp" + "src/tools/collider_gizmos/plugin.cpp" + "src/tools/play_pause/plugin.cpp" + "src/tools/ecs_statistics/plugin.cpp" + "src/tools/console/plugin.cpp" + "src/tools/plugin.cpp" ) # Create cubos engine diff --git a/engine/include/cubos/engine/tools/collider_gizmos/plugin.hpp b/engine/include/cubos/engine/tools/collider_gizmos/plugin.hpp new file mode 100644 index 000000000..aba411bdb --- /dev/null +++ b/engine/include/cubos/engine/tools/collider_gizmos/plugin.hpp @@ -0,0 +1,23 @@ +/// @dir +/// @brief @ref collider-gizmos-tool-plugin plugin directory. + +/// @file +/// @brief Plugin entry point. +/// @ingroup collider-gizmos-tool-plugin + +#pragma once + +#include +#include + +namespace cubos::engine +{ + /// @defgroup collider-gizmos-tool-plugin Collider Gizmos + /// @ingroup tool-plugins + /// @brief Draws gizmos for colliders of selected entities. + + /// @brief Plugin entry function. + /// @param cubos @b Cubos main class + /// @ingroup collider-gizmos-tool-plugin + CUBOS_ENGINE_API void colliderGizmosPlugin(Cubos& cubos); +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/tools/console/plugin.hpp b/engine/include/cubos/engine/tools/console/plugin.hpp new file mode 100644 index 000000000..6c1f7be19 --- /dev/null +++ b/engine/include/cubos/engine/tools/console/plugin.hpp @@ -0,0 +1,22 @@ +/// @dir +/// @brief @ref console-tool-plugin plugin directory. + +/// @file +/// @brief Plugin entry point. +/// @ingroup console-tool-plugin + +#pragma once + +#include + +namespace cubos::engine +{ + /// @defgroup console-tool-plugin Console + /// @ingroup tool-plugins + /// @brief Displays the log messages in an ImGui window. + + /// @brief Plugin entry function. + /// @param cubos @b Cubos main class + /// @ingroup console-tool-plugin + void consolePlugin(Cubos& cubos); +} // namespace cubos::engine \ No newline at end of file diff --git a/engine/include/cubos/engine/tools/debug_camera/plugin.hpp b/engine/include/cubos/engine/tools/debug_camera/plugin.hpp new file mode 100644 index 000000000..13b5381b6 --- /dev/null +++ b/engine/include/cubos/engine/tools/debug_camera/plugin.hpp @@ -0,0 +1,22 @@ +/// @dir +/// @brief @ref debug-camera-tool-plugin plugin directory. + +/// @file +/// @brief Plugin entry point. +/// @ingroup debug-camera-tool-plugin + +#pragma once + +#include + +namespace cubos::engine +{ + /// @defgroup debug-camera-tool-plugin Debug Camera + /// @ingroup tool-plugins + /// @brief Adds a toggleable debug camera. + + /// @brief Plugin entry function. + /// @param cubos @b Cubos main class + /// @ingroup debug-camera-tool-plugin + void debugCameraPlugin(Cubos& cubos); +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/tools/ecs_statistics/plugin.hpp b/engine/include/cubos/engine/tools/ecs_statistics/plugin.hpp new file mode 100644 index 000000000..0a10586ad --- /dev/null +++ b/engine/include/cubos/engine/tools/ecs_statistics/plugin.hpp @@ -0,0 +1,22 @@ +/// @dir +/// @brief @ref ecs-statistics-tool-plugin plugin directory. + +/// @file +/// @brief Plugin entry point. +/// @ingroup ecs-statistics-tool-plugin + +#pragma once + +#include + +namespace cubos::engine +{ + /// @defgroup ecs-statistics-tool-plugin ECS Statistics + /// @ingroup tool-plugins + /// @brief Shows tons of statistics and information about the internal state of the ECS. + + /// @brief Plugin entry function. + /// @param cubos @b Cubos main class + /// @ingroup ecs-statistics-tool-plugin + void ecsStatisticsPlugin(Cubos& cubos); +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/tools/entity_inspector/plugin.hpp b/engine/include/cubos/engine/tools/entity_inspector/plugin.hpp new file mode 100644 index 000000000..e698c66f8 --- /dev/null +++ b/engine/include/cubos/engine/tools/entity_inspector/plugin.hpp @@ -0,0 +1,22 @@ +/// @dir +/// @brief @ref entity-inspector-tool-plugin plugin directory. + +/// @file +/// @brief Plugin entry point. +/// @ingroup entity-inspector-tool-plugin + +#pragma once + +#include + +namespace cubos::engine +{ + /// @defgroup entity-inspector-tool-plugin Entity Inspector + /// @ingroup tool-plugins + /// @brief Allows inspecting and modifying the components of the current @ref Selection. + + /// @brief Plugin entry function. + /// @param cubos @b Cubos main class + /// @ingroup entity-inspector-tool-plugin + void entityInspectorPlugin(Cubos& cubos); +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/tools/metrics_panel/plugin.hpp b/engine/include/cubos/engine/tools/metrics_panel/plugin.hpp new file mode 100644 index 000000000..c633f5113 --- /dev/null +++ b/engine/include/cubos/engine/tools/metrics_panel/plugin.hpp @@ -0,0 +1,22 @@ +/// @dir +/// @brief @ref metrics-panel-tool-plugin plugin directory. + +/// @file +/// @brief Plugin entry point. +/// @ingroup metrics-panel-tool-plugin + +#pragma once + +#include + +namespace cubos::engine +{ + /// @defgroup metrics-panel-tool-plugin Metrics Panel + /// @ingroup tool-plugins + /// @brief Shows some useful performance metrics through a ImGui window. + + /// @brief Plugin entry function. + /// @param cubos @b Cubos main class + /// @ingroup metrics-panel-tool-plugin + void metricsPanelPlugin(Cubos& cubos); +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/tools/play_pause/plugin.hpp b/engine/include/cubos/engine/tools/play_pause/plugin.hpp new file mode 100644 index 000000000..adc7b4ffe --- /dev/null +++ b/engine/include/cubos/engine/tools/play_pause/plugin.hpp @@ -0,0 +1,22 @@ +/// @dir +/// @brief @ref play-pause-tool-plugin plugin directory. + +/// @file +/// @brief Plugin entry point. +/// @ingroup play-pause-tool-plugin + +#pragma once + +#include + +namespace cubos::engine +{ + /// @defgroup play-pause-tool-plugin Play Pause + /// @ingroup tool-plugins + /// @brief Allows changing the current simulation speed, or even pause it. + + /// @brief Plugin entry function. + /// @param cubos @b Cubos main class + /// @ingroup play-pause-tool-plugin + void playPauseToolPlugin(Cubos& cubos); +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/tools/plugin.hpp b/engine/include/cubos/engine/tools/plugin.hpp new file mode 100644 index 000000000..2a93851a4 --- /dev/null +++ b/engine/include/cubos/engine/tools/plugin.hpp @@ -0,0 +1,24 @@ +/// @dir +/// @brief @ref tool-plugins module. + +/// @file +/// @brief Plugin entry point. +/// @ingroup tool-plugins + +#pragma once + +#include + +namespace cubos::engine +{ + /// @defgroup tool-plugins Tools + /// @ingroup engine + /// @brief Adds various debugging tool plugins. + /// + /// Most of these tools provide their own ImGui windows which can be toggled with the @ref toolbox-plugin. + + /// @brief Plugin entry function. + /// @param cubos @b Cubos main class + /// @ingroup tool-plugins + void toolsPlugin(Cubos& cubos); +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/tools/selection/plugin.hpp b/engine/include/cubos/engine/tools/selection/plugin.hpp new file mode 100644 index 000000000..1c66eb7f9 --- /dev/null +++ b/engine/include/cubos/engine/tools/selection/plugin.hpp @@ -0,0 +1,28 @@ +/// @dir +/// @brief @ref selection-tool-plugin plugin directory. + +/// @file +/// @brief Plugin entry point. +/// @ingroup selection-tool-plugin + +#pragma once + +#include +#include + +namespace cubos::engine +{ + /// @defgroup selection-tool-plugin Selection + /// @ingroup tool-plugins + /// @brief Adds a resource which keeps track of what the current selection is. + /// + /// This plugins exists to reduce coupling between plugins. For example, a plugin which allows + /// selecting entities through a ImGui window only needs to depend on this plugin, instead of + /// having to know about all the plugins which care about it. The same applies in the other + /// direction. + + /// @brief Plugin entry function. + /// @param cubos @b Cubos main class + /// @ingroup selection-tool-plugin + void selectionPlugin(Cubos& cubos); +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/tools/selection/selection.hpp b/engine/include/cubos/engine/tools/selection/selection.hpp new file mode 100644 index 000000000..02ff0998e --- /dev/null +++ b/engine/include/cubos/engine/tools/selection/selection.hpp @@ -0,0 +1,19 @@ +/// @file +/// @brief Resource @ref cubos::engine::Selection. +/// @ingroup selection-tool-plugin + +#pragma once + +#include + +namespace cubos::engine +{ + /// @brief Resource which identifies the current selection. + /// @ingroup selection-tool-plugin + struct Selection + { + CUBOS_REFLECT; + + cubos::core::ecs::Entity entity; ///< Selected entity, or null if none. + }; +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/tools/settings_inspector/plugin.hpp b/engine/include/cubos/engine/tools/settings_inspector/plugin.hpp new file mode 100644 index 000000000..1c43836d3 --- /dev/null +++ b/engine/include/cubos/engine/tools/settings_inspector/plugin.hpp @@ -0,0 +1,22 @@ +/// @dir +/// @brief @ref settings-inspector-tool-plugin plugin directory. + +/// @file +/// @brief Plugin entry point. +/// @ingroup settings-inspector-tool-plugin + +#pragma once + +#include + +namespace cubos::engine +{ + /// @defgroup settings-inspector-tool-plugin Settings Inspector + /// @ingroup tool-plugins + /// @brief Allows inspecting the current setting values through a ImGui window. + + /// @brief Plugin entry function. + /// @param cubos @b Cubos main class + /// @ingroup settings-inspector-tool-plugin + void settingsInspectorPlugin(Cubos& cubos); +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/tools/toolbox/plugin.hpp b/engine/include/cubos/engine/tools/toolbox/plugin.hpp new file mode 100644 index 000000000..a5c39d1a6 --- /dev/null +++ b/engine/include/cubos/engine/tools/toolbox/plugin.hpp @@ -0,0 +1,26 @@ +/// @dir +/// @brief @ref toolbox-tool-plugin plugin directory. + +/// @file +/// @brief Plugin entry point. +/// @ingroup toolbox-tool-plugin + +#pragma once + +#include +#include + +namespace cubos::engine +{ + /// @defgroup toolbox-tool-plugin Toolbox + /// @ingroup tool-plugins + /// @brief Allows toggling the visibility of other tools. + /// + /// Most tools in the @ref tool-plugins module rely on the @ref Toolbox to keep track of whether they are open or + /// not. + + /// @brief Plugin entry function. + /// @param cubos @b Cubos main class + /// @ingroup toolbox-tool-plugin + void toolboxPlugin(Cubos& cubos); +} // namespace cubos::engine diff --git a/tools/tesseratos/src/tesseratos/toolbox/plugin.hpp b/engine/include/cubos/engine/tools/toolbox/toolbox.hpp similarity index 56% rename from tools/tesseratos/src/tesseratos/toolbox/plugin.hpp rename to engine/include/cubos/engine/tools/toolbox/toolbox.hpp index a35b294f6..6a9d6883a 100644 --- a/tools/tesseratos/src/tesseratos/toolbox/plugin.hpp +++ b/engine/include/cubos/engine/tools/toolbox/toolbox.hpp @@ -1,28 +1,15 @@ -/// @dir -/// @brief @ref tesseratos-toolbox-plugin plugin directory. - /// @file -/// @brief Plugin entry point. -/// @ingroup tesseratos-toolbox-plugin +/// @brief Resource @ref cubos::engine::Toolbox. +/// @ingroup toolbox-tool-plugin #pragma once #include -namespace tesseratos +namespace cubos::engine { - /// @defgroup tesseratos-toolbox-plugin Toolbox - /// @ingroup tesseratos - /// @brief Adds a resource used to keep track of whether each tool is open or not. - /// - /// ## Resources - /// - @ref Toolbox - /// - /// ## Dependencies - /// - @ref imguiPlugin - - /// @brief Resource which manages other tools windows. - /// @ingroup tesseratos-toolbox-plugin + /// @brief Manages the visibility of each tool. + /// @ingroup toolbox-tool-plugin class Toolbox final { public: @@ -45,8 +32,8 @@ namespace tesseratos /// @param toolName Tool name. void toggle(const std::string& toolName); - /// @brief Returns the beggining of the map with known tools. - /// @return Begginng of the map. + /// @brief Returns the beginning of the map with known tools. + /// @return Beginning of the map. auto begin() const { return mToolsMap.begin(); @@ -62,9 +49,4 @@ namespace tesseratos private: std::unordered_map mToolsMap; }; - - /// @brief Plugin entry function. - /// @param cubos @b Cubos main class - /// @ingroup tesseratos-toolbox-plugin - void toolboxPlugin(cubos::engine::Cubos& cubos); -} // namespace tesseratos +} // namespace cubos::engine diff --git a/tools/tesseratos/src/tesseratos/transform_gizmo/plugin.hpp b/engine/include/cubos/engine/tools/transform_gizmo/plugin.hpp similarity index 52% rename from tools/tesseratos/src/tesseratos/transform_gizmo/plugin.hpp rename to engine/include/cubos/engine/tools/transform_gizmo/plugin.hpp index bd353181e..5580d6591 100644 --- a/tools/tesseratos/src/tesseratos/transform_gizmo/plugin.hpp +++ b/engine/include/cubos/engine/tools/transform_gizmo/plugin.hpp @@ -1,19 +1,19 @@ /// @dir -/// @brief @ref tesseratos-transform-gizmo-plugin plugin directory. +/// @brief @ref transform-gizmo-tool-plugin plugin directory. /// @file /// @brief Plugin entry point. -/// @ingroup tesseratos-transform-gizmo-plugin +/// @ingroup transform-gizmo-tool-plugin #pragma once #include -namespace tesseratos +namespace cubos::engine { - /// @defgroup tesseratos-transform-gizmo-plugin Transform gizmo - /// @ingroup tesseratos - /// @brief Add a gizmo that allows changing an entity's position. + /// @defgroup transform-gizmo-tool-plugin Transform Gizmo + /// @ingroup tool-plugins + /// @brief Adds a gizmo that allows changing the selected entity's position. /// /// ## Settings /// - `"transformGizmo.useLocalAxis"` - whether to use local instead of global axis (default: `true`). @@ -22,6 +22,6 @@ namespace tesseratos /// @brief Plugin entry function. /// @param cubos @b Cubos main class - /// @ingroup tesseratos-transform-gizmo-plugin - void transformGizmoPlugin(cubos::engine::Cubos& cubos); -} // namespace tesseratos + /// @ingroup transform-gizmo-tool-plugin + void transformGizmoPlugin(Cubos& cubos); +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/tools/world_inspector/plugin.hpp b/engine/include/cubos/engine/tools/world_inspector/plugin.hpp new file mode 100644 index 000000000..3104b3225 --- /dev/null +++ b/engine/include/cubos/engine/tools/world_inspector/plugin.hpp @@ -0,0 +1,22 @@ +/// @dir +/// @brief @ref world-inspector-tool-plugin plugin directory. + +/// @file +/// @brief Plugin entry point. +/// @ingroup world-inspector-tool-plugin + +#pragma once + +#include + +namespace cubos::engine +{ + /// @defgroup world-inspector-tool-plugin World Inspector + /// @ingroup tool-plugins + /// @brief Shows all of the entities in the world, and allows selecting them. + + /// @brief Plugin entry function. + /// @param cubos @b Cubos main class + /// @ingroup world-inspector-tool-plugin + void worldInspectorPlugin(Cubos& cubos); +} // namespace cubos::engine diff --git a/engine/samples/collisions/main.cpp b/engine/samples/collisions/main.cpp index 2c19ddfc1..7acabb417 100644 --- a/engine/samples/collisions/main.cpp +++ b/engine/samples/collisions/main.cpp @@ -190,7 +190,7 @@ int main(int argc, char** argv) cubos.system("check collisions") .tagged(collisionsSampleUpdated) - .after(cubos::engine::collisionsTag) + .after(collisionsTag) .call([](Query query, State& state) { for (auto [ent1, colliding, ent2] : query) { diff --git a/engine/samples/games/cubosurfers/assets/scenes/main.cubos b/engine/samples/games/cubosurfers/assets/scenes/main.cubos index 99b1ab47a..f19b540a1 100644 --- a/engine/samples/games/cubosurfers/assets/scenes/main.cubos +++ b/engine/samples/games/cubosurfers/assets/scenes/main.cubos @@ -1,7 +1,8 @@ { "entities": { "render-target": { - "cubos::engine::RenderTargetDefaults": {} + "cubos::engine::RenderTargetDefaults": {}, + "cubos::engine::GizmosTarget": {} }, "player": { "cubos::engine::RenderVoxelGrid": { diff --git a/engine/samples/games/cubosurfers/main.cpp b/engine/samples/games/cubosurfers/main.cpp index 4086c70c1..87af77ad4 100644 --- a/engine/samples/games/cubosurfers/main.cpp +++ b/engine/samples/games/cubosurfers/main.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include "obstacle.hpp" @@ -23,6 +25,8 @@ int main(int argc, char** argv) Cubos cubos{argc, argv}; cubos.plugin(defaultsPlugin); + cubos.plugin(freeCameraPlugin); + cubos.plugin(toolsPlugin); cubos.plugin(spawnerPlugin); cubos.plugin(obstaclePlugin); cubos.plugin(playerPlugin); diff --git a/engine/samples/games/cubosurfers/obstacle.cpp b/engine/samples/games/cubosurfers/obstacle.cpp index cd636073b..76bc4c01f 100644 --- a/engine/samples/games/cubosurfers/obstacle.cpp +++ b/engine/samples/games/cubosurfers/obstacle.cpp @@ -18,7 +18,7 @@ CUBOS_REFLECT_IMPL(Obstacle) .build(); } -void obstaclePlugin(cubos::engine::Cubos& cubos) +void obstaclePlugin(Cubos& cubos) { cubos.depends(assetsPlugin); cubos.depends(transformPlugin); diff --git a/engine/samples/games/cubosurfers/player.cpp b/engine/samples/games/cubosurfers/player.cpp index aeb538a70..7e91b97dd 100644 --- a/engine/samples/games/cubosurfers/player.cpp +++ b/engine/samples/games/cubosurfers/player.cpp @@ -16,7 +16,7 @@ CUBOS_REFLECT_IMPL(Player) .build(); } -void playerPlugin(cubos::engine::Cubos& cubos) +void playerPlugin(Cubos& cubos) { cubos.depends(inputPlugin); cubos.depends(transformPlugin); diff --git a/engine/samples/games/cubosurfers/spawner.cpp b/engine/samples/games/cubosurfers/spawner.cpp index 92c0ed4f8..dd481146c 100644 --- a/engine/samples/games/cubosurfers/spawner.cpp +++ b/engine/samples/games/cubosurfers/spawner.cpp @@ -20,7 +20,7 @@ CUBOS_REFLECT_IMPL(Spawner) .build(); } -void spawnerPlugin(cubos::engine::Cubos& cubos) +void spawnerPlugin(Cubos& cubos) { cubos.depends(assetsPlugin); cubos.depends(transformPlugin); diff --git a/tools/tesseratos/src/tesseratos/collider_gizmos/plugin.cpp b/engine/src/tools/collider_gizmos/plugin.cpp similarity index 59% rename from tools/tesseratos/src/tesseratos/collider_gizmos/plugin.cpp rename to engine/src/tools/collider_gizmos/plugin.cpp index 739c8474f..8e1bb6f63 100644 --- a/tools/tesseratos/src/tesseratos/collider_gizmos/plugin.cpp +++ b/engine/src/tools/collider_gizmos/plugin.cpp @@ -1,29 +1,24 @@ -#include "plugin.hpp" - #include #include #include #include +#include +#include +#include #include -#include "../entity_selector/plugin.hpp" -#include "../toolbox/plugin.hpp" - -using namespace cubos::engine; - -void tesseratos::colliderGizmosPlugin(Cubos& cubos) +void cubos::engine::colliderGizmosPlugin(Cubos& cubos) { - cubos.depends(cubos::engine::gizmosPlugin); - cubos.depends(cubos::engine::collisionsPlugin); - cubos.depends(cubos::engine::transformPlugin); - + cubos.depends(gizmosPlugin); + cubos.depends(collisionsPlugin); + cubos.depends(transformPlugin); cubos.depends(toolboxPlugin); - cubos.depends(entitySelectorPlugin); + cubos.depends(selectionPlugin); cubos.system("draw box collision shape gizmos") - .after(cubos::engine::transformUpdateTag) - .before(cubos::engine::gizmosDrawTag) - .call([](Toolbox& toolbox, Gizmos& gizmos, const EntitySelector& selector, + .after(transformUpdateTag) + .before(gizmosDrawTag) + .call([](Toolbox& toolbox, Gizmos& gizmos, const Selection& selection, Query boxes) { bool showAll = toolbox.isOpen("All Collider Gizmos"); @@ -31,7 +26,7 @@ void tesseratos::colliderGizmosPlugin(Cubos& cubos) for (auto [ent, localToWorld, collider, shape] : boxes) { - if (showAll || ent == selector.selection) + if (showAll || ent == selection.entity) { auto size = shape.box.halfSize * 2.0F; auto transform = glm::scale(localToWorld.mat * collider.transform, size); diff --git a/tools/tesseratos/src/tesseratos/console/plugin.cpp b/engine/src/tools/console/plugin.cpp similarity index 96% rename from tools/tesseratos/src/tesseratos/console/plugin.cpp rename to engine/src/tools/console/plugin.cpp index bbe47e385..00edb2520 100644 --- a/tools/tesseratos/src/tesseratos/console/plugin.cpp +++ b/engine/src/tools/console/plugin.cpp @@ -1,16 +1,10 @@ -#include "plugin.hpp" - #include #include #include - -#include "../toolbox/plugin.hpp" - -using cubos::engine::Cubos; - -using namespace tesseratos; +#include +#include namespace { @@ -77,13 +71,14 @@ static ImVec4 levelToColor(cubos::core::Logger::Level level) } } -void tesseratos::consolePlugin(Cubos& cubos) +void cubos::engine::consolePlugin(Cubos& cubos) { - cubos.depends(cubos::engine::imguiPlugin); + cubos.depends(imguiPlugin); cubos.depends(toolboxPlugin); + cubos.resource(); - cubos.system("show Logger UI").tagged(cubos::engine::imguiTag).call([](Toolbox& toolbox, State& state) { + cubos.system("show Logger UI").tagged(imguiTag).call([](Toolbox& toolbox, State& state) { if (!toolbox.isOpen("Console")) { return; diff --git a/tools/tesseratos/src/tesseratos/debug_camera/plugin.cpp b/engine/src/tools/debug_camera/plugin.cpp similarity index 85% rename from tools/tesseratos/src/tesseratos/debug_camera/plugin.cpp rename to engine/src/tools/debug_camera/plugin.cpp index ed85780e8..72083dc87 100644 --- a/tools/tesseratos/src/tesseratos/debug_camera/plugin.cpp +++ b/engine/src/tools/debug_camera/plugin.cpp @@ -1,4 +1,3 @@ -#include "plugin.hpp" #include #include @@ -12,27 +11,15 @@ #include #include #include +#include +#include #include #include -#include "../toolbox/plugin.hpp" - using namespace cubos::core::io; - +using cubos::core::ecs::Entity; using cubos::core::ecs::EntityHash; -using cubos::engine::Camera; -using cubos::engine::Commands; -using cubos::engine::Cubos; -using cubos::engine::DrawsTo; -using cubos::engine::Entity; -using cubos::engine::FreeCameraController; -using cubos::engine::Input; -using cubos::engine::PerspectiveCamera; -using cubos::engine::Position; -using cubos::engine::Query; -using cubos::engine::RenderTarget; - namespace { struct State @@ -50,14 +37,13 @@ namespace }; } // namespace -void tesseratos::debugCameraPlugin(Cubos& cubos) +void cubos::engine::debugCameraPlugin(Cubos& cubos) { - cubos.depends(cubos::engine::imguiPlugin); - cubos.depends(cubos::engine::freeCameraPlugin); - cubos.depends(cubos::engine::cameraPlugin); - cubos.depends(cubos::engine::renderTargetPlugin); - cubos.depends(cubos::engine::inputPlugin); - + cubos.depends(imguiPlugin); + cubos.depends(freeCameraPlugin); + cubos.depends(cameraPlugin); + cubos.depends(renderTargetPlugin); + cubos.depends(inputPlugin); cubos.depends(toolboxPlugin); cubos.resource(); @@ -102,7 +88,7 @@ void tesseratos::debugCameraPlugin(Cubos& cubos) }); cubos.system("update Debug Camera") - .tagged(cubos::engine::imguiTag) + .tagged(imguiTag) .onlyIf([](Toolbox& toolbox) { return toolbox.isOpen("Debug Camera"); }) .call([](State& state, Commands cmds, Query cameras, Query targets) { diff --git a/tools/tesseratos/src/tesseratos/ecs_statistics/plugin.cpp b/engine/src/tools/ecs_statistics/plugin.cpp similarity index 95% rename from tools/tesseratos/src/tesseratos/ecs_statistics/plugin.cpp rename to engine/src/tools/ecs_statistics/plugin.cpp index adfa27749..4487ad8e4 100644 --- a/tools/tesseratos/src/tesseratos/ecs_statistics/plugin.cpp +++ b/engine/src/tools/ecs_statistics/plugin.cpp @@ -1,25 +1,15 @@ -#include "plugin.hpp" - #include #include #include #include +#include +#include +#include -#include "../entity_selector/plugin.hpp" -#include "../toolbox/plugin.hpp" - -using cubos::core::ecs::ArchetypeId; -using cubos::core::ecs::ColumnId; -using cubos::core::ecs::DataTypeId; -using cubos::core::ecs::Name; -using cubos::core::ecs::SparseRelationTableId; -using cubos::core::ecs::World; +using namespace cubos::core::ecs; using cubos::core::reflection::Type; -using cubos::engine::Cubos; -using cubos::engine::DataInspector; -using cubos::engine::Entity; namespace { @@ -37,21 +27,21 @@ namespace }; } // namespace -void tesseratos::ecsStatisticsPlugin(Cubos& cubos) +void cubos::engine::ecsStatisticsPlugin(Cubos& cubos) { - cubos.depends(cubos::engine::imguiPlugin); + cubos.depends(imguiPlugin); cubos.depends(toolboxPlugin); - cubos.depends(entitySelectorPlugin); + cubos.depends(selectionPlugin); cubos.resource(); cubos.system("show ECS statistics") - .tagged(cubos::engine::imguiTag) + .tagged(imguiTag) .onlyIf([](Toolbox& toolbox) { return toolbox.isOpen("ECS Statistics"); }) - .call([](const World& world, State& state, EntitySelector& selector, DataInspector& inspector) { - if (world.isAlive(selector.selection)) + .call([](const World& world, State& state, Selection& selection, DataInspector& inspector) { + if (world.isAlive(selection.entity)) { - state.selectedArchetype = world.archetype(selector.selection); + state.selectedArchetype = world.archetype(selection.entity); } ImGui::Begin("ECS Statistics"); @@ -115,7 +105,7 @@ void tesseratos::ecsStatisticsPlugin(Cubos& cubos) if (ImGui::Button(std::to_string(archetype.inner).c_str())) { state.selectedArchetype = archetype; - selector.selection = {}; + selection.entity = {}; } ImGui::TableNextColumn(); if (world.tables().dense().contains(archetype)) @@ -183,7 +173,7 @@ void tesseratos::ecsStatisticsPlugin(Cubos& cubos) } if (ImGui::Button(name.c_str())) { - selector.selection = entity; + selection.entity = entity; } } ImGui::EndTable(); @@ -363,7 +353,7 @@ void tesseratos::ecsStatisticsPlugin(Cubos& cubos) } if (ImGui::Button(name.c_str())) { - selector.selection = from; + selection.entity = from; } ImGui::TableNextColumn(); Entity to{table.to(row), world.generation(table.to(row))}; @@ -374,7 +364,7 @@ void tesseratos::ecsStatisticsPlugin(Cubos& cubos) } if (ImGui::Button(name.c_str())) { - selector.selection = to; + selection.entity = to; } ImGui::PopID(); } diff --git a/tools/tesseratos/src/tesseratos/entity_inspector/plugin.cpp b/engine/src/tools/entity_inspector/plugin.cpp similarity index 93% rename from tools/tesseratos/src/tesseratos/entity_inspector/plugin.cpp rename to engine/src/tools/entity_inspector/plugin.cpp index bc4a54c48..a397cc5ee 100644 --- a/tools/tesseratos/src/tesseratos/entity_inspector/plugin.cpp +++ b/engine/src/tools/entity_inspector/plugin.cpp @@ -1,5 +1,3 @@ -#include "plugin.hpp" - #include #include @@ -8,9 +6,9 @@ #include #include - -#include "../entity_selector/plugin.hpp" -#include "../toolbox/plugin.hpp" +#include +#include +#include using cubos::core::ecs::Name; using cubos::core::ecs::World; @@ -18,8 +16,6 @@ using cubos::core::memory::AnyValue; using cubos::core::reflection::reflect; using cubos::core::reflection::Type; -using cubos::engine::Cubos; -using cubos::engine::DataInspector; using cubos::engine::Entity; using cubos::engine::Opt; using cubos::engine::Query; @@ -90,18 +86,18 @@ static void addRelationButton(State& state, World& world, Entity entity, bool in } } -void tesseratos::entityInspectorPlugin(Cubos& cubos) +void cubos::engine::entityInspectorPlugin(Cubos& cubos) { - cubos.depends(cubos::engine::imguiPlugin); - cubos.depends(entitySelectorPlugin); + cubos.depends(imguiPlugin); + cubos.depends(selectionPlugin); cubos.depends(toolboxPlugin); cubos.resource(); cubos.system("show Entity Inspector UI") - .tagged(cubos::engine::imguiTag) - .call([](State& state, World& world, Toolbox& toolbox, const EntitySelector& entitySelector, - DataInspector& dataInspector, Query> query) { + .tagged(imguiTag) + .call([](State& state, World& world, Toolbox& toolbox, const Selection& selection, DataInspector& dataInspector, + Query> query) { if (!toolbox.isOpen("Entity Inspector")) { return; @@ -124,7 +120,7 @@ void tesseratos::entityInspectorPlugin(Cubos& cubos) ImGui::Begin("Entity Inspector"); if (!ImGui::IsWindowCollapsed()) { - auto entity = entitySelector.selection; + auto entity = selection.entity; if (!entity.isNull() && world.isAlive(entity)) { ImGui::Text("Entity %s selected", getName(entity).c_str()); diff --git a/tools/tesseratos/src/tesseratos/metrics_panel/plugin.cpp b/engine/src/tools/metrics_panel/plugin.cpp similarity index 92% rename from tools/tesseratos/src/tesseratos/metrics_panel/plugin.cpp rename to engine/src/tools/metrics_panel/plugin.cpp index 92f2291bc..28b2b34c6 100644 --- a/tools/tesseratos/src/tesseratos/metrics_panel/plugin.cpp +++ b/engine/src/tools/metrics_panel/plugin.cpp @@ -1,4 +1,3 @@ -#include "plugin.hpp" #include #include //Included for the accumulated/max_element funcs @@ -6,11 +5,8 @@ #include #include - -#include "../toolbox/plugin.hpp" - -using cubos::engine::Cubos; -using cubos::engine::DeltaTime; +#include +#include namespace { @@ -30,14 +26,15 @@ namespace }; } // namespace -void tesseratos::metricsPanelPlugin(Cubos& cubos) +void cubos::engine::metricsPanelPlugin(Cubos& cubos) { - cubos.depends(cubos::engine::imguiPlugin); + cubos.depends(imguiPlugin); cubos.depends(toolboxPlugin); + cubos.resource(); cubos.system("show Metrics UI") - .tagged(cubos::engine::imguiTag) + .tagged(imguiTag) .call([](Toolbox& toolbox, const DeltaTime& deltaTime, Metrics& metrics) { if (!toolbox.isOpen("Metrics Panel")) { diff --git a/engine/src/tools/play_pause/plugin.cpp b/engine/src/tools/play_pause/plugin.cpp new file mode 100644 index 000000000..ee2eebfd7 --- /dev/null +++ b/engine/src/tools/play_pause/plugin.cpp @@ -0,0 +1,66 @@ +#include + +#include +#include +#include + +namespace +{ + struct State + { + CUBOS_ANONYMOUS_REFLECT(State); + + bool paused{false}; + float scale{1.0F}; + }; +} // namespace + +void cubos::engine::playPauseToolPlugin(Cubos& cubos) +{ + cubos.depends(imguiPlugin); + cubos.depends(toolboxPlugin); + + cubos.resource(); + + cubos.system("show Play Pause tool UI").tagged(imguiTag).call([](State& state, Toolbox& toolbox, DeltaTime& dt) { + if (!toolbox.isOpen("Play Pause")) + { + return; + } + + if (ImGui::Begin("Play Pause")) + { + if (ImGui::Button("Play")) + { + state.paused = false; + dt.scale = state.scale; + } + + ImGui::SameLine(); + + if (ImGui::Button("Pause")) + { + state.paused = true; + dt.scale = 0.0; + } + + ImGui::SameLine(); + + ImGui::Text(state.paused ? "(Paused)" : "(Running)"); + + ImGui::SliderFloat("Speed Scale", &state.scale, 0.0F, 5.0F); + + if (ImGui::Button("Reset")) + { + state.scale = 1.0F; + } + + ImGui::End(); + } + + if (!state.paused) + { + dt.scale = state.scale; + } + }); +} diff --git a/engine/src/tools/plugin.cpp b/engine/src/tools/plugin.cpp new file mode 100644 index 000000000..a4d2334ca --- /dev/null +++ b/engine/src/tools/plugin.cpp @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void cubos::engine::toolsPlugin(Cubos& cubos) +{ + // For readability purposes, plugins are divided into blocks based on their dependencies. + // The first block contains plugins without dependencies. + // The second block contains plugins which depend on plugins from the first block. + // The third block contains plugins which depend on plugins from the first and second blocks. + // And so on. + + cubos.plugin(toolboxPlugin); + cubos.plugin(selectionPlugin); + + cubos.plugin(entityInspectorPlugin); + cubos.plugin(worldInspectorPlugin); + cubos.plugin(debugCameraPlugin); + cubos.plugin(settingsInspectorPlugin); + cubos.plugin(metricsPanelPlugin); + cubos.plugin(colliderGizmosPlugin); + cubos.plugin(transformGizmoPlugin); + cubos.plugin(playPauseToolPlugin); + cubos.plugin(ecsStatisticsPlugin); + cubos.plugin(consolePlugin); +} diff --git a/engine/src/tools/selection/plugin.cpp b/engine/src/tools/selection/plugin.cpp new file mode 100644 index 000000000..ea2f97b97 --- /dev/null +++ b/engine/src/tools/selection/plugin.cpp @@ -0,0 +1,53 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +using cubos::core::ecs::World; + +void cubos::engine::selectionPlugin(Cubos& cubos) +{ + cubos.depends(imguiPlugin); + cubos.depends(renderTargetPlugin); + cubos.depends(renderPickerPlugin); + + cubos.resource(); + + cubos.system("select entities on mouse click") + .after(drawToRenderPickerTag) + .call([](Query pickers, const World& world, Selection& selection) { + if (ImGui::GetIO().WantCaptureMouse) + { + return; + } + + if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) + { + for (auto [picker, target] : pickers) + { + // Find the render picker for the main window (nullptr framebuffer) + if (target.framebuffer == nullptr) + { + uint32_t entityId = picker.read(static_cast(ImGui::GetMousePos().x), + static_cast(ImGui::GetMousePos().y)); + + if (entityId == UINT32_MAX) + { + selection.entity = Entity{}; + } + else if (entityId < static_cast(1 << 31)) + { + selection.entity = Entity{entityId, world.generation(entityId)}; + } + + break; + } + } + } + }); +} diff --git a/engine/src/tools/selection/selection.cpp b/engine/src/tools/selection/selection.cpp new file mode 100644 index 000000000..3214cf568 --- /dev/null +++ b/engine/src/tools/selection/selection.cpp @@ -0,0 +1,10 @@ +#include + +#include + +CUBOS_REFLECT_IMPL(cubos::engine::Selection) +{ + return cubos::core::ecs::TypeBuilder("cubos::engine::::Selection") + .withField("entity", &Selection::entity) + .build(); +} diff --git a/tools/tesseratos/src/tesseratos/settings_inspector/plugin.cpp b/engine/src/tools/settings_inspector/plugin.cpp similarity index 72% rename from tools/tesseratos/src/tesseratos/settings_inspector/plugin.cpp rename to engine/src/tools/settings_inspector/plugin.cpp index d9601548b..a4b473186 100644 --- a/tools/tesseratos/src/tesseratos/settings_inspector/plugin.cpp +++ b/engine/src/tools/settings_inspector/plugin.cpp @@ -1,5 +1,3 @@ -#include "plugin.hpp" - #include #include @@ -9,23 +7,17 @@ #include #include #include +#include +#include -#include "../toolbox/plugin.hpp" - -using cubos::core::reflection::reflect; - -using cubos::engine::Cubos; -using cubos::engine::DataInspector; -using cubos::engine::Settings; - -void tesseratos::settingsInspectorPlugin(Cubos& cubos) +void cubos::engine::settingsInspectorPlugin(Cubos& cubos) { - cubos.depends(cubos::engine::settingsPlugin); - cubos.depends(cubos::engine::imguiPlugin); + cubos.depends(settingsPlugin); + cubos.depends(imguiPlugin); cubos.depends(toolboxPlugin); cubos.system("show Settings Inspector UI") - .tagged(cubos::engine::imguiTag) + .tagged(imguiTag) .call([](Settings& settings, DataInspector& inspector, Toolbox& toolbox) { if (!toolbox.isOpen("Settings Inspector")) { diff --git a/engine/src/tools/toolbox/plugin.cpp b/engine/src/tools/toolbox/plugin.cpp new file mode 100644 index 000000000..81a31468f --- /dev/null +++ b/engine/src/tools/toolbox/plugin.cpp @@ -0,0 +1,30 @@ +#include + +#include +#include + +void cubos::engine::toolboxPlugin(Cubos& cubos) +{ + cubos.depends(imguiPlugin); + + cubos.resource(); + + cubos.system("show Toolbox UI").tagged(imguiTag).call([](Toolbox& toolbox) { + if (!ImGui::Begin("Toolbox")) + { + ImGui::End(); + return; + } + + for (const auto& [tool, open] : toolbox) + { + bool check = open; + if (ImGui::Checkbox(data(tool), &check)) + { + toolbox.toggle(tool); + } + } + + ImGui::End(); + }); +} diff --git a/engine/src/tools/toolbox/toolbox.cpp b/engine/src/tools/toolbox/toolbox.cpp new file mode 100644 index 000000000..934e22b29 --- /dev/null +++ b/engine/src/tools/toolbox/toolbox.cpp @@ -0,0 +1,35 @@ +#include + +#include + +using namespace cubos::engine; + +CUBOS_REFLECT_IMPL(Toolbox) +{ + return cubos::core::ecs::TypeBuilder("cubos::engine::Toolbox").build(); +} + +bool Toolbox::isOpen(const std::string& toolName) +{ + if (mToolsMap.contains(toolName)) + { + return mToolsMap[toolName]; + } + mToolsMap[toolName] = false; + return false; +} + +void Toolbox::open(const std::string& toolName) +{ + mToolsMap[toolName] = true; +} + +void Toolbox::close(const std::string& toolName) +{ + mToolsMap[toolName] = false; +} + +void Toolbox::toggle(const std::string& toolName) +{ + mToolsMap[toolName] = !mToolsMap[toolName]; +} \ No newline at end of file diff --git a/tools/tesseratos/src/tesseratos/transform_gizmo/plugin.cpp b/engine/src/tools/transform_gizmo/plugin.cpp similarity index 89% rename from tools/tesseratos/src/tesseratos/transform_gizmo/plugin.cpp rename to engine/src/tools/transform_gizmo/plugin.cpp index 932036559..bd4025818 100644 --- a/tools/tesseratos/src/tesseratos/transform_gizmo/plugin.cpp +++ b/engine/src/tools/transform_gizmo/plugin.cpp @@ -1,5 +1,3 @@ -#include "plugin.hpp" - #include #include #include @@ -11,30 +9,15 @@ #include #include #include +#include +#include #include #include -#include "../debug_camera/plugin.hpp" -#include "../entity_selector/plugin.hpp" - -using cubos::core::ecs::Entity; -using cubos::core::ecs::EventReader; -using cubos::core::ecs::Query; using cubos::core::ecs::World; using cubos::core::io::Window; -using cubos::core::memory::Opt; - -using cubos::engine::Camera; -using cubos::engine::Cubos; -using cubos::engine::Gizmos; -using cubos::engine::Input; -using cubos::engine::LocalToWorld; -using cubos::engine::Position; -using cubos::engine::Rotation; -using cubos::engine::Scale; -using cubos::engine::Settings; -using namespace tesseratos; +using namespace cubos::engine; static glm::vec3 intersectLinePlane(glm::vec3 linePoint, glm::vec3 lineVector, glm::vec3 planePoint, glm::vec3 planeNormal) @@ -286,24 +269,24 @@ static void drawRotationGizmo(Query positionQuery, con drawPosition - (forwardVector * 0.01F), 1.4F, 1.25F); } -void tesseratos::transformGizmoPlugin(Cubos& cubos) +void cubos::engine::transformGizmoPlugin(Cubos& cubos) { - cubos.depends(cubos::engine::transformPlugin); - cubos.depends(cubos::engine::gizmosPlugin); - cubos.depends(cubos::engine::inputPlugin); - cubos.depends(cubos::engine::settingsPlugin); - cubos.depends(cubos::engine::cameraPlugin); - cubos.depends(cubos::engine::windowPlugin); + cubos.depends(transformPlugin); + cubos.depends(gizmosPlugin); + cubos.depends(inputPlugin); + cubos.depends(settingsPlugin); + cubos.depends(cameraPlugin); + cubos.depends(windowPlugin); - cubos.depends(entitySelectorPlugin); + cubos.depends(selectionPlugin); cubos.system("draw Transform Gizmo") - .after(cubos::engine::transformUpdateTag) - .call([](const EntitySelector& entitySelector, const Window& window, const Input& input, Settings& settings, + .after(transformUpdateTag) + .call([](const Selection& selection, const Window& window, const Input& input, Settings& settings, Gizmos& gizmos, Query positionQuery, Query rotationQuery, Query cameraQuery) { - if (entitySelector.selection.isNull()) + if (selection.entity.isNull()) { return; } @@ -312,11 +295,11 @@ void tesseratos::transformGizmoPlugin(Cubos& cubos) return; } auto [cameraEnt, camera, cameraLtw] = *cameraQuery.first(); - if (cameraEnt == entitySelector.selection) + if (cameraEnt == selection.entity) { return; } - if (!positionQuery.at(entitySelector.selection)) + if (!positionQuery.at(selection.entity)) { return; } @@ -324,9 +307,9 @@ void tesseratos::transformGizmoPlugin(Cubos& cubos) bool useLocal = settings.getBool("transformGizmo.useLocalAxis", true); double distance = settings.getDouble("transformGizmo.distanceToCamera", 10.0F); - drawPositionGizmo(positionQuery, camera, cameraLtw, gizmos, input, window, entitySelector.selection, - useLocal, distance); - drawRotationGizmo(rotationQuery, camera, cameraLtw, gizmos, input, window, entitySelector.selection, - useLocal, distance); + drawPositionGizmo(positionQuery, camera, cameraLtw, gizmos, input, window, selection.entity, useLocal, + distance); + drawRotationGizmo(rotationQuery, camera, cameraLtw, gizmos, input, window, selection.entity, useLocal, + distance); }); } diff --git a/tools/tesseratos/src/tesseratos/world_inspector/plugin.cpp b/engine/src/tools/world_inspector/plugin.cpp similarity index 75% rename from tools/tesseratos/src/tesseratos/world_inspector/plugin.cpp rename to engine/src/tools/world_inspector/plugin.cpp index 5e000e777..619d0e874 100644 --- a/tools/tesseratos/src/tesseratos/world_inspector/plugin.cpp +++ b/engine/src/tools/world_inspector/plugin.cpp @@ -1,4 +1,3 @@ -#include "plugin.hpp" #include #include #include @@ -10,20 +9,16 @@ #include #include +#include +#include +#include #include #include -#include "../entity_selector/plugin.hpp" -#include "../toolbox/plugin.hpp" - using cubos::core::ecs::Name; using cubos::core::ecs::World; -using cubos::engine::ChildOf; -using cubos::engine::Cubos; -using cubos::engine::Entity; -using cubos::engine::Opt; -using cubos::engine::Query; +using namespace cubos::engine; static bool isSingleWord(const std::string& query) { @@ -44,8 +39,7 @@ static bool isValid(const std::string& query) } static void showQueries(World& world, Query> all, const std::string& nameQuery, - const std::vector& components, - tesseratos::EntitySelector& selector) + const std::vector& components, Selection& selection) { auto textColor = (ImVec4)ImColor(255, 255, 255); @@ -68,23 +62,22 @@ static void showQueries(World& world, Query> all, const if (hasComponents && name.contains() && name->value.find(nameQuery) != std::string::npos) { auto displayName = name.contains() ? name->value : std::to_string(entity.index); - selector.selection == entity ? textColor = (ImVec4)ImColor(149, 252, 75) - : textColor = (ImVec4)ImColor(255, 255, 255); + selection.entity == entity ? textColor = (ImVec4)ImColor(149, 252, 75) + : textColor = (ImVec4)ImColor(255, 255, 255); ImGui::PushStyleColor(ImGuiCol_Text, textColor); - ImGui::Selectable((" " + displayName).c_str(), selector.selection == entity); + ImGui::Selectable((" " + displayName).c_str(), selection.entity == entity); ImGui::PopStyleColor(); if (ImGui::IsItemClicked(0)) { - selector.selection = entity; + selection.entity = entity; } } } } -static void parse(World& world, const char* searchBuffer, Query> all, - tesseratos::EntitySelector& selector) +static void parse(World& world, const char* searchBuffer, Query> all, Selection& selection) { std::stringstream ss(searchBuffer); std::string query; // query string @@ -121,29 +114,28 @@ static void parse(World& world, const char* searchBuffer, Query, const ChildOf&, Entity> childOf, - Opt name, tesseratos::EntitySelector& selector) + Opt name, Selection& selection) { auto displayName = name.contains() ? name->value : std::to_string(entity.index); auto children = childOf.pin(1, entity); auto textColor = (ImVec4)ImColor(255, 255, 255); - selector.selection == entity ? textColor = (ImVec4)ImColor(149, 252, 75) - : textColor = (ImVec4)ImColor(255, 255, 255); + selection.entity == entity ? textColor = (ImVec4)ImColor(149, 252, 75) : textColor = (ImVec4)ImColor(255, 255, 255); // check if entity has children if (children.empty()) { ImGui::PushStyleColor(ImGuiCol_Text, textColor); - ImGui::Selectable((" " + displayName).c_str(), selector.selection == entity); + ImGui::Selectable((" " + displayName).c_str(), selection.entity == entity); ImGui::PopStyleColor(); if (ImGui::IsItemClicked(0)) { - selector.selection = entity; + selection.entity = entity; } return; @@ -156,11 +148,11 @@ static void showHierarchy(Entity entity, Query, const C if (ImGui::IsItemClicked(0)) { - selector.selection = entity; + selection.entity = entity; } for (auto [child, nameChild, _, parent] : children) { - showHierarchy(child, childOf, nameChild, selector); + showHierarchy(child, childOf, nameChild, selection); } ImGui::TreePop(); @@ -169,24 +161,22 @@ static void showHierarchy(Entity entity, Query, const C ImGui::PopStyleColor(); } -void tesseratos::worldInspectorPlugin(Cubos& cubos) +void cubos::engine::worldInspectorPlugin(Cubos& cubos) { - cubos.depends(cubos::engine::imguiPlugin); - cubos.depends(cubos::engine::transformPlugin); + cubos.depends(imguiPlugin); + cubos.depends(transformPlugin); cubos.depends(toolboxPlugin); - cubos.depends(entitySelectorPlugin); + cubos.depends(selectionPlugin); cubos.system("show World Inspector UI") - .tagged(cubos::engine::imguiTag) - .call([](World& world, Query> all, + .tagged(imguiTag) + .call([](World& world, Toolbox& toolbox, Selection& selection, Query> all, Query, const ChildOf&, Entity> query) { - if (!(world.resource().isOpen("World Inspector"))) + if (!(toolbox.isOpen("World Inspector"))) { return; } - auto& selector = world.resource(); - ImGui::Begin("World Inspector"); if (!ImGui::IsWindowCollapsed()) @@ -204,7 +194,7 @@ void tesseratos::worldInspectorPlugin(Cubos& cubos) if (searchBuffer[0] != '\0') { - parse(world, searchBuffer, all, selector); + parse(world, searchBuffer, all, selection); } else { @@ -215,7 +205,7 @@ void tesseratos::worldInspectorPlugin(Cubos& cubos) continue; // Skip all entities with parents } - showHierarchy(entity, query, name, selector); + showHierarchy(entity, query, name, selection); } } } diff --git a/tools/tesseratos/CMakeLists.txt b/tools/tesseratos/CMakeLists.txt index f6fb63af3..d709ceb47 100644 --- a/tools/tesseratos/CMakeLists.txt +++ b/tools/tesseratos/CMakeLists.txt @@ -7,20 +7,8 @@ set(TESSERATOS_SOURCE "src/tesseratos/debugger/debugger.cpp" "src/tesseratos/asset_explorer/plugin.cpp" "src/tesseratos/asset_explorer/popup.cpp" - "src/tesseratos/settings_inspector/plugin.cpp" - "src/tesseratos/entity_selector/plugin.cpp" - "src/tesseratos/world_inspector/plugin.cpp" - "src/tesseratos/entity_inspector/plugin.cpp" "src/tesseratos/scene_editor/plugin.cpp" - "src/tesseratos/debug_camera/plugin.cpp" "src/tesseratos/voxel_palette_editor/plugin.cpp" - "src/tesseratos/toolbox/plugin.cpp" - "src/tesseratos/transform_gizmo/plugin.cpp" - "src/tesseratos/metrics_panel/plugin.cpp" - "src/tesseratos/collider_gizmos/plugin.cpp" - "src/tesseratos/play_pause/plugin.cpp" - "src/tesseratos/ecs_statistics/plugin.cpp" - "src/tesseratos/console/plugin.cpp" ) add_executable(tesseratos ${TESSERATOS_SOURCE}) diff --git a/tools/tesseratos/src/tesseratos/asset_explorer/plugin.cpp b/tools/tesseratos/src/tesseratos/asset_explorer/plugin.cpp index bf9270a69..4d544e5b4 100644 --- a/tools/tesseratos/src/tesseratos/asset_explorer/plugin.cpp +++ b/tools/tesseratos/src/tesseratos/asset_explorer/plugin.cpp @@ -5,8 +5,7 @@ #include #include #include - -#include "../toolbox/plugin.hpp" +#include using cubos::core::ecs::EventWriter; @@ -14,6 +13,7 @@ using cubos::engine::AnyAsset; using cubos::engine::Assets; using cubos::engine::Cubos; using cubos::engine::Settings; +using cubos::engine::Toolbox; using namespace tesseratos; @@ -122,7 +122,7 @@ void tesseratos::assetExplorerPlugin(Cubos& cubos) cubos.depends(cubos::engine::imguiPlugin); cubos.depends(cubos::engine::assetsPlugin); - cubos.depends(toolboxPlugin); + cubos.depends(cubos::engine::toolboxPlugin); cubos.system("show Asset Explorer UI") .tagged(cubos::engine::imguiTag) diff --git a/tools/tesseratos/src/tesseratos/asset_explorer/plugin.hpp b/tools/tesseratos/src/tesseratos/asset_explorer/plugin.hpp index e499fc134..7ddb7864d 100644 --- a/tools/tesseratos/src/tesseratos/asset_explorer/plugin.hpp +++ b/tools/tesseratos/src/tesseratos/asset_explorer/plugin.hpp @@ -17,11 +17,6 @@ namespace tesseratos /// /// ## Events /// - @ref AssetSelectedEvent - sent when an asset is selected in the explorer. - /// - /// ## Dependencies - /// - @ref imgui-plugin - /// - @ref assets-plugin - /// - @ref tesseratos-toolbox-plugin /// @brief Event sent when an asset is selected. struct AssetSelectedEvent diff --git a/tools/tesseratos/src/tesseratos/collider_gizmos/plugin.hpp b/tools/tesseratos/src/tesseratos/collider_gizmos/plugin.hpp deleted file mode 100644 index 189110528..000000000 --- a/tools/tesseratos/src/tesseratos/collider_gizmos/plugin.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/// @dir -/// @brief @ref tesseratos-collider-gizmos-plugin plugin directory. - -/// @file -/// @brief Plugin entry point. -/// @ingroup tesseratos-collider-gizmos-plugin - -#pragma once - -#include - -namespace tesseratos -{ - /// @defgroup tesseratos-collider-gizmos-plugin Collider gizmos - /// @ingroup tesseratos - /// @brief Draws gizmos for selected colliders. - /// - /// ## Dependencies - /// - @ref gizmos-plugin - /// - @ref collisions-plugin - /// - @ref tesseratos-toolbox-plugin - - /// @brief Plugin entry function. - /// @param cubos @b Cubos main class - /// @ingroup tesseratos-collider-gizmos-plugin - void colliderGizmosPlugin(cubos::engine::Cubos& cubos); -} // namespace tesseratos diff --git a/tools/tesseratos/src/tesseratos/console/plugin.hpp b/tools/tesseratos/src/tesseratos/console/plugin.hpp deleted file mode 100644 index 0b24ae787..000000000 --- a/tools/tesseratos/src/tesseratos/console/plugin.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/// @dir -/// @brief @ref tesseratos-console-plugin plugin directory. - -/// @file -/// @brief Plugin entry point. -/// @ingroup tesseratos-console-plugin - -#pragma once - -#include - -namespace tesseratos -{ - /// @defgroup tesseratos-console-plugin Console/Logs - /// @ingroup tesseratos - /// @brief Displays Cubos Logs. - /// - /// ## Dependencies - /// - @ref imgui-plugin - /// - @ref log-plugin - - /// @brief Plugin entry function. - /// @param cubos @b CUBOS. main class - /// @ingroup tesseratos-console-plugin - void consolePlugin(cubos::engine::Cubos& cubos); -} // namespace tesseratos \ No newline at end of file diff --git a/tools/tesseratos/src/tesseratos/debug_camera/plugin.hpp b/tools/tesseratos/src/tesseratos/debug_camera/plugin.hpp deleted file mode 100644 index fb95ca107..000000000 --- a/tools/tesseratos/src/tesseratos/debug_camera/plugin.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/// @dir -/// @brief @ref tesseratos-debug-camera-plugin plugin directory. - -/// @file -/// @brief Plugin entry point. -/// @ingroup tesseratos-debug-camera-plugin - -#pragma once - -#include - -namespace tesseratos -{ - /// @defgroup tesseratos-debug-camera-plugin Debug camera - /// @ingroup tesseratos - /// @brief Adds a toggleable debug camera. - /// - /// ## Dependencies - /// - @ref imgui-plugin - /// - @ref renderer-plugin - /// - @ref tesseratos-toolbox-plugin - - /// @brief Plugin entry function. - /// @param cubos @b Cubos main class - /// @ingroup tesseratos-debug-camera-plugin - void debugCameraPlugin(cubos::engine::Cubos& cubos); -} // namespace tesseratos diff --git a/tools/tesseratos/src/tesseratos/debugger/plugin.cpp b/tools/tesseratos/src/tesseratos/debugger/plugin.cpp index 564bfbc5a..1a9cae6bd 100644 --- a/tools/tesseratos/src/tesseratos/debugger/plugin.cpp +++ b/tools/tesseratos/src/tesseratos/debugger/plugin.cpp @@ -4,8 +4,7 @@ #include #include - -#include "../toolbox/plugin.hpp" +#include using cubos::core::net::Address; diff --git a/tools/tesseratos/src/tesseratos/ecs_statistics/plugin.hpp b/tools/tesseratos/src/tesseratos/ecs_statistics/plugin.hpp deleted file mode 100644 index ec9db73f9..000000000 --- a/tools/tesseratos/src/tesseratos/ecs_statistics/plugin.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/// @dir -/// @brief @ref tesseratos-ecs-statistics-plugin plugin directory. - -/// @file -/// @brief Plugin entry point. -/// @ingroup tesseratos-ecs-statistics-plugin - -#pragma once - -#include - -namespace tesseratos -{ - /// @defgroup tesseratos-ecs-statistics-plugin ECS Statistics - /// @ingroup tesseratos - /// @brief Shows tons of statistics and information about the internal state of the ECS. - /// - /// ## Dependencies - /// - @ref imgui-plugin - /// - @ref tesseratos-toolbox-plugin - /// - @ref tesseratos-entity-selector-plugin - - /// @brief Plugin entry function. - /// @param cubos @b Cubos main class - /// @ingroup tesseratos-ecs-statistics-plugin - void ecsStatisticsPlugin(cubos::engine::Cubos& cubos); -} // namespace tesseratos diff --git a/tools/tesseratos/src/tesseratos/entity_inspector/plugin.hpp b/tools/tesseratos/src/tesseratos/entity_inspector/plugin.hpp deleted file mode 100644 index ef3ab7197..000000000 --- a/tools/tesseratos/src/tesseratos/entity_inspector/plugin.hpp +++ /dev/null @@ -1,30 +0,0 @@ -/// @dir -/// @brief @ref tesseratos-entity-inspector-plugin plugin directory. - -/// @file -/// @brief Plugin entry point. -/// @ingroup tesseratos-entity-inspector-plugin - -#pragma once - -#include - -namespace tesseratos -{ - /// @defgroup tesseratos-entity-inspector-plugin Entity inspector - /// @ingroup tesseratos - /// @brief Allows inspecting and modifying the components of the selected entity through a - /// ImGui window. - /// - /// @note The selected entity is identified by the @ref EntitySelector resource. - /// - /// ## Dependencies - /// - @ref imgui-plugin - /// - @ref tesseratos-entity-selector-plugin - /// - @ref tesseratos-toolbox-plugin - - /// @brief Plugin entry function. - /// @param cubos @b Cubos main class - /// @ingroup tesseratos-entity-inspector-plugin - void entityInspectorPlugin(cubos::engine::Cubos& cubos); -} // namespace tesseratos diff --git a/tools/tesseratos/src/tesseratos/entity_selector/plugin.cpp b/tools/tesseratos/src/tesseratos/entity_selector/plugin.cpp deleted file mode 100644 index 745d99c99..000000000 --- a/tools/tesseratos/src/tesseratos/entity_selector/plugin.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "plugin.hpp" - -#include - -#include - -#include -#include -#include -#include -#include -#include - -using cubos::core::ecs::Entity; -using cubos::core::ecs::World; - -using cubos::core::io::MouseButton; -using cubos::core::io::MouseButtonEvent; -using cubos::core::io::MouseMoveEvent; -using cubos::core::io::WindowEvent; - -using cubos::engine::Cubos; -using cubos::engine::EventReader; -using cubos::engine::Query; -using cubos::engine::RenderPicker; -using cubos::engine::RenderTarget; - -using namespace tesseratos; - -CUBOS_REFLECT_IMPL(EntitySelector) -{ - return cubos::core::ecs::TypeBuilder("tesseratos::EntitySelector") - .withField("selection", &EntitySelector::selection) - .build(); -} - -void tesseratos::entitySelectorPlugin(Cubos& cubos) -{ - cubos.depends(cubos::engine::imguiPlugin); - cubos.depends(cubos::engine::windowPlugin); - cubos.depends(cubos::engine::renderTargetPlugin); - cubos.depends(cubos::engine::renderPickerPlugin); - - cubos.resource(); - - cubos.startupSystem("initialize EntitySelector").call([](EntitySelector& entitySelector) { - entitySelector.selection = Entity{}; - entitySelector.lastMousePosition = glm::ivec2{0, 0}; - }); - - cubos.system("process window input for EntitySelector") - .after(cubos::engine::windowPollTag) - .after(cubos::engine::drawToRenderPickerTag) - .call([](Query pickers, EntitySelector& entitySelector, - const World& world, EventReader windowEvent) { - for (const auto& event : windowEvent) - { - if (ImGui::GetIO().WantCaptureMouse) - { - // Consume event but don't do anything - continue; - } - - if (std::holds_alternative(event)) - { - entitySelector.lastMousePosition = std::get(event).position; - } - else if (std::holds_alternative(event)) - { - if (std::get(event).button == cubos::core::io::MouseButton::Left) - { - if (std::get(event).pressed) - { - for (auto [picker, target] : pickers) - { - if (target.framebuffer == nullptr) - { - uint32_t entityId = - picker.read(static_cast(entitySelector.lastMousePosition.x), - static_cast(entitySelector.lastMousePosition.y)); - - if (entityId == UINT32_MAX) - { - entitySelector.selection = Entity{}; - } - else if (entityId < static_cast(1 << 31)) - { - entitySelector.selection = Entity{entityId, world.generation(entityId)}; - } - - break; - } - } - } - } - } - } - }); -} diff --git a/tools/tesseratos/src/tesseratos/entity_selector/plugin.hpp b/tools/tesseratos/src/tesseratos/entity_selector/plugin.hpp deleted file mode 100644 index 95a7b5ac1..000000000 --- a/tools/tesseratos/src/tesseratos/entity_selector/plugin.hpp +++ /dev/null @@ -1,47 +0,0 @@ -/// @dir -/// @brief @ref tesseratos-entity-selector-plugin plugin directory. - -/// @file -/// @brief Plugin entry point. -/// @ingroup tesseratos-entity-selector-plugin - -#pragma once - -#include -#include - -#include - -namespace tesseratos -{ - /// @defgroup tesseratos-entity-selector-plugin Entity selector - /// @ingroup tesseratos - /// @brief Adds a resource used to select an entity. - /// - /// This plugins exists to reduce coupling between plugins. For example, a plugin which allows - /// selecting entities through a ImGui window only needs to depend on this plugin, instead of - /// having to know about all the plugins which care about it. The same applies in the other - /// direction. - /// - /// ## Resources - /// - @ref EntitySelector - identifies the currently selected entity. - /// - /// ## Dependencies - /// - @ref imgui-plugin - /// - @ref screen-picker-plugin - /// - @ref window-plugin - - /// @brief Resource which identifies the currently selected entity. - struct EntitySelector - { - CUBOS_REFLECT; - - cubos::core::ecs::Entity selection; ///< Selected entity, or `null` if none. - glm::ivec2 lastMousePosition; ///< Cursor position. - }; - - /// @brief Plugin entry function. - /// @param cubos @b Cubos main class - /// @ingroup tesseratos-entity-selector-plugin - void entitySelectorPlugin(cubos::engine::Cubos& cubos); -} // namespace tesseratos diff --git a/tools/tesseratos/src/tesseratos/main.cpp b/tools/tesseratos/src/tesseratos/main.cpp index c9c5abe99..e802e3523 100644 --- a/tools/tesseratos/src/tesseratos/main.cpp +++ b/tools/tesseratos/src/tesseratos/main.cpp @@ -4,24 +4,13 @@ #include #include #include +#include #include #include "asset_explorer/plugin.hpp" -#include "collider_gizmos/plugin.hpp" -#include "console/plugin.hpp" -#include "debug_camera/plugin.hpp" #include "debugger/plugin.hpp" -#include "ecs_statistics/plugin.hpp" -#include "entity_inspector/plugin.hpp" -#include "entity_selector/plugin.hpp" -#include "metrics_panel/plugin.hpp" -#include "play_pause/plugin.hpp" #include "scene_editor/plugin.hpp" -#include "settings_inspector/plugin.hpp" -#include "toolbox/plugin.hpp" -#include "transform_gizmo/plugin.hpp" #include "voxel_palette_editor/plugin.hpp" -#include "world_inspector/plugin.hpp" using namespace cubos::engine; using namespace tesseratos; @@ -40,21 +29,10 @@ int main(int argc, char** argv) // The third block contains plugins which depend on plugins from the first and second blocks. // And so on. - cubos.plugin(toolboxPlugin); - cubos.plugin(entitySelectorPlugin); + cubos.plugin(cubos::engine::toolsPlugin); cubos.plugin(debuggerPlugin); cubos.plugin(assetExplorerPlugin); - cubos.plugin(entityInspectorPlugin); - cubos.plugin(worldInspectorPlugin); - cubos.plugin(debugCameraPlugin); - cubos.plugin(settingsInspectorPlugin); - cubos.plugin(metricsPanelPlugin); - cubos.plugin(colliderGizmosPlugin); - cubos.plugin(transformGizmoPlugin); - cubos.plugin(playPausePlugin); - cubos.plugin(ecsStatisticsPlugin); - cubos.plugin(consolePlugin); cubos.plugin(sceneEditorPlugin); cubos.plugin(voxelPaletteEditorPlugin); diff --git a/tools/tesseratos/src/tesseratos/metrics_panel/plugin.hpp b/tools/tesseratos/src/tesseratos/metrics_panel/plugin.hpp deleted file mode 100644 index 727272c7e..000000000 --- a/tools/tesseratos/src/tesseratos/metrics_panel/plugin.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/// @dir -/// @brief @ref tesseratos-metrics-panel-plugin plugin directory. - -/// @file -/// @brief Plugin entry point. -/// @ingroup tesseratos-metrics-panel-plugin - -#pragma once - -#include - -namespace tesseratos -{ - /// @defgroup tesseratos-metrics-panel-plugin Metrics - /// @ingroup tesseratos - /// @brief Shows some useful performance metrics through a ImGui window. - /// - /// ## Dependencies - /// - @ref imgui-plugin - /// - @ref tesseratos-toolbox-plugin - - /// @brief Plugin entry function. - /// @param cubos @b Cubos main class - /// @ingroup tesseratos-metrics-panel-plugin - void metricsPanelPlugin(cubos::engine::Cubos& cubos); -} // namespace tesseratos diff --git a/tools/tesseratos/src/tesseratos/play_pause/plugin.cpp b/tools/tesseratos/src/tesseratos/play_pause/plugin.cpp deleted file mode 100644 index 894bbb927..000000000 --- a/tools/tesseratos/src/tesseratos/play_pause/plugin.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "plugin.hpp" - -#include - -#include - -#include "../toolbox/plugin.hpp" - -using cubos::core::reflection::reflect; - -using cubos::engine::Cubos; -using cubos::engine::DeltaTime; - -namespace -{ - struct State - { - CUBOS_ANONYMOUS_REFLECT(State); - - bool paused{false}; - float scale{1.0F}; - }; -} // namespace - -void tesseratos::playPausePlugin(Cubos& cubos) -{ - cubos.depends(cubos::engine::imguiPlugin); - cubos.depends(toolboxPlugin); - - cubos.resource(); - - cubos.system("show Play Pause UI") - .tagged(cubos::engine::imguiTag) - .call([](State& state, Toolbox& toolbox, DeltaTime& dt) { - if (!toolbox.isOpen("Play Pause")) - { - return; - } - - if (ImGui::Begin("Play Pause")) - { - if (ImGui::Button("Play")) - { - state.paused = false; - dt.scale = state.scale; - } - - ImGui::SameLine(); - - if (ImGui::Button("Pause")) - { - state.paused = true; - dt.scale = 0.0; - } - - ImGui::SameLine(); - - ImGui::Text(state.paused ? "(Paused)" : "(Running)"); - - ImGui::SliderFloat("Speed Scale", &state.scale, 0.0F, 5.0F); - - if (ImGui::Button("Reset")) - { - state.scale = 1.0F; - } - - ImGui::End(); - } - - if (!state.paused) - { - dt.scale = state.scale; - } - }); -} diff --git a/tools/tesseratos/src/tesseratos/play_pause/plugin.hpp b/tools/tesseratos/src/tesseratos/play_pause/plugin.hpp deleted file mode 100644 index c2103374e..000000000 --- a/tools/tesseratos/src/tesseratos/play_pause/plugin.hpp +++ /dev/null @@ -1,26 +0,0 @@ -/// @dir -/// @brief @ref tesseratos-play-pause-plugin plugin directory. - -/// @file -/// @brief Plugin entry point. -/// @ingroup tesseratos-play-pause-plugin - -#pragma once - -#include - -namespace tesseratos -{ - /// @defgroup tesseratos-play-pause-plugin Play Pause - /// @ingroup tesseratos - /// @brief Allows changing the current simulation speed, or even pause it. - /// - /// ## Dependencies - /// - @ref imgui-plugin - /// - @ref tesseratos-toolbox-plugin - - /// @brief Plugin entry function. - /// @param cubos @b Cubos main class - /// @ingroup tesseratos-play-pause-plugin - void playPausePlugin(cubos::engine::Cubos& cubos); -} // namespace tesseratos diff --git a/tools/tesseratos/src/tesseratos/scene_editor/plugin.cpp b/tools/tesseratos/src/tesseratos/scene_editor/plugin.cpp index 10ea4153e..c139dc78f 100644 --- a/tools/tesseratos/src/tesseratos/scene_editor/plugin.cpp +++ b/tools/tesseratos/src/tesseratos/scene_editor/plugin.cpp @@ -13,11 +13,11 @@ #include #include #include +#include +#include #include "../asset_explorer/plugin.hpp" #include "../asset_explorer/popup.hpp" -#include "../entity_selector/plugin.hpp" -#include "../toolbox/plugin.hpp" using cubos::core::ecs::Blueprint; using cubos::core::ecs::convertEntities; @@ -33,6 +33,8 @@ using cubos::engine::Commands; using cubos::engine::Cubos; using cubos::engine::Entity; using cubos::engine::Scene; +using cubos::engine::Selection; +using cubos::engine::Toolbox; using namespace tesseratos; @@ -133,7 +135,7 @@ static int entityNameFilter(ImGuiInputTextCallbackData* data) // Shows the entities within a scene and allows the user to select, add more or remove them. static void showSceneEntities(std::vector>& entities, SceneInfo& scene, - EntitySelector& selector, Commands& cmds, int hierarchyDepth) + Selection& selection, Commands& cmds, int hierarchyDepth) { ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)ImColor(255, 255, 255)); // Add entity to current scene (needs to be root, not a sub scene) @@ -150,7 +152,7 @@ static void showSceneEntities(std::vector>& entit bool removed = false; auto name = entities[i].first; auto handle = entities[i].second; - bool selected = selector.selection == handle; + bool selected = selection.entity == handle; std::string buff = name; std::string id = "##" + name; // Gives the selected entity a different color (bright green) @@ -175,7 +177,7 @@ static void showSceneEntities(std::vector>& entit else if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) { CUBOS_INFO("Selected entity {}", name); - selector.selection = handle; + selection.entity = handle; } if (ImGui::IsMouseClicked(ImGuiMouseButton_Right) && hierarchyDepth == 0) @@ -249,7 +251,7 @@ static void updateNameComponent(SceneInfo& scene, Commands& commands) } // Recursively draws the scene hierarchy and allows the user to remove scenes -static void showSceneHierarchy(SceneInfo& scene, Commands& cmds, EntitySelector& selector, int hierarchyDepth, +static void showSceneHierarchy(SceneInfo& scene, Commands& cmds, Selection& selection, int hierarchyDepth, Assets& assets, State& state) { ImGui::PushID(&scene); @@ -333,7 +335,7 @@ static void showSceneHierarchy(SceneInfo& scene, Commands& cmds, EntitySelector& { // Add entity to current scene (needs to be root, not a sub scene) - showSceneEntities(scene.entities, scene, selector, cmds, hierarchyDepth); + showSceneEntities(scene.entities, scene, selection, cmds, hierarchyDepth); if (hierarchyDepth == 0) { ImGui::Separator(); @@ -364,7 +366,7 @@ static void showSceneHierarchy(SceneInfo& scene, Commands& cmds, EntitySelector& } else { - showSceneHierarchy(*scene.scenes[i], cmds, selector, hierarchyDepth + 1, assets, state); + showSceneHierarchy(*scene.scenes[i], cmds, selection, hierarchyDepth + 1, assets, state); } } for (const auto& i : sceneToRemove) @@ -432,10 +434,10 @@ void tesseratos::sceneEditorPlugin(Cubos& cubos) cubos.depends(cubos::engine::assetsPlugin); cubos.depends(cubos::engine::scenePlugin); cubos.depends(cubos::engine::imguiPlugin); + cubos.depends(cubos::engine::selectionPlugin); + cubos.depends(cubos::engine::toolboxPlugin); - cubos.depends(entitySelectorPlugin); cubos.depends(assetExplorerPlugin); - cubos.depends(toolboxPlugin); cubos.resource(); @@ -457,7 +459,7 @@ void tesseratos::sceneEditorPlugin(Cubos& cubos) cubos.system("show Scene Editor UI") .tagged(cubos::engine::imguiTag) - .call([](const World& world, Assets& assets, Commands cmds, State& state, EntitySelector& selector, + .call([](const World& world, Assets& assets, Commands cmds, State& state, Selection& selection, Toolbox& toolbox) { if (!toolbox.isOpen("Scene Editor")) { @@ -489,7 +491,7 @@ void tesseratos::sceneEditorPlugin(Cubos& cubos) else { ImGui::Separator(); - showSceneHierarchy(state.root, cmds, selector, 0, assets, state); + showSceneHierarchy(state.root, cmds, selection, 0, assets, state); } } diff --git a/tools/tesseratos/src/tesseratos/scene_editor/plugin.hpp b/tools/tesseratos/src/tesseratos/scene_editor/plugin.hpp index 8256d771d..358ec8647 100644 --- a/tools/tesseratos/src/tesseratos/scene_editor/plugin.hpp +++ b/tools/tesseratos/src/tesseratos/scene_editor/plugin.hpp @@ -15,14 +15,8 @@ namespace tesseratos /// @ingroup tesseratos /// @brief Adds a window to edit scenes and select entities in them. /// - /// @note Selected entities are registered in the @ref EntitySelector resource. + /// @note Selected entities are registered in the @ref Selection resource. /// @note The opened scene is identified by the @ref AssetSelectedEvent event. - /// - /// ## Dependencies - /// - @ref scene-plugin - /// - @ref tesseratos-asset-explorer-plugin - /// - @ref tesseratos-entity-selector-plugin - /// - @ref tesseratos-toolbox-plugin /// @brief Plugin entry function. /// @param cubos @b Cubos main class diff --git a/tools/tesseratos/src/tesseratos/settings_inspector/plugin.hpp b/tools/tesseratos/src/tesseratos/settings_inspector/plugin.hpp deleted file mode 100644 index c886f3851..000000000 --- a/tools/tesseratos/src/tesseratos/settings_inspector/plugin.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/// @dir -/// @brief @ref tesseratos-settings-inspector-plugin plugin directory. - -/// @file -/// @brief Plugin entry point. -/// @ingroup tesseratos-settings-inspector-plugin - -#pragma once - -#include - -namespace tesseratos -{ - /// @defgroup tesseratos-settings-inspector-plugin Settings inspector - /// @ingroup tesseratos - /// @brief Allows inspecting the current setting values through a ImGui window. - /// - /// ## Dependencies - /// - @ref settings-plugin - /// - @ref imgui-plugin - /// - @ref tesseratos-toolbox-plugin - - /// @brief Plugin entry function. - /// @param cubos @b Cubos main class - /// @ingroup tesseratos-settings-inspector-plugin - void settingsInspectorPlugin(cubos::engine::Cubos& cubos); -} // namespace tesseratos diff --git a/tools/tesseratos/src/tesseratos/toolbox/plugin.cpp b/tools/tesseratos/src/tesseratos/toolbox/plugin.cpp deleted file mode 100644 index 89e0e39e0..000000000 --- a/tools/tesseratos/src/tesseratos/toolbox/plugin.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "plugin.hpp" - -#include - -#include - -#include - -using cubos::core::ecs::EventWriter; - -using cubos::engine::Cubos; - -using namespace tesseratos; - -CUBOS_REFLECT_IMPL(Toolbox) -{ - return cubos::core::ecs::TypeBuilder("tesseratos::Toolbox").build(); -} - -bool Toolbox::isOpen(const std::string& toolName) -{ - if (mToolsMap.contains(toolName)) - { - return mToolsMap[toolName]; - } - mToolsMap[toolName] = false; - return false; -} - -void Toolbox::open(const std::string& toolName) -{ - mToolsMap[toolName] = true; -} - -void Toolbox::close(const std::string& toolName) -{ - mToolsMap[toolName] = false; -} - -void Toolbox::toggle(const std::string& toolName) -{ - mToolsMap[toolName] = !mToolsMap[toolName]; -} - -static void showToolbox(Toolbox& toolbox) -{ - ImGui::Begin("Toolbox"); - - for (const auto& [tool, open] : toolbox) - { - bool check = open; - if (ImGui::Checkbox(data(tool), &check)) - { - toolbox.toggle(tool); - } - } - - ImGui::End(); -} - -void tesseratos::toolboxPlugin(Cubos& cubos) -{ - cubos.depends(cubos::engine::imguiPlugin); - - cubos.resource(); - - cubos.system("show Toolbox UI").tagged(cubos::engine::imguiTag).call(showToolbox); -} diff --git a/tools/tesseratos/src/tesseratos/voxel_palette_editor/plugin.cpp b/tools/tesseratos/src/tesseratos/voxel_palette_editor/plugin.cpp index 9f4502b86..f5a2a8ea4 100644 --- a/tools/tesseratos/src/tesseratos/voxel_palette_editor/plugin.cpp +++ b/tools/tesseratos/src/tesseratos/voxel_palette_editor/plugin.cpp @@ -9,10 +9,10 @@ #include #include #include +#include #include #include "../asset_explorer/plugin.hpp" -#include "../toolbox/plugin.hpp" using cubos::core::ecs::EventReader; @@ -20,6 +20,7 @@ using cubos::engine::Asset; using cubos::engine::Assets; using cubos::engine::Cubos; using cubos::engine::RenderPalette; +using cubos::engine::Toolbox; using cubos::engine::VoxelMaterial; using cubos::engine::VoxelPalette; @@ -106,9 +107,9 @@ void tesseratos::voxelPaletteEditorPlugin(Cubos& cubos) cubos.depends(cubos::engine::renderVoxelsPlugin); cubos.depends(cubos::engine::imguiPlugin); cubos.depends(cubos::engine::voxelsPlugin); + cubos.depends(cubos::engine::toolboxPlugin); cubos.depends(assetExplorerPlugin); - cubos.depends(toolboxPlugin); cubos.resource(); diff --git a/tools/tesseratos/src/tesseratos/voxel_palette_editor/plugin.hpp b/tools/tesseratos/src/tesseratos/voxel_palette_editor/plugin.hpp index 677e1f118..3612230b1 100644 --- a/tools/tesseratos/src/tesseratos/voxel_palette_editor/plugin.hpp +++ b/tools/tesseratos/src/tesseratos/voxel_palette_editor/plugin.hpp @@ -14,9 +14,6 @@ namespace tesseratos /// @defgroup tesseratos-voxel-palette-editor-plugin Palette editor /// @ingroup tesseratos /// @brief Allows the user to open and inspect/edit a palette asset. - /// - /// ## Dependencies - /// - @ref tesseratos-toolbox-plugin /// @brief Plugin entry function. /// @param cubos @b Cubos main class diff --git a/tools/tesseratos/src/tesseratos/world_inspector/plugin.hpp b/tools/tesseratos/src/tesseratos/world_inspector/plugin.hpp deleted file mode 100644 index 82608eedf..000000000 --- a/tools/tesseratos/src/tesseratos/world_inspector/plugin.hpp +++ /dev/null @@ -1,30 +0,0 @@ -/// @dir -/// @brief @ref tesseratos-world-inspector-plugin plugin directory. - -/// @file -/// @brief Plugin entry point. -/// @ingroup tesseratos-world-inspector-plugin - -#pragma once - -#include - -namespace tesseratos -{ - /// @defgroup tesseratos-world-inspector-plugin World inspector - /// @ingroup tesseratos - /// @brief Shows all of the entities in the world through a ImGui window, and allows selecting - /// them. - /// - /// @note Selected entities are identified by the @ref EntitySelector resource. - /// - /// ## Dependencies - /// - @ref imgui-plugin - /// - @ref tesseratos-entity-selector-plugin - /// - @ref tesseratos-toolbox-plugin - - /// @brief Plugin entry function. - /// @param cubos @b Cubos main class - /// @ingroup tesseratos-world-inspector-plugin - void worldInspectorPlugin(cubos::engine::Cubos& cubos); -} // namespace tesseratos From 29100058647ce89e746380558ca097c035b8ec11 Mon Sep 17 00:00:00 2001 From: Ricardo Antunes Date: Fri, 27 Sep 2024 11:53:19 +0200 Subject: [PATCH 2/7] feat(data): add StandardArchive::initialized --- core/include/cubos/core/data/fs/standard_archive.hpp | 4 ++++ core/src/data/fs/standard_archive.cpp | 5 +++++ core/tests/data/fs/standard_archive.cpp | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/core/include/cubos/core/data/fs/standard_archive.hpp b/core/include/cubos/core/data/fs/standard_archive.hpp index 46f020d32..c3913bdd7 100644 --- a/core/include/cubos/core/data/fs/standard_archive.hpp +++ b/core/include/cubos/core/data/fs/standard_archive.hpp @@ -35,6 +35,10 @@ namespace cubos::core::data /// @param readOnly True if the archive is read-only, false otherwise. StandardArchive(const std::filesystem::path& osPath, bool isDirectory, bool readOnly); + /// @brief Checks if the archive was successfully initialized. + /// @return True if the archive was successfully initialized, false otherwise. + bool initialized() const; + std::size_t create(std::size_t parent, std::string_view name, bool directory = false) override; bool destroy(std::size_t id) override; std::string name(std::size_t id) const override; diff --git a/core/src/data/fs/standard_archive.cpp b/core/src/data/fs/standard_archive.cpp index 34cf73e39..32e342d08 100644 --- a/core/src/data/fs/standard_archive.cpp +++ b/core/src/data/fs/standard_archive.cpp @@ -109,6 +109,11 @@ void StandardArchive::generate(std::size_t parent) } } +bool StandardArchive::initialized() const +{ + return !mFiles.empty(); +} + std::size_t StandardArchive::create(std::size_t parent, std::string_view name, bool directory) { INIT_OR_RETURN(0); diff --git a/core/tests/data/fs/standard_archive.cpp b/core/tests/data/fs/standard_archive.cpp index e2ec5abf7..9ef878908 100644 --- a/core/tests/data/fs/standard_archive.cpp +++ b/core/tests/data/fs/standard_archive.cpp @@ -16,6 +16,7 @@ using cubos::core::memory::Stream; static void assertInitializationFailed(StandardArchive& archive) { REQUIRE_FALSE(archive.directory(1)); // Independently of it was created as a directory or not. + REQUIRE_FALSE(archive.initialized()); REQUIRE(archive.parent(1) == 0); REQUIRE(archive.sibling(1) == 0); REQUIRE(archive.child(1) == 0); @@ -62,6 +63,7 @@ TEST_CASE("data::StandardArchive") // NOLINT(readability-function-size) // Check if the structure is correct. CHECK(archive.readOnly() == readOnly); + CHECK(archive.initialized()); CHECK(archive.parent(1) == 0); CHECK(archive.sibling(1) == 0); CHECK(archive.child(1) == 0); @@ -133,6 +135,7 @@ TEST_CASE("data::StandardArchive") // NOLINT(readability-function-size) { archive = std::make_unique(path, true, false); CHECK_FALSE(archive->readOnly()); + CHECK(archive->initialized()); // Check initial structure. CHECK(archive->parent(1) == 0); @@ -220,6 +223,7 @@ TEST_CASE("data::StandardArchive") // NOLINT(readability-function-size) // Create a read-only archive on the generated directory. archive = std::make_unique(path, true, true); CHECK(archive->readOnly()); + CHECK(archive->initialized()); // Check root. CHECK(archive->directory(1)); From d3ce06a8765db3ecf56727f200083975c518c5fe Mon Sep 17 00:00:00 2001 From: Ricardo Antunes Date: Fri, 27 Sep 2024 11:54:05 +0200 Subject: [PATCH 3/7] feat(thread): add Task finish constructor --- core/include/cubos/core/thread/task.hpp | 9 +++++++++ core/tests/thread/task.cpp | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/core/include/cubos/core/thread/task.hpp b/core/include/cubos/core/thread/task.hpp index e54fb8ed1..464a025cc 100644 --- a/core/include/cubos/core/thread/task.hpp +++ b/core/include/cubos/core/thread/task.hpp @@ -29,6 +29,15 @@ namespace cubos::core::thread mData = new Data(); } + /// @brief Constructs a finished task. + /// @param value Task result. + /// @return Task. + Task(T value) + : Task{} + { + this->finish(std::move(value)); + } + /// @brief Copy constructs. /// @param other Task. Task(const Task& other) diff --git a/core/tests/thread/task.cpp b/core/tests/thread/task.cpp index d392336c3..6f5801278 100644 --- a/core/tests/thread/task.cpp +++ b/core/tests/thread/task.cpp @@ -10,6 +10,13 @@ using cubos::core::thread::Task; TEST_CASE("thread::Task") { + SUBCASE("finished task") + { + Task task{42}; + REQUIRE(task.isDone()); + REQUIRE(task.result() == 42); + } + SUBCASE("task which produces an int") { Task task{}; From 0a6e088ebe874cd6ee5e926f482f3717a93b42fe Mon Sep 17 00:00:00 2001 From: Ricardo Antunes Date: Fri, 27 Sep 2024 13:03:16 +0200 Subject: [PATCH 4/7] feat(assets): allow unloading a metadata directory --- engine/include/cubos/engine/assets/assets.hpp | 8 ++++++ engine/src/assets/assets.cpp | 24 +++++++++++++++++ engine/src/assets/bridges/file.cpp | 27 +++++++++++++------ 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/engine/include/cubos/engine/assets/assets.hpp b/engine/include/cubos/engine/assets/assets.hpp index 6cfcb38ef..0419572f6 100644 --- a/engine/include/cubos/engine/assets/assets.hpp +++ b/engine/include/cubos/engine/assets/assets.hpp @@ -87,6 +87,14 @@ namespace cubos::engine /// @param path Path to load metadata from. void loadMeta(std::string_view path); + /// @brief Unloads all asset metadata from assets within the given path. + /// + /// If an asset from the given path is currently loaded, it will not be unloaded, but it will be dissociated + /// from its original metadata path. + /// + /// @param path Path to unload metadata from. + void unloadMeta(std::string_view path); + /// @brief Loads the asset with the given handle, upgrading the handle to a strong one. /// /// This method doesn't block, thus the asset may have not yet been loaded when it returns. diff --git a/engine/src/assets/assets.cpp b/engine/src/assets/assets.cpp index fa3412c12..511d3ce06 100644 --- a/engine/src/assets/assets.cpp +++ b/engine/src/assets/assets.cpp @@ -181,6 +181,30 @@ void Assets::loadMeta(std::string_view path) } } +void Assets::unloadMeta(std::string_view path) +{ + std::unique_lock lock(mMutex); + + // Search for assets that have the given path as a prefix and remove the path from their metadata. + std::vector toRemove; + for (auto& [id, entry] : mEntries) + { + std::unique_lock lock(entry->mutex); + + if (auto metaPath = entry->meta.get("path")) + { + if (metaPath->starts_with(path)) + { + entry->meta.remove("path"); + if (entry->status == Status::Unloaded || entry->status == Status::Unknown) + { + toRemove.push_back(id); + } + } + } + } +} + AnyAsset Assets::load(AnyAsset handle) const { auto assetEntry = this->entry(handle); diff --git a/engine/src/assets/bridges/file.cpp b/engine/src/assets/bridges/file.cpp index d891cadfe..d2a0dd764 100644 --- a/engine/src/assets/bridges/file.cpp +++ b/engine/src/assets/bridges/file.cpp @@ -11,17 +11,23 @@ using namespace cubos::engine; bool FileBridge::load(Assets& assets, const AnyAsset& handle) { - auto path = assets.readMeta(handle)->get("path").value(); - auto stream = FileSystem::open(path, File::OpenMode::Read); + auto path = assets.readMeta(handle)->get("path"); + if (!path.has_value()) + { + CUBOS_ERROR("Asset does not have a file path"); + return false; + } + + auto stream = FileSystem::open(*path, File::OpenMode::Read); if (stream == nullptr) { - CUBOS_ERROR("Could not open file {}", path); + CUBOS_ERROR("Could not open file {}", *path); return false; } if (!this->loadFromFile(assets, handle, *stream)) { - CUBOS_ERROR("Could not load asset from file {}", path); + CUBOS_ERROR("Could not load asset from file {}", *path); return false; } @@ -30,9 +36,14 @@ bool FileBridge::load(Assets& assets, const AnyAsset& handle) bool FileBridge::save(const Assets& assets, const AnyAsset& handle) { - auto path = assets.readMeta(handle)->get("path").value(); + auto path = assets.readMeta(handle)->get("path"); + if (!path.has_value()) + { + CUBOS_ERROR("Asset does not have a file path"); + return false; + } - auto swpPath = path + ".swp"; + auto swpPath = *path + ".swp"; auto swpFile = FileSystem::create(swpPath); if (swpFile == nullptr) @@ -58,9 +69,9 @@ bool FileBridge::save(const Assets& assets, const AnyAsset& handle) stream = nullptr; /// @todo This can be done simpler with #737. - if (!FileSystem::copy(swpPath, path)) + if (!FileSystem::copy(swpPath, *path)) { - CUBOS_ERROR("Could not overwrite asset {} with swap file", path); + CUBOS_ERROR("Could not overwrite asset {} with swap file", *path); return false; } From ac1f364589bec562e4e8bfa71870960a3fe8855d Mon Sep 17 00:00:00 2001 From: Ricardo Antunes Date: Fri, 27 Sep 2024 17:49:12 +0200 Subject: [PATCH 5/7] feat(thread): add Process --- CHANGELOG.md | 1 + core/CMakeLists.txt | 1 + core/include/cubos/core/thread/process.hpp | 58 ++++++ core/src/thread/process.cpp | 197 +++++++++++++++++++++ 4 files changed, 257 insertions(+) create mode 100644 core/include/cubos/core/thread/process.hpp create mode 100644 core/src/thread/process.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index fee7ea5af..4e0337f44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Generic Camera component to hold projection matrix (#1331, **@mkuritsu**). - Initial application debugging through Tesseratos (#1303, **@RiscadoA**). - Print stacktrace with *cpptrace* on calls to CUBOS_FAIL (#1172, **@RiscadoA**). +- Simple cross-platform multi-process utilities (**@RiscadoA**). ### Changed diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index 9cd7af533..4acb58c20 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -31,6 +31,7 @@ set(CUBOS_CORE_SOURCE "src/metrics.cpp" "src/thread/pool.cpp" + "src/thread/process.cpp" "src/thread/task.cpp" "src/memory/stream.cpp" diff --git a/core/include/cubos/core/thread/process.hpp b/core/include/cubos/core/thread/process.hpp new file mode 100644 index 000000000..fe006d201 --- /dev/null +++ b/core/include/cubos/core/thread/process.hpp @@ -0,0 +1,58 @@ +/// @file +/// @brief Class @ref cubos::core::thread::Process. +/// @ingroup core-thread + +#pragma once + +#include +#include + +#include + +namespace cubos::core::thread +{ + /// @brief Provides a cross-platform way to spawn child processes. + /// @ingroup core-thread + class Process final + { + public: + CUBOS_REFLECT; + + ~Process(); + + /// @brief Default constructor. + Process() = default; + + /// @brief Move constructor. + Process(Process&& other) noexcept; + + /// @brief Move assignment operator. + Process& operator=(Process&& other) noexcept; + + /// @brief Starts a new process. + /// @param command Command to execute. + /// @param args Arguments to pass to the command. + /// @param cwd Working directory for the new process. + /// @return Whether the process was started successfully. + bool start(const std::string& command, const std::vector& args = {}, const std::string& cwd = ""); + + /// @brief Kills the process. + void kill(); + + /// @brief Waits for the process to finish. + /// @return Whether the process exited normally. + bool wait(); + + /// @brief Waits for the process to finish. + /// @param status Exit code of the process, if it exited normally. + /// @return Whether the process exited normally. + bool wait(int& status); + + /// @brief Checks whether the process has been started. + /// @return Whether the process has been started. + bool started() const; + + private: + void* mHandle{nullptr}; + }; +} // namespace cubos::core::thread diff --git a/core/src/thread/process.cpp b/core/src/thread/process.cpp new file mode 100644 index 000000000..8db4fbcb7 --- /dev/null +++ b/core/src/thread/process.cpp @@ -0,0 +1,197 @@ +#include +#include +#include +#include +#include +#include +#include + +using cubos::core::thread::Process; + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#else +#include +#include + +#include +#include +#include +#endif + +CUBOS_REFLECT_IMPL(Process) +{ + return reflection::Type::create("cubos::core::thread::Process") + .with(reflection::ConstructibleTrait::typed().withDefaultConstructor().withMoveConstructor().build()); +} + +Process::~Process() +{ + this->kill(); + this->wait(); +} + +Process::Process(Process&& other) noexcept + : mHandle{other.mHandle} +{ + other.mHandle = nullptr; +} + +Process& Process::operator=(Process&& other) noexcept +{ + if (this == &other) + { + return *this; + } + + this->wait(); + mHandle = other.mHandle; + other.mHandle = nullptr; + return *this; +} + +bool Process::start(const std::string& command, const std::vector& args, const std::string& cwd) +{ + this->wait(); + +#ifdef _WIN32 + // Launch the binary with appropriate arguments. + std::string finalCommand = command; + for (const auto& arg : args) + { + finalCommand += " " + arg; + } + STARTUPINFOA si = {sizeof(si)}; + PROCESS_INFORMATION pi; + if (!CreateProcessA(nullptr, const_cast(finalCommand.c_str()), nullptr, nullptr, FALSE, 0, nullptr, + cwd.empty() ? nullptr : cwd.c_str(), &si, &pi)) + { + CUBOS_ERROR("Failed to start process {} with error {}", command, GetLastError()); + return false; + } + + mHandle = new PROCESS_INFORMATION{pi}; + CUBOS_INFO("Started process {} with PID {}", command, pi.dwProcessId); +#else + auto pid = fork(); + if (pid == -1) + { + CUBOS_ERROR("Failed to fork process"); + return false; + } + + if (pid == 0) // Are we the child process? + { + if (!cwd.empty()) + { + // Change the working directory. + if (chdir(cwd.c_str()) == -1) + { + CUBOS_CRITICAL("Failed to change working directory to {}", cwd); + exit(1); + } + } + + // Launch the binary with appropriate arguments. + std::vector argsCopy = args; + argsCopy.insert(argsCopy.begin(), command); + std::vector argv{}; + argv.reserve(argsCopy.size() + 1); + for (const auto& arg : argsCopy) + { + argv.push_back(const_cast(arg.c_str())); + } + argv.push_back(nullptr); + execvp(command.c_str(), argv.data()); + + // If we reach this point, execv failed. Get the error message and log it. + CUBOS_CRITICAL("Failed to start process {} with error {}", command, strerror(errno)); + exit(1); + } + + // We are the parent process. + mHandle = new pid_t{pid}; + CUBOS_INFO("Started process {} with PID {}", command, pid); +#endif + + return true; +} + +void Process::kill() +{ + if (mHandle == nullptr) + { + return; + } + +#ifdef _WIN32 + auto* pi = static_cast(mHandle); + ::TerminateProcess(pi->hProcess, 1); + CUBOS_DEBUG("Process {} killed", pi->hProcess); +#else + auto* pid = static_cast(mHandle); + ::kill(*pid, SIGKILL); + CUBOS_DEBUG("Process {} killed", *pid); +#endif +} + +bool Process::wait() +{ + int status; + return this->wait(status); +} + +bool Process::wait(int& status) +{ + if (mHandle == nullptr) + { + return false; + } + +#ifdef _WIN32 + auto* pi = static_cast(mHandle); + mHandle = nullptr; + + ::WaitForSingleObject(pi->hProcess, INFINITE); + + DWORD exitCode; + GetExitCodeProcess(pi->hProcess, &exitCode); + status = static_cast(exitCode); + CUBOS_DEBUG("Process {} exited with status {}", pi->hProcess, status); + + ::CloseHandle(pi->hProcess); + ::CloseHandle(pi->hThread); + delete pi; + + return true; +#else + auto pid = *static_cast(mHandle); + delete static_cast(mHandle); + mHandle = nullptr; + + int waitStatus; + ::waitpid(pid, &waitStatus, 0); + + if (WIFEXITED(waitStatus)) + { + status = WEXITSTATUS(waitStatus); + CUBOS_DEBUG("Process {} exited with status {}", pid, status); + return true; + } + + if (WIFSIGNALED(waitStatus)) + { + CUBOS_WARN("Process {} terminated by signal {}", pid, WTERMSIG(waitStatus)); + return false; + } + + CUBOS_WARN("Process {} terminated abnormally", pid); + return false; +#endif +} + +bool Process::started() const +{ + return mHandle != nullptr; +} From 4953e6779bc30d73e82793ced918de62af4299fb Mon Sep 17 00:00:00 2001 From: Ricardo Antunes Date: Fri, 27 Sep 2024 12:34:46 +0200 Subject: [PATCH 6/7] feat(tesseratos): add Project plugin --- CHANGELOG.md | 1 + tools/tesseratos/CMakeLists.txt | 2 + tools/tesseratos/src/tesseratos/main.cpp | 3 + .../src/tesseratos/project/manager.cpp | 145 ++++++++++++++++++ .../src/tesseratos/project/manager.hpp | 115 ++++++++++++++ .../src/tesseratos/project/plugin.cpp | 85 ++++++++++ .../src/tesseratos/project/plugin.hpp | 24 +++ 7 files changed, 375 insertions(+) create mode 100644 tools/tesseratos/src/tesseratos/project/manager.cpp create mode 100644 tools/tesseratos/src/tesseratos/project/manager.hpp create mode 100644 tools/tesseratos/src/tesseratos/project/plugin.cpp create mode 100644 tools/tesseratos/src/tesseratos/project/plugin.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e0337f44..3a9db5937 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Initial application debugging through Tesseratos (#1303, **@RiscadoA**). - Print stacktrace with *cpptrace* on calls to CUBOS_FAIL (#1172, **@RiscadoA**). - Simple cross-platform multi-process utilities (**@RiscadoA**). +- Project opening and closing on Tesseratos (#1218, **@RiscadoA**). ### Changed diff --git a/tools/tesseratos/CMakeLists.txt b/tools/tesseratos/CMakeLists.txt index d709ceb47..cf2fc5677 100644 --- a/tools/tesseratos/CMakeLists.txt +++ b/tools/tesseratos/CMakeLists.txt @@ -5,6 +5,8 @@ set(TESSERATOS_SOURCE "src/tesseratos/main.cpp" "src/tesseratos/debugger/plugin.cpp" "src/tesseratos/debugger/debugger.cpp" + "src/tesseratos/project/plugin.cpp" + "src/tesseratos/project/manager.cpp" "src/tesseratos/asset_explorer/plugin.cpp" "src/tesseratos/asset_explorer/popup.cpp" "src/tesseratos/scene_editor/plugin.cpp" diff --git a/tools/tesseratos/src/tesseratos/main.cpp b/tools/tesseratos/src/tesseratos/main.cpp index e802e3523..95a2c9fbd 100644 --- a/tools/tesseratos/src/tesseratos/main.cpp +++ b/tools/tesseratos/src/tesseratos/main.cpp @@ -9,6 +9,7 @@ #include "asset_explorer/plugin.hpp" #include "debugger/plugin.hpp" +#include "project/plugin.hpp" #include "scene_editor/plugin.hpp" #include "voxel_palette_editor/plugin.hpp" @@ -34,6 +35,8 @@ int main(int argc, char** argv) cubos.plugin(debuggerPlugin); cubos.plugin(assetExplorerPlugin); + cubos.plugin(projectPlugin); + cubos.plugin(sceneEditorPlugin); cubos.plugin(voxelPaletteEditorPlugin); diff --git a/tools/tesseratos/src/tesseratos/project/manager.cpp b/tools/tesseratos/src/tesseratos/project/manager.cpp new file mode 100644 index 000000000..f1c28590d --- /dev/null +++ b/tools/tesseratos/src/tesseratos/project/manager.cpp @@ -0,0 +1,145 @@ +#include "manager.hpp" +#include + +#include +#include +#include +#include +#include +#include +#include + +using cubos::core::data::FileSystem; +using cubos::core::data::StandardArchive; +using cubos::core::net::Address; + +CUBOS_REFLECT_IMPL(tesseratos::ProjectManager::State) +{ + using namespace cubos::core::reflection; + return Type::create("tesseratos::ProjectManager::State") + .with(ConstructibleTrait::typed().withMoveConstructor().build()); +} + +tesseratos::ProjectManager::ProjectManager(State& state, cubos::engine::Assets& assets, Debugger& debugger) + : mState(state) + , mAssets(assets) + , mDebugger(debugger) +{ +} + +bool tesseratos::ProjectManager::open(std::string projectOSPath, std::string binaryOSPath) +{ + if (projectOSPath.empty()) + { + CUBOS_ERROR("Project path is empty"); + return false; + } + + this->close(); + + // Prepare the project directory for mounting. + auto archive = std::make_unique(projectOSPath, /*isDirectory=*/true, /*readOnly=*/false); + if (!archive->initialized()) + { + CUBOS_ERROR("Could not open project at {}", projectOSPath); + return false; + } + + if (!FileSystem::mount("/project", std::move(archive))) + { + CUBOS_ERROR("Could not mount project archive to /project"); + return false; + } + + // Load asset metadata from the project assets directory. + mAssets.loadMeta("/project/assets"); + + // We managed to open the project's directory, store the paths. + mState.mProjectOSPath = std::move(projectOSPath); + mState.mBinaryOSPath = std::move(binaryOSPath); + + // Try to launch the project. + // If we can't, we can still keep the project open, but we won't be able to use its types. + this->launch(); + + return true; +} + +bool tesseratos::ProjectManager::open() const +{ + return !mState.mProjectOSPath.empty(); +} + +void tesseratos::ProjectManager::close() +{ + if (mState.mProjectOSPath.empty()) + { + return; + } + + this->terminate(); + + // Unload asset metadata from the project. + mAssets.unloadMeta("/project/assets"); + + // Unmount its directory from the virtual file system. + if (!FileSystem::unmount("/project")) + { + CUBOS_ERROR("Failed to unmount previously open project directory"); + } + + mState.mProjectOSPath.clear(); +} + +bool tesseratos::ProjectManager::launch() +{ + // Stop the binary if it is already running. + this->terminate(); + + if (!mState.mProcess.start(mState.mBinaryOSPath, {"--debug", std::to_string(mState.mPort)})) + { + CUBOS_ERROR("Could not start project's process at {}", mState.mBinaryOSPath); + return false; + } + + // Try to connect to the child process's debugger. + for (int i = 1, sleep = 100; i <= 3; ++i, sleep *= 2) + { + if (i > 0) + { + CUBOS_WARN("CCould not connect to project's process debugger in try {}, retrying in {} ms", i - 1, sleep); + std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); + } + + if (mDebugger.connect(Address::LocalHost, mState.mPort)) + { + CUBOS_INFO("Successfully connected to project's process debugger in try {}", i); + break; + } + } + + // Check if we successfully connected to the child process's debugger. + // If we didn't, kill the child process. + if (!mDebugger.isConnected()) + { + CUBOS_ERROR("Could not connect to the project's process debugger, terminating the process"); + mState.mProcess.kill(); + return false; + } + + return true; +} + +void tesseratos::ProjectManager::terminate() +{ + if (mDebugger.isConnected()) + { + mDebugger.close(); // Issue a close command to the process' debugger. + } + else + { + mState.mProcess.kill(); + } + + mState.mProcess.wait(); // Wait for the process to finish. +} diff --git a/tools/tesseratos/src/tesseratos/project/manager.hpp b/tools/tesseratos/src/tesseratos/project/manager.hpp new file mode 100644 index 000000000..580752503 --- /dev/null +++ b/tools/tesseratos/src/tesseratos/project/manager.hpp @@ -0,0 +1,115 @@ +/// @file +/// @brief System argument @ref tesseratos::ProjectManager. +/// @ingroup tesseratos-debugger-plugin + +#pragma once + +#include + +#include +#include + +#include + +#include "../debugger/debugger.hpp" + +namespace tesseratos +{ + /// @brief System argument which can be used to manage the currently loaded project. + class ProjectManager + { + public: + CUBOS_REFLECT; + + /// @brief Resource which holds the state of the project manager. + class State; + + /// @brief Constructs. + /// @param state State of the project manager. + /// @param assets Asset manager. + /// @param debugger Debugger. + ProjectManager(State& state, cubos::engine::Assets& assets, Debugger& debugger); + + /// @brief Opens a project directory. + /// + /// The given project directory is mounted in the /project directory in the virtual file system. + /// Unmounts any previously opened project directory. + /// + /// @param projectOSPath Project's directory path in the operating system. + /// @param binaryOSPath Project's binary directory path in the operating system. + /// @return Whether the project could be opened successfully. + bool open(std::string projectOSPath, std::string binaryOSPath); + + /// @brief Checks whether a project is currently open. + /// @return Whether a project is currently open. + bool open() const; + + /// @brief Closes the currently open project. + void close(); + + /// @brief Launches the project's binary and attaches the debugger. + /// + /// If the binary is already running, it is stopped first. + /// + /// @return Whether the project could be launched successfully. + bool launch(); + + /// @brief Stops the project's binary. + void terminate(); + + private: + State& mState; + cubos::engine::Assets& mAssets; + Debugger& mDebugger; + }; + + class ProjectManager::State + { + public: + CUBOS_REFLECT; + + /// @brief Default constructs. + State() = default; + + private: + friend ProjectManager; + + std::string mProjectOSPath{}; + std::string mBinaryOSPath{}; + cubos::core::thread::Process mProcess{}; + uint16_t mPort{9335}; + }; +} // namespace tesseratos + +namespace cubos::core::ecs +{ + template <> + class SystemFetcher + { + public: + static inline constexpr bool ConsumesOptions = false; + + SystemFetcher state; + SystemFetcher assets; + SystemFetcher debugger; + + SystemFetcher(World& world, const SystemOptions& options) + : state{world, options} + , assets{world, options} + , debugger{world, options} + { + } + + void analyze(SystemAccess& access) const + { + state.analyze(access); + assets.analyze(access); + debugger.analyze(access); + } + + tesseratos::ProjectManager fetch(const SystemContext& ctx) + { + return {state.fetch(ctx), assets.fetch(ctx), debugger.fetch(ctx)}; + } + }; +} // namespace cubos::core::ecs diff --git a/tools/tesseratos/src/tesseratos/project/plugin.cpp b/tools/tesseratos/src/tesseratos/project/plugin.cpp new file mode 100644 index 000000000..bf44e0bcc --- /dev/null +++ b/tools/tesseratos/src/tesseratos/project/plugin.cpp @@ -0,0 +1,85 @@ +#include "plugin.hpp" +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "../debugger/plugin.hpp" + +using namespace cubos::core::data; +using namespace cubos::engine; + +void tesseratos::projectPlugin(Cubos& cubos) +{ + cubos.depends(toolboxPlugin); + cubos.depends(imguiPlugin); + cubos.depends(settingsPlugin); + cubos.depends(assetsPlugin); + cubos.depends(debuggerPlugin); + + cubos.resource(); + + cubos.system("show Project") + .tagged(imguiTag) + .call([](ProjectManager project, Toolbox& toolbox, Settings& settings) { + if (!toolbox.isOpen("Project")) + { + return; + } + + if (!ImGui::Begin("Project")) + { + ImGui::End(); + return; + } + + if (!project.open()) + { + // If the project is not open, only show the open dialog. + auto projectOSPath = settings.getString("project.path", ""); + if (ImGui::InputText("Project Path", &projectOSPath)) + { + settings.setString("project.path", projectOSPath); + } + + auto binaryOSPath = settings.getString("project.binary.path", ""); + if (ImGui::InputText("Binary Path", &binaryOSPath)) + { + settings.setString("project.binary.path", binaryOSPath); + } + + if (ImGui::Button("Open") && !project.open(projectOSPath, binaryOSPath)) + { + CUBOS_ERROR("Failed to open project"); + } + + ImGui::End(); + return; + } + + if (ImGui::Button("Launch")) + { + project.launch(); + } + + if (ImGui::Button("Terminate")) + { + project.terminate(); + } + + if (ImGui::Button("Close")) + { + project.close(); + } + + ImGui::End(); + }); +} diff --git a/tools/tesseratos/src/tesseratos/project/plugin.hpp b/tools/tesseratos/src/tesseratos/project/plugin.hpp new file mode 100644 index 000000000..4ded20a54 --- /dev/null +++ b/tools/tesseratos/src/tesseratos/project/plugin.hpp @@ -0,0 +1,24 @@ +/// @dir +/// @brief @ref tesseratos-project-plugin plugin directory. + +/// @file +/// @brief Plugin entry point. +/// @ingroup tesseratos-project-plugin + +#pragma once + +#include + +#include "manager.hpp" + +namespace tesseratos +{ + /// @defgroup tesseratos-project-plugin Project + /// @ingroup tesseratos + /// @brief Adds a resource used to manage the currently loaded project. + + /// @brief Plugin entry function. + /// @param cubos @b Cubos main class + /// @ingroup tesseratos-project-plugin + void projectPlugin(cubos::engine::Cubos& cubos); +} // namespace tesseratos From 383985e2884aac23722f0a0f736e53984ea4e7b6 Mon Sep 17 00:00:00 2001 From: Ricardo Antunes Date: Sun, 29 Sep 2024 16:23:44 +0200 Subject: [PATCH 7/7] style(tesseratos): remove unnecessary include in Debugger --- tools/tesseratos/src/tesseratos/debugger/plugin.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/tesseratos/src/tesseratos/debugger/plugin.hpp b/tools/tesseratos/src/tesseratos/debugger/plugin.hpp index 0dfdbf463..0975cd89f 100644 --- a/tools/tesseratos/src/tesseratos/debugger/plugin.hpp +++ b/tools/tesseratos/src/tesseratos/debugger/plugin.hpp @@ -7,9 +7,6 @@ #pragma once -#include -#include - #include #include "debugger.hpp"