From 6450b874ffa2e81fcb018b85dbcb33ca923cebdb Mon Sep 17 00:00:00 2001 From: Jan W Date: Thu, 16 Nov 2023 20:26:53 +0800 Subject: [PATCH 1/2] feat: update some settings --- src/configuration.rs | 34 ++++++++++ src/plugin.rs | 155 +++++++++++++++++++++++-------------------- 2 files changed, 116 insertions(+), 73 deletions(-) diff --git a/src/configuration.rs b/src/configuration.rs index 5ec5422..7f90877 100644 --- a/src/configuration.rs +++ b/src/configuration.rs @@ -23,6 +23,40 @@ pub struct BarSettings { pub phantom_data: PhantomData, } +impl BarSettings { + fn absolute_height(&self) -> f32 { + match self.height { + BarHeight::Relative(pct) => pct * self.width, + BarHeight::Static(height) => height, + } + } + + pub fn normalized_height(&self) -> f32 { + match self.orientation { + BarOrientation::Horizontal => self.absolute_height(), + BarOrientation::Vertical => self.width, + } + } + + pub fn normalized_width(&self) -> f32 { + match self.orientation { + BarOrientation::Horizontal => self.width, + BarOrientation::Vertical => self.absolute_height(), + } + } + + fn offset_axis(&self) -> Vec3 { + match self.orientation { + BarOrientation::Horizontal => Vec3::Y, + BarOrientation::Vertical => Vec3::X, + } + } + + pub fn normalized_offset(&self) -> Vec3 { + self.offset * self.offset_axis() + } +} + impl Default for BarSettings { fn default() -> Self { Self { diff --git a/src/plugin.rs b/src/plugin.rs index c16bf5e..dc2762a 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -4,7 +4,7 @@ use bevy::asset::load_internal_asset; use bevy::pbr::{NotShadowCaster, NotShadowReceiver}; use bevy::prelude::*; -use crate::configuration::{BarHeight, ForegroundColor, Percentage}; +use crate::configuration::{ForegroundColor, Percentage}; use crate::constants::BAR_SHADER_HANDLE; use crate::material::BarMaterial; use crate::mesh::MeshHandles; @@ -39,7 +39,10 @@ impl Plugin for HealthBarPlugin { .init_resource::>() .register_type::>() .add_systems(PostUpdate, reset_rotation) - .add_systems(Update, (spawn::, remove::, update::)); + .add_systems( + Update, + (spawn::, remove::, update::, update_settings::), + ); } } @@ -61,81 +64,59 @@ fn spawn( color_scheme: Res>, query: Query<(Entity, &T, &BarSettings), Added>, ) { - query.iter().for_each( - |( - entity, - percentage, - BarSettings { + query.iter().for_each(|(entity, percentage, settings)| { + let width = settings.normalized_width(); + let height = settings.normalized_height(); + + let mesh = mesh_handles.get(width, height).cloned().unwrap_or_else(|| { + mesh_handles.insert( width, height, - offset, - border, - orientation, - .. - }, - )| { - let height = match height { - BarHeight::Relative(pct) => pct * width, - BarHeight::Static(height) => *height, - }; - - let (width, height, vertical, offset_axis) = match orientation { - BarOrientation::Horizontal => (*width, height, false, Vec3::Y), - BarOrientation::Vertical => (height, *width, true, Vec3::X), - }; - - let mesh = mesh_handles.get(width, height).cloned().unwrap_or_else(|| { - mesh_handles.insert( - width, - height, - meshes.add(Mesh::from(shape::Quad::new(Vec2::new(width, height)))), - ) - }); - - let offset = *offset * offset_axis; - - let (high, moderate, low) = match color_scheme.foreground_color { - ForegroundColor::Static(color) => (color, color, color), - ForegroundColor::TriSpectrum { - high, - moderate, - low, - } => (high, moderate, low), - }; - - let material = materials.add(BarMaterial { - value_and_dimensions: (percentage.value(), width, height, border.width).into(), - background_color: color_scheme.background_color, - high_color: high, - moderate_color: moderate, - low_color: low, - vertical, - offset: offset.extend(0.), - border_color: border.color, - }); - - let health_bar = commands - .spawn(( - Name::new(format!("{}Bar", T::type_path())), - MaterialMeshBundle { - mesh, - material, - ..default() - }, - NotShadowCaster, - NotShadowReceiver, - )) - .id(); - - commands - .entity(entity) - .insert(WithBar(health_bar, PhantomData::)) - .add_child(health_bar); - }, - ); + meshes.add(Mesh::from(shape::Quad::new(Vec2::new(width, height)))), + ) + }); + + let (high, moderate, low) = match color_scheme.foreground_color { + ForegroundColor::Static(color) => (color, color, color), + ForegroundColor::TriSpectrum { + high, + moderate, + low, + } => (high, moderate, low), + }; + + let material = materials.add(BarMaterial { + value_and_dimensions: (percentage.value(), width, height, settings.border.width).into(), + background_color: color_scheme.background_color, + high_color: high, + moderate_color: moderate, + low_color: low, + vertical: settings.orientation == BarOrientation::Vertical, + offset: settings.normalized_offset().extend(0.), + border_color: settings.border.color, + }); + + let health_bar = commands + .spawn(( + Name::new(format!("{}Bar", T::type_path())), + MaterialMeshBundle { + mesh, + material, + ..default() + }, + NotShadowCaster, + NotShadowReceiver, + )) + .id(); + + commands + .entity(entity) + .insert(WithBar(health_bar, PhantomData::)) + .add_child(health_bar); + }); } -fn update( +fn update( mut materials: ResMut>, parent_query: Query<(&WithBar, &T), Changed>, bar_query: Query<&Handle>, @@ -149,6 +130,34 @@ fn update( }); } +#[allow(clippy::type_complexity)] +fn update_settings( + mut materials: ResMut>, + parent_query: Query<(&WithBar, &BarSettings), Changed>>, + bar_query: Query<&Handle>, +) { + parent_query.iter().for_each(|(bar, settings)| { + let Ok(material_handle) = bar_query.get(bar.get()) else { + return; + }; + + let material = materials.get_mut(material_handle).unwrap(); + let offset = settings.normalized_offset().extend(0.); + + if material.offset != offset { + material.offset = offset + } + + if material.border_color != settings.border.color { + material.border_color = settings.border.color + } + + if material.value_and_dimensions.w != settings.border.width { + material.value_and_dimensions.w = settings.border.width + } + }); +} + fn remove( mut commands: Commands, mut removals: RemovedComponents, From 18cadfef104aeaf8ce2cba171b4db7b5fb3937e4 Mon Sep 17 00:00:00 2001 From: Jan W Date: Thu, 16 Nov 2023 21:03:04 +0800 Subject: [PATCH 2/2] feat: update remaining properties on settings change --- src/plugin.rs | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/plugin.rs b/src/plugin.rs index dc2762a..e5f1ad5 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -132,29 +132,43 @@ fn update( #[allow(clippy::type_complexity)] fn update_settings( + mut commands: Commands, mut materials: ResMut>, + mut meshes: ResMut>, + mut mesh_handles: ResMut, parent_query: Query<(&WithBar, &BarSettings), Changed>>, - bar_query: Query<&Handle>, + bar_query: Query<(Entity, &Handle, &Handle)>, ) { parent_query.iter().for_each(|(bar, settings)| { - let Ok(material_handle) = bar_query.get(bar.get()) else { + let Ok((entity, material_handle, mesh_handle)) = bar_query.get(bar.get()) else { return; }; let material = materials.get_mut(material_handle).unwrap(); let offset = settings.normalized_offset().extend(0.); + let width = settings.normalized_width(); + let height = settings.normalized_height(); - if material.offset != offset { - material.offset = offset - } + let mesh_for_settings_dimensions = mesh_handles.get(width, height).cloned(); + let mesh_changed = mesh_for_settings_dimensions + .clone() + .map_or(true, |handle| handle != *mesh_handle); - if material.border_color != settings.border.color { - material.border_color = settings.border.color + if mesh_changed { + let new_mesh = mesh_for_settings_dimensions.unwrap_or(mesh_handles.insert( + width, + height, + meshes.add(Mesh::from(shape::Quad::new(Vec2::new(width, height)))), + )); + commands.entity(entity).insert(new_mesh); + material.value_and_dimensions.y = width; + material.value_and_dimensions.z = height; } - if material.value_and_dimensions.w != settings.border.width { - material.value_and_dimensions.w = settings.border.width - } + material.offset = offset; + material.border_color = settings.border.color; + material.value_and_dimensions.w = settings.border.width; + material.vertical = settings.orientation == BarOrientation::Vertical; }); }