pub trait ContainEntity:
RegisterComponent
+ BorrowComponent
+ AddEntity {
// Required methods
fn create_twin(&self) -> Box<dyn ContainEntity>;
fn get_item_mut(&mut self, ci: usize, ri: usize) -> Option<NonNull<u8>>;
fn len(&self) -> usize;
fn capacity(&self) -> usize;
fn reserve(&mut self, additional: usize);
fn shrink_to_fit(&mut self);
unsafe fn resize_column(
&mut self,
ci: usize,
new_len: usize,
val_ptr: NonNull<u8>,
);
}Expand description
A trait for collecting heterogeneous component types.
In this trait, each component type is gathered in each component column and all columns have the same length so that it looks like 2d matrix.
When it comes to in & out types, this trait has intentionally raw pointer parameters not to use generic for object safety. So that you can hold various sorts of entity container in a single variable.
§Index system
There are three index systems for this trait.
The first one is ‘column index’ which is for pointing a certain component
column. When you add or remove component column from an entity container,
you will get or need this column index. Column indices starts with 0 and
increases by 1 as you put in a component column. To avoid confusion, column
must be added in a sorted order by ComponentKey.
The second and third index systems are related to pointing a certain entity in an entity container. In other words, you need one of those index systems when you need access to a single entity.
Second one is ‘row index’ which is a kind of outer index for each entity. You will get this row index when you put your entity in an entity container. Also, you can remove an entity using the row index. Row indices may not be in order and not consecutive.
The last one is ‘value index’ which is inner index for each entity. In contrast to former one, value indices are in order and consecutive like indices on a slice. Plus, all component columns follows the same value indices in an entity container.
Take a look at example below.
column index 0 1
--------------------------------------------
| row index | value index | comp_a | comp_b |
| 0 | 0 | . | . |
| 4 | 1 | . | . |
| 2 | 2 | . | . |§Examples
use my_ecs::prelude::*;
use std::{hash::RandomState, ptr::NonNull};
#[derive(Entity)]
struct Entity {
a: Ca,
b: Cb,
}
#[derive(Component)]
struct Ca(i32);
#[derive(Component)]
struct Cb(i32);
let mut cont: SparseSet<RandomState> = SparseSet::new();
// Adds component columns.
let ci_a = cont.add_column(tinfo!(Ca)).unwrap();
let ci_b = cont.add_column(tinfo!(Cb)).unwrap();
// Adds component values for the entity.
cont.begin_add_row();
let ri = unsafe {
let ptr = NonNull::new(&mut Ca(4) as *mut Ca as *mut u8).unwrap();
cont.add_value(ci_a, ptr);
let ptr = NonNull::new(&mut Cb(2) as *mut Cb as *mut u8).unwrap();
cont.add_value(ci_b, ptr);
cont.end_add_row()
};
assert_eq!(cont.len(), 1);
// Borrows component columns and test them if they are as we expected.
let col_a = cont.borrow_column(ci_a).unwrap();
let col_b = cont.borrow_column(ci_b).unwrap();
unsafe {
let ptr = col_a.get(0).unwrap();
assert_eq!(*ptr.as_ref(), 4);
let ptr = col_b.get(0).unwrap();
assert_eq!(*ptr.as_ref(), 2);
}
drop(col_a);
drop(col_b);
// Removes the entity we just put.
let is_removed = cont.remove_row(ri);
assert!(is_removed);
assert_eq!(cont.len(), 0);Required Methods§
Sourcefn create_twin(&self) -> Box<dyn ContainEntity>
fn create_twin(&self) -> Box<dyn ContainEntity>
Creates a new entity container that has the same component types without component values.
In other words, the copied container doesn’t have any entities in it. So it’s empty.
§Examples
use my_ecs::prelude::*;
use std::{hash::RandomState, ptr::NonNull, any::TypeId};
#[derive(Entity)]
struct Entity {
a: Ca,
}
#[derive(Component)]
struct Ca(i32);
let mut cont: SparseSet<RandomState> = SparseSet::new();
let ci = cont.add_column(tinfo!(Ca)).unwrap();
// Adds component values for an entity.
cont.begin_add_row();
unsafe {
let ptr = NonNull::new(&mut Ca(0) as *mut Ca as *mut u8).unwrap();
cont.add_value(ci, ptr);
cont.end_add_row();
}
assert_eq!(cont.len(), 1);
let twin = cont.create_twin();
assert_eq!(twin.len(), 0);
assert!(twin.contains_column(&TypeId::of::<Ca>()));Sourcefn get_item_mut(&mut self, ci: usize, ri: usize) -> Option<NonNull<u8>>
fn get_item_mut(&mut self, ci: usize, ri: usize) -> Option<NonNull<u8>>
Retrieves an entity for the given component column index and row index from the entity container.
If one of two indices is out of bounds, returns None.
Sourcefn capacity(&self) -> usize
fn capacity(&self) -> usize
Returns capacity of the entity container.
But if entity container doesn’t support getting capacity, it returns number of entities instead.
§Examples
See ContainEntity::reserve document.
Sourcefn reserve(&mut self, additional: usize)
fn reserve(&mut self, additional: usize)
May reserve at least additional extra capacity.
This method doesn’t guarantee definite extension of capacity. It depends on implementations.
§Examples
use my_ecs::prelude::*;
use std::{hash::RandomState, ptr::NonNull, any::TypeId};
#[derive(Entity)]
struct Entity {
a: Ca,
}
#[derive(Component)]
struct Ca(i32);
// SparseSet supports capacity.
let mut cont: SparseSet<RandomState> = SparseSet::new();
cont.add_column(tinfo!(Ca)).unwrap();
assert_eq!(cont.capacity(), 0);
cont.reserve(10);
assert!(cont.capacity() >= 10);
cont.shrink_to_fit();
assert_eq!(cont.capacity(), 0);Sourcefn shrink_to_fit(&mut self)
fn shrink_to_fit(&mut self)
May shrink capacity of the entity container as much as possible.
This method doesn’t guarantee definite removal of extra capacity. It depends on implementations.
§Examples
See ContainEntity::reserve document.