Plugins


Plugins are custom code you can write for the Navigator. They are written for a particular context, for example written for the cursor-bar where you can write your own "click" handling.

Plugins are written in Javascript with an optional HTML file as well.

You can add, edit, and enable plugins through the Navigator project view dashboard.

File layout

A Plugin is a zipped folder that includes an index.js and index.html file.

The HTML file (if present) will automatically be added to the context's HTML container. It will also be automatically removed when disposed.


Here is an example of a Plugin's index.js file.

// Ensure you have a Run function that takes a params object.
function Run(params) {
    console.log("Plugin was run", params);

    // HTML container the plugin is sitting in.
    // This may not exist if it's run as a background script!
    const container = params.container;

    // The element of the plugin itself.
    // This will be sitting inside the container element.
    // This will not exist if either the container or HTML template is not present.
    const element = params.element;

    // The plugin's own ID and record. The record carries Settings,
    // which is where per-account configuration belongs.
    const pluginId = params.pluginId;
    const plugin = params.plugin;

    // Ensure to return a dispose function.
    return () => {
        console.log("Plugin was disposed");
    };
}

Here is an example of a Plugin's index.html file. Please note the usage of an HTML ID for the styles and root element. It is highly recommended to work with a very unique ID to avoid conflicts with other Plugins and the Navigator itself.

<style>
    #MyPlugin {
        background-color: red;
        padding: 8px;
        border-radius: 8px;
        position: absolute;
        z-index: 1;
        left: 0;
        top: 0;
    }
</style>

<div id="MyPlugin">
    <span>
        My plugin!
    </span>
</div>

Plugin Locations

A Plugin's location decides where it can be loaded, what container it gets, and which params it is handed.

LocationDescription
Cursor bar
NAVIGATOR_CURSOR_BAR
The cursor bar is the toolbar found in the top-left corner of the Navigator. It is responsible for actions the user performs when clicking on the scene or Entities in the scene.

The Plugin loads when the user enables the tool and is disposed when they disable it, so a cursor Plugin needs no state of its own to know whether it is active.
Cursor bar
Info View
NAVIGATOR_INFO_VIEW
The Info View panel is the dialog that appears when an Entity is selected. This location replaces that panel's contents, so the Plugin is responsible for presenting the Entity itself.Info View
Selected Entity panel tab
NAVIGATOR_INFO_VIEW_ENTITY
Adds a tab alongside Navigator's own tabs in the selected Entity panel, rather than replacing it. This is usually what you want: the user keeps the built-in views and gains yours.
Selected Multi-Entity panel tab
NAVIGATOR_INFO_VIEW_MULTI_ENTITY
The same, for when several Entities are selected at once. Read the selection from the visual register rather than expecting a single Entity.
Sidebar
NAVIGATOR_SIDE_BAR
The side bar is the toolbar found in the left side of Navigator which holds Menu Items, Bookmarks, and Scene Tree.

Set the Plugin setting "panelWidth" to control the panel's width. See Side panel width below.
Background
NAVIGATOR_BACKGROUND
Plugins that are set to load in the background will load automatically when the page loads without the user needing to click any buttons.

A background Plugin is reloaded when the Project View or the active Bookmark changes, and is the only location handed the view and bookmark params.
AI Tool
AI_TOOL
Not a piece of UI. The Plugin is offered to the AI agent as a callable tool and exports Invoke rather than Run. See the AI Tools page.
Operator
OPERATOR
Loads inside the Operator management portal rather than Navigator. The params described below are Navigator's, so do not assume a viewer here.

Setting a location is not enough on its own. A Plugin must also be enabled on the Project View that is being viewed, which is what Navigator checks before loading anything. A Plugin that appears to do nothing is almost always a Plugin that was never enabled on the view.

Plugin Params

Below are what parameters are passed into the Plugin's Run function in Navigator.

