@fmsim/machine 2.0.0-beta.85 → 2.0.0-beta.87
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-manager.js +123 -37
- package/dist/carrier-manager.js.map +1 -1
- package/dist/carrier.js +16 -1
- package/dist/carrier.js.map +1 -1
- package/dist/crane.js +134 -1
- package/dist/crane.js.map +1 -1
- package/dist/factories/crane-3d.js +45 -7
- package/dist/factories/crane-3d.js.map +1 -1
- package/dist/factories/machine-3d.js +41 -2
- package/dist/factories/machine-3d.js.map +1 -1
- package/dist/features/mcs-status-default.js +2 -1
- package/dist/features/mcs-status-default.js.map +1 -1
- package/dist/mcs-carrier-holder.js +39 -26
- package/dist/mcs-carrier-holder.js.map +1 -1
- package/dist/scene/root-container-override.js +55 -100
- package/dist/scene/root-container-override.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/carrier-manager.ts +143 -41
- package/src/carrier.ts +18 -1
- package/src/crane.ts +171 -1
- package/src/factories/crane-3d.ts +50 -7
- package/src/factories/machine-3d.ts +39 -1
- package/src/features/mcs-status-default.ts +2 -1
- package/src/mcs-carrier-holder.ts +40 -27
- package/src/scene/root-container-override.ts +48 -113
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import { themesColorMap, themesAnimationMap } from '@fmsim/api'
|
|
2
2
|
import MCSUnit from './mcs-unit.js'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Holder.data 변경 감지 시 carrierManager 에 전달할 4 키 묶음 + ADDITIONS 배열.
|
|
6
|
+
* 비교 결과 단 하나라도 다르면 carrierManager.update 호출.
|
|
7
|
+
*/
|
|
8
|
+
const CARRIER_DATA_KEYS = ['CARRIERNAME', 'CARRIERTYPE', 'EMPTYTYPE', 'CARRIERSTATUS'] as const
|
|
9
|
+
|
|
10
|
+
function additionsChanged(a: any, b: any): boolean {
|
|
11
|
+
// shallow JSON 비교로 충분 — 각 항목이 4 키 primitive 만 가짐. 깊은 ref 비교
|
|
12
|
+
// 보다 빠르고 정확. 빈/누락은 같은 '[]' 직렬화로 동치 취급.
|
|
13
|
+
return JSON.stringify(a?.ADDITIONS ?? []) !== JSON.stringify(b?.ADDITIONS ?? [])
|
|
14
|
+
}
|
|
15
|
+
|
|
4
16
|
export default class MCSCarrierHolder extends MCSUnit {
|
|
5
17
|
static get properties(): any {
|
|
6
18
|
return [
|
|
@@ -26,6 +38,8 @@ export default class MCSCarrierHolder extends MCSUnit {
|
|
|
26
38
|
label: 'show-carrier-text',
|
|
27
39
|
name: 'showCarrierText'
|
|
28
40
|
}
|
|
41
|
+
// 적층 두께는 carrier 측 (Carrier.added) 에서 자기 default depth 를 결정.
|
|
42
|
+
// holder 측에는 별도 carrierDepth 속성을 두지 않는다.
|
|
29
43
|
]
|
|
30
44
|
}
|
|
31
45
|
|
|
@@ -48,39 +62,38 @@ export default class MCSCarrierHolder extends MCSUnit {
|
|
|
48
62
|
async ready() {
|
|
49
63
|
super.ready()
|
|
50
64
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
if(CARRIERNAME) {
|
|
54
|
-
;(this.root as any).carrierManager.update(this, {
|
|
55
|
-
CARRIERNAME,
|
|
56
|
-
CARRIERTYPE,
|
|
57
|
-
EMPTYTYPE,
|
|
58
|
-
CARRIERSTATUS
|
|
59
|
-
}, undefined)
|
|
65
|
+
if (this._hasCarrierData(this.data)) {
|
|
66
|
+
;(this.root as any).carrierManager.update(this, this.data || {}, undefined)
|
|
60
67
|
}
|
|
61
68
|
}
|
|
62
69
|
|
|
63
70
|
onchangeData(after: Record<string, any>, before: Record<string, any>): void {
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
CARRIERSTATUS: beforeCARRIERSTATUS
|
|
81
|
-
})
|
|
71
|
+
const afterData = after.data || {}
|
|
72
|
+
const beforeData = before.data || {}
|
|
73
|
+
|
|
74
|
+
let changed = false
|
|
75
|
+
for (const k of CARRIER_DATA_KEYS) {
|
|
76
|
+
if (afterData[k] !== beforeData[k]) {
|
|
77
|
+
changed = true
|
|
78
|
+
break
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (!changed) {
|
|
82
|
+
changed = additionsChanged(afterData, beforeData)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (changed) {
|
|
86
|
+
;(this.root as any).carrierManager.update(this, afterData, beforeData)
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
super.onchangeData(after, before)
|
|
85
90
|
}
|
|
91
|
+
|
|
92
|
+
/** data 안에 carrier 정보 (대표 또는 ADDITIONS) 가 하나라도 있는지. */
|
|
93
|
+
private _hasCarrierData(data: any): boolean {
|
|
94
|
+
if (!data) return false
|
|
95
|
+
if (data.CARRIERNAME) return true
|
|
96
|
+
if (Array.isArray(data.ADDITIONS) && data.ADDITIONS.some((a: any) => a?.CARRIERNAME)) return true
|
|
97
|
+
return false
|
|
98
|
+
}
|
|
86
99
|
}
|
|
@@ -249,124 +249,59 @@ ModelLayer.prototype.onchange = function (after: any) {
|
|
|
249
249
|
return _origModelLayerOnchange.call(this, after)
|
|
250
250
|
}
|
|
251
251
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
Object.defineProperty(RootContainer.prototype, 'agvlineLegendTheme', {
|
|
267
|
-
get: function () {
|
|
268
|
-
const { agvlineLegendName } = this.rootModel.state
|
|
269
|
-
return agvlineLegendName && this.state.style[agvlineLegendName]
|
|
270
|
-
}
|
|
271
|
-
})
|
|
272
|
-
|
|
273
|
-
Object.defineProperty(RootContainer.prototype, 'ohtlineLegendTheme', {
|
|
274
|
-
get: function () {
|
|
275
|
-
const { ohtlineLegendName } = this.rootModel.state
|
|
276
|
-
return ohtlineLegendName && this.state.style[ohtlineLegendName]
|
|
277
|
-
}
|
|
278
|
-
})
|
|
279
|
-
|
|
280
|
-
Object.defineProperty(RootContainer.prototype, 'conveyorLegendTheme', {
|
|
281
|
-
get: function () {
|
|
282
|
-
const { conveyorLegendName } = this.rootModel.state
|
|
283
|
-
return conveyorLegendName && this.state.style[conveyorLegendName]
|
|
284
|
-
}
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
Object.defineProperty(RootContainer.prototype, 'stokerLegendTheme', {
|
|
288
|
-
get: function () {
|
|
289
|
-
const { stokerLegendName } = this.rootModel.state
|
|
290
|
-
return stokerLegendName && this.state.style[stokerLegendName]
|
|
291
|
-
}
|
|
292
|
-
})
|
|
293
|
-
|
|
294
|
-
Object.defineProperty(RootContainer.prototype, 'agvLegendTheme', {
|
|
295
|
-
get: function () {
|
|
296
|
-
const { agvLegendName } = this.rootModel.state
|
|
297
|
-
return agvLegendName && this.state.style[agvLegendName]
|
|
298
|
-
}
|
|
299
|
-
})
|
|
300
|
-
|
|
301
|
-
Object.defineProperty(RootContainer.prototype, 'ohtLegendTheme', {
|
|
302
|
-
get: function () {
|
|
303
|
-
const { ohtLegendName } = this.rootModel.state
|
|
304
|
-
return ohtLegendName && this.state.style[ohtLegendName]
|
|
305
|
-
}
|
|
306
|
-
})
|
|
307
|
-
|
|
308
|
-
Object.defineProperty(RootContainer.prototype, 'shuttleLegendTheme', {
|
|
309
|
-
get: function () {
|
|
310
|
-
const { shuttleLegendName } = this.rootModel.state
|
|
311
|
-
return shuttleLegendName && this.state.style[shuttleLegendName]
|
|
312
|
-
}
|
|
313
|
-
})
|
|
314
|
-
|
|
315
|
-
Object.defineProperty(RootContainer.prototype, 'craneLegendTheme', {
|
|
316
|
-
get: function () {
|
|
317
|
-
const { craneLegendName } = this.rootModel.state
|
|
318
|
-
return craneLegendName && this.state.style[craneLegendName]
|
|
319
|
-
}
|
|
320
|
-
})
|
|
321
|
-
|
|
322
|
-
Object.defineProperty(RootContainer.prototype, 'shelfLegendTheme', {
|
|
323
|
-
get: function () {
|
|
324
|
-
const { shelfLegendName } = this.rootModel.state
|
|
325
|
-
return shelfLegendName && this.state.style[shelfLegendName]
|
|
326
|
-
}
|
|
327
|
-
})
|
|
328
|
-
|
|
329
|
-
Object.defineProperty(RootContainer.prototype, 'portLegendTheme', {
|
|
330
|
-
get: function () {
|
|
331
|
-
const { portLegendName } = this.rootModel.state
|
|
332
|
-
return portLegendName && this.state.style[portLegendName]
|
|
333
|
-
}
|
|
334
|
-
})
|
|
335
|
-
|
|
336
|
-
Object.defineProperty(RootContainer.prototype, 'carrierLegendTheme', {
|
|
337
|
-
get: function () {
|
|
338
|
-
const { carrierLegendName } = this.rootModel.state
|
|
339
|
-
return carrierLegendName && this.state.style[carrierLegendName]
|
|
340
|
-
}
|
|
341
|
-
})
|
|
342
|
-
|
|
343
|
-
Object.defineProperty(RootContainer.prototype, 'carrierAnimationTheme', {
|
|
344
|
-
get: function () {
|
|
345
|
-
const { carrierAnimationName } = this.rootModel.state
|
|
346
|
-
return carrierAnimationName && this.state.style[carrierAnimationName]
|
|
347
|
-
}
|
|
348
|
-
})
|
|
252
|
+
// === LegendTheme / AnimationTheme value resolve ===
|
|
253
|
+
//
|
|
254
|
+
// rootModel.state.style[name] 에 저장된 legend/animation 값은 보드 직렬화
|
|
255
|
+
// 형태에 따라 (a) 정상 object 또는 (b) JSON 문자열 둘 다로 나타난다 (2026-06-09
|
|
256
|
+
// 진단 — consumer 인 carrier.ts:animationPreset 이 같은 이유로 typeof string
|
|
257
|
+
// 분기 + JSON5.parse 처리하는 선례 존재). LegendTheme getter 들이 이 분기를
|
|
258
|
+
// 두지 않아 string 통과 → getValueOnRanges 매칭 실패 → 3D gauge 의 색상이
|
|
259
|
+
// fallback 으로만 결정되던 증상.
|
|
260
|
+
//
|
|
261
|
+
// fix 는 getter 한 곳에서 lazy parse. WeakMap<state, Map<rawString, parsed>>
|
|
262
|
+
// 으로 *raw string 자체를 key* — 보드 편집으로 raw 가 바뀌면 자연 무효화,
|
|
263
|
+
// 같은 raw 의 반복 lookup 은 O(1). root 가 GC 되면 cache 도 같이 GC.
|
|
264
|
+
const _legendParseCache = new WeakMap<object, Map<string, any>>()
|
|
349
265
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
266
|
+
function parseLegendIfString(state: any, raw: any): any {
|
|
267
|
+
if (typeof raw !== 'string') return raw
|
|
268
|
+
let cache = _legendParseCache.get(state)
|
|
269
|
+
if (!cache) {
|
|
270
|
+
cache = new Map()
|
|
271
|
+
_legendParseCache.set(state, cache)
|
|
354
272
|
}
|
|
355
|
-
|
|
273
|
+
if (cache.has(raw)) return cache.get(raw)
|
|
274
|
+
let parsed: any
|
|
275
|
+
try { parsed = JSON.parse(raw) } catch { parsed = raw } // parse 실패 시 raw 보존
|
|
276
|
+
cache.set(raw, parsed)
|
|
277
|
+
return parsed
|
|
278
|
+
}
|
|
356
279
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
const
|
|
360
|
-
|
|
280
|
+
function legendThemeGetter(stateKey: string) {
|
|
281
|
+
return function (this: any) {
|
|
282
|
+
const name = this.rootModel.state[stateKey]
|
|
283
|
+
const raw = name && this.state.style[name]
|
|
284
|
+
return parseLegendIfString(this.state, raw)
|
|
361
285
|
}
|
|
362
|
-
}
|
|
286
|
+
}
|
|
363
287
|
|
|
364
|
-
Object.defineProperty(RootContainer.prototype, '
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
})
|
|
288
|
+
Object.defineProperty(RootContainer.prototype, 'equipmentLegendTheme', { get: legendThemeGetter('equipmentLegendName') })
|
|
289
|
+
Object.defineProperty(RootContainer.prototype, 'bufferLegendTheme', { get: legendThemeGetter('bufferLegendName') })
|
|
290
|
+
Object.defineProperty(RootContainer.prototype, 'agvlineLegendTheme', { get: legendThemeGetter('agvlineLegendName') })
|
|
291
|
+
Object.defineProperty(RootContainer.prototype, 'ohtlineLegendTheme', { get: legendThemeGetter('ohtlineLegendName') })
|
|
292
|
+
Object.defineProperty(RootContainer.prototype, 'conveyorLegendTheme', { get: legendThemeGetter('conveyorLegendName') })
|
|
293
|
+
Object.defineProperty(RootContainer.prototype, 'stokerLegendTheme', { get: legendThemeGetter('stokerLegendName') })
|
|
294
|
+
Object.defineProperty(RootContainer.prototype, 'agvLegendTheme', { get: legendThemeGetter('agvLegendName') })
|
|
295
|
+
Object.defineProperty(RootContainer.prototype, 'ohtLegendTheme', { get: legendThemeGetter('ohtLegendName') })
|
|
296
|
+
Object.defineProperty(RootContainer.prototype, 'shuttleLegendTheme', { get: legendThemeGetter('shuttleLegendName') })
|
|
297
|
+
Object.defineProperty(RootContainer.prototype, 'craneLegendTheme', { get: legendThemeGetter('craneLegendName') })
|
|
298
|
+
Object.defineProperty(RootContainer.prototype, 'shelfLegendTheme', { get: legendThemeGetter('shelfLegendName') })
|
|
299
|
+
Object.defineProperty(RootContainer.prototype, 'portLegendTheme', { get: legendThemeGetter('portLegendName') })
|
|
300
|
+
Object.defineProperty(RootContainer.prototype, 'carrierLegendTheme', { get: legendThemeGetter('carrierLegendName') })
|
|
301
|
+
Object.defineProperty(RootContainer.prototype, 'carrierAnimationTheme', { get: legendThemeGetter('carrierAnimationName') })
|
|
302
|
+
Object.defineProperty(RootContainer.prototype, 'stockerCapacityLegendTheme', { get: legendThemeGetter('stockerCapacityLegendName') })
|
|
303
|
+
Object.defineProperty(RootContainer.prototype, 'zoneCapacityLegendTheme', { get: legendThemeGetter('zoneCapacityLegendName') })
|
|
304
|
+
Object.defineProperty(RootContainer.prototype, 'batteryRateLegendTheme', { get: legendThemeGetter('batteryRateLegendName') })
|
|
370
305
|
|
|
371
306
|
Object.defineProperty(RootContainer.prototype, 'vehicleAnimation', {
|
|
372
307
|
get: function () {
|