没有多按钮系统的多按钮?

Multiple buttons without multiple button systems?

我对 rust 和 bevy 都比较陌生。我意识到现在还处于早期阶段,并且非常喜欢 bevy,但坦率地说,我发现示例和文档有点缺乏。

我使用 /examples/ui/button.rs 作为起点。我想添加一堆按钮而不是一个。

我正在寻找一种方法来区分单击了哪个按钮。

我知道我可以为每个按钮添加一个系统,但这在任何语言中都不是正确的方法。

所以,我开始添加标记(就像 bevy-cheatsheet 所建议的那样)。

commands
    .spawn(ButtonComponents { /* cut for brevity */ })
    .with_children(|parent| {
        parent
            .spawn(TextComponents {  /* cut for brevity */ })
            .with(Marker1);
    });

但是我该如何检查生成按钮的标记?

fn button_system(
    button_materials: Res<ButtonMaterials>,
    mut interaction_query: Query<(
        &Button,
        Mutated<Interaction>,
        &mut Handle<ColorMaterial>,
        &Children,
    )>,
    text_query: Query<&mut Text>,
) {
    for (_button, interaction,  mut material, children) in &mut interaction_query.iter() {
        let mut text = text_query.get_mut::<Text>(children[0]).unwrap();
        match *interaction {
            Interaction::Clicked => {            

                // This obviously doesn't work, just to illustrate what I'm looking for.
                match text.spawned_with {
                    Marker1 => doSomething(),
                    Marker2 => doBarrelRoll(),
                    _ => unreachable!()
                }    

            }
            Interaction::Hovered => {
                text.value = "Hover".to_string();
                *material = button_materials.hovered.clone();
            }
            Interaction::None => {
                text.value = "Button".to_string();
                *material = button_materials.normal.clone();
            }
        }
    }
}

欢迎任何提示,谢谢!

编辑:现在我很困惑,因为这实际上适用于按钮 1,(但会使按钮 2 崩溃):

Interaction::Clicked => {
    let marker = text_query.get::<_>(children[0]).unwrap();
    match *marker {
        Marker1 => println!("marker 1"),
        _ => unreachable!(),
    }
}

但这甚至无法构建:

    let marker = text_query.get::<_>(children[0]).unwrap();
    match *marker {
        Marker1 => println!("marker 1"),
        Marker2 => println!("marker 2"),
        _ => unreachable!(),
    }

这是错误:

   |                     expected struct `Marker1`, found struct `Marker2`
   |                     `Marker2` is interpreted as a unit struct, not a new binding
   |                     help: introduce a new binding instead: `other_marker2`

好的,我找到了答案,但如果您有更优雅的答案,我很乐意学习并改成正确答案!

Interaction::Clicked => {
    if let Ok(_) = text_query.get::<Marker1>(children[0]) {
        println!("marker 1")
    }
    if let Ok(_) = text_query.get::<Marker2>(children[0]) {
        println!("marker 2")
    }
    if let Ok(_) = text_query.get::<Marker3>(children[0]) {
        doBarrelRoll()
    }
    ...
}

在 daniel kullmans 的评论之后,我得到了这样的结果:

#[derive(PartialEq)]    // needed for comparison
pub enum Buttons {
    MyFirstButton,
    MySecondButton,
}
struct MyButton {
    target: Buttons,
}

还有...

commands
    .spawn(ButtonComponents { /* cut for brevity */ })
    .with_children(|parent| {
        parent
            .spawn(TextComponents {  /* cut for brevity */ })
            .with(MyButton { target: Buttons }); 
    });

还有...

Interaction::Clicked => {
    if let Ok(btn) = text_query.get_mut::<MyButton>(children[0]) {
        match btn.target {
            Buttons::MyFirstButton => {
               ...
            },
            Buttons::MySecondButton => {
               ...
            },
            _ => unreachable!(),
        }
    }
}