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