#ifndef DEFINITIONS_H #define DEFINITIONS_H #include "app/app.h" namespace definitions { 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); mrb_value obj = mrb_obj_value(obj_b); Wrapper *w = new Wrapper(); w->id = id; mrb_data_init(obj, w, type); return obj; } static void Font_free(mrb_state *mrb, void *ptr) { UNUSED(mrb); uint64_t id = ((Wrapper *)ptr)->id; font_pool.release(id); delete (Wrapper *)ptr; } static const struct mrb_data_type Font_type = {"Font", Font_free}; 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(); 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); mrb_data_init(self, s, &Font_type); return self; } inline uint64_t get_id_Font(mrb_state *mrb, mrb_value self) { Wrapper *wrapper; Data_Get_Struct(mrb, self, &Font_type, wrapper); return wrapper->id; } static mrb_value font_equal(mrb_state *mrb, mrb_value self) { mrb_value other; mrb_get_args(mrb, "o", &other); if (!mrb_obj_is_kind_of(mrb, other, mrb_class_get(mrb, "Font"))) return mrb_false_value(); uint64_t id_self = get_id_Font(mrb, self); uint64_t id_other = get_id_Font(mrb, other); return mrb_bool_value(id_self == id_other); } static mrb_value font_hash(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_Font(mrb, self); return mrb_fixnum_value(id); } static void Image_free(mrb_state *mrb, void *ptr) { UNUSED(mrb); uint64_t 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); bool pixel_art = false; if (!mrb_nil_p(kwargs)) HASH_BOOL(kwargs, pixel_art, pixel_art); s->id = window.load_image(path, pixel_art); mrb_data_init(self, s, &Image_type); return self; } inline uint64_t get_id_Image(mrb_state *mrb, mrb_value self) { Wrapper *wrapper; Data_Get_Struct(mrb, self, &Image_type, wrapper); return wrapper->id; } static mrb_value image_equal(mrb_state *mrb, mrb_value self) { mrb_value other; mrb_get_args(mrb, "o", &other); if (!mrb_obj_is_kind_of(mrb, other, mrb_class_get(mrb, "Image"))) return mrb_false_value(); uint64_t id_self = get_id_Image(mrb, self); uint64_t id_other = get_id_Image(mrb, other); return mrb_bool_value(id_self == id_other); } static mrb_value image_hash(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_Image(mrb, self); return mrb_fixnum_value(id); } static mrb_value image_width(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_Image(mrb, self); return mrb_float_value(mrb, window.get_image_size(id).x); } static mrb_value image_height(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_Image(mrb, self); return mrb_float_value(mrb, window.get_image_size(id).y); } static void Animation_free(mrb_state *mrb, void *ptr) { UNUSED(mrb); uint64_t 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(); } uint64_t frame_id = get_id_Image(mrb, frame_val); image_pool.use(frame_id); frame_ids.push_back(frame_id); } Animation *animation = new Animation{frame_ids, fps}; s->id = animation_pool.acquire(animation); animation_pool.use(s->id); mrb_data_init(self, s, &Animation_type); return self; } inline uint64_t get_id_Animation(mrb_state *mrb, mrb_value self) { Wrapper *wrapper; Data_Get_Struct(mrb, self, &Animation_type, wrapper); return wrapper->id; } static mrb_value animation_equal(mrb_state *mrb, mrb_value self) { mrb_value other; mrb_get_args(mrb, "o", &other); if (!mrb_obj_is_kind_of(mrb, other, mrb_class_get(mrb, "Animation"))) return mrb_false_value(); uint64_t id_self = get_id_Animation(mrb, self); uint64_t id_other = get_id_Animation(mrb, other); return mrb_bool_value(id_self == id_other); } static mrb_value animation_hash(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_Animation(mrb, self); return mrb_fixnum_value(id); } static mrb_value animation_frames_set(mrb_state *mrb, mrb_value self) { const mrb_value *frames_val; mrb_int frames_len; mrb_get_args(mrb, "a", &frames_val, &frames_len); uint64_t id = get_id_Animation(mrb, self); Animation *animation = animation_pool[id]; std::vector new_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(); } uint64_t frame_id = get_id_Image(mrb, frame_val); image_pool.use(frame_id); new_frame_ids.push_back(frame_id); } // Release old frames for (uint64_t frame_id : animation->frames) image_pool.release(frame_id); animation->frames = std::move(new_frame_ids); return mrb_nil_value(); } static mrb_value animation_frames_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_Animation(mrb, self); Animation *animation = animation_pool[id]; mrb_value frames_array = mrb_ary_new_capa(mrb, animation->frames.size()); for (uint64_t frame_id : animation->frames) { image_pool.use(frame_id); mrb_value frame_obj = wrap(mrb, mrb_class_get(mrb, "Image"), &Image_type, frame_id); mrb_ary_push(mrb, frames_array, frame_obj); } return frames_array; } static mrb_value animation_fps_set(mrb_state *mrb, mrb_value self) { mrb_float fps; mrb_get_args(mrb, "f", &fps); uint64_t id = get_id_Animation(mrb, self); Animation *animation = animation_pool[id]; animation->frame_rate = fps; return mrb_nil_value(); } static mrb_value animation_fps_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_Animation(mrb, self); Animation *animation = animation_pool[id]; return mrb_float_value(mrb, animation->frame_rate); } static void ElementText_free(mrb_state *mrb, void *ptr) { UNUSED(mrb); uint64_t id = ((Wrapper *)ptr)->id; app::element_pool.release(id); delete (Wrapper *)ptr; } static const struct mrb_data_type ElementText_type = { "ElementText", ElementText_free }; 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_sym key; mrb_value font_val; mrb_int color_i = 0xFFFFFF; mrb_value t_args; mrb_value kwargs; mrb_get_args(mrb, "noi|HH", &key, &font_val, &color_i, &t_args, &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, y = 0, z = 0, rotation = 0; float scale_x = 1, scale_y = 1, alpha = 1; float pivot_x = 0.5, pivot_y = 0.5; mrb_sym click_mode_sym = sym_block; if (!mrb_nil_p(kwargs)) { mrb_value pos_hash = HASH_GET(kwargs, position); if (!mrb_nil_p(pos_hash)) { HASH_FLOAT(pos_hash, x, x); HASH_FLOAT(pos_hash, y, y); } mrb_value scale_hash = HASH_GET(kwargs, scale); if (!mrb_nil_p(scale_hash)) { HASH_FLOAT(scale_hash, x, scale_x); HASH_FLOAT(scale_hash, y, scale_y); } mrb_value pivot_hash = HASH_GET(kwargs, pivot); if (!mrb_nil_p(pivot_hash)) { HASH_FLOAT(pivot_hash, x, pivot_x); HASH_FLOAT(pivot_hash, y, pivot_y); } HASH_FLOAT(kwargs, z, z); HASH_FLOAT(kwargs, rotation, rotation); HASH_FLOAT(kwargs, alpha, alpha); mrb_value v = HASH_GET(kwargs, click_mode); if (!mrb_nil_p(v)) { click_mode_sym = mrb_symbol(v); } } uint64_t id = get_id_Font(mrb, font_val); font_pool.use(id); Color color = { (uint8_t)((color_i >> 16) & 0xFF), (uint8_t)((color_i >> 8) & 0xFF), (uint8_t)((color_i) & 0xFF) }; app::EText *element = new app::EText(key_id, id, color, t_args); element->position = {x, y}; element->scale = {scale_x, scale_y}; element->rotation = rotation; element->pivot = {pivot_x, pivot_y}; element->alpha = alpha; element->z = z; std::string click_mode = mrb_sym2name(mrb, click_mode_sym); if (click_mode == "pass") element->click_mode = ClickMode::PASS; else if (click_mode == "block") element->click_mode = ClickMode::BLOCK; else if (click_mode == "ignore") element->click_mode = ClickMode::IGNORE; s->id = app::element_pool.acquire(element); app::element_pool.use(s->id); mrb_data_init(self, s, &ElementText_type); return self; } inline uint64_t 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; mrb_get_args(mrb, "&", &block); uint64_t id = get_id_ElementText(mrb, self); app::Element *element = app::element_pool[id]; element->on_click.set_proc(block); return self; } static mrb_value element_text_equal(mrb_state *mrb, mrb_value self) { mrb_value other; mrb_get_args(mrb, "o", &other); if (!mrb_obj_is_kind_of(mrb, other, mrb_class_get(mrb, "ElementText"))) return mrb_false_value(); uint64_t id_self = get_id_ElementText(mrb, self); uint64_t id_other = get_id_ElementText(mrb, other); return mrb_bool_value(id_self == id_other); } static mrb_value element_text_inspect(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; std::string str = "#key) + " font_id=" + std::format("0x{:016x}", element->font_id) + ">"; return mrb_str_new_cstr(mrb, str.c_str()); } static mrb_value element_text_to_s(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; std::string localized_text = Localization::get(Ruby::mrb, element->key, element->params); return mrb_str_new_cstr(mrb, localized_text.c_str()); } static mrb_value element_text_hash(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); return mrb_fixnum_value(id); } static mrb_value element_text_key_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; return mrb_symbol_value(Localization::lang_to_sym(mrb, element->key)); } static mrb_value element_text_key_set(mrb_state *mrb, mrb_value self) { mrb_sym key_sym; mrb_get_args(mrb, "n", &key_sym); uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; element->key = Localization::lang_from_sym(mrb, key_sym); return mrb_nil_value(); } static mrb_value element_text_font_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; if (element->font_id == UINT64_MAX) return mrb_nil_value(); font_pool.use(element->font_id); return wrap(mrb, mrb_class_get(mrb, "Font"), &Font_type, element->font_id); } static mrb_value element_text_font_set(mrb_state *mrb, mrb_value self) { mrb_value font_val; mrb_get_args(mrb, "o", &font_val); 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(); } uint64_t font_id = get_id_Font(mrb, font_val); uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; if (element->font_id != UINT64_MAX) font_pool.release(element->font_id); element->font_id = font_id; font_pool.use(font_id); return mrb_nil_value(); } static mrb_value element_text_color_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; return mrb_fixnum_value( (element->color.r << 16) | (element->color.g << 8) | (element->color.b) ); } static mrb_value element_text_color_set(mrb_state *mrb, mrb_value self) { mrb_int color_val; mrb_get_args(mrb, "i", &color_val); uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; element->color = { (uint8_t)((color_val >> 16) & 0xFF), (uint8_t)((color_val >> 8) & 0xFF), (uint8_t)((color_val) & 0xFF) }; return mrb_nil_value(); } static mrb_value element_text_params(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; return element->params; } static mrb_value element_text_params_load(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; element->reload_params(); return mrb_nil_value(); } static mrb_value element_text_position_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; mrb_value pos_hash = mrb_hash_new(mrb); HASH_SET(pos_hash, x, mrb_float_value(mrb, element->position.x)); HASH_SET(pos_hash, y, mrb_float_value(mrb, element->position.y)); return pos_hash; } static mrb_value element_text_position_set(mrb_state *mrb, mrb_value self) { mrb_value pos_hash; mrb_get_args(mrb, "H", &pos_hash); uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; HASH_FLOAT(pos_hash, x, element->position.x); HASH_FLOAT(pos_hash, y, element->position.y); return mrb_nil_value(); } static mrb_value element_text_rotation_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; return mrb_float_value(mrb, element->rotation); } static mrb_value element_text_rotation_set(mrb_state *mrb, mrb_value self) { mrb_float rotation; mrb_get_args(mrb, "f", &rotation); uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; element->rotation = rotation; return mrb_nil_value(); } static mrb_value element_text_pivot_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; mrb_value pivot_hash = mrb_hash_new(mrb); HASH_SET(pivot_hash, x, mrb_float_value(mrb, element->pivot.x)); HASH_SET(pivot_hash, y, mrb_float_value(mrb, element->pivot.y)); return pivot_hash; } static mrb_value element_text_pivot_set(mrb_state *mrb, mrb_value self) { mrb_value pivot_hash; mrb_get_args(mrb, "H", &pivot_hash); uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; HASH_FLOAT(pivot_hash, x, element->pivot.x); HASH_FLOAT(pivot_hash, y, element->pivot.y); return mrb_nil_value(); } static mrb_value element_text_scale_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; mrb_value scale_hash = mrb_hash_new(mrb); HASH_SET(scale_hash, x, mrb_float_value(mrb, element->scale.x)); HASH_SET(scale_hash, y, mrb_float_value(mrb, element->scale.y)); return scale_hash; } static mrb_value element_text_scale_set(mrb_state *mrb, mrb_value self) { mrb_value scale_hash; mrb_get_args(mrb, "H", &scale_hash); uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; HASH_FLOAT(scale_hash, x, element->scale.x); HASH_FLOAT(scale_hash, y, element->scale.y); return mrb_nil_value(); } static mrb_value element_text_alpha_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; return mrb_float_value(mrb, element->alpha); } static mrb_value element_text_alpha_set(mrb_state *mrb, mrb_value self) { mrb_float alpha; mrb_get_args(mrb, "f", &alpha); uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; element->alpha = alpha; return mrb_nil_value(); } static mrb_value element_text_z_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; return mrb_float_value(mrb, element->z); } static mrb_value element_text_z_set(mrb_state *mrb, mrb_value self) { mrb_float z; mrb_get_args(mrb, "f", &z); uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; element->z = z; return mrb_nil_value(); } static mrb_value element_text_click_mode_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; std::string click_mode_str; switch (element->click_mode) { case ClickMode::PASS: click_mode_str = "pass"; break; case ClickMode::BLOCK: click_mode_str = "block"; break; case ClickMode::IGNORE: click_mode_str = "ignore"; break; } return mrb_symbol_value(mrb_intern_cstr(mrb, click_mode_str.c_str())); } static mrb_value element_text_click_mode_set(mrb_state *mrb, mrb_value self) { mrb_sym click_mode_sym; mrb_get_args(mrb, "n", &click_mode_sym); uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; std::string click_mode_str = mrb_sym2name(mrb, click_mode_sym); if (click_mode_str == "pass") element->click_mode = ClickMode::PASS; else if (click_mode_str == "block") element->click_mode = ClickMode::BLOCK; else if (click_mode_str == "ignore") element->click_mode = ClickMode::IGNORE; return mrb_nil_value(); } static mrb_value element_text_width(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; return mrb_float_value(mrb, element->size().x); } static mrb_value element_text_height(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementText(mrb, self); app::EText *element = (app::EText *)app::element_pool[id]; return mrb_float_value(mrb, element->size().y); } static void ElementRect_free(mrb_state *mrb, void *ptr) { UNUSED(mrb); uint64_t id = ((Wrapper *)ptr)->id; app::element_pool.release(id); delete (Wrapper *)ptr; } static const struct mrb_data_type ElementRect_type = { "ElementRect", ElementRect_free }; 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(); mrb_float w, h; mrb_int color_i = 0xFFFFFF; mrb_value kwargs; mrb_get_args(mrb, "ffi|H", &w, &h, &color_i, &kwargs); float x = 0, y = 0, z = 0, rotation = 0; float scale_x = 1, scale_y = 1, alpha = 1, pivot_x = 0.5, pivot_y = 0.5; mrb_sym click_mode_sym = sym_block; if (!mrb_nil_p(kwargs)) { mrb_value pos_hash = HASH_GET(kwargs, position); if (!mrb_nil_p(pos_hash)) { HASH_FLOAT(pos_hash, x, x); HASH_FLOAT(pos_hash, y, y); } mrb_value scale_hash = HASH_GET(kwargs, scale); if (!mrb_nil_p(scale_hash)) { HASH_FLOAT(scale_hash, x, scale_x); HASH_FLOAT(scale_hash, y, scale_y); } mrb_value pivot_hash = HASH_GET(kwargs, pivot); if (!mrb_nil_p(pivot_hash)) { HASH_FLOAT(pivot_hash, x, pivot_x); HASH_FLOAT(pivot_hash, y, pivot_y); } HASH_FLOAT(kwargs, z, z); HASH_FLOAT(kwargs, rotation, rotation); HASH_FLOAT(kwargs, alpha, alpha); mrb_value v = HASH_GET(kwargs, click_mode); if (!mrb_nil_p(v)) { click_mode_sym = mrb_symbol(v); } } Vec2 shape = {(float)w, (float)h}; Color color = { (uint8_t)((color_i >> 16) & 0xFF), (uint8_t)((color_i >> 8) & 0xFF), (uint8_t)((color_i) & 0xFF) }; app::ERect *element = new app::ERect( shape, color ); element->position = {x, y}; element->scale = {scale_x, scale_y}; element->rotation = rotation; element->pivot = {pivot_x, pivot_y}; element->alpha = alpha; element->z = z; std::string click_mode = mrb_sym2name(mrb, click_mode_sym); if (click_mode == "pass") element->click_mode = ClickMode::PASS; else if (click_mode == "block") element->click_mode = ClickMode::BLOCK; else if (click_mode == "ignore") element->click_mode = ClickMode::IGNORE; s->id = app::element_pool.acquire(element); app::element_pool.use(s->id); mrb_data_init(self, s, &ElementRect_type); return self; } inline uint64_t 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; mrb_get_args(mrb, "&", &block); uint64_t id = get_id_ElementRect(mrb, self); app::Element *element = app::element_pool[id]; element->on_click.set_proc(block); return self; } static mrb_value element_rect_width_set(mrb_state *mrb, mrb_value self) { mrb_float width; mrb_get_args(mrb, "f", &width); uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; element->shape.x = width; return mrb_nil_value(); } static mrb_value element_rect_width_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; return mrb_float_value(mrb, element->shape.x); } static mrb_value element_rect_height_set(mrb_state *mrb, mrb_value self) { mrb_float height; mrb_get_args(mrb, "f", &height); uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; element->shape.y = height; return mrb_nil_value(); } static mrb_value element_rect_height_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; return mrb_float_value(mrb, element->shape.y); } static mrb_value element_rect_color_set(mrb_state *mrb, mrb_value self) { mrb_value color_val; mrb_get_args(mrb, "o", &color_val); uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; element->color = { (uint8_t)((mrb_fixnum(color_val) >> 16) & 0xFF), (uint8_t)((mrb_fixnum(color_val) >> 8) & 0xFF), (uint8_t)((mrb_fixnum(color_val)) & 0xFF) }; return self; } static mrb_value element_rect_color_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; uint32_t color = ((uint32_t)element->color.r << 16) | ((uint32_t)element->color.g << 8) | ((uint32_t)element->color.b); return mrb_fixnum_value(color); } static mrb_value element_rect_equal(mrb_state *mrb, mrb_value self) { mrb_value other; mrb_get_args(mrb, "o", &other); if (!mrb_obj_is_kind_of(mrb, other, mrb_class_get(mrb, "ElementRect"))) return mrb_false_value(); uint64_t id_self = get_id_ElementRect(mrb, self); uint64_t id_other = get_id_ElementRect(mrb, other); return mrb_bool_value(id_self == id_other); } static mrb_value element_rect_inspect(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; std::string str = "#shape.x) + " height=" + std::format("{}", element->shape.y) + ">"; return mrb_str_new_cstr(mrb, str.c_str()); } static mrb_value element_rect_hash(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementRect(mrb, self); return mrb_fixnum_value(id); } static mrb_value element_rect_position_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; mrb_value pos_hash = mrb_hash_new(mrb); HASH_SET(pos_hash, x, mrb_float_value(mrb, element->position.x)); HASH_SET(pos_hash, y, mrb_float_value(mrb, element->position.y)); return pos_hash; } static mrb_value element_rect_position_set(mrb_state *mrb, mrb_value self) { mrb_value pos_hash; mrb_get_args(mrb, "H", &pos_hash); uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; HASH_FLOAT(pos_hash, x, element->position.x); HASH_FLOAT(pos_hash, y, element->position.y); return mrb_nil_value(); } static mrb_value element_rect_rotation_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; return mrb_float_value(mrb, element->rotation); } static mrb_value element_rect_rotation_set(mrb_state *mrb, mrb_value self) { mrb_float rotation; mrb_get_args(mrb, "f", &rotation); uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; element->rotation = rotation; return mrb_nil_value(); } static mrb_value element_rect_pivot_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; mrb_value pivot_hash = mrb_hash_new(mrb); HASH_SET(pivot_hash, x, mrb_float_value(mrb, element->pivot.x)); HASH_SET(pivot_hash, y, mrb_float_value(mrb, element->pivot.y)); return pivot_hash; } static mrb_value element_rect_pivot_set(mrb_state *mrb, mrb_value self) { mrb_value pivot_hash; mrb_get_args(mrb, "H", &pivot_hash); uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; HASH_FLOAT(pivot_hash, x, element->pivot.x); HASH_FLOAT(pivot_hash, y, element->pivot.y); return mrb_nil_value(); } static mrb_value element_rect_scale_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; mrb_value scale_hash = mrb_hash_new(mrb); HASH_SET(scale_hash, x, mrb_float_value(mrb, element->scale.x)); HASH_SET(scale_hash, y, mrb_float_value(mrb, element->scale.y)); return scale_hash; } static mrb_value element_rect_scale_set(mrb_state *mrb, mrb_value self) { mrb_value scale_hash; mrb_get_args(mrb, "H", &scale_hash); uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; HASH_FLOAT(scale_hash, x, element->scale.x); HASH_FLOAT(scale_hash, y, element->scale.y); return mrb_nil_value(); } static mrb_value element_rect_alpha_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; return mrb_float_value(mrb, element->alpha); } static mrb_value element_rect_alpha_set(mrb_state *mrb, mrb_value self) { mrb_float alpha; mrb_get_args(mrb, "f", &alpha); uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; element->alpha = alpha; return mrb_nil_value(); } static mrb_value element_rect_z_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; return mrb_float_value(mrb, element->z); } static mrb_value element_rect_z_set(mrb_state *mrb, mrb_value self) { mrb_float z; mrb_get_args(mrb, "f", &z); uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; element->z = z; return mrb_nil_value(); } static mrb_value element_rect_click_mode_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; std::string click_mode_str; switch (element->click_mode) { case ClickMode::PASS: click_mode_str = "pass"; break; case ClickMode::BLOCK: click_mode_str = "block"; break; case ClickMode::IGNORE: click_mode_str = "ignore"; break; } return mrb_symbol_value(mrb_intern_cstr(mrb, click_mode_str.c_str())); } static mrb_value element_rect_click_mode_set(mrb_state *mrb, mrb_value self) { mrb_sym click_mode_sym; mrb_get_args(mrb, "n", &click_mode_sym); uint64_t id = get_id_ElementRect(mrb, self); app::ERect *element = (app::ERect *)app::element_pool[id]; std::string click_mode = mrb_sym2name(mrb, click_mode_sym); if (click_mode == "pass") element->click_mode = ClickMode::PASS; else if (click_mode == "block") element->click_mode = ClickMode::BLOCK; else if (click_mode == "ignore") element->click_mode = ClickMode::IGNORE; return mrb_nil_value(); } static void ElementImage_free(mrb_state *mrb, void *ptr) { UNUSED(mrb); uint64_t id = ((Wrapper *)ptr)->id; app::element_pool.release(id); delete (Wrapper *)ptr; } static const struct mrb_data_type ElementImage_type = { "ElementImage", ElementImage_free }; 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(); 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(); } float x = 0, y = 0, z = 0, rotation = 0; float scale_x = 1, scale_y = 1, alpha = 1, pivot_x = 0.5, pivot_y = 0.5; mrb_sym click_mode_sym = sym_block; if (!mrb_nil_p(kwargs)) { mrb_value pos_hash = HASH_GET(kwargs, position); if (!mrb_nil_p(pos_hash)) { HASH_FLOAT(pos_hash, x, x); HASH_FLOAT(pos_hash, y, y); } mrb_value scale_hash = HASH_GET(kwargs, scale); if (!mrb_nil_p(scale_hash)) { HASH_FLOAT(scale_hash, x, scale_x); HASH_FLOAT(scale_hash, y, scale_y); } mrb_value pivot_hash = HASH_GET(kwargs, pivot); if (!mrb_nil_p(pivot_hash)) { HASH_FLOAT(pivot_hash, x, pivot_x); HASH_FLOAT(pivot_hash, y, pivot_y); } HASH_FLOAT(kwargs, z, z); HASH_FLOAT(kwargs, rotation, rotation); HASH_FLOAT(kwargs, alpha, alpha); mrb_value v = HASH_GET(kwargs, click_mode); if (!mrb_nil_p(v)) { click_mode_sym = mrb_symbol(v); } } uint64_t id = get_id_Animation(mrb, animation_val); app::EImage *element = new app::EImage(id); element->position = {x, y}; element->scale = {scale_x, scale_y}; element->rotation = rotation; element->pivot = {pivot_x, pivot_y}; element->alpha = alpha; element->z = z; std::string click_mode = mrb_sym2name(mrb, click_mode_sym); if (click_mode == "pass") element->click_mode = ClickMode::PASS; else if (click_mode == "block") element->click_mode = ClickMode::BLOCK; else if (click_mode == "ignore") element->click_mode = ClickMode::IGNORE; s->id = app::element_pool.acquire(element); app::element_pool.use(s->id); mrb_data_init(self, s, &ElementImage_type); return self; } inline uint64_t 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; mrb_get_args(mrb, "&", &block); uint64_t id = get_id_ElementImage(mrb, self); app::Element *element = app::element_pool[id]; element->on_click.set_proc(block); return self; } static mrb_value element_image_equal(mrb_state *mrb, mrb_value self) { mrb_value other; mrb_get_args(mrb, "o", &other); if (!mrb_obj_is_kind_of(mrb, other, mrb_class_get(mrb, "ElementImage"))) return mrb_false_value(); uint64_t id_self = get_id_ElementImage(mrb, self); uint64_t id_other = get_id_ElementImage(mrb, other); return mrb_bool_value(id_self == id_other); } static mrb_value element_image_inspect(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; std::string str = "#animation_id) + ">"; return mrb_str_new_cstr(mrb, str.c_str()); } static mrb_value element_image_hash(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementImage(mrb, self); return mrb_fixnum_value(id); } static mrb_value element_image_animation_set(mrb_state *mrb, mrb_value self) { mrb_value animation; mrb_get_args(mrb, "o", &animation); if (!mrb_obj_is_kind_of( mrb, animation, mrb_class_get(mrb, "Animation") )) { mrb_raise( mrb, mrb_class_get(mrb, "Exception"), "Expected an Animation object" ); return mrb_nil_value(); } uint64_t animation_id = get_id_Animation(mrb, animation); uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; animation_pool.use(animation_id); animation_pool.release(element->animation_id); element->animation_id = animation_id; return self; } static mrb_value element_image_animation_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; uint64_t animation_id = element->animation_id; if (animation_id == UINT64_MAX) return mrb_nil_value(); animation_pool.use(animation_id); return wrap(mrb, mrb_class_get(mrb, "Animation"), &Animation_type, animation_id); } static mrb_value element_image_position_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; mrb_value pos_hash = mrb_hash_new(mrb); HASH_SET(pos_hash, x, mrb_float_value(mrb, element->position.x)); HASH_SET(pos_hash, y, mrb_float_value(mrb, element->position.y)); return pos_hash; } static mrb_value element_image_position_set(mrb_state *mrb, mrb_value self) { mrb_value pos_hash; mrb_get_args(mrb, "H", &pos_hash); uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; HASH_FLOAT(pos_hash, x, element->position.x); HASH_FLOAT(pos_hash, y, element->position.y); return mrb_nil_value(); } static mrb_value element_image_rotation_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; return mrb_float_value(mrb, element->rotation); } static mrb_value element_image_rotation_set(mrb_state *mrb, mrb_value self) { mrb_float rotation; mrb_get_args(mrb, "f", &rotation); uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; element->rotation = rotation; return mrb_nil_value(); } static mrb_value element_image_pivot_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; mrb_value pivot_hash = mrb_hash_new(mrb); HASH_SET(pivot_hash, x, mrb_float_value(mrb, element->pivot.x)); HASH_SET(pivot_hash, y, mrb_float_value(mrb, element->pivot.y)); return pivot_hash; } static mrb_value element_image_pivot_set(mrb_state *mrb, mrb_value self) { mrb_value pivot_hash; mrb_get_args(mrb, "H", &pivot_hash); uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; HASH_FLOAT(pivot_hash, x, element->pivot.x); HASH_FLOAT(pivot_hash, y, element->pivot.y); return mrb_nil_value(); } static mrb_value element_image_scale_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; mrb_value scale_hash = mrb_hash_new(mrb); HASH_SET(scale_hash, x, mrb_float_value(mrb, element->scale.x)); HASH_SET(scale_hash, y, mrb_float_value(mrb, element->scale.y)); return scale_hash; } static mrb_value element_image_scale_set(mrb_state *mrb, mrb_value self) { mrb_value scale_hash; mrb_get_args(mrb, "H", &scale_hash); uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; HASH_FLOAT(scale_hash, x, element->scale.x); HASH_FLOAT(scale_hash, y, element->scale.y); return mrb_nil_value(); } static mrb_value element_image_alpha_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; return mrb_float_value(mrb, element->alpha); } static mrb_value element_image_alpha_set(mrb_state *mrb, mrb_value self) { mrb_float alpha; mrb_get_args(mrb, "f", &alpha); uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; element->alpha = alpha; return mrb_nil_value(); } static mrb_value element_image_z_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; return mrb_float_value(mrb, element->z); } static mrb_value element_image_z_set(mrb_state *mrb, mrb_value self) { mrb_float z; mrb_get_args(mrb, "f", &z); uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; element->z = z; return mrb_nil_value(); } static mrb_value element_image_click_mode_get(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; std::string click_mode_str; switch (element->click_mode) { case ClickMode::PASS: click_mode_str = "pass"; break; case ClickMode::BLOCK: click_mode_str = "block"; break; case ClickMode::IGNORE: click_mode_str = "ignore"; break; } return mrb_symbol_value(mrb_intern_cstr(mrb, click_mode_str.c_str())); } static mrb_value element_image_click_mode_set(mrb_state *mrb, mrb_value self) { mrb_sym click_mode_sym; mrb_get_args(mrb, "n", &click_mode_sym); uint64_t id = get_id_ElementImage(mrb, self); app::EImage *element = (app::EImage *)app::element_pool[id]; std::string click_mode = mrb_sym2name(mrb, click_mode_sym); if (click_mode == "pass") element->click_mode = ClickMode::PASS; else if (click_mode == "block") element->click_mode = ClickMode::BLOCK; else if (click_mode == "ignore") element->click_mode = ClickMode::IGNORE; return mrb_nil_value(); } static void Scene_free(mrb_state *mrb, void *ptr) { UNUSED(mrb); uint64_t 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 uint64_t 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; mrb_get_args(mrb, "o", &element_val); 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")) && !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" ); return mrb_nil_value(); } uint64_t id = get_id_Scene(mrb, self); app::Scene *scene = app::scene_pool[id]; uint64_t 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")) ) { element_id = get_id_ElementRect(mrb, element_val); } 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" ); return mrb_nil_value(); } scene->add_element(element_id); return self; } static mrb_value scene_delete_element(mrb_state *mrb, mrb_value self) { mrb_value element_val; mrb_get_args(mrb, "o", &element_val); 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")) && !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" ); return mrb_nil_value(); } uint64_t id = get_id_Scene(mrb, self); app::Scene *scene = app::scene_pool[id]; uint64_t 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")) ) { element_id = get_id_ElementRect(mrb, element_val); } 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" ); return mrb_nil_value(); } scene->delete_element(element_id); return self; } static mrb_value scene_on_update(mrb_state *mrb, mrb_value self) { mrb_value block; mrb_get_args(mrb, "&", &block); uint64_t id = get_id_Scene(mrb, self); app::Scene *scene = app::scene_pool[id]; scene->update.set_proc(block); 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 position = {x, y}; uint64_t id = get_id_Scene(mrb, self); app::Scene *scene = app::scene_pool[id]; std::vector 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]; app::element_pool.use(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 scene_elements(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_Scene(mrb, self); app::Scene *scene = app::scene_pool[id]; std::vector element_ids = scene->element_ids; 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]; app::element_pool.use(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 scene_equal(mrb_state *mrb, mrb_value self) { mrb_value other; mrb_get_args(mrb, "o", &other); if (!mrb_obj_is_kind_of(mrb, other, mrb_class_get(mrb, "Scene"))) return mrb_false_value(); uint64_t id_self = get_id_Scene(mrb, self); uint64_t id_other = get_id_Scene(mrb, other); return mrb_bool_value(id_self == id_other); } static mrb_value scene_inspect(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_Scene(mrb, self); return mrb_str_new_cstr(mrb, ("#").c_str()); } static mrb_value scene_hash(mrb_state *mrb, mrb_value self) { uint64_t id = get_id_Scene(mrb, self); return mrb_fixnum_value(id); } static mrb_value app_run(mrb_state *mrb, mrb_value) { mrb_int width, height; mrb_value options_hash; char *title = nullptr; mrb_get_args(mrb, "iiz|H", &width, &height, &title, &options_hash); app_ = new app::App({(float)width, (float)height}, title); float fps = 60; if (!mrb_nil_p(options_hash)) HASH_FLOAT(options_hash, fps, fps); app_->set_fps(fps); return mrb_nil_value(); } static mrb_value app_fps_get(mrb_state *mrb, mrb_value) { return mrb_float_value(mrb, app_->get_fps()); } static mrb_value app_fps_set(mrb_state *mrb, mrb_value) { mrb_float fps; mrb_get_args(mrb, "f", &fps); app_->set_fps(fps); return mrb_nil_value(); } static mrb_value app_start(mrb_state *mrb, mrb_value) { mrb_value scene_val; mrb_get_args(mrb, "o", &scene_val); if (!mrb_obj_is_kind_of(mrb, scene_val, mrb_class_get(mrb, "Scene"))) { mrb_raise(mrb, mrb_class_get(mrb, "Exception"), "Expected a Scene object"); return mrb_nil_value(); } uint64_t id = get_id_Scene(mrb, scene_val); app_->switch_to_scene(id); app_->loop(); return mrb_nil_value(); } static mrb_value app_switch_to(mrb_state *mrb, mrb_value) { mrb_value scene_val; mrb_get_args(mrb, "o", &scene_val); if (!mrb_obj_is_kind_of(mrb, scene_val, mrb_class_get(mrb, "Scene"))) { mrb_raise(mrb, mrb_class_get(mrb, "Exception"), "Expected a Scene object"); return mrb_nil_value(); } uint64_t id = get_id_Scene(mrb, scene_val); app_->switch_to_scene(id); return mrb_nil_value(); } static mrb_value app_localize(mrb_state *mrb, mrb_value) { mrb_sym lang_sym, key_sym; char *text; mrb_get_args(mrb, "nnz", &lang_sym, &key_sym, &text); auto lang = Localization::lang_from_sym(mrb, lang_sym); const char *key_name = mrb_sym2name(mrb, key_sym); auto it = Localization::localization_key_map.find(key_name); Localization::Key key_id; if (it == Localization::localization_key_map.end()) { key_id = (Localization::Key)Localization::localization_key_map.size(); Localization::localization_key_map[key_name] = key_id; } else { key_id = it->second; } Localization::set(lang, key_id, text); return mrb_nil_value(); } static mrb_value app_language_set(mrb_state *mrb, mrb_value) { mrb_sym lang_sym; mrb_get_args(mrb, "n", &lang_sym); Localization::current_language = Localization::lang_from_sym(mrb, lang_sym); return mrb_nil_value(); } static mrb_value app_language_get(mrb_state *mrb, mrb_value) { return mrb_symbol_value(Localization::lang_to_sym(mrb, Localization::current_language)); } static mrb_value app_mouse_position(mrb_state *mrb, mrb_value) { Vec2 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; } static mrb_value app_is_down(mrb_state *mrb, mrb_value) { mrb_sym key_sym; mrb_get_args(mrb, "n", &key_sym); std::string key_name = mrb_sym2name(mrb, key_sym); Key key = get_key(key_name); return mrb_bool_value(app_->down_keys[key]); } static mrb_value app_is_pressed(mrb_state *mrb, mrb_value) { mrb_sym key_sym; mrb_get_args(mrb, "n", &key_sym); std::string key_name = mrb_sym2name(mrb, key_sym); Key key = get_key(key_name); for (Key pressed_key : app_->pressed_keys) if (pressed_key == key) return mrb_bool_value(true); return mrb_bool_value(false); } static mrb_value app_is_released(mrb_state *mrb, mrb_value) { mrb_sym key_sym; mrb_get_args(mrb, "n", &key_sym); std::string key_name = mrb_sym2name(mrb, key_sym); Key key = get_key(key_name); for (Key released_key : app_->released_keys) if (released_key == key) return mrb_bool_value(true); return mrb_bool_value(false); } static mrb_value app_map_key(mrb_state *mrb, mrb_value) { mrb_sym key_sym; mrb_sym action_sym; mrb_get_args(mrb, "nn", &key_sym, &action_sym); std::string key_name = mrb_sym2name(mrb, key_sym); std::string action_name = mrb_sym2name(mrb, action_sym); set_action_mapping(action_name, key_name); return mrb_nil_value(); } static mrb_value app_scroll(mrb_state *mrb, mrb_value) { Vec2 scroll = app_->scroll; mrb_value result = mrb_hash_new(mrb); HASH_SET(result, x, mrb_float_value(mrb, scroll.x)); HASH_SET(result, y, mrb_float_value(mrb, scroll.y)); return result; } static mrb_value app_text_input(mrb_state *mrb, mrb_value) { return mrb_str_new_cstr(mrb, app_->text.c_str()); } static mrb_value app_exit(mrb_state *, mrb_value) { app_->exit(); return mrb_nil_value(); } inline void setup() { DEF_CLASS(Font, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1)); ADD_METHOD(Font, "==", font_equal, MRB_ARGS_REQ(1)); ADD_METHOD(Font, "eql?", font_equal, MRB_ARGS_REQ(1)); ADD_METHOD(Font, "hash", font_hash, MRB_ARGS_NONE()); DEF_CLASS(Image, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1)); ADD_METHOD(Image, "==", image_equal, MRB_ARGS_REQ(1)); ADD_METHOD(Image, "eql?", image_equal, MRB_ARGS_REQ(1)); ADD_METHOD(Image, "hash", image_hash, MRB_ARGS_NONE()); ADD_METHOD(Image, "width", image_width, MRB_ARGS_NONE()); ADD_METHOD(Image, "height", image_height, MRB_ARGS_NONE()); DEF_CLASS(Animation, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1)); ADD_METHOD(Animation, "==", animation_equal, MRB_ARGS_REQ(1)); ADD_METHOD(Animation, "eql?", animation_equal, MRB_ARGS_REQ(1)); ADD_METHOD(Animation, "hash", animation_hash, MRB_ARGS_NONE()); ADD_METHOD(Animation, "fps=", animation_fps_set, MRB_ARGS_REQ(1)); ADD_METHOD(Animation, "fps", animation_fps_get, MRB_ARGS_NONE()); ADD_METHOD(Animation, "frames=", animation_frames_set, MRB_ARGS_REQ(1)); ADD_METHOD(Animation, "frames", animation_frames_get, MRB_ARGS_NONE()); DEF_CLASS(ElementText, MRB_ARGS_REQ(3) | MRB_ARGS_OPT(2)); ADD_METHOD(ElementText, "==", element_text_equal, MRB_ARGS_REQ(1)); ADD_METHOD(ElementText, "eql?", element_text_equal, MRB_ARGS_REQ(1)); ADD_METHOD(ElementText, "inspect", element_text_inspect, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "hash", element_text_hash, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "on_click", element_text_on_click, MRB_ARGS_BLOCK()); ADD_METHOD(ElementText, "to_s", element_text_to_s, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "key=", element_text_key_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementText, "key", element_text_key_get, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "color=", element_text_color_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementText, "color", element_text_color_get, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "font=", element_text_font_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementText, "font", element_text_font_get, MRB_ARGS_NONE()); #warning "Make text params a proper class instead of using a hash for text params" ADD_METHOD(ElementText, "params", element_text_params, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "params!", element_text_params_load, MRB_ARGS_NONE()); #warning "Make vector a proper class instead of using a hash for vectors" ADD_METHOD(ElementText, "position=", element_text_position_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementText, "position", element_text_position_get, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "scale=", element_text_scale_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementText, "scale", element_text_scale_get, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "rotation=", element_text_rotation_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementText, "rotation", element_text_rotation_get, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "pivot=", element_text_pivot_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementText, "pivot", element_text_pivot_get, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "alpha=", element_text_alpha_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementText, "alpha", element_text_alpha_get, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "z=", element_text_z_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementText, "z", element_text_z_get, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "click_mode=", element_text_click_mode_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementText, "click_mode", element_text_click_mode_get, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "width", element_text_width, MRB_ARGS_NONE()); ADD_METHOD(ElementText, "height", element_text_height, MRB_ARGS_NONE()); DEF_CLASS(ElementRect, MRB_ARGS_REQ(3) | MRB_ARGS_OPT(1)); ADD_METHOD(ElementRect, "==", element_rect_equal, MRB_ARGS_REQ(1)); ADD_METHOD(ElementRect, "eql?", element_rect_equal, MRB_ARGS_REQ(1)); ADD_METHOD(ElementRect, "inspect", element_rect_inspect, MRB_ARGS_NONE()); ADD_METHOD(ElementRect, "to_s", element_rect_inspect, MRB_ARGS_NONE()); ADD_METHOD(ElementRect, "hash", element_rect_hash, MRB_ARGS_NONE()); ADD_METHOD(ElementRect, "on_click", element_rect_on_click, MRB_ARGS_BLOCK()); ADD_METHOD(ElementRect, "width=", element_rect_width_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementRect, "width", element_rect_width_get, MRB_ARGS_NONE()); ADD_METHOD(ElementRect, "height=", element_rect_height_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementRect, "height", element_rect_height_get, MRB_ARGS_NONE()); 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, "position=", element_rect_position_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementRect, "position", element_rect_position_get, MRB_ARGS_NONE()); ADD_METHOD(ElementRect, "scale=", element_rect_scale_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementRect, "scale", element_rect_scale_get, MRB_ARGS_NONE()); ADD_METHOD(ElementRect, "rotation=", element_rect_rotation_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementRect, "rotation", element_rect_rotation_get, MRB_ARGS_NONE()); ADD_METHOD(ElementRect, "pivot=", element_rect_pivot_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementRect, "pivot", element_rect_pivot_get, MRB_ARGS_NONE()); ADD_METHOD(ElementRect, "alpha=", element_rect_alpha_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementRect, "alpha", element_rect_alpha_get, MRB_ARGS_NONE()); ADD_METHOD(ElementRect, "z=", element_rect_z_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementRect, "z", element_rect_z_get, MRB_ARGS_NONE()); ADD_METHOD(ElementRect, "click_mode=", element_rect_click_mode_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementRect, "click_mode", element_rect_click_mode_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, "==", element_image_equal, MRB_ARGS_REQ(1)); ADD_METHOD(ElementImage, "eql?", element_image_equal, MRB_ARGS_REQ(1)); ADD_METHOD(ElementImage, "inspect", element_image_inspect, MRB_ARGS_NONE()); ADD_METHOD(ElementImage, "to_s", element_image_inspect, MRB_ARGS_NONE()); ADD_METHOD(ElementImage, "hash", element_image_hash, MRB_ARGS_NONE()); ADD_METHOD(ElementImage, "animation=", element_image_animation_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementImage, "animation", element_image_animation_get, MRB_ARGS_NONE()); ADD_METHOD(ElementImage, "position=", element_image_position_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementImage, "position", element_image_position_get, MRB_ARGS_NONE()); ADD_METHOD(ElementImage, "scale=", element_image_scale_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementImage, "scale", element_image_scale_get, MRB_ARGS_NONE()); ADD_METHOD(ElementImage, "rotation=", element_image_rotation_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementImage, "rotation", element_image_rotation_get, MRB_ARGS_NONE()); ADD_METHOD(ElementImage, "pivot=", element_image_pivot_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementImage, "pivot", element_image_pivot_get, MRB_ARGS_NONE()); ADD_METHOD(ElementImage, "alpha=", element_image_alpha_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementImage, "alpha", element_image_alpha_get, MRB_ARGS_NONE()); ADD_METHOD(ElementImage, "z=", element_image_z_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementImage, "z", element_image_z_get, MRB_ARGS_NONE()); ADD_METHOD(ElementImage, "click_mode=", element_image_click_mode_set, MRB_ARGS_REQ(1)); ADD_METHOD(ElementImage, "click_mode", element_image_click_mode_get, MRB_ARGS_NONE()); DEF_CLASS(Scene, MRB_ARGS_NONE()); ADD_METHOD(Scene, "==", scene_equal, MRB_ARGS_REQ(1)); ADD_METHOD(Scene, "eql?", scene_equal, MRB_ARGS_REQ(1)); ADD_METHOD(Scene, "inspect", scene_inspect, MRB_ARGS_NONE()); ADD_METHOD(Scene, "to_s", scene_inspect, MRB_ARGS_NONE()); ADD_METHOD(Scene, "hash", scene_hash, MRB_ARGS_NONE()); ADD_METHOD(Scene, "<<", scene_add_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, "on_update", scene_on_update, MRB_ARGS_BLOCK()); ADD_METHOD(Scene, "elements_at", scene_elements_at, MRB_ARGS_REQ(1)); ADD_METHOD(Scene, "elements", scene_elements, MRB_ARGS_NONE()); DEF_MODULE(App); ADD_MODULE_METHOD(App, "run", app_run, MRB_ARGS_REQ(3) | MRB_ARGS_OPT(1)); ADD_MODULE_METHOD(App, "start", app_start, MRB_ARGS_REQ(1)); ADD_MODULE_METHOD(App, "switch_to", app_switch_to, MRB_ARGS_REQ(1)); ADD_MODULE_METHOD(App, "fps=", app_fps_set, MRB_ARGS_REQ(1)); ADD_MODULE_METHOD(App, "fps", app_fps_get, MRB_ARGS_NONE()); 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_get, MRB_ARGS_NONE()); ADD_MODULE_METHOD(App, "mouse_position", app_mouse_position, MRB_ARGS_NONE()); ADD_MODULE_METHOD(App, "down?", app_is_down, MRB_ARGS_REQ(1)); ADD_MODULE_METHOD(App, "pressed?", app_is_pressed, MRB_ARGS_REQ(1)); ADD_MODULE_METHOD(App, "released?", app_is_released, MRB_ARGS_REQ(1)); ADD_MODULE_METHOD(App, "map_key", app_map_key, MRB_ARGS_REQ(2)); ADD_MODULE_METHOD(App, "scroll", app_scroll, MRB_ARGS_NONE()); ADD_MODULE_METHOD(App, "text_input", app_text_input, MRB_ARGS_NONE()); ADD_MODULE_METHOD(App, "exit!", app_exit, MRB_ARGS_NONE()); } } // namespace definitions #endif