threlte logo
@threlte/theatre

<SheetObject>

The <SheetObject> component allows you to pool the properties of a logical entity which can be a anything from a single material, multiple meshes or a complete scene. The component <SheetObject> and make them editable and animatable in the Theatre.js studio. It’s a great choice if you are making a reusable Threlte component which you want to make editable in the Theatre.js studio.

Theatre.js Docs

   
Sheet ObjectSheet Object ManualSheet Object API Reference

Overview

The <SheetObject> component offers several distinct ways to declare and syncronize props in the Theatre.js studio. Convenient auto prop APIs address common usecases and allow quick and easy prop declaration. Meanwhile, manual props APIs allow full customization of prop declaration. Many of these are offered through slot props.

<script lang="ts">
  import { Canvas } from '@threlte/core'
  import { Sequence, Theatre } from '@threlte/theatre'
  import Scene from './Scene.svelte'
  import state from './state.json'
</script>

<div>
  <Canvas>
    <Theatre
      config={{
        state
      }}
    >
      <Sequence
        autoplay
        iterationCount={Infinity}
      >
        <Scene />
      </Sequence>
    </Theatre>
  </Canvas>
</div>

<style>
  div {
    width: 100%;
    height: 100%;
  }
</style>
<script lang="ts">
  import { T } from '@threlte/core'
  import { RoundedBoxGeometry, interactivity, useCursor } from '@threlte/extras'
  import { SheetObject } from '@threlte/theatre'
  import { DEG2RAD } from 'three/src/math/MathUtils.js'

  interactivity()

  const { onPointerEnter, onPointerLeave } = useCursor()
</script>

<SheetObject
  key="Directional Light"
  let:Sync
  let:Transform
>
  <Transform>
    <T.DirectionalLight castShadow>
      <Sync
        intensity
        color
      />
    </T.DirectionalLight>
  </Transform>
</SheetObject>

<SheetObject
  key="Ambient Light"
  let:Sync
>
  <T.AmbientLight>
    <Sync
      intensity
      color
    />
  </T.AmbientLight>
</SheetObject>

<T.PerspectiveCamera
  makeDefault
  position={[5, 5, 5]}
  on:create={({ ref }) => {
    ref.lookAt(0, 0, 0)
  }}
/>

<SheetObject
  key="Box"
  let:Sync
  let:Transform
  let:select
  let:deselect
>
  <Transform>
    <T.Mesh
      castShadow
      on:click={select}
      on:pointerenter={onPointerEnter}
      on:pointerleave={onPointerLeave}
      on:pointermissed={deselect}
    >
      <RoundedBoxGeometry radius={0.1} />
      <T.MeshStandardMaterial
        let:ref
        transparent
      >
        <Sync
          type={ref}
          color
          roughness
          metalness
          side
          opacity
        />
      </T.MeshStandardMaterial>
    </T.Mesh>
  </Transform>
</SheetObject>

<T.Mesh
  receiveShadow
  position.y={-1}
  rotation.x={-90 * DEG2RAD}
>
  <T.CircleGeometry args={[1.4, 48]} />
  <T.MeshStandardMaterial />
