npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@unseenco/theatre-threejs

v0.1.16

Published

Three.js devtools extension for Theatre.js Studio

Readme

@unseenco/theatre-threejs

Three.js helpers and Studio extension for Theatre.js.

Runtime helpers (autoAddObject, autoAddMaterial, autoAddCamera, …) import from the package root and do not load Studio. Studio devtools (buildExtension) import from @unseenco/theatre-threejs/extension.

Usage

import studio from '@unseenco/theatre-studio'
import {autoAddObject} from '@unseenco/theatre-threejs'
import {buildExtension} from '@unseenco/theatre-threejs/extension'

let activeScene = scene1

// Register Three.js objects on Theatre sheets
autoAddObject(mesh, sheet)

const devtools = buildExtension({
  renderer,
  scenes: [
    {scene: scene1, camera: camera1},
    {name: 'Scene 2', scene: scene2, camera: camera2},
  ],
  studio,
  // Prefer config callbacks to receive persisted restore during init.
  onSceneSwitch(_name, scene) {
    activeScene = scene
  },
  onOrbitModeSwitch(enabled) {
    // e.g. pause gameplay camera while orbiting
  },
})

studio.extend(devtools.extension)

// When the app switches scenes outside the toolbar flyout:
// devtools.switchScene('Scene 2')
// or: devtools.switchScene(1)

function loop() {
  requestAnimationFrame(loop)
  devtools.update()
  renderer.render(activeScene, devtools.getCamera())
}

The extension adds a toolbar flyout to switch between scenes (when more than one is configured), a toggle between your scene camera and an OrbitControls dev camera, and orbit-mode tools for camera frustum visualization, line overlays, and interactive transform editing. Use devtools.isOrbitMode() to read the current mode. Pass onOrbitModeSwitch / onSceneSwitch in the buildExtension config to react to persisted restore during init; the returned devtools.onOrbitModeSwitch() / devtools.onSceneSwitch() methods also accept late subscribers but only receive subsequent changes. Call devtools.switchScene(nameOrIndex) when your app changes scenes outside the toolbar so the extension stays in sync; devtools.getActiveSceneName() returns the current scene name.

configureTheatreThreejs

Set project-wide defaults once at startup. Excludes from defaults and per-call autoAddObject options are merged.

import {configureTheatreThreejs} from '@unseenco/theatre-threejs'

configureTheatreThreejs({
  autoAddObject: {
    exclude: {uniforms: ['uTime']},
  },
})

autoAddObject

Automatically adds a Three.js Object3D to a Theatre sheet, parsing transform data (position, rotation, scale, visible) and material properties (colors, scalars, vectors, textures, shader uniforms).

import {autoAddObject} from '@unseenco/theatre-threejs'

const sheetObject = autoAddObject(mesh, sheet, {
  objectKey: 'My Mesh',
  exclude: {transform: ['scale'], material: ['normalMap']},
  include: {material: ['color', 'metalness', 'roughness']},
  trackMaterial: true, // default when the object has a material
})

Shared materials

If two meshes registered with autoAddObject share the same Three.js Material instance, the package auto-splits that material into its own Theatre object under Shared Materials / <material.name>, removes material props from the first mesh, and links both via showPropsOf. Name your materials for stable keys; unnamed materials warn and fall back to a UUID-based key. Use trackMaterial: false to opt out, or call autoAddMaterial first to own the material object yourself.

Static and transient props

When autoAddObject registers props on a Theatre sheet object, most props are static: they are saved in project state, can be keyframed, and reload on refresh. Transform props, material colors/scalars/vectors, and shader uniform numbers all fall in this category.

Transient props are excluded from exported project state JSON. They still appear in Studio for the current session but reset on refresh. autoAddObject registers material texture slots and shader uniform textures as transient image props (persist: false).

Texture props

Material texture slots (map, normalMap, etc.) and shader uniform textures are exposed as transient Theatre image props (see Static and transient props). Assignments apply for the current session only and are cleared on refresh. When you swap a texture, wrap/repeat/filter settings from the existing texture are preserved.

Shader uniform textures are detected by name (uDiffuseMap, tDiffuse, etc.) or by gui: { type: 'texture' } on the uniform.

When used together with buildExtension, selection is synced bidirectionally in orbit mode:

  • Click a registered mesh in the viewport to select it in the Theatre outline
  • Select an object in the outline to show a BoxHelper around the matching mesh

