void DeclareEntityQueries(PerGroupCtxComponents ctx)
        {
            List <ComponentDefinition> flattenedComponentDefinitions = ctx.Context.FlattenedComponentDefinitions().ToList();

            IEnumerable <ArgumentSyntax> arguments = BuildArguments(ctx, flattenedComponentDefinitions);

            foreach (var(name, buildQuery) in BuildQueries(ctx, m_QueryHasStateTracking, m_Coroutines, arguments,
                                                           ctx.Context.GroupName))
            {
                var initValue = MakeInitQueryExpression(buildQuery);

                DeclareAndInitField(typeof(EntityQuery), name, initValue: initValue);
            }
        }
        IEnumerable <ArgumentSyntax> BuildArguments(PerGroupCtxComponents ctx, List <ComponentDefinition> flattenedComponentDefinitions)
        {
            IEnumerable <ArgumentSyntax> ComponentTypeHandlesDeclarationSyntax(IEnumerable <ComponentDefinition> componentDefinitions, string declarationType)
            {
                return(componentDefinitions.Select(c => ComponentTypeDeclarationSyntax(c.TypeHandle.ToTypeSyntax(ctx.Context.Stencil), declarationType)));
            }

            var excludedComponents = flattenedComponentDefinitions.Where(c => c.Subtract);
            var writtenComponents  = flattenedComponentDefinitions.Where(c => !c.Subtract && ctx.WrittenComponents.Contains(c.TypeHandle));
            var readonlyComponents = flattenedComponentDefinitions.Where(c => !c.Subtract && !ctx.WrittenComponents.Contains(c.TypeHandle));

            IEnumerable <ArgumentSyntax> arguments = ComponentTypeHandlesDeclarationSyntax(excludedComponents, nameof(ComponentType.Exclude))
                                                     .Concat(ComponentTypeHandlesDeclarationSyntax(writtenComponents, nameof(ComponentType.ReadWrite)))
                                                     .Concat(ComponentTypeHandlesDeclarationSyntax(readonlyComponents, nameof(ComponentType.ReadOnly)));

            return(arguments);
        }
Ejemplo n.º 3
0
        void DeclareEntityQueries(PerGroupCtxComponents ctx)
        {
            List <ComponentDefinition> flattenedComponentDefinitions = ctx.Context.FlattenedComponentDefinitions().ToList();

            IEnumerable <ArgumentSyntax> arguments = BuildArguments(ctx, flattenedComponentDefinitions);

            foreach (var(name, buildQuery) in BuildQueries(ctx, m_QueryHasStateTracking, arguments, ctx.Context.GroupName))
            {
                var initValue = !buildQuery.Any()
                    ? (ExpressionSyntax)MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                               IdentifierName("EntityManager"),
                                                               IdentifierName("UniversalQuery"))
                    : InvocationExpression(IdentifierName(SafeGuardNamingSystem.EntityQueryMethodName))
                                .WithArgumentList(ArgumentList(SeparatedList(buildQuery)));

                DeclareAndInitField(typeof(EntityQuery), name, initValue: initValue);
            }
        }
        static IEnumerable <(string, IEnumerable <ArgumentSyntax>)> BuildQueries(
            PerGroupCtxComponents ctx,
            IReadOnlyDictionary <ComponentQueryDeclarationModel, QueryStateComponent> queryHasStateTracking,
            IReadOnlyDictionary <RoslynEcsTranslator.IterationContext, string> coroutineComponents,
            IEnumerable <ArgumentSyntax> arguments,
            string contextGroupName)
        {
            IEnumerable <ArgumentSyntax> PrependComponentToArguments(string name, string methodName)
            {
                return(Enumerable.Repeat(ComponentTypeDeclarationSyntax(IdentifierName(name), methodName), 1)
                       .Concat(arguments));
            }

            IEnumerable <ArgumentSyntax> PrependComponentFromTypeToArguments(Type t, string methodName)
            {
                return(Enumerable.Repeat(ComponentTypeDeclarationSyntax(t.ToTypeSyntax(), methodName), 1)
                       .Concat(arguments));
            }

            if (ctx.Context.Query is IPrivateIteratorStackModel updateMatching)
            {
                if (updateMatching.Mode == UpdateMode.OnEvent)
                {
                    var eventType = ((OnEventNodeModel)updateMatching).EventTypeHandle.Resolve(updateMatching.GraphModel.Stencil);
                    yield return(SendEventTranslator.MakeQueryIncludingEventName(ctx.Context, eventType),
                                 PrependComponentFromTypeToArguments(
                                     eventType, nameof(ComponentType.ReadOnly)));
                }

                var queryModel = ctx.Context.Query.ComponentQueryDeclarationModel;
                if (queryHasStateTracking.TryGetValue(queryModel, out var trackingComponent))
                {
                    string methodName = null;
                    switch (updateMatching.Mode)
                    {
                    case UpdateMode.OnUpdate:
                    case UpdateMode.OnEvent:
                        methodName = nameof(ComponentType.ReadWrite);
                        break;

                    case UpdateMode.OnStart:
                        methodName = nameof(ComponentType.Exclude);
                        break;

                    case UpdateMode.OnEnd:
                        yield return(GetQueryAddStateName(contextGroupName),
                                     PrependComponentToArguments(
                                         trackingComponent.ComponentName,
                                         nameof(ComponentType.Exclude)));

                        methodName = nameof(ComponentType.ReadOnly);
                        break;
                    }

                    arguments = PrependComponentToArguments(trackingComponent.ComponentName, methodName);
                }

                // query_MissingEvents is only used in non-jobs context
                if ((ctx.Context.TranslationOptions & RoslynEcsTranslator.TranslationOptions.UseJobs) == 0)
                {
                    foreach (Type eventType in ctx.WrittenEvents)
                    {
                        yield return(SendEventTranslator.MakeMissingEventQueryName(ctx.Context, eventType),
                                     PrependComponentFromTypeToArguments(
                                         eventType, nameof(ComponentType.Exclude)));
                    }
                }
            }

            if (coroutineComponents.TryGetValue(ctx.Context, out var coroutine))
            {
                yield return(CoroutineTranslator.MakeExcludeCoroutineQueryName(ctx.Context),
                             PrependComponentToArguments(coroutine, nameof(ComponentType.Exclude)));

                arguments = PrependComponentToArguments(coroutine, nameof(ComponentType.ReadWrite));
            }

            yield return(contextGroupName, arguments);
        }