rust/hwphysics/src/data.rs
author alfadur
Tue, 28 Mar 2023 19:30:57 +0300
changeset 15945 343b8819b051
parent 15942 bcd43b90401a
permissions -rw-r--r--
optimize out allocations in data iterator
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
     1
use super::common::GearId;
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
     2
use std::{
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
     3
    any::TypeId,
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
     4
    fmt::{Debug, Error, Formatter},
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
     5
    marker::PhantomData,
15426
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
     6
    mem::{align_of, size_of, MaybeUninit},
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
     7
    num::NonZeroU16,
15368
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
     8
    ptr::{copy_nonoverlapping, null_mut, NonNull},
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
     9
    slice,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    10
};
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    11
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    12
const MAX_TYPES: usize = 8;
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    13
15368
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
    14
pub trait TypeTuple: Sized {
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    15
    fn get_types(_types: &mut [TypeId; MAX_TYPES]) -> usize;
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
    16
}
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
    17
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
    18
impl TypeTuple for () {
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    19
    fn get_types(_types: &mut [TypeId; MAX_TYPES]) -> usize {
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    20
        0
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    21
    }
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
    22
}
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
    23
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
    24
impl<T: 'static> TypeTuple for &T {
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    25
    fn get_types(types: &mut [TypeId; MAX_TYPES]) -> usize {
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    26
        if MAX_TYPES > 0 {
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    27
            unsafe {
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    28
                *types.get_unchecked_mut(0) = TypeId::of::<T>();
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    29
            }
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    30
            1
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    31
        } else {
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    32
            0
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    33
        }
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
    34
    }
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
    35
}
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
    36
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
    37
