@fmsim/machine 1.0.18 → 1.0.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/carrier.js +46 -32
- package/dist/carrier.js.map +1 -1
- package/dist/features/mcs-status-default.js +3 -3
- package/dist/features/mcs-status-default.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/mcs-carrier-holder.js +10 -183
- package/dist/mcs-carrier-holder.js.map +1 -1
- package/dist/mcs-unit.js +2 -2
- package/dist/mcs-unit.js.map +1 -1
- package/dist/port-flow.js +43 -10
- package/dist/port-flow.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/carrier.ts +46 -35
- package/src/features/mcs-status-default.ts +3 -3
- package/src/index.ts +1 -0
- package/src/mcs-carrier-holder.ts +15 -241
- package/src/mcs-unit.ts +2 -2
- package/src/port-flow.ts +34 -18
|
@@ -1,226 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
import { BOUNDS, Component } from '@hatiolab/things-scene'
|
|
1
|
+
import { Model } from '@hatiolab/things-scene'
|
|
4
2
|
import { themesColorMap, themesAnimationMap } from '@fmsim/api'
|
|
5
|
-
import { ANIMATION_DEFAULT, AnimationPreset, AnimationConfig } from './features/animation-default.js'
|
|
6
|
-
import { LEGEND_CARRIER, Legend } from './features/mcs-status-default.js'
|
|
7
|
-
import { MCSStatusMixin } from './features/mcs-status-mixin.js'
|
|
8
3
|
import MCSUnit from './mcs-unit.js'
|
|
9
|
-
|
|
10
|
-
export class Carrier extends MCSStatusMixin(Object) {
|
|
11
|
-
host: Component
|
|
12
|
-
|
|
13
|
-
id?: string
|
|
14
|
-
emptyType?: 'FULL' | 'EMPTY' | 'EMPTYEMPTY'
|
|
15
|
-
carrierStatus?: string
|
|
16
|
-
|
|
17
|
-
lastCarrierStatus?: string
|
|
18
|
-
|
|
19
|
-
constructor(host: Component) {
|
|
20
|
-
super()
|
|
21
|
-
this.host = host
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
set data(data: any) {
|
|
25
|
-
const { CARRIERNAME, CARRIERTYPE = '', EMPTYTYPE, CARRIERSTATUS } = data || {}
|
|
26
|
-
|
|
27
|
-
this.id = CARRIERNAME
|
|
28
|
-
this.emptyType = EMPTYTYPE
|
|
29
|
-
this.carrierStatus = CARRIERSTATUS
|
|
30
|
-
|
|
31
|
-
// TODO carrierstatus에 따라서 매핑되는 애니메이션 테마 수행
|
|
32
|
-
if (this.lastCarrierStatus !== this.carrierStatus) {
|
|
33
|
-
const lastAnimationConfig = this.getAnimationConfig(this.lastCarrierStatus)
|
|
34
|
-
const target = this.host as any
|
|
35
|
-
|
|
36
|
-
if (lastAnimationConfig) {
|
|
37
|
-
let { animation, decorator, border, arrow } = lastAnimationConfig
|
|
38
|
-
if (animation) {
|
|
39
|
-
target.started = false
|
|
40
|
-
target._animation = null
|
|
41
|
-
target.setState('animation', {
|
|
42
|
-
oncreate: null
|
|
43
|
-
})
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (decorator) {
|
|
47
|
-
target.trigger('iconoff')
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (border) {
|
|
51
|
-
target.trigger('borderoff')
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (arrow) {
|
|
55
|
-
target.trigger('bouncingoff')
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const animationConfig = this.getAnimationConfig(this.carrierStatus)
|
|
60
|
-
|
|
61
|
-
if (animationConfig) {
|
|
62
|
-
let { animation, decorator, border, arrow } = animationConfig
|
|
63
|
-
if (animation) {
|
|
64
|
-
target.started = false
|
|
65
|
-
target._animation = null
|
|
66
|
-
target.setState('animation', {
|
|
67
|
-
oncreate: animation
|
|
68
|
-
})
|
|
69
|
-
target.started = true
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
if (decorator) {
|
|
73
|
-
target.trigger('iconoff')
|
|
74
|
-
target.trigger('icon', decorator)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if (border) {
|
|
78
|
-
target.trigger('borderoff')
|
|
79
|
-
target.trigger('border', border)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (arrow) {
|
|
83
|
-
target.trigger('bouncingoff')
|
|
84
|
-
target.trigger('bouncing', arrow)
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
this.lastCarrierStatus = this.carrierStatus
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
get status() {
|
|
93
|
-
return this.emptyType
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
get legend(): Legend {
|
|
97
|
-
const { carrierLegendName } = this.host.state
|
|
98
|
-
|
|
99
|
-
if (carrierLegendName) {
|
|
100
|
-
return (this.host.root as any)?.style[carrierLegendName]
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return LEGEND_CARRIER
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
getAnimationConfig(carrierStatus): AnimationConfig | null {
|
|
107
|
-
const config = this.animationPreset[carrierStatus || 'default']
|
|
108
|
-
|
|
109
|
-
if (config && typeof config == 'string') {
|
|
110
|
-
try {
|
|
111
|
-
return JSON5.parse(config)
|
|
112
|
-
} catch (e) {
|
|
113
|
-
console.error(e)
|
|
114
|
-
}
|
|
115
|
-
} else {
|
|
116
|
-
return (config as AnimationConfig) || null
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return null
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
get animationPreset(): AnimationPreset {
|
|
123
|
-
const { carrierAnimationName } = this.host.state
|
|
124
|
-
|
|
125
|
-
if (carrierAnimationName) {
|
|
126
|
-
return (this.host.root as any)?.style[carrierAnimationName] || ANIMATION_DEFAULT
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return ANIMATION_DEFAULT
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
calculateShrunkRectangle(originalRect: BOUNDS): BOUNDS {
|
|
133
|
-
const shrunkRect: BOUNDS = { ...originalRect }
|
|
134
|
-
|
|
135
|
-
shrunkRect.left += originalRect.width * 0.1
|
|
136
|
-
shrunkRect.width *= 0.8
|
|
137
|
-
|
|
138
|
-
shrunkRect.top += originalRect.height * 0.1
|
|
139
|
-
shrunkRect.height *= 0.8
|
|
140
|
-
|
|
141
|
-
return shrunkRect
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
isPointOnCarrier(x, y, { left, top, width, height }) {
|
|
145
|
-
const rect = this.calculateShrunkRectangle({ left, top, width, height })
|
|
146
|
-
x -= rect.left
|
|
147
|
-
y -= rect.top
|
|
148
|
-
|
|
149
|
-
if (x < 0 || y < 0 || x > rect.width || y > rect.height) {
|
|
150
|
-
return false
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// 윗변 중앙 좌표
|
|
154
|
-
const topCenterX = rect.width / 2
|
|
155
|
-
const topCenterY = 0
|
|
156
|
-
|
|
157
|
-
// 오른쪽 변 중앙 좌표
|
|
158
|
-
const rightCenterX = rect.width
|
|
159
|
-
const rightCenterY = rect.height / 2
|
|
160
|
-
|
|
161
|
-
// 기울기 m = (y2 - y1) / (x2 - x1)
|
|
162
|
-
const m = (rightCenterY - topCenterY) / (rightCenterX - topCenterX)
|
|
163
|
-
|
|
164
|
-
// y 절편 b = y - mx
|
|
165
|
-
const b = topCenterY - m * topCenterX
|
|
166
|
-
|
|
167
|
-
// 점(px, py)이 선 아래(좌하부)에 있는지 확인
|
|
168
|
-
return y > m * x + b
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
render(ctx: CanvasRenderingContext2D) {
|
|
172
|
-
if (!this.emptyType) {
|
|
173
|
-
return
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const { left, top, width, height } = this.calculateShrunkRectangle(this.host.bounds)
|
|
177
|
-
|
|
178
|
-
const radius = Math.round(Math.min(width, height) * 0.1)
|
|
179
|
-
|
|
180
|
-
// 시작점 설정
|
|
181
|
-
ctx.beginPath()
|
|
182
|
-
ctx.moveTo(left + radius, top)
|
|
183
|
-
|
|
184
|
-
// 상단 가로선 그리기
|
|
185
|
-
ctx.lineTo(left + width / 2, top)
|
|
186
|
-
|
|
187
|
-
// 우측 세로선 그리기
|
|
188
|
-
ctx.lineTo(left + width, top + height / 2)
|
|
189
|
-
ctx.lineTo(left + width, top + height)
|
|
190
|
-
|
|
191
|
-
// 하단 가로선 그리기
|
|
192
|
-
ctx.lineTo(left, top + height)
|
|
193
|
-
|
|
194
|
-
// 좌측 세로선 그리기
|
|
195
|
-
ctx.lineTo(left, top)
|
|
196
|
-
|
|
197
|
-
// 경로 닫기 및 그리기
|
|
198
|
-
ctx.closePath()
|
|
199
|
-
|
|
200
|
-
ctx.lineWidth = radius > 5 ? 1 : 0.5
|
|
201
|
-
ctx.fillStyle = this.statusColor || 'transparent'
|
|
202
|
-
ctx.strokeStyle = this.auxColor || 'transparent'
|
|
203
|
-
|
|
204
|
-
ctx.fill()
|
|
205
|
-
ctx.stroke()
|
|
206
|
-
|
|
207
|
-
ctx.beginPath()
|
|
208
|
-
|
|
209
|
-
// const text =
|
|
210
|
-
// this.emptyType == 'FULL' ? 'F' : this.emptyType == 'EMPTY' ? 'E' : this.emptyType == 'EMPTYEMPTY' ? 'X' : ''
|
|
211
|
-
|
|
212
|
-
// if (text) {
|
|
213
|
-
// const { x: cx, y: cy } = this.host.center
|
|
214
|
-
|
|
215
|
-
// ctx.fillStyle = 'black'
|
|
216
|
-
// ctx.font = `normal ${Math.round(radius * 8)}px Arial`
|
|
217
|
-
// ctx.textAlign = 'center'
|
|
218
|
-
// ctx.textBaseline = 'middle'
|
|
219
|
-
|
|
220
|
-
// ctx.fillText(text, cx - width / 8, cy + height / 8)
|
|
221
|
-
// }
|
|
222
|
-
}
|
|
223
|
-
}
|
|
4
|
+
import Carrier from './carrier.js'
|
|
224
5
|
|
|
225
6
|
export default class MCSCarrierHolder extends MCSUnit {
|
|
226
7
|
static get properties(): any {
|
|
@@ -245,36 +26,29 @@ export default class MCSCarrierHolder extends MCSUnit {
|
|
|
245
26
|
]
|
|
246
27
|
}
|
|
247
28
|
|
|
248
|
-
carrier
|
|
29
|
+
carrier?: Carrier | null
|
|
249
30
|
|
|
250
31
|
ready() {
|
|
251
|
-
|
|
252
|
-
|
|
32
|
+
super.ready()
|
|
33
|
+
|
|
34
|
+
this.carrier = Model.compile({ type: 'Carrier' }, this.root.app) as any
|
|
253
35
|
|
|
254
|
-
|
|
255
|
-
this.carrier.render(ctx)
|
|
36
|
+
this.carrier!.data = this.data
|
|
256
37
|
|
|
257
|
-
|
|
38
|
+
this.addComponent(this.carrier!)
|
|
258
39
|
}
|
|
259
40
|
|
|
260
|
-
|
|
261
|
-
this.carrier
|
|
41
|
+
dispose(): void {
|
|
42
|
+
this.carrier = null
|
|
262
43
|
|
|
263
|
-
super.
|
|
44
|
+
super.dispose()
|
|
264
45
|
}
|
|
265
46
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
return false
|
|
47
|
+
onchangeData(after: any, before: any) {
|
|
48
|
+
if (this.carrier) {
|
|
49
|
+
this.carrier.data = this.data
|
|
270
50
|
}
|
|
271
51
|
|
|
272
|
-
|
|
273
|
-
const { left, top, width, height } = this.bounds
|
|
274
|
-
|
|
275
|
-
point.x -= left
|
|
276
|
-
point.y -= top
|
|
277
|
-
|
|
278
|
-
return this.carrier.isPointOnCarrier(point.x, point.y, { left: 0, top: 0, width, height })
|
|
52
|
+
super.onchangeData(after, before)
|
|
279
53
|
}
|
|
280
54
|
}
|
package/src/mcs-unit.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component } from '@hatiolab/things-scene'
|
|
1
|
+
import { Component, ContainerAbstract } from '@hatiolab/things-scene'
|
|
2
2
|
import { getPopupData } from '@fmsim/api'
|
|
3
3
|
|
|
4
4
|
import { MCSStatusMixin, MCSStatusMixinProperties } from './features/mcs-status-mixin'
|
|
@@ -8,7 +8,7 @@ import { ParentObjectMixin, ParentObjectMixinProperties } from './features/paren
|
|
|
8
8
|
/**
|
|
9
9
|
* MCS용 Unit들의 공통 속성을 정의한 오브젝트
|
|
10
10
|
*/
|
|
11
|
-
export default class MCSUnit extends MCSStatusMixin(ParentObjectMixin(
|
|
11
|
+
export default class MCSUnit extends MCSStatusMixin(ParentObjectMixin(ContainerAbstract)) {
|
|
12
12
|
static get properties(): any {
|
|
13
13
|
return [...MCSStatusMixinProperties, ...ParentObjectMixinProperties]
|
|
14
14
|
}
|
package/src/port-flow.ts
CHANGED
|
@@ -40,39 +40,56 @@ export default class PortFlow extends ParentObjectMixin(RectPath(Shape)) {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
get textBounds() {
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
var { paddingTop, paddingLeft, paddingRight, paddingBottom, fontSize = 24 } = this.state
|
|
44
|
+
|
|
45
|
+
paddingBottom ||= 0
|
|
46
|
+
paddingTop ||= 0
|
|
47
|
+
paddingLeft ||= 0
|
|
48
|
+
paddingRight ||= 0
|
|
49
|
+
|
|
50
|
+
var { left, top, width, height } = this.bounds
|
|
51
|
+
var { labelPosition = 'top' } = this.state
|
|
52
|
+
|
|
53
|
+
left += paddingLeft
|
|
54
|
+
top += paddingTop
|
|
55
|
+
width = Math.max(width - paddingLeft - paddingRight, 0)
|
|
56
|
+
height = Math.max(height - paddingTop - paddingBottom, 0)
|
|
45
57
|
|
|
46
58
|
switch (labelPosition) {
|
|
47
59
|
case 'top':
|
|
48
60
|
return {
|
|
49
|
-
|
|
50
|
-
top: top -
|
|
51
|
-
|
|
61
|
+
left,
|
|
62
|
+
top: top - fontSize,
|
|
63
|
+
width,
|
|
64
|
+
height: fontSize
|
|
52
65
|
}
|
|
53
66
|
case 'bottom':
|
|
54
67
|
return {
|
|
55
|
-
|
|
68
|
+
left,
|
|
56
69
|
top: top + height,
|
|
57
|
-
|
|
70
|
+
width,
|
|
71
|
+
height: fontSize
|
|
58
72
|
}
|
|
59
73
|
case 'left':
|
|
60
74
|
return {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
width:
|
|
75
|
+
left: left - fontSize * 4,
|
|
76
|
+
top,
|
|
77
|
+
width: fontSize * 4,
|
|
78
|
+
height
|
|
64
79
|
}
|
|
65
80
|
case 'right':
|
|
66
81
|
return {
|
|
67
|
-
...this.bounds,
|
|
68
82
|
left: left + width,
|
|
69
|
-
|
|
83
|
+
top,
|
|
84
|
+
width: fontSize * 4,
|
|
85
|
+
height
|
|
70
86
|
}
|
|
71
87
|
default:
|
|
72
88
|
return {
|
|
73
|
-
|
|
74
|
-
top: top -
|
|
75
|
-
|
|
89
|
+
left,
|
|
90
|
+
top: top - fontSize,
|
|
91
|
+
width,
|
|
92
|
+
height: fontSize
|
|
76
93
|
}
|
|
77
94
|
}
|
|
78
95
|
}
|
|
@@ -85,11 +102,10 @@ export default class PortFlow extends ParentObjectMixin(RectPath(Shape)) {
|
|
|
85
102
|
|
|
86
103
|
render(ctx) {
|
|
87
104
|
const { left, top, width, height } = this.bounds
|
|
88
|
-
var { orientation = 'left to right', direction = '
|
|
89
|
-
const { INOUTTYPE } = this.data
|
|
105
|
+
var { orientation = 'left to right', direction = 'BOTH' }: { orientation?: string; direction?: string } = this.state
|
|
106
|
+
const { INOUTTYPE } = this.data || {}
|
|
90
107
|
|
|
91
108
|
if (INOUTTYPE) {
|
|
92
|
-
// TODO bothtype value 조정하기.
|
|
93
109
|
direction = INOUTTYPE /* IN | OUT | BOTH */
|
|
94
110
|
}
|
|
95
111
|
|