@nice2dev/ui-3d 1.0.0 → 1.0.3

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 (204) hide show
  1. package/CHANGELOG.md +115 -1
  2. package/dist/cjs/collaborative/collaborativeScene.js +210 -0
  3. package/dist/cjs/collaborative/collaborativeScene.js.map +1 -0
  4. package/dist/cjs/core/i18n.js +3 -3
  5. package/dist/cjs/core/i18n.js.map +1 -1
  6. package/dist/cjs/dance/DanceBridge.js +162 -0
  7. package/dist/cjs/dance/DanceBridge.js.map +1 -0
  8. package/dist/cjs/dance/DanceScoreEngine.js +210 -0
  9. package/dist/cjs/dance/DanceScoreEngine.js.map +1 -0
  10. package/dist/cjs/dance/PoseDetector.js +199 -0
  11. package/dist/cjs/dance/PoseDetector.js.map +1 -0
  12. package/dist/cjs/index.js +254 -0
  13. package/dist/cjs/index.js.map +1 -1
  14. package/dist/cjs/material/MaterialEditor.module.css.js +6 -0
  15. package/dist/cjs/material/MaterialEditor.module.css.js.map +1 -0
  16. package/dist/cjs/material/NiceMaterialEditor.js +737 -0
  17. package/dist/cjs/material/NiceMaterialEditor.js.map +1 -0
  18. package/dist/cjs/material/materialEditorTypes.js +73 -0
  19. package/dist/cjs/material/materialEditorTypes.js.map +1 -0
  20. package/dist/cjs/material/materialEditorUtils.js +841 -0
  21. package/dist/cjs/material/materialEditorUtils.js.map +1 -0
  22. package/dist/cjs/material/materialNodeDefinitions.js +1285 -0
  23. package/dist/cjs/material/materialNodeDefinitions.js.map +1 -0
  24. package/dist/cjs/model/ModelEditor.js +4 -1
  25. package/dist/cjs/model/ModelEditor.js.map +1 -1
  26. package/dist/cjs/model/ModelEditor.module.css.js +1 -1
  27. package/dist/cjs/model/ModelEditorLeftPanel.js +5 -4
  28. package/dist/cjs/model/ModelEditorLeftPanel.js.map +1 -1
  29. package/dist/cjs/model/ModelEditorMenuBar.js +8 -3
  30. package/dist/cjs/model/ModelEditorMenuBar.js.map +1 -1
  31. package/dist/cjs/model/ModelEditorRightPanel.js +27 -26
  32. package/dist/cjs/model/ModelEditorRightPanel.js.map +1 -1
  33. package/dist/cjs/model/ModelEditorSubComponents.js +20 -16
  34. package/dist/cjs/model/ModelEditorSubComponents.js.map +1 -1
  35. package/dist/cjs/model/ModelEditorTimeline.js +5 -4
  36. package/dist/cjs/model/ModelEditorTimeline.js.map +1 -1
  37. package/dist/cjs/model/ModelEditorToolbar.js +4 -3
  38. package/dist/cjs/model/ModelEditorToolbar.js.map +1 -1
  39. package/dist/cjs/model/ModelEditorViewport.js +2 -2
  40. package/dist/cjs/model/ModelEditorViewport.js.map +1 -1
  41. package/dist/cjs/model/ModelViewer.js +68 -0
  42. package/dist/cjs/model/ModelViewer.js.map +1 -0
  43. package/dist/cjs/model/ModelViewer.module.css.js +6 -0
  44. package/dist/cjs/model/ModelViewer.module.css.js.map +1 -0
  45. package/dist/cjs/model/NiceArmatureEditor.js +255 -0
  46. package/dist/cjs/model/NiceArmatureEditor.js.map +1 -0
  47. package/dist/cjs/model/NiceMorphTargetEditor.js +206 -0
  48. package/dist/cjs/model/NiceMorphTargetEditor.js.map +1 -0
  49. package/dist/cjs/model/NiceOctree.js +339 -0
  50. package/dist/cjs/model/NiceOctree.js.map +1 -0
  51. package/dist/cjs/model/NicePhysicsSimulation.js +283 -0
  52. package/dist/cjs/model/NicePhysicsSimulation.js.map +1 -0
  53. package/dist/cjs/model/NiceProceduralGeometry.js +269 -0
  54. package/dist/cjs/model/NiceProceduralGeometry.js.map +1 -0
  55. package/dist/cjs/model/NiceTerrainEditor.js +343 -0
  56. package/dist/cjs/model/NiceTerrainEditor.js.map +1 -0
  57. package/dist/cjs/model/NiceWeightPainter.js +258 -0
  58. package/dist/cjs/model/NiceWeightPainter.js.map +1 -0
  59. package/dist/cjs/model/NiceXRPreview.js +269 -0
  60. package/dist/cjs/model/NiceXRPreview.js.map +1 -0
  61. package/dist/cjs/model/cadModeUtils.js +130 -0
  62. package/dist/cjs/model/cadModeUtils.js.map +1 -0
  63. package/dist/cjs/model/editorShortcuts.js +187 -0
  64. package/dist/cjs/model/editorShortcuts.js.map +1 -0
  65. package/dist/cjs/model/modelEditorTypes.js +11 -0
  66. package/dist/cjs/model/modelEditorTypes.js.map +1 -1
  67. package/dist/cjs/model/modelEditorUtils.js +1049 -0
  68. package/dist/cjs/model/modelEditorUtils.js.map +1 -0
  69. package/dist/cjs/model/simsModeUtils.js +358 -0
  70. package/dist/cjs/model/simsModeUtils.js.map +1 -0
  71. package/dist/cjs/model/useModelEditor.js +319 -115
  72. package/dist/cjs/model/useModelEditor.js.map +1 -1
  73. package/dist/cjs/model/useModelViewer.js +634 -0
  74. package/dist/cjs/model/useModelViewer.js.map +1 -0
  75. package/dist/cjs/nice2dev-ui-3d.css +1 -1
  76. package/dist/cjs/particle/NiceParticleEditor.js +526 -0
  77. package/dist/cjs/particle/NiceParticleEditor.js.map +1 -0
  78. package/dist/cjs/particle/ParticleEditor.module.css.js +6 -0
  79. package/dist/cjs/particle/ParticleEditor.module.css.js.map +1 -0
  80. package/dist/cjs/particle/particleEditorTypes.js +92 -0
  81. package/dist/cjs/particle/particleEditorTypes.js.map +1 -0
  82. package/dist/cjs/particle/particleEditorUtils.js +1084 -0
  83. package/dist/cjs/particle/particleEditorUtils.js.map +1 -0
  84. package/dist/cjs/rendering/NiceCascadedShadows.js +266 -0
  85. package/dist/cjs/rendering/NiceCascadedShadows.js.map +1 -0
  86. package/dist/cjs/rendering/NiceRenderExport.js +341 -0
  87. package/dist/cjs/rendering/NiceRenderExport.js.map +1 -0
  88. package/dist/cjs/rendering/NiceSSAO.js +359 -0
  89. package/dist/cjs/rendering/NiceSSAO.js.map +1 -0
  90. package/dist/cjs/rendering/NiceSSR.js +277 -0
  91. package/dist/cjs/rendering/NiceSSR.js.map +1 -0
  92. package/dist/cjs/rendering/NiceWebGPURenderer.js +215 -0
  93. package/dist/cjs/rendering/NiceWebGPURenderer.js.map +1 -0
  94. package/dist/cjs/ui/dist/index.js +50089 -0
  95. package/dist/cjs/ui/dist/index.js.map +1 -0
  96. package/dist/cjs/uv/NiceUVEditor.js +520 -0
  97. package/dist/cjs/uv/NiceUVEditor.js.map +1 -0
  98. package/dist/cjs/uv/UVEditor.module.css.js +6 -0
  99. package/dist/cjs/uv/UVEditor.module.css.js.map +1 -0
  100. package/dist/cjs/uv/uvEditorTypes.js +98 -0
  101. package/dist/cjs/uv/uvEditorTypes.js.map +1 -0
  102. package/dist/cjs/uv/uvEditorUtils.js +670 -0
  103. package/dist/cjs/uv/uvEditorUtils.js.map +1 -0
  104. package/dist/esm/collaborative/collaborativeScene.js +206 -0
  105. package/dist/esm/collaborative/collaborativeScene.js.map +1 -0
  106. package/dist/esm/dance/DanceBridge.js +158 -0
  107. package/dist/esm/dance/DanceBridge.js.map +1 -0
  108. package/dist/esm/dance/DanceScoreEngine.js +207 -0
  109. package/dist/esm/dance/DanceScoreEngine.js.map +1 -0
  110. package/dist/esm/dance/PoseDetector.js +195 -0
  111. package/dist/esm/dance/PoseDetector.js.map +1 -0
  112. package/dist/esm/index.js +35 -1
  113. package/dist/esm/index.js.map +1 -1
  114. package/dist/esm/material/MaterialEditor.module.css.js +4 -0
  115. package/dist/esm/material/MaterialEditor.module.css.js.map +1 -0
  116. package/dist/esm/material/NiceMaterialEditor.js +734 -0
  117. package/dist/esm/material/NiceMaterialEditor.js.map +1 -0
  118. package/dist/esm/material/materialEditorTypes.js +62 -0
  119. package/dist/esm/material/materialEditorTypes.js.map +1 -0
  120. package/dist/esm/material/materialEditorUtils.js +811 -0
  121. package/dist/esm/material/materialEditorUtils.js.map +1 -0
  122. package/dist/esm/material/materialNodeDefinitions.js +1280 -0
  123. package/dist/esm/material/materialNodeDefinitions.js.map +1 -0
  124. package/dist/esm/model/ModelEditor.js +4 -2
  125. package/dist/esm/model/ModelEditor.js.map +1 -1
  126. package/dist/esm/model/ModelEditor.module.css.js +1 -1
  127. package/dist/esm/model/ModelEditorLeftPanel.js +5 -4
  128. package/dist/esm/model/ModelEditorLeftPanel.js.map +1 -1
  129. package/dist/esm/model/ModelEditorMenuBar.js +8 -3
  130. package/dist/esm/model/ModelEditorMenuBar.js.map +1 -1
  131. package/dist/esm/model/ModelEditorRightPanel.js +27 -26
  132. package/dist/esm/model/ModelEditorRightPanel.js.map +1 -1
  133. package/dist/esm/model/ModelEditorSubComponents.js +17 -13
  134. package/dist/esm/model/ModelEditorSubComponents.js.map +1 -1
  135. package/dist/esm/model/ModelEditorTimeline.js +5 -4
  136. package/dist/esm/model/ModelEditorTimeline.js.map +1 -1
  137. package/dist/esm/model/ModelEditorToolbar.js +4 -3
  138. package/dist/esm/model/ModelEditorToolbar.js.map +1 -1
  139. package/dist/esm/model/ModelEditorViewport.js +2 -2
  140. package/dist/esm/model/ModelEditorViewport.js.map +1 -1
  141. package/dist/esm/model/ModelViewer.js +65 -0
  142. package/dist/esm/model/ModelViewer.js.map +1 -0
  143. package/dist/esm/model/ModelViewer.module.css.js +4 -0
  144. package/dist/esm/model/ModelViewer.module.css.js.map +1 -0
  145. package/dist/esm/model/NiceArmatureEditor.js +233 -0
  146. package/dist/esm/model/NiceArmatureEditor.js.map +1 -0
  147. package/dist/esm/model/NiceMorphTargetEditor.js +184 -0
  148. package/dist/esm/model/NiceMorphTargetEditor.js.map +1 -0
  149. package/dist/esm/model/NiceOctree.js +317 -0
  150. package/dist/esm/model/NiceOctree.js.map +1 -0
  151. package/dist/esm/model/NicePhysicsSimulation.js +261 -0
  152. package/dist/esm/model/NicePhysicsSimulation.js.map +1 -0
  153. package/dist/esm/model/NiceProceduralGeometry.js +242 -0
  154. package/dist/esm/model/NiceProceduralGeometry.js.map +1 -0
  155. package/dist/esm/model/NiceTerrainEditor.js +321 -0
  156. package/dist/esm/model/NiceTerrainEditor.js.map +1 -0
  157. package/dist/esm/model/NiceWeightPainter.js +236 -0
  158. package/dist/esm/model/NiceWeightPainter.js.map +1 -0
  159. package/dist/esm/model/NiceXRPreview.js +247 -0
  160. package/dist/esm/model/NiceXRPreview.js.map +1 -0
  161. package/dist/esm/model/cadModeUtils.js +103 -0
  162. package/dist/esm/model/cadModeUtils.js.map +1 -0
  163. package/dist/esm/model/editorShortcuts.js +185 -0
  164. package/dist/esm/model/editorShortcuts.js.map +1 -0
  165. package/dist/esm/model/modelEditorTypes.js +11 -0
  166. package/dist/esm/model/modelEditorTypes.js.map +1 -1
  167. package/dist/esm/model/modelEditorUtils.js +997 -0
  168. package/dist/esm/model/modelEditorUtils.js.map +1 -0
  169. package/dist/esm/model/simsModeUtils.js +325 -0
  170. package/dist/esm/model/simsModeUtils.js.map +1 -0
  171. package/dist/esm/model/useModelEditor.js +204 -0
  172. package/dist/esm/model/useModelEditor.js.map +1 -1
  173. package/dist/esm/model/useModelViewer.js +613 -0
  174. package/dist/esm/model/useModelViewer.js.map +1 -0
  175. package/dist/esm/nice2dev-ui-3d.css +1 -1
  176. package/dist/esm/particle/NiceParticleEditor.js +523 -0
  177. package/dist/esm/particle/NiceParticleEditor.js.map +1 -0
  178. package/dist/esm/particle/ParticleEditor.module.css.js +4 -0
  179. package/dist/esm/particle/ParticleEditor.module.css.js.map +1 -0
  180. package/dist/esm/particle/particleEditorTypes.js +84 -0
  181. package/dist/esm/particle/particleEditorTypes.js.map +1 -0
  182. package/dist/esm/particle/particleEditorUtils.js +1054 -0
  183. package/dist/esm/particle/particleEditorUtils.js.map +1 -0
  184. package/dist/esm/rendering/NiceCascadedShadows.js +244 -0
  185. package/dist/esm/rendering/NiceCascadedShadows.js.map +1 -0
  186. package/dist/esm/rendering/NiceRenderExport.js +319 -0
  187. package/dist/esm/rendering/NiceRenderExport.js.map +1 -0
  188. package/dist/esm/rendering/NiceSSAO.js +337 -0
  189. package/dist/esm/rendering/NiceSSAO.js.map +1 -0
  190. package/dist/esm/rendering/NiceSSR.js +255 -0
  191. package/dist/esm/rendering/NiceSSR.js.map +1 -0
  192. package/dist/esm/rendering/NiceWebGPURenderer.js +193 -0
  193. package/dist/esm/rendering/NiceWebGPURenderer.js.map +1 -0
  194. package/dist/esm/ui/dist/index.js +49686 -0
  195. package/dist/esm/ui/dist/index.js.map +1 -0
  196. package/dist/esm/uv/NiceUVEditor.js +518 -0
  197. package/dist/esm/uv/NiceUVEditor.js.map +1 -0
  198. package/dist/esm/uv/UVEditor.module.css.js +4 -0
  199. package/dist/esm/uv/UVEditor.module.css.js.map +1 -0
  200. package/dist/esm/uv/uvEditorTypes.js +88 -0
  201. package/dist/esm/uv/uvEditorTypes.js.map +1 -0
  202. package/dist/esm/uv/uvEditorUtils.js +621 -0
  203. package/dist/esm/uv/uvEditorUtils.js.map +1 -0
  204. package/package.json +3 -4
