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]]
|
[[package]]
|
||||||
name = "maze-ascension"
|
name = "maze-ascension"
|
||||||
version = "1.0.2"
|
version = "1.0.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bevy",
|
"bevy",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "maze-ascension"
|
name = "maze-ascension"
|
||||||
authors = ["Kristofers Solo <dev@kristofers.xyz>"]
|
authors = ["Kristofers Solo <dev@kristofers.xyz>"]
|
||||||
version = "1.0.2"
|
version = "1.0.3"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
2
justfile
2
justfile
@ -12,7 +12,7 @@ native-release:
|
|||||||
|
|
||||||
# Run web dev
|
# Run web dev
|
||||||
web-dev:
|
web-dev:
|
||||||
RUST_BACKTRACE=full trunk serve
|
RUSTC_WRAPPER=sccache RUST_BACKTRACE=full trunk serve
|
||||||
|
|
||||||
# Run web release
|
# Run web release
|
||||||
web-release:
|
web-release:
|
||||||
|
|||||||
@ -7,7 +7,7 @@ use crate::{
|
|||||||
hint::assets::HintAssets,
|
hint::assets::HintAssets,
|
||||||
player::assets::PlayerAssets,
|
player::assets::PlayerAssets,
|
||||||
screens::Screen,
|
screens::Screen,
|
||||||
theme::{interaction::InteractionAssets, prelude::*},
|
theme::{assets::InteractionAssets, prelude::*},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn plugin(app: &mut App) {
|
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.
|
// Unused utilities may trigger this lints undesirably.
|
||||||
|
|
||||||
|
pub mod assets;
|
||||||
mod colorscheme;
|
mod colorscheme;
|
||||||
pub mod interaction;
|
pub mod components;
|
||||||
|
pub mod events;
|
||||||
pub mod palette;
|
pub mod palette;
|
||||||
|
mod systems;
|
||||||
mod widgets;
|
mod widgets;
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use super::{
|
pub use super::{
|
||||||
colorscheme::{ColorScheme, ColorSchemeWrapper},
|
colorscheme::{ColorScheme, ColorSchemeWrapper},
|
||||||
interaction::{InteractionPalette, OnPress},
|
components::{InteractionPalette, UrlLink},
|
||||||
|
events::OnPress,
|
||||||
palette as ui_palette,
|
palette as ui_palette,
|
||||||
widgets::{Containers as _, Widgets as _},
|
widgets::{Containers as _, Widgets as _},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use assets::InteractionAssets;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
use prelude::InteractionPalette;
|
||||||
|
|
||||||
|
use crate::asset_tracking::LoadResource;
|
||||||
|
|
||||||
pub(super) fn plugin(app: &mut App) {
|
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.
|
//! 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 rose_pine::RosePineDawn;
|
||||||
|
|
||||||
use super::prelude::ColorScheme;
|
use super::prelude::{ColorScheme, InteractionPalette};
|
||||||
use crate::theme::{interaction::InteractionPalette, palette::*};
|
use crate::theme::palette::*;
|
||||||
|
|
||||||
/// An extension trait for spawning UI widgets.
|
/// An extension trait for spawning UI widgets.
|
||||||
pub trait Widgets {
|
pub trait Widgets {
|
||||||
@ -35,6 +38,7 @@ impl<T: SpawnUi> Widgets for T {
|
|||||||
border: UiRect::all(Px(4.)),
|
border: UiRect::all(Px(4.)),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
|
CursorIcon::System(SystemCursorIcon::Pointer),
|
||||||
BorderRadius::all(Px(8.)),
|
BorderRadius::all(Px(8.)),
|
||||||
BorderColor(RosePineDawn::Text.to_color()),
|
BorderColor(RosePineDawn::Text.to_color()),
|
||||||
InteractionPalette {
|
InteractionPalette {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user