Пример #1
0
        public override ExpressionSyntax GetEventBufferWriter(RoslynEcsTranslator.IterationContext iterationContext, ExpressionSyntax entity, Type eventType, out StatementSyntax bufferInitialization)
        {
            GetEventSystem(iterationContext, eventType);
            var bufferVariableName            = SendEventTranslator.GetBufferVariableName(iterationContext, eventType);
            var buffersFromEntityVariableName = bufferVariableName + "s";
            var cmdBuffer = GetOrDeclareCommandBuffer(true);

            bufferInitialization = RoslynBuilder.DeclareLocalVariable((Type)null, bufferVariableName, variableDeclarationType: RoslynBuilder.VariableDeclarationType.InferredType, initValue: ConditionalExpression(
                                                                          InvocationExpression(
                                                                              MemberAccessExpression(
                                                                                  SyntaxKind.SimpleMemberAccessExpression,
                                                                                  IdentifierName(buffersFromEntityVariableName),
                                                                                  IdentifierName("Exists")))
                                                                          .WithArgumentList(
                                                                              ArgumentList(
                                                                                  SingletonSeparatedList(
                                                                                      Argument(
                                                                                          IdentifierName(EntityName))))),
                                                                          ElementAccessExpression(
                                                                              IdentifierName(buffersFromEntityVariableName))
                                                                          .WithArgumentList(
                                                                              BracketedArgumentList(
                                                                                  SingletonSeparatedList(
                                                                                      Argument(
                                                                                          IdentifierName(EntityName))))),
                                                                          InvocationExpression(
                                                                              MemberAccessExpression(
                                                                                  SyntaxKind.SimpleMemberAccessExpression,
                                                                                  cmdBuffer,
                                                                                  GenericName(
                                                                                      Identifier(nameof(EntityCommandBuffer.AddBuffer)))
                                                                                  .WithTypeArgumentList(
                                                                                      TypeArgumentList(
                                                                                          SingletonSeparatedList <TypeSyntax>(
                                                                                              eventType.ToTypeSyntax())))))
                                                                          .WithArgumentList(
                                                                              ArgumentList(
                                                                                  SeparatedList <ArgumentSyntax>(
                                                                                      new SyntaxNodeOrToken[] {
                Argument(
                    IdentifierName(GetJobIndexParameterName())),
                Token(SyntaxKind.CommaToken),
                Argument(
                    IdentifierName(EntityName))
            })))));
            GetCachedValue(buffersFromEntityVariableName,
                           InvocationExpression(
                               GenericName(
                                   Identifier(nameof(JobComponentSystem.GetBufferFromEntity)))
                               .WithTypeArgumentList(
                                   TypeArgumentList(
                                       SingletonSeparatedList(
                                           eventType.ToTypeSyntax())))),
                           typeof(BufferFromEntity <>).MakeGenericType(eventType).GenerateTypeHandle(iterationContext.Stencil));

            // The BufferFromEntity<EventStruct> is not parallel-write safe. We might have multiple iterations sending
            // events to the same separate entity, so we run the job on a single thread to be safe
            m_ScheduleSingleThreaded = true;
            return(IdentifierName(bufferVariableName));
        }
Пример #2
0
        LocalDeclarationStatementSyntax GetCoroutineComponentDeclaration(string loopIndexName)
        {
            string compArrayName = GetOrDeclareComponentArray(
                IterationContext,
                m_CoroutineComponentName,
                out var componentDataArrayInitialization,
                out var componentDataArrayDisposal);

            if (componentDataArrayInitialization != null)
            {
                m_InitComponentDataArrays.Add(componentDataArrayInitialization);
            }
            if (componentDataArrayDisposal != null)
            {
                m_DisposeComponentDataArrays.Add(componentDataArrayDisposal);
            }

            var initValue = ElementAccessExpression(IdentifierName(compArrayName))
                            .WithArgumentList(
                BracketedArgumentList(
                    SingletonSeparatedList(
                        Argument(
                            IdentifierName(loopIndexName)))));

            return(RoslynBuilder.DeclareLocalVariable(
                       (Type)null,
                       CoroutineContext.BuildCoroutineParameterName(m_CoroutineComponentName),
                       initValue,
                       RoslynBuilder.VariableDeclarationType.InferredType));
        }
        public override IdentifierNameSyntax GetEventBufferWriter(RoslynEcsTranslator.IterationContext iterationContext, ExpressionSyntax entity, Type eventType, out StatementSyntax bufferInitialization)
        {
            bufferInitialization = null;
            var bufferVariableName = SendEventTranslator.GetBufferVariableName(iterationContext, eventType);

            iterationContext.WrittenEventTypes.Add(eventType);
            if (GetEventSystem(iterationContext, eventType))
            {
                // var buffer = EntityManager.GetBuffer<EventType>(entity);
                var bufferInitValue = InvocationExpression(
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        IdentifierName("EntityManager"),
                        GenericName(
                            Identifier("GetBuffer"))
                        .WithTypeArgumentList(
                            TypeArgumentList(
                                SingletonSeparatedList(
                                    eventType.ToTypeSyntax())))))
                                      .WithArgumentList(
                    ArgumentList(
                        SingletonSeparatedList(
                            Argument(entity)
                            )
                        )
                    );
                bufferInitialization = RoslynBuilder.DeclareLocalVariable((Type)null, bufferVariableName, bufferInitValue, RoslynBuilder.VariableDeclarationType.InferredType);
            }
            return(IdentifierName(bufferVariableName));
        }
