SDK API 指南
当前 Turboism 插件 SDK 的入口点、服务、对象模型、生命周期与能力边界。
Turboism SDK 是插件唯一的公开依赖项。新 API 默认处于 Preview 状态。其可用性取决于四项彼此独立的事实:
- API 存在于 SDK 中;
- 插件声明了所需权限;
- Runtime 具有匹配的能力 Provider;
- 支持当前启用的 Cubism 版本和对象世代。
如需查看生成的类型和方法索引,请打开 SDK HTML API 文档。
插件生命周期
每个入口点都实现 TurboismPlugin 或其子接口,例如 CubismPlugin。
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 {}
}init:保留上下文、注册配置架构,并创建插件私有状态。enable:提供操作、事件、UI、任务和其他活动行为。disable:在 Runtime 关闭插件作用域前停止活动行为。shutdown:释放不归该作用域所有的插件私有资源。
一个 JAR 可以包含多个有序入口点。构造、初始化和启用遵循清单顺序;禁用和关闭则按相反顺序执行。整个 JAR 的启动是原子的。
PluginContext
| 条目 | 用途 |
|---|---|
descriptor() | 当前 JAR 级别的 PluginDescriptor |
logger() | 插件作用域内的日志记录 |
paths() | 配置、数据、缓存、状态和日志命名空间 |
localization() | 区域设置、文本查找和格式化 |
tasks() | 有界的一次性和固定延迟任务 |
hostReads() | 有界的异步主机读取 |
storage() | 插件拥有的 DATA、STATE 和 CACHE 存储 |
userFiles() | 用户授予的文件句柄 |
cubism() | 快照、统一对象访问和事务兼容入口点 |
parameterQuery() | 范围受限的参数查询 |
selectionQuery() | 选区读取和变更订阅 |
modelHierarchyQuery() | 模型树查询 |
cubismRead() | 聚合的读取能力族 |
eventBus() | 类型化事件的发布和订阅 |
actions() 和 menus() | 操作注册和菜单贡献 |
mainToolbar()、paletteToolbar()、contextMenu() | 类型化 UI 贡献注册表 |
uiHost() 和 uiScheduler() | 工具包无关的 UI 能力和 UI 线程调度 |
config() | 类型化插件配置 |
diagnostics() | 当前结构化诊断信息 |
disposableScope() | 逆序生命周期清理 |
部分默认服务会抛出 UnsupportedOperationException;另一些则返回显式的不可用实现。插件必须处理不可用的能力族,而不是绕过它们。
注册与清理
大多数注册表返回 Registration,这是一个 AutoCloseable 句柄。
Registration registration = context.actions().register("example.refresh", action);
context.disposableScope().register(registration);该作用域按相反顺序关闭注册项。应将操作、菜单、UI 贡献、订阅、任务句柄和其他可关闭资源放入作用域中,以便 Runtime 能够安全地释放插件 ClassLoader。
Cubism 生命周期钩子通过入口点接口发现,而非通过回调注册总线。
操作、菜单与事件
ActionRegistry.Action 提供 ID、标签和处理程序。ActionContext 可以携带类型化 UI 操作事件,或绑定到世代的上下文菜单选区。
MenuRegistry.MenuContribution 将斜杠分隔的菜单路径与已注册的操作 ID 及顺序绑定。
通用事件总线是类型化的:
Registration subscription = context.eventBus().subscribe(
MyEvent.class,
event -> context.logger().info(event.value())
);
context.disposableScope().register(subscription);
context.eventBus().publish(new MyEvent("changed"));
record MyEvent(String value) implements EventBus.TurboismEvent {}事件应为不可变的、由插件或 SDK 拥有的值。请勿在事件中放入原始主机对象、Swing 小部件、原生句柄或主机 ClassLoader。
快照与查询 API
CubismFacade 仍提供不可变的运行时快照:
CubismRuntimeSnapshot runtime = context.cubism().runtime();
Optional<ProjectSnapshot> project = context.cubism().activeProject();
Optional<DocumentSnapshot> document = context.cubism().activeDocument();
Optional<ModelSnapshot> model = context.cubism().activeModel();
boolean hostPresent = context.cubism().isHostPresent();范围受限的查询服务包括:
ParameterQueryService:用于参数查找和枚举;SelectionQueryService:用于当前选区和选区变更订阅;ModelHierarchyQueryService:用于模型树遍历;CubismReadCapabilityService:用于项目、文档、模型、选区、参数、模型对象、网格、变形器、PSD、剪裁蒙版、纹理图集、渲染状态、工作区和主题状态读取族。
快照和查询值是不可变 DTO,而非主机对象引用。
统一的 Cubism 对象图
新的插件代码应优先使用统一对象 API:
CubismModel model = context.cubism().model().active();
Parameter parameter = model.parameters().find(new ParameterId("ParamAngleX"));
float value = parameter.getValue();
parameter.setValue(value + 1.0f);CubismModel 公开参数、参数组、部件、可绘制对象、变形器、Warp 和 Rotation Deformers、Glue、画布、模型更新、默认关键帧锁定和参数绑定操作。
强类型 ID 包括 ProjectId、DocumentId、ModelId、ModelObjectId、ParameterId、ParameterGroupId、PartId、ArtMeshId、DeformerId、GlueId 和 ParameterBindingPointId。
模型及其子对象绑定到世代。在文档切换、重新加载、删除、插件禁用、Provider 替换或其他使其失效的生命周期事件之后,引用会以安全失败方式失效。
操作生命周期钩子
CubismPlugin 组合了 Parameter、Part、Drawable、Deformer 和 Model 钩子族。
public final class ClampPlugin implements CubismPlugin {
@Override
public float beforeSetParameterValue(Parameter parameter, float value) {
return Math.min(value, parameter.getMaximumValue());
}
@Override
public void onParameterValueChanged(
Parameter parameter,
float oldValue,
float newValue
) {
// 仅在权威状态变更后运行。
}
@Override
public void afterSetParameterValue(Parameter parameter, float value) {
// 观察正常完成;请勿执行第二次变更。
}
}before -> 规范操作 -> 权威状态探测 -> on(仅发生变更时)-> after(正常完成时)before同步、有序,并且可以改写参数。on仅在发生可观察到的变更时发出。after观察正常完成。- observe 和 intercept 权限彼此独立。
- 插件无法直接注册字节码转换器。
配置
类型化配置支持架构、编解码器、顺序迁移、异步读取,以及基于修订版本的 compare-and-set 写入。
ConfigKey<Boolean> enabled = new ConfigKey<>(
"example.settings",
"enabled",
true,
ConfigCodecs.booleanValue()
);
ConfigSchema schema = new ConfigSchema(
"example.settings",
"settings.json",
1,
List.of(enabled)
);
context.config().registerSchema(schema, List.of());
context.config().read(enabled);
context.config().write(enabled, true, expectedRevision);Runtime 将插件设置存储在 config/<pluginId>/ 下。插件不得自行构建 turboism.home 下的路径。
插件存储和用户文件
PluginStorage 在三个根目录下提供原子读取、写入、复制、移动、列出和删除操作:
- DATA:用于持久化业务数据;
- STATE:用于可重建的运行时状态;
- CACHE:用于可重建的缓存数据。
StoragePath path = new StoragePath(StorageRoot.STATE, "manual-order.txt");
context.storage().writeUtf8Atomic(path, "a\nb\n");
context.storage().readUtf8(path, 256 * 1024);路径必须是规范化的相对路径。用户选择的外部文件使用 UserFileAccessService 和有作用域的 UserFileHandle 对象;用户文件并非不受限制的文件系统能力。
任务与异步读取
应使用 PluginTaskScheduler,而不是持有不受管理的线程、执行器或计时器。
TaskSubmission submission = context.tasks().submit(
new PluginTaskRequest(
new TaskId("refresh"),
PluginTaskKind.COMPUTE,
PluginTaskPriority.NORMAL,
token -> token.checkCanceled()
)
);任务公开类型化的提交、取消、完成、超时、拒绝、背压和断路器打开结果。
AsyncHostReadService 的意图集经过刻意收窄。仅使用当前 SDK 中存在的意图;不要假定未来会提供 parameter、mesh 或 PSD 意图。
用户界面 API
UI API 使用 SDK DTO,而不是 Swing/AWT 或主机小部件。当前族包括:
- 操作和菜单;
- 主工具栏和调色板工具栏;
- 类型化上下文菜单和上下文选区;
- 覆盖层、对话框、状态通知和文件选择;
- 工具包无关的
PanelView嵌入式面板; - UI 线程调度;
- 场景表、外观、控件外观和部分选定的 Editor 贡献。
每个 UI 族都有独立的能力和 Provider 依据。一个可用的族不会启用所有其他族。
权限、能力和操作
- 权限:授权跨越风险边界。
- 能力:表示当前 Provider 和主机版本支持某个功能族。
- 操作:一次具体调用及其诊断身份。
权限不会绕过操作验证,也不会创建缺失的 Provider。
版本与就绪状态说明
- 参数创作写入具有已验证的 Cubism 5.3.02 路径,但调用方仍必须处理不可用性和过时目标。
- 部件显示名称写入在 5.2.03 和 5.3.02 上具有真实主机证据。
- 不得声称部件不透明度创作写入支持 5.2.03。
- Fake 和静态测试仅证明其所命名的层。
- 快照/查询/事务兼容接口当前与统一对象图并存。