@operato/scene-storage 10.0.0-beta.55 → 10.0.0-beta.57
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 +25 -0
- package/dist/rack-grid-cell.d.ts +4 -1
- package/dist/stockpile-3d.d.ts +0 -5
- package/dist/stockpile-3d.js +89 -93
- package/dist/stockpile-3d.js.map +1 -1
- package/dist/stockpile-grid-3d.js +5 -1
- package/dist/stockpile-grid-3d.js.map +1 -1
- 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 +21 -3
- package/dist/stockpile.js +31 -4
- package/dist/stockpile.js.map +1 -1
- package/package.json +3 -3
- package/src/stockpile-3d.ts +76 -106
- package/src/stockpile-grid-3d.ts +5 -1
- package/src/stockpile-grid.ts +17 -6
- package/src/stockpile.ts +44 -6
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,31 @@
|
|
|
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.57](https://github.com/things-scene/operato-scene/compare/v10.0.0-beta.56...v10.0.0-beta.57) (2026-06-15)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### :rocket: New Features
|
|
10
|
+
|
|
11
|
+
* **conveyance/storage:** 슈트→stockpile 자동링크 + 배치 flush ([971f870](https://github.com/things-scene/operato-scene/commit/971f870d7ec9b3bafebdf157089fdd9d1fb535d4))
|
|
12
|
+
* **routing:** StockPile = RoutingTarget(destination) + topology 없는 sink 노드 (D) ([df83d9a](https://github.com/things-scene/operato-scene/commit/df83d9a8f76bafc14a3b6b474cda5aa00f5ced74))
|
|
13
|
+
* **storage:** 입구 맞은편부터 슬라이스 적치 + 입구 자동도출 ([6314ede](https://github.com/things-scene/operato-scene/commit/6314ede1409c110748f67c8dc37864fad096aa6e))
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### :house: Code Refactoring
|
|
17
|
+
|
|
18
|
+
* **scene-base:** computeStackPositions 공유 helper 추출 (벌크 carrier 기반, B1) ([6840a65](https://github.com/things-scene/operato-scene/commit/6840a65633904ee80e75894a3155ddac85067c42))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
## [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)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### :house: Code Refactoring
|
|
26
|
+
|
|
27
|
+
* **storage:** Stockpile/StockpileGrid SlottedHolder 명시 표준화 (Phase 2) ([54b0a6d](https://github.com/things-scene/operato-scene/commit/54b0a6d961aba59ad830874c9b1847fb355a3940))
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
6
31
|
## [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
32
|
|
|
8
33
|
|
package/dist/rack-grid-cell.d.ts
CHANGED
|
@@ -81,6 +81,7 @@ declare const RackGridCell_base: (new (...args: any[]) => {
|
|
|
81
81
|
setState(props: Partial<import("@hatiolab/things-scene").State> | string, propval?: any): any;
|
|
82
82
|
get model(): any;
|
|
83
83
|
get state(): import("@hatiolab/things-scene").State;
|
|
84
|
+
get refid(): any;
|
|
84
85
|
get hierarchy(): any;
|
|
85
86
|
get volatile(): never[];
|
|
86
87
|
_applyProps(target: any, props: any, options: any): any;
|
|
@@ -120,7 +121,9 @@ declare const RackGridCell_base: (new (...args: any[]) => {
|
|
|
120
121
|
prepareIf(condition: boolean): void;
|
|
121
122
|
drawText(context: import("@hatiolab/things-scene").SceneRenderContext): void;
|
|
122
123
|
drawStroke(context: import("@hatiolab/things-scene").SceneRenderContext, override?: Record<string, unknown>): void;
|
|
123
|
-
drawFill(context: import("@hatiolab/things-scene").SceneRenderContext, override
|
|
124
|
+
drawFill(context: import("@hatiolab/things-scene").SceneRenderContext, override
|
|
125
|
+
/** 3D mesh 미생성 — view mode 의 리소스 0. */
|
|
126
|
+
?: Record<string, unknown>): void;
|
|
124
127
|
get strokeStyle(): any;
|
|
125
128
|
set strokeStyle(v: any): any;
|
|
126
129
|
get fillStyle(): any;
|
package/dist/stockpile-3d.d.ts
CHANGED
|
@@ -32,11 +32,6 @@ export declare class Stockpile3D extends RealObjectGroup {
|
|
|
32
32
|
private _rebuildCarriers;
|
|
33
33
|
/** record.id 로 해당 carrier mesh 직접 조회 — popup tether anchor 용. */
|
|
34
34
|
getMeshByRecordId(recordId: string): THREE.Mesh | undefined;
|
|
35
|
-
/**
|
|
36
|
-
* stackPattern 별 각 carrier 의 local 좌표(영역 중심 기준). y 는 pad 위에 쌓이는
|
|
37
|
-
* 높이(cd 단위), x/z 는 영역 평면 위 분포.
|
|
38
|
-
*/
|
|
39
|
-
private _computeStackPositions;
|
|
40
35
|
/** carrierPreset 별 geometry. drum 은 cylinder, 나머지는 box. */
|
|
41
36
|
private _carrierGeometry;
|
|
42
37
|
/**
|
package/dist/stockpile-3d.js
CHANGED
|
@@ -12,7 +12,87 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import * as THREE from 'three';
|
|
14
14
|
import { RealObjectGroup } from '@hatiolab/things-scene';
|
|
15
|
+
import { computeStackPositions } from '@operato/scene-base';
|
|
15
16
|
const PAD_DEPTH = 2;
|
|
17
|
+
/**
|
|
18
|
+
* 그래프(root.__flowGraph)에서 이 stockpile 로 *들어오는* 노드(입구)를 찾아, 적치를 *입구
|
|
19
|
+
* 맞은편부터* 하도록 reverseX/Z 를 산출한다. storage 가 conveyance 를 import 하지 않고
|
|
20
|
+
* 캐시 속성만 일반적으로 읽음(토폴로지 viz 와 동일 방식). 입구/그래프 없으면 undefined →
|
|
21
|
+
* 기본(-x/-z 모서리부터). 입구 방향은 stockpile local frame 기준(회전 반영).
|
|
22
|
+
*/
|
|
23
|
+
function inflowFillOpts(stockpile) {
|
|
24
|
+
const root = stockpile?.root;
|
|
25
|
+
// 로드 직후(sim 전)엔 그래프 캐시가 없을 수 있다 — conveyance 가 globalThis 에 심은
|
|
26
|
+
// 빌더로 즉석 build(토폴로지 viz 와 동일). 없으면(컨베이어 미로드) 기본값.
|
|
27
|
+
if (root && !root.__flowGraph) {
|
|
28
|
+
try {
|
|
29
|
+
globalThis.__operatoBuildFlowGraph?.(root);
|
|
30
|
+
}
|
|
31
|
+
catch { /* ignore */ }
|
|
32
|
+
}
|
|
33
|
+
const cache = root?.__flowGraph;
|
|
34
|
+
const out = cache?.graph?.out;
|
|
35
|
+
const comps = cache?.components;
|
|
36
|
+
// 그래프 빌더(flow-graph-coordinator collect)와 *동일* idOf — refid 는 set('refid') 로
|
|
37
|
+
// state.refid 에 저장되므로 c.refid 와 state.refid 를 둘 다 확인해야 한다. (c.refid 만 보면
|
|
38
|
+
// 명시 id 없는 stockpile 이 전부 undefined → bail → 기본값으로 떨어져 입구 도출 실패.)
|
|
39
|
+
const idOf = (c) => {
|
|
40
|
+
const raw = c?.state?.id;
|
|
41
|
+
if (typeof raw === 'string' && raw.length > 0)
|
|
42
|
+
return raw;
|
|
43
|
+
const refid = c?.refid ?? c?.state?.refid;
|
|
44
|
+
return refid != null ? String(refid) : undefined;
|
|
45
|
+
};
|
|
46
|
+
const myId = idOf(stockpile);
|
|
47
|
+
if (!out || !comps || !myId)
|
|
48
|
+
return undefined;
|
|
49
|
+
let feeder;
|
|
50
|
+
out.forEach((targets, srcId) => {
|
|
51
|
+
if (!feeder && Array.isArray(targets) && targets.includes(myId))
|
|
52
|
+
feeder = comps.get(srcId);
|
|
53
|
+
});
|
|
54
|
+
const ss = stockpile?.state;
|
|
55
|
+
// feeder(입구) 못 찾으면 기본값(undefined) — 마주한 슈트 없는 stockpile.
|
|
56
|
+
if (!feeder || !ss)
|
|
57
|
+
return undefined;
|
|
58
|
+
// 입구 흐름 = *소스 링크의 방향* — feeder(슈트)의 배출 anchor(이 stockpile 로 향하는) direction.
|
|
59
|
+
// (중심-중심 벡터가 아니라 링크 방향면을 써야 정확. 긴 슈트의 중심은 실제 유입면과 다를 수 있음.)
|
|
60
|
+
let dir;
|
|
61
|
+
try {
|
|
62
|
+
const outs = feeder.getSegmentTopology?.()?.outbounds;
|
|
63
|
+
if (Array.isArray(outs) && outs.length) {
|
|
64
|
+
const sx = (ss.left ?? 0) + (ss.width ?? 0) / 2;
|
|
65
|
+
const sz = (ss.top ?? 0) + (ss.height ?? 0) / 2;
|
|
66
|
+
let best = outs[0];
|
|
67
|
+
let bestD = Infinity;
|
|
68
|
+
for (const a of outs) {
|
|
69
|
+
if (!a?.worldPos || !a.direction)
|
|
70
|
+
continue;
|
|
71
|
+
const d = (a.worldPos.x - sx) ** 2 + (a.worldPos.z - sz) ** 2;
|
|
72
|
+
if (d < bestD) {
|
|
73
|
+
bestD = d;
|
|
74
|
+
best = a;
|
|
75
|
+
} // stockpile 에 가장 가까운 배출 anchor
|
|
76
|
+
}
|
|
77
|
+
if (best?.direction)
|
|
78
|
+
dir = best.direction;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
catch { /* topology 못 얻으면 fallback 없음 → 기본 */ }
|
|
82
|
+
if (!dir)
|
|
83
|
+
return undefined;
|
|
84
|
+
// 흐름 방향(world)을 stockpile local frame 으로 (회전 -rot).
|
|
85
|
+
const rot = typeof ss.rotation === 'number' ? ss.rotation : 0;
|
|
86
|
+
const cos = Math.cos(-rot);
|
|
87
|
+
const sin = Math.sin(-rot);
|
|
88
|
+
const lx = dir.x * cos - dir.z * sin;
|
|
89
|
+
const lz = dir.x * sin + dir.z * cos;
|
|
90
|
+
// 흐름이 x 우세면 x축 진행. items 는 흐름 방향 끝(먼저 닿는 곳)부터 쌓여 입구쪽으로 →
|
|
91
|
+
// 흐름이 + 면 + 끝부터(reverse).
|
|
92
|
+
const advanceAlongX = Math.abs(lx) >= Math.abs(lz);
|
|
93
|
+
const reverse = advanceAlongX ? lx > 0 : lz > 0;
|
|
94
|
+
return { advanceAlongX, reverse };
|
|
95
|
+
}
|
|
16
96
|
/** carrierPreset 별 default 색 (state.carrierWidth/Height/Depth 미지정 시 크기와 함께). */
|
|
17
97
|
const PRESET_COLOR = {
|
|
18
98
|
box: 0xb87333, // kraft brown
|
|
@@ -176,7 +256,15 @@ export class Stockpile3D extends RealObjectGroup {
|
|
|
176
256
|
}
|
|
177
257
|
return presetDefaultColor;
|
|
178
258
|
};
|
|
179
|
-
|
|
259
|
+
// stackHeightLimit = *총 적치 높이*(scene unit) — 단(layer) 개수가 아니다. 아이템
|
|
260
|
+
// 한 단 높이(cd)로 나눠 최대 단 수로 환산해 전달. 예: 한도 60 + 아이템높이 10 → 6단.
|
|
261
|
+
const heightLimit = state.stackHeightLimit;
|
|
262
|
+
const maxLayers = typeof heightLimit === 'number' && heightLimit > 0 && cd > 0
|
|
263
|
+
? Math.max(1, Math.floor(heightLimit / cd))
|
|
264
|
+
: undefined;
|
|
265
|
+
// 입구 맞은편부터 채우기 — 그래프에서 이 stockpile 로 들어오는 노드(입구)를 도출.
|
|
266
|
+
const fillOpts = inflowFillOpts(stockpile);
|
|
267
|
+
const positions = computeStackPositions(pattern, count, { w: areaW, h: areaH }, { w: cw, h: ch, d: cd }, gap, maxLayers, fillOpts);
|
|
180
268
|
this._meshByRecordId.clear();
|
|
181
269
|
const records = stockpile.records;
|
|
182
270
|
for (let i = 0; i < positions.length; i++) {
|
|
@@ -201,98 +289,6 @@ export class Stockpile3D extends RealObjectGroup {
|
|
|
201
289
|
getMeshByRecordId(recordId) {
|
|
202
290
|
return this._meshByRecordId.get(recordId);
|
|
203
291
|
}
|
|
204
|
-
/**
|
|
205
|
-
* stackPattern 별 각 carrier 의 local 좌표(영역 중심 기준). y 는 pad 위에 쌓이는
|
|
206
|
-
* 높이(cd 단위), x/z 는 영역 평면 위 분포.
|
|
207
|
-
*/
|
|
208
|
-
_computeStackPositions(pattern, count, areaW, areaH, cw, ch, cd, gap, heightLimit) {
|
|
209
|
-
const out = [];
|
|
210
|
-
// column — 한 자리에 수직 적층
|
|
211
|
-
if (pattern === 'column') {
|
|
212
|
-
const layers = heightLimit ?? count;
|
|
213
|
-
for (let i = 0; i < count; i++) {
|
|
214
|
-
const layer = Math.min(i, layers - 1);
|
|
215
|
-
out.push({ x: 0, y: layer * cd + cd / 2, z: 0 });
|
|
216
|
-
}
|
|
217
|
-
return out;
|
|
218
|
-
}
|
|
219
|
-
// 격자 cell — 행/열 수. cell stride = carrier + gap (인접 carrier 사이 분리).
|
|
220
|
-
const stridX = cw + gap;
|
|
221
|
-
const stridZ = ch + gap;
|
|
222
|
-
const cols = Math.max(1, Math.floor((areaW + gap) / stridX));
|
|
223
|
-
const rows = Math.max(1, Math.floor((areaH + gap) / stridZ));
|
|
224
|
-
const cellsPerLayer = cols * rows;
|
|
225
|
-
// pyramid — 위로 갈수록 행/열 -1 씩 (사다리꼴)
|
|
226
|
-
if (pattern === 'pyramid') {
|
|
227
|
-
let remaining = count;
|
|
228
|
-
let layer = 0;
|
|
229
|
-
while (remaining > 0) {
|
|
230
|
-
const lcols = Math.max(1, cols - layer);
|
|
231
|
-
const lrows = Math.max(1, rows - layer);
|
|
232
|
-
const cellsThisLayer = lcols * lrows;
|
|
233
|
-
const take = Math.min(remaining, cellsThisLayer);
|
|
234
|
-
for (let i = 0; i < take; i++) {
|
|
235
|
-
const c = i % lcols;
|
|
236
|
-
const r = Math.floor(i / lcols);
|
|
237
|
-
// 가운데 정렬 — 줄어든 만큼 offset
|
|
238
|
-
const offsetCol = (cols - lcols) / 2;
|
|
239
|
-
const offsetRow = (rows - lrows) / 2;
|
|
240
|
-
const x = -areaW / 2 + (c + offsetCol + 0.5) * stridX;
|
|
241
|
-
const z = -areaH / 2 + (r + offsetRow + 0.5) * stridZ;
|
|
242
|
-
out.push({ x, y: layer * cd + cd / 2, z });
|
|
243
|
-
}
|
|
244
|
-
remaining -= take;
|
|
245
|
-
layer++;
|
|
246
|
-
if (lcols === 1 && lrows === 1) {
|
|
247
|
-
// 정상에 도달 — 남은 건 column 처럼 위로
|
|
248
|
-
for (let i = 0; i < remaining; i++) {
|
|
249
|
-
out.push({ x: 0, y: (layer + i) * cd + cd / 2, z: 0 });
|
|
250
|
-
}
|
|
251
|
-
break;
|
|
252
|
-
}
|
|
253
|
-
if (heightLimit && layer >= heightLimit)
|
|
254
|
-
break;
|
|
255
|
-
}
|
|
256
|
-
return out;
|
|
257
|
-
}
|
|
258
|
-
// pile — 자연 더미. row 와 비슷하되 가장자리는 약간 옆으로 흘러내림 효과
|
|
259
|
-
// (간단 구현 — 단마다 약간 random offset).
|
|
260
|
-
if (pattern === 'pile') {
|
|
261
|
-
// pseudo-random (인덱스 기반, deterministic)
|
|
262
|
-
const rng = (i) => ((Math.sin(i * 12.9898) * 43758.5453) % 1 + 1) % 1;
|
|
263
|
-
for (let i = 0; i < count; i++) {
|
|
264
|
-
const layer = Math.floor(i / cellsPerLayer);
|
|
265
|
-
const idx = i % cellsPerLayer;
|
|
266
|
-
const c = idx % cols;
|
|
267
|
-
const r = Math.floor(idx / cols);
|
|
268
|
-
const jitterX = (rng(i * 2) - 0.5) * cw * 0.2;
|
|
269
|
-
const jitterZ = (rng(i * 2 + 1) - 0.5) * ch * 0.2;
|
|
270
|
-
const x = -areaW / 2 + (c + 0.5) * stridX + jitterX;
|
|
271
|
-
const z = -areaH / 2 + (r + 0.5) * stridZ + jitterZ;
|
|
272
|
-
out.push({ x, y: layer * cd + cd / 2, z });
|
|
273
|
-
if (heightLimit && layer >= heightLimit - 1 && idx === cellsPerLayer - 1)
|
|
274
|
-
break;
|
|
275
|
-
}
|
|
276
|
-
return out;
|
|
277
|
-
}
|
|
278
|
-
// row (default) / staggered — 격자 적층
|
|
279
|
-
for (let i = 0; i < count; i++) {
|
|
280
|
-
const layer = Math.floor(i / cellsPerLayer);
|
|
281
|
-
if (heightLimit && layer >= heightLimit)
|
|
282
|
-
break;
|
|
283
|
-
const idx = i % cellsPerLayer;
|
|
284
|
-
const c = idx % cols;
|
|
285
|
-
const r = Math.floor(idx / cols);
|
|
286
|
-
let x = -areaW / 2 + (c + 0.5) * stridX;
|
|
287
|
-
const z = -areaH / 2 + (r + 0.5) * stridZ;
|
|
288
|
-
// staggered — 홀수 layer 는 1/2 cell offset (벽돌식)
|
|
289
|
-
if (pattern === 'staggered' && layer % 2 === 1) {
|
|
290
|
-
x += stridX / 2;
|
|
291
|
-
}
|
|
292
|
-
out.push({ x, y: layer * cd + cd / 2, z });
|
|
293
|
-
}
|
|
294
|
-
return out;
|
|
295
|
-
}
|
|
296
292
|
/** carrierPreset 별 geometry. drum 은 cylinder, 나머지는 box. */
|
|
297
293
|
_carrierGeometry(preset, w, h, d) {
|
|
298
294
|
if (preset === 'drum') {
|
package/dist/stockpile-3d.js.map
CHANGED
|
@@ -1 +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"]}
|
|
1
|
+
{"version":3,"file":"stockpile-3d.js","sourceRoot":"","sources":["../src/stockpile-3d.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAK3D,MAAM,SAAS,GAAG,CAAC,CAAA;AAEnB;;;;;GAKG;AACH,SAAS,cAAc,CAAC,SAAc;IACpC,MAAM,IAAI,GAAG,SAAS,EAAE,IAAI,CAAA;IAC5B,+DAA+D;IAC/D,kDAAkD;IAClD,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAC9B,IAAI,CAAC;YAAE,UAAkB,CAAC,uBAAuB,EAAE,CAAC,IAAI,CAAC,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;IACpF,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,EAAE,WAAW,CAAA;IAC/B,MAAM,GAAG,GAAG,KAAK,EAAE,KAAK,EAAE,GAAoD,CAAA;IAC9E,MAAM,KAAK,GAAG,KAAK,EAAE,UAA0C,CAAA;IAC/D,6EAA6E;IAC7E,yEAAyE;IACzE,kEAAkE;IAClE,MAAM,IAAI,GAAG,CAAC,CAAM,EAAsB,EAAE;QAC1C,MAAM,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,CAAA;QACxB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,GAAG,CAAA;QACzD,MAAM,KAAK,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAA;QACzC,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAClD,CAAC,CAAA;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,CAAA;IAC5B,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IAC7C,IAAI,MAAW,CAAA;IACf,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QAC7B,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IAC5F,CAAC,CAAC,CAAA;IACF,MAAM,EAAE,GAAG,SAAS,EAAE,KAAK,CAAA;IAC3B,yDAAyD;IACzD,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE;QAAE,OAAO,SAAS,CAAA;IACpC,4EAA4E;IAC5E,4DAA4D;IAC5D,IAAI,GAAyC,CAAA;IAC7C,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,CAAC,kBAAkB,EAAE,EAAE,EAAE,SAA6G,CAAA;QACzJ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YACvC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;YAC/C,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;YAC/C,IAAI,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;YAClB,IAAI,KAAK,GAAG,QAAQ,CAAA;YACpB,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;gBACrB,IAAI,CAAC,CAAC,EAAE,QAAQ,IAAI,CAAC,CAAC,CAAC,SAAS;oBAAE,SAAQ;gBAC1C,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;gBAC7D,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC;oBAAC,KAAK,GAAG,CAAC,CAAC;oBAAC,IAAI,GAAG,CAAC,CAAA;gBAAC,CAAC,CAAC,+BAA+B;YACxE,CAAC;YACD,IAAI,IAAI,EAAE,SAAS;gBAAE,GAAG,GAAG,IAAI,CAAC,SAAS,CAAA;QAC3C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,qCAAqC,CAAC,CAAC;IACjD,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAA;IAC1B,oDAAoD;IACpD,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;IAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;IAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAA;IAC1B,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAA;IACpC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAA;IACpC,yDAAyD;IACzD,0BAA0B;IAC1B,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAClD,MAAM,OAAO,GAAG,aAAa,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IAC/C,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,CAAA;AACnC,CAAC;AAED,gFAAgF;AAChF,MAAM,YAAY,GAAkC;IAClD,GAAG,EAAE,QAAQ,EAAO,cAAc;IAClC,MAAM,EAAE,QAAQ,EAAI,QAAQ;IAC5B,IAAI,EAAE,QAAQ,EAAM,eAAe;IACnC,IAAI,EAAE,QAAQ,EAAM,UAAU;IAC9B,KAAK,EAAE,QAAQ,EAAK,QAAQ;IAC5B,IAAI,EAAE,QAAQ,CAAM,QAAQ;CAC7B,CAAA;AAED,MAAM,mBAAmB,GAA+D;IACtF,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;IAC5B,MAAM,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;IAC/B,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;IAC7B,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;IAC7B,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;IAC9B,IAAI,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;CAC9B,CAAA;AAED,MAAM,OAAO,WAAY,SAAQ,eAAe;IACtC,cAAc,CAAc;IAC5B,QAAQ,CAAa;IAC7B,8DAA8D;IACtD,WAAW,CAAqB;IACxC,wEAAwE;IAChE,eAAe,GAA4B,IAAI,GAAG,EAAE,CAAA;IAC5D,6EAA6E;IACrE,gBAAgB,GAA4C,IAAI,GAAG,EAAE,CAAA;IAErE,oBAAoB,CAAC,QAAgB;QAC3C,IAAI,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC3C,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,CAAC,GAAG,IAAI,KAAK,CAAC,oBAAoB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAA;YACvE,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAA;QACxC,CAAC;QACD,OAAO,CAAC,CAAA;IACV,CAAC;IAEO,qBAAqB;QAC3B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE;YAAE,CAAC,CAAC,OAAO,EAAE,CAAA;QAC3D,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAA;IAC/B,CAAC;IAED,KAAK;QACH,KAAK,CAAC,KAAK,EAAE,CAAA;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,KAAY,CAAA;QACzC,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,IAAI,GAAG,CAAA;QAC5B,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,GAAG,CAAA;QAE7B,+DAA+D;QAC/D,MAAM,OAAO,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAA;QACtD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;QACjC,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,oBAAoB,CAAC;YAC5C,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI;YAClE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,EAAE,IAAI;SAC5C,CAAC,CAAA;QACF,IAAI,CAAC,QAAQ,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;QAC/C,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,GAAG,CAAC,CAAA;QACxC,IAAI,CAAC,QAAQ,CAAC,aAAa,GAAG,IAAI,CAAA;QAClC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAEhC,4DAA4D;QAC5D,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,CAAA;QACxC,MAAM,UAAU,GAAG,IAAI,KAAK,CAAC,iBAAiB,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAA;QACvE,IAAI,CAAC,WAAW,GAAG,IAAI,KAAK,CAAC,YAAY,CAAC,IAAI,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,CAAA;QACvF,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,GAAG,CAAC,CAAA;QAC3C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAEnC,6DAA6D;QAC7D,IAAI,CAAC,cAAc,GAAG,IAAI,KAAK,CAAC,KAAK,EAAE,CAAA;QACvC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,CAAA;QAC1C,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;QACtC,IAAI,CAAC,gBAAgB,EAAE,CAAA;IACzB,CAAC;IAED,MAAM;QACJ,KAAK,CAAC,MAAM,EAAE,CAAA;QACd,IAAI,CAAC,gBAAgB,EAAE,CAAA;IACzB,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAC,MAAe;QAC5B,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;YAC7C,IAAI,IAAI;gBAAE,OAAO,IAAI,CAAA;QACvB,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED;oEACgE;IACxD,SAAS;QACf,MAAM,GAAG,GAAI,IAAI,CAAC,SAAS,CAAC,KAAa,EAAE,SAAS,CAAA;QACpD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,IAAI,CAAC;gBAAC,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;IAClC,CAAC;IAED;uBACmB;IACX,YAAY;QAClB,MAAM,GAAG,GAAI,IAAI,CAAC,SAAS,CAAC,KAAa,EAAE,WAAW,CAAA;QACtD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,IAAI,CAAC;gBAAC,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;IACrD,CAAC;IAEO,iBAAiB;QACvB,IAAI,CAAC,IAAI,CAAC,WAAW;YAAE,OAAM;QAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,QAAmC,CAAA;QAC9D,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAA;QACjC,CAAC,CAAC,WAAW,GAAG,IAAI,CAAA;IACtB,CAAC;IAED,qEAAqE;IAC7D,cAAc;QACpB,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,OAAM;QAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAsC,CAAA;QAC9D,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;QAC1B,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACf,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QAClB,CAAC,CAAC,WAAW,GAAG,IAAI,CAAA;IACtB,CAAC;IAEO,gBAAgB;QACtB,MAAM,CAAC,GAAG,IAAI,CAAC,cAAc,CAAA;QAC7B,IAAI,CAAC,CAAC;YAAE,OAAM;QACd,sDAAsD;QACtD,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;QAErD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAiC,CAAA;QACxD,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,CAAA;QACtC,IAAI,KAAK,KAAK,CAAC;YAAE,OAAM;QAEvB,MAAM,KAAK,GAAG,SAAS,CAAC,KAAY,CAAA;QACpC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,IAAI,GAAG,CAAA;QAChC,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,IAAI,GAAG,CAAA;QACjC,MAAM,OAAO,GAAI,KAAK,CAAC,YAA6B,IAAI,KAAK,CAAA;QAC7D,MAAM,MAAM,GAAI,KAAK,CAAC,aAA+B,IAAI,KAAK,CAAA;QAE9D,0CAA0C;QAC1C,MAAM,GAAG,GAAG,mBAAmB,CAAC,MAAM,CAAC,IAAI,mBAAmB,CAAC,GAAG,CAAA;QAClE,MAAM,EAAE,GAAG,KAAK,CAAC,YAAY,IAAI,GAAG,CAAC,CAAC,CAAA;QACtC,MAAM,EAAE,GAAG,KAAK,CAAC,aAAa,IAAI,GAAG,CAAC,CAAC,CAAA;QACvC,MAAM,EAAE,GAAG,KAAK,CAAC,YAAY,IAAI,GAAG,CAAC,CAAC,CAAA;QACtC,MAAM,GAAG,GAAG,KAAK,CAAC,UAAU,IAAI,EAAE,CAAA,CAAG,kEAAkE;QAEvG,MAAM,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;QACtD,2DAA2D;QAC3D,oDAAoD;QACpD,MAAM,kBAAkB,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC,GAAG,CAAA;QACnE,IAAI,CAAC,qBAAqB,EAAE,CAAA;QAC5B,MAAM,YAAY,GAAG,CAAC,MAAW,EAAU,EAAE;YAC3C,MAAM,WAAW,GAAI,SAAiB,CAAC,kBAAkB,EAAE,CAAC,MAAM,CAAC,CAAA;YACnE,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9D,IAAI,CAAC;oBAAC,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,CAAA;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;YAClF,CAAC;YACD,OAAO,kBAAkB,CAAA;QAC3B,CAAC,CAAA;QAED,mEAAmE;QACnE,2DAA2D;QAC3D,MAAM,WAAW,GAAG,KAAK,CAAC,gBAAgB,CAAA;QAC1C,MAAM,SAAS,GAAG,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC;YAC5E,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,EAAE,CAAC,CAAC;YAC3C,CAAC,CAAC,SAAS,CAAA;QACb,sDAAsD;QACtD,MAAM,QAAQ,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;QAC1C,MAAM,SAAS,GAAG,qBAAqB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAA;QAClI,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAA;QAC5B,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAA;QACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;YACtB,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;YACzB,MAAM,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;YACrC,MAAM,GAAG,GAAG,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAA;YAC/C,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;YACtC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;YAChC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;YACtB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAA;YACzB,+DAA+D;YAC/D,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAA;YAC1B,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;gBAChB,IAAI,CAAC,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAA;gBACpC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAA;YAC7C,CAAC;YACD,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACb,CAAC;IACH,CAAC;IAED,iEAAiE;IACjE,iBAAiB,CAAC,QAAgB;QAChC,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAC3C,CAAC;IAED,2DAA2D;IACnD,gBAAgB,CAAC,MAAqB,EAAE,CAAS,EAAE,CAAS,EAAE,CAAS;QAC7E,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAA;YACjC,OAAO,IAAI,KAAK,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;QAC1D,CAAC;QACD,+BAA+B;QAC/B,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YAC3C,OAAO,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAA;QAC5D,CAAC;QACD,OAAO,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IACvC,CAAC;IAED;;;;OAIG;IACH,WAAW;QACT,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,KAAY,CAAA;QACzC,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;QAC/D,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAsC,CAAA;YAC9D,CAAC,CAAC,OAAO,GAAG,IAAI,GAAG,KAAK,CAAA;YACxB,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC,CAAA;YAC7B,CAAC,CAAC,WAAW,GAAG,IAAI,CAAA;QACtB,CAAC;QACD,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC;gBACjD,MAAM,IAAI,GAAG,KAAmB,CAAA;gBAChC,MAAM,CAAC,GAAG,IAAI,CAAC,QAAsC,CAAA;gBACrD,IAAI,CAAC,CAAC;oBAAE,SAAQ;gBAChB,CAAC,CAAC,OAAO,GAAG,KAAK,CAAA;gBACjB,CAAC,CAAC,WAAW,GAAG,KAAK,GAAG,CAAC,CAAA;gBACzB,CAAC,CAAC,WAAW,GAAG,IAAI,CAAA;YACtB,CAAC;QACH,CAAC;IACH,CAAC;IAED,eAAe;QACb,0DAA0D;QAC1D,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,KAAY,CAAA;YACzC,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,IAAI,GAAG,CAAA;YAC5B,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,GAAG,CAAA;YAC7B,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAA;YAChC,IAAI,CAAC,QAAQ,CAAC,QAAQ,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAA;YAC/D,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAA;gBACnC,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG,IAAI,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;YAC7E,CAAC;QACH,CAAC;QACD,IAAI,CAAC,gBAAgB,EAAE,CAAA;IACzB,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,KAA8B,EAAE,MAA+B;QACtE,IAAI,OAAO,IAAI,KAAK,IAAI,QAAQ,IAAI,KAAK,EAAE,CAAC;YAC1C,IAAI,CAAC,eAAe,EAAE,CAAA;YACtB,OAAM;QACR,CAAC;QACD,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;YACrB,IAAI,CAAC,WAAW,EAAE,CAAA;YAClB,OAAM;QACR,CAAC;QACD,IAAI,WAAW,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,cAAc,EAAE,CAAA;YACrB,2DAA2D;YAC3D,IAAK,IAAI,CAAC,SAAS,CAAC,KAAa,CAAC,WAAW,IAAI,IAAI;gBAAE,IAAI,CAAC,iBAAiB,EAAE,CAAA;YAC/E,OAAM;QACR,CAAC;QACD,IAAI,aAAa,IAAI,KAAK,EAAE,CAAC;YAC3B,IAAI,CAAC,iBAAiB,EAAE,CAAA;YACxB,OAAM;QACR,CAAC;QACD,MAAM,WAAW,GAAG;YAClB,MAAM;YACN,cAAc,EAAE,eAAe;YAC/B,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,YAAY;YAC7D,UAAU,EAAE,kBAAkB,EAAE,YAAY;SAC7C,CAAA;QACD,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC,gBAAgB,EAAE,CAAA;YACvB,OAAM;QACR,CAAC;QACD,KAAK,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IACjC,CAAC;CACF","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'\nimport { computeStackPositions } from '@operato/scene-base'\n\nimport type Stockpile from './stockpile.js'\nimport type { StackPattern, CarrierPreset } from './stockpile.js'\n\nconst PAD_DEPTH = 2\n\n/**\n * 그래프(root.__flowGraph)에서 이 stockpile 로 *들어오는* 노드(입구)를 찾아, 적치를 *입구\n * 맞은편부터* 하도록 reverseX/Z 를 산출한다. storage 가 conveyance 를 import 하지 않고\n * 캐시 속성만 일반적으로 읽음(토폴로지 viz 와 동일 방식). 입구/그래프 없으면 undefined →\n * 기본(-x/-z 모서리부터). 입구 방향은 stockpile local frame 기준(회전 반영).\n */\nfunction inflowFillOpts(stockpile: any): { advanceAlongX?: boolean; reverse?: boolean } | undefined {\n const root = stockpile?.root\n // 로드 직후(sim 전)엔 그래프 캐시가 없을 수 있다 — conveyance 가 globalThis 에 심은\n // 빌더로 즉석 build(토폴로지 viz 와 동일). 없으면(컨베이어 미로드) 기본값.\n if (root && !root.__flowGraph) {\n try { (globalThis as any).__operatoBuildFlowGraph?.(root) } catch { /* ignore */ }\n }\n const cache = root?.__flowGraph\n const out = cache?.graph?.out as Map<string, Array<string | null>> | undefined\n const comps = cache?.components as Map<string, any> | undefined\n // 그래프 빌더(flow-graph-coordinator collect)와 *동일* idOf — refid 는 set('refid') 로\n // state.refid 에 저장되므로 c.refid 와 state.refid 를 둘 다 확인해야 한다. (c.refid 만 보면\n // 명시 id 없는 stockpile 이 전부 undefined → bail → 기본값으로 떨어져 입구 도출 실패.)\n const idOf = (c: any): string | undefined => {\n const raw = c?.state?.id\n if (typeof raw === 'string' && raw.length > 0) return raw\n const refid = c?.refid ?? c?.state?.refid\n return refid != null ? String(refid) : undefined\n }\n const myId = idOf(stockpile)\n if (!out || !comps || !myId) return undefined\n let feeder: any\n out.forEach((targets, srcId) => {\n if (!feeder && Array.isArray(targets) && targets.includes(myId)) feeder = comps.get(srcId)\n })\n const ss = stockpile?.state\n // feeder(입구) 못 찾으면 기본값(undefined) — 마주한 슈트 없는 stockpile.\n if (!feeder || !ss) return undefined\n // 입구 흐름 = *소스 링크의 방향* — feeder(슈트)의 배출 anchor(이 stockpile 로 향하는) direction.\n // (중심-중심 벡터가 아니라 링크 방향면을 써야 정확. 긴 슈트의 중심은 실제 유입면과 다를 수 있음.)\n let dir: { x: number; z: number } | undefined\n try {\n const outs = feeder.getSegmentTopology?.()?.outbounds as Array<{ worldPos?: { x: number; z: number }; direction?: { x: number; z: number } }> | undefined\n if (Array.isArray(outs) && outs.length) {\n const sx = (ss.left ?? 0) + (ss.width ?? 0) / 2\n const sz = (ss.top ?? 0) + (ss.height ?? 0) / 2\n let best = outs[0]\n let bestD = Infinity\n for (const a of outs) {\n if (!a?.worldPos || !a.direction) continue\n const d = (a.worldPos.x - sx) ** 2 + (a.worldPos.z - sz) ** 2\n if (d < bestD) { bestD = d; best = a } // stockpile 에 가장 가까운 배출 anchor\n }\n if (best?.direction) dir = best.direction\n }\n } catch { /* topology 못 얻으면 fallback 없음 → 기본 */ }\n if (!dir) return undefined\n // 흐름 방향(world)을 stockpile local frame 으로 (회전 -rot).\n const rot = typeof ss.rotation === 'number' ? ss.rotation : 0\n const cos = Math.cos(-rot)\n const sin = Math.sin(-rot)\n const lx = dir.x * cos - dir.z * sin\n const lz = dir.x * sin + dir.z * cos\n // 흐름이 x 우세면 x축 진행. items 는 흐름 방향 끝(먼저 닿는 곳)부터 쌓여 입구쪽으로 →\n // 흐름이 + 면 + 끝부터(reverse).\n const advanceAlongX = Math.abs(lx) >= Math.abs(lz)\n const reverse = advanceAlongX ? lx > 0 : lz > 0\n return { advanceAlongX, reverse }\n}\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 // stackHeightLimit = *총 적치 높이*(scene unit) — 단(layer) 개수가 아니다. 아이템\n // 한 단 높이(cd)로 나눠 최대 단 수로 환산해 전달. 예: 한도 60 + 아이템높이 10 → 6단.\n const heightLimit = state.stackHeightLimit\n const maxLayers = typeof heightLimit === 'number' && heightLimit > 0 && cd > 0\n ? Math.max(1, Math.floor(heightLimit / cd))\n : undefined\n // 입구 맞은편부터 채우기 — 그래프에서 이 stockpile 로 들어오는 노드(입구)를 도출.\n const fillOpts = inflowFillOpts(stockpile)\n const positions = computeStackPositions(pattern, count, { w: areaW, h: areaH }, { w: cw, h: ch, d: cd }, gap, maxLayers, fillOpts)\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 /** 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"]}
|
|
@@ -143,7 +143,11 @@ export class StockpileGrid3D extends RealObjectGroup {
|
|
|
143
143
|
const ch = state.carrierHeight ?? def.h;
|
|
144
144
|
const cd = state.carrierDepth ?? def.d;
|
|
145
145
|
const gap = state.carrierGap ?? 10;
|
|
146
|
-
|
|
146
|
+
// stackHeightLimit = *총 적치 높이*(scene unit) → 단(layer) 수로 환산 (아이템 한 단 = cd).
|
|
147
|
+
const rawHeightLimit = state.stackHeightLimit;
|
|
148
|
+
const heightLimit = typeof rawHeightLimit === 'number' && rawHeightLimit > 0 && cd > 0
|
|
149
|
+
? Math.max(1, Math.floor(rawHeightLimit / cd))
|
|
150
|
+
: undefined;
|
|
147
151
|
const cellW = grid.cellW;
|
|
148
152
|
const cellH = grid.cellH;
|
|
149
153
|
const geom = this._carrierGeometry(preset, cw, ch, cd);
|
|
@@ -1 +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"]}
|
|
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 // stackHeightLimit = *총 적치 높이*(scene unit) → 단(layer) 수로 환산 (아이템 한 단 = cd).\n const rawHeightLimit = state.stackHeightLimit as number | undefined\n const heightLimit = typeof rawHeightLimit === 'number' && rawHeightLimit > 0 && cd > 0\n ? Math.max(1, Math.floor(rawHeightLimit / cd))\n : 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"]}
|
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?.();
|