diff --git a/README.md b/README.md index e8c2d65..a225bf6 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,10 @@ ``` TAG :: fragment NAME :: fragment +PREFAB :: fragment + +UNIQUE :: fragment +EXPLICIT :: fragment DEFAULT :: fragment DUPLICATE :: fragment @@ -140,6 +144,10 @@ builder:clear :: builder builder:tag :: builder builder:name :: string -> builder +builder:prefab :: builder + +builder:unique :: builder +builder:explicit :: builder builder:default :: component -> builder builder:duplicate :: {component -> component} -> builder diff --git a/ROADMAP.md b/ROADMAP.md index 69b31a3..7092a02 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -2,9 +2,6 @@ ## Backlog -- add PREFAB entity trait -- is/has_all/any for lists? - ## After first release - cached queries diff --git a/develop/all.lua b/develop/all.lua index 13d3ed0..1a518e5 100644 --- a/develop/all.lua +++ b/develop/all.lua @@ -9,3 +9,7 @@ print '----------------------------------------' basics.describe_fuzz 'develop.fuzzing.destroy_fuzz' print '----------------------------------------' basics.describe_fuzz 'develop.fuzzing.batch_destroy_fuzz' +print '----------------------------------------' +basics.describe_fuzz 'develop.fuzzing.explicit_fuzz' +print '----------------------------------------' +basics.describe_fuzz 'develop.fuzzing.unique_fuzz' diff --git a/develop/fuzzing/explicit_fuzz.lua b/develop/fuzzing/explicit_fuzz.lua new file mode 100644 index 0000000..6aeb7c6 --- /dev/null +++ b/develop/fuzzing/explicit_fuzz.lua @@ -0,0 +1,81 @@ +local evo = require 'evolved' + +evo.debug_mode(true) + +--- +--- +--- +--- +--- + +local __table_unpack = (function() + ---@diagnostic disable-next-line: deprecated + return table.unpack or unpack +end)() + +--- +--- +--- +--- +--- + +local all_entity_list = {} ---@type evolved.entity[] + +for i = 1, math.random(1, 10) do + local entity = evo.id() + all_entity_list[i] = entity +end + +for _, entity in ipairs(all_entity_list) do + for _ = 0, math.random(0, #all_entity_list) do + local fragment = all_entity_list[math.random(1, #all_entity_list)] + evo.set(entity, fragment) + end + + if math.random(1, 5) == 1 then + evo.set(entity, evo.EXPLICIT) + end +end + +--- +--- +--- +--- +--- + +for _ = 1, 100 do + local include_set = {} ---@type table + local include_list = {} ---@type evolved.entity[] + local include_count = 0 + + for _ = 1, math.random(1, #all_entity_list) do + local include = all_entity_list[math.random(1, #all_entity_list)] + + if not include_set[include] then + include_count = include_count + 1 + include_set[include] = include_count + include_list[include_count] = include + end + end + + local q = evo.builder():include(__table_unpack(include_list)):spawn() + + for chunk in evo.execute(q) do + local fragment_list, fragment_count = chunk:fragments() + for i = 1, fragment_count do + local fragment = fragment_list[i] + assert(include_set[fragment] or not evo.has(fragment, evo.EXPLICIT)) + end + end + + evo.destroy(q) +end + +--- +--- +--- +--- +--- + +evo.destroy(__table_unpack(all_entity_list)) +evo.collect_garbage() diff --git a/develop/fuzzing/unique_fuzz.lua b/develop/fuzzing/unique_fuzz.lua new file mode 100644 index 0000000..731ba5e --- /dev/null +++ b/develop/fuzzing/unique_fuzz.lua @@ -0,0 +1,67 @@ +local evo = require 'evolved' + +evo.debug_mode(true) + +--- +--- +--- +--- +--- + +local __table_unpack = (function() + ---@diagnostic disable-next-line: deprecated + return table.unpack or unpack +end)() + +--- +--- +--- +--- +--- + +local all_entity_list = {} ---@type evolved.entity[] + +for i = 1, math.random(1, 10) do + local entity = evo.id() + all_entity_list[i] = entity +end + +for _, entity in ipairs(all_entity_list) do + for _ = 0, math.random(0, #all_entity_list) do + local fragment = all_entity_list[math.random(1, #all_entity_list)] + evo.set(entity, fragment) + end + + if math.random(1, 5) == 1 then + evo.set(entity, evo.UNIQUE) + end +end + +--- +--- +--- +--- +--- + +for _, entity in ipairs(all_entity_list) do + local entity_clone = evo.clone(entity) + + for fragment in evo.each(entity_clone) do + assert(not evo.has(fragment, evo.UNIQUE)) + end + + for fragment in evo.each(entity) do + assert(evo.has(entity_clone, fragment) or evo.has(fragment, evo.UNIQUE)) + end + + evo.destroy(entity_clone) +end + +--- +--- +--- +--- +--- + +evo.destroy(__table_unpack(all_entity_list)) +evo.collect_garbage() diff --git a/develop/untests.lua b/develop/untests.lua index 0fbfe74..06c1c1f 100644 --- a/develop/untests.lua +++ b/develop/untests.lua @@ -5,7 +5,7 @@ local evo = require 'evolved' evo.debug_mode(true) -do +if os.getenv("LOCAL_LUA_DEBUGGER_VSCODE") == nil then local i = evo.id() for _ = 1, 0xFFFFE do @@ -6156,3 +6156,166 @@ do assert(evo.has(e3g, f3) and evo.get(e3g, f3) == 33) end end + +do + local f1, f2, f3 = evo.id(3) + + evo.set(f2, evo.UNIQUE) + evo.set(f3, evo.UNIQUE) + + do + local p = evo.spawn { [f1] = 11, [f2] = 22 } + local e = evo.clone(p) + + assert(evo.has(p, f1) and evo.get(p, f1) == 11) + assert(evo.has(p, f2) and evo.get(p, f2) == 22) + + assert(evo.has(e, f1) and evo.get(e, f1) == 11) + assert(not evo.has(e, f2) and evo.get(e, f2) == nil) + end + + do + local p = evo.spawn { [f1] = 11, [f2] = 22, [f3] = 33 } + local e = evo.clone(p) + + assert(evo.has(p, f1) and evo.get(p, f1) == 11) + assert(evo.has(p, f2) and evo.get(p, f2) == 22) + assert(evo.has(p, f3) and evo.get(p, f3) == 33) + + assert(evo.has(e, f1) and evo.get(e, f1) == 11) + assert(not evo.has(e, f2) and evo.get(e, f2) == nil) + assert(not evo.has(e, f3) and evo.get(e, f3) == nil) + end + + do + local p = evo.spawn { [f2] = 22 } + local e = evo.clone(p) + + assert(not evo.has(p, f1) and evo.get(p, f1) == nil) + assert(evo.has(p, f2) and evo.get(p, f2) == 22) + assert(not evo.has(p, f3) and evo.get(p, f3) == nil) + + assert(not evo.has(e, f1) and evo.get(e, f1) == nil) + assert(not evo.has(e, f2) and evo.get(e, f2) == nil) + assert(not evo.has(e, f3) and evo.get(e, f3) == nil) + end + do + local p = evo.spawn { [f2] = 22, [f3] = 33 } + local e = evo.clone(p) + + assert(not evo.has(p, f1) and evo.get(p, f1) == nil) + assert(evo.has(p, f2) and evo.get(p, f2) == 22) + assert(evo.has(p, f3) and evo.get(p, f3) == 33) + + assert(not evo.has(e, f1) and evo.get(e, f1) == nil) + assert(not evo.has(e, f2) and evo.get(e, f2) == nil) + assert(not evo.has(e, f3) and evo.get(e, f3) == nil) + end + + do + local p = evo.spawn { [f1] = 11, [f2] = 22 } + local e = evo.clone(p, { [f2] = 2 }) + + assert(evo.has(p, f1) and evo.get(p, f1) == 11) + assert(evo.has(p, f2) and evo.get(p, f2) == 22) + + assert(evo.has(e, f1) and evo.get(e, f1) == 11) + assert(evo.has(e, f2) and evo.get(e, f2) == 2) + end + + do + local p = evo.spawn { [f1] = 11, [f2] = 22 } + local e = evo.clone(p, { [f2] = 2, [f3] = 3 }) + + assert(evo.has(p, f1) and evo.get(p, f1) == 11) + assert(evo.has(p, f2) and evo.get(p, f2) == 22) + + assert(evo.has(e, f1) and evo.get(e, f1) == 11) + assert(evo.has(e, f2) and evo.get(e, f2) == 2) + assert(evo.has(e, f3) and evo.get(e, f3) == 3) + end +end + +do + local f1, f2, f3 = evo.id(3) + + evo.set(f2, evo.UNIQUE) + + do + local p = evo.spawn { [f1] = 11, [f2] = 22, [f3] = 33 } + local e = evo.clone(p) + + assert(evo.has(p, f1) and evo.get(p, f1) == 11) + assert(evo.has(p, f2) and evo.get(p, f2) == 22) + assert(evo.has(p, f3) and evo.get(p, f3) == 33) + + assert(evo.has(e, f1) and evo.get(e, f1) == 11) + assert(not evo.has(e, f2) and evo.get(e, f2) == nil) + assert(evo.has(e, f3) and evo.get(e, f3) == 33) + end +end + +do + local f1, f2 = evo.id(2) + + local p = evo.builder():prefab():set(f1, 11):set(f2, 22):spawn() + local e = evo.clone(p) + + do + local q = evo.builder():include(f1, f2):spawn() + local iter, state = evo.execute(q) + local chunk, entity_list, entity_count = iter(state) + assert(chunk and entity_list and entity_count) + assert(chunk == evo.chunk(f1, f2)) + assert(entity_count == 1 and entity_list[1] == e) + end + + do + local q = evo.builder():exclude(f1):spawn() + + for c in evo.execute(q) do + local fs, fc = c:fragments() + for i = 1, fc do assert(not evo.has(fs[i], evo.EXPLICIT)) end + end + end + + do + local q = evo.builder():spawn() + + for c in evo.execute(q) do + local fs, fc = c:fragments() + for i = 1, fc do assert(not evo.has(fs[i], evo.EXPLICIT)) end + end + end +end + +do + local f1, f2 = evo.id(2) + + evo.set(f2, evo.EXPLICIT) + + local e1 = evo.builder():set(f1, 11):spawn() + local e2 = evo.builder():set(f1, 11):set(f2, 22):spawn() + + do + local q = evo.builder():include(f1):spawn() + local iter, state = evo.execute(q) + local chunk, entity_list, entity_count = iter(state) + assert(chunk and entity_list and entity_count) + assert(chunk == evo.chunk(f1)) + assert(entity_count == 1 and entity_list[1] == e1) + chunk, entity_list, entity_count = iter(state) + assert(not chunk and not entity_list and not entity_count) + end + + do + local q = evo.builder():include(f1, f2):spawn() + local iter, state = evo.execute(q) + local chunk, entity_list, entity_count = iter(state) + assert(chunk and entity_list and entity_count) + assert(chunk == evo.chunk(f1, f2)) + assert(entity_count == 1 and entity_list[1] == e2) + chunk, entity_list, entity_count = iter(state) + assert(not chunk and not entity_list and not entity_count) + end +end diff --git a/evolved.lua b/evolved.lua index 408fdcb..a547b46 100644 --- a/evolved.lua +++ b/evolved.lua @@ -124,6 +124,12 @@ local __query_sorted_excludes = {} ---@type table __EMPTY_FRAGMENT_SET = __lua_setmetatable({}, { - __newindex = function() __error_fmt('attempt to modify empty fragment set') end + __tostring = function() return 'empty fragment set' end, + __newindex = function() __error_fmt 'attempt to modify empty fragment set' end }), ---@type evolved.fragment[] __EMPTY_FRAGMENT_LIST = __lua_setmetatable({}, { - __newindex = function() __error_fmt('attempt to modify empty fragment list') end + __tostring = function() return 'empty fragment list' end, + __newindex = function() __error_fmt 'attempt to modify empty fragment list' end }), ---@type table __EMPTY_COMPONENT_MAP = __lua_setmetatable({}, { - __newindex = function() __error_fmt('attempt to modify empty component map') end + __tostring = function() return 'empty component map' end, + __newindex = function() __error_fmt 'attempt to modify empty component map' end }), ---@type evolved.component[] __EMPTY_COMPONENT_LIST = __lua_setmetatable({}, { - __newindex = function() __error_fmt('attempt to modify empty component list') end + __tostring = function() return 'empty component list' end, + __newindex = function() __error_fmt 'attempt to modify empty component list' end }), ---@type evolved.component[] __EMPTY_COMPONENT_STORAGE = __lua_setmetatable({}, { - __newindex = function() __error_fmt('attempt to modify empty component storage') end + __tostring = function() return 'empty component storage' end, + __newindex = function() __error_fmt 'attempt to modify empty component storage' end }), } @@ -994,18 +1011,26 @@ local function __new_chunk(chunk_parent, chunk_fragment) ---@type evolved.fragment[] local chunk_component_fragments = {} - local has_setup_hooks = (chunk_parent and chunk_parent.__has_setup_hooks) + local has_setup_hooks = (chunk_parent ~= nil and chunk_parent.__has_setup_hooks) or __evolved_has_any(chunk_fragment, __DEFAULT, __DUPLICATE) - local has_assign_hooks = (chunk_parent and chunk_parent.__has_assign_hooks) + local has_assign_hooks = (chunk_parent ~= nil and chunk_parent.__has_assign_hooks) or __evolved_has_any(chunk_fragment, __ON_SET, __ON_ASSIGN) - local has_insert_hooks = (chunk_parent and chunk_parent.__has_insert_hooks) + local has_insert_hooks = (chunk_parent ~= nil and chunk_parent.__has_insert_hooks) or __evolved_has_any(chunk_fragment, __ON_SET, __ON_INSERT) - local has_remove_hooks = (chunk_parent and chunk_parent.__has_remove_hooks) + local has_remove_hooks = (chunk_parent ~= nil and chunk_parent.__has_remove_hooks) or __evolved_has(chunk_fragment, __ON_REMOVE) + local has_unique_major = __evolved_has(chunk_fragment, __UNIQUE) + local has_unique_minors = chunk_parent ~= nil and chunk_parent.__has_unique_fragments + local has_unique_fragments = has_unique_major or has_unique_minors + + local has_explicit_major = __evolved_has(chunk_fragment, __EXPLICIT) + local has_explicit_minors = chunk_parent ~= nil and chunk_parent.__has_explicit_fragments + local has_explicit_fragments = has_explicit_major or has_explicit_minors + ---@type evolved.chunk local chunk = __lua_setmetatable({ __parent = nil, @@ -1029,6 +1054,12 @@ local function __new_chunk(chunk_parent, chunk_fragment) __has_assign_hooks = has_assign_hooks, __has_insert_hooks = has_insert_hooks, __has_remove_hooks = has_remove_hooks, + __has_unique_major = has_unique_major, + __has_unique_minors = has_unique_minors, + __has_unique_fragments = has_unique_fragments, + __has_explicit_major = has_explicit_major, + __has_explicit_minors = has_explicit_minors, + __has_explicit_fragments = has_explicit_fragments, }, __chunk_mt) if chunk_parent then @@ -1213,6 +1244,40 @@ local function __chunk_without_fragments(chunk, ...) return chunk end +---@param chunk? evolved.chunk +---@return evolved.chunk? +---@nodiscard +local function __chunk_without_unique_fragments(chunk) + if not chunk then + return nil + end + + if not chunk.__has_unique_fragments then + return chunk + end + + while chunk and chunk.__has_unique_major do + chunk = chunk.__parent + end + + local new_chunk = nil + + if chunk then + local chunk_fragment_list = chunk.__fragment_list + local chunk_fragment_count = chunk.__fragment_count + + for i = 1, chunk_fragment_count do + local fragment = chunk_fragment_list[i] + + if not __evolved_has(fragment, __UNIQUE) then + new_chunk = __chunk_with_fragment(new_chunk, fragment) + end + end + end + + return new_chunk +end + --- --- --- @@ -1648,7 +1713,9 @@ local function __clone_entity(entity, prefab, components) local prefab_chunk = __entity_chunks[prefab_index] local prefab_place = __entity_places[prefab_index] - local chunk = __chunk_with_components(prefab_chunk, components) + local chunk = __chunk_with_components( + __chunk_without_unique_fragments(prefab_chunk), + components) if not chunk then return @@ -1682,46 +1749,50 @@ local function __clone_entity(entity, prefab, components) if prefab_chunk.__has_setup_hooks then for prefab_component_index = 1, prefab_component_count do local fragment = prefab_component_fragments[prefab_component_index] - - ---@type evolved.duplicate? - local fragment_duplicate = - __evolved_get(fragment, __DUPLICATE) - - local prefab_component_storage = prefab_component_storages[prefab_component_index] - local prefab_component = prefab_component_storage[prefab_place] - - local new_component = prefab_component - - if new_component ~= nil and fragment_duplicate then - new_component = fragment_duplicate(new_component) - end - - if new_component == nil then - new_component = true - end - local component_index = chunk_component_indices[fragment] - local component_storage = chunk_component_storages[component_index] - component_storage[place] = new_component + if component_index then + ---@type evolved.duplicate? + local fragment_duplicate = + __evolved_get(fragment, __DUPLICATE) + + local prefab_component_storage = prefab_component_storages[prefab_component_index] + local prefab_component = prefab_component_storage[prefab_place] + + local new_component = prefab_component + + if new_component ~= nil and fragment_duplicate then + new_component = fragment_duplicate(new_component) + end + + if new_component == nil then + new_component = true + end + + local component_storage = chunk_component_storages[component_index] + + component_storage[place] = new_component + end end else for prefab_component_index = 1, prefab_component_count do local fragment = prefab_component_fragments[prefab_component_index] - - local prefab_component_storage = prefab_component_storages[prefab_component_index] - local prefab_component = prefab_component_storage[prefab_place] - - local new_component = prefab_component - - if new_component == nil then - new_component = true - end - local component_index = chunk_component_indices[fragment] - local component_storage = chunk_component_storages[component_index] - component_storage[place] = new_component + if component_index then + local prefab_component_storage = prefab_component_storages[prefab_component_index] + local prefab_component = prefab_component_storage[prefab_place] + + local new_component = prefab_component + + if new_component == nil then + new_component = true + end + + local component_storage = chunk_component_storages[component_index] + + component_storage[place] = new_component + end end end end @@ -4285,6 +4356,7 @@ function __evolved_execute(query) local chunk_stack_size = 0 local query_includes = __query_sorted_includes[query] + local query_include_set = query_includes and query_includes.__item_set --[[@as table]] local query_include_list = query_includes and query_includes.__item_list --[=[@as evolved.fragment[]]=] local query_include_count = query_includes and query_includes.__item_count or 0 --[[@as integer]] @@ -4309,6 +4381,20 @@ function __evolved_execute(query) (query_exclude_count == 0 or not __chunk_has_any_fragment_list( major_chunk, query_exclude_list, query_exclude_count)) + if is_major_chunk_matched and major_chunk.__has_explicit_minors then + local major_chunk_fragment_list = major_chunk.__fragment_list + local major_chunk_fragment_count = major_chunk.__fragment_count + + for major_chunk_fragment_index = 1, major_chunk_fragment_count - 1 do + local major_chunk_fragment = major_chunk_fragment_list[major_chunk_fragment_index] + + if not query_include_set[major_chunk_fragment] and __evolved_has(major_chunk_fragment, __EXPLICIT) then + is_major_chunk_matched = false + break + end + end + end + if is_major_chunk_matched then chunk_stack_size = chunk_stack_size + 1 chunk_stack[chunk_stack_size] = major_chunk @@ -4316,15 +4402,24 @@ function __evolved_execute(query) end elseif query_exclude_count > 0 then for root_fragment, root_chunk in __lua_next, __root_chunks do - if not query_exclude_set[root_fragment] then + local is_root_chunk_matched = + not root_chunk.__has_explicit_major and + not query_exclude_set[root_fragment] + + if is_root_chunk_matched then chunk_stack_size = chunk_stack_size + 1 chunk_stack[chunk_stack_size] = root_chunk end end else for _, root_chunk in __lua_next, __root_chunks do - chunk_stack_size = chunk_stack_size + 1 - chunk_stack[chunk_stack_size] = root_chunk + local is_root_chunk_matched = + not root_chunk.__has_explicit_major + + if is_root_chunk_matched then + chunk_stack_size = chunk_stack_size + 1 + chunk_stack[chunk_stack_size] = root_chunk + end end end @@ -4856,6 +4951,21 @@ function __builder_mt:name(name) return self:set(__NAME, name) end +---@return evolved.builder builder +function __builder_mt:prefab() + return self:set(__PREFAB) +end + +---@return evolved.builder builder +function __builder_mt:unique() + return self:set(__UNIQUE) +end + +---@return evolved.builder builder +function __builder_mt:explicit() + return self:set(__EXPLICIT) +end + ---@param default evolved.component ---@return evolved.builder builder function __builder_mt:default(default) @@ -4994,23 +5104,39 @@ end local function __update_chunk_caches_trace(chunk) local chunk_parent, chunk_fragment = chunk.__parent, chunk.__fragment - local has_setup_hooks = (chunk_parent and chunk_parent.__has_setup_hooks) + local has_setup_hooks = (chunk_parent ~= nil and chunk_parent.__has_setup_hooks) or __evolved_has_any(chunk_fragment, __DEFAULT, __DUPLICATE) - local has_assign_hooks = (chunk_parent and chunk_parent.__has_assign_hooks) + local has_assign_hooks = (chunk_parent ~= nil and chunk_parent.__has_assign_hooks) or __evolved_has_any(chunk_fragment, __ON_SET, __ON_ASSIGN) - local has_insert_hooks = (chunk_parent and chunk_parent.__has_insert_hooks) + local has_insert_hooks = (chunk_parent ~= nil and chunk_parent.__has_insert_hooks) or __evolved_has_any(chunk_fragment, __ON_SET, __ON_INSERT) - local has_remove_hooks = (chunk_parent and chunk_parent.__has_remove_hooks) + local has_remove_hooks = (chunk_parent ~= nil and chunk_parent.__has_remove_hooks) or __evolved_has(chunk_fragment, __ON_REMOVE) + local has_unique_major = __evolved_has(chunk_fragment, __UNIQUE) + local has_unique_minors = chunk_parent ~= nil and chunk_parent.__has_unique_fragments + local has_unique_fragments = has_unique_major or has_unique_minors + + local has_explicit_major = __evolved_has(chunk_fragment, __EXPLICIT) + local has_explicit_minors = chunk_parent ~= nil and chunk_parent.__has_explicit_fragments + local has_explicit_fragments = has_explicit_major or has_explicit_minors + chunk.__has_setup_hooks = has_setup_hooks chunk.__has_assign_hooks = has_assign_hooks chunk.__has_insert_hooks = has_insert_hooks chunk.__has_remove_hooks = has_remove_hooks + chunk.__has_unique_major = has_unique_major + chunk.__has_unique_minors = has_unique_minors + chunk.__has_unique_fragments = has_unique_fragments + + chunk.__has_explicit_major = has_explicit_major + chunk.__has_explicit_minors = has_explicit_minors + chunk.__has_explicit_fragments = has_explicit_fragments + return true end @@ -5101,6 +5227,14 @@ local function __update_fragment_tags(fragment) __trace_fragment_chunks(fragment, __update_chunk_tags_trace, fragment) end +local function __update_fragment_uniques(fragment) + __trace_fragment_chunks(fragment, __update_chunk_caches_trace, fragment) +end + +local function __update_fragment_explicits(fragment) + __trace_fragment_chunks(fragment, __update_chunk_caches_trace, fragment) +end + ---@param fragment evolved.fragment local function __update_fragment_defaults(fragment) __trace_fragment_chunks(fragment, __update_chunk_caches_trace, fragment) @@ -5114,6 +5248,12 @@ end __evolved_set(__TAG, __ON_INSERT, __update_fragment_tags) __evolved_set(__TAG, __ON_REMOVE, __update_fragment_tags) +__evolved_set(__UNIQUE, __ON_INSERT, __update_fragment_uniques) +__evolved_set(__UNIQUE, __ON_REMOVE, __update_fragment_uniques) + +__evolved_set(__EXPLICIT, __ON_INSERT, __update_fragment_explicits) +__evolved_set(__EXPLICIT, __ON_REMOVE, __update_fragment_explicits) + __evolved_set(__DEFAULT, __ON_INSERT, __update_fragment_defaults) __evolved_set(__DEFAULT, __ON_REMOVE, __update_fragment_defaults) @@ -5128,6 +5268,10 @@ __evolved_set(__DUPLICATE, __ON_REMOVE, __update_fragment_duplicates) __evolved_set(__TAG, __NAME, 'TAG') __evolved_set(__NAME, __NAME, 'NAME') +__evolved_set(__PREFAB, __NAME, 'PREFAB') + +__evolved_set(__UNIQUE, __NAME, 'UNIQUE') +__evolved_set(__EXPLICIT, __NAME, 'EXPLICIT') __evolved_set(__DEFAULT, __NAME, 'DEFAULT') __evolved_set(__DUPLICATE, __NAME, 'DUPLICATE') @@ -5162,12 +5306,25 @@ __evolved_set(__DESTROY_POLICY_REMOVE_FRAGMENT, __NAME, 'DESTROY_POLICY_REMOVE_F __evolved_set(__TAG, __TAG) +__evolved_set(__PREFAB, __TAG) +__evolved_set(__PREFAB, __UNIQUE) +__evolved_set(__PREFAB, __EXPLICIT) + +__evolved_set(__UNIQUE, __TAG) + +__evolved_set(__EXPLICIT, __TAG) + __evolved_set(__INCLUDES, __DEFAULT, {}) __evolved_set(__INCLUDES, __DUPLICATE, __list_copy) __evolved_set(__EXCLUDES, __DEFAULT, {}) __evolved_set(__EXCLUDES, __DUPLICATE, __list_copy) +__evolved_set(__ON_SET, __UNIQUE) +__evolved_set(__ON_ASSIGN, __UNIQUE) +__evolved_set(__ON_INSERT, __UNIQUE) +__evolved_set(__ON_REMOVE, __UNIQUE) + __evolved_set(__DISABLED, __TAG) --- @@ -5290,6 +5447,10 @@ end) evolved.TAG = __TAG evolved.NAME = __NAME +evolved.PREFAB = __PREFAB + +evolved.UNIQUE = __UNIQUE +evolved.EXPLICIT = __EXPLICIT evolved.DEFAULT = __DEFAULT evolved.DUPLICATE = __DUPLICATE @@ -5335,12 +5496,12 @@ evolved.empty = __evolved_empty evolved.empty_all = __evolved_empty_all evolved.empty_any = __evolved_empty_any -evolved.get = __evolved_get - evolved.has = __evolved_has evolved.has_all = __evolved_has_all evolved.has_any = __evolved_has_any +evolved.get = __evolved_get + evolved.set = __evolved_set evolved.remove = __evolved_remove evolved.clear = __evolved_clear