@nice2dev/ui-3d 1.0.6 → 1.1.0
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.
- package/dist/cjs/core/i18n.js +3 -3
- package/dist/cjs/dance/DanceBridge.js +13 -13
- package/dist/cjs/dance/DanceScoreEngine.js +8 -8
- package/dist/cjs/dance/PoseDetector.js +20 -20
- package/dist/cjs/material/NiceMaterialEditor.js +19 -19
- package/dist/cjs/model/ModelEditorLeftPanel.js +5 -5
- package/dist/cjs/model/ModelEditorMenuBar.js +6 -6
- package/dist/cjs/model/ModelEditorRightPanel.js +19 -19
- package/dist/cjs/model/ModelEditorSubComponents.js +10 -10
- package/dist/cjs/model/ModelEditorTimeline.js +6 -6
- package/dist/cjs/model/ModelEditorToolbar.js +4 -4
- package/dist/cjs/model/ModelEditorViewport.js +2 -2
- package/dist/cjs/model/ModelViewer.js +14 -14
- package/dist/cjs/model/NiceArmatureEditor.js +18 -18
- package/dist/cjs/model/NiceMorphTargetEditor.js +18 -18
- package/dist/cjs/model/NiceOctree.js +16 -16
- package/dist/cjs/model/NicePhysicsSimulation.js +24 -24
- package/dist/cjs/model/NiceProceduralGeometry.js +8 -8
- package/dist/cjs/model/NiceTerrainEditor.js +19 -19
- package/dist/cjs/model/NiceWeightPainter.js +14 -14
- package/dist/cjs/model/NiceXRPreview.js +18 -18
- package/dist/cjs/model/useModelEditor.js +127 -127
- package/dist/cjs/model/useModelViewer.js +61 -61
- package/dist/cjs/particle/NiceParticleEditor.js +11 -11
- package/dist/cjs/rendering/NiceCascadedShadows.js +12 -12
- package/dist/cjs/rendering/NiceRenderExport.js +5 -5
- package/dist/cjs/rendering/NiceSSAO.js +18 -18
- package/dist/cjs/rendering/NiceSSR.js +14 -14
- package/dist/cjs/rendering/NiceWebGPURenderer.js +21 -21
- package/dist/cjs/ui/dist/NiceButton-D9l39Rs7.js +598 -0
- package/dist/cjs/ui/dist/NiceButton-D9l39Rs7.js.map +1 -0
- package/dist/cjs/ui/dist/NiceErrorBoundary-niMx1aSJ.js +647 -0
- package/dist/cjs/ui/dist/NiceErrorBoundary-niMx1aSJ.js.map +1 -0
- package/dist/cjs/ui/dist/NiceModuleLifecyclePanel-I_TXRiiY.js +5048 -0
- package/dist/cjs/ui/dist/NiceModuleLifecyclePanel-I_TXRiiY.js.map +1 -0
- package/dist/cjs/ui/dist/NicePinCodeInput-CrMfdxxc.js +13081 -0
- package/dist/cjs/ui/dist/NicePinCodeInput-CrMfdxxc.js.map +1 -0
- package/dist/cjs/ui/dist/NiceSavedQueryPanel-CUAsdOjJ.js +6054 -0
- package/dist/cjs/ui/dist/NiceSavedQueryPanel-CUAsdOjJ.js.map +1 -0
- package/dist/cjs/ui/dist/NiceToggle-CaY1u82g.js +280 -0
- package/dist/cjs/ui/dist/NiceToggle-CaY1u82g.js.map +1 -0
- package/dist/cjs/ui/dist/NiceWindow-SiCaREbq.js +806 -0
- package/dist/cjs/ui/dist/NiceWindow-SiCaREbq.js.map +1 -0
- package/dist/cjs/ui/dist/charts-Bx_kNBsE.js +3508 -0
- package/dist/cjs/ui/dist/charts-Bx_kNBsE.js.map +1 -0
- package/dist/cjs/ui/dist/core-BpghV7Ls.js +10249 -0
- package/dist/cjs/ui/dist/core-BpghV7Ls.js.map +1 -0
- package/dist/cjs/ui/dist/index-CIl98Vbm.js +40039 -0
- package/dist/cjs/ui/dist/index-CIl98Vbm.js.map +1 -0
- package/dist/cjs/uv/NiceUVEditor.js +24 -24
- package/dist/esm/model/ModelEditorLeftPanel.js +4 -4
- package/dist/esm/model/ModelEditorMenuBar.js +4 -4
- package/dist/esm/model/ModelEditorRightPanel.js +5 -5
- package/dist/esm/model/ModelEditorSubComponents.js +2 -2
- package/dist/esm/model/ModelEditorTimeline.js +5 -5
- package/dist/esm/model/ModelEditorToolbar.js +3 -3
- package/dist/esm/model/ModelEditorViewport.js +2 -2
- package/dist/esm/model/ModelViewer.js +2 -2
- package/dist/esm/ui/dist/NiceButton-D9l39Rs7.js +593 -0
- package/dist/esm/ui/dist/NiceButton-D9l39Rs7.js.map +1 -0
- package/dist/esm/ui/dist/NiceErrorBoundary-niMx1aSJ.js +637 -0
- package/dist/esm/ui/dist/NiceErrorBoundary-niMx1aSJ.js.map +1 -0
- package/dist/esm/ui/dist/NiceModuleLifecyclePanel-I_TXRiiY.js +5007 -0
- package/dist/esm/ui/dist/NiceModuleLifecyclePanel-I_TXRiiY.js.map +1 -0
- package/dist/esm/ui/dist/NicePinCodeInput-CrMfdxxc.js +13011 -0
- package/dist/esm/ui/dist/NicePinCodeInput-CrMfdxxc.js.map +1 -0
- package/dist/esm/ui/dist/NiceSavedQueryPanel-CUAsdOjJ.js +6037 -0
- package/dist/esm/ui/dist/NiceSavedQueryPanel-CUAsdOjJ.js.map +1 -0
- package/dist/esm/ui/dist/NiceToggle-CaY1u82g.js +276 -0
- package/dist/esm/ui/dist/NiceToggle-CaY1u82g.js.map +1 -0
- package/dist/esm/ui/dist/NiceWindow-SiCaREbq.js +795 -0
- package/dist/esm/ui/dist/NiceWindow-SiCaREbq.js.map +1 -0
- package/dist/esm/ui/dist/charts-Bx_kNBsE.js +3483 -0
- package/dist/esm/ui/dist/charts-Bx_kNBsE.js.map +1 -0
- package/dist/esm/ui/dist/core-BpghV7Ls.js +10071 -0
- package/dist/esm/ui/dist/core-BpghV7Ls.js.map +1 -0
- package/dist/esm/ui/dist/index-CIl98Vbm.js +39917 -0
- package/dist/esm/ui/dist/index-CIl98Vbm.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
-
var
|
|
4
|
+
var ke = require('react');
|
|
5
5
|
var uvEditorTypes = require('./uvEditorTypes.js');
|
|
6
6
|
var uvEditorUtils = require('./uvEditorUtils.js');
|
|
7
7
|
var UVEditor_module = require('./UVEditor.module.css.js');
|
|
@@ -10,31 +10,31 @@ var UVEditor_module = require('./UVEditor.module.css.js');
|
|
|
10
10
|
Component
|
|
11
11
|
═══════════════════════════════════════════ */
|
|
12
12
|
const NiceUVEditor = ({ geometry, texture, channel = 'uv', onUVChange, onSelectionChange, width = '100%', height = 600, showToolbar = true, showSidebar = true, className, readOnly = false, }) => {
|
|
13
|
-
const canvasRef =
|
|
14
|
-
const containerRef =
|
|
13
|
+
const canvasRef = ke.useRef(null);
|
|
14
|
+
const containerRef = ke.useRef(null);
|
|
15
15
|
// State
|
|
16
|
-
const [state, setState] =
|
|
16
|
+
const [state, setState] = ke.useState({
|
|
17
17
|
...uvEditorTypes.DEFAULT_UV_STATE,
|
|
18
18
|
activeChannel: channel,
|
|
19
19
|
});
|
|
20
|
-
const [meshData, setMeshData] =
|
|
21
|
-
const [selection, setSelection] =
|
|
20
|
+
const [meshData, setMeshData] = ke.useState(null);
|
|
21
|
+
const [selection, setSelection] = ke.useState({
|
|
22
22
|
vertices: new Set(),
|
|
23
23
|
edges: new Set(),
|
|
24
24
|
faces: new Set(),
|
|
25
25
|
islands: new Set(),
|
|
26
26
|
});
|
|
27
|
-
const [dragState, setDragState] =
|
|
27
|
+
const [dragState, setDragState] = ke.useState({
|
|
28
28
|
active: false,
|
|
29
29
|
startPos: { u: 0, v: 0 },
|
|
30
30
|
currentPos: { u: 0, v: 0 },
|
|
31
31
|
mode: 'select',
|
|
32
32
|
initialPositions: new Map(),
|
|
33
33
|
});
|
|
34
|
-
const [undoStack, setUndoStack] =
|
|
35
|
-
const [redoStack, setRedoStack] =
|
|
34
|
+
const [undoStack, setUndoStack] = ke.useState([]);
|
|
35
|
+
const [redoStack, setRedoStack] = ke.useState([]);
|
|
36
36
|
// Extract mesh data when geometry changes
|
|
37
|
-
|
|
37
|
+
ke.useEffect(() => {
|
|
38
38
|
if (geometry) {
|
|
39
39
|
const data = uvEditorUtils.extractUVMeshData(geometry, state.activeChannel);
|
|
40
40
|
setMeshData(data);
|
|
@@ -45,7 +45,7 @@ const NiceUVEditor = ({ geometry, texture, channel = 'uv', onUVChange, onSelecti
|
|
|
45
45
|
}
|
|
46
46
|
}, [geometry, state.activeChannel]);
|
|
47
47
|
// Render UV view
|
|
48
|
-
|
|
48
|
+
ke.useEffect(() => {
|
|
49
49
|
if (!canvasRef.current || !meshData)
|
|
50
50
|
return;
|
|
51
51
|
const canvas = canvasRef.current;
|
|
@@ -193,7 +193,7 @@ const NiceUVEditor = ({ geometry, texture, channel = 'uv', onUVChange, onSelecti
|
|
|
193
193
|
}
|
|
194
194
|
}, [meshData, state, texture, dragState, selection]);
|
|
195
195
|
// Resize canvas
|
|
196
|
-
|
|
196
|
+
ke.useEffect(() => {
|
|
197
197
|
if (!canvasRef.current || !containerRef.current)
|
|
198
198
|
return;
|
|
199
199
|
const observer = new ResizeObserver(() => {
|
|
@@ -205,14 +205,14 @@ const NiceUVEditor = ({ geometry, texture, channel = 'uv', onUVChange, onSelecti
|
|
|
205
205
|
return () => observer.disconnect();
|
|
206
206
|
}, []);
|
|
207
207
|
// Push undo state
|
|
208
|
-
const pushUndo =
|
|
208
|
+
const pushUndo = ke.useCallback(() => {
|
|
209
209
|
if (!meshData)
|
|
210
210
|
return;
|
|
211
211
|
setUndoStack(prev => [...prev.slice(-20), JSON.parse(JSON.stringify(meshData))]);
|
|
212
212
|
setRedoStack([]);
|
|
213
213
|
}, [meshData]);
|
|
214
214
|
// Undo
|
|
215
|
-
const undo =
|
|
215
|
+
const undo = ke.useCallback(() => {
|
|
216
216
|
if (undoStack.length === 0 || !meshData)
|
|
217
217
|
return;
|
|
218
218
|
setRedoStack(prev => [...prev, JSON.parse(JSON.stringify(meshData))]);
|
|
@@ -221,7 +221,7 @@ const NiceUVEditor = ({ geometry, texture, channel = 'uv', onUVChange, onSelecti
|
|
|
221
221
|
setMeshData(prev);
|
|
222
222
|
}, [undoStack, meshData]);
|
|
223
223
|
// Redo
|
|
224
|
-
const redo =
|
|
224
|
+
const redo = ke.useCallback(() => {
|
|
225
225
|
if (redoStack.length === 0)
|
|
226
226
|
return;
|
|
227
227
|
const next = redoStack[redoStack.length - 1];
|
|
@@ -232,7 +232,7 @@ const NiceUVEditor = ({ geometry, texture, channel = 'uv', onUVChange, onSelecti
|
|
|
232
232
|
setMeshData(next);
|
|
233
233
|
}, [redoStack, meshData]);
|
|
234
234
|
// Screen to UV conversion
|
|
235
|
-
const screenToUV =
|
|
235
|
+
const screenToUV = ke.useCallback((clientX, clientY) => {
|
|
236
236
|
if (!canvasRef.current)
|
|
237
237
|
return { u: 0, v: 0 };
|
|
238
238
|
const rect = canvasRef.current.getBoundingClientRect();
|
|
@@ -245,7 +245,7 @@ const NiceUVEditor = ({ geometry, texture, channel = 'uv', onUVChange, onSelecti
|
|
|
245
245
|
};
|
|
246
246
|
}, [state]);
|
|
247
247
|
// Mouse handlers
|
|
248
|
-
const handleMouseDown =
|
|
248
|
+
const handleMouseDown = ke.useCallback((e) => {
|
|
249
249
|
if (readOnly || !meshData)
|
|
250
250
|
return;
|
|
251
251
|
const uv = screenToUV(e.clientX, e.clientY);
|
|
@@ -294,7 +294,7 @@ const NiceUVEditor = ({ geometry, texture, channel = 'uv', onUVChange, onSelecti
|
|
|
294
294
|
}
|
|
295
295
|
}
|
|
296
296
|
}, [readOnly, meshData, state.activeTool, screenToUV, pushUndo]);
|
|
297
|
-
const handleMouseMove =
|
|
297
|
+
const handleMouseMove = ke.useCallback((e) => {
|
|
298
298
|
if (!dragState.active || !meshData)
|
|
299
299
|
return;
|
|
300
300
|
const uv = screenToUV(e.clientX, e.clientY);
|
|
@@ -344,7 +344,7 @@ const NiceUVEditor = ({ geometry, texture, channel = 'uv', onUVChange, onSelecti
|
|
|
344
344
|
}
|
|
345
345
|
setDragState(prev => ({ ...prev, currentPos: uv }));
|
|
346
346
|
}, [dragState, meshData, state.activeTool, screenToUV]);
|
|
347
|
-
const handleMouseUp =
|
|
347
|
+
const handleMouseUp = ke.useCallback((e) => {
|
|
348
348
|
if (!dragState.active || !meshData) {
|
|
349
349
|
setDragState(prev => ({ ...prev, active: false }));
|
|
350
350
|
return;
|
|
@@ -380,7 +380,7 @@ const NiceUVEditor = ({ geometry, texture, channel = 'uv', onUVChange, onSelecti
|
|
|
380
380
|
setDragState(prev => ({ ...prev, active: false }));
|
|
381
381
|
}, [dragState, meshData, geometry, state.activeChannel, onSelectionChange, onUVChange]);
|
|
382
382
|
// Wheel handler (zoom)
|
|
383
|
-
const handleWheel =
|
|
383
|
+
const handleWheel = ke.useCallback((e) => {
|
|
384
384
|
e.preventDefault();
|
|
385
385
|
const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1;
|
|
386
386
|
setState(prev => ({
|
|
@@ -389,7 +389,7 @@ const NiceUVEditor = ({ geometry, texture, channel = 'uv', onUVChange, onSelecti
|
|
|
389
389
|
}));
|
|
390
390
|
}, []);
|
|
391
391
|
// Keyboard handler
|
|
392
|
-
|
|
392
|
+
ke.useEffect(() => {
|
|
393
393
|
const handler = (e) => {
|
|
394
394
|
if (readOnly)
|
|
395
395
|
return;
|
|
@@ -448,7 +448,7 @@ const NiceUVEditor = ({ geometry, texture, channel = 'uv', onUVChange, onSelecti
|
|
|
448
448
|
return () => window.removeEventListener('keydown', handler);
|
|
449
449
|
}, [readOnly, meshData, undo, redo]);
|
|
450
450
|
// Tool actions
|
|
451
|
-
const handlePack =
|
|
451
|
+
const handlePack = ke.useCallback(() => {
|
|
452
452
|
if (!meshData || readOnly)
|
|
453
453
|
return;
|
|
454
454
|
pushUndo();
|
|
@@ -460,7 +460,7 @@ const NiceUVEditor = ({ geometry, texture, channel = 'uv', onUVChange, onSelecti
|
|
|
460
460
|
}
|
|
461
461
|
setMeshData({ ...meshData });
|
|
462
462
|
}, [meshData, geometry, state.activeChannel, readOnly, pushUndo, onUVChange]);
|
|
463
|
-
const handleRelax =
|
|
463
|
+
const handleRelax = ke.useCallback(() => {
|
|
464
464
|
if (!meshData || readOnly)
|
|
465
465
|
return;
|
|
466
466
|
pushUndo();
|
|
@@ -474,7 +474,7 @@ const NiceUVEditor = ({ geometry, texture, channel = 'uv', onUVChange, onSelecti
|
|
|
474
474
|
}
|
|
475
475
|
setMeshData({ ...meshData });
|
|
476
476
|
}, [meshData, geometry, state.activeChannel, readOnly, pushUndo, onUVChange]);
|
|
477
|
-
const handleProject =
|
|
477
|
+
const handleProject = ke.useCallback((type) => {
|
|
478
478
|
if (!meshData || !geometry || readOnly)
|
|
479
479
|
return;
|
|
480
480
|
pushUndo();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
2
|
+
import ke from 'react';
|
|
3
3
|
import styles from './ModelEditor.module.css.js';
|
|
4
|
-
import { c as Fe, b as Re } from '../ui/dist/NiceButton-
|
|
4
|
+
import { c as Fe, b as Re } from '../ui/dist/NiceButton-D9l39Rs7.js';
|
|
5
5
|
|
|
6
|
-
const ModelEditorLeftPanel =
|
|
6
|
+
const ModelEditorLeftPanel = ke.memo(({ api }) => {
|
|
7
7
|
const { sceneTree, selectedId, outlinerSearch, setOutlinerSearch, selectObject, rebuildTree, toggleNodeExpanded, toggleNodeVisibility, } = api;
|
|
8
8
|
const renderTreeNode = (node, depth) => {
|
|
9
9
|
// Outliner search filter
|
|
@@ -22,7 +22,7 @@ const ModelEditorLeftPanel = we.memo(({ api }) => {
|
|
|
22
22
|
node.type === "light" ? "💡" :
|
|
23
23
|
node.type === "camera" ? "📷" :
|
|
24
24
|
node.type === "helper" ? "◇" : "📁";
|
|
25
|
-
return (jsxs(
|
|
25
|
+
return (jsxs(ke.Fragment, { children: [jsxs("div", { className: `${styles.treeItem} ${selectedId === node.id ? styles.treeItemActive : ""}`, style: { paddingLeft: depth * 16 + 4 }, onClick: () => selectObject(node), children: [hasChildren ? (jsx("span", { className: styles.treeToggle, onClick: (e) => {
|
|
26
26
|
e.stopPropagation();
|
|
27
27
|
toggleNodeExpanded(node);
|
|
28
28
|
}, children: node.expanded ? "▼" : "▶" })) : (jsx("span", { className: styles.treeToggle })), jsx("span", { className: styles.treeIcon, children: icon }), jsx("span", { style: { flex: 1, overflow: "hidden", textOverflow: "ellipsis" }, children: node.name }), jsx("span", { className: styles.treeVisibility, onClick: (e) => {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
2
|
+
import ke from 'react';
|
|
3
3
|
import styles from './ModelEditor.module.css.js';
|
|
4
|
-
import { a as De, c as Fe, N as Ae } from '../ui/dist/NiceButton-
|
|
5
|
-
import { N as se } from '../ui/dist/NiceToggle-
|
|
4
|
+
import { a as De, c as Fe, N as Ae } from '../ui/dist/NiceButton-D9l39Rs7.js';
|
|
5
|
+
import { N as se } from '../ui/dist/NiceToggle-CaY1u82g.js';
|
|
6
6
|
|
|
7
|
-
const ModelEditorMenuBar =
|
|
7
|
+
const ModelEditorMenuBar = ke.memo(({ api, hasOnSaveToLibrary }) => {
|
|
8
8
|
const { editorMode, setEditorMode, fileInputRef, mergeInputRef, addMenuOpen, setAddMenuOpen, addPrimitive, addSceneLight, addCameraObject, addEmpty, selectedNode, duplicateSelected, deleteSelected, exportGLTF, exportOBJ, exportSTL, exportPLY, exportUSDZ, saveToLibrary, clearScene, showGrid, setShowGrid, showAxes, setShowAxes, wireframe, setWireframe, showSkeleton, setShowSkeleton, showLightHelpers, setShowLightHelpers, bgColor, setBgColor, } = api;
|
|
9
9
|
return (jsxs("div", { className: styles.menuBar, children: [jsx(De, { className: styles.modeSelect, value: editorMode, onChange: (val) => setEditorMode(val), options: [
|
|
10
10
|
{ value: "object", label: "Object Mode" },
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
2
|
+
import ke from 'react';
|
|
3
3
|
import * as THREE from 'three';
|
|
4
4
|
import styles from './ModelEditor.module.css.js';
|
|
5
5
|
import { DEG } from './modelEditorTypes.js';
|
|
6
6
|
import { Vec3Row, Vec3RowDeg, MaterialCard } from './ModelEditorSubComponents.js';
|
|
7
|
-
import { c as Fe, b as Re, N as Ae } from '../ui/dist/NiceButton-
|
|
8
|
-
import { U as Dn } from '../ui/dist/NicePinCodeInput-
|
|
9
|
-
import { N as se, a as ie } from '../ui/dist/NiceToggle-
|
|
7
|
+
import { c as Fe, b as Re, N as Ae } from '../ui/dist/NiceButton-D9l39Rs7.js';
|
|
8
|
+
import { U as Dn } from '../ui/dist/NicePinCodeInput-CrMfdxxc.js';
|
|
9
|
+
import { N as se, a as ie } from '../ui/dist/NiceToggle-CaY1u82g.js';
|
|
10
10
|
|
|
11
|
-
const ModelEditorRightPanel =
|
|
11
|
+
const ModelEditorRightPanel = ke.memo(({ api }) => {
|
|
12
12
|
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;
|
|
13
13
|
return (jsxs("div", { className: styles.rightPanel, children: [jsx("div", { className: styles.propTabs, children: ["object", "material", "world", "modifiers", "physics"].map((t) => (jsx(Fe, { className: styles.propTabBtn, variant: propTab === t ? "primary" : "ghost", size: "sm", onClick: () => setPropTab(t), title: t.charAt(0).toUpperCase() + t.slice(1), children: t === "object" ? "🔧" : t === "material" ? "🎨" : t === "world" ? "🌍" : t === "modifiers" ? "🔩" : "⚡" }, t))) }), propTab === "object" && (jsxs(Fragment, { children: [jsxs("div", { className: styles.panelSection, children: [jsx("div", { className: styles.panelTitle, children: "\uD83D\uDD27 Transform" }), jsx("div", { className: styles.panelContent, children: selectedNode ? (jsxs(Fragment, { children: [jsxs("div", { className: styles.propRow, children: [jsx("span", { className: styles.propLabel, children: "Name" }), jsx(Re, { className: styles.propInput, value: selectedNode.name, onChange: (val) => {
|
|
14
14
|
selectedNode.object.name = val;
|
|
@@ -3,8 +3,8 @@ import { useState } from 'react';
|
|
|
3
3
|
import * as THREE from 'three';
|
|
4
4
|
import styles from './ModelEditor.module.css.js';
|
|
5
5
|
import { DEG } from './modelEditorTypes.js';
|
|
6
|
-
import { b as Re, N as Ae, a as De } from '../ui/dist/NiceButton-
|
|
7
|
-
import { U as Dn } from '../ui/dist/NicePinCodeInput-
|
|
6
|
+
import { b as Re, N as Ae, a as De } from '../ui/dist/NiceButton-D9l39Rs7.js';
|
|
7
|
+
import { U as Dn } from '../ui/dist/NicePinCodeInput-CrMfdxxc.js';
|
|
8
8
|
|
|
9
9
|
/* ═══════════════════════════════════════════
|
|
10
10
|
Sub-components
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
2
|
+
import ke from 'react';
|
|
3
3
|
import styles from './ModelEditor.module.css.js';
|
|
4
4
|
import { fmtTime } from './modelEditorTypes.js';
|
|
5
|
-
import { c as Fe } from '../ui/dist/NiceButton-
|
|
6
|
-
import { U as Dn } from '../ui/dist/NicePinCodeInput-
|
|
5
|
+
import { c as Fe } from '../ui/dist/NiceButton-D9l39Rs7.js';
|
|
6
|
+
import { U as Dn } from '../ui/dist/NicePinCodeInput-CrMfdxxc.js';
|
|
7
7
|
|
|
8
|
-
const ModelEditorTimeline =
|
|
8
|
+
const ModelEditorTimeline = ke.memo(({ api }) => {
|
|
9
9
|
const { bottomCollapsed, setBottomCollapsed, animations, activeAnimIdx, isPlaying, animTime, animDuration, animSpeed, setAnimSpeed, loopAnim, setLoopAnim, seekAnim, togglePlay, stopAnim, playClip, mergeInputRef, } = api;
|
|
10
10
|
return (jsxs("div", { className: `${styles.bottomPanel} ${bottomCollapsed ? styles.bottomPanelCollapsed : ""}`, children: [jsxs("div", { className: styles.bottomPanelHeader, children: [jsx("span", { className: styles.bottomToggle, onClick: () => setBottomCollapsed((c) => !c), children: bottomCollapsed ? "▶" : "▼" }), jsxs("span", { className: styles.bottomPanelTitle, onClick: () => setBottomCollapsed((c) => !c), children: ["Animation (", animations.length, " clip", animations.length !== 1 ? "s" : "", ")"] }), jsx("div", { className: styles.menuSep }), jsxs("div", { className: styles.transportBar, children: [jsx(Fe, { className: styles.transportBtn, variant: "ghost", size: "sm", onClick: () => seekAnim(0), title: "Go to start", children: "\u23EE" }), jsx(Fe, { className: styles.transportBtn, variant: isPlaying ? "primary" : "ghost", size: "sm", onClick: togglePlay, title: "Play/Pause (Space)", children: isPlaying ? "⏸" : "▶" }), jsx(Fe, { className: styles.transportBtn, variant: "ghost", size: "sm", onClick: stopAnim, title: "Stop", children: "\u23F9" }), jsx(Fe, { className: styles.transportBtn, variant: loopAnim ? "primary" : "ghost", size: "sm", onClick: () => setLoopAnim((v) => !v), title: "Loop", children: "\uD83D\uDD01" })] }), jsxs("span", { className: styles.transportTime, children: [fmtTime(animTime), " / ", fmtTime(animDuration)] }), jsx("div", { className: styles.menuSep }), jsx("label", { className: styles.menuLabel, children: "Speed" }), jsx(Dn, { min: 0.1, max: 3, step: 0.1, value: animSpeed, onChange: (val) => setAnimSpeed(val), style: { width: 60 } }), jsxs("span", { className: styles.menuLabel, children: [animSpeed.toFixed(1), "\u00D7"] })] }), !bottomCollapsed && (jsxs("div", { className: styles.animListArea, children: [jsxs("div", { className: styles.animList, children: [animations.length === 0 && (jsx("div", { style: { color: "#666", fontSize: 10, padding: 8 }, children: "No animations loaded" })), animations.map((anim, i) => (jsxs("div", { className: `${styles.animItem} ${i === activeAnimIdx ? styles.animItemActive : ""}`, onClick: () => playClip(i), children: [jsx("span", { children: anim.name }), jsxs("span", { className: styles.animDuration, children: [anim.duration.toFixed(1), "s"] })] }, `${anim.name}-${i}`))), jsx("div", { style: { padding: "4px 8px" }, children: jsx(Fe, { className: styles.btnSecondary, variant: "ghost", size: "sm", style: { width: "100%", fontSize: 10 }, onClick: () => { var _a; return (_a = mergeInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, children: "+ Add Animation File" }) })] }), jsxs("div", { className: styles.timelineArea, children: [jsxs("div", { className: styles.timelineRuler, children: [animDuration > 0 &&
|
|
11
11
|
Array.from({ length: Math.ceil(animDuration) + 1 }, (_, i) => {
|
|
12
12
|
const pct = (i / animDuration) * 100;
|
|
13
|
-
return (jsxs(
|
|
13
|
+
return (jsxs(ke.Fragment, { children: [jsx("div", { className: styles.rulerTick, style: { left: `${pct}%` } }), jsxs("span", { className: styles.rulerLabel, style: { left: `${pct}%` }, children: [i, "s"] })] }, i));
|
|
14
14
|
}), animDuration > 0 && (jsx("div", { className: styles.playhead, style: {
|
|
15
15
|
left: `${(animTime / animDuration) * 100}%`,
|
|
16
16
|
height: "100%",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
2
|
+
import ke from 'react';
|
|
3
3
|
import styles from './ModelEditor.module.css.js';
|
|
4
|
-
import { c as Fe } from '../ui/dist/NiceButton-
|
|
4
|
+
import { c as Fe } from '../ui/dist/NiceButton-D9l39Rs7.js';
|
|
5
5
|
|
|
6
|
-
const ModelEditorToolbar =
|
|
6
|
+
const ModelEditorToolbar = ke.memo(({ api }) => {
|
|
7
7
|
const { transformMode, setTransformMode, snapEnabled, setSnapEnabled, gizmoSpace, setGizmoSpace, rootObjectRef, focusOnObject, setCameraPreset, deleteSelected, duplicateSelected, selectedNode, } = api;
|
|
8
8
|
return (jsxs("div", { className: styles.toolbar, children: [jsx(Fe, { className: styles.toolBtn, variant: transformMode === "translate" ? "primary" : "ghost", size: "sm", onClick: () => setTransformMode("translate"), title: "Translate (G)", children: "\u2725" }), jsx(Fe, { className: styles.toolBtn, variant: transformMode === "rotate" ? "primary" : "ghost", size: "sm", onClick: () => setTransformMode("rotate"), title: "Rotate (R)", children: "\u21BB" }), jsx(Fe, { className: styles.toolBtn, variant: transformMode === "scale" ? "primary" : "ghost", size: "sm", onClick: () => setTransformMode("scale"), title: "Scale (S)", children: "\u2B21" }), jsx("div", { className: styles.toolSep }), jsx(Fe, { className: styles.toolBtn, variant: snapEnabled ? "primary" : "ghost", size: "sm", onClick: () => setSnapEnabled((v) => !v), title: `Snap to Grid (${snapEnabled ? "ON" : "OFF"})`, children: "\uD83E\uDDF2" }), jsx(Fe, { className: styles.toolBtn, variant: "ghost", size: "sm", onClick: () => setGizmoSpace((s) => (s === "local" ? "world" : "local")), title: `Orientation: ${gizmoSpace}`, children: gizmoSpace === "local" ? "🔶" : "🌐" }), jsx("div", { className: styles.toolSep }), jsx(Fe, { className: styles.toolBtn, variant: "ghost", size: "sm", onClick: () => rootObjectRef.current && focusOnObject(rootObjectRef.current), title: "Focus (F)", children: "\u25CE" }), jsx(Fe, { className: styles.toolBtn, variant: "ghost", size: "sm", onClick: () => setCameraPreset("front"), title: "Front view (Numpad 1)", children: "1" }), jsx(Fe, { className: styles.toolBtn, variant: "ghost", size: "sm", onClick: () => setCameraPreset("right"), title: "Right view (Numpad 3)", children: "3" }), jsx(Fe, { className: styles.toolBtn, variant: "ghost", size: "sm", onClick: () => setCameraPreset("top"), title: "Top view (Numpad 7)", children: "7" }), jsx("div", { className: styles.toolSep }), jsx(Fe, { className: styles.toolBtn, variant: "ghost", size: "sm", onClick: deleteSelected, title: "Delete selected (Del)", children: "\uD83D\uDDD1" }), jsx(Fe, { className: styles.toolBtn, variant: "ghost", size: "sm", onClick: duplicateSelected, title: "Duplicate (Shift+D)", disabled: !selectedNode, children: "\uD83D\uDCCB" })] }));
|
|
9
9
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
2
|
+
import ke from 'react';
|
|
3
3
|
import styles from './ModelEditor.module.css.js';
|
|
4
4
|
|
|
5
|
-
const ModelEditorViewport =
|
|
5
|
+
const ModelEditorViewport = ke.memo(({ api }) => {
|
|
6
6
|
const { mountRef, dragOver, handleDragOver, handleDragLeave, handleDrop, handleViewportClick, handleContextMenu, editorMode, polyCount, meshCount, boneCount, shadingMode, setShadingMode, gizmoSpace, setGizmoSpace, contextMenu, closeContextMenu, addPrimitive, addSceneLight, duplicateSelected, deleteSelected, selectedNode, rootObjectRef, focusOnObject, snapEnabled, setSnapEnabled, } = api;
|
|
7
7
|
return (jsxs(Fragment, { children: [jsxs("div", { ref: mountRef, className: `${styles.viewportContainer} ${dragOver ? styles.dragOver : ""}`, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, onClick: handleViewportClick, onContextMenu: handleContextMenu, children: [jsxs("div", { className: styles.viewportOverlay, children: [jsxs("span", { className: styles.viewportBadge, children: [editorMode.toUpperCase(), " MODE"] }), jsxs("span", { className: styles.viewportBadge, children: [polyCount.toLocaleString(), " tris \u00B7 ", meshCount, " meshes \u00B7 ", boneCount, " bones"] })] }), jsx("div", { className: styles.viewportShadingBar, children: ["wireframe", "solid", "material", "rendered"].map((m) => (jsx("button", { className: `${styles.shadingBtn} ${shadingMode === m ? styles.shadingBtnActive : ""}`, onClick: (e) => { e.stopPropagation(); setShadingMode(m); }, title: m.charAt(0).toUpperCase() + m.slice(1), children: m === "wireframe" ? "◇" : m === "solid" ? "◆" : m === "material" ? "🎨" : "☀" }, m))) }), jsx("div", { className: styles.viewportGizmoInfo, children: jsx("button", { className: styles.shadingBtn, onClick: (e) => {
|
|
8
8
|
e.stopPropagation();
|
|
@@ -2,8 +2,8 @@ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
|
2
2
|
import { useState, useRef, useCallback } from 'react';
|
|
3
3
|
import styles from './ModelViewer.module.css.js';
|
|
4
4
|
import { useModelViewer } from './useModelViewer.js';
|
|
5
|
-
import { c as Fe, a as De } from '../ui/dist/NiceButton-
|
|
6
|
-
import { U as Dn } from '../ui/dist/NicePinCodeInput-
|
|
5
|
+
import { c as Fe, a as De } from '../ui/dist/NiceButton-D9l39Rs7.js';
|
|
6
|
+
import { U as Dn } from '../ui/dist/NicePinCodeInput-CrMfdxxc.js';
|
|
7
7
|
|
|
8
8
|
const NAV_LABELS = {
|
|
9
9
|
orbit: '🌍 Orbit',
|