diff --git a/src/lang/english.txt b/src/lang/english.txt index d16cb1addc..122922fd09 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -4208,7 +4208,7 @@ STR_NEWGRF_INSPECT_LOG_CONSOLE :{BLACK}L STR_NEWGRF_INSPECT_LOG_CONSOLE_TOOLTIP :{BLACK}Log text content of this window to the console STR_NEWGRF_INSPECT_SPRITE_DUMP :{BLACK}S STR_NEWGRF_INSPECT_SPRITE_DUMP_TOOLTIP :{BLACK}Display current sprite chain -STR_NEWGRF_INSPECT_SPRITE_DUMP_PANEL_TOOLTIP :{BLACK}Click to highlight sprite group{}Ctrl+Click to highlight temporary storage register +STR_NEWGRF_INSPECT_SPRITE_DUMP_PANEL_TOOLTIP :{BLACK}Click to highlight sprite group{}Shift+Click to collapse sprite group{}Ctrl+Click to highlight temporary storage register STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT :{STRING1} at {HEX} STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT_OBJECT :Object diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index 8e41f29736..98becf5d0f 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -322,6 +322,7 @@ struct NewGRFInspectWindow : Window { const SpriteGroup *selected_sprite_group = nullptr; btree::btree_map highlight_tag_lines; uint32 selected_highlight_tag = 0; + btree::btree_set collapsed_groups; /** * Check whether the given variable has a parameter. @@ -527,8 +528,31 @@ struct NewGRFInspectWindow : Window { }; const_cast(this)->sprite_group_lines.clear(); if (this->sprite_dump) { - nih->SpriteDump(index, [&](const SpriteGroup *group, uint32 highlight_tag, const char *buf) { - if (this->log_console) DEBUG(misc, 0, " %s", buf); + bool collapsed = false; + const SpriteGroup *collapse_group = nullptr; + uint collapse_lines = 0; + char tmp_buf[256]; + nih->SpriteDump(index, [&](const SpriteGroup *group, DumpSpriteGroupPrintOp operation, uint32 highlight_tag, const char *buf) { + if (this->log_console && operation == DSGPO_PRINT) DEBUG(misc, 0, " %s", buf); + + if (operation == DSGPO_START && !collapsed && this->collapsed_groups.count(group)) { + collapsed = true; + collapse_group = group; + collapse_lines = 0; + } + if (operation == DSGPO_END && collapsed && collapse_group == group) { + seprintf(tmp_buf, lastof(tmp_buf), "%*sCOLLAPSED: %u lines omitted", highlight_tag + 2, "", collapse_lines); + buf = tmp_buf; + collapsed = false; + highlight_tag = 0; + operation = DSGPO_PRINT; + } + + if (operation != DSGPO_PRINT) return; + if (collapsed) { + collapse_lines++; + return; + } int offset = i++; int scroll_offset = offset - this->vscroll->GetPosition(); @@ -742,6 +766,20 @@ struct NewGRFInspectWindow : Window { this->selected_highlight_tag = (highlight_tag == this->selected_highlight_tag) ? 0 : highlight_tag; this->SetWidgetDirty(WID_NGRFI_MAINPANEL); } + } else if (_shift_pressed) { + const SpriteGroup *group = nullptr; + auto iter = this->sprite_group_lines.find(line); + if (iter != this->sprite_group_lines.end()) group = iter->second; + if (group != nullptr) { + auto iter = this->collapsed_groups.lower_bound(group); + if (iter != this->collapsed_groups.end() && *iter == group) { + this->collapsed_groups.erase(iter); + } else { + this->collapsed_groups.insert(iter, group); + } + this->SetWidgetDirty(WID_NGRFI_MAINPANEL); + } + } else { const SpriteGroup *group = nullptr; auto iter = this->sprite_group_lines.find(line); diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index 99abd01a17..671147ba78 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -17,6 +17,7 @@ #include "string_func.h" #include "newgrf_extension.h" #include "newgrf_industrytiles_analysis.h" +#include "scope.h" #include "safeguards.h" @@ -688,7 +689,7 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint { uint32 highlight_tag = 0; auto print = [&]() { - this->print_fn(sg, highlight_tag, this->buffer); + this->print_fn(sg, DSGPO_PRINT, highlight_tag, this->buffer); highlight_tag = 0; }; @@ -698,12 +699,24 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint return; } + bool start_emitted = false; + auto emit_start = [&]() { + this->print_fn(sg, DSGPO_START, 0, nullptr); + start_emitted = true; + }; + auto guard = scope_guard([&]() { + if (start_emitted) { + this->print_fn(sg, DSGPO_END, padding, nullptr); + } + }); + switch (sg->type) { case SGT_REAL: { const RealSpriteGroup *rsg = (const RealSpriteGroup*)sg; seprintf(this->buffer, lastof(this->buffer), "%*sReal (loaded: %u, loading: %u) [%u]", padding, "", (uint)rsg->loaded.size(), (uint)rsg->loading.size(), sg->nfo_line); print(); + emit_start(); for (size_t i = 0; i < rsg->loaded.size(); i++) { seprintf(this->buffer, lastof(this->buffer), "%*sLoaded %u", padding + 2, "", (uint)i); print(); @@ -737,6 +750,7 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint seprintf(this->buffer, lastof(this->buffer), "%*sDeterministic (%s, %s), [%u]", padding, "", _sg_scope_names[dsg->var_scope], _sg_size_names[dsg->size], dsg->nfo_line); print(); + emit_start(); padding += 2; for (const auto &adjust : dsg->adjusts) { char *p = this->buffer; @@ -807,6 +821,7 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint padding, "", _sg_scope_names[rsg->var_scope], rsg->cmp_mode == RSG_CMP_ANY ? "ANY" : "ALL", rsg->triggers, rsg->count, rsg->lowest_randbit, (uint)rsg->groups.size(), rsg->nfo_line); print(); + emit_start(); for (const auto &group : rsg->groups) { this->DumpSpriteGroup(group, padding + 2, 0); } @@ -825,6 +840,7 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint const TileLayoutSpriteGroup *tlsg = (const TileLayoutSpriteGroup*)sg; seprintf(this->buffer, lastof(this->buffer), "%*sTile Layout [%u]", padding, "", sg->nfo_line); print(); + emit_start(); padding += 2; if (tlsg->dts.registers != nullptr) { const TileLayoutRegisters *registers = tlsg->dts.registers; @@ -866,6 +882,7 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint const IndustryProductionSpriteGroup *ipsg = (const IndustryProductionSpriteGroup*)sg; seprintf(this->buffer, lastof(this->buffer), "%*sIndustry Production (version %X) [%u]", padding, "", ipsg->version, ipsg->nfo_line); print(); + emit_start(); auto log_io = [&](const char *prefix, int i, int quantity, CargoID cargo) { if (ipsg->version >= 1) highlight_tag = (1 << 16) | quantity; if (ipsg->version >= 2) { diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 540a0ece5d..e2dd4e0d0e 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -579,7 +579,13 @@ struct ResolverObject { virtual uint32 GetDebugID() const { return 0; } }; -using DumpSpriteGroupPrinter = std::function; +enum DumpSpriteGroupPrintOp { + DSGPO_PRINT, + DSGPO_START, + DSGPO_END, +}; + +using DumpSpriteGroupPrinter = std::function; void DumpSpriteGroup(const SpriteGroup *sg, DumpSpriteGroupPrinter print); uint32 EvaluateDeterministicSpriteGroupAdjust(DeterministicSpriteGroupSize size, const DeterministicSpriteGroupAdjust &adjust, ScopeResolver *scope, uint32 last_value, uint32 value);