Plugin Interfaces

Current Preview SDK interface families available through PluginContext.

The current Turboism plugin boundary is Java-based and source-backed. Plugins implement TurboismPlugin or a subinterface and receive a PluginContext from Runtime.

For signatures and detailed semantics, use the SDK API Guide and generated HTML reference.

Lifecycle

public interface TurboismPlugin {
    default void init(PluginContext context) throws Exception {}
    default void enable() throws Exception {}
    default void disable() throws Exception {}
    default void shutdown() throws Exception {}
}

Use init for context and configuration setup, enable for active registrations, disable for stopping behavior, and shutdown for plugin-private cleanup.

Context service families

FamilyCurrent entrypointTypical use
Metadatadescriptor()Inspect the current JAR-level descriptor
Logginglogger()Emit plugin-scoped diagnostics
Pathspaths()Access plugin-owned config/data/cache/state/log namespaces
Localizationlocalization()Read localized text declared in the manifest
Taskstasks()Submit bounded cancellable work
Host readshostReads()Request bounded asynchronous host snapshots
Storagestorage()Read and atomically write plugin-owned data
User filesuserFiles()Use user-granted external-file handles
Cubismcubism()Read snapshots and use the unified object graph
QueriesparameterQuery(), selectionQuery(), modelHierarchyQuery()Narrow typed queries
EventseventBus()Publish and subscribe to immutable typed events
Actionsactions()Register reusable plugin actions
Menus and UImenus(), toolbar/context-menu registries, uiHost()Contribute toolkit-neutral UI descriptors
Configurationconfig()Register typed schemas, read values, and compare-and-set writes
Diagnosticsdiagnostics()Inspect structured Runtime diagnostics
CleanupdisposableScope()Register closeable lifecycle resources

A service may be unavailable on a particular Runtime/host combination. Handle explicit unavailable results or exceptions rather than bypassing Runtime.

Actions and menus

Register behavior once as an action and bind UI contributions to its ID.

var action = context.actions().register("hello.show", new ActionRegistry.Action() {
    @Override public String id() { return "hello.show"; }
    @Override public String label() { return "Hello"; }
    @Override public Consumer<ActionRegistry.ActionContext> handler() {
        return ignored -> context.logger().info("Hello from Turboism");
    }
});
context.disposableScope().register(action);

Menu, toolbar, panel, and context-menu contributions use SDK descriptors. They do not expose host widgets.

Events

record HelloEvent(String message) implements EventBus.TurboismEvent {}

var subscription = context.eventBus().subscribe(
    HelloEvent.class,
    event -> context.logger().info(event.message())
);
context.disposableScope().register(subscription);
context.eventBus().publish(new HelloEvent("enabled"));

Subscribe and publish permissions are separate. Events must not contain raw host state.

Cubism object API

CubismModel model = context.cubism().model().active();
Parameter parameter = model.parameters().find(new ParameterId("ParamAngleX"));
float current = parameter.getValue();

Writes require a matching permission and Provider. An interface method does not imply support on every Cubism version.

Hooks

Implement CubismPlugin or a specific hook interface for operation lifecycle observation or interception.

public final class HelloHooks implements CubismPlugin {
    @Override
    public void onParameterValueChanged(
        Parameter parameter,
        float oldValue,
        float newValue
    ) {
        // Bounded observation only.
    }
}

Hooks follow before -> operation -> changed-only on -> after. Plugins cannot register bytecode transformers.

Configuration, storage, and tasks

  • Use typed PluginConfigRegistry for settings.
  • Use PluginStorage for DATA, STATE, and CACHE.
  • Use UserFileAccessService for user-selected external files.
  • Use PluginTaskScheduler instead of unmanaged threads, executors, or timers.

Cleanup rule

Every returned registration or handle that can outlive the current method must either be closed explicitly or enrolled in context.disposableScope().