From 77676085950bf70f6993c18a6a6d9e7dcc4771f5 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Sat, 19 Feb 2022 18:20:03 -0600 Subject: [PATCH] ecs: query takes [#entity] list --- src/common/ecs/compiler.ts | 20 +++++++++++++++++--- src/common/ecs/ecs.ts | 23 +++++++++++++++++------ 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/common/ecs/compiler.ts b/src/common/ecs/compiler.ts index 9d743758..db2274ac 100644 --- a/src/common/ecs/compiler.ts +++ b/src/common/ecs/compiler.ts @@ -170,12 +170,16 @@ export class ECSCompiler extends Tokenizer { if (tok.str == '#') { this.consumeToken(); let reftype = field.dtype == 'ref' ? field as RefType : undefined; - let token = this.expectIdent(); - return { reftype, token }; + return this.parseEntityForwardRef(reftype); } this.compileError(`I expected a ${field.dtype} here.`); throw new Error(); } + parseEntityForwardRef(reftype?: RefType) : ForwardRef { + let token = this.expectIdent(); + return { reftype, token }; + } + parseDataArray() { this.expectToken('['); let arr = this.parseList(this.expectInteger, ','); @@ -283,12 +287,22 @@ export class ECSCompiler extends Tokenizer { if (prefix.type != TokenType.Ident) { this.consumeToken(); } - let cref = this.parseComponentRef(); if (prefix.type == TokenType.Ident) { + let cref = this.parseComponentRef(); q.include.push(cref); } else if (prefix.str == '-') { + let cref = this.parseComponentRef(); if (!q.exclude) q.exclude = []; q.exclude.push(cref); + } else if (prefix.str == '#') { + const scope = this.currentScope; + if (scope == null) { this.internalError(); throw new Error(); } + let eref = this.parseEntityForwardRef(); + this.deferred.push(() => { + let refvalue = this.resolveEntityRef(scope, eref); + if (!q.entities) q.entities = []; + q.entities.push(scope.entities[refvalue]); + }); } else { this.compileError(`Query components may be preceded only by a '-'.`); } diff --git a/src/common/ecs/ecs.ts b/src/common/ecs/ecs.ts index 563588cc..2a1c9448 100644 --- a/src/common/ecs/ecs.ts +++ b/src/common/ecs/ecs.ts @@ -46,6 +46,7 @@ export interface ComponentType extends SourceLocated { export interface Query extends SourceLocated { include: ComponentType[]; // TODO: make ComponentType exclude?: ComponentType[]; + entities?: Entity[]; limit?: number; } @@ -503,10 +504,18 @@ class EntitySet { constructor(scope: EntityScope, query?: Query, a?: EntityArchetype[], e?: Entity[]) { this.scope = scope; if (query) { - this.atypes = scope.em.archetypesMatching(query); - this.entities = scope.entitiesMatching(this.atypes); - if (query.limit) { - this.entities = this.entities.slice(0, query.limit); + if (query.entities) { + this.entities = query.entities.slice(0); + this.atypes = []; + for (let e of this.entities) + if (!this.atypes.includes(e.etype)) + this.atypes.push(e.etype); + } else { + this.atypes = scope.em.archetypesMatching(query); + this.entities = scope.entitiesMatching(this.atypes); + if (query.limit) { + this.entities = this.entities.slice(0, query.limit); + } } } else if (a && e) { this.atypes = a; @@ -751,8 +760,10 @@ class ActionEval { throw new ECSError('unroll is not yet implemented'); } // define properties - props['%elo'] = entities[0].id.toString(); - props['%ehi'] = entities[entities.length - 1].id.toString(); + if (entities.length) { + props['%elo'] = entities[0].id.toString(); + props['%ehi'] = entities[entities.length - 1].id.toString(); + } props['%ecount'] = entities.length.toString(); props['%efullcount'] = fullEntityCount.toString(); // TODO