Skip to content

ModelTreePlugin

Hierarchical model tree view built from StorageService. Provides filter, search, selection sync with the scene, per-node visibility toggle, and an optional built-in UI panel.

Usage

ts
import { ViewerCore, ModelTreePlugin } from "@optellix/xviewr-sdk";

const viewer = new ViewerCore(container, config);
await viewer.ready();

const tree = new ModelTreePlugin({
  expandDepth: 2,
  sortBy: "name",
  ui: { enabled: true, container: "#tree-panel", theme: "dark" },
});
await viewer.loadPlugin(tree);

Service dependencies: scene-hierarchy, selection, mesh. The plugin rebuilds tree data on storage events and keeps tree-side selection in sync with scene-side selection.

Constructor

ts
new ModelTreePlugin(config?: Partial<TreeConfig>)

Public API

MethodDescription
getTreeData()Returns a shallow copy of the full TreeNodeData[].
getFilteredTreeData(filter?)Returns the tree filtered by filter (or the current filter).
setFilter(filter)Replace the current TreeFilter.
clearFilter()Clear the active filter.
getNodeById(nodeId)Find a tree node by id.
selectNode(nodeId)Select a node in tree and scene. Returns false if the node has no mesh loaded.
getSelectedNode()Returns the currently selected tree node or null.
expandNode(nodeId, expanded?)Expand or collapse a node.
isNodeExpanded(nodeId)Boolean.
toggleNodeVisibility(nodeId)Flip the node and its descendants visible/hidden via MeshService.
updateConfig(config)Partial update of TreeConfig and rebuild.
getConfig()Returns the active TreeConfig.
rebuildTreeData(reason?)Rebuild tree from storage. Emits tree:rebuild-* events.
getStats(){ totalNodes, expandedNodes, selectedNode, nodesByType }.
enableUI(container?, config?)Mount the built-in UI panel.
disableUI()Tear down the UI panel.
getUIInstance()Returns the ModelTreeUI instance or null.
updateUITheme("dark" | "light")Switch UI theme.
setCustomStyles({ customCSS?, styleOverrides? })Inject custom CSS and CSS variable overrides.

Types

TreeNodeData

ts
interface TreeNodeData {
  id: string;
  name: string;
  type: NodeType;
  path: string;
  isVisible: boolean;
  isLocked: boolean;
  depth: number;
  hasChildren: boolean;
  children: TreeNodeData[];
  metadata: {
    partNumber?: string;
    material?: string;
    tags: string[];
    customData: Record<string, any>;
    datasetType?: string;
  };
  stats: {
    childCount: number;
    totalDescendants: number;
    meshCount: number;
  };
}

TreeFilter

ts
interface TreeFilter {
  nodeTypes?: NodeType[];
  tags?: string[];
  namePattern?: RegExp;
  visibleOnly?: boolean;
  maxDepth?: number;
  customFilter?: (node: HierarchyNode) => boolean;
}

TreeConfig

ts
interface TreeConfig {
  expandDepth: number;            // initial expansion depth
  showStats: boolean;
  showMetadata: boolean;
  autoExpandSingleChild: boolean;
  sortBy: "name" | "type" | "depth" | "custom";
  sortOrder: "asc" | "desc";
  customSortFn?: (a: TreeNodeData, b: TreeNodeData) => number;
  ui?: ModelTreeUIConfig & {
    enabled: boolean;
    customCSS?: string;
    customTheme?: Record<string, string>;
    styleOverrides?: {
      nodeHeight?: string;
      fontSize?: string;
      iconSize?: string;
      indentSize?: string;
      borderRadius?: string;
      colors?: {
        background?: string;
        foreground?: string;
        accent?: string;
        border?: string;
        hover?: string;
        selected?: string;
      };
    };
  };
}

Events

EventPayload
tree:data-updated{ rootNodes, totalNodes }
tree:node-selected{ nodeId, nodeData }
tree:node-expanded{ nodeId, expanded }
tree:node-visibility-changed{ nodeId, visible }
tree:filter-changed{ filter, resultCount }
tree:rebuild-started{ reason }
tree:rebuild-completed{ duration, nodeCount }

Example

ts
const tree = viewer.pluginManager.getPlugin("modelTree") as ModelTreePlugin;

tree.setFilter({ namePattern: /bolt/i, visibleOnly: true });

const root = tree.getTreeData()[0];
if (root) tree.selectNode(root.id);

viewer.eventBus.on("tree:node-visibility-changed", ({ nodeId, visible }) => {
  console.log(nodeId, visible);
});

XViewr SDK and xConvert CLI documentation.