#imgui #game #values #default #inspect #traits #inspecting

imgui-inspect-derive

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

10 个版本 (破坏性更新)

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.0 2019年9月8日

#inspecting 中排名 16

每月下载量 42
用于 imgui-inspect

MIT/Apache

23KB
567 行代码(不包括注释)

imgui_inspect

这是一个使用 ImGuiRust 实现的属性编辑器的简化实现。

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

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

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

Build Status Crates.io

示例

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

YouTube Demo

您还可以参考 minimum 中的代码。此视频 中的属性编辑器 展示了在此库中的使用。

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

状态

此包的整体设计不太可能更改,但实现了很多 imgui 小部件类型和值类型。

大部分未来的工作将包括

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

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

随着需要支持更多类型,我会继续扩展这个功能。如果你需要缺少的功能,请提交PR!下面有详细的说明。

用法

为了实现默认渲染行为,请派生你的结构体上的Inspect

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

要绘制,请使用UI窗口和你的结构体实例的引用调用它

    // ....
    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]传递的原因是通常需要选择多个对象。在这种情况下,渲染代码可以比较所有选定项目的值是否一致,或者在可变渲染的情况下,将更改应用到所有选定值。

简单定制

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

#[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,
}

高级定制

内部,派生Inspect实现了MyStruct上的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_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,
}

这将调用<f32 as 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 InspectRender[<[TYPE]> for [TYPE]
    • 示例:impl InspectRenderSlider<f32> for f32

添加新的小部件类型

总之,我们需要为小部件添加一个特性,为某些类型实现该特性,并将小部件/config选项添加到进程宏中

  • 添加特性
    • InspectArgs[WIDGET]InspectRender[WIDGET]添加到imgui-inspect/src/[WIDGET]/mod.rs
    • 示例:在imgui-inspect/src/slider中的InspectArgsSliderInspectRenderSlider
    • InspectArgs[WIDGET]中的值是可以输入到imgui中的选项
    • InspectArgs[WIDGET]的实现应将这些值传入imgui小部件
  • 按照上述“添加默认值类型的小部件实现”说明为类型实现特性
  • 将小部件添加到进程宏
    • InspectFieldArgs[WIDGET]InspectArgs[WIDGET]添加到imgui-inspect-derive/src/inspect_macro/args/[WIDGET]_args.rs
      • 示例:在slider_args.rs中的InspectFieldArgsSliderInspectFieldArgsSlider
      • InspectArgs[WIDGET]是inspect-imgui中的相同结构的复制粘贴(因为它被重复,因为进程宏crate不能导出类型)
      • InspectArgs[WIDGET]是特定于小部件的唯一值,而InspectFieldArgs[WIDGET]是通过宏可以更改的每个属性
    • 这些结构InspectArgsDefaultInspectFieldArgsDefault应该是任何小部件可能的所有arg的超集。更新
      • 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中将小部件类型添加到进程宏_derive

使imgui成为可选的

通常,你不想将imgui打包到最终产品中。但是,条件性地包含进程宏很尴尬。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

字体目录包含受各自许可证保护的几个字体

依赖项

~2MB
~43K SLoC