lel-guecs/src/guecs/ui.cpp

241 lines
6.1 KiB
C++

#include "guecs/ui.hpp"
#include <typeinfo>
#include <cassert>
#include <fmt/core.h>
#include <iostream>
namespace guecs {
using std::make_shared;
UI::UI() {
$font = make_shared<sf::Font>(THEME.FONT_FILE_NAME);
}
void UI::position(int x, int y, int width, int height) {
$parser.position(x, y, width, height);
}
sf::Vector2f UI::get_position() {
return {float($parser.grid_x), float($parser.grid_y)};
}
sf::Vector2f UI::get_size() {
return {float($parser.grid_w), float($parser.grid_h)};
}
void UI::layout(const string& grid) {
$grid = grid;
bool good = $parser.parse($grid);
assert(good && "LEL parsing failed.");
for(auto& [name, cell] : $parser.cells) {
auto ent = init_entity(name);
set<lel::Cell>(ent, cell);
}
}
Entity UI::init_entity(const string& name) {
auto ent = entity();
// this lets you look up an entity by name
$name_ents.insert_or_assign(name, ent);
// this lets you get a name by entity
$ents_name.insert_or_assign(ent, name);
// this makes it easier to get the name during querying
set<CellName>(ent, {name});
return ent;
}
const std::string& UI::name_for(Entity gui_id) {
assert($ents_name.contains(gui_id) &&
"Attempt to get name_for an Entity but that's not a valid ID.");
return $ents_name.at(gui_id);
}
bool UI::contains(const string& name) {
return $name_ents.contains(name);
}
Entity UI::entity(const string& name) {
assert($name_ents.contains(name) &&
"GUECS entity does not exist. Mispelled cell name?");
return $name_ents.at(name);
}
Entity UI::entity(const string& name, int id) {
return entity(fmt::format("{}{}", name, id));
}
void UI::init() {
query<Background>([](auto, auto& bg) {
bg.init();
});
query<lel::Cell, Rectangle>([](auto, auto& cell, auto& rect) {
rect.init(cell);
});
query<lel::Cell, Effect>([](auto, auto& cell, auto& shader) {
shader.init(cell);
});
query<lel::Cell, Meter>([this](auto ent, auto &cell, auto& meter) {
if(auto bg = get_if<Rectangle>(ent)) {
meter.init(cell, *bg);
} else {
meter.init(cell);
}
});
query<lel::Cell, Text>([this](auto, auto& cell, auto& text) {
text.init(cell, $font);
});
query<lel::Cell, Sprite>([&](auto, auto &cell, auto &sprite) {
sprite.init(cell);
});
query<lel::Cell, Icon>([&](auto, auto &cell, auto &icon) {
icon.init(cell);
});
}
void UI::debug_layout(sf::RenderTarget& window) {
query<lel::Cell>([&](const auto, auto &cell) {
sf::RectangleShape rect{{float(cell.w), float(cell.h)}};
rect.setPosition({float(cell.x), float(cell.y)});
rect.setFillColor(sf::Color::Transparent);
rect.setOutlineColor(sf::Color::Red);
rect.setOutlineThickness(2.0f);
window.draw(rect);
});
}
sf::Shader* UI::find_shader(Entity ent, bool is_shape) {
if(auto shader = get_if<Effect>(ent)) {
return shader->get_shader(is_shape);
} else {
return nullptr;
}
}
void UI::render(sf::RenderTarget& window) {
if(auto bg = get_if<Background>(MAIN)) {
bg->render(window);
}
query<Effect>([&](auto, auto& shader) {
if(shader.$active) shader.render();
});
query<Rectangle>([&](auto ent, auto& rect) {
auto shader_ptr = find_shader(ent, true);
rect.render(window, shader_ptr);
});
query<lel::Cell, Meter>([&](auto ent, auto& cell, auto &meter) {
auto shader_ptr = find_shader(ent, true);
meter.render(cell, window, shader_ptr);
});
query<Sprite>([&](auto ent, auto& sprite) {
auto shader_ptr = find_shader(ent, false);
sprite.render(window, shader_ptr);
});
query<Icon>([&](auto ent, auto& icon) {
auto shader_ptr = find_shader(ent, false);
icon.render(window, shader_ptr);
});
query<Text>([&](auto ent, auto& text) {
auto shader_ptr = find_shader(ent, false);
text.render(window, shader_ptr);
});
}
bool UI::mouse(float x, float y, Modifiers mods) {
int action_count = 0;
bool hover = mods.test(size_t(ModBit::hover));
query<lel::Cell>([&](auto ent, auto& cell) {
if((x >= cell.x && x <= cell.x + cell.w) &&
(y >= cell.y && y <= cell.y + cell.h))
{
do_if<Effect>(ent, [hover](auto& effect) {
effect.$shader->setUniform("hover", hover);
effect.run();
});
do_if<Sound>(ent, [hover](auto& sound) {
// here set that it played then only play once
sound.play(hover);
});
if(hover) return;
click_on(ent, mods);
action_count++;
} else {
do_if<Effect>(ent, [](auto& effect) {
effect.stop();
});
do_if<Sound>(ent, [hover](auto& sound) {
// here set that it played then only play once
sound.stop(hover);
});
}
});
return action_count > 0;
}
void UI::show_sprite(const string& region, const string& sprite_name) {
auto ent = entity(region);
if(auto sprite = get_if<Sprite>(ent)) {
sprite->update(sprite_name);
} else {
set_init<Sprite>(ent, {sprite_name});
}
}
void UI::show_icon(const string& region, const string& sprite_name) {
auto ent = entity(region);
if(auto sprite = get_if<Icon>(ent)) {
sprite->update(sprite_name);
} else {
set_init<Icon>(ent, {sprite_name});
}
}
void UI::show_text(const string& region, const wstring& content) {
auto ent = entity(region);
if(auto tc = get_if<Text>(ent)) {
tc->text->setString(content);
} else {
auto &cell = cell_for(ent);
Text to_set{content, THEME.TEXT_SIZE};
to_set.init(cell, $font);
set<Text>(ent, to_set);
}
}
void UI::click_on(const std::string& name, Modifiers mods) {
click_on(entity(name), mods);
}
void UI::click_on(Entity gui_id, Modifiers mods) {
if(auto to_click = get_if<Clickable>(gui_id)) {
to_click->action(mods);
};
}
wstring to_wstring(const string& str) {
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> $converter;
return $converter.from_bytes(str);
}
}