@fmsim/machine 2.0.0-beta.19 → 2.0.0-beta.20
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/dist/factories/agv-3d.js +0 -113
- package/dist/factories/agv-3d.js.map +1 -1
- package/dist/factories/machine-3d.js +2 -2
- package/dist/factories/machine-3d.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/factories/agv-3d.ts +0 -133
- package/src/factories/machine-3d.ts +3 -4
package/dist/factories/agv-3d.js
CHANGED
|
@@ -23,9 +23,6 @@ export class AGV3D extends RealObjectGroup {
|
|
|
23
23
|
constructor() {
|
|
24
24
|
super(...arguments);
|
|
25
25
|
this._ownMeshes = [];
|
|
26
|
-
this._batteryLen = 0;
|
|
27
|
-
this._batteryY = 0;
|
|
28
|
-
this._batteryZ = 0;
|
|
29
26
|
}
|
|
30
27
|
get effectiveDepth() {
|
|
31
28
|
const { depth } = this.component.state;
|
|
@@ -60,14 +57,6 @@ export class AGV3D extends RealObjectGroup {
|
|
|
60
57
|
}
|
|
61
58
|
build() {
|
|
62
59
|
super.build();
|
|
63
|
-
// data 변경 감지 (배터리 잔량 업데이트)
|
|
64
|
-
if (!this._dataHandler) {
|
|
65
|
-
this._dataHandler = (_after, _before) => {
|
|
66
|
-
if (_after.data !== undefined)
|
|
67
|
-
this.updateBattery();
|
|
68
|
-
};
|
|
69
|
-
this.component.on('change', this._dataHandler);
|
|
70
|
-
}
|
|
71
60
|
const { width = 10, height = 10 } = this.component.state;
|
|
72
61
|
const w = Math.abs(width);
|
|
73
62
|
const h = Math.abs(height);
|
|
@@ -119,107 +108,9 @@ export class AGV3D extends RealObjectGroup {
|
|
|
119
108
|
plat.castShadow = true;
|
|
120
109
|
plat.receiveShadow = true;
|
|
121
110
|
this._ownMeshes = [bumper, body, plat];
|
|
122
|
-
// ── 배터리 실린더 (바디 뒷면, BATTERYRATE 데이터가 있을 때만) ──
|
|
123
|
-
if (this.getBatteryRate() > 0) {
|
|
124
|
-
const batteryMeshes = this.buildBattery(w, h, bumperH, bodyH);
|
|
125
|
-
this._ownMeshes.push(...batteryMeshes);
|
|
126
|
-
}
|
|
127
111
|
for (const m of this._ownMeshes)
|
|
128
112
|
this.object3d.add(m);
|
|
129
113
|
}
|
|
130
|
-
buildBattery(agvW, agvH, bodyBottomY, bodyH) {
|
|
131
|
-
const radius = Math.min(agvW, agvH) * 0.15;
|
|
132
|
-
this._batteryLen = agvW * 0.7;
|
|
133
|
-
this._batteryY = bodyBottomY + bodyH * 0.5;
|
|
134
|
-
this._batteryZ = -agvH / 2 - radius * 1.5;
|
|
135
|
-
const rate = this.getBatteryRate();
|
|
136
|
-
const batteryColor = this.getBatteryColor(rate);
|
|
137
|
-
const innerRadius = radius * 0.85;
|
|
138
|
-
const capWidth = radius * 0.3;
|
|
139
|
-
const meshes = [];
|
|
140
|
-
// 투명 외장 (유리 쉘, 양단 막힘)
|
|
141
|
-
const shellGeo = new THREE.CylinderGeometry(radius, radius, this._batteryLen, 20);
|
|
142
|
-
shellGeo.rotateZ(Math.PI / 2);
|
|
143
|
-
const shellMat = new THREE.MeshStandardMaterial({
|
|
144
|
-
color: 0xffffff,
|
|
145
|
-
transparent: true,
|
|
146
|
-
opacity: 0.25,
|
|
147
|
-
roughness: 0.1,
|
|
148
|
-
metalness: 0.1,
|
|
149
|
-
side: THREE.DoubleSide,
|
|
150
|
-
depthWrite: false,
|
|
151
|
-
});
|
|
152
|
-
const shell = new THREE.Mesh(shellGeo, shellMat);
|
|
153
|
-
shell.position.set(0, this._batteryY, this._batteryZ);
|
|
154
|
-
meshes.push(shell);
|
|
155
|
-
// 좌측 캡 (금속)
|
|
156
|
-
const capGeo = new THREE.CylinderGeometry(radius * 0.6, radius, capWidth, 20);
|
|
157
|
-
capGeo.rotateZ(Math.PI / 2);
|
|
158
|
-
const capMat = new THREE.MeshStandardMaterial({
|
|
159
|
-
color: batteryColor, roughness: 0.3, metalness: 0.7,
|
|
160
|
-
emissive: batteryColor, emissiveIntensity: 0.2,
|
|
161
|
-
});
|
|
162
|
-
const leftCap = new THREE.Mesh(capGeo, capMat);
|
|
163
|
-
leftCap.position.set(-this._batteryLen / 2 - capWidth / 2, this._batteryY, this._batteryZ);
|
|
164
|
-
meshes.push(leftCap);
|
|
165
|
-
// 우측 캡 (금속)
|
|
166
|
-
const rightCapGeo = capGeo.clone();
|
|
167
|
-
const rightCap = new THREE.Mesh(rightCapGeo, capMat);
|
|
168
|
-
rightCap.position.set(this._batteryLen / 2 + capWidth / 2, this._batteryY, this._batteryZ);
|
|
169
|
-
rightCap.rotation.z = Math.PI;
|
|
170
|
-
meshes.push(rightCap);
|
|
171
|
-
// 내부 잔량/빈 부분
|
|
172
|
-
const fillLen = Math.max(this._batteryLen * rate / 100, 0.1);
|
|
173
|
-
const emptyLen = Math.max(this._batteryLen - fillLen, 0.1);
|
|
174
|
-
// 빈 부분 (짙은 회색, 불투명, 양단 닫힘)
|
|
175
|
-
const emptyGeo = new THREE.CylinderGeometry(innerRadius, innerRadius, emptyLen, 16);
|
|
176
|
-
emptyGeo.rotateZ(Math.PI / 2);
|
|
177
|
-
const emptyMat = new THREE.MeshStandardMaterial({
|
|
178
|
-
color: 0x333333,
|
|
179
|
-
roughness: 0.6,
|
|
180
|
-
metalness: 0.2,
|
|
181
|
-
side: THREE.DoubleSide,
|
|
182
|
-
});
|
|
183
|
-
const emptyMesh = new THREE.Mesh(emptyGeo, emptyMat);
|
|
184
|
-
emptyMesh.position.set((this._batteryLen - emptyLen) / 2, this._batteryY, this._batteryZ);
|
|
185
|
-
meshes.push(emptyMesh);
|
|
186
|
-
// 잔량 채움 (상태 컬러)
|
|
187
|
-
const fillGeo = new THREE.CylinderGeometry(innerRadius * 0.98, innerRadius * 0.98, fillLen, 16);
|
|
188
|
-
fillGeo.rotateZ(Math.PI / 2);
|
|
189
|
-
const fillMat = new THREE.MeshStandardMaterial({
|
|
190
|
-
color: batteryColor,
|
|
191
|
-
roughness: 0.3,
|
|
192
|
-
metalness: 0.1,
|
|
193
|
-
emissive: batteryColor,
|
|
194
|
-
emissiveIntensity: 0.4,
|
|
195
|
-
side: THREE.DoubleSide,
|
|
196
|
-
});
|
|
197
|
-
this._batteryFillMesh = new THREE.Mesh(fillGeo, fillMat);
|
|
198
|
-
this._batteryFillMesh.position.set(-(this._batteryLen - fillLen) / 2, this._batteryY, this._batteryZ);
|
|
199
|
-
meshes.push(this._batteryFillMesh);
|
|
200
|
-
return meshes;
|
|
201
|
-
}
|
|
202
|
-
getBatteryRate() {
|
|
203
|
-
const data = this.component.data;
|
|
204
|
-
return typeof (data === null || data === void 0 ? void 0 : data.BATTERYRATE) === 'number' ? data.BATTERYRATE : 0;
|
|
205
|
-
}
|
|
206
|
-
getBatteryColor(rate) {
|
|
207
|
-
try {
|
|
208
|
-
const comp = this.component;
|
|
209
|
-
if (comp.getBatteryColor) {
|
|
210
|
-
const color = comp.getBatteryColor(rate);
|
|
211
|
-
if (color)
|
|
212
|
-
return new THREE.Color(color).getHex();
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
catch ( /* fallback */_a) { /* fallback */ }
|
|
216
|
-
// 기본: 녹색 > 노랑 > 빨강
|
|
217
|
-
if (rate > 50)
|
|
218
|
-
return 0x4caf50;
|
|
219
|
-
if (rate > 20)
|
|
220
|
-
return 0xffc107;
|
|
221
|
-
return 0xf44336;
|
|
222
|
-
}
|
|
223
114
|
updateDimension() { }
|
|
224
115
|
update() {
|
|
225
116
|
// 자신의 mesh만 제거 (Carrier 등 자식 컴포넌트 3D 보존)
|
|
@@ -253,10 +144,6 @@ export class AGV3D extends RealObjectGroup {
|
|
|
253
144
|
}
|
|
254
145
|
super.onchange(after, before);
|
|
255
146
|
}
|
|
256
|
-
updateBattery() {
|
|
257
|
-
// 전체 rebuild로 정확한 geometry 생성
|
|
258
|
-
this.update();
|
|
259
|
-
}
|
|
260
147
|
}
|
|
261
148
|
registerRealObjectFactory('AGV', (component) => new AGV3D(component));
|
|
262
149
|
//# sourceMappingURL=agv-3d.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agv-3d.js","sourceRoot":"","sources":["../../src/factories/agv-3d.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * AGV 3D Factory\n *\n * 범퍼 + 본체 + 플랫폼 3단 구조:\n * - 하단 범퍼 (10%, 본체보다 약간 넓음, #222222)\n * - 본체 (58%, RoundedBoxGeometry, statusColor 적용)\n * - 간격 (4%)\n * - 상단 플랫폼 (28%, 본체보다 안쪽, #333333)\n *\n * Based on operato-scene Vehicle3D, adapted for fmsim:\n * - extends RealObjectGroup (Conveyor3D와 동일 패턴)\n * - statusColor from MCSStatusMixin\n * - 바닥 원점 (y=0~depth)\n */\n\nimport * as THREE from 'three'\nimport { RoundedBoxGeometry } from 'three/examples/jsm/geometries/RoundedBoxGeometry.js'\nimport { RealObjectGroup, registerRealObjectFactory, disposeObject3D } from '@hatiolab/things-scene'\nimport type { Component } from '@hatiolab/things-scene'\nimport { TRANSPORT_SURFACE_HEIGHT } from './machine-3d.js'\n\nconst BUMPER_COLOR = 0x222222\nconst PLATFORM_COLOR = 0x333333\nconst DEFAULT_BODY_COLOR = 0x6688cc\n\nexport class AGV3D extends RealObjectGroup {\n private _ownMeshes: THREE.Mesh[] = []\n get effectiveDepth(): number {\n const { depth } = this.component.state\n return depth || TRANSPORT_SURFACE_HEIGHT\n }\n\n protected get syncZPosOffset(): number {\n return 0\n }\n\n private resolveColor(): number {\n const comp = this.component as any\n\n // 1) MCSStatusMixin.statusColor (legend 기반 상태 색상)\n // '#F0F0F0'은 상태 미설정 시 기본 fallback — 무시하고 defaultColor 사용\n try {\n const sc = comp.statusColor\n if (typeof sc === 'string' && sc && sc.toUpperCase() !== '#F0F0F0') return new THREE.Color(sc).getHex()\n } catch {\n /* statusColor 미구현 시 무시 */\n }\n\n // 2) state.fillStyle fallback\n const { fillStyle } = this.component.state\n if (fillStyle && typeof fillStyle === 'string') {\n try {\n return new THREE.Color(fillStyle).getHex()\n } catch {\n /* 파싱 실패 시 무시 */\n }\n }\n\n return DEFAULT_BODY_COLOR\n }\n\n private _dataHandler?: () => void\n\n build() {\n super.build()\n\n // data 변경 감지 (배터리 잔량 업데이트)\n if (!this._dataHandler) {\n this._dataHandler = (_after: any, _before: any) => {\n if (_after.data !== undefined) this.updateBattery()\n }\n this.component.on('change', this._dataHandler)\n }\n\n const { width = 10, height = 10 } = this.component.state\n const w = Math.abs(width)\n const h = Math.abs(height)\n const d = this.effectiveDepth\n if (!w || !h) return\n\n // 비율: 하단 범퍼 10%, 본체 58%, 간격 4%, 플랫폼 28%\n const bumperH = d * 0.1\n const bodyH = d * 0.58\n const gapH = d * 0.04\n const platH = d * 0.28\n\n const cornerR = Math.min(w, h, bodyH) * 0.12\n\n // ── 하단 범퍼 밴드 (본체보다 약간 넓게 돌출) ──\n const bumperPad = Math.min(w, h) * 0.03\n const bumperCornerR = Math.min(w + bumperPad * 2, h + bumperPad * 2, bumperH) * 0.2\n const bumperGeo = new RoundedBoxGeometry(w + bumperPad * 2, bumperH, h + bumperPad * 2, 4, bumperCornerR)\n const bumperMat = new THREE.MeshStandardMaterial({\n color: BUMPER_COLOR,\n roughness: 0.8,\n metalness: 0.1,\n })\n const bumper = new THREE.Mesh(bumperGeo, bumperMat)\n bumper.position.y = bumperH / 2\n bumper.castShadow = true\n bumper.receiveShadow = true\n\n // ── 본체 (둥근 모서리, statusColor 적용) ──\n const bodyColor = this.resolveColor()\n const bodyGeo = new RoundedBoxGeometry(w, bodyH, h, 4, cornerR)\n const bodyMat = new THREE.MeshStandardMaterial({\n color: bodyColor,\n roughness: 0.3,\n metalness: 0.5,\n })\n const body = new THREE.Mesh(bodyGeo, bodyMat)\n body.position.y = bumperH + bodyH / 2\n body.castShadow = true\n body.receiveShadow = true\n\n // ── 상단 플랫폼 (본체보다 안쪽, 어두운색) ──\n const platInset = Math.min(w, h) * 0.04\n const platCornerR = Math.min(w - platInset * 2, h - platInset * 2, platH) * 0.15\n const platGeo = new RoundedBoxGeometry(w - platInset * 2, platH, h - platInset * 2, 4, platCornerR)\n const platMat = new THREE.MeshStandardMaterial({\n color: PLATFORM_COLOR,\n roughness: 0.5,\n metalness: 0.15,\n })\n const plat = new THREE.Mesh(platGeo, platMat)\n plat.position.y = bumperH + bodyH + gapH + platH / 2\n plat.castShadow = true\n plat.receiveShadow = true\n\n this._ownMeshes = [bumper, body, plat]\n\n // ── 배터리 실린더 (바디 뒷면, BATTERYRATE 데이터가 있을 때만) ──\n if (this.getBatteryRate() > 0) {\n const batteryMeshes = this.buildBattery(w, h, bumperH, bodyH)\n this._ownMeshes.push(...batteryMeshes)\n }\n\n for (const m of this._ownMeshes) this.object3d.add(m)\n }\n\n private _batteryFillMesh?: THREE.Mesh\n private _batteryLen = 0\n private _batteryY = 0\n private _batteryZ = 0\n\n private buildBattery(agvW: number, agvH: number, bodyBottomY: number, bodyH: number): THREE.Mesh[] {\n const radius = Math.min(agvW, agvH) * 0.15\n this._batteryLen = agvW * 0.7\n this._batteryY = bodyBottomY + bodyH * 0.5\n this._batteryZ = -agvH / 2 - radius * 1.5\n\n const rate = this.getBatteryRate()\n const batteryColor = this.getBatteryColor(rate)\n const innerRadius = radius * 0.85\n const capWidth = radius * 0.3\n const meshes: THREE.Mesh[] = []\n\n // 투명 외장 (유리 쉘, 양단 막힘)\n const shellGeo = new THREE.CylinderGeometry(radius, radius, this._batteryLen, 20)\n shellGeo.rotateZ(Math.PI / 2)\n const shellMat = new THREE.MeshStandardMaterial({\n color: 0xffffff,\n transparent: true,\n opacity: 0.25,\n roughness: 0.1,\n metalness: 0.1,\n side: THREE.DoubleSide,\n depthWrite: false,\n })\n const shell = new THREE.Mesh(shellGeo, shellMat)\n shell.position.set(0, this._batteryY, this._batteryZ)\n meshes.push(shell)\n\n // 좌측 캡 (금속)\n const capGeo = new THREE.CylinderGeometry(radius * 0.6, radius, capWidth, 20)\n capGeo.rotateZ(Math.PI / 2)\n const capMat = new THREE.MeshStandardMaterial({\n color: batteryColor, roughness: 0.3, metalness: 0.7,\n emissive: batteryColor, emissiveIntensity: 0.2,\n })\n const leftCap = new THREE.Mesh(capGeo, capMat)\n leftCap.position.set(-this._batteryLen / 2 - capWidth / 2, this._batteryY, this._batteryZ)\n meshes.push(leftCap)\n\n // 우측 캡 (금속)\n const rightCapGeo = capGeo.clone()\n const rightCap = new THREE.Mesh(rightCapGeo, capMat)\n rightCap.position.set(this._batteryLen / 2 + capWidth / 2, this._batteryY, this._batteryZ)\n rightCap.rotation.z = Math.PI\n meshes.push(rightCap)\n\n // 내부 잔량/빈 부분\n const fillLen = Math.max(this._batteryLen * rate / 100, 0.1)\n const emptyLen = Math.max(this._batteryLen - fillLen, 0.1)\n\n // 빈 부분 (짙은 회색, 불투명, 양단 닫힘)\n const emptyGeo = new THREE.CylinderGeometry(innerRadius, innerRadius, emptyLen, 16)\n emptyGeo.rotateZ(Math.PI / 2)\n const emptyMat = new THREE.MeshStandardMaterial({\n color: 0x333333,\n roughness: 0.6,\n metalness: 0.2,\n side: THREE.DoubleSide,\n })\n const emptyMesh = new THREE.Mesh(emptyGeo, emptyMat)\n emptyMesh.position.set(\n (this._batteryLen - emptyLen) / 2,\n this._batteryY, this._batteryZ\n )\n meshes.push(emptyMesh)\n\n // 잔량 채움 (상태 컬러)\n const fillGeo = new THREE.CylinderGeometry(innerRadius * 0.98, innerRadius * 0.98, fillLen, 16)\n fillGeo.rotateZ(Math.PI / 2)\n const fillMat = new THREE.MeshStandardMaterial({\n color: batteryColor,\n roughness: 0.3,\n metalness: 0.1,\n emissive: batteryColor,\n emissiveIntensity: 0.4,\n side: THREE.DoubleSide,\n })\n this._batteryFillMesh = new THREE.Mesh(fillGeo, fillMat)\n this._batteryFillMesh.position.set(\n -(this._batteryLen - fillLen) / 2,\n this._batteryY, this._batteryZ\n )\n meshes.push(this._batteryFillMesh)\n\n return meshes\n }\n\n private getBatteryRate(): number {\n const data = (this.component as any).data\n return typeof data?.BATTERYRATE === 'number' ? data.BATTERYRATE : 0\n }\n\n private getBatteryColor(rate: number): number {\n try {\n const comp = this.component as any\n if (comp.getBatteryColor) {\n const color = comp.getBatteryColor(rate)\n if (color) return new THREE.Color(color).getHex()\n }\n } catch { /* fallback */ }\n // 기본: 녹색 > 노랑 > 빨강\n if (rate > 50) return 0x4caf50\n if (rate > 20) return 0xffc107\n return 0xf44336\n }\n\n updateDimension() {}\n\n update() {\n // 자신의 mesh만 제거 (Carrier 등 자식 컴포넌트 3D 보존)\n for (const m of this._ownMeshes) {\n this.object3d.remove(m)\n disposeObject3D(m)\n }\n this._ownMeshes = []\n\n this.build()\n this.updateTransform()\n this.updateAlpha()\n this.updateHidden()\n }\n\n updateAlpha() {\n const { alpha = 1 } = this.component.state\n for (const m of this._ownMeshes) {\n const materials = Array.isArray(m.material) ? m.material : [m.material]\n for (const mat of materials) {\n ;(mat as THREE.MeshStandardMaterial).opacity = alpha\n ;(mat as THREE.MeshStandardMaterial).transparent = alpha < 1\n }\n }\n }\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n if ('width' in after || 'height' in after || 'depth' in after ||\n 'fillStyle' in after || 'strokeStyle' in after || 'id' in after ||\n 'EMPTYTYPE' in after || 'CARRIERSTATUS' in after) {\n this.update()\n return\n }\n\n super.onchange(after, before)\n }\n\n private updateBattery() {\n // 전체 rebuild로 정확한 geometry 생성\n this.update()\n }\n}\n\nregisterRealObjectFactory('AGV', (component: Component) => new AGV3D(component))\n"]}
|
|
1
|
+
{"version":3,"file":"agv-3d.js","sourceRoot":"","sources":["../../src/factories/agv-3d.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * AGV 3D Factory\n *\n * 범퍼 + 본체 + 플랫폼 3단 구조:\n * - 하단 범퍼 (10%, 본체보다 약간 넓음, #222222)\n * - 본체 (58%, RoundedBoxGeometry, statusColor 적용)\n * - 간격 (4%)\n * - 상단 플랫폼 (28%, 본체보다 안쪽, #333333)\n *\n * Based on operato-scene Vehicle3D, adapted for fmsim:\n * - extends RealObjectGroup (Conveyor3D와 동일 패턴)\n * - statusColor from MCSStatusMixin\n * - 바닥 원점 (y=0~depth)\n */\n\nimport * as THREE from 'three'\nimport { RoundedBoxGeometry } from 'three/examples/jsm/geometries/RoundedBoxGeometry.js'\nimport { RealObjectGroup, registerRealObjectFactory, disposeObject3D } from '@hatiolab/things-scene'\nimport type { Component } from '@hatiolab/things-scene'\nimport { TRANSPORT_SURFACE_HEIGHT } from './machine-3d.js'\n\nconst BUMPER_COLOR = 0x222222\nconst PLATFORM_COLOR = 0x333333\nconst DEFAULT_BODY_COLOR = 0x6688cc\n\nexport class AGV3D extends RealObjectGroup {\n private _ownMeshes: THREE.Mesh[] = []\n get effectiveDepth(): number {\n const { depth } = this.component.state\n return depth || TRANSPORT_SURFACE_HEIGHT\n }\n\n protected get syncZPosOffset(): number {\n return 0\n }\n\n private resolveColor(): number {\n const comp = this.component as any\n\n // 1) MCSStatusMixin.statusColor (legend 기반 상태 색상)\n // '#F0F0F0'은 상태 미설정 시 기본 fallback — 무시하고 defaultColor 사용\n try {\n const sc = comp.statusColor\n if (typeof sc === 'string' && sc && sc.toUpperCase() !== '#F0F0F0') return new THREE.Color(sc).getHex()\n } catch {\n /* statusColor 미구현 시 무시 */\n }\n\n // 2) state.fillStyle fallback\n const { fillStyle } = this.component.state\n if (fillStyle && typeof fillStyle === 'string') {\n try {\n return new THREE.Color(fillStyle).getHex()\n } catch {\n /* 파싱 실패 시 무시 */\n }\n }\n\n return DEFAULT_BODY_COLOR\n }\n\n build() {\n super.build()\n\n const { width = 10, height = 10 } = this.component.state\n const w = Math.abs(width)\n const h = Math.abs(height)\n const d = this.effectiveDepth\n if (!w || !h) return\n\n // 비율: 하단 범퍼 10%, 본체 58%, 간격 4%, 플랫폼 28%\n const bumperH = d * 0.1\n const bodyH = d * 0.58\n const gapH = d * 0.04\n const platH = d * 0.28\n\n const cornerR = Math.min(w, h, bodyH) * 0.12\n\n // ── 하단 범퍼 밴드 (본체보다 약간 넓게 돌출) ──\n const bumperPad = Math.min(w, h) * 0.03\n const bumperCornerR = Math.min(w + bumperPad * 2, h + bumperPad * 2, bumperH) * 0.2\n const bumperGeo = new RoundedBoxGeometry(w + bumperPad * 2, bumperH, h + bumperPad * 2, 4, bumperCornerR)\n const bumperMat = new THREE.MeshStandardMaterial({\n color: BUMPER_COLOR,\n roughness: 0.8,\n metalness: 0.1,\n })\n const bumper = new THREE.Mesh(bumperGeo, bumperMat)\n bumper.position.y = bumperH / 2\n bumper.castShadow = true\n bumper.receiveShadow = true\n\n // ── 본체 (둥근 모서리, statusColor 적용) ──\n const bodyColor = this.resolveColor()\n const bodyGeo = new RoundedBoxGeometry(w, bodyH, h, 4, cornerR)\n const bodyMat = new THREE.MeshStandardMaterial({\n color: bodyColor,\n roughness: 0.3,\n metalness: 0.5,\n })\n const body = new THREE.Mesh(bodyGeo, bodyMat)\n body.position.y = bumperH + bodyH / 2\n body.castShadow = true\n body.receiveShadow = true\n\n // ── 상단 플랫폼 (본체보다 안쪽, 어두운색) ──\n const platInset = Math.min(w, h) * 0.04\n const platCornerR = Math.min(w - platInset * 2, h - platInset * 2, platH) * 0.15\n const platGeo = new RoundedBoxGeometry(w - platInset * 2, platH, h - platInset * 2, 4, platCornerR)\n const platMat = new THREE.MeshStandardMaterial({\n color: PLATFORM_COLOR,\n roughness: 0.5,\n metalness: 0.15,\n })\n const plat = new THREE.Mesh(platGeo, platMat)\n plat.position.y = bumperH + bodyH + gapH + platH / 2\n plat.castShadow = true\n plat.receiveShadow = true\n\n this._ownMeshes = [bumper, body, plat]\n for (const m of this._ownMeshes) this.object3d.add(m)\n }\n\n updateDimension() {}\n\n update() {\n // 자신의 mesh만 제거 (Carrier 등 자식 컴포넌트 3D 보존)\n for (const m of this._ownMeshes) {\n this.object3d.remove(m)\n disposeObject3D(m)\n }\n this._ownMeshes = []\n\n this.build()\n this.updateTransform()\n this.updateAlpha()\n this.updateHidden()\n }\n\n updateAlpha() {\n const { alpha = 1 } = this.component.state\n for (const m of this._ownMeshes) {\n const materials = Array.isArray(m.material) ? m.material : [m.material]\n for (const mat of materials) {\n ;(mat as THREE.MeshStandardMaterial).opacity = alpha\n ;(mat as THREE.MeshStandardMaterial).transparent = alpha < 1\n }\n }\n }\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n if ('width' in after || 'height' in after || 'depth' in after ||\n 'fillStyle' in after || 'strokeStyle' in after || 'id' in after ||\n 'EMPTYTYPE' in after || 'CARRIERSTATUS' in after) {\n this.update()\n return\n }\n\n super.onchange(after, before)\n }\n}\n\nregisterRealObjectFactory('AGV', (component: Component) => new AGV3D(component))\n"]}
|
|
@@ -517,7 +517,7 @@ registerRealObjectFactory('STOCKER', (component) => new StockerRealObject3D(comp
|
|
|
517
517
|
// Unit (이동체 · 홀더) — 낮은 depth, 불투명
|
|
518
518
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
519
519
|
// Port: 바닥판 (PlaneGeometry)
|
|
520
|
-
const PORT_CONFIG = Object.assign(Object.assign({}, DEFAULTS), { depthRatio: 0.01, defaultZPosFromParent: true, opacity: 1, metalness: 0.3, roughness: 0.8, defaultColor: 0xb0a090, shape: 'plane' });
|
|
520
|
+
const PORT_CONFIG = Object.assign(Object.assign({}, DEFAULTS), { depthRatio: 0.01, defaultZPosFromParent: true, opacity: 0.1, metalness: 0.3, roughness: 0.8, defaultColor: 0xb0a090, shape: 'plane' });
|
|
521
521
|
registerRealObjectFactory('Port', (component) => new MCSRealObject3D(component, PORT_CONFIG));
|
|
522
522
|
register('Shelf', {
|
|
523
523
|
depthRatio: 0.25,
|
|
@@ -526,7 +526,7 @@ register('Shelf', {
|
|
|
526
526
|
defaultColor: 0xaabbcc,
|
|
527
527
|
});
|
|
528
528
|
// Carrier: CARRIERSTATUS에 따른 3D 애니메이션 지원
|
|
529
|
-
const CARRIER_CONFIG = Object.assign(Object.assign({}, DEFAULTS), { depthRatio: 0.5, metalness: 0
|
|
529
|
+
const CARRIER_CONFIG = Object.assign(Object.assign({}, DEFAULTS), { depthRatio: 0.5, metalness: 0, roughness: 1, defaultColor: 0x66bb66, isVisible: (c) => !!c.state.id, sizeRatio: 0.8, texturedTop: true });
|
|
530
530
|
class CarrierRealObject3D extends MCSRealObject3D {
|
|
531
531
|
constructor(component) {
|
|
532
532
|
super(component, CARRIER_CONFIG);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"machine-3d.js","sourceRoot":"","sources":["../../src/factories/machine-3d.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAEpG,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAmC9D;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAA;AAE1C,MAAM,QAAQ,GAAgB;IAC5B,UAAU,EAAE,GAAG;IACf,OAAO,EAAE,GAAG;IACZ,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,GAAG;IACd,YAAY,EAAE,QAAQ;IACtB,KAAK,EAAE,KAAK;CACb,CAAA;AAED,wDAAwD;AAExD,MAAM,eAAgB,SAAQ,eAAe;IAG3C,YAAY,SAAoB,EAAE,MAAmB;QACnD,KAAK,CAAC,SAAS,CAAC,CAAA;QAsNlB,wBAAwB;QAEhB,mBAAc,GAAG,KAAK,CAAA;QAvN5B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;IACvB,CAAC;IAED,mCAAmC;IACnC,IAAc,OAAO;QACnB,MAAM,EAAE,KAAK,GAAG,EAAE,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAA;QACxD,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAA;IACpD,CAAC;IAED,IAAI,cAAc;QAChB,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAA;QACtC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAA;QACvB,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAAA;QAC/D,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;QAC7B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAA;IACjD,CAAC;IAED,IAAc,cAAc;;QAC1B,qBAAqB;QACrB,IAAI,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC;YACvC,OAAO,wBAAwB,CAAA;QACjC,CAAC;QACD,uCAAuC;QACvC,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;YACzD,MAAM,UAAU,GAAG,MAAA,MAAA,IAAI,CAAC,SAAS,CAAC,MAAM,0CAAE,KAAK,0CAAE,IAAI,CAAA;YACrD,IAAI,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,KAAK,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;gBACxG,OAAO,CAAC,CAAA;YACV,CAAC;YACD,OAAO,wBAAwB,CAAA;QACjC,CAAC;QACD,OAAO,CAAC,CAAA;IACV,CAAC;IAED,yDAAyD;IAC/C,YAAY;QACpB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAgB,CAAA;QAElC,kDAAkD;QAClD,4DAA4D;QAC5D,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAA;YAC3B,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,SAAS;gBAAE,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAA;QACzG,CAAC;QAAC,WAAM,CAAC;YACP,0BAA0B;QAC5B,CAAC;QAED,8BAA8B;QAC9B,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAA;QAC1C,IAAI,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC/C,IAAI,CAAC;gBACH,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAA;YAC5C,CAAC;YAAC,WAAM,CAAC;gBACP,gBAAgB;YAClB,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,CAAA;IAClC,CAAC;IAED,yBAAyB;IAEzB;;;OAGG;IACK,gBAAgB,CAAC,QAA8B;QACrD,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC,CAAA;QACjD,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAA;QAChD,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAA;QAEjC,IAAI,CAAC,OAAO,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK;YAAE,OAAO,QAAQ,CAAA;QAEpD,MAAM,UAAU,GAAa,EAAE,CAAA;QAC/B,MAAM,OAAO,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,CAAA;QAEnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACvB,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YAC3B,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;YAE3B,4BAA4B;YAC5B,MAAM,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;YAEzE,+CAA+C;YAC/C,IAAI,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;gBAChB,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;YAC1B,CAAC;QACH,CAAC;QAED,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;QAC7B,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,0BAA0B;IAElB,gBAAgB,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;QACtD,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QAC1C,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAA;IACvE,CAAC;IAEO,oBAAoB,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;QAC1D,8BAA8B;QAC9B,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAA;QACnC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAA;QAChB,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAA;QAEhB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE,CAAA;QAC/B,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;QAC/B,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC,CAAA;QAC9B,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;QACnB,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC,CAAA;QAC7B,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC,CAAA;QAC9B,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAA;QACpB,KAAK,CAAC,SAAS,EAAE,CAAA;QAEjB,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,eAAe,CAAC,KAAK,EAAE;YAC3C,KAAK,EAAE,CAAC;YACR,KAAK,EAAE,CAAC;YACR,YAAY,EAAE,KAAK;SACpB,CAAC,CAAA;QAEF,2CAA2C;QAC3C,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QAC3B,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;QAExB,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAA;IACnC,CAAC;IAEO,kBAAkB,CAAC,CAAS,EAAE,CAAS;QAC7C,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QACzC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;QACzB,OAAO,GAAG,CAAA;IACZ,CAAC;IAMD,KAAK;;QACH,KAAK,CAAC,KAAK,EAAE,CAAA;QAEb,2CAA2C;QAC3C,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC;YAAE,OAAM;QAE7E,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAA;QACpC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;YAAE,OAAM;QAE1B,MAAM,KAAK,GAAG,MAAA,IAAI,CAAC,OAAO,CAAC,SAAS,mCAAI,GAAG,CAAA;QAC3C,MAAM,CAAC,GAAG,IAAI,GAAG,KAAK,CAAA;QACtB,MAAM,CAAC,GAAG,IAAI,GAAG,KAAK,CAAA;QACtB,MAAM,KAAK,GAAG,QAAQ,GAAG,KAAK,CAAA;QAE9B,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAA;QACjC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;QAE7D,MAAM,QAAQ,GACZ,KAAK,KAAK,OAAO;YACf,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAC;YAC/B,CAAC,CAAC,KAAK,KAAK,SAAS;gBACnB,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;gBACxC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;QAE1C,MAAM,OAAO,GAAG,KAAK,KAAK,OAAO,CAAA;QACjC,MAAM,QAAQ,GAAG,OAAO;YACtB,CAAC,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC;gBAC1B,KAAK;gBACL,OAAO;gBACP,WAAW,EAAE,OAAO,GAAG,CAAC;gBACxB,IAAI,EAAE,KAAK,CAAC,UAAU;gBACtB,UAAU,EAAE,OAAO,IAAI,GAAG;aAC3B,CAAC;YACJ,CAAC,CAAC,IAAI,KAAK,CAAC,oBAAoB,iBAC5B,KAAK;gBACL,SAAS;gBACT,SAAS;gBACT,OAAO,EACP,WAAW,EAAE,OAAO,GAAG,CAAC,EACxB,IAAI,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,EACtD,UAAU,EAAE,OAAO,IAAI,GAAG,IACvB,CAAC,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,iBAAiB,EAAE,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EACjH,CAAA;QACN,6CAA6C;QAC7C,QAAQ,CAAC,aAAa,GAAG,IAAI,CAAA;QAC7B,QAAQ,CAAC,mBAAmB,GAAG,CAAC,CAAC,CAAA;QACjC,QAAQ,CAAC,iBAAiB,GAAG,CAAC,CAAC,CAAA;QAE/B,wEAAwE;QACxE,IAAI,YAAY,GAAsC,QAAQ,CAAA;QAC9D,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;YACpB,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBACzB,oBAAoB;gBACpB,MAAM,SAAS,GAAG,IAAI,KAAK,CAAC,iBAAiB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;gBACjE,YAAY,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;YAC9E,CAAC;iBAAM,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;gBACpC,iBAAiB;gBACjB,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;gBACzC,YAAY,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;YAC3E,CAAC;iBAAM,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACjC,UAAU;gBACV,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,GAAG,CAAC,EAAE,CAAC,CAAA;gBACvF,YAAY,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAA;YAC1E,CAAC;QACH,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAA;QACtD,uDAAuD;QACvD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAA;QAC7E,IAAI,CAAC,QAAQ,CAAC,UAAU,GAAG,CAAC,OAAO,CAAA;QACnC,IAAI,CAAC,QAAQ,CAAC,aAAa,GAAG,IAAI,CAAA;QAClC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IAClC,CAAC;IAMD,QAAQ,CAAC,KAA8B,EAAE,MAA+B;QACtE,IACE,OAAO,IAAI,KAAK;YAChB,QAAQ,IAAI,KAAK;YACjB,OAAO,IAAI,KAAK;YAChB,WAAW,IAAI,KAAK;YACpB,aAAa,IAAI,KAAK;YACtB,IAAI,IAAI,KAAK;YACb,WAAW,IAAI,KAAK;YACpB,eAAe,IAAI,KAAK,EACxB,CAAC;YACD,gDAAgD;YAChD,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;gBACzB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAA;gBAC1B,cAAc,CAAC,GAAG,EAAE;oBAClB,IAAI,CAAC,cAAc,GAAG,KAAK,CAAA;oBAC3B,IAAI,CAAC,MAAM,EAAE,CAAA;gBACf,CAAC,CAAC,CAAA;YACJ,CAAC;YACD,OAAM;QACR,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IAC/B,CAAC;IAED;;OAEG;IACO,eAAe,CAAC,CAAS,EAAE,CAAS;;QAC5C,MAAM,KAAK,GAAG,CAAC,CAAA;QACf,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,KAAK,CAAC,CAAA;QACnC,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,KAAK,CAAC,CAAA;QACnC,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;QAC/C,MAAM,CAAC,KAAK,GAAG,EAAE,CAAA;QACjB,MAAM,CAAC,MAAM,GAAG,EAAE,CAAA;QAClB,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAE,CAAA;QAEpC,MAAM,WAAW,GAAG,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;QAC3E,MAAM,SAAS,GAAG,CAAA,MAAC,IAAI,CAAC,SAAS,CAAC,KAAa,0CAAE,SAAS,KAAI,EAAE,CAAA;QAChE,MAAM,IAAI,GAAG,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,KAAK,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAA;QAE7G,4BAA4B;QAC5B,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAA;QACvB,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAA;QAEvB,yBAAyB;QACzB,GAAG,CAAC,SAAS,GAAG,WAAW,CAAA;QAC3B,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAA;QAEhC,iBAAiB;QACjB,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC,CAAA;YACzD,GAAG,CAAC,IAAI,GAAG,QAAQ,QAAQ,UAAU,CAAA;YACrC,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAA;YACxB,GAAG,CAAC,YAAY,GAAG,QAAQ,CAAA;YAC3B,GAAG,CAAC,SAAS,GAAG,SAAS,CAAA;YACzB,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAA;QAC1C,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;QAC/C,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC,CAAA;QACrC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,EAAE,KAAK,GAAG,EAAE,CAAC,CAAA;QAC1C,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC,cAAc,CAAA;QAEzC,OAAO,IAAI,KAAK,CAAC,iBAAiB,CAAC;YACjC,GAAG,EAAE,OAAO;YACZ,WAAW,EAAE,IAAI;YACjB,IAAI,EAAE,KAAK,CAAC,UAAU;SACvB,CAAC,CAAA;IACJ,CAAC;IAEO,QAAQ,CAAC,CAAS;QACxB,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAAE,OAAO,CAAC,CAAA;QACtB,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACpB,CAAC,EAAE,CAAA;QACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;QAChE,OAAO,CAAC,GAAG,CAAC,CAAA;IACd,CAAC;IAED;;;;;OAKG;IACH,MAAM;QACJ,oCAAoC;QACpC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YACnC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YAC9B,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAA;QAC3B,CAAC;QAED,IAAI,CAAC,KAAK,EAAE,CAAA;QACZ,IAAI,CAAC,eAAe,EAAE,CAAA;QACtB,IAAI,CAAC,WAAW,EAAE,CAAA;QAClB,IAAI,CAAC,YAAY,EAAE,CAAA;IACrB,CAAC;IAED,6BAA6B;IAC7B,eAAe,KAAI,CAAC;IAEpB,WAAW;QACT,MAAM,EAAE,KAAK,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAA;QAC1C,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAA;QAC1C,MAAM,SAAS,GAAG,aAAa,GAAG,KAAK,CAAA;QAEvC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAM,EAAE,EAAE;YAChC,IAAI,CAAC,CAAC,CAAC,QAAQ;gBAAE,OAAM;YACvB,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAA;YACvE,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;gBAC1B,IAAI,CAAC,CAAC,CAAC,OAAO;oBAAE,SAAQ,CAAC,4BAA4B;gBACrD,IAAI,CAAC,CAAC,GAAG;oBAAE,SAAQ,CAAC,kCAAkC;gBACtD,CAAC,CAAC,OAAO,GAAG,SAAS,CAAA;gBACrB,CAAC,CAAC,WAAW,GAAG,SAAS,GAAG,CAAC,CAAA;YAC/B,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;CACF;AAED,qDAAqD;AAErD,SAAS,QAAQ,CAAC,IAAY,EAAE,YAAkC,EAAE;IAClE,MAAM,MAAM,mCAAqB,QAAQ,GAAK,SAAS,CAAE,CAAA;IACzD,yBAAyB,CAAC,IAAI,EAAE,CAAC,SAAoB,EAAE,EAAE,CAAC,IAAI,eAAe,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;AACnG,CAAC;AAED,0DAA0D;AAC1D,0CAA0C;AAC1C,0DAA0D;AAE1D,QAAQ,CAAC,WAAW,EAAE;IACpB,YAAY,EAAE,CAAC,GAAG,wBAAwB;IAC1C,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,GAAG;IACd,YAAY,EAAE,QAAQ;CACvB,CAAC,CAAA;AAEF,QAAQ,CAAC,QAAQ,EAAE;IACjB,YAAY,EAAE,wBAAwB;IACtC,OAAO,EAAE,GAAG;IACZ,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,GAAG;IACd,YAAY,EAAE,QAAQ;IACtB,KAAK,EAAE,SAAS;CACjB,CAAC,CAAA;AAEF,QAAQ,CAAC,SAAS,EAAE;IAClB,UAAU,EAAE,IAAI;IAChB,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,GAAG;IACd,YAAY,EAAE,QAAQ;CACvB,CAAC,CAAA;AAEF,QAAQ,CAAC,SAAS,EAAE;IAClB,UAAU,EAAE,IAAI;IAChB,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,GAAG;IACd,YAAY,EAAE,QAAQ;CACvB,CAAC,CAAA;AAEF,0CAA0C;AAC1C,MAAM,cAAc,mCACf,QAAQ,KACX,YAAY,EAAE,CAAC,GAAG,wBAAwB,EAC1C,OAAO,EAAE,IAAI,EACb,SAAS,EAAE,GAAG,EACd,SAAS,EAAE,GAAG,EACd,YAAY,EAAE,QAAQ,GACvB,CAAA;AAED,MAAM,mBAAoB,SAAQ,eAAe;IAG/C,YAAY,SAAoB;QAC9B,KAAK,CAAC,SAAS,EAAE,cAAc,CAAC,CAAA;IAClC,CAAC;IAED,KAAK;QACH,KAAK,CAAC,KAAK,EAAE,CAAA;QACb,IAAI,CAAC,UAAU,EAAE,CAAA;IACnB,CAAC;IAEO,UAAU;;QAChB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAgB,CAAA;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAA;QAC5B,MAAM,SAAS,GAAG,CAAA,MAAA,MAAA,IAAI,CAAC,IAAI,0CAAE,KAAK,0CAAE,gBAAgB,KAAI,UAAU,CAAA;QAElE,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;QAEhD,mCAAmC;QACnC,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,CAAA;QACpC,IAAI,WAAW,IAAI,WAAW,CAAC,WAAW,EAAE,KAAK,SAAS,EAAE,CAAC;YAC3D,KAAK,CAAC,WAAW,GAAG,WAAW,CAAA;QACjC,CAAC;QAED,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAA;QACjC,MAAM,aAAa,GAAG,CAAC,IAAI,CAAC,CAAA;QAE5B,iBAAiB;QACjB,MAAM,IAAI,GAAG,GAAG,CAAA;QAChB,MAAM,IAAI,GAAG,EAAE,CAAA;QACf,MAAM,KAAK,GAAG,CAAC,CAAA;QACf,MAAM,OAAO,GAAG,IAAI,GAAG,KAAK,CAAA;QAC5B,MAAM,OAAO,GAAG,IAAI,GAAG,KAAK,CAAA;QAC5B,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;QAC/C,MAAM,CAAC,KAAK,GAAG,OAAO,CAAA;QACtB,MAAM,CAAC,MAAM,GAAG,OAAO,CAAA;QACvB,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAE,CAAA;QAEpC,MAAM,GAAG,GAAG,EAAE,CAAA;QAEd,WAAW;QACX,GAAG,CAAC,SAAS,GAAG,SAAS,CAAA;QACzB,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;QACpC,GAAG,CAAC,WAAW,GAAG,KAAK,CAAC,WAAW,CAAA;QACnC,GAAG,CAAC,SAAS,GAAG,EAAE,CAAA;QAClB,GAAG,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,GAAG,EAAE,EAAE,OAAO,GAAG,EAAE,CAAC,CAAA;QAEhD,gBAAgB;QAChB,MAAM,MAAM,GAAG,OAAO,GAAG,GAAG,GAAG,CAAC,CAAA;QAChC,MAAM,MAAM,GAAG,OAAO,GAAG,GAAG,GAAG,CAAC,CAAA;QAChC,IAAI,CAAC,GAAG,GAAG,CAAA;QACX,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACjC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;YAChE,IAAI,IAAI,IAAI,CAAC;gBAAE,SAAQ;YACvB,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC,KAAK,CAAA;YACzB,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;YAClC,CAAC,IAAI,IAAI,CAAA;QACX,CAAC;QAED,MAAM;QACN,GAAG,CAAC,IAAI,GAAG,QAAQ,EAAE,GAAG,KAAK,eAAe,CAAA;QAC5C,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAA;QACxB,GAAG,CAAC,YAAY,GAAG,QAAQ,CAAA;QAC3B,GAAG,CAAC,SAAS,GAAG,SAAS,CAAA;QACzB,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAA;QAEnD,cAAc;QACd,MAAM,OAAO,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;QAC/C,OAAO,CAAC,UAAU,GAAG,KAAK,CAAC,cAAc,CAAA;QAEzC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QAC/C,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA,CAAC,YAAY;QACtC,IAAI,CAAC,aAAa;YAAE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;QAE5C,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,iBAAiB,CAAC;YACtC,GAAG,EAAE,OAAO;YACZ,WAAW,EAAE,IAAI;YACjB,IAAI,EAAE,KAAK,CAAC,UAAU;SACvB,CAAC,CAAA;QACF,GAAG,CAAC,aAAa,GAAG,IAAI,CAAA;QACxB,GAAG,CAAC,mBAAmB,GAAG,CAAC,CAAC,CAAA;QAC5B,GAAG,CAAC,iBAAiB,GAAG,CAAC,CAAC,CAAA;QAE1B,IAAI,CAAC,SAAS,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;QACzC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,GAAG,EAAE,CAAC,CAAC,CAAA;QAC9C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACnC,CAAC;IAEO,YAAY,CAAC,IAAS,EAAE,IAAY;;QAC1C,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,SAAS,CAAC,CAAC,CAAC;gBACf,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;gBACvC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAA;gBACzC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;gBACnD,MAAM,KAAK,GAAG,IAAI,GAAG,KAAK,GAAG,UAAU,CAAA;gBACvC,MAAM,QAAQ,GAAG,KAAK,GAAG,CAAC;oBACxB,CAAC,CAAC;wBACE,EAAE,KAAK,EAAE,IAAI,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE;wBACzC,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE;wBAC1C,EAAE,KAAK,EAAE,UAAU,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE;qBAChD;oBACH,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;gBACpC,OAAO;oBACL,QAAQ;oBACR,WAAW,EAAE,SAAS;oBACtB,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,KAAK,KAAK,MAAM,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE;iBAC7D,CAAA;YACH,CAAC;YACD,KAAK,UAAU,CAAC,CAAC,CAAC;gBAChB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;gBAC/C,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAA;gBACnD,MAAM,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;gBAC/B,MAAM,QAAQ,GAAG,KAAK,GAAG,CAAC;oBACxB,CAAC,CAAC;wBACE,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE;wBAC3C,EAAE,KAAK,EAAE,QAAQ,GAAG,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE;qBAC9C;oBACH,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;gBACpC,OAAO;oBACL,QAAQ;oBACR,WAAW,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;oBACjD,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE;iBAClD,CAAA;YACH,CAAC;YACD,OAAO,CAAC,CAAC,CAAC,CAAC,WAAW;gBACpB,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;gBAC7C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,GAAG,CAAA;gBAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,KAAK,GAAG,CAAA;gBAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAA;gBAC3C,MAAM,MAAM,GAAG,CAAA,MAAA,MAAC,IAAI,CAAC,SAAiB,CAAC,IAAI,0CAAE,KAAK,0CAAE,eAAe,KAAI,eAAe,CAAA;gBACtF,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,SAAS,CAAC,CAAA;gBAC5E,OAAO;oBACL,QAAQ,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,GAAG,EAAE,KAAK,EAAE,CAAC;oBACzC,WAAW,EAAE,KAAK;oBAClB,KAAK,EAAE,GAAG,KAAK,GAAG;iBACnB,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,KAA8B,EAAE,MAA+B;QACtE,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;YACpB,IAAI,CAAC,UAAU,EAAE,CAAA;YACjB,IAAI,CAAC,UAAU,EAAE,CAAA;QACnB,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IAC/B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,UAAU,EAAE,CAAA;QACjB,OAAO,KAAK,CAAC,KAAK,EAAE,CAAA;IACtB,CAAC;IAEO,UAAU;;QAChB,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;YACpC,MAAA,IAAI,CAAC,SAAS,CAAC,QAAQ,0CAAE,OAAO,EAAE,CAAA;YAClC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,QAAmC,CAAA;YAC9D,MAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,GAAG,0CAAE,OAAO,EAAE,CAAA;YACnB,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,OAAO,EAAE,CAAA;YACd,IAAI,CAAC,SAAS,GAAG,SAAS,CAAA;QAC5B,CAAC;IACH,CAAC;CACF;AAED,yBAAyB,CAAC,SAAS,EAAE,CAAC,SAAoB,EAAE,EAAE,CAAC,IAAI,mBAAmB,CAAC,SAAS,CAAC,CAAC,CAAA;AAElG,0DAA0D;AAC1D,mCAAmC;AACnC,0DAA0D;AAE1D,4BAA4B;AAC5B,MAAM,WAAW,mCACZ,QAAQ,KACX,UAAU,EAAE,IAAI,EAChB,qBAAqB,EAAE,IAAI,EAC3B,OAAO,EAAE,CAAC,EACV,SAAS,EAAE,GAAG,EACd,SAAS,EAAE,GAAG,EACd,YAAY,EAAE,QAAQ,EACtB,KAAK,EAAE,OAAO,GACf,CAAA;AACD,yBAAyB,CAAC,MAAM,EAAE,CAAC,SAAoB,EAAE,EAAE,CAAC,IAAI,eAAe,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAA;AAExG,QAAQ,CAAC,OAAO,EAAE;IAChB,UAAU,EAAE,IAAI;IAChB,SAAS,EAAE,GAAG;IACd,SAAS,EAAE,GAAG;IACd,YAAY,EAAE,QAAQ;CACvB,CAAC,CAAA;AAEF,yCAAyC;AACzC,MAAM,cAAc,mCACf,QAAQ,KACX,UAAU,EAAE,GAAG,EACf,SAAS,EAAE,GAAG,EACd,SAAS,EAAE,GAAG,EACd,YAAY,EAAE,QAAQ,EACtB,SAAS,EAAE,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAE,CAAC,CAAC,KAAa,CAAC,EAAE,EAClD,SAAS,EAAE,GAAG,EACd,WAAW,EAAE,IAAI,EACjB,iBAAiB,EAAE,GAAG,GACvB,CAAA;AAED,MAAM,mBAAoB,SAAQ,eAAe;IAC/C,YAAY,SAAoB;QAC9B,KAAK,CAAC,SAAS,EAAE,cAAc,CAAC,CAAA;IAClC,CAAC;CACF;AAED,yBAAyB,CAAC,SAAS,EAAE,CAAC,SAAoB,EAAE,EAAE,CAAC,IAAI,mBAAmB,CAAC,SAAS,CAAC,CAAC,CAAA;AAElG,0DAA0D;AAC1D,yBAAyB;AACzB,0DAA0D;AAE1D,0DAA0D;AAC1D,6CAA6C;AAC7C,0DAA0D;AAE1D,yEAAyE;AACzE,uDAAuD;AACvD,yBAAyB,CAAC,oBAAoB,EAAE,GAAG,EAAE,CAAC,IAAW,CAAC,CAAA;AAClE,yBAAyB,CAAC,qBAAqB,EAAE,GAAG,EAAE,CAAC,IAAW,CAAC,CAAA;AACnE,yBAAyB,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,IAAW,CAAC,CAAA","sourcesContent":["/**\n * MCS 설비 컴포넌트 3D 팩토리\n *\n * 10,000+ 인스턴스를 위한 최소 폴리곤 설계:\n * - 컴포넌트당 단일 Mesh (draw call 최소화)\n * - BoxGeometry / ExtrudeGeometry(hexagon) 만 사용\n * - Machine: 높은 depth, 컨테이너는 반투명\n * - Unit: 낮은 depth, 불투명\n */\n\nimport * as THREE from 'three'\nimport { RealObjectGroup, registerRealObjectFactory, disposeObject3D } from '@hatiolab/things-scene'\nimport type { Component } from '@hatiolab/things-scene'\nimport { LEGEND_CAPACITY } from '../features/mcs-status-default'\nimport { getVaueOnRanges } from '../utils/get-value-on-ranges'\n\n// ── 설정 타입 ────────────────────────────────────────────\n\ninterface MCS3DConfig {\n /** state.depth 미설정 시 기본 depth.\n * defaultDepth > 0이면 절대값, 아니면 min(w,h) * depthRatio */\n depthRatio: number\n defaultDepth?: number\n /** true이면 syncZPosOffset = TRANSPORT_SURFACE_HEIGHT */\n defaultZPosFromParent?: boolean\n /** 1.0 = 불투명, 0.35 = 반투명 컨테이너 */\n opacity: number\n metalness: number\n roughness: number\n /** statusColor 미사용 시 기본 색상 */\n defaultColor: number\n /** 'box' | 'hexagon' */\n shape: 'box' | 'hexagon' | 'plane'\n /** mesh 생성 전 가시성 판정 — false 반환 시 mesh 미생성 */\n isVisible?: (component: Component) => boolean\n /** 부모 대비 크기 비율 (기본 1.0). < 1이면 부모 중심에 배치. */\n sizeRatio?: number\n /** 상부 면 제거 (5면 개방 박스) */\n openTop?: boolean\n /** 상판 무반사 (MeshBasicMaterial) */\n matteTop?: boolean\n /** 상판에 2D 렌더링 텍스처 적용 */\n texturedTop?: boolean\n /** 자체 발광 강도 (0~1). 조명 약한 면에서도 색상 유지 */\n emissiveIntensity?: number\n /** 바닥면 유지 (기본 false — 바닥면 제거) */\n keepBottomFace?: boolean\n}\n\n/**\n * 포트 기본 높이 (절대값).\n * 모든 이송장치의 상단 높이 = 이 값.\n * 캐리어가 이송장치 간 높이 차 없이 이동할 수 있는 기준 높이.\n */\nexport const TRANSPORT_SURFACE_HEIGHT = 30\n\nconst DEFAULTS: MCS3DConfig = {\n depthRatio: 0.5,\n opacity: 1.0,\n metalness: 0.3,\n roughness: 0.7,\n defaultColor: 0xaabbcc,\n shape: 'box',\n}\n\n// ── 3D 오브젝트 ──────────────────────────────────────────\n\nclass MCSRealObject3D extends RealObjectGroup {\n private _config: MCS3DConfig\n\n constructor(component: Component, config: MCS3DConfig) {\n super(component)\n this._config = config\n }\n\n // width, height 절대값 (음수 값은 양수로 취급)\n protected get absSize(): { w: number; h: number } {\n const { width = 10, height = 10 } = this.component.state\n return { w: Math.abs(width), h: Math.abs(height) }\n }\n\n get effectiveDepth(): number {\n const { depth } = this.component.state\n if (depth) return depth\n if (this._config.defaultDepth) return this._config.defaultDepth\n const { w, h } = this.absSize\n return Math.min(w, h) * this._config.depthRatio\n }\n\n protected get syncZPosOffset(): number {\n // Port: 이송 표면 높이에 배치\n if (this._config.defaultZPosFromParent) {\n return TRANSPORT_SURFACE_HEIGHT\n }\n // Carrier: Port 안이면 중앙, 그 외 컨테이너면 상단 위\n if (this._config.sizeRatio && this._config.sizeRatio < 1) {\n const parentType = this.component.parent?.state?.type\n if (parentType === 'Port' || parentType === 'Shelf' || parentType === 'OHT' || parentType === 'Shuttle') {\n return 0\n }\n return TRANSPORT_SURFACE_HEIGHT\n }\n return 0\n }\n\n // 컴포넌트의 상태 색상(statusColor) 또는 fillStyle → Three.js 색상 변환\n protected resolveColor(): number {\n const comp = this.component as any\n\n // 1) MCSStatusMixin.statusColor (legend 기반 상태 색상)\n // '#F0F0F0'은 상태 미설정 시 기본 fallback — 무시하고 defaultColor 사용\n try {\n const sc = comp.statusColor\n if (typeof sc === 'string' && sc && sc.toUpperCase() !== '#F0F0F0') return new THREE.Color(sc).getHex()\n } catch {\n /* statusColor 미구현 시 무시 */\n }\n\n // 2) state.fillStyle fallback\n const { fillStyle } = this.component.state\n if (fillStyle && typeof fillStyle === 'string') {\n try {\n return new THREE.Color(fillStyle).getHex()\n } catch {\n /* 파싱 실패 시 무시 */\n }\n }\n\n return this._config.defaultColor\n }\n\n // ── Geometry helpers ──\n\n /**\n * 바닥면(-Y 방향) 삼각형 제거: z-fighting 근본 해결.\n * 바닥면이 없으면 floor grid와 겹칠 면 자체가 없어진다.\n */\n private removeBottomFace(geometry: THREE.BufferGeometry): THREE.BufferGeometry {\n const posAttr = geometry.getAttribute('position')\n const normAttr = geometry.getAttribute('normal')\n const index = geometry.getIndex()\n\n if (!posAttr || !normAttr || !index) return geometry\n\n const newIndices: number[] = []\n const normalY = new THREE.Vector3()\n\n for (let i = 0; i < index.count; i += 3) {\n const a = index.getX(i)\n const b = index.getX(i + 1)\n const c = index.getX(i + 2)\n\n // 세 꼭짓점 노말의 Y 성분 평균으로 방향 판단\n const avgY = (normAttr.getY(a) + normAttr.getY(b) + normAttr.getY(c)) / 3\n\n // -Y 방향 삼각형 제거 (threshold -0.9: 거의 아래를 향하는 면만)\n if (avgY > -0.9) {\n newIndices.push(a, b, c)\n }\n }\n\n geometry.setIndex(newIndices)\n return geometry\n }\n\n // ── Geometry builders ──\n\n private buildBoxGeometry(w: number, d: number, h: number): THREE.BufferGeometry {\n const geo = new THREE.BoxGeometry(w, d, h)\n return this._config.keepBottomFace ? geo : this.removeBottomFace(geo)\n }\n\n private buildHexagonGeometry(w: number, d: number, h: number): THREE.BufferGeometry {\n // Buffer의 2D 형태: 좌우 끝이 꺾인 육각형\n const offset = Math.min(w, h) * 0.2\n const hw = w / 2\n const hh = h / 2\n\n const shape = new THREE.Shape()\n shape.moveTo(-hw + offset, -hh)\n shape.lineTo(hw - offset, -hh)\n shape.lineTo(hw, 0)\n shape.lineTo(hw - offset, hh)\n shape.lineTo(-hw + offset, hh)\n shape.lineTo(-hw, 0)\n shape.closePath()\n\n const geo = new THREE.ExtrudeGeometry(shape, {\n steps: 1,\n depth: d,\n bevelEnabled: false,\n })\n\n // 중심 정렬 후 Y-up 좌표계 회전 (extrude 축: +Z → +Y)\n geo.translate(0, 0, -d / 2)\n geo.rotateX(Math.PI / 2)\n\n return this.removeBottomFace(geo)\n }\n\n private buildPlaneGeometry(w: number, h: number): THREE.BufferGeometry {\n const geo = new THREE.PlaneGeometry(w, h)\n geo.rotateX(-Math.PI / 2)\n return geo\n }\n\n // ── Build ──\n\n protected _ownMesh?: THREE.Mesh\n\n build() {\n super.build()\n\n // 가시성 판정 — e.g., Carrier는 데이터 없으면 mesh 미생성\n if (this._config.isVisible && !this._config.isVisible(this.component)) return\n\n const { w: rawW, h: rawH } = this.absSize\n const rawDepth = this.effectiveDepth\n if (!rawW || !rawH) return\n\n const ratio = this._config.sizeRatio ?? 1.0\n const w = rawW * ratio\n const h = rawH * ratio\n const depth = rawDepth * ratio\n\n const color = this.resolveColor()\n const { opacity, metalness, roughness, shape } = this._config\n\n const geometry =\n shape === 'plane'\n ? this.buildPlaneGeometry(w, h)\n : shape === 'hexagon'\n ? this.buildHexagonGeometry(w, depth, h)\n : this.buildBoxGeometry(w, depth, h)\n\n const isPlane = shape === 'plane'\n const material = isPlane\n ? new THREE.MeshBasicMaterial({\n color,\n opacity,\n transparent: opacity < 1,\n side: THREE.DoubleSide,\n depthWrite: opacity >= 0.9,\n })\n : new THREE.MeshStandardMaterial({\n color,\n metalness,\n roughness,\n opacity,\n transparent: opacity < 1,\n side: opacity < 1 ? THREE.DoubleSide : THREE.FrontSide,\n depthWrite: opacity >= 0.9,\n ...(this._config.emissiveIntensity ? { emissive: color, emissiveIntensity: this._config.emissiveIntensity } : {}),\n })\n // z-fighting 방지: 바닥면(floor grid)보다 항상 앞에 렌더링\n material.polygonOffset = true\n material.polygonOffsetFactor = -1\n material.polygonOffsetUnit = -1\n\n // BoxGeometry material groups: +x(0), -x(1), +y(2), -y(3), +z(4), -z(5)\n let meshMaterial: THREE.Material | THREE.Material[] = material\n if (shape === 'box') {\n if (this._config.openTop) {\n // 상단면 제거 → 5면 개방 박스\n const invisible = new THREE.MeshBasicMaterial({ visible: false })\n meshMaterial = [material, material, invisible, material, material, material]\n } else if (this._config.texturedTop) {\n // 상판에 2D 렌더링 텍스처\n const topMat = this.buildTopTexture(w, h)\n meshMaterial = [material, material, topMat, material, material, material]\n } else if (this._config.matteTop) {\n // 상판만 무반사\n const matte = new THREE.MeshBasicMaterial({ color, opacity, transparent: opacity < 1 })\n meshMaterial = [material, material, matte, material, material, material]\n }\n }\n\n this._ownMesh = new THREE.Mesh(geometry, meshMaterial)\n // sizeRatio < 1이면 부모 중심에 배치 (rawDepth/2), plane은 살짝 띄움\n this._ownMesh.position.y = isPlane ? 1 : ratio < 1 ? rawDepth / 2 : depth / 2\n this._ownMesh.castShadow = !isPlane\n this._ownMesh.receiveShadow = true\n this.object3d.add(this._ownMesh)\n }\n\n // ── Change handling ──\n\n private _updatePending = false\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n if (\n 'width' in after ||\n 'height' in after ||\n 'depth' in after ||\n 'fillStyle' in after ||\n 'strokeStyle' in after ||\n 'id' in after ||\n 'EMPTYTYPE' in after ||\n 'CARRIERSTATUS' in after\n ) {\n // 연속 setState에 의한 다중 rebuild 방지: 한 프레임에 한 번만 실행\n if (!this._updatePending) {\n this._updatePending = true\n queueMicrotask(() => {\n this._updatePending = false\n this.update()\n })\n }\n return\n }\n\n super.onchange(after, before)\n }\n\n /**\n * 상판 텍스처: 컴포넌트의 2D render()를 캔버스에 그려서 텍스처로 사용\n */\n protected buildTopTexture(w: number, h: number): THREE.MeshBasicMaterial {\n const scale = 4\n const cw = this.nextPow2(w * scale)\n const ch = this.nextPow2(h * scale)\n const canvas = document.createElement('canvas')\n canvas.width = cw\n canvas.height = ch\n const ctx = canvas.getContext('2d')!\n\n const statusColor = '#' + this.resolveColor().toString(16).padStart(6, '0')\n const emptyType = (this.component.state as any)?.EMPTYTYPE || ''\n const text = emptyType === 'FULL' ? 'F' : emptyType === 'EMPTY' ? 'E' : emptyType === 'EMPTYEMPTY' ? 'X' : ''\n\n // 실제 사용 영역 (nextPow2 이전 크기)\n const usedW = w * scale\n const usedH = h * scale\n\n // 바탕: 캐리어 상태 색상 (사용 영역만)\n ctx.fillStyle = statusColor\n ctx.fillRect(0, 0, usedW, usedH)\n\n // 텍스트 (사용 영역 중앙)\n if (text) {\n const fontSize = Math.round(Math.min(usedW, usedH) * 0.7)\n ctx.font = `bold ${fontSize}px Arial`\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n ctx.fillStyle = '#000000'\n ctx.fillText(text, usedW / 2, usedH / 2)\n }\n\n const texture = new THREE.CanvasTexture(canvas)\n texture.offset.set(0, 1 - usedH / ch)\n texture.repeat.set(usedW / cw, usedH / ch)\n texture.colorSpace = THREE.SRGBColorSpace\n\n return new THREE.MeshBasicMaterial({\n map: texture,\n transparent: true,\n side: THREE.DoubleSide,\n })\n }\n\n private nextPow2(n: number): number {\n if (!(n > 0)) return 1\n let v = Math.ceil(n)\n v--\n v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16\n return v + 1\n }\n\n /**\n * 자신의 mesh만 제거 후 rebuild.\n * 기본 update()는 clear()로 object3d의 모든 children을 제거하는데,\n * 컨테이너(Port 등)의 경우 자식 컴포넌트(Carrier 등)의 3D 오브젝트도 함께 제거됨.\n * 이를 방지하기 위해 자신이 생성한 mesh만 제거한다.\n */\n update() {\n // 자신의 mesh만 제거 (자식 컴포넌트 3D 오브젝트 보존)\n if (this._ownMesh) {\n this.object3d.remove(this._ownMesh)\n disposeObject3D(this._ownMesh)\n this._ownMesh = undefined\n }\n\n this.build()\n this.updateTransform()\n this.updateAlpha()\n this.updateHidden()\n }\n\n // RealObjectGroup 기본 동작 비활성화\n updateDimension() {}\n\n updateAlpha() {\n const { alpha = 1 } = this.component.state\n const configOpacity = this._config.opacity\n const effective = configOpacity * alpha\n\n this.object3d.traverse((o: any) => {\n if (!o.material) return\n const materials = Array.isArray(o.material) ? o.material : [o.material]\n for (const m of materials) {\n if (!m.visible) continue // openTop invisible face 무시\n if (m.map) continue // 텍스처 material은 자체 transparent 유지\n m.opacity = effective\n m.transparent = effective < 1\n }\n })\n }\n}\n\n// ── 팩토리 등록 헬퍼 ─────────────────────────────────────\n\nfunction register(type: string, overrides: Partial<MCS3DConfig> = {}) {\n const config: MCS3DConfig = { ...DEFAULTS, ...overrides }\n registerRealObjectFactory(type, (component: Component) => new MCSRealObject3D(component, config))\n}\n\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n// Machine (인프라 설비) — 높은 depth, 컨테이너는 반투명\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\nregister('Equipment', {\n defaultDepth: 3 * TRANSPORT_SURFACE_HEIGHT,\n opacity: 0.75,\n metalness: 0.4,\n roughness: 0.6,\n defaultColor: 0x8899aa,\n})\n\nregister('Buffer', {\n defaultDepth: TRANSPORT_SURFACE_HEIGHT,\n opacity: 1.0,\n metalness: 0.3,\n roughness: 0.7,\n defaultColor: 0x99aa88,\n shape: 'hexagon',\n})\n\nregister('AGVLine', {\n depthRatio: 0.12,\n metalness: 0.6,\n roughness: 0.3,\n defaultColor: 0x888899,\n})\n\nregister('OHTLine', {\n depthRatio: 0.12,\n metalness: 0.6,\n roughness: 0.3,\n defaultColor: 0x888899,\n})\n\n// STOCKER: 벽면에 용량 게이지 바를 포함하는 커스텀 3D 오브젝트\nconst STOCKER_CONFIG: MCS3DConfig = {\n ...DEFAULTS,\n defaultDepth: 5 * TRANSPORT_SURFACE_HEIGHT,\n opacity: 0.75,\n metalness: 0.3,\n roughness: 0.6,\n defaultColor: 0x8899bb,\n}\n\nclass StockerRealObject3D extends MCSRealObject3D {\n private gaugeMesh?: THREE.Mesh\n\n constructor(component: Component) {\n super(component, STOCKER_CONFIG)\n }\n\n build() {\n super.build()\n this.buildGauge()\n }\n\n private buildGauge() {\n const comp = this.component as any\n const data = comp.data || {}\n const gaugeMode = comp.root?.style?.stockerGaugeMode || 'capacity'\n\n const gauge = this.resolveGauge(data, gaugeMode)\n\n // 테두리는 스토커의 상태 색상 (machine status)\n const statusColor = comp.statusColor\n if (statusColor && statusColor.toUpperCase() !== '#F0F0F0') {\n gauge.borderColor = statusColor\n }\n\n const { w, h } = this.absSize\n const depth = this.effectiveDepth\n const isWidthLonger = w >= h\n\n // 게이지 캔버스 (고해상도)\n const barW = 130\n const barH = 26\n const scale = 4\n const canvasW = barW * scale\n const canvasH = barH * scale\n const canvas = document.createElement('canvas')\n canvas.width = canvasW\n canvas.height = canvasH\n const ctx = canvas.getContext('2d')!\n\n const pad = 12\n\n // 배경 + 테두리\n ctx.fillStyle = '#dddddd'\n ctx.fillRect(0, 0, canvasW, canvasH)\n ctx.strokeStyle = gauge.borderColor\n ctx.lineWidth = 12\n ctx.strokeRect(6, 6, canvasW - 12, canvasH - 12)\n\n // 세그먼트 채움 (왼→오)\n const innerW = canvasW - pad * 2\n const innerH = canvasH - pad * 2\n let x = pad\n for (const seg of gauge.segments) {\n const segW = Math.max(innerW * seg.ratio, seg.ratio > 0 ? 1 : 0)\n if (segW <= 0) continue\n ctx.fillStyle = seg.color\n ctx.fillRect(x, pad, segW, innerH)\n x += segW\n }\n\n // 텍스트\n ctx.font = `bold ${10 * scale}px sans-serif`\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n ctx.fillStyle = '#333333'\n ctx.fillText(gauge.label, canvasW / 2, canvasH / 2)\n\n // 텍스처 → Plane\n const texture = new THREE.CanvasTexture(canvas)\n texture.colorSpace = THREE.SRGBColorSpace\n\n const geo = new THREE.PlaneGeometry(barW, barH)\n geo.rotateX(-Math.PI / 2) // 수평 (지붕 위)\n if (!isWidthLonger) geo.rotateY(Math.PI / 2)\n\n const mat = new THREE.MeshBasicMaterial({\n map: texture,\n transparent: true,\n side: THREE.DoubleSide,\n })\n mat.polygonOffset = true\n mat.polygonOffsetFactor = -2\n mat.polygonOffsetUnit = -2\n\n this.gaugeMesh = new THREE.Mesh(geo, mat)\n this.gaugeMesh.position.set(0, depth + 0.5, 0)\n this.object3d.add(this.gaugeMesh)\n }\n\n private resolveGauge(data: any, mode: string) {\n switch (mode) {\n case 'carrier': {\n const full = Number(data.FULL_CNT) || 0\n const empty = Number(data.EMPTY_CNT) || 0\n const emptyEmpty = Number(data.EMPTYEMPTY_CNT) || 0\n const total = full + empty + emptyEmpty\n const segments = total > 0\n ? [\n { ratio: full / total, color: '#4AA7FE' },\n { ratio: empty / total, color: '#8BDA5B' },\n { ratio: emptyEmpty / total, color: '#019D59' },\n ]\n : [{ ratio: 1, color: '#dddddd' }]\n return {\n segments,\n borderColor: '#4AA7FE',\n label: total > 0 ? `F${full} E${empty} EE${emptyEmpty}` : '',\n }\n }\n case 'abnormal': {\n const normal = Number(data.CARRIER_NORMAL) || 0\n const abnormal = Number(data.CARRIER_ABNORMAL) || 0\n const total = normal + abnormal\n const segments = total > 0\n ? [\n { ratio: normal / total, color: '#8BDA5B' },\n { ratio: abnormal / total, color: '#F4B4B4' },\n ]\n : [{ ratio: 1, color: '#dddddd' }]\n return {\n segments,\n borderColor: abnormal > 0 ? '#F4B4B4' : '#8BDA5B',\n label: total > 0 ? `N${normal} A${abnormal}` : '',\n }\n }\n default: { // capacity\n const cur = Number(data.CURRENTCAPACITY) || 0\n const max = Number(data.MAXCAPACITY) || 100\n const fullup = data.FULLUP === 'T'\n const usage = Math.round((cur / max) * 100)\n const legend = (this.component as any).root?.style?.LEGEND_CAPACITY || LEGEND_CAPACITY\n const color = fullup ? 'red' : (getVaueOnRanges(usage, legend) || '#44aa44')\n return {\n segments: [{ ratio: usage / 100, color }],\n borderColor: color,\n label: `${usage}%`,\n }\n }\n }\n }\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n if ('data' in after) {\n this.clearGauge()\n this.buildGauge()\n }\n super.onchange(after, before)\n }\n\n clear() {\n this.clearGauge()\n return super.clear()\n }\n\n private clearGauge() {\n if (this.gaugeMesh) {\n this.object3d.remove(this.gaugeMesh)\n this.gaugeMesh.geometry?.dispose()\n const mat = this.gaugeMesh.material as THREE.MeshBasicMaterial\n mat?.map?.dispose()\n mat?.dispose()\n this.gaugeMesh = undefined\n }\n }\n}\n\nregisterRealObjectFactory('STOCKER', (component: Component) => new StockerRealObject3D(component))\n\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n// Unit (이동체 · 홀더) — 낮은 depth, 불투명\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n// Port: 바닥판 (PlaneGeometry)\nconst PORT_CONFIG: MCS3DConfig = {\n ...DEFAULTS,\n depthRatio: 0.01,\n defaultZPosFromParent: true,\n opacity: 1,\n metalness: 0.3,\n roughness: 0.8,\n defaultColor: 0xb0a090,\n shape: 'plane',\n}\nregisterRealObjectFactory('Port', (component: Component) => new MCSRealObject3D(component, PORT_CONFIG))\n\nregister('Shelf', {\n depthRatio: 0.25,\n metalness: 0.3,\n roughness: 0.7,\n defaultColor: 0xaabbcc,\n})\n\n// Carrier: CARRIERSTATUS에 따른 3D 애니메이션 지원\nconst CARRIER_CONFIG: MCS3DConfig = {\n ...DEFAULTS,\n depthRatio: 0.5,\n metalness: 0.2,\n roughness: 0.8,\n defaultColor: 0x66bb66,\n isVisible: (c: Component) => !!(c.state as any).id,\n sizeRatio: 0.8,\n texturedTop: true,\n emissiveIntensity: 0.4,\n}\n\nclass CarrierRealObject3D extends MCSRealObject3D {\n constructor(component: Component) {\n super(component, CARRIER_CONFIG)\n }\n}\n\nregisterRealObjectFactory('Carrier', (component: Component) => new CarrierRealObject3D(component))\n\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n// Gauge (용량 게이지) — 얇은 바\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n// Gauge (용량 게이지) — 2D 렌더링을 Plane 텍스처로 3D 표시\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n// Gauge 컴포넌트 (StockerCapacityBar, ZoneCapacityBar, MCSGaugeCapacityBar)는\n// 3D에서 표시하지 않음. 대신 부모(STOCKER 등)의 3D 모델에서 직접 게이지를 렌더링.\nregisterRealObjectFactory('StockerCapacityBar', () => null as any)\nregisterRealObjectFactory('MCSGaugeCapacityBar', () => null as any)\nregisterRealObjectFactory('ZoneCapacityBar', () => null as any)\n"]}
|
|
1
|
+
{"version":3,"file":"machine-3d.js","sourceRoot":"","sources":["../../src/factories/machine-3d.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCS 설비 컴포넌트 3D 팩토리\n *\n * 10,000+ 인스턴스를 위한 최소 폴리곤 설계:\n * - 컴포넌트당 단일 Mesh (draw call 최소화)\n * - BoxGeometry / ExtrudeGeometry(hexagon) 만 사용\n * - Machine: 높은 depth, 컨테이너는 반투명\n * - Unit: 낮은 depth, 불투명\n */\n\nimport * as THREE from 'three'\nimport { RealObjectGroup, registerRealObjectFactory, disposeObject3D } from '@hatiolab/things-scene'\nimport type { Component } from '@hatiolab/things-scene'\nimport { LEGEND_CAPACITY } from '../features/mcs-status-default'\nimport { getVaueOnRanges } from '../utils/get-value-on-ranges'\n\n// ── 설정 타입 ────────────────────────────────────────────\n\ninterface MCS3DConfig {\n /** state.depth 미설정 시 기본 depth.\n * defaultDepth > 0이면 절대값, 아니면 min(w,h) * depthRatio */\n depthRatio: number\n defaultDepth?: number\n /** true이면 syncZPosOffset = TRANSPORT_SURFACE_HEIGHT */\n defaultZPosFromParent?: boolean\n /** 1.0 = 불투명, 0.35 = 반투명 컨테이너 */\n opacity: number\n metalness: number\n roughness: number\n /** statusColor 미사용 시 기본 색상 */\n defaultColor: number\n /** 'box' | 'hexagon' */\n shape: 'box' | 'hexagon' | 'plane'\n /** mesh 생성 전 가시성 판정 — false 반환 시 mesh 미생성 */\n isVisible?: (component: Component) => boolean\n /** 부모 대비 크기 비율 (기본 1.0). < 1이면 부모 중심에 배치. */\n sizeRatio?: number\n /** 상부 면 제거 (5면 개방 박스) */\n openTop?: boolean\n /** 상판 무반사 (MeshBasicMaterial) */\n matteTop?: boolean\n /** 상판에 2D 렌더링 텍스처 적용 */\n texturedTop?: boolean\n /** 자체 발광 강도 (0~1). 조명 약한 면에서도 색상 유지 */\n emissiveIntensity?: number\n /** 바닥면 유지 (기본 false — 바닥면 제거) */\n keepBottomFace?: boolean\n}\n\n/**\n * 포트 기본 높이 (절대값).\n * 모든 이송장치의 상단 높이 = 이 값.\n * 캐리어가 이송장치 간 높이 차 없이 이동할 수 있는 기준 높이.\n */\nexport const TRANSPORT_SURFACE_HEIGHT = 30\n\nconst DEFAULTS: MCS3DConfig = {\n depthRatio: 0.5,\n opacity: 1.0,\n metalness: 0.3,\n roughness: 0.7,\n defaultColor: 0xaabbcc,\n shape: 'box',\n}\n\n// ── 3D 오브젝트 ──────────────────────────────────────────\n\nclass MCSRealObject3D extends RealObjectGroup {\n private _config: MCS3DConfig\n\n constructor(component: Component, config: MCS3DConfig) {\n super(component)\n this._config = config\n }\n\n // width, height 절대값 (음수 값은 양수로 취급)\n protected get absSize(): { w: number; h: number } {\n const { width = 10, height = 10 } = this.component.state\n return { w: Math.abs(width), h: Math.abs(height) }\n }\n\n get effectiveDepth(): number {\n const { depth } = this.component.state\n if (depth) return depth\n if (this._config.defaultDepth) return this._config.defaultDepth\n const { w, h } = this.absSize\n return Math.min(w, h) * this._config.depthRatio\n }\n\n protected get syncZPosOffset(): number {\n // Port: 이송 표면 높이에 배치\n if (this._config.defaultZPosFromParent) {\n return TRANSPORT_SURFACE_HEIGHT\n }\n // Carrier: Port 안이면 중앙, 그 외 컨테이너면 상단 위\n if (this._config.sizeRatio && this._config.sizeRatio < 1) {\n const parentType = this.component.parent?.state?.type\n if (parentType === 'Port' || parentType === 'Shelf' || parentType === 'OHT' || parentType === 'Shuttle') {\n return 0\n }\n return TRANSPORT_SURFACE_HEIGHT\n }\n return 0\n }\n\n // 컴포넌트의 상태 색상(statusColor) 또는 fillStyle → Three.js 색상 변환\n protected resolveColor(): number {\n const comp = this.component as any\n\n // 1) MCSStatusMixin.statusColor (legend 기반 상태 색상)\n // '#F0F0F0'은 상태 미설정 시 기본 fallback — 무시하고 defaultColor 사용\n try {\n const sc = comp.statusColor\n if (typeof sc === 'string' && sc && sc.toUpperCase() !== '#F0F0F0') return new THREE.Color(sc).getHex()\n } catch {\n /* statusColor 미구현 시 무시 */\n }\n\n // 2) state.fillStyle fallback\n const { fillStyle } = this.component.state\n if (fillStyle && typeof fillStyle === 'string') {\n try {\n return new THREE.Color(fillStyle).getHex()\n } catch {\n /* 파싱 실패 시 무시 */\n }\n }\n\n return this._config.defaultColor\n }\n\n // ── Geometry helpers ──\n\n /**\n * 바닥면(-Y 방향) 삼각형 제거: z-fighting 근본 해결.\n * 바닥면이 없으면 floor grid와 겹칠 면 자체가 없어진다.\n */\n private removeBottomFace(geometry: THREE.BufferGeometry): THREE.BufferGeometry {\n const posAttr = geometry.getAttribute('position')\n const normAttr = geometry.getAttribute('normal')\n const index = geometry.getIndex()\n\n if (!posAttr || !normAttr || !index) return geometry\n\n const newIndices: number[] = []\n const normalY = new THREE.Vector3()\n\n for (let i = 0; i < index.count; i += 3) {\n const a = index.getX(i)\n const b = index.getX(i + 1)\n const c = index.getX(i + 2)\n\n // 세 꼭짓점 노말의 Y 성분 평균으로 방향 판단\n const avgY = (normAttr.getY(a) + normAttr.getY(b) + normAttr.getY(c)) / 3\n\n // -Y 방향 삼각형 제거 (threshold -0.9: 거의 아래를 향하는 면만)\n if (avgY > -0.9) {\n newIndices.push(a, b, c)\n }\n }\n\n geometry.setIndex(newIndices)\n return geometry\n }\n\n // ── Geometry builders ──\n\n private buildBoxGeometry(w: number, d: number, h: number): THREE.BufferGeometry {\n const geo = new THREE.BoxGeometry(w, d, h)\n return this._config.keepBottomFace ? geo : this.removeBottomFace(geo)\n }\n\n private buildHexagonGeometry(w: number, d: number, h: number): THREE.BufferGeometry {\n // Buffer의 2D 형태: 좌우 끝이 꺾인 육각형\n const offset = Math.min(w, h) * 0.2\n const hw = w / 2\n const hh = h / 2\n\n const shape = new THREE.Shape()\n shape.moveTo(-hw + offset, -hh)\n shape.lineTo(hw - offset, -hh)\n shape.lineTo(hw, 0)\n shape.lineTo(hw - offset, hh)\n shape.lineTo(-hw + offset, hh)\n shape.lineTo(-hw, 0)\n shape.closePath()\n\n const geo = new THREE.ExtrudeGeometry(shape, {\n steps: 1,\n depth: d,\n bevelEnabled: false,\n })\n\n // 중심 정렬 후 Y-up 좌표계 회전 (extrude 축: +Z → +Y)\n geo.translate(0, 0, -d / 2)\n geo.rotateX(Math.PI / 2)\n\n return this.removeBottomFace(geo)\n }\n\n private buildPlaneGeometry(w: number, h: number): THREE.BufferGeometry {\n const geo = new THREE.PlaneGeometry(w, h)\n geo.rotateX(-Math.PI / 2)\n return geo\n }\n\n // ── Build ──\n\n protected _ownMesh?: THREE.Mesh\n\n build() {\n super.build()\n\n // 가시성 판정 — e.g., Carrier는 데이터 없으면 mesh 미생성\n if (this._config.isVisible && !this._config.isVisible(this.component)) return\n\n const { w: rawW, h: rawH } = this.absSize\n const rawDepth = this.effectiveDepth\n if (!rawW || !rawH) return\n\n const ratio = this._config.sizeRatio ?? 1.0\n const w = rawW * ratio\n const h = rawH * ratio\n const depth = rawDepth * ratio\n\n const color = this.resolveColor()\n const { opacity, metalness, roughness, shape } = this._config\n\n const geometry =\n shape === 'plane'\n ? this.buildPlaneGeometry(w, h)\n : shape === 'hexagon'\n ? this.buildHexagonGeometry(w, depth, h)\n : this.buildBoxGeometry(w, depth, h)\n\n const isPlane = shape === 'plane'\n const material = isPlane\n ? new THREE.MeshBasicMaterial({\n color,\n opacity,\n transparent: opacity < 1,\n side: THREE.DoubleSide,\n depthWrite: opacity >= 0.9,\n })\n : new THREE.MeshStandardMaterial({\n color,\n metalness,\n roughness,\n opacity,\n transparent: opacity < 1,\n side: opacity < 1 ? THREE.DoubleSide : THREE.FrontSide,\n depthWrite: opacity >= 0.9,\n ...(this._config.emissiveIntensity ? { emissive: color, emissiveIntensity: this._config.emissiveIntensity } : {}),\n })\n // z-fighting 방지: 바닥면(floor grid)보다 항상 앞에 렌더링\n material.polygonOffset = true\n material.polygonOffsetFactor = -1\n material.polygonOffsetUnit = -1\n\n // BoxGeometry material groups: +x(0), -x(1), +y(2), -y(3), +z(4), -z(5)\n let meshMaterial: THREE.Material | THREE.Material[] = material\n if (shape === 'box') {\n if (this._config.openTop) {\n // 상단면 제거 → 5면 개방 박스\n const invisible = new THREE.MeshBasicMaterial({ visible: false })\n meshMaterial = [material, material, invisible, material, material, material]\n } else if (this._config.texturedTop) {\n // 상판에 2D 렌더링 텍스처\n const topMat = this.buildTopTexture(w, h)\n meshMaterial = [material, material, topMat, material, material, material]\n } else if (this._config.matteTop) {\n // 상판만 무반사\n const matte = new THREE.MeshBasicMaterial({ color, opacity, transparent: opacity < 1 })\n meshMaterial = [material, material, matte, material, material, material]\n }\n }\n\n this._ownMesh = new THREE.Mesh(geometry, meshMaterial)\n // sizeRatio < 1이면 부모 중심에 배치 (rawDepth/2), plane은 살짝 띄움\n this._ownMesh.position.y = isPlane ? 1 : ratio < 1 ? rawDepth / 2 : depth / 2\n this._ownMesh.castShadow = !isPlane\n this._ownMesh.receiveShadow = true\n this.object3d.add(this._ownMesh)\n }\n\n // ── Change handling ──\n\n private _updatePending = false\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n if (\n 'width' in after ||\n 'height' in after ||\n 'depth' in after ||\n 'fillStyle' in after ||\n 'strokeStyle' in after ||\n 'id' in after ||\n 'EMPTYTYPE' in after ||\n 'CARRIERSTATUS' in after\n ) {\n // 연속 setState에 의한 다중 rebuild 방지: 한 프레임에 한 번만 실행\n if (!this._updatePending) {\n this._updatePending = true\n queueMicrotask(() => {\n this._updatePending = false\n this.update()\n })\n }\n return\n }\n\n super.onchange(after, before)\n }\n\n /**\n * 상판 텍스처: 컴포넌트의 2D render()를 캔버스에 그려서 텍스처로 사용\n */\n protected buildTopTexture(w: number, h: number): THREE.MeshBasicMaterial {\n const scale = 4\n const cw = this.nextPow2(w * scale)\n const ch = this.nextPow2(h * scale)\n const canvas = document.createElement('canvas')\n canvas.width = cw\n canvas.height = ch\n const ctx = canvas.getContext('2d')!\n\n const statusColor = '#' + this.resolveColor().toString(16).padStart(6, '0')\n const emptyType = (this.component.state as any)?.EMPTYTYPE || ''\n const text = emptyType === 'FULL' ? 'F' : emptyType === 'EMPTY' ? 'E' : emptyType === 'EMPTYEMPTY' ? 'X' : ''\n\n // 실제 사용 영역 (nextPow2 이전 크기)\n const usedW = w * scale\n const usedH = h * scale\n\n // 바탕: 캐리어 상태 색상 (사용 영역만)\n ctx.fillStyle = statusColor\n ctx.fillRect(0, 0, usedW, usedH)\n\n // 텍스트 (사용 영역 중앙)\n if (text) {\n const fontSize = Math.round(Math.min(usedW, usedH) * 0.7)\n ctx.font = `bold ${fontSize}px Arial`\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n ctx.fillStyle = '#000000'\n ctx.fillText(text, usedW / 2, usedH / 2)\n }\n\n const texture = new THREE.CanvasTexture(canvas)\n texture.offset.set(0, 1 - usedH / ch)\n texture.repeat.set(usedW / cw, usedH / ch)\n texture.colorSpace = THREE.SRGBColorSpace\n\n return new THREE.MeshBasicMaterial({\n map: texture,\n transparent: true,\n side: THREE.DoubleSide,\n })\n }\n\n private nextPow2(n: number): number {\n if (!(n > 0)) return 1\n let v = Math.ceil(n)\n v--\n v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16\n return v + 1\n }\n\n /**\n * 자신의 mesh만 제거 후 rebuild.\n * 기본 update()는 clear()로 object3d의 모든 children을 제거하는데,\n * 컨테이너(Port 등)의 경우 자식 컴포넌트(Carrier 등)의 3D 오브젝트도 함께 제거됨.\n * 이를 방지하기 위해 자신이 생성한 mesh만 제거한다.\n */\n update() {\n // 자신의 mesh만 제거 (자식 컴포넌트 3D 오브젝트 보존)\n if (this._ownMesh) {\n this.object3d.remove(this._ownMesh)\n disposeObject3D(this._ownMesh)\n this._ownMesh = undefined\n }\n\n this.build()\n this.updateTransform()\n this.updateAlpha()\n this.updateHidden()\n }\n\n // RealObjectGroup 기본 동작 비활성화\n updateDimension() {}\n\n updateAlpha() {\n const { alpha = 1 } = this.component.state\n const configOpacity = this._config.opacity\n const effective = configOpacity * alpha\n\n this.object3d.traverse((o: any) => {\n if (!o.material) return\n const materials = Array.isArray(o.material) ? o.material : [o.material]\n for (const m of materials) {\n if (!m.visible) continue // openTop invisible face 무시\n if (m.map) continue // 텍스처 material은 자체 transparent 유지\n m.opacity = effective\n m.transparent = effective < 1\n }\n })\n }\n}\n\n// ── 팩토리 등록 헬퍼 ─────────────────────────────────────\n\nfunction register(type: string, overrides: Partial<MCS3DConfig> = {}) {\n const config: MCS3DConfig = { ...DEFAULTS, ...overrides }\n registerRealObjectFactory(type, (component: Component) => new MCSRealObject3D(component, config))\n}\n\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n// Machine (인프라 설비) — 높은 depth, 컨테이너는 반투명\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\nregister('Equipment', {\n defaultDepth: 3 * TRANSPORT_SURFACE_HEIGHT,\n opacity: 0.75,\n metalness: 0.4,\n roughness: 0.6,\n defaultColor: 0x8899aa,\n})\n\nregister('Buffer', {\n defaultDepth: TRANSPORT_SURFACE_HEIGHT,\n opacity: 1.0,\n metalness: 0.3,\n roughness: 0.7,\n defaultColor: 0x99aa88,\n shape: 'hexagon',\n})\n\nregister('AGVLine', {\n depthRatio: 0.12,\n metalness: 0.6,\n roughness: 0.3,\n defaultColor: 0x888899,\n})\n\nregister('OHTLine', {\n depthRatio: 0.12,\n metalness: 0.6,\n roughness: 0.3,\n defaultColor: 0x888899,\n})\n\n// STOCKER: 벽면에 용량 게이지 바를 포함하는 커스텀 3D 오브젝트\nconst STOCKER_CONFIG: MCS3DConfig = {\n ...DEFAULTS,\n defaultDepth: 5 * TRANSPORT_SURFACE_HEIGHT,\n opacity: 0.75,\n metalness: 0.3,\n roughness: 0.6,\n defaultColor: 0x8899bb,\n}\n\nclass StockerRealObject3D extends MCSRealObject3D {\n private gaugeMesh?: THREE.Mesh\n\n constructor(component: Component) {\n super(component, STOCKER_CONFIG)\n }\n\n build() {\n super.build()\n this.buildGauge()\n }\n\n private buildGauge() {\n const comp = this.component as any\n const data = comp.data || {}\n const gaugeMode = comp.root?.style?.stockerGaugeMode || 'capacity'\n\n const gauge = this.resolveGauge(data, gaugeMode)\n\n // 테두리는 스토커의 상태 색상 (machine status)\n const statusColor = comp.statusColor\n if (statusColor && statusColor.toUpperCase() !== '#F0F0F0') {\n gauge.borderColor = statusColor\n }\n\n const { w, h } = this.absSize\n const depth = this.effectiveDepth\n const isWidthLonger = w >= h\n\n // 게이지 캔버스 (고해상도)\n const barW = 130\n const barH = 26\n const scale = 4\n const canvasW = barW * scale\n const canvasH = barH * scale\n const canvas = document.createElement('canvas')\n canvas.width = canvasW\n canvas.height = canvasH\n const ctx = canvas.getContext('2d')!\n\n const pad = 12\n\n // 배경 + 테두리\n ctx.fillStyle = '#dddddd'\n ctx.fillRect(0, 0, canvasW, canvasH)\n ctx.strokeStyle = gauge.borderColor\n ctx.lineWidth = 12\n ctx.strokeRect(6, 6, canvasW - 12, canvasH - 12)\n\n // 세그먼트 채움 (왼→오)\n const innerW = canvasW - pad * 2\n const innerH = canvasH - pad * 2\n let x = pad\n for (const seg of gauge.segments) {\n const segW = Math.max(innerW * seg.ratio, seg.ratio > 0 ? 1 : 0)\n if (segW <= 0) continue\n ctx.fillStyle = seg.color\n ctx.fillRect(x, pad, segW, innerH)\n x += segW\n }\n\n // 텍스트\n ctx.font = `bold ${10 * scale}px sans-serif`\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n ctx.fillStyle = '#333333'\n ctx.fillText(gauge.label, canvasW / 2, canvasH / 2)\n\n // 텍스처 → Plane\n const texture = new THREE.CanvasTexture(canvas)\n texture.colorSpace = THREE.SRGBColorSpace\n\n const geo = new THREE.PlaneGeometry(barW, barH)\n geo.rotateX(-Math.PI / 2) // 수평 (지붕 위)\n if (!isWidthLonger) geo.rotateY(Math.PI / 2)\n\n const mat = new THREE.MeshBasicMaterial({\n map: texture,\n transparent: true,\n side: THREE.DoubleSide,\n })\n mat.polygonOffset = true\n mat.polygonOffsetFactor = -2\n mat.polygonOffsetUnit = -2\n\n this.gaugeMesh = new THREE.Mesh(geo, mat)\n this.gaugeMesh.position.set(0, depth + 0.5, 0)\n this.object3d.add(this.gaugeMesh)\n }\n\n private resolveGauge(data: any, mode: string) {\n switch (mode) {\n case 'carrier': {\n const full = Number(data.FULL_CNT) || 0\n const empty = Number(data.EMPTY_CNT) || 0\n const emptyEmpty = Number(data.EMPTYEMPTY_CNT) || 0\n const total = full + empty + emptyEmpty\n const segments = total > 0\n ? [\n { ratio: full / total, color: '#4AA7FE' },\n { ratio: empty / total, color: '#8BDA5B' },\n { ratio: emptyEmpty / total, color: '#019D59' },\n ]\n : [{ ratio: 1, color: '#dddddd' }]\n return {\n segments,\n borderColor: '#4AA7FE',\n label: total > 0 ? `F${full} E${empty} EE${emptyEmpty}` : '',\n }\n }\n case 'abnormal': {\n const normal = Number(data.CARRIER_NORMAL) || 0\n const abnormal = Number(data.CARRIER_ABNORMAL) || 0\n const total = normal + abnormal\n const segments = total > 0\n ? [\n { ratio: normal / total, color: '#8BDA5B' },\n { ratio: abnormal / total, color: '#F4B4B4' },\n ]\n : [{ ratio: 1, color: '#dddddd' }]\n return {\n segments,\n borderColor: abnormal > 0 ? '#F4B4B4' : '#8BDA5B',\n label: total > 0 ? `N${normal} A${abnormal}` : '',\n }\n }\n default: { // capacity\n const cur = Number(data.CURRENTCAPACITY) || 0\n const max = Number(data.MAXCAPACITY) || 100\n const fullup = data.FULLUP === 'T'\n const usage = Math.round((cur / max) * 100)\n const legend = (this.component as any).root?.style?.LEGEND_CAPACITY || LEGEND_CAPACITY\n const color = fullup ? 'red' : (getVaueOnRanges(usage, legend) || '#44aa44')\n return {\n segments: [{ ratio: usage / 100, color }],\n borderColor: color,\n label: `${usage}%`,\n }\n }\n }\n }\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n if ('data' in after) {\n this.clearGauge()\n this.buildGauge()\n }\n super.onchange(after, before)\n }\n\n clear() {\n this.clearGauge()\n return super.clear()\n }\n\n private clearGauge() {\n if (this.gaugeMesh) {\n this.object3d.remove(this.gaugeMesh)\n this.gaugeMesh.geometry?.dispose()\n const mat = this.gaugeMesh.material as THREE.MeshBasicMaterial\n mat?.map?.dispose()\n mat?.dispose()\n this.gaugeMesh = undefined\n }\n }\n}\n\nregisterRealObjectFactory('STOCKER', (component: Component) => new StockerRealObject3D(component))\n\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n// Unit (이동체 · 홀더) — 낮은 depth, 불투명\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n// Port: 바닥판 (PlaneGeometry)\nconst PORT_CONFIG: MCS3DConfig = {\n ...DEFAULTS,\n depthRatio: 0.01,\n defaultZPosFromParent: true,\n opacity: 0.1,\n metalness: 0.3,\n roughness: 0.8,\n defaultColor: 0xb0a090,\n shape: 'plane',\n}\nregisterRealObjectFactory('Port', (component: Component) => new MCSRealObject3D(component, PORT_CONFIG))\n\nregister('Shelf', {\n depthRatio: 0.25,\n metalness: 0.3,\n roughness: 0.7,\n defaultColor: 0xaabbcc,\n})\n\n// Carrier: CARRIERSTATUS에 따른 3D 애니메이션 지원\nconst CARRIER_CONFIG: MCS3DConfig = {\n ...DEFAULTS,\n depthRatio: 0.5,\n metalness: 0,\n roughness: 1,\n defaultColor: 0x66bb66,\n isVisible: (c: Component) => !!(c.state as any).id,\n sizeRatio: 0.8,\n texturedTop: true,\n}\n\nclass CarrierRealObject3D extends MCSRealObject3D {\n constructor(component: Component) {\n super(component, CARRIER_CONFIG)\n }\n}\n\nregisterRealObjectFactory('Carrier', (component: Component) => new CarrierRealObject3D(component))\n\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n// Gauge (용량 게이지) — 얇은 바\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n// Gauge (용량 게이지) — 2D 렌더링을 Plane 텍스처로 3D 표시\n// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n// Gauge 컴포넌트 (StockerCapacityBar, ZoneCapacityBar, MCSGaugeCapacityBar)는\n// 3D에서 표시하지 않음. 대신 부모(STOCKER 등)의 3D 모델에서 직접 게이지를 렌더링.\nregisterRealObjectFactory('StockerCapacityBar', () => null as any)\nregisterRealObjectFactory('MCSGaugeCapacityBar', () => null as any)\nregisterRealObjectFactory('ZoneCapacityBar', () => null as any)\n"]}
|