Make pools with generations and bind mouse position logic
This commit is contained in:
+50
-25
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user