mirror of
https://github.com/kristoferssolo/maze-ascension.git
synced 2025-10-21 19:20:34 +00:00
refactor(themes): separate into files
This commit is contained in:
parent
69eacd42d5
commit
0f4899319d
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -3129,7 +3129,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "maze-ascension"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bevy",
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "maze-ascension"
|
||||
authors = ["Kristofers Solo <dev@kristofers.xyz>"]
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
2
justfile
2
justfile
@ -12,7 +12,7 @@ native-release:
|
||||
|
||||
# Run web dev
|
||||
web-dev:
|
||||
RUST_BACKTRACE=full trunk serve
|
||||
RUSTC_WRAPPER=sccache RUST_BACKTRACE=full trunk serve
|
||||
|
||||
# Run web release
|
||||
web-release:
|
||||
|
||||
@ -7,7 +7,7 @@ use crate::{
|
||||
hint::assets::HintAssets,
|
||||
player::assets::PlayerAssets,
|
||||
screens::Screen,
|
||||
theme::{interaction::InteractionAssets, prelude::*},
|
||||
theme::{assets::InteractionAssets, prelude::*},
|
||||
};
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
|
||||
24
src/theme/assets.rs
Normal file
24
src/theme/assets.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
#[derive(Resource, Asset, Reflect, Clone)]
|
||||
pub struct InteractionAssets {
|
||||
#[dependency]
|
||||
pub(super) hover: Handle<AudioSource>,
|
||||
#[dependency]
|
||||
pub(super) press: Handle<AudioSource>,
|
||||
}
|
||||
|
||||
impl InteractionAssets {
|
||||
pub const PATH_BUTTON_HOVER: &'static str = "audio/sound_effects/button_hover.ogg";
|
||||
pub const PATH_BUTTON_PRESS: &'static str = "audio/sound_effects/button_press.ogg";
|
||||
}
|
||||
|
||||
impl FromWorld for InteractionAssets {
|
||||
fn from_world(world: &mut World) -> Self {
|
||||
let assets = world.resource::<AssetServer>();
|
||||
Self {
|
||||
hover: assets.load(Self::PATH_BUTTON_HOVER),
|
||||
press: assets.load(Self::PATH_BUTTON_PRESS),
|
||||
}
|
||||
}
|
||||
}
|
||||
16
src/theme/components.rs
Normal file
16
src/theme/components.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
/// Palette for widget interactions. Add this to an entity that supports
|
||||
/// [`Interaction`]s, such as a button, to change its [`BackgroundColor`] based
|
||||
/// on the current interaction state.
|
||||
#[derive(Component, Debug, Reflect)]
|
||||
#[reflect(Component)]
|
||||
pub struct InteractionPalette {
|
||||
pub none: Color,
|
||||
pub hovered: Color,
|
||||
pub pressed: Color,
|
||||
}
|
||||
|
||||
#[derive(Debug, Reflect, Component)]
|
||||
#[reflect(Component)]
|
||||
pub struct UrlLink(pub String);
|
||||
6
src/theme/events.rs
Normal file
6
src/theme/events.rs
Normal file
@ -0,0 +1,6 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
/// Event triggered on a UI entity when the [`Interaction`] component on the same entity changes to
|
||||
/// [`Interaction::Pressed`]. Observe this event to detect e.g. button presses.
|
||||
#[derive(Event)]
|
||||
pub struct OnPress;
|
||||
@ -1,102 +0,0 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::{asset_tracking::LoadResource, audio::SoundEffect};
|
||||
|
||||
pub(super) fn plugin(app: &mut App) {
|
||||
app.register_type::<InteractionPalette>();
|
||||
app.load_resource::<InteractionAssets>();
|
||||
app.add_systems(
|
||||
Update,
|
||||
(
|
||||
trigger_on_press,
|
||||
apply_interaction_palette,
|
||||
trigger_interaction_sound_effect,
|
||||
)
|
||||
.run_if(resource_exists::<InteractionAssets>),
|
||||
);
|
||||
}
|
||||
|
||||
/// Palette for widget interactions. Add this to an entity that supports
|
||||
/// [`Interaction`]s, such as a button, to change its [`BackgroundColor`] based
|
||||
/// on the current interaction state.
|
||||
#[derive(Component, Debug, Reflect)]
|
||||
#[reflect(Component)]
|
||||
pub struct InteractionPalette {
|
||||
pub none: Color,
|
||||
pub hovered: Color,
|
||||
pub pressed: Color,
|
||||
}
|
||||
|
||||
/// Event triggered on a UI entity when the [`Interaction`] component on the same entity changes to
|
||||
/// [`Interaction::Pressed`]. Observe this event to detect e.g. button presses.
|
||||
#[derive(Event)]
|
||||
pub struct OnPress;
|
||||
|
||||
fn trigger_on_press(
|
||||
interaction_query: Query<(Entity, &Interaction), Changed<Interaction>>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (entity, interaction) in &interaction_query {
|
||||
if matches!(interaction, Interaction::Pressed) {
|
||||
commands.trigger_targets(OnPress, entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_interaction_palette(
|
||||
mut palette_query: Query<
|
||||
(&Interaction, &InteractionPalette, &mut BackgroundColor),
|
||||
Changed<Interaction>,
|
||||
>,
|
||||
) {
|
||||
for (interaction, palette, mut background) in &mut palette_query {
|
||||
*background = match interaction {
|
||||
Interaction::None => palette.none,
|
||||
Interaction::Hovered => palette.hovered,
|
||||
Interaction::Pressed => palette.pressed,
|
||||
}
|
||||
.into();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Resource, Asset, Reflect, Clone)]
|
||||
pub struct InteractionAssets {
|
||||
#[dependency]
|
||||
hover: Handle<AudioSource>,
|
||||
#[dependency]
|
||||
press: Handle<AudioSource>,
|
||||
}
|
||||
|
||||
impl InteractionAssets {
|
||||
pub const PATH_BUTTON_HOVER: &'static str = "audio/sound_effects/button_hover.ogg";
|
||||
pub const PATH_BUTTON_PRESS: &'static str = "audio/sound_effects/button_press.ogg";
|
||||
}
|
||||
|
||||
impl FromWorld for InteractionAssets {
|
||||
fn from_world(world: &mut World) -> Self {
|
||||
let assets = world.resource::<AssetServer>();
|
||||
Self {
|
||||
hover: assets.load(Self::PATH_BUTTON_HOVER),
|
||||
press: assets.load(Self::PATH_BUTTON_PRESS),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn trigger_interaction_sound_effect(
|
||||
interaction_query: Query<&Interaction, Changed<Interaction>>,
|
||||
interaction_assets: Res<InteractionAssets>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for interaction in &interaction_query {
|
||||
let source = match interaction {
|
||||
Interaction::Hovered => interaction_assets.hover.clone(),
|
||||
Interaction::Pressed => interaction_assets.press.clone(),
|
||||
_ => continue,
|
||||
};
|
||||
commands.spawn((
|
||||
AudioPlayer::<AudioSource>(source),
|
||||
PlaybackSettings::DESPAWN,
|
||||
SoundEffect,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -2,23 +2,33 @@
|
||||
|
||||
// Unused utilities may trigger this lints undesirably.
|
||||
|
||||
pub mod assets;
|
||||
mod colorscheme;
|
||||
pub mod interaction;
|
||||
pub mod components;
|
||||
pub mod events;
|
||||
pub mod palette;
|
||||
mod systems;
|
||||
mod widgets;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub mod prelude {
|
||||
pub use super::{
|
||||
colorscheme::{ColorScheme, ColorSchemeWrapper},
|
||||
interaction::{InteractionPalette, OnPress},
|
||||
components::{InteractionPalette, UrlLink},
|
||||
events::OnPress,
|
||||
palette as ui_palette,
|
||||
widgets::{Containers as _, Widgets as _},
|
||||
};
|
||||
}
|
||||
|
||||
use assets::InteractionAssets;
|
||||
use bevy::prelude::*;
|
||||
use prelude::InteractionPalette;
|
||||
|
||||
use crate::asset_tracking::LoadResource;
|
||||
|
||||
pub(super) fn plugin(app: &mut App) {
|
||||
app.add_plugins(interaction::plugin);
|
||||
app.register_type::<InteractionPalette>();
|
||||
app.load_resource::<InteractionAssets>();
|
||||
app.add_plugins(systems::plugin);
|
||||
}
|
||||
|
||||
52
src/theme/systems/button.rs
Normal file
52
src/theme/systems/button.rs
Normal file
@ -0,0 +1,52 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::{
|
||||
audio::SoundEffect,
|
||||
theme::{assets::InteractionAssets, events::OnPress, prelude::InteractionPalette},
|
||||
};
|
||||
|
||||
pub fn trigger_on_press(
|
||||
interaction_query: Query<(Entity, &Interaction), Changed<Interaction>>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (entity, interaction) in &interaction_query {
|
||||
if matches!(interaction, Interaction::Pressed) {
|
||||
commands.trigger_targets(OnPress, entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply_interaction_palette(
|
||||
mut palette_query: Query<
|
||||
(&Interaction, &InteractionPalette, &mut BackgroundColor),
|
||||
Changed<Interaction>,
|
||||
>,
|
||||
) {
|
||||
for (interaction, palette, mut background) in &mut palette_query {
|
||||
*background = match interaction {
|
||||
Interaction::None => palette.none,
|
||||
Interaction::Hovered => palette.hovered,
|
||||
Interaction::Pressed => palette.pressed,
|
||||
}
|
||||
.into();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trigger_interaction_sound_effect(
|
||||
interaction_query: Query<&Interaction, Changed<Interaction>>,
|
||||
interaction_assets: Res<InteractionAssets>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for interaction in &interaction_query {
|
||||
let source = match interaction {
|
||||
Interaction::Hovered => interaction_assets.hover.clone(),
|
||||
Interaction::Pressed => interaction_assets.press.clone(),
|
||||
_ => continue,
|
||||
};
|
||||
commands.spawn((
|
||||
AudioPlayer::<AudioSource>(source),
|
||||
PlaybackSettings::DESPAWN,
|
||||
SoundEffect,
|
||||
));
|
||||
}
|
||||
}
|
||||
18
src/theme/systems/mod.rs
Normal file
18
src/theme/systems/mod.rs
Normal file
@ -0,0 +1,18 @@
|
||||
mod button;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use button::{apply_interaction_palette, trigger_interaction_sound_effect, trigger_on_press};
|
||||
|
||||
use super::assets::InteractionAssets;
|
||||
|
||||
pub(super) fn plugin(app: &mut App) {
|
||||
app.add_systems(
|
||||
Update,
|
||||
(
|
||||
trigger_on_press,
|
||||
apply_interaction_palette,
|
||||
trigger_interaction_sound_effect,
|
||||
)
|
||||
.run_if(resource_exists::<InteractionAssets>),
|
||||
);
|
||||
}
|
||||
@ -1,10 +1,13 @@
|
||||
//! Helper traits for creating common widgets.
|
||||
|
||||
use bevy::{ecs::system::EntityCommands, prelude::*, ui::Val::*};
|
||||
use bevy::{
|
||||
ecs::system::EntityCommands, prelude::*, ui::Val::*, window::SystemCursorIcon,
|
||||
winit::cursor::CursorIcon,
|
||||
};
|
||||
use rose_pine::RosePineDawn;
|
||||
|
||||
use super::prelude::ColorScheme;
|
||||
use crate::theme::{interaction::InteractionPalette, palette::*};
|
||||
use super::prelude::{ColorScheme, InteractionPalette};
|
||||
use crate::theme::palette::*;
|
||||
|
||||
/// An extension trait for spawning UI widgets.
|
||||
pub trait Widgets {
|
||||
@ -35,6 +38,7 @@ impl<T: SpawnUi> Widgets for T {
|
||||
border: UiRect::all(Px(4.)),
|
||||
..default()
|
||||
},
|
||||
CursorIcon::System(SystemCursorIcon::Pointer),
|
||||
BorderRadius::all(Px(8.)),
|
||||
BorderColor(RosePineDawn::Text.to_color()),
|
||||
InteractionPalette {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user