com.wallstop-studios.unity-helpers 2.0.0-rc68 → 2.0.0-rc70
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/AnimationCopier.cs +875 -93
- package/Editor/AnimationCreator.cs +840 -137
- package/Editor/AnimationEventEditor.cs +4 -4
- package/Editor/AnimatorControllerCopier.cs +3 -3
- package/Editor/Extensions/UnityExtensions.cs +26 -0
- package/Editor/Extensions/UnityExtensions.cs.meta +3 -0
- package/Editor/Extensions.meta +3 -0
- package/Editor/FitTextureSizeWindow.cs +371 -0
- package/Editor/PrefabChecker.cs +716 -0
- package/Editor/SpriteAtlasGenerator.cs +598 -0
- package/Editor/SpriteAtlasGenerator.cs.meta +3 -0
- package/Editor/SpriteCropper.cs +407 -0
- package/Editor/SpriteCropper.cs.meta +3 -0
- package/Editor/SpriteSettingsApplier.cs +756 -92
- package/Editor/TextureResizerWizard.cs +3 -3
- package/Editor/TextureSettingsApplier.cs +9 -9
- package/Editor/WShowIfPropertyDrawer.cs +2 -2
- package/Runtime/Core/Attributes/EnumDisplayNameAttribute.cs +15 -0
- package/Runtime/Core/Attributes/EnumDisplayNameAttribute.cs.meta +3 -0
- package/Runtime/Core/Attributes/ValidateAssignmentAttribute.cs +1 -1
- package/Runtime/Core/Extension/EnumExtensions.cs +176 -1
- package/Runtime/Core/Extension/UnityExtensions.cs +1 -1
- package/Runtime/Core/Helper/Partials/LogHelpers.cs +1 -1
- package/Runtime/Core/Helper/Partials/MathHelpers.cs +1 -1
- package/Runtime/Core/Helper/Partials/ObjectHelpers.cs +3 -4
- package/Runtime/Tags/Attribute.cs +205 -0
- package/Runtime/Tags/Attribute.cs.meta +3 -0
- package/Runtime/Tags/AttributeEffect.cs +276 -0
- package/Runtime/Tags/AttributeEffect.cs.meta +3 -0
- package/Runtime/Tags/AttributeModification.cs +51 -0
- package/Runtime/Tags/AttributeModification.cs.meta +3 -0
- package/Runtime/Tags/AttributeUtilities.cs +209 -0
- package/Runtime/Tags/AttributeUtilities.cs.meta +3 -0
- package/Runtime/Tags/AttributesComponent.cs +163 -0
- package/Runtime/Tags/AttributesComponent.cs.meta +3 -0
- package/Runtime/Tags/CosmeticEffectComponent.cs +50 -0
- package/Runtime/Tags/CosmeticEffectComponent.cs.meta +3 -0
- package/Runtime/Tags/CosmeticEffectData.cs +63 -0
- package/Runtime/Tags/CosmeticEffectData.cs.meta +3 -0
- package/Runtime/Tags/EffectHandle.cs +63 -0
- package/Runtime/Tags/EffectHandle.cs.meta +3 -0
- package/Runtime/Tags/EffectHandler.cs +380 -0
- package/Runtime/Tags/EffectHandler.cs.meta +3 -0
- package/Runtime/Tags/ModificationAction.cs +9 -0
- package/Runtime/Tags/ModificationAction.cs.meta +3 -0
- package/Runtime/Tags/ModifierDurationType.cs +13 -0
- package/Runtime/Tags/ModifierDurationType.cs.meta +3 -0
- package/Runtime/{Utils → Tags}/TagHandler.cs +42 -5
- package/Runtime/Tags.meta +3 -0
- package/Tests/Runtime/DataStructures/BalancedKDTreeTests.cs +1 -1
- package/Tests/Runtime/DataStructures/CyclicBufferTests.cs +1 -1
- package/Tests/Runtime/DataStructures/QuadTreeTests.cs +1 -1
- package/Tests/Runtime/DataStructures/SpatialTreeTests.cs +1 -1
- package/Tests/Runtime/DataStructures/UnbalancedKDTreeTests.cs +1 -1
- package/Tests/Runtime/Extensions/DictionaryExtensionTests.cs +1 -1
- package/Tests/Runtime/Extensions/EnumExtensionTests.cs +1 -1
- package/Tests/Runtime/Extensions/IListExtensionTests.cs +1 -1
- package/Tests/Runtime/Extensions/LoggingExtensionTests.cs +1 -1
- package/Tests/Runtime/Extensions/RandomExtensionTests.cs +1 -1
- package/Tests/Runtime/Extensions/StringExtensionTests.cs +1 -1
- package/Tests/Runtime/Helper/ObjectHelperTests.cs +1 -0
- package/Tests/Runtime/Helper/WallMathTests.cs +1 -1
- package/Tests/Runtime/Performance/KDTreePerformanceTests.cs +1 -1
- package/Tests/Runtime/Performance/QuadTreePerformanceTests.cs +1 -1
- package/Tests/Runtime/Performance/SpatialTreePerformanceTest.cs +1 -1
- package/Tests/Runtime/Performance/UnbalancedKDTreeTests.cs +1 -1
- package/Tests/Runtime/Random/RandomTestBase.cs +2 -2
- package/Tests/Runtime/Serialization/JsonSerializationTest.cs +1 -1
- package/package.json +1 -1
- package/Editor/FitTextureSizeWizard.cs +0 -147
- package/Editor/PrefabCheckWizard.cs +0 -167
- /package/Editor/{FitTextureSizeWizard.cs.meta → FitTextureSizeWindow.cs.meta} +0 -0
- /package/Editor/{PrefabCheckWizard.cs.meta → PrefabChecker.cs.meta} +0 -0
- /package/Runtime/{Utils → Tags}/TagHandler.cs.meta +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
namespace WallstopStudios.UnityHelpers.Tags
|
|
2
|
+
{
|
|
3
|
+
using System.Collections.Generic;
|
|
4
|
+
using Core.Extension;
|
|
5
|
+
using UnityEngine;
|
|
6
|
+
|
|
7
|
+
[RequireComponent(typeof(CosmeticEffectData))]
|
|
8
|
+
public abstract class CosmeticEffectComponent : MonoBehaviour
|
|
9
|
+
{
|
|
10
|
+
public virtual bool RequiresInstance => false;
|
|
11
|
+
|
|
12
|
+
public virtual bool CleansUpSelf => false;
|
|
13
|
+
|
|
14
|
+
protected readonly List<GameObject> _appliedTargets = new();
|
|
15
|
+
|
|
16
|
+
protected virtual void OnDestroy()
|
|
17
|
+
{
|
|
18
|
+
if (_appliedTargets.Count <= 0)
|
|
19
|
+
{
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
foreach (GameObject appliedTarget in _appliedTargets.ToArray())
|
|
24
|
+
{
|
|
25
|
+
if (appliedTarget == null)
|
|
26
|
+
{
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
OnRemoveEffect(appliedTarget);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Executed when the associated effect is applied.
|
|
35
|
+
public virtual void OnApplyEffect(GameObject target)
|
|
36
|
+
{
|
|
37
|
+
_appliedTargets.Add(target);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Executed when the associated effect is non-instant and removed.
|
|
41
|
+
public virtual void OnRemoveEffect(GameObject target)
|
|
42
|
+
{
|
|
43
|
+
int appliedIndex = _appliedTargets.IndexOf(target);
|
|
44
|
+
if (0 <= appliedIndex)
|
|
45
|
+
{
|
|
46
|
+
_appliedTargets.RemoveAtSwapBack(appliedIndex);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
namespace WallstopStudios.UnityHelpers.Tags
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using System.Collections.Generic;
|
|
5
|
+
using System.Linq;
|
|
6
|
+
using Core.Helper;
|
|
7
|
+
using UnityEngine;
|
|
8
|
+
|
|
9
|
+
[DisallowMultipleComponent]
|
|
10
|
+
public sealed class CosmeticEffectData : MonoBehaviour, IEquatable<CosmeticEffectData>
|
|
11
|
+
{
|
|
12
|
+
// Is an instanced version of this gameObject created when applied.
|
|
13
|
+
public bool RequiresInstancing =>
|
|
14
|
+
_cosmetics.Value.Any(cosmeticEffect => cosmeticEffect.RequiresInstance);
|
|
15
|
+
|
|
16
|
+
[NonSerialized]
|
|
17
|
+
private readonly Lazy<CosmeticEffectComponent[]> _cosmetics;
|
|
18
|
+
|
|
19
|
+
[NonSerialized]
|
|
20
|
+
private readonly Lazy<HashSet<Type>> _cosmeticTypes;
|
|
21
|
+
|
|
22
|
+
public CosmeticEffectData()
|
|
23
|
+
{
|
|
24
|
+
_cosmetics = new Lazy<CosmeticEffectComponent[]>(
|
|
25
|
+
GetComponents<CosmeticEffectComponent>
|
|
26
|
+
);
|
|
27
|
+
_cosmeticTypes = new Lazy<HashSet<Type>>(
|
|
28
|
+
() => _cosmetics.Value.Select(cosmetic => cosmetic.GetType()).ToHashSet()
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public override bool Equals(object other)
|
|
33
|
+
{
|
|
34
|
+
return other is CosmeticEffectData cosmeticEffectData && Equals(cosmeticEffectData);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public bool Equals(CosmeticEffectData other)
|
|
38
|
+
{
|
|
39
|
+
if (ReferenceEquals(this, other))
|
|
40
|
+
{
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (other == null || GetHashCode() != other.GetHashCode())
|
|
45
|
+
{
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
bool componentTypeEquals = _cosmeticTypes.Value.SetEquals(other._cosmeticTypes.Value);
|
|
50
|
+
if (!componentTypeEquals)
|
|
51
|
+
{
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return Helpers.NameEquals(this, other);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public override int GetHashCode()
|
|
59
|
+
{
|
|
60
|
+
return _cosmeticTypes.Value.Count.GetHashCode();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
namespace WallstopStudios.UnityHelpers.Tags
|
|
2
|
+
{
|
|
3
|
+
using System;
|
|
4
|
+
using Core.DataStructure.Adapters;
|
|
5
|
+
using Core.Extension;
|
|
6
|
+
|
|
7
|
+
[Serializable]
|
|
8
|
+
public readonly struct EffectHandle
|
|
9
|
+
: IEquatable<EffectHandle>,
|
|
10
|
+
IComparable<EffectHandle>,
|
|
11
|
+
IComparable
|
|
12
|
+
{
|
|
13
|
+
public readonly AttributeEffect effect;
|
|
14
|
+
|
|
15
|
+
public readonly KGuid id;
|
|
16
|
+
|
|
17
|
+
public static EffectHandle CreateInstance(AttributeEffect effect)
|
|
18
|
+
{
|
|
19
|
+
return new EffectHandle(Guid.NewGuid(), effect);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
private EffectHandle(KGuid id, AttributeEffect effect)
|
|
23
|
+
{
|
|
24
|
+
this.id = id;
|
|
25
|
+
this.effect = effect;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public int CompareTo(EffectHandle other)
|
|
29
|
+
{
|
|
30
|
+
return id.CompareTo(other.id);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public int CompareTo(object obj)
|
|
34
|
+
{
|
|
35
|
+
if (obj is EffectHandle other)
|
|
36
|
+
{
|
|
37
|
+
return CompareTo(other);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return -1;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public override bool Equals(object obj)
|
|
44
|
+
{
|
|
45
|
+
return obj is EffectHandle other && Equals(other);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public bool Equals(EffectHandle other)
|
|
49
|
+
{
|
|
50
|
+
return id == other.id;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public override int GetHashCode()
|
|
54
|
+
{
|
|
55
|
+
return id.GetHashCode();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public override string ToString()
|
|
59
|
+
{
|
|
60
|
+
return this.ToJson();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
namespace WallstopStudios.UnityHelpers.Tags
|
|
2
|
+
{
|
|
3
|
+
using System.Collections.Generic;
|
|
4
|
+
using System.Linq;
|
|
5
|
+
using Core.Attributes;
|
|
6
|
+
using Core.DataStructure.Adapters;
|
|
7
|
+
using Core.Extension;
|
|
8
|
+
using Core.Helper;
|
|
9
|
+
using UnityEngine;
|
|
10
|
+
using Utils;
|
|
11
|
+
|
|
12
|
+
[DisallowMultipleComponent]
|
|
13
|
+
[RequireComponent(typeof(TagHandler))]
|
|
14
|
+
public sealed class EffectHandler : MonoBehaviour
|
|
15
|
+
{
|
|
16
|
+
[SiblingComponent()]
|
|
17
|
+
private TagHandler _tagHandler;
|
|
18
|
+
|
|
19
|
+
[SiblingComponent(optional = true)]
|
|
20
|
+
private AttributesComponent[] _attributes;
|
|
21
|
+
|
|
22
|
+
// Stores instanced cosmetic effect data for associated effects.
|
|
23
|
+
private readonly Dictionary<
|
|
24
|
+
EffectHandle,
|
|
25
|
+
List<CosmeticEffectData>
|
|
26
|
+
> _instancedCosmeticEffects = new();
|
|
27
|
+
|
|
28
|
+
// Stores expiration time of duration effects (We store by Id because it's much cheaper to iterate Guids than it is EffectHandles
|
|
29
|
+
private readonly Dictionary<KGuid, float> _effectExpirations = new();
|
|
30
|
+
private readonly Dictionary<KGuid, EffectHandle> _effectHandlesById = new();
|
|
31
|
+
|
|
32
|
+
// Used only to save allocations in Update()
|
|
33
|
+
private readonly List<KGuid> _expiredEffectIds = new();
|
|
34
|
+
private readonly List<EffectHandle> _appliedEffects = new();
|
|
35
|
+
|
|
36
|
+
private bool _initialized;
|
|
37
|
+
|
|
38
|
+
private void Awake()
|
|
39
|
+
{
|
|
40
|
+
this.AssignRelationalComponents();
|
|
41
|
+
_initialized = true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public EffectHandle? ApplyEffect(AttributeEffect effect)
|
|
45
|
+
{
|
|
46
|
+
EffectHandle? maybeHandle = null;
|
|
47
|
+
|
|
48
|
+
if (effect.durationType != ModifierDurationType.Instant)
|
|
49
|
+
{
|
|
50
|
+
if (effect.durationType == ModifierDurationType.Duration)
|
|
51
|
+
{
|
|
52
|
+
foreach (EffectHandle appliedEffect in _appliedEffects)
|
|
53
|
+
{
|
|
54
|
+
if (appliedEffect.effect == null)
|
|
55
|
+
{
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
string serializableName = appliedEffect.effect.name;
|
|
60
|
+
if (string.Equals(effect.name, serializableName))
|
|
61
|
+
{
|
|
62
|
+
maybeHandle = appliedEffect;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
maybeHandle ??= EffectHandle.CreateInstance(effect);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (maybeHandle.HasValue)
|
|
72
|
+
{
|
|
73
|
+
EffectHandle handle = maybeHandle.Value;
|
|
74
|
+
InternalApplyEffect(handle);
|
|
75
|
+
if (
|
|
76
|
+
effect.durationType == ModifierDurationType.Duration
|
|
77
|
+
&& (effect.resetDurationOnReapplication || !_appliedEffects.Contains(handle))
|
|
78
|
+
)
|
|
79
|
+
{
|
|
80
|
+
KGuid handleId = handle.id;
|
|
81
|
+
_effectExpirations[handleId] = Time.time + effect.duration;
|
|
82
|
+
_effectHandlesById[handleId] = handle;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else
|
|
86
|
+
{
|
|
87
|
+
InternalApplyEffect(effect);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return maybeHandle;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public void RemoveEffect(EffectHandle handle)
|
|
94
|
+
{
|
|
95
|
+
InternalRemoveEffect(handle);
|
|
96
|
+
_ = _appliedEffects.Remove(handle);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
public void RemoveAllEffects()
|
|
100
|
+
{
|
|
101
|
+
foreach (EffectHandle handle in _appliedEffects.ToArray())
|
|
102
|
+
{
|
|
103
|
+
InternalRemoveEffect(handle);
|
|
104
|
+
}
|
|
105
|
+
_appliedEffects.Clear();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private void InternalRemoveEffect(EffectHandle handle)
|
|
109
|
+
{
|
|
110
|
+
foreach (AttributesComponent attributesComponent in _attributes)
|
|
111
|
+
{
|
|
112
|
+
attributesComponent.ForceRemoveAttributeModifications(handle);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!_initialized && _tagHandler == null)
|
|
116
|
+
{
|
|
117
|
+
this.AssignRelationalComponents();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Then, tags are removed (so cosmetic components can look up if any tags are still applied)
|
|
121
|
+
if (_tagHandler != null)
|
|
122
|
+
{
|
|
123
|
+
_ = _tagHandler.ForceRemoveTags(handle);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
KGuid handleId = handle.id;
|
|
127
|
+
_ = _effectExpirations.Remove(handleId);
|
|
128
|
+
_ = _effectHandlesById.Remove(handleId);
|
|
129
|
+
InternalRemoveCosmeticEffects(handle);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
private void InternalApplyEffect(EffectHandle handle)
|
|
133
|
+
{
|
|
134
|
+
bool exists = _appliedEffects.Contains(handle);
|
|
135
|
+
if (!exists)
|
|
136
|
+
{
|
|
137
|
+
_appliedEffects.Add(handle);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
AttributeEffect effect = handle.effect;
|
|
141
|
+
if (effect.durationType == ModifierDurationType.Duration)
|
|
142
|
+
{
|
|
143
|
+
if (effect.resetDurationOnReapplication || !exists)
|
|
144
|
+
{
|
|
145
|
+
KGuid handleId = handle.id;
|
|
146
|
+
_effectExpirations[handleId] = Time.time + effect.duration;
|
|
147
|
+
_effectHandlesById[handleId] = handle;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (!_initialized && _tagHandler == null)
|
|
152
|
+
{
|
|
153
|
+
this.AssignRelationalComponents();
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (_tagHandler != null && effect.effectTags is { Count: > 0 })
|
|
157
|
+
{
|
|
158
|
+
_tagHandler.ForceApplyTags(handle);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (effect.cosmeticEffects is { Count: > 0 })
|
|
162
|
+
{
|
|
163
|
+
InternalApplyCosmeticEffects(handle);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (effect.modifications is { Count: > 0 })
|
|
167
|
+
{
|
|
168
|
+
foreach (AttributesComponent attributesComponent in _attributes)
|
|
169
|
+
{
|
|
170
|
+
attributesComponent.ForceApplyAttributeModifications(handle);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private void InternalApplyEffect(AttributeEffect effect)
|
|
176
|
+
{
|
|
177
|
+
if (!_initialized && _tagHandler == null)
|
|
178
|
+
{
|
|
179
|
+
this.AssignRelationalComponents();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (_tagHandler != null && effect.effectTags is { Count: > 0 })
|
|
183
|
+
{
|
|
184
|
+
_tagHandler.ForceApplyEffect(effect);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (effect.cosmeticEffects is { Count: > 0 })
|
|
188
|
+
{
|
|
189
|
+
InternalApplyCosmeticEffects(effect);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (effect.modifications is { Count: > 0 })
|
|
193
|
+
{
|
|
194
|
+
foreach (AttributesComponent attributesComponent in _attributes)
|
|
195
|
+
{
|
|
196
|
+
attributesComponent.ForceApplyAttributeModifications(effect);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
private void InternalApplyCosmeticEffects(EffectHandle handle)
|
|
202
|
+
{
|
|
203
|
+
if (_instancedCosmeticEffects.ContainsKey(handle))
|
|
204
|
+
{
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
List<CosmeticEffectData> instancedCosmeticData = null;
|
|
209
|
+
|
|
210
|
+
AttributeEffect effect = handle.effect;
|
|
211
|
+
|
|
212
|
+
foreach (CosmeticEffectData cosmeticEffectData in effect.cosmeticEffects)
|
|
213
|
+
{
|
|
214
|
+
CosmeticEffectData cosmeticEffect = cosmeticEffectData;
|
|
215
|
+
if (cosmeticEffect == null)
|
|
216
|
+
{
|
|
217
|
+
this.LogError(
|
|
218
|
+
$"CosmeticEffectData is null for effect {effect:json}, cannot determine instancing scheme."
|
|
219
|
+
);
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (cosmeticEffectData.RequiresInstancing)
|
|
224
|
+
{
|
|
225
|
+
cosmeticEffect = Instantiate(
|
|
226
|
+
cosmeticEffectData,
|
|
227
|
+
transform.position,
|
|
228
|
+
Quaternion.identity
|
|
229
|
+
);
|
|
230
|
+
cosmeticEffect.transform.SetParent(transform, true);
|
|
231
|
+
(instancedCosmeticData ??= new List<CosmeticEffectData>()).Add(cosmeticEffect);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
Buffers<CosmeticEffectComponent>.List.Clear();
|
|
235
|
+
cosmeticEffect.GetComponents(Buffers<CosmeticEffectComponent>.List);
|
|
236
|
+
foreach (
|
|
237
|
+
CosmeticEffectComponent cosmeticComponent in Buffers<CosmeticEffectComponent>.List
|
|
238
|
+
)
|
|
239
|
+
{
|
|
240
|
+
cosmeticComponent.OnApplyEffect(gameObject);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (instancedCosmeticData != null)
|
|
245
|
+
{
|
|
246
|
+
_instancedCosmeticEffects.Add(handle, instancedCosmeticData);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
private void InternalApplyCosmeticEffects(AttributeEffect attributeEffect)
|
|
251
|
+
{
|
|
252
|
+
foreach (CosmeticEffectData cosmeticEffectData in attributeEffect.cosmeticEffects)
|
|
253
|
+
{
|
|
254
|
+
CosmeticEffectData cosmeticEffect = cosmeticEffectData;
|
|
255
|
+
if (cosmeticEffect == null)
|
|
256
|
+
{
|
|
257
|
+
this.LogError(
|
|
258
|
+
$"CosmeticEffectData is null for effect {attributeEffect:json}, cannot determine instancing scheme."
|
|
259
|
+
);
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (cosmeticEffectData.RequiresInstancing)
|
|
264
|
+
{
|
|
265
|
+
this.LogError(
|
|
266
|
+
$"CosmeticEffectData requires instancing, but can't instance (no handle)."
|
|
267
|
+
);
|
|
268
|
+
continue;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
Buffers<CosmeticEffectComponent>.List.Clear();
|
|
272
|
+
cosmeticEffect.GetComponents(Buffers<CosmeticEffectComponent>.List);
|
|
273
|
+
foreach (
|
|
274
|
+
CosmeticEffectComponent cosmeticComponent in Buffers<CosmeticEffectComponent>.List
|
|
275
|
+
)
|
|
276
|
+
{
|
|
277
|
+
cosmeticComponent.OnApplyEffect(gameObject);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
private void InternalRemoveCosmeticEffects(EffectHandle handle)
|
|
283
|
+
{
|
|
284
|
+
if (
|
|
285
|
+
!_instancedCosmeticEffects.TryGetValue(
|
|
286
|
+
handle,
|
|
287
|
+
out List<CosmeticEffectData> cosmeticDatas
|
|
288
|
+
)
|
|
289
|
+
)
|
|
290
|
+
{
|
|
291
|
+
// If we don't have instanced cosmetic effects, then they were applied directly to the cosmetic data
|
|
292
|
+
foreach (
|
|
293
|
+
CosmeticEffectData cosmeticEffectData in handle.effect.cosmeticEffects
|
|
294
|
+
?? Enumerable.Empty<CosmeticEffectData>()
|
|
295
|
+
)
|
|
296
|
+
{
|
|
297
|
+
if (cosmeticEffectData.RequiresInstancing)
|
|
298
|
+
{
|
|
299
|
+
this.LogWarn(
|
|
300
|
+
$"Double-deregistration detected for handle {handle:json}. Existing handles: [{(string.Join(",", _instancedCosmeticEffects.Keys))}]."
|
|
301
|
+
);
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
Buffers<CosmeticEffectComponent>.List.Clear();
|
|
306
|
+
cosmeticEffectData.GetComponents(Buffers<CosmeticEffectComponent>.List);
|
|
307
|
+
foreach (
|
|
308
|
+
CosmeticEffectComponent cosmeticComponent in Buffers<CosmeticEffectComponent>.List
|
|
309
|
+
)
|
|
310
|
+
{
|
|
311
|
+
cosmeticComponent.OnRemoveEffect(gameObject);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
foreach (
|
|
319
|
+
CosmeticEffectComponent cosmeticComponent in cosmeticDatas.SelectMany(
|
|
320
|
+
cosmeticData => cosmeticData.GetComponents<CosmeticEffectComponent>()
|
|
321
|
+
)
|
|
322
|
+
)
|
|
323
|
+
{
|
|
324
|
+
cosmeticComponent.OnRemoveEffect(gameObject);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
foreach (CosmeticEffectData data in cosmeticDatas)
|
|
328
|
+
{
|
|
329
|
+
bool shouldDestroyGameObject = true;
|
|
330
|
+
Buffers<CosmeticEffectComponent>.List.Clear();
|
|
331
|
+
data.GetComponents(Buffers<CosmeticEffectComponent>.List);
|
|
332
|
+
foreach (
|
|
333
|
+
CosmeticEffectComponent cosmeticEffect in Buffers<CosmeticEffectComponent>.List
|
|
334
|
+
)
|
|
335
|
+
{
|
|
336
|
+
if (cosmeticEffect.CleansUpSelf)
|
|
337
|
+
{
|
|
338
|
+
shouldDestroyGameObject = false;
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
cosmeticEffect.Destroy();
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (shouldDestroyGameObject)
|
|
346
|
+
{
|
|
347
|
+
data.gameObject.Destroy();
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
_ = _instancedCosmeticEffects.Remove(handle);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
private void Update()
|
|
355
|
+
{
|
|
356
|
+
if (_effectExpirations.Count <= 0)
|
|
357
|
+
{
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
_expiredEffectIds.Clear();
|
|
362
|
+
float currentTime = Time.time;
|
|
363
|
+
foreach (KeyValuePair<KGuid, float> entry in _effectExpirations)
|
|
364
|
+
{
|
|
365
|
+
if (entry.Value < currentTime)
|
|
366
|
+
{
|
|
367
|
+
_expiredEffectIds.Add(entry.Key);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
foreach (KGuid expiredHandleId in _expiredEffectIds)
|
|
372
|
+
{
|
|
373
|
+
if (_effectHandlesById.TryGetValue(expiredHandleId, out EffectHandle expiredHandle))
|
|
374
|
+
{
|
|
375
|
+
RemoveEffect(expiredHandle);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
namespace WallstopStudios.UnityHelpers.
|
|
1
|
+
namespace WallstopStudios.UnityHelpers.Tags
|
|
2
2
|
{
|
|
3
3
|
using System;
|
|
4
4
|
using System.Collections.Generic;
|
|
5
|
+
using Core.DataStructure.Adapters;
|
|
5
6
|
using Core.Extension;
|
|
6
7
|
using UnityEngine;
|
|
7
8
|
|
|
8
9
|
[DisallowMultipleComponent]
|
|
9
|
-
public class TagHandler : MonoBehaviour
|
|
10
|
+
public sealed class TagHandler : MonoBehaviour
|
|
10
11
|
{
|
|
11
12
|
public IReadOnlyCollection<string> Tags => _tagCount.Keys;
|
|
12
13
|
|
|
13
14
|
[SerializeField]
|
|
14
|
-
|
|
15
|
+
private List<string> _initialEffectTags = new();
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
private readonly Dictionary<string, uint> _tagCount = new(StringComparer.Ordinal);
|
|
18
|
+
private readonly Dictionary<KGuid, EffectHandle> _effectHandles = new();
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
private void Awake()
|
|
19
21
|
{
|
|
20
22
|
if (_initialEffectTags is { Count: > 0 })
|
|
21
23
|
{
|
|
@@ -74,6 +76,41 @@
|
|
|
74
76
|
InternalRemoveTag(effectTag);
|
|
75
77
|
}
|
|
76
78
|
|
|
79
|
+
public void ForceApplyTags(EffectHandle handle)
|
|
80
|
+
{
|
|
81
|
+
KGuid id = handle.id;
|
|
82
|
+
if (!_effectHandles.TryAdd(id, handle))
|
|
83
|
+
{
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
ForceApplyEffect(handle.effect);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public void ForceApplyEffect(AttributeEffect effect)
|
|
91
|
+
{
|
|
92
|
+
foreach (string effectTag in effect.effectTags)
|
|
93
|
+
{
|
|
94
|
+
InternalApplyTag(effectTag);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public bool ForceRemoveTags(EffectHandle handle)
|
|
99
|
+
{
|
|
100
|
+
KGuid id = handle.id;
|
|
101
|
+
if (!_effectHandles.Remove(id, out EffectHandle appliedHandle))
|
|
102
|
+
{
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
foreach (string effectTag in appliedHandle.effect.effectTags)
|
|
107
|
+
{
|
|
108
|
+
InternalRemoveTag(effectTag);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
|
|
77
114
|
private void InternalApplyTag(string effectTag)
|
|
78
115
|
{
|
|
79
116
|
_ = _tagCount.AddOrUpdate(effectTag, _ => 1U, (_, existing) => existing + 1);
|