summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2020-12-09 01:01:22 +1100
committer Vas Crabb <vas@vastheman.com>2020-12-09 01:10:26 +1100
commite008c7b1b1042d644be2a1e177ffa15d53e942c5 (patch)
treed248f9fcbe15563c46c1ae9605d35a19ed4ada5e /src/frontend
parent06568860e7a30424bab61498cd2a8a44889e4412 (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')
-rw-r--r--src/frontend/mame/luaengine.cpp2
-rw-r--r--src/frontend/mame/luaengine.h7
-rw-r--r--src/frontend/mame/luaengine.ipp85
-rw-r--r--src/frontend/mame/luaengine_input.cpp635
-rw-r--r--src/frontend/mame/luaengine_render.cpp82
5 files changed, 500 insertions, 311 deletions
diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp
index e4da280e221..f069497bf6d 100644
--- a/src/frontend/mame/luaengine.cpp
+++ b/src/frontend/mame/luaengine.cpp
@@ -378,8 +378,6 @@ bool lua_engine::menu_callback(const std::string &menu, int index, const std::st
void lua_engine::set_machine(running_machine *machine)
{
- if (!machine || (machine != m_machine))
- m_seq_poll.reset();
m_machine = machine;
}
diff --git a/src/frontend/mame/luaengine.h b/src/frontend/mame/luaengine.h
index 14d47fbf89c..bfcbaf04a50 100644
--- a/src/frontend/mame/luaengine.h
+++ b/src/frontend/mame/luaengine.h
@@ -12,8 +12,6 @@
#pragma once
-#include "iptseqpoll.h"
-
#include <condition_variable>
#include <functional>
#include <map>
@@ -35,10 +33,10 @@ class lua_engine
public:
// helper structures
template <typename T> struct devenum;
- template <typename T, typename C, typename I = typename C::iterator> struct immutable_container_helper;
-
+ template <typename T> struct simple_list_wrapper;
template <typename T> struct tag_object_ptr_map;
template <typename T> using standard_tag_object_ptr_map = tag_object_ptr_map<std::unordered_map<std::string, std::unique_ptr<T> > >;
+ template <typename T, typename C, typename I = typename C::iterator> struct immutable_container_helper;
// construction/destruction
lua_engine();
@@ -146,7 +144,6 @@ private:
lua_State *m_lua_state;
std::unique_ptr<sol::state_view> m_sol_state;
running_machine *m_machine;
- std::unique_ptr<input_sequence_poller> m_seq_poll;
std::vector<std::string> m_menu;
diff --git a/src/frontend/mame/luaengine.ipp b/src/frontend/mame/luaengine.ipp
index 9e5dddc8065..4cd4112bee5 100644
--- a/src/frontend/mame/luaengine.ipp
+++ b/src/frontend/mame/luaengine.ipp
@@ -19,6 +19,15 @@
template <typename T>
+struct lua_engine::simple_list_wrapper
+{
+ simple_list_wrapper(simple_list<T> const &l) : list(l) { }
+
+ simple_list<T> const &list;
+};
+
+
+template <typename T>
struct lua_engine::tag_object_ptr_map
{
tag_object_ptr_map(T const &m) : map(m) { }
@@ -75,15 +84,83 @@ template <> struct is_container<core_options> : std::false_type { };
sol::buffer *sol_lua_get(sol::types<buffer *>, lua_State *L, int index, sol::stack::record &tracking);
int sol_lua_push(sol::types<buffer *>, lua_State *L, buffer *value);
-// lua_engine::devenum customisation
+
+// these things should be treated as containers
template <typename T> struct is_container<lua_engine::devenum<T> > : std::true_type { };
+template <typename T> struct is_container<lua_engine::simple_list_wrapper<T> > : std::true_type { };
+template <typename T> struct is_container<lua_engine::tag_object_ptr_map<T> > : std::true_type { };
+
+
template <typename T> struct usertype_container<lua_engine::devenum<T> >;
-// tag_object_ptr_map is_container
-template <typename T> struct is_container<lua_engine::tag_object_ptr_map<T> > : std::true_type { };
+template <typename T>
+struct usertype_container<lua_engine::simple_list_wrapper<T> > : lua_engine::immutable_container_helper<lua_engine::simple_list_wrapper<T>, simple_list<T> const, typename simple_list<T>::auto_iterator>
+{
+private:
+ static int next_pairs(lua_State *L)
+ {
+ typename usertype_container::indexed_iterator &i(stack::unqualified_get<user<typename usertype_container::indexed_iterator> >(L, 1));
+ if (i.src.end() == i.it)
+ return stack::push(L, lua_nil);
+ int result;
+ result = stack::push(L, i.ix + 1);
+ result += stack::push_reference(L, *i.it);
+ ++i;
+ return result;
+ }
+
+public:
+ static int at(lua_State *L)
+ {
+ lua_engine::simple_list_wrapper<T> &self(usertype_container::get_self(L));
+ std::ptrdiff_t const index(stack::unqualified_get<std::ptrdiff_t>(L, 2));
+ if ((0 >= index) || (self.list.count() < index))
+ return stack::push(L, lua_nil);
+ else
+ return stack::push_reference(L, *self.list.find(index - 1));
+ }
+
+ static int get(lua_State *L) { return at(L); }
+ static int index_get(lua_State *L) { return at(L); }
+
+ static int index_of(lua_State *L)
+ {
+ lua_engine::simple_list_wrapper<T> &self(usertype_container::get_self(L));
+ T &target(stack::unqualified_get<T>(L, 2));
+ int const found(self.list.indexof(target));
+ if (0 > found)
+ return stack::push(L, lua_nil);
+ else
+ return stack::push(L, found + 1);
+ }
+
+ static int size(lua_State *L)
+ {
+ lua_engine::simple_list_wrapper<T> &self(usertype_container::get_self(L));
+ return stack::push(L, self.list.count());
+ }
+
+ static int empty(lua_State *L)
+ {
+ lua_engine::simple_list_wrapper<T> &self(usertype_container::get_self(L));
+ return stack::push(L, self.list.empty());
+ }
+
+ static int next(lua_State *L) { return stack::push(L, next_pairs); }
+ static int pairs(lua_State *L) { return ipairs(L); }
+
+ static int ipairs(lua_State *L)
+ {
+ lua_engine::simple_list_wrapper<T> &self(usertype_container::get_self(L));
+ stack::push(L, next_pairs);
+ stack::push<user<typename usertype_container::indexed_iterator> >(L, self.list, self.list.begin());
+ stack::push(L, lua_nil);
+ return 3;
+ }
+};
+
-// tag_object_ptr_map usertype_container
template <typename T>
struct usertype_container<lua_engine::tag_object_ptr_map<T> > : lua_engine::immutable_container_helper<lua_engine::tag_object_ptr_map<T>, T const, typename T::const_iterator>
{
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
diff --git a/src/frontend/mame/luaengine_render.cpp b/src/frontend/mame/luaengine_render.cpp
index 5df401c9b17..9fff8f4171b 100644
--- a/src/frontend/mame/luaengine_render.cpp
+++ b/src/frontend/mame/luaengine_render.cpp
@@ -33,21 +33,13 @@ struct layout_view_items
layout_view &view;
};
-
-struct render_manager_targets
-{
- render_manager_targets(render_manager &m) : targets(m.targets()) { }
-
- simple_list<render_target> const &targets;
-};
-
} // anonymous namespace
+
namespace sol {
template <> struct is_container<layout_file_views> : std::true_type { };
template <> struct is_container<layout_view_items> : std::true_type { };
-template <> struct is_container<render_manager_targets> : std::true_type { };
template <>
@@ -239,76 +231,6 @@ public:
}
};
-
-template <>
-struct usertype_container<render_manager_targets> : lua_engine::immutable_container_helper<render_manager_targets, simple_list<render_target> const, simple_list<render_target>::auto_iterator>
-{
-private:
- using target_list = simple_list<render_target>;
-
- static int next_pairs(lua_State *L)
- {
- indexed_iterator &i(stack::unqualified_get<user<indexed_iterator> >(L, 1));
- if (i.src.end() == i.it)
- return stack::push(L, lua_nil);
- int result;
- result = stack::push(L, i.ix + 1);
- result += stack::push_reference(L, *i.it);
- ++i.it;
- ++i.ix;
- return result;
- }
-
-public:
- static int at(lua_State *L)
- {
- render_manager_targets &self(get_self(L));
- std::ptrdiff_t const index(stack::unqualified_get<std::ptrdiff_t>(L, 2));
- if ((0 >= index) || (self.targets.count() < index))
- return stack::push(L, lua_nil);
- else
- return stack::push_reference(L, *self.targets.find(index - 1));
- }
-
- static int get(lua_State *L) { return at(L); }
- static int index_get(lua_State *L) { return at(L); }
-
- static int index_of(lua_State *L)
- {
- render_manager_targets &self(get_self(L));
- render_target &target(stack::unqualified_get<render_target>(L, 2));
- int const found(self.targets.indexof(target));
- if (0 > found)
- return stack::push(L, lua_nil);
- else
- return stack::push(L, found + 1);
- }
-
- static int size(lua_State *L)
- {
- render_manager_targets &self(get_self(L));
- return stack::push(L, self.targets.count());
- }
-
- static int empty(lua_State *L)
- {
- render_manager_targets &self(get_self(L));
- return stack::push(L, self.targets.empty());
- }
-
- static int next(lua_State *L) { return stack::push(L, next_pairs); }
- static int pairs(lua_State *L) { return ipairs(L); }
-
- static int ipairs(lua_State *L)
- {
- render_manager_targets &self(get_self(L));
- stack::push(L, next_pairs);
- stack::push<user<indexed_iterator> >(L, self.targets, self.targets.begin());
- stack::push(L, lua_nil);
- return 3;
- }
-};
-
} // namespace sol
@@ -619,6 +541,6 @@ void lua_engine::initialize_render(sol::table &emu)
render_type["max_update_rate"] = &render_manager::max_update_rate;
render_type["ui_target"] = &render_manager::ui_target;
render_type["ui_container"] = &render_manager::ui_container;
- render_type["targets"] = sol::property([] (render_manager &m) { return render_manager_targets(m); });
+ render_type["targets"] = sol::property([] (render_manager &m) { return simple_list_wrapper<render_target>(m.targets()); });
}