How to make React button to change scene parameters

Hello friends,

There were similar questions here but none if them could give me a solution.
My knowledge of React is far from desired, but I believe it should be quite simple for those who know React.
I know how to do it in declarative way, but don’t want to use it.
So the question is: how to create a button to change scene parameters on click? Any working examples are welcome :slight_smile:

The trick is, of course, is getting the scene instance. I have read enough framework source code to probably do this, whether React wants to or not. From engine.ts

    /**
     * Gets the latest created engine
     */
    public static get LastCreatedEngine(): Nullable<Engine> {
        return EngineStore.LastCreatedEngine;
    }

    /**
     * Gets the latest created scene
     */
    public static get LastCreatedScene(): Nullable<Scene> {
        return EngineStore.LastCreatedScene;
    }

You might want to wait for a React specific answer, but think this should work unless you have multiple concurrent scenes.

1 Like

depending on your code structure, if you get a ref to the scene then you can use it in a button click handler. You didn’t specify if it was a GUI button or DOM one, but here is a DOM one because GUI one you likely have access to scene already:

import { useRef, useEffect } from 'react';

const MyMyScene = () => {
  const sceneRef = useRef();
  onButtonClicked = () => {
   if (sceneRef.current) {
    // sceneRef.current is a scene object
   }
  }

  useEffect(() => {
    // maybe here you set your sceneRef
    sceneRef.current = new Scene(...);

    return () => {
       // dispose Engine/Scene here
    }
  }, []);

  return <div>
      <button onClick={onButtonClicked}>click me</button>
    </div>
}

edit: here is a non-declarative way to integrate babylonjs-hook - npm (npmjs.com) you could just copy/paste what you wanted - there is a hook useScene.

1 Like

Thank you for your answer.
I made it work with

   onButtonClicked = () => {
    this.scene.meshes[0].position.z -= 0.1 // just for example
   }

Still don’t understand where I need to use Ref. I tried with this repo - GitHub - superbright/SB-BabylonJS-React: Babylon JS React Wrapper

1 Like

Yeah, you would use this.scene then for regular React Component. I was referring to Functional Components that can use hooks. Your project is 4 years old, so that way was more typical back then. You can use both functional and regular Components together in a project. All of the react docs were moved also to Functional, so I tend to provide answers that way nowadays. Glad you got it working - cheers.

The problem is that I didn’t find any working open source React+Babylon.js project or template with functional components and non-declarative way.
Probably this - babylonjs-cra-vanilla-ts/src at master · brianzinn/babylonjs-cra-vanilla-ts · GitHub could help but it doesn’t work anymore.
So, I am still in the dark :slight_smile: and, as I already mentioned, would be grateful for any working example.

those vanilla repos I should archive - they were an experiment in code re-use gone wrong.

what about the babylonjs-hook npm linked above? it’s declarative and there are at least a couple hundred projects using it and most of them should be working and there is an example in the readme:
Network Dependents · brianzinn/babylonjs-hook (github.com)

You only need to declare the component on the page, but that’s primarily to render a canvas element to to attach to. You could copy what is needed from there. I suppose you could make a hook that does a document createElement for a canvas without needing to declare anything at all though. some UI libraries do similar things.

Thanks for the dependencies link, I’ll explore them and hopefully will find some good button :slight_smile:

I understand what you mean theoretically, but cannot find how to use it in practice, surely because of my poor knowledge of React.

Did you just want an example where a button can access the scene?? I have some time tomorrow to make a demo.

Sure, it would help a lot!

sorry got slammed with work… will msg when ready. thx for patience.

@labris does this help?
codesandbox-react-tsx (forked) - CodeSandbox
NOTE: useScene won’t work if declared outside of SceneComponent, but you could still useRef on the scene creation callback.

More explanations here:
https://brianzinn.github.io/react-babylonjs/guides/react-with-imperative-babylonjs

The above codesandbox is actually forked right from the docs with “Run in Sandbox” button :smile:

Thanks a lot, it definitely will help, and now I can click the button and it changes something! :slight_smile:

These words are still sound like a riddle for me but I believe that after some React practice I’ll solve it (or probably you could put some piece of code how to do it?).

Yes - feel free to ask more questions!!