1 using System.Collections.Generic;
5 namespace Entitas.CodeGenerator {
10 var generatorName = GetType().FullName;
12 .Where(info => info.generateMethods)
14 info.fullTypeName +
"GeneratedExtension",
15 generateComponentExtension(info),
20 static string generateComponentExtension(
ComponentInfo componentInfo) {
21 var code = addNamespace();
22 code += addEntityMethods(componentInfo);
23 if(componentInfo.isSingleEntity) {
24 code += addPoolMethods(componentInfo);
27 if(componentInfo.generateComponent) {
29 code += addMatcher(componentInfo,
true);
30 code += closeNamespace();
32 code += addMatcher(componentInfo);
33 return addUsings(
"Entitas")
34 + generateComponent(componentInfo)
38 code += addMatcher(componentInfo,
true);
39 code += closeNamespace();
41 var hasCustomPools = componentInfo.pools.Length > 1 || !componentInfo.pools[0].IsDefaultPoolName();
43 code += addMatcher(componentInfo);
44 code = addUsings(
"Entitas") + code;
50 static string generateComponent(
ComponentInfo componentInfo) {
51 const string hideInBlueprintInspector =
"[Entitas.Serialization.Blueprints.HideInBlueprintInspectorAttribute]\n";
52 const string componentFormat =
@"public class {0} : IComponent {{ 58 var memberInfo = componentInfo.memberInfos[0];
59 var code =
string.Format(componentFormat, componentInfo.fullTypeName, memberInfo.type, memberInfo.name);
60 return componentInfo.hideInBlueprintInspector
61 ? hideInBlueprintInspector + code
65 static string addUsings(params
string[] usings) {
66 return string.Join(
"\n", usings
67 .Select(name =>
"using " + name +
";")
71 static string addNamespace() {
72 return "namespace Entitas {\n";
75 static string closeNamespace() {
86 return addEntityClassHeader()
87 + addGetMethods(componentInfo)
88 + addHasMethods(componentInfo)
89 + addAddMethods(componentInfo)
90 + addReplaceMethods(componentInfo)
91 + addRemoveMethods(componentInfo)
95 static string addEntityClassHeader() {
96 return "\n public partial class Entity {\n";
100 var getMethod = componentInfo.isSingletonComponent
101 ?
"\n static readonly $Type $nameComponent = new $Type();\n" 102 :
"\n public $Type $name { get { return ($Type)GetComponent($Ids.$Name); } }\n";
104 return buildString(componentInfo, getMethod);
108 var hasMethod = componentInfo.isSingletonComponent ?
@" 109 public bool $prefix$Name { 110 get { return HasComponent($Ids.$Name); } 112 if(value != $prefix$Name) { 114 AddComponent($Ids.$Name, $nameComponent); 116 RemoveComponent($Ids.$Name); 122 public Entity $Prefix$Name(bool value) { 123 $prefix$Name = value; 126 " :
@" public bool has$Name { get { return HasComponent($Ids.$Name); } } 128 return buildString(componentInfo, hasMethod);
132 return componentInfo.isSingletonComponent ?
string.Empty : buildString(componentInfo,
@" 133 public Entity Add$Name($typedArgs) { 134 var component = CreateComponent<$Type>($Ids.$Name); 136 return AddComponent($Ids.$Name, component); 141 static string addReplaceMethods(
ComponentInfo componentInfo) {
142 return componentInfo.isSingletonComponent ?
string.Empty : buildString(componentInfo,
@" 143 public Entity Replace$Name($typedArgs) { 144 var component = CreateComponent<$Type>($Ids.$Name); 146 ReplaceComponent($Ids.$Name, component); 152 static string addRemoveMethods(
ComponentInfo componentInfo) {
153 return componentInfo.isSingletonComponent ?
string.Empty : buildString(componentInfo,
@" 154 public Entity Remove$Name() { 155 return RemoveComponent($Ids.$Name); 167 return addPoolClassHeader()
168 + addPoolGetMethods(componentInfo)
169 + addPoolHasMethods(componentInfo)
170 + addPoolAddMethods(componentInfo)
171 + addPoolReplaceMethods(componentInfo)
172 + addPoolRemoveMethods(componentInfo)
176 static string addPoolClassHeader() {
177 return "\n public partial class Pool {\n";
180 static string addPoolGetMethods(
ComponentInfo componentInfo) {
181 var getMehod = componentInfo.isSingletonComponent ?
@" 182 public Entity $nameEntity { get { return GetGroup($TagMatcher.$Name).GetSingleEntity(); } } 184 public Entity $nameEntity { get { return GetGroup($TagMatcher.$Name).GetSingleEntity(); } } 185 public $Type $name { get { return $nameEntity.$name; } } 187 return buildString(componentInfo, getMehod);
190 static string addPoolHasMethods(
ComponentInfo componentInfo) {
191 var hasMethod = componentInfo.isSingletonComponent ?
@" 192 public bool $prefix$Name { 193 get { return $nameEntity != null; } 195 var entity = $nameEntity; 196 if(value != (entity != null)) { 198 CreateEntity().$prefix$Name = true; 200 DestroyEntity(entity); 205 " :
@" public bool has$Name { get { return $nameEntity != null; } } 207 return buildString(componentInfo, hasMethod);
210 static object addPoolAddMethods(
ComponentInfo componentInfo) {
211 return componentInfo.isSingletonComponent ?
string.Empty : buildString(componentInfo,
@" 212 public Entity Set$Name($typedArgs) { 214 throw new EntitasException(""Could not set $name!\n"" + this + "" already has an entity with $Type!"", 215 ""You should check if the pool already has a $nameEntity before setting it or use pool.Replace$Name().""); 217 var entity = CreateEntity(); 218 entity.Add$Name($args); 224 static string addPoolReplaceMethods(
ComponentInfo componentInfo) {
225 return componentInfo.isSingletonComponent ?
string.Empty : buildString(componentInfo,
@" 226 public Entity Replace$Name($typedArgs) { 227 var entity = $nameEntity; 229 entity = Set$Name($args); 231 entity.Replace$Name($args); 239 static string addPoolRemoveMethods(
ComponentInfo componentInfo) {
240 return componentInfo.isSingletonComponent ?
string.Empty : buildString(componentInfo,
@" 241 public void Remove$Name() { 242 DestroyEntity($nameEntity); 253 static string addMatcher(
ComponentInfo componentInfo,
bool onlyDefault =
false) {
254 const string matcherFormat =
@" 255 public partial class $TagMatcher { 257 static IMatcher _matcher$Name; 259 public static IMatcher $Name { 261 if(_matcher$Name == null) { 262 var matcher = (Matcher)Matcher.AllOf($Ids.$Name); 263 matcher.componentNames = $Ids.componentNames; 264 _matcher$Name = matcher; 267 return _matcher$Name; 274 if(componentInfo.pools.Contains(
CodeGenerator.DEFAULT_POOL_NAME)) {
275 return buildString(componentInfo, matcherFormat);
281 var matchers = componentInfo.pools.Aggregate(
string.Empty, (acc, poolName) => {
282 if(!poolName.IsDefaultPoolName()) {
283 return acc + buildString(componentInfo, matcherFormat, poolIndex++);
290 return buildString(componentInfo, matchers);
300 static string buildString(
ComponentInfo componentInfo,
string format,
int poolIndex = 0) {
301 format = createFormatString(format);
302 var a0_type = componentInfo.fullTypeName;
303 var a1_name = componentInfo.typeName.RemoveComponentSuffix();
304 var a2_lowercaseName = a1_name.LowercaseFirst();
305 var poolNames = componentInfo.pools;
306 var a3_tag = poolNames[poolIndex].PoolPrefix();
307 var lookupTags = componentInfo.ComponentLookupTags();
308 var a4_ids = lookupTags.Length == 0 ?
string.Empty : lookupTags[poolIndex];
309 var memberInfos = componentInfo.memberInfos;
310 var a5_memberNamesWithType = memberNamesWithType(memberInfos);
311 var a6_memberAssigns = memberAssignments(memberInfos);
312 var a7_memberNames = memberNames(memberInfos);
313 var prefix = componentInfo.singleComponentPrefix;
314 var a8_prefix = prefix.UppercaseFirst();
315 var a9_lowercasePrefix = prefix.LowercaseFirst();
317 return string.Format(format, a0_type, a1_name, a2_lowercaseName,
318 a3_tag, a4_ids, a5_memberNamesWithType, a6_memberAssigns, a7_memberNames,
319 a8_prefix, a9_lowercasePrefix);
322 static string createFormatString(
string format) {
323 return format.Replace(
"{",
"{{")
325 .Replace(
"$Type",
"{0}")
326 .Replace(
"$Name",
"{1}")
327 .Replace(
"$name",
"{2}")
328 .Replace(
"$Tag",
"{3}")
329 .Replace(
"$Ids",
"{4}")
330 .Replace(
"$typedArgs",
"{5}")
331 .Replace(
"$assign",
"{6}")
332 .Replace(
"$args",
"{7}")
333 .Replace(
"$Prefix",
"{8}")
334 .Replace(
"$prefix",
"{9}");
337 static string memberNamesWithType(List<PublicMemberInfo> memberInfos) {
338 var typedArgs = memberInfos
339 .Select(info => info.type.ToCompilableString() +
" new" + info.name.UppercaseFirst())
342 return string.Join(
", ", typedArgs);
345 static string memberAssignments(List<PublicMemberInfo> memberInfos) {
346 const string format =
" component.{0} = {1};";
347 var assignments = memberInfos.Select(info => {
348 var newArg =
"new" + info.name.UppercaseFirst();
349 return string.Format(format, info.name, newArg);
352 return string.Join(
"\n", assignments);
355 static string memberNames(List<PublicMemberInfo> memberInfos) {
356 var args = memberInfos.Select(info =>
"new" + info.name.UppercaseFirst()).ToArray();
357 return string.Join(
", ", args);
360 static string addCloseClass() {