예제 #1
0
        public static IEnumerable <SyntaxNode> Build(
            this RoslynEcsTranslator translator,
            RemoveComponentNodeModel model,
            IPortModel portModel)
        {
            var componentType    = model.ComponentType.Resolve(model.GraphModel.Stencil);
            var entityTranslator = translator.context.GetEntityManipulationTranslator();
            var entitySyntax     = translator.BuildPort(model.EntityPort).SingleOrDefault() as ExpressionSyntax;

            return(entityTranslator.RemoveComponent(translator.context, entitySyntax, componentType));
        }
예제 #2
0
        public static IEnumerable <SyntaxNode> Build(
            this RoslynEcsTranslator translator,
            AddComponentNodeModel model,
            IPortModel portModel)
        {
            var componentType    = model.ComponentType.Resolve(model.GraphModel.Stencil);
            var entitySyntax     = translator.BuildPort(model.EntityPort).SingleOrDefault() as ExpressionSyntax;
            var componentInputs  = model.GetPortsForComponent().ToArray();
            var componentSyntax  = translator.BuildComponentFromInput(componentType, componentInputs);
            var entityTranslator = translator.context.GetEntityManipulationTranslator();

            return(entityTranslator.AddComponent(translator.context, entitySyntax, componentType, componentSyntax));
        }
예제 #3
0
        public static IEnumerable <SyntaxNode> Build(
            this RoslynEcsTranslator translator,
            CountEntitiesNodeModel model,
            IPortModel portModel)
        {
            var connected = model.InputPort.ConnectionPortModels.FirstOrDefault();

            if (connected?.NodeModel is VariableNodeModel variableNode &&
                variableNode.DeclarationModel is ComponentQueryDeclarationModel queryDeclaration)
            {
                yield return(RoslynBuilder.MethodInvocation(nameof(EntityQuery.CalculateEntityCount),
                                                            SyntaxFactory.IdentifierName(queryDeclaration.VariableName), null, null));
            }
        }
예제 #4
0
        public static IEnumerable <SyntaxNode> Build(this RoslynEcsTranslator translator, SetComponentNodeModel model,
                                                     IPortModel portModel)
        {
            var query            = translator.context.IterationContext.Query;
            var queryDeclaration = query.ComponentQueryDeclarationModel;
            var componentTypes   = model.GetComponentTypesFromEntityPort();

            if (!model.ComponentType.Equals(TypeHandle.Unknown) && !componentTypes.Any(c => c == model.ComponentType))
            {
                var componentName = model.ComponentType.Name(translator.Stencil);
                var queryCopy     = queryDeclaration;

                translator.AddError(
                    model,
                    $"A component of type {componentName} is required, which the query {queryDeclaration.Name} " +
                    "doesn't specify",
                    new CompilerQuickFix(
                        $"Add {componentName} to the query",
                        s => s.Dispatch(new AddComponentToQueryAction(
                                            queryCopy,
                                            model.ComponentType,
                                            ComponentDefinitionFlags.None))));

                return(Enumerable.Empty <SyntaxNode>());
            }

            if (!queryDeclaration.Components.Any())
            {
                translator.AddError(model, $"The query {queryDeclaration.Name} doesn't contain any component.");
                return(Enumerable.Empty <SyntaxNode>());
            }

            if (model.ComponentType.Equals(TypeHandle.Unknown))
            {
                translator.AddError(model, "You must select a valid component type");
                return(Enumerable.Empty <SyntaxNode>());
            }

            var entitySyntax     = translator.BuildEntityFromPortOrCurrentIteration(model.EntityPort);
            var componentType    = model.ComponentType.Resolve(model.GraphModel.Stencil);
            var componentInputs  = model.GetPortsForComponent().ToArray();
            var componentSyntax  = translator.BuildComponentFromInput(componentType, componentInputs);
            var entityTranslator = translator.context.GetEntityManipulationTranslator();

            return(entityTranslator.SetComponent(translator.context, entitySyntax, componentType, componentSyntax));
        }
