2 using System.Collections.Generic;
13 private readonly Dictionary<string, (SerializedObject serializedAsset, string path)> assets =
14 new Dictionary<string, (SerializedObject, string)>();
15 private readonly Dictionary<string, bool> existingAssets =
new Dictionary<string, bool>();
17 public static AssetEditor Instance => Cache<AssetEditor>.Instance;
19 public AssetEditor Add(
string assetName,
string nameSpace,
string path) {
20 var qualifiedName =
string.IsNullOrWhiteSpace(nameSpace) ? assetName : $
"{nameSpace}.{assetName}";
21 Type assetType = ScriptableType(qualifiedName);
22 if (assetType ==
default)
throw new Exception($
"No asset '{qualifiedName}' found to add");
23 return Add(assetName, assetType, path);
26 public AssetEditor Add(
string assetName, Type assetType,
string path) {
27 if (assetType ==
default)
throw new Exception($
"No asset '{assetName}' found to add");
28 if (assetType.IsSubclassOf(typeof(ScriptableObject))) {
29 var scriptableObject = ScriptableObject.CreateInstance(assetType);
30 assets[assetName] = (
new SerializedObject(scriptableObject), path);
31 }
else if (assetType.IsSubclassOf(typeof(MonoBehaviour))) {
32 GetPrefabMonoBehaviour(assetName, assetType, path);
33 }
else if (assetType.IsSubclassOf(typeof(
Object))) {
34 var asset = Resources.Load(assetName, assetType);
35 if (asset == null)
throw new Exception($
"No resource '{assetName}' of type {assetType.Name}");
36 var serialisedObject =
new SerializedObject(asset);
37 assets[assetName] = (serialisedObject, path);
39 throw new Exception($
"{assetType.Name} is not a MonoBehaviour, ScriptableObject or Resource");
44 public AssetEditor Load(
string assetName,
string nameSpace,
string path) {
45 if (Exists(assetName))
return this;
46 var name = assetName.Contains(
".") ? assetName : $
"{assetName}.asset";
47 var assetType = ScriptableType($
"{nameSpace}.{assetName}");
48 var asset = AssetDb.Load(name, assetType) ?? AssetDatabase.LoadAssetAtPath($
"{path}/{assetName}", assetType);
49 if (asset == null)
throw new Exception($
"No asset '{name}' found to load");
50 existingAssets[assetName] =
true;
51 assets[assetName] = (
new SerializedObject(asset), path);
55 public bool Exists(
string assetName) => assets.ContainsKey(assetName);
57 public SerializedObject SerialisedAsset(
string assetName) {
58 if (!Exists(assetName))
throw new Exception($
"No asset '{assetName}' set in CreateAssetDictionary");
59 return assets[assetName].serializedAsset;
62 public Object Asset(
string assetName) => SerialisedAsset(assetName).targetObject;
64 public string AssetPath(
string assetName) => assets[assetName].path;
66 protected void SetActiveObject(
string assetName) => Selection.activeObject = Asset(assetName);
68 private static Type ScriptableType(
string name) => ScriptableObject.CreateInstance(name)?.GetType();
70 public AssetEditor SetFieldToAssetEditorEntry(
string assetName,
string fieldName,
string assetField) =>
71 SetField(assetName, fieldName, Asset(assetField));
73 public AssetEditor SetField(
string assetName,
string fieldName, SerializedObject fieldValue) =>
74 SetField(assetName, fieldName, fieldValue.targetObject);
76 public AssetEditor SetField(
string assetName,
string fieldName,
string fieldValue) {
77 Field(assetName, fieldName).stringValue = fieldValue;
81 public AssetEditor SetField(
string assetName,
string fieldName,
Object fieldValue) {
82 Field(assetName, fieldName).objectReferenceValue = fieldValue;
86 public SerializedProperty Field(
string assetName,
string fieldName =
"value") {
87 if (!assets.ContainsKey(assetName))
throw new Exception($
"No asset '{assetName}' set in CreateAssetDictionary");
88 fieldName = CamelCase(fieldName);
89 var
property = FindProperty(assetName, fieldName);
90 if (property ==
default) FindProperty(assetName,
char.ToUpper(fieldName[0]) + fieldName.Substring(1));
91 if (property ==
default)
throw new Exception($
"No property '{fieldName}' in '{assetName}'");
95 private string CamelCase(
string name) {
96 name = name.Replace(
" ",
"");
97 if (name.Length == 0)
return "";
98 if (name.Length == 1)
return $
"{char.ToLower(name[0])}";
99 return char.ToLower(name[0]) + name.Substring(1);
103 string assetName,
string fieldName,
string assetField,
int index = 0) =>
104 InsertIntoArrayField(assetName, fieldName, Asset(assetField), index);
107 string assetName,
string fieldName, SerializedObject fieldValue,
int index = 0) =>
108 InsertIntoArrayField(assetName, fieldName, fieldValue.targetObject, index);
110 public AssetEditor InsertIntoArrayField(
string assetName,
string fieldName,
Object fieldValue,
int index = 0) {
111 var serialisedProperty = FindProperty(assetName, fieldName);
112 serialisedProperty.InsertArrayElementAtIndex(index);
113 serialisedProperty.GetArrayElementAtIndex(index).objectReferenceValue = fieldValue;
114 SerialisedAsset(assetName).ApplyModifiedPropertiesWithoutUndo();
118 public void InsertIntoArrayField(SerializedObject asset,
string fieldName,
Object fieldValue,
int index = 0) {
119 var serialisedProperty = FindProperty(asset, fieldName);
120 serialisedProperty.InsertArrayElementAtIndex(index);
121 serialisedProperty.GetArrayElementAtIndex(index).objectReferenceValue = fieldValue;
122 asset.ApplyModifiedPropertiesWithoutUndo();
125 public T FindProperty<T>(
string assetName,
string fieldName =
"value") where T :
class =>
126 FindProperty(assetName, fieldName).exposedReferenceValue as T;
128 private SerializedProperty FindProperty(SerializedObject asset,
string fieldName) {
129 var
property = asset.FindProperty(fieldName);
130 if (property ==
default)
throw new Exception($
"No property '{fieldName}'");
134 private SerializedProperty FindProperty(
string assetName,
string fieldName) {
135 var
property = SerialisedAsset(assetName).FindProperty(fieldName);
136 if (property ==
default)
throw new Exception($
"No property '{fieldName}' in '{assetName}'");
141 var manager = GetCustomAssetManager();
143 foreach (var entry
in assets) {
144 if (entry.Value.serializedAsset.targetObject.GetType().IsSubclassOf(typeof(ScriptableObject))) {
145 if (!existingAssets.ContainsKey(entry.Key))
146 AssetDatabase.CreateAsset(item = entry.Value.serializedAsset.targetObject, entry.Value.path);
147 if (entry.Key.EndsWith(
"Manager"))
148 InsertIntoArrayField(manager,
"managers", entry.Value.serializedAsset.targetObject);
150 entry.Value.serializedAsset.ApplyModifiedPropertiesWithoutUndo();
152 AssetDatabase.SaveAssets();
153 AssetDb.Instance.Select(item).Dispose();
157 private SerializedObject GetCustomAssetManager() =>
158 GetPrefabMonoBehaviour(
"Custom Asset Managers", typeof(
Managers),
"");
160 private SerializedObject GetPrefabMonoBehaviour(
string prefabName, Type monoBehaviour,
string path) {
162 if (gameObject ==
default) {
163 var prefab = Resources.Load(prefabName);
164 if (prefab == null)
throw new Exception($
"No prefab named {prefabName}");
165 gameObject = (
GameObject)
Object.Instantiate(prefab, Vector3.zero, Quaternion.identity);
166 gameObject.name = prefabName;
168 var component = gameObject.GetComponentInChildren(monoBehaviour);
169 if (component ==
default)
throw new Exception($
"No component '{monoBehaviour.Name}' in '{gameObject.name}'1");
170 var serialisedObject =
new SerializedObject(component);
171 assets[prefabName] = (serialisedObject, path);
172 return serialisedObject;
174 public void Dispose() {
176 Cache<AssetEditor>.Dispose(
this);
MonoBehaviour container for all manager custom assets for a game //#TBD#//
CustomAsset that contains a string. Events are triggered every time the string changes ...