Add mixed tint palette remaps

This commit is contained in:
dP
2025-11-28 17:36:05 +05:00
parent 3080b32815
commit f356de80b1
9 changed files with 103 additions and 73 deletions

Binary file not shown.

BIN
bin/data/cmclient-6.grf Normal file

Binary file not shown.

View File

@@ -190,26 +190,9 @@ def gen_oklab_tint(tint, ratio):
# (0.7433, 0, 0.15)
# (0.7418, -0.09, 0.15)
remap = lambda f: g.add(grf.PaletteRemap.oklab_from_function(f, remap_range=grf.ALL_COLOURS))
remap(gen_tint((1, 0, 0), 0.6)) # deep red tint
remap(gen_tint((1, 0.5, 0), 0.65)) # deep orange tint
remap(gen_tint((0, 1, 0), 0.65)) # deep green tint
remap(gen_tint((0, 1, 1), 0.65)) # deep cyan tint
remap(gen_tint((1, 0, 0), 0.4)) # red tint
remap(gen_tint((1, 0.5, 0), 0.4)) # orange tint
remap(gen_tint((1.0, 1.0, 0), 0.4)) # yellow tint
# remap(gen_oklab_tint((0.5498, 0.17, 0.1), 0.5)) # red tint
# remap(gen_oklab_tint((0.7433, 0.09, 0.15), 0.5)) # orange tint
# remap(gen_oklab_tint((0.7433, 0, 0.15), 0.5)) # yellow tint
remap(gen_tint((1.0, 1.0, 0.5), 0.4)) # yellow white tint
remap(gen_white_tint_contrast()) # white tint
# remap(gen_oklab_tint((0.7418, -0.09, 0.15), 0.5)) # white tint
remap(gen_tint((0, 1.0, 0), 0.4)) # green tint
remap(gen_tint((0, 1.0, 1.0), 0.4)) # cyan tint
remap(gen_tint((0.5, 1.0, 1.0), 0.4)) # cyan white tint
remap(gen_tint((0, 0, 1.0), 0.4)) # blue tint
# Tree shades
B = 22.2
remap(gen_brightness(21.7 - B)) # shade N
remap(gen_brightness(24.2 - B)) # shade NE 27.2
@@ -220,7 +203,35 @@ remap(gen_brightness(18.4 - B)) # shade SW
remap(gen_brightness(17.1 - B)) # shade W
remap(gen_brightness(17.5 - B)) # shade NW
grf.main(g, '../../bin/data/cmclient-5.grf')
BASE_TINTS = {
'red_deep': gen_tint((1, 0, 0), 0.6),
'orange_deep': gen_tint((1, 0.5, 0), 0.65),
#'green_deep': gen_tint((0, 1, 0), 0.65),
#'cyan_deep': gen_tint((0, 1, 1), 0.65),
'red': gen_tint((1, 0, 0), 0.4),
'orange': gen_tint((1, 0.5, 0), 0.4),
'yellow': gen_tint((1.0, 1.0, 0), 0.4),
'white': gen_white_tint_contrast(),
'green': gen_tint((0, 1.0, 0), 0.4),
'cyan': gen_tint((0, 1.0, 1.0), 0.4),
'blue': gen_tint((0, 0, 1.0), 0.4),
}
# remap(gen_tint((0.5, 1.0, 1.0), 0.4)) # cyan white tint
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)))
# Only white can be mixed over any combination
white = BASE_TINTS['white']
for f1 in BASE_TINTS.values():
for f2 in BASE_TINTS.values():
remap(lambda x: white(f2(f1(x))))
grf.main(g, '../../bin/data/cmclient-6.grf')
# func = gen_brightness(17.1 - B)
# grf.make_palette_image([grf.oklab_to_srgb(func(x)) for x in grf.OKLAB_PALETTE]).show()

View File

