240 lines
6.8 KiB
C++
240 lines
6.8 KiB
C++
#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<float> position = {x, y};
|
|
|
|
Wrapper *wrapper = (Wrapper *)DATA_PTR(self);
|
|
app::Scene *scene = app::scene_pool[wrapper->id];
|
|
|
|
std::vector<uint64_t> element_ids = scene->elements_at(position);
|
|
|
|
mrb_value result = mrb_ary_new_capa(mrb, element_ids.size());
|
|
for (uint64_t element_id : element_ids) {
|
|
app::Element *element = app::element_pool[element_id];
|
|
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<uint64_t> 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, ("#<Scene:" + std::to_string(id) + ">").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
|