#![allow(
clippy::needless_pass_by_value,
clippy::type_complexity,
clippy::option_if_let_else
)]
use crate::components::cloth::Cloth;
use crate::components::cloth_builder::ClothBuilder;
use crate::components::cloth_rendering::ClothRendering;
use crate::config::ClothConfig;
use crate::wind::Winds;
use bevy::log::{debug, error, warn};
use bevy::math::Vec3;
use bevy::prelude::*;
pub fn update(
mut query: Query<(&mut Cloth, &GlobalTransform, Option<&ClothConfig>)>,
anchor_query: Query<&GlobalTransform, Without<Cloth>>,
config: Res<ClothConfig>,
wind: Option<Res<Winds>>,
time: Res<Time>,
) {
let delta_time = time.delta_seconds();
let wind_force = wind.map_or(Vec3::ZERO, |w| w.current_velocity(time.elapsed_seconds()));
for (mut cloth, transform, custom_config) in query.iter_mut() {
let config: &ClothConfig = custom_config.unwrap_or(&config);
cloth.update_points(
config.friction_coefficient(),
config.smoothed_acceleration(wind_force + config.gravity, delta_time),
);
cloth.update_anchored_points(transform, |entity| {
if let Ok(t) = anchor_query.get(entity) {
Some(t)
} else {
error!("Could not find cloth anchor target entity {:?}", entity);
None
}
});
cloth.update_sticks(config.sticks_computation_depth);
}
}
pub fn render(
mut cloth_query: Query<(&Cloth, &mut ClothRendering, &GlobalTransform, &Handle<Mesh>)>,
mut meshes: ResMut<Assets<Mesh>>,
) {
for (cloth, mut rendering, transform, handle) in cloth_query.iter_mut() {
if let Some(mesh) = meshes.get_mut(handle) {
rendering.update_positions(cloth.compute_vertex_positions(transform));
rendering.apply(mesh);
} else {
warn!("A Cloth has a `ClothRendering` component without a loaded mesh handle");
}
}
}
pub fn init(
mut commands: Commands,
query: Query<(Entity, &ClothBuilder, &GlobalTransform, &Handle<Mesh>), Without<Cloth>>,
meshes: Res<Assets<Mesh>>,
) {
for (entity, builder, transform, handle) in query.iter() {
if let Some(mesh) = meshes.get(handle) {
let matrix = transform.compute_matrix();
debug!("Initializing Cloth entity {:?}", entity);
let rendering = ClothRendering::init(mesh, builder.normals_computing).unwrap();
let cloth = Cloth::new(
&rendering.vertex_positions,
&rendering.indices,
builder.anchored_vertex_ids(mesh),
builder.stick_generation,
builder.stick_length,
&matrix,
);
commands.entity(entity).insert((rendering, cloth));
}
}
}