130 lines
3.4 KiB
C++
130 lines
3.4 KiB
C++
#include "guecs/lel.hpp"
|
|
#include <fmt/core.h>
|
|
#include <numeric>
|
|
#include <cassert>
|
|
|
|
#include "./lel_parser.cpp"
|
|
|
|
namespace lel {
|
|
|
|
Parser::Parser(int x, int y, int width, int height) :
|
|
grid_x(x),
|
|
grid_y(y),
|
|
grid_w(width),
|
|
grid_h(height)
|
|
{
|
|
}
|
|
|
|
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(const std::string& name) {
|
|
if(name != "_") {
|
|
assert(!cells.contains(name) && "duplicate cell name");
|
|
cells.insert_or_assign(name, cur);
|
|
}
|
|
|
|
cur = {.col=cur.col + 1, .row=cur.row};
|
|
auto& row = grid.back();
|
|
row.push_back(name);
|
|
}
|
|
|
|
void Parser::finalize() {
|
|
size_t rows = grid.size();
|
|
int cell_height = grid_h / rows;
|
|
|
|
for(auto& row : grid) {
|
|
// BUG: see issue #16
|
|
size_t columns = row.size();
|
|
int cell_width = grid_w / columns;
|
|
assert(cell_width > 0 && "invalid cell width calc");
|
|
assert(cell_height > 0 && "invalid cell height calc");
|
|
|
|
for(auto& name : row) {
|
|
if(name == "_") continue;
|
|
auto& cell = cells.at(name);
|
|
|
|
// ZED: getting a bit hairy but this should work
|
|
if(cell.percent) {
|
|
// when percent mode we have to take unset to 100%
|
|
if(cell.max_w == 0) cell.max_w = 100;
|
|
if(cell.max_h == 0) cell.max_h = 100;
|
|
cell.max_w *= cell_width * 0.01;
|
|
cell.max_h *= cell_height * 0.01;
|
|
} else {
|
|
if(cell.max_w == 0) cell.max_w = cell_width;
|
|
if(cell.max_h == 0) cell.max_h = cell_height;
|
|
}
|
|
|
|
cell.w = cell.expand ? std::min(cell.max_w, grid_w) : std::min(cell_width, cell.max_w);
|
|
cell.h = cell.expand ? std::min(cell.max_h, grid_h) : std::min(cell_height, cell.max_h);
|
|
|
|
assert(cell.h > 0 && "invalid height cell is <= 0");
|
|
assert(cell.w > 0 && "invalid width cell is <= 0");
|
|
|
|
cell.x = grid_x + (cell.col * cell_width);
|
|
cell.y = grid_y + (cell.row * cell_height);
|
|
|
|
// keep the midpoint since it is used a lot
|
|
cell.mid_x = std::midpoint(cell.x, cell.x + cell.w);
|
|
cell.mid_y = std::midpoint(cell.y, cell.y + cell.h);
|
|
|
|
// perform alignments
|
|
if(cell.right) cell.x += cell_width - cell.w;
|
|
if(cell.bottom) cell.y += cell_height - cell.h;
|
|
if(cell.center) {
|
|
cell.x = cell.mid_x - cell.w / 2;
|
|
cell.y = cell.mid_y - cell.h / 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Parser::reset() {
|
|
cur = {.col=0, .row=0};
|
|
main = {.col=0, .row=0};
|
|
grid.clear();
|
|
cells.clear();
|
|
}
|
|
|
|
std::optional<std::string> Parser::hit(int x, int y) {
|
|
for(auto& [name, cell] : cells) {
|
|
if(name != "_MAIN" &&
|
|
(x >= cell.x && x <= cell.x + cell.w) &&
|
|
(y >= cell.y && y <= cell.y + cell.h))
|
|
{
|
|
return name;
|
|
}
|
|
}
|
|
|
|
return std::nullopt;
|
|
}
|
|
|
|
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;
|
|
copy.h = height;
|
|
|
|
return copy;
|
|
}
|
|
}
|