@operato/property-panel 10.0.0-beta.40 → 10.0.0-beta.41
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
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [10.0.0-beta.41](https://github.com/hatiolab/operato/compare/v10.0.0-beta.40...v10.0.0-beta.41) (2026-04-18)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### :rocket: New Features
|
|
10
|
+
|
|
11
|
+
* **property-panel:** environment + light mood 2-tier 프리셋 구조로 재설계 ([226bbab](https://github.com/hatiolab/operato/commit/226bbabbe8f198936d88e7d7c01b6365f910a71d))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
6
15
|
## [10.0.0-beta.40](https://github.com/hatiolab/operato/compare/v10.0.0-beta.39...v10.0.0-beta.40) (2026-04-18)
|
|
7
16
|
|
|
8
17
|
|
|
@@ -35,9 +35,23 @@ export declare class PropertyScene3D extends AbstractProperty {
|
|
|
35
35
|
private _renderPlacement;
|
|
36
36
|
private _renderMode;
|
|
37
37
|
private _renderRenderer;
|
|
38
|
+
/**
|
|
39
|
+
* Environment 드롭다운 — 씬의 공간적 맥락을 정의.
|
|
40
|
+
* 선택 시 sky 값과 함께 ENVIRONMENT_DEFAULTS의 기본 조명까지 한 번에 적용한다.
|
|
41
|
+
* "원클릭 전체 look" — 사용자가 원하면 Light Mood/원자 컨트롤로 위에 얹어 조정.
|
|
42
|
+
*/
|
|
38
43
|
private _renderSky;
|
|
44
|
+
/**
|
|
45
|
+
* Environment 선택 핸들러 — sky 필드만 바꾸는 게 아니라 ENVIRONMENT_DEFAULTS에
|
|
46
|
+
* 정의된 hemi/dir 기본 조명까지 한 번의 property-change로 함께 적용한다.
|
|
47
|
+
*/
|
|
48
|
+
private _onEnvironmentChange;
|
|
39
49
|
private _renderHemisphereLight;
|
|
40
50
|
private _renderKeyLight;
|
|
51
|
+
/**
|
|
52
|
+
* Light Mood — Environment가 설정한 기본 조명 위에 얹는 분위기 오버라이드.
|
|
53
|
+
* sky는 건드리지 않고 hemi/dir 값만 적용. Environment와 독립적으로 조합 가능.
|
|
54
|
+
*/
|
|
41
55
|
private _renderLightingPresets;
|
|
42
56
|
private _onPresetChange;
|
|
43
57
|
private _renderFloor;
|
|
@@ -9,15 +9,67 @@ import { css, html } from 'lit';
|
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { PropertyGridStyles } from '@operato/styles/property-grid-styles.js';
|
|
11
11
|
import { AbstractProperty } from '../abstract-property.js';
|
|
12
|
+
/**
|
|
13
|
+
* Environment별 기본 조명 프로파일.
|
|
14
|
+
* Environment 드롭다운에서 선택 시 sky 값과 함께 이 조명 필드들이 자동 적용된다.
|
|
15
|
+
* Light Mood(아래)는 이 위에 얹는 오버라이드 역할.
|
|
16
|
+
*/
|
|
17
|
+
const ENVIRONMENT_DEFAULTS = {
|
|
18
|
+
// 실내
|
|
19
|
+
studio: {
|
|
20
|
+
hemiSkyColor: '#ffffff', hemiGroundColor: '#888888', hemiIntensity: 3.0,
|
|
21
|
+
dirLightEnabled: true, dirLightColor: '#ffffff', dirLightIntensity: 2.0,
|
|
22
|
+
dirLightFollowCamera: true
|
|
23
|
+
},
|
|
24
|
+
warehouse: {
|
|
25
|
+
hemiSkyColor: '#e0e4ea', hemiGroundColor: '#707880', hemiIntensity: 2.5,
|
|
26
|
+
dirLightEnabled: true, dirLightColor: '#f8fafc', dirLightIntensity: 1.8,
|
|
27
|
+
dirLightFollowCamera: true
|
|
28
|
+
},
|
|
29
|
+
factory: {
|
|
30
|
+
hemiSkyColor: '#d8dce2', hemiGroundColor: '#606870', hemiIntensity: 2.0,
|
|
31
|
+
dirLightEnabled: true, dirLightColor: '#e8eef2', dirLightIntensity: 2.0,
|
|
32
|
+
dirLightFollowCamera: true
|
|
33
|
+
},
|
|
34
|
+
office: {
|
|
35
|
+
hemiSkyColor: '#ffffff', hemiGroundColor: '#aaaaaa', hemiIntensity: 3.0,
|
|
36
|
+
dirLightEnabled: true, dirLightColor: '#ffffff', dirLightIntensity: 1.5,
|
|
37
|
+
dirLightFollowCamera: true
|
|
38
|
+
},
|
|
39
|
+
home: {
|
|
40
|
+
hemiSkyColor: '#ffe8c8', hemiGroundColor: '#7a5a40', hemiIntensity: 2.0,
|
|
41
|
+
dirLightEnabled: true, dirLightColor: '#ffd8a0', dirLightIntensity: 1.5,
|
|
42
|
+
dirLightFollowCamera: true
|
|
43
|
+
},
|
|
44
|
+
// 실외 (날씨)
|
|
45
|
+
sunny: {
|
|
46
|
+
hemiSkyColor: '#87ceeb', hemiGroundColor: '#8b7355', hemiIntensity: 2.0,
|
|
47
|
+
dirLightEnabled: true, dirLightColor: '#fff4cf', dirLightIntensity: 3.0,
|
|
48
|
+
dirLightFollowCamera: false, dirLightAzimuth: 135, dirLightElevation: 60
|
|
49
|
+
},
|
|
50
|
+
cloudy: {
|
|
51
|
+
hemiSkyColor: '#c8cbd0', hemiGroundColor: '#9ba1a8', hemiIntensity: 3.0,
|
|
52
|
+
dirLightEnabled: true, dirLightColor: '#e8e8e8', dirLightIntensity: 0.6,
|
|
53
|
+
dirLightFollowCamera: false, dirLightAzimuth: 120, dirLightElevation: 50
|
|
54
|
+
},
|
|
55
|
+
rainy: {
|
|
56
|
+
hemiSkyColor: '#8a909a', hemiGroundColor: '#4a4f55', hemiIntensity: 1.5,
|
|
57
|
+
dirLightEnabled: true, dirLightColor: '#b8c0c8', dirLightIntensity: 0.3,
|
|
58
|
+
dirLightFollowCamera: false, dirLightAzimuth: 110, dirLightElevation: 40
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Light Mood 프리셋 — Environment 기본값 위에 얹는 분위기 오버라이드.
|
|
63
|
+
* Environment(지금 씬이 어디에 있는가)와 독립적으로 작동하며 sky는 건드리지 않는다.
|
|
64
|
+
* 원자 조명 필드(hemi/dir)만 세팅.
|
|
65
|
+
*/
|
|
12
66
|
const LIGHTING_PRESETS = {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Dramatic: { hemiIntensity: 0.15, dirLightEnabled: true, dirLightColor: '#ffffff', dirLightIntensity: 2.5 },
|
|
20
|
-
Flat: { hemiIntensity: 2.0, dirLightEnabled: false, dirLightColor: '#ffffff', dirLightIntensity: 0 }
|
|
67
|
+
Bright: { hemiIntensity: 3.0, dirLightEnabled: true, dirLightColor: '#ffffff', dirLightIntensity: 2.5 },
|
|
68
|
+
Dim: { hemiIntensity: 0.5, dirLightEnabled: true, dirLightColor: '#fff5e0', dirLightIntensity: 0.5 },
|
|
69
|
+
Warm: { hemiIntensity: 1.5, dirLightEnabled: true, dirLightColor: '#ffaa55', dirLightIntensity: 2.0 },
|
|
70
|
+
Cool: { hemiIntensity: 1.5, dirLightEnabled: true, dirLightColor: '#88bbff', dirLightIntensity: 2.0 },
|
|
71
|
+
Dramatic: { hemiIntensity: 0.3, dirLightEnabled: true, dirLightColor: '#ffffff', dirLightIntensity: 3.0 },
|
|
72
|
+
Flat: { hemiIntensity: 3.0, dirLightEnabled: false, dirLightColor: '#ffffff', dirLightIntensity: 0 }
|
|
21
73
|
};
|
|
22
74
|
/**
|
|
23
75
|
* Scene-level 3D settings for model-layer.
|
|
@@ -197,23 +249,45 @@ export class PropertyScene3D extends AbstractProperty {
|
|
|
197
249
|
</fieldset>
|
|
198
250
|
`;
|
|
199
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* Environment 드롭다운 — 씬의 공간적 맥락을 정의.
|
|
254
|
+
* 선택 시 sky 값과 함께 ENVIRONMENT_DEFAULTS의 기본 조명까지 한 번에 적용한다.
|
|
255
|
+
* "원클릭 전체 look" — 사용자가 원하면 Light Mood/원자 컨트롤로 위에 얹어 조정.
|
|
256
|
+
*/
|
|
200
257
|
_renderSky(value) {
|
|
201
|
-
const
|
|
202
|
-
{ value: '', label: 'None' },
|
|
203
|
-
{ value: 'color', label: 'Color' },
|
|
204
|
-
{ value: 'studio', label: 'Studio' },
|
|
205
|
-
{ value: 'warehouse', label: 'Warehouse' },
|
|
206
|
-
{ value: 'factory', label: 'Factory' },
|
|
207
|
-
{ value: 'office', label: 'Office' },
|
|
208
|
-
{ value: 'home', label: 'Home' },
|
|
258
|
+
const envOptions = [
|
|
259
|
+
{ value: '', label: 'None', group: 'basic' },
|
|
260
|
+
{ value: 'color', label: 'Color', group: 'basic' },
|
|
261
|
+
{ value: 'studio', label: 'Studio', group: 'indoor' },
|
|
262
|
+
{ value: 'warehouse', label: 'Warehouse', group: 'indoor' },
|
|
263
|
+
{ value: 'factory', label: 'Factory', group: 'indoor' },
|
|
264
|
+
{ value: 'office', label: 'Office', group: 'indoor' },
|
|
265
|
+
{ value: 'home', label: 'Home', group: 'indoor' },
|
|
266
|
+
{ value: 'sunny', label: 'Sunny', group: 'outdoor' },
|
|
267
|
+
{ value: 'cloudy', label: 'Cloudy', group: 'outdoor' },
|
|
268
|
+
{ value: 'rainy', label: 'Rainy', group: 'outdoor' }
|
|
209
269
|
];
|
|
210
270
|
return html `
|
|
211
271
|
<fieldset>
|
|
212
|
-
<legend>
|
|
272
|
+
<legend>Environment</legend>
|
|
213
273
|
<div class="property-grid">
|
|
214
274
|
<label>Preset</label>
|
|
215
|
-
<select
|
|
216
|
-
|
|
275
|
+
<select @change=${this._onEnvironmentChange}>
|
|
276
|
+
<optgroup label="Basic">
|
|
277
|
+
${envOptions
|
|
278
|
+
.filter(o => o.group === 'basic')
|
|
279
|
+
.map(o => html `<option value=${o.value} ?selected=${(value.sky || '') === o.value}>${o.label}</option>`)}
|
|
280
|
+
</optgroup>
|
|
281
|
+
<optgroup label="Indoor">
|
|
282
|
+
${envOptions
|
|
283
|
+
.filter(o => o.group === 'indoor')
|
|
284
|
+
.map(o => html `<option value=${o.value} ?selected=${(value.sky || '') === o.value}>${o.label}</option>`)}
|
|
285
|
+
</optgroup>
|
|
286
|
+
<optgroup label="Outdoor">
|
|
287
|
+
${envOptions
|
|
288
|
+
.filter(o => o.group === 'outdoor')
|
|
289
|
+
.map(o => html `<option value=${o.value} ?selected=${(value.sky || '') === o.value}>${o.label}</option>`)}
|
|
290
|
+
</optgroup>
|
|
217
291
|
</select>
|
|
218
292
|
|
|
219
293
|
${value.sky === 'color'
|
|
@@ -226,6 +300,24 @@ export class PropertyScene3D extends AbstractProperty {
|
|
|
226
300
|
</fieldset>
|
|
227
301
|
`;
|
|
228
302
|
}
|
|
303
|
+
/**
|
|
304
|
+
* Environment 선택 핸들러 — sky 필드만 바꾸는 게 아니라 ENVIRONMENT_DEFAULTS에
|
|
305
|
+
* 정의된 hemi/dir 기본 조명까지 한 번의 property-change로 함께 적용한다.
|
|
306
|
+
*/
|
|
307
|
+
_onEnvironmentChange(e) {
|
|
308
|
+
const select = e.target;
|
|
309
|
+
const sky = select.value;
|
|
310
|
+
const detail = { sky };
|
|
311
|
+
const defaults = ENVIRONMENT_DEFAULTS[sky];
|
|
312
|
+
if (defaults) {
|
|
313
|
+
Object.assign(detail, defaults);
|
|
314
|
+
}
|
|
315
|
+
this.dispatchEvent(new CustomEvent('property-change', {
|
|
316
|
+
bubbles: true,
|
|
317
|
+
composed: true,
|
|
318
|
+
detail
|
|
319
|
+
}));
|
|
320
|
+
}
|
|
229
321
|
_renderHemisphereLight(value) {
|
|
230
322
|
var _a, _b;
|
|
231
323
|
return html `
|
|
@@ -352,12 +444,16 @@ export class PropertyScene3D extends AbstractProperty {
|
|
|
352
444
|
</fieldset>
|
|
353
445
|
`;
|
|
354
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* Light Mood — Environment가 설정한 기본 조명 위에 얹는 분위기 오버라이드.
|
|
449
|
+
* sky는 건드리지 않고 hemi/dir 값만 적용. Environment와 독립적으로 조합 가능.
|
|
450
|
+
*/
|
|
355
451
|
_renderLightingPresets() {
|
|
356
452
|
return html `
|
|
357
453
|
<fieldset>
|
|
358
|
-
<legend>
|
|
454
|
+
<legend>Light Mood</legend>
|
|
359
455
|
<div class="property-grid">
|
|
360
|
-
<label>
|
|
456
|
+
<label>Apply</label>
|
|
361
457
|
<select @change=${this._onPresetChange}>
|
|
362
458
|
<option value="" selected>Select...</option>
|
|
363
459
|
${Object.keys(LIGHTING_PRESETS).map(name => html `<option value=${name}>${name}</option>`)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"property-scene3d.js","sourceRoot":"","sources":["../../../../src/property-panel/threed/property-scene3d.ts"],"names":[],"mappings":"AAAA;;GAEG;;AAEH,OAAO,kCAAkC,CAAA;AACzC,OAAO,0BAA0B,CAAA;AAEjC,OAAO,0BAA0B,CAAA;AAEjC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAA;AAC/B,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAG5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AAE5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAE1D,MAAM,gBAAgB,GAA4C;IAChE,OAAO,EAAG,EAAE,aAAa,EAAE,GAAG,EAAG,eAAe,EAAE,IAAI,EAAG,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,EAAE;IAC3G,MAAM,EAAI,EAAE,aAAa,EAAE,GAAG,EAAG,eAAe,EAAE,IAAI,EAAG,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,EAAE;IAC3G,MAAM,EAAI,EAAE,aAAa,EAAE,GAAG,EAAG,eAAe,EAAE,IAAI,EAAG,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,EAAE;IAC3G,GAAG,EAAO,EAAE,aAAa,EAAE,GAAG,EAAG,eAAe,EAAE,IAAI,EAAG,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,EAAE;IAC3G,IAAI,EAAM,EAAE,aAAa,EAAE,GAAG,EAAG,eAAe,EAAE,IAAI,EAAG,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,EAAE;IAC3G,IAAI,EAAM,EAAE,aAAa,EAAE,GAAG,EAAG,eAAe,EAAE,IAAI,EAAG,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,EAAE;IAC3G,QAAQ,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAG,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,EAAE;IAC3G,IAAI,EAAM,EAAE,aAAa,EAAE,GAAG,EAAG,eAAe,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC,EAAE;CAC1G,CAAA;AAED;;;GAGG;AACH,MAAM,OAAO,eAAgB,SAAQ,gBAAgB;IAArD;;QAgD8B,UAAK,GAAiB,IAAI,CAAA;IAsZxD,CAAC;IApZC,MAAM;QACJ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAA;QAE9B,OAAO,IAAI,CAAA;QACP,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC;QACvD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;QACzB,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;QACrD,IAAI,CAAC,sBAAsB,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,sBAAsB,EAAE;QAClG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC;KAC3B,CAAA;IACH,CAAC;IAED;;;;OAIG;IACK,aAAa,CAAC,KAAiB;;QACrC,MAAM,KAAK,GAAG;YACZ,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE;YAC9C,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;YAC9B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;YAClC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;YAChC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;YAClC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;SACjC,CAAA;QACD,MAAM,WAAW,GAAI,KAAK,CAAC,iBAA4B,IAAI,aAAa,CAAA;QACxE,MAAM,GAAG,GAAG,MAAM,CAAC,MAAA,KAAK,CAAC,GAAG,mCAAI,EAAE,CAAC,CAAA;QACnC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAA,KAAK,CAAC,IAAI,mCAAI,GAAG,CAAC,CAAA;QACtC,MAAM,GAAG,GAAG,MAAM,CAAC,MAAA,KAAK,CAAC,GAAG,mCAAI,KAAK,CAAC,CAAA;QAEtC,OAAO,IAAI,CAAA;;;;;;cAMD,KAAK,CAAC,GAAG,CACT,CAAC,CAAC,EAAE,CAAC,IAAI,CAAA,iBAAiB,CAAC,CAAC,KAAK,cAAc,WAAW,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,WAAW,CAC7F;;;;mFAIsE,MAAM,CAAC,GAAG,CAAC;;;+EAGf,MAAM,CAAC,IAAI,CAAC;;;2EAGhB,MAAM,CAAC,GAAG,CAAC;;;;yCAI7C,IAAI,CAAC,iBAAiB;;;KAG1D,CAAA;IACH,CAAC;IAED;;;OAGG;IACK,iBAAiB;;QACvB,MAAM,GAAG,GAAG,MAAA,MAAC,MAAA,IAAI,CAAC,KAAK,0CAAE,aAAqB,0CAAE,WAAW,0CAAE,gBAAgB,CAAA;QAC7E,IAAI,CAAC,CAAA,GAAG,aAAH,GAAG,uBAAH,GAAG,CAAE,cAAc,CAAA;YAAE,OAAM;QAChC,MAAM,KAAK,GAAG,GAAG,CAAC,cAAc,EAAE,CAAA;QAClC,IAAI,CAAC,KAAK;YAAE,OAAM;QAElB,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,iBAAiB,EAAE;YACjC,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE;gBACN,iBAAiB,EAAE,KAAK,CAAC,IAAI;gBAC7B,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB;SACF,CAAC,CACH,CAAA;IACH,CAAC;IAED;;;;;OAKG;IACK,gBAAgB,CAAC,KAAiB;QACxC,MAAM,OAAO,GAAG;YACd,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,iBAAiB,EAAE;YAC5C,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;YAClC,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,iBAAiB,EAAE;SAChD,CAAA;QACD,MAAM,OAAO,GAAI,KAAK,CAAC,SAAoB,IAAI,OAAO,CAAA;QAEtD,OAAO,IAAI,CAAA;;;;;;cAMD,OAAO,CAAC,GAAG,CACX,CAAC,CAAC,EAAE,CAAC,IAAI,CAAA,iBAAiB,CAAC,CAAC,KAAK,cAAc,OAAO,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,WAAW,CACzF;;;;KAIR,CAAA;IACH,CAAC;IAEO,WAAW,CAAC,KAAiB;QACnC,OAAO,IAAI,CAAA;;;;8EAI+D,CAAC,CAAC,KAAK,CAAC,MAAM;;;;;cAK9E;YACA,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;YAC5B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;YAClC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE;SAC3C,CAAC,GAAG,CACH,CAAC,CAAC,EAAE,CACF,IAAI,CAAA,iBAAiB,CAAC,CAAC,KAAK,cAAc,CAAC,KAAK,CAAC,cAAc,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK;oBAC9E,CAAC,CAAC,KAAK;0BACD,CACb;;;;;;;uBAOU,CAAC,CAAC,KAAK,CAAC,qBAAqB;;;;;KAK/C,CAAA;IACH,CAAC;IAEO,eAAe,CAAC,KAAiB;;QACvC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAA,KAAK,CAAC,QAAQ,mCAAI,GAAG,CAAC,CAAA;QAC9C,OAAO,IAAI,CAAA;;;;oFAIqE,KAAK,CAAC,SAAS,KAAK,KAAK;;;;;cAK/F;YACA,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE;YACjC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE;YACrC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE;SAChC,CAAC,GAAG,CACH,CAAC,CAAC,EAAE,CACF,IAAI,CAAA,iBAAiB,CAAC,CAAC,KAAK,cAAc,CAAC,KAAK,CAAC,SAAS,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,KAAK;oBAC9E,CAAC,CAAC,KAAK;0BACD,CACb;;;;;;;;;;;uBAWU,MAAM,CAAC,QAAQ,CAAC;;oBAEnB,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;;;;KAIlC,CAAA;IACH,CAAC;IAEO,UAAU,CAAC,KAAiB;QAClC,MAAM,UAAU,GAAG;YACjB,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;YAC5B,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;YAClC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;YACpC,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE;YAC1C,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;YACtC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;YACpC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;SACjC,CAAA;QAED,OAAO,IAAI,CAAA;;;;;;cAMD,UAAU,CAAC,GAAG,CACd,CAAC,CAAC,EAAE,CAAC,IAAI,CAAA,iBAAiB,CAAC,CAAC,KAAK,cAAc,CAAC,KAAK,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,WAAW,CACnG;;;YAGD,KAAK,CAAC,GAAG,KAAK,OAAO;YACrB,CAAC,CAAC,IAAI,CAAA;;8DAE4C,KAAK,CAAC,QAAQ,IAAI,SAAS;eAC1E;YACH,CAAC,CAAC,EAAE;;;KAGX,CAAA;IACH,CAAC;IAEO,sBAAsB,CAAC,KAAiB;;QAC9C,OAAO,IAAI,CAAA;;;;;4DAK6C,KAAK,CAAC,YAAY,IAAI,SAAS;;;+DAG5B,KAAK,CAAC,eAAe,IAAI,SAAS;;;;;;;;;;uBAU1E,MAAM,CAAC,MAAA,KAAK,CAAC,aAAa,mCAAI,GAAG,CAAC;;oBAErC,CAAC,MAAA,KAAK,CAAC,aAAa,mCAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;;;;KAItD,CAAA;IACH,CAAC;IAEO,eAAe,CAAC,KAAiB;;QACvC,MAAM,YAAY,GAAG,KAAK,CAAC,oBAAoB,KAAK,KAAK,CAAA;QACzD,MAAM,aAAa,GAAG,KAAK,CAAC,gBAAgB,KAAK,KAAK,CAAA;QACtD,OAAO,IAAI,CAAA;;;;;;;;uBAQQ,KAAK,CAAC,eAAe,KAAK,KAAK;;;;;6DAKO,KAAK,CAAC,aAAa,IAAI,SAAS;;;;;;;;;;uBAUtE,MAAM,CAAC,MAAA,KAAK,CAAC,iBAAiB,mCAAI,GAAG,CAAC;;oBAEzC,CAAC,MAAA,KAAK,CAAC,iBAAiB,mCAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;;;;;;;uBAOxC,YAAY;;;;YAIvB,CAAC,YAAY;YACb,CAAC,CAAC,IAAI,CAAA;;;;;;;;;6BASW,MAAM,CAAC,MAAA,KAAK,CAAC,eAAe,mCAAI,EAAE,CAAC;;0BAEtC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAA,KAAK,CAAC,eAAe,mCAAI,EAAE,CAAW,CAAC;;;;;;;;;;;6BAWhD,MAAM,CAAC,MAAA,KAAK,CAAC,iBAAiB,mCAAI,EAAE,CAAC;;0BAExC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAA,KAAK,CAAC,iBAAiB,mCAAI,EAAE,CAAW,CAAC;;eAEhE;YACH,CAAC,CAAC,EAAE;;;;;;uBAMO,aAAa;;;;YAIxB,aAAa;YACb,CAAC,CAAC,IAAI,CAAA;;;;;;;;;6BASW,MAAM,CAAC,MAAA,KAAK,CAAC,aAAa,mCAAI,CAAC,MAAM,CAAC;;0BAEzC,CAAC,MAAA,KAAK,CAAC,aAAa,mCAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;;eAEtD;YACH,CAAC,CAAC,EAAE;;;KAGX,CAAA;IACH,CAAC;IAEO,sBAAsB;QAC5B,OAAO,IAAI,CAAA;;;;;4BAKa,IAAI,CAAC,eAAe;;cAElC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,GAAG,CACjC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAA,iBAAiB,IAAI,IAAI,IAAI,WAAW,CACrD;;;;KAIR,CAAA;IACH,CAAC;IAEO,eAAe,CAAC,CAAQ;QAC9B,MAAM,MAAM,GAAG,CAAC,CAAC,MAA2B,CAAA;QAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAA;QACzB,IAAI,CAAC,IAAI;YAAE,OAAM;QACjB,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAA;QACrC,IAAI,MAAM;YAAE,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAA;QAC7C,mCAAmC;QACnC,MAAM,CAAC,KAAK,GAAG,EAAE,CAAA;IACnB,CAAC;IAEO,YAAY,CAAC,KAAiB;QACpC,OAAO,IAAI,CAAA;;;iBAGE,KAAK,CAAC,eAAe,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;2BACtC,IAAI,CAAC,sBAAsB;;;KAGjD,CAAA;IACH,CAAC;IAEO,oBAAoB,CAAC,MAA+B;QAC1D,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,iBAAiB,EAAE;YACjC,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,MAAM;SACf,CAAC,CACH,CAAA;IACH,CAAC;IAEO,sBAAsB,CAAC,CAAc;QAC3C,CAAC,CAAC,eAAe,EAAE,CAAA;QACnB,IAAI,CAAC,aAAa,CAChB,IAAI,WAAW,CAAC,iBAAiB,EAAE;YACjC,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,IAAI;YACd,MAAM,EAAE,EAAE,eAAe,EAAE,CAAC,CAAC,MAAM,CAAC,UAAU,EAAE;SACjD,CAAC,CACH,CAAA;IACH,CAAC;;AAncM,sBAAM,GAAG;IACd,kBAAkB;IAClB,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAyCF;CACF,AA5CY,CA4CZ;AAE2B;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8CAAmB;AAClB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;8CAA2B","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@operato/input/ox-input-color.js'\nimport '@operato/i18n/ox-i18n.js'\n\nimport './property-material3d.js'\n\nimport { css, html } from 'lit'\nimport { property } from 'lit/decorators.js'\n\nimport { Properties, Scene } from '@hatiolab/things-scene'\nimport { PropertyGridStyles } from '@operato/styles/property-grid-styles.js'\n\nimport { AbstractProperty } from '../abstract-property.js'\n\nconst LIGHTING_PRESETS: Record<string, Record<string, unknown>> = {\n Neutral: { hemiIntensity: 1.0, dirLightEnabled: true, dirLightColor: '#ffffff', dirLightIntensity: 1.0 },\n Studio: { hemiIntensity: 0.6, dirLightEnabled: true, dirLightColor: '#ffffff', dirLightIntensity: 1.8 },\n Bright: { hemiIntensity: 2.0, dirLightEnabled: true, dirLightColor: '#ffffff', dirLightIntensity: 2.0 },\n Dim: { hemiIntensity: 0.2, dirLightEnabled: true, dirLightColor: '#fff5e0', dirLightIntensity: 0.5 },\n Warm: { hemiIntensity: 0.8, dirLightEnabled: true, dirLightColor: '#ffaa55', dirLightIntensity: 1.5 },\n Cool: { hemiIntensity: 0.8, dirLightEnabled: true, dirLightColor: '#88bbff', dirLightIntensity: 1.5 },\n Dramatic: { hemiIntensity: 0.15, dirLightEnabled: true, dirLightColor: '#ffffff', dirLightIntensity: 2.5 },\n Flat: { hemiIntensity: 2.0, dirLightEnabled: false, dirLightColor: '#ffffff', dirLightIntensity: 0 }\n}\n\n/**\n * Scene-level 3D settings for model-layer.\n * Includes 3D mode, camera, renderer, lighting, presets, and floor configuration.\n */\nexport class PropertyScene3D extends AbstractProperty {\n static styles = [\n PropertyGridStyles,\n css`\n .range-with-value {\n grid-column: 9 / -1;\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .range-with-value input[type='range'] {\n flex: 1;\n border: none;\n background: transparent;\n padding: 0;\n }\n\n .range-with-value span {\n min-width: 2.5em;\n text-align: right;\n font-size: 11px;\n color: var(--md-sys-color-on-secondary-container);\n }\n\n .camera-actions {\n display: flex;\n justify-content: flex-end;\n margin-top: 6px;\n }\n\n .camera-actions button {\n font-size: 12px;\n padding: 4px 10px;\n border: 1px solid var(--md-sys-color-outline, #c4c7c5);\n border-radius: 4px;\n background: var(--md-sys-color-surface, #fff);\n color: var(--md-sys-color-on-surface, #1c1b1f);\n cursor: pointer;\n }\n\n .camera-actions button:hover {\n background: var(--md-sys-color-surface-variant, #e7e0ec);\n }\n `\n ]\n\n @property({ type: Object }) value?: Properties\n @property({ type: Object }) scene: Scene | null = null\n\n render() {\n const value = this.value || {}\n\n return html`\n ${this._renderMode(value)} ${this._renderPlacement(value)}\n ${this._renderCamera(value)}\n ${this._renderRenderer(value)} ${this._renderSky(value)}\n ${this._renderHemisphereLight(value)} ${this._renderKeyLight(value)} ${this._renderLightingPresets()}\n ${this._renderFloor(value)}\n `\n }\n\n /**\n * Camera 초기 설정 — Initial View(뷰 프리셋), FOV/Near/Far, 현재 카메라 저장 버튼.\n * 사용자가 씬을 3D로 돌려본 후 \"이 각도가 마음에 든다\" 싶으면\n * Save Current View로 현재 viewport의 position을 모델에 기록 → 다음 로드 시 같은 각도로 시작.\n */\n private _renderCamera(value: Properties) {\n const views = [\n { value: 'perspective', label: 'Perspective' },\n { value: 'top', label: 'Top' },\n { value: 'front', label: 'Front' },\n { value: 'back', label: 'Back' },\n { value: 'right', label: 'Right' },\n { value: 'left', label: 'Left' }\n ]\n const currentView = (value.initialCameraView as string) || 'perspective'\n const fov = Number(value.fov ?? 45)\n const near = Number(value.near ?? 0.1)\n const far = Number(value.far ?? 20000)\n\n return html`\n <fieldset>\n <legend>Camera</legend>\n <div class=\"property-grid\">\n <label>Initial View</label>\n <select value-key=\"initialCameraView\">\n ${views.map(\n v => html`<option value=${v.value} ?selected=${currentView === v.value}>${v.label}</option>`\n )}\n </select>\n\n <label>FOV</label>\n <input type=\"number\" value-key=\"fov\" step=\"1\" min=\"1\" max=\"170\" .value=${String(fov)} />\n\n <label>Near</label>\n <input type=\"number\" value-key=\"near\" step=\"0.1\" min=\"0.01\" .value=${String(near)} />\n\n <label>Far</label>\n <input type=\"number\" value-key=\"far\" step=\"100\" min=\"1\" .value=${String(far)} />\n </div>\n\n <div class=\"camera-actions\">\n <button type=\"button\" @click=${this._onSaveCameraView}>Save Current View</button>\n </div>\n </fieldset>\n `\n }\n\n /**\n * 현재 3D viewport의 카메라 상태를 모델에 저장한다.\n * scene의 getCameraState를 호출하여 view/cameraX/cameraY/cameraZ를 얻어 property-change로 전파.\n */\n private _onSaveCameraView() {\n const cap = (this.scene?.rootContainer as any)?.model_layer?._threeCapability\n if (!cap?.getCameraState) return\n const state = cap.getCameraState()\n if (!state) return\n\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail: {\n initialCameraView: state.view,\n cameraX: state.cameraX,\n cameraY: state.cameraY,\n cameraZ: state.cameraZ\n }\n })\n )\n }\n\n /**\n * Scene placement 모드 선택 — zPos 해석과 볼륨 origin 방향을 씬 전체에 일관 적용.\n * floor : zPos=바닥 높이, 볼륨이 위로 쌓임 (공장/창고/건축)\n * space : zPos=볼륨 중심 Y, 바닥 개념 없음 (우주/추상/전시)\n * inverted: zPos=천장, 볼륨이 아래로 매달림 (천장 설비, 베타)\n */\n private _renderPlacement(value: Properties) {\n const options = [\n { value: 'floor', label: 'Floor (default)' },\n { value: 'space', label: 'Space' },\n { value: 'inverted', label: 'Inverted (beta)' }\n ]\n const current = (value.placement as string) || 'floor'\n\n return html`\n <fieldset>\n <legend>Placement</legend>\n <div class=\"property-grid\">\n <label>Mode</label>\n <select value-key=\"placement\">\n ${options.map(\n o => html`<option value=${o.value} ?selected=${current === o.value}>${o.label}</option>`\n )}\n </select>\n </div>\n </fieldset>\n `\n }\n\n private _renderMode(value: Properties) {\n return html`\n <fieldset>\n <legend>3D Mode</legend>\n <div class=\"property-grid\">\n <input id=\"cb-threed\" type=\"checkbox\" value-key=\"threed\" .checked=${!!value.threed} />\n <label for=\"cb-threed\"><ox-i18n msgid=\"label.start-in-3d\">Start in 3D</ox-i18n></label>\n\n <label>Viewer Auto</label>\n <select value-key=\"cameraAutoPlay\">\n ${[\n { value: '', label: 'None' },\n { value: 'orbit', label: 'Orbit' },\n { value: 'play', label: 'Play Bookmarks' }\n ].map(\n o =>\n html`<option value=${o.value} ?selected=${(value.cameraAutoPlay || '') === o.value}>\n ${o.label}\n </option>`\n )}\n </select>\n\n <input\n id=\"cb-floor-constraint\"\n type=\"checkbox\"\n value-key=\"cameraFloorConstraint\"\n .checked=${!!value.cameraFloorConstraint}\n />\n <label for=\"cb-floor-constraint\"><ox-i18n msgid=\"label.keep-above-ground\">Keep Above Ground</ox-i18n></label>\n </div>\n </fieldset>\n `\n }\n\n private _renderRenderer(value: Properties) {\n const exposure = Number(value.exposure ?? 1.2)\n return html`\n <fieldset>\n <legend>Renderer</legend>\n <div class=\"property-grid\">\n <input id=\"cb-antialias\" type=\"checkbox\" value-key=\"antialias\" .checked=${value.antialias !== false} />\n <label for=\"cb-antialias\">Anti-alias</label>\n\n <label>Precision</label>\n <select value-key=\"precision\">\n ${[\n { value: 'highp', label: 'High' },\n { value: 'mediump', label: 'Medium' },\n { value: 'lowp', label: 'Low' }\n ].map(\n o =>\n html`<option value=${o.value} ?selected=${(value.precision || 'highp') === o.value}>\n ${o.label}\n </option>`\n )}\n </select>\n\n <label>Exposure</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"0.3\"\n max=\"2.5\"\n step=\"0.05\"\n value-key=\"exposure\"\n .value=${String(exposure)}\n />\n <span>${exposure.toFixed(2)}</span>\n </div>\n </div>\n </fieldset>\n `\n }\n\n private _renderSky(value: Properties) {\n const skyOptions = [\n { value: '', label: 'None' },\n { value: 'color', label: 'Color' },\n { value: 'studio', label: 'Studio' },\n { value: 'warehouse', label: 'Warehouse' },\n { value: 'factory', label: 'Factory' },\n { value: 'office', label: 'Office' },\n { value: 'home', label: 'Home' },\n ]\n\n return html`\n <fieldset>\n <legend>Sky</legend>\n <div class=\"property-grid\">\n <label>Preset</label>\n <select value-key=\"sky\">\n ${skyOptions.map(\n o => html`<option value=${o.value} ?selected=${(value.sky || '') === o.value}>${o.label}</option>`\n )}\n </select>\n\n ${value.sky === 'color'\n ? html`\n <label>Color</label>\n <ox-input-color value-key=\"skyColor\" .value=${value.skyColor || '#87ceeb'}> </ox-input-color>\n `\n : ''}\n </div>\n </fieldset>\n `\n }\n\n private _renderHemisphereLight(value: Properties) {\n return html`\n <fieldset>\n <legend>Hemisphere Light</legend>\n <div class=\"property-grid\">\n <label>Sky</label>\n <ox-input-color value-key=\"hemiSkyColor\" .value=${value.hemiSkyColor || '#ffffff'}></ox-input-color>\n\n <label>Ground</label>\n <ox-input-color value-key=\"hemiGroundColor\" .value=${value.hemiGroundColor || '#444444'}></ox-input-color>\n\n <label>Intensity</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"3\"\n step=\"0.1\"\n value-key=\"hemiIntensity\"\n .value=${String(value.hemiIntensity ?? 0.6)}\n />\n <span>${(value.hemiIntensity ?? 0.6).toFixed(1)}</span>\n </div>\n </div>\n </fieldset>\n `\n }\n\n private _renderKeyLight(value: Properties) {\n const followCamera = value.dirLightFollowCamera !== false\n const shadowEnabled = value.dirShadowEnabled !== false\n return html`\n <fieldset>\n <legend>Key Light</legend>\n <div class=\"property-grid\">\n <input\n id=\"cb-dirlight\"\n type=\"checkbox\"\n value-key=\"dirLightEnabled\"\n .checked=${value.dirLightEnabled !== false}\n />\n <label for=\"cb-dirlight\">Enabled</label>\n\n <label>Color</label>\n <ox-input-color value-key=\"dirLightColor\" .value=${value.dirLightColor || '#ffffff'}> </ox-input-color>\n\n <label>Intensity</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"3\"\n step=\"0.1\"\n value-key=\"dirLightIntensity\"\n .value=${String(value.dirLightIntensity ?? 0.5)}\n />\n <span>${(value.dirLightIntensity ?? 0.5).toFixed(1)}</span>\n </div>\n\n <input\n id=\"cb-dirlight-follow\"\n type=\"checkbox\"\n value-key=\"dirLightFollowCamera\"\n .checked=${followCamera}\n />\n <label for=\"cb-dirlight-follow\">Follow Camera</label>\n\n ${!followCamera\n ? html`\n <label>Azimuth</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"360\"\n step=\"5\"\n value-key=\"dirLightAzimuth\"\n .value=${String(value.dirLightAzimuth ?? 30)}\n />\n <span>${Math.round((value.dirLightAzimuth ?? 30) as number)}°</span>\n </div>\n\n <label>Elevation</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"90\"\n step=\"5\"\n value-key=\"dirLightElevation\"\n .value=${String(value.dirLightElevation ?? 45)}\n />\n <span>${Math.round((value.dirLightElevation ?? 45) as number)}°</span>\n </div>\n `\n : ''}\n\n <input\n id=\"cb-dirlight-shadow\"\n type=\"checkbox\"\n value-key=\"dirShadowEnabled\"\n .checked=${shadowEnabled}\n />\n <label for=\"cb-dirlight-shadow\">Cast Shadow</label>\n\n ${shadowEnabled\n ? html`\n <label>Shadow Bias</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"-0.01\"\n max=\"0.01\"\n step=\"0.0001\"\n value-key=\"dirShadowBias\"\n .value=${String(value.dirShadowBias ?? -0.0005)}\n />\n <span>${(value.dirShadowBias ?? -0.0005).toFixed(4)}</span>\n </div>\n `\n : ''}\n </div>\n </fieldset>\n `\n }\n\n private _renderLightingPresets() {\n return html`\n <fieldset>\n <legend>Lighting Presets</legend>\n <div class=\"property-grid\">\n <label>Preset</label>\n <select @change=${this._onPresetChange}>\n <option value=\"\" selected>Select...</option>\n ${Object.keys(LIGHTING_PRESETS).map(\n name => html`<option value=${name}>${name}</option>`\n )}\n </select>\n </div>\n </fieldset>\n `\n }\n\n private _onPresetChange(e: Event) {\n const select = e.target as HTMLSelectElement\n const name = select.value\n if (!name) return\n const preset = LIGHTING_PRESETS[name]\n if (preset) this._applyLightingPreset(preset)\n // 동일 preset을 다시 선택할 수 있도록 초기값으로 리셋\n select.value = ''\n }\n\n private _renderFloor(value: Properties) {\n return html`\n <property-material3d\n legend=\"Floor Material\"\n .value=${value.floorMaterial3d || { receiveShadow: true }}\n @property-change=${this._onFloorMaterialChange}\n >\n </property-material3d>\n `\n }\n\n private _applyLightingPreset(values: Record<string, unknown>) {\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail: values\n })\n )\n }\n\n private _onFloorMaterialChange(e: CustomEvent) {\n e.stopPropagation()\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail: { floorMaterial3d: e.detail.material3d }\n })\n )\n }\n\n}\n"]}
|
|
1
|
+
{"version":3,"file":"property-scene3d.js","sourceRoot":"","sources":["../../../../src/property-panel/threed/property-scene3d.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@operato/input/ox-input-color.js'\nimport '@operato/i18n/ox-i18n.js'\n\nimport './property-material3d.js'\n\nimport { css, html } from 'lit'\nimport { property } from 'lit/decorators.js'\n\nimport { Properties, Scene } from '@hatiolab/things-scene'\nimport { PropertyGridStyles } from '@operato/styles/property-grid-styles.js'\n\nimport { AbstractProperty } from '../abstract-property.js'\n\n/**\n * Environment별 기본 조명 프로파일.\n * Environment 드롭다운에서 선택 시 sky 값과 함께 이 조명 필드들이 자동 적용된다.\n * Light Mood(아래)는 이 위에 얹는 오버라이드 역할.\n */\nconst ENVIRONMENT_DEFAULTS: Record<string, Record<string, unknown>> = {\n // 실내\n studio: {\n hemiSkyColor: '#ffffff', hemiGroundColor: '#888888', hemiIntensity: 3.0,\n dirLightEnabled: true, dirLightColor: '#ffffff', dirLightIntensity: 2.0,\n dirLightFollowCamera: true\n },\n warehouse: {\n hemiSkyColor: '#e0e4ea', hemiGroundColor: '#707880', hemiIntensity: 2.5,\n dirLightEnabled: true, dirLightColor: '#f8fafc', dirLightIntensity: 1.8,\n dirLightFollowCamera: true\n },\n factory: {\n hemiSkyColor: '#d8dce2', hemiGroundColor: '#606870', hemiIntensity: 2.0,\n dirLightEnabled: true, dirLightColor: '#e8eef2', dirLightIntensity: 2.0,\n dirLightFollowCamera: true\n },\n office: {\n hemiSkyColor: '#ffffff', hemiGroundColor: '#aaaaaa', hemiIntensity: 3.0,\n dirLightEnabled: true, dirLightColor: '#ffffff', dirLightIntensity: 1.5,\n dirLightFollowCamera: true\n },\n home: {\n hemiSkyColor: '#ffe8c8', hemiGroundColor: '#7a5a40', hemiIntensity: 2.0,\n dirLightEnabled: true, dirLightColor: '#ffd8a0', dirLightIntensity: 1.5,\n dirLightFollowCamera: true\n },\n // 실외 (날씨)\n sunny: {\n hemiSkyColor: '#87ceeb', hemiGroundColor: '#8b7355', hemiIntensity: 2.0,\n dirLightEnabled: true, dirLightColor: '#fff4cf', dirLightIntensity: 3.0,\n dirLightFollowCamera: false, dirLightAzimuth: 135, dirLightElevation: 60\n },\n cloudy: {\n hemiSkyColor: '#c8cbd0', hemiGroundColor: '#9ba1a8', hemiIntensity: 3.0,\n dirLightEnabled: true, dirLightColor: '#e8e8e8', dirLightIntensity: 0.6,\n dirLightFollowCamera: false, dirLightAzimuth: 120, dirLightElevation: 50\n },\n rainy: {\n hemiSkyColor: '#8a909a', hemiGroundColor: '#4a4f55', hemiIntensity: 1.5,\n dirLightEnabled: true, dirLightColor: '#b8c0c8', dirLightIntensity: 0.3,\n dirLightFollowCamera: false, dirLightAzimuth: 110, dirLightElevation: 40\n }\n}\n\n/**\n * Light Mood 프리셋 — Environment 기본값 위에 얹는 분위기 오버라이드.\n * Environment(지금 씬이 어디에 있는가)와 독립적으로 작동하며 sky는 건드리지 않는다.\n * 원자 조명 필드(hemi/dir)만 세팅.\n */\nconst LIGHTING_PRESETS: Record<string, Record<string, unknown>> = {\n Bright: { hemiIntensity: 3.0, dirLightEnabled: true, dirLightColor: '#ffffff', dirLightIntensity: 2.5 },\n Dim: { hemiIntensity: 0.5, dirLightEnabled: true, dirLightColor: '#fff5e0', dirLightIntensity: 0.5 },\n Warm: { hemiIntensity: 1.5, dirLightEnabled: true, dirLightColor: '#ffaa55', dirLightIntensity: 2.0 },\n Cool: { hemiIntensity: 1.5, dirLightEnabled: true, dirLightColor: '#88bbff', dirLightIntensity: 2.0 },\n Dramatic: { hemiIntensity: 0.3, dirLightEnabled: true, dirLightColor: '#ffffff', dirLightIntensity: 3.0 },\n Flat: { hemiIntensity: 3.0, dirLightEnabled: false, dirLightColor: '#ffffff', dirLightIntensity: 0 }\n}\n\n/**\n * Scene-level 3D settings for model-layer.\n * Includes 3D mode, camera, renderer, lighting, presets, and floor configuration.\n */\nexport class PropertyScene3D extends AbstractProperty {\n static styles = [\n PropertyGridStyles,\n css`\n .range-with-value {\n grid-column: 9 / -1;\n display: flex;\n align-items: center;\n gap: 4px;\n }\n\n .range-with-value input[type='range'] {\n flex: 1;\n border: none;\n background: transparent;\n padding: 0;\n }\n\n .range-with-value span {\n min-width: 2.5em;\n text-align: right;\n font-size: 11px;\n color: var(--md-sys-color-on-secondary-container);\n }\n\n .camera-actions {\n display: flex;\n justify-content: flex-end;\n margin-top: 6px;\n }\n\n .camera-actions button {\n font-size: 12px;\n padding: 4px 10px;\n border: 1px solid var(--md-sys-color-outline, #c4c7c5);\n border-radius: 4px;\n background: var(--md-sys-color-surface, #fff);\n color: var(--md-sys-color-on-surface, #1c1b1f);\n cursor: pointer;\n }\n\n .camera-actions button:hover {\n background: var(--md-sys-color-surface-variant, #e7e0ec);\n }\n `\n ]\n\n @property({ type: Object }) value?: Properties\n @property({ type: Object }) scene: Scene | null = null\n\n render() {\n const value = this.value || {}\n\n return html`\n ${this._renderMode(value)} ${this._renderPlacement(value)}\n ${this._renderCamera(value)}\n ${this._renderRenderer(value)} ${this._renderSky(value)}\n ${this._renderHemisphereLight(value)} ${this._renderKeyLight(value)} ${this._renderLightingPresets()}\n ${this._renderFloor(value)}\n `\n }\n\n /**\n * Camera 초기 설정 — Initial View(뷰 프리셋), FOV/Near/Far, 현재 카메라 저장 버튼.\n * 사용자가 씬을 3D로 돌려본 후 \"이 각도가 마음에 든다\" 싶으면\n * Save Current View로 현재 viewport의 position을 모델에 기록 → 다음 로드 시 같은 각도로 시작.\n */\n private _renderCamera(value: Properties) {\n const views = [\n { value: 'perspective', label: 'Perspective' },\n { value: 'top', label: 'Top' },\n { value: 'front', label: 'Front' },\n { value: 'back', label: 'Back' },\n { value: 'right', label: 'Right' },\n { value: 'left', label: 'Left' }\n ]\n const currentView = (value.initialCameraView as string) || 'perspective'\n const fov = Number(value.fov ?? 45)\n const near = Number(value.near ?? 0.1)\n const far = Number(value.far ?? 20000)\n\n return html`\n <fieldset>\n <legend>Camera</legend>\n <div class=\"property-grid\">\n <label>Initial View</label>\n <select value-key=\"initialCameraView\">\n ${views.map(\n v => html`<option value=${v.value} ?selected=${currentView === v.value}>${v.label}</option>`\n )}\n </select>\n\n <label>FOV</label>\n <input type=\"number\" value-key=\"fov\" step=\"1\" min=\"1\" max=\"170\" .value=${String(fov)} />\n\n <label>Near</label>\n <input type=\"number\" value-key=\"near\" step=\"0.1\" min=\"0.01\" .value=${String(near)} />\n\n <label>Far</label>\n <input type=\"number\" value-key=\"far\" step=\"100\" min=\"1\" .value=${String(far)} />\n </div>\n\n <div class=\"camera-actions\">\n <button type=\"button\" @click=${this._onSaveCameraView}>Save Current View</button>\n </div>\n </fieldset>\n `\n }\n\n /**\n * 현재 3D viewport의 카메라 상태를 모델에 저장한다.\n * scene의 getCameraState를 호출하여 view/cameraX/cameraY/cameraZ를 얻어 property-change로 전파.\n */\n private _onSaveCameraView() {\n const cap = (this.scene?.rootContainer as any)?.model_layer?._threeCapability\n if (!cap?.getCameraState) return\n const state = cap.getCameraState()\n if (!state) return\n\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail: {\n initialCameraView: state.view,\n cameraX: state.cameraX,\n cameraY: state.cameraY,\n cameraZ: state.cameraZ\n }\n })\n )\n }\n\n /**\n * Scene placement 모드 선택 — zPos 해석과 볼륨 origin 방향을 씬 전체에 일관 적용.\n * floor : zPos=바닥 높이, 볼륨이 위로 쌓임 (공장/창고/건축)\n * space : zPos=볼륨 중심 Y, 바닥 개념 없음 (우주/추상/전시)\n * inverted: zPos=천장, 볼륨이 아래로 매달림 (천장 설비, 베타)\n */\n private _renderPlacement(value: Properties) {\n const options = [\n { value: 'floor', label: 'Floor (default)' },\n { value: 'space', label: 'Space' },\n { value: 'inverted', label: 'Inverted (beta)' }\n ]\n const current = (value.placement as string) || 'floor'\n\n return html`\n <fieldset>\n <legend>Placement</legend>\n <div class=\"property-grid\">\n <label>Mode</label>\n <select value-key=\"placement\">\n ${options.map(\n o => html`<option value=${o.value} ?selected=${current === o.value}>${o.label}</option>`\n )}\n </select>\n </div>\n </fieldset>\n `\n }\n\n private _renderMode(value: Properties) {\n return html`\n <fieldset>\n <legend>3D Mode</legend>\n <div class=\"property-grid\">\n <input id=\"cb-threed\" type=\"checkbox\" value-key=\"threed\" .checked=${!!value.threed} />\n <label for=\"cb-threed\"><ox-i18n msgid=\"label.start-in-3d\">Start in 3D</ox-i18n></label>\n\n <label>Viewer Auto</label>\n <select value-key=\"cameraAutoPlay\">\n ${[\n { value: '', label: 'None' },\n { value: 'orbit', label: 'Orbit' },\n { value: 'play', label: 'Play Bookmarks' }\n ].map(\n o =>\n html`<option value=${o.value} ?selected=${(value.cameraAutoPlay || '') === o.value}>\n ${o.label}\n </option>`\n )}\n </select>\n\n <input\n id=\"cb-floor-constraint\"\n type=\"checkbox\"\n value-key=\"cameraFloorConstraint\"\n .checked=${!!value.cameraFloorConstraint}\n />\n <label for=\"cb-floor-constraint\"><ox-i18n msgid=\"label.keep-above-ground\">Keep Above Ground</ox-i18n></label>\n </div>\n </fieldset>\n `\n }\n\n private _renderRenderer(value: Properties) {\n const exposure = Number(value.exposure ?? 1.2)\n return html`\n <fieldset>\n <legend>Renderer</legend>\n <div class=\"property-grid\">\n <input id=\"cb-antialias\" type=\"checkbox\" value-key=\"antialias\" .checked=${value.antialias !== false} />\n <label for=\"cb-antialias\">Anti-alias</label>\n\n <label>Precision</label>\n <select value-key=\"precision\">\n ${[\n { value: 'highp', label: 'High' },\n { value: 'mediump', label: 'Medium' },\n { value: 'lowp', label: 'Low' }\n ].map(\n o =>\n html`<option value=${o.value} ?selected=${(value.precision || 'highp') === o.value}>\n ${o.label}\n </option>`\n )}\n </select>\n\n <label>Exposure</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"0.3\"\n max=\"2.5\"\n step=\"0.05\"\n value-key=\"exposure\"\n .value=${String(exposure)}\n />\n <span>${exposure.toFixed(2)}</span>\n </div>\n </div>\n </fieldset>\n `\n }\n\n /**\n * Environment 드롭다운 — 씬의 공간적 맥락을 정의.\n * 선택 시 sky 값과 함께 ENVIRONMENT_DEFAULTS의 기본 조명까지 한 번에 적용한다.\n * \"원클릭 전체 look\" — 사용자가 원하면 Light Mood/원자 컨트롤로 위에 얹어 조정.\n */\n private _renderSky(value: Properties) {\n const envOptions = [\n { value: '', label: 'None', group: 'basic' },\n { value: 'color', label: 'Color', group: 'basic' },\n { value: 'studio', label: 'Studio', group: 'indoor' },\n { value: 'warehouse', label: 'Warehouse', group: 'indoor' },\n { value: 'factory', label: 'Factory', group: 'indoor' },\n { value: 'office', label: 'Office', group: 'indoor' },\n { value: 'home', label: 'Home', group: 'indoor' },\n { value: 'sunny', label: 'Sunny', group: 'outdoor' },\n { value: 'cloudy', label: 'Cloudy', group: 'outdoor' },\n { value: 'rainy', label: 'Rainy', group: 'outdoor' }\n ]\n\n return html`\n <fieldset>\n <legend>Environment</legend>\n <div class=\"property-grid\">\n <label>Preset</label>\n <select @change=${this._onEnvironmentChange}>\n <optgroup label=\"Basic\">\n ${envOptions\n .filter(o => o.group === 'basic')\n .map(o => html`<option value=${o.value} ?selected=${(value.sky || '') === o.value}>${o.label}</option>`)}\n </optgroup>\n <optgroup label=\"Indoor\">\n ${envOptions\n .filter(o => o.group === 'indoor')\n .map(o => html`<option value=${o.value} ?selected=${(value.sky || '') === o.value}>${o.label}</option>`)}\n </optgroup>\n <optgroup label=\"Outdoor\">\n ${envOptions\n .filter(o => o.group === 'outdoor')\n .map(o => html`<option value=${o.value} ?selected=${(value.sky || '') === o.value}>${o.label}</option>`)}\n </optgroup>\n </select>\n\n ${value.sky === 'color'\n ? html`\n <label>Color</label>\n <ox-input-color value-key=\"skyColor\" .value=${value.skyColor || '#87ceeb'}> </ox-input-color>\n `\n : ''}\n </div>\n </fieldset>\n `\n }\n\n /**\n * Environment 선택 핸들러 — sky 필드만 바꾸는 게 아니라 ENVIRONMENT_DEFAULTS에\n * 정의된 hemi/dir 기본 조명까지 한 번의 property-change로 함께 적용한다.\n */\n private _onEnvironmentChange(e: Event) {\n const select = e.target as HTMLSelectElement\n const sky = select.value\n const detail: Record<string, unknown> = { sky }\n const defaults = ENVIRONMENT_DEFAULTS[sky]\n if (defaults) {\n Object.assign(detail, defaults)\n }\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail\n })\n )\n }\n\n private _renderHemisphereLight(value: Properties) {\n return html`\n <fieldset>\n <legend>Hemisphere Light</legend>\n <div class=\"property-grid\">\n <label>Sky</label>\n <ox-input-color value-key=\"hemiSkyColor\" .value=${value.hemiSkyColor || '#ffffff'}></ox-input-color>\n\n <label>Ground</label>\n <ox-input-color value-key=\"hemiGroundColor\" .value=${value.hemiGroundColor || '#444444'}></ox-input-color>\n\n <label>Intensity</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"3\"\n step=\"0.1\"\n value-key=\"hemiIntensity\"\n .value=${String(value.hemiIntensity ?? 0.6)}\n />\n <span>${(value.hemiIntensity ?? 0.6).toFixed(1)}</span>\n </div>\n </div>\n </fieldset>\n `\n }\n\n private _renderKeyLight(value: Properties) {\n const followCamera = value.dirLightFollowCamera !== false\n const shadowEnabled = value.dirShadowEnabled !== false\n return html`\n <fieldset>\n <legend>Key Light</legend>\n <div class=\"property-grid\">\n <input\n id=\"cb-dirlight\"\n type=\"checkbox\"\n value-key=\"dirLightEnabled\"\n .checked=${value.dirLightEnabled !== false}\n />\n <label for=\"cb-dirlight\">Enabled</label>\n\n <label>Color</label>\n <ox-input-color value-key=\"dirLightColor\" .value=${value.dirLightColor || '#ffffff'}> </ox-input-color>\n\n <label>Intensity</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"3\"\n step=\"0.1\"\n value-key=\"dirLightIntensity\"\n .value=${String(value.dirLightIntensity ?? 0.5)}\n />\n <span>${(value.dirLightIntensity ?? 0.5).toFixed(1)}</span>\n </div>\n\n <input\n id=\"cb-dirlight-follow\"\n type=\"checkbox\"\n value-key=\"dirLightFollowCamera\"\n .checked=${followCamera}\n />\n <label for=\"cb-dirlight-follow\">Follow Camera</label>\n\n ${!followCamera\n ? html`\n <label>Azimuth</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"360\"\n step=\"5\"\n value-key=\"dirLightAzimuth\"\n .value=${String(value.dirLightAzimuth ?? 30)}\n />\n <span>${Math.round((value.dirLightAzimuth ?? 30) as number)}°</span>\n </div>\n\n <label>Elevation</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"90\"\n step=\"5\"\n value-key=\"dirLightElevation\"\n .value=${String(value.dirLightElevation ?? 45)}\n />\n <span>${Math.round((value.dirLightElevation ?? 45) as number)}°</span>\n </div>\n `\n : ''}\n\n <input\n id=\"cb-dirlight-shadow\"\n type=\"checkbox\"\n value-key=\"dirShadowEnabled\"\n .checked=${shadowEnabled}\n />\n <label for=\"cb-dirlight-shadow\">Cast Shadow</label>\n\n ${shadowEnabled\n ? html`\n <label>Shadow Bias</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"-0.01\"\n max=\"0.01\"\n step=\"0.0001\"\n value-key=\"dirShadowBias\"\n .value=${String(value.dirShadowBias ?? -0.0005)}\n />\n <span>${(value.dirShadowBias ?? -0.0005).toFixed(4)}</span>\n </div>\n `\n : ''}\n </div>\n </fieldset>\n `\n }\n\n /**\n * Light Mood — Environment가 설정한 기본 조명 위에 얹는 분위기 오버라이드.\n * sky는 건드리지 않고 hemi/dir 값만 적용. Environment와 독립적으로 조합 가능.\n */\n private _renderLightingPresets() {\n return html`\n <fieldset>\n <legend>Light Mood</legend>\n <div class=\"property-grid\">\n <label>Apply</label>\n <select @change=${this._onPresetChange}>\n <option value=\"\" selected>Select...</option>\n ${Object.keys(LIGHTING_PRESETS).map(\n name => html`<option value=${name}>${name}</option>`\n )}\n </select>\n </div>\n </fieldset>\n `\n }\n\n private _onPresetChange(e: Event) {\n const select = e.target as HTMLSelectElement\n const name = select.value\n if (!name) return\n const preset = LIGHTING_PRESETS[name]\n if (preset) this._applyLightingPreset(preset)\n // 동일 preset을 다시 선택할 수 있도록 초기값으로 리셋\n select.value = ''\n }\n\n private _renderFloor(value: Properties) {\n return html`\n <property-material3d\n legend=\"Floor Material\"\n .value=${value.floorMaterial3d || { receiveShadow: true }}\n @property-change=${this._onFloorMaterialChange}\n >\n </property-material3d>\n `\n }\n\n private _applyLightingPreset(values: Record<string, unknown>) {\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail: values\n })\n )\n }\n\n private _onFloorMaterialChange(e: CustomEvent) {\n e.stopPropagation()\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail: { floorMaterial3d: e.detail.material3d }\n })\n )\n }\n\n}\n"]}
|