Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup and document engine-sample.events #504

Merged
merged 4 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/pages/3_examples/2_engine/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ multiple plugins of the engine:
- @subpage examples-engine-renderer - @copybrief examples-engine-renderer
- @subpage examples-engine-scene - @copybrief examples-engine-scene
- @subpage examples-engine-assets - @copybrief examples-engine-assets
- @subpage examples-engine-events - @copybrief examples-engine-events
122 changes: 72 additions & 50 deletions engine/samples/events/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,73 +3,93 @@

#include <cubos/engine/cubos.hpp>

using namespace cubos::core;
/// [Using type for aesthetic sake]
using cubos::core::ecs::EventReader;
using cubos::core::ecs::EventWriter;
/// [Using type for aesthetic sake]
using cubos::core::ecs::Write;

using namespace cubos::engine;

/// [Event struct]
struct MyEvent
{
int value;
};
/// [Event struct]

struct State
{
int step;
};

/// [Event reader system]
static void firstSystem(EventReader<MyEvent> reader)
{
for (const auto& event : reader)
{
CUBOS_INFO("A read {}", event.value);
}
}
/// [Event reader system]

/// [Event writer system]
static void secondSystem(EventWriter<MyEvent> writer, Write<State> state, Write<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<MyEvent> reader)
{
for (const auto& event : reader)
{
CUBOS_INFO("C read {}", event.value);
}
}

static void fourthSystem(EventReader<MyEvent> reader)
{
for (const auto& event : reader)
{
CUBOS_INFO("D read {}", event.value);
}
}

int main()
{
cubos::engine::Cubos cubos;
cubos.addResource<State>(State{.step = 0});

/// [Adding event]
cubos.addEvent<MyEvent>();
cubos.startupSystem([](ecs::Write<cubos::engine::ShouldQuit> quit) { quit->value = false; });
cubos
.system([](ecs::EventReader<MyEvent> reader) {
for (const auto& event : reader)
{
CUBOS_INFO("A read {}", event.value);
}
})
.tagged("A")
.before("B");
cubos
.system(
[](ecs::EventWriter<MyEvent> writer, ecs::Write<State> state, ecs::Write<cubos::engine::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");
}
})
.tagged("B");
cubos
.system([](ecs::EventReader<MyEvent> reader) {
for (const auto& event : reader)
{
CUBOS_INFO("C read {}", event.value);
}
})
.tagged("C")
.after("B");
cubos
.system([](ecs::EventReader<MyEvent> reader) {
for (const auto& event : reader)
{
CUBOS_INFO("D read {}", event.value);
}
})
.tagged("D")
.after("C");
/// [Adding event]

cubos.startupSystem([](Write<ShouldQuit> quit) { quit->value = false; });

/// [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]

/// [Expected results]
// Should print:
// B wrote 1 2 3
// C read 1
Expand All @@ -88,5 +108,7 @@ int main()
// D read 4
// D read 5
// D read 6
/// [Expected results]

cubos.run();
}
32 changes: 32 additions & 0 deletions engine/samples/events/page.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Events {#examples-engine-events}

@brief Using the @ref cubos::core::ecs::EventReader "EventReader" and @ref cubos::core::ecs::EventWriter "EventWriter".

This example shows how the @ref cubos::core::ecs::EventReader "EventReader" and the @ref cubos::core::ecs::EventWriter "EventWriter" system arguments can be used to communicate from one system to another.

For convinience, we introduce these names in our scope with using-declarations.

@snippet events/main.cpp Using type for aesthetic sake

Firstly, we need to create and register the event we want to emit. Here, our event is a simple struct with a single field, however, you can use any type you want.

@snippet events/main.cpp Event struct
@snippet events/main.cpp Adding event

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

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

There are a couple of things to note here. First, the order in which the systems appear to receive the event. C receives the event, followed by D, this happens because even though A comes before C it also come before B, which is where the event is emitted, this means that C and D can read the event emitted by B on that same frame, while A will only read it on the next frame. This also explains why on the second run, A is never displayed, indeed, the engine quit before A got a chance to receive it's so desired events. This shows how the results of the execution of systems that use events may vary with the order set for them, so special care should be taken when defining this.
Loading