Refractor and cleanup binding logic
This commit is contained in:
@@ -9,3 +9,4 @@ AllowShortFunctionsOnASingleLine: Empty
|
|||||||
AlignAfterOpenBracket: BlockIndent
|
AlignAfterOpenBracket: BlockIndent
|
||||||
BinPackArguments: false
|
BinPackArguments: false
|
||||||
AllowAllArgumentsOnNextLine: false
|
AllowAllArgumentsOnNextLine: false
|
||||||
|
BreakBeforeBinaryOperators: NonAssignment
|
||||||
|
|||||||
@@ -240,4 +240,6 @@ struct App {
|
|||||||
};
|
};
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
|
||||||
|
inline app::App *app_ = nullptr;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -0,0 +1,327 @@
|
|||||||
|
#ifndef DEFINITIONS_H
|
||||||
|
#define DEFINITIONS_H
|
||||||
|
|
||||||
|
#include "app/app.h"
|
||||||
|
|
||||||
|
namespace definitions {
|
||||||
|
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<float> 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<float> position = {x, y};
|
||||||
|
Vec2<float> 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);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
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);
|
||||||
|
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),
|
||||||
|
(uint8_t)((mrb_fixnum(color_val) >> 8) & 0xFF),
|
||||||
|
(uint8_t)(mrb_fixnum(color_val) & 0xFF)
|
||||||
|
};
|
||||||
|
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);
|
||||||
|
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)
|
||||||
|
| (uint32_t)element->color.a;
|
||||||
|
return mrb_fixnum_value(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
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_raise(mrb, mrb_class_get(Ruby::mrb, "Exception"), "Expected an ElementText or ElementRect object");
|
||||||
|
return mrb_nil_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
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"))
|
||||||
|
|| 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static mrb_value app_run(mrb_state *mrb, mrb_value) {
|
||||||
|
mrb_int width, height;
|
||||||
|
char *title = nullptr;
|
||||||
|
mrb_get_args(mrb, "iiz", &width, &height, &title);
|
||||||
|
|
||||||
|
int loading_image = window.load_image("assets/images/menu_bg.png", 1.0f, true);
|
||||||
|
|
||||||
|
Animation loading_animation = {
|
||||||
|
.frames = {loading_image},
|
||||||
|
.frame_rate = 1.0f,
|
||||||
|
.loop = false
|
||||||
|
};
|
||||||
|
|
||||||
|
app_ = new app::App({(float)width, (float)height}, title, loading_animation);
|
||||||
|
|
||||||
|
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(Ruby::mrb, "Exception"), "Expected a Scene object");
|
||||||
|
return mrb_nil_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = get_id(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(Ruby::mrb, "Exception"), "Expected a Scene object");
|
||||||
|
return mrb_nil_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = get_id(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::localized_strings[Localization::join_keys(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();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setup() {
|
||||||
|
DEF_CLASS(Font, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1));
|
||||||
|
|
||||||
|
DEF_CLASS(ElementText, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1));
|
||||||
|
ADD_METHOD(
|
||||||
|
ElementText,
|
||||||
|
"on_click",
|
||||||
|
element_on_click,
|
||||||
|
MRB_ARGS_BLOCK()
|
||||||
|
);
|
||||||
|
|
||||||
|
DEF_CLASS(ElementRect, MRB_ARGS_REQ(2) | MRB_ARGS_OPT(1));
|
||||||
|
ADD_METHOD(
|
||||||
|
ElementRect,
|
||||||
|
"on_click",
|
||||||
|
element_on_click,
|
||||||
|
MRB_ARGS_BLOCK()
|
||||||
|
);
|
||||||
|
ADD_METHOD(
|
||||||
|
ElementRect,
|
||||||
|
"color=",
|
||||||
|
element_rect_color_set,
|
||||||
|
MRB_ARGS_REQ(1)
|
||||||
|
);
|
||||||
|
ADD_METHOD(
|
||||||
|
ElementRect,
|
||||||
|
"color",
|
||||||
|
element_rect_color_get,
|
||||||
|
MRB_ARGS_NONE()
|
||||||
|
);
|
||||||
|
|
||||||
|
DEF_CLASS(Scene, MRB_ARGS_NONE());
|
||||||
|
ADD_METHOD(Scene, "<<", scene_add_element, MRB_ARGS_REQ(1));
|
||||||
|
|
||||||
|
DEF_MODULE(App);
|
||||||
|
ADD_MODULE_METHOD(App, "run", app_run, MRB_ARGS_REQ(3));
|
||||||
|
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, "localize", app_localize, MRB_ARGS_REQ(3));
|
||||||
|
ADD_MODULE_METHOD(App, "language=", app_language_set, MRB_ARGS_REQ(1));
|
||||||
|
}
|
||||||
|
} // namespace definitions
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -29,6 +29,7 @@ struct Wrapper {
|
|||||||
|
|
||||||
#define DEF_RB(NAME, FN_FREE, FN_INIT) \
|
#define DEF_RB(NAME, FN_FREE, FN_INIT) \
|
||||||
static void NAME##_free(mrb_state *mrb, void *ptr) { \
|
static void NAME##_free(mrb_state *mrb, void *ptr) { \
|
||||||
|
UNUSED(mrb); \
|
||||||
int id = ((Wrapper *)ptr)->id; \
|
int id = ((Wrapper *)ptr)->id; \
|
||||||
FN_FREE; \
|
FN_FREE; \
|
||||||
delete (Wrapper *)ptr; \
|
delete (Wrapper *)ptr; \
|
||||||
@@ -38,6 +39,7 @@ struct Wrapper {
|
|||||||
NAME##_free \
|
NAME##_free \
|
||||||
}; \
|
}; \
|
||||||
static mrb_value NAME##_init(mrb_state *mrb, mrb_value self) { \
|
static mrb_value NAME##_init(mrb_state *mrb, mrb_value self) { \
|
||||||
|
UNUSED(mrb); \
|
||||||
Wrapper *s = new Wrapper(); \
|
Wrapper *s = new Wrapper(); \
|
||||||
FN_INIT; \
|
FN_INIT; \
|
||||||
DATA_PTR(self) = s; \
|
DATA_PTR(self) = s; \
|
||||||
@@ -45,6 +47,19 @@ struct Wrapper {
|
|||||||
return self; \
|
return self; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ADD_METHOD(NAME, METHOD, FUNC, ARGS) \
|
||||||
|
mrb_define_method(Ruby::mrb, NAME##_class, METHOD, FUNC, ARGS);
|
||||||
|
|
||||||
|
#define DEF_CLASS(NAME, ARGS) \
|
||||||
|
RClass *NAME##_class = mrb_define_class(Ruby::mrb, #NAME, Ruby::mrb->object_class); \
|
||||||
|
ADD_METHOD(NAME, "initialize", NAME##_init, ARGS);
|
||||||
|
|
||||||
|
#define DEF_MODULE(NAME) \
|
||||||
|
RClass *NAME##_module = mrb_define_module(Ruby::mrb, #NAME);
|
||||||
|
|
||||||
|
#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) {
|
inline int get_id(mrb_value self) {
|
||||||
return ((Wrapper *)DATA_PTR(self))->id;
|
return ((Wrapper *)DATA_PTR(self))->id;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-10
@@ -6,6 +6,8 @@
|
|||||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||||
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
||||||
|
|
||||||
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
||||||
struct Color {
|
struct Color {
|
||||||
uint8_t r, g, b = 0, a = 255;
|
uint8_t r, g, b = 0, a = 255;
|
||||||
};
|
};
|
||||||
@@ -77,18 +79,13 @@ struct Line {
|
|||||||
Line(Vec2<float> start, Vec2<float> end) : start(start), end(end) {}
|
Line(Vec2<float> start, Vec2<float> end) : start(start), end(end) {}
|
||||||
|
|
||||||
bool intersects(const Line &other) const {
|
bool intersects(const Line &other) const {
|
||||||
float denom = (other.end.y - other.start.y) * (end.x - start.x) -
|
float denom = (other.end.y - other.start.y) * (end.x - start.x) - (other.end.x - other.start.x) * (end.y - start.y);
|
||||||
(other.end.x - other.start.x) * (end.y - start.y);
|
|
||||||
|
|
||||||
if (std::abs(denom) < 1e-6f) // Lines are parallel (or very close to it)
|
if (std::abs(denom) < 1e-6f) // Lines are parallel (or very close to it)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
float ua = ((other.end.x - other.start.x) * (start.y - other.start.y) -
|
float ua = ((other.end.x - other.start.x) * (start.y - other.start.y) - (other.end.y - other.start.y) * (start.x - other.start.x)) / denom;
|
||||||
(other.end.y - other.start.y) * (start.x - other.start.x)) /
|
float ub = ((end.x - start.x) * (start.y - other.start.y) - (end.y - start.y) * (start.x - other.start.x)) / denom;
|
||||||
denom;
|
|
||||||
float ub = ((end.x - start.x) * (start.y - other.start.y) -
|
|
||||||
(end.y - start.y) * (start.x - other.start.x)) /
|
|
||||||
denom;
|
|
||||||
|
|
||||||
return ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1;
|
return ua >= 0 && ua <= 1 && ub >= 0 && ub <= 1;
|
||||||
}
|
}
|
||||||
@@ -113,8 +110,7 @@ struct Rect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool contains(const Vec2<float> &point) const {
|
bool contains(const Vec2<float> &point) const {
|
||||||
return point.x >= diagonal.start.x && point.x <= diagonal.end.x &&
|
return point.x >= diagonal.start.x && point.x <= diagonal.end.x && point.y >= diagonal.start.y && point.y <= diagonal.end.y;
|
||||||
point.y >= diagonal.start.y && point.y <= diagonal.end.y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool intersects(const Rect &other) const {
|
bool intersects(const Rect &other) const {
|
||||||
|
|||||||
+2
-292
@@ -1,297 +1,7 @@
|
|||||||
#include "app/app.h"
|
#include "binding/definitions.h"
|
||||||
|
|
||||||
app::App *app_ = nullptr;
|
|
||||||
|
|
||||||
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;
|
|
||||||
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_raise(mrb, mrb_class_get(Ruby::mrb, "Exception"), "Expected an ElementText or ElementRect object");
|
|
||||||
return mrb_nil_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
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")) || 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<float> 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<float> position = {x, y};
|
|
||||||
Vec2<float> 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;
|
|
||||||
mrb_get_args(mrb, "iiz", &width, &height, &title);
|
|
||||||
|
|
||||||
int loading_image = window.load_image("assets/images/menu_bg.png", 1.0f, true);
|
|
||||||
|
|
||||||
Animation loading_animation = {
|
|
||||||
.frames = {loading_image},
|
|
||||||
.frame_rate = 1.0f,
|
|
||||||
.loop = false
|
|
||||||
};
|
|
||||||
|
|
||||||
app_ = new app::App({(float)width, (float)height}, title, loading_animation);
|
|
||||||
|
|
||||||
return mrb_nil_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
mrb_value app_start(mrb_state *mrb, mrb_value self) {
|
|
||||||
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(Ruby::mrb, "Exception"), "Expected a Scene object");
|
|
||||||
return mrb_nil_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
int id = get_id(scene_val);
|
|
||||||
app_->switch_to_scene(id);
|
|
||||||
app_->loop();
|
|
||||||
|
|
||||||
return mrb_nil_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
mrb_value app_switch_to(mrb_state *mrb, mrb_value self) {
|
|
||||||
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(Ruby::mrb, "Exception"), "Expected a Scene object");
|
|
||||||
return mrb_nil_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
int id = get_id(scene_val);
|
|
||||||
app_->switch_to_scene(id);
|
|
||||||
|
|
||||||
return mrb_nil_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
static mrb_value app_localize(mrb_state *mrb, mrb_value self) {
|
|
||||||
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::localized_strings[Localization::join_keys(lang, key_id)] = text;
|
|
||||||
|
|
||||||
return mrb_nil_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
RClass *font_class = mrb_define_class(Ruby::mrb, "Font", Ruby::mrb->object_class);
|
definitions::setup();
|
||||||
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", 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);
|
|
||||||
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", 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);
|
|
||||||
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);
|
|
||||||
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),
|
|
||||||
(uint8_t)((mrb_fixnum(color_val) >> 8) & 0xFF),
|
|
||||||
(uint8_t)(mrb_fixnum(color_val) & 0xFF)
|
|
||||||
};
|
|
||||||
return self; }, MRB_ARGS_REQ(1));
|
|
||||||
mrb_define_method(Ruby::mrb, element_rect_class, "color", [](mrb_state *mrb, mrb_value self) {
|
|
||||||
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) |
|
|
||||||
(uint32_t)element->color.a;
|
|
||||||
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, "<<", scene_add_element, MRB_ARGS_REQ(1));
|
|
||||||
|
|
||||||
RClass *app_module = mrb_define_module(Ruby::mrb, "App");
|
|
||||||
mrb_define_class_method(Ruby::mrb, app_module, "run", app_run, MRB_ARGS_REQ(3));
|
|
||||||
mrb_define_class_method(Ruby::mrb, app_module, "start", app_start, MRB_ARGS_REQ(1));
|
|
||||||
mrb_define_class_method(Ruby::mrb, app_module, "switch_to", app_switch_to, MRB_ARGS_REQ(1));
|
|
||||||
mrb_define_class_method(Ruby::mrb, app_module, "localize", app_localize, MRB_ARGS_REQ(3));
|
|
||||||
mrb_define_class_method(Ruby::mrb, app_module, "language=", [](mrb_state *mrb, mrb_value self) {
|
|
||||||
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(); }, MRB_ARGS_REQ(1));
|
|
||||||
|
|
||||||
char *startup_script = nullptr;
|
char *startup_script = nullptr;
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
|
|||||||
@@ -384,7 +384,8 @@ bool Window::poll(Event &event) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_EVENT_KEY_DOWN:
|
case SDL_EVENT_KEY_DOWN:
|
||||||
#warning This is a bit of a hack to prevent key down/up events from being generated when text input is active on certian keys, but this list is not enough, need to look more into it
|
#warning "This is a bit of a hack to prevent key down/up events from being generated when text input is active on certian keys," \
|
||||||
|
"but this list is not enough, need to look more into it"
|
||||||
if (text_input_active && sdl_event.key.key > '0' && sdl_event.key.key < 'z')
|
if (text_input_active && sdl_event.key.key > '0' && sdl_event.key.key < 'z')
|
||||||
return false;
|
return false;
|
||||||
event.type = Event::KEY_DOWN;
|
event.type = Event::KEY_DOWN;
|
||||||
@@ -516,6 +517,5 @@ void Window::compute_transform() {
|
|||||||
bool Window::mouse_in_window(const Vec2<float> real_position, Vec2<float> &virtual_position) {
|
bool Window::mouse_in_window(const Vec2<float> real_position, Vec2<float> &virtual_position) {
|
||||||
virtual_position = (real_position - offset) / scale;
|
virtual_position = (real_position - offset) / scale;
|
||||||
|
|
||||||
return virtual_position.x >= 0 && virtual_position.x <= virtual_size.x &&
|
return virtual_position.x >= 0 && virtual_position.x <= virtual_size.x && virtual_position.y >= 0 && virtual_position.y <= virtual_size.y;
|
||||||
virtual_position.y >= 0 && virtual_position.y <= virtual_size.y;
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user