@operato/scene-storage 10.0.0-beta.55 → 10.0.0-beta.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/stockpile-grid.d.ts +9 -2
- package/dist/stockpile-grid.js +14 -5
- package/dist/stockpile-grid.js.map +1 -1
- package/dist/stockpile.d.ts +9 -3
- package/dist/stockpile.js +12 -4
- package/dist/stockpile.js.map +1 -1
- package/package.json +3 -3
- package/src/stockpile-grid.ts +17 -6
- package/src/stockpile.ts +16 -6
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [10.0.0-beta.56](https://github.com/things-scene/operato-scene/compare/v10.0.0-beta.55...v10.0.0-beta.56) (2026-06-13)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### :house: Code Refactoring
|
|
10
|
+
|
|
11
|
+
* **storage:** Stockpile/StockpileGrid SlottedHolder 명시 표준화 (Phase 2) ([54b0a6d](https://github.com/things-scene/operato-scene/commit/54b0a6d961aba59ad830874c9b1847fb355a3940))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
6
15
|
## [10.0.0-beta.55](https://github.com/things-scene/operato-scene/compare/v10.0.0-beta.54...v10.0.0-beta.55) (2026-06-08)
|
|
7
16
|
|
|
8
17
|
|
package/dist/stockpile-grid.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Component, ComponentNature, RealObject } from '@hatiolab/things-scene';
|
|
2
2
|
import type { State, Material3D } from '@hatiolab/things-scene';
|
|
3
|
-
import { SlotTarget, type AttachFrame, type Alignment, type Heights, type PlacementArchetype } from '@operato/scene-base';
|
|
3
|
+
import { SlotTarget, type AttachFrame, type Alignment, type Heights, type PlacementArchetype, type SlottedHolder } from '@operato/scene-base';
|
|
4
4
|
import { StockpileGrid3D } from './stockpile-grid-3d.js';
|
|
5
5
|
import type { StackPattern, CarrierPreset, StockpileRecord, PickPolicy } from './stockpile.js';
|
|
6
6
|
/** grid 의 한 cell — 위치 + 그 cell 의 records. */
|
|
@@ -31,7 +31,7 @@ export interface StockpileGridState extends State {
|
|
|
31
31
|
material3d?: Material3D;
|
|
32
32
|
}
|
|
33
33
|
declare const StockpileGrid_base: any;
|
|
34
|
-
export default class StockpileGrid extends StockpileGrid_base {
|
|
34
|
+
export default class StockpileGrid extends StockpileGrid_base implements SlottedHolder {
|
|
35
35
|
state: StockpileGridState;
|
|
36
36
|
_realObject?: StockpileGrid3D;
|
|
37
37
|
static placement: PlacementArchetype;
|
|
@@ -61,6 +61,13 @@ export default class StockpileGrid extends StockpileGrid_base {
|
|
|
61
61
|
occupiedSlotIds(): ReadonlyArray<string>;
|
|
62
62
|
emptySlotIds(): ReadonlyArray<string>;
|
|
63
63
|
obtainCarrier(slotId: string): Component | null;
|
|
64
|
+
/**
|
|
65
|
+
* carrier → StockpileRecord 추출. id 누락 시 `stkg-` prefix 자동 생성.
|
|
66
|
+
* SlottedHolder duck 의 표준 entry — receiveAt 안에서 호출. cell 정보 (col/row) 는
|
|
67
|
+
* slotId 의 parseCellId 로 receiveAt 가 처리 — record 자체에는 cell 좌표 미포함
|
|
68
|
+
* (cell array 가 그 컨텍스트 보유).
|
|
69
|
+
*/
|
|
70
|
+
recordFromCarrier(carrier: Component, _slotId: string): StockpileRecord;
|
|
64
71
|
receiveAt(slotId: string, carrier: Component, _options?: any): Promise<void>;
|
|
65
72
|
accept(carrier: Component, options?: any): Promise<void>;
|
|
66
73
|
receive(carrier: Component, options?: any): Promise<void>;
|
package/dist/stockpile-grid.js
CHANGED
|
@@ -139,19 +139,28 @@ let StockpileGrid = class StockpileGrid extends RecordStorage()(CarrierHolder(Pl
|
|
|
139
139
|
this._setCellRecords(p.col, p.row, records);
|
|
140
140
|
return this._materializeCarrier(record, p.col, p.row);
|
|
141
141
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
142
|
+
/**
|
|
143
|
+
* carrier → StockpileRecord 추출. id 누락 시 `stkg-` prefix 자동 생성.
|
|
144
|
+
* SlottedHolder duck 의 표준 entry — receiveAt 안에서 호출. cell 정보 (col/row) 는
|
|
145
|
+
* slotId 의 parseCellId 로 receiveAt 가 처리 — record 자체에는 cell 좌표 미포함
|
|
146
|
+
* (cell array 가 그 컨텍스트 보유).
|
|
147
|
+
*/
|
|
148
|
+
recordFromCarrier(carrier, _slotId) {
|
|
146
149
|
const cstate = carrier?.state ?? {};
|
|
147
150
|
const cid = cstate.id ?? `stkg-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
|
|
148
|
-
|
|
151
|
+
return {
|
|
149
152
|
id: String(cid),
|
|
150
153
|
...(cstate.type ? { type: cstate.type } : {}),
|
|
151
154
|
...(typeof cstate.width === 'number' ? { width: cstate.width } : {}),
|
|
152
155
|
...(typeof cstate.height === 'number' ? { height: cstate.height } : {}),
|
|
153
156
|
...(typeof cstate.depth === 'number' ? { depth: cstate.depth } : {})
|
|
154
157
|
};
|
|
158
|
+
}
|
|
159
|
+
async receiveAt(slotId, carrier, _options) {
|
|
160
|
+
const p = this.parseCellId(slotId);
|
|
161
|
+
if (!p)
|
|
162
|
+
return;
|
|
163
|
+
const record = this.recordFromCarrier(carrier, slotId);
|
|
155
164
|
const records = [...this.recordsOf(p.col, p.row), record];
|
|
156
165
|
this._setCellRecords(p.col, p.row, records);
|
|
157
166
|
carrier?.dispose?.();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stockpile-grid.js","sourceRoot":"","sources":["../src/stockpile-grid.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * StockpileGrid — cols × rows cell 들로 분할된 평치 영역. cell 들은 grid 공통 설정\n * (carrierPreset/stackPattern/크기/capacity 등)을 *_모두 공유_* 하고, 각 cell 은 자기\n * 위치(col, row)에서의 records 만 별도 가진다. cell 별 override 는 의미가 없어\n * 제거됨 — cell 별 다른 설정이 진짜 필요한 경우엔 Stockpile 컴포넌트를 따로 두는\n * 것이 자연스럽다.\n *\n * state.data = grid 의 cell 들 배열 (각 element 는 cell-단위 stockpile-like 데이터).\n * data: [\n * { col: 0, row: 0, data: [{ id, ... }, ...] },\n * { col: 1, row: 0, data: [...] },\n * ...\n * ]\n * cell.data 가 그 cell 의 records. 외부 데이터 매핑은 이 배열을 target.\n */\n\nimport * as THREE from 'three'\nimport { Component, ComponentNature, ContainerAbstract, RealObject, sceneComponent } from '@hatiolab/things-scene'\nimport type { State, Material3D } from '@hatiolab/things-scene'\nimport {\n CarrierHolder,\n Placeable,\n RecordStorage,\n SlotTarget,\n type AttachFrame,\n type Alignment,\n type Heights,\n type PlacementArchetype\n} from '@operato/scene-base'\n\nimport { StockpileGrid3D } from './stockpile-grid-3d.js'\nimport type { StackPattern, CarrierPreset, StockpileRecord, PickPolicy } from './stockpile.js'\n\n/** grid 의 한 cell — 위치 + 그 cell 의 records. */\nexport interface StockpileGridCell {\n col: number\n row: number\n data?: StockpileRecord[]\n}\n\nexport interface StockpileGridState extends State {\n cols?: number\n rows?: number\n /** 한 cell 의 평면 크기 (전체 width/height = cellWidth*cols, cellHeight*rows). */\n cellWidth?: number\n cellHeight?: number\n\n /** grid 의 cell 들 — 각 cell 은 { col, row, data: Record[] }. */\n data?: StockpileGridCell[]\n\n // ── 공통 carrier 설정 (모든 cell 공유) ──\n stackPattern?: StackPattern\n carrierPreset?: CarrierPreset\n carrierWidth?: number\n carrierHeight?: number\n carrierDepth?: number\n carrierGap?: number\n capacity?: number // cell 별 capacity (모든 cell 공통)\n stackHeightLimit?: number\n pickPolicy?: PickPolicy\n\n popupRef?: string\n legendTarget?: string\n material3d?: Material3D\n}\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n { type: 'number', label: 'cols', name: 'cols' },\n { type: 'number', label: 'rows', name: 'rows' },\n { type: 'number', label: 'cell-width', name: 'cellWidth' },\n { type: 'number', label: 'cell-height', name: 'cellHeight' },\n { type: 'select', label: 'stack-pattern', name: 'stackPattern',\n property: { options: ['row', 'staggered', 'pyramid', 'column', 'pile'] } },\n { type: 'select', label: 'carrier-preset', name: 'carrierPreset',\n property: { options: ['box', 'pallet', 'drum', 'sack', 'crate', 'bale'] } },\n { type: 'number', label: 'carrier-width', name: 'carrierWidth' },\n { type: 'number', label: 'carrier-height', name: 'carrierHeight' },\n { type: 'number', label: 'carrier-depth', name: 'carrierDepth' },\n { type: 'number', label: 'carrier-gap', name: 'carrierGap' },\n { type: 'number', label: 'capacity', name: 'capacity' },\n { type: 'number', label: 'stack-height-limit', name: 'stackHeightLimit' },\n { type: 'select', label: 'pick-policy', name: 'pickPolicy',\n property: { options: ['lifo', 'fifo'] } },\n { type: 'id-input', label: 'popup-ref', name: 'popupRef',\n property: { component: 'popup' } },\n { type: 'id-input', label: 'legend-target', name: 'legendTarget',\n property: { component: 'legend' },\n placeholder: '미명시 시 scene 의 legend 자동 발견' }\n ],\n help: 'scene/component/stockpile-grid'\n}\n\n@sceneComponent('stockpile-grid')\nexport default class StockpileGrid extends RecordStorage<StockpileGridCell>()(\n CarrierHolder(Placeable(ContainerAbstract))\n) {\n declare state: StockpileGridState\n declare _realObject?: StockpileGrid3D\n\n static placement: PlacementArchetype = 'floor'\n static align: Alignment = 'bottom'\n static defaultDepth = (_h: Heights) => 5\n\n get nature(): ComponentNature { return NATURE }\n get anchors() { return [] }\n\n // RecordStorage mixin 의 records / inventoryCount / addRecord / removeRecord 는\n // cell-aware 시맨틱과 호환 안 됨. cell-nested data 라 *_recordsOf(col,row)_* 와\n // _setCellRecords 를 사용. legend / popup / onLegendChanged 는 mixin 사용.\n // _rebuildVisual hook 만 override.\n _rebuildVisual(): void {\n this._realObject?.update?.()\n }\n\n // ── grid 좌표 helpers ─────────────────────────────────────\n get cols(): number { return Math.max(1, Math.floor(this.state.cols ?? 3)) }\n get rows(): number { return Math.max(1, Math.floor(this.state.rows ?? 3)) }\n get cellW(): number { return this.state.cellWidth ?? 80 }\n get cellH(): number { return this.state.cellHeight ?? 80 }\n\n cellIdOf(col: number, row: number): string { return `${col}-${row}` }\n parseCellId(slotId: string): { col: number; row: number } | null {\n const m = slotId.match(/^(\\d+)-(\\d+)$/)\n if (!m) return null\n return { col: Number(m[1]), row: Number(m[2]) }\n }\n\n /** state.data 에서 (col,row) cell 찾기. */\n private _findCell(col: number, row: number): StockpileGridCell | undefined {\n return (this.state.data ?? []).find(c => c.col === col && c.row === row)\n }\n\n /** cell 의 records (없으면 빈 배열). */\n recordsOf(col: number, row: number): ReadonlyArray<StockpileRecord> {\n return this._findCell(col, row)?.data ?? []\n }\n\n /** capacity 는 모든 cell 공통. */\n capacityOf(_col: number, _row: number): number | undefined {\n return this.state.capacity\n }\n\n // ── SlottedHolder — cell 별 slot ─────────────────────────────\n slotIds(): ReadonlyArray<string> {\n const out: string[] = []\n for (let r = 0; r < this.rows; r++) {\n for (let c = 0; c < this.cols; c++) out.push(this.cellIdOf(c, r))\n }\n return out\n }\n hasCarrierAt(slotId: string): boolean {\n const p = this.parseCellId(slotId)\n return !!p && this.recordsOf(p.col, p.row).length > 0\n }\n canReceiveAt(slotId: string, _carrier?: Component): boolean {\n const p = this.parseCellId(slotId)\n if (!p) return false\n const cap = this.capacityOf(p.col, p.row)\n if (typeof cap === 'number' && this.recordsOf(p.col, p.row).length >= cap) return false\n return true\n }\n occupiedSlotIds(): ReadonlyArray<string> {\n const out: string[] = []\n for (let r = 0; r < this.rows; r++) for (let c = 0; c < this.cols; c++) {\n if (this.recordsOf(c, r).length > 0) out.push(this.cellIdOf(c, r))\n }\n return out\n }\n emptySlotIds(): ReadonlyArray<string> {\n const out: string[] = []\n for (let r = 0; r < this.rows; r++) for (let c = 0; c < this.cols; c++) {\n if (this.canReceiveAt(this.cellIdOf(c, r))) out.push(this.cellIdOf(c, r))\n }\n return out\n }\n\n obtainCarrier(slotId: string): Component | null {\n const p = this.parseCellId(slotId)\n if (!p) return null\n const recs = this.recordsOf(p.col, p.row)\n if (recs.length === 0) return null\n const records = [...recs]\n const policy = (this.state.pickPolicy ?? 'lifo') as PickPolicy\n const record = policy === 'fifo' ? records.shift()! : records.pop()!\n this._setCellRecords(p.col, p.row, records)\n return this._materializeCarrier(record, p.col, p.row)\n }\n\n async receiveAt(slotId: string, carrier: Component, _options?: any): Promise<void> {\n const p = this.parseCellId(slotId)\n if (!p) return\n const cstate: any = (carrier as any)?.state ?? {}\n const cid = cstate.id ?? `stkg-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`\n const record: StockpileRecord = {\n id: String(cid),\n ...(cstate.type ? { type: cstate.type } : {}),\n ...(typeof cstate.width === 'number' ? { width: cstate.width } : {}),\n ...(typeof cstate.height === 'number' ? { height: cstate.height } : {}),\n ...(typeof cstate.depth === 'number' ? { depth: cstate.depth } : {})\n }\n const records = [...this.recordsOf(p.col, p.row), record]\n this._setCellRecords(p.col, p.row, records)\n ;(carrier as any)?.dispose?.()\n }\n\n async accept(carrier: Component, options?: any): Promise<void> {\n const empty = this.emptySlotIds()\n if (empty.length === 0) return\n return this.receiveAt(empty[0], carrier, options)\n }\n async receive(carrier: Component, options?: any): Promise<void> {\n return this.accept(carrier, options)\n }\n\n slotTargetAt(slotId: string): SlotTarget { return new SlotTarget(this as any, slotId) }\n getSlotAttachObject3d(slotId: string): any {\n return (this as any)._realObject?.getCellPadMesh?.(slotId)\n }\n\n attachPointFor(carrier: Component): AttachFrame | null {\n const ro = this._realObject\n const frame = ro?.getAttachFrame?.()\n if (!frame) return null\n const carrierDepth = resolveDepth(carrier)\n return { attach: frame, localPosition: { x: 0, y: carrierDepth / 2, z: 0 } }\n }\n\n private _setCellRecords(col: number, row: number, records: StockpileRecord[]): void {\n const cells = [...((this.state.data as StockpileGridCell[]) ?? [])]\n const idx = cells.findIndex(c => c.col === col && c.row === row)\n if (idx === -1) cells.push({ col, row, data: records })\n else cells[idx] = { ...cells[idx], data: records }\n ;(this.state as any).data = cells\n this._realObject?.update?.()\n }\n\n private _materializeCarrier(record: StockpileRecord, col: number, row: number): Component | null {\n const preset = (this.state.carrierPreset ?? 'box') as CarrierPreset\n const PRESET_TO_TYPE: Record<CarrierPreset, string> = {\n box: 'box', pallet: 'pallet', crate: 'box',\n drum: 'parcel', sack: 'parcel', bale: 'parcel'\n }\n const carrierType = (record as any).type ?? PRESET_TO_TYPE[preset] ?? 'parcel'\n const CarrierClass = (Component as any).register(carrierType) as\n | (new (...args: any[]) => Component) | undefined\n if (!CarrierClass) {\n console.warn(`[stockpile-grid] carrier type \"${carrierType}\" 미등록`)\n return null\n }\n\n const cw = this.state.carrierWidth ?? 30\n const ch = this.state.carrierHeight ?? 30\n const cd = this.state.carrierDepth ?? 22\n\n const { id: _id, refid: _refid, transform: _tf, ...recordCopy } = record as any\n const cellCenterX = col * this.cellW + this.cellW / 2\n const cellCenterZ = row * this.cellH + this.cellH / 2\n\n const carrierState: any = {\n ...recordCopy,\n type: carrierType,\n width: cw,\n height: ch,\n depth: cd,\n refid: _nextStockpileGridCarrierRefid(),\n left: cellCenterX - cw / 2,\n top: cellCenterZ - ch / 2\n }\n\n const carrier = new CarrierClass(carrierState, (this as any)._app)\n ;(this as any).addComponent(carrier, { silent: true })\n void (carrier as any).realObject\n ;(carrier as any).applyHolderAttachPoint?.()\n return carrier\n }\n\n // legendTarget / _onLegendChanged / resolveLegendColor — RecordStorage mixin 제공.\n\n // ── Popup + click — mixin 의 _invokePopup 활용, cell payload 만 wrapper ──\n get eventMap() {\n return { '(self)': { '(self)': { click: this._onGridClick } } }\n }\n private _onGridClick = (mouseEvent: MouseEvent) => {\n if (!(this as any).app?.isViewMode) return\n const hit = this._raycastHit(mouseEvent)\n if (!hit) return\n const slotId = (hit.object?.userData?.slotId as string | undefined)\n this._dispatchCellPopup(slotId)\n }\n private _dispatchCellPopup(slotId?: string): void {\n if (!this.state.popupRef) return\n if (slotId) {\n const p = this.parseCellId(slotId)\n this._invokePopup(slotId, {\n cellId: slotId,\n col: p?.col, row: p?.row,\n records: p ? this.recordsOf(p.col, p.row) : [],\n capacity: p ? this.capacityOf(p.col, p.row) : undefined\n })\n } else {\n this._invokePopup(this.cellIdOf(0, 0), {\n componentId: (this.state as any).id,\n cols: this.cols, rows: this.rows\n })\n }\n }\n\n private _raycastHit(mouseEvent: MouseEvent): THREE.Intersection | undefined {\n const ro: any = (this as any)._realObject\n if (!ro?.object3d) return undefined\n const tc: any = ro.threeContainer\n if (!tc) return undefined\n const cap: any = tc._threeCapability ?? tc._capability\n let intersects: THREE.Intersection[] | undefined\n if (cap?.getObjectsByRaycast) intersects = cap.getObjectsByRaycast() as THREE.Intersection[] | undefined\n if (!intersects || intersects.length === 0) {\n const scene = tc.scene3d as THREE.Scene | undefined\n const renderer = tc.renderer3d as THREE.WebGLRenderer | undefined\n const camera =\n (tc.activeCamera3d as THREE.Camera | undefined) ??\n (cap?.activeCamera as THREE.Camera | undefined) ??\n (cap?.camera as THREE.Camera | undefined)\n const canvas = renderer?.domElement\n if (!scene || !canvas || !camera) return undefined\n const rect = canvas.getBoundingClientRect()\n if (rect.width === 0 || rect.height === 0) return undefined\n const ndc = new THREE.Vector2(\n ((mouseEvent.clientX - rect.left) / rect.width) * 2 - 1,\n -((mouseEvent.clientY - rect.top) / rect.height) * 2 + 1\n )\n const raycaster = new THREE.Raycaster()\n raycaster.setFromCamera(ndc, camera)\n intersects = raycaster.intersectObjects(scene.children, true)\n }\n if (!intersects || intersects.length === 0) return undefined\n const closest = intersects[0]\n let obj: THREE.Object3D | null = closest.object\n while (obj) {\n if (obj.userData?.context === ro) return closest\n obj = obj.parent\n }\n return undefined\n }\n\n // ── 2D render ─────────────────────────────────────────────\n render(ctx: CanvasRenderingContext2D) {\n const { left = 0, top = 0 } = this.state\n const totalW = this.cellW * this.cols\n const totalH = this.cellH * this.rows\n const fillStyle = (this.state.fillStyle as string) || '#c89c5c'\n const strokeStyle = (this.state.strokeStyle as string) || '#7a5a2e'\n\n ctx.save()\n ctx.fillStyle = fillStyle\n ctx.globalAlpha = 0.15\n ctx.fillRect(left, top, totalW, totalH)\n ctx.restore()\n\n ctx.save()\n ctx.strokeStyle = strokeStyle\n ctx.lineWidth = 1.2\n ctx.strokeRect(left + 0.6, top + 0.6, totalW - 1.2, totalH - 1.2)\n for (let c = 1; c < this.cols; c++) {\n const x = left + c * this.cellW\n ctx.beginPath(); ctx.moveTo(x, top); ctx.lineTo(x, top + totalH); ctx.stroke()\n }\n for (let r = 1; r < this.rows; r++) {\n const y = top + r * this.cellH\n ctx.beginPath(); ctx.moveTo(left, y); ctx.lineTo(left + totalW, y); ctx.stroke()\n }\n ctx.restore()\n\n ctx.save()\n const fontSize = Math.min(this.cellW, this.cellH) * 0.22\n ctx.fillStyle = '#333'\n ctx.font = `bold ${fontSize}px sans-serif`\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n for (let r = 0; r < this.rows; r++) for (let c = 0; c < this.cols; c++) {\n const count = this.recordsOf(c, r).length\n if (count === 0) continue\n ctx.fillText(`${count}`, left + (c + 0.5) * this.cellW, top + (r + 0.5) * this.cellH)\n }\n ctx.restore()\n }\n\n buildRealObject(): RealObject | undefined {\n return new StockpileGrid3D(this)\n }\n}\n\nlet _stockpileGridCarrierSeq = 0\nfunction _nextStockpileGridCarrierRefid(): number {\n return 850000 + (_stockpileGridCarrierSeq++)\n}\n\nfunction resolveDepth(c: Component): number {\n const eff = (c as any)._realObject?.effectiveDepth\n if (typeof eff === 'number' && Number.isFinite(eff)) return eff\n const d = (c as any)?.state?.depth\n return typeof d === 'number' && Number.isFinite(d) ? d : 0\n}\n"]}
|
|
1
|
+
{"version":3,"file":"stockpile-grid.js","sourceRoot":"","sources":["../src/stockpile-grid.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * StockpileGrid — cols × rows cell 들로 분할된 평치 영역. cell 들은 grid 공통 설정\n * (carrierPreset/stackPattern/크기/capacity 등)을 *_모두 공유_* 하고, 각 cell 은 자기\n * 위치(col, row)에서의 records 만 별도 가진다. cell 별 override 는 의미가 없어\n * 제거됨 — cell 별 다른 설정이 진짜 필요한 경우엔 Stockpile 컴포넌트를 따로 두는\n * 것이 자연스럽다.\n *\n * state.data = grid 의 cell 들 배열 (각 element 는 cell-단위 stockpile-like 데이터).\n * data: [\n * { col: 0, row: 0, data: [{ id, ... }, ...] },\n * { col: 1, row: 0, data: [...] },\n * ...\n * ]\n * cell.data 가 그 cell 의 records. 외부 데이터 매핑은 이 배열을 target.\n */\n\nimport * as THREE from 'three'\nimport { Component, ComponentNature, ContainerAbstract, RealObject, sceneComponent } from '@hatiolab/things-scene'\nimport type { State, Material3D } from '@hatiolab/things-scene'\nimport {\n CarrierHolder,\n Placeable,\n RecordStorage,\n SlotTarget,\n type AttachFrame,\n type Alignment,\n type Heights,\n type PlacementArchetype,\n type SlottedHolder\n} from '@operato/scene-base'\n\nimport { StockpileGrid3D } from './stockpile-grid-3d.js'\nimport type { StackPattern, CarrierPreset, StockpileRecord, PickPolicy } from './stockpile.js'\n\n/** grid 의 한 cell — 위치 + 그 cell 의 records. */\nexport interface StockpileGridCell {\n col: number\n row: number\n data?: StockpileRecord[]\n}\n\nexport interface StockpileGridState extends State {\n cols?: number\n rows?: number\n /** 한 cell 의 평면 크기 (전체 width/height = cellWidth*cols, cellHeight*rows). */\n cellWidth?: number\n cellHeight?: number\n\n /** grid 의 cell 들 — 각 cell 은 { col, row, data: Record[] }. */\n data?: StockpileGridCell[]\n\n // ── 공통 carrier 설정 (모든 cell 공유) ──\n stackPattern?: StackPattern\n carrierPreset?: CarrierPreset\n carrierWidth?: number\n carrierHeight?: number\n carrierDepth?: number\n carrierGap?: number\n capacity?: number // cell 별 capacity (모든 cell 공통)\n stackHeightLimit?: number\n pickPolicy?: PickPolicy\n\n popupRef?: string\n legendTarget?: string\n material3d?: Material3D\n}\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n { type: 'number', label: 'cols', name: 'cols' },\n { type: 'number', label: 'rows', name: 'rows' },\n { type: 'number', label: 'cell-width', name: 'cellWidth' },\n { type: 'number', label: 'cell-height', name: 'cellHeight' },\n { type: 'select', label: 'stack-pattern', name: 'stackPattern',\n property: { options: ['row', 'staggered', 'pyramid', 'column', 'pile'] } },\n { type: 'select', label: 'carrier-preset', name: 'carrierPreset',\n property: { options: ['box', 'pallet', 'drum', 'sack', 'crate', 'bale'] } },\n { type: 'number', label: 'carrier-width', name: 'carrierWidth' },\n { type: 'number', label: 'carrier-height', name: 'carrierHeight' },\n { type: 'number', label: 'carrier-depth', name: 'carrierDepth' },\n { type: 'number', label: 'carrier-gap', name: 'carrierGap' },\n { type: 'number', label: 'capacity', name: 'capacity' },\n { type: 'number', label: 'stack-height-limit', name: 'stackHeightLimit' },\n { type: 'select', label: 'pick-policy', name: 'pickPolicy',\n property: { options: ['lifo', 'fifo'] } },\n { type: 'id-input', label: 'popup-ref', name: 'popupRef',\n property: { component: 'popup' } },\n { type: 'id-input', label: 'legend-target', name: 'legendTarget',\n property: { component: 'legend' },\n placeholder: '미명시 시 scene 의 legend 자동 발견' }\n ],\n help: 'scene/component/stockpile-grid'\n}\n\n@sceneComponent('stockpile-grid')\nexport default class StockpileGrid extends RecordStorage<StockpileGridCell>()(\n CarrierHolder(Placeable(ContainerAbstract))\n) implements SlottedHolder {\n declare state: StockpileGridState\n declare _realObject?: StockpileGrid3D\n\n static placement: PlacementArchetype = 'floor'\n static align: Alignment = 'bottom'\n static defaultDepth = (_h: Heights) => 5\n\n get nature(): ComponentNature { return NATURE }\n get anchors() { return [] }\n\n // RecordStorage mixin 의 records / inventoryCount / addRecord / removeRecord 는\n // cell-aware 시맨틱과 호환 안 됨. cell-nested data 라 *_recordsOf(col,row)_* 와\n // _setCellRecords 를 사용. legend / popup / onLegendChanged 는 mixin 사용.\n // _rebuildVisual hook 만 override.\n _rebuildVisual(): void {\n this._realObject?.update?.()\n }\n\n // ── grid 좌표 helpers ─────────────────────────────────────\n get cols(): number { return Math.max(1, Math.floor(this.state.cols ?? 3)) }\n get rows(): number { return Math.max(1, Math.floor(this.state.rows ?? 3)) }\n get cellW(): number { return this.state.cellWidth ?? 80 }\n get cellH(): number { return this.state.cellHeight ?? 80 }\n\n cellIdOf(col: number, row: number): string { return `${col}-${row}` }\n parseCellId(slotId: string): { col: number; row: number } | null {\n const m = slotId.match(/^(\\d+)-(\\d+)$/)\n if (!m) return null\n return { col: Number(m[1]), row: Number(m[2]) }\n }\n\n /** state.data 에서 (col,row) cell 찾기. */\n private _findCell(col: number, row: number): StockpileGridCell | undefined {\n return (this.state.data ?? []).find(c => c.col === col && c.row === row)\n }\n\n /** cell 의 records (없으면 빈 배열). */\n recordsOf(col: number, row: number): ReadonlyArray<StockpileRecord> {\n return this._findCell(col, row)?.data ?? []\n }\n\n /** capacity 는 모든 cell 공통. */\n capacityOf(_col: number, _row: number): number | undefined {\n return this.state.capacity\n }\n\n // ── SlottedHolder — cell 별 slot ─────────────────────────────\n slotIds(): ReadonlyArray<string> {\n const out: string[] = []\n for (let r = 0; r < this.rows; r++) {\n for (let c = 0; c < this.cols; c++) out.push(this.cellIdOf(c, r))\n }\n return out\n }\n hasCarrierAt(slotId: string): boolean {\n const p = this.parseCellId(slotId)\n return !!p && this.recordsOf(p.col, p.row).length > 0\n }\n canReceiveAt(slotId: string, _carrier?: Component): boolean {\n const p = this.parseCellId(slotId)\n if (!p) return false\n const cap = this.capacityOf(p.col, p.row)\n if (typeof cap === 'number' && this.recordsOf(p.col, p.row).length >= cap) return false\n return true\n }\n occupiedSlotIds(): ReadonlyArray<string> {\n const out: string[] = []\n for (let r = 0; r < this.rows; r++) for (let c = 0; c < this.cols; c++) {\n if (this.recordsOf(c, r).length > 0) out.push(this.cellIdOf(c, r))\n }\n return out\n }\n emptySlotIds(): ReadonlyArray<string> {\n const out: string[] = []\n for (let r = 0; r < this.rows; r++) for (let c = 0; c < this.cols; c++) {\n if (this.canReceiveAt(this.cellIdOf(c, r))) out.push(this.cellIdOf(c, r))\n }\n return out\n }\n\n obtainCarrier(slotId: string): Component | null {\n const p = this.parseCellId(slotId)\n if (!p) return null\n const recs = this.recordsOf(p.col, p.row)\n if (recs.length === 0) return null\n const records = [...recs]\n const policy = (this.state.pickPolicy ?? 'lifo') as PickPolicy\n const record = policy === 'fifo' ? records.shift()! : records.pop()!\n this._setCellRecords(p.col, p.row, records)\n return this._materializeCarrier(record, p.col, p.row)\n }\n\n /**\n * carrier → StockpileRecord 추출. id 누락 시 `stkg-` prefix 자동 생성.\n * SlottedHolder duck 의 표준 entry — receiveAt 안에서 호출. cell 정보 (col/row) 는\n * slotId 의 parseCellId 로 receiveAt 가 처리 — record 자체에는 cell 좌표 미포함\n * (cell array 가 그 컨텍스트 보유).\n */\n recordFromCarrier(carrier: Component, _slotId: string): StockpileRecord {\n const cstate: any = (carrier as any)?.state ?? {}\n const cid = cstate.id ?? `stkg-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`\n return {\n id: String(cid),\n ...(cstate.type ? { type: cstate.type } : {}),\n ...(typeof cstate.width === 'number' ? { width: cstate.width } : {}),\n ...(typeof cstate.height === 'number' ? { height: cstate.height } : {}),\n ...(typeof cstate.depth === 'number' ? { depth: cstate.depth } : {})\n }\n }\n\n async receiveAt(slotId: string, carrier: Component, _options?: any): Promise<void> {\n const p = this.parseCellId(slotId)\n if (!p) return\n const record = this.recordFromCarrier(carrier, slotId)\n const records = [...this.recordsOf(p.col, p.row), record]\n this._setCellRecords(p.col, p.row, records)\n ;(carrier as any)?.dispose?.()\n }\n\n async accept(carrier: Component, options?: any): Promise<void> {\n const empty = this.emptySlotIds()\n if (empty.length === 0) return\n return this.receiveAt(empty[0], carrier, options)\n }\n async receive(carrier: Component, options?: any): Promise<void> {\n return this.accept(carrier, options)\n }\n\n slotTargetAt(slotId: string): SlotTarget { return new SlotTarget(this as any, slotId) }\n getSlotAttachObject3d(slotId: string): any {\n return (this as any)._realObject?.getCellPadMesh?.(slotId)\n }\n\n attachPointFor(carrier: Component): AttachFrame | null {\n const ro = this._realObject\n const frame = ro?.getAttachFrame?.()\n if (!frame) return null\n const carrierDepth = resolveDepth(carrier)\n return { attach: frame, localPosition: { x: 0, y: carrierDepth / 2, z: 0 } }\n }\n\n private _setCellRecords(col: number, row: number, records: StockpileRecord[]): void {\n const cells = [...((this.state.data as StockpileGridCell[]) ?? [])]\n const idx = cells.findIndex(c => c.col === col && c.row === row)\n if (idx === -1) cells.push({ col, row, data: records })\n else cells[idx] = { ...cells[idx], data: records }\n ;(this.state as any).data = cells\n this._realObject?.update?.()\n }\n\n private _materializeCarrier(record: StockpileRecord, col: number, row: number): Component | null {\n const preset = (this.state.carrierPreset ?? 'box') as CarrierPreset\n const PRESET_TO_TYPE: Record<CarrierPreset, string> = {\n box: 'box', pallet: 'pallet', crate: 'box',\n drum: 'parcel', sack: 'parcel', bale: 'parcel'\n }\n const carrierType = (record as any).type ?? PRESET_TO_TYPE[preset] ?? 'parcel'\n const CarrierClass = (Component as any).register(carrierType) as\n | (new (...args: any[]) => Component) | undefined\n if (!CarrierClass) {\n console.warn(`[stockpile-grid] carrier type \"${carrierType}\" 미등록`)\n return null\n }\n\n const cw = this.state.carrierWidth ?? 30\n const ch = this.state.carrierHeight ?? 30\n const cd = this.state.carrierDepth ?? 22\n\n const { id: _id, refid: _refid, transform: _tf, ...recordCopy } = record as any\n const cellCenterX = col * this.cellW + this.cellW / 2\n const cellCenterZ = row * this.cellH + this.cellH / 2\n\n const carrierState: any = {\n ...recordCopy,\n type: carrierType,\n width: cw,\n height: ch,\n depth: cd,\n refid: _nextStockpileGridCarrierRefid(),\n left: cellCenterX - cw / 2,\n top: cellCenterZ - ch / 2\n }\n\n const carrier = new CarrierClass(carrierState, (this as any)._app)\n ;(this as any).addComponent(carrier, { silent: true })\n void (carrier as any).realObject\n ;(carrier as any).applyHolderAttachPoint?.()\n return carrier\n }\n\n // legendTarget / _onLegendChanged / resolveLegendColor — RecordStorage mixin 제공.\n\n // ── Popup + click — mixin 의 _invokePopup 활용, cell payload 만 wrapper ──\n get eventMap() {\n return { '(self)': { '(self)': { click: this._onGridClick } } }\n }\n private _onGridClick = (mouseEvent: MouseEvent) => {\n if (!(this as any).app?.isViewMode) return\n const hit = this._raycastHit(mouseEvent)\n if (!hit) return\n const slotId = (hit.object?.userData?.slotId as string | undefined)\n this._dispatchCellPopup(slotId)\n }\n private _dispatchCellPopup(slotId?: string): void {\n if (!this.state.popupRef) return\n if (slotId) {\n const p = this.parseCellId(slotId)\n this._invokePopup(slotId, {\n cellId: slotId,\n col: p?.col, row: p?.row,\n records: p ? this.recordsOf(p.col, p.row) : [],\n capacity: p ? this.capacityOf(p.col, p.row) : undefined\n })\n } else {\n this._invokePopup(this.cellIdOf(0, 0), {\n componentId: (this.state as any).id,\n cols: this.cols, rows: this.rows\n })\n }\n }\n\n private _raycastHit(mouseEvent: MouseEvent): THREE.Intersection | undefined {\n const ro: any = (this as any)._realObject\n if (!ro?.object3d) return undefined\n const tc: any = ro.threeContainer\n if (!tc) return undefined\n const cap: any = tc._threeCapability ?? tc._capability\n let intersects: THREE.Intersection[] | undefined\n if (cap?.getObjectsByRaycast) intersects = cap.getObjectsByRaycast() as THREE.Intersection[] | undefined\n if (!intersects || intersects.length === 0) {\n const scene = tc.scene3d as THREE.Scene | undefined\n const renderer = tc.renderer3d as THREE.WebGLRenderer | undefined\n const camera =\n (tc.activeCamera3d as THREE.Camera | undefined) ??\n (cap?.activeCamera as THREE.Camera | undefined) ??\n (cap?.camera as THREE.Camera | undefined)\n const canvas = renderer?.domElement\n if (!scene || !canvas || !camera) return undefined\n const rect = canvas.getBoundingClientRect()\n if (rect.width === 0 || rect.height === 0) return undefined\n const ndc = new THREE.Vector2(\n ((mouseEvent.clientX - rect.left) / rect.width) * 2 - 1,\n -((mouseEvent.clientY - rect.top) / rect.height) * 2 + 1\n )\n const raycaster = new THREE.Raycaster()\n raycaster.setFromCamera(ndc, camera)\n intersects = raycaster.intersectObjects(scene.children, true)\n }\n if (!intersects || intersects.length === 0) return undefined\n const closest = intersects[0]\n let obj: THREE.Object3D | null = closest.object\n while (obj) {\n if (obj.userData?.context === ro) return closest\n obj = obj.parent\n }\n return undefined\n }\n\n // ── 2D render ─────────────────────────────────────────────\n render(ctx: CanvasRenderingContext2D) {\n const { left = 0, top = 0 } = this.state\n const totalW = this.cellW * this.cols\n const totalH = this.cellH * this.rows\n const fillStyle = (this.state.fillStyle as string) || '#c89c5c'\n const strokeStyle = (this.state.strokeStyle as string) || '#7a5a2e'\n\n ctx.save()\n ctx.fillStyle = fillStyle\n ctx.globalAlpha = 0.15\n ctx.fillRect(left, top, totalW, totalH)\n ctx.restore()\n\n ctx.save()\n ctx.strokeStyle = strokeStyle\n ctx.lineWidth = 1.2\n ctx.strokeRect(left + 0.6, top + 0.6, totalW - 1.2, totalH - 1.2)\n for (let c = 1; c < this.cols; c++) {\n const x = left + c * this.cellW\n ctx.beginPath(); ctx.moveTo(x, top); ctx.lineTo(x, top + totalH); ctx.stroke()\n }\n for (let r = 1; r < this.rows; r++) {\n const y = top + r * this.cellH\n ctx.beginPath(); ctx.moveTo(left, y); ctx.lineTo(left + totalW, y); ctx.stroke()\n }\n ctx.restore()\n\n ctx.save()\n const fontSize = Math.min(this.cellW, this.cellH) * 0.22\n ctx.fillStyle = '#333'\n ctx.font = `bold ${fontSize}px sans-serif`\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n for (let r = 0; r < this.rows; r++) for (let c = 0; c < this.cols; c++) {\n const count = this.recordsOf(c, r).length\n if (count === 0) continue\n ctx.fillText(`${count}`, left + (c + 0.5) * this.cellW, top + (r + 0.5) * this.cellH)\n }\n ctx.restore()\n }\n\n buildRealObject(): RealObject | undefined {\n return new StockpileGrid3D(this)\n }\n}\n\nlet _stockpileGridCarrierSeq = 0\nfunction _nextStockpileGridCarrierRefid(): number {\n return 850000 + (_stockpileGridCarrierSeq++)\n}\n\nfunction resolveDepth(c: Component): number {\n const eff = (c as any)._realObject?.effectiveDepth\n if (typeof eff === 'number' && Number.isFinite(eff)) return eff\n const d = (c as any)?.state?.depth\n return typeof d === 'number' && Number.isFinite(d) ? d : 0\n}\n"]}
|
package/dist/stockpile.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Component, ComponentNature, RealObject } from '@hatiolab/things-scene';
|
|
2
2
|
import type { State, Material3D } from '@hatiolab/things-scene';
|
|
3
|
-
import { SlotTarget, type AttachFrame, type Alignment, type Heights, type PlacementArchetype } from '@operato/scene-base';
|
|
3
|
+
import { SlotTarget, type AttachFrame, type Alignment, type Heights, type PlacementArchetype, type SlottedHolder } from '@operato/scene-base';
|
|
4
4
|
import { Stockpile3D } from './stockpile-3d.js';
|
|
5
5
|
export type StackPattern = 'row' | 'staggered' | 'pyramid' | 'column' | 'pile';
|
|
6
6
|
export type CarrierPreset = 'box' | 'pallet' | 'drum' | 'sack' | 'crate' | 'bale';
|
|
@@ -40,7 +40,7 @@ export interface StockpileState extends State {
|
|
|
40
40
|
material3d?: Material3D;
|
|
41
41
|
}
|
|
42
42
|
declare const Stockpile_base: any;
|
|
43
|
-
export default class Stockpile extends Stockpile_base {
|
|
43
|
+
export default class Stockpile extends Stockpile_base implements SlottedHolder {
|
|
44
44
|
state: StockpileState;
|
|
45
45
|
_realObject?: Stockpile3D;
|
|
46
46
|
static placement: PlacementArchetype;
|
|
@@ -61,11 +61,17 @@ export default class Stockpile extends Stockpile_base {
|
|
|
61
61
|
*/
|
|
62
62
|
obtainCarrier(slotId: string): Component | null;
|
|
63
63
|
private _materializeCarrier;
|
|
64
|
+
/**
|
|
65
|
+
* carrier 의 state → StockpileRecord 추출. id 누락 시 `stk-` prefix 자동 생성.
|
|
66
|
+
* transform/refid 등 *_물리적 위치 필드_* 는 *_제외_* — record 는 *_논리적 식별_*
|
|
67
|
+
* 만. SlottedHolder duck 의 표준 entry point — receiveAt 안에서 호출.
|
|
68
|
+
*/
|
|
69
|
+
recordFromCarrier(carrier: Component, _slotId: string): StockpileRecord;
|
|
64
70
|
/**
|
|
65
71
|
* carrier 를 받아 record 로 push, carrier 객체는 dispose (시각은 _realObject 가
|
|
66
72
|
* records 길이 기준 자동 갱신). capacity 초과 시도는 canReceiveAt 가 이미 차단.
|
|
67
73
|
*/
|
|
68
|
-
receiveAt(
|
|
74
|
+
receiveAt(slotId: string, carrier: Component, _options?: any): Promise<void>;
|
|
69
75
|
/** dispatch → handoff 의 accept 분기 — receiveAt 으로 위임. */
|
|
70
76
|
accept(carrier: Component, options?: any): Promise<void>;
|
|
71
77
|
receive(carrier: Component, options?: any): Promise<void>;
|
package/dist/stockpile.js
CHANGED
|
@@ -132,19 +132,27 @@ let Stockpile = class Stockpile extends RecordStorage()(CarrierHolder(Placeable(
|
|
|
132
132
|
return carrier;
|
|
133
133
|
}
|
|
134
134
|
/**
|
|
135
|
-
* carrier
|
|
136
|
-
*
|
|
135
|
+
* carrier 의 state → StockpileRecord 추출. id 누락 시 `stk-` prefix 자동 생성.
|
|
136
|
+
* transform/refid 등 *_물리적 위치 필드_* 는 *_제외_* — record 는 *_논리적 식별_*
|
|
137
|
+
* 만. SlottedHolder duck 의 표준 entry point — receiveAt 안에서 호출.
|
|
137
138
|
*/
|
|
138
|
-
|
|
139
|
+
recordFromCarrier(carrier, _slotId) {
|
|
139
140
|
const cstate = carrier?.state ?? {};
|
|
140
141
|
const cid = cstate.id ?? `stk-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
|
|
141
|
-
|
|
142
|
+
return {
|
|
142
143
|
id: String(cid),
|
|
143
144
|
...(cstate.type ? { type: cstate.type } : {}),
|
|
144
145
|
...(typeof cstate.width === 'number' ? { width: cstate.width } : {}),
|
|
145
146
|
...(typeof cstate.height === 'number' ? { height: cstate.height } : {}),
|
|
146
147
|
...(typeof cstate.depth === 'number' ? { depth: cstate.depth } : {})
|
|
147
148
|
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* carrier 를 받아 record 로 push, carrier 객체는 dispose (시각은 _realObject 가
|
|
152
|
+
* records 길이 기준 자동 갱신). capacity 초과 시도는 canReceiveAt 가 이미 차단.
|
|
153
|
+
*/
|
|
154
|
+
async receiveAt(slotId, carrier, _options) {
|
|
155
|
+
const record = this.recordFromCarrier(carrier, slotId);
|
|
148
156
|
const records = [...this.records, record];
|
|
149
157
|
this._setDataSilently(records);
|
|
150
158
|
carrier?.dispose?.();
|
package/dist/stockpile.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stockpile.js","sourceRoot":"","sources":["../src/stockpile.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * Stockpile — 평치(block/floor) 보관 영역. 사각형 footprint + `state.data` 의 record[].\n * 실제 carrier component 를 자식으로 두지 않고, 인벤토리(records)의 *_개수와 종류_* 만으로\n * 가상 carrier mesh 를 자동 적치(stackPattern × carrierPreset)해 시각화한다.\n *\n * 데이터 idiom — StorageRack 과 동일 (`state.data: Record[]`). mover 가 pick/place 하면\n * record push/pop, _realObject 가 records.length 기준 mesh 를 재배치.\n *\n * 1단계 — 시각화: 모델에 `data: [{id:'a'},{id:'b'},...]` 가 들어오면 mesh 가 자동 적치.\n * 2단계(추후) — mover 통합: obtainCarrier 가 transient carrier 컴포넌트 materialize,\n * receiveAt 가 record push + carrier dispose.\n */\n\nimport * as THREE from 'three'\nimport { Component, ComponentNature, ContainerAbstract, RealObject, sceneComponent } from '@hatiolab/things-scene'\nimport type { State, Material3D } from '@hatiolab/things-scene'\nimport {\n CarrierHolder,\n Placeable,\n RecordStorage,\n SlotTarget,\n type AttachFrame,\n type Alignment,\n type Heights,\n type PlacementArchetype\n} from '@operato/scene-base'\n\nimport { Stockpile3D } from './stockpile-3d.js'\n\nexport type StackPattern = 'row' | 'staggered' | 'pyramid' | 'column' | 'pile'\nexport type CarrierPreset = 'box' | 'pallet' | 'drum' | 'sack' | 'crate' | 'bale'\nexport type PickPolicy = 'lifo' | 'fifo'\n\n/** 적치된 carrier 의 record. 향후 sku / weight / 입고시각 등 확장. */\nexport interface StockpileRecord {\n id: string\n [key: string]: any\n}\n\nexport interface StockpileState extends State {\n /** 적치 carrier 의 record 목록 — storage-rack 의 state.data 와 동일 idiom. */\n data?: StockpileRecord[]\n\n /** 적치 형태 프리셋. default 'row'. */\n stackPattern?: StackPattern\n /** 가상 carrier 종류 프리셋. default 'box'. */\n carrierPreset?: CarrierPreset\n\n /** 가상 carrier 한 개의 크기 (없으면 preset 별 기본). */\n carrierWidth?: number\n carrierHeight?: number\n carrierDepth?: number\n /** 적치된 carrier 사이의 평면(xz) 간격 — 0 이면 딱 붙음, default 3. y(단 적층)는 항상 딱 붙음. */\n carrierGap?: number\n\n /** 최대 적치 수 (undefined = 무제한). */\n capacity?: number\n /** 위로 몇 단까지 (undefined = stack 형태에 맡김). */\n stackHeightLimit?: number\n /** 어느 끝에서 빼나. default 'lifo'. */\n pickPolicy?: PickPolicy\n\n /** click 시 invoke 할 Popup 컴포넌트 id (StorageRack / RackGrid 와 동일 패턴). */\n popupRef?: string\n\n /**\n * Legend 컴포넌트 id. legend 의 `state.status = {field, ranges, defaultColor}` 를\n * 참조해 각 record 의 field 값을 색상으로 매핑한다 (StorageRack 와 동일 패턴).\n * 미명시 시 scene 안 `type='legend'` 첫 컴포넌트 자동 발견.\n */\n legendTarget?: string\n\n material3d?: Material3D\n}\n\nconst SLOT_ID = 'pile'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n { type: 'select', label: 'stack-pattern', name: 'stackPattern',\n property: { options: ['row', 'staggered', 'pyramid', 'column', 'pile'] } },\n { type: 'select', label: 'carrier-preset', name: 'carrierPreset',\n property: { options: ['box', 'pallet', 'drum', 'sack', 'crate', 'bale'] } },\n { type: 'number', label: 'carrier-width', name: 'carrierWidth' },\n { type: 'number', label: 'carrier-height', name: 'carrierHeight' },\n { type: 'number', label: 'carrier-depth', name: 'carrierDepth' },\n { type: 'number', label: 'carrier-gap', name: 'carrierGap' },\n { type: 'number', label: 'capacity', name: 'capacity' },\n { type: 'number', label: 'stack-height-limit', name: 'stackHeightLimit' },\n { type: 'select', label: 'pick-policy', name: 'pickPolicy',\n property: { options: ['lifo', 'fifo'] } },\n { type: 'id-input', label: 'popup-ref', name: 'popupRef',\n property: { component: 'popup' } },\n { type: 'id-input', label: 'legend-target', name: 'legendTarget',\n property: { component: 'legend' },\n placeholder: '미명시 시 scene 의 legend 자동 발견' }\n ],\n help: 'scene/component/stockpile'\n}\n\n@sceneComponent('stockpile')\nexport default class Stockpile extends RecordStorage<StockpileRecord>()(\n CarrierHolder(Placeable(ContainerAbstract))\n) {\n declare state: StockpileState\n declare _realObject?: Stockpile3D\n\n static placement: PlacementArchetype = 'floor'\n static align: Alignment = 'bottom'\n static defaultDepth = (_h: Heights) => 5 // pad 두께\n\n get nature(): ComponentNature { return NATURE }\n get anchors() { return [] }\n\n // ── records / inventoryCount: RecordStorage mixin 제공.\n\n // ── SlottedHolder duck-type override — 단일 slot ('pile') ───────────────\n // mixin default 는 record 마다 slotId. Stockpile 은 *_단일 슬롯_* 시맨틱이라\n // 자기 구현 유지.\n slotIds(): ReadonlyArray<string> { return [SLOT_ID] }\n\n hasCarrierAt(slotId: string): boolean {\n return slotId === SLOT_ID && this.inventoryCount > 0\n }\n\n canReceiveAt(slotId: string, _carrier?: Component): boolean {\n if (slotId !== SLOT_ID) return false\n const cap = this.state.capacity\n if (typeof cap === 'number' && this.inventoryCount >= cap) return false\n return true\n }\n\n occupiedSlotIds(): ReadonlyArray<string> {\n return this.inventoryCount > 0 ? [SLOT_ID] : []\n }\n emptySlotIds(): ReadonlyArray<string> {\n return this.canReceiveAt(SLOT_ID) ? [SLOT_ID] : []\n }\n\n /**\n * record 한 개를 빼서 carrier 컴포넌트로 transient materialize. mover 가 pickup\n * 하면 이걸 reparent 해서 들고 다닌다. storage-rack._materializeCarrier 와 동일\n * 패턴 — Component.register(type) 으로 클래스 lookup, addComponent({silent: true})\n * 로 cascade 차단.\n */\n obtainCarrier(slotId: string): Component | null {\n if (slotId !== SLOT_ID) return null\n if (this.records.length === 0) return null\n const records = [...this.records]\n const policy = (this.state.pickPolicy ?? 'lifo') as PickPolicy\n const record = policy === 'fifo' ? records.shift()! : records.pop()!\n this._setDataSilently(records)\n return this._materializeCarrier(record)\n }\n\n private _materializeCarrier(record: StockpileRecord): Component | null {\n // carrierPreset → 등록된 컴포넌트 type. 미등록(drum/sack/bale 등) 은 시각 mesh\n // 전용이라 carrier 컴포넌트로는 fallback ('parcel'/'box').\n const preset = (this.state.carrierPreset ?? 'box') as CarrierPreset\n const PRESET_TO_TYPE: Record<CarrierPreset, string> = {\n box: 'box',\n pallet: 'pallet',\n crate: 'box',\n drum: 'parcel',\n sack: 'parcel',\n bale: 'parcel'\n }\n const carrierType = (record as any).type ?? PRESET_TO_TYPE[preset] ?? 'parcel'\n const CarrierClass = (Component as any).register(carrierType) as\n | (new (...args: any[]) => Component) | undefined\n if (!CarrierClass) {\n console.warn(`[stockpile] carrier type \"${carrierType}\" 미등록 — obtainCarrier 실패`)\n return null\n }\n\n // 크기 — state.carrier* 또는 preset default\n const stockpileW = (this.state as any).width ?? 100\n const stockpileH = (this.state as any).height ?? 100\n const cw = this.state.carrierWidth ?? 30\n const ch = this.state.carrierHeight ?? 30\n const cd = this.state.carrierDepth ?? 22\n\n // id/refid/transform 류 제외 — scene 안 기존 component 충돌 회피 (storage-rack 패턴)\n const { id: _id, refid: _refid, transform: _tf, ...recordCopy } = record as any\n // stockpile-inner 좌표 — center 에 놓기 (Mover 가 곧 pick 해 들고 감)\n const carrierState: any = {\n ...recordCopy,\n type: carrierType,\n width: cw,\n height: ch,\n depth: cd,\n refid: _nextStockpileCarrierRefid(),\n left: stockpileW / 2 - cw / 2,\n top: stockpileH / 2 - ch / 2\n }\n\n const carrier = new CarrierClass(carrierState, (this as any)._app)\n // silent: refreshMappings cascade 차단 (transient 라 매핑 재계산 불필요)\n ;(this as any).addComponent(carrier, { silent: true })\n void (carrier as any).realObject\n ;(carrier as any).applyHolderAttachPoint?.()\n return carrier\n }\n\n /**\n * carrier 를 받아 record 로 push, carrier 객체는 dispose (시각은 _realObject 가\n * records 길이 기준 자동 갱신). capacity 초과 시도는 canReceiveAt 가 이미 차단.\n */\n async receiveAt(_slotId: string, carrier: Component, _options?: any): Promise<void> {\n const cstate: any = (carrier as any)?.state ?? {}\n const cid = cstate.id ?? `stk-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`\n const record: StockpileRecord = {\n id: String(cid),\n ...(cstate.type ? { type: cstate.type } : {}),\n ...(typeof cstate.width === 'number' ? { width: cstate.width } : {}),\n ...(typeof cstate.height === 'number' ? { height: cstate.height } : {}),\n ...(typeof cstate.depth === 'number' ? { depth: cstate.depth } : {})\n }\n const records = [...this.records, record]\n this._setDataSilently(records)\n ;(carrier as any)?.dispose?.()\n }\n\n /** dispatch → handoff 의 accept 분기 — receiveAt 으로 위임. */\n async accept(carrier: Component, options?: any): Promise<void> {\n return this.receiveAt(SLOT_ID, carrier, options)\n }\n async receive(carrier: Component, options?: any): Promise<void> {\n return this.receiveAt(SLOT_ID, carrier, options)\n }\n\n /**\n * mover 가 obtainCarrier 로 빼낸 transient carrier 를 pad 위에 안착 (잠깐 보이는\n * 위치). mover 가 pick 하면 즉시 deck 으로 reparent 되므로 잔류는 짧다.\n * Spot 과 동일 idiom — pad-top + carrier 의 halfDepth 만큼 들어올림.\n */\n attachPointFor(carrier: Component): AttachFrame | null {\n const ro = this._realObject\n const frame = ro?.getAttachFrame?.()\n if (!frame) return null\n const carrierDepth = resolveDepth(carrier)\n return {\n attach: frame,\n localPosition: { x: 0, y: carrierDepth / 2, z: 0 }\n }\n }\n\n slotTargetAt(slotId: string): SlotTarget {\n return new SlotTarget(this as any, slotId)\n }\n getSlotAttachObject3d(slotId: string): any {\n // slotId 가 'pile' 이면 pad. record.id 면 그 carrier mesh — popup tether 가 그\n // stock 에 정확히 연결되도록.\n return (this as any)._realObject?.getAttachFrame?.(slotId)\n }\n\n // _setDataSilently 는 RecordStorage mixin 제공 — 다만 mixin 은 _rebuildVisual\n // 호출. Stockpile 의 3D 갱신은 update() 라서 hook override.\n _rebuildVisual(): void {\n this._realObject?.update?.()\n }\n\n /**\n * 2D — outlined pad + 인벤토리 카운트 텍스트. 평치 의도가 한 눈에 — 사각 영역 위에\n * 적재된 carrier 수가 가운데 큰 글씨로.\n */\n render(ctx: CanvasRenderingContext2D) {\n const { left = 0, top = 0, width = 100, height = 100 } = this.state\n const fillStyle = (this.state.fillStyle as string) || '#c89c5c'\n const strokeStyle = (this.state.strokeStyle as string) || fillStyle\n\n // pad (반투명)\n ctx.save()\n ctx.fillStyle = fillStyle\n ctx.globalAlpha = 0.18\n ctx.fillRect(left, top, width, height)\n ctx.restore()\n\n // outline (dashed)\n ctx.save()\n ctx.strokeStyle = strokeStyle\n ctx.lineWidth = 1.5\n ctx.setLineDash([6, 3])\n ctx.strokeRect(left + 0.75, top + 0.75, width - 1.5, height - 1.5)\n ctx.setLineDash([])\n ctx.restore()\n\n // 인벤토리 수 + capacity (있으면)\n ctx.save()\n const fontSize = Math.min(width, height) * 0.22\n ctx.fillStyle = '#333'\n ctx.font = `bold ${fontSize}px sans-serif`\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n const label = typeof this.state.capacity === 'number'\n ? `${this.inventoryCount}/${this.state.capacity}`\n : `${this.inventoryCount}`\n ctx.fillText(label, left + width / 2, top + height / 2)\n ctx.restore()\n }\n\n // ── Popup 연동 — storage-rack 동일 패턴 ───────────────────────────────\n /**\n * things-scene EventManager3D 가 raycast → object3d.userData.context.component 의\n * `trigger(\"click\", mouseEvent)` 을 호출 → eventMap 으로 receive. pad / carrier mesh\n * 어느 쪽을 클릭하든 stockpile 전체 popup invoke (단일 slot 이라 cell 구분 없음).\n */\n get eventMap() {\n return {\n '(self)': {\n '(self)': {\n click: this._onStockpileClick\n }\n }\n }\n }\n\n private _onStockpileClick = (mouseEvent: MouseEvent) => {\n // view mode 에서만 동작 (modeling 중 click 은 framework 선택 로직 우선).\n if (!(this as any).app?.isViewMode) return\n const hit = this._raycastStockpileHit(mouseEvent)\n if (!hit) return\n // hit.object 가 carrier mesh 면 userData.recordId 보유 → 그 stock 의 popup.\n // pad / 기타면 stockpile 전체 popup.\n const recordId = hit.object?.userData?.recordId as string | undefined\n this._dispatchStockpilePopup(typeof recordId === 'string' ? recordId : undefined)\n }\n\n /**\n * state.popupRef 가 가리키는 Popup 컴포넌트를 invoke.\n * - recordId 명시 → 그 record 의 anchor = mesh. payload = 해당 record.\n * - 미명시 (pad 클릭) → 'pile' anchor (pad). payload = 전체 inventory.\n *\n * RecordStorage mixin 의 `_invokePopup(slotId, payload)` 를 활용. 단일 slot\n * 시맨틱이 record/pile 두 모드라 mixin 위 wrapper 로 dispatch.\n */\n private _dispatchStockpilePopup(recordId?: string): void {\n if (!this.state.popupRef) return\n if (recordId) {\n const record = (this.records as ReadonlyArray<StockpileRecord>)\n .find(r => r.id === recordId) ?? { id: recordId }\n this._invokePopup(recordId, record)\n } else {\n this._invokePopup(SLOT_ID, {\n componentId: (this.state as any).id,\n records: this.records,\n inventoryCount: this.inventoryCount,\n capacity: this.state.capacity,\n carrierPreset: this.state.carrierPreset,\n stackPattern: this.state.stackPattern\n })\n }\n }\n\n /**\n * 클릭 시 framework 의 mouse NDC 를 재사용해 raycast → *우리 stockpile* 의 어떤 mesh 가\n * closest hit 인지 반환 (다른 object 가 더 가까우면 undefined). storage-rack._raycastRackHit\n * 와 동일 패턴 — capability.getObjectsByRaycast 우선, 없으면 scene/camera/canvas 재구성.\n */\n private _raycastStockpileHit(mouseEvent: MouseEvent): THREE.Intersection | undefined {\n const ro: any = (this as any)._realObject\n if (!ro?.object3d) return undefined\n\n const tc: any = ro.threeContainer\n if (!tc) return undefined\n\n const cap: any = tc._threeCapability ?? tc._capability\n let intersects: THREE.Intersection[] | undefined\n if (cap?.getObjectsByRaycast) {\n intersects = cap.getObjectsByRaycast() as THREE.Intersection[] | undefined\n }\n if (!intersects || intersects.length === 0) {\n const scene = tc.scene3d as THREE.Scene | undefined\n const renderer = tc.renderer3d as THREE.WebGLRenderer | undefined\n const camera =\n (tc.activeCamera3d as THREE.Camera | undefined) ??\n (cap?.activeCamera as THREE.Camera | undefined) ??\n (cap?.camera as THREE.Camera | undefined)\n const canvas = renderer?.domElement\n if (!scene || !canvas || !camera) return undefined\n const rect = canvas.getBoundingClientRect()\n if (rect.width === 0 || rect.height === 0) return undefined\n const ndc = new THREE.Vector2(\n ((mouseEvent.clientX - rect.left) / rect.width) * 2 - 1,\n -((mouseEvent.clientY - rect.top) / rect.height) * 2 + 1\n )\n const raycaster = new THREE.Raycaster()\n raycaster.setFromCamera(ndc, camera)\n intersects = raycaster.intersectObjects(scene.children, true)\n }\n if (!intersects || intersects.length === 0) return undefined\n\n // 가장 가까운 hit 이 *이 stockpile* 의 descendant 여야 한다 (다른 mesh 가 사이에 있으면 skip).\n const closest = intersects[0]\n let obj: THREE.Object3D | null = closest.object\n while (obj) {\n if (obj.userData?.context === ro) return closest\n obj = obj.parent\n }\n return undefined\n }\n\n // legendTarget / _onLegendChanged / resolveLegendColor — RecordStorage mixin 제공.\n\n buildRealObject(): RealObject | undefined {\n return new Stockpile3D(this)\n }\n}\n\n// transient carrier refid — scene 내 기존 컴포넌트와 충돌 회피용 큰 시작값\n// (storage-rack 의 _nextCarrierRefid 와 같은 idiom, 별도 범위로 분리).\nlet _stockpileCarrierSeq = 0\nfunction _nextStockpileCarrierRefid(): number {\n return 800000 + (_stockpileCarrierSeq++)\n}\n\nfunction resolveDepth(c: Component): number {\n const eff = (c as any)._realObject?.effectiveDepth\n if (typeof eff === 'number' && Number.isFinite(eff)) return eff\n const d = (c as any)?.state?.depth\n return typeof d === 'number' && Number.isFinite(d) ? d : 0\n}\n"]}
|
|
1
|
+
{"version":3,"file":"stockpile.js","sourceRoot":"","sources":["../src/stockpile.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * Stockpile — 평치(block/floor) 보관 영역. 사각형 footprint + `state.data` 의 record[].\n * 실제 carrier component 를 자식으로 두지 않고, 인벤토리(records)의 *_개수와 종류_* 만으로\n * 가상 carrier mesh 를 자동 적치(stackPattern × carrierPreset)해 시각화한다.\n *\n * 데이터 idiom — StorageRack 과 동일 (`state.data: Record[]`). mover 가 pick/place 하면\n * record push/pop, _realObject 가 records.length 기준 mesh 를 재배치.\n *\n * 1단계 — 시각화: 모델에 `data: [{id:'a'},{id:'b'},...]` 가 들어오면 mesh 가 자동 적치.\n * 2단계(추후) — mover 통합: obtainCarrier 가 transient carrier 컴포넌트 materialize,\n * receiveAt 가 record push + carrier dispose.\n */\n\nimport * as THREE from 'three'\nimport { Component, ComponentNature, ContainerAbstract, RealObject, sceneComponent } from '@hatiolab/things-scene'\nimport type { State, Material3D } from '@hatiolab/things-scene'\nimport {\n CarrierHolder,\n Placeable,\n RecordStorage,\n SlotTarget,\n type AttachFrame,\n type Alignment,\n type Heights,\n type PlacementArchetype,\n type SlottedHolder\n} from '@operato/scene-base'\n\nimport { Stockpile3D } from './stockpile-3d.js'\n\nexport type StackPattern = 'row' | 'staggered' | 'pyramid' | 'column' | 'pile'\nexport type CarrierPreset = 'box' | 'pallet' | 'drum' | 'sack' | 'crate' | 'bale'\nexport type PickPolicy = 'lifo' | 'fifo'\n\n/** 적치된 carrier 의 record. 향후 sku / weight / 입고시각 등 확장. */\nexport interface StockpileRecord {\n id: string\n [key: string]: any\n}\n\nexport interface StockpileState extends State {\n /** 적치 carrier 의 record 목록 — storage-rack 의 state.data 와 동일 idiom. */\n data?: StockpileRecord[]\n\n /** 적치 형태 프리셋. default 'row'. */\n stackPattern?: StackPattern\n /** 가상 carrier 종류 프리셋. default 'box'. */\n carrierPreset?: CarrierPreset\n\n /** 가상 carrier 한 개의 크기 (없으면 preset 별 기본). */\n carrierWidth?: number\n carrierHeight?: number\n carrierDepth?: number\n /** 적치된 carrier 사이의 평면(xz) 간격 — 0 이면 딱 붙음, default 3. y(단 적층)는 항상 딱 붙음. */\n carrierGap?: number\n\n /** 최대 적치 수 (undefined = 무제한). */\n capacity?: number\n /** 위로 몇 단까지 (undefined = stack 형태에 맡김). */\n stackHeightLimit?: number\n /** 어느 끝에서 빼나. default 'lifo'. */\n pickPolicy?: PickPolicy\n\n /** click 시 invoke 할 Popup 컴포넌트 id (StorageRack / RackGrid 와 동일 패턴). */\n popupRef?: string\n\n /**\n * Legend 컴포넌트 id. legend 의 `state.status = {field, ranges, defaultColor}` 를\n * 참조해 각 record 의 field 값을 색상으로 매핑한다 (StorageRack 와 동일 패턴).\n * 미명시 시 scene 안 `type='legend'` 첫 컴포넌트 자동 발견.\n */\n legendTarget?: string\n\n material3d?: Material3D\n}\n\nconst SLOT_ID = 'pile'\n\nconst NATURE: ComponentNature = {\n mutable: false,\n resizable: true,\n rotatable: true,\n properties: [\n { type: 'select', label: 'stack-pattern', name: 'stackPattern',\n property: { options: ['row', 'staggered', 'pyramid', 'column', 'pile'] } },\n { type: 'select', label: 'carrier-preset', name: 'carrierPreset',\n property: { options: ['box', 'pallet', 'drum', 'sack', 'crate', 'bale'] } },\n { type: 'number', label: 'carrier-width', name: 'carrierWidth' },\n { type: 'number', label: 'carrier-height', name: 'carrierHeight' },\n { type: 'number', label: 'carrier-depth', name: 'carrierDepth' },\n { type: 'number', label: 'carrier-gap', name: 'carrierGap' },\n { type: 'number', label: 'capacity', name: 'capacity' },\n { type: 'number', label: 'stack-height-limit', name: 'stackHeightLimit' },\n { type: 'select', label: 'pick-policy', name: 'pickPolicy',\n property: { options: ['lifo', 'fifo'] } },\n { type: 'id-input', label: 'popup-ref', name: 'popupRef',\n property: { component: 'popup' } },\n { type: 'id-input', label: 'legend-target', name: 'legendTarget',\n property: { component: 'legend' },\n placeholder: '미명시 시 scene 의 legend 자동 발견' }\n ],\n help: 'scene/component/stockpile'\n}\n\n@sceneComponent('stockpile')\nexport default class Stockpile extends RecordStorage<StockpileRecord>()(\n CarrierHolder(Placeable(ContainerAbstract))\n) implements SlottedHolder {\n declare state: StockpileState\n declare _realObject?: Stockpile3D\n\n static placement: PlacementArchetype = 'floor'\n static align: Alignment = 'bottom'\n static defaultDepth = (_h: Heights) => 5 // pad 두께\n\n get nature(): ComponentNature { return NATURE }\n get anchors() { return [] }\n\n // ── records / inventoryCount: RecordStorage mixin 제공.\n\n // ── SlottedHolder duck-type override — 단일 slot ('pile') ───────────────\n // mixin default 는 record 마다 slotId. Stockpile 은 *_단일 슬롯_* 시맨틱이라\n // 자기 구현 유지.\n slotIds(): ReadonlyArray<string> { return [SLOT_ID] }\n\n hasCarrierAt(slotId: string): boolean {\n return slotId === SLOT_ID && this.inventoryCount > 0\n }\n\n canReceiveAt(slotId: string, _carrier?: Component): boolean {\n if (slotId !== SLOT_ID) return false\n const cap = this.state.capacity\n if (typeof cap === 'number' && this.inventoryCount >= cap) return false\n return true\n }\n\n occupiedSlotIds(): ReadonlyArray<string> {\n return this.inventoryCount > 0 ? [SLOT_ID] : []\n }\n emptySlotIds(): ReadonlyArray<string> {\n return this.canReceiveAt(SLOT_ID) ? [SLOT_ID] : []\n }\n\n /**\n * record 한 개를 빼서 carrier 컴포넌트로 transient materialize. mover 가 pickup\n * 하면 이걸 reparent 해서 들고 다닌다. storage-rack._materializeCarrier 와 동일\n * 패턴 — Component.register(type) 으로 클래스 lookup, addComponent({silent: true})\n * 로 cascade 차단.\n */\n obtainCarrier(slotId: string): Component | null {\n if (slotId !== SLOT_ID) return null\n if (this.records.length === 0) return null\n const records = [...this.records]\n const policy = (this.state.pickPolicy ?? 'lifo') as PickPolicy\n const record = policy === 'fifo' ? records.shift()! : records.pop()!\n this._setDataSilently(records)\n return this._materializeCarrier(record)\n }\n\n private _materializeCarrier(record: StockpileRecord): Component | null {\n // carrierPreset → 등록된 컴포넌트 type. 미등록(drum/sack/bale 등) 은 시각 mesh\n // 전용이라 carrier 컴포넌트로는 fallback ('parcel'/'box').\n const preset = (this.state.carrierPreset ?? 'box') as CarrierPreset\n const PRESET_TO_TYPE: Record<CarrierPreset, string> = {\n box: 'box',\n pallet: 'pallet',\n crate: 'box',\n drum: 'parcel',\n sack: 'parcel',\n bale: 'parcel'\n }\n const carrierType = (record as any).type ?? PRESET_TO_TYPE[preset] ?? 'parcel'\n const CarrierClass = (Component as any).register(carrierType) as\n | (new (...args: any[]) => Component) | undefined\n if (!CarrierClass) {\n console.warn(`[stockpile] carrier type \"${carrierType}\" 미등록 — obtainCarrier 실패`)\n return null\n }\n\n // 크기 — state.carrier* 또는 preset default\n const stockpileW = (this.state as any).width ?? 100\n const stockpileH = (this.state as any).height ?? 100\n const cw = this.state.carrierWidth ?? 30\n const ch = this.state.carrierHeight ?? 30\n const cd = this.state.carrierDepth ?? 22\n\n // id/refid/transform 류 제외 — scene 안 기존 component 충돌 회피 (storage-rack 패턴)\n const { id: _id, refid: _refid, transform: _tf, ...recordCopy } = record as any\n // stockpile-inner 좌표 — center 에 놓기 (Mover 가 곧 pick 해 들고 감)\n const carrierState: any = {\n ...recordCopy,\n type: carrierType,\n width: cw,\n height: ch,\n depth: cd,\n refid: _nextStockpileCarrierRefid(),\n left: stockpileW / 2 - cw / 2,\n top: stockpileH / 2 - ch / 2\n }\n\n const carrier = new CarrierClass(carrierState, (this as any)._app)\n // silent: refreshMappings cascade 차단 (transient 라 매핑 재계산 불필요)\n ;(this as any).addComponent(carrier, { silent: true })\n void (carrier as any).realObject\n ;(carrier as any).applyHolderAttachPoint?.()\n return carrier\n }\n\n /**\n * carrier 의 state → StockpileRecord 추출. id 누락 시 `stk-` prefix 자동 생성.\n * transform/refid 등 *_물리적 위치 필드_* 는 *_제외_* — record 는 *_논리적 식별_*\n * 만. SlottedHolder duck 의 표준 entry point — receiveAt 안에서 호출.\n */\n recordFromCarrier(carrier: Component, _slotId: string): StockpileRecord {\n const cstate: any = (carrier as any)?.state ?? {}\n const cid = cstate.id ?? `stk-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`\n return {\n id: String(cid),\n ...(cstate.type ? { type: cstate.type } : {}),\n ...(typeof cstate.width === 'number' ? { width: cstate.width } : {}),\n ...(typeof cstate.height === 'number' ? { height: cstate.height } : {}),\n ...(typeof cstate.depth === 'number' ? { depth: cstate.depth } : {})\n }\n }\n\n /**\n * carrier 를 받아 record 로 push, carrier 객체는 dispose (시각은 _realObject 가\n * records 길이 기준 자동 갱신). capacity 초과 시도는 canReceiveAt 가 이미 차단.\n */\n async receiveAt(slotId: string, carrier: Component, _options?: any): Promise<void> {\n const record = this.recordFromCarrier(carrier, slotId)\n const records = [...this.records, record]\n this._setDataSilently(records)\n ;(carrier as any)?.dispose?.()\n }\n\n /** dispatch → handoff 의 accept 분기 — receiveAt 으로 위임. */\n async accept(carrier: Component, options?: any): Promise<void> {\n return this.receiveAt(SLOT_ID, carrier, options)\n }\n async receive(carrier: Component, options?: any): Promise<void> {\n return this.receiveAt(SLOT_ID, carrier, options)\n }\n\n /**\n * mover 가 obtainCarrier 로 빼낸 transient carrier 를 pad 위에 안착 (잠깐 보이는\n * 위치). mover 가 pick 하면 즉시 deck 으로 reparent 되므로 잔류는 짧다.\n * Spot 과 동일 idiom — pad-top + carrier 의 halfDepth 만큼 들어올림.\n */\n attachPointFor(carrier: Component): AttachFrame | null {\n const ro = this._realObject\n const frame = ro?.getAttachFrame?.()\n if (!frame) return null\n const carrierDepth = resolveDepth(carrier)\n return {\n attach: frame,\n localPosition: { x: 0, y: carrierDepth / 2, z: 0 }\n }\n }\n\n slotTargetAt(slotId: string): SlotTarget {\n return new SlotTarget(this as any, slotId)\n }\n getSlotAttachObject3d(slotId: string): any {\n // slotId 가 'pile' 이면 pad. record.id 면 그 carrier mesh — popup tether 가 그\n // stock 에 정확히 연결되도록.\n return (this as any)._realObject?.getAttachFrame?.(slotId)\n }\n\n // _setDataSilently 는 RecordStorage mixin 제공 — 다만 mixin 은 _rebuildVisual\n // 호출. Stockpile 의 3D 갱신은 update() 라서 hook override.\n _rebuildVisual(): void {\n this._realObject?.update?.()\n }\n\n /**\n * 2D — outlined pad + 인벤토리 카운트 텍스트. 평치 의도가 한 눈에 — 사각 영역 위에\n * 적재된 carrier 수가 가운데 큰 글씨로.\n */\n render(ctx: CanvasRenderingContext2D) {\n const { left = 0, top = 0, width = 100, height = 100 } = this.state\n const fillStyle = (this.state.fillStyle as string) || '#c89c5c'\n const strokeStyle = (this.state.strokeStyle as string) || fillStyle\n\n // pad (반투명)\n ctx.save()\n ctx.fillStyle = fillStyle\n ctx.globalAlpha = 0.18\n ctx.fillRect(left, top, width, height)\n ctx.restore()\n\n // outline (dashed)\n ctx.save()\n ctx.strokeStyle = strokeStyle\n ctx.lineWidth = 1.5\n ctx.setLineDash([6, 3])\n ctx.strokeRect(left + 0.75, top + 0.75, width - 1.5, height - 1.5)\n ctx.setLineDash([])\n ctx.restore()\n\n // 인벤토리 수 + capacity (있으면)\n ctx.save()\n const fontSize = Math.min(width, height) * 0.22\n ctx.fillStyle = '#333'\n ctx.font = `bold ${fontSize}px sans-serif`\n ctx.textAlign = 'center'\n ctx.textBaseline = 'middle'\n const label = typeof this.state.capacity === 'number'\n ? `${this.inventoryCount}/${this.state.capacity}`\n : `${this.inventoryCount}`\n ctx.fillText(label, left + width / 2, top + height / 2)\n ctx.restore()\n }\n\n // ── Popup 연동 — storage-rack 동일 패턴 ───────────────────────────────\n /**\n * things-scene EventManager3D 가 raycast → object3d.userData.context.component 의\n * `trigger(\"click\", mouseEvent)` 을 호출 → eventMap 으로 receive. pad / carrier mesh\n * 어느 쪽을 클릭하든 stockpile 전체 popup invoke (단일 slot 이라 cell 구분 없음).\n */\n get eventMap() {\n return {\n '(self)': {\n '(self)': {\n click: this._onStockpileClick\n }\n }\n }\n }\n\n private _onStockpileClick = (mouseEvent: MouseEvent) => {\n // view mode 에서만 동작 (modeling 중 click 은 framework 선택 로직 우선).\n if (!(this as any).app?.isViewMode) return\n const hit = this._raycastStockpileHit(mouseEvent)\n if (!hit) return\n // hit.object 가 carrier mesh 면 userData.recordId 보유 → 그 stock 의 popup.\n // pad / 기타면 stockpile 전체 popup.\n const recordId = hit.object?.userData?.recordId as string | undefined\n this._dispatchStockpilePopup(typeof recordId === 'string' ? recordId : undefined)\n }\n\n /**\n * state.popupRef 가 가리키는 Popup 컴포넌트를 invoke.\n * - recordId 명시 → 그 record 의 anchor = mesh. payload = 해당 record.\n * - 미명시 (pad 클릭) → 'pile' anchor (pad). payload = 전체 inventory.\n *\n * RecordStorage mixin 의 `_invokePopup(slotId, payload)` 를 활용. 단일 slot\n * 시맨틱이 record/pile 두 모드라 mixin 위 wrapper 로 dispatch.\n */\n private _dispatchStockpilePopup(recordId?: string): void {\n if (!this.state.popupRef) return\n if (recordId) {\n const record = (this.records as ReadonlyArray<StockpileRecord>)\n .find(r => r.id === recordId) ?? { id: recordId }\n this._invokePopup(recordId, record)\n } else {\n this._invokePopup(SLOT_ID, {\n componentId: (this.state as any).id,\n records: this.records,\n inventoryCount: this.inventoryCount,\n capacity: this.state.capacity,\n carrierPreset: this.state.carrierPreset,\n stackPattern: this.state.stackPattern\n })\n }\n }\n\n /**\n * 클릭 시 framework 의 mouse NDC 를 재사용해 raycast → *우리 stockpile* 의 어떤 mesh 가\n * closest hit 인지 반환 (다른 object 가 더 가까우면 undefined). storage-rack._raycastRackHit\n * 와 동일 패턴 — capability.getObjectsByRaycast 우선, 없으면 scene/camera/canvas 재구성.\n */\n private _raycastStockpileHit(mouseEvent: MouseEvent): THREE.Intersection | undefined {\n const ro: any = (this as any)._realObject\n if (!ro?.object3d) return undefined\n\n const tc: any = ro.threeContainer\n if (!tc) return undefined\n\n const cap: any = tc._threeCapability ?? tc._capability\n let intersects: THREE.Intersection[] | undefined\n if (cap?.getObjectsByRaycast) {\n intersects = cap.getObjectsByRaycast() as THREE.Intersection[] | undefined\n }\n if (!intersects || intersects.length === 0) {\n const scene = tc.scene3d as THREE.Scene | undefined\n const renderer = tc.renderer3d as THREE.WebGLRenderer | undefined\n const camera =\n (tc.activeCamera3d as THREE.Camera | undefined) ??\n (cap?.activeCamera as THREE.Camera | undefined) ??\n (cap?.camera as THREE.Camera | undefined)\n const canvas = renderer?.domElement\n if (!scene || !canvas || !camera) return undefined\n const rect = canvas.getBoundingClientRect()\n if (rect.width === 0 || rect.height === 0) return undefined\n const ndc = new THREE.Vector2(\n ((mouseEvent.clientX - rect.left) / rect.width) * 2 - 1,\n -((mouseEvent.clientY - rect.top) / rect.height) * 2 + 1\n )\n const raycaster = new THREE.Raycaster()\n raycaster.setFromCamera(ndc, camera)\n intersects = raycaster.intersectObjects(scene.children, true)\n }\n if (!intersects || intersects.length === 0) return undefined\n\n // 가장 가까운 hit 이 *이 stockpile* 의 descendant 여야 한다 (다른 mesh 가 사이에 있으면 skip).\n const closest = intersects[0]\n let obj: THREE.Object3D | null = closest.object\n while (obj) {\n if (obj.userData?.context === ro) return closest\n obj = obj.parent\n }\n return undefined\n }\n\n // legendTarget / _onLegendChanged / resolveLegendColor — RecordStorage mixin 제공.\n\n buildRealObject(): RealObject | undefined {\n return new Stockpile3D(this)\n }\n}\n\n// transient carrier refid — scene 내 기존 컴포넌트와 충돌 회피용 큰 시작값\n// (storage-rack 의 _nextCarrierRefid 와 같은 idiom, 별도 범위로 분리).\nlet _stockpileCarrierSeq = 0\nfunction _nextStockpileCarrierRefid(): number {\n return 800000 + (_stockpileCarrierSeq++)\n}\n\nfunction resolveDepth(c: Component): number {\n const eff = (c as any)._realObject?.effectiveDepth\n if (typeof eff === 'number' && Number.isFinite(eff)) return eff\n const d = (c as any)?.state?.depth\n return typeof d === 'number' && Number.isFinite(d) ? d : 0\n}\n"]}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@operato/scene-storage",
|
|
3
3
|
"description": "Storage-domain components for things-scene (smart factory / logistics) — pallet, box, parcel; AS/RS and shelves planned.",
|
|
4
4
|
"author": "heartyoh",
|
|
5
|
-
"version": "10.0.0-beta.
|
|
5
|
+
"version": "10.0.0-beta.56",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"module": "dist/index.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@hatiolab/things-scene": "^10.0.0-beta.1",
|
|
29
|
-
"@operato/scene-base": "^10.0.0-beta.
|
|
29
|
+
"@operato/scene-base": "^10.0.0-beta.56",
|
|
30
30
|
"three": "^0.183.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
@@ -45,5 +45,5 @@
|
|
|
45
45
|
"typescript": "^5.0.4"
|
|
46
46
|
},
|
|
47
47
|
"prettier": "@hatiolab/prettier-config",
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "0f2063b2545025837fa21ef15bfb47e7b4a07f1d"
|
|
49
49
|
}
|
package/src/stockpile-grid.ts
CHANGED
|
@@ -27,7 +27,8 @@ import {
|
|
|
27
27
|
type AttachFrame,
|
|
28
28
|
type Alignment,
|
|
29
29
|
type Heights,
|
|
30
|
-
type PlacementArchetype
|
|
30
|
+
type PlacementArchetype,
|
|
31
|
+
type SlottedHolder
|
|
31
32
|
} from '@operato/scene-base'
|
|
32
33
|
|
|
33
34
|
import { StockpileGrid3D } from './stockpile-grid-3d.js'
|
|
@@ -99,7 +100,7 @@ const NATURE: ComponentNature = {
|
|
|
99
100
|
@sceneComponent('stockpile-grid')
|
|
100
101
|
export default class StockpileGrid extends RecordStorage<StockpileGridCell>()(
|
|
101
102
|
CarrierHolder(Placeable(ContainerAbstract))
|
|
102
|
-
) {
|
|
103
|
+
) implements SlottedHolder {
|
|
103
104
|
declare state: StockpileGridState
|
|
104
105
|
declare _realObject?: StockpileGrid3D
|
|
105
106
|
|
|
@@ -192,18 +193,28 @@ export default class StockpileGrid extends RecordStorage<StockpileGridCell>()(
|
|
|
192
193
|
return this._materializeCarrier(record, p.col, p.row)
|
|
193
194
|
}
|
|
194
195
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
196
|
+
/**
|
|
197
|
+
* carrier → StockpileRecord 추출. id 누락 시 `stkg-` prefix 자동 생성.
|
|
198
|
+
* SlottedHolder duck 의 표준 entry — receiveAt 안에서 호출. cell 정보 (col/row) 는
|
|
199
|
+
* slotId 의 parseCellId 로 receiveAt 가 처리 — record 자체에는 cell 좌표 미포함
|
|
200
|
+
* (cell array 가 그 컨텍스트 보유).
|
|
201
|
+
*/
|
|
202
|
+
recordFromCarrier(carrier: Component, _slotId: string): StockpileRecord {
|
|
198
203
|
const cstate: any = (carrier as any)?.state ?? {}
|
|
199
204
|
const cid = cstate.id ?? `stkg-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`
|
|
200
|
-
|
|
205
|
+
return {
|
|
201
206
|
id: String(cid),
|
|
202
207
|
...(cstate.type ? { type: cstate.type } : {}),
|
|
203
208
|
...(typeof cstate.width === 'number' ? { width: cstate.width } : {}),
|
|
204
209
|
...(typeof cstate.height === 'number' ? { height: cstate.height } : {}),
|
|
205
210
|
...(typeof cstate.depth === 'number' ? { depth: cstate.depth } : {})
|
|
206
211
|
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async receiveAt(slotId: string, carrier: Component, _options?: any): Promise<void> {
|
|
215
|
+
const p = this.parseCellId(slotId)
|
|
216
|
+
if (!p) return
|
|
217
|
+
const record = this.recordFromCarrier(carrier, slotId)
|
|
207
218
|
const records = [...this.recordsOf(p.col, p.row), record]
|
|
208
219
|
this._setCellRecords(p.col, p.row, records)
|
|
209
220
|
;(carrier as any)?.dispose?.()
|
package/src/stockpile.ts
CHANGED
|
@@ -24,7 +24,8 @@ import {
|
|
|
24
24
|
type AttachFrame,
|
|
25
25
|
type Alignment,
|
|
26
26
|
type Heights,
|
|
27
|
-
type PlacementArchetype
|
|
27
|
+
type PlacementArchetype,
|
|
28
|
+
type SlottedHolder
|
|
28
29
|
} from '@operato/scene-base'
|
|
29
30
|
|
|
30
31
|
import { Stockpile3D } from './stockpile-3d.js'
|
|
@@ -106,7 +107,7 @@ const NATURE: ComponentNature = {
|
|
|
106
107
|
@sceneComponent('stockpile')
|
|
107
108
|
export default class Stockpile extends RecordStorage<StockpileRecord>()(
|
|
108
109
|
CarrierHolder(Placeable(ContainerAbstract))
|
|
109
|
-
) {
|
|
110
|
+
) implements SlottedHolder {
|
|
110
111
|
declare state: StockpileState
|
|
111
112
|
declare _realObject?: Stockpile3D
|
|
112
113
|
|
|
@@ -208,19 +209,28 @@ export default class Stockpile extends RecordStorage<StockpileRecord>()(
|
|
|
208
209
|
}
|
|
209
210
|
|
|
210
211
|
/**
|
|
211
|
-
* carrier
|
|
212
|
-
*
|
|
212
|
+
* carrier 의 state → StockpileRecord 추출. id 누락 시 `stk-` prefix 자동 생성.
|
|
213
|
+
* transform/refid 등 *_물리적 위치 필드_* 는 *_제외_* — record 는 *_논리적 식별_*
|
|
214
|
+
* 만. SlottedHolder duck 의 표준 entry point — receiveAt 안에서 호출.
|
|
213
215
|
*/
|
|
214
|
-
|
|
216
|
+
recordFromCarrier(carrier: Component, _slotId: string): StockpileRecord {
|
|
215
217
|
const cstate: any = (carrier as any)?.state ?? {}
|
|
216
218
|
const cid = cstate.id ?? `stk-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 6)}`
|
|
217
|
-
|
|
219
|
+
return {
|
|
218
220
|
id: String(cid),
|
|
219
221
|
...(cstate.type ? { type: cstate.type } : {}),
|
|
220
222
|
...(typeof cstate.width === 'number' ? { width: cstate.width } : {}),
|
|
221
223
|
...(typeof cstate.height === 'number' ? { height: cstate.height } : {}),
|
|
222
224
|
...(typeof cstate.depth === 'number' ? { depth: cstate.depth } : {})
|
|
223
225
|
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* carrier 를 받아 record 로 push, carrier 객체는 dispose (시각은 _realObject 가
|
|
230
|
+
* records 길이 기준 자동 갱신). capacity 초과 시도는 canReceiveAt 가 이미 차단.
|
|
231
|
+
*/
|
|
232
|
+
async receiveAt(slotId: string, carrier: Component, _options?: any): Promise<void> {
|
|
233
|
+
const record = this.recordFromCarrier(carrier, slotId)
|
|
224
234
|
const records = [...this.records, record]
|
|
225
235
|
this._setDataSilently(records)
|
|
226
236
|
;(carrier as any)?.dispose?.()
|