mirror of
https://github.com/holub/mame
synced 2025-07-02 08:39:21 +03:00
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:
parent
075a8929c6
commit
017f4e485a
@ -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");
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user