diff --git a/demos/clicker_game.cpp b/demos/clicker_game.cpp index b7d7c56..b2e99b9 100644 --- a/demos/clicker_game.cpp +++ b/demos/clicker_game.cpp @@ -81,7 +81,12 @@ struct ClickerUI { } void init() { - $gui.set($gui.MAIN, {$gui.$parser, {0, 0, 0, 255}}); + guecs::Background bg{$gui.$parser, }; + + bg.set_color({0, 0, 0, 255}); + bg.set_sprite("clicker_treat_bone"); + + $gui.set($gui.MAIN, bg); for(auto& [name, cell] : $gui.cells()) { auto id = $gui.entity(name); diff --git a/include/guecs/lel.hpp b/include/guecs/lel.hpp index b48df96..3850126 100644 --- a/include/guecs/lel.hpp +++ b/include/guecs/lel.hpp @@ -7,6 +7,8 @@ namespace lel { struct Cell { + int col = 0; + int row = 0; int x = 0; int y = 0; int w = 0; @@ -15,16 +17,11 @@ namespace lel { int mid_y = 0; int max_w = 0; int max_h = 0; - int col = 0; - int row = 0; bool right = false; bool bottom = false; bool expand = false; bool center = false; bool percent = false; - - Cell(int col, int row) : col(col), row(row) {} - Cell() {} }; using Row = std::vector; @@ -36,16 +33,17 @@ namespace lel { int grid_w = 0; int grid_h = 0; Cell cur; + Cell main; std::vector grid; CellMap cells; Parser(int x, int y, int width, int height); - Parser(); + Parser() : cur{.col=0, .row=0} {}; void position(int x, int y, int width, int height); - void id(std::string name); + void id(const std::string& name); void reset(); - bool parse(std::string input); + bool parse(const std::string& input); void finalize(); std::optional hit(int x, int y); }; diff --git a/include/guecs/sfml/components.hpp b/include/guecs/sfml/components.hpp index 1e40b8f..ca8f4fc 100644 --- a/include/guecs/sfml/components.hpp +++ b/include/guecs/sfml/components.hpp @@ -104,6 +104,7 @@ namespace guecs { float h = 0.0f; sf::Color color=THEME.BG_COLOR; shared_ptr shape = nullptr; + shared_ptr sprite = nullptr; Background(lel::Parser& parser, sf::Color bg_color=THEME.BG_COLOR) : x(parser.grid_x), @@ -117,5 +118,8 @@ namespace guecs { void init(); void render(sf::RenderWindow& window); + + void set_color(sf::Color c); + void set_sprite(const std::string& name, bool stretch=false); }; } diff --git a/src/guecs/lel.cpp b/src/guecs/lel.cpp index 5c18989..b363293 100644 --- a/src/guecs/lel.cpp +++ b/src/guecs/lel.cpp @@ -11,27 +11,36 @@ namespace lel { grid_x(x), grid_y(y), grid_w(width), - grid_h(height), - cur(0, 0) + grid_h(height) { } - Parser::Parser() : cur(0, 0) { } - void Parser::position(int x, int y, int width, int height) { grid_x = x; grid_y = y; grid_w = width; grid_h = height; + + // used in GUIs for setting backgrounds + main = { + .x=grid_x, + .y=grid_y, + .w=grid_w, + .h=grid_h, + .mid_x=std::midpoint(grid_x, grid_x + grid_w), + .mid_y=std::midpoint(grid_y, grid_y + grid_h), + .max_w=grid_w, + .max_h=grid_h + }; } - void Parser::id(std::string name) { + void Parser::id(const std::string& name) { if(name != "_") { assert(!cells.contains(name) && "duplicate cell name"); cells.insert_or_assign(name, cur); } - cur = {cur.col + 1, cur.row}; + cur = {.col=cur.col + 1, .row=cur.row}; auto& row = grid.back(); row.push_back(name); } @@ -87,15 +96,18 @@ namespace lel { } void Parser::reset() { - cur = {0, 0}; + cur = {.col=0, .row=0}; + main = {.col=0, .row=0}; grid.clear(); cells.clear(); } std::optional Parser::hit(int x, int y) { for(auto& [name, cell] : cells) { - if((x >= cell.x && x <= cell.x + cell.w) && - (y >= cell.y && y <= cell.y + cell.h)) { + if(name != "_MAIN" && + (x >= cell.x && x <= cell.x + cell.w) && + (y >= cell.y && y <= cell.y + cell.h)) + { return name; } } @@ -106,6 +118,7 @@ namespace lel { Cell center(int width, int height, Cell &parent) { Cell copy = parent; + // BUG: could I use std::midpoint here or am I even using this? copy.x = parent.mid_x - width / 2; copy.y = parent.mid_y - height / 2; copy.w = width; diff --git a/src/guecs/lel_parser.cpp b/src/guecs/lel_parser.cpp index b60715c..ba99a2b 100644 --- a/src/guecs/lel_parser.cpp +++ b/src/guecs/lel_parser.cpp @@ -86,7 +86,7 @@ static const int Parser_en_main = 1; #line 44 "src/guecs/lel_parser.rl" -bool Parser::parse(std::string input) { +bool Parser::parse(const std::string& input) { reset(); int cs = 0; const char *start = nullptr; diff --git a/src/guecs/lel_parser.rl b/src/guecs/lel_parser.rl index f6a37c2..a123bfc 100644 --- a/src/guecs/lel_parser.rl +++ b/src/guecs/lel_parser.rl @@ -42,7 +42,7 @@ namespace lel { %% write data; -bool Parser::parse(std::string input) { +bool Parser::parse(const std::string& input) { reset(); int cs = 0; const char *start = nullptr; diff --git a/src/guecs/sfml/components.cpp b/src/guecs/sfml/components.cpp index 01743c5..1f1f349 100644 --- a/src/guecs/sfml/components.cpp +++ b/src/guecs/sfml/components.cpp @@ -121,8 +121,36 @@ namespace guecs { assert(shape != nullptr && "failed to make rectangle"); } + void Background::set_color(sf::Color c) { + color = c; + } + + void Background::set_sprite(const std::string& name, bool stretch) { + auto sprite_texture = BACKEND->texture_get(name); + + sprite = make_shared( + *sprite_texture.texture, + sprite_texture.sprite->getTextureRect()); + + sprite->setPosition({float(x), float(y)}); + + if(stretch) { + auto bounds = sprite->getLocalBounds(); + + sprite->setScale({ + float(w) / bounds.size.x, + float(h) / bounds.size.y}); + } + } + void Background::render(sf::RenderWindow& window) { - window.draw(*shape); + if(shape != nullptr) { + window.draw(*shape); + } + + if(sprite != nullptr) { + window.draw(*sprite); + } } void Effect::init(lel::Cell &cell) { diff --git a/src/guecs/ui.cpp b/src/guecs/ui.cpp index 357e500..5fbad51 100644 --- a/src/guecs/ui.cpp +++ b/src/guecs/ui.cpp @@ -143,7 +143,7 @@ namespace guecs { bool UI::mouse(float x, float y, bool hover) { int action_count = 0; - // BUG: use lel::Parser.hit instead of this + // BUG: Is Parser::hit useful? query([&](auto ent, auto& cell) { if((x >= cell.x && x <= cell.x + cell.w) && diff --git a/tests/lel.cpp b/tests/lel.cpp index b6ed7ff..244e751 100644 --- a/tests/lel.cpp +++ b/tests/lel.cpp @@ -21,6 +21,15 @@ TEST_CASE("test basic ops", "[lel]") { auto &name = row[colcount]; if(name == "_") { REQUIRE(!parser.cells.contains(name)); + } else if(name == "_MAIN") { + // it's the main cell which covers the whole area + auto &cell = parser.cells.at(name); + REQUIRE(cell.row == 0); + REQUIRE(cell.col == 0); + REQUIRE(cell.x == parser.grid_x); + REQUIRE(cell.y == parser.grid_y); + REQUIRE(cell.w == parser.grid_w); + REQUIRE(cell.h == parser.grid_h); } else { auto &cell = parser.cells.at(name); REQUIRE(cell.row == int(rowcount));