[Scummvm-git-logs] scummvm master -> 50ed7606612f92de1ae50d275ab21426247f7997

sev- noreply at scummvm.org
Sun Jun 21 22:35:54 UTC 2026


This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
a275be078c SDL: Add ImGui Event Recorder rendering hook
0317f20da1 Common: Promote imgui debug channel to global
3467c5fb27 Engines: Clean up duplicate local imgui debug channels
50ed760661 GUI: Implement ImGui Event Recorder controls and cleanup


Commit: a275be078c59cbdc6fff23890f6a2e5caf84df96
    https://github.com/scummvm/scummvm/commit/a275be078c59cbdc6fff23890f6a2e5caf84df96
Author: SHANKHARAJ DATTA (shankharajdatta2004 at gmail.com)
Date: 2026-06-22T00:35:49+02:00

Commit Message:
SDL: Add ImGui Event Recorder rendering hook

Changed paths:
    backends/graphics/sdl/sdl-graphics.cpp


diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp
index ceb1fbdc387..b3d25e7fd7c 100644
--- a/backends/graphics/sdl/sdl-graphics.cpp
+++ b/backends/graphics/sdl/sdl-graphics.cpp
@@ -34,6 +34,10 @@
 #include "common/translation.h"
 #endif
 
+#if defined(USE_IMGUI) && defined(ENABLE_EVENTRECORDER)
+#include "gui/EventRecorder.h"
+#endif
+
 #ifdef EMSCRIPTEN
 #include "backends/platform/sdl/emscripten/emscripten.h"
 #endif