Пример #4
0
        public override string GetOrDeclareComponentArray(
            RoslynEcsTranslator.IterationContext ctx,
            ComponentDefinition componentDefinition,
            out LocalDeclarationStatementSyntax arrayInitialization,
            out StatementSyntax arrayDisposal)
        {
            Type resolvedType = componentDefinition.TypeHandle.Resolve(m_Stencil);
            var  arrayName    = ctx.GetComponentDataArrayName(resolvedType);

            Type arrayType = typeof(NativeArray <>).MakeGenericType(resolvedType);

            arrayInitialization = RoslynBuilder.DeclareLocalVariable(
                arrayType, arrayName,
                MakeInitComponentDataArrayExpression(ctx, resolvedType),
                RoslynBuilder.VariableDeclarationType.InferredType);

            arrayDisposal = ExpressionStatement(
                InvocationExpression(
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        IdentifierName(arrayName),
                        IdentifierName(nameof(IDisposable.Dispose)))))
                            .NormalizeWhitespace();

            return(arrayName);
        }
Пример #5
0
        protected override IEnumerable <StatementSyntax> OnPopContext()
        {
            var rootContext = (RootContext)Parent;
            var build       = BuildJobStruct();

            if (build != null)
            {
                rootContext.AddMember(build);
                if ((TranslationOptions & RoslynEcsTranslator.TranslationOptions.Tracing) == 0)
                {
                    yield return(MakeJobSchedulingStatement());

                    yield break;
                }

                var recorderName = $"{IterationContext.GroupName}Recorder";
                yield return(RoslynBuilder.DeclareLocalVariable(typeof(GraphStream), recorderName,
                                                                InvocationExpression(
                                                                    MemberAccessExpression(
                                                                        SyntaxKind.SimpleMemberAccessExpression,
                                                                        IdentifierName(nameof(TracingRecorderSystem)),
                                                                        IdentifierName(nameof(TracingRecorderSystem.GetRecordingStream))))
                                                                .WithArgumentList(
                                                                    ArgumentList(
                                                                        SeparatedList(
                                                                            new[]
                {
                    Argument(
                        InvocationExpression(
                            MemberAccessExpression(
                                SyntaxKind.SimpleMemberAccessExpression,
                                IdentifierName(IterationContext.GroupName),
                                IdentifierName(nameof(EntityQuery.CalculateEntityCount))))),
                    Argument(
                        LiteralExpression(
                            SyntaxKind.NumericLiteralExpression,
                            Literal(((UnityEngine.Object)IterationContext.Query.GraphModel.AssetModel).GetInstanceID())))
                })))));

                yield return(MakeJobSchedulingStatement());

                yield return(ExpressionStatement(
                                 InvocationExpression(
                                     MemberAccessExpression(
                                         SyntaxKind.SimpleMemberAccessExpression,
                                         IdentifierName(nameof(TracingRecorderSystem)),
                                         IdentifierName(nameof(TracingRecorderSystem.FlushRecordingStream))))
                                 .WithArgumentList(
                                     ArgumentList(
                                         SeparatedList(
                                             new[]
                {
                    Argument(
                        IdentifierName(recorderName)),
                    Argument(
                        IdentifierName("inputDeps"))
                })))));
            }
        }
