Skip to content

客户端渲染

WheelWidget

AbstractWidget 子类,核心控件,负责扇区计算、交互和渲染。

布局

根据中心点、内外半径、每页槽位数计算每个扇区(WheelSection)的位置和检测角度。

交互

方法说明
checkMousePos()根据鼠标相对于中心的极坐标判断当前指向的扇区
mouseScrolled()扇区间循环切换选中
onClosing()播放关闭动画

死区(deadZone)内不选中任何扇区。

动画

  • 打开时弹性缩放动画
  • 关闭时反向动画

自定义渲染

  • 圆环背景:RingRenderState + 自定义 RingUniform 着色器
  • 选中圆点:SelectionRenderStateWheelSelectionEffect.DOT
  • 扇形高亮:AnnularSectorRenderStateWheelSelectionEffect.ANNULAR_SECTOR
  • 条目渲染器 + 文本绘制

WheelScreen

轮盘菜单的屏幕宿主,管理页面堆栈和模式触发。

核心字段

字段说明
WheelMenuModel model轮盘菜单模型
WheelOpenMode mode打开模式
Deque<List<WheelEntry>> menuStack菜单栈(支持子菜单压栈/回退)

交互行为

点按模式:

  • 鼠标左键触发当前选中条目
  • 若无选中则关闭屏幕
  • 有子菜单时进入子菜单

长按模式:

  • triggerFromHoldRelease() 由外部长按释放时调用
  • 触发当前选中的动作项(忽略子菜单)

翻页

鼠标滚轮在页面间切换。

渲染管道与 Uniform enhanced in 26.1

着色器管道 (LibRenders)

管道Uniform作用
RING_PIPELINERingUniform抗锯齿圆环
SELECTION_PIPELINESelectionUniform边缘柔和的圆点
ANNULAR_SECTOR_PIPELINEAnnularSectorUniform扇形高亮

所有管道基于通用 SNIPPET_COMMON,通过 RingRenderStateSelectionRenderStateAnnularSectorRenderState(均实现 LibQuadGuiElementRenderState)自动绑定 UBO。

动态 Uniform (LibDynamicUniforms)

管理并复用帧内 Uniform Buffer,避免每帧大量 GPU 内存分配:

java
LibDynamicUniforms uniforms = AnvilLibWheel.getLibDynamicUniforms();

// 写入 Uniform 数据
uniforms.writeRing(center, innerDiameter, outerDiameter, aa);
uniforms.writeSelection(framebufferSize, center, radius, aa);
uniforms.writeAnnularSector(...);

// 每帧结束时复位
uniforms.reset();

内部使用 DynamicUniformStorage 搭配三个数据类(RingUniformSelectionUniformAnnularSectorUniform),按 STD140 布局写入。

全局单例通过 AnvilLibWheel.getLibDynamicUniforms() 获取,在 ConfigureMainRenderTargetEvent 时初始化。

输入控制

WheelScreenController

封装点按与长按两种模式的输入逻辑,避免在 tick 事件中直接操作导致重复打开。

java
WheelScreenController controller = new WheelScreenController();

// 打开点按屏幕
controller.openTap(menuModel);

// 长按键按下
controller.onHoldKeyPressed(menuModel);

// 长按键释放(触发选中动作 + 关闭)
controller.onHoldKeyReleased();

测试与示例

dev.anvilcraft.lib.v2.test.wheel 包提供完整的可运行示例。

测试组件

说明
WheelTestKeys注册四个按键(点按/长按 + 圆点/扇形)
WheelTestClientHandlerClientTickEvent.Pre 处理点按,InputEvent.Key 处理长按
WheelDemoMenus构建 buildTapDemo() / buildHoldDemo() 演示菜单

演示菜单特性

  • 动作项(Action entries)
  • 子菜单(Submenus)
  • 自定义渲染器(渲染苹果物品图标)

扩展指南

自定义渲染器

java
// 实现 WheelEntryRenderer
WheelEntryRenderer myRenderer = (graphics, entry, x, y, radius) -> {
    // 在扇区内绘制任意 GUI 元素
};

// 传入 action 或 submenu 的重载方法
builder.action("id", Component.literal("Custom"), ctx -> {}, myRenderer);

动态样式

通过 WheelMenuBuilderWheelWidget 构造参数调整:

  • 动画时长
  • 选中效果颜色
  • 字体缩放
  • 死区大小

与服务端交互

WheelEntryAction 可通过 WheelActionContext 获取页面与槽位信息,结合 PacketDistributor 发送网络包:

java
builder.action("action", Component.literal("Do Something"), ctx -> {
    PacketDistributor.sendToServer(new MyActionPacket(ctx.slotIndex(), ctx.openMode()));
});

Released under the CC-BY-NC-SA 4.0 License.