diff --git a/core/src/utils/typemap.rs b/core/src/utils/typemap.rs index 88d3dc5..bd28a66 100644 --- a/core/src/utils/typemap.rs +++ b/core/src/utils/typemap.rs @@ -7,9 +7,7 @@ macro_rules! define_typemap { impl $name { pub fn new() -> Self { - Self { - map: std::collections::HashMap::new(), - } + Self { map: std::collections::HashMap::new() } } pub fn insert(&mut self, value: T) -> Option> @@ -17,49 +15,33 @@ macro_rules! define_typemap { T: std::any::Any + 'static + $($trait_bound)*, { let type_id = std::any::TypeId::of::(); - self.map - .insert(type_id, Box::new(value)) - .and_then(|boxed| boxed.downcast().ok()) + self.map.insert(type_id, Box::new(value)).and_then(|b| b.downcast().ok()) } pub fn get(&self) -> Option<&T> where T: std::any::Any + 'static + $($trait_bound)*, { - self.map - .get(&std::any::TypeId::of::()) - .and_then(|any| any.downcast_ref::()) + self.map.get(&std::any::TypeId::of::())?.downcast_ref::() } pub fn get_mut(&mut self) -> Option<&mut T> where T: std::any::Any + 'static + $($trait_bound)*, { - self.map - .get_mut(&std::any::TypeId::of::()) - .and_then(|any| any.downcast_mut::()) + self.map.get_mut(&std::any::TypeId::of::())?.downcast_mut::() } pub fn remove(&mut self) -> Option> where T: std::any::Any + 'static + $($trait_bound)*, { - self.map - .remove(&std::any::TypeId::of::()) - .and_then(|boxed| boxed.downcast().ok()) + self.map.remove(&std::any::TypeId::of::())?.downcast().ok() } - pub fn len(&self) -> usize { - self.map.len() - } - - pub fn is_empty(&self) -> bool { - self.map.is_empty() - } - - pub fn clear(&mut self) { - self.map.clear(); - } + pub fn len(&self) -> usize { self.map.len() } + pub fn is_empty(&self) -> bool { self.map.is_empty() } + pub fn clear(&mut self) { self.map.clear(); } pub fn contains(&self) -> bool where @@ -67,11 +49,407 @@ macro_rules! define_typemap { { self.map.contains_key(&std::any::TypeId::of::()) } + + // --- tuple-based multi-get API --- + pub fn get_many<'a, T>(&'a self) -> Option<::Output<'a>> + where + T: __tm_get::GetTuple, + { + ::get_from(&self.map) + } + + pub fn get_many_mut<'a, T>(&'a mut self) -> Option<::Output<'a>> + where + T: __tm_get::GetTupleMut, + { + ::get_from_mut(&mut self.map) + } } - impl Default for $name { - fn default() -> Self { - Self::new() + impl Default for $name { fn default() -> Self { Self::new() } } + + // Put helper traits/impls in a private module to avoid name clashes. + mod __tm_get { + use std::any::{Any, TypeId}; + use std::collections::HashMap; + + pub trait GetTuple { + type Output<'a>; + fn get_from<'a>(map: &'a HashMap>) -> Option>; + } + + pub trait GetTupleMut { + type Output<'a>; + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option>; + } + + // Manual implementations for arities 1..=8. + impl GetTuple for (A,) + where + A: Any + 'static, + { + type Output<'a> = (&'a A,); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a,)) + } + } + + impl GetTupleMut for (A,) + where + A: Any + 'static, + { + type Output<'a> = (&'a mut A,); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + Some((a,)) + } + } + } + + impl GetTuple for (A, B) + where + A: Any + 'static, + B: Any + 'static, + { + type Output<'a> = (&'a A, &'a B); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::()]; + if ids[0] == ids[1] { return None; } + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + let b = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a, b)) + } + } + + impl GetTupleMut for (A, B) + where + A: Any + 'static, + B: Any + 'static, + { + type Output<'a> = (&'a mut A, &'a mut B); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::()]; + if ids[0] == ids[1] { return None; } + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + let b = (&mut *ptr_b).downcast_mut::()?; + Some((a, b)) + } + } + } + + impl GetTuple for (A, B, C) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + { + type Output<'a> = (&'a A, &'a B, &'a C); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::()]; + if ids[0] == ids[1] || ids[0] == ids[2] || ids[1] == ids[2] { return None; } + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + let b = map.get(&TypeId::of::())?.downcast_ref::()?; + let c = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a, b, c)) + } + } + + impl GetTupleMut for (A, B, C) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + { + type Output<'a> = (&'a mut A, &'a mut B, &'a mut C); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::()]; + if ids[0] == ids[1] || ids[0] == ids[2] || ids[1] == ids[2] { return None; } + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + let b = (&mut *ptr_b).downcast_mut::()?; + let c = (&mut *ptr_c).downcast_mut::()?; + Some((a, b, c)) + } + } + } + + impl GetTuple for (A, B, C, D) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + { + type Output<'a> = (&'a A, &'a B, &'a C, &'a D); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + let b = map.get(&TypeId::of::())?.downcast_ref::()?; + let c = map.get(&TypeId::of::())?.downcast_ref::()?; + let d = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a, b, c, d)) + } + } + + impl GetTupleMut for (A, B, C, D) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + { + type Output<'a> = (&'a mut A, &'a mut B, &'a mut C, &'a mut D); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + let b = (&mut *ptr_b).downcast_mut::()?; + let c = (&mut *ptr_c).downcast_mut::()?; + let d = (&mut *ptr_d).downcast_mut::()?; + Some((a, b, c, d)) + } + } + } + + impl GetTuple for (A, B, C, D, E) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + { + type Output<'a> = (&'a A, &'a B, &'a C, &'a D, &'a E); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + let b = map.get(&TypeId::of::())?.downcast_ref::()?; + let c = map.get(&TypeId::of::())?.downcast_ref::()?; + let d = map.get(&TypeId::of::())?.downcast_ref::()?; + let e = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a, b, c, d, e)) + } + } + + impl GetTupleMut for (A, B, C, D, E) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + { + type Output<'a> = (&'a mut A, &'a mut B, &'a mut C, &'a mut D, &'a mut E); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + let b = (&mut *ptr_b).downcast_mut::()?; + let c = (&mut *ptr_c).downcast_mut::()?; + let d = (&mut *ptr_d).downcast_mut::()?; + let e = (&mut *ptr_e).downcast_mut::()?; + Some((a, b, c, d, e)) + } + } + } + + impl GetTuple for (A, B, C, D, E, F) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + F: Any + 'static, + { + type Output<'a> = (&'a A, &'a B, &'a C, &'a D, &'a E, &'a F); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + let b = map.get(&TypeId::of::())?.downcast_ref::()?; + let c = map.get(&TypeId::of::())?.downcast_ref::()?; + let d = map.get(&TypeId::of::())?.downcast_ref::()?; + let e = map.get(&TypeId::of::())?.downcast_ref::()?; + let f = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a, b, c, d, e, f)) + } + } + + impl GetTupleMut for (A, B, C, D, E, F) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + F: Any + 'static, + { + type Output<'a> = (&'a mut A, &'a mut B, &'a mut C, &'a mut D, &'a mut E, &'a mut F); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_f = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + let b = (&mut *ptr_b).downcast_mut::()?; + let c = (&mut *ptr_c).downcast_mut::()?; + let d = (&mut *ptr_d).downcast_mut::()?; + let e = (&mut *ptr_e).downcast_mut::()?; + let f = (&mut *ptr_f).downcast_mut::()?; + Some((a, b, c, d, e, f)) + } + } + } + + impl GetTuple for (A, B, C, D, E, F, G) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + F: Any + 'static, + G: Any + 'static, + { + type Output<'a> = (&'a A, &'a B, &'a C, &'a D, &'a E, &'a F, &'a G); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + let b = map.get(&TypeId::of::())?.downcast_ref::()?; + let c = map.get(&TypeId::of::())?.downcast_ref::()?; + let d = map.get(&TypeId::of::())?.downcast_ref::()?; + let e = map.get(&TypeId::of::())?.downcast_ref::()?; + let f = map.get(&TypeId::of::())?.downcast_ref::()?; + let g = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a, b, c, d, e, f, g)) + } + } + + impl GetTupleMut for (A, B, C, D, E, F, G) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + F: Any + 'static, + G: Any + 'static, + { + type Output<'a> = (&'a mut A, &'a mut B, &'a mut C, &'a mut D, &'a mut E, &'a mut F, &'a mut G); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_f = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_g = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + let b = (&mut *ptr_b).downcast_mut::()?; + let c = (&mut *ptr_c).downcast_mut::()?; + let d = (&mut *ptr_d).downcast_mut::()?; + let e = (&mut *ptr_e).downcast_mut::()?; + let f = (&mut *ptr_f).downcast_mut::()?; + let g = (&mut *ptr_g).downcast_mut::()?; + Some((a, b, c, d, e, f, g)) + } + } + } + + impl GetTuple for (A, B, C, D, E, F, G, H) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + F: Any + 'static, + G: Any + 'static, + H: Any + 'static, + { + type Output<'a> = (&'a A, &'a B, &'a C, &'a D, &'a E, &'a F, &'a G, &'a H); + fn get_from<'a>(map: &'a HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let a = map.get(&TypeId::of::())?.downcast_ref::()?; + let b = map.get(&TypeId::of::())?.downcast_ref::()?; + let c = map.get(&TypeId::of::())?.downcast_ref::()?; + let d = map.get(&TypeId::of::())?.downcast_ref::()?; + let e = map.get(&TypeId::of::())?.downcast_ref::()?; + let f = map.get(&TypeId::of::())?.downcast_ref::()?; + let g = map.get(&TypeId::of::())?.downcast_ref::()?; + let h = map.get(&TypeId::of::())?.downcast_ref::()?; + Some((a, b, c, d, e, f, g, h)) + } + } + + impl GetTupleMut for (A, B, C, D, E, F, G, H) + where + A: Any + 'static, + B: Any + 'static, + C: Any + 'static, + D: Any + 'static, + E: Any + 'static, + F: Any + 'static, + G: Any + 'static, + H: Any + 'static, + { + type Output<'a> = (&'a mut A, &'a mut B, &'a mut C, &'a mut D, &'a mut E, &'a mut F, &'a mut G, &'a mut H); + fn get_from_mut<'a>(map: &'a mut HashMap>) -> Option> { + let ids = [TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::(), TypeId::of::()]; + for i in 0..ids.len() { for j in (i+1)..ids.len() { if ids[i] == ids[j] { return None; } } } + let ptr_a = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_b = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_c = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_d = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_e = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_f = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_g = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + let ptr_h = { map.get_mut(&TypeId::of::()).map(|v| v as *mut dyn Any) }?; + unsafe { + let a = (&mut *ptr_a).downcast_mut::()?; + let b = (&mut *ptr_b).downcast_mut::()?; + let c = (&mut *ptr_c).downcast_mut::()?; + let d = (&mut *ptr_d).downcast_mut::()?; + let e = (&mut *ptr_e).downcast_mut::()?; + let f = (&mut *ptr_f).downcast_mut::()?; + let g = (&mut *ptr_g).downcast_mut::()?; + let h = (&mut *ptr_h).downcast_mut::()?; + Some((a, b, c, d, e, f, g, h)) + } + } } } }; diff --git a/engine/src/systems/fps_camera.rs b/engine/src/systems/fps_camera.rs index 6bd99f7..0d98577 100644 --- a/engine/src/systems/fps_camera.rs +++ b/engine/src/systems/fps_camera.rs @@ -92,8 +92,7 @@ impl System for FPSDebugCameraSystem { } fn frame_update(&mut self, res: &mut EngineResources, scene: &mut Scene) { - let pctx = res.get::().unwrap(); - let input = res.get::().unwrap(); + let (pctx, input) = res.get_many::<(PlatformContext, InputState)>().unwrap(); if self.mouse_enabled { self.yaw += self.mouse_delta.0 as f32 * self.sensitivity;