@fmsim/machine 3.0.0-beta.3 → 3.0.0-beta.5

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 (94) hide show
  1. package/dist/agv-line.js +2 -2
  2. package/dist/agv-line.js.map +1 -1
  3. package/dist/agv.js +6 -2
  4. package/dist/agv.js.map +1 -1
  5. package/dist/buffer.js +2 -2
  6. package/dist/buffer.js.map +1 -1
  7. package/dist/conveyor-join.js +2 -2
  8. package/dist/conveyor-join.js.map +1 -1
  9. package/dist/conveyor.js +2 -2
  10. package/dist/conveyor.js.map +1 -1
  11. package/dist/crane.js +2 -2
  12. package/dist/crane.js.map +1 -1
  13. package/dist/equipment.js +2 -2
  14. package/dist/equipment.js.map +1 -1
  15. package/dist/factories/conveyor-3d.js +2 -2
  16. package/dist/factories/conveyor-3d.js.map +1 -1
  17. package/dist/factories/machine-3d.js +12 -12
  18. package/dist/factories/machine-3d.js.map +1 -1
  19. package/dist/factories/oht-3d.js +3 -4
  20. package/dist/factories/oht-3d.js.map +1 -1
  21. package/dist/features/legend-panel.js +29 -0
  22. package/dist/features/legend-panel.js.map +1 -0
  23. package/dist/features/legend-rows.js +88 -0
  24. package/dist/features/legend-rows.js.map +1 -0
  25. package/dist/features/lv-figures.js +137 -0
  26. package/dist/features/lv-figures.js.map +1 -0
  27. package/dist/features/lv-heights.js +20 -0
  28. package/dist/features/lv-heights.js.map +1 -0
  29. package/dist/features/mcs-status-default.js +3 -49
  30. package/dist/features/mcs-status-default.js.map +1 -1
  31. package/dist/features/oht-rail.js +32 -0
  32. package/dist/features/oht-rail.js.map +1 -0
  33. package/dist/features/vehicle-travel.js +90 -0
  34. package/dist/features/vehicle-travel.js.map +1 -0
  35. package/dist/index.js +4 -0
  36. package/dist/index.js.map +1 -1
  37. package/dist/mcs-carrier-holder.js +19 -25
  38. package/dist/mcs-carrier-holder.js.map +1 -1
  39. package/dist/mcs-machine.js +10 -1
  40. package/dist/mcs-machine.js.map +1 -1
  41. package/dist/mcs-unit.js +10 -1
  42. package/dist/mcs-unit.js.map +1 -1
  43. package/dist/mcs-vehicle.js +2 -60
  44. package/dist/mcs-vehicle.js.map +1 -1
  45. package/dist/oht-line.js +7 -3
  46. package/dist/oht-line.js.map +1 -1
  47. package/dist/oht.js +2 -2
  48. package/dist/oht.js.map +1 -1
  49. package/dist/port.js +2 -2
  50. package/dist/port.js.map +1 -1
  51. package/dist/scene/root-container-override.js +15 -210
  52. package/dist/scene/root-container-override.js.map +1 -1
  53. package/dist/shelf.js +2 -2
  54. package/dist/shelf.js.map +1 -1
  55. package/dist/shuttle.js +2 -2
  56. package/dist/shuttle.js.map +1 -1
  57. package/dist/stocker.js +2 -2
  58. package/dist/stocker.js.map +1 -1
  59. package/dist/tsconfig.tsbuildinfo +1 -1
  60. package/package.json +5 -4
  61. package/src/agv-line.ts +2 -2
  62. package/src/agv.ts +7 -2
  63. package/src/buffer.ts +2 -2
  64. package/src/conveyor-join.ts +2 -2
  65. package/src/conveyor.ts +2 -2
  66. package/src/crane.ts +2 -2
  67. package/src/equipment.ts +2 -2
  68. package/src/factories/conveyor-3d.ts +2 -2
  69. package/src/factories/machine-3d.ts +11 -12
  70. package/src/factories/oht-3d.ts +3 -5
  71. package/src/features/legend-panel.ts +31 -0
  72. package/src/features/legend-rows.ts +86 -0
  73. package/src/features/lv-figures.ts +144 -0
  74. package/src/features/lv-heights.ts +22 -0
  75. package/src/features/mcs-status-default.ts +3 -53
  76. package/src/features/oht-rail.ts +31 -0
  77. package/src/features/vehicle-travel.ts +97 -0
  78. package/src/index.ts +4 -0
  79. package/src/mcs-carrier-holder.ts +17 -26
  80. package/src/mcs-machine.ts +12 -1
  81. package/src/mcs-unit.ts +12 -1
  82. package/src/mcs-vehicle.ts +3 -71
  83. package/src/oht-line.ts +7 -3
  84. package/src/oht.ts +2 -2
  85. package/src/port.ts +2 -2
  86. package/src/scene/root-container-override.ts +15 -207
  87. package/src/shelf.ts +2 -2
  88. package/src/shuttle.ts +2 -2
  89. package/src/stocker.ts +2 -2
  90. package/translations/en.json +7 -1
  91. package/translations/ja.json +7 -1
  92. package/translations/ko.json +7 -1
  93. package/translations/ms.json +7 -1
  94. package/translations/zh.json +7 -1