function Run(params) {
    console.log("Plugin was run", params);
    const pluginParams = params.pluginParams;

    // Plugin record itself.
    // Useful for accessing the settings object within it.
    const plugin = params.plugin;

    // Reference to the Cesium viewer.
    const viewer = pluginParams.viewer;

    // Reference to the Menu Item manager and visual register.
    // This lets you manage Menu Items and know what is currently rendered in the scene.
    const manager = pluginParams.menuItemManager;
    const register = pluginParams.visualRegister;

    // Reference to Cesium, bruce-models, and bruce-cesium NPM libraries.
    const Cesium = pluginParams.Cesium;
    const BModels = pluginParams.BModels;
    const BEngine = pluginParams.BEngine;

    // The current context, without needing a request for any of it.
    // 'getters' is already pointed at this account and session.
    const getters = pluginParams.getters;
    const session = pluginParams.session;
    const account = pluginParams.account;
    const version = pluginParams.version;

    // Reference to function to call so you can force the plugin to dispose and the tool to be disabled.
    const close = pluginParams.close;
    // close();

    // Reference to function to call to open/close a Navigator side-panel.
    // Options are: "dashboard", "menu-items", "bookmarks", "scene-tree", "user", "scene-config", "entity-editor"
    // "comments", "markup", and "walkthrough".
    // If you have an active side-bar plugin, you can open it through "PLUGIN_<THE_PLUGIN_ID>" eg: "PLUGIN_1234abcd".
    const setPanelActive = pluginParams.setPanelActive;

    // Open a panel:
    // setPanelActive("bookmarks", true);

    // Close a panel:
    // setPanelActive("bookmarks", false);

    // Reference to function to call to select or deselect Entities.
    const select = pluginParams.select;
    /*
     * select({
     *     entityIds: ["a", "b"]
     * })
     */

    // Reference to function to call to refresh Entities in the scene/panels.
    const refreshData = pluginParams.refreshData;
    /*
    * refreshData({
    *     entityIds: ["a", "b"]
    * });
    */

    // Reference to function to call to toggle "liveness" of Entities.
    // When an Entity is live, it periodically refreshes its data.
    const updateLiveData = pluginParams.updateLiveData;

    /*
    * Replace current live Entity IDs with given IDs.
    * updateLiveData({
    *     entityIds: ["a", "b"]
    * });
    */

    /*
    * Add given Entity IDs to the current live Entities.
    * updateLiveData({
    *     entityIds: ["a", "b"],
    *     action: true
    * });
    */

    /*
    * Remove given Entity IDs to the current live Entities.
    * updateLiveData({
    *     entityIds: ["a", "b"],
    *     action: false
    * });
    */

    return () => {
        console.log("Plugin was disposed");
    };
}

Params by location

Not every location is handed every param. The params above are present everywhere in Navigator; the ones below depend on where the Plugin runs, so check for a param rather than assuming it. Params marked unstable are the ones Navigator happens to expose today and may change.

ParamWhereWhat it is
setPanelWidthSide barChanges the panel width at runtime, taking the same value as the panelWidth setting. Affects the current session only.
setFocusedAttachmentInfo View locationsOpens Navigator's own attachment viewer on an attachment, with its siblings, so a Plugin does not need to build media browsing itself. Called as setFocusedAttachment(attachment, siblings).
view, viewIdBackgroundThe active Project View record and its ID. A background Plugin is reloaded when this changes.
bookmark, bookmarkId, enableBookmarkBackgroundThe active Bookmark, its ID, and a call to activate one. A background Plugin is also reloaded when the Bookmark changes.
getCursor
unstable
BackgroundReturns the cursor tool the user currently has active, so a background Plugin can react to it.

The Plugin record

Every Plugin is handed its own record as params.plugin. It is worth knowing what is on it, because several fields exist specifically so a Plugin does not have to be edited per account or per deployment.

FieldWhat it does
SettingsArbitrary JSON, passed to the Plugin when it loads. This is where an Entity Type ID, an endpoint, a threshold or a colour belongs, so one Plugin serves every account with no code change. Also carries the reserved panelWidth, and tool for AI Tools.
EnabledTurns a Plugin off without unpicking it from every Project View that references it.
GroupAn arbitrary grouping you can query against, so a whole related set can be retrieved and enabled at once. This is how an embedded Navigator can be told to enable a group of Plugins by URL param, and have that set change without the URL changing.
VersionBumped every time a new code bundle is uploaded, and used as the cache key for the Plugin's code. See Caching while you develop below.
Icon, IconSourceThe button icon, either a Font Awesome class (FONT_AWESOME) or a Client File ID (CLIENT_FILE) for your own image. For background Plugins the icon is only for identification in admin panels.
IsLoginRequiredRequires a logged-in user.
IsAccessRestrictedRestricts the Plugin to users holding the UIPlugin_<pluginId> permission. Only checked alongside IsLoginRequired.

Side panel width

A side bar Plugin's panel is 300px wide by default. The panelWidth setting takes either a fixed CSS width or a range, and a range is what makes the panel user-resizable.

{
    "panelWidth": "500px"
}

{
    "panelWidth": "300px-900px"
}

{
    "panelWidth": "300px-900px-480px"
}

A single value is a fixed width. Two values are a minimum and a maximum, which the user can drag between. Three values add the width to open at. A Plugin can also change this while it runs through the setPanelWidth param, which affects the current session only and does not rewrite the setting.

Caching while you develop

A Plugin's code file is cached against its Version, which is bumped on upload. That is right for users and awkward while iterating, because a browser that already holds a version will keep serving it.

Navigator has a user flag for exactly this. Turn on Disable plugin cache on your own user while developing, and every load refetches the code. Leave it off in normal use: it costs a request per Plugin per load.

Worked examples

The FAQ pages in this section answer the cases most Plugins start from: making API requests, letting the user pick a position in the scene, and rendering directly to the Cesium viewer. The AI Tools page covers the agent-callable location, which uses a different entry point entirely.