import { Component, RootContainer } from '@hatiolab/things-scene' import { themesColorMap, themesColorRange, themesAnimationMap } from '@fmsim/api' import { Legend } from '../features/mcs-status-default' import CarrierManager from '../carrier-manager' // RootContainer 클래스 타입 확장 declare module '@hatiolab/things-scene' { interface RootContainer { portLegendTheme?: any carrierLegendTheme?: any carrierAnimationTheme?: any stockerCapacityLegendTheme?: any zoneCapacityLegendTheme?: any batteryRateLegendTheme?: any bufferLegendTheme?: any agvlineLegendTheme?: any ohtlineLegendTheme?: any conveyorLegendTheme?: any stokerLegendTheme?: any agvLegendTheme?: any ohtLegendTheme?: any shuttleLegendTheme?: any craneLegendTheme?: any shelfLegendTheme?: any equipmentLegendTheme?: any style: any vehicleAnimation?: boolean // 캐시 관련 속성 추가 _animationConfigCache?: Map _carrierManager?: CarrierManager carrierManager: CarrierManager } } const ModelLayer = (Component as any).register('model-layer') as any Object.defineProperty(ModelLayer.prototype, 'nature', { get: function () { return { mutable: false, rotatable: false, resizable: true, properties: [ { type: 'boolean', label: 'vehicle-animation', name: 'vehicleAnimation' }, { type: 'legend', label: '', name: 'LEGENDS', property: { label: 'LEGENDS' } }, { type: 'select', label: 'equipment-legend-name', name: 'equipmentLegendName', property: { options: themesColorMap } }, { type: 'select', label: 'buffer-legend-name', name: 'bufferLegendName', property: { options: themesColorMap } }, { type: 'select', label: 'agvline-legend-name', name: 'agvlineLegendName', property: { options: themesColorMap } }, { type: 'select', label: 'ohtline-legend-name', name: 'ohtlineLegendName', property: { options: themesColorMap } }, { type: 'select', label: 'conveyor-legend-name', name: 'conveyorLegendName', property: { options: themesColorMap } }, { type: 'select', label: 'stoker-legend-name', name: 'stokerLegendName', property: { options: themesColorMap } }, { type: 'select', label: 'port-legend-name', name: 'portLegendName', property: { options: themesColorMap } }, { type: 'select', label: 'agv-legend-name', name: 'agvLegendName', property: { options: themesColorMap } }, { type: 'select', label: 'oht-legend-name', name: 'ohtLegendName', property: { options: themesColorMap } }, { type: 'select', label: 'shuttle-legend-name', name: 'shuttleLegendName', property: { options: themesColorMap } }, { type: 'select', label: 'crane-legend-name', name: 'craneLegendName', property: { options: themesColorMap } }, { type: 'select', label: 'port-legend-name', name: 'portLegendName', property: { options: themesColorMap } }, { type: 'select', label: 'shelf-legend-name', name: 'shelfLegendName', property: { options: themesColorMap } }, { type: 'select', label: 'carrier-legend-name', name: 'carrierLegendName', property: { options: themesColorMap } }, { type: 'select', label: 'carrier-animation-name', name: 'carrierAnimationName', property: { options: themesAnimationMap } }, { type: 'select', label: 'stocker-capacity-legend-name', name: 'stockerCapacityLegendName', property: { options: themesColorRange } }, { type: 'select', label: 'zone-capacity-legend-name', name: 'zoneCapacityLegendName', property: { options: themesColorRange } }, { type: 'select', label: 'battery-rate-legend-name', name: 'batteryRateLegendName', property: { options: themesColorRange } }, { type: 'legend', label: '', name: 'MOOD', property: { label: 'MOOD' } }, { type: 'select', label: 'light-preset', name: 'lightPreset', property: { options: ['dark', 'medium', 'bright'] } } ], 'value-property': 'text' } } }) /** * 조명 프리셋 — 3 단계 밝기 토글. * * fmsim 은 디테일 조명 옵션 UI 를 노출하지 않으므로 단일 select 로 단순화. * medium = things-scene 의 현재 default 값과 동일 (외관 변화 없음). * 사용자가 select 변경 시 onchange 가 exposure + hemiIntensity + dirLightIntensity * 를 일괄 set → three-capability 의 변경 감지 핸들러가 즉시 갱신. */ const LIGHT_PRESETS: Record = { dark: { exposure: 1.2, hemiIntensity: 4.0, dirLightIntensity: 0.6 }, medium: { exposure: 1.2, hemiIntensity: 4.0, dirLightIntensity: 2.0 }, bright: { exposure: 1.2, hemiIntensity: 4.0, dirLightIntensity: 5.0 } } const _origModelLayerOnchange = ModelLayer.prototype.onchange ModelLayer.prototype.onchange = function (after: any) { if (after && Object.prototype.hasOwnProperty.call(after, 'lightPreset')) { const preset = LIGHT_PRESETS[after.lightPreset as string] if (preset) { this.set({ exposure: preset.exposure, hemiIntensity: preset.hemiIntensity, dirLightIntensity: preset.dirLightIntensity }) } } return _origModelLayerOnchange.call(this, after) } Object.defineProperty(RootContainer.prototype, 'equipmentLegendTheme', { get: function () { const { equipmentLegendName } = this.rootModel.state return equipmentLegendName && this.state.style[equipmentLegendName] } }) Object.defineProperty(RootContainer.prototype, 'bufferLegendTheme', { get: function () { const { bufferLegendName } = this.rootModel.state return bufferLegendName && this.state.style[bufferLegendName] } }) Object.defineProperty(RootContainer.prototype, 'agvlineLegendTheme', { get: function () { const { agvlineLegendName } = this.rootModel.state return agvlineLegendName && this.state.style[agvlineLegendName] } }) Object.defineProperty(RootContainer.prototype, 'ohtlineLegendTheme', { get: function () { const { ohtlineLegendName } = this.rootModel.state return ohtlineLegendName && this.state.style[ohtlineLegendName] } }) Object.defineProperty(RootContainer.prototype, 'conveyorLegendTheme', { get: function () { const { conveyorLegendName } = this.rootModel.state return conveyorLegendName && this.state.style[conveyorLegendName] } }) Object.defineProperty(RootContainer.prototype, 'stokerLegendTheme', { get: function () { const { stokerLegendName } = this.rootModel.state return stokerLegendName && this.state.style[stokerLegendName] } }) Object.defineProperty(RootContainer.prototype, 'agvLegendTheme', { get: function () { const { agvLegendName } = this.rootModel.state return agvLegendName && this.state.style[agvLegendName] } }) Object.defineProperty(RootContainer.prototype, 'ohtLegendTheme', { get: function () { const { ohtLegendName } = this.rootModel.state return ohtLegendName && this.state.style[ohtLegendName] } }) Object.defineProperty(RootContainer.prototype, 'shuttleLegendTheme', { get: function () { const { shuttleLegendName } = this.rootModel.state return shuttleLegendName && this.state.style[shuttleLegendName] } }) Object.defineProperty(RootContainer.prototype, 'craneLegendTheme', { get: function () { const { craneLegendName } = this.rootModel.state return craneLegendName && this.state.style[craneLegendName] } }) Object.defineProperty(RootContainer.prototype, 'shelfLegendTheme', { get: function () { const { shelfLegendName } = this.rootModel.state return shelfLegendName && this.state.style[shelfLegendName] } }) Object.defineProperty(RootContainer.prototype, 'portLegendTheme', { get: function () { const { portLegendName } = this.rootModel.state return portLegendName && this.state.style[portLegendName] } }) Object.defineProperty(RootContainer.prototype, 'carrierLegendTheme', { get: function () { const { carrierLegendName } = this.rootModel.state return carrierLegendName && this.state.style[carrierLegendName] } }) Object.defineProperty(RootContainer.prototype, 'carrierAnimationTheme', { get: function () { const { carrierAnimationName } = this.rootModel.state return carrierAnimationName && this.state.style[carrierAnimationName] } }) Object.defineProperty(RootContainer.prototype, 'stockerCapacityLegendTheme', { get: function () { const { stockerCapacityLegendName } = this.rootModel.state return stockerCapacityLegendName && this.state.style[stockerCapacityLegendName] } }) Object.defineProperty(RootContainer.prototype, 'zoneCapacityLegendTheme', { get: function () { const { zoneCapacityLegendName } = this.rootModel.state return zoneCapacityLegendName && this.state.style[zoneCapacityLegendName] } }) Object.defineProperty(RootContainer.prototype, 'batteryRateLegendTheme', { get: function () { const { batteryRateLegendName } = this.rootModel.state return batteryRateLegendName && this.state.style[batteryRateLegendName] } }) Object.defineProperty(RootContainer.prototype, 'vehicleAnimation', { get: function () { const { vehicleAnimation } = this.rootModel.state return !!vehicleAnimation } }) Object.defineProperty(RootContainer.prototype, 'carrierManager', { get: function () { if (!this._carrierManager) { this._carrierManager = new CarrierManager(this) } return this._carrierManager } })