[Scummvm-git-logs] scummvm master -> f2ae66e3388e9d6b198aa4d222e7d3a76c622392
sev-
noreply at scummvm.org
Mon Aug 18 10:31:48 UTC 2025
This automated email contains information about 43 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
8b957c29de DIRECTOR: IMGUI: Fix breakpoint error pop-up in the script window
e8b1a8f7a8 DIRECTOR: IMGUI: Add Execution Context Window
76067a905d DIRECTOR: IMGUI: Add execution context for multiple windows
4de416208e DIRECTOR: IMGUI: Fix material fonts in the score window
a30d2bd0bb DIRECTOR: IMGUI: Removed the `DT::showScripts()` function
58b11ed906 DIRECTOR: IMGUI: Render global variables using `renderVar()` instead of
99b90ab7c2 DIRECTOR: IMGUI: Remove Script flicker from Execution Context Window
26c929873e DIRECTOR: IMGUI: Fix error pop-up in Vars window while hovering over
f2a6736bb3 DIRECTOR: IMGUI: Show variable name when hovering over
2fbf88e2a0 DIRECTOR: IMGUI: Improve Search for handler in `getHandler()`
643d866abd DIRECTOR: IMGUI: Show handlers from the same context in the same window
3d166f02a2 DIRECTOR: IMGUI: Remove new line when showing Prop list
65b159b152 DIRECTOR: IMGUI: Minor change in `windowID` increment position
2f5ec42789 DIRECTOR: IMGUI: Implement `Save State` and `Load State`
736b80735b DIRECTOR: IMGUI: Fix segmentation faults in the loadCurrentState
10084ac787 DIRECTOR: IMGUI: Save the window settings when called `Save state`
d08f334ece DIRECTOR: IMGUI: Save the current log when called `Save State`
38cbc6e5e6 DIRECTOR: IMGUI: Out of Scope variables color difference in the Watched Vars window
235430e36e DIRECTOR: IMGUI: Fix pop-up error in Watched Variables
69a3b43cd9 DIRECTOR: IMGUI: Rework execution context for separate windows
f9a923cafe DIRECTOR: IMGUI: Render text data in Cast window
3c88e47b2a DIRECTOR: IMGUI: Render Shapes in Cast Window (only Rectangles)
6856dafcb7 DIRECTOR: IMGUI: Fix multiple window script showing
2bbcf954cc DIRECTOR: IMGUI: Set up Shape rendering in the Cast Window
08d30482ac DIRECTOR: IMGUI: Fix Rendering Shapes Properly in the Cast Window
2d069867af DIRECTOR: IMGUI: Do not prematurely set cursor in Cast window
72c0855930 DIRECTOR: IMGUI: Render shapes in Score window as well
7e4c5343c4 DIRECTOR: IMGUI: Code clean up and remove debug leftovers
91cd92366f DIRECTOR: IMGUI: Render text cast members previews in cast window
977443ca3f DIRECTOR: IMGUI: Render Text/Button/RichText cast previews in Score window
ce426a25a1 DIRECTOR: Prevent memory leak in `getTextID()` and `getShapeID()`
b28b9775ed DIRECTOR: IMGUI: Cache Text and Shape textures after rendering once
73bc872d1c DIRECTOR: IMGUI: Fix scrolling to current handler in execution context window
47e262fc9a DIRECTOR: IMGUI: Render shape/text previews in grid view of Cast window
141631ca6c DIRECTOR: IMGUI: Fix wrong column height in preview of cast members in Cast Window
a002d120eb DIRECTOR: IMGUI: Render shape previews without using current channels
ce552e80da DIRECTOR: IMGUI: Render Text Previews without using current channels
a69fa302aa DIRECTOR: IMGUI: Implement 'Go to Definition' in scripts
68d7353619 DIRECTOR: IMGUI: Scroll to the handler when "Go To Definition" is clicked
b90fe17221 DIRECTOR: IMGUI: Remove unnecessary pointer `ScriptData`
41bd02feb8 DIRECTOR: IMGUI: Create table for saving and loading window flags
ace600df99 DIRECTOR: IMGUI: Fix ID Pop up warning in Execution Context window
f2ae66e338 DIRECTOR: IMGUI: Show context info in the Execution Context window
Commit: 8b957c29de528d3075776562a4904eb7162803b8
https://github.com/scummvm/scummvm/commit/8b957c29de528d3075776562a4904eb7162803b8
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Fix breakpoint error pop-up in the script window
Each rendered line needed a new ID
Changed paths:
engines/director/debugger/dt-script-d4.cpp
diff --git a/engines/director/debugger/dt-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index 35ba13ce20c..faf8590aded 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -1132,7 +1132,11 @@ private:
if (bp)
color = _state->_colors._bp_color_enabled;
+ // Need to give a new id for each button
+ ImGui::PushID(_renderLineID);
ImGui::InvisibleButton("Line", ImVec2(16, ImGui::GetFontSize()));
+ ImGui::PopID();
+ _renderLineID++;
// click on breakpoint column?
if (ImGui::IsItemClicked(0)) {
@@ -1211,6 +1215,7 @@ private:
int _indent = 0;
bool _currentStatementDisplayed = false;
bool _isScriptInDebug = false;
+ int _renderLineID = 0;
};
void renderScriptAST(ImGuiScript &script, bool showByteCode) {
Commit: e8b1a8f7a8b97feb79c57aadb6ae03637bfa6353
https://github.com/scummvm/scummvm/commit/e8b1a8f7a8b97feb79c57aadb6ae03637bfa6353
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Add Execution Context Window
Move the callstack and the scripts to the Exection Context Window
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-lists.cpp
engines/director/debugger/dt-scripts.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 63006a602dd..ea3ffb5d786 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -355,12 +355,12 @@ void onImGuiRender() {
ImGui::MenuItem("Functions", NULL, &_state->_w.funcList);
ImGui::MenuItem("Cast", NULL, &_state->_w.cast);
ImGui::MenuItem("Channels", NULL, &_state->_w.channels);
- ImGui::MenuItem("CallStack", NULL, &_state->_w.callStack);
ImGui::MenuItem("Breakpoints", NULL, &_state->_w.bpList);
ImGui::MenuItem("Vars", NULL, &_state->_w.vars);
ImGui::MenuItem("Watched Vars", NULL, &_state->_w.watchedVars);
ImGui::MenuItem("Logger", NULL, &_state->_w.logger);
ImGui::MenuItem("Archive", NULL, &_state->_w.archive);
+ ImGui::MenuItem("Execution Context", NULL, &_state->_w.executionContext);
ImGui::SeparatorText("Misc");
if (ImGui::MenuItem("Save state")) {
@@ -376,11 +376,10 @@ void onImGuiRender() {
}
showScriptCasts();
- showScripts();
+ showExecutionContext();
showControlPanel();
showVars();
- showCallStack();
showChannels();
showCast();
showFuncList();
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index 9996ed0f998..af2800e3d3e 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -95,6 +95,7 @@ typedef struct ImGuiWindows {
bool logger = false;
bool archive = false;
bool watchedVars = false;
+ bool executionContext = false;
} ImGuiWindows;
typedef struct ImGuiState {
@@ -214,6 +215,7 @@ void renderScriptAST(ImGuiScript &script, bool showByteCode); // dt-script
void showFuncList();
void showScriptCasts();
void showScripts();
+void showExecutionContext();
extern ImGuiState *_state;
diff --git a/engines/director/debugger/dt-lists.cpp b/engines/director/debugger/dt-lists.cpp
index 7674edfab4c..a57fad01073 100644
--- a/engines/director/debugger/dt-lists.cpp
+++ b/engines/director/debugger/dt-lists.cpp
@@ -29,19 +29,6 @@
namespace Director {
namespace DT {
-void showCallStack() {
- if (!_state->_w.callStack)
- return;
-
- Director::Lingo *lingo = g_director->getLingo();
- ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
- ImGui::SetNextWindowSize(ImVec2(120, 120), ImGuiCond_FirstUseEver);
- if (ImGui::Begin("CallStack", &_state->_w.callStack)) {
- ImGui::Text("%s", lingo->formatCallStack(lingo->_state->pc).c_str());
- }
- ImGui::End();
-}
-
static void cacheVars() {
// take a snapshot of the variables every 500 ms
if ((g_director->getTotalPlayTime() - _state->_vars._lastTimeRefreshed) > 500) {
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index 89ff48d4f2d..059e1830879 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -351,5 +351,63 @@ void showFuncList() {
ImGui::End();
}
+void showExecutionContext() {
+ if (!_state->_w.executionContext)
+ return;
+
+ ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(360, 240), ImGuiCond_FirstUseEver);
+
+ Director::Lingo *lingo = g_director->getLingo();
+
+ if (ImGui::Begin("Execution Context", &_state->_w.executionContext)) {
+ if (ImGui::CollapsingHeader("Backtrace", ImGuiTreeNodeFlags_DefaultOpen)) {
+ ImGui::Text("%s", lingo->formatCallStack(lingo->_state->pc).c_str());
+ }
+
+ if (ImGui::CollapsingHeader("Scripts", ImGuiTreeNodeFlags_DefaultOpen)) {
+ updateCurrentScript();
+
+ if (_state->_functions._showScript) {
+ const char *currentScript = nullptr;
+
+ if (_state->_functions._current < _state->_functions._scripts.size()) {
+ currentScript = _state->_functions._scripts[_state->_functions._current].handlerName.c_str();
+ }
+
+ if (ImGui::BeginCombo("##handlers", currentScript)) {
+ for (uint i = 0; i < _state->_functions._scripts.size(); i++) {
+ auto &script = _state->_functions._scripts[i];
+ bool selected = i == _state->_functions._current;
+ if (ImGui::Selectable(script.handlerName.c_str(), &selected)) {
+ _state->_functions._current = i;
+ }
+ }
+ ImGui::EndCombo();
+ }
+
+ if (!_state->_functions._scripts[_state->_functions._current].oldAst) {
+ ImGui::SameLine(0, 20);
+ ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &_state->_functions._showByteCode, true); // Lingo
+ ImGui::SetItemTooltip("Lingo");
+ ImGui::SameLine();
+
+ ImGuiEx::toggleButton(ICON_MS_STACKS, &_state->_functions._showByteCode); // Bytecode
+ ImGui::SetItemTooltip("Bytecode");
+ }
+
+ ImGui::Separator();
+ const ImVec2 childsize = ImGui::GetContentRegionAvail();
+ ImGui::BeginChild("##script", childsize);
+ ImGuiScript &script = _state->_functions._scripts[_state->_functions._current];
+ renderScript(script, _state->_functions._showByteCode);
+ ImGui::EndChild();
+ }
+ }
+ }
+ ImGui::End();
+
+}
+
} // namespace DT
} // namespace Director
Commit: 76067a905dee90657e3ed989b7d2b9aadf2ce2a7
https://github.com/scummvm/scummvm/commit/76067a905dee90657e3ed989b7d2b9aadf2ce2a7
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Add execution context for multiple windows
Expanding the Execution Context Window
Changed paths:
engines/director/debugger/dt-scripts.cpp
engines/director/lingo/lingo-object.cpp
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index 059e1830879..2722b4e4c58 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -25,6 +25,7 @@
#include "director/debugger/dt-internal.h"
#include "director/archive.h"
+#include "director/window.h"
#include "director/cast.h"
#include "director/debugger.h"
#include "director/movie.h"
@@ -356,19 +357,120 @@ void showExecutionContext() {
return;
ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
- ImGui::SetNextWindowSize(ImVec2(360, 240), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(600, 500), ImGuiCond_FirstUseEver);
Director::Lingo *lingo = g_director->getLingo();
if (ImGui::Begin("Execution Context", &_state->_w.executionContext)) {
- if (ImGui::CollapsingHeader("Backtrace", ImGuiTreeNodeFlags_DefaultOpen)) {
- ImGui::Text("%s", lingo->formatCallStack(lingo->_state->pc).c_str());
+ const Common::Array<Window *> *windowList = g_director->getWindowList();
+
+ ImGui::PushID(0);
+ ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg));
+
+ ImGui::BeginChild("Window##", ImVec2(350.0f, 450.0f), ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY);
+ ImGui::Text("%s", g_director->getStage()->asString().c_str());
+
+ ImGui::SeparatorText("Backtrace");
+ ImGui::Text("%s", lingo->formatCallStack(lingo->_state->pc).c_str());
+
+ ImGui::SeparatorText("Scripts");
+ updateCurrentScript();
+
+ if (_state->_functions._showScript) {
+ ImGui::BeginDisabled(_state->_functions._scripts.empty() || _state->_functions._current == 0);
+ if (ImGui::Button(ICON_MS_ARROW_BACK)) {
+ _state->_functions._current--;
+ }
+ ImGui::EndDisabled();
+ ImGui::SetItemTooltip("Backward");
+ ImGui::SameLine();
+
+ ImGui::BeginDisabled(_state->_functions._current >= _state->_functions._scripts.size() - 1);
+ if (ImGui::Button(ICON_MS_ARROW_FORWARD)) {
+ _state->_functions._current++;
+ }
+ ImGui::EndDisabled();
+ ImGui::SetItemTooltip("Forward");
+ ImGui::SameLine();
+
+ const char *currentScript = nullptr;
+
+ if (_state->_functions._current < _state->_functions._scripts.size()) {
+ currentScript = _state->_functions._scripts[_state->_functions._current].handlerName.c_str();
+ }
+
+ if (ImGui::BeginCombo("##handlers", currentScript)) {
+ for (uint i = 0; i < _state->_functions._scripts.size(); i++) {
+ auto &script = _state->_functions._scripts[i];
+ bool selected = i == _state->_functions._current;
+ if (ImGui::Selectable(script.handlerName.c_str(), &selected)) {
+ _state->_functions._current = i;
+ }
+ }
+ ImGui::EndCombo();
+ }
+
+ if (!_state->_functions._scripts[_state->_functions._current].oldAst) {
+ ImGui::SameLine(0, 20);
+ ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &_state->_functions._showByteCode, true); // Lingo
+ ImGui::SetItemTooltip("Lingo");
+ ImGui::SameLine();
+
+ ImGuiEx::toggleButton(ICON_MS_STACKS, &_state->_functions._showByteCode); // Bytecode
+ ImGui::SetItemTooltip("Bytecode");
+ }
+
+ ImGui::Separator();
+ const ImVec2 childsize = ImGui::GetContentRegionAvail();
+ ImGui::BeginChild("##script", childsize);
+ ImGuiScript &script = _state->_functions._scripts[_state->_functions._current];
+ renderScript(script, _state->_functions._showByteCode);
+ ImGui::EndChild();
}
- if (ImGui::CollapsingHeader("Scripts", ImGuiTreeNodeFlags_DefaultOpen)) {
+ ImGui::EndChild();
+ ImGui::PopStyleColor();
+ ImGui::PopID();
+
+ int windowID = 1;
+ ImGui::SameLine();
+
+ Window *mainWindow = g_director->getCurrentWindow();
+
+ for (auto window : (*windowList)) {
+ g_director->setCurrentWindow(window);
+ g_lingo->switchStateFromWindow();
+
+ ImGui::PushID(windowID);
+ ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg));
+
+ ImGui::BeginChild("Window##", ImVec2(350.0f, 450.0f), ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY);
+
+ ImGui::Text("%s", window->asString().c_str());
+
+ ImGui::SeparatorText("Backtrace");
+ ImGui::Text("%s", lingo->formatCallStack(lingo->_state->pc).c_str());
+
+ ImGui::SeparatorText("Scripts");
updateCurrentScript();
if (_state->_functions._showScript) {
+ ImGui::BeginDisabled(_state->_functions._scripts.empty() || _state->_functions._current == 0);
+ if (ImGui::Button(ICON_MS_ARROW_BACK)) {
+ _state->_functions._current--;
+ }
+ ImGui::EndDisabled();
+ ImGui::SetItemTooltip("Backward");
+ ImGui::SameLine();
+
+ ImGui::BeginDisabled(_state->_functions._current >= _state->_functions._scripts.size() - 1);
+ if (ImGui::Button(ICON_MS_ARROW_FORWARD)) {
+ _state->_functions._current++;
+ }
+ ImGui::EndDisabled();
+ ImGui::SetItemTooltip("Forward");
+ ImGui::SameLine();
+
const char *currentScript = nullptr;
if (_state->_functions._current < _state->_functions._scripts.size()) {
@@ -403,7 +505,16 @@ void showExecutionContext() {
renderScript(script, _state->_functions._showByteCode);
ImGui::EndChild();
}
+
+ ImGui::EndChild();
+ ImGui::PopStyleColor();
+ ImGui::PopID();
+
+ windowID++;
}
+
+ g_director->setCurrentWindow(mainWindow);
+ g_lingo->switchStateFromWindow();
}
ImGui::End();
diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index 0a83ff1aea8..ee3ecdcb506 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -724,7 +724,7 @@ void LM::m_respondsTo(int nargs) {
// Window
Common::String Window::asString() {
- return "window \"" + getName() + "\"";
+ return "Window \"" + getName() + "\"";
}
bool Window::hasProp(const Common::String &propName) {
Commit: 4de416208e62e9ee28ba95c511ad12ac51061246
https://github.com/scummvm/scummvm/commit/4de416208e62e9ee28ba95c511ad12ac51061246
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Fix material fonts in the score window
Manually set the material font as the default font for Director
ImGui debugger
Changed paths:
engines/director/debugger/debugtools.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index ea3ffb5d786..9ab219f534e 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -302,7 +302,7 @@ void onImGuiInit() {
icons_config.GlyphOffset = {0, 4};
static const ImWchar icons_ranges[] = {ICON_MIN_MS, ICON_MAX_MS, 0};
- ImGui::addTTFFontFromArchive("MaterialSymbolsSharp.ttf", 16.f, &icons_config, icons_ranges);
+ io.FontDefault = ImGui::addTTFFontFromArchive("MaterialSymbolsSharp.ttf", 16.f, &icons_config, icons_ranges);
_state = new ImGuiState();
Commit: a30d2bd0bbebfa31e88e91ad82f1030a5fc65459
https://github.com/scummvm/scummvm/commit/a30d2bd0bbebfa31e88e91ad82f1030a5fc65459
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Removed the `DT::showScripts()` function
Refactored it to the `DT::showExecutionContext()`
Changed paths:
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-scripts.cpp
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index af2800e3d3e..4c0b85e9eed 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -198,7 +198,6 @@ void showCast(); // dt-cast.cpp
void showControlPanel(); // dt-controlpanel.cpp
// dt-lists.cpp
-void showCallStack();
void showVars();
void showWatchedVars();
void showBreakpointList();
@@ -214,7 +213,6 @@ void renderScriptAST(ImGuiScript &script, bool showByteCode); // dt-script
// dt-scripts.cpp
void showFuncList();
void showScriptCasts();
-void showScripts();
void showExecutionContext();
extern ImGuiState *_state;
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index 2722b4e4c58..7162bb82d88 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -179,68 +179,6 @@ static void updateCurrentScript() {
setScriptToDisplay(script);
}
-void showScripts() {
- updateCurrentScript();
-
- if (!_state->_functions._showScript)
- return;
-
- ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
- ImGui::SetNextWindowSize(ImVec2(240, 240), ImGuiCond_FirstUseEver);
-
- if (ImGui::Begin("Script", &_state->_functions._showScript)) {
- ImGui::BeginDisabled(_state->_functions._scripts.empty() || _state->_functions._current == 0);
- if (ImGui::Button(ICON_MS_ARROW_BACK)) {
- _state->_functions._current--;
- }
- ImGui::EndDisabled();
- ImGui::SetItemTooltip("Backward");
- ImGui::SameLine();
-
- ImGui::BeginDisabled(_state->_functions._current >= _state->_functions._scripts.size() - 1);
- if (ImGui::Button(ICON_MS_ARROW_FORWARD)) {
- _state->_functions._current++;
- }
- ImGui::EndDisabled();
- ImGui::SetItemTooltip("Forward");
- ImGui::SameLine();
-
- const char *currentScript = nullptr;
- if (_state->_functions._current < _state->_functions._scripts.size()) {
- currentScript = _state->_functions._scripts[_state->_functions._current].handlerName.c_str();
- }
-
- if (ImGui::BeginCombo("##handlers", currentScript)) {
- for (uint i = 0; i < _state->_functions._scripts.size(); i++) {
- auto &script = _state->_functions._scripts[i];
- bool selected = i == _state->_functions._current;
- if (ImGui::Selectable(script.handlerName.c_str(), &selected)) {
- _state->_functions._current = i;
- }
- }
- ImGui::EndCombo();
- }
-
- if (!_state->_functions._scripts[_state->_functions._current].oldAst) {
- ImGui::SameLine(0, 20);
- ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &_state->_functions._showByteCode, true); // Lingo
- ImGui::SetItemTooltip("Lingo");
- ImGui::SameLine();
-
- ImGuiEx::toggleButton(ICON_MS_STACKS, &_state->_functions._showByteCode); // Bytecode
- ImGui::SetItemTooltip("Bytecode");
- }
-
- ImGui::Separator();
- const ImVec2 childsize = ImGui::GetContentRegionAvail();
- ImGui::BeginChild("##script", childsize);
- ImGuiScript &script = _state->_functions._scripts[_state->_functions._current];
- renderScript(script, _state->_functions._showByteCode);
- ImGui::EndChild();
- }
- ImGui::End();
-}
-
static Common::String getHandlerName(Symbol &sym) {
Common::String handlerName;
Commit: 58b11ed906ecbe71cbf35776805722c0b8b74c6d
https://github.com/scummvm/scummvm/commit/58b11ed906ecbe71cbf35776805722c0b8b74c6d
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Render global variables using `renderVar()` instead of
normal text
Changed paths:
engines/director/debugger/dt-script-d4.cpp
diff --git a/engines/director/debugger/dt-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index faf8590aded..b99fc49231f 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -1008,7 +1008,7 @@ private:
ImGui::Text(",");
ImGui::SameLine();
}
- ImGui::TextColored(_state->_colors._var_color, "%s", _script.globalNames[i].c_str());
+ renderVar(_script.globalNames[i]);
ImGui::SameLine();
}
}
Commit: 99b90ab7c20ce9c7f660a0980fd16495721a26d1
https://github.com/scummvm/scummvm/commit/99b90ab7c20ce9c7f660a0980fd16495721a26d1
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Remove Script flicker from Execution Context Window
Render the backtrace in a child rather than as plain text
Make the size of the window one third of the entire Execution Window
Changed paths:
engines/director/debugger/dt-scripts.cpp
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index 7162bb82d88..adefeff478b 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -305,11 +305,15 @@ void showExecutionContext() {
ImGui::PushID(0);
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg));
- ImGui::BeginChild("Window##", ImVec2(350.0f, 450.0f), ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY);
+ ImGui::BeginChild("Window##", ImVec2(500.0f, 700.0f));
ImGui::Text("%s", g_director->getStage()->asString().c_str());
ImGui::SeparatorText("Backtrace");
+ ImVec2 childSize = ImGui::GetContentRegionAvail();
+ childSize.y /= 3;
+ ImGui::BeginChild("##backtrace", childSize);
ImGui::Text("%s", lingo->formatCallStack(lingo->_state->pc).c_str());
+ ImGui::EndChild();
ImGui::SeparatorText("Scripts");
updateCurrentScript();
@@ -387,7 +391,11 @@ void showExecutionContext() {
ImGui::Text("%s", window->asString().c_str());
ImGui::SeparatorText("Backtrace");
+ ImVec2 childsize = ImGui::GetContentRegionAvail();
+ childsize.y /= 3;
+ ImGui::BeginChild("##backtrace", childsize);
ImGui::Text("%s", lingo->formatCallStack(lingo->_state->pc).c_str());
+ ImGui::EndChild();
ImGui::SeparatorText("Scripts");
updateCurrentScript();
Commit: 26c929873e2c795d40e138830c9a5a4aa098a899
https://github.com/scummvm/scummvm/commit/26c929873e2c795d40e138830c9a5a4aa098a899
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Fix error pop-up in Vars window while hovering over
variables
Changed paths:
engines/director/debugger/dt-lists.cpp
diff --git a/engines/director/debugger/dt-lists.cpp b/engines/director/debugger/dt-lists.cpp
index a57fad01073..7b55f5d2ab6 100644
--- a/engines/director/debugger/dt-lists.cpp
+++ b/engines/director/debugger/dt-lists.cpp
@@ -62,12 +62,17 @@ void showVars() {
keyBuffer.push_back(it._key);
}
Common::sort(keyBuffer.begin(), keyBuffer.end());
+
+ uint32 id = 0;
for (auto &i : keyBuffer) {
+ ImGui::PushID(id);
Datum &val = _state->_vars._globals.getVal(i);
bool changed = !_state->_vars._prevGlobals.contains(i) || !(_state->_vars._globals.getVal(i) == _state->_vars._prevGlobals.getVal(i));
displayVariable(i, changed);
ImGui::SameLine();
ImGui::Text(" - [%s] %s", val.type2str(), formatStringForDump(val.asString(true)).c_str());
+ ImGui::PopID();
+ id += 1;
}
keyBuffer.clear();
}
@@ -77,12 +82,17 @@ void showVars() {
keyBuffer.push_back(it._key);
}
Common::sort(keyBuffer.begin(), keyBuffer.end());
+
+ uint32 id = 0;
for (auto &i : keyBuffer) {
+ ImGui::PushID(id);
Datum &val = _state->_vars._locals.getVal(i);
bool changed = !_state->_vars._prevLocals.contains(i) || !(_state->_vars._locals.getVal(i) == _state->_vars._prevLocals.getVal(i));
displayVariable(i, changed);
ImGui::SameLine();
ImGui::Text(" - [%s] %s", val.type2str(), formatStringForDump(val.asString(true)).c_str());
+ ImGui::PopID();
+ id += 1;
}
keyBuffer.clear();
} else {
@@ -96,11 +106,16 @@ void showVars() {
keyBuffer.push_back(script->getPropAt(i));
}
Common::sort(keyBuffer.begin(), keyBuffer.end());
+
+ uint32 id = 0;
for (auto &i : keyBuffer) {
+ ImGui::PushID(id);
Datum val = script->getProp(i);
displayVariable(i, false);
ImGui::SameLine();
ImGui::Text(" - [%s] %s", val.type2str(), formatStringForDump(val.asString(true)).c_str());
+ ImGui::PopID();
+ id += 1;
}
keyBuffer.clear();
} else {
Commit: f2a6736bb342491989070e9915fe88d723289107
https://github.com/scummvm/scummvm/commit/f2a6736bb342491989070e9915fe88d723289107
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Show variable name when hovering over
Changed paths:
engines/director/debugger/dt-script-d4.cpp
diff --git a/engines/director/debugger/dt-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index b99fc49231f..264a3ac03ae 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -943,6 +943,7 @@ private:
if (ImGui::IsItemHovered() && g_lingo->_globalvars.contains(varName)) {
const Datum &val = g_lingo->_globalvars.getVal(varName);
ImGui::BeginTooltip();
+ ImGui::Text("%s", varName.c_str());
ImGui::Text("Click to add to watches.");
Common::String s = val.asString(true);
s.wordWrap(150);
Commit: 2fbf88e2a00a847cfdb4494ce53848150f8cde82
https://github.com/scummvm/scummvm/commit/2fbf88e2a00a847cfdb4494ce53848150f8cde82
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Improve Search for handler in `getHandler()`
Only search the cast that has the same castLibID as the
CastMemberInfo object passed to the function
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-scripts.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 9ab219f534e..92bbef9ca33 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -62,13 +62,13 @@ const LingoDec::Handler *getHandler(const Cast *cast, CastMemberID id, const Com
}
const LingoDec::Handler *getHandler(CastMemberID id, const Common::String &handlerId) {
- const Director::Movie *movie = g_director->getCurrentMovie();
- for (const auto it : *movie->getCasts()) {
- const Cast *cast = it._value;
- const LingoDec::Handler *handler = getHandler(cast, id, handlerId);
- if (handler)
- return handler;
- }
+ const Director::Movie *movie = g_director->getCurrentMovie();;
+ const Cast *cast = movie->getCasts()->getVal(id.castLib);
+
+ const LingoDec::Handler *handler = getHandler(cast, id, handlerId);
+ if (handler)
+ return handler;
+
return getHandler(movie->getSharedCast(), id, handlerId);
}
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index adefeff478b..00d106ee0b1 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -166,6 +166,7 @@ static void updateCurrentScript() {
Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
if (callstack.empty())
return;
+ }
// show current script of the current stack frame
CFrame *head = callstack[callstack.size() - 1];
Commit: 643d866abdbcbba01e7266da21be99104c31ec1d
https://github.com/scummvm/scummvm/commit/643d866abdbcbba01e7266da21be99104c31ec1d
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Show handlers from the same context in the same window
For better navigation
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-scripts.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 92bbef9ca33..992c1a29998 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -106,6 +106,18 @@ ImGuiScript toImGuiScript(ScriptType scriptType, CastMemberID id, const Common::
return result;
}
+ScriptContext *getScriptContext(CastMemberID id) {
+ const Director::Movie *movie = g_director->getCurrentMovie();;
+ const Cast *cast = movie->getCasts()->getVal(id.castLib);
+
+ if (!cast) {
+ return nullptr;
+ }
+
+ ScriptContext *ctx = cast->_lingoArchive->findScriptContext(id.member);
+ return ctx;
+}
+
Director::Breakpoint *getBreakpoint(const Common::String &handlerName, uint16 scriptId, uint pc) {
auto &bps = g_lingo->getBreakpoints();
for (uint i = 0; i < bps.size(); i++) {
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index 4c0b85e9eed..f677da2a593 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -185,6 +185,7 @@ typedef struct ImGuiState {
// debugtools.cpp
ImGuiScript toImGuiScript(ScriptType scriptType, CastMemberID id, const Common::String &handlerId);
+ScriptContext *getScriptContext(CastMemberID id);
void setScriptToDisplay(const ImGuiScript &script);
Director::Breakpoint *getBreakpoint(const Common::String &handlerName, uint16 scriptId, uint pc);
void displayScriptRef(CastMemberID &scriptId);
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index 00d106ee0b1..a3f4cf1c4fa 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -366,8 +366,25 @@ void showExecutionContext() {
ImGui::Separator();
const ImVec2 childsize = ImGui::GetContentRegionAvail();
ImGui::BeginChild("##script", childsize);
- ImGuiScript &script = _state->_functions._scripts[_state->_functions._current];
- renderScript(script, _state->_functions._showByteCode);
+ ImGuiScript ¤t = _state->_functions._scripts[_state->_functions._current];
+
+ // Get all the handlers from the script
+ ScriptContext* context = getScriptContext(current.id);
+ Movie *movie = g_director->getCurrentMovie();
+
+ if (!context || context->_functionHandlers.size() == 1) {
+ renderScript(current, _state->_functions._showByteCode);
+ } else {
+ for (auto &functionHandler : context->_functionHandlers) {
+ ImGuiScript script = toImGuiScript(context->_scriptType, current.id, functionHandler._key);
+ script.byteOffsets = context->_functionByteOffsets[script.handlerId];
+ script.moviePath = movie->getArchive()->getPathName().toString();
+ script.handlerName = getHandlerName(functionHandler._value);
+ renderScript(script, _state->_functions._showByteCode);
+ ImGui::NewLine();
+ }
+ }
+
ImGui::EndChild();
}
@@ -448,8 +465,25 @@ void showExecutionContext() {
ImGui::Separator();
const ImVec2 childsize = ImGui::GetContentRegionAvail();
ImGui::BeginChild("##script", childsize);
- ImGuiScript &script = _state->_functions._scripts[_state->_functions._current];
- renderScript(script, _state->_functions._showByteCode);
+ ImGuiScript ¤t = _state->_functions._scripts[_state->_functions._current];
+
+ // Get all the handlers from the script
+ ScriptContext* context = getScriptContext(current.id);
+ Movie *movie = g_director->getCurrentMovie();
+
+ if (!context || context->_functionHandlers.size() == 1) {
+ renderScript(current, _state->_functions._showByteCode);
+ } else {
+ for (auto &functionHandler : context->_functionHandlers) {
+ ImGuiScript script = toImGuiScript(context->_scriptType, current.id, functionHandler._key);
+ script.byteOffsets = context->_functionByteOffsets[script.handlerId];
+ script.moviePath = movie->getArchive()->getPathName().toString();
+ script.handlerName = getHandlerName(functionHandler._value);
+ renderScript(script, _state->_functions._showByteCode);
+ ImGui::NewLine();
+ }
+ }
+
ImGui::EndChild();
}
Commit: 3d166f02a2087ba42cdc09ff911ebad041d07d0a
https://github.com/scummvm/scummvm/commit/3d166f02a2087ba42cdc09ff911ebad041d07d0a
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Remove new line when showing Prop list
Instead of
```
propList = [
a, b, c, d]
```
Output
```
propList = [a, b, c, d]
```
Changed paths:
engines/director/debugger/dt-script-d4.cpp
diff --git a/engines/director/debugger/dt-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index 264a3ac03ae..960b920e99c 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -916,6 +916,7 @@ private:
return;
case LingoDec::kDatumPropList: {
ImGui::Text("[");
+ ImGui::SameLine();
if (datum.l.size() == 0) {
ImGui::Text(":");
ImGui::SameLine();
Commit: 65b159b1526ce412d57ed1077f63031c43b9b419
https://github.com/scummvm/scummvm/commit/65b159b1526ce412d57ed1077f63031c43b9b419
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Minor change in `windowID` increment position
Moved it to right above its use in `ImGui::PushID`
Changed paths:
engines/director/debugger/dt-scripts.cpp
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index a3f4cf1c4fa..a164abfe8ea 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -490,8 +490,6 @@ void showExecutionContext() {
ImGui::EndChild();
ImGui::PopStyleColor();
ImGui::PopID();
-
- windowID++;
}
g_director->setCurrentWindow(mainWindow);
Commit: 2f5ec4278988d687d740d9da61aa4c6db6634e01
https://github.com/scummvm/scummvm/commit/2f5ec4278988d687d740d9da61aa4c6db6634e01
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Implement `Save State` and `Load State`
Only saving the whether a certain window is on or off
Changed paths:
A engines/director/debugger/dt-save-state.cpp
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-scripts.cpp
engines/director/module.mk
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 992c1a29998..4bb72c9d547 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -376,8 +376,10 @@ void onImGuiRender() {
ImGui::SeparatorText("Misc");
if (ImGui::MenuItem("Save state")) {
+ saveCurrentState();
}
if (ImGui::MenuItem("Load state")) {
+ loadSavedState();
}
ImGui::Separator();
ImGui::MenuItem("Settings", NULL, &_state->_w.settings);
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index f677da2a593..5ef63a84bf5 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -84,7 +84,6 @@ typedef struct ImGuiScript {
typedef struct ImGuiWindows {
bool controlPanel = true;
- bool callStack = false;
bool vars = false;
bool channels = false;
bool cast = false;
@@ -216,7 +215,9 @@ void showFuncList();
void showScriptCasts();
void showExecutionContext();
-extern ImGuiState *_state;
+// dt-save-state.cpp
+void saveCurrentState();
+void loadSavedState();
}
diff --git a/engines/director/debugger/dt-save-state.cpp b/engines/director/debugger/dt-save-state.cpp
new file mode 100644
index 00000000000..b8b6508fa59
--- /dev/null
+++ b/engines/director/debugger/dt-save-state.cpp
@@ -0,0 +1,99 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/formats/json.h"
+#include "common/memstream.h"
+#include "common/savefile.h"
+#include "common/file.h"
+
+#include "director/director.h"
+#include "director/debugger/dt-internal.h"
+
+namespace Director {
+namespace DT {
+
+Common::String savedStateFileName = Common::String("ImGuiSaveState.json");
+
+// What are the things that need saving?
+// 1) Window Positions
+// 2) Score frame number
+// 3) Windows that are open/closed
+// 4) Watched Variables
+void saveCurrentState() {
+ Common::JSONObject json = Common::JSONObject();
+
+ // Whether windows are open or not
+ long long int openFlags = 0;
+ openFlags += (_state->_w.archive) ? 1 : 0;
+ openFlags += (_state->_w.bpList) ? 1 << 1 : 0;
+ openFlags += (_state->_w.cast) ? 1 << 2 : 0;
+ openFlags += (_state->_w.channels) ? 1 << 3 : 0;
+ openFlags += (_state->_w.controlPanel) ? 1 << 4 : 0;
+ openFlags += (_state->_w.executionContext) ? 1 << 5 : 0;
+ openFlags += (_state->_w.funcList) ? 1 << 6: 0;
+ openFlags += (_state->_w.logger) ? 1 << 7 : 0;
+ openFlags += (_state->_w.score) ? 1 << 8 : 0;
+ openFlags += (_state->_w.settings) ? 1 << 9 : 0;
+ openFlags += (_state->_w.vars) ? 1 << 10 : 0;
+ openFlags += (_state->_w.watchedVars) ? 1 << 11 : 0;
+
+ json["Windows"] = new Common::JSONValue(openFlags);
+ Common::JSONValue save(json);
+
+ debug("ImGui::saved state: %s", save.stringify().c_str());
+
+ Common::OutSaveFile *stream = g_engine->getSaveFileManager()->openForSaving(savedStateFileName);
+ stream->writeString(save.stringify());
+
+ if (stream) {
+ stream->flush();
+ debugC(-1, kDebugImGui, "Saved the current ImGui State @%s", savedStateFileName.c_str());
+ }
+
+ delete stream;
+}
+
+void loadSavedState() {
+ Common::InSaveFile *savedState = g_engine->getSaveFileManager()->openForLoading(savedStateFileName);
+ char *data = (char *)malloc(savedState->size());
+ savedState->read(data, savedState->size());
+
+ Common::JSONValue *saved = Common::JSON::parse(data);
+ debug("ImGui::loaded state: %s", saved->stringify().c_str());
+
+ long long int openFlags = saved->asObject()["Windows"]->asIntegerNumber();
+
+ _state->_w.archive = (openFlags & 1) ? true : false;
+ _state->_w.bpList = (openFlags & 1 << 1) ? true : false;
+ _state->_w.cast = (openFlags & 1 << 2) ? true : false;
+ _state->_w.channels = (openFlags & 1 << 3) ? true : false;
+ _state->_w.controlPanel = (openFlags & 1 << 4) ? true : false;
+ _state->_w.executionContext = (openFlags & 1 << 5) ? true : false;
+ _state->_w.funcList = (openFlags & 1 << 6) ? true : false;
+ _state->_w.logger = (openFlags & 1 << 7) ? true : false;
+ _state->_w.score = (openFlags & 1 << 8) ? true : false;
+ _state->_w.settings = (openFlags & 1 << 9) ? true : false;
+ _state->_w.vars = (openFlags & 1 << 10) ? true : false;
+ _state->_w.watchedVars = (openFlags & 1 << 11) ? true : false;
+}
+
+} // End of namespace DT
+} // End of namespace Director
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index a164abfe8ea..0d107776421 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -112,7 +112,7 @@ static void renderScript(ImGuiScript &script, bool showByteCode) {
}
static bool showScriptCast(CastMemberID &id) {
- Common::String wName("Script ");
+ Common::String wName("Script ");;
wName += id.asString();
ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
diff --git a/engines/director/module.mk b/engines/director/module.mk
index ae958a5c596..2c01865c7bc 100644
--- a/engines/director/module.mk
+++ b/engines/director/module.mk
@@ -188,6 +188,7 @@ MODULE_OBJS += \
debugger/dt-cast.o \
debugger/dt-controlpanel.o \
debugger/dt-lists.o \
+ debugger/dt-save-state.o \
debugger/dt-score.o \
debugger/dt-script-d2.o \
debugger/dt-script-d4.o \
Commit: 736b80735b878480075b165444bda3d02306a166
https://github.com/scummvm/scummvm/commit/736b80735b878480075b165444bda3d02306a166
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Fix segmentation faults in the loadCurrentState
Also separate out functions `getWindowFlags`/`setWindowFlags`
Changed paths:
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-save-state.cpp
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index 5ef63a84bf5..3676a79e26b 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -218,6 +218,8 @@ void showExecutionContext();
// dt-save-state.cpp
void saveCurrentState();
void loadSavedState();
+long long int getWindowFlags();
+void setWindowFlags(long long int openFlags);
}
diff --git a/engines/director/debugger/dt-save-state.cpp b/engines/director/debugger/dt-save-state.cpp
index b8b6508fa59..21897e49faa 100644
--- a/engines/director/debugger/dt-save-state.cpp
+++ b/engines/director/debugger/dt-save-state.cpp
@@ -19,6 +19,7 @@
*
*/
+#include "backends/imgui/imgui_utils.h"
#include "common/formats/json.h"
#include "common/memstream.h"
#include "common/savefile.h"
@@ -31,6 +32,10 @@ namespace Director {
namespace DT {
Common::String savedStateFileName = Common::String("ImGuiSaveState.json");
+const char *WINDOW_LIST[] = {
+ "Archive", "Breakpoints", "Vars", "Watched Vars", "Score", "Control Panel",
+ "Execution Context", "Functions", "Channels", "Cast", "Settings"
+};
// What are the things that need saving?
// 1) Window Positions
@@ -41,6 +46,32 @@ void saveCurrentState() {
Common::JSONObject json = Common::JSONObject();
// Whether windows are open or not
+ long long int openFlags = getWindowFlags();
+ json["Windows"] = new Common::JSONValue(openFlags);
+
+ // Save the JSON
+ Common::JSONValue save(json);
+ debug("ImGui::Saved state: %s", save.stringify().c_str());
+
+ Common::OutSaveFile *stream = g_engine->getSaveFileManager()->openForSaving(savedStateFileName);
+
+ if (stream) {
+ stream->writeString(save.stringify());
+ stream->finalize();
+ debug("ImGui::SaveCurrentState: Saved the current ImGui State @%s", savedStateFileName.c_str());
+ } else {
+ debug("ImGui::SaveCurrentState: Failed to open the file %s for saving", savedStateFileName.c_str());
+ }
+
+ // Clean up everything
+ {
+ delete stream;
+ delete json["Windows"];
+ delete json["Window Positions"];
+ }
+}
+
+long long int getWindowFlags() {
long long int openFlags = 0;
openFlags += (_state->_w.archive) ? 1 : 0;
openFlags += (_state->_w.bpList) ? 1 << 1 : 0;
@@ -55,32 +86,34 @@ void saveCurrentState() {
openFlags += (_state->_w.vars) ? 1 << 10 : 0;
openFlags += (_state->_w.watchedVars) ? 1 << 11 : 0;
- json["Windows"] = new Common::JSONValue(openFlags);
- Common::JSONValue save(json);
-
- debug("ImGui::saved state: %s", save.stringify().c_str());
-
- Common::OutSaveFile *stream = g_engine->getSaveFileManager()->openForSaving(savedStateFileName);
- stream->writeString(save.stringify());
-
- if (stream) {
- stream->flush();
- debugC(-1, kDebugImGui, "Saved the current ImGui State @%s", savedStateFileName.c_str());
- }
-
- delete stream;
+ return openFlags;
}
void loadSavedState() {
Common::InSaveFile *savedState = g_engine->getSaveFileManager()->openForLoading(savedStateFileName);
+
+ if (!savedState) {
+ debug("ImGui::loadSavedState(): Failed to open saved state file: %s", savedStateFileName.c_str());
+ return;
+ }
+
char *data = (char *)malloc(savedState->size());
savedState->read(data, savedState->size());
Common::JSONValue *saved = Common::JSON::parse(data);
- debug("ImGui::loaded state: %s", saved->stringify().c_str());
+
+ if (!saved) {
+ debug("ImGui:: Bad JSON: Failed to parse the Saved state");
+ return;
+ }
+
+ debug("ImGui::loaded state: %s", saved->stringify(true).c_str());
long long int openFlags = saved->asObject()["Windows"]->asIntegerNumber();
+ setWindowFlags(openFlags);
+}
+void setWindowFlags(long long int openFlags) {
_state->_w.archive = (openFlags & 1) ? true : false;
_state->_w.bpList = (openFlags & 1 << 1) ? true : false;
_state->_w.cast = (openFlags & 1 << 2) ? true : false;
Commit: 10084ac78795f4ea480ce5d5942bb9b2d3a0e4ae
https://github.com/scummvm/scummvm/commit/10084ac78795f4ea480ce5d5942bb9b2d3a0e4ae
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Save the window settings when called `Save state`
Also load them back when called `Load state` in Director's Imgui
Debugger
Changed paths:
engines/director/debugger/dt-save-state.cpp
diff --git a/engines/director/debugger/dt-save-state.cpp b/engines/director/debugger/dt-save-state.cpp
index 21897e49faa..001dbc95d9d 100644
--- a/engines/director/debugger/dt-save-state.cpp
+++ b/engines/director/debugger/dt-save-state.cpp
@@ -49,6 +49,10 @@ void saveCurrentState() {
long long int openFlags = getWindowFlags();
json["Windows"] = new Common::JSONValue(openFlags);
+ // Window Settings
+ const char *windowSettings = ImGui::SaveIniSettingsToMemory();
+ json["Window Settings"] = new Common::JSONValue(windowSettings);
+
// Save the JSON
Common::JSONValue save(json);
debug("ImGui::Saved state: %s", save.stringify().c_str());
@@ -64,11 +68,7 @@ void saveCurrentState() {
}
// Clean up everything
- {
- delete stream;
- delete json["Windows"];
- delete json["Window Positions"];
- }
+ delete stream;
}
long long int getWindowFlags() {
@@ -109,8 +109,13 @@ void loadSavedState() {
debug("ImGui::loaded state: %s", saved->stringify(true).c_str());
+ // Load open/closed window flags
long long int openFlags = saved->asObject()["Windows"]->asIntegerNumber();
setWindowFlags(openFlags);
+
+ // Load window settings
+ const char *windowSettings = saved->asObject()["Window Settings"]->asString().c_str();
+ ImGui::LoadIniSettingsFromMemory(windowSettings);
}
void setWindowFlags(long long int openFlags) {
Commit: d08f334ece8386c2ccb7cc9a02208b815fd0beb0
https://github.com/scummvm/scummvm/commit/d08f334ece8386c2ccb7cc9a02208b815fd0beb0
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Save the current log when called `Save State`
Also load it back when called `Load state` from the ImGui Debugger
Changed paths:
backends/imgui/components/imgui_logger.h
engines/director/debugger/dt-save-state.cpp
diff --git a/backends/imgui/components/imgui_logger.h b/backends/imgui/components/imgui_logger.h
index e26910bbd5d..4a93b29a298 100644
--- a/backends/imgui/components/imgui_logger.h
+++ b/backends/imgui/components/imgui_logger.h
@@ -62,6 +62,7 @@ public:
void addLog(const char *fmt, ...) IM_FMTARGS(2);
void drawColorOptions();
void draw(const char *title, bool *p_open);
+ ImVector<char *> getItems() { return _items; }
};
} // namespace ImGuiEx
diff --git a/engines/director/debugger/dt-save-state.cpp b/engines/director/debugger/dt-save-state.cpp
index 001dbc95d9d..fbd33eee047 100644
--- a/engines/director/debugger/dt-save-state.cpp
+++ b/engines/director/debugger/dt-save-state.cpp
@@ -53,6 +53,15 @@ void saveCurrentState() {
const char *windowSettings = ImGui::SaveIniSettingsToMemory();
json["Window Settings"] = new Common::JSONValue(windowSettings);
+ // Current Log
+ ImVector<char *> currentLog = _state->_logger->getItems();
+ Common::JSONArray log;
+
+ for (auto iter : currentLog) {
+ log.push_back(new Common::JSONValue(iter));
+ }
+ json["Log"] = new Common::JSONValue(log);
+
// Save the JSON
Common::JSONValue save(json);
debug("ImGui::Saved state: %s", save.stringify().c_str());
@@ -116,6 +125,23 @@ void loadSavedState() {
// Load window settings
const char *windowSettings = saved->asObject()["Window Settings"]->asString().c_str();
ImGui::LoadIniSettingsFromMemory(windowSettings);
+
+ // Load the log
+ Common::JSONArray log = saved->asObject()["Log"]->asArray();
+
+ if (debugChannelSet(7, kDebugImGui)) {
+ debugC(7, kDebugImGui, "Loading log: \n");
+ for (auto iter: log) {
+ debugC(7, kDebugImGui, "%s", iter->asString().c_str());
+ }
+ }
+
+ _state->_logger->clear();
+ for (auto iter : log) {
+ _state->_logger->addLog(iter->asString().c_str());
+ }
+
+ free(data);
}
void setWindowFlags(long long int openFlags) {
Commit: 38cbc6e5e679478a64351d55c1f7e878134ad345
https://github.com/scummvm/scummvm/commit/38cbc6e5e679478a64351d55c1f7e878134ad345
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Out of Scope variables color difference in the Watched Vars window
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-lists.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 4bb72c9d547..0855d67452d 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -176,7 +176,7 @@ void showImage(const ImGuiImage &image, const char *name, float thumbnailSize) {
setToolTipImage(image, name);
}
-void displayVariable(const Common::String &name, bool changed) {
+void displayVariable(const Common::String &name, bool changed, bool outOfScope) {
ImU32 var_color = ImGui::GetColorU32(_state->_colors._var_ref);
ImU32 color;
@@ -201,8 +201,11 @@ void displayVariable(const Common::String &name, bool changed) {
}
}
- if (changed)
+ if (changed) {
var_color = ImGui::GetColorU32(_state->_colors._var_ref_changed);
+ } else if (outOfScope) {
+ var_color = ImGui::GetColorU32(_state->_colors._var_ref_out_of_scope);
+ }
if (color == ImGui::GetColorU32(_state->_colors._bp_color_disabled) && ImGui::IsItemHovered()) {
color = ImGui::GetColorU32(_state->_colors._bp_color_hover);
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index 3676a79e26b..27dc3316813 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -137,6 +137,7 @@ typedef struct ImGuiState {
ImVec4 _script_ref = ImColor(IM_COL32(0x7f, 0x7f, 0xff, 0xfff));
ImVec4 _var_ref = ImColor(IM_COL32(0xe6, 0xe6, 0x00, 0xff));
ImVec4 _var_ref_changed = ImColor(IM_COL32(0xFF, 0x00, 0x00, 0xFF));
+ ImVec4 _var_ref_out_of_scope = ImColor(IM_COL32(0xFF, 0x00, 0xFF, 0xFF));
} _colors;
struct {
diff --git a/engines/director/debugger/dt-lists.cpp b/engines/director/debugger/dt-lists.cpp
index 7b55f5d2ab6..382284902a3 100644
--- a/engines/director/debugger/dt-lists.cpp
+++ b/engines/director/debugger/dt-lists.cpp
@@ -140,7 +140,11 @@ void showWatchedVars() {
name.type = VARREF;
Datum val = g_lingo->varFetch(name, true);
- displayVariable(v._key, false);
+ bool outOfScope = false;
+ if (val.type == VOID) {
+ outOfScope = true;
+ }
+ displayVariable(v._key, false, outOfScope);
ImGui::SameLine();
ImGui::Text(" - [%s] %s", val.type2str(), formatStringForDump(val.asString(true)).c_str());
}
Commit: 235430e36eb833a3113c0f3569aa717c80df170d
https://github.com/scummvm/scummvm/commit/235430e36eb833a3113c0f3569aa717c80df170d
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Fix pop-up error in Watched Variables
All the variables were being generated with the same ID
Changed paths:
engines/director/debugger/dt-lists.cpp
diff --git a/engines/director/debugger/dt-lists.cpp b/engines/director/debugger/dt-lists.cpp
index 382284902a3..7d8efa8c5ea 100644
--- a/engines/director/debugger/dt-lists.cpp
+++ b/engines/director/debugger/dt-lists.cpp
@@ -135,6 +135,7 @@ void showWatchedVars() {
ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(300, 250), ImGuiCond_FirstUseEver);
if (ImGui::Begin("Watched Vars", &_state->_w.watchedVars)) {
+ int id = -1;
for (auto &v : _state->_variables) {
Datum name(v._key);
name.type = VARREF;
@@ -144,7 +145,12 @@ void showWatchedVars() {
if (val.type == VOID) {
outOfScope = true;
}
+
+ id += 1;
+ ImGui::PushID(id);
displayVariable(v._key, false, outOfScope);
+ ImGui::PopID();
+
ImGui::SameLine();
ImGui::Text(" - [%s] %s", val.type2str(), formatStringForDump(val.asString(true)).c_str());
}
Commit: 69a3b43cd94defb9c6b8781ae89386e9da694068
https://github.com/scummvm/scummvm/commit/69a3b43cd94defb9c6b8781ae89386e9da694068
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Rework execution context for separate windows
Instead of making a separate `ImGuiState` for each window
Only separate out things necessary for Window execution context
Changed paths:
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-scripts.cpp
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index 27dc3316813..04cdca3edbb 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -193,7 +193,7 @@ ImGuiImage getImageID(CastMember *castMember);
Common::String getDisplayName(CastMember *castMember);
void showImage(const ImGuiImage &image, const char *name, float thumbnailSize);
ImVec4 convertColor(uint32 color);
-void displayVariable(const Common::String &name, bool changed);
+ImVec4 convertColor(uint32 color);
void showCast(); // dt-cast.cpp
void showControlPanel(); // dt-controlpanel.cpp
@@ -222,8 +222,10 @@ void loadSavedState();
long long int getWindowFlags();
void setWindowFlags(long long int openFlags);
-}
+extern ImGuiState *_state;
+
+} // End of namespace DT
-}
+} // End of namespace Director
#endif
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index 0d107776421..ce2acb95af2 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -100,7 +100,6 @@ static void renderCastScript(Symbol &sym) {
static void renderScript(ImGuiScript &script, bool showByteCode) {
if (script.oldAst) {
renderOldScriptAST(script, showByteCode);
- _state->_dbg._isScriptDirty = false;
return;
}
@@ -108,11 +107,10 @@ static void renderScript(ImGuiScript &script, bool showByteCode) {
return;
renderScriptAST(script, showByteCode);
- _state->_dbg._isScriptDirty = false;
}
static bool showScriptCast(CastMemberID &id) {
- Common::String wName("Script ");;
+ Common::String wName("Script ");
wName += id.asString();
ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
@@ -166,7 +164,6 @@ static void updateCurrentScript() {
Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
if (callstack.empty())
return;
- }
// show current script of the current stack frame
CFrame *head = callstack[callstack.size() - 1];
@@ -296,18 +293,23 @@ void showExecutionContext() {
return;
ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
- ImGui::SetNextWindowSize(ImVec2(600, 500), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(500, 750), ImGuiCond_FirstUseEver);
Director::Lingo *lingo = g_director->getLingo();
- if (ImGui::Begin("Execution Context", &_state->_w.executionContext)) {
- const Common::Array<Window *> *windowList = g_director->getWindowList();
+ Window *currentWindow = g_director->getCurrentWindow();
+
+ if (ImGui::Begin("Execution Context", &_state->_w.executionContext, ImGuiWindowFlags_AlwaysAutoResize)) {
+ Window *stage = g_director->getStage();
+ g_director->setCurrentWindow(stage);
- ImGui::PushID(0);
+ int windowID = 0;
+ ImGui::PushID(windowID);
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg));
ImGui::BeginChild("Window##", ImVec2(500.0f, 700.0f));
- ImGui::Text("%s", g_director->getStage()->asString().c_str());
+ ImGui::Text("%s", stage->asString().c_str());
+ ImGui::Text("%s", stage->getCurrentMovie()->getMacName().c_str());
ImGui::SeparatorText("Backtrace");
ImVec2 childSize = ImGui::GetContentRegionAvail();
@@ -317,6 +319,8 @@ void showExecutionContext() {
ImGui::EndChild();
ImGui::SeparatorText("Scripts");
+
+ g_lingo->switchStateFromWindow();
updateCurrentScript();
if (_state->_functions._showScript) {
@@ -364,8 +368,8 @@ void showExecutionContext() {
}
ImGui::Separator();
- const ImVec2 childsize = ImGui::GetContentRegionAvail();
- ImGui::BeginChild("##script", childsize);
+ childSize = ImGui::GetContentRegionAvail();
+ ImGui::BeginChild("##script", childSize);
ImGuiScript ¤t = _state->_functions._scripts[_state->_functions._current];
// Get all the handlers from the script
@@ -392,30 +396,32 @@ void showExecutionContext() {
ImGui::PopStyleColor();
ImGui::PopID();
- int windowID = 1;
ImGui::SameLine();
- Window *mainWindow = g_director->getCurrentWindow();
+ const Common::Array<Window *> *windowList = g_director->getWindowList();
for (auto window : (*windowList)) {
g_director->setCurrentWindow(window);
- g_lingo->switchStateFromWindow();
+ windowID += 1;
ImGui::PushID(windowID);
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg));
- ImGui::BeginChild("Window##", ImVec2(350.0f, 450.0f), ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY);
+ ImGui::BeginChild("Window##", ImVec2(500.0f, 700.0f), ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY);
ImGui::Text("%s", window->asString().c_str());
+ ImGui::Text("%s", window->getCurrentMovie()->getMacName().c_str());
ImGui::SeparatorText("Backtrace");
- ImVec2 childsize = ImGui::GetContentRegionAvail();
- childsize.y /= 3;
- ImGui::BeginChild("##backtrace", childsize);
+ childSize = ImGui::GetContentRegionAvail();
+ childSize.y /= 3;
+ ImGui::BeginChild("##backtrace", childSize);
ImGui::Text("%s", lingo->formatCallStack(lingo->_state->pc).c_str());
ImGui::EndChild();
ImGui::SeparatorText("Scripts");
+
+ g_lingo->switchStateFromWindow();
updateCurrentScript();
if (_state->_functions._showScript) {
@@ -463,8 +469,8 @@ void showExecutionContext() {
}
ImGui::Separator();
- const ImVec2 childsize = ImGui::GetContentRegionAvail();
- ImGui::BeginChild("##script", childsize);
+ childSize = ImGui::GetContentRegionAvail();
+ ImGui::BeginChild("##script", childSize);
ImGuiScript ¤t = _state->_functions._scripts[_state->_functions._current];
// Get all the handlers from the script
@@ -491,12 +497,13 @@ void showExecutionContext() {
ImGui::PopStyleColor();
ImGui::PopID();
}
-
- g_director->setCurrentWindow(mainWindow);
- g_lingo->switchStateFromWindow();
+ // Mark the scripts not dirty after all the scripts have been rendered
+ _state->_dbg._isScriptDirty = false;
}
ImGui::End();
+ g_director->setCurrentWindow(currentWindow);
+ g_lingo->switchStateFromWindow();
}
} // namespace DT
Commit: f9a923cafe963e8c2a8ae6e564cc04abc12ba812
https://github.com/scummvm/scummvm/commit/f9a923cafe963e8c2a8ae6e564cc04abc12ba812
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Render text data in Cast window
Changed paths:
engines/director/debugger/dt-cast.cpp
engines/director/debugger/dt-internal.h
diff --git a/engines/director/debugger/dt-cast.cpp b/engines/director/debugger/dt-cast.cpp
index f7990439321..46d31776229 100644
--- a/engines/director/debugger/dt-cast.cpp
+++ b/engines/director/debugger/dt-cast.cpp
@@ -111,7 +111,7 @@ void showCast() {
return;
ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
- ImGui::SetNextWindowSize(ImVec2(520, 240), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(560, 240), ImGuiCond_FirstUseEver);
if (ImGui::Begin("Cast", &_state->_w.cast)) {
// display a toolbar with: grid/list/filters buttons + name filter
@@ -152,7 +152,7 @@ void showCast() {
ImGui::TableSetupColumn("#", 0, 20.f);
ImGui::TableSetupColumn("Script", 0, 80.f);
ImGui::TableSetupColumn("Type", 0, 80.f);
- ImGui::TableSetupColumn("Preview", 0, 32.f);
+ ImGui::TableSetupColumn("Preview", ImGuiTableColumnFlags_WidthStretch, 80.f);
ImGui::TableHeadersRow();
for (auto it : *movie->getCasts()) {
@@ -186,9 +186,35 @@ void showCast() {
ImGui::Text("%s", toString(castMember._value->_type));
ImGui::TableNextColumn();
- ImGuiImage imgID = getImageID(castMember._value);
- if (imgID.id) {
- showImage(imgID, name.c_str(), 32.f);
+ if (castMember._value->_type == kCastBitmap) {
+ ImGuiImage imgID = getImageID(castMember._value);
+ if (imgID.id) {
+ showImage(imgID, name.c_str(), 32.f);
+ }
+ } else if (castMember._value->_type == kCastText) {
+ const char *text = Common::toPrintable(((TextCastMember *)castMember._value)->_rtext).c_str();
+ ImVec2 textSize = ImGui::CalcTextSize(text);
+ float columnWidth = ImGui::GetColumnWidth();
+ float offsetX = (columnWidth - textSize.x) * 0.5f;
+
+ ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
+ ImGui::Text("%s", text);
+ } else if (castMember._value->_type == kCastButton) {
+ ImGui::PushID(castMember._value->getID());
+ ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg));
+
+ ImGui::BeginChild("Button Cast", ImVec2(200, 20), (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize));
+
+ const char *text = Common::toPrintable(((TextCastMember *)castMember._value)->_rtext).c_str();
+ ImVec2 textSize = ImGui::CalcTextSize(text);
+ float offsetX = (200 /* child size */ - textSize.x) * 0.5f;
+
+ ImGui::SetCursorPosX(offsetX);
+ ImGui::Text("%s", text);
+ ImGui::EndChild();
+
+ ImGui::PopStyleColor();
+ ImGui::PopID();
}
}
}
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index 04cdca3edbb..14b934daa8f 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -193,7 +193,7 @@ ImGuiImage getImageID(CastMember *castMember);
Common::String getDisplayName(CastMember *castMember);
void showImage(const ImGuiImage &image, const char *name, float thumbnailSize);
ImVec4 convertColor(uint32 color);
-ImVec4 convertColor(uint32 color);
+void displayVariable(const Common::String &name, bool changed, bool outOfScope = false);
void showCast(); // dt-cast.cpp
void showControlPanel(); // dt-controlpanel.cpp
Commit: 3c88e47b2a7cd86862cabb3982f0e618f7599bc3
https://github.com/scummvm/scummvm/commit/3c88e47b2a7cd86862cabb3982f0e618f7599bc3
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Render Shapes in Cast Window (only Rectangles)
Changed paths:
engines/director/castmember/richtext.h
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-cast.cpp
engines/director/debugger/dt-internal.h
diff --git a/engines/director/castmember/richtext.h b/engines/director/castmember/richtext.h
index 6a2bdd524dd..92ad1293e09 100644
--- a/engines/director/castmember/richtext.h
+++ b/engines/director/castmember/richtext.h
@@ -45,6 +45,7 @@ public:
Datum getField(int field) override;
bool setField(int field, const Datum &value) override;
+ Common::String getText() { return Common::String(_plainText); }
uint32 getCastDataSize() override;
void writeCastData(Common::SeekableWriteStream *writeStream) override;
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 0855d67452d..785103fb2e3 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -26,6 +26,7 @@
#include "director/lingo/lingodec/script.h"
#include "director/cast.h"
#include "director/castmember/bitmap.h"
+#include "director/castmember/shape.h"
#include "director/debugger.h"
#include "director/movie.h"
#include "director/picture.h"
@@ -176,6 +177,34 @@ void showImage(const ImGuiImage &image, const char *name, float thumbnailSize) {
setToolTipImage(image, name);
}
+void showShape(CastMember *cast, float thumbnailSize) {
+ // Show in a square box
+ Common::Rect bbox = cast->getBbox();
+ ImVec2 size = {thumbnailSize - 2, (thumbnailSize - 2) * bbox.height() / bbox.width()};
+
+ ImGui::BeginGroup();
+ ImVec2 screenPos = ImGui::GetCursorScreenPos();
+ ImDrawList *dl = ImGui::GetWindowDrawList();
+
+ // If there is no background, set it to white
+ if (cast->getBackColor()) {
+ dl->AddRectFilled(screenPos, screenPos + ImVec2(thumbnailSize, thumbnailSize), cast->getBackColor());
+ } else {
+ dl->AddRectFilled(screenPos, screenPos + ImVec2(thumbnailSize, thumbnailSize), 0xFFFFFFFF);
+ }
+ ImVec2 shapePos = screenPos + ImVec2(1 + (thumbnailSize - 2 - size.x) * 0.5f, 1 + (thumbnailSize - 2 - size.y) * 0.5f);
+
+ uint8 foreCol = cast->getForeColor();
+ debug("%d: bg: %x, fg: %x", cast->getBackColor(), cast->getForeColor(), cast->getID());
+
+ // The forecolor is in 8 bit format
+ dl->AddRectFilled(shapePos, shapePos + size, cast->getForeColor());
+
+ // Have to add this to make the column auto adjust to correct height
+ ImGui::Dummy(ImVec2(thumbnailSize, thumbnailSize));
+ ImGui::EndGroup();
+}
+
void displayVariable(const Common::String &name, bool changed, bool outOfScope) {
ImU32 var_color = ImGui::GetColorU32(_state->_colors._var_ref);
ImU32 color;
diff --git a/engines/director/debugger/dt-cast.cpp b/engines/director/debugger/dt-cast.cpp
index 46d31776229..99264b08891 100644
--- a/engines/director/debugger/dt-cast.cpp
+++ b/engines/director/debugger/dt-cast.cpp
@@ -27,6 +27,8 @@
#include "director/cast.h"
#include "director/castmember/bitmap.h"
#include "director/castmember/text.h"
+#include "director/castmember/shape.h"
+#include "director/castmember/richtext.h"
#include "director/castmember/script.h"
#include "director/movie.h"
#include "director/types.h"
@@ -186,39 +188,75 @@ void showCast() {
ImGui::Text("%s", toString(castMember._value->_type));
ImGui::TableNextColumn();
- if (castMember._value->_type == kCastBitmap) {
- ImGuiImage imgID = getImageID(castMember._value);
- if (imgID.id) {
- showImage(imgID, name.c_str(), 32.f);
+ float columnWidth = ImGui::GetColumnWidth();
+
+ switch (castMember._value->_type) {
+ case kCastBitmap:
+ {
+ float offsetX = (columnWidth - 32.f) * 0.5f;
+ ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
+
+ ImGuiImage imgID = getImageID(castMember._value);
+ if (imgID.id) {
+ showImage(imgID, name.c_str(), 32.f);
+ }
}
- } else if (castMember._value->_type == kCastText) {
- const char *text = Common::toPrintable(((TextCastMember *)castMember._value)->_rtext).c_str();
- ImVec2 textSize = ImGui::CalcTextSize(text);
- float columnWidth = ImGui::GetColumnWidth();
- float offsetX = (columnWidth - textSize.x) * 0.5f;
+ break;
- ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
- ImGui::Text("%s", text);
- } else if (castMember._value->_type == kCastButton) {
- ImGui::PushID(castMember._value->getID());
- ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg));
+ case kCastText:
+ {
+ const char *text = Common::toPrintable(((TextCastMember *)castMember._value)->_rtext).c_str();
+ ImVec2 textSize = ImGui::CalcTextSize(text);
+ float offsetX = (columnWidth - textSize.x) * 0.5f;
- ImGui::BeginChild("Button Cast", ImVec2(200, 20), (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize));
+ ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
+ ImGui::Text("%s", text);
+ }
+ break;
- const char *text = Common::toPrintable(((TextCastMember *)castMember._value)->_rtext).c_str();
- ImVec2 textSize = ImGui::CalcTextSize(text);
- float offsetX = (200 /* child size */ - textSize.x) * 0.5f;
+ case kCastRichText:
+ {
+ const char *text = Common::toPrintable(((RichTextCastMember *)castMember._value)->getText()).c_str();
+ ImVec2 textSize = ImGui::CalcTextSize(text);
+ float offsetX = (columnWidth - textSize.x) * 0.5f;
- ImGui::SetCursorPosX(offsetX);
- ImGui::Text("%s", text);
- ImGui::EndChild();
+ ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
+ ImGui::Text("%s", text);
+ }
+ break;
- ImGui::PopStyleColor();
- ImGui::PopID();
+ case kCastButton:
+ {
+ ImGui::PushID(castMember._value->getID());
+ ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg));
+
+ ImGui::BeginChild("Button Cast", ImVec2(columnWidth, 20) , (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize));
+
+ const char *text = Common::toPrintable(((TextCastMember *)castMember._value)->_rtext).c_str();
+ ImVec2 textSize = ImGui::CalcTextSize(text);
+ float offsetX = (columnWidth - textSize.x) * 0.5f;
+
+ ImGui::SetCursorPosX(offsetX);
+ ImGui::Text("%s", text);
+ ImGui::EndChild();
+
+ ImGui::PopStyleColor();
+ ImGui::PopID();
+ }
+ break;
+
+ case kCastShape:
+ {
+ float offsetX = (columnWidth - 32.f) * 0.5f;
+ ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
+ showShape((ShapeCastMember *)castMember._value, 32.f);
+ }
+ break;
+ default:
+ break;
}
}
}
-
ImGui::EndTable();
}
} else {
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index 14b934daa8f..eff765173e7 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -192,6 +192,7 @@ void displayScriptRef(CastMemberID &scriptId);
ImGuiImage getImageID(CastMember *castMember);
Common::String getDisplayName(CastMember *castMember);
void showImage(const ImGuiImage &image, const char *name, float thumbnailSize);
+void showShape(CastMember *cast, float thumbnailSize);
ImVec4 convertColor(uint32 color);
void displayVariable(const Common::String &name, bool changed, bool outOfScope = false);
Commit: 6856dafcb75dbabfb2953584327afbd9742f3fc3
https://github.com/scummvm/scummvm/commit/6856dafcb75dbabfb2953584327afbd9742f3fc3
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Fix multiple window script showing
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-controlpanel.cpp
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-script-d4.cpp
engines/director/debugger/dt-scripts.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 785103fb2e3..b5a4de63195 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -63,7 +63,7 @@ const LingoDec::Handler *getHandler(const Cast *cast, CastMemberID id, const Com
}
const LingoDec::Handler *getHandler(CastMemberID id, const Common::String &handlerId) {
- const Director::Movie *movie = g_director->getCurrentMovie();;
+ const Director::Movie *movie = g_director->getCurrentMovie();
const Cast *cast = movie->getCasts()->getVal(id.castLib);
const LingoDec::Handler *handler = getHandler(cast, id, handlerId);
@@ -177,6 +177,15 @@ void showImage(const ImGuiImage &image, const char *name, float thumbnailSize) {
setToolTipImage(image, name);
}
+// ImGuiImage getShapeID(CastMember *castMember) {
+// if (castMember->_type != CastType::kCastShape)
+// return {};
+
+// ShapeCastMember *shapeMember = (ShapeCastMember *)castMember;
+// Common::Rect bbox(shapeMember->getBbox());
+
+// }
+
void showShape(CastMember *cast, float thumbnailSize) {
// Show in a square box
Common::Rect bbox = cast->getBbox();
@@ -187,11 +196,6 @@ void showShape(CastMember *cast, float thumbnailSize) {
ImDrawList *dl = ImGui::GetWindowDrawList();
// If there is no background, set it to white
- if (cast->getBackColor()) {
- dl->AddRectFilled(screenPos, screenPos + ImVec2(thumbnailSize, thumbnailSize), cast->getBackColor());
- } else {
- dl->AddRectFilled(screenPos, screenPos + ImVec2(thumbnailSize, thumbnailSize), 0xFFFFFFFF);
- }
ImVec2 shapePos = screenPos + ImVec2(1 + (thumbnailSize - 2 - size.x) * 0.5f, 1 + (thumbnailSize - 2 - size.y) * 0.5f);
uint8 foreCol = cast->getForeColor();
@@ -262,14 +266,15 @@ static void addScriptCastToDisplay(CastMemberID &id) {
}
void setScriptToDisplay(const ImGuiScript &script) {
- uint index = _state->_functions._scripts.size();
- if (index && _state->_functions._scripts[index - 1] == script) {
- _state->_functions._showScript = true;
+ uint index = _state->_functions._scriptData->_scripts.size();
+ if (index && _state->_functions._scriptData->_scripts[index - 1] == script) {
+ debug("Here I returned: %s", g_director->getCurrentMovie()->getMacName().c_str());
+ _state->_functions._scriptData->_showScript = true;
return;
}
- _state->_functions._scripts.push_back(script);
- _state->_functions._current = index;
- _state->_functions._showScript = true;
+ _state->_functions._scriptData->_scripts.push_back(script);
+ _state->_functions._scriptData->_current = index;
+ _state->_functions._scriptData->_showScript = true;
}
void displayScriptRef(CastMemberID &scriptId) {
diff --git a/engines/director/debugger/dt-controlpanel.cpp b/engines/director/debugger/dt-controlpanel.cpp
index febaae610dc..3fdcf457e71 100644
--- a/engines/director/debugger/dt-controlpanel.cpp
+++ b/engines/director/debugger/dt-controlpanel.cpp
@@ -24,16 +24,19 @@
#include "director/archive.h"
#include "director/movie.h"
+#include "director/window.h"
#include "director/score.h"
namespace Director {
namespace DT {
static uint32 getLineFromPC() {
+ _state->_functions._scriptData = &_state->_functions._windowScriptData.getOrCreateVal(g_director->getCurrentWindow());
+
const uint pc = g_lingo->_state->pc;
- if (_state->_functions._scripts.empty())
+ if (_state->_functions._scriptData->_scripts.empty())
return 0;
- const Common::Array<uint> &offsets = _state->_functions._scripts[_state->_functions._current].startOffsets;
+ const Common::Array<uint> &offsets = _state->_functions._scriptData->_scripts[_state->_functions._scriptData->_current].startOffsets;
for (uint i = 0; i < offsets.size(); i++) {
if (pc <= offsets[i])
return i;
@@ -121,6 +124,9 @@ void showControlPanel() {
ImGui::SetNextWindowPos(ImVec2(vp.x - 220.0f, 20.0f), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(200, 103), ImGuiCond_FirstUseEver);
+ _state->_functions._scriptData = &_state->_functions._windowScriptData.getOrCreateVal(g_director->getCurrentWindow());
+ debug("What is the current movie in the control panel: %s", g_director->getCurrentMovie()->getMacName().c_str());
+
if (ImGui::Begin("Control Panel", &_state->_w.controlPanel)) {
Movie *movie = g_director->getCurrentMovie();
Score *score = movie->getScore();
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index eff765173e7..a3acfe2fd12 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -106,16 +106,20 @@ typedef struct ImGuiState {
int _typeFilter = 0x7FFF;
} _cast;
struct {
- Common::Array<ImGuiScript> _scripts;
- uint _current = 0;
+ struct ScriptData {
+ Common::Array<ImGuiScript> _scripts;
+ uint _current = 0;
+ bool _showByteCode = false;
+ bool _showScript = false;
+ } *_scriptData;
ImGuiTextFilter _nameFilter;
- bool _showByteCode = false;
- bool _showScript = false;
+ Common::HashMap<Window *, ScriptData> _windowScriptData;
} _functions;
+
struct {
+ bool _isScriptDirty = false; // indicates whether or not we have to display the script corresponding to the current stackframe
uint _lastLinePC = 0;
uint _callstackSize = 0;
- bool _isScriptDirty = false; // indicates whether or not we have to display the script corresponding to the current stackframe
} _dbg;
struct {
diff --git a/engines/director/debugger/dt-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index 960b920e99c..c436ad818df 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -1168,9 +1168,11 @@ private:
// draw current statement
if (showCurrentStatement) {
+ debug("Does this get called for all statements: %s", _script.handlerId.c_str());
dl->AddQuadFilled(ImVec2(pos.x, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 10.f), ImVec2(pos.x, pos.y + 10.f), ImColor(_state->_colors._current_statement));
dl->AddTriangleFilled(ImVec2(pos.x + 8.f, pos.y), ImVec2(pos.x + 14.f, pos.y + 7.f), ImVec2(pos.x + 8.f, pos.y + 14.f), ImColor(_state->_colors._current_statement));
- if (_state->_dbg._isScriptDirty && !ImGui::IsItemVisible()) {
+ debug("Why not scroll here?: %d:%d", _state->_dbg._isScriptDirty, !ImGui::IsItemVisible());
+ if (_state->_dbg._isScriptDirty) {
ImGui::SetScrollHereY(0.5f);
}
dl->AddRectFilled(ImVec2(pos.x + 16.f, pos.y), ImVec2(pos.x + width, pos.y + 16.f), ImColor(IM_COL32(0xFF, 0xFF, 0x00, 0x20)), 0.4f);
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index ce2acb95af2..88000e2986d 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -100,6 +100,7 @@ static void renderCastScript(Symbol &sym) {
static void renderScript(ImGuiScript &script, bool showByteCode) {
if (script.oldAst) {
renderOldScriptAST(script, showByteCode);
+ _state->_dbg._isScriptDirty = false;
return;
}
@@ -107,6 +108,7 @@ static void renderScript(ImGuiScript &script, bool showByteCode) {
return;
renderScriptAST(script, showByteCode);
+ _state->_dbg._isScriptDirty = false;
}
static bool showScriptCast(CastMemberID &id) {
@@ -158,12 +160,16 @@ void showScriptCasts() {
}
static void updateCurrentScript() {
- if ((g_lingo->_exec._state != kPause) || !_state->_dbg._isScriptDirty)
+ if ((g_lingo->_exec._state != kPause) || !_state->_dbg._isScriptDirty) {
+ debug("%d:%d: %s", g_lingo->_exec._state, _state->_dbg._isScriptDirty, g_director->getCurrentMovie()->getMacName().c_str());
return;
+ }
Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
- if (callstack.empty())
+ if (callstack.empty()) {
+ debug("Here I returned but before, movie name: %s", g_director->getCurrentMovie()->getMacName().c_str());
return;
+ }
// show current script of the current stack frame
CFrame *head = callstack[callstack.size() - 1];
@@ -302,6 +308,7 @@ void showExecutionContext() {
if (ImGui::Begin("Execution Context", &_state->_w.executionContext, ImGuiWindowFlags_AlwaysAutoResize)) {
Window *stage = g_director->getStage();
g_director->setCurrentWindow(stage);
+ g_lingo->switchStateFromWindow();
int windowID = 0;
ImGui::PushID(windowID);
@@ -320,21 +327,21 @@ void showExecutionContext() {
ImGui::SeparatorText("Scripts");
- g_lingo->switchStateFromWindow();
+ _state->_functions._scriptData = &_state->_functions._windowScriptData.getOrCreateVal(stage);
updateCurrentScript();
- if (_state->_functions._showScript) {
- ImGui::BeginDisabled(_state->_functions._scripts.empty() || _state->_functions._current == 0);
+ if (_state->_functions._scriptData->_showScript) {
+ ImGui::BeginDisabled(_state->_functions._scriptData->_scripts.empty() || _state->_functions._scriptData->_current == 0);
if (ImGui::Button(ICON_MS_ARROW_BACK)) {
- _state->_functions._current--;
+ _state->_functions._scriptData->_current--;
}
ImGui::EndDisabled();
ImGui::SetItemTooltip("Backward");
ImGui::SameLine();
- ImGui::BeginDisabled(_state->_functions._current >= _state->_functions._scripts.size() - 1);
+ ImGui::BeginDisabled(_state->_functions._scriptData->_current >= _state->_functions._scriptData->_scripts.size() - 1);
if (ImGui::Button(ICON_MS_ARROW_FORWARD)) {
- _state->_functions._current++;
+ _state->_functions._scriptData->_current++;
}
ImGui::EndDisabled();
ImGui::SetItemTooltip("Forward");
@@ -342,49 +349,49 @@ void showExecutionContext() {
const char *currentScript = nullptr;
- if (_state->_functions._current < _state->_functions._scripts.size()) {
- currentScript = _state->_functions._scripts[_state->_functions._current].handlerName.c_str();
+ if (_state->_functions._scriptData->_current < _state->_functions._scriptData->_scripts.size()) {
+ currentScript = _state->_functions._scriptData->_scripts[_state->_functions._scriptData->_current].handlerName.c_str();
}
if (ImGui::BeginCombo("##handlers", currentScript)) {
- for (uint i = 0; i < _state->_functions._scripts.size(); i++) {
- auto &script = _state->_functions._scripts[i];
- bool selected = i == _state->_functions._current;
+ for (uint i = 0; i < _state->_functions._scriptData->_scripts.size(); i++) {
+ auto &script = _state->_functions._scriptData->_scripts[i];
+ bool selected = i == _state->_functions._scriptData->_current;
if (ImGui::Selectable(script.handlerName.c_str(), &selected)) {
- _state->_functions._current = i;
+ _state->_functions._scriptData->_current = i;
}
}
ImGui::EndCombo();
}
- if (!_state->_functions._scripts[_state->_functions._current].oldAst) {
+ if (!_state->_functions._scriptData->_scripts[_state->_functions._scriptData->_current].oldAst) {
ImGui::SameLine(0, 20);
- ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &_state->_functions._showByteCode, true); // Lingo
+ ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &_state->_functions._scriptData->_showByteCode, true); // Lingo
ImGui::SetItemTooltip("Lingo");
ImGui::SameLine();
- ImGuiEx::toggleButton(ICON_MS_STACKS, &_state->_functions._showByteCode); // Bytecode
+ ImGuiEx::toggleButton(ICON_MS_STACKS, &_state->_functions._scriptData->_showByteCode); // Bytecode
ImGui::SetItemTooltip("Bytecode");
}
ImGui::Separator();
childSize = ImGui::GetContentRegionAvail();
ImGui::BeginChild("##script", childSize);
- ImGuiScript ¤t = _state->_functions._scripts[_state->_functions._current];
+ ImGuiScript ¤t = _state->_functions._scriptData->_scripts[_state->_functions._scriptData->_current];
// Get all the handlers from the script
ScriptContext* context = getScriptContext(current.id);
Movie *movie = g_director->getCurrentMovie();
if (!context || context->_functionHandlers.size() == 1) {
- renderScript(current, _state->_functions._showByteCode);
+ renderScript(current, _state->_functions._scriptData->_showByteCode);
} else {
for (auto &functionHandler : context->_functionHandlers) {
ImGuiScript script = toImGuiScript(context->_scriptType, current.id, functionHandler._key);
script.byteOffsets = context->_functionByteOffsets[script.handlerId];
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = getHandlerName(functionHandler._value);
- renderScript(script, _state->_functions._showByteCode);
+ renderScript(script, _state->_functions._scriptData->_showByteCode);
ImGui::NewLine();
}
}
@@ -402,6 +409,7 @@ void showExecutionContext() {
for (auto window : (*windowList)) {
g_director->setCurrentWindow(window);
+ g_lingo->switchStateFromWindow();
windowID += 1;
ImGui::PushID(windowID);
@@ -421,21 +429,21 @@ void showExecutionContext() {
ImGui::SeparatorText("Scripts");
- g_lingo->switchStateFromWindow();
+ _state->_functions._scriptData = &_state->_functions._windowScriptData.getOrCreateVal(window);
updateCurrentScript();
- if (_state->_functions._showScript) {
- ImGui::BeginDisabled(_state->_functions._scripts.empty() || _state->_functions._current == 0);
+ if (_state->_functions._scriptData->_showScript) {
+ ImGui::BeginDisabled(_state->_functions._scriptData->_scripts.empty() || _state->_functions._scriptData->_current == 0);
if (ImGui::Button(ICON_MS_ARROW_BACK)) {
- _state->_functions._current--;
+ _state->_functions._scriptData->_current--;
}
ImGui::EndDisabled();
ImGui::SetItemTooltip("Backward");
ImGui::SameLine();
- ImGui::BeginDisabled(_state->_functions._current >= _state->_functions._scripts.size() - 1);
+ ImGui::BeginDisabled(_state->_functions._scriptData->_current >= _state->_functions._scriptData->_scripts.size() - 1);
if (ImGui::Button(ICON_MS_ARROW_FORWARD)) {
- _state->_functions._current++;
+ _state->_functions._scriptData->_current++;
}
ImGui::EndDisabled();
ImGui::SetItemTooltip("Forward");
@@ -443,49 +451,49 @@ void showExecutionContext() {
const char *currentScript = nullptr;
- if (_state->_functions._current < _state->_functions._scripts.size()) {
- currentScript = _state->_functions._scripts[_state->_functions._current].handlerName.c_str();
+ if (_state->_functions._scriptData->_current < _state->_functions._scriptData->_scripts.size()) {
+ currentScript = _state->_functions._scriptData->_scripts[_state->_functions._scriptData->_current].handlerName.c_str();
}
if (ImGui::BeginCombo("##handlers", currentScript)) {
- for (uint i = 0; i < _state->_functions._scripts.size(); i++) {
- auto &script = _state->_functions._scripts[i];
- bool selected = i == _state->_functions._current;
+ for (uint i = 0; i < _state->_functions._scriptData->_scripts.size(); i++) {
+ auto &script = _state->_functions._scriptData->_scripts[i];
+ bool selected = i == _state->_functions._scriptData->_current;
if (ImGui::Selectable(script.handlerName.c_str(), &selected)) {
- _state->_functions._current = i;
+ _state->_functions._scriptData->_current = i;
}
}
ImGui::EndCombo();
}
- if (!_state->_functions._scripts[_state->_functions._current].oldAst) {
+ if (!_state->_functions._scriptData->_scripts[_state->_functions._scriptData->_current].oldAst) {
ImGui::SameLine(0, 20);
- ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &_state->_functions._showByteCode, true); // Lingo
+ ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &_state->_functions._scriptData->_showByteCode, true); // Lingo
ImGui::SetItemTooltip("Lingo");
ImGui::SameLine();
- ImGuiEx::toggleButton(ICON_MS_STACKS, &_state->_functions._showByteCode); // Bytecode
+ ImGuiEx::toggleButton(ICON_MS_STACKS, &_state->_functions._scriptData->_showByteCode); // Bytecode
ImGui::SetItemTooltip("Bytecode");
}
ImGui::Separator();
childSize = ImGui::GetContentRegionAvail();
ImGui::BeginChild("##script", childSize);
- ImGuiScript ¤t = _state->_functions._scripts[_state->_functions._current];
+ ImGuiScript ¤t = _state->_functions._scriptData->_scripts[_state->_functions._scriptData->_current];
// Get all the handlers from the script
ScriptContext* context = getScriptContext(current.id);
Movie *movie = g_director->getCurrentMovie();
if (!context || context->_functionHandlers.size() == 1) {
- renderScript(current, _state->_functions._showByteCode);
+ renderScript(current, _state->_functions._scriptData->_showByteCode);
} else {
for (auto &functionHandler : context->_functionHandlers) {
ImGuiScript script = toImGuiScript(context->_scriptType, current.id, functionHandler._key);
script.byteOffsets = context->_functionByteOffsets[script.handlerId];
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = getHandlerName(functionHandler._value);
- renderScript(script, _state->_functions._showByteCode);
+ renderScript(script, _state->_functions._scriptData->_showByteCode);
ImGui::NewLine();
}
}
@@ -497,13 +505,11 @@ void showExecutionContext() {
ImGui::PopStyleColor();
ImGui::PopID();
}
- // Mark the scripts not dirty after all the scripts have been rendered
- _state->_dbg._isScriptDirty = false;
+
+ g_director->setCurrentWindow(currentWindow);
+ g_lingo->switchStateFromWindow();
}
ImGui::End();
-
- g_director->setCurrentWindow(currentWindow);
- g_lingo->switchStateFromWindow();
}
} // namespace DT
Commit: 2bbcf954cc1234d4a409d5b6d4dd4ea461ceda26
https://github.com/scummvm/scummvm/commit/2bbcf954cc1234d4a409d5b6d4dd4ea461ceda26
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Set up Shape rendering in the Cast Window
Instead of relying on ImGui methods to show a shape
Show the shape pixel data from Director onto the Cast Window
Currently, the shapes aren't rendered at all
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-cast.cpp
engines/director/debugger/dt-controlpanel.cpp
engines/director/debugger/dt-internal.h
engines/director/window.h
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index b5a4de63195..54d654c3789 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -21,6 +21,8 @@
#include "backends/imgui/IconsMaterialSymbols.h"
+#include "image/png.h"
+
#include "director/director.h"
#include "director/lingo/lingodec/context.h"
#include "director/lingo/lingodec/script.h"
@@ -29,6 +31,9 @@
#include "director/castmember/shape.h"
#include "director/debugger.h"
#include "director/movie.h"
+#include "director/window.h"
+#include "director/score.h"
+#include "director/channel.h"
#include "director/picture.h"
#include "director/debugger/debugtools.h"
@@ -177,36 +182,46 @@ void showImage(const ImGuiImage &image, const char *name, float thumbnailSize) {
setToolTipImage(image, name);
}
-// ImGuiImage getShapeID(CastMember *castMember) {
-// if (castMember->_type != CastType::kCastShape)
-// return {};
+ImGuiImage getShapeID(CastMember *castMember) {
+ if (castMember->_type != CastType::kCastShape)
+ return {};
+
+ ShapeCastMember *shapeMember = (ShapeCastMember *)castMember;
-// ShapeCastMember *shapeMember = (ShapeCastMember *)castMember;
-// Common::Rect bbox(shapeMember->getBbox());
+ Common::Array<Channel *> channels = g_director->getCurrentMovie()->getScore()->_channels;
+ Channel *channel = nullptr;
-// }
+ for (auto it : channels) {
+ if (it->_sprite->_castId.member == castMember->getID()) {
+ channel = it;
+ break;
+ }
+ }
+ if (!channel) {
+ return {};
+ }
-void showShape(CastMember *cast, float thumbnailSize) {
- // Show in a square box
- Common::Rect bbox = cast->getBbox();
- ImVec2 size = {thumbnailSize - 2, (thumbnailSize - 2) * bbox.height() / bbox.width()};
+ Common::Rect bbox(castMember->getBbox());
+ Graphics::ManagedSurface *managedSurface = new Graphics::ManagedSurface();
+ managedSurface->create(bbox.width(), bbox.height(), g_director->_pixelformat);
+ Window::inkBlitFrom(channel, bbox, managedSurface);
+ Graphics::Surface surface = managedSurface->rawSurface();
- ImGui::BeginGroup();
- ImVec2 screenPos = ImGui::GetCursorScreenPos();
- ImDrawList *dl = ImGui::GetWindowDrawList();
+ if (debugChannelSet(8, kDebugImages)) {
+ Common::String prepend = "shape";
+ Common::String filename = Common::String::format("./dumps/%s-%d.png", encodePathForDump(prepend).c_str(), shapeMember->getID());
+ Common::DumpFile bitmapFile;
- // If there is no background, set it to white
- ImVec2 shapePos = screenPos + ImVec2(1 + (thumbnailSize - 2 - size.x) * 0.5f, 1 + (thumbnailSize - 2 - size.y) * 0.5f);
+ bitmapFile.open(Common::Path(filename), true);
+ Image::writePNG(bitmapFile, surface, g_director->getPalette());
- uint8 foreCol = cast->getForeColor();
- debug("%d: bg: %x, fg: %x", cast->getBackColor(), cast->getForeColor(), cast->getID());
+ bitmapFile.close();
+ }
- // The forecolor is in 8 bit format
- dl->AddRectFilled(shapePos, shapePos + size, cast->getForeColor());
+ ImTextureID textureID = (ImTextureID)(intptr_t)g_system->getImGuiTexture(surface, g_director->getPalette(), g_director->getPaletteColorCount());
- // Have to add this to make the column auto adjust to correct height
- ImGui::Dummy(ImVec2(thumbnailSize, thumbnailSize));
- ImGui::EndGroup();
+ delete managedSurface;
+ return {textureID, surface.w, surface.h};
}
void displayVariable(const Common::String &name, bool changed, bool outOfScope) {
diff --git a/engines/director/debugger/dt-cast.cpp b/engines/director/debugger/dt-cast.cpp
index 99264b08891..28925d55bf1 100644
--- a/engines/director/debugger/dt-cast.cpp
+++ b/engines/director/debugger/dt-cast.cpp
@@ -113,7 +113,7 @@ void showCast() {
return;
ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
- ImGui::SetNextWindowSize(ImVec2(560, 240), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(560, 480), ImGuiCond_FirstUseEver);
if (ImGui::Begin("Cast", &_state->_w.cast)) {
// display a toolbar with: grid/list/filters buttons + name filter
@@ -249,7 +249,10 @@ void showCast() {
{
float offsetX = (columnWidth - 32.f) * 0.5f;
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
- showShape((ShapeCastMember *)castMember._value, 32.f);
+ ImGuiImage shapeID = getShapeID(castMember._value);
+ if (shapeID.id) {
+ showImage(shapeID, name.c_str(), 32.f);
+ }
}
break;
default:
diff --git a/engines/director/debugger/dt-controlpanel.cpp b/engines/director/debugger/dt-controlpanel.cpp
index 3fdcf457e71..13d9f54d4a8 100644
--- a/engines/director/debugger/dt-controlpanel.cpp
+++ b/engines/director/debugger/dt-controlpanel.cpp
@@ -125,7 +125,6 @@ void showControlPanel() {
ImGui::SetNextWindowSize(ImVec2(200, 103), ImGuiCond_FirstUseEver);
_state->_functions._scriptData = &_state->_functions._windowScriptData.getOrCreateVal(g_director->getCurrentWindow());
- debug("What is the current movie in the control panel: %s", g_director->getCurrentMovie()->getMacName().c_str());
if (ImGui::Begin("Control Panel", &_state->_w.controlPanel)) {
Movie *movie = g_director->getCurrentMovie();
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index a3acfe2fd12..f5bc048ce9c 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -194,9 +194,9 @@ void setScriptToDisplay(const ImGuiScript &script);
Director::Breakpoint *getBreakpoint(const Common::String &handlerName, uint16 scriptId, uint pc);
void displayScriptRef(CastMemberID &scriptId);
ImGuiImage getImageID(CastMember *castMember);
+ImGuiImage getShapeID(CastMember *castMember);
Common::String getDisplayName(CastMember *castMember);
void showImage(const ImGuiImage &image, const char *name, float thumbnailSize);
-void showShape(CastMember *cast, float thumbnailSize);
ImVec4 convertColor(uint32 color);
void displayVariable(const Common::String &name, bool changed, bool outOfScope = false);
diff --git a/engines/director/window.h b/engines/director/window.h
index 574a9362cbd..d84b017263f 100644
--- a/engines/director/window.h
+++ b/engines/director/window.h
@@ -169,6 +169,8 @@ public:
Common::String formatWindowInfo();
+ static void inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::ManagedSurface *blitTo = nullptr);
+
// events.cpp
bool processEvent(Common::Event &event) override;
@@ -225,7 +227,6 @@ private:
bool _isModal;
private:
- void inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::ManagedSurface *blitTo = nullptr);
static void drawChannelBox(Director::Movie *currentMovie, Graphics::ManagedSurface *blitTo, int selectedChannel);
void drawFrameCounter(Graphics::ManagedSurface *blitTo);
Commit: 08d30482ac16819187d69a536c95ce3d8f7c95e1
https://github.com/scummvm/scummvm/commit/08d30482ac16819187d69a536c95ce3d8f7c95e1
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Fix Rendering Shapes Properly in the Cast Window
Previously, no shape was rendered since the bbox for the channel
was incorrect
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/graphics.cpp
engines/director/window.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 54d654c3789..675e2a0d0b6 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -193,17 +193,19 @@ ImGuiImage getShapeID(CastMember *castMember) {
for (auto it : channels) {
if (it->_sprite->_castId.member == castMember->getID()) {
- channel = it;
+ channel = new Channel(*it);
break;
}
}
+ // This means the shapes that are not in any channel won't be shown
if (!channel) {
return {};
}
Common::Rect bbox(castMember->getBbox());
- Graphics::ManagedSurface *managedSurface = new Graphics::ManagedSurface();
- managedSurface->create(bbox.width(), bbox.height(), g_director->_pixelformat);
+ channel->setBbox(bbox.left, bbox.top, bbox.right, bbox.bottom);
+ Graphics::ManagedSurface *managedSurface = new Graphics::ManagedSurface(bbox.width(), bbox.height(), g_director->_pixelformat);
+
Window::inkBlitFrom(channel, bbox, managedSurface);
Graphics::Surface surface = managedSurface->rawSurface();
@@ -221,6 +223,7 @@ ImGuiImage getShapeID(CastMember *castMember) {
ImTextureID textureID = (ImTextureID)(intptr_t)g_system->getImGuiTexture(surface, g_director->getPalette(), g_director->getPaletteColorCount());
delete managedSurface;
+ delete channel;
return {textureID, surface.w, surface.h};
}
diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp
index 80b3fd52e4a..5529f9b4979 100644
--- a/engines/director/graphics.cpp
+++ b/engines/director/graphics.cpp
@@ -288,8 +288,10 @@ void InkPrimitives<T>::drawPoint(int x, int y, uint32 src, void *data) {
DirectorPlotData *p = (DirectorPlotData *)data;
Graphics::MacWindowManager *wm = p->d->_wm;
- if (!p->destRect.contains(x, y))
+ if (!p->destRect.contains(x, y)) {
+ debug("What is x: %d, y: %d", x, y);
return;
+ }
T *dst;
uint32 tmpDst;
diff --git a/engines/director/window.cpp b/engines/director/window.cpp
index 940f61ddf3b..b1727ad5888 100644
--- a/engines/director/window.cpp
+++ b/engines/director/window.cpp
@@ -328,9 +328,14 @@ void Window::reset() {
void Window::inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::ManagedSurface *blitTo) {
Common::Rect srcRect = channel->getBbox();
+ DirectorPlotData pd = channel->getPlotData();
+ if (pd.ms)
+ debug("shape: %d", pd.ms->spriteType);
+ destRect.debugPrint();
+ srcRect.debugPrint();
destRect.clip(srcRect);
+ destRect.debugPrint();
- DirectorPlotData pd = channel->getPlotData();
pd.destRect = destRect;
pd.dst = blitTo;
Commit: 2d069867af9e1974e6bb081a8eea5dc091b170cc
https://github.com/scummvm/scummvm/commit/2d069867af9e1974e6bb081a8eea5dc091b170cc
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Do not prematurely set cursor in Cast window
While showing a preview of bitmap, the cursor is set prematurely to
the middle of the column, if we fail to get the bitmap
ImGuiImage, causes an error, fix that, only after we get ImGuiImage,
should we set the cursor
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-cast.cpp
engines/director/window.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 675e2a0d0b6..5cf6e56bf2b 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -147,6 +147,7 @@ ImGuiImage getImageID(CastMember *castMember) {
if (_state->_cast._textures.contains(bmp))
return _state->_cast._textures[bmp];
+ bmpMember->load();
Picture *pic = bmpMember->_picture;
if (!pic)
return {};
@@ -186,8 +187,6 @@ ImGuiImage getShapeID(CastMember *castMember) {
if (castMember->_type != CastType::kCastShape)
return {};
- ShapeCastMember *shapeMember = (ShapeCastMember *)castMember;
-
Common::Array<Channel *> channels = g_director->getCurrentMovie()->getScore()->_channels;
Channel *channel = nullptr;
@@ -203,6 +202,10 @@ ImGuiImage getShapeID(CastMember *castMember) {
}
Common::Rect bbox(castMember->getBbox());
+
+ // Manually set the bbox of the channel to the bbox of cast member
+ // Even though the BBox of the channel and cast member are the same, the channel's bbox is offset to a non zero origin
+ // Depending upon the position of the sprite in the window
channel->setBbox(bbox.left, bbox.top, bbox.right, bbox.bottom);
Graphics::ManagedSurface *managedSurface = new Graphics::ManagedSurface(bbox.width(), bbox.height(), g_director->_pixelformat);
@@ -211,7 +214,7 @@ ImGuiImage getShapeID(CastMember *castMember) {
if (debugChannelSet(8, kDebugImages)) {
Common::String prepend = "shape";
- Common::String filename = Common::String::format("./dumps/%s-%d.png", encodePathForDump(prepend).c_str(), shapeMember->getID());
+ Common::String filename = Common::String::format("./dumps/%s-%s-%d.png", g_director->getCurrentMovie()->getMacName().c_str(), encodePathForDump(prepend).c_str(), castMember->getID());
Common::DumpFile bitmapFile;
bitmapFile.open(Common::Path(filename), true);
diff --git a/engines/director/debugger/dt-cast.cpp b/engines/director/debugger/dt-cast.cpp
index 28925d55bf1..0c2f330da94 100644
--- a/engines/director/debugger/dt-cast.cpp
+++ b/engines/director/debugger/dt-cast.cpp
@@ -193,11 +193,10 @@ void showCast() {
switch (castMember._value->_type) {
case kCastBitmap:
{
- float offsetX = (columnWidth - 32.f) * 0.5f;
- ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
-
ImGuiImage imgID = getImageID(castMember._value);
if (imgID.id) {
+ float offsetX = (columnWidth - 32.f) * 0.5f;
+ ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
showImage(imgID, name.c_str(), 32.f);
}
}
@@ -247,10 +246,10 @@ void showCast() {
case kCastShape:
{
- float offsetX = (columnWidth - 32.f) * 0.5f;
- ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
ImGuiImage shapeID = getShapeID(castMember._value);
if (shapeID.id) {
+ float offsetX = (columnWidth - 32.f) * 0.5f;
+ ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
showImage(shapeID, name.c_str(), 32.f);
}
}
diff --git a/engines/director/window.cpp b/engines/director/window.cpp
index b1727ad5888..940f61ddf3b 100644
--- a/engines/director/window.cpp
+++ b/engines/director/window.cpp
@@ -328,14 +328,9 @@ void Window::reset() {
void Window::inkBlitFrom(Channel *channel, Common::Rect destRect, Graphics::ManagedSurface *blitTo) {
Common::Rect srcRect = channel->getBbox();
- DirectorPlotData pd = channel->getPlotData();
- if (pd.ms)
- debug("shape: %d", pd.ms->spriteType);
- destRect.debugPrint();
- srcRect.debugPrint();
destRect.clip(srcRect);
- destRect.debugPrint();
+ DirectorPlotData pd = channel->getPlotData();
pd.destRect = destRect;
pd.dst = blitTo;
Commit: 72c0855930f7ad1031d9882913fd4965615ec90a
https://github.com/scummvm/scummvm/commit/72c0855930f7ad1031d9882913fd4965615ec90a
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Render shapes in Score window as well
Changed paths:
engines/director/debugger/dt-score.cpp
diff --git a/engines/director/debugger/dt-score.cpp b/engines/director/debugger/dt-score.cpp
index b9d6b603862..113a782bd10 100644
--- a/engines/director/debugger/dt-score.cpp
+++ b/engines/director/debugger/dt-score.cpp
@@ -24,6 +24,7 @@
#include "director/debugger/dt-internal.h"
#include "director/cast.h"
+#include "director/castmember/castmember.h"
#include "director/channel.h"
#include "director/frame.h"
#include "director/movie.h"
@@ -234,8 +235,11 @@ void showScore() {
if (castMember || shape) {
ImGuiImage imgID = {};
- if (castMember)
+ if (castMember && castMember->_type == kCastBitmap) {
imgID = getImageID(castMember);
+ } else if (castMember && castMember->_type == kCastShape) {
+ imgID = getShapeID(castMember);
+ }
if (castMember && imgID.id) {
Common::String name(getDisplayName(castMember));
Commit: 7e4c5343c440c8322d062440f3fee4f9ebb26a4d
https://github.com/scummvm/scummvm/commit/7e4c5343c440c8322d062440f3fee4f9ebb26a4d
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Code clean up and remove debug leftovers
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-script-d4.cpp
engines/director/debugger/dt-scripts.cpp
engines/director/graphics.cpp
engines/director/lingo/lingo-object.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 5cf6e56bf2b..4df70369eb1 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -289,7 +289,6 @@ static void addScriptCastToDisplay(CastMemberID &id) {
void setScriptToDisplay(const ImGuiScript &script) {
uint index = _state->_functions._scriptData->_scripts.size();
if (index && _state->_functions._scriptData->_scripts[index - 1] == script) {
- debug("Here I returned: %s", g_director->getCurrentMovie()->getMacName().c_str());
_state->_functions._scriptData->_showScript = true;
return;
}
diff --git a/engines/director/debugger/dt-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index c436ad818df..d033f7c7ad8 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -1168,10 +1168,8 @@ private:
// draw current statement
if (showCurrentStatement) {
- debug("Does this get called for all statements: %s", _script.handlerId.c_str());
dl->AddQuadFilled(ImVec2(pos.x, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 10.f), ImVec2(pos.x, pos.y + 10.f), ImColor(_state->_colors._current_statement));
dl->AddTriangleFilled(ImVec2(pos.x + 8.f, pos.y), ImVec2(pos.x + 14.f, pos.y + 7.f), ImVec2(pos.x + 8.f, pos.y + 14.f), ImColor(_state->_colors._current_statement));
- debug("Why not scroll here?: %d:%d", _state->_dbg._isScriptDirty, !ImGui::IsItemVisible());
if (_state->_dbg._isScriptDirty) {
ImGui::SetScrollHereY(0.5f);
}
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index 88000e2986d..f6943b65a4c 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -160,16 +160,14 @@ void showScriptCasts() {
}
static void updateCurrentScript() {
- if ((g_lingo->_exec._state != kPause) || !_state->_dbg._isScriptDirty) {
- debug("%d:%d: %s", g_lingo->_exec._state, _state->_dbg._isScriptDirty, g_director->getCurrentMovie()->getMacName().c_str());
+ if ((g_lingo->_exec._state != kPause) || !_state->_dbg._isScriptDirty)
return;
- }
+
Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
- if (callstack.empty()) {
- debug("Here I returned but before, movie name: %s", g_director->getCurrentMovie()->getMacName().c_str());
+ if (callstack.empty())
return;
- }
+
// show current script of the current stack frame
CFrame *head = callstack[callstack.size() - 1];
diff --git a/engines/director/graphics.cpp b/engines/director/graphics.cpp
index 5529f9b4979..55adc26af01 100644
--- a/engines/director/graphics.cpp
+++ b/engines/director/graphics.cpp
@@ -288,10 +288,9 @@ void InkPrimitives<T>::drawPoint(int x, int y, uint32 src, void *data) {
DirectorPlotData *p = (DirectorPlotData *)data;
Graphics::MacWindowManager *wm = p->d->_wm;
- if (!p->destRect.contains(x, y)) {
- debug("What is x: %d, y: %d", x, y);
+ if (!p->destRect.contains(x, y))
return;
- }
+
T *dst;
uint32 tmpDst;
diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index ee3ecdcb506..0a83ff1aea8 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -724,7 +724,7 @@ void LM::m_respondsTo(int nargs) {
// Window
Common::String Window::asString() {
- return "Window \"" + getName() + "\"";
+ return "window \"" + getName() + "\"";
}
bool Window::hasProp(const Common::String &propName) {
Commit: 91cd92366fe84df17e3ec08aa8657704256e31e3
https://github.com/scummvm/scummvm/commit/91cd92366fe84df17e3ec08aa8657704256e31e3
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Render text cast members previews in cast window
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-cast.cpp
engines/director/debugger/dt-internal.h
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 4df70369eb1..727d75e7073 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -21,6 +21,8 @@
#include "backends/imgui/IconsMaterialSymbols.h"
+#include "graphics/macgui/mactext.h"
+
#include "image/png.h"
#include "director/director.h"
@@ -191,7 +193,7 @@ ImGuiImage getShapeID(CastMember *castMember) {
Channel *channel = nullptr;
for (auto it : channels) {
- if (it->_sprite->_castId.member == castMember->getID()) {
+ if (it->_sprite && it->_sprite->_castId.member == castMember->getID()) {
channel = new Channel(*it);
break;
}
@@ -230,6 +232,44 @@ ImGuiImage getShapeID(CastMember *castMember) {
return {textureID, surface.w, surface.h};
}
+ImGuiImage getTextID(CastMember *castMember) {
+ if (castMember->_type != CastType::kCastText)
+ return {};
+
+ Common::Array<Channel *> channels = g_director->getCurrentMovie()->getScore()->_channels;
+ Graphics::Surface source;
+
+ // This means the shapes that are not in any channel won't be shown
+ for (auto it : channels) {
+ if (it->_sprite && it->_sprite->_castId.member == castMember->getID()) {
+ source = it->_widget->getSurface()->rawSurface();
+ break;
+ }
+ }
+
+ if (source.format.bytesPerPixel > 4 || !source.getPixels()) {
+ return {};
+ }
+
+ Graphics::Surface surface;
+ surface.copyFrom(source);
+
+ if (debugChannelSet(8, kDebugImages)) {
+ Common::String prepend = "text";
+ Common::String filename = Common::String::format("./dumps/%s-%s-%d.png", g_director->getCurrentMovie()->getMacName().c_str(), encodePathForDump(prepend).c_str(), castMember->getID());
+ Common::DumpFile bitmapFile;
+
+ bitmapFile.open(Common::Path(filename), true);
+ Image::writePNG(bitmapFile, surface, g_director->getPalette());
+
+ bitmapFile.close();
+ }
+
+ ImTextureID textureID = (ImTextureID)(intptr_t)g_system->getImGuiTexture(surface, g_director->getPalette(), g_director->getPaletteColorCount());
+
+ return {textureID, surface.w, surface.h};
+}
+
void displayVariable(const Common::String &name, bool changed, bool outOfScope) {
ImU32 var_color = ImGui::GetColorU32(_state->_colors._var_ref);
ImU32 color;
diff --git a/engines/director/debugger/dt-cast.cpp b/engines/director/debugger/dt-cast.cpp
index 0c2f330da94..aac4df780ba 100644
--- a/engines/director/debugger/dt-cast.cpp
+++ b/engines/director/debugger/dt-cast.cpp
@@ -204,12 +204,12 @@ void showCast() {
case kCastText:
{
- const char *text = Common::toPrintable(((TextCastMember *)castMember._value)->_rtext).c_str();
- ImVec2 textSize = ImGui::CalcTextSize(text);
- float offsetX = (columnWidth - textSize.x) * 0.5f;
-
- ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
- ImGui::Text("%s", text);
+ ImGuiImage textID = getTextID(castMember._value);
+ if (textID.id) {
+ float offsetX = (columnWidth - 32.f) * 0.5f;
+ ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
+ showImage(textID, name.c_str(), 32.f);
+ }
}
break;
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index f5bc048ce9c..734ad89e36e 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -195,6 +195,7 @@ Director::Breakpoint *getBreakpoint(const Common::String &handlerName, uint16 sc
void displayScriptRef(CastMemberID &scriptId);
ImGuiImage getImageID(CastMember *castMember);
ImGuiImage getShapeID(CastMember *castMember);
+ImGuiImage getTextID(CastMember *castMember);
Common::String getDisplayName(CastMember *castMember);
void showImage(const ImGuiImage &image, const char *name, float thumbnailSize);
ImVec4 convertColor(uint32 color);
Commit: 977443ca3f6a537c1002412619598ce8f7773754
https://github.com/scummvm/scummvm/commit/977443ca3f6a537c1002412619598ce8f7773754
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Render Text/Button/RichText cast previews in Score window
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-cast.cpp
engines/director/debugger/dt-score.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 727d75e7073..4114cb88fd8 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -233,7 +233,7 @@ ImGuiImage getShapeID(CastMember *castMember) {
}
ImGuiImage getTextID(CastMember *castMember) {
- if (castMember->_type != CastType::kCastText)
+ if (castMember->_type != CastType::kCastText && castMember->_type != CastType::kCastButton && castMember->_type != CastType::kCastRichText)
return {};
Common::Array<Channel *> channels = g_director->getCurrentMovie()->getScore()->_channels;
@@ -241,7 +241,7 @@ ImGuiImage getTextID(CastMember *castMember) {
// This means the shapes that are not in any channel won't be shown
for (auto it : channels) {
- if (it->_sprite && it->_sprite->_castId.member == castMember->getID()) {
+ if (it->_sprite && it->_sprite->_castId.member == castMember->getID() && it->_widget) {
source = it->_widget->getSurface()->rawSurface();
break;
}
diff --git a/engines/director/debugger/dt-cast.cpp b/engines/director/debugger/dt-cast.cpp
index aac4df780ba..4c4bd5bf45b 100644
--- a/engines/director/debugger/dt-cast.cpp
+++ b/engines/director/debugger/dt-cast.cpp
@@ -203,6 +203,8 @@ void showCast() {
break;
case kCastText:
+ case kCastRichText:
+ case kCastButton:
{
ImGuiImage textID = getTextID(castMember._value);
if (textID.id) {
@@ -213,37 +215,6 @@ void showCast() {
}
break;
- case kCastRichText:
- {
- const char *text = Common::toPrintable(((RichTextCastMember *)castMember._value)->getText()).c_str();
- ImVec2 textSize = ImGui::CalcTextSize(text);
- float offsetX = (columnWidth - textSize.x) * 0.5f;
-
- ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
- ImGui::Text("%s", text);
- }
- break;
-
- case kCastButton:
- {
- ImGui::PushID(castMember._value->getID());
- ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg));
-
- ImGui::BeginChild("Button Cast", ImVec2(columnWidth, 20) , (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize));
-
- const char *text = Common::toPrintable(((TextCastMember *)castMember._value)->_rtext).c_str();
- ImVec2 textSize = ImGui::CalcTextSize(text);
- float offsetX = (columnWidth - textSize.x) * 0.5f;
-
- ImGui::SetCursorPosX(offsetX);
- ImGui::Text("%s", text);
- ImGui::EndChild();
-
- ImGui::PopStyleColor();
- ImGui::PopID();
- }
- break;
-
case kCastShape:
{
ImGuiImage shapeID = getShapeID(castMember._value);
diff --git a/engines/director/debugger/dt-score.cpp b/engines/director/debugger/dt-score.cpp
index 113a782bd10..a057f2311d7 100644
--- a/engines/director/debugger/dt-score.cpp
+++ b/engines/director/debugger/dt-score.cpp
@@ -235,10 +235,23 @@ void showScore() {
if (castMember || shape) {
ImGuiImage imgID = {};
- if (castMember && castMember->_type == kCastBitmap) {
- imgID = getImageID(castMember);
- } else if (castMember && castMember->_type == kCastShape) {
- imgID = getShapeID(castMember);
+ if (castMember) {
+ switch (castMember->_type) {
+ case kCastBitmap:
+ imgID = getImageID(castMember);
+ break;
+ case kCastShape:
+ imgID = getShapeID(castMember);
+ break;
+ case kCastText:
+ case kCastButton:
+ case kCastRichText:
+ imgID = getTextID(castMember);
+ break;
+
+ default:
+ break;
+ }
}
if (castMember && imgID.id) {
Commit: ce426a25a1257c5067c90807c224db29ebc6300e
https://github.com/scummvm/scummvm/commit/ce426a25a1257c5067c90807c224db29ebc6300e
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: Prevent memory leak in `getTextID()` and `getShapeID()`
Changed paths:
engines/director/debugger/debugtools.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 4114cb88fd8..7a7d1855529 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -229,7 +229,10 @@ ImGuiImage getShapeID(CastMember *castMember) {
delete managedSurface;
delete channel;
- return {textureID, surface.w, surface.h};
+
+ int16 width = surface.w, height = surface.h;
+ surface.free();
+ return {textureID, width, height};
}
ImGuiImage getTextID(CastMember *castMember) {
@@ -267,7 +270,9 @@ ImGuiImage getTextID(CastMember *castMember) {
ImTextureID textureID = (ImTextureID)(intptr_t)g_system->getImGuiTexture(surface, g_director->getPalette(), g_director->getPaletteColorCount());
- return {textureID, surface.w, surface.h};
+ int16 width = surface.w, height = surface.h;
+ surface.free();
+ return {textureID, width, height};
}
void displayVariable(const Common::String &name, bool changed, bool outOfScope) {
Commit: b28b9775edd15110a417d87902673e156affc037
https://github.com/scummvm/scummvm/commit/b28b9775edd15110a417d87902673e156affc037
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Cache Text and Shape textures after rendering once
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-internal.h
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 7a7d1855529..e48ddeaaf6a 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -137,17 +137,17 @@ Director::Breakpoint *getBreakpoint(const Common::String &handlerName, uint16 sc
}
ImGuiImage getImageID(CastMember *castMember) {
- if (castMember->_type != CastType::kCastBitmap)
+ if (castMember->_type != CastType::kCastBitmap) {
return {};
+ }
BitmapCastMember *bmpMember = (BitmapCastMember *)castMember;
- Common::Rect bbox(bmpMember->getBbox());
- Graphics::Surface *bmp = bmpMember->getMatte(bbox);
- if (!bmp)
- return {};
- if (_state->_cast._textures.contains(bmp))
- return _state->_cast._textures[bmp];
+ if (_state->_cast._textures.contains(bmpMember)) {
+ return _state->_cast._textures[bmpMember];
+ }
+
+ Common::Rect bbox(bmpMember->getBbox());
bmpMember->load();
Picture *pic = bmpMember->_picture;
@@ -155,8 +155,8 @@ ImGuiImage getImageID(CastMember *castMember) {
return {};
ImTextureID textureID = (ImTextureID)(intptr_t)g_system->getImGuiTexture(pic->_surface, pic->_palette, pic->_paletteColors);
- _state->_cast._textures[bmp] = {textureID, pic->_surface.w, pic->_surface.h};
- return _state->_cast._textures[bmp];
+ _state->_cast._textures[bmpMember] = {textureID, pic->_surface.w, pic->_surface.h};
+ return _state->_cast._textures[bmpMember];
}
static void setToolTipImage(const ImGuiImage &image, const char *name) {
@@ -186,8 +186,14 @@ void showImage(const ImGuiImage &image, const char *name, float thumbnailSize) {
}
ImGuiImage getShapeID(CastMember *castMember) {
- if (castMember->_type != CastType::kCastShape)
+ if (castMember->_type != CastType::kCastShape) {
return {};
+ }
+
+ if (_state->_cast._textures.contains(castMember)) {
+ debug("I work");
+ return _state->_cast._textures[castMember];
+ }
Common::Array<Channel *> channels = g_director->getCurrentMovie()->getScore()->_channels;
Channel *channel = nullptr;
@@ -231,13 +237,20 @@ ImGuiImage getShapeID(CastMember *castMember) {
delete channel;
int16 width = surface.w, height = surface.h;
- surface.free();
- return {textureID, width, height};
+
+ _state->_cast._textures[castMember] = {textureID, width, height};
+ return _state->_cast._textures[castMember];
}
ImGuiImage getTextID(CastMember *castMember) {
- if (castMember->_type != CastType::kCastText && castMember->_type != CastType::kCastButton && castMember->_type != CastType::kCastRichText)
+ if (castMember->_type != CastType::kCastText && castMember->_type != CastType::kCastButton && castMember->_type != CastType::kCastRichText) {
return {};
+ }
+
+ if (_state->_cast._textures.contains(castMember)) {
+ debug("I work");
+ return _state->_cast._textures[castMember];
+ }
Common::Array<Channel *> channels = g_director->getCurrentMovie()->getScore()->_channels;
Graphics::Surface source;
@@ -272,7 +285,9 @@ ImGuiImage getTextID(CastMember *castMember) {
int16 width = surface.w, height = surface.h;
surface.free();
- return {textureID, width, height};
+
+ _state->_cast._textures[castMember] = {textureID, width, height};
+ return _state->_cast._textures[castMember];
}
void displayVariable(const Common::String &name, bool changed, bool outOfScope) {
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index 734ad89e36e..f55d44efa9d 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -99,7 +99,7 @@ typedef struct ImGuiWindows {
typedef struct ImGuiState {
struct {
- Common::HashMap<Graphics::Surface *, ImGuiImage> _textures;
+ Common::HashMap<CastMember *, ImGuiImage> _textures;
bool _listView = true;
int _thumbnailSize = 64;
ImGuiTextFilter _nameFilter;
Commit: 73bc872d1c83ae160f87b6dee6498c28cd2b1dbd
https://github.com/scummvm/scummvm/commit/73bc872d1c83ae160f87b6dee6498c28cd2b1dbd
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Fix scrolling to current handler in execution context window
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-script-d2.cpp
engines/director/debugger/dt-script-d4.cpp
engines/director/debugger/dt-scripts.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index e48ddeaaf6a..0048aeba994 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -191,7 +191,6 @@ ImGuiImage getShapeID(CastMember *castMember) {
}
if (_state->_cast._textures.contains(castMember)) {
- debug("I work");
return _state->_cast._textures[castMember];
}
@@ -248,7 +247,6 @@ ImGuiImage getTextID(CastMember *castMember) {
}
if (_state->_cast._textures.contains(castMember)) {
- debug("I work");
return _state->_cast._textures[castMember];
}
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index f55d44efa9d..8a37f9dfb0b 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -214,8 +214,8 @@ void showArchive();
void showScore();
void showChannels();
-void renderOldScriptAST(ImGuiScript &script, bool showByteCode); // dt-script-d2.cpp
-void renderScriptAST(ImGuiScript &script, bool showByteCode); // dt-script-d4.cpp
+void renderOldScriptAST(ImGuiScript &script, bool showByteCode, bool scrollTo); // dt-script-d2.cpp
+void renderScriptAST(ImGuiScript &script, bool showByteCode, bool scrollTo); // dt-script-d4.cpp
// dt-scripts.cpp
void showFuncList();
diff --git a/engines/director/debugger/dt-script-d2.cpp b/engines/director/debugger/dt-script-d2.cpp
index 4c06a05a996..2ee490a64c1 100644
--- a/engines/director/debugger/dt-script-d2.cpp
+++ b/engines/director/debugger/dt-script-d2.cpp
@@ -38,9 +38,10 @@ private:
int _indent = 0;
bool _isScriptInDebug = false;
bool _currentStatementDisplayed = false;
+ bool _scrollTo = false;
public:
- explicit RenderOldScriptVisitor(ImGuiScript &script) : _script(script) {
+ explicit RenderOldScriptVisitor(ImGuiScript &script, bool scrollTo) : _script(script), _scrollTo(scrollTo) {
Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
if (!callstack.empty()) {
CFrame *head = callstack[callstack.size() - 1];
@@ -823,7 +824,7 @@ private:
if (showCurrentStatement) {
dl->AddQuadFilled(ImVec2(pos.x, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 10.f), ImVec2(pos.x, pos.y + 10.f), ImColor(_state->_colors._current_statement));
dl->AddTriangleFilled(ImVec2(pos.x + 8.f, pos.y), ImVec2(pos.x + 14.f, pos.y + 7.f), ImVec2(pos.x + 8.f, pos.y + 14.f), ImColor(_state->_colors._current_statement));
- if (_state->_dbg._isScriptDirty && !ImGui::IsItemVisible()) {
+ if (_state->_dbg._isScriptDirty && _scrollTo) {
ImGui::SetScrollHereY(0.5f);
}
dl->AddRectFilled(ImVec2(pos.x + 16.f, pos.y), ImVec2(pos.x + width, pos.y + 16.f), ImColor(IM_COL32(0xFF, 0xFF, 0x00, 0x20)), 0.4f);
@@ -841,8 +842,8 @@ private:
}
};
-void renderOldScriptAST(ImGuiScript &script, bool showByteCode) {
- RenderOldScriptVisitor oldVisitor(script);
+void renderOldScriptAST(ImGuiScript &script, bool showByteCode, bool scrollTo) {
+ RenderOldScriptVisitor oldVisitor(script, scrollTo);
script.oldAst->accept(&oldVisitor);
}
diff --git a/engines/director/debugger/dt-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index d033f7c7ad8..4a46108606c 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -35,7 +35,7 @@ namespace DT {
class RenderScriptVisitor : public LingoDec::NodeVisitor {
public:
- RenderScriptVisitor(ImGuiScript &script, bool showByteCode) : _script(script), _showByteCode(showByteCode) {
+ RenderScriptVisitor(ImGuiScript &script, bool showByteCode, bool scrollTo) : _script(script), _showByteCode(showByteCode), _scrollTo(scrollTo) {
Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
if (!callstack.empty()) {
CFrame *head = callstack[callstack.size() - 1];
@@ -1170,7 +1170,7 @@ private:
if (showCurrentStatement) {
dl->AddQuadFilled(ImVec2(pos.x, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 10.f), ImVec2(pos.x, pos.y + 10.f), ImColor(_state->_colors._current_statement));
dl->AddTriangleFilled(ImVec2(pos.x + 8.f, pos.y), ImVec2(pos.x + 14.f, pos.y + 7.f), ImVec2(pos.x + 8.f, pos.y + 14.f), ImColor(_state->_colors._current_statement));
- if (_state->_dbg._isScriptDirty) {
+ if (_state->_dbg._isScriptDirty && _scrollTo) {
ImGui::SetScrollHereY(0.5f);
}
dl->AddRectFilled(ImVec2(pos.x + 16.f, pos.y), ImVec2(pos.x + width, pos.y + 16.f), ImColor(IM_COL32(0xFF, 0xFF, 0x00, 0x20)), 0.4f);
@@ -1218,10 +1218,11 @@ private:
bool _currentStatementDisplayed = false;
bool _isScriptInDebug = false;
int _renderLineID = 0;
+ bool _scrollTo = false;
};
-void renderScriptAST(ImGuiScript &script, bool showByteCode) {
- RenderScriptVisitor visitor(script, showByteCode);
+void renderScriptAST(ImGuiScript &script, bool showByteCode, bool scrollTo) {
+ RenderScriptVisitor visitor(script, showByteCode, scrollTo);
script.root->accept(visitor);
}
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index f6943b65a4c..45489ce4259 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -97,18 +97,16 @@ static void renderCastScript(Symbol &sym) {
}
}
-static void renderScript(ImGuiScript &script, bool showByteCode) {
+static void renderScript(ImGuiScript &script, bool showByteCode, bool scrollTo) {
if (script.oldAst) {
- renderOldScriptAST(script, showByteCode);
- _state->_dbg._isScriptDirty = false;
+ renderOldScriptAST(script, showByteCode, scrollTo);
return;
}
if (!script.root)
return;
- renderScriptAST(script, showByteCode);
- _state->_dbg._isScriptDirty = false;
+ renderScriptAST(script, showByteCode, scrollTo);
}
static bool showScriptCast(CastMemberID &id) {
@@ -302,6 +300,7 @@ void showExecutionContext() {
Director::Lingo *lingo = g_director->getLingo();
Window *currentWindow = g_director->getCurrentWindow();
+ bool scriptsRendered = false;
if (ImGui::Begin("Execution Context", &_state->_w.executionContext, ImGuiWindowFlags_AlwaysAutoResize)) {
Window *stage = g_director->getStage();
@@ -382,17 +381,18 @@ void showExecutionContext() {
Movie *movie = g_director->getCurrentMovie();
if (!context || context->_functionHandlers.size() == 1) {
- renderScript(current, _state->_functions._scriptData->_showByteCode);
+ renderScript(current, _state->_functions._scriptData->_showByteCode, true);
} else {
for (auto &functionHandler : context->_functionHandlers) {
ImGuiScript script = toImGuiScript(context->_scriptType, current.id, functionHandler._key);
script.byteOffsets = context->_functionByteOffsets[script.handlerId];
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = getHandlerName(functionHandler._value);
- renderScript(script, _state->_functions._scriptData->_showByteCode);
+ renderScript(script, _state->_functions._scriptData->_showByteCode, script == current);
ImGui::NewLine();
}
}
+ scriptsRendered = true;
ImGui::EndChild();
}
@@ -484,18 +484,19 @@ void showExecutionContext() {
Movie *movie = g_director->getCurrentMovie();
if (!context || context->_functionHandlers.size() == 1) {
- renderScript(current, _state->_functions._scriptData->_showByteCode);
+ renderScript(current, _state->_functions._scriptData->_showByteCode, true);
} else {
for (auto &functionHandler : context->_functionHandlers) {
ImGuiScript script = toImGuiScript(context->_scriptType, current.id, functionHandler._key);
script.byteOffsets = context->_functionByteOffsets[script.handlerId];
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = getHandlerName(functionHandler._value);
- renderScript(script, _state->_functions._scriptData->_showByteCode);
+ renderScript(script, _state->_functions._scriptData->_showByteCode, script == current);
ImGui::NewLine();
}
}
+ scriptsRendered = true;
ImGui::EndChild();
}
@@ -504,6 +505,9 @@ void showExecutionContext() {
ImGui::PopID();
}
+ // Mark the scripts not dirty after all the handlers have been rendered
+ _state->_dbg._isScriptDirty = !scriptsRendered;
+
g_director->setCurrentWindow(currentWindow);
g_lingo->switchStateFromWindow();
}
Commit: 47e262fc9a78f7c4da1a3176b6aaf514f39dd739
https://github.com/scummvm/scummvm/commit/47e262fc9a78f7c4da1a3176b6aaf514f39dd739
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Render shape/text previews in grid view of Cast window
Changed paths:
engines/director/debugger/dt-cast.cpp
diff --git a/engines/director/debugger/dt-cast.cpp b/engines/director/debugger/dt-cast.cpp
index 4c4bd5bf45b..7b8bcab2873 100644
--- a/engines/director/debugger/dt-cast.cpp
+++ b/engines/director/debugger/dt-cast.cpp
@@ -154,7 +154,7 @@ void showCast() {
ImGui::TableSetupColumn("#", 0, 20.f);
ImGui::TableSetupColumn("Script", 0, 80.f);
ImGui::TableSetupColumn("Type", 0, 80.f);
- ImGui::TableSetupColumn("Preview", ImGuiTableColumnFlags_WidthStretch, 80.f);
+ ImGui::TableSetupColumn("Preview", ImGuiTableColumnFlags_WidthStretch, 30.f);
ImGui::TableHeadersRow();
for (auto it : *movie->getCasts()) {
@@ -190,10 +190,11 @@ void showCast() {
ImGui::TableNextColumn();
float columnWidth = ImGui::GetColumnWidth();
+ ImGuiImage imgID = {};
switch (castMember._value->_type) {
case kCastBitmap:
{
- ImGuiImage imgID = getImageID(castMember._value);
+ imgID = getImageID(castMember._value);
if (imgID.id) {
float offsetX = (columnWidth - 32.f) * 0.5f;
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
@@ -206,22 +207,22 @@ void showCast() {
case kCastRichText:
case kCastButton:
{
- ImGuiImage textID = getTextID(castMember._value);
- if (textID.id) {
+ imgID = getTextID(castMember._value);
+ if (imgID.id) {
float offsetX = (columnWidth - 32.f) * 0.5f;
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
- showImage(textID, name.c_str(), 32.f);
+ showImage(imgID, name.c_str(), 32.f);
}
}
break;
case kCastShape:
{
- ImGuiImage shapeID = getShapeID(castMember._value);
- if (shapeID.id) {
+ imgID = getShapeID(castMember._value);
+ if (imgID.id) {
float offsetX = (columnWidth - 32.f) * 0.5f;
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX);
- showImage(shapeID, name.c_str(), 32.f);
+ showImage(imgID, name.c_str(), 32.f);
}
}
break;
@@ -264,10 +265,41 @@ void showCast() {
textHeight *= (textSize.x / textWidth);
}
- ImGuiImage imgID = getImageID(castMember._value);
- if (imgID.id) {
- showImage(imgID, name.c_str(), thumbnailSize);
- } else {
+ ImGuiImage imgID = {};
+ switch (castMember._value->_type) {
+ case kCastBitmap:
+ {
+ imgID = getImageID(castMember._value);
+ if (imgID.id) {
+ showImage(imgID, name.c_str(), thumbnailSize);
+ }
+ }
+ break;
+
+ case kCastText:
+ case kCastRichText:
+ case kCastButton:
+ {
+ imgID = getTextID(castMember._value);
+ if (imgID.id) {
+ showImage(imgID, name.c_str(), thumbnailSize);
+ }
+ }
+ break;
+
+ case kCastShape:
+ {
+ imgID = getShapeID(castMember._value);
+ if (imgID.id) {
+ showImage(imgID, name.c_str(), thumbnailSize);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!imgID.id) {
ImGui::PushID(castMember._key);
ImGui::InvisibleButton("##canvas", ImVec2(thumbnailSize, thumbnailSize));
ImGui::PopID();
Commit: 141631ca6c0aa575f005a956d9e8575942e3a6aa
https://github.com/scummvm/scummvm/commit/141631ca6c0aa575f005a956d9e8575942e3a6aa
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Fix wrong column height in preview of cast members in Cast Window
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-cast.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 0048aeba994..dc390e3cb85 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -178,6 +178,9 @@ void showImage(const ImGuiImage &image, const char *name, float thumbnailSize) {
ImVec2 screenPos = ImGui::GetCursorScreenPos();
ImGui::GetWindowDrawList()->AddRect(screenPos, screenPos + ImVec2(thumbnailSize, thumbnailSize), 0xFFFFFFFF);
ImVec2 pos = ImGui::GetCursorPos();
+
+ // Reserve the space of area thumbnailSize * thumbnailSize to make sure the column stretches properly
+ ImGui::Dummy(ImVec2(thumbnailSize, thumbnailSize));
ImVec2 imgPos = pos + ImVec2(1 + (thumbnailSize - 2 - size.x) * 0.5f, 1 + (thumbnailSize - 2 - size.y) * 0.5f);
ImGui::SetCursorPos(imgPos);
ImGui::Image(image.id, size);
diff --git a/engines/director/debugger/dt-cast.cpp b/engines/director/debugger/dt-cast.cpp
index 7b8bcab2873..3d4a6eeddbc 100644
--- a/engines/director/debugger/dt-cast.cpp
+++ b/engines/director/debugger/dt-cast.cpp
@@ -113,7 +113,7 @@ void showCast() {
return;
ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
- ImGui::SetNextWindowSize(ImVec2(560, 480), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(480, 480), ImGuiCond_FirstUseEver);
if (ImGui::Begin("Cast", &_state->_w.cast)) {
// display a toolbar with: grid/list/filters buttons + name filter
@@ -154,7 +154,7 @@ void showCast() {
ImGui::TableSetupColumn("#", 0, 20.f);
ImGui::TableSetupColumn("Script", 0, 80.f);
ImGui::TableSetupColumn("Type", 0, 80.f);
- ImGui::TableSetupColumn("Preview", ImGuiTableColumnFlags_WidthStretch, 30.f);
+ ImGui::TableSetupColumn("Preview", ImGuiTableColumnFlags_WidthStretch, 50.f);
ImGui::TableHeadersRow();
for (auto it : *movie->getCasts()) {
Commit: a002d120eb100db9009f6d5367bee1169c404e59
https://github.com/scummvm/scummvm/commit/a002d120eb100db9009f6d5367bee1169c404e59
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Render shape previews without using current channels
Create a new channel with the same information and use that to blit
the preview. This allows all shapes to be rendered even if they are
not present in any channel in the current score frame
Changed paths:
engines/director/debugger/debugtools.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index dc390e3cb85..96463c474a6 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -197,19 +197,20 @@ ImGuiImage getShapeID(CastMember *castMember) {
return _state->_cast._textures[castMember];
}
- Common::Array<Channel *> channels = g_director->getCurrentMovie()->getScore()->_channels;
- Channel *channel = nullptr;
-
- for (auto it : channels) {
- if (it->_sprite && it->_sprite->_castId.member == castMember->getID()) {
- channel = new Channel(*it);
- break;
- }
- }
- // This means the shapes that are not in any channel won't be shown
- if (!channel) {
- return {};
- }
+ ShapeCastMember *shapeMember = (ShapeCastMember *)castMember;
+
+ // Make a temporary Sprite
+ Sprite *sprite = new Sprite();
+ sprite->_movie = g_director->getCurrentMovie();
+ sprite->setCast(CastMemberID(castMember->getID(), castMember->getCast()->_castLibID));
+ sprite->_ink = shapeMember->_ink;
+ sprite->_backColor = shapeMember->getBackColor();
+ sprite->_foreColor = shapeMember->getForeColor();
+ sprite->_pattern = shapeMember->_pattern;
+ sprite->_thickness = shapeMember->_lineThickness;
+
+ // Make a temporary channel to blit the shape to
+ Channel *channel = new Channel(nullptr, sprite);
Common::Rect bbox(castMember->getBbox());
Commit: ce552e80da7010bebd2eee081897540406027dfa
https://github.com/scummvm/scummvm/commit/ce552e80da7010bebd2eee081897540406027dfa
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Render Text Previews without using current channels
Create a new channel with the same information and use that to blit
the preview. This allows all text to be rendered even if they are
not present in any channel in the current score frame
Changed paths:
engines/director/debugger/debugtools.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 96463c474a6..f097f6ee5b5 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -31,6 +31,7 @@
#include "director/cast.h"
#include "director/castmember/bitmap.h"
#include "director/castmember/shape.h"
+#include "director/castmember/text.h"
#include "director/debugger.h"
#include "director/movie.h"
#include "director/window.h"
@@ -209,7 +210,7 @@ ImGuiImage getShapeID(CastMember *castMember) {
sprite->_pattern = shapeMember->_pattern;
sprite->_thickness = shapeMember->_lineThickness;
- // Make a temporary channel to blit the shape to
+ // Make a temporary channel to blit the shape from
Channel *channel = new Channel(nullptr, sprite);
Common::Rect bbox(castMember->getBbox());
@@ -237,6 +238,7 @@ ImGuiImage getShapeID(CastMember *castMember) {
ImTextureID textureID = (ImTextureID)(intptr_t)g_system->getImGuiTexture(surface, g_director->getPalette(), g_director->getPaletteColorCount());
delete managedSurface;
+ delete sprite;
delete channel;
int16 width = surface.w, height = surface.h;
@@ -254,23 +256,23 @@ ImGuiImage getTextID(CastMember *castMember) {
return _state->_cast._textures[castMember];
}
- Common::Array<Channel *> channels = g_director->getCurrentMovie()->getScore()->_channels;
- Graphics::Surface source;
+ Common::Rect bbox(castMember->getBbox());
- // This means the shapes that are not in any channel won't be shown
- for (auto it : channels) {
- if (it->_sprite && it->_sprite->_castId.member == castMember->getID() && it->_widget) {
- source = it->_widget->getSurface()->rawSurface();
- break;
- }
- }
+ // Make a temporary Sprite
+ Sprite *sprite = new Sprite();
+ sprite->_spriteType = kTextSprite;
+ sprite->_movie = g_director->getCurrentMovie();
+ sprite->setCast(CastMemberID(castMember->getID(), castMember->getCast()->_castLibID));
+ sprite->_backColor = castMember->getBackColor();
+ sprite->_foreColor = castMember->getForeColor();
+ sprite->_editable = false;
- if (source.format.bytesPerPixel > 4 || !source.getPixels()) {
- return {};
- }
+ // Make a temporary channel to blit the shape from
+ Channel *channel = new Channel(nullptr, sprite);
+ Graphics::MacWidget *widget = castMember->createWidget(bbox, channel, kTextSprite);
Graphics::Surface surface;
- surface.copyFrom(source);
+ surface.copyFrom(*widget->getSurface());
if (debugChannelSet(8, kDebugImages)) {
Common::String prepend = "text";
@@ -287,6 +289,9 @@ ImGuiImage getTextID(CastMember *castMember) {
int16 width = surface.w, height = surface.h;
surface.free();
+ delete widget;
+ delete sprite;
+ delete channel;
_state->_cast._textures[castMember] = {textureID, width, height};
return _state->_cast._textures[castMember];
Commit: a69fa302aa0eed1fc1f6595d44aad56ebd7b4b23
https://github.com/scummvm/scummvm/commit/a69fa302aa0eed1fc1f6595d44aad56ebd7b4b23
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Implement 'Go to Definition' in scripts
In the execution context a call to a function can be clicked on
to jump to the script that contains its definition
Implement the functionality
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-script-d4.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index f097f6ee5b5..31646210e80 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -127,6 +127,24 @@ ScriptContext *getScriptContext(CastMemberID id) {
return ctx;
}
+int16 getCastIdFromScriptNameIndex(uint32 nameIndex, CastMemberID id, Common::String handlerName) {
+ Movie *movie = g_director->getCurrentMovie();
+ Cast *cast = movie->getCasts()->getVal(id.castLib);
+
+ // If the name at nameIndex is not the same as handler name, means its a local script
+ if (cast->_lingoArchive->names[nameIndex] != handlerName) {
+ return id.member;
+ }
+
+ for (auto it : cast->_lingoArchive->scriptContexts[kMovieScript]) {
+ if (it._value->_functionHandlers.contains(handlerName)) {
+ return it._key;
+ }
+ }
+
+ return -1;
+}
+
Director::Breakpoint *getBreakpoint(const Common::String &handlerName, uint16 scriptId, uint pc) {
auto &bps = g_lingo->getBreakpoints();
for (uint i = 0; i < bps.size(); i++) {
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index 8a37f9dfb0b..b92483e5f71 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -190,6 +190,7 @@ typedef struct ImGuiState {
// debugtools.cpp
ImGuiScript toImGuiScript(ScriptType scriptType, CastMemberID id, const Common::String &handlerId);
ScriptContext *getScriptContext(CastMemberID id);
+int16 getCastIdFromScriptNameIndex(uint32 nameIndex, CastMemberID castId, Common::String handler);
void setScriptToDisplay(const ImGuiScript &script);
Director::Breakpoint *getBreakpoint(const Common::String &handlerName, uint16 scriptId, uint pc);
void displayScriptRef(CastMemberID &scriptId);
diff --git a/engines/director/debugger/dt-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index 4a46108606c..40bd72f93c1 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -98,6 +98,8 @@ public:
int32 obj = 0;
for (uint i = 0; i < _script.bytecodeArray.size(); i++) {
if (node._startOffset == _script.bytecodeArray[i].pos) {
+ // This obj represents the index of the handler being called
+ // The index may be local (lingo context-wide) or global (cast-wide)
obj = _script.bytecodeArray[i].obj;
break;
}
@@ -117,10 +119,13 @@ public:
ImGui::EndTooltip();
}
if (!g_lingo->_builtinCmds.contains(node.name) && ImGui::IsItemClicked()) {
- ImGuiScript script = toImGuiScript(_script.type, CastMemberID(obj, _script.id.castLib), node.name);
+ int16 castId = getCastIdFromScriptNameIndex(obj, _script.id, node.name);
+ debug("Does it work? %d", castId);
+ ImGuiScript script = toImGuiScript(_script.type, CastMemberID(castId, _script.id.castLib), node.name);
script.moviePath = _script.moviePath;
script.handlerName = node.name;
setScriptToDisplay(script);
+ _state->_dbg._isScriptDirty = true;
}
ImGui::SameLine();
@@ -1016,6 +1021,10 @@ private:
}
ImGui::NewLine();
+ if (_state->_dbg._isScriptDirty && _scrollTo) {
+ debug("I set scroll, %s", _script.handlerId.c_str());
+ ImGui::SetScrollHereY(0.5f);
+ }
unindent();
node.block->accept(*this);
@@ -1171,6 +1180,7 @@ private:
dl->AddQuadFilled(ImVec2(pos.x, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 10.f), ImVec2(pos.x, pos.y + 10.f), ImColor(_state->_colors._current_statement));
dl->AddTriangleFilled(ImVec2(pos.x + 8.f, pos.y), ImVec2(pos.x + 14.f, pos.y + 7.f), ImVec2(pos.x + 8.f, pos.y + 14.f), ImColor(_state->_colors._current_statement));
if (_state->_dbg._isScriptDirty && _scrollTo) {
+ debug("I set scroll here as well: %s", _script.handlerId.c_str());
ImGui::SetScrollHereY(0.5f);
}
dl->AddRectFilled(ImVec2(pos.x + 16.f, pos.y), ImVec2(pos.x + width, pos.y + 16.f), ImColor(IM_COL32(0xFF, 0xFF, 0x00, 0x20)), 0.4f);
Commit: 68d73536190048271bb2e2158316ef0db5abc0f1
https://github.com/scummvm/scummvm/commit/68d73536190048271bb2e2158316ef0db5abc0f1
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Scroll to the handler when "Go To Definition" is clicked
Fix an issue where when we jump to the definition of a handler by
clicking on it, the script opens up, but it doesn't scroll to the
correct handler and we have to manually search through
Now the script automatically scrolls to the handler
Changed paths:
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-script-d2.cpp
engines/director/debugger/dt-script-d4.cpp
engines/director/debugger/dt-scripts.cpp
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index b92483e5f71..b3e5f246757 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -118,6 +118,7 @@ typedef struct ImGuiState {
struct {
bool _isScriptDirty = false; // indicates whether or not we have to display the script corresponding to the current stackframe
+ bool _goToDefinition = false;
uint _lastLinePC = 0;
uint _callstackSize = 0;
} _dbg;
diff --git a/engines/director/debugger/dt-script-d2.cpp b/engines/director/debugger/dt-script-d2.cpp
index 2ee490a64c1..1d632b57d50 100644
--- a/engines/director/debugger/dt-script-d2.cpp
+++ b/engines/director/debugger/dt-script-d2.cpp
@@ -69,6 +69,11 @@ public:
}
ImGui::NewLine();
}
+ if (_state->_dbg._goToDefinition && _scrollTo) {
+ ImGui::SetScrollHereY(0.5f);
+ _state->_dbg._goToDefinition = false;
+ }
+
indent();
for (uint i = 0; i < node->stmts->size(); i++) {
Node *stmt = (*node->stmts)[i];
@@ -497,10 +502,12 @@ public:
}
}
- ImGuiScript script = toImGuiScript(_script.type, CastMemberID(obj, _script.id.castLib), *node->name);
+ int16 castId = getCastIdFromScriptNameIndex(obj, _script.id, *node->name);
+ ImGuiScript script = toImGuiScript(_script.type, CastMemberID(castId, _script.id.castLib), *node->name);
script.moviePath = _script.moviePath;
script.handlerName = *node->name;
setScriptToDisplay(script);
+ _state->_dbg._goToDefinition = true;
}
ImGui::SameLine();
for (uint i = 0; i < node->args->size(); i++) {
diff --git a/engines/director/debugger/dt-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index 40bd72f93c1..1f24732b2ac 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -95,16 +95,6 @@ public:
}
virtual void visit(const LingoDec::CallNode &node) override {
- int32 obj = 0;
- for (uint i = 0; i < _script.bytecodeArray.size(); i++) {
- if (node._startOffset == _script.bytecodeArray[i].pos) {
- // This obj represents the index of the handler being called
- // The index may be local (lingo context-wide) or global (cast-wide)
- obj = _script.bytecodeArray[i].obj;
- break;
- }
- }
-
// new line only if it's a statement
if (node.isStatement) {
renderLine(node._startOffset);
@@ -119,13 +109,21 @@ public:
ImGui::EndTooltip();
}
if (!g_lingo->_builtinCmds.contains(node.name) && ImGui::IsItemClicked()) {
+ int32 obj = 0;
+ for (uint i = 0; i < _script.bytecodeArray.size(); i++) {
+ if (node._startOffset == _script.bytecodeArray[i].pos) {
+ // This obj represents the index of the handler being called
+ // The index may be local (lingo context-wide) or global (cast-wide)
+ obj = _script.bytecodeArray[i].obj;
+ break;
+ }
+ }
int16 castId = getCastIdFromScriptNameIndex(obj, _script.id, node.name);
- debug("Does it work? %d", castId);
ImGuiScript script = toImGuiScript(_script.type, CastMemberID(castId, _script.id.castLib), node.name);
script.moviePath = _script.moviePath;
script.handlerName = node.name;
setScriptToDisplay(script);
- _state->_dbg._isScriptDirty = true;
+ _state->_dbg._goToDefinition = true;
}
ImGui::SameLine();
@@ -991,6 +989,11 @@ private:
ImGui::SameLine();
}
}
+ if (_state->_dbg._goToDefinition && _scrollTo) {
+ ImGui::SetScrollHereY(0.5f);
+ _state->_dbg._goToDefinition = false;
+ }
+
indent();
if (isMethod && !_script.propertyNames.empty() && node.handler == &node.handler->script->handlers[0]) {
@@ -1021,10 +1024,6 @@ private:
}
ImGui::NewLine();
- if (_state->_dbg._isScriptDirty && _scrollTo) {
- debug("I set scroll, %s", _script.handlerId.c_str());
- ImGui::SetScrollHereY(0.5f);
- }
unindent();
node.block->accept(*this);
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index 45489ce4259..1a5ca6544f1 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -166,7 +166,6 @@ static void updateCurrentScript() {
if (callstack.empty())
return;
-
// show current script of the current stack frame
CFrame *head = callstack[callstack.size() - 1];
Director::Movie *movie = g_director->getCurrentMovie();
@@ -481,14 +480,14 @@ void showExecutionContext() {
// Get all the handlers from the script
ScriptContext* context = getScriptContext(current.id);
- Movie *movie = g_director->getCurrentMovie();
-
+ context->_id;
if (!context || context->_functionHandlers.size() == 1) {
renderScript(current, _state->_functions._scriptData->_showByteCode, true);
} else {
for (auto &functionHandler : context->_functionHandlers) {
ImGuiScript script = toImGuiScript(context->_scriptType, current.id, functionHandler._key);
script.byteOffsets = context->_functionByteOffsets[script.handlerId];
+ Movie *movie = g_director->getCurrentMovie();
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = getHandlerName(functionHandler._value);
renderScript(script, _state->_functions._scriptData->_showByteCode, script == current);
Commit: b90fe172212f4b50a428504c0e8ff7c2e24c38af
https://github.com/scummvm/scummvm/commit/b90fe172212f4b50a428504c0e8ff7c2e24c38af
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Remove unnecessary pointer `ScriptData`
Instead access the array of `ImGuiScript` for the ScriptData
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-controlpanel.cpp
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-script-d4.cpp
engines/director/debugger/dt-scripts.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 31646210e80..6c0b7350700 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -372,14 +372,15 @@ static void addScriptCastToDisplay(CastMemberID &id) {
}
void setScriptToDisplay(const ImGuiScript &script) {
- uint index = _state->_functions._scriptData->_scripts.size();
- if (index && _state->_functions._scriptData->_scripts[index - 1] == script) {
- _state->_functions._scriptData->_showScript = true;
+ ScriptData *scriptData = &_state->_functions._windowScriptData.getOrCreateVal(g_director->getCurrentWindow());
+ uint index = scriptData->_scripts.size();
+ if (index && scriptData->_scripts[index - 1] == script) {
+ scriptData->_showScript = true;
return;
}
- _state->_functions._scriptData->_scripts.push_back(script);
- _state->_functions._scriptData->_current = index;
- _state->_functions._scriptData->_showScript = true;
+ scriptData->_scripts.push_back(script);
+ scriptData->_current = index;
+ scriptData->_showScript = true;
}
void displayScriptRef(CastMemberID &scriptId) {
diff --git a/engines/director/debugger/dt-controlpanel.cpp b/engines/director/debugger/dt-controlpanel.cpp
index 13d9f54d4a8..f2f1072578d 100644
--- a/engines/director/debugger/dt-controlpanel.cpp
+++ b/engines/director/debugger/dt-controlpanel.cpp
@@ -31,12 +31,12 @@ namespace Director {
namespace DT {
static uint32 getLineFromPC() {
- _state->_functions._scriptData = &_state->_functions._windowScriptData.getOrCreateVal(g_director->getCurrentWindow());
+ ScriptData *scriptData = &_state->_functions._windowScriptData.getOrCreateVal(g_director->getCurrentWindow());
const uint pc = g_lingo->_state->pc;
- if (_state->_functions._scriptData->_scripts.empty())
+ if (scriptData->_scripts.empty())
return 0;
- const Common::Array<uint> &offsets = _state->_functions._scriptData->_scripts[_state->_functions._scriptData->_current].startOffsets;
+ const Common::Array<uint> &offsets = scriptData->_scripts[scriptData->_current].startOffsets;
for (uint i = 0; i < offsets.size(); i++) {
if (pc <= offsets[i])
return i;
@@ -124,8 +124,6 @@ void showControlPanel() {
ImGui::SetNextWindowPos(ImVec2(vp.x - 220.0f, 20.0f), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(200, 103), ImGuiCond_FirstUseEver);
- _state->_functions._scriptData = &_state->_functions._windowScriptData.getOrCreateVal(g_director->getCurrentWindow());
-
if (ImGui::Begin("Control Panel", &_state->_w.controlPanel)) {
Movie *movie = g_director->getCurrentMovie();
Score *score = movie->getScore();
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index b3e5f246757..ddd0dc74dfc 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -97,6 +97,13 @@ typedef struct ImGuiWindows {
bool executionContext = false;
} ImGuiWindows;
+typedef struct ScriptData {
+ Common::Array<ImGuiScript> _scripts;
+ uint _current = 0;
+ bool _showByteCode = false;
+ bool _showScript = false;
+} ScriptData;
+
typedef struct ImGuiState {
struct {
Common::HashMap<CastMember *, ImGuiImage> _textures;
@@ -106,12 +113,6 @@ typedef struct ImGuiState {
int _typeFilter = 0x7FFF;
} _cast;
struct {
- struct ScriptData {
- Common::Array<ImGuiScript> _scripts;
- uint _current = 0;
- bool _showByteCode = false;
- bool _showScript = false;
- } *_scriptData;
ImGuiTextFilter _nameFilter;
Common::HashMap<Window *, ScriptData> _windowScriptData;
} _functions;
diff --git a/engines/director/debugger/dt-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index 1f24732b2ac..3e6c8cd7bbf 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -1179,7 +1179,6 @@ private:
dl->AddQuadFilled(ImVec2(pos.x, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 4.f), ImVec2(pos.x + 9.f, pos.y + 10.f), ImVec2(pos.x, pos.y + 10.f), ImColor(_state->_colors._current_statement));
dl->AddTriangleFilled(ImVec2(pos.x + 8.f, pos.y), ImVec2(pos.x + 14.f, pos.y + 7.f), ImVec2(pos.x + 8.f, pos.y + 14.f), ImColor(_state->_colors._current_statement));
if (_state->_dbg._isScriptDirty && _scrollTo) {
- debug("I set scroll here as well: %s", _script.handlerId.c_str());
ImGui::SetScrollHereY(0.5f);
}
dl->AddRectFilled(ImVec2(pos.x + 16.f, pos.y), ImVec2(pos.x + width, pos.y + 16.f), ImColor(IM_COL32(0xFF, 0xFF, 0x00, 0x20)), 0.4f);
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index 1a5ca6544f1..f3c746c3420 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -323,21 +323,21 @@ void showExecutionContext() {
ImGui::SeparatorText("Scripts");
- _state->_functions._scriptData = &_state->_functions._windowScriptData.getOrCreateVal(stage);
+ ScriptData *scriptData = &_state->_functions._windowScriptData.getOrCreateVal(stage);
updateCurrentScript();
- if (_state->_functions._scriptData->_showScript) {
- ImGui::BeginDisabled(_state->_functions._scriptData->_scripts.empty() || _state->_functions._scriptData->_current == 0);
+ if (scriptData->_showScript) {
+ ImGui::BeginDisabled(scriptData->_scripts.empty() || scriptData->_current == 0);
if (ImGui::Button(ICON_MS_ARROW_BACK)) {
- _state->_functions._scriptData->_current--;
+ scriptData->_current--;
}
ImGui::EndDisabled();
ImGui::SetItemTooltip("Backward");
ImGui::SameLine();
- ImGui::BeginDisabled(_state->_functions._scriptData->_current >= _state->_functions._scriptData->_scripts.size() - 1);
+ ImGui::BeginDisabled(scriptData->_current >= scriptData->_scripts.size() - 1);
if (ImGui::Button(ICON_MS_ARROW_FORWARD)) {
- _state->_functions._scriptData->_current++;
+ scriptData->_current++;
}
ImGui::EndDisabled();
ImGui::SetItemTooltip("Forward");
@@ -345,49 +345,49 @@ void showExecutionContext() {
const char *currentScript = nullptr;
- if (_state->_functions._scriptData->_current < _state->_functions._scriptData->_scripts.size()) {
- currentScript = _state->_functions._scriptData->_scripts[_state->_functions._scriptData->_current].handlerName.c_str();
+ if (scriptData->_current < scriptData->_scripts.size()) {
+ currentScript = scriptData->_scripts[scriptData->_current].handlerName.c_str();
}
if (ImGui::BeginCombo("##handlers", currentScript)) {
- for (uint i = 0; i < _state->_functions._scriptData->_scripts.size(); i++) {
- auto &script = _state->_functions._scriptData->_scripts[i];
- bool selected = i == _state->_functions._scriptData->_current;
+ for (uint i = 0; i < scriptData->_scripts.size(); i++) {
+ auto &script = scriptData->_scripts[i];
+ bool selected = i == scriptData->_current;
if (ImGui::Selectable(script.handlerName.c_str(), &selected)) {
- _state->_functions._scriptData->_current = i;
+ scriptData->_current = i;
}
}
ImGui::EndCombo();
}
- if (!_state->_functions._scriptData->_scripts[_state->_functions._scriptData->_current].oldAst) {
+ if (!scriptData->_scripts[scriptData->_current].oldAst) {
ImGui::SameLine(0, 20);
- ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &_state->_functions._scriptData->_showByteCode, true); // Lingo
+ ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &scriptData->_showByteCode, true); // Lingo
ImGui::SetItemTooltip("Lingo");
ImGui::SameLine();
- ImGuiEx::toggleButton(ICON_MS_STACKS, &_state->_functions._scriptData->_showByteCode); // Bytecode
+ ImGuiEx::toggleButton(ICON_MS_STACKS, &scriptData->_showByteCode); // Bytecode
ImGui::SetItemTooltip("Bytecode");
}
ImGui::Separator();
childSize = ImGui::GetContentRegionAvail();
ImGui::BeginChild("##script", childSize);
- ImGuiScript ¤t = _state->_functions._scriptData->_scripts[_state->_functions._scriptData->_current];
+ ImGuiScript ¤t = scriptData->_scripts[scriptData->_current];
// Get all the handlers from the script
ScriptContext* context = getScriptContext(current.id);
Movie *movie = g_director->getCurrentMovie();
if (!context || context->_functionHandlers.size() == 1) {
- renderScript(current, _state->_functions._scriptData->_showByteCode, true);
+ renderScript(current, scriptData->_showByteCode, true);
} else {
for (auto &functionHandler : context->_functionHandlers) {
ImGuiScript script = toImGuiScript(context->_scriptType, current.id, functionHandler._key);
script.byteOffsets = context->_functionByteOffsets[script.handlerId];
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = getHandlerName(functionHandler._value);
- renderScript(script, _state->_functions._scriptData->_showByteCode, script == current);
+ renderScript(script, scriptData->_showByteCode, script == current);
ImGui::NewLine();
}
}
@@ -426,21 +426,21 @@ void showExecutionContext() {
ImGui::SeparatorText("Scripts");
- _state->_functions._scriptData = &_state->_functions._windowScriptData.getOrCreateVal(window);
+ scriptData = &_state->_functions._windowScriptData.getOrCreateVal(window);
updateCurrentScript();
- if (_state->_functions._scriptData->_showScript) {
- ImGui::BeginDisabled(_state->_functions._scriptData->_scripts.empty() || _state->_functions._scriptData->_current == 0);
+ if (scriptData->_showScript) {
+ ImGui::BeginDisabled(scriptData->_scripts.empty() || scriptData->_current == 0);
if (ImGui::Button(ICON_MS_ARROW_BACK)) {
- _state->_functions._scriptData->_current--;
+ scriptData->_current--;
}
ImGui::EndDisabled();
ImGui::SetItemTooltip("Backward");
ImGui::SameLine();
- ImGui::BeginDisabled(_state->_functions._scriptData->_current >= _state->_functions._scriptData->_scripts.size() - 1);
+ ImGui::BeginDisabled(scriptData->_current >= scriptData->_scripts.size() - 1);
if (ImGui::Button(ICON_MS_ARROW_FORWARD)) {
- _state->_functions._scriptData->_current++;
+ scriptData->_current++;
}
ImGui::EndDisabled();
ImGui::SetItemTooltip("Forward");
@@ -448,41 +448,41 @@ void showExecutionContext() {
const char *currentScript = nullptr;
- if (_state->_functions._scriptData->_current < _state->_functions._scriptData->_scripts.size()) {
- currentScript = _state->_functions._scriptData->_scripts[_state->_functions._scriptData->_current].handlerName.c_str();
+ if (scriptData->_current < scriptData->_scripts.size()) {
+ currentScript = scriptData->_scripts[scriptData->_current].handlerName.c_str();
}
if (ImGui::BeginCombo("##handlers", currentScript)) {
- for (uint i = 0; i < _state->_functions._scriptData->_scripts.size(); i++) {
- auto &script = _state->_functions._scriptData->_scripts[i];
- bool selected = i == _state->_functions._scriptData->_current;
+ for (uint i = 0; i < scriptData->_scripts.size(); i++) {
+ auto &script = scriptData->_scripts[i];
+ bool selected = i == scriptData->_current;
if (ImGui::Selectable(script.handlerName.c_str(), &selected)) {
- _state->_functions._scriptData->_current = i;
+ scriptData->_current = i;
}
}
ImGui::EndCombo();
}
- if (!_state->_functions._scriptData->_scripts[_state->_functions._scriptData->_current].oldAst) {
+ if (!scriptData->_scripts[scriptData->_current].oldAst) {
ImGui::SameLine(0, 20);
- ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &_state->_functions._scriptData->_showByteCode, true); // Lingo
+ ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &scriptData->_showByteCode, true); // Lingo
ImGui::SetItemTooltip("Lingo");
ImGui::SameLine();
- ImGuiEx::toggleButton(ICON_MS_STACKS, &_state->_functions._scriptData->_showByteCode); // Bytecode
+ ImGuiEx::toggleButton(ICON_MS_STACKS, &scriptData->_showByteCode); // Bytecode
ImGui::SetItemTooltip("Bytecode");
}
ImGui::Separator();
childSize = ImGui::GetContentRegionAvail();
ImGui::BeginChild("##script", childSize);
- ImGuiScript ¤t = _state->_functions._scriptData->_scripts[_state->_functions._scriptData->_current];
+ ImGuiScript ¤t = scriptData->_scripts[scriptData->_current];
// Get all the handlers from the script
ScriptContext* context = getScriptContext(current.id);
context->_id;
if (!context || context->_functionHandlers.size() == 1) {
- renderScript(current, _state->_functions._scriptData->_showByteCode, true);
+ renderScript(current, scriptData->_showByteCode, true);
} else {
for (auto &functionHandler : context->_functionHandlers) {
ImGuiScript script = toImGuiScript(context->_scriptType, current.id, functionHandler._key);
@@ -490,7 +490,7 @@ void showExecutionContext() {
Movie *movie = g_director->getCurrentMovie();
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = getHandlerName(functionHandler._value);
- renderScript(script, _state->_functions._scriptData->_showByteCode, script == current);
+ renderScript(script, scriptData->_showByteCode, script == current);
ImGui::NewLine();
}
}
Commit: 41bd02feb8de6c8450d3ab74aacc0b525aeedc19
https://github.com/scummvm/scummvm/commit/41bd02feb8de6c8450d3ab74aacc0b525aeedc19
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Create table for saving and loading window flags
While saving and loading ImGui state, we take into account whether
or not a certain ImGui window is open or not, but instead of using
a bunch of constants, create a table to store the flags to make it
extensible
Changed paths:
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-save-state.cpp
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index ddd0dc74dfc..bf31d94ef50 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -104,6 +104,11 @@ typedef struct ScriptData {
bool _showScript = false;
} ScriptData;
+typedef struct WindowFlag {
+ const char *name;
+ bool *flag;
+} WindowFlag;
+
typedef struct ImGuiState {
struct {
Common::HashMap<CastMember *, ImGuiImage> _textures;
@@ -228,8 +233,7 @@ void showExecutionContext();
// dt-save-state.cpp
void saveCurrentState();
void loadSavedState();
-long long int getWindowFlags();
-void setWindowFlags(long long int openFlags);
+Common::Array<WindowFlag> getWindowFlags();
extern ImGuiState *_state;
diff --git a/engines/director/debugger/dt-save-state.cpp b/engines/director/debugger/dt-save-state.cpp
index fbd33eee047..581693453f6 100644
--- a/engines/director/debugger/dt-save-state.cpp
+++ b/engines/director/debugger/dt-save-state.cpp
@@ -26,16 +26,31 @@
#include "common/file.h"
#include "director/director.h"
+#include "director/movie.h"
+#include "director/score.h"
#include "director/debugger/dt-internal.h"
namespace Director {
namespace DT {
Common::String savedStateFileName = Common::String("ImGuiSaveState.json");
-const char *WINDOW_LIST[] = {
- "Archive", "Breakpoints", "Vars", "Watched Vars", "Score", "Control Panel",
- "Execution Context", "Functions", "Channels", "Cast", "Settings"
-};
+
+Common::Array<WindowFlag> getWindowFlags() {
+ return {
+ { "Archive", &_state->_w.archive },
+ { "Breakpoints", &_state->_w.bpList },
+ { "Cast", &_state->_w.cast },
+ { "Channels", &_state->_w.channels },
+ { "Control Panel", &_state->_w.controlPanel },
+ { "Execution Context", &_state->_w.executionContext },
+ { "Functions", &_state->_w.funcList },
+ { "Log", &_state->_w.logger },
+ { "Score", &_state->_w.score },
+ { "Settings", &_state->_w.settings },
+ { "Vars", &_state->_w.vars },
+ { "Watched Vars", &_state->_w.watchedVars },
+ };
+}
// What are the things that need saving?
// 1) Window Positions
@@ -46,8 +61,22 @@ void saveCurrentState() {
Common::JSONObject json = Common::JSONObject();
// Whether windows are open or not
- long long int openFlags = getWindowFlags();
- json["Windows"] = new Common::JSONValue(openFlags);
+ Common::Array<WindowFlag> windows = getWindowFlags();
+
+ uint index = 0;
+ int64 openFlags = 0;
+ for (const WindowFlag &it : windows) {
+ openFlags += (*it.flag) ? 1 << index : 0;
+ index += 1;
+ }
+ if (debugChannelSet(7, kDebugImGui)) {
+ debugC(7, kDebugImGui, "Window flags: ");
+ for (auto it : windows) {
+ debug("%s: %s", it.name, *it.flag ? "open" : "closed");
+ }
+ }
+
+ json["Windows"] = new Common::JSONValue((long long int)openFlags);
// Window Settings
const char *windowSettings = ImGui::SaveIniSettingsToMemory();
@@ -56,7 +85,6 @@ void saveCurrentState() {
// Current Log
ImVector<char *> currentLog = _state->_logger->getItems();
Common::JSONArray log;
-
for (auto iter : currentLog) {
log.push_back(new Common::JSONValue(iter));
}
@@ -64,7 +92,7 @@ void saveCurrentState() {
// Save the JSON
Common::JSONValue save(json);
- debug("ImGui::Saved state: %s", save.stringify().c_str());
+ debugC(7, kDebugImGui, "ImGui::Saved state: %s", save.stringify().c_str());
Common::OutSaveFile *stream = g_engine->getSaveFileManager()->openForSaving(savedStateFileName);
@@ -80,47 +108,46 @@ void saveCurrentState() {
delete stream;
}
-long long int getWindowFlags() {
- long long int openFlags = 0;
- openFlags += (_state->_w.archive) ? 1 : 0;
- openFlags += (_state->_w.bpList) ? 1 << 1 : 0;
- openFlags += (_state->_w.cast) ? 1 << 2 : 0;
- openFlags += (_state->_w.channels) ? 1 << 3 : 0;
- openFlags += (_state->_w.controlPanel) ? 1 << 4 : 0;
- openFlags += (_state->_w.executionContext) ? 1 << 5 : 0;
- openFlags += (_state->_w.funcList) ? 1 << 6: 0;
- openFlags += (_state->_w.logger) ? 1 << 7 : 0;
- openFlags += (_state->_w.score) ? 1 << 8 : 0;
- openFlags += (_state->_w.settings) ? 1 << 9 : 0;
- openFlags += (_state->_w.vars) ? 1 << 10 : 0;
- openFlags += (_state->_w.watchedVars) ? 1 << 11 : 0;
-
- return openFlags;
-}
-
void loadSavedState() {
Common::InSaveFile *savedState = g_engine->getSaveFileManager()->openForLoading(savedStateFileName);
- if (!savedState) {
+ if (!savedState || savedState->size() == 0) {
debug("ImGui::loadSavedState(): Failed to open saved state file: %s", savedStateFileName.c_str());
return;
}
- char *data = (char *)malloc(savedState->size());
+ // ASAN throws an error if the data is exactly equal to savedState->size() in JSON::parse()
+ // Probably because JSON::parse() expects a NULL terminated data
+ char *data = (char *)malloc(savedState->size() + 1);
+ data[savedState->size()] = '\0';
savedState->read(data, savedState->size());
Common::JSONValue *saved = Common::JSON::parse(data);
if (!saved) {
debug("ImGui:: Bad JSON: Failed to parse the Saved state");
+ free(data);
return;
}
- debug("ImGui::loaded state: %s", saved->stringify(true).c_str());
+ debugC(7, kDebugImGui, "ImGui::loaded state: %s", saved->stringify(true).c_str());
// Load open/closed window flags
- long long int openFlags = saved->asObject()["Windows"]->asIntegerNumber();
- setWindowFlags(openFlags);
+ int64 openFlags = saved->asObject()["Windows"]->asIntegerNumber();
+ Common::Array<WindowFlag> windows = getWindowFlags();
+
+ uint index = 0;
+ for (WindowFlag it : windows) {
+ *it.flag = (openFlags & 1 << index) ? true : false;
+ index += 1;
+ }
+ _state->_w.archive = (openFlags & 1) ? true : false;
+ if (debugChannelSet(7, kDebugImGui)) {
+ debugC(7, kDebugImGui, "Window flags: ");
+ for (auto it : windows) {
+ debug("%s: %s", it.name, *it.flag ? "open" : "closed");
+ }
+ }
// Load window settings
const char *windowSettings = saved->asObject()["Window Settings"]->asString().c_str();
@@ -131,7 +158,7 @@ void loadSavedState() {
if (debugChannelSet(7, kDebugImGui)) {
debugC(7, kDebugImGui, "Loading log: \n");
- for (auto iter: log) {
+ for (auto iter : log) {
debugC(7, kDebugImGui, "%s", iter->asString().c_str());
}
}
@@ -142,21 +169,8 @@ void loadSavedState() {
}
free(data);
-}
-
-void setWindowFlags(long long int openFlags) {
- _state->_w.archive = (openFlags & 1) ? true : false;
- _state->_w.bpList = (openFlags & 1 << 1) ? true : false;
- _state->_w.cast = (openFlags & 1 << 2) ? true : false;
- _state->_w.channels = (openFlags & 1 << 3) ? true : false;
- _state->_w.controlPanel = (openFlags & 1 << 4) ? true : false;
- _state->_w.executionContext = (openFlags & 1 << 5) ? true : false;
- _state->_w.funcList = (openFlags & 1 << 6) ? true : false;
- _state->_w.logger = (openFlags & 1 << 7) ? true : false;
- _state->_w.score = (openFlags & 1 << 8) ? true : false;
- _state->_w.settings = (openFlags & 1 << 9) ? true : false;
- _state->_w.vars = (openFlags & 1 << 10) ? true : false;
- _state->_w.watchedVars = (openFlags & 1 << 11) ? true : false;
+ delete saved;
+ delete savedState;
}
} // End of namespace DT
Commit: ace600df99c170684c50159512574d99d3a9d888
https://github.com/scummvm/scummvm/commit/ace600df99c170684c50159512574d99d3a9d888
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Fix ID Pop up warning in Execution Context window
In case of multiple handlers in the same script, the corresponding
line numbers of each handler gave a warning for duplicate ID
e.g. 0th line of each handler had the same ID and hence gave a pop
up error
Fix that.
Changed paths:
engines/director/debugger/dt-script-d4.cpp
diff --git a/engines/director/debugger/dt-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index 3e6c8cd7bbf..c83672049f0 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -1143,7 +1143,8 @@ private:
color = _state->_colors._bp_color_enabled;
// Need to give a new id for each button
- ImGui::PushID(_renderLineID);
+ Common::String id = _script.handlerId + _renderLineID;
+ ImGui::PushID(id.c_str());
ImGui::InvisibleButton("Line", ImVec2(16, ImGui::GetFontSize()));
ImGui::PopID();
_renderLineID++;
@@ -1225,7 +1226,7 @@ private:
int _indent = 0;
bool _currentStatementDisplayed = false;
bool _isScriptInDebug = false;
- int _renderLineID = 0;
+ int _renderLineID = 1;
bool _scrollTo = false;
};
Commit: f2ae66e3388e9d6b198aa4d222e7d3a76c622392
https://github.com/scummvm/scummvm/commit/f2ae66e3388e9d6b198aa4d222e7d3a76c622392
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-18T12:31:27+02:00
Commit Message:
DIRECTOR: IMGUI: Show context info in the Execution Context window
Changed paths:
engines/director/debugger/dt-scripts.cpp
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index f3c746c3420..d73ca2b3878 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -327,6 +327,13 @@ void showExecutionContext() {
updateCurrentScript();
if (scriptData->_showScript) {
+ ImGuiScript ¤t = scriptData->_scripts[scriptData->_current];
+
+ // Get all the handlers from the script
+ ScriptContext* context = getScriptContext(current.id);
+ Common::String scriptInfo = Common::String::format("%d:%s type:%s", context->_id, context->getName().c_str(), scriptType2str(context->_scriptType));
+ ImGui::Text("%s", scriptInfo.c_str());
+
ImGui::BeginDisabled(scriptData->_scripts.empty() || scriptData->_current == 0);
if (ImGui::Button(ICON_MS_ARROW_BACK)) {
scriptData->_current--;
@@ -373,15 +380,11 @@ void showExecutionContext() {
ImGui::Separator();
childSize = ImGui::GetContentRegionAvail();
ImGui::BeginChild("##script", childSize);
- ImGuiScript ¤t = scriptData->_scripts[scriptData->_current];
-
- // Get all the handlers from the script
- ScriptContext* context = getScriptContext(current.id);
- Movie *movie = g_director->getCurrentMovie();
if (!context || context->_functionHandlers.size() == 1) {
renderScript(current, scriptData->_showByteCode, true);
} else {
+ Movie *movie = g_director->getCurrentMovie();
for (auto &functionHandler : context->_functionHandlers) {
ImGuiScript script = toImGuiScript(context->_scriptType, current.id, functionHandler._key);
script.byteOffsets = context->_functionByteOffsets[script.handlerId];
@@ -425,11 +428,17 @@ void showExecutionContext() {
ImGui::EndChild();
ImGui::SeparatorText("Scripts");
-
scriptData = &_state->_functions._windowScriptData.getOrCreateVal(window);
updateCurrentScript();
if (scriptData->_showScript) {
+ ImGuiScript ¤t = scriptData->_scripts[scriptData->_current];
+
+ // Get all the handlers from the script
+ ScriptContext* context = getScriptContext(current.id);
+ Common::String scriptInfo = Common::String::format("%d:%s type:%s", context->_id, context->getName().c_str(), scriptType2str(context->_scriptType));
+ ImGui::Text("%s", scriptInfo.c_str());
+
ImGui::BeginDisabled(scriptData->_scripts.empty() || scriptData->_current == 0);
if (ImGui::Button(ICON_MS_ARROW_BACK)) {
scriptData->_current--;
@@ -476,11 +485,7 @@ void showExecutionContext() {
ImGui::Separator();
childSize = ImGui::GetContentRegionAvail();
ImGui::BeginChild("##script", childSize);
- ImGuiScript ¤t = scriptData->_scripts[scriptData->_current];
- // Get all the handlers from the script
- ScriptContext* context = getScriptContext(current.id);
- context->_id;
if (!context || context->_functionHandlers.size() == 1) {
renderScript(current, scriptData->_showByteCode, true);
} else {
More information about the Scummvm-git-logs
mailing list