@tileflow/core 0.1.0-alpha.35 → 0.1.0-alpha.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,6 +15,61 @@ same token keys, so changing a theme can never change map structure or silently
15
15
  role. `defineTheme(base, definition)` is an authoring convenience that returns a fully materialized
16
16
  document; it does not leave an inheritance edge in the resolved config.
17
17
 
18
+ ## Start with one appearance
19
+
20
+ A map can have one appearance for its entire lifetime. Neither `systemThemes` nor `timeOfDay` is
21
+ required. This complete theme supplies the twelve base color roles the semantic compiler needs;
22
+ copy it and change its colors to start an independent design without inheriting an official map:
23
+
24
+ <!-- docs:check -->
25
+
26
+ ```ts
27
+ import {defineTheme} from '@tileflow/core';
28
+
29
+ export const paper = defineTheme({
30
+ id: 'paper',
31
+ version: 1,
32
+ colorScheme: 'light',
33
+ tokens: {
34
+ color: {
35
+ 'surface.background': '#F6F7F3',
36
+ 'surface.land': '#F1F3ED',
37
+ 'surface.water': '#A9D3F5',
38
+ 'surface.park': '#CDE8B5',
39
+ 'surface.building': '#E6E3DA',
40
+ 'roads.default': '#FFFFFF',
41
+ 'roads.major': '#F4C95D',
42
+ 'roads.casing': '#D9DEE2',
43
+ 'boundaries.default': '#C9D1D9',
44
+ 'labels.primary': '#3C4043',
45
+ 'labels.muted': '#727B84',
46
+ 'labels.halo': '#FFFFFF',
47
+ },
48
+ },
49
+ });
50
+ ```
51
+
52
+ An existing map definition can select this appearance with `themes: {paper}` and
53
+ `defaultTheme: 'paper'`. Supply that map's data and font assets separately; the default typography
54
+ uses `Noto Sans Regular`. A theme without these base roles is a valid appearance document but cannot
55
+ compile a semantic map. Colors above are an editable starting point, including for monochrome,
56
+ historical, dark-only, or imagined worlds; `colorScheme` describes the appearance for consumers and
57
+ does not generate a palette or choose a time of day.
58
+
59
+ The compiler derives more specific roles when they are absent. For example, primary and motorway
60
+ roads initially use `roads.major`; declaring `roads.motorway` replaces only that derived color.
61
+ Land-use fills, road casings, and label colors have their own semantic roles, so an explicit role
62
+ always wins over its fallback. Use `color.mix()` and `token.color()` in a theme when the relationship
63
+ itself should be authored and inspectable. Derivations resolve during compilation, without a clock
64
+ or a per-frame palette calculation.
65
+
66
+ Add named appearances when the map needs them. A day/night pair does not need dawn or dusk, and a
67
+ theme named `paper` or `fantasy` does not need a temporal family. Declare `timeOfDay` only when the
68
+ application should offer those artistic moments; see
69
+ [time-of-day selection](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/docs/theme-transitions-and-blends.md#time-of-day).
70
+
71
+ ## Compose and replace appearance values
72
+
18
73
  Some optional tokens are for the application rather than the map's own layers. Route inks
19
74
  (`route.line`, `route.casing`, `route.core`, `route.glow`, `route.alternative`,
20
75
  `route.glow.opacity` and `route.core.opacity`) set how an application draws its routes; a theme
@@ -83,6 +138,17 @@ deterministic OKLCH `color.mix()` keep derived palette logic inspectable. Unknow
83
138
  cross-category refs, token-schema drift, and unresolved visual nodes fail before Style JSON is
84
139
  emitted.
85
140
 
141
+ Theme lighting also supports explicit removal during `defineTheme` composition. Use
142
+ `lighting: reset()` to remove the entire inherited lighting configuration, or
143
+ `lighting: {sun: reset(), ambient: reset()}` to remove those presets while retaining other light
144
+ properties. The same operation can remove a direct property such as `position` or `color`.
145
+ Omitting a property, or supplying an empty object, continues to inherit it. Reset operations are
146
+ materialized immediately and never enter the resolved theme or Style JSON. Removing a lighting
147
+ preset restores the renderer's fallback; it does not disable 3D shadows or occlusion. Those remain
148
+ explicit building settings. See
149
+ [sun and light](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/docs/sun-and-light.md#replace-inherited-lighting)
150
+ for a complete example.
151
+
86
152
  There is no physical-layer override for the Tileflow basemap or separate official-map authoring
87
153
  surface. Basemap behavior belongs to a typed control or owner-local render stack. Every
88
154
  official and application map therefore follows the same schema, inheritance rules, diagnostics,
package/docs/trees-3d.md CHANGED
@@ -3,7 +3,7 @@
3
3
  `createTileflowTrees3D` stands the trees of a Tileflow map's vector tiles round the camera as 3D
4
4
  trees, lit by the theme controller's sun. Each tree takes the form and the size its data gives:
5
5
  palms, conifers, columns and three broadleaf forms, at their mapped height and crown where the data
6
- has them. Trees cast shadows on the ground and, with `createTileflowBuildings3D`, on the buildings,
6
+ has them. The data's hedges stand beside them as clipped green walls. Trees cast shadows on the ground and, with `createTileflowBuildings3D`, on the buildings,
7
7
  and take the buildings' shadows; nearer buildings hide them.
8
8
 
9
9
  The map describes how its trees look; the renderer only stands them. A map that declares
@@ -107,7 +107,7 @@ sunk or the layer leaves the map.
107
107
 
108
108
  `stats.declared` tells whether the map's style describes 3D trees. When it is false the layer draws
109
109
  nothing: declare `vegetation({mode: '3d'})` in the map. `stats` also counts the tiles, the trees
110
- placed and the trees drawn in the last frame.
110
+ placed, the pieces of hedge placed and the trees drawn in the last frame.
111
111
 
112
112
  ## What the trees come from
113
113
 
@@ -120,6 +120,10 @@ The renderer reads the source's z15 tiles round the camera:
120
120
  - World's `canopy` layer, where the data has it: decorative points in urban parks and gardens, each
121
121
  standing one to three trees by its canopy cover, inside the room it leaves before a path, a
122
122
  building or the park's edge. They stand for measured canopy, not for mapped trees.
123
+ - World's `traffic_control` layer: its hedges (`subclass` `hedge`), the lines OpenStreetMap maps and
124
+ the hedges it maps as areas. A hedge stands as pieces 1.2 metres apart along each line and round
125
+ each area, 0.8 metres thick, at its `height` or 1.3 metres, a metre higher where `hedge` says
126
+ `hedge_bank`. The style still draws the hedge flat underneath, and fences and walls stay flat.
123
127
 
124
128
  | Form | From the data |
125
129
  | ---------- | ---------------------------------------------------------------------------- |
@@ -139,8 +143,12 @@ tile's buffer belong to the neighbouring tile, so no tree stands twice.
139
143
 
140
144
  Colours come from the theme: `vegetation.tree.bark`, `vegetation.tree.broadleaf.a` to `.d`,
141
145
  `vegetation.tree.conifer.a` to `.c` and `vegetation.tree.palm.a` to `.c`, sunlit, from darkest to
142
- lightest. A crown facing a sunlit sky takes its colour; shade takes the sky's light, as on 3D
143
- buildings. The vegetation module's `threeDimensional` options refine them for one map:
146
+ lightest. Hedges take `hedgeColors`, the two darkest broadleaf colours unless the map gives its own;
147
+ Streets gives its flat hedge's colours, so a hedge keeps its colour as it rises. `hedges: false`
148
+ leaves hedges flat. A crown facing a sunlit sky takes its colour; shade takes the sky's light, as on 3D
149
+ buildings. At night a neutral lift keeps crown tops visible; grey materials stay grey under neutral
150
+ lighting, while coloured scene lighting can tint them. The vegetation module's `threeDimensional`
151
+ options refine them for one map:
144
152
 
145
153
  <!-- docs:check -->
146
154
 
@@ -239,16 +247,20 @@ the same name; omitting `models` inherits them, and `[]` declares none.
239
247
  The light comes from `controller.getSun()`: the theme's sun, mixed during a blend, or the sun an
240
248
  application places by direction or by date and place (see
241
249
  [sun and light](https://github.com/tileflow/tileflow-sdk/blob/main/packages/core/docs/sun-and-light.md)).
250
+ Without a controller, trees read the compiled style's sun and light direction, falling back to
251
+ SDK daylight, just as 3D buildings do. This cached light refreshes when the style changes.
242
252
  Leaves take light round their edges and glow a little against a low sun; the underside and the
243
253
  inside of a crown stay darker.
244
254
 
245
255
  Trees and 3D buildings on one map share one shadow map: trees cast shadows on the ground and on the
246
256
  buildings, and stand in the buildings' shade. The flat map darkens under both. Without 3D buildings
247
- the trees darken the map themselves.
257
+ the trees darken the map themselves. The depth pass uses the same visible tree ranks, near/far
258
+ models and distance fade as the colour pass, so hidden trees do not leave full shadows behind.
259
+ Shadow direction stops lowering at 15° above the horizon; the actual scene light keeps its angle.
248
260
 
249
261
  ## Options
250
262
 
251
- `minzoom` (15 by default) and `maxTiles` (25 by default, at most 64) bound where and how far trees
263
+ `minzoom` (15 by default, fading to full coverage at 15.25 like buildings) and `maxTiles` (25 by default, at most 64) bound where and how far trees
252
264
  stand; trees thin out and fade with distance from the map's centre, and near trees take more detail
253
265
  than far ones. `canopySource` names a vector source with canopy points when they are not in the
254
266
  map's World source. `beforeId` places the layer before another one; `transformRequest` applies the
@@ -258,9 +270,10 @@ tile's download.
258
270
  ## Cost
259
271
 
260
272
  A near tree has 60 to 120 triangles and a far one about 20, and each form is one instanced draw per
261
- tile. The shadow map is drawn again only when the sun, the trees on screen or their size change, not
262
- when the camera moves. Over the Champ de Mars in Paris, where OpenStreetMap maps every tree, about
263
- 13,000 trees stand in a pitched view at zoom 16.6.
273
+ tile. The shared shadow map concentrates resolution on the view when its public camera methods
274
+ provide a safe planar fit. It is drawn again when that focused area, the light, visible tree
275
+ selection, fading or geometry changes. Unchanged views reuse it. Over the Champ de Mars in Paris,
276
+ where OpenStreetMap maps every tree, about 13,000 trees stand in a pitched view at zoom 16.6.
264
277
 
265
278
  ## Limits
266
279
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/core",
3
- "version": "0.1.0-alpha.35",
3
+ "version": "0.1.0-alpha.36",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Typed Tileflow config and MapLibre style compiler.",
6
6
  "type": "module",
@@ -90,7 +90,7 @@
90
90
  "whatwg-url": "17.2.0"
91
91
  },
92
92
  "scripts": {
93
- "build": "tsup --config tsup.build.config.ts && tsup --config tsup.native-profile.config.ts && tsup src/browser.ts --format esm --dts --no-splitting --platform browser && tsup --config tsup.native.config.ts && cp ../../docs/modules-api-reference.json dist/config-reference.json",
93
+ "build": "tsup --config tsup.build.config.ts && tsup --config tsup.native-profile.config.ts && tsup --config tsup.browser.config.ts && tsup --config tsup.native.config.ts && cp ../../docs/modules-api-reference.json dist/config-reference.json",
94
94
  "reference:check": "tsx scripts/generate-config-reference.ts --check",
95
95
  "reference:generate": "tsx scripts/generate-config-reference.ts --write",
96
96
  "verify": "pnpm run build && tsx --test test/*.test.ts",