com.wallstop-studios.unity-helpers 1.0.0-rc8 → 1.0.1-rc01

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -139,11 +139,14 @@
139
139
  }
140
140
 
141
141
  frameRate = _currentClip.frameRate = EditorGUILayout.FloatField("FrameRate", frameRate);
142
+ DrawGuiLine(height: 5, color: new Color(0f, 0.5f, 1f, 1f));
142
143
  _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
143
144
 
144
145
  // Need a copy because we might be mutating it
145
- foreach (AnimationEventItem item in _state.ToList())
146
+ List<AnimationEventItem> stateCopy = _state.ToList();
147
+ for (int i = 0; i < stateCopy.Count; ++i)
146
148
  {
149
+ AnimationEventItem item = stateCopy[i];
147
150
  AnimationEvent animEvent = item.animationEvent;
148
151
 
149
152
  int frame = Mathf.RoundToInt(animEvent.time * oldFrameRate);
@@ -152,11 +155,15 @@
152
155
  DrawSpritePreview(item);
153
156
 
154
157
  EditorGUI.indentLevel++;
155
-
156
158
  RenderAnimationEventItem(item, frame, frameRate);
157
-
159
+
160
+ if (i != stateCopy.Count - 1)
161
+ {
162
+ DrawGuiLine(height: 3, color: new Color(0f, 1f, 0.3f, 1f));
163
+ EditorGUILayout.Space();
164
+ }
165
+
158
166
  EditorGUI.indentLevel--;
159
- EditorGUILayout.Space();
160
167
  }
161
168
 
162
169
  EditorGUILayout.EndScrollView();
@@ -641,7 +648,7 @@
641
648
  private bool TryFindSpriteForEvent(AnimationEventItem item, out Sprite sprite)
642
649
  {
643
650
  sprite = null;
644
- foreach (ObjectReferenceKeyframe keyFrame in _referenceCurve)
651
+ foreach (ObjectReferenceKeyframe keyFrame in _referenceCurve ?? Enumerable.Empty<ObjectReferenceKeyframe>())
645
652
  {
646
653
  if (keyFrame.time <= item.animationEvent.time)
647
654
  {
@@ -739,6 +746,15 @@
739
746
  }
740
747
  }
741
748
  }
749
+
750
+ private void DrawGuiLine(int height = 1, Color? color = null)
751
+ {
752
+ Rect rect = EditorGUILayout.GetControlRect(false, height);
753
+ rect.height = height;
754
+ int minusWidth = EditorGUI.indentLevel * 16;
755
+ rect.xMin += minusWidth;
756
+ EditorGUI.DrawRect(rect, color ?? new Color(0.5f, 0.5f, 0.5f, 1f));
757
+ }
742
758
  }
743
759
  #endif
744
760
  }
@@ -18,18 +18,20 @@
18
18
 
19
19
  public static class ChildComponentExtensions
