@fmsim/machine 1.0.87 → 2.0.0-beta.12

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.
Files changed (84) hide show
  1. package/dist/agv-line.js.map +1 -1
  2. package/dist/agv.js.map +1 -1
  3. package/dist/buffer.js.map +1 -1
  4. package/dist/carrier.js +7 -6
  5. package/dist/carrier.js.map +1 -1
  6. package/dist/conveyor-join.js.map +1 -1
  7. package/dist/conveyor.js +1 -1
  8. package/dist/conveyor.js.map +1 -1
  9. package/dist/crane-rail.js +53 -0
  10. package/dist/crane-rail.js.map +1 -0
  11. package/dist/crane.js.map +1 -1
  12. package/dist/equipment.js.map +1 -1
  13. package/dist/factories/agv-3d.js +148 -0
  14. package/dist/factories/agv-3d.js.map +1 -0
  15. package/dist/factories/conveyor-3d.js +258 -0
  16. package/dist/factories/conveyor-3d.js.map +1 -0
  17. package/dist/factories/crane-3d.js +150 -0
  18. package/dist/factories/crane-3d.js.map +1 -0
  19. package/dist/factories/crane-rail-3d.js +95 -0
  20. package/dist/factories/crane-rail-3d.js.map +1 -0
  21. package/dist/factories/machine-3d.js +627 -0
  22. package/dist/factories/machine-3d.js.map +1 -0
  23. package/dist/factories/oht-3d.js +177 -0
  24. package/dist/factories/oht-3d.js.map +1 -0
  25. package/dist/factories/shuttle-3d.js +162 -0
  26. package/dist/factories/shuttle-3d.js.map +1 -0
  27. package/dist/index.js +38 -0
  28. package/dist/index.js.map +1 -1
  29. package/dist/mcs-carrier-holder.js +6 -1
  30. package/dist/mcs-carrier-holder.js.map +1 -1
  31. package/dist/mcs-machine.js.map +1 -1
  32. package/dist/mcs-unit.js.map +1 -1
  33. package/dist/mcs-vehicle.js +2 -1
  34. package/dist/mcs-vehicle.js.map +1 -1
  35. package/dist/oht-line.js.map +1 -1
  36. package/dist/oht.js.map +1 -1
  37. package/dist/port-flow.js.map +1 -1
  38. package/dist/port.js.map +1 -1
  39. package/dist/scene/root-container-override.js.map +1 -1
  40. package/dist/shelf.js.map +1 -1
  41. package/dist/shuttle.js.map +1 -1
  42. package/dist/stocker-abnormal-bar.js +180 -0
  43. package/dist/stocker-abnormal-bar.js.map +1 -0
  44. package/dist/stocker-capacity-bar.js.map +1 -1
  45. package/dist/stocker-carrier-bar.js +194 -0
  46. package/dist/stocker-carrier-bar.js.map +1 -0
  47. package/dist/stocker.js +1 -1
  48. package/dist/stocker.js.map +1 -1
  49. package/dist/tsconfig.tsbuildinfo +1 -1
  50. package/dist/zone-capacity-bar.js.map +1 -1
  51. package/package.json +6 -6
  52. package/src/agv-line.ts +1 -1
  53. package/src/agv.ts +3 -3
  54. package/src/buffer.ts +1 -1
  55. package/src/carrier.ts +11 -11
  56. package/src/conveyor-join.ts +1 -1
  57. package/src/conveyor.ts +2 -2
  58. package/src/crane-rail.ts +58 -0
  59. package/src/crane.ts +1 -1
  60. package/src/equipment.ts +1 -1
  61. package/src/factories/agv-3d.ts +161 -0
  62. package/src/factories/conveyor-3d.ts +311 -0
  63. package/src/factories/crane-3d.ts +176 -0
  64. package/src/factories/crane-rail-3d.ts +114 -0
  65. package/src/factories/machine-3d.ts +767 -0
  66. package/src/factories/oht-3d.ts +196 -0
  67. package/src/factories/shuttle-3d.ts +183 -0
  68. package/src/index.ts +40 -0
  69. package/src/mcs-carrier-holder.ts +8 -2
  70. package/src/mcs-machine.ts +1 -1
  71. package/src/mcs-unit.ts +1 -1
  72. package/src/mcs-vehicle.ts +3 -3
  73. package/src/oht-line.ts +1 -1
  74. package/src/oht.ts +1 -1
  75. package/src/port-flow.ts +1 -1
  76. package/src/port.ts +1 -1
  77. package/src/scene/root-container-override.ts +2 -2
  78. package/src/shelf.ts +1 -1
  79. package/src/shuttle.ts +1 -1
  80. package/src/stocker-abnormal-bar.ts +242 -0
  81. package/src/stocker-capacity-bar.ts +3 -3
  82. package/src/stocker-carrier-bar.ts +257 -0
  83. package/src/stocker.ts +3 -3
  84. package/src/zone-capacity-bar.ts +2 -2
