@operato/scene-visualizer 9.2.2 → 10.0.0-beta.10

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 (249) hide show
  1. package/dist/carrier.d.ts +263 -0
  2. package/dist/carrier.js +272 -0
  3. package/dist/carrier.js.map +1 -0
  4. package/dist/desk.d.ts +238 -3
  5. package/dist/desk.js +1 -2
  6. package/dist/desk.js.map +1 -1
  7. package/dist/editors/index.d.ts +3 -0
  8. package/dist/editors/index.js +15 -0
  9. package/dist/editors/index.js.map +1 -1
  10. package/dist/editors/property-editor-gltf-fill-targets.d.ts +20 -0
  11. package/dist/editors/property-editor-gltf-fill-targets.js +313 -0
  12. package/dist/editors/property-editor-gltf-fill-targets.js.map +1 -0
  13. package/dist/editors/property-editor-gltf-info.d.ts +25 -3
  14. package/dist/editors/property-editor-gltf-info.js +333 -73
  15. package/dist/editors/property-editor-gltf-info.js.map +1 -1
  16. package/dist/editors/property-editor-gltf-play-targets.d.ts +25 -0
  17. package/dist/editors/property-editor-gltf-play-targets.js +388 -0
  18. package/dist/editors/property-editor-gltf-play-targets.js.map +1 -0
  19. package/dist/editors/property-editor-location-increase-pattern.js +87 -95
  20. package/dist/editors/property-editor-location-increase-pattern.js.map +1 -1
  21. package/dist/editors/property-editor-stocker-location.d.ts +13 -0
  22. package/dist/editors/property-editor-stocker-location.js +151 -0
  23. package/dist/editors/property-editor-stocker-location.js.map +1 -0
  24. package/dist/editors/property-editor-stocker-ports.d.ts +8 -0
  25. package/dist/editors/property-editor-stocker-ports.js +112 -0
  26. package/dist/editors/property-editor-stocker-ports.js.map +1 -0
  27. package/dist/effects/outline.js +1 -1
  28. package/dist/effects/outline.js.map +1 -1
  29. package/dist/index.d.ts +8 -17
  30. package/dist/index.js +10 -17
  31. package/dist/index.js.map +1 -1
  32. package/dist/rack-table-3d.d.ts +16 -0
  33. package/dist/rack-table-3d.js +95 -0
  34. package/dist/rack-table-3d.js.map +1 -0
  35. package/dist/rack-table-cell.d.ts +238 -3
  36. package/dist/rack-table-cell.js +44 -51
  37. package/dist/rack-table-cell.js.map +1 -1
  38. package/dist/rack-table-location.d.ts +37 -0
  39. package/dist/rack-table-location.js +227 -0
  40. package/dist/rack-table-location.js.map +1 -0
  41. package/dist/rack-table.d.ts +13 -29
  42. package/dist/rack-table.js +121 -380
  43. package/dist/rack-table.js.map +1 -1
  44. package/dist/rack.d.ts +16 -5
  45. package/dist/rack.js +106 -19
  46. package/dist/rack.js.map +1 -1
  47. package/dist/signal-tower.d.ts +492 -0
  48. package/dist/signal-tower.js +275 -0
  49. package/dist/signal-tower.js.map +1 -0
  50. package/dist/stock-hub.d.ts +25 -0
  51. package/dist/stock-hub.js +147 -0
  52. package/dist/stock-hub.js.map +1 -0
  53. package/dist/stock.d.ts +52 -8
  54. package/dist/stock.js +223 -120
  55. package/dist/stock.js.map +1 -1
  56. package/dist/stocker-3d.d.ts +23 -0
  57. package/dist/stocker-3d.js +352 -0
  58. package/dist/stocker-3d.js.map +1 -0
  59. package/dist/stocker-port-3d.d.ts +14 -0
  60. package/dist/stocker-port-3d.js +80 -0
  61. package/dist/stocker-port-3d.js.map +1 -0
  62. package/dist/stocker-port.d.ts +254 -0
  63. package/dist/stocker-port.js +123 -0
  64. package/dist/stocker-port.js.map +1 -0
  65. package/dist/stocker.d.ts +340 -0
  66. package/dist/stocker.js +370 -0
  67. package/dist/stocker.js.map +1 -0
  68. package/dist/tank.d.ts +492 -0
  69. package/dist/tank.js +312 -0
  70. package/dist/tank.js.map +1 -0
  71. package/dist/templates/carrier.d.ts +19 -0
  72. package/dist/templates/carrier.js +20 -0
  73. package/dist/templates/carrier.js.map +1 -0
  74. package/dist/templates/cube.js +1 -1
  75. package/dist/templates/cube.js.map +1 -1
  76. package/dist/templates/cylinder.js +3 -3
  77. package/dist/templates/cylinder.js.map +1 -1
  78. package/dist/templates/index.d.ts +38 -38
  79. package/dist/templates/index.js +15 -1
  80. package/dist/templates/index.js.map +1 -1
  81. package/dist/templates/rack-table.d.ts +2 -0
  82. package/dist/templates/rack-table.js +4 -2
  83. package/dist/templates/rack-table.js.map +1 -1
  84. package/dist/templates/signal-tower.d.ts +21 -0
  85. package/dist/templates/signal-tower.js +22 -0
  86. package/dist/templates/signal-tower.js.map +1 -0
  87. package/dist/templates/sphere.d.ts +1 -0
  88. package/dist/templates/sphere.js +5 -4
  89. package/dist/templates/sphere.js.map +1 -1
  90. package/dist/templates/stock-hub.d.ts +14 -0
  91. package/dist/templates/stock-hub.js +15 -0
  92. package/dist/templates/stock-hub.js.map +1 -0
  93. package/dist/templates/stocker-port.d.ts +17 -0
  94. package/dist/templates/stocker-port.js +17 -0
  95. package/dist/templates/stocker-port.js.map +1 -0
  96. package/dist/templates/stocker.d.ts +27 -0
  97. package/dist/templates/stocker.js +38 -0
  98. package/dist/templates/stocker.js.map +1 -0
  99. package/dist/templates/tank.d.ts +21 -0
  100. package/dist/templates/tank.js +22 -0
  101. package/dist/templates/tank.js.map +1 -0
  102. package/dist/templates/vehicle.d.ts +19 -0
  103. package/dist/templates/vehicle.js +20 -0
  104. package/dist/templates/vehicle.js.map +1 -0
  105. package/dist/templates/visualizer.js +1 -1
  106. package/dist/templates/visualizer.js.map +1 -1
  107. package/dist/vehicle.d.ts +248 -0
  108. package/dist/vehicle.js +133 -0
  109. package/dist/vehicle.js.map +1 -0
  110. package/dist/visualizer.d.ts +5 -5
  111. package/dist/visualizer.js +72 -68
  112. package/dist/visualizer.js.map +1 -1
  113. package/icons/carrier.png +0 -0
  114. package/icons/signal-tower.png +0 -0
  115. package/icons/stock-hub.png +0 -0
  116. package/icons/tank.png +0 -0
  117. package/icons/vehicle.png +0 -0
  118. package/package.json +16 -18
  119. package/translations/en.json +6 -0
  120. package/translations/ja.json +5 -0
  121. package/translations/ko.json +6 -1
  122. package/translations/ms.json +5 -0
  123. package/translations/zh.json +5 -0
  124. package/dist/banner.d.ts +0 -15
  125. package/dist/banner.js +0 -76
  126. package/dist/banner.js.map +0 -1
  127. package/dist/camera.d.ts +0 -20
  128. package/dist/camera.js +0 -108
  129. package/dist/camera.js.map +0 -1
  130. package/dist/cube.d.ts +0 -13
  131. package/dist/cube.js +0 -38
  132. package/dist/cube.js.map +0 -1
  133. package/dist/cylinder.d.ts +0 -11
  134. package/dist/cylinder.js +0 -38
  135. package/dist/cylinder.js.map +0 -1
  136. package/dist/ellipse.d.ts +0 -5
  137. package/dist/ellipse.js +0 -22
  138. package/dist/ellipse.js.map +0 -1
  139. package/dist/gltf-object.d.ts +0 -20
  140. package/dist/gltf-object.js +0 -104
  141. package/dist/gltf-object.js.map +0 -1
  142. package/dist/html-overlay-element.d.ts +0 -1
  143. package/dist/html-overlay-element.js +0 -12
  144. package/dist/html-overlay-element.js.map +0 -1
  145. package/dist/light.d.ts +0 -15
  146. package/dist/light.js +0 -135
  147. package/dist/light.js.map +0 -1
  148. package/dist/polygon.d.ts +0 -17
  149. package/dist/polygon.js +0 -64
  150. package/dist/polygon.js.map +0 -1
  151. package/dist/rect.d.ts +0 -5
  152. package/dist/rect.js +0 -36
  153. package/dist/rect.js.map +0 -1
  154. package/dist/scene/component.d.ts +0 -1
  155. package/dist/scene/component.js +0 -29
  156. package/dist/scene/component.js.map +0 -1
  157. package/dist/sphere.d.ts +0 -11
  158. package/dist/sphere.js +0 -38
  159. package/dist/sphere.js.map +0 -1
  160. package/dist/sprite.d.ts +0 -9
  161. package/dist/sprite.js +0 -28
  162. package/dist/sprite.js.map +0 -1
  163. package/dist/text.d.ts +0 -1
  164. package/dist/text.js +0 -9
  165. package/dist/text.js.map +0 -1
  166. package/dist/three-container-editor.d.ts +0 -22
  167. package/dist/three-container-editor.js +0 -132
  168. package/dist/three-container-editor.js.map +0 -1
  169. package/dist/three-container.d.ts +0 -85
  170. package/dist/three-container.js +0 -565
  171. package/dist/three-container.js.map +0 -1
  172. package/dist/three-controls.d.ts +0 -11
  173. package/dist/three-controls.js +0 -616
  174. package/dist/three-controls.js.map +0 -1
  175. package/dist/three-layout.d.ts +0 -8
  176. package/dist/three-layout.js +0 -20
  177. package/dist/three-layout.js.map +0 -1
  178. package/dist/three-space.d.ts +0 -85
  179. package/dist/three-space.js +0 -570
  180. package/dist/three-space.js.map +0 -1
  181. package/dist/threed/common.d.ts +0 -22
  182. package/dist/threed/common.js +0 -19
  183. package/dist/threed/common.js.map +0 -1
  184. package/dist/threed/floor/floor.d.ts +0 -3
  185. package/dist/threed/floor/floor.js +0 -51
  186. package/dist/threed/floor/floor.js.map +0 -1
  187. package/dist/threed/html/elements.d.ts +0 -2
  188. package/dist/threed/html/elements.js +0 -21
  189. package/dist/threed/html/elements.js.map +0 -1
  190. package/dist/threed/index.d.ts +0 -15
  191. package/dist/threed/index.js +0 -16
  192. package/dist/threed/index.js.map +0 -1
  193. package/dist/threed/real-object-camera-meshed.d.ts +0 -12
  194. package/dist/threed/real-object-camera-meshed.js +0 -49
  195. package/dist/threed/real-object-camera-meshed.js.map +0 -1
  196. package/dist/threed/real-object-camera.d.ts +0 -9
  197. package/dist/threed/real-object-camera.js +0 -31
  198. package/dist/threed/real-object-camera.js.map +0 -1
  199. package/dist/threed/real-object-dom-element.d.ts +0 -9
  200. package/dist/threed/real-object-dom-element.js +0 -40
  201. package/dist/threed/real-object-dom-element.js.map +0 -1
  202. package/dist/threed/real-object-dummy.d.ts +0 -6
  203. package/dist/threed/real-object-dummy.js +0 -11
  204. package/dist/threed/real-object-dummy.js.map +0 -1
  205. package/dist/threed/real-object-extrude.d.ts +0 -21
  206. package/dist/threed/real-object-extrude.js +0 -173
  207. package/dist/threed/real-object-extrude.js.map +0 -1
  208. package/dist/threed/real-object-gltf.d.ts +0 -16
  209. package/dist/threed/real-object-gltf.js +0 -101
  210. package/dist/threed/real-object-gltf.js.map +0 -1
  211. package/dist/threed/real-object-group.d.ts +0 -5
  212. package/dist/threed/real-object-group.js +0 -11
  213. package/dist/threed/real-object-group.js.map +0 -1
  214. package/dist/threed/real-object-mesh.d.ts +0 -13
  215. package/dist/threed/real-object-mesh.js +0 -75
  216. package/dist/threed/real-object-mesh.js.map +0 -1
  217. package/dist/threed/real-object-plane.d.ts +0 -5
  218. package/dist/threed/real-object-plane.js +0 -22
  219. package/dist/threed/real-object-plane.js.map +0 -1
  220. package/dist/threed/real-object-scene.d.ts +0 -21
  221. package/dist/threed/real-object-scene.js +0 -67
  222. package/dist/threed/real-object-scene.js.map +0 -1
  223. package/dist/threed/real-object-sprite-2d.d.ts +0 -14
  224. package/dist/threed/real-object-sprite-2d.js +0 -45
  225. package/dist/threed/real-object-sprite-2d.js.map +0 -1
  226. package/dist/threed/real-object-sprite.d.ts +0 -11
  227. package/dist/threed/real-object-sprite.js +0 -50
  228. package/dist/threed/real-object-sprite.js.map +0 -1
  229. package/dist/threed/real-object-text.d.ts +0 -15
  230. package/dist/threed/real-object-text.js +0 -64
  231. package/dist/threed/real-object-text.js.map +0 -1
  232. package/dist/threed/real-object.d.ts +0 -64
  233. package/dist/threed/real-object.js +0 -260
  234. package/dist/threed/real-object.js.map +0 -1
  235. package/dist/threed/texture/canvas-texture.d.ts +0 -4
  236. package/dist/threed/texture/canvas-texture.js +0 -49
  237. package/dist/threed/texture/canvas-texture.js.map +0 -1
  238. package/dist/threed/texture/text-texture.d.ts +0 -8
  239. package/dist/threed/texture/text-texture.js +0 -79
  240. package/dist/threed/texture/text-texture.js.map +0 -1
  241. package/dist/threed/three-dimensional-container.d.ts +0 -8
  242. package/dist/threed/three-dimensional-container.js +0 -2
  243. package/dist/threed/three-dimensional-container.js.map +0 -1
  244. package/dist/threed/utils/bound-uv-generator.d.ts +0 -16
  245. package/dist/threed/utils/bound-uv-generator.js +0 -42
  246. package/dist/threed/utils/bound-uv-generator.js.map +0 -1
  247. package/dist/wall.d.ts +0 -13
  248. package/dist/wall.js +0 -45
  249. package/dist/wall.js.map +0 -1
