可视化 UI 可以独立使用,也可以和扩展程序组合成「可视化布局 + TypeScript 控制器」。
常见用法包括:
- 打开界面前准备数据或冻结画面;
- 界面打开后修改文字、样式和可见性;
- 监听某个按钮点击;
- 在程序中打开或关闭界面。
给元素设置引用名
程序通过元素的「引用名」查找它。在可视化界面检查器中为需要控制的元素填写唯一引用名,例如 title、close-button。
没有引用名的元素不会出现在程序查询结果中,但仍会正常渲染。引用名只要求在当前界面内唯一。
界面名称
ctx.visualUI 使用由扩展 id 和界面名称组成的完整名称:
扩展自己的界面建议从 extension.json 读取 id,避免在代码中重复写:
import manifest from "../extension.json";
const uiName = `@${manifest.id}/main-panel`;
监听界面打开
onOpen 会在界面挂载完成后触发,无论它是由剧本、系统插槽、按钮动作还是程序打开:
import manifest from "../extension.json";
import { Extension } from "@avg-studio/sdk";
export class MyExtension extends Extension {
static onRegister(ctx) {
const uiName = `@${manifest.id}/main-panel`;
ctx.visualUI.onOpen(uiName, (view) => {
view.get("title")?.setProps({ text: "欢迎回来" });
const closeButton = view.get("close-button");
const offClick = closeButton?.on("click", () => view.close());
view.onClose(() => offClick?.());
});
}
}
同一个元素在 JSON 中配置的点击动作,和程序注册的 click 监听可以同时执行。
把 onOpen 注册放在扩展的静态 onRegister 中,控制器会在每次打开界面时获得本次对应的 view。
打开前准备
onBeforeOpen 在界面创建 DOM 和挂载之前执行,并会等待异步任务完成:
ctx.visualUI.onBeforeOpen(uiName, async () => {
await preparePreviewImage();
});
适合需要先生成截图、整理数据或冻结背景的界面。不要在这里执行耗时且无反馈的网络请求,否则玩家会感觉按钮没有响应。
操作元素
view.get(refId) 返回一个元素句柄;引用名不存在时返回 null。
const score = view.get("score");
score?.setProps({ text: "1200" });
score?.setStyle({
color: "#ffd76a",
fontSize: 42,
});
score?.setHidden(false);
可用方法:
| 方法 | 作用 |
|---|
setProps(patch) | 合并更新元素内容或组件属性 |
setStyle(patch) | 合并更新元素样式 |
setHidden(hidden) | 显示或隐藏元素 |
on("click", listener) | 监听点击,返回取消监听函数 |
这些修改只作用于当前运行中的界面实例,不会写回 JSON 设计稿。
打开、获取和关闭界面
// 打开界面,并等待拿到实例
const view = await ctx.visualUI.open(uiName, {
modal: true,
size: "(100%, 100%)",
position: "(0, 0)",
});
// 获取当前已经打开的实例
const existing = ctx.visualUI.attach(uiName);
// 主动关闭
view.close();
attach() 在界面没有打开时返回 null。
view.onClose(listener) 用于界面关闭后的清理,并返回取消监听函数。界面关闭后,旧句柄不再代表一个有效运行实例,不应缓存到下一次打开继续使用。
生命周期方法
| API | 触发时机 |
|---|
ctx.visualUI.onBeforeOpen(name, listener) | 创建并挂载界面之前;等待异步监听完成 |
ctx.visualUI.onOpen(name, listener) | 界面已经打开,可以获取元素 |
view.onClose(listener) | 当前界面实例关闭时 |
三者都会返回取消监听函数。扩展被卸载或不再需要监听时,应调用它们清理。
什么时候仍然使用 React UI
可视化 UI 更适合布局、表单、菜单和由引擎能力驱动的组件。以下情况仍可以使用 Extension 的 render():
- 大量动态节点或复杂实时计算;
- 依赖成熟 React 组件库;
- 小游戏、Canvas、WebGL 等自定义渲染;
- 完全由程序状态决定的交互。
两种方式可以共存。系统插槽和显示 UI选择器都能按各自规则使用可视化 UI 或程序 UI。