@fmsim/board 2.0.0-beta.2 → 2.0.0-beta.21
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/custom-elements.json +1954 -778
- package/demo/index-modeller.html +1 -1
- package/demo/index-player.html +2 -2
- package/demo/index-viewer.html +2 -2
- package/demo/index.html +2 -2
- package/dist/src/component/etc.js +17 -0
- package/dist/src/component/etc.js.map +1 -1
- package/dist/src/data-storage/board-model-cache.d.ts +13 -0
- package/dist/src/data-storage/board-model-cache.js +66 -0
- package/dist/src/data-storage/board-model-cache.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.js +2 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/modeller/edit-toolbar-style.js +43 -3
- package/dist/src/modeller/edit-toolbar-style.js.map +1 -1
- package/dist/src/modeller/edit-toolbar.d.ts +8 -14
- package/dist/src/modeller/edit-toolbar.js +208 -211
- package/dist/src/modeller/edit-toolbar.js.map +1 -1
- package/dist/src/modeller/property-sidebar/property-sidebar.js +3 -16
- package/dist/src/modeller/property-sidebar/property-sidebar.js.map +1 -1
- package/dist/src/modeller/property-sidebar/styles/styles.d.ts +6 -4
- package/dist/src/modeller/property-sidebar/styles/styles.js +139 -436
- package/dist/src/modeller/property-sidebar/styles/styles.js.map +1 -1
- package/dist/src/modeller/scene-viewer/ox-scene-viewer.d.ts +2 -1
- package/dist/src/modeller/scene-viewer/ox-scene-viewer.js +5 -1
- package/dist/src/modeller/scene-viewer/ox-scene-viewer.js.map +1 -1
- package/dist/src/ox-board-list.js +2 -2
- package/dist/src/ox-board-list.js.map +1 -1
- package/dist/src/ox-board-modeller.d.ts +5 -2
- package/dist/src/ox-board-modeller.js +14 -4
- package/dist/src/ox-board-modeller.js.map +1 -1
- package/dist/src/ox-board-viewer.d.ts +22 -2
- package/dist/src/ox-board-viewer.js +247 -21
- package/dist/src/ox-board-viewer.js.map +1 -1
- package/dist/src/ox-editor-board-selector.d.ts +3 -0
- package/dist/src/ox-editor-board-selector.js +38 -9
- package/dist/src/ox-editor-board-selector.js.map +1 -1
- package/dist/src/ox-playback-controls.d.ts +60 -0
- package/dist/src/ox-playback-controls.js +512 -0
- package/dist/src/ox-playback-controls.js.map +1 -0
- package/dist/src/playback/playback-engine.d.ts +78 -0
- package/dist/src/playback/playback-engine.js +215 -0
- package/dist/src/playback/playback-engine.js.map +1 -0
- package/dist/src/selector/board-creation-popup.js +2 -2
- package/dist/src/selector/board-creation-popup.js.map +1 -1
- package/dist/src/selector/board-thumbnail-card.js +6 -6
- package/dist/src/selector/board-thumbnail-card.js.map +1 -1
- package/dist/src/selector/ox-board-creation-card.js +2 -2
- package/dist/src/selector/ox-board-creation-card.js.map +1 -1
- package/dist/src/selector/ox-board-selector.js +21 -10
- package/dist/src/selector/ox-board-selector.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/icons/icon-htoolbar.png +0 -0
- package/package.json +3 -6
|
@@ -3,8 +3,9 @@ import '@material/web/icon/icon.js';
|
|
|
3
3
|
import './layers/movement-layer.js';
|
|
4
4
|
import './ox-board-component-info.js';
|
|
5
5
|
import './layers/mcs-mouse-event-handler.js';
|
|
6
|
+
import './ox-playback-controls.js';
|
|
6
7
|
import { LitElement, PropertyValues } from 'lit';
|
|
7
|
-
import { Component, ReferenceProvider } from '@hatiolab/things-scene';
|
|
8
|
+
import { Component, LoadTracker, ReferenceProvider } from '@hatiolab/things-scene';
|
|
8
9
|
export declare class BoardViewer extends LitElement {
|
|
9
10
|
static styles: import("lit").CSSResult[];
|
|
10
11
|
baseUrl: string;
|
|
@@ -12,6 +13,8 @@ export declare class BoardViewer extends LitElement {
|
|
|
12
13
|
provider: ReferenceProvider | null;
|
|
13
14
|
data: any;
|
|
14
15
|
values: any;
|
|
16
|
+
/** 앱에서 미리 생성한 LoadTracker — fetch 시작 전 생성하면 네트워크 시간도 추적 */
|
|
17
|
+
loadTracker?: LoadTracker;
|
|
15
18
|
hideFullscreen: boolean;
|
|
16
19
|
hideNavigation: boolean;
|
|
17
20
|
_scene: any;
|
|
@@ -23,13 +26,17 @@ export declare class BoardViewer extends LitElement {
|
|
|
23
26
|
id: string;
|
|
24
27
|
scene: any;
|
|
25
28
|
}[];
|
|
29
|
+
private _loadingOverlay?;
|
|
26
30
|
_oldtarget: HTMLElement | null;
|
|
27
31
|
_fade_animations?: Array<Animation>;
|
|
32
|
+
_fabExpanded: boolean;
|
|
33
|
+
_playbackActive: boolean;
|
|
34
|
+
get _is3dMode(): boolean;
|
|
28
35
|
currentBoardId?: string;
|
|
29
36
|
_target: HTMLElement;
|
|
30
37
|
_prev: HTMLElement;
|
|
31
38
|
_next: HTMLElement;
|
|
32
|
-
|
|
39
|
+
_fabGroup: HTMLElement;
|
|
33
40
|
private popup;
|
|
34
41
|
private lastComponent;
|
|
35
42
|
render(): import("lit-html").TemplateResult<1>;
|
|
@@ -46,11 +53,13 @@ export declare class BoardViewer extends LitElement {
|
|
|
46
53
|
fmbStartAnimation: (e: Event) => void;
|
|
47
54
|
fmbStopAnimation: (e: Event) => void;
|
|
48
55
|
fmbResetAnimation: () => void;
|
|
56
|
+
private _pointerMoveHandler;
|
|
49
57
|
connectedCallback(): void;
|
|
50
58
|
disconnectedCallback(): void;
|
|
51
59
|
updated(changes: PropertyValues<this>): void;
|
|
52
60
|
initSceneAsync(): Promise<void>;
|
|
53
61
|
initScene(): void;
|
|
62
|
+
private _ensureOverlay;
|
|
54
63
|
closeScene(): void;
|
|
55
64
|
releaseScene(): void;
|
|
56
65
|
setupScene({ id, scene }: {
|
|
@@ -65,6 +74,17 @@ export declare class BoardViewer extends LitElement {
|
|
|
65
74
|
onTapNext(): void;
|
|
66
75
|
onTapPrev(): void;
|
|
67
76
|
onTapFullscreen(): void;
|
|
77
|
+
onTapToggle3D(): void;
|
|
78
|
+
private _playbackEngine?;
|
|
79
|
+
onTapPlayback(): void;
|
|
80
|
+
private _onPlaybackStart;
|
|
81
|
+
private _onPlaybackPause;
|
|
82
|
+
private _onPlaybackResume;
|
|
83
|
+
private _onPlaybackStop;
|
|
84
|
+
private _onPlaybackSeek;
|
|
85
|
+
private _onPlaybackSpeed;
|
|
86
|
+
/** 페이지에서 주입하는 playback 데이터 fetch 함수 */
|
|
87
|
+
_fetchPlaybackData?: (startTime: string, endTime: string) => Promise<any>;
|
|
68
88
|
onRunBoard(): void;
|
|
69
89
|
onLinkGoto(targetBoardId: string, options: any, fromComponent: any): void;
|
|
70
90
|
onLinkOpen(url: string, value: any, fromComponent: Component): void;
|
|
@@ -4,9 +4,11 @@ import '@material/web/icon/icon.js';
|
|
|
4
4
|
import './layers/movement-layer.js';
|
|
5
5
|
import './ox-board-component-info.js';
|
|
6
6
|
import './layers/mcs-mouse-event-handler.js';
|
|
7
|
-
import
|
|
7
|
+
import './ox-playback-controls.js';
|
|
8
|
+
import { css, html, LitElement, nothing } from 'lit';
|
|
8
9
|
import { customElement, property, query, state } from 'lit/decorators.js';
|
|
9
|
-
import {
|
|
10
|
+
import { PlaybackEngine } from './playback/playback-engine.js';
|
|
11
|
+
import { create, LoadTracker, LoadingOverlay, SCENE_MODE } from '@hatiolab/things-scene';
|
|
10
12
|
import { isIOS, togglefullscreen } from '@operato/utils';
|
|
11
13
|
import { ScrollbarStyles } from '@operato/styles';
|
|
12
14
|
import { DataStorage } from './data-storage/data-storage.js';
|
|
@@ -24,6 +26,8 @@ let BoardViewer = class BoardViewer extends LitElement {
|
|
|
24
26
|
this._forward = [];
|
|
25
27
|
this._backward = [];
|
|
26
28
|
this._oldtarget = null;
|
|
29
|
+
this._fabExpanded = false;
|
|
30
|
+
this._playbackActive = false;
|
|
27
31
|
this.currentBoardId = (_a = this.board) === null || _a === void 0 ? void 0 : _a.id;
|
|
28
32
|
this.popup = null;
|
|
29
33
|
this.lastComponent = null;
|
|
@@ -33,7 +37,6 @@ let BoardViewer = class BoardViewer extends LitElement {
|
|
|
33
37
|
const id = e.detail.value;
|
|
34
38
|
const components = (_a = this._scene) === null || _a === void 0 ? void 0 : _a.findAll(`#${id}`);
|
|
35
39
|
if (!components || components.length == 0) {
|
|
36
|
-
console.log('No equipment was found.');
|
|
37
40
|
return;
|
|
38
41
|
}
|
|
39
42
|
window.dispatchEvent(new CustomEvent('clickComponent', { detail: components[0] }));
|
|
@@ -173,20 +176,50 @@ let BoardViewer = class BoardViewer extends LitElement {
|
|
|
173
176
|
var _a;
|
|
174
177
|
(_a = this._scene) === null || _a === void 0 ? void 0 : _a.root.trigger('deco-reset');
|
|
175
178
|
};
|
|
179
|
+
this._pointerMoveHandler = () => this.transientShowButtons();
|
|
176
180
|
this.resizeHandler = () => {
|
|
177
181
|
this._scene && this._scene.fit();
|
|
178
182
|
};
|
|
179
183
|
}
|
|
184
|
+
get _is3dMode() {
|
|
185
|
+
var _a, _b, _c;
|
|
186
|
+
return !!((_c = (_b = (_a = this._scene) === null || _a === void 0 ? void 0 : _a.root) === null || _b === void 0 ? void 0 : _b.state) === null || _c === void 0 ? void 0 : _c.threed);
|
|
187
|
+
}
|
|
180
188
|
render() {
|
|
181
|
-
var
|
|
189
|
+
var _a, _b;
|
|
190
|
+
var fabGroup = !isIOS() && !this.hideFullscreen
|
|
182
191
|
? html `
|
|
183
|
-
<
|
|
184
|
-
|
|
185
|
-
|
|
192
|
+
<div
|
|
193
|
+
fab-group
|
|
194
|
+
?expanded=${this._fabExpanded}
|
|
186
195
|
@mouseover=${(e) => this.transientShowButtons(true)}
|
|
187
196
|
@mouseout=${(e) => this.transientShowButtons()}
|
|
188
|
-
|
|
189
|
-
|
|
197
|
+
>
|
|
198
|
+
<md-fab
|
|
199
|
+
class="main-fab"
|
|
200
|
+
?expanded=${this._fabExpanded}
|
|
201
|
+
@click=${() => { this._fabExpanded = !this._fabExpanded; }}
|
|
202
|
+
title="menu"
|
|
203
|
+
><md-icon slot="icon">add</md-icon></md-fab>
|
|
204
|
+
|
|
205
|
+
<md-fab
|
|
206
|
+
class="sub-fab"
|
|
207
|
+
@click=${() => { this._fabExpanded = false; this.onTapFullscreen(); }}
|
|
208
|
+
title="fullscreen"
|
|
209
|
+
><md-icon slot="icon">${document.fullscreenElement ? 'fullscreen_exit' : 'fullscreen'}</md-icon></md-fab>
|
|
210
|
+
|
|
211
|
+
<md-fab
|
|
212
|
+
class="sub-fab"
|
|
213
|
+
@click=${() => { this._fabExpanded = false; this.onTapPlayback(); }}
|
|
214
|
+
title=${this._playbackActive ? 'stop playback' : 'start playback'}
|
|
215
|
+
><md-icon slot="icon">${this._playbackActive ? 'stop' : 'replay'}</md-icon></md-fab>
|
|
216
|
+
|
|
217
|
+
<md-fab
|
|
218
|
+
class="sub-fab"
|
|
219
|
+
@click=${() => { this._fabExpanded = false; this.onTapToggle3D(); }}
|
|
220
|
+
title=${this._is3dMode ? '2D mode' : '3D mode'}
|
|
221
|
+
><md-icon slot="icon">${this._is3dMode ? 'view_in_ar' : '3d_rotation'}</md-icon></md-fab>
|
|
222
|
+
</div>
|
|
190
223
|
`
|
|
191
224
|
: html ``;
|
|
192
225
|
var prev = !this.hideNavigation
|
|
@@ -216,19 +249,29 @@ let BoardViewer = class BoardViewer extends LitElement {
|
|
|
216
249
|
return html `
|
|
217
250
|
${prev}
|
|
218
251
|
|
|
219
|
-
<div
|
|
220
|
-
id="target"
|
|
221
|
-
@touchstart=${(e) => this.transientShowButtons()}
|
|
222
|
-
@mousemove=${(e) => this.transientShowButtons()}
|
|
223
|
-
></div>
|
|
252
|
+
<div id="target"></div>
|
|
224
253
|
|
|
225
254
|
<slot></slot>
|
|
226
|
-
${next} ${
|
|
255
|
+
${next} ${fabGroup}
|
|
256
|
+
|
|
257
|
+
${this._playbackActive
|
|
258
|
+
? html `<ox-playback-controls
|
|
259
|
+
.playbackState=${((_a = this._playbackEngine) === null || _a === void 0 ? void 0 : _a.state) === 'playing' ? 'playing' : ((_b = this._playbackEngine) === null || _b === void 0 ? void 0 : _b.state) === 'paused' ? 'paused' : 'idle'}
|
|
260
|
+
@playback-start=${this._onPlaybackStart}
|
|
261
|
+
@playback-pause=${this._onPlaybackPause}
|
|
262
|
+
@playback-resume=${this._onPlaybackResume}
|
|
263
|
+
@playback-stop=${this._onPlaybackStop}
|
|
264
|
+
@playback-seek=${this._onPlaybackSeek}
|
|
265
|
+
@playback-speed=${this._onPlaybackSpeed}
|
|
266
|
+
></ox-playback-controls>`
|
|
267
|
+
: nothing}
|
|
227
268
|
`;
|
|
228
269
|
}
|
|
229
270
|
connectedCallback() {
|
|
230
271
|
super.connectedCallback();
|
|
231
272
|
window.addEventListener('resize', this.resizeHandler);
|
|
273
|
+
// 3D 모드에서도 마우스 움직임 감지 (document 레벨, capture phase)
|
|
274
|
+
document.addEventListener('pointermove', this._pointerMoveHandler, true);
|
|
232
275
|
this.renderRoot.addEventListener('close-scene', e => {
|
|
233
276
|
e.preventDefault();
|
|
234
277
|
this.onTapPrev();
|
|
@@ -258,6 +301,7 @@ let BoardViewer = class BoardViewer extends LitElement {
|
|
|
258
301
|
disconnectedCallback() {
|
|
259
302
|
super.disconnectedCallback();
|
|
260
303
|
window.removeEventListener('resize', this.resizeHandler);
|
|
304
|
+
document.removeEventListener('pointermove', this._pointerMoveHandler, true);
|
|
261
305
|
// 모니터링에서 장비 아이디에 해당하는 object를 찾아 캔버스 가운데 위치하도록 조정한다.
|
|
262
306
|
window.removeEventListener('fetchIFactsData', this.fetchIFactsDataHandler);
|
|
263
307
|
// 모니터링에서 Movement Data를 보여준다.
|
|
@@ -280,10 +324,25 @@ let BoardViewer = class BoardViewer extends LitElement {
|
|
|
280
324
|
window.removeEventListener('fmbShowFloatingContainer', this.fmbShowFloatingContainerHandler);
|
|
281
325
|
window.removeEventListener('fmbHideFloatingContainer', this.fmbHideFloatingContainerHandler);
|
|
282
326
|
this.lastComponent = null;
|
|
327
|
+
// 플레이백 정리
|
|
328
|
+
if (this._playbackEngine) {
|
|
329
|
+
this._playbackEngine.dispose();
|
|
330
|
+
this._playbackEngine = undefined;
|
|
331
|
+
}
|
|
332
|
+
this._playbackActive = false;
|
|
283
333
|
this.closeScene();
|
|
284
334
|
}
|
|
285
335
|
updated(changes) {
|
|
336
|
+
// loadTracker가 외부에서 전달되면 즉시 overlay 연결 (fetch 중에도 표시)
|
|
337
|
+
if (changes.has('loadTracker') && this.loadTracker) {
|
|
338
|
+
this._ensureOverlay(this.loadTracker);
|
|
339
|
+
}
|
|
286
340
|
if (changes.has('board')) {
|
|
341
|
+
// tracker: 외부에서 안 왔으면 여기서 생성
|
|
342
|
+
if (!this.loadTracker) {
|
|
343
|
+
this.loadTracker = new LoadTracker();
|
|
344
|
+
this._ensureOverlay(this.loadTracker);
|
|
345
|
+
}
|
|
287
346
|
this.hidePopup();
|
|
288
347
|
this.closeScene();
|
|
289
348
|
if (this.board && this.board.id) {
|
|
@@ -322,13 +381,20 @@ let BoardViewer = class BoardViewer extends LitElement {
|
|
|
322
381
|
layers: [{ type: 'scroll-layer' }, { type: 'movement-layer', id: 'movement-layer' }],
|
|
323
382
|
refProvider: this.provider,
|
|
324
383
|
dataStorage: this.board.id !== 'preview' ? new DataStorage(this.board.id) : undefined,
|
|
325
|
-
dataSubscriptionProvider: isRestfulAvailable() ? undefined : new DataSubscriptionProviderImpl()
|
|
384
|
+
dataSubscriptionProvider: isRestfulAvailable() ? undefined : new DataSubscriptionProviderImpl(),
|
|
385
|
+
loading: this.loadTracker ? { tracker: this.loadTracker } : undefined
|
|
326
386
|
});
|
|
327
387
|
if (this.baseUrl) {
|
|
328
388
|
this._scene.baseUrl = this.baseUrl;
|
|
329
389
|
}
|
|
330
390
|
this.setupScene({ id: this.board.id, scene: this._scene });
|
|
331
391
|
}
|
|
392
|
+
_ensureOverlay(tracker) {
|
|
393
|
+
if (!this._loadingOverlay) {
|
|
394
|
+
this._loadingOverlay = new LoadingOverlay();
|
|
395
|
+
}
|
|
396
|
+
this._loadingOverlay.attach(this.renderRoot, tracker);
|
|
397
|
+
}
|
|
332
398
|
closeScene() {
|
|
333
399
|
if (this._scene) {
|
|
334
400
|
this.unbindSceneEvents(this._scene);
|
|
@@ -348,6 +414,10 @@ let BoardViewer = class BoardViewer extends LitElement {
|
|
|
348
414
|
}
|
|
349
415
|
setupScene({ id, scene }) {
|
|
350
416
|
var _a;
|
|
417
|
+
// 플레이백 리셋
|
|
418
|
+
if (this._playbackActive) {
|
|
419
|
+
this._onPlaybackStop();
|
|
420
|
+
}
|
|
351
421
|
this._scene = scene;
|
|
352
422
|
const backgroundColor = (_a = this._scene) === null || _a === void 0 ? void 0 : _a.root.state.fillStyle;
|
|
353
423
|
if (typeof backgroundColor === 'string') {
|
|
@@ -424,7 +494,7 @@ let BoardViewer = class BoardViewer extends LitElement {
|
|
|
424
494
|
transientShowButtons(stop) {
|
|
425
495
|
var buttons = [];
|
|
426
496
|
!this.hideNavigation && buttons.push(this._next, this._prev);
|
|
427
|
-
!this.hideFullscreen && buttons.push(this.
|
|
497
|
+
!this.hideFullscreen && buttons.push(this._fabGroup);
|
|
428
498
|
if (buttons.length == 0) {
|
|
429
499
|
return;
|
|
430
500
|
}
|
|
@@ -447,7 +517,7 @@ let BoardViewer = class BoardViewer extends LitElement {
|
|
|
447
517
|
}
|
|
448
518
|
this._forward.length <= 0 ? this._next.setAttribute('hidden', '') : this._next.removeAttribute('hidden');
|
|
449
519
|
this._backward.length <= 0 ? this._prev.setAttribute('hidden', '') : this._prev.removeAttribute('hidden');
|
|
450
|
-
this.
|
|
520
|
+
this._fabGroup && this._fabGroup.removeAttribute('hidden');
|
|
451
521
|
this._fade_animations.forEach(animation => {
|
|
452
522
|
animation.cancel();
|
|
453
523
|
if (stop)
|
|
@@ -485,6 +555,109 @@ let BoardViewer = class BoardViewer extends LitElement {
|
|
|
485
555
|
onTapFullscreen() {
|
|
486
556
|
togglefullscreen(this, () => this.requestUpdate(), () => this.requestUpdate());
|
|
487
557
|
}
|
|
558
|
+
onTapToggle3D() {
|
|
559
|
+
var _a;
|
|
560
|
+
if (!this._scene)
|
|
561
|
+
return;
|
|
562
|
+
const root = this._scene.root;
|
|
563
|
+
if (!root)
|
|
564
|
+
return;
|
|
565
|
+
const entering3D = !this._is3dMode;
|
|
566
|
+
root.set('threed', entering3D);
|
|
567
|
+
this.requestUpdate();
|
|
568
|
+
if (entering3D) {
|
|
569
|
+
const capability = (_a = root.rootModel) === null || _a === void 0 ? void 0 : _a._threeCapability;
|
|
570
|
+
if (capability === null || capability === void 0 ? void 0 : capability.isInitialized) {
|
|
571
|
+
capability.controlsManager.reset();
|
|
572
|
+
capability.controlsManager.setAutoRotate(true);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
onTapPlayback() {
|
|
577
|
+
if (this._playbackActive) {
|
|
578
|
+
this._onPlaybackStop();
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
this._playbackActive = true;
|
|
582
|
+
if (!this._playbackEngine) {
|
|
583
|
+
this._playbackEngine = new PlaybackEngine();
|
|
584
|
+
this._playbackEngine.on('frame', ({ time }) => {
|
|
585
|
+
const controls = this.renderRoot.querySelector('ox-playback-controls');
|
|
586
|
+
if (controls)
|
|
587
|
+
controls.currentTime = time;
|
|
588
|
+
});
|
|
589
|
+
this._playbackEngine.on('state-change', (state) => {
|
|
590
|
+
if (state === 'stopped') {
|
|
591
|
+
const controls = this.renderRoot.querySelector('ox-playback-controls');
|
|
592
|
+
if (controls)
|
|
593
|
+
controls.playbackState = 'stopped';
|
|
594
|
+
}
|
|
595
|
+
this.requestUpdate();
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
if (this._scene) {
|
|
599
|
+
this._playbackEngine.attachScene(this._scene);
|
|
600
|
+
}
|
|
601
|
+
this.dispatchEvent(new CustomEvent('playback-toggle', {
|
|
602
|
+
bubbles: true,
|
|
603
|
+
composed: true,
|
|
604
|
+
detail: { active: true }
|
|
605
|
+
}));
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
async _onPlaybackStart(e) {
|
|
609
|
+
var _a;
|
|
610
|
+
const { fromTime, speed } = e.detail;
|
|
611
|
+
if (!this._playbackEngine)
|
|
612
|
+
return;
|
|
613
|
+
const endTime = new Date(fromTime.getTime() + 3600000);
|
|
614
|
+
const fmt = (d) => {
|
|
615
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
616
|
+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
|
|
617
|
+
};
|
|
618
|
+
// 라이브 데이터 구독 일시 중단
|
|
619
|
+
this.dispatchEvent(new CustomEvent('playback-live-pause', { bubbles: true, composed: true }));
|
|
620
|
+
try {
|
|
621
|
+
// fetchPlayback은 페이지에서 주입 (api 패키지 의존 방지)
|
|
622
|
+
const result = await ((_a = this._fetchPlaybackData) === null || _a === void 0 ? void 0 : _a.call(this, fmt(fromTime), fmt(endTime)));
|
|
623
|
+
if ((result === null || result === void 0 ? void 0 : result.status) && result.playback) {
|
|
624
|
+
this._playbackEngine.loadData(result.playback.scenarios);
|
|
625
|
+
this._playbackEngine.play(speed);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
catch (ex) {
|
|
629
|
+
console.error('[Playback] load failed:', ex);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
_onPlaybackPause() {
|
|
633
|
+
var _a;
|
|
634
|
+
(_a = this._playbackEngine) === null || _a === void 0 ? void 0 : _a.pause();
|
|
635
|
+
}
|
|
636
|
+
_onPlaybackResume() {
|
|
637
|
+
var _a;
|
|
638
|
+
(_a = this._playbackEngine) === null || _a === void 0 ? void 0 : _a.resume();
|
|
639
|
+
}
|
|
640
|
+
_onPlaybackStop() {
|
|
641
|
+
var _a, _b;
|
|
642
|
+
(_a = this._playbackEngine) === null || _a === void 0 ? void 0 : _a.stop();
|
|
643
|
+
(_b = this._playbackEngine) === null || _b === void 0 ? void 0 : _b.detachScene();
|
|
644
|
+
this._playbackActive = false;
|
|
645
|
+
// 라이브 데이터 구독 재개
|
|
646
|
+
this.dispatchEvent(new CustomEvent('playback-live-resume', { bubbles: true, composed: true }));
|
|
647
|
+
this.dispatchEvent(new CustomEvent('playback-toggle', {
|
|
648
|
+
bubbles: true,
|
|
649
|
+
composed: true,
|
|
650
|
+
detail: { active: false }
|
|
651
|
+
}));
|
|
652
|
+
}
|
|
653
|
+
_onPlaybackSeek(e) {
|
|
654
|
+
var _a;
|
|
655
|
+
(_a = this._playbackEngine) === null || _a === void 0 ? void 0 : _a.seekTo(e.detail.toTime);
|
|
656
|
+
}
|
|
657
|
+
_onPlaybackSpeed(e) {
|
|
658
|
+
var _a;
|
|
659
|
+
(_a = this._playbackEngine) === null || _a === void 0 ? void 0 : _a.setSpeed(e.detail.speed);
|
|
660
|
+
}
|
|
488
661
|
onRunBoard() {
|
|
489
662
|
this.dispatchEvent(new CustomEvent('run-board', { bubbles: true, composed: true, detail: this.board.id }));
|
|
490
663
|
}
|
|
@@ -643,10 +816,51 @@ BoardViewer.styles = [
|
|
|
643
816
|
right: 5px;
|
|
644
817
|
}
|
|
645
818
|
|
|
646
|
-
|
|
819
|
+
[fab-group] {
|
|
647
820
|
position: absolute;
|
|
648
821
|
bottom: 15px;
|
|
649
822
|
right: 16px;
|
|
823
|
+
display: flex;
|
|
824
|
+
flex-direction: column-reverse;
|
|
825
|
+
align-items: center;
|
|
826
|
+
gap: 12px;
|
|
827
|
+
z-index: 1000;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
[fab-group] md-fab {
|
|
831
|
+
transition: transform 0.2s ease, opacity 0.2s ease;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
[fab-group] md-fab.main-fab md-icon {
|
|
835
|
+
transition: transform 0.3s ease;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
[fab-group] md-fab.main-fab[expanded] md-icon {
|
|
839
|
+
transform: rotate(45deg);
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
[fab-group] md-fab.sub-fab {
|
|
843
|
+
--md-fab-container-width: 40px;
|
|
844
|
+
--md-fab-container-height: 40px;
|
|
845
|
+
--md-icon-size: 20px;
|
|
846
|
+
transform: scale(0);
|
|
847
|
+
opacity: 0;
|
|
848
|
+
pointer-events: none;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
[fab-group][expanded] md-fab.sub-fab {
|
|
852
|
+
transform: scale(1);
|
|
853
|
+
opacity: 1;
|
|
854
|
+
pointer-events: auto;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
[fab-group] md-fab.sub-fab[disabled] {
|
|
858
|
+
opacity: 0.4;
|
|
859
|
+
pointer-events: none;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
ox-playback-controls {
|
|
863
|
+
transition: opacity 0.3s ease;
|
|
650
864
|
}
|
|
651
865
|
|
|
652
866
|
[hidden] {
|
|
@@ -693,6 +907,9 @@ __decorate([
|
|
|
693
907
|
__decorate([
|
|
694
908
|
property({ type: Object })
|
|
695
909
|
], BoardViewer.prototype, "values", void 0);
|
|
910
|
+
__decorate([
|
|
911
|
+
property({ type: Object })
|
|
912
|
+
], BoardViewer.prototype, "loadTracker", void 0);
|
|
696
913
|
__decorate([
|
|
697
914
|
property({ type: Boolean, reflect: true, attribute: 'hide-fullscreen' })
|
|
698
915
|
], BoardViewer.prototype, "hideFullscreen", void 0);
|
|
@@ -714,6 +931,12 @@ __decorate([
|
|
|
714
931
|
__decorate([
|
|
715
932
|
state()
|
|
716
933
|
], BoardViewer.prototype, "_fade_animations", void 0);
|
|
934
|
+
__decorate([
|
|
935
|
+
state()
|
|
936
|
+
], BoardViewer.prototype, "_fabExpanded", void 0);
|
|
937
|
+
__decorate([
|
|
938
|
+
state()
|
|
939
|
+
], BoardViewer.prototype, "_playbackActive", void 0);
|
|
717
940
|
__decorate([
|
|
718
941
|
query('#target')
|
|
719
942
|
], BoardViewer.prototype, "_target", void 0);
|
|
@@ -724,8 +947,11 @@ __decorate([
|
|
|
724
947
|
query('#next')
|
|
725
948
|
], BoardViewer.prototype, "_next", void 0);
|
|
726
949
|
__decorate([
|
|
727
|
-
query('
|
|
728
|
-
], BoardViewer.prototype, "
|
|
950
|
+
query('[fab-group]')
|
|
951
|
+
], BoardViewer.prototype, "_fabGroup", void 0);
|
|
952
|
+
__decorate([
|
|
953
|
+
property({ attribute: false })
|
|
954
|
+
], BoardViewer.prototype, "_fetchPlaybackData", void 0);
|
|
729
955
|
BoardViewer = __decorate([
|
|
730
956
|
customElement('ox-board-viewer')
|
|
731
957
|
], BoardViewer);
|