@fmsim/machine 1.0.88 → 2.0.0-beta.100

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 (165) hide show
  1. package/dist/agv-line.js.map +1 -1
  2. package/dist/agv.js +6 -2
  3. package/dist/agv.js.map +1 -1
  4. package/dist/buffer.js.map +1 -1
  5. package/dist/carrier-manager.js +183 -0
  6. package/dist/carrier-manager.js.map +1 -0
  7. package/dist/carrier.js +105 -14
  8. package/dist/carrier.js.map +1 -1
  9. package/dist/conveyor-join.js +8 -2
  10. package/dist/conveyor-join.js.map +1 -1
  11. package/dist/conveyor.js +9 -1
  12. package/dist/conveyor.js.map +1 -1
  13. package/dist/crane-rail.js +53 -0
  14. package/dist/crane-rail.js.map +1 -0
  15. package/dist/crane.js +144 -1
  16. package/dist/crane.js.map +1 -1
  17. package/dist/equipment.js.map +1 -1
  18. package/dist/factories/agv-3d.js +147 -0
  19. package/dist/factories/agv-3d.js.map +1 -0
  20. package/dist/factories/conveyor-3d.js +345 -0
  21. package/dist/factories/conveyor-3d.js.map +1 -0
  22. package/dist/factories/crane-3d.js +186 -0
  23. package/dist/factories/crane-3d.js.map +1 -0
  24. package/dist/factories/crane-rail-3d.js +95 -0
  25. package/dist/factories/crane-rail-3d.js.map +1 -0
  26. package/dist/factories/machine-3d.js +973 -0
  27. package/dist/factories/machine-3d.js.map +1 -0
  28. package/dist/factories/oht-3d.js +177 -0
  29. package/dist/factories/oht-3d.js.map +1 -0
  30. package/dist/factories/shuttle-3d.js +159 -0
  31. package/dist/factories/shuttle-3d.js.map +1 -0
  32. package/dist/factories/z-priority-defaults.js +33 -0
  33. package/dist/factories/z-priority-defaults.js.map +1 -0
  34. package/dist/factories/z-priority.js +54 -0
  35. package/dist/factories/z-priority.js.map +1 -0
  36. package/dist/features/conveyor-mixin.js.map +1 -1
  37. package/dist/features/mcs-status-default.js +15 -1
  38. package/dist/features/mcs-status-default.js.map +1 -1
  39. package/dist/features/mcs-status-mixin.js +22 -0
  40. package/dist/features/mcs-status-mixin.js.map +1 -1
  41. package/dist/features/mcs-zone-mixin.js.map +1 -1
  42. package/dist/features/parent-object-mixin.js +15 -7
  43. package/dist/features/parent-object-mixin.js.map +1 -1
  44. package/dist/floating-container.js +5 -0
  45. package/dist/floating-container.js.map +1 -1
  46. package/dist/index.js +58 -2
  47. package/dist/index.js.map +1 -1
  48. package/dist/mcs-carrier-holder.js +56 -17
  49. package/dist/mcs-carrier-holder.js.map +1 -1
  50. package/dist/mcs-machine.js +39 -0
  51. package/dist/mcs-machine.js.map +1 -1
  52. package/dist/mcs-unit.js +20 -0
  53. package/dist/mcs-unit.js.map +1 -1
  54. package/dist/mcs-vehicle.js +10 -4
  55. package/dist/mcs-vehicle.js.map +1 -1
  56. package/dist/node.js +10 -3
  57. package/dist/node.js.map +1 -1
  58. package/dist/oht-line.js.map +1 -1
  59. package/dist/oht.js +4 -0
  60. package/dist/oht.js.map +1 -1
  61. package/dist/port-flow.js +4 -0
  62. package/dist/port-flow.js.map +1 -1
  63. package/dist/port.js +4 -0
  64. package/dist/port.js.map +1 -1
  65. package/dist/scanner.js +30 -0
  66. package/dist/scanner.js.map +1 -0
  67. package/dist/scene/root-container-override.js +160 -96
  68. package/dist/scene/root-container-override.js.map +1 -1
  69. package/dist/shelf.js +4 -0
  70. package/dist/shelf.js.map +1 -1
  71. package/dist/shuttle.js.map +1 -1
  72. package/dist/static-container.js +5 -0
  73. package/dist/static-container.js.map +1 -1
  74. package/dist/stocker-abnormal-bar.js +184 -0
  75. package/dist/stocker-abnormal-bar.js.map +1 -0
  76. package/dist/stocker-capacity-bar.js +253 -6
  77. package/dist/stocker-capacity-bar.js.map +1 -1
  78. package/dist/stocker-carrier-bar.js +198 -0
  79. package/dist/stocker-carrier-bar.js.map +1 -0
  80. package/dist/stocker.js +7 -1
  81. package/dist/stocker.js.map +1 -1
  82. package/dist/templates/backdrop.js +30 -0
  83. package/dist/templates/backdrop.js.map +1 -0
  84. package/dist/templates/decal.js +21 -0
  85. package/dist/templates/decal.js.map +1 -0
  86. package/dist/templates/index.js +7 -1
  87. package/dist/templates/index.js.map +1 -1
  88. package/dist/templates/scanner.js +20 -0
  89. package/dist/templates/scanner.js.map +1 -0
  90. package/dist/tsconfig.tsbuildinfo +1 -1
  91. package/dist/utils/crane-position.js +83 -0
  92. package/dist/utils/crane-position.js.map +1 -0
  93. package/dist/utils/data-value.js +21 -0
  94. package/dist/utils/data-value.js.map +1 -0
  95. package/dist/utils/fit-gauge-scale.js +28 -0
  96. package/dist/utils/fit-gauge-scale.js.map +1 -0
  97. package/dist/utils/get-value-on-ranges.js +2 -4
  98. package/dist/utils/get-value-on-ranges.js.map +1 -1
  99. package/dist/utils/stocker-gauge.js +78 -0
  100. package/dist/utils/stocker-gauge.js.map +1 -0
  101. package/dist/zone-capacity-bar.js +3 -3
  102. package/dist/zone-capacity-bar.js.map +1 -1
  103. package/icons/backdrop.png +0 -0
  104. package/icons/decal.png +0 -0
  105. package/jest.config.js +10 -0
  106. package/package.json +7 -6
  107. package/src/agv-line.ts +1 -1
  108. package/src/agv.ts +10 -5
  109. package/src/buffer.ts +1 -1
  110. package/src/carrier-manager.ts +223 -0
  111. package/src/carrier.ts +111 -18
  112. package/src/conveyor-join.ts +6 -3
  113. package/src/conveyor.ts +10 -2
  114. package/src/crane-rail.ts +58 -0
  115. package/src/crane.ts +182 -2
  116. package/src/equipment.ts +1 -1
  117. package/src/factories/agv-3d.ts +160 -0
  118. package/src/factories/conveyor-3d.ts +398 -0
  119. package/src/factories/crane-3d.ts +217 -0
  120. package/src/factories/crane-rail-3d.ts +115 -0
  121. package/src/factories/machine-3d.ts +1192 -0
  122. package/src/factories/oht-3d.ts +196 -0
  123. package/src/factories/shuttle-3d.ts +179 -0
  124. package/src/factories/z-priority-defaults.ts +38 -0
  125. package/src/factories/z-priority.ts +60 -0
  126. package/src/features/conveyor-mixin.ts +1 -1
  127. package/src/features/mcs-status-default.ts +15 -1
  128. package/src/features/mcs-status-mixin.ts +26 -4
  129. package/src/features/mcs-zone-mixin.ts +1 -1
  130. package/src/features/parent-object-mixin.ts +17 -8
  131. package/src/floating-container.ts +5 -0
  132. package/src/index.ts +66 -2
  133. package/src/mcs-carrier-holder.ts +58 -29
  134. package/src/mcs-machine.ts +43 -1
  135. package/src/mcs-unit.ts +25 -2
  136. package/src/mcs-vehicle.ts +12 -9
  137. package/src/node.ts +9 -3
  138. package/src/oht-line.ts +1 -1
  139. package/src/oht.ts +7 -2
  140. package/src/port-flow.ts +6 -1
  141. package/src/port.ts +6 -1
  142. package/src/scanner.ts +29 -0
  143. package/src/scene/root-container-override.ts +156 -105
  144. package/src/shelf.ts +6 -1
  145. package/src/shuttle.ts +1 -1
  146. package/src/static-container.ts +5 -0
  147. package/src/stocker-abnormal-bar.ts +247 -0
  148. package/src/stocker-capacity-bar.ts +301 -10
  149. package/src/stocker-carrier-bar.ts +262 -0
  150. package/src/stocker.ts +10 -3
  151. package/src/templates/backdrop.ts +30 -0
  152. package/src/templates/decal.ts +21 -0
  153. package/src/templates/index.ts +7 -1
  154. package/src/templates/scanner.ts +20 -0
  155. package/src/utils/crane-position.ts +105 -0
  156. package/src/utils/data-value.ts +19 -0
  157. package/src/utils/fit-gauge-scale.ts +35 -0
  158. package/src/utils/get-value-on-ranges.ts +2 -4
  159. package/src/utils/stocker-gauge.ts +111 -0
  160. package/src/zone-capacity-bar.ts +5 -5
  161. package/translations/en.json +26 -1
  162. package/translations/ja.json +26 -1
  163. package/translations/ko.json +26 -1
  164. package/translations/ms.json +26 -1
  165. package/translations/zh.json +26 -1
