diff --git a/Cargo.toml b/Cargo.toml index fdf6aaa9..3ac253b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "shura" -version = "0.4.3" +version = "0.5.0" edition = "2021" repository = "https://github.com/AndriBaal/shura" documentation = "https://docs.rs/shura" @@ -62,7 +62,6 @@ naga = "0.12" egui-wgpu = { version = "0.22", features = ["winit"], optional = true } egui = { version = "0.22", default-features = false, optional = true, features = [ "bytemuck", - # "tracing", "default_fonts", "mint", ] } diff --git a/examples/bunnymark/main.rs b/examples/bunnymark/main.rs index 9405ee85..82c44edd 100644 --- a/examples/bunnymark/main.rs +++ b/examples/bunnymark/main.rs @@ -110,7 +110,7 @@ impl ComponentController for Bunny { let frame = ctx.frame.frame_time(); let fov = ctx.world_camera.fov(); - for bunny in ctx.components.iter_mut::() { + ctx.components.for_each_mut::(|bunny| { let mut linvel = bunny.linvel; let mut translation = bunny.base.translation(); @@ -133,14 +133,15 @@ impl ComponentController for Bunny { } bunny.linvel = linvel; bunny.base.set_translation(translation); - } + }); } fn render(ctx: &Context, encoder: &mut RenderEncoder) { let scene = ctx.scene_states.get::(); - encoder.render_all::(ctx, RenderConfig::WORLD, |r, instances| { - r.render_sprite(instances, &scene.bunny_model, &scene.bunny_sprite) - }); + ctx.components + .render_all::(encoder, RenderConfig::WORLD, |r, instances| { + r.render_sprite(instances, &scene.bunny_model, &scene.bunny_sprite) + }); if let Some(screenshot) = &scene.screenshot { encoder.copy_to_target(&ctx.defaults.world_target, &screenshot); } diff --git a/examples/bunnymark_text/main.rs b/examples/bunnymark_text/main.rs index e5d94743..178f1dd8 100644 --- a/examples/bunnymark_text/main.rs +++ b/examples/bunnymark_text/main.rs @@ -101,7 +101,7 @@ impl ComponentController for Bunny { let frame = ctx.frame.frame_time(); let fov = ctx.world_camera.fov(); - for bunny in ctx.components.iter_mut::() { + ctx.components.for_each_mut::(|bunny| { let mut linvel = bunny.linvel; let mut translation = bunny.base.translation(); @@ -124,14 +124,15 @@ impl ComponentController for Bunny { } bunny.linvel = linvel; bunny.base.set_translation(translation); - } + }); } fn render(ctx: &Context, encoder: &mut RenderEncoder) { let scene = ctx.scene_states.get::(); - encoder.render_all::(ctx, RenderConfig::WORLD, |r, instances| { - r.render_sprite(instances, &scene.bunny_model, &scene.bunny_sprite); - }); + ctx.components + .render_all::(encoder, RenderConfig::WORLD, |r, instances| { + r.render_sprite(instances, &scene.bunny_model, &scene.bunny_sprite); + }); scene.font.queue( ctx.defaults, diff --git a/examples/flappy_bird/main.rs b/examples/flappy_bird/main.rs index 5d77dbe2..48d95e31 100644 --- a/examples/flappy_bird/main.rs +++ b/examples/flappy_bird/main.rs @@ -100,11 +100,20 @@ impl Bird { } impl ComponentController for Bird { + const CONFIG: ComponentConfig = ComponentConfig { + storage: ComponentStorage::Single, + ..ComponentConfig::DEFAULT + }; + fn render(ctx: &Context, encoder: &mut RenderEncoder) { - encoder.render_each::(ctx, RenderConfig::default(), |r, bird, instance| { - let index = (ctx.frame.total_time() * 7.0 % 3.0) as usize; - r.render_sprite(instance, &bird.model, &bird.sprite[index]) - }); + ctx.components.render_each::( + encoder, + RenderConfig::default(), + |r, bird, instance| { + let index = (ctx.frame.total_time() * 7.0 % 3.0) as usize; + r.render_sprite(instance, &bird.model, &bird.sprite[index]) + }, + ); } fn update(ctx: &mut Context) { @@ -229,9 +238,11 @@ impl ComponentController for Ground { ..ComponentConfig::DEFAULT }; fn render(ctx: &Context, encoder: &mut RenderEncoder) { - encoder.render_each::(ctx, RenderConfig::default(), |r, ground, instance| { - r.render_sprite(instance, &ground.model, &ground.sprite) - }); + ctx.components.render_each::( + encoder, + RenderConfig::default(), + |r, ground, instance| r.render_sprite(instance, &ground.model, &ground.sprite), + ); } } @@ -260,12 +271,17 @@ impl ComponentController for Background { const CONFIG: ComponentConfig = ComponentConfig { priority: 1, buffer: BufferOperation::Manual, + storage: ComponentStorage::Single, ..ComponentConfig::DEFAULT }; fn render(ctx: &Context, encoder: &mut RenderEncoder) { - encoder.render_each::(ctx, RenderConfig::default(), |r, background, instance| { - r.render_sprite(instance, &background.model, &background.sprite) - }); + ctx.components.render_each::( + encoder, + RenderConfig::default(), + |r, background, instance| { + r.render_sprite(instance, &background.model, &background.sprite) + }, + ); } } @@ -335,9 +351,10 @@ impl ComponentController for Pipe { fn render(ctx: &Context, encoder: &mut RenderEncoder) { let scene = ctx.scene_states.get::(); - encoder.render_all::(ctx, RenderConfig::default(), |r, instances| { - r.render_sprite(instances.clone(), &scene.top_pipe_model, &scene.pipe_sprite); - r.render_sprite(instances, &scene.bottom_pipe_model, &scene.pipe_sprite); - }); + ctx.components + .render_all::(encoder, RenderConfig::default(), |r, instances| { + r.render_sprite(instances.clone(), &scene.top_pipe_model, &scene.pipe_sprite); + r.render_sprite(instances, &scene.bottom_pipe_model, &scene.pipe_sprite); + }); } } diff --git a/examples/flappy_bird_ai/main.rs b/examples/flappy_bird_ai/main.rs index f7482cb4..a5206c2b 100644 --- a/examples/flappy_bird_ai/main.rs +++ b/examples/flappy_bird_ai/main.rs @@ -210,10 +210,7 @@ impl ComponentController for Bird { let mut new_birds = Vec::with_capacity(amount); for _ in 0..amount { let index = gene_pool.sample(&mut rng); - let rand_bird = ctx - .components - .index_mut::(GroupHandle::DEFAULT_GROUP, index) - .unwrap(); + let rand_bird = ctx.components.index_mut::(index).unwrap(); let mut new_bird = Bird::with_brain(&rand_bird); new_bird.brain.mutate(); @@ -244,11 +241,15 @@ impl ComponentController for Bird { fn render(ctx: &Context, encoder: &mut RenderEncoder) { let scene = ctx.scene_states.get::(); - encoder.render_each::(ctx, RenderConfig::default(), |r, bird, instance| { - if !bird.dead { - r.render_sprite(instance, &scene.bird_model, &scene.bird_sprite) - } - }); + ctx.components.render_each::( + encoder, + RenderConfig::default(), + |r, bird, instance| { + if !bird.dead { + r.render_sprite(instance, &scene.bird_model, &scene.bird_sprite) + } + }, + ); } } @@ -282,9 +283,11 @@ impl ComponentController for Ground { ..ComponentConfig::DEFAULT }; fn render(ctx: &Context, encoder: &mut RenderEncoder) { - encoder.render_each::(ctx, RenderConfig::default(), |r, ground, instance| { - r.render_sprite(instance, &ground.model, &ground.sprite) - }); + ctx.components.render_each::( + encoder, + RenderConfig::default(), + |r, ground, instance| r.render_sprite(instance, &ground.model, &ground.sprite), + ); } } @@ -316,9 +319,13 @@ impl ComponentController for Background { ..ComponentConfig::DEFAULT }; fn render(ctx: &Context, encoder: &mut RenderEncoder) { - encoder.render_each::(ctx, RenderConfig::default(), |r, background, instance| { - r.render_sprite(instance, &background.model, &background.sprite) - }); + ctx.components.render_each::( + encoder, + RenderConfig::default(), + |r, background, instance| { + r.render_sprite(instance, &background.model, &background.sprite) + }, + ); } } @@ -367,10 +374,11 @@ impl ComponentController for Pipe { fn render(ctx: &Context, encoder: &mut RenderEncoder) { let scene = ctx.scene_states.get::(); - encoder.render_all::(ctx, RenderConfig::default(), |r, instances| { - r.render_sprite(instances.clone(), &scene.top_pipe_model, &scene.pipe_sprite); - r.render_sprite(instances, &scene.bottom_pipe_model, &scene.pipe_sprite); - }); + ctx.components + .render_all::(encoder, RenderConfig::default(), |r, instances| { + r.render_sprite(instances.clone(), &scene.top_pipe_model, &scene.pipe_sprite); + r.render_sprite(instances, &scene.bottom_pipe_model, &scene.pipe_sprite); + }); } } diff --git a/examples/lighting/main.rs b/examples/lighting/main.rs index 5ff5c9db..3ed4a2d3 100644 --- a/examples/lighting/main.rs +++ b/examples/lighting/main.rs @@ -168,9 +168,10 @@ impl ComponentController for Obstacle { }; fn render(ctx: &Context, encoder: &mut RenderEncoder) { - encoder.render_each::(ctx, RenderConfig::WORLD, |renderer, o, i| { - renderer.render_color(i, &o.model, &o.color) - }); + ctx.components + .render_each::(encoder, RenderConfig::WORLD, |renderer, o, i| { + renderer.render_color(i, &o.model, &o.color) + }); } } @@ -353,19 +354,17 @@ impl ComponentController for Light { clear_color: Some(Color::TRANSPARENT), ..RenderConfig::WORLD }); - for (buffer, lights) in ctx.components.iter_render::() { + for (buffer, instance, light) in ctx.components.iter_render::() { renderer.use_instances(buffer); - for (i, light) in lights { - renderer.use_shader(&state.light_shader); - renderer.use_model(&light.light_model); - renderer.use_uniform(&light.light_color, 1); - renderer.draw(i); - - for shadow in &light.shadows { - renderer.use_shader(&state.shadow_shader); - renderer.use_model(shadow); - renderer.draw(i); - } + renderer.use_shader(&state.light_shader); + renderer.use_model(&light.light_model); + renderer.use_uniform(&light.light_color, 1); + renderer.draw(instance); + + for shadow in &light.shadows { + renderer.use_shader(&state.shadow_shader); + renderer.use_model(shadow); + renderer.draw(instance); } } } diff --git a/examples/models/main.rs b/examples/models/main.rs index 3334bbd7..29948b6d 100644 --- a/examples/models/main.rs +++ b/examples/models/main.rs @@ -128,8 +128,9 @@ impl ComponentController for ModelTest { ..ComponentConfig::DEFAULT }; fn render(ctx: &Context, encoder: &mut RenderEncoder) { - encoder.render_each::(ctx, RenderConfig::WORLD, |r, model, index| { - r.render_color(index, &model.model, &model.color) - }); + ctx.components + .render_each::(encoder, RenderConfig::WORLD, |r, model, index| { + r.render_color(index, &model.model, &model.color) + }); } } diff --git a/examples/physics_serde/main.rs b/examples/physics_serde/main.rs index 26a1e075..4a2a3fe5 100644 --- a/examples/physics_serde/main.rs +++ b/examples/physics_serde/main.rs @@ -124,6 +124,11 @@ impl Player { } impl ComponentController for Player { + const CONFIG: ComponentConfig = ComponentConfig { + storage: ComponentStorage::Single, + ..ComponentConfig::DEFAULT + }; + fn update(ctx: &mut Context) { let scroll = ctx.input.wheel_delta(); let fov = ctx.world_camera.fov(); @@ -203,9 +208,10 @@ impl ComponentController for Player { } fn render(ctx: &Context, encoder: &mut RenderEncoder) { - encoder.render_each::(ctx, RenderConfig::WORLD, |r, player, index| { - r.render_sprite(index, &player.model, &player.sprite) - }); + ctx.components + .render_each::(encoder, RenderConfig::WORLD, |r, player, index| { + r.render_sprite(index, &player.model, &player.sprite) + }); } fn collision( @@ -258,9 +264,10 @@ impl Floor { impl ComponentController for Floor { fn render(ctx: &Context, encoder: &mut RenderEncoder) { - encoder.render_each::(ctx, RenderConfig::WORLD, |r, floor, index| { - r.render_color(index, &floor.model, &floor.color) - }); + ctx.components + .render_each::(encoder, RenderConfig::WORLD, |r, floor, index| { + r.render_color(index, &floor.model, &floor.color) + }); } } @@ -294,28 +301,17 @@ impl PhysicsBox { impl ComponentController for PhysicsBox { fn render(ctx: &Context, encoder: &mut RenderEncoder) { - let mut renderer = encoder.renderer(RenderConfig::WORLD); let state = ctx.scene_states.get::(); - for (buffer, boxes) in ctx.components.iter_render::() { - let mut ranges = vec![]; - let mut last = 0; - for (i, b) in boxes.clone() { - if b.collided { - ranges.push((&state.default_color, last..i.index)); - ranges.push((&state.collision_color, i.index..i.index + 1)); - last = i.index + 1; - } else if b.hovered { - ranges.push((&state.default_color, last..i.index)); - ranges.push((&state.hover_color, i.index..i.index + 1)); - last = i.index + 1; - } - } - ranges.push((&state.default_color, last..buffer.len())); - renderer.use_instances(buffer); - for (color, r) in ranges { - renderer.render_color(r, &state.box_model, color) - } - } + ctx.components.render_each::(encoder, RenderConfig::WORLD, |renderer, b, instance| { + let sprite = if b.hovered { + &state.hover_color + } else if b.collided { + &state.collision_color + } else { + &state.default_color + }; + renderer.render_color(instance, &state.box_model, sprite); + }) ; } fn update(ctx: &mut Context) { diff --git a/src/component/component_config.rs b/src/component/component_config.rs index 31d5f41b..ea033dff 100644 --- a/src/component/component_config.rs +++ b/src/component/component_config.rs @@ -40,9 +40,19 @@ pub enum UpdateOperation { AfterDuration(Duration), } +/// Defines how to component gets stored. It is either a signle, multiple of it can be +/// stored or it has multiple groups +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum ComponentStorage { + Single, + Multiple, + Groups, +} + /// The configuration of a component type. This configuration is used to statically define /// behaviour of a component type for perfomance and utility reason. -#[derive(Debug, Clone, Copy)] +#[derive(Clone, Copy, Eq, PartialEq, Debug)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ComponentConfig { /// Describes the order in which components are processed @@ -51,12 +61,14 @@ pub struct ComponentConfig { // pub auto_register: bool, pub update: UpdateOperation, pub buffer: BufferOperation, + pub storage: ComponentStorage, } impl ComponentConfig { pub const DEFAULT: ComponentConfig = ComponentConfig { buffer: BufferOperation::EveryFrame, update: UpdateOperation::EveryFrame, + storage: ComponentStorage::Multiple, priority: 16, }; } diff --git a/src/component/component_derive.rs b/src/component/component_derive.rs index 48ad33d4..18e8d86c 100644 --- a/src/component/component_derive.rs +++ b/src/component/component_derive.rs @@ -63,7 +63,7 @@ where /// This has massive performance advantes since many components /// can be rendered with the same operation, therefore it is mainly used for rendering /// components that have the exact same [model](crate::Model), [uniforms](crate::Uniform) or [sprites](crate::Sprite). - /// Rendering is mainly done with [render_each](crate::RenderEncoder::render_each) and [render_all](crate::RenderEncoder::render_all). + /// Rendering is mainly done with [render_each](crate::ComponentManager::render_each) and [render_all](crate::ComponentManager::render_all). fn render(ctx: &Context, encoder: &mut RenderEncoder) {} /// Method called when the game is closed or the scene gets removed diff --git a/src/component/component_handle.rs b/src/component/component_handle.rs index f409d045..3ea98c05 100644 --- a/src/component/component_handle.rs +++ b/src/component/component_handle.rs @@ -13,9 +13,14 @@ pub struct GroupHandle(pub(crate) ArenaIndex); pub(crate) struct TypeIndex(pub(crate) ArenaIndex); impl GroupHandle { + pub const INVALID: Self = GroupHandle(ArenaIndex::INVALID); pub const DEFAULT_GROUP: Self = GroupHandle(ArenaIndex::FIRST); } +impl ComponentIndex { + pub const INVALID: Self = ComponentIndex(ArenaIndex::INVALID); +} + impl Default for GroupHandle { fn default() -> Self { Self::DEFAULT_GROUP diff --git a/src/component/component_manager.rs b/src/component/component_manager.rs index 528b62ef..96bf06c5 100644 --- a/src/component/component_manager.rs +++ b/src/component/component_manager.rs @@ -7,7 +7,8 @@ use crate::physics::World; use crate::{ Arena, BoxedComponent, CallableType, CameraBuffer, ComponentConfig, ComponentController, ComponentHandle, ComponentSet, ComponentSetMut, ComponentType, ComponentTypeId, Gpu, Group, - GroupActivation, GroupHandle, InstanceBuffer, InstanceIndex, TypeIndex, Vector, + GroupActivation, GroupHandle, InstanceBuffer, InstanceIndex, InstanceIndices, RenderConfig, + RenderEncoder, Renderer, TypeIndex, Vector, }; use std::cell::RefCell; use std::collections::BTreeMap; @@ -329,8 +330,7 @@ impl ComponentManager { pub fn add_group(&mut self, group: Group) -> GroupHandle { let handle = GroupHandle(self.groups.insert(group)); for (_, ty) in &mut self.types { - let result = ty.add_group(); - assert_eq!(handle, result); + ty.add_group(); } self.all_groups.push(handle); return handle; @@ -348,12 +348,20 @@ impl ComponentManager { return group; } - pub fn index(&self, group: GroupHandle, index: usize) -> Option<&C> { + pub fn index(&self, index: usize) -> Option<&C> { + self.index_of(GroupHandle::DEFAULT_GROUP, index) + } + + pub fn index_mut(&mut self, index: usize) -> Option<&mut C> { + self.index_mut_of(GroupHandle::DEFAULT_GROUP, index) + } + + pub fn index_of(&self, group: GroupHandle, index: usize) -> Option<&C> { let ty = type_ref!(self, C); ty.index(group, index) } - pub fn index_mut( + pub fn index_mut_of( &mut self, group: GroupHandle, index: usize, @@ -490,14 +498,11 @@ impl ComponentManager { } #[inline] - pub fn remove_all(&mut self) -> Vec<(GroupHandle, Vec)> { + pub fn remove_all(&mut self) -> Vec { self.remove_all_of(ComponentFilter::All) } - pub fn remove_all_of( - &mut self, - filter: ComponentFilter, - ) -> Vec<(GroupHandle, Vec)> { + pub fn remove_all_of(&mut self, filter: ComponentFilter) -> Vec { let groups = group_filter!(self, filter).1; let ty = type_mut!(self, C); ty.remove_all(groups) @@ -556,24 +561,14 @@ impl ComponentManager { #[inline] pub fn iter_render( &self, - ) -> impl DoubleEndedIterator< - Item = ( - &InstanceBuffer, - impl DoubleEndedIterator + Clone, - ), - > { + ) -> impl DoubleEndedIterator { self.iter_render_of::(ComponentFilter::Active) } pub fn iter_render_of( &self, filter: ComponentFilter, - ) -> impl DoubleEndedIterator< - Item = ( - &InstanceBuffer, - impl DoubleEndedIterator + Clone, - ), - > { + ) -> impl DoubleEndedIterator { let groups = group_filter!(self, filter).1; let ty = type_ref!(self, C); ty.iter_render(groups) @@ -672,29 +667,33 @@ impl ComponentManager { } #[inline] - pub fn each(&self, each: impl FnMut(&C)) { - self.each_of(ComponentFilter::Active, each) + pub fn for_each(&self, each: impl FnMut(&C)) { + self.for_each_of(ComponentFilter::Active, each) } - pub fn each_of(&self, filter: ComponentFilter, each: impl FnMut(&C)) { + pub fn for_each_of( + &self, + filter: ComponentFilter, + each: impl FnMut(&C), + ) { let groups = group_filter!(self, filter).1; let ty = type_ref!(self, C); - ty.each(groups, each); + ty.for_each(groups, each); } #[inline] - pub fn each_mut(&mut self, each: impl FnMut(&mut C)) { - self.each_mut_of(ComponentFilter::Active, each) + pub fn for_each_mut(&mut self, each: impl FnMut(&mut C)) { + self.for_each_mut_of(ComponentFilter::Active, each) } - pub fn each_mut_of( + pub fn for_each_mut_of( &mut self, filter: ComponentFilter, each: impl FnMut(&mut C), ) { let groups = group_filter!(self, filter).1; let ty = type_mut!(self, C); - ty.each_mut(groups, each); + ty.for_each_mut(groups, each); } #[inline] @@ -711,4 +710,63 @@ impl ComponentManager { let ty = type_mut!(self, C); ty.retain(groups, keep); } + + pub fn render_each<'a, C: ComponentController>( + &'a self, + encoder: &'a mut RenderEncoder, + config: RenderConfig<'a>, + each: impl FnMut(&mut Renderer<'a>, &'a C, InstanceIndex), + ) -> Renderer<'a> { + let ty = type_ref!(self, C); + ty.render_each(encoder, config, each) + } + + pub fn render_each_prepare<'a, C: ComponentController>( + &'a self, + encoder: &'a mut RenderEncoder, + config: RenderConfig<'a>, + prepare: impl FnOnce(&mut Renderer<'a>), + each: impl FnMut(&mut Renderer<'a>, &'a C, InstanceIndex), + ) -> Renderer<'a> { + let ty = type_ref!(self, C); + ty.render_each_prepare(encoder, config, prepare, each) + } + + pub fn render_all<'a, C: ComponentController>( + &'a self, + encoder: &'a mut RenderEncoder, + config: RenderConfig<'a>, + all: impl FnMut(&mut Renderer<'a>, InstanceIndices), + ) -> Renderer<'a> { + let ty = type_ref!(self, C); + ty.render_all::(encoder, config, all) + } + + pub fn single(&self) -> Option<&C> { + let ty = type_ref!(self, C); + ty.single() + } + + pub fn single_mut(&mut self) -> Option<&mut C> { + let ty = type_mut!(self, C); + ty.single_mut() + } + + pub fn remove_single(&mut self) -> Option { + let ty = type_mut!(self, C); + ty.remove_single() + } + + pub fn set_single(&mut self, new: C) -> ComponentHandle { + let ty = type_mut!(self, C); + ty.set_single(new) + } + + pub fn set_single_with( + &mut self, + create: impl FnOnce(ComponentHandle) -> C, + ) -> ComponentHandle { + let ty = type_mut!(self, C); + ty.set_single_with(create) + } } diff --git a/src/component/component_set.rs b/src/component/component_set.rs index 9da4c55d..aae6d2da 100644 --- a/src/component/component_set.rs +++ b/src/component/component_set.rs @@ -1,6 +1,6 @@ use crate::{ BoxedComponent, ComponentController, ComponentHandle, ComponentType, GroupHandle, - InstanceBuffer, InstanceIndex, + InstanceBuffer, InstanceIndex, InstanceIndices, RenderConfig, RenderEncoder, Renderer, }; use std::marker::PhantomData; @@ -21,11 +21,15 @@ impl<'a, C: ComponentController> ComponentSet<'a, C> { } } - pub fn each(&mut self, each: impl FnMut(&C)) { - self.ty.each(self.groups, each); + pub fn for_each(&mut self, each: impl FnMut(&C)) { + self.ty.for_each(self.groups, each); } - pub fn index(&self, group: GroupHandle, index: usize) -> Option<&C> { + pub fn index(&self, index: usize) -> Option<&C> { + self.index_of(GroupHandle::DEFAULT_GROUP, index) + } + + pub fn index_of(&self, group: GroupHandle, index: usize) -> Option<&C> { self.ty.index(group, index) } @@ -44,6 +48,10 @@ impl<'a, C: ComponentController> ComponentSet<'a, C> { pub fn iter(&self) -> impl DoubleEndedIterator { self.ty.iter(self.groups) } + + pub fn single(&self) -> Option<&C> { + self.ty.single() + } } /// Set of mutable components from the same type only from the specified (groups)[crate::Group] @@ -68,23 +76,31 @@ impl<'a, C: ComponentController> ComponentSetMut<'a, C> { } } - pub fn each(&self, each: impl FnMut(&C)) { - self.ty.each(self.groups, each); + pub fn for_each(&self, each: impl FnMut(&C)) { + self.ty.for_each(self.groups, each); } - pub fn each_mut(&mut self, each: impl FnMut(&mut C)) { - self.ty.each_mut(self.groups, each); + pub fn for_each_mut(&mut self, each: impl FnMut(&mut C)) { + self.ty.for_each_mut(self.groups, each); } pub fn retain(&mut self, keep: impl FnMut(&mut C) -> bool) { self.ty.retain(self.groups, keep); } - pub fn index(&self, group: GroupHandle, index: usize) -> Option<&C> { + pub fn index(&self, index: usize) -> Option<&C> { + self.index_of(GroupHandle::DEFAULT_GROUP, index) + } + + pub fn index_mut(&mut self, index: usize) -> Option<&mut C> { + self.index_mut_of(GroupHandle::DEFAULT_GROUP, index) + } + + pub fn index_of(&self, group: GroupHandle, index: usize) -> Option<&C> { self.ty.index(group, index) } - pub fn index_mut(&mut self, group: GroupHandle, index: usize) -> Option<&mut C> { + pub fn index_mut_of(&mut self, group: GroupHandle, index: usize) -> Option<&mut C> { self.ty.index_mut(group, index) } @@ -120,7 +136,7 @@ impl<'a, C: ComponentController> ComponentSetMut<'a, C> { self.ty.remove_boxed(handle) } - pub fn remove_all(&mut self) -> Vec<(GroupHandle, Vec)> { + pub fn remove_all(&mut self) -> Vec { self.ty.remove_all(self.groups) } @@ -174,12 +190,7 @@ impl<'a, C: ComponentController> ComponentSetMut<'a, C> { pub fn iter_render( &self, - ) -> impl DoubleEndedIterator< - Item = ( - &InstanceBuffer, - impl DoubleEndedIterator + Clone, - ), - > { + ) -> impl DoubleEndedIterator { self.ty.iter_render(self.groups) } @@ -192,4 +203,55 @@ impl<'a, C: ComponentController> ComponentSetMut<'a, C> { ) -> impl DoubleEndedIterator { self.ty.iter_mut_with_handles(self.groups, self.check) } + + pub fn render_each( + &'a self, + encoder: &'a mut RenderEncoder, + config: RenderConfig<'a>, + each: impl FnMut(&mut Renderer<'a>, &'a C, InstanceIndex), + ) -> Renderer<'a> { + self.ty.render_each(encoder, config, each) + } + + pub fn render_each_prepare( + &'a self, + encoder: &'a mut RenderEncoder, + config: RenderConfig<'a>, + prepare: impl FnOnce(&mut Renderer<'a>), + each: impl FnMut(&mut Renderer<'a>, &'a C, InstanceIndex), + ) -> Renderer<'a> { + self.ty.render_each_prepare(encoder, config, prepare, each) + } + + pub fn render_all( + &'a self, + encoder: &'a mut RenderEncoder, + config: RenderConfig<'a>, + all: impl FnMut(&mut Renderer<'a>, InstanceIndices), + ) -> Renderer<'a> { + self.ty.render_all::(encoder, config, all) + } + + pub fn single(&self) -> Option<&C> { + self.ty.single() + } + + pub fn single_mut(&mut self) -> Option<&mut C> { + self.ty.single_mut() + } + + pub fn remove_single(&mut self) -> Option { + self.ty.remove_single() + } + + pub fn set_single(&mut self, new: C) -> ComponentHandle { + self.ty.set_single(new) + } + + pub fn set_single_with( + &mut self, + create: impl FnOnce(ComponentHandle) -> C, + ) -> ComponentHandle { + self.ty.set_single_with(create) + } } diff --git a/src/component/component_type.rs b/src/component/component_type.rs index 928c8b58..46239c65 100644 --- a/src/component/component_type.rs +++ b/src/component/component_type.rs @@ -7,8 +7,9 @@ use crate::physics::{CollideType, ColliderHandle, World, WorldChanges}; use crate::{ data::arena::ArenaEntry, Arena, BoxedComponent, BufferOperation, ComponentConfig, - ComponentController, ComponentDerive, ComponentHandle, ComponentIndex, Context, EndReason, Gpu, - Group, GroupHandle, InstanceBuffer, InstanceIndex, Matrix, RenderEncoder, TypeIndex, + ComponentController, ComponentDerive, ComponentHandle, ComponentIndex, ComponentStorage, + Context, EndReason, Gpu, Group, GroupHandle, InstanceBuffer, InstanceIndex, InstanceIndices, + Matrix, RenderConfig, RenderEncoder, Renderer, TypeIndex, }; #[derive(Clone, Copy)] @@ -71,12 +72,34 @@ pub trait ComponentIdentifier { const IDENTIFIER: ComponentTypeId; } +#[cfg(feature = "serde")] +fn default_true() -> bool { + true +} + +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub(crate) enum ComponentTypeStorage { + Single { + #[cfg_attr(feature = "serde", serde(skip))] + #[cfg_attr(feature = "serde", serde(default))] + buffer: Option, + #[cfg_attr(feature = "serde", serde(skip))] + #[cfg_attr(feature = "serde", serde(default = "default_true"))] + force_buffer: bool, + #[cfg_attr(feature = "serde", serde(skip))] + #[cfg_attr(feature = "serde", serde(default))] + component: Option, + }, + Multiple(ComponentTypeGroup), + MultipleGroups(Arena), +} + #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub(crate) struct ComponentTypeGroup { #[cfg_attr(feature = "serde", serde(skip))] #[cfg_attr(feature = "serde", serde(default))] pub components: Arena, - pub force_buffer: bool, + force_buffer: bool, #[cfg_attr(feature = "serde", serde(skip))] #[cfg_attr(feature = "serde", serde(default))] buffer: Option, @@ -104,35 +127,6 @@ impl ComponentTypeGroup { }) .collect::>() } - - pub fn buffer( - &mut self, - #[cfg(feature = "physics")] world: &mut World, - every_frame: bool, - gpu: &Gpu, - ) { - let new_len = self.components.len(); - if new_len != self.last_len { - // We have to resize the buffer - let instances = self.instances( - #[cfg(feature = "physics")] - world, - ); - self.last_len = new_len; - self.buffer = Some(InstanceBuffer::new(gpu, &instances[..])); - } else if every_frame || self.force_buffer { - let instances = self.instances( - #[cfg(feature = "physics")] - world, - ); - self.force_buffer = false; - if let Some(buffer) = &mut self.buffer { - buffer.write(gpu, &instances[..]); - } else { - self.buffer = Some(InstanceBuffer::new(gpu, &instances)); - } - } - } } pub(crate) struct CallableType { @@ -159,9 +153,9 @@ pub(crate) struct ComponentType { index: TypeIndex, type_id: ComponentTypeId, config: ComponentConfig, - pub groups: Arena, + pub storage: ComponentTypeStorage, #[cfg(feature = "physics")] - pub world_changes: WorldChanges, + world_changes: WorldChanges, } impl ComponentType { @@ -170,25 +164,33 @@ impl ComponentType { index: TypeIndex, group_structure: &Arena, ) -> Self { - let groups = Arena { - items: group_structure - .items - .iter() - .map(|entry| match *entry { - ArenaEntry::Free { next_free } => ArenaEntry::Free { next_free }, - ArenaEntry::Occupied { generation, .. } => ArenaEntry::Occupied { - generation, - data: ComponentTypeGroup::new(), - }, - }) - .collect(), - generation: group_structure.generation, - free_list_head: group_structure.free_list_head, - len: group_structure.len(), + let storage = match config.storage { + ComponentStorage::Single => ComponentTypeStorage::Single { + buffer: None, + force_buffer: true, + component: None, + }, + ComponentStorage::Multiple => ComponentTypeStorage::Multiple(ComponentTypeGroup::new()), + ComponentStorage::Groups => ComponentTypeStorage::MultipleGroups(Arena { + items: group_structure + .items + .iter() + .map(|entry| match *entry { + ArenaEntry::Free { next_free } => ArenaEntry::Free { next_free }, + ArenaEntry::Occupied { generation, .. } => ArenaEntry::Occupied { + generation, + data: ComponentTypeGroup::new(), + }, + }) + .collect(), + generation: group_structure.generation, + free_list_head: group_structure.free_list_head, + len: group_structure.len(), + }), }; Self { index, - groups, + storage, config, type_id: C::IDENTIFIER, #[cfg(feature = "physics")] @@ -196,6 +198,10 @@ impl ComponentType { } } + pub fn component_type_id(&self) -> ComponentTypeId { + self.type_id + } + pub(crate) fn buffer( &mut self, #[cfg(feature = "physics")] world: &mut World, @@ -206,72 +212,188 @@ impl ComponentType { return; } - let every_frame = self.config.buffer == BufferOperation::EveryFrame; - for index in active { - let group = &mut self.groups[index.0]; - group.buffer( - #[cfg(feature = "physics")] - world, - every_frame, - gpu, - ); + match &mut self.storage { + ComponentTypeStorage::MultipleGroups(groups) => { + for index in active { + let group = &mut groups[index.0]; + let new_len = group.components.len(); + if new_len != group.last_len { + // We have to resize the buffer + let instances = group.instances( + #[cfg(feature = "physics")] + world, + ); + group.last_len = new_len; + group.buffer = Some(InstanceBuffer::new(gpu, &instances[..])); + } else if self.config.buffer == BufferOperation::EveryFrame + || group.force_buffer + { + let instances = group.instances( + #[cfg(feature = "physics")] + world, + ); + group.force_buffer = false; + if let Some(buffer) = &mut group.buffer { + buffer.write(gpu, &instances[..]); + } else { + group.buffer = Some(InstanceBuffer::new(gpu, &instances)); + } + } + } + } + ComponentTypeStorage::Multiple(multiple) => { + let new_len = multiple.components.len(); + if new_len != multiple.last_len { + // We have to resize the buffer + let instances = multiple.instances( + #[cfg(feature = "physics")] + world, + ); + multiple.last_len = new_len; + multiple.buffer = Some(InstanceBuffer::new(gpu, &instances[..])); + } else if self.config.buffer == BufferOperation::EveryFrame || multiple.force_buffer + { + let instances = multiple.instances( + #[cfg(feature = "physics")] + world, + ); + multiple.force_buffer = false; + if let Some(buffer) = &mut multiple.buffer { + buffer.write(gpu, &instances[..]); + } else { + multiple.buffer = Some(InstanceBuffer::new(gpu, &instances)); + } + } + } + ComponentTypeStorage::Single { + buffer, + force_buffer, + component, + } => { + if let Some(component) = component { + if self.config.buffer == BufferOperation::EveryFrame || *force_buffer { + let matrix = component.base().matrix( + #[cfg(feature = "physics")] + world, + ); + *force_buffer = false; + if let Some(buffer) = buffer { + buffer.write(gpu, &[matrix]); + } else { + *buffer = Some(InstanceBuffer::new(gpu, &[matrix])); + } + } + } + } } } - pub(crate) fn add_group(&mut self) -> GroupHandle { - let index = self.groups.insert(ComponentTypeGroup::new()); - return GroupHandle(index); + pub(crate) fn add_group(&mut self) { + match &mut self.storage { + ComponentTypeStorage::MultipleGroups(groups) => { + groups.insert(ComponentTypeGroup::new()); + } + _ => {} + } } pub(crate) fn remove_group(&mut self, handle: GroupHandle) { - let _group = self.groups.remove(handle.0).unwrap(); - #[cfg(feature = "physics")] - for component in _group.components { - self.world_changes.register_remove(&component); + match &mut self.storage { + ComponentTypeStorage::MultipleGroups(groups) => { + let _group = groups.remove(handle.0).unwrap(); + #[cfg(feature = "physics")] + for component in _group.components { + self.world_changes.register_remove(&component); + } + } + _ => {} } } - pub fn component_type_id(&self) -> ComponentTypeId { - self.type_id - } - #[cfg(feature = "physics")] pub fn apply_world_mapping(&mut self, world: &mut World) { self.world_changes.apply(world) } - pub fn each(&self, groups: &[GroupHandle], mut each: impl FnMut(&C)) { - for group in groups { - if let Some(group) = self.groups.get(group.0) { - for (_, component) in &group.components { + pub fn for_each( + &self, + group_handles: &[GroupHandle], + mut each: impl FnMut(&C), + ) { + match &self.storage { + ComponentTypeStorage::Single { component, .. } => { + if let Some(component) = component { (each)(component.downcast_ref::().unwrap()); } } - } + ComponentTypeStorage::Multiple(multiple) => { + for (_, component) in &multiple.components { + (each)(component.downcast_ref::().unwrap()); + } + } + ComponentTypeStorage::MultipleGroups(groups) => { + for group in group_handles { + if let Some(group) = groups.get(group.0) { + for (_, component) in &group.components { + (each)(component.downcast_ref::().unwrap()); + } + } + } + } + }; } - pub fn each_mut( + pub fn for_each_mut( &mut self, - groups: &[GroupHandle], + group_handles: &[GroupHandle], mut each: impl FnMut(&mut C), ) { - for group in groups { - if let Some(group) = self.groups.get_mut(group.0) { - for (_, component) in &mut group.components { + match &mut self.storage { + ComponentTypeStorage::Single { component, .. } => { + if let Some(component) = component { (each)(component.downcast_mut::().unwrap()); } } - } + ComponentTypeStorage::Multiple(multiple) => { + for (_, component) in &mut multiple.components { + (each)(component.downcast_mut::().unwrap()); + } + } + ComponentTypeStorage::MultipleGroups(groups) => { + for group in group_handles { + if let Some(group) = groups.get_mut(group.0) { + for (_, component) in &mut group.components { + (each)(component.downcast_mut::().unwrap()); + } + } + } + } + }; } pub fn retain( &mut self, - groups: &[GroupHandle], + group_handles: &[GroupHandle], mut keep: impl FnMut(&mut C) -> bool, ) { - for group in groups { - if let Some(group) = self.groups.get_mut(group.0) { - group.components.retain(|_, component| { + match &mut self.storage { + ComponentTypeStorage::Single { + force_buffer, + component, + .. + } => { + if let Some(c) = component { + let c = c.downcast_mut::().unwrap(); + #[cfg(feature = "physics")] + self.world_changes.register_remove(c); + if !keep(c) { + *force_buffer = true; + *component = None; + } + } + } + ComponentTypeStorage::Multiple(multiple) => { + multiple.components.retain(|_, component| { let component = component.downcast_mut::().unwrap(); if keep(component) { true @@ -282,16 +404,50 @@ impl ComponentType { } }); } - } + ComponentTypeStorage::MultipleGroups(groups) => { + for group in group_handles { + if let Some(group) = groups.get_mut(group.0) { + group.components.retain(|_, component| { + let component = component.downcast_mut::().unwrap(); + if keep(component) { + true + } else { + #[cfg(feature = "physics")] + self.world_changes.register_remove(component); + false + } + }); + } + } + } + }; } pub fn index(&self, group: GroupHandle, index: usize) -> Option<&C> { - if let Some(group) = self.groups.get(group.0) { - if let Some(component) = group.components.get_unknown_gen(index) { - return component.downcast_ref::(); + match &self.storage { + ComponentTypeStorage::Single { component, .. } => { + if index == 0 { + if let Some(c) = component { + return c.downcast_ref::(); + } + } + return None; } - } - return None; + ComponentTypeStorage::Multiple(multiple) => { + if let Some(component) = multiple.components.get_unknown_gen(index) { + return component.downcast_ref::(); + } + return None; + } + ComponentTypeStorage::MultipleGroups(groups) => { + if let Some(group) = groups.get(group.0) { + if let Some(component) = group.components.get_unknown_gen(index) { + return component.downcast_ref::(); + } + } + return None; + } + }; } pub fn index_mut( @@ -299,30 +455,80 @@ impl ComponentType { group: GroupHandle, index: usize, ) -> Option<&mut C> { - if let Some(group) = self.groups.get_mut(group.0) { - if let Some(component) = group.components.get_unknown_gen_mut(index) { - return component.downcast_mut::(); + match &mut self.storage { + ComponentTypeStorage::Single { component, .. } => { + if index == 0 { + if let Some(c) = component { + return c.downcast_mut::(); + } + } + return None; } - } - return None; + ComponentTypeStorage::Multiple(multiple) => { + if let Some(component) = multiple.components.get_unknown_gen_mut(index) { + return component.downcast_mut::(); + } + return None; + } + ComponentTypeStorage::MultipleGroups(groups) => { + if let Some(group) = groups.get_mut(group.0) { + if let Some(component) = group.components.get_unknown_gen_mut(index) { + return component.downcast_mut::(); + } + } + return None; + } + }; } pub fn get(&self, handle: ComponentHandle) -> Option<&C> { - if let Some(group) = self.groups.get(handle.group_handle().0) { - if let Some(component) = group.components.get(handle.component_index().0) { - return component.downcast_ref::(); + match &self.storage { + ComponentTypeStorage::Single { component, .. } => { + if let Some(c) = component { + return c.downcast_ref::(); + } + return None; } - } - return None; + ComponentTypeStorage::Multiple(multiple) => { + if let Some(component) = multiple.components.get(handle.component_index().0) { + return component.downcast_ref::(); + } + return None; + } + ComponentTypeStorage::MultipleGroups(groups) => { + if let Some(group) = groups.get(handle.group_handle().0) { + if let Some(component) = group.components.get(handle.component_index().0) { + return component.downcast_ref::(); + } + } + return None; + } + }; } pub fn get_mut(&mut self, handle: ComponentHandle) -> Option<&mut C> { - if let Some(group) = self.groups.get_mut(handle.group_handle().0) { - if let Some(component) = group.components.get_mut(handle.component_index().0) { - return component.downcast_mut::(); + match &mut self.storage { + ComponentTypeStorage::Single { component, .. } => { + if let Some(c) = component { + return c.downcast_mut::(); + } + return None; } - } - return None; + ComponentTypeStorage::Multiple(multiple) => { + if let Some(component) = multiple.components.get_mut(handle.component_index().0) { + return component.downcast_mut::(); + } + return None; + } + ComponentTypeStorage::MultipleGroups(groups) => { + if let Some(group) = groups.get_mut(handle.group_handle().0) { + if let Some(component) = group.components.get_mut(handle.component_index().0) { + return component.downcast_mut::(); + } + } + return None; + } + }; } pub fn get2_mut( @@ -330,11 +536,14 @@ impl ComponentType { handle1: ComponentHandle, handle2: ComponentHandle, ) -> (Option<&mut C1>, Option<&mut C2>) { - let mut c1 = None; - let mut c2 = None; - if handle1.group_handle() == handle2.group_handle() { - if let Some(group) = self.groups.get_mut(handle1.group_handle().0) { - let result = group + match &mut self.storage { + ComponentTypeStorage::Single { .. } => { + panic!("Cannot get 2 on component with ComponentStorage::Single!"); + } + ComponentTypeStorage::Multiple(multiple) => { + let mut c1 = None; + let mut c2 = None; + let result = multiple .components .get2_mut(handle1.component_index().0, handle2.component_index().0); if let Some(component) = result.0 { @@ -343,24 +552,45 @@ impl ComponentType { if let Some(component) = result.1 { c2 = component.downcast_mut::(); } + return (c1, c2); } - } else { - let (group1, group2) = self - .groups - .get2_mut(handle1.group_handle().0, handle2.group_handle().0); - if let Some(group) = group1 { - if let Some(component) = group.components.get_mut(handle1.component_index().0) { - c1 = component.downcast_mut::(); - } - } + ComponentTypeStorage::MultipleGroups(groups) => { + let mut c1 = None; + let mut c2 = None; + if handle1.group_handle() == handle2.group_handle() { + if let Some(group) = groups.get_mut(handle1.group_handle().0) { + let result = group + .components + .get2_mut(handle1.component_index().0, handle2.component_index().0); + if let Some(component) = result.0 { + c1 = component.downcast_mut::(); + } + if let Some(component) = result.1 { + c2 = component.downcast_mut::(); + } + } + } else { + let (group1, group2) = + groups.get2_mut(handle1.group_handle().0, handle2.group_handle().0); + if let Some(group) = group1 { + if let Some(component) = + group.components.get_mut(handle1.component_index().0) + { + c1 = component.downcast_mut::(); + } + } - if let Some(group) = group2 { - if let Some(component) = group.components.get_mut(handle2.component_index().0) { - c2 = component.downcast_mut::(); + if let Some(group) = group2 { + if let Some(component) = + group.components.get_mut(handle2.component_index().0) + { + c2 = component.downcast_mut::(); + } + } } + return (c1, c2); } - } - return (c1, c2); + }; } pub fn get2_mut_boxed( @@ -368,286 +598,826 @@ impl ComponentType { handle1: ComponentHandle, handle2: ComponentHandle, ) -> (Option<&mut BoxedComponent>, Option<&mut BoxedComponent>) { - let mut c1 = None; - let mut c2 = None; - if handle1.group_handle() == handle2.group_handle() { - if let Some(group) = self.groups.get_mut(handle1.group_handle().0) { - (c1, c2) = group + match &mut self.storage { + ComponentTypeStorage::Single { .. } => { + panic!("Cannot get 2 on component with ComponentStorage::Single!"); + } + ComponentTypeStorage::Multiple(multiple) => { + return multiple .components .get2_mut(handle1.component_index().0, handle2.component_index().0); } - } else { - let (group1, group2) = self - .groups - .get2_mut(handle1.group_handle().0, handle2.group_handle().0); - if let Some(group) = group1 { - c1 = group.components.get_mut(handle1.component_index().0); - } + ComponentTypeStorage::MultipleGroups(groups) => { + let mut c1 = None; + let mut c2 = None; + if handle1.group_handle() == handle2.group_handle() { + if let Some(group) = groups.get_mut(handle1.group_handle().0) { + (c1, c2) = group + .components + .get2_mut(handle1.component_index().0, handle2.component_index().0); + } + } else { + let (group1, group2) = + groups.get2_mut(handle1.group_handle().0, handle2.group_handle().0); + if let Some(group) = group1 { + c1 = group.components.get_mut(handle1.component_index().0); + } - if let Some(group) = group2 { - c2 = group.components.get_mut(handle2.component_index().0); + if let Some(group) = group2 { + c2 = group.components.get_mut(handle2.component_index().0); + } + } + return (c1, c2); } - } - return (c1, c2); + }; } pub fn get_boxed(&self, handle: ComponentHandle) -> Option<&BoxedComponent> { - if let Some(group) = self.groups.get(handle.group_handle().0) { - return group.components.get(handle.component_index().0); - } - return None; + match &self.storage { + ComponentTypeStorage::Single { component, .. } => { + return component.as_ref(); + } + ComponentTypeStorage::Multiple(multiple) => { + return multiple.components.get(handle.component_index().0); + } + ComponentTypeStorage::MultipleGroups(groups) => { + if let Some(group) = groups.get(handle.group_handle().0) { + return group.components.get(handle.component_index().0); + } + return None; + } + }; } pub fn get_boxed_mut(&mut self, handle: ComponentHandle) -> Option<&mut BoxedComponent> { - if let Some(group) = self.groups.get_mut(handle.group_handle().0) { - return group.components.get_mut(handle.component_index().0); - } - return None; + match &mut self.storage { + ComponentTypeStorage::Single { component, .. } => { + return component.as_mut(); + } + ComponentTypeStorage::Multiple(multiple) => { + return multiple.components.get_mut(handle.component_index().0); + } + ComponentTypeStorage::MultipleGroups(groups) => { + if let Some(group) = groups.get_mut(handle.group_handle().0) { + return group.components.get_mut(handle.component_index().0); + } + return None; + } + }; } pub fn remove(&mut self, handle: ComponentHandle) -> Option { - if let Some(group) = self.groups.get_mut(handle.group_handle().0) { - if let Some(component) = group.components.remove(handle.component_index().0) { - #[cfg(feature = "physics")] - self.world_changes.register_remove(&component); - return component.downcast::().ok().and_then(|b| Some(*b)); + match &mut self.storage { + ComponentTypeStorage::Single { + force_buffer, + component, + .. + } => { + if let Some(component) = component.take() { + #[cfg(feature = "physics")] + self.world_changes.register_remove(&component); + *force_buffer = true; + return component.downcast::().ok().and_then(|b| Some(*b)); + } + return None; } - } - return None; + ComponentTypeStorage::Multiple(multiple) => { + if let Some(component) = multiple.components.remove(handle.component_index().0) { + #[cfg(feature = "physics")] + self.world_changes.register_remove(&component); + return component.downcast::().ok().and_then(|b| Some(*b)); + } + return None; + } + ComponentTypeStorage::MultipleGroups(groups) => { + if let Some(group) = groups.get_mut(handle.group_handle().0) { + if let Some(component) = group.components.remove(handle.component_index().0) { + #[cfg(feature = "physics")] + self.world_changes.register_remove(&component); + return component.downcast::().ok().and_then(|b| Some(*b)); + } + } + return None; + } + }; } pub fn remove_boxed(&mut self, handle: ComponentHandle) -> Option { - if let Some(group) = self.groups.get_mut(handle.group_handle().0) { - if let Some(component) = group.components.remove(handle.component_index().0) { - #[cfg(feature = "physics")] - self.world_changes.register_remove(&component); - return Some(component); + match &mut self.storage { + ComponentTypeStorage::Single { + force_buffer, + component, + .. + } => { + if let Some(component) = component.take() { + #[cfg(feature = "physics")] + self.world_changes.register_remove(&component); + *force_buffer = true; + return Some(component); + } + return None; } - } - return None; + ComponentTypeStorage::Multiple(multiple) => { + if let Some(component) = multiple.components.remove(handle.component_index().0) { + #[cfg(feature = "physics")] + self.world_changes.register_remove(&component); + return Some(component); + } + return None; + } + ComponentTypeStorage::MultipleGroups(groups) => { + if let Some(group) = groups.get_mut(handle.group_handle().0) { + if let Some(component) = group.components.remove(handle.component_index().0) { + #[cfg(feature = "physics")] + self.world_changes.register_remove(&component); + return Some(component); + } + } + return None; + } + }; } - pub fn remove_all( - &mut self, - groups: &[GroupHandle], - ) -> Vec<(GroupHandle, Vec)> { - let mut result = Vec::with_capacity(groups.len()); - for group_handle in groups { - if let Some(group) = self.groups.get_mut(group_handle.0) { - let components = std::mem::replace(&mut group.components, Default::default()); - let mut casted = Vec::with_capacity(components.len()); + pub fn remove_all(&mut self, group_handles: &[GroupHandle]) -> Vec { + match &mut self.storage { + ComponentTypeStorage::Single { + force_buffer, + component, + .. + } => { + let mut result = Vec::with_capacity(1); + if let Some(component) = component.take() { + #[cfg(feature = "physics")] + self.world_changes.register_remove(&component); + *force_buffer = true; + result.push(*component.downcast::().ok().unwrap()); + } + return result; + } + ComponentTypeStorage::Multiple(multiple) => { + let mut result = Vec::with_capacity(multiple.components.len()); + let components = std::mem::replace(&mut multiple.components, Default::default()); for component in components { #[cfg(feature = "physics")] self.world_changes.register_remove(&component); - casted.push(*component.downcast::().ok().unwrap()) + result.push(*component.downcast::().ok().unwrap()) } - result.push((*group_handle, casted)); + return result; } - } - return result; + ComponentTypeStorage::MultipleGroups(groups) => { + let mut result = Vec::new(); + for group_handle in group_handles { + if let Some(group) = groups.get_mut(group_handle.0) { + let components = + std::mem::replace(&mut group.components, Default::default()); + for component in components { + #[cfg(feature = "physics")] + self.world_changes.register_remove(&component); + result.push(*component.downcast::().ok().unwrap()); + } + } + } + return result; + } + }; } pub fn add( &mut self, group_handle: GroupHandle, - component: C, + new: C, ) -> ComponentHandle { - assert_eq!(C::IDENTIFIER, self.type_id); - let group = &mut self.groups[group_handle.0]; - let mut handle = Default::default(); - group.components.insert_with(|idx| { - handle = ComponentHandle::new(ComponentIndex(idx), self.index, group_handle); - #[cfg(feature = "physics")] - self.world_changes.register_add(handle, &component); - Box::new(component) - }); - return handle; + match &mut self.storage { + ComponentTypeStorage::Single { + force_buffer, + component, + .. + } => { + assert!(component.is_none(), "Single component is already set!"); + let handle = + ComponentHandle::new(ComponentIndex::INVALID, self.index, GroupHandle::INVALID); + #[cfg(feature = "physics")] + self.world_changes.register_add(handle, &new); + *component = Some(Box::new(new)); + *force_buffer = true; + return handle; + } + ComponentTypeStorage::Multiple(multiple) => { + let mut handle = Default::default(); + multiple.components.insert_with(|idx| { + handle = + ComponentHandle::new(ComponentIndex(idx), self.index, GroupHandle::INVALID); + #[cfg(feature = "physics")] + self.world_changes.register_add(handle, &new); + Box::new(new) + }); + return handle; + } + ComponentTypeStorage::MultipleGroups(groups) => { + let group = &mut groups[group_handle.0]; + let mut handle = Default::default(); + group.components.insert_with(|idx| { + handle = ComponentHandle::new(ComponentIndex(idx), self.index, group_handle); + #[cfg(feature = "physics")] + self.world_changes.register_add(handle, &new); + Box::new(new) + }); + return handle; + } + }; } - pub fn add_many( + pub fn add_with( &mut self, group_handle: GroupHandle, - components: impl IntoIterator, - ) -> Vec { - let components = components.into_iter(); - let mut handles = Vec::with_capacity(components.size_hint().0); - if let Some(group) = self.groups.get_mut(group_handle.0) { - for component in components { + create: impl FnOnce(ComponentHandle) -> C, + ) -> ComponentHandle { + match &mut self.storage { + ComponentTypeStorage::Single { + force_buffer, + component, + .. + } => { + assert!(component.is_none(), "Single component is already set!"); + let handle = + ComponentHandle::new(ComponentIndex::INVALID, self.index, GroupHandle::INVALID); + let new = create(handle); + #[cfg(feature = "physics")] + self.world_changes.register_add(handle, &new); + *component = Some(Box::new(new)); + *force_buffer = true; + return handle; + } + ComponentTypeStorage::Multiple(multiple) => { + let mut handle = Default::default(); + multiple.components.insert_with(|idx| { + handle = + ComponentHandle::new(ComponentIndex(idx), self.index, GroupHandle::INVALID); + let new = create(handle); + #[cfg(feature = "physics")] + self.world_changes.register_add(handle, &new); + Box::new(new) + }); + return handle; + } + ComponentTypeStorage::MultipleGroups(groups) => { + let group = &mut groups[group_handle.0]; + let mut handle = Default::default(); group.components.insert_with(|idx| { - let handle = - ComponentHandle::new(ComponentIndex(idx), self.index, group_handle); + handle = ComponentHandle::new(ComponentIndex(idx), self.index, group_handle); + let new = create(handle); #[cfg(feature = "physics")] - self.world_changes.register_add(handle, &component); - handles.push(handle); - Box::new(component) + self.world_changes.register_add(handle, &new); + Box::new(new) }); + return handle; } - } - return handles; + }; } - pub fn add_with( + pub fn add_many( &mut self, group_handle: GroupHandle, - create: impl FnOnce(ComponentHandle) -> C, - ) -> ComponentHandle { - assert_eq!(C::IDENTIFIER, self.type_id); - let group = &mut self.groups[group_handle.0]; - let mut handle = Default::default(); - group.components.insert_with(|idx| { - handle = ComponentHandle::new(ComponentIndex(idx), self.index, group_handle); - let component = create(handle); - #[cfg(feature = "physics")] - self.world_changes.register_add(handle, &component); - Box::new(component) - }); - return handle; + components: impl IntoIterator, + ) -> Vec { + match &mut self.storage { + ComponentTypeStorage::Single { .. } => { + panic!("Cannot add naby on component with ComponentStorage::Single!"); + } + ComponentTypeStorage::Multiple(multiple) => { + let components = components.into_iter(); + let mut handles = Vec::with_capacity(components.size_hint().0); + for component in components { + multiple.components.insert_with(|idx| { + let handle = ComponentHandle::new( + ComponentIndex(idx), + self.index, + GroupHandle::INVALID, + ); + #[cfg(feature = "physics")] + self.world_changes.register_add(handle, &component); + handles.push(handle); + Box::new(component) + }); + } + return handles; + } + ComponentTypeStorage::MultipleGroups(groups) => { + let components = components.into_iter(); + let mut handles = Vec::with_capacity(components.size_hint().0); + if let Some(group) = groups.get_mut(group_handle.0) { + for component in components { + group.components.insert_with(|idx| { + let handle = + ComponentHandle::new(ComponentIndex(idx), self.index, group_handle); + #[cfg(feature = "physics")] + self.world_changes.register_add(handle, &component); + handles.push(handle); + Box::new(component) + }); + } + } + return handles; + } + }; } - pub fn force_buffer(&mut self, groups: &[GroupHandle]) { - for group in groups { - if let Some(group) = self.groups.get_mut(group.0) { - group.force_buffer = true; + pub fn force_buffer(&mut self, group_handles: &[GroupHandle]) { + match &mut self.storage { + ComponentTypeStorage::Single { force_buffer, .. } => { + *force_buffer = true; } - } + ComponentTypeStorage::Multiple(multiple) => { + multiple.force_buffer = true; + } + ComponentTypeStorage::MultipleGroups(groups) => { + for group in group_handles { + if let Some(group) = groups.get_mut(group.0) { + group.force_buffer = true; + } + } + } + }; } - pub fn len(&self, groups: &[GroupHandle]) -> usize { - let mut len = 0; - for group in groups { - if let Some(group) = self.groups.get(group.0) { - len += group.components.len(); + pub fn len(&self, group_handles: &[GroupHandle]) -> usize { + match &self.storage { + ComponentTypeStorage::Single { .. } => { + return 1; } - } - return len; + ComponentTypeStorage::Multiple(multiple) => { + return multiple.components.len(); + } + ComponentTypeStorage::MultipleGroups(groups) => { + let mut len = 0; + for group in group_handles { + if let Some(group) = groups.get(group.0) { + len += group.components.len(); + } + } + return len; + } + }; } pub fn iter<'a, C: ComponentController>( &'a self, - groups: &[GroupHandle], - ) -> impl DoubleEndedIterator { - let mut iters = Vec::with_capacity(groups.len()); - for group in groups { - if let Some(group) = self.groups.get(group.0) { - if !group.components.is_empty() { - iters.push( - group - .components - .iter() - .map(|(_, c)| c.downcast_ref::().unwrap()), - ); + group_handles: &[GroupHandle], + ) -> Box + 'a> { + match &self.storage { + ComponentTypeStorage::Single { component, .. } => { + if let Some(component) = component { + return Box::new(std::iter::once(component.downcast_ref::().unwrap())); + } else { + return Box::new(std::iter::empty::<&C>()); } } - } - return iters.into_iter().flatten(); + ComponentTypeStorage::Multiple(multiple) => { + return Box::new( + multiple + .components + .iter() + .map(|(_, c)| c.downcast_ref::().unwrap()), + ); + } + ComponentTypeStorage::MultipleGroups(groups) => { + let mut iters = Vec::with_capacity(groups.len()); + for group in group_handles { + if let Some(group) = groups.get(group.0) { + if !group.components.is_empty() { + iters.push( + group + .components + .iter() + .map(|(_, c)| c.downcast_ref::().unwrap()), + ); + } + } + } + return Box::new(iters.into_iter().flatten()); + } + }; } pub fn iter_with_handles<'a, C: ComponentController>( &'a self, - groups: &'a [GroupHandle], - ) -> impl DoubleEndedIterator { - let mut iters = Vec::with_capacity(groups.len()); - for group_handle in groups { - if let Some(group) = self.groups.get(group_handle.0) { - if !group.components.is_empty() { - iters.push(group.components.iter().map(|(idx, c)| { - ( - ComponentHandle::new(ComponentIndex(idx), self.index, *group_handle), - c.downcast_ref::().unwrap(), - ) - })); + group_handles: &'a [GroupHandle], + ) -> Box + 'a> { + match &self.storage { + ComponentTypeStorage::Single { component, .. } => { + if let Some(component) = component { + return Box::new(std::iter::once(( + ComponentHandle::new( + ComponentIndex::INVALID, + self.index, + GroupHandle::INVALID, + ), + component.downcast_ref::().unwrap(), + ))); + } else { + return Box::new(std::iter::empty::<(ComponentHandle, &'a C)>()); } } - } - return iters.into_iter().flatten(); + ComponentTypeStorage::Multiple(multiple) => { + return Box::new(multiple.components.iter().map(|(idx, c)| { + ( + ComponentHandle::new(ComponentIndex(idx), self.index, GroupHandle::INVALID), + c.downcast_ref::().unwrap(), + ) + })); + } + ComponentTypeStorage::MultipleGroups(groups) => { + let mut iters = Vec::with_capacity(groups.len()); + for group_handle in group_handles { + if let Some(group) = groups.get(group_handle.0) { + if !group.components.is_empty() { + iters.push(group.components.iter().map(|(idx, c)| { + ( + ComponentHandle::new( + ComponentIndex(idx), + self.index, + *group_handle, + ), + c.downcast_ref::().unwrap(), + ) + })); + } + } + } + return Box::new(iters.into_iter().flatten()); + } + }; } - pub fn iter_mut_with_handles<'a, C: ComponentController>( + pub fn iter_mut<'a, C: ComponentController>( &'a mut self, - groups: &'a [GroupHandle], + group_handles: &[GroupHandle], check: bool, - ) -> impl DoubleEndedIterator { - let mut iters = Vec::with_capacity(groups.len()); - let ptr: *mut Arena = &mut self.groups as *mut _; - if check && groups.len() > 1 { - for (index, value) in groups.iter().enumerate() { - for other in groups.iter().skip(index + 1) { - assert_ne!(value.0.index(), other.0.index(), "Duplicate GroupHandle!"); + ) -> Box + 'a> { + match &mut self.storage { + ComponentTypeStorage::Single { component, .. } => { + if let Some(component) = component { + return Box::new(std::iter::once(component.downcast_mut::().unwrap())); + } else { + return Box::new(std::iter::empty::<&mut C>()); } } - } - unsafe { - for group_handle in groups { - if let Some(group) = (&mut *ptr).get_mut(group_handle.0) { - let type_index = &self.index; - - iters.push(group.components.iter_mut().map(move |(idx, c)| { - ( - ComponentHandle::new(ComponentIndex(idx), *type_index, *group_handle), - c.downcast_mut::().unwrap(), - ) - })); - }; + ComponentTypeStorage::Multiple(multiple) => { + return Box::new( + multiple + .components + .iter_mut() + .map(|(_, c)| c.downcast_mut::().unwrap()), + ); } - } + ComponentTypeStorage::MultipleGroups(groups) => { + if check && groups.len() > 1 { + for (index, value) in groups.iter().enumerate() { + for other in groups.iter().skip(index + 1) { + assert_ne!(value.0.index(), other.0.index(), "Duplicate GroupHandle!"); + } + } + } + let mut iters = Vec::with_capacity(groups.len()); + let ptr: *mut Arena = groups as *mut _; + unsafe { + for group_handle in group_handles { + if let Some(group) = (&mut *ptr).get_mut(group_handle.0) { + iters.push( + group + .components + .iter_mut() + .map(|(_, c)| c.downcast_mut::().unwrap()), + ); + }; + } + } - return iters.into_iter().flatten(); + return Box::new(iters.into_iter().flatten()); + } + }; } - pub fn iter_mut<'a, C: ComponentController>( + pub fn iter_mut_with_handles<'a, C: ComponentController>( &'a mut self, - groups: &[GroupHandle], + group_handles: &'a [GroupHandle], check: bool, - ) -> impl DoubleEndedIterator { - if check && groups.len() > 1 { - for (index, value) in groups.iter().enumerate() { - for other in groups.iter().skip(index + 1) { - assert_ne!(value.0.index(), other.0.index(), "Duplicate GroupHandle!"); + ) -> Box + 'a> { + match &mut self.storage { + ComponentTypeStorage::Single { component, .. } => { + if let Some(component) = component { + return Box::new(std::iter::once(( + ComponentHandle::new( + ComponentIndex::INVALID, + self.index, + GroupHandle::INVALID, + ), + component.downcast_mut::().unwrap(), + ))); + } else { + return Box::new(std::iter::empty::<(ComponentHandle, &mut C)>()); + } + } + ComponentTypeStorage::Multiple(multiple) => { + return Box::new(multiple.components.iter_mut().map(|(idx, c)| { + ( + ComponentHandle::new(ComponentIndex(idx), self.index, GroupHandle::INVALID), + c.downcast_mut::().unwrap(), + ) + })); + } + ComponentTypeStorage::MultipleGroups(groups) => { + if check && groups.len() > 1 { + for (index, value) in groups.iter().enumerate() { + for other in groups.iter().skip(index + 1) { + assert_ne!(value.0.index(), other.0.index(), "Duplicate GroupHandle!"); + } + } + } + let mut iters = Vec::with_capacity(groups.len()); + let ptr: *mut Arena = groups as *mut _; + unsafe { + for group_handle in group_handles { + if let Some(group) = (&mut *ptr).get_mut(group_handle.0) { + let type_index = &self.index; + + iters.push(group.components.iter_mut().map(move |(idx, c)| { + ( + ComponentHandle::new( + ComponentIndex(idx), + *type_index, + *group_handle, + ), + c.downcast_mut::().unwrap(), + ) + })); + }; + } + } + + return Box::new(iters.into_iter().flatten()); + } + }; + } + + pub fn iter_render<'a, C: ComponentController>( + &'a self, + group_handles: &[GroupHandle], + ) -> Box + 'a> { + match &self.storage { + ComponentTypeStorage::Single { + component, buffer, .. + } => { + if let Some(component) = component { + return Box::new(std::iter::once(( + buffer.as_ref().unwrap(), + InstanceIndex::new(0), + component.downcast_ref::().unwrap(), + ))); + } else { + return Box::new(std::iter::empty::<(&InstanceBuffer, InstanceIndex, &C)>()); + } + } + ComponentTypeStorage::Multiple(multiple) => { + return Box::new(multiple.components.iter().enumerate().map(|(i, (_, c))| { + ( + multiple.buffer.as_ref().unwrap(), + InstanceIndex::new(i as u32), + c.downcast_ref::().unwrap(), + ) + })); + } + ComponentTypeStorage::MultipleGroups(groups) => { + let mut iters = Vec::with_capacity(groups.len()); + for group in group_handles { + if let Some(group) = groups.get(group.0) { + if !group.components.is_empty() { + iters.push(group.components.iter().enumerate().map(|(i, (_, c))| { + ( + group.buffer.as_ref().unwrap(), + InstanceIndex::new(i as u32), + c.downcast_ref::().unwrap(), + ) + })); + } + } + } + return Box::new(iters.into_iter().flatten()); + } + }; + } + + pub fn render_each<'a, C: ComponentController>( + &'a self, + encoder: &'a mut RenderEncoder, + config: RenderConfig<'a>, + mut each: impl FnMut(&mut Renderer<'a>, &'a C, InstanceIndex), + ) -> Renderer<'a> { + let mut renderer = encoder.renderer(config); + match &self.storage { + ComponentTypeStorage::Single { + buffer, component, .. + } => { + renderer.use_instances(buffer.as_ref().unwrap()); + if let Some(component) = component { + (each)( + &mut renderer, + component.downcast_ref::().unwrap(), + InstanceIndex::new(0), + ); + } + } + ComponentTypeStorage::Multiple(multiple) => { + renderer.use_instances(multiple.buffer.as_ref().unwrap()); + for (instance, (_, component)) in multiple.components.iter().enumerate() { + (each)( + &mut renderer, + component.downcast_ref::().unwrap(), + InstanceIndex::new(instance as u32), + ); + } + } + ComponentTypeStorage::MultipleGroups(groups) => { + for (_, group) in groups { + renderer.use_instances(group.buffer.as_ref().unwrap()); + for (instance, (_, component)) in group.components.iter().enumerate() { + (each)( + &mut renderer, + component.downcast_ref::().unwrap(), + InstanceIndex::new(instance as u32), + ); + } } } } - let mut iters = Vec::with_capacity(groups.len()); - let ptr: *mut Arena = &mut self.groups as *mut _; - unsafe { - for group_handle in groups { - if let Some(group) = (&mut *ptr).get_mut(group_handle.0) { - iters.push( - group - .components - .iter_mut() - .map(|(_, c)| c.downcast_mut::().unwrap()), + return renderer; + } + + pub fn render_each_prepare<'a, C: ComponentController>( + &'a self, + encoder: &'a mut RenderEncoder, + config: RenderConfig<'a>, + prepare: impl FnOnce(&mut Renderer<'a>), + mut each: impl FnMut(&mut Renderer<'a>, &'a C, InstanceIndex), + ) -> Renderer<'a> { + let mut renderer = encoder.renderer(config); + prepare(&mut renderer); + match &self.storage { + ComponentTypeStorage::Single { + buffer, component, .. + } => { + renderer.use_instances(buffer.as_ref().unwrap()); + if let Some(component) = component { + (each)( + &mut renderer, + component.downcast_ref::().unwrap(), + InstanceIndex::new(0), + ); + } + } + ComponentTypeStorage::Multiple(multiple) => { + renderer.use_instances(multiple.buffer.as_ref().unwrap()); + for (instance, (_, component)) in multiple.components.iter().enumerate() { + (each)( + &mut renderer, + component.downcast_ref::().unwrap(), + InstanceIndex::new(instance as u32), ); - }; + } + } + ComponentTypeStorage::MultipleGroups(groups) => { + for (_, group) in groups { + renderer.use_instances(group.buffer.as_ref().unwrap()); + for (instance, (_, component)) in group.components.iter().enumerate() { + (each)( + &mut renderer, + component.downcast_ref::().unwrap(), + InstanceIndex::new(instance as u32), + ); + } + } } } + return renderer; + } - return iters.into_iter().flatten(); + pub fn render_all<'a, C: ComponentController>( + &'a self, + encoder: &'a mut RenderEncoder, + config: RenderConfig<'a>, + mut all: impl FnMut(&mut Renderer<'a>, InstanceIndices), + ) -> Renderer<'a> { + let mut renderer = encoder.renderer(config); + match &self.storage { + ComponentTypeStorage::Single { buffer, .. } => { + let buffer = buffer.as_ref().unwrap(); + renderer.use_instances(buffer); + (all)(&mut renderer, buffer.all_instances()); + } + ComponentTypeStorage::Multiple(multiple) => { + let buffer = multiple.buffer.as_ref().unwrap(); + renderer.use_instances(buffer); + (all)(&mut renderer, buffer.all_instances()); + } + ComponentTypeStorage::MultipleGroups(groups) => { + for (_, group) in groups { + let buffer = group.buffer.as_ref().unwrap(); + renderer.use_instances(buffer); + (all)(&mut renderer, buffer.all_instances()); + } + } + } + return renderer; } - pub fn iter_render( - &self, - groups: &[GroupHandle], - ) -> impl DoubleEndedIterator< - Item = ( - &InstanceBuffer, - impl DoubleEndedIterator + Clone, - ), - > { - let mut iters = Vec::with_capacity(groups.len()); - for group in groups { - if let Some(group) = self.groups.get(group.0) { - if !group.components.is_empty() { - iters.push(( - group.buffer.as_ref().expect( - "This component's buffer is either not initialized or disabled.", - ), - group.components.iter().enumerate().map(|(i, (_, c))| { - (InstanceIndex::new(i as u32), c.downcast_ref::().unwrap()) - }), - )); + pub fn single(&self) -> Option<&C> { + match &self.storage { + ComponentTypeStorage::Single { component, .. } => { + if let Some(component) = component { + return component.downcast_ref::(); + } + return None; + } + _ => panic!("Cannot get single on component without ComponentStorage::Single!"), + } + } + + pub fn single_mut(&mut self) -> Option<&mut C> { + match &mut self.storage { + ComponentTypeStorage::Single { component, .. } => { + if let Some(component) = component { + return component.downcast_mut::(); + } + return None; + } + _ => panic!("Cannot get single on component without ComponentStorage::Single!"), + } + } + + pub fn remove_single(&mut self) -> Option { + match &mut self.storage { + ComponentTypeStorage::Single { + force_buffer, + component, + .. + } => { + if let Some(component) = component.take() { + *force_buffer = true; + #[cfg(feature = "physics")] + self.world_changes.register_remove(&component); + return component.downcast::().ok().and_then(|b| Some(*b)); + } + return None; + } + _ => panic!("Cannot get single on component without ComponentStorage::Single!"), + } + } + + pub fn set_single(&mut self, new: C) -> ComponentHandle { + match &mut self.storage { + ComponentTypeStorage::Single { + force_buffer, + component, + .. + } => { + *force_buffer = true; + let handle = + ComponentHandle::new(ComponentIndex::INVALID, self.index, GroupHandle::INVALID); + #[cfg(feature = "physics")] + self.world_changes.register_add(handle, &new); + if let Some(_old) = component.replace(Box::new(new)) { + #[cfg(feature = "physics")] + self.world_changes.register_remove(&_old); + } + return handle; + } + _ => panic!("Cannot get single on component without ComponentStorage::Single!"), + } + } + + pub fn set_single_with( + &mut self, + create: impl FnOnce(ComponentHandle) -> C, + ) -> ComponentHandle { + match &mut self.storage { + ComponentTypeStorage::Single { + force_buffer, + component, + .. + } => { + let handle = + ComponentHandle::new(ComponentIndex::INVALID, self.index, GroupHandle::INVALID); + let new = create(handle); + #[cfg(feature = "physics")] + self.world_changes.register_add(handle, &new); + *force_buffer = true; + if let Some(_old) = component.replace(Box::new(new)) { + #[cfg(feature = "physics")] + self.world_changes.register_remove(&_old); } + return handle; } + _ => panic!("Cannot get single on component without ComponentStorage::Single!"), } - return iters.into_iter(); } } diff --git a/src/graphics/render_encoder.rs b/src/graphics/render_encoder.rs index bef64d23..1d078076 100644 --- a/src/graphics/render_encoder.rs +++ b/src/graphics/render_encoder.rs @@ -1,6 +1,5 @@ use crate::{ - CameraBuffer, Color, ComponentController, Context, Gpu, GpuDefaults, InstanceBuffer, - InstanceIndex, InstanceIndices, RenderTarget, Renderer, Sprite, + CameraBuffer, Color, Gpu, GpuDefaults, InstanceBuffer, RenderTarget, Renderer, Sprite, }; #[derive(Clone, Copy)] @@ -193,54 +192,6 @@ impl<'a> RenderEncoder<'a> { return renderer; } - pub fn render_each<'b, C: ComponentController>( - &'b mut self, - ctx: &'b Context<'b>, - config: RenderConfig<'b>, - mut each: impl FnMut(&mut Renderer<'b>, &'b C, InstanceIndex), - ) -> Renderer<'b> { - let mut renderer = self.renderer(config); - for (buffer, components) in ctx.components.iter_render::() { - renderer.use_instances(buffer); - for (instance, component) in components { - (each)(&mut renderer, component, instance); - } - } - return renderer; - } - - pub fn render_each_prepare<'b, C: ComponentController>( - &'b mut self, - ctx: &'b Context<'b>, - config: RenderConfig<'b>, - prepare: impl FnOnce(&mut Renderer<'b>), - mut each: impl FnMut(&mut Renderer<'b>, &'b C, InstanceIndex), - ) -> Renderer<'b> { - let mut renderer = self.renderer(config); - prepare(&mut renderer); - for (buffer, components) in ctx.components.iter_render::() { - renderer.use_instances(buffer); - for (instance, component) in components { - (each)(&mut renderer, component, instance); - } - } - return renderer; - } - - pub fn render_all<'b, C: ComponentController>( - &'b mut self, - ctx: &'b Context<'b>, - config: RenderConfig<'b>, - mut all: impl FnMut(&mut Renderer<'b>, InstanceIndices), - ) -> Renderer<'b> { - let mut renderer = self.renderer(config); - for (buffer, _) in ctx.components.iter_render::() { - renderer.use_instances(buffer); - (all)(&mut renderer, buffer.all_instances()); - } - return renderer; - } - pub fn finish(self) -> wgpu::SubmissionIndex { self.gpu.queue.submit(Some(self.inner.finish())) } diff --git a/src/scene/context.rs b/src/scene/context.rs index d085c3de..201b11ff 100644 --- a/src/scene/context.rs +++ b/src/scene/context.rs @@ -4,7 +4,10 @@ use crate::{ }; #[cfg(feature = "serde")] -use crate::{ComponentTypeId, GroupHandle, SceneSerializer, StateTypeId}; +use crate::{ComponentTypeId, SceneSerializer, SerializedComponentStorage, StateTypeId}; + +#[cfg(feature = "serde")] +use rustc_hash::FxHashMap; #[cfg(feature = "audio")] use crate::audio::AudioManager; @@ -90,8 +93,6 @@ impl<'a> Context<'a> { &mut self, mut serialize: impl FnMut(&mut SceneSerializer), ) -> Result, Box> { - use rustc_hash::FxHashMap; - let components = &self.components; let mut serializer = @@ -121,9 +122,23 @@ impl<'a> Context<'a> { for (_, ty) in self.components.types() { if !ser_components.contains_key(&ty.component_type_id()) { - for (_, group) in &ty.groups { - for (_, component) in &group.components { - changes.register_remove(component); + match &ty.storage { + crate::ComponentTypeStorage::Single { component, .. } => { + if let Some(component) = component { + changes.register_remove(component); + } + } + crate::ComponentTypeStorage::Multiple(multiple) => { + for (_, component) in &multiple.components { + changes.register_remove(component); + } + } + crate::ComponentTypeStorage::MultipleGroups(groups) => { + for (_, group) in groups { + for (_, component) in &group.components { + changes.register_remove(component); + } + } } } } @@ -143,7 +158,7 @@ impl<'a> Context<'a> { }; let scene: ( &Scene, - FxHashMap)>>)>>, + FxHashMap, FxHashMap>, FxHashMap>, ) = (&scene, ser_components, ser_scene_state, ser_global_state); @@ -166,7 +181,7 @@ impl<'a> Context<'a> { }; let scene: ( &Scene, - FxHashMap)>>)>>, + FxHashMap, FxHashMap>, FxHashMap>, ) = (&scene, ser_components, ser_scene_state, ser_global_state); @@ -174,20 +189,4 @@ impl<'a> Context<'a> { return result; } } - - // pub fn remove_scene(&mut self, id: u32) -> Option { - // if let Some(mut scene) = self.scenes.remove(id) { - // for end in scene.states.ends() { - // let mut ctx = Context::from_fields(ShuraFields::from_ctx(self), &mut scene); - // end(&mut ctx); - // } - // return Some(scene); - // } - // return None; - // } - - // pub fn add_scene(&mut self, scene: impl SceneCreator) { - // let scene = scene.scene(ShuraFields::from_ctx(self)); - // self.scenes.add(scene); - // } } diff --git a/src/scene/scene_serde.rs b/src/scene/scene_serde.rs index 010540c9..8403c7a2 100644 --- a/src/scene/scene_serde.rs +++ b/src/scene/scene_serde.rs @@ -5,21 +5,29 @@ use bincode::{ }; use rustc_hash::FxHashMap; use serde::{de::Visitor, Deserializer, Serialize}; -use std::{cmp, marker::PhantomData}; +use std::marker::PhantomData; use crate::{ Arena, ArenaEntry, BoxedComponent, ComponentController, ComponentManager, ComponentTypeId, - Context, FieldNames, GroupHandle, Scene, SceneCreator, Shura, StateDerive, StateIdentifier, - StateManager, StateTypeId, + ComponentTypeStorage, Context, FieldNames, GroupHandle, Scene, SceneCreator, Shura, + StateDerive, StateIdentifier, StateManager, StateTypeId, }; +#[cfg(feature = "serde")] +#[derive(serde::Deserialize, serde::Serialize)] +pub(crate) enum SerializedComponentStorage { + Single(Option>), + Multiple(Vec)>>), + MultipleGroups(Vec<(GroupHandle, Vec)>>)>), +} + /// Helper to serialize [Components](crate::Component) and [States](crate::State) of a [Scene] pub struct SceneSerializer<'a> { components: &'a ComponentManager, global_states: &'a StateManager, scene_states: &'a StateManager, - ser_components: FxHashMap)>>)>>, + ser_components: FxHashMap, ser_scene_states: FxHashMap>, ser_global_states: FxHashMap>, } @@ -43,7 +51,7 @@ impl<'a> SceneSerializer<'a> { pub(crate) fn finish( self, ) -> ( - FxHashMap)>>)>>, + FxHashMap, FxHashMap>, FxHashMap>, ) { @@ -56,12 +64,29 @@ impl<'a> SceneSerializer<'a> { pub fn serialize_components(&mut self) { let ty = self.components.type_ref::(); - let mut group_data = vec![]; - for (group_handle, group) in &ty.groups { - let ser_components = group.components.serialize_components::(); - group_data.push((GroupHandle(group_handle), ser_components)); - } - self.ser_components.insert(C::IDENTIFIER, group_data); + let ser = match &ty.storage { + ComponentTypeStorage::Single { component, .. } => { + let data = if let Some(component) = &component { + bincode::serialize(component.downcast_ref::().unwrap()).ok() + } else { + None + }; + SerializedComponentStorage::Single(data) + } + ComponentTypeStorage::Multiple(multiple) => { + let ser_components = multiple.components.serialize_components::(); + SerializedComponentStorage::Multiple(ser_components) + } + ComponentTypeStorage::MultipleGroups(groups) => { + let mut group_data = vec![]; + for (group_handle, group) in groups { + let ser_components = group.components.serialize_components::(); + group_data.push((GroupHandle(group_handle), ser_components)); + } + SerializedComponentStorage::MultipleGroups(group_data) + } + }; + self.ser_components.insert(C::IDENTIFIER, ser); } pub fn serialize_global_state(&mut self) { @@ -100,7 +125,7 @@ impl SceneCreator for fn create(mut self: Box, shura: &mut Shura) -> Scene { let (mut scene, ser_components, ser_scene_state, ser_global_state): ( Scene, - FxHashMap)>>)>>, + FxHashMap, FxHashMap>, FxHashMap>, ) = bincode::deserialize(&self.scene).unwrap(); @@ -115,14 +140,14 @@ impl SceneCreator for #[derive(serde::Deserialize)] /// Helper to deserialize [Components](crate::Component) and [States](crate::State) of a serialized [Scene] pub struct SceneDeserializer { - ser_components: FxHashMap)>>)>>, + ser_components: FxHashMap, ser_scene_states: FxHashMap>, ser_global_states: FxHashMap>, } impl SceneDeserializer { pub(crate) fn new( - ser_components: FxHashMap)>>)>>, + ser_components: FxHashMap, ser_scene_states: FxHashMap>, ser_global_states: FxHashMap>, ) -> Self { @@ -140,30 +165,73 @@ impl SceneDeserializer { ctx.components.reregister::(); let type_id = C::IDENTIFIER; let ty = ctx.components.type_mut::(); - if let Some(components) = self.ser_components.remove(&type_id) { - for (group_id, components) in components { - let mut items: Vec> = - Vec::with_capacity(components.capacity()); - let mut generation = 0; - for component in components { - let item = match component { - Some((gen, data)) => { - generation = cmp::max(generation, gen); - let component: BoxedComponent = - Box::new(bincode::deserialize::(&data).unwrap()); + if let Some(storage) = self.ser_components.remove(&type_id) { + match storage { + SerializedComponentStorage::Single(single) => match &mut ty.storage { + ComponentTypeStorage::Single { component, .. } => { + if let Some(single) = single { + *component = + Some(Box::new(bincode::deserialize::(&single).unwrap())); + } + } + _ => unreachable!(), + }, + SerializedComponentStorage::Multiple(ser_multiple) => match &mut ty.storage { + ComponentTypeStorage::Multiple(multiple) => { + let mut items: Vec> = + Vec::with_capacity(ser_multiple.capacity()); + let mut generation = 0; + for component in ser_multiple { + let item = match component { + Some((gen, data)) => { + generation = std::cmp::max(generation, gen); + let component: BoxedComponent = + Box::new(bincode::deserialize::(&data).unwrap()); - ArenaEntry::Occupied { - generation: gen, - data: component, - } + ArenaEntry::Occupied { + generation: gen, + data: component, + } + } + None => ArenaEntry::Free { next_free: None }, + }; + items.push(item); } - None => ArenaEntry::Free { next_free: None }, - }; - items.push(item); - } - let components = Arena::from_items(items, generation); - ty.groups[group_id.0].components = components; + let components = Arena::from_items(items, generation); + multiple.components = components; + } + _ => unreachable!(), + }, + SerializedComponentStorage::MultipleGroups(ser_groups) => match &mut ty.storage { + ComponentTypeStorage::MultipleGroups(groups) => { + for (group_id, components) in ser_groups { + let mut items: Vec> = + Vec::with_capacity(components.capacity()); + let mut generation = 0; + for component in components { + let item = match component { + Some((gen, data)) => { + generation = std::cmp::max(generation, gen); + let component: BoxedComponent = + Box::new(bincode::deserialize::(&data).unwrap()); + + ArenaEntry::Occupied { + generation: gen, + data: component, + } + } + None => ArenaEntry::Free { next_free: None }, + }; + items.push(item); + } + + let components = Arena::from_items(items, generation); + groups[group_id.0].components = components; + } + } + _ => unreachable!(), + }, } } } @@ -175,34 +243,81 @@ impl SceneDeserializer { ) { ctx.components.reregister::(); let type_id = C::IDENTIFIER; - if let Some(components) = self.ser_components.remove(&type_id) { - for (group_id, components) in components { - let mut items: Vec> = - Vec::with_capacity(components.capacity()); - let mut generation = 0; - for component in components { - let item = match component { - Some((gen, data)) => { - generation = cmp::max(generation, gen); - let wrapper = DeserializeWrapper::new(&data); - let component: BoxedComponent = Box::new((de)(wrapper, ctx)); - // #[cfg(feature = "physics")] - // if component.base().is_body() { - // component.base_mut().init_body(ctx.components.world.clone()); - // } - ArenaEntry::Occupied { - generation: gen, - data: component, + if let Some(storage) = self.ser_components.remove(&type_id) { + match storage { + SerializedComponentStorage::Single(single) => { + if let Some(single) = single { + let wrapper = DeserializeWrapper::new(&single); + let c: BoxedComponent = Box::new((de)(wrapper, ctx)); + let ty = ctx.components.type_mut::(); + match &mut ty.storage { + ComponentTypeStorage::Single { component, .. } => { + *component = Some(c); } + _ => unreachable!(), } - None => ArenaEntry::Free { next_free: None }, - }; - items.push(item); + } } + SerializedComponentStorage::Multiple(ser_multiple) => { + let mut items: Vec> = + Vec::with_capacity(ser_multiple.capacity()); + let mut generation = 0; + for component in ser_multiple { + let item = match component { + Some((gen, data)) => { + generation = std::cmp::max(generation, gen); + let wrapper = DeserializeWrapper::new(&data); + let component: BoxedComponent = Box::new((de)(wrapper, ctx)); + ArenaEntry::Occupied { + generation: gen, + data: component, + } + } + None => ArenaEntry::Free { next_free: None }, + }; + items.push(item); + } - let ty = ctx.components.type_mut::(); - let components = Arena::from_items(items, generation); - ty.groups[group_id.0].components = components; + let components = Arena::from_items(items, generation); + let ty = ctx.components.type_mut::(); + match &mut ty.storage { + ComponentTypeStorage::Multiple(multiple) => { + multiple.components = components; + } + _ => unreachable!(), + } + } + SerializedComponentStorage::MultipleGroups(ser_groups) => { + for (group_id, components) in ser_groups { + let mut items: Vec> = + Vec::with_capacity(components.capacity()); + let mut generation = 0; + for component in components { + let item = match component { + Some((gen, data)) => { + generation = std::cmp::max(generation, gen); + let wrapper = DeserializeWrapper::new(&data); + let component: BoxedComponent = Box::new((de)(wrapper, ctx)); + ArenaEntry::Occupied { + generation: gen, + data: component, + } + } + None => ArenaEntry::Free { next_free: None }, + }; + items.push(item); + } + + let ty = ctx.components.type_mut::(); + match &mut ty.storage { + ComponentTypeStorage::MultipleGroups(groups) => { + let components = Arena::from_items(items, generation); + groups[group_id.0].components = components; + } + _ => unreachable!(), + } + } + } } } } diff --git a/src/shura.rs b/src/shura.rs index 3ac9374f..1fd7a322 100644 --- a/src/shura.rs +++ b/src/shura.rs @@ -156,16 +156,20 @@ impl ShuraConfig { match update_status { Ok(_) => {} Err(wgpu::SurfaceError::Lost) => { + #[cfg(feature = "log")] + error!("Lost surface!"); let mint: mint::Vector2 = shura.window.inner_size().into(); let window_size: Vector = mint.into(); shura.resize(window_size); } Err(wgpu::SurfaceError::OutOfMemory) => { + #[cfg(feature = "log")] + error!("Not enough memory!"); *control_flow = winit::event_loop::ControlFlow::Exit } Err(_e) => { #[cfg(feature = "log")] - error!("Render Error: {:?}", _e) + error!("Render error: {:?}", _e) } } @@ -439,9 +443,9 @@ impl Shura { }; let now = ctx.frame.update_time(); { - for ((priority, _), type_index) in ctx.components.priorities().borrow().iter() { + for ((_priority, _), type_index) in ctx.components.priorities().borrow().iter() { #[cfg(feature = "physics")] - if !done_step && *priority > physics_priority { + if !done_step && *_priority > physics_priority { done_step = true; Self::physics_step(&mut ctx); } diff --git a/src/sound/audio_manager.rs b/src/sound/audio_manager.rs index 65b29205..c06c2940 100644 --- a/src/sound/audio_manager.rs +++ b/src/sound/audio_manager.rs @@ -1,5 +1,6 @@ use crate::audio::{AudioSink, Sound}; +// Thin wrapper around rodio pub struct AudioManager { pub output_stream: rodio::OutputStream, pub output_handle: rodio::OutputStreamHandle, @@ -14,6 +15,19 @@ impl AudioManager { }; } + pub fn play_once(&self, sound: &Sound) { + self.output_handle + .play_once(std::io::Cursor::new(sound.0)) + .unwrap() + .detach() + } + + pub fn play_once_and(&self, sound: &Sound) -> AudioSink { + self.output_handle + .play_once(std::io::Cursor::new(sound.0)) + .unwrap() + } + pub fn create_sink(&self) -> AudioSink { AudioSink::try_new(&self.output_handle).unwrap() } diff --git a/src/sound/sound.rs b/src/sound/sound.rs index b329bbc8..38084979 100644 --- a/src/sound/sound.rs +++ b/src/sound/sound.rs @@ -1,7 +1,7 @@ use rodio::Decoder; /// Sound ressource which can be loaded from a static source using [include_bytes!](include_bytes!) -pub struct Sound(&'static [u8]); +pub struct Sound(pub &'static [u8]); impl Sound { pub fn new(sound: &'static [u8]) -> Sound {