@@ -0,0 +1,388 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ *
4
+ * GLTF 애니메이션 타겟 선택 에디터.
5
+ * All / None / Custom 모드로 started에 바인딩할 애니메이션 선택.
6
+ * 각 애니메이션을 개별 미리보기(play/stop) 가능.
7
+ */
8
+ import { __decorate } from "tslib";
9
+ import '@material/web/icon/icon.js';
10
+ import '@operato/i18n/ox-i18n.js';
11
+ import { css, html, nothing } from 'lit';
12
+ import { customElement, property, state } from 'lit/decorators.js';
13
+ import { OxPropertyEditor } from '@operato/property-editor';
14
+ import { ScrollbarStyles } from '@operato/styles/scrollbar-styles.js';
15
+ function getMode(value) {
16
+ if (value === '*')
17
+ return 'all';
18
+ if (value === 'none')
19
+ return 'none';
20
+ if (Array.isArray(value) && value.length > 0)
21
+ return 'custom';
22
+ if (Array.isArray(value))
23
+ return 'custom'; // empty array = custom with nothing
24
+ if (!value)
25
+ return 'all'; // undefined = default = all
26
+ return 'all';
27
+ }
28
+ let GLTFPlayTargetsEditor = class GLTFPlayTargetsEditor extends OxPropertyEditor {
29
+ static styles = [
30
+ ...OxPropertyEditor.styles,
31
+ ScrollbarStyles,
32
+ css `
33
+ .mode-selector {
34
+ display: flex;
35
+ gap: 0;
36
+ margin-bottom: 6px;
37
+ border: 1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, 0.15));
38
+ border-radius: 6px;
39
+ overflow: hidden;
40
+ }
41
+
42
+ .mode-btn {
43
+ flex: 1;
44
+ padding: 5px 0;
45
+ font-size: 11px;
46
+ font-weight: 500;
47
+ text-align: center;
48
+ cursor: pointer;
49
+ background: var(--md-sys-color-surface-container, #f3edf7);
50
+ color: var(--md-sys-color-on-surface, #1c1b1f);
51
+ border: none;
52
+ border-right: 1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, 0.1));
53
+ transition: all 0.15s;
54
+ }
55
+
56
+ .mode-btn:last-child {
57
+ border-right: none;
58
+ }
59
+
60
+ .mode-btn:hover {
61
+ background: var(--md-sys-color-surface-container-highest, #e6e0e9);
62
+ }
63
+
64
+ .mode-btn[active] {
65
+ background: var(--md-sys-color-primary, #6750a4);
66
+ color: var(--md-sys-color-on-primary, #fff);
67
+ }
68
+
69
+ .anim-list {
70
+ display: flex;
71
+ flex-direction: column;
72
+ gap: 1px;
73
+ max-height: 200px;
74
+ overflow-y: auto;
75
+ font-size: 12px;
76
+ }
77
+
78
+ .anim-item {
79
+ display: flex;
80
+ align-items: center;
81
+ gap: 6px;
82
+ padding: 4px 8px;
83
+ border-radius: 4px;
84
+ transition: background 0.1s;
85
+ }
86
+
87
+ .anim-item:hover {
88
+ background: var(--md-sys-color-primary-container, rgba(103, 80, 164, 0.12));
89
+ }
90
+
91
+ .anim-item input[type='checkbox'] {
92
+ margin: 0;
93
+ accent-color: var(--md-sys-color-primary, #6750a4);
94
+ }
95
+
96
+ .anim-item span {
97
+ flex: 1;
98
+ font-size: 12px;
99
+ color: var(--md-sys-color-on-surface, #1c1b1f);
100
+ }
101
+
102
+ .anim-item md-icon {
103
+ --md-icon-size: 18px;
104
+ cursor: pointer;
105
+ color: var(--md-sys-color-on-surface-variant, #666);
106
+ transition: color 0.15s;
107
+ }
108
+
109
+ .anim-item md-icon:hover {
110
+ color: var(--md-sys-color-primary, #6750a4);
111
+ }
112
+
113
+ .anim-item md-icon[playing] {
114
+ color: var(--md-sys-color-primary, #6750a4);
115
+ }
116
+
117
+ .mode-desc {
118
+ display: flex;
119
+ align-items: center;
120
+ gap: 6px;
121
+ font-size: 11px;
122
+ color: var(--md-sys-color-on-surface-variant, #666);
123
+ padding: 4px 0;
124
+ }
125
+
126
+ .mini-btn {
127
+ font-size: 10px;
128
+ padding: 2px 8px;
129
+ border: 1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, 0.15));
130
+ border-radius: 4px;
131
+ background: var(--md-sys-color-surface-container, #f3edf7);
132
+ color: var(--md-sys-color-on-surface, #1c1b1f);
133
+ cursor: pointer;
134
+ }
135
+
136
+ .mini-btn:hover {
137
+ background: var(--md-sys-color-surface-container-highest, #e6e0e9);
138
+ }
139
+
140
+ .play-toggle {
141
+ display: flex;
142
+ align-items: center;
143
+ gap: 6px;
144
+ padding: 4px 0;
145
+ margin-bottom: 4px;
146
+ cursor: pointer;
147
+ font-size: 12px;
148
+ font-weight: 500;
149
+ color: var(--md-sys-color-on-surface, #1c1b1f);
150
+ }
151
+
152
+ .play-toggle input[type='checkbox'] {
153
+ accent-color: var(--md-sys-color-primary, #6750a4);
154
+ }
155
+
156
+ .empty {
157
+ color: var(--md-sys-color-on-surface-variant, #999);
158
+ font-size: 11px;
159
+ padding: 8px;
160
+ text-align: center;
161
+ }
162
+ `
163
+ ];
164
+ _component = null;
165
+ _lastExternalValue = undefined;
166
+ updated(changes) {
167
+ if (changes.has('src')) {
168
+ this.dispatchEvent(new CustomEvent('i-need-selected', {
169
+ bubbles: true,
170
+ composed: true,
171
+ detail: {
172
+ callback: (selected) => {
173
+ this._component = selected?.[0];
174
+ this._refreshAnimNames();
175
+ }
176
+ }
177
+ }));
178
+ }
179
+ }
180
+ _refreshAnimNames() {
181
+ if (!this._component) {
182
+ this._animNames = [];
183
+ return;
184
+ }
185
+ this._animNames = this._component.animationNames ?? [];
186
+ }
187
+ _pollTimer;
188
+ connectedCallback() {
189
+ super.connectedCallback();
190
+ // GLTF 비동기 로드 후 애니메이션 목록 갱신을 위한 폴링 (최대 20회 = 20초)
191
+ let retries = 0;
192
+ this._pollTimer = window.setInterval(() => {
193
+ if (!this._animNames?.length) {
194
+ this._refreshAnimNames();
195
+ }
196
+ if (this._animNames?.length || ++retries >= 20) {
197
+ clearInterval(this._pollTimer);
198
+ this._pollTimer = undefined;
199
+ }
200
+ }, 1000);
201
+ }
202
+ disconnectedCallback() {
203
+ super.disconnectedCallback();
204
+ if (this._pollTimer) {
205
+ clearInterval(this._pollTimer);
206
+ }
207
+ }
208
+ editorTemplate(value, _spec) {
209
+ if (!this._animNames?.length) {
210
+ this._refreshAnimNames();
211
+ }
212
+ if (value !== this._lastExternalValue) {
213
+ this._lastExternalValue = value;
214
+ this._mode = getMode(value);
215
+ }
216
+ const mode = this._mode;
217
+ const animCount = this._animNames?.length ?? 0;
218
+ const targets = Array.isArray(this.value) ? this.value : (Array.isArray(value) ? value : []);
219
+ const isPlaying = this._getPlayState();
220
+ return html `
221
+ <fieldset fullwidth>
222
+ ${animCount > 0
223
+ ? html `
224
+ <label class="play-toggle">
225
+ <input
226
+ type="checkbox"
227
+ .checked=${isPlaying}
228
+ @change=${(e) => {
229
+ e.stopPropagation();
230
+ this._setPlay(e.target.checked);
231
+ }}
232
+ />
233
+ <span>Play</span>
234
+ </label>
235
+
236
+ <div class="mode-selector">
237
+ <div class="mode-btn" ?active=${mode === 'all'} @click=${() => this._setMode('all')}>All</div>
238
+ <div class="mode-btn" ?active=${mode === 'none'} @click=${() => this._setMode('none')}>None</div>
239
+ <div class="mode-btn" ?active=${mode === 'custom'} @click=${() => this._setMode('custom')}>Custom</div>
240
+ </div>
241
+
242
+ ${mode === 'all'
243
+ ? html `<div class="mode-desc">${animCount} animations — play all</div>`
244
+ : nothing}
245
+ ${mode === 'none'
246
+ ? html `<div class="mode-desc">No animations auto-play</div>`
247
+ : nothing}
248
+ ${mode === 'custom'
249
+ ? html `
250
+ <div class="mode-desc">
251
+ <span style="flex:1">${targets.length} / ${animCount} selected</span>
252
+ <button class="mini-btn" @click=${() => this._applyValue([...(this._animNames ?? [])])}>All</button>
253
+ <button class="mini-btn" @click=${() => this._applyValue([])}>Clear</button>
254
+ </div>
255
+ `
256
+ : nothing}
257
+
258
+ <div class="anim-list">
259
+ ${(this._animNames ?? []).map(name => html `
260
+ <div class="anim-item">
261
+ ${mode === 'custom'
262
+ ? html `
263
+ <input
264
+ type="checkbox"
265
+ .checked=${targets.includes(name)}
266
+ @change=${(e) => {
267
+ e.stopPropagation();
268
+ this._onToggle(name, e.target.checked, targets);
269
+ }}
270
+ />
271
+ `
272
+ : nothing}
273
+ <span>${name}</span>
274
+ <md-icon
275
+ ?playing=${this._playingAnim === name}
276
+ @click=${() => this._togglePreview(name)}
277
+ title="preview"
278
+ >${this._playingAnim === name ? 'stop' : 'play_arrow'}</md-icon>
279
+ </div>
280
+ `)}
281
+ </div>
282
+ `
283
+ : html `<div class="empty">No animations available</div>`}
284
+ </fieldset>
285
+ `;
286
+ }
287
+ _setMode(mode) {
288
+ const prevMode = this._mode;
289
+ this._mode = mode;
290
+ let newValue;
291
+ switch (mode) {
292
+ case 'all':
293
+ newValue = '*';
294
+ break;
295
+ case 'none':
296
+ newValue = 'none';
297
+ break;
298
+ case 'custom':
299
+ if (prevMode === 'all') {
300
+ newValue = [...(this._animNames ?? [])];
301
+ }
302
+ else if (prevMode === 'none') {
303
+ newValue = [];
304
+ }
305
+ else {
306
+ newValue = Array.isArray(this.value) ? this.value : [];
307
+ }
308
+ break;
309
+ }
310
+ this._applyValue(newValue);
311
+ }
312
+ _onToggle(name, checked, current) {
313
+ const list = [...current];
314
+ if (checked) {
315
+ if (!list.includes(name))
316
+ list.push(name);
317
+ }
318
+ else {
319
+ const idx = list.indexOf(name);
320
+ if (idx >= 0)
321
+ list.splice(idx, 1);
322
+ }
323
+ this._applyValue(list);
324
+ }
325
+ _applyValue(newValue) {
326
+ this.value = newValue;
327
+ this.requestUpdate();
328
+ this.dispatchEvent(new CustomEvent('i-need-selected', {
329
+ bubbles: true,
330
+ composed: true,
331
+ detail: {
332
+ callback: (selected) => {
333
+ selected[0].set('playTargets', newValue);
334
+ }
335
+ }
336
+ }));
337
+ }
338
+ _getPlayState() {
339
+ return this._component?.state?.play !== false;
340
+ }
341
+ _setPlay(value) {
342
+ if (!this._component)
343
+ return;
344
+ this._component.set('play', value);
345
+ this.requestUpdate();
346
+ }
347
+ _togglePreview(name) {
348
+ if (!this._component)
349
+ return;
350
+ const ro = this._component.realObject;
351
+ if (!ro?._animationActions)
352
+ return;
353
+ const action = ro._animationActions.get(name);
354
+ if (!action)
355
+ return;
356
+ if (this._playingAnim === name) {
357
+ action.stop();
358
+ this._playingAnim = null;
359
+ }
360
+ else {
361
+ // 이전 프리뷰 중지
362
+ if (this._playingAnim) {
363
+ ro._animationActions.get(this._playingAnim)?.stop();
364
+ }
365
+ action.play();
366
+ this._playingAnim = name;
367
+ }
368
+ this._component.invalidate();
369
+ this.requestUpdate();
370
+ }
371
+ };
372
+ __decorate([
373
+ property({ type: String })
374
+ ], GLTFPlayTargetsEditor.prototype, "src", void 0);
375
+ __decorate([
376
+ state()
377
+ ], GLTFPlayTargetsEditor.prototype, "_animNames", void 0);
378
+ __decorate([
379
+ state()
380
+ ], GLTFPlayTargetsEditor.prototype, "_mode", void 0);
381
+ __decorate([
382
+ state()
383
+ ], GLTFPlayTargetsEditor.prototype, "_playingAnim", void 0);
384
+ GLTFPlayTargetsEditor = __decorate([
385
+ customElement('property-editor-gltf-play-targets')
386
+ ], GLTFPlayTargetsEditor);
387
+ export default GLTFPlayTargetsEditor;
388
+ //# sourceMappingURL=property-editor-gltf-play-targets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property-editor-gltf-play-targets.js","sourceRoot":"","sources":["../../src/editors/property-editor-gltf-play-targets.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * GLTF 애니메이션 타겟 선택 에디터.\n * All / None / Custom 모드로 started에 바인딩할 애니메이션 선택.\n * 각 애니메이션을 개별 미리보기(play/stop) 가능.\n */\n\nimport '@material/web/icon/icon.js'\nimport '@operato/i18n/ox-i18n.js'\n\nimport { css, html, PropertyValues, TemplateResult, nothing } from 'lit'\nimport { customElement, property, state } from 'lit/decorators.js'\n\nimport { OxPropertyEditor, PropertySpec } from '@operato/property-editor'\nimport { ScrollbarStyles } from '@operato/styles/scrollbar-styles.js'\n\ntype AnimMode = 'all' | 'none' | 'custom'\n\nfunction getMode(value: any): AnimMode {\n if (value === '*') return 'all'\n if (value === 'none') return 'none'\n if (Array.isArray(value) && value.length > 0) return 'custom'\n if (Array.isArray(value)) return 'custom' // empty array = custom with nothing\n if (!value) return 'all' // undefined = default = all\n return 'all'\n}\n\n@customElement('property-editor-gltf-play-targets')\nexport default class GLTFPlayTargetsEditor extends OxPropertyEditor {\n static styles = [\n ...OxPropertyEditor.styles,\n ScrollbarStyles,\n css`\n .mode-selector {\n display: flex;\n gap: 0;\n margin-bottom: 6px;\n border: 1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, 0.15));\n border-radius: 6px;\n overflow: hidden;\n }\n\n .mode-btn {\n flex: 1;\n padding: 5px 0;\n font-size: 11px;\n font-weight: 500;\n text-align: center;\n cursor: pointer;\n background: var(--md-sys-color-surface-container, #f3edf7);\n color: var(--md-sys-color-on-surface, #1c1b1f);\n border: none;\n border-right: 1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, 0.1));\n transition: all 0.15s;\n }\n\n .mode-btn:last-child {\n border-right: none;\n }\n\n .mode-btn:hover {\n background: var(--md-sys-color-surface-container-highest, #e6e0e9);\n }\n\n .mode-btn[active] {\n background: var(--md-sys-color-primary, #6750a4);\n color: var(--md-sys-color-on-primary, #fff);\n }\n\n .anim-list {\n display: flex;\n flex-direction: column;\n gap: 1px;\n max-height: 200px;\n overflow-y: auto;\n font-size: 12px;\n }\n\n .anim-item {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 8px;\n border-radius: 4px;\n transition: background 0.1s;\n }\n\n .anim-item:hover {\n background: var(--md-sys-color-primary-container, rgba(103, 80, 164, 0.12));\n }\n\n .anim-item input[type='checkbox'] {\n margin: 0;\n accent-color: var(--md-sys-color-primary, #6750a4);\n }\n\n .anim-item span {\n flex: 1;\n font-size: 12px;\n color: var(--md-sys-color-on-surface, #1c1b1f);\n }\n\n .anim-item md-icon {\n --md-icon-size: 18px;\n cursor: pointer;\n color: var(--md-sys-color-on-surface-variant, #666);\n transition: color 0.15s;\n }\n\n .anim-item md-icon:hover {\n color: var(--md-sys-color-primary, #6750a4);\n }\n\n .anim-item md-icon[playing] {\n color: var(--md-sys-color-primary, #6750a4);\n }\n\n .mode-desc {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 11px;\n color: var(--md-sys-color-on-surface-variant, #666);\n padding: 4px 0;\n }\n\n .mini-btn {\n font-size: 10px;\n padding: 2px 8px;\n border: 1px solid var(--md-sys-color-outline-variant, rgba(0, 0, 0, 0.15));\n border-radius: 4px;\n background: var(--md-sys-color-surface-container, #f3edf7);\n color: var(--md-sys-color-on-surface, #1c1b1f);\n cursor: pointer;\n }\n\n .mini-btn:hover {\n background: var(--md-sys-color-surface-container-highest, #e6e0e9);\n }\n\n .play-toggle {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 4px 0;\n margin-bottom: 4px;\n cursor: pointer;\n font-size: 12px;\n font-weight: 500;\n color: var(--md-sys-color-on-surface, #1c1b1f);\n }\n\n .play-toggle input[type='checkbox'] {\n accent-color: var(--md-sys-color-primary, #6750a4);\n }\n\n .empty {\n color: var(--md-sys-color-on-surface-variant, #999);\n font-size: 11px;\n padding: 8px;\n text-align: center;\n }\n `\n ]\n\n @property({ type: String }) declare src: string | undefined\n\n @state() declare private _animNames: string[]\n @state() declare private _mode: AnimMode\n @state() declare private _playingAnim: string | null\n\n private _component: any = null\n private _lastExternalValue: any = undefined\n\n updated(changes: PropertyValues<this>) {\n if (changes.has('src')) {\n this.dispatchEvent(\n new CustomEvent('i-need-selected', {\n bubbles: true,\n composed: true,\n detail: {\n callback: (selected: any[]) => {\n this._component = selected?.[0]\n this._refreshAnimNames()\n }\n }\n })\n )\n }\n }\n\n private _refreshAnimNames() {\n if (!this._component) {\n this._animNames = []\n return\n }\n\n this._animNames = (this._component.animationNames as string[]) ?? []\n }\n\n private _pollTimer?: number\n\n connectedCallback() {\n super.connectedCallback()\n // GLTF 비동기 로드 후 애니메이션 목록 갱신을 위한 폴링 (최대 20회 = 20초)\n let retries = 0\n this._pollTimer = window.setInterval(() => {\n if (!this._animNames?.length) {\n this._refreshAnimNames()\n }\n if (this._animNames?.length || ++retries >= 20) {\n clearInterval(this._pollTimer)\n this._pollTimer = undefined\n }\n }, 1000)\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n if (this._pollTimer) {\n clearInterval(this._pollTimer)\n }\n }\n\n editorTemplate(value: any, _spec: PropertySpec): TemplateResult {\n if (!this._animNames?.length) {\n this._refreshAnimNames()\n }\n\n if (value !== this._lastExternalValue) {\n this._lastExternalValue = value\n this._mode = getMode(value)\n }\n\n const mode = this._mode\n const animCount = this._animNames?.length ?? 0\n const targets: string[] = Array.isArray(this.value) ? this.value : (Array.isArray(value) ? value : [])\n\n const isPlaying = this._getPlayState()\n\n return html`\n <fieldset fullwidth>\n ${animCount > 0\n ? html`\n <label class=\"play-toggle\">\n <input\n type=\"checkbox\"\n .checked=${isPlaying}\n @change=${(e: Event) => {\n e.stopPropagation()\n this._setPlay((e.target as HTMLInputElement).checked)\n }}\n />\n <span>Play</span>\n </label>\n\n <div class=\"mode-selector\">\n <div class=\"mode-btn\" ?active=${mode === 'all'} @click=${() => this._setMode('all')}>All</div>\n <div class=\"mode-btn\" ?active=${mode === 'none'} @click=${() => this._setMode('none')}>None</div>\n <div class=\"mode-btn\" ?active=${mode === 'custom'} @click=${() => this._setMode('custom')}>Custom</div>\n </div>\n\n ${mode === 'all'\n ? html`<div class=\"mode-desc\">${animCount} animations — play all</div>`\n : nothing}\n ${mode === 'none'\n ? html`<div class=\"mode-desc\">No animations auto-play</div>`\n : nothing}\n ${mode === 'custom'\n ? html`\n <div class=\"mode-desc\">\n <span style=\"flex:1\">${targets.length} / ${animCount} selected</span>\n <button class=\"mini-btn\" @click=${() => this._applyValue([...(this._animNames ?? [])])}>All</button>\n <button class=\"mini-btn\" @click=${() => this._applyValue([])}>Clear</button>\n </div>\n `\n : nothing}\n\n <div class=\"anim-list\">\n ${(this._animNames ?? []).map(\n name => html`\n <div class=\"anim-item\">\n ${mode === 'custom'\n ? html`\n <input\n type=\"checkbox\"\n .checked=${targets.includes(name)}\n @change=${(e: Event) => {\n e.stopPropagation()\n this._onToggle(name, (e.target as HTMLInputElement).checked, targets)\n }}\n />\n `\n : nothing}\n <span>${name}</span>\n <md-icon\n ?playing=${this._playingAnim === name}\n @click=${() => this._togglePreview(name)}\n title=\"preview\"\n >${this._playingAnim === name ? 'stop' : 'play_arrow'}</md-icon>\n </div>\n `\n )}\n </div>\n `\n : html`<div class=\"empty\">No animations available</div>`}\n </fieldset>\n `\n }\n\n private _setMode(mode: AnimMode) {\n const prevMode = this._mode\n this._mode = mode\n\n let newValue: any\n switch (mode) {\n case 'all':\n newValue = '*'\n break\n case 'none':\n newValue = 'none'\n break\n case 'custom':\n if (prevMode === 'all') {\n newValue = [...(this._animNames ?? [])]\n } else if (prevMode === 'none') {\n newValue = []\n } else {\n newValue = Array.isArray(this.value) ? this.value : []\n }\n break\n }\n\n this._applyValue(newValue)\n }\n\n private _onToggle(name: string, checked: boolean, current: string[]) {\n const list = [...current]\n if (checked) {\n if (!list.includes(name)) list.push(name)\n } else {\n const idx = list.indexOf(name)\n if (idx >= 0) list.splice(idx, 1)\n }\n this._applyValue(list)\n }\n\n private _applyValue(newValue: any) {\n this.value = newValue\n this.requestUpdate()\n\n this.dispatchEvent(\n new CustomEvent('i-need-selected', {\n bubbles: true,\n composed: true,\n detail: {\n callback: (selected: any[]) => {\n selected[0].set('playTargets', newValue)\n }\n }\n })\n )\n }\n\n private _getPlayState(): boolean {\n return this._component?.state?.play !== false\n }\n\n private _setPlay(value: boolean) {\n if (!this._component) return\n this._component.set('play', value)\n this.requestUpdate()\n }\n\n private _togglePreview(name: string) {\n if (!this._component) return\n\n const ro = this._component.realObject as any\n if (!ro?._animationActions) return\n\n const action = ro._animationActions.get(name)\n if (!action) return\n\n if (this._playingAnim === name) {\n action.stop()\n this._playingAnim = null\n } else {\n // 이전 프리뷰 중지\n if (this._playingAnim) {\n ro._animationActions.get(this._playingAnim)?.stop()\n }\n action.play()\n this._playingAnim = name\n }\n\n this._component.invalidate()\n this.requestUpdate()\n }\n}\n"]}
@@ -4,100 +4,9 @@ import { css, html } from 'lit';
4
4
  import { customElement, property } from 'lit/decorators.js';
