← TeiaViewer examples
Plugins

A plugin

A plugin with its settings class, wired to a signal and driving a command, registered with its config.

CreatePlugin.ts
import {
  CameraFocusSelectedObjectsCommand, SetSettingCommand, Viewer, ViewerPlugin, type ViewerPluginKey,
} from '@stereograph/teiaviewer';
import { BooleanController, NumberController, Settings } from '@stereograph/teiaviewer-engine';

/**
 * The settings of the plugin: engine settings classes, saved in the local storage, shown by the
 * developer tools, validated (a number clamped to its range).
 */
export class AutoFocusPluginSettings extends Settings {
  readonly title = 'Auto focus';
  readonly icon = 'camera';

  readonly enabled = new BooleanController(true, {
    description: 'Frames the selection when it changes.',
  });

  readonly distance = new NumberController(1.5, {
    description: 'Distance of the camera to the selection, in radii of its bounding sphere.',
    min: 1,
    max: 5,
    step: 0.1,
  });
}

// Registers the plugin's key: `viewer.getPlugin('AutoFocus')` is typed.
declare module '@stereograph/teiaviewer' {
  interface ViewerPluginRegistry {
    AutoFocus: AutoFocusPlugin;
  }
}

// The plugin's name: shown, and the key of its saved settings.
const PluginBaseClass = ViewerPlugin.Create('AutoFocus', AutoFocusPluginSettings);

/** Frames the selection each time it changes. */
export class AutoFocusPlugin extends PluginBaseClass {
  /** None: it only uses the viewer. */
  override dependencies(): ReadonlyArray<ViewerPluginKey> {
    return [];
  }

  override onRegister(): void {
    this.viewer.signals.onObjectSelectionChanged.connect(this._focusSelection);
  }

  // Undoes exactly what `onRegister` did.
  override onUnregister(): void {
    this.viewer.signals.onObjectSelectionChanged.disconnect(this._focusSelection);
  }

  private readonly _focusSelection = () => {
    if (!this.settings.enabled.value || this.viewer.scene.objectSelection.length === 0) {
      return;
    }
    // A camera move, not kept in the undo history.
    void new CameraFocusSelectedObjectsCommand(this.viewer, {
      radiusMultiplier: this.settings.distance.value,
    }).execute({
      addToUndoHistory: false,
    });
  };
}

const viewer = new Viewer();
// The config overrides the defaults (and the saved values).
viewer.registerPlugin('AutoFocus', new AutoFocusPlugin(viewer, {
  distance: 2,
}));

// A setting changed by the user, undoable.
const { enabled } = viewer.getPlugin('AutoFocus').settings;
void new SetSettingCommand(viewer, enabled, false).execute();