Appearance
Plugins
Plugins extend the viewer with self-contained features. They are registered with the PluginManager, receive a PluginContext on load, and clean up on unload.
Authoring a plugin
ts
import type { IPlugin, PluginContext, PluginMetadata, PluginStatus } from "@optellix/xviewr-sdk";
class MyPlugin implements IPlugin {
readonly metadata: PluginMetadata = {
name: "my-plugin",
version: "1.0.0",
author: "Me",
description: "Example",
serviceDependencies: ["camera", "selection"],
};
private ctx!: PluginContext;
async load(context: PluginContext): Promise<void> {
this.ctx = context;
}
async init(context: PluginContext): Promise<void> {
// Wire up listeners, scene objects, services.
context.eventBus.on("selection:object-selected", ({ object }) => {
// ...
});
}
async destroy(): Promise<void> {
// Remove listeners, dispose GPU resources, detach DOM.
}
}
await viewer.loadPlugin(new MyPlugin());load runs first, then init. destroy runs on unload or viewer dispose. activate/deactivate/unload are optional hooks used by plugins that toggle interaction modes.
IPlugin
| Member | Type | Required | Description |
|---|---|---|---|
metadata | PluginMetadata | yes | Identity and dependency declaration. |
load(context) | Promise<void> | yes | First call. Receive the context. |
init(context) | Promise<void> | yes | Initialize state, listeners, scene contributions. |
destroy() | Promise<void> | yes | Tear down everything created in load/init. |
getStatus() | PluginStatus | no | Report current lifecycle status. |
activate() | Promise<void> | no | Enter active interaction mode. |
deactivate() | Promise<void> | no | Exit active mode. Free transient resources. |
unload() | Promise<void> | no | Optional pre-destroy hook. |
getCommands() | CommandDefinition[] | no | Declare commands the plugin contributes to the command runner. Registered on activate, removed on deactivate. |
PluginMetadata
| Field | Type | Description |
|---|---|---|
name | string | Unique plugin identifier. |
version | string | Semver string. |
author | string | Author name. |
description | string | Short description. |
serviceDependencies | string[] | Services required for the plugin to load. |
pluginDependencies | string[] | Plugins required to be loaded first. |
optionalServiceDependencies | string[] | Services used if present. |
optionalPluginDependencies | string[] | Plugins used if present. |
homepage | string | Optional URL. |
PluginContext
Passed to load and init.
| Field | Type | Description |
|---|---|---|
viewer | IViewer | The viewer. |
eventBus | IEventBus | Shared event bus. |
serviceRegistry | IServiceRegistry | Lookup services. |
configManager | IConfigManager | Read and watch config. |
api | Record<string, unknown> | Optional per-plugin API namespace. |
PluginStatus
ts
enum PluginStatus {
Unregistered = "unregistered",
Registered = "registered",
Loading = "loading",
Loaded = "loaded",
Initialized = "initialized",
Activating = "activating",
Active = "active",
Deactivating = "deactivating",
Deactivated = "deactivated",
Unloading = "unloading",
Unloaded = "unloaded",
Destroyed = "destroyed",
Error = "error",
}IPluginManager
Accessible as viewer.pluginManager.
| Method | Returns | Description |
|---|---|---|
register(plugin) | void | Register a plugin instance. |
unregister(name) | boolean | Remove a registered plugin. |
load(name, options?) | Promise<void> | Load and initialize. skipIfUnlicensed swallows license failures. |
unload(name) | Promise<void> | Destroy and remove. |
getPlugin(name) | IPlugin | null | Lookup by name. |
getStatus(name) | PluginStatus | Current status. |
listPlugins() | PluginMetadata[] | Metadata for every registered plugin. |
unloadAll() | Promise<void> | Unload everything. |
loadPluginsFromConfig(configs) | Promise<void> | Load plugins from XViewerConfig.plugins. |
Plugin lifecycle events on the event bus: plugin:registered, plugin:loading, plugin:loaded, plugin:activated, plugin:deactivated, plugin:unloaded, plugin:error.
Resource discipline
Every THREE.Geometry, Material, and Texture created by a plugin must be .dispose()d on destroy. Three.js does not garbage-collect GPU resources. Remove every event listener registered in init. Detach any DOM elements added to viewer.container.