tosijs-3d 0.7.2 → 0.7.4

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.
Files changed (153) hide show
  1. package/CHANGELOG.md +900 -0
  2. package/dist/b3d-aircraft.d.ts +14 -0
  3. package/dist/b3d-aircraft.d.ts.map +1 -1
  4. package/dist/b3d-aircraft.js +45 -0
  5. package/dist/b3d-aircraft.js.map +1 -1
  6. package/dist/b3d-ambient.d.ts +12 -0
  7. package/dist/b3d-ambient.d.ts.map +1 -1
  8. package/dist/b3d-ambient.js +83 -1
  9. package/dist/b3d-ambient.js.map +1 -1
  10. package/dist/b3d-biped.d.ts +290 -0
  11. package/dist/b3d-biped.d.ts.map +1 -1
  12. package/dist/b3d-biped.js +1366 -22
  13. package/dist/b3d-biped.js.map +1 -1
  14. package/dist/b3d-collisions.d.ts.map +1 -1
  15. package/dist/b3d-collisions.js +45 -7
  16. package/dist/b3d-collisions.js.map +1 -1
  17. package/dist/b3d-controllable.d.ts +50 -0
  18. package/dist/b3d-controllable.d.ts.map +1 -1
  19. package/dist/b3d-controllable.js +61 -0
  20. package/dist/b3d-controllable.js.map +1 -1
  21. package/dist/b3d-death.d.ts +26 -0
  22. package/dist/b3d-death.d.ts.map +1 -1
  23. package/dist/b3d-death.js +224 -2
  24. package/dist/b3d-death.js.map +1 -1
  25. package/dist/b3d-interactive.d.ts +80 -0
  26. package/dist/b3d-interactive.d.ts.map +1 -0
  27. package/dist/b3d-interactive.js +284 -0
  28. package/dist/b3d-interactive.js.map +1 -0
  29. package/dist/b3d-library.d.ts +39 -0
  30. package/dist/b3d-library.d.ts.map +1 -1
  31. package/dist/b3d-library.js +67 -0
  32. package/dist/b3d-library.js.map +1 -1
  33. package/dist/b3d-svg-plane.d.ts +35 -0
  34. package/dist/b3d-svg-plane.d.ts.map +1 -1
  35. package/dist/b3d-svg-plane.js +96 -8
  36. package/dist/b3d-svg-plane.js.map +1 -1
  37. package/dist/b3d-water.d.ts.map +1 -1
  38. package/dist/b3d-water.js +32 -6
  39. package/dist/b3d-water.js.map +1 -1
  40. package/dist/buoyancy.d.ts +90 -0
  41. package/dist/buoyancy.d.ts.map +1 -0
  42. package/dist/buoyancy.js +150 -0
  43. package/dist/buoyancy.js.map +1 -0
  44. package/dist/curve-field.d.ts +39 -0
  45. package/dist/curve-field.d.ts.map +1 -0
  46. package/dist/curve-field.js +491 -0
  47. package/dist/curve-field.js.map +1 -0
  48. package/dist/curve.d.ts +241 -0
  49. package/dist/curve.d.ts.map +1 -0
  50. package/dist/curve.js +559 -0
  51. package/dist/curve.js.map +1 -0
  52. package/dist/dialog-placement.d.ts +69 -7
  53. package/dist/dialog-placement.d.ts.map +1 -1
  54. package/dist/dialog-placement.js +90 -9
  55. package/dist/dialog-placement.js.map +1 -1
  56. package/dist/embed-font.d.ts +48 -0
  57. package/dist/embed-font.d.ts.map +1 -0
  58. package/dist/embed-font.js +135 -0
  59. package/dist/embed-font.js.map +1 -0
  60. package/dist/footprint-field.d.ts +30 -0
  61. package/dist/footprint-field.d.ts.map +1 -0
  62. package/dist/footprint-field.js +256 -0
  63. package/dist/footprint-field.js.map +1 -0
  64. package/dist/frame-panel.d.ts.map +1 -1
  65. package/dist/frame-panel.js +15 -12
  66. package/dist/frame-panel.js.map +1 -1
  67. package/dist/glb-manifest.d.ts +75 -0
  68. package/dist/glb-manifest.d.ts.map +1 -0
  69. package/dist/glb-manifest.js +198 -0
  70. package/dist/glb-manifest.js.map +1 -0
  71. package/dist/icon-data.d.ts.map +1 -1
  72. package/dist/icon-data.js +20 -1
  73. package/dist/icon-data.js.map +1 -1
  74. package/dist/index.d.ts +33 -4
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +38 -3
  77. package/dist/index.js.map +1 -1
  78. package/dist/interaction.d.ts +66 -0
  79. package/dist/interaction.d.ts.map +1 -0
  80. package/dist/interaction.js +117 -0
  81. package/dist/interaction.js.map +1 -0
  82. package/dist/interactive-behavior.d.ts +105 -0
  83. package/dist/interactive-behavior.d.ts.map +1 -0
  84. package/dist/interactive-behavior.js +253 -0
  85. package/dist/interactive-behavior.js.map +1 -0
  86. package/dist/key-layout.d.ts +70 -0
  87. package/dist/key-layout.d.ts.map +1 -1
  88. package/dist/key-layout.js +122 -0
  89. package/dist/key-layout.js.map +1 -1
  90. package/dist/keyboard-gamepad.d.ts.map +1 -1
  91. package/dist/keyboard-gamepad.js +19 -6
  92. package/dist/keyboard-gamepad.js.map +1 -1
  93. package/dist/keyboard.d.ts +100 -1
  94. package/dist/keyboard.d.ts.map +1 -1
  95. package/dist/keyboard.js +280 -35
  96. package/dist/keyboard.js.map +1 -1
  97. package/dist/mantle.d.ts +56 -0
  98. package/dist/mantle.d.ts.map +1 -0
  99. package/dist/mantle.js +115 -0
  100. package/dist/mantle.js.map +1 -0
  101. package/dist/popup-surface.d.ts +5 -1
  102. package/dist/popup-surface.d.ts.map +1 -1
  103. package/dist/popup-surface.js +181 -14
  104. package/dist/popup-surface.js.map +1 -1
  105. package/dist/surface.d.ts.map +1 -1
  106. package/dist/surface.js +111 -15
  107. package/dist/surface.js.map +1 -1
  108. package/dist/svg-icons.d.ts.map +1 -1
  109. package/dist/svg-icons.js +13 -1
  110. package/dist/svg-icons.js.map +1 -1
  111. package/dist/svg-texture.d.ts.map +1 -1
  112. package/dist/svg-texture.js +40 -1
  113. package/dist/svg-texture.js.map +1 -1
  114. package/dist/swim-aim.d.ts +78 -0
  115. package/dist/swim-aim.d.ts.map +1 -0
  116. package/dist/swim-aim.js +140 -0
  117. package/dist/swim-aim.js.map +1 -0
  118. package/dist/theme-editor.d.ts +41 -0
  119. package/dist/theme-editor.d.ts.map +1 -0
  120. package/dist/theme-editor.js +303 -0
  121. package/dist/theme-editor.js.map +1 -0
  122. package/dist/tosi-b3d.d.ts +24 -4
  123. package/dist/tosi-b3d.d.ts.map +1 -1
  124. package/dist/tosi-b3d.js +238 -37
  125. package/dist/tosi-b3d.js.map +1 -1
  126. package/dist/vector-field.d.ts +58 -0
  127. package/dist/vector-field.d.ts.map +1 -0
  128. package/dist/vector-field.js +321 -0
  129. package/dist/vector-field.js.map +1 -0
  130. package/dist/virtual-gamepad.d.ts.map +1 -1
  131. package/dist/virtual-gamepad.js +46 -9
  132. package/dist/virtual-gamepad.js.map +1 -1
  133. package/dist/w3d-theme.d.ts +115 -17
  134. package/dist/w3d-theme.d.ts.map +1 -1
  135. package/dist/w3d-theme.js +311 -0
  136. package/dist/w3d-theme.js.map +1 -1
  137. package/dist/water-normal.d.ts +26 -0
  138. package/dist/water-normal.d.ts.map +1 -0
  139. package/dist/water-normal.js +105 -0
  140. package/dist/water-normal.js.map +1 -0
  141. package/dist/widgets3d-layout.d.ts +58 -0
  142. package/dist/widgets3d-layout.d.ts.map +1 -1
  143. package/dist/widgets3d-layout.js +79 -1
  144. package/dist/widgets3d-layout.js.map +1 -1
  145. package/dist/widgets3d.d.ts +51 -2
  146. package/dist/widgets3d.d.ts.map +1 -1
  147. package/dist/widgets3d.js +418 -112
  148. package/dist/widgets3d.js.map +1 -1
  149. package/dist/wreck-fall.d.ts +86 -0
  150. package/dist/wreck-fall.d.ts.map +1 -0
  151. package/dist/wreck-fall.js +129 -0
  152. package/dist/wreck-fall.js.map +1 -0
  153. package/package.json +9 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buoyancy.js","sourceRoot":"","sources":["../src/buoyancy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkCE;AACF,2BAA2B;AAsB3B;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAa,EACb,MAAc,EACd,QAAgB;IAEhB,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,KAAK,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACjD,MAAM,KAAK,GAAG,CAAC,QAAQ,GAAG,KAAK,CAAC,GAAG,MAAM,CAAA;IACzC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;AAChD,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CACzB,EAAU,EACV,SAAiB,EACjB,EAAU,EACV,SAAyB,EAAE;IAE3B,MAAM,EACJ,OAAO,GAAG,CAAC,IAAI,EACf,QAAQ,GAAG,IAAI,EACf,SAAS,GAAG,CAAC,EACb,OAAO,GAAG,IAAI,EACd,MAAM,GAAG,CAAC,GACX,GAAG,MAAM,CAAA;IACV,IAAI,EAAE,IAAI,CAAC;QAAE,OAAO,EAAE,CAAA;IACtB,MAAM,CAAC,GAAG,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAC7D,8EAA8E;IAC9E,8EAA8E;IAC9E,4CAA4C;IAC5C,MAAM,KAAK,GAAG,OAAO,GAAG,CAAC,OAAO,GAAG,QAAQ,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,CAAA;IAC5D,MAAM,IAAI,GAAG,OAAO,GAAG,CAAC,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;IAChD,MAAM,IAAI,GAAG,EAAE,GAAG,KAAK,GAAG,EAAE,CAAA;IAC5B,6EAA6E;IAC7E,2DAA2D;IAC3D,OAAO,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,GAAG,EAAE,CAAA;AACjD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAQ,GAAG,IAAI;IACnD,OAAO,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAA;AACzC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,UAAU,CACxB,SAAiB,EACjB,cAAuB,EACvB,WAAW,GAAG,KAAK;IAEnB,IAAI,cAAc;QAAE,OAAO,KAAK,CAAA;IAChC;;;;;;;;;;;;;;;MAeE;IACF,OAAO,SAAS,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;AAChD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,YAAY,CAC1B,SAAiB,EACjB,SAAkE,EAAE;IAEpE,MAAM,EAAE,QAAQ,GAAG,IAAI,EAAE,OAAO,GAAG,IAAI,EAAE,KAAK,GAAG,GAAG,EAAE,GAAG,MAAM,CAAA;IAC/D,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAA;IACnC,MAAM,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC,CAAA;IACzD,OAAO,QAAQ,GAAG,CAAC,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAA;AAC5C,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { type ControlPoint, type CurveKind } from './curve';
