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
 | 
					   	if without then
 | 
				
			||||||
		for _, term in without do
 | 
							for _, term in without do
 | 
				
			||||||
			if jecs.IS_PAIR(term) then
 | 
								if jecs.IS_PAIR(term) then
 | 
				
			||||||
				term = jecs.ECS_PAIR_FIRST(term)
 | 
									local rel = jecs.ECS_PAIR_SECOND(term)
 | 
				
			||||||
			end
 | 
									local tgt = jecs.ECS_PAIR_SECOND(term)
 | 
				
			||||||
			local onremoved = world:removed(term, function(entity, id)
 | 
									local wc = tgt == jecs.w
 | 
				
			||||||
				local r = jecs.record(world, entity)
 | 
									local onremoved = world:removed(term, function(entity, id)
 | 
				
			||||||
				local archetype = r.archetype
 | 
										local r = jecs.record(world, entity)
 | 
				
			||||||
				if archetype then
 | 
										local archetype = r.archetype
 | 
				
			||||||
					local dst = jecs.archetype_traverse_remove(world, id, archetype)
 | 
										if archetype then
 | 
				
			||||||
					if archetypes[dst.id] then
 | 
											if not wc and id ~= tgt then
 | 
				
			||||||
						callback(entity)
 | 
												return
 | 
				
			||||||
 | 
											end
 | 
				
			||||||
 | 
											local dst = jecs.archetype_traverse_remove(world, id, archetype)
 | 
				
			||||||
 | 
											if archetypes[dst.id] then
 | 
				
			||||||
 | 
												callback(entity)
 | 
				
			||||||
 | 
											end
 | 
				
			||||||
					end
 | 
										end
 | 
				
			||||||
				end
 | 
									end)
 | 
				
			||||||
			end)
 | 
					
 | 
				
			||||||
			table.insert(cleanup, onremoved)
 | 
									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
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -192,24 +211,70 @@ local function monitors_new<T...>(query: Query<T...>): Observer<T...>
 | 
				
			||||||
   	if without then
 | 
					   	if without then
 | 
				
			||||||
	   	for _, term in without do
 | 
						   	for _, term in without do
 | 
				
			||||||
			if jecs.IS_PAIR(term) then
 | 
								if jecs.IS_PAIR(term) then
 | 
				
			||||||
				term = jecs.ECS_PAIR_FIRST(term)
 | 
									local rel = jecs.ECS_PAIR_FIRST(term)
 | 
				
			||||||
			end
 | 
									local tgt = jecs.ECS_PAIR_SECOND(term)
 | 
				
			||||||
			local onadded = world:added(term, removed)
 | 
									local wc = tgt == jecs.w
 | 
				
			||||||
			local onremoved = world:removed(term, function(entity, id)
 | 
									local onadded = world:added(rel, function(entity, id)
 | 
				
			||||||
				if callback_added == nil then
 | 
										if callback_removed == nil then
 | 
				
			||||||
					return
 | 
											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
 | 
										local r = jecs.record(world, entity)
 | 
				
			||||||
			end)
 | 
										local archetype = r.archetype
 | 
				
			||||||
			table.insert(cleanup, onadded)
 | 
										if archetype then
 | 
				
			||||||
			table.insert(cleanup, onremoved)
 | 
											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
 | 
				
			||||||
    end
 | 
					    end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3244,8 +3244,7 @@ local function world_new()
 | 
				
			||||||
	return world
 | 
						return world
 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- type function ecs_id_t(entity)
 | 
					-- type function ecs_id_t(ty)
 | 
				
			||||||
-- 	local ty = entity:components()[2]
 | 
					 | 
				
			||||||
-- 	local __T = ty:readproperty(types.singleton("__T"))
 | 
					-- 	local __T = ty:readproperty(types.singleton("__T"))
 | 
				
			||||||
-- 	if not __T then
 | 
					-- 	if not __T then
 | 
				
			||||||
-- 		return ty:readproperty(types.singleton("__jecs_pair_value"))
 | 
					-- 		return ty:readproperty(types.singleton("__jecs_pair_value"))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,6 +24,60 @@ TEST("addons/ob", function()
 | 
				
			||||||
		CHECK(c==2)
 | 
							CHECK(c==2)
 | 
				
			||||||
	end
 | 
						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()"
 | 
						do CASE "Should support query:without()"
 | 
				
			||||||
		local A = world:component()
 | 
							local A = world:component()
 | 
				
			||||||
		local B = world:component()
 | 
							local B = world:component()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue