use crate::game::Level; use bevy::prelude::{shape::Quad, *}; use bevy_rapier2d::prelude::*; #[derive(Component)] pub enum PassThroughFilter { /// Absorbs this color (ignoring alpha) Absorbing(Color), /// Rotates hue by this angle (in degrees) Rotating(f32), } impl PassThroughFilter { pub fn apply(&self, color: Color) -> Color { match self { PassThroughFilter::Absorbing(filter_color) => Vec4::from(color) .mul_add( -Vec4::from(*filter_color) * Vec4::from([1., 1., 1., 0.]), Vec4::from(color), ) .into(), PassThroughFilter::Rotating(filter_angle) => { let mut hsla = color.as_hsla_f32(); hsla[0] = (hsla[0] + filter_angle) % 360.; // floating rem is not modulo! if hsla[0] < 0. { hsla[0] += 360.; } Color::hsla(hsla[0], hsla[1], hsla[2], hsla[3]) } } } } #[derive(Bundle)] pub struct AbsorbingFilter { #[bundle] pub mesh: ColorMesh2dBundle, pub collider: Collider, pub sensor: Sensor, pub filter: PassThroughFilter, } pub fn spawn_absorbing_filter( commands: &mut Commands, meshes: &mut ResMut>, materials: &mut ResMut>, transform: Transform, size: Vec2, color: Color, ) { let mut material_color = color; material_color.set_a(0.5); commands .spawn_bundle(AbsorbingFilter { mesh: ColorMesh2dBundle { mesh: meshes.add(Mesh::from(Quad { size, flip: false })).into(), material: materials.add(material_color.into()), transform, ..Default::default() }, collider: Collider::cuboid(size.x / 2., size.y / 2.), sensor: Sensor, filter: PassThroughFilter::Absorbing(color), }) .insert(Level); } #[derive(Bundle)] pub struct RotatingFilter { #[bundle] pub sprite: SpriteBundle, pub collider: Collider, pub sensor: Sensor, pub filter: PassThroughFilter, pub velocity: Velocity, pub rigid_body: RigidBody, } pub fn spawn_rotating_filter( commands: &mut Commands, asset_server: &Res, transform: Transform, angle: f32, ) { commands .spawn_bundle(RotatingFilter { sprite: SpriteBundle { texture: asset_server.get_handle("bevy.png"), transform, ..Default::default() }, collider: Collider::ball(32.), sensor: Sensor, filter: PassThroughFilter::Rotating(angle), velocity: Velocity::angular(1.), rigid_body: RigidBody::KinematicVelocityBased, }) .insert(Level); }