use core::ffi::c_void;
use super::{world::WorldRaw, ComponentId, EntityId, QueryId};
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TermAccess {
In,
Out,
InOut,
InOptional,
InOutOptional,
Filter,
Not,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct QueryTerm {
pub id: ComponentId,
pub access: TermAccess,
}
impl Default for QueryTerm {
#[inline]
fn default() -> Self {
Self {
id: 0,
access: TermAccess::In,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct QueryDesc {
pub terms: [QueryTerm; 64],
pub is_a: EntityId,
}
impl Default for QueryDesc {
#[inline]
fn default() -> Self {
Self {
terms: [QueryTerm::default(); 64],
is_a: 0,
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum FieldKind {
None,
Owned,
Shared,
}
#[repr(C)]
pub struct QueryCache {
_private: [u8; 0],
}
#[repr(C)]
pub struct Iter {
pub world: *mut WorldRaw,
pub count: u32,
pub entities: *mut EntityId,
pub cache: *mut QueryCache,
pub ptrs: *mut *mut c_void,
pub field_kinds: *mut FieldKind,
pub user_data: usize,
pub table_idx: u16,
pub table_count: u16,
}
extern "C" {
pub fn ecs_query_init(world: *mut WorldRaw, query: *const QueryDesc) -> QueryId;
pub fn ecs_query_fini(world: *mut WorldRaw, query: QueryId);
pub fn ecs_query_iter(world: *mut WorldRaw, query_id: QueryId) -> Iter;
pub fn ecs_iter_next(it: *mut Iter) -> bool;
}
#[inline]
pub unsafe fn ecs_field(it: *mut Iter, field_index: u16) -> *mut c_void {
let field = *(*it).ptrs.add(field_index as usize);
if *(*it).field_kinds.add(field_index as usize) == FieldKind::Owned {
*(field as *mut *mut c_void)
} else {
field
}
}
#[inline]
pub unsafe fn ecs_field_kind(it: *const Iter, field_index: u16) -> FieldKind {
*(*it).field_kinds.add(field_index as usize)
}
#[inline]
pub unsafe fn ecs_field_is_shared(it: *const Iter, field_index: u16) -> bool {
ecs_field_kind(it, field_index) == FieldKind::Shared
}