Make pools with generations and bind mouse position logic

This commit is contained in:
2026-05-06 16:40:36 +01:00
parent 08a642e07a
commit 3894b90398
8 changed files with 221 additions and 125 deletions
+50 -25
View File
@@ -6,8 +6,13 @@
#include "utils.h"
#include "window/window.h"
enum Type { IMAGE,
TEXT,
RECT };
namespace app {
struct Element {
Type type;
Vec2<float> position = {0, 0};
float rotation = 0;
Vec2<float> scale = {1, 1};
@@ -15,6 +20,7 @@ struct Element {
bool click_through = false;
Ruby::Block on_click;
Element(Type type) : type(type) {}
virtual ~Element() = default;
virtual void render(Window &window, uint64_t abs_time) = 0;
virtual Vec2<float> size(Window *window) = 0;
@@ -26,14 +32,14 @@ struct Element {
};
struct EImage : Element {
int animation_id = -1;
uint64_t animation_id = UINT64_MAX;
EImage(int animation_id) : animation_id(animation_id) {
EImage(uint64_t animation_id) : Element(Type::IMAGE), animation_id(animation_id) {
animation_pool.use(animation_id);
}
~EImage() {
if (animation_id != -1)
if (animation_id != UINT64_MAX)
animation_pool.release(animation_id);
}
@@ -56,30 +62,32 @@ struct EImage : Element {
struct EText : Element {
Localization::Key key;
int font_id = -1;
uint64_t font_id = UINT64_MAX;
~EText() {
if (text_id != -1)
if (text_id != UINT64_MAX)
text_pool.release(text_id);
if (font_id != -1)
if (font_id != UINT64_MAX)
font_pool.release(font_id);
}
Color color = {255, 255, 255, 255};
EText(Localization::Key key, int font_id, Color color)
: key(key), font_id(font_id), color(color) {
EText(Localization::Key key, uint64_t font_id, Color color)
: Element(Type::TEXT), key(key), font_id(font_id), color(color) {
font_pool.use(font_id);
}
Vec2<float> size(Window *window) override {
if (text_id == UINT64_MAX)
return {0, 0};
return window->get_text_size(text_id);
};
void render(Window &window, uint64_t) override {
if (last_language != Localization::current_language || last_key != key || text_id == -1) {
if (last_language != Localization::current_language || last_key != key || text_id == UINT64_MAX) {
std::string localized_str = Localization::get(key);
if (text_id != -1)
if (text_id != UINT64_MAX)
text_pool.release(text_id);
text_id = window.create_text(font_id, localized_str.c_str(), localized_str.size(), color);
last_language = Localization::current_language;
@@ -89,9 +97,9 @@ struct EText : Element {
}
private:
int text_id = -1;
Localization::LanguageCode last_language = -1;
Localization::Key last_key = -1;
uint64_t text_id = UINT64_MAX;
Localization::LanguageCode last_language = UINT_MAX;
Localization::Key last_key = UINT_MAX;
};
struct ERect : Element {
@@ -101,7 +109,7 @@ struct ERect : Element {
return shape;
};
ERect(Vec2<float> shape, Color color) : shape(shape), color(color) {}
ERect(Vec2<float> shape, Color color) : Element(Type::RECT), shape(shape), color(color) {}
void render(Window &window, uint64_t) override {
window.draw_rect(Rect::from_size(position, shape), color, z, rotation);
@@ -111,15 +119,15 @@ struct ERect : Element {
inline Pool<Element> element_pool;
struct Scene {
std::vector<int> element_ids;
std::vector<uint64_t> element_ids;
Ruby::Block update;
~Scene() {
for (const int &id : element_ids)
for (const uint64_t &id : element_ids)
element_pool.release(id);
}
void add_element(int element_id) {
void add_element(uint64_t element_id) {
auto it = std::lower_bound(
element_ids.begin(),
element_ids.end(),
@@ -134,7 +142,7 @@ struct Scene {
element_ids.insert(it, element_id);
}
void delete_element(int element_id) {
void delete_element(uint64_t element_id) {
auto it = std::find(element_ids.begin(), element_ids.end(), element_id);
if (it != element_ids.end()) {
element_pool.release(element_id);
@@ -149,23 +157,33 @@ struct Scene {
}
}
void click(Window *window, Vec2<float> position) {
void click(Vec2<float> position) {
std::vector<uint64_t> clicked_elements = elements_at(position);
for (const uint64_t &id : clicked_elements)
element_pool[id]->click();
}
std::vector<uint64_t> elements_at(Vec2<float> position) {
std::vector<uint64_t> result;
for (auto it = element_ids.rbegin(); it != element_ids.rend(); ++it) {
Element *e = element_pool[*it];
Vec2<float> size = e->size(window);
Vec2<float> size = e->size(&window);
Rect rect = Rect::from_size(e->position, size * e->scale);
if (rect.contains(position)) {
e->click();
result.push_back(*it);
if (e->click_through)
continue;
else
break;
}
}
return result;
}
void render(Window &window, uint64_t abs_time) {
for (const int &e : element_ids)
for (const uint64_t &e : element_ids)
element_pool[e]->render(window, abs_time);
}
};
@@ -173,10 +191,11 @@ struct Scene {
inline Pool<Scene> scene_pool;
struct App {
int current_scene_id = 0;
uint64_t current_scene_id = 0;
bool running = true;
Vec2<float> mouse_position = {-1, -1};
void switch_to_scene(int scene_id) {
void switch_to_scene(uint64_t scene_id) {
scene_pool.release(current_scene_id);
scene_pool.use(scene_id);
current_scene_id = scene_id;
@@ -213,7 +232,13 @@ struct App {
running = false;
break;
case Event::MOUSE_BUTTON_DOWN:
scene->click(&window, e.mouse_button.position);
scene->click(e.mouse_button.position);
break;
case Event::MOUSE_MOVE:
mouse_position = e.mouse_move.position;
break;
case Event::MOUSE_LEAVE:
mouse_position = {-1, -1};
break;
default:
break;