十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Bevy Feathers 数字输入控件 API 迁移:从 UpdateNumberInput 事件到 NumberInputValue 组件

Bevy Feathers 数字输入控件 API 迁移:从 UpdateNumberInput 事件到 NumberInputValue 组件 Bevy Feathers 数字输入控件 API 迁移从 UpdateNumberInput 事件到 NumberInputValue 组件【免费下载链接】bevyA refreshingly simple>项目地址: https://gitcode.com/GitHub_Trending/be/bevy本文聚焦 BevyFeathersNumberInput控件的 API 变更程序化更新数值的方式从触发UpdateNumberInput事件改为向实体插入NumberInputValue组件。读完后你能够理解这次迁移的动机与具体改法掌握SoftLimit、HardLimit、NumberInputPrecision、NumberInputStep等配置组件的用法并理解控件在 scrubbing拖拽、点击与键入三种编辑模式下的底层状态机从而正确地为应用编写ValueChange事件处理器。迁移核心用组件插入替代事件触发FeathersNumberInput的 API 发生了变化要程序化地更新数值不应再触发UpdateNumberInput事件而应直接插入NumberInputValue组件。这一改动的主要收益是在控件创建时就能顺带指定初始值创建实体时把NumberInputValue一并放入而无需等待实体生成后再发一次事件。迁移前后的对比// BEFORE commands.trigger(UpdateNumberInput { entity: input_ent, value: NumberInputValue::F32(new_value), }); // AFTER commands .entity(input_ent) .insert(NumberInputValue::F32(new_value));从源码看这一机制由一个 ECS Observer 实现FeathersNumberInput的bsn!场景模板在控件根实体上注册了on(number_input_on_insert_value)对应观察者监听OnInsertNumberInputValue。当NumberInputValue被插入时观察者会通过Children查询找到内部的可编辑文本实体若存在HardLimit先对新值做clamp借助UnitsRegistry把数值格式化为显示文本若与当前文本缓冲区不同则通过TextEdit::SelectAllTextEdit::Insert替换内容调用update_slider_pos同步背景滑动条的位置。该实现位于 number_input_on_insert_value这正是组件插入即可驱动 UI 刷新这一新契约的代码依据。同时FeathersNumberInput结构体上带有#[require(NumberInputValue)]属性第 96-100 行意味着每个数字输入控件都会被要求持有一个NumberInputValue初始值因此可以在生成时直接给全。数值类型与双向同步模型NumberInputValue是一个枚举组件携带具体的数值与类型变体第 286-297 行变体类型对应发射的事件NumberInputValue::F32f32ValueChangef32NumberInputValue::F64f64ValueChangef64NumberInputValue::I32i32ValueChangei32NumberInputValue::I64i64ValueChangei64该枚举内部还实现了parse_from按类型解析文本失败时返回错误信息、offset_by/scale_by保持变体不变地做增量/缩放运算整数变体使用saturating_add与四舍五入防止溢出等辅助方法是拖拽运算的基础。这是一个受控控件controlled widget控件内部的数值不会自动成为单一事实来源。源码文档注释明确了两向同步的职责划分第 69-95 行控件 → 应用用户键入或拖拽时控件通过ValueChangeT事件向外发出数值应用 → 控件应用侧属性变化无论是否由ValueChange触发时插入NumberInputValue组件来刷新显示。一个容易被忽视的细节拖拽过程中ValueChange的is_final字段为false但你仍然应该响应这些中间事件并更新控件否则用户在拖拽时看不到实时变化的数值。为避免不必要的刷新建议仅在新值与当前值不同时才插入组件。行为配置组件HardLimit、SoftLimit、Precision 与 Step控件的行为可以通过插入若干可选组件来定制。官方示例 feathers_number_input.rs 演示了这些组件的典型组合用法demo_field_f32(soft limit, 2.0, bsn!( SoftLimit(NumberInputRange::F32(0.0..10.0)) )), demo_field_f32(hard limit, 3.0, bsn!( HardLimit(NumberInputRange::F32(-100.0..100.0)) )), demo_field_f32(precision(2), 6.0, bsn!( NumberInputPrecision(2) )), demo_field_f32(step(1.0), 8.0, bsn!( NumberInputStep(1.0f64) )), demo_field_f32(hard limit wrap, 0.0, bsn!( HardLimit(NumberInputRange::F32(-180.0..180.0)) NumberInputWrap::Wrap )), demo_field_f32(in meters, 2.0, bsn!( NumberInputUnits::new(LengthMeters) )),各组件的语义与源码实现细节如下HardLimit(NumberInputRange)值的绝对约束。数值超出范围会被clamp截断若同时指定NumberInputWrap::Wrap则改为wrap通过rem_euclid环绕回区间内。clamp/wrap的类型一致性在 NumberInputRange 中按变体配对实现类型不匹配时仅警告一次并原样放行。若该组件不存在则使用数据类型的自然取值范围。SoftLimit(NumberInputRange)拖拽scrubbing可到达的范围键入的值仍可以超出此范围。当SoftLimit存在时控件外观与手感类似滑块背景会绘制一条滑动条且拖拽速度按范围宽度 / 滑块像素宽度计算使滑动条长度变化与鼠标移动同步。若不存在SoftLimit控件更像scrubber没有滑动条拖拽速度由启发式规则推算。NumberInputPrecision(i32)拖拽时的十进制精度位数防止数字在屏幕上疯狂跳动。值为2表示四舍五入到百分位负值如-3表示按千位取整。它只在拖拽时对值做量化不影响键入。默认值为2。它还会作为拖拽速度启发式的输入之一。NumberInputStep(f64)递增/递减的步长示例中两侧还有 chevron 图标按钮默认值为1.0。它也参与无SoftLimit时的拖拽速度启发式。NumberInputUnits(SmolStr)补充标注所编辑量的类型与单位长度、角度、时间等字符串指向一个已注册的UnitsFormat例如LengthMeters、TimeSeconds、AngleDegrees。它同时影响显示格式化如把°换成易输入的d与解析。拖拽速度的完整启发式链在 scrubber_on_drag_start 中优先级为有SoftLimit(range.end - range.start) / slider_size像素否则有NumberInputStepstep * BASE_DRAG_SPEEDBASE_DRAG_SPEED 0.01否则是整数类型视同步长 1使用BASE_DRAG_SPEED否则有NumberInputPrecision10^(-precision)都没有根据当前数值量级取最近的 10 的幂乘以BASE_DRAG_SPEED。编辑模式状态机点击、拖拽与键入控件内部用EditMode枚举管理三种状态第 649-657 行Idle未聚焦、Scrubbing拖拽取值、Editing键入编辑。状态转换逻辑按下scrubber_on_press非编辑状态下进入Scrubbing并把文本实体切为TextReadWriteMode::Static拖拽开始/移动/结束scrubber_on_drag_*仅当Scrubbing模式生效。拖动超过阈值DRAG_THRESHOLD_DISTANCE 0.5像素后按drag_speed把像素位移换算为数值增量按住Shift时增量乘以0.1实现微调。每次变化经emit_drag_value_change依次应用 SoftLimit 截断、Precision 取整、HardLimit 截断或 Wrap 环绕后触发ValueChange拖动过程中is_final false结束时为true释放scrubber_on_release若本次总位移不超过 0.5 像素即判定为点击而非拖拽进入Editing模式文本实体变为可编辑光标切换为 I 型并按点击位置放置光标Enter 或失焦number_input_on_enter_key/number_input_on_focus_lost解析文本缓冲区退出Editing模式并通过emit_value_change发射最终的ValueChange。所有拖拽手势由一个覆盖在输入区域上的透明子实体拦截处理场景模板第 219-235 行它同时注册了scrubber_on_press/scrubber_on_release/scrubber_on_drag_start/scrubber_on_drag/scrubber_on_drag_end/scrubber_on_drag_cancel六个观察者。事件处理器官方的最小同步范例作为受控控件应用必须自己写处理器把ValueChange回填到NumberInputValue。官方示例给出了一个极简写法feathers_number_input.rs 第 133-137 行on( |value_change: OnValueChangef32, mut commands: Commands| { commands.entity(value_change.event_target()) .insert(NumberInputValue::F32(value_change.value)); })即收到ValueChangef32观察者事件时向事件源实体插入对应的NumberInputValue组件完成一次闭环。示例中f64与i32字段的处理器同理只是泛型参数与组件变体不同。若需要区分多个输入控件可在示例的bsn!中为每个控件附加一个专属标识组件再查询哪个带该标识的FeathersNumberInput是事件源仓库还提供了 number_input_f32 这类封装了标签、NumberInputPrecision、HardLimit的辅助函数。迁移检查清单全局替换UpdateNumberInput事件触发为commands.entity(x).insert(NumberInputValue::T(v))UpdateNumberInput在当前仓库中已无定义仅存留于本迁移指南的历史说明中创建控件时直接把初始NumberInputValue放入bsn!场景替代先生成、再触发事件的两步流程确认你的ValueChangeT处理器对拖拽中间值is_final false也执行回填以保证拖拽实时显示需要限定取值范围、量化精度或单位显示时分别插入HardLimit/SoftLimit/NumberInputPrecision/NumberInputStep/NumberInputUnits并用 示例 中的组合方式验证行为涉及角度环绕的场景可加NumberInputWrap::Wrap必须搭配HardLimit才生效否则仅警告并忽略。【免费下载链接】bevyA refreshingly simple>项目地址: https://gitcode.com/GitHub_Trending/be/bevy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表