/* ** input-binding.h ** ** This file is part of mkxp. ** ** Copyright (C) 2013 - 2021 Amaryllis Kulla ** ** mkxp is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 2 of the License, or ** (at your option) any later version. ** ** mkxp is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with mkxp. If not, see . */ #ifndef MKXPZ_SANDBOX_INPUT_BINDING_H #define MKXPZ_SANDBOX_INPUT_BINDING_H #include "sandbox.h" #include "core.h" #include "input.h" #include "sharedstate.h" namespace mkxp_sandbox { static VALUE input_module; static VALUE symhash; struct { const char *str; Input::ButtonCode val; } static codes[] = { {"DOWN", Input::Down}, {"LEFT", Input::Left}, {"RIGHT", Input::Right}, {"UP", Input::Up}, {"C", Input::C}, {"Z", Input::Z}, {"A", Input::A}, {"B", Input::B}, {"X", Input::X}, {"Y", Input::Y}, {"L", Input::L}, {"R", Input::R}, {"SHIFT", Input::Shift}, {"CTRL", Input::Ctrl}, {"ALT", Input::Alt}, {"F5", Input::F5}, {"F6", Input::F6}, {"F7", Input::F7}, {"F8", Input::F8}, {"F9", Input::F9}, {"MOUSELEFT", Input::MouseLeft}, {"MOUSEMIDDLE", Input::MouseMiddle}, {"MOUSERIGHT", Input::MouseRight}, {"MOUSEX1", Input::MouseX1}, {"MOUSEX2", Input::MouseX2}, }; SANDBOX_COROUTINE(input_binding_init, SANDBOX_COROUTINE(get_button_arg, VALUE value; int32_t button; int32_t operator()(VALUE arg) { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_AND_SET(value, rb_obj_is_kind_of, arg, sb()->rb_cInteger()); if (SANDBOX_VALUE_TO_BOOL(value)) { SANDBOX_AWAIT_AND_SET(button, rb_num2int, arg); } else { SANDBOX_AWAIT_AND_SET(value, rb_obj_is_kind_of, arg, sb()->rb_cSymbol()); if (SANDBOX_VALUE_TO_BOOL(value) && rgssVer >= 3) { SANDBOX_AWAIT_AND_SET(value, rb_ll2inum, Input::None); SANDBOX_AWAIT_AND_SET(value, rb_hash_lookup2, symhash, arg, value); SANDBOX_AWAIT_AND_SET(button, rb_num2int, value); } else { // FIXME: RMXP allows only few more types that // don't make sense (symbols in pre 3, floats) button = 0; } } } return button; } ) static VALUE delta(VALUE self) { return sb()->bind()()(mkxp_retro::input->getDelta()); } static VALUE update(VALUE self) { mkxp_retro::input->update(); return SANDBOX_NIL; } static VALUE press(VALUE self, VALUE code) { SANDBOX_COROUTINE(coro, int32_t button; VALUE operator()(VALUE self, VALUE code) { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_AND_SET(button, get_button_arg, code); return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->isPressed(button)); } return SANDBOX_UNDEF; } ) return sb()->bind()()(self, code); } static VALUE trigger(VALUE self, VALUE code) { SANDBOX_COROUTINE(coro, int32_t button; VALUE operator()(VALUE self, VALUE code) { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_AND_SET(button, get_button_arg, code); return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->isTriggered(button)); } return SANDBOX_UNDEF; } ) return sb()->bind()()(self, code); } static VALUE repeat(VALUE self, VALUE code) { SANDBOX_COROUTINE(coro, int32_t button; VALUE operator()(VALUE self, VALUE code) { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_AND_SET(button, get_button_arg, code); return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->isRepeated(button)); } return SANDBOX_UNDEF; } ) return sb()->bind()()(self, code); } static VALUE release(VALUE self, VALUE code) { SANDBOX_COROUTINE(coro, int32_t button; VALUE operator()(VALUE self, VALUE code) { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_AND_SET(button, get_button_arg, code); return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->isReleased(button)); } return SANDBOX_UNDEF; } ) return sb()->bind()()(self, code); } static VALUE count(VALUE self, VALUE code) { SANDBOX_COROUTINE(coro, int32_t button; int32_t count; VALUE value; VALUE operator()(VALUE self, VALUE code) { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_AND_SET(button, get_button_arg, code); count = mkxp_retro::input->count(button); SANDBOX_AWAIT_AND_SET(value, rb_ll2inum, count); } return value; } ) return sb()->bind()()(self, code); } static VALUE time(VALUE self, VALUE code) { SANDBOX_COROUTINE(coro, int32_t button; double time; VALUE value; VALUE operator()(VALUE self, VALUE code) { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_AND_SET(button, get_button_arg, code); time = mkxp_retro::input->repeatTime(button); SANDBOX_AWAIT_AND_SET(value, rb_float_new, time); } return value; } ) return sb()->bind()()(self, code); } static VALUE pressex(VALUE self, VALUE code) { SANDBOX_COROUTINE(coro, int32_t button; VALUE operator()(VALUE self, VALUE code) { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_AND_SET(button, get_button_arg, code); return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->isPressedEx(button, false)); } return SANDBOX_UNDEF; } ) return sb()->bind()()(self, code); } static VALUE triggerex(VALUE self, VALUE code) { SANDBOX_COROUTINE(coro, int32_t button; VALUE operator()(VALUE self, VALUE code) { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_AND_SET(button, get_button_arg, code); return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->isTriggeredEx(button, false)); } return SANDBOX_UNDEF; } ) return sb()->bind()()(self, code); } static VALUE repeatex(VALUE self, VALUE code) { SANDBOX_COROUTINE(coro, int32_t button; VALUE operator()(VALUE self, VALUE code) { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_AND_SET(button, get_button_arg, code); return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->isRepeatedEx(button, false)); } return SANDBOX_UNDEF; } ) return sb()->bind()()(self, code); } static VALUE releaseex(VALUE self, VALUE code) { SANDBOX_COROUTINE(coro, int32_t button; VALUE operator()(VALUE self, VALUE code) { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_AND_SET(button, get_button_arg, code); return SANDBOX_BOOL_TO_VALUE(mkxp_retro::input->isReleasedEx(button, false)); } return SANDBOX_UNDEF; } ) return sb()->bind()()(self, code); } static VALUE repeatcount(VALUE self, VALUE code) { SANDBOX_COROUTINE(coro, int32_t button; int32_t count; VALUE value; VALUE operator()(VALUE self, VALUE code) { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_AND_SET(button, get_button_arg, code); count = mkxp_retro::input->repeatcount(button, false); SANDBOX_AWAIT_AND_SET(value, rb_ll2inum, count); } return value; } ) return sb()->bind()()(self, code); } static VALUE timeex(VALUE self, VALUE code) { SANDBOX_COROUTINE(coro, int32_t button; double time; VALUE value; VALUE operator()(VALUE self, VALUE code) { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_AND_SET(button, get_button_arg, code); time = mkxp_retro::input->repeatTimeEx(button, false); SANDBOX_AWAIT_AND_SET(value, rb_float_new, time); } return value; } ) return sb()->bind()()(self, code); } static VALUE dir4(VALUE self) { return sb()->bind()()(mkxp_retro::input->dir4Value()); } static VALUE dir8(VALUE self) { return sb()->bind()()(mkxp_retro::input->dir8Value()); } static VALUE todo_bool(int32_t argc, wasm_ptr_t argv, VALUE self) { return SANDBOX_FALSE; } static VALUE todo_number(int32_t argc, wasm_ptr_t argv, VALUE self) { return sb()->bind()()(0); } VALUE button_val; VALUE id_val; size_t i; ID id; void operator()() { BOOST_ASIO_CORO_REENTER (this) { SANDBOX_AWAIT_AND_SET(input_module, rb_define_module, "Input"); SANDBOX_AWAIT(rb_define_module_function, input_module, "delta", (VALUE (*)(ANYARGS))delta, 0); SANDBOX_AWAIT(rb_define_module_function, input_module, "update", (VALUE (*)(ANYARGS))update, 0); SANDBOX_AWAIT(rb_define_module_function, input_module, "press?", (VALUE (*)(ANYARGS))press, 1); SANDBOX_AWAIT(rb_define_module_function, input_module, "trigger?", (VALUE (*)(ANYARGS))trigger, 1); SANDBOX_AWAIT(rb_define_module_function, input_module, "repeat?", (VALUE (*)(ANYARGS))repeat, 1); SANDBOX_AWAIT(rb_define_module_function, input_module, "release?", (VALUE (*)(ANYARGS))release, 1); SANDBOX_AWAIT(rb_define_module_function, input_module, "count", (VALUE (*)(ANYARGS))count, 1); SANDBOX_AWAIT(rb_define_module_function, input_module, "time?", (VALUE (*)(ANYARGS))time, 1); SANDBOX_AWAIT(rb_define_module_function, input_module, "pressex?", (VALUE (*)(ANYARGS))pressex, 1); SANDBOX_AWAIT(rb_define_module_function, input_module, "triggerex?", (VALUE (*)(ANYARGS))triggerex, 1); SANDBOX_AWAIT(rb_define_module_function, input_module, "repeatex?", (VALUE (*)(ANYARGS))repeatex, 1); SANDBOX_AWAIT(rb_define_module_function, input_module, "releaseex?", (VALUE (*)(ANYARGS))releaseex, 1); SANDBOX_AWAIT(rb_define_module_function, input_module, "repeatcount", (VALUE (*)(ANYARGS))repeatcount, 1); SANDBOX_AWAIT(rb_define_module_function, input_module, "timeex?", (VALUE (*)(ANYARGS))timeex, 1); SANDBOX_AWAIT(rb_define_module_function, input_module, "dir4", (VALUE (*)(ANYARGS))dir4, 0); SANDBOX_AWAIT(rb_define_module_function, input_module, "dir8", (VALUE (*)(ANYARGS))dir8, 0); SANDBOX_AWAIT(rb_define_module_function, input_module, "mouse_x", (VALUE (*)(ANYARGS))todo_number, -1); SANDBOX_AWAIT(rb_define_module_function, input_module, "mouse_y", (VALUE (*)(ANYARGS))todo_number, -1); SANDBOX_AWAIT(rb_define_module_function, input_module, "scroll_v", (VALUE (*)(ANYARGS))todo_number, -1); SANDBOX_AWAIT(rb_define_module_function, input_module, "mouse_in_window", (VALUE (*)(ANYARGS))todo_bool, -1); SANDBOX_AWAIT(rb_define_module_function, input_module, "mouse_in_window?", (VALUE (*)(ANYARGS))todo_bool, -1); if (rgssVer >= 3) { SANDBOX_AWAIT_AND_SET(symhash, rb_hash_new); for (i = 0; i < sizeof(codes) / sizeof(*codes); ++i) { SANDBOX_AWAIT_AND_SET(id, rb_intern, codes[i].str); SANDBOX_AWAIT_AND_SET(button_val, rb_ll2inum, codes[i].val); /* In RGSS3 all Input::XYZ constants are equal to :XYZ symbols, * to be compatible with the previous convention */ SANDBOX_AWAIT_AND_SET(id_val, rb_id2sym, id); SANDBOX_AWAIT(rb_const_set, input_module, id, id_val); SANDBOX_AWAIT(rb_hash_aset, symhash, id_val, button_val); } SANDBOX_AWAIT(rb_iv_set, input_module, "buttoncodes", symhash); } else { for (i = 0; i < sizeof(codes) / sizeof(*codes); ++i) { SANDBOX_AWAIT_AND_SET(id, rb_intern, codes[i].str); SANDBOX_AWAIT_AND_SET(button_val, rb_ll2inum, codes[i].val); SANDBOX_AWAIT(rb_const_set, input_module, id, button_val); } } } } ) } #endif // MKXPZ_SANDBOX_INPUT_BINDING_H