#imgui #widgets #inspect #values #default #ui #traits

imgui-inspect

使用 imgui 检查值的特性和默认实现

13 个版本 (7 个破坏性更新)

0.8.0 2021 年 2 月 6 日
0.7.0 2020 年 11 月 17 日
0.5.0 2020 年 5 月 30 日
0.4.0 2020 年 3 月 7 日
0.3.3 2019 年 9 月 28 日

#223GUI

每月 46 次下载

MIT/Apache

23KB
541 代码行

imgui_inspect

简而言之,这是一个使用 ImGuiRust 实现的属性编辑器的实现。

更具体地说,这个 crate 旨在成为 imgui 检查的 serde。它定义了一个公共接口,用于将值放入 imgui 并将其导出。

为某些类型提供了默认实现,以便作为特定小部件绘制,但主要目标是使其轻松实现自己的首选值渲染方式。

  • 每个小部件类型都有一个特例(例如 InspectRenderSlider
  • 每个值类型都有一个实现(例如 f32

Build Status Crates.io

示例

如果您想看到这个 crate 的实际应用,请查看 imgui-inspect-demo。在该目录下运行 cargo run 将启动它。

YouTube Demo

您还可以参考 minimum 中的代码。该视频 此视频 展示了在这个库中的应用。

其中实现了许多更复杂的使用案例,例如自定义类型和处理多个选定的值。

状态

这个 crate 的整体设计不太可能改变,但实现了许多 imgui 小部件类型和值类型。

未来的大部分工作将是

  • 为每个 imgui 小部件类型添加特例
  • 定义表示该 imgui 小部件有效选项的结构体
  • 为 std 类型实现合理的默认值

这是一个相当直接的过程,并且存在基本示例,但添加它们需要时间。

随着我对更多类型的支持需求,我将继续扩展它,但如果您需要缺少的东西,请提交 PR!下面有详细的说明。

使用

对于默认渲染行为,在您的结构上派生 Inspect

#[derive(Inspect)]
pub struct MyStruct {
    pub first_value: f32,
    pub second_value: f32,
}

要绘制,请使用UI窗口和您struct实例的引用调用它

    // ....
    ui.text(im_str!("This...is...imgui!"));
    ui.separator();
    let my_struct = MyStruct::default(); // example, maybe get it from somewhere else instead
    <MyStruct as InspectRenderDefault<MyStruct>>::render(
        &[&my_struct], 
        &"my_struct_test", 
        ui, 
        &InspectArgsDefault::default()
    );

my_struct被传递为&[&my_struct]的原因是通常需要选择多个对象。在这种情况下,渲染代码可以比较所有选中项的值是否一致,或者在可变渲染的情况下,将更改应用于所有选中值。

简单自定义

通过标记化struct成员,您可以获得略微不同的行为。这可以选择要绘制的小部件并调整它们的设置。

#[derive(Inspect)]
pub struct MyStruct {    
    // Use a slider widget with the given min/max values
    #[inspect_slider(min_value = 5.0, max_value = 53.0)]
    pub sliding_value: f32,
}

高级自定义

内部,为MyStruct实现Inspect时,实现InspectRenderDefault。但如果您需要执行自定义操作,可以手动实现它。

impl InspectRenderDefault<MyStruct> for MyStruct {
    fn render(data: &[&MyStruct], label: &'static str, ui: &imgui::Ui, args: &InspectArgsDefault) {
        ui.text("custom rendering is easy!");
    }
    fn render_mut(data: &mut [&mut MyStruct], label: &'static str, ui: &imgui::Ui, args: &InspectArgsDefault) {
        ui.text("custom rendering is easy!");
    }
}

screenshot

API允许混合和匹配正在渲染的Render特性和类型。可以通过重写render_trait使单个类型以多种方式渲染。

pub trait InspectRenderMyCustomWidgetType<T> {
    fn render(data: &[&T], label: &'static str, ui: &imgui::Ui, args: &InspectArgsDefault);
    fn render_mut(data: &mut [&mut T], label: &'static str, ui: &imgui::Ui, args: &InspectArgsDefault);
}

#[derive(Inspect)]
pub struct MyStruct {
    #[inspect(render_trait = "InspectRenderMyCustomWidgetType")]
    pub a_value: f32,
}

这将调用<f32as InspectRenderMyCustomWidgetType>::render(...)。这对于以几种不同的方式渲染同一类型非常有用。

有时您想在其他crate中为类型实现自己的渲染,但有一个问题...特性能在特性和类型本身所在的同一crate中实现。

您可以自己包装类型(例如,struct MyVec2(glm::Vec2)),或者使用虚拟类型并重写proxy_type。

struct ImGlmVec2;
impl InspectRenderDefault<glm::Vec2> for ImGlmVec2 {
    fn render(data: &[&glm::Vec2], label: &'static str, ui: &imgui::Ui, args: &InspectArgsDefault) {
        // ...
    }

    fn render_mut(data: &mut [&mut glm::Vec2], label: &'static str, ui: &imgui::Ui, args: &InspectArgsDefault) {
        // ...
    }
}

#[derive(Inspect, Clone)]
pub struct MyStruct {
    #[inspect(proxy_type = "ImGlmVec2")]
    pub position: glm::Vec2,
}

此类型永远不会实例化。它仅用于解决应调用哪个函数:<ImGlmVec2 as InspectRenderDefault>::render(...)

为值类型添加默认小部件实现

请记住,如果您不想进行更改或不喜欢默认实现,您始终可以使用代理类型!

这很容易做到,只需要更改imgui-inspect

  • 许多示例位于imgui-inspect/src
  • 添加一个新模块[WIDGET]/[WIDGET]_[TYPE]
    • 示例:slider/slider_f32.rs
  • 添加实现:impl<TYPE> InspectRender[WIDGET] for TYPE
    • 示例:impl<f32> InspectRenderSlider for f32

添加新的小部件类型

总之,我们需要添加一个特性,为一些类型实现该特性和将小部件/配置选项添加到proc宏。

  • 添加特性
    • InspectArgs[WIDGET]InspectRender[WIDGET] 添加到 imgui-inspect/src/[WIDGET]/mod.rs
    • 示例:在 imgui-inspect/src/slider 中,InspectArgsSliderInspectRenderSlider
    • InspectArgs[WIDGET] 中的值是可以传递给 imgui 的选项
    • InspectArgs[WIDGET] 的实现应该将这些值传递给 imgui 小部件
  • 按照上述“为值类型添加默认小部件实现”的说明,为类型实现特制
  • 将小部件添加到 proc macro
    • InspectFieldArgs[WIDGET]InspectArgs[WIDGET] 添加到 imgui-inspect-derive/src/inspect_macro/args/[WIDGET]_args.rs
      • 示例:在 slider_args.rs 中,InspectFieldArgsSliderInspectFieldArgsSlider
      • InspectArgs[WIDGET] 是 inspect-imgui 中相同结构的复制粘贴。(它被复制,因为 proc_macro 包不能导出类型)
      • InspectArgs[WIDGET] 是小部件的独特值,而 InspectFieldArgs[WIDGET] 是可以通过宏更改的每个属性
    • 这些结构 InspectArgsDefaultInspectFieldArgsDefault 应该是任何小部件所有可能参数的超集。更新
      • imgui-inspect-derive/src/inspect_macro/args/default_args.rs
      • imgui-inspect/src/default/mod.rs
    • imgui-inspect-derive/src/inspect_macro/mod.rs 中更新 handle_inspect_types()
    • imgui-inspect-derive/src/lib.rs 中添加小部件类型到 proc_macro_derive

使 imgui 可选

通常,你不想将 imgui 部署到最终产品中。然而,有条件地包含 proc_macro 是不方便的。Rust 会对它不知道的任何宏发出警告,因此有条件地从项目中删除 imgui-inspect-derive 依赖项需要嘈杂的标记。

为了解决这个问题,imgui-inspect-derive 宏使用了一个特性 "generate_code"。禁用默认特性将阻止生成代码。

步骤

  • 将 imgui-inspect 设置为可选
    • 示例:imgui-inspect = { version = "...", optional = true }
  • 关闭 imgui-inspect-derive 默认特性
    • 示例:imgui-inspect-derive = { version = "...", default-features = false }

imgui-inspect-derive 生成样板代码,但实际上并不依赖于 imgui。禁用默认功能意味着 generate_code 功能将关闭,导致宏被解析,但不会生成代码。

贡献

所有贡献都假定在 MIT/Apache-2 许可下双许可。

许可

在 MIT 许可证和 Apache 许可证(版本 2.0)的条款下分发。

请参阅 LICENSE-APACHELICENSE-MIT

字体目录包含多个字体,分别受其自己的许可证保护

依赖关系

约 15MB
约 284K SLoC