From 6cd590e9b78cf424382d969eb772774e206c364e Mon Sep 17 00:00:00 2001 From: Soham Samanta Date: Fri, 12 Dec 2025 15:45:44 -0500 Subject: [PATCH] new export :) --- WebVis/src/GUI.js | 31 ++++++++++++++++++++----------- WebVis/src/Scenario.js | 10 +++++++++- WebVis/src/utils.js | 31 +++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/WebVis/src/GUI.js b/WebVis/src/GUI.js index d355b8f..786b79d 100644 --- a/WebVis/src/GUI.js +++ b/WebVis/src/GUI.js @@ -4,7 +4,7 @@ import { Scenario } from './Scenario.js'; import { gScene, gLights, gRenderer, gModules, gReferenceModule, gModulePositions, gCanvas, gHighlightModule } from './main.js'; import { moduleBrush, pathfinderData, WorkerType, MessageType, ContentType, VisConfigData, ModuleType, getModuleAtPosition } from './utils.js'; import { CameraType } from "./utils.js"; -import { saveConfiguration, downloadConfiguration } from './utils.js'; +import { saveConfiguration, downloadConfiguration, downloadScenario } from './utils.js'; import { Module } from './Module.js'; // Exact filenames of example scenarios in /Scenarios/ @@ -257,17 +257,17 @@ window._pathfinderRun = function() { /* GUI setup */ /* ****************************** */ // GUI elements for general settings -export const gGraphicsGui = new GUI( { title: "Graphics",width: window.innerWidth*.1, container: document.getElementById("controlBar") } ).close(); +export const gGraphicsGui = new GUI( { title: "Graphics",width: window.innerWidth*.08, container: document.getElementById("controlBar") } ).close(); let style_controller; // GUI elements for Visualizer Mode -export const gAnimGui = new GUI( { title: "Animation",width: window.innerWidth*.1, container: document.getElementById("controlBar") } ); -export const gScenGui = new GUI( { title: "Scenario",width: window.innerWidth*.1, container: document.getElementById("controlBar") } ).close(); +export const gAnimGui = new GUI( { title: "Animation",width: window.innerWidth*.08, container: document.getElementById("controlBar") } ); +export const gScenGui = new GUI( { title: "Scenario",width: window.innerWidth*.08, container: document.getElementById("controlBar") } ).close(); // GUI elements for Configurizer Mode -export const gModuleBrushGui = new GUI( { title: "Brush",width: window.innerWidth*.1, container: document.getElementById("controlBar") } ).hide(); +export const gModuleBrushGui = new GUI( { title: "Brush",width: window.innerWidth*.08, container: document.getElementById("controlBar") } ).hide(); let brushColor_selector; -export const gLayerGui = new GUI( { title: "Layer",width: window.innerWidth*.1, container: document.getElementById("controlBar") } ).hide(); -export const gSelectedModuleGui = new GUI( { title: "Selected Module",width: window.innerWidth*.1, container: document.getElementById("controlBar") } ).hide(); +export const gLayerGui = new GUI( { title: "Layer",width: window.innerWidth*.08, container: document.getElementById("controlBar") } ).hide(); +export const gSelectedModuleGui = new GUI( { title: "Selected Module",width: window.innerWidth*.08, container: document.getElementById("controlBar") } ).hide(); export const zSliceController = gLayerGui.add(moduleBrush, 'zSlice', VisConfigData.bounds.z.min - 2, VisConfigData.bounds.z.max + 2, 1).name("Layer").onChange((value) => { if (window._isPainterModeActive) { updateVisibleModules(value); @@ -275,8 +275,9 @@ export const zSliceController = gLayerGui.add(moduleBrush, 'zSlice', VisConfigDa }); // GUI element for Pathfinder and developer options -export const gPathfinderGui = new GUI( { title: "Pathfinder",width: window.innerWidth*.1, container: document.getElementById("controlBar") } ).close(); -export const gModeGui = new GUI( { title: "View/Edit",width: window.innerWidth*.1, container: document.getElementById("controlBar") } ); +export const gPathfinderGui = new GUI( { title: "Pathfinder",width: window.innerWidth*.12, container: document.getElementById("controlBar") } ).close(); +export const gExportGui = new GUI( { title: "Export",width: window.innerWidth*.08, container: document.getElementById("controlBar") } ); +export const gModeGui = new GUI( { title: "View/Edit",width: window.innerWidth*.12, container: document.getElementById("controlBar") } ); // Global variables for module selection let selectedModule = null; const selectedModuleColor = { color: 0x808080 }; @@ -451,18 +452,26 @@ document.addEventListener("DOMContentLoaded", async function () { } } }, 'loadFinal').name("Load Final Config"); - gPathfinderGui.add({ + + // Export Controls + gExportGui.add({ downloadInitial: function() { downloadConfiguration(true); } }, 'downloadInitial').name("Download Initial"); - gPathfinderGui.add({ + gExportGui.add({ downloadFinal: function() { downloadConfiguration(false); } }, 'downloadFinal').name("Download Final"); + gExportGui.add({ + downloadScenario: function() { + downloadScenario(); + } + }, 'downloadScenario').name("Download Scenario"); + const _folder = gScenGui.addFolder("Example Scenarios"); for (let i in EXAMPLE_SCENARIOS) { let ex = EXAMPLE_SCENARIOS[i]; diff --git a/WebVis/src/Scenario.js b/WebVis/src/Scenario.js index f0f0dd3..2f6585a 100644 --- a/WebVis/src/Scenario.js +++ b/WebVis/src/Scenario.js @@ -1,5 +1,5 @@ import * as THREE from 'three'; -import {CameraType, ModuleType, MoveType, VisConfigData} from "./utils.js"; +import {CameraType, ModuleType, MoveType, VisConfigData, pathfinderData} from "./utils.js"; import { Module } from "./Module.js"; import { Move } from "./Move.js"; import { MoveSet } from "./MoveSet.js"; @@ -24,6 +24,10 @@ export class Scenario { // Reset Data VisConfigData.nextModID = 0; VisConfigData.clearBounds(); + + // Store the scenario content for export + pathfinderData.currentScenario = rawString; + console.log("Stored scenario content, length:", rawString ? rawString.length : 0); // remove '\r' characters rawString = rawString.replace(/\r/g, ''); @@ -37,6 +41,10 @@ export class Scenario { let metadataLines = metadataString.split('\n'); let scenarioName = metadataLines[0]; let scenarioDescription = metadataLines[1]; + + // Store the scenario name for export + pathfinderData.currentScenarioName = scenarioName; + let scenarioModuleType; switch (metadataLines[2]) { case 'CUBE': scenarioModuleType = ModuleType.CUBE; break; diff --git a/WebVis/src/utils.js b/WebVis/src/utils.js index 41fa454..e9eec9d 100644 --- a/WebVis/src/utils.js +++ b/WebVis/src/utils.js @@ -85,6 +85,8 @@ export let pathfinderData = { config_i: '{"exists": false}', config_f: '{"exists": false}', scen_out: 'INVALID SCENE', + currentScenario: null, // Stores the currently loaded scenario content + currentScenarioName: null, // Stores the name of the currently loaded scenario settings: { name: "WebPathfinder-Out", description: "Output produced by a valid Pathfinder run.", @@ -261,3 +263,32 @@ export function downloadConfiguration(isInitial = true) { // Clean up URL.revokeObjectURL(url); } + +// Function to download scenario file +export function downloadScenario() { + // Try to export current scenario first, then pathfinder output + let scenarioContent = pathfinderData.currentScenario || pathfinderData.scen_out; + + console.log("Download scenario called - currentScenario:", pathfinderData.currentScenario ? "exists" : "null"); + console.log("Download scenario called - scen_out:", pathfinderData.scen_out); + + if (!scenarioContent || scenarioContent === 'INVALID SCENE') { + console.warn("No valid scenario to download. Please load a scenario first."); + return; + } + + // Use current scenario name if available, otherwise use settings name + const scenarioName = (pathfinderData.currentScenarioName || pathfinderData.settings.name) + ".scen"; + + // Create blob and download link + const blob = new Blob([scenarioContent], { type: "text/plain" }); + const url = URL.createObjectURL(blob); + + const link = document.createElement("a"); + link.href = url; + link.download = scenarioName; + link.click(); + + // Clean up + URL.revokeObjectURL(url); +}