Shader uniform gui options

For ShaderMaterial / RawShaderMaterial, autoAddObject reads optional gui metadata on each uniform and maps it to Theatre number prop options:

| Uniform gui | Theatre types.number() option | | --- | --- | | min / max | range: [min, max] | | step | nudgeMultiplier | | type: 'texture' | Registers the uniform as a Theatre image prop (useful when the uniform value is null) |

import {ShaderMaterial, Color} from 'three'
import {autoAddObject} from '@unseenco/theatre-threejs'

const material = new ShaderMaterial({
  uniforms: {
    uColor: {value: new Color(1, 0.4, 0.2)},
    uOpacity: {
      value: 0.85,
      gui: {min: 0, max: 1, step: 0.01},
    },
    uDiffuseMap: {value: null},
    uTime: {value: 0}, // often excluded via configureTheatreThreejs when driven by your render loop
  },
  // vertexShader / fragmentShader ...
})

autoAddObject(new Mesh(geometry, material), sheet)

For Vector2 / Vector3 uniforms, set per-component gui options:

uOffset: {
  value: new Vector2(0, 0),
  gui: {
    x: {min: -1, max: 1, step: 0.01},
    y: {min: -1, max: 1, step: 0.01},
  },
}

If gui is omitted, number uniforms default to nudgeMultiplier: 0.01 with no range.

autoAddMaterial

Register a Three.js Material (or material array) on a Theatre sheet with auto-parsed material properties only — no transforms or Object3D selection sync. Use this when a material is shared across meshes, or when you only want to animate material props.

import {autoAddMaterial} from '@unseenco/theatre-threejs'

autoAddMaterial(mesh.material, sheet, {
  objectKey: 'Shared Material',
  exclude: {uniforms: ['uTime']},
  include: {material: ['color', 'metalness', 'roughness']},
})

Material / uniform exclude and include lists merge with configureTheatreThreejs({ autoAddObject }) defaults the same way as autoAddObject. Texture slots are registered as transient image props (see Static and transient props).

autoAddCamera

Register a Three.js Camera on a Theatre sheet with transform props and camera-specific props. Scale is excluded by default (cameras are not meaningfully scaled in Three.js).

import {autoAddCamera} from '@unseenco/theatre-threejs'

autoAddCamera(camera, sheet, {
  objectKey: 'Main Camera',
  scene, // add camera to scene if it has no parent; required for transform controls
  sensorHeight: 24, // mm, for focal length ↔ FOV conversion (default: 24)
  exclude: {
    transform: ['scale'],
    camera: ['zoom'], // focalLength, near, far, zoom
  },
})

For PerspectiveCamera instances, camera props include focal length (converted from FOV), near, far, and zoom. All camera props are static. An invisible selection hitbox is attached so the camera can be picked in orbit mode when used with buildExtension.

Orbit-mode devtools

When the orbit camera is active, the toolbar exposes three optional helpers. Each toggle persists per scene (along with orbit mode and camera pose).

Camera helper

Shows a CameraHelper frustum for the active scene camera. Useful for comparing the scene camera to the orbit camera while framing a shot.

Line helpers

Reveals scene geometry that would otherwise be invisible:

  • Line, LineSegments, and LineLoop objects in the scene graph
  • CatmullRomCurve3 instances stored on object.userData (for example userData.path)

The extension clones matching geometry into cyan overlay helpers; the original lines stay as-is. Helpers are rebuilt when you switch scenes or toggle the tool on.

Transform controls

When enabled and a registered object with transform props is selected in the Theatre outline, Three.js TransformControls appear in the viewport. Dragging the gizmo writes position, rotation, and scale back to the Theatre sheet as an undoable scrub. Orbit controls are disabled while dragging.

The toolbar adds translate / rotate / scale and world / local space switches when an object is attached. The selected object must be in the active scene graph — pass scene to autoAddCamera if your camera is not already parented to a scene.

Persistence

Scene names are taken from the optional name property, then from scene.name on the Three.js Scene instance, then default to "Scene" (with numeric suffixes when needed).

Devtools state (orbit mode, camera position, orbit target, and the camera / line / transform-controls helper toggles) is persisted per scene across page refreshes via Studio sheet objects (Devtools: <scene name>), using non-undoable transactions so it does not pollute the undo history.