#ifndef RUBY_H #define RUBY_H #include "pch.h" #include "utils.h" #include "binding/ruby_compiled.h" #define DEF_SYM(name) inline mrb_sym sym_##name = mrb_intern_cstr(Ruby::mrb, #name); #define SYM(name) mrb_symbol_value(sym_##name) #define HASH_GET(h, key) mrb_hash_get(Ruby::mrb, h, SYM(key)) #define HASH_SET(h, key, value) mrb_hash_set(Ruby::mrb, h, SYM(key), value) #define HASH_FLOAT(h, key, out) \ do { \ mrb_value v = HASH_GET(h, key); \ if (mrb_float_p(v)) \ out = mrb_float(v); \ else if (mrb_fixnum_p(v)) \ out = (float)mrb_fixnum(v); \ } while (0) #define HASH_BOOL(h, key, out) \ do { \ mrb_value v = HASH_GET(h, key); \ if (!mrb_nil_p(v)) \ out = mrb_bool(v); \ } while (0) struct Wrapper { uint64_t id; }; #define ADD_FUNCTION(NAME, FUNC, ARGS) \ mrb_define_method(Ruby::mrb, Ruby::mrb->object_class, NAME, FUNC, ARGS); #define ADD_METHOD(NAME, METHOD, FUNC, ARGS) \ mrb_define_method(Ruby::mrb, NAME##_class, METHOD, FUNC, ARGS); #define ADD_CLASS_METHOD(CLASS, METHOD, FUNC, ARGS) \ mrb_define_class_method(Ruby::mrb, CLASS##_class, METHOD, FUNC, ARGS); #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) \ 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); namespace Ruby { inline mrb_state *mrb = mrb_open(); struct Block { mrb_value proc; Block(mrb_value proc) : proc(proc) { mrb_gc_register(mrb, proc); } Block() : proc(mrb_nil_value()) {} ~Block() { if (!mrb_nil_p(proc)) mrb_gc_unregister(mrb, proc); } void set_proc(mrb_value new_proc) { if (!mrb_nil_p(proc)) mrb_gc_unregister(mrb, proc); proc = new_proc; mrb_gc_register(mrb, proc); } Block(const Block &) = delete; Block &operator=(const Block &) = delete; mrb_value call(int argc = 0, mrb_value *argv = nullptr) const { if (mrb_nil_p(proc)) return mrb_nil_value(); mrb_value result = mrb_funcall_argv(mrb, proc, mrb_intern_cstr(mrb, "call"), argc, argv); return result; } }; inline void run_string(const char *code, size_t length) { int ai = mrb_gc_arena_save(mrb); mrb_load_nstring(mrb, code, length); mrb_gc_arena_restore(mrb, ai); } inline void load_mgems() { int ai = mrb_gc_arena_save(mrb); mrb_load_irep(mrb, mgems); mrb_gc_arena_restore(mrb, ai); } }; // namespace Ruby DEF_SYM(pixel_art) DEF_SYM(bold) DEF_SYM(italic) DEF_SYM(underline) DEF_SYM(position) DEF_SYM(rotation) DEF_SYM(pivot) DEF_SYM(scale) DEF_SYM(alpha) DEF_SYM(fps) DEF_SYM(click_mode) DEF_SYM(pass) DEF_SYM(block) DEF_SYM(ignore) DEF_SYM(call) DEF_SYM(x) DEF_SYM(y) DEF_SYM(w) DEF_SYM(h) DEF_SYM(z) #endif