Skip to content

Commit

Permalink
docs(engine): cleanup and document events sample
Browse files Browse the repository at this point in the history
  • Loading branch information
fallenatlas committed Sep 7, 2023
1 parent fcc60af commit 51a818e
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 49 deletions.
5 changes: 4 additions & 1 deletion docs/pages/3_examples/2_engine/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@

@brief Showcases features of the @ref engine library.

@note Under construction.
The following examples have fully documented tutorials on how to use the
multiple plugins of the engine:

- @subpage examples-engine-events - @copybrief examples-engine-events
114 changes: 66 additions & 48 deletions engine/samples/events/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,71 +5,87 @@

using namespace cubos::core;

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

struct State
{
int step;
};

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

/// [Event writer system]
static void secondSystem(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");
}
}
/// [Event writer system]

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

static void fourthSystem(ecs::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});

/// [Add Event]
cubos.addEvent<MyEvent>();
/// [Add Event]

/// [Set ShouldQuit resource]
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")
.beforeTag("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")
.afterTag("B");
cubos
.system([](ecs::EventReader<MyEvent> reader) {
for (const auto& event : reader)
{
CUBOS_INFO("D read {}", event.value);
}
})
.tagged("D")
.afterTag("C");
/// [Set ShouldQuit resource]

/// [Add systems]
cubos.system(firstSystem).tagged("A").beforeTag("B");
cubos.system(secondSystem).tagged("B");
cubos.system(thirdSystem).tagged("C").afterTag("B");
cubos.system(fourthSystem).tagged("D").afterTag("C");
/// [Add systems]

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

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

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

This example shows how the @ref cubos::core::ecs::EventReader and the @ref cubos::core::ecs::EventWriter can be used and configured, in a simple scene, to emit and read events. These are in the core, meaning, you don't need to add them to cubos.

Firstly, we need to create and register the event we want to emit. Here, our event has one variable, however, you can give it any number of variables of any type you want.

@snippet Event struct

To receive these events, we can make a simple system, using the @ref cubos::core::ecs::EventReader and iterating through all the events it has. This will be the layout of all our reader systems (A, C, D).

@snippet Event reader system

Now, to emit these events, we will use the @ref cubos::core::ecs::EventWriter. This system will emit 3 events on the first frame and another 3 on the second frame. By setting the value of the ShouldQuit resource to true on the second frame, the engine stops before reaching the third frame.

@snippet Event writer system

Lastly, let's set the order we want these system to execute in.

@snippet Adding the systems

These are the expected results with this order.

@snippet 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.

0 comments on commit 51a818e

Please sign in to comment.