diff --git a/crates/bevy_mesh/src/index.rs b/crates/bevy_mesh/src/index.rs index 5ec5c993a9..af2b3635ba 100644 --- a/crates/bevy_mesh/src/index.rs +++ b/crates/bevy_mesh/src/index.rs @@ -1,4 +1,5 @@ use bevy_reflect::Reflect; +use core::iter; use core::iter::FusedIterator; use derive_more::derive::{Display, Error}; use wgpu::IndexFormat; @@ -98,6 +99,25 @@ impl Indices { Indices::U32(vec) => vec.is_empty(), } } + + /// Add an index. If the index is greater than `u16::MAX`, + /// the storage will be converted to `u32`. + pub fn push(&mut self, index: u32) { + match self { + Indices::U32(vec) => vec.push(index), + Indices::U16(vec) => match u16::try_from(index) { + Ok(index) => vec.push(index), + Err(_) => { + let new_vec = vec + .iter() + .map(|&index| u32::from(index)) + .chain(iter::once(index)) + .collect::>(); + *self = Indices::U32(new_vec); + } + }, + } + } } /// An Iterator for the [`Indices`]. @@ -135,3 +155,30 @@ impl From<&Indices> for IndexFormat { } } } + +#[cfg(test)] +mod tests { + use crate::Indices; + use wgpu::IndexFormat; + + #[test] + fn test_indices_push() { + let mut indices = Indices::U16(Vec::new()); + indices.push(10); + assert_eq!(IndexFormat::Uint16, IndexFormat::from(&indices)); + assert_eq!(vec![10], indices.iter().collect::>()); + + // Add a value that is too large for `u16` so the storage should be converted to `U32`. + indices.push(0x10000); + assert_eq!(IndexFormat::Uint32, IndexFormat::from(&indices)); + assert_eq!(vec![10, 0x10000], indices.iter().collect::>()); + + indices.push(20); + indices.push(0x20000); + assert_eq!(IndexFormat::Uint32, IndexFormat::from(&indices)); + assert_eq!( + vec![10, 0x10000, 20, 0x20000], + indices.iter().collect::>() + ); + } +}