mirror of
				https://github.com/Ukendio/jecs.git
				synced 2025-11-03 18:39:19 +00:00 
			
		
		
		
	Handle wildcard pairs in observers
This commit is contained in:
		
							parent
							
								
									4ed2fb7a40
								
							
						
					
					
						commit
						23bf021f01
					
				
					 3 changed files with 149 additions and 31 deletions
				
			
		
							
								
								
									
										123
									
								
								addons/ob.luau
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								addons/ob.luau
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -77,19 +77,38 @@ local function observers_new<T...>(
 | 
			
		|||
   	if without then
 | 
			
		||||
		for _, term in without do
 | 
			
		||||
			if jecs.IS_PAIR(term) then
 | 
			
		||||
				term = jecs.ECS_PAIR_FIRST(term)
 | 
			
		||||
			end
 | 
			
		||||
			local onremoved = world:removed(term, function(entity, id)
 | 
			
		||||
				local r = jecs.record(world, entity)
 | 
			
		||||
				local archetype = r.archetype
 | 
			
		||||
				if archetype then
 | 
			
		||||
					local dst = jecs.archetype_traverse_remove(world, id, archetype)
 | 
			
		||||
					if archetypes[dst.id] then
 | 
			
		||||
						callback(entity)
 | 
			
		||||
				local rel = jecs.ECS_PAIR_SECOND(term)
 | 
			
		||||
				local tgt = jecs.ECS_PAIR_SECOND(term)
 | 
			
		||||
				local wc = tgt == jecs.w
 | 
			
		||||
				local onremoved = world:removed(term, function(entity, id)
 | 
			
		||||
					local r = jecs.record(world, entity)
 | 
			
		||||
					local archetype = r.archetype
 | 
			
		||||
					if archetype then
 | 
			
		||||
						if not wc and id ~= tgt then
 | 
			
		||||
							return
 | 
			
		||||
						end
 | 
			
		||||
						local dst = jecs.archetype_traverse_remove(world, id, archetype)
 | 
			
		||||
						if archetypes[dst.id] then
 | 
			
		||||
							callback(entity)
 | 
			
		||||
						end
 | 
			
		||||
					end
 | 
			
		||||
				end
 | 
			
		||||
			end)
 | 
			
		||||
			table.insert(cleanup, onremoved)
 | 
			
		||||
				end)
 | 
			
		||||
 | 
			
		||||
				table.insert(cleanup, onremoved)
 | 
			
		||||
			else
 | 
			
		||||
				local onremoved = world:removed(term, function(entity, id)
 | 
			
		||||
					local r = jecs.record(world, entity)
 | 
			
		||||
					local archetype = r.archetype
 | 
			
		||||
					if archetype then
 | 
			
		||||
						local dst = jecs.archetype_traverse_remove(world, id, archetype)
 | 
			
		||||
						if archetypes[dst.id] then
 | 
			
		||||
							callback(entity)
 | 
			
		||||
						end
 | 
			
		||||
					end
 | 
			
		||||
				end)
 | 
			
		||||
 | 
			
		||||
				table.insert(cleanup, onremoved)
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -192,24 +211,70 @@ local function monitors_new<T...>(query: Query<T...>): Observer<T...>
 | 
			
		|||
   	if without then
 | 
			
		||||
	   	for _, term in without do
 | 
			
		||||
			if jecs.IS_PAIR(term) then
 | 
			
		||||
				term = jecs.ECS_PAIR_FIRST(term)
 | 
			
		||||
			end
 | 
			
		||||
			local onadded = world:added(term, removed)
 | 
			
		||||
			local onremoved = world:removed(term, function(entity, id)
 | 
			
		||||
				if callback_added == nil then
 | 
			
		||||
					return
 | 
			
		||||
				end
 | 
			
		||||
				local r = jecs.record(world, entity)
 | 
			
		||||
				local archetype = r.archetype
 | 
			
		||||
				if archetype then
 | 
			
		||||
					local dst = jecs.archetype_traverse_remove(world, id, archetype)
 | 
			
		||||
					if archetypes[dst.id] then
 | 
			
		||||
						callback_added(entity)
 | 
			
		||||
				local rel = jecs.ECS_PAIR_FIRST(term)
 | 
			
		||||
				local tgt = jecs.ECS_PAIR_SECOND(term)
 | 
			
		||||
				local wc = tgt == jecs.w
 | 
			
		||||
				local onadded = world:added(rel, function(entity, id)
 | 
			
		||||
					if callback_removed == nil then
 | 
			
		||||
						return
 | 
			
		||||
					end
 | 
			
		||||
				end
 | 
			
		||||
			end)
 | 
			
		||||
			table.insert(cleanup, onadded)
 | 
			
		||||
			table.insert(cleanup, onremoved)
 | 
			
		||||
					local r = jecs.record(world, entity)
 | 
			
		||||
					local archetype = r.archetype
 | 
			
		||||
					if archetype then
 | 
			
		||||
						if not wc and id ~= term then
 | 
			
		||||
							return
 | 
			
		||||
						end
 | 
			
		||||
						local dst = jecs.archetype_traverse_remove(world, id, archetype)
 | 
			
		||||
						if archetypes[dst.id] then
 | 
			
		||||
							callback_removed(entity)
 | 
			
		||||
						end
 | 
			
		||||
					end
 | 
			
		||||
				end)
 | 
			
		||||
				local onremoved = world:removed(rel, function(entity, id)
 | 
			
		||||
					if callback_added == nil then
 | 
			
		||||
						return
 | 
			
		||||
					end
 | 
			
		||||
					local r = jecs.record(world, entity)
 | 
			
		||||
					local archetype = r.archetype
 | 
			
		||||
					if archetype then
 | 
			
		||||
						local dst = jecs.archetype_traverse_remove(world, id, archetype)
 | 
			
		||||
						if archetypes[dst.id] then
 | 
			
		||||
							callback_added(entity)
 | 
			
		||||
						end
 | 
			
		||||
					end
 | 
			
		||||
				end)
 | 
			
		||||
				table.insert(cleanup, onadded)
 | 
			
		||||
				table.insert(cleanup, onremoved)
 | 
			
		||||
			else
 | 
			
		||||
				local onadded = world:added(term, function(entity, id)
 | 
			
		||||
					if callback_removed == nil then
 | 
			
		||||
						return
 | 
			
		||||
					end
 | 
			
		||||
					local r = jecs.record(world, entity)
 | 
			
		||||
					local archetype = r.archetype
 | 
			
		||||
					if archetype then
 | 
			
		||||
						local dst = jecs.archetype_traverse_remove(world, id, archetype)
 | 
			
		||||
						if archetypes[dst.id] then
 | 
			
		||||
							callback_removed(entity)
 | 
			
		||||
						end
 | 
			
		||||
					end
 | 
			
		||||
				end)
 | 
			
		||||
				local onremoved = world:removed(term, function(entity, id)
 | 
			
		||||
					if callback_added == nil then
 | 
			
		||||
						return
 | 
			
		||||
					end
 | 
			
		||||
					local r = jecs.record(world, entity)
 | 
			
		||||
					local archetype = r.archetype
 | 
			
		||||
					if archetype then
 | 
			
		||||
						local dst = jecs.archetype_traverse_remove(world, id, archetype)
 | 
			
		||||
						if archetypes[dst.id] then
 | 
			
		||||
							callback_added(entity)
 | 
			
		||||
						end
 | 
			
		||||
					end
 | 
			
		||||
				end)
 | 
			
		||||
				table.insert(cleanup, onadded)
 | 
			
		||||
				table.insert(cleanup, onremoved)
 | 
			
		||||
			end
 | 
			
		||||
    	end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3244,8 +3244,7 @@ local function world_new()
 | 
			
		|||
	return world
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- type function ecs_id_t(entity)
 | 
			
		||||
-- 	local ty = entity:components()[2]
 | 
			
		||||
-- type function ecs_id_t(ty)
 | 
			
		||||
-- 	local __T = ty:readproperty(types.singleton("__T"))
 | 
			
		||||
-- 	if not __T then
 | 
			
		||||
-- 		return ty:readproperty(types.singleton("__jecs_pair_value"))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,60 @@ TEST("addons/ob", function()
 | 
			
		|||
		CHECK(c==2)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	do CASE "Should support query:without(pair(R, t1)) when adding pair(R, t2)"
 | 
			
		||||
		local A = world:component()
 | 
			
		||||
		local B = world:component()
 | 
			
		||||
		local C = world:component()
 | 
			
		||||
		local D = world:component()
 | 
			
		||||
 | 
			
		||||
		local c = 1
 | 
			
		||||
		local r = 1
 | 
			
		||||
		local monitor = ob.monitor(world:query(A):without(jecs.pair(B, C)))
 | 
			
		||||
		monitor.added(function()
 | 
			
		||||
			c += 1
 | 
			
		||||
		end)
 | 
			
		||||
		monitor.removed(function()
 | 
			
		||||
			r += 1
 | 
			
		||||
		end)
 | 
			
		||||
 | 
			
		||||
		local child = world:entity()
 | 
			
		||||
		world:add(child, A)
 | 
			
		||||
		CHECK(c==2)
 | 
			
		||||
		world:add(child, jecs.pair(B, D))
 | 
			
		||||
		CHECK(c==2)
 | 
			
		||||
		CHECK(r==1)
 | 
			
		||||
		world:add(child, jecs.pair(B, C))
 | 
			
		||||
		CHECK(c==2)
 | 
			
		||||
		CHECK(r==2)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	do CASE "Should support query:without(pair(R, *)) when adding pair(R, t1)"
 | 
			
		||||
		local A = world:component()
 | 
			
		||||
		local B = world:component()
 | 
			
		||||
		local C = world:component()
 | 
			
		||||
		local D = world:component()
 | 
			
		||||
 | 
			
		||||
		local c = 1
 | 
			
		||||
		local r = 1
 | 
			
		||||
		local monitor = ob.monitor(world:query(A):without(jecs.pair(B, jecs.w)))
 | 
			
		||||
		monitor.added(function()
 | 
			
		||||
			c += 1
 | 
			
		||||
		end)
 | 
			
		||||
		monitor.removed(function()
 | 
			
		||||
			r += 1
 | 
			
		||||
		end)
 | 
			
		||||
 | 
			
		||||
		local child = world:entity()
 | 
			
		||||
		world:add(child, A)
 | 
			
		||||
		CHECK(c==2)
 | 
			
		||||
		world:add(child, jecs.pair(B, D))
 | 
			
		||||
		CHECK(c==2)
 | 
			
		||||
		CHECK(r==2)
 | 
			
		||||
		world:add(child, jecs.pair(B, C))
 | 
			
		||||
		CHECK(c==2)
 | 
			
		||||
		CHECK(r==2)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	do CASE "Should support query:without()"
 | 
			
		||||
		local A = world:component()
 | 
			
		||||
		local B = world:component()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue