[Scummvm-git-logs] scummvm master -> 5f01c272c1508d470f7a8d468cfe12fa0beb2ad4
sev-
noreply at scummvm.org
Sun Jun 7 19:32:42 UTC 2026
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
a97b925d2e DIRECTOR: DT: improve search with new modes and ui
5f01c272c1 DIRECTOR: DT: add Windows panel showing loaded windows and all movies
Commit: a97b925d2e888c0ad1c09eeb41bb6bd9e62e5fd6
https://github.com/scummvm/scummvm/commit/a97b925d2e888c0ad1c09eeb41bb6bd9e62e5fd6
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-06-07T21:32:37+02:00
Commit Message:
DIRECTOR: DT: improve search with new modes and ui
Changed paths:
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-search.cpp
engines/director/lingo/lingo-object.h
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index 998f4795286..f1b51776c1d 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -104,8 +104,9 @@ typedef struct ImGuiWindows {
enum SearchMode {
kSearchAll = 0,
- kSearchHandlerNames,
- kSearchScriptBody,
+ kSearchHandlers,
+ kSearchVariables,
+ kSearchBody,
};
typedef struct ScriptData {
@@ -329,6 +330,7 @@ typedef struct ImGuiState {
} ImGuiState;
// debugtools.cpp
+const LingoDec::Handler *getHandler(const Cast *cast, CastMemberID id, const Common::String &handlerId);
ImGuiScript toImGuiScript(ScriptType scriptType, CastMemberID id, const Common::String &handlerId);
ScriptContext *getScriptContext(CastMemberID id);
ScriptContext *getScriptContext(uint32 nameIndex, CastMemberID castId, Common::String handler);
diff --git a/engines/director/debugger/dt-search.cpp b/engines/director/debugger/dt-search.cpp
index 51edf530b28..454f5400449 100644
--- a/engines/director/debugger/dt-search.cpp
+++ b/engines/director/debugger/dt-search.cpp
@@ -22,8 +22,9 @@
#include "director/director.h"
#include "director/debugger/dt-internal.h"
+#include "director/archive.h"
#include "director/cast.h"
-#include "director/castmember/text.h"
+#include "director/castmember/castmember.h"
#include "director/movie.h"
namespace Director {
@@ -31,57 +32,82 @@ namespace DT {
static const char *searchModeNames[] = {
"All",
- "Handler Names",
- "Script Body",
+ "Handlers",
+ "Variables",
+ "Body",
};
+static bool containsQuery(const Common::String &s, const Common::String &query) {
+ Common::String lower = s;
+ lower.toLowercase();
+ return lower.contains(query.c_str());
+}
+
static void searchCast(Cast *cast, int castLibID, const Common::String &query, Director::Lingo *lingo, Movie *movie, SearchMode mode) {
- if (!cast) return;
- if (!cast->_lingoArchive) return;
+ if (!cast || !cast->_lingoArchive)
+ return;
for (int i = 0; i <= kMaxScriptType; i++) {
if (cast->_lingoArchive->scriptContexts[i].empty())
continue;
for (auto &scriptContext : cast->_lingoArchive->scriptContexts[i]) {
+ // check property names once per script context, shared across all its handlers
+ bool propertyMatch = false;
+ if (mode == kSearchAll || mode == kSearchVariables) {
+ for (const Common::String &name : scriptContext._value->getPropertyNames()) {
+ if (containsQuery(name, query)) {
+ propertyMatch = true;
+ break;
+ }
+ }
+ }
+
+ // also search the cast member name itself
+ bool castNameMatch = false;
+ if (mode == kSearchAll || mode == kSearchHandlers) {
+ CastMember *cm = cast->getCastMember(scriptContext._key, false);
+ if (cm && containsQuery(cm->getName(), query))
+ castNameMatch = true;
+ }
+
for (auto &functionHandler : scriptContext._value->_functionHandlers) {
bool found = false;
- // Search handler name
- if (mode == kSearchAll || mode == kSearchHandlerNames) {
- Common::String handlerLower = functionHandler._key;
- handlerLower.toLowercase();
- if (handlerLower.contains(query.c_str()))
+ // handler name and cast member name
+ if (mode == kSearchAll || mode == kSearchHandlers) {
+ if (castNameMatch || containsQuery(functionHandler._key, query))
found = true;
+ }
- // Search property and global names
- if (!found) {
+ // variable names -> property (from ScriptContext), argument and global (from lingodec handler)
+ if (!found && (mode == kSearchAll || mode == kSearchVariables)) {
+ if (propertyMatch) {
+ found = true;
+ } else {
CastMemberID memberID(scriptContext._key, castLibID);
- ImGuiScript script = toImGuiScript(scriptContext._value->_scriptType, memberID, functionHandler._key);
- for (auto &name : script.propertyNames) {
- Common::String n = name;
- n.toLowercase();
- if (n.contains(query.c_str())) { found = true; break; }
- }
- if (!found) {
- for (auto &name : script.globalNames) {
- Common::String n = name;
- n.toLowercase();
- if (n.contains(query.c_str())) { found = true; break; }
+ const LingoDec::Handler *ldHandler = getHandler(cast, memberID, functionHandler._key);
+ if (ldHandler) {
+ for (const Common::String &name : ldHandler->argumentNames) {
+ if (containsQuery(name, query)) { found = true; break; }
+ }
+ if (!found) {
+ for (const Common::String &name : ldHandler->globalNames) {
+ if (containsQuery(name, query)) { found = true; break; }
+ }
}
}
}
}
- // Search script body via decodeInstruction
- if (!found && lingo && (mode == kSearchAll || mode == kSearchScriptBody)) {
+ // acript body via decoded bytecode
+ if (!found && lingo && (mode == kSearchAll || mode == kSearchBody)) {
Symbol &sym = functionHandler._value;
if (sym.type == HANDLER && sym.u.defn) {
uint pc = 0;
while (pc < sym.u.defn->size()) {
Common::String line = lingo->decodeInstruction(sym.u.defn, pc, &pc);
- line.toLowercase();
- if (line.contains(query.c_str())) {
+ if (containsQuery(line, query)) {
found = true;
break;
}
@@ -130,7 +156,7 @@ void showSearchBar() {
auto &search = _state->_search;
ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver);
- ImGui::SetNextWindowSize(ImVec2(480, 240), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(560, 320), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Search", &_state->_w.search)) {
_state->_dbg._highlightQuery = "";
@@ -144,6 +170,9 @@ void showSearchBar() {
ImGui::SameLine();
ImGui::SetNextItemWidth(-80);
+ // focus the input field when the window first opens
+ if (ImGui::IsWindowAppearing())
+ ImGui::SetKeyboardFocusHere();
if (ImGui::InputText("##search", search.input, sizeof(search.input),
ImGuiInputTextFlags_EnterReturnsTrue))
search.dirty = true;
@@ -156,35 +185,62 @@ void showSearchBar() {
search.dirty = false;
Common::String query(search.input);
query.toLowercase();
- if (!query.empty())
+ if (query.empty()) {
+ // clear results immediately when the input is erased
+ search.results.clear();
+ _state->_dbg._highlightQuery = "";
+ } else {
runSearch(query, (SearchMode)search.mode);
+ }
}
- // display results
ImGui::Separator();
ImGui::Text("Results: %d", (int)search.results.size());
ImGui::Separator();
- if (ImGui::BeginTable("##results", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg)) {
- ImGui::TableSetupColumn("Handler", 0, 240.f);
- ImGui::TableSetupColumn("Cast", ImGuiTableColumnFlags_WidthStretch, 240.f);
+ ImVec2 tableSize = ImGui::GetContentRegionAvail();
+ if (ImGui::BeginTable("##results", 3,
+ ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit |
+ ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg |
+ ImGuiTableFlags_ScrollY, tableSize)) {
+ ImGui::TableSetupScrollFreeze(0, 1);
+ ImGui::TableSetupColumn("Handler", 0, 200.f);
+ ImGui::TableSetupColumn("Type", 0, 75.f);
+ ImGui::TableSetupColumn("Cast Member", ImGuiTableColumnFlags_WidthStretch, 200.f);
ImGui::TableHeadersRow();
for (int i = 0; i < (int)search.results.size(); i++) {
- auto &script = search.results[i];
+ ImGuiScript &script = search.results[i];
ImGui::PushID(i);
ImGui::TableNextRow();
ImGui::TableNextColumn();
- if (ImGui::Selectable(script.handlerName.c_str())) {
+
+ if (ImGui::Selectable(script.handlerName.c_str(), false,
+ ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap)) {
Common::String q(search.input);
q.toLowercase();
_state->_dbg._highlightQuery = q;
-
addToOpenHandlers(script);
_state->_dbg._goToDefinition = true;
}
+
+ ImGui::TableNextColumn();
+ ImGui::TextUnformatted(scriptType2str(script.type));
+
ImGui::TableNextColumn();
- ImGui::Text("%s", script.id.asString().c_str());
+ // show human-readable cast member name, falling back to the ID string
+ Common::String castLabel = script.id.asString();
+ Cast *resCast = nullptr;
+ if (script.id.castLib == SHARED_CAST_LIB)
+ resCast = movie->getSharedCast();
+ else
+ resCast = movie->getCasts()->getValOrDefault(script.id.castLib, nullptr);
+ if (resCast) {
+ CastMember *cm = resCast->getCastMember(script.id.member, false);
+ if (cm) castLabel = getDisplayName(cm);
+ }
+ ImGui::TextUnformatted(castLabel.c_str());
+
ImGui::PopID();
}
ImGui::EndTable();
diff --git a/engines/director/lingo/lingo-object.h b/engines/director/lingo/lingo-object.h
index 335a9846969..ebd29576ad4 100644
--- a/engines/director/lingo/lingo-object.h
+++ b/engines/director/lingo/lingo-object.h
@@ -239,6 +239,8 @@ public:
bool isFactory() const { return _objType == kFactoryObj; };
void setFactory(bool flag) { _objType = flag ? kFactoryObj : kScriptObj; }
+ const Common::Array<Common::String> &getPropertyNames() const { return _propertyNames; }
+
void setOnlyInLctxContexts() { _onlyInLctxContexts = true; }
bool getOnlyInLctxContexts() { return _onlyInLctxContexts; }
Commit: 5f01c272c1508d470f7a8d468cfe12fa0beb2ad4
https://github.com/scummvm/scummvm/commit/5f01c272c1508d470f7a8d468cfe12fa0beb2ad4
Author: ramyak-sharma (ramyaksharma1 at gmail.com)
Date: 2026-06-07T21:32:37+02:00
Commit Message:
DIRECTOR: DT: add Windows panel showing loaded windows and all movies
Changed paths:
engines/director/cast.cpp
engines/director/debugger/debugtools.cpp
engines/director/debugger/dt-internal.h
engines/director/debugger/dt-lists.cpp
engines/director/debugger/dt-save-state.cpp
diff --git a/engines/director/cast.cpp b/engines/director/cast.cpp
index 1915d5d1558..f9001f7009a 100644
--- a/engines/director/cast.cpp
+++ b/engines/director/cast.cpp
@@ -314,7 +314,8 @@ void Cast::setArchive(Common::SharedPtr<Archive> archive) {
}
void Cast::loadArchive() {
- loadConfig();
+ if (!loadConfig())
+ return;
loadCast();
}
@@ -527,8 +528,11 @@ bool Cast::loadConfig() {
//Calculation and verification of checksum
uint32 check = computeChecksum();
- if (check != _checksum)
- warning("BUILDBOT: The checksum for this VWCF resource is incorrect. Got %04x, but expected %04x", check, _checksum);
+ if (check != _checksum) {
+ warning("BUILDBOT: The checksum for this VWCF resource is incorrect. Got %08x, but expected %08x", check, _checksum);
+ delete stream;
+ return false;
+ }
if (_version >= kFileVer400 && _version < kFileVer500) {
_field30 = stream->readSint16();
diff --git a/engines/director/debugger/debugtools.cpp b/engines/director/debugger/debugtools.cpp
index 6512c3e3eaf..eac525112e0 100644
--- a/engines/director/debugger/debugtools.cpp
+++ b/engines/director/debugger/debugtools.cpp
@@ -916,6 +916,7 @@ void onImGuiRender() {
ImGui::MenuItem("Watched Vars", NULL, &_state->_w.watchedVars);
ImGui::MenuItem("Logger", NULL, &_state->_w.logger);
ImGui::MenuItem("Archive", NULL, &_state->_w.archive);
+ ImGui::MenuItem("Windows", NULL, &_state->_w.windows);
ImGui::MenuItem("Execution Context", NULL, &_state->_w.executionContext);
ImGui::SeparatorText("Misc");
@@ -949,6 +950,7 @@ void onImGuiRender() {
showBreakpointList();
showSettings();
showArchive();
+ showWindows();
showWatchedVars();
_state->_logger->draw("Logger", &_state->_w.logger);
}
diff --git a/engines/director/debugger/dt-internal.h b/engines/director/debugger/dt-internal.h
index f1b51776c1d..1372e834365 100644
--- a/engines/director/debugger/dt-internal.h
+++ b/engines/director/debugger/dt-internal.h
@@ -99,6 +99,7 @@ typedef struct ImGuiWindows {
bool executionContext = false;
bool search = false;
bool imageViewer = false;
+ bool windows = false;
} ImGuiWindows;
@@ -373,6 +374,7 @@ void showVars();
void showWatchedVars();
void showBreakpointList();
void showArchive();
+void showWindows();
// dt-score.cpp
void showScore();
diff --git a/engines/director/debugger/dt-lists.cpp b/engines/director/debugger/dt-lists.cpp
index a88aecd4615..7208a81c51d 100644
--- a/engines/director/debugger/dt-lists.cpp
+++ b/engines/director/debugger/dt-lists.cpp
@@ -20,12 +20,18 @@
*/
#include "director/director.h"
+#include "common/archive.h"
#include "director/archive.h"
+#include "director/cast.h"
#include "director/debugger.h"
#include "director/debugger/dt-internal.h"
-
+#include "director/movie.h"
+#include "director/score.h"
+#include "director/window.h"
#include "director/lingo/lingo-object.h"
+#include "graphics/macgui/macwindow.h"
+
namespace Director {
namespace DT {
@@ -355,6 +361,152 @@ void showArchive() {
ImGui::End();
}
+void showWindows() {
+ if (!_state->_w.windows)
+ return;
+
+ ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(700, 280), ImGuiCond_FirstUseEver);
+
+ if (!ImGui::Begin("Windows", &_state->_w.windows)) {
+ ImGui::End();
+ return;
+ }
+
+ // Stage is not in getWindowList() â it must be prepended separately
+ Common::Array<Window *> allWindows;
+ allWindows.push_back(g_director->getStage());
+ for (auto w : *g_director->getWindowList())
+ allWindows.push_back(w);
+
+ float availH = ImGui::GetContentRegionAvail().y;
+ ImVec2 tableSize(0, availH * 0.5f);
+ if (ImGui::BeginTable("##windowtable", 6,
+ ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
+ ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable |
+ ImGuiTableFlags_ScrollY, tableSize)) {
+ ImGui::TableSetupScrollFreeze(0, 1);
+ ImGui::TableSetupColumn("Title", 0, 100.f);
+ ImGui::TableSetupColumn("Movie", 0, 130.f);
+ ImGui::TableSetupColumn("Filename", ImGuiTableColumnFlags_WidthStretch, 160.f);
+ ImGui::TableSetupColumn("State", 0, 75.f);
+ ImGui::TableSetupColumn("Frame", 0, 55.f);
+ ImGui::TableSetupColumn("Shared Cast", ImGuiTableColumnFlags_WidthStretch, 140.f);
+ ImGui::TableHeadersRow();
+
+ for (uint i = 0; i < allWindows.size(); i++) {
+ Window *window = allWindows[i];
+ ImGui::PushID((int)i);
+ ImGui::TableNextRow();
+
+ ImGui::TableNextColumn();
+ bool isStage = (window == g_director->getStage());
+ const char *title = isStage ? "(stage)" :
+ (window->getMacWindow() ? window->getMacWindow()->getTitle().c_str() : "");
+ ImGui::TextUnformatted(title);
+
+ Movie *movie = window->getCurrentMovie();
+
+ ImGui::TableNextColumn();
+ if (movie)
+ ImGui::TextUnformatted(movie->getMacName().c_str());
+ else
+ ImGui::TextDisabled("(none)");
+
+ ImGui::TableNextColumn();
+ Common::String filename = window->getFileName();
+ if (!filename.empty())
+ ImGui::TextUnformatted(filename.c_str());
+ else if (!window->getCurrentPath().empty())
+ ImGui::TextUnformatted(window->getCurrentPath().c_str());
+ else
+ ImGui::TextDisabled("(none)");
+
+ ImGui::TableNextColumn();
+ if (movie) {
+ Score *score = movie->getScore();
+ if (score) {
+ const char *stateStr = "unknown";
+ switch (score->_playState) {
+ case kPlayNotStarted: stateStr = "not started"; break;
+ case kPlayStarted: stateStr = "playing"; break;
+ case kPlayStopped: stateStr = "stopped"; break;
+ case kPlayPaused: stateStr = "paused"; break;
+ default: stateStr = "other"; break;
+ }
+ ImGui::TextUnformatted(stateStr);
+ }
+ } else {
+ ImGui::TextDisabled("-");
+ }
+
+ ImGui::TableNextColumn();
+ if (movie) {
+ Score *score = movie->getScore();
+ if (score)
+ ImGui::Text("%d / %d", score->getCurrentFrameNum(), score->getFramesNum());
+ else
+ ImGui::TextDisabled("-");
+ } else {
+ ImGui::TextDisabled("-");
+ }
+
+ ImGui::TableNextColumn();
+ Cast *sharedCast = movie ? movie->getSharedCast() : nullptr;
+ if (sharedCast && sharedCast->getArchive())
+ ImGui::TextUnformatted(sharedCast->getArchive()->getPathName().toString().c_str());
+ else
+ ImGui::TextDisabled("(none)");
+
+ ImGui::PopID();
+ }
+
+ ImGui::EndTable();
+ }
+
+ ImGui::SeparatorText("All Movies");
+
+ Common::ArchiveMemberList dirFiles;
+ SearchMan.listMatchingMembers(dirFiles, "*.dir");
+ SearchMan.listMatchingMembers(dirFiles, "*.DIR");
+
+ // deduplicate by name
+ Common::HashMap<Common::String, bool, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> seen;
+ Common::ArchiveMemberList uniqueFiles;
+ for (auto &f : dirFiles) {
+ if (!seen.contains(f->getName())) {
+ seen[f->getName()] = true;
+ uniqueFiles.push_back(f);
+ }
+ }
+
+ ImGui::Text("%d movies found", (int)uniqueFiles.size());
+
+ if (ImGui::BeginTable("##allfiles", 1,
+ ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
+ ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_ScrollY,
+ ImVec2(0, ImGui::GetContentRegionAvail().y))) {
+ ImGui::TableSetupScrollFreeze(0, 1);
+ ImGui::TableSetupColumn("Filename", ImGuiTableColumnFlags_WidthStretch);
+ ImGui::TableHeadersRow();
+
+ for (auto &f : uniqueFiles) {
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ if (ImGui::Selectable(f->getName().c_str(), false, ImGuiSelectableFlags_SpanAllColumns)) {
+ Datum frame, movie;
+ movie.type = STRING;
+ movie.u.s = new Common::String(f->getName());
+ g_lingo->func_goto(frame, movie);
+ }
+ }
+
+ ImGui::EndTable();
+ }
+
+ ImGui::End();
+}
+
} // namespace DT
} // namespace Director
diff --git a/engines/director/debugger/dt-save-state.cpp b/engines/director/debugger/dt-save-state.cpp
index e8088fc94e0..689977fd4f9 100644
--- a/engines/director/debugger/dt-save-state.cpp
+++ b/engines/director/debugger/dt-save-state.cpp
@@ -49,6 +49,7 @@ Common::Array<WindowFlag> getWindowFlags() {
{ "Settings", &_state->_w.settings },
{ "Vars", &_state->_w.vars },
{ "Watched Vars", &_state->_w.watchedVars },
+ { "Windows", &_state->_w.windows },
};
}
More information about the Scummvm-git-logs
mailing list