first commit
This commit is contained in:
263
js/panels.js
Normal file
263
js/panels.js
Normal file
@@ -0,0 +1,263 @@
|
||||
const debugPanel = document.getElementById('debug-panel');
|
||||
const infoPanel = document.getElementById('info-panel');
|
||||
const infoButton = document.getElementById('info-button');
|
||||
const moveButton = document.getElementById('move-button');
|
||||
const toolPalette = document.getElementById('tool-palette');
|
||||
|
||||
let infoPanelPinned = false;
|
||||
let pinnedBuildingData = null;
|
||||
let debugOn = true;
|
||||
let interactableObjects = [];
|
||||
let INTERSECTED;
|
||||
|
||||
// Add these variables at the top of your file (outside any function)
|
||||
let lastFpsUpdate = performance.now();
|
||||
let frameCount = 0;
|
||||
let currentFps = 0;
|
||||
|
||||
// Call this in your animation loop (e.g., in animate() in main.js)
|
||||
function updateFps() {
|
||||
frameCount++;
|
||||
const now = performance.now();
|
||||
if (now - lastFpsUpdate > 500) { // Update every 0.5s
|
||||
currentFps = (frameCount * 1000) / (now - lastFpsUpdate);
|
||||
lastFpsUpdate = now;
|
||||
frameCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function initPanels(){
|
||||
window.addEventListener('keydown', function(event) {
|
||||
if (event.key === 'h') {
|
||||
console.log('H');
|
||||
hideDebugPanel()
|
||||
debugOn = !debugOn;
|
||||
}
|
||||
});
|
||||
/* renderer.domElement.addEventListener('pointerdown', function(event) {
|
||||
// Calculate mouse position in normalized device coordinates
|
||||
const rect = renderer.domElement.getBoundingClientRect();
|
||||
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
|
||||
mouse.y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
|
||||
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
const intersects = raycaster.intersectObjects(interactableObjects);
|
||||
|
||||
if (intersects.length > 0) {
|
||||
console.log(intersects[0].object);
|
||||
// Pin the info panel to this building
|
||||
infoPanelPinned = true;
|
||||
const selected = intersects[0].object.userData.parentGroup || intersects[0].object;
|
||||
pinnedBuildingData = selected.userData;
|
||||
displayInfo(pinnedBuildingData);
|
||||
} else {
|
||||
// Unpin if clicking empty space
|
||||
infoPanelPinned = false;
|
||||
pinnedBuildingData = null;
|
||||
hideInfo();
|
||||
}
|
||||
}); */
|
||||
document.addEventListener('mousemove', onMouseMove, false);
|
||||
|
||||
toolPalette.addEventListener('mouseup', (event) => event.stopPropagation(), false);
|
||||
|
||||
// Tool Palette Button Listeners
|
||||
infoButton.addEventListener('click', showInfoPanelForSelected);
|
||||
moveButton.addEventListener('click', () => {
|
||||
if (selectedObject) {
|
||||
console.log("Move tool clicked for:", selectedObject.userData.description);
|
||||
// Add move logic here later
|
||||
hideToolPalette(); // Hide palette after action (optional)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function onMouseMove(event) {
|
||||
if (infoPanelPinned) return;
|
||||
// Calculate mouse position (Unchanged)
|
||||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
|
||||
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
|
||||
|
||||
// --- Info Panel Positioning (Adjusted for bottom-left) ---
|
||||
const panelRect = infoPanel.getBoundingClientRect();
|
||||
let panelX = event.clientX + 15;
|
||||
let panelY = event.clientY - panelRect.height - 15; // Position above cursor
|
||||
|
||||
// Basic boundary checks (adjust as needed)
|
||||
if (panelX + panelRect.width > window.innerWidth - 10) {
|
||||
panelX = event.clientX - panelRect.width - 15;
|
||||
}
|
||||
if (panelY < 10) { // Check top boundary
|
||||
panelY = event.clientY + 15; // Move below cursor if too high
|
||||
}
|
||||
if (panelX < 10) panelX = 10; // Prevent going off left
|
||||
|
||||
infoPanel.style.left = `${panelX}px`;
|
||||
infoPanel.style.top = `${panelY}px`;
|
||||
}
|
||||
|
||||
// --- Debug Panel ---
|
||||
function displaySunDebug() {
|
||||
const pos = directionalLight.position;
|
||||
debugPanel.innerHTML = `<h3>Debug Info</h3>
|
||||
<p><strong>Position:</strong> (${pos.x.toFixed(2)}, ${pos.y.toFixed(2)}, ${pos.z.toFixed(2)})</p>`;
|
||||
debugPanel.style.display = 'block';
|
||||
}
|
||||
|
||||
function displayDebugPanel(object) {
|
||||
if (!object || !object.position) {
|
||||
debugPanel.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
const pos = object.position;
|
||||
debugPanel.innerHTML = `<h3>Debug Info</h3>
|
||||
<p><strong>ID:</strong> ${object.userData?.id ?? 'N/A'}</p>
|
||||
<p><strong>Position:</strong> (${pos.x.toFixed(2)}, ${pos.y.toFixed(2)}, ${pos.z.toFixed(2)})</p>`;
|
||||
debugPanel.style.display = 'block';
|
||||
}
|
||||
|
||||
function hideDebugPanel() {
|
||||
debugPanel.style.display = 'none';
|
||||
}
|
||||
|
||||
function showToolPalette(targetObject) {
|
||||
if (!targetObject) return;
|
||||
|
||||
// Calculate screen position of the object
|
||||
const screenPos = toScreenPosition(targetObject, camera);
|
||||
|
||||
// Position palette slightly above and to the right of the object's center
|
||||
toolPalette.style.left = `${screenPos.x + 10}px`;
|
||||
toolPalette.style.top = `${screenPos.y - toolPalette.offsetHeight - 10}px`; // Offset by palette height
|
||||
|
||||
// Basic boundary check (prevent going off screen) - needs improvement
|
||||
const paletteRect = toolPalette.getBoundingClientRect(); // Get actual size after potential content change
|
||||
if (parseInt(toolPalette.style.left) + paletteRect.width > window.innerWidth - 10) {
|
||||
toolPalette.style.left = `${window.innerWidth - paletteRect.width - 10}px`;
|
||||
}
|
||||
if (parseInt(toolPalette.style.top) < 10) {
|
||||
toolPalette.style.top = '10px';
|
||||
}
|
||||
if (parseInt(toolPalette.style.left) < 10) {
|
||||
toolPalette.style.left = '10px';
|
||||
}
|
||||
|
||||
|
||||
toolPalette.style.display = 'flex'; // Use flex to show it
|
||||
}
|
||||
|
||||
function hideToolPalette() {
|
||||
toolPalette.style.display = 'none';
|
||||
}
|
||||
|
||||
function showInfoPanelForSelected() {
|
||||
if (selectedObject && selectedObject.userData) {
|
||||
displayInfo(selectedObject.userData);
|
||||
} else {
|
||||
hideInfoPanel();
|
||||
}
|
||||
// Optionally hide palette after clicking info
|
||||
// hideToolPalette();
|
||||
}
|
||||
|
||||
function displayInfo(buildingData) {
|
||||
document.getElementById('info-title').textContent = buildingData.description;
|
||||
document.getElementById('info-consumption').textContent = buildingData.consumption;
|
||||
document.getElementById('info-generation').textContent = buildingData.generation;
|
||||
document.getElementById('info-iot').textContent = buildingData.iot;
|
||||
infoPanel.style.display = 'block'; // Show the panel
|
||||
}
|
||||
|
||||
function hideInfoPanel() {
|
||||
infoPanel.style.display = 'none'; // Hide the panel
|
||||
}
|
||||
|
||||
// --- Info Panel ---
|
||||
function displayInfo(buildingData) {
|
||||
if (infoPanelPinned && pinnedBuildingData && pinnedBuildingData !== buildingData) return;
|
||||
if (infoPanelPinned && !pinnedBuildingData) pinnedBuildingData = buildingData;
|
||||
|
||||
document.getElementById('info-title').textContent = buildingData.id;
|
||||
document.getElementById('info-consumption').textContent = buildingData.consumption + ' kWh';
|
||||
document.getElementById('info-generation').textContent = buildingData.generation + ' kWh';
|
||||
// Dynamically show IoT/device consumption
|
||||
let iotHtml = '';
|
||||
if (buildingData.devices) {
|
||||
for (const [key, value] of Object.entries(buildingData.devices)) {
|
||||
iotHtml += `<strong>${key}:</strong> ${value ?? 'N/A'}<br>`;
|
||||
}
|
||||
} else {
|
||||
iotHtml = 'N/A';
|
||||
}
|
||||
document.getElementById('info-iot').innerHTML = iotHtml;
|
||||
|
||||
infoPanel.style.display = 'block';
|
||||
}
|
||||
|
||||
function hideInfo() {
|
||||
if (!infoPanelPinned) {
|
||||
infoPanel.style.display = 'none';
|
||||
pinnedBuildingData = null;
|
||||
}
|
||||
}
|
||||
|
||||
function displayDebugPanelWithCamera(object) {
|
||||
let html = `<h3>Debug Info</h3>`;
|
||||
if (object && object.position) {
|
||||
html += `<p><strong>ID:</strong> ${object.userData?.id ?? 'N/A'}</p>
|
||||
<p><strong>Object Position:</strong> (${object.position.x.toFixed(2)}, ${object.position.y.toFixed(2)}, ${object.position.z.toFixed(2)})</p>`;
|
||||
}
|
||||
html += `<p><strong>FPS:</strong> ${currentFps.toFixed(1)}</p>`;
|
||||
html += `<p><strong>Camera Position:</strong> (${camera.position.x.toFixed(2)}, ${camera.position.y.toFixed(2)}, ${camera.position.z.toFixed(2)})</p>`;
|
||||
html += `<p><strong>Controls Target:</strong> (${controls.target.x.toFixed(2)}, ${controls.target.y.toFixed(2)}, ${controls.target.z.toFixed(2)})</p>`;
|
||||
html += `<p><strong>Sun Position:</strong> (${directionalLight.position.x.toFixed(2)}, ${directionalLight.position.y.toFixed(2)}, ${directionalLight.position.z.toFixed(2)})</p>`;
|
||||
debugPanel.innerHTML = html;
|
||||
debugPanel.style.display = 'block';
|
||||
}
|
||||
|
||||
function updatePanels(){
|
||||
|
||||
if (infoPanelPinned && pinnedBuildingData) {
|
||||
displayInfo(pinnedBuildingData);
|
||||
}
|
||||
|
||||
// --- Raycasting Logic ---
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
const intersects = raycaster.intersectObjects(interactableObjects);
|
||||
|
||||
let debugTarget = null;
|
||||
if (infoPanelPinned && pinnedBuildingData) {
|
||||
debugTarget = interactableObjects.find(obj => obj.userData === pinnedBuildingData);
|
||||
} else if (intersects.length > 0) {
|
||||
debugTarget = intersects[0].object.userData.parentGroup || intersects[0].object;
|
||||
}
|
||||
|
||||
if (debugOn){
|
||||
displayDebugPanelWithCamera(debugTarget);
|
||||
//displaySunDebug();
|
||||
}
|
||||
|
||||
|
||||
if (intersects.length > 0) {
|
||||
if (INTERSECTED != intersects[0].object) {
|
||||
if (INTERSECTED) { /* Optional: Revert highlight */ }
|
||||
//INTERSECTED = intersects[0].object.userData.parentGroup || intersects[0].object;
|
||||
INTERSECTED = intersects[0].object;
|
||||
if (INTERSECTED.userData) {
|
||||
//console.log('Pinned building data:', INTERSECTED.userData);
|
||||
if (INTERSECTED.userData.id){
|
||||
displayInfo(INTERSECTED.userData);
|
||||
} else{
|
||||
displayInfo(INTERSECTED.userData.parentGroup.userData);
|
||||
}
|
||||
} else {
|
||||
hideInfo();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (INTERSECTED) {
|
||||
hideInfo();
|
||||
}
|
||||
INTERSECTED = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user