From 0229e9f45bb2834db9261f305743e5486a042510 Mon Sep 17 00:00:00 2001 From: Ricardo Antunes Date: Wed, 31 Jan 2024 10:17:18 +0000 Subject: [PATCH] docs(engine): switch samples to new Cubos syntax --- engine/samples/assets/bridge/main.cpp | 49 +++--- engine/samples/assets/bridge/page.md | 2 - engine/samples/assets/json/main.cpp | 70 +++----- engine/samples/assets/json/page.md | 12 +- engine/samples/assets/saving/main.cpp | 78 +++------ engine/samples/assets/saving/page.md | 10 +- engine/samples/collisions/main.cpp | 200 +++++++++++----------- engine/samples/events/main.cpp | 99 +++++------ engine/samples/events/page.md | 6 +- engine/samples/gizmos/main.cpp | 169 +++++++++--------- engine/samples/hello-cubos/components.hpp | 11 -- engine/samples/hello-cubos/main.cpp | 100 ++++------- engine/samples/hello-cubos/page.md | 52 ++---- engine/samples/imgui/main.cpp | 66 ++++--- engine/samples/imgui/page.md | 10 +- engine/samples/input/main.cpp | 110 ++++++------ engine/samples/input/page.md | 6 +- engine/samples/physics/main.cpp | 132 +++++++------- engine/samples/renderer/main.cpp | 148 +++++++--------- engine/samples/renderer/page.md | 12 +- engine/samples/scene/main.cpp | 97 +++++------ engine/samples/scene/page.md | 2 +- engine/samples/settings/main.cpp | 14 +- engine/samples/settings/page.md | 10 +- engine/samples/voxels/main.cpp | 94 +++++----- engine/samples/voxels/page.md | 6 +- 26 files changed, 669 insertions(+), 896 deletions(-) delete mode 100644 engine/samples/hello-cubos/components.hpp diff --git a/engine/samples/assets/bridge/main.cpp b/engine/samples/assets/bridge/main.cpp index dba996a0a0..645020b677 100644 --- a/engine/samples/assets/bridge/main.cpp +++ b/engine/samples/assets/bridge/main.cpp @@ -47,42 +47,33 @@ class TextBridge : public FileBridge }; /// [TextBridge::saveToFile] -static void configSystem(Settings& settings) +int main() { - settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER); -} + auto cubos = Cubos(); -/// [Registering the bridge] -static void bridgeSystem(Assets& assets) -{ - // Add a custom bridge to load .txt files. - assets.registerBridge(".txt", std::make_unique()); -} -/// [Registering the bridge] + cubos.addPlugin(assetsPlugin); -/// [Loading the asset] -// Assets are identified through UUIDs which are defined in their .meta files. -static const Asset SampleAsset = AnyAsset("6f42ae5a-59d1-5df3-8720-83b8df6dd536"); + cubos.startupSystem("configure Assets plugin").tagged("cubos.settings").call([](Settings& settings) { + settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER); + }); -static void loadSystem(const Assets& assets) -{ - // Access the text asset - will be loaded automatically. - auto text = assets.read(SampleAsset); - Stream::stdOut.print(*text); -} -/// [Loading the asset] + /// [Registering the bridge] + cubos.startupSystem("setup bridge to load .txt files").tagged("cubos.assets.bridge").call([](Assets& assets) { + assets.registerBridge(".txt", std::make_unique()); + }); + /// [Registering the bridge] -int main() -{ - auto cubos = Cubos(); + /// [Loading the asset] + // Assets are identified through UUIDs which are defined in their .meta files. + static const Asset SampleAsset = AnyAsset("6f42ae5a-59d1-5df3-8720-83b8df6dd536"); - /// [Configuration] - cubos.addPlugin(assetsPlugin); - cubos.startupSystem(bridgeSystem).tagged("cubos.assets.bridge"); - cubos.startupSystem(loadSystem).tagged("cubos.assets"); - /// [Configuration] + cubos.startupSystem("access .txt asset").tagged("cubos.assets").call([](const Assets& assets) { + // Access the text asset - will be loaded automatically. + auto text = assets.read(SampleAsset); + Stream::stdOut.print(*text); + }); + /// [Loading the asset] - cubos.startupSystem(configSystem).tagged("cubos.settings"); cubos.run(); return 0; } diff --git a/engine/samples/assets/bridge/page.md b/engine/samples/assets/bridge/page.md index 17cd5e141a..2c45395354 100644 --- a/engine/samples/assets/bridge/page.md +++ b/engine/samples/assets/bridge/page.md @@ -57,5 +57,3 @@ startup phase. Systems which add bridges should be tagged with `cubos.assets.bridge` so that they run before any assets are loaded. Similarly, startup systems which load assets should be tagged with `cubos.assets` so that they run after all bridges have been registered. - -@snippet assets/bridge/main.cpp Configuration diff --git a/engine/samples/assets/json/main.cpp b/engine/samples/assets/json/main.cpp index c7e1af6d93..cb998efdea 100644 --- a/engine/samples/assets/json/main.cpp +++ b/engine/samples/assets/json/main.cpp @@ -12,8 +12,6 @@ #include using cubos::core::data::FileSystem; -using cubos::core::data::old::Deserializer; -using cubos::core::data::old::Serializer; using cubos::core::memory::Stream; using cubos::core::reflection::FieldsTrait; using cubos::core::reflection::Type; @@ -34,59 +32,33 @@ CUBOS_REFLECT_IMPL(Strings) } /// [Asset type] -/// [Serialization definition] -template <> -void cubos::core::data::old::serialize(Serializer& ser, const Strings& obj, const char* name) -{ - ser.beginObject(name); - ser.write(obj.strings, "strings"); - ser.endObject(); -} - -template <> -void cubos::core::data::old::deserialize(Deserializer& des, Strings& obj) -{ - des.beginObject(); - des.read(obj.strings); - des.endObject(); -} -/// [Serialization definition] - -static void configSystem(Settings& settings) +int main() { - settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER); -} + Cubos cubos{}; -/// [Register bridge] -static void bridgeSystem(Assets& assets) -{ - assets.registerBridge(".strings", std::make_unique>()); -} -/// [Register bridge] + cubos.addPlugin(assetsPlugin); -/// [Loading the asset] -static const Asset SampleAsset = AnyAsset("6f42ae5a-59d1-5df3-8720-83b8df6dd536"); + cubos.startupSystem("configure Assets plugin").tagged("cubos.settings").call([](Settings& settings) { + settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER); + }); -static void loadSystem(Assets& assets) -{ - auto read = assets.read(SampleAsset); - for (const auto& str : read->strings) - { - Stream::stdOut.printf("String: {}\n", str); - } -} -/// [Loading the asset] + /// [Register bridge] + cubos.startupSystem("setup bridge to load .strings files").tagged("cubos.assets.bridge").call([](Assets& assets) { + assets.registerBridge(".strings", std::make_unique>()); + }); + /// [Register bridge] -int main() -{ - Cubos cubos{}; + /// [Loading the asset] + static const Asset SampleAsset = AnyAsset("6f42ae5a-59d1-5df3-8720-83b8df6dd536"); - /// [Configuration] - cubos.addPlugin(assetsPlugin); - cubos.startupSystem(bridgeSystem).tagged("cubos.assets.bridge"); - cubos.startupSystem(loadSystem).tagged("cubos.assets"); - /// [Configuration] + cubos.startupSystem("access .strings asset").tagged("cubos.assets").call([](Assets& assets) { + auto read = assets.read(SampleAsset); + for (const auto& str : read->strings) + { + Stream::stdOut.printf("String: {}\n", str); + } + }); + /// [Loading the asset] - cubos.startupSystem(configSystem).tagged("cubos.settings"); cubos.run(); } diff --git a/engine/samples/assets/json/page.md b/engine/samples/assets/json/page.md index dfa5965108..b3e7f36c77 100644 --- a/engine/samples/assets/json/page.md +++ b/engine/samples/assets/json/page.md @@ -1,6 +1,6 @@ -# Loading Serializable Assets {#examples-engine-assets-json} +# Loading Reflectable Assets {#examples-engine-assets-json} -@brief Loading serializable assets from JSON. +@brief Loading reflectable assets from JSON. @see Full source code [here](https://github.com/GameDevTecnico/cubos/tree/main/engine/samples/assets/json). @@ -8,13 +8,9 @@ We'll use the following type as an example: @snippet assets/json/main.cpp Asset type -We can make it serializable by implementing the following specializations: - -@snippet assets/json/main.cpp Serialization definition - Then, we must register a bridge for this type. We provide @ref cubos::engine::JSONBridge "JSONBridge" for easily loading and saving -serializable assets as JSON. +reflectable assets as JSON. @snippet assets/json/main.cpp Register bridge @@ -24,5 +20,3 @@ With the bridge registered, we can just load it from its handle: These sytems are configured the usual way, as explained in @ref examples-engine-assets-bridge. - -@snippet assets/json/main.cpp Configuration diff --git a/engine/samples/assets/saving/main.cpp b/engine/samples/assets/saving/main.cpp index 54510aff3a..19b9f0e1a0 100644 --- a/engine/samples/assets/saving/main.cpp +++ b/engine/samples/assets/saving/main.cpp @@ -9,8 +9,6 @@ #include using cubos::core::data::FileSystem; -using cubos::core::data::old::Deserializer; -using cubos::core::data::old::Serializer; using cubos::core::memory::Stream; using cubos::core::reflection::FieldsTrait; using cubos::core::reflection::Type; @@ -30,67 +28,43 @@ CUBOS_REFLECT_IMPL(IntegerAsset) } /// [Asset type] -template <> -void cubos::core::data::old::serialize(Serializer& ser, const IntegerAsset& obj, const char* name) +int main() { - ser.beginObject(name); - ser.write(obj.value, "value"); - ser.endObject(); -} + Cubos cubos{}; -template <> -void cubos::core::data::old::deserialize(Deserializer& des, IntegerAsset& obj) -{ - des.beginObject(); - des.read(obj.value); - des.endObject(); -} + cubos.addPlugin(assetsPlugin); -/// [Setting] -static void configSystem(Settings& settings) -{ - // If we want to save assets, we must set this to false. - settings.setBool("assets.io.readOnly", false); /// [Setting] + cubos.startupSystem("configure Assets plugin").tagged("cubos.settings").call([](Settings& settings) { + // If we want to save assets, we must set this to false. + settings.setBool("assets.io.readOnly", false); + /// [Setting] - settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER); -} + settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER); + }); -static void bridgeSystem(Assets& assets) -{ - assets.registerBridge(".int", std::make_unique>()); -} + cubos.startupSystem("setup bridge to load and save .int assets") + .tagged("cubos.assets.bridge") + .call([](Assets& assets) { assets.registerBridge(".int", std::make_unique>()); }); -/// [Create a new asset] -static void saveSystem(Assets& assets) -{ - // Create a new asset (with a random UUID). - auto handle = assets.create(IntegerAsset{1337}); /// [Create a new asset] + cubos.startupSystem("create and save asset").tagged("cubos.assets").call([](Assets& assets) { + // Create a new asset (with a random UUID). + auto handle = assets.create(IntegerAsset{1337}); + /// [Create a new asset] - /// [Save the asset] - assets.writeMeta(handle)->set("path", "/assets/sample/sample.int"); - assets.save(handle); - /// [Save the asset] + /// [Save the asset] + assets.writeMeta(handle)->set("path", "/assets/sample/sample.int"); + assets.save(handle); + /// [Save the asset] - // Wait for input before exiting. - Stream::stdOut.print("You can now check the contents of the file!\nPress enter to exit..."); - Stream::stdIn.get(); + // Wait for input before exiting. + Stream::stdOut.print("You can now check the contents of the file!\nPress enter to exit..."); + Stream::stdIn.get(); - // Cleanup the created asset. - FileSystem::destroy("/assets/sample"); -} - -int main() -{ - Cubos cubos{}; - - /// [Configure] - cubos.addPlugin(assetsPlugin); - cubos.startupSystem(saveSystem).tagged("cubos.assets"); - /// [Configure] + // Cleanup the created asset. + FileSystem::destroy("/assets/sample"); + }); - cubos.startupSystem(configSystem).tagged("cubos.settings"); - cubos.startupSystem(bridgeSystem).tagged("cubos.assets.bridge"); cubos.run(); } diff --git a/engine/samples/assets/saving/page.md b/engine/samples/assets/saving/page.md index 9319a96fb8..91f4516b6a 100644 --- a/engine/samples/assets/saving/page.md +++ b/engine/samples/assets/saving/page.md @@ -4,9 +4,9 @@ @see Full source code [here](https://github.com/GameDevTecnico/cubos/tree/main/engine/samples/assets/saving). -This example demonstrates how a new asset be created programatically and how it +This example demonstrates how a new asset can be created programatically and how it can be saved to the assets directory, which is useful while working on tools -such as **TESSERATOS.** +such as **TESSERATOS** Before we go any further, if we want to save assets to the filesystem, we must allow assets to be modified. This is done through the following setting: @@ -23,7 +23,7 @@ First, we'll create an asset of this type: @snippet assets/saving/main.cpp Create a new asset -Then, we'll assign it a path and save it. Its important that the path ends with +Then, we'll assign it a path and save it. It's important that the path ends with the correct extension, so that @ref cubos::engine::Assets "Assets" knows which bridge to use when loading it. @@ -33,8 +33,4 @@ With this, the files `sample/sample.int` and `sample/sample.int.meta` should have appeared on the `assets/` directory. The `.meta` file contains the UUID of the asset, which is used by the engine to identify it. -Finally, the engine is configured the following way: - -@snippet assets/saving/main.cpp Configure - Try running the sample yourself to see the files being created! diff --git a/engine/samples/collisions/main.cpp b/engine/samples/collisions/main.cpp index 216886a2c0..f8a304dddc 100644 --- a/engine/samples/collisions/main.cpp +++ b/engine/samples/collisions/main.cpp @@ -31,102 +31,6 @@ struct State glm::vec3 bRotationAxis; }; -static void settings(Settings& settings) -{ - settings.setBool("assets.io.enabled", false); -} - -static void init(Commands commands, Input& input, ActiveCameras& camera) -{ - // Add procedural asset for detecting a reset action on a space key press. - auto bindings = InputBindings{}; - bindings.actions()["reset"].keys().emplace_back(Key::Space, Modifiers::None); - input.bind(bindings); - - // Spawn the camera. - camera.entities[0] = - commands.create() - .add(Camera{.fovY = 60.0, .zNear = 0.1F, .zFar = 100.0F}) - .add(LocalToWorld{}) - .add(Position{{-4.0, 1.5, 0}}) - .add(Rotation{glm::quatLookAt(glm::normalize(glm::vec3{3.0, -1.0, 0.0}), glm::vec3{0.0, 1.0, 0.0})}) - .entity(); -} - -static void addColliders(State& state, Commands commands) -{ - state.a = commands.create() - .add(Collider{}) - .add(CapsuleCollisionShape{{0.5F, 1.0F}}) - .add(LocalToWorld{}) - .add(Position{glm::vec3{0.0F, 0.0F, -2.0F}}) - .add(Rotation{}) - .entity(); - state.aRotationAxis = glm::sphericalRand(1.0F); - - state.b = commands.create() - .add(Collider{}) - .add(BoxCollisionShape{}) - .add(LocalToWorld{}) - .add(Position{glm::vec3{0.0F, 0.0F, 2.0F}}) - .add(Rotation{}) - .entity(); - state.bRotationAxis = glm::sphericalRand(1.0F); -} - -static void updateTransform(State& state, const Input& input, Query query) -{ - auto [aPos, aRot] = *query.at(state.a); - auto [bPos, bRot] = *query.at(state.b); - - if (state.collided) - { - if (input.pressed("reset")) - { - state.collided = false; - - aPos.vec = glm::vec3{0.0F, 0.0F, -2.0F}; - aRot.quat = glm::quat{1.0F, 0.0F, 0.0F, 0.0F}; - state.aRotationAxis = glm::sphericalRand(1.0F); - - bPos.vec = glm::vec3{0.0F, 0.0F, 2.0F}; - bRot.quat = glm::quat{1.0F, 0.0F, 0.0F, 0.0F}; - state.bRotationAxis = glm::sphericalRand(1.0F); - } - return; - } - - aRot.quat = glm::rotate(aRot.quat, 0.01F, state.aRotationAxis); - aPos.vec += glm::vec3{0.0F, 0.0F, 0.01F}; - - bRot.quat = glm::rotate(bRot.quat, 0.01F, state.bRotationAxis); - bPos.vec += glm::vec3{0.0F, 0.0F, -0.01F}; -} - -static void updateCollided(Query query, State& state) -{ - for (auto [ent1, colliding, ent2] : query) - { - if ((ent1 == state.a && ent2 == state.b) || (ent1 == state.b && ent2 == state.a)) - { - state.collided = true; - } - } -} - -static void render(Query query) -{ - for (auto [localToWorld, collider] : query) - { - cubos::core::gl::Debug::drawWireBox( - collider.localAABB.box(), - glm::translate(localToWorld.mat * collider.transform, collider.localAABB.center())); - cubos::core::gl::Debug::drawWireBox(collider.worldAABB.box(), - glm::translate(glm::mat4{1.0}, collider.worldAABB.center()), - glm::vec3{1.0, 0.0, 0.0}); - } -} - int main() { auto cubos = Cubos(); @@ -137,14 +41,102 @@ int main() cubos.addResource(); - cubos.startupSystem(settings).tagged("cubos.settings"); - cubos.startupSystem(init); - - cubos.startupSystem(addColliders); - - cubos.system(updateTransform).before("cubos.transform.update"); - cubos.system(updateCollided).tagged("updated").after("cubos.collisions.broad"); - cubos.system(render).after("updated"); + cubos.startupSystem("activate assets IO").tagged("cubos.settings").call([](Settings& settings) { + settings.setBool("assets.io.enabled", false); + }); + + cubos.startupSystem("setup input").call([](Input& input) { + // Add procedural asset for detecting a reset action on a space key press. + auto bindings = InputBindings{}; + bindings.actions()["reset"].keys().emplace_back(Key::Space, Modifiers::None); + input.bind(bindings); + }); + + cubos.startupSystem("setup camera").call([](Commands commands, ActiveCameras& cameras) { + // Spawn the camera. + cameras.entities[0] = + commands.create() + .add(Camera{.fovY = 60.0, .zNear = 0.1F, .zFar = 100.0F}) + .add(LocalToWorld{}) + .add(Position{{-4.0, 1.5, 0}}) + .add(Rotation{glm::quatLookAt(glm::normalize(glm::vec3{3.0, -1.0, 0.0}), glm::vec3{0.0, 1.0, 0.0})}) + .entity(); + }); + + cubos.startupSystem("create colliders").call([](State& state, Commands commands) { + state.a = commands.create() + .add(Collider{}) + .add(CapsuleCollisionShape{{0.5F, 1.0F}}) + .add(LocalToWorld{}) + .add(Position{glm::vec3{0.0F, 0.0F, -2.0F}}) + .add(Rotation{}) + .entity(); + state.aRotationAxis = glm::sphericalRand(1.0F); + + state.b = commands.create() + .add(Collider{}) + .add(BoxCollisionShape{}) + .add(LocalToWorld{}) + .add(Position{glm::vec3{0.0F, 0.0F, 2.0F}}) + .add(Rotation{}) + .entity(); + state.bRotationAxis = glm::sphericalRand(1.0F); + }); + + cubos.system("move colliders") + .before("cubos.transform.update") + .call([](State& state, const Input& input, Query query) { + auto [aPos, aRot] = *query.at(state.a); + auto [bPos, bRot] = *query.at(state.b); + + if (state.collided) + { + if (input.pressed("reset")) + { + state.collided = false; + + aPos.vec = glm::vec3{0.0F, 0.0F, -2.0F}; + aRot.quat = glm::quat{1.0F, 0.0F, 0.0F, 0.0F}; + state.aRotationAxis = glm::sphericalRand(1.0F); + + bPos.vec = glm::vec3{0.0F, 0.0F, 2.0F}; + bRot.quat = glm::quat{1.0F, 0.0F, 0.0F, 0.0F}; + state.bRotationAxis = glm::sphericalRand(1.0F); + } + return; + } + + aRot.quat = glm::rotate(aRot.quat, 0.01F, state.aRotationAxis); + aPos.vec += glm::vec3{0.0F, 0.0F, 0.01F}; + + bRot.quat = glm::rotate(bRot.quat, 0.01F, state.bRotationAxis); + bPos.vec += glm::vec3{0.0F, 0.0F, -0.01F}; + }); + + cubos.system("check collisions") + .tagged("updated") + .after("cubos.collisions.broad") + .call([](Query query, State& state) { + for (auto [ent1, colliding, ent2] : query) + { + if ((ent1 == state.a && ent2 == state.b) || (ent1 == state.b && ent2 == state.a)) + { + state.collided = true; + } + } + }); + + cubos.system("render").after("updated").call([](Query query) { + for (auto [localToWorld, collider] : query) + { + cubos::core::gl::Debug::drawWireBox( + collider.localAABB.box(), + glm::translate(localToWorld.mat * collider.transform, collider.localAABB.center())); + cubos::core::gl::Debug::drawWireBox(collider.worldAABB.box(), + glm::translate(glm::mat4{1.0}, collider.worldAABB.center()), + glm::vec3{1.0, 0.0, 0.0}); + } + }); cubos.run(); return 0; diff --git a/engine/samples/events/main.cpp b/engine/samples/events/main.cpp index 049231d8cd..07b2774a1b 100644 --- a/engine/samples/events/main.cpp +++ b/engine/samples/events/main.cpp @@ -18,54 +18,6 @@ struct State int step; }; -/// [Event reader system] -static void firstSystem(EventReader reader) -{ - for (const auto& event : reader) - { - CUBOS_INFO("A read {}", event.value); - } -} -/// [Event reader system] - -/// [Event writer system] -static void secondSystem(EventWriter writer, State& state, ShouldQuit& quit) -{ - state.step += 1; - if (state.step == 1) // Write 1 2 3 on first run. - { - writer.push({1}); - writer.push({2}); - writer.push({3}); - CUBOS_INFO("B wrote 1 2 3"); - } - else if (state.step == 2) - { - quit.value = true; // Stop the loop. - writer.push({4}); - writer.push({5}); - writer.push({6}); - CUBOS_INFO("B wrote 4 5 6"); - } -} -/// [Event writer system] - -static void thirdSystem(EventReader reader) -{ - for (const auto& event : reader) - { - CUBOS_INFO("C read {}", event.value); - } -} - -static void fourthSystem(EventReader reader) -{ - for (const auto& event : reader) - { - CUBOS_INFO("D read {}", event.value); - } -} - int main() { cubos::engine::Cubos cubos; @@ -75,14 +27,51 @@ int main() cubos.addEvent(); /// [Adding event] - cubos.startupSystem([](ShouldQuit& quit) { quit.value = false; }); + cubos.startupSystem("set ShouldQuit to false").call([](ShouldQuit& quit) { quit.value = false; }); + + /// [Event reader systems] + cubos.system("A").before("b").call([](EventReader reader) { + for (const auto& event : reader) + { + CUBOS_INFO("A read {}", event.value); + } + }); + + cubos.system("C").tagged("c").after("b").call([](EventReader reader) { + for (const auto& event : reader) + { + CUBOS_INFO("C read {}", event.value); + } + }); + + cubos.system("D").after("c").call([](EventReader reader) { + for (const auto& event : reader) + { + CUBOS_INFO("D read {}", event.value); + } + }); + /// [Event reader system] - /// [Adding systems] - cubos.system(firstSystem).tagged("A").before("B"); - cubos.system(secondSystem).tagged("B"); - cubos.system(thirdSystem).tagged("C").after("B"); - cubos.system(fourthSystem).tagged("D").after("C"); - /// [Adding systems] + /// [Event writer system] + cubos.system("B").tagged("b").call([](EventWriter writer, State& state, ShouldQuit& quit) { + state.step += 1; + if (state.step == 1) // Write 1 2 3 on first run. + { + writer.push({1}); + writer.push({2}); + writer.push({3}); + CUBOS_INFO("B wrote 1 2 3"); + } + else if (state.step == 2) + { + quit.value = true; // Stop the loop. + writer.push({4}); + writer.push({5}); + writer.push({6}); + CUBOS_INFO("B wrote 4 5 6"); + } + }); + /// [Event writer system] /// [Expected results] // Should print: diff --git a/engine/samples/events/page.md b/engine/samples/events/page.md index a4de94b11c..8ed534d210 100644 --- a/engine/samples/events/page.md +++ b/engine/samples/events/page.md @@ -13,16 +13,12 @@ Firstly, we need to create and register the event we want to emit. Here, our eve To receive these events, we can make a simple system which takes the @ref cubos::core::ecs::EventReader "EventReader" system argument and iterates through all the events it has. This will be the layout of all our reader systems (A, C, D). -@snippet events/main.cpp Event reader system +@snippet events/main.cpp Event reader systems Now, to emit these events, we will use the @ref cubos::core::ecs::EventWriter "EventWriter" system argument. This system will emit 3 events on the first frame and another 3 on the second frame. By setting the value of the @ref cubos::engine::ShouldQuit "ShouldQuit" resource to true on the second frame, the engine stops before reaching the third frame. @snippet events/main.cpp Event writer system -Lastly, let's set the order we want these system to execute in. - -@snippet events/main.cpp Adding systems - These are the expected results with this order. @snippet events/main.cpp Expected results diff --git a/engine/samples/gizmos/main.cpp b/engine/samples/gizmos/main.cpp index 2267b094bf..b862130e71 100644 --- a/engine/samples/gizmos/main.cpp +++ b/engine/samples/gizmos/main.cpp @@ -6,88 +6,6 @@ using namespace cubos::engine; -static void settingsSystem(Settings& settings) -{ - // We don't load assets in this sample and we don't even have an assets folder, so we should - // disable assets IO. - settings.setBool("assets.io.enabled", false); -} - -static void setCameraSystem(ActiveCameras& camera, Commands cmds) -{ - camera.entities[0] = cmds.create() - .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) - .add(LocalToWorld{}) - .add(Position{{5.0F, 5.0F, 0.0F}}) - .add(Rotation{glm::quatLookAt(glm::vec3{-1.0F, -1.0F, 0.0F}, glm::vec3{0.0F, 1.0F, 0.0F})}) - .entity(); - camera.entities[1] = cmds.create() - .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) - .add(LocalToWorld{}) - .add(Position{{-25.0F, 25.0F, 0.0F}}) - .add(Rotation{glm::quatLookAt(glm::vec3{1.0F, -1.0F, 0.0F}, glm::vec3{0.0F, 1.0F, 0.0F})}) - .entity(); - camera.entities[2] = cmds.create() - .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) - .add(LocalToWorld{}) - .add(Position{{-25.0F, -25.0F, 0.0F}}) - .add(Rotation{glm::quatLookAt(glm::vec3{1.0F, 1.0F, 0.0F}, glm::vec3{0.0F, 1.0F, 0.0F})}) - .entity(); - camera.entities[3] = cmds.create() - .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) - .add(LocalToWorld{}) - .add(Position{{25.0F, -25.0F, 0.0F}}) - .add(Rotation{glm::quatLookAt(glm::vec3{-1.0F, 1.0F, 0.0F}, glm::vec3{0.0F, 1.0F, 0.0F})}) - .entity(); -} - -/// [System] -static void drawSystem(Gizmos& gizmos) -{ - /// [Lines] - gizmos.color({1.0F, 1.0F, 1.0F}); - gizmos.drawLine("separator line", {1.0F, 0.5F, 0.5F}, {0.0F, 0.5F, 0.5F}, 0, Gizmos::Space::Screen); - gizmos.drawLine("separator line", {0.5F, 1.0F, 0.5F}, {0.5F, 0.0F, 0.5F}, 0, Gizmos::Space::Screen); - /// [Lines] - - /// [WireBox] - gizmos.color({1.0F, 0.5F, 1.0F}); - gizmos.drawBox("box", {0.4, 0.4, 0}, {0.55, 0.55, 0}, 0, Gizmos::Space::View); - /// [WireBox] - - /// [Box] - gizmos.color({0.2F, 0.2F, 1.0F}); - gizmos.drawWireBox("wire box", {-5, -5, -5}, {-7, -7, -7}, 0, Gizmos::Space::World); - /// [Box] - - ///[Cut Cone] - if (gizmos.hovered("cut cone")) - { - gizmos.color({0.25F, 0.15F, 0.5F}); - } - else if (gizmos.pressed("cut cone")) - { - gizmos.color({0.5F, 0.3F, 1}); - } - else - { - gizmos.color({0.1F, 0.05F, 0.25F}); - } - - gizmos.drawCutCone("cut cone", {0.7F, 0.7F, 0.7F}, 5.0F, {-3, -3, -3}, 3.0F, 0, Gizmos::Space::World); - ///[Cut Cone] -} -/// [System] - -/// [Start Up System] -static void drawStartingLineSystem(Gizmos& gizmos) -{ - gizmos.color({1, 0, 1}); - gizmos.drawArrow("arrow", {0.6F, 0.6F, 0.0F}, {-0.1F, -0.1F, 0.0F}, 0.003F, 0.009F, 0.7F, 10.0F, - Gizmos::Space::Screen); -} -/// [Start Up System] - int main(int argc, char** argv) { /// [Adding plugin] @@ -96,11 +14,90 @@ int main(int argc, char** argv) /// [Adding plugin] cubos.addPlugin(rendererPlugin); - cubos.startupSystem(settingsSystem).tagged("cubos.settings"); - cubos.startupSystem(setCameraSystem); - cubos.startupSystem(drawStartingLineSystem).tagged("sample.init").after("cubos.gizmos.init"); + cubos.startupSystem("disable Assets IO").tagged("cubos.settings").call([](Settings& settings) { + // We don't load assets in this sample and we don't even have an assets folder, so we should + // disable assets IO. + settings.setBool("assets.io.enabled", false); + }); + + cubos.startupSystem("setup camera").call([](ActiveCameras& camera, Commands cmds) { + camera.entities[0] = + cmds.create() + .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) + .add(LocalToWorld{}) + .add(Position{{5.0F, 5.0F, 0.0F}}) + .add(Rotation{glm::quatLookAt(glm::vec3{-1.0F, -1.0F, 0.0F}, glm::vec3{0.0F, 1.0F, 0.0F})}) + .entity(); + camera.entities[1] = + cmds.create() + .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) + .add(LocalToWorld{}) + .add(Position{{-25.0F, 25.0F, 0.0F}}) + .add(Rotation{glm::quatLookAt(glm::vec3{1.0F, -1.0F, 0.0F}, glm::vec3{0.0F, 1.0F, 0.0F})}) + .entity(); + camera.entities[2] = + cmds.create() + .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) + .add(LocalToWorld{}) + .add(Position{{-25.0F, -25.0F, 0.0F}}) + .add(Rotation{glm::quatLookAt(glm::vec3{1.0F, 1.0F, 0.0F}, glm::vec3{0.0F, 1.0F, 0.0F})}) + .entity(); + camera.entities[3] = + cmds.create() + .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) + .add(LocalToWorld{}) + .add(Position{{25.0F, -25.0F, 0.0F}}) + .add(Rotation{glm::quatLookAt(glm::vec3{-1.0F, 1.0F, 0.0F}, glm::vec3{0.0F, 1.0F, 0.0F})}) + .entity(); + }); + + /// [Start Up System] + cubos.startupSystem("draw line at startup") + .tagged("sample.init") + .after("cubos.gizmos.init") + .call([](Gizmos& gizmos) { + gizmos.color({1, 0, 1}); + gizmos.drawArrow("arrow", {0.6F, 0.6F, 0.0F}, {-0.1F, -0.1F, 0.0F}, 0.003F, 0.009F, 0.7F, 10.0F, + Gizmos::Space::Screen); + }); + /// [Start Up System] + + /// [System] + cubos.system("draw gizmos").call([](Gizmos& gizmos) { + /// [Lines] + gizmos.color({1.0F, 1.0F, 1.0F}); + gizmos.drawLine("separator line", {1.0F, 0.5F, 0.5F}, {0.0F, 0.5F, 0.5F}, 0, Gizmos::Space::Screen); + gizmos.drawLine("separator line", {0.5F, 1.0F, 0.5F}, {0.5F, 0.0F, 0.5F}, 0, Gizmos::Space::Screen); + /// [Lines] + + /// [WireBox] + gizmos.color({1.0F, 0.5F, 1.0F}); + gizmos.drawBox("box", {0.4, 0.4, 0}, {0.55, 0.55, 0}, 0, Gizmos::Space::View); + /// [WireBox] + + /// [Box] + gizmos.color({0.2F, 0.2F, 1.0F}); + gizmos.drawWireBox("wire box", {-5, -5, -5}, {-7, -7, -7}, 0, Gizmos::Space::World); + /// [Box] + + ///[Cut Cone] + if (gizmos.hovered("cut cone")) + { + gizmos.color({0.25F, 0.15F, 0.5F}); + } + else if (gizmos.pressed("cut cone")) + { + gizmos.color({0.5F, 0.3F, 1}); + } + else + { + gizmos.color({0.1F, 0.05F, 0.25F}); + } - cubos.system(drawSystem); + gizmos.drawCutCone("cut cone", {0.7F, 0.7F, 0.7F}, 5.0F, {-3, -3, -3}, 3.0F, 0, Gizmos::Space::World); + ///[Cut Cone] + }); + /// [System] cubos.run(); } diff --git a/engine/samples/hello-cubos/components.hpp b/engine/samples/hello-cubos/components.hpp deleted file mode 100644 index 11c782f651..0000000000 --- a/engine/samples/hello-cubos/components.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include -#include - -struct Num -{ - CUBOS_REFLECT; - - int value; -}; diff --git a/engine/samples/hello-cubos/main.cpp b/engine/samples/hello-cubos/main.cpp index 70d033af32..199cb856fc 100644 --- a/engine/samples/hello-cubos/main.cpp +++ b/engine/samples/hello-cubos/main.cpp @@ -1,24 +1,25 @@ -/// [Include Components] -#include "components.hpp" -/// [Include Components] - /// [Include] #include -using cubos::engine::Cubos; -/// [Include] - using namespace cubos::engine; +/// [Include] -/// [Component Refl] +/// [Component Decl] #include #include +struct Num +{ + CUBOS_REFLECT; + + int value; +}; + CUBOS_REFLECT_IMPL(Num) { return cubos::core::ecs::TypeBuilder("Num").withField("value", &Num::value).build(); } -/// [Component Refl] +/// [Component Decl] /// [Resource Decl] struct Pop @@ -27,65 +28,25 @@ struct Pop }; /// [Resource Decl] -/// [Hello Cubos] -static void sayHelloCubosSystem() -{ - CUBOS_INFO("Hello CUBOS"); -} -/// [Hello Cubos] - -/// [Hello World] -static void sayHelloSystem() -{ - CUBOS_INFO("Hello"); -} - -static void sayWorldSystem() -{ - CUBOS_INFO("World"); -} -/// [Hello World] - -/// [Entity Spawn] -static void spawnEntitiesSystem(Commands cmds, Pop& pop) -{ - for (int i = 0; i < 10; i++) - { - cmds.create().add(Num{i}); - pop.count += 1; - } -} -/// [Entity Spawn] - -/// [Entity Print] -static void checkEntitiesSystem(Query query, const Pop& pop) -{ - for (auto [num] : query) - { - CUBOS_INFO("Entity '{}' of '{}'", num.value, pop.count); - } -} -/// [Entity Print] - /// [Engine] int main() { Cubos cubos{}; /// [Engine] + /// [Hello CUBOS] + cubos.startupSystem("say Hello CUBOS").call([]() { CUBOS_INFO("Hello CUBOS"); }); + /// [Hello CUBOS] + + /// [Hello World] + cubos.system("say Hello").tagged("helloTag").call([]() { CUBOS_INFO("Hello"); }); + cubos.system("say World").tagged("worldTag").call([]() { CUBOS_INFO("World"); }); + /// [Hello World] + /// [Tags] cubos.tag("helloTag").before("worldTag"); /// [Tags] - /// [Set Startup] - cubos.startupSystem(sayHelloCubosSystem); - /// [Set Startup] - - /// [Set Systems] - cubos.system(sayHelloSystem).tagged("helloTag"); - cubos.system(sayWorldSystem).tagged("worldTag"); - /// [Set Systems] - /// [Component Add] cubos.addComponent(); /// [Component Add] @@ -94,11 +55,24 @@ int main() cubos.addResource(); /// [Resource Add] - /// [Entity System] - cubos.startupSystem(spawnEntitiesSystem); - - cubos.system(checkEntitiesSystem); - /// [Entity System] + /// [Entity Spawn] + cubos.startupSystem("spawn entities").call([](Commands cmds, Pop& pop) { + for (int i = 0; i < 10; i++) + { + cmds.create().add(Num{i}); + pop.count += 1; + } + }); + /// [Entity Spawn] + + /// [Entity Print] + cubos.system("check entities").call([](Query query, const Pop& pop) { + for (auto [num] : query) + { + CUBOS_INFO("Entity '{}' of '{}'", num.value, pop.count); + } + }); + /// [Entity Print] /// [Run] cubos.run(); diff --git a/engine/samples/hello-cubos/page.md b/engine/samples/hello-cubos/page.md index c0fdf17a8e..e3957da5e3 100644 --- a/engine/samples/hello-cubos/page.md +++ b/engine/samples/hello-cubos/page.md @@ -4,7 +4,6 @@ @see Full source code [here](https://github.com/GameDevTecnico/cubos/tree/main/engine/samples/hello-cubos). - This example shows the basics of how @ref cubos::engine::Cubos is used, by making a simple "Hello World" program. @snippet hello-cubos/main.cpp Include @@ -16,18 +15,14 @@ First we'll need to get a `Cubos` object. The @ref cubos::engine::Cubos "Cubos" class represents the engine. We'll need it to add functionality to our program. -Let's start by defining what functionality we want to add. +Let's start by defining what functionality we want to add, by adding our first system. -@snippet hello-cubos/main.cpp Hello Cubos +@snippet hello-cubos/main.cpp Hello CUBOS -This function simply prints `Hello CUBOS` to the console. -It uses one of CUBOS.'s logging macros. +This startup system simply prints `Hello CUBOS` to the console, using one of CUBOS's logging macros. You can find more about them @ref core/include/cubos/core/log.hpp "here". -However, this function is not currently called, so we'll need to tell CUBOS. that we want it to run. - -@snippet hello-cubos/main.cpp Set Startup - Startup systems run only once when the engine is loaded. + Now let's make things more interesting. Let's print `Hello World`, but split it over two different systems. @@ -38,42 +33,32 @@ This means the systems will be called after the startup systems and repeat every @note As we don't have anything that would require multiple cycles (such as a window to draw to), the CUBOS. main cycle will run only once. -However, we can't just do as we did for `sayHelloCubos` and call it a day. -We want `sayHello` to come before `sayWorld`, so we'll have to explicitly tell that to the engine, or else we risk having them in the wrong order. +Notice that we can't just do as we did for `Hello CUBOS` and call it a day. +We want `Hello` to come before `World`, so we'll have to explicitly tell that to the engine, or else we risk having them in the wrong order. To do that we use tags. -Let's create two tags, one for each system. @snippet hello-cubos/main.cpp Tags -@ref cubos::engine::Cubos::tag "Cubos::tag" creates a new tag, and @ref cubos::engine::TagBuilder::before "before" makes any systems tagged with it come before systems tagged with the one given as parameter. +@ref cubos::engine::Cubos::tag "Cubos::tag" can be used to apply properties to all systems with a given tag, and @ref cubos::engine::TagBuilder::before "before" makes any systems tagged with it come before systems tagged with the one given as parameter. There's also an @ref cubos::engine::TagBuilder::after "after" that has the inverse effect. -Now all we have to do is to assign these tags to our systems. -@note If we wanted to give these tags to a system running on startup, we'd have to use @ref cubos::engine::Cubos::startupTag "Cubos::startupTag" instead. -@snippet hello-cubos/main.cpp Set Systems +@note If we wanted to give these tags to a system running on startup, we'd have to use @ref cubos::engine::Cubos::startupTag "Cubos::startupTag" instead. Now let's see a bit about entities, components and resources. First we are going to need to use a few more things. We'll go over what each does as it comes up. -Entities have components, so let's create one to give our entities. -Because of how the engine works, we cannot declare a component on our `main.cpp` file. -We'll need to create a `components.hpp` for that. - -@include hello-cubos/components.hpp +Lets define a new component type, which stores a single integer, which we can use to identify the entity. -Here we create a component called "num" that stores a single integer. -We'll use it as the id of the entity it is attached to. -Back on our `main.cpp` file we'll need to include our new file. +@snippet hello-cubos/main.cpp Component Decl -@snippet hello-cubos/main.cpp Include Components +Notice that not only we define the type, but we also define reflection for it. This is a way to let CUBOS know what our data type is made of, making it compatible with serialization, UI debug tools and others automatically. -And the component needs to be registered. +We also need to register the component type with the `Cubos` object. @snippet hello-cubos/main.cpp Component Add -Let's create a resource now. -Unlike components, resources can be declared on the `main.cpp` file, so let's do that. +Now, lets create our own resource. @snippet hello-cubos/main.cpp Resource Decl @@ -88,21 +73,18 @@ Now let's create a startup system that spawns some entities. @ref cubos::core::ecs::Commands "Commands" is a system argument that allows us to interact with the world, in this case, by creating entities that have a `Num` component. -@ref cubos::core::ecs::Write "Write" is a system argument that allows us to modify a resource, in this case `Pop`. +To access the resource `Pop`, we just add a reference to it as a system argument (`Pop&`). Finally, we'll want a system that prints our entities. @snippet hello-cubos/main.cpp Entity Print -@ref cubos::core::ecs::Read "Read" is similar to `Write`, only it just gives us permission to read data from resources and components, we cannot alter them. +In this case, we don't change `Pop`, and only read its value. Thus, we use `const Pop&`. This allows CUBOS to make some optimizations behind the scenes. @ref cubos::core::ecs::Query "Query" allows us to access all entities with a given configuration of components. In this case, it will give us all entities with the `Num` component. -To finish configuring our program, we just need to register these two new systems. -We'll also have the entities be printed after our `Hello World` message. - -@snippet hello-cubos/main.cpp Entity System - With everything properly set up, all that remains is to run the engine. @snippet hello-cubos/main.cpp Run + +Try running the sample yourself, and you should see both the hello world messages and the list of entities we spawned! diff --git a/engine/samples/imgui/main.cpp b/engine/samples/imgui/main.cpp index d68333b231..0ba45de45e 100644 --- a/engine/samples/imgui/main.cpp +++ b/engine/samples/imgui/main.cpp @@ -68,34 +68,6 @@ struct DummyResource }; /// [Creating a dummy resource] -/// [DataInspector window example] -static void exampleDataInspectorSystem(DataInspector& inspector, DummyResource& data) -{ - ImGui::Begin("Data Inspector"); - ImGui::BeginTable("id1", 2); - - inspector.show("data.integer", data.integer); - inspector.edit("data.person", data.person); - inspector.edit("data.persons", data.persons); - inspector.edit("data.vec", data.vec); - inspector.edit("data.map", data.map); - - ImGui::EndTable(); - ImGui::End(); -} -/// [DataInspector window example] - -/// [ImGui window example] -static void exampleWindowSystem() -{ - ImGui::Begin("Dear ImGui + CUBOS."); - ImGui::Text("Hello world!"); - ImGui::End(); - - ImGui::ShowDemoWindow(); -} -/// [ImGui window example] - int main() { Cubos cubos{}; @@ -104,11 +76,17 @@ int main() cubos.addPlugin(imguiPlugin); /// [Adding the plugin] - /// [Adding the system] - cubos.system(exampleWindowSystem).tagged("cubos.imgui"); - /// [Adding the system] + /// [ImGui Demo] + cubos.system("show ImGui demo").tagged("cubos.imgui").call([]() { + ImGui::Begin("Dear ImGui + CUBOS."); + ImGui::Text("Hello world!"); + ImGui::End(); - /// [Filling the dummy resource 1] + ImGui::ShowDemoWindow(); + }); + /// [ImGui Demo] + + /// [Filling the dummy resource] cubos.addResource( DummyResource{.integer = 1337, .person = Person{"roby", 1337, 666.5F, false}, @@ -120,11 +98,25 @@ int main() {3, 6}, {4, 8}, }}); - /// [Filling the dummy resource 1] - - /// [Adding the system and a dummy resource with data] - cubos.system(exampleDataInspectorSystem).tagged("cubos.imgui"); - /// [Adding the system and a dummy resource with data] + /// [Filling the dummy resource] + + /// [DataInspector window example] + cubos.system("data inspector example") + .tagged("cubos.imgui") + .call([](DataInspector& inspector, DummyResource& data) { + ImGui::Begin("Data Inspector"); + ImGui::BeginTable("id1", 2); + + inspector.show("data.integer", data.integer); + inspector.edit("data.person", data.person); + inspector.edit("data.persons", data.persons); + inspector.edit("data.vec", data.vec); + inspector.edit("data.map", data.map); + + ImGui::EndTable(); + ImGui::End(); + }); + /// [DataInspector window example] cubos.run(); } diff --git a/engine/samples/imgui/page.md b/engine/samples/imgui/page.md index 4a34ec9b4c..9dcc8f7fb7 100644 --- a/engine/samples/imgui/page.md +++ b/engine/samples/imgui/page.md @@ -16,14 +16,12 @@ Then, make sure to add the plugin. @snippet imgui/main.cpp Adding the plugin -Once the ImGui plugin is added, you can create systems to display ImGui windows and widgets. Here's an example of how to create an ImGui window. +Once the ImGui plugin is added, you can create systems to display ImGui windows and widgets. Here's a system which opens an ImGui window, and its demo. -@snippet imgui/main.cpp ImGui window example +@snippet imgui/main.cpp ImGui Demo Ensure that you add your system with the `cubos.imgui` tag; otherwise, the ImGui elements from that system won't be be visible. -@snippet imgui/main.cpp Adding the system - Pretty simple right? You're now equipped to craft and utilize ImGui's functions to design your cool user interface. Now, we'll also show you how you can use the @ref cubos::engine::DataInspector resource in combination with @ref imgui-plugin plugin to inspect/modify data in real time. @@ -34,9 +32,9 @@ To start off, we'll need to have some sort of dummy data shared across our appli @snippet imgui/main.cpp Creating a dummy resource -@snippet imgui/main.cpp Filling the dummy resource 1 +@snippet imgui/main.cpp Filling the dummy resource -Well now, using the @ref cubos::engine::DataInspector is pretty easy, all you have to do is, obviously, access the resource on your system, and use the functions `DataInspector::edit` and `DataInspector::edit`. +Well now, using the @ref cubos::engine::DataInspector is pretty easy, all you have to do is access the resource on your system, and use the functions `DataInspector::edit` and `DataInspector::edit`. @snippet imgui/main.cpp DataInspector window example diff --git a/engine/samples/input/main.cpp b/engine/samples/input/main.cpp index c190b331fd..976173239b 100644 --- a/engine/samples/input/main.cpp +++ b/engine/samples/input/main.cpp @@ -164,59 +164,6 @@ static void showcaseMouseButtons(const Input& input, bool& explained) } /// [Showcase Mouse Buttons] -/// [Checking Type of Press] -static void update(const Input& input, const Window& window, State& state, ShouldQuit& shouldQuit) -{ - // FIXME: This is an hack to have one-shot actions while we don't have input events. - if (input.pressed("next-showcase")) - { - state.nextPressed = true; - } - else if (state.nextPressed) - { - state.nextPressed = false; - state.explained = false; - state.showcase++; - } - /// [Checking Type of Press] - - switch (state.showcase) - { - case 0: - return explain(state.explained); - case 1: - return showcaseXZ(input, state.explained); - case 2: - return showcaseModifiers(input, state.explained); - case 3: - return showcaseMultipleModifiers(input, state.explained); - case 4: - return showcaseAxis(input, state.explained); - case 5: - return showcaseModifierAxis(input, state.explained); - case 6: - return showcaseUnbound(window, state.explained); - case 7: - return showcaseMouseButtons(input, state.explained); - default: - shouldQuit.value = true; - } -} - -/// [Loading the bindings] -static void config(Settings& settings) -{ - settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER); -} - -static void init(const Assets& assets, Input& input) -{ - auto bindings = assets.read(BindingsAsset); - input.bind(*bindings); - CUBOS_INFO("Loaded bindings: {}", input.bindings().at(0)); -} -/// [Loading the bindings] - int main() { auto cubos = Cubos(); @@ -227,12 +174,59 @@ int main() cubos.addResource(); - /// [Systems to load bindings] - cubos.startupSystem(config).tagged("cubos.settings"); - cubos.startupSystem(init).tagged("cubos.assets"); - /// [Systems to load bindings] + cubos.startupSystem("configure Assets").tagged("cubos.settings").call([](Settings& settings) { + settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER); + }); - cubos.system(update).after("cubos.input.update"); + /// [Loading the bindings] + cubos.startupSystem("load and set the Input Bindings") + .tagged("cubos.assets") + .call([](const Assets& assets, Input& input) { + auto bindings = assets.read(BindingsAsset); + input.bind(*bindings); + CUBOS_INFO("Loaded bindings: {}", input.bindings().at(0)); + }); + /// [Loading the bindings] + + /// [Checking Type of Press] + cubos.system("detect input") + .after("cubos.input.update") + .call([](const Input& input, const Window& window, State& state, ShouldQuit& shouldQuit) { + // FIXME: This is an hack to have one-shot actions while we don't have input events. + if (input.pressed("next-showcase")) + { + state.nextPressed = true; + } + else if (state.nextPressed) + { + state.nextPressed = false; + state.explained = false; + state.showcase++; + } + /// [Checking Type of Press] + + switch (state.showcase) + { + case 0: + return explain(state.explained); + case 1: + return showcaseXZ(input, state.explained); + case 2: + return showcaseModifiers(input, state.explained); + case 3: + return showcaseMultipleModifiers(input, state.explained); + case 4: + return showcaseAxis(input, state.explained); + case 5: + return showcaseModifierAxis(input, state.explained); + case 6: + return showcaseUnbound(window, state.explained); + case 7: + return showcaseMouseButtons(input, state.explained); + default: + shouldQuit.value = true; + } + }); cubos.run(); return 0; diff --git a/engine/samples/input/page.md b/engine/samples/input/page.md index f5944e70ae..5c952255ca 100644 --- a/engine/samples/input/page.md +++ b/engine/samples/input/page.md @@ -35,9 +35,7 @@ For the purposes of this sample we can simply use an hardcoded reference to the @snippet input/main.cpp Setting the Bindings -To utilize the bindings, loading them is essential. This can be accomplished by establishing two startup systems: one to configure the `assets.io.path` path and the other to read from the asset and establish the required bindings. - -@snippet input/main.cpp Systems to load bindings +To utilize the bindings, loading them is essential. This can be accomplished by establishing a startup systems which reads from the asset and sets the required bindings. @snippet input/main.cpp Loading the bindings @@ -54,7 +52,7 @@ This avoids the state advancing more than once if the user presses it for more t Now let's see each of the prompt, to understand the full breadth of the plugin's functionalities. -@note All the functions henceforth are not systems, they are mere functions called by the `update` system, which passes the `Input` resource to them. +@note All the functions henceforth are not systems, they are mere functions called by the system above, which passes the `Input` resource to them. @snippet input/main.cpp Showcase Action Press diff --git a/engine/samples/physics/main.cpp b/engine/samples/physics/main.cpp index 8994b169d4..7fcaa8447f 100644 --- a/engine/samples/physics/main.cpp +++ b/engine/samples/physics/main.cpp @@ -19,71 +19,6 @@ struct MaxTime float current = 0.0F; }; -static void settingsSystem(Settings& settings) -{ - settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER); -} - -static void setPaletteSystem(const Assets& assets, Renderer& renderer) -{ - // Read the palette's data and pass it to the renderer. - auto palette = assets.read(PaletteAsset); - renderer->setPalette(*palette); -} - -static void spawnCameraSystem(Commands cmds, ActiveCameras& activeCameras) -{ - // Spawn the camera entity. - activeCameras.entities[0] = - cmds.create() - .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 1000.0F}) - .add(Position{{50.0F, 50.0F, 50.0F}}) - .add(Rotation{glm::quatLookAt(glm::normalize(glm::vec3{-1.0F, -1.0F, -1.0F}), glm::vec3{0.0F, 1.0F, 0.0F})}) - .entity(); -} - -static void spawnLightSystem(Commands cmds) -{ - // Spawn the sun. - cmds.create() - .add(DirectionalLight{glm::vec3(1.0F), 1.0F}) - .add(Rotation{glm::quat(glm::vec3(glm::radians(45.0F), glm::radians(45.0F), 0))}); -} - -static void spawnCarSystem(Commands cmds, const Assets& assets) -{ - // Calculate the necessary offset to center the model on (0, 0, 0). - auto car = assets.read(CarAsset); - glm::vec3 offset = glm::vec3(car->size().x, 0.0F, car->size().z) / -2.0F; - - // Create the car entity - cmds.create() - .add(RenderableGrid{CarAsset, offset}) - .add(Position{{0.0F, 0.0F, 0.0F}}) - .add(PreviousPosition{{0.0F, 0.0F, 0.0F}}) - .add( - PhysicsVelocity{.velocity = {0.0F, 0.0F, 0.0F}, .force = {0.0F, 0.0F, 0.0F}, .impulse = {0.0F, 0.0F, 0.0F}}) - .add(PhysicsMass{.mass = 500.0F, .inverseMass = 1.0F / 500.0F}) - .add(AccumulatedCorrection{{0.0F, 0.0F, 0.0F}}) - .add(LocalToWorld{}); -} - -static void pushCarSystem(Query query, MaxTime& time, const DeltaTime& deltaTime) -{ - for (auto [velocity] : query) - { - if (time.current < time.max) - { - if (time.current == 0.0F) - { - velocity.impulse += glm::vec3(0.0F, 5000.0F, 0.0F); - } - velocity.force += glm::vec3(0.0F, 0.0F, -5000.0F); - time.current += deltaTime.value; - } - } -} - int main(int argc, char** argv) { Cubos cubos{argc, argv}; @@ -94,13 +29,68 @@ int main(int argc, char** argv) cubos.addPlugin(voxelsPlugin); cubos.addPlugin(physicsPlugin); - cubos.startupSystem(settingsSystem).tagged("cubos.settings"); - cubos.startupSystem(spawnCameraSystem); - cubos.startupSystem(spawnLightSystem); - cubos.startupSystem(setPaletteSystem).after("cubos.renderer.init"); - cubos.startupSystem(spawnCarSystem).after("cubos.settings").after("cubos.assets.bridge"); + cubos.startupSystem("configure Assets").tagged("cubos.settings").call([](Settings& settings) { + settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER); + }); + + cubos.startupSystem("create Camera").call([](Commands cmds, ActiveCameras& activeCameras) { + activeCameras.entities[0] = cmds.create() + .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 1000.0F}) + .add(Position{{50.0F, 50.0F, 50.0F}}) + .add(Rotation{glm::quatLookAt(glm::normalize(glm::vec3{-1.0F, -1.0F, -1.0F}), + glm::vec3{0.0F, 1.0F, 0.0F})}) + .entity(); + }); - cubos.system(pushCarSystem).tagged("cubos.physics.apply_forces"); + cubos.startupSystem("create the sun").call([](Commands cmds) { + cmds.create() + .add(DirectionalLight{glm::vec3(1.0F), 1.0F}) + .add(Rotation{glm::quat(glm::vec3(glm::radians(45.0F), glm::radians(45.0F), 0))}); + }); + + cubos.startupSystem("load the palette") + .after("cubos.renderer.init") + .call([](const Assets& assets, Renderer& renderer) { + auto palette = assets.read(PaletteAsset); + renderer->setPalette(*palette); + }); + + cubos.startupSystem("create a car") + .after("cubos.settings") + .after("cubos.assets.bridge") + .call([](Commands cmds, const Assets& assets) { + // Calculate the necessary offset to center the model on (0, 0, 0). + auto car = assets.read(CarAsset); + glm::vec3 offset = glm::vec3(car->size().x, 0.0F, car->size().z) / -2.0F; + + // Create the car entity + cmds.create() + .add(RenderableGrid{CarAsset, offset}) + .add(Position{{0.0F, 0.0F, 0.0F}}) + .add(PreviousPosition{{0.0F, 0.0F, 0.0F}}) + .add(PhysicsVelocity{ + .velocity = {0.0F, 0.0F, 0.0F}, .force = {0.0F, 0.0F, 0.0F}, .impulse = {0.0F, 0.0F, 0.0F}}) + .add(PhysicsMass{.mass = 500.0F, .inverseMass = 1.0F / 500.0F}) + .add(AccumulatedCorrection{{0.0F, 0.0F, 0.0F}}) + .add(LocalToWorld{}); + }); + + cubos.system("push the car") + .tagged("cubos.physics.apply_forces") + .call([](Query query, MaxTime& time, const DeltaTime& deltaTime) { + for (auto [velocity] : query) + { + if (time.current < time.max) + { + if (time.current == 0.0F) + { + velocity.impulse += glm::vec3(0.0F, 5000.0F, 0.0F); + } + velocity.force += glm::vec3(0.0F, 0.0F, -5000.0F); + time.current += deltaTime.value; + } + } + }); cubos.run(); } diff --git a/engine/samples/renderer/main.cpp b/engine/samples/renderer/main.cpp index 4139deb7d6..4f262c462d 100644 --- a/engine/samples/renderer/main.cpp +++ b/engine/samples/renderer/main.cpp @@ -7,100 +7,84 @@ using namespace cubos::engine; -static void settingsSystem(Settings& settings) -{ - // We don't load assets in this sample and we don't even have an assets folder, so we should - // disable assets IO. - settings.setBool("assets.io.enabled", false); -} - -/// [Setting the palette] -static void setPaletteSystem(Renderer& renderer) -{ - // Create a simple palette with 3 materials (red, green and blue). - renderer->setPalette(VoxelPalette{{ - {{1, 0, 0, 1}}, - {{0, 1, 0, 1}}, - {{0, 0, 1, 1}}, - }}); -} -/// [Setting the palette] - -/// [Spawning a voxel grid] -static void spawnVoxelGridSystem(Commands commands, Assets& assets) +int main() { - // Create a 2x2x2 grid whose voxels alternate between the materials defined in the palette. - auto gridAsset = assets.create(VoxelGrid{{2, 2, 2}, {1, 2, 3, 1, 2, 3, 1, 2}}); + Cubos cubos{}; - // Spawn an entity with a renderable grid component and a identity transform. - commands.create().add(RenderableGrid{gridAsset, {-1.0F, 0.0F, -1.0F}}).add(LocalToWorld{}); -} -/// [Spawning a voxel grid] + /// [Adding the plugin] + cubos.addPlugin(splitscreenPlugin); + cubos.addPlugin(rendererPlugin); + /// [Adding the plugin] -/// [Spawning a point light] -static void spawnLightSystem(Commands commands) -{ - // Spawn a point light. - commands.create() - .add(PointLight{.color = {1.0F, 1.0F, 1.0F}, .intensity = 1.0F, .range = 10.0F}) - .add(Position{{1.0F, 3.0F, -2.0F}}); -} -/// [Spawning a point light] + cubos.startupSystem("configure Assets").tagged("cubos.settings").call([](Settings& settings) { + // We don't load assets in this sample and we don't even have an assets folder, so we should + // disable assets IO. + settings.setBool("assets.io.enabled", false); + }); -/// [Setting the environment] -static void setEnvironmentSystem(RendererEnvironment& env) -{ - env.ambient = {0.2F, 0.2F, 0.2F}; - env.skyGradient[0] = {0.1F, 0.2F, 0.4F}; - env.skyGradient[1] = {0.6F, 0.6F, 0.8F}; -} -/// [Setting the environment] + /// [Setting the palette] + cubos.startupSystem("set the palette").after("cubos.renderer.init").call([](Renderer& renderer) { + // Create a simple palette with 3 materials (red, green and blue). + renderer->setPalette(VoxelPalette{{ + {{1, 0, 0, 1}}, + {{0, 1, 0, 1}}, + {{0, 0, 1, 1}}, + }}); + }); + /// [Setting the palette] -/// [Spawn the cameras] -static void spawnCamerasSystem(Commands commands, ActiveCameras& camera) -{ - // Spawn the a camera entity for the first viewport. - camera.entities[0] = - commands.create() - .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) - .add(Position{{-3.0, 1.0F, -3.0F}}) - .add(Rotation{glm::quatLookAt(glm::normalize(glm::vec3{1.0F, 0.0F, 1.0F}), glm::vec3{0.0F, 1.0F, 0.0F})}) - .entity(); + /// [Spawning a voxel grid] + cubos.startupSystem("create a voxel grid").call([](Commands commands, Assets& assets) { + // Create a 2x2x2 grid whose voxels alternate between the materials defined in the palette. + auto gridAsset = assets.create(VoxelGrid{{2, 2, 2}, {1, 2, 3, 1, 2, 3, 1, 2}}); - camera.entities[1] = - commands.create() - .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) - .add(Position{{-3.0, 1.0F, -3.0F}}) - .add(Rotation{glm::quatLookAt(glm::normalize(glm::vec3{1.0F, 0.0F, 1.0F}), glm::vec3{0.0F, 1.0F, 0.0F})}) - .entity(); + // Spawn an entity with a renderable grid component and a identity transform. + commands.create().add(RenderableGrid{gridAsset, {-1.0F, 0.0F, -1.0F}}).add(LocalToWorld{}); + }); + /// [Spawning a voxel grid] - camera.entities[2] = + /// [Spawning a point light] + cubos.startupSystem("create a point light").call([](Commands commands) { + // Spawn a point light. commands.create() - .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) - .add(Position{{-3.0, 1.0F, -3.0F}}) - .add(Rotation{glm::quatLookAt(glm::normalize(glm::vec3{1.0F, 0.0F, 1.0F}), glm::vec3{0.0F, 1.0F, 0.0F})}) - .entity(); -} -/// [Spawn the cameras] + .add(PointLight{.color = {1.0F, 1.0F, 1.0F}, .intensity = 1.0F, .range = 10.0F}) + .add(Position{{1.0F, 3.0F, -2.0F}}); + }); + /// [Spawning a point light] -int main() -{ - Cubos cubos{}; + /// [Setting the environment] + cubos.startupSystem("set the environment").call([](RendererEnvironment& env) { + env.ambient = {0.2F, 0.2F, 0.2F}; + env.skyGradient[0] = {0.1F, 0.2F, 0.4F}; + env.skyGradient[1] = {0.6F, 0.6F, 0.8F}; + }); + /// [Setting the environment] - /// [Adding the plugin] - cubos.addPlugin(splitscreenPlugin); - cubos.addPlugin(rendererPlugin); - /// [Adding the plugin] + /// [Spawn the cameras] + cubos.startupSystem("create cameras").call([](Commands commands, ActiveCameras& camera) { + // Spawn the a camera entity for the first viewport. + camera.entities[0] = commands.create() + .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) + .add(Position{{-3.0, 1.0F, -3.0F}}) + .add(Rotation{glm::quatLookAt(glm::normalize(glm::vec3{1.0F, 0.0F, 1.0F}), + glm::vec3{0.0F, 1.0F, 0.0F})}) + .entity(); - cubos.startupSystem(settingsSystem).tagged("cubos.settings"); + camera.entities[1] = commands.create() + .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) + .add(Position{{-3.0, 1.0F, -3.0F}}) + .add(Rotation{glm::quatLookAt(glm::normalize(glm::vec3{1.0F, 0.0F, 1.0F}), + glm::vec3{0.0F, 1.0F, 0.0F})}) + .entity(); - /// [Adding the systems] - cubos.startupSystem(setPaletteSystem).after("cubos.renderer.init"); - cubos.startupSystem(spawnVoxelGridSystem); - cubos.startupSystem(spawnLightSystem); - cubos.startupSystem(setEnvironmentSystem); - cubos.startupSystem(spawnCamerasSystem); - /// [Adding the systems] + camera.entities[2] = commands.create() + .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 100.0F}) + .add(Position{{-3.0, 1.0F, -3.0F}}) + .add(Rotation{glm::quatLookAt(glm::normalize(glm::vec3{1.0F, 0.0F, 1.0F}), + glm::vec3{0.0F, 1.0F, 0.0F})}) + .entity(); + }); + /// [Spawn the cameras] cubos.run(); } diff --git a/engine/samples/renderer/page.md b/engine/samples/renderer/page.md index e0e41ae999..ea544f65c7 100644 --- a/engine/samples/renderer/page.md +++ b/engine/samples/renderer/page.md @@ -12,6 +12,8 @@ configured with a simple scene, lighting and split-screen rendering. The plugin function is included from the @ref engine/renderer/plugin.hpp header. You may need to include other headers, depending on what you want to access. +In this sample we also use the split-screen plugin which automatically sets the viewport of each camera to achieve split-screen. + @snippet renderer/main.cpp Adding the plugin The first thing we're going to worry about is setting the @@ -19,6 +21,9 @@ The first thing we're going to worry about is setting the would usually be loaded from a file, but for this example we'll just create it manually. +Since this system accesses the @ref cubos::engine::Renderer "Renderer" resource, which is only +initialized on the tag `cubos.renderer.init`, we should specify that it must run after it. + @snippet renderer/main.cpp Setting the palette We should also spawn a @ref cubos::engine::VoxelGrid "voxel grid", so we have @@ -40,10 +45,3 @@ Lastly, without a camera, we won't be able to see anything. Cameras can be set using the @ref cubos::engine::ActiveCameras "ActiveCameras" resource. @snippet renderer/main.cpp Spawn the cameras - -Then, its just a matter of adding these systems to the engine. The only one -which requires special attention is the `setPaletteSystem`. This system -accesses the @ref cubos::engine::Renderer "Renderer" resource, which is only -initialized on the tag `cubos.renderer.init`. - -@snippet renderer/main.cpp Adding the systems diff --git a/engine/samples/scene/main.cpp b/engine/samples/scene/main.cpp index 62aff8eabd..b45615181f 100644 --- a/engine/samples/scene/main.cpp +++ b/engine/samples/scene/main.cpp @@ -38,51 +38,6 @@ CUBOS_REFLECT_IMPL(DistanceTo) static const Asset SceneAsset = AnyAsset("f0d86ba8-5f34-440f-a180-d9d12c8e8b91"); /// [Setting the asset] -static void settings(Settings& settings) -{ - settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER); -} - -/// [Spawning the scene] -static void spawnScene(Commands commands, const Assets& assets) -{ - auto sceneRead = assets.read(SceneAsset); - commands.spawn(sceneRead->blueprint); -} -/// [Spawning the scene] - -/// [Displaying the scene] -static void printStuff(Query numQuery, Query ownedByQuery, - Query distanceToQuery) -{ - using cubos::core::data::DebugSerializer; - using cubos::core::memory::Stream; - - DebugSerializer ser{Stream::stdOut}; - - for (auto [entity, num] : numQuery) - { - Stream::stdOut.print("Entity "); - ser.write(entity); - Stream::stdOut.printf(":\n- Num = {}\n", num.value); - - for (auto [distanceTo, what] : distanceToQuery.pin(0, entity)) - { - Stream::stdOut.print("- DistanceTo("); - ser.write(what); - Stream::stdOut.printf(") = {}\n", distanceTo.value); - } - - for (auto [ownedBy, owner] : ownedByQuery.pin(0, entity)) - { - Stream::stdOut.print("- OwnedBy("); - ser.write(owner); - Stream::stdOut.print(")\n"); - } - } -} -/// [Displaying the scene] - int main(int argc, char** argv) { Cubos cubos(argc, argv); @@ -95,12 +50,52 @@ int main(int argc, char** argv) cubos.addRelation(); cubos.addRelation(); - cubos.startupSystem(settings).tagged("cubos.settings"); - - /// [Adding the system] - cubos.startupSystem(spawnScene).tagged("spawn").tagged("cubos.assets"); - /// [Adding the system] + cubos.startupSystem("configure Assets").tagged("cubos.settings").call([](Settings& settings) { + settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER); + }); + + /// [Spawning the scene] + cubos.startupSystem("spawn the scene") + .tagged("spawn") + .tagged("cubos.assets") + .call([](Commands commands, const Assets& assets) { + auto sceneRead = assets.read(SceneAsset); + commands.spawn(sceneRead->blueprint); + }); + /// [Spawning the scene] + + /// [Printing the scene] + cubos.startupSystem("print the scene") + .after("spawn") + .call([](Query numQuery, Query ownedByQuery, + Query distanceToQuery) { + using cubos::core::data::DebugSerializer; + using cubos::core::memory::Stream; + + DebugSerializer ser{Stream::stdOut}; + + for (auto [entity, num] : numQuery) + { + Stream::stdOut.print("Entity "); + ser.write(entity); + Stream::stdOut.printf(":\n- Num = {}\n", num.value); + + for (auto [distanceTo, what] : distanceToQuery.pin(0, entity)) + { + Stream::stdOut.print("- DistanceTo("); + ser.write(what); + Stream::stdOut.printf(") = {}\n", distanceTo.value); + } + + for (auto [ownedBy, owner] : ownedByQuery.pin(0, entity)) + { + Stream::stdOut.print("- OwnedBy("); + ser.write(owner); + Stream::stdOut.print(")\n"); + } + } + }); + /// [Printing the scene] - cubos.startupSystem(printStuff).after("spawn"); cubos.run(); } diff --git a/engine/samples/scene/page.md b/engine/samples/scene/page.md index 7e3974f3cf..00a7f6fe7f 100644 --- a/engine/samples/scene/page.md +++ b/engine/samples/scene/page.md @@ -55,7 +55,7 @@ In this case, we'll run this system at startup, since we want to spawn it a sing Since it's a startup system, we'll have to tag it with `cubos.assets` to make sure it runs only after the scene bridge has been registered. On a real game, you could have, for example, a scene for an enemy which you spawn multiple times, instead of just once at startup. -@snippet scene/main.cpp Adding the system +@snippet scene/main.cpp Printing the scene This sample also contains a system which prints the components and relations of the spawned entities. If you run it, it should give you a list that has: diff --git a/engine/samples/settings/main.cpp b/engine/samples/settings/main.cpp index 658b546613..93426e6794 100644 --- a/engine/samples/settings/main.cpp +++ b/engine/samples/settings/main.cpp @@ -5,19 +5,17 @@ using namespace cubos::engine; -/// [System] -static void checkSettings(Settings& settings) -{ - CUBOS_INFO("{}", settings.getString("greeting", "Hello!")); -} -/// [System] - /// [Run] int main(int argc, char** argv) { Cubos cubos{argc, argv}; + cubos.addPlugin(settingsPlugin); - cubos.startupSystem(checkSettings).after("cubos.settings"); + + cubos.startupSystem("print setting value").after("cubos.settings").call([](Settings& settings) { + CUBOS_INFO("{}", settings.getString("greeting", "Hello!")); + }); + cubos.run(); } /// [Run] diff --git a/engine/samples/settings/page.md b/engine/samples/settings/page.md index 7bc6db386e..1703aac143 100644 --- a/engine/samples/settings/page.md +++ b/engine/samples/settings/page.md @@ -7,18 +7,16 @@ This example shows how the @ref settings-plugin plugin can be used to load settings from a file and command-line arguments. -Accesing the settings is straightforward: +@snippet settings/main.cpp Run -@snippet settings/main.cpp System +We add a system which prints the value of the setting `greetings`. +Notice that we make it run after the tag `cubos.settings`, so that the settings have already been loaded. If the setting `greetings` has been set on the `settings.json` file next to the sample's executable, or if it has been passed as a command-line argument (e.g. `./engine-sample.settings --greetings "Hello, world!"`), the sample will output that value. Otherwise, it will output `Hello!`, which we set as a default. -We want this system to run after the settings have been loaded, so we run it -after the tag `cubos.settings`. Notice that if we want the command-line -arguments to be loaded as settings, we need to pass `argc` and `argv` to the +Notice that if we want the command-line arguments to be loaded as settings, we need to pass `argc` and `argv` to the @ref cubos::engine::Cubos::Cubos(int, char**) "Cubos::Cubos(int, char**)" constructor. -@snippet settings/main.cpp Run diff --git a/engine/samples/voxels/main.cpp b/engine/samples/voxels/main.cpp index 997383bbee..278270853d 100644 --- a/engine/samples/voxels/main.cpp +++ b/engine/samples/voxels/main.cpp @@ -12,52 +12,6 @@ static const Asset CarAsset = AnyAsset("059c16e7-a439-44c7-9bdc-6e069 static const Asset PaletteAsset = AnyAsset("1aa5e234-28cb-4386-99b4-39386b0fc215"); /// [Get handles to assets] -static void settingsSystem(Settings& settings) -{ - settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER); -} - -/// [Load and set palette] -static void setPaletteSystem(const Assets& assets, Renderer& renderer) -{ - // Read the palette's data and pass it to the renderer. - auto palette = assets.read(PaletteAsset); - renderer->setPalette(*palette); -} -/// [Load and set palette] - -static void spawnCameraSystem(Commands cmds, ActiveCameras& activeCameras) -{ - // Spawn the camera entity. - activeCameras.entities[0] = - cmds.create() - .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 1000.0F}) - .add(Position{{50.0F, 50.0F, 50.0F}}) - .add(Rotation{glm::quatLookAt(glm::normalize(glm::vec3{-1.0F, -1.0F, -1.0F}), glm::vec3{0.0F, 1.0F, 0.0F})}) - .add(FreeCameraController{}) - .entity(); -} - -static void spawnLightSystem(Commands cmds) -{ - // Spawn the sun. - cmds.create() - .add(DirectionalLight{glm::vec3(1.0F), 1.0F}) - .add(Rotation{glm::quat(glm::vec3(glm::radians(45.0F), glm::radians(45.0F), 0))}); -} - -/// [Spawn car system] -static void spawnCarSystem(Commands cmds, const Assets& assets) -{ - // Calculate the necessary offset to center the model on (0, 0, 0). - auto car = assets.read(CarAsset); - glm::vec3 offset = glm::vec3(car->size().x, 0.0F, car->size().z) / -2.0F; - - // Create the car entity - cmds.create().add(RenderableGrid{CarAsset, offset}).add(LocalToWorld{}); -} -/// [Spawn car system] - int main(int argc, char** argv) { Cubos cubos{argc, argv}; @@ -68,13 +22,47 @@ int main(int argc, char** argv) /// [Adding the plugin] cubos.addPlugin(freeCameraControllerPlugin); - cubos.startupSystem(settingsSystem).tagged("cubos.settings"); - cubos.startupSystem(spawnCameraSystem); - cubos.startupSystem(spawnLightSystem); - /// [Adding systems] - cubos.startupSystem(setPaletteSystem).after("cubos.renderer.init"); - cubos.startupSystem(spawnCarSystem).tagged("cubos.assets"); - /// [Adding systems] + cubos.startupSystem("configure Assets").tagged("cubos.settings").call([](Settings& settings) { + settings.setString("assets.io.path", SAMPLE_ASSETS_FOLDER); + }); + + cubos.startupSystem("create a camera").call([](Commands cmds, ActiveCameras& activeCameras) { + // Spawn the camera entity. + activeCameras.entities[0] = cmds.create() + .add(Camera{.fovY = 60.0F, .zNear = 0.1F, .zFar = 1000.0F}) + .add(Position{{50.0F, 50.0F, 50.0F}}) + .add(Rotation{glm::quatLookAt(glm::normalize(glm::vec3{-1.0F, -1.0F, -1.0F}), + glm::vec3{0.0F, 1.0F, 0.0F})}) + .add(FreeCameraController{}) + .entity(); + }); + + cubos.startupSystem("create the sun").call([](Commands cmds) { + cmds.create() + .add(DirectionalLight{glm::vec3(1.0F), 1.0F}) + .add(Rotation{glm::quat(glm::vec3(glm::radians(45.0F), glm::radians(45.0F), 0))}); + }); + + /// [Load and set palette] + cubos.startupSystem("load and set pallete") + .after("cubos.renderer.init") + .call([](const Assets& assets, Renderer& renderer) { + // Read the palette's data and pass it to the renderer. + auto palette = assets.read(PaletteAsset); + renderer->setPalette(*palette); + }); + /// [Load and set palette] + + /// [Spawn car system] + cubos.startupSystem("create a car").tagged("cubos.assets").call([](Commands cmds, const Assets& assets) { + // Calculate the necessary offset to center the model on (0, 0, 0). + auto car = assets.read(CarAsset); + glm::vec3 offset = glm::vec3(car->size().x, 0.0F, car->size().z) / -2.0F; + + // Create the car entity + cmds.create().add(RenderableGrid{CarAsset, offset}).add(LocalToWorld{}); + }); + /// [Spawn car system] cubos.run(); } \ No newline at end of file diff --git a/engine/samples/voxels/page.md b/engine/samples/voxels/page.md index 14bbbc5ed8..9733485f51 100644 --- a/engine/samples/voxels/page.md +++ b/engine/samples/voxels/page.md @@ -27,8 +27,4 @@ Now, we can create an entity with our car asset. @snippet voxels/main.cpp Spawn car system -Finally, we just add these systems. - -@snippet voxels/main.cpp Adding systems - -And voilá, you now have a car floating in space. \ No newline at end of file +And voilá, you now have a car floating in space.