2
+ import type { Widget3d } from './widgets3d';
3
+ export interface Curve3dOptions {
4
+ /** `profile` (both ends free) or `falloff` (pinned to 0 at x = 1). */
5
+ kind?: CurveKind;
6
+ /** Starting points, or the name of a preset (`'constant'`, `'ease in'`, …). */
7
+ value?: ControlPoint[] | string;
8
+ /** Caption drawn above the plot. */
9
+ label?: string;
10
+ /** Plot height as a fraction of width. Default 0.62. */
11
+ aspect?: number;
12
+ /** Fired after any edit that changes the curve. */
13
+ onChange?: (points: ControlPoint[]) => void;
14
+ }
15
+ export interface CurveField extends Widget3d {
16
+ readonly points: ControlPoint[];
17
+ setPoints: (p: ControlPoint[]) => void;
18
+ /** Sample it — what a consumer actually wants. */
19
+ evaluate: (t: number) => number;
20
+ /** Index of the selected point, or -1. */
21
+ readonly selected: number;
22
+ /** Remove the selected point. Ends and the last two are protected. */
23
+ deleteSelected: () => void;
24
+ /** Apply a preset by name; unknown names are ignored. */
25
+ applyPreset: (name: string) => void;
26
+ /** Settable so a demo can wire it after construction. */
27
+ onChange?: (points: ControlPoint[]) => void;
28
+ }
29
+ /**
30
+ * An editable curve.
31
+ *
32
+ * ```js
33
+ * const falloff = curve3d({ kind: 'falloff', label: 'falloff' })
34
+ * falloff.onChange = () => rebuildTerrain()
35
+ * falloff.evaluate(0.5)
36
+ * ```
37
+ */
38
+ export declare function curve3d(config?: Curve3dOptions): CurveField;
39
+ //# sourceMappingURL=curve-field.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"curve-field.d.ts","sourceRoot":"","sources":["../src/curve-field.ts"],"names":[],"mappings":"AA4NA,OAAO,EASL,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,SAAS,CAAA;AAEhB,OAAO,KAAK,EAAe,QAAQ,EAAE,MAAM,aAAa,CAAA;AAIxD,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,+EAA+E;IAC/E,KAAK,CAAC,EAAE,YAAY,EAAE,GAAG,MAAM,CAAA;IAC/B,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,mDAAmD;IACnD,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,IAAI,CAAA;CAC5C;AAED,MAAM,WAAW,UAAW,SAAQ,QAAQ;IAC1C,QAAQ,CAAC,MAAM,EAAE,YAAY,EAAE,CAAA;IAC/B,SAAS,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,IAAI,CAAA;IACtC,kDAAkD;IAClD,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAA;IAC/B,0CAA0C;IAC1C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,sEAAsE;IACtE,cAAc,EAAE,MAAM,IAAI,CAAA;IAC1B,yDAAyD;IACzD,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,yDAAyD;IACzD,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,IAAI,CAAA;CAC5C;AAeD;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,MAAM,GAAE,cAAmB,GAAG,UAAU,CA2Q/D"}
@@ -0,0 +1,491 @@
1
+ /*#
2
+ # curve-field
3
+
4
+ **`curve3d` — an editor for a continuous `[0,1] → [0,1]`.** A `Widget3d`, so it
5
+ works as a flat DOM overlay, on an in-scene panel, and in a headset without
6
+ changing. The rules live in [[curve|curve.ts]]; this draws them and routes the
7
+ pointer.
8
+
9
+ Its reason for existing is terrain **provinces**: a province is a footprint plus
10
+ one curve per layer, so this is how you author a plateau, a crater rim or a
11
+ treeline without writing code. See `PROVINCE-DESIGN.md` → "every one of those
12
+ responses IS a curve", and the [[b3d-terrain|province editor]] demo below.
13
+
14
+ ## Deleting a point is a BUTTON, not a gesture
15
+
16
+ Adding is a tap on empty space and moving is a drag, which leaves deleting with
17
+ no obvious third gesture. The usual answers all fail somewhere that matters
18
+ here: right-click does not exist on a controller, double-tap is unreliable when
19
+ the pointer is a ray from two metres away, and drag-off-the-edge collides with
20
+ the clamp that keeps the curve in range.
21
+
22
+ So the widget exposes `selected` and `deleteSelected()`, and the host puts a
23
+ button somewhere honest. A discoverable button beats a gesture you have to be
24
+ told about — which is the same argument the popup title bar makes for its grip.
25
+
26
+ ## Demo — a province editor
27
+
28
+ Two curves and a terrain block. The **shape** says what height the province wants
29
+ at each distance from its centre; the **falloff** says how strongly it overrides
30
+ the terrain around it. Drag the points, or pick a preset.
31
+
32
+ ```js
33
+ import { b3d, b3dLight, panel3d, label3d, button3d, toggle3d, curve3d, footprint3d, slider3d, select3d, presetsFor, PerlinNoise, attachBiomePlugin, blendSample } from 'tosijs-3d'
34
+ import { orbitCam } from 'tosijs-3d/demo-utils'
35
+ import { elements } from 'tosijs'
36
+ const { div } = elements
37
+
38
+ const SIZE = 24 // metres across
39
+ const SUBS = 110 // grid resolution
40
+ // `height` scales the whole BLOCK, not the province inside it — see `rebuild`.
41
+ // 4.5 over a 24 m tile: the field now spans the whole block, so the old 9 (tuned
42
+ // when the base was squeezed into a third of the range) came out as alps.
43
+ const state = { height: 4.5, extent: 0.7, noise: 1 }
44
+
45
+ // A province is a footprint plus one curve per layer. SHAPE says what height it
46
+ // wants at each distance from its centre; FALLOFF says how strongly it overrides
47
+ // the terrain around it. Both are [0,1] -> [0,1] over normalised distance: 0 at
48
+ // the centre, 1 at the extent.
49
+ // SHAPE is a levels adjustment: it maps the height SAMPLE to a height, exactly
50
+ // like slope-profile's cliff/beach/mesa. It starts as the IDENTITY, so a fresh
51
+ // province is invisible — drag it off the diagonal and the terrain responds.
52
+ // Try `constant` (flattens whatever is there: a plateau) or drag it the other
53
+ // way up (maps low ground high, which lifts the whole province).
54
+ const shape = curve3d({ kind: 'profile', label: 'shape — remaps the height sample', value: 'no change', aspect: 0.45 })
55
+ const falloff = curve3d({ kind: 'falloff', label: 'falloff — weight by distance', aspect: 0.45 })
56
+ // The FOOTPRINT, edited as the shape it is rather than as extent-against-angle
57
+ // on a graph: a hexagon looks like a hexagon, and a corner is where the corner
58
+ // is. The square is the province's bounds.
59
+ const footprint = footprint3d({ value: 'hexagon', label: 'footprint — drag the corners' })
60
+
61
+ let ground = null
62
+ let biome = null
63
+
64
+ // Base terrain: seeded fBm, NORMALISED to [0,1] like everything else here.
65
+ //
66
+ // Four octaves rather than a couple of sine waves — smooth ground gives the eye
67
+ // no scale reference, so the province's edge has nothing to be crisp against and
68
+ // the whole thing reads as a bulge in a bedsheet. Detail in the base is what
69
+ // makes the blend legible.
70
+ const noise = new PerlinNoise(1337)
71
+ const fbm = (x, z) => {
72
+ let sum = 0, amp = 1, freq = 0.055 * state.noise, norm = 0
73
+ for (let o = 0; o < 4; o++) {
74
+ sum += noise.noise2D(x * freq, z * freq) * amp
75
+ norm += amp
76
+ amp *= 0.5
77
+ freq *= 2.1 // not exactly 2, so octaves do not line up into visible grain
78
+ }
79
+ return sum / norm // roughly [-1, 1]
80
+ }
81
+ // The FULL [0,1], because that is the shape curve's DOMAIN.
82
+ //
83
+ // This was banded to 0.12 … 0.5 for legibility, which quietly broke the remap:
84
+ // the editor offers you the whole domain while the terrain only ever asks about
85
+ // the bottom third, so a threshold drawn at 0.5 answered 0 for every sample and
86
+ // the province went flat. Tonio: "[0,0]-[0.5,0][0.5,1]-[1,1] does NOT work as
87
+ // expected" — the curve was right and could not be reached.
88
+ //
89
+ // A control whose input range does not match its data is worse than a coarse
90
+ // one, because it fails silently and looks like the model being wrong.
91
+ // …and normalised against its OWN measured range, not against fBm's theoretical
92
+ // one. Four octaves of Perlin almost never reach +/-1, so `fbm * 0.5 + 0.5`
93
+ // spans about 0.28 to 0.62 — the same domain mismatch, just smaller and harder
94
+ // to notice. Measuring the field costs one extra pass over a grid we are
95
+ // building anyway.
96
+ const base = (x, z) => fbm(x, z)
97
+ const normalise = (raw, lo, hi) => (hi - lo < 1e-6 ? 0.5 : (raw - lo) / (hi - lo))
98
+
99
+ const rebuild = () => {
100
+ if (ground == null) return
101
+ // Read x/z back out of the buffer and write y: order-independent, so it does
102
+ // not matter how CreateGround laid the grid out.
103
+ const pos = ground.getVerticesData('position')
104
+ const reach = SIZE * 0.5 * state.extent
105
+ // Pass one: the raw field and its extremes, so the shape curve's [0,1] domain
106
+ // maps onto terrain that actually spans [0,1].
107
+ const raw = new Float32Array(pos.length / 3)
108
+ let lo = Infinity
109
+ let hi = -Infinity
110
+ for (let i = 0, k = 0; i < pos.length; i += 3, k++) {
111
+ raw[k] = base(pos[i], pos[i + 2])
112
+ if (raw[k] < lo) lo = raw[k]
113
+ if (raw[k] > hi) hi = raw[k]
114
+ }
115
+ for (let i = 0, k = 0; i < pos.length; i += 3, k++) {
116
+ const x = pos[i], z = pos[i + 2]
117
+ // Direction first: the footprint says how far the province reaches THIS way,
118
+ // and distance is normalised against that. Direction lives in the footprint;
119
+ // response lives in the other two curves.
120
+ const theta = (Math.atan2(z, x) / (Math.PI * 2) + 1) % 1
121
+ const spread = Math.max(0.05, footprint.evaluate(theta))
122
+ const r = Math.min(1, Math.hypot(x, z) / (reach * spread))
123
+ const w = falloff.evaluate(r)
124
+ // THE HEIGHT SAMPLE goes through the shape curve — a levels adjustment, not
125
+ // a function of distance. Tonio: "shape isn't working properly. It's being
126
+ // treated as an output constant NOT as a map from height field to terrain
127
+ // height." It was `shape.evaluate(r)`, which made a profile into a second
128
+ // radial curve and quietly threw away the terrain underneath it.
129
+ //
130
+ // The falloff still works on DISTANCE — that is the split: what the province
131
+ // does to a sample, versus how far its say extends.
132
+ //
133
+ // `blendSample` is convex, so two values in [0,1] mixed by a weight in [0,1]
134
+ // cannot leave [0,1]: the tile's bounds are known before anything is
135
+ // evaluated, and `height` scales the whole block rather than pushing one
136
+ // province through the top of it.
137
+ const sample = normalise(raw[k], lo, hi)
138
+ const h = blendSample(sample, shape.evaluate(sample), w)
139
+ pos[i + 1] = h * state.height
140
+ }
141
+ ground.updateVerticesData('position', pos)
142
+ ground.createNormals(true)
143
+ }
144
+
145
+ shape.onChange = rebuild
146
+ falloff.onChange = rebuild
147
+ footprint.onChange = rebuild
148
+
149
+ const scene = b3d(
150
+ {
151
+ // `flex:1` on the ELEMENT, not just its wrapper: a <tosi-b3d> in a flex row
152
+ // has no flex-grow of its own, so it shrinks to content width — which is 0,
153
+ // and renders a 0x296 canvas that looks exactly like a broken scene.
154
+ style: 'flex:1;min-width:0;border-radius:8px;overflow:hidden',
155
+ sceneCreated(el) {
156
+ orbitCam(el, { radius: 32, beta: 1.02, alpha: -1.15, target: [0, 1.5, 0] })
157
+ ground = el.make.ground({
158
+ width: SIZE,
159
+ height: SIZE,
160
+ subdivisions: SUBS,
161
+ updatable: true,
162
+ color: '#6d7a58',
163
+ })
164
+ rebuild()
165
+ },
166
+ },
167
+ b3dLight({ intensity: 0.95 })
168
+ )
169
+
170
+ // A preset menu per curve. Presets are the fastest way to learn what a curve
171
+ // DOES — you pick "desert terraces", see terraces, then drag from there.
172
+ const menu = (widget, kind, value) =>
173
+ select3d({
174
+ value,
175
+ options: presetsFor(kind).map((p) => p.name),
176
+ onChange: (name) => { widget.applyPreset(name); rebuild() },
177
+ })
178
+
179
+ const panel = panel3d(
180
+ { width: 320 },
181
+ label3d({ text: 'province editor', bold: true }),
182
+ shape,
183
+ menu(shape, 'profile', 'no change'),
184
+ button3d({ label: 'delete selected point', onClick: () => shape.deleteSelected() }),
185
+ falloff,
186
+ menu(falloff, 'falloff', 'linear'),
187
+ button3d({ label: 'delete selected point', onClick: () => falloff.deleteSelected() }),
188
+ footprint,
189
+ menu(footprint, 'radial', 'hexagon'),
190
+ slider3d({ label: 'block height', min: 1, max: 16, value: state.height, onChange: (v) => { state.height = v; rebuild() } }),
191
+ slider3d({ label: 'extent', min: 0.2, max: 1, value: state.extent, onChange: (v) => { state.extent = v; rebuild() } }),
192
+ slider3d({ label: 'noise scale', min: 0.2, max: 4, value: state.noise, onChange: (v) => { state.noise = v; rebuild() } }),
193
+ toggle3d({ label: 'wireframe', value: false, onChange: (v) => { if (ground?.material) ground.material.wireframe = v } }),
194
+ // The real biome shader, on this block's material — the same one b3d-terrain
195
+ // puts on a tile, so the province is judged against how it will actually look
196
+ // rather than against a flat green.
197
+ toggle3d({ label: 'terrain shader', value: false, onChange: (v) => {
198
+ if (ground?.material == null) return
199
+ if (biome == null) biome = attachBiomePlugin(ground.material)
200
+ biome.isEnabled = v
201
+ } })
202
+ )
203
+
204
+ preview.append(
205
+ div(
206
+ { style: 'display:flex;gap:16px;height:100%;padding:12px;background:#0c0e14;box-sizing:border-box' },
207
+ div({ style: 'flex:0 0 320px;overflow:auto' }, panel),
208
+ div({ style: 'flex:1;min-width:0;display:flex' }, scene)
209
+ )
210
+ )
211
+ ```
212
+ ```css
213
+ .preview {
214
+ height: 100%;
215
+ }
216
+ ```
217
+ */
218
+ /*{ "parent": "UI", "order": 260 }*/
219
+ import { svgElements } from 'tosijs';
220
+ import { deletePoint, evaluateCurve, insertPoint, linear, movePoint, normalizeCurve, presetsFor, falloffDefault, } from './curve';
221
+ import { w3dTheme } from './w3d-theme';
222
+ const { g, rect, path, circle, text } = svgElements;
223
+ /** Resolve the `value` option, which may name a preset. */
224
+ function initialPoints(value, kind) {
225
+ if (Array.isArray(value))
226
+ return normalizeCurve(value, kind);
227
+ if (typeof value === 'string') {
228
+ const preset = presetsFor(kind).find((p) => p.name === value);
229
+ if (preset != null)
230
+ return normalizeCurve(preset.build(), kind);
231
+ }
232
+ return normalizeCurve(kind === 'falloff' ? falloffDefault() : linear(), kind);
233
+ }
234
+ /**
235
+ * An editable curve.
236
+ *
237
+ * ```js
238
+ * const falloff = curve3d({ kind: 'falloff', label: 'falloff' })
239
+ * falloff.onChange = () => rebuildTerrain()
240
+ * falloff.evaluate(0.5)
241
+ * ```
242
+ */
243
+ export function curve3d(config = {}) {
244
+ const kind = config.kind ?? 'profile';
245
+ const aspect = config.aspect ?? 0.62;
246
+ let points = initialPoints(config.value, kind);
247
+ let selected = -1;
248
+ let dragging = -1;
249
+ const el = g();
250
+ const bg = rect({ 'data-curve-bg': '', x: 0, y: 0, rx: 4, ry: 4 });
251
+ const grid = path({ 'data-curve-grid': '', fill: 'none' });
252
+ /*
253
+ THE IDENTITY, drawn faintly — the single most useful mark on a profile plot.
254
+
255
+ Without it the plot has no orientation cue at all: which corner is (0,0) is a
256
+ guess, and a curve drawn from top-left to bottom-right looks as reasonable as
257
+ its mirror while meaning the opposite (it maps low ground HIGH). Tonio drew
258
+ exactly that, expected a no-op, and got a raised province — a reading error the
259
+ plot invited by saying nothing.
260
+
261
+ With the diagonal there, "no change" has a picture: on the line. Only for a
262
+ profile — a falloff is not a remap, so its diagonal would mean nothing.
263
+ */
264
+ const identityLine = path({ 'data-curve-identity': '', fill: 'none' });
265
+ const line = path({ 'data-curve-line': '', fill: 'none' });
266
+ const caption = text({
267
+ 'font-family': w3dTheme.fontFamily,
268
+ 'font-size': String(Math.round(w3dTheme.fontSize * 0.85)),
269
+ fill: w3dTheme.muted,
270
+ }, config.label ?? '');
271
+ el.appendChild(bg);
272
+ el.appendChild(grid);
273
+ if (kind === 'profile')
274
+ el.appendChild(identityLine);
275
+ el.appendChild(line);
276
+ el.appendChild(caption);
277
+ const handles = g({ 'data-curve-points': '' });
278
+ el.appendChild(handles);
279
+ // Plot geometry from the last layout, so the pointer maps through exactly what
280
+ // was drawn — the rule row3d and vector-field both follow.
281
+ //
282
+ // FRAME is the drawn box; PLOT is inset within it, so the x = 0 and x = 1
283
+ // points sit INSIDE the interactive area instead of straddling its edge.
284
+ // Tonio: "I'm finding it very hard to move the edge points or even select
285
+ // them." Half of each end handle's grab area fell outside `hitTest`, and a
286
+ // near-miss did not just fail — it INSERTED a point, which is the worst
287
+ // available outcome for a mis-aimed press.
288
+ let frame = { x: 0, y: 0, w: 1, h: 1 };
289
+ let plot = { x: 0, y: 0, w: 1, h: 1 };
290
+ let rowHeight = 0;
291
+ /** Handle radius, and the inset that keeps a whole handle inside the frame. */
292
+ const HANDLE = 5;
293
+ const INSET = HANDLE + 4;
294
+ /** Grab radius in PIXELS — see `nearestPx`. */
295
+ const GRAB = 16;
296
+ // Curve space ↔ widget space. y is flipped: 1 is the TOP of the plot.
297
+ const toPx = (p) => ({
298
+ x: plot.x + p.x * plot.w,
299
+ y: plot.y + (1 - p.y) * plot.h,
300
+ });
301
+ const toCurve = (x, y) => ({
302
+ x: (x - plot.x) / Math.max(1, plot.w),
303
+ y: 1 - (y - plot.y) / Math.max(1, plot.h),
304
+ });
305
+ /**
306
+ * Nearest point within `GRAB` PIXELS, or -1.
307
+ *
308
+ * Deliberately not `curve.pointAt`, which measures in curve units: the plot is
309
+ * wider than it is tall, so one radius in curve space is an ELLIPSE on screen —
310
+ * generous horizontally, mean vertically, and the asymmetry is invisible until
311
+ * you try to grab something. Pixels are what the finger and the ray both work
312
+ * in.
313
+ */
314
+ const nearestPx = (px, py) => {
315
+ let best = -1;
316
+ let bestD = GRAB * GRAB;
317
+ points.forEach((p, i) => {
318
+ const c = toPx(p);
319
+ const d = (c.x - px) * (c.x - px) + (c.y - py) * (c.y - py);
320
+ if (d <= bestD) {
321
+ bestD = d;
322
+ best = i;
323
+ }
324
+ });
325
+ return best;
326
+ };
327
+ const emit = () => {
328
+ api.onChange?.(points.map((p) => ({ ...p })));
329
+ };
330
+ const drawHandles = () => {
331
+ while (handles.firstChild)
332
+ handles.removeChild(handles.firstChild);
333
+ points.forEach((p, i) => {
334
+ const c = toPx(p);
335
+ handles.appendChild(circle({
336
+ cx: c.x,
337
+ cy: c.y,
338
+ r: i === selected ? HANDLE : HANDLE - 1.5,
339
+ fill: i === selected ? w3dTheme.accent : w3dTheme.panelBg,
340
+ stroke: w3dTheme.accent,
341
+ 'stroke-width': String(w3dTheme.strokeWidth),
342
+ }));
343
+ });
344
+ };
345
+ const draw = () => {
346
+ bg.setAttribute('x', String(frame.x));
347
+ bg.setAttribute('y', String(frame.y));
348
+ bg.setAttribute('width', String(frame.w));
349
+ bg.setAttribute('height', String(frame.h));
350
+ bg.setAttribute('fill', w3dTheme.rowBg);
351
+ bg.setAttribute('stroke', w3dTheme.divider);
352
+ bg.setAttribute('stroke-width', String(w3dTheme.strokeWidth));
353
+ // Quarters, so you can read a value off the plot without a scale.
354
+ const lines = [];
355
+ for (let i = 1; i < 4; i++) {
356
+ const gx = plot.x + (plot.w * i) / 4;
357
+ const gy = plot.y + (plot.h * i) / 4;
358
+ lines.push(`M${gx} ${plot.y}V${plot.y + plot.h}`);
359
+ lines.push(`M${plot.x} ${gy}H${plot.x + plot.w}`);
360
+ }
361
+ grid.setAttribute('d', lines.join(''));
362
+ grid.setAttribute('stroke', w3dTheme.divider);
363
+ grid.setAttribute('stroke-width', '1');
364
+ if (kind === 'profile') {
365
+ const a = toPx({ x: 0, y: 0 });
366
+ const b = toPx({ x: 1, y: 1 });
367
+ identityLine.setAttribute('d', `M${a.x} ${a.y}L${b.x} ${b.y}`);
368
+ identityLine.setAttribute('stroke', w3dTheme.muted);
369
+ identityLine.setAttribute('stroke-width', '1');
370
+ identityLine.setAttribute('stroke-dasharray', '4 4');
371
+ identityLine.setAttribute('opacity', '0.5');
372
+ }
373
+ // The curve IS piecewise linear, so the control points are the polyline —
374
+ // no sampling, and what you see is exactly what `evaluate` returns.
375
+ const d = points
376
+ .map((p, i) => {
377
+ const c = toPx(p);
378
+ return `${i === 0 ? 'M' : 'L'}${c.x} ${c.y}`;
379
+ })
380
+ .join('');
381
+ line.setAttribute('d', d);
382
+ line.setAttribute('stroke', w3dTheme.accent);
383
+ line.setAttribute('stroke-width', String(Math.max(1.5, w3dTheme.strokeWidth)));
384
+ drawHandles();
385
+ };
386
+ const api = {
387
+ el,
388
+ onChange: config.onChange,
389
+ layout(width) {
390
+ const pad = Math.max(2, Math.round(w3dTheme.spacing * 0.5));
391
+ const capH = config.label ? Math.round(w3dTheme.fontSize * 1.2) : 0;
392
+ const plotH = Math.round(width * aspect);
393
+ frame = {
394
+ x: pad,
395
+ y: capH,
396
+ w: Math.max(8, width - pad * 2),
397
+ h: Math.max(8, plotH),
398
+ };
399
+ plot = {
400
+ x: frame.x + INSET,
401
+ y: frame.y + INSET,
402
+ w: Math.max(8, frame.w - INSET * 2),
403
+ h: Math.max(8, frame.h - INSET * 2),
404
+ };
405
+ if (config.label) {
406
+ caption.setAttribute('x', String(pad));
407
+ caption.setAttribute('y', String(Math.round(w3dTheme.fontSize * 0.9)));
408
+ }
409
+ rowHeight = capH + plotH + pad;
410
+ draw();
411
+ return rowHeight;
412
+ },
413
+ handle(kind_, x, y) {
414
+ if (kind_ === 'down') {
415
+ const hit = nearestPx(x, y);
416
+ const c = toCurve(x, y);
417
+ if (hit >= 0) {
418
+ selected = hit;
419
+ dragging = hit;
420
+ }
421
+ else {
422
+ const added = insertPoint(points, c.x, c.y, kind);
423
+ points = added.points;
424
+ selected = added.index;
425
+ dragging = added.index;
426
+ emit();
427
+ }
428
+ draw();
429
+ return;
430
+ }
431
+ if (kind_ === 'move' && dragging >= 0) {
432
+ const c = toCurve(x, y);
433
+ const moved = movePoint(points, dragging, c.x, c.y, kind);
434
+ points = moved.points;
435
+ // The index can change mid-drag when a point crosses a neighbour —
436
+ // keeping the old one would silently start dragging a different point.
437
+ dragging = moved.index;
438
+ selected = moved.index;
439
+ draw();
440
+ emit();
441
+ return;
442
+ }
443
+ if (kind_ === 'up' || kind_ === 'leave')
444
+ dragging = -1;
445
+ },
446
+ hitTest(x, y) {
447
+ // The FRAME, not the plot: an end handle sits on the plot boundary, so a
448
+ // plot-bounded test rejects half of every press aimed at one.
449
+ return (x >= frame.x &&
450
+ x <= frame.x + frame.w &&
451
+ y >= frame.y &&
452
+ y <= frame.y + frame.h);
453
+ },
454
+ get points() {
455
+ return points.map((p) => ({ ...p }));
456
+ },
457
+ setPoints(p) {
458
+ points = normalizeCurve(p, kind);
459
+ selected = -1;
460
+ draw();
461
+ },
462
+ evaluate(t) {
463
+ return evaluateCurve(points, t);
464
+ },
465
+ get selected() {
466
+ return selected;
467
+ },
468
+ deleteSelected() {
469
+ if (selected < 0)
470
+ return;
471
+ const next = deletePoint(points, selected, kind);
472
+ if (next === points)
473
+ return;
474
+ points = next;
475
+ selected = -1;
476
+ draw();
477
+ emit();
478
+ },
479
+ applyPreset(name) {
480
+ const preset = presetsFor(kind).find((p) => p.name === name);
481
+ if (preset == null)
482
+ return;
483
+ points = normalizeCurve(preset.build(), kind);
484
+ selected = -1;
485
+ draw();
486
+ emit();
487
+ },
488
+ };
489
+ return api;
490
+ }
491
+ //# sourceMappingURL=curve-field.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"curve-field.js","sourceRoot":"","sources":["../src/curve-field.ts"],"names":[],"mappings":"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"}