Пример #6
0
 public override void AddEntityDeclaration(string variableName)
 {
     // Entity {m_EntityName} = {IterationContext.EntitiesArrayName}[{IterationContext.IndexVariableName}];
     EntityName          = variableName;
     m_EntityDeclaration = RoslynBuilder.DeclareLocalVariable(
         typeof(Entity),
         EntityName,
         ElementAccessExpression(IdentifierName(IterationContext.EntitiesArrayName))
         .WithArgumentList(
             BracketedArgumentList(
                 SingletonSeparatedList(
                     Argument(
                         IdentifierName(IterationContext.IndexVariableName))))),
         RoslynBuilder.VariableDeclarationType.InferredType);
 }
 protected override StatementSyntax GetOrDeclareEntityArray(RoslynEcsTranslator.IterationContext iterationContext, out StatementSyntax arrayDisposal)
 {
     arrayDisposal = ExpressionStatement(
         InvocationExpression(
             MemberAccessExpression(
                 SyntaxKind.SimpleMemberAccessExpression,
                 IdentifierName(iterationContext.EntitiesArrayName),
                 IdentifierName(nameof(IDisposable.Dispose)))))
                     .NormalizeWhitespace();
     return(RoslynBuilder.DeclareLocalVariable(
                typeof(NativeArray <Entity>),
                iterationContext.EntitiesArrayName,
                ForEachContext.MakeInitEntityArray(iterationContext),
                RoslynBuilder.VariableDeclarationType.InferredType));
 }
        public override ExpressionSyntax GetSingletonVariable(IVariableDeclarationModel variable)
        {
            if (m_SingletonDeclarationSyntax == null)
            {
                var init = RoslynBuilder.MethodInvocation(
                    SafeGuardNamingSystem.GetSingletonName,
                    null,
                    Enumerable.Empty <ArgumentSyntax>(),
                    new[] { IdentifierName(SingletonComponentTypeName) });
                m_SingletonDeclarationSyntax = RoslynBuilder.DeclareLocalVariable(
                    SingletonComponentTypeName,
                    SingletonVariableName,
                    init);
                AddStatement(m_SingletonDeclarationSyntax);
            }

            return(MemberAccessExpression(
                       SyntaxKind.SimpleMemberAccessExpression,
                       IdentifierName(SingletonVariableName),
                       IdentifierName(variable.VariableName)));
        }
        public override string GetOrDeclareComponentArray(RoslynEcsTranslator.IterationContext ctx,
                                                          string componentTypeName,
                                                          out LocalDeclarationStatementSyntax arrayInitialization,
                                                          out StatementSyntax arrayDisposal)
        {
            var arrayName = ctx.GetComponentDataArrayName(componentTypeName);

            arrayInitialization = RoslynBuilder.DeclareLocalVariable(
                (Type)null, arrayName,
                MakeInitComponentDataArrayExpression(ctx, componentTypeName),
                RoslynBuilder.VariableDeclarationType.InferredType);

            arrayDisposal = ExpressionStatement(
                InvocationExpression(
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        IdentifierName(arrayName),
                        IdentifierName(nameof(IDisposable.Dispose)))))
                            .NormalizeWhitespace();

            return(arrayName);
        }
