import { Component, ContainerAbstract } from '@hatiolab/things-scene' import { getPopupData } from '@fmsim/api' import { MCSStatusMixin, MCSStatusMixinProperties } from './features/mcs-status-mixin' import { LEGEND_MACHINE, Legend } from './features/mcs-status-default' /** * MCS Machine의 공통 속성을 정의한 최상위 오브젝트 * - Container * - */ export default class MCSMachine extends MCSStatusMixin(ContainerAbstract) { static get properties(): any { return [ ...MCSStatusMixinProperties, { type: 'number', name: 'round', label: 'round' } ] } get showMoveHandle() { return false } containable(component: Component) { return ['rect', 'ellipse'].includes(component.state.type) } get decorators() { return ['decotag'] } getTheme() { const { legendName } = this.state if (legendName) { return (this.root as any)?.style?.[legendName] } } get hasTextProperty() { return true } get status() { return this.data?.STATUS } get auxStatus() { return this.data?.STATUS } get legend(): Legend { return this.getTheme() || this.getLegendFallback() } get auxLegend() { return LEGEND_MACHINE } get auxColor() { return this.state.strokeStyle } getLegendFallback() { return LEGEND_MACHINE } /** * In 2D, ignore `state.alpha`; preserve everything else. * * things-scene's base prerender (component-drawing.ts:31, 44) does: * const fade = (alpha || 1) - this._delta.fade * if (fade) context.globalAlpha = fade * * It *overwrites* `globalAlpha` (not multiplies), so the inherited * parent alpha is also lost — that's a base-layer quirk we match the * recovery for. Then at line 48 it applies editMode+hidden dimming * with a *= 0.5. * * Our recovery: * 1. Capture the inherited `globalAlpha` *before* super runs. * 2. Let super do its work (transforms / shadow / dim flags). * 3. Restore globalAlpha to inherited × editMode-hidden dim factor — * i.e., what super would have produced if our state.alpha were 1. * * 3D path is unaffected: 3D factories read `state.alpha` directly via * their `updateAlpha()` implementations and continue to honor it (with * per-config opacity fallback). */ prerender(ctx: any) { const inherited = ctx.globalAlpha super.prerender(ctx) const dim = this.app.isEditMode && this.hidden ? 0.5 : 1 ctx.globalAlpha = inherited * dim } render(ctx) { var { round = 0, lineWidth } = this.state var { left, top, width, height } = this.bounds ctx.beginPath() ctx.strokeStyle = this.auxColor ctx.fillStyle = this.statusColor! ctx.lineWidth = lineWidth || 1 ctx.lineCap = 'round' ctx.setLineDash([]) if (round > 0) { ctx.roundRect(left, top, width, height, round) } else { ctx.rect(left, top, width, height) } ctx.fill() ctx.stroke() } // get text() { // if (this.data?.LOCALENAME) { // // TODO 왜 LOCALENAME 데이타는 문자열인가 ? 오브젝트로 보내달라. // return JSON.parse(this.data.LOCALENAME)[getLocaleLanguage()] // } // return super.text // } // set text(text) { // super.text = text // } async detailInfo() { const { type, id } = this.state if (!id) { return } return await getPopupData(type, id) } }