</T.Mesh>
{
  "sheetsById": {
    "default": {
      "staticOverrides": {
        "byObject": {
          "Directional Light": {
            "intensity": 2.600000000000001,
            "position": {
              "x": 0.3394033225355889,
              "y": 2.3720157022596795,
              "z": 0.09009663353739894
            },
            "rotation": {
              "x": 0,
              "y": 0,
              "z": 0
            },
            "scale": {
              "x": 1,
              "y": 1,
              "z": 1
            },
            "color": {
              "r": 0.9372549019607843,
              "g": 0.8784313725490196,
              "b": 0.7686274509803922,
              "a": 1
            }
          },
          "Ambient Light": {
            "intensity": 1.15,
            "color": {
              "r": 0.43137254901960786,
              "g": 0.4745098039215686,
              "b": 0.7176470588235294,
              "a": 1
            }
          },
          "Box": {
            "helo": {
              "position": {
                "x": 0,
                "y": 0.028659367564094484,
                "z": 0
              },
              "rotation": {
                "x": 0,
                "y": 0,
                "z": 0
              },
              "scale": {
                "x": 1,
                "y": 1,
                "z": 1
              }
            },
            "color": {
              "r": 0.0196078431372549,
              "g": 1,
              "b": 0,
              "a": 1
            },
            "position": {
              "x": 0,
              "y": 0,
              "z": 0
            },
            "rotation": {
              "x": 0,
              "y": 0,
              "z": 0
            },
            "scale": {
              "x": 1,
              "y": 1,
              "z": 1
            },
            "side": "f",
            "opacity": 1,
            "metalness": 0.3797468354430377,
            "roughness": 0.38607594936708833
          }
        }
      },
      "sequence": {
        "subUnitsPerUnit": 30,
        "length": 4,
        "type": "PositionalSequence",
        "tracksByObject": {
          "Box": {
            "trackData": {
              "XpQldofCoc": {
                "type": "BasicKeyframedTrack",
                "__debugName": "Box:[\"position\",\"x\"]",
                "keyframes": [
                  {
                    "id": "iGoSxeB7Tg",
                    "position": 0,
                    "connectedRight": true,
                    "handles": [
                      0.5,
                      1,
                      0.5,
                      0
                    ],
                    "type": "bezier",
                    "value": 0
                  }
                ]
              },
              "DIrxDuzcU2": {
                "type": "BasicKeyframedTrack",
                "__debugName": "Box:[\"position\",\"y\"]",
                "keyframes": [
                  {
                    "id": "RmM1HUOqZm",
                    "position": 0,
                    "connectedRight": true,
                    "handles": [
                      0.5,
                      1,
                      0.455,
                      0.03
                    ],
                    "type": "bezier",
                    "value": 0
                  },
                  {
                    "id": "5MNKDVNvWP",
                    "position": 2,
                    "connectedRight": true,
                    "handles": [
                      0.515,
                      0.955,
                      0.455,
                      0.03
                    ],
                    "type": "bezier",
                    "value": -0.2
                  },
                  {
                    "id": "h_vCrfvuFs",
                    "position": 4,
                    "connectedRight": true,
                    "handles": [
                      0.515,
                      0.955,
                      0.5,
                      0
                    ],
                    "type": "bezier",
                    "value": 0
                  }
                ]
              },
              "5yT_h05zwt": {
                "type": "BasicKeyframedTrack",
                "__debugName": "Box:[\"position\",\"z\"]",
                "keyframes": [
                  {
                    "id": "2FKQERGrJH",
                    "position": 0,
                    "connectedRight": true,
                    "handles": [
                      0.5,
                      1,
                      0.5,
                      0
                    ],
                    "type": "bezier",
                    "value": 0
                  }
                ]
              }
            },
            "trackIdByPropPath": {
              "[\"position\",\"x\"]": "XpQldofCoc",
              "[\"position\",\"y\"]": "DIrxDuzcU2",
              "[\"position\",\"z\"]": "5yT_h05zwt"
            }
          }
        }
      }
    }
  },
  "definitionVersion": "0.4.0",
  "revisionHistory": [
    "qqJwziYf9rQuLpNb",
    "3WZqMkutbe2nKFJw",
    "H4q1oRw5vKb-x7io",
    "fFmuTDfiXVI1Yc10"
  ]
}

Auto Props

The <Sync> component automatically infers and synchronizes props of its parent component. Meanwhile the <Transform> component creates position and rotation props for its child components, and adds transform controls to the them.

Manual Props

Sometimes we want to control prop declaration manually for better control when implementing custom domain specific props. We can achieve this using manual prop declaration. Provide the props property to the component <SheetObject> for a manual property declaration.

<SheetObject
  props={{
    x: 0
  }}
  let:values
>
  <T.Mesh position.x={values.x} />
</SheetObject>

You can also use the <Declare> prop slot component to colocate your manual declaration with other code.

Selection

The <SheetObject> component offers a slot prop based API for controlling selection in the Theatre.js studio. Simply declare the select and deselect methods and the selected variables to use it. You then need to use these in the mesh of your choice; see the example above for a demonstration.

Component Signature

Props

name
type
required
default

key
string
yes

detach
boolean
no
false

props
UnknownShorthandCompoundProps
no