BaseTypeSyntax MakeJobBaseType(RoslynEcsTranslator.IterationContext iterationContext, List <ParameterSyntax> functionParameters, out Type eventType) { var genericArguments = new List <TypeSyntax>(); eventType = null; int componentCount = 0; int bufferCount = 0; if (iterationContext.UpdateMode != UpdateMode.OnEnd) { if (iterationContext.UpdateMode == UpdateMode.OnEvent) // add DynamicBuffer<eventType> { eventType = ((OnEventNodeModel)iterationContext.Query).EventTypeHandle.Resolve(iterationContext.Stencil); var eventTypeSyntax = TypeSystem.BuildTypeSyntax(eventType); var bufferType = GenericName("DynamicBuffer") .WithTypeArgumentList(TypeArgumentList(SingletonSeparatedList(eventTypeSyntax))); var parameterSyntax = Parameter( Identifier(OnEventNodeModel.GetBufferName(eventType))) .WithType(bufferType); AddReadOnlyAttribute(ref parameterSyntax); bufferCount = 1; functionParameters.Add(parameterSyntax); genericArguments.Add(eventTypeSyntax); } foreach (ComponentDefinition definition in iterationContext.FlattenedComponentDefinitions().Where(def => !def.Subtract)) { if (!RoslynEcsTranslatorExtensions.ShouldGenerateComponentAccess(definition.TypeHandle, true, out Type resolvedType, iterationContext.Stencil, out bool isShared, out bool isGameObjectComponent) || isGameObjectComponent) { continue; } if (isShared) { throw new RoslynEcsTranslator.JobSystemNotCompatibleException("Shared Components are not supported in jobs yet"); } genericArguments.Add(TypeSystem.BuildTypeSyntax(resolvedType)); var parameterSyntax = Parameter( Identifier(GetComponentVariableName(iterationContext.Query, definition.TypeHandle))) .WithModifiers(TokenList(Token(SyntaxKind.RefKeyword))) .WithType(TypeSystem.BuildTypeSyntax(resolvedType)); if (!m_WrittenComponents.Contains(definition.TypeHandle)) { AddReadOnlyAttribute(ref parameterSyntax); } functionParameters.Add( parameterSyntax); componentCount++; } if (genericArguments.Count == 0) { return(null); } } string CleanGenericName(string s) { var index = s.IndexOf('`'); return(index == -1 ? s : s.Substring(0, index)); } // IJobForEachWitEntity_EBBCCC string suffix = componentCount > 0 || bufferCount > 0 ? $"_E{new String('B', bufferCount)}{new String('C', componentCount)}" : ""; return(SimpleBaseType( GenericName( Identifier(CleanGenericName(typeof(IJobForEachWithEntity <>).Name) + suffix)) .WithTypeArgumentList( TypeArgumentList( SeparatedList( genericArguments))))); ParameterSyntax AddReadOnlyAttribute(ref ParameterSyntax parameterSyntax) { return(parameterSyntax = parameterSyntax.WithAttributeLists( SingletonList( AttributeList( SingletonSeparatedList( Attribute( IdentifierName(nameof(ReadOnlyAttribute)))))))); } }
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); }
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); }