[Scummvm-git-logs] scummvm master -> 7494441d8603f640fcb4d8fce63d5c15f4ab8200
sev-
noreply at scummvm.org
Mon Jun 15 23:33:34 UTC 2026
This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
824b057902 DIRECTOR: DT: Improve cast details panel and unify script display
f318fc13ae DIRECTOR: DT: Add browser navigation to scripts window, decouple from execution context
7494441d86 DIRECTOR: DT: Add Ctrl+2/3/4 shortcuts for Control Panel, Cast, Score
Commit: 824b0579026a88879916d1c062973efb54b70cd3
https://github.com/scummvm/scummvm/commit/824b0579026a88879916d1c062973efb54b70cd3
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-06-16T01:33:29+02:00
Commit Message:
DIRECTOR: DT: Improve cast details panel and unify script display
Show actual data in the cast details panel instead of placeholder ellipses.
scriptText displays as "(hover)" with a multiline tooltip preview; clicking
opens the script in the handlers window via addToOpenHandlers. modifiedBy and
comments show "N/A" when absent.
Removes the old showScriptCasts/addScriptCastToDisplay/renderCastScript
pipeline entirely. all script display now goes through renderScript. Fixes
a bug where the Lingo/Bytecode toggle in the script viewer was a single
global flag shared across all open handlers.
Changed paths:
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-castdetails.cpp
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-score.cpp
engines/director/debugger/dt-scripts.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index eac525112e0..e121297d662 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -524,11 +524,6 @@ ImVec4 convertColor(uint32 color) {
return ImGui::ColorConvertU32ToFloat4(color);
}
-static void addScriptCastToDisplay(CastMemberID &id) {
- _state->_scriptCasts.remove(id);
- _state->_scriptCasts.push_back(id);
-}
-
void addToOpenHandlers(ImGuiScript handler) {
_state->_openHandlers.erase(handler.id.member);
_state->_openHandlers[handler.id.member] = handler;
@@ -553,8 +548,19 @@ void displayScriptRef(CastMemberID &scriptId) {
ImGui::SetItemTooltip(scriptId.asString().c_str());
- if (ImGui::IsItemClicked(0))
- addScriptCastToDisplay(scriptId);
+ if (ImGui::IsItemClicked(0)) {
+ ScriptContext *ctx = getScriptContext(scriptId);
+ if (ctx) {
+ Common::String moviePath = g_director->getCurrentMovie()->getArchive()->getPathName().toString();
+ for (auto &handler : ctx->_functionHandlers) {
+ ImGuiScript script = toImGuiScript(ctx->_scriptType, scriptId, handler._key);
+ script.byteOffsets = ctx->_functionByteOffsets[script.handlerId];
+ script.moviePath = moviePath;
+ script.handlerName = formatHandlerName(ctx->_scriptId, scriptId.member, script.handlerId, ctx->_scriptType, false);
+ addToOpenHandlers(script);
+ }
+ }
+ }
} else {
ImGui::Selectable(" ");
}
@@ -934,7 +940,6 @@ void onImGuiRender() {
ImGui::EndMainMenuBar();
}
- showScriptCasts();
showExecutionContext();
showHandlers();
diff --git a/engines/director/debugger/dt-castdetails.cpp b/engines/director/debugger/dt-castdetails.cpp
index 1999dddddfa..4546709984a 100644
--- a/engines/director/debugger/dt-castdetails.cpp
+++ b/engines/director/debugger/dt-castdetails.cpp
@@ -44,6 +44,7 @@
namespace Director {
namespace DT {
+
template<typename... Args>
void showProperty(const Common::String &title,
const ImVec4 *color,
@@ -448,9 +449,9 @@ void drawRichTextCMprops(RichTextCastMember *member) {
for (int i = 7; i >= 0; i--) {
bool bitSet = (member->_cropFlags & (1 << i)) != 0;
if (bitSet) {
- ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "1");
+ ImGui::TextColored(_state->theme->var_color, "1");
} else {
- ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "0");
+ ImGui::TextDisabled("0");
}
if (i > 0) {
ImGui::SameLine();
@@ -521,8 +522,8 @@ void drawBaseCMprops(CastMember *member) {
if (info) {
showProperty("name", "%s", info->name.c_str());
} else {
- ImVec4 grayColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f);
- showProperty("name", &grayColor, "No Info");
+ ImVec4 disabledColor = ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled);
+ showProperty("name", &disabledColor, "No Info");
}
showProperty("number", "%d", member->getID());
@@ -532,8 +533,8 @@ void drawBaseCMprops(CastMember *member) {
if (info && !info->fileName.empty()) {
showProperty("fileName", "%s", info->fileName.c_str());
} else {
- ImVec4 grayColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f);
- showProperty("fileName", &grayColor, "...");
+ ImVec4 disabledColor = ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled);
+ showProperty("fileName", &disabledColor, "...");
}
showProperty("type", "#%s", castType2str(member->_type));
@@ -544,47 +545,73 @@ void drawBaseCMprops(CastMember *member) {
ImGui::TableSetColumnIndex(0);
ImGui::Text("scriptText");
ImGui::TableSetColumnIndex(1);
- if (info && !info->script.empty()) {
+ {
CastMemberID scriptCastId(member->getID(), cast->_castLibID);
+ ScriptContext *scriptCtx = getScriptContext(scriptCastId);
+ bool hasScript = scriptCtx != nullptr || (info && !info->script.empty());
bool hasCastScript = g_director->getCurrentMovie()->getScriptContext(kCastScript, scriptCastId) != nullptr;
- ImGui::TextColored(hasCastScript ? ImVec4(0.4f, 0.8f, 0.4f, 1.0f) : ImVec4(0.7f, 0.7f, 1.0f, 1.0f), "...");
- if (ImGui::IsItemHovered()) {
- ImGui::SetTooltip(hasCastScript ? "%s\n\n(click to open script)" : "%s", info->script.c_str());
- if (hasCastScript)
+ if (hasScript) {
+ ImGui::TextColored(hasCastScript ? _state->theme->var_color : _state->theme->script_ref, "(hover)");
+ if (ImGui::IsItemHovered()) {
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
+ if (ImGui::BeginTooltip()) {
+ ImGui::PushTextWrapPos(400.0f);
+ if (info && !info->script.empty()) {
+ Common::String tip = info->script;
+ tip.replace('\r', '\n');
+ if (tip.size() > 500)
+ tip = tip.substr(0, 500) + "\n...";
+ ImGui::TextUnformatted(tip.c_str());
+ ImGui::Separator();
+ }
+ ImGui::TextDisabled("(click to open script)");
+ ImGui::PopTextWrapPos();
+ ImGui::EndTooltip();
+ }
+ }
+ if (ImGui::IsItemClicked(0)) {
+ if (scriptCtx) {
+ Common::String moviePath = g_director->getCurrentMovie()->getArchive()->getPathName().toString();
+ for (auto &handler : scriptCtx->_functionHandlers) {
+ ImGuiScript script = toImGuiScript(scriptCtx->_scriptType, scriptCastId, handler._key);
+ script.byteOffsets = scriptCtx->_functionByteOffsets[script.handlerId];
+ script.moviePath = moviePath;
+ script.handlerName = formatHandlerName(scriptCtx->_scriptId, scriptCastId.member, script.handlerId, scriptCtx->_scriptType, false);
+ addToOpenHandlers(script);
+ }
+ }
+ }
+ } else {
+ ImGui::TextDisabled("...");
}
- if (hasCastScript && ImGui::IsItemClicked(0))
- displayScriptRef(scriptCastId);
- } else {
- ImGui::TextColored(ImVec4(0.5f, 0.5f, 0.5f, 1.0f), "...");
}
if (info && info->creationTime != 0) {
showProperty("creationDate", "%u", info->creationTime);
} else {
- ImVec4 grayColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f);
- showProperty("creationDate", &grayColor, "...");
+ ImVec4 disabledColor = ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled);
+ showProperty("creationDate", &disabledColor, "N/A");
}
if (info && info->modifiedTime != 0) {
showProperty("modifiedDate", "%u", info->modifiedTime);
} else {
- ImVec4 grayColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f);
- showProperty("modifiedDate", &grayColor, "...");
+ ImVec4 disabledColor = ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled);
+ showProperty("modifiedDate", &disabledColor, "N/A");
}
if (info && !info->modifiedBy.empty()) {
showProperty("modifiedBy", "%s", info->modifiedBy.c_str());
} else {
- ImVec4 grayColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f);
- showProperty("modifiedBy", &grayColor, "...");
+ ImVec4 disabledColor = ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled);
+ showProperty("modifiedBy", &disabledColor, "N/A");
}
if (info && !info->comments.empty()) {
showProperty("comments", "%s", info->comments.c_str());
} else {
- ImVec4 grayColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f);
- showProperty("comments", &grayColor, "...");
+ ImVec4 disabledColor = ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled);
+ showProperty("comments", &disabledColor, "N/A");
}
showProperty("purgePriority", "%d", member->_purgePriority);
@@ -604,8 +631,8 @@ void drawBaseCMprops(CastMember *member) {
ImGuiImage media = getImageID(member);
- ImVec4 grayColor = ImVec4(0.5f, 0.5f, 0.5f, 1.0f);
- showProperty("media", &grayColor, "%s", media.id == 0 ? "empty" : "...");
+ ImVec4 disabledColor = ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled);
+ showProperty("media", &disabledColor, "%s", media.id == 0 ? "empty" : "...");
// Not using showProperty() here because we want to show a
// thumbnail of the media instead of text.
@@ -933,10 +960,10 @@ void drawSoundCMprops(SoundCastMember *member) {
showProperty("sampleSize", "%d bit", member->_audio->getSampleSize());
showProperty("channels", "%d", member->_audio->getChannelCount());
} else {
- ImVec4 gray = ImVec4(0.5f, 0.5f, 0.5f, 1.0f);
- showProperty("sampleRate", &gray, "N/A");
- showProperty("sampleSize", &gray, "N/A");
- showProperty("channels", &gray, "N/A");
+ ImVec4 disabledColor = ImGui::GetStyleColorVec4(ImGuiCol_TextDisabled);
+ showProperty("sampleRate", &disabledColor, "N/A");
+ showProperty("sampleSize", &disabledColor, "N/A");
+ showProperty("channels", &disabledColor, "N/A");
}
ImGui::EndTable();
}
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index 1372e834365..673791dde7e 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -57,6 +57,7 @@ typedef struct ImGuiScriptCodeLine {
typedef struct ImGuiScript {
bool score = false;
+ bool showByteCode = false;
CastMemberID id;
ScriptType type;
Common::String handlerId;
@@ -276,7 +277,6 @@ typedef struct ImGuiState {
ImGuiWindows _savedW;
bool _wasHidden = false;
- Common::List<CastMemberID> _scriptCasts;
Common::HashMap<int, ImGuiScript> _openHandlers;
bool _showCompleteScript = true;
@@ -385,7 +385,6 @@ void renderScriptAST(ImGuiScript &script, bool showByteCode, bool scrollTo);
// dt-scripts.cpp
void showFuncList();
-void showScriptCasts();
void showExecutionContext();
void showHandlers();
diff --git a/engines/director/debugger/dt-score.cpp b/engines/director/debugger/dt-score.cpp
index fcc05364f08..2f66701c6e6 100644
--- a/engines/director/debugger/dt-score.cpp
+++ b/engines/director/debugger/dt-score.cpp
@@ -959,12 +959,6 @@ static void drawMainChannelGrid(ImDrawList *dl, ImVec2 startPos, Score *score) {
case kChPalette: // open cast window focused on palette member
if (mc.palette.paletteId.member) {
_state->_w.cast = true;
- // select it in the cast so showCast() highlights it
- for (auto &scriptCast : _state->_scriptCasts) {
- if (scriptCast == mc.palette.paletteId) {
- break;
- }
- }
}
break;
case kChTransition:
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index 402f96376cf..c44bf27c76b 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -36,69 +36,6 @@
namespace Director {
namespace DT {
-static void renderCastScript(Symbol &sym) {
- if (sym.type != HANDLER)
- return;
-
- Director::Lingo *lingo = g_director->getLingo();
- Common::String handlerName;
-
- if (sym.ctx && sym.ctx->_id)
- handlerName = Common::String::format("%d:", sym.ctx->_id);
-
- handlerName += lingo->formatFunctionName(sym);
-
- ImGui::Text("%s", handlerName.c_str());
-
- ImDrawList *dl = ImGui::GetWindowDrawList();
-
- ImVec4 color;
-
- uint pc = 0;
- while (pc < sym.u.defn->size()) {
- ImVec2 pos = ImGui::GetCursorScreenPos();
- const ImVec2 mid(pos.x + 7, pos.y + 7);
- Common::String bpName = Common::String::format("%s-%d", handlerName.c_str(), pc);
-
- color = _state->theme->bp_color_disabled;
-
- Director::Breakpoint *bp = getBreakpoint(handlerName, sym.ctx->_id, pc);
- if (bp)
- color = _state->theme->bp_color_enabled;
-
- ImGui::PushID(pc);
- ImGui::InvisibleButton("Line", ImVec2(16, ImGui::GetFontSize()));
- if (ImGui::IsItemClicked(0)) {
- if (bp) {
- g_lingo->delBreakpoint(bp->id);
- color = _state->theme->bp_color_disabled;
- } else {
- Director::Breakpoint newBp;
- newBp.type = kBreakpointFunction;
- newBp.funcName = handlerName;
- newBp.funcOffset = pc;
- g_lingo->addBreakpoint(newBp);
- color = _state->theme->bp_color_enabled;
- }
- }
-
- if (color == _state->theme->bp_color_disabled && ImGui::IsItemHovered()) {
- color = _state->theme->bp_color_hover;
- }
-
- dl->AddCircleFilled(mid, 4.0f, ImColor(color));
- dl->AddLine(ImVec2(pos.x + 16.0f, pos.y), ImVec2(pos.x + 16.0f, pos.y + 17), ImColor(_state->theme->line_color));
-
- ImGui::SetItemTooltip("Click to add a breakpoint");
-
- ImGui::SameLine();
- ImGui::Text("[%5d] ", pc);
- ImGui::SameLine();
- ImGui::Text("%s", lingo->decodeInstruction(sym.u.defn, pc, &pc).c_str());
- ImGui::PopID();
- }
-}
-
static void renderScript(ImGuiScript &script, bool showByteCode, bool scrollTo) {
if (script.oldAst) {
renderOldScriptAST(script, showByteCode, scrollTo);
@@ -176,55 +113,7 @@ static void renderCallStack(uint pc) {
}
}
-static bool showScriptCast(CastMemberID &id) {
- Common::String wName("Script ");
- wName += id.asString();
-
- ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
- ImGui::SetNextWindowSize(ImVec2(240, 240), ImGuiCond_FirstUseEver);
-
- bool closed = true;
-
- if (ImGui::Begin(wName.c_str(), &closed)) {
- Cast *cast = g_director->getCurrentMovie()->getCasts()->getValOrDefault(id.castLib, nullptr);
- ScriptContext *ctx = g_director->getCurrentMovie()->getScriptContext(kScoreScript, id);
-
- if (ctx) {
- for (auto &handler : ctx->_functionHandlers)
- renderCastScript(handler._value);
- } else if (cast && cast->_lingoArchive->factoryContexts.contains(id.member)) {
- for (auto &it : *cast->_lingoArchive->factoryContexts.getVal(id.member)) {
- for (auto &handler : it._value->_functionHandlers)
- renderCastScript(handler._value);
- }
- } else {
- ImGui::Text("[Nothing]");
- }
- }
- ImGui::End();
-
- if (!closed)
- return false;
-
- return true;
-}
-
-/**
- * Display all open scripts
- */
-void showScriptCasts() {
- if (_state->_scriptCasts.empty())
- return;
-
- for (Common::List<CastMemberID>::iterator scr = _state->_scriptCasts.begin(); scr != _state->_scriptCasts.end();) {
- if (!showScriptCast(*scr))
- scr = _state->_scriptCasts.erase(scr);
- else
- scr++;
- }
-}
-
-static bool showHandler(ImGuiScript handler) {
+static bool showHandler(ImGuiScript &handler) {
ScriptContext *ctx = getScriptContext(handler.id);
Common::String wName;
if (ctx) {
@@ -237,27 +126,14 @@ static bool showHandler(ImGuiScript handler) {
bool closed = true;
if (ImGui::Begin(wName.c_str(), &closed)) {
- ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &_state->_showCompleteScript, true); // Lingo
- ImGui::SetItemTooltip("Show Handler");
+ ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &handler.showByteCode, true); // Lingo
+ ImGui::SetItemTooltip("Show Lingo");
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];
+ ImGuiEx::toggleButton(ICON_MS_STACKS, &handler.showByteCode); // Bytecode
+ ImGui::SetItemTooltip("Show Bytecode");
- if (script == handler) {
- _state->_dbg._goToDefinition = true;
- }
- renderScript(script, false, script == handler);
- ImGui::NewLine();
- }
- }
+ renderScript(handler, handler.showByteCode, true);
}
ImGui::End();
@@ -276,7 +152,7 @@ void showHandlers() {
}
Common::Array<uint32> toClose;
- for (auto handler : _state->_openHandlers) {
+ for (auto &handler : _state->_openHandlers) {
if (!showHandler(handler._value))
toClose.push_back(handler._value.id.member);
}
Commit: f318fc13ae404b1e857d61a239307eec4c75cf76
https://github.com/scummvm/scummvm/commit/f318fc13ae404b1e857d61a239307eec4c75cf76
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-06-16T01:33:29+02:00
Commit Message:
DIRECTOR: DT: Add browser navigation to scripts window, decouple from execution context
Replace the per-handler floating windows with a single "Scripts" window
backed by browser-style history (back/forward buttons + dropdown combo).
Extract renderScriptNavBar() and renderScriptContext() as shared helpers
used by both the Scripts window and Execution Context, removing ~80 lines
of duplicated code.
addToOpenHandlers() now pushes into ScriptData _openScripts with forward-
history truncation, replacing HashMap<int, ImGuiScript> _openHandlers which
had a collision bug (two scripts from different cast libs with the same
member number would overwrite each other).
Also fixes: closing the Scripts window and clicking the same script now
reopens it; back/forward in the non-stage execution context window now sets
_goToDefinition; combo entries now use PushID(); getScriptContext() falls
back to lctxContexts so Movie/parent scripts are found by cast member ID.
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 e121297d662..3d4b3ef210b 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -133,7 +133,7 @@ ImGuiScript toImGuiScript(ScriptType scriptType, CastMemberID id, const Common::
}
ScriptContext *getScriptContext(CastMemberID id) {
- const Director::Movie *movie = g_director->getCurrentMovie();;
+ const Director::Movie *movie = g_director->getCurrentMovie();
const Cast *cast;
if (id.castLib == SHARED_CAST_LIB)
@@ -141,12 +141,20 @@ ScriptContext *getScriptContext(CastMemberID id) {
else
cast = movie->getCasts()->getVal(id.castLib);
- if (!cast) {
+ if (!cast)
return nullptr;
- }
ScriptContext *ctx = cast->_lingoArchive->findScriptContext(id.member);
- return ctx;
+ if (ctx)
+ return ctx;
+
+ // Some scripts are only in lctxContexts (keyed by lctx index, not cast member ID).
+ // Do a reverse lookup: find the lctx entry whose cast ID maps to id.member.
+ for (auto &entry : cast->_lingoArchive->lctxContexts) {
+ if (cast->getCastIdByScriptId(entry._key) == id.member)
+ return entry._value;
+ }
+ return nullptr;
}
ScriptContext *getScriptContext(uint32 nameIndex, CastMemberID id, Common::String handlerName) {
@@ -525,8 +533,17 @@ ImVec4 convertColor(uint32 color) {
}
void addToOpenHandlers(ImGuiScript handler) {
- _state->_openHandlers.erase(handler.id.member);
- _state->_openHandlers[handler.id.member] = handler;
+ ScriptData &data = _state->_openScripts;
+ _state->_w.scripts = true; // always (re)open the window
+ // Truncate forward history when navigating to a new script
+ if (data._current + 1 < data._scripts.size())
+ data._scripts.resize(data._current + 1);
+ // Don't add a duplicate at the current position
+ if (!data._scripts.empty() && data._scripts.back() == handler)
+ return;
+ data._scripts.push_back(handler);
+ data._current = data._scripts.size() - 1;
+ data._showScript = true;
}
void setScriptToDisplay(const ImGuiScript &script) {
@@ -941,7 +958,7 @@ void onImGuiRender() {
}
showExecutionContext();
- showHandlers();
+ showScriptsWindow();
showControlPanel();
showVars();
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index 673791dde7e..24d21b061d5 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -98,6 +98,7 @@ typedef struct ImGuiWindows {
bool archive = false;
bool watchedVars = false;
bool executionContext = false;
+ bool scripts = false;
bool search = false;
bool imageViewer = false;
bool windows = false;
@@ -277,7 +278,7 @@ typedef struct ImGuiState {
ImGuiWindows _savedW;
bool _wasHidden = false;
- Common::HashMap<int, ImGuiScript> _openHandlers;
+ ScriptData _openScripts;
bool _showCompleteScript = true;
Common::HashMap<Common::String, bool, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> _variables;
@@ -386,7 +387,7 @@ void renderScriptAST(ImGuiScript &script, bool showByteCode, bool scrollTo);
// dt-scripts.cpp
void showFuncList();
void showExecutionContext();
-void showHandlers();
+void showScriptsWindow();
// dt-save-state.cpp
void saveCurrentState();
diff --git a/engines/director/debugger/dt-scripts.cpp b/engines/director/debugger/dt-scripts.cpp
index c44bf27c76b..562b24ddaaf 100644
--- a/engines/director/debugger/dt-scripts.cpp
+++ b/engines/director/debugger/dt-scripts.cpp
@@ -113,51 +113,112 @@ static void renderCallStack(uint pc) {
}
}
-static bool showHandler(ImGuiScript &handler) {
- ScriptContext *ctx = getScriptContext(handler.id);
- Common::String wName;
- if (ctx) {
- wName = Common::String(ctx->asString());
- }
-
- ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
- ImGui::SetNextWindowSize(ImVec2(480, 540), ImGuiCond_FirstUseEver);
+static Common::String getHandlerName(Symbol &sym) {
+ Common::String handlerName;
+ if (sym.ctx && sym.ctx->_id)
+ handlerName = Common::String::format("%d:", sym.ctx->_id);
+ handlerName += g_lingo->formatFunctionName(sym);
+ return handlerName;
+}
- bool closed = true;
+// Renders back/forward navigation, handler dropdown, and Lingo/Bytecode toggle for a ScriptData.
+// Returns true when there is a script to render.
+static bool renderScriptNavBar(ScriptData &data) {
+ if (data._scripts.empty())
+ return false;
- if (ImGui::Begin(wName.c_str(), &closed)) {
- ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &handler.showByteCode, true); // Lingo
- ImGui::SetItemTooltip("Show Lingo");
+ ImGui::BeginDisabled(data._current == 0);
+ if (ImGui::Button(ICON_MS_ARROW_BACK)) {
+ data._current--;
+ _state->_dbg._goToDefinition = true;
+ }
+ ImGui::EndDisabled();
+ ImGui::SetItemTooltip("Backward");
+ ImGui::SameLine();
+
+ ImGui::BeginDisabled(data._current >= data._scripts.size() - 1);
+ if (ImGui::Button(ICON_MS_ARROW_FORWARD)) {
+ data._current++;
+ _state->_dbg._goToDefinition = true;
+ }
+ ImGui::EndDisabled();
+ ImGui::SetItemTooltip("Forward");
+ ImGui::SameLine();
+
+ const char *currentName = data._scripts[data._current].handlerName.c_str();
+ if (ImGui::BeginCombo("##handlers", currentName)) {
+ for (uint i = 0; i < data._scripts.size(); i++) {
+ bool selected = (i == data._current);
+ ImGui::PushID(i);
+ if (ImGui::Selectable(data._scripts[i].handlerName.c_str(), &selected)) {
+ data._current = i;
+ _state->_dbg._goToDefinition = true;
+ }
+ ImGui::PopID();
+ }
+ ImGui::EndCombo();
+ }
+ if (!data._scripts[data._current].oldAst) {
+ ImGui::SameLine(0, 20);
+ ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &data._showByteCode, true);
+ ImGui::SetItemTooltip("Lingo");
ImGui::SameLine();
- ImGuiEx::toggleButton(ICON_MS_STACKS, &handler.showByteCode); // Bytecode
- ImGui::SetItemTooltip("Show Bytecode");
-
- renderScript(handler, handler.showByteCode, true);
+ ImGuiEx::toggleButton(ICON_MS_STACKS, &data._showByteCode);
+ ImGui::SetItemTooltip("Bytecode");
}
- ImGui::End();
-
- if (!closed)
- return false;
return true;
}
-/**
- * Display all open handlers
- */
-void showHandlers() {
- if (_state->_openHandlers.empty()) {
+// Renders all handlers in the context, scrolling to the selected one.
+static void renderScriptContext(ScriptData &data, const Movie *movie) {
+ ImGuiScript ¤t = data._scripts[data._current];
+ ScriptContext *context = getScriptContext(current.id);
+ bool scrollTo = _state->_dbg._goToDefinition;
+
+ if (!context || context->_functionHandlers.size() == 1) {
+ renderScript(current, data._showByteCode, scrollTo);
return;
}
- Common::Array<uint32> toClose;
- for (auto &handler : _state->_openHandlers) {
- if (!showHandler(handler._value))
- toClose.push_back(handler._value.id.member);
+ for (auto &functionHandler : context->_functionHandlers) {
+ if (current.handlerId == functionHandler._key) {
+ renderScript(current, data._showByteCode, scrollTo);
+ } 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);
+ renderScript(script, data._showByteCode, false);
+ }
+ ImGui::NewLine();
}
- for (uint32 key : toClose)
- _state->_openHandlers.erase(key);
+}
+
+void showScriptsWindow() {
+ ScriptData &data = _state->_openScripts;
+ if (!_state->_w.scripts || !data._showScript || data._scripts.empty())
+ return;
+
+ ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(480, 540), ImGuiCond_FirstUseEver);
+
+ if (ImGui::Begin("Scripts", &_state->_w.scripts)) {
+ ScriptContext *ctx = getScriptContext(data._scripts[data._current].id);
+ if (ctx)
+ ImGui::Text("%s", ctx->asString().c_str());
+
+ if (renderScriptNavBar(data)) {
+ ImGui::Separator();
+ ImVec2 childSize = ImGui::GetContentRegionAvail();
+ ImGui::BeginChild("##script", childSize);
+ renderScriptContext(data, g_director->getCurrentMovie());
+ ImGui::EndChild();
+ }
+ }
+ ImGui::End();
+ _state->_dbg._goToDefinition = false;
}
static void updateCurrentScript() {
@@ -190,16 +251,6 @@ static void updateCurrentScript() {
setScriptToDisplay(script);
}
-static Common::String getHandlerName(Symbol &sym) {
- Common::String handlerName;
-
- if (sym.ctx && sym.ctx->_id)
- handlerName = Common::String::format("%d:", sym.ctx->_id);
- handlerName += g_lingo->formatFunctionName(sym);
-
- return handlerName;
-}
-
void showFuncList() {
if (!_state->_w.funcList)
return;
@@ -456,91 +507,23 @@ void showExecutionContext() {
ScriptData *scriptData = &_state->_functions._windowScriptData.getOrCreateVal(stage);
updateCurrentScript();
- if (scriptData->_showScript && !scriptData->_scripts.empty() && scriptData->_current < scriptData->_scripts.size()) {
- // disable highlighting while rendering scripts in Execution Context
+ if (scriptData->_showScript && !scriptData->_scripts.empty()) {
bool oldSuppress = _state->_dbg._suppressHighlight;
_state->_dbg._suppressHighlight = true;
- ImGuiScript ¤t = scriptData->_scripts[scriptData->_current];
-
- // Get all the handlers from the script
- ScriptContext* context = getScriptContext(current.id);
-
- if (context) {
+ ScriptContext *context = getScriptContext(scriptData->_scripts[scriptData->_current].id);
+ if (context)
ImGui::Text("%d:%s type:%s", context->_id, context->getName().c_str(), scriptType2str(context->_scriptType));
- }
- ImGui::BeginDisabled(scriptData->_scripts.empty() || scriptData->_current == 0);
- if (ImGui::Button(ICON_MS_ARROW_BACK)) {
- scriptData->_current--;
- _state->_dbg._goToDefinition = true;
- }
- ImGui::EndDisabled();
- ImGui::SetItemTooltip("Backward");
- ImGui::SameLine();
-
- ImGui::BeginDisabled(scriptData->_current >= scriptData->_scripts.size() - 1);
- if (ImGui::Button(ICON_MS_ARROW_FORWARD)) {
- scriptData->_current++;
- _state->_dbg._goToDefinition = true;
- }
- ImGui::EndDisabled();
- ImGui::SetItemTooltip("Forward");
- ImGui::SameLine();
-
- const char *currentScript = nullptr;
-
- if (scriptData->_current < scriptData->_scripts.size()) {
- currentScript = scriptData->_scripts[scriptData->_current].handlerName.c_str();
- }
-
- if (ImGui::BeginCombo("##handlers", currentScript)) {
- for (uint i = 0; i < scriptData->_scripts.size(); i++) {
- auto &script = scriptData->_scripts[i];
- bool selected = i == scriptData->_current;
- ImGui::PushID(i);
- if (ImGui::Selectable(script.handlerName.c_str(), &selected)) {
- scriptData->_current = i;
- }
- ImGui::PopID();
- }
- ImGui::EndCombo();
- }
-
- if (!scriptData->_scripts[scriptData->_current].oldAst) {
- ImGui::SameLine(0, 20);
- ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &scriptData->_showByteCode, true); // Lingo
- ImGui::SetItemTooltip("Lingo");
- ImGui::SameLine();
-
- ImGuiEx::toggleButton(ICON_MS_STACKS, &scriptData->_showByteCode); // Bytecode
- ImGui::SetItemTooltip("Bytecode");
- }
-
- ImGui::Separator();
- childSize = ImGui::GetContentRegionAvail();
- ImGui::BeginChild("##script", childSize);
-
- if (!context || context->_functionHandlers.size() == 1) {
- renderScript(current, scriptData->_showByteCode, true);
- } else {
- for (auto &functionHandler : context->_functionHandlers) {
- 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();
- }
+ if (renderScriptNavBar(*scriptData)) {
+ ImGui::Separator();
+ childSize = ImGui::GetContentRegionAvail();
+ ImGui::BeginChild("##script", childSize);
+ renderScriptContext(*scriptData, movie);
+ ImGui::EndChild();
+ scriptsRendered = true;
}
- scriptsRendered = true;
- ImGui::EndChild();
_state->_dbg._suppressHighlight = oldSuppress;
}
@@ -576,90 +559,23 @@ void showExecutionContext() {
scriptData = &_state->_functions._windowScriptData.getOrCreateVal(window);
updateCurrentScript();
- if (scriptData->_showScript && !scriptData->_scripts.empty() && scriptData->_current < scriptData->_scripts.size()) {
+ if (scriptData->_showScript && !scriptData->_scripts.empty()) {
bool oldSuppress = _state->_dbg._suppressHighlight;
_state->_dbg._suppressHighlight = true;
- ImGuiScript ¤t = scriptData->_scripts[scriptData->_current];
-
- // Get all the handlers from the script
- ScriptContext* context = getScriptContext(current.id);
-
- if (context) {
- int castId = context->_id;
- if (castId == -1) {
- castId = movie->getCast()->getCastIdByScriptId(context->_parentNumber);
- }
- Common::String scriptInfo = Common::String::format("%d:%s type:%s", castId, 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--;
- }
- ImGui::EndDisabled();
- ImGui::SetItemTooltip("Backward");
- ImGui::SameLine();
- ImGui::BeginDisabled(scriptData->_current >= scriptData->_scripts.size() - 1);
- if (ImGui::Button(ICON_MS_ARROW_FORWARD)) {
- scriptData->_current++;
- }
- ImGui::EndDisabled();
- ImGui::SetItemTooltip("Forward");
- ImGui::SameLine();
-
- const char *currentScript = nullptr;
-
- if (scriptData->_current < scriptData->_scripts.size()) {
- currentScript = scriptData->_scripts[scriptData->_current].handlerName.c_str();
- }
-
- if (ImGui::BeginCombo("##handlers", currentScript)) {
- 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)) {
- scriptData->_current = i;
- }
- }
- ImGui::EndCombo();
+ ScriptContext *context = getScriptContext(scriptData->_scripts[scriptData->_current].id);
+ if (context)
+ ImGui::Text("%d:%s type:%s", context->_id, context->getName().c_str(), scriptType2str(context->_scriptType));
+
+ if (renderScriptNavBar(*scriptData)) {
+ ImGui::Separator();
+ childSize = ImGui::GetContentRegionAvail();
+ ImGui::BeginChild("##script", childSize);
+ renderScriptContext(*scriptData, movie);
+ ImGui::EndChild();
+ scriptsRendered = true;
}
- if (!scriptData->_scripts[scriptData->_current].oldAst) {
- ImGui::SameLine(0, 20);
- ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &scriptData->_showByteCode, true); // Lingo
- ImGui::SetItemTooltip("Lingo");
- ImGui::SameLine();
-
- ImGuiEx::toggleButton(ICON_MS_STACKS, &scriptData->_showByteCode); // Bytecode
- ImGui::SetItemTooltip("Bytecode");
- }
-
- ImGui::Separator();
- childSize = ImGui::GetContentRegionAvail();
- ImGui::BeginChild("##script", childSize);
-
- if (!context || context->_functionHandlers.size() == 1) {
- renderScript(current, scriptData->_showByteCode, true);
- } else {
- for (auto &functionHandler : context->_functionHandlers) {
- 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();
- }
- }
-
- scriptsRendered = true;
- ImGui::EndChild();
_state->_dbg._suppressHighlight = oldSuppress;
}
@@ -670,6 +586,7 @@ void showExecutionContext() {
// Mark the scripts not dirty after all the handlers have been rendered
_state->_dbg._isScriptDirty = !scriptsRendered;
+ _state->_dbg._goToDefinition = false;
g_director->setCurrentWindow(currentWindow);
g_lingo->switchStateFromWindow();
Commit: 7494441d8603f640fcb4d8fce63d5c15f4ab8200
https://github.com/scummvm/scummvm/commit/7494441d8603f640fcb4d8fce63d5c15f4ab8200
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-06-16T01:33:29+02:00
Commit Message:
DIRECTOR: DT: Add Ctrl+2/3/4 shortcuts for Control Panel, Cast, Score
Use ImGui::Shortcut() with RouteGlobal | RouteOverFocused inside
BeginMainMenuBar() to register global shortcuts for toggling the
Control Panel (Ctrl+2), Cast (Ctrl+3), and Score (Ctrl+4) windows.
Since MacOS overrides ctrl, use cmd instead.:wq
Changed paths:
engines/director/debugger/debugtools.cpp
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 3d4b3ef210b..f9c32539a1d 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -908,6 +908,12 @@ void onImGuiRender() {
ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode);
if (ImGui::BeginMainMenuBar()) {
+ if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_2, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused))
+ _state->_w.controlPanel = !_state->_w.controlPanel;
+ if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_3, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused))
+ _state->_w.cast = !_state->_w.cast;
+ if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_4, ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused))
+ _state->_w.score = !_state->_w.score;
if (ImGui::BeginMenu("View")) {
ImGui::SeparatorText("Windows");
More information about the Scummvm-git-logs
mailing list