From cc9335eea6724a42d89e343d6a204ea1cdd7b15d Mon Sep 17 00:00:00 2001 From: Alex Forsythe Date: Fri, 3 May 2019 21:51:07 -0500 Subject: [PATCH] Add Lua function gui.setlayermask This change adds a Lua function called gui.setlayermask, which allows Lua scripts to procedurally modify which render layers are visible. It takes two arguments: one integer bitfield representing the visibility states for the main GPU, and the other representing the sub GPU. For example: 0b11111 shows all layers, 0b00000 hides all layers, 0b00001 shows only layer 0 (BG0), 0b10000 shows only layer 5 (OBJ), etc. Since display layer state is coupled to the frontend, and since frontends are entirely separate between platforms (i.e., on Windows, toggling display layer state requires updating the GUI state asl well), this function is only supported and tested on the Windows build. On MacOS and Linux, gui.setlayermask will simply return 0 without doing anything. --- desmume/src/frontend/windows/display.cpp | 25 ++++++++++++++++++++++++ desmume/src/frontend/windows/display.h | 1 + desmume/src/lua-engine.cpp | 18 ++++++++++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/desmume/src/frontend/windows/display.cpp b/desmume/src/frontend/windows/display.cpp index a538bb336..ce5c04d2d 100644 --- a/desmume/src/frontend/windows/display.cpp +++ b/desmume/src/frontend/windows/display.cpp @@ -968,3 +968,28 @@ void TwiddleLayer(UINT ctlid, int core, int layer) gpu->SetLayerEnableState(layer, newLayerState); MainWindow->checkMenu(ctlid, newLayerState); } + +void SetLayerMasks(int mainEngineMask, int subEngineMask) +{ + static const size_t numCores = sizeof(CommonSettings.dispLayers) / sizeof(CommonSettings.dispLayers[0]); + static const size_t numLayers = sizeof(CommonSettings.dispLayers[0]) / sizeof(CommonSettings.dispLayers[0][0]); + static const UINT ctlids[numCores][numLayers] = { + {IDM_MBG0, IDM_MBG1, IDM_MBG2, IDM_MBG3, IDM_MOBJ}, + {IDM_SBG0, IDM_SBG1, IDM_SBG2, IDM_SBG3, IDM_SOBJ}, + }; + + for (int core = 0; core < 2; core++) + { + GPUEngineBase *gpu = (GPUEngineID)core == GPUEngineID_Main ? (GPUEngineBase *)GPU->GetEngineMain() : (GPUEngineBase *)GPU->GetEngineSub(); + const int mask = core == 0 ? mainEngineMask : subEngineMask; + for (size_t layer = 0; layer < numLayers; layer++) + { + const bool newLayerState = (mask >> layer) & 0x01 != 0; + if (newLayerState != CommonSettings.dispLayers[core][layer]) + { + gpu->SetLayerEnableState(layer, newLayerState); + MainWindow->checkMenu(ctlids[core][layer], newLayerState); + } + } + } +} diff --git a/desmume/src/frontend/windows/display.h b/desmume/src/frontend/windows/display.h index ea3662bf5..1c099c06e 100644 --- a/desmume/src/frontend/windows/display.h +++ b/desmume/src/frontend/windows/display.h @@ -105,5 +105,6 @@ FORCEINLINE void ServiceDisplayThreadInvocations() void UpdateWndRects(HWND hwnd, RECT* newClientRect = NULL); void TwiddleLayer(UINT ctlid, int core, int layer); +void SetLayerMasks(int mainEngineMask, int subEngineMask); #endif \ No newline at end of file diff --git a/desmume/src/lua-engine.cpp b/desmume/src/lua-engine.cpp index a75fdbef2..92527117f 100644 --- a/desmume/src/lua-engine.cpp +++ b/desmume/src/lua-engine.cpp @@ -28,6 +28,7 @@ #include "frontend/windows/main.h" #include "frontend/windows/video.h" #include "frontend/windows/resource.h" + #include "frontend/windows/display.h" #else // TODO: define appropriate types for menu typedef void* PlatformMenu; @@ -3278,6 +3279,20 @@ DEFINE_LUA_FUNCTION(gui_settransparency, "transparency_4_to_0") return 0; } +// gui.setlayermask(int top, int bottom) +// enables or disables display layers for each screen according to the bitfields provided +// e.g. 31 (11111) shows all layers; 0 (00000) hides all layers; 16 (10000) shows only the object layer (layer 4) +// this function is only supported by the windows frontend. +DEFINE_LUA_FUNCTION(gui_setlayermask, "top,bottom") +{ +#if defined(WIN32) + lua_Integer top = luaL_checkint(L, 1); + lua_Integer bottom = luaL_checkint(L, 2); + SetLayerMasks(top, bottom); +#endif + return 0; +} + // takes a screenshot and returns it in gdstr format // example: gd.createFromGdStr(gui.gdscreenshot()):png("outputimage.png") DEFINE_LUA_FUNCTION(gui_gdscreenshot, "[whichScreen='both']") @@ -3849,7 +3864,7 @@ DEFINE_LUA_FUNCTION(emu_registermenustart, "func") DEFINE_LUA_FUNCTION(emu_set3dtransform, "mode, matrix") { - extern int freelookMode; + extern int freelookMode; extern s32 freelookMatrix[16]; int mode = luaL_checkinteger(L,1); @@ -4861,6 +4876,7 @@ static const struct luaL_reg guilib [] = {"transparency", gui_settransparency}, {"popup", gui_popup}, {"parsecolor", gui_parsecolor}, + {"setlayermask", gui_setlayermask}, {"gdscreenshot", gui_gdscreenshot}, {"gdoverlay", gui_gdoverlay}, {"redraw", emu_redraw}, // some people might think of this as more of a GUI function