mirror of
https://github.com/Ukendio/jecs.git
synced 2025-04-24 17:10:03 +00:00
Update removal functions to handle more variants
This commit is contained in:
parent
b81bd6eea8
commit
4eb15bbb55
2 changed files with 131 additions and 83 deletions
150
jecs.luau
150
jecs.luau
|
@ -1064,21 +1064,19 @@ local function archetype_delete(world: ecs_world_t, archetype: ecs_archetype_t,
|
|||
end
|
||||
|
||||
local function world_clear(world: ecs_world_t, entity: i53)
|
||||
--TODO: use sparse_get (stashed)
|
||||
local record = entity_index_try_get(world.entity_index, entity)
|
||||
if not record then
|
||||
return
|
||||
end
|
||||
local component_index = world.component_index
|
||||
local archetypes = world.archetypes
|
||||
local tgt = ECS_PAIR(EcsWildcard, entity)
|
||||
local idr_t = component_index[tgt]
|
||||
local idr = component_index[entity]
|
||||
local rel = ECS_PAIR(entity, EcsWildcard)
|
||||
local idr_r = component_index[rel]
|
||||
|
||||
local archetype = record.archetype
|
||||
local row = record.row
|
||||
|
||||
local idr = world.component_index[entity]
|
||||
if idr then
|
||||
local count = 0
|
||||
local queue = {}
|
||||
for archetype_id in idr.cache do
|
||||
local idr_archetype = world.archetypes[archetype_id]
|
||||
local idr_archetype = archetypes[archetype_id]
|
||||
local entities = idr_archetype.entities
|
||||
local n = #entities
|
||||
count += n
|
||||
|
@ -1089,14 +1087,79 @@ local function world_clear(world: ecs_world_t, entity: i53)
|
|||
end
|
||||
end
|
||||
|
||||
if archetype then
|
||||
-- In the future should have a destruct mode for
|
||||
-- deleting archetypes themselves. Maybe requires recycling
|
||||
archetype_delete(world, archetype, row)
|
||||
if idr_t then
|
||||
local children
|
||||
local ids
|
||||
|
||||
local count = 0
|
||||
local archetype_ids = idr_t.cache
|
||||
for archetype_id in archetype_ids do
|
||||
local idr_t_archetype = archetypes[archetype_id]
|
||||
local idr_t_types = idr_t_archetype.types
|
||||
local entities = idr_t_archetype.entities
|
||||
local removal_queued = false
|
||||
|
||||
for _, id in idr_t_types do
|
||||
if not ECS_IS_PAIR(id) then
|
||||
continue
|
||||
end
|
||||
local object = entity_index_get_alive(
|
||||
entity_index, ECS_PAIR_SECOND(id))
|
||||
if object ~= entity then
|
||||
continue
|
||||
end
|
||||
if not ids then
|
||||
ids = {}
|
||||
end
|
||||
ids[id] = true
|
||||
removal_queued = true
|
||||
end
|
||||
|
||||
record.archetype = nil :: any
|
||||
record.row = nil :: any
|
||||
if not removal_queued then
|
||||
continue
|
||||
end
|
||||
|
||||
if not queue then
|
||||
queue = {}
|
||||
end
|
||||
|
||||
local n = #entities
|
||||
table.move(entities, 1, n, count + 1, queue)
|
||||
count += n
|
||||
end
|
||||
|
||||
for id in ids do
|
||||
for _, child in queue do
|
||||
world_remove(world, child, id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if idr_r then
|
||||
local count = 0
|
||||
local archetype_ids = idr_r.cache
|
||||
local ids = {}
|
||||
local queue = {}
|
||||
for archetype_id in archetype_ids do
|
||||
local idr_r_archetype = archetypes[archetype_id]
|
||||
local entities = idr_r_archetype.entities
|
||||
local tr = idr_r_archetype.records[rel]
|
||||
local tr_count = idr_r_archetype.counts[rel]
|
||||
local types = idr_r_archetype.types
|
||||
for i = tr, tr + tr_count - 1 do
|
||||
ids[types[i]] = true
|
||||
end
|
||||
local n = #entities
|
||||
table.move(entities, 1, n, count + 1, queue)
|
||||
count += n
|
||||
end
|
||||
|
||||
for _, e in queue do
|
||||
for id in ids do
|
||||
world_remove(world, e, id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function archetype_disconnect_edge(edge: ecs_graph_edge_t)
|
||||
|
@ -1225,8 +1288,11 @@ local function world_delete(world: ecs_world_t, entity: i53)
|
|||
local component_index = world.component_index
|
||||
local archetypes = world.archetypes
|
||||
local tgt = ECS_PAIR(EcsWildcard, delete)
|
||||
local rel = ECS_PAIR(delete, EcsWildcard)
|
||||
|
||||
local idr_t = component_index[tgt]
|
||||
local idr = component_index[delete]
|
||||
local idr_r = component_index[rel]
|
||||
|
||||
if idr then
|
||||
local flags = idr.flags
|
||||
|
@ -1256,11 +1322,10 @@ local function world_delete(world: ecs_world_t, entity: i53)
|
|||
end
|
||||
end
|
||||
|
||||
local dense_array = entity_index.dense_array
|
||||
|
||||
if idr_t then
|
||||
local children
|
||||
local ids
|
||||
|
||||
local count = 0
|
||||
local archetype_ids = idr_t.cache
|
||||
for archetype_id in archetype_ids do
|
||||
|
@ -1308,8 +1373,8 @@ local function world_delete(world: ecs_world_t, entity: i53)
|
|||
end
|
||||
|
||||
if ids then
|
||||
for id in ids do
|
||||
for _, child in children do
|
||||
for id in ids do
|
||||
world_remove(world, child, id)
|
||||
end
|
||||
end
|
||||
|
@ -1320,6 +1385,51 @@ local function world_delete(world: ecs_world_t, entity: i53)
|
|||
end
|
||||
end
|
||||
|
||||
if idr_r then
|
||||
local count = 0
|
||||
local archetype_ids = idr_r.cache
|
||||
local flags = idr_r.flags
|
||||
if bit32.band(flags, ECS_ID_DELETE) ~= 0 then
|
||||
for archetype_id in archetype_ids do
|
||||
local idr_r_archetype = archetypes[archetype_id]
|
||||
local entities = idr_r_archetype.entities
|
||||
local n = #entities
|
||||
for i = n, 1, -1 do
|
||||
world_delete(world, entities[i])
|
||||
end
|
||||
archetype_destroy(world, idr_r_archetype)
|
||||
end
|
||||
else
|
||||
local children = {}
|
||||
local count = 0
|
||||
local ids = {}
|
||||
for archetype_id in archetype_ids do
|
||||
local idr_r_archetype = archetypes[archetype_id]
|
||||
local entities = idr_r_archetype.entities
|
||||
local tr = idr_r_achetype.records[rel]
|
||||
local tr_count = idr_r_archetype.counts[rel]
|
||||
local types = idr_r_achetype.types
|
||||
for i = tr, tr_count - 1 do
|
||||
ids[types[tr]] = true
|
||||
end
|
||||
local n = #entities
|
||||
table.move(entities, 1, n, count + 1, children)
|
||||
count += n
|
||||
end
|
||||
|
||||
for _, child in children do
|
||||
for id in ids do
|
||||
world_remove(world, child, id)
|
||||
end
|
||||
end
|
||||
|
||||
for archetype_id in archetype_ids do
|
||||
archetype_destroy(world, archetypes[archetype_id])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local dense_array = entity_index.dense_array
|
||||
local index_of_deleted_entity = record.dense
|
||||
local index_of_last_alive_entity = entity_index.alive_count
|
||||
entity_index.alive_count = index_of_last_alive_entity - 1
|
||||
|
@ -1350,8 +1460,6 @@ export type QueryInner = {
|
|||
world: World,
|
||||
}
|
||||
|
||||
|
||||
|
||||
local function query_iter_init(query: ecs_query_data_t): () -> (number, ...any)
|
||||
local world_query_iter_next
|
||||
|
||||
|
|
|
@ -1109,66 +1109,6 @@ TEST("world:clear()", function()
|
|||
CHECK(world:get(e1, A) == nil)
|
||||
CHECK(world:get(e1, B))
|
||||
end
|
||||
do CASE("should remove its components")
|
||||
local world = jecs.World.new() :: World
|
||||
local A = world:component()
|
||||
local B = world:component()
|
||||
|
||||
local e = world:entity()
|
||||
|
||||
world:set(e, A, true)
|
||||
world:set(e, B, true)
|
||||
|
||||
CHECK(world:get(e, A))
|
||||
CHECK(world:get(e, B))
|
||||
|
||||
world:clear(e)
|
||||
CHECK(world:get(e, A) == nil)
|
||||
CHECK(world:get(e, B) == nil)
|
||||
end
|
||||
|
||||
do CASE("should move last record")
|
||||
local world = world_new()
|
||||
local A = world:component()
|
||||
|
||||
local e = world:entity()
|
||||
local e1 = world:entity()
|
||||
|
||||
world:add(e, A)
|
||||
world:add(e1, A)
|
||||
|
||||
local archetype = world.archetype_index["1"]
|
||||
local archetype_entities = archetype.entities
|
||||
|
||||
local _e = e :: number
|
||||
local _e1 = e1 :: number
|
||||
|
||||
CHECK(archetype_entities[1] == _e)
|
||||
CHECK(archetype_entities[2] == _e1)
|
||||
|
||||
local e_record: jecs.Record = entity_index_try_get_any(
|
||||
world.entity_index, e) :: any
|
||||
local e1_record: jecs.Record = entity_index_try_get_any(
|
||||
world.entity_index, e1) :: any
|
||||
CHECK(e_record.archetype == archetype)
|
||||
CHECK(e1_record.archetype == archetype)
|
||||
CHECK(e1_record.row == 2)
|
||||
|
||||
world:clear(e)
|
||||
|
||||
CHECK((e_record.archetype :: jecs.Archetype?) == nil)
|
||||
CHECK((e_record.row :: number?) == nil)
|
||||
CHECK(e1_record.archetype == archetype)
|
||||
CHECK(e1_record.row == 1)
|
||||
|
||||
CHECK(archetype_entities[1] == _e1)
|
||||
CHECK(archetype_entities[2] == nil)
|
||||
|
||||
CHECK(world:contains(e) == true)
|
||||
CHECK(world:has(e, A) == false)
|
||||
CHECK(world:contains(e1) == true)
|
||||
CHECK(world:has(e1, A) == true)
|
||||
end
|
||||
end)
|
||||
|
||||
TEST("world:has()", function()
|
||||
|
|
Loading…
Reference in a new issue