mirror of
https://github.com/Ukendio/jecs.git
synced 2025-04-24 17:10:03 +00:00
Merge f6cac301db
into a466ab151b
This commit is contained in:
commit
13cb7db8eb
2 changed files with 50 additions and 4 deletions
33
jecs.luau
33
jecs.luau
|
@ -120,15 +120,17 @@ local EcsOnDeleteTarget = HI_COMPONENT_ID + 8
|
||||||
local EcsDelete = HI_COMPONENT_ID + 9
|
local EcsDelete = HI_COMPONENT_ID + 9
|
||||||
local EcsRemove = HI_COMPONENT_ID + 10
|
local EcsRemove = HI_COMPONENT_ID + 10
|
||||||
local EcsName = HI_COMPONENT_ID + 11
|
local EcsName = HI_COMPONENT_ID + 11
|
||||||
local EcsOnArchetypeCreate = HI_COMPONENT_ID + 12
|
local EcsExclusive = HI_COMPONENT_ID + 12
|
||||||
local EcsOnArchetypeDelete = HI_COMPONENT_ID + 13
|
local EcsOnArchetypeCreate = HI_COMPONENT_ID + 13
|
||||||
local EcsRest = HI_COMPONENT_ID + 14
|
local EcsOnArchetypeDelete = HI_COMPONENT_ID + 14
|
||||||
|
local EcsRest = HI_COMPONENT_ID + 15
|
||||||
|
|
||||||
local ECS_ID_DELETE = 0b0000_0001
|
local ECS_ID_DELETE = 0b0000_0001
|
||||||
local ECS_ID_IS_TAG = 0b0000_0010
|
local ECS_ID_IS_TAG = 0b0000_0010
|
||||||
local ECS_ID_HAS_ON_ADD = 0b0000_0100
|
local ECS_ID_HAS_ON_ADD = 0b0000_0100
|
||||||
local ECS_ID_HAS_ON_SET = 0b0000_1000
|
local ECS_ID_HAS_ON_SET = 0b0000_1000
|
||||||
local ECS_ID_HAS_ON_REMOVE = 0b0001_0000
|
local ECS_ID_HAS_ON_REMOVE = 0b0001_0000
|
||||||
|
local ECS_ID_EXCLUSIVE = 0b0010_0000
|
||||||
local ECS_ID_MASK = 0b0000_0000
|
local ECS_ID_MASK = 0b0000_0000
|
||||||
|
|
||||||
local ECS_ENTITY_MASK = bit32.lshift(1, 24)
|
local ECS_ENTITY_MASK = bit32.lshift(1, 24)
|
||||||
|
@ -575,6 +577,7 @@ local function id_record_ensure(world: ecs_world_t, id: number): ecs_id_record_t
|
||||||
local on_add, on_set, on_remove = world_get(world, relation, EcsOnAdd, EcsOnSet, EcsOnRemove)
|
local on_add, on_set, on_remove = world_get(world, relation, EcsOnAdd, EcsOnSet, EcsOnRemove)
|
||||||
|
|
||||||
local is_tag = not world_has_one_inline(world, relation, EcsComponent)
|
local is_tag = not world_has_one_inline(world, relation, EcsComponent)
|
||||||
|
local is_exclusive = world_has_one_inline(world, relation, EcsExclusive)
|
||||||
|
|
||||||
if is_tag and is_pair then
|
if is_tag and is_pair then
|
||||||
is_tag = not world_has_one_inline(world, target, EcsComponent)
|
is_tag = not world_has_one_inline(world, target, EcsComponent)
|
||||||
|
@ -586,7 +589,8 @@ local function id_record_ensure(world: ecs_world_t, id: number): ecs_id_record_t
|
||||||
if on_remove then ECS_ID_HAS_ON_REMOVE else 0,
|
if on_remove then ECS_ID_HAS_ON_REMOVE else 0,
|
||||||
if on_set then ECS_ID_HAS_ON_SET else 0,
|
if on_set then ECS_ID_HAS_ON_SET else 0,
|
||||||
if has_delete then ECS_ID_DELETE else 0,
|
if has_delete then ECS_ID_DELETE else 0,
|
||||||
if is_tag then ECS_ID_IS_TAG else 0
|
if is_tag then ECS_ID_IS_TAG else 0,
|
||||||
|
if is_exclusive then ECS_ID_EXCLUSIVE else 0
|
||||||
)
|
)
|
||||||
|
|
||||||
idr = {
|
idr = {
|
||||||
|
@ -737,6 +741,23 @@ local function find_archetype_with(world: ecs_world_t, node: ecs_archetype_t, id
|
||||||
-- them each time would be expensive. Instead this insertion sort can find the insertion
|
-- them each time would be expensive. Instead this insertion sort can find the insertion
|
||||||
-- point in the types array.
|
-- point in the types array.
|
||||||
|
|
||||||
|
if ECS_IS_PAIR(id) then
|
||||||
|
local relation = ECS_PAIR_FIRST(id)
|
||||||
|
local idr = id_record_ensure(world, ECS_PAIR(relation, EcsWildcard))
|
||||||
|
|
||||||
|
if bit32.band(idr.flags, ECS_ID_EXCLUSIVE) ~= 0 then
|
||||||
|
-- Relationship is exclusive, check if archetype already has it
|
||||||
|
local tr = idr.cache[node.id]
|
||||||
|
if tr then
|
||||||
|
-- Archetype already has an instance of the relationship, create
|
||||||
|
-- a new id sequence with the existing id replaced
|
||||||
|
local dst = table.clone(id_types)
|
||||||
|
dst[tr] = id
|
||||||
|
return archetype_ensure(world, dst)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local at = find_insert(id_types, id)
|
local at = find_insert(id_types, id)
|
||||||
if at == -1 then
|
if at == -1 then
|
||||||
-- If it finds a duplicate, it just means it is the same archetype so it can return it
|
-- If it finds a duplicate, it just means it is the same archetype so it can return it
|
||||||
|
@ -2475,12 +2496,14 @@ local function world_new()
|
||||||
world_add(self, EcsOnAdd, EcsComponent)
|
world_add(self, EcsOnAdd, EcsComponent)
|
||||||
world_add(self, EcsOnRemove, EcsComponent)
|
world_add(self, EcsOnRemove, EcsComponent)
|
||||||
world_add(self, EcsWildcard, EcsComponent)
|
world_add(self, EcsWildcard, EcsComponent)
|
||||||
|
world_add(self, EcsExclusive, EcsComponent)
|
||||||
world_add(self, EcsRest, EcsComponent)
|
world_add(self, EcsRest, EcsComponent)
|
||||||
|
|
||||||
world_set(self, EcsOnAdd, EcsName, "jecs.OnAdd")
|
world_set(self, EcsOnAdd, EcsName, "jecs.OnAdd")
|
||||||
world_set(self, EcsOnRemove, EcsName, "jecs.OnRemove")
|
world_set(self, EcsOnRemove, EcsName, "jecs.OnRemove")
|
||||||
world_set(self, EcsOnSet, EcsName, "jecs.OnSet")
|
world_set(self, EcsOnSet, EcsName, "jecs.OnSet")
|
||||||
world_set(self, EcsWildcard, EcsName, "jecs.Wildcard")
|
world_set(self, EcsWildcard, EcsName, "jecs.Wildcard")
|
||||||
|
world_set(self, EcsExclusive, EcsName, "jecs.Exclusive")
|
||||||
world_set(self, EcsChildOf, EcsName, "jecs.ChildOf")
|
world_set(self, EcsChildOf, EcsName, "jecs.ChildOf")
|
||||||
world_set(self, EcsComponent, EcsName, "jecs.Component")
|
world_set(self, EcsComponent, EcsName, "jecs.Component")
|
||||||
world_set(self, EcsOnDelete, EcsName, "jecs.OnDelete")
|
world_set(self, EcsOnDelete, EcsName, "jecs.OnDelete")
|
||||||
|
@ -2490,6 +2513,7 @@ local function world_new()
|
||||||
world_set(self, EcsName, EcsName, "jecs.Name")
|
world_set(self, EcsName, EcsName, "jecs.Name")
|
||||||
world_set(self, EcsRest, EcsRest, "jecs.Rest")
|
world_set(self, EcsRest, EcsRest, "jecs.Rest")
|
||||||
|
|
||||||
|
world_add(self, EcsChildOf, EcsExclusive)
|
||||||
world_add(self, EcsChildOf, ECS_PAIR(EcsOnDeleteTarget, EcsDelete))
|
world_add(self, EcsChildOf, ECS_PAIR(EcsOnDeleteTarget, EcsDelete))
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
@ -2622,6 +2646,7 @@ return {
|
||||||
Delete = EcsDelete :: Entity,
|
Delete = EcsDelete :: Entity,
|
||||||
Remove = EcsRemove :: Entity,
|
Remove = EcsRemove :: Entity,
|
||||||
Name = EcsName :: Entity<string>,
|
Name = EcsName :: Entity<string>,
|
||||||
|
Exclusive = EcsExclusive :: Entity,
|
||||||
Rest = EcsRest :: Entity,
|
Rest = EcsRest :: Entity,
|
||||||
|
|
||||||
pair = (ECS_PAIR :: any) :: <P, O>(first: Id<P>, second: Id<O>) -> Pair<P, O>,
|
pair = (ECS_PAIR :: any) :: <P, O>(first: Id<P>, second: Id<O>) -> Pair<P, O>,
|
||||||
|
|
|
@ -1947,4 +1947,25 @@ TEST("world:delete() invokes OnRemove hook", function()
|
||||||
CHECK(called)
|
CHECK(called)
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
TEST("exclusive relationships", function()
|
||||||
|
local world = world_new()
|
||||||
|
local pair = jecs.pair
|
||||||
|
|
||||||
|
local child = world:entity()
|
||||||
|
|
||||||
|
for _ = 1, 10 do
|
||||||
|
local A = world:entity()
|
||||||
|
local B = world:entity()
|
||||||
|
|
||||||
|
world:add(child, pair(world:entity(), child)) -- noise
|
||||||
|
world:add(child, pair(ChildOf, A))
|
||||||
|
world:add(child, pair(child, world:entity())) -- noise
|
||||||
|
world:add(child, pair(ChildOf, B))
|
||||||
|
|
||||||
|
CHECK(world:has(child, pair(ChildOf, B)))
|
||||||
|
CHECK(not world:has(child, pair(ChildOf, A)))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
FINISH()
|
FINISH()
|
||||||
|
|
Loading…
Reference in a new issue