Fix major incorrect usage of mrb class definitions causing segfaults
This commit is contained in:
+215
-49
@@ -27,17 +27,63 @@ DEF_RB(
|
||||
})
|
||||
)
|
||||
|
||||
DEF_RB(
|
||||
Image,
|
||||
({ window.unload_image(id); }),
|
||||
({
|
||||
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);
|
||||
#warning "Fix lifetimes for images/fonts right now they'll always exist"
|
||||
})
|
||||
)
|
||||
|
||||
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);
|
||||
|
||||
float fps = 1.0f;
|
||||
if (!mrb_nil_p(kwargs))
|
||||
HASH_FLOAT(kwargs, fps, fps);
|
||||
|
||||
std::vector<int> 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);
|
||||
window.use_image(frame_id);
|
||||
frame_ids.push_back(frame_id);
|
||||
}
|
||||
|
||||
Animation *animation = new Animation{frame_ids, fps, true};
|
||||
s->id = animation_pool.acquire(animation);
|
||||
animation_pool.use(s->id);
|
||||
})
|
||||
)
|
||||
|
||||
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);
|
||||
}
|
||||
app::element_pool.release(id);
|
||||
}),
|
||||
({
|
||||
mrb_value font_val;
|
||||
@@ -48,7 +94,7 @@ DEF_RB(
|
||||
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");
|
||||
mrb_raise(mrb, mrb_class_get(mrb, "Exception"), "Expected a Font object");
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
@@ -67,29 +113,32 @@ DEF_RB(
|
||||
|
||||
Vec2<float> position = {x, y};
|
||||
|
||||
int id = get_id(font_val);
|
||||
int id = get_id_Font(mrb, font_val);
|
||||
window.use_font(id);
|
||||
|
||||
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);
|
||||
app::element_pool.use(s->id);
|
||||
})
|
||||
)
|
||||
|
||||
static mrb_value element_text_on_click(mrb_state *mrb, mrb_value self) {
|
||||
mrb_value block;
|
||||
mrb_get_args(mrb, "&", &block);
|
||||
int id = get_id_ElementText(mrb, self);
|
||||
app::Element *element = app::element_pool[id];
|
||||
element->on_click.set_proc(block);
|
||||
return self;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
app::element_pool.release(id);
|
||||
}),
|
||||
({
|
||||
mrb_value shape_val;
|
||||
@@ -119,18 +168,27 @@ DEF_RB(
|
||||
(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);
|
||||
app::element_pool.use(s->id);
|
||||
})
|
||||
)
|
||||
|
||||
static mrb_value element_rect_on_click(mrb_state *mrb, mrb_value self) {
|
||||
mrb_value block;
|
||||
mrb_get_args(mrb, "&", &block);
|
||||
int 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_color_set(mrb_state *mrb, mrb_value self) {
|
||||
mrb_value color_val;
|
||||
mrb_get_args(mrb, "o", &color_val);
|
||||
int id = get_id(self);
|
||||
int id = get_id_ElementRect(mrb, self);
|
||||
app::ERect *element = (app::ERect *)app::element_pool[id];
|
||||
element->color = {
|
||||
(uint8_t)((mrb_fixnum(color_val) >> 24) & 0xFF),
|
||||
@@ -141,17 +199,8 @@ static mrb_value element_rect_color_set(mrb_state *mrb, mrb_value self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
static mrb_value element_on_click(mrb_state *mrb, mrb_value self) {
|
||||
mrb_value block;
|
||||
mrb_get_args(mrb, "&", &block);
|
||||
int id = get_id(self);
|
||||
app::Element *element = app::element_pool[id];
|
||||
element->on_click.set_proc(block);
|
||||
return self;
|
||||
}
|
||||
|
||||
static mrb_value element_rect_color_get(mrb_state *, mrb_value self) {
|
||||
int id = get_id(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)
|
||||
@@ -160,16 +209,65 @@ static mrb_value element_rect_color_get(mrb_state *, mrb_value self) {
|
||||
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);
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
int id = get_id_Animation(mrb, animation_val);
|
||||
Animation *animation = animation_pool[id];
|
||||
|
||||
app::EImage *element = new app::EImage(*animation);
|
||||
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);
|
||||
})
|
||||
)
|
||||
|
||||
static mrb_value element_image_on_click(mrb_state *mrb, mrb_value self) {
|
||||
mrb_value block;
|
||||
mrb_get_args(mrb, "&", &block);
|
||||
int id = get_id_ElementImage(mrb, self);
|
||||
app::Element *element = app::element_pool[id];
|
||||
element->on_click.set_proc(block);
|
||||
return self;
|
||||
}
|
||||
|
||||
DEF_RB(
|
||||
Scene,
|
||||
({
|
||||
app::Scene *scene = app::scene_pool[id];
|
||||
if (scene != nullptr)
|
||||
scene->unused = true;
|
||||
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);
|
||||
})
|
||||
)
|
||||
|
||||
@@ -180,23 +278,75 @@ static mrb_value scene_add_element(mrb_state *mrb, mrb_value self) {
|
||||
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(Ruby::mrb, "Exception"), "Expected an ElementText or ElementRect object");
|
||||
mrb_raise(mrb, mrb_class_get(mrb, "Exception"), "Expected an ElementText, ElementRect, or ElementImage object");
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
int id = get_id(self);
|
||||
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"))) {
|
||||
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();
|
||||
}
|
||||
|
||||
int id = get_id_Scene(mrb, 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"))
|
||||
|| mrb_obj_is_kind_of(mrb, element_val, mrb_class_get(mrb, "ElementRect"))
|
||||
) {
|
||||
element_id = get_id(element_val);
|
||||
scene->add_element(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);
|
||||
|
||||
int id = get_id_Scene(mrb, self);
|
||||
app::Scene *scene = app::scene_pool[id];
|
||||
scene->update.set_proc(block);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -223,12 +373,13 @@ static mrb_value app_start(mrb_state *mrb, mrb_value) {
|
||||
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(Ruby::mrb, "Exception"), "Expected a Scene object");
|
||||
mrb_raise(mrb, mrb_class_get(mrb, "Exception"), "Expected a Scene object");
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
int id = get_id(scene_val);
|
||||
int id = get_id_Scene(mrb, scene_val);
|
||||
app_->switch_to_scene(id);
|
||||
|
||||
app_->loop();
|
||||
|
||||
return mrb_nil_value();
|
||||
@@ -239,11 +390,11 @@ static mrb_value app_switch_to(mrb_state *mrb, mrb_value) {
|
||||
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(Ruby::mrb, "Exception"), "Expected a Scene object");
|
||||
mrb_raise(mrb, mrb_class_get(mrb, "Exception"), "Expected a Scene object");
|
||||
return mrb_nil_value();
|
||||
}
|
||||
|
||||
int id = get_id(scene_val);
|
||||
int id = get_id_Scene(mrb, scene_val);
|
||||
app_->switch_to_scene(id);
|
||||
|
||||
return mrb_nil_value();
|
||||
@@ -284,11 +435,15 @@ static mrb_value app_language_set(mrb_state *mrb, mrb_value) {
|
||||
inline void setup() {
|
||||
DEF_CLASS(Font, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1));
|
||||
|
||||
DEF_CLASS(Image, MRB_ARGS_REQ(1) | MRB_ARGS_OPT(1));
|
||||
|
||||
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_on_click,
|
||||
element_text_on_click,
|
||||
MRB_ARGS_BLOCK()
|
||||
);
|
||||
|
||||
@@ -296,7 +451,7 @@ inline void setup() {
|
||||
ADD_METHOD(
|
||||
ElementRect,
|
||||
"on_click",
|
||||
element_on_click,
|
||||
element_rect_on_click,
|
||||
MRB_ARGS_BLOCK()
|
||||
);
|
||||
ADD_METHOD(
|
||||
@@ -312,8 +467,19 @@ inline void setup() {
|
||||
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()
|
||||
);
|
||||
|
||||
DEF_CLASS(Scene, 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());
|
||||
|
||||
DEF_MODULE(App);
|
||||
ADD_MODULE_METHOD(App, "run", app_run, MRB_ARGS_REQ(3));
|
||||
|
||||
+23
-10
@@ -12,8 +12,12 @@
|
||||
#define HASH_FLOAT(h, key, out) \
|
||||
do { \
|
||||
mrb_value v = HASH_GET(h, key); \
|
||||
if (mrb_fixnum_p(v)) \
|
||||
if (mrb_float_p(v)) \
|
||||
out = mrb_float(v); \
|
||||
else if (mrb_fixnum_p(v)) \
|
||||
out = (float)mrb_fixnum(v); \
|
||||
else \
|
||||
out = 0; \
|
||||
} while (0)
|
||||
|
||||
#define HASH_BOOL(h, key, out) \
|
||||
@@ -40,11 +44,19 @@ struct Wrapper {
|
||||
}; \
|
||||
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; \
|
||||
DATA_PTR(self) = s; \
|
||||
DATA_TYPE(self) = &NAME##_type; \
|
||||
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) \
|
||||
@@ -52,6 +64,7 @@ struct Wrapper {
|
||||
|
||||
#define DEF_CLASS(NAME, ARGS) \
|
||||
RClass *NAME##_class = mrb_define_class(Ruby::mrb, #NAME, Ruby::mrb->object_class); \
|
||||
MRB_SET_INSTANCE_TT(NAME##_class, MRB_TT_CDATA); \
|
||||
ADD_METHOD(NAME, "initialize", NAME##_init, ARGS);
|
||||
|
||||
#define DEF_MODULE(NAME) \
|
||||
@@ -60,10 +73,6 @@ struct Wrapper {
|
||||
#define ADD_MODULE_METHOD(MODULE, METHOD, FUNC, ARGS) \
|
||||
mrb_define_class_method(Ruby::mrb, MODULE##_module, METHOD, FUNC, ARGS);
|
||||
|
||||
inline int get_id(mrb_value self) {
|
||||
return ((Wrapper *)DATA_PTR(self))->id;
|
||||
}
|
||||
|
||||
namespace Ruby {
|
||||
inline mrb_state *mrb = mrb_open();
|
||||
|
||||
@@ -71,7 +80,7 @@ struct Block {
|
||||
mrb_value proc;
|
||||
|
||||
Block(mrb_value proc) : proc(proc) {
|
||||
mrb_gc_register(mrb, proc);
|
||||
mrb_gc_protect(mrb, proc);
|
||||
}
|
||||
|
||||
Block() : proc(mrb_nil_value()) {}
|
||||
@@ -81,7 +90,7 @@ struct Block {
|
||||
mrb_gc_unregister(mrb, proc);
|
||||
proc = new_proc;
|
||||
if (!mrb_nil_p(proc))
|
||||
mrb_gc_register(mrb, proc);
|
||||
mrb_gc_protect(mrb, proc);
|
||||
}
|
||||
|
||||
Block(const Block &) = delete;
|
||||
@@ -90,7 +99,8 @@ struct Block {
|
||||
mrb_value call(int argc = 0, mrb_value *argv = nullptr) const {
|
||||
if (mrb_nil_p(proc))
|
||||
return mrb_nil_value();
|
||||
return mrb_funcall(mrb, proc, "call", argc, argv);
|
||||
mrb_value result = mrb_funcall_argv(mrb, proc, mrb_intern_cstr(mrb, "call"), argc, argv);
|
||||
return result;
|
||||
}
|
||||
|
||||
~Block() {
|
||||
@@ -110,7 +120,10 @@ DEF_SYM(bold)
|
||||
DEF_SYM(italic)
|
||||
DEF_SYM(underline)
|
||||
DEF_SYM(position)
|
||||
DEF_SYM(alpha)
|
||||
DEF_SYM(fps)
|
||||
DEF_SYM(click_through)
|
||||
DEF_SYM(call)
|
||||
DEF_SYM(x)
|
||||
DEF_SYM(y)
|
||||
DEF_SYM(w)
|
||||
|
||||
Reference in New Issue
Block a user