-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathResourceReference.cs
More file actions
193 lines (162 loc) · 5.26 KB
/
ResourceReference.cs
File metadata and controls
193 lines (162 loc) · 5.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
using System;
using System.IO;
using System.Text.RegularExpressions;
using UnityEngine;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace Jackey.Utilities.Unity {
/// <summary>
/// Save a reference to an asset located within a "Resources/" folder
/// </summary>
[Serializable]
public struct ResourceReference<T> : ISerializationCallbackReceiver, IEquatable<ResourceReference<T>> where T : Object {
#if UNITY_EDITOR
[SerializeField] private string m_assetGuid;
#endif
[SerializeField] private string m_resourcePath;
/// <summary>
/// The path to the referenced asset following its 'Resources/' folder
/// </summary>
public string ResourcePath {
get {
#if UNITY_EDITOR
return GetResourcePath();
#else
return m_resourcePath;
#endif
}
}
/// <summary>
/// Is the reference valid?
/// </summary>
public bool IsValid {
get {
#if UNITY_EDITOR
return !string.IsNullOrEmpty(GetResourcePath());
#else
return !string.IsNullOrEmpty(m_resourcePath);
#endif
}
}
#region Serialization
public void OnBeforeSerialize() {
#if UNITY_EDITOR
m_resourcePath = GetResourcePath();
#endif
}
public void OnAfterDeserialize() { }
#endregion
/// <summary>
/// Load the referenced asset
/// </summary>
/// <returns>Returns the loaded asset</returns>
public T Load() {
if (!IsValid) {
Debug.LogWarning("Unable to load resource. Reference is invalid");
return null;
}
#if UNITY_EDITOR
return Resources.Load<T>(GetResourcePath());
#else
return Resources.Load<T>(m_resourcePath);
#endif
}
/// <summary>
/// Begin asynchronous loading of the referenced asset
/// </summary>
/// <returns>Returns the asset load request</returns>
public ResourceRequest LoadAsync() {
if (!IsValid) {
Debug.LogWarning("Unable to load resource. Reference is invalid");
return null;
}
#if UNITY_EDITOR
return Resources.LoadAsync<T>(GetResourcePath());
#else
return Resources.LoadAsync<T>(m_resourcePath);
#endif
}
#if UNITY_EDITOR
/// <summary>
/// Create a new resource reference. This method can only ever be called in the Editor!
/// </summary>
/// <param name="asset">The asset to create a reference to</param>
/// <returns>A reference to the asset via its resource path. Note that the reference may be invalid if the asset is not in a Resources/ folder</returns>
public static ResourceReference<T> Create(T asset) {
return new ResourceReference<T>() {
m_assetGuid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(asset)),
};
}
#endif
#if UNITY_EDITOR
private string GetResourcePath() {
string assetPath;
if (string.IsNullOrEmpty(m_assetGuid) || string.IsNullOrEmpty(assetPath = AssetDatabase.GUIDToAssetPath(m_assetGuid))) {
return string.Empty;
}
string directoryName = Path.GetDirectoryName(assetPath);
string fileName = Path.GetFileNameWithoutExtension(assetPath);
string assetPathWithoutExtension = Path.Combine(directoryName, fileName);
assetPathWithoutExtension = assetPathWithoutExtension.Replace('\\', '/');
return Regex.Match(assetPathWithoutExtension, "(?<=/Resources/).+$").Value;
}
#endif
public override string ToString() {
#if UNITY_EDITOR
return GetResourcePath();
#else
return m_resourcePath;
#endif
}
public static bool operator ==(ResourceReference<T> lhs, ResourceReference<T> rhs) => lhs.Equals(rhs);
public static bool operator !=(ResourceReference<T> lhs, ResourceReference<T> rhs) => !lhs.Equals(rhs);
public override bool Equals(object obj) => obj is ResourceReference<T> other && Equals(other);
public bool Equals(ResourceReference<T> other) {
#if UNITY_EDITOR
return m_assetGuid == other.m_assetGuid;
#else
return m_resourcePath == other.m_resourcePath;
#endif
}
public override int GetHashCode() {
#if UNITY_EDITOR
return GetResourcePath().GetHashCode();
#else
return m_resourcePath.GetHashCode();
#endif
}
}
#if UNITY_EDITOR
namespace PropertyDrawers {
[CustomPropertyDrawer(typeof(ResourceReference<>))]
public class ResourceReferencePropertyDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
Color defaultGUIBackgroundColor = GUI.backgroundColor;
label = EditorGUI.BeginProperty(position, label, property);
SerializedProperty guidProperty = property.FindPropertyRelative("m_assetGuid");
string assetGuid = guidProperty.stringValue;
Type assetType = fieldInfo.FieldType.GenericTypeArguments[0];
Object asset = null;
if (!string.IsNullOrEmpty(assetGuid)) {
string assetPath = AssetDatabase.GUIDToAssetPath(assetGuid);
asset = AssetDatabase.LoadAssetAtPath(assetPath, assetType);
if (!Regex.IsMatch(assetPath, "(?<=/Resources/).+$")) {
GUI.backgroundColor = Color.red;
label.tooltip = "Asset is not located within a \"Resources/\" folder";
}
}
EditorGUI.BeginChangeCheck();
Object fieldValue = EditorGUI.ObjectField(position, label, asset, assetType, false);
if (EditorGUI.EndChangeCheck()) {
string assetPath = AssetDatabase.GetAssetPath(fieldValue);
guidProperty.stringValue = AssetDatabase.GUIDFromAssetPath(assetPath).ToString();
}
EditorGUI.EndProperty();
GUI.backgroundColor = defaultGUIBackgroundColor;
}
}
}
#endif
}