Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion examples/visualizer/modules/interactions.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,16 @@ export function setupEventListeners(handleFileUploadCallback, handleDownloadCall
document.getElementById('download').addEventListener('click', handleDownloadCallback);

// Reset button
document.getElementById('reset').addEventListener('click', resetViewCallback);
document.getElementById('reset').addEventListener('click', () => {
if (confirm('Are you sure you want to reset? This will restore all settings to their default values.')) {
const resetIcon = document.getElementById('reset');
resetIcon.classList.add('spinning');
resetIcon.addEventListener('animationend', () => {
resetIcon.classList.remove('spinning');
}, { once: true });
resetViewCallback();
}
});
}

/**
Expand Down
26 changes: 26 additions & 0 deletions examples/visualizer/modules/state.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,29 @@ export function clearSlicingSettings() {
console.warn('Failed to clear slicing settings from localStorage:', error);
}
}

/**
* Save folder open/closed states to localStorage.
*/
export function saveFolderStates(states) {
try {
localStorage.setItem('visualizer-folder-states', JSON.stringify(states));
} catch (error) {
console.warn('Failed to save folder states to localStorage:', error);
}
}

/**
* Load folder open/closed states from localStorage.
*/
export function loadFolderStates() {
try {
const saved = localStorage.getItem('visualizer-folder-states');
if (saved) {
return JSON.parse(saved);
}
} catch (error) {
console.warn('Failed to load folder states from localStorage:', error);
}
return null;
}
26 changes: 25 additions & 1 deletion examples/visualizer/modules/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*/

import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
import { saveSlicingSettings, loadSlicingSettings } from './state.js';
import { saveSlicingSettings, loadSlicingSettings, saveFolderStates, loadFolderStates } from './state.js';

/**
* Create the legends for movement types and axes.
Expand Down Expand Up @@ -216,6 +216,30 @@ export function createSlicingGUI(sliceCallback, useDefaults = false, rotateCallb
slicingGUI.add(params, 'slice').name('Slice');
slicingGUI.open();

// Collect the open/closed state of all folders and persist it.
const collectFolderStates = () => {
const states = {};
for (const folder of slicingGUI.folders) {
states[folder._title] = !folder._closed;
}
return states;
};

// Apply saved folder states, then attach a save handler to each folder.
const savedFolderStates = loadFolderStates();
for (const folder of slicingGUI.folders) {
if (savedFolderStates && folder._title in savedFolderStates) {
if (savedFolderStates[folder._title]) {
folder.open();
} else {
folder.close();
}
}
folder.$title.addEventListener('click', () => {
saveFolderStates(collectFolderStates());
});
}

// Store params on the GUI instance for access in sliceModel
slicingGUI.userData = params;

Expand Down
9 changes: 9 additions & 0 deletions examples/visualizer/visualizer.css
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ body {
transform: scale(1.1);
}

@keyframes spin-once {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}

#reset.spinning {
animation: spin-once 0.5s ease-in-out;
}

.icon-row {
display: flex;
flex-direction: row;
Expand Down