예제 #5
0
        public static IEnumerable <SyntaxNode> BuildSetTranslation(this RoslynEcsTranslator translator, SetPositionNodeModel model, IPortModel portModel)
        {
            IPortModel entityOrComponentPort = model.InstancePort;

            if (!translator.GetComponentFromEntityOrComponentPort(model, entityOrComponentPort, out _, out ExpressionSyntax setValue, RoslynEcsTranslator.AccessMode.Write))
            {
                yield break;
            }

            switch (model.Mode)
            {
            case SetPositionNodeModel.TranslationMode.Float3:
                yield return(RoslynBuilder.SetProperty(
                                 model.Add ? RoslynBuilder.AssignmentKind.Add : RoslynBuilder.AssignmentKind.Set,
                                 setValue,
                                 translator.BuildPort(model.GetInput(SetPositionNodeModel.InputType.Value)).FirstOrDefault() as ExpressionSyntax,
                                 nameof(Translation.Value)));

                break;

            case SetPositionNodeModel.TranslationMode.Axis:
                var inputTypes = new[]
                {
                    Tuple.Create(SetPositionNodeModel.InputType.X, nameof(float3.x)),
                    Tuple.Create(SetPositionNodeModel.InputType.Y, nameof(float3.y)),
                    Tuple.Create(SetPositionNodeModel.InputType.Z, nameof(float3.z))
                };
                foreach (var inputType in inputTypes)
                {
                    IPortModel axisPort = model.GetInput(inputType.Item1);
                    yield return(RoslynBuilder.SetProperty(
                                     model.Add ? RoslynBuilder.AssignmentKind.Add : RoslynBuilder.AssignmentKind.Set,
                                     setValue,
                                     translator.BuildPort(axisPort).FirstOrDefault() as ExpressionSyntax,
                                     nameof(Translation.Value), inputType.Item2));
                }
                break;
            }
        }
        Type CompileGraph(CodeGenMode mode)
        {
            RoslynEcsTranslator translator = (RoslynEcsTranslator)GraphModel.CreateTranslator();

            translator.AllowNoJobsFallback = false;

            // because of the hack in the translator constructor, override right after
            ((EcsStencil)Stencil).UseJobSystem = mode == CodeGenMode.Jobs;

            CompilationResult results = GraphModel.Compile(AssemblyType.Memory, translator,
                                                           CompilationOptions.LiveEditing);

            if (results?.sourceCode != null && results.sourceCode.Length != 0)
            {
                LogAssert.Expect(LogType.Log, new Regex("using.*"));
                Debug.Log(results.sourceCode[(int)SourceCodePhases.Initial]);
            }

            Assert.That(results?.status, Is.EqualTo(CompilationStatus.Succeeded),
                        () => $"Compilation failed, errors: {String.Join("\n", results?.errors)}");

            return(EcsStencil.LiveCompileGraph(GraphModel, results, includeVscriptingAssemblies: true));
        }
        public static IEnumerable <SyntaxNode> BuildGetComponent(this RoslynEcsTranslator translator, GetOrCreateComponentNodeModel model, IPortModel portModel)
        {
            var entity = translator.BuildPort(model.EntityPort).First() as ExpressionSyntax;

            TypeSyntax componentType = TypeSystem.BuildTypeSyntax(model.ComponentType.Resolve(translator.Stencil));

            yield return(InvocationExpression(
                             MemberAccessExpression(
                                 SyntaxKind.SimpleMemberAccessExpression,
                                 IdentifierName(nameof(EntityManager)),
                                 GenericName(
                                     Identifier(model.CreateIfNeeded ? nameof(EcsHelper.GetOrCreateComponentData) : nameof(EntityManager.GetComponentData)))
                                 .WithTypeArgumentList(
                                     TypeArgumentList(
                                         SingletonSeparatedList(
                                             componentType
                                             )))))
                         .WithArgumentList(
                             ArgumentList(
                                 SingletonSeparatedList(
                                     Argument(
                                         entity)))));
        }
