#pragma once #include "color.hpp" #include "dinkyecs.hpp" #include "lel.hpp" #include #include #include #include "textures.hpp" #include #include "events.hpp" #include "constants.hpp" #include "components.hpp" #include #include "shaders.hpp" namespace guecs { using std::shared_ptr, std::make_shared, std::wstring, std::string; struct Textual { std::wstring content; unsigned int size = GUECS_FONT_SIZE; sf::Color color = GUECS_TEXT_COLOR; int padding = GUECS_PADDING; bool centered = false; shared_ptr font = nullptr; shared_ptr text = nullptr; void init(lel::Cell &cell, shared_ptr font_ptr); void update(std::wstring& new_content); }; struct Label : public Textual { template Label(Args... args) : Textual(args...) { centered = true; } Label() { centered = true; }; }; struct Clickable { /* This is actually called by UI::mouse and passed the entity ID of the * button pressed so you can interact with it in the event handler. */ std::function action; }; struct Sprite { std::string name; int padding = GUECS_PADDING; std::shared_ptr sprite = nullptr; std::shared_ptr texture = nullptr; void init(lel::Cell &cell); }; struct Rectangle { int padding = GUECS_PADDING; sf::Color color = GUECS_FILL_COLOR; sf::Color border_color = GUECS_BORDER_COLOR; int border_px = GUECS_BORDER_PX; shared_ptr shape = nullptr; void init(lel::Cell& cell); }; struct Meter { float percent = 1.0f; Rectangle bar; void init(lel::Cell& cell); }; struct ActionData { std::any data; }; struct CellName { std::string name; }; struct Effect { float duration = 0.1f; std::string name{"ui_shader"}; float $u_time_end = 0.0; bool $active = false; std::shared_ptr $clock = nullptr; std::shared_ptr $shader = nullptr; int $shader_version = 0; void init(lel::Cell &cell); void run(); void step(); shared_ptr checkout_ptr(); }; struct Sound { std::string on_click{"ui_click"}; void play(bool hover); }; struct Background { float x = 0.0f; float y = 0.0f; float w = 0.0f; float h = 0.0f; sf::Color color = GUECS_BG_COLOR; shared_ptr shape = nullptr; Background(lel::Parser& parser, sf::Color bg_color=GUECS_BG_COLOR) : x(parser.grid_x), y(parser.grid_y), w(parser.grid_w), h(parser.grid_h), color(bg_color) {} Background() {} void init(); }; class UI { public: DinkyECS::World $world; std::unordered_map $name_ents; shared_ptr $font = nullptr; lel::Parser $parser; std::string $grid = ""; UI(); void position(int x, int y, int width, int height); void layout(std::string grid); DinkyECS::Entity init_entity(std::string name); DinkyECS::Entity entity(std::string name); inline lel::CellMap& cells() { return $parser.cells; } inline DinkyECS::World& world() { return $world; } void init(); void render(sf::RenderWindow& window); bool mouse(float x, float y, bool hover); void debug_layout(sf::RenderWindow& window); template void set(DinkyECS::Entity ent, Comp val) { $world.set(ent, val); } template void set_init(DinkyECS::Entity ent, Comp val) { dbc::check(has(ent),"WRONG! slot is missing its cell?!"); auto& cell = get(ent); val.init(cell); $world.set(ent, val); } template void do_if(DinkyECS::Entity ent, std::function cb) { if($world.has(ent)) { cb($world.get(ent)); } } lel::Cell& cell_for(DinkyECS::Entity ent) { return $world.get(ent); } lel::Cell& cell_for(std::string name) { DinkyECS::Entity ent = entity(name); return $world.get(ent); } template Comp& get(DinkyECS::Entity entity) { return $world.get(entity); } template std::optional get_if(DinkyECS::Entity entity) { return $world.get_if(entity); } template bool has(DinkyECS::Entity entity) { return $world.has(entity); } template void remove(DinkyECS::Entity ent) { $world.remove(ent); } template void close(string region) { auto ent = entity(region); remove(ent); } template void render_helper(sf::RenderWindow& window, DinkyECS::Entity ent, bool is_shape, T& target) { sf::Shader *shader_ptr = nullptr; if($world.has(ent)) { auto& shader = $world.get(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(); } } window.draw(*target, shader_ptr); } void show_sprite(string region, string sprite_name); void show_text(string region, wstring content); void update_text(string region, wstring content); void update_label(string region, wstring content); void show_label(string region, wstring content); }; Clickable make_action(DinkyECS::World& target, Events::GUI event); }