private void OnRenderAnimationSet(Camera camera, Spine3DAnimationSet animationSet) { if (!_renderedAnimationSet) { _lastRenderedAnimationSet = animationSet; } }
public override void ProcessFrame(Playable playable, FrameData info, object playerData) { if (_trackBinding != null && _animationStates != null) { for (int i = 0; i < _animationStates.Length; i++) { Spine3DAnimationSet animationSet = _trackBinding._renderer._animationSets[i]; ApplyChannelsToState(animationSet, _animationStates[i]); } #if UNITY_EDITOR if (!Application.isPlaying) { ApplyInEditor(); } else #endif { for (int i = 0; i < _animationStates.Length; i++) { SpineAnimator spineAnimator = _trackBinding._renderer._animationSets[i]._animatior; _animationStates[i].Apply(spineAnimator.GetSkeletonAnimation().Skeleton); } } } }
private void PlayAnimation(Spine3DAnimationSet animationSet, AnimationState animationState, TrackEntry[] trackEntries, int trackIndex, ChannelAnimationData animation) { //Proxy Animation if (animation._proxyAnimation != null) { //Valid for this animation set (matches orientations) if ((animationSet._orientation & animation._proxyAnimationOrientations) != 0) { TrackEntry trackEntry = trackEntries[trackIndex]; if (trackEntry == null || trackEntry.Animation != animation._proxyAnimation) { animationState.ClearTrack(trackIndex); trackEntry = animationState.SetAnimation(trackIndex, animation._proxyAnimation, true); } if (trackEntry != null) { trackEntry.TrackTime = animation._animationTime * animation._animationSpeed; trackEntry.Alpha = animation._animationWeight; trackEntry.TimeScale = animation._animationSpeed; } } else { animationState.ClearTrack(trackIndex); } } //Normal animation else if (!string.IsNullOrEmpty(animation._animationId)) { string animationId = _trackBinding.GetAnimNameForAnimationSet(animationSet, animation._animationId); TrackEntry trackEntry = trackEntries[trackIndex]; if (trackEntry == null || trackEntry.Animation == null || trackEntry.Animation.Name != animationId) { animationState.ClearTrack(trackIndex); Animation anim = animationState.Data.SkeletonData.FindAnimation(animationId); if (anim != null) { trackEntry = animationState.SetAnimation(trackIndex, anim, true); } } if (trackEntry != null) { trackEntry.TrackTime = animation._animationTime * animation._animationSpeed; trackEntry.Alpha = animation._animationWeight; trackEntry.TimeScale = animation._animationSpeed; } } //Nothing playing else { animationState.ClearTrack(trackIndex); } }
public string GetAnimNameForAnimationSet(Spine3DAnimationSet animationSet, string animName) { if (!string.IsNullOrEmpty(animationSet._animationPrefix)) { SpineAnimator childAnimator = animationSet._animatior; string fullAnimName = animName + animationSet._animationPrefix; if (childAnimator.DoesAnimationExist(fullAnimName)) { return(fullAnimName); } } return(animName); }
private void OnSkeletonRebuild(SkeletonRenderer skeletonRenderer) { if (_onRebuildSkeleton != null) { Spine3DAnimationSet animationSet = null; for (int i = 0; i < _animationSets.Length; i++) { if (_animationSets[i]._animatior.GetSkeletonAnimation() == skeletonRenderer) { animationSet = _animationSets[i]; break; } } _onRebuildSkeleton.Invoke(animationSet); } }
private void ApplyChannelsToState(Spine3DAnimationSet animationSet, AnimationState animationState) { //First work out how many track entries are needed int numTrackEntries = 0; foreach (ChannelData channelData in _channelData) { numTrackEntries++; numTrackEntries += channelData._backgroundAnimations.Length; } //Grow to new amount if needed animationState.Tracks.GrowIfNeeded(numTrackEntries); TrackEntry[] trackEntries = animationState.Tracks.Items; //Ensure animations are playing at correct times / weights int trackIndex = 0; foreach (ChannelData channelData in _channelData) { for (int i = 0; i < channelData._backgroundAnimations.Length; i++) { PlayAnimation(animationSet, animationState, trackEntries, trackIndex, channelData._backgroundAnimations[i]); trackIndex++; } PlayAnimation(animationSet, animationState, trackEntries, trackIndex, channelData._primaryAnimation); trackIndex++; } //Clear unused tracks for (; trackIndex < trackEntries.Length; trackIndex++) { animationState.ClearTrack(trackIndex); } }
public void SetAnimationSetForCamera(Camera camera) { //Work out angle between character face direction and camera forward. //Choose a animation set based on horizontal angle between camera forward and character forward Transform graphicsOrigin = _graphicsOrigin; if (graphicsOrigin == null) { graphicsOrigin = this.transform; } //Convert camera pos and forward into character space Vector3 localspaceCameraPos = _graphicsOrigin.InverseTransformPoint(camera.transform.position); Vector3 localspaceCameraDir = _graphicsOrigin.InverseTransformDirection(-camera.transform.forward); //Get forward in XY space Vector2 localspaceCameraDirXY = new Vector2(localspaceCameraDir.x, localspaceCameraDir.z).normalized; Vector2 forwardXY = Vector2.up; //The angle between camera forward and character forward float horizAngle = MathUtils.AngleBetween(forwardXY, localspaceCameraDirXY); //Work out which animations to use int bestAnimationSet = -1; float nearestAngleDif = 0.0f; for (int i = 0; i < _animationSets.Length; i++) { //Disable the sets renderer SetAnimationSetActive(_animationSets[i], false); //Never use sprites that direction is more than 90 degrees to camera Vector2 spriteForwardXY = MathUtils.Rotate(forwardXY, _animationSets[i]._fowardAngle); float spriteAngle = MathUtils.AngleBetween(localspaceCameraDirXY, spriteForwardXY); if (Mathf.Abs(spriteAngle) < _animationSets[i]._maxAngle) { float angleDiff = MathUtils.AngleDiff(horizAngle, MathUtils.DegreesTo180Range(_animationSets[i]._faceAngle)); if (bestAnimationSet == -1 || Mathf.Abs(angleDiff) < Mathf.Abs(nearestAngleDif)) { bestAnimationSet = i; nearestAngleDif = angleDiff; } } } if (bestAnimationSet != -1) { Spine3DAnimationSet animationSet = _animationSets[bestAnimationSet]; SetAnimationSetActive(animationSet, true); if (_onRenderAnimationSet != null) { _onRenderAnimationSet.Invoke(camera, animationSet); } //Horizontal sprite rotation { //Rotate this forward to face sprite towards its face angle. Vector2 localSpaceSpriteForwardXY = MathUtils.Rotate(forwardXY, -animationSet._faceAngle); //When hit max view angle maintain that relative angle diff. float spriteAngle = MathUtils.AngleBetween(localspaceCameraDirXY, localSpaceSpriteForwardXY); float spriteMaxAngle = animationSet._maxViewAngle; if (Mathf.Abs(spriteAngle) > spriteMaxAngle) { //Rotate camera forward by max angle in correct direction float clampedAngle = spriteMaxAngle; if (spriteAngle < 0) { clampedAngle = -clampedAngle; } localSpaceSpriteForwardXY = MathUtils.Rotate(localspaceCameraDirXY, -clampedAngle); } //Set rotation matrix based off adjusted up and the correct sprite forward vector { Vector3 spriteForward = new Vector3(localSpaceSpriteForwardXY.x, 0.0f, localSpaceSpriteForwardXY.y).normalized; animationSet.transform.localRotation = Quaternion.FromToRotation(Vector3.forward, -spriteForward); } } //Vertical sprite rotation { Vector3 localSpaceCamerDirFlat = new Vector3(localspaceCameraDir.x, 0.0f, localspaceCameraDir.z).normalized; //Work out roll angle between sprite and camera float rollAngle = Vector3.Angle(localSpaceCamerDirFlat, localspaceCameraDir); if (localspaceCameraDir.y < 0) { rollAngle = -rollAngle; } //If roll angle is too severe then rotate sprite to align better with the camera if (Mathf.Abs(rollAngle) > _minRollAngle) { //ifs over min angle then rotate by amount over float angle = Mathf.Abs(rollAngle) - _minRollAngle; if (angle > _maxRollAngle) { angle = _maxRollAngle; } if (rollAngle < 0.0f) { angle = -angle; } Vector3 spriteAxis = Vector3.Cross(Vector3.up, localspaceCameraDir).normalized; animationSet.transform.localRotation *= Quaternion.AngleAxis(angle, Vector3.right); } } } }
private void SetAnimationSetActive(Spine3DAnimationSet animationSet, bool active) { animationSet.gameObject.SetActive(active); }