iobroker.mywebui 1.42.7 → 1.42.9
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/io-package.json
CHANGED
package/package.json
CHANGED
|
@@ -3,30 +3,42 @@ import { iobrokerHandler } from "../common/IobrokerHandler.js";
|
|
|
3
3
|
|
|
4
4
|
export class IobrokerWebui3DScreenEditor extends BaseCustomWebComponentConstructorAppend {
|
|
5
5
|
static template = html`
|
|
6
|
-
<div id="editor-container" style="width:100%;height:100%;display:flex;flex-direction:column;overflow:hidden;">
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
<button id="
|
|
10
|
-
<button id="
|
|
6
|
+
<div id="editor-container" style="width:100%;height:100%;display:flex;flex-direction:column;overflow:hidden;background:#1a1a1a;">
|
|
7
|
+
<!-- Toolbar -->
|
|
8
|
+
<div id="toolbar" style="height:48px;background:linear-gradient(180deg, #2a2a2a 0%, #1f1f1f 100%);border-bottom:1px solid #333;display:flex;align-items:center;padding:0 12px;gap:8px;box-shadow:0 2px 8px rgba(0,0,0,0.5);">
|
|
9
|
+
<button id="saveBtn" style="padding:8px 16px;background:#0078d4;color:white;border:none;cursor:pointer;border-radius:4px;font-weight:bold;font-size:12px;">💾 Save</button>
|
|
10
|
+
<button id="addAssetBtn" style="padding:8px 16px;background:#28a745;color:white;border:none;cursor:pointer;border-radius:4px;font-weight:bold;font-size:12px;">➕ Model</button>
|
|
11
|
+
<button id="addLightBtn" style="padding:8px 16px;background:#ffa500;color:white;border:none;cursor:pointer;border-radius:4px;font-weight:bold;font-size:12px;">💡 Light</button>
|
|
11
12
|
<input id="fileInput" type="file" accept=".glb,.gltf,.fbx,.obj" style="display:none;">
|
|
12
|
-
<
|
|
13
|
-
<button id="
|
|
13
|
+
<div style="width:1px;height:24px;background:#444;margin:0 8px;"></div>
|
|
14
|
+
<button id="undoBtn" style="padding:8px 12px;background:#333;color:#aaa;border:1px solid #444;cursor:pointer;border-radius:4px;font-size:12px;">↶</button>
|
|
15
|
+
<button id="redoBtn" style="padding:8px 12px;background:#333;color:#aaa;border:1px solid #444;cursor:pointer;border-radius:4px;font-size:12px;">↷</button>
|
|
14
16
|
<div style="flex:1;"></div>
|
|
15
|
-
<button id="gridToggle" style="padding:
|
|
16
|
-
<button id="axesToggle" style="padding:
|
|
17
|
+
<button id="gridToggle" style="padding:8px 12px;background:#333;color:#888;border:1px solid #444;cursor:pointer;border-radius:4px;font-size:12px;">Grid</button>
|
|
18
|
+
<button id="axesToggle" style="padding:8px 12px;background:#333;color:#888;border:1px solid #444;cursor:pointer;border-radius:4px;font-size:12px;">Axes</button>
|
|
17
19
|
</div>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
|
|
21
|
+
<!-- Main Content -->
|
|
22
|
+
<div id="mainContent" style="flex:1;display:flex;overflow:hidden;gap:0;">
|
|
23
|
+
<!-- Viewport (Main) -->
|
|
24
|
+
<div id="viewport" style="flex:1;background:#2a2a2a;position:relative;overflow:hidden;box-shadow:inset 0 0 20px rgba(0,0,0,0.8);"></div>
|
|
25
|
+
|
|
26
|
+
<!-- Asset Panel (Right) -->
|
|
27
|
+
<div id="rightPanel" style="width:280px;background:#1e1e1e;border-left:1px solid #333;overflow:hidden;display:flex;flex-direction:column;box-shadow:-2px 0 8px rgba(0,0,0,0.3);">
|
|
28
|
+
<!-- Tabs -->
|
|
29
|
+
<div style="display:flex;border-bottom:1px solid #333;background:#242424;">
|
|
30
|
+
<button id="treeTab" style="flex:1;padding:12px;background:#2a2a2a;color:#0f0;border:none;cursor:pointer;font-weight:bold;font-size:12px;border-bottom:2px solid #0f0;">Scene</button>
|
|
31
|
+
<button id="assetsTab" style="flex:1;padding:12px;background:#1e1e1e;color:#888;border:none;cursor:pointer;font-weight:bold;font-size:12px;border-bottom:2px solid transparent;">Assets</button>
|
|
23
32
|
</div>
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
|
|
34
|
+
<!-- Scene Tree -->
|
|
35
|
+
<div id="sceneTree" style="padding:12px;flex:1;overflow:auto;font-size:12px;"></div>
|
|
36
|
+
|
|
37
|
+
<!-- Assets List -->
|
|
38
|
+
<div id="assetsList" style="padding:12px;flex:1;overflow:auto;display:none;font-size:12px;">
|
|
39
|
+
<div id="assetsListContent" style="color:#888;">No assets loaded</div>
|
|
27
40
|
</div>
|
|
28
41
|
</div>
|
|
29
|
-
<div id="viewport" style="flex:1;background:#333;position:relative;overflow:hidden;"></div>
|
|
30
42
|
</div>
|
|
31
43
|
</div>
|
|
32
44
|
`;
|
|
@@ -311,22 +323,34 @@ export class IobrokerWebui3DScreenEditor extends BaseCustomWebComponentConstruct
|
|
|
311
323
|
this.raycaster.setFromCamera(this.mouse, this.camera);
|
|
312
324
|
const intersects = this.raycaster.intersectObjects(this.scene.children, true);
|
|
313
325
|
|
|
326
|
+
// Find the closest asset root (not just first match)
|
|
327
|
+
let closestAsset = null;
|
|
328
|
+
let closestDistance = Infinity;
|
|
329
|
+
|
|
314
330
|
for (const intersection of intersects) {
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
331
|
+
let obj = intersection.object;
|
|
332
|
+
|
|
333
|
+
// Skip grid, axes, lights
|
|
334
|
+
if (obj.userData.isGrid || obj.userData.isAxes || obj.userData.lightId) {
|
|
335
|
+
continue;
|
|
319
336
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
while (
|
|
323
|
-
if (
|
|
324
|
-
|
|
325
|
-
|
|
337
|
+
|
|
338
|
+
// Find root asset containing this mesh
|
|
339
|
+
while (obj && obj !== this.scene) {
|
|
340
|
+
if (obj.userData.assetData) {
|
|
341
|
+
if (intersection.distance < closestDistance) {
|
|
342
|
+
closestAsset = obj;
|
|
343
|
+
closestDistance = intersection.distance;
|
|
344
|
+
}
|
|
345
|
+
break;
|
|
326
346
|
}
|
|
327
|
-
|
|
347
|
+
obj = obj.parent;
|
|
328
348
|
}
|
|
329
349
|
}
|
|
350
|
+
|
|
351
|
+
if (closestAsset) {
|
|
352
|
+
this.selectObject(closestAsset);
|
|
353
|
+
}
|
|
330
354
|
}
|
|
331
355
|
|
|
332
356
|
selectObject(obj) {
|
|
@@ -335,26 +359,33 @@ export class IobrokerWebui3DScreenEditor extends BaseCustomWebComponentConstruct
|
|
|
335
359
|
// Deselect previous (remove highlight)
|
|
336
360
|
if (this.selectedObject) {
|
|
337
361
|
this.selectedObject.userData.selected = false;
|
|
338
|
-
// Restore original
|
|
362
|
+
// Restore original materials
|
|
339
363
|
this.selectedObject.traverse((child) => {
|
|
340
|
-
if (child.
|
|
364
|
+
if (child.isMesh && child.userData.originalMaterial) {
|
|
341
365
|
child.material = child.userData.originalMaterial;
|
|
366
|
+
delete child.userData.originalMaterial;
|
|
342
367
|
}
|
|
343
368
|
});
|
|
344
369
|
}
|
|
345
370
|
|
|
346
|
-
// Select new (add
|
|
371
|
+
// Select new (add subtle highlight)
|
|
347
372
|
this.selectedObject = obj;
|
|
348
373
|
obj.userData.selected = true;
|
|
349
374
|
|
|
350
|
-
// Apply subtle highlight
|
|
375
|
+
// Apply very subtle highlight - only emissive, preserve all other properties
|
|
351
376
|
obj.traverse((child) => {
|
|
352
|
-
if (child.isMesh && child.material) {
|
|
353
|
-
|
|
354
|
-
|
|
377
|
+
if (child.isMesh && child.material && !Array.isArray(child.material)) {
|
|
378
|
+
// Store original if not already stored
|
|
379
|
+
if (!child.userData.originalMaterial) {
|
|
380
|
+
child.userData.originalMaterial = child.material;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Clone and apply subtle glow
|
|
355
384
|
const hlMat = child.material.clone();
|
|
356
|
-
hlMat.emissive
|
|
357
|
-
|
|
385
|
+
if (hlMat.emissive) {
|
|
386
|
+
hlMat.emissive.setHex(0xffff00);
|
|
387
|
+
hlMat.emissiveIntensity = 0.1; // Even more subtle
|
|
388
|
+
}
|
|
358
389
|
child.material = hlMat;
|
|
359
390
|
}
|
|
360
391
|
});
|