@@ -0,0 +1,196 @@
1
+ /**
2
+ * OHT (Overhead Hoist Transport) 3D Factory
3
+ *
4
+ * 천장 레일에 매달려 이동하는 반송 차량. 캐리어를 호이스트로 운반.
5
+ * 구조 (바닥 원점, y=0~depth):
6
+ * - 하단 그리퍼 바 (캐리어 집는 가로 바)
7
+ * - 호이스트 암 (좌우 수직 기둥)
8
+ * - 본체 하우징 (statusColor 적용)
9
+ * - 상단 트롤리 (납작+넓은 레일 클램프 + 좌우 바퀴)
10
+ */
11
+
12
+ import * as THREE from 'three'
13
+ import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js'
14
+ import { RoundedBoxGeometry } from 'three/examples/jsm/geometries/RoundedBoxGeometry.js'
15
+ import { RealObjectGroup, registerRealObjectFactory, disposeObject3D } from '@hatiolab/things-scene'
16
+ import type { Component } from '@hatiolab/things-scene'
17
+ import { TRANSPORT_SURFACE_HEIGHT } from './machine-3d.js'
18
+
19
+ const TROLLEY_COLOR = 0x222222
20
+ const FRAME_COLOR = 0x444444
21
+ const DEFAULT_BODY_COLOR = 0x6688cc
22
+
23
+ /** OHT 레일 높이: 스토커(5x) 위 */
24
+ const OHT_RAIL_HEIGHT = 6 * TRANSPORT_SURFACE_HEIGHT
25
+
26
+ export class OHT3D extends RealObjectGroup {
27
+ private _ownMeshes: THREE.Mesh[] = []
28
+ get effectiveDepth(): number {
29
+ const { depth } = this.component.state
30
+ return depth || TRANSPORT_SURFACE_HEIGHT
31
+ }
32
+
33
+ /** 천장 레일 높이에 배치 */
34
+ protected get syncZPosOffset(): number {
35
+ return OHT_RAIL_HEIGHT
36
+ }
37
+
38
+ private resolveColor(): number {
39
+ const comp = this.component as any
40
+
41
+ try {
42
+ const sc = comp.statusColor
43
+ if (typeof sc === 'string' && sc && sc.toUpperCase() !== '#F0F0F0') return new THREE.Color(sc).getHex()
44
+ } catch {
45
+ /* statusColor 미구현 시 무시 */
46
+ }
47
+
48
+ const { fillStyle } = this.component.state
49
+ if (fillStyle && typeof fillStyle === 'string') {
50
+ try {
51
+ return new THREE.Color(fillStyle).getHex()
52
+ } catch {
53
+ /* 파싱 실패 시 무시 */
54
+ }
55
+ }
56
+
57
+ return DEFAULT_BODY_COLOR
58
+ }
59
+
60
+ build() {
61
+ super.build()
62
+
63
+ const { width = 10, height = 10 } = this.component.state
64
+ const w = Math.abs(width)
65
+ const h = Math.abs(height)
66
+ const d = this.effectiveDepth
67
+ if (!w || !h) return
68
+
69
+ // 높이 배분: 그리퍼 8%, 호이스트암 22%, 본체 45%, 간격 5%, 트롤리 12%, 바퀴 8%
70
+ const gripperBarH = d * 0.08
71
+ const armH = d * 0.22
72
+ const bodyH = d * 0.45
73
+ const gap = d * 0.05
74
+ const trolleyH = d * 0.12
75
+ const wheelH = d * 0.08
76
+
77
+ const armThickness = Math.min(w, h) * 0.12
78
+ const bodyCornerR = Math.min(w, h, bodyH) * 0.1
79
+
80
+ const frameMat = new THREE.MeshStandardMaterial({
81
+ color: FRAME_COLOR,
82
+ roughness: 0.5,
83
+ metalness: 0.4,
84
+ })
85
+
86
+ // ── 1. 하단 그리퍼 바 (캐리어를 집는 가로 바) ──
87
+ const gripperBarW = w * 0.7
88
+ const gripperBarD = h * 0.15
89
+ const gripperGeo = new THREE.BoxGeometry(gripperBarW, gripperBarH, gripperBarD)
90
+ const gripperMesh = new THREE.Mesh(gripperGeo, frameMat)
91
+ gripperMesh.position.y = gripperBarH / 2
92
+ gripperMesh.castShadow = true
93
+
94
+ // ── 2. 호이스트 암 (좌우 수직 기둥 + 하단 가로연결) ──
95
+ const armBaseY = gripperBarH
96
+ const armGeometries: THREE.BufferGeometry[] = []
97
+
98
+ // 좌우 수직 기둥
99
+ for (const xSign of [-1, 1]) {
100
+ const pillar = new THREE.BoxGeometry(armThickness, armH, armThickness)
101
+ pillar.translate(xSign * (w * 0.3), armBaseY + armH / 2, 0)
102
+ armGeometries.push(pillar)
103
+ }
104
+
105
+ // 하단 가로 연결 바 (그리퍼와 암을 잇는 수평 바)
106
+ const crossBarW = w * 0.6 + armThickness
107
+ const crossBarH = armThickness * 0.6
108
+ const crossBar = new THREE.BoxGeometry(crossBarW, crossBarH, armThickness)
109
+ crossBar.translate(0, armBaseY + crossBarH / 2, 0)
110
+ armGeometries.push(crossBar)
111
+
112
+ const armMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(armGeometries), frameMat)
113
+ armMesh.castShadow = true
114
+
115
+ // ── 3. 본체 하우징 (statusColor 적용) ──
116
+ const bodyBaseY = armBaseY + armH
117
+ const bodyColor = this.resolveColor()
118
+ const bodyGeo = new RoundedBoxGeometry(w, bodyH, h, 4, bodyCornerR)
119
+ const bodyMat = new THREE.MeshStandardMaterial({
120
+ color: bodyColor,
121
+ roughness: 0.3,
122
+ metalness: 0.5,
123
+ })
124
+ const bodyMesh = new THREE.Mesh(bodyGeo, bodyMat)
125
+ bodyMesh.position.y = bodyBaseY + bodyH / 2
126
+ bodyMesh.castShadow = true
127
+ bodyMesh.receiveShadow = true
128
+
129
+ // ── 4. 상단 트롤리 플레이트 (납작하고 넓은 레일 클램프) ──
130
+ const trolleyBaseY = bodyBaseY + bodyH + gap
131
+ const trolleyW = w * 1.15
132
+ const trolleyD = h * 0.6
133
+ const trolleyGeo = new THREE.BoxGeometry(trolleyW, trolleyH, trolleyD)
134
+ const trolleyMat = new THREE.MeshStandardMaterial({
135
+ color: TROLLEY_COLOR,
136
+ roughness: 0.6,
137
+ metalness: 0.3,
138
+ })
139
+ const trolleyMesh = new THREE.Mesh(trolleyGeo, trolleyMat)
140
+ trolleyMesh.position.y = trolleyBaseY + trolleyH / 2
141
+ trolleyMesh.castShadow = true
142
+
143
+ // ── 5. 좌우 바퀴 (트롤리 위, 레일을 타는 원통형 바퀴) ──
144
+ const wheelBaseY = trolleyBaseY + trolleyH
145
+ const wheelRadius = wheelH / 2
146
+ const wheelDepth = h * 0.2
147
+ const wheelMeshes: THREE.Mesh[] = []
148
+ for (const xSign of [-1, 1]) {
149
+ const wheelGeo = new THREE.CylinderGeometry(wheelRadius, wheelRadius, wheelDepth, 12)
150
+ wheelGeo.rotateX(Math.PI / 2)
151
+ const wheelMesh = new THREE.Mesh(wheelGeo, trolleyMat)
152
+ wheelMesh.position.set(xSign * (trolleyW * 0.35), wheelBaseY + wheelRadius, 0)
153
+ wheelMesh.castShadow = true
154
+ wheelMeshes.push(wheelMesh)
155
+ }
156
+
157
+ this._ownMeshes = [gripperMesh, armMesh, bodyMesh, trolleyMesh, ...wheelMeshes]
158
+ for (const m of this._ownMeshes) this.object3d.add(m)
159
+ }
160
+
161
+ updateDimension() {}
162
+
163
+ update() {
164
+ for (const m of this._ownMeshes) {
165
+ this.object3d.remove(m)
166
+ disposeObject3D(m)
167
+ }
168
+ this._ownMeshes = []
169
+ this.build()
170
+ this.updateTransform()
171
+ this.updateAlpha()
172
+ this.updateHidden()
173
+ }
174
+
175
+ updateAlpha() {
176
+ const { alpha = 1 } = this.component.state
177
+ for (const m of this._ownMeshes) {
178
+ const materials = Array.isArray(m.material) ? m.material : [m.material]
179
+ for (const mat of materials) {
180
+ ;(mat as THREE.MeshStandardMaterial).opacity = alpha
181
+ ;(mat as THREE.MeshStandardMaterial).transparent = alpha < 1
182
+ }
183
+ }
184
+ }
185
+
186
+ onchange(after: Record<string, unknown>, before: Record<string, unknown>) {
187
+ if ('width' in after || 'height' in after || 'depth' in after ||
188
+ 'fillStyle' in after || 'strokeStyle' in after || 'id' in after) {
189
+ this.update()
190
+ return
191
+ }
192
+ super.onchange(after, before)
193
+ }
194
+ }
195
+
196
+ registerRealObjectFactory('OHT', (component: Component) => new OHT3D(component))
@@ -0,0 +1,183 @@
1
+ /**
2
+ * Shuttle 3D Factory
3
+ *
4
+ * 스토커 내부에서 캐리어를 선반↔포트 간 이송하는 포크 캐리지.
5
+ * 수평 레일 위를 이동하며, 포크를 밀어넣어 캐리어를 적재/하역.
6
+ *
7
+ * 구조 (바닥 원점, y=0~depth):
8
+ * - 하단 베이스 플레이트 (납작, 넓음, 레일 위 주행부)
9
+ * - 중앙 마스트 (좌우 수직 기둥, statusColor 적용)
10
+ * - 상단 포크 (2개의 평행한 가로 암, 캐리어 적재면)
11
+ */
12
+
13
+ import * as THREE from 'three'
14
+ import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js'
15
+ import { RealObjectGroup, registerRealObjectFactory, disposeObject3D } from '@hatiolab/things-scene'
16
+ import type { Component } from '@hatiolab/things-scene'
17
+ import { TRANSPORT_SURFACE_HEIGHT } from './machine-3d.js'
18
+
19
+ const BASE_COLOR = 0x333333
20
+ const FORK_COLOR = 0x777777
21
+ const DEFAULT_BODY_COLOR = 0x6688cc
22
+
23
+ export class Shuttle3D extends RealObjectGroup {
24
+ private _ownMeshes: THREE.Mesh[] = []
25
+ get effectiveDepth(): number {
26
+ const { depth } = this.component.state
27
+ return depth || TRANSPORT_SURFACE_HEIGHT
28
+ }
29
+
30
+ protected get syncZPosOffset(): number {
31
+ return 0
32
+ }
33
+
34
+ private resolveColor(): number {
35
+ const comp = this.component as any
36
+
37
+ try {
38
+ const sc = comp.statusColor
39
+ if (typeof sc === 'string' && sc && sc.toUpperCase() !== '#F0F0F0') return new THREE.Color(sc).getHex()
40
+ } catch {
41
+ /* statusColor 미구현 시 무시 */
42
+ }
43
+
44
+ const { fillStyle } = this.component.state
45
+ if (fillStyle && typeof fillStyle === 'string') {
46
+ try {
47
+ return new THREE.Color(fillStyle).getHex()
48
+ } catch {
49
+ /* 파싱 실패 시 무시 */
50
+ }
51
+ }
52
+
53
+ return DEFAULT_BODY_COLOR
54
+ }
55
+
56
+ build() {
57
+ super.build()
58
+
59
+ const { width = 10, height = 10 } = this.component.state
60
+ const w = Math.abs(width)
61
+ const h = Math.abs(height)
62
+ const d = this.effectiveDepth
63
+ if (!w || !h) return
64
+
65
+ // 높이 배분: 베이스 15%, 마스트 55%, 포크 30%
66
+ const baseH = d * 0.15
67
+ const mastH = d * 0.55
68
+ const forkH = d * 0.30
69
+
70
+ const mastThickness = Math.min(w, h) * 0.15
71
+
72
+ // ── 1. 하단 베이스 플레이트 (납작하고 넓은 주행부) ──
73
+ const basePad = Math.min(w, h) * 0.05
74
+ const baseGeo = new THREE.BoxGeometry(w + basePad * 2, baseH, h + basePad * 2)
75
+ const baseMat = new THREE.MeshStandardMaterial({
76
+ color: BASE_COLOR,
77
+ roughness: 0.7,
78
+ metalness: 0.3,
79
+ })
80
+ const baseMesh = new THREE.Mesh(baseGeo, baseMat)
81
+ baseMesh.position.y = baseH / 2
82
+ baseMesh.castShadow = true
83
+ baseMesh.receiveShadow = true
84
+
85
+ // ── 2. 좌우 마스트 기둥 (statusColor 적용) ──
86
+ const mastBaseY = baseH
87
+ const bodyColor = this.resolveColor()
88
+ const mastMat = new THREE.MeshStandardMaterial({
89
+ color: bodyColor,
90
+ roughness: 0.4,
91
+ metalness: 0.5,
92
+ })
93
+
94
+ const mastGeometries: THREE.BufferGeometry[] = []
95
+
96
+ // 좌우 수직 기둥
97
+ for (const xSign of [-1, 1]) {
98
+ const pillar = new THREE.BoxGeometry(mastThickness, mastH, mastThickness)
99
+ pillar.translate(xSign * (w / 2 - mastThickness / 2), mastBaseY + mastH / 2, 0)
100
+ mastGeometries.push(pillar)
101
+ }
102
+
103
+ // 중간 가로 연결 바 (구조 강성)
104
+ const crossBarW = w - mastThickness
105
+ const crossBarH = mastThickness * 0.5
106
+ const crossBar = new THREE.BoxGeometry(crossBarW, crossBarH, mastThickness)
107
+ crossBar.translate(0, mastBaseY + mastH * 0.4, 0)
108
+ mastGeometries.push(crossBar)
109
+
110
+ const mastMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(mastGeometries), mastMat)
111
+ mastMesh.castShadow = true
112
+
113
+ // ── 3. 상단 포크 (2개의 평행 암 + 백 플레이트) ──
114
+ const forkBaseY = mastBaseY + mastH
115
+ const forkMat = new THREE.MeshStandardMaterial({
116
+ color: FORK_COLOR,
117
+ roughness: 0.4,
118
+ metalness: 0.6,
119
+ })
120
+
121
+ const forkGeometries: THREE.BufferGeometry[] = []
122
+
123
+ // 백 플레이트 (마스트 상단을 잇는 가로판)
124
+ const backPlateH = forkH * 0.4
125
+ const backPlate = new THREE.BoxGeometry(w, backPlateH, mastThickness * 0.8)
126
+ backPlate.translate(0, forkBaseY + backPlateH / 2, -h * 0.35)
127
+ forkGeometries.push(backPlate)
128
+
129
+ // 2개의 포크 암 (앞으로 뻗은 평행 막대)
130
+ const forkArmW = mastThickness * 0.7
131
+ const forkArmH = forkH * 0.25
132
+ const forkArmD = h * 0.85
133
+ const forkSpacing = w * 0.55
134
+
135
+ for (const xSign of [-1, 1]) {
136
+ const arm = new THREE.BoxGeometry(forkArmW, forkArmH, forkArmD)
137
+ arm.translate(xSign * (forkSpacing / 2), forkBaseY + forkArmH / 2, forkArmD / 2 - h * 0.35)
138
+ forkGeometries.push(arm)
139
+ }
140
+
141
+ const forkMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(forkGeometries), forkMat)
142
+ forkMesh.castShadow = true
143
+
144
+ this._ownMeshes = [baseMesh, mastMesh, forkMesh]
145
+ for (const m of this._ownMeshes) this.object3d.add(m)
146
+ }
147
+
148
+ updateDimension() {}
149
+
150
+ update() {
151
+ for (const m of this._ownMeshes) {
152
+ this.object3d.remove(m)
153
+ disposeObject3D(m)
154
+ }
155
+ this._ownMeshes = []
156
+ this.build()
157
+ this.updateTransform()
158
+ this.updateAlpha()
159
+ this.updateHidden()
160
+ }
161
+
162
+ updateAlpha() {
163
+ const { alpha = 1 } = this.component.state
164
+ for (const m of this._ownMeshes) {
165
+ const materials = Array.isArray(m.material) ? m.material : [m.material]
166
+ for (const mat of materials) {
167
+ ;(mat as THREE.MeshStandardMaterial).opacity = alpha
168
+ ;(mat as THREE.MeshStandardMaterial).transparent = alpha < 1
169
+ }
170
+ }
171
+ }
172
+
173
+ onchange(after: Record<string, unknown>, before: Record<string, unknown>) {
174
+ if ('width' in after || 'height' in after || 'depth' in after ||
175
+ 'fillStyle' in after || 'strokeStyle' in after || 'id' in after) {
176
+ this.update()
177
+ return
178
+ }
179
+ super.onchange(after, before)
180
+ }
181
+ }
182
+
183
+ registerRealObjectFactory('Shuttle', (component: Component) => new Shuttle3D(component))
package/src/index.ts CHANGED
@@ -1,5 +1,42 @@
1
+ // ── side-effect: scene override ──
1
2
  import './scene/root-container-override.js'
