microsoft / mixed-reality-extension-sdk

The Mixed Reality Extension SDK enables developers to build 3D world extensions for AltspaceVR, using Node.JS.
MIT License
142 stars 61 forks source link

Idea: jsx-based scene graph syntax #322

Open eanders-ms opened 5 years ago

eanders-ms commented 5 years ago

Provide a way to describe the scene in a react-native kind of syntax, in .tsx/.jsx files:

/// in app.tsx:
class MyApp extends MRE.ReactApp {
    ...
    render() {
        return (
            <MyScene>
                <Actor src=`${baseUrl}/monkey.gltf`>
                    <Appearance>
                        // etc.
                    </Appearance>
                </Actor>
            </MyScene>);
    }
eanders-ms commented 5 years ago

An independent render method might integrate better with what we have today:


class App {
    onStarted() {
        this.context.render(
            <MyScene>
                <Actor src=`${baseUrl}/monkey.gltf`>
                    <Appearance>
                        // etc.
                    </Appearance>
                </Actor>
            </MyScene>
        );
    }
}
sorenhan commented 5 years ago

I think it makes sense to implement, but I'd want this to be implemented as a layer on top of/outside the MRE SDK core, as it should internally just call a number of MRE API calls, which shouldn't affect the protocol/client implementation. Second note: I understand that "render" is standard React terminology, but it's would be non-standard for 3d engine/game developer terminology. I'd want something that is less confusing and more descriptive - maybe createSceneGraph?

eanders-ms commented 5 years ago

I think we'd implement similar to the way React works, with state and props. It would have a renderer and detect changes in the scene graph made by calls to setState. In an implementation like that, I think render makes sense for individual components (shown below), but for mounting the scene graph (what is shown above), something like what you suggest makes sense, but is against convention.

Pseudo-code example with components. This example defines a chess piece that can optionally be selected. Notice the state change in the toggleSelected method of ChessPiece. This state change triggers new render calls in the subtree:

/// chesspiece.tsx

type ChessPieceProps {
    src: string;
    selected: boolean;
}

type ChessPieceState {
    selected: boolean;
}

class ChessPiece extends MREact.Component {
    constructor(props: ChessPieceProps) {
        super(props);
        this.state = { selected: props.selected };
    }

    // This state change triggers a new `render` calls in this scene subtree.
    toggleSelected() {
        this.setState({ selected: !this.state.selected });
    }

    render() {
        return(
            <Actor src=this.props.src onClick={ () => this.toggleSelected() }>
                <Selected visible=this.state.selected />
            </Actor>);
    }
}

/// selected.tsx

type SelectedProps {
    src: string;
    visible: boolean;
}

class Selected extends MREact.Component {
    constructor(props: SelectedProps) {
        super(props);
    }

    render() {
        return(
            <Actor src=this.props.src>
                <Appearance visible=this.props.visible />
            </Actor>);
    }
}

For mounting the scene, I agree that render is an odd name, but it is what React does and still lean toward going with convention.

tombuMS commented 5 years ago

I think that if we are presenting this as a npm package for react developers who want to build MRE's, this could be an awesome approach. At the core we will always have the MRE way of doing things and that a developer can always build directly with the MRE SDK, but for someone familiar with working in React, this could be a huge win in getting a large community of developers interested in MRE's. I personally love this.

eanders-ms commented 5 years ago

I would only write MREs this way if it existed.