1
+ using Ambratolm . ScriptGenerator . Utilities ;
2
+ using System ;
3
+ using System . IO ;
4
+ using UnityEditor ;
5
+ using UnityEngine ;
6
+ using static Ambratolm . ScriptGenerator . Utilities . SelectionUtility ;
7
+
8
+ namespace Ambratolm . ScriptGenerator
9
+ {
10
+ /// <summary>
11
+ /// Generates C# classes from template assets.
12
+ /// </summary>
13
+ internal sealed class ClassGenerator : AssetModificationProcessor
14
+ {
15
+ private const string _templateExtension = ".template.cs" ;
16
+ private const string _assetMenuItemPath = "Assets/Generate C# Class" ;
17
+ private static string _templateFilePath ;
18
+ private static string _templateFileName ;
19
+
20
+ //----------------------------------------------------------------------------------------------------
21
+
22
+ /// <summary>
23
+ /// Menu item function. It generates a class file from the selected class template asset.
24
+ /// </summary>
25
+ [ MenuItem ( _assetMenuItemPath ) ]
26
+ public static void OnGenerate ( ) => Generate ( ) ;
27
+
28
+ /// <summary>
29
+ /// Menu item validation function. It validates the selected asset.
30
+ /// <para>
31
+ /// Called before invoking the menu item function with the same itemName on the MenuItem attribute.
32
+ /// </para>
33
+ /// </summary>
34
+ /// <returns>A boolean value that indicates whether the validation succeeded or not.</returns>
35
+ [ MenuItem ( _assetMenuItemPath , isValidateFunction : true ) ]
36
+ private static bool OnValidate ( ) => Validate ( throwException : false ) ;
37
+
38
+ //----------------------------------------------------------------------------------------------------
39
+
40
+ /// <summary>
41
+ /// Generates a C# class file from a template and saves it to the output location.
42
+ /// </summary>
43
+ private static void Generate ( )
44
+ {
45
+ Validate ( ) ;
46
+ Type templateType = GetClassTemplateType ( out string templateText ) ;
47
+ ClassTemplate template = Activator . CreateInstance ( templateType , templateText ) as ClassTemplate ;
48
+ string className = template . HasClass ? template . ClassName : "_" ;
49
+ string fileName = $ "{ className } .cs";
50
+ string filePath = _templateFilePath . Replace ( _templateFileName , fileName ) ;
51
+ File . WriteAllText ( filePath , contents : template . GenerateClassCode ( ) ) ;
52
+ UnityEngine . Object generatedAsset = AssetDatabase . LoadAssetAtPath ( filePath , typeof ( UnityEngine . Object ) ) ;
53
+ Debug . Log ( $ "\" { className } \" class generated at \" { filePath } \" ", generatedAsset ) ;
54
+ AssetDatabase . Refresh ( ) ;
55
+ }
56
+
57
+ /// <summary>
58
+ /// Validates the selected asset.
59
+ /// <para>
60
+ /// The asset is considered valid if it is a class template script that has the template extension.
61
+ /// </para>
62
+ /// </summary>
63
+ /// <param name="throwException">Whether to throw an exception if the validation fails.</param>
64
+ /// <returns>True if the asset is valid, false otherwise.</returns>
65
+ private static bool Validate ( bool throwException = true )
66
+ {
67
+ _templateFilePath = SelectedAssetPath ;
68
+ _templateFileName = Path . GetFileName ( _templateFilePath ) ;
69
+ bool assetIsValid = SelectedAssetIsScript ;
70
+ if ( throwException && ! assetIsValid ) throw new InvalidDataException ( $ "Invalid asset type at \" { _templateFilePath } \" . " +
71
+ $ "\" { _templateFileName } \" asset should be a script.") ;
72
+ assetIsValid &= FileUtility . Validate ( _templateFilePath , _templateExtension , out Exception exception ) ;
73
+ if ( throwException && ! assetIsValid )
74
+ throw exception ;
75
+ return assetIsValid ;
76
+ }
77
+
78
+ /// <summary>
79
+ /// Gets the type of the ClassTemplate class defined in the selected script and its text.
80
+ /// </summary>
81
+ /// <param name="classTemplateText">The text of the class template script.</param>
82
+ /// <returns>The class template type.</returns>
83
+ /// <exception cref="InvalidDataException">
84
+ /// Thrown when the script is invalid or does not inherit from ClassTemplate.
85
+ /// </exception>
86
+ private static Type GetClassTemplateType ( out string classTemplateText )
87
+ {
88
+ MonoScript script = Selection . activeObject as MonoScript ;
89
+ Type classTemplateType = script . GetClass ( ) ;
90
+ if ( classTemplateType is null ) throw new InvalidDataException ( $ "Invalid script at \" { _templateFilePath } \" . " +
91
+ $ "Script doesn't implement any class. It should implement a class that inherits from \" { nameof ( ClassTemplate ) } \" ") ;
92
+ if ( ! classTemplateType . IsSubclassOf ( typeof ( ClassTemplate ) ) ) throw new InvalidDataException ( $ "Invalid script at \" { _templateFilePath } \" . " +
93
+ $ "Implemented \" { classTemplateType . Name } \" class should inherit from \" { nameof ( ClassTemplate ) } \" .") ;
94
+ classTemplateText = script . text ;
95
+ return classTemplateType ;
96
+ }
97
+ }
98
+ }
0 commit comments