Răsfoiți Sursa

Clean up data binding sample, add a basic example.

Michael Ragazzon 5 ani în urmă
părinte
comite
2a8d17d86b

+ 13 - 52
Samples/basic/databinding/data/databinding.rml

@@ -30,9 +30,9 @@ tabs
 	position: fixed;
 	clip: none;
 	text-align: right;
-	padding-left: 200px;
-	padding-right: 10px;
 	top: -47px;
+	left: 205px;
+	right: 10px;
 }
 tab
 {
@@ -104,43 +104,6 @@ p.title
 }
 
 
-/***  Decorators  ***/
-#decorators {
-	text-align: left;
-}
-#decorators p
-{
-	margin: 0.5em 0;
-}
-#decorators button.gradient
-{
-	decorator: gradient( vertical #415857 #5990A3 );
-	border: 2px #415857;
-	margin-right: 12px;
-}
-#decorators button.gradient.horizontal
-{
-	decorator: gradient( horizontal #DB6565 #F1B58A );
-	border: 2px #DB6565;
-}
-#decorators button.gradient:hover
-{
-	border-color: #F9EFA3;
-}
-
-/***  Font effects  ***/
-
-#font_effects div 
-{
-	display: inline-block;
-	width: 150px;
-	margin: 0px 30px 30px;
-	text-align: center;
-	font-size: 35px;
-	color: #b33;
-}
-
-
 /***  Forms  ***/
 
 form
@@ -176,8 +139,14 @@ form h2
 
 <body template="window">
 <tabset id="menu">
-<tab>Welcome</tab>
-<panel id="welcome" data-model="my_model">
+<tab>Basics</tab>
+<panel data-model="basics">
+	<h1>{{title}}</h1>
+	<p data-if="show_text">The quick brown fox jumps over the lazy {{animal}}.</p>
+	<input type="text" data-value="animal"/>
+</panel>
+<tab>Events</tab>
+<panel id="welcome" data-model="events">
 	<p class="title" style="margin-top: 1.8em;">{{hello_world}}<span style="color: blue;"> Rated: {{rating}}</span></p>
 	<p>Data binding demo. We rate this a good old {{rating}}!</p>
 	<input type="range" name="rating" min="0" max="100" step="1" value="50" data-value="rating"/>
@@ -191,19 +160,11 @@ form h2
 		Recorded mouse positions.<br/>
 		<span data-for="pos : positions"> x: {{ pos.x }}, y: {{ pos.y }}<br/></span>
 	</div>
-	<h1>{{delightful_invader.name}}</h1>
-	<img data-attr-sprite="delightful_invader.sprite" data-style-image-color="rating < 80 ? 'black' : 'green'"/>
+	<img sprite="icon-invader" data-style-image-color="rating < 80 ? 'black' : 'green'"/>
 	<p>
-		Indices: <span style="padding-left: 1em;" data-for="i : indices"> {{ i * 2 + (i > 10 ? ' wow!' | to_upper : '') }}</span>
+		For loop with data expressions:<br/>
+		<span style="padding-left: 1em;" data-for="i : list"> {{ i * 2 + (i > 10 ? ' wow!' | to_upper : '') }}</span>
 	</p>
-	<div data-for="invader : invaders">
-		<h1 data-class-red="rating < 30" data-class-big="rating == 0">{{invader.name}}</h1>
-		<p>Invader {{it_index + 1}} of {{ invaders.size }}.</p>
-		<img data-attr-sprite="invader.sprite" data-style-image-color="invader.color"/>
-		<p>
-			Damage: <span data-for="invader.damage"> {{it}} </span>
-		</p>
-	</div> 
 </panel>
 <tab>Invaders</tab>
 <panel id="invaders" data-model="invaders">

+ 233 - 224
Samples/basic/databinding/src/main.cpp

@@ -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());
 

+ 1 - 1
Source/Core/DataModel.cpp

@@ -319,7 +319,7 @@ bool DataModel::GetVariableInto(const DataAddress& address, Variant& out_value)
 void DataModel::DirtyVariable(const String& variable_name)
 {
 	RMLUI_ASSERTMSG(LegalVariableName(variable_name) == nullptr, "Illegal variable name provided. Only top-level variables can be dirtied.");
-	RMLUI_ASSERTMSG(variables.count(variable_name) == 1, "Variable name not found among added variables.");
+	RMLUI_ASSERTMSG(variables.count(variable_name) == 1, "In DirtyVariable: Variable name not found among added variables.");
 	dirty_variables.emplace(variable_name);
 }