[Scummvm-git-logs] scummvm master -> f596c31c95abfbe0c6e4dd5aebd27910adb6cc31
scemino
noreply at scummvm.org
Sat Jun 1 06:11:05 UTC 2024
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
be8a1a26a7 DIRECTOR: Fix script navigation during debug
f14f4e32aa DIRECTOR: Add script decompiler for D2 and D3
23c472d3b8 DIRECTOR: Add indentation in script for D2 and D3
f596c31c95 DIRECTOR: Add syntax highlighting in script for D2 and D3
Commit: be8a1a26a72b31e46c39f5bfaeb03bdd36fbb732
https://github.com/scummvm/scummvm/commit/be8a1a26a72b31e46c39f5bfaeb03bdd36fbb732
Author: scemino (scemino74 at gmail.com)
Date: 2024-06-01T07:51:02+02:00
Commit Message:
DIRECTOR: Fix script navigation during debug
Changed paths:
engines/director/debugtools.cpp
diff --git a/engines/director/debugtools.cpp b/engines/director/debugtools.cpp
index 424a2ba0982..bd700121c5e 100644
--- a/engines/director/debugtools.cpp
+++ b/engines/director/debugtools.cpp
@@ -379,6 +379,7 @@ typedef struct ImGuiState {
struct {
uint _lastLinePC = 0;
uint _callstackSize = 0;
+ bool _isScriptDirty = false; // indicates whether or not we have to display the script corresponding to the current stackframe
} _dbg;
struct {
@@ -1626,7 +1627,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 (!ImGui::IsItemVisible()) {
+ if (_state->_dbg._isScriptDirty && !ImGui::IsItemVisible()) {
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);
@@ -1727,6 +1728,36 @@ static bool stepOutShouldPause() {
return false;
}
+static void dgbStop() {
+ g_lingo->_exec._state = kPause;
+ g_lingo->_exec._shouldPause = nullptr;
+ _state->_dbg._isScriptDirty = true;
+}
+
+static void dbgStepOver() {
+ g_lingo->_exec._state = kRunning;
+ _state->_dbg._lastLinePC = getLineFromPC();
+ _state->_dbg._callstackSize = g_lingo->_state->callstack.size();
+ g_lingo->_exec._shouldPause = stepOverShouldPauseDebugger;
+ _state->_dbg._isScriptDirty = true;
+}
+
+static void dbgStepInto() {
+ g_lingo->_exec._state = kRunning;
+ _state->_dbg._lastLinePC = getLineFromPC();
+ _state->_dbg._callstackSize = g_lingo->_state->callstack.size();
+ g_lingo->_exec._shouldPause = stepInShouldPauseDebugger;
+ _state->_dbg._isScriptDirty = true;
+}
+
+static void dbgStepOut() {
+ g_lingo->_exec._state = kRunning;
+ _state->_dbg._lastLinePC = getLineFromPC();
+ _state->_dbg._callstackSize = g_lingo->_state->callstack.size();
+ g_lingo->_exec._shouldPause = stepOutShouldPause;
+ _state->_dbg._isScriptDirty = true;
+}
+
static void showControlPanel() {
if (!_state->_w.controlPanel)
return;
@@ -1802,6 +1833,7 @@ static void showControlPanel() {
score->_playState = kPlayPaused;
g_lingo->_exec._state = kPause;
g_lingo->_exec._shouldPause = nullptr;
+ _state->_dbg._isScriptDirty = true;
}
if (ImGui::IsItemHovered())
@@ -1878,10 +1910,11 @@ static void showControlPanel() {
if (ImGui::IsItemClicked(0)) {
score->_playState = kPlayStarted;
- g_lingo->_exec._state = kRunning;
- _state->_dbg._lastLinePC = getLineFromPC();
- _state->_dbg._callstackSize = g_lingo->_state->callstack.size();
- g_lingo->_exec._shouldPause = stepOverShouldPauseDebugger;
+ if (g_lingo->_exec._state == kRunning) {
+ dgbStop();
+ } else {
+ dbgStepOver();
+ }
}
if (ImGui::IsItemHovered())
@@ -1903,10 +1936,11 @@ static void showControlPanel() {
if (ImGui::IsItemClicked(0)) {
score->_playState = kPlayStarted;
- g_lingo->_exec._state = kRunning;
- _state->_dbg._lastLinePC = getLineFromPC();
- _state->_dbg._callstackSize = g_lingo->_state->callstack.size();
- g_lingo->_exec._shouldPause = stepInShouldPauseDebugger;
+ if (g_lingo->_exec._state == kRunning) {
+ dgbStop();
+ } else {
+ dbgStepInto();
+ }
}
if (ImGui::IsItemHovered())
@@ -1927,10 +1961,11 @@ static void showControlPanel() {
if (ImGui::IsItemClicked(0)) {
score->_playState = kPlayStarted;
- g_lingo->_exec._state = kRunning;
- _state->_dbg._lastLinePC = getLineFromPC();
- _state->_dbg._callstackSize = g_lingo->_state->callstack.size();
- g_lingo->_exec._shouldPause = stepOutShouldPause;
+ if (g_lingo->_exec._state == kRunning) {
+ dgbStop();
+ } else {
+ dbgStepOut();
+ }
}
if (ImGui::IsItemHovered())
@@ -2603,6 +2638,7 @@ static void renderScript(ImGuiScript &script, bool showByteCode) {
RenderScriptVisitor visitor(script, showByteCode);
script.root->accept(visitor);
+ _state->_dbg._isScriptDirty = false;
}
static bool showScriptCast(CastMemberID &id) {
@@ -2654,7 +2690,7 @@ static void displayScriptCasts() {
}
static void updateCurrentScript() {
- if (g_lingo->_exec._state != kPause)
+ if ((g_lingo->_exec._state != kPause) || !_state->_dbg._isScriptDirty)
return;
Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
Commit: f14f4e32aa43e0e9c963a613e38ced3d11df8e6a
https://github.com/scummvm/scummvm/commit/f14f4e32aa43e0e9c963a613e38ced3d11df8e6a
Author: scemino (scemino74 at gmail.com)
Date: 2024-06-01T07:51:02+02:00
Commit Message:
DIRECTOR: Add script decompiler for D2 and D3
Changed paths:
engines/director/debugtools.cpp
engines/director/lingo/lingo-ast.h
engines/director/lingo/lingo-codegen.cpp
engines/director/lingo/lingo-codegen.h
engines/director/lingo/lingo-gr.cpp
engines/director/lingo/lingo-gr.y
engines/director/lingo/lingo-object.cpp
engines/director/lingo/lingo-object.h
diff --git a/engines/director/debugtools.cpp b/engines/director/debugtools.cpp
index bd700121c5e..a66a9a21606 100644
--- a/engines/director/debugtools.cpp
+++ b/engines/director/debugtools.cpp
@@ -32,7 +32,10 @@
#include "director/director.h"
#include "director/lingo/lingo.h"
+#include "director/lingo/lingo-ast.h"
+#include "director/lingo/lingo-code.h"
#include "director/lingo/lingo-object.h"
+#include "director/lingo/lingo-the.h"
#include "director/lingo/lingodec/ast.h"
#include "director/lingo/lingodec/codewritervisitor.h"
#include "director/lingo/lingodec/context.h"
@@ -90,7 +93,7 @@ typedef struct ImGuiScript {
Common::SharedPtr<LingoDec::HandlerNode> root;
Common::Array<LingoDec::Bytecode> bytecodeArray;
Common::Array<uint> startOffsets;
-
+ Common::SharedPtr<Node> oldAst;
bool operator==(const ImGuiScript &c) const {
return moviePath == c.moviePath && score == c.score && id == c.id && handlerId == c.handlerId;
@@ -443,6 +446,9 @@ const LingoDec::Handler *getHandler(const Cast *cast, CastMemberID id, const Com
const ScriptContext *ctx = cast->_lingoArchive->findScriptContext(id.member);
if (!ctx || !ctx->_functionHandlers.contains(handlerId))
return nullptr;
+ // for the moment it's happening with Director version < 4
+ if (!cast->_lingodec)
+ return nullptr;
for (auto p : cast->_lingodec->scripts) {
if ((p.second->castID & 0xFFFF) != id.member)
continue;
@@ -467,14 +473,24 @@ const LingoDec::Handler *getHandler(CastMemberID id, const Common::String &handl
return getHandler(movie->getSharedCast(), id, handlerId);
}
-ImGuiScript toImGuiScript(CastMemberID id, const Common::String &handlerId) {
+ImGuiScript toImGuiScript(ScriptType scriptType, CastMemberID id, const Common::String &handlerId) {
ImGuiScript result;
result.id = id;
result.handlerId = handlerId;
+ result.type = scriptType;
const LingoDec::Handler *handler = getHandler(id, handlerId);
- if (!handler)
+ if (!handler) {
+ const ScriptContext *ctx;
+ if (id.castLib == SHARED_CAST_LIB) {
+ ctx = g_director->getCurrentMovie()->getSharedCast()->_lingoArchive->getScriptContext(scriptType, id.member);
+ } else {
+ ctx = g_director->getCurrentMovie()->getScriptContext(scriptType, id);
+ }
+ if (!ctx) return result;
+ result.oldAst = ctx->_assemblyAST;
return result;
+ }
result.bytecodeArray = handler->bytecodeArray;
result.root = handler->ast.root;
@@ -503,9 +519,583 @@ static Director::Breakpoint *getBreakpoint(const Common::String &handlerName, ui
return nullptr;
}
+class RenderOldScriptVisitor : public NodeVisitor {
+private:
+ ImGuiScript &_script;
+
+public:
+ explicit RenderOldScriptVisitor(ImGuiScript &script) : _script(script) {}
+
+ virtual bool visitHandlerNode(HandlerNode *node) {
+ ImGui::Text("on %s", node->name->c_str());
+ if(!node->args->empty()) {
+ ImGui::SameLine();
+ ImGui::Text(" ");
+ ImGui::SameLine();
+ for (uint i = 0; i < node->args->size(); i++) {
+ Common::String *arg = (*node->args)[i];
+ ImGui::Text("%s", arg->c_str());
+ ImGui::SameLine();
+ if (i != (node->args->size() - 1)) {
+ ImGui::Text(", ");
+ ImGui::SameLine();
+ }
+ }
+ ImGui::NewLine();
+ }
+ for (uint i = 0; i < node->stmts->size(); i++) {
+ Node *stmt = (*node->stmts)[i];
+ stmt->accept(this);
+ ImGui::NewLine();
+ }
+ ImGui::Text("end");
+ return true;
+ }
+
+ virtual bool visitScriptNode(ScriptNode *node){
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2());
+ for(Node* child : *node->children) {
+ if(child->type == kHandlerNode && *((HandlerNode*)child)->name != _script.handlerId) continue;
+ child->accept(this);
+ }
+ ImGui::PopStyleVar();
+ return true;
+ }
+ virtual bool visitFactoryNode(FactoryNode *node){
+ ImGui::Text("factory %s", node->name->c_str());
+ ImGui::SameLine();
+ for (uint i = 0; i < node->methods->size(); i++) {
+ Node *method = (*node->methods)[i];
+ method->accept(this);
+ ImGui::NewLine();
+ }
+ return true;
+ }
+ virtual bool visitCmdNode(CmdNode *node) {
+ ImGui::Text("%s ", node->name->c_str());
+ ImGui::SameLine();
+ if(*node->name == "go") {
+ ImGui::Text("to ");
+ ImGui::SameLine();
+ }
+ for (uint i = 0; i < node->args->size(); i++) {
+ Node *arg = (*node->args)[i];
+ if ((i != 0) || (node->args->size() < 2) || ((*node->args)[1]->type != kMovieNode)) {
+ arg->accept(this);
+ ImGui::SameLine();
+ if (i != (node->args->size() - 1)) {
+ ImGui::Text(", ");
+ ImGui::SameLine();
+ }
+ }
+ }
+ return true;
+ }
+ virtual bool visitPutIntoNode(PutIntoNode *node){
+ ImGui::Text("put ");
+ ImGui::SameLine();
+ node->val->accept(this);
+ ImGui::Text(" into ");
+ ImGui::SameLine();
+ node->var->accept(this);
+ return true;
+ }
+ virtual bool visitPutAfterNode(PutAfterNode *node) {
+ ImGui::Text("put ");
+ ImGui::SameLine();
+ node->val->accept(this);
+ ImGui::Text(" after ");
+ ImGui::SameLine();
+ node->var->accept(this);
+ return true;
+ }
+ virtual bool visitPutBeforeNode(PutBeforeNode *node){
+ ImGui::Text("put ");
+ ImGui::SameLine();
+ node->val->accept(this);
+ ImGui::Text(" before ");
+ ImGui::SameLine();
+ node->var->accept(this);
+ return true;
+ }
+ virtual bool visitSetNode(SetNode *node){
+ ImGui::Text("set ");
+ ImGui::SameLine();
+ node->val->accept(this);
+ ImGui::Text(" to ");
+ ImGui::SameLine();
+ node->var->accept(this);
+ return true;
+ }
+
+ void displayDefineVar(const char *name, IDList *names) {
+ ImGui::Text("%s ", name);
+ ImGui::SameLine();
+ for (uint i = 0; i < names->size(); i++) {
+ Common::String *arg = (*names)[i];
+ ImGui::Text("%s", arg->c_str());
+ ImGui::SameLine();
+ if (i != (names->size() - 1)) {
+ ImGui::Text(" ");
+ ImGui::SameLine();
+ }
+ }
+ }
+
+ virtual bool visitGlobalNode(GlobalNode *node){
+ displayDefineVar("global ", node->names);
+ return true;
+ }
+ virtual bool visitPropertyNode(PropertyNode *node){
+ displayDefineVar("property ", node->names);
+ return true;
+ }
+ virtual bool visitInstanceNode(InstanceNode *node){
+ displayDefineVar("instance ", node->names);
+ return true;
+ }
+ virtual bool visitIfStmtNode(IfStmtNode *node){
+ ImGui::Text("if ");
+ ImGui::SameLine();
+ node->cond->accept(this);
+ ImGui::Text(" then ");
+ if(node->stmts->size() == 1) {
+ ImGui::SameLine();
+ (*node->stmts)[0]->accept(this);
+ } else {
+ for (uint i = 0; i < node->stmts->size(); i++) {
+ Node *stmt = (*node->stmts)[i];
+ stmt->accept(this);
+ ImGui::NewLine();
+ }
+ ImGui::Text("endif");
+ ImGui::SameLine();
+ }
+ return true;
+ }
+ virtual bool visitIfElseStmtNode(IfElseStmtNode *node){
+ ImGui::Text("if ");
+ ImGui::SameLine();
+ node->cond->accept(this);
+ ImGui::Text(" then ");
+ if(node->stmts1->size() == 1) {
+ ImGui::SameLine();
+ (*node->stmts1)[0]->accept(this);
+ ImGui::Text(" ");
+ ImGui::SameLine();
+ } else {
+ for (uint i = 0; i < node->stmts1->size(); i++) {
+ Node *stmt = (*node->stmts1)[i];
+ stmt->accept(this);
+ ImGui::NewLine();
+ }
+ }
+ ImGui::Text("else ");
+ if(node->stmts2->size() == 1) {
+ ImGui::SameLine();
+ (*node->stmts2)[0]->accept(this);
+ } else {
+ for (uint i = 0; i < node->stmts2->size(); i++) {
+ Node *stmt = (*node->stmts2)[i];
+ stmt->accept(this);
+ ImGui::NewLine();
+ }
+ ImGui::Text("endif");
+ ImGui::SameLine();
+ }
+ return true;
+ }
+ virtual bool visitRepeatWhileNode(RepeatWhileNode *node){
+ ImGui::Text("repeat while ");
+ ImGui::SameLine();
+ node->cond->accept(this);
+ ImGui::NewLine();
+ for (uint i = 0; i < node->stmts->size(); i++) {
+ Node *stmt = (*node->stmts)[i];
+ stmt->accept(this);
+ ImGui::NewLine();
+ }
+ ImGui::Text("endrepeat");
+ return true;
+ }
+ virtual bool visitRepeatWithToNode(RepeatWithToNode *node){
+ ImGui::Text("repeat with ");
+ ImGui::SameLine();
+ ImGui::Text("%s = ", node->var->c_str());
+ ImGui::SameLine();
+ node->start->accept(this);
+ ImGui::Text(" %s ", node->down ? "down to" : "to");
+ node->end->accept(this);
+ ImGui::NewLine();
+ for (uint i = 0; i < node->stmts->size(); i++) {
+ Node *stmt = (*node->stmts)[i];
+ stmt->accept(this);
+ ImGui::NewLine();
+ }
+ ImGui::Text("endrepeat");
+ return true;
+ }
+ virtual bool visitRepeatWithInNode(RepeatWithInNode *node){
+ ImGui::Text("repeat with ");
+ ImGui::SameLine();
+ ImGui::Text("%s in ", node->var->c_str());
+ ImGui::SameLine();
+ node->list->accept(this);
+ ImGui::NewLine();
+ for (uint i = 0; i < node->stmts->size(); i++) {
+ Node *stmt = (*node->stmts)[i];
+ stmt->accept(this);
+ ImGui::NewLine();
+ }
+ ImGui::Text("endrepeat");
+ return true;
+ }
+ virtual bool visitNextRepeatNode(NextRepeatNode *node){
+ ImGui::Text("next repeat");
+ return true;
+ }
+ virtual bool visitExitRepeatNode(ExitRepeatNode *node){
+ ImGui::Text("exit repeat");
+ return true;
+ }
+ virtual bool visitExitNode(ExitNode *node){
+ ImGui::Text("exit");
+ return true;
+ }
+ virtual bool visitReturnNode(ReturnNode *node){
+ ImGui::Text("return");
+ if(node->expr) {
+ ImGui::Text(" ");
+ ImGui::SameLine();
+ node->expr->accept(this);
+ ImGui::NewLine();
+ }
+ return true;
+ }
+ virtual bool visitTellNode(TellNode *node){
+ ImGui::Text("tell ");
+ node->target->accept(this);
+ if(node->stmts->size() == 1) {
+ ImGui::SameLine();
+ ImGui::Text(" to ");
+ ImGui::SameLine();
+ (*node->stmts)[0]->accept(this);
+ } else {
+ for (uint i = 0; i < node->stmts->size(); i++) {
+ Node *stmt = (*node->stmts)[i];
+ stmt->accept(this);
+ ImGui::NewLine();
+ }
+ ImGui::Text("endtell");
+ }
+ return true;
+ }
+ virtual bool visitWhenNode(WhenNode *node){
+ ImGui::Text("when %s then %s", node->event->c_str(), node->code->c_str());
+ ImGui::SameLine();
+ return true;
+ }
+ virtual bool visitDeleteNode(DeleteNode *node){
+ ImGui::Text("delete ");
+ ImGui::SameLine();
+ node->chunk->accept(this);
+ return true;
+ }
+ virtual bool visitHiliteNode(HiliteNode *node){
+ ImGui::Text("hilite ");
+ ImGui::SameLine();
+ node->chunk->accept(this);
+ return true;
+ }
+ virtual bool visitAssertErrorNode(AssertErrorNode *node){
+ ImGui::Text("scummvmAssertError ");
+ ImGui::SameLine();
+ node->stmt->accept(this);
+ return true;
+ }
+ virtual bool visitIntNode(IntNode *node){
+ ImGui::Text("%d", node->val);
+ ImGui::SameLine();
+ return true;
+ }
+ virtual bool visitFloatNode(FloatNode *node){
+ ImGui::Text("%g", node->val);
+ ImGui::SameLine();
+ return true;
+ }
+ virtual bool visitSymbolNode(SymbolNode *node){
+ ImGui::Text("%s", node->val->c_str());
+ ImGui::SameLine();
+ return true;
+ }
+ virtual bool visitStringNode(StringNode *node){
+ ImGui::Text("\"%s\"", node->val->c_str());
+ ImGui::SameLine();
+ return true;
+ }
+ virtual bool visitListNode(ListNode *node){
+ ImGui::Text("[");
+ ImGui::SameLine();
+ for (uint i = 0; i < node->items->size(); i++) {
+ Node *prop = (*node->items)[i];
+ prop->accept(this);
+ if (i != (node->items->size() - 1)) {
+ ImGui::Text(",");
+ ImGui::SameLine();
+ }
+ }
+ ImGui::Text("]");
+ ImGui::SameLine();
+ return true;
+ }
+ virtual bool visitPropListNode(PropListNode *node){
+ ImGui::Text("[");
+ ImGui::SameLine();
+ if(node->items->empty()) {
+ ImGui::Text(":");
+ ImGui::SameLine();
+ } else {
+ for (uint i = 0; i < node->items->size(); i++) {
+ Node *prop = (*node->items)[i];
+ prop->accept(this);
+ if (i != (node->items->size() - 1)) {
+ ImGui::Text(",");
+ ImGui::SameLine();
+ }
+ }
+ }
+ ImGui::Text("]");
+ ImGui::SameLine();
+ return true;
+ }
+ virtual bool visitPropPairNode(PropPairNode *node){
+ node->key->accept(this);
+ ImGui::Text(":");
+ ImGui::SameLine();
+ node->val->accept(this);
+ return true;
+ }
+ virtual bool visitFuncNode(FuncNode *node){
+ ImGui::Text("%s(", node->name->c_str());
+ ImGui::SameLine();
+ for (uint i = 0; i < node->args->size(); i++) {
+ Node *arg = (*node->args)[i];
+ arg->accept(this);
+ if (i != (node->args->size() - 1)) {
+ ImGui::Text(",");
+ ImGui::SameLine();
+ }
+ }
+ ImGui::Text(")");
+ ImGui::SameLine();
+ return true;
+ }
+ virtual bool visitVarNode(VarNode *node){
+ ImGui::Text("%s", node->name->c_str());
+ ImGui::SameLine();
+ return true;
+ }
+ virtual bool visitParensNode(ParensNode *node){
+ ImGui::Text("(");
+ ImGui::SameLine();
+ node->expr->accept(this);
+ ImGui::Text(")");
+ ImGui::SameLine();
+ return true;
+ }
+ virtual bool visitUnaryOpNode(UnaryOpNode *node){
+ char op = '?';
+ if(node->op == LC::c_negate) {
+ op = '-';
+ } else if(node->op == LC::c_not) {
+ op = '!';
+ }
+ ImGui::Text("%c", op);
+ ImGui::SameLine();
+ node->arg->accept(this);
+ return true;
+ }
+ virtual bool visitBinaryOpNode(BinaryOpNode *node){
+ node->a->accept(this);
+ static struct {
+ inst op;
+ const char *name;
+ } ops[] = {
+ {LC::c_add, "+"},
+ {LC::c_sub, "-"},
+ {LC::c_mul, "*"},
+ {LC::c_div, "/"},
+ {LC::c_mod, "mod"},
+ {LC::c_gt, ">"},
+ {LC::c_lt, "<"},
+ {LC::c_eq, "="},
+ {LC::c_neq, "<>"},
+ {LC::c_ge, ">="},
+ {LC::c_le, "<="},
+ {LC::c_and, "and"},
+ {LC::c_or, "or"},
+ {LC::c_ampersand, "&"},
+ {LC::c_concat, "&&"},
+ {LC::c_contains, "contains"},
+ {LC::c_starts, "starts"},
+ };
+ for (auto &op : ops) {
+ if (op.op == node->op) {
+ ImGui::Text(" %s ", op.name);
+ ImGui::SameLine();
+ break;
+ }
+ }
+ node->b->accept(this);
+ return true;
+ }
+ virtual bool visitFrameNode(FrameNode *node){
+ ImGui::Text("frame ");
+ ImGui::SameLine();
+ node->arg->accept(this);
+ return true;
+ }
+ virtual bool visitMovieNode(MovieNode *node){
+ ImGui::Text("movie ");
+ ImGui::SameLine();
+ node->arg->accept(this);
+ return true;
+ }
+ virtual bool visitIntersectsNode(IntersectsNode *node){
+ ImGui::Text("sprite ");
+ ImGui::SameLine();
+ node->sprite1->accept(this);
+ ImGui::Text("intersects ");
+ node->sprite2->accept(this);
+ return true;
+ }
+ virtual bool visitWithinNode(WithinNode *node){
+ ImGui::Text("sprite ");
+ ImGui::SameLine();
+ node->sprite1->accept(this);
+ ImGui::Text("within ");
+ node->sprite2->accept(this);
+ return true;
+ }
+ virtual bool visitTheNode(TheNode *node){
+ ImGui::Text("the %s", node->prop->c_str());
+ ImGui::SameLine();
+ return true;
+ }
+ virtual bool visitTheOfNode(TheOfNode *node){
+ ImGui::Text("the %s of ", node->prop->c_str());
+ ImGui::SameLine();
+ node->obj->accept(this);
+ return true;
+ }
+ virtual bool visitTheNumberOfNode(TheNumberOfNode *node){
+ ImGui::Text("the number of ");
+ ImGui::SameLine();
+ node->arg->accept(this);
+ return true;
+ }
+ virtual bool visitTheLastNode(TheLastNode *node){
+ // TODO: change the node to know if it's 'in' or 'of'
+ ImGui::Text("the last %s in/of ", toString(node->type).c_str());
+ ImGui::SameLine();
+ node->arg->accept(this);
+ return true;
+ }
+ virtual bool visitTheDateTimeNode(TheDateTimeNode *node){
+ const char* key1 = "";
+ switch(node->field) {
+ case kTheAbbr:
+ key1 = "abbreviated";
+ break;
+ case kTheLong:
+ key1 = "long";
+ break;
+ case kTheShort:
+ key1 = "short";
+ break;
+ }
+ const char *key2 = node->entity == kTheDate ? "date" : "time";
+ ImGui::Text("the %s %s", key1, key2);
+ ImGui::SameLine();
+ return true;
+ }
+ virtual bool visitMenuNode(MenuNode *node){
+ ImGui::Text("menu ");
+ ImGui::SameLine();
+ node->arg->accept(this);
+ return true;
+ }
+ virtual bool visitMenuItemNode(MenuItemNode *node){
+ ImGui::Text("menuitem ");
+ ImGui::SameLine();
+ node->arg1->accept(this);
+ ImGui::Text("of menu ");
+ ImGui::SameLine();
+ node->arg2->accept(this);
+ return true;
+ }
+ virtual bool visitSoundNode(SoundNode *node){
+ ImGui::Text("sound ");
+ ImGui::SameLine();
+ node->arg->accept(this);
+ return true;
+ }
+ virtual bool visitSpriteNode(SpriteNode *node){
+ ImGui::Text("sprite ");
+ ImGui::SameLine();
+ node->arg->accept(this);
+ return true;
+ }
+ virtual bool visitChunkExprNode(ChunkExprNode *node){
+ const char* key1 = "";
+ switch(node->type) {
+ case kChunkChar:
+ key1 = "char";
+ break;
+ case kChunkWord:
+ key1 = "word";
+ break;
+ case kChunkItem:
+ key1 = "item";
+ break;
+ case kChunkLine:
+ key1 = "line";
+ break;
+ }
+ ImGui::Text("%s", key1);
+ ImGui::SameLine();
+ node->start->accept(this);
+ if(node->end) {
+ ImGui::Text(" to ");
+ ImGui::SameLine();
+ node->end->accept(this);
+ }
+ ImGui::Text(" of ");
+ ImGui::SameLine();
+ node->src->accept(this);
+ return true;
+ }
+
+private:
+ static Common::String toString(ChunkType chunkType) {
+ // TODO: this method could be used in ChunkExprNode
+ switch(chunkType) {
+ case kChunkChar:
+ return "char";
+ case kChunkWord:
+ return "word";
+ case kChunkItem:
+ return "item";
+ case kChunkLine:
+ return "line";
+ }
+ return "<unknown>";
+ }
+};
+
class RenderScriptVisitor : public LingoDec::NodeVisitor {
public:
- explicit RenderScriptVisitor(ImGuiScript &script, bool showByteCode) : _script(script), _showByteCode(showByteCode) {
+ RenderScriptVisitor(ImGuiScript &script, bool showByteCode) : _script(script), _showByteCode(showByteCode) {
Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
if (!callstack.empty()) {
CFrame *head = callstack[callstack.size() - 1];
@@ -587,7 +1177,7 @@ public:
ImGui::EndTooltip();
}
if (!g_lingo->_builtinCmds.contains(node.name) && ImGui::IsItemClicked()) {
- ImGuiScript script = toImGuiScript(CastMemberID(obj, _script.id.castLib), node.name);
+ ImGuiScript script = toImGuiScript(_script.type, CastMemberID(obj, _script.id.castLib), node.name);
script.moviePath = _script.moviePath;
script.handlerName = node.name;
setScriptToDisplay(script);
@@ -2634,7 +3224,14 @@ static void renderCastScript(Symbol &sym) {
}
static void renderScript(ImGuiScript &script, bool showByteCode) {
- if (!script.root) return;
+ if (script.oldAst) {
+ RenderOldScriptVisitor oldVisitor(script);
+ script.oldAst->accept(&oldVisitor);
+ _state->_dbg._isScriptDirty = false;
+ return;
+ }
+
+ if(!script.root) return;
RenderScriptVisitor visitor(script, showByteCode);
script.root->accept(visitor);
@@ -2702,7 +3299,7 @@ static void updateCurrentScript() {
Director::Movie *movie = g_director->getCurrentMovie();
ScriptContext *scriptContext = head->sp.ctx;
int castLibID = movie->getCast()->_castLibID;
- ImGuiScript script = toImGuiScript(CastMemberID(head->sp.ctx->_id, castLibID), *head->sp.name);
+ ImGuiScript script = toImGuiScript(scriptContext->_scriptType, CastMemberID(head->sp.ctx->_id, castLibID), *head->sp.name);
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;
@@ -2819,7 +3416,7 @@ static void showFuncList() {
ImGui::TableNextColumn();
if (ImGui::Selectable(function.c_str())) {
CastMemberID memberID(scriptContext._key, cast._key);
- ImGuiScript script = toImGuiScript(memberID, functionHandler._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);
@@ -2857,7 +3454,7 @@ static void showFuncList() {
ImGui::TableNextColumn();
if (ImGui::Selectable(function.c_str())) {
CastMemberID memberID(scriptContext._key, SHARED_CAST_LIB);
- ImGuiScript script = toImGuiScript(memberID, functionHandler._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);
diff --git a/engines/director/lingo/lingo-ast.h b/engines/director/lingo/lingo-ast.h
index df828a4972a..c4d7ad48a9b 100644
--- a/engines/director/lingo/lingo-ast.h
+++ b/engines/director/lingo/lingo-ast.h
@@ -216,9 +216,7 @@ public:
};
#define VISITNODE(nodeName) \
- storeStart(); \
bool res = visitor->visit ## nodeName(this); \
- storeEnd(); \
return res
/* Node */
diff --git a/engines/director/lingo/lingo-codegen.cpp b/engines/director/lingo/lingo-codegen.cpp
index fb2c3f575d9..63f86e49b98 100644
--- a/engines/director/lingo/lingo-codegen.cpp
+++ b/engines/director/lingo/lingo-codegen.cpp
@@ -90,13 +90,16 @@ namespace Director {
return false; \
}
-void Node::storeStart() {
- startOffset = g_lingo->_compiler->_currentAssembly->size() - 1;
-}
+class NodeStore {
+public:
+ explicit NodeStore(Node *node) : _node(node) {
+ _node->startOffset = g_lingo->_compiler->_currentAssembly->size() - 1;
+ }
+ ~NodeStore() { _node->endOffset = g_lingo->_compiler->_currentAssembly->size() - 1; }
-void Node::storeEnd() {
- endOffset = g_lingo->_compiler->_currentAssembly->size() - 1;
-}
+private:
+ Node *_node = nullptr;
+};
LingoCompiler::LingoCompiler() {
_assemblyAST = nullptr;
@@ -129,6 +132,7 @@ ScriptContext *LingoCompiler::compileLingo(const Common::U32String &code, LingoA
_assemblyArchive = archive;
_assemblyAST = nullptr;
_assemblyId = id.member;
+ warning("%s: %s", scriptName.c_str(), code.encode().c_str());
ScriptContext *mainContext = _assemblyContext = new ScriptContext(scriptName, type, _assemblyId);
_currentAssembly = new ScriptData;
@@ -178,7 +182,6 @@ ScriptContext *LingoCompiler::compileLingo(const Common::U32String &code, LingoA
delete _assemblyContext;
delete _currentAssembly;
delete _methodVars;
- delete _assemblyAST;
_assemblyId = -1;
return nullptr;
}
@@ -260,7 +263,7 @@ ScriptContext *LingoCompiler::compileLingo(const Common::U32String &code, LingoA
if (debugChannelSet(-1, kDebugImGui)) {
_assemblyContext->_assemblyAST = _assemblyAST;
} else {
- delete _assemblyAST;
+ _assemblyAST.reset();
}
_assemblyAST = nullptr;
_assemblyContext = nullptr;
@@ -448,6 +451,7 @@ void LingoCompiler::updateLoopJumps(uint nextTargetPos, uint exitTargetPos) {
/* ScriptNode */
bool LingoCompiler::visitScriptNode(ScriptNode *node) {
+ NodeStore store(node);
COMPILE_LIST(node->children);
return true;
}
@@ -455,6 +459,7 @@ bool LingoCompiler::visitScriptNode(ScriptNode *node) {
/* FactoryNode */
bool LingoCompiler::visitFactoryNode(FactoryNode *node) {
+ NodeStore store(node);
_inFactory = true;
ScriptContext *mainContext = _assemblyContext;
_assemblyContext = new ScriptContext(*node->name, mainContext->_scriptType, mainContext->_id);
@@ -470,6 +475,7 @@ bool LingoCompiler::visitFactoryNode(FactoryNode *node) {
/* HandlerNode */
bool LingoCompiler::visitHandlerNode(HandlerNode *node) {
+ NodeStore store(node);
_indef = true;
ScriptData *mainAssembly = _currentAssembly;
_currentAssembly = new ScriptData;
@@ -535,6 +541,7 @@ bool LingoCompiler::visitHandlerNode(HandlerNode *node) {
/* CmdNode */
bool LingoCompiler::visitCmdNode(CmdNode *node) {
+ NodeStore store(node);
uint numargs = node->args->size();
if (node->name->equalsIgnoreCase("go") && numargs == 1 && (*node->args)[0]->type == kVarNode){
@@ -611,6 +618,7 @@ bool LingoCompiler::visitCmdNode(CmdNode *node) {
/* PutIntoNode */
bool LingoCompiler::visitPutIntoNode(PutIntoNode *node) {
+ NodeStore store(node);
if (node->var->type == kVarNode) {
registerMethodVar(*static_cast<VarNode *>(node->var)->name);
}
@@ -623,6 +631,7 @@ bool LingoCompiler::visitPutIntoNode(PutIntoNode *node) {
/* PutAfterNode */
bool LingoCompiler::visitPutAfterNode(PutAfterNode *node) {
+ NodeStore store(node);
if (node->var->type == kVarNode) {
registerMethodVar(*static_cast<VarNode *>(node->var)->name);
}
@@ -635,6 +644,7 @@ bool LingoCompiler::visitPutAfterNode(PutAfterNode *node) {
/* PutBeforeNode */
bool LingoCompiler::visitPutBeforeNode(PutBeforeNode *node) {
+ NodeStore store(node);
if (node->var->type == kVarNode) {
registerMethodVar(*static_cast<VarNode *>(node->var)->name);
}
@@ -657,6 +667,7 @@ int LingoCompiler::getTheFieldID(int entity, const Common::String &field, bool s
}
bool LingoCompiler::visitSetNode(SetNode *node) {
+ NodeStore store(node);
if (node->var->type == kTheNode) {
TheNode *the = static_cast<TheNode *>(node->var);
if (g_lingo->_theEntities.contains(*the->prop) && !g_lingo->_theEntities[*the->prop]->hasId) {
@@ -820,6 +831,7 @@ bool LingoCompiler::visitSetNode(SetNode *node) {
/* GlobalNode */
bool LingoCompiler::visitGlobalNode(GlobalNode *node) {
+ NodeStore store(node);
for (uint i = 0; i < node->names->size(); i++) {
registerMethodVar(*(*node->names)[i], kVarGlobal);
}
@@ -836,6 +848,7 @@ bool LingoCompiler::visitGlobalNode(GlobalNode *node) {
/* PropertyNode */
bool LingoCompiler::visitPropertyNode(PropertyNode *node) {
+ NodeStore store(node);
for (uint i = 0; i < node->names->size(); i++) {
registerMethodVar(*(*node->names)[i], kVarProperty);
}
@@ -845,6 +858,7 @@ bool LingoCompiler::visitPropertyNode(PropertyNode *node) {
/* InstanceNode */
bool LingoCompiler::visitInstanceNode(InstanceNode *node) {
+ NodeStore store(node);
for (uint i = 0; i < node->names->size(); i++) {
registerMethodVar(*(*node->names)[i], kVarInstance);
}
@@ -854,6 +868,7 @@ bool LingoCompiler::visitInstanceNode(InstanceNode *node) {
/* IfStmtNode */
bool LingoCompiler::visitIfStmtNode(IfStmtNode *node) {
+ NodeStore store(node);
COMPILE(node->cond);
uint jzPos = _currentAssembly->size();
code2(LC::c_jumpifz, nullptr);
@@ -870,6 +885,7 @@ bool LingoCompiler::visitIfStmtNode(IfStmtNode *node) {
/* IfElseStmtNode */
bool LingoCompiler::visitIfElseStmtNode(IfElseStmtNode *node) {
+ NodeStore store(node);
COMPILE(node->cond);
uint jzPos = _currentAssembly->size();
code2(LC::c_jumpifz, nullptr);
@@ -895,6 +911,7 @@ bool LingoCompiler::visitIfElseStmtNode(IfElseStmtNode *node) {
/* RepeatWhileNode */
bool LingoCompiler::visitRepeatWhileNode(RepeatWhileNode *node) {
+ NodeStore store(node);
LoopNode *prevLoop = _currentLoop;
_currentLoop = node;
@@ -924,6 +941,7 @@ bool LingoCompiler::visitRepeatWhileNode(RepeatWhileNode *node) {
/* RepeatWithToNode */
bool LingoCompiler::visitRepeatWithToNode(RepeatWithToNode *node) {
+ NodeStore store(node);
LoopNode *prevLoop = _currentLoop;
_currentLoop = node;
@@ -975,6 +993,7 @@ bool LingoCompiler::visitRepeatWithToNode(RepeatWithToNode *node) {
/* RepeatWithInNode */
bool LingoCompiler::visitRepeatWithInNode(RepeatWithInNode *node) {
+ NodeStore store(node);
LoopNode *prevLoop = _currentLoop;
_currentLoop = node;
@@ -1030,6 +1049,7 @@ bool LingoCompiler::visitRepeatWithInNode(RepeatWithInNode *node) {
/* NextRepeatNode */
bool LingoCompiler::visitNextRepeatNode(NextRepeatNode *node) {
+ NodeStore store(node);
if (!_currentLoop) {
warning("BUILDBOT: LingoCompiler::visitNextRepeatNode: next repeat not inside repeat loop");
return false;
@@ -1042,6 +1062,7 @@ bool LingoCompiler::visitNextRepeatNode(NextRepeatNode *node) {
/* ExitRepeatNode */
bool LingoCompiler::visitExitRepeatNode(ExitRepeatNode *node) {
+ NodeStore store(node);
if (!_currentLoop) {
warning("BUILDBOT: LingoCompiler::visitExitRepeatLoop: exit repeat not inside repeat loop");
return false;
@@ -1054,6 +1075,7 @@ bool LingoCompiler::visitExitRepeatNode(ExitRepeatNode *node) {
/* ExitNode */
bool LingoCompiler::visitExitNode(ExitNode *node) {
+ NodeStore store(node);
code1(LC::c_procret);
return true;
}
@@ -1061,6 +1083,7 @@ bool LingoCompiler::visitExitNode(ExitNode *node) {
/* ReturnNode */
bool LingoCompiler::visitReturnNode(ReturnNode *node) {
+ NodeStore store(node);
if (node->expr) {
COMPILE_REF(node->expr);
codeCmd("return", 1);
@@ -1074,6 +1097,7 @@ bool LingoCompiler::visitReturnNode(ReturnNode *node) {
/* TellNode */
bool LingoCompiler::visitTellNode(TellNode *node) {
+ NodeStore store(node);
COMPILE(node->target);
code1(LC::c_tell);
COMPILE_LIST(node->stmts);
@@ -1084,6 +1108,7 @@ bool LingoCompiler::visitTellNode(TellNode *node) {
/* WhenNode */
bool LingoCompiler::visitWhenNode(WhenNode *node) {
+ NodeStore store(node);
code1(LC::c_stringpush);
codeString(node->code->c_str());
code1(LC::c_whencode);
@@ -1094,6 +1119,7 @@ bool LingoCompiler::visitWhenNode(WhenNode *node) {
/* DeleteNode */
bool LingoCompiler::visitDeleteNode(DeleteNode *node) {
+ NodeStore store(node);
COMPILE_REF(node->chunk);
code1(LC::c_delete);
return true;
@@ -1102,6 +1128,7 @@ bool LingoCompiler::visitDeleteNode(DeleteNode *node) {
/* HiliteNode */
bool LingoCompiler::visitHiliteNode(HiliteNode *node) {
+ NodeStore store(node);
COMPILE_REF(node->chunk);
code1(LC::c_hilite);
return true;
@@ -1110,6 +1137,7 @@ bool LingoCompiler::visitHiliteNode(HiliteNode *node) {
/* AssertErrorNode */
bool LingoCompiler::visitAssertErrorNode(AssertErrorNode *node) {
+ NodeStore store(node);
code1(LC::c_asserterror);
COMPILE(node->stmt);
code1(LC::c_asserterrordone);
@@ -1119,6 +1147,7 @@ bool LingoCompiler::visitAssertErrorNode(AssertErrorNode *node) {
/* IntNode */
bool LingoCompiler::visitIntNode(IntNode *node) {
+ NodeStore store(node);
code1(LC::c_intpush);
codeInt(node->val);
return true;
@@ -1127,6 +1156,7 @@ bool LingoCompiler::visitIntNode(IntNode *node) {
/* FloatNode */
bool LingoCompiler::visitFloatNode(FloatNode *node) {
+ NodeStore store(node);
code1(LC::c_floatpush);
codeFloat(node->val);
return true;
@@ -1135,6 +1165,7 @@ bool LingoCompiler::visitFloatNode(FloatNode *node) {
/* SymbolNode */
bool LingoCompiler::visitSymbolNode(SymbolNode *node) {
+ NodeStore store(node);
code1(LC::c_symbolpush);
codeString(node->val->c_str());
return true;
@@ -1143,6 +1174,7 @@ bool LingoCompiler::visitSymbolNode(SymbolNode *node) {
/* StringNode */
bool LingoCompiler::visitStringNode(StringNode *node) {
+ NodeStore store(node);
code1(LC::c_stringpush);
codeString(node->val->c_str());
return true;
@@ -1151,6 +1183,7 @@ bool LingoCompiler::visitStringNode(StringNode *node) {
/* ListNode */
bool LingoCompiler::visitListNode(ListNode *node) {
+ NodeStore store(node);
COMPILE_LIST(node->items);
code1(LC::c_arraypush);
codeInt(node->items->size());
@@ -1160,6 +1193,7 @@ bool LingoCompiler::visitListNode(ListNode *node) {
/* PropListNode */
bool LingoCompiler::visitPropListNode(PropListNode *node) {
+ NodeStore store(node);
bool refModeStore = _refMode;
_refMode = false;
bool success = true;
@@ -1187,6 +1221,7 @@ bool LingoCompiler::visitPropListNode(PropListNode *node) {
/* PropPairNode */
bool LingoCompiler::visitPropPairNode(PropPairNode *node) {
+ NodeStore store(node);
COMPILE(node->key);
COMPILE(node->val);
return true;
@@ -1195,6 +1230,7 @@ bool LingoCompiler::visitPropPairNode(PropPairNode *node) {
/* FuncNode */
bool LingoCompiler::visitFuncNode(FuncNode *node) {
+ NodeStore store(node);
if (node->name->equalsIgnoreCase("field") && node->args->size() >= 1) {
COMPILE((*node->args)[0]);
if (_refMode) {
@@ -1221,6 +1257,7 @@ bool LingoCompiler::visitFuncNode(FuncNode *node) {
/* VarNode */
bool LingoCompiler::visitVarNode(VarNode *node) {
+ NodeStore store(node);
if (g_director->getVersion() < 400 || (g_director->getCurrentMovie() && g_director->getCurrentMovie()->_allowOutdatedLingo)) {
int val = castNumToNum(node->name->c_str());
if (val != -1) {
@@ -1245,6 +1282,7 @@ bool LingoCompiler::visitVarNode(VarNode *node) {
/* ParensNode */
bool LingoCompiler::visitParensNode(ParensNode *node) {
+ NodeStore store(node);
COMPILE(node->expr);
return true;
}
@@ -1252,6 +1290,7 @@ bool LingoCompiler::visitParensNode(ParensNode *node) {
/* UnaryOpNode */
bool LingoCompiler::visitUnaryOpNode(UnaryOpNode *node) {
+ NodeStore store(node);
COMPILE(node->arg);
code1(node->op);
return true;
@@ -1260,6 +1299,7 @@ bool LingoCompiler::visitUnaryOpNode(UnaryOpNode *node) {
/* BinaryOpNode */
bool LingoCompiler::visitBinaryOpNode(BinaryOpNode *node) {
+ NodeStore store(node);
COMPILE(node->a);
COMPILE(node->b);
code1(node->op);
@@ -1269,6 +1309,7 @@ bool LingoCompiler::visitBinaryOpNode(BinaryOpNode *node) {
/* FrameNode */
bool LingoCompiler::visitFrameNode(FrameNode *node) {
+ NodeStore store(node);
COMPILE(node->arg);
return true;
}
@@ -1276,6 +1317,7 @@ bool LingoCompiler::visitFrameNode(FrameNode *node) {
/* MovieNode */
bool LingoCompiler::visitMovieNode(MovieNode *node) {
+ NodeStore store(node);
COMPILE(node->arg);
return true;
}
@@ -1283,6 +1325,7 @@ bool LingoCompiler::visitMovieNode(MovieNode *node) {
/* IntersectsNode */
bool LingoCompiler::visitIntersectsNode(IntersectsNode *node) {
+ NodeStore store(node);
COMPILE(node->sprite1);
COMPILE(node->sprite2);
code1(LC::c_intersects);
@@ -1292,6 +1335,7 @@ bool LingoCompiler::visitIntersectsNode(IntersectsNode *node) {
/* WithinNode */
bool LingoCompiler::visitWithinNode(WithinNode *node) {
+ NodeStore store(node);
COMPILE(node->sprite1);
COMPILE(node->sprite2);
code1(LC::c_within);
@@ -1301,6 +1345,7 @@ bool LingoCompiler::visitWithinNode(WithinNode *node) {
/* TheNode */
bool LingoCompiler::visitTheNode(TheNode *node) {
+ NodeStore store(node);
if (g_lingo->_theEntities.contains(*node->prop) && !g_lingo->_theEntities[*node->prop]->hasId) {
code1(LC::c_intpush);
codeInt(0); // Put dummy id
@@ -1317,6 +1362,7 @@ bool LingoCompiler::visitTheNode(TheNode *node) {
/* TheOfNode */
bool LingoCompiler::visitTheOfNode(TheOfNode *node) {
+ NodeStore store(node);
switch (node->obj->type) {
case kChunkExprNode:
{
@@ -1451,6 +1497,7 @@ bool LingoCompiler::visitTheOfNode(TheOfNode *node) {
/* TheNumberOfNode */
bool LingoCompiler::visitTheNumberOfNode(TheNumberOfNode *node) {
+ NodeStore store(node);
switch (node->type) {
case kNumberOfCastlibs:
codeInt(0); // Put dummy id
@@ -1506,6 +1553,7 @@ bool LingoCompiler::visitTheNumberOfNode(TheNumberOfNode *node) {
/* TheLastNode */
bool LingoCompiler::visitTheLastNode(TheLastNode *node) {
+ NodeStore store(node);
code1(LC::c_intpush);
codeInt(-30000);
code1(LC::c_intpush);
@@ -1551,6 +1599,7 @@ bool LingoCompiler::visitTheLastNode(TheLastNode *node) {
/* TheDateTimeNode */
bool LingoCompiler::visitTheDateTimeNode(TheDateTimeNode *node) {
+ NodeStore store(node);
code1(LC::c_intpush);
codeInt(0); // Put dummy id
code1(LC::c_theentitypush);
@@ -1562,30 +1611,35 @@ bool LingoCompiler::visitTheDateTimeNode(TheDateTimeNode *node) {
/* MenuNode */
bool LingoCompiler::visitMenuNode(MenuNode *node) {
+ NodeStore store(node);
return true;
}
/* MenuItemNode */
bool LingoCompiler::visitMenuItemNode(MenuItemNode *node) {
+ NodeStore store(node);
return true;
}
/* SoundItem */
bool LingoCompiler::visitSoundNode(SoundNode *node) {
+ NodeStore store(node);
return true;
}
/* SpriteNode */
bool LingoCompiler::visitSpriteNode(SpriteNode *node) {
+ NodeStore store(node);
return true;
}
/* ChunkExprNode */
bool LingoCompiler::visitChunkExprNode(ChunkExprNode *node) {
+ NodeStore store(node);
COMPILE(node->start);
if (node->end) {
COMPILE(node->end);
diff --git a/engines/director/lingo/lingo-codegen.h b/engines/director/lingo/lingo-codegen.h
index 1a71035c8e7..88bd91ba042 100644
--- a/engines/director/lingo/lingo-codegen.h
+++ b/engines/director/lingo/lingo-codegen.h
@@ -55,7 +55,7 @@ public:
LingoArchive *_assemblyArchive;
ScriptContext *_assemblyContext;
- Node *_assemblyAST;
+ Common::SharedPtr<Node> _assemblyAST;
int32 _assemblyId;
ScriptData *_currentAssembly;
bool _indef;
diff --git a/engines/director/lingo/lingo-gr.cpp b/engines/director/lingo/lingo-gr.cpp
index 23b1d72a045..900fa9c2490 100644
--- a/engines/director/lingo/lingo-gr.cpp
+++ b/engines/director/lingo/lingo-gr.cpp
@@ -2865,7 +2865,7 @@ yyreduce:
{
case 2: /* script: scriptpartlist */
#line 208 "engines/director/lingo/lingo-gr.y"
- { g_lingo->_compiler->_assemblyAST = new ScriptNode((yyvsp[0].nodelist)); (yyval.node) = nullptr; }
+ { g_lingo->_compiler->_assemblyAST = Common::SharedPtr<Node>(new ScriptNode((yyvsp[0].nodelist))); (yyval.node) = nullptr; }
#line 2870 "engines/director/lingo/lingo-gr.cpp"
break;
diff --git a/engines/director/lingo/lingo-gr.y b/engines/director/lingo/lingo-gr.y
index c818f154a70..684d3711363 100644
--- a/engines/director/lingo/lingo-gr.y
+++ b/engines/director/lingo/lingo-gr.y
@@ -205,7 +205,7 @@ static void checkEnd(Common::String *token, Common::String *expect, bool require
// TOP-LEVEL STUFF
-script: scriptpartlist { g_lingo->_compiler->_assemblyAST = new ScriptNode($scriptpartlist); $$ = nullptr; } ;
+script: scriptpartlist { g_lingo->_compiler->_assemblyAST = Common::SharedPtr<Node>(new ScriptNode($scriptpartlist)); $$ = nullptr; } ;
scriptpartlist: scriptpart[item] {
NodeList *list = new NodeList;
diff --git a/engines/director/lingo/lingo-object.cpp b/engines/director/lingo/lingo-object.cpp
index 53737a63a4c..03f4b7b5ac1 100644
--- a/engines/director/lingo/lingo-object.cpp
+++ b/engines/director/lingo/lingo-object.cpp
@@ -425,7 +425,6 @@ ScriptContext::ScriptContext(const ScriptContext &sc) : Object<ScriptContext>(sc
}
ScriptContext::~ScriptContext() {
- delete _assemblyAST;
}
Common::String ScriptContext::asString() {
diff --git a/engines/director/lingo/lingo-object.h b/engines/director/lingo/lingo-object.h
index 47bfb69dffa..f61e0a81b1d 100644
--- a/engines/director/lingo/lingo-object.h
+++ b/engines/director/lingo/lingo-object.h
@@ -216,7 +216,7 @@ public:
Common::Array<Datum> _constants;
Common::HashMap<uint32, Datum> _objArray;
MethodHash _methodNames;
- Node *_assemblyAST = nullptr; // Optionally contains AST when we compile Lingo
+ Common::SharedPtr<Node> _assemblyAST; // Optionally contains AST when we compile Lingo
private:
DatumHash _properties;
Commit: 23c472d3b815dbc65937ce5f40695a8a4b8c84c8
https://github.com/scummvm/scummvm/commit/23c472d3b815dbc65937ce5f40695a8a4b8c84c8
Author: scemino (scemino74 at gmail.com)
Date: 2024-06-01T07:51:02+02:00
Commit Message:
DIRECTOR: Add indentation in script for D2 and D3
Changed paths:
engines/director/debugtools.cpp
diff --git a/engines/director/debugtools.cpp b/engines/director/debugtools.cpp
index a66a9a21606..c7ea39510e9 100644
--- a/engines/director/debugtools.cpp
+++ b/engines/director/debugtools.cpp
@@ -473,7 +473,7 @@ const LingoDec::Handler *getHandler(CastMemberID id, const Common::String &handl
return getHandler(movie->getSharedCast(), id, handlerId);
}
-ImGuiScript toImGuiScript(ScriptType scriptType, CastMemberID id, const Common::String &handlerId) {
+static ImGuiScript toImGuiScript(ScriptType scriptType, CastMemberID id, const Common::String &handlerId) {
ImGuiScript result;
result.id = id;
result.handlerId = handlerId;
@@ -522,6 +522,7 @@ static Director::Breakpoint *getBreakpoint(const Common::String &handlerName, ui
class RenderOldScriptVisitor : public NodeVisitor {
private:
ImGuiScript &_script;
+ int _indent = 0;
public:
explicit RenderOldScriptVisitor(ImGuiScript &script) : _script(script) {}
@@ -543,11 +544,15 @@ public:
}
ImGui::NewLine();
}
+ indent();
for (uint i = 0; i < node->stmts->size(); i++) {
+ renderIndentation();
Node *stmt = (*node->stmts)[i];
stmt->accept(this);
ImGui::NewLine();
}
+ unindent();
+ renderIndentation();
ImGui::Text("end");
return true;
}
@@ -561,16 +566,21 @@ public:
ImGui::PopStyleVar();
return true;
}
+
virtual bool visitFactoryNode(FactoryNode *node){
ImGui::Text("factory %s", node->name->c_str());
- ImGui::SameLine();
+ ImGui::NewLine();
+ indent();
for (uint i = 0; i < node->methods->size(); i++) {
+ renderIndentation();
Node *method = (*node->methods)[i];
method->accept(this);
ImGui::NewLine();
}
+ unindent();
return true;
}
+
virtual bool visitCmdNode(CmdNode *node) {
ImGui::Text("%s ", node->name->c_str());
ImGui::SameLine();
@@ -591,6 +601,7 @@ public:
}
return true;
}
+
virtual bool visitPutIntoNode(PutIntoNode *node){
ImGui::Text("put ");
ImGui::SameLine();
@@ -600,6 +611,7 @@ public:
node->var->accept(this);
return true;
}
+
virtual bool visitPutAfterNode(PutAfterNode *node) {
ImGui::Text("put ");
ImGui::SameLine();
@@ -609,6 +621,7 @@ public:
node->var->accept(this);
return true;
}
+
virtual bool visitPutBeforeNode(PutBeforeNode *node){
ImGui::Text("put ");
ImGui::SameLine();
@@ -618,6 +631,7 @@ public:
node->var->accept(this);
return true;
}
+
virtual bool visitSetNode(SetNode *node){
ImGui::Text("set ");
ImGui::SameLine();
@@ -643,17 +657,20 @@ public:
}
virtual bool visitGlobalNode(GlobalNode *node){
- displayDefineVar("global ", node->names);
+ displayDefineVar("global", node->names);
return true;
}
+
virtual bool visitPropertyNode(PropertyNode *node){
- displayDefineVar("property ", node->names);
+ displayDefineVar("property", node->names);
return true;
}
+
virtual bool visitInstanceNode(InstanceNode *node){
- displayDefineVar("instance ", node->names);
+ displayDefineVar("instance", node->names);
return true;
}
+
virtual bool visitIfStmtNode(IfStmtNode *node){
ImGui::Text("if ");
ImGui::SameLine();
@@ -663,16 +680,21 @@ public:
ImGui::SameLine();
(*node->stmts)[0]->accept(this);
} else {
+ indent();
for (uint i = 0; i < node->stmts->size(); i++) {
+ renderIndentation();
Node *stmt = (*node->stmts)[i];
stmt->accept(this);
ImGui::NewLine();
}
+ unindent();
+ renderIndentation();
ImGui::Text("endif");
ImGui::SameLine();
}
return true;
}
+
virtual bool visitIfElseStmtNode(IfElseStmtNode *node){
ImGui::Text("if ");
ImGui::SameLine();
@@ -684,40 +706,54 @@ public:
ImGui::Text(" ");
ImGui::SameLine();
} else {
+ indent();
for (uint i = 0; i < node->stmts1->size(); i++) {
+ renderIndentation();
Node *stmt = (*node->stmts1)[i];
stmt->accept(this);
ImGui::NewLine();
}
+ unindent();
+ renderIndentation();
}
ImGui::Text("else ");
if(node->stmts2->size() == 1) {
ImGui::SameLine();
(*node->stmts2)[0]->accept(this);
} else {
+ indent();
for (uint i = 0; i < node->stmts2->size(); i++) {
+ renderIndentation();
Node *stmt = (*node->stmts2)[i];
stmt->accept(this);
ImGui::NewLine();
}
+ unindent();
+ renderIndentation();
ImGui::Text("endif");
ImGui::SameLine();
}
return true;
}
+
virtual bool visitRepeatWhileNode(RepeatWhileNode *node){
ImGui::Text("repeat while ");
ImGui::SameLine();
node->cond->accept(this);
ImGui::NewLine();
+ indent();
for (uint i = 0; i < node->stmts->size(); i++) {
+ renderIndentation();
Node *stmt = (*node->stmts)[i];
stmt->accept(this);
ImGui::NewLine();
}
+ unindent();
+ renderIndentation();
ImGui::Text("endrepeat");
return true;
}
+
virtual bool visitRepeatWithToNode(RepeatWithToNode *node){
ImGui::Text("repeat with ");
ImGui::SameLine();
@@ -727,14 +763,19 @@ public:
ImGui::Text(" %s ", node->down ? "down to" : "to");
node->end->accept(this);
ImGui::NewLine();
+ indent();
for (uint i = 0; i < node->stmts->size(); i++) {
+ renderIndentation();
Node *stmt = (*node->stmts)[i];
stmt->accept(this);
ImGui::NewLine();
}
+ unindent();
+ renderIndentation();
ImGui::Text("endrepeat");
return true;
}
+
virtual bool visitRepeatWithInNode(RepeatWithInNode *node){
ImGui::Text("repeat with ");
ImGui::SameLine();
@@ -742,26 +783,34 @@ public:
ImGui::SameLine();
node->list->accept(this);
ImGui::NewLine();
+ indent();
for (uint i = 0; i < node->stmts->size(); i++) {
+ renderIndentation();
Node *stmt = (*node->stmts)[i];
stmt->accept(this);
ImGui::NewLine();
}
+ unindent();
+ renderIndentation();
ImGui::Text("endrepeat");
return true;
}
+
virtual bool visitNextRepeatNode(NextRepeatNode *node){
ImGui::Text("next repeat");
return true;
}
+
virtual bool visitExitRepeatNode(ExitRepeatNode *node){
ImGui::Text("exit repeat");
return true;
}
+
virtual bool visitExitNode(ExitNode *node){
ImGui::Text("exit");
return true;
}
+
virtual bool visitReturnNode(ReturnNode *node){
ImGui::Text("return");
if(node->expr) {
@@ -772,6 +821,7 @@ public:
}
return true;
}
+
virtual bool visitTellNode(TellNode *node){
ImGui::Text("tell ");
node->target->accept(this);
@@ -781,58 +831,71 @@ public:
ImGui::SameLine();
(*node->stmts)[0]->accept(this);
} else {
+ indent();
for (uint i = 0; i < node->stmts->size(); i++) {
+ renderIndentation();
Node *stmt = (*node->stmts)[i];
stmt->accept(this);
ImGui::NewLine();
}
+ unindent();
+ renderIndentation();
ImGui::Text("endtell");
}
return true;
}
+
virtual bool visitWhenNode(WhenNode *node){
ImGui::Text("when %s then %s", node->event->c_str(), node->code->c_str());
ImGui::SameLine();
return true;
}
+
virtual bool visitDeleteNode(DeleteNode *node){
ImGui::Text("delete ");
ImGui::SameLine();
node->chunk->accept(this);
return true;
}
+
virtual bool visitHiliteNode(HiliteNode *node){
ImGui::Text("hilite ");
ImGui::SameLine();
node->chunk->accept(this);
return true;
}
+
virtual bool visitAssertErrorNode(AssertErrorNode *node){
ImGui::Text("scummvmAssertError ");
ImGui::SameLine();
node->stmt->accept(this);
return true;
}
+
virtual bool visitIntNode(IntNode *node){
ImGui::Text("%d", node->val);
ImGui::SameLine();
return true;
}
+
virtual bool visitFloatNode(FloatNode *node){
ImGui::Text("%g", node->val);
ImGui::SameLine();
return true;
}
+
virtual bool visitSymbolNode(SymbolNode *node){
ImGui::Text("%s", node->val->c_str());
ImGui::SameLine();
return true;
}
+
virtual bool visitStringNode(StringNode *node){
ImGui::Text("\"%s\"", node->val->c_str());
ImGui::SameLine();
return true;
}
+
virtual bool visitListNode(ListNode *node){
ImGui::Text("[");
ImGui::SameLine();
@@ -848,6 +911,7 @@ public:
ImGui::SameLine();
return true;
}
+
virtual bool visitPropListNode(PropListNode *node){
ImGui::Text("[");
ImGui::SameLine();
@@ -868,6 +932,7 @@ public:
ImGui::SameLine();
return true;
}
+
virtual bool visitPropPairNode(PropPairNode *node){
node->key->accept(this);
ImGui::Text(":");
@@ -875,6 +940,7 @@ public:
node->val->accept(this);
return true;
}
+
virtual bool visitFuncNode(FuncNode *node){
ImGui::Text("%s(", node->name->c_str());
ImGui::SameLine();
@@ -890,11 +956,13 @@ public:
ImGui::SameLine();
return true;
}
+
virtual bool visitVarNode(VarNode *node){
ImGui::Text("%s", node->name->c_str());
ImGui::SameLine();
return true;
}
+
virtual bool visitParensNode(ParensNode *node){
ImGui::Text("(");
ImGui::SameLine();
@@ -903,6 +971,7 @@ public:
ImGui::SameLine();
return true;
}
+
virtual bool visitUnaryOpNode(UnaryOpNode *node){
char op = '?';
if(node->op == LC::c_negate) {
@@ -915,6 +984,7 @@ public:
node->arg->accept(this);
return true;
}
+
virtual bool visitBinaryOpNode(BinaryOpNode *node){
node->a->accept(this);
static struct {
@@ -949,18 +1019,21 @@ public:
node->b->accept(this);
return true;
}
+
virtual bool visitFrameNode(FrameNode *node){
ImGui::Text("frame ");
ImGui::SameLine();
node->arg->accept(this);
return true;
}
+
virtual bool visitMovieNode(MovieNode *node){
ImGui::Text("movie ");
ImGui::SameLine();
node->arg->accept(this);
return true;
}
+
virtual bool visitIntersectsNode(IntersectsNode *node){
ImGui::Text("sprite ");
ImGui::SameLine();
@@ -969,6 +1042,7 @@ public:
node->sprite2->accept(this);
return true;
}
+
virtual bool visitWithinNode(WithinNode *node){
ImGui::Text("sprite ");
ImGui::SameLine();
@@ -977,23 +1051,27 @@ public:
node->sprite2->accept(this);
return true;
}
+
virtual bool visitTheNode(TheNode *node){
ImGui::Text("the %s", node->prop->c_str());
ImGui::SameLine();
return true;
}
+
virtual bool visitTheOfNode(TheOfNode *node){
ImGui::Text("the %s of ", node->prop->c_str());
ImGui::SameLine();
node->obj->accept(this);
return true;
}
+
virtual bool visitTheNumberOfNode(TheNumberOfNode *node){
ImGui::Text("the number of ");
ImGui::SameLine();
node->arg->accept(this);
return true;
}
+
virtual bool visitTheLastNode(TheLastNode *node){
// TODO: change the node to know if it's 'in' or 'of'
ImGui::Text("the last %s in/of ", toString(node->type).c_str());
@@ -1001,6 +1079,7 @@ public:
node->arg->accept(this);
return true;
}
+
virtual bool visitTheDateTimeNode(TheDateTimeNode *node){
const char* key1 = "";
switch(node->field) {
@@ -1019,12 +1098,14 @@ public:
ImGui::SameLine();
return true;
}
+
virtual bool visitMenuNode(MenuNode *node){
ImGui::Text("menu ");
ImGui::SameLine();
node->arg->accept(this);
return true;
}
+
virtual bool visitMenuItemNode(MenuItemNode *node){
ImGui::Text("menuitem ");
ImGui::SameLine();
@@ -1034,18 +1115,21 @@ public:
node->arg2->accept(this);
return true;
}
+
virtual bool visitSoundNode(SoundNode *node){
ImGui::Text("sound ");
ImGui::SameLine();
node->arg->accept(this);
return true;
}
+
virtual bool visitSpriteNode(SpriteNode *node){
ImGui::Text("sprite ");
ImGui::SameLine();
node->arg->accept(this);
return true;
}
+
virtual bool visitChunkExprNode(ChunkExprNode *node){
const char* key1 = "";
switch(node->type) {
@@ -1091,8 +1175,23 @@ private:
}
return "<unknown>";
}
-};
+ void indent() {
+ _indent++;
+ }
+
+ void unindent() {
+ if (_indent > 0)
+ _indent--;
+ }
+
+ void renderIndentation() const {
+ for (int i = 0; i < _indent; i++) {
+ ImGui::Text(" ");
+ ImGui::SameLine();
+ }
+ }
+};
class RenderScriptVisitor : public LingoDec::NodeVisitor {
public:
RenderScriptVisitor(ImGuiScript &script, bool showByteCode) : _script(script), _showByteCode(showByteCode) {
Commit: f596c31c95abfbe0c6e4dd5aebd27910adb6cc31
https://github.com/scummvm/scummvm/commit/f596c31c95abfbe0c6e4dd5aebd27910adb6cc31
Author: scemino (scemino74 at gmail.com)
Date: 2024-06-01T07:51:02+02:00
Commit Message:
DIRECTOR: Add syntax highlighting in script for D2 and D3
Changed paths:
engines/director/debugtools.cpp
diff --git a/engines/director/debugtools.cpp b/engines/director/debugtools.cpp
index c7ea39510e9..2fbabedfd2c 100644
--- a/engines/director/debugtools.cpp
+++ b/engines/director/debugtools.cpp
@@ -523,13 +523,24 @@ class RenderOldScriptVisitor : public NodeVisitor {
private:
ImGuiScript &_script;
int _indent = 0;
+ bool _isScriptInDebug = false;
+ bool _currentStatementDisplayed = false;
public:
- explicit RenderOldScriptVisitor(ImGuiScript &script) : _script(script) {}
+ explicit RenderOldScriptVisitor(ImGuiScript &script) : _script(script) {
+ Common::Array<CFrame *> &callstack = g_lingo->_state->callstack;
+ if (!callstack.empty()) {
+ CFrame *head = callstack[callstack.size() - 1];
+ _isScriptInDebug = (head->sp.ctx->_id == script.id.member) && (*head->sp.name == script.handlerId);
+ }
+ _script.startOffsets.clear();
+ }
virtual bool visitHandlerNode(HandlerNode *node) {
- ImGui::Text("on %s", node->name->c_str());
- if(!node->args->empty()) {
+ ImGui::Text("on ");
+ ImGui::SameLine();
+ ImGui::TextColored(_state->_colors._call_color, "%s", node->name->c_str());
+ if (!node->args->empty()) {
ImGui::SameLine();
ImGui::Text(" ");
ImGui::SameLine();
@@ -546,34 +557,36 @@ public:
}
indent();
for (uint i = 0; i < node->stmts->size(); i++) {
- renderIndentation();
Node *stmt = (*node->stmts)[i];
+ renderLine(stmt->startOffset);
stmt->accept(this);
ImGui::NewLine();
}
unindent();
- renderIndentation();
- ImGui::Text("end");
+ renderLine(node->endOffset);
+ ImGui::TextColored(_state->_colors._keyword_color, "end");
return true;
}
- virtual bool visitScriptNode(ScriptNode *node){
+ virtual bool visitScriptNode(ScriptNode *node) {
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2());
- for(Node* child : *node->children) {
- if(child->type == kHandlerNode && *((HandlerNode*)child)->name != _script.handlerId) continue;
+ for (Node *child : *node->children) {
+ if (child->type == kHandlerNode && *((HandlerNode *)child)->name != _script.handlerId)
+ continue;
+ renderLine(child->startOffset);
child->accept(this);
}
ImGui::PopStyleVar();
return true;
}
- virtual bool visitFactoryNode(FactoryNode *node){
+ virtual bool visitFactoryNode(FactoryNode *node) {
ImGui::Text("factory %s", node->name->c_str());
ImGui::NewLine();
indent();
for (uint i = 0; i < node->methods->size(); i++) {
- renderIndentation();
Node *method = (*node->methods)[i];
+ renderLine(method->startOffset);
method->accept(this);
ImGui::NewLine();
}
@@ -584,8 +597,8 @@ public:
virtual bool visitCmdNode(CmdNode *node) {
ImGui::Text("%s ", node->name->c_str());
ImGui::SameLine();
- if(*node->name == "go") {
- ImGui::Text("to ");
+ if (*node->name == "go") {
+ ImGui::TextColored(_state->_colors._keyword_color, "to ");
ImGui::SameLine();
}
for (uint i = 0; i < node->args->size(); i++) {
@@ -602,41 +615,41 @@ public:
return true;
}
- virtual bool visitPutIntoNode(PutIntoNode *node){
- ImGui::Text("put ");
+ virtual bool visitPutIntoNode(PutIntoNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "put ");
ImGui::SameLine();
node->val->accept(this);
- ImGui::Text(" into ");
+ ImGui::TextColored(_state->_colors._keyword_color, " into ");
ImGui::SameLine();
node->var->accept(this);
return true;
}
virtual bool visitPutAfterNode(PutAfterNode *node) {
- ImGui::Text("put ");
+ ImGui::TextColored(_state->_colors._keyword_color, "put ");
ImGui::SameLine();
node->val->accept(this);
- ImGui::Text(" after ");
+ ImGui::TextColored(_state->_colors._keyword_color, " after ");
ImGui::SameLine();
node->var->accept(this);
return true;
}
- virtual bool visitPutBeforeNode(PutBeforeNode *node){
- ImGui::Text("put ");
+ virtual bool visitPutBeforeNode(PutBeforeNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "put ");
ImGui::SameLine();
node->val->accept(this);
- ImGui::Text(" before ");
+ ImGui::TextColored(_state->_colors._keyword_color, " before ");
ImGui::SameLine();
node->var->accept(this);
return true;
}
- virtual bool visitSetNode(SetNode *node){
- ImGui::Text("set ");
+ virtual bool visitSetNode(SetNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "set ");
ImGui::SameLine();
node->val->accept(this);
- ImGui::Text(" to ");
+ ImGui::TextColored(_state->_colors._keyword_color, " to ");
ImGui::SameLine();
node->var->accept(this);
return true;
@@ -656,128 +669,134 @@ public:
}
}
- virtual bool visitGlobalNode(GlobalNode *node){
+ virtual bool visitGlobalNode(GlobalNode *node) {
displayDefineVar("global", node->names);
return true;
}
- virtual bool visitPropertyNode(PropertyNode *node){
+ virtual bool visitPropertyNode(PropertyNode *node) {
displayDefineVar("property", node->names);
return true;
}
- virtual bool visitInstanceNode(InstanceNode *node){
+ virtual bool visitInstanceNode(InstanceNode *node) {
displayDefineVar("instance", node->names);
return true;
}
- virtual bool visitIfStmtNode(IfStmtNode *node){
- ImGui::Text("if ");
+ virtual bool visitIfStmtNode(IfStmtNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "if ");
ImGui::SameLine();
node->cond->accept(this);
- ImGui::Text(" then ");
- if(node->stmts->size() == 1) {
+ ImGui::TextColored(_state->_colors._keyword_color, " then ");
+ if (node->stmts->size() == 1) {
ImGui::SameLine();
(*node->stmts)[0]->accept(this);
} else {
indent();
for (uint i = 0; i < node->stmts->size(); i++) {
- renderIndentation();
Node *stmt = (*node->stmts)[i];
+ renderLine(stmt->startOffset);
stmt->accept(this);
ImGui::NewLine();
}
unindent();
- renderIndentation();
- ImGui::Text("endif");
+ renderLine(node->endOffset);
+ ImGui::TextColored(_state->_colors._keyword_color, "endif");
ImGui::SameLine();
}
return true;
}
- virtual bool visitIfElseStmtNode(IfElseStmtNode *node){
- ImGui::Text("if ");
+ virtual bool visitIfElseStmtNode(IfElseStmtNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "if ");
ImGui::SameLine();
node->cond->accept(this);
- ImGui::Text(" then ");
- if(node->stmts1->size() == 1) {
+ ImGui::TextColored(_state->_colors._keyword_color, " then ");
+ if (node->stmts1->size() == 1) {
ImGui::SameLine();
(*node->stmts1)[0]->accept(this);
ImGui::Text(" ");
ImGui::SameLine();
} else {
+ uint offset = node->cond->endOffset;
indent();
for (uint i = 0; i < node->stmts1->size(); i++) {
- renderIndentation();
Node *stmt = (*node->stmts1)[i];
+ renderLine(stmt->startOffset);
stmt->accept(this);
ImGui::NewLine();
+ offset = stmt->endOffset;
}
unindent();
- renderIndentation();
+ renderLine(offset);
}
- ImGui::Text("else ");
- if(node->stmts2->size() == 1) {
+ ImGui::TextColored(_state->_colors._keyword_color, "else ");
+ if (node->stmts2->size() == 1) {
ImGui::SameLine();
(*node->stmts2)[0]->accept(this);
} else {
+ uint offset = node->cond->endOffset;
indent();
for (uint i = 0; i < node->stmts2->size(); i++) {
- renderIndentation();
Node *stmt = (*node->stmts2)[i];
+ renderLine(stmt->startOffset);
stmt->accept(this);
ImGui::NewLine();
+ offset = stmt->endOffset;
}
unindent();
- renderIndentation();
- ImGui::Text("endif");
+ renderLine(offset);
+ ImGui::TextColored(_state->_colors._keyword_color, "endif");
ImGui::SameLine();
}
return true;
}
- virtual bool visitRepeatWhileNode(RepeatWhileNode *node){
- ImGui::Text("repeat while ");
+ virtual bool visitRepeatWhileNode(RepeatWhileNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "repeat while ");
ImGui::SameLine();
node->cond->accept(this);
ImGui::NewLine();
indent();
+ uint offset = node->cond->endOffset;
for (uint i = 0; i < node->stmts->size(); i++) {
- renderIndentation();
Node *stmt = (*node->stmts)[i];
+ renderLine(stmt->startOffset);
stmt->accept(this);
ImGui::NewLine();
+ offset = stmt->endOffset;
}
unindent();
- renderIndentation();
- ImGui::Text("endrepeat");
+ renderLine(offset);
+ ImGui::TextColored(_state->_colors._keyword_color, "endrepeat");
return true;
}
- virtual bool visitRepeatWithToNode(RepeatWithToNode *node){
- ImGui::Text("repeat with ");
+ virtual bool visitRepeatWithToNode(RepeatWithToNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "repeat with ");
ImGui::SameLine();
ImGui::Text("%s = ", node->var->c_str());
ImGui::SameLine();
node->start->accept(this);
- ImGui::Text(" %s ", node->down ? "down to" : "to");
+ ImGui::TextColored(_state->_colors._keyword_color, " %s ", node->down ? "down to" : "to");
node->end->accept(this);
ImGui::NewLine();
indent();
for (uint i = 0; i < node->stmts->size(); i++) {
- renderIndentation();
Node *stmt = (*node->stmts)[i];
+ renderLine(stmt->startOffset);
stmt->accept(this);
ImGui::NewLine();
}
unindent();
- renderIndentation();
- ImGui::Text("endrepeat");
+ renderLine(node->endOffset);
+ ImGui::TextColored(_state->_colors._keyword_color, "endrepeat");
return true;
}
- virtual bool visitRepeatWithInNode(RepeatWithInNode *node){
- ImGui::Text("repeat with ");
+ virtual bool visitRepeatWithInNode(RepeatWithInNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "repeat with ");
ImGui::SameLine();
ImGui::Text("%s in ", node->var->c_str());
ImGui::SameLine();
@@ -785,35 +804,35 @@ public:
ImGui::NewLine();
indent();
for (uint i = 0; i < node->stmts->size(); i++) {
- renderIndentation();
Node *stmt = (*node->stmts)[i];
+ renderLine(stmt->startOffset);
stmt->accept(this);
ImGui::NewLine();
}
unindent();
- renderIndentation();
- ImGui::Text("endrepeat");
+ renderLine(node->endOffset);
+ ImGui::TextColored(_state->_colors._keyword_color, "endrepeat");
return true;
}
- virtual bool visitNextRepeatNode(NextRepeatNode *node){
- ImGui::Text("next repeat");
+ virtual bool visitNextRepeatNode(NextRepeatNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "next repeat");
return true;
}
- virtual bool visitExitRepeatNode(ExitRepeatNode *node){
- ImGui::Text("exit repeat");
+ virtual bool visitExitRepeatNode(ExitRepeatNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "exit repeat");
return true;
}
- virtual bool visitExitNode(ExitNode *node){
- ImGui::Text("exit");
+ virtual bool visitExitNode(ExitNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "exit");
return true;
}
- virtual bool visitReturnNode(ReturnNode *node){
- ImGui::Text("return");
- if(node->expr) {
+ virtual bool visitReturnNode(ReturnNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "return");
+ if (node->expr) {
ImGui::Text(" ");
ImGui::SameLine();
node->expr->accept(this);
@@ -822,81 +841,87 @@ public:
return true;
}
- virtual bool visitTellNode(TellNode *node){
- ImGui::Text("tell ");
+ virtual bool visitTellNode(TellNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "tell ");
node->target->accept(this);
- if(node->stmts->size() == 1) {
+ if (node->stmts->size() == 1) {
ImGui::SameLine();
- ImGui::Text(" to ");
+ ImGui::TextColored(_state->_colors._keyword_color, " to ");
ImGui::SameLine();
(*node->stmts)[0]->accept(this);
} else {
indent();
for (uint i = 0; i < node->stmts->size(); i++) {
- renderIndentation();
Node *stmt = (*node->stmts)[i];
+ renderLine(stmt->startOffset);
stmt->accept(this);
ImGui::NewLine();
}
unindent();
- renderIndentation();
- ImGui::Text("endtell");
+ renderLine(node->endOffset);
+ ImGui::TextColored(_state->_colors._keyword_color, "endtell");
}
return true;
}
- virtual bool visitWhenNode(WhenNode *node){
- ImGui::Text("when %s then %s", node->event->c_str(), node->code->c_str());
+ virtual bool visitWhenNode(WhenNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "when ");
+ ImGui::SameLine();
+ ImGui::Text("%s", node->event->c_str());
+ ImGui::SameLine();
+ ImGui::TextColored(_state->_colors._keyword_color, " then ");
+ ImGui::SameLine();
+ ImGui::Text("%s", node->code->c_str());
ImGui::SameLine();
return true;
}
- virtual bool visitDeleteNode(DeleteNode *node){
- ImGui::Text("delete ");
+ virtual bool visitDeleteNode(DeleteNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "delete ");
ImGui::SameLine();
node->chunk->accept(this);
return true;
}
- virtual bool visitHiliteNode(HiliteNode *node){
- ImGui::Text("hilite ");
+ virtual bool visitHiliteNode(HiliteNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "hilite ");
ImGui::SameLine();
node->chunk->accept(this);
return true;
}
- virtual bool visitAssertErrorNode(AssertErrorNode *node){
- ImGui::Text("scummvmAssertError ");
+ virtual bool visitAssertErrorNode(AssertErrorNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "scummvmAssertError ");
ImGui::SameLine();
node->stmt->accept(this);
return true;
}
- virtual bool visitIntNode(IntNode *node){
- ImGui::Text("%d", node->val);
+ virtual bool visitIntNode(IntNode *node) {
+ ImGui::TextColored(_state->_colors._literal_color, "%d", node->val);
ImGui::SameLine();
return true;
}
- virtual bool visitFloatNode(FloatNode *node){
- ImGui::Text("%g", node->val);
+ virtual bool visitFloatNode(FloatNode *node) {
+ ImGui::TextColored(_state->_colors._literal_color, "%g", node->val);
ImGui::SameLine();
return true;
}
- virtual bool visitSymbolNode(SymbolNode *node){
- ImGui::Text("%s", node->val->c_str());
+ virtual bool visitSymbolNode(SymbolNode *node) {
+ ImGui::TextColored(_state->_colors._literal_color, "%s", node->val->c_str());
ImGui::SameLine();
return true;
}
- virtual bool visitStringNode(StringNode *node){
- ImGui::Text("\"%s\"", node->val->c_str());
+ virtual bool visitStringNode(StringNode *node) {
+ ImGui::TextColored(_state->_colors._literal_color, "\"%s\"", node->val->c_str());
ImGui::SameLine();
return true;
}
- virtual bool visitListNode(ListNode *node){
+ virtual bool visitListNode(ListNode *node) {
ImGui::Text("[");
ImGui::SameLine();
for (uint i = 0; i < node->items->size(); i++) {
@@ -912,10 +937,10 @@ public:
return true;
}
- virtual bool visitPropListNode(PropListNode *node){
+ virtual bool visitPropListNode(PropListNode *node) {
ImGui::Text("[");
ImGui::SameLine();
- if(node->items->empty()) {
+ if (node->items->empty()) {
ImGui::Text(":");
ImGui::SameLine();
} else {
@@ -933,7 +958,7 @@ public:
return true;
}
- virtual bool visitPropPairNode(PropPairNode *node){
+ virtual bool visitPropPairNode(PropPairNode *node) {
node->key->accept(this);
ImGui::Text(":");
ImGui::SameLine();
@@ -941,8 +966,28 @@ public:
return true;
}
- virtual bool visitFuncNode(FuncNode *node){
- ImGui::Text("%s(", node->name->c_str());
+ virtual bool visitFuncNode(FuncNode *node) {
+ const bool isBuiltin = g_lingo->_builtinCmds.contains(*node->name);
+ const ImVec4 color = (ImVec4)ImColor(isBuiltin ? _state->_colors._builtin_color : _state->_colors._call_color);
+ ImGui::TextColored(color, "%s(", node->name->c_str());
+ if (!isBuiltin && ImGui::IsItemHovered() && ImGui::BeginTooltip()) {
+ ImGui::Text("Go to definition");
+ ImGui::EndTooltip();
+ }
+ if (!isBuiltin && ImGui::IsItemClicked()) {
+ int obj = 0;
+ for (uint i = 0; i < _script.bytecodeArray.size(); i++) {
+ if (node->startOffset == _script.bytecodeArray[i].pos) {
+ obj = _script.bytecodeArray[i].obj;
+ break;
+ }
+ }
+
+ ImGuiScript script = toImGuiScript(_script.type, CastMemberID(obj, _script.id.castLib), *node->name);
+ script.moviePath = _script.moviePath;
+ script.handlerName = *node->name;
+ setScriptToDisplay(script);
+ }
ImGui::SameLine();
for (uint i = 0; i < node->args->size(); i++) {
Node *arg = (*node->args)[i];
@@ -957,13 +1002,23 @@ public:
return true;
}
- virtual bool visitVarNode(VarNode *node){
- ImGui::Text("%s", node->name->c_str());
+ virtual bool visitVarNode(VarNode *node) {
+ ImGui::TextColored(_state->_colors._var_color, "%s", node->name->c_str());
+ if (ImGui::IsItemHovered() && g_lingo->_globalvars.contains(*node->name)) {
+ const Datum &val = g_lingo->_globalvars.getVal(*node->name);
+ ImGui::BeginTooltip();
+ ImGui::Text("Click to add to watches.");
+ ImGui::Text("= %s", val.asString(true).c_str());
+ ImGui::EndTooltip();
+ }
+ if (ImGui::IsItemClicked()) {
+ _state->_variables[*node->name] = true;
+ }
ImGui::SameLine();
return true;
}
- virtual bool visitParensNode(ParensNode *node){
+ virtual bool visitParensNode(ParensNode *node) {
ImGui::Text("(");
ImGui::SameLine();
node->expr->accept(this);
@@ -972,11 +1027,11 @@ public:
return true;
}
- virtual bool visitUnaryOpNode(UnaryOpNode *node){
+ virtual bool visitUnaryOpNode(UnaryOpNode *node) {
char op = '?';
- if(node->op == LC::c_negate) {
+ if (node->op == LC::c_negate) {
op = '-';
- } else if(node->op == LC::c_not) {
+ } else if (node->op == LC::c_not) {
op = '!';
}
ImGui::Text("%c", op);
@@ -985,7 +1040,7 @@ public:
return true;
}
- virtual bool visitBinaryOpNode(BinaryOpNode *node){
+ virtual bool visitBinaryOpNode(BinaryOpNode *node) {
node->a->accept(this);
static struct {
inst op;
@@ -1018,143 +1073,143 @@ public:
}
node->b->accept(this);
return true;
- }
+ }
- virtual bool visitFrameNode(FrameNode *node){
- ImGui::Text("frame ");
+ virtual bool visitFrameNode(FrameNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "frame ");
ImGui::SameLine();
node->arg->accept(this);
return true;
}
- virtual bool visitMovieNode(MovieNode *node){
- ImGui::Text("movie ");
+ virtual bool visitMovieNode(MovieNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "movie ");
ImGui::SameLine();
node->arg->accept(this);
return true;
}
- virtual bool visitIntersectsNode(IntersectsNode *node){
- ImGui::Text("sprite ");
+ virtual bool visitIntersectsNode(IntersectsNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "sprite ");
ImGui::SameLine();
node->sprite1->accept(this);
- ImGui::Text("intersects ");
+ ImGui::TextColored(_state->_colors._keyword_color, "intersects ");
node->sprite2->accept(this);
return true;
}
- virtual bool visitWithinNode(WithinNode *node){
- ImGui::Text("sprite ");
+ virtual bool visitWithinNode(WithinNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "sprite ");
ImGui::SameLine();
node->sprite1->accept(this);
- ImGui::Text("within ");
+ ImGui::TextColored(_state->_colors._keyword_color, "within ");
node->sprite2->accept(this);
return true;
}
- virtual bool visitTheNode(TheNode *node){
- ImGui::Text("the %s", node->prop->c_str());
+ virtual bool visitTheNode(TheNode *node) {
+ ImGui::TextColored(_state->_colors._the_color, "the %s", node->prop->c_str());
ImGui::SameLine();
return true;
}
- virtual bool visitTheOfNode(TheOfNode *node){
- ImGui::Text("the %s of ", node->prop->c_str());
+ virtual bool visitTheOfNode(TheOfNode *node) {
+ ImGui::TextColored(_state->_colors._the_color, "the %s of ", node->prop->c_str());
ImGui::SameLine();
node->obj->accept(this);
return true;
}
- virtual bool visitTheNumberOfNode(TheNumberOfNode *node){
- ImGui::Text("the number of ");
+ virtual bool visitTheNumberOfNode(TheNumberOfNode *node) {
+ ImGui::TextColored(_state->_colors._the_color, "the number of ");
ImGui::SameLine();
node->arg->accept(this);
return true;
}
- virtual bool visitTheLastNode(TheLastNode *node){
+ virtual bool visitTheLastNode(TheLastNode *node) {
// TODO: change the node to know if it's 'in' or 'of'
- ImGui::Text("the last %s in/of ", toString(node->type).c_str());
+ ImGui::TextColored(_state->_colors._the_color, "the last %s in/of ", toString(node->type).c_str());
ImGui::SameLine();
node->arg->accept(this);
return true;
}
- virtual bool visitTheDateTimeNode(TheDateTimeNode *node){
- const char* key1 = "";
- switch(node->field) {
- case kTheAbbr:
+ virtual bool visitTheDateTimeNode(TheDateTimeNode *node) {
+ const char *key1 = "";
+ switch (node->field) {
+ case kTheAbbr:
key1 = "abbreviated";
break;
- case kTheLong:
+ case kTheLong:
key1 = "long";
break;
- case kTheShort:
+ case kTheShort:
key1 = "short";
break;
}
const char *key2 = node->entity == kTheDate ? "date" : "time";
- ImGui::Text("the %s %s", key1, key2);
+ ImGui::TextColored(_state->_colors._the_color, "the %s %s", key1, key2);
ImGui::SameLine();
return true;
}
- virtual bool visitMenuNode(MenuNode *node){
- ImGui::Text("menu ");
+ virtual bool visitMenuNode(MenuNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "menu ");
ImGui::SameLine();
node->arg->accept(this);
return true;
}
- virtual bool visitMenuItemNode(MenuItemNode *node){
- ImGui::Text("menuitem ");
+ virtual bool visitMenuItemNode(MenuItemNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "menuitem ");
ImGui::SameLine();
node->arg1->accept(this);
- ImGui::Text("of menu ");
+ ImGui::TextColored(_state->_colors._keyword_color, "of menu ");
ImGui::SameLine();
node->arg2->accept(this);
return true;
}
- virtual bool visitSoundNode(SoundNode *node){
- ImGui::Text("sound ");
+ virtual bool visitSoundNode(SoundNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "sound ");
ImGui::SameLine();
node->arg->accept(this);
return true;
}
- virtual bool visitSpriteNode(SpriteNode *node){
- ImGui::Text("sprite ");
+ virtual bool visitSpriteNode(SpriteNode *node) {
+ ImGui::TextColored(_state->_colors._keyword_color, "sprite ");
ImGui::SameLine();
node->arg->accept(this);
return true;
}
- virtual bool visitChunkExprNode(ChunkExprNode *node){
- const char* key1 = "";
- switch(node->type) {
- case kChunkChar:
+ virtual bool visitChunkExprNode(ChunkExprNode *node) {
+ const char *key1 = "";
+ switch (node->type) {
+ case kChunkChar:
key1 = "char";
break;
- case kChunkWord:
+ case kChunkWord:
key1 = "word";
break;
- case kChunkItem:
+ case kChunkItem:
key1 = "item";
break;
- case kChunkLine:
+ case kChunkLine:
key1 = "line";
break;
}
ImGui::Text("%s", key1);
ImGui::SameLine();
node->start->accept(this);
- if(node->end) {
- ImGui::Text(" to ");
+ if (node->end) {
+ ImGui::TextColored(_state->_colors._keyword_color, " to ");
ImGui::SameLine();
node->end->accept(this);
}
- ImGui::Text(" of ");
+ ImGui::TextColored(_state->_colors._keyword_color, " of ");
ImGui::SameLine();
node->src->accept(this);
return true;
@@ -1163,14 +1218,14 @@ public:
private:
static Common::String toString(ChunkType chunkType) {
// TODO: this method could be used in ChunkExprNode
- switch(chunkType) {
- case kChunkChar:
+ switch (chunkType) {
+ case kChunkChar:
return "char";
- case kChunkWord:
+ case kChunkWord:
return "word";
- case kChunkItem:
+ case kChunkItem:
return "item";
- case kChunkLine:
+ case kChunkLine:
return "line";
}
return "<unknown>";
@@ -1191,7 +1246,81 @@ private:
ImGui::SameLine();
}
}
+
+ void renderLine(uint32 pc) {
+ bool showCurrentStatement = false;
+ _script.startOffsets.push_back(pc);
+
+ if (_isScriptInDebug && g_lingo->_exec._state == kPause) {
+ // check current statement
+ if (!_currentStatementDisplayed) {
+ if (g_lingo->_state->pc <= pc) {
+ showCurrentStatement = true;
+ _currentStatementDisplayed = true;
+ }
+ }
+ }
+
+ ImDrawList *dl = ImGui::GetWindowDrawList();
+ const ImVec2 pos = ImGui::GetCursorScreenPos();
+ const float width = ImGui::GetContentRegionAvail().x;
+ const ImVec2 mid(pos.x + 7, pos.y + 7);
+
+ ImVec4 color = _state->_colors._bp_color_disabled;
+ const Director::Breakpoint *bp = getBreakpoint(_script.handlerId, _script.id.member, pc);
+ if (bp)
+ color = _state->_colors._bp_color_enabled;
+
+ ImGui::InvisibleButton("Line", ImVec2(16, ImGui::GetFontSize()));
+
+ // click on breakpoint column?
+ if (ImGui::IsItemClicked(0)) {
+ if (color == _state->_colors._bp_color_enabled) {
+ g_lingo->delBreakpoint(bp->id);
+ color = _state->_colors._bp_color_disabled;
+ } else {
+ Director::Breakpoint newBp;
+ newBp.type = kBreakpointFunction;
+ newBp.scriptId = _script.id.member;
+ newBp.funcName = _script.handlerId;
+ newBp.funcOffset = pc;
+ g_lingo->addBreakpoint(newBp);
+ color = _state->_colors._bp_color_enabled;
+ }
+ }
+
+ if (color == _state->_colors._bp_color_disabled && ImGui::IsItemHovered()) {
+ color = _state->_colors._bp_color_hover;
+ }
+
+ // draw breakpoint
+ if (!bp || bp->enabled)
+ dl->AddCircleFilled(mid, 4.0f, ImColor(color));
+ else
+ dl->AddCircle(mid, 4.0f, ImColor(_state->_colors._line_color));
+
+ // draw current statement
+ 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 && !ImGui::IsItemVisible()) {
+ 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);
+ }
+ // draw separator
+ dl->AddLine(ImVec2(pos.x + 16.0f, pos.y), ImVec2(pos.x + 16.0f, pos.y + 17), ImColor(_state->_colors._line_color));
+
+ ImGui::SetItemTooltip("Click to add a breakpoint");
+ ImGui::SameLine();
+
+ // draw offset
+ ImGui::Text("[%5d] ", pc == 0xFFFFFFFF ? -1 : pc);
+ ImGui::SameLine();
+ renderIndentation();
+ }
};
+
class RenderScriptVisitor : public LingoDec::NodeVisitor {
public:
RenderScriptVisitor(ImGuiScript &script, bool showByteCode) : _script(script), _showByteCode(showByteCode) {
@@ -2132,7 +2261,7 @@ private:
ImGui::Text(", ");
ImGui::SameLine();
}
- ImGui::TextColored(_state->_colors._var_color, "%s", _script.argumentNames[i].c_str());
+ ImGui::Text("%s", _script.argumentNames[i].c_str());
ImGui::SameLine();
}
}
@@ -2367,6 +2496,8 @@ private:
static uint32 getLineFromPC() {
const uint pc = g_lingo->_state->pc;
+ if (_state->_functions._scripts.empty())
+ return 0;
const Common::Array<uint> &offsets = _state->_functions._scripts[_state->_functions._current].startOffsets;
for (uint i = 0; i < offsets.size(); i++) {
if (pc <= offsets[i])
@@ -3446,16 +3577,18 @@ static void displayScripts() {
}
ImGui::EndCombo();
}
- ImGui::SameLine(0, 20);
- toggleButton("\uf569", &_state->_functions._showByteCode, true); // Lingo // package_2
- ImGui::SetItemTooltip("Lingo");
- ImGui::SameLine();
+ if (!_state->_functions._scripts[_state->_functions._current].oldAst) {
+ ImGui::SameLine(0, 20);
+ toggleButton("\uf569", &_state->_functions._showByteCode, true); // Lingo // package_2
+ ImGui::SetItemTooltip("Lingo");
+ ImGui::SameLine();
- toggleButton("\uf500", &_state->_functions._showByteCode); // Bytecode // stacks
- ImGui::SetItemTooltip("Bytecode");
- ImGui::Separator();
+ toggleButton("\uf500", &_state->_functions._showByteCode); // Bytecode // stacks
+ ImGui::SetItemTooltip("Bytecode");
+ }
+ ImGui::Separator();
const ImVec2 childsize = ImGui::GetContentRegionAvail();
ImGui::BeginChild("##script", childsize);
ImGuiScript &script = _state->_functions._scripts[_state->_functions._current];
More information about the Scummvm-git-logs
mailing list