Пример #10
0
        protected override StatementSyntax OnPopContext()
        {
            BlockSyntax forBody = Block();

            var loopIndexName = IterationContext.IndexVariableName;
            List <StatementSyntax> reassignComponentDataArrays = new List <StatementSyntax>();


            BlockSyntax blockSyntax = Block();

            // foreach in a job: the entity array will be declared as a job field, initialized at job creation

            StatementSyntax initEntitiesArray = GetOrDeclareEntityArray(IterationContext, out var disposeEntitiesArray);

            foreach (ComponentDefinition definition in IterationContext.FlattenedComponentDefinitions())
            {
                if (!RoslynEcsTranslatorExtensions.ShouldGenerateComponentAccess(definition.TypeHandle, true, out var componentType, IterationContext.Stencil, out bool isShared, out bool isGameObjectComponent) ||
                    isGameObjectComponent)
                {
                    continue;
                }

                if (!m_WrittenComponents.TryGetValue(definition.TypeHandle, out var mode))
                {
                    mode = RoslynEcsTranslator.AccessMode.None;
                }

                if (mode == RoslynEcsTranslator.AccessMode.None)
                {
                    continue;
                }

                ExpressionSyntax initValue;
                if (isShared)
                {
                    initValue = InvocationExpression(
                        MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            IdentifierName(nameof(EntityManager)),
                            GenericName(
                                Identifier(nameof(EntityManager.GetSharedComponentData)))
                            .WithTypeArgumentList(
                                TypeArgumentList(
                                    SingletonSeparatedList(
                                        TypeSystem.BuildTypeSyntax(componentType))))))
                                .WithArgumentList(
                        ArgumentList(
                            SingletonSeparatedList(
                                Argument(
                                    IdentifierName(EntityName)))));
                }
                else
                {
                    string compArrayName = GetOrDeclareComponentArray(IterationContext, definition,
                                                                      out var componentDataArrayInitialization,
                                                                      out var componentDataArrayDisposal);
                    if (componentDataArrayInitialization != null)
                    {
                        m_InitComponentDataArrays.Add(componentDataArrayInitialization);
                    }
                    if (componentDataArrayDisposal != null)
                    {
                        m_DisposeComponentDataArrays.Add(componentDataArrayDisposal);
                    }

                    initValue = ElementAccessExpression(IdentifierName(compArrayName))
                                .WithArgumentList(
                        BracketedArgumentList(
                            SingletonSeparatedList(
                                Argument(
                                    IdentifierName(loopIndexName)))));
                }


                // per-entity component variable
                StatementSyntax componentVarDeclaration = RoslynBuilder.DeclareLocalVariable(
                    componentType,
                    IterationContext.GetComponentDataName(componentType),
                    initValue,
                    RoslynBuilder.VariableDeclarationType.InferredType);
                forBody = forBody.AddStatements(componentVarDeclaration);

                if (mode == RoslynEcsTranslator.AccessMode.Write)
                {
                    reassignComponentDataArrays.Add(ExpressionStatement(
                                                        GetEntityManipulationTranslator().SetComponent(
                                                            this,
                                                            ElementAccessExpression(IdentifierName(IterationContext.EntitiesArrayName))
                                                            .WithArgumentList(
                                                                BracketedArgumentList(
                                                                    SingletonSeparatedList(
                                                                        Argument(
                                                                            IdentifierName(IterationContext.IndexVariableName))))),
                                                            componentType,
                                                            IdentifierName(IterationContext.GetComponentDataName(componentType)))
                                                        .Cast <ExpressionSyntax>()
                                                        .Single())
                                                    );
                }
            }

            forBody = forBody.AddStatements(m_UpdateStatements.ToArray());
            forBody = forBody.AddStatements(reassignComponentDataArrays.ToArray());

            if (forBody.Statements.Count != 0) // strip the iteration loop if empty
            {
                forBody = forBody.WithStatements(forBody.Statements.Insert(0, m_EntityDeclaration));

                if (initEntitiesArray != null)
                {
                    blockSyntax = blockSyntax.AddStatements(initEntitiesArray);
                }

                blockSyntax = blockSyntax
                              .AddStatements(m_InitComponentDataArrays.ToArray())
                              .AddStatements(RoslynEcsTranslatorExtensions.ComponentQueryForLoop(forBody, loopIndexName, IterationContext.EntitiesArrayName))
                              .AddStatements(m_DisposeComponentDataArrays.ToArray());

                if (disposeEntitiesArray != null)
                {
                    blockSyntax = blockSyntax.AddStatements(disposeEntitiesArray);
                }
            }

            return(AddMissingEventBuffers(IterationContext, blockSyntax));
        }
