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.
- package/Editor/AnimationEventEditor.cs +21 -5
- package/Runtime/Core/Attributes/ChildComponentAttribute.cs +17 -12
- package/Runtime/Core/Attributes/ParentComponent.cs +15 -12
- package/Runtime/Core/Attributes/SiblingComponentAttribute.cs +10 -7
- package/Runtime/Core/Attributes/ValidateAssignmentAttribute.cs +43 -14
- package/Runtime/Core/Extension/StringExtensions.cs +65 -10
- package/Runtime/Core/Helper/Helpers.cs +107 -51
- package/Runtime/Utils/SpriteRendererMetadata.cs +273 -0
- package/Runtime/Utils/SpriteRendererMetadata.cs.meta +3 -0
- package/Runtime/Utils/SpriteRendererSyncer.cs +98 -0
- package/Runtime/Utils/SpriteRendererSyncer.cs.meta +3 -0
- package/Tests/Runtime/Extensions/StringExtensionTests.cs +31 -0
- package/Tests/Runtime/Extensions/StringExtensionTests.cs.meta +3 -0
- package/Tests/Runtime/Extensions.meta +3 -0
- package/Tests/Runtime/Random/RandomTestBase.cs +16 -8
- package/Tests/Runtime/Utils/SpriteRendererMetadataTests.cs +395 -0
- package/Tests/Runtime/Utils/SpriteRendererMetadataTests.cs.meta +3 -0
- package/Tests/Runtime/Utils.meta +3 -0
- package/package.json +2 -1
- package/Runtime/Core/Attributes/AutomaticallyFindAttribute.cs +0 -43
- package/Runtime/Core/Attributes/AutomaticallyFindAttribute.cs.meta +0 -11
|
@@ -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
|
-
|
|
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,
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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)
|
|
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
|
|
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,
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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)
|
|
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
|
|
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,
|
|
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
|
-
|
|
26
|
+
FieldInfo[] fields = FieldsByType.GetOrAdd(
|
|
27
|
+
componentType,
|
|
27
28
|
type =>
|
|
28
29
|
{
|
|
29
|
-
FieldInfo[] fields = type.GetFields(
|
|
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
|
-
.
|
|
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)
|
|
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
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
24
|
+
return Encoding.Default.GetBytes(input);
|
|
21
25
|
}
|
|
22
26
|
|
|
23
27
|
public static string GetString(this byte[] bytes)
|
|
24
28
|
{
|
|
25
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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]) &&
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|