@fmsim/machine 2.0.0-beta.10 → 2.0.0-beta.101

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/dist/agv.js +6 -2
  2. package/dist/agv.js.map +1 -1
  3. package/dist/carrier-manager.js +183 -0
  4. package/dist/carrier-manager.js.map +1 -0
  5. package/dist/carrier.js +99 -9
  6. package/dist/carrier.js.map +1 -1
  7. package/dist/conveyor-join.js +8 -2
  8. package/dist/conveyor-join.js.map +1 -1
  9. package/dist/conveyor.js +8 -0
  10. package/dist/conveyor.js.map +1 -1
  11. package/dist/crane.js +144 -1
  12. package/dist/crane.js.map +1 -1
  13. package/dist/factories/agv-3d.js +17 -36
  14. package/dist/factories/agv-3d.js.map +1 -1
  15. package/dist/factories/conveyor-3d.js +179 -100
  16. package/dist/factories/conveyor-3d.js.map +1 -1
  17. package/dist/factories/crane-3d.js +56 -29
  18. package/dist/factories/crane-3d.js.map +1 -1
  19. package/dist/factories/crane-rail-3d.js +14 -18
  20. package/dist/factories/crane-rail-3d.js.map +1 -1
  21. package/dist/factories/machine-3d.js +533 -197
  22. package/dist/factories/machine-3d.js.map +1 -1
  23. package/dist/factories/oht-3d.js +29 -47
  24. package/dist/factories/oht-3d.js.map +1 -1
  25. package/dist/factories/shuttle-3d.js +13 -32
  26. package/dist/factories/shuttle-3d.js.map +1 -1
  27. package/dist/factories/z-priority-defaults.js +33 -0
  28. package/dist/factories/z-priority-defaults.js.map +1 -0
  29. package/dist/factories/z-priority.js +54 -0
  30. package/dist/factories/z-priority.js.map +1 -0
  31. package/dist/features/conveyor-mixin.js.map +1 -1
  32. package/dist/features/mcs-status-default.js +15 -1
  33. package/dist/features/mcs-status-default.js.map +1 -1
  34. package/dist/features/mcs-status-mixin.js +22 -0
  35. package/dist/features/mcs-status-mixin.js.map +1 -1
  36. package/dist/features/mcs-zone-mixin.js.map +1 -1
  37. package/dist/features/parent-object-mixin.js +15 -7
  38. package/dist/features/parent-object-mixin.js.map +1 -1
  39. package/dist/floating-container.js +5 -0
  40. package/dist/floating-container.js.map +1 -1
  41. package/dist/index.js +52 -34
  42. package/dist/index.js.map +1 -1
  43. package/dist/mcs-carrier-holder.js +56 -22
  44. package/dist/mcs-carrier-holder.js.map +1 -1
  45. package/dist/mcs-machine.js +20 -0
  46. package/dist/mcs-machine.js.map +1 -1
  47. package/dist/mcs-unit.js +17 -0
  48. package/dist/mcs-unit.js.map +1 -1
  49. package/dist/mcs-vehicle.js +8 -3
  50. package/dist/mcs-vehicle.js.map +1 -1
  51. package/dist/node.js +10 -3
  52. package/dist/node.js.map +1 -1
  53. package/dist/oht.js +4 -0
  54. package/dist/oht.js.map +1 -1
  55. package/dist/port-flow.js +4 -0
  56. package/dist/port-flow.js.map +1 -1
  57. package/dist/port.js +4 -0
  58. package/dist/port.js.map +1 -1
  59. package/dist/scanner.js +30 -0
  60. package/dist/scanner.js.map +1 -0
  61. package/dist/scene/root-container-override.js +160 -96
  62. package/dist/scene/root-container-override.js.map +1 -1
  63. package/dist/shelf.js +4 -0
  64. package/dist/shelf.js.map +1 -1
  65. package/dist/static-container.js +5 -0
  66. package/dist/static-container.js.map +1 -1
  67. package/dist/stocker-abnormal-bar.js +5 -1
  68. package/dist/stocker-abnormal-bar.js.map +1 -1
  69. package/dist/stocker-capacity-bar.js +253 -6
  70. package/dist/stocker-capacity-bar.js.map +1 -1
  71. package/dist/stocker-carrier-bar.js +5 -1
  72. package/dist/stocker-carrier-bar.js.map +1 -1
  73. package/dist/stocker.js +6 -0
  74. package/dist/stocker.js.map +1 -1
  75. package/dist/templates/backdrop.js +30 -0
  76. package/dist/templates/backdrop.js.map +1 -0
  77. package/dist/templates/decal.js +21 -0
  78. package/dist/templates/decal.js.map +1 -0
  79. package/dist/templates/index.js +7 -1
  80. package/dist/templates/index.js.map +1 -1
  81. package/dist/templates/scanner.js +20 -0
  82. package/dist/templates/scanner.js.map +1 -0
  83. package/dist/tsconfig.tsbuildinfo +1 -1
  84. package/dist/utils/crane-position.js +83 -0
  85. package/dist/utils/crane-position.js.map +1 -0
  86. package/dist/utils/data-value.js +21 -0
  87. package/dist/utils/data-value.js.map +1 -0
  88. package/dist/utils/fit-gauge-scale.js +28 -0
  89. package/dist/utils/fit-gauge-scale.js.map +1 -0
  90. package/dist/utils/get-value-on-ranges.js +2 -4
  91. package/dist/utils/get-value-on-ranges.js.map +1 -1
  92. package/dist/utils/stocker-gauge.js +78 -0
  93. package/dist/utils/stocker-gauge.js.map +1 -0
  94. package/dist/zone-capacity-bar.js +3 -3
  95. package/dist/zone-capacity-bar.js.map +1 -1
  96. package/icons/backdrop.png +0 -0
  97. package/icons/decal.png +0 -0
  98. package/jest.config.js +10 -0
  99. package/package.json +4 -3
  100. package/src/agv.ts +7 -2
  101. package/src/carrier-manager.ts +223 -0
  102. package/src/carrier.ts +103 -10
  103. package/src/conveyor-join.ts +5 -2
  104. package/src/conveyor.ts +8 -0
  105. package/src/crane.ts +181 -1
  106. package/src/factories/agv-3d.ts +19 -36
  107. package/src/factories/conveyor-3d.ts +183 -103
  108. package/src/factories/crane-3d.ts +62 -29
  109. package/src/factories/crane-rail-3d.ts +17 -20
  110. package/src/factories/machine-3d.ts +631 -205
  111. package/src/factories/oht-3d.ts +30 -46
  112. package/src/factories/shuttle-3d.ts +14 -32
  113. package/src/factories/z-priority-defaults.ts +38 -0
  114. package/src/factories/z-priority.ts +60 -0
  115. package/src/features/conveyor-mixin.ts +1 -1
  116. package/src/features/mcs-status-default.ts +15 -1
  117. package/src/features/mcs-status-mixin.ts +26 -4
  118. package/src/features/mcs-zone-mixin.ts +1 -1
  119. package/src/features/parent-object-mixin.ts +17 -8
  120. package/src/floating-container.ts +5 -0
  121. package/src/index.ts +58 -34
  122. package/src/mcs-carrier-holder.ts +57 -34
  123. package/src/mcs-machine.ts +23 -0
  124. package/src/mcs-unit.ts +21 -1
  125. package/src/mcs-vehicle.ts +9 -6
  126. package/src/node.ts +9 -3
  127. package/src/oht.ts +6 -1
  128. package/src/port-flow.ts +5 -0
  129. package/src/port.ts +5 -0
  130. package/src/scanner.ts +29 -0
  131. package/src/scene/root-container-override.ts +154 -103
  132. package/src/shelf.ts +5 -0
  133. package/src/static-container.ts +5 -0
  134. package/src/stocker-abnormal-bar.ts +6 -1
  135. package/src/stocker-capacity-bar.ts +298 -7
  136. package/src/stocker-carrier-bar.ts +6 -1
  137. package/src/stocker.ts +7 -0
  138. package/src/templates/backdrop.ts +30 -0
  139. package/src/templates/decal.ts +21 -0
  140. package/src/templates/index.ts +7 -1
  141. package/src/templates/scanner.ts +20 -0
  142. package/src/utils/crane-position.ts +105 -0
  143. package/src/utils/data-value.ts +19 -0
  144. package/src/utils/fit-gauge-scale.ts +35 -0
  145. package/src/utils/get-value-on-ranges.ts +2 -4
  146. package/src/utils/stocker-gauge.ts +111 -0
  147. package/src/zone-capacity-bar.ts +3 -3
  148. package/translations/en.json +26 -1
  149. package/translations/ja.json +26 -1
  150. package/translations/ko.json +26 -1
  151. package/translations/ms.json +26 -1
  152. package/translations/zh.json +26 -1
