-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Open
Description
I have tried my best to store and load the same structure that I visually see into the DB, but the component's schema keys and values are not being included, also, even if I store the HTML content into the DB, when loaded, most of the entities' component values lost, the following are simplified examples tried with:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>A-Frame Scene Saver</title>
<script src="https://aframe.io/releases/1.7.1/aframe.min.js"></script>
</head>
<body>
<div class="html">
<h2>Scene Management</h2>
<button onclick="createScene()">Add a Scene</button>
<select id="sceneSelect">
<option value="">Select a saved scene...</option>
</select>
<button onclick="loadScene()">Load Scene</button>
<button onclick="saveScene()">Save Scene</button>
<input type="text" id="sceneName" placeholder="Enter scene name to save">
</div>
<div id="sceneContainer"></div>
<script>
document.addEventListener("DOMContentLoaded", populateScenes);
function createScene() {
const sceneContainer = document.getElementById("sceneContainer");
if (!document.querySelector("a-scene")) {
sceneContainer.innerHTML = `
<a-scene>
<a-entity camera look-controls position="0 1.6 0"></a-entity>
</a-scene>
`;
}
}
function populateScenes() {
const sceneSelect = document.getElementById("sceneSelect");
const scenes = JSON.parse(localStorage.getItem("scenes") || "{}");
sceneSelect.innerHTML = '<option value="">Select a saved scene...</option>';
for (let name in scenes) {
let option = document.createElement("option");
option.value = name;
option.textContent = name;
sceneSelect.appendChild(option);
}
}
function saveScene() {
const sceneElement = document.querySelector("a-scene");
const sceneName = document.getElementById("sceneName").value.trim();
if (!sceneElement || !sceneName) return alert("No scene or name provided!");
let scenes = JSON.parse(localStorage.getItem("scenes") || "{}");
scenes[sceneName] = sceneElement.innerHTML;
localStorage.setItem("scenes", JSON.stringify(scenes));
populateScenes();
alert("Scene saved!");
}
function loadScene() {
const sceneName = document.getElementById("sceneSelect").value;
if (!sceneName) return alert("Select a scene!");
const scenes = JSON.parse(localStorage.getItem("scenes") || "{}");
const sceneContent = scenes[sceneName];
if (sceneContent) {
const sceneContainer = document.getElementById("sceneContainer");
sceneContainer.innerHTML = `<a-scene>${sceneContent}</a-scene>`;
}
}
</script>
<style>.html{z-index:999999999999;position:fixed;left:40%}</style>
</body>
</html>
and
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>A-Frame Scene Saver</title>
<script src="https://aframe.io/releases/1.7.1/aframe.min.js"></script>
<style>
#controls {
position: fixed;
top: 10px;
left: 10px;
z-index: 1000;
background: white;
padding: 10px;
border-radius: 5px;
}
</style>
</head>
<body>
<div id="controls">
<label for="sceneSelector">Choose Scene:</label>
<select id="sceneSelector"></select>
<button onclick="saveCurrentScene()">Save Current Scene</button>
</div>
<a-scene id="mainScene">
<!-- Default scene -->
<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
<a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
<a-sky color="#ECECEC"></a-sky>
</a-scene>
<script>
const DB_NAME = "AFRAME_SCENE_DB";
const STORE_NAME = "scenes";
let db;
// Open IndexedDB
function openDB() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(DB_NAME, 1);
request.onupgradeneeded = function (event) {
db = event.target.result;
if (!db.objectStoreNames.contains(STORE_NAME)) {
db.createObjectStore(STORE_NAME, { keyPath: "name" });
}
};
request.onsuccess = function (event) {
db = event.target.result;
resolve(db);
};
request.onerror = function (event) {
reject("Error opening IndexedDB");
};
});
}
// Save scene to IndexedDB
function saveScene(name, sceneHTML) {
const transaction = db.transaction([STORE_NAME], "readwrite");
const store = transaction.objectStore(STORE_NAME);
store.put({ name, sceneHTML });
}
// Load all scenes from IndexedDB
function loadScenes() {
const selector = document.getElementById("sceneSelector");
const transaction = db.transaction([STORE_NAME], "readonly");
const store = transaction.objectStore(STORE_NAME);
const getAllRequest = store.getAll();
getAllRequest.onsuccess = function () {
const scenes = getAllRequest.result;
selector.innerHTML = ""; // Clear existing options
// Add default option
let defaultOption = document.createElement("option");
defaultOption.value = "default";
defaultOption.text = "Default Scene";
selector.appendChild(defaultOption);
scenes.forEach((scene) => {
let option = document.createElement("option");
option.value = scene.name;
option.text = scene.name;
selector.appendChild(option);
});
};
}
// Load a specific scene by name
function loadSceneByName(name) {
const mainScene = document.getElementById("mainScene");
if (name === "default") {
const defaultHTML = getDefaultSceneHTML();
replaceSceneHTML(mainScene, defaultHTML);
return;
}
const transaction = db.transaction([STORE_NAME], "readonly");
const store = transaction.objectStore(STORE_NAME);
const getRequest = store.get(name);
getRequest.onsuccess = function () {
const result = getRequest.result;
if (result) {
replaceSceneHTML(mainScene, result.sceneHTML);
}
};
}
// Get default scene HTML as string (only children)
function getDefaultSceneHTML() {
return `
<a-box position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
<a-sphere position="0 1.25 -5" radius="1.25" color="#EF2D5E"></a-sphere>
<a-cylinder position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D"></a-cylinder>
<a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
<a-sky color="#ECECEC"></a-sky>
`;
}
// Event listener for select
document.getElementById("sceneSelector").addEventListener("change", function (e) {
loadSceneByName(e.target.value);
});
// Save current scene
window.saveCurrentScene = function () {
const sceneName = prompt("Enter scene name:");
if (!sceneName) return;
const mainScene = document.getElementById("mainScene");
// Only save child elements, not the <a-scene> itself
const sceneHTML = Array.from(mainScene.children)
.map(el => el.outerHTML)
.join("");
saveScene(sceneName, sceneHTML);
loadScenes(); // Refresh selector
};
// Initialize
openDB().then(() => {
loadScenes();
});
function replaceSceneHTML(sceneEl, htmlString) {
// Clear existing scene content
while (sceneEl.firstChild) {
sceneEl.removeChild(sceneEl.firstChild);
}
// Convert HTML string to DOM elements
const div = document.createElement('div');
div.innerHTML = htmlString.trim();
// Append each child to <a-scene>
Array.from(div.children).forEach(child => {
sceneEl.appendChild(child);
});
}
</script>
</body>
</html>
Metadata
Metadata
Assignees
Labels
No labels