#bevy-ui #menu #bevy #ui #gamepad-input #bevyui

bevy_quickmenu

在bevy中快速创建嵌套菜单的一种简单方法,可以通过键盘、手柄和指针进行导航

5个版本

0.2.0 2023年7月11日
0.1.6 2023年7月11日
0.1.5 2022年12月4日
0.1.1 2022年11月18日
0.1.0 2022年11月18日

#1494游戏开发

48 每月下载次数

MIT 许可证

77KB
1.5K SLoC

License: MIT Doc Crate

🏃‍♂️ Bevy Quickmenu

每个游戏都需要菜单。无论是设置、暂停屏幕还是用户进入游戏时的主菜单。

虽然Bevy UI允许构建菜单,但这是一个繁琐的过程,尤其是在需要嵌套菜单的情况下。更糟糕的是,如果你想让你的菜单可以通过键盘、手柄或鼠标访问,那么所需的努力就更大了。

Bevy Quickmenu提供所有这些功能。它是一种超轻量级的构建游戏菜单的方法,可以通过所有输入设备进行控制。它甚至提供了一个简单的方法来设置 hover 状态。所有内容都可以进行自定义。

  • 为bevy提供的超简单菜单插件,基于Bevy UI构建
  • 处理键盘、鼠标、手柄输入
  • 支持简化的样式表中的鼠标悬停状态
  • 许多自定义选项(请参阅 examples/custom.rs

用法

添加到 Cargo.toml

[dependencies]
bevy_quickmenu = "0.1.5"

版本兼容性

Bevy版本 Crate版本
0.11.0 0.2.0
0.10.0 0.1.6
0.9.0 0.1.5

演示

Demo Gif

快速示例

所需组件的解释

状态

一个泛型类型,用于托管菜单的状态(例如,哪些项目被选中等)。每当此状态发生变化时,菜单会自动重新绘制。

动作

(符合 ActionTrait): 此枚举定义了用户可以执行的所有操作。例如 SoundOnSoundOff 等。当用户执行操作(通过选择相应的菜单项)时,将在您的 ActionTrait 实现上调用 handle 方法。 ActionTrait 有两个泛型类型:您的 State 以及您可以定义的 Event。这允许您处理您的操作

#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
enum Actions {
    Close,
    SoundOn,
    SoundOff,
    Control(usize, ControlDevice),
}

impl ActionTrait for Actions {
    type State = CustomState;
    type Event = MyEvent;
    fn handle(&self, state: &mut CustomState, event_writer: &mut EventWriter<MyEvent>) {
        match self {
            Actions::Close => event_writer.send(MyEvent::CloseSettings),
            Actions::SoundOn => state.sound_on = true,
            Actions::SoundOff => state.sound_on = false,
            Actions::Control(p, d) => {
                state.controls.insert(*p, *d);
            }
        }
    }
}

屏幕

(符合 ScreenTrait)。您的菜单中的每个页面或屏幕都由此枚举定义。请注意,菜单屏幕是 不嵌套 的!相反,ScreenTrait 有一个 resolve 函数,允许您返回给定枚举的相应菜单定义

#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
enum Screens {
    Root,
    Controls,
    Sound,
    Player(usize),
}

impl ScreenTrait for Screens {
    type Action = Actions;
    fn resolve(&self, state: &mut CustomState) -> Menu<Screens> {
        match self {
            Screens::Root => root_menu(state),
            Screens::Controls => controls_menu(state),
            Screens::Sound => sound_menu(state),
            Screens::Player(p) => player_controls_menu(state, *p),
        }
    }
}

菜单

菜单只是一个返回要显示的 MenuItem 列表的功能。每个菜单都需要有一个独特的 ID。示例显示了 rootsound 菜单的定义。

fn root_menu(_state: &mut CustomState) -> Menu<Screens> {
    Menu::new(
        Id::new("root"),
        vec![
            MenuItem::headline("Settings"),
            MenuItem::action("Back", Actions::Close).with_icon(MenuIcon::Back),
            MenuItem::screen("Sound", Screens::Sound).with_icon(MenuIcon::Sound),
            MenuItem::screen("Controls", Screens::Controls).with_icon(MenuIcon::Controls),
        ],
    )
}

fn sound_menu(state: &mut CustomState) -> Menu<Screens> {
    Menu::new(
        Id::new("sound"),
        vec![
            MenuItem::label("Toggles sound and music"),
            MenuItem::action("On", Actions::SoundOn).checked(state.sound_on),
            MenuItem::action("Off", Actions::SoundOff).checked(!state.sound_on),
        ],
    )
}

菜单项

为了给您提供 一些 灵活性,菜单项允许您返回五种不同的类型

  • MenuItem::label:一个小文本标签,不能被选择
  • MenuItem::headline:一个大文本标签,不能被选择
  • MenuItem::action:当用户选择时执行的操作
  • MenuItem::screen:当用户选择此选项时,深入屏幕
  • MenuItem::image:单个图像(包括可选的 Style

此外,菜单项可以具有一些预定义的图标或自定义图标

MenuItem::screen("Controls", Screens::Controls).with_icon(MenuIcon::Controls)
MenuItem::screen("Save", Screens::Save).with_icon(MenuIcon::Other(icons.save.clone()))

MenuItem 也可以是勾选或取消勾选的

MenuItem::action("On", Actions::SoundOn).checked(state.sound_on)
MenuItem::action("Off", Actions::SoundOff).checked(!state.sound_on)

显示菜单

以下是从示例中提供的注释设置函数

impl Plugin for SettingsPlugin {
    fn build(&self, app: &mut App) {
        app
            // Register a event that can be called from your action handler
            .add_event::<BasicEvent>()
            // The plugin
            .add_plugins(QuickMenuPlugin::<Screens>::new())
            // Some systems
            .add_startup_system(setup)
            .add_system(event_reader);
    }
}

fn setup(mut commands: Commands) {
    commands.spawn(Camera3dBundle::default());
    commands.insert_resource(MenuState::new(
        BasicState::default(),
        Screens::Root,
        Some(StyleSheet::default()),
    ))
}

移除菜单

为了移除菜单,有 bevy_quickmenu::cleanup 函数。通常,最好与 Bevy Quickmenu 允许您注册的事件一起使用

#[derive(Debug)]
enum BasicEvent {
    Close,
}

impl ActionTrait for Actions {
    fn handle(&self, state: &mut BasicState, event_writer: &mut EventWriter<BasicEvent>) {
        match self {
            Actions::Close => event_writer.send(BasicEvent::Close),
        }
    }
}

fn event_reader(mut commands: Commands, mut event_reader: EventReader<BasicEvent>) {
    for event in event_reader.iter() {
        match event {
            BasicEvent::Close => bevy_quickmenu::cleanup(&mut commands),
        }
    }
}

自定义屏幕的截图

data/customized.png

依赖关系

~44–78MB
~1M SLoC