package/dist/agv-line.js CHANGED
@@ -17,8 +17,8 @@ let AGVLine = class AGVLine extends MCSTransport {
17
17
  get auxColor() {
18
18
  return '#333';
19
19
  }
20
- getLegendFallback() {
21
- return this.root.agvlineLegendTheme || super.getLegendFallback();
20
+ get statusLegendRow() {
21
+ return 'agvline';
22
22
  }
23
23
  render(context) {
24
24
  const { left, top, width, height } = this.bounds;
@@ -1 +1 @@
1
- {"version":3,"file":"agv-line.js","sourceRoot":"","sources":["../src/agv-line.ts"],"names":[],"mappings":";AAAA,OAAO,EAA8B,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACnF,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;AAGc,IAAM,OAAO,GAAb,MAAM,OAAQ,SAAQ,YAAY;IAC/C,MAAM,KAAK,MAAM;QACf,OAAO,MAAM,CAAA;IACf,CAAC;IAED,WAAW,CAAC,SAAoB;QAC9B,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACvD,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,MAAM,CAAA;IACf,CAAC;IAED,iBAAiB;QACf,OAAQ,IAAI,CAAC,IAAY,CAAC,kBAAkB,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAA;IAC3E,CAAC;IAED,MAAM,CAAC,OAAiC;QACtC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAA;QAEhD,OAAO,CAAC,SAAS,EAAE,CAAA;QAEnB,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAE5B,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,WAAY,CAAA;QACrC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,QAAS,CAAA;QACpC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAExB,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;QAErC,IAAI,KAAK,GAAG,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YACpB,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;YACxB,gCAAgC;YAChC,oCAAoC;YACpC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;YACzB,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QAC/B,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YACpB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;YACzB,+BAA+B;YAC/B,oCAAoC;YACpC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;YACxB,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QAC/B,CAAC;QAED,OAAO,CAAC,MAAM,EAAE,CAAA;QAEhB,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAA;IAChC,CAAC;CACF,CAAA;AAlDoB,OAAO;IAD3B,cAAc,CAAC,SAAS,CAAC;GACL,OAAO,CAkD3B;eAlDoB,OAAO","sourcesContent":["import { Component, ComponentNature, 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@sceneComponent('AGVLine')\nexport default class AGVLine extends MCSTransport {\n static get nature() {\n return NATURE\n }\n\n containable(component: Component) {\n return ['AGV', 'Node'].includes(component.state.type)\n }\n\n get auxColor() {\n return '#333'\n }\n\n getLegendFallback() {\n return (this.root as any).agvlineLegendTheme || super.getLegendFallback()\n }\n\n render(context: CanvasRenderingContext2D) {\n const { left, top, width, height } = this.bounds\n\n context.beginPath()\n\n context.translate(left, top)\n\n context.fillStyle = this.statusColor!\n context.strokeStyle = this.auxColor!\n context.setLineDash([3])\n\n context.fillRect(0, 0, width, height)\n\n if (width > height) {\n context.moveTo(0, 0)\n context.lineTo(width, 0)\n // context.moveTo(0, height / 2)\n // context.lineTo(width, height / 2)\n context.moveTo(0, height)\n context.lineTo(width, height)\n } else {\n context.moveTo(0, 0)\n context.lineTo(0, height)\n // context.moveTo(width / 2, 0)\n // context.lineTo(width / 2, height)\n context.moveTo(width, 0)\n context.lineTo(width, height)\n }\n\n context.stroke()\n\n context.translate(-left, -top)\n }\n}\n"]}
1
+ {"version":3,"file":"agv-line.js","sourceRoot":"","sources":["../src/agv-line.ts"],"names":[],"mappings":";AAAA,OAAO,EAA8B,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACnF,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;AAGc,IAAM,OAAO,GAAb,MAAM,OAAQ,SAAQ,YAAY;IAC/C,MAAM,KAAK,MAAM;QACf,OAAO,MAAM,CAAA;IACf,CAAC;IAED,WAAW,CAAC,SAAoB;QAC9B,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACvD,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,MAAM,CAAA;IACf,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,MAAM,CAAC,OAAiC;QACtC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAA;QAEhD,OAAO,CAAC,SAAS,EAAE,CAAA;QAEnB,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAE5B,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,WAAY,CAAA;QACrC,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,QAAS,CAAA;QACpC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAExB,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;QAErC,IAAI,KAAK,GAAG,MAAM,EAAE,CAAC;YACnB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YACpB,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;YACxB,gCAAgC;YAChC,oCAAoC;YACpC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;YACzB,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QAC/B,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;YACpB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;YACzB,+BAA+B;YAC/B,oCAAoC;YACpC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;YACxB,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QAC/B,CAAC;QAED,OAAO,CAAC,MAAM,EAAE,CAAA;QAEhB,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAA;IAChC,CAAC;CACF,CAAA;AAlDoB,OAAO;IAD3B,cAAc,CAAC,SAAS,CAAC;GACL,OAAO,CAkD3B;eAlDoB,OAAO","sourcesContent":["import { Component, ComponentNature, 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@sceneComponent('AGVLine')\nexport default class AGVLine extends MCSTransport {\n static get nature() {\n return NATURE\n }\n\n containable(component: Component) {\n return ['AGV', 'Node'].includes(component.state.type)\n }\n\n get auxColor() {\n return '#333'\n }\n\n get statusLegendRow(): string {\n return 'agvline'\n }\n\n render(context: CanvasRenderingContext2D) {\n const { left, top, width, height } = this.bounds\n\n context.beginPath()\n\n context.translate(left, top)\n\n context.fillStyle = this.statusColor!\n context.strokeStyle = this.auxColor!\n context.setLineDash([3])\n\n context.fillRect(0, 0, width, height)\n\n if (width > height) {\n context.moveTo(0, 0)\n context.lineTo(width, 0)\n // context.moveTo(0, height / 2)\n // context.lineTo(width, height / 2)\n context.moveTo(0, height)\n context.lineTo(width, height)\n } else {\n context.moveTo(0, 0)\n context.lineTo(0, height)\n // context.moveTo(width / 2, 0)\n // context.lineTo(width / 2, height)\n context.moveTo(width, 0)\n context.lineTo(width, height)\n }\n\n context.stroke()\n\n context.translate(-left, -top)\n }\n}\n"]}
package/dist/agv.js CHANGED
@@ -31,8 +31,12 @@ let AGV = class AGV extends MCSVehicle {
31
31
  get parentObjectTypes() {
32
32
  return ['AGVLine'];
33
33
  }
34
- getLegendFallback() {
35
- return this.root.agvLegendTheme || super.getLegendFallback();
34
+ get statusLegendRow() {
35
+ return 'agv';
36
+ }
37
+ /** Its STATUS row and its battery's (the battery is the AGV's own: only a board with AGVs shows the row) */
38
+ get legendRowsUsed() {
39
+ return [...super.legendRowsUsed, 'battery-rate'];
36
40
  }
37
41
  getBatteryLegendFallback() {
38
42
  return this.root.batteryRateLegendTheme || BATTERY_RATE_LEGEND;
package/dist/agv.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"agv.js","sourceRoot":"","sources":["../src/agv.ts"],"names":[],"mappings":"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","sourcesContent":["import { ComponentNature, sceneComponent } from '@hatiolab/things-scene'\nimport { themesColorRange } from '@fmsim/api'\nimport MCSVehicle from './mcs-vehicle'\nimport { BATTERY_RATE_LEGEND, legendColor, legendRangeEntryOf } from './features/mcs-status-default'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n ...MCSVehicle.properties,\n {\n type: 'select',\n label: 'battery-rate-legend-name',\n name: 'batteryRateLegendName',\n property: {\n options: themesColorRange\n }\n }\n ]\n}\n\nconst GAP = 2\n\n@sceneComponent('AGV')\nexport default class AGV extends MCSVehicle {\n static get nature() {\n return NATURE\n }\n\n get auxColor() {\n return 'black'\n }\n\n /** AGV 의 parentObject 는 AGVLine. */\n get parentObjectTypes(): string[] {\n return ['AGVLine']\n }\n\n getLegendFallback() {\n return (this.root as any).agvLegendTheme || super.getLegendFallback()\n }\n\n getBatteryLegendFallback() {\n return (this.root as any).batteryRateLegendTheme || BATTERY_RATE_LEGEND\n }\n\n getBatteryLegendTheme() {\n const { batteryRateLegendName } = this.state\n\n if (batteryRateLegendName) {\n return (this.root as any)?.style?.[batteryRateLegendName]\n }\n }\n\n getBatteryColor(rate: number) {\n return legendColor(legendRangeEntryOf(rate, this.getBatteryLegendTheme() || this.getBatteryLegendFallback()))\n }\n\n render(ctx: CanvasRenderingContext2D) {\n var { left, top, width, height } = this.bounds\n\n ctx.translate(left, top)\n ctx.beginPath()\n\n // 작은 크기에서도 보이도록 최소 선 두께 설정\n const minLineWidth = 0.5\n const scaleFactor = Math.min(width, height) / 100\n const lineWidth = Math.max(minLineWidth, scaleFactor)\n\n ctx.strokeStyle = this.auxColor\n ctx.fillStyle = this.statusColor!\n ctx.lineWidth = lineWidth\n ctx.lineCap = 'round'\n ctx.setLineDash([])\n\n // 기본 사각형 그리기\n ctx.rect(1, 0, width - 2, height)\n ctx.rect(GAP + 1, GAP, width - (GAP + 1) * 2, height - GAP * 2)\n\n ctx.fill()\n ctx.stroke()\n\n ctx.beginPath()\n\n // 바퀴 그리기\n ctx.strokeStyle = 'black'\n\n ctx.moveTo(0, (height * 1) / 3)\n ctx.lineTo(0, (height * 2) / 3)\n ctx.moveTo(width, (height * 1) / 3)\n ctx.lineTo(width, (height * 2) / 3)\n\n ctx.stroke()\n\n ctx.translate(-left, -top)\n }\n\n // 사선 패턴을 그리는 함수\n drawHatchPattern(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) {\n // 6개의 빗금을 그리기 위한 간격 계산\n const spacing = (width + height) / 6\n\n // 선 두께 계산 (크기에 비례)\n const minLineWidth = 0.5\n const scaleFactor = Math.min(width, height) / 20 // 130에서 50으로 변경하여 더 두껍게\n const lineWidth = Math.max(minLineWidth, scaleFactor)\n\n ctx.beginPath()\n ctx.strokeStyle = 'black'\n ctx.lineWidth = lineWidth\n\n // 배터리 박스 내부로 클리핑 설정\n ctx.save()\n ctx.rect(x, y, width, height)\n ctx.clip()\n\n // 6개의 사선 패턴 그리기\n for (let i = 0; i < 6; i++) {\n const startX = x + i * spacing\n ctx.moveTo(startX, y)\n ctx.lineTo(startX - height, y + height)\n }\n\n ctx.stroke()\n // 클리핑 해제\n ctx.restore()\n }\n\n postrender(ctx: CanvasRenderingContext2D): void {\n super.postrender(ctx)\n\n const BATTERYRATE = this.data?.BATTERYRATE\n\n if (typeof BATTERYRATE === 'number') {\n const { left, top, width, height } = this.bounds\n ctx.translate(left, top)\n\n // 배터리 크기 및 위치 설정 (최소 크기 보장)\n const minBatteryHeight = 2\n const minBatteryWidth = 4\n const preferredHeight = height / 5\n const preferredWidth = (width * 3) / 4\n\n const batteryHeight = Math.max(minBatteryHeight, preferredHeight)\n const batteryWidth = Math.max(minBatteryWidth, preferredWidth)\n const batteryX = (width - batteryWidth) / 2\n const batteryY = (height - batteryHeight) * 1.1\n\n // 배터리 테두리 그리기 (크기에 비례한 선 두께)\n const minLineWidth = 0.5\n const scaleFactor = Math.min(width, height) / 100\n const lineWidth = Math.max(minLineWidth, scaleFactor)\n\n // 배터리 배경을 흰색으로 채우기\n ctx.fillStyle = 'white'\n ctx.fillRect(batteryX, batteryY, batteryWidth, batteryHeight)\n\n // 배터리 전체 영역에 사선 패턴 그리기\n this.drawHatchPattern(ctx, batteryX, batteryY, batteryWidth, batteryHeight)\n\n // 배터리 잔량 표시\n const fillWidth = (batteryWidth * BATTERYRATE) / 100\n\n // 배터리 잔량에 따른 색상 설정 - 테마 적용\n ctx.fillStyle = this.getBatteryColor(BATTERYRATE)\n\n // 배터리 잔량 영역 채우기\n ctx.fillRect(batteryX, batteryY, fillWidth, batteryHeight)\n\n // 배터리 테두리 다시 그리기\n ctx.beginPath()\n ctx.strokeStyle = 'black'\n ctx.lineWidth = lineWidth\n ctx.strokeRect(batteryX, batteryY, batteryWidth, batteryHeight)\n\n // 배터리 잔량 텍스트 표시\n const fontSize = batteryHeight * 0.8\n\n // 실제 렌더링될 텍스트 크기 계산\n const transform = ctx.getTransform()\n const scaleX = Math.sqrt(transform.m11 * transform.m11 + transform.m21 * transform.m21)\n const actualFontSize = (fontSize * (scaleX || 1)) / window.devicePixelRatio\n\n // 실제 텍스트 크기가 10px 이상일 때만 텍스트 표시\n if (actualFontSize >= 10) {\n ctx.font = `${fontSize}px Roboto, Arial, sans-serif`\n ctx.fillStyle = 'black'\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n\n // 배터리 잔량 텍스트 (정수 + % 포함)\n const { BATTERYRATETEXT } = this.data || {}\n const text = BATTERYRATETEXT || `${Math.round(BATTERYRATE)}%`\n\n // 텍스트 크기 측정\n const textMetrics = ctx.measureText(text)\n const textWidth = textMetrics.width * 1.1 // 여백을 위해 10% 추가\n const textHeight = fontSize * 1.1 // 여백을 위해 10% 추가\n\n // 배터리 중심점 계산\n const batteryCenterX = batteryX + batteryWidth / 2\n const batteryCenterY = batteryY + batteryHeight / 2\n\n // 현재 변환 상태 저장\n ctx.save()\n\n // 배터리 중심점으로 이동\n ctx.translate(batteryCenterX, batteryCenterY)\n\n // 순수한 회전 각도 계산 (라디안)\n const normalizedM11 = transform.m11 / scaleX\n const normalizedM21 = transform.m21 / scaleX\n let angle = Math.atan2(normalizedM21, normalizedM11)\n\n // 회전 보정 (같은 방향으로 회전)\n ctx.rotate(angle)\n\n // 텍스트 배경 위치 계산 (중심점 기준)\n const textBgX = -textWidth / 2\n const textBgY = -textHeight / 2\n\n // 텍스트 배경 그리기\n ctx.fillStyle = 'white'\n ctx.fillRect(textBgX, textBgY, textWidth, textHeight)\n\n // 텍스트 그리기\n ctx.fillStyle = 'black'\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n ctx.fillText(text, 0, textHeight * 0.1) // 텍스트를 약간 아래로 이동\n\n // 변환 상태 복원\n ctx.restore()\n }\n\n ctx.translate(-left, -top)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"agv.js","sourceRoot":"","sources":["../src/agv.ts"],"names":[],"mappings":";AAAA,OAAO,EAAmB,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,UAAU,MAAM,eAAe,CAAA;AACtC,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAA;AAEpG,MAAM,MAAM,GAAoB;IAC9B,OAAO,EAAE,KAAK;IACd,SAAS,EAAE,IAAI;IACf,SAAS,EAAE,IAAI;IACf,UAAU,EAAE;QACV,GAAG,UAAU,CAAC,UAAU;QACxB;YACE,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,0BAA0B;YACjC,IAAI,EAAE,uBAAuB;YAC7B,QAAQ,EAAE;gBACR,OAAO,EAAE,gBAAgB;aAC1B;SACF;KACF;CACF,CAAA;AAED,MAAM,GAAG,GAAG,CAAC,CAAA;AAGE,IAAM,GAAG,GAAT,MAAM,GAAI,SAAQ,UAAU;IACzC,MAAM,KAAK,MAAM;QACf,OAAO,MAAM,CAAA;IACf,CAAC;IAED,IAAI,QAAQ;QACV,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,oCAAoC;IACpC,IAAI,iBAAiB;QACnB,OAAO,CAAC,SAAS,CAAC,CAAA;IACpB,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,KAAK,CAAA;IACd,CAAC;IAED,4GAA4G;IAC5G,IAAI,cAAc;QAChB,OAAO,CAAC,GAAG,KAAK,CAAC,cAAc,EAAE,cAAc,CAAC,CAAA;IAClD,CAAC;IAED,wBAAwB;QACtB,OAAQ,IAAI,CAAC,IAAY,CAAC,sBAAsB,IAAI,mBAAmB,CAAA;IACzE,CAAC;IAED,qBAAqB;;QACnB,MAAM,EAAE,qBAAqB,EAAE,GAAG,IAAI,CAAC,KAAK,CAAA;QAE5C,IAAI,qBAAqB,EAAE,CAAC;YAC1B,OAAO,MAAA,MAAC,IAAI,CAAC,IAAY,0CAAE,KAAK,0CAAG,qBAAqB,CAAC,CAAA;QAC3D,CAAC;IACH,CAAC;IAED,eAAe,CAAC,IAAY;QAC1B,OAAO,WAAW,CAAC,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,qBAAqB,EAAE,IAAI,IAAI,CAAC,wBAAwB,EAAE,CAAC,CAAC,CAAA;IAC/G,CAAC;IAED,MAAM,CAAC,GAA6B;QAClC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAA;QAE9C,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QACxB,GAAG,CAAC,SAAS,EAAE,CAAA;QAEf,2BAA2B;QAC3B,MAAM,YAAY,GAAG,GAAG,CAAA;QACxB,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,GAAG,CAAA;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC,CAAA;QAErD,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAA;QAC/B,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,WAAY,CAAA;QACjC,GAAG,CAAC,SAAS,GAAG,SAAS,CAAA;QACzB,GAAG,CAAC,OAAO,GAAG,OAAO,CAAA;QACrB,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;QAEnB,aAAa;QACb,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,CAAA;QACjC,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,CAAA;QAE/D,GAAG,CAAC,IAAI,EAAE,CAAA;QACV,GAAG,CAAC,MAAM,EAAE,CAAA;QAEZ,GAAG,CAAC,SAAS,EAAE,CAAA;QAEf,SAAS;QACT,GAAG,CAAC,WAAW,GAAG,OAAO,CAAA;QAEzB,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QAC/B,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QAC/B,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QACnC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QAEnC,GAAG,CAAC,MAAM,EAAE,CAAA;QAEZ,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAA;IAC5B,CAAC;IAED,gBAAgB;IAChB,gBAAgB,CAAC,GAA6B,EAAE,CAAS,EAAE,CAAS,EAAE,KAAa,EAAE,MAAc;QACjG,uBAAuB;QACvB,MAAM,OAAO,GAAG,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;QAEpC,mBAAmB;QACnB,MAAM,YAAY,GAAG,GAAG,CAAA;QACxB,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,EAAE,CAAA,CAAC,wBAAwB;QACzE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC,CAAA;QAErD,GAAG,CAAC,SAAS,EAAE,CAAA;QACf,GAAG,CAAC,WAAW,GAAG,OAAO,CAAA;QACzB,GAAG,CAAC,SAAS,GAAG,SAAS,CAAA;QAEzB,oBAAoB;QACpB,GAAG,CAAC,IAAI,EAAE,CAAA;QACV,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAA;QAC7B,GAAG,CAAC,IAAI,EAAE,CAAA;QAEV,gBAAgB;QAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,CAAA;YAC9B,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;YACrB,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,MAAM,CAAC,CAAA;QACzC,CAAC;QAED,GAAG,CAAC,MAAM,EAAE,CAAA;QACZ,SAAS;QACT,GAAG,CAAC,OAAO,EAAE,CAAA;IACf,CAAC;IAED,UAAU,CAAC,GAA6B;;QACtC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;QAErB,MAAM,WAAW,GAAG,MAAA,IAAI,CAAC,IAAI,0CAAE,WAAW,CAAA;QAE1C,IAAI,OAAO,WAAW,KAAK,QAAQ,EAAE,CAAC;YACpC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAA;YAChD,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;YAExB,4BAA4B;YAC5B,MAAM,gBAAgB,GAAG,CAAC,CAAA;YAC1B,MAAM,eAAe,GAAG,CAAC,CAAA;YACzB,MAAM,eAAe,GAAG,MAAM,GAAG,CAAC,CAAA;YAClC,MAAM,cAAc,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;YAEtC,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAA;YACjE,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,cAAc,CAAC,CAAA;YAC9D,MAAM,QAAQ,GAAG,CAAC,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;YAC3C,MAAM,QAAQ,GAAG,CAAC,MAAM,GAAG,aAAa,CAAC,GAAG,GAAG,CAAA;YAE/C,6BAA6B;YAC7B,MAAM,YAAY,GAAG,GAAG,CAAA;YACxB,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,GAAG,CAAA;YACjD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,WAAW,CAAC,CAAA;YAErD,mBAAmB;YACnB,GAAG,CAAC,SAAS,GAAG,OAAO,CAAA;YACvB,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,CAAC,CAAA;YAE7D,uBAAuB;YACvB,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,CAAC,CAAA;YAE3E,YAAY;YACZ,MAAM,SAAS,GAAG,CAAC,YAAY,GAAG,WAAW,CAAC,GAAG,GAAG,CAAA;YAEpD,2BAA2B;YAC3B,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,CAAA;YAEjD,gBAAgB;YAChB,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,CAAC,CAAA;YAE1D,iBAAiB;YACjB,GAAG,CAAC,SAAS,EAAE,CAAA;YACf,GAAG,CAAC,WAAW,GAAG,OAAO,CAAA;YACzB,GAAG,CAAC,SAAS,GAAG,SAAS,CAAA;YACzB,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,CAAC,CAAA;YAE/D,gBAAgB;YAChB,MAAM,QAAQ,GAAG,aAAa,GAAG,GAAG,CAAA;YAEpC,oBAAoB;YACpB,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,EAAE,CAAA;YACpC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;YACvF,MAAM,cAAc,GAAG,CAAC,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,gBAAgB,CAAA;YAE3E,gCAAgC;YAChC,IAAI,cAAc,IAAI,EAAE,EAAE,CAAC;gBACzB,GAAG,CAAC,IAAI,GAAG,GAAG,QAAQ,8BAA8B,CAAA;gBACpD,GAAG,CAAC,SAAS,GAAG,OAAO,CAAA;gBACvB,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAA;gBACxB,GAAG,CAAC,YAAY,GAAG,QAAQ,CAAA;gBAE3B,yBAAyB;gBACzB,MAAM,EAAE,eAAe,EAAE,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAA;gBAC3C,MAAM,IAAI,GAAG,eAAe,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,CAAA;gBAE7D,YAAY;gBACZ,MAAM,WAAW,GAAG,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;gBACzC,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,GAAG,GAAG,CAAA,CAAC,gBAAgB;gBAC1D,MAAM,UAAU,GAAG,QAAQ,GAAG,GAAG,CAAA,CAAC,gBAAgB;gBAElD,aAAa;gBACb,MAAM,cAAc,GAAG,QAAQ,GAAG,YAAY,GAAG,CAAC,CAAA;gBAClD,MAAM,cAAc,GAAG,QAAQ,GAAG,aAAa,GAAG,CAAC,CAAA;gBAEnD,cAAc;gBACd,GAAG,CAAC,IAAI,EAAE,CAAA;gBAEV,eAAe;gBACf,GAAG,CAAC,SAAS,CAAC,cAAc,EAAE,cAAc,CAAC,CAAA;gBAE7C,qBAAqB;gBACrB,MAAM,aAAa,GAAG,SAAS,CAAC,GAAG,GAAG,MAAM,CAAA;gBAC5C,MAAM,aAAa,GAAG,SAAS,CAAC,GAAG,GAAG,MAAM,CAAA;gBAC5C,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;gBAEpD,qBAAqB;gBACrB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBAEjB,wBAAwB;gBACxB,MAAM,OAAO,GAAG,CAAC,SAAS,GAAG,CAAC,CAAA;gBAC9B,MAAM,OAAO,GAAG,CAAC,UAAU,GAAG,CAAC,CAAA;gBAE/B,aAAa;gBACb,GAAG,CAAC,SAAS,GAAG,OAAO,CAAA;gBACvB,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,CAAA;gBAErD,UAAU;gBACV,GAAG,CAAC,SAAS,GAAG,OAAO,CAAA;gBACvB,GAAG,CAAC,SAAS,GAAG,QAAQ,CAAA;gBACxB,GAAG,CAAC,YAAY,GAAG,QAAQ,CAAA;gBAC3B,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,UAAU,GAAG,GAAG,CAAC,CAAA,CAAC,iBAAiB;gBAEzD,WAAW;gBACX,GAAG,CAAC,OAAO,EAAE,CAAA;YACf,CAAC;YAED,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAA;QAC5B,CAAC;IACH,CAAC;CACF,CAAA;AA3NoB,GAAG;IADvB,cAAc,CAAC,KAAK,CAAC;GACD,GAAG,CA2NvB;eA3NoB,GAAG","sourcesContent":["import { ComponentNature, sceneComponent } from '@hatiolab/things-scene'\nimport { themesColorRange } from '@fmsim/api'\nimport MCSVehicle from './mcs-vehicle'\nimport { BATTERY_RATE_LEGEND, legendColor, legendRangeEntryOf } from './features/mcs-status-default'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n ...MCSVehicle.properties,\n {\n type: 'select',\n label: 'battery-rate-legend-name',\n name: 'batteryRateLegendName',\n property: {\n options: themesColorRange\n }\n }\n ]\n}\n\nconst GAP = 2\n\n@sceneComponent('AGV')\nexport default class AGV extends MCSVehicle {\n static get nature() {\n return NATURE\n }\n\n get auxColor() {\n return 'black'\n }\n\n /** AGV 의 parentObject 는 AGVLine. */\n get parentObjectTypes(): string[] {\n return ['AGVLine']\n }\n\n get statusLegendRow(): string {\n return 'agv'\n }\n\n /** Its STATUS row and its battery's (the battery is the AGV's own: only a board with AGVs shows the row) */\n get legendRowsUsed(): string[] {\n return [...super.legendRowsUsed, 'battery-rate']\n }\n\n getBatteryLegendFallback() {\n return (this.root as any).batteryRateLegendTheme || BATTERY_RATE_LEGEND\n }\n\n getBatteryLegendTheme() {\n const { batteryRateLegendName } = this.state\n\n if (batteryRateLegendName) {\n return (this.root as any)?.style?.[batteryRateLegendName]\n }\n }\n\n getBatteryColor(rate: number) {\n return legendColor(legendRangeEntryOf(rate, this.getBatteryLegendTheme() || this.getBatteryLegendFallback()))\n }\n\n render(ctx: CanvasRenderingContext2D) {\n var { left, top, width, height } = this.bounds\n\n ctx.translate(left, top)\n ctx.beginPath()\n\n // 작은 크기에서도 보이도록 최소 선 두께 설정\n const minLineWidth = 0.5\n const scaleFactor = Math.min(width, height) / 100\n const lineWidth = Math.max(minLineWidth, scaleFactor)\n\n ctx.strokeStyle = this.auxColor\n ctx.fillStyle = this.statusColor!\n ctx.lineWidth = lineWidth\n ctx.lineCap = 'round'\n ctx.setLineDash([])\n\n // 기본 사각형 그리기\n ctx.rect(1, 0, width - 2, height)\n ctx.rect(GAP + 1, GAP, width - (GAP + 1) * 2, height - GAP * 2)\n\n ctx.fill()\n ctx.stroke()\n\n ctx.beginPath()\n\n // 바퀴 그리기\n ctx.strokeStyle = 'black'\n\n ctx.moveTo(0, (height * 1) / 3)\n ctx.lineTo(0, (height * 2) / 3)\n ctx.moveTo(width, (height * 1) / 3)\n ctx.lineTo(width, (height * 2) / 3)\n\n ctx.stroke()\n\n ctx.translate(-left, -top)\n }\n\n // 사선 패턴을 그리는 함수\n drawHatchPattern(ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) {\n // 6개의 빗금을 그리기 위한 간격 계산\n const spacing = (width + height) / 6\n\n // 선 두께 계산 (크기에 비례)\n const minLineWidth = 0.5\n const scaleFactor = Math.min(width, height) / 20 // 130에서 50으로 변경하여 더 두껍게\n const lineWidth = Math.max(minLineWidth, scaleFactor)\n\n ctx.beginPath()\n ctx.strokeStyle = 'black'\n ctx.lineWidth = lineWidth\n\n // 배터리 박스 내부로 클리핑 설정\n ctx.save()\n ctx.rect(x, y, width, height)\n ctx.clip()\n\n // 6개의 사선 패턴 그리기\n for (let i = 0; i < 6; i++) {\n const startX = x + i * spacing\n ctx.moveTo(startX, y)\n ctx.lineTo(startX - height, y + height)\n }\n\n ctx.stroke()\n // 클리핑 해제\n ctx.restore()\n }\n\n postrender(ctx: CanvasRenderingContext2D): void {\n super.postrender(ctx)\n\n const BATTERYRATE = this.data?.BATTERYRATE\n\n if (typeof BATTERYRATE === 'number') {\n const { left, top, width, height } = this.bounds\n ctx.translate(left, top)\n\n // 배터리 크기 및 위치 설정 (최소 크기 보장)\n const minBatteryHeight = 2\n const minBatteryWidth = 4\n const preferredHeight = height / 5\n const preferredWidth = (width * 3) / 4\n\n const batteryHeight = Math.max(minBatteryHeight, preferredHeight)\n const batteryWidth = Math.max(minBatteryWidth, preferredWidth)\n const batteryX = (width - batteryWidth) / 2\n const batteryY = (height - batteryHeight) * 1.1\n\n // 배터리 테두리 그리기 (크기에 비례한 선 두께)\n const minLineWidth = 0.5\n const scaleFactor = Math.min(width, height) / 100\n const lineWidth = Math.max(minLineWidth, scaleFactor)\n\n // 배터리 배경을 흰색으로 채우기\n ctx.fillStyle = 'white'\n ctx.fillRect(batteryX, batteryY, batteryWidth, batteryHeight)\n\n // 배터리 전체 영역에 사선 패턴 그리기\n this.drawHatchPattern(ctx, batteryX, batteryY, batteryWidth, batteryHeight)\n\n // 배터리 잔량 표시\n const fillWidth = (batteryWidth * BATTERYRATE) / 100\n\n // 배터리 잔량에 따른 색상 설정 - 테마 적용\n ctx.fillStyle = this.getBatteryColor(BATTERYRATE)\n\n // 배터리 잔량 영역 채우기\n ctx.fillRect(batteryX, batteryY, fillWidth, batteryHeight)\n\n // 배터리 테두리 다시 그리기\n ctx.beginPath()\n ctx.strokeStyle = 'black'\n ctx.lineWidth = lineWidth\n ctx.strokeRect(batteryX, batteryY, batteryWidth, batteryHeight)\n\n // 배터리 잔량 텍스트 표시\n const fontSize = batteryHeight * 0.8\n\n // 실제 렌더링될 텍스트 크기 계산\n const transform = ctx.getTransform()\n const scaleX = Math.sqrt(transform.m11 * transform.m11 + transform.m21 * transform.m21)\n const actualFontSize = (fontSize * (scaleX || 1)) / window.devicePixelRatio\n\n // 실제 텍스트 크기가 10px 이상일 때만 텍스트 표시\n if (actualFontSize >= 10) {\n ctx.font = `${fontSize}px Roboto, Arial, sans-serif`\n ctx.fillStyle = 'black'\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n\n // 배터리 잔량 텍스트 (정수 + % 포함)\n const { BATTERYRATETEXT } = this.data || {}\n const text = BATTERYRATETEXT || `${Math.round(BATTERYRATE)}%`\n\n // 텍스트 크기 측정\n const textMetrics = ctx.measureText(text)\n const textWidth = textMetrics.width * 1.1 // 여백을 위해 10% 추가\n const textHeight = fontSize * 1.1 // 여백을 위해 10% 추가\n\n // 배터리 중심점 계산\n const batteryCenterX = batteryX + batteryWidth / 2\n const batteryCenterY = batteryY + batteryHeight / 2\n\n // 현재 변환 상태 저장\n ctx.save()\n\n // 배터리 중심점으로 이동\n ctx.translate(batteryCenterX, batteryCenterY)\n\n // 순수한 회전 각도 계산 (라디안)\n const normalizedM11 = transform.m11 / scaleX\n const normalizedM21 = transform.m21 / scaleX\n let angle = Math.atan2(normalizedM21, normalizedM11)\n\n // 회전 보정 (같은 방향으로 회전)\n ctx.rotate(angle)\n\n // 텍스트 배경 위치 계산 (중심점 기준)\n const textBgX = -textWidth / 2\n const textBgY = -textHeight / 2\n\n // 텍스트 배경 그리기\n ctx.fillStyle = 'white'\n ctx.fillRect(textBgX, textBgY, textWidth, textHeight)\n\n // 텍스트 그리기\n ctx.fillStyle = 'black'\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n ctx.fillText(text, 0, textHeight * 0.1) // 텍스트를 약간 아래로 이동\n\n // 변환 상태 복원\n ctx.restore()\n }\n\n ctx.translate(-left, -top)\n }\n }\n}\n"]}
package/dist/buffer.js CHANGED
@@ -11,8 +11,8 @@ let Buffer = class Buffer extends MCSMachine {
11
11
  static get nature() {
12
12
  return NATURE;
13
13
  }
14
- getLegendFallback() {
15
- return this.root.bufferLegendTheme || super.getLegendFallback();
14
+ get statusLegendRow() {
15
+ return 'buffer';
16
16
  }
17
17
  containable(component) {
18
18
  return super.containable(component) || ['Port'].includes(component.state.type);
@@ -1 +1 @@
1
- {"version":3,"file":"buffer.js","sourceRoot":"","sources":["../src/buffer.ts"],"names":[],"mappings":";AAAA,OAAO,EAA8B,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACnF,OAAO,UAAU,MAAM,eAAe,CAAA;AAEtC,MAAM,MAAM,GAAoB;IAC9B,OAAO,EAAE,KAAK;IACd,SAAS,EAAE,IAAI;IACf,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC;CACvC,CAAA;AAGc,IAAM,MAAM,GAAZ,MAAM,MAAO,SAAQ,UAAU;IAC5C,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,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAChF,CAAC;IAED,MAAM,CAAC,GAAG;QACR,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,KAAK,CAAA;QAC9B,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAA;QAE9C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,GAAG,CAAC,CAAA;QAExD,GAAG,CAAC,SAAS,EAAE,CAAA;QACf,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAExB,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAA;QAC/B,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,WAAY,CAAA;QACjC,GAAG,CAAC,SAAS,GAAG,SAAS,IAAI,CAAC,CAAA;QAC9B,GAAG,CAAC,OAAO,GAAG,OAAO,CAAA;QACrB,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;QAEnB,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACrB,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,EAAE,CAAC,CAAC,CAAA;QAC7B,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC,CAAA;QAC7B,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,EAAE,MAAM,CAAC,CAAA;QAClC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC1B,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAA;QACzB,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QAErB,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAA;QAE1B,GAAG,CAAC,IAAI,EAAE,CAAA;QACV,GAAG,CAAC,MAAM,EAAE,CAAA;IACd,CAAC;CACF,CAAA;AAzCoB,MAAM;IAD1B,cAAc,CAAC,QAAQ,CAAC;GACJ,MAAM,CAyC1B;eAzCoB,MAAM","sourcesContent":["import { Component, ComponentNature, sceneComponent } from '@hatiolab/things-scene'\nimport MCSMachine from './mcs-machine'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [...MCSMachine.properties]\n}\n\n@sceneComponent('Buffer')\nexport default class Buffer extends MCSMachine {\n static get nature() {\n return NATURE\n }\n\n getLegendFallback() {\n return (this.root as any).bufferLegendTheme || super.getLegendFallback()\n }\n\n containable(component: Component) {\n return super.containable(component) || ['Port'].includes(component.state.type)\n }\n\n render(ctx) {\n var { lineWidth } = this.state\n var { left, top, width, height } = this.bounds\n\n const offset = Math.round(Math.min(width, height) * 0.2)\n\n ctx.beginPath()\n ctx.translate(left, top)\n\n ctx.strokeStyle = this.auxColor\n ctx.fillStyle = this.statusColor!\n ctx.lineWidth = lineWidth || 1\n ctx.lineCap = 'round'\n ctx.setLineDash([])\n\n ctx.moveTo(offset, 0)\n ctx.lineTo(width - offset, 0)\n ctx.lineTo(width, height / 2)\n ctx.lineTo(width - offset, height)\n ctx.lineTo(offset, height)\n ctx.lineTo(0, height / 2)\n ctx.lineTo(offset, 0)\n\n ctx.translate(-left, -top)\n\n ctx.fill()\n ctx.stroke()\n }\n}\n"]}
1
+ {"version":3,"file":"buffer.js","sourceRoot":"","sources":["../src/buffer.ts"],"names":[],"mappings":";AAAA,OAAO,EAA8B,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACnF,OAAO,UAAU,MAAM,eAAe,CAAA;AAEtC,MAAM,MAAM,GAAoB;IAC9B,OAAO,EAAE,KAAK;IACd,SAAS,EAAE,IAAI;IACf,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC;CACvC,CAAA;AAGc,IAAM,MAAM,GAAZ,MAAM,MAAO,SAAQ,UAAU;IAC5C,MAAM,KAAK,MAAM;QACf,OAAO,MAAM,CAAA;IACf,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,WAAW,CAAC,SAAoB;QAC9B,OAAO,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAChF,CAAC;IAED,MAAM,CAAC,GAAG;QACR,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,KAAK,CAAA;QAC9B,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAA;QAE9C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,GAAG,CAAC,CAAA;QAExD,GAAG,CAAC,SAAS,EAAE,CAAA;QACf,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAExB,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAA;QAC/B,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,WAAY,CAAA;QACjC,GAAG,CAAC,SAAS,GAAG,SAAS,IAAI,CAAC,CAAA;QAC9B,GAAG,CAAC,OAAO,GAAG,OAAO,CAAA;QACrB,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;QAEnB,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACrB,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,EAAE,CAAC,CAAC,CAAA;QAC7B,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC,CAAA;QAC7B,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,EAAE,MAAM,CAAC,CAAA;QAClC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC1B,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAA;QACzB,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QAErB,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAA;QAE1B,GAAG,CAAC,IAAI,EAAE,CAAA;QACV,GAAG,CAAC,MAAM,EAAE,CAAA;IACd,CAAC;CACF,CAAA;AAzCoB,MAAM;IAD1B,cAAc,CAAC,QAAQ,CAAC;GACJ,MAAM,CAyC1B;eAzCoB,MAAM","sourcesContent":["import { Component, ComponentNature, sceneComponent } from '@hatiolab/things-scene'\nimport MCSMachine from './mcs-machine'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [...MCSMachine.properties]\n}\n\n@sceneComponent('Buffer')\nexport default class Buffer extends MCSMachine {\n static get nature() {\n return NATURE\n }\n\n get statusLegendRow(): string {\n return 'buffer'\n }\n\n containable(component: Component) {\n return super.containable(component) || ['Port'].includes(component.state.type)\n }\n\n render(ctx) {\n var { lineWidth } = this.state\n var { left, top, width, height } = this.bounds\n\n const offset = Math.round(Math.min(width, height) * 0.2)\n\n ctx.beginPath()\n ctx.translate(left, top)\n\n ctx.strokeStyle = this.auxColor\n ctx.fillStyle = this.statusColor!\n ctx.lineWidth = lineWidth || 1\n ctx.lineCap = 'round'\n ctx.setLineDash([])\n\n ctx.moveTo(offset, 0)\n ctx.lineTo(width - offset, 0)\n ctx.lineTo(width, height / 2)\n ctx.lineTo(width - offset, height)\n ctx.lineTo(offset, height)\n ctx.lineTo(0, height / 2)\n ctx.lineTo(offset, 0)\n\n ctx.translate(-left, -top)\n\n ctx.fill()\n ctx.stroke()\n }\n}\n"]}
@@ -81,8 +81,8 @@ let ConveyorJoin = class ConveyorJoin extends ConveyorMixin(MCSTransport) {
81
81
  get nature() {
82
82
  return NATURE;
83
83
  }
84
- getLegendFallback() {
85
- return this.root.conveyorLegendTheme || super.getLegendFallback();
84
+ get statusLegendRow() {
85
+ return 'conveyor';
86
86
  }
87
87
  containable(component) {
88
88
  return ['Shuttle', 'Port'].includes(component.state.type);
@@ -1 +1 @@
1
- {"version":3,"file":"conveyor-join.js","sourceRoot":"","sources":["../src/conveyor-join.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ComponentNature, Control, POSITION, sceneComponent } from '@hatiolab/things-scene'\nimport MCSTransport from './mcs-transport'\nimport { ConveyorMixin } from './features/conveyor-mixin'\nimport { normalizeAngle } from './utils/normalize-angle'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n ...MCSTransport.properties,\n {\n type: 'angle',\n label: 'start-angle',\n name: 'startAngle'\n },\n {\n type: 'angle',\n label: 'end-angle',\n name: 'endAngle'\n },\n {\n type: 'number',\n label: 'ratio',\n name: 'ratio'\n },\n {\n type: 'number',\n label: 'roll-width',\n name: 'rollWidth'\n }\n ]\n}\n\nvar controlHandler = {\n ondragmove: function (point: POSITION, index: number, component: Component) {\n var { cx, cy, rx, ry, startAngle, endAngle } = component.model\n\n var { x, y } = component.transcoordP2S(point.x, point.y)\n\n const angle = (startAngle + endAngle) / 2\n\n /* 원점으로부터 최대 거리 */\n const dx = Math.abs(rx * Math.sin(angle))\n const dy = Math.abs(ry * Math.cos(angle))\n const distance = Math.sqrt(dx * dx + dy * dy)\n\n /* 원점으로부터 현재 컨트롤 위치까지의 거리 */\n const px = Math.abs(cx - x)\n const py = Math.abs(cy - y)\n const pdistance = Math.sqrt(px * px + py * py)\n\n var ratio = (pdistance / distance) * 100\n\n ratio = ratio >= 100 || ratio <= -100 ? 100 : Math.abs(ratio)\n\n component.set({ ratio })\n }\n}\n\nvar antiClockWiseControlHandler = {\n ondragmove: function (point: POSITION, index: number, component: Component) {\n var { cx, cy } = component.model\n\n var transcoorded = component.transcoordP2S(point.x, point.y)\n\n var theta = Math.atan2(-(transcoorded.y - cy), transcoorded.x - cx)\n\n if (theta > 0 && theta <= Math.PI / 2) theta = Math.PI / 2\n if (theta < 0 && theta >= -Math.PI / 2) theta = -Math.PI / 2\n\n const startAngle = (-theta + Math.PI / 2 - Math.PI * 2) % (Math.PI * 2)\n\n component.set({ startAngle })\n }\n}\n\nvar clockwiseControlHandler = {\n ondragmove: function (point: POSITION, index: number, component: Component) {\n var { cx, cy } = component.model\n\n var transcoorded = component.transcoordP2S(point.x, point.y)\n\n var theta = Math.atan2(-(transcoorded.y - cy), transcoorded.x - cx)\n\n if (theta > 0) if (theta >= Math.PI / 2) theta = Math.PI / 2\n if (theta < 0) if (theta <= -Math.PI / 2) theta = -Math.PI / 2\n\n var endAngle = -theta + Math.PI / 2\n\n component.set({ endAngle })\n }\n}\n\n@sceneComponent('ConveyorJoin')\nexport default class ConveyorJoin extends ConveyorMixin(MCSTransport) {\n get nature() {\n return NATURE\n }\n\n getLegendFallback() {\n return (this.root as any).conveyorLegendTheme || super.getLegendFallback()\n }\n\n containable(component: Component) {\n return ['Shuttle', 'Port'].includes(component.state.type)\n }\n\n contains(x: number, y: number) {\n var { cx, cy, rx, ry, ratio, startAngle, endAngle } = this.state\n rx = Math.abs(rx)\n ry = Math.abs(ry)\n\n const normx = (x - cx) / (rx * 2 - 0.5)\n const normy = (y - cy) / (ry * 2 - 0.5)\n const ratiox = (x - cx) / ((rx / 100) * ratio * 2 - 0.5)\n const ratioy = (y - cy) / ((ry / 100) * ratio * 2 - 0.5)\n\n if (normx * normx + normy * normy < 0.25 && ratiox * ratiox + ratioy * ratioy > 0.25) {\n const angle = normalizeAngle(Math.atan2(-normy, normx) - Math.PI / 2)\n\n if (startAngle <= endAngle) {\n if (angle >= startAngle && angle <= endAngle) return true\n } else {\n // wraparound: startAngle > endAngle (예: π → 0)\n if (angle >= startAngle || angle <= endAngle) return true\n }\n }\n\n return false\n }\n\n render(context: CanvasRenderingContext2D) {\n var { ratio = 50, cx, cy, rx, ry, startAngle = 0, endAngle = Math.PI / 2 } = this.state\n\n context.beginPath()\n\n startAngle -= Math.PI / 2\n endAngle -= Math.PI / 2\n\n /* outer ellipse and inner ellipse */\n context.ellipse(cx, cy, Math.abs(rx), Math.abs(ry), 0, startAngle, endAngle)\n context.ellipse(cx, cy, Math.abs((rx / 100) * ratio), Math.abs((ry / 100) * ratio), 0, endAngle, startAngle, true)\n\n context.lineTo(rx * Math.cos(startAngle) + cx, ry * Math.sin(startAngle) + cy)\n\n this.drawFill(context)\n this.drawStroke(context)\n }\n\n get path() {\n var { cx, cy, rx, ry } = this.state\n\n return [\n {\n x: cx - rx,\n y: cy - ry\n },\n {\n x: cx + rx,\n y: cy - ry\n },\n {\n x: cx + rx,\n y: cy + ry\n },\n {\n x: cx - rx,\n y: cy + ry\n }\n ]\n }\n\n set path(path) {\n var left_top = path[0]\n var right_bottom = path[2]\n\n this.set({\n cx: left_top.x + (right_bottom.x - left_top.x) / 2,\n cy: left_top.y + (right_bottom.y - left_top.y) / 2,\n rx: (right_bottom.x - left_top.x) / 2,\n ry: (right_bottom.y - left_top.y) / 2\n })\n }\n\n get controls(): Control[] {\n var { cx, cy, rx, ry, ratio, startAngle, endAngle } = this.state\n\n var controls = [] as Control[]\n\n controls.push({\n x: cx + ((rx + (rx * ratio) / 100) / 2) * Math.sin(startAngle),\n y: cy - ((ry + (ry * ratio) / 100) / 2) * Math.cos(startAngle),\n handler: antiClockWiseControlHandler\n })\n\n controls.push({\n x: cx + ((rx + (rx * ratio) / 100) / 2) * Math.sin(endAngle),\n y: cy - ((ry + (ry * ratio) / 100) / 2) * Math.cos(endAngle),\n handler: clockwiseControlHandler\n })\n\n const angle = (startAngle + endAngle) / 2\n controls.push({\n x: cx + ((rx * ratio) / 100) * Math.sin(angle),\n y: cy - ((ry * ratio) / 100) * Math.cos(angle),\n handler: controlHandler\n })\n\n return controls\n }\n}\n\nComponent.memoize(ConveyorJoin.prototype, 'controls', false)\n"]}
1
+ {"version":3,"file":"conveyor-join.js","sourceRoot":"","sources":["../src/conveyor-join.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ComponentNature, Control, POSITION, sceneComponent } from '@hatiolab/things-scene'\nimport MCSTransport from './mcs-transport'\nimport { ConveyorMixin } from './features/conveyor-mixin'\nimport { normalizeAngle } from './utils/normalize-angle'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n ...MCSTransport.properties,\n {\n type: 'angle',\n label: 'start-angle',\n name: 'startAngle'\n },\n {\n type: 'angle',\n label: 'end-angle',\n name: 'endAngle'\n },\n {\n type: 'number',\n label: 'ratio',\n name: 'ratio'\n },\n {\n type: 'number',\n label: 'roll-width',\n name: 'rollWidth'\n }\n ]\n}\n\nvar controlHandler = {\n ondragmove: function (point: POSITION, index: number, component: Component) {\n var { cx, cy, rx, ry, startAngle, endAngle } = component.model\n\n var { x, y } = component.transcoordP2S(point.x, point.y)\n\n const angle = (startAngle + endAngle) / 2\n\n /* 원점으로부터 최대 거리 */\n const dx = Math.abs(rx * Math.sin(angle))\n const dy = Math.abs(ry * Math.cos(angle))\n const distance = Math.sqrt(dx * dx + dy * dy)\n\n /* 원점으로부터 현재 컨트롤 위치까지의 거리 */\n const px = Math.abs(cx - x)\n const py = Math.abs(cy - y)\n const pdistance = Math.sqrt(px * px + py * py)\n\n var ratio = (pdistance / distance) * 100\n\n ratio = ratio >= 100 || ratio <= -100 ? 100 : Math.abs(ratio)\n\n component.set({ ratio })\n }\n}\n\nvar antiClockWiseControlHandler = {\n ondragmove: function (point: POSITION, index: number, component: Component) {\n var { cx, cy } = component.model\n\n var transcoorded = component.transcoordP2S(point.x, point.y)\n\n var theta = Math.atan2(-(transcoorded.y - cy), transcoorded.x - cx)\n\n if (theta > 0 && theta <= Math.PI / 2) theta = Math.PI / 2\n if (theta < 0 && theta >= -Math.PI / 2) theta = -Math.PI / 2\n\n const startAngle = (-theta + Math.PI / 2 - Math.PI * 2) % (Math.PI * 2)\n\n component.set({ startAngle })\n }\n}\n\nvar clockwiseControlHandler = {\n ondragmove: function (point: POSITION, index: number, component: Component) {\n var { cx, cy } = component.model\n\n var transcoorded = component.transcoordP2S(point.x, point.y)\n\n var theta = Math.atan2(-(transcoorded.y - cy), transcoorded.x - cx)\n\n if (theta > 0) if (theta >= Math.PI / 2) theta = Math.PI / 2\n if (theta < 0) if (theta <= -Math.PI / 2) theta = -Math.PI / 2\n\n var endAngle = -theta + Math.PI / 2\n\n component.set({ endAngle })\n }\n}\n\n@sceneComponent('ConveyorJoin')\nexport default class ConveyorJoin extends ConveyorMixin(MCSTransport) {\n get nature() {\n return NATURE\n }\n\n get statusLegendRow(): string {\n return 'conveyor'\n }\n\n containable(component: Component) {\n return ['Shuttle', 'Port'].includes(component.state.type)\n }\n\n contains(x: number, y: number) {\n var { cx, cy, rx, ry, ratio, startAngle, endAngle } = this.state\n rx = Math.abs(rx)\n ry = Math.abs(ry)\n\n const normx = (x - cx) / (rx * 2 - 0.5)\n const normy = (y - cy) / (ry * 2 - 0.5)\n const ratiox = (x - cx) / ((rx / 100) * ratio * 2 - 0.5)\n const ratioy = (y - cy) / ((ry / 100) * ratio * 2 - 0.5)\n\n if (normx * normx + normy * normy < 0.25 && ratiox * ratiox + ratioy * ratioy > 0.25) {\n const angle = normalizeAngle(Math.atan2(-normy, normx) - Math.PI / 2)\n\n if (startAngle <= endAngle) {\n if (angle >= startAngle && angle <= endAngle) return true\n } else {\n // wraparound: startAngle > endAngle (예: π → 0)\n if (angle >= startAngle || angle <= endAngle) return true\n }\n }\n\n return false\n }\n\n render(context: CanvasRenderingContext2D) {\n var { ratio = 50, cx, cy, rx, ry, startAngle = 0, endAngle = Math.PI / 2 } = this.state\n\n context.beginPath()\n\n startAngle -= Math.PI / 2\n endAngle -= Math.PI / 2\n\n /* outer ellipse and inner ellipse */\n context.ellipse(cx, cy, Math.abs(rx), Math.abs(ry), 0, startAngle, endAngle)\n context.ellipse(cx, cy, Math.abs((rx / 100) * ratio), Math.abs((ry / 100) * ratio), 0, endAngle, startAngle, true)\n\n context.lineTo(rx * Math.cos(startAngle) + cx, ry * Math.sin(startAngle) + cy)\n\n this.drawFill(context)\n this.drawStroke(context)\n }\n\n get path() {\n var { cx, cy, rx, ry } = this.state\n\n return [\n {\n x: cx - rx,\n y: cy - ry\n },\n {\n x: cx + rx,\n y: cy - ry\n },\n {\n x: cx + rx,\n y: cy + ry\n },\n {\n x: cx - rx,\n y: cy + ry\n }\n ]\n }\n\n set path(path) {\n var left_top = path[0]\n var right_bottom = path[2]\n\n this.set({\n cx: left_top.x + (right_bottom.x - left_top.x) / 2,\n cy: left_top.y + (right_bottom.y - left_top.y) / 2,\n rx: (right_bottom.x - left_top.x) / 2,\n ry: (right_bottom.y - left_top.y) / 2\n })\n }\n\n get controls(): Control[] {\n var { cx, cy, rx, ry, ratio, startAngle, endAngle } = this.state\n\n var controls = [] as Control[]\n\n controls.push({\n x: cx + ((rx + (rx * ratio) / 100) / 2) * Math.sin(startAngle),\n y: cy - ((ry + (ry * ratio) / 100) / 2) * Math.cos(startAngle),\n handler: antiClockWiseControlHandler\n })\n\n controls.push({\n x: cx + ((rx + (rx * ratio) / 100) / 2) * Math.sin(endAngle),\n y: cy - ((ry + (ry * ratio) / 100) / 2) * Math.cos(endAngle),\n handler: clockwiseControlHandler\n })\n\n const angle = (startAngle + endAngle) / 2\n controls.push({\n x: cx + ((rx * ratio) / 100) * Math.sin(angle),\n y: cy - ((ry * ratio) / 100) * Math.cos(angle),\n handler: controlHandler\n })\n\n return controls\n }\n}\n\nComponent.memoize(ConveyorJoin.prototype, 'controls', false)\n"]}
package/dist/conveyor.js CHANGED
@@ -32,8 +32,8 @@ let Conveyor = class Conveyor extends MCSTransport {
32
32
  get auxColor() {
33
33
  return '#777';
34
34
  }
35
- getLegendFallback() {
36
- return this.root.conveyorLegendTheme || super.getLegendFallback();
35
+ get statusLegendRow() {
36
+ return 'conveyor';
37
37
  }
38
38
  containable(component) {
39
39
  return ['Shuttle', 'Port', 'Node'].includes(component.state.type);
@@ -1 +1 @@
1
- {"version":3,"file":"conveyor.js","sourceRoot":"","sources":["../src/conveyor.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ComponentNature, 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: [\n {\n type: 'select',\n label: 'conveyor-type',\n name: 'conveyorType',\n property: {\n options: ['', 'conveyor', 'belt', 'rail']\n }\n },\n {\n type: 'select',\n label: 'conveyor-orientation',\n name: 'orientation',\n property: {\n options: ['', 'horizontal', 'vertical']\n }\n },\n ...MCSTransport.properties\n ]\n}\n\n@sceneComponent('Conveyor')\nexport default class Conveyor extends MCSTransport {\n static get nature() {\n return NATURE\n }\n\n get auxColor() {\n return '#777'\n }\n\n getLegendFallback() {\n return (this.root as any).conveyorLegendTheme || super.getLegendFallback()\n }\n\n containable(component: Component) {\n return ['Shuttle', 'Port', 'Node'].includes(component.state.type)\n }\n\n renderConveyor(ctx: CanvasRenderingContext2D) {\n const { left, top, width, height } = this.bounds\n\n const rollWidth = Math.max(10, Math.min(width, height) / 2)\n\n ctx.beginPath()\n ctx.fillStyle = this.statusColor!\n ctx.strokeStyle = this.auxColor!\n ctx.lineWidth = 1\n\n ctx.translate(left, top)\n ctx.rect(0, 0, width, height)\n ctx.fill()\n ctx.stroke()\n\n ctx.beginPath()\n ctx.strokeStyle = '#aaa'\n\n if (width > height) {\n for (let d = 0; d < width; d += rollWidth) {\n ctx.moveTo(d, 0)\n ctx.lineTo(d, height)\n }\n } else {\n for (let d = 0; d < height; d += rollWidth) {\n ctx.moveTo(0, d)\n ctx.lineTo(width, d)\n }\n }\n\n ctx.stroke()\n\n ctx.translate(-left, -top)\n }\n\n renderRtvRail(ctx: CanvasRenderingContext2D) {\n const { left, top, width, height } = this.bounds\n\n ctx.beginPath()\n\n ctx.translate(left, top)\n\n ctx.fillStyle = this.statusColor!\n\n if (width > height) {\n ctx.fillRect(0, 0, width, (height * 1) / 5)\n ctx.fillRect(0, (height * 4) / 5, width, (height * 1) / 5)\n } else {\n ctx.fillRect(0, 0, (width * 1) / 5, height)\n ctx.fillRect((width * 4) / 5, 0, (width * 1) / 5, height)\n }\n\n ctx.translate(-left, -top)\n }\n\n render(ctx: CanvasRenderingContext2D) {\n const { conveyorType } = this.state\n\n if (conveyorType == 'rail') {\n this.renderRtvRail(ctx)\n } else {\n this.renderConveyor(ctx)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"conveyor.js","sourceRoot":"","sources":["../src/conveyor.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ComponentNature, 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: [\n {\n type: 'select',\n label: 'conveyor-type',\n name: 'conveyorType',\n property: {\n options: ['', 'conveyor', 'belt', 'rail']\n }\n },\n {\n type: 'select',\n label: 'conveyor-orientation',\n name: 'orientation',\n property: {\n options: ['', 'horizontal', 'vertical']\n }\n },\n ...MCSTransport.properties\n ]\n}\n\n@sceneComponent('Conveyor')\nexport default class Conveyor extends MCSTransport {\n static get nature() {\n return NATURE\n }\n\n get auxColor() {\n return '#777'\n }\n\n get statusLegendRow(): string {\n return 'conveyor'\n }\n\n containable(component: Component) {\n return ['Shuttle', 'Port', 'Node'].includes(component.state.type)\n }\n\n renderConveyor(ctx: CanvasRenderingContext2D) {\n const { left, top, width, height } = this.bounds\n\n const rollWidth = Math.max(10, Math.min(width, height) / 2)\n\n ctx.beginPath()\n ctx.fillStyle = this.statusColor!\n ctx.strokeStyle = this.auxColor!\n ctx.lineWidth = 1\n\n ctx.translate(left, top)\n ctx.rect(0, 0, width, height)\n ctx.fill()\n ctx.stroke()\n\n ctx.beginPath()\n ctx.strokeStyle = '#aaa'\n\n if (width > height) {\n for (let d = 0; d < width; d += rollWidth) {\n ctx.moveTo(d, 0)\n ctx.lineTo(d, height)\n }\n } else {\n for (let d = 0; d < height; d += rollWidth) {\n ctx.moveTo(0, d)\n ctx.lineTo(width, d)\n }\n }\n\n ctx.stroke()\n\n ctx.translate(-left, -top)\n }\n\n renderRtvRail(ctx: CanvasRenderingContext2D) {\n const { left, top, width, height } = this.bounds\n\n ctx.beginPath()\n\n ctx.translate(left, top)\n\n ctx.fillStyle = this.statusColor!\n\n if (width > height) {\n ctx.fillRect(0, 0, width, (height * 1) / 5)\n ctx.fillRect(0, (height * 4) / 5, width, (height * 1) / 5)\n } else {\n ctx.fillRect(0, 0, (width * 1) / 5, height)\n ctx.fillRect((width * 4) / 5, 0, (width * 1) / 5, height)\n }\n\n ctx.translate(-left, -top)\n }\n\n render(ctx: CanvasRenderingContext2D) {\n const { conveyorType } = this.state\n\n if (conveyorType == 'rail') {\n this.renderRtvRail(ctx)\n } else {\n this.renderConveyor(ctx)\n }\n }\n}\n"]}
package/dist/crane.js CHANGED
@@ -63,8 +63,8 @@ let Crane = class Crane extends LoadLayoutHolder(MCSVehicle) {
63
63
  get parentObjectTypes() {
64
64
  return ['STOCKER'];
65
65
  }
66
- getLegendFallback() {
67
- return this.root.craneLegendTheme || super.getLegendFallback();
66
+ get statusLegendRow() {
67
+ return 'crane';
68
68
  }
69
69
  /**
70
70
  * data.cranePosition = { current: {x,y,z}, limit: {x|y|z:{min,max}} } 분기.
package/dist/crane.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"crane.js","sourceRoot":"","sources":["../src/crane.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ComponentNature, sceneComponent, frameClock } from '@hatiolab/things-scene'\nimport MCSVehicle from './mcs-vehicle'\nimport { LEGEND_CRANE } from './features/mcs-status-default'\nimport { LoadLayoutHolder } from './features/load-layout-holder'\nimport { HOLDER_ANCHOR, forkAnchorId } from '@hatiolab/figure-model'\nimport { craneForkCount } from './utils/crane-forks'\nimport {\n axisRatio,\n mapCraneLocalPosition,\n normalizeCranePosition,\n type CranePositionData\n} from './utils/crane-position'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n ...MCSVehicle.properties,\n {\n type: 'select',\n label: 'fork-count',\n name: 'forkCount',\n property: { options: ['1', '2'] }\n }\n ]\n}\n\n\nconst GAP = 2\n\n/** 좌표 보간 기본 duration (ms). data.DURATION_MS 가 없으면 이 값 사용. */\nconst DEFAULT_DURATION_MS = 1000\n\nfunction lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t\n}\n\nfunction easeInOut(t: number): number {\n return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2\n}\n\ninterface CranePositionAnimator {\n fromLeft: number\n fromTop: number\n fromForkZ: number\n toLeft: number\n toTop: number\n toForkZ: number\n startTime: number\n duration: number\n unsubscribe: () => void\n}\n\n@sceneComponent('Crane')\nexport default class Crane extends LoadLayoutHolder(MCSVehicle) {\n static get nature() {\n return NATURE\n }\n\n /**\n * 크레인이 주는 Anchor (설계 02번 3.7.2절): 홀더 원점과 포크마다 하나(fork_1, fork_2). 포크가 하나뿐인 장비에\n * fork_2 에 선 Tier 가 있으면 레이아웃 전체가 잘못된 값이다: Carrier 를 자리 없이 한 무더기로 쌓고 패널에 오류를 보인다\n * (ADR-0051 4.1절 결정 8).\n */\n slotAnchors(): string[] {\n const forks = craneForkCount((this.state as any).forkCount)\n return [HOLDER_ANCHOR, ...Array.from({ length: forks }, (_, i) => forkAnchorId(i + 1))]\n }\n\n /** 포크 Anchor 는 크레인 3D 의 그 포크 판 윗면 노드다. 포크가 오르내리고 뻗으면 그 위의 Carrier 가 함께 간다 */\n anchorObject3D(anchorId: string): any {\n return (this as any)._realObject?.forkAnchor?.(anchorId) ?? super.anchorObject3D(anchorId)\n }\n\n /** 포크 수가 바뀌면 주는 Anchor 가 바뀌므로, 데이터가 다시 오지 않아도 지금 데이터로 자리를 다시 배정한다 */\n onchange(after: Record<string, any>, before: Record<string, any>): void {\n super.onchange(after, before)\n if ('forkCount' in after && craneForkCount(after.forkCount) !== craneForkCount(before?.forkCount)) {\n ;(this as any)._carrierRecordsTaken = undefined\n ;(this as any).syncCarriers(this.data || {})\n ;(this as any)._carriersSeatedAgain()\n }\n }\n\n get auxColor() {\n return 'black'\n }\n\n /** Crane 의 parentObject 는 STOCKER. */\n get parentObjectTypes(): string[] {\n return ['STOCKER']\n }\n\n getLegendFallback() {\n return (this.root as any).craneLegendTheme || super.getLegendFallback()\n }\n\n private _posAnimator?: CranePositionAnimator\n\n /**\n * data.cranePosition = { current: {x,y,z}, limit: {x|y|z:{min,max}} } 분기.\n * current 를 limit 범위 안의 0~1 비율로 환산한 뒤, 부모 (보통 Stocker) 기준으로\n * 실 좌표 (state.left/top) 와 forkZ 로 변환해 lerp 시작. x→host 긴쪽, y→짧은쪽,\n * z→포크 높이. 보간 중 새 값이 들어오면 *현재 보간 위치* 를 from 으로 잡고 새\n * target 으로 새 lerp 시작.\n * NODEID 경로는 super (MCSVehicle.onchangeData) 가 처리 — cranePosition 만 있는\n * 데이터에선 NODEID 가 없어 자연스럽게 noop.\n */\n onchangeData(after: Record<string, any>, before: Record<string, any>): void {\n const afterData = after?.data\n // 데이터 키는 모두 대문자 전제. CRANEPOSITION 의 중첩 키(CURRENT/LIMIT/X/Y/Z/MIN/MAX)는\n // normalizeCranePosition 이 내부 표준형(소문자)으로 변환. DURATION_MS 는 사용하지 않음.\n const afterCP = normalizeCranePosition(afterData?.CRANEPOSITION)\n if (afterCP) {\n const beforeCP = normalizeCranePosition(before?.data?.CRANEPOSITION)\n if (this._cranePositionChanged(afterCP, beforeCP)) {\n this._startPositionAnimation(afterCP)\n }\n }\n super.onchangeData(after, before)\n }\n\n /** current 또는 limit 중 하나라도 바뀌면 재계산 필요 (limit 변화도 실 위치를 바꿈). */\n private _cranePositionChanged(a: CranePositionData, b?: CranePositionData): boolean {\n if (!b) return true\n return (\n JSON.stringify(a?.current ?? null) !== JSON.stringify(b?.current ?? null) ||\n JSON.stringify(a?.limit ?? null) !== JSON.stringify(b?.limit ?? null)\n )\n }\n\n dispose() {\n if (this._posAnimator) {\n this._posAnimator.unsubscribe()\n this._posAnimator = undefined\n }\n super.dispose()\n }\n\n private _startPositionAnimation(cranePosition: CranePositionData, durationMs?: number): void {\n const target = this._ratioToReal(cranePosition)\n if (!target) return // 부모(host) 없거나 크기 0 이면 변환 skip\n\n const now = frameClock.simTime\n const duration = Math.max(1, Number(durationMs) || DEFAULT_DURATION_MS)\n\n // 현재 위치 — 보간 중이면 그 시점 보간값을 from 으로\n let fromLeft = Number(this.state.left) || 0\n let fromTop = Number(this.state.top) || 0\n let fromForkZ = Number((this.state as any).forkZ) || 0\n\n if (this._posAnimator) {\n const a = this._posAnimator\n const t = Math.min(1, Math.max(0, (now - a.startTime) / a.duration))\n const e = easeInOut(t)\n fromLeft = lerp(a.fromLeft, a.toLeft, e)\n fromTop = lerp(a.fromTop, a.toTop, e)\n fromForkZ = lerp(a.fromForkZ, a.toForkZ, e)\n a.unsubscribe()\n this._posAnimator = undefined\n }\n\n const unsubscribe = frameClock.subscribe(\n (_dt: number, simTime: number) => this._tickPositionAnimation(simTime),\n { description: 'crane-position', component: this }\n )\n\n this._posAnimator = {\n fromLeft,\n fromTop,\n fromForkZ,\n toLeft: target.left,\n toTop: target.top,\n toForkZ: target.forkZ,\n startTime: now,\n duration,\n unsubscribe\n }\n // 즉시 첫 frame 반영 (t=0) — set 한 번 호출. paused 환경에서도 from→target\n // 진입 시점이 명확.\n this._tickPositionAnimation(now)\n }\n\n private _tickPositionAnimation(simTime: number): void {\n const a = this._posAnimator\n if (!a) return\n const t = Math.min(1, Math.max(0, (simTime - a.startTime) / a.duration))\n const e = easeInOut(t)\n this.set({\n left: lerp(a.fromLeft, a.toLeft, e),\n top: lerp(a.fromTop, a.toTop, e),\n forkZ: lerp(a.fromForkZ, a.toForkZ, e)\n })\n if (t >= 1) {\n a.unsubscribe()\n this._posAnimator = undefined\n }\n }\n\n /**\n * cranePosition (current + limit) → state.left/top + forkZ.\n *\n * 부모 오브젝트 (보통은 Stocker 이지만 다른 컨테이너일 수도) 의 width/height\n * 만 사용해 좌표 매핑 — 타입 무관 일반화. 축 배정과 원점은 host 의 내부 좌표계 설정을\n * 따른다 (coordAxisX / coordInvertX / coordInvertY, 미설정 시 아래 폴백):\n * - current.x → X축 (기본: host 의 긴쪽, 자동 판별 max(width, height))\n * - current.y → Y축 (기본: 짧은쪽)\n * - current.z → forkZ (state 에 0~100 으로 저장, 3D 측에서 mast 비율로 매핑).\n * Z 는 바닥 기준이 물리적으로 고정이라 반전 설정을 두지 않는다.\n *\n * 각 축 비율 = (current - limit.min) / (limit.max - limit.min) ∈ [0,1].\n *\n * **스토커 안쪽 오프셋**: 크레인의 폭/두께를 감안해, 크레인 *전체* 가 host 안에\n * 머무르도록 top-left 좌표를 [0, hostLen - craneLen] 범위로 매핑한다 (= 양끝에서\n * craneLen/2 만큼 inset 된 중심선 위를 움직임). 크레인이 host 보다 크면 span 0\n * 으로 떨어져 host 모서리에 정렬.\n *\n * 참조는 ParentObjectMixin 이 제공하는 `parentObject` 사용 —\n * state.parentObjectId 명시 시 그것, 미명시 시 this.parent 자동 fallback.\n */\n private _ratioToReal(\n cp: CranePositionData\n ): { left: number; top: number; forkZ: number } | undefined {\n const host: any = (this as any).parentObject\n if (!host) return undefined\n\n const hw = Number(host.state?.width) || 0\n const hh = Number(host.state?.height) || 0\n const cw = Number(this.state.width) || 0\n const ch = Number(this.state.height) || 0\n if (!hw || !hh) return undefined\n\n const rx = axisRatio(cp.current?.x, cp.limit?.x)\n const ry = axisRatio(cp.current?.y, cp.limit?.y)\n const rz = axisRatio(cp.current?.z, cp.limit?.z)\n\n // 축 배정/원점은 host(보통 STOCKER) 의 내부 좌표계 설정을 따른다. 타입을 묻지 않고\n // state 만 읽어 어떤 컨테이너가 host 여도 동일하게 동작한다 — 미설정이면 종전\n // 폴백(긴쪽=X, 원점 left/top).\n const { left, top } = mapCraneLocalPosition(hw, hh, cw, ch, rx, ry, {\n axisX: host.state?.coordAxisX,\n invertX: !!host.state?.coordInvertX,\n invertY: !!host.state?.coordInvertY\n })\n\n return {\n left,\n top,\n forkZ: rz * 100 // forkZ 0~100, 3D 측 (crane-3d) 에서 mast 비율로 매핑\n }\n }\n\n render(ctx: CanvasRenderingContext2D) {\n var { left, top, width, height } = this.bounds\n const { x: cx, y: cy } = this.center\n const rx = width / 2\n const ry = height / 2\n\n const round = Math.min(rx, ry) * 0.5\n\n ctx.translate(left, top)\n ctx.beginPath()\n\n ctx.strokeStyle = this.auxColor\n ctx.fillStyle = this.statusColor!\n ctx.lineWidth = 1\n ctx.lineCap = 'round'\n ctx.setLineDash([])\n\n const radius = Math.round(Math.min(width, height) * 0.1)\n ctx.roundRect(1, 0, width - 2, height, radius)\n ctx.roundRect(GAP + 1, GAP, width - (GAP + 1) * 2, height - GAP * 2, radius - 1)\n ctx.fill()\n ctx.stroke()\n\n ctx.beginPath()\n ctx.arc(cx - left, cy - top, round, 0, Math.PI * 2)\n ctx.stroke()\n\n ctx.beginPath()\n ctx.roundRect(width / 2 - (round * 2) / 4 - round / 8, height / 2 - (round * 6) / 5, round / 4, (round * 6) / 5, 1)\n ctx.roundRect(width / 2 + (round * 2) / 4 - round / 8, height / 2 - (round * 6) / 5, round / 4, (round * 6) / 5, 1)\n\n ctx.fill()\n ctx.stroke()\n\n ctx.beginPath()\n\n // draw crane bar metapore\n ctx.strokeStyle = 'black'\n ctx.lineWidth = 3\n ctx.lineCap = 'butt'\n\n ctx.moveTo(GAP * 3, height / 2)\n ctx.lineTo(width - GAP * 3, height / 2)\n\n ctx.stroke()\n\n ctx.translate(-left, -top)\n }\n}\n"]}
1
+ {"version":3,"file":"crane.js","sourceRoot":"","sources":["../src/crane.ts"],"names":[],"mappings":"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","sourcesContent":["import { Component, ComponentNature, sceneComponent, frameClock } from '@hatiolab/things-scene'\nimport MCSVehicle from './mcs-vehicle'\nimport { LEGEND_CRANE } from './features/mcs-status-default'\nimport { LoadLayoutHolder } from './features/load-layout-holder'\nimport { HOLDER_ANCHOR, forkAnchorId } from '@hatiolab/figure-model'\nimport { craneForkCount } from './utils/crane-forks'\nimport {\n axisRatio,\n mapCraneLocalPosition,\n normalizeCranePosition,\n type CranePositionData\n} from './utils/crane-position'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n ...MCSVehicle.properties,\n {\n type: 'select',\n label: 'fork-count',\n name: 'forkCount',\n property: { options: ['1', '2'] }\n }\n ]\n}\n\n\nconst GAP = 2\n\n/** 좌표 보간 기본 duration (ms). data.DURATION_MS 가 없으면 이 값 사용. */\nconst DEFAULT_DURATION_MS = 1000\n\nfunction lerp(a: number, b: number, t: number): number {\n return a + (b - a) * t\n}\n\nfunction easeInOut(t: number): number {\n return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2\n}\n\ninterface CranePositionAnimator {\n fromLeft: number\n fromTop: number\n fromForkZ: number\n toLeft: number\n toTop: number\n toForkZ: number\n startTime: number\n duration: number\n unsubscribe: () => void\n}\n\n@sceneComponent('Crane')\nexport default class Crane extends LoadLayoutHolder(MCSVehicle) {\n static get nature() {\n return NATURE\n }\n\n /**\n * 크레인이 주는 Anchor (설계 02번 3.7.2절): 홀더 원점과 포크마다 하나(fork_1, fork_2). 포크가 하나뿐인 장비에\n * fork_2 에 선 Tier 가 있으면 레이아웃 전체가 잘못된 값이다: Carrier 를 자리 없이 한 무더기로 쌓고 패널에 오류를 보인다\n * (ADR-0051 4.1절 결정 8).\n */\n slotAnchors(): string[] {\n const forks = craneForkCount((this.state as any).forkCount)\n return [HOLDER_ANCHOR, ...Array.from({ length: forks }, (_, i) => forkAnchorId(i + 1))]\n }\n\n /** 포크 Anchor 는 크레인 3D 의 그 포크 판 윗면 노드다. 포크가 오르내리고 뻗으면 그 위의 Carrier 가 함께 간다 */\n anchorObject3D(anchorId: string): any {\n return (this as any)._realObject?.forkAnchor?.(anchorId) ?? super.anchorObject3D(anchorId)\n }\n\n /** 포크 수가 바뀌면 주는 Anchor 가 바뀌므로, 데이터가 다시 오지 않아도 지금 데이터로 자리를 다시 배정한다 */\n onchange(after: Record<string, any>, before: Record<string, any>): void {\n super.onchange(after, before)\n if ('forkCount' in after && craneForkCount(after.forkCount) !== craneForkCount(before?.forkCount)) {\n ;(this as any)._carrierRecordsTaken = undefined\n ;(this as any).syncCarriers(this.data || {})\n ;(this as any)._carriersSeatedAgain()\n }\n }\n\n get auxColor() {\n return 'black'\n }\n\n /** Crane 의 parentObject 는 STOCKER. */\n get parentObjectTypes(): string[] {\n return ['STOCKER']\n }\n\n get statusLegendRow(): string {\n return 'crane'\n }\n\n private _posAnimator?: CranePositionAnimator\n\n /**\n * data.cranePosition = { current: {x,y,z}, limit: {x|y|z:{min,max}} } 분기.\n * current 를 limit 범위 안의 0~1 비율로 환산한 뒤, 부모 (보통 Stocker) 기준으로\n * 실 좌표 (state.left/top) 와 forkZ 로 변환해 lerp 시작. x→host 긴쪽, y→짧은쪽,\n * z→포크 높이. 보간 중 새 값이 들어오면 *현재 보간 위치* 를 from 으로 잡고 새\n * target 으로 새 lerp 시작.\n * NODEID 경로는 super (MCSVehicle.onchangeData) 가 처리 — cranePosition 만 있는\n * 데이터에선 NODEID 가 없어 자연스럽게 noop.\n */\n onchangeData(after: Record<string, any>, before: Record<string, any>): void {\n const afterData = after?.data\n // 데이터 키는 모두 대문자 전제. CRANEPOSITION 의 중첩 키(CURRENT/LIMIT/X/Y/Z/MIN/MAX)는\n // normalizeCranePosition 이 내부 표준형(소문자)으로 변환. DURATION_MS 는 사용하지 않음.\n const afterCP = normalizeCranePosition(afterData?.CRANEPOSITION)\n if (afterCP) {\n const beforeCP = normalizeCranePosition(before?.data?.CRANEPOSITION)\n if (this._cranePositionChanged(afterCP, beforeCP)) {\n this._startPositionAnimation(afterCP)\n }\n }\n super.onchangeData(after, before)\n }\n\n /** current 또는 limit 중 하나라도 바뀌면 재계산 필요 (limit 변화도 실 위치를 바꿈). */\n private _cranePositionChanged(a: CranePositionData, b?: CranePositionData): boolean {\n if (!b) return true\n return (\n JSON.stringify(a?.current ?? null) !== JSON.stringify(b?.current ?? null) ||\n JSON.stringify(a?.limit ?? null) !== JSON.stringify(b?.limit ?? null)\n )\n }\n\n dispose() {\n if (this._posAnimator) {\n this._posAnimator.unsubscribe()\n this._posAnimator = undefined\n }\n super.dispose()\n }\n\n private _startPositionAnimation(cranePosition: CranePositionData, durationMs?: number): void {\n const target = this._ratioToReal(cranePosition)\n if (!target) return // 부모(host) 없거나 크기 0 이면 변환 skip\n\n const now = frameClock.simTime\n const duration = Math.max(1, Number(durationMs) || DEFAULT_DURATION_MS)\n\n // 현재 위치 — 보간 중이면 그 시점 보간값을 from 으로\n let fromLeft = Number(this.state.left) || 0\n let fromTop = Number(this.state.top) || 0\n let fromForkZ = Number((this.state as any).forkZ) || 0\n\n if (this._posAnimator) {\n const a = this._posAnimator\n const t = Math.min(1, Math.max(0, (now - a.startTime) / a.duration))\n const e = easeInOut(t)\n fromLeft = lerp(a.fromLeft, a.toLeft, e)\n fromTop = lerp(a.fromTop, a.toTop, e)\n fromForkZ = lerp(a.fromForkZ, a.toForkZ, e)\n a.unsubscribe()\n this._posAnimator = undefined\n }\n\n const unsubscribe = frameClock.subscribe(\n (_dt: number, simTime: number) => this._tickPositionAnimation(simTime),\n { description: 'crane-position', component: this }\n )\n\n this._posAnimator = {\n fromLeft,\n fromTop,\n fromForkZ,\n toLeft: target.left,\n toTop: target.top,\n toForkZ: target.forkZ,\n startTime: now,\n duration,\n unsubscribe\n }\n // 즉시 첫 frame 반영 (t=0) — set 한 번 호출. paused 환경에서도 from→target\n // 진입 시점이 명확.\n this._tickPositionAnimation(now)\n }\n\n private _tickPositionAnimation(simTime: number): void {\n const a = this._posAnimator\n if (!a) return\n const t = Math.min(1, Math.max(0, (simTime - a.startTime) / a.duration))\n const e = easeInOut(t)\n this.set({\n left: lerp(a.fromLeft, a.toLeft, e),\n top: lerp(a.fromTop, a.toTop, e),\n forkZ: lerp(a.fromForkZ, a.toForkZ, e)\n })\n if (t >= 1) {\n a.unsubscribe()\n this._posAnimator = undefined\n }\n }\n\n /**\n * cranePosition (current + limit) → state.left/top + forkZ.\n *\n * 부모 오브젝트 (보통은 Stocker 이지만 다른 컨테이너일 수도) 의 width/height\n * 만 사용해 좌표 매핑 — 타입 무관 일반화. 축 배정과 원점은 host 의 내부 좌표계 설정을\n * 따른다 (coordAxisX / coordInvertX / coordInvertY, 미설정 시 아래 폴백):\n * - current.x → X축 (기본: host 의 긴쪽, 자동 판별 max(width, height))\n * - current.y → Y축 (기본: 짧은쪽)\n * - current.z → forkZ (state 에 0~100 으로 저장, 3D 측에서 mast 비율로 매핑).\n * Z 는 바닥 기준이 물리적으로 고정이라 반전 설정을 두지 않는다.\n *\n * 각 축 비율 = (current - limit.min) / (limit.max - limit.min) ∈ [0,1].\n *\n * **스토커 안쪽 오프셋**: 크레인의 폭/두께를 감안해, 크레인 *전체* 가 host 안에\n * 머무르도록 top-left 좌표를 [0, hostLen - craneLen] 범위로 매핑한다 (= 양끝에서\n * craneLen/2 만큼 inset 된 중심선 위를 움직임). 크레인이 host 보다 크면 span 0\n * 으로 떨어져 host 모서리에 정렬.\n *\n * 참조는 ParentObjectMixin 이 제공하는 `parentObject` 사용 —\n * state.parentObjectId 명시 시 그것, 미명시 시 this.parent 자동 fallback.\n */\n private _ratioToReal(\n cp: CranePositionData\n ): { left: number; top: number; forkZ: number } | undefined {\n const host: any = (this as any).parentObject\n if (!host) return undefined\n\n const hw = Number(host.state?.width) || 0\n const hh = Number(host.state?.height) || 0\n const cw = Number(this.state.width) || 0\n const ch = Number(this.state.height) || 0\n if (!hw || !hh) return undefined\n\n const rx = axisRatio(cp.current?.x, cp.limit?.x)\n const ry = axisRatio(cp.current?.y, cp.limit?.y)\n const rz = axisRatio(cp.current?.z, cp.limit?.z)\n\n // 축 배정/원점은 host(보통 STOCKER) 의 내부 좌표계 설정을 따른다. 타입을 묻지 않고\n // state 만 읽어 어떤 컨테이너가 host 여도 동일하게 동작한다 — 미설정이면 종전\n // 폴백(긴쪽=X, 원점 left/top).\n const { left, top } = mapCraneLocalPosition(hw, hh, cw, ch, rx, ry, {\n axisX: host.state?.coordAxisX,\n invertX: !!host.state?.coordInvertX,\n invertY: !!host.state?.coordInvertY\n })\n\n return {\n left,\n top,\n forkZ: rz * 100 // forkZ 0~100, 3D 측 (crane-3d) 에서 mast 비율로 매핑\n }\n }\n\n render(ctx: CanvasRenderingContext2D) {\n var { left, top, width, height } = this.bounds\n const { x: cx, y: cy } = this.center\n const rx = width / 2\n const ry = height / 2\n\n const round = Math.min(rx, ry) * 0.5\n\n ctx.translate(left, top)\n ctx.beginPath()\n\n ctx.strokeStyle = this.auxColor\n ctx.fillStyle = this.statusColor!\n ctx.lineWidth = 1\n ctx.lineCap = 'round'\n ctx.setLineDash([])\n\n const radius = Math.round(Math.min(width, height) * 0.1)\n ctx.roundRect(1, 0, width - 2, height, radius)\n ctx.roundRect(GAP + 1, GAP, width - (GAP + 1) * 2, height - GAP * 2, radius - 1)\n ctx.fill()\n ctx.stroke()\n\n ctx.beginPath()\n ctx.arc(cx - left, cy - top, round, 0, Math.PI * 2)\n ctx.stroke()\n\n ctx.beginPath()\n ctx.roundRect(width / 2 - (round * 2) / 4 - round / 8, height / 2 - (round * 6) / 5, round / 4, (round * 6) / 5, 1)\n ctx.roundRect(width / 2 + (round * 2) / 4 - round / 8, height / 2 - (round * 6) / 5, round / 4, (round * 6) / 5, 1)\n\n ctx.fill()\n ctx.stroke()\n\n ctx.beginPath()\n\n // draw crane bar metapore\n ctx.strokeStyle = 'black'\n ctx.lineWidth = 3\n ctx.lineCap = 'butt'\n\n ctx.moveTo(GAP * 3, height / 2)\n ctx.lineTo(width - GAP * 3, height / 2)\n\n ctx.stroke()\n\n ctx.translate(-left, -top)\n }\n}\n"]}
package/dist/equipment.js CHANGED
@@ -11,8 +11,8 @@ let Equipment = class Equipment extends MCSMachine {
11
11
  static get nature() {
12
12
  return NATURE;
13
13
  }
14
- getLegendFallback() {
15
- return this.root.equipmentLegendTheme || super.getLegendFallback();
14
+ get statusLegendRow() {
15
+ return 'equipment';
16
16
  }
17
17
  containable(component) {
18
18
  return super.containable(component) || ['Port'].includes(component.state.type);
@@ -1 +1 @@
1
- {"version":3,"file":"equipment.js","sourceRoot":"","sources":["../src/equipment.ts"],"names":[],"mappings":";AAAA,OAAO,EAA8B,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACnF,OAAO,UAAU,MAAM,eAAe,CAAA;AAEtC,MAAM,MAAM,GAAoB;IAC9B,OAAO,EAAE,KAAK;IACd,SAAS,EAAE,IAAI;IACf,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC;CACvC,CAAA;AAGc,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,UAAU;IAC/C,MAAM,KAAK,MAAM;QACf,OAAO,MAAM,CAAA;IACf,CAAC;IAED,iBAAiB;QACf,OAAQ,IAAI,CAAC,IAAY,CAAC,oBAAoB,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAA;IAC7E,CAAC;IAED,WAAW,CAAC,SAAoB;QAC9B,OAAO,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAChF,CAAC;CACF,CAAA;AAZoB,SAAS;IAD7B,cAAc,CAAC,WAAW,CAAC;GACP,SAAS,CAY7B;eAZoB,SAAS","sourcesContent":["import { Component, ComponentNature, sceneComponent } from '@hatiolab/things-scene'\nimport MCSMachine from './mcs-machine'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [...MCSMachine.properties]\n}\n\n@sceneComponent('Equipment')\nexport default class Equipment extends MCSMachine {\n static get nature() {\n return NATURE\n }\n\n getLegendFallback() {\n return (this.root as any).equipmentLegendTheme || super.getLegendFallback()\n }\n\n containable(component: Component) {\n return super.containable(component) || ['Port'].includes(component.state.type)\n }\n}\n"]}
1
+ {"version":3,"file":"equipment.js","sourceRoot":"","sources":["../src/equipment.ts"],"names":[],"mappings":";AAAA,OAAO,EAA8B,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACnF,OAAO,UAAU,MAAM,eAAe,CAAA;AAEtC,MAAM,MAAM,GAAoB;IAC9B,OAAO,EAAE,KAAK;IACd,SAAS,EAAE,IAAI;IACf,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC;CACvC,CAAA;AAGc,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,UAAU;IAC/C,MAAM,KAAK,MAAM;QACf,OAAO,MAAM,CAAA;IACf,CAAC;IAED,IAAI,eAAe;QACjB,OAAO,WAAW,CAAA;IACpB,CAAC;IAED,WAAW,CAAC,SAAoB;QAC9B,OAAO,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAChF,CAAC;CACF,CAAA;AAZoB,SAAS;IAD7B,cAAc,CAAC,WAAW,CAAC;GACP,SAAS,CAY7B;eAZoB,SAAS","sourcesContent":["import { Component, ComponentNature, sceneComponent } from '@hatiolab/things-scene'\nimport MCSMachine from './mcs-machine'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [...MCSMachine.properties]\n}\n\n@sceneComponent('Equipment')\nexport default class Equipment extends MCSMachine {\n static get nature() {\n return NATURE\n }\n\n get statusLegendRow(): string {\n return 'equipment'\n }\n\n containable(component: Component) {\n return super.containable(component) || ['Port'].includes(component.state.type)\n }\n}\n"]}
@@ -13,7 +13,7 @@
13
13
  import * as THREE from 'three';
14
14
  import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js';
15
15
  import { RealObjectGroup, registerRealObjectFactory, MaterialBank } from '@hatiolab/things-scene';
16
- import { TRANSPORT_SURFACE_HEIGHT } from './machine-3d.js';
16
+ import { MACHINE_HEIGHTS } from '../features/lv-heights.js';
17
17
  import { Z_FMSIM } from './z-priority';
18
18
  const FRAME_COLOR = 0x888899;
19
19
  const ROLLER_COLOR = 0xaaaabc;
@@ -22,7 +22,7 @@ export class Conveyor3D extends RealObjectGroup {
22
22
  get zPriority() { return Z_FMSIM.CONVEYOR; }
23
23
  get effectiveDepth() {
24
24
  const { depth } = this.component.state;
25
- return depth || TRANSPORT_SURFACE_HEIGHT;
25
+ return depth || MACHINE_HEIGHTS.conveyor;
26
26
  }
27
27
  resolveColor() {
28
28
  const comp = this.component;
@@ -1 +1 @@
1
- {"version":3,"file":"conveyor-3d.js","sourceRoot":"","sources":["../../src/factories/conveyor-3d.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Conveyor 3D Factory\n *\n * 'conveyor' type (default): side rails + cylindrical rollers + 4 legs + cross-bracing\n * 'belt' type: side rails + two end drums + belt wrapping + 4 legs + cross-bracing\n * 'rail' type: side rails + two parallel rails + 4 legs + cross-bracing\n *\n * Based on operato-scene conveyor-3d.ts, adapted for fmsim:\n * - conveyorType is string ('', 'conveyor', 'belt', 'rail') instead of numeric\n * - statusColor from MCSStatusMixin instead of value-based lookup\n * - rollWidth auto-calculated: Math.max(10, Math.min(width, height) / 2)\n */\n\nimport * as THREE from 'three'\nimport * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js'\nimport { RealObjectGroup, registerRealObjectFactory, MaterialBank } from '@hatiolab/things-scene'\nimport type { Component } from '@hatiolab/things-scene'\nimport { TRANSPORT_SURFACE_HEIGHT } from './machine-3d.js'\nimport { Z_FMSIM } from './z-priority'\n\nconst FRAME_COLOR = 0x888899\nconst ROLLER_COLOR = 0xaaaabc\nconst DEFAULT_COLOR = 0x999999\n\nexport class Conveyor3D extends RealObjectGroup {\n get zPriority(): number { return Z_FMSIM.CONVEYOR }\n\n get effectiveDepth(): number {\n const { depth } = this.component.state\n return depth || TRANSPORT_SURFACE_HEIGHT\n }\n\n private resolveColor(): number {\n const comp = this.component as any\n\n // 1) MCSStatusMixin.statusColor (legend 기반 상태 색상)\n // '#F0F0F0'은 상태 미설정 시 기본 fallback — 무시하고 defaultColor 사용\n try {\n const sc = comp.statusColor\n if (typeof sc === 'string' && sc && sc.toUpperCase() !== '#F0F0F0' && sc !== 'transparent') return new THREE.Color(sc).getHex()\n } catch {\n /* statusColor 미구현 시 무시 */\n }\n\n // 2) state.fillStyle fallback\n const { fillStyle } = this.component.state\n if (fillStyle && typeof fillStyle === 'string' && fillStyle !== 'transparent') {\n try {\n return new THREE.Color(fillStyle).getHex()\n } catch {\n /* 파싱 실패 시 무시 */\n }\n }\n\n return DEFAULT_COLOR\n }\n\n build() {\n super.build()\n\n const { width: rawWidth, height: rawHeight, conveyorType, orientation } = this.component.state\n const depth = this.effectiveDepth\n if (!rawWidth || !rawHeight) return\n\n // orientation: 'horizontal' = 롤러가 Z축(세로), 'vertical' = 롤러가 X축(가로)\n // default = 긴 방향에 수직 (긴 축을 따라 이송)\n const isVertical = orientation === 'vertical' ? true\n : orientation === 'horizontal' ? false\n : rawWidth < rawHeight // default: 세로가 길면 롤러는 가로(X축)\n // isVertical=true → 롤러 축이 X(가로), 이송 방향이 Z(세로)\n // isVertical=false → 롤러 축이 Z(세로), 이송 방향이 X(가로)\n const width = rawWidth\n const height = rawHeight\n\n // 2D와 동일 로직으로 rollWidth 산출\n const rollWidth = Math.max(10, Math.min(width, height) / 2)\n const rollerDiameter = Math.max(rollWidth, 2)\n const frameH = Math.min(rollerDiameter, depth)\n const legH = Math.max(depth - frameH, 0)\n\n // isVertical일 때 이송 방향이 Z축: 레일은 Z축을 따라, 벨트폭은 width\n // !isVertical일 때 이송 방향이 X축: 레일은 X축을 따라, 벨트폭은 height\n const beltWidth = isVertical ? width : height\n const railLen = isVertical ? height : width\n const railW = Math.max(beltWidth * 0.06, 2)\n const legThickness = Math.max(railW * 0.8, 2)\n\n // MaterialBank 공유(dedup). 자체 update() 없이 base 생명주기(guarded disposeObject3D) 상속 → 안전.\n const frameMaterial = MaterialBank.material('conveyor|frame', { metalness: 0.85, roughness: 0.35 }, FRAME_COLOR)\n\n // --- Frame: side rails + legs + cross-bracing ---\n // Y 좌표: y=0(바닥) ~ y=depth(상단). 레일 상단이 depth에 위치.\n const frameGeometries: THREE.BufferGeometry[] = []\n const railY = depth - frameH / 2\n\n // Side rails — 이송 방향을 따라, 벨트 양측에 배치\n if (isVertical) {\n // 레일이 Z축(세로)을 따라, ±X에 배치\n for (const xSign of [-1, 1]) {\n const rail = new THREE.BoxGeometry(railW, frameH, height)\n rail.translate(xSign * (width / 2 - railW / 2), railY, 0)\n frameGeometries.push(rail)\n }\n } else {\n // 레일이 X축(가로)을 따라, ±Z에 배치\n for (const zSign of [-1, 1]) {\n const rail = new THREE.BoxGeometry(width, frameH, railW)\n rail.translate(0, railY, zSign * (height / 2 - railW / 2))\n frameGeometries.push(rail)\n }\n }\n\n // 4 legs at corners\n if (legH > 0) {\n const legTopY = depth - frameH\n const legCenterY = legTopY - legH / 2\n\n // 다리 위치: 레일 안쪽에 정렬\n const legXPos = isVertical ? (width / 2 - railW / 2) : (width / 2 - legThickness / 2)\n const legZPos = isVertical ? (height / 2 - legThickness / 2) : (height / 2 - railW / 2)\n\n for (const xSign of [-1, 1]) {\n for (const zSign of [-1, 1]) {\n const leg = new THREE.BoxGeometry(legThickness, legH, legThickness)\n leg.translate(xSign * legXPos, legCenterY, zSign * legZPos)\n frameGeometries.push(leg)\n }\n }\n\n // Cross-bracing\n const braceH = legThickness * 0.6\n const braceW = legThickness * 0.6\n const braceY = legTopY - legH * 0.35\n\n // 이송 방향 브레이스 (레일과 평행)\n if (isVertical) {\n for (const xSign of [-1, 1]) {\n const brace = new THREE.BoxGeometry(braceW, braceH, height - legThickness)\n brace.translate(xSign * legXPos, braceY, 0)\n frameGeometries.push(brace)\n }\n } else {\n for (const zSign of [-1, 1]) {\n const brace = new THREE.BoxGeometry(width - legThickness, braceH, braceW)\n brace.translate(0, braceY, zSign * legZPos)\n frameGeometries.push(brace)\n }\n }\n\n // 벨트폭 방향 브레이스 (레일과 수직)\n if (isVertical) {\n for (const zSign of [-1, 1]) {\n const brace = new THREE.BoxGeometry(width - railW, braceH, braceW)\n brace.translate(0, braceY, zSign * legZPos)\n frameGeometries.push(brace)\n }\n } else {\n for (const xSign of [-1, 1]) {\n const brace = new THREE.BoxGeometry(braceW, braceH, height - railW)\n brace.translate(xSign * legXPos, braceY, 0)\n frameGeometries.push(brace)\n }\n }\n }\n\n const frameMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(frameGeometries), frameMaterial)\n frameMesh.castShadow = true\n frameMesh.receiveShadow = true\n this.components3D.add(frameMesh)\n\n // --- Rollers, Belt, or Rails ---\n if (conveyorType === 'rail') {\n this.buildRails(width, height, depth, frameH, railW, isVertical)\n } else if (conveyorType === 'belt') {\n this.buildBelt(width, height, depth, frameH, railW, isVertical)\n } else {\n this.buildRollers(width, height, depth, frameH, railW, rollWidth, isVertical)\n }\n\n // mesh 는 super.build() 이후 생성 → 코어 faint 를 명시 적용(편집 흐림이 mesh 에 닿게).\n this.updateAlpha()\n }\n\n private buildRollers(\n width: number,\n height: number,\n depth: number,\n frameH: number,\n railW: number,\n rollWidth: number,\n isVertical: boolean = false\n ) {\n const rollerRadius = Math.max(rollWidth / 8, 1)\n const diameter = rollerRadius * 2\n const step = diameter * 1.05\n const rollerY = depth - rollerRadius\n const color = this.resolveColor()\n\n const rollerGeometries: THREE.BufferGeometry[] = []\n\n if (isVertical) {\n // 롤러 축 = X축(가로), 이송 방향 = Z축(세로)\n const rollerLength = width - railW * 2 - 0.5\n const count = Math.max(1, Math.floor(height / step))\n const totalSpan = (count - 1) * step\n const startZ = -totalSpan / 2\n\n for (let i = 0; i < count; i++) {\n const z = startZ + i * step\n const roller = new THREE.CylinderGeometry(rollerRadius, rollerRadius, rollerLength, 16)\n roller.rotateZ(Math.PI / 2)\n roller.translate(0, rollerY, z)\n rollerGeometries.push(roller)\n }\n } else {\n // 롤러 축 = Z축(세로), 이송 방향 = X축(가로) — 기존 동작\n const rollerLength = height - railW * 2 - 0.5\n const count = Math.max(1, Math.floor(width / step))\n const totalSpan = (count - 1) * step\n const startX = -totalSpan / 2\n\n for (let i = 0; i < count; i++) {\n const x = startX + i * step\n const roller = new THREE.CylinderGeometry(rollerRadius, rollerRadius, rollerLength, 16)\n roller.rotateX(Math.PI / 2)\n roller.translate(x, rollerY, 0)\n rollerGeometries.push(roller)\n }\n }\n\n if (rollerGeometries.length > 0) {\n const rollerMesh = new THREE.Mesh(\n BufferGeometryUtils.mergeGeometries(rollerGeometries),\n MaterialBank.material('conveyor|roller', { metalness: 0.9, roughness: 0.2 }, color)\n )\n rollerMesh.castShadow = true\n this.components3D.add(rollerMesh)\n }\n }\n\n private buildBelt(width: number, height: number, depth: number, frameH: number, railW: number, isVertical: boolean = false) {\n const drumRadius = frameH * 0.38\n const beltY = depth - drumRadius\n const color = this.resolveColor()\n\n // 이송 방향 길이와 벨트폭\n const transportLen = isVertical ? height : width\n const beltWidth = isVertical ? width : height\n const drumLength = beltWidth - railW * 2\n\n // Two end drums\n const drumGeometries: THREE.BufferGeometry[] = []\n const drumInset = drumRadius * 1.5\n const drum1 = -transportLen / 2 + drumInset\n const drum2 = transportLen / 2 - drumInset\n\n for (const dp of [drum1, drum2]) {\n const drum = new THREE.CylinderGeometry(drumRadius, drumRadius, drumLength, 16)\n if (isVertical) {\n drum.rotateZ(Math.PI / 2)\n drum.translate(0, beltY, dp)\n } else {\n drum.rotateX(Math.PI / 2)\n drum.translate(dp, beltY, 0)\n }\n drumGeometries.push(drum)\n }\n\n const drumMesh = new THREE.Mesh(\n BufferGeometryUtils.mergeGeometries(drumGeometries),\n MaterialBank.material('conveyor|drum', { metalness: 0.9, roughness: 0.2 }, ROLLER_COLOR)\n )\n drumMesh.castShadow = true\n this.components3D.add(drumMesh)\n\n // Belt surface\n const beltThickness = drumRadius * 0.12\n const beltMaterial = MaterialBank.material('conveyor|belt', { metalness: 0.0, roughness: 0.9 }, color)\n\n // Flat belt top surface spanning between drums\n const flatLen = drum2 - drum1\n const flatGeo = isVertical\n ? new THREE.BoxGeometry(drumLength, beltThickness, flatLen)\n : new THREE.BoxGeometry(flatLen, beltThickness, drumLength)\n const flatMesh = new THREE.Mesh(flatGeo, beltMaterial)\n flatMesh.position.set(0, beltY + drumRadius, 0)\n flatMesh.castShadow = true\n this.components3D.add(flatMesh)\n\n // Belt wrap around drums (segmented half-cylinder)\n const wrapSegments = 12\n for (const [dp, angleStart] of [\n [drum1, Math.PI / 2],\n [drum2, -Math.PI / 2],\n ] as [number, number][]) {\n const wrapGeometries: THREE.BufferGeometry[] = []\n for (let i = 0; i < wrapSegments; i++) {\n const a0 = angleStart + (Math.PI * i) / wrapSegments\n const a1 = angleStart + (Math.PI * (i + 1)) / wrapSegments\n const r = drumRadius + beltThickness / 2\n\n const p0 = dp + Math.cos(a0) * r\n const y0 = beltY + Math.sin(a0) * r\n const p1 = dp + Math.cos(a1) * r\n const y1 = beltY + Math.sin(a1) * r\n\n const segLen = Math.sqrt((p1 - p0) ** 2 + (y1 - y0) ** 2) * 1.05\n const segAngle = Math.atan2(y1 - y0, p1 - p0)\n\n if (isVertical) {\n const seg = new THREE.BoxGeometry(drumLength, beltThickness, segLen)\n seg.rotateX(-segAngle)\n seg.translate(0, (y0 + y1) / 2, (p0 + p1) / 2)\n wrapGeometries.push(seg)\n } else {\n const seg = new THREE.BoxGeometry(segLen, beltThickness, drumLength)\n seg.rotateZ(segAngle)\n seg.translate((p0 + p1) / 2, (y0 + y1) / 2, 0)\n wrapGeometries.push(seg)\n }\n }\n const wrapMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(wrapGeometries), beltMaterial)\n wrapMesh.castShadow = true\n this.components3D.add(wrapMesh)\n }\n\n // Flat belt bottom (return path)\n const bottomGeo = isVertical\n ? new THREE.BoxGeometry(drumLength * 0.85, beltThickness, flatLen)\n : new THREE.BoxGeometry(flatLen, beltThickness, drumLength * 0.85)\n const bottomMesh = new THREE.Mesh(bottomGeo, beltMaterial)\n bottomMesh.position.set(0, beltY - drumRadius, 0)\n this.components3D.add(bottomMesh)\n }\n\n private buildRails(width: number, height: number, depth: number, frameH: number, railW: number, isVertical: boolean = false) {\n const color = this.resolveColor()\n const railHeight = frameH * 0.3\n const railY = depth - railHeight / 2\n const beltWidth = isVertical ? width : height\n const transportLen = isVertical ? height : width\n const innerWidth = beltWidth - railW * 2\n // 두 레일 간격: 내부 폭의 60%\n const railSpacing = innerWidth * 0.6\n\n const railMaterial = MaterialBank.material('conveyor|rail', { metalness: 0.7, roughness: 0.3 }, color)\n\n const railGeometries: THREE.BufferGeometry[] = []\n\n // Two parallel rails running along transport direction\n if (isVertical) {\n for (const xSign of [-1, 1]) {\n const rail = new THREE.BoxGeometry(railW * 0.8, railHeight, transportLen - railW * 2)\n rail.translate(xSign * (railSpacing / 2), railY, 0)\n railGeometries.push(rail)\n }\n } else {\n for (const zSign of [-1, 1]) {\n const rail = new THREE.BoxGeometry(transportLen - railW * 2, railHeight, railW * 0.8)\n rail.translate(0, railY, zSign * (railSpacing / 2))\n railGeometries.push(rail)\n }\n }\n\n const railMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(railGeometries), railMaterial)\n railMesh.castShadow = true\n this.components3D.add(railMesh)\n }\n\n updateDimension() {}\n // updateAlpha override 제거 — 코어 RealObject.updateAlpha(=applyMaterialOpacity)로 수렴(faint).\n // view 모드는 factor=1 → build-시 opacity 그대로(불변), 편집 모드만 faint 추가.\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n if (\n 'conveyorType' in after ||\n 'orientation' in after ||\n 'width' in after ||\n 'height' in after ||\n 'depth' in after ||\n 'fillStyle' in after ||\n 'strokeStyle' in after\n ) {\n this.update()\n return\n }\n super.onchange(after, before)\n }\n}\n\nregisterRealObjectFactory('Conveyor', (component: Component) => new Conveyor3D(component))\n"]}
1
+ {"version":3,"file":"conveyor-3d.js","sourceRoot":"","sources":["../../src/factories/conveyor-3d.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,mBAAmB,MAAM,iDAAiD,CAAA;AACtF,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAEjG,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAEtC,MAAM,WAAW,GAAG,QAAQ,CAAA;AAC5B,MAAM,YAAY,GAAG,QAAQ,CAAA;AAC7B,MAAM,aAAa,GAAG,QAAQ,CAAA;AAE9B,MAAM,OAAO,UAAW,SAAQ,eAAe;IAC7C,IAAI,SAAS,KAAa,OAAO,OAAO,CAAC,QAAQ,CAAA,CAAC,CAAC;IAEnD,IAAI,cAAc;QAChB,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAA;QACtC,OAAO,KAAK,IAAI,eAAe,CAAC,QAAQ,CAAA;IAC1C,CAAC;IAEO,YAAY;QAClB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAgB,CAAA;QAElC,kDAAkD;QAClD,4DAA4D;QAC5D,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,IAAI,CAAC,WAAW,CAAA;YAC3B,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,aAAa;gBAAE,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAA;QACjI,CAAC;QAAC,WAAM,CAAC;YACP,0BAA0B;QAC5B,CAAC;QAED,8BAA8B;QAC9B,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAA;QAC1C,IAAI,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,aAAa,EAAE,CAAC;YAC9E,IAAI,CAAC;gBACH,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,CAAA;YAC5C,CAAC;YAAC,WAAM,CAAC;gBACP,gBAAgB;YAClB,CAAC;QACH,CAAC;QAED,OAAO,aAAa,CAAA;IACtB,CAAC;IAED,KAAK;QACH,KAAK,CAAC,KAAK,EAAE,CAAA;QAEb,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAA;QAC9F,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAA;QACjC,IAAI,CAAC,QAAQ,IAAI,CAAC,SAAS;YAAE,OAAM;QAEnC,kEAAkE;QAClE,kCAAkC;QAClC,MAAM,UAAU,GAAG,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI;YAClD,CAAC,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,KAAK;gBACtC,CAAC,CAAC,QAAQ,GAAG,SAAS,CAAA,CAAE,6BAA6B;QACvD,8CAA8C;QAC9C,+CAA+C;QAC/C,MAAM,KAAK,GAAG,QAAQ,CAAA;QACtB,MAAM,MAAM,GAAG,SAAS,CAAA;QAExB,2BAA2B;QAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;QAC3D,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAA;QAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,MAAM,EAAE,CAAC,CAAC,CAAA;QAExC,kDAAkD;QAClD,oDAAoD;QACpD,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAA;QAC7C,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAA;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,IAAI,EAAE,CAAC,CAAC,CAAA;QAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,EAAE,CAAC,CAAC,CAAA;QAE7C,qFAAqF;QACrF,MAAM,aAAa,GAAG,YAAY,CAAC,QAAQ,CAAC,gBAAgB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,WAAW,CAAC,CAAA;QAEhH,mDAAmD;QACnD,iDAAiD;QACjD,MAAM,eAAe,GAA2B,EAAE,CAAA;QAClD,MAAM,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,CAAC,CAAA;QAEhC,oCAAoC;QACpC,IAAI,UAAU,EAAE,CAAC;YACf,yBAAyB;YACzB,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;gBACzD,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;gBACzD,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAC5B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,yBAAyB;YACzB,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAA;gBACxD,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAA;gBAC1D,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAC5B,CAAC;QACH,CAAC;QAED,oBAAoB;QACpB,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,KAAK,GAAG,MAAM,CAAA;YAC9B,MAAM,UAAU,GAAG,OAAO,GAAG,IAAI,GAAG,CAAC,CAAA;YAErC,mBAAmB;YACnB,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC,CAAC,CAAA;YACrF,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAA;YAEvF,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBAC5B,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;oBAC5B,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,YAAY,EAAE,IAAI,EAAE,YAAY,CAAC,CAAA;oBACnE,GAAG,CAAC,SAAS,CAAC,KAAK,GAAG,OAAO,EAAE,UAAU,EAAE,KAAK,GAAG,OAAO,CAAC,CAAA;oBAC3D,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBAC3B,CAAC;YACH,CAAC;YAED,gBAAgB;YAChB,MAAM,MAAM,GAAG,YAAY,GAAG,GAAG,CAAA;YACjC,MAAM,MAAM,GAAG,YAAY,GAAG,GAAG,CAAA;YACjC,MAAM,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,IAAI,CAAA;YAEpC,sBAAsB;YACtB,IAAI,UAAU,EAAE,CAAC;gBACf,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;oBAC5B,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAAC,CAAA;oBAC1E,KAAK,CAAC,SAAS,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;oBAC3C,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC7B,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;oBAC5B,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,GAAG,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;oBACzE,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,GAAG,OAAO,CAAC,CAAA;oBAC3C,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC7B,CAAC;YACH,CAAC;YAED,uBAAuB;YACvB,IAAI,UAAU,EAAE,CAAC;gBACf,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;oBAC5B,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,GAAG,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;oBAClE,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,GAAG,OAAO,CAAC,CAAA;oBAC3C,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC7B,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;oBAC5B,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CAAC,CAAA;oBACnE,KAAK,CAAC,SAAS,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;oBAC3C,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAC7B,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,eAAe,CAAC,eAAe,CAAC,EAAE,aAAa,CAAC,CAAA;QACrG,SAAS,CAAC,UAAU,GAAG,IAAI,CAAA;QAC3B,SAAS,CAAC,aAAa,GAAG,IAAI,CAAA;QAC9B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QAEhC,kCAAkC;QAClC,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;YAC5B,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAA;QAClE,CAAC;aAAM,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;YACnC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAA;QACjE,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,CAAC,CAAA;QAC/E,CAAC;QAED,mEAAmE;QACnE,IAAI,CAAC,WAAW,EAAE,CAAA;IACpB,CAAC;IAEO,YAAY,CAClB,KAAa,EACb,MAAc,EACd,KAAa,EACb,MAAc,EACd,KAAa,EACb,SAAiB,EACjB,aAAsB,KAAK;QAE3B,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;QAC/C,MAAM,QAAQ,GAAG,YAAY,GAAG,CAAC,CAAA;QACjC,MAAM,IAAI,GAAG,QAAQ,GAAG,IAAI,CAAA;QAC5B,MAAM,OAAO,GAAG,KAAK,GAAG,YAAY,CAAA;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAA;QAEjC,MAAM,gBAAgB,GAA2B,EAAE,CAAA;QAEnD,IAAI,UAAU,EAAE,CAAC;YACf,gCAAgC;YAChC,MAAM,YAAY,GAAG,KAAK,GAAG,KAAK,GAAG,CAAC,GAAG,GAAG,CAAA;YAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAA;YACpD,MAAM,SAAS,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAA;YACpC,MAAM,MAAM,GAAG,CAAC,SAAS,GAAG,CAAC,CAAA;YAE7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/B,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,GAAG,IAAI,CAAA;gBAC3B,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,gBAAgB,CAAC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,CAAC,CAAA;gBACvF,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;gBAC3B,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAA;gBAC/B,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YAC/B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,wCAAwC;YACxC,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,GAAG,CAAC,GAAG,GAAG,CAAA;YAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAA;YACnD,MAAM,SAAS,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,IAAI,CAAA;YACpC,MAAM,MAAM,GAAG,CAAC,SAAS,GAAG,CAAC,CAAA;YAE7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/B,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,GAAG,IAAI,CAAA;gBAC3B,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,gBAAgB,CAAC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,CAAC,CAAA;gBACvF,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;gBAC3B,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAA;gBAC/B,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YAC/B,CAAC;QACH,CAAC;QAED,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,IAAI,KAAK,CAAC,IAAI,CAC/B,mBAAmB,CAAC,eAAe,CAAC,gBAAgB,CAAC,EACrD,YAAY,CAAC,QAAQ,CAAC,iBAAiB,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,KAAK,CAAC,CACpF,CAAA;YACD,UAAU,CAAC,UAAU,GAAG,IAAI,CAAA;YAC5B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;QACnC,CAAC;IACH,CAAC;IAEO,SAAS,CAAC,KAAa,EAAE,MAAc,EAAE,KAAa,EAAE,MAAc,EAAE,KAAa,EAAE,aAAsB,KAAK;QACxH,MAAM,UAAU,GAAG,MAAM,GAAG,IAAI,CAAA;QAChC,MAAM,KAAK,GAAG,KAAK,GAAG,UAAU,CAAA;QAChC,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAA;QAEjC,gBAAgB;QAChB,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAA;QAChD,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAA;QAC7C,MAAM,UAAU,GAAG,SAAS,GAAG,KAAK,GAAG,CAAC,CAAA;QAExC,gBAAgB;QAChB,MAAM,cAAc,GAA2B,EAAE,CAAA;QACjD,MAAM,SAAS,GAAG,UAAU,GAAG,GAAG,CAAA;QAClC,MAAM,KAAK,GAAG,CAAC,YAAY,GAAG,CAAC,GAAG,SAAS,CAAA;QAC3C,MAAM,KAAK,GAAG,YAAY,GAAG,CAAC,GAAG,SAAS,CAAA;QAE1C,KAAK,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE,CAAC,CAAA;YAC/E,IAAI,UAAU,EAAE,CAAC;gBACf,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;gBACzB,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;YAC9B,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;gBACzB,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;YAC9B,CAAC;YACD,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC3B,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,IAAI,CAC7B,mBAAmB,CAAC,eAAe,CAAC,cAAc,CAAC,EACnD,YAAY,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,YAAY,CAAC,CACzF,CAAA;QACD,QAAQ,CAAC,UAAU,GAAG,IAAI,CAAA;QAC1B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAE/B,eAAe;QACf,MAAM,aAAa,GAAG,UAAU,GAAG,IAAI,CAAA;QACvC,MAAM,YAAY,GAAG,YAAY,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,KAAK,CAAC,CAAA;QAEtG,+CAA+C;QAC/C,MAAM,OAAO,GAAG,KAAK,GAAG,KAAK,CAAA;QAC7B,MAAM,OAAO,GAAG,UAAU;YACxB,CAAC,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,UAAU,EAAE,aAAa,EAAE,OAAO,CAAC;YAC3D,CAAC,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,aAAa,EAAE,UAAU,CAAC,CAAA;QAC7D,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAA;QACtD,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,UAAU,EAAE,CAAC,CAAC,CAAA;QAC/C,QAAQ,CAAC,UAAU,GAAG,IAAI,CAAA;QAC1B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAE/B,mDAAmD;QACnD,MAAM,YAAY,GAAG,EAAE,CAAA;QACvB,KAAK,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI;YAC7B,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;YACpB,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;SACA,EAAE,CAAC;YACxB,MAAM,cAAc,GAA2B,EAAE,CAAA;YACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,EAAE,GAAG,UAAU,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,YAAY,CAAA;gBACpD,MAAM,EAAE,GAAG,UAAU,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,YAAY,CAAA;gBAC1D,MAAM,CAAC,GAAG,UAAU,GAAG,aAAa,GAAG,CAAC,CAAA;gBAExC,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;gBAChC,MAAM,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;gBACnC,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;gBAChC,MAAM,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;gBAEnC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAA;gBAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;gBAE7C,IAAI,UAAU,EAAE,CAAC;oBACf,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,UAAU,EAAE,aAAa,EAAE,MAAM,CAAC,CAAA;oBACpE,GAAG,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAA;oBACtB,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAA;oBAC9C,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBAC1B,CAAC;qBAAM,CAAC;oBACN,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,CAAC,CAAA;oBACpE,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;oBACrB,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;oBAC9C,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;gBAC1B,CAAC;YACH,CAAC;YACD,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE,YAAY,CAAC,CAAA;YAClG,QAAQ,CAAC,UAAU,GAAG,IAAI,CAAA;YAC1B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACjC,CAAC;QAED,iCAAiC;QACjC,MAAM,SAAS,GAAG,UAAU;YAC1B,CAAC,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,UAAU,GAAG,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC;YAClE,CAAC,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,OAAO,EAAE,aAAa,EAAE,UAAU,GAAG,IAAI,CAAC,CAAA;QACpE,MAAM,UAAU,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAA;QAC1D,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,UAAU,EAAE,CAAC,CAAC,CAAA;QACjD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACnC,CAAC;IAEO,UAAU,CAAC,KAAa,EAAE,MAAc,EAAE,KAAa,EAAE,MAAc,EAAE,KAAa,EAAE,aAAsB,KAAK;QACzH,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,CAAA;QACjC,MAAM,UAAU,GAAG,MAAM,GAAG,GAAG,CAAA;QAC/B,MAAM,KAAK,GAAG,KAAK,GAAG,UAAU,GAAG,CAAC,CAAA;QACpC,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAA;QAC7C,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAA;QAChD,MAAM,UAAU,GAAG,SAAS,GAAG,KAAK,GAAG,CAAC,CAAA;QACxC,qBAAqB;QACrB,MAAM,WAAW,GAAG,UAAU,GAAG,GAAG,CAAA;QAEpC,MAAM,YAAY,GAAG,YAAY,CAAC,QAAQ,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,KAAK,CAAC,CAAA;QAEtG,MAAM,cAAc,GAA2B,EAAE,CAAA;QAEjD,uDAAuD;QACvD,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,KAAK,GAAG,GAAG,EAAE,UAAU,EAAE,YAAY,GAAG,KAAK,GAAG,CAAC,CAAC,CAAA;gBACrF,IAAI,CAAC,SAAS,CAAC,KAAK,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;gBACnD,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAC3B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBAC5B,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,YAAY,GAAG,KAAK,GAAG,CAAC,EAAE,UAAU,EAAE,KAAK,GAAG,GAAG,CAAC,CAAA;gBACrF,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,CAAA;gBACnD,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YAC3B,CAAC;QACH,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE,YAAY,CAAC,CAAA;QAClG,QAAQ,CAAC,UAAU,GAAG,IAAI,CAAA;QAC1B,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACjC,CAAC;IAED,eAAe,KAAI,CAAC;IACpB,yFAAyF;IACzF,gEAAgE;IAEhE,QAAQ,CAAC,KAA8B,EAAE,MAA+B;QACtE,IACE,cAAc,IAAI,KAAK;YACvB,aAAa,IAAI,KAAK;YACtB,OAAO,IAAI,KAAK;YAChB,QAAQ,IAAI,KAAK;YACjB,OAAO,IAAI,KAAK;YAChB,WAAW,IAAI,KAAK;YACpB,aAAa,IAAI,KAAK,EACtB,CAAC;YACD,IAAI,CAAC,MAAM,EAAE,CAAA;YACb,OAAM;QACR,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IAC/B,CAAC;CACF;AAED,yBAAyB,CAAC,UAAU,EAAE,CAAC,SAAoB,EAAE,EAAE,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,CAAC,CAAA","sourcesContent":["/**\n * Conveyor 3D Factory\n *\n * 'conveyor' type (default): side rails + cylindrical rollers + 4 legs + cross-bracing\n * 'belt' type: side rails + two end drums + belt wrapping + 4 legs + cross-bracing\n * 'rail' type: side rails + two parallel rails + 4 legs + cross-bracing\n *\n * Based on operato-scene conveyor-3d.ts, adapted for fmsim:\n * - conveyorType is string ('', 'conveyor', 'belt', 'rail') instead of numeric\n * - statusColor from MCSStatusMixin instead of value-based lookup\n * - rollWidth auto-calculated: Math.max(10, Math.min(width, height) / 2)\n */\n\nimport * as THREE from 'three'\nimport * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js'\nimport { RealObjectGroup, registerRealObjectFactory, MaterialBank } from '@hatiolab/things-scene'\nimport type { Component } from '@hatiolab/things-scene'\nimport { MACHINE_HEIGHTS } from '../features/lv-heights.js'\nimport { Z_FMSIM } from './z-priority'\n\nconst FRAME_COLOR = 0x888899\nconst ROLLER_COLOR = 0xaaaabc\nconst DEFAULT_COLOR = 0x999999\n\nexport class Conveyor3D extends RealObjectGroup {\n get zPriority(): number { return Z_FMSIM.CONVEYOR }\n\n get effectiveDepth(): number {\n const { depth } = this.component.state\n return depth || MACHINE_HEIGHTS.conveyor\n }\n\n private resolveColor(): number {\n const comp = this.component as any\n\n // 1) MCSStatusMixin.statusColor (legend 기반 상태 색상)\n // '#F0F0F0'은 상태 미설정 시 기본 fallback — 무시하고 defaultColor 사용\n try {\n const sc = comp.statusColor\n if (typeof sc === 'string' && sc && sc.toUpperCase() !== '#F0F0F0' && sc !== 'transparent') return new THREE.Color(sc).getHex()\n } catch {\n /* statusColor 미구현 시 무시 */\n }\n\n // 2) state.fillStyle fallback\n const { fillStyle } = this.component.state\n if (fillStyle && typeof fillStyle === 'string' && fillStyle !== 'transparent') {\n try {\n return new THREE.Color(fillStyle).getHex()\n } catch {\n /* 파싱 실패 시 무시 */\n }\n }\n\n return DEFAULT_COLOR\n }\n\n build() {\n super.build()\n\n const { width: rawWidth, height: rawHeight, conveyorType, orientation } = this.component.state\n const depth = this.effectiveDepth\n if (!rawWidth || !rawHeight) return\n\n // orientation: 'horizontal' = 롤러가 Z축(세로), 'vertical' = 롤러가 X축(가로)\n // default = 긴 방향에 수직 (긴 축을 따라 이송)\n const isVertical = orientation === 'vertical' ? true\n : orientation === 'horizontal' ? false\n : rawWidth < rawHeight // default: 세로가 길면 롤러는 가로(X축)\n // isVertical=true → 롤러 축이 X(가로), 이송 방향이 Z(세로)\n // isVertical=false → 롤러 축이 Z(세로), 이송 방향이 X(가로)\n const width = rawWidth\n const height = rawHeight\n\n // 2D와 동일 로직으로 rollWidth 산출\n const rollWidth = Math.max(10, Math.min(width, height) / 2)\n const rollerDiameter = Math.max(rollWidth, 2)\n const frameH = Math.min(rollerDiameter, depth)\n const legH = Math.max(depth - frameH, 0)\n\n // isVertical일 때 이송 방향이 Z축: 레일은 Z축을 따라, 벨트폭은 width\n // !isVertical일 때 이송 방향이 X축: 레일은 X축을 따라, 벨트폭은 height\n const beltWidth = isVertical ? width : height\n const railLen = isVertical ? height : width\n const railW = Math.max(beltWidth * 0.06, 2)\n const legThickness = Math.max(railW * 0.8, 2)\n\n // MaterialBank 공유(dedup). 자체 update() 없이 base 생명주기(guarded disposeObject3D) 상속 → 안전.\n const frameMaterial = MaterialBank.material('conveyor|frame', { metalness: 0.85, roughness: 0.35 }, FRAME_COLOR)\n\n // --- Frame: side rails + legs + cross-bracing ---\n // Y 좌표: y=0(바닥) ~ y=depth(상단). 레일 상단이 depth에 위치.\n const frameGeometries: THREE.BufferGeometry[] = []\n const railY = depth - frameH / 2\n\n // Side rails — 이송 방향을 따라, 벨트 양측에 배치\n if (isVertical) {\n // 레일이 Z축(세로)을 따라, ±X에 배치\n for (const xSign of [-1, 1]) {\n const rail = new THREE.BoxGeometry(railW, frameH, height)\n rail.translate(xSign * (width / 2 - railW / 2), railY, 0)\n frameGeometries.push(rail)\n }\n } else {\n // 레일이 X축(가로)을 따라, ±Z에 배치\n for (const zSign of [-1, 1]) {\n const rail = new THREE.BoxGeometry(width, frameH, railW)\n rail.translate(0, railY, zSign * (height / 2 - railW / 2))\n frameGeometries.push(rail)\n }\n }\n\n // 4 legs at corners\n if (legH > 0) {\n const legTopY = depth - frameH\n const legCenterY = legTopY - legH / 2\n\n // 다리 위치: 레일 안쪽에 정렬\n const legXPos = isVertical ? (width / 2 - railW / 2) : (width / 2 - legThickness / 2)\n const legZPos = isVertical ? (height / 2 - legThickness / 2) : (height / 2 - railW / 2)\n\n for (const xSign of [-1, 1]) {\n for (const zSign of [-1, 1]) {\n const leg = new THREE.BoxGeometry(legThickness, legH, legThickness)\n leg.translate(xSign * legXPos, legCenterY, zSign * legZPos)\n frameGeometries.push(leg)\n }\n }\n\n // Cross-bracing\n const braceH = legThickness * 0.6\n const braceW = legThickness * 0.6\n const braceY = legTopY - legH * 0.35\n\n // 이송 방향 브레이스 (레일과 평행)\n if (isVertical) {\n for (const xSign of [-1, 1]) {\n const brace = new THREE.BoxGeometry(braceW, braceH, height - legThickness)\n brace.translate(xSign * legXPos, braceY, 0)\n frameGeometries.push(brace)\n }\n } else {\n for (const zSign of [-1, 1]) {\n const brace = new THREE.BoxGeometry(width - legThickness, braceH, braceW)\n brace.translate(0, braceY, zSign * legZPos)\n frameGeometries.push(brace)\n }\n }\n\n // 벨트폭 방향 브레이스 (레일과 수직)\n if (isVertical) {\n for (const zSign of [-1, 1]) {\n const brace = new THREE.BoxGeometry(width - railW, braceH, braceW)\n brace.translate(0, braceY, zSign * legZPos)\n frameGeometries.push(brace)\n }\n } else {\n for (const xSign of [-1, 1]) {\n const brace = new THREE.BoxGeometry(braceW, braceH, height - railW)\n brace.translate(xSign * legXPos, braceY, 0)\n frameGeometries.push(brace)\n }\n }\n }\n\n const frameMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(frameGeometries), frameMaterial)\n frameMesh.castShadow = true\n frameMesh.receiveShadow = true\n this.components3D.add(frameMesh)\n\n // --- Rollers, Belt, or Rails ---\n if (conveyorType === 'rail') {\n this.buildRails(width, height, depth, frameH, railW, isVertical)\n } else if (conveyorType === 'belt') {\n this.buildBelt(width, height, depth, frameH, railW, isVertical)\n } else {\n this.buildRollers(width, height, depth, frameH, railW, rollWidth, isVertical)\n }\n\n // mesh 는 super.build() 이후 생성 → 코어 faint 를 명시 적용(편집 흐림이 mesh 에 닿게).\n this.updateAlpha()\n }\n\n private buildRollers(\n width: number,\n height: number,\n depth: number,\n frameH: number,\n railW: number,\n rollWidth: number,\n isVertical: boolean = false\n ) {\n const rollerRadius = Math.max(rollWidth / 8, 1)\n const diameter = rollerRadius * 2\n const step = diameter * 1.05\n const rollerY = depth - rollerRadius\n const color = this.resolveColor()\n\n const rollerGeometries: THREE.BufferGeometry[] = []\n\n if (isVertical) {\n // 롤러 축 = X축(가로), 이송 방향 = Z축(세로)\n const rollerLength = width - railW * 2 - 0.5\n const count = Math.max(1, Math.floor(height / step))\n const totalSpan = (count - 1) * step\n const startZ = -totalSpan / 2\n\n for (let i = 0; i < count; i++) {\n const z = startZ + i * step\n const roller = new THREE.CylinderGeometry(rollerRadius, rollerRadius, rollerLength, 16)\n roller.rotateZ(Math.PI / 2)\n roller.translate(0, rollerY, z)\n rollerGeometries.push(roller)\n }\n } else {\n // 롤러 축 = Z축(세로), 이송 방향 = X축(가로) — 기존 동작\n const rollerLength = height - railW * 2 - 0.5\n const count = Math.max(1, Math.floor(width / step))\n const totalSpan = (count - 1) * step\n const startX = -totalSpan / 2\n\n for (let i = 0; i < count; i++) {\n const x = startX + i * step\n const roller = new THREE.CylinderGeometry(rollerRadius, rollerRadius, rollerLength, 16)\n roller.rotateX(Math.PI / 2)\n roller.translate(x, rollerY, 0)\n rollerGeometries.push(roller)\n }\n }\n\n if (rollerGeometries.length > 0) {\n const rollerMesh = new THREE.Mesh(\n BufferGeometryUtils.mergeGeometries(rollerGeometries),\n MaterialBank.material('conveyor|roller', { metalness: 0.9, roughness: 0.2 }, color)\n )\n rollerMesh.castShadow = true\n this.components3D.add(rollerMesh)\n }\n }\n\n private buildBelt(width: number, height: number, depth: number, frameH: number, railW: number, isVertical: boolean = false) {\n const drumRadius = frameH * 0.38\n const beltY = depth - drumRadius\n const color = this.resolveColor()\n\n // 이송 방향 길이와 벨트폭\n const transportLen = isVertical ? height : width\n const beltWidth = isVertical ? width : height\n const drumLength = beltWidth - railW * 2\n\n // Two end drums\n const drumGeometries: THREE.BufferGeometry[] = []\n const drumInset = drumRadius * 1.5\n const drum1 = -transportLen / 2 + drumInset\n const drum2 = transportLen / 2 - drumInset\n\n for (const dp of [drum1, drum2]) {\n const drum = new THREE.CylinderGeometry(drumRadius, drumRadius, drumLength, 16)\n if (isVertical) {\n drum.rotateZ(Math.PI / 2)\n drum.translate(0, beltY, dp)\n } else {\n drum.rotateX(Math.PI / 2)\n drum.translate(dp, beltY, 0)\n }\n drumGeometries.push(drum)\n }\n\n const drumMesh = new THREE.Mesh(\n BufferGeometryUtils.mergeGeometries(drumGeometries),\n MaterialBank.material('conveyor|drum', { metalness: 0.9, roughness: 0.2 }, ROLLER_COLOR)\n )\n drumMesh.castShadow = true\n this.components3D.add(drumMesh)\n\n // Belt surface\n const beltThickness = drumRadius * 0.12\n const beltMaterial = MaterialBank.material('conveyor|belt', { metalness: 0.0, roughness: 0.9 }, color)\n\n // Flat belt top surface spanning between drums\n const flatLen = drum2 - drum1\n const flatGeo = isVertical\n ? new THREE.BoxGeometry(drumLength, beltThickness, flatLen)\n : new THREE.BoxGeometry(flatLen, beltThickness, drumLength)\n const flatMesh = new THREE.Mesh(flatGeo, beltMaterial)\n flatMesh.position.set(0, beltY + drumRadius, 0)\n flatMesh.castShadow = true\n this.components3D.add(flatMesh)\n\n // Belt wrap around drums (segmented half-cylinder)\n const wrapSegments = 12\n for (const [dp, angleStart] of [\n [drum1, Math.PI / 2],\n [drum2, -Math.PI / 2],\n ] as [number, number][]) {\n const wrapGeometries: THREE.BufferGeometry[] = []\n for (let i = 0; i < wrapSegments; i++) {\n const a0 = angleStart + (Math.PI * i) / wrapSegments\n const a1 = angleStart + (Math.PI * (i + 1)) / wrapSegments\n const r = drumRadius + beltThickness / 2\n\n const p0 = dp + Math.cos(a0) * r\n const y0 = beltY + Math.sin(a0) * r\n const p1 = dp + Math.cos(a1) * r\n const y1 = beltY + Math.sin(a1) * r\n\n const segLen = Math.sqrt((p1 - p0) ** 2 + (y1 - y0) ** 2) * 1.05\n const segAngle = Math.atan2(y1 - y0, p1 - p0)\n\n if (isVertical) {\n const seg = new THREE.BoxGeometry(drumLength, beltThickness, segLen)\n seg.rotateX(-segAngle)\n seg.translate(0, (y0 + y1) / 2, (p0 + p1) / 2)\n wrapGeometries.push(seg)\n } else {\n const seg = new THREE.BoxGeometry(segLen, beltThickness, drumLength)\n seg.rotateZ(segAngle)\n seg.translate((p0 + p1) / 2, (y0 + y1) / 2, 0)\n wrapGeometries.push(seg)\n }\n }\n const wrapMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(wrapGeometries), beltMaterial)\n wrapMesh.castShadow = true\n this.components3D.add(wrapMesh)\n }\n\n // Flat belt bottom (return path)\n const bottomGeo = isVertical\n ? new THREE.BoxGeometry(drumLength * 0.85, beltThickness, flatLen)\n : new THREE.BoxGeometry(flatLen, beltThickness, drumLength * 0.85)\n const bottomMesh = new THREE.Mesh(bottomGeo, beltMaterial)\n bottomMesh.position.set(0, beltY - drumRadius, 0)\n this.components3D.add(bottomMesh)\n }\n\n private buildRails(width: number, height: number, depth: number, frameH: number, railW: number, isVertical: boolean = false) {\n const color = this.resolveColor()\n const railHeight = frameH * 0.3\n const railY = depth - railHeight / 2\n const beltWidth = isVertical ? width : height\n const transportLen = isVertical ? height : width\n const innerWidth = beltWidth - railW * 2\n // 두 레일 간격: 내부 폭의 60%\n const railSpacing = innerWidth * 0.6\n\n const railMaterial = MaterialBank.material('conveyor|rail', { metalness: 0.7, roughness: 0.3 }, color)\n\n const railGeometries: THREE.BufferGeometry[] = []\n\n // Two parallel rails running along transport direction\n if (isVertical) {\n for (const xSign of [-1, 1]) {\n const rail = new THREE.BoxGeometry(railW * 0.8, railHeight, transportLen - railW * 2)\n rail.translate(xSign * (railSpacing / 2), railY, 0)\n railGeometries.push(rail)\n }\n } else {\n for (const zSign of [-1, 1]) {\n const rail = new THREE.BoxGeometry(transportLen - railW * 2, railHeight, railW * 0.8)\n rail.translate(0, railY, zSign * (railSpacing / 2))\n railGeometries.push(rail)\n }\n }\n\n const railMesh = new THREE.Mesh(BufferGeometryUtils.mergeGeometries(railGeometries), railMaterial)\n railMesh.castShadow = true\n this.components3D.add(railMesh)\n }\n\n updateDimension() {}\n // updateAlpha override 제거 — 코어 RealObject.updateAlpha(=applyMaterialOpacity)로 수렴(faint).\n // view 모드는 factor=1 → build-시 opacity 그대로(불변), 편집 모드만 faint 추가.\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>) {\n if (\n 'conveyorType' in after ||\n 'orientation' in after ||\n 'width' in after ||\n 'height' in after ||\n 'depth' in after ||\n 'fillStyle' in after ||\n 'strokeStyle' in after\n ) {\n this.update()\n return\n }\n super.onchange(after, before)\n }\n}\n\nregisterRealObjectFactory('Conveyor', (component: Component) => new Conveyor3D(component))\n"]}