CustomAssets
Askowl Custom Assets
AssetWizard.cs
1 // Copyright 2019 (C) paul@marrington.net http://www.askowl.net/unity-packages
2 
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 using System.Text;
7 using System.Text.RegularExpressions;
8 using CustomAsset;
9 using UnityEditor;
10 using UnityEngine;
11 
12 namespace Askowl {
13  public interface ICreate {
14  void Create();
15  }
16  public abstract class AssetWizard : Manager, ICreate {
17  protected static string destination, type;
18  private List<string> sources = new List<string>();
19  protected string Label = "BuildCustomAsset";
20 
21  [SerializeField, Tooltip("Optional: Overrides default project directory")]
22  protected Jit<string> selectedPathInProjectView = Jit<string>.Instance(getProjectFolder);
23  private static readonly Func<bool, string> getProjectFolder = _ => AssetDb.ProjectFolder();
24 
25  protected void CreateAssets(string assetName, string assetType, string basePath) {
26  name = assetName;
27  type = assetType;
28  SetDestination(basePath);
29  sources.Clear();
30  ProcessAllFiles(@"cs|txt");
31  AssetDatabase.ImportAsset(
32  Path.GetDirectoryName(destination)
33  , ImportAssetOptions.ForceUpdate | ImportAssetOptions.ForceSynchronousImport |
34  ImportAssetOptions.ImportRecursive);
35 
36  if (sources.Count > 0) {
37  foreach (string source in sources) {
38  var asset = AssetDb.Load<MonoScript>(source);
39  AssetDb.Labels(asset, Label);
40  }
41  Debug.Log($" Please wait while compiling scripts in `{destination}`");
42  }
43  }
44 
45  protected virtual void ProcessAllFiles(string textAssetTypes) {
46  string[] guids = AssetDatabase.FindAssets("", new[] {TemplatePath()});
47  for (int i = 0; i < guids.Length; i++) guids[i] = AssetDatabase.GUIDToAssetPath(guids[i]);
48  ProcessFiles(textAssetTypes, guids);
49  }
50 
51  protected void ProcessFiles(string textAssetTypes, params string[] files) {
52  Regex textAssetTypesRegex = new Regex($@"\.({textAssetTypes})$");
53  using (var template = Template.Instance) {
54  for (int i = 0; i < files.Length; i++) {
55  if (File.Exists(files[i])) {
56  var fileName = Path.GetFileName(files[i]) ?? "";
57  var filePath = fileName.StartsWith(name) ? $"{destination}/{fileName}" : $"{destination}/{name}{fileName}";
58  if (textAssetTypesRegex.IsMatch(files[i])) {
59  if (File.Exists(filePath) && (filePath != files[i]))
60  Fatal($"{filePath} already exists. Select a different name or directory");
61  var text = FillTemplate(template, File.ReadAllText(files[i]));
62  if (files[i].EndsWith(".cs") && text.Contains(" [CreateAssetMenu(")) sources.Add(filePath);
63  File.WriteAllText(filePath, text);
64  } else {
65  if (File.Exists(filePath)) Fatal($"{filePath} already exists. Select a different name or directory");
66  File.Copy(files[i], filePath);
67  }
68  }
69  }
70  }
71  }
72 
73  protected virtual string FillTemplate(Template template, string text) => template.From(text).Result();
74 
75  protected virtual string TemplatePath() => throw new NotImplementedException();
76 
77  protected string AskForDestinationPath(string basePath) {
78  destination = EditorUtility.SaveFilePanel($"Location for your new asset", basePath, "", "");
79  name = Path.GetFileNameWithoutExtension(destination) ?? "UNKNOWN";
80  return destination;
81  }
82 
83  private string SetDestination(string path) {
84  if (!path.EndsWith(name)) path = $"{path}/{name}";
85  if (path.Contains("Assets/Askowl/")) path = path.Substring(path.IndexOf("Assets/", StringComparison.Ordinal));
86  AssetDb.Instance.CreateFolders(path);
87  return destination = path;
88  }
89 
90  protected void Fatal(string msg) => throw new Exception(msg);
91 
92  protected string[] ToDefinitions(string text) => csRegex.Split(text);
93 
94  protected string ToTuple(string fields) {
95  var pairs = ToDefinitions(fields);
96  if (pairs.Length == 0) return null;
97  if (pairs.Length == 1) return pairs[0];
98 
99  if ((pairs.Length < 4) || ((pairs.Length % 2) != 0))
100  throw new Exception($"'{fields}' must be single type or pairs of (type, name)");
101 
102  builder.Clear().Append("(");
103  builder.Append($"{pairs[0]} {pairs[1]}");
104  for (int i = 2; i < pairs.Length; i += 2) builder.Append($",{pairs[i]} {pairs[i + 1]}");
105  return builder.Append(")").ToString();
106  }
107  private readonly StringBuilder builder = new StringBuilder();
108  private static readonly Regex csRegex = new Regex(@"\s*;\s*|\s*,\s*|\s+", RegexOptions.Singleline);
109 
110  [CustomEditor(typeof(AssetWizard), true)] public class AssetWizardEditor : Editor {
111  public override void OnInspectorGUI() {
112  GUI.SetNextControlName("FirstWizardField");
113  if (GUILayout.Button("Clear")) {
114  ((AssetWizard) target).Clear();
115  GUI.FocusControl(null);
116  }
117  serializedObject.Update();
118  DrawDefaultInspector();
119  if (GUILayout.Button("Create")) ((AssetWizard) target).Create();
120  serializedObject.ApplyModifiedProperties();
121  }
122  }
123  public virtual void Create() => throw new NotImplementedException();
124  public virtual void Clear() => throw new NotImplementedException();
125  }
126 }
//#TBD#//
Definition: Manager.cs:8