mirror of
https://github.com/Ukendio/jecs.git
synced 2025-08-04 03:09:18 +00:00
Add exclusive relationship
This commit is contained in:
parent
53f705ac2e
commit
12d88496f0
2 changed files with 41 additions and 7 deletions
33
jecs.luau
33
jecs.luau
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
--!optimize 2
|
--!optimize 2
|
||||||
--!native
|
--!native
|
||||||
--!strict
|
--!strict
|
||||||
|
@ -186,9 +187,10 @@ 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_PAIR_OFFSET = 2^48
|
local ECS_PAIR_OFFSET = 2^48
|
||||||
|
|
||||||
local ECS_ID_DELETE = 0b01
|
local ECS_ID_DELETE = 0b0001
|
||||||
local ECS_ID_IS_TAG = 0b10
|
local ECS_ID_IS_TAG = 0b0010
|
||||||
local ECS_ID_MASK = 0b00
|
local ECS_ID_IS_EXCLUSIVE = 0b0100
|
||||||
|
local ECS_ID_MASK = 0b0000
|
||||||
|
|
||||||
local HI_COMPONENT_ID = 256
|
local HI_COMPONENT_ID = 256
|
||||||
local EcsOnAdd = HI_COMPONENT_ID + 1
|
local EcsOnAdd = HI_COMPONENT_ID + 1
|
||||||
|
@ -204,7 +206,8 @@ 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 EcsOnArchetypeCreate = HI_COMPONENT_ID + 12
|
||||||
local EcsOnArchetypeDelete = HI_COMPONENT_ID + 13
|
local EcsOnArchetypeDelete = HI_COMPONENT_ID + 13
|
||||||
local EcsRest = HI_COMPONENT_ID + 14
|
local EcsExclusive = HI_COMPONENT_ID + 14
|
||||||
|
local EcsRest = HI_COMPONENT_ID + 15
|
||||||
|
|
||||||
local NULL_ARRAY = table.freeze({}) :: Column
|
local NULL_ARRAY = table.freeze({}) :: Column
|
||||||
local NULL = newproxy(false)
|
local NULL = newproxy(false)
|
||||||
|
@ -673,6 +676,7 @@ local function id_record_ensure(world: World, id: Entity): ComponentRecord
|
||||||
local is_pair = ECS_IS_PAIR(id :: number)
|
local is_pair = ECS_IS_PAIR(id :: number)
|
||||||
|
|
||||||
local has_delete = false
|
local has_delete = false
|
||||||
|
local is_exclusive = false
|
||||||
|
|
||||||
if is_pair then
|
if is_pair then
|
||||||
relation = entity_index_get_alive(entity_index, ECS_PAIR_FIRST(id :: number)) :: i53
|
relation = entity_index_get_alive(entity_index, ECS_PAIR_FIRST(id :: number)) :: i53
|
||||||
|
@ -687,6 +691,10 @@ local function id_record_ensure(world: World, id: Entity): ComponentRecord
|
||||||
if cleanup_policy_target == EcsDelete then
|
if cleanup_policy_target == EcsDelete then
|
||||||
has_delete = true
|
has_delete = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if world_has_one_inline(world, relation, EcsExclusive) then
|
||||||
|
is_exclusive = true
|
||||||
|
end
|
||||||
else
|
else
|
||||||
local cleanup_policy = world_target(world, relation, EcsOnDelete, 0)
|
local cleanup_policy = world_target(world, relation, EcsOnDelete, 0)
|
||||||
|
|
||||||
|
@ -708,7 +716,8 @@ local function id_record_ensure(world: World, id: Entity): ComponentRecord
|
||||||
flags = bit32.bor(
|
flags = bit32.bor(
|
||||||
flags,
|
flags,
|
||||||
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_IS_EXCLUSIVE else 0
|
||||||
)
|
)
|
||||||
|
|
||||||
idr = {
|
idr = {
|
||||||
|
@ -919,9 +928,20 @@ end
|
||||||
|
|
||||||
local function find_archetype_with(world: World, id: Id, from: Archetype): Archetype
|
local function find_archetype_with(world: World, id: Id, from: Archetype): Archetype
|
||||||
local id_types = from.types
|
local id_types = from.types
|
||||||
|
local dst = table.clone(id_types)
|
||||||
|
|
||||||
|
if ECS_IS_PAIR(id::number) then
|
||||||
|
local first = ECS_PAIR_FIRST(id::number)
|
||||||
|
local idr = world.component_index[ECS_PAIR(first, EcsWildcard)]
|
||||||
|
if idr and bit32.btest(idr.flags, EcsExclusive) then
|
||||||
|
local cr = idr.records[from.id]
|
||||||
|
dst[cr] = id
|
||||||
|
return archetype_ensure(world, dst)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local at = find_insert(id_types :: { number } , id :: number)
|
local at = find_insert(id_types :: { number } , id :: number)
|
||||||
local dst = table.clone(id_types)
|
|
||||||
table.insert(dst, at, id)
|
table.insert(dst, at, id)
|
||||||
|
|
||||||
return archetype_ensure(world, dst)
|
return archetype_ensure(world, dst)
|
||||||
|
@ -2903,6 +2923,7 @@ return {
|
||||||
Delete = (EcsDelete :: any) :: Entity,
|
Delete = (EcsDelete :: any) :: Entity,
|
||||||
Remove = (EcsRemove :: any) :: Entity,
|
Remove = (EcsRemove :: any) :: Entity,
|
||||||
Name = (EcsName :: any) :: Entity<string>,
|
Name = (EcsName :: any) :: Entity<string>,
|
||||||
|
Exclusive = EcsExclusive :: Entity,
|
||||||
Rest = (EcsRest :: any) :: Entity,
|
Rest = (EcsRest :: any) :: 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>,
|
||||||
|
|
|
@ -24,9 +24,22 @@ type Id<T=unknown> = jecs.Id<T>
|
||||||
local entity_visualiser = require("@tools/entity_visualiser")
|
local entity_visualiser = require("@tools/entity_visualiser")
|
||||||
local dwi = entity_visualiser.stringify
|
local dwi = entity_visualiser.stringify
|
||||||
|
|
||||||
TEST("repro", function()
|
FOCUS()
|
||||||
|
TEST("exclusive", function()
|
||||||
|
local world = jecs.world()
|
||||||
|
local A = world:component()
|
||||||
|
world:add(A, jecs.Exclusive)
|
||||||
|
|
||||||
|
local B = world:component()
|
||||||
|
local C = world:component()
|
||||||
|
|
||||||
|
local e = world:entity()
|
||||||
|
world:add(e, pair(A, B))
|
||||||
|
world:add(e, pair(A, C))
|
||||||
|
|
||||||
|
CHECK(world:has(e, pair(A, B)) == false)
|
||||||
|
CHECK(world:has(e, pair(A, C)) == true)
|
||||||
|
-- print(jecs.entity_index_try_get(world.entity_index, e).archetype.type)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
TEST("bulk", function()
|
TEST("bulk", function()
|
||||||
|
|
Loading…
Reference in a new issue