set should not invoke OnAdd

This commit is contained in:
Ukendio 2024-08-14 16:51:20 +02:00
parent 67edb101e6
commit 3596477dca

View file

@ -59,6 +59,10 @@ type ArchetypeDiff = {
local HI_COMPONENT_ID = 256 local HI_COMPONENT_ID = 256
--------------------------------------------------
-------- ID_RECORD -------------------------------
--------------------------------------------------
local EcsOnAdd = HI_COMPONENT_ID + 1 local EcsOnAdd = HI_COMPONENT_ID + 1
local EcsOnRemove = HI_COMPONENT_ID + 2 local EcsOnRemove = HI_COMPONENT_ID + 2
local EcsOnSet = HI_COMPONENT_ID + 3 local EcsOnSet = HI_COMPONENT_ID + 3
@ -73,6 +77,10 @@ local ECS_ID_FLAGS_MASK = 0x10
local ECS_ENTITY_MASK = bit32.lshift(1, 24) local ECS_ENTITY_MASK = bit32.lshift(1, 24)
local ECS_GENERATION_MASK = bit32.lshift(1, 16) local ECS_GENERATION_MASK = bit32.lshift(1, 16)
local ECS_ID_HAS_DELETE = 0b0001
local ECS_ID_HAS_HOOKS = 0b0010
--local EcsIdExclusive = 0b0100
local function FLAGS_ADD(is_pair: boolean): number local function FLAGS_ADD(is_pair: boolean): number
local flags = 0x0 local flags = 0x0
@ -360,9 +368,28 @@ local function world_has(world: World, entity: number, ...: i53): boolean
return true return true
end end
local EcsIdHasDelete = 0b0001 local function world_has_any(world: World, entity: number, ...: i53): boolean
local EcsIdHasHooks = 0b0010 local record = world.entityIndex.sparse[entity]
--local EcsIdExclusive = 0b0100 if not record then
return false
end
local archetype = record.archetype
if not archetype then
return false
end
local records = archetype.records
for i = 1, select("#", ...) do
if not records[select(i, ...)] then
return true
end
end
return false
end
local function id_record_ensure( local function id_record_ensure(
world, world,
@ -375,13 +402,13 @@ local function id_record_ensure(
local flags = 0b0000 local flags = 0b0000
local relation = ECS_ENTITY_T_HI(id) local relation = ECS_ENTITY_T_HI(id)
if world_has_one_inline(world, relation, EcsDelete) then if world_has_one_inline(world, relation, EcsDelete) then
flags = bit32.bor(flags, EcsIdHasDelete) flags = bit32.bor(flags, ECS_ID_HAS_DELETE)
end end
if world_has(world, relation, if world_has_any(world, relation,
EcsOnAdd, EcsOnSet, EcsOnRemove) EcsOnAdd, EcsOnSet, EcsOnRemove)
then then
flags = bit32.bor(flags, EcsIdHasHooks) flags = bit32.bor(flags, ECS_ID_HAS_HOOKS)
end end
-- local FLAG2 = 0b0010 -- local FLAG2 = 0b0010
@ -586,7 +613,7 @@ local function world_add(world: World, entity: i53, id: i53)
end end
local idr = world.componentIndex[id] local idr = world.componentIndex[id]
local has_hooks = bit32.band(idr.flags, EcsIdHasHooks) local has_hooks = bit32.band(idr.flags, ECS_ID_HAS_HOOKS) ~= 0
if has_hooks then if has_hooks then
invoke_hook(world, EcsOnAdd, id, entity) invoke_hook(world, EcsOnAdd, id, entity)
@ -599,7 +626,7 @@ local function world_set(world: World, entity: i53, id: i53, data: unknown)
local from = record.archetype local from = record.archetype
local to = archetype_traverse_add(world, id, from) local to = archetype_traverse_add(world, id, from)
local idr = world.componentIndex[id] local idr = world.componentIndex[id]
local has_hooks = bit32.band(idr.flags, EcsIdHasHooks) local has_hooks = bit32.band(idr.flags, ECS_ID_HAS_HOOKS) ~= 0
if from == to then if from == to then
-- If the archetypes are the same it can avoid moving the entity -- If the archetypes are the same it can avoid moving the entity
@ -623,13 +650,10 @@ local function world_set(world: World, entity: i53, id: i53, data: unknown)
end end
end end
if not has_hooks then
local tr = to.records[id]
from.columns[tr.column][record.row] = data
else
invoke_hook(world, EcsOnAdd, id, entity)
local tr = to.records[id] local tr = to.records[id]
to.columns[tr.column][record.row] = data to.columns[tr.column][record.row] = data
if has_hooks then
invoke_hook(world, EcsOnSet, id, entity, data) invoke_hook(world, EcsOnSet, id, entity, data)
end end
end end
@ -764,13 +788,18 @@ local function archetype_delete(world: World, archetype,
table.insert(children, child) table.insert(children, child)
end end
end end
local flags = idr.flags
if bit32.band(flags, ECS_ID_HAS_DELETE) ~= 0 then
for _, child in children do for _, child in children do
if world_has_one_inline(world, child, EcsDelete) then -- Cascade deletion to children
world_delete(world, child) world_delete(world, child)
end
else else
for _, child in children do
world_remove(world, child, delete) world_remove(world, child, delete)
end end
end end
component_index[delete] = nil component_index[delete] = nil
end end
@ -822,7 +851,7 @@ local function archetype_delete(world: World, archetype,
if id_record then if id_record then
local flags = id_record.flags local flags = id_record.flags
if bit32.band(flags, EcsIdHasDelete) ~= 0 then if bit32.band(flags, ECS_ID_HAS_DELETE) ~= 0 then
for _, child in children do for _, child in children do
-- Cascade deletions of it has Delete as component trait -- Cascade deletions of it has Delete as component trait
world_delete(world, child) world_delete(world, child)