diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4c568ad..f4c0ec8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,17 +22,22 @@ add_library(rmlui_backend STATIC
vendor/rmlui_backend/RmlUi_Renderer_GL3.cpp
)
+file(GLOB_RECURSE PAGE_SOURCES CONFIGURE_DEPENDS "src/pages/*.cpp")
+file(GLOB_RECURSE ELEMENT_SOURCES CONFIGURE_DEPENDS "src/elements/*.cpp")
+
add_executable(${PROJECT_NAME}
src/main.cpp
src/app.cpp
src/lua_app_api.cpp
src/page.cpp
- src/pages/test_page.cpp
+ ${PAGE_SOURCES}
+ ${ELEMENT_SOURCES}
)
target_include_directories(${PROJECT_NAME} PRIVATE
src
+ src/elements
vendor/rmlui_backend
${FREETYPE_INCLUDE_DIRS}
)
diff --git a/assets/pages/lua-test.rcss b/assets/pages/lua-test.rcss
new file mode 100644
index 0000000..e69de29
diff --git a/assets/pages/test-page.lua b/assets/pages/test-page.lua
new file mode 100644
index 0000000..bda0ae6
--- /dev/null
+++ b/assets/pages/test-page.lua
@@ -0,0 +1,28 @@
+TestPage = {}
+
+local maxHp = 100
+local currentHp = 100
+
+function TestPage.Damage(event)
+
+ currentHp = currentHp - 5
+
+ local document = event.current_element.owner_document
+ local target = document:GetElementById("hp-bar")
+
+ if target then
+ target:SetAttribute("current", currentHp)
+ end
+
+end
+
+function TestPage.Heal(event)
+ currentHp = currentHp + 5
+
+ local document = event.current_element.owner_document
+ local target = document:GetElementById("hp-bar")
+
+ if target then
+ target:SetAttribute("current", currentHp)
+ end
+end
\ No newline at end of file
diff --git a/assets/pages/test-page.rcss b/assets/pages/test-page.rcss
index 8903548..ed280c9 100644
--- a/assets/pages/test-page.rcss
+++ b/assets/pages/test-page.rcss
@@ -1,3 +1,17 @@
#page-root h1 {
color: red;
+}
+
+.healthbar-track {
+ display: block;
+ width: 200px;
+ height: 16px;
+ background-color: #3c3c3c;
+ border: 1px #666666;
+}
+
+.healthbar-fill {
+ display: block;
+ height: 100%;
+ background-color: #ffffff;
}
\ No newline at end of file
diff --git a/assets/pages/test-page.rml b/assets/pages/test-page.rml
index 6d7c007..5e19a48 100644
--- a/assets/pages/test-page.rml
+++ b/assets/pages/test-page.rml
@@ -4,4 +4,10 @@
If you have a .rcss file with the same name as the page in the pages directory, it will be loaded at runtime so you can add custom styling to a page, which is why the header is red on this page only.
+
+
This next section demonstates two things, the custom "healthbar" rml element, and scoped lua with the damage and heal buttons
+
+
+
+
\ No newline at end of file
diff --git a/src/element_registry.hpp b/src/element_registry.hpp
new file mode 100644
index 0000000..81c7bda
--- /dev/null
+++ b/src/element_registry.hpp
@@ -0,0 +1,22 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+class ElementRegistry {
+public:
+ template
+ void Register(const std::string& tag) {
+ static_assert(std::is_base_of::value, "T must derive from Rml::Element");
+ auto instancer = std::make_unique>();
+ Rml::Factory::RegisterElementInstancer(tag, instancer.get());
+ instancers.push_back(std::move(instancer));
+ }
+
+private:
+ std::vector> instancers;
+};
\ No newline at end of file
diff --git a/src/elements/health_bar_element.cpp b/src/elements/health_bar_element.cpp
new file mode 100644
index 0000000..3691fd8
--- /dev/null
+++ b/src/elements/health_bar_element.cpp
@@ -0,0 +1,51 @@
+#include "health_bar_element.hpp"
+#include
+#include
+#include
+#include
+#include
+#include
+
+HealthBarElement::HealthBarElement(const Rml::String& tag) : Rml::Element(tag) {
+ Rml::XMLAttributes attributes;
+
+ Rml::ElementPtr track = Rml::Factory::InstanceElement(this, "div", "div", attributes);
+ track->SetClass("healthbar-track", true);
+
+ Rml::ElementPtr fillElement = Rml::Factory::InstanceElement(this, "div", "div", attributes);
+ fillElement->SetClass("healthbar-fill", true);
+ fill = fillElement.get();
+
+ track->AppendChild(std::move(fillElement));
+ AppendChild(std::move(track));
+
+ UpdateFill();
+}
+
+void HealthBarElement::OnAttributeChange(const Rml::ElementAttributes &changed_attributes) {
+ Rml::Element::OnAttributeChange(changed_attributes);
+ if (changed_attributes.find("current") != changed_attributes.end() ||
+ changed_attributes.find("max") != changed_attributes.end()) {
+ UpdateFill();
+ }
+}
+
+void HealthBarElement::UpdateFill() {
+ int current = GetAttribute("current", 0);
+ int max = GetAttribute("max", 100);
+ if (max <= 0) max = 1;
+
+ float pct = Rml::Math::Clamp(static_cast(current) / static_cast(max), 0.0f, 1.0f) * 100.0f;
+
+ if (fill) {
+ fill->SetProperty(Rml::PropertyId::Width, Rml::Property(pct, Rml::Unit::PERCENT));
+
+ if (current >= 90) {
+ fill->SetProperty(Rml::PropertyId::BackgroundColor, Rml::Property("#33cc33", Rml::Unit::COLOUR));
+ } else if (current >= 50) {
+ fill->SetProperty(Rml::PropertyId::BackgroundColor, Rml::Property("#cccc33", Rml::Unit::COLOUR));
+ } else if (current >= 0) {
+ fill->SetProperty(Rml::PropertyId::BackgroundColor, Rml::Property("#cc3333", Rml::Unit::COLOUR));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/elements/health_bar_element.hpp b/src/elements/health_bar_element.hpp
new file mode 100644
index 0000000..6b51a50
--- /dev/null
+++ b/src/elements/health_bar_element.hpp
@@ -0,0 +1,14 @@
+#pragma once
+#include
+#include
+
+class HealthBarElement : public Rml::Element {
+public:
+ explicit HealthBarElement(const Rml::String& tag);
+
+ void OnAttributeChange(const Rml::ElementAttributes &changed_attributes) override;
+
+private:
+ void UpdateFill();
+ Rml::Element* fill = nullptr;
+};
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index 023d858..a572ddc 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -13,14 +13,21 @@
#include
#include
#include "app.hpp"
+#include "element_registry.hpp"
#include "pages/test_page.hpp"
#include "ButtonClickListener.hpp"
#include "lui_app_api.hpp"
+#include "elements/health_bar_element.hpp"
static bool is_initalized = false;
static bool is_running = false;
static Rml::Context *ctx;
static App *app;
+static ElementRegistry elementRegistry;
+
+void RegisterElements() {
+ elementRegistry.Register("healthbar");
+}
bool InitalizeApplication() {
if (!Backend::Initialize("RmlUi App Template", 800, 600, true)) {
@@ -55,6 +62,8 @@ bool InitalizeApplication() {
AppLuaApi *lua_app_api = new AppLuaApi(app, L);
lua_app_api->RegisterLuaBindings();
+ RegisterElements();
+
std::cout << "Application initalized...\n";
return true;