diff options
-rw-r--r-- | plugins/dummy/init.lua | 11 | ||||
-rw-r--r-- | scripts/src/emu.lua | 2 | ||||
-rw-r--r-- | src/emu/luaengine.cpp | 86 | ||||
-rw-r--r-- | src/emu/luaengine.h | 13 | ||||
-rw-r--r-- | src/emu/ui/mainmenu.cpp | 8 | ||||
-rw-r--r-- | src/emu/ui/mainmenu.h | 1 | ||||
-rw-r--r-- | src/emu/ui/pluginopt.cpp | 100 | ||||
-rw-r--r-- | src/emu/ui/pluginopt.h | 38 |
8 files changed, 257 insertions, 2 deletions
diff --git a/plugins/dummy/init.lua b/plugins/dummy/init.lua index 3ef8fe3fc0b..8058bcad452 100644 --- a/plugins/dummy/init.lua +++ b/plugins/dummy/init.lua @@ -17,6 +17,17 @@ function dummy.startplugin() emu.register_stop(function() print("Exiting " .. emu.gamename()) end) + + local function menu_populate() + return {{ "This is a", "test", 32 }, { "Also a", "test", 0 }} -- 32 is MENU_FLAG_DISABLE + end + + local function menu_callback(index, event) + print("index: " .. index .. " event: " .. event) + return false + end + + emu.register_menu(menu_callback, menu_populate, "Dummy") end return exports diff --git a/scripts/src/emu.lua b/scripts/src/emu.lua index e2fe63f5e10..ca3103422a5 100644 --- a/scripts/src/emu.lua +++ b/scripts/src/emu.lua @@ -216,6 +216,8 @@ files { MAME_DIR .. "src/emu/ui/barcode.h", MAME_DIR .. "src/emu/ui/cheatopt.cpp", MAME_DIR .. "src/emu/ui/cheatopt.h", + MAME_DIR .. "src/emu/ui/pluginopt.cpp", + MAME_DIR .. "src/emu/ui/pluginopt.h", MAME_DIR .. "src/emu/ui/devopt.cpp", MAME_DIR .. "src/emu/ui/devopt.h", MAME_DIR .. "src/emu/ui/filemngr.cpp", diff --git a/src/emu/luaengine.cpp b/src/emu/luaengine.cpp index 8de543669d2..ce170910c5c 100644 --- a/src/emu/luaengine.cpp +++ b/src/emu/luaengine.cpp @@ -1274,6 +1274,82 @@ lua_engine::~lua_engine() close(); } +std::vector<lua_engine::menu_item> &lua_engine::menu_populate(std::string &menu) +{ + std::vector<menu_item> &menu_list = *global_alloc(std::vector<menu_item>); + std::string field = "menu_pop_" + menu; + lua_settop(m_lua_state, 0); + lua_getfield(m_lua_state, LUA_REGISTRYINDEX, field.c_str()); + + if(!lua_isfunction(m_lua_state, -1)) + { + lua_pop(m_lua_state, 1); + return menu_list; + } + lua_pcall(m_lua_state, 0, 1, 0); + if(!lua_istable(m_lua_state, -1)) + { + lua_pop(m_lua_state, 1); + return menu_list; + } + + lua_pushnil(m_lua_state); + while(lua_next(m_lua_state, -2)) + { + if(lua_istable(m_lua_state, -1)) + { + menu_item item; + lua_rawgeti(m_lua_state, -1, 1); + item.text = lua_tostring(m_lua_state, -1); + lua_pop(m_lua_state, 1); + lua_rawgeti(m_lua_state, -1, 2); + item.subtext = lua_tostring(m_lua_state, -1); + lua_pop(m_lua_state, 1); + lua_rawgeti(m_lua_state, -1, 3); + item.flags = lua_tointeger(m_lua_state, -1); + lua_pop(m_lua_state, 1); + menu_list.push_back(item); + } + lua_pop(m_lua_state, 1); + } + lua_pop(m_lua_state, 1); + return menu_list; +} + +bool lua_engine::menu_callback(std::string &menu, int index, std::string event) +{ + std::string field = "menu_cb_" + menu; + bool ret = false; + lua_settop(m_lua_state, 0); + lua_getfield(m_lua_state, LUA_REGISTRYINDEX, field.c_str()); + + if(lua_isfunction(m_lua_state, -1)) + { + lua_pushinteger(m_lua_state, index); + lua_pushstring(m_lua_state, event.c_str()); + lua_pcall(m_lua_state, 2, 1, 0); + ret = lua_toboolean(m_lua_state, -1); + lua_pop(m_lua_state, 1); + } + return ret; +} + +int lua_engine::l_emu_register_menu(lua_State *L) +{ + luaL_argcheck(L, lua_isfunction(L, 1), 1, "callback function expected"); + luaL_argcheck(L, lua_isfunction(L, 2), 2, "callback function expected"); + luaL_argcheck(L, lua_isstring(L, 3), 3, "message (string) expected"); + std::string name = luaL_checkstring(L, 3); + std::string cbfield = "menu_cb_" + name; + std::string popfield = "menu_pop_" + name; + luaThis->m_menu.push_back(std::string(name)); + lua_pushvalue(L, 1); + lua_setfield(L, LUA_REGISTRYINDEX, cbfield.c_str()); + lua_pushvalue(L, 2); + lua_setfield(L, LUA_REGISTRYINDEX, popfield.c_str()); + return 1; +} + void lua_engine::execute_function(const char *id) { lua_settop(m_lua_state, 0); @@ -1286,7 +1362,12 @@ void lua_engine::execute_function(const char *id) { if (lua_isfunction(m_lua_state, -1)) { - lua_pcall(m_lua_state, 0, 0, 0); + if(int error = lua_pcall(m_lua_state, 0, 0, 0)) + { + if(error == 2) + printf("%s\n", lua_tostring(m_lua_state, -1)); + lua_pop(m_lua_state, 1); + } } else { @@ -1453,7 +1534,8 @@ void lua_engine::initialize() .addCFunction ("register_pause", l_emu_register_pause ) .addCFunction ("register_resume",l_emu_register_resume ) .addCFunction ("register_frame", l_emu_register_frame ) - .beginClass <machine_manager> ("manager") + .addCFunction ("register_menu", l_emu_register_menu ) + .beginClass <machine_manager> ("manager") .addFunction ("machine", &machine_manager::machine) .addFunction ("options", &machine_manager::options) .addFunction ("plugins", &machine_manager::plugins) diff --git a/src/emu/luaengine.h b/src/emu/luaengine.h index b98b9597b56..1ed1c82df36 100644 --- a/src/emu/luaengine.h +++ b/src/emu/luaengine.h @@ -49,9 +49,19 @@ public: bool frame_hook(); void execute_function(const char *id); + struct menu_item { + std::string text; + std::string subtext; + int flags; + }; + std::vector<menu_item> &menu_populate(std::string &menu); + bool menu_callback(std::string &menu, int index, std::string event); + void resume(lua_State *L, int nparam = 0, lua_State *root = nullptr); void set_machine(running_machine *machine) { m_machine = machine; update_machine(); } + std::vector<std::string> &get_menu() { return m_menu; } void attach_notifiers(); + private: struct hook { lua_State *L; @@ -70,6 +80,8 @@ private: lua_State *m_lua_state; running_machine * m_machine; + std::vector<std::string> m_menu; + hook hook_output_cb; bool output_notifier_set; @@ -121,6 +133,7 @@ private: static int l_emu_register_pause(lua_State *L); static int l_emu_register_resume(lua_State *L); static int l_emu_register_frame(lua_State *L); + static int l_emu_register_menu(lua_State *L); static int register_function(lua_State *L, const char *id); // "emu.machine" namespace diff --git a/src/emu/ui/mainmenu.cpp b/src/emu/ui/mainmenu.cpp index 7fe16d771b0..33156e21ec2 100644 --- a/src/emu/ui/mainmenu.cpp +++ b/src/emu/ui/mainmenu.cpp @@ -33,6 +33,7 @@ #include "ui/datfile.h" #include "ui/inifile.h" #include "ui/datmenu.h" +#include "ui/pluginopt.h" /*************************************************************************** @@ -131,6 +132,9 @@ void ui_menu_main::populate() if (machine().options().cheat()) item_append(_("Cheat"), nullptr, 0, (void *)CHEAT); + if (machine().options().plugins()) + item_append(_("Plugin Options"), nullptr, 0, (void *)PLUGINS); + // add dats menu if (machine().ui().options().enabled_dats() && machine().datfile().has_data()) item_append(_("External DAT View"), nullptr, 0, (void *)EXTERNAL_DATS); @@ -241,6 +245,10 @@ void ui_menu_main::handle() ui_menu::stack_push(global_alloc_clear<ui_menu_cheat>(machine(), container)); break; + case PLUGINS: + ui_menu::stack_push(global_alloc_clear<ui_menu_plugin>(machine(), container)); + break; + case SELECT_GAME: if (strcmp(machine().options().ui(),"simple")==0) { ui_menu::stack_push(global_alloc_clear<ui_simple_menu_select_game>(machine(), container, nullptr)); diff --git a/src/emu/ui/mainmenu.h b/src/emu/ui/mainmenu.h index 0684e230ad8..cb12e6e1d1a 100644 --- a/src/emu/ui/mainmenu.h +++ b/src/emu/ui/mainmenu.h @@ -42,6 +42,7 @@ private: VIDEO_OPTIONS, CROSSHAIR, CHEAT, + PLUGINS, SELECT_GAME, BIOS_SELECTION, BARCODE_READ, diff --git a/src/emu/ui/pluginopt.cpp b/src/emu/ui/pluginopt.cpp new file mode 100644 index 00000000000..625d60600f1 --- /dev/null +++ b/src/emu/ui/pluginopt.cpp @@ -0,0 +1,100 @@ +// license:BSD-3-Clause +// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods +/********************************************************************* + + ui/pluginopt.cpp + + Internal menu for the plugin interface. + +*********************************************************************/ + +#include "emu.h" +#include "luaengine.h" + +#include "ui/pluginopt.h" + +void ui_menu_plugin::handle() +{ + const ui_menu_event *menu_event = process(0); + + if (menu_event != nullptr && menu_event->itemref != nullptr) + { + if (menu_event->iptkey == IPT_UI_SELECT) + ui_menu::stack_push(global_alloc_clear<ui_menu_plugin_opt>(machine(), container, (char *)menu_event->itemref)); + } +} + +ui_menu_plugin::ui_menu_plugin(running_machine &machine, render_container *container) : + ui_menu(machine, container), + m_plugins(machine.manager().lua()->get_menu()) +{ +} + +void ui_menu_plugin::populate() +{ + for (auto &curplugin : m_plugins) + item_append(curplugin.c_str(), 0, 0, (void *)curplugin.c_str()); + item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr); +} + +ui_menu_plugin::~ui_menu_plugin() +{ +} + +ui_menu_plugin_opt::ui_menu_plugin_opt(running_machine &machine, render_container *container, char *menu) : + ui_menu(machine, container), + m_menu(menu) +{ +} + +void ui_menu_plugin_opt::handle() +{ + const ui_menu_event *menu_event = process(0); + + if (menu_event != nullptr && (FPTR)menu_event->itemref) + { + std::string key; + switch(menu_event->iptkey) + { + case IPT_UI_UP: + key = "up"; + break; + case IPT_UI_DOWN: + key = "down"; + break; + case IPT_UI_LEFT: + key = "left"; + break; + case IPT_UI_RIGHT: + key = "right"; + break; + case IPT_UI_SELECT: + key = "select"; + break; + case IPT_UI_DISPLAY_COMMENT: + key = "comment"; + break; + case IPT_UI_CLEAR: + key = "clear"; + break; + default: + return; + } + if(machine().manager().lua()->menu_callback(m_menu, (FPTR)menu_event->itemref, key)) + reset(UI_MENU_RESET_REMEMBER_REF); + } +} + +void ui_menu_plugin_opt::populate() +{ + std::vector<lua_engine::menu_item> &menu_list = machine().manager().lua()->menu_populate(m_menu); + FPTR i = 1; + for(auto &item : menu_list) + item_append(item.text.c_str(), item.subtext.c_str(), item.flags, (void *)i++); + item_append(MENU_SEPARATOR_ITEM, nullptr, 0, nullptr); + global_free(&menu_list); +} + +ui_menu_plugin_opt::~ui_menu_plugin_opt() +{ +} diff --git a/src/emu/ui/pluginopt.h b/src/emu/ui/pluginopt.h new file mode 100644 index 00000000000..9d529e93749 --- /dev/null +++ b/src/emu/ui/pluginopt.h @@ -0,0 +1,38 @@ +// license:BSD-3-Clause +// copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods, Carl +/*************************************************************************** + + ui/pluginopt.h + + Internal menu for the plugin interface. + +***************************************************************************/ + +#pragma once + +#ifndef __UI_PLUGINOPT_H__ +#define __UI_PLUGINOPT_H__ + +#include "ui/ui.h" +#include "ui/menu.h" + +class ui_menu_plugin : public ui_menu { +public: + ui_menu_plugin(running_machine &machine, render_container *container); + virtual ~ui_menu_plugin(); + virtual void populate() override; + virtual void handle() override; +private: + std::vector<std::string> &m_plugins; +}; + +class ui_menu_plugin_opt : public ui_menu { +public: + ui_menu_plugin_opt(running_machine &machine, render_container *container, char *menu); + virtual ~ui_menu_plugin_opt(); + virtual void populate() override; + virtual void handle() override; +private: + std::string m_menu; +}; +#endif /* __UI_PLUGINOPT_H__ */ |