@things-factory/figure-ui 10.1.3 → 10.1.5
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/client/graphql/index.ts +87 -12
- package/client/modeller/figure-ask.ts +14 -4
- package/client/modeller/figure-canvas.ts +53 -0
- package/client/modeller/figure-history-panel.ts +324 -0
- package/client/modeller/figure-inspector.ts +78 -2
- package/client/modeller/figure-side.ts +22 -1
- package/client/modeller/figure-thumbnail.ts +78 -0
- package/client/pages/figure-list-page.ts +391 -195
- package/client/pages/figure-modeller-page.ts +114 -19
- package/client/types.ts +17 -0
- package/dist-client/graphql/index.d.ts +24 -4
- package/dist-client/graphql/index.js +70 -9
- package/dist-client/graphql/index.js.map +1 -1
- package/dist-client/modeller/figure-ask.js +14 -4
- package/dist-client/modeller/figure-ask.js.map +1 -1
- package/dist-client/modeller/figure-canvas.d.ts +11 -0
- package/dist-client/modeller/figure-canvas.js +42 -0
- package/dist-client/modeller/figure-canvas.js.map +1 -1
- package/dist-client/modeller/figure-history-panel.d.ts +42 -0
- package/dist-client/modeller/figure-history-panel.js +343 -0
- package/dist-client/modeller/figure-history-panel.js.map +1 -0
- package/dist-client/modeller/figure-inspector.d.ts +17 -0
- package/dist-client/modeller/figure-inspector.js +77 -2
- package/dist-client/modeller/figure-inspector.js.map +1 -1
- package/dist-client/modeller/figure-side.d.ts +7 -0
- package/dist-client/modeller/figure-side.js +43 -0
- package/dist-client/modeller/figure-side.js.map +1 -1
- package/dist-client/modeller/figure-thumbnail.d.ts +3 -0
- package/dist-client/modeller/figure-thumbnail.js +59 -0
- package/dist-client/modeller/figure-thumbnail.js.map +1 -0
- package/dist-client/pages/figure-list-page.d.ts +45 -17
- package/dist-client/pages/figure-list-page.js +374 -209
- package/dist-client/pages/figure-list-page.js.map +1 -1
- package/dist-client/pages/figure-modeller-page.d.ts +27 -0
- package/dist-client/pages/figure-modeller-page.js +109 -19
- package/dist-client/pages/figure-modeller-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -0
- package/dist-client/types.d.ts +19 -0
- package/dist-client/types.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -0
- package/package.json +5 -3
- package/translations/en.json +19 -0
- package/translations/ja.json +21 -2
- package/translations/ko.json +21 -2
- package/translations/ms.json +21 -2
- package/translations/zh.json +21 -2
- package/client/viewparts/figure-card.ts +0 -226
- package/dist-client/viewparts/figure-card.d.ts +0 -24
- package/dist-client/viewparts/figure-card.js +0 -221
- package/dist-client/viewparts/figure-card.js.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import './figure-inspector.js'
|
|
2
2
|
import './figure-report.js'
|
|
3
3
|
import './figure-settings.js'
|
|
4
|
+
import './figure-history-panel.js'
|
|
4
5
|
|
|
5
6
|
import { css, html, LitElement } from 'lit'
|
|
6
7
|
import { customElement, property, state } from 'lit/decorators.js'
|
|
@@ -12,7 +13,7 @@ import type { BoardModel, PartModel } from './figure-source.js'
|
|
|
12
13
|
import { DEFAULT_VIEW } from './figure-view.js'
|
|
13
14
|
import type { ViewSettings } from './figure-view.js'
|
|
14
15
|
|
|
15
|
-
type Tab = 'properties' | 'verdict' | 'view'
|
|
16
|
+
type Tab = 'properties' | 'verdict' | 'view' | 'history'
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* 저작면 오른쪽 칸 — 속성과 판정을 탭으로 겹쳐 둔다.
|
|
@@ -116,6 +117,13 @@ export class FigureSide extends localize(i18next)(LitElement) {
|
|
|
116
117
|
속성은 **수정하는** 곳이라 편집 중인 씬 모델을 받는다. 판정은 **저장될 것을 측정하는**
|
|
117
118
|
곳이라 변환된 FigureSource 를 받는다. 변환은 모델러 페이지가 한 번만 해서 내려보낸다.
|
|
118
119
|
*/
|
|
120
|
+
@property({ type: String }) figureName = ''
|
|
121
|
+
/** 이력 탭이 발행하고 되돌리는 데 필요한 것들. 정본은 저작면이 든다. */
|
|
122
|
+
@property({ type: String }) figureId?: string
|
|
123
|
+
@property({ type: String }) figureState?: 'draft' | 'released'
|
|
124
|
+
@property({ type: Number }) figureVersion = 0
|
|
125
|
+
@property({ type: Boolean }) dirty = false
|
|
126
|
+
|
|
119
127
|
@property({ type: Object }) board?: BoardModel
|
|
120
128
|
@property({ type: Array }) parts: PartModel[] = []
|
|
121
129
|
@property({ type: Object }) source?: FigureSource
|
|
@@ -133,10 +141,12 @@ export class FigureSide extends localize(i18next)(LitElement) {
|
|
|
133
141
|
${this.renderTab('properties', i18next.t('label.properties'))}
|
|
134
142
|
${this.renderTab('verdict', i18next.t('label.maturity'), this.instances)}
|
|
135
143
|
${this.renderTab('view', i18next.t('label.view'))}
|
|
144
|
+
${this.renderTab('history', i18next.t('label.history'))}
|
|
136
145
|
</div>
|
|
137
146
|
|
|
138
147
|
<figure-inspector
|
|
139
148
|
?off=${this.tab !== 'properties'}
|
|
149
|
+
.figureName=${this.figureName}
|
|
140
150
|
.board=${this.board}
|
|
141
151
|
.parts=${this.parts}
|
|
142
152
|
.selected=${this.selected}
|
|
@@ -149,6 +159,17 @@ export class FigureSide extends localize(i18next)(LitElement) {
|
|
|
149
159
|
></figure-report>
|
|
150
160
|
|
|
151
161
|
<figure-settings ?off=${this.tab !== 'view'} .view=${this.view}></figure-settings>
|
|
162
|
+
|
|
163
|
+
<!--
|
|
164
|
+
이력은 감춰도 DOM 에 남긴다 — 다른 탭들과 같은 규칙이다. 떼었다 붙이면 판본을 다시 부른다.
|
|
165
|
+
-->
|
|
166
|
+
<figure-history-panel
|
|
167
|
+
?off=${this.tab !== 'history'}
|
|
168
|
+
.figureId=${this.figureId}
|
|
169
|
+
.figureState=${this.figureState}
|
|
170
|
+
.figureVersion=${this.figureVersion}
|
|
171
|
+
.dirty=${this.dirty}
|
|
172
|
+
></figure-history-panel>
|
|
152
173
|
`
|
|
153
174
|
}
|
|
154
175
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import './figure-canvas.js'
|
|
2
|
+
|
|
3
|
+
import type { BoardModel, PartModel } from './figure-source.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 카드에 쓸 그림을 찍는다 — **숨은 자리에 저작 캔버스를 하나 더 세워서.**
|
|
7
|
+
*
|
|
8
|
+
* ## 왜 보이는 캔버스를 찍지 않나
|
|
9
|
+
*
|
|
10
|
+
* 저작면의 캔버스는 저작자가 돌려 둔 각도와 확대로 서 있고, 칸의 비율도 창 크기와 접힌 패널에 따라
|
|
11
|
+
* 다르다. 그것을 찍으면 카드마다 프레임이 달라지고, 방금 확대해 보던 나사 하나가 그 자산의 얼굴이
|
|
12
|
+
* 된다. 목록은 견주는 자리이므로 그림은 **정해진 크기와 정해진 카메라**로 찍는다.
|
|
13
|
+
*
|
|
14
|
+
* ## 왜 씬을 여기서 세우지 않고 부품을 세우나
|
|
15
|
+
*
|
|
16
|
+
* 씬 값(환경 · 하늘 · 조명 · 픽셀 비율 · 좌표 바탕)은 `figure-canvas` 가 든다. 여기서 다시 적으면
|
|
17
|
+
* 두 벌이 되고, 그러면 **카드에 보이는 그림과 저작면에서 보던 것이 아무 오류 없이 갈린다.** 그래서
|
|
18
|
+
* 같은 부품을 `viewOnly` 로 하나 더 세워 그 부품이 자기 씬을 세우게 하고, 찍은 뒤 버린다.
|
|
19
|
+
*
|
|
20
|
+
* ## 왜 서버가 아니라 브라우저인가
|
|
21
|
+
*
|
|
22
|
+
* 보드는 저장할 때 서버가 찍는데, 백엔드에 GPU 가 없는 배포가 많아 헤드리스로 3D 를 찍는 것이 자주
|
|
23
|
+
* 실패한다. 도형을 그릴 GPU 는 이미 보는 사람 손에 있다.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/** 카드는 4:3 이다. */
|
|
27
|
+
const WIDTH = 480
|
|
28
|
+
const HEIGHT = 360
|
|
29
|
+
|
|
30
|
+
interface Shooter extends HTMLElement {
|
|
31
|
+
board?: BoardModel
|
|
32
|
+
parts?: PartModel[]
|
|
33
|
+
viewOnly?: boolean
|
|
34
|
+
snapshot?: (width?: number, height?: number) => Promise<string | undefined>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** 프레임 두 장 뒤에 한 번 더 쉰다 — 씬이 서고 카메라가 자리를 잡을 틈. 씬에 그 신호가 없다. */
|
|
38
|
+
function settle(): Promise<void> {
|
|
39
|
+
return new Promise(resolve =>
|
|
40
|
+
requestAnimationFrame(() => requestAnimationFrame(() => setTimeout(resolve, 150)))
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function captureThumbnail(
|
|
45
|
+
board: BoardModel | undefined,
|
|
46
|
+
parts: PartModel[]
|
|
47
|
+
): Promise<string | undefined> {
|
|
48
|
+
if (!board || !parts.length) {
|
|
49
|
+
return undefined
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/*
|
|
53
|
+
화면 밖에 둔다. `display: none` 이면 캔버스가 크기를 못 얻어 아무것도 그리지 못한다.
|
|
54
|
+
WebGL context 는 브라우저가 8~16개에서 끊으므로 찍은 뒤 반드시 버린다(아래 finally).
|
|
55
|
+
*/
|
|
56
|
+
const host = document.createElement('div')
|
|
57
|
+
host.setAttribute('figure-thumbnail-stage', '')
|
|
58
|
+
host.style.cssText = `position: fixed; left: -10000px; top: 0; width: ${WIDTH}px; height: ${HEIGHT}px; pointer-events: none;`
|
|
59
|
+
document.body.appendChild(host)
|
|
60
|
+
|
|
61
|
+
const shooter = document.createElement('figure-canvas') as Shooter
|
|
62
|
+
shooter.viewOnly = true
|
|
63
|
+
shooter.board = board
|
|
64
|
+
shooter.parts = parts
|
|
65
|
+
shooter.style.cssText = 'display: block; width: 100%; height: 100%;'
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
host.appendChild(shooter)
|
|
69
|
+
await settle()
|
|
70
|
+
|
|
71
|
+
return shooter.snapshot ? await shooter.snapshot(WIDTH, HEIGHT) : undefined
|
|
72
|
+
} catch (e) {
|
|
73
|
+
console.warn(`[thumbnail] 세우지 못했습니다 — ${(e as Error).message}`)
|
|
74
|
+
return undefined
|
|
75
|
+
} finally {
|
|
76
|
+
host.remove()
|
|
77
|
+
}
|
|
78
|
+
}
|