可视化 UI 可以独立使用,也可以和扩展程序组合成「可视化布局 + TypeScript 控制器」。 常见用法包括:
  • 打开界面前准备数据或冻结画面;
  • 界面打开后修改文字、样式和可见性;
  • 监听某个按钮点击;
  • 在程序中打开或关闭界面。

给元素设置引用名

程序通过元素的「引用名」查找它。在可视化界面检查器中为需要控制的元素填写唯一引用名,例如 titleclose-button 没有引用名的元素不会出现在程序查询结果中,但仍会正常渲染。引用名只要求在当前界面内唯一。

界面名称

ctx.visualUI 使用由扩展 id 和界面名称组成的完整名称:
@my.extension/main-panel
扩展自己的界面建议从 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。