#![allow(clippy::module_name_repetitions)]
use bevy::prelude::*;
pub struct ButtonPlugin;
impl Plugin for ButtonPlugin {
fn build(&self, app: &mut App) {
app.add_event::<ButtonPressEvent>()
.add_systems(Update, (setup, interact));
}
}
#[derive(Bundle)]
pub struct FormButtonBundle {
form_button: FormButton,
button: ButtonBundle,
button_role: ButtonRole,
}
impl FormButtonBundle {
pub fn new(text: impl Into<String>) -> Self {
FormButtonBundle {
form_button: FormButton {
text: text.into(),
form: None,
},
button: ButtonBundle::default(),
button_role: ButtonRole::default(),
}
}
#[must_use]
pub fn with_role(mut self, role: ButtonRole) -> Self {
self.button_role = role;
self
}
#[must_use]
pub fn with_form(mut self, form: Entity) -> Self {
self.form_button.form = Some(form);
self
}
}
#[derive(Component, Clone, Default, Debug)]
pub struct FormButton {
pub text: String,
pub form: Option<Entity>,
}
#[derive(Component, Clone, PartialEq, Eq, Hash, Debug)]
pub enum FormInteraction {
None,
Hovered,
Pressed,
}
#[derive(Event, Debug)]
pub struct ButtonPressEvent {
pub entity: Entity,
pub button: FormButton,
pub role: ButtonRole,
}
impl From<&Interaction> for FormInteraction {
fn from(interaction: &Interaction) -> Self {
match interaction {
Interaction::None => FormInteraction::None,
Interaction::Hovered => FormInteraction::Hovered,
Interaction::Pressed => FormInteraction::Pressed,
}
}
}
#[derive(Component, Clone, PartialEq, Eq, Hash, Default, Debug)]
#[non_exhaustive]
pub enum ButtonRole {
#[default]
Submit,
Cancel,
Apply,
Custom(String),
}
impl From<&str> for ButtonRole {
fn from(s: &str) -> Self {
match s {
"submit" => ButtonRole::Submit,
"cancel" => ButtonRole::Cancel,
"apply" => ButtonRole::Apply,
_ => ButtonRole::Custom(s.to_string()),
}
}
}
impl From<String> for ButtonRole {
fn from(s: String) -> Self {
ButtonRole::from(s.as_str())
}
}
fn setup(mut commands: Commands, mut q_button: Query<(Entity, &FormButton), Added<FormButton>>) {
for (entity, button) in &mut q_button {
let text = commands
.spawn(TextBundle::from_section(
button.text.clone(),
TextStyle::default(),
))
.id();
commands
.entity(entity)
.add_child(text);
}
}
#[allow(clippy::needless_pass_by_value)]
fn interact(
q_button: Query<(Entity, &FormButton, &ButtonRole, &Interaction), Changed<Interaction>>,
mut ev_button: EventWriter<ButtonPressEvent>,
) {
for (entity, button, role, _) in q_button
.iter()
.filter(|(_, _, _, interaction)| **interaction == Interaction::Pressed)
{
ev_button.send(ButtonPressEvent {
entity,
button: button.clone(),
role: role.clone(),
});
}
}