Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/BizHawk.Client.Common/Api/Classes/GuiApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Copy link
Copy Markdown
Member

@YoshiRulz YoshiRulz Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ApiHawk already has a draw call batching/scoping method, WithSurface.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's completely unrelated. WithSurface(surfaceId, action) is just a wrapper for UseSurface(surfaceId); action(); UseSurface(originalSurfaceId). The new callbacks don't care about which surface is being drawn, it's just a signal to draw.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, I'm saying if you're going to limit draw calls to callbacks, use the callback which already exists and which I've been promoting for this reason.

Copy link
Copy Markdown
Contributor Author

@SuuperW SuuperW Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand how WithSurface could be used in a way that is similar to AddDrawCallback.
And if you were to change how WithSurface works, that would be an API change that I think is better done while changing the name, so that existing code will fail at compile time instead of run time. (better yet, have both so existing code keeps working, at least until the old way is deprecated)

EDIT:

if you're going to limit draw calls to callbacks

This PR does not do that. Old Lua scripts should continue to work exactly as they have before.


public void SetDefaultForegroundColor(Color color) => _defaultForeground = color;

Expand Down
16 changes: 16 additions & 0 deletions src/BizHawk.Client.Common/Api/Interfaces/IGuiApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

/// <summary>
/// Clears all prior drawings and calls any actions given to <see cref="AddDrawCallback(Action)"/>.
/// This should only be used when you want to redraw while paused.
/// </summary>
void Draw();

/// <summary>
/// The given action will be called before each API draw. This means after each frame and any time <see cref="Draw"/> is called.
/// </summary>
void AddDrawCallback(Action callback);
void RemoveDrawCallback(Action callback);

void SetDefaultForegroundColor(Color color);
void SetDefaultBackgroundColor(Color color);
Color GetDefaultTextBackground();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ public DisplayManagerRenderTargetProvider(Func<Size, IRenderTarget> callback)

public SnowyNullVideo SnowyVP { get; private set; }

public Action/*?*/ OnDraw;

protected DisplayManagerBase(
Config config,
IEmulator emulator,
Expand Down Expand Up @@ -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");

/// <summary>
/// Clear stuff drawn by the gui API
/// </summary>
public void ClearApiHawkSurfaces()
{
foreach (var renderer in _apiHawkIDTo2DRenderer.Values)
{
renderer.Clear();
}
OSD.ClearApiHawkText();
}

public void DiscardApiHawkSurfaces()
Expand Down
2 changes: 1 addition & 1 deletion src/BizHawk.Client.Common/DisplayManager/OSDManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions src/BizHawk.Client.Common/lua/NamedLuaFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 4 additions & 3 deletions src/BizHawk.Client.EmuHawk/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -3055,6 +3055,7 @@ private void StepRunLoop_Core(bool force = false)
UpdateToolsAfter();
}
}
DisplayManager.OnDraw?.Invoke();

if (newFrame)
{
Expand Down Expand Up @@ -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);
Expand Down
29 changes: 26 additions & 3 deletions src/BizHawk.Client.EmuHawk/tools/Lua/Libraries/GuiLuaLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string> logOutputCallback)
: base(luaLibsImpl, apiContainer, logOutputCallback) {}

Expand Down Expand Up @@ -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")]
Expand Down
2 changes: 0 additions & 2 deletions src/BizHawk.Client.EmuHawk/tools/Lua/LuaConsole.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ public LuaConsole()
ResetDrawSurfacePadding();
ClearFileWatches();
LuaImp?.Close();
DisplayManager.OSD.ClearGuiText();
}
else
{
Expand Down Expand Up @@ -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
}
}
Expand Down
Loading