com.wallstop-studios.unity-helpers 2.0.0-rc76.6 → 2.0.0-rc76.8
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/AssetProcessors/SpriteLabelProcessor.cs +133 -0
- package/Editor/AssetProcessors/SpriteLabelProcessor.cs.meta +3 -0
- package/Editor/AssetProcessors.meta +3 -0
- package/Editor/CustomDrawers/StringInListeDrawer.cs +104 -25
- package/Editor/CustomDrawers/WShowIfPropertyDrawer.cs +12 -4
- package/Editor/CustomEditors/SourceFolderEntryDrawer.cs +182 -57
- package/Editor/Extensions/SerializedPropertyExtensions.cs +11 -0
- package/Editor/Sprites/ScriptableSpriteAtlas.cs +71 -1
- package/Editor/Sprites/ScriptableSpriteAtlasEditor.cs +91 -40
- package/Editor/Sprites/SpriteSheetAnimationCreator.cs +421 -102
- package/Runtime/Core/Attributes/WShowIfAttribute.cs +9 -1
- package/Runtime/Core/Helper/Helpers.cs +31 -3
- package/Runtime/Core/Helper/StringInList.cs +22 -3
- package/package.json +3 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
// ReSharper disable HeapView.CanAvoidClosure
|
|
2
|
+
namespace WallstopStudios.UnityHelpers.Editor.Sprites
|
|
2
3
|
{
|
|
3
4
|
#if UNITY_EDITOR
|
|
4
5
|
using System;
|
|
@@ -13,7 +14,6 @@
|
|
|
13
14
|
using UnityEditor.UIElements;
|
|
14
15
|
using UnityEngine;
|
|
15
16
|
using UnityEngine.UIElements;
|
|
16
|
-
using Debug = UnityEngine.Debug;
|
|
17
17
|
using Object = UnityEngine.Object;
|
|
18
18
|
|
|
19
19
|
public sealed class SpriteSheetAnimationCreator : EditorWindow
|
|
@@ -43,6 +43,14 @@
|
|
|
43
43
|
private Button _nextFrameButton;
|
|
44
44
|
private Slider _previewScrubber;
|
|
45
45
|
|
|
46
|
+
private bool _isDraggingToSelectSprites;
|
|
47
|
+
private int _spriteSelectionDragStartIndex = -1;
|
|
48
|
+
private int _spriteSelectionDragCurrentIndex = -1;
|
|
49
|
+
private StyleColor _selectedThumbnailBackgroundColor = new(
|
|
50
|
+
new Color(0.2f, 0.5f, 0.8f, 0.4f)
|
|
51
|
+
);
|
|
52
|
+
private readonly StyleColor _defaultThumbnailBackgroundColor = new(StyleKeyword.Null);
|
|
53
|
+
|
|
46
54
|
private bool _isPreviewing;
|
|
47
55
|
private int _currentPreviewAnimDefIndex = -1;
|
|
48
56
|
private int _currentPreviewSpriteIndex;
|
|
@@ -65,6 +73,8 @@
|
|
|
65
73
|
public sealed class AnimationDefinition
|
|
66
74
|
{
|
|
67
75
|
public string Name = "New Animation";
|
|
76
|
+
public bool loop;
|
|
77
|
+
public float cycleOffset;
|
|
68
78
|
public int StartSpriteIndex;
|
|
69
79
|
public int EndSpriteIndex;
|
|
70
80
|
public float DefaultFrameRate = 12f;
|
|
@@ -79,6 +89,8 @@
|
|
|
79
89
|
public Label spriteCountLabel;
|
|
80
90
|
public Button previewButton;
|
|
81
91
|
public Button removeButton;
|
|
92
|
+
public Toggle loopingField;
|
|
93
|
+
public FloatField cycleOffsetField;
|
|
82
94
|
}
|
|
83
95
|
|
|
84
96
|
public SpriteSheetAnimationCreator()
|
|
@@ -161,7 +173,9 @@
|
|
|
161
173
|
topSection.Add(_refreshSpritesButton);
|
|
162
174
|
root.Add(topSection);
|
|
163
175
|
|
|
164
|
-
Label thumbnailsLabel = new(
|
|
176
|
+
Label thumbnailsLabel = new(
|
|
177
|
+
"Available Sprites (Drag to select range for new animation):"
|
|
178
|
+
)
|
|
165
179
|
{
|
|
166
180
|
style =
|
|
167
181
|
{
|
|
@@ -175,8 +189,8 @@
|
|
|
175
189
|
{
|
|
176
190
|
style =
|
|
177
191
|
{
|
|
178
|
-
height = ThumbnailSize + 20,
|
|
179
|
-
minHeight = ThumbnailSize + 20,
|
|
192
|
+
height = ThumbnailSize + 20 + 10,
|
|
193
|
+
minHeight = ThumbnailSize + 20 + 10,
|
|
180
194
|
borderTopWidth = 1,
|
|
181
195
|
borderBottomWidth = 1,
|
|
182
196
|
borderLeftWidth = 1,
|
|
@@ -196,6 +210,72 @@
|
|
|
196
210
|
{
|
|
197
211
|
style = { flexDirection = FlexDirection.Row },
|
|
198
212
|
};
|
|
213
|
+
|
|
214
|
+
_spriteThumbnailsContainer.RegisterCallback<PointerMoveEvent>(evt =>
|
|
215
|
+
{
|
|
216
|
+
if (
|
|
217
|
+
_isDraggingToSelectSprites
|
|
218
|
+
&& _spriteThumbnailsContainer.HasPointerCapture(evt.pointerId)
|
|
219
|
+
)
|
|
220
|
+
{
|
|
221
|
+
VisualElement currentElementOver = evt.target as VisualElement;
|
|
222
|
+
|
|
223
|
+
VisualElement thumbChild = currentElementOver;
|
|
224
|
+
while (thumbChild != null && thumbChild.parent != _spriteThumbnailsContainer)
|
|
225
|
+
{
|
|
226
|
+
thumbChild = thumbChild.parent;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (
|
|
230
|
+
thumbChild is { userData: int hoveredIndex }
|
|
231
|
+
&& _spriteSelectionDragCurrentIndex != hoveredIndex
|
|
232
|
+
)
|
|
233
|
+
{
|
|
234
|
+
_spriteSelectionDragCurrentIndex = hoveredIndex;
|
|
235
|
+
UpdateSpriteSelectionHighlight();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
_spriteThumbnailsContainer.RegisterCallback<PointerUpEvent>(
|
|
241
|
+
evt =>
|
|
242
|
+
{
|
|
243
|
+
if (
|
|
244
|
+
evt.button == 0
|
|
245
|
+
&& _isDraggingToSelectSprites
|
|
246
|
+
&& _spriteThumbnailsContainer.HasPointerCapture(evt.pointerId)
|
|
247
|
+
)
|
|
248
|
+
{
|
|
249
|
+
_spriteThumbnailsContainer.ReleasePointer(evt.pointerId);
|
|
250
|
+
_isDraggingToSelectSprites = false;
|
|
251
|
+
|
|
252
|
+
if (
|
|
253
|
+
_spriteSelectionDragStartIndex != -1
|
|
254
|
+
&& _spriteSelectionDragCurrentIndex != -1
|
|
255
|
+
)
|
|
256
|
+
{
|
|
257
|
+
int start = Mathf.Min(
|
|
258
|
+
_spriteSelectionDragStartIndex,
|
|
259
|
+
_spriteSelectionDragCurrentIndex
|
|
260
|
+
);
|
|
261
|
+
int end = Mathf.Max(
|
|
262
|
+
_spriteSelectionDragStartIndex,
|
|
263
|
+
_spriteSelectionDragCurrentIndex
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
if (start <= end)
|
|
267
|
+
{
|
|
268
|
+
CreateAnimationDefinitionFromSelection(start, end);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
ClearSpriteSelectionHighlight();
|
|
272
|
+
_spriteSelectionDragStartIndex = -1;
|
|
273
|
+
_spriteSelectionDragCurrentIndex = -1;
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
TrickleDown.TrickleDown
|
|
277
|
+
);
|
|
278
|
+
|
|
199
279
|
_spriteThumbnailsScrollView.Add(_spriteThumbnailsContainer);
|
|
200
280
|
root.Add(_spriteThumbnailsScrollView);
|
|
201
281
|
|
|
@@ -424,6 +504,115 @@
|
|
|
424
504
|
SetPreviewFrame(nextFrame);
|
|
425
505
|
}
|
|
426
506
|
|
|
507
|
+
private void UpdateSpriteSelectionHighlight()
|
|
508
|
+
{
|
|
509
|
+
if (
|
|
510
|
+
!_isDraggingToSelectSprites
|
|
511
|
+
|| _spriteSelectionDragStartIndex == -1
|
|
512
|
+
|| _spriteSelectionDragCurrentIndex == -1
|
|
513
|
+
)
|
|
514
|
+
{
|
|
515
|
+
ClearSpriteSelectionHighlight();
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
int minIdx = Mathf.Min(
|
|
520
|
+
_spriteSelectionDragStartIndex,
|
|
521
|
+
_spriteSelectionDragCurrentIndex
|
|
522
|
+
);
|
|
523
|
+
int maxIdx = Mathf.Max(
|
|
524
|
+
_spriteSelectionDragStartIndex,
|
|
525
|
+
_spriteSelectionDragCurrentIndex
|
|
526
|
+
);
|
|
527
|
+
|
|
528
|
+
for (int i = 0; i < _spriteThumbnailsContainer.childCount; i++)
|
|
529
|
+
{
|
|
530
|
+
VisualElement thumb = _spriteThumbnailsContainer.ElementAt(i);
|
|
531
|
+
if (thumb.userData is int thumbIndex)
|
|
532
|
+
{
|
|
533
|
+
if (thumbIndex >= minIdx && thumbIndex <= maxIdx)
|
|
534
|
+
{
|
|
535
|
+
thumb.style.backgroundColor = _selectedThumbnailBackgroundColor;
|
|
536
|
+
thumb.style.borderBottomColor =
|
|
537
|
+
_selectedThumbnailBackgroundColor.value * 1.5f;
|
|
538
|
+
thumb.style.borderTopColor = _selectedThumbnailBackgroundColor.value * 1.5f;
|
|
539
|
+
thumb.style.borderLeftColor =
|
|
540
|
+
_selectedThumbnailBackgroundColor.value * 1.5f;
|
|
541
|
+
thumb.style.borderRightColor =
|
|
542
|
+
_selectedThumbnailBackgroundColor.value * 1.5f;
|
|
543
|
+
}
|
|
544
|
+
else
|
|
545
|
+
{
|
|
546
|
+
thumb.style.backgroundColor = _defaultThumbnailBackgroundColor;
|
|
547
|
+
thumb.style.borderBottomColor = Color.clear;
|
|
548
|
+
thumb.style.borderTopColor = Color.clear;
|
|
549
|
+
thumb.style.borderLeftColor = Color.clear;
|
|
550
|
+
thumb.style.borderRightColor = Color.clear;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
private void ClearSpriteSelectionHighlight()
|
|
557
|
+
{
|
|
558
|
+
for (int i = 0; i < _spriteThumbnailsContainer.childCount; i++)
|
|
559
|
+
{
|
|
560
|
+
VisualElement thumb = _spriteThumbnailsContainer.ElementAt(i);
|
|
561
|
+
thumb.style.backgroundColor = _defaultThumbnailBackgroundColor;
|
|
562
|
+
thumb.style.borderBottomColor = Color.clear;
|
|
563
|
+
thumb.style.borderTopColor = Color.clear;
|
|
564
|
+
thumb.style.borderLeftColor = Color.clear;
|
|
565
|
+
thumb.style.borderRightColor = Color.clear;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
private void CreateAnimationDefinitionFromSelection(
|
|
570
|
+
int startSpriteIndex,
|
|
571
|
+
int endSpriteIndex
|
|
572
|
+
)
|
|
573
|
+
{
|
|
574
|
+
if (
|
|
575
|
+
startSpriteIndex < 0
|
|
576
|
+
|| endSpriteIndex < 0
|
|
577
|
+
|| startSpriteIndex >= _availableSprites.Count
|
|
578
|
+
|| endSpriteIndex >= _availableSprites.Count
|
|
579
|
+
)
|
|
580
|
+
{
|
|
581
|
+
this.LogWarn(
|
|
582
|
+
$"Invalid sprite indices for new animation definition from selection."
|
|
583
|
+
);
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
AnimationDefinition newDefinition = new()
|
|
588
|
+
{
|
|
589
|
+
Name =
|
|
590
|
+
_selectedSpriteSheet != null
|
|
591
|
+
? $"{_selectedSpriteSheet.name}_Anim_{_animationDefinitions.Count}"
|
|
592
|
+
: $"New_Animation_{_animationDefinitions.Count}",
|
|
593
|
+
StartSpriteIndex = startSpriteIndex,
|
|
594
|
+
EndSpriteIndex = endSpriteIndex,
|
|
595
|
+
DefaultFrameRate = 12f,
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
newDefinition.FrameRateCurve = AnimationCurve.Constant(
|
|
599
|
+
0,
|
|
600
|
+
1,
|
|
601
|
+
newDefinition.DefaultFrameRate
|
|
602
|
+
);
|
|
603
|
+
|
|
604
|
+
_animationDefinitions.Add(newDefinition);
|
|
605
|
+
UpdateSpritesForDefinition(newDefinition);
|
|
606
|
+
_currentPreviewAnimDefIndex = _animationDefinitions.Count - 1;
|
|
607
|
+
StartOrUpdateCurrentPreview(newDefinition);
|
|
608
|
+
_animationDefinitionsListView.Rebuild();
|
|
609
|
+
|
|
610
|
+
if (_animationDefinitionsListView.itemsSource.Count > 0)
|
|
611
|
+
{
|
|
612
|
+
_animationDefinitionsListView.ScrollToItem(_animationDefinitions.Count - 1);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
427
616
|
private void OnSpriteSheetSelected(ChangeEvent<Object> evt)
|
|
428
617
|
{
|
|
429
618
|
_selectedSpriteSheet = evt.newValue as Texture2D;
|
|
@@ -540,7 +729,20 @@
|
|
|
540
729
|
Sprite sprite = _availableSprites[i];
|
|
541
730
|
VisualElement thumbContainer = new()
|
|
542
731
|
{
|
|
543
|
-
style =
|
|
732
|
+
style =
|
|
733
|
+
{
|
|
734
|
+
alignItems = Align.Center,
|
|
735
|
+
marginRight = 5,
|
|
736
|
+
paddingBottom = 2,
|
|
737
|
+
borderBottomWidth = 1,
|
|
738
|
+
borderLeftWidth = 1,
|
|
739
|
+
borderRightWidth = 1,
|
|
740
|
+
borderTopWidth = 1,
|
|
741
|
+
borderBottomColor = Color.clear,
|
|
742
|
+
borderTopColor = Color.clear,
|
|
743
|
+
borderLeftColor = Color.clear,
|
|
744
|
+
borderRightColor = Color.clear,
|
|
745
|
+
},
|
|
544
746
|
};
|
|
545
747
|
Image img = new()
|
|
546
748
|
{
|
|
@@ -550,6 +752,36 @@
|
|
|
550
752
|
};
|
|
551
753
|
thumbContainer.Add(img);
|
|
552
754
|
thumbContainer.Add(new Label($"{i}") { style = { fontSize = 9 } });
|
|
755
|
+
|
|
756
|
+
int currentIndex = i;
|
|
757
|
+
thumbContainer.userData = currentIndex;
|
|
758
|
+
|
|
759
|
+
thumbContainer.RegisterCallback<PointerDownEvent>(evt =>
|
|
760
|
+
{
|
|
761
|
+
if (evt.button == 0)
|
|
762
|
+
{
|
|
763
|
+
_isDraggingToSelectSprites = true;
|
|
764
|
+
_spriteSelectionDragStartIndex = currentIndex;
|
|
765
|
+
_spriteSelectionDragCurrentIndex = currentIndex;
|
|
766
|
+
UpdateSpriteSelectionHighlight();
|
|
767
|
+
|
|
768
|
+
_spriteThumbnailsContainer.CapturePointer(evt.pointerId);
|
|
769
|
+
evt.StopPropagation();
|
|
770
|
+
}
|
|
771
|
+
});
|
|
772
|
+
|
|
773
|
+
thumbContainer.RegisterCallback<PointerEnterEvent>(_ =>
|
|
774
|
+
{
|
|
775
|
+
if (
|
|
776
|
+
_isDraggingToSelectSprites
|
|
777
|
+
&& _spriteThumbnailsContainer.HasPointerCapture(PointerId.mousePointerId)
|
|
778
|
+
&& _spriteSelectionDragCurrentIndex != currentIndex
|
|
779
|
+
)
|
|
780
|
+
{
|
|
781
|
+
_spriteSelectionDragCurrentIndex = currentIndex;
|
|
782
|
+
UpdateSpriteSelectionHighlight();
|
|
783
|
+
}
|
|
784
|
+
});
|
|
553
785
|
_spriteThumbnailsContainer.Add(thumbContainer);
|
|
554
786
|
}
|
|
555
787
|
}
|
|
@@ -562,7 +794,7 @@
|
|
|
562
794
|
}
|
|
563
795
|
}
|
|
564
796
|
|
|
565
|
-
private VisualElement MakeAnimationDefinitionItem()
|
|
797
|
+
private static VisualElement MakeAnimationDefinitionItem()
|
|
566
798
|
{
|
|
567
799
|
VisualElement container = new()
|
|
568
800
|
{
|
|
@@ -597,6 +829,10 @@
|
|
|
597
829
|
{
|
|
598
830
|
style = { flexDirection = FlexDirection.Row, alignItems = Align.Center },
|
|
599
831
|
};
|
|
832
|
+
VisualElement fourthRow = new()
|
|
833
|
+
{
|
|
834
|
+
style = { flexDirection = FlexDirection.Row, alignItems = Align.Center },
|
|
835
|
+
};
|
|
600
836
|
|
|
601
837
|
TextField nameField = new("Name:")
|
|
602
838
|
{
|
|
@@ -657,9 +893,33 @@
|
|
|
657
893
|
thirdRow.Add(fpsField);
|
|
658
894
|
thirdRow.Add(curveField);
|
|
659
895
|
|
|
896
|
+
Toggle looping = new("Looping:")
|
|
897
|
+
{
|
|
898
|
+
style =
|
|
899
|
+
{
|
|
900
|
+
flexGrow = 1,
|
|
901
|
+
flexShrink = 1,
|
|
902
|
+
marginRight = 5,
|
|
903
|
+
},
|
|
904
|
+
};
|
|
905
|
+
|
|
906
|
+
FloatField cycleOffset = new("Cycle Offset:")
|
|
907
|
+
{
|
|
908
|
+
style =
|
|
909
|
+
{
|
|
910
|
+
flexGrow = 1,
|
|
911
|
+
flexShrink = 1,
|
|
912
|
+
marginRight = 5,
|
|
913
|
+
},
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
fourthRow.Add(looping);
|
|
917
|
+
fourthRow.Add(cycleOffset);
|
|
918
|
+
|
|
660
919
|
container.Add(firstRow);
|
|
661
920
|
container.Add(secondRow);
|
|
662
921
|
container.Add(thirdRow);
|
|
922
|
+
container.Add(fourthRow);
|
|
663
923
|
|
|
664
924
|
container.userData = new AnimationDefUITags
|
|
665
925
|
{
|
|
@@ -671,6 +931,8 @@
|
|
|
671
931
|
spriteCountLabel = spriteCountLabel,
|
|
672
932
|
previewButton = previewButton,
|
|
673
933
|
removeButton = removeButton,
|
|
934
|
+
looping = looping,
|
|
935
|
+
cycleOffset = cycleOffset,
|
|
674
936
|
};
|
|
675
937
|
return container;
|
|
676
938
|
}
|
|
@@ -685,11 +947,13 @@
|
|
|
685
947
|
public Label spriteCountLabel;
|
|
686
948
|
public Button previewButton;
|
|
687
949
|
public Button removeButton;
|
|
950
|
+
public Toggle looping;
|
|
951
|
+
public FloatField cycleOffset;
|
|
688
952
|
}
|
|
689
953
|
|
|
690
954
|
private void BindAnimationDefinitionItem(VisualElement element, int index)
|
|
691
955
|
{
|
|
692
|
-
AnimationDefinition
|
|
956
|
+
AnimationDefinition definition = _animationDefinitions[index];
|
|
693
957
|
if (element.userData is not AnimationDefUITags tags)
|
|
694
958
|
{
|
|
695
959
|
this.LogError(
|
|
@@ -698,143 +962,178 @@
|
|
|
698
962
|
return;
|
|
699
963
|
}
|
|
700
964
|
|
|
701
|
-
|
|
702
|
-
|
|
965
|
+
definition.nameField?.UnregisterValueChangedCallback(
|
|
966
|
+
definition.nameField.userData as EventCallback<ChangeEvent<string>>
|
|
703
967
|
);
|
|
704
968
|
|
|
705
|
-
|
|
706
|
-
|
|
969
|
+
definition.startIndexField?.UnregisterValueChangedCallback(
|
|
970
|
+
definition.startIndexField.userData as EventCallback<ChangeEvent<int>>
|
|
707
971
|
);
|
|
708
972
|
|
|
709
|
-
|
|
710
|
-
|
|
973
|
+
definition.endIndexField?.UnregisterValueChangedCallback(
|
|
974
|
+
definition.endIndexField.userData as EventCallback<ChangeEvent<int>>
|
|
711
975
|
);
|
|
712
976
|
|
|
713
|
-
|
|
714
|
-
|
|
977
|
+
definition.defaultFrameRateField?.UnregisterValueChangedCallback(
|
|
978
|
+
definition.defaultFrameRateField.userData as EventCallback<ChangeEvent<float>>
|
|
715
979
|
);
|
|
716
980
|
|
|
717
|
-
|
|
718
|
-
|
|
981
|
+
definition.frameRateCurveField?.UnregisterValueChangedCallback(
|
|
982
|
+
definition.frameRateCurveField.userData
|
|
983
|
+
as EventCallback<ChangeEvent<AnimationCurve>>
|
|
719
984
|
);
|
|
720
985
|
|
|
721
|
-
if (
|
|
986
|
+
if (definition.removeButton != null)
|
|
722
987
|
{
|
|
723
|
-
|
|
988
|
+
definition.removeButton.clicked -= (Action)definition.removeButton.userData;
|
|
724
989
|
}
|
|
725
990
|
|
|
726
|
-
if (
|
|
991
|
+
if (definition.previewButton != null)
|
|
727
992
|
{
|
|
728
|
-
|
|
993
|
+
definition.previewButton.clicked -= (Action)definition.previewButton.userData;
|
|
729
994
|
}
|
|
730
995
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
def.removeButton = tags.removeButton;
|
|
738
|
-
def.previewButton = tags.previewButton;
|
|
996
|
+
definition.loopingField?.UnregisterValueChangedCallback(
|
|
997
|
+
(EventCallback<ChangeEvent<bool>>)definition.loopingField.userData
|
|
998
|
+
);
|
|
999
|
+
definition.cycleOffsetField?.UnregisterValueChangedCallback(
|
|
1000
|
+
(EventCallback<ChangeEvent<float>>)definition.cycleOffsetField.userData
|
|
1001
|
+
);
|
|
739
1002
|
|
|
740
|
-
|
|
1003
|
+
definition.nameField = tags.nameField;
|
|
1004
|
+
definition.startIndexField = tags.startIndexField;
|
|
1005
|
+
definition.endIndexField = tags.endIndexField;
|
|
1006
|
+
definition.defaultFrameRateField = tags.defaultFrameRateField;
|
|
1007
|
+
definition.frameRateCurveField = tags.frameRateCurveField;
|
|
1008
|
+
definition.spriteCountLabel = tags.spriteCountLabel;
|
|
1009
|
+
definition.removeButton = tags.removeButton;
|
|
1010
|
+
definition.previewButton = tags.previewButton;
|
|
1011
|
+
definition.loopingField = tags.looping;
|
|
1012
|
+
definition.cycleOffsetField = tags.cycleOffset;
|
|
1013
|
+
|
|
1014
|
+
definition.nameField.SetValueWithoutNotify(definition.Name);
|
|
741
1015
|
EventCallback<ChangeEvent<string>> nameChangeCallback = evt =>
|
|
742
1016
|
{
|
|
743
|
-
|
|
1017
|
+
definition.Name = evt.newValue;
|
|
744
1018
|
};
|
|
745
|
-
|
|
746
|
-
|
|
1019
|
+
definition.nameField.RegisterValueChangedCallback(nameChangeCallback);
|
|
1020
|
+
definition.nameField.userData = nameChangeCallback;
|
|
747
1021
|
|
|
748
|
-
|
|
1022
|
+
definition.startIndexField.SetValueWithoutNotify(definition.StartSpriteIndex);
|
|
749
1023
|
EventCallback<ChangeEvent<int>> startChangeCallback = evt =>
|
|
750
1024
|
{
|
|
751
|
-
|
|
1025
|
+
definition.StartSpriteIndex = Mathf.Clamp(
|
|
752
1026
|
evt.newValue,
|
|
753
1027
|
0,
|
|
754
1028
|
_availableSprites.Count > 0 ? _availableSprites.Count - 1 : 0
|
|
755
1029
|
);
|
|
756
|
-
if (
|
|
1030
|
+
if (
|
|
1031
|
+
definition.StartSpriteIndex > definition.EndSpriteIndex
|
|
1032
|
+
&& 0 < _availableSprites.Count
|
|
1033
|
+
)
|
|
757
1034
|
{
|
|
758
|
-
|
|
1035
|
+
definition.EndSpriteIndex = definition.StartSpriteIndex;
|
|
759
1036
|
}
|
|
760
1037
|
|
|
761
|
-
|
|
762
|
-
UpdateSpritesForDefinition(
|
|
1038
|
+
definition.startIndexField.SetValueWithoutNotify(definition.StartSpriteIndex);
|
|
1039
|
+
UpdateSpritesForDefinition(definition);
|
|
763
1040
|
if (_currentPreviewAnimDefIndex == index)
|
|
764
1041
|
{
|
|
765
|
-
StartOrUpdateCurrentPreview(
|
|
1042
|
+
StartOrUpdateCurrentPreview(definition);
|
|
766
1043
|
}
|
|
767
1044
|
};
|
|
768
|
-
|
|
769
|
-
|
|
1045
|
+
definition.startIndexField.RegisterValueChangedCallback(startChangeCallback);
|
|
1046
|
+
definition.startIndexField.userData = startChangeCallback;
|
|
770
1047
|
|
|
771
|
-
|
|
1048
|
+
definition.endIndexField.SetValueWithoutNotify(definition.EndSpriteIndex);
|
|
772
1049
|
EventCallback<ChangeEvent<int>> endChangeCallback = evt =>
|
|
773
1050
|
{
|
|
774
|
-
|
|
1051
|
+
definition.EndSpriteIndex = Mathf.Clamp(
|
|
775
1052
|
evt.newValue,
|
|
776
1053
|
0,
|
|
777
1054
|
_availableSprites.Count > 0 ? _availableSprites.Count - 1 : 0
|
|
778
1055
|
);
|
|
779
|
-
if (
|
|
1056
|
+
if (
|
|
1057
|
+
definition.EndSpriteIndex < definition.StartSpriteIndex
|
|
1058
|
+
&& 0 < _availableSprites.Count
|
|
1059
|
+
)
|
|
780
1060
|
{
|
|
781
|
-
|
|
1061
|
+
definition.StartSpriteIndex = definition.EndSpriteIndex;
|
|
782
1062
|
}
|
|
783
1063
|
|
|
784
|
-
|
|
785
|
-
UpdateSpritesForDefinition(
|
|
1064
|
+
definition.endIndexField.SetValueWithoutNotify(definition.EndSpriteIndex);
|
|
1065
|
+
UpdateSpritesForDefinition(definition);
|
|
786
1066
|
if (_currentPreviewAnimDefIndex == index)
|
|
787
1067
|
{
|
|
788
|
-
StartOrUpdateCurrentPreview(
|
|
1068
|
+
StartOrUpdateCurrentPreview(definition);
|
|
789
1069
|
}
|
|
790
1070
|
};
|
|
791
|
-
|
|
792
|
-
|
|
1071
|
+
definition.endIndexField.RegisterValueChangedCallback(endChangeCallback);
|
|
1072
|
+
definition.endIndexField.userData = endChangeCallback;
|
|
793
1073
|
|
|
794
|
-
|
|
1074
|
+
definition.defaultFrameRateField.SetValueWithoutNotify(definition.DefaultFrameRate);
|
|
795
1075
|
EventCallback<ChangeEvent<float>> fpsChangeCallback = evt =>
|
|
796
1076
|
{
|
|
797
|
-
|
|
798
|
-
|
|
1077
|
+
definition.DefaultFrameRate = Mathf.Max(0.1f, evt.newValue);
|
|
1078
|
+
definition.defaultFrameRateField.SetValueWithoutNotify(definition.DefaultFrameRate);
|
|
799
1079
|
|
|
800
|
-
if (IsCurveConstant(
|
|
1080
|
+
if (IsCurveConstant(definition.FrameRateCurve))
|
|
801
1081
|
{
|
|
802
|
-
|
|
803
|
-
|
|
1082
|
+
definition.FrameRateCurve = AnimationCurve.Constant(
|
|
1083
|
+
0,
|
|
1084
|
+
1,
|
|
1085
|
+
definition.DefaultFrameRate
|
|
1086
|
+
);
|
|
1087
|
+
definition.frameRateCurveField.SetValueWithoutNotify(definition.FrameRateCurve);
|
|
804
1088
|
}
|
|
805
1089
|
if (_currentPreviewAnimDefIndex == index)
|
|
806
1090
|
{
|
|
807
|
-
StartOrUpdateCurrentPreview(
|
|
1091
|
+
StartOrUpdateCurrentPreview(definition);
|
|
808
1092
|
}
|
|
809
1093
|
};
|
|
810
|
-
|
|
811
|
-
|
|
1094
|
+
definition.defaultFrameRateField.RegisterValueChangedCallback(fpsChangeCallback);
|
|
1095
|
+
definition.defaultFrameRateField.userData = fpsChangeCallback;
|
|
812
1096
|
|
|
813
|
-
|
|
1097
|
+
definition.frameRateCurveField.SetValueWithoutNotify(definition.FrameRateCurve);
|
|
814
1098
|
EventCallback<ChangeEvent<AnimationCurve>> curveChangeCallback = evt =>
|
|
815
1099
|
{
|
|
816
|
-
|
|
1100
|
+
definition.FrameRateCurve = evt.newValue;
|
|
817
1101
|
if (_currentPreviewAnimDefIndex == index)
|
|
818
1102
|
{
|
|
819
|
-
StartOrUpdateCurrentPreview(
|
|
1103
|
+
StartOrUpdateCurrentPreview(definition);
|
|
820
1104
|
}
|
|
821
1105
|
};
|
|
822
|
-
|
|
823
|
-
|
|
1106
|
+
definition.frameRateCurveField.RegisterValueChangedCallback(curveChangeCallback);
|
|
1107
|
+
definition.frameRateCurveField.userData = curveChangeCallback;
|
|
824
1108
|
|
|
825
1109
|
Action removeAction = () => RemoveAnimationDefinition(index);
|
|
826
|
-
|
|
827
|
-
|
|
1110
|
+
definition.removeButton.clicked += removeAction;
|
|
1111
|
+
definition.removeButton.userData = removeAction;
|
|
828
1112
|
|
|
829
1113
|
Action previewAction = () =>
|
|
830
1114
|
{
|
|
831
1115
|
_currentPreviewAnimDefIndex = index;
|
|
832
|
-
StartOrUpdateCurrentPreview(
|
|
1116
|
+
StartOrUpdateCurrentPreview(definition);
|
|
1117
|
+
};
|
|
1118
|
+
definition.previewButton.clicked += previewAction;
|
|
1119
|
+
definition.previewButton.userData = previewAction;
|
|
1120
|
+
|
|
1121
|
+
EventCallback<ChangeEvent<bool>> loopingChangeCallback = evt =>
|
|
1122
|
+
{
|
|
1123
|
+
definition.loop = evt.newValue;
|
|
833
1124
|
};
|
|
834
|
-
def.previewButton.clicked += previewAction;
|
|
835
|
-
def.previewButton.userData = previewAction;
|
|
836
1125
|
|
|
837
|
-
|
|
1126
|
+
definition.loopingField.RegisterValueChangedCallback(loopingChangeCallback);
|
|
1127
|
+
definition.loopingField.userData = loopingChangeCallback;
|
|
1128
|
+
|
|
1129
|
+
EventCallback<ChangeEvent<float>> cycleOffsetChangeCallback = evt =>
|
|
1130
|
+
{
|
|
1131
|
+
definition.cycleOffset = evt.newValue;
|
|
1132
|
+
};
|
|
1133
|
+
definition.cycleOffsetField.RegisterValueChangedCallback(cycleOffsetChangeCallback);
|
|
1134
|
+
definition.cycleOffsetField.userData = cycleOffsetChangeCallback;
|
|
1135
|
+
|
|
1136
|
+
UpdateSpritesForDefinition(definition);
|
|
838
1137
|
}
|
|
839
1138
|
|
|
840
1139
|
private static bool IsCurveConstant(AnimationCurve curve)
|
|
@@ -880,18 +1179,35 @@
|
|
|
880
1179
|
|
|
881
1180
|
private void AddAnimationDefinition()
|
|
882
1181
|
{
|
|
883
|
-
AnimationDefinition
|
|
1182
|
+
AnimationDefinition newDefinition = new();
|
|
884
1183
|
if (_selectedSpriteSheet != null)
|
|
885
1184
|
{
|
|
886
|
-
|
|
1185
|
+
newDefinition.Name =
|
|
1186
|
+
$"{_selectedSpriteSheet.name}_Anim_{_animationDefinitions.Count}";
|
|
887
1187
|
}
|
|
888
1188
|
if (0 < _availableSprites.Count)
|
|
889
1189
|
{
|
|
890
|
-
|
|
1190
|
+
if (0 < _animationDefinitions.Count)
|
|
1191
|
+
{
|
|
1192
|
+
int nextStartIndex = _animationDefinitions[^1].EndSpriteIndex + 1;
|
|
1193
|
+
if (_availableSprites.Count - 1 < nextStartIndex)
|
|
1194
|
+
{
|
|
1195
|
+
nextStartIndex = 0;
|
|
1196
|
+
}
|
|
1197
|
+
newDefinition.StartSpriteIndex = nextStartIndex;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
newDefinition.EndSpriteIndex = _availableSprites.Count - 1;
|
|
891
1201
|
}
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
1202
|
+
newDefinition.FrameRateCurve = AnimationCurve.Constant(
|
|
1203
|
+
0,
|
|
1204
|
+
1,
|
|
1205
|
+
newDefinition.DefaultFrameRate
|
|
1206
|
+
);
|
|
1207
|
+
_animationDefinitions.Add(newDefinition);
|
|
1208
|
+
_currentPreviewAnimDefIndex = _animationDefinitions.Count - 1;
|
|
1209
|
+
StartOrUpdateCurrentPreview(newDefinition);
|
|
1210
|
+
UpdateSpritesForDefinition(newDefinition);
|
|
895
1211
|
_animationDefinitionsListView.Rebuild();
|
|
896
1212
|
}
|
|
897
1213
|
|
|
@@ -1068,12 +1384,17 @@
|
|
|
1068
1384
|
Directory.CreateDirectory(animationsFolder);
|
|
1069
1385
|
}
|
|
1070
1386
|
|
|
1387
|
+
if (!animationsFolder.StartsWith("Assets", StringComparison.OrdinalIgnoreCase))
|
|
1388
|
+
{
|
|
1389
|
+
animationsFolder = DirectoryHelper.AbsoluteToUnityRelativePath(animationsFolder);
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1071
1392
|
int createdCount = 0;
|
|
1072
|
-
foreach (AnimationDefinition
|
|
1393
|
+
foreach (AnimationDefinition definition in _animationDefinitions)
|
|
1073
1394
|
{
|
|
1074
|
-
if (
|
|
1395
|
+
if (definition.SpritesToAnimate.Count == 0)
|
|
1075
1396
|
{
|
|
1076
|
-
|
|
1397
|
+
this.LogWarn($"Skipping animation '{definition.Name}' as it has no sprites.");
|
|
1077
1398
|
continue;
|
|
1078
1399
|
}
|
|
1079
1400
|
|
|
@@ -1087,21 +1408,21 @@
|
|
|
1087
1408
|
};
|
|
1088
1409
|
|
|
1089
1410
|
ObjectReferenceKeyframe[] keyframes = new ObjectReferenceKeyframe[
|
|
1090
|
-
|
|
1411
|
+
definition.SpritesToAnimate.Count
|
|
1091
1412
|
];
|
|
1092
1413
|
float currentTime = 0f;
|
|
1093
|
-
AnimationCurve curve =
|
|
1414
|
+
AnimationCurve curve = definition.FrameRateCurve;
|
|
1094
1415
|
if (curve == null || curve.keys.Length == 0)
|
|
1095
1416
|
{
|
|
1096
|
-
|
|
1097
|
-
$"Animation '{
|
|
1417
|
+
this.LogWarn(
|
|
1418
|
+
$"Animation '{definition.Name}' has an invalid FrameRateCurve. Falling back to DefaultFrameRate."
|
|
1098
1419
|
);
|
|
1099
|
-
curve = AnimationCurve.Constant(0, 1,
|
|
1420
|
+
curve = AnimationCurve.Constant(0, 1, definition.DefaultFrameRate);
|
|
1100
1421
|
}
|
|
1101
1422
|
|
|
1102
1423
|
if (curve.keys.Length == 0)
|
|
1103
1424
|
{
|
|
1104
|
-
curve.AddKey(0,
|
|
1425
|
+
curve.AddKey(0, definition.DefaultFrameRate);
|
|
1105
1426
|
}
|
|
1106
1427
|
|
|
1107
1428
|
float curveDuration = curve.keys.LastOrDefault().time;
|
|
@@ -1110,26 +1431,26 @@
|
|
|
1110
1431
|
curveDuration = 1f;
|
|
1111
1432
|
}
|
|
1112
1433
|
|
|
1113
|
-
for (int i = 0; i <
|
|
1434
|
+
for (int i = 0; i < definition.SpritesToAnimate.Count; ++i)
|
|
1114
1435
|
{
|
|
1115
1436
|
keyframes[i] = new ObjectReferenceKeyframe
|
|
1116
1437
|
{
|
|
1117
1438
|
time = currentTime,
|
|
1118
|
-
value =
|
|
1439
|
+
value = definition.SpritesToAnimate[i],
|
|
1119
1440
|
};
|
|
1120
1441
|
|
|
1121
|
-
if (i <
|
|
1442
|
+
if (i < definition.SpritesToAnimate.Count - 1)
|
|
1122
1443
|
{
|
|
1123
1444
|
float normalizedTimeForCurve =
|
|
1124
|
-
|
|
1125
|
-
? (float)i / (
|
|
1445
|
+
definition.SpritesToAnimate.Count > 1
|
|
1446
|
+
? (float)i / (definition.SpritesToAnimate.Count - 1)
|
|
1126
1447
|
: 0;
|
|
1127
1448
|
float timeForCurveEval = normalizedTimeForCurve * curveDuration;
|
|
1128
1449
|
|
|
1129
1450
|
float fps = curve.Evaluate(timeForCurveEval);
|
|
1130
1451
|
if (fps <= 0)
|
|
1131
1452
|
{
|
|
1132
|
-
fps =
|
|
1453
|
+
fps = definition.DefaultFrameRate;
|
|
1133
1454
|
}
|
|
1134
1455
|
|
|
1135
1456
|
if (fps <= 0)
|
|
@@ -1144,15 +1465,16 @@
|
|
|
1144
1465
|
AnimationUtility.SetObjectReferenceCurve(clip, spriteBinding, keyframes);
|
|
1145
1466
|
|
|
1146
1467
|
AnimationClipSettings settings = AnimationUtility.GetAnimationClipSettings(clip);
|
|
1147
|
-
settings.loopTime =
|
|
1468
|
+
settings.loopTime = definition.loop;
|
|
1469
|
+
settings.cycleOffset = definition.cycleOffset;
|
|
1148
1470
|
AnimationUtility.SetAnimationClipSettings(clip, settings);
|
|
1149
1471
|
|
|
1150
|
-
string animName = string.IsNullOrEmpty(
|
|
1472
|
+
string animName = string.IsNullOrEmpty(definition.Name)
|
|
1473
|
+
? "UnnamedAnim"
|
|
1474
|
+
: definition.Name;
|
|
1151
1475
|
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
animName = animName.Replace(character, '_');
|
|
1155
|
-
}
|
|
1476
|
+
animName = Path.GetInvalidFileNameChars()
|
|
1477
|
+
.Aggregate(animName, (current, character) => current.Replace(character, '_'));
|
|
1156
1478
|
string assetPath = Path.Combine(animationsFolder, $"{animName}.anim");
|
|
1157
1479
|
assetPath = AssetDatabase.GenerateUniqueAssetPath(assetPath);
|
|
1158
1480
|
|
|
@@ -1169,9 +1491,6 @@
|
|
|
1169
1491
|
$"{createdCount} animation(s) created in:\n{animationsFolder}",
|
|
1170
1492
|
"OK"
|
|
1171
1493
|
);
|
|
1172
|
-
EditorGUIUtility.PingObject(
|
|
1173
|
-
AssetDatabase.LoadAssetAtPath<Object>(animationsFolder)
|
|
1174
|
-
);
|
|
1175
1494
|
}
|
|
1176
1495
|
else
|
|
1177
1496
|
{
|