luaengine: add plugin options menu [Carl]

This commit is contained in:
cracyc 2016-04-04 18:17:18 -05:00
parent 0d217bb97c
commit 817f19fcc1
8 changed files with 257 additions and 2 deletions

View File

@ -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

View File

@ -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",

View File

@ -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)

View File

@ -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

View File

@ -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));

View File

@ -42,6 +42,7 @@ private:
VIDEO_OPTIONS,
CROSSHAIR,
CHEAT,
PLUGINS,
SELECT_GAME,
BIOS_SELECTION,
BARCODE_READ,

100
src/emu/ui/pluginopt.cpp Normal file
View File

@ -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()
{
}

38
src/emu/ui/pluginopt.h Normal file
View File

@ -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__ */