#include "app/app.h" #include "bindings/definitions.h" namespace { void Scene_free(mrb_state *mrb, void *ptr) { UNUSED(mrb); uint64_t id = ((Wrapper *)ptr)->id; app::scene_pool.release(id); delete (Wrapper *)ptr; } const struct mrb_data_type Scene_type = {"Scene", Scene_free}; mrb_value Scene_init(mrb_state *mrb, mrb_value self) { 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; } 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, definitions::bindings.ElementText.cls) && !mrb_obj_is_kind_of(mrb, element_val, definitions::bindings.ElementRect.cls) && !mrb_obj_is_kind_of(mrb, element_val, definitions::bindings.ElementImage.cls) && !mrb_obj_is_kind_of(mrb, element_val, definitions::bindings.ElementScript.cls) ) { mrb_raise( mrb, mrb_class_get(mrb, "Exception"), "Expected an ElementText, ElementRect, or ElementImage object" ); return mrb_nil_value(); } Wrapper *wrapper = (Wrapper *)DATA_PTR(self); app::Scene *scene = app::scene_pool[wrapper->id]; Wrapper *element_wrapper = (Wrapper *)DATA_PTR(element_val); scene->add_element(element_wrapper->id); return self; } 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, definitions::bindings.ElementText.cls) && !mrb_obj_is_kind_of(mrb, element_val, definitions::bindings.ElementRect.cls) && !mrb_obj_is_kind_of(mrb, element_val, definitions::bindings.ElementImage.cls) && !mrb_obj_is_kind_of(mrb, element_val, definitions::bindings.ElementScript.cls) ) { mrb_raise( mrb, mrb_class_get(mrb, "Exception"), "Expected an ElementText, ElementRect, or ElementImage object" ); return mrb_nil_value(); } Wrapper *wrapper = (Wrapper *)DATA_PTR(self); app::Scene *scene = app::scene_pool[wrapper->id]; Wrapper *element_wrapper = (Wrapper *)DATA_PTR(element_val); scene->delete_element(element_wrapper->id); return self; } mrb_value scene_on_update(mrb_state *mrb, mrb_value self) { mrb_value block; mrb_get_args(mrb, "&", &block); Wrapper *wrapper = (Wrapper *)DATA_PTR(self); app::Scene *scene = app::scene_pool[wrapper->id]; scene->update.set_proc(block); return self; } mrb_value scene_elements_at(mrb_state *mrb, mrb_value self) { mrb_value position_val; mrb_get_args(mrb, "o", &position_val); float x = 0, y = 0; HASH_FLOAT(position_val, x, x); HASH_FLOAT(position_val, y, y); Vec2 position = {x, y}; Wrapper *wrapper = (Wrapper *)DATA_PTR(self); app::Scene *scene = app::scene_pool[wrapper->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); mrb_value obj; switch (element->type) { case Type::TEXT: obj = definitions::wrap( definitions::bindings.ElementText, element_id ); break; case Type::RECT: obj = definitions::wrap( definitions::bindings.ElementRect, element_id ); break; case Type::IMAGE: obj = definitions::wrap( definitions::bindings.ElementImage, element_id ); mrb_ary_push(mrb, result, obj); break; case Type::SCRIPT: obj = definitions::wrap( definitions::bindings.ElementScript, element_id ); break; default: continue; } mrb_ary_push(mrb, result, obj); } return result; } mrb_value scene_elements(mrb_state *mrb, mrb_value self) { Wrapper *wrapper = (Wrapper *)DATA_PTR(self); app::Scene *scene = app::scene_pool[wrapper->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); mrb_value obj; switch (element->type) { case Type::TEXT: obj = definitions::wrap( definitions::bindings.ElementText, element_id ); break; case Type::RECT: obj = definitions::wrap( definitions::bindings.ElementRect, element_id ); break; case Type::IMAGE: obj = definitions::wrap( definitions::bindings.ElementImage, element_id ); mrb_ary_push(mrb, result, obj); break; case Type::SCRIPT: obj = definitions::wrap( definitions::bindings.ElementScript, element_id ); break; default: continue; } mrb_ary_push(mrb, result, obj); } return result; } 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, definitions::bindings.Scene.cls)) return mrb_false_value(); Wrapper *self_wrapper = (Wrapper *)DATA_PTR(self); uint64_t id_self = self_wrapper->id; Wrapper *other_wrapper = (Wrapper *)DATA_PTR(other); uint64_t id_other = other_wrapper->id; return mrb_bool_value(id_self == id_other); } mrb_value scene_inspect(mrb_state *mrb, mrb_value self) { Wrapper *wrapper = (Wrapper *)DATA_PTR(self); uint64_t id = wrapper->id; return mrb_str_new_cstr(mrb, ("#").c_str()); } mrb_value scene_hash(mrb_state *, mrb_value self) { Wrapper *wrapper = (Wrapper *)DATA_PTR(self); uint64_t id = wrapper->id; return mrb_fixnum_value(id); } } // namespace namespace definitions { void register_scene() { 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, "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()); bindings.Scene = {Scene_class, &Scene_type}; } } // namespace definitions