diff options
author | 2020-12-09 01:01:22 +1100 | |
---|---|---|
committer | 2020-12-09 01:10:26 +1100 | |
commit | e008c7b1b1042d644be2a1e177ffa15d53e942c5 (patch) | |
tree | d248f9fcbe15563c46c1ae9605d35a19ed4ada5e /src/frontend/mame/luaengine_input.cpp | |
parent | 06568860e7a30424bab61498cd2a8a44889e4412 (diff) |
-Lua engine cleanup, input edition:
* Modernised and cleaned up Lua bindings for input classes.
* Exposed the input_sequence_poller class to Lua and updated the
autofire and cheat plugins to use it, rather than continuing to
pretend it's part of the input manager.
* Exposed more of the natural keyboard manager, including the ability
to enable/disable individual keyboard and keypad devices like you
can from the keyboard mode menu.
* Exposed a few more things on ioport_port and input_device.
-plugins/cheat: Fixed menu item not updating visually when disabling a
cheat with UI Left.
-plugins/cheatfind: Fixed not finding the first screen after screen
enumerator was exposed as an object rather than using a table.
-bwidow.cpp, pacman.cpp: Minor cleanup to recent changes.
Diffstat (limited to 'src/frontend/mame/luaengine_input.cpp')
-rw-r--r-- | src/frontend/mame/luaengine_input.cpp | 635 |
1 files changed, 415 insertions, 220 deletions
diff --git a/src/frontend/mame/luaengine_input.cpp b/src/frontend/mame/luaengine_input.cpp index e135678a840..327f58e8a4f 100644 --- a/src/frontend/mame/luaengine_input.cpp +++ b/src/frontend/mame/luaengine_input.cpp @@ -11,11 +11,140 @@ #include "emu.h" #include "luaengine.ipp" +#include "iptseqpoll.h" + #include "inputdev.h" #include "natkeyboard.h" #include "render.h" #include "uiinput.h" +#include <cstring> + + +namespace { + +struct natkbd_kbd_dev +{ + natkbd_kbd_dev(natural_keyboard &m, std::size_t i) : manager(m), index(i) { } + + natural_keyboard &manager; + std::size_t index; +}; + + +struct natkbd_kbd_list +{ + natkbd_kbd_list(natural_keyboard &m) : manager(m) { } + + natural_keyboard &manager; +}; + +} // anonymous namespace + + +namespace sol { + +template <> struct is_container<natkbd_kbd_list> : std::true_type { }; + + +template <> +struct usertype_container<natkbd_kbd_list> +{ +private: + static natkbd_kbd_list &get_self(lua_State *L) + { + auto p(sol::stack::unqualified_check_get<natkbd_kbd_list *>(L, 1)); + if (!p) + luaL_error(L, "sol: 'self' is not of type 'natkbd_kbd_list' (pass 'self' as first argument with ':' or call on proper type)"); + if (!*p) + luaL_error(L, "sol: 'self' argument is nil (pass 'self' as first argument with ':' or call on a 'natkbd_kbd_list' type"); + return **p; + } + + template <bool Indexed> + static int next_pairs(lua_State *L) + { + natkbd_kbd_dev &i(stack::unqualified_get<user<natkbd_kbd_dev> >(L, 1)); + if (i.manager.keyboard_count() <= i.index) + return stack::push(L, lua_nil); + int result; + if constexpr (Indexed) + result = stack::push(L, i.index + 1); + else + result = stack::push(L, i.manager.keyboard_device(i.index).tag()); + result += stack::push(L, i); + ++i.index; + return result; + } + + template <bool Indexed> + static int start_pairs(lua_State *L) + { + natkbd_kbd_list &self(get_self(L)); + stack::push(L, next_pairs<Indexed>); + stack::push<user<natkbd_kbd_dev> >(L, self.manager, 0); + stack::push(L, lua_nil); + return 3; + } + +public: + static int at(lua_State *L) + { + natkbd_kbd_list &self(get_self(L)); + std::ptrdiff_t const index(stack::unqualified_get<std::ptrdiff_t>(L, 2)); + if ((0 < index) && (self.manager.keyboard_count() >= index)) + return stack::push(L, natkbd_kbd_dev(self.manager, index - 1)); + else + return stack::push(L, lua_nil); + } + + static int get(lua_State *L) + { + natkbd_kbd_list &self(get_self(L)); + char const *const tag(stack::unqualified_get<char const *>(L)); + for (std::size_t i = 0; self.manager.keyboard_count() > i; ++i) + { + if (!std::strcmp(self.manager.keyboard_device(i).tag(), tag)) + return stack::push(L, natkbd_kbd_dev(self.manager, i)); + } + return stack::push(L, lua_nil); + } + + static int index_get(lua_State *L) + { + return get(L); + } + + static int size(lua_State *L) + { + natkbd_kbd_list &self(get_self(L)); + return stack::push(L, self.manager.keyboard_count()); + } + + static int empty(lua_State *L) + { + natkbd_kbd_list &self(get_self(L)); + return stack::push(L, !self.manager.keyboard_count()); + } + + // produce errors for unsupported operations + static int set(lua_State *L) { return luaL_error(L, "sol: cannot call 'set(key, value)' on type 'natkbd_kbd_list': container is not modifiable"); } + static int index_set(lua_State *L) { return luaL_error(L, "sol: cannot call 'container[key] = value' on type 'natkbd_kbd_list': container is not modifiable"); } + static int add(lua_State *L) { return luaL_error(L, "sol: cannot call 'add' on type 'natkbd_kbd_list': container is not modifiable"); } + static int insert(lua_State *L) { return luaL_error(L, "sol: cannot call 'insert' on type 'natkbd_kbd_list': container is not modifiable"); } + static int find(lua_State *L) { return luaL_error(L, "sol: cannot call 'find' on type 'natkbd_kbd_list': no supported comparison operator for the value type"); } + static int index_of(lua_State *L) { return luaL_error(L, "sol: cannot call 'index_of' on type 'natkbd_kbd_list': no supported comparison operator for the value type"); } + static int clear(lua_State *L) { return luaL_error(L, "sol: cannot call 'clear' on type 'natkbd_kbd_list': container is not modifiable"); } + static int erase(lua_State *L) { return luaL_error(L, "sol: cannot call 'erase' on type 'natkbd_kbd_list': container is not modifiable"); } + + // support for iteration with pairs and ipairs + static int next(lua_State *L) { return stack::push(L, next_pairs<false>); } + static int pairs(lua_State *L) { return start_pairs<false>(L); } + static int ipairs(lua_State *L) { return start_pairs<true>(L); } +}; + +} // namespace sol + //------------------------------------------------- // initialize_input - register input user types @@ -41,86 +170,123 @@ void lua_engine::initialize_input(sol::table &emu) * ioport:type_seq(type, player, seqtype) - get input sequence for ioport type/player * * ioport.ports[] - ioports table (k=tag, v=ioport_port) + * ioport.natkeyboard - get natural keyboard manager */ - auto ioport_manager_type = sol().registry().new_usertype<ioport_manager>("ioport", "new", sol::no_constructor); - ioport_manager_type.set("count_players", &ioport_manager::count_players); - ioport_manager_type.set("natkeyboard", &ioport_manager::natkeyboard); - ioport_manager_type.set("type_group", [](ioport_manager &im, ioport_type type, int player) { - return im.type_group(type, player); - }); - ioport_manager_type.set("ports", sol::property([this](ioport_manager &im) { - sol::table port_table = sol().create_table(); - for (auto &port : im.ports()) - port_table[port.second->tag()] = port.second.get(); - return port_table; - })); - ioport_manager_type.set("type_seq", [](ioport_manager &m, ioport_type type, int player, input_seq_type seqtype) { - return m.type_seq(type, player, seqtype); - }); + auto ioport_manager_type = sol().registry().new_usertype<ioport_manager>("ioport", sol::no_constructor); + ioport_manager_type["count_players"] = &ioport_manager::count_players; + ioport_manager_type["type_group"] = &ioport_manager::type_group; + ioport_manager_type["type_seq"] = &ioport_manager::type_seq; + ioport_manager_type["ports"] = sol::property([] (ioport_manager &im) { return tag_object_ptr_map<ioport_list>(im.ports()); }); + ioport_manager_type["natkeyboard"] = sol::property(&ioport_manager::natkeyboard); /* natural_keyboard library * - * manager:machine():ioport():natkeyboard() + * manager:machine():ioport().natkeyboard * - * natkeyboard:paste() - paste clipboard data - * natkeyboard:post() - post data to natural keyboard - * natkeyboard:post_coded() - post data to natural keyboard + * natkeyboard:post(text) - post data to natural keyboard + * natkeyboard:post_coded(text) - post data to natural keyboard + * natkeyboard:paste() - paste host clipboard text + * natkeyboard:dump() - returns human-readable description of character mappings * * natkeyboard.empty - is the natural keyboard buffer empty? - * natkeyboard.in_use - is the natural keyboard in use? + * natkeyboard.full - is the natural keyboard buffer full? + * natkeyboard.can_post - does the system support posting characters via natural keyboard? + * natkeyboard.is_posting - is a post operation currently in progress? + * natkeyboard.in_use - is natural keyboard mode enabled (read/write)? + * natkeyboard.keyboards[] - get keyboard devices in system (k=tag, v=natkbd_kbd_dev) + */ + + auto natkeyboard_type = sol().registry().new_usertype<natural_keyboard>("natkeyboard", sol::no_constructor); + natkeyboard_type["post"] = [] (natural_keyboard &nat, std::string const &text) { nat.post_utf8(text); }; + natkeyboard_type["post_coded"] = [] (natural_keyboard &nat, std::string const &text) { nat.post_coded(text); }; + natkeyboard_type["paste"] = &natural_keyboard::paste; + natkeyboard_type["dump"] = static_cast<std::string (natural_keyboard::*)() const>(&natural_keyboard::dump); + natkeyboard_type["empty"] = sol::property(&natural_keyboard::empty); + natkeyboard_type["full"] = sol::property(&natural_keyboard::full); + natkeyboard_type["can_post"] = sol::property(&natural_keyboard::can_post); + natkeyboard_type["is_posting"] = sol::property(&natural_keyboard::is_posting); + natkeyboard_type["in_use"] = sol::property(&natural_keyboard::in_use, &natural_keyboard::set_in_use); + natkeyboard_type["keyboards"] = sol::property([] (natural_keyboard &nat) { return natkbd_kbd_list(nat); }); + + +/* natkbd_kbd_dev library + * + * manager:machine():ioport().natkeyboard.keyboards[tag] + * + * keyboard.device - underlying device that the inputs belong to + * keyboard.tag - absolute tag of the device + * keyboard.basetag - last component of the device tag ("root" for root device) + * keyboard.name - device type full name + * keyboard.shortname - device type short name + * keyboard.is_keypad - does the device have keypad inputs but no keyboard inputs? + * keyboard.enabled - are the device's keyboard/keypad inputs enabled (read/write)? */ - auto natkeyboard_type = sol().registry().new_usertype<natural_keyboard>("natkeyboard", "new", sol::no_constructor); - natkeyboard_type.set("empty", sol::property(&natural_keyboard::empty)); - natkeyboard_type.set("in_use", sol::property(&natural_keyboard::in_use, &natural_keyboard::set_in_use)); - natkeyboard_type.set("paste", &natural_keyboard::paste); - natkeyboard_type.set("post", [](natural_keyboard &nat, const std::string &text) { nat.post_utf8(text); }); - natkeyboard_type.set("post_coded", [](natural_keyboard &nat, const std::string &text) { nat.post_coded(text); }); + auto natkbddev_type = sol().registry().new_usertype<natkbd_kbd_dev>("natkeyboard_device", sol::no_constructor); + natkbddev_type["device"] = sol::property([] (natkbd_kbd_dev const &kbd) -> device_t & { return kbd.manager.keyboard_device(kbd.index); }); + natkbddev_type["tag"] = sol::property([] (natkbd_kbd_dev const &kbd) { return kbd.manager.keyboard_device(kbd.index).tag(); }); + natkbddev_type["basetag"] = sol::property([] (natkbd_kbd_dev const &kbd) { return kbd.manager.keyboard_device(kbd.index).basetag(); }); + natkbddev_type["name"] = sol::property([] (natkbd_kbd_dev const &kbd) { return kbd.manager.keyboard_device(kbd.index).name(); }); + natkbddev_type["shortname"] = sol::property([] (natkbd_kbd_dev const &kbd) { return kbd.manager.keyboard_device(kbd.index).shortname(); }); + natkbddev_type["is_keypad"] = sol::property([] (natkbd_kbd_dev const &kbd) { return kbd.manager.keyboard_is_keypad(kbd.index); }); + natkbddev_type["enabled"] = sol::property( + [] (natkbd_kbd_dev const &kbd) { return kbd.manager.keyboard_enabled(kbd.index); }, + [] (natkbd_kbd_dev &kbd, bool enable) + { + if (enable) + kbd.manager.enable_keyboard(kbd.index); + else + kbd.manager.disable_keyboard(kbd.index); + }); /* ioport_port library * * manager:machine():ioport().ports[port_tag] * - * port:tag() - get port tag - * port:active() - get port status - * port:live() - get port ioport_port_live (TODO: not usable from lua as of now) * port:read() - get port value * port:write(val, mask) - set port to value & mask (output fields only, for other fields use field:set_value(val)) * port:field(mask) - get ioport_field for port and mask * + * port.device - get device that the port belongs to + * port.tag - get port tag + * port.active - get port status + * port.live - get port ioport_port_live (TODO: not usable from lua as of now) * port.fields[] - get ioport_field table (k=name, v=ioport_field) */ auto ioport_port_type = sol().registry().new_usertype<ioport_port>("ioport_port", "new", sol::no_constructor); - ioport_port_type.set("tag", &ioport_port::tag); - ioport_port_type.set("active", &ioport_port::active); - ioport_port_type.set("live", &ioport_port::live); - ioport_port_type.set("read", &ioport_port::read); - ioport_port_type.set("write", &ioport_port::write); - ioport_port_type.set("field", &ioport_port::field); - ioport_port_type.set("fields", sol::property([this](ioport_port &p){ - sol::table f_table = sol().create_table(); - // parse twice for custom and default names, default has priority - for(ioport_field &field : p.fields()) - { - if (field.type_class() != INPUT_CLASS_INTERNAL) - f_table[field.name()] = &field; - } - for(ioport_field &field : p.fields()) + ioport_port_type["read"] = &ioport_port::read; + ioport_port_type["write"] = &ioport_port::write; + ioport_port_type["field"] = &ioport_port::field; + ioport_port_type["device"] = sol::property(&ioport_port::device); + ioport_port_type["tag"] = sol::property(&ioport_port::tag); + ioport_port_type["active"] = sol::property(&ioport_port::active); + ioport_port_type["live"] = sol::property(&ioport_port::live); + ioport_port_type["fields"] = sol::property( + [this] (ioport_port &p) { - if (field.type_class() != INPUT_CLASS_INTERNAL) + sol::table f_table = sol().create_table(); + // parse twice for custom and default names, default has priority + for (ioport_field &field : p.fields()) + { + if (field.type_class() != INPUT_CLASS_INTERNAL) + f_table[field.name()] = &field; + } + for (ioport_field &field : p.fields()) { - if(field.specific_name()) - f_table[field.specific_name()] = &field; - else - f_table[field.manager().type_name(field.type(), field.player())] = &field; + if (field.type_class() != INPUT_CLASS_INTERNAL) + { + if (field.specific_name()) + f_table[field.specific_name()] = &field; + else + f_table[field.manager().type_name(field.type(), field.player())] = &field; + } } - } - return f_table; - })); + return f_table; + }); /* ioport_field library @@ -165,92 +331,110 @@ void lua_engine::initialize_input(sol::table &emu) * field.settings[] - ioport_setting table (k=value, v=name) */ - auto ioport_field_type = sol().registry().new_usertype<ioport_field>("ioport_field", "new", sol::no_constructor); - ioport_field_type.set("set_value", &ioport_field::set_value); - ioport_field_type.set("set_input_seq", [](ioport_field &f, const std::string &seq_type_string, const input_seq &seq) { + auto ioport_field_type = sol().registry().new_usertype<ioport_field>("ioport_field", sol::no_constructor); + ioport_field_type["set_value"] = &ioport_field::set_value; + ioport_field_type["set_input_seq"] = + [] (ioport_field &f, std::string const &seq_type_string, const input_seq &seq) + { input_seq_type seq_type = s_seq_type_parser(seq_type_string); ioport_field::user_settings settings; f.get_user_settings(settings); settings.seq[seq_type] = seq; f.set_user_settings(settings); - }); - ioport_field_type.set("input_seq", [](ioport_field &f, const std::string &seq_type_string) { + }; + ioport_field_type["input_seq"] = + [] (ioport_field &f, std::string const &seq_type_string) + { input_seq_type seq_type = s_seq_type_parser(seq_type_string); return f.seq(seq_type); - }); - ioport_field_type.set("set_default_input_seq", [](ioport_field &f, const std::string &seq_type_string, const input_seq &seq) { + }; + ioport_field_type["set_default_input_seq"] = + [] (ioport_field &f, std::string const &seq_type_string, input_seq const &seq) + { input_seq_type seq_type = s_seq_type_parser(seq_type_string); f.set_defseq(seq_type, seq); - }); - ioport_field_type.set("default_input_seq", [](ioport_field &f, const std::string &seq_type_string) { + }; + ioport_field_type["default_input_seq"] = + [] (ioport_field &f, const std::string &seq_type_string) + { input_seq_type seq_type = s_seq_type_parser(seq_type_string); return f.defseq(seq_type); - }); - ioport_field_type.set("keyboard_codes", [this](ioport_field &f, int which) { + }; + ioport_field_type["keyboard_codes"] = + [this] (ioport_field &f, int which) + { sol::table result = sol().create_table(); int index = 1; for (char32_t code : f.keyboard_codes(which)) result[index++] = code; return result; - }); - ioport_field_type.set("device", sol::property(&ioport_field::device)); - ioport_field_type.set("port", sol::property(&ioport_field::port)); - ioport_field_type.set("name", sol::property(&ioport_field::name)); - ioport_field_type.set("default_name", sol::property([](ioport_field &f) { - return f.specific_name() ? f.specific_name() : f.manager().type_name(f.type(), f.player()); - })); - ioport_field_type.set("player", sol::property(&ioport_field::player, &ioport_field::set_player)); - ioport_field_type.set("mask", sol::property(&ioport_field::mask)); - ioport_field_type.set("defvalue", sol::property(&ioport_field::defvalue)); - ioport_field_type.set("sensitivity", sol::property(&ioport_field::sensitivity)); - ioport_field_type.set("way", sol::property(&ioport_field::way)); - ioport_field_type.set("type_class", sol::property([](ioport_field &f) { - switch (f.type_class()) + }; + ioport_field_type["device"] = sol::property(&ioport_field::device); + ioport_field_type["port"] = sol::property(&ioport_field::port); + ioport_field_type["name"] = sol::property(&ioport_field::name); + ioport_field_type["default_name"] = sol::property( + [] (ioport_field &f) { - case INPUT_CLASS_KEYBOARD: return "keyboard"; - case INPUT_CLASS_CONTROLLER: return "controller"; - case INPUT_CLASS_CONFIG: return "config"; - case INPUT_CLASS_DIPSWITCH: return "dipswitch"; - case INPUT_CLASS_MISC: return "misc"; - default: break; - } - throw false; - })); - ioport_field_type.set("is_analog", sol::property(&ioport_field::is_analog)); - ioport_field_type.set("is_digital_joystick", sol::property(&ioport_field::is_digital_joystick)); - ioport_field_type.set("enabled", sol::property(&ioport_field::enabled)); - ioport_field_type.set("optional", sol::property(&ioport_field::optional)); - ioport_field_type.set("cocktail", sol::property(&ioport_field::cocktail)); - ioport_field_type.set("toggle", sol::property(&ioport_field::toggle)); - ioport_field_type.set("rotated", sol::property(&ioport_field::rotated)); - ioport_field_type.set("analog_reverse", sol::property(&ioport_field::analog_reverse)); - ioport_field_type.set("analog_reset", sol::property(&ioport_field::analog_reset)); - ioport_field_type.set("analog_wraps", sol::property(&ioport_field::analog_wraps)); - ioport_field_type.set("analog_invert", sol::property(&ioport_field::analog_invert)); - ioport_field_type.set("impulse", sol::property(&ioport_field::impulse)); - ioport_field_type.set("type", sol::property(&ioport_field::type)); - ioport_field_type.set("live", sol::property(&ioport_field::live)); - ioport_field_type.set("crosshair_scale", sol::property(&ioport_field::crosshair_scale, &ioport_field::set_crosshair_scale)); - ioport_field_type.set("crosshair_offset", sol::property(&ioport_field::crosshair_offset, &ioport_field::set_crosshair_offset)); - ioport_field_type.set("user_value", sol::property( - [](ioport_field &f) { - ioport_field::user_settings settings; - f.get_user_settings(settings); - return settings.value; - }, - [](ioport_field &f, ioport_value val) { - ioport_field::user_settings settings; - f.get_user_settings(settings); - settings.value = val; - f.set_user_settings(settings); - })); - ioport_field_type.set("settings", sol::property([this](ioport_field &f) { - sol::table result = sol().create_table(); - for (ioport_setting &setting : f.settings()) - if (setting.enabled()) - result[setting.value()] = setting.name(); - return result; - })); + return f.specific_name() ? f.specific_name() : f.manager().type_name(f.type(), f.player()); + }); + ioport_field_type["player"] = sol::property(&ioport_field::player, &ioport_field::set_player); + ioport_field_type["mask"] = sol::property(&ioport_field::mask); + ioport_field_type["defvalue"] = sol::property(&ioport_field::defvalue); + ioport_field_type["sensitivity"] = sol::property(&ioport_field::sensitivity); + ioport_field_type["way"] = sol::property(&ioport_field::way); + ioport_field_type["type_class"] = sol::property( + [] (ioport_field &f) + { + switch (f.type_class()) + { + case INPUT_CLASS_KEYBOARD: return "keyboard"; + case INPUT_CLASS_CONTROLLER: return "controller"; + case INPUT_CLASS_CONFIG: return "config"; + case INPUT_CLASS_DIPSWITCH: return "dipswitch"; + case INPUT_CLASS_MISC: return "misc"; + default: break; + } + throw false; + }); + ioport_field_type["is_analog"] = sol::property(&ioport_field::is_analog); + ioport_field_type["is_digital_joystick"] = sol::property(&ioport_field::is_digital_joystick); + ioport_field_type["enabled"] = sol::property(&ioport_field::enabled); + ioport_field_type["optional"] = sol::property(&ioport_field::optional); + ioport_field_type["cocktail"] = sol::property(&ioport_field::cocktail); + ioport_field_type["toggle"] = sol::property(&ioport_field::toggle); + ioport_field_type["rotated"] = sol::property(&ioport_field::rotated); + ioport_field_type["analog_reverse"] = sol::property(&ioport_field::analog_reverse); + ioport_field_type["analog_reset"] = sol::property(&ioport_field::analog_reset); + ioport_field_type["analog_wraps"] = sol::property(&ioport_field::analog_wraps); + ioport_field_type["analog_invert"] = sol::property(&ioport_field::analog_invert); + ioport_field_type["impulse"] = sol::property(&ioport_field::impulse); + ioport_field_type["type"] = sol::property(&ioport_field::type); + ioport_field_type["live"] = sol::property(&ioport_field::live); + ioport_field_type["crosshair_scale"] = sol::property(&ioport_field::crosshair_scale, &ioport_field::set_crosshair_scale); + ioport_field_type["crosshair_offset"] = sol::property(&ioport_field::crosshair_offset, &ioport_field::set_crosshair_offset); + ioport_field_type["user_value"] = sol::property( + [] (ioport_field &f) + { + ioport_field::user_settings settings; + f.get_user_settings(settings); + return settings.value; + }, + [] (ioport_field &f, ioport_value val) + { + ioport_field::user_settings settings; + f.get_user_settings(settings); + settings.value = val; + f.set_user_settings(settings); + }); + ioport_field_type["settings"] = sol::property( + [this] (ioport_field &f) + { + sol::table result = sol().create_table(); + for (ioport_setting &setting : f.settings()) + if (setting.enabled()) + result[setting.value()] = setting.name(); + return result; + }); /* ioport_field_live library @@ -260,44 +444,79 @@ void lua_engine::initialize_input(sol::table &emu) * live.name */ - sol().registry().new_usertype<ioport_field_live>("ioport_field_live", "new", sol::no_constructor, - "name", &ioport_field_live::name); + auto ioport_field_live_type = sol().registry().new_usertype<ioport_field_live>("ioport_field_live", sol::no_constructor); + ioport_field_live_type["name"] = &ioport_field_live::name; /* input_manager library * * manager:machine():input() * - * input:code_from_token(token) - get input_code for KEYCODE_* string token + * input:code_value(code) - * input:code_pressed(code) - get pressed state for input_code - * input:code_to_token(code) - get KEYCODE_* string token for code + * input:code_pressed_once(code) - * input:code_name(code) - get code friendly name - * input:seq_from_tokens(tokens) - get input_seq for multiple space separated KEYCODE_* string tokens + * input:code_to_token(code) - get KEYCODE_* string token for code + * input:code_from_token(token) - get input_code for KEYCODE_* string token * input:seq_pressed(seq) - get pressed state for input_seq - * input:seq_to_tokens(seq) - get KEYCODE_* string tokens for seq - * input:seq_name(seq) - get seq friendly name * input:seq_clean(seq) - clean the seq and remove invalid elements - * input:seq_poll_start(class, [opt] start_seq) - start polling for input_item_class passed as string - * (switch/abs[olute]/rel[ative]/max[imum]) - * input:seq_poll() - poll once, returns true if input was fetched - * input:seq_poll_final() - get final input_seq - * input.device_classes - returns device classes + * input:seq_name(seq) - get seq friendly name + * input:seq_to_tokens(seq) - get KEYCODE_* string tokens for seq + * input:seq_from_tokens(tokens) - get input_seq for multiple space separated KEYCODE_* string tokens + * input:sequence_poller() - get an input sequence poller + * + * input.device_classes[] - returns device classes (k=name, v=input_device_class) */ - auto input_type = sol().registry().new_usertype<input_manager>("input", "new", sol::no_constructor); - input_type.set("code_from_token", [](input_manager &input, const char *token) { return input.code_from_token(token); }); - input_type.set("code_pressed", [](input_manager &input, const input_code &code) { return input.code_pressed(code); }); - input_type.set("code_to_token", [](input_manager &input, const input_code &code) { return input.code_to_token(code); }); - input_type.set("code_name", [](input_manager &input, const input_code &code) { return input.code_name(code); }); - input_type.set("seq_from_tokens", [](input_manager &input, const char *tokens) { input_seq seq; input.seq_from_tokens(seq, tokens); return seq; }); - input_type.set("seq_pressed", [](input_manager &input, const input_seq &seq) { return input.seq_pressed(seq); }); - input_type.set("seq_to_tokens", [](input_manager &input, const input_seq &seq) { return input.seq_to_tokens(seq); }); - input_type.set("seq_name", [](input_manager &input, const input_seq &seq) { return input.seq_name(seq); }); - input_type.set("seq_clean", [](input_manager &input, const input_seq &seq) { return input.seq_clean(seq); }); - input_type.set("seq_poll_start", [this](input_manager &input, const char *cls_string, sol::object seq) { - if (!m_seq_poll) - m_seq_poll.reset(new input_sequence_poller(input)); + auto input_type = sol().registry().new_usertype<input_manager>("input", sol::no_constructor); + input_type["code_value"] = &input_manager::code_value; + input_type["code_pressed"] = &input_manager::code_pressed; + input_type["code_pressed_once"] = &input_manager::code_pressed_once; + input_type["code_name"] = &input_manager::code_name; + input_type["code_to_token"] = &input_manager::code_to_token; + input_type["code_from_token"] = &input_manager::code_from_token; + input_type["seq_pressed"] = &input_manager::seq_pressed; + input_type["seq_clean"] = &input_manager::seq_clean; + input_type["seq_name"] = &input_manager::seq_name; + input_type["seq_to_tokens"] = &input_manager::seq_to_tokens; + input_type["seq_from_tokens"] = + [] (input_manager &input, const char *tokens) + { + input_seq seq; + input.seq_from_tokens(seq, tokens); + return seq; + }; + input_type["sequence_poller"] = [] (input_manager &input) { return input_sequence_poller(input); }; + input_type["device_classes"] = sol::property( + [this] (input_manager &input) + { + sol::table result = sol().create_table(); + for (input_device_class devclass_id = DEVICE_CLASS_FIRST_VALID; devclass_id <= DEVICE_CLASS_LAST_VALID; devclass_id++) + { + input_class &devclass = input.device_class(devclass_id); + result[devclass.name()] = &devclass; + } + return result; + }); + +/* input_sequence_poller library + * + * manager:machine():input():seq_poll() + * + * poller:start(class, [opt] start_seq) - start polling for input_item_class passed as string + * (switch/abs[olute]/rel[ative]/max[imum]) + * poller:poll() - poll once, returns true if input was fetched + * + * poller.sequence - get current input_seq + * poller.valid - true if input sequence is valid + * poller.modified - true if input sequence was modified + */ + + auto seqpoll_type = sol().registry().new_usertype<input_sequence_poller>("input_seq_poller", sol::no_constructor); + seqpoll_type["start"] = + [this] (input_sequence_poller &poller, char const *cls_string, sol::object seq) + { input_item_class cls; if (!strcmp(cls_string, "switch")) cls = ITEM_CLASS_SWITCH; @@ -311,44 +530,14 @@ void lua_engine::initialize_input(sol::table &emu) cls = ITEM_CLASS_INVALID; if (seq.is<sol::user<input_seq>>()) - m_seq_poll->start(cls, seq.as<sol::user<input_seq>>()); + poller.start(cls, seq.as<input_seq>()); else - m_seq_poll->start(cls); - }); - input_type.set("seq_poll", [this](input_manager &input) -> sol::object { - if (!m_seq_poll) - return sol::make_object(sol(), sol::lua_nil); - return sol::make_object(sol(), m_seq_poll->poll()); - }); - input_type.set("seq_poll_final", [this](input_manager &input) -> sol::object { - if (!m_seq_poll) - return sol::make_object(sol(), sol::lua_nil); - return sol::make_object(sol(), m_seq_poll->valid() ? m_seq_poll->sequence() : input_seq()); - }); - input_type.set("seq_poll_modified", [this](input_manager &input) -> sol::object { - if (!m_seq_poll) - return sol::make_object(sol(), sol::lua_nil); - return sol::make_object(sol(), m_seq_poll->modified()); - }); - input_type.set("seq_poll_valid", [this](input_manager &input) -> sol::object { - if (!m_seq_poll) - return sol::make_object(sol(), sol::lua_nil); - return sol::make_object(sol(), m_seq_poll->valid()); - }); - input_type.set("seq_poll_sequence", [this](input_manager &input) -> sol::object { - if (!m_seq_poll) - return sol::make_object(sol(), sol::lua_nil); - return sol::make_object(sol(), m_seq_poll->sequence()); - }); - input_type.set("device_classes", sol::property([this](input_manager &input) { - sol::table result = sol().create_table(); - for (input_device_class devclass_id = DEVICE_CLASS_FIRST_VALID; devclass_id <= DEVICE_CLASS_LAST_VALID; devclass_id++) - { - input_class &devclass = input.device_class(devclass_id); - result[devclass.name()] = &devclass; - } - return result; - })); + poller.start(cls); + }; + seqpoll_type["poll"] = &input_sequence_poller::poll; + seqpoll_type["sequence"] = sol::property(&input_sequence_poller::sequence); + seqpoll_type["valid"] = sol::property(&input_sequence_poller::valid); + seqpoll_type["modified"] = sol::property(&input_sequence_poller::modified); /* input_class library @@ -362,61 +551,67 @@ void lua_engine::initialize_input(sol::table &emu) */ auto input_class_type = sol().registry().new_usertype<input_class>("input_class", "new", sol::no_constructor); - input_class_type.set("name", sol::property(&input_class::name)); - input_class_type.set("enabled", sol::property(&input_class::enabled, &input_class::enable)); - input_class_type.set("multi", sol::property(&input_class::multi, &input_class::set_multi)); - input_class_type.set("devices", sol::property([this](input_class &devclass) { - sol::table result = sol().create_table(); - int index = 1; - for (int devindex = 0; devindex <= devclass.maxindex(); devindex++) + input_class_type["name"] = sol::property(&input_class::name); + input_class_type["enabled"] = sol::property(&input_class::enabled, &input_class::enable); + input_class_type["multi"] = sol::property(&input_class::multi, &input_class::set_multi); + input_class_type["devices"] = sol::property( + [this] (input_class &devclass) { - input_device *dev = devclass.device(devindex); - if (dev) - result[index++] = dev; - } - return result; - })); + sol::table result = sol().create_table(); + int index = 1; + for (int devindex = 0; devindex <= devclass.maxindex(); devindex++) + { + input_device *dev = devclass.device(devindex); + if (dev) + result[index++] = dev; + } + return result; + }); /* input_device library * * manager:machine():input().device_classes[devclass].devices[index] - * device.name - * device.id - * device.devindex - * device.items[] + * + * device.name - + * device.id - + * device.devindex - + * device.items[] - */ auto input_device_type = sol().registry().new_usertype<input_device>("input_device", "new", sol::no_constructor); - input_device_type.set("name", sol::property(&input_device::name)); - input_device_type.set("id", sol::property(&input_device::id)); - input_device_type.set("devindex", sol::property(&input_device::devindex)); - input_device_type.set("items", sol::property([this](input_device &dev) { - sol::table result = sol().create_table(); - for (input_item_id id = ITEM_ID_FIRST_VALID; id < dev.maxitem(); id++) + input_device_type["name"] = sol::property(&input_device::name); + input_device_type["id"] = sol::property(&input_device::id); + input_device_type["devindex"] = sol::property(&input_device::devindex); + input_device_type["items"] = sol::property( + [this] (input_device &dev) { - input_device_item *item = dev.item(id); - if (item) - result[id] = dev.item(id); - } - return result; - })); + sol::table result = sol().create_table(); + for (input_item_id id = ITEM_ID_FIRST_VALID; id < dev.maxitem(); id++) + { + input_device_item *item = dev.item(id); + if (item) + result[id] = dev.item(id); + } + return result; + }); /* input_device_item library * * manager:machine():input().device_classes[devclass].devices[index].items[item_id] - * item.name - * item.token - * item:code() + * + * item.name - + * item.code - + * item.token - + * item.current - */ auto input_device_item_type = sol().registry().new_usertype<input_device_item>("input_device_item", "new", sol::no_constructor); - input_device_item_type.set("name", sol::property(&input_device_item::name)); - input_device_item_type.set("token", sol::property(&input_device_item::token)); - input_device_item_type.set("code", [](input_device_item &item) { - return input_code(item.device().devclass(), item.device().devindex(), item.itemclass(), ITEM_MODIFIER_NONE, item.itemid()); - }); + input_device_item_type["name"] = sol::property(&input_device_item::name); + input_device_item_type["code"] = sol::property(&input_device_item::code); + input_device_item_type["token"] = sol::property(&input_device_item::token); + input_device_item_type["current"] = sol::property(&input_device_item::current); /* ui_input_manager library |