20
20
  {
21
- private static readonly Dictionary<Type, List<FieldInfo>> FieldsByType = new();
21
+ private static readonly Dictionary<Type, FieldInfo[]> FieldsByType = new();
22
22
 
23
23
  public static void AssignChildComponents(this Component component)
24
24
  {
25
25
  Type componentType = component.GetType();
26
- List<FieldInfo> fields = FieldsByType.GetOrAdd(componentType, type =>
27
- {
28
- FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
29
- return fields
30
- .Where(prop => Attribute.IsDefined(prop, typeof(ChildComponentAttribute)))
31
- .ToList();
32
- });
26
+ FieldInfo[] fields = FieldsByType.GetOrAdd(
27
+ componentType, type =>
28
+ {
29
+ FieldInfo[] fields = type.GetFields(
30
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
31
+ return fields
32
+ .Where(prop => Attribute.IsDefined(prop, typeof(ChildComponentAttribute)))
33
+ .ToArray();
34
+ });
33
35
 
34
36
  foreach (FieldInfo field in fields)
35
37
  {
@@ -42,7 +44,7 @@
42
44
  {
43
45
  Component[] childComponents = component.GetComponentsInChildren(childComponentType, true);
44
46
  foundChild = 0 < childComponents.Length;
45
-
47
+
46
48
  Array correctTypedArray = Array.CreateInstance(childComponentType, childComponents.Length);
47
49
  Array.Copy(childComponents, correctTypedArray, childComponents.Length);
48
50
  field.SetValue(component, correctTypedArray);
@@ -51,7 +53,7 @@
51
53
  {
52
54
  childComponentType = fieldType.GenericTypeArguments[0];
53
55
  Type constructedListType = typeof(List<>).MakeGenericType(childComponentType);
54
- IList instance = (IList) Activator.CreateInstance(constructedListType);
56
+ IList instance = (IList)Activator.CreateInstance(constructedListType);
55
57
 
56
58
  foundChild = false;
57
59
  foreach (Component childComponent in component.GetComponentsInChildren(childComponentType, true))
@@ -74,7 +76,10 @@
74
76
 
75
77
  if (!foundChild)
76
78
  {
77
- if (field.GetCustomAttributes(typeof(ChildComponentAttribute), false)[0] is ChildComponentAttribute { optional: false } _)
79
+ if (field.GetCustomAttributes(typeof(ChildComponentAttribute), false)[0] is ChildComponentAttribute
80
+ {
81
+ optional: false
82
+ } _)
78
83
  {
79
84
  component.LogError($"Unable to find child component of type {fieldType}");
80
85
  }
@@ -82,4 +87,4 @@
82
87
  }
83
88
  }
84
89
  }
85
- }
90
+ }
@@ -18,18 +18,20 @@
18
18
 
19
19
  public static class ParentComponentExtensions
20
20
  {
21
- private static readonly Dictionary<Type, List<FieldInfo>> FieldsByType = new();
21
+ private static readonly Dictionary<Type, FieldInfo[]> FieldsByType = new();
22
22
 
23
23
  public static void AssignParentComponents(this Component component)
24
24
  {
25
25
  Type componentType = component.GetType();
26
- List<FieldInfo> fields = FieldsByType.GetOrAdd(componentType, type =>
27
- {
28
- FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
29
- return fields
30
- .Where(prop => Attribute.IsDefined(prop, typeof(ParentComponentAttribute)))
31
- .ToList();
32
- });
26
+ FieldInfo[] fields = FieldsByType.GetOrAdd(
27
+ componentType, type =>
28
+ {
29
+ FieldInfo[] fields = type.GetFields(
30
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
31
+ return fields
32
+ .Where(prop => Attribute.IsDefined(prop, typeof(ParentComponentAttribute)))
33
+ .ToArray();
34
+ });
33
35
 
34
36
  foreach (FieldInfo field in fields)
35
37
  {
@@ -42,7 +44,7 @@
42
44
  {
43
45
  Component[] parentComponents = component.GetComponentsInParent(parentComponentType, true);
44
46
  foundParent = 0 < parentComponents.Length;
45
-
47
+
46
48
  Array correctTypedArray = Array.CreateInstance(parentComponentType, parentComponents.Length);
47
49
  Array.Copy(parentComponents, correctTypedArray, parentComponents.Length);
48
50
  field.SetValue(component, correctTypedArray);
@@ -51,7 +53,7 @@
51
53
  {
52
54
  parentComponentType = fieldType.GenericTypeArguments[0];
53
55
  Type constructedListType = typeof(List<>).MakeGenericType(parentComponentType);
54
- IList instance = (IList) Activator.CreateInstance(constructedListType);
56
+ IList instance = (IList)Activator.CreateInstance(constructedListType);
55
57
 
56
58
  foundParent = false;
57
59
  foreach (Component parentComponent in component.GetComponentsInParent(parentComponentType, true))
@@ -74,7 +76,8 @@
74
76
 
75
77
  if (!foundParent)
76
78
  {
77
- if (field.GetCustomAttributes(typeof(ParentComponentAttribute), false)[0] is ParentComponentAttribute { optional: false } _)
79
+ if (field.GetCustomAttributes(typeof(ParentComponentAttribute), false)[0] is
80
+ ParentComponentAttribute { optional: false } _)
78
81
  {
79
82
  component.LogError($"Unable to find parent component of type {fieldType}");
80
83
  }
@@ -82,4 +85,4 @@
82
85
  }
83
86
  }
84
87
  }
85
- }
88
+ }
@@ -18,18 +18,20 @@
18
18
 
19
19
  public static class SiblingComponentExtensions
20
20
  {
21
- private static readonly Dictionary<Type, List<FieldInfo>> FieldsByType = new();
21
+ private static readonly Dictionary<Type, FieldInfo[]> FieldsByType = new();
22
22
 
23
23
  public static void AssignSiblingComponents(this Component component)
24
24
  {
25
25
  Type componentType = component.GetType();
26
- List<FieldInfo> fields = FieldsByType.GetOrAdd(componentType,
26
+ FieldInfo[] fields = FieldsByType.GetOrAdd(
27
+ componentType,
27
28
  type =>
28
29
  {
29
- FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
30
+ FieldInfo[] fields = type.GetFields(
31
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
30
32
  return fields
31
33
  .Where(prop => Attribute.IsDefined(prop, typeof(SiblingComponentAttribute)))
32
- .ToList();
34
+ .ToArray();
33
35
  });
34
36
 
35
37
  foreach (FieldInfo field in fields)
@@ -52,7 +54,7 @@
52
54
  {
53
55
  siblingComponentType = fieldType.GenericTypeArguments[0];
54
56
  Type constructedListType = typeof(List<>).MakeGenericType(siblingComponentType);
55
- IList instance = (IList) Activator.CreateInstance(constructedListType);
57
+ IList instance = (IList)Activator.CreateInstance(constructedListType);
56
58
 
57
59
  foundSibling = false;
58
60
  foreach (Component siblingComponent in component.GetComponents(siblingComponentType))
@@ -78,7 +80,8 @@
78
80
 
79
81
  if (!foundSibling)
80
82
  {
81
- if (field.GetCustomAttributes(typeof(SiblingComponentAttribute), false)[0] is SiblingComponentAttribute {optional: false} _)
83
+ if (field.GetCustomAttributes(typeof(SiblingComponentAttribute), false)[0] is
84
+ SiblingComponentAttribute { optional: false } _)
82
85
  {
83
86
  component.LogError($"Unable to find sibling component of type {fieldType}");
84
87
  }
@@ -86,4 +89,4 @@
86
89
  }
87
90
  }
88
91
  }
89
- }
92
+ }
@@ -12,21 +12,26 @@
12
12
 
13
13
  [AttributeUsage(AttributeTargets.Field)]
14
14
  [MeansImplicitUse]
15
- public sealed class ValidateAssignmentAttribute : Attribute
16
- {
17
- }
15
+ public sealed class ValidateAssignmentAttribute : Attribute { }
18
16
 
19
17
  public static class ValidateAssignmentExtensions
20
18
  {
21
- private static readonly Dictionary<Type, List<FieldInfo>> FieldsByType = new();
19
+ private static readonly Dictionary<Type, FieldInfo[]> FieldsByType = new();
20
+
21
+ private static FieldInfo[] GetOrAdd(Type objectType)
22
+ {
23
+ return FieldsByType.GetOrAdd(
24
+ objectType, type => type
25
+ .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
26
+ .Where(prop => Attribute.IsDefined(prop, typeof(ValidateAssignmentAttribute)))
27
+ .ToArray());
28
+ }
22
29
 
23
30
  public static void ValidateAssignments(this Object o)
24
31
  {
25
32
  #if UNITY_EDITOR
26
33
  Type objectType = o.GetType();
27
- List<FieldInfo> fields = FieldsByType.GetOrAdd(objectType, type => type
28
- .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
29
- .Where(prop => Attribute.IsDefined(prop, typeof(ValidateAssignmentAttribute))).ToList());
34
+ FieldInfo[] fields = GetOrAdd(objectType);
30
35
 
31
36
  foreach (FieldInfo field in fields)
32
37
  {
@@ -43,24 +48,48 @@
43
48
  public static bool AreAnyAssignmentsInvalid(this Object o)
44
49
  {
45
50
  Type objectType = o.GetType();
46
- List<FieldInfo> fields = FieldsByType.GetOrAdd(objectType, type => type
47
- .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
48
- .Where(prop => Attribute.IsDefined(prop, typeof(ValidateAssignmentAttribute))).ToList());
51
+ FieldInfo[] fields = GetOrAdd(objectType);
49
52
 
50
- return fields.Any(field => IsFieldInvalid(field, o));
53
+ foreach (FieldInfo field in fields)
54
+ {
55
+ if (IsFieldInvalid(field, o))
56
+ {
57
+ return true;
58
+ }
59
+ }
60
+
61
+ return false;
62
+ }
63
+
64
+ private static bool IsInvalid(IEnumerable enumerable)
65
+ {
66
+ IEnumerator enumerator = enumerable.GetEnumerator();
67
+ try
68
+ {
69
+ return !enumerator.MoveNext();
70
+ }
71
+ finally
72
+ {
73
+ if (enumerator is IDisposable disposable)
74
+ {
75
+ disposable.Dispose();
76
+ }
77
+ }
51
78
  }
52
79
 
53
80
  private static bool IsFieldInvalid(FieldInfo field, Object o)
54
81
  {
55
82
  object fieldValue = field.GetValue(o);
83
+
56
84
  return fieldValue switch
57
85
  {
58
- IList list => list.Count <= 0,
59
- ICollection collection => collection.Count <= 0,
60
86
  Object unityObject => !unityObject,
61
87
  string stringValue => string.IsNullOrWhiteSpace(stringValue),
88
+ IList list => list.Count <= 0,
89
+ ICollection collection => collection.Count <= 0,
90
+ IEnumerable enumerable => IsInvalid(enumerable),
62
91
  _ => fieldValue == null
63
92
  };
64
93
  }
65
94
  }
66
- }
95
+ }
@@ -1,10 +1,14 @@
1
1
  namespace UnityHelpers.Core.Extension
2
2
  {
3
+ using System.Collections.Generic;
3
4
  using System.Text;
4
5
  using Serialization;
5
6
 
6
7
  public static class StringExtensions
7
8
  {
9
+ private static readonly HashSet<char> PascalCaseSeparators =
10
+ new() { '_', ' ', '\r', '\n', '\t', '.', '\'', '"' };
11
+
8
12
  public static string Center(this string input, int length)
9
13
  {
10
14
  if (input == null || length <= input.Length)
@@ -17,12 +21,12 @@
17
21
 
18
22
  public static byte[] GetBytes(this string input)
19
23
  {
20
- return System.Text.Encoding.Default.GetBytes(input);
24
+ return Encoding.Default.GetBytes(input);
21
25
  }
22
26
 
23
27
  public static string GetString(this byte[] bytes)
24
28
  {
25
- return System.Text.Encoding.Default.GetString(bytes);
29
+ return Encoding.Default.GetString(bytes);
26
30
  }
27
31
 
28
32
  public static string ToJson<T>(this T value)
@@ -34,29 +38,66 @@
34
38
  {
35
39
  int startIndex = 0;
36
40
  StringBuilder stringBuilder = new();
41
+ bool appendedAnySeparator = false;
37
42
  for (int i = 0; i < value.Length; ++i)
38
43
  {
39
- if (startIndex < i && char.IsLower(value[i - 1]) && char.IsUpper(value[i]))
44
+ while (startIndex < value.Length && PascalCaseSeparators.Contains(value[startIndex]))
45
+ {
46
+ ++startIndex;
47
+ }
48
+
49
+ if (startIndex < i && char.IsLower(value[i - 1]) &&
50
+ (char.IsUpper(value[i]) || PascalCaseSeparators.Contains(value[i])))
40
51
  {
41
52
  _ = stringBuilder.Append(char.ToUpper(value[startIndex]));
42
53
  if (1 < i - startIndex)
43
54
  {
44
- _ = stringBuilder.Append(value.Substring(startIndex + 1, i - 1 - startIndex).ToLower());
55
+ for (int j = startIndex + 1; j < i; ++j)
56
+ {
57
+ char current = value[j];
58
+ if (PascalCaseSeparators.Contains(current))
59
+ {
60
+ continue;
61
+ }
62
+
63
+ _ = stringBuilder.Append(char.ToLower(current));
64
+ }
65
+ }
66
+
67
+ if (!string.IsNullOrEmpty(separator))
68
+ {
69
+ appendedAnySeparator = true;
70
+ _ = stringBuilder.Append(separator);
45
71
  }
46
72
 
47
- _ = stringBuilder.Append(separator);
48
73
  startIndex = i;
49
74
  continue;
50
75
  }
51
76
 
52
- if (startIndex + 1 < i && char.IsLower(value[i]) && char.IsUpper(value[i - 1]))
77
+ if (startIndex + 1 < i && char.IsLower(value[i]) &&
78
+ (char.IsUpper(value[i - 1]) || PascalCaseSeparators.Contains(value[i - 1])))
53
79
  {
54
80
  _ = stringBuilder.Append(char.ToUpper(value[startIndex]));
55
81
  if (1 < i - 1 - startIndex)
56
82
  {
57
- _ = stringBuilder.Append(value.Substring(startIndex + 1, i - 1 - startIndex).ToLower());
83
+ for (int j = startIndex + 1; j < i; ++j)
84
+ {
85
+ char current = value[j];
86
+ if (PascalCaseSeparators.Contains(current))
87
+ {
88
+ continue;
89
+ }
90
+
91
+ _ = stringBuilder.Append(char.ToLower(current));
92
+ }
93
+ }
94
+
95
+ if (!string.IsNullOrEmpty(separator))
96
+ {
97
+ appendedAnySeparator = true;
98
+ _ = stringBuilder.Append(separator);
58
99
  }
59
- _ = stringBuilder.Append(separator);
100
+
60
101
  startIndex = i - 1;
61
102
  }
62
103
  }
@@ -66,11 +107,25 @@
66
107
  _ = stringBuilder.Append(char.ToUpper(value[startIndex]));
67
108
  if (startIndex + 1 < value.Length)
68
109
  {
69
- _ = stringBuilder.Append(value.Substring(startIndex + 1, value.Length - 1 - startIndex).ToLower());
110
+ for (int j = startIndex + 1; j < value.Length; ++j)
111
+ {
112
+ char current = value[j];
113
+ if (PascalCaseSeparators.Contains(current))
114
+ {
115
+ continue;
116
+ }
117
+
118
+ _ = stringBuilder.Append(char.ToLower(current));
119
+ }
70
120
  }
71
121
  }
122
+ else if (appendedAnySeparator && !string.IsNullOrEmpty(separator) &&
123
+ separator.Length <= stringBuilder.Length)
124
+ {
125
+ stringBuilder.Remove(stringBuilder.Length - separator.Length, separator.Length);
126
+ }
72
127
 
73
128
  return stringBuilder.ToString();
74
129
  }
75
130
  }
76
- }
131
+ }