@nice2dev/ui-3d 1.3.15 → 1.3.17

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 (108) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/collaborative/collaborativeScene.js +160 -206
  3. package/dist/cjs/core/editorAsk.js +51 -41
  4. package/dist/cjs/core/i18n.js +13 -14
  5. package/dist/cjs/core/threeCompat.js +29 -42
  6. package/dist/cjs/dance/DanceBridge.js +148 -177
  7. package/dist/cjs/dance/DanceScoreEngine.js +209 -221
  8. package/dist/cjs/dance/PoseDetector.js +302 -275
  9. package/dist/cjs/index.js +110 -113
  10. package/dist/cjs/material/MaterialEditor.module.css.js +242 -5
  11. package/dist/cjs/material/NiceMaterialEditor.js +1213 -757
  12. package/dist/cjs/material/materialEditorTypes.js +35 -49
  13. package/dist/cjs/material/materialEditorUtils.js +684 -747
  14. package/dist/cjs/material/materialNodeDefinitions.js +1411 -1459
  15. package/dist/cjs/model/ModelEditor.js +90 -40
  16. package/dist/cjs/model/ModelEditor.module.css.js +257 -5
  17. package/dist/cjs/model/ModelEditorLeftPanel.js +126 -47
  18. package/dist/cjs/model/ModelEditorMenuBar.js +359 -32
  19. package/dist/cjs/model/ModelEditorRightPanel.js +647 -131
  20. package/dist/cjs/model/ModelEditorSubComponents.js +277 -112
  21. package/dist/cjs/model/ModelEditorTimeline.js +232 -34
  22. package/dist/cjs/model/ModelEditorToolbar.js +170 -14
  23. package/dist/cjs/model/ModelEditorViewport.js +231 -39
  24. package/dist/cjs/model/ModelViewer.js +388 -63
  25. package/dist/cjs/model/ModelViewer.module.css.js +77 -5
  26. package/dist/cjs/model/NiceArmatureEditor.js +473 -274
  27. package/dist/cjs/model/NiceMorphTargetEditor.js +333 -227
  28. package/dist/cjs/model/NiceOctree.js +372 -320
  29. package/dist/cjs/model/NicePhysicsSimulation.js +528 -298
  30. package/dist/cjs/model/NiceProceduralGeometry.js +673 -300
  31. package/dist/cjs/model/NiceTerrainEditor.js +595 -385
  32. package/dist/cjs/model/NiceWeightPainter.js +384 -261
  33. package/dist/cjs/model/NiceXRPreview.js +385 -308
  34. package/dist/cjs/model/cadModeUtils.js +103 -106
  35. package/dist/cjs/model/editorShortcuts.js +171 -194
  36. package/dist/cjs/model/modelEditorTypes.js +100 -118
  37. package/dist/cjs/model/modelEditorUtils.js +1061 -1146
  38. package/dist/cjs/model/simsModeUtils.js +1023 -1053
  39. package/dist/cjs/model/useModelEditor.js +1977 -1933
  40. package/dist/cjs/model/useModelViewer.js +633 -665
  41. package/dist/cjs/nice2dev-ui-3d.css +1 -1
  42. package/dist/cjs/particle/NiceParticleEditor.js +1186 -571
  43. package/dist/cjs/particle/ParticleEditor.module.css.js +122 -5
  44. package/dist/cjs/particle/particleEditorTypes.js +62 -70
  45. package/dist/cjs/particle/particleEditorUtils.js +998 -1013
  46. package/dist/cjs/rendering/NiceCascadedShadows.js +381 -259
  47. package/dist/cjs/rendering/NiceRenderExport.js +424 -337
  48. package/dist/cjs/rendering/NiceSSAO.js +454 -337
  49. package/dist/cjs/rendering/NiceSSR.js +387 -261
  50. package/dist/cjs/rendering/NiceWebGPURenderer.js +359 -230
  51. package/dist/cjs/uv/NiceUVEditor.js +787 -550
  52. package/dist/cjs/uv/UVEditor.module.css.js +53 -5
  53. package/dist/cjs/uv/uvEditorTypes.js +59 -76
  54. package/dist/cjs/uv/uvEditorUtils.js +501 -575
  55. package/dist/esm/collaborative/collaborativeScene.js +163 -205
  56. package/dist/esm/core/editorAsk.js +53 -40
  57. package/dist/esm/core/i18n.js +15 -13
  58. package/dist/esm/core/threeCompat.js +18 -26
  59. package/dist/esm/dance/DanceBridge.js +151 -176
  60. package/dist/esm/dance/DanceScoreEngine.js +211 -220
  61. package/dist/esm/dance/PoseDetector.js +304 -274
  62. package/dist/esm/index.js +258 -36
  63. package/dist/esm/material/MaterialEditor.module.css.js +242 -3
  64. package/dist/esm/material/NiceMaterialEditor.js +1215 -756
  65. package/dist/esm/material/materialEditorTypes.js +45 -48
  66. package/dist/esm/material/materialEditorUtils.js +713 -746
  67. package/dist/esm/material/materialNodeDefinitions.js +1415 -1458
  68. package/dist/esm/model/ModelEditor.js +91 -39
  69. package/dist/esm/model/ModelEditor.module.css.js +257 -3
  70. package/dist/esm/model/ModelEditorLeftPanel.js +126 -45
  71. package/dist/esm/model/ModelEditorMenuBar.js +359 -30
  72. package/dist/esm/model/ModelEditorRightPanel.js +634 -114
  73. package/dist/esm/model/ModelEditorSubComponents.js +265 -94
  74. package/dist/esm/model/ModelEditorTimeline.js +232 -32
  75. package/dist/esm/model/ModelEditorToolbar.js +170 -12
  76. package/dist/esm/model/ModelEditorViewport.js +231 -37
  77. package/dist/esm/model/ModelViewer.js +389 -62
  78. package/dist/esm/model/ModelViewer.module.css.js +77 -3
  79. package/dist/esm/model/NiceArmatureEditor.js +462 -258
  80. package/dist/esm/model/NiceMorphTargetEditor.js +322 -211
  81. package/dist/esm/model/NiceOctree.js +361 -304
  82. package/dist/esm/model/NicePhysicsSimulation.js +517 -282
  83. package/dist/esm/model/NiceProceduralGeometry.js +667 -284
  84. package/dist/esm/model/NiceTerrainEditor.js +584 -369
  85. package/dist/esm/model/NiceWeightPainter.js +373 -245
  86. package/dist/esm/model/NiceXRPreview.js +374 -292
  87. package/dist/esm/model/cadModeUtils.js +95 -88
  88. package/dist/esm/model/editorShortcuts.js +172 -193
  89. package/dist/esm/model/modelEditorTypes.js +90 -100
  90. package/dist/esm/model/modelEditorUtils.js +1056 -1128
  91. package/dist/esm/model/simsModeUtils.js +1021 -1035
  92. package/dist/esm/model/useModelEditor.js +1946 -1920
  93. package/dist/esm/model/useModelViewer.js +619 -647
  94. package/dist/esm/nice2dev-ui-3d.css +1 -1
  95. package/dist/esm/particle/NiceParticleEditor.js +1188 -570
  96. package/dist/esm/particle/ParticleEditor.module.css.js +122 -3
  97. package/dist/esm/particle/particleEditorTypes.js +69 -69
  98. package/dist/esm/particle/particleEditorUtils.js +1027 -1012
  99. package/dist/esm/rendering/NiceCascadedShadows.js +370 -243
  100. package/dist/esm/rendering/NiceRenderExport.js +413 -321
  101. package/dist/esm/rendering/NiceSSAO.js +450 -328
  102. package/dist/esm/rendering/NiceSSR.js +383 -252
  103. package/dist/esm/rendering/NiceWebGPURenderer.js +326 -214
  104. package/dist/esm/uv/NiceUVEditor.js +788 -549
  105. package/dist/esm/uv/UVEditor.module.css.js +53 -3
  106. package/dist/esm/uv/uvEditorTypes.js +68 -75
  107. package/dist/esm/uv/uvEditorUtils.js +515 -557
  108. package/package.json +7 -12
