@nice2dev/ui-3d 1.3.15 → 1.3.16

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 +9 -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,137 +1,653 @@
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
- var ModelEditor_module = require('./ModelEditor.module.css.js');
9
- var ModelEditorSubComponents = require('./ModelEditorSubComponents.js');
10
- var modelEditorTypes = require('./modelEditorTypes.js');
11
-
1
+ "use strict";
2
+ Object.defineProperties(exports, { __esModule: { value: true }, [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");
8
+ const ModelEditor_module = require("./ModelEditor.module.css.js");
9
+ const ModelEditorSubComponents = require("./ModelEditorSubComponents.js");
10
+ const modelEditorTypes = require("./modelEditorTypes.js");
12
11
  function _interopNamespaceDefault(e) {
13
- var n = Object.create(null);
14
- if (e) {
15
- Object.keys(e).forEach(function (k) {
16
- if (k !== 'default') {
17
- var d = Object.getOwnPropertyDescriptor(e, k);
18
- Object.defineProperty(n, k, d.get ? d : {
19
- enumerable: true,
20
- get: function () { return e[k]; }
21
- });
22
- }
12
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
13
+ if (e) {
14
+ for (const k in e) {
15
+ if (k !== "default") {
16
+ const d = Object.getOwnPropertyDescriptor(e, k);
17
+ Object.defineProperty(n, k, d.get ? d : {
18
+ enumerable: true,
19
+ get: () => e[k]
23
20
  });
21
+ }
24
22
  }
25
- n.default = e;
26
- return Object.freeze(n);
23
+ }
24
+ n.default = e;
25
+ return Object.freeze(n);
27
26
  }
28
-
29
- var THREE__namespace = /*#__PURE__*/_interopNamespaceDefault(THREE);
30
-
27
+ const THREE__namespace = /* @__PURE__ */ _interopNamespaceDefault(THREE);
31
28
  const ModelEditorRightPanel = /* @__PURE__ */ Object.assign(
32
- /* @__PURE__ */ React.memo(({ api }) => {
29
+ /* @__PURE__ */ React.memo(({ api }) => {
33
30
  const { t } = i18n.useNiceTranslation();
34
- const { propTab, setPropTab, selectedNode, selectedMaterials, selMaterialIdx, setSelMaterialIdx, setMatRefresh, rebuildTree, aiBusy, aiStatus, rootObjectRef, videoInputRef, bgColor, setBgColor, fogEnabled, setFogEnabled, fogColor, setFogColor, fogNear, setFogNear, fogFar, setFogFar, showLightHelpers, setShowLightHelpers, showGrid, setShowGrid, showAxes, setShowAxes, showSkeleton, setShowSkeleton, snapEnabled, setSnapEnabled, snapGrid, setSnapGrid, setStatusText, } = api;
35
- return (jsxRuntime.jsxs("div", { className: ModelEditor_module.rightPanel, children: [jsxRuntime.jsx("div", { className: ModelEditor_module.propTabs, children: ['object', 'material', 'world', 'modifiers', 'physics'].map((t) => (jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.propTabBtn, variant: propTab === t ? 'primary' : 'ghost', size: "sm", onClick: () => setPropTab(t), title: t.charAt(0).toUpperCase() + t.slice(1), "aria-label": t.charAt(0).toUpperCase() + t.slice(1), children: jsxRuntime.jsx(ui.NiceIcon, { name: t === 'object'
36
- ? 'settings'
37
- : t === 'material'
38
- ? 'palette'
39
- : t === 'world'
40
- ? 'globe'
41
- : t === 'modifiers'
42
- ? 'settings'
43
- : 'zap', size: 16 }) }, t))) }), propTab === 'object' && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.panelSection, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.panelTitle, children: [jsxRuntime.jsx(ui.NiceIcon, { name: "settings", size: 14 }), ' ', t('modelEditorRightPanel.transform', 'Transform')] }), jsxRuntime.jsx("div", { className: ModelEditor_module.panelContent, children: selectedNode ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.name', 'Name') }), jsxRuntime.jsx(ui.NiceTextInput, { className: ModelEditor_module.propInput, value: selectedNode.name, onChange: (val) => {
44
- selectedNode.object.name = val;
45
- rebuildTree();
46
- } })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.type', 'Type') }), jsxRuntime.jsx("span", { style: { fontSize: 10, color: 'var(--nice-text-secondary, #888)' }, children: selectedNode.type })] }), jsxRuntime.jsx(ModelEditorSubComponents.Vec3Row, { label: t('modelEditorRightPanel.position', 'Position'), value: selectedNode.object.position, onChange: () => setMatRefresh((n) => n + 1) }), jsxRuntime.jsx(ModelEditorSubComponents.Vec3RowDeg, { label: t('modelEditorRightPanel.rotation', 'Rotation'), value: selectedNode.object.rotation, onChange: () => setMatRefresh((n) => n + 1) }), jsxRuntime.jsx(ModelEditorSubComponents.Vec3Row, { label: t('modelEditorRightPanel.scale', 'Scale'), value: selectedNode.object.scale, onChange: () => setMatRefresh((n) => n + 1) })] })) : (jsxRuntime.jsx("div", { style: { color: 'var(--nice-text-secondary, #666)', fontSize: 10 }, children: t('modelEditorRightPanel.selectAnObject', 'Select an object') })) })] }), selectedNode && selectedNode.object instanceof THREE__namespace.Light && (jsxRuntime.jsxs("div", { className: ModelEditor_module.panelSection, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.panelTitle, children: [jsxRuntime.jsx(ui.NiceIcon, { name: "lightbulb", size: 14 }), ' ', t('modelEditorRightPanel.light', 'Light')] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.panelContent, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.color', 'Color') }), jsxRuntime.jsx(ui.NiceColorPicker, { value: `#${selectedNode.object.color.getHexString()}`, onChange: (c) => {
47
- selectedNode.object.color.set(c);
48
- setMatRefresh((n) => n + 1);
49
- } })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.intensity', 'Intensity') }), jsxRuntime.jsx(ui.NiceSlider, { min: 0, max: 10, step: 0.1, value: selectedNode.object.intensity, onChange: (val) => {
50
- selectedNode.object.intensity = val;
51
- setMatRefresh((n) => n + 1);
52
- }, style: { flex: 1 } }), jsxRuntime.jsx("span", { style: {
53
- fontSize: 9,
54
- color: 'var(--nice-text-secondary, #888)',
55
- width: 28,
56
- textAlign: 'right',
57
- }, children: selectedNode.object.intensity.toFixed(1) })] }), 'castShadow' in selectedNode.object && (jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.shadow', 'Shadow') }), jsxRuntime.jsx(ui.NiceCheckbox, { checked: selectedNode.object.castShadow, onChange: (checked) => {
58
- selectedNode.object.castShadow = checked;
59
- setMatRefresh((n) => n + 1);
60
- } })] })), selectedNode.object instanceof THREE__namespace.SpotLight && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.angle', 'Angle') }), jsxRuntime.jsx(ui.NiceSlider, { min: 0, max: 90, step: 1, value: selectedNode.object.angle * modelEditorTypes.DEG, onChange: (val) => {
61
- selectedNode.object.angle = val / modelEditorTypes.DEG;
62
- setMatRefresh((n) => n + 1);
63
- }, style: { flex: 1 } }), jsxRuntime.jsxs("span", { style: {
64
- fontSize: 9,
65
- color: 'var(--nice-text-secondary, #888)',
66
- width: 28,
67
- textAlign: 'right',
68
- }, children: [(selectedNode.object.angle * modelEditorTypes.DEG).toFixed(0), "\u00B0"] })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.penumbra', 'Penumbra') }), jsxRuntime.jsx(ui.NiceSlider, { min: 0, max: 1, step: 0.01, value: selectedNode.object.penumbra, onChange: (val) => {
69
- selectedNode.object.penumbra = val;
70
- setMatRefresh((n) => n + 1);
71
- }, style: { flex: 1 } })] })] }))] })] })), selectedNode && selectedNode.object instanceof THREE__namespace.PerspectiveCamera && (jsxRuntime.jsxs("div", { className: ModelEditor_module.panelSection, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.panelTitle, children: [jsxRuntime.jsx(ui.NiceIcon, { name: "camera", size: 14 }), " ", t('modelEditorRightPanel.camera', 'Camera')] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.panelContent, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.fov', 'FOV') }), jsxRuntime.jsx(ui.NiceSlider, { min: 10, max: 120, step: 1, value: selectedNode.object.fov, onChange: (val) => {
72
- const cam = selectedNode.object;
73
- cam.fov = val;
74
- cam.updateProjectionMatrix();
75
- setMatRefresh((n) => n + 1);
76
- }, style: { flex: 1 } }), jsxRuntime.jsxs("span", { style: {
77
- fontSize: 9,
78
- color: 'var(--nice-text-secondary, #888)',
79
- width: 28,
80
- textAlign: 'right',
81
- }, children: [selectedNode.object.fov.toFixed(0), "\u00B0"] })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.near', 'Near') }), jsxRuntime.jsx(ui.NiceNumberInput, { className: ModelEditor_module.propInput, step: 0.01, value: selectedNode.object.near, onChange: (val) => {
82
- const cam = selectedNode.object;
83
- cam.near = val !== null && val !== void 0 ? val : 0.1;
84
- cam.updateProjectionMatrix();
85
- setMatRefresh((n) => n + 1);
86
- }, style: { width: 60 } })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.far', 'Far') }), jsxRuntime.jsx(ui.NiceNumberInput, { className: ModelEditor_module.propInput, step: 1, value: selectedNode.object.far, onChange: (val) => {
87
- const cam = selectedNode.object;
88
- cam.far = val !== null && val !== void 0 ? val : 1000;
89
- cam.updateProjectionMatrix();
90
- setMatRefresh((n) => n + 1);
91
- }, style: { width: 80 } })] })] })] })), jsxRuntime.jsxs("div", { className: ModelEditor_module.panelSection, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.panelTitle, children: [jsxRuntime.jsx(ui.NiceIcon, { name: "wand", size: 14 }), ' ', t('modelEditorRightPanel.aiAnimation', 'AI Animation')] }), jsxRuntime.jsx("div", { className: ModelEditor_module.panelContent, children: jsxRuntime.jsxs("div", { className: ModelEditor_module.aiPanel, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.aiHeader, children: [jsxRuntime.jsx(ui.NiceIcon, { name: "wand", size: 14 }), ' ', t('modelEditorRightPanel.generateAnimationFromVideo', 'Generate animation from video')] }), jsxRuntime.jsx("p", { style: {
92
- fontSize: 10,
93
- color: 'var(--nice-text-secondary, #888)',
94
- margin: '0 0 6px',
95
- }, children: t('modelEditorRightPanel.uploadAVideoAndAi', 'Upload a video and AI will extract 3D pose data to create an animation clip for the current model.') }), jsxRuntime.jsx("div", { className: ModelEditor_module.aiBtnRow, children: jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.aiBtn, variant: "ghost", size: "sm", disabled: aiBusy || !rootObjectRef.current, onClick: () => { var _a; return (_a = videoInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, children: aiBusy
96
- ? t('modelEditorRightPanel.processing', 'Processing...')
97
- : t('modelEditorRightPanel.uploadVideo', 'Upload Video') }) }), aiStatus && jsxRuntime.jsx("div", { className: ModelEditor_module.aiStatus, children: aiStatus })] }) })] })] })), propTab === 'material' && (jsxRuntime.jsxs("div", { className: ModelEditor_module.panelSection, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.panelTitle, children: [jsxRuntime.jsx(ui.NiceIcon, { name: "palette", size: 14 }), ' ', t('modelEditorRightPanel.materials', 'Materials')] }), jsxRuntime.jsx("div", { className: ModelEditor_module.panelContent, children: selectedMaterials.length > 0 ? (selectedMaterials.map((mat, i) => (jsxRuntime.jsx(ModelEditorSubComponents.MaterialCard, { material: mat, active: i === selMaterialIdx, onClick: () => setSelMaterialIdx(i), onUpdate: () => setMatRefresh((n) => n + 1) }, i)))) : (jsxRuntime.jsx("div", { style: { color: 'var(--nice-text-secondary, #666)', fontSize: 10 }, children: selectedNode
98
- ? t('modelEditorRightPanel.noMaterialsOnThisObject', 'No materials on this object')
99
- : t('modelEditorRightPanel.selectAMeshToInspect', 'Select a mesh to inspect') })) })] })), propTab === 'world' && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.panelSection, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.panelTitle, children: [jsxRuntime.jsx(ui.NiceIcon, { name: "globe", size: 14 }), ' ', t('modelEditorRightPanel.environment', 'Environment')] }), jsxRuntime.jsx("div", { className: ModelEditor_module.panelContent, children: jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.background', 'Background') }), jsxRuntime.jsx(ui.NiceColorPicker, { value: bgColor, onChange: (c) => setBgColor(c) }), jsxRuntime.jsx("span", { style: { fontSize: 9, color: 'var(--nice-text-secondary, #888)' }, children: bgColor })] }) })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.panelSection, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.panelTitle, children: [jsxRuntime.jsx(ui.NiceIcon, { name: "cloud", size: 14 }), " ", t('modelEditorRightPanel.fog', 'Fog')] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.panelContent, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.enable', 'Enable') }), jsxRuntime.jsx(ui.NiceCheckbox, { checked: fogEnabled, onChange: () => setFogEnabled((v) => !v) })] }), fogEnabled && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.color', 'Color') }), jsxRuntime.jsx(ui.NiceColorPicker, { value: fogColor, onChange: (c) => setFogColor(c) })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.near', 'Near') }), jsxRuntime.jsx(ui.NiceNumberInput, { className: ModelEditor_module.propInput, value: fogNear, onChange: (val) => setFogNear(val !== null && val !== void 0 ? val : 1), style: { width: 60 } })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.far', 'Far') }), jsxRuntime.jsx(ui.NiceNumberInput, { className: ModelEditor_module.propInput, value: fogFar, onChange: (val) => setFogFar(val !== null && val !== void 0 ? val : 100), style: { width: 60 } })] })] }))] })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.panelSection, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.panelTitle, children: [jsxRuntime.jsx(ui.NiceIcon, { name: "lightbulb", size: 14 }), ' ', t('modelEditorRightPanel.sceneLights', 'Scene Lights')] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.panelContent, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.showHelpers', 'Show Helpers') }), jsxRuntime.jsx(ui.NiceCheckbox, { checked: showLightHelpers, onChange: () => setShowLightHelpers((v) => !v) })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.grid', 'Grid') }), jsxRuntime.jsx(ui.NiceCheckbox, { checked: showGrid, onChange: () => setShowGrid((v) => !v) })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.axes', 'Axes') }), jsxRuntime.jsx(ui.NiceCheckbox, { checked: showAxes, onChange: () => setShowAxes((v) => !v) })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.skeleton', 'Skeleton') }), jsxRuntime.jsx(ui.NiceCheckbox, { checked: showSkeleton, onChange: () => setShowSkeleton((v) => !v) })] })] })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.panelSection, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.panelTitle, children: [jsxRuntime.jsx(ui.NiceIcon, { name: "grid", size: 14 }), " ", t('modelEditorRightPanel.snapping', 'Snapping')] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.panelContent, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.snap', 'Snap') }), jsxRuntime.jsx(ui.NiceCheckbox, { checked: snapEnabled, onChange: () => setSnapEnabled((v) => !v) })] }), snapEnabled && (jsxRuntime.jsxs("div", { className: ModelEditor_module.propRow, children: [jsxRuntime.jsx("span", { className: ModelEditor_module.propLabel, children: t('modelEditorRightPanel.gridSize', 'Grid Size') }), jsxRuntime.jsx(ui.NiceNumberInput, { className: ModelEditor_module.propInput, step: 0.25, min: 0.1, value: snapGrid, onChange: (val) => setSnapGrid(val !== null && val !== void 0 ? val : 1), style: { width: 60 } })] }))] })] })] })), propTab === 'modifiers' && (jsxRuntime.jsxs("div", { className: ModelEditor_module.panelSection, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.panelTitle, children: [jsxRuntime.jsx(ui.NiceIcon, { name: "settings", size: 14 }), ' ', t('modelEditorRightPanel.modifiers', 'Modifiers')] }), jsxRuntime.jsx("div", { className: ModelEditor_module.panelContent, children: selectedNode && selectedNode.object instanceof THREE__namespace.Mesh ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.btnSecondary, variant: "ghost", size: "sm", style: { width: '100%', marginBottom: 4 }, onClick: () => {
100
- const mesh = selectedNode.object;
101
- const geo = mesh.geometry;
102
- const pos = geo.attributes.position;
103
- if (pos) {
104
- const wireGeo = new THREE__namespace.WireframeGeometry(geo);
105
- mesh.geometry = wireGeo;
106
- setStatusText(t('modelEditorRightPanel.appliedWireframeModifier', 'Applied Wireframe modifier'));
107
- rebuildTree();
108
- }
109
- }, children: t('modelEditorRightPanel.wireframeModifier', '+ Wireframe Modifier') }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.btnSecondary, variant: "ghost", size: "sm", style: { width: '100%', marginBottom: 4 }, onClick: () => {
110
- const mesh = selectedNode.object;
111
- mesh.geometry.computeVertexNormals();
112
- setStatusText(t('modelEditorRightPanel.recomputedNormals', 'Recomputed normals'));
113
- }, children: t('modelEditorRightPanel.recomputeNormals', 'Recompute Normals') }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.btnSecondary, variant: "ghost", size: "sm", style: { width: '100%', marginBottom: 4 }, onClick: () => {
114
- const mesh = selectedNode.object;
115
- const geo = mesh.geometry;
116
- geo.center();
117
- setStatusText(t('modelEditorRightPanel.centeredGeometry', 'Centered geometry'));
118
- setMatRefresh((n) => n + 1);
119
- }, children: t('modelEditorRightPanel.centerGeometry', 'Center Geometry') }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.btnSecondary, variant: "ghost", size: "sm", style: { width: '100%', marginBottom: 4 }, onClick: () => {
120
- const mesh = selectedNode.object;
121
- const geo = mesh.geometry;
122
- const idx = geo.index;
123
- if (idx) {
124
- const arr = idx.array;
125
- for (let i = 0; i < arr.length; i += 3) {
126
- const tmp = arr[i];
127
- arr[i] = arr[i + 2];
128
- arr[i + 2] = tmp;
129
- }
130
- idx.needsUpdate = true;
131
- geo.computeVertexNormals();
132
- setStatusText(t('modelEditorRightPanel.flippedNormals', 'Flipped normals'));
133
- }
134
- }, children: t('modelEditorRightPanel.flipNormals', 'Flip Normals') })] })) : (jsxRuntime.jsx("div", { style: { color: 'var(--nice-text-secondary, #666)', fontSize: 10 }, children: t('modelEditorRightPanel.selectAMeshToApply', 'Select a mesh to apply modifiers') })) })] })), propTab === 'physics' && (jsxRuntime.jsxs("div", { className: ModelEditor_module.panelSection, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.panelTitle, children: [jsxRuntime.jsx(ui.NiceIcon, { name: "zap", size: 14 }), ' ', t('modelEditorRightPanel.physicsInfo', 'Physics (Info)')] }), jsxRuntime.jsx("div", { className: ModelEditor_module.panelContent, children: jsxRuntime.jsxs("div", { style: { color: 'var(--nice-text-secondary, #666)', fontSize: 10, lineHeight: 1.5 }, children: [t('modelEditorRightPanel.physicsSimulationPreviewIsNot', 'Physics simulation preview is not yet available.'), jsxRuntime.jsx("br", {}), jsxRuntime.jsx("br", {}), t('modelEditorRightPanel.plannedFeatures', 'Planned features:'), jsxRuntime.jsx("br", {}), t('modelEditorRightPanel.rigidBodySimulation', '• Rigid body simulation'), jsxRuntime.jsx("br", {}), t('modelEditorRightPanel.softBodyDynamics', '• Soft body dynamics'), jsxRuntime.jsx("br", {}), t('modelEditorRightPanel.clothSimulation', '• Cloth simulation'), jsxRuntime.jsx("br", {}), t('modelEditorRightPanel.particleSystems', '• Particle systems')] }) })] }))] }));
135
- }), { displayName: 'ModelEditorRightPanel' });
136
-
137
- module.exports = ModelEditorRightPanel;
31
+ const {
32
+ propTab,
33
+ setPropTab,
34
+ selectedNode,
35
+ selectedMaterials,
36
+ selMaterialIdx,
37
+ setSelMaterialIdx,
38
+ setMatRefresh,
39
+ rebuildTree,
40
+ aiBusy,
41
+ aiStatus,
42
+ rootObjectRef,
43
+ videoInputRef,
44
+ bgColor,
45
+ setBgColor,
46
+ fogEnabled,
47
+ setFogEnabled,
48
+ fogColor,
49
+ setFogColor,
50
+ fogNear,
51
+ setFogNear,
52
+ fogFar,
53
+ setFogFar,
54
+ showLightHelpers,
55
+ setShowLightHelpers,
56
+ showGrid,
57
+ setShowGrid,
58
+ showAxes,
59
+ setShowAxes,
60
+ showSkeleton,
61
+ setShowSkeleton,
62
+ snapEnabled,
63
+ setSnapEnabled,
64
+ snapGrid,
65
+ setSnapGrid,
66
+ setStatusText
67
+ } = api;
68
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.rightPanel, children: [
69
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.propTabs, children: ["object", "material", "world", "modifiers", "physics"].map((t2) => /* @__PURE__ */ jsxRuntime.jsx(
70
+ ui.NiceButton,
71
+ {
72
+ className: ModelEditor_module.default.propTabBtn,
73
+ variant: propTab === t2 ? "primary" : "ghost",
74
+ size: "sm",
75
+ onClick: () => setPropTab(t2),
76
+ title: t2.charAt(0).toUpperCase() + t2.slice(1),
77
+ "aria-label": t2.charAt(0).toUpperCase() + t2.slice(1),
78
+ children: /* @__PURE__ */ jsxRuntime.jsx(
79
+ ui.NiceIcon,
80
+ {
81
+ name: t2 === "object" ? "settings" : t2 === "material" ? "palette" : t2 === "world" ? "globe" : t2 === "modifiers" ? "settings" : "zap",
82
+ size: 16
83
+ }
84
+ )
85
+ },
86
+ t2
87
+ )) }),
88
+ propTab === "object" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
89
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelSection, children: [
90
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelTitle, children: [
91
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "settings", size: 14 }),
92
+ " ",
93
+ t("modelEditorRightPanel.transform", "Transform")
94
+ ] }),
95
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.panelContent, children: selectedNode ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
96
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
97
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.name", "Name") }),
98
+ /* @__PURE__ */ jsxRuntime.jsx(
99
+ ui.NiceTextInput,
100
+ {
101
+ className: ModelEditor_module.default.propInput,
102
+ value: selectedNode.name,
103
+ onChange: (val) => {
104
+ selectedNode.object.name = val;
105
+ rebuildTree();
106
+ }
107
+ }
108
+ )
109
+ ] }),
110
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
111
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.type", "Type") }),
112
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 10, color: "var(--nice-text-secondary, #888)" }, children: selectedNode.type })
113
+ ] }),
114
+ /* @__PURE__ */ jsxRuntime.jsx(
115
+ ModelEditorSubComponents.Vec3Row,
116
+ {
117
+ label: t("modelEditorRightPanel.position", "Position"),
118
+ value: selectedNode.object.position,
119
+ onChange: () => setMatRefresh((n) => n + 1)
120
+ }
121
+ ),
122
+ /* @__PURE__ */ jsxRuntime.jsx(
123
+ ModelEditorSubComponents.Vec3RowDeg,
124
+ {
125
+ label: t("modelEditorRightPanel.rotation", "Rotation"),
126
+ value: selectedNode.object.rotation,
127
+ onChange: () => setMatRefresh((n) => n + 1)
128
+ }
129
+ ),
130
+ /* @__PURE__ */ jsxRuntime.jsx(
131
+ ModelEditorSubComponents.Vec3Row,
132
+ {
133
+ label: t("modelEditorRightPanel.scale", "Scale"),
134
+ value: selectedNode.object.scale,
135
+ onChange: () => setMatRefresh((n) => n + 1)
136
+ }
137
+ )
138
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "var(--nice-text-secondary, #666)", fontSize: 10 }, children: t("modelEditorRightPanel.selectAnObject", "Select an object") }) })
139
+ ] }),
140
+ selectedNode && selectedNode.object instanceof THREE__namespace.Light && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelSection, children: [
141
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelTitle, children: [
142
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "lightbulb", size: 14 }),
143
+ " ",
144
+ t("modelEditorRightPanel.light", "Light")
145
+ ] }),
146
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelContent, children: [
147
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
148
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.color", "Color") }),
149
+ /* @__PURE__ */ jsxRuntime.jsx(
150
+ ui.NiceColorPicker,
151
+ {
152
+ value: `#${selectedNode.object.color.getHexString()}`,
153
+ onChange: (c) => {
154
+ selectedNode.object.color.set(c);
155
+ setMatRefresh((n) => n + 1);
156
+ }
157
+ }
158
+ )
159
+ ] }),
160
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
161
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.intensity", "Intensity") }),
162
+ /* @__PURE__ */ jsxRuntime.jsx(
163
+ ui.NiceSlider,
164
+ {
165
+ min: 0,
166
+ max: 10,
167
+ step: 0.1,
168
+ value: selectedNode.object.intensity,
169
+ onChange: (val) => {
170
+ selectedNode.object.intensity = val;
171
+ setMatRefresh((n) => n + 1);
172
+ },
173
+ style: { flex: 1 }
174
+ }
175
+ ),
176
+ /* @__PURE__ */ jsxRuntime.jsx(
177
+ "span",
178
+ {
179
+ style: {
180
+ fontSize: 9,
181
+ color: "var(--nice-text-secondary, #888)",
182
+ width: 28,
183
+ textAlign: "right"
184
+ },
185
+ children: selectedNode.object.intensity.toFixed(1)
186
+ }
187
+ )
188
+ ] }),
189
+ "castShadow" in selectedNode.object && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
190
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.shadow", "Shadow") }),
191
+ /* @__PURE__ */ jsxRuntime.jsx(
192
+ ui.NiceCheckbox,
193
+ {
194
+ checked: selectedNode.object.castShadow,
195
+ onChange: (checked) => {
196
+ selectedNode.object.castShadow = checked;
197
+ setMatRefresh((n) => n + 1);
198
+ }
199
+ }
200
+ )
201
+ ] }),
202
+ selectedNode.object instanceof THREE__namespace.SpotLight && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
203
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
204
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.angle", "Angle") }),
205
+ /* @__PURE__ */ jsxRuntime.jsx(
206
+ ui.NiceSlider,
207
+ {
208
+ min: 0,
209
+ max: 90,
210
+ step: 1,
211
+ value: selectedNode.object.angle * modelEditorTypes.DEG,
212
+ onChange: (val) => {
213
+ selectedNode.object.angle = val / modelEditorTypes.DEG;
214
+ setMatRefresh((n) => n + 1);
215
+ },
216
+ style: { flex: 1 }
217
+ }
218
+ ),
219
+ /* @__PURE__ */ jsxRuntime.jsxs(
220
+ "span",
221
+ {
222
+ style: {
223
+ fontSize: 9,
224
+ color: "var(--nice-text-secondary, #888)",
225
+ width: 28,
226
+ textAlign: "right"
227
+ },
228
+ children: [
229
+ (selectedNode.object.angle * modelEditorTypes.DEG).toFixed(0),
230
+ "°"
231
+ ]
232
+ }
233
+ )
234
+ ] }),
235
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
236
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.penumbra", "Penumbra") }),
237
+ /* @__PURE__ */ jsxRuntime.jsx(
238
+ ui.NiceSlider,
239
+ {
240
+ min: 0,
241
+ max: 1,
242
+ step: 0.01,
243
+ value: selectedNode.object.penumbra,
244
+ onChange: (val) => {
245
+ selectedNode.object.penumbra = val;
246
+ setMatRefresh((n) => n + 1);
247
+ },
248
+ style: { flex: 1 }
249
+ }
250
+ )
251
+ ] })
252
+ ] })
253
+ ] })
254
+ ] }),
255
+ selectedNode && selectedNode.object instanceof THREE__namespace.PerspectiveCamera && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelSection, children: [
256
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelTitle, children: [
257
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "camera", size: 14 }),
258
+ " ",
259
+ t("modelEditorRightPanel.camera", "Camera")
260
+ ] }),
261
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelContent, children: [
262
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
263
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.fov", "FOV") }),
264
+ /* @__PURE__ */ jsxRuntime.jsx(
265
+ ui.NiceSlider,
266
+ {
267
+ min: 10,
268
+ max: 120,
269
+ step: 1,
270
+ value: selectedNode.object.fov,
271
+ onChange: (val) => {
272
+ const cam = selectedNode.object;
273
+ cam.fov = val;
274
+ cam.updateProjectionMatrix();
275
+ setMatRefresh((n) => n + 1);
276
+ },
277
+ style: { flex: 1 }
278
+ }
279
+ ),
280
+ /* @__PURE__ */ jsxRuntime.jsxs(
281
+ "span",
282
+ {
283
+ style: {
284
+ fontSize: 9,
285
+ color: "var(--nice-text-secondary, #888)",
286
+ width: 28,
287
+ textAlign: "right"
288
+ },
289
+ children: [
290
+ selectedNode.object.fov.toFixed(0),
291
+ "°"
292
+ ]
293
+ }
294
+ )
295
+ ] }),
296
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
297
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.near", "Near") }),
298
+ /* @__PURE__ */ jsxRuntime.jsx(
299
+ ui.NiceNumberInput,
300
+ {
301
+ className: ModelEditor_module.default.propInput,
302
+ step: 0.01,
303
+ value: selectedNode.object.near,
304
+ onChange: (val) => {
305
+ const cam = selectedNode.object;
306
+ cam.near = val ?? 0.1;
307
+ cam.updateProjectionMatrix();
308
+ setMatRefresh((n) => n + 1);
309
+ },
310
+ style: { width: 60 }
311
+ }
312
+ )
313
+ ] }),
314
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
315
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.far", "Far") }),
316
+ /* @__PURE__ */ jsxRuntime.jsx(
317
+ ui.NiceNumberInput,
318
+ {
319
+ className: ModelEditor_module.default.propInput,
320
+ step: 1,
321
+ value: selectedNode.object.far,
322
+ onChange: (val) => {
323
+ const cam = selectedNode.object;
324
+ cam.far = val ?? 1e3;
325
+ cam.updateProjectionMatrix();
326
+ setMatRefresh((n) => n + 1);
327
+ },
328
+ style: { width: 80 }
329
+ }
330
+ )
331
+ ] })
332
+ ] })
333
+ ] }),
334
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelSection, children: [
335
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelTitle, children: [
336
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "wand", size: 14 }),
337
+ " ",
338
+ t("modelEditorRightPanel.aiAnimation", "AI Animation")
339
+ ] }),
340
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.panelContent, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.aiPanel, children: [
341
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.aiHeader, children: [
342
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "wand", size: 14 }),
343
+ " ",
344
+ t(
345
+ "modelEditorRightPanel.generateAnimationFromVideo",
346
+ "Generate animation from video"
347
+ )
348
+ ] }),
349
+ /* @__PURE__ */ jsxRuntime.jsx(
350
+ "p",
351
+ {
352
+ style: {
353
+ fontSize: 10,
354
+ color: "var(--nice-text-secondary, #888)",
355
+ margin: "0 0 6px"
356
+ },
357
+ children: t(
358
+ "modelEditorRightPanel.uploadAVideoAndAi",
359
+ "Upload a video and AI will extract 3D pose data to create an animation clip for the current model."
360
+ )
361
+ }
362
+ ),
363
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.aiBtnRow, children: /* @__PURE__ */ jsxRuntime.jsx(
364
+ ui.NiceButton,
365
+ {
366
+ className: ModelEditor_module.default.aiBtn,
367
+ variant: "ghost",
368
+ size: "sm",
369
+ disabled: aiBusy || !rootObjectRef.current,
370
+ onClick: () => videoInputRef.current?.click(),
371
+ children: aiBusy ? t("modelEditorRightPanel.processing", "Processing...") : t("modelEditorRightPanel.uploadVideo", "Upload Video")
372
+ }
373
+ ) }),
374
+ aiStatus && /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.aiStatus, children: aiStatus })
375
+ ] }) })
376
+ ] })
377
+ ] }),
378
+ propTab === "material" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelSection, children: [
379
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelTitle, children: [
380
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "palette", size: 14 }),
381
+ " ",
382
+ t("modelEditorRightPanel.materials", "Materials")
383
+ ] }),
384
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.panelContent, children: selectedMaterials.length > 0 ? selectedMaterials.map((mat, i) => /* @__PURE__ */ jsxRuntime.jsx(
385
+ ModelEditorSubComponents.MaterialCard,
386
+ {
387
+ material: mat,
388
+ active: i === selMaterialIdx,
389
+ onClick: () => setSelMaterialIdx(i),
390
+ onUpdate: () => setMatRefresh((n) => n + 1)
391
+ },
392
+ i
393
+ )) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "var(--nice-text-secondary, #666)", fontSize: 10 }, children: selectedNode ? t(
394
+ "modelEditorRightPanel.noMaterialsOnThisObject",
395
+ "No materials on this object"
396
+ ) : t("modelEditorRightPanel.selectAMeshToInspect", "Select a mesh to inspect") }) })
397
+ ] }),
398
+ propTab === "world" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
399
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelSection, children: [
400
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelTitle, children: [
401
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "globe", size: 14 }),
402
+ " ",
403
+ t("modelEditorRightPanel.environment", "Environment")
404
+ ] }),
405
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.panelContent, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
406
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.background", "Background") }),
407
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceColorPicker, { value: bgColor, onChange: (c) => setBgColor(c) }),
408
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 9, color: "var(--nice-text-secondary, #888)" }, children: bgColor })
409
+ ] }) })
410
+ ] }),
411
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelSection, children: [
412
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelTitle, children: [
413
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "cloud", size: 14 }),
414
+ " ",
415
+ t("modelEditorRightPanel.fog", "Fog")
416
+ ] }),
417
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelContent, children: [
418
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
419
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.enable", "Enable") }),
420
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceCheckbox, { checked: fogEnabled, onChange: () => setFogEnabled((v) => !v) })
421
+ ] }),
422
+ fogEnabled && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
423
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
424
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.color", "Color") }),
425
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceColorPicker, { value: fogColor, onChange: (c) => setFogColor(c) })
426
+ ] }),
427
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
428
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.near", "Near") }),
429
+ /* @__PURE__ */ jsxRuntime.jsx(
430
+ ui.NiceNumberInput,
431
+ {
432
+ className: ModelEditor_module.default.propInput,
433
+ value: fogNear,
434
+ onChange: (val) => setFogNear(val ?? 1),
435
+ style: { width: 60 }
436
+ }
437
+ )
438
+ ] }),
439
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
440
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.far", "Far") }),
441
+ /* @__PURE__ */ jsxRuntime.jsx(
442
+ ui.NiceNumberInput,
443
+ {
444
+ className: ModelEditor_module.default.propInput,
445
+ value: fogFar,
446
+ onChange: (val) => setFogFar(val ?? 100),
447
+ style: { width: 60 }
448
+ }
449
+ )
450
+ ] })
451
+ ] })
452
+ ] })
453
+ ] }),
454
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelSection, children: [
455
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelTitle, children: [
456
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "lightbulb", size: 14 }),
457
+ " ",
458
+ t("modelEditorRightPanel.sceneLights", "Scene Lights")
459
+ ] }),
460
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelContent, children: [
461
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
462
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.showHelpers", "Show Helpers") }),
463
+ /* @__PURE__ */ jsxRuntime.jsx(
464
+ ui.NiceCheckbox,
465
+ {
466
+ checked: showLightHelpers,
467
+ onChange: () => setShowLightHelpers((v) => !v)
468
+ }
469
+ )
470
+ ] }),
471
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
472
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.grid", "Grid") }),
473
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceCheckbox, { checked: showGrid, onChange: () => setShowGrid((v) => !v) })
474
+ ] }),
475
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
476
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.axes", "Axes") }),
477
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceCheckbox, { checked: showAxes, onChange: () => setShowAxes((v) => !v) })
478
+ ] }),
479
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
480
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.skeleton", "Skeleton") }),
481
+ /* @__PURE__ */ jsxRuntime.jsx(
482
+ ui.NiceCheckbox,
483
+ {
484
+ checked: showSkeleton,
485
+ onChange: () => setShowSkeleton((v) => !v)
486
+ }
487
+ )
488
+ ] })
489
+ ] })
490
+ ] }),
491
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelSection, children: [
492
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelTitle, children: [
493
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "grid", size: 14 }),
494
+ " ",
495
+ t("modelEditorRightPanel.snapping", "Snapping")
496
+ ] }),
497
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelContent, children: [
498
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
499
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.snap", "Snap") }),
500
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceCheckbox, { checked: snapEnabled, onChange: () => setSnapEnabled((v) => !v) })
501
+ ] }),
502
+ snapEnabled && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.propRow, children: [
503
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: ModelEditor_module.default.propLabel, children: t("modelEditorRightPanel.gridSize", "Grid Size") }),
504
+ /* @__PURE__ */ jsxRuntime.jsx(
505
+ ui.NiceNumberInput,
506
+ {
507
+ className: ModelEditor_module.default.propInput,
508
+ step: 0.25,
509
+ min: 0.1,
510
+ value: snapGrid,
511
+ onChange: (val) => setSnapGrid(val ?? 1),
512
+ style: { width: 60 }
513
+ }
514
+ )
515
+ ] })
516
+ ] })
517
+ ] })
518
+ ] }),
519
+ propTab === "modifiers" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelSection, children: [
520
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelTitle, children: [
521
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "settings", size: 14 }),
522
+ " ",
523
+ t("modelEditorRightPanel.modifiers", "Modifiers")
524
+ ] }),
525
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.panelContent, children: selectedNode && selectedNode.object instanceof THREE__namespace.Mesh ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
526
+ /* @__PURE__ */ jsxRuntime.jsx(
527
+ ui.NiceButton,
528
+ {
529
+ className: ModelEditor_module.default.btnSecondary,
530
+ variant: "ghost",
531
+ size: "sm",
532
+ style: { width: "100%", marginBottom: 4 },
533
+ onClick: () => {
534
+ const mesh = selectedNode.object;
535
+ const geo = mesh.geometry;
536
+ const pos = geo.attributes.position;
537
+ if (pos) {
538
+ const wireGeo = new THREE__namespace.WireframeGeometry(geo);
539
+ mesh.geometry = wireGeo;
540
+ setStatusText(
541
+ t(
542
+ "modelEditorRightPanel.appliedWireframeModifier",
543
+ "Applied Wireframe modifier"
544
+ )
545
+ );
546
+ rebuildTree();
547
+ }
548
+ },
549
+ children: t("modelEditorRightPanel.wireframeModifier", "+ Wireframe Modifier")
550
+ }
551
+ ),
552
+ /* @__PURE__ */ jsxRuntime.jsx(
553
+ ui.NiceButton,
554
+ {
555
+ className: ModelEditor_module.default.btnSecondary,
556
+ variant: "ghost",
557
+ size: "sm",
558
+ style: { width: "100%", marginBottom: 4 },
559
+ onClick: () => {
560
+ const mesh = selectedNode.object;
561
+ mesh.geometry.computeVertexNormals();
562
+ setStatusText(
563
+ t("modelEditorRightPanel.recomputedNormals", "Recomputed normals")
564
+ );
565
+ },
566
+ children: t("modelEditorRightPanel.recomputeNormals", "Recompute Normals")
567
+ }
568
+ ),
569
+ /* @__PURE__ */ jsxRuntime.jsx(
570
+ ui.NiceButton,
571
+ {
572
+ className: ModelEditor_module.default.btnSecondary,
573
+ variant: "ghost",
574
+ size: "sm",
575
+ style: { width: "100%", marginBottom: 4 },
576
+ onClick: () => {
577
+ const mesh = selectedNode.object;
578
+ const geo = mesh.geometry;
579
+ geo.center();
580
+ setStatusText(
581
+ t("modelEditorRightPanel.centeredGeometry", "Centered geometry")
582
+ );
583
+ setMatRefresh((n) => n + 1);
584
+ },
585
+ children: t("modelEditorRightPanel.centerGeometry", "Center Geometry")
586
+ }
587
+ ),
588
+ /* @__PURE__ */ jsxRuntime.jsx(
589
+ ui.NiceButton,
590
+ {
591
+ className: ModelEditor_module.default.btnSecondary,
592
+ variant: "ghost",
593
+ size: "sm",
594
+ style: { width: "100%", marginBottom: 4 },
595
+ onClick: () => {
596
+ const mesh = selectedNode.object;
597
+ const geo = mesh.geometry;
598
+ const idx = geo.index;
599
+ if (idx) {
600
+ const arr = idx.array;
601
+ for (let i = 0; i < arr.length; i += 3) {
602
+ const tmp = arr[i];
603
+ arr[i] = arr[i + 2];
604
+ arr[i + 2] = tmp;
605
+ }
606
+ idx.needsUpdate = true;
607
+ geo.computeVertexNormals();
608
+ setStatusText(t("modelEditorRightPanel.flippedNormals", "Flipped normals"));
609
+ }
610
+ },
611
+ children: t("modelEditorRightPanel.flipNormals", "Flip Normals")
612
+ }
613
+ )
614
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "var(--nice-text-secondary, #666)", fontSize: 10 }, children: t(
615
+ "modelEditorRightPanel.selectAMeshToApply",
616
+ "Select a mesh to apply modifiers"
617
+ ) }) })
618
+ ] }),
619
+ propTab === "physics" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelSection, children: [
620
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.panelTitle, children: [
621
+ /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "zap", size: 14 }),
622
+ " ",
623
+ t("modelEditorRightPanel.physicsInfo", "Physics (Info)")
624
+ ] }),
625
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.panelContent, children: /* @__PURE__ */ jsxRuntime.jsxs(
626
+ "div",
627
+ {
628
+ style: { color: "var(--nice-text-secondary, #666)", fontSize: 10, lineHeight: 1.5 },
629
+ children: [
630
+ t(
631
+ "modelEditorRightPanel.physicsSimulationPreviewIsNot",
632
+ "Physics simulation preview is not yet available."
633
+ ),
634
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
635
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
636
+ t("modelEditorRightPanel.plannedFeatures", "Planned features:"),
637
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
638
+ t("modelEditorRightPanel.rigidBodySimulation", "• Rigid body simulation"),
639
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
640
+ t("modelEditorRightPanel.softBodyDynamics", "• Soft body dynamics"),
641
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
642
+ t("modelEditorRightPanel.clothSimulation", "• Cloth simulation"),
643
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
644
+ t("modelEditorRightPanel.particleSystems", "• Particle systems")
645
+ ]
646
+ }
647
+ ) })
648
+ ] })
649
+ ] });
650
+ }),
651
+ { displayName: "ModelEditorRightPanel" }
652
+ );
653
+ exports.default = ModelEditorRightPanel;