Пример #11
0
        StatementSyntax BuildInner()
        {
            const string eventBufferName = "eventBuffer";
            Type         eventType       = IterationContext.UpdateMode == UpdateMode.OnEvent
                ? ((OnEventNodeModel)IterationContext.Query).EventTypeHandle.Resolve(IterationContext.Stencil)
                : null;

            List <ParameterSyntax> parameters = new List <ParameterSyntax>
            {
                Parameter(
                    Identifier(EntityName))
                .WithType(typeof(Entity).ToTypeSyntax())
            };

            var stateComponentName = IterationContext.UpdateMode == UpdateMode.OnUpdate || IterationContext.UpdateMode == UpdateMode.OnEvent
                ? null
                : IncludeTrackingSystemStateComponent(IterationContext.Query.ComponentQueryDeclarationModel, IterationContext.UpdateMode == UpdateMode.OnEnd);
            var stateComponentParameterName = stateComponentName?.ToLowerInvariant();

            switch (IterationContext.UpdateMode)
            {
            case UpdateMode.OnUpdate:
                break;

            case UpdateMode.OnEvent:
                // Add it at the end

                break;

            case UpdateMode.OnStart:
                m_UpdateStatements.AddRange(GetEntityManipulationTranslator().AddComponent(
                                                this,
                                                IdentifierName(EntityName),
                                                DefaultExpression(IdentifierName(stateComponentName)),
                                                IdentifierName(stateComponentName),
                                                false));
                break;

            case UpdateMode.OnEnd:
                parameters.Add(MakeLambdaParameter(
                                   stateComponentParameterName,
                                   IdentifierName(stateComponentName),
                                   false,
                                   false));

                m_UpdateStatements.AddRange(GetEntityManipulationTranslator().RemoveComponent(
                                                this,
                                                IdentifierName(EntityName),
                                                IdentifierName(stateComponentName)));
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            // SharedComponents should be inserted first in ForEach
            var sortedComponents = IterationContext.FlattenedComponentDefinitions()
                                   .OrderBy(d =>
                                            !typeof(ISharedComponentData).IsAssignableFrom(d.TypeHandle.Resolve(IterationContext.Stencil)))
                                   .ToList();

            foreach (ComponentDefinition definition in sortedComponents)
            {
                if (!RoslynEcsTranslatorExtensions.ShouldGenerateComponentAccess(
                        definition.TypeHandle,
                        true,
                        out Type componentType,
                        IterationContext.Stencil,
                        out bool _,
                        out bool isGameObjectComponent))
                {
                    continue;
                }

                if (!m_WrittenComponents.TryGetValue(definition.TypeHandle, out RoslynEcsTranslator.AccessMode mode))
                {
                    mode = RoslynEcsTranslator.AccessMode.None;
                }

                if (mode == RoslynEcsTranslator.AccessMode.None)
                {
                    continue;
                }

                string componentDataName = IterationContext.GetComponentDataName(componentType);
                parameters.Add(MakeLambdaParameter(
                                   componentDataName,
                                   componentType.ToTypeSyntax(),
                                   isGameObjectComponent,
                                   typeof(ISharedComponentData).IsAssignableFrom(componentType)));
            }

            switch (IterationContext.UpdateMode)
            {
            case UpdateMode.OnEvent:
                parameters.Add(MakeLambdaParameter(
                                   eventBufferName,
                                   GenericName("DynamicBuffer").WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(eventType.ToTypeSyntax()))),
                                   false,
                                   true));
                break;
            }


            ExpressionSyntax baseQuery = InvocationExpression(
                MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    IdentifierName("Entities"),
                    IdentifierName("With")))
                                         .WithArgumentList(
                ArgumentList(
                    SingletonSeparatedList(
                        Argument(
                            IdentifierName(IterationContext.UpdateMode == UpdateMode.OnEvent
                                    ? SendEventTranslator.MakeQueryIncludingEventName(IterationContext, eventType)
                                    : IterationContext.GroupName)))));

            if (IterationContext.UpdateMode == UpdateMode.OnEnd)
            {
                // REPLACE query
                baseQuery = IdentifierName("Entities");
                m_UpdateStatements.Insert(0, IfStatement(
                                              MemberAccessExpression(
                                                  SyntaxKind.SimpleMemberAccessExpression,
                                                  IdentifierName(stateComponentParameterName),
                                                  IdentifierName("Processed")),
                                              ReturnStatement()));
            }

            BlockSyntax innerLambdaBody;

            if (IterationContext.UpdateMode == UpdateMode.OnEvent)
            {
                //for (int event_index = 0; event_index < eventBuffer.Length; event_index++) { T ev = eventBuffer[event_index]; ... }
                var eventIndexName = "event_index";
                m_UpdateStatements.Insert(0, RoslynBuilder.DeclareLocalVariable(eventType, "ev",
                                                                                ElementAccessExpression(
                                                                                    IdentifierName(eventBufferName))
                                                                                .WithArgumentList(
                                                                                    BracketedArgumentList(
                                                                                        SingletonSeparatedList(
                                                                                            Argument(
                                                                                                IdentifierName(eventIndexName)))))
                                                                                .NormalizeWhitespace()));
                innerLambdaBody = Block(ForStatement(
                                            Block(m_UpdateStatements))
                                        .WithDeclaration(
                                            VariableDeclaration(
                                                PredefinedType(
                                                    Token(SyntaxKind.IntKeyword)))
                                            .WithVariables(
                                                SingletonSeparatedList <VariableDeclaratorSyntax>(
                                                    VariableDeclarator(
                                                        Identifier(eventIndexName))
                                                    .WithInitializer(
                                                        EqualsValueClause(
                                                            LiteralExpression(
                                                                SyntaxKind.NumericLiteralExpression,
                                                                Literal(0)))))))
                                        .WithCondition(
                                            BinaryExpression(
                                                SyntaxKind.LessThanExpression,
                                                IdentifierName(eventIndexName),
                                                MemberAccessExpression(
                                                    SyntaxKind.SimpleMemberAccessExpression,
                                                    IdentifierName(eventBufferName),
                                                    IdentifierName("Length"))))
                                        .WithIncrementors(
                                            SingletonSeparatedList <ExpressionSyntax>(
                                                PostfixUnaryExpression(
                                                    SyntaxKind.PostIncrementExpression,
                                                    IdentifierName(eventIndexName))))
                                        .NormalizeWhitespace());
            }
            else
            {
                innerLambdaBody = Block(m_UpdateStatements);
            }

            var parenthesizedLambdaExpressionSyntax = ParenthesizedLambdaExpression(
                innerLambdaBody)
                                                      .WithParameterList(
                ParameterList().AddParameters(parameters.ToArray()));

            var updateCall = ExpressionStatement(
                InvocationExpression(
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        baseQuery,
                        IdentifierName("ForEach")))
                .WithArgumentList(
                    ArgumentList(
                        SingletonSeparatedList(
                            Argument(
                                parenthesizedLambdaExpressionSyntax)))));

            if (IterationContext.UpdateMode == UpdateMode.OnEnd)
            {
                var addMissingStateComponents = ExpressionStatement(
                    InvocationExpression(
                        MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            IdentifierName("EntityManager"),
                            IdentifierName("AddComponent")))
                    .WithArgumentList(
                        ArgumentList(
                            SeparatedList(
                                new [] {
                    Argument(
                        IdentifierName(RootContext.GetQueryAddStateName(IterationContext.GroupName))),
                    Argument(
                        TypeOfExpression(
                            IdentifierName(stateComponentName)))
                }))));

                var foreachClearProcessed = ExpressionStatement(
                    InvocationExpression(
                        MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            IdentifierName("Entities"),
                            IdentifierName("ForEach")))
                    .WithArgumentList(
                        ArgumentList(
                            SingletonSeparatedList(
                                Argument(
                                    ParenthesizedLambdaExpression(
                                        MakeProcessed(false))
                                    .WithParameterList(
                                        ParameterList(
                                            SingletonSeparatedList(
                                                Parameter(
                                                    Identifier(stateComponentParameterName))
                                                .WithModifiers(
                                                    TokenList(
                                                        Token(SyntaxKind.RefKeyword)))
                                                .WithType(
                                                    IdentifierName(stateComponentName))))))))));
                var foreachQueryMarkProcessed = ExpressionStatement(
                    InvocationExpression(
                        MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            InvocationExpression(
                                MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    IdentifierName("Entities"),
                                    IdentifierName("With")))
                            .WithArgumentList(
                                ArgumentList(
                                    SingletonSeparatedList(
                                        Argument(
                                            IdentifierName(IterationContext.GroupName))))),
                            IdentifierName("ForEach")))
                    .WithArgumentList(
                        ArgumentList(
                            SingletonSeparatedList(
                                Argument(
                                    ParenthesizedLambdaExpression(MakeProcessed(true))
                                    .WithParameterList(
                                        ParameterList(
                                            SeparatedList(parameters))))))));
                return(Block(
                           addMissingStateComponents,
                           foreachClearProcessed,
                           foreachQueryMarkProcessed,
                           updateCall
                           ));
            }

            return(updateCall);

            ParameterSyntax MakeLambdaParameter(string componentDataName, TypeSyntax typeSyntax,
                                                bool isGameObjectComponent, bool isSharedComponent)
            {
                var modifiers = new List <SyntaxToken>();

                if (!isSharedComponent)
                {
                    modifiers.Add(Token(SyntaxKind.RefKeyword));
                }

                var parameterSyntax = Parameter(
                    Identifier(componentDataName))
                                      .WithType(
                    typeSyntax);

                if (!isGameObjectComponent)
                {
                    parameterSyntax = parameterSyntax
                                      .WithModifiers(TokenList(modifiers));
                }
                return(parameterSyntax);
            }

            AssignmentExpressionSyntax MakeProcessed(bool processed)
            {
                return(AssignmentExpression(
                           SyntaxKind.SimpleAssignmentExpression,
                           MemberAccessExpression(
                               SyntaxKind.SimpleMemberAccessExpression,
                               IdentifierName(stateComponentParameterName),
                               IdentifierName("Processed")),
                           LiteralExpression(processed
                        ? SyntaxKind.TrueLiteralExpression
                        : SyntaxKind.FalseLiteralExpression)));
            }
        }
