diff --git a/bin/data/CMakeLists.txt b/bin/data/CMakeLists.txt index f1b7d731f1..8c41e98c9a 100644 --- a/bin/data/CMakeLists.txt +++ b/bin/data/CMakeLists.txt @@ -1,5 +1,5 @@ set(DATA_SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/cmclient-5.grf + ${CMAKE_CURRENT_SOURCE_DIR}/cmclient-6.grf ) foreach(DATA_SOURCE_FILE IN LISTS DATA_SOURCE_FILES) diff --git a/bin/data/cmclient-6.grf b/bin/data/cmclient-6.grf index 9577b4c9cf..a328db91cf 100644 Binary files a/bin/data/cmclient-6.grf and b/bin/data/cmclient-6.grf differ diff --git a/grf/cmclient/gencmclientgrf.py b/grf/cmclient/gencmclientgrf.py index f5d9f180c7..33bc9b269c 100644 --- a/grf/cmclient/gencmclientgrf.py +++ b/grf/cmclient/gencmclientgrf.py @@ -221,9 +221,12 @@ BASE_TINTS = { for f in BASE_TINTS.values(): remap(f) -for f1 in BASE_TINTS.values(): - for f2 in BASE_TINTS.values(): - remap(lambda x: f2(f1(x))) +for k1, f1 in BASE_TINTS.items(): + for k2, f2 in BASE_TINTS.items(): + if k1 == 'cyan' and k2 == 'white': + remap(gen_tint((0.5, 1.0, 1.0), 0.4)) + else: + remap(lambda x: f2(f1(x))) # Only white can be mixed over any combination white = BASE_TINTS['white'] diff --git a/src/citymania/cm_blueprint.cpp b/src/citymania/cm_blueprint.cpp index 45167b92a5..1c88521238 100644 --- a/src/citymania/cm_blueprint.cpp +++ b/src/citymania/cm_blueprint.cpp @@ -589,7 +589,7 @@ void SetBlueprintHighlight(const TileInfo *ti, TileHighlight &th) { return; if (_active_blueprint.second->HasSourceTile(ti->tile)) { - th.ground_pal = th.structure_pal = CM_PALETTE_TINT_BLUE; + th.tint_all(CM_PALETTE_TINT_BLUE); } } diff --git a/src/citymania/cm_highlight.cpp b/src/citymania/cm_highlight.cpp index aa623dbe64..07bccd4b72 100644 --- a/src/citymania/cm_highlight.cpp +++ b/src/citymania/cm_highlight.cpp @@ -408,7 +408,7 @@ bool ObjectTileHighlight::operator==(const ObjectTileHighlight &oh) const { return true; } -bool ObjectTileHighlight::SetTileHighlight(TileHighlight &th, const TileInfo *) const { +bool ObjectTileHighlight::SetTileHighlight(TileHighlight &th, const TileInfo *ti) const { switch (this->type) { case ObjectTileHighlight::Type::RAIL_DEPOT: // case ObjectTileHighlight::Type::RAIL_TRACK: Depot track shouldn't remove foundation @@ -422,14 +422,13 @@ bool ObjectTileHighlight::SetTileHighlight(TileHighlight &th, const TileInfo *) case ObjectTileHighlight::Type::INDUSTRY_TILE: case ObjectTileHighlight::Type::DOCK_SLOPE: case ObjectTileHighlight::Type::DOCK_FLAT: - th.structure_pal = CM_PALETTE_HIDE_SPRITE; - th.highlight_ground_pal = th.highlight_structure_pal = this->palette; + th.set_structure(this->palette); return true; case ObjectTileHighlight::Type::TINT: - th.ground_pal = th.structure_pal = this->palette; + th.tint_all(this->palette); return true; case ObjectTileHighlight::Type::STRUCT_TINT: - th.structure_pal = this->palette; + th.tint_structure_prio(this->palette); return true; default: @@ -1050,7 +1049,7 @@ SpriteID MixTints(SpriteID bottom, SpriteID top) { } // White mix can't be mixed again if (bottom >= CM_PALETTE_TINT_MIXES_WHITE) { - Debug(misc, 0, "White highlights can't be stacked"); + Debug(misc, 0, "White highlights can't be stacked on white mixes"); return bottom; } if (top == CM_PALETTE_TINT_WHITE) { @@ -1101,6 +1100,19 @@ SpriteID GetSelectionColourByTint(SpriteID colour) { } } +void TileHighlight::set_old_selection(SpriteID sprite) { + this->selection = sprite; + this->tint_ground(GetTintBySelectionColour(sprite)); +} + +void TileHighlight::tint_ground(SpriteID colour) { + this->ground_pal = MixTints(this->ground_pal, colour); +} + +void TileHighlight::tint_structure(SpriteID colour) { + this->structure_pal = MixTints(this->structure_pal, colour); +} + void DrawTrainDepotSprite(SpriteID palette, const TileInfo *ti, RailType railtype, DiagDirection ddir) { const DrawTileSprites *dts = &_depot_gfx_table[ddir]; @@ -1249,13 +1261,13 @@ struct PreviewStationScopeResolver : public StationScopeResolver { struct StationPreivewResolverObject : public StationResolverObject { PreviewStationScopeResolver preview_station_scope; TileIndex tile; - TileIndexDiffC offset; + TileIndexDiffC offset; // TODO remove? StationPreivewResolverObject(const StationSpec *statspec, TileIndex tile, TileArea area, StationGfx gfx, Axis axis, bool purchase, CallbackID callback = CBID_NO_CALLBACK, uint32_t callback_param1 = 0, uint32_t callback_param2 = 0) : StationResolverObject(statspec, nullptr, tile, callback, callback_param1, callback_param2), preview_station_scope{*this, statspec, tile, area, gfx, axis, purchase}, - tile{tile}, offset{offset} { + tile{tile}, offset{} { CargoID ctype = (purchase ? SpriteGroupCargo::SG_PURCHASE : SpriteGroupCargo::SG_DEFAULT_NA); this->root_spritegroup = statspec->grf_prop.spritegroup[ctype]; @@ -1937,15 +1949,13 @@ TileHighlight ObjectHighlight::GetTileHighlight(const TileInfo *ti) { return th; } -HighlightMap ObjectHighlight::GetHighlightMap(SpriteID palette) { +void ObjectHighlight::AddToHighlightMap(HighlightMap &hlmap, SpriteID palette) { // TODO remove the need to convert (maybe replace HighlightMap with multimap?) - HighlightMap res; for (auto &[tile, oth] : this->tiles) { auto othp = oth; othp.palette = palette; - res.Add(tile, othp); + hlmap.Add(tile, othp); } - return res; } std::optional ObjectHighlight::GetArea() { @@ -2166,14 +2176,11 @@ static void SetStationSelectionHighlight(const TileInfo *ti, TileHighlight &th) th.add_border(b.first, CM_SPR_PALETTE_ZONING_RED); } if (IsInsideSelectedRectangle(TileX(ti->tile) * TILE_SIZE, TileY(ti->tile) * TILE_SIZE)) { - // th.ground_pal = GetTintBySelectionColour(color); if (_thd.make_square_red) { - th.ground_pal = th.structure_pal = CM_PALETTE_TINT_RED; - th.highlight_structure_pal = th.highlight_ground_pal = CM_PALETTE_TINT_RED; + th.tint_ground(CM_PALETTE_TINT_RED); + th.set_structure(CM_PALETTE_TINT_RED); } else { - th.ground_pal = PAL_NONE; - th.structure_pal = CM_PALETTE_HIDE_SPRITE; - th.highlight_structure_pal = th.highlight_ground_pal = PAL_NONE; + th.hide_structure(); } return; } @@ -2189,11 +2196,10 @@ static void SetStationSelectionHighlight(const TileInfo *ti, TileHighlight &th) }; auto b = CalcTileBorders(ti->tile, coverage_getter); if (b.second) { - // const SpriteID pal[] = {PAL_NONE, SPR_PALETTE_ZONING_WHITE, SPR_PALETTE_ZONING_LIGHT_BLUE}; const SpriteID pal[] = {PAL_NONE, CM_SPR_PALETTE_ZONING_WHITE, PAL_NONE}; th.add_border(b.first, pal[b.second]); const SpriteID pal2[] = {PAL_NONE, CM_PALETTE_TINT_WHITE, CM_PALETTE_TINT_BLUE}; - th.ground_pal = th.structure_pal = pal2[b.second]; + th.tint_all(pal2[b.second]); } } @@ -2268,15 +2274,6 @@ void CalcCBTownLimitBorder(TileHighlight &th, TileIndex tile, SpriteID border_pa TileHighlight GetTileHighlight(const TileInfo *ti, TileType tile_type) { TileHighlight th; - auto hl = _at.tiles.GetForTile(ti->tile); - if (hl.has_value()) { - for (auto &oth : hl->get()) { - oth.SetTileHighlight(th, ti); - Debug(misc, 0, "GetTileHighlight {} {}:{}", ti->tile, oth.type, th.structure_pal == CM_PALETTE_HIDE_SPRITE); - } - return th; - } - th = _thd.cm.GetTileHighlight(ti);; if (ti->tile == INVALID_TILE || tile_type == MP_VOID) return th; if (_zoning.outer == CHECKTOWNZONES) { @@ -2291,7 +2288,7 @@ TileHighlight GetTileHighlight(const TileInfo *ti, TileType tile_type) { case 5: color = CM_SPR_PALETTE_ZONING_RED; break; // Tz4 - center }; th.add_border(p.first, color); - th.ground_pal = th.structure_pal = GetTintBySelectionColour(color); + th.tint_all(GetTintBySelectionColour(color)); if (CB_Enabled()) CalcCBTownLimitBorder(th, ti->tile, CM_SPR_PALETTE_ZONING_RED, PAL_NONE); } else if (_zoning.outer == CHECKSTACATCH) { @@ -2302,39 +2299,38 @@ TileHighlight GetTileHighlight(const TileInfo *ti, TileType tile_type) { switch (_game->get_town_growth_tile(ti->tile)) { // case TGTS_CB_HOUSE_REMOVED_NOGROW: case TownGrowthTileState::RH_REMOVED: - th.selection = CM_SPR_PALETTE_ZONING_LIGHT_BLUE; + th.set_old_selection(CM_SPR_PALETTE_ZONING_LIGHT_BLUE); break; case TownGrowthTileState::RH_REBUILT: - th.selection = CM_SPR_PALETTE_ZONING_WHITE; - th.structure_pal = CM_PALETTE_TINT_WHITE; + th.set_old_selection(CM_SPR_PALETTE_ZONING_WHITE); + th.tint_structure(CM_PALETTE_TINT_WHITE); break; case TownGrowthTileState::NEW_HOUSE: - th.selection = CM_SPR_PALETTE_ZONING_GREEN; - th.structure_pal = CM_PALETTE_TINT_GREEN; + th.set_old_selection(CM_SPR_PALETTE_ZONING_GREEN); + th.tint_structure(CM_PALETTE_TINT_GREEN); break; case TownGrowthTileState::CS: - th.selection = CM_SPR_PALETTE_ZONING_ORANGE; + th.set_old_selection(CM_SPR_PALETTE_ZONING_ORANGE); break; case TownGrowthTileState::HS: - th.selection = CM_SPR_PALETTE_ZONING_YELLOW; + th.set_old_selection(CM_SPR_PALETTE_ZONING_YELLOW); break; case TownGrowthTileState::HR: - th.selection = CM_SPR_PALETTE_ZONING_RED; + th.set_old_selection(CM_SPR_PALETTE_ZONING_RED); break; - default: th.selection = PAL_NONE; + default: th.set_old_selection(PAL_NONE); } - if (th.selection) th.ground_pal = GetTintBySelectionColour(th.selection); } else if (_zoning.outer == CHECKBULUNSER) { if (IsTileType (ti->tile, MP_HOUSE)) { StationFinder stations(TileArea(ti->tile, 1, 1)); // TODO check cargos if (stations.GetStations()->empty()) - th.ground_pal = th.structure_pal = CM_PALETTE_TINT_RED_DEEP; + th.tint_all(CM_PALETTE_TINT_RED_DEEP); } } else if (_zoning.outer == CHECKINDUNSER) { auto pal = GetIndustryZoningPalette(ti->tile); - if (pal) th.ground_pal = th.structure_pal = CM_PALETTE_TINT_RED_DEEP; + if (pal) th.tint_all(CM_PALETTE_TINT_RED_DEEP); } else if (_zoning.outer == CHECKTOWNADZONES) { auto getter = [](TileIndex t) { return _mz[t.base()].advertisement_zone; }; auto b = CalcTileBorders(ti->tile, getter); @@ -2346,7 +2342,7 @@ TileHighlight GetTileHighlight(const TileInfo *ti, TileType tile_type) { if (station) check_tile = station->xy; } auto z = getter(check_tile); - if (z) th.ground_pal = th.structure_pal = GetTintBySelectionColour(pal[z]); + if (z) th.tint_all(GetTintBySelectionColour(pal[z])); } else if (_zoning.outer == CHECKCBACCEPTANCE) { CalcCBAcceptanceBorders(th, ti->tile, CM_SPR_PALETTE_ZONING_WHITE, CM_PALETTE_TINT_WHITE); } else if (_zoning.outer == CHECKCBTOWNLIMIT) { @@ -2364,7 +2360,7 @@ TileHighlight GetTileHighlight(const TileInfo *ti, TileType tile_type) { const SpriteID pal[] = {PAL_NONE, CM_SPR_PALETTE_ZONING_GREEN, CM_SPR_PALETTE_ZONING_RED}; th.add_border(b.first, pal[b.second]); auto z = getter(ti->tile); - if (z) th.ground_pal = th.structure_pal = GetTintBySelectionColour(pal[z]); + if (z) th.tint_all(GetTintBySelectionColour(pal[z])); } if (_settings_client.gui.cm_show_industry_forbidden_tiles && @@ -2372,19 +2368,25 @@ TileHighlight GetTileHighlight(const TileInfo *ti, TileType tile_type) { auto b = CalcTileBorders(ti->tile, [](TileIndex t) { return !CanBuildIndustryOnTileCached(_industry_forbidden_tiles, t); }); th.add_border(b.first, CM_SPR_PALETTE_ZONING_RED); if (!CanBuildIndustryOnTileCached(_industry_forbidden_tiles, ti->tile)) - th.ground_pal = th.structure_pal = CM_PALETTE_TINT_RED; + th.tint_all(CM_PALETTE_TINT_RED); } SetStationSelectionHighlight(ti, th); SetBlueprintHighlight(ti, th); + auto hl = _at.tiles.GetForTile(ti->tile); + if (hl.has_value()) { + for (auto &oth : hl->get()) { + oth.SetTileHighlight(th, ti); + } + } return th; } void DrawTileZoning(const TileInfo *ti, const TileHighlight &th, TileType tile_type) { if (ti->tile == INVALID_TILE || tile_type == MP_VOID) return; for (uint i = 0; i < th.border_count; i++) - DrawBorderSprites(ti, th.border[i], th.border_color[i]); + DrawBorderSprites(ti, th.border[i], th.border_colour[i]); if (th.sprite) { DrawSelectionSprite(th.sprite, PAL_NONE, ti, 0, FOUNDATION_PART_NORMAL); } diff --git a/src/citymania/cm_highlight_type.hpp b/src/citymania/cm_highlight_type.hpp index 1040e11c5c..15c5460981 100644 --- a/src/citymania/cm_highlight_type.hpp +++ b/src/citymania/cm_highlight_type.hpp @@ -48,24 +48,54 @@ class TileHighlight { public: SpriteID ground_pal = PAL_NONE; SpriteID structure_pal = PAL_NONE; - SpriteID highlight_ground_pal = PAL_NONE; - SpriteID highlight_structure_pal = PAL_NONE; + SpriteID structure_pal_prio = PAL_NONE; + bool structure_hidden = false; + SpriteID highlight_pal = PAL_NONE; SpriteID sprite = 0; SpriteID selection = PAL_NONE; ZoningBorder border[4] = {}; - SpriteID border_color[4] = {}; + SpriteID border_colour[4] = {}; uint border_count = 0; - void add_border(ZoningBorder border, SpriteID color) { - if (border == ZoningBorder::NONE || !color) return; + std::pair get_structure_pal() { + auto pal = this->structure_pal_prio; + if (pal == PAL_NONE) pal = this->structure_pal; + return {!this->structure_hidden, pal}; + } + + SpriteID pick_ground_pal(SpriteID colour) { + // TODO mix with colour? + if (this->structure_pal_prio != PAL_NONE) return this->structure_pal_prio; + if (this->ground_pal != PAL_NONE) return this->ground_pal; + return colour; + } + + void add_border(ZoningBorder border, SpriteID colour) { + if (border == ZoningBorder::NONE || !colour) return; this->border[this->border_count] = border; - this->border_color[this->border_count] = color; + this->border_colour[this->border_count] = colour; this->border_count++; } - void tint_all(SpriteID color) { - if (!color) return; - this->ground_pal = this->structure_pal = color; + void set_old_selection(SpriteID sprite); + void tint_ground(SpriteID colour); + void tint_structure(SpriteID colour); + void tint_structure_prio(SpriteID colour) { + this->structure_pal_prio = colour; + } + + void tint_all(SpriteID colour) { + this->tint_ground(colour); + this->tint_structure(colour); + } + + void hide_structure() { + this->structure_hidden = true; + } + + void set_structure(SpriteID colour) { + this->hide_structure(); + this->highlight_pal = colour; } void clear_borders() { @@ -392,7 +422,7 @@ public: static ObjectHighlight make_dock(TileIndex tile, DiagDirection orientation); TileHighlight GetTileHighlight(const TileInfo *ti); - HighlightMap GetHighlightMap(SpriteID palette); + void AddToHighlightMap(HighlightMap &hlmap, SpriteID palette); std::optional GetArea(); void Draw(const TileInfo *ti); void DrawSelectionOverlay(DrawPixelInfo *dpi); diff --git a/src/citymania/cm_station_gui.cpp b/src/citymania/cm_station_gui.cpp index a0af544c17..27b730385d 100644 --- a/src/citymania/cm_station_gui.cpp +++ b/src/citymania/cm_station_gui.cpp @@ -690,7 +690,7 @@ static void UpdateStationAction(std::optional area, up cmdptr static HighlightMap PrepareHighilightMap(Station *st_join, std::optional ohl, SpriteID pal, bool show_join_area, bool show_coverage, uint rad) { bool add_current = true; // FIXME - auto hlmap = ohl.has_value() ? ohl->GetHighlightMap(pal) : HighlightMap{}; + HighlightMap hlmap{}; TileArea join_area; std::set coverage_area; @@ -702,8 +702,7 @@ static HighlightMap PrepareHighilightMap(Station *st_join, std::optionalcatchment_tiles) { - auto pal = join_area.Contains(t) ? MixTints(CM_PALETTE_TINT_CYAN, CM_PALETTE_TINT_WHITE) : CM_PALETTE_TINT_WHITE; - hlmap.Add(t, ObjectTileHighlight::make_tint(pal)); + hlmap.Add(t, ObjectTileHighlight::make_tint(CM_PALETTE_TINT_WHITE)); coverage_area.insert(t); } } @@ -720,8 +719,8 @@ static HighlightMap PrepareHighilightMap(Station *st_join, std::optionalAddToHighlightMap(hlmap, pal); + return hlmap; } diff --git a/src/table/sprites.h b/src/table/sprites.h index f2792950c1..d8e16413f6 100644 --- a/src/table/sprites.h +++ b/src/table/sprites.h @@ -366,11 +366,10 @@ static const SpriteID CM_PALETTE_TINT_MIXES_WHITE = CM_PALETTE_TINT_BASE + static const SpriteID CM_PALETTE_TINT_COUNT = CM_PALETTE_TINT_BASE_COUNT + 2 * CM_PALETTE_TINT_BASE_COUNT * CM_PALETTE_TINT_BASE_COUNT; /* Special flag to hide sprite */ -static const SpriteID CM_PALETTE_HIDE_SPRITE = CM_PALETTE_TINT_BASE + CM_PALETTE_TINT_COUNT; -static const SpriteID CM_PALETTE_TINT_END = CM_PALETTE_HIDE_SPRITE; +static const SpriteID CM_PALETTE_TINT_END = CM_PALETTE_TINT_BASE + CM_PALETTE_TINT_COUNT; /* From where can we start putting NewGRFs? */ -static const SpriteID SPR_NEWGRFS_BASE = CM_PALETTE_TINT_BASE + CM_PALETTE_TINT_COUNT + 1; +static const SpriteID SPR_NEWGRFS_BASE = CM_PALETTE_TINT_END; /* Manager face sprites */ static const SpriteID SPR_GRADIENT = 874; // background gradient behind manager face diff --git a/src/viewport.cpp b/src/viewport.cpp index 60bbcdabd3..921eb3ffd9 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -622,7 +622,7 @@ void DrawGroundSpriteAt(SpriteID image, PaletteID pal, int32_t x, int32_t y, int { /* Switch to first foundation part, if no foundation was drawn */ if (_vd.foundation_part == FOUNDATION_PART_NONE) _vd.foundation_part = FOUNDATION_PART_NORMAL; - if (_vd.cm_highlight.ground_pal) pal = _vd.cm_highlight.ground_pal; + pal = _vd.cm_highlight.pick_ground_pal(pal); if (_vd.foundation[_vd.foundation_part] != -1) { Point pt = RemapCoords(x, y, z); AddChildSpriteToFoundation(image, pal, sub, _vd.foundation_part, pt.x + extra_offs_x * ZOOM_LVL_BASE, pt.y + extra_offs_y * ZOOM_LVL_BASE); @@ -731,14 +731,14 @@ void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w, assert((image & SPRITE_MASK) < MAX_SPRITES); - if (!ignore_highlight_pal) { - if (_vd.cm_highlight.structure_pal) pal = _vd.cm_highlight.structure_pal; - } - /* make the sprites transparent with the right palette */ if (transparent) { SetBit(image, PALETTE_MODIFIER_TRANSPARENT); pal = PALETTE_TO_TRANSPARENT; + } else if (!ignore_highlight_pal) { + auto [draw, new_pal] = _vd.cm_highlight.get_structure_pal(); + if (!draw) return; + if (new_pal != PAL_NONE) pal = new_pal; } if (_vd.combine_sprites == SPRITE_COMBINE_ACTIVE) { @@ -747,7 +747,6 @@ void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w, } _vd.last_child = nullptr; - if (!ignore_highlight_pal && pal == CM_PALETTE_HIDE_SPRITE) return; Point pt = RemapCoords(x, y, z); int tmp_left, tmp_top, tmp_x = pt.x, tmp_y = pt.y; @@ -1350,8 +1349,9 @@ static void ViewportAddLandscape() _tile_type_procs[tile_type]->draw_tile_proc(&_cur_ti); if (_cur_ti.tile != INVALID_TILE) { // CM TODO why is this check here? - _vd.cm_highlight.ground_pal = _vd.cm_highlight.highlight_ground_pal; - _vd.cm_highlight.structure_pal = _vd.cm_highlight.highlight_structure_pal; + _vd.cm_highlight.structure_pal = _vd.cm_highlight.highlight_pal; + _vd.cm_highlight.structure_pal_prio = PAL_NONE; + _vd.cm_highlight.structure_hidden = false; citymania::DrawTileZoning(&_cur_ti); // old zoning patch citymania::DrawTileZoning(&_cur_ti, _vd.cm_highlight, tile_type); DrawTileSelection(&_cur_ti);