@@ -0,0 +1,198 @@
1
+ import { __decorate } from "tslib";
2
+ import { RectPath, Shape, sceneComponent } from '@hatiolab/things-scene';
3
+ import { LEGEND_CARRIER } from './features/mcs-status-default';
4
+ import { safeRound } from './utils/safe-round';
5
+ import { ParentObjectMixin, ParentObjectMixinProperties } from './features/parent-object-mixin';
6
+ const NATURE = {
7
+ mutable: false,
8
+ resizable: true,
9
+ rotatable: true,
10
+ properties: [
11
+ ...ParentObjectMixinProperties,
12
+ {
13
+ type: 'number',
14
+ name: 'carrierFull',
15
+ label: 'carrier-full'
16
+ },
17
+ {
18
+ type: 'number',
19
+ name: 'carrierEmpty',
20
+ label: 'carrier-empty'
21
+ },
22
+ {
23
+ type: 'number',
24
+ name: 'carrierEmptyEmpty',
25
+ label: 'carrier-empty-empty'
26
+ },
27
+ {
28
+ type: 'number',
29
+ label: 'round',
30
+ name: 'round',
31
+ property: {
32
+ min: 0
33
+ }
34
+ }
35
+ ]
36
+ };
37
+ const DEFAULT_COLORS = {
38
+ full: LEGEND_CARRIER['FULL'] || '#4AA7FE',
39
+ empty: LEGEND_CARRIER['EMPTY'] || '#8BDA5B',
40
+ emptyEmpty: LEGEND_CARRIER['EMPTYEMPTY'] || '#019D59'
41
+ };
42
+ var controlHandler = {
43
+ ondragmove: function (point, index, component) {
44
+ var { left, top, width, height } = component.model;
45
+ var transcoorded = component.transcoordP2S(point.x, point.y);
46
+ var round = ((transcoorded.x - left) / (width / 2)) * 100;
47
+ round = safeRound(round, width, height);
48
+ component.set({ round });
49
+ }
50
+ };
51
+ let StockerCarrierBar = class StockerCarrierBar extends ParentObjectMixin(RectPath(Shape)) {
52
+ static get nature() {
53
+ return NATURE;
54
+ }
55
+ /** StockerCarrierBar 의 parentObject 는 STOCKER. */
56
+ get parentObjectTypes() {
57
+ return ['STOCKER'];
58
+ }
59
+ get controls() {
60
+ var { left, top, width, round, height } = this.state;
61
+ round = round == undefined ? 0 : safeRound(round, width, height);
62
+ return [
63
+ {
64
+ x: left + (width / 2) * (round / 100),
65
+ y: top,
66
+ handler: controlHandler
67
+ }
68
+ ];
69
+ }
70
+ isIdentifiable() {
71
+ return false;
72
+ }
73
+ get segments() {
74
+ const { carrierFull = 0, carrierEmpty = 0, carrierEmptyEmpty = 0 } = this.state;
75
+ const total = carrierFull + carrierEmpty + carrierEmptyEmpty;
76
+ if (total === 0) {
77
+ return [
78
+ { label: 'Full', count: 0, ratio: 0, color: DEFAULT_COLORS.full },
79
+ { label: 'Empty', count: 0, ratio: 0, color: DEFAULT_COLORS.empty },
80
+ { label: 'Empty\nEmpty', count: 0, ratio: 0, color: DEFAULT_COLORS.emptyEmpty }
81
+ ];
82
+ }
83
+ return [
84
+ { label: 'Full', count: carrierFull, ratio: carrierFull / total, color: DEFAULT_COLORS.full },
85
+ { label: 'Empty', count: carrierEmpty, ratio: carrierEmpty / total, color: DEFAULT_COLORS.empty },
86
+ { label: 'Empty\nEmpty', count: carrierEmptyEmpty, ratio: carrierEmptyEmpty / total, color: DEFAULT_COLORS.emptyEmpty }
87
+ ];
88
+ }
89
+ render(context) {
90
+ const { width, height } = this.bounds;
91
+ if (width >= height) {
92
+ this.renderLandscape(context);
93
+ }
94
+ else {
95
+ this.renderPortrait(context);
96
+ }
97
+ }
98
+ renderPortrait(context) {
99
+ const { left, top, width, height } = this.bounds;
100
+ const { lineWidth, strokeStyle, round, fillStyle = 'white' } = this.state;
101
+ const segments = this.segments;
102
+ context.save();
103
+ context.translate(left, top);
104
+ // background
105
+ context.beginPath();
106
+ context.fillStyle = fillStyle;
107
+ context.roundRect(0, 0, width, height, round);
108
+ context.fill();
109
+ context.clip();
110
+ // segments (아래→위)
111
+ let y = height;
112
+ for (const seg of segments) {
113
+ const segHeight = height * seg.ratio;
114
+ if (segHeight <= 0)
115
+ continue;
116
+ y -= segHeight;
117
+ context.beginPath();
118
+ context.fillStyle = seg.color;
119
+ context.rect(0, y, width, segHeight);
120
+ context.fill();
121
+ // label
122
+ this._drawSegmentLabel(context, seg, 0, y, width, segHeight);
123
+ }
124
+ // outline
125
+ context.beginPath();
126
+ context.setLineDash([]);
127
+ context.strokeStyle = strokeStyle;
128
+ context.lineWidth = lineWidth;
129
+ context.roundRect(0, 0, width, height, round);
130
+ context.stroke();
131
+ context.translate(-left, -top);
132
+ context.restore();
133
+ }
134
+ renderLandscape(context) {
135
+ const { left, top, width, height } = this.bounds;
136
+ const { lineWidth, strokeStyle, round, fillStyle = 'white' } = this.state;
137
+ const segments = this.segments;
138
+ context.save();
139
+ context.translate(left, top);
140
+ // background
141
+ context.beginPath();
142
+ context.fillStyle = fillStyle;
143
+ context.roundRect(0, 0, width, height, round);
144
+ context.fill();
145
+ context.clip();
146
+ // segments (왼→오)
147
+ let x = 0;
148
+ for (const seg of segments) {
149
+ const segWidth = width * seg.ratio;
150
+ if (segWidth <= 0)
151
+ continue;
152
+ context.beginPath();
153
+ context.fillStyle = seg.color;
154
+ context.rect(x, 0, segWidth, height);
155
+ context.fill();
156
+ this._drawSegmentLabel(context, seg, x, 0, segWidth, height);
157
+ x += segWidth;
158
+ }
159
+ // outline
160
+ context.beginPath();
161
+ context.setLineDash([]);
162
+ context.strokeStyle = strokeStyle;
163
+ context.lineWidth = lineWidth;
164
+ context.roundRect(0, 0, width, height, round);
165
+ context.stroke();
166
+ context.translate(-left, -top);
167
+ context.restore();
168
+ }
169
+ _drawSegmentLabel(context, seg, x, y, w, h) {
170
+ const percent = Math.round(seg.ratio * 100);
171
+ const lines = seg.label.split('\n');
172
+ lines.push(`${percent}%`);
173
+ const fontSize = Math.max(9, Math.min(14, Math.min(w, h) * 0.22));
174
+ context.font = `bold ${fontSize}px sans-serif`;
175
+ context.fillStyle = '#333';
176
+ context.textAlign = 'center';
177
+ context.textBaseline = 'middle';
178
+ const lineHeight = fontSize * 1.2;
179
+ const totalHeight = lines.length * lineHeight;
180
+ const startY = y + (h - totalHeight) / 2 + lineHeight / 2;
181
+ for (let i = 0; i < lines.length; i++) {
182
+ context.fillText(lines[i], x + w / 2, startY + i * lineHeight);
183
+ }
184
+ }
185
+ onchangeData(after, before) {
186
+ const { CARRIER_FULL = 0, CARRIER_EMPTY = 0, CARRIER_EMPTY_EMPTY = 0 } = this.data && typeof this.data == 'object' ? this.data : {};
187
+ this.setState({
188
+ carrierFull: Number(CARRIER_FULL) || 0,
189
+ carrierEmpty: Number(CARRIER_EMPTY) || 0,
190
+ carrierEmptyEmpty: Number(CARRIER_EMPTY_EMPTY) || 0
191
+ });
192
+ }
193
+ };
194
+ StockerCarrierBar = __decorate([
195
+ sceneComponent('StockerCarrierBar')
196
+ ], StockerCarrierBar);
197
+ export default StockerCarrierBar;
198
+ //# sourceMappingURL=stocker-carrier-bar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stocker-carrier-bar.js","sourceRoot":"","sources":["../src/stocker-carrier-bar.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n ComponentNature,\n POSITION,\n RectPath,\n Shape,\n sceneComponent\n} from '@hatiolab/things-scene'\nimport { LEGEND_CARRIER } from './features/mcs-status-default'\nimport { safeRound } from './utils/safe-round'\nimport { ParentObjectMixin, ParentObjectMixinProperties } from './features/parent-object-mixin'\n\n/**\n * 캐리어 상태별 비율 게이지 (Full / Empty / EmptyEmpty)\n *\n * 스토커에 보관된 캐리어들의 상태 비율을 세그먼트 게이지로 표시한다.\n * Portrait(세로) 모드에서는 아래→위, Landscape(가로) 모드에서는 왼→오 방향으로 채운다.\n */\n\ninterface Segment {\n label: string\n count: number\n ratio: number\n color: string\n}\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n ...ParentObjectMixinProperties,\n {\n type: 'number',\n name: 'carrierFull',\n label: 'carrier-full'\n },\n {\n type: 'number',\n name: 'carrierEmpty',\n label: 'carrier-empty'\n },\n {\n type: 'number',\n name: 'carrierEmptyEmpty',\n label: 'carrier-empty-empty'\n },\n {\n type: 'number',\n label: 'round',\n name: 'round',\n property: {\n min: 0\n }\n }\n ]\n}\n\nconst DEFAULT_COLORS = {\n full: LEGEND_CARRIER['FULL'] || '#4AA7FE',\n empty: LEGEND_CARRIER['EMPTY'] || '#8BDA5B',\n emptyEmpty: LEGEND_CARRIER['EMPTYEMPTY'] || '#019D59'\n}\n\nvar controlHandler = {\n ondragmove: function (point: POSITION, index: number, component: Component) {\n var { left, top, width, height } = component.model\n\n var transcoorded = component.transcoordP2S(point.x, point.y)\n var round = ((transcoorded.x - left) / (width / 2)) * 100\n\n round = safeRound(round, width, height)\n\n component.set({ round })\n }\n}\n\n@sceneComponent('StockerCarrierBar')\nexport default class StockerCarrierBar extends ParentObjectMixin(RectPath(Shape)) {\n static get nature() {\n return NATURE\n }\n\n /** StockerCarrierBar 의 parentObject 는 STOCKER. */\n get parentObjectTypes(): string[] {\n return ['STOCKER']\n }\n\n get controls() {\n var { left, top, width, round, height } = this.state\n round = round == undefined ? 0 : safeRound(round, width, height)\n\n return [\n {\n x: left + (width / 2) * (round / 100),\n y: top,\n handler: controlHandler\n }\n ]\n }\n\n isIdentifiable() {\n return false\n }\n\n get segments(): Segment[] {\n const { carrierFull = 0, carrierEmpty = 0, carrierEmptyEmpty = 0 } = this.state\n const total = carrierFull + carrierEmpty + carrierEmptyEmpty\n\n if (total === 0) {\n return [\n { label: 'Full', count: 0, ratio: 0, color: DEFAULT_COLORS.full },\n { label: 'Empty', count: 0, ratio: 0, color: DEFAULT_COLORS.empty },\n { label: 'Empty\\nEmpty', count: 0, ratio: 0, color: DEFAULT_COLORS.emptyEmpty }\n ]\n }\n\n return [\n { label: 'Full', count: carrierFull, ratio: carrierFull / total, color: DEFAULT_COLORS.full },\n { label: 'Empty', count: carrierEmpty, ratio: carrierEmpty / total, color: DEFAULT_COLORS.empty },\n { label: 'Empty\\nEmpty', count: carrierEmptyEmpty, ratio: carrierEmptyEmpty / total, color: DEFAULT_COLORS.emptyEmpty }\n ]\n }\n\n render(context: CanvasRenderingContext2D) {\n const { width, height } = this.bounds\n\n if (width >= height) {\n this.renderLandscape(context)\n } else {\n this.renderPortrait(context)\n }\n }\n\n renderPortrait(context: CanvasRenderingContext2D) {\n const { left, top, width, height } = this.bounds\n const { lineWidth, strokeStyle, round, fillStyle = 'white' } = this.state\n const segments = this.segments\n\n context.save()\n context.translate(left, top)\n\n // background\n context.beginPath()\n context.fillStyle = fillStyle\n context.roundRect(0, 0, width, height, round)\n context.fill()\n context.clip()\n\n // segments (아래→위)\n let y = height\n for (const seg of segments) {\n const segHeight = height * seg.ratio\n if (segHeight <= 0) continue\n\n y -= segHeight\n\n context.beginPath()\n context.fillStyle = seg.color\n context.rect(0, y, width, segHeight)\n context.fill()\n\n // label\n this._drawSegmentLabel(context, seg, 0, y, width, segHeight)\n }\n\n // outline\n context.beginPath()\n context.setLineDash([])\n context.strokeStyle = strokeStyle\n context.lineWidth = lineWidth\n context.roundRect(0, 0, width, height, round)\n context.stroke()\n\n context.translate(-left, -top)\n context.restore()\n }\n\n renderLandscape(context: CanvasRenderingContext2D) {\n const { left, top, width, height } = this.bounds\n const { lineWidth, strokeStyle, round, fillStyle = 'white' } = this.state\n const segments = this.segments\n\n context.save()\n context.translate(left, top)\n\n // background\n context.beginPath()\n context.fillStyle = fillStyle\n context.roundRect(0, 0, width, height, round)\n context.fill()\n context.clip()\n\n // segments (왼→오)\n let x = 0\n for (const seg of segments) {\n const segWidth = width * seg.ratio\n if (segWidth <= 0) continue\n\n context.beginPath()\n context.fillStyle = seg.color\n context.rect(x, 0, segWidth, height)\n context.fill()\n\n this._drawSegmentLabel(context, seg, x, 0, segWidth, height)\n\n x += segWidth\n }\n\n // outline\n context.beginPath()\n context.setLineDash([])\n context.strokeStyle = strokeStyle\n context.lineWidth = lineWidth\n context.roundRect(0, 0, width, height, round)\n context.stroke()\n\n context.translate(-left, -top)\n context.restore()\n }\n\n private _drawSegmentLabel(\n context: CanvasRenderingContext2D,\n seg: Segment,\n x: number,\n y: number,\n w: number,\n h: number\n ) {\n const percent = Math.round(seg.ratio * 100)\n const lines = seg.label.split('\\n')\n lines.push(`${percent}%`)\n\n const fontSize = Math.max(9, Math.min(14, Math.min(w, h) * 0.22))\n context.font = `bold ${fontSize}px sans-serif`\n context.fillStyle = '#333'\n context.textAlign = 'center'\n context.textBaseline = 'middle'\n\n const lineHeight = fontSize * 1.2\n const totalHeight = lines.length * lineHeight\n const startY = y + (h - totalHeight) / 2 + lineHeight / 2\n\n for (let i = 0; i < lines.length; i++) {\n context.fillText(lines[i], x + w / 2, startY + i * lineHeight)\n }\n }\n\n onchangeData(after: Record<string, any>, before: Record<string, any>): void {\n const {\n CARRIER_FULL = 0,\n CARRIER_EMPTY = 0,\n CARRIER_EMPTY_EMPTY = 0\n } = this.data && typeof this.data == 'object' ? this.data : {}\n\n this.setState({\n carrierFull: Number(CARRIER_FULL) || 0,\n carrierEmpty: Number(CARRIER_EMPTY) || 0,\n carrierEmptyEmpty: Number(CARRIER_EMPTY_EMPTY) || 0\n })\n }\n}\n"]}
package/dist/stocker.js CHANGED
@@ -33,9 +33,15 @@ let Stocker = class Stocker extends MCSTransport {
33
33
  }