@@ -1,337 +1,710 @@
1
- 'use strict';
2
-
3
- var jsxRuntime = require('react/jsx-runtime');
4
- var ui = require('@nice2dev/ui');
5
- var React = require('react');
6
- var THREE = require('three');
7
- var i18n = require('../core/i18n.js');
8
-
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const ui = require("@nice2dev/ui");
5
+ const React = require("react");
6
+ const THREE = require("three");
7
+ const i18n = require("../core/i18n.js");
9
8
  function _interopNamespaceDefault(e) {
10
- var n = Object.create(null);
11
- if (e) {
12
- Object.keys(e).forEach(function (k) {
13
- if (k !== 'default') {
14
- var d = Object.getOwnPropertyDescriptor(e, k);
15
- Object.defineProperty(n, k, d.get ? d : {
16
- enumerable: true,
17
- get: function () { return e[k]; }
18
- });
19
- }
9
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
10
+ if (e) {
11
+ for (const k in e) {
12
+ if (k !== "default") {
13
+ const d = Object.getOwnPropertyDescriptor(e, k);
14
+ Object.defineProperty(n, k, d.get ? d : {
15
+ enumerable: true,
16
+ get: () => e[k]
20
17
  });
18
+ }
21
19
  }
22
- n.default = e;
23
- return Object.freeze(n);
20
+ }
21
+ n.default = e;
22
+ return Object.freeze(n);
24
23
  }
25
-
26
- var THREE__namespace = /*#__PURE__*/_interopNamespaceDefault(THREE);
27
-
28
- /* ── Generators ── */
24
+ const THREE__namespace = /* @__PURE__ */ _interopNamespaceDefault(THREE);
29
25
  function seededRng(seed) {
30
- let s = seed;
31
- return () => {
32
- s = (s * 16807) % 2147483647;
33
- return (s - 1) / 2147483646;
34
- };
26
+ let s = seed;
27
+ return () => {
28
+ s = s * 16807 % 2147483647;
29
+ return (s - 1) / 2147483646;
30
+ };
35
31
  }
36
32
  function generateTree(params) {
37
- const group = new THREE__namespace.Group();
38
- group.name = 'ProceduralTree';
39
- const rng = seededRng(params.seed);
40
- const trunkMat = new THREE__namespace.MeshStandardMaterial({ color: 0x8b4513 });
41
- const leafMat = new THREE__namespace.MeshStandardMaterial({ color: 0x228b22 });
42
- function addBranch(parent, position, direction, length, radius, depth) {
43
- const geo = new THREE__namespace.CylinderGeometry(radius * params.branchTaper, radius, length, 8);
44
- geo.translate(0, length / 2, 0);
45
- const mesh = new THREE__namespace.Mesh(geo, trunkMat);
46
- mesh.position.copy(position);
47
- // Orient along direction
48
- const up = new THREE__namespace.Vector3(0, 1, 0);
49
- const quat = new THREE__namespace.Quaternion().setFromUnitVectors(up, direction.clone().normalize());
50
- mesh.quaternion.copy(quat);
51
- parent.add(mesh);
52
- if (depth <= 0) {
53
- // Add leaf cluster
54
- const leafGeo = new THREE__namespace.IcosahedronGeometry(length * 0.6, 1);
55
- const leaf = new THREE__namespace.Mesh(leafGeo, leafMat);
56
- const tip = position.clone().addScaledVector(direction.clone().normalize(), length);
57
- leaf.position.copy(tip);
58
- parent.add(leaf);
59
- return;
60
- }
61
- const tip = position.clone().addScaledVector(direction.clone().normalize(), length);
62
- const angleRad = (params.branchAngle * Math.PI) / 180;
63
- for (let i = 0; i < params.branches; i++) {
64
- const phi = (i / params.branches) * Math.PI * 2 + rng() * 0.5;
65
- const theta = angleRad + (rng() - 0.5) * 0.3;
66
- const newDir = new THREE__namespace.Vector3(Math.sin(theta) * Math.cos(phi), Math.cos(theta), Math.sin(theta) * Math.sin(phi));
67
- // Blend with parent direction
68
- newDir.add(direction.clone().normalize().multiplyScalar(0.5)).normalize();
69
- addBranch(parent, tip, newDir, length * (0.6 + rng() * 0.2), radius * params.branchTaper, depth - 1);
70
- }
33
+ const group = new THREE__namespace.Group();
34
+ group.name = "ProceduralTree";
35
+ const rng = seededRng(params.seed);
36
+ const trunkMat = new THREE__namespace.MeshStandardMaterial({ color: 9127187 });
37
+ const leafMat = new THREE__namespace.MeshStandardMaterial({ color: 2263842 });
38
+ function addBranch(parent, position, direction, length, radius, depth) {
39
+ const geo = new THREE__namespace.CylinderGeometry(radius * params.branchTaper, radius, length, 8);
40
+ geo.translate(0, length / 2, 0);
41
+ const mesh = new THREE__namespace.Mesh(geo, trunkMat);
42
+ mesh.position.copy(position);
43
+ const up = new THREE__namespace.Vector3(0, 1, 0);
44
+ const quat = new THREE__namespace.Quaternion().setFromUnitVectors(up, direction.clone().normalize());
45
+ mesh.quaternion.copy(quat);
46
+ parent.add(mesh);
47
+ if (depth <= 0) {
48
+ const leafGeo = new THREE__namespace.IcosahedronGeometry(length * 0.6, 1);
49
+ const leaf = new THREE__namespace.Mesh(leafGeo, leafMat);
50
+ const tip2 = position.clone().addScaledVector(direction.clone().normalize(), length);
51
+ leaf.position.copy(tip2);
52
+ parent.add(leaf);
53
+ return;
71
54
  }
72
- addBranch(group, new THREE__namespace.Vector3(), new THREE__namespace.Vector3(0, 1, 0), params.trunkHeight, params.trunkRadius, params.depth);
73
- return group;
55
+ const tip = position.clone().addScaledVector(direction.clone().normalize(), length);
56
+ const angleRad = params.branchAngle * Math.PI / 180;
57
+ for (let i = 0; i < params.branches; i++) {
58
+ const phi = i / params.branches * Math.PI * 2 + rng() * 0.5;
59
+ const theta = angleRad + (rng() - 0.5) * 0.3;
60
+ const newDir = new THREE__namespace.Vector3(
61
+ Math.sin(theta) * Math.cos(phi),
62
+ Math.cos(theta),
63
+ Math.sin(theta) * Math.sin(phi)
64
+ );
65
+ newDir.add(direction.clone().normalize().multiplyScalar(0.5)).normalize();
66
+ addBranch(
67
+ parent,
68
+ tip,
69
+ newDir,
70
+ length * (0.6 + rng() * 0.2),
71
+ radius * params.branchTaper,
72
+ depth - 1
73
+ );
74
+ }
75
+ }
76
+ addBranch(
77
+ group,
78
+ new THREE__namespace.Vector3(),
79
+ new THREE__namespace.Vector3(0, 1, 0),
80
+ params.trunkHeight,
81
+ params.trunkRadius,
82
+ params.depth
83
+ );
84
+ return group;
74
85
  }
75
86
  function generateRock(params) {
76
- const geo = new THREE__namespace.IcosahedronGeometry(params.radius, params.detail);
77
- const posAttr = geo.attributes.position;
78
- const rng = seededRng(params.seed);
79
- for (let i = 0; i < posAttr.count; i++) {
80
- const vertex = new THREE__namespace.Vector3().fromBufferAttribute(posAttr, i);
81
- const normal = vertex.clone().normalize();
82
- // Noise displacement
83
- const noise = (rng() - 0.5) * 2 * params.noiseAmount;
84
- const freq = params.noiseScale;
85
- const displacement = Math.sin(vertex.x * freq) * Math.cos(vertex.y * freq) * Math.sin(vertex.z * freq);
86
- const totalDisp = (noise + displacement * params.noiseAmount) * params.radius;
87
- vertex.addScaledVector(normal, totalDisp);
88
- posAttr.setXYZ(i, vertex.x, vertex.y, vertex.z);
89
- }
90
- geo.computeVertexNormals();
91
- const mesh = new THREE__namespace.Mesh(geo, new THREE__namespace.MeshStandardMaterial({ color: 0x808080, roughness: 0.9 }));
92
- mesh.name = 'ProceduralRock';
93
- mesh.castShadow = true;
94
- return mesh;
87
+ const geo = new THREE__namespace.IcosahedronGeometry(params.radius, params.detail);
88
+ const posAttr = geo.attributes.position;
89
+ const rng = seededRng(params.seed);
90
+ for (let i = 0; i < posAttr.count; i++) {
91
+ const vertex = new THREE__namespace.Vector3().fromBufferAttribute(posAttr, i);
92
+ const normal = vertex.clone().normalize();
93
+ const noise = (rng() - 0.5) * 2 * params.noiseAmount;
94
+ const freq = params.noiseScale;
95
+ const displacement = Math.sin(vertex.x * freq) * Math.cos(vertex.y * freq) * Math.sin(vertex.z * freq);
96
+ const totalDisp = (noise + displacement * params.noiseAmount) * params.radius;
97
+ vertex.addScaledVector(normal, totalDisp);
98
+ posAttr.setXYZ(i, vertex.x, vertex.y, vertex.z);
99
+ }
100
+ geo.computeVertexNormals();
101
+ const mesh = new THREE__namespace.Mesh(
102
+ geo,
103
+ new THREE__namespace.MeshStandardMaterial({ color: 8421504, roughness: 0.9 })
104
+ );
105
+ mesh.name = "ProceduralRock";
106
+ mesh.castShadow = true;
107
+ return mesh;
95
108
  }
96
109
  function generateBuilding(params) {
97
- const group = new THREE__namespace.Group();
98
- group.name = 'ProceduralBuilding';
99
- const wallMat = new THREE__namespace.MeshStandardMaterial({ color: 0xd4c5a9 });
100
- const windowMat = new THREE__namespace.MeshStandardMaterial({
101
- color: 0x87ceeb,
102
- metalness: 0.3,
103
- roughness: 0.1,
104
- });
105
- const roofMat = new THREE__namespace.MeshStandardMaterial({ color: 0x8b0000 });
106
- const totalHeight = params.floors * params.floorHeight;
107
- // Main body
108
- const bodyGeo = new THREE__namespace.BoxGeometry(params.width, totalHeight, params.depth);
109
- bodyGeo.translate(0, totalHeight / 2, 0);
110
- group.add(new THREE__namespace.Mesh(bodyGeo, wallMat));
111
- // Windows
112
- for (let floor = 0; floor < params.floors; floor++) {
113
- const y = floor * params.floorHeight + params.floorHeight * 0.5;
114
- for (let w = 0; w < params.windowsPerFloor; w++) {
115
- const x = (w - (params.windowsPerFloor - 1) / 2) * (params.width / (params.windowsPerFloor + 1));
116
- // Front face windows
117
- const winGeo = new THREE__namespace.PlaneGeometry(params.windowWidth, params.windowHeight);
118
- const winMesh = new THREE__namespace.Mesh(winGeo, windowMat);
119
- winMesh.position.set(x, y, params.depth / 2 + 0.01);
120
- group.add(winMesh);
121
- // Back face windows
122
- const winBack = winMesh.clone();
123
- winBack.position.z = -params.depth / 2 - 0.01;
124
- winBack.rotation.y = Math.PI;
125
- group.add(winBack);
126
- }
110
+ const group = new THREE__namespace.Group();
111
+ group.name = "ProceduralBuilding";
112
+ const wallMat = new THREE__namespace.MeshStandardMaterial({ color: 13944233 });
113
+ const windowMat = new THREE__namespace.MeshStandardMaterial({
114
+ color: 8900331,
115
+ metalness: 0.3,
116
+ roughness: 0.1
117
+ });
118
+ const roofMat = new THREE__namespace.MeshStandardMaterial({ color: 9109504 });
119
+ const totalHeight = params.floors * params.floorHeight;
120
+ const bodyGeo = new THREE__namespace.BoxGeometry(params.width, totalHeight, params.depth);
121
+ bodyGeo.translate(0, totalHeight / 2, 0);
122
+ group.add(new THREE__namespace.Mesh(bodyGeo, wallMat));
123
+ for (let floor = 0; floor < params.floors; floor++) {
124
+ const y = floor * params.floorHeight + params.floorHeight * 0.5;
125
+ for (let w = 0; w < params.windowsPerFloor; w++) {
126
+ const x = (w - (params.windowsPerFloor - 1) / 2) * (params.width / (params.windowsPerFloor + 1));
127
+ const winGeo = new THREE__namespace.PlaneGeometry(params.windowWidth, params.windowHeight);
128
+ const winMesh = new THREE__namespace.Mesh(winGeo, windowMat);
129
+ winMesh.position.set(x, y, params.depth / 2 + 0.01);
130
+ group.add(winMesh);
131
+ const winBack = winMesh.clone();
132
+ winBack.position.z = -params.depth / 2 - 0.01;
133
+ winBack.rotation.y = Math.PI;
134
+ group.add(winBack);
135
+ }
136
+ }
137
+ switch (params.roofStyle) {
138
+ case "gable": {
139
+ const shape = new THREE__namespace.Shape();
140
+ shape.moveTo(-params.width / 2, 0);
141
+ shape.lineTo(0, params.roofHeight);
142
+ shape.lineTo(params.width / 2, 0);
143
+ shape.lineTo(-params.width / 2, 0);
144
+ const extrudeGeo = new THREE__namespace.ExtrudeGeometry(shape, {
145
+ depth: params.depth,
146
+ bevelEnabled: false
147
+ });
148
+ const roof = new THREE__namespace.Mesh(extrudeGeo, roofMat);
149
+ roof.position.set(0, totalHeight, -params.depth / 2);
150
+ group.add(roof);
151
+ break;
152
+ }
153
+ case "hip": {
154
+ const roofGeo = new THREE__namespace.ConeGeometry(
155
+ Math.max(params.width, params.depth) * 0.7,
156
+ params.roofHeight,
157
+ 4
158
+ );
159
+ roofGeo.rotateY(Math.PI / 4);
160
+ const roof = new THREE__namespace.Mesh(roofGeo, roofMat);
161
+ roof.position.y = totalHeight + params.roofHeight / 2;
162
+ group.add(roof);
163
+ break;
127
164
  }
128
- // Roof
129
- switch (params.roofStyle) {
130
- case 'gable': {
131
- const shape = new THREE__namespace.Shape();
132
- shape.moveTo(-params.width / 2, 0);
133
- shape.lineTo(0, params.roofHeight);
134
- shape.lineTo(params.width / 2, 0);
135
- shape.lineTo(-params.width / 2, 0);
136
- const extrudeGeo = new THREE__namespace.ExtrudeGeometry(shape, {
137
- depth: params.depth,
138
- bevelEnabled: false,
139
- });
140
- const roof = new THREE__namespace.Mesh(extrudeGeo, roofMat);
141
- roof.position.set(0, totalHeight, -params.depth / 2);
142
- group.add(roof);
143
- break;
144
- }
145
- case 'hip': {
146
- const roofGeo = new THREE__namespace.ConeGeometry(Math.max(params.width, params.depth) * 0.7, params.roofHeight, 4);
147
- roofGeo.rotateY(Math.PI / 4);
148
- const roof = new THREE__namespace.Mesh(roofGeo, roofMat);
149
- roof.position.y = totalHeight + params.roofHeight / 2;
150
- group.add(roof);
151
- break;
152
- }
153
- default: {
154
- // flat roof
155
- const flatGeo = new THREE__namespace.BoxGeometry(params.width + 0.4, 0.2, params.depth + 0.4);
156
- const roof = new THREE__namespace.Mesh(flatGeo, roofMat);
157
- roof.position.y = totalHeight + 0.1;
158
- group.add(roof);
159
- }
165
+ default: {
166
+ const flatGeo = new THREE__namespace.BoxGeometry(params.width + 0.4, 0.2, params.depth + 0.4);
167
+ const roof = new THREE__namespace.Mesh(flatGeo, roofMat);
168
+ roof.position.y = totalHeight + 0.1;
169
+ group.add(roof);
160
170
  }
161
- group.traverse((child) => {
162
- if (child instanceof THREE__namespace.Mesh) {
163
- child.castShadow = true;
164
- child.receiveShadow = true;
165
- }
166
- });
167
- return group;
171
+ }
172
+ group.traverse((child) => {
173
+ if (child instanceof THREE__namespace.Mesh) {
174
+ child.castShadow = true;
175
+ child.receiveShadow = true;
176
+ }
177
+ });
178
+ return group;
168
179
  }
169
180
  function generatePipe(params) {
170
- const curve = new THREE__namespace.CatmullRomCurve3(params.points, params.closed);
171
- const geo = new THREE__namespace.TubeGeometry(curve, params.segments, params.radius, params.radialSegments, params.closed);
172
- const mesh = new THREE__namespace.Mesh(geo, new THREE__namespace.MeshStandardMaterial({ color: 0xaaaaaa, metalness: 0.8, roughness: 0.2 }));
173
- mesh.name = 'ProceduralPipe';
174
- mesh.castShadow = true;
175
- return mesh;
181
+ const curve = new THREE__namespace.CatmullRomCurve3(params.points, params.closed);
182
+ const geo = new THREE__namespace.TubeGeometry(
183
+ curve,
184
+ params.segments,
185
+ params.radius,
186
+ params.radialSegments,
187
+ params.closed
188
+ );
189
+ const mesh = new THREE__namespace.Mesh(
190
+ geo,
191
+ new THREE__namespace.MeshStandardMaterial({ color: 11184810, metalness: 0.8, roughness: 0.2 })
192
+ );
193
+ mesh.name = "ProceduralPipe";
194
+ mesh.castShadow = true;
195
+ return mesh;
176
196
  }
177
197
  function generateGear(params) {
178
- const shape = new THREE__namespace.Shape();
179
- const angleStep = (Math.PI * 2) / (params.teeth * 2);
180
- for (let i = 0; i < params.teeth * 2; i++) {
181
- const angle = i * angleStep;
182
- const r = i % 2 === 0 ? params.outerRadius : params.outerRadius - params.toothDepth;
183
- const x = Math.cos(angle) * r;
184
- const y = Math.sin(angle) * r;
185
- if (i === 0) {
186
- shape.moveTo(x, y);
187
- }
188
- else {
189
- shape.lineTo(x, y);
190
- }
198
+ const shape = new THREE__namespace.Shape();
199
+ const angleStep = Math.PI * 2 / (params.teeth * 2);
200
+ for (let i = 0; i < params.teeth * 2; i++) {
201
+ const angle = i * angleStep;
202
+ const r = i % 2 === 0 ? params.outerRadius : params.outerRadius - params.toothDepth;
203
+ const x = Math.cos(angle) * r;
204
+ const y = Math.sin(angle) * r;
205
+ if (i === 0) {
206
+ shape.moveTo(x, y);
207
+ } else {
208
+ shape.lineTo(x, y);
191
209
  }
192
- shape.closePath();
193
- // Inner hole
194
- const hole = new THREE__namespace.Path();
195
- const holeSegments = 32;
196
- for (let i = 0; i <= holeSegments; i++) {
197
- const angle = (i / holeSegments) * Math.PI * 2;
198
- const x = Math.cos(angle) * params.innerRadius;
199
- const y = Math.sin(angle) * params.innerRadius;
200
- if (i === 0) {
201
- hole.moveTo(x, y);
202
- }
203
- else {
204
- hole.lineTo(x, y);
205
- }
210
+ }
211
+ shape.closePath();
212
+ const hole = new THREE__namespace.Path();
213
+ const holeSegments = 32;
214
+ for (let i = 0; i <= holeSegments; i++) {
215
+ const angle = i / holeSegments * Math.PI * 2;
216
+ const x = Math.cos(angle) * params.innerRadius;
217
+ const y = Math.sin(angle) * params.innerRadius;
218
+ if (i === 0) {
219
+ hole.moveTo(x, y);
220
+ } else {
221
+ hole.lineTo(x, y);
206
222
  }
207
- shape.holes.push(hole);
208
- const geo = new THREE__namespace.ExtrudeGeometry(shape, {
209
- depth: params.thickness,
210
- bevelEnabled: false,
211
- });
212
- geo.rotateX(-Math.PI / 2);
213
- geo.translate(0, params.thickness / 2, 0);
214
- const mesh = new THREE__namespace.Mesh(geo, new THREE__namespace.MeshStandardMaterial({ color: 0x888888, metalness: 0.7, roughness: 0.3 }));
215
- mesh.name = 'ProceduralGear';
216
- mesh.castShadow = true;
217
- return mesh;
223
+ }
224
+ shape.holes.push(hole);
225
+ const geo = new THREE__namespace.ExtrudeGeometry(shape, {
226
+ depth: params.thickness,
227
+ bevelEnabled: false
228
+ });
229
+ geo.rotateX(-Math.PI / 2);
230
+ geo.translate(0, params.thickness / 2, 0);
231
+ const mesh = new THREE__namespace.Mesh(
232
+ geo,
233
+ new THREE__namespace.MeshStandardMaterial({ color: 8947848, metalness: 0.7, roughness: 0.3 })
234
+ );
235
+ mesh.name = "ProceduralGear";
236
+ mesh.castShadow = true;
237
+ return mesh;
218
238
  }
219
- /* ── Hook ── */
220
239
  const DEFAULT_TREE = {
221
- trunkRadius: 0.3,
222
- trunkHeight: 4,
223
- branches: 3,
224
- depth: 3,
225
- branchAngle: 30,
226
- branchLength: 3,
227
- branchTaper: 0.7,
228
- seed: 42,
240
+ trunkRadius: 0.3,
241
+ trunkHeight: 4,
242
+ branches: 3,
243
+ depth: 3,
244
+ branchAngle: 30,
245
+ branchLength: 3,
246
+ branchTaper: 0.7,
247
+ seed: 42
229
248
  };
230
249
  const DEFAULT_ROCK = {
231
- radius: 1,
232
- detail: 3,
233
- noiseScale: 3,
234
- noiseAmount: 0.2,
235
- seed: 42,
250
+ radius: 1,
251
+ detail: 3,
252
+ noiseScale: 3,
253
+ noiseAmount: 0.2,
254
+ seed: 42
236
255
  };
237
256
  const DEFAULT_BUILDING = {
238
- width: 8,
239
- depth: 6,
240
- floors: 4,
241
- floorHeight: 3,
242
- windowsPerFloor: 3,
243
- windowWidth: 1.2,
244
- windowHeight: 1.5,
245
- roofStyle: 'gable',
246
- roofHeight: 3,
257
+ width: 8,
258
+ depth: 6,
259
+ floors: 4,
260
+ floorHeight: 3,
261
+ windowsPerFloor: 3,
262
+ windowWidth: 1.2,
263
+ windowHeight: 1.5,
264
+ roofStyle: "gable",
265
+ roofHeight: 3
247
266
  };
248
267
  const DEFAULT_PIPE = {
249
- radius: 0.2,
250
- segments: 64,
251
- radialSegments: 8,
252
- closed: false,
253
- points: [
254
- new THREE__namespace.Vector3(0, 0, 0),
255
- new THREE__namespace.Vector3(2, 2, 0),
256
- new THREE__namespace.Vector3(4, 0, 2),
257
- new THREE__namespace.Vector3(6, 2, 2),
258
- ],
268
+ radius: 0.2,
269
+ segments: 64,
270
+ radialSegments: 8,
271
+ closed: false,
272
+ points: [
273
+ new THREE__namespace.Vector3(0, 0, 0),
274
+ new THREE__namespace.Vector3(2, 2, 0),
275
+ new THREE__namespace.Vector3(4, 0, 2),
276
+ new THREE__namespace.Vector3(6, 2, 2)
277
+ ]
259
278
  };
260
279
  const DEFAULT_GEAR = {
261
- innerRadius: 0.5,
262
- outerRadius: 2,
263
- teeth: 12,
264
- toothDepth: 0.3,
265
- thickness: 0.4,
280
+ innerRadius: 0.5,
281
+ outerRadius: 2,
282
+ teeth: 12,
283
+ toothDepth: 0.3,
284
+ thickness: 0.4
266
285
  };
267
286
  function useProceduralGeometry(scene, onGenerated) {
268
- const [type, setType] = React.useState('tree');
269
- const [treeParams, setTreeParams] = React.useState(DEFAULT_TREE);
270
- const [rockParams, setRockParams] = React.useState(DEFAULT_ROCK);
271
- const [buildingParams, setBuildingParams] = React.useState(DEFAULT_BUILDING);
272
- const [pipeParams, setPipeParams] = React.useState(DEFAULT_PIPE);
273
- const [gearParams, setGearParams] = React.useState(DEFAULT_GEAR);
274
- const generate = React.useCallback(() => {
275
- if (!scene) {
276
- return;
277
- }
278
- let result;
279
- switch (type) {
280
- case 'tree':
281
- result = generateTree(treeParams);
282
- break;
283
- case 'rock':
284
- result = generateRock(rockParams);
285
- break;
286
- case 'building':
287
- result = generateBuilding(buildingParams);
288
- break;
289
- case 'pipe':
290
- result = generatePipe(pipeParams);
291
- break;
292
- case 'gear':
293
- result = generateGear(gearParams);
294
- break;
295
- }
296
- scene.add(result);
297
- onGenerated === null || onGenerated === void 0 ? void 0 : onGenerated(result);
298
- }, [scene, type, treeParams, rockParams, buildingParams, pipeParams, gearParams, onGenerated]);
299
- return {
300
- type,
301
- setType,
302
- treeParams,
303
- setTreeParams,
304
- rockParams,
305
- setRockParams,
306
- buildingParams,
307
- setBuildingParams,
308
- pipeParams,
309
- setPipeParams,
310
- gearParams,
311
- setGearParams,
312
- generate,
313
- };
287
+ const [type, setType] = React.useState("tree");
288
+ const [treeParams, setTreeParams] = React.useState(DEFAULT_TREE);
289
+ const [rockParams, setRockParams] = React.useState(DEFAULT_ROCK);
290
+ const [buildingParams, setBuildingParams] = React.useState(DEFAULT_BUILDING);
291
+ const [pipeParams, setPipeParams] = React.useState(DEFAULT_PIPE);
292
+ const [gearParams, setGearParams] = React.useState(DEFAULT_GEAR);
293
+ const generate = React.useCallback(() => {
294
+ if (!scene) {
295
+ return;
296
+ }
297
+ let result;
298
+ switch (type) {
299
+ case "tree":
300
+ result = generateTree(treeParams);
301
+ break;
302
+ case "rock":
303
+ result = generateRock(rockParams);
304
+ break;
305
+ case "building":
306
+ result = generateBuilding(buildingParams);
307
+ break;
308
+ case "pipe":
309
+ result = generatePipe(pipeParams);
310
+ break;
311
+ case "gear":
312
+ result = generateGear(gearParams);
313
+ break;
314
+ }
315
+ scene.add(result);
316
+ onGenerated?.(result);
317
+ }, [scene, type, treeParams, rockParams, buildingParams, pipeParams, gearParams, onGenerated]);
318
+ return {
319
+ type,
320
+ setType,
321
+ treeParams,
322
+ setTreeParams,
323
+ rockParams,
324
+ setRockParams,
325
+ buildingParams,
326
+ setBuildingParams,
327
+ pipeParams,
328
+ setPipeParams,
329
+ gearParams,
330
+ setGearParams,
331
+ generate
332
+ };
314
333
  }
315
- /* ── Component ── */
316
- const NiceProceduralGeometry = ({ scene, onGenerated, className = '', }) => {
317
- const { t } = i18n.useNiceTranslation();
318
- const { type, setType, treeParams, setTreeParams, rockParams, setRockParams, buildingParams, setBuildingParams, gearParams, setGearParams, generate, } = useProceduralGeometry(scene, onGenerated);
319
- return (jsxRuntime.jsxs("div", { className: `nice-procedural-geometry ${className}`, style: { display: 'grid', gap: 8, fontSize: 13 }, children: [jsxRuntime.jsx("strong", { children: t('proceduralGeometry.proceduralGeometry', 'Procedural Geometry') }), jsxRuntime.jsxs("select", { value: type, onChange: (e) => setType(e.target.value), style: { width: '100%', padding: '4px 8px' }, children: [jsxRuntime.jsx("option", { value: "tree", children: t('proceduralGeometry.tree', 'Tree') }), jsxRuntime.jsx("option", { value: "rock", children: t('proceduralGeometry.rock', 'Rock') }), jsxRuntime.jsx("option", { value: "building", children: t('proceduralGeometry.building', 'Building') }), jsxRuntime.jsx("option", { value: "pipe", children: t('proceduralGeometry.pipe', 'Pipe') }), jsxRuntime.jsx("option", { value: "gear", children: t('proceduralGeometry.gear', 'Gear') })] }), type === 'tree' && (jsxRuntime.jsxs("div", { style: { display: 'grid', gap: 4 }, children: [jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.height', 'Height: {trunkHeight}').replace('{trunkHeight}', String(treeParams.trunkHeight.toFixed(1))), jsxRuntime.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%' } })] }), jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.branches', 'Branches: {branches}').replace('{branches}', String(treeParams.branches)), jsxRuntime.jsx("input", { type: "range", min: 1, max: 6, value: treeParams.branches, onChange: (e) => setTreeParams({ ...treeParams, branches: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.depth', 'Depth: {depth}').replace('{depth}', String(treeParams.depth)), jsxRuntime.jsx("input", { type: "range", min: 1, max: 5, value: treeParams.depth, onChange: (e) => setTreeParams({ ...treeParams, depth: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.angle', 'Angle: {branchAngle}°').replace('{branchAngle}', String(treeParams.branchAngle)), jsxRuntime.jsx("input", { type: "range", min: 10, max: 80, value: treeParams.branchAngle, onChange: (e) => setTreeParams({ ...treeParams, branchAngle: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.seed', 'Seed: {seed}').replace('{seed}', String(treeParams.seed)), jsxRuntime.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' && (jsxRuntime.jsxs("div", { style: { display: 'grid', gap: 4 }, children: [jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.radius', 'Radius: {radius}').replace('{radius}', String(rockParams.radius.toFixed(1))), jsxRuntime.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%' } })] }), jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.detail', 'Detail: {detail}').replace('{detail}', String(rockParams.detail)), jsxRuntime.jsx("input", { type: "range", min: 1, max: 5, value: rockParams.detail, onChange: (e) => setRockParams({ ...rockParams, detail: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.noise', 'Noise: {noiseAmount}').replace('{noiseAmount}', String(rockParams.noiseAmount.toFixed(2))), jsxRuntime.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%' } })] }), jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.seed', 'Seed: {seed}').replace('{seed}', String(rockParams.seed)), jsxRuntime.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' && (jsxRuntime.jsxs("div", { style: { display: 'grid', gap: 4 }, children: [jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.width', 'Width: {width}').replace('{width}', String(buildingParams.width)), jsxRuntime.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%' } })] }), jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.floors', 'Floors: {floors}').replace('{floors}', String(buildingParams.floors)), jsxRuntime.jsx("input", { type: "range", min: 1, max: 20, value: buildingParams.floors, onChange: (e) => setBuildingParams({ ...buildingParams, floors: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.windowsFloor', 'Windows/Floor: {windowsPerFloor}').replace('{windowsPerFloor}', String(buildingParams.windowsPerFloor)), jsxRuntime.jsx("input", { type: "range", min: 1, max: 10, value: buildingParams.windowsPerFloor, onChange: (e) => setBuildingParams({
320
- ...buildingParams,
321
- windowsPerFloor: parseInt(e.target.value, 10),
322
- }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.roof', 'Roof:'), jsxRuntime.jsxs("select", { value: buildingParams.roofStyle, onChange: (e) => setBuildingParams({
323
- ...buildingParams,
324
- roofStyle: e.target.value,
325
- }), style: { marginLeft: 8 }, children: [jsxRuntime.jsx("option", { value: "flat", children: t('proceduralGeometry.flat', 'Flat') }), jsxRuntime.jsx("option", { value: "gable", children: t('proceduralGeometry.gable', 'Gable') }), jsxRuntime.jsx("option", { value: "hip", children: t('proceduralGeometry.hip', 'Hip') })] })] })] })), type === 'gear' && (jsxRuntime.jsxs("div", { style: { display: 'grid', gap: 4 }, children: [jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.outerRadius', 'Outer Radius: {outerRadius}').replace('{outerRadius}', String(gearParams.outerRadius.toFixed(1))), jsxRuntime.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%' } })] }), jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.teeth', 'Teeth: {teeth}').replace('{teeth}', String(gearParams.teeth)), jsxRuntime.jsx("input", { type: "range", min: 4, max: 30, value: gearParams.teeth, onChange: (e) => setGearParams({ ...gearParams, teeth: parseInt(e.target.value, 10) }), style: { width: '100%' } })] }), jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.toothDepth', 'Tooth Depth: {toothDepth}').replace('{toothDepth}', String(gearParams.toothDepth.toFixed(2))), jsxRuntime.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%' } })] }), jsxRuntime.jsxs("label", { children: [t('proceduralGeometry.thickness', 'Thickness: {thickness}').replace('{thickness}', String(gearParams.thickness.toFixed(2))), jsxRuntime.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%' } })] })] })), jsxRuntime.jsxs("button", { type: "button", onClick: generate, style: {
326
- background: 'var(--nice-color-accent, #6366f1)',
327
- color: 'var(--nice-text-on-primary, #fff)',
328
- border: 'none',
329
- borderRadius: 4,
330
- padding: '6px 12px',
331
- cursor: 'pointer',
332
- }, children: [jsxRuntime.jsx(ui.NiceIcon, { name: "wand", size: 14 }), " ", t('proceduralGeometry.generate', 'Generate')] })] }));
334
+ const NiceProceduralGeometry = ({
335
+ scene,
336
+ onGenerated,
337
+ className = ""
338
+ }) => {
339
+ const { t } = i18n.useNiceTranslation();
340
+ const {
341
+ type,
342
+ setType,
343
+ treeParams,
344
+ setTreeParams,
345
+ rockParams,
346
+ setRockParams,
347
+ buildingParams,
348
+ setBuildingParams,
349
+ gearParams,
350
+ setGearParams,
351
+ generate
352
+ } = useProceduralGeometry(scene, onGenerated);
353
+ return /* @__PURE__ */ jsxRuntime.jsxs(
354
+ "div",
355
+ {
356
+ className: `nice-procedural-geometry ${className}`,
357
+ style: { display: "grid", gap: 8, fontSize: 13 },
358
+ children: [
359
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: t("proceduralGeometry.proceduralGeometry", "Procedural Geometry") }),
360
+ /* @__PURE__ */ jsxRuntime.jsxs(
361
+ "select",
362
+ {
363
+ value: type,
364
+ onChange: (e) => setType(e.target.value),
365
+ style: { width: "100%", padding: "4px 8px" },
366
+ children: [
367
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "tree", children: t("proceduralGeometry.tree", "Tree") }),
368
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "rock", children: t("proceduralGeometry.rock", "Rock") }),
369
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "building", children: t("proceduralGeometry.building", "Building") }),
370
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "pipe", children: t("proceduralGeometry.pipe", "Pipe") }),
371
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "gear", children: t("proceduralGeometry.gear", "Gear") })
372
+ ]
373
+ }
374
+ ),
375
+ type === "tree" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "grid", gap: 4 }, children: [
376
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
377
+ t("proceduralGeometry.height", "Height: {trunkHeight}").replace(
378
+ "{trunkHeight}",
379
+ String(treeParams.trunkHeight.toFixed(1))
380
+ ),
381
+ /* @__PURE__ */ jsxRuntime.jsx(
382
+ "input",
383
+ {
384
+ type: "range",
385
+ min: 1,
386
+ max: 15,
387
+ step: 0.5,
388
+ value: treeParams.trunkHeight,
389
+ onChange: (e) => setTreeParams({ ...treeParams, trunkHeight: parseFloat(e.target.value) }),
390
+ style: { width: "100%" }
391
+ }
392
+ )
393
+ ] }),
394
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
395
+ t("proceduralGeometry.branches", "Branches: {branches}").replace(
396
+ "{branches}",
397
+ String(treeParams.branches)
398
+ ),
399
+ /* @__PURE__ */ jsxRuntime.jsx(
400
+ "input",
401
+ {
402
+ type: "range",
403
+ min: 1,
404
+ max: 6,
405
+ value: treeParams.branches,
406
+ onChange: (e) => setTreeParams({ ...treeParams, branches: parseInt(e.target.value, 10) }),
407
+ style: { width: "100%" }
408
+ }
409
+ )
410
+ ] }),
411
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
412
+ t("proceduralGeometry.depth", "Depth: {depth}").replace(
413
+ "{depth}",
414
+ String(treeParams.depth)
415
+ ),
416
+ /* @__PURE__ */ jsxRuntime.jsx(
417
+ "input",
418
+ {
419
+ type: "range",
420
+ min: 1,
421
+ max: 5,
422
+ value: treeParams.depth,
423
+ onChange: (e) => setTreeParams({ ...treeParams, depth: parseInt(e.target.value, 10) }),
424
+ style: { width: "100%" }
425
+ }
426
+ )
427
+ ] }),
428
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
429
+ t("proceduralGeometry.angle", "Angle: {branchAngle}°").replace(
430
+ "{branchAngle}",
431
+ String(treeParams.branchAngle)
432
+ ),
433
+ /* @__PURE__ */ jsxRuntime.jsx(
434
+ "input",
435
+ {
436
+ type: "range",
437
+ min: 10,
438
+ max: 80,
439
+ value: treeParams.branchAngle,
440
+ onChange: (e) => setTreeParams({ ...treeParams, branchAngle: parseInt(e.target.value, 10) }),
441
+ style: { width: "100%" }
442
+ }
443
+ )
444
+ ] }),
445
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
446
+ t("proceduralGeometry.seed", "Seed: {seed}").replace(
447
+ "{seed}",
448
+ String(treeParams.seed)
449
+ ),
450
+ /* @__PURE__ */ jsxRuntime.jsx(
451
+ "input",
452
+ {
453
+ type: "range",
454
+ min: 1,
455
+ max: 999,
456
+ value: treeParams.seed,
457
+ onChange: (e) => setTreeParams({ ...treeParams, seed: parseInt(e.target.value, 10) }),
458
+ style: { width: "100%" }
459
+ }
460
+ )
461
+ ] })
462
+ ] }),
463
+ type === "rock" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "grid", gap: 4 }, children: [
464
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
465
+ t("proceduralGeometry.radius", "Radius: {radius}").replace(
466
+ "{radius}",
467
+ String(rockParams.radius.toFixed(1))
468
+ ),
469
+ /* @__PURE__ */ jsxRuntime.jsx(
470
+ "input",
471
+ {
472
+ type: "range",
473
+ min: 0.2,
474
+ max: 5,
475
+ step: 0.1,
476
+ value: rockParams.radius,
477
+ onChange: (e) => setRockParams({ ...rockParams, radius: parseFloat(e.target.value) }),
478
+ style: { width: "100%" }
479
+ }
480
+ )
481
+ ] }),
482
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
483
+ t("proceduralGeometry.detail", "Detail: {detail}").replace(
484
+ "{detail}",
485
+ String(rockParams.detail)
486
+ ),
487
+ /* @__PURE__ */ jsxRuntime.jsx(
488
+ "input",
489
+ {
490
+ type: "range",
491
+ min: 1,
492
+ max: 5,
493
+ value: rockParams.detail,
494
+ onChange: (e) => setRockParams({ ...rockParams, detail: parseInt(e.target.value, 10) }),
495
+ style: { width: "100%" }
496
+ }
497
+ )
498
+ ] }),
499
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
500
+ t("proceduralGeometry.noise", "Noise: {noiseAmount}").replace(
501
+ "{noiseAmount}",
502
+ String(rockParams.noiseAmount.toFixed(2))
503
+ ),
504
+ /* @__PURE__ */ jsxRuntime.jsx(
505
+ "input",
506
+ {
507
+ type: "range",
508
+ min: 0,
509
+ max: 0.5,
510
+ step: 0.01,
511
+ value: rockParams.noiseAmount,
512
+ onChange: (e) => setRockParams({ ...rockParams, noiseAmount: parseFloat(e.target.value) }),
513
+ style: { width: "100%" }
514
+ }
515
+ )
516
+ ] }),
517
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
518
+ t("proceduralGeometry.seed", "Seed: {seed}").replace(
519
+ "{seed}",
520
+ String(rockParams.seed)
521
+ ),
522
+ /* @__PURE__ */ jsxRuntime.jsx(
523
+ "input",
524
+ {
525
+ type: "range",
526
+ min: 1,
527
+ max: 999,
528
+ value: rockParams.seed,
529
+ onChange: (e) => setRockParams({ ...rockParams, seed: parseInt(e.target.value, 10) }),
530
+ style: { width: "100%" }
531
+ }
532
+ )
533
+ ] })
534
+ ] }),
535
+ type === "building" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "grid", gap: 4 }, children: [
536
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
537
+ t("proceduralGeometry.width", "Width: {width}").replace(
538
+ "{width}",
539
+ String(buildingParams.width)
540
+ ),
541
+ /* @__PURE__ */ jsxRuntime.jsx(
542
+ "input",
543
+ {
544
+ type: "range",
545
+ min: 4,
546
+ max: 20,
547
+ step: 1,
548
+ value: buildingParams.width,
549
+ onChange: (e) => setBuildingParams({ ...buildingParams, width: parseInt(e.target.value, 10) }),
550
+ style: { width: "100%" }
551
+ }
552
+ )
553
+ ] }),
554
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
555
+ t("proceduralGeometry.floors", "Floors: {floors}").replace(
556
+ "{floors}",
557
+ String(buildingParams.floors)
558
+ ),
559
+ /* @__PURE__ */ jsxRuntime.jsx(
560
+ "input",
561
+ {
562
+ type: "range",
563
+ min: 1,
564
+ max: 20,
565
+ value: buildingParams.floors,
566
+ onChange: (e) => setBuildingParams({ ...buildingParams, floors: parseInt(e.target.value, 10) }),
567
+ style: { width: "100%" }
568
+ }
569
+ )
570
+ ] }),
571
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
572
+ t("proceduralGeometry.windowsFloor", "Windows/Floor: {windowsPerFloor}").replace(
573
+ "{windowsPerFloor}",
574
+ String(buildingParams.windowsPerFloor)
575
+ ),
576
+ /* @__PURE__ */ jsxRuntime.jsx(
577
+ "input",
578
+ {
579
+ type: "range",
580
+ min: 1,
581
+ max: 10,
582
+ value: buildingParams.windowsPerFloor,
583
+ onChange: (e) => setBuildingParams({
584
+ ...buildingParams,
585
+ windowsPerFloor: parseInt(e.target.value, 10)
586
+ }),
587
+ style: { width: "100%" }
588
+ }
589
+ )
590
+ ] }),
591
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
592
+ t("proceduralGeometry.roof", "Roof:"),
593
+ /* @__PURE__ */ jsxRuntime.jsxs(
594
+ "select",
595
+ {
596
+ value: buildingParams.roofStyle,
597
+ onChange: (e) => setBuildingParams({
598
+ ...buildingParams,
599
+ roofStyle: e.target.value
600
+ }),
601
+ style: { marginLeft: 8 },
602
+ children: [
603
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "flat", children: t("proceduralGeometry.flat", "Flat") }),
604
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "gable", children: t("proceduralGeometry.gable", "Gable") }),
605
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "hip", children: t("proceduralGeometry.hip", "Hip") })
606
+ ]
607
+ }
608
+ )
609
+ ] })
610
+ ] }),
611
+ type === "gear" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "grid", gap: 4 }, children: [
612
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
613
+ t("proceduralGeometry.outerRadius", "Outer Radius: {outerRadius}").replace(
614
+ "{outerRadius}",
615
+ String(gearParams.outerRadius.toFixed(1))
616
+ ),
617
+ /* @__PURE__ */ jsxRuntime.jsx(
618
+ "input",
619
+ {
620
+ type: "range",
621
+ min: 0.5,
622
+ max: 5,
623
+ step: 0.1,
624
+ value: gearParams.outerRadius,
625
+ onChange: (e) => setGearParams({ ...gearParams, outerRadius: parseFloat(e.target.value) }),
626
+ style: { width: "100%" }
627
+ }
628
+ )
629
+ ] }),
630
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
631
+ t("proceduralGeometry.teeth", "Teeth: {teeth}").replace(
632
+ "{teeth}",
633
+ String(gearParams.teeth)
634
+ ),
635
+ /* @__PURE__ */ jsxRuntime.jsx(
636
+ "input",
637
+ {
638
+ type: "range",
639
+ min: 4,
640
+ max: 30,
641
+ value: gearParams.teeth,
642
+ onChange: (e) => setGearParams({ ...gearParams, teeth: parseInt(e.target.value, 10) }),
643
+ style: { width: "100%" }
644
+ }
645
+ )
646
+ ] }),
647
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
648
+ t("proceduralGeometry.toothDepth", "Tooth Depth: {toothDepth}").replace(
649
+ "{toothDepth}",
650
+ String(gearParams.toothDepth.toFixed(2))
651
+ ),
652
+ /* @__PURE__ */ jsxRuntime.jsx(
653
+ "input",
654
+ {
655
+ type: "range",
656
+ min: 0.05,
657
+ max: 1,
658
+ step: 0.05,
659
+ value: gearParams.toothDepth,
660
+ onChange: (e) => setGearParams({ ...gearParams, toothDepth: parseFloat(e.target.value) }),
661
+ style: { width: "100%" }
662
+ }
663
+ )
664
+ ] }),
665
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
666
+ t("proceduralGeometry.thickness", "Thickness: {thickness}").replace(
667
+ "{thickness}",
668
+ String(gearParams.thickness.toFixed(2))
669
+ ),
670
+ /* @__PURE__ */ jsxRuntime.jsx(
671
+ "input",
672
+ {
673
+ type: "range",
674
+ min: 0.1,
675
+ max: 2,
676
+ step: 0.1,
677
+ value: gearParams.thickness,
678
+ onChange: (e) => setGearParams({ ...gearParams, thickness: parseFloat(e.target.value) }),
679
+ style: { width: "100%" }
680
+ }
681
+ )
682
+ ] })
683
+ ] }),
684
+ /* @__PURE__ */ jsxRuntime.jsxs(
685
+ "button",
686
+ {
687
+ type: "button",
688
+ onClick: generate,
689
+ style: {
690
+ background: "var(--nice-color-accent, #6366f1)",
691
+ color: "var(--nice-text-on-primary, #fff)",
692
+ border: "none",
693
+ borderRadius: 4,
694
+ padding: "6px 12px",
695
+ cursor: "pointer"
696
+ },
697
+ children: [
698
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "wand", size: 14 }),
699
+ " ",
700
+ t("proceduralGeometry.generate", "Generate")
701
+ ]
702
+ }
703
+ )
704
+ ]
705
+ }
706
+ );
333
707
  };
334
-
335
708
  exports.NiceProceduralGeometry = NiceProceduralGeometry;
336
709
  exports.generateBuilding = generateBuilding;
337
710
  exports.generateGear = generateGear;