mirror of
https://github.com/Ukendio/jecs.git
synced 2025-04-25 09:30:03 +00:00
Merge branch 'main' of https://github.com/Ukendio/jecs into add-clear
This commit is contained in:
commit
c426436104
1 changed files with 43 additions and 50 deletions
|
@ -640,34 +640,31 @@ export type Query = typeof(EmptyQuery)
|
||||||
|
|
||||||
type CompatibleArchetype = { archetype: Archetype, indices: { number } }
|
type CompatibleArchetype = { archetype: Archetype, indices: { number } }
|
||||||
|
|
||||||
local function PreparedQuery(compatibleArchetypes: { CompatibleArchetype } , components: { i53 })
|
local function preparedQuery(compatibleArchetypes: { Archetype },
|
||||||
|
components: { i53? }, indices: { { number } })
|
||||||
|
|
||||||
local queryLength = #components
|
local queryLength = #components
|
||||||
|
|
||||||
local lastArchetype = 1
|
local lastArchetype = 1
|
||||||
local compatibleArchetype: CompatibleArchetype = compatibleArchetypes[lastArchetype]
|
local archetype: Archetype = compatibleArchetypes[lastArchetype]
|
||||||
|
|
||||||
if not compatibleArchetype then
|
if not archetype then
|
||||||
return EmptyQuery
|
return EmptyQuery
|
||||||
end
|
end
|
||||||
|
|
||||||
local preparedQuery = {}
|
|
||||||
preparedQuery.__index = preparedQuery
|
|
||||||
|
|
||||||
local queryOutput = {}
|
local queryOutput = {}
|
||||||
|
|
||||||
local i = 1
|
local i = 1
|
||||||
|
|
||||||
local function queryNext(): ...any
|
local function queryNext(): ...any
|
||||||
local archetype = compatibleArchetype.archetype
|
|
||||||
local entityId = archetype.entities[i]
|
local entityId = archetype.entities[i]
|
||||||
|
|
||||||
while entityId == nil do
|
while entityId == nil do
|
||||||
lastArchetype += 1
|
lastArchetype += 1
|
||||||
if lastArchetype > #compatibleArchetypes then
|
archetype = compatibleArchetypes[lastArchetype]
|
||||||
|
if not archetype then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
compatibleArchetype = compatibleArchetypes[lastArchetype]
|
|
||||||
archetype = compatibleArchetype.archetype
|
|
||||||
i = 1
|
i = 1
|
||||||
entityId = archetype.entities[i]
|
entityId = archetype.entities[i]
|
||||||
end
|
end
|
||||||
|
@ -676,7 +673,7 @@ local function PreparedQuery(compatibleArchetypes: { CompatibleArchetype } , com
|
||||||
i+=1
|
i+=1
|
||||||
|
|
||||||
local columns = archetype.columns
|
local columns = archetype.columns
|
||||||
local tr = compatibleArchetype.indices
|
local tr = indices[lastArchetype]
|
||||||
|
|
||||||
if queryLength == 1 then
|
if queryLength == 1 then
|
||||||
return entityId, columns[tr[1]][row]
|
return entityId, columns[tr[1]][row]
|
||||||
|
@ -728,19 +725,11 @@ local function PreparedQuery(compatibleArchetypes: { CompatibleArchetype } , com
|
||||||
|
|
||||||
return entityId, unpack(queryOutput, 1, queryLength)
|
return entityId, unpack(queryOutput, 1, queryLength)
|
||||||
end
|
end
|
||||||
|
|
||||||
function preparedQuery:__iter(): () -> ...any
|
|
||||||
return queryNext
|
|
||||||
end
|
|
||||||
|
|
||||||
function preparedQuery:next(): ...any
|
local function without(self, ...): Query
|
||||||
return queryNext()
|
|
||||||
end
|
|
||||||
|
|
||||||
function preparedQuery:without(...: any): Query
|
|
||||||
local withoutComponents = { ... }
|
local withoutComponents = { ... }
|
||||||
for i = #compatibleArchetypes, 1, -1 do
|
for i = #compatibleArchetypes, 1, -1 do
|
||||||
local archetype = compatibleArchetypes[i].archetype
|
local archetype = compatibleArchetypes[i]
|
||||||
local records = archetype.records
|
local records = archetype.records
|
||||||
local shouldRemove = false
|
local shouldRemove = false
|
||||||
|
|
||||||
|
@ -756,39 +745,47 @@ local function PreparedQuery(compatibleArchetypes: { CompatibleArchetype } , com
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
lastArchetype, compatibleArchetype = next(compatibleArchetypes)
|
|
||||||
if not lastArchetype then
|
|
||||||
return EmptyQuery
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local query = {
|
||||||
|
__iter = function()
|
||||||
|
i = 1
|
||||||
|
lastArchetype = 1
|
||||||
|
archetype = compatibleArchetypes[1]
|
||||||
|
|
||||||
return setmetatable({}, preparedQuery) :: any
|
return queryNext
|
||||||
|
end,
|
||||||
|
next = queryNext,
|
||||||
|
without = without
|
||||||
|
}
|
||||||
|
|
||||||
|
return setmetatable(query, query) :: any
|
||||||
end
|
end
|
||||||
|
|
||||||
function World.query(world: World, ...: any): Query
|
function World.query(world: World, ...: number): Query
|
||||||
-- breaking?
|
-- breaking?
|
||||||
if (...) == nil then
|
if (...) == nil then
|
||||||
error("Missing components")
|
error("Missing components")
|
||||||
end
|
end
|
||||||
|
|
||||||
local compatibleArchetypes: { CompatibleArchetype } = {}
|
local indices: { { number } } = {}
|
||||||
|
local compatibleArchetypes: { Archetype } = {}
|
||||||
local length = 0
|
local length = 0
|
||||||
|
|
||||||
local components = { ... } :: any
|
local components: { number } = { ... }
|
||||||
local archetypes = world.archetypes
|
local archetypes: { Archetype } = world.archetypes :: any
|
||||||
|
|
||||||
local firstArchetypeMap: ArchetypeMap
|
local firstArchetypeMap: ArchetypeMap
|
||||||
local componentIndex = world.componentIndex
|
local componentIndex = world.componentIndex
|
||||||
|
|
||||||
for _, componentId in components do
|
for _, componentId in components do
|
||||||
local map = componentIndex[componentId]
|
local map: ArchetypeMap = componentIndex[componentId] :: any
|
||||||
if not map then
|
if not map then
|
||||||
return EmptyQuery
|
return EmptyQuery
|
||||||
end
|
end
|
||||||
|
|
||||||
if firstArchetypeMap == nil or map.size < firstArchetypeMap.size then
|
if (firstArchetypeMap :: any) == nil or firstArchetypeMap.size < map.size then
|
||||||
firstArchetypeMap = map
|
firstArchetypeMap = map
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -797,7 +794,7 @@ function World.query(world: World, ...: any): Query
|
||||||
local archetype = archetypes[id]
|
local archetype = archetypes[id]
|
||||||
local archetypeRecords = archetype.records
|
local archetypeRecords = archetype.records
|
||||||
|
|
||||||
local indices = {}
|
local records: { number } = {}
|
||||||
local skip = false
|
local skip = false
|
||||||
|
|
||||||
for i, componentId in components do
|
for i, componentId in components do
|
||||||
|
@ -807,7 +804,7 @@ function World.query(world: World, ...: any): Query
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
-- index should be index.offset
|
-- index should be index.offset
|
||||||
indices[i] = index
|
records[i] = index
|
||||||
end
|
end
|
||||||
|
|
||||||
if skip then
|
if skip then
|
||||||
|
@ -815,28 +812,28 @@ function World.query(world: World, ...: any): Query
|
||||||
end
|
end
|
||||||
|
|
||||||
length += 1
|
length += 1
|
||||||
compatibleArchetypes[length] = {
|
compatibleArchetypes[length] = archetype
|
||||||
archetype = archetype,
|
indices[length] = records
|
||||||
indices = indices,
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return PreparedQuery(compatibleArchetypes, components)
|
return preparedQuery(compatibleArchetypes, components, indices)
|
||||||
end
|
end
|
||||||
|
|
||||||
type WorldIterator = (() -> (i53, { [unknown]: unknown? })) & (() -> ()) & (() -> i53)
|
type WorldIterator = (() -> (i53, { [unknown]: unknown? })) & (() -> ()) & (() -> i53)
|
||||||
|
|
||||||
function World.__iter(world: World): WorldIterator
|
function World.__iter(world: World): WorldIterator
|
||||||
local dense = world.entityIndex.dense
|
local entityIndex = world.entityIndex
|
||||||
local sparse = world.entityIndex.sparse
|
local dense = entityIndex.dense
|
||||||
|
local sparse = entityIndex.sparse
|
||||||
local last
|
local last
|
||||||
|
|
||||||
-- new solver doesnt like the world iterator type even tho its correct
|
-- new solver doesnt like the world iterator type even tho its correct
|
||||||
-- so any cast here i come
|
-- so any cast here i come
|
||||||
|
local i = 0
|
||||||
local function iterator()
|
local function iterator()
|
||||||
local lastEntity: number?, entityId: number = next(dense, last)
|
i+=1
|
||||||
if not lastEntity then
|
local entityId = dense[i]
|
||||||
-- ignore type error
|
if not entityId then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -865,10 +862,6 @@ function World.__iter(world: World): WorldIterator
|
||||||
return iterator :: any
|
return iterator :: any
|
||||||
end
|
end
|
||||||
|
|
||||||
-- freezing it incase somebody tries doing something stupid and modifying it
|
|
||||||
-- (unlikely but its easy to add extra safety so)
|
|
||||||
table.freeze(World)
|
|
||||||
|
|
||||||
-- __nominal_type_dont_use could not be any or T as it causes a type error
|
-- __nominal_type_dont_use could not be any or T as it causes a type error
|
||||||
-- or produces a union
|
-- or produces a union
|
||||||
export type Entity<T = any> = number & { __nominal_type_dont_use: T }
|
export type Entity<T = any> = number & { __nominal_type_dont_use: T }
|
||||||
|
@ -999,7 +992,7 @@ export type WorldShim = typeof(setmetatable(
|
||||||
))
|
))
|
||||||
|
|
||||||
return table.freeze({
|
return table.freeze({
|
||||||
World = (World :: any) :: { new: () -> WorldShim },
|
World = (table.freeze(World) :: any) :: { new: () -> WorldShim },
|
||||||
|
|
||||||
OnAdd = (ON_ADD :: any) :: Entity,
|
OnAdd = (ON_ADD :: any) :: Entity,
|
||||||
OnRemove = (ON_REMOVE :: any) :: Entity,
|
OnRemove = (ON_REMOVE :: any) :: Entity,
|
||||||
|
|
Loading…
Reference in a new issue