diff --git a/src/gg.regression.unity.bots/Editor/Scripts/CodeGenerators/CodeGeneratorUtils.cs b/src/gg.regression.unity.bots/Editor/Scripts/CodeGenerators/CodeGeneratorUtils.cs
index fa2426786..76fb0b047 100644
--- a/src/gg.regression.unity.bots/Editor/Scripts/CodeGenerators/CodeGeneratorUtils.cs
+++ b/src/gg.regression.unity.bots/Editor/Scripts/CodeGenerators/CodeGeneratorUtils.cs
@@ -1,15 +1,24 @@
+using System.Linq;
using System.Text.RegularExpressions;
#if UNITY_EDITOR
+using System;
+using Codice.Client.Common.TreeGrouper;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
using UnityEditor;
+using UnityEngine;
#endif
namespace RegressionGames
{
#if UNITY_EDITOR
- public class CodeGeneratorUtils
+ public static class CodeGeneratorUtils
{
- public static readonly string HeaderComment = $"/*\r\n* This file has been automatically generated. Do not modify.\r\n*/\r\n\r\n";
-
+ public static readonly string HeaderComment = "/// " + Environment.NewLine +
+ "/// This file has been automatically generated. Do not modify." + Environment.NewLine +
+ "/// " + Environment.NewLine + Environment.NewLine;
+
public static string SanitizeActionName(string name)
{
return Regex.Replace(name.Replace(" ", "_"), "[^0-9a-zA-Z_]", "_");
@@ -22,6 +31,33 @@ public static string GetNamespaceForProject()
{
return Regex.Replace("RG" + PlayerSettings.productName.Replace(" ", "_"), "[^0-9a-zA-Z_]", "_");
}
+
+ public static NameSyntax QualifiedNameFor(Type type) => SyntaxFactory.ParseName(type.FullName);
+
+ public static AttributeSyntax Attribute(Type attributeType, params ExpressionSyntax[] arguments)
+ {
+ return SyntaxFactory.Attribute(
+ QualifiedNameFor(attributeType),
+ SyntaxFactory.AttributeArgumentList(
+ SyntaxFactory.SeparatedList(arguments.Select(SyntaxFactory.AttributeArgument))));
+ }
+
+ public static TypeOfExpressionSyntax TypeOf(Type t) => SyntaxFactory.TypeOfExpression(QualifiedNameFor(t));
+ public static TypeOfExpressionSyntax TypeOf(string fullTypeName) => SyntaxFactory.TypeOfExpression(SyntaxFactory.ParseName(fullTypeName));
+ public static ClassDeclarationSyntax PartialClass(string name) => SyntaxFactory.ClassDeclaration(name)
+ .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PartialKeyword)));
+
+ public static MemberDeclarationSyntax CreatePartialAttacherClass(
+ string ns, string name, params string[] componentTypeNames)
+ {
+ var classDeclaration = PartialClass(name)
+ .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(
+ componentTypeNames.Select(componentType =>
+ Attribute(typeof(RequireComponent), TypeOf(componentType))))));
+ return string.IsNullOrEmpty(ns)
+ ? classDeclaration
+ : SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(ns)).AddMembers(classDeclaration);
+ }
}
#endif
}
diff --git a/src/gg.regression.unity.bots/Editor/Scripts/CodeGenerators/GenerateRGActionClasses.cs b/src/gg.regression.unity.bots/Editor/Scripts/CodeGenerators/GenerateRGActionClasses.cs
index ae935c232..000df179a 100644
--- a/src/gg.regression.unity.bots/Editor/Scripts/CodeGenerators/GenerateRGActionClasses.cs
+++ b/src/gg.regression.unity.bots/Editor/Scripts/CodeGenerators/GenerateRGActionClasses.cs
@@ -8,6 +8,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
+using RegressionGames.RGBotConfigs;
using UnityEditor;
#endif
@@ -19,7 +20,7 @@ public static class GenerateRGActionClasses
{
public static void Generate(List actionInfos)
{
- Dictionary fileWriteTasks = new();
+ Dictionary fileWriteTasks = new();
// Iterate through BotActions
foreach (var botAction in actionInfos)
{
@@ -41,11 +42,12 @@ public static void Generate(List actionInfos)
}
var projectNamespace = CodeGeneratorUtils.GetNamespaceForProject();
-
+
botAction.GeneratedClassName =
$"{projectNamespace}.RGAction_{CodeGeneratorUtils.SanitizeActionName(botAction.ActionName)}";
// Create a new compilation unit
+ var actionClassName = $"RGAction_{CodeGeneratorUtils.SanitizeActionName(botAction.ActionName)}";
CompilationUnitSyntax compilationUnit = SyntaxFactory.CompilationUnit()
.AddUsings(
usings.Select(v => SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(v))).ToArray()
@@ -56,8 +58,13 @@ public static void Generate(List actionInfos)
.AddMembers(
// Class declaration
SyntaxFactory
- .ClassDeclaration(
- $"RGAction_{CodeGeneratorUtils.SanitizeActionName(botAction.ActionName)}")
+ .ClassDeclaration(actionClassName)
+ .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SeparatedList(new[]
+ {
+ CodeGeneratorUtils.Attribute(typeof(DisallowMultipleComponent)),
+ CodeGeneratorUtils.Attribute(typeof(RequireComponent),
+ CodeGeneratorUtils.TypeOf(typeof(RGEntity)))
+ })))
.AddModifiers(
SyntaxFactory.Token(SyntaxKind.PublicKeyword)
// Only add one of the "class" keywords here
@@ -87,10 +94,15 @@ public static void Generate(List actionInfos)
GenerateActionRequestConstructor(botAction)
)
)
- );
+ )
+ .AddMembers(CodeGeneratorUtils.CreatePartialAttacherClass(
+ botAction.Namespace,
+ botAction.Object,
+ typeof(RGEntity).FullName,
+ $"{projectNamespace}.{actionClassName}"));
// Format the generated code
- string formattedCode = compilationUnit.NormalizeWhitespace().ToFullString();
+ string formattedCode = compilationUnit.NormalizeWhitespace(eol: Environment.NewLine).ToFullString();
// Save to 'Assets/RegressionGames/Runtime/GeneratedScripts/RGActions,RGSerialization.cs'
string fileName = $"RGAction_{CodeGeneratorUtils.SanitizeActionName(botAction.ActionName)}.cs";
@@ -167,7 +179,7 @@ private static MemberDeclarationSyntax GenerateGetActionNameMethod(RGActionAttri
return getActionNameMethod;
}
-
+
private static ArgumentSyntax GenerateActionDelegate(RGActionAttributeInfo action)
{
// Generate the GetComponent