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