资讯动态

Bevy 0.20 迁移指南:cursor 光标模块从 bevy_feathers 迁入 bevy_picking

发布时间:2026/9/6 18:43:56 来源:尧图企业网站定制
Bevy 0.20 迁移指南cursor 光标模块从 bevy_feathers 迁入 bevy_picking【免费下载链接】bevyA refreshingly simple>项目地址: https://gitcode.com/GitHub_Trending/be/bevy在 Bevy 当前仓库版本0.20.0-dev中bevy_feathers的cursor模块已被整体迁移到bevy_picking之下custom_cursor特性也随之转移。阅读本文后你将掌握这次迁移涉及的类型、导入路径与特性开关的具体变化能够正确修改自己的use语句与Cargo.toml并理解EntityCursor、DefaultCursor、OverrideCursor与CursorIconPlugin在新位置的实现原理即如何根据指针悬停实体自动切换窗口鼠标光标以及custom_cursor特性如何逐层打通bevy_window与bevy_winit。迁移内容总览根据迁移说明文档 _release-content/migration-guides/cursor_module_to_bevy_picking.md本次迁移对应上游 PR #25294包含两部分变化bevy_feathers中的cursor模块——包含EntityCursor、DefaultCursor、OverrideCursor和CursorIconPlugin四个公开类型——从bevy_feathers::cursor移动到bevy_picking::cursorcustom_cursor特性从bevy_feathers迁移到bevy_picking。最直接的改动就是导入路径// Before0.20 之前 use bevy_feathers::cursor::{CursorIconPlugin, DefaultCursor, EntityCursor, OverrideCursor};// After当前仓库版本 use bevy_picking::cursor::{CursorIconPlugin, DefaultCursor, EntityCursor, OverrideCursor};模块本身在 crates/bevy_picking/src/lib.rs 中以pub mod cursor;的形式公开见第 160 行实现代码位于 crates/bevy_picking/src/cursor.rs。四个类型的职责与实现DefaultCursor无悬停时的回退光标DefaultCursor是一个资源Resource指定当鼠标没有悬停在任何带光标设置的实体上时窗口使用的默认光标图标。其实现是一个对EntityCursor的透明包装/// A resource that specifies the cursor icon to be used when the mouse is not hovering over /// any other entity. #[derive(Deref, Resource, Debug, Clone, Default, Reflect)] #[reflect(Resource, Debug, Default)] pub struct DefaultCursor(pub EntityCursor);它支持Deref因此ResDefaultCursor可以直接按EntityCursor使用同时派生了Reflect可参与 ECS 反射体系。EntityCursor悬停实体的光标形状EntityCursor是组件Component插入到实体上后当指针悬停该实体时窗口光标会被设置为该值。它是一个枚举#[derive(Component, Debug, Clone, Reflect, PartialEq, Eq, FromTemplate)] #[reflect(Component, Debug, Default, PartialEq, Clone)] pub enum EntityCursor { #[cfg(feature custom_cursor)] /// Custom cursor image. Custom(CustomCursor), #[default] /// System provided cursor icon. System(SystemCursorIcon), }EntityCursor::Custom(CustomCursor)仅在custom_cursor特性开启时存在允许使用自定义光标图片CustomCursor来自 bevy_windowEntityCursor::System(SystemCursorIcon)使用系统提供的标准光标箭头、等待、文本框等且是该枚举的#[default]。该类型还提供两个转换方法见 cursor.rs 第 54-75 行to_cursor_icon()把EntityCursor转为bevy_window::CursorIcon以便插入窗口实体eq_cursor_icon()比较当前值与窗口已有的CursorIcon是否一致用于避免每帧重复写入窗口组件。源码中的注释特别解释了它的实现动机当bevy_feathers未启用custom_cursor时无法静态判断bevy_window侧是否启用了该特性因此借助cursor_icon.as_system()包装函数让bevy_window自行按自身特性决定比较逻辑从而在所有特性组合下都能编译通过且无不可达分支。OverrideCursor全局覆盖OverrideCursor是另一个资源内部为OptionEntityCursor/// A resource used to override any [EntityCursor] cursor changes. /// This is meant for cases like loading where you dont want the cursor to imply /// you can interact with something. #[derive(Deref, Resource, Debug, Clone, Default, Reflect)] pub struct OverrideCursor(pub OptionEntityCursor);它的用途是全局压过任何实体级的EntityCursor——典型场景是加载期间强制显示等待光标避免误导用户以为可以交互。CursorIconPlugin 与 update_cursor 系统CursorIconPlugin是入口插件其build方法做了两件事见 cursor.rs 第 124-131 行若资源尚未初始化则init_resource::DefaultCursor()和init_resource::OverrideCursor()把update_cursor系统注册到PreUpdate调度并放入PickingSystems::Last系统集。update_cursor系统的决策逻辑是理解整条链路的钥匙let cursor r_override_cursor.0.as_ref().unwrap_or_else(|| { hover_map .and_then(|hover_map| match hover_map.get(PointerId::Mouse)) ... .unwrap_or(r_default_cursor) });优先级为OverrideCursor有值时直接使用它否则查询HoverMap中鼠标PointerId::Mouse悬停的实体集合逐一查找带EntityCursor组件的实体排除Window实体并沿ChildOf父链向上回溯parent_query.iter_ancestors子实体未设置时继承祖先的光标都找不到时回落到DefaultCursor资源。确定目标光标后系统遍历所有带Window组件的实体若窗口当前的CursorIcon与新值不相等eq_cursor_icon判断才执行commands.entity(entity).insert(cursor.to_cursor_icon())天然支持多窗口场景并避免无谓写入。值得注意的运行时机系统挂在 PickingSystems::Last即PreUpdate中所有 picking 系统集ProcessInput→Backend→Hover→PostHover→Last定义于 lib.rs 第 259-277 行之后——此时HoverMap已由本帧的悬停计算更新完毕光标切换始终基于最新悬停状态。custom_cursor 特性的迁移路径特性迁移在 Cargo 层面的证据链如下crates/bevy_picking/Cargo.tomlcustom_cursor [bevy_window/custom_cursor]第 13 行即bevy_picking的该特性现在直接转发给bevy_windowcrates/bevy_internal/Cargo.toml统一入口bevy的custom_cursor特性第 404-407 行展开为三个依赖项特性custom_cursor [ bevy_window/custom_cursor, bevy_winit/custom_cursor, bevy_picking/custom_cursor, ]crates/bevy_feathers/Cargo.tomlbevy_feathers对bevy_picking的依赖已固定启用custom_cursor特性第 26-28 行因此使用 feathers 的EntityCursor::Custom变体无需用户再额外声明特性。从源码结构看这条特性链最终落到 crates/bevy_winit/src/cursor/mod.rsbevy_winit在custom_cursor开启时才会编译自定义光标模块、维护WinitCustomCursorCache光标缓存并在渲染循环中通过event_loop.create_custom_cursor(cursor)创建 winit 层的自定义光标。也就是说光标的“决策”Bevy 侧与“落地”winit 侧被特性开关严格对齐。bevy_feathers自身也已完成内部切换crates/bevy_feathers/src/lib.rs 第 30 行改为use bevy_picking::cursor::{CursorIconPlugin, DefaultCursor, EntityCursor};FeathersCorePlugin::build中直接注册CursorIconPlugin第 79 行并插入默认值DefaultCursor(EntityCursor::System(SystemCursorIcon::Default))第 98-100 行。由于旧路径bevy_feathers::cursor已删除第三方 crate 若仍按旧路径导入将直接编译失败必须按前文 “After” 代码更新导入。实际用例验证仓库内的示例 examples/ui/widgets/feathers_gallery.rs 展示了迁移后 API 的典型用法通过picking::cursor::{EntityCursor, OverrideCursor}导入类型并在加载中把覆盖光标设为系统等待光标Some(EntityCursor::System(SystemCursorIcon::Wait))配合OverrideCursor资源即可实现“加载时禁用交互暗示”的效果与源码文档注释中的设计意图一致。迁移检查清单针对升级0.20.0-dev的项目建议按以下顺序核对全局替换导入路径把bevy_feathers::cursor::{...}替换为bevy_picking::cursor::{...}涉及EntityCursor、DefaultCursor、OverrideCursor、CursorIconPlugin四个类型更新特性声明如果Cargo.toml中对bevy或bevy_feathers启用了custom_cursor确认改为/补充启用bevy_picking/custom_cursor或直接依赖统一的bevy入口特性由 bevy_internal 转发依赖可达性直接使用bevy_picking::cursor需要项目依赖bevy_pickingcrate或经由bevy入口与bevy_picking特性启用见 crates/bevy_internal/Cargo.toml 第 352 行bevy_picking [dep:bevy_picking]行为不变确认迁移只改变了模块归属与特性位置update_cursor的优先级逻辑Override → 悬停实体/祖先链 → Default、多窗口写入与变化检测行为均保持原样。适用前提说明以上结论均基于当前仓库0.20.0-dev版本源码与迁移文档EntityCursor::Custom变体仅在custom_cursor特性开启时存在未启用该特性的代码应只使用EntityCursor::System分支。【免费下载链接】bevyA refreshingly simple>项目地址: https://gitcode.com/GitHub_Trending/be/bevy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价