예제 #8
0
        public static IEnumerable <SyntaxNode> BuildInstantiateEntityTranslator(this RoslynEcsTranslator translator,
                                                                                InstantiateNodeModel model, IPortModel portModel)
        {
            bool             hasAnyComponentInstruction = false;
            ExpressionSyntax newInstance = null;

            if (model.InstancePort.Connected)
            {
                newInstance = translator.BuildPort(model.InstancePort).SingleOrDefault() as ExpressionSyntax;
                hasAnyComponentInstruction = true;
            }

            // always instantiate
            var newEntity = InstantiateEntity(translator, model);

            if (hasAnyComponentInstruction) // == if connected. assignment of implicit variable is done only if it's required in the foreach loop below
            {
                yield return(RoslynBuilder.Assignment(newInstance, newEntity));
            }

            var entityTranslator = translator.context.GetEntityManipulationTranslator();

            foreach (ComponentOperation compOperation in model.GetEditableComponents())
            {
                var componentType = compOperation.Type.Resolve(model.GraphModel.Stencil);
                IEnumerable <SyntaxNode> instructions;
                // first instruction forces the declaration of an implicit variable if not already done
                if (!hasAnyComponentInstruction)
                {
                    hasAnyComponentInstruction = true;
                    string entityVariableName = translator.MakeUniqueName("entity");
                    yield return(RoslynBuilder.DeclareLocalVariable(typeof(Entity), entityVariableName, newEntity));

                    newInstance = SyntaxFactory.IdentifierName(entityVariableName);
                }
                switch (compOperation.OperationType)
                {
                case ComponentOperationType.AddComponent:
                    instructions = entityTranslator.AddComponent(translator.context, newInstance, componentType,
                                                                 BuildNewComponent(compOperation, componentType));
                    break;

                case ComponentOperationType.RemoveComponent:
                    instructions = entityTranslator.RemoveComponent(translator.context, newInstance, componentType);
                    break;

                case ComponentOperationType.SetComponent:
                    instructions = entityTranslator.SetComponent(translator.context, newInstance, componentType,
                                                                 BuildNewComponent(compOperation, componentType));
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                foreach (var instruction in instructions)
                {
                    yield return(instruction);
                }
            }

            if (!hasAnyComponentInstruction) // implicit variable, never used in the loop
            {
                yield return(SyntaxFactory.ExpressionStatement(newEntity));
            }

            ExpressionSyntax BuildNewComponent(ComponentOperation compOperation, Type componentType)
            {
                var componentInput = model.GetPortsForComponent(compOperation.Type).ToArray();
                var newComponent   = translator.BuildComponentFromInput(componentType, componentInput);

                return(newComponent);
            }
        }
예제 #9
0
 public static IEnumerable <SyntaxNode> BuildOnKeyPressEcs(this RoslynEcsTranslator translator,
                                                           ConditionalUpdateEntitiesNodeModel model, IPortModel portModel)
 {
     return(translator.BuildOnEntitiesEventBase(model, MakeConstraint(model)));
 }
예제 #10
0
        public static IEnumerable <SyntaxNode> BuildSetTranslation(this RoslynEcsTranslator translator, SetRotationNodeModel model, IPortModel portModel)
        {
            ExpressionSyntax BuildPortForInput(SetRotationNodeModel.InputType inputType)
            {
                return(translator.BuildPort(model.GetInput(inputType)).FirstOrDefault() as ExpressionSyntax);
            }

            ExpressionSyntax value;

            switch (model.Mode)
            {
            case SetRotationNodeModel.RotationMode.Axis:
                var axisValue  = BuildPortForInput(SetRotationNodeModel.InputType.Axis);
                var angleValue = BuildPortForInput(SetRotationNodeModel.InputType.Angle);
                axisValue = InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
                                                                        IdentifierName(nameof(math)), IdentifierName(nameof(math.normalize)))).WithArgumentList(ArgumentList(SingletonSeparatedList(Argument(axisValue))));
                value = InvocationExpression(
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        IdentifierName(nameof(quaternion)),
                        IdentifierName(nameof(quaternion.AxisAngle))))
                        .WithArgumentList(
                    ArgumentList(
                        SeparatedList(new[]
                {
                    Argument(axisValue),
                    Argument(angleValue)
                })));
                break;

            case SetRotationNodeModel.RotationMode.Quaternion:
                value = BuildPortForInput(SetRotationNodeModel.InputType.Quaternion);
                break;

            case SetRotationNodeModel.RotationMode.Euler:
                value = InvocationExpression(
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        IdentifierName(nameof(quaternion)),
                        IdentifierName(nameof(quaternion.EulerXYZ))))
                        .WithArgumentList(
                    ArgumentList(
                        SeparatedList(new[]
                {
                    Argument(BuildPortForInput(SetRotationNodeModel.InputType.X)),
                    Argument(BuildPortForInput(SetRotationNodeModel.InputType.Y)),
                    Argument(BuildPortForInput(SetRotationNodeModel.InputType.Z))
                })));
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            if (!translator.GetComponentFromEntityOrComponentPort(model, model.InstancePort, out _, out ExpressionSyntax setValue, RoslynEcsTranslator.AccessMode.Write))
            {
                yield break;
            }
            var finalValue = !model.Add
                ? value
                : InvocationExpression( // rot.value = math.mul(rot.value, <input>)
                MemberAccessExpression(
                    SyntaxKind.SimpleMemberAccessExpression,
                    IdentifierName(nameof(math)),
                    IdentifierName(nameof(math.mul))))
                             .WithArgumentList(
                ArgumentList(
                    SeparatedList(new[]
            {
                Argument(
                    MemberAccessExpression(
                        SyntaxKind.SimpleMemberAccessExpression,
                        setValue,
                        IdentifierName(nameof(Rotation.Value)))),
                Argument(value)
            })));

            yield return(RoslynBuilder.SetProperty(
                             RoslynBuilder.AssignmentKind.Set,
                             setValue,
                             finalValue,
                             nameof(Rotation.Value)
                             ));
        }