diff --git a/src/autoreplace_gui.cpp b/src/autoreplace_gui.cpp --- a/src/autoreplace_gui.cpp +++ b/src/autoreplace_gui.cpp @@ -148,7 +148,7 @@ class ReplaceVehicleWindow : public Wind GUIEngineList list; for (const Engine *e : Engine::IterateType(type)) { - if (!draw_left && !this->show_hidden_engines && e->IsHidden(_local_company)) continue; + if (!draw_left && !this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue; EngineID eid = e->index; switch (type) { case VEH_TRAIN: diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -1349,7 +1349,7 @@ struct BuildVehicleWindow : Window { * and if not, reset selection to INVALID_ENGINE. This could be the case * when engines become obsolete and are removed */ for (const Engine *e : Engine::IterateType(VEH_TRAIN)) { - if (!this->show_hidden_engines && e->IsHidden(_local_company)) continue; + if (!this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue; EngineID eid = e->index; const RailVehicleInfo *rvi = &e->u.rail; @@ -1400,7 +1400,7 @@ struct BuildVehicleWindow : Window { this->eng_list.clear(); for (const Engine *e : Engine::IterateType(VEH_ROAD)) { - if (!this->show_hidden_engines && e->IsHidden(_local_company)) continue; + if (!this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue; EngineID eid = e->index; if (!IsEngineBuildable(eid, VEH_ROAD, _local_company)) continue; if (this->filter.roadtype != INVALID_ROADTYPE && !HasPowerOnRoad(e->u.road.roadtype, this->filter.roadtype)) continue; @@ -1419,7 +1419,7 @@ struct BuildVehicleWindow : Window { this->eng_list.clear(); for (const Engine *e : Engine::IterateType(VEH_SHIP)) { - if (!this->show_hidden_engines && e->IsHidden(_local_company)) continue; + if (!this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue; EngineID eid = e->index; if (!IsEngineBuildable(eid, VEH_SHIP, _local_company)) continue; this->eng_list.emplace_back(eid, e->info.variant_id, e->display_flags, 0); @@ -1443,7 +1443,7 @@ struct BuildVehicleWindow : Window { * and if not, reset selection to INVALID_ENGINE. This could be the case * when planes become obsolete and are removed */ for (const Engine *e : Engine::IterateType(VEH_AIRCRAFT)) { - if (!this->show_hidden_engines && e->IsHidden(_local_company)) continue; + if (!this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue; EngineID eid = e->index; if (!IsEngineBuildable(eid, VEH_AIRCRAFT, _local_company)) continue; /* First VEH_END window_numbers are fake to allow a window open for all different types at once */ diff --git a/src/engine.cpp b/src/engine.cpp --- a/src/engine.cpp +++ b/src/engine.cpp @@ -476,6 +476,30 @@ StringID Engine::GetAircraftTypeText() c } /** + * Check whether the engine variant chain is hidden in the GUI for the given company. + * @param c Company to check. + * @return \c true iff the engine variant chain is hidden in the GUI for the given company. + */ +bool Engine::IsVariantHidden(CompanyID c) const +{ + /* In case company is spectator. */ + if (c >= MAX_COMPANIES) return false; + + /* Shortcut if this engine is explicitly hidden. */ + if (this->IsHidden(c)) return true; + + /* Check for hidden parent variants. This is a bit convoluted as we must check hidden status of + * the last display variant rather than the actual parent variant. */ + const Engine *re = this; + const Engine *ve = re->GetDisplayVariant(); + while (!(ve->IsHidden(c)) && re->info.variant_id != INVALID_ENGINE && re->info.variant_id != re->index) { + re = Engine::Get(re->info.variant_id); + ve = re->GetDisplayVariant(); + } + return ve->IsHidden(c); +} + +/** * Initializes the #EngineOverrideManager with the default engines. */ void EngineOverrideManager::ResetToDefaultMapping() diff --git a/src/engine_base.h b/src/engine_base.h --- a/src/engine_base.h +++ b/src/engine_base.h @@ -138,6 +138,18 @@ struct Engine : EnginePool::PoolItem<&_e } /** + * Get the last display variant for an engine. + * @return Engine's last display variant or engine itself if no last display variant is set. + */ + const Engine *GetDisplayVariant() const + { + if (this->display_last_variant == this->index || this->display_last_variant == INVALID_ENGINE) return this; + return Engine::Get(this->display_last_variant); + } + + bool IsVariantHidden(CompanyID c) const; + + /** * Check if the engine is a ground vehicle. * @return True iff the engine is a train or a road vehicle. */