From 08a642e07ac84adef95082830927ee8f9a864b8b Mon Sep 17 00:00:00 2001 From: Daanish Date: Tue, 5 May 2026 23:10:14 +0100 Subject: [PATCH] Resolve macros and cleanup --- include/binding/definitions.h | 616 +++++++++++++++++++++------------- include/binding/ruby.h | 28 -- samples/button.rb | 53 +++ 3 files changed, 445 insertions(+), 252 deletions(-) diff --git a/include/binding/definitions.h b/include/binding/definitions.h index 011f960..9e3155d 100644 --- a/include/binding/definitions.h +++ b/include/binding/definitions.h @@ -3,127 +3,231 @@ #include "app/app.h" +#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 { -DEF_RB( - Font, - ({ font_pool.release(id); }), - ({ - char *path; - mrb_int size; - mrb_value kwargs; - mrb_get_args(mrb, "zi|H", &path, &size, &kwargs); +inline mrb_value wrap(mrb_state *mrb, RClass *cls, mrb_data_type *type, int id) { + RBasic *obj_b = mrb_obj_alloc(mrb, MRB_TT_DATA, cls); + mrb_value obj = mrb_obj_value(obj_b); - bool pixel_art = false; - bool bold = false; - bool italic = false; - bool underline = false; - if (!mrb_nil_p(kwargs)) { - HASH_BOOL(kwargs, pixel_art, pixel_art); - HASH_BOOL(kwargs, bold, bold); - HASH_BOOL(kwargs, italic, italic); - HASH_BOOL(kwargs, underline, underline); - } - s->id = window.load_font(path, size, bold, italic, underline, pixel_art); - }) -) + Wrapper *w = new Wrapper(); + w->id = id; -DEF_RB( - Image, - ({ image_pool.release(id); }), - ({ - char *path; - mrb_value kwargs; - mrb_get_args(mrb, "z|H", &path, &kwargs); + mrb_data_init(obj, w, type); - float alpha = 1.0f; - bool pixel_art = false; - if (!mrb_nil_p(kwargs)) { - HASH_FLOAT(kwargs, alpha, alpha); - HASH_BOOL(kwargs, pixel_art, pixel_art); - } + return obj; +} - s->id = window.load_image(path, alpha, pixel_art); - }) -) +static void Font_free(mrb_state *mrb, void *ptr) { + UNUSED(mrb); + int id = ((Wrapper *)ptr)->id; + font_pool.release(id); + delete (Wrapper *)ptr; +} -DEF_RB( - Animation, - ({ - animation_pool.release(id); - }), - ({ - const mrb_value *frames_val; - mrb_int frames_len; - mrb_value kwargs; - mrb_get_args(mrb, "a|H", &frames_val, &frames_len, &kwargs); +static const struct mrb_data_type Font_type = {"Font", Font_free}; - float fps = 1.0f; - if (!mrb_nil_p(kwargs)) - HASH_FLOAT(kwargs, fps, fps); +static mrb_value Font_init(mrb_state *mrb, mrb_value self) { + UNUSED(mrb); + Wrapper *old = (Wrapper *)DATA_PTR(self); + if (old) + mrb_free(mrb, old); + mrb_data_init(self, nullptr, &Font_type); + Wrapper *s = new Wrapper(); - std::vector frame_ids; - for (mrb_int i = 0; i < frames_len; i++) { - mrb_value frame_val = frames_val[i]; - if (!mrb_obj_is_kind_of(mrb, frame_val, mrb_class_get(mrb, "Image"))) { - mrb_raise(mrb, mrb_class_get(mrb, "Exception"), "Expected an array of Image objects"); - return mrb_nil_value(); - } - int frame_id = get_id_Image(mrb, frame_val); - image_pool.use(frame_id); - frame_ids.push_back(frame_id); - } + char *path; + mrb_int size; + mrb_value kwargs; + mrb_get_args(mrb, "zi|H", &path, &size, &kwargs); - Animation *animation = new Animation{frame_ids, fps, true}; - s->id = animation_pool.acquire(animation); - animation_pool.use(s->id); - }) -) + bool pixel_art = false; + bool bold = false; + bool italic = false; + bool underline = false; + if (!mrb_nil_p(kwargs)) { + HASH_BOOL(kwargs, pixel_art, pixel_art); + HASH_BOOL(kwargs, bold, bold); + HASH_BOOL(kwargs, italic, italic); + HASH_BOOL(kwargs, underline, underline); + } -DEF_RB( - ElementText, - ({ - app::element_pool.release(id); - }), - ({ - mrb_value font_val; - mrb_sym key; - mrb_value kwargs; - mrb_get_args(mrb, "no|H", &key, &font_val, &kwargs); + s->id = window.load_font(path, size, bold, italic, underline, pixel_art); - auto key_id = Localization::key_from_sym(mrb, key); + mrb_data_init(self, s, &Font_type); + return self; +} - if (!mrb_obj_is_kind_of(mrb, font_val, mrb_class_get(mrb, "Font"))) { - mrb_raise(mrb, mrb_class_get(mrb, "Exception"), "Expected a Font object"); +inline int get_id_Font(mrb_state *mrb, mrb_value self) { + Wrapper *wrapper; + Data_Get_Struct(mrb, self, &Font_type, wrapper); + return wrapper->id; +} + +static void Image_free(mrb_state *mrb, void *ptr) { + UNUSED(mrb); + int id = ((Wrapper *)ptr)->id; + image_pool.release(id); + delete (Wrapper *)ptr; +} + +static const struct mrb_data_type Image_type = {"Image", Image_free}; + +static mrb_value Image_init(mrb_state *mrb, mrb_value self) { + UNUSED(mrb); + Wrapper *old = (Wrapper *)DATA_PTR(self); + if (old) + mrb_free(mrb, old); + mrb_data_init(self, nullptr, &Image_type); + Wrapper *s = new Wrapper(); + + char *path; + mrb_value kwargs; + mrb_get_args(mrb, "z|H", &path, &kwargs); + + float alpha = 1.0f; + bool pixel_art = false; + if (!mrb_nil_p(kwargs)) { + HASH_FLOAT(kwargs, alpha, alpha); + HASH_BOOL(kwargs, pixel_art, pixel_art); + } + + s->id = window.load_image(path, alpha, pixel_art); + + mrb_data_init(self, s, &Image_type); + return self; +} + +inline int get_id_Image(mrb_state *mrb, mrb_value self) { + Wrapper *wrapper; + Data_Get_Struct(mrb, self, &Image_type, wrapper); + return wrapper->id; +} + +static void Animation_free(mrb_state *mrb, void *ptr) { + UNUSED(mrb); + int id = ((Wrapper *)ptr)->id; + animation_pool.release(id); + delete (Wrapper *)ptr; +} + +static const struct mrb_data_type Animation_type = { + "Animation", Animation_free +}; + +static mrb_value Animation_init(mrb_state *mrb, mrb_value self) { + UNUSED(mrb); + Wrapper *old = (Wrapper *)DATA_PTR(self); + if (old) + mrb_free(mrb, old); + mrb_data_init(self, nullptr, &Animation_type); + Wrapper *s = new Wrapper(); + + const mrb_value *frames_val; + mrb_int frames_len; + mrb_value kwargs; + mrb_get_args(mrb, "a|H", &frames_val, &frames_len, &kwargs); + + float fps = 1.0f; + if (!mrb_nil_p(kwargs)) + HASH_FLOAT(kwargs, fps, fps); + + std::vector frame_ids; + for (mrb_int i = 0; i < frames_len; i++) { + mrb_value frame_val = frames_val[i]; + if (!mrb_obj_is_kind_of(mrb, frame_val, mrb_class_get(mrb, "Image"))) { + mrb_raise( + mrb, + mrb_class_get(mrb, "Exception"), + "Expected an array of Image objects" + ); return mrb_nil_value(); } + int frame_id = get_id_Image(mrb, frame_val); + image_pool.use(frame_id); + frame_ids.push_back(frame_id); + } - float x = 0; - float y = 0; - float z = 0; - bool click_through = false; - if (!mrb_nil_p(kwargs)) { - mrb_value pos_hash = HASH_GET(kwargs, position); - HASH_FLOAT(pos_hash, x, x); - HASH_FLOAT(pos_hash, y, y); + Animation *animation = new Animation{frame_ids, fps, true}; + s->id = animation_pool.acquire(animation); + animation_pool.use(s->id); - HASH_FLOAT(kwargs, z, z); - HASH_BOOL(kwargs, click_through, click_through); - } + mrb_data_init(self, s, &Animation_type); + return self; +} - Vec2 position = {x, y}; +inline int get_id_Animation(mrb_state *mrb, mrb_value self) { + Wrapper *wrapper; + Data_Get_Struct(mrb, self, &Animation_type, wrapper); + return wrapper->id; +} - int id = get_id_Font(mrb, font_val); - font_pool.use(id); +static void ElementText_free(mrb_state *mrb, void *ptr) { + UNUSED(mrb); + int id = ((Wrapper *)ptr)->id; + app::element_pool.release(id); + delete (Wrapper *)ptr; +} - app::EText *element = new app::EText(key_id, id, {255, 255, 255, 255}); - element->position = position; - element->z = z; - element->click_through = click_through; +static const struct mrb_data_type ElementText_type = { + "ElementText", ElementText_free +}; - s->id = app::element_pool.acquire(element); - app::element_pool.use(s->id); - }) -) +static mrb_value ElementText_init(mrb_state *mrb, mrb_value self) { + UNUSED(mrb); + Wrapper *old = (Wrapper *)DATA_PTR(self); + if (old) + mrb_free(mrb, old); + mrb_data_init(self, nullptr, &ElementText_type); + Wrapper *s = new Wrapper(); + + mrb_value font_val; + mrb_sym key; + mrb_value kwargs; + mrb_get_args(mrb, "no|H", &key, &font_val, &kwargs); + + auto key_id = Localization::key_from_sym(mrb, key); + + if (!mrb_obj_is_kind_of(mrb, font_val, mrb_class_get(mrb, "Font"))) { + mrb_raise(mrb, mrb_class_get(mrb, "Exception"), "Expected a Font object"); + return mrb_nil_value(); + } + + float x = 0; + float y = 0; + float z = 0; + bool click_through = false; + if (!mrb_nil_p(kwargs)) { + mrb_value pos_hash = HASH_GET(kwargs, position); + HASH_FLOAT(pos_hash, x, x); + HASH_FLOAT(pos_hash, y, y); + + HASH_FLOAT(kwargs, z, z); + HASH_BOOL(kwargs, click_through, click_through); + } + + Vec2 position = {x, y}; + + int id = get_id_Font(mrb, font_val); + font_pool.use(id); + + app::EText *element = new app::EText(key_id, id, {255, 255, 255, 255}); + element->position = position; + element->z = z; + element->click_through = click_through; + + s->id = app::element_pool.acquire(element); + app::element_pool.use(s->id); + + mrb_data_init(self, s, &ElementText_type); + return self; +} + +inline int get_id_ElementText(mrb_state *mrb, mrb_value self) { + Wrapper *wrapper; + Data_Get_Struct(mrb, self, &ElementText_type, wrapper); + return wrapper->id; +} static mrb_value element_text_on_click(mrb_state *mrb, mrb_value self) { mrb_value block; @@ -134,46 +238,67 @@ static mrb_value element_text_on_click(mrb_state *mrb, mrb_value self) { return self; } -DEF_RB( - ElementRect, - ({ - app::element_pool.release(id); - }), - ({ - mrb_value shape_val; - mrb_int color; - mrb_value kwargs; - mrb_get_args(mrb, "Hi|H", &shape_val, &color, &kwargs); +static void ElementRect_free(mrb_state *mrb, void *ptr) { + UNUSED(mrb); + int id = ((Wrapper *)ptr)->id; + app::element_pool.release(id); + delete (Wrapper *)ptr; +} - float x = 0, y = 0, w = 0, h = 0; - if (!mrb_nil_p(shape_val)) { - HASH_FLOAT(shape_val, x, x); - HASH_FLOAT(shape_val, y, y); - HASH_FLOAT(shape_val, w, w); - HASH_FLOAT(shape_val, h, h); - } +static const struct mrb_data_type ElementRect_type = { + "ElementRect", ElementRect_free +}; - float z = 0; - if (!mrb_nil_p(kwargs)) - HASH_FLOAT(kwargs, z, z); +static mrb_value ElementRect_init(mrb_state *mrb, mrb_value self) { + UNUSED(mrb); + Wrapper *old = (Wrapper *)DATA_PTR(self); + if (old) + mrb_free(mrb, old); + mrb_data_init(self, nullptr, &ElementRect_type); + Wrapper *s = new Wrapper(); - Vec2 position = {x, y}; - Vec2 shape = {w, h}; + mrb_value shape_val; + mrb_int color; + mrb_value kwargs; + mrb_get_args(mrb, "Hi|H", &shape_val, &color, &kwargs); - app::ERect *element = new app::ERect( - shape, - {(uint8_t)((color >> 24) & 0xFF), - (uint8_t)((color >> 16) & 0xFF), - (uint8_t)((color >> 8) & 0xFF), - (uint8_t)(color & 0xFF)} - ); - element->position = position; - element->z = z; + float x = 0, y = 0, w = 0, h = 0; + if (!mrb_nil_p(shape_val)) { + HASH_FLOAT(shape_val, x, x); + HASH_FLOAT(shape_val, y, y); + HASH_FLOAT(shape_val, w, w); + HASH_FLOAT(shape_val, h, h); + } - s->id = app::element_pool.acquire(element); - app::element_pool.use(s->id); - }) -) + float z = 0; + if (!mrb_nil_p(kwargs)) + HASH_FLOAT(kwargs, z, z); + + Vec2 position = {x, y}; + Vec2 shape = {w, h}; + + app::ERect *element = new app::ERect( + shape, + {(uint8_t)((color >> 24) & 0xFF), + (uint8_t)((color >> 16) & 0xFF), + (uint8_t)((color >> 8) & 0xFF), + (uint8_t)(color & 0xFF)} + ); + element->position = position; + element->z = z; + + s->id = app::element_pool.acquire(element); + app::element_pool.use(s->id); + + mrb_data_init(self, s, &ElementRect_type); + return self; +} + +inline int get_id_ElementRect(mrb_state *mrb, mrb_value self) { + Wrapper *wrapper; + Data_Get_Struct(mrb, self, &ElementRect_type, wrapper); + return wrapper->id; +} static mrb_value element_rect_on_click(mrb_state *mrb, mrb_value self) { mrb_value block; @@ -201,52 +326,79 @@ 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) { int id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; - uint32_t color = ((uint32_t)element->color.r << 24) - | ((uint32_t)element->color.g << 16) - | ((uint32_t)element->color.b << 8) - | (uint32_t)element->color.a; + uint32_t color = + ((uint32_t)element->color.r << 24) | ((uint32_t)element->color.g << 16) + | ((uint32_t)element->color.b << 8) | (uint32_t)element->color.a; return mrb_fixnum_value(color); } -DEF_RB( - ElementImage, - ({ - app::element_pool.release(id); - }), - ({ - mrb_value animation_val; - mrb_value kwargs; - mrb_get_args(mrb, "o|H", &animation_val, &kwargs); +static void ElementImage_free(mrb_state *mrb, void *ptr) { + UNUSED(mrb); + int id = ((Wrapper *)ptr)->id; + app::element_pool.release(id); + delete (Wrapper *)ptr; +} - if (!mrb_obj_is_kind_of(mrb, animation_val, mrb_class_get(mrb, "Animation"))) { - mrb_raise(mrb, mrb_class_get(mrb, "Exception"), "Expected an Animation object"); - return mrb_nil_value(); - } +static const struct mrb_data_type ElementImage_type = { + "ElementImage", ElementImage_free +}; - float x = 0; - float y = 0; - float z = 0; - bool click_through = false; - if (!mrb_nil_p(kwargs)) { - mrb_value pos_hash = HASH_GET(kwargs, position); - HASH_FLOAT(pos_hash, x, x); - HASH_FLOAT(pos_hash, y, y); +static mrb_value ElementImage_init(mrb_state *mrb, mrb_value self) { + UNUSED(mrb); + Wrapper *old = (Wrapper *)DATA_PTR(self); + if (old) + mrb_free(mrb, old); + mrb_data_init(self, nullptr, &ElementImage_type); + Wrapper *s = new Wrapper(); - HASH_FLOAT(kwargs, z, z); - HASH_BOOL(kwargs, click_through, click_through); - } + mrb_value animation_val; + mrb_value kwargs; + mrb_get_args(mrb, "o|H", &animation_val, &kwargs); + if (!mrb_obj_is_kind_of( + mrb, + animation_val, + mrb_class_get(mrb, "Animation") + )) { + mrb_raise( + mrb, + mrb_class_get(mrb, "Exception"), + "Expected an Animation object" + ); + return mrb_nil_value(); + } - int id = get_id_Animation(mrb, animation_val); + float x = 0; + float y = 0; + float z = 0; + bool click_through = false; + if (!mrb_nil_p(kwargs)) { + mrb_value pos_hash = HASH_GET(kwargs, position); + HASH_FLOAT(pos_hash, x, x); + HASH_FLOAT(pos_hash, y, y); - app::EImage *element = new app::EImage(id); - element->position = {x, y}; - element->z = z; - element->click_through = click_through; + HASH_FLOAT(kwargs, z, z); + HASH_BOOL(kwargs, click_through, click_through); + } - s->id = app::element_pool.acquire(element); - app::element_pool.use(s->id); - }) -) + int id = get_id_Animation(mrb, animation_val); + + app::EImage *element = new app::EImage(id); + element->position = {x, y}; + element->z = z; + element->click_through = click_through; + + s->id = app::element_pool.acquire(element); + app::element_pool.use(s->id); + + mrb_data_init(self, s, &ElementImage_type); + return self; +} + +inline int get_id_ElementImage(mrb_state *mrb, mrb_value self) { + Wrapper *wrapper; + Data_Get_Struct(mrb, self, &ElementImage_type, wrapper); + return wrapper->id; +} static mrb_value element_image_on_click(mrb_state *mrb, mrb_value self) { mrb_value block; @@ -257,17 +409,36 @@ static mrb_value element_image_on_click(mrb_state *mrb, mrb_value self) { return self; } -DEF_RB( - Scene, - ({ - app::scene_pool.release(id); - }), - ({ - app::Scene *loading_scene = new app::Scene{}; - s->id = app::scene_pool.acquire(loading_scene); - app::scene_pool.use(s->id); - }) -) +static void Scene_free(mrb_state *mrb, void *ptr) { + UNUSED(mrb); + int id = ((Wrapper *)ptr)->id; + app::scene_pool.release(id); + delete (Wrapper *)ptr; +} + +static const struct mrb_data_type Scene_type = {"Scene", Scene_free}; + +static mrb_value Scene_init(mrb_state *mrb, mrb_value self) { + UNUSED(mrb); + Wrapper *old = (Wrapper *)DATA_PTR(self); + if (old) + mrb_free(mrb, old); + mrb_data_init(self, nullptr, &Scene_type); + Wrapper *s = new Wrapper(); + + app::Scene *loading_scene = new app::Scene{}; + s->id = app::scene_pool.acquire(loading_scene); + app::scene_pool.use(s->id); + + mrb_data_init(self, s, &Scene_type); + return self; +} + +inline int get_id_Scene(mrb_state *mrb, mrb_value self) { + Wrapper *wrapper; + Data_Get_Struct(mrb, self, &Scene_type, wrapper); + return wrapper->id; +} static mrb_value scene_add_element(mrb_state *mrb, mrb_value self) { mrb_value element_val; @@ -278,24 +449,34 @@ static mrb_value scene_add_element(mrb_state *mrb, mrb_value self) { && !mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementRect")) && !mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementImage")) ) { - mrb_raise(mrb, mrb_class_get(mrb, "Exception"), "Expected an ElementText, ElementRect, or ElementImage object"); + mrb_raise( + mrb, + mrb_class_get(mrb, "Exception"), + "Expected an ElementText, ElementRect, or ElementImage object" + ); return mrb_nil_value(); } int id = get_id_Scene(mrb, self); app::Scene *scene = app::scene_pool[id]; - // int element_id = get_id_Element(mrb, element_val); - int element_id; if (mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementText"))) { element_id = get_id_ElementText(mrb, element_val); - } else if (mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementRect"))) { + } else if ( + mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementRect")) + ) { element_id = get_id_ElementRect(mrb, element_val); - } else if (mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementImage"))) { + } else if ( + mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementImage")) + ) { element_id = get_id_ElementImage(mrb, element_val); } else { - mrb_raise(mrb, mrb_class_get(mrb, "Exception"), "Expected an ElementText, ElementRect, or ElementImage object"); + mrb_raise( + mrb, + mrb_class_get(mrb, "Exception"), + "Expected an ElementText, ElementRect, or ElementImage object" + ); return mrb_nil_value(); } @@ -313,7 +494,11 @@ static mrb_value scene_delete_element(mrb_state *mrb, mrb_value self) { && !mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementRect")) && !mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementImage")) ) { - mrb_raise(mrb, mrb_class_get(mrb, "Exception"), "Expected an ElementText, ElementRect, or ElementImage object"); + mrb_raise( + mrb, + mrb_class_get(mrb, "Exception"), + "Expected an ElementText, ElementRect, or ElementImage object" + ); return mrb_nil_value(); } @@ -323,12 +508,20 @@ static mrb_value scene_delete_element(mrb_state *mrb, mrb_value self) { int element_id; if (mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementText"))) { element_id = get_id_ElementText(mrb, element_val); - } else if (mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementRect"))) { + } else if ( + mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementRect")) + ) { element_id = get_id_ElementRect(mrb, element_val); - } else if (mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementImage"))) { + } else if ( + mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementImage")) + ) { element_id = get_id_ElementImage(mrb, element_val); } else { - mrb_raise(mrb, mrb_class_get(mrb, "Exception"), "Expected an ElementText, ElementRect, or ElementImage object"); + mrb_raise( + mrb, + mrb_class_get(mrb, "Exception"), + "Expected an ElementText, ElementRect, or ElementImage object" + ); return mrb_nil_value(); } @@ -430,40 +623,15 @@ inline void setup() { DEF_CLASS(Animation, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1)); DEF_CLASS(ElementText, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1)); - ADD_METHOD( - ElementText, - "on_click", - element_text_on_click, - MRB_ARGS_BLOCK() - ); + ADD_METHOD(ElementText, "on_click", element_text_on_click, MRB_ARGS_BLOCK()); DEF_CLASS(ElementRect, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1)); - ADD_METHOD( - ElementRect, - "on_click", - element_rect_on_click, - MRB_ARGS_BLOCK() - ); - ADD_METHOD( - ElementRect, - "color=", - element_rect_color_set, - MRB_ARGS_REQ(1) - ); - ADD_METHOD( - ElementRect, - "color", - element_rect_color_get, - MRB_ARGS_NONE() - ); + ADD_METHOD(ElementRect, "on_click", element_rect_on_click, MRB_ARGS_BLOCK()); + ADD_METHOD(ElementRect, "color=", element_rect_color_set, MRB_ARGS_REQ(1)); + ADD_METHOD(ElementRect, "color", element_rect_color_get, MRB_ARGS_NONE()); DEF_CLASS(ElementImage, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1)); - ADD_METHOD( - ElementImage, - "on_click", - element_image_on_click, - MRB_ARGS_BLOCK() - ); + ADD_METHOD(ElementImage, "on_click", element_image_on_click, MRB_ARGS_BLOCK()); DEF_CLASS(Scene, MRB_ARGS_NONE()); ADD_METHOD(Scene, "<<", scene_add_element, MRB_ARGS_REQ(1)); diff --git a/include/binding/ruby.h b/include/binding/ruby.h index 6bd0976..d8411e6 100644 --- a/include/binding/ruby.h +++ b/include/binding/ruby.h @@ -31,34 +31,6 @@ struct Wrapper { int id; }; -#define DEF_RB(NAME, FN_FREE, FN_INIT) \ - static void NAME##_free(mrb_state *mrb, void *ptr) { \ - UNUSED(mrb); \ - int id = ((Wrapper *)ptr)->id; \ - FN_FREE; \ - delete (Wrapper *)ptr; \ - } \ - static const struct mrb_data_type NAME##_type = { \ - #NAME, \ - NAME##_free \ - }; \ - static mrb_value NAME##_init(mrb_state *mrb, mrb_value self) { \ - UNUSED(mrb); \ - Wrapper *old = (Wrapper *)DATA_PTR(self); \ - if (old) \ - mrb_free(mrb, old); \ - mrb_data_init(self, nullptr, &NAME##_type); \ - Wrapper *s = new Wrapper(); \ - FN_INIT; \ - mrb_data_init(self, s, &NAME##_type); \ - return self; \ - } \ - inline int get_id_##NAME(mrb_state *mrb, mrb_value self) { \ - Wrapper *wrapper; \ - Data_Get_Struct(mrb, self, &NAME##_type, wrapper); \ - return wrapper->id; \ - } - #define ADD_METHOD(NAME, METHOD, FUNC, ARGS) \ mrb_define_method(Ruby::mrb, NAME##_class, METHOD, FUNC, ARGS); diff --git a/samples/button.rb b/samples/button.rb index 4fe94b4..0f03802 100644 --- a/samples/button.rb +++ b/samples/button.rb @@ -25,10 +25,63 @@ rect.on_click do 0xFF0000FF end +=begin + +input handling: + +on_click - exists to simplify on elements, not the standard way. + +App.map_key(:space, :jump) # maps the space key to a :jump action (multiple keys can be mapped to the same action) +# all events here are in english ones, (so need to find which english key corresponds to the key in the current language of the keyboard) +key can be one of [:a..:z, :0..:9, :space, :enter, :shift, :ctrl, :alt, :tab, :backspace, :escape, :up, :down, :left, :right, :middle] + +this can be checked anywhere using: + +App.down?(:jump) # returns true if the jump action is currently being pressed +App.pressed?(:jump) # returns true if the jump action was just pressed this frame +App.released?(:jump) # returns true if the jump action was just released this frame + +for wheel, you can use: + +App.wheel # returns a hash with :x and :y values representing the wheel movement since the last frame (can be used for zooming, scrolling, etc.) + +mouse position can be accessed with: + +App.mouse_position # returns a hash with :x and :y values representing the current mouse position in the window + +For localized input, you can use: + +App.start_text_input! + +App.text_input # returns the text typed this frame as a string (useful for text input fields, chat, etc.) + # can be multiple characters if the user types fast, so you should append it to a string variable to get the full input + +App.stop_text_input! + +#### + +also in a scene you can use (with click_though semantics): + +main_scene.elements_at(x, y) + +=end + + + main_scene.on_update do |delta_time| # puts "Delta time: #{delta_time}ms" # 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 + + # simple logic to handle hover + pos = App.mouse_position + next if pos.nil? # mouse position can be nil if the window is not focused, so we skip the hover logic in that case + elements = main_scene.elements_at(*pos.values) + if elements.include?(rect) + rect.color = 0x0000FFFF + else # also handles nil case, if the mouse is not over any element, we reset the color + rect.color = 0xFF0000FF + end end main_scene << text