Пример #12
0
        MemberDeclarationSyntax MakeJobUpdateOverride(List <ParameterSyntax> functionParameters, List <StatementSyntax> updateStatements, string trackingComponentName, Type eventType)
        {
            var blockSyntax = Block(updateStatements);

            switch (IterationContext.UpdateMode)
            {
            case UpdateMode.OnStart:
                blockSyntax = blockSyntax.AddStatements(GetEntityManipulationTranslator().AddComponent(
                                                            this, IdentifierName(EntityName),
                                                            DefaultExpression(IdentifierName(trackingComponentName)),
                                                            IdentifierName(trackingComponentName),
                                                            false).ToArray());
                break;

            case UpdateMode.OnEvent:
                Assert.IsNotNull(eventType);
                const string eventIndexName   = "event_idx";
                string       eventBufferName  = OnEventNodeModel.GetBufferName(eventType);
                var          eventDeclaration = RoslynBuilder.DeclareLocalVariable(eventType, "ev" /* TODO hardcoded event name*/,
                                                                                   ElementAccessExpression(
                                                                                       IdentifierName(eventBufferName))
                                                                                   .WithArgumentList(
                                                                                       BracketedArgumentList(
                                                                                           SingletonSeparatedList(
                                                                                               Argument(
                                                                                                   IdentifierName(eventIndexName))))));
                blockSyntax = Block(ForStatement(Block(blockSyntax.Statements.Insert(0, eventDeclaration)))
                                    .WithDeclaration(
                                        VariableDeclaration(
                                            PredefinedType(
                                                Token(SyntaxKind.IntKeyword)))
                                        .WithVariables(
                                            SingletonSeparatedList(
                                                VariableDeclarator(
                                                    Identifier(eventIndexName))
                                                .WithInitializer(
                                                    EqualsValueClause(
                                                        LiteralExpression(
                                                            SyntaxKind.NumericLiteralExpression,
                                                            Literal(0)))))))
                                    .WithCondition(
                                        BinaryExpression(
                                            SyntaxKind.LessThanExpression,
                                            IdentifierName(eventIndexName),
                                            MemberAccessExpression(
                                                SyntaxKind.SimpleMemberAccessExpression,
                                                IdentifierName(eventBufferName),
                                                IdentifierName("Length"))))
                                    .WithIncrementors(
                                        SingletonSeparatedList <ExpressionSyntax>(
                                            PostfixUnaryExpression(
                                                SyntaxKind.PostIncrementExpression,
                                                IdentifierName(eventIndexName)))));

                break;
            }

            var executeMethod = MethodDeclaration(
                PredefinedType(
                    Token(SyntaxKind.VoidKeyword)),
                Identifier("Execute"))
                                .WithModifiers(
                TokenList(
                    Token(SyntaxKind.PublicKeyword)))
                                .WithParameterList(
                ParameterList(
                    SeparatedList(functionParameters)))
                                .WithBody(blockSyntax);

            return(executeMethod);
        }
