From 4d71f552aae6ed998349e8e784ed2128fd5188c2 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Mon, 12 May 2025 00:09:21 -0400 Subject: [PATCH] Refactoring the GUECS UI::render and the components so that it's just calling a .render on each one. This will then let me allow registering any components people want. --- demos/calc.cpp | 2 +- demos/clicker_game.cpp | 65 ++++++++++++++++--------------- include/guecs/sfml/components.hpp | 12 ++++-- include/guecs/ui.hpp | 17 ++------ src/guecs/sfml/backend.cpp | 4 +- src/guecs/sfml/components.cpp | 37 ++++++++++++++++-- src/guecs/ui.cpp | 44 +++++++++++++-------- 7 files changed, 110 insertions(+), 71 deletions(-) diff --git a/demos/calc.cpp b/demos/calc.cpp index 14417b1..5268791 100644 --- a/demos/calc.cpp +++ b/demos/calc.cpp @@ -150,7 +150,7 @@ struct CalculatorUI { } void init() { - $gui.set($gui.MAIN, {}); + $gui.set($gui.MAIN, {$gui.$parser}); for(auto& [name, cell] : $gui.cells()) { auto id = $gui.entity(name); diff --git a/demos/clicker_game.cpp b/demos/clicker_game.cpp index 05a6906..b7d7c56 100644 --- a/demos/clicker_game.cpp +++ b/demos/clicker_game.cpp @@ -55,7 +55,7 @@ struct Shake { float tick = ease(); sf::Vector2f scale{ std::lerp(initial_scale.x, initial_scale.x + scale_factor, tick), - std::lerp(initial_scale.y, initial_scale.y + scale_factor, tick)}; + std::lerp(initial_scale.y, initial_scale.y + scale_factor, tick)}; sprite.sprite->setScale(scale); } else { @@ -83,34 +83,35 @@ struct ClickerUI { void init() { $gui.set($gui.MAIN, {$gui.$parser, {0, 0, 0, 255}}); - for(auto& [name, cell] : $gui.cells()) { - auto id = $gui.entity(name); - if(name != "clicker") { - $gui.set(id, {}); - $gui.set(id, {}); - $gui.set(id, { "clicker_treat_bone" }); - fmt::println("button dim: {},{}", cell.w, cell.h); - $gui.set(id, { - [&](auto, auto) { handle_button(Event::A_BUTTON); } - }); - } - } - - $clicker = $gui.entity("clicker"); - $gui.set($clicker, {"clicker_the_dog"}); - $gui.set($clicker, {"clicker_bark"}); - $gui.set($clicker, { - [&](auto, auto) { handle_button(Event::CLICKER); } - }); - - // custom components need to be initialized manually - $gui.set_init($clicker, {}); + for(auto& [name, cell] : $gui.cells()) { + auto id = $gui.entity(name); + if(name != "clicker") { + $gui.set(id, {}); + $gui.set(id, {}); + $gui.set(id, { "clicker_treat_bone" }); + fmt::println("button dim: {},{}", cell.w, cell.h); + $gui.set(id, { + [&](auto, auto) { handle_button(Event::A_BUTTON); } + }); + } + } + + $clicker = $gui.entity("clicker"); + $gui.set($clicker, {"clicker_the_dog"}); + $gui.set($clicker, {"clicker_bark"}); + $gui.set($clicker, { + [&](auto, auto) { handle_button(Event::CLICKER); } + }); + + // custom components need to be initialized manually + $gui.set_init($clicker, {}); $gui.init(); } void render(sf::RenderWindow& window) { auto& shaker = $gui.get($clicker); + if(shaker.playing) { auto& sprite = $gui.get($clicker); shaker.render(sprite); @@ -130,17 +131,17 @@ struct ClickerUI { using enum Event; switch(ev) { case CLICKER: { - auto& shaker = $gui.get($clicker); - auto& sprite = $gui.get($clicker); - shaker.play(sprite); - fmt::println("CLICKER LOVES YOU!"); - } break; + auto& shaker = $gui.get($clicker); + auto& sprite = $gui.get($clicker); + shaker.play(sprite); + fmt::println("CLICKER LOVES YOU!"); + } break; case A_BUTTON: - fmt::println("a button clicked"); - break; + fmt::println("a button clicked"); + break; default: - assert(false && "invalid event"); + assert(false && "invalid event"); } } }; @@ -149,7 +150,7 @@ int main() { sfml::Backend backend; guecs::init(&backend); - sf::RenderWindow window(sf::VideoMode({WINDOW_WIDTH, WINDOW_HEIGHT}), "LEL-GUECS Calculator"); + sf::RenderWindow window(sf::VideoMode({WINDOW_WIDTH, WINDOW_HEIGHT}), "Clicker the Dog"); window.setFramerateLimit(FRAME_LIMIT); window.setVerticalSyncEnabled(VSYNC); diff --git a/include/guecs/sfml/components.hpp b/include/guecs/sfml/components.hpp index 9fdb8b8..1e40b8f 100644 --- a/include/guecs/sfml/components.hpp +++ b/include/guecs/sfml/components.hpp @@ -21,6 +21,7 @@ namespace guecs { void init(lel::Cell &cell, shared_ptr font_ptr); void update(const std::wstring& new_content); + void render(sf::RenderWindow& window, sf::Shader *shader_ptr); }; struct Label : public Textual { @@ -49,6 +50,7 @@ namespace guecs { void init(lel::Cell &cell); void update(const string& new_name); + void render(sf::RenderWindow& window, sf::Shader *shader_ptr); }; struct Rectangle { @@ -59,6 +61,7 @@ namespace guecs { shared_ptr shape = nullptr; void init(lel::Cell& cell); + void render(sf::RenderWindow& window, sf::Shader *shader_ptr); }; struct Meter { @@ -67,7 +70,8 @@ namespace guecs { Rectangle bar; void init(lel::Cell& cell); - void render(lel::Cell& cell); + void init(lel::Cell& cell, Rectangle& bg); + void render(lel::Cell& cell, sf::RenderWindow& window, sf::Shader *shader_ptr); }; struct Effect { @@ -82,8 +86,9 @@ namespace guecs { void init(lel::Cell &cell); void run(); void stop(); - void step(); - shared_ptr checkout_ptr(); + void render(); + sf::Shader* get_shader(bool is_shape); + }; struct Sound { @@ -111,5 +116,6 @@ namespace guecs { Background() {} void init(); + void render(sf::RenderWindow& window); }; } diff --git a/include/guecs/ui.hpp b/include/guecs/ui.hpp index cffca14..94081aa 100644 --- a/include/guecs/ui.hpp +++ b/include/guecs/ui.hpp @@ -209,20 +209,11 @@ namespace guecs { } template - void render_helper(sf::RenderWindow& window, Entity ent, bool is_shape, T& target) { - sf::Shader *shader_ptr = nullptr; - - if(auto shader = get_if(ent)) { - if(shader->$active) { - auto ptr = shader->checkout_ptr(); - ptr->setUniform("is_shape", is_shape); - // NOTE: this is needed because SFML doesn't handle shared_ptr - shader_ptr = ptr.get(); - } - } + void render_helper(sf::RenderWindow& window, T& target, sf::Shader *shader_ptr) { + window.draw(*target, shader_ptr); + } - window.draw(*target, shader_ptr); - } + sf::Shader* find_shader(Entity ent, bool is_shape); void show_sprite(const string& region, const string& sprite_name); void show_text(const string& region, const wstring& content); diff --git a/src/guecs/sfml/backend.cpp b/src/guecs/sfml/backend.cpp index 33f2c69..424f54e 100644 --- a/src/guecs/sfml/backend.cpp +++ b/src/guecs/sfml/backend.cpp @@ -45,8 +45,8 @@ namespace sfml { theme.LABEL_SIZE = 20; theme.FILL_COLOR = theme.DARK_MID; theme.TEXT_COLOR = theme.LIGHT_LIGHT; - theme.BG_COLOR = theme.MID; - theme.BORDER_COLOR = theme.LIGHT_DARK; + theme.BG_COLOR = theme.DARK_DARK; + theme.BORDER_COLOR = theme.DARK_LIGHT; theme.BG_COLOR_DARK = theme.BLACK; theme.FONT_FILE_NAME = "assets/text.otf"; diff --git a/src/guecs/sfml/components.cpp b/src/guecs/sfml/components.cpp index bd1250b..01743c5 100644 --- a/src/guecs/sfml/components.cpp +++ b/src/guecs/sfml/components.cpp @@ -24,6 +24,10 @@ namespace guecs { text->setCharacterSize(size); } + void Textual::render(sf::RenderWindow& window, sf::Shader *shader_ptr) { + window.draw(*text, shader_ptr); + } + void Textual::update(const wstring& new_content) { content = new_content; text->setString(content); @@ -56,6 +60,10 @@ namespace guecs { float(cell.h - padding * 2) / bounds.size.y}); } + void Sprite::render(sf::RenderWindow& window, sf::Shader *shader_ptr) { + window.draw(*sprite, shader_ptr); + } + void Rectangle::init(lel::Cell& cell) { sf::Vector2f size{float(cell.w) - padding * 2, float(cell.h) - padding * 2}; if(shape == nullptr) shape = make_shared(size); @@ -65,15 +73,24 @@ namespace guecs { shape->setOutlineThickness(border_px); } + void Rectangle::render(sf::RenderWindow& window, sf::Shader *shader_ptr) { + window.draw(*shape, shader_ptr); + } + + void Meter::init(lel::Cell& cell, Rectangle& bg) { + bg.shape->setFillColor(color); + init(cell); + } void Meter::init(lel::Cell& cell) { bar.init(cell); } - void Meter::render(lel::Cell& cell) { + void Meter::render(lel::Cell& cell, sf::RenderWindow& window, sf::Shader *shader_ptr) { float level = std::clamp(percent, 0.0f, 1.0f) * float(cell.w); // ZED: this 6 is a border width, make it a thing bar.shape->setSize({std::max(level, 0.0f), float(cell.h - 6)}); + window.draw(*bar.shape, shader_ptr); } void Sound::play(bool hover) { @@ -104,13 +121,17 @@ namespace guecs { assert(shape != nullptr && "failed to make rectangle"); } + void Background::render(sf::RenderWindow& window) { + window.draw(*shape); + } + void Effect::init(lel::Cell &cell) { $shader = BACKEND->shader_get(name); $shader->setUniform("u_resolution", sf::Vector2f({float(cell.w), float(cell.h)})); $clock = std::make_shared(); } - void Effect::step() { + void Effect::render() { sf::Time cur_time = $clock->getElapsedTime(); float u_time = cur_time.asSeconds(); @@ -129,12 +150,20 @@ namespace guecs { $u_time_end = u_time.asSeconds() + duration; } - shared_ptr Effect::checkout_ptr() { + sf::Shader* Effect::get_shader(bool is_shape) { + sf::Shader *shader_ptr = nullptr; + if(BACKEND->shader_updated()) { $shader = BACKEND->shader_get(name); } - return $shader; + if($active) { + $shader->setUniform("is_shape", is_shape); + // NOTE: this is needed because SFML doesn't handle shared_ptr + shader_ptr = $shader.get(); + } + + return shader_ptr; } void Effect::stop() { diff --git a/src/guecs/ui.cpp b/src/guecs/ui.cpp index dcb0b69..a95ab72 100644 --- a/src/guecs/ui.cpp +++ b/src/guecs/ui.cpp @@ -66,12 +66,12 @@ namespace guecs { shader.init(cell); }); - query([](auto, auto& bg, auto &meter) { - bg.shape->setFillColor(meter.color); - }); - - query([](auto, auto &cell, auto& meter) { - meter.init(cell); + query([this](auto ent, auto &cell, auto& meter) { + if(auto bg = get_if(ent)) { + meter.init(cell, *bg); + } else { + meter.init(cell); + } }); query([this](auto, auto& cell, auto& text) { @@ -98,34 +98,46 @@ namespace guecs { }); } + sf::Shader* UI::find_shader(Entity ent, bool is_shape) { + if(auto shader = get_if(ent)) { + return shader->get_shader(is_shape); + } else { + return nullptr; + } + } + void UI::render(sf::RenderWindow& window) { if(auto bg = get_if(MAIN)) { - window.draw(*(bg->shape)); + bg->render(window); } query([&](auto, auto& shader) { - if(shader.$active) shader.step(); + if(shader.$active) shader.render(); }); query([&](auto ent, auto& rect) { - render_helper(window, ent, true, rect.shape); + auto shader_ptr = find_shader(ent, true); + rect.render(window, shader_ptr); }); query([&](auto ent, auto& cell, auto &meter) { - meter.render(cell); - render_helper(window, ent, true, meter.bar.shape); + auto shader_ptr = find_shader(ent, true); + meter.render(cell, window, shader_ptr); }); query([&](auto ent, auto& sprite) { - render_helper(window, ent, false, sprite.sprite); + auto shader_ptr = find_shader(ent, false); + sprite.render(window, shader_ptr); }); query