diff --git a/examples/mario/main.rs b/examples/mario/main.rs index b33afec..47eacac 100644 --- a/examples/mario/main.rs +++ b/examples/mario/main.rs @@ -51,7 +51,7 @@ impl SimpleGameLayer for Mario { let mut camera_transform = Transform::from_xy(-202., -320.); camera_transform.set_global_translation_bounds(Some(0.), Some(2060.), Some(0.), Some(0.)); world.push(( - Camera::new(500., 640., 10.), + Camera::new(500., 640.), camera_transform, Parent(self.hero.expect("Hero is mandatory")), )); diff --git a/examples/tetris/layer.rs b/examples/tetris/layer.rs index e3c4f9a..31407b6 100644 --- a/examples/tetris/layer.rs +++ b/examples/tetris/layer.rs @@ -13,6 +13,7 @@ use scion::{ }; use crate::{asset_path, resources::TetrisResource}; +use scion::core::legion_ext::ScionWorldExtension; #[derive(Default)] pub struct TetrisLayer { @@ -24,7 +25,7 @@ impl SimpleGameLayer for TetrisLayer { add_main_ui_mask(world); add_ui_top_overflow(world); self.score = Some(add_score_ui(world)); - world.push((Camera::new(544., 704., 10.), Transform::default())); + world.add_default_camera(); let _r = resources.timers().add_timer("piece", TimerType::Cyclic, 0.5); let _r = resources.timers().add_timer("action_reset_timer", TimerType::Manual, 0.2); let mut tetris = TetrisResource::default(); diff --git a/src/application.rs b/src/application.rs index 34e2a3d..e296810 100644 --- a/src/application.rs +++ b/src/application.rs @@ -35,7 +35,7 @@ use crate::{ systems::{ animations_system::animation_executer_system, asset_ref_resolver_system::{asset_ref_resolver_system, MaterialAssetResolverFn}, - collider_systems::{colliders_cleaner_system, compute_collisions_system}, + collider_systems::{colliders_cleaner_system, compute_collisions_system, debug_colliders_system}, default_camera_system::default_camera_system, hide_propagation_system::{hide_propagated_deletion_system, hide_propagation_system}, hierarchy_system::children_manager_system, @@ -276,6 +276,7 @@ impl ScionBuilder { self.schedule_builder .add_system(default_camera_system()) .add_system(ui_text_bitmap_update_system()) + .add_system(debug_colliders_system()) .flush() .add_system(children_manager_system()) .add_system(hide_propagated_deletion_system()) diff --git a/src/core/components/maths/camera.rs b/src/core/components/maths/camera.rs index b2f269b..ce115ba 100644 --- a/src/core/components/maths/camera.rs +++ b/src/core/components/maths/camera.rs @@ -12,7 +12,7 @@ pub struct Camera { impl Camera { /// Creates a camera with a viewport of size (width;height;depth). In general the same width and height of the window. - pub fn new(width: f32, height: f32, depth: f32) -> Self { - Self { left: 0., right: width, top: 0., bottom: -1. * height, near: 0.0, far: depth } + pub fn new(width: f32, height: f32) -> Self { + Self { left: 0., right: width, top: 0., bottom: -1. * height, near: 0.0, far: 100. } } } diff --git a/src/core/components/maths/collider.rs b/src/core/components/maths/collider.rs index 18079e7..a1f1430 100644 --- a/src/core/components/maths/collider.rs +++ b/src/core/components/maths/collider.rs @@ -35,6 +35,7 @@ pub struct Collider { collider_type: ColliderType, collision_filter: Vec, collisions: Vec, + debug_lines: bool } impl Collider { @@ -45,7 +46,12 @@ impl Collider { collision_filter: Vec, collider_type: ColliderType, ) -> Self { - Collider { collider_mask, collider_type, collision_filter, collisions: vec![] } + Collider { collider_mask, collider_type, collision_filter, collisions: vec![], debug_lines: false } + } + + pub fn with_debug_lines(mut self) -> Self{ + self.debug_lines = true; + self } /// Return whether or not this collider colliding to any other collider ? @@ -57,6 +63,15 @@ impl Collider { /// The mask of this collision pub fn mask(&self) -> &ColliderMask { &self.collider_mask } + /// Retrieve the collider type of this collider + pub fn collider_type(&self) -> &ColliderType { + &self.collider_type + } + + pub(crate) fn debug_lines(&self) -> bool{ + self.debug_lines + } + pub(crate) fn passive(&self) -> bool { self.collision_filter.len() == 1 && self.collision_filter.contains(&ColliderMask::None) } @@ -123,6 +138,9 @@ impl Collision { pub fn coordinates(&self) -> &Coordinates { &self.coordinates } } +/// Internal component used to keep track of a collider debug display +pub (crate) struct ColliderDebug; + #[cfg(test)] mod tests { use super::*; diff --git a/src/core/components/shapes/polygon.rs b/src/core/components/shapes/polygon.rs index 5551c4f..11492bd 100644 --- a/src/core/components/shapes/polygon.rs +++ b/src/core/components/shapes/polygon.rs @@ -7,8 +7,6 @@ use crate::{ rendering::{gl_representations::TexturedGlVertex, Renderable2D}, }; -const INDICES: &[u16] = &[0, 1]; - /// Renderable 2D Polygon made of outlines. pub struct Polygon { pub vertices: Vec, @@ -78,5 +76,5 @@ impl Renderable2D for Polygon { fn dirty(&self) -> bool { self.dirty } - fn set_dirty(&mut self, _is_dirty: bool) {} + fn set_dirty(&mut self, is_dirty: bool) { self.dirty = is_dirty;} } diff --git a/src/core/systems/collider_systems.rs b/src/core/systems/collider_systems.rs index 5d5f1d5..1b3d25d 100644 --- a/src/core/systems/collider_systems.rs +++ b/src/core/systems/collider_systems.rs @@ -4,6 +4,14 @@ use crate::core::components::maths::{ collider::{Collider, Collision}, transform::Transform, }; +use legion::systems::CommandBuffer; +use crate::core::components::maths::hierarchy::{Children, Parent}; +use crate::core::components::maths::collider::{ColliderDebug, ColliderType}; +use std::collections::HashSet; +use crate::core::components::shapes::polygon::Polygon; +use crate::core::components::maths::coordinates::Coordinates; +use crate::core::components::material::Material; +use crate::core::components::color::Color; #[system(for_each)] pub(crate) fn colliders_cleaner(collider: &mut Collider) { collider.clear_collisions() } @@ -53,6 +61,40 @@ pub(crate) fn compute_collisions( } } +/// System responsible to add a `ColliderDebug` component to each colliders that are in debug mode +#[system] +pub(crate) fn debug_colliders( + cmd: &mut CommandBuffer, + world: &mut SubWorld, + query_colliders: &mut Query<(Entity, &Transform, &mut Collider)>, + query_collider_debug: &mut Query<(&ColliderDebug, &Parent)>) { + let (mut collider_world, debug_world) = world.split_for_query(query_colliders); + + let collider_debug: HashSet = query_collider_debug.iter(&debug_world).map(|(_, p)| p.0).collect(); + + query_colliders.for_each_mut(&mut collider_world, |(entity, _, collider)| { + if collider.debug_lines() && !collider_debug.contains(entity) { + let ColliderType::Square(size) = collider.collider_type(); + let size = *size as f32; + cmd.push((Parent(*entity), + ColliderDebug, + Transform::from_xyz(0., 0., 99), + Polygon::new( + vec![ + Coordinates::new(0., 0.), + Coordinates::new(size, 0.), + Coordinates::new(size, size), + Coordinates::new(0., size), + Coordinates::new(0., 0.), + ] + ), + Material::Color(Color::new_rgb(0, 255, 0)) + )); + } + }); +} + + #[cfg(test)] mod tests { use legion::{EntityStore, Resources, Schedule, World}; @@ -127,4 +169,18 @@ mod tests { let res = entry.get_component::().unwrap(); assert_eq!(1, res.collisions().len()); } + + #[test] + fn debug_colliders_system_test() { + let mut world = World::default(); + let mut resources = Resources::default(); + let mut schedule = Schedule::builder().add_system(debug_colliders_system()).build(); + + let collider = world.push((Transform::default(), Collider::new(ColliderMask::None, vec![], ColliderType::Square(100)) + .with_debug_lines())); + schedule.execute(&mut world, &mut resources); + + let res = <(&ColliderDebug, &Parent)>::query().iter(&world).count(); + assert_eq!(1, res); + } } diff --git a/src/core/systems/default_camera_system.rs b/src/core/systems/default_camera_system.rs index 6d21325..5e72678 100644 --- a/src/core/systems/default_camera_system.rs +++ b/src/core/systems/default_camera_system.rs @@ -20,7 +20,7 @@ pub(crate) fn default_camera( cmd.remove_component::(*entity); cmd.add_component( *entity, - Camera::new(window_dimension.width() as f32, window_dimension.height() as f32, 10.), + Camera::new(window_dimension.width() as f32, window_dimension.height() as f32), ); cmd.add_component(*entity, Transform::default()); }