luaengine: add screen drawing/HUD capabilities

This commit allows LUA scripts to implement HUD capabilities,
by overlaying elements (lines, boxes, text) to screen.
Mostly used to draw custom graphic helpers for trainings and
TAS runs development.

Signed-off-by: Luca Bruno <lucab@debian.org>
This commit is contained in:
Luca Bruno 2014-12-25 19:10:11 +01:00
parent 075a8929c6
commit 017f4e485a
2 changed files with 141 additions and 1 deletions

View File

@ -17,6 +17,7 @@
#include "emuopts.h"
#include "osdepend.h"
#include "drivenum.h"
#include "ui/ui.h"
#include "web/mongoose.h"
//**************************************************************************
@ -336,6 +337,26 @@ int lua_engine::l_emu_hook_output(lua_State *L)
return 0;
}
//-------------------------------------------------
// machine_get_screens - return table of available screens userdata
// -> manager:machine().screens[":screen"]
//-------------------------------------------------
luabridge::LuaRef lua_engine::l_machine_get_screens(const running_machine *r)
{
lua_State *L = luaThis->m_lua_state;
luabridge::LuaRef screens_table = luabridge::LuaRef::newTable(L);
for (device_t *dev = r->first_screen(); dev != NULL; dev = dev->next()) {
screen_device *sc = dynamic_cast<screen_device *>(dev);
if (sc && sc->configured() && sc->started() && sc->type()) {
screens_table[sc->tag()] = sc;
}
}
return screens_table;
}
//-------------------------------------------------
// machine_get_devices - return table of available devices userdata
// -> manager:machine().devices[":maincpu"]
@ -438,6 +459,108 @@ int lua_engine::lua_addr_space::l_mem_read(lua_State *L)
}
//-------------------------------------------------
// draw_box - draw a box on a screen container
// -> manager:machine().screens[":screen"]:draw_box(x1, y1, x2, y2, bgcolor, linecolor)
//-------------------------------------------------
int lua_engine::lua_screen::l_draw_box(lua_State *L)
{
screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1);
if(!sc) {
return 0;
}
// ensure that we got 6 numerical parameters
luaL_argcheck(L, lua_isnumber(L, 2), 2, "x1 (integer) expected");
luaL_argcheck(L, lua_isnumber(L, 3), 3, "y1 (integer) expected");
luaL_argcheck(L, lua_isnumber(L, 4), 4, "x2 (integer) expected");
luaL_argcheck(L, lua_isnumber(L, 5), 5, "y2 (integer) expected");
luaL_argcheck(L, lua_isnumber(L, 6), 6, "background color (integer) expected");
luaL_argcheck(L, lua_isnumber(L, 7), 7, "outline color (integer) expected");
// retrieve all parameters
float x1, y1, x2, y2;
x1 = MIN(lua_tounsigned(L, 2) / static_cast<float>(sc->width()) , 1.0f);
y1 = MIN(lua_tounsigned(L, 3) / static_cast<float>(sc->height()), 1.0f);
x2 = MIN(lua_tounsigned(L, 4) / static_cast<float>(sc->width()) , 1.0f);
y2 = MIN(lua_tounsigned(L, 5) / static_cast<float>(sc->height()), 1.0f);
UINT32 bgcolor = lua_tounsigned(L, 6);
UINT32 fgcolor = lua_tounsigned(L, 7);
// draw the box
render_container &rc = sc->container();
ui_manager &ui = sc->machine().ui();
ui.draw_outlined_box(&rc, x1, y1, x2, y2, fgcolor, bgcolor);
return 0;
}
//-------------------------------------------------
// draw_line - draw a line on a screen container
// -> manager:machine().screens[":screen"]:draw_line(x1, y1, x2, y2, linecolor)
//-------------------------------------------------
int lua_engine::lua_screen::l_draw_line(lua_State *L)
{
screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1);
if(!sc) {
return 0;
}
// ensure that we got 5 numerical parameters
luaL_argcheck(L, lua_isnumber(L, 2), 2, "x1 (integer) expected");
luaL_argcheck(L, lua_isnumber(L, 3), 3, "y1 (integer) expected");
luaL_argcheck(L, lua_isnumber(L, 4), 4, "x2 (integer) expected");
luaL_argcheck(L, lua_isnumber(L, 5), 5, "y2 (integer) expected");
luaL_argcheck(L, lua_isnumber(L, 6), 6, "color (integer) expected");
// retrieve all parameters
float x1, y1, x2, y2;
x1 = MIN(lua_tounsigned(L, 2) / static_cast<float>(sc->width()) , 1.0f);
y1 = MIN(lua_tounsigned(L, 3) / static_cast<float>(sc->height()), 1.0f);
x2 = MIN(lua_tounsigned(L, 4) / static_cast<float>(sc->width()) , 1.0f);
y2 = MIN(lua_tounsigned(L, 5) / static_cast<float>(sc->height()), 1.0f);
UINT32 color = lua_tounsigned(L, 6);
// draw the line
sc->container().add_line(x1, y1, x2, y2, UI_LINE_WIDTH, rgb_t(color), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
return 0;
}
//-------------------------------------------------
// draw_text - draw text on a screen container
// -> manager:machine().screens[":screen"]:draw_text(x, y, message)
//-------------------------------------------------
int lua_engine::lua_screen::l_draw_text(lua_State *L)
{
screen_device *sc = luabridge::Stack<screen_device *>::get(L, 1);
if(!sc) {
return 0;
}
// ensure that we got proper parameters
luaL_argcheck(L, lua_isnumber(L, 2), 2, "x (integer) expected");
luaL_argcheck(L, lua_isnumber(L, 3), 3, "y (integer) expected");
luaL_argcheck(L, lua_isstring(L, 4), 4, "message (string) expected");
// retrieve all parameters
float x = MIN(lua_tounsigned(L, 2) / static_cast<float>(sc->width()) , 1.0f);
float y = MIN(lua_tounsigned(L, 3) / static_cast<float>(sc->height()), 1.0f);
const char *msg = luaL_checkstring(L,4);
// TODO: add optional parameters (colors, etc.)
// draw the text
render_container &rc = sc->container();
ui_manager &ui = sc->machine().ui();
ui.draw_text_full(&rc, msg, x, y , (1.0f - x),
JUSTIFY_LEFT, WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR,
UI_TEXT_BG_COLOR, NULL, NULL);
return 0;
}
void *lua_engine::checkparam(lua_State *L, int idx, const char *tname)
{
const char *name;
@ -667,6 +790,7 @@ void lua_engine::initialize()
.addFunction ("soft_reset", &running_machine::schedule_soft_reset)
.addFunction ("system", &running_machine::system)
.addProperty <luabridge::LuaRef, void> ("devices", &lua_engine::l_machine_get_devices)
.addProperty <luabridge::LuaRef, void> ("screens", &lua_engine::l_machine_get_screens)
.endClass ()
.beginClass <game_driver> ("game_driver")
.addData ("name", &game_driver::name)
@ -691,7 +815,17 @@ void lua_engine::initialize()
.deriveClass <address_space, lua_addr_space> ("addr_space")
.addFunction("name", &address_space::name)
.endClass()
.endNamespace ();
.beginClass <lua_screen> ("lua_screen_dev")
.addCFunction ("draw_box", &lua_screen::l_draw_box)
.addCFunction ("draw_line", &lua_screen::l_draw_line)
.addCFunction ("draw_text", &lua_screen::l_draw_text)
.endClass()
.deriveClass <screen_device, lua_screen> ("screen_dev")
.addFunction ("name", &screen_device::name)
.addFunction ("height", &screen_device::height)
.addFunction ("width", &screen_device::width)
.endClass()
.endNamespace();
luabridge::push (m_lua_state, machine_manager::instance());
lua_setglobal(m_lua_state, "manager");

View File

@ -105,6 +105,12 @@ private:
struct lua_addr_space {
template<typename T> int l_mem_read(lua_State *L);
};
static luabridge::LuaRef l_machine_get_screens(const running_machine *r);
struct lua_screen {
int l_draw_box(lua_State *L);
int l_draw_line(lua_State *L);
int l_draw_text(lua_State *L);
};
void resume(void *L, INT32 param);
void report_errors(int status);