com.wallstop-studios.unity-helpers 2.0.0 → 2.0.2
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/.github/workflows/format-on-demand.yml +2 -2
- package/.github/workflows/markdown-json.yml +1 -1
- package/.github/workflows/npm-publish.yml +1 -1
- package/.github/workflows/prettier-autofix.yml +4 -4
- package/.github/workflows/yaml-format-lint.yml +1 -1
- package/Docs/EFFECTS_SYSTEM.md +1316 -0
- package/{EFFECTS_SYSTEM_TUTORIAL.md → Docs/EFFECTS_SYSTEM_TUTORIAL.md} +1 -1
- package/{GETTING_STARTED.md → Docs/GETTING_STARTED.md} +10 -8
- package/{GLOSSARY.md → Docs/GLOSSARY.md} +4 -4
- package/Docs/HELPER_UTILITIES.md +885 -0
- package/Docs/HELPER_UTILITIES.md.meta +7 -0
- package/{INDEX.md → Docs/INDEX.md} +107 -62
- package/Docs/MATH_AND_EXTENSIONS.md +1039 -0
- package/{RANDOM_PERFORMANCE.md → Docs/RANDOM_PERFORMANCE.md} +15 -15
- package/{RELATIONAL_COMPONENTS.md → Docs/RELATIONAL_COMPONENTS.md} +21 -3
- package/{SPATIAL_TREES_2D_GUIDE.md → Docs/SPATIAL_TREES_2D_GUIDE.md} +2 -2
- package/{SPATIAL_TREES_3D_GUIDE.md → Docs/SPATIAL_TREES_3D_GUIDE.md} +1 -1
- package/{SPATIAL_TREE_2D_PERFORMANCE.md → Docs/SPATIAL_TREE_2D_PERFORMANCE.md} +64 -64
- package/{SPATIAL_TREE_3D_PERFORMANCE.md → Docs/SPATIAL_TREE_3D_PERFORMANCE.md} +64 -64
- package/Docs/UTILITY_COMPONENTS.md +906 -0
- package/Docs/UTILITY_COMPONENTS.md.meta +7 -0
- package/Docs/VISUAL_COMPONENTS.md +337 -0
- package/Docs/VISUAL_COMPONENTS.md.meta +7 -0
- package/Editor/Sprites/AnimationCopier.cs +3 -3
- package/README.md +69 -62
- package/Runtime/AssemblyInfo.cs +2 -0
- package/Runtime/Core/DataStructure/KDTree3D.cs +1 -1
- package/Runtime/Core/DataStructure/OctTree3D.cs +1 -1
- package/Runtime/Core/Extension/AsyncOperationExtensions.cs +122 -0
- package/Runtime/Core/Helper/Logging/UnityLogTagFormatter.cs +76 -90
- package/Runtime/Core/Serialization/ProtobufUnitySurrogates.cs +24 -29
- package/Runtime/Integrations/Reflex/AssemblyInfo.cs +7 -0
- package/Runtime/Integrations/Reflex/AssemblyInfo.cs.meta +11 -0
- package/Runtime/Integrations/Reflex/ContainerRelationalExtensions.cs +198 -0
- package/Runtime/Integrations/Reflex/ContainerRelationalExtensions.cs.meta +11 -0
- package/Runtime/Integrations/Reflex/RelationalComponentsInstaller.cs +86 -0
- package/Runtime/Integrations/Reflex/RelationalComponentsInstaller.cs.meta +11 -0
- package/Runtime/Integrations/Reflex/RelationalReflexSceneBootstrapper.cs +316 -0
- package/Runtime/Integrations/Reflex/RelationalReflexSceneBootstrapper.cs.meta +11 -0
- package/Runtime/Integrations/Reflex/RelationalSceneAssignmentOptions.cs +86 -0
- package/Runtime/Integrations/Reflex/RelationalSceneAssignmentOptions.cs.meta +11 -0
- package/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Integration.Reflex.asmdef +20 -0
- package/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Integration.Reflex.asmdef.meta +7 -0
- package/Runtime/Integrations/Reflex.meta +8 -0
- package/Runtime/Utils/ScriptableObjectSingleton.cs +1 -1
- package/Samples~/DI - Reflex/README.md +527 -0
- package/Samples~/DI - Reflex/README.md.meta +7 -0
- package/Samples~/DI - Reflex/Scripts/ReflexPaletteService.cs +36 -0
- package/Samples~/DI - Reflex/Scripts/ReflexPaletteService.cs.meta +11 -0
- package/Samples~/DI - Reflex/Scripts/ReflexRelationalConsumer.cs +79 -0
- package/Samples~/DI - Reflex/Scripts/ReflexRelationalConsumer.cs.meta +11 -0
- package/Samples~/DI - Reflex/Scripts/ReflexSampleInstaller.cs +30 -0
- package/Samples~/DI - Reflex/Scripts/ReflexSampleInstaller.cs.meta +11 -0
- package/Samples~/DI - Reflex/Scripts/ReflexSpawner.cs +79 -0
- package/Samples~/DI - Reflex/Scripts/ReflexSpawner.cs.meta +11 -0
- package/Samples~/DI - Reflex/Scripts/Samples.UnityHelpers.DI.Reflex.asmdef +26 -0
- package/Samples~/DI - Reflex/Scripts/Samples.UnityHelpers.DI.Reflex.asmdef.meta +9 -0
- package/Samples~/DI - Reflex/Scripts.meta +8 -0
- package/Samples~/DI - Reflex.meta +8 -0
- package/Samples~/DI - VContainer/README.md +6 -5
- package/Samples~/DI - Zenject/README.md +6 -5
- package/Tests/Editor/Core/Attributes/RelationalComponentAssignerTests.cs +29 -31
- package/Tests/Editor/Integrations/Reflex/ReflexIntegrationCompilationTests.cs +41 -0
- package/Tests/Editor/Integrations/Reflex/ReflexIntegrationCompilationTests.cs.meta +11 -0
- package/Tests/Editor/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Editor.Reflex.asmdef +27 -0
- package/Tests/Editor/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Editor.Reflex.asmdef.meta +7 -0
- package/Tests/Editor/Integrations/Reflex.meta +8 -0
- package/Tests/Editor/Integrations/VContainer/VContainerRelationalEntryPointTests.cs +15 -16
- package/Tests/Editor/Integrations/VContainer/VContainerRelationalHelpersTests.cs +7 -13
- package/Tests/Editor/Integrations/Zenject/ZenjectRelationalHelpersTests.cs +7 -11
- package/Tests/Editor/Integrations/Zenject/ZenjectRelationalInitializerTests.cs +19 -21
- package/Tests/Editor/PersistentDirectorySettingsTests.cs +0 -1
- package/Tests/Editor/Sprites/AnimationCopierFilterTests.cs +0 -1
- package/Tests/Editor/Sprites/AnimationViewerWindowTests.cs +2 -2
- package/Tests/Editor/Tools/ImageBlurToolTests.cs +1 -1
- package/Tests/Editor/Utils/CommonTestBase.cs +17 -0
- package/Tests/Editor/Utils/ScriptableObjectSingletonCreatorTests.cs +1 -1
- package/Tests/Runtime/Extensions/AsyncOperationExtensionsTests.cs +179 -0
- package/Tests/Runtime/Extensions/RandomExtensionTests.cs +55 -0
- package/Tests/Runtime/Extensions/UnityLogTagFormatterEdgeTests.cs +84 -0
- package/Tests/Runtime/Integrations/Reflex/RelationalComponentsReflexTests.cs +445 -0
- package/Tests/Runtime/Integrations/Reflex/RelationalComponentsReflexTests.cs.meta +11 -0
- package/Tests/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Runtime.Reflex.asmdef +28 -0
- package/Tests/Runtime/Integrations/Reflex/WallstopStudios.UnityHelpers.Tests.Runtime.Reflex.asmdef.meta +7 -0
- package/Tests/Runtime/Integrations/Reflex.meta +8 -0
- package/Tests/Runtime/Integrations/VContainer/RelationalComponentsVContainerTests.cs +24 -29
- package/Tests/Runtime/Integrations/VContainer/RelationalObjectPoolsVContainerTests.cs +8 -3
- package/Tests/Runtime/Integrations/Zenject/RelationalComponentsZenjectTests.cs +10 -20
- package/Tests/Runtime/Performance/RandomPerformanceTests.cs +1 -1
- package/Tests/Runtime/Performance/SpatialTree2DPerformanceTests.cs +1 -1
- package/Tests/Runtime/Performance/SpatialTree3DPerformanceTests.cs +1 -1
- package/Tests/Runtime/Serialization/JsonRoundtripComprehensiveTests.cs +4 -9
- package/Tests/Runtime/Serialization/ProtoRoundtripComprehensiveTests.cs +13 -13
- package/Tests/Runtime/TestUtils/CommonTestBase.cs +11 -0
- package/Tests/Runtime/TestUtils/ReflexTestSupport.cs +111 -0
- package/Tests/Runtime/TestUtils/ReflexTestSupport.cs.meta +12 -0
- package/Tests/Runtime/Utils/MatchColliderToSpriteTests.cs +4 -4
- package/Tests/TestUtils.meta +8 -0
- package/package.json +6 -1
- package/EFFECTS_SYSTEM.md +0 -242
- package/MATH_AND_EXTENSIONS.md +0 -316
- /package/{CHANGELOG.md → Docs/CHANGELOG.md} +0 -0
- /package/{CHANGELOG.md.meta → Docs/CHANGELOG.md.meta} +0 -0
- /package/{CONTRIBUTING.md → Docs/CONTRIBUTING.md} +0 -0
- /package/{CONTRIBUTING.md.meta → Docs/CONTRIBUTING.md.meta} +0 -0
- /package/{DATA_STRUCTURES.md → Docs/DATA_STRUCTURES.md} +0 -0
- /package/{DATA_STRUCTURES.md.meta → Docs/DATA_STRUCTURES.md.meta} +0 -0
- /package/{EDITOR_TOOLS_GUIDE.md → Docs/EDITOR_TOOLS_GUIDE.md} +0 -0
- /package/{EDITOR_TOOLS_GUIDE.md.meta → Docs/EDITOR_TOOLS_GUIDE.md.meta} +0 -0
- /package/{EFFECTS_SYSTEM.md.meta → Docs/EFFECTS_SYSTEM.md.meta} +0 -0
- /package/{EFFECTS_SYSTEM_TUTORIAL.md.meta → Docs/EFFECTS_SYSTEM_TUTORIAL.md.meta} +0 -0
- /package/{GETTING_STARTED.md.meta → Docs/GETTING_STARTED.md.meta} +0 -0
- /package/{GLOSSARY.md.meta → Docs/GLOSSARY.md.meta} +0 -0
- /package/{HULLS.md → Docs/HULLS.md} +0 -0
- /package/{HULLS.md.meta → Docs/HULLS.md.meta} +0 -0
- /package/{INDEX.md.meta → Docs/INDEX.md.meta} +0 -0
- /package/{LICENSE.md → Docs/LICENSE.md} +0 -0
- /package/{LICENSE.md.meta → Docs/LICENSE.md.meta} +0 -0
- /package/{MATH_AND_EXTENSIONS.md.meta → Docs/MATH_AND_EXTENSIONS.md.meta} +0 -0
- /package/{RANDOM_PERFORMANCE.md.meta → Docs/RANDOM_PERFORMANCE.md.meta} +0 -0
- /package/{REFLECTION_HELPERS.md → Docs/REFLECTION_HELPERS.md} +0 -0
- /package/{REFLECTION_HELPERS.md.meta → Docs/REFLECTION_HELPERS.md.meta} +0 -0
- /package/{RELATIONAL_COMPONENTS.md.meta → Docs/RELATIONAL_COMPONENTS.md.meta} +0 -0
- /package/{SERIALIZATION.md → Docs/SERIALIZATION.md} +0 -0
- /package/{SERIALIZATION.md.meta → Docs/SERIALIZATION.md.meta} +0 -0
- /package/{SINGLETONS.md → Docs/SINGLETONS.md} +0 -0
- /package/{SINGLETONS.md.meta → Docs/SINGLETONS.md.meta} +0 -0
- /package/{SPATIAL_TREES_2D_GUIDE.md.meta → Docs/SPATIAL_TREES_2D_GUIDE.md.meta} +0 -0
- /package/{SPATIAL_TREES_3D_GUIDE.md.meta → Docs/SPATIAL_TREES_3D_GUIDE.md.meta} +0 -0
- /package/{SPATIAL_TREE_2D_PERFORMANCE.md.meta → Docs/SPATIAL_TREE_2D_PERFORMANCE.md.meta} +0 -0
- /package/{SPATIAL_TREE_3D_PERFORMANCE.md.meta → Docs/SPATIAL_TREE_3D_PERFORMANCE.md.meta} +0 -0
- /package/{SPATIAL_TREE_SEMANTICS.md → Docs/SPATIAL_TREE_SEMANTICS.md} +0 -0
- /package/{SPATIAL_TREE_SEMANTICS.md.meta → Docs/SPATIAL_TREE_SEMANTICS.md.meta} +0 -0
- /package/{THIRD_PARTY_NOTICES.md → Docs/THIRD_PARTY_NOTICES.md} +0 -0
- /package/{THIRD_PARTY_NOTICES.md.meta → Docs/THIRD_PARTY_NOTICES.md.meta} +0 -0
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
# Visual Components Guide
|
|
2
|
+
|
|
3
|
+
## TL;DR — Why Use These
|
|
4
|
+
|
|
5
|
+
- **AnimatedSpriteLayer**: Data structure for packaging sprite animation frames with per-frame offsets and transparency
|
|
6
|
+
- **LayeredImage**: UI Toolkit element that composites multiple sprite animation layers into a single animated image
|
|
7
|
+
- **EnhancedImage**: Extended Unity UI Image with HDR color support and shape masking
|
|
8
|
+
|
|
9
|
+
These components solve the problem of creating complex, multi-layer sprite animations without pre-rendering every combination into massive sprite sheets.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## AnimatedSpriteLayer
|
|
14
|
+
|
|
15
|
+
**What it is:** An immutable data structure (struct) that packages a sprite animation sequence with per-frame position offsets and layer-wide alpha transparency.
|
|
16
|
+
|
|
17
|
+
**Why it exists:** When building complex sprite animations (like a character with equipment, effects, or layered body parts), you need a standardized way to represent each layer with its timing, positioning, and transparency. This struct is the building block for the LayeredImage composition system.
|
|
18
|
+
|
|
19
|
+
**Problem it solves:**
|
|
20
|
+
|
|
21
|
+
- Eliminates manually syncing sprite frames, offsets, and alpha values across multiple systems
|
|
22
|
+
- Provides type-safe storage for animation layer data
|
|
23
|
+
- Automatically converts world-space offsets to pixel-space for rendering
|
|
24
|
+
- Validates texture readability at construction time (catches import setting errors early)
|
|
25
|
+
|
|
26
|
+
### When to Use
|
|
27
|
+
|
|
28
|
+
✅ **Use when:**
|
|
29
|
+
|
|
30
|
+
- Building `LayeredImage` compositions
|
|
31
|
+
- Creating character animations with separate layers for body parts
|
|
32
|
+
- Combining sprite effects (glow, shadow, outline) with base sprites
|
|
33
|
+
- You need frame-by-frame position adjustments (bobbing, recoil, etc.)
|
|
34
|
+
- Working with sprite-based animations that need dynamic layering
|
|
35
|
+
|
|
36
|
+
❌ **Don't use when:**
|
|
37
|
+
|
|
38
|
+
- You only have a single sprite sequence (just use `Animator`)
|
|
39
|
+
- Sprites don't need per-frame offsets (just use sprite arrays)
|
|
40
|
+
- You're working with UI Toolkit animations (use USS transitions)
|
|
41
|
+
- Performance is critical and you can pre-render combinations
|
|
42
|
+
|
|
43
|
+
### Basic Usage
|
|
44
|
+
|
|
45
|
+
```csharp
|
|
46
|
+
using WallstopStudios.UnityHelpers.Visuals;
|
|
47
|
+
using UnityEngine;
|
|
48
|
+
|
|
49
|
+
// Create a layer from sprite sequence
|
|
50
|
+
Sprite[] walkCycleFrames = LoadWalkCycleSprites(); // Must have Read/Write enabled!
|
|
51
|
+
|
|
52
|
+
// Optional: per-frame offsets in world space (e.g., for bobbing motion)
|
|
53
|
+
Vector2[] walkBobOffsets = new[]
|
|
54
|
+
{
|
|
55
|
+
new Vector2(0, 0.1f), // Frame 0: slight up
|
|
56
|
+
new Vector2(0, 0), // Frame 1: neutral
|
|
57
|
+
new Vector2(0, 0.1f), // Frame 2: slight up
|
|
58
|
+
new Vector2(0, 0) // Frame 3: neutral
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
AnimatedSpriteLayer bodyLayer = new AnimatedSpriteLayer(
|
|
62
|
+
sprites: walkCycleFrames,
|
|
63
|
+
worldSpaceOffsets: walkBobOffsets,
|
|
64
|
+
alpha: 1f // Fully opaque
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// Create equipment layer (same frame count, different sprites)
|
|
68
|
+
Sprite[] helmetFrames = LoadHelmetSprites();
|
|
69
|
+
AnimatedSpriteLayer helmetLayer = new AnimatedSpriteLayer(
|
|
70
|
+
sprites: helmetFrames,
|
|
71
|
+
worldSpaceOffsets: null, // No offsets
|
|
72
|
+
alpha: 0.9f // Slightly transparent
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
// Combine in LayeredImage (see below)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Editor-Only: Creating from AnimationClip
|
|
79
|
+
|
|
80
|
+
In editor code, you can create layers directly from AnimationClips:
|
|
81
|
+
|
|
82
|
+
```csharp
|
|
83
|
+
#if UNITY_EDITOR
|
|
84
|
+
using UnityEditor;
|
|
85
|
+
|
|
86
|
+
AnimationClip walkClip = AssetDatabase.LoadAssetAtPath<AnimationClip>("Assets/Animations/Walk.anim");
|
|
87
|
+
AnimatedSpriteLayer layer = new AnimatedSpriteLayer(
|
|
88
|
+
clip: walkClip,
|
|
89
|
+
worldSpaceOffsets: null,
|
|
90
|
+
alpha: 1f
|
|
91
|
+
);
|
|
92
|
+
#endif
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Important Notes
|
|
96
|
+
|
|
97
|
+
**Texture Readability:**
|
|
98
|
+
All sprites must have **Read/Write Enabled** in their texture import settings. The constructor validates this and logs errors for non-readable textures.
|
|
99
|
+
|
|
100
|
+
To fix:
|
|
101
|
+
|
|
102
|
+
1. Select the texture asset
|
|
103
|
+
2. In Inspector, check "Read/Write Enabled"
|
|
104
|
+
3. Click Apply
|
|
105
|
+
|
|
106
|
+
**Frame Rate:**
|
|
107
|
+
Default frame rate is 12 fps (stored in `AnimatedSpriteLayer.FrameRate` constant). This matches classic sprite animation timing.
|
|
108
|
+
|
|
109
|
+
**Offset Conversion:**
|
|
110
|
+
World-space offsets are automatically converted to pixel-space using sprite pixels-per-unit. This ensures offsets scale correctly with sprite resolution.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## LayeredImage
|
|
115
|
+
|
|
116
|
+
**What it is:** A UI Toolkit `VisualElement` that composites multiple `AnimatedSpriteLayer` instances into a single animated image with alpha blending, automatic cropping, and frame timing.
|
|
117
|
+
|
|
118
|
+
**Why it exists:** Creating character customization systems (body + equipment), visual effects (base + glow), or any multi-layer sprite animation traditionally requires pre-rendering every combination into massive sprite sheets. LayeredImage composes layers dynamically at runtime.
|
|
119
|
+
|
|
120
|
+
**Problem it solves:**
|
|
121
|
+
|
|
122
|
+
- **Sprite sheet explosion**: Instead of 10 bodies × 20 helmets × 15 armors = 3,000 pre-rendered sprites, you have 10 + 20 + 15 = 45 source sprites
|
|
123
|
+
- **Memory efficiency**: Only active layers are loaded, not every possible combination
|
|
124
|
+
- **Runtime flexibility**: Change equipment/effects without new assets
|
|
125
|
+
- **Automatic composition**: Handles alpha blending, pivot alignment, and cropping
|
|
126
|
+
|
|
127
|
+
### When to Use
|
|
128
|
+
|
|
129
|
+
✅ **Use when:**
|
|
130
|
+
|
|
131
|
+
- Character customization systems (swap equipment, clothing, accessories)
|
|
132
|
+
- Visual effects that layer over base sprites (shields, auras, damage flashes)
|
|
133
|
+
- Procedural sprite generation from components
|
|
134
|
+
- UI that needs animated, multi-layer sprites
|
|
135
|
+
- You want to avoid combinatorial explosion of pre-rendered sprites
|
|
136
|
+
|
|
137
|
+
❌ **Don't use when:**
|
|
138
|
+
|
|
139
|
+
- Single-layer animations (use Unity's `Image` or `Animator`)
|
|
140
|
+
- 3D models (use skinned mesh renderers)
|
|
141
|
+
- Performance is absolutely critical and you can afford pre-rendered sheets
|
|
142
|
+
- Sprites don't share the same frame count/timing
|
|
143
|
+
- Working in UGUI (use `EnhancedImage` for UGUI, though it doesn't support layering)
|
|
144
|
+
|
|
145
|
+
### Basic Usage
|
|
146
|
+
|
|
147
|
+
```csharp
|
|
148
|
+
using WallstopStudios.UnityHelpers.Visuals.UIToolkit;
|
|
149
|
+
using UnityEngine.UIElements;
|
|
150
|
+
|
|
151
|
+
// Create layers (see AnimatedSpriteLayer section above)
|
|
152
|
+
AnimatedSpriteLayer[] layers = new[]
|
|
153
|
+
{
|
|
154
|
+
bodyLayer, // Base character
|
|
155
|
+
armorLayer, // Equipment layer 1
|
|
156
|
+
helmetLayer, // Equipment layer 2
|
|
157
|
+
glowLayer // Effect layer
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// Create LayeredImage
|
|
161
|
+
LayeredImage characterImage = new LayeredImage(
|
|
162
|
+
inputSpriteLayers: layers,
|
|
163
|
+
backgroundColor: null, // Transparent background (or use Color for solid background)
|
|
164
|
+
fps: 12f, // Animation speed
|
|
165
|
+
updatesSelf: true, // Automatically advances frames (uses Unity editor ticks or coroutines)
|
|
166
|
+
pixelCutoff: 0.01f // Alpha threshold for cropping transparent pixels
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
// Add to UI Toolkit hierarchy
|
|
170
|
+
rootVisualElement.Add(characterImage);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Manual Frame Control
|
|
174
|
+
|
|
175
|
+
If you need precise control over frame advancement:
|
|
176
|
+
|
|
177
|
+
```csharp
|
|
178
|
+
LayeredImage manualImage = new LayeredImage(
|
|
179
|
+
inputSpriteLayers: layers,
|
|
180
|
+
backgroundColor: null,
|
|
181
|
+
fps: 12f,
|
|
182
|
+
updatesSelf: false, // Disable automatic updates
|
|
183
|
+
pixelCutoff: 0.01f
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
// In your update loop
|
|
187
|
+
void Update()
|
|
188
|
+
{
|
|
189
|
+
manualImage.Update(force: false); // Advances frame based on elapsed time
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Or force immediate frame advance
|
|
193
|
+
manualImage.Update(force: true);
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Changing Animation Speed
|
|
197
|
+
|
|
198
|
+
```csharp
|
|
199
|
+
// Set frames per second at runtime
|
|
200
|
+
characterImage.Fps = 24f; // Speed up animation
|
|
201
|
+
characterImage.Fps = 6f; // Slow down animation
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### How Compositing Works
|
|
205
|
+
|
|
206
|
+
LayeredImage performs these steps each frame:
|
|
207
|
+
|
|
208
|
+
1. **Allocates canvas**: Creates a texture large enough to hold all layers with their offsets
|
|
209
|
+
2. **Alpha blending**: Layers are composited back-to-front with alpha blending
|
|
210
|
+
3. **Pivot alignment**: Each sprite's pivot point is respected during positioning
|
|
211
|
+
4. **Offset application**: Per-frame pixel offsets are applied
|
|
212
|
+
5. **Cropping**: Transparent borders are trimmed (configurable via `pixelCutoff`)
|
|
213
|
+
6. **Rendering**: Final composited texture is displayed
|
|
214
|
+
|
|
215
|
+
**Performance optimization:**
|
|
216
|
+
|
|
217
|
+
- Uses parallel processing for large sprites (2048+ pixels total)
|
|
218
|
+
- Employs array pooling to minimize GC allocations
|
|
219
|
+
- Caches composited frames when possible
|
|
220
|
+
|
|
221
|
+
### Pixel Cutoff Parameter
|
|
222
|
+
|
|
223
|
+
Controls how aggressive transparent pixel cropping is:
|
|
224
|
+
|
|
225
|
+
```csharp
|
|
226
|
+
// More aggressive cropping (removes near-transparent pixels)
|
|
227
|
+
layeredImage.pixelCutoff = 0.05f;
|
|
228
|
+
|
|
229
|
+
// Less aggressive (keeps more semi-transparent pixels)
|
|
230
|
+
layeredImage.pixelCutoff = 0.001f;
|
|
231
|
+
|
|
232
|
+
// No cropping (includes fully transparent border)
|
|
233
|
+
layeredImage.pixelCutoff = 0f;
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Higher values = smaller final image, but may clip soft edges (glows, shadows).
|
|
237
|
+
|
|
238
|
+
### Important Notes
|
|
239
|
+
|
|
240
|
+
**Frame Synchronization:**
|
|
241
|
+
All layers must have the same number of frames. Mixing 4-frame and 8-frame animations will cause visual glitches.
|
|
242
|
+
|
|
243
|
+
**Performance Considerations:**
|
|
244
|
+
|
|
245
|
+
- Compositing happens every frame for animated images
|
|
246
|
+
- Large sprite resolutions (1024×1024+) will impact performance
|
|
247
|
+
- Consider pre-rendering if targeting low-end devices
|
|
248
|
+
- Parallel processing threshold is 2048 pixels (width × height)
|
|
249
|
+
|
|
250
|
+
**Editor vs Runtime:**
|
|
251
|
+
|
|
252
|
+
- In Editor: Uses Unity's editor update ticks for animation
|
|
253
|
+
- In Runtime: Uses coroutines for frame timing
|
|
254
|
+
- Both honor `updatesSelf` setting
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## EnhancedImage (UGUI)
|
|
259
|
+
|
|
260
|
+
**What it is:** An extended version of Unity's UI `Image` component with HDR color support and texture-based shape masking.
|
|
261
|
+
|
|
262
|
+
**Why it exists:** Unity's standard `Image` component doesn't support:
|
|
263
|
+
|
|
264
|
+
- HDR colors (for bloom/glow effects)
|
|
265
|
+
- Complex shape masks (beyond sprite masks)
|
|
266
|
+
- Shader-based shape rendering
|
|
267
|
+
|
|
268
|
+
**See full documentation:** [Editor Tools Guide - EnhancedImage](EDITOR_TOOLS_GUIDE.md#enhancedimage-editor)
|
|
269
|
+
|
|
270
|
+
**Quick example:**
|
|
271
|
+
|
|
272
|
+
```csharp
|
|
273
|
+
using WallstopStudios.UnityHelpers.Visuals.UGUI;
|
|
274
|
+
|
|
275
|
+
EnhancedImage image = GetComponent<EnhancedImage>();
|
|
276
|
+
|
|
277
|
+
// HDR color for bloom
|
|
278
|
+
image.HdrColor = new Color(2f, 0.5f, 0.1f, 1f); // RGB values > 1 for bloom
|
|
279
|
+
|
|
280
|
+
// Shape mask
|
|
281
|
+
image.shapeMask = myMaskTexture; // Black areas are transparent
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Best Practices
|
|
287
|
+
|
|
288
|
+
### AnimatedSpriteLayer
|
|
289
|
+
|
|
290
|
+
- **Always enable Read/Write** on source textures (build will fail otherwise)
|
|
291
|
+
- **Keep frame counts consistent** across layers for the same animation
|
|
292
|
+
- **Use world-space offsets** for consistent motion across different sprite resolutions
|
|
293
|
+
- **Cache layer instances** when using the same animation repeatedly (they're immutable)
|
|
294
|
+
|
|
295
|
+
### LayeredImage
|
|
296
|
+
|
|
297
|
+
- **Layer order matters**: Layers are rendered front-to-back in array order
|
|
298
|
+
- **Optimize sprite sizes**: Trim transparent borders before importing (use Sprite Editor's "Tight" mode)
|
|
299
|
+
- **Profile on target hardware**: Mobile devices may struggle with 512×512+ composites at 60fps
|
|
300
|
+
- **Use manual updates** when syncing with non-UI systems (like gameplay state)
|
|
301
|
+
- **Pre-render** if combinations are limited and performance is critical
|
|
302
|
+
|
|
303
|
+
### EnhancedImage
|
|
304
|
+
|
|
305
|
+
- **Don't mix with Image**: EnhancedImage replaces Unity's Image, don't use both
|
|
306
|
+
- **Material cleanup** is automatic but test in edit mode transitions
|
|
307
|
+
- **HDR requires post-processing**: Ensure Bloom is enabled in your camera's post-processing
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## Related Documentation
|
|
312
|
+
|
|
313
|
+
- [Editor Tools Guide](EDITOR_TOOLS_GUIDE.md) - EnhancedImage editor integration
|
|
314
|
+
- [Samples](Samples~/) - Example projects for each component
|
|
315
|
+
- [Math & Extensions](MATH_AND_EXTENSIONS.md) - Color utilities used internally
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## FAQ
|
|
320
|
+
|
|
321
|
+
**Q: Can I mix different frame counts in LayeredImage?**
|
|
322
|
+
A: No, all layers must have the same frame count. Pad shorter animations with duplicate frames if needed.
|
|
323
|
+
|
|
324
|
+
**Q: Why are my layers not aligned correctly?**
|
|
325
|
+
A: Check that sprite pivots are set correctly (usually center). LayeredImage respects sprite pivot points.
|
|
326
|
+
|
|
327
|
+
**Q: Can I change layers at runtime?**
|
|
328
|
+
A: Currently no, LayeredImage is immutable after construction. Create a new instance with updated layers.
|
|
329
|
+
|
|
330
|
+
**Q: Performance impact vs pre-rendered sprites?**
|
|
331
|
+
A: Compositing costs ~1-3ms per image on modern hardware. Pre-rendered is faster but uses more memory/storage.
|
|
332
|
+
|
|
333
|
+
**Q: Does this work with Unity's Animator?**
|
|
334
|
+
A: No, LayeredImage is independent. It's designed for UI Toolkit programmatic control.
|
|
335
|
+
|
|
336
|
+
**Q: Can I export the composited result?**
|
|
337
|
+
A: Not directly, but you could capture the rendered texture using `Texture2D.ReadPixels` in a render texture setup.
|
|
@@ -962,7 +962,7 @@ namespace WallstopStudios.UnityHelpers.Editor.Sprites
|
|
|
962
962
|
return;
|
|
963
963
|
}
|
|
964
964
|
|
|
965
|
-
List<AnimationFileInfo> animationsToDelete = new
|
|
965
|
+
List<AnimationFileInfo> animationsToDelete = new();
|
|
966
966
|
for (int i = 0; i < _unchangedAnimations.Count; i++)
|
|
967
967
|
{
|
|
968
968
|
AnimationFileInfo a = _unchangedAnimations[i];
|
|
@@ -1325,7 +1325,7 @@ namespace WallstopStudios.UnityHelpers.Editor.Sprites
|
|
|
1325
1325
|
{
|
|
1326
1326
|
try
|
|
1327
1327
|
{
|
|
1328
|
-
Regex rx = new
|
|
1328
|
+
Regex rx = new(_filterText, RegexOptions.IgnoreCase);
|
|
1329
1329
|
for (int i = 0; i < items.Count; i++)
|
|
1330
1330
|
{
|
|
1331
1331
|
AnimationFileInfo it = items[i];
|
|
@@ -1381,7 +1381,7 @@ namespace WallstopStudios.UnityHelpers.Editor.Sprites
|
|
|
1381
1381
|
return;
|
|
1382
1382
|
}
|
|
1383
1383
|
|
|
1384
|
-
List<AnimationFileInfo> toDelete = new
|
|
1384
|
+
List<AnimationFileInfo> toDelete = new();
|
|
1385
1385
|
for (int i = 0; i < _destinationOrphans.Count; i++)
|
|
1386
1386
|
{
|
|
1387
1387
|
AnimationFileInfo a = _destinationOrphans[i];
|