Skip to content

Latest commit

 

History

History
183 lines (122 loc) · 8.94 KB

File metadata and controls

183 lines (122 loc) · 8.94 KB

Spatialstrates API

Importing and Exporting Code Between Fragments

When using Spatialstrates, code from other fragments can be imported using the import keywords in connection with a CSS selector. For example, to import the <TodoItem> component from a fragment with the id todo-item-component the following code can be used:

import { TodoItem } from '#todo-item-component';

export function MyOtherComponent() {
    return <TodoItem />;
}

Dynamic Components

In order for Spatialstrates to render new components that are generated by the user, it provides a Dynamic Components mechanism, which automatically scans the webstrate for new fragments with components that should be rendered in the scene. For components to be rendered in the scene, they have to be part of a "JavascriptBabel" (data-type="text/javascript+babel") code fragment with either of the following classes:

Selector Description
.dynamic-gui-component 2D GUI components that are rendered in the GUI of Spatialstrates, e.g., the Menu or the Spatialstrates logo.
.dynamic-scene-component 3D scene components that are rendered in the 3D scene view of Spatialstrates.
.dynamic-movable-scene-component Movable components for the 3D scene view.
.dynamic-canvas-component 2D canvas components that are rendered in the 2D canvas view of Spatialstrates.
.dynamic-shape-component ShapeUtil classes (for tldraw) for custom shapes that should be enabled in the 2D canvas view.

For each dynamic component the App component will attempt to render its Main() function. This function should be exported in the dynamic component like this:

export function Main() {
    return <div>What to render in the scene or 2D GUI.</div>;
}

Whenever code within the dynamic component is changed, the App component will automatically re-render the component in the scene. This allows for live coding and immediate feedback in the scene—even across devices.

Menu

See here for the documentation of the menu component.

Controller Menu

See here for the documentation of the controller menu component.

Varv React

Varv is used as the persisted data store in Spatialstrates. To better integrate Varv into React, there is a small API to access Varv concept instances and properties from within React components (see code here).

<Varv>

A component that renders its children for each concept instance found for the given concept or property. The concept, property, and if parameters work similar to how the DOM View in Varv works (see here).

Parameter Description
children The child components that should be rendered for each concept instance found for the given concept or property.
concept The concept, whose concept instances should be rendered.
property The property of a concept instance, whose concept instances should be rendered.
if Takes a property name of a boolean property. Only concept instances where this property is true are rendered.
<Varv concept="conceptName">
    <MyComponent />
</Varv>

useProperty(propertyName)

A hook to access the value of a property of a concept instance. It can only be used within a <Varv> component. The value is updated whenever the property changes and works similar to React's useState hook.

Parameter Description
propertyName The name of the property to access.
const [value, setValue] = useProperty('propertyName');

Movables

Warning

This section is outdated. The new version of Spatialstrates requires both a 3D component and 2D shape to use movables across both the 3D scene and 2D canvas views.

Movables are a class of components that are placed in the 3D scene and that have their position and rotation persisted and synchronized using Varv.

Movables rely on Varv for sharing and persisting their location and rotation across clients. To use them, it is required to add a concept definition. See the example below for how to define a concept for a new movable component.

<Movable>

The Movable component is a wrapper for other movable components. It handles grabbing events and synchronization of the position and rotation of the movable with the data store.

All children of the Movable component will be moved when the Movable is dragged. The handle of a Movable describes the part of a movable that can be dragged. For example, when creating a board game, the board could be the handle to move it, while the pieces on the board would be the children of the Movable and provide their own interactive behavior. But also the whole component can be the handle, this is, for instance, the case for the sticky note, trashcan, and image.

It can be imported from '#Movable .default'.

Parameter Description
children The children of the movable.
handle The handle of the movable.
upright Whether the movable should be upright or not. If true, it will only rotate around the y-axis.
onDragStart The function to call when the movable is started to be dragged.
onDragEnd The function to call when the movable is stopped to be dragged.
onDragging The function to call when the movable is being dragged.

createMovable

Creates a new movable concept instance of the given concept type with the given properties. The new movable is placed in front of the current camera position by default.

It can be imported from '#Movable .helpers'.

Parameter Description
concept The name of the concept that should be created.
properties An object with property values for the new movable.

State Properties

The following properties are available in concept instances that are derived from the Movable concept:

Property Description
position The position of the movable in the 3D scene.
rotation The rotation of the movable in the 3D scene.
selected Whether the movable is selected or not.
hovered Whether the movable is hovered or not.
beingDragged Whether the movable is being dragged or not.

Example

Concept Definition Fragment

{
    "concepts": {
        "MyMovable": {
            "schema": {
                "myProperty": "string"
            },
            "extensions": {
                "inject": [ "Movable" ]
            }
        }
    }
}

Custom Movable Component

import React from 'react';
const { useMemo } = React;

import { Varv, useProperty } from '#VarvReact';
import { Movable } from '#Movable .default';
import { Text } from '#Text .default';

function MyMovable() {
    const [myProperty, setMyProperty] = useProperty('myProperty');

    const handle = useMemo(() => <Box args={[0.15, 0.15, 0.15]}>
        <meshStandardMaterial color="red" />
    </Box>, []);

    return <Movable handle={handle} upright={false}>
        <Text>{myProperty}</Text>
    </Movable>;
}

export function Main() {
    return <Varv concept="MyMovable">
        <MyMovable />
    </Varv>;
}