iobroker.mywebui 1.42.23 → 1.42.24

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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "mywebui",
4
- "version": "1.42.23",
4
+ "version": "1.42.24",
5
5
  "titleLang": {
6
6
  "en": "mywebui",
7
7
  "de": "mywebui",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.mywebui",
3
- "version": "1.42.23",
3
+ "version": "1.42.24",
4
4
  "description": "ioBroker mywebui - Custom edited mywebui by gokturk413 with 3D Editor",
5
5
  "type": "module",
6
6
  "main": "dist/backend/main.js",
@@ -3,247 +3,139 @@ import { iobrokerHandler } from "../common/IobrokerHandler.js";
3
3
 
4
4
  export class IobrokerWebui3DScreenViewer extends BaseCustomWebComponentConstructorAppend {
5
5
  static template = html`
6
- <div id="container" style="width:100%;height:100%;position:relative;overflow:hidden;background:#333;">
6
+ <div id="container" style="width:100%;height:100%;position:relative;overflow:hidden;background:#1a1a1a;">
7
7
  <div id="viewport" style="width:100%;height:100%;"></div>
8
- <div id="status" style="position:absolute;bottom:10px;left:10px;background:rgba(0,0,0,0.7);color:#0f0;padding:10px;font-family:monospace;font-size:12px;z-index:10;border-radius:3px;">Ready</div>
9
8
  </div>
10
9
  `;
11
10
 
12
11
  static style = css`
13
- :host {
14
- display: block;
15
- width: 100%;
16
- height: 100%;
17
- background: #333;
18
- }
12
+ :host { display:block;width:100%;height:100%; }
19
13
  `;
20
14
 
21
15
  constructor() {
22
16
  super();
23
- this.scene = null;
24
- this.camera = null;
25
- this.renderer = null;
26
- this.controls = null;
27
- this.THREE = null;
28
- this.gltfLoader = null;
29
- this.sceneData = null;
30
- this.sceneNameAttr = null;
17
+ this._animating = false;
18
+ this._renderer = null;
31
19
  }
32
20
 
33
21
  async connectedCallback() {
34
- this.sceneNameAttr = this.getAttribute('scene-name');
35
- if (!this.sceneNameAttr) {
36
- this._getDomElement('status').textContent = '❌ No scene name';
37
- return;
38
- }
22
+ const sceneName = this.getAttribute('scene-name');
23
+ const sceneType = this.getAttribute('scene-type') || '3dscreen';
24
+ if (!sceneName) return;
25
+ await this._init(sceneName, sceneType);
26
+ }
39
27
 
40
- await this.init();
28
+ disconnectedCallback() {
29
+ this._animating = false;
30
+ if (this._renderer) { this._renderer.dispose(); this._renderer.domElement.remove(); this._renderer = null; }
31
+ window.removeEventListener('resize', this._onResize);
41
32
  }
42
33
 
43
- async init() {
34
+ async _init(sceneName, sceneType) {
44
35
  try {
45
- const statusEl = this._getDomElement('status');
46
- statusEl.textContent = '⏳ Loading...';
47
-
48
- // Load Three.js
49
36
  const THREE = await import('three');
50
37
  const { OrbitControls } = await import('three/addons/controls/OrbitControls.js');
51
- const { GLTFLoader } = await import('three/addons/loaders/GLTFLoader.js');
52
38
 
53
- this.THREE = THREE;
54
- this.gltfLoader = new GLTFLoader();
39
+ // Load scene data
40
+ const sceneData = sceneType === '3dcontrol'
41
+ ? await iobrokerHandler.getWebuiObject('3dcontrol', sceneName)
42
+ : await iobrokerHandler.get3DScreen(sceneName);
55
43
 
56
- // Initialize Three.js
57
- this.initThreeJS(THREE, OrbitControls);
44
+ if (!sceneData) { console.warn('3D scene not found:', sceneName); return; }
58
45
 
59
- // Load scene
60
- await this.loadScene(this.sceneNameAttr);
46
+ const viewport = this._getDomElement('viewport');
47
+ const w = viewport.clientWidth || 800;
48
+ const h = viewport.clientHeight || 600;
61
49
 
62
- statusEl.textContent = '✅ Ready';
63
- } catch (error) {
64
- console.error('❌ 3D Viewer init failed:', error);
65
- this._getDomElement('status').textContent = '❌ ' + error.message;
66
- }
67
- }
50
+ // Renderer
51
+ const renderer = new THREE.WebGLRenderer({ antialias: true });
52
+ renderer.setPixelRatio(window.devicePixelRatio);
53
+ renderer.setSize(w, h);
54
+ renderer.shadowMap.enabled = true;
55
+ viewport.appendChild(renderer.domElement);
56
+ this._renderer = renderer;
68
57
 
69
- initThreeJS(THREE, OrbitControls) {
70
- const viewport = this._getDomElement('viewport');
71
- const width = viewport.clientWidth;
72
- const height = viewport.clientHeight;
73
-
74
- // Scene
75
- this.scene = new THREE.Scene();
76
- this.scene.background = new THREE.Color(0x333333);
77
-
78
- // Camera
79
- this.camera = new THREE.PerspectiveCamera(75, width / height, 0.1, 1000);
80
- this.camera.position.set(10, 10, 10);
81
-
82
- // Renderer
83
- this.renderer = new THREE.WebGLRenderer({ antialias: true });
84
- this.renderer.setSize(width, height);
85
- this.renderer.shadowMap.enabled = true;
86
- viewport.appendChild(this.renderer.domElement);
87
-
88
- // Lighting
89
- const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
90
- this.scene.add(ambientLight);
91
-
92
- const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
93
- directionalLight.position.set(10, 10, 10);
94
- directionalLight.castShadow = true;
95
- directionalLight.shadow.mapSize.width = 2048;
96
- directionalLight.shadow.mapSize.height = 2048;
97
- this.scene.add(directionalLight);
98
-
99
- // Grid
100
- const gridHelper = new THREE.GridHelper(20, 20, 0x888888, 0x444444);
101
- gridHelper.position.y = -0.01;
102
- this.scene.add(gridHelper);
103
-
104
- // Axes
105
- const axesHelper = new THREE.AxesHelper(5);
106
- this.scene.add(axesHelper);
107
-
108
- // Controls
109
- this.controls = new OrbitControls(this.camera, this.renderer.domElement);
110
- this.controls.autoRotate = false;
111
- this.controls.enableZoom = true;
112
- this.controls.enablePan = true;
113
-
114
- // Animation loop
115
- let animating = true;
116
- const animate = () => {
117
- if (animating) {
118
- requestAnimationFrame(animate);
119
- this.controls.update();
120
- this.renderer.render(this.scene, this.camera);
121
- }
122
- };
123
- animate();
58
+ let scene, camera;
124
59
 
125
- // Resize
126
- window.addEventListener('resize', () => this.onWindowResize());
60
+ if (sceneData.threeScene && sceneData.threeScene.scene) {
61
+ // New format: three.js editor JSON → ObjectLoader
62
+ const loader = new THREE.ObjectLoader();
63
+ scene = loader.parse(sceneData.threeScene.scene);
127
64
 
128
- this._stopAnimation = () => { animating = false; };
129
- }
130
-
131
- async loadScene(sceneName) {
132
- try {
133
- this.sceneData = await iobrokerHandler.get3DScreen(sceneName);
134
- if (!this.sceneData) {
135
- throw new Error(`Scene not found: ${sceneName}`);
136
- }
137
-
138
- // Load assets
139
- if (this.sceneData.assets) {
140
- for (const asset of this.sceneData.assets) {
141
- if (asset.type === 'model' && asset.glbPath) {
142
- await this.loadAsset(asset);
143
- }
65
+ // Restore camera
66
+ if (sceneData.threeScene.camera) {
67
+ try { camera = loader.parse(sceneData.threeScene.camera); } catch (_) {}
144
68
  }
145
- }
146
-
147
- // Add lights
148
- if (this.sceneData.lights) {
149
- for (const light of this.sceneData.lights) {
150
- this.addLightToScene(light);
69
+ if (!camera || !(camera.isCamera)) {
70
+ camera = new THREE.PerspectiveCamera(50, w / h, 0.1, 10000);
71
+ camera.position.set(0, 0, 50);
151
72
  }
152
- }
153
73
 
154
- // Set camera
155
- if (this.sceneData.camera) {
156
- this.camera.position.set(
157
- this.sceneData.camera.position.x,
158
- this.sceneData.camera.position.y,
159
- this.sceneData.camera.position.z
160
- );
161
- this.camera.lookAt(
162
- this.sceneData.camera.target.x,
163
- this.sceneData.camera.target.y,
164
- this.sceneData.camera.target.z
165
- );
166
- }
167
-
168
- console.log('✅ Scene loaded:', sceneName);
169
- } catch (error) {
170
- console.error('Error loading scene:', error);
171
- throw error;
172
- }
173
- }
174
-
175
- loadAsset(asset) {
176
- return new Promise((resolve, reject) => {
177
- this.gltfLoader.load(
178
- asset.glbPath,
179
- (gltf) => {
180
- const model = gltf.scene;
181
- model.position.set(asset.position.x, asset.position.y, asset.position.z);
182
- model.rotation.set(asset.rotation.x, asset.rotation.y, asset.rotation.z);
183
- model.scale.set(asset.scale.x, asset.scale.y, asset.scale.z);
184
- this.scene.add(model);
185
- console.log('✅ Asset loaded:', asset.name);
186
- resolve();
187
- },
188
- undefined,
189
- (error) => {
190
- console.error('Error loading asset:', error);
191
- reject(error);
74
+ // Renderer settings from project
75
+ const proj = sceneData.threeScene.project || {};
76
+ if (proj.shadows !== undefined) renderer.shadowMap.enabled = proj.shadows;
77
+ if (proj.physicallyCorrectLights) renderer.useLegacyLights = false;
78
+ } else {
79
+ // Old format backward compatibility
80
+ scene = new THREE.Scene();
81
+ scene.background = new THREE.Color(0x333333);
82
+ camera = new THREE.PerspectiveCamera(75, w / h, 0.1, 1000);
83
+ camera.position.set(10, 10, 10);
84
+
85
+ scene.add(new THREE.AmbientLight(0xffffff, 0.6));
86
+ const dir = new THREE.DirectionalLight(0xffffff, 0.8);
87
+ dir.position.set(10, 10, 10);
88
+ scene.add(dir);
89
+
90
+ if (sceneData.assets) {
91
+ const { GLTFLoader } = await import('three/addons/loaders/GLTFLoader.js');
92
+ const loader = new GLTFLoader();
93
+ for (const asset of sceneData.assets) {
94
+ if (asset.type === 'model' && asset.glbPath) {
95
+ await new Promise(res => loader.load(asset.glbPath, gltf => {
96
+ const m = gltf.scene;
97
+ if (asset.position) m.position.set(asset.position.x, asset.position.y, asset.position.z);
98
+ if (asset.scale) m.scale.set(asset.scale.x, asset.scale.y, asset.scale.z);
99
+ scene.add(m); res();
100
+ }, undefined, res));
101
+ }
102
+ }
192
103
  }
193
- );
194
- });
195
- }
104
+ }
196
105
 
197
- addLightToScene(light) {
198
- let threeLight;
199
-
200
- switch (light.type) {
201
- case 'ambient':
202
- threeLight = new this.THREE.AmbientLight(light.color, light.intensity);
203
- break;
204
- case 'directional':
205
- threeLight = new this.THREE.DirectionalLight(light.color, light.intensity);
206
- if (light.position) {
207
- threeLight.position.set(light.position.x, light.position.y, light.position.z);
208
- }
209
- if (light.castShadow) {
210
- threeLight.castShadow = true;
211
- }
212
- break;
213
- case 'point':
214
- threeLight = new this.THREE.PointLight(light.color, light.intensity);
215
- if (light.position) {
216
- threeLight.position.set(light.position.x, light.position.y, light.position.z);
217
- }
218
- break;
219
- case 'spot':
220
- threeLight = new this.THREE.SpotLight(light.color, light.intensity);
221
- if (light.position) {
222
- threeLight.position.set(light.position.x, light.position.y, light.position.z);
223
- }
224
- break;
225
- }
106
+ camera.aspect = w / h;
107
+ camera.updateProjectionMatrix();
226
108
 
227
- if (threeLight) {
228
- this.scene.add(threeLight);
229
- }
230
- }
109
+ const controls = new OrbitControls(camera, renderer.domElement);
110
+ controls.enableDamping = true;
231
111
 
232
- onWindowResize() {
233
- const viewport = this._getDomElement('viewport');
234
- const width = viewport.clientWidth;
235
- const height = viewport.clientHeight;
112
+ // Run scene script if present
113
+ if (sceneData.script) {
114
+ try {
115
+ const fn = new Function('THREE', 'scene', 'camera', 'renderer', 'controls', sceneData.script);
116
+ fn(THREE, scene, camera, renderer, controls);
117
+ } catch (e) { console.warn('3D scene script error:', e); }
118
+ }
236
119
 
237
- this.camera.aspect = width / height;
238
- this.camera.updateProjectionMatrix();
239
- this.renderer.setSize(width, height);
240
- }
120
+ this._animating = true;
121
+ this._onResize = () => {
122
+ const vw = viewport.clientWidth, vh = viewport.clientHeight;
123
+ camera.aspect = vw / vh;
124
+ camera.updateProjectionMatrix();
125
+ renderer.setSize(vw, vh);
126
+ };
127
+ window.addEventListener('resize', this._onResize);
128
+
129
+ const animate = () => {
130
+ if (!this._animating) return;
131
+ requestAnimationFrame(animate);
132
+ controls.update();
133
+ renderer.render(scene, camera);
134
+ };
135
+ animate();
241
136
 
242
- disconnectedCallback() {
243
- if (this._stopAnimation) this._stopAnimation();
244
- if (this.renderer) {
245
- this.renderer.dispose();
246
- this.renderer.domElement.remove();
137
+ } catch (err) {
138
+ console.error('3D Viewer error:', err);
247
139
  }
248
140
  }
249
141
  }