From 6a29c113e055f4ce34e837ea0f5a9c5f8cd9dc65 Mon Sep 17 00:00:00 2001 From: Daanish Date: Tue, 5 May 2026 13:15:09 +0100 Subject: [PATCH] Refractor --- include/binding/ruby.h | 65 ++++++- src/main.cc | 418 ++++++++++++++++------------------------- 2 files changed, 221 insertions(+), 262 deletions(-) diff --git a/include/binding/ruby.h b/include/binding/ruby.h index 44f0a9e..501a0fa 100644 --- a/include/binding/ruby.h +++ b/include/binding/ruby.h @@ -1,8 +1,57 @@ +#ifndef RUBY_H +#define RUBY_H + #include "pch.h" #include "utils.h" +#define DEF_SYM(name) inline mrb_sym sym_##name = mrb_intern_cstr(Ruby::mrb, #name); +#define SYM(name) mrb_symbol_value(sym_##name) + +#define HASH_GET(h, key) mrb_hash_get(Ruby::mrb, h, SYM(key)) + +#define HASH_FLOAT(h, key, out) \ + do { \ + mrb_value v = HASH_GET(h, key); \ + if (mrb_fixnum_p(v)) \ + out = (float)mrb_fixnum(v); \ + } while (0) + +#define HASH_BOOL(h, key, out) \ + do { \ + mrb_value v = HASH_GET(h, key); \ + if (!mrb_nil_p(v)) \ + out = mrb_bool(v); \ + } while (0) + +struct Wrapper { + int id; +}; + +#define DEF_RB(NAME, FN_FREE, FN_INIT) \ + static void NAME##_free(mrb_state *mrb, void *ptr) { \ + 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) { \ + Wrapper *s = new Wrapper(); \ + FN_INIT; \ + DATA_PTR(self) = s; \ + DATA_TYPE(self) = &NAME##_type; \ + return self; \ + } + +inline int get_id(mrb_value self) { + return ((Wrapper *)DATA_PTR(self))->id; +} + namespace Ruby { inline mrb_state *mrb = mrb_open(); + struct Block { mrb_value proc; @@ -39,4 +88,18 @@ inline void run_string(const char *code, size_t length) { mrb_load_nstring(mrb, code, length); mrb_gc_arena_restore(mrb, ai); } -}; // namespace Ruby \ No newline at end of file +}; // namespace Ruby + +DEF_SYM(pixel_art) +DEF_SYM(bold) +DEF_SYM(italic) +DEF_SYM(underline) +DEF_SYM(position) +DEF_SYM(click_through) +DEF_SYM(x) +DEF_SYM(y) +DEF_SYM(w) +DEF_SYM(h) +DEF_SYM(z) + +#endif \ No newline at end of file diff --git a/src/main.cc b/src/main.cc index b0ff34b..69efecb 100644 --- a/src/main.cc +++ b/src/main.cc @@ -2,241 +2,18 @@ app::App *app_ = nullptr; -struct SceneWrapper { - int id; -}; - -static void scene_free(mrb_state *mrb, void *ptr) { - int id = ((SceneWrapper *)ptr)->id; - - app::Scene *scene = app::scene_pool[id]; - if (scene != nullptr) - scene->unused = true; - - delete (SceneWrapper *)ptr; -} - -static const struct mrb_data_type scene_type = { - "Scene", - scene_free -}; - -static mrb_value scene_init(mrb_state *mrb, mrb_value self) { - SceneWrapper *s = new SceneWrapper(); - - app::Scene *loading_scene = new app::Scene{}; - s->id = app::scene_pool.acquire(loading_scene); - - DATA_PTR(self) = s; - DATA_TYPE(self) = &scene_type; - - return self; -} - -SceneWrapper *unwrap_scene(mrb_value self) { - return (SceneWrapper *)DATA_PTR(self); -} - -struct FontWrapper { - int id; -}; - -static void font_free(mrb_state *mrb, void *ptr) { - int id = ((FontWrapper *)ptr)->id; - - window.unload_font(id); - - delete (FontWrapper *)ptr; -} - -static const struct mrb_data_type font_type = { - "Font", - font_free -}; - -static mrb_value font_init(mrb_state *mrb, mrb_value self) { - char *path; - mrb_int size; - mrb_value kwargs; - mrb_get_args(mrb, "zi|H", &path, &size, &kwargs); - - bool pixel_art = false, bold = false, italic = false, underline = false; - if (!mrb_nil_p(kwargs)) { - mrb_value p_val = mrb_hash_get(mrb, kwargs, mrb_symbol_value(mrb_intern_cstr(mrb, "pixel_art"))); - if (!mrb_nil_p(p_val)) - pixel_art = mrb_bool(p_val); - mrb_value bold_val = mrb_hash_get(mrb, kwargs, mrb_symbol_value(mrb_intern_cstr(mrb, "bold"))); - if (!mrb_nil_p(bold_val)) - bold = mrb_bool(bold_val); - mrb_value italic_val = mrb_hash_get(mrb, kwargs, mrb_symbol_value(mrb_intern_cstr(mrb, "italic"))); - if (!mrb_nil_p(italic_val)) - italic = mrb_bool(italic_val); - mrb_value underline_val = mrb_hash_get(mrb, kwargs, mrb_symbol_value(mrb_intern_cstr(mrb, "underline"))); - if (!mrb_nil_p(underline_val)) - underline = mrb_bool(underline_val); - } - - FontWrapper *f = new FontWrapper(); - f->id = window.load_font(path, size, bold, italic, underline, pixel_art); - - DATA_PTR(self) = f; - DATA_TYPE(self) = &font_type; - - return self; -} - -struct ElementTextWrapper { - int id; -}; - -static void element_text_free(mrb_state *mrb, void *ptr) { - int id = ((ElementTextWrapper *)ptr)->id; - - app::Element *element = app::element_pool[id]; - if (element != nullptr) - element->reference_count--; - - if (element != nullptr && element->reference_count <= 0) { - delete element; - app::element_pool.release(id); - } - - delete (ElementTextWrapper *)ptr; -} - -static const struct mrb_data_type element_text_type = { - "ElementText", - element_text_free -}; - -static mrb_value element_text_init(mrb_state *mrb, mrb_value self) { - 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(Ruby::mrb, "Exception"), "Expected a Font object"); - return mrb_nil_value(); - } - - float x = 0, y = 0; - float z = 0; - bool click_through = false; - if (!mrb_nil_p(kwargs)) { - mrb_value pos_hash = mrb_hash_get(mrb, kwargs, mrb_symbol_value(mrb_intern_cstr(mrb, "position"))); - if (!mrb_nil_p(pos_hash)) { - mrb_value x_val = mrb_hash_get(mrb, pos_hash, mrb_symbol_value(mrb_intern_cstr(mrb, "x"))); - mrb_value y_val = mrb_hash_get(mrb, pos_hash, mrb_symbol_value(mrb_intern_cstr(mrb, "y"))); - if (mrb_fixnum_p(x_val)) - x = (float)mrb_fixnum(x_val); - if (mrb_fixnum_p(y_val)) - y = (float)mrb_fixnum(y_val); - } - mrb_value z_val = mrb_hash_get(mrb, kwargs, mrb_symbol_value(mrb_intern_cstr(mrb, "z"))); - if (mrb_fixnum_p(z_val)) - z = (float)mrb_fixnum(z_val); - mrb_value click_through_val = mrb_hash_get(mrb, kwargs, mrb_symbol_value(mrb_intern_cstr(mrb, "click_through"))); - if (!mrb_nil_p(click_through_val)) - click_through = mrb_bool(click_through_val); - } - - Vec2 position = {x, y}; - - FontWrapper *font = (FontWrapper *)DATA_PTR(font_val); - - app::EText *element = new app::EText(key_id, font->id, {255, 255, 255, 255}); - element->reference_count++; - element->position = position; - element->z = z; - element->click_through = click_through; - - ElementTextWrapper *wrapper = new ElementTextWrapper(); - wrapper->id = app::element_pool.acquire(element); - - DATA_PTR(self) = wrapper; - DATA_TYPE(self) = &element_text_type; - - return self; -} - -struct ElementRectWrapper { - int id; -}; - -static void element_rect_free(mrb_state *mrb, void *ptr) { - int id = ((ElementRectWrapper *)ptr)->id; - - app::Element *element = app::element_pool[id]; - if (element != nullptr) - element->reference_count--; - - if (element != nullptr && element->reference_count <= 0) { - delete element; - app::element_pool.release(id); - } - - delete (ElementRectWrapper *)ptr; -} - -static const struct mrb_data_type element_rect_type = { - "ElementRect", - element_rect_free -}; - -static mrb_value element_rect_init(mrb_state *mrb, mrb_value self) { - mrb_value shape_val; - mrb_int color; - mrb_value kwargs; - mrb_get_args(mrb, "Hi|H", &shape_val, &color, &kwargs); - - float x = 0, y = 0, w = 0, h = 0; - if (!mrb_nil_p(shape_val)) { - mrb_value x_val = mrb_hash_get(mrb, shape_val, mrb_symbol_value(mrb_intern_cstr(mrb, "x"))); - mrb_value y_val = mrb_hash_get(mrb, shape_val, mrb_symbol_value(mrb_intern_cstr(mrb, "y"))); - mrb_value w_val = mrb_hash_get(mrb, shape_val, mrb_symbol_value(mrb_intern_cstr(mrb, "w"))); - mrb_value h_val = mrb_hash_get(mrb, shape_val, mrb_symbol_value(mrb_intern_cstr(mrb, "h"))); - if (mrb_fixnum_p(x_val)) - x = (float)mrb_fixnum(x_val); - if (mrb_fixnum_p(y_val)) - y = (float)mrb_fixnum(y_val); - if (mrb_fixnum_p(w_val)) - w = (float)mrb_fixnum(w_val); - if (mrb_fixnum_p(h_val)) - h = (float)mrb_fixnum(h_val); - } - - float z = 0; - if (!mrb_nil_p(kwargs)) { - mrb_value z_val = mrb_hash_get(mrb, kwargs, mrb_symbol_value(mrb_intern_cstr(mrb, "z"))); - if (mrb_fixnum_p(z_val)) - z = (float)mrb_fixnum(z_val); - } - - 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->reference_count++; - element->position = position; - element->z = z; - - ElementRectWrapper *wrapper = new ElementRectWrapper(); - wrapper->id = app::element_pool.acquire(element); - - DATA_PTR(self) = wrapper; - DATA_TYPE(self) = &element_rect_type; - - return self; -} +DEF_RB( + Scene, + ({ + app::Scene *scene = app::scene_pool[id]; + if (scene != nullptr) + scene->unused = true; + }), + ({ + app::Scene *loading_scene = new app::Scene{}; + s->id = app::scene_pool.acquire(loading_scene); + }) +) static mrb_value scene_add_element(mrb_state *mrb, mrb_value self) { mrb_value element_val; @@ -247,23 +24,142 @@ static mrb_value scene_add_element(mrb_state *mrb, mrb_value self) { return mrb_nil_value(); } - SceneWrapper *s = unwrap_scene(self); - app::Scene *scene = app::scene_pool[s->id]; + int id = get_id(self); + app::Scene *scene = app::scene_pool[id]; int element_id; - if (mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementText"))) { - ElementTextWrapper *wrapper = (ElementTextWrapper *)DATA_PTR(element_val); - element_id = wrapper->id; - } else { - ElementRectWrapper *wrapper = (ElementRectWrapper *)DATA_PTR(element_val); - element_id = wrapper->id; - } + if ( + mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementText")) || mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementRect")) + ) + element_id = get_id(element_val); scene->add_element(element_id); - return self; } +DEF_RB( + Font, + ({ window.unload_font(id); }), + ({ + char *path; + mrb_int size; + mrb_value kwargs; + mrb_get_args(mrb, "zi|H", &path, &size, &kwargs); + + 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); + }) +) + +DEF_RB( + ElementText, + ({ + app::Element *element = app::element_pool[id]; + if (element != nullptr) + element->reference_count--; + + if (element != nullptr && element->reference_count <= 0) { + delete element; + 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); + + 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(Ruby::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_val); + + app::EText *element = new app::EText(key_id, id, {255, 255, 255, 255}); + element->reference_count++; + element->position = position; + element->z = z; + element->click_through = click_through; + + s->id = app::element_pool.acquire(element); + }) +) + +DEF_RB( + ElementRect, + ({ + app::Element *element = app::element_pool[id]; + if (element != nullptr) + element->reference_count--; + + if (element != nullptr && element->reference_count <= 0) { + delete element; + 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); + + 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); + } + + 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->reference_count++; + element->position = position; + element->z = z; + + s->id = app::element_pool.acquire(element); + }) +) + mrb_value app_run(mrb_state *mrb, mrb_value self) { mrb_int width, height; char *title = nullptr; @@ -291,8 +187,8 @@ mrb_value app_start(mrb_state *mrb, mrb_value self) { return mrb_nil_value(); } - SceneWrapper *s = unwrap_scene(scene_val); - app_->switch_to_scene(s->id); + int id = get_id(scene_val); + app_->switch_to_scene(id); app_->loop(); return mrb_nil_value(); @@ -307,8 +203,8 @@ mrb_value app_switch_to(mrb_state *mrb, mrb_value self) { return mrb_nil_value(); } - SceneWrapper *s = unwrap_scene(scene_val); - app_->switch_to_scene(s->id); + int id = get_id(scene_val); + app_->switch_to_scene(id); return mrb_nil_value(); } @@ -340,32 +236,32 @@ static mrb_value app_localize(mrb_state *mrb, mrb_value self) { int main(int argc, char *argv[]) { RClass *font_class = mrb_define_class(Ruby::mrb, "Font", Ruby::mrb->object_class); - mrb_define_method(Ruby::mrb, font_class, "initialize", font_init, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1)); + mrb_define_method(Ruby::mrb, font_class, "initialize", Font_init, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1)); RClass *element_text_class = mrb_define_class(Ruby::mrb, "ElementText", Ruby::mrb->object_class); - mrb_define_method(Ruby::mrb, element_text_class, "initialize", element_text_init, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1)); + mrb_define_method(Ruby::mrb, element_text_class, "initialize", ElementText_init, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1)); mrb_define_method(Ruby::mrb, element_text_class, "on_click", [](mrb_state *mrb, mrb_value self) { mrb_value block; mrb_get_args(mrb, "&", &block); - ElementTextWrapper *wrapper = (ElementTextWrapper *)DATA_PTR(self); - app::Element *element = app::element_pool[wrapper->id]; + int id = get_id(self); + app::Element *element = app::element_pool[id]; element->on_click.set_proc(block); return self; }, MRB_ARGS_BLOCK()); RClass *element_rect_class = mrb_define_class(Ruby::mrb, "ElementRect", Ruby::mrb->object_class); - mrb_define_method(Ruby::mrb, element_rect_class, "initialize", element_rect_init, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1)); + mrb_define_method(Ruby::mrb, element_rect_class, "initialize", ElementRect_init, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1)); mrb_define_method(Ruby::mrb, element_rect_class, "on_click", [](mrb_state *mrb, mrb_value self) { mrb_value block; mrb_get_args(mrb, "&", &block); - ElementRectWrapper *wrapper = (ElementRectWrapper *)DATA_PTR(self); - app::Element *element = app::element_pool[wrapper->id]; + int id = get_id(self); + app::Element *element = app::element_pool[id]; element->on_click.set_proc(block); return self; }, MRB_ARGS_BLOCK()); mrb_define_method(Ruby::mrb, element_rect_class, "color=", [](mrb_state *mrb, mrb_value self) { mrb_value color_val; mrb_get_args(mrb, "o", &color_val); - ElementRectWrapper *wrapper = (ElementRectWrapper *)DATA_PTR(self); - app::ERect *element = (app::ERect *)app::element_pool[wrapper->id]; + int id = get_id(self); + app::ERect *element = (app::ERect *)app::element_pool[id]; element->color = { (uint8_t)((mrb_fixnum(color_val) >> 24) & 0xFF), (uint8_t)((mrb_fixnum(color_val) >> 16) & 0xFF), @@ -374,8 +270,8 @@ int main(int argc, char *argv[]) { }; return self; }, MRB_ARGS_REQ(1)); mrb_define_method(Ruby::mrb, element_rect_class, "color", [](mrb_state *mrb, mrb_value self) { - ElementRectWrapper *wrapper = (ElementRectWrapper *)DATA_PTR(self); - app::ERect *element = (app::ERect *)app::element_pool[wrapper->id]; + int id = get_id(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) | @@ -383,7 +279,7 @@ int main(int argc, char *argv[]) { return mrb_fixnum_value(color); }, MRB_ARGS_NONE()); RClass *scene_class = mrb_define_class(Ruby::mrb, "Scene", Ruby::mrb->object_class); - mrb_define_method(Ruby::mrb, scene_class, "initialize", scene_init, MRB_ARGS_NONE()); + mrb_define_method(Ruby::mrb, scene_class, "initialize", Scene_init, MRB_ARGS_NONE()); mrb_define_method(Ruby::mrb, scene_class, "<<", scene_add_element, MRB_ARGS_REQ(1)); RClass *app_module = mrb_define_module(Ruby::mrb, "App");