Saving a scene to a localStorage

Hello,
I am trying to save a model that user made on a web site. I think the way to do that would be to store it in localStorage instead of downloading it and putting in a file.
My question is:
Do I must downlaod a model to save it on localStorage?
Since I already tried to use this doc to download the model I got this error:

npm install @babylonjs/serializers
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree       
npm ERR! 
npm ERR! While resolving: 3601@0.1.0
npm ERR! Found: @babylonjs/core@5.57.1
npm ERR! node_modules/@babylonjs/core
npm ERR!   @babylonjs/core@"^5.57.1" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer @babylonjs/core@"^6.0.0" from @babylonjs/serializers@6.3.1
npm ERR! node_modules/@babylonjs/serializers
npm ERR!   @babylonjs/serializers@"*" from the root project
npm ERR!
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.

Since I must use serializer to download and BABYLON.SceneSerializer.Serialize(scene) doesnt work I will have to overcome this problem.
What is heppening with the error?

Hello @babyloner ,

I am not sure what the error is, but can you try this code and let us know if it works.

        // using SerializeAsync instead of Serialize
        let serializedScene = await BABYLON.SceneSerializer.SerializeAsync(scene);
        let strScene = JSON.stringify(serializedScene);
        const blob = new Blob([strScene], { type: "octet/stream" });
        // you could then use this blob and store in local storage

I’m sure @RaananW and @labris will know something about the error.

About the functionality that you are trying to achieve, I was looking for the solution to a similar problem and what helped me was - converting the blob to a file and uploading that file to the server using an ‘xmlhttprequest’ and ‘multer’.

you are trying to use the 5 branch core with the 6 branch serializers. choose one of the major versions and stick to it :slight_smile:

you can’t store a blob in localStorage. You can store strings. so it would make more sense not to convert it to blob and store the serialized string directly. When you need it you can read the item and convert it to a blob to read it (os, well, use it directly, as a data URL)

1 Like

oh Noted !! :blush: :ok_hand:

I didnt really understand what should I do in case to be able to use serializer (I am not even looking at versions of npm’s I havent had similar error yet)?

I could store a blob as a string in localStorage and when I need it I can just parse it and use it, but I think I will still have to downlaod it to be able to store it.

By using that I get this error:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading ‘useDelayedTextureLoading’)

I found out how to install it.

When I try to use it I get this error:
Cannot read properties of undefined (reading ‘getEngine’)

At this line:
const serializedScene = BABYLON.SceneSerializer.Serialize(scene);

I just copied the code from docs.

there is more context needed here. Can you share a playground that doesn’t work?

I am working in react right now so I dont have a playground, but I can share the code

import * as BABYLON from '@babylonjs/core';
import { Vector3, HemisphericLight, PointerEventTypes } from '@babylonjs/core';
import '@babylonjs/loaders';
import 'babylonjs-serializers';
export default class Controller {
  constructor(
    model,
    name,
    id,
    getValue,
    lastDecal,
    deleteDecal,
    meshColor,
    finishedBttnRef
  ) {
    this._scene = null;
    this._store = {};
    this.model = model;
    this.name = name;
    this.id = id;
    this.getValue = getValue;
    this.lastDecal = lastDecal;
    this.deleteDecal = deleteDecal;
    this.meshColor = meshColor;
    this.clicked = {};
    this.finishedBttnRef = finishedBttnRef;
  }

  attachScene(scene) {
    this._scene = scene;
    this._store['enabledMesh'] = 'front';
    this._store['activeImage'] = 'HomePage/logo.png';
    this._store['activeDecal'] = 0;
    this._pointerObserver = this.attachPointerObserver(scene);
    this._hoverObserver = this.attachHoverObserver(scene);
    this._pointerObserverCloner = this.cloneDecal(scene);
    this.loadScene(scene);
    this.exportModel();
  }

  exportModel = (filename, scene) => {
    this.finishedBttnRef.current.addEventListener('click', async () => {
      console.log(1);
      let objectUrl;

      function doDownload(filename, mesh) {
        if (objectUrl) {
          window.URL.revokeObjectURL(objectUrl);
        }

        const serializedMesh = BABYLON.SceneSerializer.SerializeMesh(mesh);

        const strMesh = JSON.stringify(serializedMesh);

        if (
          filename.toLowerCase().lastIndexOf('.babylon') !==
            filename.length - 8 ||
          filename.length < 9
        ) {
          filename += '.babylon';
        }

        const blob = new Blob([strMesh], { type: 'octet/stream' });

        // turn blob into an object URL; saved as a member, so can be cleaned out later
        objectUrl = (window.webkitURL || window.URL).createObjectURL(blob);

        const link = window.document.createElement('a');
        link.href = objectUrl;
        link.download = filename;
        const click = document.createEvent('MouseEvents');
        click.initEvent('click', true, false);
        link.dispatchEvent(click);
      }

      doDownload();
    });
  };
}

please install @babylonjs/serializers in the right verion (the same version as core), otherwise it won’t work.

Oh, and - i wouldn’t import the entire BABYLON namespace, as it is not needed. import the classes you need, and leave the rest behind.

This is the core version “@babylonjs/core”: “^5.57.1”
I am trying to find similar versions of @babylonjs/serializers but I only get 6.3.1. Am I missing something or I can specify the version I want to install?

Maybe the problem could be that the button is outside of canvas.
In the code above I didnt provide scene, but if I provide scene and log it, I get undefined.
Maybe it would be better to just add babylon gui so I will have access to scene from canvas

I’m a bit puzzled by exactly what you mean here, you mean you want to have something like a remote storage? Your website’s user creates a model, and then can save it for later without having to download it?

Yes, that’s it. But I am thinking about how to set something in storage without having it downloaded.

In this case you should probably use something like Introduction to Azure Storage - Cloud storage on Azure | Microsoft Learn and download your user’s models to that remote storage and retrieve it later

Thanks you, I will try it.

you can set the version. either in package.json or while installing. or upgrade your core package to 6. otherwise it won’t really work.

How do I adjust the code to just save the model but not to download it?