pub trait TypeIter: TypeTuple {
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
    38
    unsafe fn iter<F: FnMut(GearId, Self)>(slices: &[*mut u8], count: usize, f: F);
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    39
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    40
15369
0f2fd8d12734 fix tupo
alfadur
parents: 15368
diff changeset
    41
macro_rules! type_tuple_impl {
0f2fd8d12734 fix tupo
alfadur
parents: 15368
diff changeset
    42
    ($($n: literal: $t: ident),+) => {
0f2fd8d12734 fix tupo
alfadur
parents: 15368
diff changeset
    43
        impl<$($t: 'static),+> TypeTuple for ($(&$t),+,) {
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    44
            fn get_types(types: &mut [TypeId; MAX_TYPES]) -> usize {
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    45
                let mut count = 0;
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    46
                $({
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    47
                    if MAX_TYPES > $n {
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    48
                        unsafe {
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    49
                            *types.get_unchecked_mut($n) = TypeId::of::<$t>();
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    50
                        }
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    51
                        count = $n + 1;
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    52
                    }
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    53
                });+
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    54
                count
15368
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
    55
            }
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
    56
        }
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    57
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
    58
        impl<$($t: 'static),+> TypeIter for ($(&$t),+,) {
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    59
            unsafe fn iter<FI: FnMut(GearId, Self)>(slices: &[*mut u8], count: usize, mut f: FI) {
15368
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
    60
                for i in 0..count {
15380
6e3e5be8b2e2 update hwphysics motion to use the new system
alfadur
parents: 15379
diff changeset
    61
                    f(*(*slices.get_unchecked(0) as *const GearId).add(i),
6e3e5be8b2e2 update hwphysics motion to use the new system
alfadur
parents: 15379
diff changeset
    62
                      ($(&*(*slices.get_unchecked($n + 1) as *mut $t).add(i)),+,));
15368
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
    63
                }
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
    64
            }
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
    65
        }
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    66
15369
0f2fd8d12734 fix tupo
alfadur
parents: 15368
diff changeset
    67
        impl<$($t: 'static),+> TypeTuple for ($(&mut $t),+,) {
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    68
            fn get_types(types: &mut [TypeId; MAX_TYPES]) -> usize {
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    69
                let mut count = 0;
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    70
                $({
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    71
                    if MAX_TYPES > $n {
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    72
                        unsafe {
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    73
                            *types.get_unchecked_mut($n) = TypeId::of::<$t>();
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    74
                        }
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    75
                        count = $n + 1;
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    76
                    }
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    77
                });+
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    78
                count
15368
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
    79
            }
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
    80
        }
15368
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
    81
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
    82
        impl<$($t: 'static),+> TypeIter for ($(&mut $t),+,) {
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    83
            unsafe fn iter<FI: FnMut(GearId, Self)>(slices: &[*mut u8], count: usize, mut f: FI) {
15368
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
    84
                for i in 0..count {
15380
6e3e5be8b2e2 update hwphysics motion to use the new system
alfadur
parents: 15379
diff changeset
    85
                    f(*(*slices.get_unchecked(0) as *const GearId).add(i),
6e3e5be8b2e2 update hwphysics motion to use the new system
alfadur
parents: 15379
diff changeset
    86
                      ($(&mut *(*slices.get_unchecked($n + 1) as *mut $t).add(i)),+,));
15368
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
    87
                }
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
    88
            }
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    89
        }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
    90
    }
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    91
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    92
15369
0f2fd8d12734 fix tupo
alfadur
parents: 15368
diff changeset
    93
type_tuple_impl!(0: A);
0f2fd8d12734 fix tupo
alfadur
parents: 15368
diff changeset
    94
type_tuple_impl!(0: A, 1: B);
0f2fd8d12734 fix tupo
alfadur
parents: 15368
diff changeset
    95
type_tuple_impl!(0: A, 1: B, 2: C);
0f2fd8d12734 fix tupo
alfadur
parents: 15368
diff changeset
    96
type_tuple_impl!(0: A, 1: B, 2: C, 3: D);
0f2fd8d12734 fix tupo
alfadur
parents: 15368
diff changeset
    97
type_tuple_impl!(0: A, 1: B, 2: C, 3: D, 4: E);
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    98
type_tuple_impl!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F);
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
    99
type_tuple_impl!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G);
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   100
type_tuple_impl!(0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G, 7: H);
15368
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
   101
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   102
const BLOCK_SIZE: usize = 32768;
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   103
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   104
struct DataBlock {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   105
    max_elements: u16,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   106
    elements_count: u16,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   107
    data: Box<[u8; BLOCK_SIZE]>,
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   108
    component_blocks: [Option<NonNull<u8>>; 64],
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   109
    element_sizes: Box<[u16]>,
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   110
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   111
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   112
impl Unpin for DataBlock {}
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   113
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   114
impl Debug for DataBlock {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   115
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   116
        write!(
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   117
            f,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   118
            "Block ({}/{}) {{\n",
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   119
            self.elements_count, self.max_elements
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   120
        )?;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   121
        write!(f, "\tIDs: [")?;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   122
        let id_slice = unsafe {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   123
            slice::from_raw_parts(
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   124
                self.data.as_ptr() as *const GearId,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   125
                self.elements_count as usize,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   126
            )
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   127
        };
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   128
        for gear_id in id_slice {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   129
            write!(f, "{}, ", gear_id)?;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   130
        }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   131
        write!(f, "]\n")?;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   132
        for type_index in 0..self.element_sizes.len() {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   133
            if let Some(ptr) = self.component_blocks[type_index] {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   134
                write!(f, "\tC{}: [", type_index)?;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   135
                let slice = unsafe {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   136
                    slice::from_raw_parts(
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   137
                        ptr.as_ptr(),
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   138
                        (self.elements_count * self.element_sizes[type_index]) as usize,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   139
                    )
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   140
                };
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   141
                for byte in slice {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   142
                    write!(f, "{}, ", byte)?;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   143
                }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   144
                write!(f, "]\n")?;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   145
            }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   146
        }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   147
        write!(f, "}}\n")
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   148
    }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   149
}
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   150
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   151
impl DataBlock {
15426
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   152
    fn new(mask: u64, element_sizes: &[u16], element_alignments: &[u8]) -> Self {
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   153
        let total_padding: usize = element_alignments.iter().map(|x| *x as usize).sum();
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   154
        let total_size: u16 = element_sizes
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   155
            .iter()
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   156
            .enumerate()
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   157
            .filter(|(i, _)| mask & (1 << *i as u64) != 0)
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   158
            .map(|(_, size)| *size)
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   159
            .sum();
15426
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   160
        let max_elements =
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   161
            ((BLOCK_SIZE - total_padding) / (total_size as usize + size_of::<GearId>())) as u16;
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   162
15426
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   163
        //ensure the block memory is aligned to GearId
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   164
        let tmp_data: Box<[GearId; BLOCK_SIZE / size_of::<GearId>()]> =
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   165
            Box::new(unsafe { MaybeUninit::uninit().assume_init() });
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   166
        let mut data: Box<[u8; BLOCK_SIZE]> =
15426
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   167
            unsafe { Box::from_raw(Box::into_raw(tmp_data) as *mut [u8; BLOCK_SIZE]) };
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   168
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   169
        let mut blocks = [None; 64];
15426
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   170
        let mut address = unsafe {
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   171
            data.as_mut_ptr()
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   172
                .add(size_of::<GearId>() * max_elements as usize)
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   173
        };
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   174
15941
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   175
        let mut mask_bits = mask;
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   176
        while mask_bits != 0 {
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   177
            let i = mask_bits.trailing_zeros() as usize;
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   178
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   179
            unsafe {
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   180
                address = address.add(address.align_offset(element_alignments[i] as usize));
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   181
                blocks[i] = Some(NonNull::new_unchecked(address));
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   182
                address = address.add(element_sizes[i] as usize * max_elements as usize)
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   183
            };
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   184
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   185
            mask_bits &= mask_bits - 1;
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   186
        }
15426
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   187
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   188
        Self {
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   189
            elements_count: 0,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   190
            max_elements,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   191
            data,
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   192
            component_blocks: blocks,
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   193
            element_sizes: Box::from(element_sizes),
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   194
        }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   195
    }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   196
15941
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   197
    #[inline]
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   198
    fn gear_ids(&self) -> &[GearId] {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   199
        unsafe {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   200
            slice::from_raw_parts(
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   201
                self.data.as_ptr() as *const GearId,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   202
                self.max_elements as usize,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   203
            )
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   204
        }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   205
    }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   206
15941
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   207
    #[inline]
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   208
    fn gear_ids_mut(&mut self) -> &mut [GearId] {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   209
        unsafe {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   210
            slice::from_raw_parts_mut(
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   211
                self.data.as_mut_ptr() as *mut GearId,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   212
                self.max_elements as usize,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   213
            )
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   214
        }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   215
    }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   216
15941
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   217
    #[inline]
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   218
    fn is_full(&self) -> bool {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   219
        self.elements_count == self.max_elements
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   220
    }
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   221
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   222
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   223
#[derive(Clone, Copy, Debug, Default)]
15379
27915135f87f allow iterating with gear id
alfadur
parents: 15375
diff changeset
   224
struct LookupEntry {
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   225
    index: Option<NonZeroU16>,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   226
    block_index: u16,
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   227
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   228
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   229
impl LookupEntry {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   230
    fn new(block_index: u16, index: u16) -> Self {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   231
        Self {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   232
            index: unsafe { Some(NonZeroU16::new_unchecked(index + 1)) },
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   233
            block_index,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   234
        }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   235
    }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   236
}
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   237
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   238
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   239
struct BlockMask {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   240
    type_mask: u64,
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   241
    tag_mask: u64,
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   242
}
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   243
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   244
impl BlockMask {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   245
    #[inline]
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   246
    fn new(type_mask: u64, tag_mask: u64) -> Self {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   247
        Self {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   248
            type_mask,
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   249
            tag_mask,
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   250
        }
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   251
    }
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   252
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   253
    #[inline]
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   254
    fn with_type(&self, type_bit: u64) -> Self {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   255
        Self::new(self.type_mask | type_bit, self.tag_mask)
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   256
    }
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   257
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   258
    #[inline]
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   259
    fn without_type(&self, type_bit: u64) -> Self {
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   260
        Self::new(self.type_mask & !type_bit, self.tag_mask)
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   261
    }
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   262
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   263
    #[inline]
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   264
    fn with_tag(&self, tag_bit: u64) -> Self {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   265
        Self::new(self.type_mask, self.tag_mask | tag_bit)
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   266
    }
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   267
}
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   268
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   269
pub struct GearDataManager {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   270
    types: Vec<TypeId>,
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   271
    tags: Vec<TypeId>,
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   272
    blocks: Vec<DataBlock>,
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   273
    block_masks: Vec<BlockMask>,
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   274
    element_sizes: Box<[u16; 64]>,
15426
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   275
    element_alignments: Box<[u8; 64]>,
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   276
    lookup: Box<[LookupEntry]>,
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   277
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   278
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   279
impl GearDataManager {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   280
    pub fn new() -> Self {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   281
        Self {
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   282
            types: Vec::with_capacity(64),
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   283
            tags: Vec::with_capacity(64),
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   284
            blocks: vec![],
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   285
            block_masks: vec![],
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   286
            element_sizes: Box::new([0; 64]),
15426
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   287
            element_alignments: Box::new([0; 64]),
15829
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   288
            lookup: vec![LookupEntry::default(); u16::MAX as usize].into_boxed_slice(),
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   289
        }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   290
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   291
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   292
    #[inline]
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   293
    fn get_type_index<T: 'static>(&self) -> Option<usize> {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   294
        let type_id = TypeId::of::<T>();
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   295
        self.types.iter().position(|id| *id == type_id)
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   296
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   297
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   298
    #[inline]
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   299
    fn get_tag_index<T: 'static>(&self) -> Option<usize> {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   300
        let type_id = TypeId::of::<T>();
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   301
        self.tags.iter().position(|id| *id == type_id)
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   302
    }
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   303
15395
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   304
    fn move_between_blocks(
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   305
        &mut self,
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   306
        src_block_index: u16,
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   307
        src_index: u16,
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   308
        dest_block_index: u16,
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   309
    ) -> u16 {
15373
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15372
diff changeset
   310
        debug_assert!(src_block_index != dest_block_index);
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15372
diff changeset
   311
        let src_mask = self.block_masks[src_block_index as usize];
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15372
diff changeset
   312
        let dest_mask = self.block_masks[dest_block_index as usize];
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   313
        debug_assert!(src_mask.type_mask & dest_mask.type_mask != 0);
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   314
15373
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15372
diff changeset
   315
        let src_block = &self.blocks[src_block_index as usize];
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15372
diff changeset
   316
        let dest_block = &self.blocks[dest_block_index as usize];
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15372
diff changeset
   317
        debug_assert!(src_index < src_block.elements_count);
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15372
diff changeset
   318
        debug_assert!(!dest_block.is_full());
15357
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   319
15373
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15372
diff changeset
   320
        let dest_index = dest_block.elements_count;
15941
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   321
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   322
        let mut type_mask = src_mask.type_mask;
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   323
        while type_mask != 0 {
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   324
            let i = type_mask.trailing_zeros() as usize;
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   325
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   326
            let size = self.element_sizes[i];
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   327
            let src_ptr = src_block.component_blocks[i].unwrap().as_ptr();
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   328
            if let Some(dest_ptr) = dest_block.component_blocks[i] {
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   329
                let dest_ptr = dest_ptr.as_ptr();
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   330
                unsafe {
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   331
                    copy_nonoverlapping(
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   332
                        src_ptr.add((src_index * size) as usize),
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   333
                        dest_ptr.add((dest_index * size) as usize),
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   334
                        size as usize,
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   335
                    );
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   336
                }
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   337
            }
15941
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   338
            unsafe {
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   339
                if src_index < src_block.elements_count - 1 {
15357
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   340
                    copy_nonoverlapping(
15941
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   341
                        src_ptr.add((size * (src_block.elements_count - 1)) as usize),
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   342
                        src_ptr.add((size * src_index) as usize),
15373
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15372
diff changeset
   343
                        size as usize,
15357
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   344
                    );
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   345
                }
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   346
            }
15941
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   347
8035f7452b48 optimize type mask iteration
alfadur
parents: 15829
diff changeset
   348
            type_mask &= type_mask - 1;
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   349
        }
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   350
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   351
        let src_block = &mut self.blocks[src_block_index as usize];
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   352
        let gear_id = src_block.gear_ids()[src_index as usize];
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   353
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   354
        if src_index + 1 < src_block.elements_count {
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   355
            let relocated_index = src_block.elements_count as usize - 1;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   356
            let gear_ids = src_block.gear_ids_mut();
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   357
            let relocated_id = gear_ids[relocated_index];
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   358
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   359
            gear_ids[src_index as usize] = relocated_id;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   360
            self.lookup[relocated_id.get() as usize - 1] =
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   361
                LookupEntry::new(src_block_index, src_index);
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   362
        }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   363
        src_block.elements_count -= 1;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   364
15373
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15372
diff changeset
   365
        let dest_block = &mut self.blocks[dest_block_index as usize];
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   366
        let dest_index = dest_block.elements_count;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   367
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   368
        dest_block.gear_ids_mut()[dest_index as usize] = gear_id;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   369
        self.lookup[gear_id.get() as usize - 1] = LookupEntry::new(dest_block_index, dest_index);
15373
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15372
diff changeset
   370
        dest_block.elements_count += 1;
15395
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   371
        dest_block.elements_count - 1
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   372
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   373
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   374
    fn add_to_block<T: Clone>(&mut self, gear_id: GearId, block_index: u16, value: &T) {
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   375
        debug_assert!(
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   376
            self.block_masks[block_index as usize]
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   377
                .type_mask
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   378
                .count_ones()
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   379
                == 1
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   380
        );
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   381
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   382
        let block = &mut self.blocks[block_index as usize];
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   383
        debug_assert!(block.elements_count < block.max_elements);
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   384
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   385
        unsafe {
15395
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   386
            *(block.component_blocks[0].unwrap().as_ptr() as *mut T)
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   387
                .add(block.elements_count as usize) = value.clone();
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   388
        };
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   389
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   390
        let index = block.elements_count;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   391
        self.lookup[gear_id.get() as usize - 1] = LookupEntry::new(block_index, index);
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   392
        block.gear_ids_mut()[index as usize] = gear_id;
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   393
        block.elements_count += 1;
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   394
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   395
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   396
    fn remove_from_block(&mut self, block_index: u16, index: u16) {
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   397
        let block = &mut self.blocks[block_index as usize];
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   398
        debug_assert!(index < block.elements_count);
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   399
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   400
        for (i, size) in self.element_sizes.iter().cloned().enumerate() {
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   401
            if index < block.elements_count - 1 {
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   402
                if let Some(ptr) = block.component_blocks[i] {
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   403
                    unsafe {
15357
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   404
                        copy_nonoverlapping(
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   405
                            ptr.as_ptr()
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   406
                                .add((size * (block.elements_count - 1)) as usize),
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   407
                            ptr.as_ptr().add((size * index) as usize),
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   408
                            size as usize,
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   409
                        );
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   410
                    }
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   411
                }
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   412
            }
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   413
        }
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   414
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   415
        self.lookup[block.gear_ids()[index as usize].get() as usize - 1] = LookupEntry::default();
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   416
        if index < block.elements_count - 1 {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   417
            let relocated_index = block.elements_count as usize - 1;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   418
            let gear_ids = block.gear_ids_mut();
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   419
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   420
            gear_ids[index as usize] = gear_ids[relocated_index];
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   421
            self.lookup[gear_ids[relocated_index].get() as usize - 1] =
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   422
                LookupEntry::new(block_index, index);
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   423
        }
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   424
        block.elements_count -= 1;
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   425
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   426
15395
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   427
    fn write_component<T: Clone>(
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   428
        &mut self,
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   429
        block_index: u16,
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   430
        index: u16,
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   431
        type_index: usize,
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   432
        value: &T,
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   433
    ) {
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   434
        debug_assert!(type_index < self.types.len());
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   435
        let block = &mut self.blocks[block_index as usize];
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   436
        debug_assert!(index < block.elements_count);
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   437
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   438
        unsafe {
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   439
            *(block.component_blocks[type_index].unwrap().as_ptr() as *mut T).add(index as usize) =
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   440
                value.clone();
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   441
        };
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   442
    }
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   443
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   444
    #[inline]
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   445
    fn ensure_block(&mut self, mask: BlockMask) -> u16 {
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   446
        if let Some(index) = self
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   447
            .block_masks
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   448
            .iter()
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   449
            .enumerate()
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   450
            .position(|(i, m)| *m == mask && !self.blocks[i].is_full())
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   451
        {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   452
            index as u16
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   453
        } else {
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   454
            self.blocks.push(DataBlock::new(
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   455
                mask.type_mask,
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   456
                &self.element_sizes[0..self.types.len()],
15426
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   457
                &self.element_alignments[0..self.types.len()],
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   458
            ));
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   459
            self.block_masks.push(mask);
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   460
            (self.blocks.len() - 1) as u16
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   461
        }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   462
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   463
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   464
    pub fn add<T: Clone + 'static>(&mut self, gear_id: GearId, value: &T) {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   465
        if let Some(type_index) = self.get_type_index::<T>() {
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   466
            let type_bit = 1 << type_index as u64;
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   467
            let entry = self.lookup[gear_id.get() as usize - 1];
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   468
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   469
            if let Some(index) = entry.index {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   470
                let mask = self.block_masks[entry.block_index as usize];
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   471
                let new_mask = mask.with_type(type_bit);
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   472
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   473
                if new_mask != mask {
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   474
                    let dest_block_index = self.ensure_block(new_mask);
15395
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   475
                    let dest_index = self.move_between_blocks(
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   476
                        entry.block_index,
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   477
                        index.get() - 1,
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   478
                        dest_block_index,
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   479
                    );
a87b5e16b863 save data for blocks with more than a single component
alfadur
parents: 15393
diff changeset
   480
                    self.write_component(dest_block_index, dest_index, type_index, value);
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   481
                }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   482
            } else {
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   483
                let dest_block_index = self.ensure_block(BlockMask::new(type_bit, 0));
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   484
                self.add_to_block(gear_id, dest_block_index, value);
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   485
            }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   486
        } else {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   487
            panic!("Unregistered type")
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   488
        }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   489
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   490
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   491
    pub fn add_tag<T: 'static>(&mut self, gear_id: GearId) {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   492
        if let Some(tag_index) = self.get_tag_index::<T>() {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   493
            let tag_bit = 1 << tag_index as u64;
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   494
            let entry = self.lookup[gear_id.get() as usize - 1];
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   495
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   496
            if let Some(index) = entry.index {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   497
                let mask = self.block_masks[entry.block_index as usize];
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   498
                let new_mask = mask.with_tag(tag_bit);
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   499
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   500
                if new_mask != mask {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   501
                    let dest_block_index = self.ensure_block(new_mask);
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   502
                    self.move_between_blocks(entry.block_index, index.get() - 1, dest_block_index);
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   503
                }
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   504
            } else {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   505
                panic!("Cannot tag a gear with no data")
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   506
            }
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   507
        } else {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   508
            panic!("Unregistered tag")
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   509
        }
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   510
    }
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   511
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   512
    pub fn remove<T: 'static>(&mut self, gear_id: GearId) {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   513
        if let Some(type_index) = self.get_type_index::<T>() {
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   514
            let type_bit = 1 << type_index as u64;
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   515
            let entry = self.lookup[gear_id.get() as usize - 1];
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   516
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   517
            if let Some(index) = entry.index {
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   518
                let mask = self.block_masks[entry.block_index as usize];
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   519
                let new_mask = mask.without_type(type_bit);
15357
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   520
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   521
                if new_mask != mask {
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   522
                    if new_mask.type_mask == 0 {
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   523
                        self.remove_from_block(entry.block_index, index.get() - 1);
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   524
                    } else {
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   525
                        let dest_block_index = self.ensure_block(new_mask);
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   526
                        self.move_between_blocks(
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   527
                            entry.block_index,
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   528
                            index.get() - 1,
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   529
                            dest_block_index,
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   530
                        );
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   531
                    }
15357
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   532
                }
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   533
            }
15357
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   534
        } else {
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   535
            panic!("Unregistered type")
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   536
        }
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   537
    }
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   538
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   539
    pub fn remove_all(&mut self, gear_id: GearId) {
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   540
        let entry = self.lookup[gear_id.get() as usize - 1];
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   541
        if let Some(index) = entry.index {
135c29237a56 implement moving between blocks
alfadur
parents: 15356
diff changeset
   542
            self.remove_from_block(entry.block_index, index.get() - 1);
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   543
        }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   544
    }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   545
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   546
    pub fn register<T: 'static>(&mut self) {
15356
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15354
diff changeset
   547
        debug_assert!(!std::mem::needs_drop::<T>());
15829
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   548
        debug_assert!(size_of::<T>() <= u16::MAX as usize);
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   549
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   550
        let id = TypeId::of::<T>();
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   551
        if size_of::<T>() == 0 {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   552
            if !self.tags.contains(&id) {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   553
                debug_assert!(self.tags.len() <= 64);
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   554
                self.tags.push(id)
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   555
            }
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   556
        } else {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   557
            if !self.types.contains(&id) {
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   558
                debug_assert!(self.types.len() <= 64);
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   559
                self.element_sizes[self.types.len()] = size_of::<T>() as u16;
15426
a027e60d7820 fix alignments of the component slices
alfadur
parents: 15395
diff changeset
   560
                self.element_alignments[self.types.len()] = align_of::<T>() as u8;
15387
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   561
                self.types.push(id);
90a79670de52 allow registering zero-sized types
alfadur
parents: 15381
diff changeset
   562
            }
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   563
        }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   564
    }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   565
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   566
    fn run_impl<T: TypeIter + 'static, F: FnMut(GearId, T)>(
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   567
        &mut self,
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   568
        type_selector: u64,
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   569
        included_tags: u64,
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   570
        type_indices: &[i8],
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   571
        mut f: F,
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   572
    ) {
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   573
        let mut slices = [null_mut(); MAX_TYPES + 1];
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   574
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   575
        for (block_index, mask) in self.block_masks.iter().enumerate() {
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   576
            if mask.type_mask & type_selector == type_selector
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   577
                && mask.tag_mask & included_tags == included_tags
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   578
            {
15379
27915135f87f allow iterating with gear id
alfadur
parents: 15375
diff changeset
   579
                let block = &mut self.blocks[block_index];
27915135f87f allow iterating with gear id
alfadur
parents: 15375
diff changeset
   580
                slices[0] = block.data.as_mut_ptr();
27915135f87f allow iterating with gear id
alfadur
parents: 15375
diff changeset
   581
15367
d6b4586b271f make sure component slice order corresponds to the type args
alfadur
parents: 15358
diff changeset
   582
                for (arg_index, type_index) in type_indices.iter().cloned().enumerate() {
15379
27915135f87f allow iterating with gear id
alfadur
parents: 15375
diff changeset
   583
                    slices[arg_index as usize + 1] = block.component_blocks[type_index as usize]
15368
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
   584
                        .unwrap()
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
   585
                        .as_ptr()
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   586
                }
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   587
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   588
                unsafe {
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   589
                    T::iter(
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   590
                        &slices[0..=type_indices.len()],
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   591
                        block.elements_count as usize,
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   592
                        |id, x| f(id, x),
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   593
                    );
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   594
                }
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   595
            }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   596
        }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   597
    }
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   598
15829
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   599
    pub fn get<T: 'static>(&self, gear_id: GearId) -> Option<&T> {
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   600
        let entry = self.lookup[gear_id.get() as usize - 1];
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   601
        match (entry.index, self.get_type_index::<T>()) {
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   602
            (Some(index), Some(type_index)) => {
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   603
                let block = &self.blocks[entry.block_index as usize];
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   604
                block.component_blocks[type_index].map(|ptr| unsafe {
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   605
                    &*(ptr.as_ptr() as *const T).add(index.get() as usize - 1)
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   606
                })
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   607
            }
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   608
            _ => None,
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   609
        }
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   610
    }
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   611
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   612
    pub fn iter<T: TypeIter + 'static>(&mut self) -> DataIterator<T> {
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   613
        let mut arg_types: [TypeId; MAX_TYPES] = unsafe { MaybeUninit::uninit().assume_init() };
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   614
        let types_count = T::get_types(&mut arg_types);
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   615
        let mut type_indices = [-1; MAX_TYPES];
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   616
        let mut selector = 0u64;
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   617
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   618
        for (arg_index, type_id) in arg_types[0..types_count].iter().enumerate() {
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   619
            match self.types.iter().position(|t| t == type_id) {
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   620
                Some(i) if selector & (1 << i as u64) != 0 => panic!("Duplicate type"),
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   621
                Some(i) => {
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   622
                    type_indices[arg_index] = i as i8;
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   623
                    selector |= 1 << i as u64;
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   624
                }
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   625
                None => panic!("Unregistered type"),
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   626
            }
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   627
        }
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   628
        DataIterator::new(self, selector, type_indices)
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   629
    }
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   630
}
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   631
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   632
pub struct DataIterator<'a, T> {
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   633
    data: &'a mut GearDataManager,
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   634
    types: u64,
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   635
    type_indices: [i8; MAX_TYPES],
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   636
    tags: u64,
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   637
    phantom_types: PhantomData<T>,
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   638
}
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   639
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   640
impl<'a, T: TypeIter + 'static> DataIterator<'a, T> {
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   641
    fn new(
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   642
        data: &'a mut GearDataManager,
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   643
        types: u64,
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   644
        type_indices: [i8; MAX_TYPES],
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   645
    ) -> DataIterator<'a, T> {
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   646
        Self {
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   647
            data,
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   648
            types,
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   649
            type_indices,
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   650
            tags: 0,
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   651
            phantom_types: PhantomData,
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   652
        }
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   653
    }
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   654
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   655
    pub fn with_tags<U: TypeTuple + 'static>(self) -> Self {
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   656
        let mut tag_types: [TypeId; MAX_TYPES] = unsafe { MaybeUninit::uninit().assume_init() };
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   657
        let tags_count = U::get_types(&mut tag_types);
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   658
        let mut tags = 0;
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   659
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   660
        for (i, tag) in self.data.tags.iter().enumerate() {
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   661
            if tag_types[0..tags_count].contains(tag) {
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   662
                tags |= 1 << i as u64;
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   663
            }
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   664
        }
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   665
        Self { tags, ..self }
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   666
    }
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   667
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   668
    #[inline]
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   669
    pub fn run<F: FnMut(T)>(&mut self, mut f: F) {
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   670
        self.run_id(|_, x| f(x))
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   671
    }
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   672
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   673
    #[inline]
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   674
    pub fn run_id<F: FnMut(GearId, T)>(&mut self, f: F) {
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   675
        let types_count = self
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   676
            .type_indices
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   677
            .iter()
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   678
            .position(|i| *i == -1)
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   679
            .unwrap_or(self.type_indices.len());
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   680
        self.data
15945
343b8819b051 optimize out allocations in data iterator
alfadur
parents: 15942
diff changeset
   681
            .run_impl(self.types, self.tags, &self.type_indices[0..types_count], f);
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   682
    }
