@operato/property-panel 9.2.1 → 10.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/src/index.d.ts +1 -0
  2. package/dist/src/index.js +1 -0
  3. package/dist/src/index.js.map +1 -1
  4. package/dist/src/ox-property-panel.d.ts +8 -0
  5. package/dist/src/ox-property-panel.js +44 -3
  6. package/dist/src/ox-property-panel.js.map +1 -1
  7. package/dist/src/property-panel/abstract-property.js +1 -0
  8. package/dist/src/property-panel/abstract-property.js.map +1 -1
  9. package/dist/src/property-panel/data-binding/data-binding-mapper.js +1 -1
  10. package/dist/src/property-panel/data-binding/data-binding-mapper.js.map +1 -1
  11. package/dist/src/property-panel/data-binding/data-binding.js.map +1 -1
  12. package/dist/src/property-panel/effects/property-animation.js +1 -1
  13. package/dist/src/property-panel/effects/property-animation.js.map +1 -1
  14. package/dist/src/property-panel/effects/property-event-hover.d.ts +1 -1
  15. package/dist/src/property-panel/effects/property-event-hover.js +3 -3
  16. package/dist/src/property-panel/effects/property-event-hover.js.map +1 -1
  17. package/dist/src/property-panel/effects/property-event-tap.js +4 -4
  18. package/dist/src/property-panel/effects/property-event-tap.js.map +1 -1
  19. package/dist/src/property-panel/inspector/inspector.js +6 -6
  20. package/dist/src/property-panel/inspector/inspector.js.map +1 -1
  21. package/dist/src/property-panel/shapes/shapes.d.ts +0 -2
  22. package/dist/src/property-panel/shapes/shapes.js +5 -44
  23. package/dist/src/property-panel/shapes/shapes.js.map +1 -1
  24. package/dist/src/property-panel/threed/property-material3d.d.ts +27 -0
  25. package/dist/src/property-panel/threed/property-material3d.js +189 -0
  26. package/dist/src/property-panel/threed/property-material3d.js.map +1 -0
  27. package/dist/src/property-panel/threed/property-scene3d.d.ts +26 -0
  28. package/dist/src/property-panel/threed/property-scene3d.js +314 -0
  29. package/dist/src/property-panel/threed/property-scene3d.js.map +1 -0
  30. package/dist/src/property-panel/threed/threed.d.ts +17 -0
  31. package/dist/src/property-panel/threed/threed.js +98 -0
  32. package/dist/src/property-panel/threed/threed.js.map +1 -0
  33. package/dist/src/types.d.ts +1 -1
  34. package/dist/src/types.js.map +1 -1
  35. package/dist/tsconfig.tsbuildinfo +1 -1
  36. package/package.json +13 -9
  37. package/.editorconfig +0 -29
  38. package/.storybook/main.js +0 -5
  39. package/.storybook/preview.js +0 -52
  40. package/.storybook/server.mjs +0 -8
  41. package/demo/index.html +0 -30
  42. package/dist/stories/index.stories.d.ts +0 -22
  43. package/dist/stories/index.stories.js +0 -121
  44. package/dist/stories/index.stories.js.map +0 -1
  45. package/src/graphql/board.ts +0 -144
  46. package/src/graphql/data-subscription.ts +0 -30
  47. package/src/graphql/favorite-board.ts +0 -25
  48. package/src/graphql/group.ts +0 -138
  49. package/src/graphql/index.ts +0 -4
  50. package/src/graphql/play-group.ts +0 -225
  51. package/src/graphql/scenario.ts +0 -79
  52. package/src/index.ts +0 -8
  53. package/src/ox-property-panel.ts +0 -347
  54. package/src/property-panel/abstract-property.ts +0 -65
  55. package/src/property-panel/data-binding/data-binding-mapper.ts +0 -408
  56. package/src/property-panel/data-binding/data-binding-value-map.ts +0 -19
  57. package/src/property-panel/data-binding/data-binding-value-range.ts +0 -19
  58. package/src/property-panel/data-binding/data-binding.ts +0 -470
  59. package/src/property-panel/effects/effects.ts +0 -77
  60. package/src/property-panel/effects/property-animation.ts +0 -155
  61. package/src/property-panel/effects/property-animations.ts +0 -73
  62. package/src/property-panel/effects/property-event-hover-emphasize.ts +0 -74
  63. package/src/property-panel/effects/property-event-hover.ts +0 -255
  64. package/src/property-panel/effects/property-event-tap.ts +0 -269
  65. package/src/property-panel/effects/property-event.ts +0 -73
  66. package/src/property-panel/effects/property-shadow.ts +0 -77
  67. package/src/property-panel/effects/value-converter.ts +0 -17
  68. package/src/property-panel/inspector/inspector.ts +0 -376
  69. package/src/property-panel/shapes/shapes.ts +0 -379
  70. package/src/property-panel/specifics/specific-properties-builder.ts +0 -160
  71. package/src/property-panel/specifics/specifics.ts +0 -81
  72. package/src/property-panel/styles/styles.ts +0 -285
  73. package/src/types.ts +0 -63
  74. package/stories/index.stories.ts +0 -134
  75. package/tsconfig.json +0 -26
  76. package/web-dev-server.config.mjs +0 -27
  77. package/web-test-runner.config.mjs +0 -41