2
3
 
4
+ // ── side-effect: 3D factories ──
5
+ import './factories/machine-3d.js'
6
+ import './factories/conveyor-3d.js'
7
+ import './factories/agv-3d.js'
8
+ import './factories/oht-3d.js'
9
+ import './factories/shuttle-3d.js'
10
+ import './factories/crane-3d.js'
11
+ import './factories/crane-rail-3d.js'
12
+
13
+ // ── side-effect: @sceneComponent 등록 (tree-shaking 방지) ──
14
+ import './zone-capacity-bar.js'
15
+ import './stocker-capacity-bar.js'
16
+ import './stocker-carrier-bar.js'
17
+ import './stocker-abnormal-bar.js'
18
+ import './port-flow.js'
19
+ import './agv-line.js'
20
+ import './buffer.js'
21
+ import './conveyor.js'
22
+ import './conveyor-join.js'
23
+ import './equipment.js'
24
+ import './oht-line.js'
25
+ import './stocker.js'
26
+ import './crane-rail.js'
27
+ import './agv.js'
28
+ import './oht.js'
29
+ import './shuttle.js'
30
+ import './port.js'
31
+ import './crane.js'
32
+ import './shelf.js'
33
+ import './carrier.js'
34
+ import './node.js'
35
+ import './node-path.js'
36
+ import './floating-container.js'
37
+ import './static-container.js'
38
+ import './clickable-popup.js'
39
+
3
40
  export { default as MachineGroups } from './groups'
