From 564d7e5029064b752f78d3cc7401a14f9071beb3 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 1 Jun 2022 21:31:05 +0100 Subject: [PATCH] Debug: Allow clicking to highlight group in sprite group dump window --- src/newgrf_debug_gui.cpp | 31 +++++++++++++-- src/newgrf_engine.cpp | 2 +- src/newgrf_industries.cpp | 4 +- src/newgrf_object.cpp | 2 +- src/newgrf_roadstop.cpp | 2 +- src/newgrf_spritegroup.cpp | 72 ++++++++++++++++++----------------- src/newgrf_spritegroup.h | 4 +- src/table/newgrf_debug_data.h | 24 ++++++------ 8 files changed, 84 insertions(+), 57 deletions(-) diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index e83df24519..f80c7ab74b 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -213,7 +213,7 @@ public: } virtual void ExtraInfo(uint index, NIExtraInfoOutput &output) const {} - virtual void SpriteDump(uint index, std::function print) const {} + virtual void SpriteDump(uint index, DumpSpriteGroupPrinter print) const {} virtual bool ShowExtraInfoOnly(uint index) const { return false; }; virtual bool ShowSpriteDumpButton(uint index) const { return false; }; @@ -318,6 +318,8 @@ struct NewGRFInspectWindow : Window { uint32 extra_info_flags = 0; btree::btree_map extra_info_click_flag_toggles; + btree::btree_map sprite_group_lines; + const SpriteGroup *selected_sprite_group = nullptr; /** * Check whether the given variable has a parameter. @@ -521,8 +523,20 @@ struct NewGRFInspectWindow : Window { ::DrawString(r.left + LEFT_OFFSET, r.right - RIGHT_OFFSET, r.top + TOP_OFFSET + (offset * this->resize.step_height), buf, TC_BLACK); }; + const_cast(this)->sprite_group_lines.clear(); if (this->sprite_dump) { - nih->SpriteDump(index, line_handler); + nih->SpriteDump(index, [&](const SpriteGroup *group, const char *buf) { + if (this->log_console) DEBUG(misc, 0, " %s", buf); + + int offset = i++; + int scroll_offset = offset - this->vscroll->GetPosition(); + if (scroll_offset < 0 || scroll_offset >= this->vscroll->GetCapacity()) return; + + const_cast(this)->sprite_group_lines[offset] = group; + + TextColour colour = (this->selected_sprite_group == group) ? TC_LIGHT_BLUE : TC_BLACK; + ::DrawString(r.left + LEFT_OFFSET, r.right - RIGHT_OFFSET, r.top + TOP_OFFSET + (scroll_offset * this->resize.step_height), buf, colour); + }); return; } else { NewGRFInspectWindow *this_mutable = const_cast(this); @@ -711,12 +725,21 @@ struct NewGRFInspectWindow : Window { break; case WID_NGRFI_MAINPANEL: { - if (this->sprite_dump) return; - /* Get the line, make sure it's within the boundaries. */ int line = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NGRFI_MAINPANEL, TOP_OFFSET); if (line == INT_MAX) return; + if (this->sprite_dump) { + 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 || this->selected_sprite_group != nullptr) { + this->selected_sprite_group = (group == this->selected_sprite_group) ? nullptr : group; + this->SetWidgetDirty(WID_NGRFI_MAINPANEL); + } + return; + } + auto iter = this->extra_info_click_flag_toggles.find(line); if (iter != this->extra_info_click_flag_toggles.end()) { this->extra_info_flags ^= iter->second; diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 13ba3fdf53..f8aad753fe 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -1619,7 +1619,7 @@ void AnalyseEngineCallbacks() } } -void DumpVehicleSpriteGroup(const Vehicle *v, std::function print) +void DumpVehicleSpriteGroup(const Vehicle *v, DumpSpriteGroupPrinter print) { const SpriteGroup *root_spritegroup = nullptr; if (v->IsGroundVehicle()) root_spritegroup = GetWagonOverrideSpriteSet(v->engine_type, v->cargo_type, v->GetGroundVehicleCache()->first_engine); diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index 50809a1b8d..19592f4dc0 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -691,12 +691,12 @@ bool IndustryTemporarilyRefusesCargo(Industry *ind, CargoID cargo_type) return false; } -void DumpIndustrySpriteGroup(const IndustrySpec *spec, std::function print) +void DumpIndustrySpriteGroup(const IndustrySpec *spec, DumpSpriteGroupPrinter print) { DumpSpriteGroup(spec->grf_prop.spritegroup[0], std::move(print)); } -void DumpIndustryTileSpriteGroup(const IndustryTileSpec *spec, std::function print) +void DumpIndustryTileSpriteGroup(const IndustryTileSpec *spec, DumpSpriteGroupPrinter print) { DumpSpriteGroup(spec->grf_prop.spritegroup[0], std::move(print)); } diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp index 9d27c9a68d..305eddb20f 100644 --- a/src/newgrf_object.cpp +++ b/src/newgrf_object.cpp @@ -617,7 +617,7 @@ void TriggerObjectAnimation(Object *o, ObjectAnimationTrigger trigger, const Obj } } -void DumpObjectSpriteGroup(const ObjectSpec *spec, std::function print) +void DumpObjectSpriteGroup(const ObjectSpec *spec, DumpSpriteGroupPrinter print) { DumpSpriteGroup(spec->grf_prop.spritegroup[0], std::move(print)); } diff --git a/src/newgrf_roadstop.cpp b/src/newgrf_roadstop.cpp index 5f4a76e126..7299fe7cf4 100644 --- a/src/newgrf_roadstop.cpp +++ b/src/newgrf_roadstop.cpp @@ -634,7 +634,7 @@ void StationUpdateRoadStopCachedTriggers(BaseStation *st) } } -void DumpRoadStopSpriteGroup(const BaseStation *st, const RoadStopSpec *spec, std::function print) +void DumpRoadStopSpriteGroup(const BaseStation *st, const RoadStopSpec *spec, DumpSpriteGroupPrinter print) { CargoID ctype = CT_DEFAULT_NA; diff --git a/src/newgrf_spritegroup.cpp b/src/newgrf_spritegroup.cpp index a1d7ce4d98..d2f4744ef2 100644 --- a/src/newgrf_spritegroup.cpp +++ b/src/newgrf_spritegroup.cpp @@ -607,19 +607,17 @@ const DrawTileSprites *TileLayoutSpriteGroup::ProcessRegisters(uint8 *stage) con struct SpriteGroupDumper { private: char buffer[1024]; - std::function print_fn; + DumpSpriteGroupPrinter print_fn; const SpriteGroup *top_default_group = nullptr; btree::btree_set seen_dsgs; - void print() { this->print_fn(this->buffer); } - enum SpriteGroupDumperFlags { SGDF_DEFAULT = 1 << 0, }; public: - SpriteGroupDumper(std::function print) : print_fn(print) {} + SpriteGroupDumper(DumpSpriteGroupPrinter print) : print_fn(print) {} void DumpSpriteGroup(const SpriteGroup *sg, int padding, uint flags); }; @@ -684,9 +682,13 @@ static const char *GetAdjustOperationName(DeterministicSpriteGroupAdjustOperatio void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint flags) { + auto print = [&]() { + this->print_fn(sg, this->buffer); + }; + if (sg == nullptr) { seprintf(this->buffer, lastof(this->buffer), "%*sNULL GROUP", padding, ""); - this->print(); + print(); return; } @@ -695,15 +697,15 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint 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); - this->print(); + print(); for (size_t i = 0; i < rsg->loaded.size(); i++) { seprintf(this->buffer, lastof(this->buffer), "%*sLoaded %u", padding + 2, "", (uint)i); - this->print(); + print(); this->DumpSpriteGroup(rsg->loaded[i], padding + 4, 0); } for (size_t i = 0; i < rsg->loading.size(); i++) { seprintf(this->buffer, lastof(this->buffer), "%*sLoading %u", padding + 2, "", (uint)i); - this->print(); + print(); this->DumpSpriteGroup(rsg->loading[i], padding + 4, 0); } break; @@ -716,25 +718,25 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint if (dsg == this->top_default_group && !(padding == 4 && (flags & SGDF_DEFAULT))) { seprintf(this->buffer, lastof(this->buffer), "%*sTOP LEVEL DEFAULT GROUP: Deterministic (%s, %s), [%u]", padding, "", _sg_scope_names[dsg->var_scope], _sg_size_names[dsg->size], dsg->nfo_line); - this->print(); + print(); return; } auto res = this->seen_dsgs.insert(dsg); if (!res.second) { seprintf(this->buffer, lastof(this->buffer), "%*sGROUP SEEN ABOVE: Deterministic (%s, %s), [%u]", padding, "", _sg_scope_names[dsg->var_scope], _sg_size_names[dsg->size], dsg->nfo_line); - this->print(); + print(); return; } 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); - this->print(); + print(); padding += 2; for (const auto &adjust : dsg->adjusts) { char *p = this->buffer; if (adjust.operation == DSGA_OP_TERNARY) { p += seprintf(p, lastof(this->buffer), "%*sTERNARY: true: %X, false: %X", padding, "", adjust.and_mask, adjust.add_val); - this->print(); + print(); continue; } p += seprintf(p, lastof(this->buffer), "%*svar: %X", padding, "", adjust.variable); @@ -757,23 +759,23 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint case DSGA_TYPE_NONE: break; } p += seprintf(p, lastof(this->buffer), ", op: %X (%s)", adjust.operation, GetAdjustOperationName(adjust.operation)); - this->print(); + print(); if (adjust.variable == 0x7E && adjust.subroutine != nullptr) { this->DumpSpriteGroup(adjust.subroutine, padding + 5, 0); } } if (dsg->calculated_result) { seprintf(this->buffer, lastof(this->buffer), "%*scalculated_result", padding, ""); - this->print(); + print(); } else { for (const auto &range : dsg->ranges) { seprintf(this->buffer, lastof(this->buffer), "%*srange: %X -> %X", padding, "", range.low, range.high); - this->print(); + print(); this->DumpSpriteGroup(range.group, padding + 2, 0); } if (dsg->default_group != nullptr) { seprintf(this->buffer, lastof(this->buffer), "%*sdefault", padding, ""); - this->print(); + print(); this->DumpSpriteGroup(dsg->default_group, padding + 2, SGDF_DEFAULT); } } @@ -784,7 +786,7 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint seprintf(this->buffer, lastof(this->buffer), "%*sRandom (%s, %s, triggers: %X, count: %X, lowest_randbit: %X, groups: %u) [%u]", 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); - this->print(); + print(); for (const auto &group : rsg->groups) { this->DumpSpriteGroup(group, padding + 2, 0); } @@ -792,17 +794,17 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint } case SGT_CALLBACK: seprintf(this->buffer, lastof(this->buffer), "%*sCallback Result: %X", padding, "", ((const CallbackResultSpriteGroup *) sg)->result); - this->print(); + print(); break; case SGT_RESULT: seprintf(this->buffer, lastof(this->buffer), "%*sSprite Result: SpriteID: %u, num: %u", padding, "", ((const ResultSpriteGroup *) sg)->sprite, ((const ResultSpriteGroup *) sg)->num_sprites); - this->print(); + print(); break; case SGT_TILELAYOUT: { const TileLayoutSpriteGroup *tlsg = (const TileLayoutSpriteGroup*)sg; seprintf(this->buffer, lastof(this->buffer), "%*sTile Layout [%u]", padding, "", sg->nfo_line); - this->print(); + print(); padding += 2; if (tlsg->dts.registers != nullptr) { const TileLayoutRegisters *registers = tlsg->dts.registers; @@ -812,42 +814,42 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint for (size_t i = 0; i < count; i ++) { const TileLayoutRegisters *reg = registers + i; seprintf(this->buffer, lastof(this->buffer), "%*ssection: %X, register flags: %X", padding, "", (uint)i, reg->flags); - this->print(); + print(); if (reg->flags & TLF_DODRAW) { seprintf(this->buffer, lastof(this->buffer), "%*sTLF_DODRAW reg: %X", padding + 2, "", reg->dodraw); - this->print(); + print(); } if (reg->flags & TLF_SPRITE) { seprintf(this->buffer, lastof(this->buffer), "%*sTLF_SPRITE reg: %X", padding + 2, "", reg->sprite); - this->print(); + print(); } if (reg->flags & TLF_PALETTE) { seprintf(this->buffer, lastof(this->buffer), "%*sTLF_PALETTE reg: %X", padding + 2, "", reg->palette); - this->print(); + print(); } if (reg->flags & TLF_BB_XY_OFFSET) { seprintf(this->buffer, lastof(this->buffer), "%*sTLF_BB_XY_OFFSET reg: %X, %X", padding + 2, "", reg->delta.parent[0], reg->delta.parent[1]); - this->print(); + print(); } if (reg->flags & TLF_BB_Z_OFFSET) { seprintf(this->buffer, lastof(this->buffer), "%*sTLF_BB_Z_OFFSET reg: %X", padding + 2, "", reg->delta.parent[2]); - this->print(); + print(); } if (reg->flags & TLF_CHILD_X_OFFSET) { seprintf(this->buffer, lastof(this->buffer), "%*sTLF_CHILD_X_OFFSET reg: %X", padding + 2, "", reg->delta.child[0]); - this->print(); + print(); } if (reg->flags & TLF_CHILD_Y_OFFSET) { seprintf(this->buffer, lastof(this->buffer), "%*sTLF_CHILD_Y_OFFSET reg: %X", padding + 2, "", reg->delta.child[1]); - this->print(); + print(); } if (reg->flags & TLF_SPRITE_VAR10) { seprintf(this->buffer, lastof(this->buffer), "%*sTLF_SPRITE_VAR10 value: %X", padding + 2, "", reg->sprite_var10); - this->print(); + print(); } if (reg->flags & TLF_PALETTE_VAR10) { seprintf(this->buffer, lastof(this->buffer), "%*sTLF_PALETTE_VAR10 value: %X", padding + 2, "", reg->palette_var10); - this->print(); + print(); } } } @@ -856,15 +858,15 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint case SGT_INDUSTRY_PRODUCTION: { const IndustryProductionSpriteGroup *ipsg = (const IndustryProductionSpriteGroup*)sg; seprintf(this->buffer, lastof(this->buffer), "%*sIndustry Production (version %X) [%u]", padding, "", ipsg->version, ipsg->nfo_line); - this->print(); + print(); auto log_io = [&](const char *prefix, int i, int quantity, CargoID cargo) { if (ipsg->version >= 2) { seprintf(this->buffer, lastof(this->buffer), "%*s%s %X: reg %X, cargo ID: %X", padding + 2, "", prefix, i, quantity, cargo); - this->print(); + print(); } else { const char *type = (ipsg->version >= 1) ? "reg" : "value"; seprintf(this->buffer, lastof(this->buffer), "%*s%s %X: %s %X", padding + 2, "", prefix, i, type, quantity); - this->print(); + print(); } }; for (int i = 0; i < ipsg->num_input; i++) { @@ -874,13 +876,13 @@ void SpriteGroupDumper::DumpSpriteGroup(const SpriteGroup *sg, int padding, uint log_io("Add input", i, ipsg->add_output[i], ipsg->cargo_output[i]); } seprintf(this->buffer, lastof(this->buffer), "%*sAgain: %s %X", padding + 2, "", (ipsg->version >= 1) ? "reg" : "value", ipsg->again); - this->print(); + print(); break; } } } -void DumpSpriteGroup(const SpriteGroup *sg, std::function print) +void DumpSpriteGroup(const SpriteGroup *sg, DumpSpriteGroupPrinter print) { SpriteGroupDumper dumper(std::move(print)); dumper.DumpSpriteGroup(sg, 0, 0); diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h index 9a50a4bab2..8f227ce22a 100644 --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -569,7 +569,9 @@ struct ResolverObject { virtual uint32 GetDebugID() const { return 0; } }; -void DumpSpriteGroup(const SpriteGroup *sg, std::function print); +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); #endif /* NEWGRF_SPRITEGROUP_H */ diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h index ab866e95d9..159f413841 100644 --- a/src/table/newgrf_debug_data.h +++ b/src/table/newgrf_debug_data.h @@ -397,9 +397,9 @@ class NIHVehicle : public NIHelper { output.print(buffer); } - /* virtual */ void SpriteDump(uint index, std::function print) const override + /* virtual */ void SpriteDump(uint index, DumpSpriteGroupPrinter print) const override { - extern void DumpVehicleSpriteGroup(const Vehicle *v, std::function print); + extern void DumpVehicleSpriteGroup(const Vehicle *v, DumpSpriteGroupPrinter print); DumpVehicleSpriteGroup(Vehicle::Get(index), std::move(print)); } }; @@ -467,7 +467,7 @@ class NIHStation : public NIHelper { return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, extra); } - /* virtual */ void SpriteDump(uint index, std::function print) const override + /* virtual */ void SpriteDump(uint index, DumpSpriteGroupPrinter print) const override { StationResolverObject ro(GetStationSpec(index), Station::GetByTile(index), index, INVALID_RAILTYPE); DumpSpriteGroup(ro.root_spritegroup, std::move(print)); @@ -567,7 +567,7 @@ class NIHHouse : public NIHelper { } } - /* virtual */ void SpriteDump(uint index, std::function print) const override + /* virtual */ void SpriteDump(uint index, DumpSpriteGroupPrinter print) const override { DumpSpriteGroup(HouseSpec::Get(GetHouseType(index))->grf_prop.spritegroup[0], std::move(print)); } @@ -640,11 +640,11 @@ class NIHIndustryTile : public NIHelper { } } - /* virtual */ void SpriteDump(uint index, std::function print) const override + /* virtual */ void SpriteDump(uint index, DumpSpriteGroupPrinter print) const override { const IndustryTileSpec *indts = GetIndustryTileSpec(GetIndustryGfx(index)); if (indts) { - extern void DumpIndustryTileSpriteGroup(const IndustryTileSpec *spec, std::function print); + extern void DumpIndustryTileSpriteGroup(const IndustryTileSpec *spec, DumpSpriteGroupPrinter print); DumpIndustryTileSpriteGroup(indts, std::move(print)); } } @@ -832,11 +832,11 @@ class NIHIndustry : public NIHelper { } } - /* virtual */ void SpriteDump(uint index, std::function print) const override + /* virtual */ void SpriteDump(uint index, DumpSpriteGroupPrinter print) const override { const Industry *ind = Industry::GetIfValid(index); if (ind) { - extern void DumpIndustrySpriteGroup(const IndustrySpec *spec, std::function print); + extern void DumpIndustrySpriteGroup(const IndustrySpec *spec, DumpSpriteGroupPrinter print); DumpIndustrySpriteGroup(GetIndustrySpec(ind->type), std::move(print)); } } @@ -970,9 +970,9 @@ class NIHObject : public NIHelper { } } - /* virtual */ void SpriteDump(uint index, std::function print) const override + /* virtual */ void SpriteDump(uint index, DumpSpriteGroupPrinter print) const override { - extern void DumpObjectSpriteGroup(const ObjectSpec *spec, std::function print); + extern void DumpObjectSpriteGroup(const ObjectSpec *spec, DumpSpriteGroupPrinter print); DumpObjectSpriteGroup(ObjectSpec::GetByTile(index), std::move(print)); } }; @@ -1482,9 +1482,9 @@ class NIHRoadStop : public NIHelper { } } - /* virtual */ void SpriteDump(uint index, std::function print) const override + /* virtual */ void SpriteDump(uint index, DumpSpriteGroupPrinter print) const override { - extern void DumpRoadStopSpriteGroup(const BaseStation *st, const RoadStopSpec *spec, std::function print); + extern void DumpRoadStopSpriteGroup(const BaseStation *st, const RoadStopSpec *spec, DumpSpriteGroupPrinter print); DumpRoadStopSpriteGroup(BaseStation::GetByTile(index), GetRoadStopSpec(index), std::move(print)); } };