Map: name the four hues the console cannot guess
Water, its watercourses, parks and highways were literal hex, so the PicoCalc fold picked their slots by nearest neighbour and lost the point of each one: the dark blue landed on grey, the dark green on black, the motorway amber on bright red. Same failure the node-type marks already dodge by naming a style, so these do too — a map.* block in both themes, resolved through mark_rgb like every other mark. On the console water is now blue, every watercourse the bright blue one rung up, parks green and highways brown. Truecolour is unchanged: the named styles carry the same hexes they replaced. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
87f6dd7dd8
commit
6f5c61b133
2 files changed
+48
-16
No files matched your search
+25
-16
@@ -9,6 +9,9 @@ the one-shot CLI render call the same code.
|
||||
Colours target a dark terminal (the app theme): warm roads, grey minor streets, blue water
|
||||
and rivers, faint green parks. Because a cell shows one colour, draw priorities keep the
|
||||
important feature visible where things overlap (rivers over water, major roads over minor).
|
||||
The features whose hue *is* the information — water, its watercourses, parks, highways —
|
||||
name a ``map.*`` theme style instead of a hex so the 16-slot console chooses its own shade
|
||||
(see :data:`~meshterm.ui.theme.MESH_THEME_16`); everything else is grey either way.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -22,6 +25,7 @@ from ..core.geo import Viewport
|
||||
from ..core.mvt import GEOM_LINE, GEOM_POLYGON, Layer
|
||||
from .mapcanvas import MapCanvas
|
||||
from .marks import NODE_MARK, REPEATER_MARK, RGB, SELF_MARK, UNKNOWN_MARK, parse_hex
|
||||
from .theme import mark_rgb
|
||||
|
||||
# -- node markers -------------------------------------------------------------
|
||||
|
||||
@@ -64,10 +68,15 @@ _UNKNOWN = UNKNOWN_MARK
|
||||
|
||||
# -- basemap styling ----------------------------------------------------------
|
||||
|
||||
# Every colour here is whatever :func:`~meshterm.ui.theme.mark_rgb` takes: a literal
|
||||
# ``#rrggbb``, or a theme style name where the hue carries meaning and the platform must
|
||||
# pick its own shade (the ``map.*`` entries — see the theme, which explains why water,
|
||||
# parks and highways cannot survive a naive downsample to 16 slots).
|
||||
|
||||
# Road class -> (colour, priority). Higher priority wins a shared cell.
|
||||
_ROAD_STYLE: dict[str, tuple[str, int]] = {
|
||||
"motorway": ("#f2a13d", 27),
|
||||
"trunk": ("#f2a13d", 26),
|
||||
"motorway": ("map.highway", 27),
|
||||
"trunk": ("map.highway", 26),
|
||||
"primary": ("#e8b24a", 25),
|
||||
"secondary": ("#d7c257", 24),
|
||||
"tertiary": ("#a7adb8", 23),
|
||||
@@ -87,14 +96,14 @@ _RAIL = ("#8a8f98", 22)
|
||||
|
||||
# Waterway class -> (colour, priority).
|
||||
_WATERWAY_STYLE: dict[str, tuple[str, int]] = {
|
||||
"river": ("#49b0ec", 30),
|
||||
"canal": ("#49b0ec", 30),
|
||||
"stream": ("#3f8fbf", 29),
|
||||
"ditch": ("#3a7ba6", 28),
|
||||
"drain": ("#3a7ba6", 28),
|
||||
"river": ("map.river", 30),
|
||||
"canal": ("map.river", 30),
|
||||
"stream": ("map.stream", 29),
|
||||
"ditch": ("map.ditch", 28),
|
||||
"drain": ("map.ditch", 28),
|
||||
}
|
||||
_WATER_FILL = ("#153b56", 6)
|
||||
_GREEN_FILL = ("#173a29", 4)
|
||||
_WATER_FILL = ("map.water", 6)
|
||||
_GREEN_FILL = ("map.park", 4)
|
||||
_GREEN_CLASSES = {"wood", "forest", "grass", "park", "meadow", "scrub", "wetland", "cemetery"}
|
||||
|
||||
# Label styling per place class: (colour, bold, rank, min_display_zoom). Lower rank places
|
||||
@@ -204,7 +213,7 @@ def _draw_tile(frame: _Frame, layers: list[Layer], z: int, x: int, y: int) -> No
|
||||
else:
|
||||
continue
|
||||
vp.fill_polygon(
|
||||
[project(r, layer.extent) for r in feat.rings], parse_hex(color), prio
|
||||
[project(r, layer.extent) for r in feat.rings], mark_rgb(color), prio
|
||||
)
|
||||
|
||||
# Waterways (rivers/streams) as lines.
|
||||
@@ -217,7 +226,7 @@ def _draw_tile(frame: _Frame, layers: list[Layer], z: int, x: int, y: int) -> No
|
||||
color, prio = style
|
||||
for ring in feat.rings:
|
||||
if len(ring) >= 2:
|
||||
vp.draw_line(project(ring, waterway.extent), parse_hex(color), prio)
|
||||
vp.draw_line(project(ring, waterway.extent), mark_rgb(color), prio)
|
||||
if feat.name:
|
||||
_add_line_label(frame, feat.rings, waterway.extent, z, x, y, feat.name, _WATER_LABEL)
|
||||
|
||||
@@ -232,7 +241,7 @@ def _draw_tile(frame: _Frame, layers: list[Layer], z: int, x: int, y: int) -> No
|
||||
color, prio = _RAIL
|
||||
else:
|
||||
color, prio = _ROAD_STYLE.get(cls, _ROAD_DEFAULT)
|
||||
rgb = parse_hex(color)
|
||||
rgb = mark_rgb(color)
|
||||
for ring in feat.rings:
|
||||
if len(ring) >= 2:
|
||||
vp.draw_line(project(ring, transportation.extent), rgb, prio)
|
||||
@@ -250,7 +259,7 @@ def _draw_tile(frame: _Frame, layers: list[Layer], z: int, x: int, y: int) -> No
|
||||
continue
|
||||
for ring in feat.rings:
|
||||
if len(ring) >= 2:
|
||||
vp.draw_line(project(ring, boundary.extent), parse_hex("#6d5f88"), 14)
|
||||
vp.draw_line(project(ring, boundary.extent), mark_rgb("#6d5f88"), 14)
|
||||
|
||||
# Street-name labels (only kick in at high zoom via the label's min_zoom gate).
|
||||
tname = by_name.get("transportation_name")
|
||||
@@ -276,7 +285,7 @@ def _draw_tile(frame: _Frame, layers: list[Layer], z: int, x: int, y: int) -> No
|
||||
lx, ly = feat.rings[0][0]
|
||||
dx, dy = frame.viewport.feature_to_dot(x, y, z, place.extent, lx, ly)
|
||||
frame.labels.append(
|
||||
_Label(rank, dx, dy, feat.name, parse_hex(color), bold, min_zoom)
|
||||
_Label(rank, dx, dy, feat.name, mark_rgb(color), bold, min_zoom)
|
||||
)
|
||||
|
||||
# Water-body names.
|
||||
@@ -287,7 +296,7 @@ def _draw_tile(frame: _Frame, layers: list[Layer], z: int, x: int, y: int) -> No
|
||||
if feat.name and feat.rings and feat.rings[0]:
|
||||
lx, ly = feat.rings[0][0]
|
||||
dx, dy = frame.viewport.feature_to_dot(x, y, z, water_name.extent, lx, ly)
|
||||
frame.labels.append(_Label(rank, dx, dy, feat.name, parse_hex(color), bold, 8))
|
||||
frame.labels.append(_Label(rank, dx, dy, feat.name, mark_rgb(color), bold, 8))
|
||||
|
||||
|
||||
def _add_line_label(
|
||||
@@ -307,7 +316,7 @@ def _add_line_label(
|
||||
lx, ly = longest[len(longest) // 2]
|
||||
dx, dy = frame.viewport.feature_to_dot(x, y, z, extent, lx, ly)
|
||||
color, bold, rank = style
|
||||
frame.labels.append(_Label(rank, dx, dy, text, parse_hex(color), bold, min_zoom))
|
||||
frame.labels.append(_Label(rank, dx, dy, text, mark_rgb(color), bold, min_zoom))
|
||||
|
||||
|
||||
def _marker_style(marker: MapMarker) -> tuple[str, str]:
|
||||
|
||||
@@ -103,6 +103,18 @@ MESH_THEME = Theme(
|
||||
"type.repeater": "#a78bfa",
|
||||
"type.room": "#ffffff",
|
||||
"type.sensor": "#fb923c",
|
||||
# The basemap features whose *hue* is the information — water is blue, parks are
|
||||
# green, a highway is the warm one — and which a naive downsample therefore ruins
|
||||
# (the dark blue lands on grey, the dark green on black, the amber on bright red).
|
||||
# Named for the same reason as ``type.*``: the console picks the slot itself. The
|
||||
# rest of the basemap is grey by design and quantizes honestly, so minor roads,
|
||||
# rail, boundaries and labels stay literal hex in ui.map_render.
|
||||
"map.water": "#153b56",
|
||||
"map.river": "#49b0ec",
|
||||
"map.stream": "#3f8fbf",
|
||||
"map.ditch": "#3a7ba6",
|
||||
"map.park": "#173a29",
|
||||
"map.highway": "#f2a13d",
|
||||
# The heard-age heat scale's steps, named for how old the node they colour is:
|
||||
# a node heard eight minutes ago is ``heat.minutes``, one heard eight days ago is
|
||||
# ``heat.days``. Seven steps from white-hot to cold ash (JP's spec) — a cooling
|
||||
@@ -259,6 +271,17 @@ MESH_THEME_16 = Theme(
|
||||
"type.repeater": "not bold color(5)",
|
||||
"type.room": "color(15)",
|
||||
"type.sensor": "not bold color(3)",
|
||||
# The basemap on the console: a water body is the dim blue, every watercourse
|
||||
# crossing it the bright blue one rung up (the palette has exactly one of each —
|
||||
# a river's depth of shade is a truecolour luxury, and all three waterway shades
|
||||
# land on the same rung here), parks the dim green, highways brown. Backgrounds
|
||||
# never come into it: the canvas paints these as braille dots in the foreground.
|
||||
"map.water": "not bold color(4)",
|
||||
"map.river": "color(12)",
|
||||
"map.stream": "color(12)",
|
||||
"map.ditch": "color(12)",
|
||||
"map.park": "not bold color(2)",
|
||||
"map.highway": "not bold color(3)",
|
||||
# JP's ladder, slot by slot: white-hot, yellow, the ember's light red, brown as it
|
||||
# chars, dark red as it dies, then ash — light grey, and cold grey for what may as
|
||||
# well never have been heard. Six of the sixteen slots do the whole scale; the
|
||||
|
||||
Reference in new issue
Block a user