34
34
  containable(component) {
35
35
  return (super.containable(component) ||
36
- ['Crane', 'Shelf', 'Port', 'MCSGaugeCapacityBar', 'StockerCapacityBar', 'ZoneCapacityBar'].includes(component.state.type));
36
+ ['Crane', 'CraneRail', 'Shelf', 'Port', 'MCSGaugeCapacityBar', 'StockerCapacityBar', 'StockerCarrierBar', 'StockerAbnormalBar', 'ZoneCapacityBar'].includes(component.state.type));
37
37
  }
38
38
  onchangeData(after, before) {
39
+ /* MCSStatusMixin.onchangeData 의 statusColor → state.fillStyle 동기화 로직을
40
+ * 호출. 3D 경로에서는 mesh material 의 color 가 build 시점 한 번 결정되므로
41
+ * 데이터 변경 시 fillStyle 이 갱신되어야 MCSRealObject3D.onchange 의
42
+ * 'fillStyle in after' 분기를 타고 mesh rebuild 가 발생한다.
43
+ * (2D 는 render() 가 매 프레임 statusColor getter 를 직접 사용하므로 영향 없음.) */
44
+ super.onchangeData(after, before);
39
45
  /* non-identifiable component 즉, StockerCapacityBar 에게 데이터를 전달함 */
40
46
  this.components.filter(component => !component.isIdentifiable()).forEach(component => (component.data = this.data));
41
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"stocker.js","sourceRoot":"","sources":["../src/stocker.ts"],"names":[],"mappings":";AAAA,OAAO,EAA0C,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC/F,OAAO,YAAY,MAAM,iBAAiB,CAAA;AAE1C,MAAM,MAAM,GAAoB;IAC9B,OAAO,EAAE,KAAK;IACd,SAAS,EAAE,IAAI;IACf,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,CAAC,GAAG,YAAY,CAAC,UAAU,CAAC;CACzC,CAAA;AAED,mEAAmE;AAEnE,wCAAwC;AACxC,oBAAoB;AACpB,wCAAwC;AACxC,cAAc;AACd,0CAA0C;AAC1C,sCAAsC;AACtC,6DAA6D;AAC7D,wBAAwB;AACxB,wGAAwG;AACxG,0EAA0E;AAC1E,QAAQ;AACR,8CAA8C;AAC9C,wBAAwB;AACxB,MAAM;AACN,uBAAuB;AACvB,IAAI;AAGW,IAAM,OAAO,GAAb,MAAM,OAAQ,SAAQ,YAAY;IAC/C,MAAM,KAAK,MAAM;QACf,OAAO,MAAM,CAAA;IACf,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC,IAAI,CAAC,iBAAiB,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAA;IACjE,CAAC;IAED,WAAW,CAAC,SAAoB;QAC9B,OAAO,CACL,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC;YAC5B,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,iBAAiB,CAAC,CAAC,QAAQ,CACjG,SAAS,CAAC,KAAK,CAAC,IAAI,CACrB,CACF,CAAA;IACH,CAAC;IAED,YAAY,CAAC,KAAiB,EAAE,MAAkB;QAChD,kEAAkE;QAClE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACrH,CAAC;CACF,CAAA;AAtBoB,OAAO;IAD3B,cAAc,CAAC,SAAS,CAAC;GACL,OAAO,CAsB3B;eAtBoB,OAAO","sourcesContent":["import { Component, ComponentNature, Properties, sceneComponent } from '@hatiolab/things-scene'\nimport MCSTransport from './mcs-transport'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [...MCSTransport.properties]\n}\n\n// const capacity = { ko: 'Capacity', en: 'Capacity', zh_CN: '容量' }\n\n// export function getLocaleLanguage() {\n// let localeValue\n// let nameOfCookie = 'miipLang' + '='\n// let x = 0\n// while (x <= document.cookie.length) {\n// let y = x + nameOfCookie.length\n// if (document.cookie.substring(x, y) == nameOfCookie) {\n// let endOfCookie\n// if ((endOfCookie = document.cookie.indexOf(';', y)) == -1) endOfCookie = document.cookie.length\n// localeValue = unescape(document.cookie.substring(y, endOfCookie))\n// }\n// x = document.cookie.indexOf(' ', x) + 1\n// if (x == 0) break\n// }\n// return localeValue\n// }\n\n@sceneComponent('STOCKER')\nexport default class Stocker extends MCSTransport {\n static get nature() {\n return NATURE\n }\n\n getLegendFallback() {\n return this.root.stokerLegendTheme || super.getLegendFallback()\n }\n\n containable(component: Component) {\n return (\n super.containable(component) ||\n ['Crane', 'Shelf', 'Port', 'MCSGaugeCapacityBar', 'StockerCapacityBar', 'ZoneCapacityBar'].includes(\n component.state.type\n )\n )\n }\n\n onchangeData(after: Properties, before: Properties): void {\n /* non-identifiable component 즉, StockerCapacityBar 에게 데이터를 전달함 */\n this.components.filter(component => !component.isIdentifiable()).forEach(component => (component.data = this.data))\n }\n}\n"]}
1
+ {"version":3,"file":"stocker.js","sourceRoot":"","sources":["../src/stocker.ts"],"names":[],"mappings":";AAAA,OAAO,EAA0C,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAC/F,OAAO,YAAY,MAAM,iBAAiB,CAAA;AAE1C,MAAM,MAAM,GAAoB;IAC9B,OAAO,EAAE,KAAK;IACd,SAAS,EAAE,IAAI;IACf,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,CAAC,GAAG,YAAY,CAAC,UAAU,CAAC;CACzC,CAAA;AAED,mEAAmE;AAEnE,wCAAwC;AACxC,oBAAoB;AACpB,wCAAwC;AACxC,cAAc;AACd,0CAA0C;AAC1C,sCAAsC;AACtC,6DAA6D;AAC7D,wBAAwB;AACxB,wGAAwG;AACxG,0EAA0E;AAC1E,QAAQ;AACR,8CAA8C;AAC9C,wBAAwB;AACxB,MAAM;AACN,uBAAuB;AACvB,IAAI;AAGW,IAAM,OAAO,GAAb,MAAM,OAAQ,SAAQ,YAAY;IAC/C,MAAM,KAAK,MAAM;QACf,OAAO,MAAM,CAAA;IACf,CAAC;IAED,iBAAiB;QACf,OAAQ,IAAI,CAAC,IAAY,CAAC,iBAAiB,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAA;IAC1E,CAAC;IAED,WAAW,CAAC,SAAoB;QAC9B,OAAO,CACL,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC;YAC5B,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,iBAAiB,CAAC,CAAC,QAAQ,CACzJ,SAAS,CAAC,KAAK,CAAC,IAAI,CACrB,CACF,CAAA;IACH,CAAC;IAED,YAAY,CAAC,KAA0B,EAAE,MAA2B;QAClE;;;;0EAIkE;QAClE,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QAEjC,kEAAkE;QAClE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACrH,CAAC;CACF,CAAA;AA7BoB,OAAO;IAD3B,cAAc,CAAC,SAAS,CAAC;GACL,OAAO,CA6B3B;eA7BoB,OAAO","sourcesContent":["import { Component, ComponentNature, Properties, sceneComponent } from '@hatiolab/things-scene'\nimport MCSTransport from './mcs-transport'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [...MCSTransport.properties]\n}\n\n// const capacity = { ko: 'Capacity', en: 'Capacity', zh_CN: '容量' }\n\n// export function getLocaleLanguage() {\n// let localeValue\n// let nameOfCookie = 'miipLang' + '='\n// let x = 0\n// while (x <= document.cookie.length) {\n// let y = x + nameOfCookie.length\n// if (document.cookie.substring(x, y) == nameOfCookie) {\n// let endOfCookie\n// if ((endOfCookie = document.cookie.indexOf(';', y)) == -1) endOfCookie = document.cookie.length\n// localeValue = unescape(document.cookie.substring(y, endOfCookie))\n// }\n// x = document.cookie.indexOf(' ', x) + 1\n// if (x == 0) break\n// }\n// return localeValue\n// }\n\n@sceneComponent('STOCKER')\nexport default class Stocker extends MCSTransport {\n static get nature() {\n return NATURE\n }\n\n getLegendFallback() {\n return (this.root as any).stokerLegendTheme || super.getLegendFallback()\n }\n\n containable(component: Component) {\n return (\n super.containable(component) ||\n ['Crane', 'CraneRail', 'Shelf', 'Port', 'MCSGaugeCapacityBar', 'StockerCapacityBar', 'StockerCarrierBar', 'StockerAbnormalBar', 'ZoneCapacityBar'].includes(\n component.state.type\n )\n )\n }\n\n onchangeData(after: Record<string, any>, before: Record<string, any>): void {\n /* MCSStatusMixin.onchangeData 의 statusColor → state.fillStyle 동기화 로직을\n * 호출. 3D 경로에서는 mesh material 의 color 가 build 시점 한 번 결정되므로\n * 데이터 변경 시 fillStyle 이 갱신되어야 MCSRealObject3D.onchange 의\n * 'fillStyle in after' 분기를 타고 mesh rebuild 가 발생한다.\n * (2D 는 render() 가 매 프레임 statusColor getter 를 직접 사용하므로 영향 없음.) */\n super.onchangeData(after, before)\n\n /* non-identifiable component 즉, StockerCapacityBar 에게 데이터를 전달함 */\n this.components.filter(component => !component.isIdentifiable()).forEach(component => (component.data = this.data))\n }\n}\n"]}
@@ -0,0 +1,30 @@
1
+ const icon = new URL('../../icons/backdrop.png', import.meta.url).href;
2
+ export default {
3
+ type: 'backdrop',
4
+ description: '3D scene backdrop — 6-sided envelope (4 walls + floor + ceiling)',
5
+ group: ['etc'],
6
+ icon,
7
+ model: {
8
+ type: 'backdrop',
9
+ top: 0,
10
+ left: 0,
11
+ width: 3000,
12
+ height: 2400,
13
+ // depth seeded on creation as min(width, height) by Backdrop's
14
+ // `_syncFromRoot(seedDepth=true)`. Editable via property panel
15
+ // afterward — board-resize syncs won't override it.
16
+ fitToBoard: true,
17
+ alpha: 1,
18
+ // 6면 합성 상태. 비어있으면 backdrop 컴포넌트의 default 가 적용됨
19
+ // (벽 4면 = #dde2e8/0.35, 바닥 = #9c9c9c/1.0, 천장 = #e8e8ec/1.0).
20
+ faces: {
21
+ east: { fillStyle: '#dde2e8', visible: true, alpha: 0.35 },
22
+ west: { fillStyle: '#dde2e8', visible: true, alpha: 0.35 },
23
+ north: { fillStyle: '#dde2e8', visible: true, alpha: 0.35 },
24
+ south: { fillStyle: '#dde2e8', visible: true, alpha: 0.35 },
25
+ floor: { fillStyle: '#9c9c9c', visible: true, alpha: 1.0 },
26
+ ceiling: { fillStyle: '#e8e8ec', visible: true, alpha: 1.0 }
27
+ }
28
+ }
29
+ };
30
+ //# sourceMappingURL=backdrop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backdrop.js","sourceRoot":"","sources":["../../src/templates/backdrop.ts"],"names":[],"mappings":"AAAA,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,0BAA0B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAA;AAEtE,eAAe;IACb,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,kEAAkE;IAC/E,KAAK,EAAE,CAAC,KAAK,CAAC;IACd,IAAI;IACJ,KAAK,EAAE;QACL,IAAI,EAAE,UAAU;QAChB,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,CAAC;QACP,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,+DAA+D;QAC/D,+DAA+D;QAC/D,oDAAoD;QACpD,UAAU,EAAE,IAAI;QAChB,KAAK,EAAE,CAAC;QACR,+CAA+C;QAC/C,6DAA6D;QAC7D,KAAK,EAAE;YACL,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;YAC1D,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;YAC1D,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;YAC3D,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;YAC3D,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE;YAC1D,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE;SAC7D;KACF;CACF,CAAA","sourcesContent":["const icon = new URL('../../icons/backdrop.png', import.meta.url).href\n\nexport default {\n type: 'backdrop',\n description: '3D scene backdrop — 6-sided envelope (4 walls + floor + ceiling)',\n group: ['etc'],\n icon,\n model: {\n type: 'backdrop',\n top: 0,\n left: 0,\n width: 3000,\n height: 2400,\n // depth seeded on creation as min(width, height) by Backdrop's\n // `_syncFromRoot(seedDepth=true)`. Editable via property panel\n // afterward — board-resize syncs won't override it.\n fitToBoard: true,\n alpha: 1,\n // 6면 합성 상태. 비어있으면 backdrop 컴포넌트의 default 가 적용됨\n // (벽 4면 = #dde2e8/0.35, 바닥 = #9c9c9c/1.0, 천장 = #e8e8ec/1.0).\n faces: {\n east: { fillStyle: '#dde2e8', visible: true, alpha: 0.35 },\n west: { fillStyle: '#dde2e8', visible: true, alpha: 0.35 },\n north: { fillStyle: '#dde2e8', visible: true, alpha: 0.35 },\n south: { fillStyle: '#dde2e8', visible: true, alpha: 0.35 },\n floor: { fillStyle: '#9c9c9c', visible: true, alpha: 1.0 },\n ceiling: { fillStyle: '#e8e8ec', visible: true, alpha: 1.0 }\n }\n }\n}\n"]}
@@ -0,0 +1,21 @@
1
+ const icon = new URL('../../icons/decal.png', import.meta.url).href;
2
+ export default {
3
+ type: 'decal',
4
+ description: 'flat surface decal (3D-only) — floor zone paint, path lanes, signage',
5
+ group: ['etc'],
6
+ icon,
7
+ model: {
8
+ type: 'decal',
9
+ top: 100,
10
+ left: 100,
11
+ width: 200,
12
+ height: 200,
13
+ zPos: 0,
14
+ depth: 0,
15
+ fillStyle: '#cccccc',
16
+ strokeStyle: '#999999',
17
+ lineWidth: 1,
18
+ alpha: 1
19
+ }
20
+ };
21
+ //# sourceMappingURL=decal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decal.js","sourceRoot":"","sources":["../../src/templates/decal.ts"],"names":[],"mappings":"AAAA,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,uBAAuB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAA;AAEnE,eAAe;IACb,IAAI,EAAE,OAAO;IACb,WAAW,EAAE,sEAAsE;IACnF,KAAK,EAAE,CAAC,KAAK,CAAC;IACd,IAAI;IACJ,KAAK,EAAE;QACL,IAAI,EAAE,OAAO;QACb,GAAG,EAAE,GAAG;QACR,IAAI,EAAE,GAAG;QACT,KAAK,EAAE,GAAG;QACV,MAAM,EAAE,GAAG;QACX,IAAI,EAAE,CAAC;QACP,KAAK,EAAE,CAAC;QACR,SAAS,EAAE,SAAS;QACpB,WAAW,EAAE,SAAS;QACtB,SAAS,EAAE,CAAC;QACZ,KAAK,EAAE,CAAC;KACT;CACF,CAAA","sourcesContent":["const icon = new URL('../../icons/decal.png', import.meta.url).href\n\nexport default {\n type: 'decal',\n description: 'flat surface decal (3D-only) — floor zone paint, path lanes, signage',\n group: ['etc'],\n icon,\n model: {\n type: 'decal',\n top: 100,\n left: 100,\n width: 200,\n height: 200,\n zPos: 0,\n depth: 0,\n fillStyle: '#cccccc',\n strokeStyle: '#999999',\n lineWidth: 1,\n alpha: 1\n }\n}\n"]}
@@ -13,9 +13,12 @@ import Shelf from './shelf';
13
13
  import agvLine from './agv-line';