4
41
 
5
42
  export { default as MCSMachine } from './mcs-machine'
@@ -9,6 +46,8 @@ export { default as MCSVehicle } from './mcs-vehicle'
9
46
  export { default as MCSTransport } from './mcs-transport'
10
47
  export { default as ZoneCapacityBar } from './zone-capacity-bar'
11
48
  export { default as StockerCapacityBar } from './stocker-capacity-bar'
49
+ export { default as StockerCarrierBar } from './stocker-carrier-bar'
50
+ export { default as StockerAbnormalBar } from './stocker-abnormal-bar'
12
51
  export { default as PortFlow } from './port-flow'
13
52
 
14
53
  export { default as AGVLine } from './agv-line'
@@ -18,6 +57,7 @@ export { default as ConveyorJoin } from './conveyor-join'
18
57
  export { default as Equipment } from './equipment'
19
58
  export { default as OHTLine } from './oht-line'
20
59
  export { default as Stocker } from './stocker'
60
+ export { default as CraneRail } from './crane-rail'
21
61
 
22
62
  export { default as AGV } from './agv'
23
63
  export { default as OHT } from './oht'
@@ -33,16 +33,22 @@ export default class MCSCarrierHolder extends MCSUnit {
33
33
 
34
34
  carrier?: Carrier | null
35
35
 
36
- ready() {
36
+ async ready() {
37
37
  super.ready()
38
38
 
39
39
  for (let component of this.components) {
40
40
  this.removeComponent(component)
41
41
  }
42
42
 
43
+ const { width, height } = this.state
44
+
43
45
  this.carrier = Model.compile(
44
46
  {
45
47
  type: 'Carrier',
48
+ left: 0,
49
+ top: 0,
50
+ width,
51
+ height,
46
52
  showText: this.getState('showCarrierText') || false
47
53
  },
48
54
  this.root.app
@@ -66,7 +72,7 @@ export default class MCSCarrierHolder extends MCSUnit {
66
72
  }
67
73
  }
68
74
 
69
- onchangeData(after: Properties, before: Properties): void {
75
+ onchangeData(after: Record<string, any>, before: Record<string, any>): void {
70
76
  if (this.carrier) {
71
77
  this.carrier.data = this.data
72
78
  }
@@ -38,7 +38,7 @@ export default class MCSMachine extends MCSStatusMixin(ContainerAbstract) {
38
38
  const { legendName } = this.state
39
39
 
40
40
  if (legendName) {
41
- return this.root?.style?.[legendName]
41
+ return (this.root as any)?.style?.[legendName]
42
42
  }
43
43
  }
44
44
 
package/src/mcs-unit.ts CHANGED
@@ -25,7 +25,7 @@ export default class MCSUnit extends MCSStatusMixin(ParentObjectMixin(ContainerA
25
25
  const { legendName } = this.state
26
26
 
27
27
  if (legendName) {
28
- return this.root?.style?.[legendName]
28
+ return (this.root as any)?.style?.[legendName]
29
29
  }
30
30
  }
31
31
 
@@ -10,7 +10,7 @@ function findNode(vehicle: MCSVehicle, nodeId: string, nodeMachine: string) {
10
10
  return null
11
11
  }
12
12
 
13
- const nodes = vehicle.root.findAllById(nodeId).filter(node => node.state.type == 'Node') as Node[]
13
+ const nodes = (vehicle.root.findAllById?.(nodeId) || []).filter(node => node.state.type == 'Node') as Node[]
14
14
 
15
15
  return nodes.find((node: Node) => {
16
16
  return node.nodeMachine === nodeMachine
@@ -94,7 +94,7 @@ export default class MCSVehicle extends MCSCarrierHolder {
94
94
  // this.renderDirection(ctx)
95
95
  }
96
96
 
97
- onchangeData(after: Properties, before: Properties): void {
97
+ onchangeData(after: Record<string, any>, before: Record<string, any>): void {
98
98
  super.onchangeData(after, before)
99
99
 
100
100
  const { NODEID: beforeNodeId, NODEMACHINE: beforeNodeMachine } = before.data || {}
@@ -122,7 +122,7 @@ export default class MCSVehicle extends MCSCarrierHolder {
122
122
  // 실제 존재하는 노드 중 가장 최근에 이동한 노드
123
123
  this.lastWaypoint = { NodeId, NodeMachine }
124
124
 
125
- if (this.root.vehicleAnimation) {
125
+ if ((this.root as any).vehicleAnimation) {
126
126
  this.trigger('waypoint', {
127
127
  from: beforeNode,
128
128
  to: afterNode,
package/src/oht-line.ts CHANGED
@@ -19,7 +19,7 @@ export default class OHTLine extends MCSTransport {
19
19
  }
20
20
 
21
21
  getLegendFallback() {
22
- return this.root.ohtlineLegendTheme || super.getLegendFallback()
22
+ return (this.root as any).ohtlineLegendTheme || super.getLegendFallback()
23
23
  }
24
24
 
25
25
  containable(component: Component) {
package/src/oht.ts CHANGED
@@ -21,7 +21,7 @@ export default class OHT extends MCSVehicle {
21
21
  }
22
22
 
23
23
  getLegendFallback() {
24
- return this.root.ohtLegendTheme || super.getLegendFallback()
24
+ return (this.root as any).ohtLegendTheme || super.getLegendFallback()
25
25
  }
26
26
 
27
27
  render(ctx: CanvasRenderingContext2D) {
package/src/port-flow.ts CHANGED
@@ -232,7 +232,7 @@ export default class PortFlow extends ParentObjectMixin(RectPath(Shape)) {
232
232
  this.drawStroke(ctx)
233
233
  }
234
234
 
235
- onchangeData(after: Properties, before: Properties): void {
235
+ onchangeData(after: Record<string, any>, before: Record<string, any>): void {
236
236
  const { INOUTTYPE } = after.data
237
237
 
238
238
  this.setState('direction', INOUTTYPE)
package/src/port.ts CHANGED
@@ -20,7 +20,7 @@ export default class Port extends MCSZoneMixin(MCSCarrierHolder) {
20
20
  }
21
21
 
22
22
  getLegendFallback() {
23
- return this.root.portLegendTheme || super.getLegendFallback()
23
+ return (this.root as any).portLegendTheme || super.getLegendFallback()
24
24
  }
25
25
 
26
26
  render(ctx: CanvasRenderingContext2D) {
@@ -22,14 +22,14 @@ declare module '@hatiolab/things-scene' {
22
22
  craneLegendTheme?: any
23
23
  shelfLegendTheme?: any
24
24
  equipmentLegendTheme?: any
25
- style: { [key: string]: any | Legend }
25
+ style: any
26
26
  vehicleAnimation?: boolean
27
27
  // 캐시 관련 속성 추가
28
28
  _animationConfigCache?: Map<string, any>
29
29
  }
30
30
  }
31
31
 
32
- const ModelLayer = Component.register('model-layer') as any
32
+ const ModelLayer = (Component as any).register('model-layer') as any
33
33
 
34
34
  Object.defineProperty(ModelLayer.prototype, 'nature', {
35
35
  get: function () {
package/src/shelf.ts CHANGED
@@ -20,7 +20,7 @@ export default class Shelf extends MCSZoneMixin(MCSCarrierHolder) {
20
20
  }
21
21
 
22
22
  getLegendFallback() {
23
- return this.root.shelfLegendTheme || super.getLegendFallback()
23
+ return (this.root as any).shelfLegendTheme || super.getLegendFallback()
24
24
  }
25
25
 
26
26
  render(ctx: CanvasRenderingContext2D) {
package/src/shuttle.ts CHANGED
@@ -20,7 +20,7 @@ export default class Shuttle extends MCSVehicle {
20
20
  }
21
21
 
22
22
  getLegendFallback() {
23
- return this.root.shuttleLegendTheme || super.getLegendFallback()
23
+ return (this.root as any).shuttleLegendTheme || super.getLegendFallback()
24
24
  }
25
25
 
26
26
  render(ctx: CanvasRenderingContext2D) {