[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