14
14
  import ohtLine from './oht-line';
15
15
  import conveyor from './conveyor';
16
+ import Scanner from './scanner';
16
17
  import Node from './node';
17
18
  import DataSubscription from './data-subscription';
18
19
  import FloatingContainer from './floating-container';
20
+ import Decal from './decal';
21
+ import Backdrop from './backdrop';
19
22
  export default [
20
23
  StockerCapacityBar,
21
24
  ZoneCapacityBar,
@@ -32,8 +35,11 @@ export default [
32
35
  Crane,
33
36
  Shelf,
34
37
  Port,
38
+ Scanner,
35
39
  Node,
36
40
  FloatingContainer,
37
- DataSubscription
41
+ DataSubscription,
42
+ Decal,
43
+ Backdrop
38
44
  ];
39
45
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,MAAM,wBAAwB,CAAA;AACvD,OAAO,eAAe,MAAM,qBAAqB,CAAA;AACjD,OAAO,QAAQ,MAAM,aAAa,CAAA;AAElC,OAAO,GAAG,MAAM,OAAO,CAAA;AACvB,OAAO,MAAM,MAAM,UAAU,CAAA;AAC7B,OAAO,SAAS,MAAM,aAAa,CAAA;AACnC,OAAO,GAAG,MAAM,OAAO,CAAA;AACvB,OAAO,OAAO,MAAM,WAAW,CAAA;AAE/B,OAAO,OAAO,MAAM,WAAW,CAAA;AAC/B,OAAO,IAAI,MAAM,QAAQ,CAAA;AACzB,OAAO,KAAK,MAAM,SAAS,CAAA;AAC3B,OAAO,KAAK,MAAM,SAAS,CAAA;AAE3B,OAAO,OAAO,MAAM,YAAY,CAAA;AAChC,OAAO,OAAO,MAAM,YAAY,CAAA;AAChC,OAAO,QAAQ,MAAM,YAAY,CAAA;AAEjC,OAAO,IAAI,MAAM,QAAQ,CAAA;AACzB,OAAO,gBAAgB,MAAM,qBAAqB,CAAA;AAClD,OAAO,iBAAiB,MAAM,sBAAsB,CAAA;AAEpD,eAAe;IACb,kBAAkB;IAClB,eAAe;IACf,QAAQ;IAER,MAAM;IACN,OAAO;IACP,SAAS;IAET,OAAO;IACP,OAAO;IACP,QAAQ;IAER,GAAG;IACH,GAAG;IACH,OAAO;IACP,KAAK;IACL,KAAK;IACL,IAAI;IAEJ,IAAI;IACJ,iBAAiB;IACjB,gBAAgB;CACjB,CAAA","sourcesContent":["import StockerCapacityBar from './stocker-capacity-bar'\nimport ZoneCapacityBar from './zone-capacity-bar'\nimport PortFlow from './port-flow'\n\nimport AGV from './agv'\nimport Buffer from './buffer'\nimport Equipment from './equipment'\nimport OHT from './oht'\nimport Stocker from './stocker'\n\nimport Shuttle from './shuttle'\nimport Port from './port'\nimport Crane from './crane'\nimport Shelf from './shelf'\n\nimport agvLine from './agv-line'\nimport ohtLine from './oht-line'\nimport conveyor from './conveyor'\n\nimport Node from './node'\nimport DataSubscription from './data-subscription'\nimport FloatingContainer from './floating-container'\n\nexport default [\n StockerCapacityBar,\n ZoneCapacityBar,\n PortFlow,\n\n Buffer,\n Stocker,\n Equipment,\n\n agvLine,\n ohtLine,\n conveyor,\n\n AGV,\n OHT,\n Shuttle,\n Crane,\n Shelf,\n Port,\n\n Node,\n FloatingContainer,\n DataSubscription\n]\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,MAAM,wBAAwB,CAAA;AACvD,OAAO,eAAe,MAAM,qBAAqB,CAAA;AACjD,OAAO,QAAQ,MAAM,aAAa,CAAA;AAElC,OAAO,GAAG,MAAM,OAAO,CAAA;AACvB,OAAO,MAAM,MAAM,UAAU,CAAA;AAC7B,OAAO,SAAS,MAAM,aAAa,CAAA;AACnC,OAAO,GAAG,MAAM,OAAO,CAAA;AACvB,OAAO,OAAO,MAAM,WAAW,CAAA;AAE/B,OAAO,OAAO,MAAM,WAAW,CAAA;AAC/B,OAAO,IAAI,MAAM,QAAQ,CAAA;AACzB,OAAO,KAAK,MAAM,SAAS,CAAA;AAC3B,OAAO,KAAK,MAAM,SAAS,CAAA;AAE3B,OAAO,OAAO,MAAM,YAAY,CAAA;AAChC,OAAO,OAAO,MAAM,YAAY,CAAA;AAChC,OAAO,QAAQ,MAAM,YAAY,CAAA;AAEjC,OAAO,OAAO,MAAM,WAAW,CAAA;AAC/B,OAAO,IAAI,MAAM,QAAQ,CAAA;AACzB,OAAO,gBAAgB,MAAM,qBAAqB,CAAA;AAClD,OAAO,iBAAiB,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,MAAM,SAAS,CAAA;AAC3B,OAAO,QAAQ,MAAM,YAAY,CAAA;AAEjC,eAAe;IACb,kBAAkB;IAClB,eAAe;IACf,QAAQ;IAER,MAAM;IACN,OAAO;IACP,SAAS;IAET,OAAO;IACP,OAAO;IACP,QAAQ;IAER,GAAG;IACH,GAAG;IACH,OAAO;IACP,KAAK;IACL,KAAK;IACL,IAAI;IAEJ,OAAO;IACP,IAAI;IACJ,iBAAiB;IACjB,gBAAgB;IAChB,KAAK;IACL,QAAQ;CACT,CAAA","sourcesContent":["import StockerCapacityBar from './stocker-capacity-bar'\nimport ZoneCapacityBar from './zone-capacity-bar'\nimport PortFlow from './port-flow'\n\nimport AGV from './agv'\nimport Buffer from './buffer'\nimport Equipment from './equipment'\nimport OHT from './oht'\nimport Stocker from './stocker'\n\nimport Shuttle from './shuttle'\nimport Port from './port'\nimport Crane from './crane'\nimport Shelf from './shelf'\n\nimport agvLine from './agv-line'\nimport ohtLine from './oht-line'\nimport conveyor from './conveyor'\n\nimport Scanner from './scanner'\nimport Node from './node'\nimport DataSubscription from './data-subscription'\nimport FloatingContainer from './floating-container'\nimport Decal from './decal'\nimport Backdrop from './backdrop'\n\nexport default [\n StockerCapacityBar,\n ZoneCapacityBar,\n PortFlow,\n\n Buffer,\n Stocker,\n Equipment,\n\n agvLine,\n ohtLine,\n conveyor,\n\n AGV,\n OHT,\n Shuttle,\n Crane,\n Shelf,\n Port,\n\n Scanner,\n Node,\n FloatingContainer,\n DataSubscription,\n Decal,\n Backdrop\n]\n"]}
@@ -0,0 +1,20 @@
1
+ const icon = new URL('../../icons/equipment.png', import.meta.url).href;
2
+ export default {
3
+ type: 'Scanner',
4
+ description: 'Fixed mount barcode/QR scanner',
5
+ group: ['etc'],
6
+ icon,
7
+ model: {
8
+ type: 'Scanner',
9
+ x1: 100,
10
+ y1: 100,
11
+ x2: 130,
12
+ y2: 110,
13
+ x3: 100,
14
+ y3: 120,
15
+ strokeStyle: '#333',
16
+ fillStyle: 'red',
17
+ lineWidth: 1
18
+ }
19
+ };
20
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/templates/scanner.ts"],"names":[],"mappings":"AAAA,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,2BAA2B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAA;AAEvE,eAAe;IACb,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,gCAAgC;IAC7C,KAAK,EAAE,CAAC,KAAK,CAAC;IACd,IAAI;IACJ,KAAK,EAAE;QACL,IAAI,EAAE,SAAS;QACf,EAAE,EAAE,GAAG;QACP,EAAE,EAAE,GAAG;QACP,EAAE,EAAE,GAAG;QACP,EAAE,EAAE,GAAG;QACP,EAAE,EAAE,GAAG;QACP,EAAE,EAAE,GAAG;QACP,WAAW,EAAE,MAAM;QACnB,SAAS,EAAE,KAAK;QAChB,SAAS,EAAE,CAAC;KACb;CACF,CAAA","sourcesContent":["const icon = new URL('../../icons/equipment.png', import.meta.url).href\n\nexport default {\n type: 'Scanner',\n description: 'Fixed mount barcode/QR scanner',\n group: ['etc'],\n icon,\n model: {\n type: 'Scanner',\n x1: 100,\n y1: 100,\n x2: 130,\n y2: 110,\n x3: 100,\n y3: 120,\n strokeStyle: '#333',\n fillStyle: 'red',\n lineWidth: 1\n }\n}\n"]}