@operato/scene-storage 10.0.0-beta.47 → 10.0.0-beta.50

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 (68) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/index.d.ts +9 -0
  3. package/dist/index.js +6 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/picking-station-3d.d.ts +20 -0
  6. package/dist/picking-station-3d.js +162 -0
  7. package/dist/picking-station-3d.js.map +1 -0
  8. package/dist/picking-station.d.ts +56 -0
  9. package/dist/picking-station.js +212 -0
  10. package/dist/picking-station.js.map +1 -0
  11. package/dist/rack-capability.d.ts +11 -0
  12. package/dist/rack-capability.js +25 -0
  13. package/dist/rack-capability.js.map +1 -0
  14. package/dist/rack-grid.js +3 -10
  15. package/dist/rack-grid.js.map +1 -1
  16. package/dist/spot.d.ts +19 -1
  17. package/dist/spot.js +63 -1
  18. package/dist/spot.js.map +1 -1
  19. package/dist/stockpile-3d.d.ts +55 -0
  20. package/dist/stockpile-3d.js +387 -0
  21. package/dist/stockpile-3d.js.map +1 -0
  22. package/dist/stockpile-grid-3d.d.ts +30 -0
  23. package/dist/stockpile-grid-3d.js +301 -0
  24. package/dist/stockpile-grid-3d.js.map +1 -0
  25. package/dist/stockpile-grid.d.ts +88 -0
  26. package/dist/stockpile-grid.js +429 -0
  27. package/dist/stockpile-grid.js.map +1 -0
  28. package/dist/stockpile.d.ts +133 -0
  29. package/dist/stockpile.js +439 -0
  30. package/dist/stockpile.js.map +1 -0
  31. package/dist/storage-rack.d.ts +12 -0
  32. package/dist/storage-rack.js +20 -10
  33. package/dist/storage-rack.js.map +1 -1
  34. package/dist/templates/index.d.ts +80 -0
  35. package/dist/templates/index.js +7 -1
  36. package/dist/templates/index.js.map +1 -1
  37. package/dist/templates/picking-station.d.ts +20 -0
  38. package/dist/templates/picking-station.js +22 -0
  39. package/dist/templates/picking-station.js.map +1 -0
  40. package/dist/templates/stockpile-grid.d.ts +37 -0
  41. package/dist/templates/stockpile-grid.js +38 -0
  42. package/dist/templates/stockpile-grid.js.map +1 -0
  43. package/dist/templates/stockpile.d.ts +29 -0
  44. package/dist/templates/stockpile.js +31 -0
  45. package/dist/templates/stockpile.js.map +1 -0
  46. package/package.json +3 -3
  47. package/src/index.ts +14 -0
  48. package/src/picking-station-3d.ts +164 -0
  49. package/src/picking-station.ts +243 -0
  50. package/src/rack-capability.ts +26 -0
  51. package/src/rack-grid.ts +3 -8
  52. package/src/spot.ts +62 -0
  53. package/src/stockpile-3d.ts +412 -0
  54. package/src/stockpile-grid-3d.ts +327 -0
  55. package/src/stockpile-grid.ts +456 -0
  56. package/src/stockpile.ts +508 -0
  57. package/src/storage-rack.ts +21 -8
  58. package/src/templates/index.ts +7 -1
  59. package/src/templates/picking-station.ts +23 -0
  60. package/src/templates/stockpile-grid.ts +39 -0
  61. package/src/templates/stockpile.ts +32 -0
  62. package/test/test-rack-capability.ts +51 -0
  63. package/translations/en.json +18 -6
  64. package/translations/ja.json +18 -6
  65. package/translations/ko.json +17 -5
  66. package/translations/ms.json +18 -6
  67. package/translations/zh.json +17 -5
  68. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stockpile-3d.js","sourceRoot":"","sources":["../src/stockpile-3d.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * Stockpile3D — 평치 영역의 3D 시각화.\n *\n * - floor pad (얇은 box, 영역 footprint).\n * - records.length 만큼 가상 carrier mesh 를 *_stackPattern_* 으로 자동 배치.\n * - mesh geometry / material 은 *_carrierPreset_* 별.\n *\n * 핵심 — 실제 carrier 컴포넌트를 자식으로 두지 않고 *_가상 mesh_* 만 그려서 다수\n * 적치를 가볍게 표현. records 변경 시 update() 가 호출되어 mesh 가 재배치된다.\n */\n\nimport * as THREE from 'three'\nimport { RealObjectGroup } from '@hatiolab/things-scene'\n\nimport type Stockpile from './stockpile.js'\nimport type { StackPattern, CarrierPreset } from './stockpile.js'\n\nconst PAD_DEPTH = 2\n\n/** carrierPreset 별 default 색 (state.carrierWidth/Height/Depth 미지정 시 크기와 함께). */\nconst PRESET_COLOR: Record<CarrierPreset, number> = {\n box: 0xb87333, // kraft brown\n pallet: 0x8b6f47, // 짙은 나무\n drum: 0x556679, // 금속/blue-grey\n sack: 0xd4c89a, // beige 천\n crate: 0x9a7548, // 나무 상자\n bale: 0xa89968 // 압축 베일\n}\n\nconst PRESET_DEFAULT_SIZE: Record<CarrierPreset, { w: number; h: number; d: number }> = {\n box: { w: 26, h: 26, d: 20 },\n pallet: { w: 40, h: 30, d: 15 },\n drum: { w: 24, h: 24, d: 30 },\n sack: { w: 30, h: 28, d: 18 },\n crate: { w: 30, h: 30, d: 22 },\n bale: { w: 32, h: 30, d: 18 }\n}\n\nexport class Stockpile3D extends RealObjectGroup {\n private _carriersGroup?: THREE.Group\n private _padMesh?: THREE.Mesh\n /** pad 의 외곽선 — strokeStyle 표현 (2D dashed outline 의 3D 대응). */\n private _padOutline?: THREE.LineSegments\n /** record.id → 해당 carrier mesh 매핑 — popup anchor / tether 의 대상으로 사용. */\n private _meshByRecordId: Map<string, THREE.Mesh> = new Map()\n /** Legend 매핑된 색을 material 로 캐시 — 같은 색 record 들은 material 공유 (drawcall ↓). */\n private _materialByColor: Map<number, THREE.MeshStandardMaterial> = new Map()\n\n private _getMaterialForColor(colorHex: number): THREE.MeshStandardMaterial {\n let m = this._materialByColor.get(colorHex)\n if (!m) {\n m = new THREE.MeshStandardMaterial({ color: colorHex, roughness: 0.7 })\n this._materialByColor.set(colorHex, m)\n }\n return m\n }\n\n private _disposeMaterialCache(): void {\n for (const m of this._materialByColor.values()) m.dispose()\n this._materialByColor.clear()\n }\n\n build() {\n super.build()\n const state = this.component.state as any\n const w = state.width ?? 100\n const h = state.height ?? 100\n\n // ── floor pad — 영역 표시 (얇은 box) ──────────────────────────────\n const padGeom = new THREE.BoxGeometry(w, PAD_DEPTH, h)\n const padColor = this._padColor()\n const padMat = new THREE.MeshStandardMaterial({\n color: padColor, roughness: 0.85, transparent: true, opacity: 0.55,\n emissive: padColor, emissiveIntensity: 0.05\n })\n this._padMesh = new THREE.Mesh(padGeom, padMat)\n this._padMesh.position.y = PAD_DEPTH / 2\n this._padMesh.receiveShadow = true\n this.object3d.add(this._padMesh)\n\n // pad 외곽선 — strokeStyle 3D 표현. 2D 의 dashed outline 과 같은 의도.\n const outlineColor = this._strokeColor()\n const outlineMat = new THREE.LineBasicMaterial({ color: outlineColor })\n this._padOutline = new THREE.LineSegments(new THREE.EdgesGeometry(padGeom), outlineMat)\n this._padOutline.position.y = PAD_DEPTH / 2\n this.object3d.add(this._padOutline)\n\n // ── carriers group — records 기반 자동 적치 ─────────────────────\n this._carriersGroup = new THREE.Group()\n this._carriersGroup.position.y = PAD_DEPTH\n this.object3d.add(this._carriersGroup)\n this._rebuildCarriers()\n }\n\n update() {\n super.update()\n this._rebuildCarriers()\n }\n\n /**\n * carrier attach point.\n * - slotId 가 record.id 와 매칭되면 그 record 의 mesh 반환 → popup tether 가 정확히\n * 해당 stock 에 연결.\n * - 아니면 pad 반환 (단일 'pile' slot, mover place 의 default anchor).\n */\n getAttachFrame(slotId?: string): THREE.Object3D | undefined {\n if (slotId) {\n const mesh = this._meshByRecordId.get(slotId)\n if (mesh) return mesh\n }\n return this._padMesh\n }\n\n /** state.fillStyle → THREE.Color. 잘못된 값/없으면 default. capacity 점유율에 따른\n * 색 변경은 강요하지 않음 — 필요하면 사용자가 mapping(eval)으로 fillStyle 을 조정. */\n private _padColor(): THREE.Color {\n const raw = (this.component.state as any)?.fillStyle\n if (typeof raw === 'string' && raw.length > 0) {\n try { return new THREE.Color(raw) } catch { /* fallthrough */ }\n }\n return new THREE.Color(0xc89c5c)\n }\n\n /** state.strokeStyle → THREE.Color (pad 외곽선 색). 미설정 시 fillStyle 따라가되\n * 대비 위해 약간 어둡게 */\n private _strokeColor(): THREE.Color {\n const raw = (this.component.state as any)?.strokeStyle\n if (typeof raw === 'string' && raw.length > 0) {\n try { return new THREE.Color(raw) } catch { /* fallthrough */ }\n }\n return this._padColor().clone().multiplyScalar(0.6)\n }\n\n private _applyStrokeColor(): void {\n if (!this._padOutline) return\n const m = this._padOutline.material as THREE.LineBasicMaterial\n m.color.copy(this._strokeColor())\n m.needsUpdate = true\n }\n\n /** state.fillStyle 변경 즉시 반영 — pad material 의 color + emissive 갱신. */\n private _applyPadColor(): void {\n if (!this._padMesh) return\n const m = this._padMesh.material as THREE.MeshStandardMaterial\n const c = this._padColor()\n m.color.copy(c)\n m.emissive.copy(c)\n m.needsUpdate = true\n }\n\n private _rebuildCarriers(): void {\n const g = this._carriersGroup\n if (!g) return\n // 기존 mesh 모두 제거 (geometry/material 은 공유돼 dispose 안 함)\n while (g.children.length > 0) g.remove(g.children[0])\n\n const stockpile = this.component as unknown as Stockpile\n const count = stockpile.records.length\n if (count === 0) return\n\n const state = stockpile.state as any\n const areaW = state.width ?? 100\n const areaH = state.height ?? 100\n const pattern = (state.stackPattern as StackPattern) ?? 'row'\n const preset = (state.carrierPreset as CarrierPreset) ?? 'box'\n\n // carrier 크기 — 명시값 우선, 없으면 preset default\n const def = PRESET_DEFAULT_SIZE[preset] ?? PRESET_DEFAULT_SIZE.box\n const cw = state.carrierWidth ?? def.w\n const ch = state.carrierHeight ?? def.h\n const cd = state.carrierDepth ?? def.d\n const gap = state.carrierGap ?? 10 // 평면(xz) cell 간격 — 0 이면 딱 붙음. carrier 크기 대비 충분히 분리되도록 default 10.\n\n const geom = this._carrierGeometry(preset, cw, ch, cd)\n // record 별로 색이 다를 수 있어(Legend 매핑) material 을 record 별로 생성.\n // 같은 색은 material 캐시로 공유해 dispose 비용 / drawcall 최적화.\n const presetDefaultColor = PRESET_COLOR[preset] ?? PRESET_COLOR.box\n this._disposeMaterialCache()\n const resolveColor = (record: any): number => {\n const legendColor = (stockpile as any).resolveLegendColor?.(record)\n if (typeof legendColor === 'string' && legendColor.length > 0) {\n try { return new THREE.Color(legendColor).getHex() } catch { /* fallthrough */ }\n }\n return presetDefaultColor\n }\n\n const positions = this._computeStackPositions(pattern, count, areaW, areaH, cw, ch, cd, gap, state.stackHeightLimit)\n this._meshByRecordId.clear()\n const records = stockpile.records\n for (let i = 0; i < positions.length; i++) {\n const p = positions[i]\n const record = records[i]\n const colorHex = resolveColor(record)\n const mat = this._getMaterialForColor(colorHex)\n const mesh = new THREE.Mesh(geom, mat)\n mesh.position.set(p.x, p.y, p.z)\n mesh.castShadow = true\n mesh.receiveShadow = true\n // raycast hit → record 식별을 위해 userData 에 recordId 저장 + Map 갱신.\n const rid = records[i]?.id\n if (rid != null) {\n mesh.userData.recordId = String(rid)\n this._meshByRecordId.set(String(rid), mesh)\n }\n g.add(mesh)\n }\n }\n\n /** record.id 로 해당 carrier mesh 직접 조회 — popup tether anchor 용. */\n getMeshByRecordId(recordId: string): THREE.Mesh | undefined {\n return this._meshByRecordId.get(recordId)\n }\n\n /**\n * stackPattern 별 각 carrier 의 local 좌표(영역 중심 기준). y 는 pad 위에 쌓이는\n * 높이(cd 단위), x/z 는 영역 평면 위 분포.\n */\n private _computeStackPositions(\n pattern: StackPattern,\n count: number,\n areaW: number,\n areaH: number,\n cw: number,\n ch: number,\n cd: number,\n gap: number,\n heightLimit?: number\n ): Array<{ x: number; y: number; z: number }> {\n const out: Array<{ x: number; y: number; z: number }> = []\n\n // column — 한 자리에 수직 적층\n if (pattern === 'column') {\n const layers = heightLimit ?? count\n for (let i = 0; i < count; i++) {\n const layer = Math.min(i, layers - 1)\n out.push({ x: 0, y: layer * cd + cd / 2, z: 0 })\n }\n return out\n }\n\n // 격자 cell — 행/열 수. cell stride = carrier + gap (인접 carrier 사이 분리).\n const stridX = cw + gap\n const stridZ = ch + gap\n const cols = Math.max(1, Math.floor((areaW + gap) / stridX))\n const rows = Math.max(1, Math.floor((areaH + gap) / stridZ))\n const cellsPerLayer = cols * rows\n\n // pyramid — 위로 갈수록 행/열 -1 씩 (사다리꼴)\n if (pattern === 'pyramid') {\n let remaining = count\n let layer = 0\n while (remaining > 0) {\n const lcols = Math.max(1, cols - layer)\n const lrows = Math.max(1, rows - layer)\n const cellsThisLayer = lcols * lrows\n const take = Math.min(remaining, cellsThisLayer)\n for (let i = 0; i < take; i++) {\n const c = i % lcols\n const r = Math.floor(i / lcols)\n // 가운데 정렬 — 줄어든 만큼 offset\n const offsetCol = (cols - lcols) / 2\n const offsetRow = (rows - lrows) / 2\n const x = -areaW / 2 + (c + offsetCol + 0.5) * stridX\n const z = -areaH / 2 + (r + offsetRow + 0.5) * stridZ\n out.push({ x, y: layer * cd + cd / 2, z })\n }\n remaining -= take\n layer++\n if (lcols === 1 && lrows === 1) {\n // 정상에 도달 — 남은 건 column 처럼 위로\n for (let i = 0; i < remaining; i++) {\n out.push({ x: 0, y: (layer + i) * cd + cd / 2, z: 0 })\n }\n break\n }\n if (heightLimit && layer >= heightLimit) break\n }\n return out\n }\n\n // pile — 자연 더미. row 와 비슷하되 가장자리는 약간 옆으로 흘러내림 효과\n // (간단 구현 — 단마다 약간 random offset).\n if (pattern === 'pile') {\n // pseudo-random (인덱스 기반, deterministic)\n const rng = (i: number) => ((Math.sin(i * 12.9898) * 43758.5453) % 1 + 1) % 1\n for (let i = 0; i < count; i++) {\n const layer = Math.floor(i / cellsPerLayer)\n const idx = i % cellsPerLayer\n const c = idx % cols\n const r = Math.floor(idx / cols)\n const jitterX = (rng(i * 2) - 0.5) * cw * 0.2\n const jitterZ = (rng(i * 2 + 1) - 0.5) * ch * 0.2\n const x = -areaW / 2 + (c + 0.5) * stridX + jitterX\n const z = -areaH / 2 + (r + 0.5) * stridZ + jitterZ\n out.push({ x, y: layer * cd + cd / 2, z })\n if (heightLimit && layer >= heightLimit - 1 && idx === cellsPerLayer - 1) break\n }\n return out\n }\n\n // row (default) / staggered — 격자 적층\n for (let i = 0; i < count; i++) {\n const layer = Math.floor(i / cellsPerLayer)\n if (heightLimit && layer >= heightLimit) break\n const idx = i % cellsPerLayer\n const c = idx % cols\n const r = Math.floor(idx / cols)\n let x = -areaW / 2 + (c + 0.5) * stridX\n const z = -areaH / 2 + (r + 0.5) * stridZ\n // staggered — 홀수 layer 는 1/2 cell offset (벽돌식)\n if (pattern === 'staggered' && layer % 2 === 1) {\n x += stridX / 2\n }\n out.push({ x, y: layer * cd + cd / 2, z })\n }\n return out\n }\n\n /** carrierPreset 별 geometry. drum 은 cylinder, 나머지는 box. */\n private _carrierGeometry(preset: CarrierPreset, w: number, h: number, d: number): THREE.BufferGeometry {\n if (preset === 'drum') {\n const radius = Math.min(w, h) / 2\n return new THREE.CylinderGeometry(radius, radius, d, 16)\n }\n // sack/bale — 약간 작게 (자연스러운 형태)\n if (preset === 'sack' || preset === 'bale') {\n return new THREE.BoxGeometry(w * 0.92, d * 0.92, h * 0.92)\n }\n return new THREE.BoxGeometry(w, d, h)\n }\n\n /**\n * state.alpha 변경 시 pad + carriers 의 material opacity 즉시 반영.\n * pad 는 원래 0.55 base opacity 위에 alpha 곱 (영역 표시가 너무 진해지지 않도록).\n * carriers 는 alpha 그대로 (단순한 곱은 fully opaque 이 1, 반투명이 0).\n */\n updateAlpha(): void {\n const state = this.component.state as any\n const alpha = typeof state.alpha === 'number' ? state.alpha : 1\n if (this._padMesh) {\n const m = this._padMesh.material as THREE.MeshStandardMaterial\n m.opacity = 0.55 * alpha\n m.transparent = m.opacity < 1\n m.needsUpdate = true\n }\n if (this._carriersGroup) {\n for (const child of this._carriersGroup.children) {\n const mesh = child as THREE.Mesh\n const m = mesh.material as THREE.MeshStandardMaterial\n if (!m) continue\n m.opacity = alpha\n m.transparent = alpha < 1\n m.needsUpdate = true\n }\n }\n }\n\n updateDimension(): void {\n // width/height 변경 시 pad geometry + outline + carriers 재계산\n if (this._padMesh) {\n const state = this.component.state as any\n const w = state.width ?? 100\n const h = state.height ?? 100\n this._padMesh.geometry.dispose()\n this._padMesh.geometry = new THREE.BoxGeometry(w, PAD_DEPTH, h)\n if (this._padOutline) {\n this._padOutline.geometry.dispose()\n this._padOutline.geometry = new THREE.EdgesGeometry(this._padMesh.geometry)\n }\n }\n this._rebuildCarriers()\n }\n\n /**\n * state 변경 시 즉시 3D 갱신 — property panel 의 수정이 바로 반영되도록.\n * - width/height → pad geometry 재생성 + carriers 재계산 (updateDimension)\n * - 적치/외형 관련 키 → carriers 만 재계산 (_rebuildCarriers)\n */\n onchange(after: Record<string, unknown>, before: Record<string, unknown>): void {\n if ('width' in after || 'height' in after) {\n this.updateDimension()\n return\n }\n if ('alpha' in after) {\n this.updateAlpha()\n return\n }\n if ('fillStyle' in after) {\n this._applyPadColor()\n // fillStyle 변경 시 strokeStyle 미설정이면 outline default 도 같이 갱신\n if ((this.component.state as any).strokeStyle == null) this._applyStrokeColor()\n return\n }\n if ('strokeStyle' in after) {\n this._applyStrokeColor()\n return\n }\n const rebuildKeys = [\n 'data',\n 'stackPattern', 'carrierPreset',\n 'carrierWidth', 'carrierHeight', 'carrierDepth', 'carrierGap',\n 'capacity', 'stackHeightLimit', 'pickPolicy'\n ]\n if (rebuildKeys.some(k => k in after)) {\n this._rebuildCarriers()\n return\n }\n super.onchange?.(after, before)\n }\n}\n"]}
@@ -0,0 +1,30 @@
1
+ import * as THREE from 'three';
2
+ import { RealObjectGroup } from '@hatiolab/things-scene';
3
+ export declare class StockpileGrid3D extends RealObjectGroup {
4
+ /** cellSlotId → pad mesh (popup tether anchor 용). */
5
+ private _padByCellId;
6
+ /** cellSlotId → carriers group. */
7
+ private _carriersByCellId;
8
+ /** material 캐시 (color → material) — 같은 색 carrier 공유. */
9
+ private _materialByColor;
10
+ /** grid 전체를 감싸는 outer group (보드 보정 등). */
11
+ private _gridGroup?;
12
+ build(): void;
13
+ update(): void;
14
+ /** carrier attach anchor — slotId 가 cellId 면 그 cell pad 반환, 아니면 grid group. */
15
+ getAttachFrame(slotId?: string): THREE.Object3D | undefined;
16
+ /** slotTargetAt(cellId).attachObject3d = cell pad — Stockpile.getSlotAttachObject3d 가 호출. */
17
+ getCellPadMesh(slotId: string): THREE.Mesh | undefined;
18
+ private _disposeAll;
19
+ private _disposeGroupChildren;
20
+ private _rebuildAll;
21
+ private _buildGrid;
22
+ /** cell 의 records 를 stackPattern / carrierPreset 으로 배치. */
23
+ private _populateCellCarriers;
24
+ private _computeStackPositions;
25
+ private _carrierGeometry;
26
+ private _getMaterial;
27
+ onchange(after: Record<string, unknown>, before: Record<string, unknown>): void;
28
+ updateDimension(): void;
29
+ updateAlpha(): void;
30
+ }
@@ -0,0 +1,301 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ *
4
+ * StockpileGrid3D — cell × cell 의 평치 영역 3D 시각화. cell 마다 pad + records 기반
5
+ * 자동 적치 carrier mesh. Stockpile3D 와 같은 idiom 의 cell 별 적용.
6
+ *
7
+ * cell pad mesh 에 userData.slotId 를 심어 click raycast 가 cell 을 식별, popup
8
+ * tether anchor 로 동작 (storage-rack 패턴).
9
+ */
10
+ import * as THREE from 'three';
11
+ import { RealObjectGroup } from '@hatiolab/things-scene';
12
+ const PAD_DEPTH = 2;
13
+ const PRESET_COLOR = {
14
+ box: 0xb87333,
15
+ pallet: 0x8b6f47,
16
+ drum: 0x556679,
17
+ sack: 0xd4c89a,
18
+ crate: 0x9a7548,
19
+ bale: 0xa89968
20
+ };
21
+ const PRESET_DEFAULT_SIZE = {
22
+ box: { w: 26, h: 26, d: 20 },
23
+ pallet: { w: 40, h: 30, d: 15 },
24
+ drum: { w: 24, h: 24, d: 30 },
25
+ sack: { w: 30, h: 28, d: 18 },
26
+ crate: { w: 30, h: 30, d: 22 },
27
+ bale: { w: 32, h: 30, d: 18 }
28
+ };
29
+ export class StockpileGrid3D extends RealObjectGroup {
30
+ /** cellSlotId → pad mesh (popup tether anchor 용). */
31
+ _padByCellId = new Map();
32
+ /** cellSlotId → carriers group. */
33
+ _carriersByCellId = new Map();
34
+ /** material 캐시 (color → material) — 같은 색 carrier 공유. */
35
+ _materialByColor = new Map();
36
+ /** grid 전체를 감싸는 outer group (보드 보정 등). */
37
+ _gridGroup;
38
+ build() {
39
+ super.build();
40
+ this._buildGrid();
41
+ }
42
+ update() {
43
+ super.update();
44
+ this._rebuildAll();
45
+ }
46
+ /** carrier attach anchor — slotId 가 cellId 면 그 cell pad 반환, 아니면 grid group. */
47
+ getAttachFrame(slotId) {
48
+ if (slotId) {
49
+ const pad = this._padByCellId.get(slotId);
50
+ if (pad)
51
+ return pad;
52
+ }
53
+ return this._gridGroup;
54
+ }
55
+ /** slotTargetAt(cellId).attachObject3d = cell pad — Stockpile.getSlotAttachObject3d 가 호출. */
56
+ getCellPadMesh(slotId) {
57
+ return this._padByCellId.get(slotId);
58
+ }
59
+ _disposeAll() {
60
+ if (this._gridGroup) {
61
+ this._disposeGroupChildren(this._gridGroup);
62
+ this.object3d.remove(this._gridGroup);
63
+ this._gridGroup = undefined;
64
+ }
65
+ this._padByCellId.clear();
66
+ this._carriersByCellId.clear();
67
+ for (const m of this._materialByColor.values())
68
+ m.dispose();
69
+ this._materialByColor.clear();
70
+ }
71
+ _disposeGroupChildren(group) {
72
+ while (group.children.length > 0) {
73
+ const child = group.children[0];
74
+ this._disposeGroupChildren(child);
75
+ group.remove(child);
76
+ if (child.geometry?.dispose)
77
+ child.geometry.dispose();
78
+ }
79
+ }
80
+ _rebuildAll() {
81
+ this._disposeAll();
82
+ this._buildGrid();
83
+ }
84
+ _buildGrid() {
85
+ const grid = this.component;
86
+ const cols = grid.cols;
87
+ const rows = grid.rows;
88
+ const cellW = grid.cellW;
89
+ const cellH = grid.cellH;
90
+ const state = grid.state;
91
+ const outline = new THREE.Color(state.strokeStyle || '#7a5a2e');
92
+ const fillColor = new THREE.Color(state.fillStyle || '#c89c5c');
93
+ this._gridGroup = new THREE.Group();
94
+ // grid pad 원점은 컴포넌트 중심 (left+totalW/2). state.left/top 기준 origin 0
95
+ // 인 사각형 좌상단 — grid local 좌표에서 cell 의 인덱스 (col, row) → cell center
96
+ // = (col+0.5)*cellW - totalW/2, (row+0.5)*cellH - totalH/2 (3D world 의 컴포넌트
97
+ // 중심 기준 local).
98
+ const totalW = cellW * cols;
99
+ const totalH = cellH * rows;
100
+ this.object3d.add(this._gridGroup);
101
+ for (let r = 0; r < rows; r++) {
102
+ for (let c = 0; c < cols; c++) {
103
+ const cellId = grid.cellIdOf(c, r);
104
+ const cellFill = fillColor; // cell 별 색 override 없음 — 모두 grid 공통
105
+ // ── cell pad ─────────────────────────────────────────
106
+ const padGeom = new THREE.BoxGeometry(cellW * 0.96, PAD_DEPTH, cellH * 0.96);
107
+ const padMat = new THREE.MeshStandardMaterial({
108
+ color: cellFill, roughness: 0.85, transparent: true, opacity: 0.55
109
+ });
110
+ const pad = new THREE.Mesh(padGeom, padMat);
111
+ const cx = (c + 0.5) * cellW - totalW / 2;
112
+ const cz = (r + 0.5) * cellH - totalH / 2;
113
+ pad.position.set(cx, PAD_DEPTH / 2, cz);
114
+ pad.receiveShadow = true;
115
+ pad.userData.slotId = cellId;
116
+ this._gridGroup.add(pad);
117
+ this._padByCellId.set(cellId, pad);
118
+ // cell outline — 페인트 라인
119
+ const padEdges = new THREE.EdgesGeometry(padGeom);
120
+ const padLine = new THREE.LineSegments(padEdges, new THREE.LineBasicMaterial({ color: outline }));
121
+ padLine.position.copy(pad.position);
122
+ this._gridGroup.add(padLine);
123
+ // ── cell carriers ────────────────────────────────────
124
+ const cg = new THREE.Group();
125
+ cg.position.set(cx, PAD_DEPTH, cz);
126
+ this._gridGroup.add(cg);
127
+ this._carriersByCellId.set(cellId, cg);
128
+ this._populateCellCarriers(c, r, cg);
129
+ }
130
+ }
131
+ }
132
+ /** cell 의 records 를 stackPattern / carrierPreset 으로 배치. */
133
+ _populateCellCarriers(col, row, group) {
134
+ const grid = this.component;
135
+ const records = grid.recordsOf(col, row);
136
+ if (records.length === 0)
137
+ return;
138
+ const state = grid.state;
139
+ const preset = (state.carrierPreset ?? 'box');
140
+ const pattern = (state.stackPattern ?? 'row');
141
+ const def = PRESET_DEFAULT_SIZE[preset] ?? PRESET_DEFAULT_SIZE.box;
142
+ const cw = state.carrierWidth ?? def.w;
143
+ const ch = state.carrierHeight ?? def.h;
144
+ const cd = state.carrierDepth ?? def.d;
145
+ const gap = state.carrierGap ?? 10;
146
+ const heightLimit = state.stackHeightLimit;
147
+ const cellW = grid.cellW;
148
+ const cellH = grid.cellH;
149
+ const geom = this._carrierGeometry(preset, cw, ch, cd);
150
+ const positions = this._computeStackPositions(pattern, records.length, cellW, cellH, cw, ch, cd, gap, heightLimit);
151
+ const presetDefault = PRESET_COLOR[preset] ?? PRESET_COLOR.box;
152
+ for (let i = 0; i < positions.length; i++) {
153
+ const p = positions[i];
154
+ const record = records[i];
155
+ const legendColor = grid.resolveLegendColor?.(record);
156
+ let colorHex = presetDefault;
157
+ if (typeof legendColor === 'string' && legendColor.length > 0) {
158
+ try {
159
+ colorHex = new THREE.Color(legendColor).getHex();
160
+ }
161
+ catch { /* ignore */ }
162
+ }
163
+ const mat = this._getMaterial(colorHex);
164
+ const mesh = new THREE.Mesh(geom, mat);
165
+ mesh.position.set(p.x, p.y, p.z);
166
+ mesh.castShadow = true;
167
+ mesh.receiveShadow = true;
168
+ mesh.userData.recordId = record.id;
169
+ mesh.userData.cellId = grid.cellIdOf(col, row);
170
+ group.add(mesh);
171
+ }
172
+ }
173
+ _computeStackPositions(pattern, count, areaW, areaH, cw, ch, cd, gap, heightLimit) {
174
+ const out = [];
175
+ if (pattern === 'column') {
176
+ const layers = heightLimit ?? count;
177
+ for (let i = 0; i < count; i++) {
178
+ const layer = Math.min(i, layers - 1);
179
+ out.push({ x: 0, y: layer * cd + cd / 2, z: 0 });
180
+ }
181
+ return out;
182
+ }
183
+ const stridX = cw + gap;
184
+ const stridZ = ch + gap;
185
+ const cols = Math.max(1, Math.floor((areaW + gap) / stridX));
186
+ const rows = Math.max(1, Math.floor((areaH + gap) / stridZ));
187
+ const cellsPerLayer = cols * rows;
188
+ if (pattern === 'pyramid') {
189
+ let remaining = count;
190
+ let layer = 0;
191
+ while (remaining > 0) {
192
+ const lcols = Math.max(1, cols - layer);
193
+ const lrows = Math.max(1, rows - layer);
194
+ const cellsThisLayer = lcols * lrows;
195
+ const take = Math.min(remaining, cellsThisLayer);
196
+ for (let i = 0; i < take; i++) {
197
+ const c = i % lcols;
198
+ const r = Math.floor(i / lcols);
199
+ const offC = (cols - lcols) / 2;
200
+ const offR = (rows - lrows) / 2;
201
+ const x = -areaW / 2 + (c + offC + 0.5) * stridX;
202
+ const z = -areaH / 2 + (r + offR + 0.5) * stridZ;
203
+ out.push({ x, y: layer * cd + cd / 2, z });
204
+ }
205
+ remaining -= take;
206
+ layer++;
207
+ if (lcols === 1 && lrows === 1) {
208
+ for (let i = 0; i < remaining; i++) {
209
+ out.push({ x: 0, y: (layer + i) * cd + cd / 2, z: 0 });
210
+ }
211
+ break;
212
+ }
213
+ if (heightLimit && layer >= heightLimit)
214
+ break;
215
+ }
216
+ return out;
217
+ }
218
+ if (pattern === 'pile') {
219
+ const rng = (i) => ((Math.sin(i * 12.9898) * 43758.5453) % 1 + 1) % 1;
220
+ for (let i = 0; i < count; i++) {
221
+ const layer = Math.floor(i / cellsPerLayer);
222
+ const idx = i % cellsPerLayer;
223
+ const c = idx % cols;
224
+ const r = Math.floor(idx / cols);
225
+ const jX = (rng(i * 2) - 0.5) * cw * 0.2;
226
+ const jZ = (rng(i * 2 + 1) - 0.5) * ch * 0.2;
227
+ const x = -areaW / 2 + (c + 0.5) * stridX + jX;
228
+ const z = -areaH / 2 + (r + 0.5) * stridZ + jZ;
229
+ out.push({ x, y: layer * cd + cd / 2, z });
230
+ if (heightLimit && layer >= heightLimit - 1 && idx === cellsPerLayer - 1)
231
+ break;
232
+ }
233
+ return out;
234
+ }
235
+ // row / staggered
236
+ for (let i = 0; i < count; i++) {
237
+ const layer = Math.floor(i / cellsPerLayer);
238
+ if (heightLimit && layer >= heightLimit)
239
+ break;
240
+ const idx = i % cellsPerLayer;
241
+ const c = idx % cols;
242
+ const r = Math.floor(idx / cols);
243
+ let x = -areaW / 2 + (c + 0.5) * stridX;
244
+ const z = -areaH / 2 + (r + 0.5) * stridZ;
245
+ if (pattern === 'staggered' && layer % 2 === 1)
246
+ x += stridX / 2;
247
+ out.push({ x, y: layer * cd + cd / 2, z });
248
+ }
249
+ return out;
250
+ }
251
+ _carrierGeometry(preset, w, h, d) {
252
+ if (preset === 'drum') {
253
+ const radius = Math.min(w, h) / 2;
254
+ return new THREE.CylinderGeometry(radius, radius, d, 16);
255
+ }
256
+ if (preset === 'sack' || preset === 'bale') {
257
+ return new THREE.BoxGeometry(w * 0.92, d * 0.92, h * 0.92);
258
+ }
259
+ return new THREE.BoxGeometry(w, d, h);
260
+ }
261
+ _getMaterial(colorHex) {
262
+ let m = this._materialByColor.get(colorHex);
263
+ if (!m) {
264
+ m = new THREE.MeshStandardMaterial({ color: colorHex, roughness: 0.7 });
265
+ this._materialByColor.set(colorHex, m);
266
+ }
267
+ return m;
268
+ }
269
+ onchange(after, before) {
270
+ // 거의 모든 속성 변경이 grid 재구성 — 단순화.
271
+ const keys = [
272
+ 'cols', 'rows', 'cellWidth', 'cellHeight',
273
+ 'cells', 'data',
274
+ 'stackPattern', 'carrierPreset',
275
+ 'carrierWidth', 'carrierHeight', 'carrierDepth', 'carrierGap',
276
+ 'capacity', 'stackHeightLimit', 'pickPolicy',
277
+ 'fillStyle', 'strokeStyle',
278
+ 'width', 'height'
279
+ ];
280
+ if (keys.some(k => k in after)) {
281
+ this._rebuildAll();
282
+ return;
283
+ }
284
+ super.onchange?.(after, before);
285
+ }
286
+ updateDimension() {
287
+ this._rebuildAll();
288
+ }
289
+ updateAlpha() {
290
+ const alpha = typeof this.component.state.alpha === 'number'
291
+ ? this.component.state.alpha : 1;
292
+ // pad 들의 opacity 만 (carriers 는 alpha 그대로)
293
+ for (const pad of this._padByCellId.values()) {
294
+ const m = pad.material;
295
+ m.opacity = 0.55 * alpha;
296
+ m.transparent = m.opacity < 1;
297
+ m.needsUpdate = true;
298
+ }
299
+ }
300
+ }
301
+ //# sourceMappingURL=stockpile-grid-3d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stockpile-grid-3d.js","sourceRoot":"","sources":["../src/stockpile-grid-3d.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright © HatioLab Inc. All rights reserved.\n *\n * StockpileGrid3D — cell × cell 의 평치 영역 3D 시각화. cell 마다 pad + records 기반\n * 자동 적치 carrier mesh. Stockpile3D 와 같은 idiom 의 cell 별 적용.\n *\n * cell pad mesh 에 userData.slotId 를 심어 click raycast 가 cell 을 식별, popup\n * tether anchor 로 동작 (storage-rack 패턴).\n */\n\nimport * as THREE from 'three'\nimport { RealObjectGroup } from '@hatiolab/things-scene'\n\nimport type StockpileGrid from './stockpile-grid.js'\nimport type { StackPattern, CarrierPreset } from './stockpile.js'\n\nconst PAD_DEPTH = 2\n\nconst PRESET_COLOR: Record<CarrierPreset, number> = {\n box: 0xb87333,\n pallet: 0x8b6f47,\n drum: 0x556679,\n sack: 0xd4c89a,\n crate: 0x9a7548,\n bale: 0xa89968\n}\n\nconst PRESET_DEFAULT_SIZE: Record<CarrierPreset, { w: number; h: number; d: number }> = {\n box: { w: 26, h: 26, d: 20 },\n pallet: { w: 40, h: 30, d: 15 },\n drum: { w: 24, h: 24, d: 30 },\n sack: { w: 30, h: 28, d: 18 },\n crate: { w: 30, h: 30, d: 22 },\n bale: { w: 32, h: 30, d: 18 }\n}\n\nexport class StockpileGrid3D extends RealObjectGroup {\n /** cellSlotId → pad mesh (popup tether anchor 용). */\n private _padByCellId: Map<string, THREE.Mesh> = new Map()\n /** cellSlotId → carriers group. */\n private _carriersByCellId: Map<string, THREE.Group> = new Map()\n /** material 캐시 (color → material) — 같은 색 carrier 공유. */\n private _materialByColor: Map<number, THREE.MeshStandardMaterial> = new Map()\n /** grid 전체를 감싸는 outer group (보드 보정 등). */\n private _gridGroup?: THREE.Group\n\n build() {\n super.build()\n this._buildGrid()\n }\n\n update() {\n super.update()\n this._rebuildAll()\n }\n\n /** carrier attach anchor — slotId 가 cellId 면 그 cell pad 반환, 아니면 grid group. */\n getAttachFrame(slotId?: string): THREE.Object3D | undefined {\n if (slotId) {\n const pad = this._padByCellId.get(slotId)\n if (pad) return pad\n }\n return this._gridGroup\n }\n /** slotTargetAt(cellId).attachObject3d = cell pad — Stockpile.getSlotAttachObject3d 가 호출. */\n getCellPadMesh(slotId: string): THREE.Mesh | undefined {\n return this._padByCellId.get(slotId)\n }\n\n private _disposeAll(): void {\n if (this._gridGroup) {\n this._disposeGroupChildren(this._gridGroup)\n this.object3d.remove(this._gridGroup)\n this._gridGroup = undefined\n }\n this._padByCellId.clear()\n this._carriersByCellId.clear()\n for (const m of this._materialByColor.values()) m.dispose()\n this._materialByColor.clear()\n }\n\n private _disposeGroupChildren(group: THREE.Object3D): void {\n while (group.children.length > 0) {\n const child = group.children[0]\n this._disposeGroupChildren(child)\n group.remove(child)\n if ((child as any).geometry?.dispose) (child as any).geometry.dispose()\n }\n }\n\n private _rebuildAll(): void {\n this._disposeAll()\n this._buildGrid()\n }\n\n private _buildGrid(): void {\n const grid = this.component as unknown as StockpileGrid\n const cols = grid.cols\n const rows = grid.rows\n const cellW = grid.cellW\n const cellH = grid.cellH\n const state = grid.state as any\n\n const outline = new THREE.Color((state.strokeStyle as string) || '#7a5a2e')\n const fillColor = new THREE.Color((state.fillStyle as string) || '#c89c5c')\n\n this._gridGroup = new THREE.Group()\n // grid pad 원점은 컴포넌트 중심 (left+totalW/2). state.left/top 기준 origin 0\n // 인 사각형 좌상단 — grid local 좌표에서 cell 의 인덱스 (col, row) → cell center\n // = (col+0.5)*cellW - totalW/2, (row+0.5)*cellH - totalH/2 (3D world 의 컴포넌트\n // 중심 기준 local).\n const totalW = cellW * cols\n const totalH = cellH * rows\n this.object3d.add(this._gridGroup)\n\n for (let r = 0; r < rows; r++) {\n for (let c = 0; c < cols; c++) {\n const cellId = grid.cellIdOf(c, r)\n const cellFill = fillColor // cell 별 색 override 없음 — 모두 grid 공통\n\n // ── cell pad ─────────────────────────────────────────\n const padGeom = new THREE.BoxGeometry(cellW * 0.96, PAD_DEPTH, cellH * 0.96)\n const padMat = new THREE.MeshStandardMaterial({\n color: cellFill, roughness: 0.85, transparent: true, opacity: 0.55\n })\n const pad = new THREE.Mesh(padGeom, padMat)\n const cx = (c + 0.5) * cellW - totalW / 2\n const cz = (r + 0.5) * cellH - totalH / 2\n pad.position.set(cx, PAD_DEPTH / 2, cz)\n pad.receiveShadow = true\n pad.userData.slotId = cellId\n this._gridGroup.add(pad)\n this._padByCellId.set(cellId, pad)\n\n // cell outline — 페인트 라인\n const padEdges = new THREE.EdgesGeometry(padGeom)\n const padLine = new THREE.LineSegments(padEdges, new THREE.LineBasicMaterial({ color: outline }))\n padLine.position.copy(pad.position)\n this._gridGroup.add(padLine)\n\n // ── cell carriers ────────────────────────────────────\n const cg = new THREE.Group()\n cg.position.set(cx, PAD_DEPTH, cz)\n this._gridGroup.add(cg)\n this._carriersByCellId.set(cellId, cg)\n this._populateCellCarriers(c, r, cg)\n }\n }\n }\n\n /** cell 의 records 를 stackPattern / carrierPreset 으로 배치. */\n private _populateCellCarriers(col: number, row: number, group: THREE.Group): void {\n const grid = this.component as unknown as StockpileGrid\n const records = grid.recordsOf(col, row)\n if (records.length === 0) return\n\n const state = grid.state as any\n const preset = (state.carrierPreset ?? 'box') as CarrierPreset\n const pattern = (state.stackPattern ?? 'row') as StackPattern\n const def = PRESET_DEFAULT_SIZE[preset] ?? PRESET_DEFAULT_SIZE.box\n const cw = state.carrierWidth ?? def.w\n const ch = state.carrierHeight ?? def.h\n const cd = state.carrierDepth ?? def.d\n const gap = state.carrierGap ?? 10\n const heightLimit = state.stackHeightLimit as number | undefined\n\n const cellW = grid.cellW\n const cellH = grid.cellH\n const geom = this._carrierGeometry(preset, cw, ch, cd)\n\n const positions = this._computeStackPositions(pattern, records.length, cellW, cellH, cw, ch, cd, gap, heightLimit)\n const presetDefault = PRESET_COLOR[preset] ?? PRESET_COLOR.box\n for (let i = 0; i < positions.length; i++) {\n const p = positions[i]\n const record = records[i]\n const legendColor = (grid as any).resolveLegendColor?.(record)\n let colorHex = presetDefault\n if (typeof legendColor === 'string' && legendColor.length > 0) {\n try { colorHex = new THREE.Color(legendColor).getHex() } catch { /* ignore */ }\n }\n const mat = this._getMaterial(colorHex)\n const mesh = new THREE.Mesh(geom, mat)\n mesh.position.set(p.x, p.y, p.z)\n mesh.castShadow = true\n mesh.receiveShadow = true\n mesh.userData.recordId = record.id\n mesh.userData.cellId = grid.cellIdOf(col, row)\n group.add(mesh)\n }\n }\n\n private _computeStackPositions(\n pattern: StackPattern,\n count: number,\n areaW: number, areaH: number,\n cw: number, ch: number, cd: number,\n gap: number,\n heightLimit?: number\n ): Array<{ x: number; y: number; z: number }> {\n const out: Array<{ x: number; y: number; z: number }> = []\n if (pattern === 'column') {\n const layers = heightLimit ?? count\n for (let i = 0; i < count; i++) {\n const layer = Math.min(i, layers - 1)\n out.push({ x: 0, y: layer * cd + cd / 2, z: 0 })\n }\n return out\n }\n const stridX = cw + gap\n const stridZ = ch + gap\n const cols = Math.max(1, Math.floor((areaW + gap) / stridX))\n const rows = Math.max(1, Math.floor((areaH + gap) / stridZ))\n const cellsPerLayer = cols * rows\n if (pattern === 'pyramid') {\n let remaining = count\n let layer = 0\n while (remaining > 0) {\n const lcols = Math.max(1, cols - layer)\n const lrows = Math.max(1, rows - layer)\n const cellsThisLayer = lcols * lrows\n const take = Math.min(remaining, cellsThisLayer)\n for (let i = 0; i < take; i++) {\n const c = i % lcols\n const r = Math.floor(i / lcols)\n const offC = (cols - lcols) / 2\n const offR = (rows - lrows) / 2\n const x = -areaW / 2 + (c + offC + 0.5) * stridX\n const z = -areaH / 2 + (r + offR + 0.5) * stridZ\n out.push({ x, y: layer * cd + cd / 2, z })\n }\n remaining -= take\n layer++\n if (lcols === 1 && lrows === 1) {\n for (let i = 0; i < remaining; i++) {\n out.push({ x: 0, y: (layer + i) * cd + cd / 2, z: 0 })\n }\n break\n }\n if (heightLimit && layer >= heightLimit) break\n }\n return out\n }\n if (pattern === 'pile') {\n const rng = (i: number) => ((Math.sin(i * 12.9898) * 43758.5453) % 1 + 1) % 1\n for (let i = 0; i < count; i++) {\n const layer = Math.floor(i / cellsPerLayer)\n const idx = i % cellsPerLayer\n const c = idx % cols\n const r = Math.floor(idx / cols)\n const jX = (rng(i * 2) - 0.5) * cw * 0.2\n const jZ = (rng(i * 2 + 1) - 0.5) * ch * 0.2\n const x = -areaW / 2 + (c + 0.5) * stridX + jX\n const z = -areaH / 2 + (r + 0.5) * stridZ + jZ\n out.push({ x, y: layer * cd + cd / 2, z })\n if (heightLimit && layer >= heightLimit - 1 && idx === cellsPerLayer - 1) break\n }\n return out\n }\n // row / staggered\n for (let i = 0; i < count; i++) {\n const layer = Math.floor(i / cellsPerLayer)\n if (heightLimit && layer >= heightLimit) break\n const idx = i % cellsPerLayer\n const c = idx % cols\n const r = Math.floor(idx / cols)\n let x = -areaW / 2 + (c + 0.5) * stridX\n const z = -areaH / 2 + (r + 0.5) * stridZ\n if (pattern === 'staggered' && layer % 2 === 1) x += stridX / 2\n out.push({ x, y: layer * cd + cd / 2, z })\n }\n return out\n }\n\n private _carrierGeometry(preset: CarrierPreset, w: number, h: number, d: number): THREE.BufferGeometry {\n if (preset === 'drum') {\n const radius = Math.min(w, h) / 2\n return new THREE.CylinderGeometry(radius, radius, d, 16)\n }\n if (preset === 'sack' || preset === 'bale') {\n return new THREE.BoxGeometry(w * 0.92, d * 0.92, h * 0.92)\n }\n return new THREE.BoxGeometry(w, d, h)\n }\n\n private _getMaterial(colorHex: number): THREE.MeshStandardMaterial {\n let m = this._materialByColor.get(colorHex)\n if (!m) {\n m = new THREE.MeshStandardMaterial({ color: colorHex, roughness: 0.7 })\n this._materialByColor.set(colorHex, m)\n }\n return m\n }\n\n onchange(after: Record<string, unknown>, before: Record<string, unknown>): void {\n // 거의 모든 속성 변경이 grid 재구성 — 단순화.\n const keys = [\n 'cols', 'rows', 'cellWidth', 'cellHeight',\n 'cells', 'data',\n 'stackPattern', 'carrierPreset',\n 'carrierWidth', 'carrierHeight', 'carrierDepth', 'carrierGap',\n 'capacity', 'stackHeightLimit', 'pickPolicy',\n 'fillStyle', 'strokeStyle',\n 'width', 'height'\n ]\n if (keys.some(k => k in after)) {\n this._rebuildAll()\n return\n }\n super.onchange?.(after, before)\n }\n\n updateDimension(): void {\n this._rebuildAll()\n }\n\n updateAlpha(): void {\n const alpha = typeof (this.component.state as any).alpha === 'number'\n ? (this.component.state as any).alpha : 1\n // pad 들의 opacity 만 (carriers 는 alpha 그대로)\n for (const pad of this._padByCellId.values()) {\n const m = pad.material as THREE.MeshStandardMaterial\n m.opacity = 0.55 * alpha\n m.transparent = m.opacity < 1\n m.needsUpdate = true\n }\n }\n}\n"]}
@@ -0,0 +1,88 @@
1
+ import { Component, ComponentNature, RealObject } from '@hatiolab/things-scene';
2
+ import type { State, Material3D } from '@hatiolab/things-scene';
3
+ import { SlotTarget, type AttachFrame, type Alignment, type Heights, type PlacementArchetype } from '@operato/scene-base';
4
+ import { StockpileGrid3D } from './stockpile-grid-3d.js';
5
+ import type { StackPattern, CarrierPreset, StockpileRecord, PickPolicy } from './stockpile.js';
6
+ /** grid 의 한 cell — 위치 + 그 cell 의 records. */
7
+ export interface StockpileGridCell {
8
+ col: number;
9
+ row: number;
10
+ data?: StockpileRecord[];
11
+ }
12
+ export interface StockpileGridState extends State {
13
+ cols?: number;
14
+ rows?: number;
15
+ /** 한 cell 의 평면 크기 (전체 width/height = cellWidth*cols, cellHeight*rows). */
16
+ cellWidth?: number;
17
+ cellHeight?: number;
18
+ /** grid 의 cell 들 — 각 cell 은 { col, row, data: Record[] }. */
19
+ data?: StockpileGridCell[];
20
+ stackPattern?: StackPattern;
21
+ carrierPreset?: CarrierPreset;
22
+ carrierWidth?: number;
23
+ carrierHeight?: number;
24
+ carrierDepth?: number;
25
+ carrierGap?: number;
26
+ capacity?: number;
27
+ stackHeightLimit?: number;
28
+ pickPolicy?: PickPolicy;
29
+ popupRef?: string;
30
+ legendTarget?: string;
31
+ material3d?: Material3D;
32
+ }
33
+ declare const StockpileGrid_base: any;
34
+ export default class StockpileGrid extends StockpileGrid_base {
35
+ state: StockpileGridState;
36
+ _realObject?: StockpileGrid3D;
37
+ static placement: PlacementArchetype;
38
+ static align: Alignment;
39
+ static defaultDepth: (_h: Heights) => number;
40
+ get nature(): ComponentNature;
41
+ get anchors(): never[];
42
+ get cols(): number;
43
+ get rows(): number;
44
+ get cellW(): number;
45
+ get cellH(): number;
46
+ cellIdOf(col: number, row: number): string;
47
+ parseCellId(slotId: string): {
48
+ col: number;
49
+ row: number;
50
+ } | null;
51
+ /** state.data 에서 (col,row) cell 찾기. */
52
+ private _findCell;
53
+ /** cell 의 records (없으면 빈 배열). */
54
+ recordsOf(col: number, row: number): ReadonlyArray<StockpileRecord>;
55
+ /** capacity 는 모든 cell 공통. */
56
+ capacityOf(_col: number, _row: number): number | undefined;
57
+ slotIds(): ReadonlyArray<string>;
58
+ hasCarrierAt(slotId: string): boolean;
59
+ canReceiveAt(slotId: string, _carrier?: Component): boolean;
60
+ occupiedSlotIds(): ReadonlyArray<string>;
61
+ emptySlotIds(): ReadonlyArray<string>;
62
+ obtainCarrier(slotId: string): Component | null;
63
+ receiveAt(slotId: string, carrier: Component, _options?: any): Promise<void>;
64
+ accept(carrier: Component, options?: any): Promise<void>;
65
+ receive(carrier: Component, options?: any): Promise<void>;
66
+ slotTargetAt(slotId: string): SlotTarget;
67
+ getSlotAttachObject3d(slotId: string): any;
68
+ attachPointFor(carrier: Component): AttachFrame | null;
69
+ private _setCellRecords;
70
+ private _materializeCarrier;
71
+ private _legendTarget?;
72
+ get legendTarget(): Component | undefined;
73
+ private _onLegendChanged;
74
+ resolveLegendColor(record: any): string | undefined;
75
+ get eventMap(): {
76
+ '(self)': {
77
+ '(self)': {
78
+ click: (mouseEvent: MouseEvent) => void;
79
+ };
80
+ };
81
+ };
82
+ private _onGridClick;
83
+ private _invokePopup;
84
+ private _raycastHit;
85
+ render(ctx: CanvasRenderingContext2D): void;
86
+ buildRealObject(): RealObject | undefined;
87
+ }
88
+ export {};