@@ -1035,12 +1035,44 @@ void HighlightMap::AddTilesBorder(const std::set<TileIndex> &tiles, SpriteID pal
}
}
SpriteID MixTints(SpriteID bottom, SpriteID top) {
if (top == PAL_NONE) return bottom;
if (bottom == PAL_NONE) return top;
assert (bottom >= CM_PALETTE_TINT_BASE && bottom < CM_PALETTE_TINT_END);
assert (top >= CM_PALETTE_TINT_BASE && top < CM_PALETTE_TINT_MIXES);
if (bottom < CM_PALETTE_TINT_MIXES) {
// Single tint -> use mixed
return (
CM_PALETTE_TINT_MIXES +
(bottom - CM_PALETTE_TINT_BASE) * CM_PALETTE_TINT_BASE_COUNT +
(top - CM_PALETTE_TINT_BASE)
);
}
// White mix can't be mixed again
if (bottom >= CM_PALETTE_TINT_MIXES_WHITE) {
Debug(misc, 0, "White highlights can't be stacked");
return bottom;
}
if (top == CM_PALETTE_TINT_WHITE) {
// Use same mix but in the white range
return bottom - CM_PALETTE_TINT_MIXES + CM_PALETTE_TINT_MIXES_WHITE;
}
// Mix two last tints
auto last_mixed = (bottom - CM_PALETTE_TINT_MIXES) % CM_PALETTE_TINT_BASE_COUNT;
return (
CM_PALETTE_TINT_MIXES +
last_mixed * CM_PALETTE_TINT_BASE_COUNT +
(top - CM_PALETTE_TINT_BASE)
);
}
SpriteID GetTintBySelectionColour(SpriteID colour, bool deep=false) {
switch(colour) {
case CM_SPR_PALETTE_ZONING_RED: return (deep ? CM_PALETTE_TINT_RED_DEEP : CM_PALETTE_TINT_RED);
case CM_SPR_PALETTE_ZONING_ORANGE: return (deep ? CM_PALETTE_TINT_ORANGE_DEEP : CM_PALETTE_TINT_ORANGE);
case CM_SPR_PALETTE_ZONING_GREEN: return (deep ? CM_PALETTE_TINT_GREEN_DEEP : CM_PALETTE_TINT_GREEN);
case CM_SPR_PALETTE_ZONING_LIGHT_BLUE: return (deep ? CM_PALETTE_TINT_CYAN_DEEP : CM_PALETTE_TINT_CYAN);
case CM_SPR_PALETTE_ZONING_GREEN: return CM_PALETTE_TINT_GREEN;
case CM_SPR_PALETTE_ZONING_LIGHT_BLUE: return CM_PALETTE_TINT_CYAN;
case CM_SPR_PALETTE_ZONING_YELLOW: return CM_PALETTE_TINT_YELLOW;
// case SPR_PALETTE_ZONING__: return PALETTE_TINT_YELLOW_WHITE;
case CM_SPR_PALETTE_ZONING_WHITE: return CM_PALETTE_TINT_WHITE;
@@ -1056,10 +1088,8 @@ SpriteID GetSelectionColourByTint(SpriteID colour) {
case CM_PALETTE_TINT_ORANGE_DEEP:
case CM_PALETTE_TINT_ORANGE:
return CM_SPR_PALETTE_ZONING_ORANGE;
case CM_PALETTE_TINT_GREEN_DEEP:
case CM_PALETTE_TINT_GREEN:
return CM_SPR_PALETTE_ZONING_GREEN;
case CM_PALETTE_TINT_CYAN_DEEP:
case CM_PALETTE_TINT_CYAN:
return CM_SPR_PALETTE_ZONING_LIGHT_BLUE;
case CM_PALETTE_TINT_YELLOW:
@@ -2240,8 +2270,9 @@ TileHighlight GetTileHighlight(const TileInfo *ti, TileType tile_type) {
auto hl = _at.tiles.GetForTile(ti->tile);
if (hl.has_value()) {
for (auto &oth : hl.value().get()) {
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;
}

View File

@@ -29,6 +29,7 @@ namespace citymania {
// MEDIUM = 2,
// SMALL = 3,
// };
SpriteID MixTints(SpriteID bottom, SpriteID top);
TileHighlight GetTileHighlight(const TileInfo *ti, TileType tile_type);
void DrawTileZoning(const TileInfo *ti, const TileHighlight &th, TileType tile_type);

View File

@@ -702,7 +702,7 @@ static HighlightMap PrepareHighilightMap(Station *st_join, std::optional<ObjectH
if (show_coverage && st_join != nullptr) {
// Add joining station coverage
for (auto t : st_join->catchment_tiles) {
auto pal = join_area.Contains(t) ? CM_PALETTE_TINT_CYAN_WHITE : CM_PALETTE_TINT_WHITE;
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));
coverage_area.insert(t);
}
@@ -720,7 +720,7 @@ static HighlightMap PrepareHighilightMap(Station *st_join, std::optional<ObjectH
if (show_coverage && add_current && rad_area.has_value()) {
// Add current station coverage
for (auto t : *rad_area) {
auto pal = join_area.Contains(t) ? CM_PALETTE_TINT_CYAN_WHITE : CM_PALETTE_TINT_WHITE;
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));
coverage_area.insert(t);
}

View File

@@ -971,35 +971,14 @@ Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
*/
static BlitterMode GetBlitterMode(PaletteID pal)
{
if (pal >= CM_PALETTE_TINT_BASE && pal < CM_PALETTE_TINT_END)
return CM_BM_TINT_REMAP;
switch (pal) {
case PAL_NONE: return BM_NORMAL;
case PALETTE_CRASH: return BM_CRASH_REMAP;
case PALETTE_ALL_BLACK: return BM_BLACK_REMAP;
case CM_PALETTE_TINT_RED_DEEP:
case CM_PALETTE_TINT_ORANGE_DEEP:
case CM_PALETTE_TINT_GREEN_DEEP:
case CM_PALETTE_TINT_CYAN_DEEP:
case CM_PALETTE_TINT_RED:
case CM_PALETTE_TINT_ORANGE:
case CM_PALETTE_TINT_YELLOW:
case CM_PALETTE_TINT_YELLOW_WHITE:
case CM_PALETTE_TINT_WHITE:
case CM_PALETTE_TINT_GREEN:
case CM_PALETTE_TINT_CYAN:
case CM_PALETTE_TINT_CYAN_WHITE:
case CM_PALETTE_TINT_BLUE:
case CM_PALETTE_SHADE_N:
case CM_PALETTE_SHADE_NE:
case CM_PALETTE_SHADE_E:
case CM_PALETTE_SHADE_SE:
case CM_PALETTE_SHADE_S:
case CM_PALETTE_SHADE_SW:
case CM_PALETTE_SHADE_W:
case CM_PALETTE_SHADE_NW:
case CM_PALETTE_TINT_COUNT:
return CM_BM_TINT_REMAP;
default: return BM_COLOUR_REMAP;
}
}

View File

@@ -174,7 +174,7 @@ static void LoadSpriteTables()
PAL_DOS != used_set->palette
);
}
LoadGrfFile("cmclient-5.grf", CM_SPR_CITYMANIA_BASE, PAL_DOS != used_set->palette);
LoadGrfFile("cmclient-6.grf", CM_SPR_CITYMANIA_BASE, PAL_DOS != used_set->palette);
/* Initialize the unicode to sprite mapping table */
InitializeUnicodeGlyphMap();

View File

@@ -337,30 +337,38 @@ static const SpriteID CM_SPR_INNER_HIGHLIGHT_COUNT = 30;
static const SpriteID CM_SPR_BORDER_HIGHLIGHT_BASE = CM_SPR_INNER_HIGHLIGHT_BASE + CM_SPR_INNER_HIGHLIGHT_COUNT;
static const SpriteID CM_SPR_BORDER_HIGHLIGHT_COUNT = 19 * 19;
static const SpriteID CM_PALETTE_TINT_BASE = CM_SPR_BORDER_HIGHLIGHT_BASE + CM_SPR_BORDER_HIGHLIGHT_COUNT;
/* Tree shades */
static const SpriteID CM_PALETTE_SHADE_BASE = CM_SPR_BORDER_HIGHLIGHT_BASE + CM_SPR_BORDER_HIGHLIGHT_COUNT;
static const SpriteID CM_PALETTE_SHADE_N = CM_PALETTE_SHADE_BASE;
static const SpriteID CM_PALETTE_SHADE_NE = CM_PALETTE_SHADE_BASE + 1;
static const SpriteID CM_PALETTE_SHADE_E = CM_PALETTE_SHADE_BASE + 2;
static const SpriteID CM_PALETTE_SHADE_SE = CM_PALETTE_SHADE_BASE + 3;
static const SpriteID CM_PALETTE_SHADE_S = CM_PALETTE_SHADE_BASE + 4;
static const SpriteID CM_PALETTE_SHADE_SW = CM_PALETTE_SHADE_BASE + 5;
static const SpriteID CM_PALETTE_SHADE_W = CM_PALETTE_SHADE_BASE + 6;
static const SpriteID CM_PALETTE_SHADE_NW = CM_PALETTE_SHADE_BASE + 7;
/* Tint remaps */
static const SpriteID CM_PALETTE_TINT_BASE = CM_PALETTE_SHADE_BASE + 8;
static const SpriteID CM_PALETTE_TINT_RED_DEEP = CM_PALETTE_TINT_BASE;
static const SpriteID CM_PALETTE_TINT_ORANGE_DEEP = CM_PALETTE_TINT_BASE + 1;
static const SpriteID CM_PALETTE_TINT_GREEN_DEEP = CM_PALETTE_TINT_BASE + 2;
static const SpriteID CM_PALETTE_TINT_CYAN_DEEP = CM_PALETTE_TINT_BASE + 3;
static const SpriteID CM_PALETTE_TINT_RED = CM_PALETTE_TINT_BASE + 4;
static const SpriteID CM_PALETTE_TINT_ORANGE = CM_PALETTE_TINT_BASE + 5;
static const SpriteID CM_PALETTE_TINT_YELLOW = CM_PALETTE_TINT_BASE + 6;
static const SpriteID CM_PALETTE_TINT_YELLOW_WHITE = CM_PALETTE_TINT_BASE + 7;
static const SpriteID CM_PALETTE_TINT_WHITE = CM_PALETTE_TINT_BASE + 8;
static const SpriteID CM_PALETTE_TINT_GREEN = CM_PALETTE_TINT_BASE + 9;
static const SpriteID CM_PALETTE_TINT_CYAN = CM_PALETTE_TINT_BASE + 10;
static const SpriteID CM_PALETTE_TINT_CYAN_WHITE = CM_PALETTE_TINT_BASE + 11;
static const SpriteID CM_PALETTE_TINT_BLUE = CM_PALETTE_TINT_BASE + 12;
static const SpriteID CM_PALETTE_SHADE_N = CM_PALETTE_TINT_BASE + 13;
static const SpriteID CM_PALETTE_SHADE_NE = CM_PALETTE_TINT_BASE + 14;
static const SpriteID CM_PALETTE_SHADE_E = CM_PALETTE_TINT_BASE + 15;
static const SpriteID CM_PALETTE_SHADE_SE = CM_PALETTE_TINT_BASE + 16;
static const SpriteID CM_PALETTE_SHADE_S = CM_PALETTE_TINT_BASE + 17;
static const SpriteID CM_PALETTE_SHADE_SW = CM_PALETTE_TINT_BASE + 18;
static const SpriteID CM_PALETTE_SHADE_W = CM_PALETTE_TINT_BASE + 19;
static const SpriteID CM_PALETTE_SHADE_NW = CM_PALETTE_TINT_BASE + 20;
static const SpriteID CM_PALETTE_TINT_COUNT = 13 + 8;
static const SpriteID CM_PALETTE_TINT_RED = CM_PALETTE_TINT_BASE + 2;
static const SpriteID CM_PALETTE_TINT_ORANGE = CM_PALETTE_TINT_BASE + 3;
static const SpriteID CM_PALETTE_TINT_YELLOW = CM_PALETTE_TINT_BASE + 4;
static const SpriteID CM_PALETTE_TINT_WHITE = CM_PALETTE_TINT_BASE + 5;
static const SpriteID CM_PALETTE_TINT_GREEN = CM_PALETTE_TINT_BASE + 6;
static const SpriteID CM_PALETTE_TINT_CYAN = CM_PALETTE_TINT_BASE + 7;
static const SpriteID CM_PALETTE_TINT_BLUE = CM_PALETTE_TINT_BASE + 8;
static const SpriteID CM_PALETTE_TINT_BASE_COUNT = 9;
static const SpriteID CM_PALETTE_TINT_MIXES = CM_PALETTE_TINT_BASE + CM_PALETTE_TINT_BASE_COUNT;
static const SpriteID CM_PALETTE_TINT_MIXES_WHITE = CM_PALETTE_TINT_BASE + CM_PALETTE_TINT_BASE_COUNT + CM_PALETTE_TINT_BASE_COUNT * CM_PALETTE_TINT_BASE_COUNT;
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;
/* From where can we start putting NewGRFs? */
static const SpriteID SPR_NEWGRFS_BASE = CM_PALETTE_TINT_BASE + CM_PALETTE_TINT_COUNT + 1;