use bevy_asset::Handle;
use bevy_ecs::prelude::{Bundle, Component, Entity, ReflectComponent};
use bevy_math::{Vec2, Vec3};
use bevy_reflect::prelude::*;
use bevy_render::prelude::{Image, VisibilityBundle};
use bevy_sprite::TextureAtlas;
use bevy_transform::prelude::{GlobalTransform, Transform};
use crate::values::{ColorOverTime, JitteredValue, RandomValue, ValueOverTime};
#[derive(Debug, Clone, Copy, Reflect, FromReflect)]
pub struct ParticleBurst {
pub time: f32,
pub count: usize,
}
impl ParticleBurst {
pub fn new(time: f32, count: usize) -> Self {
Self { time, count }
}
}
#[derive(Debug, Clone, Copy, Reflect, FromReflect)]
pub enum ParticleSpace {
Local,
World,
}
#[derive(Debug, Clone, Reflect, FromReflect)]
pub enum ParticleTexture {
Sprite(Handle<Image>),
TextureAtlas {
atlas: Handle<TextureAtlas>,
index: RandomValue<usize>,
},
}
#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Component, Clone, Reflect)]
#[reflect(Component)]
pub struct ParticleSystem {
pub max_particles: usize,
pub texture: ParticleTexture,
pub rescale_texture: Option<Vec2>,
pub spawn_rate_per_second: ValueOverTime,
pub spawn_radius: JitteredValue,
pub emitter_shape: f32,
pub emitter_angle: f32,
pub initial_speed: JitteredValue,
pub acceleration: ValueOverTime,
pub lifetime: JitteredValue,
pub color: ColorOverTime,
pub scale: ValueOverTime,
pub initial_rotation: JitteredValue,
pub rotation_speed: JitteredValue,
pub rotate_to_movement_direction: bool,
pub looping: bool,
pub system_duration_seconds: f32,
pub max_distance: Option<f32>,
pub z_value_override: Option<JitteredValue>,
pub bursts: Vec<ParticleBurst>,
pub space: ParticleSpace,
pub use_scaled_time: bool,
pub despawn_on_finish: bool,
pub despawn_particles_with_system: bool,
}
impl Default for ParticleSystem {
fn default() -> Self {
Self {
max_particles: 100,
texture: ParticleTexture::Sprite(Handle::default()),
rescale_texture: None,
spawn_rate_per_second: 5.0.into(),
spawn_radius: 0.0.into(),
emitter_shape: std::f32::consts::TAU,
emitter_angle: 0.0,
initial_speed: 1.0.into(),
acceleration: 0.0.into(),
lifetime: 5.0.into(),
color: ColorOverTime::default(),
scale: 1.0.into(),
initial_rotation: 0.0.into(),
rotation_speed: 0.0.into(),
rotate_to_movement_direction: false,
looping: true,
system_duration_seconds: 5.0,
max_distance: None,
z_value_override: None,
bursts: Vec::default(),
space: ParticleSpace::World,
use_scaled_time: true,
despawn_on_finish: false,
despawn_particles_with_system: false,
}
}
}
#[derive(Debug, Component)]
pub struct Particle {
pub parent_system: Entity,
pub max_lifetime: f32,
pub max_distance: Option<f32>,
pub use_scaled_time: bool,
pub color: ColorOverTime,
pub scale: ValueOverTime,
pub acceleration: ValueOverTime,
pub rotation_speed: f32,
pub despawn_with_parent: bool,
}
impl Default for Particle {
fn default() -> Self {
Self {
parent_system: Entity::from_raw(0),
max_lifetime: f32::default(),
max_distance: None,
use_scaled_time: true,
color: ColorOverTime::default(),
scale: 1.0.into(),
rotation_speed: 0.0,
acceleration: 0.0.into(),
despawn_with_parent: false,
}
}
}
#[derive(Debug, Component, Default)]
pub struct Lifetime(pub f32);
#[derive(Debug, Component, Default)]
pub struct DistanceTraveled {
pub dist_squared: f32,
pub from: Vec3,
}
#[derive(Debug, Component, Default)]
pub struct Speed(pub f32);
#[derive(Debug, Component, Default)]
pub struct Direction(pub Vec3);
impl Direction {
pub fn new(mut direction: Vec3, ignore_z: bool) -> Self {
if ignore_z {
direction.z = 0.0;
}
Self(direction.normalize())
}
}
#[derive(Debug, Component)]
pub struct Playing;
#[derive(Debug, Component, Default, Reflect)]
#[reflect(Component)]
pub struct RunningState {
pub running_time: f32,
pub current_second: f32,
pub spawned_this_second: usize,
}
#[derive(Debug, Component, Default, Reflect)]
#[reflect(Component)]
pub struct ParticleCount(pub usize);
#[derive(Debug, Component, Default, Reflect)]
#[reflect(Component)]
pub struct BurstIndex(pub usize);
#[derive(Debug, Default, Bundle)]
pub struct ParticleSystemBundle {
pub particle_system: ParticleSystem,
pub transform: Transform,
pub global_transform: GlobalTransform,
pub particle_count: ParticleCount,
pub running_state: RunningState,
pub burst_index: BurstIndex,
pub visibility: VisibilityBundle,
}
#[derive(Debug, Default, Bundle)]
pub(crate) struct ParticleBundle {
pub particle: Particle,
pub lifetime: Lifetime,
pub speed: Speed,
pub direction: Direction,
pub distance: DistanceTraveled,
}