public SyntaxNode SendEvent(TranslationContext translatorContext, ExpressionSyntax entity, Type eventType, ExpressionSyntax newEventSyntax) { if (m_Concurrent) { //throw new RoslynEcsTranslator.JobSystemNotCompatibleException("Sending event in job isn't implemented yet"); } ExpressionSyntax bufferName = translatorContext.GetEventBufferWriter(translatorContext.IterationContext, entity, eventType, out var bufferInitialization); if (bufferInitialization != null) { translatorContext.AddStatement(bufferInitialization); } // EntityManager.GetBuffer<TestEvent2>(e).Add(<new event syntax>)) return(InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, bufferName, IdentifierName("Add"))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( newEventSyntax)))) .NormalizeWhitespace()); }
Microsoft.CodeAnalysis.SyntaxTree GenerateSyntaxTree(VSGraphModel graphModel, CompilationOptions compilationOptions, bool useJobSystem) { var ecsStencil = (EcsStencil)graphModel.Stencil; ecsStencil.ClearComponentDefinitions(); //TODO fix graph name, do not use the asset name var className = graphModel.TypeName; TranslationOptions options = TranslationOptions.None; if (useJobSystem) { options |= TranslationOptions.UseJobs; } if (!compilationOptions.HasFlag(CompilationOptions.LiveEditing)) { options |= TranslationOptions.BurstCompile; } var rootContext = new RootContext(ecsStencil, className, options); context = rootContext; List <IFunctionModel> entryPoints = GetEntryPointStacks(graphModel).ToList(); BuildSpecificStack <PreUpdate>(entryPoints, rootContext); foreach (FunctionModel stack in entryPoints.Cast <FunctionModel>().OrderBy(x => x is IOrderedStack orderedStack ? orderedStack.Order : -1)) { if (stack is PreUpdate || stack is PostUpdate) { continue; } IEnumerable <SyntaxNode> entrySyntaxNode = BuildNode(stack); foreach (var node in entrySyntaxNode) { switch (node) { case null: continue; case StatementSyntax statement: context.AddStatement(statement); break; case MemberDeclarationSyntax member: rootContext.AddMember(member); break; default: Debug.LogError($"Cannot process syntax node type {node.GetType().Name}"); break; } } } // TODO: events (see KeyDownEvent) // foreach (var statementSyntax in m_EventRegistrations) rootContext.AddStatement(statementSyntax); BuildSpecificStack <PostUpdate>(entryPoints, rootContext); var referencedNamespaces = new List <string> { "System", "Unity.Burst", "Unity.Entities", "Unity.Jobs", "Unity.Mathematics", "Unity.Transforms", "Unity.Collections", "Microsoft.CSharp", "UnityEngine", }; referencedNamespaces = referencedNamespaces.Distinct().ToList(); var usingList = new List <UsingDirectiveSyntax>(); foreach (var ns in referencedNamespaces) { string[] identifiers = ns.Split(".".ToCharArray()); if (identifiers.Length == 1) { usingList.Add(UsingDirective(IdentifierName(identifiers[0]))); } else if (identifiers.Length == 2) { usingList.Add(UsingDirective(QualifiedName(IdentifierName(identifiers[0]), IdentifierName(identifiers[1])))); } else if (identifiers.Length == 3) { usingList.Add(UsingDirective(QualifiedName( QualifiedName(IdentifierName(identifiers[0]), IdentifierName(identifiers[1])), IdentifierName(identifiers[2])))); } } CompilationUnitSyntax compilationUnit = CompilationUnit() .WithUsings( List(usingList.ToArray())) .WithMembers( SingletonList <MemberDeclarationSyntax>(rootContext.Build(this, graphModel))).NormalizeWhitespace(); return(compilationUnit.SyntaxTree); }
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)); } }