Make pools with generations and bind mouse position logic
This commit is contained in:
+50
-25
@@ -6,8 +6,13 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "window/window.h"
|
#include "window/window.h"
|
||||||
|
|
||||||
|
enum Type { IMAGE,
|
||||||
|
TEXT,
|
||||||
|
RECT };
|
||||||
|
|
||||||
namespace app {
|
namespace app {
|
||||||
struct Element {
|
struct Element {
|
||||||
|
Type type;
|
||||||
Vec2<float> position = {0, 0};
|
Vec2<float> position = {0, 0};
|
||||||
float rotation = 0;
|
float rotation = 0;
|
||||||
Vec2<float> scale = {1, 1};
|
Vec2<float> scale = {1, 1};
|
||||||
@@ -15,6 +20,7 @@ struct Element {
|
|||||||
bool click_through = false;
|
bool click_through = false;
|
||||||
Ruby::Block on_click;
|
Ruby::Block on_click;
|
||||||
|
|
||||||
|
Element(Type type) : type(type) {}
|
||||||
virtual ~Element() = default;
|
virtual ~Element() = default;
|
||||||
virtual void render(Window &window, uint64_t abs_time) = 0;
|
virtual void render(Window &window, uint64_t abs_time) = 0;
|
||||||
virtual Vec2<float> size(Window *window) = 0;
|
virtual Vec2<float> size(Window *window) = 0;
|
||||||
@@ -26,14 +32,14 @@ struct Element {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct EImage : 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);
|
animation_pool.use(animation_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
~EImage() {
|
~EImage() {
|
||||||
if (animation_id != -1)
|
if (animation_id != UINT64_MAX)
|
||||||
animation_pool.release(animation_id);
|
animation_pool.release(animation_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,30 +62,32 @@ struct EImage : Element {
|
|||||||
|
|
||||||
struct EText : Element {
|
struct EText : Element {
|
||||||
Localization::Key key;
|
Localization::Key key;
|
||||||
int font_id = -1;
|
uint64_t font_id = UINT64_MAX;
|
||||||
|
|
||||||
~EText() {
|
~EText() {
|
||||||
if (text_id != -1)
|
if (text_id != UINT64_MAX)
|
||||||
text_pool.release(text_id);
|
text_pool.release(text_id);
|
||||||
if (font_id != -1)
|
if (font_id != UINT64_MAX)
|
||||||
font_pool.release(font_id);
|
font_pool.release(font_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Color color = {255, 255, 255, 255};
|
Color color = {255, 255, 255, 255};
|
||||||
|
|
||||||
EText(Localization::Key key, int font_id, Color color)
|
EText(Localization::Key key, uint64_t font_id, Color color)
|
||||||
: key(key), font_id(font_id), color(color) {
|
: Element(Type::TEXT), key(key), font_id(font_id), color(color) {
|
||||||
font_pool.use(font_id);
|
font_pool.use(font_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2<float> size(Window *window) override {
|
Vec2<float> size(Window *window) override {
|
||||||
|
if (text_id == UINT64_MAX)
|
||||||
|
return {0, 0};
|
||||||
return window->get_text_size(text_id);
|
return window->get_text_size(text_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
void render(Window &window, uint64_t) override {
|
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);
|
std::string localized_str = Localization::get(key);
|
||||||
if (text_id != -1)
|
if (text_id != UINT64_MAX)
|
||||||
text_pool.release(text_id);
|
text_pool.release(text_id);
|
||||||
text_id = window.create_text(font_id, localized_str.c_str(), localized_str.size(), color);
|
text_id = window.create_text(font_id, localized_str.c_str(), localized_str.size(), color);
|
||||||
last_language = Localization::current_language;
|
last_language = Localization::current_language;
|
||||||
@@ -89,9 +97,9 @@ struct EText : Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int text_id = -1;
|
uint64_t text_id = UINT64_MAX;
|
||||||
Localization::LanguageCode last_language = -1;
|
Localization::LanguageCode last_language = UINT_MAX;
|
||||||
Localization::Key last_key = -1;
|
Localization::Key last_key = UINT_MAX;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ERect : Element {
|
struct ERect : Element {
|
||||||
@@ -101,7 +109,7 @@ struct ERect : Element {
|
|||||||
return shape;
|
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 {
|
void render(Window &window, uint64_t) override {
|
||||||
window.draw_rect(Rect::from_size(position, shape), color, z, rotation);
|
window.draw_rect(Rect::from_size(position, shape), color, z, rotation);
|
||||||
@@ -111,15 +119,15 @@ struct ERect : Element {
|
|||||||
inline Pool<Element> element_pool;
|
inline Pool<Element> element_pool;
|
||||||
|
|
||||||
struct Scene {
|
struct Scene {
|
||||||
std::vector<int> element_ids;
|
std::vector<uint64_t> element_ids;
|
||||||
Ruby::Block update;
|
Ruby::Block update;
|
||||||
|
|
||||||
~Scene() {
|
~Scene() {
|
||||||
for (const int &id : element_ids)
|
for (const uint64_t &id : element_ids)
|
||||||
element_pool.release(id);
|
element_pool.release(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_element(int element_id) {
|
void add_element(uint64_t element_id) {
|
||||||
auto it = std::lower_bound(
|
auto it = std::lower_bound(
|
||||||
element_ids.begin(),
|
element_ids.begin(),
|
||||||
element_ids.end(),
|
element_ids.end(),
|
||||||
@@ -134,7 +142,7 @@ struct Scene {
|
|||||||
element_ids.insert(it, element_id);
|
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);
|
auto it = std::find(element_ids.begin(), element_ids.end(), element_id);
|
||||||
if (it != element_ids.end()) {
|
if (it != element_ids.end()) {
|
||||||
element_pool.release(element_id);
|
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) {
|
for (auto it = element_ids.rbegin(); it != element_ids.rend(); ++it) {
|
||||||
Element *e = element_pool[*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);
|
Rect rect = Rect::from_size(e->position, size * e->scale);
|
||||||
if (rect.contains(position)) {
|
if (rect.contains(position)) {
|
||||||
e->click();
|
result.push_back(*it);
|
||||||
if (e->click_through)
|
if (e->click_through)
|
||||||
continue;
|
continue;
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void render(Window &window, uint64_t abs_time) {
|
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);
|
element_pool[e]->render(window, abs_time);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -173,10 +191,11 @@ struct Scene {
|
|||||||
inline Pool<Scene> scene_pool;
|
inline Pool<Scene> scene_pool;
|
||||||
|
|
||||||
struct App {
|
struct App {
|
||||||
int current_scene_id = 0;
|
uint64_t current_scene_id = 0;
|
||||||
bool running = true;
|
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.release(current_scene_id);
|
||||||
scene_pool.use(scene_id);
|
scene_pool.use(scene_id);
|
||||||
current_scene_id = scene_id;
|
current_scene_id = scene_id;
|
||||||
@@ -213,7 +232,13 @@ struct App {
|
|||||||
running = false;
|
running = false;
|
||||||
break;
|
break;
|
||||||
case Event::MOUSE_BUTTON_DOWN:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -4,10 +4,9 @@
|
|||||||
#include "app/app.h"
|
#include "app/app.h"
|
||||||
|
|
||||||
#warning "Define ==, eql?, hash for each class"
|
#warning "Define ==, eql?, hash for each class"
|
||||||
#warning "Define and bind elements_at in Scene (same as click method already defined but without callback)"
|
|
||||||
|
|
||||||
namespace definitions {
|
namespace definitions {
|
||||||
inline mrb_value wrap(mrb_state *mrb, RClass *cls, mrb_data_type *type, int id) {
|
inline mrb_value wrap(mrb_state *mrb, RClass *cls, const mrb_data_type *type, uint64_t id) {
|
||||||
RBasic *obj_b = mrb_obj_alloc(mrb, MRB_TT_DATA, cls);
|
RBasic *obj_b = mrb_obj_alloc(mrb, MRB_TT_DATA, cls);
|
||||||
mrb_value obj = mrb_obj_value(obj_b);
|
mrb_value obj = mrb_obj_value(obj_b);
|
||||||
|
|
||||||
@@ -21,7 +20,7 @@ inline mrb_value wrap(mrb_state *mrb, RClass *cls, mrb_data_type *type, int id)
|
|||||||
|
|
||||||
static void Font_free(mrb_state *mrb, void *ptr) {
|
static void Font_free(mrb_state *mrb, void *ptr) {
|
||||||
UNUSED(mrb);
|
UNUSED(mrb);
|
||||||
int id = ((Wrapper *)ptr)->id;
|
uint64_t id = ((Wrapper *)ptr)->id;
|
||||||
font_pool.release(id);
|
font_pool.release(id);
|
||||||
delete (Wrapper *)ptr;
|
delete (Wrapper *)ptr;
|
||||||
}
|
}
|
||||||
@@ -58,7 +57,7 @@ static mrb_value Font_init(mrb_state *mrb, mrb_value self) {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int get_id_Font(mrb_state *mrb, mrb_value self) {
|
inline uint64_t get_id_Font(mrb_state *mrb, mrb_value self) {
|
||||||
Wrapper *wrapper;
|
Wrapper *wrapper;
|
||||||
Data_Get_Struct(mrb, self, &Font_type, wrapper);
|
Data_Get_Struct(mrb, self, &Font_type, wrapper);
|
||||||
return wrapper->id;
|
return wrapper->id;
|
||||||
@@ -66,7 +65,7 @@ inline int get_id_Font(mrb_state *mrb, mrb_value self) {
|
|||||||
|
|
||||||
static void Image_free(mrb_state *mrb, void *ptr) {
|
static void Image_free(mrb_state *mrb, void *ptr) {
|
||||||
UNUSED(mrb);
|
UNUSED(mrb);
|
||||||
int id = ((Wrapper *)ptr)->id;
|
uint64_t id = ((Wrapper *)ptr)->id;
|
||||||
image_pool.release(id);
|
image_pool.release(id);
|
||||||
delete (Wrapper *)ptr;
|
delete (Wrapper *)ptr;
|
||||||
}
|
}
|
||||||
@@ -98,7 +97,7 @@ static mrb_value Image_init(mrb_state *mrb, mrb_value self) {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int get_id_Image(mrb_state *mrb, mrb_value self) {
|
inline uint64_t get_id_Image(mrb_state *mrb, mrb_value self) {
|
||||||
Wrapper *wrapper;
|
Wrapper *wrapper;
|
||||||
Data_Get_Struct(mrb, self, &Image_type, wrapper);
|
Data_Get_Struct(mrb, self, &Image_type, wrapper);
|
||||||
return wrapper->id;
|
return wrapper->id;
|
||||||
@@ -106,7 +105,7 @@ inline int get_id_Image(mrb_state *mrb, mrb_value self) {
|
|||||||
|
|
||||||
static void Animation_free(mrb_state *mrb, void *ptr) {
|
static void Animation_free(mrb_state *mrb, void *ptr) {
|
||||||
UNUSED(mrb);
|
UNUSED(mrb);
|
||||||
int id = ((Wrapper *)ptr)->id;
|
uint64_t id = ((Wrapper *)ptr)->id;
|
||||||
animation_pool.release(id);
|
animation_pool.release(id);
|
||||||
delete (Wrapper *)ptr;
|
delete (Wrapper *)ptr;
|
||||||
}
|
}
|
||||||
@@ -132,7 +131,7 @@ static mrb_value Animation_init(mrb_state *mrb, mrb_value self) {
|
|||||||
if (!mrb_nil_p(kwargs))
|
if (!mrb_nil_p(kwargs))
|
||||||
HASH_FLOAT(kwargs, fps, fps);
|
HASH_FLOAT(kwargs, fps, fps);
|
||||||
|
|
||||||
std::vector<int> frame_ids;
|
std::vector<uint64_t> frame_ids;
|
||||||
for (mrb_int i = 0; i < frames_len; i++) {
|
for (mrb_int i = 0; i < frames_len; i++) {
|
||||||
mrb_value frame_val = frames_val[i];
|
mrb_value frame_val = frames_val[i];
|
||||||
if (!mrb_obj_is_kind_of(mrb, frame_val, mrb_class_get(mrb, "Image"))) {
|
if (!mrb_obj_is_kind_of(mrb, frame_val, mrb_class_get(mrb, "Image"))) {
|
||||||
@@ -143,7 +142,7 @@ static mrb_value Animation_init(mrb_state *mrb, mrb_value self) {
|
|||||||
);
|
);
|
||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
}
|
}
|
||||||
int frame_id = get_id_Image(mrb, frame_val);
|
uint64_t frame_id = get_id_Image(mrb, frame_val);
|
||||||
image_pool.use(frame_id);
|
image_pool.use(frame_id);
|
||||||
frame_ids.push_back(frame_id);
|
frame_ids.push_back(frame_id);
|
||||||
}
|
}
|
||||||
@@ -156,7 +155,7 @@ static mrb_value Animation_init(mrb_state *mrb, mrb_value self) {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int get_id_Animation(mrb_state *mrb, mrb_value self) {
|
inline uint64_t get_id_Animation(mrb_state *mrb, mrb_value self) {
|
||||||
Wrapper *wrapper;
|
Wrapper *wrapper;
|
||||||
Data_Get_Struct(mrb, self, &Animation_type, wrapper);
|
Data_Get_Struct(mrb, self, &Animation_type, wrapper);
|
||||||
return wrapper->id;
|
return wrapper->id;
|
||||||
@@ -164,7 +163,7 @@ inline int get_id_Animation(mrb_state *mrb, mrb_value self) {
|
|||||||
|
|
||||||
static void ElementText_free(mrb_state *mrb, void *ptr) {
|
static void ElementText_free(mrb_state *mrb, void *ptr) {
|
||||||
UNUSED(mrb);
|
UNUSED(mrb);
|
||||||
int id = ((Wrapper *)ptr)->id;
|
uint64_t id = ((Wrapper *)ptr)->id;
|
||||||
app::element_pool.release(id);
|
app::element_pool.release(id);
|
||||||
delete (Wrapper *)ptr;
|
delete (Wrapper *)ptr;
|
||||||
}
|
}
|
||||||
@@ -208,7 +207,7 @@ static mrb_value ElementText_init(mrb_state *mrb, mrb_value self) {
|
|||||||
|
|
||||||
Vec2<float> position = {x, y};
|
Vec2<float> position = {x, y};
|
||||||
|
|
||||||
int id = get_id_Font(mrb, font_val);
|
uint64_t id = get_id_Font(mrb, font_val);
|
||||||
font_pool.use(id);
|
font_pool.use(id);
|
||||||
|
|
||||||
app::EText *element = new app::EText(key_id, id, {255, 255, 255, 255});
|
app::EText *element = new app::EText(key_id, id, {255, 255, 255, 255});
|
||||||
@@ -223,7 +222,7 @@ static mrb_value ElementText_init(mrb_state *mrb, mrb_value self) {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int get_id_ElementText(mrb_state *mrb, mrb_value self) {
|
inline uint64_t get_id_ElementText(mrb_state *mrb, mrb_value self) {
|
||||||
Wrapper *wrapper;
|
Wrapper *wrapper;
|
||||||
Data_Get_Struct(mrb, self, &ElementText_type, wrapper);
|
Data_Get_Struct(mrb, self, &ElementText_type, wrapper);
|
||||||
return wrapper->id;
|
return wrapper->id;
|
||||||
@@ -232,7 +231,7 @@ inline int get_id_ElementText(mrb_state *mrb, mrb_value self) {
|
|||||||
static mrb_value element_text_on_click(mrb_state *mrb, mrb_value self) {
|
static mrb_value element_text_on_click(mrb_state *mrb, mrb_value self) {
|
||||||
mrb_value block;
|
mrb_value block;
|
||||||
mrb_get_args(mrb, "&", &block);
|
mrb_get_args(mrb, "&", &block);
|
||||||
int id = get_id_ElementText(mrb, self);
|
uint64_t id = get_id_ElementText(mrb, self);
|
||||||
app::Element *element = app::element_pool[id];
|
app::Element *element = app::element_pool[id];
|
||||||
element->on_click.set_proc(block);
|
element->on_click.set_proc(block);
|
||||||
return self;
|
return self;
|
||||||
@@ -240,7 +239,7 @@ static mrb_value element_text_on_click(mrb_state *mrb, mrb_value self) {
|
|||||||
|
|
||||||
static void ElementRect_free(mrb_state *mrb, void *ptr) {
|
static void ElementRect_free(mrb_state *mrb, void *ptr) {
|
||||||
UNUSED(mrb);
|
UNUSED(mrb);
|
||||||
int id = ((Wrapper *)ptr)->id;
|
uint64_t id = ((Wrapper *)ptr)->id;
|
||||||
app::element_pool.release(id);
|
app::element_pool.release(id);
|
||||||
delete (Wrapper *)ptr;
|
delete (Wrapper *)ptr;
|
||||||
}
|
}
|
||||||
@@ -271,8 +270,11 @@ static mrb_value ElementRect_init(mrb_state *mrb, mrb_value self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float z = 0;
|
float z = 0;
|
||||||
if (!mrb_nil_p(kwargs))
|
bool click_through = false;
|
||||||
|
if (!mrb_nil_p(kwargs)) {
|
||||||
HASH_FLOAT(kwargs, z, z);
|
HASH_FLOAT(kwargs, z, z);
|
||||||
|
HASH_BOOL(kwargs, click_through, click_through);
|
||||||
|
}
|
||||||
|
|
||||||
Vec2<float> position = {x, y};
|
Vec2<float> position = {x, y};
|
||||||
Vec2<float> shape = {w, h};
|
Vec2<float> shape = {w, h};
|
||||||
@@ -286,6 +288,7 @@ static mrb_value ElementRect_init(mrb_state *mrb, mrb_value self) {
|
|||||||
);
|
);
|
||||||
element->position = position;
|
element->position = position;
|
||||||
element->z = z;
|
element->z = z;
|
||||||
|
element->click_through = click_through;
|
||||||
|
|
||||||
s->id = app::element_pool.acquire(element);
|
s->id = app::element_pool.acquire(element);
|
||||||
app::element_pool.use(s->id);
|
app::element_pool.use(s->id);
|
||||||
@@ -294,7 +297,7 @@ static mrb_value ElementRect_init(mrb_state *mrb, mrb_value self) {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int get_id_ElementRect(mrb_state *mrb, mrb_value self) {
|
inline uint64_t get_id_ElementRect(mrb_state *mrb, mrb_value self) {
|
||||||
Wrapper *wrapper;
|
Wrapper *wrapper;
|
||||||
Data_Get_Struct(mrb, self, &ElementRect_type, wrapper);
|
Data_Get_Struct(mrb, self, &ElementRect_type, wrapper);
|
||||||
return wrapper->id;
|
return wrapper->id;
|
||||||
@@ -303,7 +306,7 @@ inline int get_id_ElementRect(mrb_state *mrb, mrb_value self) {
|
|||||||
static mrb_value element_rect_on_click(mrb_state *mrb, mrb_value self) {
|
static mrb_value element_rect_on_click(mrb_state *mrb, mrb_value self) {
|
||||||
mrb_value block;
|
mrb_value block;
|
||||||
mrb_get_args(mrb, "&", &block);
|
mrb_get_args(mrb, "&", &block);
|
||||||
int id = get_id_ElementRect(mrb, self);
|
uint64_t id = get_id_ElementRect(mrb, self);
|
||||||
app::Element *element = app::element_pool[id];
|
app::Element *element = app::element_pool[id];
|
||||||
element->on_click.set_proc(block);
|
element->on_click.set_proc(block);
|
||||||
return self;
|
return self;
|
||||||
@@ -312,7 +315,7 @@ static mrb_value element_rect_on_click(mrb_state *mrb, mrb_value self) {
|
|||||||
static mrb_value element_rect_color_set(mrb_state *mrb, mrb_value self) {
|
static mrb_value element_rect_color_set(mrb_state *mrb, mrb_value self) {
|
||||||
mrb_value color_val;
|
mrb_value color_val;
|
||||||
mrb_get_args(mrb, "o", &color_val);
|
mrb_get_args(mrb, "o", &color_val);
|
||||||
int id = get_id_ElementRect(mrb, self);
|
uint64_t id = get_id_ElementRect(mrb, self);
|
||||||
app::ERect *element = (app::ERect *)app::element_pool[id];
|
app::ERect *element = (app::ERect *)app::element_pool[id];
|
||||||
element->color = {
|
element->color = {
|
||||||
(uint8_t)((mrb_fixnum(color_val) >> 24) & 0xFF),
|
(uint8_t)((mrb_fixnum(color_val) >> 24) & 0xFF),
|
||||||
@@ -324,7 +327,7 @@ static mrb_value element_rect_color_set(mrb_state *mrb, mrb_value self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static mrb_value element_rect_color_get(mrb_state *mrb, mrb_value self) {
|
static mrb_value element_rect_color_get(mrb_state *mrb, mrb_value self) {
|
||||||
int id = get_id_ElementRect(mrb, self);
|
uint64_t id = get_id_ElementRect(mrb, self);
|
||||||
app::ERect *element = (app::ERect *)app::element_pool[id];
|
app::ERect *element = (app::ERect *)app::element_pool[id];
|
||||||
uint32_t color =
|
uint32_t color =
|
||||||
((uint32_t)element->color.r << 24) | ((uint32_t)element->color.g << 16)
|
((uint32_t)element->color.r << 24) | ((uint32_t)element->color.g << 16)
|
||||||
@@ -334,7 +337,7 @@ static mrb_value element_rect_color_get(mrb_state *mrb, mrb_value self) {
|
|||||||
|
|
||||||
static void ElementImage_free(mrb_state *mrb, void *ptr) {
|
static void ElementImage_free(mrb_state *mrb, void *ptr) {
|
||||||
UNUSED(mrb);
|
UNUSED(mrb);
|
||||||
int id = ((Wrapper *)ptr)->id;
|
uint64_t id = ((Wrapper *)ptr)->id;
|
||||||
app::element_pool.release(id);
|
app::element_pool.release(id);
|
||||||
delete (Wrapper *)ptr;
|
delete (Wrapper *)ptr;
|
||||||
}
|
}
|
||||||
@@ -380,7 +383,7 @@ static mrb_value ElementImage_init(mrb_state *mrb, mrb_value self) {
|
|||||||
HASH_BOOL(kwargs, click_through, click_through);
|
HASH_BOOL(kwargs, click_through, click_through);
|
||||||
}
|
}
|
||||||
|
|
||||||
int id = get_id_Animation(mrb, animation_val);
|
uint64_t id = get_id_Animation(mrb, animation_val);
|
||||||
|
|
||||||
app::EImage *element = new app::EImage(id);
|
app::EImage *element = new app::EImage(id);
|
||||||
element->position = {x, y};
|
element->position = {x, y};
|
||||||
@@ -394,7 +397,7 @@ static mrb_value ElementImage_init(mrb_state *mrb, mrb_value self) {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int get_id_ElementImage(mrb_state *mrb, mrb_value self) {
|
inline uint64_t get_id_ElementImage(mrb_state *mrb, mrb_value self) {
|
||||||
Wrapper *wrapper;
|
Wrapper *wrapper;
|
||||||
Data_Get_Struct(mrb, self, &ElementImage_type, wrapper);
|
Data_Get_Struct(mrb, self, &ElementImage_type, wrapper);
|
||||||
return wrapper->id;
|
return wrapper->id;
|
||||||
@@ -403,7 +406,7 @@ inline int get_id_ElementImage(mrb_state *mrb, mrb_value self) {
|
|||||||
static mrb_value element_image_on_click(mrb_state *mrb, mrb_value self) {
|
static mrb_value element_image_on_click(mrb_state *mrb, mrb_value self) {
|
||||||
mrb_value block;
|
mrb_value block;
|
||||||
mrb_get_args(mrb, "&", &block);
|
mrb_get_args(mrb, "&", &block);
|
||||||
int id = get_id_ElementImage(mrb, self);
|
uint64_t id = get_id_ElementImage(mrb, self);
|
||||||
app::Element *element = app::element_pool[id];
|
app::Element *element = app::element_pool[id];
|
||||||
element->on_click.set_proc(block);
|
element->on_click.set_proc(block);
|
||||||
return self;
|
return self;
|
||||||
@@ -411,7 +414,7 @@ static mrb_value element_image_on_click(mrb_state *mrb, mrb_value self) {
|
|||||||
|
|
||||||
static void Scene_free(mrb_state *mrb, void *ptr) {
|
static void Scene_free(mrb_state *mrb, void *ptr) {
|
||||||
UNUSED(mrb);
|
UNUSED(mrb);
|
||||||
int id = ((Wrapper *)ptr)->id;
|
uint64_t id = ((Wrapper *)ptr)->id;
|
||||||
app::scene_pool.release(id);
|
app::scene_pool.release(id);
|
||||||
delete (Wrapper *)ptr;
|
delete (Wrapper *)ptr;
|
||||||
}
|
}
|
||||||
@@ -434,7 +437,7 @@ static mrb_value Scene_init(mrb_state *mrb, mrb_value self) {
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int get_id_Scene(mrb_state *mrb, mrb_value self) {
|
inline uint64_t get_id_Scene(mrb_state *mrb, mrb_value self) {
|
||||||
Wrapper *wrapper;
|
Wrapper *wrapper;
|
||||||
Data_Get_Struct(mrb, self, &Scene_type, wrapper);
|
Data_Get_Struct(mrb, self, &Scene_type, wrapper);
|
||||||
return wrapper->id;
|
return wrapper->id;
|
||||||
@@ -457,10 +460,10 @@ static mrb_value scene_add_element(mrb_state *mrb, mrb_value self) {
|
|||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
int id = get_id_Scene(mrb, self);
|
uint64_t id = get_id_Scene(mrb, self);
|
||||||
app::Scene *scene = app::scene_pool[id];
|
app::Scene *scene = app::scene_pool[id];
|
||||||
|
|
||||||
int element_id;
|
uint64_t element_id;
|
||||||
if (mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementText"))) {
|
if (mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementText"))) {
|
||||||
element_id = get_id_ElementText(mrb, element_val);
|
element_id = get_id_ElementText(mrb, element_val);
|
||||||
} else if (
|
} else if (
|
||||||
@@ -502,10 +505,10 @@ static mrb_value scene_delete_element(mrb_state *mrb, mrb_value self) {
|
|||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
int id = get_id_Scene(mrb, self);
|
uint64_t id = get_id_Scene(mrb, self);
|
||||||
app::Scene *scene = app::scene_pool[id];
|
app::Scene *scene = app::scene_pool[id];
|
||||||
|
|
||||||
int element_id;
|
uint64_t element_id;
|
||||||
if (mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementText"))) {
|
if (mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementText"))) {
|
||||||
element_id = get_id_ElementText(mrb, element_val);
|
element_id = get_id_ElementText(mrb, element_val);
|
||||||
} else if (
|
} else if (
|
||||||
@@ -534,13 +537,50 @@ static mrb_value scene_on_update(mrb_state *mrb, mrb_value self) {
|
|||||||
mrb_value block;
|
mrb_value block;
|
||||||
mrb_get_args(mrb, "&", &block);
|
mrb_get_args(mrb, "&", &block);
|
||||||
|
|
||||||
int id = get_id_Scene(mrb, self);
|
uint64_t id = get_id_Scene(mrb, self);
|
||||||
app::Scene *scene = app::scene_pool[id];
|
app::Scene *scene = app::scene_pool[id];
|
||||||
scene->update.set_proc(block);
|
scene->update.set_proc(block);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mrb_value scene_elements_at(mrb_state *mrb, mrb_value self) {
|
||||||
|
mrb_value position_val;
|
||||||
|
mrb_get_args(mrb, "o", &position_val);
|
||||||
|
|
||||||
|
float x, y;
|
||||||
|
HASH_FLOAT(position_val, x, x);
|
||||||
|
HASH_FLOAT(position_val, y, y);
|
||||||
|
Vec2<float> position = {x, y};
|
||||||
|
|
||||||
|
uint64_t id = get_id_Scene(mrb, self);
|
||||||
|
app::Scene *scene = app::scene_pool[id];
|
||||||
|
|
||||||
|
std::vector<uint64_t> element_ids = scene->elements_at(position);
|
||||||
|
|
||||||
|
mrb_value result = mrb_ary_new_capa(mrb, element_ids.size());
|
||||||
|
for (uint64_t element_id : element_ids) {
|
||||||
|
app::Element *element = app::element_pool[element_id];
|
||||||
|
if (element->type == Type::TEXT) {
|
||||||
|
RClass *ElementText_class = mrb_class_get(mrb, "ElementText");
|
||||||
|
mrb_value obj = wrap(mrb, ElementText_class, &ElementText_type, element_id);
|
||||||
|
mrb_ary_push(mrb, result, obj);
|
||||||
|
} else if (element->type == Type::RECT) {
|
||||||
|
RClass *ElementRect_class = mrb_class_get(mrb, "ElementRect");
|
||||||
|
mrb_value obj = wrap(mrb, ElementRect_class, &ElementRect_type, element_id);
|
||||||
|
mrb_ary_push(mrb, result, obj);
|
||||||
|
} else if (element->type == Type::IMAGE) {
|
||||||
|
RClass *ElementImage_class = mrb_class_get(mrb, "ElementImage");
|
||||||
|
mrb_value obj = wrap(mrb, ElementImage_class, &ElementImage_type, element_id);
|
||||||
|
mrb_ary_push(mrb, result, obj);
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static mrb_value app_run(mrb_state *mrb, mrb_value) {
|
static mrb_value app_run(mrb_state *mrb, mrb_value) {
|
||||||
mrb_int width, height;
|
mrb_int width, height;
|
||||||
char *title = nullptr;
|
char *title = nullptr;
|
||||||
@@ -560,7 +600,7 @@ static mrb_value app_start(mrb_state *mrb, mrb_value) {
|
|||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
int id = get_id_Scene(mrb, scene_val);
|
uint64_t id = get_id_Scene(mrb, scene_val);
|
||||||
app_->switch_to_scene(id);
|
app_->switch_to_scene(id);
|
||||||
|
|
||||||
app_->loop();
|
app_->loop();
|
||||||
@@ -577,7 +617,7 @@ static mrb_value app_switch_to(mrb_state *mrb, mrb_value) {
|
|||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
int id = get_id_Scene(mrb, scene_val);
|
uint64_t id = get_id_Scene(mrb, scene_val);
|
||||||
app_->switch_to_scene(id);
|
app_->switch_to_scene(id);
|
||||||
|
|
||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
@@ -615,6 +655,14 @@ static mrb_value app_language_set(mrb_state *mrb, mrb_value) {
|
|||||||
return mrb_nil_value();
|
return mrb_nil_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mrb_value app_mouse_position(mrb_state *mrb, mrb_value) {
|
||||||
|
Vec2<float> mouse_pos = app_->mouse_position;
|
||||||
|
mrb_value result = mrb_hash_new(mrb);
|
||||||
|
HASH_SET(result, x, mrb_float_value(mrb, mouse_pos.x));
|
||||||
|
HASH_SET(result, y, mrb_float_value(mrb, mouse_pos.y));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
inline void setup() {
|
inline void setup() {
|
||||||
DEF_CLASS(Font, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1));
|
DEF_CLASS(Font, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1));
|
||||||
|
|
||||||
@@ -638,6 +686,7 @@ inline void setup() {
|
|||||||
ADD_METHOD(Scene, "delete", scene_delete_element, MRB_ARGS_REQ(1));
|
ADD_METHOD(Scene, "delete", scene_delete_element, MRB_ARGS_REQ(1));
|
||||||
ADD_METHOD(Scene, "remove", scene_delete_element, MRB_ARGS_REQ(1));
|
ADD_METHOD(Scene, "remove", scene_delete_element, MRB_ARGS_REQ(1));
|
||||||
ADD_METHOD(Scene, "on_update", scene_on_update, MRB_ARGS_BLOCK());
|
ADD_METHOD(Scene, "on_update", scene_on_update, MRB_ARGS_BLOCK());
|
||||||
|
ADD_METHOD(Scene, "elements_at", scene_elements_at, MRB_ARGS_REQ(1));
|
||||||
|
|
||||||
DEF_MODULE(App);
|
DEF_MODULE(App);
|
||||||
ADD_MODULE_METHOD(App, "run", app_run, MRB_ARGS_REQ(3));
|
ADD_MODULE_METHOD(App, "run", app_run, MRB_ARGS_REQ(3));
|
||||||
@@ -645,6 +694,7 @@ inline void setup() {
|
|||||||
ADD_MODULE_METHOD(App, "switch_to", app_switch_to, MRB_ARGS_REQ(1));
|
ADD_MODULE_METHOD(App, "switch_to", app_switch_to, MRB_ARGS_REQ(1));
|
||||||
ADD_MODULE_METHOD(App, "localize", app_localize, MRB_ARGS_REQ(3));
|
ADD_MODULE_METHOD(App, "localize", app_localize, MRB_ARGS_REQ(3));
|
||||||
ADD_MODULE_METHOD(App, "language=", app_language_set, MRB_ARGS_REQ(1));
|
ADD_MODULE_METHOD(App, "language=", app_language_set, MRB_ARGS_REQ(1));
|
||||||
|
ADD_MODULE_METHOD(App, "mouse_position", app_mouse_position, MRB_ARGS_NONE());
|
||||||
}
|
}
|
||||||
} // namespace definitions
|
} // namespace definitions
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#define HASH_GET(h, key) mrb_hash_get(Ruby::mrb, h, SYM(key))
|
#define HASH_GET(h, key) mrb_hash_get(Ruby::mrb, h, SYM(key))
|
||||||
|
|
||||||
|
#define HASH_SET(h, key, value) mrb_hash_set(Ruby::mrb, h, SYM(key), value)
|
||||||
|
|
||||||
#define HASH_FLOAT(h, key, out) \
|
#define HASH_FLOAT(h, key, out) \
|
||||||
do { \
|
do { \
|
||||||
mrb_value v = HASH_GET(h, key); \
|
mrb_value v = HASH_GET(h, key); \
|
||||||
@@ -28,7 +30,7 @@
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
struct Wrapper {
|
struct Wrapper {
|
||||||
int id;
|
uint64_t id;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ADD_METHOD(NAME, METHOD, FUNC, ARGS) \
|
#define ADD_METHOD(NAME, METHOD, FUNC, ARGS) \
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <SDL3/SDL_events.h>
|
#include <SDL3/SDL_events.h>
|
||||||
|
#include <SDL3/SDL_mouse.h>
|
||||||
#include <SDL3_image/SDL_image.h>
|
#include <SDL3_image/SDL_image.h>
|
||||||
#include <SDL3_ttf/SDL_ttf.h>
|
#include <SDL3_ttf/SDL_ttf.h>
|
||||||
|
|
||||||
|
|||||||
+31
-21
@@ -154,12 +154,13 @@ struct Rect {
|
|||||||
|
|
||||||
template <typename T = void *>
|
template <typename T = void *>
|
||||||
struct Pool {
|
struct Pool {
|
||||||
T *operator[](int index) {
|
T *operator[](uint64_t index) {
|
||||||
if (!is_valid(index)) {
|
if (!is_valid(index)) {
|
||||||
fprintf(stderr, "Invalid pool index: %d\n", index);
|
fprintf(stderr, "Invalid pool index: %llu\n", (unsigned long long)index);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return slots[index].ptr;
|
uint32_t id = (uint32_t)(index & 0xFFFFFFFFULL);
|
||||||
|
return slots[id].ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<T *> &all() {
|
const std::vector<T *> &all() {
|
||||||
@@ -171,43 +172,51 @@ struct Pool {
|
|||||||
return all_items;
|
return all_items;
|
||||||
}
|
}
|
||||||
|
|
||||||
int acquire(T *item) {
|
uint64_t acquire(T *item) {
|
||||||
int index;
|
uint32_t id;
|
||||||
if (!free_indices.empty()) {
|
if (!free_indices.empty()) {
|
||||||
index = free_indices.back();
|
id = free_indices.back();
|
||||||
free_indices.pop_back();
|
free_indices.pop_back();
|
||||||
} else {
|
} else {
|
||||||
index = slots.size();
|
id = slots.size();
|
||||||
slots.push_back({});
|
slots.push_back({});
|
||||||
}
|
}
|
||||||
slots[index].ptr = item;
|
slots[id].ptr = item;
|
||||||
slots[index].refcount = 1;
|
slots[id].refcount = 1;
|
||||||
slots[index].alive = true;
|
slots[id].alive = true;
|
||||||
|
slots[id].generation++;
|
||||||
|
uint64_t index = ((uint64_t)slots[id].generation << 32) | id;
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void use(int index) {
|
void use(uint64_t index) {
|
||||||
if (is_valid(index))
|
if (is_valid(index)) {
|
||||||
slots[index].refcount++;
|
uint64_t id = (uint32_t)(index & 0xFFFFFFFFULL);
|
||||||
|
slots[id].refcount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void release(int index) {
|
void release(uint64_t index) {
|
||||||
if (!is_valid(index))
|
if (!is_valid(index))
|
||||||
return;
|
return;
|
||||||
auto &slot = slots[index];
|
uint32_t id = (uint32_t)(index & 0xFFFFFFFFULL);
|
||||||
|
auto &slot = slots[id];
|
||||||
slot.refcount--;
|
slot.refcount--;
|
||||||
if (slot.refcount <= 0) {
|
if (slot.refcount <= 0) {
|
||||||
delete slot.ptr;
|
delete slot.ptr;
|
||||||
slot.ptr = nullptr;
|
slot.ptr = nullptr;
|
||||||
slot.alive = false;
|
slot.alive = false;
|
||||||
free_indices.push_back(index);
|
free_indices.push_back(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_valid(int index) const {
|
bool is_valid(uint64_t index) const {
|
||||||
return index >= 0
|
uint32_t id = (uint32_t)(index & 0xFFFFFFFFULL);
|
||||||
&& index < (int)slots.size()
|
uint32_t gen = (uint32_t)(index >> 32);
|
||||||
&& slots[index].alive;
|
return id >= 0
|
||||||
|
&& id < slots.size()
|
||||||
|
&& slots[id].alive
|
||||||
|
&& slots[id].generation == gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -215,9 +224,10 @@ private:
|
|||||||
T *ptr = nullptr;
|
T *ptr = nullptr;
|
||||||
int refcount = 0;
|
int refcount = 0;
|
||||||
bool alive = false;
|
bool alive = false;
|
||||||
|
uint32_t generation = 0;
|
||||||
};
|
};
|
||||||
std::vector<Slot> slots;
|
std::vector<Slot> slots;
|
||||||
std::vector<int> free_indices;
|
std::vector<uint32_t> free_indices;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+12
-11
@@ -48,6 +48,7 @@ struct Event {
|
|||||||
KEY_DOWN,
|
KEY_DOWN,
|
||||||
TEXT_INPUT,
|
TEXT_INPUT,
|
||||||
SCROLL,
|
SCROLL,
|
||||||
|
MOUSE_LEAVE,
|
||||||
MOUSE_BUTTON_UP,
|
MOUSE_BUTTON_UP,
|
||||||
MOUSE_BUTTON_DOWN,
|
MOUSE_BUTTON_DOWN,
|
||||||
MOUSE_MOVE
|
MOUSE_MOVE
|
||||||
@@ -80,13 +81,13 @@ struct Event {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Animation {
|
struct Animation {
|
||||||
std::vector<int> frames;
|
std::vector<uint64_t> frames;
|
||||||
float frame_rate;
|
float frame_rate;
|
||||||
bool loop;
|
bool loop;
|
||||||
int reference_count = 0;
|
int reference_count = 0;
|
||||||
|
|
||||||
~Animation() {
|
~Animation() {
|
||||||
for (int frame_id : frames)
|
for (uint64_t frame_id : frames)
|
||||||
image_pool.release(frame_id);
|
image_pool.release(frame_id);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -103,18 +104,18 @@ public:
|
|||||||
~Window();
|
~Window();
|
||||||
|
|
||||||
// Rendering functions
|
// Rendering functions
|
||||||
int load_image(const char *path, float alpha = 1.0f, bool pixel_art = false);
|
uint64_t load_image(const char *path, float alpha = 1.0f, bool pixel_art = false);
|
||||||
Vec2<float> get_image_size(int image_id);
|
Vec2<float> get_image_size(uint64_t image_id);
|
||||||
|
|
||||||
int load_font(const char *path, int font_size, bool bold = false, bool italic = false, bool underline = false, bool pixel_art = false);
|
uint64_t load_font(const char *path, int font_size, bool bold = false, bool italic = false, bool underline = false, bool pixel_art = false);
|
||||||
|
|
||||||
// text is copied internally, so it can be free'd by the caller after the text is created.
|
// text is copied internally, so it can be free'd by the caller after the text is created.
|
||||||
int create_text(int font_id, const char *text, uint32_t length, Color color);
|
uint64_t create_text(uint64_t font_id, const char *text, uint32_t length, Color color);
|
||||||
Vec2<float> get_text_size(int text_id);
|
Vec2<float> get_text_size(uint64_t text_id);
|
||||||
|
|
||||||
bool write(int text_id, Vec2<float> position, float z, float angle = 0.0f, Vec2<float> scale = {1.0f, 1.0f});
|
bool write(uint64_t text_id, Vec2<float> position, float z, float angle = 0.0f, Vec2<float> scale = {1.0f, 1.0f});
|
||||||
|
|
||||||
bool draw(int image_id, Vec2<float> position, float z, float angle = 0.0f, Vec2<float> scale = {1.0f, 1.0f});
|
bool draw(uint64_t image_id, Vec2<float> position, float z, float angle = 0.0f, Vec2<float> scale = {1.0f, 1.0f});
|
||||||
|
|
||||||
bool draw_rect(Rect rect, Color color, float z, float angle = 0.0f);
|
bool draw_rect(Rect rect, Color color, float z, float angle = 0.0f);
|
||||||
|
|
||||||
@@ -172,12 +173,12 @@ private:
|
|||||||
|
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
int image_id;
|
uint64_t image_id;
|
||||||
Vec2<float> position;
|
Vec2<float> position;
|
||||||
} draw_image;
|
} draw_image;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int text_id;
|
uint64_t text_id;
|
||||||
Vec2<float> position;
|
Vec2<float> position;
|
||||||
} draw_text;
|
} draw_text;
|
||||||
|
|
||||||
|
|||||||
+11
-9
@@ -16,7 +16,7 @@ text = ElementText.new :btn_text, default_font, position: {x: 50, y: 50}, z: 1,
|
|||||||
|
|
||||||
rect = ElementRect.new({x: 50, y: 50, w: 100, h: 25}, 0xFF0000FF, z: 0)
|
rect = ElementRect.new({x: 50, y: 50, w: 100, h: 25}, 0xFF0000FF, z: 0)
|
||||||
|
|
||||||
image_element = ElementImage.new bg_animation, position: {x: 0, y: 0}, z: -1
|
image_element = ElementImage.new bg_animation, position: {x: 0, y: 0}, z: -1, click_through: true
|
||||||
|
|
||||||
rect.on_click do
|
rect.on_click do
|
||||||
rect.color = rect.color == 0xFF0000FF ?
|
rect.color = rect.color == 0xFF0000FF ?
|
||||||
@@ -73,15 +73,17 @@ main_scene.on_update do |delta_time|
|
|||||||
# commented out to avoid spamming the console, but you can uncomment to see the delta time being printed every frame
|
# commented out to avoid spamming the console, but you can uncomment to see the delta time being printed every frame
|
||||||
# runs at 60fps, so you should see around 16-17ms being printed
|
# runs at 60fps, so you should see around 16-17ms being printed
|
||||||
|
|
||||||
# simple logic to handle hover
|
el = main_scene.elements_at(App.mouse_position)
|
||||||
pos = App.mouse_position
|
for elem in el
|
||||||
next if pos.nil? # mouse position can be nil if the window is not focused, so we skip the hover logic in that case
|
if elem == image_element
|
||||||
elements = main_scene.elements_at(*pos.values)
|
puts "Hovering over image element"
|
||||||
if elements.include?(rect)
|
elsif elem == rect
|
||||||
rect.color = 0x0000FFFF
|
puts "Hovering over rect element"
|
||||||
else # also handles nil case, if the mouse is not over any element, we reset the color
|
elsif elem == text
|
||||||
rect.color = 0xFF0000FF
|
puts "Hovering over text element"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
main_scene << text
|
main_scene << text
|
||||||
|
|||||||
+30
-25
@@ -56,7 +56,7 @@ Window::~Window() {
|
|||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Window::load_image(const char *path, float alpha, bool pixel_art) {
|
uint64_t Window::load_image(const char *path, float alpha, bool pixel_art) {
|
||||||
SDL_Texture *texture = IMG_LoadTexture(renderer, path);
|
SDL_Texture *texture = IMG_LoadTexture(renderer, path);
|
||||||
|
|
||||||
if (pixel_art) {
|
if (pixel_art) {
|
||||||
@@ -65,7 +65,7 @@ int Window::load_image(const char *path, float alpha, bool pixel_art) {
|
|||||||
|
|
||||||
if (texture == nullptr) {
|
if (texture == nullptr) {
|
||||||
fprintf(stderr, "Failed to load image: %s\n", SDL_GetError());
|
fprintf(stderr, "Failed to load image: %s\n", SDL_GetError());
|
||||||
return UINT32_MAX;
|
return UINT64_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_SetTextureAlphaMod(texture, (uint8_t)(alpha * 255));
|
SDL_SetTextureAlphaMod(texture, (uint8_t)(alpha * 255));
|
||||||
@@ -74,26 +74,26 @@ int Window::load_image(const char *path, float alpha, bool pixel_art) {
|
|||||||
SDL_GetTextureSize(texture, &w, &h);
|
SDL_GetTextureSize(texture, &w, &h);
|
||||||
|
|
||||||
Image *img = new Image{texture, {w, h}};
|
Image *img = new Image{texture, {w, h}};
|
||||||
int id = image_pool.acquire(img);
|
uint64_t id = image_pool.acquire(img);
|
||||||
image_pool.use(id);
|
image_pool.use(id);
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2<float> Window::get_image_size(int image_id) {
|
Vec2<float> Window::get_image_size(uint64_t image_id) {
|
||||||
if (!image_pool.is_valid(image_id)) {
|
if (!image_pool.is_valid(image_id)) {
|
||||||
fprintf(stderr, "Invalid image ID: %d\n", image_id);
|
fprintf(stderr, "Invalid image ID: %llu\n", (unsigned long long)image_id);
|
||||||
return {0, 0};
|
return {0, 0};
|
||||||
}
|
}
|
||||||
return image_pool[image_id]->size;
|
return image_pool[image_id]->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Window::load_font(const char *path, int font_size, bool bold, bool italic, bool underline, bool pixel_art) {
|
uint64_t Window::load_font(const char *path, int font_size, bool bold, bool italic, bool underline, bool pixel_art) {
|
||||||
TTF_Font *font = TTF_OpenFont(path, font_size);
|
TTF_Font *font = TTF_OpenFont(path, font_size);
|
||||||
|
|
||||||
if (font == nullptr) {
|
if (font == nullptr) {
|
||||||
fprintf(stderr, "Failed to load font: %s\n", SDL_GetError());
|
fprintf(stderr, "Failed to load font: %s\n", SDL_GetError());
|
||||||
return UINT32_MAX;
|
return UINT64_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
int style = TTF_STYLE_NORMAL;
|
int style = TTF_STYLE_NORMAL;
|
||||||
@@ -107,16 +107,16 @@ int Window::load_font(const char *path, int font_size, bool bold, bool italic, b
|
|||||||
TTF_SetFontStyle(font, style);
|
TTF_SetFontStyle(font, style);
|
||||||
|
|
||||||
Font *f = new Font{font, pixel_art};
|
Font *f = new Font{font, pixel_art};
|
||||||
int id = font_pool.acquire(f);
|
uint64_t id = font_pool.acquire(f);
|
||||||
font_pool.use(id);
|
font_pool.use(id);
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Window::create_text(int font_id, const char *text, uint32_t length, Color color) {
|
uint64_t Window::create_text(uint64_t font_id, const char *text, uint32_t length, Color color) {
|
||||||
if (!font_pool.is_valid(font_id)) {
|
if (!font_pool.is_valid(font_id)) {
|
||||||
fprintf(stderr, "Invalid font ID: %d\n", font_id);
|
fprintf(stderr, "Invalid font ID: %llu\n", (unsigned long long)font_id);
|
||||||
return UINT32_MAX;
|
return UINT64_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Color sdl_color = {color.r, color.g, color.b, color.a};
|
SDL_Color sdl_color = {color.r, color.g, color.b, color.a};
|
||||||
@@ -124,7 +124,7 @@ int Window::create_text(int font_id, const char *text, uint32_t length, Color co
|
|||||||
|
|
||||||
if (surface == nullptr) {
|
if (surface == nullptr) {
|
||||||
fprintf(stderr, "Failed to create text surface: %s\n", SDL_GetError());
|
fprintf(stderr, "Failed to create text surface: %s\n", SDL_GetError());
|
||||||
return UINT32_MAX;
|
return UINT64_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
|
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||||
@@ -132,7 +132,7 @@ int Window::create_text(int font_id, const char *text, uint32_t length, Color co
|
|||||||
|
|
||||||
if (texture == nullptr) {
|
if (texture == nullptr) {
|
||||||
fprintf(stderr, "Failed to create text texture: %s\n", SDL_GetError());
|
fprintf(stderr, "Failed to create text texture: %s\n", SDL_GetError());
|
||||||
return UINT32_MAX;
|
return UINT64_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (font_pool[font_id]->pixel_art)
|
if (font_pool[font_id]->pixel_art)
|
||||||
@@ -142,23 +142,24 @@ int Window::create_text(int font_id, const char *text, uint32_t length, Color co
|
|||||||
SDL_GetTextureSize(texture, &w, &h);
|
SDL_GetTextureSize(texture, &w, &h);
|
||||||
|
|
||||||
Text *t = new Text{texture, {w, h}};
|
Text *t = new Text{texture, {w, h}};
|
||||||
int id = text_pool.acquire(t);
|
uint64_t id = text_pool.acquire(t);
|
||||||
text_pool.use(id);
|
text_pool.use(id);
|
||||||
|
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec2<float> Window::get_text_size(int text_id) {
|
Vec2<float> Window::get_text_size(uint64_t text_id) {
|
||||||
if (!text_pool.is_valid(text_id)) {
|
if (!text_pool.is_valid(text_id)) {
|
||||||
fprintf(stderr, "Invalid text ID: %d\n", text_id);
|
fprintf(stderr, "(Size) Invalid text ID: %llu\n", (unsigned long long)text_id);
|
||||||
return {0, 0};
|
return {0, 0};
|
||||||
|
throw std::runtime_error("Invalid text ID");
|
||||||
}
|
}
|
||||||
return text_pool[text_id]->size;
|
return text_pool[text_id]->size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::write(int text_id, Vec2<float> position, float z, float angle, Vec2<float> scale) {
|
bool Window::write(uint64_t text_id, Vec2<float> position, float z, float angle, Vec2<float> scale) {
|
||||||
if (!text_pool.is_valid(text_id)) {
|
if (!text_pool.is_valid(text_id)) {
|
||||||
fprintf(stderr, "Invalid text ID: %d\n", text_id);
|
fprintf(stderr, "(Write) Invalid text ID: %llu\n", (unsigned long long)text_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,9 +177,9 @@ bool Window::write(int text_id, Vec2<float> position, float z, float angle, Vec2
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Window::draw(int image_id, Vec2<float> position, float z, float angle, Vec2<float> scale) {
|
bool Window::draw(uint64_t image_id, Vec2<float> position, float z, float angle, Vec2<float> scale) {
|
||||||
if (!image_pool.is_valid(image_id)) {
|
if (!image_pool.is_valid(image_id)) {
|
||||||
fprintf(stderr, "Invalid image ID: %d\n", image_id);
|
fprintf(stderr, "Invalid image ID: %llu\n", (unsigned long long)image_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,6 +383,10 @@ bool Window::poll(Event &event) {
|
|||||||
event.text_input.text[event.text_input.length] = '\0';
|
event.text_input.text[event.text_input.length] = '\0';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
|
||||||
|
event.type = Event::MOUSE_LEAVE;
|
||||||
|
break;
|
||||||
|
|
||||||
case SDL_EVENT_MOUSE_BUTTON_DOWN: {
|
case SDL_EVENT_MOUSE_BUTTON_DOWN: {
|
||||||
event.type = Event::MOUSE_BUTTON_DOWN;
|
event.type = Event::MOUSE_BUTTON_DOWN;
|
||||||
event.mouse_button.button = sdl_event.button.button;
|
event.mouse_button.button = sdl_event.button.button;
|
||||||
@@ -389,7 +394,7 @@ bool Window::poll(Event &event) {
|
|||||||
if (mouse_in_window({sdl_event.button.x, sdl_event.button.y}, virtual_position))
|
if (mouse_in_window({sdl_event.button.x, sdl_event.button.y}, virtual_position))
|
||||||
event.mouse_button.position = virtual_position;
|
event.mouse_button.position = virtual_position;
|
||||||
else
|
else
|
||||||
return false;
|
event.type = Event::MOUSE_LEAVE;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
||||||
@@ -399,17 +404,17 @@ bool Window::poll(Event &event) {
|
|||||||
if (mouse_in_window({sdl_event.button.x, sdl_event.button.y}, virtual_position))
|
if (mouse_in_window({sdl_event.button.x, sdl_event.button.y}, virtual_position))
|
||||||
event.mouse_button.position = virtual_position;
|
event.mouse_button.position = virtual_position;
|
||||||
else
|
else
|
||||||
return false;
|
event.type = Event::MOUSE_LEAVE;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SDL_EVENT_MOUSE_MOTION: {
|
case SDL_EVENT_MOUSE_MOTION: {
|
||||||
event.type = Event::MOUSE_MOVE;
|
event.type = Event::MOUSE_MOVE;
|
||||||
event.mouse_move.delta = {sdl_event.motion.xrel, sdl_event.motion.yrel};
|
event.mouse_move.delta = {sdl_event.motion.xrel, sdl_event.motion.yrel};
|
||||||
Vec2<float> virtual_position;
|
Vec2<float> virtual_position;
|
||||||
if (mouse_in_window({sdl_event.button.x, sdl_event.button.y}, virtual_position))
|
if (mouse_in_window({sdl_event.motion.x, sdl_event.motion.y}, virtual_position))
|
||||||
event.mouse_button.position = virtual_position;
|
event.mouse_move.position = virtual_position;
|
||||||
else
|
else
|
||||||
return false;
|
event.type = Event::MOUSE_LEAVE;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case SDL_EVENT_MOUSE_WHEEL:
|
case SDL_EVENT_MOUSE_WHEEL:
|
||||||
|
|||||||
Reference in New Issue
Block a user