@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,36 +1,234 @@
1
- 'use strict';
2
-
3
- var jsxRuntime = require('react/jsx-runtime');
4
- var ui = require('@nice2dev/ui');
5
- var React = require('react');
6
- var i18n = require('../core/i18n.js');
7
- var ModelEditor_module = require('./ModelEditor.module.css.js');
8
- var modelEditorTypes = require('./modelEditorTypes.js');
9
-
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 i18n = require("../core/i18n.js");
7
+ const ModelEditor_module = require("./ModelEditor.module.css.js");
8
+ const modelEditorTypes = require("./modelEditorTypes.js");
10
9
  const ModelEditorTimeline = /* @__PURE__ */ Object.assign(
11
- /* @__PURE__ */ React.memo(({ api }) => {
10
+ /* @__PURE__ */ React.memo(({ api }) => {
12
11
  const { t } = i18n.useNiceTranslation();
13
- const { bottomCollapsed, setBottomCollapsed, animations, activeAnimIdx, isPlaying, animTime, animDuration, animSpeed, setAnimSpeed, loopAnim, setLoopAnim, seekAnim, togglePlay, stopAnim, playClip, mergeInputRef, } = api;
14
- return (jsxRuntime.jsxs("div", { className: `${ModelEditor_module.bottomPanel} ${bottomCollapsed ? ModelEditor_module.bottomPanelCollapsed : ''}`, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.bottomPanelHeader, children: [jsxRuntime.jsx("span", { role: "presentation", className: ModelEditor_module.bottomToggle, onClick: () => setBottomCollapsed((c) => !c), children: jsxRuntime.jsx(ui.NiceIcon, { name: bottomCollapsed ? 'chevron-right' : 'chevron-down', size: 14 }) }), jsxRuntime.jsx("span", { role: "button", tabIndex: 0, "aria-expanded": !bottomCollapsed, onKeyDown: ui.clickOnActivationKey, className: ModelEditor_module.bottomPanelTitle, onClick: () => setBottomCollapsed((c) => !c), children: animations.length !== 1
15
- ? t('modelEditorTimeline.animationClipsMany', 'Animation ({animations} clips)').replace('{animations}', String(animations.length))
16
- : t('modelEditorTimeline.animationClipsOne', 'Animation ({animations} clip)').replace('{animations}', String(animations.length)) }), jsxRuntime.jsx("div", { className: ModelEditor_module.menuSep }), jsxRuntime.jsxs("div", { className: ModelEditor_module.transportBar, children: [jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.transportBtn, variant: "ghost", size: "sm", onClick: () => seekAnim(0), title: t('modelEditorTimeline.goToStart', 'Go to start'), "aria-label": t('modelEditorTimeline.goToStart', 'Go to start'), children: jsxRuntime.jsx(ui.NiceIcon, { name: "chevron-left", size: 16 }) }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.transportBtn, variant: isPlaying ? 'primary' : 'ghost', size: "sm", onClick: togglePlay, title: t('modelEditorTimeline.playPauseSpace', 'Play/Pause (Space)'), "aria-label": t('modelEditorTimeline.playPauseSpace', 'Play/Pause (Space)'), children: jsxRuntime.jsx(ui.NiceIcon, { name: isPlaying ? 'pause' : 'play', size: 16 }) }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.transportBtn, variant: "ghost", size: "sm", onClick: stopAnim, title: t('modelEditorTimeline.stop', 'Stop'), "aria-label": t('modelEditorTimeline.stop', 'Stop'), children: jsxRuntime.jsx(ui.NiceIcon, { name: "stop", size: 16 }) }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.transportBtn, variant: loopAnim ? 'primary' : 'ghost', size: "sm", onClick: () => setLoopAnim((v) => !v), title: t('modelEditorTimeline.loop', 'Loop'), "aria-label": t('modelEditorTimeline.loop', 'Loop'), children: jsxRuntime.jsx(ui.NiceIcon, { name: "refresh", size: 16 }) })] }), jsxRuntime.jsxs("span", { className: ModelEditor_module.transportTime, children: [modelEditorTypes.fmtTime(animTime), " / ", modelEditorTypes.fmtTime(animDuration)] }), jsxRuntime.jsx("div", { className: ModelEditor_module.menuSep }), jsxRuntime.jsx("label", { className: ModelEditor_module.menuLabel, children: t('modelEditorTimeline.speed', 'Speed') }), jsxRuntime.jsx(ui.NiceSlider, { min: 0.1, max: 3, step: 0.1, value: animSpeed, onChange: (val) => setAnimSpeed(val), style: { width: 60 } }), jsxRuntime.jsxs("span", { className: ModelEditor_module.menuLabel, children: [animSpeed.toFixed(1), "\u00D7"] })] }), !bottomCollapsed && (jsxRuntime.jsxs("div", { className: ModelEditor_module.animListArea, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.animList, children: [animations.length === 0 && (jsxRuntime.jsx("div", { style: { color: 'var(--nice-text-secondary, #666)', fontSize: 10, padding: 8 }, children: t('modelEditorTimeline.noAnimationsLoaded', 'No animations loaded') })), animations.map((anim, i) => (jsxRuntime.jsxs("div", { role: "button", tabIndex: 0, onKeyDown: ui.clickOnActivationKey, className: `${ModelEditor_module.animItem} ${i === activeAnimIdx ? ModelEditor_module.animItemActive : ''}`, onClick: () => playClip(i), children: [jsxRuntime.jsx("span", { children: anim.name }), jsxRuntime.jsxs("span", { className: ModelEditor_module.animDuration, children: [anim.duration.toFixed(1), "s"] })] }, `${anim.name}-${i}`))), jsxRuntime.jsx("div", { style: { padding: '4px 8px' }, children: jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.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: t('modelEditorTimeline.addAnimationFile', '+ Add Animation File') }) })] }), jsxRuntime.jsxs("div", { className: ModelEditor_module.timelineArea, children: [jsxRuntime.jsxs("div", { className: ModelEditor_module.timelineRuler, children: [animDuration > 0 &&
17
- Array.from({ length: Math.ceil(animDuration) + 1 }, (_, i) => {
18
- const pct = (i / animDuration) * 100;
19
- return (jsxRuntime.jsxs(React.Fragment, { children: [jsxRuntime.jsx("div", { className: ModelEditor_module.rulerTick, style: { left: `${pct}%` } }), jsxRuntime.jsxs("span", { className: ModelEditor_module.rulerLabel, style: { left: `${pct}%` }, children: [i, "s"] })] }, i));
20
- }), animDuration > 0 && (jsxRuntime.jsx("div", { className: ModelEditor_module.playhead, style: {
21
- left: `${(animTime / animDuration) * 100}%`,
22
- height: '100%',
23
- }, children: jsxRuntime.jsx("div", { className: ModelEditor_module.playheadHandle }) }))] }), jsxRuntime.jsx("div", { role: "presentation", className: ModelEditor_module.timelineTracks, style: { height: 140, cursor: 'pointer' }, onClick: (e) => {
24
- if (animDuration <= 0) {
25
- return;
26
- }
27
- const rect = e.currentTarget.getBoundingClientRect();
28
- const pct = (e.clientX - rect.left) / rect.width;
29
- seekAnim(Math.max(0, Math.min(animDuration, pct * animDuration)));
30
- }, children: animDuration > 0 && (jsxRuntime.jsx("div", { className: ModelEditor_module.playhead, style: {
31
- left: `${(animTime / animDuration) * 100}%`,
32
- height: '100%',
33
- } })) })] })] }))] }));
34
- }), { displayName: 'ModelEditorTimeline' });
35
-
36
- module.exports = ModelEditorTimeline;
12
+ const {
13
+ bottomCollapsed,
14
+ setBottomCollapsed,
15
+ animations,
16
+ activeAnimIdx,
17
+ isPlaying,
18
+ animTime,
19
+ animDuration,
20
+ animSpeed,
21
+ setAnimSpeed,
22
+ loopAnim,
23
+ setLoopAnim,
24
+ seekAnim,
25
+ togglePlay,
26
+ stopAnim,
27
+ playClip,
28
+ mergeInputRef
29
+ } = api;
30
+ return /* @__PURE__ */ jsxRuntime.jsxs(
31
+ "div",
32
+ {
33
+ className: `${ModelEditor_module.default.bottomPanel} ${bottomCollapsed ? ModelEditor_module.default.bottomPanelCollapsed : ""}`,
34
+ children: [
35
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.bottomPanelHeader, children: [
36
+ /* @__PURE__ */ jsxRuntime.jsx(
37
+ "span",
38
+ {
39
+ role: "presentation",
40
+ className: ModelEditor_module.default.bottomToggle,
41
+ onClick: () => setBottomCollapsed((c) => !c),
42
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: bottomCollapsed ? "chevron-right" : "chevron-down", size: 14 })
43
+ }
44
+ ),
45
+ /* @__PURE__ */ jsxRuntime.jsx(
46
+ "span",
47
+ {
48
+ role: "button",
49
+ tabIndex: 0,
50
+ "aria-expanded": !bottomCollapsed,
51
+ onKeyDown: ui.clickOnActivationKey,
52
+ className: ModelEditor_module.default.bottomPanelTitle,
53
+ onClick: () => setBottomCollapsed((c) => !c),
54
+ children: animations.length !== 1 ? t(
55
+ "modelEditorTimeline.animationClipsMany",
56
+ "Animation ({animations} clips)"
57
+ ).replace("{animations}", String(animations.length)) : t("modelEditorTimeline.animationClipsOne", "Animation ({animations} clip)").replace(
58
+ "{animations}",
59
+ String(animations.length)
60
+ )
61
+ }
62
+ ),
63
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.menuSep }),
64
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.transportBar, children: [
65
+ /* @__PURE__ */ jsxRuntime.jsx(
66
+ ui.NiceButton,
67
+ {
68
+ className: ModelEditor_module.default.transportBtn,
69
+ variant: "ghost",
70
+ size: "sm",
71
+ onClick: () => seekAnim(0),
72
+ title: t("modelEditorTimeline.goToStart", "Go to start"),
73
+ "aria-label": t("modelEditorTimeline.goToStart", "Go to start"),
74
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "chevron-left", size: 16 })
75
+ }
76
+ ),
77
+ /* @__PURE__ */ jsxRuntime.jsx(
78
+ ui.NiceButton,
79
+ {
80
+ className: ModelEditor_module.default.transportBtn,
81
+ variant: isPlaying ? "primary" : "ghost",
82
+ size: "sm",
83
+ onClick: togglePlay,
84
+ title: t("modelEditorTimeline.playPauseSpace", "Play/Pause (Space)"),
85
+ "aria-label": t("modelEditorTimeline.playPauseSpace", "Play/Pause (Space)"),
86
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: isPlaying ? "pause" : "play", size: 16 })
87
+ }
88
+ ),
89
+ /* @__PURE__ */ jsxRuntime.jsx(
90
+ ui.NiceButton,
91
+ {
92
+ className: ModelEditor_module.default.transportBtn,
93
+ variant: "ghost",
94
+ size: "sm",
95
+ onClick: stopAnim,
96
+ title: t("modelEditorTimeline.stop", "Stop"),
97
+ "aria-label": t("modelEditorTimeline.stop", "Stop"),
98
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "stop", size: 16 })
99
+ }
100
+ ),
101
+ /* @__PURE__ */ jsxRuntime.jsx(
102
+ ui.NiceButton,
103
+ {
104
+ className: ModelEditor_module.default.transportBtn,
105
+ variant: loopAnim ? "primary" : "ghost",
106
+ size: "sm",
107
+ onClick: () => setLoopAnim((v) => !v),
108
+ title: t("modelEditorTimeline.loop", "Loop"),
109
+ "aria-label": t("modelEditorTimeline.loop", "Loop"),
110
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "refresh", size: 16 })
111
+ }
112
+ )
113
+ ] }),
114
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: ModelEditor_module.default.transportTime, children: [
115
+ modelEditorTypes.fmtTime(animTime),
116
+ " / ",
117
+ modelEditorTypes.fmtTime(animDuration)
118
+ ] }),
119
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.menuSep }),
120
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: ModelEditor_module.default.menuLabel, children: t("modelEditorTimeline.speed", "Speed") }),
121
+ /* @__PURE__ */ jsxRuntime.jsx(
122
+ ui.NiceSlider,
123
+ {
124
+ min: 0.1,
125
+ max: 3,
126
+ step: 0.1,
127
+ value: animSpeed,
128
+ onChange: (val) => setAnimSpeed(val),
129
+ style: { width: 60 }
130
+ }
131
+ ),
132
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: ModelEditor_module.default.menuLabel, children: [
133
+ animSpeed.toFixed(1),
134
+ "×"
135
+ ] })
136
+ ] }),
137
+ !bottomCollapsed && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.animListArea, children: [
138
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.animList, children: [
139
+ animations.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(
140
+ "div",
141
+ {
142
+ style: { color: "var(--nice-text-secondary, #666)", fontSize: 10, padding: 8 },
143
+ children: t("modelEditorTimeline.noAnimationsLoaded", "No animations loaded")
144
+ }
145
+ ),
146
+ animations.map((anim, i) => /* @__PURE__ */ jsxRuntime.jsxs(
147
+ "div",
148
+ {
149
+ role: "button",
150
+ tabIndex: 0,
151
+ onKeyDown: ui.clickOnActivationKey,
152
+ className: `${ModelEditor_module.default.animItem} ${i === activeAnimIdx ? ModelEditor_module.default.animItemActive : ""}`,
153
+ onClick: () => playClip(i),
154
+ children: [
155
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: anim.name }),
156
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: ModelEditor_module.default.animDuration, children: [
157
+ anim.duration.toFixed(1),
158
+ "s"
159
+ ] })
160
+ ]
161
+ },
162
+ `${anim.name}-${i}`
163
+ )),
164
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "4px 8px" }, children: /* @__PURE__ */ jsxRuntime.jsx(
165
+ ui.NiceButton,
166
+ {
167
+ className: ModelEditor_module.default.btnSecondary,
168
+ variant: "ghost",
169
+ size: "sm",
170
+ style: { width: "100%", fontSize: 10 },
171
+ onClick: () => mergeInputRef.current?.click(),
172
+ children: t("modelEditorTimeline.addAnimationFile", "+ Add Animation File")
173
+ }
174
+ ) })
175
+ ] }),
176
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.timelineArea, children: [
177
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.timelineRuler, children: [
178
+ animDuration > 0 && Array.from({ length: Math.ceil(animDuration) + 1 }, (_, i) => {
179
+ const pct = i / animDuration * 100;
180
+ return /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
181
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.rulerTick, style: { left: `${pct}%` } }),
182
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: ModelEditor_module.default.rulerLabel, style: { left: `${pct}%` }, children: [
183
+ i,
184
+ "s"
185
+ ] })
186
+ ] }, i);
187
+ }),
188
+ animDuration > 0 && /* @__PURE__ */ jsxRuntime.jsx(
189
+ "div",
190
+ {
191
+ className: ModelEditor_module.default.playhead,
192
+ style: {
193
+ left: `${animTime / animDuration * 100}%`,
194
+ height: "100%"
195
+ },
196
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.playheadHandle })
197
+ }
198
+ )
199
+ ] }),
200
+ /* @__PURE__ */ jsxRuntime.jsx(
201
+ "div",
202
+ {
203
+ role: "presentation",
204
+ className: ModelEditor_module.default.timelineTracks,
205
+ style: { height: 140, cursor: "pointer" },
206
+ onClick: (e) => {
207
+ if (animDuration <= 0) {
208
+ return;
209
+ }
210
+ const rect = e.currentTarget.getBoundingClientRect();
211
+ const pct = (e.clientX - rect.left) / rect.width;
212
+ seekAnim(Math.max(0, Math.min(animDuration, pct * animDuration)));
213
+ },
214
+ children: animDuration > 0 && /* @__PURE__ */ jsxRuntime.jsx(
215
+ "div",
216
+ {
217
+ className: ModelEditor_module.default.playhead,
218
+ style: {
219
+ left: `${animTime / animDuration * 100}%`,
220
+ height: "100%"
221
+ }
222
+ }
223
+ )
224
+ }
225
+ )
226
+ ] })
227
+ ] })
228
+ ]
229
+ }
230
+ );
231
+ }),
232
+ { displayName: "ModelEditorTimeline" }
233
+ );
234
+ exports.default = ModelEditorTimeline;
@@ -1,16 +1,172 @@
1
- 'use strict';
2
-
3
- var jsxRuntime = require('react/jsx-runtime');
4
- var ui = require('@nice2dev/ui');
5
- var React = require('react');
6
- var i18n = require('../core/i18n.js');
7
- var ModelEditor_module = require('./ModelEditor.module.css.js');
8
-
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 i18n = require("../core/i18n.js");
7
+ const ModelEditor_module = require("./ModelEditor.module.css.js");
9
8
  const ModelEditorToolbar = /* @__PURE__ */ Object.assign(
10
- /* @__PURE__ */ React.memo(({ api }) => {
9
+ /* @__PURE__ */ React.memo(({ api }) => {
11
10
  const { t } = i18n.useNiceTranslation();
12
- const { transformMode, setTransformMode, snapEnabled, setSnapEnabled, gizmoSpace, setGizmoSpace, rootObjectRef, focusOnObject, setCameraPreset, deleteSelected, duplicateSelected, selectedNode, } = api;
13
- return (jsxRuntime.jsxs("div", { className: ModelEditor_module.toolbar, children: [jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.toolBtn, variant: transformMode === 'translate' ? 'primary' : 'ghost', size: "sm", onClick: () => setTransformMode('translate'), title: t('modelEditorToolbar.translateG', 'Translate (G)'), "aria-label": t('modelEditorToolbar.translateG', 'Translate (G)'), children: jsxRuntime.jsx(ui.NiceIcon, { name: "move", size: 16 }) }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.toolBtn, variant: transformMode === 'rotate' ? 'primary' : 'ghost', size: "sm", onClick: () => setTransformMode('rotate'), title: t('modelEditorToolbar.rotateR', 'Rotate (R)'), "aria-label": t('modelEditorToolbar.rotateR', 'Rotate (R)'), children: jsxRuntime.jsx(ui.NiceIcon, { name: "refresh", size: 16 }) }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.toolBtn, variant: transformMode === 'scale' ? 'primary' : 'ghost', size: "sm", onClick: () => setTransformMode('scale'), title: t('modelEditorToolbar.scaleS', 'Scale (S)'), "aria-label": t('modelEditorToolbar.scaleS', 'Scale (S)'), children: jsxRuntime.jsx(ui.NiceIcon, { name: "hexagon", size: 16 }) }), jsxRuntime.jsx("div", { className: ModelEditor_module.toolSep }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.toolBtn, variant: snapEnabled ? 'primary' : 'ghost', size: "sm", onClick: () => setSnapEnabled((v) => !v), title: t('modelEditorToolbar.snapToGridState', 'Snap to Grid ({state})').replace('{state}', snapEnabled ? t('modelEditorToolbar.on', 'ON') : t('modelEditorToolbar.off', 'OFF')), "aria-label": t('modelEditorToolbar.snapToGrid', 'Snap to Grid'), children: jsxRuntime.jsx(ui.NiceIcon, { name: "grid", size: 16 }) }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.toolBtn, variant: "ghost", size: "sm", onClick: () => setGizmoSpace((s) => (s === 'local' ? 'world' : 'local')), title: t('modelEditorToolbar.orientation', 'Orientation: {gizmoSpace}').replace('{gizmoSpace}', String(gizmoSpace)), "aria-label": t('modelEditorToolbar.orientation', 'Orientation: {gizmoSpace}').replace('{gizmoSpace}', String(gizmoSpace)), children: jsxRuntime.jsx(ui.NiceIcon, { name: gizmoSpace === 'local' ? 'target' : 'globe', size: 16 }) }), jsxRuntime.jsx("div", { className: ModelEditor_module.toolSep }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.toolBtn, variant: "ghost", size: "sm", onClick: () => rootObjectRef.current && focusOnObject(rootObjectRef.current), title: t('modelEditorToolbar.focusF', 'Focus (F)'), "aria-label": t('modelEditorToolbar.focusF', 'Focus (F)'), children: jsxRuntime.jsx(ui.NiceIcon, { name: "target", size: 16 }) }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.toolBtn, variant: "ghost", size: "sm", onClick: () => setCameraPreset('front'), title: t('modelEditorToolbar.frontViewNumpad1', 'Front view (Numpad 1)'), children: "1" }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.toolBtn, variant: "ghost", size: "sm", onClick: () => setCameraPreset('right'), title: t('modelEditorToolbar.rightViewNumpad3', 'Right view (Numpad 3)'), children: "3" }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.toolBtn, variant: "ghost", size: "sm", onClick: () => setCameraPreset('top'), title: t('modelEditorToolbar.topViewNumpad7', 'Top view (Numpad 7)'), children: "7" }), jsxRuntime.jsx("div", { className: ModelEditor_module.toolSep }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.toolBtn, variant: "ghost", size: "sm", onClick: deleteSelected, title: t('modelEditorToolbar.deleteSelectedDel', 'Delete selected (Del)'), "aria-label": t('modelEditorToolbar.deleteSelectedDel', 'Delete selected (Del)'), children: jsxRuntime.jsx(ui.NiceIcon, { name: "trash", size: 16 }) }), jsxRuntime.jsx(ui.NiceButton, { className: ModelEditor_module.toolBtn, variant: "ghost", size: "sm", onClick: duplicateSelected, title: t('modelEditorToolbar.duplicateShiftD', 'Duplicate (Shift+D)'), disabled: !selectedNode, "aria-label": t('modelEditorToolbar.duplicateShiftD', 'Duplicate (Shift+D)'), children: jsxRuntime.jsx(ui.NiceIcon, { name: "clipboard", size: 16 }) })] }));
14
- }), { displayName: 'ModelEditorToolbar' });
15
-
16
- module.exports = ModelEditorToolbar;
11
+ const {
12
+ transformMode,
13
+ setTransformMode,
14
+ snapEnabled,
15
+ setSnapEnabled,
16
+ gizmoSpace,
17
+ setGizmoSpace,
18
+ rootObjectRef,
19
+ focusOnObject,
20
+ setCameraPreset,
21
+ deleteSelected,
22
+ duplicateSelected,
23
+ selectedNode
24
+ } = api;
25
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ModelEditor_module.default.toolbar, children: [
26
+ /* @__PURE__ */ jsxRuntime.jsx(
27
+ ui.NiceButton,
28
+ {
29
+ className: ModelEditor_module.default.toolBtn,
30
+ variant: transformMode === "translate" ? "primary" : "ghost",
31
+ size: "sm",
32
+ onClick: () => setTransformMode("translate"),
33
+ title: t("modelEditorToolbar.translateG", "Translate (G)"),
34
+ "aria-label": t("modelEditorToolbar.translateG", "Translate (G)"),
35
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "move", size: 16 })
36
+ }
37
+ ),
38
+ /* @__PURE__ */ jsxRuntime.jsx(
39
+ ui.NiceButton,
40
+ {
41
+ className: ModelEditor_module.default.toolBtn,
42
+ variant: transformMode === "rotate" ? "primary" : "ghost",
43
+ size: "sm",
44
+ onClick: () => setTransformMode("rotate"),
45
+ title: t("modelEditorToolbar.rotateR", "Rotate (R)"),
46
+ "aria-label": t("modelEditorToolbar.rotateR", "Rotate (R)"),
47
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "refresh", size: 16 })
48
+ }
49
+ ),
50
+ /* @__PURE__ */ jsxRuntime.jsx(
51
+ ui.NiceButton,
52
+ {
53
+ className: ModelEditor_module.default.toolBtn,
54
+ variant: transformMode === "scale" ? "primary" : "ghost",
55
+ size: "sm",
56
+ onClick: () => setTransformMode("scale"),
57
+ title: t("modelEditorToolbar.scaleS", "Scale (S)"),
58
+ "aria-label": t("modelEditorToolbar.scaleS", "Scale (S)"),
59
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "hexagon", size: 16 })
60
+ }
61
+ ),
62
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.toolSep }),
63
+ /* @__PURE__ */ jsxRuntime.jsx(
64
+ ui.NiceButton,
65
+ {
66
+ className: ModelEditor_module.default.toolBtn,
67
+ variant: snapEnabled ? "primary" : "ghost",
68
+ size: "sm",
69
+ onClick: () => setSnapEnabled((v) => !v),
70
+ title: t("modelEditorToolbar.snapToGridState", "Snap to Grid ({state})").replace(
71
+ "{state}",
72
+ snapEnabled ? t("modelEditorToolbar.on", "ON") : t("modelEditorToolbar.off", "OFF")
73
+ ),
74
+ "aria-label": t("modelEditorToolbar.snapToGrid", "Snap to Grid"),
75
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "grid", size: 16 })
76
+ }
77
+ ),
78
+ /* @__PURE__ */ jsxRuntime.jsx(
79
+ ui.NiceButton,
80
+ {
81
+ className: ModelEditor_module.default.toolBtn,
82
+ variant: "ghost",
83
+ size: "sm",
84
+ onClick: () => setGizmoSpace((s) => s === "local" ? "world" : "local"),
85
+ title: t("modelEditorToolbar.orientation", "Orientation: {gizmoSpace}").replace(
86
+ "{gizmoSpace}",
87
+ String(gizmoSpace)
88
+ ),
89
+ "aria-label": t("modelEditorToolbar.orientation", "Orientation: {gizmoSpace}").replace(
90
+ "{gizmoSpace}",
91
+ String(gizmoSpace)
92
+ ),
93
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: gizmoSpace === "local" ? "target" : "globe", size: 16 })
94
+ }
95
+ ),
96
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.toolSep }),
97
+ /* @__PURE__ */ jsxRuntime.jsx(
98
+ ui.NiceButton,
99
+ {
100
+ className: ModelEditor_module.default.toolBtn,
101
+ variant: "ghost",
102
+ size: "sm",
103
+ onClick: () => rootObjectRef.current && focusOnObject(rootObjectRef.current),
104
+ title: t("modelEditorToolbar.focusF", "Focus (F)"),
105
+ "aria-label": t("modelEditorToolbar.focusF", "Focus (F)"),
106
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "target", size: 16 })
107
+ }
108
+ ),
109
+ /* @__PURE__ */ jsxRuntime.jsx(
110
+ ui.NiceButton,
111
+ {
112
+ className: ModelEditor_module.default.toolBtn,
113
+ variant: "ghost",
114
+ size: "sm",
115
+ onClick: () => setCameraPreset("front"),
116
+ title: t("modelEditorToolbar.frontViewNumpad1", "Front view (Numpad 1)"),
117
+ children: "1"
118
+ }
119
+ ),
120
+ /* @__PURE__ */ jsxRuntime.jsx(
121
+ ui.NiceButton,
122
+ {
123
+ className: ModelEditor_module.default.toolBtn,
124
+ variant: "ghost",
125
+ size: "sm",
126
+ onClick: () => setCameraPreset("right"),
127
+ title: t("modelEditorToolbar.rightViewNumpad3", "Right view (Numpad 3)"),
128
+ children: "3"
129
+ }
130
+ ),
131
+ /* @__PURE__ */ jsxRuntime.jsx(
132
+ ui.NiceButton,
133
+ {
134
+ className: ModelEditor_module.default.toolBtn,
135
+ variant: "ghost",
136
+ size: "sm",
137
+ onClick: () => setCameraPreset("top"),
138
+ title: t("modelEditorToolbar.topViewNumpad7", "Top view (Numpad 7)"),
139
+ children: "7"
140
+ }
141
+ ),
142
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: ModelEditor_module.default.toolSep }),
143
+ /* @__PURE__ */ jsxRuntime.jsx(
144
+ ui.NiceButton,
145
+ {
146
+ className: ModelEditor_module.default.toolBtn,
147
+ variant: "ghost",
148
+ size: "sm",
149
+ onClick: deleteSelected,
150
+ title: t("modelEditorToolbar.deleteSelectedDel", "Delete selected (Del)"),
151
+ "aria-label": t("modelEditorToolbar.deleteSelectedDel", "Delete selected (Del)"),
152
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "trash", size: 16 })
153
+ }
154
+ ),
155
+ /* @__PURE__ */ jsxRuntime.jsx(
156
+ ui.NiceButton,
157
+ {
158
+ className: ModelEditor_module.default.toolBtn,
159
+ variant: "ghost",
160
+ size: "sm",
161
+ onClick: duplicateSelected,
162
+ title: t("modelEditorToolbar.duplicateShiftD", "Duplicate (Shift+D)"),
163
+ disabled: !selectedNode,
164
+ "aria-label": t("modelEditorToolbar.duplicateShiftD", "Duplicate (Shift+D)"),
165
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.NiceIcon, { name: "clipboard", size: 16 })
166
+ }
167
+ )
168
+ ] });
169
+ }),
170
+ { displayName: "ModelEditorToolbar" }
171
+ );
172
+ exports.default = ModelEditorToolbar;