@fmsim/machine 2.0.0-beta.3 → 2.0.0-beta.6
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/carrier.js +2 -2
- package/dist/carrier.js.map +1 -1
- package/dist/factories/agv-3d.js +33 -6
- package/dist/factories/agv-3d.js.map +1 -1
- package/dist/factories/machine-3d.js +395 -56
- package/dist/factories/machine-3d.js.map +1 -1
- package/dist/factories/oht-3d.js +34 -8
- package/dist/factories/oht-3d.js.map +1 -1
- package/dist/factories/shuttle-3d.js +32 -6
- package/dist/factories/shuttle-3d.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/carrier.ts +2 -2
- package/src/factories/agv-3d.ts +32 -6
- package/src/factories/machine-3d.ts +446 -40
- package/src/factories/oht-3d.ts +32 -8
- package/src/factories/shuttle-3d.ts +30 -6
package/dist/carrier.js
CHANGED
|
@@ -111,12 +111,12 @@ let Carrier = class Carrier extends MCSStatusMixin(ParentObjectMixin(Shape)) {
|
|
|
111
111
|
// 문자열 형태의 설정들을 미리 파싱
|
|
112
112
|
const parsedTheme = {};
|
|
113
113
|
for (const [status, config] of Object.entries(theme)) {
|
|
114
|
-
if (typeof config === 'string') {
|
|
114
|
+
if (typeof config === 'string' && config.trim()) {
|
|
115
115
|
try {
|
|
116
116
|
parsedTheme[status] = JSON5.parse(config);
|
|
117
117
|
}
|
|
118
118
|
catch (e) {
|
|
119
|
-
console.error('JSON5 parse error:', e);
|
|
119
|
+
console.error('JSON5 parse error:', e, 'input:', JSON.stringify(config), 'status:', status, 'theme:', carrierAnimationName);
|
|
120
120
|
parsedTheme[status] = config;
|
|
121
121
|
}
|
|
122
122
|
}
|
package/dist/carrier.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carrier.js","sourceRoot":"","sources":["../src/carrier.ts"],"names":[],"mappings":"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","sourcesContent":["import JSON5 from 'json5'\nimport { getPopupData } from '@fmsim/api'\n\nimport { BOUNDS, Component, ComponentNature, Properties, Shape, sceneComponent } from '@hatiolab/things-scene'\nimport { ANIMATION_DEFAULT, AnimationPreset, AnimationConfig } from './features/animation-default.js'\nimport { ParentObjectMixin } from './features/parent-object-mixin.js'\nimport { LEGEND_CARRIER, Legend } from './features/mcs-status-default.js'\nimport { MCSStatusMixin } from './features/mcs-status-mixin.js'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: false,\n rotatable: false\n}\n\n@sceneComponent('Carrier')\nexport default class Carrier extends MCSStatusMixin(ParentObjectMixin(Shape)) {\n static get nature() {\n return NATURE\n }\n\n get path() {\n if (!this.parent) {\n return []\n }\n\n const { left, top, width, height } = this.calculateShrunkRectangle(this.parent.bounds)\n\n return [\n { x: left, y: top },\n { x: left + width / 2, y: top },\n { x: left + width, y: top + height / 2 },\n { x: left + width, y: top + height },\n { x: left, y: top + height }\n ]\n }\n\n set path(path) {}\n\n onchangeData(after: Record<string, any>, before: Record<string, any>): void {\n const { CARRIERNAME, CARRIERTYPE = '', EMPTYTYPE, CARRIERSTATUS } = this.data || {}\n\n this.setState('id', CARRIERNAME)\n this.setState('EMPTYTYPE', EMPTYTYPE)\n this.setState('CARRIERTYPE', CARRIERTYPE)\n this.setState('CARRIERSTATUS', CARRIERSTATUS)\n\n // TODO carrierstatus에 따라서 매핑되는 애니메이션 테마 수행\n if (after.data.CARRIERSTATUS !== before.data?.CARRIERSTATUS) {\n const { CARRIERSTATUS: lastCarrierStatus } = before.data || {}\n const lastAnimationConfig = lastCarrierStatus && this.getAnimationConfig(lastCarrierStatus)\n\n if (lastAnimationConfig) {\n let { animation, decorator, border, arrow } = lastAnimationConfig\n if (animation) {\n this.resetAnimation()\n this.setState('animation', {\n oncreate: null\n })\n }\n\n if (decorator || border || arrow) {\n this.trigger('deco-off')\n }\n }\n\n const animationConfig = this.getAnimationConfig(this.getState('CARRIERSTATUS'))\n\n if (animationConfig) {\n let { animation, decorator, border, arrow } = animationConfig\n if (animation) {\n this.resetAnimation()\n this.setState('animation', {\n oncreate: animation\n })\n this.started = true\n }\n\n if (decorator) {\n this.trigger('deco-icon-off')\n this.trigger('deco-icon', decorator)\n }\n\n if (border) {\n this.trigger('deco-border-off')\n this.trigger('deco-border', border)\n }\n\n if (arrow) {\n this.trigger('deco-arrow-off')\n this.trigger('deco-arrow', arrow)\n }\n }\n }\n }\n\n get status() {\n return this.getState('EMPTYTYPE')\n }\n\n get legend(): Legend {\n const { carrierLegendName } = this.parent?.state || {}\n\n if (carrierLegendName) {\n return (this.root as any)?.style[carrierLegendName]\n }\n\n return (this.root as any)?.carrierLegendTheme || LEGEND_CARRIER\n }\n\n getAnimationConfig(carrierStatus): AnimationConfig | null {\n const config = this.animationPreset[carrierStatus || 'default']\n return (config as AnimationConfig) || null\n }\n\n get animationPreset(): AnimationPreset {\n const carrierAnimationName = this.parent?.state.carrierAnimationName || \n this.root?.rootModel.state.carrierAnimationName || ''\n\n if (carrierAnimationName) {\n // 캐시에서 먼저 확인\n if (!(this.root as any)._animationConfigCache) {\n (this.root as any)._animationConfigCache = new Map<string, AnimationPreset>()\n }\n\n const cached = (this.root as any)._animationConfigCache.get(carrierAnimationName)\n if (cached) {\n return cached\n }\n\n // 캐시에 없으면 파싱하고 저장\n const theme = (this.root as any)?.style[carrierAnimationName]\n if (theme) {\n // 문자열 형태의 설정들을 미리 파싱\n const parsedTheme = {}\n for (const [status, config] of Object.entries(theme)) {\n if (typeof config === 'string') {\n try {\n parsedTheme[status] = JSON5.parse(config)\n } catch (e) {\n console.error('JSON5 parse error:', e)\n parsedTheme[status] = config\n }\n } else {\n parsedTheme[status] = config\n }\n }\n \n ;(this.root as any)._animationConfigCache.set(carrierAnimationName, parsedTheme)\n return parsedTheme\n }\n \n return ANIMATION_DEFAULT\n } else {\n return ANIMATION_DEFAULT\n }\n }\n\n get hasTextProperty() {\n return this.getState('showText') || false\n }\n\n calculateShrunkRectangle(originalRect: BOUNDS): BOUNDS {\n const shrunkRect: BOUNDS = { ...originalRect }\n\n shrunkRect.left = originalRect.width * 0.1\n shrunkRect.width *= 0.8\n\n shrunkRect.top = originalRect.height * 0.1\n shrunkRect.height *= 0.8\n\n return shrunkRect\n }\n\n contains(x, y) {\n const { id: CARRIERNAME } = this.state || {}\n\n if (!CARRIERNAME) {\n return false\n }\n\n const rect = this.bounds\n x -= rect.left\n y -= rect.top\n\n if (x < 0 || y < 0 || x > rect.width || y > rect.height) {\n return false\n }\n\n // 윗변 중앙 좌표\n const topCenterX = rect.width / 2\n const topCenterY = 0\n\n // 오른쪽 변 중앙 좌표\n const rightCenterX = rect.width\n const rightCenterY = rect.height / 2\n\n // 기울기 m = (y2 - y1) / (x2 - x1)\n const m = (rightCenterY - topCenterY) / (rightCenterX - topCenterX)\n\n // y 절편 b = y - mx\n const b = topCenterY - m * topCenterX\n\n // 점(px, py)이 선 아래(좌하부)에 있는지 확인\n return y > m * x + b\n }\n\n render(ctx: CanvasRenderingContext2D) {\n const { EMPTYTYPE, id: CARRIERNAME, showText } = this.state\n\n if (!CARRIERNAME) {\n return\n }\n\n const { width, height } = this.bounds\n const path = this.path\n const round = Math.round(Math.min(width, height) * 0.1)\n const lineWidth = round > 5 ? 1 : 0.5\n\n ctx.beginPath()\n ctx.moveTo(path[0].x, path[0].y)\n\n path.slice(1).forEach(({ x, y }) => {\n ctx.lineTo(x, y)\n })\n\n ctx.closePath()\n\n ctx.lineWidth = lineWidth\n ctx.fillStyle = this.statusColor || 'transparent'\n ctx.strokeStyle = this.auxColor || 'transparent'\n\n ctx.fill()\n ctx.stroke()\n\n if (showText) {\n const text = EMPTYTYPE == 'FULL' ? 'F' : EMPTYTYPE == 'EMPTY' ? 'E' : EMPTYTYPE == 'EMPTYEMPTY' ? 'X' : ''\n\n if (text) {\n const { x: cx, y: cy } = this.center\n\n ctx.fillStyle = 'black'\n ctx.font = `normal ${Math.round(round * 8)}px Arial`\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n\n ctx.fillText(text, cx - width / 8, cy + height / 8)\n }\n }\n }\n\n async detailInfo() {\n const { type, id } = this.state\n\n if (!id) {\n return\n }\n\n return await getPopupData(type, id)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"carrier.js","sourceRoot":"","sources":["../src/carrier.ts"],"names":[],"mappings":"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","sourcesContent":["import JSON5 from 'json5'\nimport { getPopupData } from '@fmsim/api'\n\nimport { BOUNDS, Component, ComponentNature, Properties, Shape, sceneComponent } from '@hatiolab/things-scene'\nimport { ANIMATION_DEFAULT, AnimationPreset, AnimationConfig } from './features/animation-default.js'\nimport { ParentObjectMixin } from './features/parent-object-mixin.js'\nimport { LEGEND_CARRIER, Legend } from './features/mcs-status-default.js'\nimport { MCSStatusMixin } from './features/mcs-status-mixin.js'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: false,\n rotatable: false\n}\n\n@sceneComponent('Carrier')\nexport default class Carrier extends MCSStatusMixin(ParentObjectMixin(Shape)) {\n static get nature() {\n return NATURE\n }\n\n get path() {\n if (!this.parent) {\n return []\n }\n\n const { left, top, width, height } = this.calculateShrunkRectangle(this.parent.bounds)\n\n return [\n { x: left, y: top },\n { x: left + width / 2, y: top },\n { x: left + width, y: top + height / 2 },\n { x: left + width, y: top + height },\n { x: left, y: top + height }\n ]\n }\n\n set path(path) {}\n\n onchangeData(after: Record<string, any>, before: Record<string, any>): void {\n const { CARRIERNAME, CARRIERTYPE = '', EMPTYTYPE, CARRIERSTATUS } = this.data || {}\n\n this.setState('id', CARRIERNAME)\n this.setState('EMPTYTYPE', EMPTYTYPE)\n this.setState('CARRIERTYPE', CARRIERTYPE)\n this.setState('CARRIERSTATUS', CARRIERSTATUS)\n\n // TODO carrierstatus에 따라서 매핑되는 애니메이션 테마 수행\n if (after.data.CARRIERSTATUS !== before.data?.CARRIERSTATUS) {\n const { CARRIERSTATUS: lastCarrierStatus } = before.data || {}\n const lastAnimationConfig = lastCarrierStatus && this.getAnimationConfig(lastCarrierStatus)\n\n if (lastAnimationConfig) {\n let { animation, decorator, border, arrow } = lastAnimationConfig\n if (animation) {\n this.resetAnimation()\n this.setState('animation', {\n oncreate: null\n })\n }\n\n if (decorator || border || arrow) {\n this.trigger('deco-off')\n }\n }\n\n const animationConfig = this.getAnimationConfig(this.getState('CARRIERSTATUS'))\n\n if (animationConfig) {\n let { animation, decorator, border, arrow } = animationConfig\n if (animation) {\n this.resetAnimation()\n this.setState('animation', {\n oncreate: animation\n })\n this.started = true\n }\n\n if (decorator) {\n this.trigger('deco-icon-off')\n this.trigger('deco-icon', decorator)\n }\n\n if (border) {\n this.trigger('deco-border-off')\n this.trigger('deco-border', border)\n }\n\n if (arrow) {\n this.trigger('deco-arrow-off')\n this.trigger('deco-arrow', arrow)\n }\n }\n }\n }\n\n get status() {\n return this.getState('EMPTYTYPE')\n }\n\n get legend(): Legend {\n const { carrierLegendName } = this.parent?.state || {}\n\n if (carrierLegendName) {\n return (this.root as any)?.style[carrierLegendName]\n }\n\n return (this.root as any)?.carrierLegendTheme || LEGEND_CARRIER\n }\n\n getAnimationConfig(carrierStatus): AnimationConfig | null {\n const config = this.animationPreset[carrierStatus || 'default']\n return (config as AnimationConfig) || null\n }\n\n get animationPreset(): AnimationPreset {\n const carrierAnimationName = this.parent?.state.carrierAnimationName || \n this.root?.rootModel.state.carrierAnimationName || ''\n\n if (carrierAnimationName) {\n // 캐시에서 먼저 확인\n if (!(this.root as any)._animationConfigCache) {\n (this.root as any)._animationConfigCache = new Map<string, AnimationPreset>()\n }\n\n const cached = (this.root as any)._animationConfigCache.get(carrierAnimationName)\n if (cached) {\n return cached\n }\n\n // 캐시에 없으면 파싱하고 저장\n const theme = (this.root as any)?.style[carrierAnimationName]\n if (theme) {\n // 문자열 형태의 설정들을 미리 파싱\n const parsedTheme = {}\n for (const [status, config] of Object.entries(theme)) {\n if (typeof config === 'string' && config.trim()) {\n try {\n parsedTheme[status] = JSON5.parse(config)\n } catch (e) {\n console.error('JSON5 parse error:', e, 'input:', JSON.stringify(config), 'status:', status, 'theme:', carrierAnimationName)\n parsedTheme[status] = config\n }\n } else {\n parsedTheme[status] = config\n }\n }\n \n ;(this.root as any)._animationConfigCache.set(carrierAnimationName, parsedTheme)\n return parsedTheme\n }\n \n return ANIMATION_DEFAULT\n } else {\n return ANIMATION_DEFAULT\n }\n }\n\n get hasTextProperty() {\n return this.getState('showText') || false\n }\n\n calculateShrunkRectangle(originalRect: BOUNDS): BOUNDS {\n const shrunkRect: BOUNDS = { ...originalRect }\n\n shrunkRect.left = originalRect.width * 0.1\n shrunkRect.width *= 0.8\n\n shrunkRect.top = originalRect.height * 0.1\n shrunkRect.height *= 0.8\n\n return shrunkRect\n }\n\n contains(x, y) {\n const { id: CARRIERNAME } = this.state || {}\n\n if (!CARRIERNAME) {\n return false\n }\n\n const rect = this.bounds\n x -= rect.left\n y -= rect.top\n\n if (x < 0 || y < 0 || x > rect.width || y > rect.height) {\n return false\n }\n\n // 윗변 중앙 좌표\n const topCenterX = rect.width / 2\n const topCenterY = 0\n\n // 오른쪽 변 중앙 좌표\n const rightCenterX = rect.width\n const rightCenterY = rect.height / 2\n\n // 기울기 m = (y2 - y1) / (x2 - x1)\n const m = (rightCenterY - topCenterY) / (rightCenterX - topCenterX)\n\n // y 절편 b = y - mx\n const b = topCenterY - m * topCenterX\n\n // 점(px, py)이 선 아래(좌하부)에 있는지 확인\n return y > m * x + b\n }\n\n render(ctx: CanvasRenderingContext2D) {\n const { EMPTYTYPE, id: CARRIERNAME, showText } = this.state\n\n if (!CARRIERNAME) {\n return\n }\n\n const { width, height } = this.bounds\n const path = this.path\n const round = Math.round(Math.min(width, height) * 0.1)\n const lineWidth = round > 5 ? 1 : 0.5\n\n ctx.beginPath()\n ctx.moveTo(path[0].x, path[0].y)\n\n path.slice(1).forEach(({ x, y }) => {\n ctx.lineTo(x, y)\n })\n\n ctx.closePath()\n\n ctx.lineWidth = lineWidth\n ctx.fillStyle = this.statusColor || 'transparent'\n ctx.strokeStyle = this.auxColor || 'transparent'\n\n ctx.fill()\n ctx.stroke()\n\n if (showText) {\n const text = EMPTYTYPE == 'FULL' ? 'F' : EMPTYTYPE == 'EMPTY' ? 'E' : EMPTYTYPE == 'EMPTYEMPTY' ? 'X' : ''\n\n if (text) {\n const { x: cx, y: cy } = this.center\n\n ctx.fillStyle = 'black'\n ctx.font = `normal ${Math.round(round * 8)}px Arial`\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n\n ctx.fillText(text, cx - width / 8, cy + height / 8)\n }\n }\n }\n\n async detailInfo() {\n const { type, id } = this.state\n\n if (!id) {\n return\n }\n\n return await getPopupData(type, id)\n }\n}\n"]}
|
package/dist/factories/agv-3d.js
CHANGED
|
@@ -14,12 +14,16 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import * as THREE from 'three';
|
|
16
16
|
import { RoundedBoxGeometry } from 'three/examples/jsm/geometries/RoundedBoxGeometry.js';
|
|
17
|
-
import { RealObjectGroup, registerRealObjectFactory } from '@hatiolab/things-scene';
|
|
17
|
+
import { RealObjectGroup, registerRealObjectFactory, disposeObject3D } from '@hatiolab/things-scene';
|
|
18
18
|
import { TRANSPORT_SURFACE_HEIGHT } from './machine-3d.js';
|
|
19
19
|
const BUMPER_COLOR = 0x222222;
|
|
20
20
|
const PLATFORM_COLOR = 0x333333;
|
|
21
21
|
const DEFAULT_BODY_COLOR = 0x6688cc;
|
|
22
22
|
export class AGV3D extends RealObjectGroup {
|
|
23
|
+
constructor() {
|
|
24
|
+
super(...arguments);
|
|
25
|
+
this._ownMeshes = [];
|
|
26
|
+
}
|
|
23
27
|
get effectiveDepth() {
|
|
24
28
|
const { depth } = this.component.state;
|
|
25
29
|
return depth || TRANSPORT_SURFACE_HEIGHT;
|
|
@@ -78,7 +82,6 @@ export class AGV3D extends RealObjectGroup {
|
|
|
78
82
|
bumper.position.y = bumperH / 2;
|
|
79
83
|
bumper.castShadow = true;
|
|
80
84
|
bumper.receiveShadow = true;
|
|
81
|
-
this.object3d.add(bumper);
|
|
82
85
|
// ── 본체 (둥근 모서리, statusColor 적용) ──
|
|
83
86
|
const bodyColor = this.resolveColor();
|
|
84
87
|
const bodyGeo = new RoundedBoxGeometry(w, bodyH, h, 4, cornerR);
|
|
@@ -91,7 +94,6 @@ export class AGV3D extends RealObjectGroup {
|
|
|
91
94
|
body.position.y = bumperH + bodyH / 2;
|
|
92
95
|
body.castShadow = true;
|
|
93
96
|
body.receiveShadow = true;
|
|
94
|
-
this.object3d.add(body);
|
|
95
97
|
// ── 상단 플랫폼 (본체보다 안쪽, 어두운색) ──
|
|
96
98
|
const platInset = Math.min(w, h) * 0.04;
|
|
97
99
|
const platCornerR = Math.min(w - platInset * 2, h - platInset * 2, platH) * 0.15;
|
|
@@ -105,12 +107,37 @@ export class AGV3D extends RealObjectGroup {
|
|
|
105
107
|
plat.position.y = bumperH + bodyH + gapH + platH / 2;
|
|
106
108
|
plat.castShadow = true;
|
|
107
109
|
plat.receiveShadow = true;
|
|
108
|
-
this.
|
|
110
|
+
this._ownMeshes = [bumper, body, plat];
|
|
111
|
+
for (const m of this._ownMeshes)
|
|
112
|
+
this.object3d.add(m);
|
|
109
113
|
}
|
|
110
114
|
updateDimension() { }
|
|
111
|
-
|
|
115
|
+
update() {
|
|
116
|
+
// 자신의 mesh만 제거 (Carrier 등 자식 컴포넌트 3D 보존)
|
|
117
|
+
for (const m of this._ownMeshes) {
|
|
118
|
+
this.object3d.remove(m);
|
|
119
|
+
disposeObject3D(m);
|
|
120
|
+
}
|
|
121
|
+
this._ownMeshes = [];
|
|
122
|
+
this.build();
|
|
123
|
+
this.updateTransform();
|
|
124
|
+
this.updateAlpha();
|
|
125
|
+
this.updateHidden();
|
|
126
|
+
}
|
|
127
|
+
updateAlpha() {
|
|
128
|
+
const { alpha = 1 } = this.component.state;
|
|
129
|
+
for (const m of this._ownMeshes) {
|
|
130
|
+
const materials = Array.isArray(m.material) ? m.material : [m.material];
|
|
131
|
+
for (const mat of materials) {
|
|
132
|
+
;
|
|
133
|
+
mat.opacity = alpha;
|
|
134
|
+
mat.transparent = alpha < 1;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
112
138
|
onchange(after, before) {
|
|
113
|
-
if ('width' in after || 'height' in after || 'depth' in after ||
|
|
139
|
+
if ('width' in after || 'height' in after || 'depth' in after ||
|
|
140
|
+
'fillStyle' in after || 'strokeStyle' in after || 'id' in after) {
|
|
114
141
|
this.update();
|
|
115
142
|
return;
|
|
116
143
|
}
|
|
@@ -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 } 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 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 this.object3d.add(bumper)\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 this.object3d.add(body)\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 this.object3d.add(plat)\n }\n\n updateDimension() {}\n updateAlpha() {}\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n if ('width' in after || 'height' in after || 'depth' in after || 'fillStyle' in after || 'strokeStyle' in after) {\n this.update()\n return\n }\n super.onchange(after, before)\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 this.update()\n return\n }\n super.onchange(after, before)\n }\n}\n\nregisterRealObjectFactory('AGV', (component: Component) => new AGV3D(component))\n"]}
|