123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- /******************************************************************************
- * Spine Runtimes License Agreement
- * Last updated January 1, 2020. Replaces all prior versions.
- *
- * Copyright (c) 2013-2020, Esoteric Software LLC
- *
- * Integration of the Spine Runtimes into software or otherwise creating
- * derivative works of the Spine Runtimes is permitted under the terms and
- * conditions of Section 2 of the Spine Editor License Agreement:
- * http://esotericsoftware.com/spine-editor-license
- *
- * Otherwise, it is permitted to integrate the Spine Runtimes into software
- * or otherwise create derivative works of the Spine Runtimes (collectively,
- * "Products"), provided that each user of the Products must obtain their own
- * Spine Editor license and redistribution of the Products in any form must
- * include this license and copyright notice.
- *
- * THE SPINE RUNTIMES ARE PROVIDED BY ESOTERIC SOFTWARE LLC "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL ESOTERIC SOFTWARE LLC BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES,
- * BUSINESS INTERRUPTION, OR LOSS OF USE, DATA, OR PROFITS) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *****************************************************************************/
- using Spine;
- using Spine.Unity;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- namespace Spine.Unity.Examples {
- //[CreateAssetMenu(menuName = "Spine/SkeletonData Modifiers/Animation Match", order = 200)]
- public class AnimationMatchModifierAsset : SkeletonDataModifierAsset {
- public bool matchAllAnimations = true;
- public override void Apply (SkeletonData skeletonData) {
- if (matchAllAnimations)
- AnimationTools.MatchAnimationTimelines(skeletonData.Animations, skeletonData);
- }
- public static class AnimationTools {
- #region Filler Timelines
- /// <summary>
- /// Matches the animation timelines across the given set of animations.
- /// This allows unkeyed properties to assume setup pose when animations are naively mixed using Animation.Apply.
- /// </summary>
- /// <param name="animations">An enumerable collection animations whose timelines will be matched.</param>
- /// <param name="skeletonData">The SkeletonData where the animations belong.</param>
- public static void MatchAnimationTimelines (IEnumerable<Spine.Animation> animations, SkeletonData skeletonData) {
- if (animations == null) return;
- if (skeletonData == null) throw new System.ArgumentNullException("skeletonData", "Timelines can't be matched without a SkeletonData source.");
- // Build a reference collection of timelines to match
- // and a collection of dummy timelines that can be used to fill-in missing items.
- var timelineDictionary = new Dictionary<string, Spine.Timeline>();
- foreach (var animation in animations) {
- foreach (var timeline in animation.Timelines) {
- if (timeline is EventTimeline) continue;
- foreach (string propertyId in timeline.PropertyIds) {
- if (!timelineDictionary.ContainsKey(propertyId)) {
- timelineDictionary.Add(propertyId, GetFillerTimeline(timeline, skeletonData));
- }
- }
- }
- }
- var idsToMatch = new List<string>(timelineDictionary.Keys);
- // For each animation in the list, check for and add missing timelines.
- var currentAnimationIDs = new HashSet<string>();
- foreach (var animation in animations) {
- currentAnimationIDs.Clear();
- foreach (var timeline in animation.Timelines) {
- if (timeline is EventTimeline) continue;
- foreach (string propertyId in timeline.PropertyIds) {
- currentAnimationIDs.Add(propertyId);
- }
- }
- var animationTimelines = animation.Timelines;
- foreach (string propertyId in idsToMatch) {
- if (!currentAnimationIDs.Contains(propertyId))
- animationTimelines.Add(timelineDictionary[propertyId]);
- }
- }
- // These are locals, but sometimes Unity's GC does weird stuff. So let's clean up.
- timelineDictionary.Clear();
- timelineDictionary = null;
- idsToMatch.Clear();
- idsToMatch = null;
- currentAnimationIDs.Clear();
- currentAnimationIDs = null;
- }
- static Timeline GetFillerTimeline (Timeline timeline, SkeletonData skeletonData) {
- if (timeline is RotateTimeline)
- return GetFillerTimeline((RotateTimeline)timeline, skeletonData);
- if (timeline is TranslateTimeline)
- return GetFillerTimeline((TranslateTimeline)timeline, skeletonData);
- if (timeline is ScaleTimeline)
- return GetFillerTimeline((ScaleTimeline)timeline, skeletonData);
- if (timeline is ShearTimeline)
- return GetFillerTimeline((ShearTimeline)timeline, skeletonData);
- if (timeline is AttachmentTimeline)
- return GetFillerTimeline((AttachmentTimeline)timeline, skeletonData);
- if (timeline is RGBATimeline)
- return GetFillerTimeline((RGBATimeline)timeline, skeletonData);
- if (timeline is RGBA2Timeline)
- return GetFillerTimeline((RGBA2Timeline)timeline, skeletonData);
- if (timeline is DeformTimeline)
- return GetFillerTimeline((DeformTimeline)timeline, skeletonData);
- if (timeline is DrawOrderTimeline)
- return GetFillerTimeline((DrawOrderTimeline)timeline, skeletonData);
- if (timeline is IkConstraintTimeline)
- return GetFillerTimeline((IkConstraintTimeline)timeline, skeletonData);
- if (timeline is TransformConstraintTimeline)
- return GetFillerTimeline((TransformConstraintTimeline)timeline, skeletonData);
- if (timeline is PathConstraintPositionTimeline)
- return GetFillerTimeline((PathConstraintPositionTimeline)timeline, skeletonData);
- if (timeline is PathConstraintSpacingTimeline)
- return GetFillerTimeline((PathConstraintSpacingTimeline)timeline, skeletonData);
- if (timeline is PathConstraintMixTimeline)
- return GetFillerTimeline((PathConstraintMixTimeline)timeline, skeletonData);
- return null;
- }
- static RotateTimeline GetFillerTimeline (RotateTimeline timeline, SkeletonData skeletonData) {
- var t = new RotateTimeline(1, 0, timeline.BoneIndex);
- t.SetFrame(0, 0, 0);
- return t;
- }
- static TranslateTimeline GetFillerTimeline (TranslateTimeline timeline, SkeletonData skeletonData) {
- var t = new TranslateTimeline(1, 0, timeline.BoneIndex);
- t.SetFrame(0, 0, 0, 0);
- return t;
- }
- static ScaleTimeline GetFillerTimeline (ScaleTimeline timeline, SkeletonData skeletonData) {
- var t = new ScaleTimeline(1, 0, timeline.BoneIndex);
- t.SetFrame(0, 0, 0, 0);
- return t;
- }
- static ShearTimeline GetFillerTimeline (ShearTimeline timeline, SkeletonData skeletonData) {
- var t = new ShearTimeline(1, 0, timeline.BoneIndex);
- t.SetFrame(0, 0, 0, 0);
- return t;
- }
- static AttachmentTimeline GetFillerTimeline (AttachmentTimeline timeline, SkeletonData skeletonData) {
- var t = new AttachmentTimeline(1, timeline.SlotIndex);
- var slotData = skeletonData.Slots.Items[t.SlotIndex];
- t.SetFrame(0, 0, slotData.AttachmentName);
- return t;
- }
- static RGBATimeline GetFillerTimeline (RGBATimeline timeline, SkeletonData skeletonData) {
- var t = new RGBATimeline(1, 0, timeline.SlotIndex);
- var slotData = skeletonData.Slots.Items[t.SlotIndex];
- t.SetFrame(0, 0, slotData.R, slotData.G, slotData.B, slotData.A);
- return t;
- }
- static RGBA2Timeline GetFillerTimeline (RGBA2Timeline timeline, SkeletonData skeletonData) {
- var t = new RGBA2Timeline(1, 0, timeline.SlotIndex);
- var slotData = skeletonData.Slots.Items[t.SlotIndex];
- t.SetFrame(0, 0, slotData.R, slotData.G, slotData.B, slotData.A, slotData.R2, slotData.G2, slotData.B2);
- return t;
- }
- static DeformTimeline GetFillerTimeline (DeformTimeline timeline, SkeletonData skeletonData) {
- var t = new DeformTimeline(1, 0, timeline.SlotIndex, timeline.Attachment);
- if (t.Attachment.IsWeighted()) {
- t.SetFrame(0, 0, new float[t.Attachment.Vertices.Length]);
- } else {
- t.SetFrame(0, 0, t.Attachment.Vertices.Clone() as float[]);
- }
- return t;
- }
- static DrawOrderTimeline GetFillerTimeline (DrawOrderTimeline timeline, SkeletonData skeletonData) {
- var t = new DrawOrderTimeline(1);
- t.SetFrame(0, 0, null); // null means use setup pose in DrawOrderTimeline.Apply.
- return t;
- }
- static IkConstraintTimeline GetFillerTimeline (IkConstraintTimeline timeline, SkeletonData skeletonData) {
- var t = new IkConstraintTimeline(1, 0, timeline.IkConstraintIndex);
- var ikConstraintData = skeletonData.IkConstraints.Items[timeline.IkConstraintIndex];
- t.SetFrame(0, 0, ikConstraintData.Mix, ikConstraintData.Softness, ikConstraintData.BendDirection, ikConstraintData.Compress, ikConstraintData.Stretch);
- return t;
- }
- static TransformConstraintTimeline GetFillerTimeline (TransformConstraintTimeline timeline, SkeletonData skeletonData) {
- var t = new TransformConstraintTimeline(1, 0, timeline.TransformConstraintIndex);
- var data = skeletonData.TransformConstraints.Items[timeline.TransformConstraintIndex];
- t.SetFrame(0, 0, data.MixRotate, data.MixX, data.MixY, data.MixScaleX, data.MixScaleY, data.MixShearY);
- return t;
- }
- static PathConstraintPositionTimeline GetFillerTimeline (PathConstraintPositionTimeline timeline, SkeletonData skeletonData) {
- var t = new PathConstraintPositionTimeline(1, 0, timeline.PathConstraintIndex);
- var data = skeletonData.PathConstraints.Items[timeline.PathConstraintIndex];
- t.SetFrame(0, 0, data.Position);
- return t;
- }
- static PathConstraintSpacingTimeline GetFillerTimeline (PathConstraintSpacingTimeline timeline, SkeletonData skeletonData) {
- var t = new PathConstraintSpacingTimeline(1, 0, timeline.PathConstraintIndex);
- var data = skeletonData.PathConstraints.Items[timeline.PathConstraintIndex];
- t.SetFrame(0, 0, data.Spacing);
- return t;
- }
- static PathConstraintMixTimeline GetFillerTimeline (PathConstraintMixTimeline timeline, SkeletonData skeletonData) {
- var t = new PathConstraintMixTimeline(1, 0, timeline.PathConstraintIndex);
- var data = skeletonData.PathConstraints.Items[timeline.PathConstraintIndex];
- t.SetFrame(0, 0, data.RotateMix, data.MixX, data.MixY);
- return t;
- }
- #endregion
- }
- }
- }
|