diff --git a/src/BizHawk.Client.Common/Api/Classes/GuiApi.cs b/src/BizHawk.Client.Common/Api/Classes/GuiApi.cs index ce448247e00..b9d164be73e 100644 --- a/src/BizHawk.Client.Common/Api/Classes/GuiApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/GuiApi.cs @@ -140,9 +140,20 @@ public void DrawNew(string name, bool clear) public void AddMessage(string message, [LiteralExpected] int? duration = null) => _dialogController.AddOnScreenMessage(message, duration); - public void ClearGraphics(DisplaySurfaceID? surfaceID = null) => Get2DRenderer(surfaceID).Clear(); + public void ClearGraphics(DisplaySurfaceID? surfaceID = null) => LogCallback("the `ClearGraphics()` function has been deprecated; use `Draw()`\n"); - public void ClearText() => _displayManager.OSD.ClearGuiText(); + public void ClearText() => LogCallback("the `ClearText()` function has been deprecated; use `Draw()`\n"); + + public void Draw() + { + _displayManager.DiscardApiHawkSurfaces(); + _displayManager.ClearApiHawkSurfaces(); + _displayManager.OnDraw?.Invoke(); + } + + public void AddDrawCallback(Action callback) => _displayManager.OnDraw += callback; + + public void RemoveDrawCallback(Action callback) => _displayManager.OnDraw -= callback; public void SetDefaultForegroundColor(Color color) => _defaultForeground = color; diff --git a/src/BizHawk.Client.Common/Api/Interfaces/IGuiApi.cs b/src/BizHawk.Client.Common/Api/Interfaces/IGuiApi.cs index a2c3311037a..27e336ec012 100644 --- a/src/BizHawk.Client.Common/Api/Interfaces/IGuiApi.cs +++ b/src/BizHawk.Client.Common/Api/Interfaces/IGuiApi.cs @@ -33,8 +33,24 @@ public interface IGuiApi : IDisposable, IExternalApi void AddMessage(string message, int? duration = null); + [Obsolete("use Draw and AddDrawCallback instead")] void ClearGraphics(DisplaySurfaceID? surfaceID = null); + + [Obsolete("use Draw and AddDrawCallback instead")] void ClearText(); + + /// + /// Clears all prior drawings and calls any actions given to . + /// This should only be used when you want to redraw while paused. + /// + void Draw(); + + /// + /// The given action will be called before each API draw. This means after each frame and any time is called. + /// + void AddDrawCallback(Action callback); + void RemoveDrawCallback(Action callback); + void SetDefaultForegroundColor(Color color); void SetDefaultBackgroundColor(Color color); Color GetDefaultTextBackground(); diff --git a/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs b/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs index 5a30295c011..ee5a82cf8b2 100644 --- a/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs +++ b/src/BizHawk.Client.Common/DisplayManager/DisplayManagerBase.cs @@ -51,6 +51,8 @@ public DisplayManagerRenderTargetProvider(Func callback) public SnowyNullVideo SnowyVP { get; private set; } + public Action/*?*/ OnDraw; + protected DisplayManagerBase( Config config, IEmulator emulator, @@ -961,12 +963,16 @@ public I2DRenderer GetApiHawk2DRenderer(DisplaySurfaceID surfaceID) ? _apiHawkIDTo2DRenderer.GetValueOrPut(surfaceID, _ => _gl.Create2DRenderer(_imGuiResourceCache)) : throw new ArgumentOutOfRangeException(paramName: nameof(surfaceID), surfaceID, message: "invalid surface ID"); + /// + /// Clear stuff drawn by the gui API + /// public void ClearApiHawkSurfaces() { foreach (var renderer in _apiHawkIDTo2DRenderer.Values) { renderer.Clear(); } + OSD.ClearApiHawkText(); } public void DiscardApiHawkSurfaces() diff --git a/src/BizHawk.Client.Common/DisplayManager/OSDManager.cs b/src/BizHawk.Client.Common/DisplayManager/OSDManager.cs index 1ab1aec2b0c..1a0d5ac6130 100644 --- a/src/BizHawk.Client.Common/DisplayManager/OSDManager.cs +++ b/src/BizHawk.Client.Common/DisplayManager/OSDManager.cs @@ -120,7 +120,7 @@ public void AddGuiText(string message, MessagePosition pos, Color backGround, Co }); } - public void ClearGuiText() + public void ClearApiHawkText() => _guiTextList.Clear(); private void DrawMessage(IBlitter g, UIMessage message, int yOffset) diff --git a/src/BizHawk.Client.Common/lua/NamedLuaFunction.cs b/src/BizHawk.Client.Common/lua/NamedLuaFunction.cs index bf665b0b826..84d06748dfe 100644 --- a/src/BizHawk.Client.Common/lua/NamedLuaFunction.cs +++ b/src/BizHawk.Client.Common/lua/NamedLuaFunction.cs @@ -28,6 +28,8 @@ public sealed class NamedLuaFunction : INamedLuaFunction public const string EVENT_TYPE_FUTURE = "BeforeFutureFrame"; + public const string EVENT_TYPE_DRAW = "OnDraw"; + private readonly LuaFunction _function; private readonly ILuaLibraries _luaImp; diff --git a/src/BizHawk.Client.EmuHawk/MainForm.cs b/src/BizHawk.Client.EmuHawk/MainForm.cs index fa4b8d800b5..bfc8ea66a4f 100644 --- a/src/BizHawk.Client.EmuHawk/MainForm.cs +++ b/src/BizHawk.Client.EmuHawk/MainForm.cs @@ -2935,8 +2935,8 @@ private void StepRunLoop_Core(bool force = false) _lastFastForwardingOrRewinding = isFastForwardingOrRewinding; - // client input-related duties - OSD.ClearGuiText(); + // Clear stuff previously drawn by gui API + DisplayManager.ClearApiHawkSurfaces(); CheatList.Pulse(); @@ -3055,6 +3055,7 @@ private void StepRunLoop_Core(bool force = false) UpdateToolsAfter(); } } + DisplayManager.OnDraw?.Invoke(); if (newFrame) { @@ -4098,7 +4099,7 @@ public bool LoadState(string path, string userFriendlyStateName, bool suppressOS return false; } - OSD.ClearGuiText(); + DisplayManager.ClearApiHawkSurfaces(); if (SavestateLoaded is not null) { StateLoadedEventArgs args = new(userFriendlyStateName); diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/GuiLuaLibrary.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/GuiLuaLibrary.cs index 4c06f27caa2..fbcaf734ba5 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/GuiLuaLibrary.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/GuiLuaLibrary.cs @@ -6,10 +6,12 @@ namespace BizHawk.Client.EmuHawk { - public sealed class GuiLuaLibrary : LuaLibraryBase, IDisposable + public sealed class GuiLuaLibrary : LuaLibraryBase, IDisposable, IRegisterFunctions { private DisplaySurfaceID _rememberedSurfaceID = DisplaySurfaceID.EmuCore; + public NLFAddCallback CreateAndRegisterNamedFunction { get; set; } + public GuiLuaLibrary(ILuaLibraries luaLibsImpl, ApiContainer apiContainer, Action logOutputCallback) : base(luaLibsImpl, apiContainer, logOutputCallback) {} @@ -37,15 +39,36 @@ public void DrawFinish() public void AddMessage(string message) => APIs.Gui.AddMessage(message); - [LuaMethodExample("gui.clearGraphics( );")] +#pragma warning disable CS0618 + [LuaDeprecatedMethod] [LuaMethod("clearGraphics", "clears all lua drawn graphics from the screen")] public void ClearGraphics(string surfaceName = null) => APIs.Gui.ClearGraphics(surfaceID: UseOrFallback(surfaceName)); - [LuaMethodExample("gui.cleartext( );")] + [LuaDeprecatedMethod] [LuaMethod("cleartext", "clears all text created by gui.text()")] public void ClearText() => APIs.Gui.ClearText(); +#pragma warning restore CS0618 + + [LuaMethodExample("gui.draw();")] + [LuaMethod("draw", "Clears all prior drawings and calls any functions given to gui.addDrawCallback. Use this to re-draw while paused.")] + public void Draw() + { + APIs.Gui.Draw(); + } + + [LuaMethodExample("local draw_cb_id = gui.addDrawCallback(\r\n\tfunction()\r\n\t\t-- gui.draw*** calls go here\r\n\tend);")] + [LuaMethod("addDrawCallback", "The given function will be called before each API draw. This means after each frame and any time gui.draw is called.")] + public string AddDrawCallback(LuaFunction luaf, string name = null) + { + INamedLuaFunction nlf = CreateAndRegisterNamedFunction(luaf, NamedLuaFunction.EVENT_TYPE_DRAW, ApiGroup.PROHIBITED_MID_FRAME, name); + Action callback = () => nlf.Call(); + APIs.Gui.AddDrawCallback(callback); + nlf.OnRemove += () => APIs.Gui.RemoveDrawCallback(callback); + + return nlf.GuidStr; + } [LuaMethodExample("gui.defaultForeground( 0x000000FF );")] [LuaMethod("defaultForeground", "Sets the default foreground color to use in drawing methods, white by default")] diff --git a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs index ff9ea53a77d..17f7752afd2 100644 --- a/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs +++ b/src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs @@ -146,7 +146,6 @@ public LuaConsole() ResetDrawSurfacePadding(); ClearFileWatches(); LuaImp?.Close(); - DisplayManager.OSD.ClearGuiText(); } else { @@ -978,7 +977,6 @@ private void RemoveScriptMenuItem_Click(object sender, EventArgs e) UpdateDialog(); DisplayManager.ClearApiHawkSurfaces(); DisplayManager.ClearApiHawkTextureCache(); - DisplayManager.OSD.ClearGuiText(); if (!_openedFiles.Any(static lf => !lf.IsSeparator)) ResetDrawSurfacePadding(); // just removed last script, reset padding } }