[Scummvm-git-logs] scummvm master -> b15e46d55c57b9c6016d842f5029110688c6b12a
sev-
noreply at scummvm.org
Fri Aug 22 08:13:47 UTC 2025
This automated email contains information about 8 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
97113794f1 DIRECTOR: IMGUI: Sanity check context before accessing
eb7f968c95 DIRECTOR: IMGUI: Fix Execution Context navigation
436df3644b DIRECTOR: IMGUI: Fix Pop-up error message in `renderCastScript` window
d861260e08 DIRECTOR: IMGUI: Show functions in a separate window when clicked on
797533505a DIRECTOR: IMGUI: Add Script Context wise list to the Functions Window
c9874e2dc4 DIRECTOR: IMGUI: Rework the Functions window all handler list
297b892513 DIRECTOR: IMGUI: Make handlers in call stack Selectable for display
b15e46d55c DIRECTOR: ImGui: Set `byteOffsets` when `Go To Function` called
Commit: 97113794f127770b87e39c33d0b30e8510d4ff44
https://github.com/scummvm/scummvm/commit/97113794f127770b87e39c33d0b30e8510d4ff44
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-22T10:13:40+02:00
Commit Message:
DIRECTOR: IMGUI: Sanity check context before accessing
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 d73ca2b3878..95131815ec2 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -331,8 +331,11 @@ void showExecutionContext() {
// 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());
+
+ if (context) {
+ 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)) {
@@ -436,8 +439,11 @@ void showExecutionContext() {
// 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());
+
+ if (context) {
+ 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)) {
Commit: eb7f968c953b723b94aedd44b8cb42d7135184f4
https://github.com/scummvm/scummvm/commit/eb7f968c953b723b94aedd44b8cb42d7135184f4
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-22T10:13:40+02:00
Commit Message:
DIRECTOR: IMGUI: Fix Execution Context navigation
Need to pass the current script by reference
Otherwise the `startOffsets` aren't stored
Also don't scroll to the current statement on every render
only scroll when the callstack level changes
Changed paths:
engines/director/debugger/dt-controlpanel.cpp
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-controlpanel.cpp b/engines/director/debugger/dt-controlpanel.cpp
index f2f1072578d..7be834a6823 100644
--- a/engines/director/debugger/dt-controlpanel.cpp
+++ b/engines/director/debugger/dt-controlpanel.cpp
@@ -69,6 +69,8 @@ static bool stepInShouldPauseDebugger() {
_state->_dbg._lastLinePC = line;
return true;
}
+
+ debug("I'm returning false for some reason, %d:%d", g_lingo->_state->callstack.size(), _state->_dbg._callstackSize);
return false;
}
@@ -76,13 +78,13 @@ static bool stepOutShouldPause() {
const uint32 line = getLineFromPC();
// we stop when:
- // - the statement line is different
// - OR we go up in the callstack
if (g_lingo->_state->callstack.size() < _state->_dbg._callstackSize) {
_state->_dbg._lastLinePC = line;
return true;
}
+ debug("I'm returning false for some reason, %d:%d", g_lingo->_state->callstack.size(), _state->_dbg._callstackSize);
return false;
}
diff --git a/engines/director/debugger/dt-script-d2.cpp b/engines/director/debugger/dt-script-d2.cpp
index 1d632b57d50..fe440f62234 100644
--- a/engines/director/debugger/dt-script-d2.cpp
+++ b/engines/director/debugger/dt-script-d2.cpp
@@ -831,7 +831,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 && _scrollTo) {
+ if (_state->_dbg._isScriptDirty && _scrollTo && g_lingo->_state->callstack.size() != _state->_dbg._callstackSize) {
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-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index c83672049f0..8bd1114e258 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -1179,7 +1179,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 && _scrollTo) {
+ if (_state->_dbg._isScriptDirty && _scrollTo && g_lingo->_state->callstack.size() != _state->_dbg._callstackSize) {
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 95131815ec2..c61d1fb7e7f 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -393,7 +393,8 @@ void showExecutionContext() {
script.byteOffsets = context->_functionByteOffsets[script.handlerId];
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = getHandlerName(functionHandler._value);
- renderScript(script, scriptData->_showByteCode, script == current);
+ // Need to pass by reference in case of the current handler
+ renderScript(current == script ? current : script, scriptData->_showByteCode, script == current);
ImGui::NewLine();
}
}
@@ -501,7 +502,8 @@ void showExecutionContext() {
Movie *movie = g_director->getCurrentMovie();
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = getHandlerName(functionHandler._value);
- renderScript(script, scriptData->_showByteCode, script == current);
+ // Need to pass by reference in case of the current handler
+ renderScript(current == script ? current : script, scriptData->_showByteCode, script == current);
ImGui::NewLine();
}
}
Commit: 436df3644b3d3fe6389dbae29334d6e8f12247e6
https://github.com/scummvm/scummvm/commit/436df3644b3d3fe6389dbae29334d6e8f12247e6
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-22T10:13:40+02:00
Commit Message:
DIRECTOR: IMGUI: Fix Pop-up error message in `renderCastScript` 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 c61d1fb7e7f..d653dee99e7 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -66,6 +66,7 @@ static void renderCastScript(Symbol &sym) {
if (bp)
color = _state->_colors._bp_color_enabled;
+ ImGui::PushID(pc);
ImGui::InvisibleButton("Line", ImVec2(16, ImGui::GetFontSize()));
if (ImGui::IsItemClicked(0)) {
if (bp) {
@@ -94,6 +95,7 @@ static void renderCastScript(Symbol &sym) {
ImGui::Text("[%5d] ", pc);
ImGui::SameLine();
ImGui::Text("%s", lingo->decodeInstruction(sym.u.defn, pc, &pc).c_str());
+ ImGui::PopID();
}
}
Commit: d861260e08292e509057e29ed1472006e1a970db
https://github.com/scummvm/scummvm/commit/d861260e08292e509057e29ed1472006e1a970db
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-22T10:13:40+02:00
Commit Message:
DIRECTOR: IMGUI: Show functions in a separate window when clicked on
Previously shown in Execution Context window
Also show all the handlers from the same script context
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 6c0b7350700..8a0cac6bcd8 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -534,6 +534,7 @@ void onImGuiRender() {
showScriptCasts();
showExecutionContext();
+ showHandlers();
showControlPanel();
showVars();
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index bf31d94ef50..630eab19164 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -166,6 +166,7 @@ typedef struct ImGuiState {
bool _wasHidden = false;
Common::List<CastMemberID> _scriptCasts;
+ Common::List<ImGuiScript> _openHandlers;
Common::HashMap<Common::String, bool, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _variables;
int _prevFrame = -1;
struct {
@@ -229,6 +230,7 @@ void renderScriptAST(ImGuiScript &script, bool showByteCode, bool scrollTo);
void showFuncList();
void showScriptCasts();
void showExecutionContext();
+void showHandlers();
// dt-save-state.cpp
void saveCurrentState();
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index d653dee99e7..155d98bbca6 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -159,6 +159,58 @@ void showScriptCasts() {
}
}
+static void addToOpenHandlers(ImGuiScript handler) {
+ _state->_openHandlers.remove(handler);
+ _state->_openHandlers.push_back(handler);
+}
+
+static bool showHandler(ImGuiScript handler) {
+ ScriptContext *ctx = getScriptContext(handler.id);
+ Common::String wName(ctx->asString());
+
+ ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(480, 540), ImGuiCond_FirstUseEver);
+
+ bool closed = true;
+
+ if (ImGui::Begin(wName.c_str(), &closed)) {
+ if (!ctx || ctx->_functionHandlers.size() <= 1) {
+ renderScript(handler, false, true);
+ } else {
+ for (auto &functionHandler : ctx->_functionHandlers) {
+ ImGuiScript script = toImGuiScript(ctx->_scriptType, handler.id, functionHandler._key);
+ script.byteOffsets = ctx->_functionByteOffsets[script.handlerId];
+ _state->_dbg._goToDefinition = true;
+ renderScript(script, false, script == handler);
+ ImGui::NewLine();
+ }
+ }
+ }
+ ImGui::End();
+
+ if (!closed)
+ return false;
+
+ return true;
+}
+
+/**
+ * Display all open handlers
+ */
+void showHandlers() {
+ if (_state->_openHandlers.empty()) {
+ return;
+ }
+
+ for (Common::List<ImGuiScript>::iterator handler = _state->_openHandlers.begin(); handler != _state->_openHandlers.end();) {
+ if (!showHandler(*handler)) {
+ handler = _state->_openHandlers.erase(handler);
+ } else {
+ handler++;
+ }
+ }
+}
+
static void updateCurrentScript() {
if ((g_lingo->_exec._state != kPause) || !_state->_dbg._isScriptDirty)
return;
@@ -234,7 +286,8 @@ void showFuncList() {
script.byteOffsets = scriptContext._value->_functionByteOffsets[script.handlerId];
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = getHandlerName(functionHandler._value);
- setScriptToDisplay(script);
+ addToOpenHandlers(script);
+ _state->_dbg._goToDefinition = true;
}
ImGui::TableNextColumn();
ImGui::Text("%s", movie->getArchive()->getPathName().toString().c_str());
@@ -272,7 +325,8 @@ void showFuncList() {
script.byteOffsets = scriptContext._value->_functionByteOffsets[script.handlerId];
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = getHandlerName(functionHandler._value);
- setScriptToDisplay(script);
+ addToOpenHandlers(script);
+ _state->_dbg._goToDefinition = true;
}
ImGui::TableNextColumn();
ImGui::Text("%s", movie->getArchive()->getPathName().toString().c_str());
Commit: 797533505ae26df4b2fc0a8d0fa0851eb7f8b308
https://github.com/scummvm/scummvm/commit/797533505ae26df4b2fc0a8d0fa0851eb7f8b308
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-22T10:13:40+02:00
Commit Message:
DIRECTOR: IMGUI: Add Script Context wise list to the Functions Window
This list will show all the handlers in a single 'Lscr' context
under one tree node
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 630eab19164..39d4bbb3991 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -119,6 +119,7 @@ typedef struct ImGuiState {
} _cast;
struct {
ImGuiTextFilter _nameFilter;
+ bool _showScriptContexts;
Common::HashMap<Window *, ScriptData> _windowScriptData;
} _functions;
@@ -167,6 +168,8 @@ typedef struct ImGuiState {
Common::List<CastMemberID> _scriptCasts;
Common::List<ImGuiScript> _openHandlers;
+ bool _showCompleteScript = true;
+
Common::HashMap<Common::String, bool, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _variables;
int _prevFrame = -1;
struct {
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index 155d98bbca6..e53eef72784 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -166,7 +166,12 @@ static void addToOpenHandlers(ImGuiScript handler) {
static bool showHandler(ImGuiScript handler) {
ScriptContext *ctx = getScriptContext(handler.id);
- Common::String wName(ctx->asString());
+ Common::String wName;
+ if (ctx) {
+ wName = Common::String(ctx->asString());
+ } else {
+ wName = Common::String();
+ }
ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(480, 540), ImGuiCond_FirstUseEver);
@@ -174,13 +179,23 @@ static bool showHandler(ImGuiScript handler) {
bool closed = true;
if (ImGui::Begin(wName.c_str(), &closed)) {
- if (!ctx || ctx->_functionHandlers.size() <= 1) {
+ ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &_state->_showCompleteScript, true); // Lingo
+ ImGui::SetItemTooltip("Show Handler");
+
+ ImGui::SameLine();
+ ImGuiEx::toggleButton(ICON_MS_STACKS, &_state->_showCompleteScript); // Bytecode
+ ImGui::SetItemTooltip("Show Script Context");
+
+ if (!ctx || ctx->_functionHandlers.size() <= 1 || !_state->_showCompleteScript) {
renderScript(handler, false, true);
} else {
for (auto &functionHandler : ctx->_functionHandlers) {
ImGuiScript script = toImGuiScript(ctx->_scriptType, handler.id, functionHandler._key);
script.byteOffsets = ctx->_functionByteOffsets[script.handlerId];
- _state->_dbg._goToDefinition = true;
+
+ if (script == handler) {
+ _state->_dbg._goToDefinition = true;
+ }
renderScript(script, false, script == handler);
ImGui::NewLine();
}
@@ -247,98 +262,156 @@ void showFuncList() {
return;
ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver);
- ImGui::SetNextWindowSize(ImVec2(480, 240), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(480, 640), ImGuiCond_FirstUseEver);
if (ImGui::Begin("Functions", &_state->_w.funcList)) {
_state->_functions._nameFilter.Draw();
ImGui::Separator();
+
+ // Show a script context wise handlers
+ ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &_state->_functions._showScriptContexts);
+ ImGui::SetItemTooltip("Script Contexts");
+
+ ImGui::SameLine();
+ // Show a list of all handlers
+ ImGuiEx::toggleButton(ICON_MS_STACKS, &_state->_functions._showScriptContexts, true);
+ ImGui::SetItemTooltip("All Handlers");
+
const ImVec2 childSize = ImGui::GetContentRegionAvail();
ImGui::BeginChild("##functions", ImVec2(childSize.x, childSize.y));
- if (ImGui::BeginTable("Functions", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
- ImGui::TableSetupColumn("Function", 0, 240.f);
- ImGui::TableSetupColumn("Movie", 0, 60.f);
- ImGui::TableSetupColumn("Cast", 0, 60.f);
- ImGui::TableSetupColumn("Type", 0, 80.f);
- ImGui::TableHeadersRow();
-
- Movie *movie = g_director->getCurrentMovie();
- for (auto &cast : *movie->getCasts()) {
- for (int i = 0; i <= kMaxScriptType; i++) {
- if (cast._value->_lingoArchive->scriptContexts[i].empty())
- continue;
- Common::String scriptType(scriptType2str((ScriptType)i));
- for (auto &scriptContext : cast._value->_lingoArchive->scriptContexts[i]) {
- Common::String name = Common::String::format("%d", scriptContext._key);
- CastMemberInfo *cmi = cast._value->getCastMemberInfo(scriptContext._key);
- if (cmi && !cmi->name.empty()) {
- name += Common::String::format(" \"%s\"", cmi->name.c_str());
+ Movie *movie = g_director->getCurrentMovie();
+ if (_state->_functions._showScriptContexts) {
+ if (ImGui::BeginTable("Functions", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
+ ImGui::TableSetupColumn("Function", ImGuiTableColumnFlags_WidthStretch, 240.f);
+ ImGui::TableSetupColumn("Movie", 0, 60.f);
+ ImGui::TableSetupColumn("Cast", 0, 60.f);
+ ImGui::TableSetupColumn("Type", 0, 80.f);
+ ImGui::TableHeadersRow();
+
+ for (auto &cast : *movie->getCasts()) {
+ for (int i = 0; i <= kMaxScriptType; i++) {
+ if (cast._value->_lingoArchive->scriptContexts[i].empty())
+ continue;
+ Common::String scriptType(scriptType2str((ScriptType)i));
+ for (auto &scriptContext : cast._value->_lingoArchive->scriptContexts[i]) {
+ Common::String name = Common::String::format("%d", scriptContext._key);
+ CastMemberInfo *cmi = cast._value->getCastMemberInfo(scriptContext._key);
+ if (cmi && !cmi->name.empty()) {
+ name += Common::String::format(" \"%s\"", cmi->name.c_str());
+ }
+ for (auto &functionHandler : scriptContext._value->_functionHandlers) {
+ Common::String function = Common::String::format("%s: %s", name.c_str(), g_lingo->formatFunctionName(functionHandler._value).c_str());
+ if (!_state->_functions._nameFilter.PassFilter(function.c_str()))
+ continue;
+
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ if (ImGui::Selectable(function.c_str())) {
+ CastMemberID memberID(scriptContext._key, cast._key);
+ ImGuiScript script = toImGuiScript(scriptContext._value->_scriptType, memberID, functionHandler._key);
+ script.byteOffsets = scriptContext._value->_functionByteOffsets[script.handlerId];
+ script.moviePath = movie->getArchive()->getPathName().toString();
+ script.handlerName = getHandlerName(functionHandler._value);
+ addToOpenHandlers(script);
+ }
+ ImGui::TableNextColumn();
+ ImGui::Text("%s", movie->getArchive()->getPathName().toString().c_str());
+ ImGui::TableNextColumn();
+ ImGui::Text("%d", cast._key);
+ ImGui::TableNextColumn();
+ ImGui::Text("%s", scriptType.c_str());
+ }
}
- for (auto &functionHandler : scriptContext._value->_functionHandlers) {
- Common::String function = Common::String::format("%s: %s", name.c_str(), g_lingo->formatFunctionName(functionHandler._value).c_str());
- if (!_state->_functions._nameFilter.PassFilter(function.c_str()))
- continue;
-
- ImGui::TableNextRow();
- ImGui::TableNextColumn();
- if (ImGui::Selectable(function.c_str())) {
- CastMemberID memberID(scriptContext._key, cast._key);
- ImGuiScript script = toImGuiScript(scriptContext._value->_scriptType, memberID, functionHandler._key);
- script.byteOffsets = scriptContext._value->_functionByteOffsets[script.handlerId];
- script.moviePath = movie->getArchive()->getPathName().toString();
- script.handlerName = getHandlerName(functionHandler._value);
- addToOpenHandlers(script);
- _state->_dbg._goToDefinition = true;
+ }
+ }
+
+ Cast *sharedCast = movie->getSharedCast();
+ if (sharedCast && sharedCast->_lingoArchive) {
+ for (int i = 0; i <= kMaxScriptType; i++) {
+ if (sharedCast->_lingoArchive->scriptContexts[i].empty())
+ continue;
+ Common::String scriptType(scriptType2str((ScriptType)i));
+ for (auto &scriptContext : sharedCast->_lingoArchive->scriptContexts[i]) {
+ Common::String name = Common::String::format("%d", scriptContext._key);
+ CastMemberInfo *cmi = sharedCast->getCastMemberInfo(scriptContext._key);
+ if (cmi && !cmi->name.empty()) {
+ name += Common::String::format(" \"%s\"", cmi->name.c_str());
+ }
+ for (auto &functionHandler : scriptContext._value->_functionHandlers) {
+ Common::String function = Common::String::format("%s: %s", name.c_str(), g_lingo->formatFunctionName(functionHandler._value).c_str());
+ if (!_state->_functions._nameFilter.PassFilter(function.c_str()))
+ continue;
+
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ if (ImGui::Selectable(function.c_str())) {
+ CastMemberID memberID(scriptContext._key, SHARED_CAST_LIB);
+ ImGuiScript script = toImGuiScript(scriptContext._value->_scriptType, memberID, functionHandler._key);
+ script.byteOffsets = scriptContext._value->_functionByteOffsets[script.handlerId];
+ script.moviePath = movie->getArchive()->getPathName().toString();
+ script.handlerName = getHandlerName(functionHandler._value);
+ addToOpenHandlers(script);
+ _state->_dbg._goToDefinition = true;
+ }
+ ImGui::TableNextColumn();
+ ImGui::Text("%s", movie->getArchive()->getPathName().toString().c_str());
+ ImGui::TableNextColumn();
+ ImGui::Text("SHARED");
+ ImGui::TableNextColumn();
+ ImGui::Text("%s", scriptType.c_str());
}
- ImGui::TableNextColumn();
- ImGui::Text("%s", movie->getArchive()->getPathName().toString().c_str());
- ImGui::TableNextColumn();
- ImGui::Text("%d", cast._key);
- ImGui::TableNextColumn();
- ImGui::Text("%s", scriptType.c_str());
}
}
}
+ ImGui::EndTable();
}
+ } else {
+ for (auto cast : *movie->getCasts()) {
+ Common::String castName = Common::String::format("%d", cast._key);
+ if (cast._value->getCastName().size()) {
+ castName += Common::String::format(": %s ", cast._value->getCastName().c_str());
+ }
- Cast *sharedCast = movie->getSharedCast();
- if (sharedCast && sharedCast->_lingoArchive) {
- for (int i = 0; i <= kMaxScriptType; i++) {
- if (sharedCast->_lingoArchive->scriptContexts[i].empty())
- continue;
- Common::String scriptType(scriptType2str((ScriptType)i));
- for (auto &scriptContext : sharedCast->_lingoArchive->scriptContexts[i]) {
- Common::String name = Common::String::format("%d", scriptContext._key);
- CastMemberInfo *cmi = sharedCast->getCastMemberInfo(scriptContext._key);
- if (cmi && !cmi->name.empty()) {
- name += Common::String::format(" \"%s\"", cmi->name.c_str());
+ if (ImGui::TreeNode(castName.c_str())) {
+ for (auto context : cast._value->_lingoArchive->lctxContexts) {
+ CastMemberInfo *cmi = cast._value->getCastMemberInfo(context._value->_id);
+ Common::String contextName = Common::String::format("%d", context._value->_id);
+ if (cmi && cmi->name.size()) {
+ contextName += Common::String::format(": %s", cmi->name.c_str());
}
- for (auto &functionHandler : scriptContext._value->_functionHandlers) {
- Common::String function = Common::String::format("%s: %s", name.c_str(), g_lingo->formatFunctionName(functionHandler._value).c_str());
- if (!_state->_functions._nameFilter.PassFilter(function.c_str()))
- continue;
-
- ImGui::TableNextRow();
- ImGui::TableNextColumn();
- if (ImGui::Selectable(function.c_str())) {
- CastMemberID memberID(scriptContext._key, SHARED_CAST_LIB);
- ImGuiScript script = toImGuiScript(scriptContext._value->_scriptType, memberID, functionHandler._key);
- script.byteOffsets = scriptContext._value->_functionByteOffsets[script.handlerId];
- script.moviePath = movie->getArchive()->getPathName().toString();
- script.handlerName = getHandlerName(functionHandler._value);
- addToOpenHandlers(script);
- _state->_dbg._goToDefinition = true;
+
+ contextName += Common::String::format(": %s", scriptType2str(context._value->_scriptType));
+ if (!context._value || !context._value->_functionHandlers.size() || !_state->_functions._nameFilter.PassFilter(contextName.c_str())) {
+ continue;
+ }
+
+ ImGui::PushID(context._key);
+ if (ImGui::TreeNode(contextName.c_str())) {
+ if (ImGui::BeginTable("Functions", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
+ ImGui::TableSetupColumn("Function", ImGuiTableColumnFlags_WidthStretch, 240.f);
+ for (auto &functionHandler : context._value->_functionHandlers) {
+ Common::String function = Common::String::format("%s", g_lingo->formatFunctionName(functionHandler._value).c_str());
+
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ if (ImGui::Selectable(function.c_str())) {
+ CastMemberID memberID(cast._value->getCastIdByScriptId(context._key), cast._key);
+ ImGuiScript script = toImGuiScript(context._value->_scriptType, memberID, functionHandler._key);
+ script.byteOffsets = context._value->_functionByteOffsets[script.handlerId];
+ script.moviePath = movie->getArchive()->getPathName().toString();
+ script.handlerName = g_lingo->formatFunctionName(functionHandler._value);
+ addToOpenHandlers(script);
+ }
+ }
+ ImGui::EndTable();
}
- ImGui::TableNextColumn();
- ImGui::Text("%s", movie->getArchive()->getPathName().toString().c_str());
- ImGui::TableNextColumn();
- ImGui::Text("SHARED");
- ImGui::TableNextColumn();
- ImGui::Text("%s", scriptType.c_str());
+ ImGui::TreePop();
}
+ ImGui::PopID();
}
+ ImGui::TreePop();
}
}
- ImGui::EndTable();
}
ImGui::EndChild();
}
Commit: c9874e2dc4b2a127225bfd0d0303fc17610cfa16
https://github.com/scummvm/scummvm/commit/c9874e2dc4b2a127225bfd0d0303fc17610cfa16
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-22T10:13:40+02:00
Commit Message:
DIRECTOR: IMGUI: Rework the Functions window all handler list
Change the way the function names are shown
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 39d4bbb3991..f9c4e0474ce 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -119,7 +119,7 @@ typedef struct ImGuiState {
} _cast;
struct {
ImGuiTextFilter _nameFilter;
- bool _showScriptContexts;
+ bool _showScriptContexts = true;
Common::HashMap<Window *, ScriptData> _windowScriptData;
} _functions;
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index e53eef72784..6c336ac6633 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -281,11 +281,104 @@ void showFuncList() {
Movie *movie = g_director->getCurrentMovie();
if (_state->_functions._showScriptContexts) {
- if (ImGui::BeginTable("Functions", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
- ImGui::TableSetupColumn("Function", ImGuiTableColumnFlags_WidthStretch, 240.f);
- ImGui::TableSetupColumn("Movie", 0, 60.f);
- ImGui::TableSetupColumn("Cast", 0, 60.f);
- ImGui::TableSetupColumn("Type", 0, 80.f);
+ for (auto cast : *movie->getCasts()) {
+ Common::String castName = Common::String::format("%d", cast._key);
+ if (cast._value->getCastName().size()) {
+ castName += Common::String::format(": %s ", cast._value->getCastName().c_str());
+ }
+
+ if (ImGui::TreeNodeEx(castName.c_str(), ImGuiTreeNodeFlags_DefaultOpen)) {
+ for (auto context : cast._value->_lingoArchive->lctxContexts) {
+ CastMemberInfo *cmi = cast._value->getCastMemberInfo(context._value->_id);
+ Common::String contextName = Common::String::format("%d", context._value->_id);
+ if (cmi && cmi->name.size()) {
+ contextName += Common::String::format(": %s", cmi->name.c_str());
+ }
+
+ contextName += Common::String::format(": %s", scriptType2str(context._value->_scriptType));
+ if (!context._value || !context._value->_functionHandlers.size() || !_state->_functions._nameFilter.PassFilter(contextName.c_str())) {
+ continue;
+ }
+
+ ImGui::PushID(context._key);
+ if (ImGui::TreeNode(contextName.c_str())) {
+ if (ImGui::BeginTable("Functions", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
+ ImGui::TableSetupColumn("Function", ImGuiTableColumnFlags_WidthStretch, 240.f);
+ for (auto &functionHandler : context._value->_functionHandlers) {
+ Common::String function = Common::String::format("%s", g_lingo->formatFunctionName(functionHandler._value).c_str());
+
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ if (ImGui::Selectable(function.c_str())) {
+ CastMemberID memberID(cast._value->getCastIdByScriptId(context._key), cast._key);
+ ImGuiScript script = toImGuiScript(context._value->_scriptType, memberID, functionHandler._key);
+ script.byteOffsets = context._value->_functionByteOffsets[script.handlerId];
+ script.moviePath = movie->getArchive()->getPathName().toString();
+ script.handlerName = g_lingo->formatFunctionName(functionHandler._value);
+ addToOpenHandlers(script);
+ }
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+ ImGui::PopID();
+ }
+ ImGui::TreePop();
+ }
+ }
+
+ Cast *sharedCast = movie->getSharedCast();
+ if (sharedCast && sharedCast->_lingoArchive) {
+ Common::String castName = Common::String::format("%s", "SHARED");
+ if (sharedCast->getCastName().size()) {
+ castName += Common::String::format(": %s ", sharedCast->getCastName().c_str());
+ }
+
+ if (ImGui::TreeNode(castName.c_str())) {
+ for (auto context : sharedCast->_lingoArchive->lctxContexts) {
+ CastMemberInfo *cmi = sharedCast->getCastMemberInfo(context._value->_id);
+ Common::String contextName = Common::String::format("%d", context._value->_id);
+ if (cmi && cmi->name.size()) {
+ contextName += Common::String::format(": %s", cmi->name.c_str());
+ }
+
+ contextName += Common::String::format(": %s", scriptType2str(context._value->_scriptType));
+ if (!context._value || !context._value->_functionHandlers.size() || !_state->_functions._nameFilter.PassFilter(contextName.c_str())) {
+ continue;
+ }
+
+ ImGui::PushID(context._key);
+ if (ImGui::TreeNode(contextName.c_str())) {
+ if (ImGui::BeginTable("Functions", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
+ ImGui::TableSetupColumn("Function", ImGuiTableColumnFlags_WidthStretch, 240.f);
+ for (auto &functionHandler : context._value->_functionHandlers) {
+ Common::String function = Common::String::format("%s", g_lingo->formatFunctionName(functionHandler._value).c_str());
+
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ if (ImGui::Selectable(function.c_str())) {
+ CastMemberID memberID(sharedCast->getCastIdByScriptId(context._key), SHARED_CAST_LIB);
+ ImGuiScript script = toImGuiScript(context._value->_scriptType, memberID, functionHandler._key);
+ script.byteOffsets = context._value->_functionByteOffsets[script.handlerId];
+ script.moviePath = movie->getArchive()->getPathName().toString();
+ script.handlerName = g_lingo->formatFunctionName(functionHandler._value);
+ addToOpenHandlers(script);
+ }
+ }
+ ImGui::EndTable();
+ }
+ ImGui::TreePop();
+ }
+ ImGui::PopID();
+ }
+ ImGui::TreePop();
+ }
+ }
+ } else {
+ if (ImGui::BeginTable("Functions", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
+ ImGui::TableSetupColumn("Function", 0, 240.f);
+ ImGui::TableSetupColumn("Cast Name", ImGuiTableColumnFlags_WidthStretch, 240.f);
ImGui::TableHeadersRow();
for (auto &cast : *movie->getCasts()) {
@@ -296,11 +389,13 @@ void showFuncList() {
for (auto &scriptContext : cast._value->_lingoArchive->scriptContexts[i]) {
Common::String name = Common::String::format("%d", scriptContext._key);
CastMemberInfo *cmi = cast._value->getCastMemberInfo(scriptContext._key);
- if (cmi && !cmi->name.empty()) {
- name += Common::String::format(" \"%s\"", cmi->name.c_str());
- }
+ CastMember *castMember = cast._value->getCastMember(scriptContext._key);
+
for (auto &functionHandler : scriptContext._value->_functionHandlers) {
- Common::String function = Common::String::format("%s: %s", name.c_str(), g_lingo->formatFunctionName(functionHandler._value).c_str());
+ Common::String function = Common::String::format("%s-%s (%d lib %d)",
+ castMember ? castType2str(castMember->_type) : "any", g_lingo->formatFunctionName(functionHandler._value).c_str(),
+ scriptContext._key, cast._key
+ );
if (!_state->_functions._nameFilter.PassFilter(function.c_str()))
continue;
@@ -314,12 +409,9 @@ void showFuncList() {
script.handlerName = getHandlerName(functionHandler._value);
addToOpenHandlers(script);
}
+
ImGui::TableNextColumn();
- ImGui::Text("%s", movie->getArchive()->getPathName().toString().c_str());
- ImGui::TableNextColumn();
- ImGui::Text("%d", cast._key);
- ImGui::TableNextColumn();
- ImGui::Text("%s", scriptType.c_str());
+ ImGui::Text("%s", (cmi && cmi->name.size()) ? cmi->name.c_str() : "unnamed");
}
}
}
@@ -334,11 +426,13 @@ void showFuncList() {
for (auto &scriptContext : sharedCast->_lingoArchive->scriptContexts[i]) {
Common::String name = Common::String::format("%d", scriptContext._key);
CastMemberInfo *cmi = sharedCast->getCastMemberInfo(scriptContext._key);
- if (cmi && !cmi->name.empty()) {
- name += Common::String::format(" \"%s\"", cmi->name.c_str());
- }
+ CastMember *castMember = sharedCast->getCastMember(scriptContext._key);
+
for (auto &functionHandler : scriptContext._value->_functionHandlers) {
- Common::String function = Common::String::format("%s: %s", name.c_str(), g_lingo->formatFunctionName(functionHandler._value).c_str());
+ Common::String function = Common::String::format("%s-%s (%d lib %d)",
+ castMember ? castType2str(castMember->_type) : "any", g_lingo->formatFunctionName(functionHandler._value).c_str(),
+ scriptContext._key, SHARED_CAST_LIB
+ );
if (!_state->_functions._nameFilter.PassFilter(function.c_str()))
continue;
@@ -351,67 +445,16 @@ void showFuncList() {
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = getHandlerName(functionHandler._value);
addToOpenHandlers(script);
- _state->_dbg._goToDefinition = true;
}
+
ImGui::TableNextColumn();
- ImGui::Text("%s", movie->getArchive()->getPathName().toString().c_str());
- ImGui::TableNextColumn();
- ImGui::Text("SHARED");
- ImGui::TableNextColumn();
- ImGui::Text("%s", scriptType.c_str());
+ ImGui::Text("%s", (cmi && cmi->name.size()) ? cmi->name.c_str() : "unnamed");
}
}
}
}
ImGui::EndTable();
}
- } else {
- for (auto cast : *movie->getCasts()) {
- Common::String castName = Common::String::format("%d", cast._key);
- if (cast._value->getCastName().size()) {
- castName += Common::String::format(": %s ", cast._value->getCastName().c_str());
- }
-
- if (ImGui::TreeNode(castName.c_str())) {
- for (auto context : cast._value->_lingoArchive->lctxContexts) {
- CastMemberInfo *cmi = cast._value->getCastMemberInfo(context._value->_id);
- Common::String contextName = Common::String::format("%d", context._value->_id);
- if (cmi && cmi->name.size()) {
- contextName += Common::String::format(": %s", cmi->name.c_str());
- }
-
- contextName += Common::String::format(": %s", scriptType2str(context._value->_scriptType));
- if (!context._value || !context._value->_functionHandlers.size() || !_state->_functions._nameFilter.PassFilter(contextName.c_str())) {
- continue;
- }
-
- ImGui::PushID(context._key);
- if (ImGui::TreeNode(contextName.c_str())) {
- if (ImGui::BeginTable("Functions", 1, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
- ImGui::TableSetupColumn("Function", ImGuiTableColumnFlags_WidthStretch, 240.f);
- for (auto &functionHandler : context._value->_functionHandlers) {
- Common::String function = Common::String::format("%s", g_lingo->formatFunctionName(functionHandler._value).c_str());
-
- ImGui::TableNextRow();
- ImGui::TableNextColumn();
- if (ImGui::Selectable(function.c_str())) {
- CastMemberID memberID(cast._value->getCastIdByScriptId(context._key), cast._key);
- ImGuiScript script = toImGuiScript(context._value->_scriptType, memberID, functionHandler._key);
- script.byteOffsets = context._value->_functionByteOffsets[script.handlerId];
- script.moviePath = movie->getArchive()->getPathName().toString();
- script.handlerName = g_lingo->formatFunctionName(functionHandler._value);
- addToOpenHandlers(script);
- }
- }
- ImGui::EndTable();
- }
- ImGui::TreePop();
- }
- ImGui::PopID();
- }
- ImGui::TreePop();
- }
- }
}
ImGui::EndChild();
}
Commit: 297b892513f35d03b1559f52b26f108a0166144f
https://github.com/scummvm/scummvm/commit/297b892513f35d03b1559f52b26f108a0166144f
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-22T10:13:40+02:00
Commit Message:
DIRECTOR: IMGUI: Make handlers in call stack Selectable for display
Pressing on it will display the script down in the Scripts window
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 f9c4e0474ce..9540619c234 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -63,6 +63,7 @@ typedef struct ImGuiScript {
Common::String handlerName;
Common::String moviePath;
Common::Array<uint32> byteOffsets;
+ uint pc = 0;
bool isMethod = false;
bool isGenericEvent = false;
diff --git a/engines/director/debugger/dt-script-d2.cpp b/engines/director/debugger/dt-script-d2.cpp
index fe440f62234..e7d5cf276d3 100644
--- a/engines/director/debugger/dt-script-d2.cpp
+++ b/engines/director/debugger/dt-script-d2.cpp
@@ -39,6 +39,7 @@ private:
bool _isScriptInDebug = false;
bool _currentStatementDisplayed = false;
bool _scrollTo = false;
+ bool _scrollDone = true;
public:
explicit RenderOldScriptVisitor(ImGuiScript &script, bool scrollTo) : _script(script), _scrollTo(scrollTo) {
@@ -779,7 +780,12 @@ private:
bool showCurrentStatement = false;
_script.startOffsets.push_back(pc);
- if (_isScriptInDebug && g_lingo->_exec._state == kPause) {
+ if (_script.pc != 0 && pc >= _script.pc) {
+ if (!_currentStatementDisplayed) {
+ showCurrentStatement = true;
+ _currentStatementDisplayed = true;
+ }
+ } else if (_isScriptInDebug && g_lingo->_exec._state == kPause) {
// check current statement
if (!_currentStatementDisplayed) {
if (g_lingo->_state->pc <= pc) {
@@ -831,8 +837,9 @@ 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 && _scrollTo && g_lingo->_state->callstack.size() != _state->_dbg._callstackSize) {
+ if (!_scrollDone && _scrollTo && g_lingo->_state->callstack.size() != _state->_dbg._callstackSize) {
ImGui::SetScrollHereY(0.5f);
+ _scrollDone = true;
}
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-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index 8bd1114e258..6faea7005ae 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -1122,7 +1122,12 @@ private:
uint pc = _script.byteOffsets[p];
_script.startOffsets.push_back(pc);
- if (_isScriptInDebug && g_lingo->_exec._state == kPause) {
+ if (_script.pc != 0 && pc >= _script.pc) {
+ if (!_currentStatementDisplayed) {
+ showCurrentStatement = true;
+ _currentStatementDisplayed = true;
+ }
+ } else if (_isScriptInDebug && g_lingo->_exec._state == kPause) {
// check current statement
if (!_currentStatementDisplayed) {
if (g_lingo->_state->pc <= pc) {
@@ -1179,8 +1184,9 @@ 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 && _scrollTo && g_lingo->_state->callstack.size() != _state->_dbg._callstackSize) {
+ if (!_scrollDone && _scrollTo && g_lingo->_state->callstack.size() != _state->_dbg._callstackSize) {
ImGui::SetScrollHereY(0.5f);
+ _scrollDone = true;
}
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);
}
@@ -1228,6 +1234,7 @@ private:
bool _isScriptInDebug = false;
int _renderLineID = 1;
bool _scrollTo = false;
+ bool _scrollDone = false;
};
void renderScriptAST(ImGuiScript &script, bool showByteCode, bool scrollTo) {
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index 6c336ac6633..3a6ef326e59 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -111,6 +111,54 @@ static void renderScript(ImGuiScript &script, bool showByteCode, bool scrollTo)
renderScriptAST(script, showByteCode, scrollTo);
}
+static void renderCallStack(uint pc) {
+ Common::Array<CFrame *> callstack = g_lingo->_state->callstack;
+ if (callstack.size() == 0) {
+ ImGui::Text("End of execution\n");
+ return;
+ }
+
+ ImGui::Text("Call stack:\n");
+ for (int i = 0; i < (int)callstack.size(); i++) {
+ Common::String stackFrame;
+ CFrame *frame = callstack[callstack.size() - i - 1];
+ uint framePc = pc;
+ if (i > 0)
+ framePc = callstack[callstack.size() - i]->retPC;
+
+ if (frame->sp.type != VOIDSYM) {
+ stackFrame = Common::String::format("#%d ", i);
+ if (frame->sp.ctx && frame->sp.ctx->_id) {
+ stackFrame += Common::String::format("%d:", frame->sp.ctx->_id);
+ }
+ if (frame->sp.ctx && frame->sp.ctx->isFactory()) {
+ stackFrame += Common::String::format("%s:", frame->sp.ctx->getName().c_str());
+ }
+ stackFrame += Common::String::format("%s at [%5d]\n",
+ frame->sp.name->c_str(),
+ framePc
+ );
+ } else {
+ stackFrame = Common::String::format("#%d [unknown] at [%5d]\n", i,
+ framePc
+ );
+ }
+
+ if (ImGui::Selectable(stackFrame.c_str())) {
+ Director::Movie *movie = g_director->getCurrentMovie();
+ CFrame *head = callstack[callstack.size() - i - 1];
+ ScriptContext *scriptContext = head->sp.ctx;
+ int castLibID = movie->getCast()->_castLibID;
+ ImGuiScript script = toImGuiScript(scriptContext->_scriptType, CastMemberID(head->sp.ctx->_id, castLibID), *head->sp.name);
+ script.byteOffsets = head->sp.ctx->_functionByteOffsets[script.handlerId];
+ script.moviePath = movie->getArchive()->getPathName().toString();
+ script.handlerName = head->sp.ctx->_id ? Common::String::format("%d:%s", head->sp.ctx->_id, script.handlerId.c_str()) : script.handlerId;
+ script.pc = framePc;
+ setScriptToDisplay(script);
+ }
+ }
+}
+
static bool showScriptCast(CastMemberID &id) {
Common::String wName("Script ");
wName += id.asString();
@@ -230,7 +278,6 @@ static void updateCurrentScript() {
if ((g_lingo->_exec._state != kPause) || !_state->_dbg._isScriptDirty)
return;
-
Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
if (callstack.empty())
return;
@@ -244,6 +291,7 @@ static void updateCurrentScript() {
script.byteOffsets = scriptContext->_functionByteOffsets[script.handlerId];
script.moviePath = movie->getArchive()->getPathName().toString();
script.handlerName = head->sp.ctx->_id ? Common::String::format("%d:%s", head->sp.ctx->_id, script.handlerId.c_str()) : script.handlerId;
+ script.pc = 0;
setScriptToDisplay(script);
}
@@ -490,7 +538,7 @@ void showExecutionContext() {
ImVec2 childSize = ImGui::GetContentRegionAvail();
childSize.y /= 3;
ImGui::BeginChild("##backtrace", childSize);
- ImGui::Text("%s", lingo->formatCallStack(lingo->_state->pc).c_str());
+ renderCallStack(lingo->_state->pc);
ImGui::EndChild();
ImGui::SeparatorText("Scripts");
@@ -561,12 +609,16 @@ void showExecutionContext() {
} 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];
- script.moviePath = movie->getArchive()->getPathName().toString();
- script.handlerName = getHandlerName(functionHandler._value);
- // Need to pass by reference in case of the current handler
- renderScript(current == script ? current : script, scriptData->_showByteCode, script == current);
+ if (current.handlerId == functionHandler._key) {
+ renderScript(current, scriptData->_showByteCode, true);
+ } else {
+ 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);
+ // Need to pass by reference in case of the current handler
+ renderScript(script, scriptData->_showByteCode, false);
+ }
ImGui::NewLine();
}
}
@@ -600,7 +652,7 @@ void showExecutionContext() {
childSize = ImGui::GetContentRegionAvail();
childSize.y /= 3;
ImGui::BeginChild("##backtrace", childSize);
- ImGui::Text("%s", lingo->formatCallStack(lingo->_state->pc).c_str());
+ renderCallStack(lingo->_state->pc);
ImGui::EndChild();
ImGui::SeparatorText("Scripts");
@@ -668,14 +720,18 @@ void showExecutionContext() {
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];
- Movie *movie = g_director->getCurrentMovie();
- script.moviePath = movie->getArchive()->getPathName().toString();
- script.handlerName = getHandlerName(functionHandler._value);
- // Need to pass by reference in case of the current handler
- renderScript(current == script ? current : script, scriptData->_showByteCode, script == current);
+ if (current.handlerId == functionHandler._key) {
+ renderScript(current, scriptData->_showByteCode, true);
+ } else {
+ 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);
+ // Need to pass by reference in case of the current handler
+ renderScript(script, scriptData->_showByteCode, false);
+ }
ImGui::NewLine();
}
}
Commit: b15e46d55c57b9c6016d842f5029110688c6b12a
https://github.com/scummvm/scummvm/commit/b15e46d55c57b9c6016d842f5029110688c6b12a
Author: Malhar (themalharbdv2046 at gmail.com)
Date: 2025-08-22T10:13:40+02:00
Commit Message:
DIRECTOR: ImGui: Set `byteOffsets` when `Go To Function` called
Solves a segmentation fault caused by accessing `byteOffsets` array
which wasn't being set when called `Go To Function` in Script window
Had to rewrite `getCastIdFromScriptId` to fetch context instead of
only castId
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-controlpanel.cpp
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-script-d2.cpp
engines/director/debugger/dt-script-d4.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 8a0cac6bcd8..1f7cee04839 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -127,22 +127,22 @@ ScriptContext *getScriptContext(CastMemberID id) {
return ctx;
}
-int16 getCastIdFromScriptNameIndex(uint32 nameIndex, CastMemberID id, Common::String handlerName) {
+ScriptContext *getScriptContext(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;
+ // If the name at nameIndex is not the same as handler name, means its a local script (in the same Lscr resource)
+ if (cast && cast->_lingoArchive->names[nameIndex] != handlerName) {
+ return cast->_lingoArchive->findScriptContext(id.member);
}
for (auto it : cast->_lingoArchive->scriptContexts[kMovieScript]) {
if (it._value->_functionHandlers.contains(handlerName)) {
- return it._key;
+ return it._value;
}
}
- return -1;
+ return nullptr;
}
Director::Breakpoint *getBreakpoint(const Common::String &handlerName, uint16 scriptId, uint pc) {
diff --git a/engines/director/debugger/dt-controlpanel.cpp b/engines/director/debugger/dt-controlpanel.cpp
index 7be834a6823..8f1afdeba67 100644
--- a/engines/director/debugger/dt-controlpanel.cpp
+++ b/engines/director/debugger/dt-controlpanel.cpp
@@ -70,7 +70,6 @@ static bool stepInShouldPauseDebugger() {
return true;
}
- debug("I'm returning false for some reason, %d:%d", g_lingo->_state->callstack.size(), _state->_dbg._callstackSize);
return false;
}
@@ -84,7 +83,6 @@ static bool stepOutShouldPause() {
return true;
}
- debug("I'm returning false for some reason, %d:%d", g_lingo->_state->callstack.size(), _state->_dbg._callstackSize);
return false;
}
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index 9540619c234..517ad9dce14 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -202,7 +202,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);
+ScriptContext *getScriptContext(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-d2.cpp b/engines/director/debugger/dt-script-d2.cpp
index e7d5cf276d3..dc4b2461a7b 100644
--- a/engines/director/debugger/dt-script-d2.cpp
+++ b/engines/director/debugger/dt-script-d2.cpp
@@ -503,8 +503,9 @@ public:
}
}
- int16 castId = getCastIdFromScriptNameIndex(obj, _script.id, *node->name);
- ImGuiScript script = toImGuiScript(_script.type, CastMemberID(castId, _script.id.castLib), *node->name);
+ ScriptContext *context = getScriptContext(obj, _script.id, *node->name);
+ ImGuiScript script = toImGuiScript(_script.type, CastMemberID(context->_id, _script.id.castLib), *node->name);
+ script.byteOffsets = context->_functionByteOffsets[script.handlerId];
script.moviePath = _script.moviePath;
script.handlerName = *node->name;
setScriptToDisplay(script);
diff --git a/engines/director/debugger/dt-script-d4.cpp b/engines/director/debugger/dt-script-d4.cpp
index 6faea7005ae..22933f73123 100644
--- a/engines/director/debugger/dt-script-d4.cpp
+++ b/engines/director/debugger/dt-script-d4.cpp
@@ -118,8 +118,9 @@ public:
break;
}
}
- int16 castId = getCastIdFromScriptNameIndex(obj, _script.id, node.name);
- ImGuiScript script = toImGuiScript(_script.type, CastMemberID(castId, _script.id.castLib), node.name);
+ ScriptContext *context = getScriptContext(obj, _script.id, node.name);
+ ImGuiScript script = toImGuiScript(_script.type, CastMemberID(context->_id, _script.id.castLib), node.name);
+ script.byteOffsets = context->_functionByteOffsets[script.handlerId];
script.moviePath = _script.moviePath;
script.handlerName = node.name;
setScriptToDisplay(script);
More information about the Scummvm-git-logs
mailing list