mirror of
https://github.com/kristoferssolo/maze-ascension.git
synced 2025-10-21 19:20:34 +00:00
Merge pull request #20 from kristoferssolo/fix/floor-transitions
This commit is contained in:
commit
e096216806
13
justfile
13
justfile
@ -8,7 +8,7 @@ native-dev:
|
||||
|
||||
# Run native release
|
||||
native-release:
|
||||
cargo run --release --no-default-features
|
||||
RUSTC_WRAPPER=sccache cargo run --release --no-default-features
|
||||
|
||||
# Run web dev
|
||||
web-dev:
|
||||
@ -16,8 +16,17 @@ web-dev:
|
||||
|
||||
# Run web release
|
||||
web-release:
|
||||
trunk serve --release --no-default-features
|
||||
RUSTC_WRAPPER=sccache trunk serve --release --no-default-features
|
||||
|
||||
# Run tests
|
||||
test:
|
||||
RUSTC_WRAPPER=sccache RUST_BACKTRACE=full cargo nextest run --no-default-features --all-targets
|
||||
|
||||
# Run CI localy
|
||||
ci:
|
||||
#!/bin/bash
|
||||
set -e
|
||||
cargo fmt --all -- --check
|
||||
cargo clippy --workspace --all-targets --all-features -- --deny warnings
|
||||
cargo doc --workspace --all-features --document-private-items --no-deps
|
||||
cargo test --workspace --no-default-features
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
pub const MOVEMENT_THRESHOLD: f32 = 0.01;
|
||||
pub const WALL_OVERLAP_MODIFIER: f32 = 1.25;
|
||||
pub const FLOOR_Y_OFFSET: u8 = 100;
|
||||
pub const FLOOR_Y_OFFSET: u8 = 200;
|
||||
pub const MOVEMENT_COOLDOWN: f32 = 1.0; // one second cooldown
|
||||
|
||||
@ -6,10 +6,12 @@ pub struct Floor(pub u8);
|
||||
|
||||
#[derive(Debug, Reflect, Component)]
|
||||
#[reflect(Component)]
|
||||
#[require(Floor)]
|
||||
pub struct CurrentFloor;
|
||||
|
||||
#[derive(Debug, Reflect, Component, Deref, DerefMut)]
|
||||
#[reflect(Component)]
|
||||
#[require(Floor)]
|
||||
pub struct FloorYTarget(pub f32);
|
||||
|
||||
impl Default for Floor {
|
||||
|
||||
@ -15,8 +15,9 @@ pub(super) fn plugin(app: &mut App) {
|
||||
spawn_floor,
|
||||
despawn_floor,
|
||||
handle_floor_transition_events,
|
||||
move_floors.after(handle_floor_transition_events),
|
||||
move_floors,
|
||||
)
|
||||
.chain()
|
||||
.run_if(resource_exists::<MazePluginLoaded>),
|
||||
);
|
||||
}
|
||||
|
||||
@ -12,10 +12,7 @@ use bevy::prelude::*;
|
||||
|
||||
pub fn move_floors(
|
||||
mut commands: Commands,
|
||||
mut maze_query: Query<
|
||||
(Entity, &mut Transform, &FloorYTarget),
|
||||
(With<HexMaze>, With<FloorYTarget>),
|
||||
>,
|
||||
mut maze_query: Query<(Entity, &mut Transform, &FloorYTarget), With<FloorYTarget>>,
|
||||
player_query: Query<&MovementSpeed, With<Player>>,
|
||||
time: Res<Time>,
|
||||
) {
|
||||
@ -48,7 +45,6 @@ pub fn handle_floor_transition_events(
|
||||
}
|
||||
|
||||
for event in event_reader.read() {
|
||||
dbg!(&event);
|
||||
let Some((current_entity, current_floor)) = current_query.get_single().ok() else {
|
||||
continue;
|
||||
};
|
||||
@ -68,7 +64,6 @@ pub fn handle_floor_transition_events(
|
||||
|
||||
for (entity, transforms, _, movement_state) in maze_query.iter_mut() {
|
||||
let target_y = (FLOOR_Y_OFFSET as f32).mul_add(direction, transforms.translation.y);
|
||||
dbg!(movement_state, target_y);
|
||||
if movement_state.is_none() {
|
||||
commands.entity(entity).insert(FloorYTarget(target_y));
|
||||
}
|
||||
@ -77,7 +72,6 @@ pub fn handle_floor_transition_events(
|
||||
update_current_next_floor(&mut commands, current_entity, target_entity);
|
||||
break;
|
||||
}
|
||||
event_reader.clear();
|
||||
}
|
||||
|
||||
fn update_current_next_floor(commands: &mut Commands, current: Entity, target: Entity) {
|
||||
|
||||
@ -4,17 +4,17 @@ use crate::{
|
||||
events::TransitionFloor,
|
||||
resources::HighestFloor,
|
||||
},
|
||||
maze::events::SpawnMaze,
|
||||
maze::{components::MazeConfig, events::SpawnMaze},
|
||||
};
|
||||
use bevy::prelude::*;
|
||||
|
||||
pub(super) fn spawn_floor(
|
||||
mut commands: Commands,
|
||||
query: Query<&mut Floor, (With<CurrentFloor>, Without<FloorYTarget>)>,
|
||||
query: Query<(&mut Floor, &MazeConfig), (With<CurrentFloor>, Without<FloorYTarget>)>,
|
||||
mut event_reader: EventReader<TransitionFloor>,
|
||||
mut highest_floor: ResMut<HighestFloor>,
|
||||
) {
|
||||
let Ok(current_floor) = query.get_single() else {
|
||||
let Ok((current_floor, config)) = query.get_single() else {
|
||||
return;
|
||||
};
|
||||
|
||||
@ -24,14 +24,17 @@ pub(super) fn spawn_floor(
|
||||
return;
|
||||
}
|
||||
|
||||
let next_floor = event.next_floor_num(current_floor);
|
||||
highest_floor.0 = highest_floor.0.max(next_floor);
|
||||
let target_floor = event.next_floor_num(current_floor);
|
||||
highest_floor.0 = highest_floor.0.max(target_floor);
|
||||
|
||||
info!("Creating level for floor {}", next_floor);
|
||||
info!("Creating level for floor {}", target_floor);
|
||||
|
||||
commands.trigger(SpawnMaze {
|
||||
floor: next_floor,
|
||||
..default()
|
||||
floor: target_floor,
|
||||
config: MazeConfig {
|
||||
start_pos: config.end_pos,
|
||||
..default()
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
11
src/lib.rs
11
src/lib.rs
@ -14,6 +14,7 @@ use bevy::{
|
||||
audio::{AudioPlugin, Volume},
|
||||
prelude::*,
|
||||
};
|
||||
use theme::{palette::rose_pine, prelude::ColorScheme};
|
||||
|
||||
pub struct AppPlugin;
|
||||
|
||||
@ -26,7 +27,7 @@ impl Plugin for AppPlugin {
|
||||
);
|
||||
|
||||
// Spawn the main camera.
|
||||
app.add_systems(Startup, spawn_camera);
|
||||
app.add_systems(Startup, (spawn_camera, load_background));
|
||||
|
||||
// Add Bevy plugins.
|
||||
app.add_plugins(
|
||||
@ -100,3 +101,11 @@ fn spawn_camera(mut commands: Commands) {
|
||||
IsDefaultUiCamera,
|
||||
));
|
||||
}
|
||||
|
||||
fn load_background(mut commands: Commands) {
|
||||
#[cfg(feature = "dev")]
|
||||
let colorcheme = rose_pine::RosePine::Base;
|
||||
#[cfg(not(feature = "dev"))]
|
||||
let colorcheme = rose_pine::RosePineDawn::Base;
|
||||
commands.insert_resource(ClearColor(colorcheme.to_color()));
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use super::resources::GlobalMazeConfig;
|
||||
use crate::{
|
||||
constants::WALL_OVERLAP_MODIFIER,
|
||||
theme::{palette::rose_pine::RosePine, prelude::ColorScheme},
|
||||
theme::{palette::rose_pine::RosePineDawn, prelude::ColorScheme},
|
||||
};
|
||||
use bevy::{prelude::*, utils::HashMap};
|
||||
use std::f32::consts::FRAC_PI_2;
|
||||
@ -15,7 +15,7 @@ pub struct MazeAssets {
|
||||
pub wall_mesh: Handle<Mesh>,
|
||||
pub hex_material: Handle<StandardMaterial>,
|
||||
pub wall_material: Handle<StandardMaterial>,
|
||||
pub custom_materials: HashMap<RosePine, Handle<StandardMaterial>>,
|
||||
pub custom_materials: HashMap<RosePineDawn, Handle<StandardMaterial>>,
|
||||
}
|
||||
|
||||
impl MazeAssets {
|
||||
@ -24,7 +24,7 @@ impl MazeAssets {
|
||||
materials: &mut ResMut<Assets<StandardMaterial>>,
|
||||
global_config: &GlobalMazeConfig,
|
||||
) -> Self {
|
||||
let custom_materials = RosePine::iter()
|
||||
let custom_materials = RosePineDawn::iter()
|
||||
.map(|color| (color, materials.add(color.to_standart_material())))
|
||||
.collect();
|
||||
Self {
|
||||
|
||||
@ -35,18 +35,17 @@ impl MazeConfig {
|
||||
orientation: HexOrientation,
|
||||
seed: Option<u64>,
|
||||
global_conig: &GlobalMazeConfig,
|
||||
start_pos: Option<Hex>,
|
||||
) -> Self {
|
||||
let seed = seed.unwrap_or_else(|| thread_rng().gen());
|
||||
let mut rng = StdRng::seed_from_u64(seed);
|
||||
|
||||
// Generate start and end positions ensuring they're different
|
||||
let mut start_pos;
|
||||
let start_pos = start_pos.unwrap_or_else(|| generate_pos(radius, &mut rng));
|
||||
|
||||
// Generate end position ensuring start and end are different
|
||||
let mut end_pos;
|
||||
|
||||
loop {
|
||||
start_pos = generate_pos(radius, &mut rng);
|
||||
end_pos = generate_pos(radius, &mut rng);
|
||||
|
||||
if start_pos != end_pos {
|
||||
break;
|
||||
}
|
||||
@ -79,7 +78,13 @@ impl MazeConfig {
|
||||
|
||||
impl Default for MazeConfig {
|
||||
fn default() -> Self {
|
||||
Self::new(8, HexOrientation::Flat, None, &GlobalMazeConfig::default())
|
||||
Self::new(
|
||||
8,
|
||||
HexOrientation::Flat,
|
||||
None,
|
||||
&GlobalMazeConfig::default(),
|
||||
None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,7 +131,7 @@ mod tests {
|
||||
let seed = Some(12345);
|
||||
let global_config = GlobalMazeConfig::default();
|
||||
|
||||
let config = MazeConfig::new(radius, orientation, seed, &global_config);
|
||||
let config = MazeConfig::new(radius, orientation, seed, &global_config, None);
|
||||
|
||||
assert_eq!(config.radius, radius);
|
||||
assert_eq!(config.seed, 12345);
|
||||
@ -173,8 +178,13 @@ mod tests {
|
||||
];
|
||||
|
||||
for seed in test_seeds {
|
||||
let config =
|
||||
MazeConfig::new(8, HexOrientation::Flat, seed, &GlobalMazeConfig::default());
|
||||
let config = MazeConfig::new(
|
||||
8,
|
||||
HexOrientation::Flat,
|
||||
seed,
|
||||
&GlobalMazeConfig::default(),
|
||||
None,
|
||||
);
|
||||
|
||||
assert_eq!(config.radius, 8);
|
||||
assert_eq!(config.layout.orientation, HexOrientation::Flat);
|
||||
@ -226,12 +236,14 @@ mod tests {
|
||||
HexOrientation::Flat,
|
||||
Some(1),
|
||||
&GlobalMazeConfig::default(),
|
||||
None,
|
||||
);
|
||||
let config2 = MazeConfig::new(
|
||||
8,
|
||||
HexOrientation::Flat,
|
||||
Some(2),
|
||||
&GlobalMazeConfig::default(),
|
||||
None,
|
||||
);
|
||||
|
||||
assert_ne!(config1.start_pos, config2.start_pos);
|
||||
@ -241,8 +253,20 @@ mod tests {
|
||||
#[test]
|
||||
fn same_seed_same_positions() {
|
||||
let seed = Some(12345);
|
||||
let config1 = MazeConfig::new(8, HexOrientation::Flat, seed, &GlobalMazeConfig::default());
|
||||
let config2 = MazeConfig::new(8, HexOrientation::Flat, seed, &GlobalMazeConfig::default());
|
||||
let config1 = MazeConfig::new(
|
||||
8,
|
||||
HexOrientation::Flat,
|
||||
seed,
|
||||
&GlobalMazeConfig::default(),
|
||||
None,
|
||||
);
|
||||
let config2 = MazeConfig::new(
|
||||
8,
|
||||
HexOrientation::Flat,
|
||||
seed,
|
||||
&GlobalMazeConfig::default(),
|
||||
None,
|
||||
);
|
||||
|
||||
assert_eq!(config1.start_pos, config2.start_pos);
|
||||
assert_eq!(config1.end_pos, config2.end_pos);
|
||||
@ -255,6 +279,7 @@ mod tests {
|
||||
HexOrientation::Pointy,
|
||||
None,
|
||||
&GlobalMazeConfig::default(),
|
||||
None,
|
||||
);
|
||||
assert_eq!(config.layout.orientation, HexOrientation::Pointy);
|
||||
}
|
||||
@ -269,6 +294,7 @@ mod tests {
|
||||
hex_size: 0.0,
|
||||
..default()
|
||||
},
|
||||
None,
|
||||
);
|
||||
assert_eq!(config.layout.hex_size.x, 0.0);
|
||||
assert_eq!(config.layout.hex_size.y, 0.0);
|
||||
|
||||
@ -8,8 +8,9 @@ use crate::{
|
||||
events::SpawnMaze,
|
||||
resources::GlobalMazeConfig,
|
||||
},
|
||||
theme::palette::rose_pine::RosePine,
|
||||
theme::palette::rose_pine::RosePineDawn,
|
||||
};
|
||||
|
||||
use bevy::prelude::*;
|
||||
use hexlab::prelude::{Tile as HexTile, *};
|
||||
use hexx::HexOrientation;
|
||||
@ -43,8 +44,6 @@ pub(super) fn spawn_maze(
|
||||
_ => FLOOR_Y_OFFSET,
|
||||
} as f32;
|
||||
|
||||
// (floor - 1) * FLOOR_Y_OFFSET
|
||||
|
||||
let entity = commands
|
||||
.spawn((
|
||||
Name::new(format!("Floor {}", floor)),
|
||||
@ -100,12 +99,12 @@ pub(super) fn spawn_single_hex_tile(
|
||||
let material = match tile.pos() {
|
||||
pos if pos == maze_config.start_pos => assets
|
||||
.custom_materials
|
||||
.get(&RosePine::Pine)
|
||||
.get(&RosePineDawn::Pine)
|
||||
.cloned()
|
||||
.unwrap_or_default(),
|
||||
pos if pos == maze_config.end_pos => assets
|
||||
.custom_materials
|
||||
.get(&RosePine::Love)
|
||||
.get(&RosePineDawn::Love)
|
||||
.cloned()
|
||||
.unwrap_or_default(),
|
||||
_ => assets.hex_material.clone(),
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::theme::{palette::rose_pine::RosePine, prelude::ColorScheme};
|
||||
use crate::theme::{palette::rose_pine::RosePineDawn, prelude::ColorScheme};
|
||||
|
||||
pub(super) fn generate_pill_mesh(radius: f32, half_length: f32) -> Mesh {
|
||||
Mesh::from(Capsule3d {
|
||||
@ -10,7 +10,7 @@ pub(super) fn generate_pill_mesh(radius: f32, half_length: f32) -> Mesh {
|
||||
}
|
||||
|
||||
pub(super) fn blue_material() -> StandardMaterial {
|
||||
let color = RosePine::Pine;
|
||||
let color = RosePineDawn::Pine;
|
||||
StandardMaterial {
|
||||
base_color: color.to_color(),
|
||||
emissive: color.to_linear_rgba() * 3.,
|
||||
|
||||
@ -3,7 +3,7 @@ use hexx::Hex;
|
||||
|
||||
#[derive(Debug, Reflect, Component)]
|
||||
#[reflect(Component)]
|
||||
#[require(CurrentPosition, MovementSpeed, MovementTarget)]
|
||||
#[require(CurrentPosition, MovementSpeed, MovementTarget, TranstitionState)]
|
||||
pub struct Player;
|
||||
|
||||
#[derive(Debug, Reflect, Component, Deref, DerefMut, Default)]
|
||||
@ -14,6 +14,13 @@ pub struct CurrentPosition(pub Hex);
|
||||
#[reflect(Component)]
|
||||
pub struct MovementSpeed(pub f32);
|
||||
|
||||
#[derive(Debug, Reflect, Component, Default)]
|
||||
#[reflect(Component)]
|
||||
pub struct TranstitionState {
|
||||
pub just_transitioned: bool,
|
||||
pub last_position: Hex,
|
||||
}
|
||||
|
||||
impl Default for MovementSpeed {
|
||||
fn default() -> Self {
|
||||
Self(100.)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
floor::components::CurrentFloor,
|
||||
floor::components::{CurrentFloor, FloorYTarget},
|
||||
maze::components::MazeConfig,
|
||||
player::components::{CurrentPosition, MovementTarget, Player},
|
||||
};
|
||||
@ -10,12 +10,16 @@ use hexx::{EdgeDirection, HexOrientation};
|
||||
pub(super) fn player_input(
|
||||
input: Res<ButtonInput<KeyCode>>,
|
||||
mut player_query: Query<(&mut MovementTarget, &CurrentPosition), With<Player>>,
|
||||
maze_query: Query<(&Maze, &MazeConfig), With<CurrentFloor>>,
|
||||
maze_query: Query<(&Maze, &MazeConfig, Has<FloorYTarget>), With<CurrentFloor>>,
|
||||
) {
|
||||
let Ok((maze, maze_config)) = maze_query.get_single() else {
|
||||
let Ok((maze, maze_config, has_y_target)) = maze_query.get_single() else {
|
||||
return;
|
||||
};
|
||||
|
||||
if has_y_target {
|
||||
return;
|
||||
}
|
||||
|
||||
for (mut target_pos, current_pos) in player_query.iter_mut() {
|
||||
if target_pos.is_some() {
|
||||
continue;
|
||||
|
||||
@ -6,11 +6,11 @@ use crate::{
|
||||
events::TransitionFloor,
|
||||
},
|
||||
maze::components::MazeConfig,
|
||||
player::components::{CurrentPosition, Player},
|
||||
player::components::{CurrentPosition, Player, TranstitionState},
|
||||
};
|
||||
|
||||
pub fn handle_floor_transition(
|
||||
player_query: Query<&CurrentPosition, With<Player>>,
|
||||
mut player_query: Query<(&CurrentPosition, &mut TranstitionState), With<Player>>,
|
||||
maze_query: Query<(&MazeConfig, &Floor), With<CurrentFloor>>,
|
||||
mut event_writer: EventWriter<TransitionFloor>,
|
||||
) {
|
||||
@ -19,17 +19,30 @@ pub fn handle_floor_transition(
|
||||
return;
|
||||
};
|
||||
|
||||
for current_hex in player_query.iter() {
|
||||
for (current_hex, mut transition_state) in player_query.iter_mut() {
|
||||
// Reset transition state if moved to a new position
|
||||
if current_hex.0 != transition_state.last_position {
|
||||
transition_state.just_transitioned = false;
|
||||
}
|
||||
transition_state.last_position = current_hex.0;
|
||||
|
||||
// Skip if transition just happened
|
||||
if transition_state.just_transitioned {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for ascending
|
||||
if current_hex.0 == config.end_pos {
|
||||
info!("Ascending");
|
||||
event_writer.send(TransitionFloor::Ascend);
|
||||
transition_state.just_transitioned = true;
|
||||
}
|
||||
|
||||
// Check for descending
|
||||
if current_hex.0 == config.start_pos && floor.0 != 1 {
|
||||
info!("Descending");
|
||||
event_writer.send(TransitionFloor::Descend);
|
||||
transition_state.just_transitioned = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,45 +1,184 @@
|
||||
use super::rgb_u8;
|
||||
use crate::theme::prelude::ColorScheme;
|
||||
use crate::{
|
||||
create_color_scheme,
|
||||
theme::{colorscheme::ColorScheme, palette::rgb_u8},
|
||||
};
|
||||
use bevy::prelude::*;
|
||||
use strum::EnumIter;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter)]
|
||||
pub enum RosePine {
|
||||
Base,
|
||||
Surface,
|
||||
Overlay,
|
||||
Muted,
|
||||
Subtle,
|
||||
Text,
|
||||
Love,
|
||||
Gold,
|
||||
Rose,
|
||||
Pine,
|
||||
Foam,
|
||||
Iris,
|
||||
HighlightLow,
|
||||
HighlightMed,
|
||||
HighlightHigh,
|
||||
}
|
||||
|
||||
impl ColorScheme for RosePine {
|
||||
fn to_color(&self) -> Color {
|
||||
match self {
|
||||
Self::Base => rgb_u8(25, 23, 36),
|
||||
Self::Surface => rgb_u8(31, 29, 46),
|
||||
Self::Overlay => rgb_u8(38, 35, 58),
|
||||
Self::Muted => rgb_u8(110, 106, 134),
|
||||
Self::Subtle => rgb_u8(144, 140, 170),
|
||||
Self::Text => rgb_u8(224, 222, 244),
|
||||
Self::Love => rgb_u8(235, 111, 146),
|
||||
Self::Gold => rgb_u8(246, 193, 119),
|
||||
Self::Rose => rgb_u8(235, 188, 186),
|
||||
Self::Pine => rgb_u8(49, 116, 143),
|
||||
Self::Foam => rgb_u8(156, 207, 216),
|
||||
Self::Iris => rgb_u8(196, 167, 231),
|
||||
Self::HighlightLow => rgb_u8(33, 32, 46),
|
||||
Self::HighlightMed => rgb_u8(64, 61, 82),
|
||||
Self::HighlightHigh => rgb_u8(82, 79, 103),
|
||||
}
|
||||
create_color_scheme!(
|
||||
pub RosePine, {
|
||||
Base: "#191724",
|
||||
Surface: "#1f1d2e",
|
||||
Overlay: "#26233a",
|
||||
Muted: "#6e6a86",
|
||||
Subtle: "#908caa",
|
||||
Text: "#e0def4",
|
||||
Love: "#eb6f92",
|
||||
Gold: "#f6c177",
|
||||
Rose: "#ebbcba",
|
||||
Pine: "#31748f",
|
||||
Foam: "#9ccfd8",
|
||||
Iris: "#c4a7e7",
|
||||
HighlightLow: "#21202e",
|
||||
HighlightMed: "#403d52",
|
||||
HighlightHigh: "#524f67"
|
||||
}
|
||||
);
|
||||
|
||||
create_color_scheme!(
|
||||
pub RosePineMoon, {
|
||||
Base: "#232136",
|
||||
Surface: "#2a273f",
|
||||
Overlay: "#393552",
|
||||
Muted: "#6e6a86",
|
||||
Subtle: "#908caa",
|
||||
Text: "#e0def4",
|
||||
Love: "#eb6f92",
|
||||
Gold: "#f6c177",
|
||||
Rose: "#ea9a97",
|
||||
Pine: "#3e8fb0",
|
||||
Foam: "#9ccfd8",
|
||||
Iris: "#c4a7e7",
|
||||
HighlightLow: "#2a283e",
|
||||
HighlightMed: "#44415a",
|
||||
HighlightHigh: "#56526e"
|
||||
}
|
||||
);
|
||||
|
||||
create_color_scheme!(
|
||||
pub RosePineDawn, {
|
||||
Base: "#faf4ed",
|
||||
Surface: "#fffaf3",
|
||||
Overlay: "#f2e9e1",
|
||||
Muted: "#9893a5",
|
||||
Subtle: "#797593",
|
||||
Text: "#575279",
|
||||
Love: "#b4637a",
|
||||
Gold: "#ea9d34",
|
||||
Rose: "#d7827e",
|
||||
Pine: "#286983",
|
||||
Foam: "#56949f",
|
||||
Iris: "#907aa9",
|
||||
HighlightLow: "#f4ede8",
|
||||
HighlightMed: "#dfdad9",
|
||||
HighlightHigh: "#cecacd"
|
||||
}
|
||||
);
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! create_color_scheme {
|
||||
($(#[$meta:meta])* $vis:vis $name:ident, {
|
||||
Base: $base:expr,
|
||||
Surface: $surface:expr,
|
||||
Overlay: $overlay:expr,
|
||||
Muted: $muted:expr,
|
||||
Subtle: $subtle:expr,
|
||||
Text: $text:expr,
|
||||
Love: $love:expr,
|
||||
Gold: $gold:expr,
|
||||
Rose: $rose:expr,
|
||||
Pine: $pine:expr,
|
||||
Foam: $foam:expr,
|
||||
Iris: $iris:expr,
|
||||
HighlightLow: $hl_low:expr,
|
||||
HighlightMed: $hl_med:expr,
|
||||
HighlightHigh: $hl_high:expr
|
||||
}) => {
|
||||
$(#[$meta])*
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumIter)]
|
||||
$vis enum $name {
|
||||
Base,
|
||||
Surface,
|
||||
Overlay,
|
||||
Muted,
|
||||
Subtle,
|
||||
Text,
|
||||
Love,
|
||||
Gold,
|
||||
Rose,
|
||||
Pine,
|
||||
Foam,
|
||||
Iris,
|
||||
HighlightLow,
|
||||
HighlightMed,
|
||||
HighlightHigh,
|
||||
}
|
||||
|
||||
impl $name {
|
||||
fn hex_to_rgb(hex: &str) -> (u8, u8, u8) {
|
||||
let hex = hex.strip_prefix('#').unwrap_or(hex);
|
||||
let r = u8::from_str_radix(&hex[0..2], 16).unwrap_or(0);
|
||||
let g = u8::from_str_radix(&hex[2..4], 16).unwrap_or(0);
|
||||
let b = u8::from_str_radix(&hex[4..6], 16).unwrap_or(0);
|
||||
(r, g, b)
|
||||
}
|
||||
}
|
||||
|
||||
impl ColorScheme for $name {
|
||||
fn to_color(&self) -> Color {
|
||||
match self {
|
||||
Self::Base => {
|
||||
let (r, g, b) = Self::hex_to_rgb($base);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
Self::Surface => {
|
||||
let (r, g, b) = Self::hex_to_rgb($surface);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
Self::Overlay => {
|
||||
let (r, g, b) = Self::hex_to_rgb($overlay);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
Self::Muted => {
|
||||
let (r, g, b) = Self::hex_to_rgb($muted);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
Self::Subtle => {
|
||||
let (r, g, b) = Self::hex_to_rgb($subtle);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
Self::Text => {
|
||||
let (r, g, b) = Self::hex_to_rgb($text);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
Self::Love => {
|
||||
let (r, g, b) = Self::hex_to_rgb($love);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
Self::Gold => {
|
||||
let (r, g, b) = Self::hex_to_rgb($gold);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
Self::Rose => {
|
||||
let (r, g, b) = Self::hex_to_rgb($rose);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
Self::Pine => {
|
||||
let (r, g, b) = Self::hex_to_rgb($pine);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
Self::Foam => {
|
||||
let (r, g, b) = Self::hex_to_rgb($foam);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
Self::Iris => {
|
||||
let (r, g, b) = Self::hex_to_rgb($iris);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
Self::HighlightLow => {
|
||||
let (r, g, b) = Self::hex_to_rgb($hl_low);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
Self::HighlightMed => {
|
||||
let (r, g, b) = Self::hex_to_rgb($hl_med);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
Self::HighlightHigh => {
|
||||
let (r, g, b) = Self::hex_to_rgb($hl_high);
|
||||
rgb_u8(r, g, b)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user