diff options
Diffstat (limited to 'src/sim/sim_manager')
| -rw-r--r-- | src/sim/sim_manager/mod.rs | 37 | ||||
| -rw-r--r-- | src/sim/sim_manager/utils.rs | 58 |
2 files changed, 90 insertions, 5 deletions
diff --git a/src/sim/sim_manager/mod.rs b/src/sim/sim_manager/mod.rs index 8fab9cf..b2441ef 100644 --- a/src/sim/sim_manager/mod.rs +++ b/src/sim/sim_manager/mod.rs @@ -1,12 +1,14 @@ use std::time::Instant; use fxhash::FxHashMap; +use rand::random_range; use crate::{ Config, InputManager, config::{PHYSICS_DELTA_TIME, PHYSICS_FPS, SIM_FPS}, input::Input, sim::{ + cell::Cell, cell_manager::manager::CellManager, entity::{Entity, EntityDef, EntityId}, particle_manager::ParticleManager, @@ -99,6 +101,41 @@ impl SimManager { // before we tick, write all the entities into the sim world let cells_written_by_entity = write_entities_to_world(self); + // --TEST DRAWING-- + if input_manager.lmb_held || input_manager.rmb_held { + // start with the bounding box of the drawing brush circle + some margin + // clamp the bounding box to the board sie + let bb_xl = (input_manager.world_mouse_pos.x - config.brush_radius).round() as i32; + let bb_xu = (input_manager.world_mouse_pos.x + config.brush_radius).round() as i32; + let bb_yl = (input_manager.world_mouse_pos.y - config.brush_radius).round() as i32; + let bb_yu = (input_manager.world_mouse_pos.y + config.brush_radius).round() as i32; + + // for each point, check if the distance is less than the brush size and write the pixel + for x in bb_xl..bb_xu { + for y in bb_yl..bb_yu { + let r = random_range(0.0..1.0); + if ((x - input_manager.world_mouse_pos.x.round() as i32).pow(2) + + (y - input_manager.world_mouse_pos.y.round() as i32).pow(2)) + < (config.brush_radius as i32).pow(2) + && r > 0.9 + { + let cell = if input_manager.lmb_held { + let mut cell = Cell::from_material(config.brush_material); + // ensure we simulate on the first tick + cell.match_parity(self.cell_manager.seqno); + cell + } else { + Cell::void() + }; + + self.cell_manager.set_cell_from_game_position( + x, y, cell, false, // wake the chunk + ) + } + } + } + } + // tick self.cell_manager.tick(config.use_threading); diff --git a/src/sim/sim_manager/utils.rs b/src/sim/sim_manager/utils.rs index f30e9a0..264597d 100644 --- a/src/sim/sim_manager/utils.rs +++ b/src/sim/sim_manager/utils.rs @@ -1,10 +1,13 @@ use glam::IVec2; +use rapier2d::{dynamics::RigidBodyBuilder, math::Pose}; use crate::{ + config::CELLS_TO_METRES, content::materials::MaterialId, sim::{ cell::Cell, - entity::{EntityId, EntityUpdateResult}, + entity::{EntityCells, EntityDef, EntityId, EntityUpdateResult}, + lib::components::compute_components, sim_manager::SimManager, }, }; @@ -117,10 +120,17 @@ pub fn read_back_entities_from_world( if let Some(entity) = &mut entity && should_update_entity { - puffin::profile_scope!("Recompute collider"); - if let Some(new_collider) = entity.compute_collider() { - { - puffin::profile_scope!("Upsert collider"); + // correctness: there's no way to get here if the entity is an uncelled entity + let ec = entity.data.cells.as_mut().unwrap(); + // first check if the entity has been partitioned + let components = compute_components(&ec.cells, ec.size.x, ec.size.y); + if components.len() == 0 { + panic!("The entity was completely destroyed?") + } else if components.len() == 1 { + // the entity's cells were changed, but not partitioned + puffin::profile_scope!("Recompute collider"); + if let Some(new_collider) = entity.compute_collider() { + // don't profile this separately as it's basically free sim.rb_manager .physics_manager .world @@ -134,6 +144,44 @@ pub fn read_back_entities_from_world( entity.data.collider_h = Some(new_handle); } + } else { + // the entity was partitioned + // destroy the original entity + // correctness -- not correct! because we don't have pos without rb + let old_rb = sim + .rb_manager + .physics_manager + .world + .bodies + .get(entity.data.rb_h.unwrap()) + .unwrap(); + let old_pose = old_rb.position().clone(); + let old_linvel = old_rb.linvel().clone(); + let old_angvel = old_rb.angvel().clone(); + + sim.destroy_entity(entity_id); + // and create a new entity for each component + for component in components { + let r = old_pose.transform_vector(component.position / CELLS_TO_METRES); + let mut pose = old_pose; + pose.translation += r; + + let rb = RigidBodyBuilder::dynamic() + .pose(pose) + .linvel(old_linvel) + .angvel(old_angvel) + .build(); + + let def = EntityDef::from_cells_and_rb( + EntityCells { + cells: component.cells, + size: component.size, + }, + rb, + None, + ); + sim.create_entity(def); + } } } } |
