/// <summary> /// Generate new Atoms based on the input data. /// </summary> /// <param name="valueType">The type of Atom to generate.abstract Eg. double, byte, MyStruct, MyClass.</param> /// <param name="baseWritePath">Base write path (relative to the Asset folder) where the Atoms are going to be written to.</param> /// <param name="isEquatable">Is the `type` provided implementing `IEquatable`?</param> /// <param name="atomTypesToGenerate">A list of `AtomType`s to be generated.</param> /// <param name="typeNamespace">If the `type` provided is defined under a namespace, provide that namespace here.</param> /// <param name="subUnityAtomsNamespace">By default the Atoms that gets generated will be under the namespace `UnityAtoms`. If you for example like it to be under `UnityAtoms.MyNamespace` you would then enter `MyNamespace` in this field.</param> /// <example> /// <code> /// namespace MyNamespace /// { /// public struct MyStruct /// { /// public string Text; /// public int Number; /// } /// } /// var generator = new Generator(); /// generator.Generate("MyStruct", "", false, new List<AtomType>() { AtomTypes.ACTION }, "MyNamespace", ""); // Generates an Atom Action of type MyStruct /// </code> /// </example> public static void Generate(AtomReceipe atomReceipe, string baseWritePath, string[] templatePaths, List <string> templateConditions, Dictionary <string, string> templateVariables) { var(atomType, valueType) = atomReceipe; // TODO: More validation of that the type exists / is correct. if (string.IsNullOrEmpty(valueType)) { Debug.LogWarning($"{Runtime.Constants.LOG_PREFIX} You need to specify a value type. Aborting!"); return; } if (string.IsNullOrEmpty(baseWritePath) || !Directory.Exists(baseWritePath)) { Debug.LogWarning($"{Runtime.Constants.LOG_PREFIX} You need to specify a valid base write path. Aborting!"); return; } Debug.Log($"{Runtime.Constants.LOG_PREFIX} Generating atom {atomType.Name} for value type {valueType}"); List <Tuple <string, string> > filesToGenerate = new List <Tuple <string, string> >() { new Tuple <string, string>(atomType.TemplateName, atomType.RelativeFileNameAndPath) }; if (atomType.HasDrawerTemplate) { filesToGenerate.Add(new Tuple <string, string>(atomType.DrawerTemplateName, atomType.RelativeDrawerFileNameAndPath)); } if (atomType.HasEditorTemplate) { filesToGenerate.Add(new Tuple <string, string>(atomType.EditorTemplateName, atomType.RelativeEditorFileNameAndPath)); } foreach (var(templateName, relativeFilePath) in filesToGenerate) { var templatePath = templatePaths.FirstOrDefault((path) => path.EndsWith(templateName)); if (string.IsNullOrEmpty(templatePath)) { Debug.Log($"{Runtime.Constants.LOG_PREFIX} Template {templateName} for {atomType.DisplayName} not found. Skipping!"); return; } var resolvedRelativeFilePath = Templating.ResolveVariables(templateVariables: templateVariables, toResolve: relativeFilePath); var template = File.ReadAllText(templatePath); var filePath = Path.Combine(baseWritePath, resolvedRelativeFilePath); var fileDirectory = Path.GetDirectoryName(filePath); // Create write directory Directory.CreateDirectory(fileDirectory); // Adjust content var content = Templating.ResolveVariables(templateVariables: templateVariables, toResolve: template); content = Templating.ResolveConditionals(template: content, trueConditions: templateConditions); content = RemoveDuplicateNamespaces(template: content); // Write to file File.WriteAllText(filePath, content); AssetDatabase.ImportAsset(filePath); } }
/// <summary> /// Generate new Atoms based on the input data. /// </summary> /// <param name="type">The type of Atom to generate.abstract Eg. double, byte, MyStruct, MyClass.</param> /// <param name="baseWritePath">Base write path (relative to the Asset folder) where the Atoms are going to be written to.</param> /// <param name="isEquatable">Is the `type` provided implementing `IEquatable`?</param> /// <param name="atomTypesToGenerate">A list of `AtomType`s to be generated.</param> /// <param name="typeNamespace">If the `type` provided is defined under a namespace, provide that namespace here.</param> /// <param name="subUnityAtomsNamespace">By default the Atoms that gets generated will be under the namespace `UnityAtoms`. If you for example like it to be under `UnityAtoms.MyNamespace` you would then enter `MyNamespace` in this field.</param> /// <example> /// <code> /// namespace MyNamespace /// { /// public struct MyStruct /// { /// public string Text; /// public int Number; /// } /// } /// var generator = new Generator(); /// generator.Generate("MyStruct", "", false, new List<AtomType>() { AtomTypes.ACTION }, "MyNamespace", ""); // Generates an Atom Action of type MyStruct /// </code> /// </example> public void Generate(string type, string baseWritePath, bool isEquatable, List <AtomType> atomTypesToGenerate, string typeNamespace, string subUnityAtomsNamespace) { // TODO: More validation of that the type exists / is correct. if (string.IsNullOrEmpty(type)) { Debug.LogWarning($"{Runtime.Constants.LOG_PREFIX} You need to specify a type name. Aborting!"); return; } if (string.IsNullOrEmpty(baseWritePath)) { Debug.LogWarning($"{Runtime.Constants.LOG_PREFIX} You need to specify a write path. Aborting!"); return; } Debug.Log($"{Runtime.Constants.LOG_PREFIX} Generating " + type); // Create directories in path if they don't exists Directory.CreateDirectory(baseWritePath); // Recursively search for template files. TODO: Is there a better way to find and load templates? var templateSearchPath = Runtime.IsUnityAtomsRepo ? Directory.GetParent(Directory.GetParent(Application.dataPath).FullName).FullName : Directory.GetParent(Application.dataPath).FullName; var templatePaths = Directory.GetFiles(templateSearchPath, "UA_Template*.txt", SearchOption.AllDirectories); var templateConditions = new List <string>(); if (isEquatable) { templateConditions.Add("EQUATABLE"); } if (!string.IsNullOrEmpty(typeNamespace)) { templateConditions.Add("TYPE_HAS_NAMESPACE"); } if (!string.IsNullOrEmpty(subUnityAtomsNamespace)) { templateConditions.Add("HAS_SUB_UA_NAMESPACE"); } var capitalizedType = Capitalize(type); var templateVariables = new Dictionary <string, string>() { { "TYPE_NAME", capitalizedType }, { "TYPE", type } }; if (!string.IsNullOrEmpty(typeNamespace)) { templateVariables.Add("TYPE_NAMESPACE", typeNamespace); } if (!string.IsNullOrEmpty(subUnityAtomsNamespace)) { templateVariables.Add("SUB_UA_NAMESPACE", subUnityAtomsNamespace); } foreach (var templatePath in templatePaths) { var templateNameStartIndex = templatePath.LastIndexOf(Path.DirectorySeparatorChar) + 1; var fileExtLength = 4; var templateName = templatePath.Substring(templateNameStartIndex, templatePath.Length - templateNameStartIndex - fileExtLength); var lastIndexOfDoubleUnderscore = templateName.LastIndexOf("__"); var atomType = templateName.Substring(lastIndexOfDoubleUnderscore + 2); var capitalizedAtomType = Capitalize(atomType); var typeOccurrences = templateName.Substring(lastIndexOfDoubleUnderscore - 1, 1).ToInt(def: 1); if (ShouldSkipTemplate(atomTypesToGenerate, capitalizedAtomType, typeOccurrences)) { continue; } var template = File.ReadAllText(templatePath); // Create write directory var dirPath = ResolveDirPath(baseWritePath, capitalizedAtomType, templateName, atomType); Directory.CreateDirectory(dirPath); // Adjust content var content = Templating.ResolveVariables(templateVariables: templateVariables, toResolve: template); content = Templating.ResolveConditionals(template: content, trueConditions: templateConditions); content = RemoveDuplicateNamespaces(content); // Write to file var fileName = ResolveFileName(templateVariables, templateName, lastIndexOfDoubleUnderscore, capitalizedType, capitalizedAtomType, typeOccurrences); var filePath = Path.Combine(dirPath, fileName); File.WriteAllText(filePath, content); AssetDatabase.ImportAsset(filePath); } AssetDatabase.Refresh(); }