/****************************************************************************** * Spine Runtimes Software License v2.5 * * Copyright (c) 2013-2016, Esoteric Software * All rights reserved. * * You are granted a perpetual, non-exclusive, non-sublicensable, and * non-transferable license to use, install, execute, and perform the Spine * Runtimes software and derivative works solely for personal or internal * use. Without the written permission of Esoteric Software (see Section 2 of * the Spine Software License Agreement), you may not (a) modify, translate, * adapt, or develop new applications using the Spine Runtimes or otherwise * create derivative works or improvements of the Spine Runtimes or (b) remove, * delete, alter, or obscure any trademarks or any copyright, trademark, patent, * or other intellectual property or proprietary rights notices on or in the * Software, including any copy thereof. Redistributions in binary or source * form must include this license and terms. * * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "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 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 THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. *****************************************************************************/ using System.Collections.Generic; using UnityEngine; namespace Spine.Unity.Examples { // This is an example of an animation handle. This is implemented with strings as state names. // Strings can serve as the identifier when Mecanim is used as the state machine and state source. // If you don't use Mecanim, using custom ScriptableObjects may be a more efficient way to store information about the state and its connection with specific Spine animations. // This animation handle implementation also comes with a dummy implementation of transition-handling. public class SkeletonAnimationHandleExample : MonoBehaviour { public SkeletonAnimation skeletonAnimation; public List statesAndAnimations = new List(); public List transitions = new List(); // Alternately, an AnimationPair-Animation Dictionary (commented out) can be used for more efficient lookups. [System.Serializable] public class StateNameToAnimationReference { public string stateName; public AnimationReferenceAsset animation; } [System.Serializable] public class AnimationTransition { public AnimationReferenceAsset from; public AnimationReferenceAsset to; public AnimationReferenceAsset transition; } //readonly Dictionary transitionDictionary = new Dictionary(Spine.AnimationStateData.AnimationPairComparer.Instance); public Spine.Animation TargetAnimation { get; private set; } void Awake () { // Initialize AnimationReferenceAssets foreach (var entry in statesAndAnimations) { entry.animation.Initialize(); } foreach (var entry in transitions) { entry.from.Initialize(); entry.to.Initialize(); entry.transition.Initialize(); } // Build Dictionary //foreach (var entry in transitions) { // transitionDictionary.Add(new AnimationStateData.AnimationPair(entry.from.Animation, entry.to.Animation), entry.transition.Animation); //} } /// Sets the horizontal flip state of the skeleton based on a nonzero float. If negative, the skeleton is flipped. If positive, the skeleton is not flipped. public void SetFlip (float horizontal) { if (horizontal != 0) { skeletonAnimation.Skeleton.ScaleX = horizontal > 0 ? 1f : -1f; } } /// Plays an animation based on the state name. public void PlayAnimationForState (string stateShortName, int layerIndex) { PlayAnimationForState(StringToHash(stateShortName), layerIndex); } /// Plays an animation based on the hash of the state name. public void PlayAnimationForState (int shortNameHash, int layerIndex) { var foundAnimation = GetAnimationForState(shortNameHash); if (foundAnimation == null) return; PlayNewAnimation(foundAnimation, layerIndex); } /// Gets a Spine Animation based on the state name. public Spine.Animation GetAnimationForState (string stateShortName) { return GetAnimationForState(StringToHash(stateShortName)); } /// Gets a Spine Animation based on the hash of the state name. public Spine.Animation GetAnimationForState (int shortNameHash) { var foundState = statesAndAnimations.Find(entry => StringToHash(entry.stateName) == shortNameHash); return (foundState == null) ? null : foundState.animation; } /// Play an animation. If a transition animation is defined, the transition is played before the target animation being passed. public void PlayNewAnimation (Spine.Animation target, int layerIndex) { Spine.Animation transition = null; Spine.Animation current = null; current = GetCurrentAnimation(layerIndex); if (current != null) transition = TryGetTransition(current, target); if (transition != null) { skeletonAnimation.AnimationState.SetAnimation(layerIndex, transition, false); skeletonAnimation.AnimationState.AddAnimation(layerIndex, target, true, 0f); } else { skeletonAnimation.AnimationState.SetAnimation(layerIndex, target, true); } this.TargetAnimation = target; } /// Play a non-looping animation once then continue playing the state animation. public void PlayOneShot (Spine.Animation oneShot, int layerIndex) { var state = skeletonAnimation.AnimationState; state.SetAnimation(0, oneShot, false); var transition = TryGetTransition(oneShot, TargetAnimation); if (transition != null) state.AddAnimation(0, transition, false, 0f); state.AddAnimation(0, this.TargetAnimation, true, 0f); } Spine.Animation TryGetTransition (Spine.Animation from, Spine.Animation to) { foreach (var transition in transitions) { if (transition.from.Animation == from && transition.to.Animation == to) { return transition.transition.Animation; } } return null; //Spine.Animation foundTransition = null; //transitionDictionary.TryGetValue(new AnimationStateData.AnimationPair(from, to), out foundTransition); //return foundTransition; } Spine.Animation GetCurrentAnimation (int layerIndex) { var currentTrackEntry = skeletonAnimation.AnimationState.GetCurrent(layerIndex); return (currentTrackEntry != null) ? currentTrackEntry.Animation : null; } int StringToHash (string s) { return Animator.StringToHash(s); } } }