rust/hwphysics/src/data.rs
author alfadur
Wed, 28 Aug 2019 23:06:34 +0300
changeset 15401 6e3e5be8b2e2
parent 15400 27915135f87f
child 15402 52844baced17
permissions -rw-r--r--
update hwphysics motion to use the new system
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
     1
use super::common::GearId;
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
     2
use std::{
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
     3
    any::TypeId,
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
     4
    fmt::{Debug, Error, Formatter},
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
     5
    io::Write,
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
     6
    mem::{size_of, MaybeUninit},
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
     7
    num::NonZeroU16,
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
     8
    ptr::{copy_nonoverlapping, null_mut, NonNull},
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
     9
    slice,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
    10
};
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    11
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
    12
pub trait TypeTuple: Sized {
15394
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
    13
    fn get_types(types: &mut Vec<TypeId>);
15400
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
    14
    unsafe fn iter<F: FnMut(GearId, Self)>(slices: &[*mut u8], count: usize, mut f: F);
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    15
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    16
15390
0f2fd8d12734 fix tupo
alfadur
parents: 15389
diff changeset
    17
macro_rules! type_tuple_impl {
0f2fd8d12734 fix tupo
alfadur
parents: 15389
diff changeset
    18
    ($($n: literal: $t: ident),+) => {
0f2fd8d12734 fix tupo
alfadur
parents: 15389
diff changeset
    19
        impl<$($t: 'static),+> TypeTuple for ($(&$t),+,) {
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
    20
            fn get_types(types: &mut Vec<TypeId>) {
15390
0f2fd8d12734 fix tupo
alfadur
parents: 15389
diff changeset
    21
                $(types.push(TypeId::of::<$t>()));+
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
    22
            }
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    23
15400
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
    24
            unsafe fn iter<F: FnMut(GearId, Self)>(slices: &[*mut u8], count: usize, mut f: F) {
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
    25
                for i in 0..count {
15401
6e3e5be8b2e2 update hwphysics motion to use the new system
alfadur
parents: 15400
diff changeset
    26
                    f(*(*slices.get_unchecked(0) as *const GearId).add(i),
6e3e5be8b2e2 update hwphysics motion to use the new system
alfadur
parents: 15400
diff changeset
    27
                      ($(&*(*slices.get_unchecked($n + 1) as *mut $t).add(i)),+,));
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
    28
                }
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
    29
            }
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
    30
        }
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
    31
15390
0f2fd8d12734 fix tupo
alfadur
parents: 15389
diff changeset
    32
        impl<$($t: 'static),+> TypeTuple for ($(&mut $t),+,) {
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
    33
            fn get_types(types: &mut Vec<TypeId>) {
15390
0f2fd8d12734 fix tupo
alfadur
parents: 15389
diff changeset
    34
                $(types.push(TypeId::of::<$t>()));+
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
    35
            }
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
    36
15400
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
    37
            unsafe fn iter<F: FnMut(GearId, Self)>(slices: &[*mut u8], count: usize, mut f: F) {
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
    38
                for i in 0..count {
15401
6e3e5be8b2e2 update hwphysics motion to use the new system
alfadur
parents: 15400
diff changeset
    39
                    f(*(*slices.get_unchecked(0) as *const GearId).add(i),
6e3e5be8b2e2 update hwphysics motion to use the new system
alfadur
parents: 15400
diff changeset
    40
                      ($(&mut *(*slices.get_unchecked($n + 1) as *mut $t).add(i)),+,));
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
    41
                }
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
    42
            }
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
    43
        }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
    44
    }
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    45
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    46
15390
0f2fd8d12734 fix tupo
alfadur
parents: 15389
diff changeset
    47
type_tuple_impl!(0: A);
0f2fd8d12734 fix tupo
alfadur
parents: 15389
diff changeset
    48
type_tuple_impl!(0: A, 1: B);
0f2fd8d12734 fix tupo
alfadur
parents: 15389
diff changeset
    49
type_tuple_impl!(0: A, 1: B, 2: C);
0f2fd8d12734 fix tupo
alfadur
parents: 15389
diff changeset
    50
type_tuple_impl!(0: A, 1: B, 2: C, 3: D);
0f2fd8d12734 fix tupo
alfadur
parents: 15389
diff changeset
    51
type_tuple_impl!(0: A, 1: B, 2: C, 3: D, 4: E);
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
    52
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
    53
const BLOCK_SIZE: usize = 32768;
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
    54
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
    55
struct DataBlock {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
    56
    max_elements: u16,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
    57
    elements_count: u16,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
    58
    data: Box<[u8; BLOCK_SIZE]>,
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
    59
    component_blocks: [Option<NonNull<u8>>; 64],
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    60
    element_sizes: Box<[u16]>,
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    61
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
    62
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
    63
impl Unpin for DataBlock {}
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
    64
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    65
impl Debug for DataBlock {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    66
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    67
        write!(
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    68
            f,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    69
            "Block ({}/{}) {{\n",
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    70
            self.elements_count, self.max_elements
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    71
        )?;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    72
        write!(f, "\tIDs: [")?;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    73
        let id_slice = unsafe {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    74
            slice::from_raw_parts(
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    75
                self.data.as_ptr() as *const GearId,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    76
                self.elements_count as usize,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    77
            )
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    78
        };
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    79
        for gear_id in id_slice {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    80
            write!(f, "{}, ", gear_id)?;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    81
        }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    82
        write!(f, "]\n")?;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    83
        for type_index in 0..self.element_sizes.len() {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    84
            if let Some(ptr) = self.component_blocks[type_index] {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    85
                write!(f, "\tC{}: [", type_index)?;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    86
                let slice = unsafe {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    87
                    slice::from_raw_parts(
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    88
                        ptr.as_ptr(),
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    89
                        (self.elements_count * self.element_sizes[type_index]) as usize,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    90
                    )
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    91
                };
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    92
                for byte in slice {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    93
                    write!(f, "{}, ", byte)?;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    94
                }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    95
                write!(f, "]\n")?;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    96
            }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    97
        }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    98
        write!(f, "}}\n")
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
    99
    }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   100
}
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   101
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   102
impl DataBlock {
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   103
    fn new(mask: u64, element_sizes: &[u16]) -> Self {
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   104
        let total_size: u16 = element_sizes
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   105
            .iter()
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   106
            .enumerate()
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   107
            .filter(|(i, _)| mask & (1 << *i as u64) != 0)
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   108
            .map(|(_, size)| *size)
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   109
            .sum();
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   110
        let max_elements = (BLOCK_SIZE / (total_size as usize + size_of::<GearId>())) as u16;
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   111
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   112
        let mut data: Box<[u8; BLOCK_SIZE]> =
15379
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   113
            Box::new(unsafe { MaybeUninit::uninit().assume_init() });
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   114
        let mut blocks = [None; 64];
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   115
        let mut offset = size_of::<GearId>() * max_elements as usize;
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   116
15393
7a3ed957cee9 fix block addition
alfadur
parents: 15392
diff changeset
   117
        for i in 0..element_sizes.len() {
7a3ed957cee9 fix block addition
alfadur
parents: 15392
diff changeset
   118
            if mask & (1 << i as u64) != 0 {
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   119
                blocks[i] = Some(NonNull::new(data[offset..].as_mut_ptr()).unwrap());
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   120
                offset += element_sizes[i] as usize * max_elements as usize;
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   121
            }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   122
        }
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   123
        Self {
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   124
            elements_count: 0,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   125
            max_elements,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   126
            data,
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   127
            component_blocks: blocks,
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   128
            element_sizes: Box::from(element_sizes),
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   129
        }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   130
    }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   131
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   132
    fn gear_ids(&self) -> &[GearId] {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   133
        unsafe {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   134
            slice::from_raw_parts(
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   135
                self.data.as_ptr() as *const GearId,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   136
                self.max_elements as usize,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   137
            )
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   138
        }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   139
    }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   140
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   141
    fn gear_ids_mut(&mut self) -> &mut [GearId] {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   142
        unsafe {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   143
            slice::from_raw_parts_mut(
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   144
                self.data.as_mut_ptr() as *mut GearId,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   145
                self.max_elements as usize,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   146
            )
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   147
        }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   148
    }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   149
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   150
    fn is_full(&self) -> bool {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   151
        self.elements_count == self.max_elements
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   152
    }
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   153
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   154
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   155
#[derive(Clone, Copy, Debug, Default)]
15400
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
   156
struct LookupEntry {
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   157
    index: Option<NonZeroU16>,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   158
    block_index: u16,
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   159
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   160
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   161
impl LookupEntry {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   162
    fn new(block_index: u16, index: u16) -> Self {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   163
        Self {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   164
            index: unsafe { Some(NonZeroU16::new_unchecked(index + 1)) },
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   165
            block_index,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   166
        }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   167
    }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   168
}
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   169
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   170
pub struct GearDataManager {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   171
    types: Vec<TypeId>,
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   172
    blocks: Vec<DataBlock>,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   173
    block_masks: Vec<u64>,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   174
    element_sizes: Box<[u16; 64]>,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   175
    lookup: Box<[LookupEntry]>,
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   176
}
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   177
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   178
impl GearDataManager {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   179
    pub fn new() -> Self {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   180
        Self {
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   181
            types: vec![],
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   182
            blocks: vec![],
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   183
            block_masks: vec![],
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   184
            element_sizes: Box::new([0; 64]),
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   185
            lookup: vec![LookupEntry::default(); u16::max_value() as usize].into_boxed_slice(),
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   186
        }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   187
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   188
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   189
    #[inline]
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   190
    fn get_type_index<T: 'static>(&self) -> Option<usize> {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   191
        let type_id = TypeId::of::<T>();
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   192
        self.types.iter().position(|id| *id == type_id)
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   193
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   194
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   195
    fn move_between_blocks(&mut self, src_block_index: u16, src_index: u16, dest_block_index: u16) {
15394
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   196
        debug_assert!(src_block_index != dest_block_index);
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   197
        let src_mask = self.block_masks[src_block_index as usize];
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   198
        let dest_mask = self.block_masks[dest_block_index as usize];
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   199
        debug_assert!(src_mask & dest_mask == src_mask);
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   200
15394
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   201
        let src_block = &self.blocks[src_block_index as usize];
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   202
        let dest_block = &self.blocks[dest_block_index as usize];
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   203
        debug_assert!(src_index < src_block.elements_count);
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   204
        debug_assert!(!dest_block.is_full());
15379
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   205
15394
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   206
        let dest_index = dest_block.elements_count;
15393
7a3ed957cee9 fix block addition
alfadur
parents: 15392
diff changeset
   207
        for i in 0..self.types.len() {
15394
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   208
            if src_mask & (1 << i as u64) != 0 {
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   209
                let size = self.element_sizes[i];
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   210
                let src_ptr = src_block.component_blocks[i].unwrap().as_ptr();
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   211
                let dest_ptr = dest_block.component_blocks[i].unwrap().as_ptr();
15379
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   212
                unsafe {
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   213
                    copy_nonoverlapping(
15394
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   214
                        src_ptr.add((src_index * size) as usize),
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   215
                        dest_ptr.add((dest_index * size) as usize),
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   216
                        size as usize,
15379
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   217
                    );
15394
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   218
                    if src_index < src_block.elements_count - 1 {
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   219
                        copy_nonoverlapping(
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   220
                            src_ptr.add((size * (src_block.elements_count - 1)) as usize),
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   221
                            src_ptr.add((size * src_index) as usize),
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   222
                            size as usize,
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   223
                        );
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   224
                    }
15379
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   225
                }
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   226
            }
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   227
        }
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   228
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   229
        let src_block = &mut self.blocks[src_block_index as usize];
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   230
        let gear_id = src_block.gear_ids()[src_index as usize];
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   231
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   232
        if src_index < src_block.elements_count - 1 {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   233
            let relocated_index = src_block.elements_count as usize - 1;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   234
            let gear_ids = src_block.gear_ids_mut();
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   235
            let relocated_id = gear_ids[relocated_index];
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   236
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   237
            gear_ids[src_index as usize] = relocated_id;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   238
            self.lookup[relocated_id.get() as usize - 1] =
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   239
                LookupEntry::new(src_block_index, src_index);
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   240
        }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   241
        src_block.elements_count -= 1;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   242
15394
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   243
        let dest_block = &mut self.blocks[dest_block_index as usize];
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   244
        let dest_index = dest_block.elements_count;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   245
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   246
        dest_block.gear_ids_mut()[dest_index as usize] = gear_id;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   247
        self.lookup[gear_id.get() as usize - 1] = LookupEntry::new(dest_block_index, dest_index);
15394
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   248
        dest_block.elements_count += 1;
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   249
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   250
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   251
    fn add_to_block<T: Clone>(&mut self, gear_id: GearId, block_index: u16, value: &T) {
15378
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   252
        debug_assert!(self.block_masks[block_index as usize].count_ones() == 1);
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   253
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   254
        let block = &mut self.blocks[block_index as usize];
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   255
        debug_assert!(block.elements_count < block.max_elements);
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   256
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   257
        unsafe {
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   258
            let slice = slice::from_raw_parts_mut(
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   259
                block.component_blocks[0].unwrap().as_ptr() as *mut T,
15378
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   260
                block.max_elements as usize,
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   261
            );
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   262
            *slice.get_unchecked_mut(block.elements_count as usize) = value.clone();
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   263
        };
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   264
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   265
        let index = block.elements_count;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   266
        self.lookup[gear_id.get() as usize - 1] = LookupEntry::new(block_index, index);
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   267
        block.gear_ids_mut()[index as usize] = gear_id;
15378
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   268
        block.elements_count += 1;
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   269
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   270
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   271
    fn remove_from_block(&mut self, block_index: u16, index: u16) {
15378
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   272
        let block = &mut self.blocks[block_index as usize];
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   273
        debug_assert!(index < block.elements_count);
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   274
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   275
        for (i, size) in self.element_sizes.iter().cloned().enumerate() {
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   276
            if index < block.elements_count - 1 {
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   277
                if let Some(ptr) = block.component_blocks[i] {
15378
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   278
                    unsafe {
15379
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   279
                        copy_nonoverlapping(
15378
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   280
                            ptr.as_ptr()
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   281
                                .add((size * (block.elements_count - 1)) as usize),
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   282
                            ptr.as_ptr().add((size * index) as usize),
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   283
                            size as usize,
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   284
                        );
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   285
                    }
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   286
                }
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   287
            }
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   288
        }
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   289
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   290
        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: 15394
diff changeset
   291
        if index < block.elements_count - 1 {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   292
            let relocated_index = block.elements_count as usize - 1;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   293
            let gear_ids = block.gear_ids_mut();
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   294
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   295
            gear_ids[index as usize] = gear_ids[relocated_index];
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   296
            self.lookup[gear_ids[relocated_index].get() as usize - 1] =
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   297
                LookupEntry::new(block_index, index);
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   298
        }
15378
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   299
        block.elements_count -= 1;
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   300
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   301
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   302
    #[inline]
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   303
    fn ensure_block(&mut self, mask: u64) -> u16 {
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   304
        if let Some(index) = self
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   305
            .block_masks
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   306
            .iter()
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   307
            .enumerate()
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   308
            .position(|(i, m)| *m == mask && !self.blocks[i].is_full())
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   309
        {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   310
            index as u16
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   311
        } else {
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   312
            self.blocks.push(DataBlock::new(
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   313
                mask,
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   314
                &self.element_sizes[0..self.types.len()],
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   315
            ));
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   316
            self.block_masks.push(mask);
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   317
            (self.blocks.len() - 1) as u16
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   318
        }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   319
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   320
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   321
    pub fn add<T: Clone + 'static>(&mut self, gear_id: GearId, value: &T) {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   322
        if let Some(type_index) = self.get_type_index::<T>() {
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   323
            let type_bit = 1 << type_index as u64;
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   324
            let entry = self.lookup[gear_id.get() as usize - 1];
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   325
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   326
            if let Some(index) = entry.index {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   327
                let mask = self.block_masks[entry.block_index as usize];
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   328
                let new_mask = mask | type_bit;
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   329
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   330
                if new_mask != mask {
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   331
                    let dest_block_index = self.ensure_block(new_mask);
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   332
                    self.move_between_blocks(entry.block_index, index.get() - 1, dest_block_index);
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   333
                }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   334
            } else {
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   335
                let dest_block_index = self.ensure_block(type_bit);
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   336
                self.add_to_block(gear_id, dest_block_index, value);
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   337
            }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   338
        } else {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   339
            panic!("Unregistered type")
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   340
        }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   341
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   342
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   343
    pub fn remove<T: 'static>(&mut self, gear_id: GearId) {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   344
        if let Some(type_index) = self.get_type_index::<T>() {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   345
            let entry = self.lookup[gear_id.get() as usize - 1];
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   346
            if let Some(index) = entry.index {
15394
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   347
                let dest_mask =
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   348
                    self.block_masks[entry.block_index as usize] & !(1 << type_index as u64);
15379
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   349
15394
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   350
                if dest_mask == 0 {
15379
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   351
                    self.remove_all(gear_id)
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   352
                } else {
15394
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   353
                    let dest_block_index = self.ensure_block(dest_mask);
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   354
                    self.move_between_blocks(entry.block_index, index.get() - 1, dest_block_index);
15379
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   355
                }
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   356
            }
15379
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   357
        } else {
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   358
            panic!("Unregistered type")
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   359
        }
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   360
    }
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   361
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   362
    pub fn remove_all(&mut self, gear_id: GearId) {
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   363
        let entry = self.lookup[gear_id.get() as usize - 1];
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   364
        if let Some(index) = entry.index {
135c29237a56 implement moving between blocks
alfadur
parents: 15378
diff changeset
   365
            self.remove_from_block(entry.block_index, index.get() - 1);
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   366
        }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   367
    }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   368
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   369
    pub fn register<T: 'static>(&mut self) {
15378
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   370
        debug_assert!(!std::mem::needs_drop::<T>());
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   371
        debug_assert!(self.types.len() <= 64);
277acc9f9fcf implement addition to/removal from blocks
alfadur
parents: 15375
diff changeset
   372
        debug_assert!(size_of::<T>() <= u16::max_value() as usize);
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   373
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   374
        let id = TypeId::of::<T>();
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   375
        if !self.types.contains(&id) {
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   376
            self.element_sizes[self.types.len()] = size_of::<T>() as u16;
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   377
            self.types.push(id);
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   378
        }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   379
    }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   380
15400
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
   381
    pub fn iter<T: TypeTuple + 'static, F: FnMut(T)>(&mut self, mut f: F) {
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
   382
        self.iter_id(|_, x| f(x));
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
   383
    }
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
   384
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
   385
    pub fn iter_id<T: TypeTuple + 'static, F: FnMut(GearId, T)>(&mut self, mut f: F) {
15388
d6b4586b271f make sure component slice order corresponds to the type args
alfadur
parents: 15380
diff changeset
   386
        let mut arg_types = Vec::with_capacity(64);
d6b4586b271f make sure component slice order corresponds to the type args
alfadur
parents: 15380
diff changeset
   387
        T::get_types(&mut arg_types);
d6b4586b271f make sure component slice order corresponds to the type args
alfadur
parents: 15380
diff changeset
   388
d6b4586b271f make sure component slice order corresponds to the type args
alfadur
parents: 15380
diff changeset
   389
        let mut type_indices = vec![-1i8; arg_types.len()];
d6b4586b271f make sure component slice order corresponds to the type args
alfadur
parents: 15380
diff changeset
   390
        let mut selector = 0u64;
d6b4586b271f make sure component slice order corresponds to the type args
alfadur
parents: 15380
diff changeset
   391
d6b4586b271f make sure component slice order corresponds to the type args
alfadur
parents: 15380
diff changeset
   392
        for (arg_index, type_id) in arg_types.iter().enumerate() {
d6b4586b271f make sure component slice order corresponds to the type args
alfadur
parents: 15380
diff changeset
   393
            match self.types.iter().position(|t| t == type_id) {
15394
5e2b9740086f refill memory when moving out of block
alfadur
parents: 15393
diff changeset
   394
                Some(i) if selector & (1 << i as u64) != 0 => panic!("Duplicate type"),
15388
d6b4586b271f make sure component slice order corresponds to the type args
alfadur
parents: 15380
diff changeset
   395
                Some(i) => {
d6b4586b271f make sure component slice order corresponds to the type args
alfadur
parents: 15380
diff changeset
   396
                    type_indices[arg_index] = i as i8;
15393
7a3ed957cee9 fix block addition
alfadur
parents: 15392
diff changeset
   397
                    selector |= 1 << i as u64;
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
   398
                }
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
   399
                None => panic!("Unregistered type"),
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   400
            }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   401
        }
15400
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
   402
        let mut slices = vec![null_mut(); arg_types.len() + 1];
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   403
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   404
        for (block_index, mask) in self.block_masks.iter().enumerate() {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   405
            if mask & selector == selector {
15400
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
   406
                let block = &mut self.blocks[block_index];
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
   407
                slices[0] = block.data.as_mut_ptr();
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
   408
15388
d6b4586b271f make sure component slice order corresponds to the type args
alfadur
parents: 15380
diff changeset
   409
                for (arg_index, type_index) in type_indices.iter().cloned().enumerate() {
15400
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
   410
                    slices[arg_index as usize + 1] = block.component_blocks[type_index as usize]
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
   411
                        .unwrap()
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
   412
                        .as_ptr()
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   413
                }
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   414
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   415
                unsafe {
15400
27915135f87f allow iterating with gear id
alfadur
parents: 15396
diff changeset
   416
                    T::iter(&slices[..], block.elements_count as usize, |id, x| f(id, x));
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   417
                }
15326
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   418
            }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   419
        }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   420
    }
0076bf602969 start gear data group implementation
alfadur
parents:
diff changeset
   421
}
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   422
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   423
#[cfg(test)]
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   424
mod test {
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   425
    use super::{super::common::GearId, GearDataManager};
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   426
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   427
    #[derive(Clone)]
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   428
    struct Datum {
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   429
        value: u32,
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   430
    }
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   431
15392
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   432
    #[derive(Clone)]
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   433
    struct Tag {
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   434
        nothing: u8,
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   435
    }
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   436
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   437
    #[test]
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   438
    fn single_component_iteration() {
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   439
        let mut manager = GearDataManager::new();
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   440
        manager.register::<Datum>();
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   441
        for i in 1..=5 {
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   442
            manager.add(GearId::new(i as u16).unwrap(), &Datum { value: i });
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   443
        }
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   444
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   445
        let mut sum = 0;
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   446
        manager.iter(|(d,): (&Datum,)| sum += d.value);
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
   447
        assert_eq!(sum, 15);
15380
b5e0a39856fd complete basic ecs
alfadur
parents: 15379
diff changeset
   448
15389
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
   449
        manager.iter(|(d,): (&mut Datum,)| d.value += 1);
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
   450
        manager.iter(|(d,): (&Datum,)| sum += d.value);
445138f388d4 expand iteration implementation to larger tuples
alfadur
parents: 15388
diff changeset
   451
        assert_eq!(sum, 35);
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   452
    }
15392
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   453
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   454
    #[test]
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   455
    fn multiple_component_iteration() {
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   456
        let mut manager = GearDataManager::new();
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   457
        manager.register::<Datum>();
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   458
        manager.register::<Tag>();
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   459
        for i in 1..=10 {
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   460
            let gear_id = GearId::new(i as u16).unwrap();
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   461
            manager.add(gear_id, &Datum { value: i });
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   462
        }
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   463
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   464
        for i in 1..=10 {
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   465
            let gear_id = GearId::new(i as u16).unwrap();
15392
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   466
            if i & 1 == 0 {
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   467
                manager.add(GearId::new(i as u16).unwrap(), &Tag { nothing: 0 });
15392
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   468
            }
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   469
        }
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   470
15396
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   471
        let mut sum = 0;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   472
        manager.iter(|(d,): (&Datum,)| sum += d.value);
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   473
        assert_eq!(sum, 55);
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   474
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   475
        let mut tag_sum1 = 0;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   476
        let mut tag_sum2 = 0;
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   477
        manager.iter(|(d, _): (&Datum, &Tag)| tag_sum1 += d.value);
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   478
        manager.iter(|(_, d): (&Tag, &Datum)| tag_sum2 += d.value);
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   479
        assert_eq!(tag_sum1, 30);
37b632d38f14 properly update gear id lookup on block modifications
alfadur
parents: 15394
diff changeset
   480
        assert_eq!(tag_sum2, tag_sum1);
15392
24a9afbf33c6 add multicomponent iteration test
alfadur
parents: 15390
diff changeset
   481
    }
15375
dff37ac61dcf convert ecs storage to untyped
alfadur
parents: 15326
diff changeset
   482
}