From b97aff78159bdb34ca5e3e645b506b657c982943 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Mon, 25 Nov 2024 17:38:05 +0700 Subject: [PATCH] include/exclude functions impl --- develop/untests/registry_untests.lua | 94 ++++++++++++++++++---------- evolved/registry.lua | 66 ++++++++++++++++--- 2 files changed, 118 insertions(+), 42 deletions(-) diff --git a/develop/untests/registry_untests.lua b/develop/untests/registry_untests.lua index c473490..6306f33 100644 --- a/develop/untests/registry_untests.lua +++ b/develop/untests/registry_untests.lua @@ -298,38 +298,19 @@ for _ = 1, 100 do end do - local f1, f2, f3 = evo.registry.entity(), evo.registry.entity(), evo.registry.entity() + local f1, f2, f3, f4 = + evo.registry.entity(), + evo.registry.entity(), + evo.registry.entity(), + evo.registry.entity() - local e1 = evo.registry.entity() - e1:insert(f1) + local e1 = evo.registry.entity():set(f1) + local e2 = evo.registry.entity():set(f1):set(f2) + local e3 = evo.registry.entity():set(f1):set(f2):set(f3) - local e2 = evo.registry.entity() - e2:insert(f1) - e2:insert(f2) - - local e3 = evo.registry.entity() - e3:insert(f1) - e3:insert(f2) - e3:insert(f3) - - do - local e = evo.registry.entity() - - e:insert(f1) - e:remove(f1) - - e:insert(f1) - e:insert(f2) - e:remove(f1) - e:remove(f2) - - e:insert(f1) - e:insert(f2) - e:insert(f3) - e:remove(f1) - e:remove(f2) - e:remove(f3) - end + local e4 = evo.registry.entity():set(f1):set(f4) + local e5 = evo.registry.entity():set(f1):set(f2):set(f4) + local e6 = evo.registry.entity():set(f1):set(f2):set(f3):set(f4) local q1 = evo.registry.query(f1) local q2 = evo.registry.query(f1, f2, f1) @@ -345,6 +326,9 @@ do table.insert(entities, e) end end + table.sort(entities, function(a, b) + return a.__guid < b.__guid + end) return entities end @@ -368,7 +352,51 @@ do assert(is_array_equal(q2.__includes, { f1, f2 })) assert(is_array_equal(q3.__includes, { f1, f2, f3 })) - assert(is_array_equal(collect_query_entities(q1), { e1, e2, e3 })) - assert(is_array_equal(collect_query_entities(q2), { e2, e3 })) - assert(is_array_equal(collect_query_entities(q3), { e3 })) + assert(is_array_equal(collect_query_entities(q1), { e1, e2, e3, e4, e5, e6 })) + assert(is_array_equal(collect_query_entities(q2), { e2, e3, e5, e6 })) + assert(is_array_equal(collect_query_entities(q3), { e3, e6 })) +end + +do + local f1, f2, f3, f4, f5 = + evo.registry.entity(), + evo.registry.entity(), + evo.registry.entity(), + evo.registry.entity(), + evo.registry.entity() + + local query = evo.registry.query(f1, f1) + assert(query == query:include(f2, f3, f2)) + assert(query == query:exclude(f4, f5, f5)) + + ---@param q evolved.query + ---@param f evolved.entity + ---@return boolean + ---@nodiscard + local function includes(q, f) + for _, qf in ipairs(q.__includes) do + if qf:guid() == f:guid() then + return true + end + end + return false + end + + ---@param q evolved.query + ---@param f evolved.entity + ---@return boolean + ---@nodiscard + local function excludes(q, f) + for _, qf in ipairs(q.__excludes) do + if qf:guid() == f:guid() then + return true + end + end + return false + end + + assert(includes(query, f1) and includes(query, f2) and includes(query, f3)) + assert(not includes(query, f4) and not includes(query, f5)) + assert(excludes(query, f4) and excludes(query, f5)) + assert(not excludes(query, f1) and not excludes(query, f2) and not excludes(query, f3)) end diff --git a/evolved/registry.lua b/evolved/registry.lua index 160a078..6dbb477 100644 --- a/evolved/registry.lua +++ b/evolved/registry.lua @@ -29,6 +29,7 @@ evolved_entity_mt.__index = evolved_entity_mt ---@class evolved.query ---@field package __includes evolved.entity[] +---@field package __excludes evolved.entity[] local evolved_query_mt = {} evolved_query_mt.__index = evolved_query_mt @@ -546,6 +547,7 @@ function registry.query(fragment, ...) ---@type evolved.query local query = { __includes = fragment_list, + __excludes = {}, } return setmetatable(query, evolved_query_mt) @@ -555,7 +557,26 @@ end ---@param ... evolved.entity fragments ---@return evolved.query function registry.include(query, ...) - error('not impl yet', 2) + ---@type table + local fragment_set = {} + local fragment_list = query.__includes + + for _, f in ipairs(fragment_list) do + fragment_set[f] = true + end + + for i = 1, select('#', ...) do + local f = select(i, ...) + if not fragment_set[f] then + fragment_set[f] = true + fragment_list[#fragment_list + 1] = f + end + end + + table.sort(fragment_list, function(a, b) + return a.__guid < b.__guid + end) + return query end @@ -563,7 +584,26 @@ end ---@param ... evolved.entity fragments ---@return evolved.query function registry.exclude(query, ...) - error('not impl yet', 2) + ---@type table + local fragment_set = {} + local fragment_list = query.__excludes + + for _, f in ipairs(fragment_list) do + fragment_set[f] = true + end + + for i = 1, select('#', ...) do + local f = select(i, ...) + if not fragment_set[f] then + fragment_set[f] = true + fragment_list[#fragment_list + 1] = f + end + end + + table.sort(fragment_list, function(a, b) + return a.__guid < b.__guid + end) + return query end @@ -571,6 +611,10 @@ end ---@return fun(): evolved.chunk? ---@nodiscard function registry.execute(query) + if #query.__excludes > 0 then + error('excluding fragments is not supported yet', 2) + end + local main_fragment = query.__includes[#query.__includes] local main_fragment_chunks = __chunks[main_fragment] or {} @@ -664,13 +708,17 @@ evolved_entity_mt.remove = registry.remove evolved_entity_mt.clear = registry.clear function evolved_query_mt:__tostring() - local fragment_ids = '' + local str = '' - for _, fragment in ipairs(self.__includes) do - fragment_ids = string.format('%s%s', fragment_ids, fragment) + for i, f in ipairs(self.__includes) do + str = string.format('%s%s%s', str, i > 1 and '+' or '', f) end - return string.format('(%s)', fragment_ids) + for _, f in ipairs(self.__excludes) do + str = string.format('%s-%s', str, f) + end + + return string.format('(%s)', str) end evolved_query_mt.include = registry.include @@ -678,14 +726,14 @@ evolved_query_mt.exclude = registry.exclude evolved_query_mt.execute = registry.execute function evolved_chunk_mt:__tostring() - local fragment_ids = '' + local str = '' local chunk_iter = self; while chunk_iter do - fragment_ids = string.format('%s%s', chunk_iter.__fragment, fragment_ids) + str = string.format('%s%s', chunk_iter.__fragment, str) chunk_iter = chunk_iter.__parent end - return string.format('{%s}', fragment_ids) + return string.format('{%s}', str) end evolved_chunk_mt.entities = registry.entities