@@ -0,0 +1,242 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import * as THREE from 'three';
3
+ import { useState, useCallback } from 'react';
4
+
5
+ /* ── Generators ── */
6
+ function seededRng(seed) {
7
+ let s = seed;
8
+ return () => {
9
+ s = (s * 16807) % 2147483647;
10
+ return (s - 1) / 2147483646;
11
+ };
12
+ }
13
+ function generateTree(params) {
14
+ const group = new THREE.Group();
15
+ group.name = 'ProceduralTree';
16
+ const rng = seededRng(params.seed);
17
+ const trunkMat = new THREE.MeshStandardMaterial({ color: 0x8B4513 });
18
+ const leafMat = new THREE.MeshStandardMaterial({ color: 0x228B22 });
19
+ function addBranch(parent, position, direction, length, radius, depth) {
20
+ const geo = new THREE.CylinderGeometry(radius * params.branchTaper, radius, length, 8);
21
+ geo.translate(0, length / 2, 0);
22
+ const mesh = new THREE.Mesh(geo, trunkMat);
23
+ mesh.position.copy(position);
24
+ // Orient along direction
25
+ const up = new THREE.Vector3(0, 1, 0);
26
+ const quat = new THREE.Quaternion().setFromUnitVectors(up, direction.clone().normalize());
27
+ mesh.quaternion.copy(quat);
28
+ parent.add(mesh);
29
+ if (depth <= 0) {
30
+ // Add leaf cluster
31
+ const leafGeo = new THREE.IcosahedronGeometry(length * 0.6, 1);
32
+ const leaf = new THREE.Mesh(leafGeo, leafMat);
33
+ const tip = position.clone().addScaledVector(direction.clone().normalize(), length);
34
+ leaf.position.copy(tip);
35
+ parent.add(leaf);
36
+ return;
37
+ }
38
+ const tip = position.clone().addScaledVector(direction.clone().normalize(), length);
39
+ const angleRad = (params.branchAngle * Math.PI) / 180;
40
+ for (let i = 0; i < params.branches; i++) {
41
+ const phi = (i / params.branches) * Math.PI * 2 + rng() * 0.5;
42
+ const theta = angleRad + (rng() - 0.5) * 0.3;
43
+ const newDir = new THREE.Vector3(Math.sin(theta) * Math.cos(phi), Math.cos(theta), Math.sin(theta) * Math.sin(phi));
44
+ // Blend with parent direction
45
+ newDir.add(direction.clone().normalize().multiplyScalar(0.5)).normalize();
46
+ addBranch(parent, tip, newDir, length * (0.6 + rng() * 0.2), radius * params.branchTaper, depth - 1);
47
+ }
48
+ }
49
+ addBranch(group, new THREE.Vector3(), new THREE.Vector3(0, 1, 0), params.trunkHeight, params.trunkRadius, params.depth);
50
+ return group;
51
+ }
52
+ function generateRock(params) {
53
+ const geo = new THREE.IcosahedronGeometry(params.radius, params.detail);
54
+ const posAttr = geo.attributes.position;
55
+ const rng = seededRng(params.seed);
56
+ for (let i = 0; i < posAttr.count; i++) {
57
+ const vertex = new THREE.Vector3().fromBufferAttribute(posAttr, i);
58
+ const normal = vertex.clone().normalize();
59
+ // Noise displacement
60
+ const noise = (rng() - 0.5) * 2 * params.noiseAmount;
61
+ const freq = params.noiseScale;
62
+ const displacement = Math.sin(vertex.x * freq) * Math.cos(vertex.y * freq) * Math.sin(vertex.z * freq);
63
+ const totalDisp = (noise + displacement * params.noiseAmount) * params.radius;
64
+ vertex.addScaledVector(normal, totalDisp);
65
+ posAttr.setXYZ(i, vertex.x, vertex.y, vertex.z);
66
+ }
67
+ geo.computeVertexNormals();
68
+ const mesh = new THREE.Mesh(geo, new THREE.MeshStandardMaterial({ color: 0x808080, roughness: 0.9 }));
69
+ mesh.name = 'ProceduralRock';
70
+ mesh.castShadow = true;
71
+ return mesh;
72
+ }
73
+ function generateBuilding(params) {
74
+ const group = new THREE.Group();
75
+ group.name = 'ProceduralBuilding';
76
+ const wallMat = new THREE.MeshStandardMaterial({ color: 0xd4c5a9 });
77
+ const windowMat = new THREE.MeshStandardMaterial({ color: 0x87CEEB, metalness: 0.3, roughness: 0.1 });
78
+ const roofMat = new THREE.MeshStandardMaterial({ color: 0x8B0000 });
79
+ const totalHeight = params.floors * params.floorHeight;
80
+ // Main body
81
+ const bodyGeo = new THREE.BoxGeometry(params.width, totalHeight, params.depth);
82
+ bodyGeo.translate(0, totalHeight / 2, 0);
83
+ group.add(new THREE.Mesh(bodyGeo, wallMat));
84
+ // Windows
85
+ for (let floor = 0; floor < params.floors; floor++) {
86
+ const y = floor * params.floorHeight + params.floorHeight * 0.5;
87
+ for (let w = 0; w < params.windowsPerFloor; w++) {
88
+ const x = (w - (params.windowsPerFloor - 1) / 2) * (params.width / (params.windowsPerFloor + 1));
89
+ // Front face windows
90
+ const winGeo = new THREE.PlaneGeometry(params.windowWidth, params.windowHeight);
91
+ const winMesh = new THREE.Mesh(winGeo, windowMat);
92
+ winMesh.position.set(x, y, params.depth / 2 + 0.01);
93
+ group.add(winMesh);
94
+ // Back face windows
95
+ const winBack = winMesh.clone();
96
+ winBack.position.z = -params.depth / 2 - 0.01;
97
+ winBack.rotation.y = Math.PI;
98
+ group.add(winBack);
99
+ }
100
+ }
101
+ // Roof
102
+ switch (params.roofStyle) {
103
+ case 'gable': {
104
+ const shape = new THREE.Shape();
105
+ shape.moveTo(-params.width / 2, 0);
106
+ shape.lineTo(0, params.roofHeight);
107
+ shape.lineTo(params.width / 2, 0);
108
+ shape.lineTo(-params.width / 2, 0);
109
+ const extrudeGeo = new THREE.ExtrudeGeometry(shape, { depth: params.depth, bevelEnabled: false });
110
+ const roof = new THREE.Mesh(extrudeGeo, roofMat);
111
+ roof.position.set(0, totalHeight, -params.depth / 2);
112
+ group.add(roof);
113
+ break;
114
+ }
115
+ case 'hip': {
116
+ const roofGeo = new THREE.ConeGeometry(Math.max(params.width, params.depth) * 0.7, params.roofHeight, 4);
117
+ roofGeo.rotateY(Math.PI / 4);
118
+ const roof = new THREE.Mesh(roofGeo, roofMat);
119
+ roof.position.y = totalHeight + params.roofHeight / 2;
120
+ group.add(roof);
121
+ break;
122
+ }
123
+ default: {
124
+ // flat roof
125
+ const flatGeo = new THREE.BoxGeometry(params.width + 0.4, 0.2, params.depth + 0.4);
126
+ const roof = new THREE.Mesh(flatGeo, roofMat);
127
+ roof.position.y = totalHeight + 0.1;
128
+ group.add(roof);
129
+ }
130
+ }
131
+ group.traverse((child) => {
132
+ if (child instanceof THREE.Mesh) {
133
+ child.castShadow = true;
134
+ child.receiveShadow = true;
135
+ }
136
+ });
137
+ return group;
138
+ }
139
+ function generatePipe(params) {
140
+ const curve = new THREE.CatmullRomCurve3(params.points, params.closed);
141
+ const geo = new THREE.TubeGeometry(curve, params.segments, params.radius, params.radialSegments, params.closed);
142
+ const mesh = new THREE.Mesh(geo, new THREE.MeshStandardMaterial({ color: 0xaaaaaa, metalness: 0.8, roughness: 0.2 }));
143
+ mesh.name = 'ProceduralPipe';
144
+ mesh.castShadow = true;
145
+ return mesh;
146
+ }
147
+ function generateGear(params) {
148
+ const shape = new THREE.Shape();
149
+ const angleStep = (Math.PI * 2) / (params.teeth * 2);
150
+ for (let i = 0; i < params.teeth * 2; i++) {
151
+ const angle = i * angleStep;
152
+ const r = i % 2 === 0 ? params.outerRadius : params.outerRadius - params.toothDepth;
153
+ const x = Math.cos(angle) * r;
154
+ const y = Math.sin(angle) * r;
155
+ if (i === 0)
156
+ shape.moveTo(x, y);
157
+ else
158
+ shape.lineTo(x, y);
159
+ }
160
+ shape.closePath();
161
+ // Inner hole
162
+ const hole = new THREE.Path();
163
+ const holeSegments = 32;
164
+ for (let i = 0; i <= holeSegments; i++) {
165
+ const angle = (i / holeSegments) * Math.PI * 2;
166
+ const x = Math.cos(angle) * params.innerRadius;
167
+ const y = Math.sin(angle) * params.innerRadius;
168
+ if (i === 0)
169
+ hole.moveTo(x, y);
170
+ else
171
+ hole.lineTo(x, y);
172
+ }
173
+ shape.holes.push(hole);
174
+ const geo = new THREE.ExtrudeGeometry(shape, {
175
+ depth: params.thickness,
176
+ bevelEnabled: false,
177
+ });
178
+ geo.rotateX(-Math.PI / 2);
179
+ geo.translate(0, params.thickness / 2, 0);
180
+ const mesh = new THREE.Mesh(geo, new THREE.MeshStandardMaterial({ color: 0x888888, metalness: 0.7, roughness: 0.3 }));
181
+ mesh.name = 'ProceduralGear';
182
+ mesh.castShadow = true;
183
+ return mesh;
184
+ }
185
+ /* ── Hook ── */
186
+ const DEFAULT_TREE = { trunkRadius: 0.3, trunkHeight: 4, branches: 3, depth: 3, branchAngle: 30, branchLength: 3, branchTaper: 0.7, seed: 42 };
187
+ const DEFAULT_ROCK = { radius: 1, detail: 3, noiseScale: 3, noiseAmount: 0.2, seed: 42 };
188
+ const DEFAULT_BUILDING = { width: 8, depth: 6, floors: 4, floorHeight: 3, windowsPerFloor: 3, windowWidth: 1.2, windowHeight: 1.5, roofStyle: 'gable', roofHeight: 3 };
189
+ const DEFAULT_PIPE = {
190
+ radius: 0.2, segments: 64, radialSegments: 8, closed: false,
191
+ points: [new THREE.Vector3(0, 0, 0), new THREE.Vector3(2, 2, 0), new THREE.Vector3(4, 0, 2), new THREE.Vector3(6, 2, 2)]
192
+ };
193
+ const DEFAULT_GEAR = { innerRadius: 0.5, outerRadius: 2, teeth: 12, toothDepth: 0.3, thickness: 0.4 };
194
+ function useProceduralGeometry(scene, onGenerated) {
195
+ const [type, setType] = useState('tree');
196
+ const [treeParams, setTreeParams] = useState(DEFAULT_TREE);
197
+ const [rockParams, setRockParams] = useState(DEFAULT_ROCK);
198
+ const [buildingParams, setBuildingParams] = useState(DEFAULT_BUILDING);
199
+ const [pipeParams, setPipeParams] = useState(DEFAULT_PIPE);
200
+ const [gearParams, setGearParams] = useState(DEFAULT_GEAR);
201
+ const generate = useCallback(() => {
202
+ if (!scene)
203
+ return;
204
+ let result;
205
+ switch (type) {
206
+ case 'tree':
207
+ result = generateTree(treeParams);
208
+ break;
209
+ case 'rock':
210
+ result = generateRock(rockParams);
211
+ break;
212
+ case 'building':
213
+ result = generateBuilding(buildingParams);
214
+ break;
215
+ case 'pipe':
216
+ result = generatePipe(pipeParams);
217
+ break;
218
+ case 'gear':
219
+ result = generateGear(gearParams);
220
+ break;
221
+ }
222
+ scene.add(result);
223
+ onGenerated === null || onGenerated === void 0 ? void 0 : onGenerated(result);
224
+ }, [scene, type, treeParams, rockParams, buildingParams, pipeParams, gearParams, onGenerated]);
225
+ return {
226
+ type, setType,
227
+ treeParams, setTreeParams,
228
+ rockParams, setRockParams,
229
+ buildingParams, setBuildingParams,
230
+ pipeParams, setPipeParams,
231
+ gearParams, setGearParams,
232
+ generate,
233
+ };
234
+ }
235
+ /* ── Component ── */
236
+ const NiceProceduralGeometry = ({ scene, onGenerated, className = '', }) => {
237
+ const { type, setType, treeParams, setTreeParams, rockParams, setRockParams, buildingParams, setBuildingParams, gearParams, setGearParams, generate, } = useProceduralGeometry(scene, onGenerated);
238
+ return (jsxs("div", { className: `nice-procedural-geometry ${className}`, style: { display: 'grid', gap: 8, fontSize: 13 }, children: [jsx("strong", { children: "Procedural Geometry" }), jsxs("select", { value: type, onChange: (e) => setType(e.target.value), style: { width: '100%', padding: '4px 8px' }, children: [jsx("option", { value: "tree", children: "\uD83C\uDF33 Tree" }), jsx("option", { value: "rock", children: "\uD83E\uDEA8 Rock" }), jsx("option", { value: "building", children: "\uD83C\uDFE2 Building" }), jsx("option", { value: "pipe", children: "\uD83D\uDD27 Pipe" }), jsx("option", { value: "gear", children: "\u2699 Gear" })] }), type === 'tree' && (jsxs("div", { style: { display: 'grid', gap: 4 }, children: [jsxs("label", { children: ["Height: ", treeParams.trunkHeight.toFixed(1), jsx("input", { type: "range", min: 1, max: 15, step: 0.5, value: treeParams.trunkHeight, onChange: (e) => setTreeParams({ ...treeParams, trunkHeight: parseFloat(e.target.value) }), style: { width: '100%' } })] }), jsxs("label", { children: ["Branches: ", treeParams.branches, jsx("input", { type: "range", min: 1, max: 6, value: treeParams.branches, onChange: (e) => setTreeParams({ ...treeParams, branches: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxs("label", { children: ["Depth: ", treeParams.depth, jsx("input", { type: "range", min: 1, max: 5, value: treeParams.depth, onChange: (e) => setTreeParams({ ...treeParams, depth: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxs("label", { children: ["Angle: ", treeParams.branchAngle, "\u00B0", jsx("input", { type: "range", min: 10, max: 80, value: treeParams.branchAngle, onChange: (e) => setTreeParams({ ...treeParams, branchAngle: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxs("label", { children: ["Seed: ", treeParams.seed, jsx("input", { type: "range", min: 1, max: 999, value: treeParams.seed, onChange: (e) => setTreeParams({ ...treeParams, seed: parseInt(e.target.value, 10) }), style: { width: '100%' } })] })] })), type === 'rock' && (jsxs("div", { style: { display: 'grid', gap: 4 }, children: [jsxs("label", { children: ["Radius: ", rockParams.radius.toFixed(1), jsx("input", { type: "range", min: 0.2, max: 5, step: 0.1, value: rockParams.radius, onChange: (e) => setRockParams({ ...rockParams, radius: parseFloat(e.target.value) }), style: { width: '100%' } })] }), jsxs("label", { children: ["Detail: ", rockParams.detail, jsx("input", { type: "range", min: 1, max: 5, value: rockParams.detail, onChange: (e) => setRockParams({ ...rockParams, detail: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxs("label", { children: ["Noise: ", rockParams.noiseAmount.toFixed(2), jsx("input", { type: "range", min: 0, max: 0.5, step: 0.01, value: rockParams.noiseAmount, onChange: (e) => setRockParams({ ...rockParams, noiseAmount: parseFloat(e.target.value) }), style: { width: '100%' } })] }), jsxs("label", { children: ["Seed: ", rockParams.seed, jsx("input", { type: "range", min: 1, max: 999, value: rockParams.seed, onChange: (e) => setRockParams({ ...rockParams, seed: parseInt(e.target.value, 10) }), style: { width: '100%' } })] })] })), type === 'building' && (jsxs("div", { style: { display: 'grid', gap: 4 }, children: [jsxs("label", { children: ["Width: ", buildingParams.width, jsx("input", { type: "range", min: 4, max: 20, step: 1, value: buildingParams.width, onChange: (e) => setBuildingParams({ ...buildingParams, width: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxs("label", { children: ["Floors: ", buildingParams.floors, jsx("input", { type: "range", min: 1, max: 20, value: buildingParams.floors, onChange: (e) => setBuildingParams({ ...buildingParams, floors: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxs("label", { children: ["Windows/Floor: ", buildingParams.windowsPerFloor, jsx("input", { type: "range", min: 1, max: 10, value: buildingParams.windowsPerFloor, onChange: (e) => setBuildingParams({ ...buildingParams, windowsPerFloor: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxs("label", { children: ["Roof:", jsxs("select", { value: buildingParams.roofStyle, onChange: (e) => setBuildingParams({ ...buildingParams, roofStyle: e.target.value }), style: { marginLeft: 8 }, children: [jsx("option", { value: "flat", children: "Flat" }), jsx("option", { value: "gable", children: "Gable" }), jsx("option", { value: "hip", children: "Hip" })] })] })] })), type === 'gear' && (jsxs("div", { style: { display: 'grid', gap: 4 }, children: [jsxs("label", { children: ["Outer Radius: ", gearParams.outerRadius.toFixed(1), jsx("input", { type: "range", min: 0.5, max: 5, step: 0.1, value: gearParams.outerRadius, onChange: (e) => setGearParams({ ...gearParams, outerRadius: parseFloat(e.target.value) }), style: { width: '100%' } })] }), jsxs("label", { children: ["Teeth: ", gearParams.teeth, jsx("input", { type: "range", min: 4, max: 30, value: gearParams.teeth, onChange: (e) => setGearParams({ ...gearParams, teeth: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxs("label", { children: ["Tooth Depth: ", gearParams.toothDepth.toFixed(2), jsx("input", { type: "range", min: 0.05, max: 1, step: 0.05, value: gearParams.toothDepth, onChange: (e) => setGearParams({ ...gearParams, toothDepth: parseFloat(e.target.value) }), style: { width: '100%' } })] }), jsxs("label", { children: ["Thickness: ", gearParams.thickness.toFixed(2), jsx("input", { type: "range", min: 0.1, max: 2, step: 0.1, value: gearParams.thickness, onChange: (e) => setGearParams({ ...gearParams, thickness: parseFloat(e.target.value) }), style: { width: '100%' } })] })] })), jsx("button", { type: "button", onClick: generate, style: { background: 'var(--accent, #6366f1)', color: '#fff', border: 'none', borderRadius: 4, padding: '6px 12px', cursor: 'pointer' }, children: "\u2728 Generate" })] }));
239
+ };
240
+
241
+ export { NiceProceduralGeometry, generateBuilding, generateGear, generatePipe, generateRock, generateTree, useProceduralGeometry };
242
+ //# sourceMappingURL=NiceProceduralGeometry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NiceProceduralGeometry.js","sources":["../../../src/model/NiceProceduralGeometry.tsx"],"sourcesContent":[null],"names":["_jsxs","_jsx"],"mappings":"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"}
@@ -0,0 +1,321 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import * as THREE from 'three';
3
+ import { useState, useRef, useEffect, useCallback } from 'react';
4
+
5
+ function fractalNoise(x, z, octaves, persistence, lacunarity, rng) {
6
+ let value = 0;
7
+ let amplitude = 1;
8
+ let frequency = 1;
9
+ let maxValue = 0;
10
+ for (let i = 0; i < octaves; i++) {
11
+ // Simple value noise using sin-based hash
12
+ const nx = x * frequency;
13
+ const nz = z * frequency;
14
+ const noise = Math.sin(nx * 12.9898 + nz * 78.233) * 43758.5453;
15
+ value += (noise - Math.floor(noise)) * amplitude;
16
+ maxValue += amplitude;
17
+ amplitude *= persistence;
18
+ frequency *= lacunarity;
19
+ }
20
+ return value / maxValue;
21
+ }
22
+ /* ── Hook ── */
23
+ function useTerrainEditor(scene, camera, canvas, config = { width: 100, depth: 100, segments: 128, maxHeight: 20 }, onTerrainChange) {
24
+ const [brush, setBrushState] = useState({
25
+ mode: 'raise',
26
+ radius: 5,
27
+ strength: 0.3,
28
+ falloff: 'smooth',
29
+ });
30
+ const [isPainting, setIsPainting] = useState(false);
31
+ const [textureLayers, setTextureLayers] = useState([
32
+ { name: 'Grass', texture: null, scale: 10 },
33
+ { name: 'Rock', texture: null, scale: 8 },
34
+ { name: 'Sand', texture: null, scale: 12 },
35
+ { name: 'Snow', texture: null, scale: 10 },
36
+ ]);
37
+ const [activeTextureLayer, setActiveTextureLayer] = useState(0);
38
+ const terrainRef = useRef(null);
39
+ const splatMapRef = useRef(null);
40
+ const raycaster = useRef(new THREE.Raycaster());
41
+ // Create terrain mesh
42
+ useEffect(() => {
43
+ if (!scene)
44
+ return;
45
+ const geometry = new THREE.PlaneGeometry(config.width, config.depth, config.segments, config.segments);
46
+ geometry.rotateX(-Math.PI / 2);
47
+ const material = new THREE.MeshStandardMaterial({
48
+ color: 0x4a7c4f,
49
+ wireframe: false,
50
+ flatShading: false,
51
+ side: THREE.DoubleSide,
52
+ });
53
+ const mesh = new THREE.Mesh(geometry, material);
54
+ mesh.receiveShadow = true;
55
+ mesh.castShadow = true;
56
+ mesh.name = 'NiceTerrain';
57
+ scene.add(mesh);
58
+ terrainRef.current = mesh;
59
+ // Initialize splat map (RGBA per vertex)
60
+ const vertexCount = geometry.attributes.position.count;
61
+ const splatMap = new Float32Array(vertexCount * 4);
62
+ for (let i = 0; i < vertexCount; i++) {
63
+ splatMap[i * 4] = 1; // R = grass by default
64
+ }
65
+ splatMapRef.current = splatMap;
66
+ return () => {
67
+ scene.remove(mesh);
68
+ geometry.dispose();
69
+ material.dispose();
70
+ };
71
+ }, [scene, config.width, config.depth, config.segments]);
72
+ const setBrush = useCallback((partial) => {
73
+ setBrushState((prev) => ({ ...prev, ...partial }));
74
+ }, []);
75
+ const applyBrushAtPoint = useCallback((point) => {
76
+ const mesh = terrainRef.current;
77
+ if (!mesh)
78
+ return;
79
+ const posAttr = mesh.geometry.attributes.position;
80
+ const vertex = new THREE.Vector3();
81
+ for (let i = 0; i < posAttr.count; i++) {
82
+ vertex.fromBufferAttribute(posAttr, i);
83
+ const dx = vertex.x - point.x;
84
+ const dz = vertex.z - point.z;
85
+ const dist = Math.sqrt(dx * dx + dz * dz);
86
+ if (dist > brush.radius)
87
+ continue;
88
+ // Falloff
89
+ const t = dist / brush.radius;
90
+ let falloff;
91
+ switch (brush.falloff) {
92
+ case 'constant':
93
+ falloff = 1;
94
+ break;
95
+ case 'linear':
96
+ falloff = 1 - t;
97
+ break;
98
+ case 'smooth':
99
+ falloff = 1 - t * t * (3 - 2 * t);
100
+ break;
101
+ default: falloff = 1 - t;
102
+ }
103
+ const influence = falloff * brush.strength;
104
+ switch (brush.mode) {
105
+ case 'raise':
106
+ posAttr.setY(i, posAttr.getY(i) + influence);
107
+ break;
108
+ case 'lower':
109
+ posAttr.setY(i, posAttr.getY(i) - influence);
110
+ break;
111
+ case 'flatten':
112
+ posAttr.setY(i, posAttr.getY(i) + (point.y - posAttr.getY(i)) * influence);
113
+ break;
114
+ case 'smooth': {
115
+ // Average with neighbors
116
+ let avg = posAttr.getY(i);
117
+ let count = 1;
118
+ const seg = config.segments + 1;
119
+ const row = Math.floor(i / seg);
120
+ const col = i % seg;
121
+ const neighbors = [
122
+ row > 0 ? i - seg : -1,
123
+ row < config.segments ? i + seg : -1,
124
+ col > 0 ? i - 1 : -1,
125
+ col < config.segments ? i + 1 : -1,
126
+ ];
127
+ for (const ni of neighbors) {
128
+ if (ni >= 0 && ni < posAttr.count) {
129
+ avg += posAttr.getY(ni);
130
+ count++;
131
+ }
132
+ }
133
+ avg /= count;
134
+ posAttr.setY(i, posAttr.getY(i) + (avg - posAttr.getY(i)) * influence);
135
+ break;
136
+ }
137
+ case 'noise':
138
+ posAttr.setY(i, posAttr.getY(i) + (Math.random() - 0.5) * influence * 2);
139
+ break;
140
+ case 'paint': {
141
+ // Paint active texture layer onto vertices
142
+ if (splatMapRef.current) {
143
+ const offset = i * 4;
144
+ // Reduce all channels slightly
145
+ for (let c = 0; c < 4; c++) {
146
+ splatMapRef.current[offset + c] *= 1 - influence * 0.5;
147
+ }
148
+ splatMapRef.current[offset + activeTextureLayer] += influence;
149
+ // Normalize
150
+ let total = 0;
151
+ for (let c = 0; c < 4; c++)
152
+ total += splatMapRef.current[offset + c];
153
+ if (total > 0) {
154
+ for (let c = 0; c < 4; c++)
155
+ splatMapRef.current[offset + c] /= total;
156
+ }
157
+ }
158
+ break;
159
+ }
160
+ }
161
+ }
162
+ posAttr.needsUpdate = true;
163
+ mesh.geometry.computeVertexNormals();
164
+ onTerrainChange === null || onTerrainChange === void 0 ? void 0 : onTerrainChange(mesh);
165
+ }, [brush, config.segments, activeTextureLayer, onTerrainChange]);
166
+ // Mouse handling
167
+ useEffect(() => {
168
+ if (!canvas || !camera || !isPainting)
169
+ return;
170
+ const onPointerMove = (e) => {
171
+ const rect = canvas.getBoundingClientRect();
172
+ const mouse = new THREE.Vector2(((e.clientX - rect.left) / rect.width) * 2 - 1, -((e.clientY - rect.top) / rect.height) * 2 + 1);
173
+ raycaster.current.setFromCamera(mouse, camera);
174
+ const mesh = terrainRef.current;
175
+ if (!mesh)
176
+ return;
177
+ const intersects = raycaster.current.intersectObject(mesh);
178
+ if (intersects.length > 0) {
179
+ applyBrushAtPoint(intersects[0].point);
180
+ }
181
+ };
182
+ canvas.addEventListener('pointermove', onPointerMove);
183
+ return () => canvas.removeEventListener('pointermove', onPointerMove);
184
+ }, [canvas, camera, isPainting, applyBrushAtPoint]);
185
+ const generateFlat = useCallback(() => {
186
+ const mesh = terrainRef.current;
187
+ if (!mesh)
188
+ return;
189
+ const posAttr = mesh.geometry.attributes.position;
190
+ for (let i = 0; i < posAttr.count; i++) {
191
+ posAttr.setY(i, 0);
192
+ }
193
+ posAttr.needsUpdate = true;
194
+ mesh.geometry.computeVertexNormals();
195
+ onTerrainChange === null || onTerrainChange === void 0 ? void 0 : onTerrainChange(mesh);
196
+ }, [onTerrainChange]);
197
+ const generateNoise = useCallback((octaves = 6, persistence = 0.5, lacunarity = 2.0) => {
198
+ const mesh = terrainRef.current;
199
+ if (!mesh)
200
+ return;
201
+ const posAttr = mesh.geometry.attributes.position;
202
+ for (let i = 0; i < posAttr.count; i++) {
203
+ const x = posAttr.getX(i) / config.width;
204
+ const z = posAttr.getZ(i) / config.depth;
205
+ const height = fractalNoise(x, z, octaves, persistence, lacunarity) * config.maxHeight;
206
+ posAttr.setY(i, height);
207
+ }
208
+ posAttr.needsUpdate = true;
209
+ mesh.geometry.computeVertexNormals();
210
+ onTerrainChange === null || onTerrainChange === void 0 ? void 0 : onTerrainChange(mesh);
211
+ }, [config, onTerrainChange]);
212
+ const importHeightmap = useCallback((image) => {
213
+ const mesh = terrainRef.current;
214
+ if (!mesh)
215
+ return;
216
+ const tmpCanvas = document.createElement('canvas');
217
+ tmpCanvas.width = image.width;
218
+ tmpCanvas.height = image.height;
219
+ const ctx = tmpCanvas.getContext('2d');
220
+ if (!ctx)
221
+ return;
222
+ ctx.drawImage(image, 0, 0);
223
+ const imageData = ctx.getImageData(0, 0, image.width, image.height);
224
+ const posAttr = mesh.geometry.attributes.position;
225
+ const seg = config.segments + 1;
226
+ for (let i = 0; i < posAttr.count; i++) {
227
+ const row = Math.floor(i / seg);
228
+ const col = i % seg;
229
+ const px = Math.floor((col / config.segments) * (image.width - 1));
230
+ const py = Math.floor((row / config.segments) * (image.height - 1));
231
+ const idx = (py * image.width + px) * 4;
232
+ const gray = imageData.data[idx] / 255;
233
+ posAttr.setY(i, gray * config.maxHeight);
234
+ }
235
+ posAttr.needsUpdate = true;
236
+ mesh.geometry.computeVertexNormals();
237
+ onTerrainChange === null || onTerrainChange === void 0 ? void 0 : onTerrainChange(mesh);
238
+ }, [config, onTerrainChange]);
239
+ const exportHeightmap = useCallback(() => {
240
+ const mesh = terrainRef.current;
241
+ if (!mesh)
242
+ return null;
243
+ const posAttr = mesh.geometry.attributes.position;
244
+ const seg = config.segments + 1;
245
+ const exportCanvas = document.createElement('canvas');
246
+ exportCanvas.width = seg;
247
+ exportCanvas.height = seg;
248
+ const ctx = exportCanvas.getContext('2d');
249
+ if (!ctx)
250
+ return null;
251
+ const imageData = ctx.createImageData(seg, seg);
252
+ let minY = Infinity;
253
+ let maxY = -Infinity;
254
+ for (let i = 0; i < posAttr.count; i++) {
255
+ const y = posAttr.getY(i);
256
+ if (y < minY)
257
+ minY = y;
258
+ if (y > maxY)
259
+ maxY = y;
260
+ }
261
+ const range = maxY - minY || 1;
262
+ for (let i = 0; i < posAttr.count; i++) {
263
+ const gray = Math.round(((posAttr.getY(i) - minY) / range) * 255);
264
+ imageData.data[i * 4] = gray;
265
+ imageData.data[i * 4 + 1] = gray;
266
+ imageData.data[i * 4 + 2] = gray;
267
+ imageData.data[i * 4 + 3] = 255;
268
+ }
269
+ ctx.putImageData(imageData, 0, 0);
270
+ return exportCanvas;
271
+ }, [config.segments]);
272
+ const setTextureLayer = useCallback((index, partial) => {
273
+ setTextureLayers((prev) => prev.map((l, i) => (i === index ? { ...l, ...partial } : l)));
274
+ }, []);
275
+ return {
276
+ terrainMesh: terrainRef.current,
277
+ brush,
278
+ setBrush,
279
+ isPainting,
280
+ startPainting: () => setIsPainting(true),
281
+ stopPainting: () => setIsPainting(false),
282
+ generateFlat,
283
+ generateNoise,
284
+ importHeightmap,
285
+ exportHeightmap,
286
+ textureLayers,
287
+ setTextureLayer,
288
+ activeTextureLayer,
289
+ setActiveTextureLayer,
290
+ };
291
+ }
292
+ /* ── Component ── */
293
+ const NiceTerrainEditor = ({ scene, camera, canvas, config: configProp, onTerrainChange, className = '', }) => {
294
+ const config = {
295
+ width: 100,
296
+ depth: 100,
297
+ segments: 128,
298
+ maxHeight: 20,
299
+ ...configProp,
300
+ };
301
+ const { brush, setBrush, isPainting, startPainting, stopPainting, generateFlat, generateNoise, exportHeightmap, textureLayers, setTextureLayer, activeTextureLayer, setActiveTextureLayer, } = useTerrainEditor(scene, camera, canvas, config, onTerrainChange);
302
+ const [noiseOctaves, setNoiseOctaves] = useState(6);
303
+ const [noisePersistence, setNoisePersistence] = useState(0.5);
304
+ return (jsxs("div", { className: `nice-terrain-editor ${className}`, style: { display: 'grid', gap: 8, fontSize: 13 }, children: [jsx("strong", { children: "Terrain Editor" }), jsxs("fieldset", { style: { border: '1px solid var(--border, #e2e8f0)', borderRadius: 6, padding: 4, display: 'flex', flexWrap: 'wrap', gap: 2 }, children: [jsx("legend", { style: { fontSize: 11 }, children: "Brush" }), ['raise', 'lower', 'flatten', 'smooth', 'noise', 'paint'].map((m) => (jsx("button", { type: "button", onClick: () => setBrush({ mode: m }), style: {
305
+ padding: '3px 6px', fontSize: 11, cursor: 'pointer', borderRadius: 4,
306
+ border: '1px solid var(--border, #e2e8f0)',
307
+ background: brush.mode === m ? 'var(--accent, #6366f1)' : 'transparent',
308
+ color: brush.mode === m ? '#fff' : 'inherit',
309
+ }, children: m }, m)))] }), jsxs("label", { children: ["Radius: ", brush.radius.toFixed(1), jsx("input", { type: "range", min: 0.5, max: 20, step: 0.5, value: brush.radius, onChange: (e) => setBrush({ radius: parseFloat(e.target.value) }), style: { width: '100%' } })] }), jsxs("label", { children: ["Strength: ", brush.strength.toFixed(2), jsx("input", { type: "range", min: 0.01, max: 1, step: 0.01, value: brush.strength, onChange: (e) => setBrush({ strength: parseFloat(e.target.value) }), style: { width: '100%' } })] }), jsx("button", { type: "button", onClick: isPainting ? stopPainting : startPainting, style: { background: isPainting ? '#ef4444' : 'var(--accent, #6366f1)', color: '#fff', border: 'none', borderRadius: 4, padding: '6px 12px', cursor: 'pointer' }, children: isPainting ? '⏹ Stop Painting' : '🖌 Start Painting' }), jsxs("fieldset", { style: { border: '1px solid var(--border, #e2e8f0)', borderRadius: 6, padding: 6, display: 'grid', gap: 4 }, children: [jsx("legend", { style: { fontSize: 11 }, children: "Procedural" }), jsxs("label", { children: ["Octaves: ", noiseOctaves, jsx("input", { type: "range", min: 1, max: 10, value: noiseOctaves, onChange: (e) => setNoiseOctaves(parseInt(e.target.value, 10)), style: { width: '100%' } })] }), jsxs("label", { children: ["Persistence: ", noisePersistence.toFixed(2), jsx("input", { type: "range", min: 0.1, max: 1, step: 0.05, value: noisePersistence, onChange: (e) => setNoisePersistence(parseFloat(e.target.value)), style: { width: '100%' } })] }), jsxs("div", { style: { display: 'flex', gap: 4 }, children: [jsx("button", { type: "button", onClick: () => generateNoise(noiseOctaves, noisePersistence), style: { flex: 1 }, children: "\uD83C\uDFD4 Generate Noise" }), jsx("button", { type: "button", onClick: generateFlat, style: { flex: 1 }, children: "\u2B1C Flatten" })] })] }), brush.mode === 'paint' && (jsxs("fieldset", { style: { border: '1px solid var(--border, #e2e8f0)', borderRadius: 6, padding: 6, display: 'grid', gap: 4 }, children: [jsx("legend", { style: { fontSize: 11 }, children: "Texture Layers" }), textureLayers.map((layer, i) => (jsxs("label", { style: { display: 'flex', alignItems: 'center', gap: 6 }, children: [jsx("input", { type: "radio", name: "texLayer", checked: activeTextureLayer === i, onChange: () => setActiveTextureLayer(i) }), jsx("input", { type: "text", value: layer.name, onChange: (e) => setTextureLayer(i, { name: e.target.value }), style: { flex: 1, padding: '2px 6px', border: '1px solid var(--border, #e2e8f0)', borderRadius: 4 } })] }, i)))] })), jsx("button", { type: "button", onClick: () => {
310
+ const c = exportHeightmap();
311
+ if (c) {
312
+ const link = document.createElement('a');
313
+ link.download = 'heightmap.png';
314
+ link.href = c.toDataURL('image/png');
315
+ link.click();
316
+ }
317
+ }, style: { fontSize: 11 }, children: "\uD83D\uDCE5 Export Heightmap PNG" })] }));
318
+ };
319
+
320
+ export { NiceTerrainEditor, useTerrainEditor };
321
+ //# sourceMappingURL=NiceTerrainEditor.js.map