15305
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   683
}
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   684
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   685
#[cfg(test)]
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   686
mod test {
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   687
    use super::{super::common::GearId, GearDataManager};
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   688
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   689
    #[derive(Clone)]
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   690
    struct DatumA {
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   691
        value: u32,
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   692
    }
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   693
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   694
    #[derive(Clone)]
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   695
    struct DatumB {
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   696
        value: u32,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   697
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   698
15371
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15369
diff changeset
   699
    #[derive(Clone)]
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   700
    struct Tag;
15371
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15369
diff changeset
   701
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   702
    #[test]
15829
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   703
    fn direct_access() {
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   704
        let mut manager = GearDataManager::new();
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   705
        manager.register::<DatumA>();
15829
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   706
        for i in 1..=5 {
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   707
            manager.add(GearId::new(i as u16).unwrap(), &DatumA { value: i * i });
15829
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   708
        }
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   709
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   710
        for i in 1..=5 {
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   711
            assert_eq!(
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   712
                manager
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   713
                    .get::<DatumA>(GearId::new(i as u16).unwrap())
15829
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   714
                    .unwrap()
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   715
                    .value,
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   716
                i * i
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   717
            );
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   718
        }
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   719
    }
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   720
d5e6c8c92d87 add direct access to gear data
alfadur
parents: 15426
diff changeset
   721
    #[test]
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   722
    fn single_component_iteration() {
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   723
        let mut manager = GearDataManager::new();
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   724
        manager.register::<DatumA>();
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   725
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   726
        for i in 1..=5 {
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   727
            manager.add(GearId::new(i as u16).unwrap(), &DatumA { value: i });
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   728
        }
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   729
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   730
        let mut sum = 0;
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   731
        manager.iter().run(|(d,): (&DatumA,)| sum += d.value);
15368
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
   732
        assert_eq!(sum, 15);
15358
b5e0a39856fd complete basic ecs
alfadur
parents: 15357
diff changeset
   733
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   734
        manager.iter().run(|(d,): (&mut DatumA,)| d.value += 1);
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   735
        manager.iter().run(|(d,): (&DatumA,)| sum += d.value);
15368
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15367
diff changeset
   736
        assert_eq!(sum, 35);
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   737
    }
15371
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15369
diff changeset
   738
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15369
diff changeset
   739
    #[test]
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   740
    fn tagged_component_iteration() {
15371
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15369
diff changeset
   741
        let mut manager = GearDataManager::new();
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   742
        manager.register::<DatumA>();
15371
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15369
diff changeset
   743
        manager.register::<Tag>();
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   744
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   745
        for i in 1..=10 {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   746
            let gear_id = GearId::new(i as u16).unwrap();
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   747
            manager.add(gear_id, &DatumA { value: i });
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   748
        }
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   749
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   750
        for i in (2..=10).step_by(2) {
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   751
            let gear_id = GearId::new(i as u16).unwrap();
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   752
            manager.add_tag::<Tag>(gear_id);
15371
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15369
diff changeset
   753
        }
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15369
diff changeset
   754
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   755
        let mut sum = 0;
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   756
        manager.iter().run(|(d,): (&DatumA,)| sum += d.value);
15375
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   757
        assert_eq!(sum, 55);
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15373
diff changeset
   758
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   759
        let mut tag_sum = 0;
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   760
        manager
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   761
            .iter()
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   762
            .with_tags::<&Tag>()
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   763
            .run(|(d,): (&DatumA,)| tag_sum += d.value);
15392
b387a51705ac implement iteration with tags
alfadur
parents: 15387
diff changeset
   764
        assert_eq!(tag_sum, 30);
15371
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15369
diff changeset
   765
    }
15942
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   766
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   767
    #[test]
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   768
    fn removal() {
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   769
        let mut manager = GearDataManager::new();
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   770
        manager.register::<DatumA>();
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   771
        manager.register::<DatumB>();
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   772
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   773
        for i in 1..=10 {
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   774
            let gear_id = GearId::new(i as u16).unwrap();
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   775
            manager.add(gear_id, &DatumA { value: i });
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   776
            manager.add(gear_id, &DatumB { value: i });
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   777
        }
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   778
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   779
        for i in (1..=10).step_by(2) {
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   780
            let gear_id = GearId::new(i as u16).unwrap();
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   781
            manager.remove::<DatumA>(gear_id);
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   782
        }
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   783
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   784
        let mut sum_a = 0;
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   785
        manager.iter().run(|(d,): (&DatumA,)| sum_a += d.value);
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   786
        assert_eq!(sum_a, 30);
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   787
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   788
        let mut sum_b = 0;
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   789
        manager.iter().run(|(d,): (&DatumB,)| sum_b += d.value);
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   790
        assert_eq!(sum_b, 55);
bcd43b90401a fix component removal
alfadur
parents: 15941
diff changeset
   791
    }
15354
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15305
diff changeset
   792
}