@@ -13,7 +13,7 @@
13
13
 
14
14
  import * as THREE from 'three'
15
15
  import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js'
16
- import { RealObjectGroup, registerRealObjectFactory } from '@hatiolab/things-scene'
16
+ import { RealObjectGroup, registerRealObjectFactory, MaterialBank } from '@hatiolab/things-scene'
17
17
  import type { Component } from '@hatiolab/things-scene'
18
18
  import { TRANSPORT_SURFACE_HEIGHT } from './machine-3d.js'
19
19
 
@@ -22,13 +22,27 @@ const FORK_COLOR = 0x999999
22
22
  const DEFAULT_BODY_COLOR = 0xcc8844
23
23
 
24
24
  export class Crane3D extends RealObjectGroup {
25
+ /** 캐리지 포크 group — Crane.state.forkZ (0~100) 가 변하면 position.y 만 lerp.
26
+ * build() 시 inner 에 add 되고, *_mastBaseY 와 mastH 를 함께 보관* 해서
27
+ * setForkZ 가 비율 계산에 사용. */
28
+ private forkGroup?: THREE.Group
29
+ private forkMastBaseY = 0
30
+ private forkMastH = 0
31
+
25
32
  get effectiveDepth(): number {
26
33
  const { depth } = this.component.state
27
34
  return depth || 5 * TRANSPORT_SURFACE_HEIGHT - 2
28
35
  }
29
36
 
30
- protected get syncZPosOffset(): number {
31
- return 0
37
+ /**
38
+ * 0~100 정규화 z (= state.forkZ) 를 mast 높이 비율로 변환해서 포크 group 의
39
+ * three-up y 위치 갱신. build() 가 안 끝났으면 noop — build 가 forkZ 를 다시
40
+ * 반영하면서 끝난다.
41
+ */
42
+ applyForkZ(z: number): void {
43
+ if (!this.forkGroup) return
44
+ const clamped = Math.max(0, Math.min(100, Number(z) || 0))
45
+ this.forkGroup.position.y = this.forkMastBaseY + (clamped / 100) * this.forkMastH
32
46
  }
33
47
 
34
48
  private resolveColor(): number {
@@ -62,17 +76,16 @@ export class Crane3D extends RealObjectGroup {
62
76
  const d = this.effectiveDepth
63
77
  if (!w || !h) return
64
78
 
79
+ const inner = this.components3D
80
+
65
81
  // 높이 배분: 하단 클램프 4%, 마스트 92%, 상단 클램프 4%
66
82
  const clampH = d * 0.04
67
83
  const mastH = d * 0.92
68
84
 
69
85
  const pillarThick = Math.min(w, h) * 0.12
70
86
 
71
- const clampMat = new THREE.MeshStandardMaterial({
72
- color: CLAMP_COLOR,
73
- roughness: 0.5,
74
- metalness: 0.5,
75
- })
87
+ // MaterialBank 공유(dedup). 자체 update() 없이 base 생명주기(guarded disposeObject3D) 상속 → 안전.
88
+ const clampMat = MaterialBank.material('crane|clamp', { roughness: 0.5, metalness: 0.5 }, CLAMP_COLOR)
76
89
 
77
90
  // ── 1. 하단 클램프 (바닥 레일에 물리는 바퀴부) ──
78
91
  const clampW = w * 0.7
@@ -81,16 +94,12 @@ export class Crane3D extends RealObjectGroup {
81
94
  const bottomClamp = new THREE.Mesh(bottomClampGeo, clampMat)
82
95
  bottomClamp.position.y = clampH / 2
83
96
  bottomClamp.castShadow = true
84
- this.object3d.add(bottomClamp)
97
+ inner.add(bottomClamp)
85
98
 
86
99
  // ── 2. 수직 마스트 (좌우 기둥 + 상·하 가로 연결 바) ──
87
100
  const mastBaseY = clampH
88
101
  const bodyColor = this.resolveColor()
89
- const mastMat = new THREE.MeshStandardMaterial({
90
- color: bodyColor,
91
- roughness: 0.3,
92
- metalness: 0.6,
93
- })
102
+ const mastMat = MaterialBank.material('crane|mast', { roughness: 0.3, metalness: 0.6 }, bodyColor)
94
103
 
95
104
  const mastGeometries: THREE.BufferGeometry[] = []
96
105
 
@@ -115,27 +124,23 @@ export class Crane3D extends RealObjectGroup {
115
124
 
116
125
  const mastMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(mastGeometries), mastMat)
117
126
  mastMesh.castShadow = true
118
- this.object3d.add(mastMesh)
127
+ inner.add(mastMesh)
119
128
 
120
- // ── 3. 캐리지 포크 (마스트 40% 높이, 양쪽으로 뻗는 포크 암) ──
121
- const forkY = mastBaseY + mastH * 0.4
122
- const forkMat = new THREE.MeshStandardMaterial({
123
- color: FORK_COLOR,
124
- roughness: 0.4,
125
- metalness: 0.5,
126
- })
129
+ // ── 3. 캐리지 포크 (별도 group — state.forkZ 변경 시 group.position.y lerp) ──
130
+ // 포크 geometry 는 *_mastBaseY 기준 local 0 에 둠* — 즉 group.position.y = 0
131
+ // 일 때 mast 바닥 자리에. forkZ 0~100 에 따라 group.position.y 만 변경하면
132
+ // mast 따라 위/아래 이동. mesh 재구축 불필요.
133
+ const forkMat = MaterialBank.material('crane|fork', { roughness: 0.4, metalness: 0.5 }, FORK_COLOR)
127
134
 
128
135
  const forkGeometries: THREE.BufferGeometry[] = []
129
136
 
130
- // 캐리지 중심 플레이트 (마스트에 부착, 양쪽 포크의 베이스)
131
137
  const plateW = w * 0.9
132
138
  const plateH = d * 0.08
133
139
  const plateD = pillarThick * 0.8
134
140
  const centerPlate = new THREE.BoxGeometry(plateW, plateH, plateD)
135
- centerPlate.translate(0, forkY + plateH / 2, 0)
141
+ centerPlate.translate(0, plateH / 2, 0) // local 0 = mast 바닥
136
142
  forkGeometries.push(centerPlate)
137
143
 
138
- // 양쪽 포크 암 (좌/우 선반 방향으로 뻗음)
139
144
  const armW = pillarThick * 0.6
140
145
  const armH = plateH * 0.4
141
146
  const armD = h * 0.6
@@ -144,31 +149,59 @@ export class Crane3D extends RealObjectGroup {
144
149
  for (const zSign of [-1, 1]) {
145
150
  for (const xSign of [-1, 1]) {
146
151
  const arm = new THREE.BoxGeometry(armW, armH, armD)
147
- arm.translate(xSign * (armSpacing / 2), forkY + armH / 2, zSign * (plateD / 2 + armD / 2))
152
+ arm.translate(xSign * (armSpacing / 2), armH / 2, zSign * (plateD / 2 + armD / 2))
148
153
  forkGeometries.push(arm)
149
154
  }
150
155
  }
151
156
 
152
157
  const forkMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(forkGeometries), forkMat)
153
158
  forkMesh.castShadow = true
154
- this.object3d.add(forkMesh)
159
+
160
+ const forkGroup = new THREE.Group()
161
+ forkGroup.add(forkMesh)
162
+ inner.add(forkGroup)
163
+ this.forkGroup = forkGroup
164
+ this.forkMastBaseY = mastBaseY
165
+ // forkZ=100 시점에 mast 의 *_위쪽 한계*. 포크 자체 두께 (plateH) 만큼은 마스트
166
+ // 안에 머무르도록 limit 보정 — 그렇지 않으면 forkZ=100 일 때 포크가 상단
167
+ // 클램프와 충돌. mastH * 0.92 로 약간 보수적 (= 마스트 본체 92% 까지만 이동).
168
+ this.forkMastH = mastH * 0.92
169
+
170
+ // 초기 forkZ 반영 — state.forkZ 가 이미 set 되어 있으면 그 위치에 배치
171
+ const initialForkZ = Number((this.component.state as any).forkZ)
172
+ this.applyForkZ(Number.isFinite(initialForkZ) ? initialForkZ : 0)
155
173
 
156
174
  // ── 4. 상단 클램프 (천장 레일에 물리는 가이드부) ──
157
175
  const topClampGeo = new THREE.BoxGeometry(clampW, clampH, clampD)
158
176
  const topClamp = new THREE.Mesh(topClampGeo, clampMat)
159
177
  topClamp.position.y = mastBaseY + mastH + clampH / 2
160
178
  topClamp.castShadow = true
161
- this.object3d.add(topClamp)
179
+ inner.add(topClamp)
180
+
181
+ // mesh 는 super.build() 이후 생성 → 코어 faint 를 명시 적용(편집 흐림이 mesh 에 닿게).
182
+ this.updateAlpha()
162
183
  }
163
184
 
164
185
  updateDimension() {}
165
- updateAlpha() {}
186
+ // updateAlpha override 제거 — 코어 RealObject.updateAlpha(=applyMaterialOpacity)로 수렴(faint).
187
+
188
+ /** build() 직전 호출. forkGroup 참조를 깨끗이 비워둔다 — 새 build 가 다시 set. */
189
+ clear() {
190
+ this.forkGroup = undefined
191
+ super.clear()
192
+ }
166
193
 
167
194
  onchange(after: Record<string, unknown>, before: Record<string, unknown>) {
168
195
  if ('width' in after || 'height' in after || 'depth' in after || 'fillStyle' in after || 'strokeStyle' in after) {
169
196
  this.update()
170
197
  return
171
198
  }
199
+ // forkZ 는 mesh 재구축 없이 group.position.y 만 갱신. 같은 onchange 에서
200
+ // left/top 도 함께 변경될 수 있으므로 super 도 반드시 호출해 본체 transform
201
+ // 갱신 path (state.left/top → obj3d.position.x/z) 가 동작하게 함.
202
+ if ('forkZ' in after) {
203
+ this.applyForkZ(Number(after.forkZ) || 0)
204
+ }
172
205
  super.onchange(after, before)
173
206
  }
174
207
  }
@@ -12,9 +12,10 @@
12
12
 
13
13
  import * as THREE from 'three'
14
14
  import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js'
15
- import { RealObjectGroup, registerRealObjectFactory } from '@hatiolab/things-scene'
15
+ import { RealObjectGroup, registerRealObjectFactory, MaterialBank } from '@hatiolab/things-scene'
16
16
  import type { Component } from '@hatiolab/things-scene'
17
17
  import { TRANSPORT_SURFACE_HEIGHT } from './machine-3d.js'
18
+ import { Z_FMSIM } from './z-priority'
18
19
 
19
20
  const RAIL_COLOR = 0x666677
20
21
  const SUPPORT_COLOR = 0x555566
@@ -23,15 +24,13 @@ const SUPPORT_COLOR = 0x555566
23
24
  const DEFAULT_RAIL_DEPTH = 5 * TRANSPORT_SURFACE_HEIGHT
24
25
 
25
26
  export class CraneRail3D extends RealObjectGroup {
27
+ get zPriority(): number { return Z_FMSIM.CRANE_RAIL }
28
+
26
29
  get effectiveDepth(): number {
27
30
  const { depth } = this.component.state
28
31
  return depth || DEFAULT_RAIL_DEPTH
29
32
  }
30
33
 
31
- protected get syncZPosOffset(): number {
32
- return 0
33
- }
34
-
35
34
  build() {
36
35
  super.build()
37
36
 
@@ -41,21 +40,16 @@ export class CraneRail3D extends RealObjectGroup {
41
40
  const d = this.effectiveDepth
42
41
  if (!w || !h) return
43
42
 
43
+ const inner = this.components3D
44
+
44
45
  const railH = Math.max(d * 0.02, 2) // 레일 높이 (얇은 트랙)
45
46
  const railW = Math.max(h * 0.06, 2) // 레일 폭
46
47
  const supportThick = Math.max(Math.min(w, h) * 0.05, 2)
47
48
 
48
- const railMat = new THREE.MeshStandardMaterial({
49
- color: RAIL_COLOR,
50
- roughness: 0.3,
51
- metalness: 0.7,
52
- })
53
-
54
- const supportMat = new THREE.MeshStandardMaterial({
55
- color: SUPPORT_COLOR,
56
- roughness: 0.5,
57
- metalness: 0.5,
58
- })
49
+ // MaterialBank 공유(정적 색 dedup). 자체 update() 없이 base 생명주기(guarded disposeObject3D)
50
+ // 상속 → 공유 base dispose 안전.
51
+ const railMat = MaterialBank.material('crane-rail|rail', { roughness: 0.3, metalness: 0.7 }, RAIL_COLOR)
52
+ const supportMat = MaterialBank.material('crane-rail|support', { roughness: 0.5, metalness: 0.5 }, SUPPORT_COLOR)
59
53
 
60
54
  // ── 바닥 레일 (2개 평행 트랙) ──
61
55
  const bottomGeometries: THREE.BufferGeometry[] = []
@@ -67,7 +61,7 @@ export class CraneRail3D extends RealObjectGroup {
67
61
  const bottomMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(bottomGeometries), railMat)
68
62
  bottomMesh.castShadow = true
69
63
  bottomMesh.receiveShadow = true
70
- this.object3d.add(bottomMesh)
64
+ inner.add(bottomMesh)
71
65
 
72
66
  // ── 천장 가이드 레일 (2개 평행 트랙) ──
73
67
  const topGeometries: THREE.BufferGeometry[] = []
@@ -78,7 +72,7 @@ export class CraneRail3D extends RealObjectGroup {
78
72
  }
79
73
  const topMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(topGeometries), railMat)
80
74
  topMesh.castShadow = true
81
- this.object3d.add(topMesh)
75
+ inner.add(topMesh)
82
76
 
83
77
  // ── 양 끝단 수직 지지대 (바닥~천장 연결) ──
84
78
  const supportH = d - railH * 2
@@ -96,11 +90,14 @@ export class CraneRail3D extends RealObjectGroup {
96
90
  }
97
91
  const supportMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(supportGeometries), supportMat)
98
92
  supportMesh.castShadow = true
99
- this.object3d.add(supportMesh)
93
+ inner.add(supportMesh)
94
+
95
+ // mesh 는 super.build() 이후 생성 → 코어 faint 를 명시 적용(편집 흐림이 mesh 에 닿게).
96
+ this.updateAlpha()
100
97
  }
101
98
 
102
99
  updateDimension() {}
103
- updateAlpha() {}
100
+ // updateAlpha override 제거 — 코어 RealObject.updateAlpha(=applyMaterialOpacity)로 수렴(faint).
104
101
 
105
102
  onchange(after: Record<string, unknown>, before: Record<string, unknown>) {
106
103
  if ('width' in after || 'height' in after || 'depth' in after || 'fillStyle' in after || 'strokeStyle' in after) {