Пример #13
0
        internal static void BuildCriteria(this IEntityManipulationTranslator self, RoslynEcsTranslator translator,
                                           TranslationContext context, ExpressionSyntax entity, IEnumerable <CriteriaModel> criteriaModels,
                                           StatementSyntax conditionBreak)
        {
            var criteriaList = criteriaModels.ToList();

            if (!criteriaList.Any())
            {
                return;
            }

            ExpressionSyntax ifExpressionSyntax = null;

            foreach (var model in criteriaList)
            {
                ExpressionSyntax finalExpression = null;
                foreach (var criterion in model.Criteria)
                {
                    if (!(criterion is Criterion componentCriterion))
                    {
                        continue;
                    }

                    var rightValue = componentCriterion.Value is ConstantNodeModel constantNodeModel
                        ? translator.Constant(constantNodeModel.ObjectValue, translator.Stencil, constantNodeModel.Type)
                        : IdentifierName(componentCriterion.Value.DeclarationModel.VariableName);

                    var expression = BinaryExpression(
                        componentCriterion.Operator.ToSyntaxKind(),
                        GetLeftValueFromCriterion(self, context, translator.Stencil, entity, componentCriterion),
                        rightValue) as ExpressionSyntax;

                    // TODO : Temporary. Once Unity.Mathematics have IComparable interface, remove this
                    // and use IComparable and IEquatable methods instead of operators
                    var rightValueType = GetRightValueType(componentCriterion, translator.Stencil);
                    if (rightValueType.Namespace != null && rightValueType.Namespace.StartsWith("Unity.Mathematics"))
                    {
                        expression = RoslynBuilder.MethodInvocation(
                            nameof(math.all),
                            typeof(math).ToTypeSyntax(),
                            new[] { Argument(expression) },
                            Enumerable.Empty <TypeSyntax>());
                    }

                    finalExpression = finalExpression == null
                        ? expression
                        : BinaryExpression(SyntaxKind.LogicalAndExpression, finalExpression, expression);
                }

                if (finalExpression == null)
                {
                    continue;
                }
                context.AddStatement(RoslynBuilder.DeclareLocalVariable(
                                         typeof(bool),
                                         model.Name,
                                         finalExpression,
                                         RoslynBuilder.VariableDeclarationType.InferredType));

                var unaryExpression = PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, IdentifierName(model.Name));
                if (model != criteriaList.First())
                {
                    ifExpressionSyntax = BinaryExpression(
                        SyntaxKind.LogicalAndExpression,
                        ifExpressionSyntax,
                        unaryExpression);
                }
                else
                {
                    ifExpressionSyntax = unaryExpression;
                }
            }

            if (ifExpressionSyntax != null)
            {
                BlockSyntax statementSyntax;
                if ((translator.Options & CompilationOptions.Tracing) != 0 && context is JobContext jobContext)
                {
                    statementSyntax = Block(List <SyntaxNode>()
                                            .Add(jobContext.MakeTracingEndForEachIndexStatement())
                                            .Add(conditionBreak));
                }
                else
                {
                    statementSyntax = Block(SingletonList(conditionBreak));
                }
                context.AddStatement(IfStatement(ifExpressionSyntax, statementSyntax));
            }
        }
