use bevy::prelude::*; use crate::grid::{Grid,GridElement}; use crate::MAX_FLUID_AMOUNT; const FLUID_FULLNES_STAGES: usize = 7; pub struct GameViewPlugin; impl Plugin for GameViewPlugin { fn build(&self, app: &mut App) { app .init_resource::() .init_resource::() .add_systems(Startup, (setup_building_planes,setup_view_cubes)) .add_systems(Update, update_cubes); } } #[derive(Resource, Default)] pub struct CubeStages(pub Vec>); #[derive(Component, Clone, Default)] pub struct TileWatch{ pub index: usize, pub previous_element: GridElement } #[derive(Resource, Default)] pub struct TileMaterials { pub solid: Handle, pub water: Handle, pub drain: Handle, pub source: Handle, } pub fn setup_building_planes( mut commands: Commands, mut meshes: ResMut>, grid: Res ) { let mut mesh: Mesh = (Cuboid::new(grid.size.x as f32, grid.size.y as f32, grid.size.z as f32).mesh()).into(); let _ = mesh.invert_winding(); let mesh_handle = meshes.add(mesh); let center = (grid.size.as_vec3() - Vec3::ONE)/2.; commands.spawn_scene(bsn!{ Mesh3d(mesh_handle) Transform { translation: center } MeshMaterial3d(asset_value( StandardMaterial { base_color: Color::WHITE, ..default() } )) Visibility::Visible }); } pub fn setup_view_cubes( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, mut stages: ResMut, mut tile_materials: ResMut, grid: Res) { for i in 0..FLUID_FULLNES_STAGES { let tile_height = ((i+1) as f32)/(FLUID_FULLNES_STAGES as f32); let mesh = meshes.add(Cuboid::new(1., tile_height, 1.)); stages.0.push(mesh); } *tile_materials = TileMaterials { solid: materials.add(StandardMaterial { base_color: Color::hsl(268., 0.778, 0.499), ..default() }), water: materials.add(StandardMaterial { base_color: Color::hsl(172.,0.502,0.571), ..default() }), drain: materials.add(StandardMaterial { base_color: Color::hsl(342., 0.628, 0.685), ..default() }), source: materials.add(StandardMaterial { base_color: Color::hsl(172., 0.502, 0.371), ..default() }) }; let mesh = stages.0[FLUID_FULLNES_STAGES-1].clone(); for i in 0..grid.cell_amount() { commands.spawn_scene( cube( grid.deindexify(i as u32).as_vec3(), i as usize, mesh.clone() ) ); } } pub fn cube(position: Vec3,index: usize,mesh: Handle) -> impl Scene { bsn! { Mesh3d(mesh) MeshMaterial3d Transform::from_translation(position) TileWatch{ index } Visibility::Hidden } } pub fn update_cubes(query: Query<(&mut Mesh3d,&mut Visibility,&mut MeshMaterial3d,&mut TileWatch, &mut Transform)>, materials: Res, stages: Res, grid: Res) { if grid.is_changed() == false { return; } for (mut mesh,mut visibility, mut material, mut tile_data, mut transform) in query { let state = grid.data[tile_data.index]; if tile_data.previous_element == state { continue; } match state { GridElement::Air => { *visibility = Visibility::Hidden; }, GridElement::Water { amount } => { *visibility = Visibility::Visible; material.0 = materials.water.clone(); let stage = ((amount as f32)/(MAX_FLUID_AMOUNT as f32) * (FLUID_FULLNES_STAGES-1) as f32).ceil() as usize; transform.translation = grid.deindexify(tile_data.index as u32).as_vec3() - vec3(0.,((FLUID_FULLNES_STAGES-1-stage) as f32 / (FLUID_FULLNES_STAGES as f32))/2.,0.); mesh.0 = stages.0[stage].clone(); }, GridElement::Solid => { *visibility = Visibility::Visible; material.0 = materials.solid.clone(); mesh.0 = stages.0[FLUID_FULLNES_STAGES-1].clone(); transform.translation = Vec3::ZERO; }, GridElement::Drain => { *visibility = Visibility::Visible; material.0 = materials.drain.clone(); mesh.0 = stages.0[FLUID_FULLNES_STAGES-1].clone(); transform.translation = Vec3::ZERO; }, GridElement::Source { source_amount } => { *visibility = Visibility::Visible; material.0 = materials.source.clone(); let stage = ((source_amount as f32)/(MAX_FLUID_AMOUNT as f32) * (FLUID_FULLNES_STAGES-1) as f32).ceil() as usize; transform.translation = grid.deindexify(tile_data.index as u32).as_vec3() - vec3(0.,((FLUID_FULLNES_STAGES-1-stage) as f32 / (FLUID_FULLNES_STAGES as f32))/2.,0.); mesh.0 = stages.0[stage].clone(); } } tile_data.previous_element = state; } }