senangwebs-tour 1.0.2 → 1.0.3

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.
@@ -1,387 +1,402 @@
1
1
  // UI Controller - Handles DOM manipulation and rendering
2
2
 
3
3
  class UIController {
4
- constructor(editor) {
5
- this.editor = editor;
6
- this.sceneList = document.getElementById('sceneList');
7
- this.hotspotList = document.getElementById('hotspotList');
8
- this.draggedElement = null;
9
- }
10
-
11
- /**
12
- * Render scene list
13
- */
14
- renderSceneList() {
15
- if (!this.sceneList) return;
16
-
17
- this.sceneList.innerHTML = '';
18
- const scenes = this.editor.sceneManager.getAllScenes();
19
- const currentIndex = this.editor.sceneManager.currentSceneIndex;
20
-
21
- if (scenes.length === 0) {
22
- const empty = document.createElement('div');
23
- empty.className = 'empty-state';
24
- empty.innerHTML = `
4
+ constructor(editor) {
5
+ this.editor = editor;
6
+ this.sceneList = document.getElementById("sceneList");
7
+ this.hotspotList = document.getElementById("hotspotList");
8
+ this.draggedElement = null;
9
+ }
10
+
11
+ /**
12
+ * Render scene list
13
+ */
14
+ renderSceneList() {
15
+ if (!this.sceneList) return;
16
+
17
+ this.sceneList.innerHTML = "";
18
+ const scenes = this.editor.sceneManager.getAllScenes();
19
+ const currentIndex = this.editor.sceneManager.currentSceneIndex;
20
+
21
+ if (scenes.length === 0) {
22
+ const empty = document.createElement("div");
23
+ empty.className = "empty-state";
24
+ empty.innerHTML = `
25
25
  <p>No scenes yet</p>
26
26
  <p class="hint">Click "Add Scene" to upload a 360° panorama</p>
27
27
  `;
28
- this.sceneList.appendChild(empty);
29
- return;
30
- }
31
-
32
- scenes.forEach((scene, index) => {
33
- const card = this.createSceneCard(scene, index, index === currentIndex);
34
- this.sceneList.appendChild(card);
35
- });
36
- }
37
-
38
- /**
39
- * Create scene card element
40
- */
41
- createSceneCard(scene, index, isActive) {
42
- const card = document.createElement('div');
43
- card.className = 'scene-card' + (isActive ? ' active' : '');
44
- card.draggable = true;
45
- card.dataset.index = index;
46
-
47
- // Drag handle
48
- const dragHandle = document.createElement('div');
49
- dragHandle.className = 'drag-handle';
50
- dragHandle.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free v6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M0 96C0 78.3 14.3 64 32 64l384 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 128C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32l384 0c17.7 0 32 14.3 32 32s-14.3 32-32 32L32 288c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32L32 448c-17.7 0-32-14.3-32-32s14.3-32 32-32l384 0c17.7 0 32 14.3 32 32z"/></svg>';
51
-
52
- // Thumbnail
53
- const thumbnail = document.createElement('img');
54
- thumbnail.src = scene.thumbnail || scene.imageUrl;
55
- thumbnail.alt = scene.name;
56
-
57
- // Info
58
- const info = document.createElement('div');
59
- info.className = 'scene-info';
60
-
61
- const name = document.createElement('div');
62
- name.className = 'scene-name';
63
- name.textContent = scene.name;
64
-
65
- const meta = document.createElement('div');
66
- meta.className = 'scene-meta';
67
- meta.textContent = `${scene.hotspots.length} hotspot${scene.hotspots.length !== 1 ? 's' : ''}`;
68
-
69
- info.appendChild(name);
70
- info.appendChild(meta);
71
-
72
- // Actions
73
- const actions = document.createElement('div');
74
- actions.className = 'scene-actions';
75
-
76
- const deleteBtn = document.createElement('button');
77
- deleteBtn.className = 'btn-icon';
78
- deleteBtn.innerHTML = '🗑️';
79
- deleteBtn.title = 'Delete scene';
80
- deleteBtn.onclick = (e) => {
81
- e.stopPropagation();
82
- this.editor.removeScene(index);
83
- };
84
-
85
- actions.appendChild(deleteBtn);
86
-
87
- card.appendChild(dragHandle);
88
- card.appendChild(thumbnail);
89
- card.appendChild(info);
90
- card.appendChild(actions);
91
-
92
- // Click handler
93
- card.onclick = () => {
94
- this.editor.selectScene(index);
95
- };
96
-
97
- // Drag and drop handlers
98
- this.setupDragAndDrop(card);
99
-
100
- return card;
101
- }
102
-
103
- /**
104
- * Setup drag and drop for scene reordering
105
- */
106
- setupDragAndDrop(card) {
107
- card.addEventListener('dragstart', (e) => {
108
- this.draggedElement = card;
109
- card.classList.add('dragging');
110
- e.dataTransfer.effectAllowed = 'move';
111
- });
112
-
113
- card.addEventListener('dragend', () => {
114
- card.classList.remove('dragging');
115
- this.draggedElement = null;
116
- });
117
-
118
- card.addEventListener('dragover', (e) => {
119
- e.preventDefault();
120
- e.dataTransfer.dropEffect = 'move';
121
-
122
- if (this.draggedElement && this.draggedElement !== card) {
123
- const bounding = card.getBoundingClientRect();
124
- const offset = bounding.y + bounding.height / 2;
125
-
126
- if (e.clientY - offset > 0) {
127
- card.style.borderBottom = '2px solid var(--accent-color)';
128
- card.style.borderTop = '';
129
- } else {
130
- card.style.borderTop = '2px solid var(--accent-color)';
131
- card.style.borderBottom = '';
132
- }
133
- }
134
- });
135
-
136
- card.addEventListener('dragleave', () => {
137
- card.style.borderTop = '';
138
- card.style.borderBottom = '';
139
- });
140
-
141
- card.addEventListener('drop', (e) => {
142
- e.preventDefault();
143
- card.style.borderTop = '';
144
- card.style.borderBottom = '';
145
-
146
- if (this.draggedElement && this.draggedElement !== card) {
147
- const fromIndex = parseInt(this.draggedElement.dataset.index);
148
- const toIndex = parseInt(card.dataset.index);
149
- this.editor.reorderScenes(fromIndex, toIndex);
150
- }
151
- });
28
+ this.sceneList.appendChild(empty);
29
+ return;
152
30
  }
153
31
 
154
- /**
155
- * Render hotspot list
156
- */
157
- renderHotspotList() {
158
- if (!this.hotspotList) return;
159
-
160
- this.hotspotList.innerHTML = '';
161
- const hotspots = this.editor.hotspotEditor.getAllHotspots();
162
- const currentIndex = this.editor.hotspotEditor.currentHotspotIndex;
163
-
164
- if (hotspots.length === 0) {
165
- const empty = document.createElement('div');
166
- empty.className = 'empty-state';
167
- empty.textContent = 'No hotspots. Click "Add Hotspot" to create one.';
168
- this.hotspotList.appendChild(empty);
169
- return;
170
- }
171
-
172
- hotspots.forEach((hotspot, index) => {
173
- const item = this.createHotspotItem(hotspot, index, index === currentIndex);
174
- this.hotspotList.appendChild(item);
175
- });
176
- }
177
-
178
- /**
179
- * Create hotspot list item
180
- */
181
- createHotspotItem(hotspot, index, isActive) {
182
- const item = document.createElement('div');
183
- item.className = 'hotspot-item' + (isActive ? ' active' : '');
184
-
185
- const color = document.createElement('div');
186
- color.className = 'hotspot-color';
187
- color.style.backgroundColor = hotspot.color;
188
-
189
- const info = document.createElement('div');
190
- info.className = 'hotspot-info';
191
-
192
- const title = document.createElement('div');
193
- title.className = 'hotspot-title';
194
- title.textContent = hotspot.title || 'Untitled Hotspot';
195
-
196
- const target = document.createElement('div');
197
- target.className = 'hotspot-target';
198
- if (hotspot.targetSceneId) {
199
- const targetScene = this.editor.sceneManager.getSceneById(hotspot.targetSceneId);
200
- target.textContent = targetScene ? `→ ${targetScene.name}` : `→ ${hotspot.targetSceneId}`;
32
+ scenes.forEach((scene, index) => {
33
+ const card = this.createSceneCard(scene, index, index === currentIndex);
34
+ this.sceneList.appendChild(card);
35
+ });
36
+ }
37
+
38
+ /**
39
+ * Create scene card element
40
+ */
41
+ createSceneCard(scene, index, isActive) {
42
+ const card = document.createElement("div");
43
+ card.className = "scene-card" + (isActive ? " active" : "");
44
+ card.draggable = true;
45
+ card.dataset.index = index;
46
+
47
+ // Drag handle
48
+ const dragHandle = document.createElement("div");
49
+ dragHandle.className = "drag-handle";
50
+ dragHandle.innerHTML =
51
+ '<ss-icon icon="arrow-up-down-left-right" thickness="2.2"></ss-icon>';
52
+
53
+ // Thumbnail
54
+ const thumbnail = document.createElement("img");
55
+ thumbnail.src = scene.thumbnail || scene.imageUrl;
56
+ thumbnail.alt = scene.name;
57
+
58
+ // Info
59
+ const info = document.createElement("div");
60
+ info.className = "scene-info";
61
+
62
+ const name = document.createElement("div");
63
+ name.className = "scene-name";
64
+ name.textContent = scene.name;
65
+
66
+ const meta = document.createElement("div");
67
+ meta.className = "scene-meta";
68
+ meta.textContent = `${scene.hotspots.length} hotspot${
69
+ scene.hotspots.length !== 1 ? "s" : ""
70
+ }`;
71
+
72
+ info.appendChild(name);
73
+ info.appendChild(meta);
74
+
75
+ // Actions
76
+ const actions = document.createElement("div");
77
+ actions.className = "scene-actions";
78
+
79
+ const deleteBtn = document.createElement("button");
80
+ deleteBtn.className = "btn-icon";
81
+ deleteBtn.innerHTML = '<ss-icon icon="trash" thickness="2.2"></ss-icon>';
82
+ deleteBtn.title = "Delete scene";
83
+ deleteBtn.onclick = (e) => {
84
+ e.stopPropagation();
85
+ this.editor.removeScene(index);
86
+ };
87
+
88
+ actions.appendChild(deleteBtn);
89
+
90
+ card.appendChild(dragHandle);
91
+ card.appendChild(thumbnail);
92
+ card.appendChild(info);
93
+ card.appendChild(actions);
94
+
95
+ // Click handler
96
+ card.onclick = () => {
97
+ this.editor.selectScene(index);
98
+ };
99
+
100
+ // Drag and drop handlers
101
+ this.setupDragAndDrop(card);
102
+
103
+ return card;
104
+ }
105
+
106
+ /**
107
+ * Setup drag and drop for scene reordering
108
+ */
109
+ setupDragAndDrop(card) {
110
+ card.addEventListener("dragstart", (e) => {
111
+ this.draggedElement = card;
112
+ card.classList.add("dragging");
113
+ e.dataTransfer.effectAllowed = "move";
114
+ });
115
+
116
+ card.addEventListener("dragend", () => {
117
+ card.classList.remove("dragging");
118
+ this.draggedElement = null;
119
+ });
120
+
121
+ card.addEventListener("dragover", (e) => {
122
+ e.preventDefault();
123
+ e.dataTransfer.dropEffect = "move";
124
+
125
+ if (this.draggedElement && this.draggedElement !== card) {
126
+ const bounding = card.getBoundingClientRect();
127
+ const offset = bounding.y + bounding.height / 2;
128
+
129
+ if (e.clientY - offset > 0) {
130
+ card.style.borderBottom = "2px solid var(--accent-color)";
131
+ card.style.borderTop = "";
201
132
  } else {
202
- target.textContent = 'No target';
133
+ card.style.borderTop = "2px solid var(--accent-color)";
134
+ card.style.borderBottom = "";
203
135
  }
204
-
205
- info.appendChild(title);
206
- info.appendChild(target);
207
-
208
- const actions = document.createElement('div');
209
- actions.className = 'hotspot-actions';
210
-
211
- const deleteBtn = document.createElement('button');
212
- deleteBtn.className = 'btn-delete';
213
- deleteBtn.innerHTML = '🗑️';
214
- deleteBtn.title = 'Delete';
215
- deleteBtn.onclick = (e) => {
216
- e.stopPropagation();
217
- this.editor.removeHotspot(index);
218
- };
219
-
220
- actions.appendChild(deleteBtn);
221
-
222
- item.appendChild(color);
223
- item.appendChild(info);
224
- item.appendChild(actions);
225
-
226
- item.onclick = () => {
227
- this.editor.selectHotspot(index);
228
- };
229
-
230
- return item;
136
+ }
137
+ });
138
+
139
+ card.addEventListener("dragleave", () => {
140
+ card.style.borderTop = "";
141
+ card.style.borderBottom = "";
142
+ });
143
+
144
+ card.addEventListener("drop", (e) => {
145
+ e.preventDefault();
146
+ card.style.borderTop = "";
147
+ card.style.borderBottom = "";
148
+
149
+ if (this.draggedElement && this.draggedElement !== card) {
150
+ const fromIndex = parseInt(this.draggedElement.dataset.index);
151
+ const toIndex = parseInt(card.dataset.index);
152
+ this.editor.reorderScenes(fromIndex, toIndex);
153
+ }
154
+ });
155
+ }
156
+
157
+ /**
158
+ * Render hotspot list
159
+ */
160
+ renderHotspotList() {
161
+ if (!this.hotspotList) return;
162
+
163
+ this.hotspotList.innerHTML = "";
164
+ const hotspots = this.editor.hotspotEditor.getAllHotspots();
165
+ const currentIndex = this.editor.hotspotEditor.currentHotspotIndex;
166
+
167
+ if (hotspots.length === 0) {
168
+ const empty = document.createElement("div");
169
+ empty.className = "empty-state";
170
+ empty.textContent = 'No hotspots. Click "Add Hotspot" to create one.';
171
+ this.hotspotList.appendChild(empty);
172
+ return;
231
173
  }
232
174
 
233
- /**
234
- * Update properties panel for hotspot
235
- */
236
- updateHotspotProperties(hotspot) {
237
- const hotspotAll = document.getElementById('hotspotAll');
238
- const hotspotProperties = document.getElementById('hotspotProperties');
239
-
240
- if (!hotspot) {
241
- // No hotspot selected - show list, hide properties
242
- if (hotspotAll) hotspotAll.style.display = 'block';
243
- if (hotspotProperties) hotspotProperties.style.display = 'none';
244
-
245
- // Clear form
246
- document.getElementById('hotspotTitle').value = '';
247
- document.getElementById('hotspotDescription').value = '';
248
- document.getElementById('hotspotTarget').value = '';
249
- document.getElementById('hotspotColor').value = '#00ff00';
250
- const colorText = document.getElementById('hotspotColorText');
251
- if (colorText) colorText.value = '#00ff00';
252
- document.getElementById('hotspotPosX').value = '';
253
- document.getElementById('hotspotPosY').value = '';
254
- document.getElementById('hotspotPosZ').value = '';
255
- return;
256
- }
257
-
258
- // Hotspot selected - show both list and properties
259
- if (hotspotAll) hotspotAll.style.display = 'block';
260
- if (hotspotProperties) hotspotProperties.style.display = 'block';
261
-
262
- document.getElementById('hotspotTitle').value = hotspot.title || '';
263
- document.getElementById('hotspotDescription').value = hotspot.description || '';
264
- document.getElementById('hotspotTarget').value = hotspot.targetSceneId || '';
265
- document.getElementById('hotspotColor').value = hotspot.color || '#00ff00';
266
-
267
- // Update color text input if it exists
268
- const colorText = document.getElementById('hotspotColorText');
269
- if (colorText) {
270
- colorText.value = hotspot.color || '#00ff00';
271
- }
272
-
273
- // Update position inputs
274
- const pos = hotspot.position || { x: 0, y: 0, z: 0 };
275
- document.getElementById('hotspotPosX').value = pos.x;
276
- document.getElementById('hotspotPosY').value = pos.y;
277
- document.getElementById('hotspotPosZ').value = pos.z;
278
-
279
- // Update target dropdown
280
- this.updateTargetSceneOptions();
175
+ hotspots.forEach((hotspot, index) => {
176
+ const item = this.createHotspotItem(
177
+ hotspot,
178
+ index,
179
+ index === currentIndex
180
+ );
181
+ this.hotspotList.appendChild(item);
182
+ });
183
+ }
184
+
185
+ /**
186
+ * Create hotspot list item
187
+ */
188
+ createHotspotItem(hotspot, index, isActive) {
189
+ const item = document.createElement("div");
190
+ item.className = "hotspot-item" + (isActive ? " active" : "");
191
+
192
+ const color = document.createElement("div");
193
+ color.className = "hotspot-color";
194
+ color.style.backgroundColor = hotspot.color;
195
+
196
+ const info = document.createElement("div");
197
+ info.className = "hotspot-info";
198
+
199
+ const title = document.createElement("div");
200
+ title.className = "hotspot-title";
201
+ title.textContent = hotspot.title || "Untitled Hotspot";
202
+
203
+ const target = document.createElement("div");
204
+ target.className = "hotspot-target";
205
+ if (hotspot.targetSceneId) {
206
+ const targetScene = this.editor.sceneManager.getSceneById(
207
+ hotspot.targetSceneId
208
+ );
209
+ target.textContent = targetScene
210
+ ? `→ ${targetScene.name}`
211
+ : `→ ${hotspot.targetSceneId}`;
212
+ } else {
213
+ target.textContent = "No target";
281
214
  }
282
215
 
283
- /**
284
- * Update properties panel for scene
285
- */
286
- updateSceneProperties(scene) {
287
- if (!scene) {
288
- document.getElementById('sceneId').value = '';
289
- document.getElementById('sceneName').value = '';
290
- document.getElementById('sceneImageUrl').value = '';
291
- return;
292
- }
293
-
294
- document.getElementById('sceneId').value = scene.id || '';
295
- document.getElementById('sceneName').value = scene.name || '';
296
- document.getElementById('sceneImageUrl').value = scene.imageUrl || '';
216
+ info.appendChild(title);
217
+ info.appendChild(target);
218
+
219
+ const actions = document.createElement("div");
220
+ actions.className = "hotspot-actions";
221
+
222
+ const deleteBtn = document.createElement("button");
223
+ deleteBtn.className = "btn-delete";
224
+ deleteBtn.innerHTML = '<ss-icon icon="trash" thickness="2.2"></ss-icon>';
225
+ deleteBtn.title = "Delete";
226
+ deleteBtn.onclick = (e) => {
227
+ e.stopPropagation();
228
+ this.editor.removeHotspot(index);
229
+ };
230
+
231
+ actions.appendChild(deleteBtn);
232
+
233
+ item.appendChild(color);
234
+ item.appendChild(info);
235
+ item.appendChild(actions);
236
+
237
+ item.onclick = () => {
238
+ this.editor.selectHotspot(index);
239
+ };
240
+
241
+ return item;
242
+ }
243
+
244
+ /**
245
+ * Update properties panel for hotspot
246
+ */
247
+ updateHotspotProperties(hotspot) {
248
+ const hotspotAll = document.getElementById("hotspotAll");
249
+ const hotspotProperties = document.getElementById("hotspotProperties");
250
+
251
+ if (!hotspot) {
252
+ // No hotspot selected - show list, hide properties
253
+ if (hotspotAll) hotspotAll.style.display = "block";
254
+ if (hotspotProperties) hotspotProperties.style.display = "none";
255
+
256
+ // Clear form
257
+ document.getElementById("hotspotTitle").value = "";
258
+ document.getElementById("hotspotDescription").value = "";
259
+ document.getElementById("hotspotTarget").value = "";
260
+ document.getElementById("hotspotColor").value = "#00ff00";
261
+ const colorText = document.getElementById("hotspotColorText");
262
+ if (colorText) colorText.value = "#00ff00";
263
+ document.getElementById("hotspotPosX").value = "";
264
+ document.getElementById("hotspotPosY").value = "";
265
+ document.getElementById("hotspotPosZ").value = "";
266
+ return;
297
267
  }
298
268
 
299
- /**
300
- * Update properties panel for tour
301
- */
302
- updateTourProperties(config) {
303
- document.getElementById('tourTitle').value = config.title || '';
304
- document.getElementById('tourDescription').value = config.description || '';
305
- document.getElementById('tourInitialScene').value = config.initialSceneId || '';
306
- document.getElementById('tourAutoRotate').checked = config.autoRotate || false;
307
- document.getElementById('tourShowCompass').checked = config.showCompass || false;
308
-
309
- // Also update project name in header if it exists
310
- const projectName = document.getElementById('project-name');
311
- if (projectName) {
312
- projectName.value = config.title || '';
313
- }
269
+ // Hotspot selected - show both list and properties
270
+ if (hotspotAll) hotspotAll.style.display = "block";
271
+ if (hotspotProperties) hotspotProperties.style.display = "block";
272
+
273
+ document.getElementById("hotspotTitle").value = hotspot.title || "";
274
+ document.getElementById("hotspotDescription").value =
275
+ hotspot.description || "";
276
+ document.getElementById("hotspotTarget").value =
277
+ hotspot.targetSceneId || "";
278
+ document.getElementById("hotspotColor").value = hotspot.color || "#00ff00";
279
+
280
+ // Update color text input if it exists
281
+ const colorText = document.getElementById("hotspotColorText");
282
+ if (colorText) {
283
+ colorText.value = hotspot.color || "#00ff00";
314
284
  }
315
285
 
316
- /**
317
- * Update target scene options in hotspot properties
318
- */
319
- updateTargetSceneOptions() {
320
- const select = document.getElementById('hotspotTarget');
321
- if (!select) return;
322
-
323
- const scenes = this.editor.sceneManager.getAllScenes();
324
- const currentValue = select.value;
325
-
326
- select.innerHTML = '<option value="">Select target scene...</option>';
327
-
328
- scenes.forEach(scene => {
329
- const option = document.createElement('option');
330
- option.value = scene.id;
331
- option.textContent = scene.name;
332
- select.appendChild(option);
333
- });
334
-
335
- select.value = currentValue;
286
+ // Update position inputs
287
+ const pos = hotspot.position || { x: 0, y: 0, z: 0 };
288
+ document.getElementById("hotspotPosX").value = pos.x;
289
+ document.getElementById("hotspotPosY").value = pos.y;
290
+ document.getElementById("hotspotPosZ").value = pos.z;
291
+
292
+ // Update target dropdown
293
+ this.updateTargetSceneOptions();
294
+ }
295
+
296
+ /**
297
+ * Update properties panel for scene
298
+ */
299
+ updateSceneProperties(scene) {
300
+ if (!scene) {
301
+ document.getElementById("sceneId").value = "";
302
+ document.getElementById("sceneName").value = "";
303
+ document.getElementById("sceneImageUrl").value = "";
304
+ return;
336
305
  }
337
306
 
338
- /**
339
- * Update initial scene options in tour properties
340
- */
341
- updateInitialSceneOptions() {
342
- const select = document.getElementById('tourInitialScene');
343
- if (!select) return;
344
-
345
- const scenes = this.editor.sceneManager.getAllScenes();
346
- const currentValue = select.value;
347
-
348
- select.innerHTML = '<option value="">Select initial scene...</option>';
349
-
350
- scenes.forEach(scene => {
351
- const option = document.createElement('option');
352
- option.value = scene.id;
353
- option.textContent = scene.name;
354
- select.appendChild(option);
355
- });
356
-
357
- select.value = currentValue;
307
+ document.getElementById("sceneId").value = scene.id || "";
308
+ document.getElementById("sceneName").value = scene.name || "";
309
+ document.getElementById("sceneImageUrl").value = scene.imageUrl || "";
310
+ }
311
+
312
+ /**
313
+ * Update properties panel for tour
314
+ */
315
+ updateTourProperties(config) {
316
+ document.getElementById("tourTitle").value = config.title || "";
317
+ document.getElementById("tourDescription").value = config.description || "";
318
+ document.getElementById("tourInitialScene").value =
319
+ config.initialSceneId || "";
320
+ document.getElementById("tourAutoRotate").checked =
321
+ config.autoRotate || false;
322
+ document.getElementById("tourShowCompass").checked =
323
+ config.showCompass || false;
324
+
325
+ // Also update project name in header if it exists
326
+ const projectName = document.getElementById("project-name");
327
+ if (projectName) {
328
+ projectName.value = config.title || "";
358
329
  }
359
-
360
- /**
361
- * Show/hide loading indicator
362
- */
363
- setLoading(isLoading) {
364
- const indicator = document.querySelector('.loading-indicator');
365
- if (indicator) {
366
- indicator.style.display = isLoading ? 'block' : 'none';
367
- }
368
- }
369
-
370
- /**
371
- * Switch properties tab
372
- */
373
- switchTab(tabName) {
374
- // Update tab buttons
375
- document.querySelectorAll('.tab-btn').forEach(btn => {
376
- btn.classList.toggle('active', btn.dataset.tab === tabName);
377
- });
378
-
379
- // Update tab content
380
- document.querySelectorAll('.tab-content').forEach(content => {
381
- content.classList.toggle('active', content.id === tabName + 'Tab');
382
- });
330
+ }
331
+
332
+ /**
333
+ * Update target scene options in hotspot properties
334
+ */
335
+ updateTargetSceneOptions() {
336
+ const select = document.getElementById("hotspotTarget");
337
+ if (!select) return;
338
+
339
+ const scenes = this.editor.sceneManager.getAllScenes();
340
+ const currentValue = select.value;
341
+
342
+ select.innerHTML = '<option value="">Select target scene...</option>';
343
+
344
+ scenes.forEach((scene) => {
345
+ const option = document.createElement("option");
346
+ option.value = scene.id;
347
+ option.textContent = scene.name;
348
+ select.appendChild(option);
349
+ });
350
+
351
+ select.value = currentValue;
352
+ }
353
+
354
+ /**
355
+ * Update initial scene options in tour properties
356
+ */
357
+ updateInitialSceneOptions() {
358
+ const select = document.getElementById("tourInitialScene");
359
+ if (!select) return;
360
+
361
+ const scenes = this.editor.sceneManager.getAllScenes();
362
+ const currentValue = select.value;
363
+
364
+ select.innerHTML = '<option value="">Select initial scene...</option>';
365
+
366
+ scenes.forEach((scene) => {
367
+ const option = document.createElement("option");
368
+ option.value = scene.id;
369
+ option.textContent = scene.name;
370
+ select.appendChild(option);
371
+ });
372
+
373
+ select.value = currentValue;
374
+ }
375
+
376
+ /**
377
+ * Show/hide loading indicator
378
+ */
379
+ setLoading(isLoading) {
380
+ const indicator = document.querySelector(".loading-indicator");
381
+ if (indicator) {
382
+ indicator.style.display = isLoading ? "block" : "none";
383
383
  }
384
+ }
385
+
386
+ /**
387
+ * Switch properties tab
388
+ */
389
+ switchTab(tabName) {
390
+ // Update tab buttons
391
+ document.querySelectorAll(".tab-btn").forEach((btn) => {
392
+ btn.classList.toggle("active", btn.dataset.tab === tabName);
393
+ });
394
+
395
+ // Update tab content
396
+ document.querySelectorAll(".tab-content").forEach((content) => {
397
+ content.classList.toggle("active", content.id === tabName + "Tab");
398
+ });
399
+ }
384
400
  }
385
401
 
386
-
387
402
  export default UIController;