|
|
@@ -35,328 +35,336 @@
|
|
|
#include <numeric>
|
|
|
|
|
|
|
|
|
-class DemoWindow : public Rml::Core::EventListener
|
|
|
-{
|
|
|
-public:
|
|
|
- DemoWindow(const Rml::Core::String &title, const Rml::Core::Vector2f &position, Rml::Core::Context *context)
|
|
|
- {
|
|
|
- using namespace Rml::Core;
|
|
|
- document = context->LoadDocument("basic/databinding/data/databinding.rml");
|
|
|
- if (document)
|
|
|
- {
|
|
|
- document->GetElementById("title")->SetInnerRML(title);
|
|
|
- document->SetProperty(PropertyId::Left, Property(position.x, Property::PX));
|
|
|
- document->SetProperty(PropertyId::Top, Property(position.y, Property::PX));
|
|
|
+namespace BasicExample {
|
|
|
|
|
|
- document->Show();
|
|
|
- }
|
|
|
- }
|
|
|
+ Rml::Core::DataModelHandle model_handle;
|
|
|
+
|
|
|
+ struct MyData {
|
|
|
+ Rml::Core::String title = "Simple data binding example";
|
|
|
+ Rml::Core::String animal = "dog";
|
|
|
+ bool show_text = true;
|
|
|
+ } my_data;
|
|
|
|
|
|
- void Update()
|
|
|
+ bool Initialize(Rml::Core::Context* context)
|
|
|
{
|
|
|
+ Rml::Core::DataModelConstructor constructor = context->CreateDataModel("basics");
|
|
|
+ if (!constructor)
|
|
|
+ return false;
|
|
|
|
|
|
+ constructor.Bind("title", &my_data.title);
|
|
|
+ constructor.Bind("animal", &my_data.animal);
|
|
|
+ constructor.Bind("show_text", &my_data.show_text);
|
|
|
+
|
|
|
+ model_handle = constructor.GetModelHandle();
|
|
|
+
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
- void Shutdown()
|
|
|
+ void Update()
|
|
|
{
|
|
|
- if (document)
|
|
|
- {
|
|
|
- document->Close();
|
|
|
- document = nullptr;
|
|
|
- }
|
|
|
+ model_handle.Update();
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- void ProcessEvent(Rml::Core::Event& event) override
|
|
|
- {
|
|
|
- using namespace Rml::Core;
|
|
|
|
|
|
- switch (event.GetId())
|
|
|
- {
|
|
|
- case EventId::Keydown:
|
|
|
- {
|
|
|
- Rml::Core::Input::KeyIdentifier key_identifier = (Rml::Core::Input::KeyIdentifier) event.GetParameter< int >("key_identifier", 0);
|
|
|
- bool ctrl_key = event.GetParameter< bool >("ctrl_key", false);
|
|
|
+namespace EventsExample {
|
|
|
|
|
|
- if (key_identifier == Rml::Core::Input::KI_ESCAPE)
|
|
|
- {
|
|
|
- Shell::RequestExit();
|
|
|
- }
|
|
|
- else if (key_identifier == Rml::Core::Input::KI_F8)
|
|
|
- {
|
|
|
- Rml::Debugger::SetVisible(!Rml::Debugger::IsVisible());
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
+ Rml::Core::DataModelHandle model_handle;
|
|
|
|
|
|
- default:
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
+ struct MyData {
|
|
|
+ Rml::Core::String hello_world = "Hello World!";
|
|
|
+ Rml::Core::String mouse_detector = "Mouse-move <em>Detector</em>.";
|
|
|
+ int rating = 99;
|
|
|
|
|
|
- Rml::Core::ElementDocument * GetDocument() {
|
|
|
- return document;
|
|
|
- }
|
|
|
+ std::vector<float> list = { 1, 2, 3, 4, 5 };
|
|
|
|
|
|
+ std::vector<Rml::Core::Vector2f> positions;
|
|
|
|
|
|
-private:
|
|
|
- Rml::Core::ElementDocument *document = nullptr;
|
|
|
-};
|
|
|
+ void AddMousePos(Rml::Core::DataModelHandle model_handle, Rml::Core::Event& ev, const Rml::Core::VariantList& arguments)
|
|
|
+ {
|
|
|
+ positions.emplace_back(ev.GetParameter("mouse_x", 0.f), ev.GetParameter("mouse_y", 0.f));
|
|
|
+ model_handle.DirtyVariable("positions");
|
|
|
+ }
|
|
|
|
|
|
+ } my_data;
|
|
|
|
|
|
|
|
|
-struct Invader {
|
|
|
- Rml::Core::String name;
|
|
|
- Rml::Core::String sprite;
|
|
|
- Rml::Core::Colourb color{ 255, 255, 255 };
|
|
|
- std::vector<int> damage;
|
|
|
- float danger_rating = 50;
|
|
|
+ void ClearPositions(Rml::Core::DataModelHandle model_handle, Rml::Core::Event& ev, const Rml::Core::VariantList& arguments)
|
|
|
+ {
|
|
|
+ my_data.positions.clear();
|
|
|
+ model_handle.DirtyVariable("positions");
|
|
|
+ }
|
|
|
|
|
|
- void GetColor(Rml::Core::Variant& variant) {
|
|
|
- variant = "rgba(" + Rml::Core::ToString(color) + ')';
|
|
|
+ void HasGoodRating(Rml::Core::Variant& variant)
|
|
|
+ {
|
|
|
+ variant = int(my_data.rating > 50);
|
|
|
}
|
|
|
- void SetColor(const Rml::Core::Variant& variant) {
|
|
|
+
|
|
|
+
|
|
|
+ bool Initialize(Rml::Core::Context* context)
|
|
|
+ {
|
|
|
using namespace Rml::Core;
|
|
|
- String str = variant.Get<String>();
|
|
|
- if (str.size() > 6)
|
|
|
- str = str.substr(5, str.size() - 6);
|
|
|
- color = Rml::Core::FromString<Colourb>(variant.Get<String>());
|
|
|
- }
|
|
|
-};
|
|
|
+ DataModelConstructor constructor = context->CreateDataModel("events");
|
|
|
+ if (!constructor)
|
|
|
+ return false;
|
|
|
|
|
|
+ // Register all the types first
|
|
|
+ constructor.RegisterArray<std::vector<float>>();
|
|
|
|
|
|
-struct MyData {
|
|
|
- Rml::Core::String hello_world = "Hello World!";
|
|
|
- Rml::Core::String mouse_detector = "Mouse-move <em>Detector</em>.";
|
|
|
+ if (auto vec2_handle = constructor.RegisterStruct<Vector2f>())
|
|
|
+ {
|
|
|
+ vec2_handle.RegisterMember("x", &Vector2f::x);
|
|
|
+ vec2_handle.RegisterMember("y", &Vector2f::y);
|
|
|
+ }
|
|
|
+ constructor.RegisterArray<std::vector<Vector2f>>();
|
|
|
|
|
|
- int rating = 99;
|
|
|
+ // Bind the variables to the data model
|
|
|
+ constructor.Bind("hello_world", &my_data.hello_world);
|
|
|
+ constructor.Bind("mouse_detector", &my_data.mouse_detector);
|
|
|
+ constructor.Bind("rating", &my_data.rating);
|
|
|
+ constructor.BindFunc("good_rating", &HasGoodRating);
|
|
|
+ constructor.BindFunc("great_rating", [](Variant& variant) {
|
|
|
+ variant = int(my_data.rating > 80);
|
|
|
+ });
|
|
|
|
|
|
- Invader delightful_invader{ "Delightful invader", "icon-invader" };
|
|
|
+ constructor.Bind("list", &my_data.list);
|
|
|
|
|
|
- std::vector<Invader> invaders = {
|
|
|
- Invader{"Angry invader", "icon-invader", {255, 40, 30}, {3, 6, 7}},
|
|
|
- Invader{"Harmless invader", "icon-flag", {20, 40, 255}, {5, 0}},
|
|
|
- Invader{"Hero", "icon-game", {255, 255, 30}, {10, 11, 12, 13, 14}},
|
|
|
- };
|
|
|
+ constructor.Bind("positions", &my_data.positions);
|
|
|
|
|
|
- std::vector<int> indices = { 1, 2, 3, 4, 5 };
|
|
|
+ constructor.BindEventCallback("clear_positions", &ClearPositions);
|
|
|
+ constructor.BindEventCallback("add_mouse_pos", &MyData::AddMousePos, &my_data);
|
|
|
|
|
|
- std::vector<Rml::Core::Vector2f> positions;
|
|
|
|
|
|
- void AddMousePos(Rml::Core::DataModelHandle model_handle, Rml::Core::Event& ev, const Rml::Core::VariantList& arguments)
|
|
|
- {
|
|
|
- positions.emplace_back(ev.GetParameter("mouse_x", 0.f), ev.GetParameter("mouse_y", 0.f));
|
|
|
- model_handle.DirtyVariable("positions");
|
|
|
+ model_handle = constructor.GetModelHandle();
|
|
|
+
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
-} my_data;
|
|
|
+ void Update()
|
|
|
+ {
|
|
|
+ if (model_handle.IsVariableDirty("rating"))
|
|
|
+ {
|
|
|
+ model_handle.DirtyVariable("good_rating");
|
|
|
+ model_handle.DirtyVariable("great_rating");
|
|
|
|
|
|
+ size_t new_size = my_data.rating / 10 + 1;
|
|
|
+ if (new_size != my_data.list.size())
|
|
|
+ {
|
|
|
+ my_data.list.resize(new_size);
|
|
|
+ std::iota(my_data.list.begin(), my_data.list.end(), float(new_size));
|
|
|
+ model_handle.DirtyVariable("list");
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-void ClearPositions(Rml::Core::DataModelHandle model_handle, Rml::Core::Event& ev, const Rml::Core::VariantList& arguments)
|
|
|
-{
|
|
|
- my_data.positions.clear();
|
|
|
- model_handle.DirtyVariable("positions");
|
|
|
+ model_handle.Update();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-void HasGoodRating(Rml::Core::Variant& variant) {
|
|
|
- variant = int(my_data.rating > 50);
|
|
|
-}
|
|
|
|
|
|
-struct InvaderModelData {
|
|
|
- double time_last_invader_spawn = 0;
|
|
|
- double time_last_weapons_launched = 0;
|
|
|
|
|
|
- float incoming_invaders_rate = 10; // Per minute
|
|
|
+namespace InvadersExample {
|
|
|
|
|
|
- std::vector<Invader> invaders = {
|
|
|
- Invader{"Angry invader", "icon-invader", {255, 40, 30}, {3, 6, 7}, 80}
|
|
|
+ Rml::Core::DataModelHandle model_handle;
|
|
|
+
|
|
|
+ struct Invader {
|
|
|
+ Rml::Core::String name;
|
|
|
+ Rml::Core::String sprite;
|
|
|
+ Rml::Core::Colourb color{ 255, 255, 255 };
|
|
|
+ std::vector<int> damage;
|
|
|
+ float danger_rating = 50;
|
|
|
+
|
|
|
+ void GetColor(Rml::Core::Variant& variant) {
|
|
|
+ variant = "rgba(" + Rml::Core::ToString(color) + ')';
|
|
|
+ }
|
|
|
+ void SetColor(const Rml::Core::Variant& variant) {
|
|
|
+ using namespace Rml::Core;
|
|
|
+ String str = variant.Get<String>();
|
|
|
+ if (str.size() > 6)
|
|
|
+ str = str.substr(5, str.size() - 6);
|
|
|
+ color = Rml::Core::FromString<Colourb>(variant.Get<String>());
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
- void LaunchWeapons(Rml::Core::DataModelHandle model_handle, Rml::Core::Event& /*ev*/, const Rml::Core::VariantList& /*arguments*/)
|
|
|
- {
|
|
|
- invaders.clear();
|
|
|
- model_handle.DirtyVariable("invaders");
|
|
|
- }
|
|
|
+ struct InvadersData {
|
|
|
+ double time_last_invader_spawn = 0;
|
|
|
+ double time_last_weapons_launched = 0;
|
|
|
|
|
|
-} invaders_data;
|
|
|
+ float incoming_invaders_rate = 10; // Per minute
|
|
|
|
|
|
+ std::vector<Invader> invaders = {
|
|
|
+ Invader{"Angry invader", "icon-invader", {255, 40, 30}, {3, 6, 7}, 80}
|
|
|
+ };
|
|
|
|
|
|
-Rml::Core::DataModelHandle invaders_model, my_model;
|
|
|
+ void LaunchWeapons(Rml::Core::DataModelHandle model_handle, Rml::Core::Event& /*ev*/, const Rml::Core::VariantList& /*arguments*/)
|
|
|
+ {
|
|
|
+ invaders.clear();
|
|
|
+ model_handle.DirtyVariable("invaders");
|
|
|
+ }
|
|
|
|
|
|
+ } invaders_data;
|
|
|
|
|
|
-bool SetupDataBinding(Rml::Core::Context* context)
|
|
|
-{
|
|
|
- // The invaders model
|
|
|
+ bool Initialize(Rml::Core::Context* context)
|
|
|
{
|
|
|
Rml::Core::DataModelConstructor constructor = context->CreateDataModel("invaders");
|
|
|
if (!constructor)
|
|
|
return false;
|
|
|
|
|
|
- constructor.Bind("incoming_invaders_rate", &invaders_data.incoming_invaders_rate);
|
|
|
-
|
|
|
+ // Since Invader::damage is an array type.
|
|
|
constructor.RegisterArray<std::vector<int>>();
|
|
|
|
|
|
+ // Structs are registered by adding all its members through the returned handle.
|
|
|
if (auto invader_handle = constructor.RegisterStruct<Invader>())
|
|
|
{
|
|
|
invader_handle.RegisterMember("name", &Invader::name);
|
|
|
invader_handle.RegisterMember("sprite", &Invader::sprite);
|
|
|
invader_handle.RegisterMember("damage", &Invader::damage);
|
|
|
invader_handle.RegisterMember("danger_rating", &Invader::danger_rating);
|
|
|
- invader_handle.RegisterMemberFunc("color", &Invader::GetColor, &Invader::SetColor);
|
|
|
+
|
|
|
+ // Getter and setter functions can also be used.
|
|
|
+ invader_handle.RegisterMemberFunc("color", &Invader::GetColor);
|
|
|
}
|
|
|
|
|
|
+ // We can even have an Array of Structs, infinitely nested if we so desire.
|
|
|
+ // Make sure the underlying type (here Invader) is registered before the array.
|
|
|
constructor.RegisterArray<std::vector<Invader>>();
|
|
|
+
|
|
|
+ // Now we can bind the variables to the model.
|
|
|
+ constructor.Bind("incoming_invaders_rate", &invaders_data.incoming_invaders_rate);
|
|
|
constructor.Bind("invaders", &invaders_data.invaders);
|
|
|
|
|
|
- constructor.BindEventCallback("launch_weapons", &InvaderModelData::LaunchWeapons, &invaders_data);
|
|
|
+ // This function will be called when the user clicks the 'Launch weapons' button.
|
|
|
+ constructor.BindEventCallback("launch_weapons", &InvadersData::LaunchWeapons, &invaders_data);
|
|
|
|
|
|
- invaders_model = constructor.GetModelHandle();
|
|
|
- }
|
|
|
+ model_handle = constructor.GetModelHandle();
|
|
|
|
|
|
+ return true;
|
|
|
+ }
|
|
|
|
|
|
- // The main model
|
|
|
+ void Update(const double t)
|
|
|
{
|
|
|
- Rml::Core::DataModelConstructor constructor = context->CreateDataModel("my_model");
|
|
|
- if (!constructor)
|
|
|
- return false;
|
|
|
-
|
|
|
- constructor.Bind("hello_world", &my_data.hello_world);
|
|
|
- constructor.Bind("mouse_detector", &my_data.mouse_detector);
|
|
|
- constructor.Bind("rating", &my_data.rating);
|
|
|
- constructor.BindFunc("good_rating", &HasGoodRating);
|
|
|
- constructor.BindFunc("great_rating", [](Rml::Core::Variant& variant) {
|
|
|
- variant = int(my_data.rating > 80);
|
|
|
- });
|
|
|
-
|
|
|
- constructor.Bind("delightful_invader", &my_data.delightful_invader);
|
|
|
-
|
|
|
- //constructor.RegisterArray<std::vector<Invader>>();
|
|
|
-
|
|
|
- constructor.Bind("indices", &my_data.indices);
|
|
|
- constructor.Bind("invaders", &my_data.invaders);
|
|
|
-
|
|
|
- if (auto vec2_handle = constructor.RegisterStruct<Rml::Core::Vector2f>())
|
|
|
+ // Add new invaders at regular time intervals.
|
|
|
+ const double t_next_spawn = invaders_data.time_last_invader_spawn + 60.0 / double(invaders_data.incoming_invaders_rate);
|
|
|
+ if (t >= t_next_spawn)
|
|
|
{
|
|
|
- vec2_handle.RegisterMember("x", &Rml::Core::Vector2f::x);
|
|
|
- vec2_handle.RegisterMember("y", &Rml::Core::Vector2f::y);
|
|
|
+ using namespace Rml::Core;
|
|
|
+ const int num_items = 4;
|
|
|
+ static std::array<String, num_items> names = { "Angry invader", "Harmless invader", "Deceitful invader", "Cute invader" };
|
|
|
+ static std::array<String, num_items> sprites = { "icon-invader", "icon-flag", "icon-game", "icon-waves" };
|
|
|
+ static std::array<Colourb, num_items> colors = { { { 255, 40, 30 }, {20, 40, 255}, {255, 255, 30}, {230, 230, 230} } };
|
|
|
+
|
|
|
+ Invader new_invader;
|
|
|
+ new_invader.name = names[rand() % num_items];
|
|
|
+ new_invader.sprite = sprites[rand() % num_items];
|
|
|
+ new_invader.color = colors[rand() % num_items];
|
|
|
+ new_invader.danger_rating = float((rand() % 100) + 1);
|
|
|
+ invaders_data.invaders.push_back(new_invader);
|
|
|
+
|
|
|
+ model_handle.DirtyVariable("invaders");
|
|
|
+ invaders_data.time_last_invader_spawn = t;
|
|
|
}
|
|
|
|
|
|
- constructor.RegisterArray<std::vector<Rml::Core::Vector2f>>();
|
|
|
- constructor.Bind("positions", &my_data.positions);
|
|
|
-
|
|
|
- constructor.BindEventCallback("clear_positions", &ClearPositions);
|
|
|
- constructor.BindEventCallback("add_mouse_pos", &MyData::AddMousePos, &my_data);
|
|
|
+ // Launch shots from a random invader.
|
|
|
+ if (t >= invaders_data.time_last_weapons_launched + 1.0)
|
|
|
+ {
|
|
|
+ if (!invaders_data.invaders.empty())
|
|
|
+ {
|
|
|
+ const size_t index = size_t(rand() % int(invaders_data.invaders.size()));
|
|
|
|
|
|
- my_model = constructor.GetModelHandle();
|
|
|
- }
|
|
|
+ Invader& invader = invaders_data.invaders[index];
|
|
|
+ invader.damage.push_back(rand() % int(invader.danger_rating));
|
|
|
|
|
|
+ model_handle.DirtyVariable("invaders");
|
|
|
+ }
|
|
|
+ invaders_data.time_last_weapons_launched = t;
|
|
|
+ }
|
|
|
|
|
|
- return true;
|
|
|
+ model_handle.Update();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
|
-Rml::Core::Context* context = nullptr;
|
|
|
-ShellRenderInterfaceExtensions *shell_renderer;
|
|
|
-std::unique_ptr<DemoWindow> demo_window;
|
|
|
|
|
|
-void GameLoop()
|
|
|
+class DemoWindow : public Rml::Core::EventListener
|
|
|
{
|
|
|
- if (my_model.IsVariableDirty("rating"))
|
|
|
+public:
|
|
|
+ DemoWindow(const Rml::Core::String &title, const Rml::Core::Vector2f &position, Rml::Core::Context *context)
|
|
|
{
|
|
|
- my_model.DirtyVariable("good_rating");
|
|
|
- my_model.DirtyVariable("great_rating");
|
|
|
-
|
|
|
- size_t new_size = my_data.rating / 10 + 1;
|
|
|
- if (new_size != my_data.indices.size())
|
|
|
+ using namespace Rml::Core;
|
|
|
+ document = context->LoadDocument("basic/databinding/data/databinding.rml");
|
|
|
+ if (document)
|
|
|
{
|
|
|
- my_data.indices.resize(new_size);
|
|
|
- std::iota(my_data.indices.begin(), my_data.indices.end(), int(new_size));
|
|
|
- my_model.DirtyVariable("indices");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const double t = Rml::Core::GetSystemInterface()->GetElapsedTime();
|
|
|
+ document->GetElementById("title")->SetInnerRML(title);
|
|
|
+ document->SetProperty(PropertyId::Left, Property(position.x, Property::PX));
|
|
|
+ document->SetProperty(PropertyId::Top, Property(position.y, Property::PX));
|
|
|
|
|
|
- const double t_next_spawn = invaders_data.time_last_invader_spawn + 60.0 / double(invaders_data.incoming_invaders_rate);
|
|
|
- if (t >= t_next_spawn)
|
|
|
- {
|
|
|
- using namespace Rml::Core;
|
|
|
- const int num_items = 4;
|
|
|
- static std::array<String, num_items> names = { "Angry invader", "Harmless invader", "Deceitful invader", "Cute invader" };
|
|
|
- static std::array<String, num_items> sprites = { "icon-invader", "icon-flag", "icon-game", "icon-waves" };
|
|
|
- static std::array<Colourb, num_items> colors = {{ { 255, 40, 30 }, {20, 40, 255}, {255, 255, 30}, {230, 230, 230} }};
|
|
|
-
|
|
|
- Invader new_invader;
|
|
|
- new_invader.name = names[rand() % num_items];
|
|
|
- new_invader.sprite = sprites[rand() % num_items];
|
|
|
- new_invader.color = colors[rand() % num_items];
|
|
|
- new_invader.danger_rating = float((rand() % 100) + 1);
|
|
|
- invaders_data.invaders.push_back(new_invader);
|
|
|
-
|
|
|
- invaders_model.DirtyVariable("invaders");
|
|
|
- invaders_data.time_last_invader_spawn = t;
|
|
|
+ document->Show();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- if (t >= invaders_data.time_last_weapons_launched + 1.0)
|
|
|
+ void Shutdown()
|
|
|
{
|
|
|
- if (!invaders_data.invaders.empty())
|
|
|
+ if (document)
|
|
|
{
|
|
|
- const size_t index = size_t(rand() % int(invaders_data.invaders.size()));
|
|
|
-
|
|
|
- Invader& invader = invaders_data.invaders[index];
|
|
|
- invader.damage.push_back(rand() % int(invader.danger_rating));
|
|
|
-
|
|
|
- invaders_model.DirtyVariable("invaders");
|
|
|
+ document->Close();
|
|
|
+ document = nullptr;
|
|
|
}
|
|
|
- invaders_data.time_last_weapons_launched = t;
|
|
|
}
|
|
|
|
|
|
- my_model.Update();
|
|
|
-
|
|
|
- invaders_model.Update();
|
|
|
-
|
|
|
- demo_window->Update();
|
|
|
- context->Update();
|
|
|
-
|
|
|
- shell_renderer->PrepareRenderBuffer();
|
|
|
- context->Render();
|
|
|
- shell_renderer->PresentRenderBuffer();
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-class DemoEventListener : public Rml::Core::EventListener
|
|
|
-{
|
|
|
-public:
|
|
|
- DemoEventListener(const Rml::Core::String& value, Rml::Core::Element* element) : value(value), element(element) {}
|
|
|
-
|
|
|
void ProcessEvent(Rml::Core::Event& event) override
|
|
|
{
|
|
|
using namespace Rml::Core;
|
|
|
|
|
|
- if (value == "exit")
|
|
|
+ switch (event.GetId())
|
|
|
+ {
|
|
|
+ case EventId::Keydown:
|
|
|
{
|
|
|
- Shell::RequestExit();
|
|
|
+ Rml::Core::Input::KeyIdentifier key_identifier = (Rml::Core::Input::KeyIdentifier) event.GetParameter< int >("key_identifier", 0);
|
|
|
+
|
|
|
+ if (key_identifier == Rml::Core::Input::KI_ESCAPE)
|
|
|
+ {
|
|
|
+ Shell::RequestExit();
|
|
|
+ }
|
|
|
+ else if (key_identifier == Rml::Core::Input::KI_F8)
|
|
|
+ {
|
|
|
+ Rml::Debugger::SetVisible(!Rml::Debugger::IsVisible());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- void OnDetach(Rml::Core::Element* element) override { delete this; }
|
|
|
+ Rml::Core::ElementDocument * GetDocument() {
|
|
|
+ return document;
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
private:
|
|
|
- Rml::Core::String value;
|
|
|
- Rml::Core::Element* element;
|
|
|
+ Rml::Core::ElementDocument *document = nullptr;
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
-class DemoEventListenerInstancer : public Rml::Core::EventListenerInstancer
|
|
|
+Rml::Core::Context* context = nullptr;
|
|
|
+ShellRenderInterfaceExtensions *shell_renderer;
|
|
|
+
|
|
|
+void GameLoop()
|
|
|
{
|
|
|
-public:
|
|
|
- Rml::Core::EventListener* InstanceEventListener(const Rml::Core::String& value, Rml::Core::Element* element) override
|
|
|
- {
|
|
|
- return new DemoEventListener(value, element);
|
|
|
- }
|
|
|
-};
|
|
|
+ const double t = Rml::Core::GetSystemInterface()->GetElapsedTime();
|
|
|
+
|
|
|
+ BasicExample::Update();
|
|
|
+ EventsExample::Update();
|
|
|
+ InvadersExample::Update(t);
|
|
|
+
|
|
|
+ context->Update();
|
|
|
+
|
|
|
+ shell_renderer->PrepareRenderBuffer();
|
|
|
+ context->Render();
|
|
|
+ shell_renderer->PresentRenderBuffer();
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
|
|
|
#if defined RMLUI_PLATFORM_WIN32
|
|
|
@@ -402,7 +410,11 @@ int main(int RMLUI_UNUSED_PARAMETER(argc), char** RMLUI_UNUSED_PARAMETER(argv))
|
|
|
// Create the main RmlUi context and set it on the shell's input layer.
|
|
|
context = Rml::Core::CreateContext("main", Rml::Core::Vector2i(width, height));
|
|
|
|
|
|
- if (!context || !SetupDataBinding(context))
|
|
|
+ if (!context
|
|
|
+ || !BasicExample::Initialize(context)
|
|
|
+ || !EventsExample::Initialize(context)
|
|
|
+ || !InvadersExample::Initialize(context)
|
|
|
+ )
|
|
|
{
|
|
|
Rml::Core::Shutdown();
|
|
|
Shell::Shutdown();
|
|
|
@@ -414,12 +426,9 @@ int main(int RMLUI_UNUSED_PARAMETER(argc), char** RMLUI_UNUSED_PARAMETER(argv))
|
|
|
Input::SetContext(context);
|
|
|
shell_renderer->SetContext(context);
|
|
|
|
|
|
- DemoEventListenerInstancer event_listener_instancer;
|
|
|
- Rml::Core::Factory::RegisterEventListenerInstancer(&event_listener_instancer);
|
|
|
-
|
|
|
Shell::LoadFonts("assets/");
|
|
|
|
|
|
- demo_window = std::make_unique<DemoWindow>("Data binding", Rml::Core::Vector2f(150, 50), context);
|
|
|
+ auto demo_window = std::make_unique<DemoWindow>("Data binding", Rml::Core::Vector2f(150, 50), context);
|
|
|
demo_window->GetDocument()->AddEventListener(Rml::Core::EventId::Keydown, demo_window.get());
|
|
|
demo_window->GetDocument()->AddEventListener(Rml::Core::EventId::Keyup, demo_window.get());
|
|
|
|