@fmsim/board 1.0.88 → 2.0.0-beta.101
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 +7366 -3448
- 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 +36 -0
- package/dist/src/component/etc.js.map +1 -1
- package/dist/src/component/index.d.ts +1 -0
- package/dist/src/component/index.js +1 -0
- package/dist/src/component/index.js.map +1 -1
- package/dist/src/component/restful-attachment-creation-card.js +1 -1
- package/dist/src/component/restful-attachment-creation-card.js.map +1 -1
- package/dist/src/component/restful-attachment-selector.js +8 -9
- package/dist/src/component/restful-attachment-selector.js.map +1 -1
- package/dist/src/component/restful-input-attachment-selector.d.ts +1 -1
- package/dist/src/component/restful-input-attachment-selector.js +3 -3
- package/dist/src/component/restful-input-attachment-selector.js.map +1 -1
- package/dist/src/component/restful-input-fill-style.d.ts +13 -2
- package/dist/src/component/restful-input-fill-style.js.map +1 -1
- package/dist/src/component/restful-property-editor-backdrop-faces.d.ts +50 -0
- package/dist/src/component/restful-property-editor-backdrop-faces.js +524 -0
- package/dist/src/component/restful-property-editor-backdrop-faces.js.map +1 -0
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/layers/mcs-mouse-event-handler.js +8 -0
- package/dist/src/layers/mcs-mouse-event-handler.js.map +1 -1
- package/dist/src/layers/movement-layer.d.ts +7 -6
- package/dist/src/layers/movement-layer.js +56 -11
- package/dist/src/layers/movement-layer.js.map +1 -1
- package/dist/src/modeller/bulk-create-dialog.d.ts +51 -0
- package/dist/src/modeller/bulk-create-dialog.js +531 -0
- package/dist/src/modeller/bulk-create-dialog.js.map +1 -0
- package/dist/src/modeller/bulk-create.d.ts +101 -0
- package/dist/src/modeller/bulk-create.js +199 -0
- package/dist/src/modeller/bulk-create.js.map +1 -0
- package/dist/src/modeller/component-toolbar/component-menu.d.ts +1 -1
- package/dist/src/modeller/component-toolbar/component-toolbar.d.ts +4 -4
- package/dist/src/modeller/component-toolbar/component-toolbar.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 +21 -14
- package/dist/src/modeller/edit-toolbar.js +371 -213
- package/dist/src/modeller/edit-toolbar.js.map +1 -1
- package/dist/src/modeller/property-sidebar/abstract-property.js +10 -2
- package/dist/src/modeller/property-sidebar/abstract-property.js.map +1 -1
- package/dist/src/modeller/property-sidebar/data-binding/data-binding-mapper.js +1 -1
- package/dist/src/modeller/property-sidebar/data-binding/data-binding-mapper.js.map +1 -1
- package/dist/src/modeller/property-sidebar/data-binding/data-binding.d.ts +2 -2
- package/dist/src/modeller/property-sidebar/data-binding/data-binding.js +18 -18
- package/dist/src/modeller/property-sidebar/data-binding/data-binding.js.map +1 -1
- package/dist/src/modeller/property-sidebar/effects/effects.d.ts +10 -1
- package/dist/src/modeller/property-sidebar/effects/effects.js +66 -1
- package/dist/src/modeller/property-sidebar/effects/effects.js.map +1 -1
- package/dist/src/modeller/property-sidebar/effects/event-handler-adapter.d.ts +44 -0
- package/dist/src/modeller/property-sidebar/effects/event-handler-adapter.js +70 -0
- package/dist/src/modeller/property-sidebar/effects/event-handler-adapter.js.map +1 -0
- package/dist/src/modeller/property-sidebar/effects/property-event-hover.js +3 -3
- package/dist/src/modeller/property-sidebar/effects/property-event-hover.js.map +1 -1
- package/dist/src/modeller/property-sidebar/effects/property-event.d.ts +13 -3
- package/dist/src/modeller/property-sidebar/effects/property-event.js +20 -11
- package/dist/src/modeller/property-sidebar/effects/property-event.js.map +1 -1
- package/dist/src/modeller/property-sidebar/inspector/inspector-controller.d.ts +62 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector-controller.js +276 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector-controller.js.map +1 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector-group-view.d.ts +15 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector-group-view.js +56 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector-group-view.js.map +1 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector-highlight.d.ts +7 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector-highlight.js +25 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector-highlight.js.map +1 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector-model.d.ts +44 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector-model.js +72 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector-model.js.map +1 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector-tree-view.d.ts +18 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector-tree-view.js +61 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector-tree-view.js.map +1 -0
- package/dist/src/modeller/property-sidebar/inspector/inspector.d.ts +17 -12
- package/dist/src/modeller/property-sidebar/inspector/inspector.js +281 -154
- package/dist/src/modeller/property-sidebar/inspector/inspector.js.map +1 -1
- package/dist/src/modeller/property-sidebar/property-sidebar.d.ts +2 -2
- package/dist/src/modeller/property-sidebar/property-sidebar.js +11 -24
- package/dist/src/modeller/property-sidebar/property-sidebar.js.map +1 -1
- package/dist/src/modeller/property-sidebar/shapes/ox-input-entity-id.d.ts +75 -0
- package/dist/src/modeller/property-sidebar/shapes/ox-input-entity-id.js +346 -0
- package/dist/src/modeller/property-sidebar/shapes/ox-input-entity-id.js.map +1 -0
- package/dist/src/modeller/property-sidebar/shapes/shapes.d.ts +23 -2
- package/dist/src/modeller/property-sidebar/shapes/shapes.js +96 -4
- package/dist/src/modeller/property-sidebar/shapes/shapes.js.map +1 -1
- package/dist/src/modeller/property-sidebar/specifics/specifics.d.ts +25 -1
- package/dist/src/modeller/property-sidebar/specifics/specifics.js +112 -2
- package/dist/src/modeller/property-sidebar/specifics/specifics.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 +140 -437
- package/dist/src/modeller/property-sidebar/styles/styles.js.map +1 -1
- package/dist/src/modeller/scene-viewer/ox-scene-layer.d.ts +4 -3
- package/dist/src/modeller/scene-viewer/ox-scene-layer.js +2 -1
- package/dist/src/modeller/scene-viewer/ox-scene-layer.js.map +1 -1
- package/dist/src/modeller/scene-viewer/ox-scene-viewer.d.ts +6 -5
- package/dist/src/modeller/scene-viewer/ox-scene-viewer.js +7 -3
- package/dist/src/modeller/scene-viewer/ox-scene-viewer.js.map +1 -1
- package/dist/src/ox-board-component-info.d.ts +3 -3
- package/dist/src/ox-board-component-info.js +58 -19
- package/dist/src/ox-board-component-info.js.map +1 -1
- package/dist/src/ox-board-list.js +12 -12
- package/dist/src/ox-board-list.js.map +1 -1
- package/dist/src/ox-board-modeller.d.ts +9 -6
- package/dist/src/ox-board-modeller.js +32 -33
- package/dist/src/ox-board-modeller.js.map +1 -1
- package/dist/src/ox-board-viewer.d.ts +129 -17
- package/dist/src/ox-board-viewer.js +804 -115
- package/dist/src/ox-board-viewer.js.map +1 -1
- package/dist/src/ox-editor-board-selector.d.ts +4 -1
- package/dist/src/ox-editor-board-selector.js +41 -12
- package/dist/src/ox-editor-board-selector.js.map +1 -1
- package/dist/src/ox-playback-controls.d.ts +157 -0
- package/dist/src/ox-playback-controls.js +1089 -0
- package/dist/src/ox-playback-controls.js.map +1 -0
- package/dist/src/ox-property-editor-theme.js +2 -2
- package/dist/src/ox-property-editor-theme.js.map +1 -1
- package/dist/src/playback/carrier-tracking-store.d.ts +51 -0
- package/dist/src/playback/carrier-tracking-store.js +115 -0
- package/dist/src/playback/carrier-tracking-store.js.map +1 -0
- package/dist/src/playback/playback-engine.d.ts +106 -0
- package/dist/src/playback/playback-engine.js +395 -0
- package/dist/src/playback/playback-engine.js.map +1 -0
- package/dist/src/selector/board-creation-popup.d.ts +4 -5
- package/dist/src/selector/board-creation-popup.js +16 -19
- package/dist/src/selector/board-creation-popup.js.map +1 -1
- package/dist/src/selector/board-thumbnail-card.js +8 -8
- package/dist/src/selector/board-thumbnail-card.js.map +1 -1
- package/dist/src/selector/ox-board-creation-card.d.ts +1 -1
- package/dist/src/selector/ox-board-creation-card.js +7 -7
- 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/components/text.png +0 -0
- package/icons/fab/mode-2d.svg +25 -0
- package/icons/fab/mode-3d.svg +25 -0
- package/icons/fab/playback-play.svg +49 -0
- package/icons/fab/playback-stop.svg +50 -0
- package/icons/icon-htoolbar.png +0 -0
- package/package.json +22 -21
|
@@ -3,18 +3,72 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { __decorate } from "tslib";
|
|
5
5
|
import { html, LitElement } from 'lit';
|
|
6
|
-
import { property,
|
|
6
|
+
import { property, state } from 'lit/decorators.js';
|
|
7
7
|
import { copyToClipboard, isMacOS } from '@operato/utils';
|
|
8
|
+
import { OxPopup } from '@operato/popup';
|
|
8
9
|
import { style } from './edit-toolbar-style';
|
|
10
|
+
import './bulk-create-dialog.js';
|
|
9
11
|
const MACOS = isMacOS();
|
|
12
|
+
/**
|
|
13
|
+
* 컴포넌트 model JSON 만으로 type-aware bounding box (width, height) 추출.
|
|
14
|
+
*
|
|
15
|
+
* things-scene 의 component.bounds 는 *path 의 bounding box* 인데, model JSON 만
|
|
16
|
+
* 으로는 path 를 그릴 수 없으므로 type-specific 필드를 직접 본다.
|
|
17
|
+
* - width/height 명시 (Rect, Container 등) → 그대로
|
|
18
|
+
* - rx/ry (Ellipse 등) → 2*rx, 2*ry
|
|
19
|
+
* - points 배열 (Line, Polygon 등) → 점들의 bounding box
|
|
20
|
+
* - 그 외 → 50x50 fallback
|
|
21
|
+
*
|
|
22
|
+
* bulk-paste 가 영역 안에 N 개 복제할 때 *원본 크기를 보존* 하기 위해 사용.
|
|
23
|
+
*/
|
|
24
|
+
function deriveBoundsFromModel(model) {
|
|
25
|
+
if (typeof model.width === 'number' && typeof model.height === 'number') {
|
|
26
|
+
return { width: model.width, height: model.height };
|
|
27
|
+
}
|
|
28
|
+
if (typeof model.rx === 'number' && typeof model.ry === 'number') {
|
|
29
|
+
return { width: 2 * Math.abs(model.rx), height: 2 * Math.abs(model.ry) };
|
|
30
|
+
}
|
|
31
|
+
if (Array.isArray(model.points) && model.points.length > 0) {
|
|
32
|
+
let minX = Infinity;
|
|
33
|
+
let maxX = -Infinity;
|
|
34
|
+
let minY = Infinity;
|
|
35
|
+
let maxY = -Infinity;
|
|
36
|
+
for (const p of model.points) {
|
|
37
|
+
if (typeof (p === null || p === void 0 ? void 0 : p.x) === 'number') {
|
|
38
|
+
if (p.x < minX)
|
|
39
|
+
minX = p.x;
|
|
40
|
+
if (p.x > maxX)
|
|
41
|
+
maxX = p.x;
|
|
42
|
+
}
|
|
43
|
+
if (typeof (p === null || p === void 0 ? void 0 : p.y) === 'number') {
|
|
44
|
+
if (p.y < minY)
|
|
45
|
+
minY = p.y;
|
|
46
|
+
if (p.y > maxY)
|
|
47
|
+
maxY = p.y;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (isFinite(minX) && isFinite(maxX) && isFinite(minY) && isFinite(maxY)) {
|
|
51
|
+
return { width: maxX - minX, height: maxY - minY };
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return { width: 50, height: 50 };
|
|
55
|
+
}
|
|
10
56
|
export class EditToolbar extends LitElement {
|
|
11
57
|
constructor() {
|
|
12
58
|
super(...arguments);
|
|
13
59
|
this.selected = [];
|
|
14
60
|
this.hideProperty = false;
|
|
61
|
+
this._dimension = null;
|
|
62
|
+
this._gizmoAttached = false;
|
|
15
63
|
}
|
|
16
64
|
firstUpdated() {
|
|
17
65
|
this.addEventListener('mousewheel', this.onWheelEvent.bind(this), false);
|
|
66
|
+
// 툴바 버튼 클릭 후 씬으로 포커스를 돌려서 키보드 단축키가 계속 작동하도록 한다
|
|
67
|
+
this.addEventListener('click', () => {
|
|
68
|
+
var _a, _b, _c;
|
|
69
|
+
;
|
|
70
|
+
(_c = (_b = (_a = this.scene) === null || _a === void 0 ? void 0 : _a.root) === null || _b === void 0 ? void 0 : _b.element) === null || _c === void 0 ? void 0 : _c.focus();
|
|
71
|
+
});
|
|
18
72
|
window.addEventListener('paste', (e) => {
|
|
19
73
|
var _a;
|
|
20
74
|
try {
|
|
@@ -24,29 +78,7 @@ export class EditToolbar extends LitElement {
|
|
|
24
78
|
console.error('model paste failed', e);
|
|
25
79
|
}
|
|
26
80
|
});
|
|
27
|
-
|
|
28
|
-
this.zorders.forEach(zorder => zorder.addEventListener('tap', this.onTapZorder.bind(this)));
|
|
29
|
-
this.distributes.forEach(distribute => distribute.addEventListener('tap', this.onTapDistribute.bind(this)));
|
|
30
|
-
this.undo.addEventListener('tap', this.onTapUndo.bind(this));
|
|
31
|
-
this.redo.addEventListener('tap', this.onTapRedo.bind(this));
|
|
32
|
-
this.fullscreen.addEventListener('tap', this.onTapFullscreen.bind(this));
|
|
33
|
-
this.cut.addEventListener('tap', this.onTapCut.bind(this));
|
|
34
|
-
this.copy.addEventListener('tap', this.onTapCopy.bind(this));
|
|
35
|
-
this.paste.addEventListener('tap', this.onTapPaste.bind(this));
|
|
36
|
-
this.delete.addEventListener('tap', this.onTapDelete.bind(this));
|
|
37
|
-
this.renderRoot
|
|
38
|
-
.querySelector('#font-increase')
|
|
39
|
-
.addEventListener('tap', this.onTapFontIncrease.bind(this));
|
|
40
|
-
this.renderRoot
|
|
41
|
-
.querySelector('#font-decrease')
|
|
42
|
-
.addEventListener('tap', this.onTapFontDecrease.bind(this));
|
|
43
|
-
this.renderRoot.querySelector('#group').addEventListener('tap', this.onTapGroup.bind(this));
|
|
44
|
-
this.renderRoot.querySelector('#ungroup').addEventListener('tap', this.onTapUngroup.bind(this));
|
|
45
|
-
this.renderRoot
|
|
46
|
-
.querySelector('#toggle-property')
|
|
47
|
-
.addEventListener('tap', this.onTapToggle.bind(this));
|
|
48
|
-
this.renderRoot.querySelector('#fit-scene').addEventListener('tap', this.onTapFitScene.bind(this));
|
|
49
|
-
this.renderRoot.querySelector('#preview').addEventListener('tap', this.onTapPreview.bind(this));
|
|
81
|
+
// 모든 버튼은 템플릿 @click 디렉티브로 바인딩 — 조건부 렌더링 시에도 정상 작동
|
|
50
82
|
}
|
|
51
83
|
updated(changes) {
|
|
52
84
|
changes.has('scene') && this.onSceneChanged(this.scene, changes.get('scene'));
|
|
@@ -59,128 +91,123 @@ export class EditToolbar extends LitElement {
|
|
|
59
91
|
|
|
60
92
|
${this.hasEmptySlot() ? html `` : html `<span class="vline"></span>`}
|
|
61
93
|
|
|
62
|
-
<span button id="undo" title="undo (${this.getShortcutString('cmd', 'z')})"> </span>
|
|
63
|
-
<span button id="redo" title="redo (${this.getShortcutString('cmd', 'shift', 'z')})"> </span>
|
|
94
|
+
<span button id="undo" title="undo (${this.getShortcutString('cmd', 'z')})" @click=${this.onTapUndo}> </span>
|
|
95
|
+
<span button id="redo" title="redo (${this.getShortcutString('cmd', 'shift', 'z')})" @click=${this.onTapRedo}> </span>
|
|
64
96
|
|
|
65
97
|
<span class="vline"></span>
|
|
66
98
|
|
|
67
|
-
<span button id="
|
|
68
|
-
<span button id="copy" title="copy (${this.getShortcutString('cmd', '
|
|
69
|
-
<span button id="paste" title="paste (${this.getShortcutString('cmd', 'v')})"> </span>
|
|
70
|
-
<span
|
|
71
|
-
button
|
|
72
|
-
id="delete"
|
|
73
|
-
title="delete (${this.getShortcutString('backspace')}, ${this.getShortcutString('delete')})"
|
|
74
|
-
>
|
|
75
|
-
</span>
|
|
99
|
+
<span button id="style-copy" title="style copy (${this.getShortcutString('cmd', '1')})" @click=${this.onStartStylePasteMode}> </span>
|
|
100
|
+
<span button id="databind-copy" title="databind copy (${this.getShortcutString('cmd', '2')})" @click=${this.onStartDatabindPasteMode}> </span>
|
|
76
101
|
|
|
77
102
|
<span class="vline"></span>
|
|
78
103
|
|
|
79
|
-
|
|
80
|
-
<span button id="
|
|
104
|
+
<span button id="cut" title="cut (${this.getShortcutString('cmd', 'x')})" @click=${this.onTapCut}> </span>
|
|
105
|
+
<span button id="copy" title="copy (${this.getShortcutString('cmd', 'c')})" @click=${this.onTapCopy}> </span>
|
|
106
|
+
<span button id="paste" title="paste (${this.getShortcutString('cmd', 'v')})" @click=${this.onTapPaste}> </span>
|
|
107
|
+
<span button id="delete"
|
|
108
|
+
title="delete (${this.getShortcutString('backspace')}, ${this.getShortcutString('delete')})"
|
|
109
|
+
@click=${this.onTapDelete}> </span>
|
|
110
|
+
|
|
81
111
|
<span class="vline"></span>
|
|
82
|
-
-->
|
|
83
112
|
|
|
84
|
-
<span
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
</span>
|
|
91
|
-
<span
|
|
92
|
-
button
|
|
93
|
-
data-align="center"
|
|
94
|
-
id="align-center"
|
|
95
|
-
title="align center (${this.getShortcutString('alt', 'shift', 'c')})"
|
|
96
|
-
>
|
|
97
|
-
</span>
|
|
98
|
-
<span
|
|
99
|
-
button
|
|
100
|
-
data-align="right"
|
|
101
|
-
id="align-right"
|
|
102
|
-
title="align right (${this.getShortcutString('alt', 'shift', 'r')})"
|
|
103
|
-
>
|
|
104
|
-
</span>
|
|
113
|
+
<span button data-align="left" id="align-left"
|
|
114
|
+
title="align left (${this.getShortcutString('alt', 'shift', 'l')})" @click=${this.onTapAlign}> </span>
|
|
115
|
+
<span button data-align="center" id="align-center"
|
|
116
|
+
title="align center (${this.getShortcutString('alt', 'shift', 'c')})" @click=${this.onTapAlign}> </span>
|
|
117
|
+
<span button data-align="right" id="align-right"
|
|
118
|
+
title="align right (${this.getShortcutString('alt', 'shift', 'r')})" @click=${this.onTapAlign}> </span>
|
|
105
119
|
|
|
106
|
-
<span button data-align="top" id="align-top"
|
|
107
|
-
|
|
108
|
-
<span
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
title="align middle (${this.getShortcutString('alt', 'shift', 'm')})"
|
|
113
|
-
>
|
|
114
|
-
</span>
|
|
115
|
-
<span
|
|
116
|
-
button
|
|
117
|
-
data-align="bottom"
|
|
118
|
-
id="align-bottom"
|
|
119
|
-
title="align bottom (${this.getShortcutString('alt', 'shift', 'b')})"
|
|
120
|
-
>
|
|
121
|
-
</span>
|
|
120
|
+
<span button data-align="top" id="align-top"
|
|
121
|
+
title="align top (${this.getShortcutString('alt', 'shift', 't')})" @click=${this.onTapAlign}> </span>
|
|
122
|
+
<span button data-align="middle" id="align-middle"
|
|
123
|
+
title="align middle (${this.getShortcutString('alt', 'shift', 'm')})" @click=${this.onTapAlign}> </span>
|
|
124
|
+
<span button data-align="bottom" id="align-bottom"
|
|
125
|
+
title="align bottom (${this.getShortcutString('alt', 'shift', 'b')})" @click=${this.onTapAlign}> </span>
|
|
122
126
|
|
|
123
|
-
<span
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
title="distribute horizontally (${this.getShortcutString('alt', 'shift', 'h')})"
|
|
128
|
-
>
|
|
129
|
-
</span>
|
|
127
|
+
<span button data-distribute="HORIZONTAL" id="distribute-horizontal"
|
|
128
|
+
title="distribute horizontally (${this.getShortcutString('alt', 'shift', 'h')})" @click=${this.onTapDistribute}> </span>
|
|
129
|
+
<span button data-distribute="VERTICAL" id="distribute-vertical"
|
|
130
|
+
title="distribute vertically (${this.getShortcutString('alt', 'shift', 'v')})" @click=${this.onTapDistribute}> </span>
|
|
130
131
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
id="distribute-vertical"
|
|
135
|
-
title="distribute vertically (${this.getShortcutString('alt', 'shift', 'v')})"
|
|
136
|
-
>
|
|
137
|
-
</span>
|
|
132
|
+
${this._dimension === '3d'
|
|
133
|
+
? html `
|
|
134
|
+
<span class="vline"></span>
|
|
138
135
|
|
|
139
|
-
|
|
136
|
+
<span button data-align="z-front" id="align-z-front" title="align Z front" @click=${this.onTapAlign}> </span>
|
|
137
|
+
<span button data-align="z-middle" id="align-z-middle" title="align Z middle" @click=${this.onTapAlign}> </span>
|
|
138
|
+
<span button data-align="z-back" id="align-z-back" title="align Z back" @click=${this.onTapAlign}> </span>
|
|
139
|
+
<span button data-distribute="Z" id="distribute-z" title="distribute Z" @click=${this.onTapDistribute}> </span>
|
|
140
|
+
`
|
|
141
|
+
: this._dimension === '2d'
|
|
142
|
+
? html `
|
|
143
|
+
<span class="vline"></span>
|
|
140
144
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
</span>
|
|
152
|
-
<span button id="backward" data-zorder="backward" title="send backward (${this.getShortcutString('cmd', 'b')})">
|
|
153
|
-
</span>
|
|
145
|
+
<span button id="front" data-zorder="front"
|
|
146
|
+
title="bring to front (${this.getShortcutString('cmd', 'shift', 'f')})" @click=${this.onTapZorder}> </span>
|
|
147
|
+
<span button id="back" data-zorder="back"
|
|
148
|
+
title="send to back (${this.getShortcutString('cmd', 'shift', 'b')})" @click=${this.onTapZorder}> </span>
|
|
149
|
+
<span button id="forward" data-zorder="forward"
|
|
150
|
+
title="bring forward (${this.getShortcutString('cmd', 'f')})" @click=${this.onTapZorder}> </span>
|
|
151
|
+
<span button id="backward" data-zorder="backward"
|
|
152
|
+
title="send backward (${this.getShortcutString('cmd', 'b')})" @click=${this.onTapZorder}> </span>
|
|
153
|
+
`
|
|
154
|
+
: ''}
|
|
154
155
|
|
|
155
|
-
|
|
156
|
+
${this._dimension === '2d' ? html `
|
|
157
|
+
<span class="vline"></span>
|
|
158
|
+
|
|
159
|
+
<span button id="group" title="group (${this.getShortcutString('cmd', 'g')})" @click=${this.onTapGroup}> </span>
|
|
160
|
+
<span button id="ungroup" title="ungroup (${this.getShortcutString('cmd', 'shift', 'g')})" @click=${this.onTapUngroup}> </span>
|
|
161
|
+
` : this._dimension === '3d' ? html `
|
|
162
|
+
<span class="vline"></span>
|
|
156
163
|
|
|
157
|
-
|
|
158
|
-
|
|
164
|
+
<span button class="gizmo-btn" data-gizmo="translate" title="Move (W)"
|
|
165
|
+
@click=${() => this._setGizmoMode('translate')}>
|
|
166
|
+
<svg viewBox="0 0 20 20" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8">
|
|
167
|
+
<line x1="10" y1="2" x2="10" y2="18"/><line x1="2" y1="10" x2="18" y2="10"/>
|
|
168
|
+
<polyline points="10,2 7.5,5"/><polyline points="10,2 12.5,5"/>
|
|
169
|
+
<polyline points="18,10 15,7.5"/><polyline points="18,10 15,12.5"/>
|
|
170
|
+
<polyline points="10,18 7.5,15"/><polyline points="10,18 12.5,15"/>
|
|
171
|
+
<polyline points="2,10 5,7.5"/><polyline points="2,10 5,12.5"/>
|
|
172
|
+
</svg>
|
|
173
|
+
</span>
|
|
174
|
+
<span button class="gizmo-btn" data-gizmo="rotate" title="Rotate (E)"
|
|
175
|
+
@click=${() => this._setGizmoMode('rotate')}>
|
|
176
|
+
<svg viewBox="0 0 20 20" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8">
|
|
177
|
+
<path d="M14.5 3.5A7 7 0 1 0 17 10"/>
|
|
178
|
+
<polyline points="14,1 15,3.5 12.5,4.5"/>
|
|
179
|
+
</svg>
|
|
180
|
+
</span>
|
|
181
|
+
<span button class="gizmo-btn" data-gizmo="scale" title="Scale (R)"
|
|
182
|
+
@click=${() => this._setGizmoMode('scale')}>
|
|
183
|
+
<svg viewBox="0 0 20 20" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.8">
|
|
184
|
+
<line x1="4" y1="16" x2="16" y2="4"/>
|
|
185
|
+
<rect x="2" y="13" width="4" height="4" rx="0.5" fill="currentColor"/>
|
|
186
|
+
<rect x="14" y="2" width="4" height="4" rx="0.5" fill="currentColor"/>
|
|
187
|
+
</svg>
|
|
188
|
+
</span>
|
|
189
|
+
` : ''}
|
|
159
190
|
|
|
160
191
|
<span class="vline"></span>
|
|
161
192
|
|
|
162
|
-
<span button id="font-increase" title="increase font size"></span>
|
|
163
|
-
<span button id="font-decrease" title="decrease font size"></span>
|
|
193
|
+
<span button id="font-increase" title="increase font size" @click=${this.onTapFontIncrease}></span>
|
|
194
|
+
<span button id="font-decrease" title="decrease font size" style="scale: 0.7;" @click=${this.onTapFontDecrease}></span>
|
|
164
195
|
|
|
165
196
|
<span class="vline"></span>
|
|
166
197
|
<span>(v${process.env['APP-VERSION']})</span>
|
|
167
198
|
<span padding></span>
|
|
168
199
|
|
|
169
|
-
<span button id="fit-scene" title="fit scene (${this.getShortcutString('cmd', 'd')})"> </span>
|
|
200
|
+
<span button id="fit-scene" title="fit scene (${this.getShortcutString('cmd', 'd')})" @click=${this.onTapFitScene}> </span>
|
|
170
201
|
|
|
171
202
|
<span class="vline"></span>
|
|
172
203
|
|
|
173
|
-
<span button id="preview" title="preview (${this.getShortcutString('ctrl', 'p')})"> </span>
|
|
204
|
+
<span button id="preview" title="preview (${this.getShortcutString('ctrl', 'p')})" @click=${this.onTapPreview}> </span>
|
|
174
205
|
|
|
175
|
-
<span button id="fullscreen" title="fullscreen (${this.getShortcutString('f11')})"> </span>
|
|
206
|
+
<span button id="fullscreen" title="fullscreen (${this.getShortcutString('f11')})" @click=${this.onTapFullscreen}> </span>
|
|
176
207
|
|
|
177
|
-
<span
|
|
178
|
-
button
|
|
179
|
-
id="toggle-property"
|
|
208
|
+
<span button id="toggle-property"
|
|
180
209
|
title="toggle property panel (${this.getShortcutString('cmd', 'h')})"
|
|
181
|
-
toggles="true"
|
|
182
|
-
>
|
|
183
|
-
</span>
|
|
210
|
+
toggles="true" @click=${this.onTapToggle}> </span>
|
|
184
211
|
</div>
|
|
185
212
|
`;
|
|
186
213
|
}
|
|
@@ -227,7 +254,7 @@ export class EditToolbar extends LitElement {
|
|
|
227
254
|
return symbols.join(MACOS ? '' : '+');
|
|
228
255
|
}
|
|
229
256
|
onShortcut(e) {
|
|
230
|
-
var _a, _b, _c, _d;
|
|
257
|
+
var _a, _b, _c, _d, _e, _f;
|
|
231
258
|
if (MACOS)
|
|
232
259
|
var ctrlKey = e.metaKey;
|
|
233
260
|
else
|
|
@@ -246,6 +273,14 @@ export class EditToolbar extends LitElement {
|
|
|
246
273
|
if (ctrlKey && !shiftKey)
|
|
247
274
|
this.onTapRedo();
|
|
248
275
|
break;
|
|
276
|
+
case 'Digit1':
|
|
277
|
+
if (ctrlKey)
|
|
278
|
+
this.onStartStylePasteMode();
|
|
279
|
+
break;
|
|
280
|
+
case 'Digit2':
|
|
281
|
+
if (ctrlKey)
|
|
282
|
+
this.onStartDatabindPasteMode();
|
|
283
|
+
break;
|
|
249
284
|
case 'KeyC':
|
|
250
285
|
if (ctrlKey && !shiftKey)
|
|
251
286
|
this.onTapCopy();
|
|
@@ -257,7 +292,13 @@ export class EditToolbar extends LitElement {
|
|
|
257
292
|
this.onTapCut();
|
|
258
293
|
break;
|
|
259
294
|
case 'KeyV':
|
|
260
|
-
if (ctrlKey && !
|
|
295
|
+
if (ctrlKey && shiftKey && !altKey) {
|
|
296
|
+
// Ctrl+Shift+V = Bulk Paste (Paste Special 컨벤션) — 클립보드의
|
|
297
|
+
// 단일 컴포넌트를 N개로 일괄 붙여넣기.
|
|
298
|
+
this.onBulkPaste();
|
|
299
|
+
defaultPrevent = true;
|
|
300
|
+
}
|
|
301
|
+
else if (ctrlKey && !shiftKey) {
|
|
261
302
|
this.onTapPaste();
|
|
262
303
|
defaultPrevent = false;
|
|
263
304
|
}
|
|
@@ -270,31 +311,45 @@ export class EditToolbar extends LitElement {
|
|
|
270
311
|
defaultPrevent = true;
|
|
271
312
|
break;
|
|
272
313
|
case 'KeyG':
|
|
273
|
-
if (
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
314
|
+
if (this._dimension === '2d') {
|
|
315
|
+
if (ctrlKey && !shiftKey)
|
|
316
|
+
this.onTapGroup();
|
|
317
|
+
else if (ctrlKey && shiftKey)
|
|
318
|
+
this.onTapUngroup();
|
|
319
|
+
}
|
|
277
320
|
break;
|
|
278
|
-
case '
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
(
|
|
321
|
+
case 'BracketRight':
|
|
322
|
+
// Ctrl+] = Bring Forward, Ctrl+Shift+] = Bring to Front
|
|
323
|
+
// (Photoshop / Illustrator 표준 컨벤션)
|
|
324
|
+
if (this._dimension === '2d') {
|
|
325
|
+
if (ctrlKey && !shiftKey) {
|
|
326
|
+
(_a = this.scene) === null || _a === void 0 ? void 0 : _a.zorder('forward');
|
|
327
|
+
defaultPrevent = true;
|
|
328
|
+
}
|
|
329
|
+
else if (ctrlKey && shiftKey) {
|
|
330
|
+
(_b = this.scene) === null || _b === void 0 ? void 0 : _b.zorder('front');
|
|
331
|
+
defaultPrevent = true;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
break;
|
|
335
|
+
case 'BracketLeft':
|
|
336
|
+
// Ctrl+[ = Send Backward, Ctrl+Shift+[ = Send to Back
|
|
337
|
+
if (this._dimension === '2d') {
|
|
338
|
+
if (ctrlKey && !shiftKey) {
|
|
339
|
+
(_c = this.scene) === null || _c === void 0 ? void 0 : _c.zorder('backward');
|
|
340
|
+
defaultPrevent = true;
|
|
341
|
+
}
|
|
342
|
+
else if (ctrlKey && shiftKey) {
|
|
343
|
+
(_d = this.scene) === null || _d === void 0 ? void 0 : _d.zorder('back');
|
|
344
|
+
defaultPrevent = true;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
283
347
|
break;
|
|
284
348
|
case 'KeyB':
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
else if (ctrlKey && shiftKey)
|
|
288
|
-
(_d = this.scene) === null || _d === void 0 ? void 0 : _d.zorder('back');
|
|
289
|
-
else if (altKey && shiftKey)
|
|
349
|
+
// zorder 는 BracketLeft 로 이동. KeyB 의 Alt+Shift+B = align bottom 만 유지.
|
|
350
|
+
if (altKey && shiftKey)
|
|
290
351
|
this.onTapAlign('bottom');
|
|
291
352
|
break;
|
|
292
|
-
// case 'Equal':
|
|
293
|
-
// if (ctrlKey) this.onTapZoom(zoomin)
|
|
294
|
-
// break
|
|
295
|
-
// case 'Minus':
|
|
296
|
-
// if (ctrlKey) this.onTapZoom(zoomout)
|
|
297
|
-
// break
|
|
298
353
|
case 'KeyH':
|
|
299
354
|
if (ctrlKey && !shiftKey)
|
|
300
355
|
this.onTapToggle();
|
|
@@ -341,17 +396,10 @@ export class EditToolbar extends LitElement {
|
|
|
341
396
|
if (ctrlKey && shiftKey)
|
|
342
397
|
this.onTapDownloadModel();
|
|
343
398
|
break;
|
|
344
|
-
case '
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
}
|
|
349
|
-
break;
|
|
350
|
-
case 'Digit2':
|
|
351
|
-
if (ctrlKey) {
|
|
352
|
-
console.log('SELECTED', this.scene && this.scene.selected);
|
|
353
|
-
defaultPrevent = true;
|
|
354
|
-
}
|
|
399
|
+
case 'Escape':
|
|
400
|
+
(_e = this.scene) === null || _e === void 0 ? void 0 : _e.stopStylePasteMode();
|
|
401
|
+
(_f = this.scene) === null || _f === void 0 ? void 0 : _f.stopDatabindPasteMode();
|
|
402
|
+
defaultPrevent = true;
|
|
355
403
|
break;
|
|
356
404
|
default:
|
|
357
405
|
return false;
|
|
@@ -360,46 +408,75 @@ export class EditToolbar extends LitElement {
|
|
|
360
408
|
e.preventDefault();
|
|
361
409
|
return true;
|
|
362
410
|
}
|
|
411
|
+
_setDisabled(id, disabled) {
|
|
412
|
+
const el = this.renderRoot.querySelector(`#${id}`);
|
|
413
|
+
disabled ? el === null || el === void 0 ? void 0 : el.setAttribute('disabled', '') : el === null || el === void 0 ? void 0 : el.removeAttribute('disabled');
|
|
414
|
+
}
|
|
363
415
|
onExecute(command, undoable, redoable) {
|
|
364
|
-
|
|
365
|
-
|
|
416
|
+
this._setDisabled('undo', !undoable);
|
|
417
|
+
this._setDisabled('redo', !redoable);
|
|
366
418
|
}
|
|
367
419
|
onUndo(undoable, redoable) {
|
|
368
|
-
|
|
369
|
-
|
|
420
|
+
this._setDisabled('undo', !undoable);
|
|
421
|
+
this._setDisabled('redo', !redoable);
|
|
370
422
|
}
|
|
371
423
|
onRedo(undoable, redoable) {
|
|
372
|
-
|
|
373
|
-
|
|
424
|
+
this._setDisabled('undo', !undoable);
|
|
425
|
+
this._setDisabled('redo', !redoable);
|
|
374
426
|
}
|
|
375
427
|
onSceneChanged(after, before) {
|
|
428
|
+
var _a, _b;
|
|
376
429
|
if (before) {
|
|
377
430
|
before.off('execute', this.onExecute, this);
|
|
378
431
|
before.off('undo', this.onUndo, this);
|
|
379
432
|
before.off('redo', this.onRedo, this);
|
|
433
|
+
before.off('dimension', this._onDimensionChanged, this);
|
|
434
|
+
before.off('gizmoattach', this._onGizmoAttachChanged, this);
|
|
380
435
|
}
|
|
381
436
|
if (after) {
|
|
382
437
|
after.on('execute', this.onExecute, this);
|
|
383
438
|
after.on('undo', this.onUndo, this);
|
|
384
439
|
after.on('redo', this.onRedo, this);
|
|
440
|
+
after.on('dimension', this._onDimensionChanged, this);
|
|
441
|
+
after.on('gizmoattach', this._onGizmoAttachChanged, this);
|
|
442
|
+
// scene 설정 시 현재 dimension을 즉시 반영 (초기 이벤트를 놓친 경우 대비)
|
|
443
|
+
const threed = (_b = (_a = after.model_layer) === null || _a === void 0 ? void 0 : _a.model) === null || _b === void 0 ? void 0 : _b.threed;
|
|
444
|
+
this._dimension = threed ? '3d' : '2d';
|
|
385
445
|
}
|
|
386
446
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
447
|
+
_onDimensionChanged(dimension) {
|
|
448
|
+
this._dimension = dimension;
|
|
449
|
+
}
|
|
450
|
+
_onGizmoAttachChanged(isAttached) {
|
|
451
|
+
this._gizmoAttached = isAttached;
|
|
452
|
+
}
|
|
453
|
+
_setGizmoMode(mode) {
|
|
454
|
+
var _a, _b;
|
|
455
|
+
;
|
|
456
|
+
(_b = (_a = this.scene) === null || _a === void 0 ? void 0 : _a.root) === null || _b === void 0 ? void 0 : _b.setGizmoMode(mode);
|
|
457
|
+
}
|
|
393
458
|
onSelectedChanged(after, before) {
|
|
459
|
+
var hasSelection = after.length > 0;
|
|
394
460
|
var alignable = after.length > 1;
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
461
|
+
['style-copy', 'databind-copy', 'cut', 'copy', 'delete'].forEach(id => this._setDisabled(id, !hasSelection));
|
|
462
|
+
// 정렬 버튼
|
|
463
|
+
this.renderRoot.querySelectorAll('[data-align]').forEach(el => alignable ? el.removeAttribute('disabled') : el.setAttribute('disabled', ''));
|
|
464
|
+
if (this._dimension === '2d') {
|
|
465
|
+
var movable = after.length === 1;
|
|
466
|
+
/* forward, backward 이동은 한 컴포넌트만 가능하다. */
|
|
467
|
+
this._setDisabled('forward', !movable);
|
|
468
|
+
this._setDisabled('backward', !movable);
|
|
469
|
+
/* 여러 컴포넌트는 front, back 이동이 가능하다. */
|
|
470
|
+
this._setDisabled('front', !(alignable || movable));
|
|
471
|
+
this._setDisabled('back', !(alignable || movable));
|
|
472
|
+
}
|
|
473
|
+
// 분배 버튼
|
|
474
|
+
this.renderRoot.querySelectorAll('[data-distribute]').forEach(el => alignable ? el.removeAttribute('disabled') : el.setAttribute('disabled', ''));
|
|
475
|
+
if (this._dimension === '3d') {
|
|
476
|
+
this.renderRoot.querySelectorAll('.gizmo-btn').forEach(btn => {
|
|
477
|
+
hasSelection ? btn.removeAttribute('disabled') : btn.setAttribute('disabled', '');
|
|
478
|
+
});
|
|
479
|
+
}
|
|
403
480
|
}
|
|
404
481
|
onTapUndo() {
|
|
405
482
|
var _a;
|
|
@@ -409,6 +486,22 @@ export class EditToolbar extends LitElement {
|
|
|
409
486
|
var _a;
|
|
410
487
|
(_a = this.scene) === null || _a === void 0 ? void 0 : _a.redo();
|
|
411
488
|
}
|
|
489
|
+
onStartStylePasteMode() {
|
|
490
|
+
var _a, _b, _c;
|
|
491
|
+
if (((_a = this.selected) === null || _a === void 0 ? void 0 : _a.length) !== 1)
|
|
492
|
+
return;
|
|
493
|
+
if (this.selected[0] === ((_b = this.scene) === null || _b === void 0 ? void 0 : _b.root))
|
|
494
|
+
return;
|
|
495
|
+
(_c = this.scene) === null || _c === void 0 ? void 0 : _c.startStylePasteMode();
|
|
496
|
+
}
|
|
497
|
+
onStartDatabindPasteMode() {
|
|
498
|
+
var _a, _b, _c;
|
|
499
|
+
if (((_a = this.selected) === null || _a === void 0 ? void 0 : _a.length) !== 1)
|
|
500
|
+
return;
|
|
501
|
+
if (this.selected[0] === ((_b = this.scene) === null || _b === void 0 ? void 0 : _b.root))
|
|
502
|
+
return;
|
|
503
|
+
(_c = this.scene) === null || _c === void 0 ? void 0 : _c.startDatabindPasteMode();
|
|
504
|
+
}
|
|
412
505
|
onTapCut() {
|
|
413
506
|
var _a;
|
|
414
507
|
(_a = this.scene) === null || _a === void 0 ? void 0 : _a.cut();
|
|
@@ -431,6 +524,101 @@ export class EditToolbar extends LitElement {
|
|
|
431
524
|
var _a;
|
|
432
525
|
(_a = this.scene) === null || _a === void 0 ? void 0 : _a.remove();
|
|
433
526
|
}
|
|
527
|
+
/**
|
|
528
|
+
* 멀티 컴포넌트 일괄 붙여넣기 — Ctrl+Shift+V 진입점.
|
|
529
|
+
*
|
|
530
|
+
* 흐름:
|
|
531
|
+
* 1. 클립보드 (this.cliped) 검증 — *단일* 컴포넌트만 허용
|
|
532
|
+
* 2. scene.startBulkCreateMode → AddLayer 가 캔버스 위에 드래그 박스 그림
|
|
533
|
+
* 3. 사용자가 영역 드래그 → Promise resolve({area, template})
|
|
534
|
+
* ESC/취소 → Promise resolve(null)
|
|
535
|
+
* 4. 영역이 결정되면 dialog 오픈
|
|
536
|
+
*/
|
|
537
|
+
async onBulkPaste() {
|
|
538
|
+
var _a;
|
|
539
|
+
if (!this.cliped) {
|
|
540
|
+
console.warn('bulk-paste: 먼저 Ctrl+C 로 컴포넌트를 복사하세요.');
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
let parsed;
|
|
544
|
+
try {
|
|
545
|
+
parsed = JSON.parse(this.cliped);
|
|
546
|
+
}
|
|
547
|
+
catch (e) {
|
|
548
|
+
console.warn('bulk-paste: 클립보드 파싱 실패', e);
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
552
|
+
console.warn('bulk-paste: 클립보드 비어있음');
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
if (parsed.length > 1) {
|
|
556
|
+
console.warn('bulk-paste: 단일 컴포넌트만 일괄 붙여넣기 가능. 다중은 일반 paste 사용.');
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
const template = parsed[0];
|
|
560
|
+
// bulk 모드 임을 시각 구분하기 위해 파란 점선 (일반 add 의 검정과 색만 차별).
|
|
561
|
+
const result = await ((_a = this.scene) === null || _a === void 0 ? void 0 : _a.startBulkCreateMode(template, { boxStrokeStyle: '#2964c2' }));
|
|
562
|
+
if (result) {
|
|
563
|
+
this._openBulkCreateDialog(template, result.area);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
_openBulkCreateDialog(template, initialArea) {
|
|
567
|
+
var _a;
|
|
568
|
+
const dialogEl = document.createElement('bulk-create-dialog');
|
|
569
|
+
dialogEl.template = template;
|
|
570
|
+
dialogEl.initialArea = initialArea;
|
|
571
|
+
// 충돌 검사용 — scene 의 모든 컴포넌트 id 수집.
|
|
572
|
+
// (scene.ids 는 indexMap 기반인데 fmsim 의 일부 컴포넌트는 indexMap 미등록
|
|
573
|
+
// 되는 케이스가 있어 직접 컴포넌트 트리 walk.)
|
|
574
|
+
const existingIds = new Set();
|
|
575
|
+
const collectIds = (comp) => {
|
|
576
|
+
var _a, _b, _c;
|
|
577
|
+
if (!comp)
|
|
578
|
+
return;
|
|
579
|
+
const id = (_b = (_a = comp === null || comp === void 0 ? void 0 : comp.state) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : (_c = comp === null || comp === void 0 ? void 0 : comp.model) === null || _c === void 0 ? void 0 : _c.id;
|
|
580
|
+
if (typeof id === 'string' && id)
|
|
581
|
+
existingIds.add(id);
|
|
582
|
+
const children = comp.components || [];
|
|
583
|
+
for (const c of children)
|
|
584
|
+
collectIds(c);
|
|
585
|
+
};
|
|
586
|
+
const root = (_a = this.scene) === null || _a === void 0 ? void 0 : _a.root;
|
|
587
|
+
if (root)
|
|
588
|
+
collectIds(root);
|
|
589
|
+
dialogEl.existingIds = existingIds;
|
|
590
|
+
dialogEl.onConfirm = (models) => {
|
|
591
|
+
const scene = this.scene;
|
|
592
|
+
if (!scene || !models.length) {
|
|
593
|
+
popup === null || popup === void 0 ? void 0 : popup.close();
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
// cliped 의 template model 자체에서 type-aware bounds 추출. things-scene 의
|
|
597
|
+
// component.bounds (= path bounding box) 와 동일 결과를 model JSON 의
|
|
598
|
+
// type-specific 필드 (width/height, rx/ry, points) 만으로 계산.
|
|
599
|
+
const bounds = deriveBoundsFromModel(template);
|
|
600
|
+
scene.undoableChange(() => {
|
|
601
|
+
for (const m of models) {
|
|
602
|
+
const cx = m.left + m.width / 2;
|
|
603
|
+
const cy = m.top + m.height / 2;
|
|
604
|
+
scene.add(m, {
|
|
605
|
+
left: cx - bounds.width / 2,
|
|
606
|
+
top: cy - bounds.height / 2,
|
|
607
|
+
width: bounds.width,
|
|
608
|
+
height: bounds.height
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
popup === null || popup === void 0 ? void 0 : popup.close();
|
|
613
|
+
};
|
|
614
|
+
dialogEl.onCancel = () => {
|
|
615
|
+
popup === null || popup === void 0 ? void 0 : popup.close();
|
|
616
|
+
};
|
|
617
|
+
const popup = OxPopup.open({
|
|
618
|
+
template: dialogEl,
|
|
619
|
+
backdrop: true
|
|
620
|
+
});
|
|
621
|
+
}
|
|
434
622
|
onTapSelectAll() {
|
|
435
623
|
var _a;
|
|
436
624
|
(_a = this.scene) === null || _a === void 0 ? void 0 : _a.select('(child)');
|
|
@@ -476,10 +664,16 @@ export class EditToolbar extends LitElement {
|
|
|
476
664
|
if (!this.scene)
|
|
477
665
|
return;
|
|
478
666
|
var selected = this.scene.selected;
|
|
479
|
-
if (selected.length <= 1)
|
|
480
|
-
return;
|
|
481
667
|
var align = typeof e === 'string' ? e : e.target.getAttribute('data-align');
|
|
482
|
-
|
|
668
|
+
if (!align) {
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
if (selected.length <= 1) {
|
|
672
|
+
this.scene.place(align);
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
this.scene.align(align);
|
|
676
|
+
}
|
|
483
677
|
}
|
|
484
678
|
onTapZorder(e) {
|
|
485
679
|
if (!this.scene)
|
|
@@ -541,45 +735,9 @@ __decorate([
|
|
|
541
735
|
property({ type: Boolean })
|
|
542
736
|
], EditToolbar.prototype, "hideProperty", void 0);
|
|
543
737
|
__decorate([
|
|
544
|
-
|
|
545
|
-
], EditToolbar.prototype, "
|
|
546
|
-
__decorate([
|
|
547
|
-
query('#undo')
|
|
548
|
-
], EditToolbar.prototype, "undo", void 0);
|
|
549
|
-
__decorate([
|
|
550
|
-
query('#fullscreen')
|
|
551
|
-
], EditToolbar.prototype, "fullscreen", void 0);
|
|
552
|
-
__decorate([
|
|
553
|
-
query('#cut')
|
|
554
|
-
], EditToolbar.prototype, "cut", void 0);
|
|
555
|
-
__decorate([
|
|
556
|
-
query('#copy')
|
|
557
|
-
], EditToolbar.prototype, "copy", void 0);
|
|
558
|
-
__decorate([
|
|
559
|
-
query('#paste')
|
|
560
|
-
], EditToolbar.prototype, "paste", void 0);
|
|
561
|
-
__decorate([
|
|
562
|
-
query('#delete')
|
|
563
|
-
], EditToolbar.prototype, "delete", void 0);
|
|
564
|
-
__decorate([
|
|
565
|
-
query('#forward')
|
|
566
|
-
], EditToolbar.prototype, "forward", void 0);
|
|
567
|
-
__decorate([
|
|
568
|
-
query('#backward')
|
|
569
|
-
], EditToolbar.prototype, "backward", void 0);
|
|
570
|
-
__decorate([
|
|
571
|
-
query('#front')
|
|
572
|
-
], EditToolbar.prototype, "front", void 0);
|
|
573
|
-
__decorate([
|
|
574
|
-
query('#back')
|
|
575
|
-
], EditToolbar.prototype, "back", void 0);
|
|
576
|
-
__decorate([
|
|
577
|
-
queryAll('[data-align]')
|
|
578
|
-
], EditToolbar.prototype, "aligners", void 0);
|
|
579
|
-
__decorate([
|
|
580
|
-
queryAll('[data-zorder]')
|
|
581
|
-
], EditToolbar.prototype, "zorders", void 0);
|
|
738
|
+
state()
|
|
739
|
+
], EditToolbar.prototype, "_dimension", void 0);
|
|
582
740
|
__decorate([
|
|
583
|
-
|
|
584
|
-
], EditToolbar.prototype, "
|
|
741
|
+
state()
|
|
742
|
+
], EditToolbar.prototype, "_gizmoAttached", void 0);
|
|
585
743
|
//# sourceMappingURL=edit-toolbar.js.map
|