How to communicate between an external button and Babylon scene?

I hava a new question: How to communicate between an external button and Babylon scene?
(Sorry I didn’t use PG, because it not just about BabylonJS)

My Enviroment:

React and BabylonJS (Although I’m not familiar with any of them :sob:)

What I want to do:

  1. Paint a babylon scene on page
  2. Add a button outside babylon scene
  3. When I click this button, I want babylon scene have some changes, such as changing camera inertia

My idea:

May I set states for class BabylonScene? I use constructor to init a inertia state and executed successfully. I use a button onClick event to drive a reset inertia function, this inertia state was changed, but camera inertia of babylon scene is still the same as previous situation.

Structure of my code just like this:

export default class BabylonScene extends React.Component<{}, {}> {
        constructor(props){
                super(props);
                this.state = {
                        inertia: 0.5,
                }
        }

        resetInertia(){
                this.setState({
                        inertia: 10,
                });
        }

        onSceneMount = (e:any) => {
                /* Some preparation */
                camera.inertia = this.state.inertia;
                
                /* Other function */
        }

        render(){
                return(
                        <div>
                                <button onClick={this.resetInertia.bind(this)}>Reset Inertia</button>
                                <BabylonScene onSceneMount={this.onSceneMount} />
                        </div>
                );
        }    
}
1 Like

Inertia is a number, it is not shared like a class or an object. You have to affect it to the camera every time you want to change it

Something like:

resetInertia(){
                this.setState({
                        inertia: 10,
                });
               camera.inertia = 1.0; // This is where you really set it
        }

Thank for your reply firstly!
I think I understand your point of view.
But I need to click an external button to change some attributes for babylon scene.

<div>
    <button id="button">Button</button>
    <BabylonScene />
</div>

Just like above code, I want to click this button for changing something in babylon scene.
Is this feasible? And do you have some idea for it?

Thank for your reply again!

Thank for your reply firstly!
I think I understand your point of view.
But I need to click an external button to change some attributes for babylon scene.

Copy to clipboard

<div>
    <button id="button">Button</button>
    <BabylonScene />
</div>

Just like above code, I want to click this button for changing something in babylon scene.
Is this feasible? And do you have some idea for it?

Thank for your reply again!

Hello. I think I was asking the same question and got a very good answer.

thanks to @RaananW

1 Like

Excellent answer, M!

Can you/others/anyone show us… what to put inside onclick=“here”… when the button is NOT created by the scene-code? (thx)

I remember having problems “crossing the scope border”… doing strange things like:

<form>
    <button onclick="window.someFunctionName(canArgsPassHere?)"> click me </button>
</form>

Or should it be window.document.someFunction(some args)?

If someone could barf-out a mini tutorial about crossing that border, that would be great. It might be nice to have an example of a webpage button running a scene function, then next click, running a DIFFERENT function, then next click… run first function again, etc.

Can onclick be easily re-targeted… each button press? Must JS that is placed inside of onclick quotes… be able to “see” the scene-function that is being (re-) targeted? Any help with that stuff… would be welcomed. I learned how to “properly” do that stuff, once before, but I forgot what it was. :slight_smile:

We might want quoted strings… to be allowed inside (canArgsPassHere), too. Do we use single quotes on the strings in there, or escaped quotes, or… hmm. (thx, everyone)

use getElementById
I did it like this:

    let myButton1 = document.getElementById("changeShotButton");
    myButton1.addEventListener("click", function(){
        myScene.meshes[0].isVisible = !myScene.meshes[0].isVisible;
    });

to have a different function executed at each click, you could use a counter
use a variable that gets increased by one each function call.
and then use the switch statement:
https://www.w3schools.com/js/js_switch.asp

1 Like

Thx, that’s a good way, for sure. But… that doesn’t allow the button to be the boss and send different and/or many args/params to the function.

What if… sometimes the button wants to onclick-call somefunction(“fred”, window, document, 45, eval(‘Math.PI/4’), Date.time(), this.style.backgroundColor, 0xCAFFEE); ??

Sidenote: Must we wait for webpage.onload… before we set the button’s onclick value… because if we set it BEFORE onload, it can’t find a function named ‘somefunction’? shrug

What if the button… is the boss, and scene code is dis-allowed from changing the button’s onclick values? Thoughts (anyone)? Possible? Nightmare? It seems similarly complicated as trying to cross a USA border, eh? heh ahem.

The approach is the same as with some HTML button and some Javascript.
While there are ways like document.getElementById or onclick etc, one can also use all power of HTML data-* attribute to embed custom data attributes on all HTML elements. The stored (custom) data can then be used in the page’s JavaScript.

Here is just example (unfinished prototype) where some camera values are written dynamically in the <div> element outside canvas (press Camera button); also there is a bunch of other simple functions for 3D model demonstration - https://mu-so.ru/3d/v112/