#ifndef ENTITY_H #define ENTITY_H #include "sprite.h" #include "mixer.h" enum entity_prop { ENTITY_PROP_NONE, ENTITY_PROP_ANIMATING, ENTITY_PROP_PLAYER_CONTROLLED, ENTITY_PROP_CAMERA, ENTITY_PROP_CAMERA_ACTIVE, /* Test props */ ENTITY_PROP_TEST, ENTITY_PROP_TEST_SOUND_EMITTER, ENTITY_PROP_COUNT }; struct entity_handle { u64 idx; u64 gen; }; struct entity_store { struct arena arena; u64 count; struct entity_handle first_free; struct entity_handle root; struct entity *entities; }; struct entity { /* Metadata */ b32 valid; struct entity_handle handle; u64 continuity_gen; u64 props[(ENTITY_PROP_COUNT + 63) / 64]; struct entity_handle next_free; /* Special value stored in first entity in store array */ u64 store_offset; /* Is this the root entity */ b32 is_root; /* Is the parent the root entity */ b32 is_top; /* Tree */ struct entity_handle parent; struct entity_handle next; struct entity_handle prev; struct entity_handle first; struct entity_handle last; /* ====================================================================== */ struct xform local_xform; /* Transform in relation to parent entity (or the world if entity has no parent) */ struct xform cached_global_xform; /* Calculated from entity tree */ b32 cached_global_xform_dirty; /* ====================================================================== */ /* Physics */ struct v2 acceleration; struct v2 velocity; struct v2 focus; /* Focus is a vector relative to the entity */ /* ENTITY_PROP_PLAYER_CONTROLLED */ f32 player_max_speed; f32 player_acceleration; /* ====================================================================== */ /* Sprite */ struct sprite_tag sprite; struct string sprite_span_name; u32 sprite_tint; struct xform sprite_local_xform; /* Sprite transform in relation to xform_world */ struct xform sprite_global_xform; /* ====================================================================== */ /* Animation */ /* ENTITY_PROP_ANIMATING */ f64 animation_time_in_frame; u32 animation_frame; /* ====================================================================== */ /* Testing */ /* ENTITY_PROP_TEST */ b32 test_initialized; struct xform test_start_local_xform; struct xform test_start_sprite_xform; /* ENTITY_PROP_TEST_SOUND_EMITTER */ struct string sound_name; struct mixer_desc sound_desc; struct mixer_track_handle sound_handle; /* ====================================================================== */ /* ENTITY_PROP_CAMERA */ struct entity_handle camera_follow; struct xform camera_quad_xform; f32 camera_lerp; /* Rate at which camera xform approaches target xform */ u32 camera_lerp_continuity_gen; struct xform camera_xform_target; /* Calculated from camera_follow */ u32 camera_applied_lerp_continuity_gen_plus_one; /* Calculated */ }; struct entity_array { struct entity *entities; u64 count; }; struct entity_prop_array { enum entity_prop *props; u64 count; }; /* ========================== * * Handle helpers * ========================== */ INLINE struct entity_handle entity_nil_handle(void) { return (struct entity_handle) { 0 }; } INLINE b32 entity_handle_eq(struct entity_handle a, struct entity_handle b) { return a.gen == b.gen && a.idx == b.idx; } /* ========================== * * Nil * ========================== */ INLINE struct entity *entity_nil(void) { extern READONLY struct entity _g_entity_nil; return &_g_entity_nil; } INLINE struct entity_store *entity_store_nil(void) { extern READONLY struct entity_store _g_entity_store_nil; return &_g_entity_store_nil; } /* ========================== * * Property helpers * ========================== */ INLINE void entity_enable_prop(struct entity *entity, enum entity_prop prop) { u64 index = prop / 64; u64 bit = prop % 64; entity->props[index] |= ((u64)1 << bit); } INLINE void entity_disable_prop(struct entity *entity, enum entity_prop prop) { u64 index = prop / 64; u64 bit = prop % 64; entity->props[index] &= ~((u64)1 << bit); } INLINE b32 entity_has_prop(struct entity *entity, enum entity_prop prop) { u64 index = prop / 64; u64 bit = prop % 64; return !!(entity->props[index] & ((u64)1 << bit)); } /* ========================== * * Entity functions * ========================== */ INLINE struct entity_array entity_store_as_array(struct entity_store *store) { return (struct entity_array) { .count = store->count, .entities = store->entities }; } /* Entity store */ struct entity_store *entity_store_alloc(void); void entity_store_release(struct entity_store *store); void entity_store_copy_replace(struct entity_store *dest, struct entity_store *src); /* Entity */ struct entity *entity_alloc_unlinked(struct entity_store *store); struct entity *entity_alloc_top(struct entity_store *store); struct entity *entity_alloc_child(struct entity *parent); void entity_release(struct entity_store *store, struct entity *entity); /* Xform */ struct xform entity_get_xform(struct entity *ent); struct xform entity_get_local_xform(struct entity *ent); void entity_set_xform(struct entity *ent, struct xform xf); void entity_set_local_xform(struct entity *ent, struct xform xf); /* Query */ struct entity_store *entity_get_store(struct entity *ent); struct entity *entity_from_handle(struct entity_store *store, struct entity_handle handle); struct entity *entity_find_first_match_one(struct entity_store *store, enum entity_prop prop); struct entity *entity_find_first_match_all(struct entity_store *store, struct entity_prop_array props); /* Tree */ void entity_link_parent_child(struct entity *parent, struct entity *child); void entity_unlink(struct entity *ent); #endif