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;