[Scummvm-git-logs] scummvm master -> a34f4b36359944147f0b05823d4297a66bbd2ab4
scemino
noreply at scummvm.org
Wed May 8 12:57:16 UTC 2024
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
a34f4b3635 DIRECTOR: Add script in function list
Commit: a34f4b36359944147f0b05823d4297a66bbd2ab4
https://github.com/scummvm/scummvm/commit/a34f4b36359944147f0b05823d4297a66bbd2ab4
Author: scemino (scemino74 at gmail.com)
Date: 2024-05-08T14:57:02+02:00
Commit Message:
DIRECTOR: Add script in function list
Changed paths:
engines/director/debugtools.cpp
diff --git a/engines/director/debugtools.cpp b/engines/director/debugtools.cpp
index a9c2299d0fc..a3e46748ec2 100644
--- a/engines/director/debugtools.cpp
+++ b/engines/director/debugtools.cpp
@@ -53,6 +53,28 @@ typedef struct ImGuiImage {
int16 height;
} ImGuiImage;
+typedef struct ImGuiScriptCode {
+ uint pc;
+ Common::String code;
+} ImGuiScriptCode;
+
+typedef struct ImGuiScript {
+ bool score = false;
+ CastMemberID id;
+ ScriptType type;
+ Common::String handlerId;
+ Common::String handlerName;
+ Common::String moviePath;
+ Common::Array<ImGuiScriptCode> code;
+
+ bool operator==(const ImGuiScript &c) const {
+ return moviePath == c.moviePath && score == c.score && id == c.id && type == c.type && handlerId == c.handlerId;
+ }
+ bool operator!=(const ImGuiScript &c) const {
+ return !(*this == c);
+ }
+} ImGuiScript;
+
typedef struct ImGuiState {
struct {
Common::HashMap<Graphics::Surface *, ImGuiImage> _textures;
@@ -61,6 +83,11 @@ typedef struct ImGuiState {
ImGuiTextFilter _nameFilter;
int _typeFilter = 0x7FFF;
} _cast;
+ struct {
+ ImGuiScript _script;
+ ImGuiTextFilter _nameFilter;
+ bool _showScript = false;
+ } _functions;
bool _showControlPanel = true;
bool _showCallStack = false;
bool _showVars = false;
@@ -552,6 +579,11 @@ static void addScriptCastToDisplay(CastMemberID &id) {
_state->_scriptCasts.push_back(id);
}
+static void setScriptToDisplay(ImGuiScript &script) {
+ _state->_functions._script = script;
+ _state->_functions._showScript = true;
+}
+
static void showChannels() {
if (!_state->_showChannels)
return;
@@ -681,7 +713,7 @@ static void showChannels() {
ImGui::End();
}
-static void renderScript(Symbol &sym) {
+static void renderCastScript(Symbol &sym) {
if (sym.type != HANDLER)
return;
@@ -741,6 +773,50 @@ static void renderScript(Symbol &sym) {
}
}
+static void renderScript(ImGuiScript &script) {
+ ImDrawList *dl = ImGui::GetWindowDrawList();
+
+ const ImU32 bp_color_disabled = ImGui::GetColorU32(ImVec4(0.9f, 0.08f, 0.0f, 0.0f));
+ const ImU32 bp_color_enabled = ImGui::GetColorU32(ImVec4(0.9f, 0.08f, 0.0f, 1.0f));
+ const ImU32 bp_color_hover = ImGui::GetColorU32(ImVec4(0.42f, 0.17f, 0.13f, 1.0f));
+ const ImU32 line_color = ImGui::GetColorU32(ImVec4(0.44f, 0.44f, 0.44f, 1.0f));
+ ImU32 color;
+
+ for (const auto& line : script.code) {
+ ImVec2 pos = ImGui::GetCursorScreenPos();
+ const ImVec2 mid(pos.x + 7, pos.y + 7);
+ Common::String bpName = Common::String::format("%s-%d", script.handlerId.c_str(), line.pc);
+
+ color = bp_color_disabled;
+
+ if (_state->_breakpoints.contains(bpName))
+ color = bp_color_enabled;
+
+ ImGui::InvisibleButton("Line", ImVec2(16, ImGui::GetFontSize()));
+ if (ImGui::IsItemClicked(0)) {
+ if (color == bp_color_enabled) {
+ _state->_breakpoints.erase(bpName);
+ color = bp_color_disabled;
+ } else {
+ _state->_breakpoints[bpName] = true;
+ color = bp_color_enabled;
+ }
+ }
+
+ if (color == bp_color_disabled && ImGui::IsItemHovered()) {
+ color = bp_color_hover;
+ }
+
+ dl->AddCircleFilled(mid, 4.0f, color);
+ dl->AddLine(ImVec2(pos.x + 16.0f, pos.y), ImVec2(pos.x + 16.0f, pos.y + 17), line_color);
+
+ ImGui::SetItemTooltip("Click to add a breakpoint");
+
+ ImGui::SameLine();
+ ImGui::Text("[%5d] %s", line.pc, line.code.c_str());
+ }
+}
+
static bool showScriptCast(CastMemberID &id) {
Common::String wName("Script ");
wName += id.asString();
@@ -756,16 +832,15 @@ static bool showScriptCast(CastMemberID &id) {
if (ctx) {
for (auto &handler : ctx->_functionHandlers)
- renderScript(handler._value);
+ renderCastScript(handler._value);
} else if (cast->_lingoArchive->factoryContexts.contains(id.member)) {
for (auto &it : *cast->_lingoArchive->factoryContexts.getVal(id.member)) {
for (auto &handler : it._value->_functionHandlers)
- renderScript(handler._value);
+ renderCastScript(handler._value);
}
} else {
ImGui::Text("[Nothing]");
}
-
}
ImGui::End();
@@ -782,7 +857,7 @@ static void displayScriptCasts() {
if (_state->_scriptCasts.empty())
return;
- for (Common::List<CastMemberID>::iterator scr = _state->_scriptCasts.begin(); scr != _state->_scriptCasts.end(); ) {
+ for (Common::List<CastMemberID>::iterator scr = _state->_scriptCasts.begin(); scr != _state->_scriptCasts.end();) {
if (!showScriptCast(*scr))
scr = _state->_scriptCasts.erase(scr);
else
@@ -790,56 +865,173 @@ static void displayScriptCasts() {
}
}
+static void displayScripts() {
+ if (!_state->_functions._showScript)
+ return;
+
+ ImGui::SetNextWindowPos(ImVec2(20, 160), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(240, 240), ImGuiCond_FirstUseEver);
+
+ if (ImGui::Begin("Script", &_state->_functions._showScript)) {
+ ImGui::Text("%s", _state->_functions._script.handlerName.c_str());
+ renderScript(_state->_functions._script);
+ }
+ ImGui::End();
+}
+
+static void getScriptCode(ImGuiScript& script, Symbol &sym) {
+ uint pc = 0;
+ while (pc < sym.u.defn->size()) {
+ script.code.push_back({pc, g_lingo->decodeInstruction(sym.u.defn, pc, &pc)});
+ }
+}
+
+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;
+}
+
static void showFuncList() {
if (!_state->_showFuncList)
return;
ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver);
- ImGui::SetNextWindowSize(ImVec2(120, 120), ImGuiCond_FirstUseEver);
+ ImGui::SetNextWindowSize(ImVec2(480, 240), ImGuiCond_FirstUseEver);
if (ImGui::Begin("Functions", &_state->_showFuncList)) {
Lingo *lingo = g_director->getLingo();
Movie *movie = g_director->getCurrentMovie();
- Score *score = movie->getScore();
ScriptContext *csc = lingo->_state->context;
- if (ImGui::TreeNode("Functions attached to current frame")) {
- ImGui::Text("Frame %d:", score->getCurrentFrameNum());
+
+ _state->_functions._nameFilter.Draw();
+ ImGui::Separator();
+ 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();
+
if (csc) {
- ImGui::Text(" %d: %s", csc->_id, csc->formatFunctionList(" ").c_str());
- } else {
- ImGui::Text(" [empty]");
- }
- ImGui::TreePop();
- }
+ Common::String scriptType(scriptType2str(csc->_scriptType));
+ for (auto &functionHandler : csc->_functionHandlers) {
+ Common::String function(g_lingo->formatFunctionName(functionHandler._value));
+ if (!_state->_functions._nameFilter.PassFilter(function.c_str()))
+ continue;
- ImGui::SetNextItemOpen(true, ImGuiCond_Once);
- if (ImGui::TreeNode("Cast functions")) {
- for (auto it : *movie->getCasts()) {
- Common::String header = Common::String::format("Cast %d functions", it._key);
- if (ImGui::TreeNode(header.c_str())) {
- Cast *cast = it._value;
- if (cast && cast->_lingoArchive) {
- ImGui::Text("%s", cast->_lingoArchive->formatFunctionList(" ").c_str());
- } else {
- ImGui::Text(" [empty]");
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn();
+ if(ImGui::Selectable(function.c_str())) {
+ ImGuiScript script;
+ script.moviePath = movie->getArchive()->getPathName().toString();
+ script.score = true;
+ script.type = csc->_scriptType;
+ script.handlerId = functionHandler._key;
+ script.handlerName = getHandlerName(functionHandler._value);
+ getScriptCode(script, functionHandler._value);
+ setScriptToDisplay(script);
}
+ ImGui::TableNextColumn();
+ ImGui::Text("%s", movie->getArchive()->getPathName().toString().c_str());
+ ImGui::TableNextColumn();
+ ImGui::Text("-");
+ ImGui::TableNextColumn();
+ ImGui::Text("%s", scriptType.c_str());
- ImGui::TreePop();
}
}
- ImGui::TreePop();
- }
- ImGui::SetNextItemOpen(true, ImGuiCond_Once);
- if (ImGui::TreeNode("Shared cast functions")) {
+ 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;
+ script.moviePath = movie->getArchive()->getPathName().toString();
+ script.id = memberID;
+ script.type = (ScriptType)i;
+ script.handlerId = functionHandler._key;
+ script.handlerName = getHandlerName(functionHandler._value);
+ getScriptCode(script, functionHandler._value);
+ setScriptToDisplay(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());
+
+ }
+ }
+ }
+ }
+
Cast *sharedCast = movie->getSharedCast();
if (sharedCast && sharedCast->_lingoArchive) {
- ImGui::Text("%s", sharedCast->_lingoArchive->formatFunctionList(" ").c_str());
- } else {
- ImGui::Text(" [empty]");
+ 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;
+ script.moviePath = movie->getArchive()->getPathName().toString();
+ script.id = memberID;
+ script.type = (ScriptType)i;
+ script.handlerId = functionHandler._key;
+ script.handlerName = getHandlerName(functionHandler._value);
+ getScriptCode(script, functionHandler._value);
+ setScriptToDisplay(script);
+ }
+ 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::EndTable();
}
+ ImGui::EndChild();
}
ImGui::End();
}
@@ -887,6 +1079,7 @@ void onImGuiRender() {
}
displayScriptCasts();
+ displayScripts();
showControlPanel();
showVars();
More information about the Scummvm-git-logs
mailing list