5
5
  import { OxPropertyEditor } from '@operato/property-editor';
6
6
  let LocationIncreasePatternEditor = class LocationIncreasePatternEditor extends OxPropertyEditor {
7
- constructor() {
8
- super(...arguments);
9
- this.startSection = 1;
10
- this.startUnit = 1;
11
- this.skipNumbering = true;
12
- this._specificPropEl = null;
13
- }
14
- editorTemplate(value, spec) {
15
- // TODO: background image change to use the url-loader
16
- return html `
17
- <fieldset fullwidth>
18
- <legend><ox-i18n msgid="label.location-increase-pattern">Increase Pattern</ox-i18n></legend>
19
-
20
- <div class="property-grid">
21
- <label> <ox-i18n msgid="label.start-section">Start Section</ox-i18n> </label>
22
- <input
23
- type="number"
24
- data-start-section
25
- value="${this.startSection}"
26
- @change=${(e) => (this.startSection = e.target.valueAsNumber)}
27
- />
28
-
29
- <label> <ox-i18n msgid="label.start-unit">Start Unit</ox-i18n> </label>
30
- <input
31
- type="number"
32
- data-start-unit
33
- value="${this.startUnit}"
34
- @change=${(e) => (this.startUnit = e.target.valueAsNumber)}
35
- />
36
-
37
- <div class="checkbox-row" fullwidth>
38
- <input id="skip-numbering" type="checkbox" data-skip-numbering ?checked="${this.skipNumbering}" />
39
- <label for="skip-numbering">
40
- <ox-i18n msgid="label.skip-numbering">Skip Numbering</ox-i18n>
41
- </label>
42
- </div>
43
-
44
- <div
45
- id="pattern-set"
46
- class="property-grid location-increase-pattern-btn"
47
- @click=${(e) => this._onTapType(e)}
48
- >
49
- <button data-value="cw" type="button"></button>
50
- <button data-value="ccw" type="button"></button>
51
- <button data-value="zigzag" type="button"></button>
52
- <button data-value="zigzag-reverse" type="button"></button>
53
- </div>
54
- </div>
55
- </fieldset>
56
- `;
57
- }
58
- connectedCallback() {
59
- super.connectedCallback();
60
- if (this.property && this.property.event) {
61
- Object.entries(this.property.event).forEach(entry => {
62
- if (entry[0]) {
63
- document.addEventListener(entry[0], entry[1]);
64
- }
65
- });
66
- }
67
- }
68
- disconnectedCallback() {
69
- super.disconnectedCallback();
70
- if (this.property && this.property.event) {
71
- Object.entries(this.property.event).forEach(entry => {
72
- if (entry[0]) {
73
- document.removeEventListener(entry[0], entry[1]);
74
- }
75
- });
76
- }
77
- }
78
- _onTapType(e) {
79
- var _a;
80
- var target = e.target;
81
- const increasingDirection = (_a = target === null || target === void 0 ? void 0 : target.closest('[data-value]')) === null || _a === void 0 ? void 0 : _a.getAttribute('data-value');
82
- if (!increasingDirection) {
83
- return;
84
- }
85
- this.dispatchEvent(new CustomEvent('i-need-selected', {
86
- bubbles: true,
87
- composed: true,
88
- detail: {
89
- callback: (selected) => {
90
- const table = selected[0].parent;
91
- table.increaseLocation(increasingDirection, this.skipNumbering, this.startSection, this.startUnit);
92
- }
93
- }
94
- }));
95
- e.stopPropagation();
96
- }
97
- };
98
- LocationIncreasePatternEditor.styles = [
99
- ...OxPropertyEditor.styles,
100
- css `
7
+ static styles = [
8
+ ...OxPropertyEditor.styles,
9
+ css `
101
10
  fieldset {
102
11
  border: none;
103
12
  border-bottom: 1px solid #cfd8dc;
@@ -250,7 +159,90 @@ LocationIncreasePatternEditor.styles = [
250
159
  text-align: left;
251
160
  }
252
161
  `
253
- ];
162
+ ];
163
+ editorTemplate(value, spec) {
164
+ // TODO: background image change to use the url-loader
165
+ return html `
166
+ <fieldset fullwidth>
167
+ <legend><ox-i18n msgid="label.location-increase-pattern">Increase Pattern</ox-i18n></legend>
168
+
169
+ <div class="property-grid">
170
+ <label> <ox-i18n msgid="label.start-section">Start Section</ox-i18n> </label>
171
+ <input
172
+ type="number"
173
+ data-start-section
174
+ value="${this.startSection}"
175
+ @change=${(e) => (this.startSection = e.target.valueAsNumber)}
176
+ />
177
+
178
+ <label> <ox-i18n msgid="label.start-unit">Start Unit</ox-i18n> </label>
179
+ <input
180
+ type="number"
181
+ data-start-unit
182
+ value="${this.startUnit}"
183
+ @change=${(e) => (this.startUnit = e.target.valueAsNumber)}
184
+ />
185
+
186
+ <div class="checkbox-row" fullwidth>
187
+ <input id="skip-numbering" type="checkbox" data-skip-numbering ?checked="${this.skipNumbering}" />
188
+ <label for="skip-numbering">
189
+ <ox-i18n msgid="label.skip-numbering">Skip Numbering</ox-i18n>
190
+ </label>
191
+ </div>
192
+
193
+ <div
194
+ id="pattern-set"
195
+ class="property-grid location-increase-pattern-btn"
196
+ @click=${(e) => this._onTapType(e)}
197
+ >
198
+ <button data-value="cw" type="button"></button>
199
+ <button data-value="ccw" type="button"></button>
200
+ <button data-value="zigzag" type="button"></button>
201
+ <button data-value="zigzag-reverse" type="button"></button>
202
+ </div>
203
+ </div>
204
+ </fieldset>
205
+ `;
206
+ }
207
+ connectedCallback() {
208
+ super.connectedCallback();
209
+ if (this.property && this.property.event) {
210
+ Object.entries(this.property.event).forEach(entry => {
211
+ if (entry[0]) {
212
+ document.addEventListener(entry[0], entry[1]);
213
+ }
214
+ });
215
+ }
216
+ }
217
+ disconnectedCallback() {
218
+ super.disconnectedCallback();
219
+ if (this.property && this.property.event) {
220
+ Object.entries(this.property.event).forEach(entry => {
221
+ if (entry[0]) {
222
+ document.removeEventListener(entry[0], entry[1]);
223
+ }
224
+ });
225
+ }
226
+ }
227
+ _onTapType(e) {
228
+ var target = e.target;
229
+ const increasingDirection = target?.closest('[data-value]')?.getAttribute('data-value');
230
+ if (!increasingDirection) {
231
+ return;
232
+ }
233
+ this.dispatchEvent(new CustomEvent('i-need-selected', {
234
+ bubbles: true,
235
+ composed: true,
236
+ detail: {
237
+ callback: (selected) => {
238
+ const table = selected[0].parent;
239
+ table.increaseLocation(increasingDirection, this.skipNumbering, this.startSection, this.startUnit);
240
+ }
241
+ }
242
+ }));
243
+ e.stopPropagation();
244
+ }
245
+ };
254
246
  __decorate([
255
247
  property({ type: Number })
256
248
  ], LocationIncreasePatternEditor.prototype, "startSection", void 0);