Пример #14
0
        MemberDeclarationSyntax MakeJobUpdateOverride(List <ParameterSyntax> functionParameters, List <StatementSyntax> updateStatements, string trackingComponentName, Type eventType)
        {
            var blockSyntax = Block(updateStatements);

            switch (IterationContext.UpdateMode)
            {
            case UpdateMode.OnStart:
                blockSyntax = blockSyntax.AddStatements(GetEntityManipulationTranslator().AddComponent(
                                                            this, IdentifierName(EntityName),
                                                            DefaultExpression(IdentifierName(trackingComponentName)),
                                                            IdentifierName(trackingComponentName),
                                                            false).ToArray());
                break;

            case UpdateMode.OnEvent:
                Assert.IsNotNull(eventType);
                const string eventIndexName   = "event_idx";
                string       eventBufferName  = OnEventNodeModel.GetBufferName(eventType);
                var          eventDeclaration = RoslynBuilder.DeclareLocalVariable(eventType, "ev" /* TODO hardcoded event name*/,
                                                                                   ElementAccessExpression(
                                                                                       IdentifierName(eventBufferName))
                                                                                   .WithArgumentList(
                                                                                       BracketedArgumentList(
                                                                                           SingletonSeparatedList(
                                                                                               Argument(
                                                                                                   IdentifierName(eventIndexName))))));
                blockSyntax = Block(ForStatement(Block(blockSyntax.Statements.Insert(0, eventDeclaration)))
                                    .WithDeclaration(
                                        VariableDeclaration(
                                            PredefinedType(
                                                Token(SyntaxKind.IntKeyword)))
                                        .WithVariables(
                                            SingletonSeparatedList(
                                                VariableDeclarator(
                                                    Identifier(eventIndexName))
                                                .WithInitializer(
                                                    EqualsValueClause(
                                                        LiteralExpression(
                                                            SyntaxKind.NumericLiteralExpression,
                                                            Literal(0)))))))
                                    .WithCondition(
                                        BinaryExpression(
                                            SyntaxKind.LessThanExpression,
                                            IdentifierName(eventIndexName),
                                            MemberAccessExpression(
                                                SyntaxKind.SimpleMemberAccessExpression,
                                                IdentifierName(eventBufferName),
                                                IdentifierName("Length"))))
                                    .WithIncrementors(
                                        SingletonSeparatedList <ExpressionSyntax>(
                                            PostfixUnaryExpression(
                                                SyntaxKind.PostIncrementExpression,
                                                IdentifierName(eventIndexName)))));

                break;
            }

            var executeMethod = MethodDeclaration(
                PredefinedType(
                    Token(SyntaxKind.VoidKeyword)),
                Identifier("Execute"))
                                .WithModifiers(
                TokenList(
                    Token(SyntaxKind.PublicKeyword)))
                                .WithParameterList(
                ParameterList(
                    SeparatedList(functionParameters)))
                                .WithBody(blockSyntax);

            if ((TranslationOptions & RoslynEcsTranslator.TranslationOptions.Tracing) != 0)
            {
                ((SerializableGUID)IterationContext.Query.Guid).ToParts(out var guid1, out var guid2);
                StatementSyntax beginStatement = ExpressionStatement(
                    InvocationExpression(
                        MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            m_RecorderJobFieldName,
                            IdentifierName(nameof(GraphStream.Writer.BeginForEachIndex))))
                    .WithArgumentList(
                        ArgumentList(
                            SeparatedList(
                                new[]
                {
                    Argument(IdentifierName(EntityName)),
                    Argument(IdentifierName(GetJobIndexParameterName())),
                    Argument(LiteralExpression(
                                 SyntaxKind.NumericLiteralExpression,
                                 Literal(guid1))),
                    Argument(LiteralExpression(
                                 SyntaxKind.NumericLiteralExpression,
                                 Literal(guid2))),
                }))))
//                    .WithAdditionalAnnotations(Annotations.MakeTracingAnnotation(IterationContext.Query))
                ;
                StatementSyntax endStatement = MakeTracingEndForEachIndexStatement();
                executeMethod = executeMethod.WithBody(executeMethod.Body.WithStatements(executeMethod.Body.Statements.Insert(0, beginStatement).Add(endStatement)));
            }

            return(executeMethod);
        }