@@ -0,0 +1,189 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+ import { __decorate } from "tslib";
5
+ import { css, html, LitElement } from 'lit';
6
+ import { customElement, property } from 'lit/decorators.js';
7
+ import { PropertyGridStyles } from '@operato/styles/property-grid-styles.js';
8
+ const PRESETS = {
9
+ default: { metalness: 0, roughness: 0.4 },
10
+ metal: { metalness: 1.0, roughness: 0.3, envMapIntensity: 1.0 },
11
+ glass: { metalness: 0, roughness: 0.1, opacity: 0.3, envMapIntensity: 1.5 },
12
+ plastic: { metalness: 0, roughness: 0.4 },
13
+ wood: { metalness: 0, roughness: 0.8, envMapIntensity: 0.3 },
14
+ ceramic: { metalness: 0.1, roughness: 0.2, envMapIntensity: 0.3 },
15
+ rubber: { metalness: 0, roughness: 0.9, envMapIntensity: 0.3 }
16
+ };
17
+ const PRESET_NAMES = Object.keys(PRESETS);
18
+ function resolve(m) {
19
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
20
+ const preset = (_b = PRESETS[(_a = m === null || m === void 0 ? void 0 : m.preset) !== null && _a !== void 0 ? _a : 'default']) !== null && _b !== void 0 ? _b : PRESETS.default;
21
+ return {
22
+ metalness: (_c = m === null || m === void 0 ? void 0 : m.metalness) !== null && _c !== void 0 ? _c : preset.metalness,
23
+ roughness: (_d = m === null || m === void 0 ? void 0 : m.roughness) !== null && _d !== void 0 ? _d : preset.roughness,
24
+ opacity: (_f = (_e = m === null || m === void 0 ? void 0 : m.opacity) !== null && _e !== void 0 ? _e : preset.opacity) !== null && _f !== void 0 ? _f : 1,
25
+ envMapIntensity: (_h = (_g = m === null || m === void 0 ? void 0 : m.envMapIntensity) !== null && _g !== void 0 ? _g : preset.envMapIntensity) !== null && _h !== void 0 ? _h : 0.5,
26
+ side: (_j = m === null || m === void 0 ? void 0 : m.side) !== null && _j !== void 0 ? _j : 'double',
27
+ castShadow: (_k = m === null || m === void 0 ? void 0 : m.castShadow) !== null && _k !== void 0 ? _k : true,
28
+ receiveShadow: (_l = m === null || m === void 0 ? void 0 : m.receiveShadow) !== null && _l !== void 0 ? _l : false
29
+ };
30
+ }
31
+ let PropertyMaterial3d = class PropertyMaterial3d extends LitElement {
32
+ constructor() {
33
+ super(...arguments);
34
+ this.value = {};
35
+ this.legend = 'Material 3D';
36
+ }
37
+ render() {
38
+ var _a, _b;
39
+ const r = resolve(this.value);
40
+ const preset = (_b = (_a = this.value) === null || _a === void 0 ? void 0 : _a.preset) !== null && _b !== void 0 ? _b : 'default';
41
+ return html `
42
+ <fieldset>
43
+ <legend>${this.legend}</legend>
44
+ <div class="property-grid">
45
+ <label>Preset</label>
46
+ <select @change=${this._onPresetChange}>
47
+ ${PRESET_NAMES.map(name => html `<option value=${name} ?selected=${preset === name}>${name}</option>`)}
48
+ </select>
49
+
50
+ <label>Metalness</label>
51
+ <div class="range-with-value">
52
+ <input
53
+ type="range"
54
+ min="0"
55
+ max="1"
56
+ step="0.05"
57
+ .value=${String(r.metalness)}
58
+ @change=${(e) => this._onRange('metalness', e)}
59
+ />
60
+ <span>${r.metalness.toFixed(2)}</span>
61
+ </div>
62
+
63
+ <label>Roughness</label>
64
+ <div class="range-with-value">
65
+ <input
66
+ type="range"
67
+ min="0"
68
+ max="1"
69
+ step="0.05"
70
+ .value=${String(r.roughness)}
71
+ @change=${(e) => this._onRange('roughness', e)}
72
+ />
73
+ <span>${r.roughness.toFixed(2)}</span>
74
+ </div>
75
+
76
+ <label>Opacity</label>
77
+ <div class="range-with-value">
78
+ <input
79
+ type="range"
80
+ min="0"
81
+ max="1"
82
+ step="0.05"
83
+ .value=${String(r.opacity)}
84
+ @change=${(e) => this._onRange('opacity', e)}
85
+ />
86
+ <span>${r.opacity.toFixed(2)}</span>
87
+ </div>
88
+
89
+ <label>Env Map</label>
90
+ <div class="range-with-value">
91
+ <input
92
+ type="range"
93
+ min="0"
94
+ max="3"
95
+ step="0.1"
96
+ .value=${String(r.envMapIntensity)}
97
+ @change=${(e) => this._onRange('envMapIntensity', e)}
98
+ />
99
+ <span>${r.envMapIntensity.toFixed(1)}</span>
100
+ </div>
101
+
102
+ <label>Side</label>
103
+ <select @change=${this._onSideChange}>
104
+ ${['double', 'front', 'back'].map(s => html `<option value=${s} ?selected=${r.side === s}>${s}</option>`)}
105
+ </select>
106
+
107
+ <input
108
+ id="cb-cast"
109
+ type="checkbox"
110
+ .checked=${r.castShadow}
111
+ @change=${(e) => this._onCheck('castShadow', e)}
112
+ />
113
+ <label for="cb-cast">Cast Shadow</label>
114
+
115
+ <input
116
+ id="cb-recv"
117
+ type="checkbox"
118
+ .checked=${r.receiveShadow}
119
+ @change=${(e) => this._onCheck('receiveShadow', e)}
120
+ />
121
+ <label for="cb-recv">Receive Shadow</label>
122
+ </div>
123
+ </fieldset>
124
+ `;
125
+ }
126
+ _onPresetChange(e) {
127
+ var _a, _b, _c;
128
+ const preset = e.target.value;
129
+ // Preset 변경 시 PBR 값을 리셋하고 프리셋 기본값 사용 (side, shadow는 유지)
130
+ this._dispatch({
131
+ preset,
132
+ side: (_a = this.value) === null || _a === void 0 ? void 0 : _a.side,
133
+ castShadow: (_b = this.value) === null || _b === void 0 ? void 0 : _b.castShadow,
134
+ receiveShadow: (_c = this.value) === null || _c === void 0 ? void 0 : _c.receiveShadow
135
+ });
136
+ }
137
+ _onRange(key, e) {
138
+ this._dispatch({ ...this.value, [key]: parseFloat(e.target.value) });
139
+ }
140
+ _onSideChange(e) {
141
+ this._dispatch({ ...this.value, side: e.target.value });
142
+ }
143
+ _onCheck(key, e) {
144
+ this._dispatch({ ...this.value, [key]: e.target.checked });
145
+ }
146
+ _dispatch(material3d) {
147
+ this.dispatchEvent(new CustomEvent('property-change', {
148
+ bubbles: true,
149
+ composed: true,
150
+ detail: { material3d }
151
+ }));
152
+ }
153
+ };
154
+ PropertyMaterial3d.styles = [
155
+ PropertyGridStyles,
156
+ css `
157
+ .range-with-value {
158
+ grid-column: 9 / -1;
159
+ display: flex;
160
+ align-items: center;
161
+ gap: 4px;
162
+ }
163
+
164
+ .range-with-value input[type='range'] {
165
+ flex: 1;
166
+ border: none;
167
+ background: transparent;
168
+ padding: 0;
169
+ }
170
+
171
+ .range-with-value span {
172
+ min-width: 2.5em;
173
+ text-align: right;
174
+ font-size: 11px;
175
+ color: var(--md-sys-color-on-secondary-container);
176
+ }
177
+ `
178
+ ];
179
+ __decorate([
180
+ property({ type: Object })
181
+ ], PropertyMaterial3d.prototype, "value", void 0);
182
+ __decorate([
183
+ property({ type: String })
184
+ ], PropertyMaterial3d.prototype, "legend", void 0);
185
+ PropertyMaterial3d = __decorate([
186
+ customElement('property-material3d')
187
+ ], PropertyMaterial3d);
188
+ export { PropertyMaterial3d };
189
+ //# sourceMappingURL=property-material3d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"property-material3d.js","sourceRoot":"","sources":["../../../../src/property-panel/threed/property-material3d.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\nimport { PropertyGridStyles } from '@operato/styles/property-grid-styles.js'\n\ninterface Material3DValue {\n preset?: string\n metalness?: number\n roughness?: number\n opacity?: number\n envMapIntensity?: number\n side?: string\n castShadow?: boolean\n receiveShadow?: boolean\n [key: string]: unknown\n}\n\nconst PRESETS: Record<string, { metalness: number; roughness: number; opacity?: number; envMapIntensity?: number }> = {\n default: { metalness: 0, roughness: 0.4 },\n metal: { metalness: 1.0, roughness: 0.3, envMapIntensity: 1.0 },\n glass: { metalness: 0, roughness: 0.1, opacity: 0.3, envMapIntensity: 1.5 },\n plastic: { metalness: 0, roughness: 0.4 },\n wood: { metalness: 0, roughness: 0.8, envMapIntensity: 0.3 },\n ceramic: { metalness: 0.1, roughness: 0.2, envMapIntensity: 0.3 },\n rubber: { metalness: 0, roughness: 0.9, envMapIntensity: 0.3 }\n}\n\nconst PRESET_NAMES = Object.keys(PRESETS)\n\nfunction resolve(m?: Material3DValue) {\n const preset = PRESETS[m?.preset ?? 'default'] ?? PRESETS.default\n return {\n metalness: m?.metalness ?? preset.metalness,\n roughness: m?.roughness ?? preset.roughness,\n opacity: m?.opacity ?? preset.opacity ?? 1,\n envMapIntensity: m?.envMapIntensity ?? preset.envMapIntensity ?? 0.5,\n side: m?.side ?? 'double',\n castShadow: m?.castShadow ?? true,\n receiveShadow: m?.receiveShadow ?? false\n }\n}\n\n@customElement('property-material3d')\nexport class PropertyMaterial3d extends LitElement {\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 ]\n\n @property({ type: Object }) value: Material3DValue = {}\n @property({ type: String }) legend: string = 'Material 3D'\n\n render() {\n const r = resolve(this.value)\n const preset = this.value?.preset ?? 'default'\n\n return html`\n <fieldset>\n <legend>${this.legend}</legend>\n <div class=\"property-grid\">\n <label>Preset</label>\n <select @change=${this._onPresetChange}>\n ${PRESET_NAMES.map(name => html`<option value=${name} ?selected=${preset === name}>${name}</option>`)}\n </select>\n\n <label>Metalness</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n .value=${String(r.metalness)}\n @change=${(e: Event) => this._onRange('metalness', e)}\n />\n <span>${r.metalness.toFixed(2)}</span>\n </div>\n\n <label>Roughness</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n .value=${String(r.roughness)}\n @change=${(e: Event) => this._onRange('roughness', e)}\n />\n <span>${r.roughness.toFixed(2)}</span>\n </div>\n\n <label>Opacity</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n .value=${String(r.opacity)}\n @change=${(e: Event) => this._onRange('opacity', e)}\n />\n <span>${r.opacity.toFixed(2)}</span>\n </div>\n\n <label>Env Map</label>\n <div class=\"range-with-value\">\n <input\n type=\"range\"\n min=\"0\"\n max=\"3\"\n step=\"0.1\"\n .value=${String(r.envMapIntensity)}\n @change=${(e: Event) => this._onRange('envMapIntensity', e)}\n />\n <span>${r.envMapIntensity.toFixed(1)}</span>\n </div>\n\n <label>Side</label>\n <select @change=${this._onSideChange}>\n ${['double', 'front', 'back'].map(\n s => html`<option value=${s} ?selected=${r.side === s}>${s}</option>`\n )}\n </select>\n\n <input\n id=\"cb-cast\"\n type=\"checkbox\"\n .checked=${r.castShadow}\n @change=${(e: Event) => this._onCheck('castShadow', e)}\n />\n <label for=\"cb-cast\">Cast Shadow</label>\n\n <input\n id=\"cb-recv\"\n type=\"checkbox\"\n .checked=${r.receiveShadow}\n @change=${(e: Event) => this._onCheck('receiveShadow', e)}\n />\n <label for=\"cb-recv\">Receive Shadow</label>\n </div>\n </fieldset>\n `\n }\n\n private _onPresetChange(e: Event) {\n const preset = (e.target as HTMLSelectElement).value\n // Preset 변경 시 PBR 값을 리셋하고 프리셋 기본값 사용 (side, shadow는 유지)\n this._dispatch({\n preset,\n side: this.value?.side,\n castShadow: this.value?.castShadow,\n receiveShadow: this.value?.receiveShadow\n })\n }\n\n private _onRange(key: string, e: Event) {\n this._dispatch({ ...this.value, [key]: parseFloat((e.target as HTMLInputElement).value) })\n }\n\n private _onSideChange(e: Event) {\n this._dispatch({ ...this.value, side: (e.target as HTMLSelectElement).value })\n }\n\n private _onCheck(key: string, e: Event) {\n this._dispatch({ ...this.value, [key]: (e.target as HTMLInputElement).checked })\n }\n\n private _dispatch(material3d: Material3DValue) {\n this.dispatchEvent(\n new CustomEvent('property-change', {\n bubbles: true,\n composed: true,\n detail: { material3d }\n })\n )\n }\n}\n"]}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+ import '@operato/input/ox-input-color.js';
5
+ import './property-material3d.js';
6
+ import { Properties, Scene } from '@hatiolab/things-scene';
7
+ import { AbstractProperty } from '../abstract-property.js';
8
+ /**
9
+ * Scene-level 3D settings for model-layer.
10
+ * Includes 3D mode, camera, renderer, lighting, presets, and floor configuration.
11
+ */
12
+ export declare class PropertyScene3D extends AbstractProperty {
13
+ static styles: import("lit").CSSResult[];
14
+ value?: Properties;
15
+ scene: Scene | null;
16
+ render(): import("lit-html").TemplateResult<1>;
17
+ private _renderMode;
18
+ private _renderCamera;
19
+ private _renderRenderer;
20
+ private _renderHemisphereLight;
21
+ private _renderKeyLight;
22
+ private _renderLightingPresets;
23
+ private _renderFloor;
24
+ private _applyLightingPreset;
25
+ private _onFloorMaterialChange;
26
+ }
@@ -0,0 +1,314 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+ import { __decorate } from "tslib";
5
+ import '@operato/input/ox-input-color.js';
6
+ import './property-material3d.js';
7
+ import { css, html } from 'lit';
8
+ import { property } from 'lit/decorators.js';
9
+ import { PropertyGridStyles } from '@operato/styles/property-grid-styles.js';
10
+ import { AbstractProperty } from '../abstract-property.js';
11
+ const LIGHTING_PRESETS = {
12
+ Neutral: {
13
+ hemiSkyColor: '#ffffff',
14
+ hemiGroundColor: '#444444',
15
+ hemiIntensity: 0.6,
16
+ dirLightEnabled: true,
17
+ dirLightColor: '#ffffff',
18
+ dirLightIntensity: 0.5
19
+ },
20
+ Studio: {
21
+ hemiSkyColor: '#ffffff',
22
+ hemiGroundColor: '#555555',
23
+ hemiIntensity: 0.5,
24
+ dirLightEnabled: true,
25
+ dirLightColor: '#ffffff',
26
+ dirLightIntensity: 0.6
27
+ },
28
+ Bright: {
29
+ hemiSkyColor: '#ffffff',
30
+ hemiGroundColor: '#888888',
31
+ hemiIntensity: 0.8,
32
+ dirLightEnabled: true,
33
+ dirLightColor: '#ffffff',
34
+ dirLightIntensity: 0.7
35
+ },
36
+ Warm: {
37
+ hemiSkyColor: '#ffe8d0',
38
+ hemiGroundColor: '#6b4226',
39
+ hemiIntensity: 0.5,
40
+ dirLightEnabled: true,
41
+ dirLightColor: '#ffcc88',
42
+ dirLightIntensity: 0.4
43
+ },
44
+ Cool: {
45
+ hemiSkyColor: '#e0e8ff',
46
+ hemiGroundColor: '#334455',
47
+ hemiIntensity: 0.5,
48
+ dirLightEnabled: true,
49
+ dirLightColor: '#cce0ff',
50
+ dirLightIntensity: 0.4
51
+ },
52
+ Flat: {
53
+ hemiSkyColor: '#ffffff',
54
+ hemiGroundColor: '#ffffff',
55
+ hemiIntensity: 0.8,
56
+ dirLightEnabled: false,
57
+ dirLightColor: '#ffffff',
58
+ dirLightIntensity: 0
59
+ }
60
+ };
61
+ /**
62
+ * Scene-level 3D settings for model-layer.
63
+ * Includes 3D mode, camera, renderer, lighting, presets, and floor configuration.
64
+ */
65
+ export class PropertyScene3D extends AbstractProperty {
66
+ constructor() {
67
+ super(...arguments);
68
+ this.scene = null;
69
+ }
70
+ render() {
71
+ const value = this.value || {};
72
+ return html `
73
+ ${this._renderMode(value)} ${this._renderCamera(value)} ${this._renderRenderer(value)}
74
+ ${this._renderHemisphereLight(value)} ${this._renderKeyLight(value)} ${this._renderLightingPresets()}
75
+ ${this._renderFloor(value)}
76
+ `;
77
+ }
78
+ _renderMode(value) {
79
+ return html `
80
+ <fieldset>
81
+ <legend>3D Mode</legend>
82
+ <div class="property-grid">
83
+ <input id="cb-threed" type="checkbox" value-key="threed" .checked=${!!value.threed} />
84
+ <label for="cb-threed">Enable 3D</label>
85
+
86
+ <input id="cb-autorotate" type="checkbox" value-key="autoRotate" .checked=${!!value.autoRotate} />
87
+ <label for="cb-autorotate">Auto Rotate</label>
88
+ </div>
89
+ </fieldset>
90
+ `;
91
+ }
92
+ _renderCamera(value) {
93
+ var _a, _b, _c, _d;
94
+ return html `
95
+ <fieldset>
96
+ <legend>Camera</legend>
97
+ <div class="property-grid">
98
+ <label>View</label>
99
+ <select value-key="initialCameraView">
100
+ ${['perspective', 'top', 'front', 'back', 'right', 'left'].map(v => html `<option value=${v} ?selected=${(value.initialCameraView || 'perspective') === v}>
101
+ ${v.charAt(0).toUpperCase() + v.slice(1)}
102
+ </option>`)}
103
+ </select>
104
+
105
+ <label class="onethird-label">FOV</label>
106
+ <input
107
+ class="onethird-editor"
108
+ type="number"
109
+ value-key="fov"
110
+ min="10"
111
+ max="120"
112
+ .value=${String((_a = value.fov) !== null && _a !== void 0 ? _a : 45)}
113
+ />
114
+ <label class="onethird-label">Near</label>
115
+ <input
116
+ class="onethird-editor"
117
+ type="number"
118
+ value-key="near"
119
+ min="0.01"
120
+ step="0.01"
121
+ .value=${String((_b = value.near) !== null && _b !== void 0 ? _b : 0.1)}
122
+ />
123
+ <label class="onethird-label">Far</label>
124
+ <input class="onethird-editor" type="number" value-key="far" .value=${String((_c = value.far) !== null && _c !== void 0 ? _c : 20000)} />
125
+
126
+ <label class="onethird-label">Zoom</label>
127
+ <input
128
+ class="onethird-editor"
129
+ type="number"
130
+ value-key="zoom"
131
+ min="100"
132
+ .value=${String((_d = value.zoom) !== null && _d !== void 0 ? _d : 100)}
133
+ />
134
+ </div>
135
+ </fieldset>
136
+ `;
137
+ }
138
+ _renderRenderer(value) {
139
+ return html `
140
+ <fieldset>
141
+ <legend>Renderer</legend>
142
+ <div class="property-grid">
143
+ <input id="cb-antialias" type="checkbox" value-key="antialias" .checked=${value.antialias !== false} />
144
+ <label for="cb-antialias">Anti-alias</label>
145
+
146
+ <label>Precision</label>
147
+ <select value-key="precision">
148
+ ${[
149
+ { value: 'highp', label: 'High' },
150
+ { value: 'mediump', label: 'Medium' },
151
+ { value: 'lowp', label: 'Low' }
152
+ ].map(o => html `<option value=${o.value} ?selected=${(value.precision || 'highp') === o.value}>
153
+ ${o.label}
154
+ </option>`)}
155
+ </select>
156
+ </div>
157
+ </fieldset>
158
+ `;
159
+ }
160
+ _renderHemisphereLight(value) {
161
+ var _a, _b;
162
+ return html `
163
+ <fieldset>
164
+ <legend>Hemisphere Light</legend>
165
+ <div class="property-grid">
166
+ <label>Sky</label>
167
+ <ox-input-color value-key="hemiSkyColor" .value=${value.hemiSkyColor || '#ffffff'}> </ox-input-color>
168
+
169
+ <label>Ground</label>
170
+ <ox-input-color value-key="hemiGroundColor" .value=${value.hemiGroundColor || '#444444'}> </ox-input-color>
171
+
172
+ <label>Intensity</label>
173
+ <div class="range-with-value">
174
+ <input
175
+ type="range"
176
+ min="0"
177
+ max="3"
178
+ step="0.1"
179
+ value-key="hemiIntensity"
180
+ .value=${String((_a = value.hemiIntensity) !== null && _a !== void 0 ? _a : 0.6)}
181
+ />
182
+ <span>${((_b = value.hemiIntensity) !== null && _b !== void 0 ? _b : 0.6).toFixed(1)}</span>
183
+ </div>
184
+ </div>
185
+ </fieldset>
186
+ `;
187
+ }
188
+ _renderKeyLight(value) {
189
+ var _a, _b;
190
+ return html `
191
+ <fieldset>
192
+ <legend>Key Light</legend>
193
+ <div class="property-grid">
194
+ <input
195
+ id="cb-dirlight"
196
+ type="checkbox"
197
+ value-key="dirLightEnabled"
198
+ .checked=${value.dirLightEnabled !== false}
199
+ />
200
+ <label for="cb-dirlight">Enabled</label>
201
+
202
+ <label>Color</label>
203
+ <ox-input-color value-key="dirLightColor" .value=${value.dirLightColor || '#ffffff'}> </ox-input-color>
204
+
205
+ <label>Intensity</label>
206
+ <div class="range-with-value">
207
+ <input
208
+ type="range"
209
+ min="0"
210
+ max="3"
211
+ step="0.1"
212
+ value-key="dirLightIntensity"
213
+ .value=${String((_a = value.dirLightIntensity) !== null && _a !== void 0 ? _a : 0.5)}
214
+ />
215
+ <span>${((_b = value.dirLightIntensity) !== null && _b !== void 0 ? _b : 0.5).toFixed(1)}</span>
216
+ </div>
217
+ </div>
218
+ </fieldset>
219
+ `;
220
+ }
221
+ _renderLightingPresets() {
222
+ return html `
223
+ <fieldset>
224
+ <legend>Lighting Presets</legend>
225
+ <div class="property-grid">
226
+ <div class="preset-buttons">
227
+ ${Object.entries(LIGHTING_PRESETS).map(([name, values]) => html `<button @click=${() => this._applyLightingPreset(values)}>${name}</button>`)}
228
+ </div>
229
+ </div>
230
+ </fieldset>
231
+ `;
232
+ }
233
+ _renderFloor(value) {
234
+ return html `
235
+ <property-material3d
236
+ legend="Floor Material"
237
+ .value=${value.floorMaterial3d || { receiveShadow: true }}
238
+ @property-change=${this._onFloorMaterialChange}
239
+ >
240
+ </property-material3d>
241
+ `;
242
+ }
243
+ _applyLightingPreset(values) {
244
+ this.dispatchEvent(new CustomEvent('property-change', {
245
+ bubbles: true,
246
+ composed: true,
247
+ detail: values
248
+ }));
249
+ }
250
+ _onFloorMaterialChange(e) {
251
+ e.stopPropagation();
252
+ this.dispatchEvent(new CustomEvent('property-change', {
253
+ bubbles: true,
254
+ composed: true,
255
+ detail: { floorMaterial3d: e.detail.material3d }
256
+ }));
257
+ }
258
+ }
259
+ PropertyScene3D.styles = [
260
+ PropertyGridStyles,
261
+ css `
262
+ .preset-buttons {
263
+ grid-column: 1 / -1;
264
+ display: flex;
265
+ flex-wrap: wrap;
266
+ gap: 4px;
267
+ padding: 2px 0;
268
+ }
269
+
270
+ .preset-buttons button {
271
+ flex: 1;
272
+ min-width: 60px;
273
+ padding: 4px 6px;
274
+ border: 1px solid var(--md-sys-color-outline, #ccc);
275
+ border-radius: 4px;
276
+ background: var(--md-sys-color-surface, #fff);
277
+ color: var(--md-sys-color-on-surface, #333);
278
+ font-size: 11px;
279
+ cursor: pointer;
280
+ }
281
+
282
+ .preset-buttons button:hover {
283
+ background: var(--md-sys-color-primary-container, #e0e0e0);
284
+ }
285
+
286
+ .range-with-value {
287
+ grid-column: 9 / -1;
288
+ display: flex;
289
+ align-items: center;
290
+ gap: 4px;
291
+ }
292
+
293
+ .range-with-value input[type='range'] {
294
+ flex: 1;
295
+ border: none;
296
+ background: transparent;
297
+ padding: 0;
298
+ }
299
+
300
+ .range-with-value span {
301
+ min-width: 2.5em;
302
+ text-align: right;
303
+ font-size: 11px;
304
+ color: var(--md-sys-color-on-secondary-container);
305
+ }
306
+ `
307
+ ];
308
+ __decorate([
309
+ property({ type: Object })
310
+ ], PropertyScene3D.prototype, "value", void 0);
311
+ __decorate([
312
+ property({ type: Object })
313
+ ], PropertyScene3D.prototype, "scene", void 0);
314
+ //# sourceMappingURL=property-scene3d.js.map
@@ -0,0 +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;AAEzC,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,EAAE;QACP,YAAY,EAAE,SAAS;QACvB,eAAe,EAAE,SAAS;QAC1B,aAAa,EAAE,GAAG;QAClB,eAAe,EAAE,IAAI;QACrB,aAAa,EAAE,SAAS;QACxB,iBAAiB,EAAE,GAAG;KACvB;IACD,MAAM,EAAE;QACN,YAAY,EAAE,SAAS;QACvB,eAAe,EAAE,SAAS;QAC1B,aAAa,EAAE,GAAG;QAClB,eAAe,EAAE,IAAI;QACrB,aAAa,EAAE,SAAS;QACxB,iBAAiB,EAAE,GAAG;KACvB;IACD,MAAM,EAAE;QACN,YAAY,EAAE,SAAS;QACvB,eAAe,EAAE,SAAS;QAC1B,aAAa,EAAE,GAAG;QAClB,eAAe,EAAE,IAAI;QACrB,aAAa,EAAE,SAAS;QACxB,iBAAiB,EAAE,GAAG;KACvB;IACD,IAAI,EAAE;QACJ,YAAY,EAAE,SAAS;QACvB,eAAe,EAAE,SAAS;QAC1B,aAAa,EAAE,GAAG;QAClB,eAAe,EAAE,IAAI;QACrB,aAAa,EAAE,SAAS;QACxB,iBAAiB,EAAE,GAAG;KACvB;IACD,IAAI,EAAE;QACJ,YAAY,EAAE,SAAS;QACvB,eAAe,EAAE,SAAS;QAC1B,aAAa,EAAE,GAAG;QAClB,eAAe,EAAE,IAAI;QACrB,aAAa,EAAE,SAAS;QACxB,iBAAiB,EAAE,GAAG;KACvB;IACD,IAAI,EAAE;QACJ,YAAY,EAAE,SAAS;QACvB,eAAe,EAAE,SAAS;QAC1B,aAAa,EAAE,GAAG;QAClB,eAAe,EAAE,KAAK;QACtB,aAAa,EAAE,SAAS;QACxB,iBAAiB,EAAE,CAAC;KACrB;CACF,CAAA;AAED;;;GAGG;AACH,MAAM,OAAO,eAAgB,SAAQ,gBAAgB;IAArD;;QAoD8B,UAAK,GAAiB,IAAI,CAAA;IAmNxD,CAAC;IAjNC,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,aAAa,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC;QACnF,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;IAEO,WAAW,CAAC,KAAiB;QACnC,OAAO,IAAI,CAAA;;;;8EAI+D,CAAC,CAAC,KAAK,CAAC,MAAM;;;sFAGN,CAAC,CAAC,KAAK,CAAC,UAAU;;;;KAInG,CAAA;IACH,CAAC;IAEO,aAAa,CAAC,KAAiB;;QACrC,OAAO,IAAI,CAAA;;;;;;cAMD,CAAC,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,GAAG,CAC5D,CAAC,CAAC,EAAE,CACF,IAAI,CAAA,iBAAiB,CAAC,cAAc,CAAC,KAAK,CAAC,iBAAiB,IAAI,aAAa,CAAC,KAAK,CAAC;oBAChF,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;0BAChC,CACb;;;;;;;;;;qBAUQ,MAAM,CAAC,MAAA,KAAK,CAAC,GAAG,mCAAI,EAAE,CAAC;;;;;;;;;qBASvB,MAAM,CAAC,MAAA,KAAK,CAAC,IAAI,mCAAI,GAAG,CAAC;;;gFAGkC,MAAM,CAAC,MAAA,KAAK,CAAC,GAAG,mCAAI,KAAK,CAAC;;;;;;;;qBAQrF,MAAM,CAAC,MAAA,KAAK,CAAC,IAAI,mCAAI,GAAG,CAAC;;;;KAIzC,CAAA;IACH,CAAC;IAEO,eAAe,CAAC,KAAiB;QACvC,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;;;;KAIR,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,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;;;;KAI1D,CAAA;IACH,CAAC;IAEO,sBAAsB;QAC5B,OAAO,IAAI,CAAA;;;;;cAKD,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,GAAG,CACpC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CACjB,IAAI,CAAA,kBAAkB,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,IAAI,IAAI,WAAW,CACnF;;;;KAIR,CAAA;IACH,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;;AApQM,sBAAM,GAAG;IACd,kBAAkB;IAClB,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA6CF;CACF,AAhDY,CAgDZ;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'\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: {\n hemiSkyColor: '#ffffff',\n hemiGroundColor: '#444444',\n hemiIntensity: 0.6,\n dirLightEnabled: true,\n dirLightColor: '#ffffff',\n dirLightIntensity: 0.5\n },\n Studio: {\n hemiSkyColor: '#ffffff',\n hemiGroundColor: '#555555',\n hemiIntensity: 0.5,\n dirLightEnabled: true,\n dirLightColor: '#ffffff',\n dirLightIntensity: 0.6\n },\n Bright: {\n hemiSkyColor: '#ffffff',\n hemiGroundColor: '#888888',\n hemiIntensity: 0.8,\n dirLightEnabled: true,\n dirLightColor: '#ffffff',\n dirLightIntensity: 0.7\n },\n Warm: {\n hemiSkyColor: '#ffe8d0',\n hemiGroundColor: '#6b4226',\n hemiIntensity: 0.5,\n dirLightEnabled: true,\n dirLightColor: '#ffcc88',\n dirLightIntensity: 0.4\n },\n Cool: {\n hemiSkyColor: '#e0e8ff',\n hemiGroundColor: '#334455',\n hemiIntensity: 0.5,\n dirLightEnabled: true,\n dirLightColor: '#cce0ff',\n dirLightIntensity: 0.4\n },\n Flat: {\n hemiSkyColor: '#ffffff',\n hemiGroundColor: '#ffffff',\n hemiIntensity: 0.8,\n dirLightEnabled: false,\n dirLightColor: '#ffffff',\n dirLightIntensity: 0\n }\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 .preset-buttons {\n grid-column: 1 / -1;\n display: flex;\n flex-wrap: wrap;\n gap: 4px;\n padding: 2px 0;\n }\n\n .preset-buttons button {\n flex: 1;\n min-width: 60px;\n padding: 4px 6px;\n border: 1px solid var(--md-sys-color-outline, #ccc);\n border-radius: 4px;\n background: var(--md-sys-color-surface, #fff);\n color: var(--md-sys-color-on-surface, #333);\n font-size: 11px;\n cursor: pointer;\n }\n\n .preset-buttons button:hover {\n background: var(--md-sys-color-primary-container, #e0e0e0);\n }\n\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 ]\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._renderCamera(value)} ${this._renderRenderer(value)}\n ${this._renderHemisphereLight(value)} ${this._renderKeyLight(value)} ${this._renderLightingPresets()}\n ${this._renderFloor(value)}\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\">Enable 3D</label>\n\n <input id=\"cb-autorotate\" type=\"checkbox\" value-key=\"autoRotate\" .checked=${!!value.autoRotate} />\n <label for=\"cb-autorotate\">Auto Rotate</label>\n </div>\n </fieldset>\n `\n }\n\n private _renderCamera(value: Properties) {\n return html`\n <fieldset>\n <legend>Camera</legend>\n <div class=\"property-grid\">\n <label>View</label>\n <select value-key=\"initialCameraView\">\n ${['perspective', 'top', 'front', 'back', 'right', 'left'].map(\n v =>\n html`<option value=${v} ?selected=${(value.initialCameraView || 'perspective') === v}>\n ${v.charAt(0).toUpperCase() + v.slice(1)}\n </option>`\n )}\n </select>\n\n <label class=\"onethird-label\">FOV</label>\n <input\n class=\"onethird-editor\"\n type=\"number\"\n value-key=\"fov\"\n min=\"10\"\n max=\"120\"\n .value=${String(value.fov ?? 45)}\n />\n <label class=\"onethird-label\">Near</label>\n <input\n class=\"onethird-editor\"\n type=\"number\"\n value-key=\"near\"\n min=\"0.01\"\n step=\"0.01\"\n .value=${String(value.near ?? 0.1)}\n />\n <label class=\"onethird-label\">Far</label>\n <input class=\"onethird-editor\" type=\"number\" value-key=\"far\" .value=${String(value.far ?? 20000)} />\n\n <label class=\"onethird-label\">Zoom</label>\n <input\n class=\"onethird-editor\"\n type=\"number\"\n value-key=\"zoom\"\n min=\"100\"\n .value=${String(value.zoom ?? 100)}\n />\n </div>\n </fieldset>\n `\n }\n\n private _renderRenderer(value: Properties) {\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 </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 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 </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 <div class=\"preset-buttons\">\n ${Object.entries(LIGHTING_PRESETS).map(\n ([name, values]) =>\n html`<button @click=${() => this._applyLightingPreset(values)}>${name}</button>`\n )}\n </div>\n </div>\n </fieldset>\n `\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"]}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @license Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+ import '@operato/input/ox-input-angle.js';
5
+ import '@operato/i18n/ox-i18n.js';
6
+ import './property-material3d.js';
7
+ import { BOUNDS, Component, Properties } from '@hatiolab/things-scene';
8
+ import { AbstractProperty } from '../abstract-property.js';
9
+ export declare class Property3D extends AbstractProperty {
10
+ static styles: import("lit").CSSResult[];
11
+ value?: Properties;
12
+ bounds: BOUNDS | null;
13
+ selected: Component[];
14
+ firstUpdated(): void;
15
+ render(): import("lit-html").TemplateResult<1>;
16
+ onValueChange(e: Event): void;
17
+ }