@@ -718,6 +722,9 @@ void SdlGraphicsManager::renderImGui() {
 
 	ImGui::NewFrame();
 	_imGuiCallbacks.render();
+#if defined(USE_IMGUI) && defined(ENABLE_EVENTRECORDER)
+	g_eventRec.showImGui();
+#endif
 	ImGui::Render();
 #ifdef USE_IMGUI_SDLRENDERER3
 	if (_imGuiSDLRenderer) {


Commit: 0317f20da1db5b83b92b42ad4ac595fe16005c28
    https://github.com/scummvm/scummvm/commit/0317f20da1db5b83b92b42ad4ac595fe16005c28
Author: SHANKHARAJ DATTA (shankharajdatta2004 at gmail.com)
Date: 2026-06-22T00:35:49+02:00

Commit Message:
Common: Promote imgui debug channel to global

Changed paths:
    common/debug.cpp
    common/debug.h


diff --git a/common/debug.cpp b/common/debug.cpp
index 784932c89af..aee96c512e8 100644
--- a/common/debug.cpp
+++ b/common/debug.cpp
@@ -41,6 +41,7 @@ const DebugChannelDef gDebugChannels[] = {
 	{ kDebugLevelGGraphics,  "ggraphics", "debug messages for global graphics" },
 	{ kDebugLevelGVideo,     "gvideo",    "debug messages for global video" },
 	{ kDebugLevelGAudio,     "gaudio",    "debug messages for global audio" },
+	{ kDebugImGui,           "imgui",     "Show ImGui debug window (if available)" },
 	DEBUG_CHANNEL_END
 };
 namespace Common {
diff --git a/common/debug.h b/common/debug.h
index 37736306349..35d9b93e9bb 100644
--- a/common/debug.h
+++ b/common/debug.h
@@ -170,6 +170,7 @@ enum GlobalDebugLevels {
 	kDebugLevelGGraphics,
 	kDebugLevelGVideo,
 	kDebugLevelGAudio,
+	kDebugImGui,
 };
 
 /** @} */


Commit: 3467c5fb272669610d2f47cdbb3e9567e652ccbc
    https://github.com/scummvm/scummvm/commit/3467c5fb272669610d2f47cdbb3e9567e652ccbc
Author: SHANKHARAJ DATTA (shankharajdatta2004 at gmail.com)
Date: 2026-06-22T00:35:49+02:00

Commit Message:
Engines: Clean up duplicate local imgui debug channels

Changed paths:
    engines/director/detection.cpp
    engines/director/director.h
    engines/qdengine/detection.cpp
    engines/qdengine/qdengine.h
    engines/scumm/detection.cpp
    engines/scumm/detection.h
    engines/scumm/scumm.cpp
    engines/twine/detection.cpp
    engines/twine/shared.h
    engines/twp/debugtools.cpp
    engines/twp/detection.cpp
    engines/twp/detection.h
    engines/ultima/detection.cpp
    engines/ultima/ultima.h
    engines/wage/detection.cpp
    engines/wage/wage.h


diff --git a/engines/director/detection.cpp b/engines/director/detection.cpp
index 94a25fb560a..942b8fb2786 100644
--- a/engines/director/detection.cpp
+++ b/engines/director/detection.cpp
@@ -92,7 +92,6 @@ static const DebugChannelDef debugFlagList[] = {
 	{Director::kDebugText, "text", "Text rendering"},
 	{Director::kDebugXObj, "xobj", "XObjects"},
 	{Director::kDebugLingoThe, "lingothe", "Lingo \"the\" entities"},
-	{Director::kDebugImGui, "imgui", "Show ImGui debug window (if available)"},
 	{Director::kDebugPaused, "paused", "Pause first movie right after start"},
 	{Director::kDebugPauseOnLoad, "pauseonload", "Pause every movie right after loading"},
 	{Director::kDebugSaving, "saving", "Show Debug output while saving movies"},
diff --git a/engines/director/director.h b/engines/director/director.h
index eab89866cd8..8c1e02b5211 100644
--- a/engines/director/director.h
+++ b/engines/director/director.h
@@ -90,7 +90,6 @@ enum {
 	kDebugConsole,
 	kDebugXObj,
 	kDebugLingoThe,
-	kDebugImGui,
 	kDebugPaused,
 	kDebugPauseOnLoad,
 	kDebugSaving,
diff --git a/engines/qdengine/detection.cpp b/engines/qdengine/detection.cpp
index ccb5f084ebe..af8c2552138 100644
--- a/engines/qdengine/detection.cpp
+++ b/engines/qdengine/detection.cpp
@@ -34,7 +34,6 @@
 
 static const DebugChannelDef debugFlagList[] = {
 	{ QDEngine::kDebugGraphics, "graphics", "Graphics debug level" },
-	{ QDEngine::kDebugImGui, "imgui", "Imgui debug output"},
 	{ QDEngine::kDebugInput, "input", "Enable user input tracing"},
 	{ QDEngine::kDebugLoad, "load", "Enable load tracing" },
 	{ QDEngine::kDebugLog, "log", "See log messages"},
diff --git a/engines/qdengine/qdengine.h b/engines/qdengine/qdengine.h
index d22ae36d66d..fcec2e4ab8b 100644
--- a/engines/qdengine/qdengine.h
+++ b/engines/qdengine/qdengine.h
@@ -46,7 +46,6 @@ class qdGameDispatcher;
 
 enum QDEngineDebugChannels {
 	kDebugGraphics = 1,
-	kDebugImGui,
 	kDebugInput,
 	kDebugLoad,
 	kDebugLog,
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index a878f223801..f8f7175e5e4 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -65,7 +65,6 @@ static const DebugChannelDef debugFlagList[] = {
 		{Scumm::DEBUG_SMUSH, "SMUSH", "Track SMUSH"},
 		{Scumm::DEBUG_MOONBASE_AI, "MOONBASEAI", "Track Moonbase AI"},
 		{Scumm::DEBUG_NETWORK, "NETWORK", "Track Networking"},
-		{Scumm::DEBUG_IMGUI, "IMGUI", "Show ImGui debug window (if available)"},
 		DEBUG_CHANNEL_END
 };
 
diff --git a/engines/scumm/detection.h b/engines/scumm/detection.h
index b04b215f58b..24b4896093e 100644
--- a/engines/scumm/detection.h
+++ b/engines/scumm/detection.h
@@ -288,7 +288,6 @@ enum {
 	DEBUG_SMUSH,		// Track SMUSH
 	DEBUG_MOONBASE_AI,	// Moonbase AI
 	DEBUG_NETWORK,		// Track Networking
-	DEBUG_IMGUI,		// Show ImGui debug window (if available)
 };
 
 } // End of namespace Scumm
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index f0bb1a53d36..0c246907ee2 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -2800,7 +2800,7 @@ Common::Error ScummEngine::go() {
 #endif // ENABLE_HE
 
 #ifdef USE_IMGUI
-	if (debugChannelSet(-1, DEBUG_IMGUI)) {
+	if (debugChannelSet(-1, kDebugImGui)) {
 		ImGuiCallbacks callbacks;
 		callbacks.init = Editor::onImGuiInit;
 		callbacks.render = Editor::onImGuiRender;
diff --git a/engines/twine/detection.cpp b/engines/twine/detection.cpp
index c85773ec4fb..4647ced9231 100644
--- a/engines/twine/detection.cpp
+++ b/engines/twine/detection.cpp
@@ -38,7 +38,6 @@ static const DebugChannelDef debugFlagList[] = {
 	{TwinE::kDebugScriptsLife, "scriptslife", "Life script debugging"},
 	{TwinE::kDebugResources, "resources", "Resources debugging"},
 	{TwinE::kDebugTimers, "timers", "Timer debugging"},
-	{TwinE::kDebugImGui, "imgui", "UI for debugging"},
 	{TwinE::kDebugInput, "input", "Input debugging"},
 	{TwinE::kDebugMovies, "movies", "Movies debugging"},
 	{TwinE::kDebugPalette, "palette", "Palette debugging"},
diff --git a/engines/twine/shared.h b/engines/twine/shared.h
index 67b2c57d1b8..cded9a8643d 100644
--- a/engines/twine/shared.h
+++ b/engines/twine/shared.h
@@ -811,7 +811,6 @@ enum kDebugLevels {
 	kDebugScriptsLife,
 	kDebugTimers,
 	kDebugResources,
-	kDebugImGui,
 	kDebugInput,
 	kDebugMovies,
 	kDebugPalette,
diff --git a/engines/twp/debugtools.cpp b/engines/twp/debugtools.cpp
index b7cf9d5fbd2..3c953bad42e 100644
--- a/engines/twp/debugtools.cpp
+++ b/engines/twp/debugtools.cpp
@@ -626,7 +626,7 @@ void onImGuiInit() {
 
 void onImGuiRender() {
 	ImGuiIO& io = ImGui::GetIO();
-	if (!debugChannelSet(-1, kDebugConsole)) {
+	if (!debugChannelSet(-1, kDebugImGui)) {
 		io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange | ImGuiConfigFlags_NoMouse;
 		io.MouseDrawCursor = false;
 		return;
diff --git a/engines/twp/detection.cpp b/engines/twp/detection.cpp
index b29b43d8c66..d78cf0656f7 100644
--- a/engines/twp/detection.cpp
+++ b/engines/twp/detection.cpp
@@ -36,7 +36,6 @@ const DebugChannelDef TwpMetaEngineDetection::debugFlagList[] = {
 	{Twp::kDebugActScript, "Actor", "Enable debug actor script dump"},
 	{Twp::kDebugSndScript, "Sound", "Enable debug sound script dump"},
 	{Twp::kDebugGame, "Game", "Game debug level"},
-	{Twp::kDebugConsole, "imgui", "Show ImGui debug window (if available)"},
 	{Twp::kDebugSave, "Save", "Export savegame supported by the original game"},
 	DEBUG_CHANNEL_END};
 
diff --git a/engines/twp/detection.h b/engines/twp/detection.h
index 9924e12f81a..5cacfe3d6c4 100644
--- a/engines/twp/detection.h
+++ b/engines/twp/detection.h
@@ -38,7 +38,6 @@ enum TwpDebugChannels {
 	kDebugActScript,
 	kDebugSndScript,
 	kDebugGame,
-	kDebugConsole,
 	kDebugSave
 };
 
diff --git a/engines/ultima/detection.cpp b/engines/ultima/detection.cpp
index 3128203618c..3741fa257bd 100644
--- a/engines/ultima/detection.cpp
+++ b/engines/ultima/detection.cpp
@@ -34,7 +34,6 @@ const DebugChannelDef UltimaMetaEngineDetection::debugFlagList[] = {
 	{Ultima::kDebugActor, "Actor", "Actor debug level"},
 	{Ultima::kDebugObject, "Object", "Object debug level"},
 	{Ultima::kDebugCollision, "Collision", "Collision debug level"},
-	{Ultima::kDebugImGui, "imgui", "Imgui debug output"},
 	DEBUG_CHANNEL_END
 };
 
diff --git a/engines/ultima/ultima.h b/engines/ultima/ultima.h
index ef8e11b795d..1341184ccda 100644
--- a/engines/ultima/ultima.h
+++ b/engines/ultima/ultima.h
@@ -31,7 +31,6 @@ enum UltimaDebugChannels {
 	kDebugActor,
 	kDebugObject,
 	kDebugCollision,
-	kDebugImGui,
 };
 
 } // End of namespace Ultima
diff --git a/engines/wage/detection.cpp b/engines/wage/detection.cpp
index ef3137ef711..224d8995b59 100644
--- a/engines/wage/detection.cpp
+++ b/engines/wage/detection.cpp
@@ -45,7 +45,6 @@ static const PlainGameDescriptor wageGames[] = {
 #include "wage/detection.h"
 
 static const DebugChannelDef debugFlagList[] = {
-	{ Wage::kDebugImGui,   "imgui",   "Show ImGui debug window (if available)"},
 	{ Wage::kDebugSound,   "sound",   "Show sound debug information"},
 	{ Wage::kDebugLoading, "loading", "Show loading debug information" },
 	DEBUG_CHANNEL_END
diff --git a/engines/wage/wage.h b/engines/wage/wage.h
index 31c970f7506..5a388f90606 100644
--- a/engines/wage/wage.h
+++ b/engines/wage/wage.h
@@ -92,8 +92,7 @@ typedef Common::List<Chr *> ChrList;
 #define STORAGESCENE "STORAGE@"
 
 enum {
-	kDebugImGui = 1,
-	kDebugSound,
+	kDebugSound = 1,
 	kDebugLoading,
 };
 


Commit: 50ed7606612f92de1ae50d275ab21426247f7997
    https://github.com/scummvm/scummvm/commit/50ed7606612f92de1ae50d275ab21426247f7997
Author: SHANKHARAJ DATTA (shankharajdatta2004 at gmail.com)
Date: 2026-06-22T00:35:49+02:00

Commit Message:
GUI: Implement ImGui Event Recorder controls and cleanup

Changed paths:
    gui/EventRecorder.cpp
    gui/EventRecorder.h


diff --git a/gui/EventRecorder.cpp b/gui/EventRecorder.cpp
index e359d162a00..f8ec2dd38cd 100644
--- a/gui/EventRecorder.cpp
+++ b/gui/EventRecorder.cpp
@@ -43,6 +43,11 @@ DECLARE_SINGLETON(GUI::EventRecorder);
 #include "graphics/surface.h"
 #include "graphics/scaler.h"
 
+#ifdef USE_IMGUI
+#include "backends/imgui/imgui.h"
+#include "backends/imgui/IconsMaterialSymbols.h"
+#endif
+
 namespace GUI {
 
 
@@ -94,8 +99,11 @@ void EventRecorder::deinit() {
 	_recordMode = kPassthrough;
 	delete _fakeMixerManager;
 	_fakeMixerManager = nullptr;
-	_controlPanel->close();
-	delete _controlPanel;
+	if (_controlPanel) {
+		_controlPanel->close();
+		delete _controlPanel;
+		_controlPanel = nullptr;
+	}
 	debugC(1, kDebugLevelEventRec, "playback:action=stopplayback");
 	Common::EventDispatcher *eventDispatcher = g_system->getEventManager()->getEventDispatcher();
 	eventDispatcher->unregisterSource(this);
@@ -118,7 +126,9 @@ void EventRecorder::updateFakeTimer(uint32 millis) {
 	uint32 millisDelay = millis - _lastMillis;
 	_lastMillis = millis;
 	_fakeTimer += millisDelay;
-	_controlPanel->setReplayedTime(_fakeTimer);
+	// _controlPanel is null when the ImGui interface is used instead of the legacy OSD
+	if (_controlPanel)
+		_controlPanel->setReplayedTime(_fakeTimer);
 }
 
 void EventRecorder::processTimeAndDate(TimeDate &td, bool skipRecord) {
@@ -220,7 +230,8 @@ void EventRecorder::processMillis(uint32 &millis, bool skipRecord) {
 		updateSubsystems();
 		_nextEvent = _playbackFile->getNextEvent();
 		_timerManager->handler();
-		_controlPanel->setReplayedTime(_fakeTimer);
+		if (_controlPanel)
+			_controlPanel->setReplayedTime(_fakeTimer);
 		_processingMillis = false;
 		break;
 	case kRecorderPlaybackPause:
@@ -280,7 +291,8 @@ void EventRecorder::processScreenUpdate() {
 			takeScreenshot();
 		}
 		_timerManager->handler();
-		_controlPanel->setReplayedTime(_fakeTimer);
+		if (_controlPanel)
+			_controlPanel->setReplayedTime(_fakeTimer);
 		_processingMillis = false;
 		break;
 	default:
@@ -339,12 +351,14 @@ void EventRecorder::togglePause() {
 	case kRecorderUpdate:
 		oldState = _recordMode;
 		_recordMode = kRecorderPlaybackPause;
-		_controlPanel->runModal();
+		if (_controlPanel)
+			_controlPanel->runModal();
 		_recordMode = oldState;
 		_initialized = true;
 		break;
 	case kRecorderPlaybackPause:
-		_controlPanel->close();
+		if (_controlPanel)
+			_controlPanel->close();
 		break;
 	default:
 		break;
@@ -408,14 +422,18 @@ void EventRecorder::init(const Common::String &recordFileName, RecordMode mode)
 	if (_screenshotPeriod == 0) {
 		_screenshotPeriod = kDefaultScreenshotPeriod;
 	}
+	_controlPanel = nullptr;
 	if (!openRecordFile(recordFileName)) {
 		deinit();
 		error("playback:action=error reason=\"Record file loading error\"");
 		return;
 	}
-	if (_recordMode != kPassthrough) {
-		_controlPanel = new GUI::OnScreenDialog(_recordMode == kRecorderRecord);
-		_controlPanel->reflowLayout();
+
+	if (!isImGuiRecorderEnabled()) {
+		if (_recordMode != kPassthrough) {
+			_controlPanel = new GUI::OnScreenDialog(_recordMode == kRecorderRecord);
+			_controlPanel->reflowLayout();
+		}
 	}
 	if ((_recordMode == kRecorderPlayback) || (_recordMode == kRecorderUpdate)) {
 		applyPlaybackSettings();
@@ -580,55 +598,70 @@ void EventRecorder::updateSubsystems() {
 }
 
 bool EventRecorder::notifyEvent(const Common::Event &ev) {
-	if ((!_initialized) && (_recordMode != kRecorderPlaybackPause)) {
+	if (!_initialized && _recordMode != kRecorderPlaybackPause)
 		return false;
-	}
 
 	checkForKeyCode(ev);
 	Common::Event evt = ev;
 	evt.mouse.x = evt.mouse.x * (g_system->getOverlayWidth() / g_system->getWidth());
 	evt.mouse.y = evt.mouse.y * (g_system->getOverlayHeight() / g_system->getHeight());
-	switch (_recordMode) {
-	case kRecorderUpdate: // passthrough
-	case kRecorderPlayback:
-		// pass through screen updates to avoid loss of sync!
-		if (evt.type == Common::EVENT_SCREEN_CHANGED)
-			g_gui.processEvent(evt, _controlPanel);
-		if (_recordMode == kRecorderUpdate) {
-			// write a copy of the event to the output buffer
+
+	if (isImGuiRecorderEnabled()) {
+		if (_recordMode == kRecorderPlaybackPause)
+			return false;
+
+		if (_recordMode == kRecorderRecord || _recordMode == kRecorderUpdate) {
 			Common::RecorderEvent e(ev);
 			e.recordedtype = Common::kRecorderEventTypeNormal;
 			e.time = _fakeTimer;
 			_recordFile->writeEvent(e);
 		}
 		return false;
-	case kRecorderRecord:
-		g_gui.processEvent(evt, _controlPanel);
-		if (((evt.type == Common::EVENT_LBUTTONDOWN) || (evt.type == Common::EVENT_LBUTTONUP) || (evt.type == Common::EVENT_MOUSEMOVE)) && _controlPanel->isMouseOver()) {
+	}
+
+	switch (_recordMode) {
+	case kRecorderUpdate:
+	case kRecorderPlayback:
+		if (evt.type == Common::EVENT_SCREEN_CHANGED && _controlPanel)
+			g_gui.processEvent(evt, _controlPanel);
+		break;
+
+	case kRecorderRecord: {
+		if (_controlPanel)
+			g_gui.processEvent(evt, _controlPanel);
+		
+		if (_controlPanel && ((evt.type == Common::EVENT_LBUTTONDOWN) || (evt.type == Common::EVENT_LBUTTONUP) || (evt.type == Common::EVENT_MOUSEMOVE)) && _controlPanel->isMouseOver())
 			return true;
-		} else {
-			Common::RecorderEvent e(ev);
-			e.recordedtype = Common::kRecorderEventTypeNormal;
-			e.time = _fakeTimer;
-			_recordFile->writeEvent(e);
-			return false;
-		}
+
+		Common::RecorderEvent e(ev);
+		e.recordedtype = Common::kRecorderEventTypeNormal;
+		e.time = _fakeTimer;
+		_recordFile->writeEvent(e);
+		return false;
+	}
+
 	case kRecorderPlaybackPause: {
-		Common::Event dialogEvent;
-		if (_controlPanel->isEditDlgVisible()) {
-			dialogEvent = ev;
-		} else {
-			dialogEvent = evt;
-		}
-		g_gui.processEvent(dialogEvent, _controlPanel->getActiveDlg());
-		if (((dialogEvent.type == Common::EVENT_LBUTTONDOWN) || (dialogEvent.type == Common::EVENT_LBUTTONUP) || (dialogEvent.type == Common::EVENT_MOUSEMOVE)) && _controlPanel->isMouseOver()) {
-			return true;
+		if (_controlPanel) {
+			Common::Event dialogEvent = _controlPanel->isEditDlgVisible() ? ev : evt;
+			g_gui.processEvent(dialogEvent, _controlPanel->getActiveDlg());
+			if (((dialogEvent.type == Common::EVENT_LBUTTONDOWN) || (dialogEvent.type == Common::EVENT_LBUTTONUP) || (dialogEvent.type == Common::EVENT_MOUSEMOVE)) && _controlPanel->isMouseOver())
+				return true;
 		}
 		return false;
 	}
 	default:
-		return false;
+		break;
 	}
+
+	// Default behavior for Update/Playback when not handled above
+	if (_recordMode == kRecorderUpdate) {
+		Common::RecorderEvent e(ev);
+		e.recordedtype = Common::kRecorderEventTypeNormal;
+		e.time = _fakeTimer;
+		_recordFile->writeEvent(e);
+	}
+
+	return false;
 }
 
 void EventRecorder::setGameMd5(const ADGameDescription *gameDesc) {
@@ -703,6 +736,9 @@ Common::SaveFileManager *EventRecorder::getSaveManager(Common::SaveFileManager *
 }
 
 void EventRecorder::preDrawOverlayGui() {
+	if (isImGuiRecorderEnabled())
+		return;
+
 	if ((_initialized) || (_needRedraw)) {
 		RecordMode oldMode = _recordMode;
 		_recordMode = kPassthrough;
@@ -720,6 +756,9 @@ void EventRecorder::preDrawOverlayGui() {
 }
 
 void EventRecorder::postDrawOverlayGui() {
+	if (isImGuiRecorderEnabled())
+		return;
+
 	if ((_initialized) || (_needRedraw)) {
 		RecordMode oldMode = _recordMode;
 		_recordMode = kPassthrough;
@@ -820,6 +859,108 @@ void EventRecorder::deleteTemporarySave() {
 	_temporarySlot = -1;
 }
 
+bool EventRecorder::isImGuiRecorderEnabled() const {
+#ifdef USE_IMGUI
+	return debugChannelSet(-1, kDebugImGui);
+#else
+	return false;
+#endif
+}
+
+#ifdef USE_IMGUI
+
+void EventRecorder::showImGui() {
+	if (_recordMode == kPassthrough || !_initialized)
+		return;
+
+	if (!isImGuiRecorderEnabled())
+		return;
+
+	// --- Design ---
+	const float windowWidth = 190.0f;
+	const ImVec2 btnSize(34, 24);
+	const ImVec4 colorRed(0.95f, 0.25f, 0.25f, 1.0f);
+	const ImVec4 colorBlue(0.25f, 0.75f, 0.95f, 1.0f);
+	const ImVec4 colorAmber(0.95f, 0.75f, 0.10f, 1.0f);
+
+	ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10, 8));
+	ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing,   ImVec2(6, 6));
+	ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 6.0f);
+	ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.12f, 0.12f, 0.15f, 0.96f));
+
+	ImGui::SetNextWindowSize(ImVec2(windowWidth, 0));
+	ImGui::SetNextWindowPos(ImVec2(15, 15), ImGuiCond_FirstUseEver);
+	
+	if (ImGui::Begin("Recorder", nullptr,
+		ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_AlwaysAutoResize | 
+		ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar)) {
+
+		bool isRecording = (_recordMode == kRecorderRecord);
+		bool isPaused    = (_recordMode == kRecorderPlaybackPause);
+		bool isPlayback  = (_recordMode == kRecorderPlayback || _recordMode == kRecorderUpdate);
+
+		// --- Status & Timer ---
+		ImVec4 modeColor = isRecording ? colorRed : (isPaused ? colorAmber : colorBlue);
+		const char *modeIcon = isRecording ? ICON_MS_FIBER_MANUAL_RECORD : (isPaused ? ICON_MS_PAUSE_CIRCLE : ICON_MS_PLAY_CIRCLE);
+		
+		ImGui::TextColored(modeColor, "%s", modeIcon);
+		ImGui::SameLine();
+		ImGui::Text("%s", isRecording ? "REC" : (isPaused ? "PAUSE" : "PLAY"));
+		
+		uint32 secs = _fakeTimer / 1000;
+		ImGui::SameLine(ImGui::GetContentRegionAvail().x - ImGui::CalcTextSize("00:00:00").x + 8);
+		ImGui::TextDisabled("%02u:%02u:%02u", secs / 3600, (secs % 3600) / 60, secs % 60);
+
+		// --- Controls ---
+		float totalButtonsWidth = (btnSize.x * 3) + (ImGui::GetStyle().ItemSpacing.x * 2);
+		ImGui::SetCursorPosX((windowWidth - totalButtonsWidth) * 0.5f);
+
+		if (ImGui::Button(ICON_MS_STOP, btnSize)) {
+			deinit();
+		}
+		ImGui::SetItemTooltip("Stop");
+		ImGui::SameLine();
+
+		const char *pauseIcon = isPaused ? ICON_MS_PLAY_ARROW : ICON_MS_PAUSE;
+		if (isPaused) {
+			ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(colorAmber.x, colorAmber.y, colorAmber.z, 0.4f));
+		}
+		if (ImGui::Button(pauseIcon, btnSize)) {
+			togglePause();
+		}
+		if (isPaused) {
+			ImGui::PopStyleColor();
+		}
+		ImGui::SetItemTooltip(isPaused ? "Resume" : "Pause");
+		ImGui::SameLine();
+
+		bool canFF = (isPlayback || isPaused);
+		if (!canFF) {
+			ImGui::BeginDisabled();
+		}
+		const char *ffIcon = _fastPlayback ? ICON_MS_FAST_REWIND : ICON_MS_FAST_FORWARD;
+		if (_fastPlayback) {
+			ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(colorBlue.x, colorBlue.y, colorBlue.z, 0.4f));
+		}
+		if (ImGui::Button(ffIcon, btnSize)) {
+			setFastPlayback(!_fastPlayback);
+		}
+		if (_fastPlayback) {
+			ImGui::PopStyleColor();
+		}
+		ImGui::SetItemTooltip(_fastPlayback ? "Normal" : "Fast");
+		if (!canFF) {
+			ImGui::EndDisabled();
+		}
+	}
+	ImGui::End();
+
+	ImGui::PopStyleColor();
+	ImGui::PopStyleVar(3);
+}
+#endif // USE_IMGUI
+
 } // End of namespace GUI
 
 #endif // ENABLE_EVENTRECORDER
+
diff --git a/gui/EventRecorder.h b/gui/EventRecorder.h
index a68dd4bbdbe..c76738d3d90 100644
--- a/gui/EventRecorder.h
+++ b/gui/EventRecorder.h
@@ -188,7 +188,16 @@ public:
 	bool switchMode();
 	void switchFastMode();
 
+#ifdef USE_IMGUI
+	void showImGui();
+#endif
+
 private:
+
+#ifdef USE_IMGUI
+	bool isImGuiRecorderEnabled() const;
+#endif
+
 	bool pollEvent(Common::Event &ev) override;
 	bool notifyEvent(const Common::Event &event) override;
 	bool _initialized;




More information about the Scummvm-git-logs mailing list