Ejemplo n.º 1
0
        public override void ProcessFrame(Playable playable, FrameData info, object playerData)
        {
            // Q: Does ProcessFrame come before or after MonoBehaviour.Update?
            //Debug.Log("MixerBehaviour ProcessFrame " + Time.frameCount);
            // A: MonoBehaviour.Update comes first. Then PlayableBehaviour.ProcessFrame.

            trackBindingPlayableHandle = playerData as SpinePlayableHandleBase;
            if (trackBindingPlayableHandle == null)
            {
                return;
            }

            // Ensure initialize all clipBehaviourData.
            if (!clipsInitialized)
            {
                var skeletonData = trackBindingPlayableHandle.SkeletonData;
                for (int i = 0, inputCount = playable.GetInputCount(); i < inputCount; i++)
                {
                    var inputPlayableClip = (ScriptPlayable <SpineAnimationBehaviour>)playable.GetInput(i);           // The clip. Returns a handle struct.
                    SpineAnimationBehaviour clipBehaviourData = inputPlayableClip.GetBehaviour();                     // the stateless data
                    clipBehaviourData.EnsureInitialize(skeletonData);
                }
                clipsInitialized = true;
            }

            trackBindingPlayableHandle.ProcessFrame(playable, info, this);

            if (Application.isPlaying)
            {
                trackBindingPlayableHandle.HandleEvents(eventBuffer);
                eventBuffer.Clear();
            }
        }
        public override Playable CreatePlayable(PlayableGraph graph, GameObject owner)
        {
            var playable = ScriptPlayable <SpineAnimationBehaviour> .Create(graph, template);

            SpineAnimationBehaviour clone = playable.GetBehaviour();

            return(playable);
        }
Ejemplo n.º 3
0
        /// <summary>Applies the Playable ScriptPlayable(SpineAnimationBehaviour) to a skeleton.</summary>
        /// <returns>The number of actual applied clips (inputs with weight greater than 0) in the current frame.</returns>
        internal int ApplyPlayableFrame(Playable playable, Skeleton skeleton, HashSet <int> frameAppliedProperties, int trackIndex)
        {
            int  inputCount   = playable.GetInputCount();
            bool isUpperTrack = trackIndex > 0;

            // Prepare lastTimes and lastInputWeights array
            if (this.lastTimes == null || this.lastTimes.Length < inputCount)
            {
                this.lastInputWeights = new float[inputCount];
                this.lastTimes        = new float[inputCount];

                for (int i = 0; i < inputCount; i++)
                {
                    this.lastInputWeights[i] = 0f;
                    this.lastTimes[i]        = 0f;
                }
            }

            var lastInputWeights = this.lastInputWeights;
            var lastTimes        = this.lastTimes;
            //var frameAppliedProperties = this.frameAppliedProperties;

            int currentInputs = 0;
            //frameAppliedProperties.Clear();

            // foreach (clip)
            var eventBuffer = this.eventBuffer;

            for (int i = 0; i < inputCount; i++)
            {
                float inputWeight       = playable.GetInputWeight(i);
                var   inputPlayableClip = (ScriptPlayable <SpineAnimationBehaviour>)playable.GetInput(i); // The clip. Returns a handle struct.
                SpineAnimationBehaviour clipBehaviourData = inputPlayableClip.GetBehaviour();             // the stateless data

                float clipTime     = (float)inputPlayableClip.GetTime();                                  // stateful: clip time.
                float applyTime    = clipTime;
                float clipLastTime = lastTimes[i];
                //bool backwardsPlayback = clipLastTime > applyTime;

                Animation spineAnimation  = clipBehaviourData.animation;
                bool      loop            = clipBehaviourData.loop;
                var       clipEventBuffer = inputWeight > clipBehaviourData.eventThreshold ? eventBuffer : null;
                bool      skipAttachments = inputWeight < clipBehaviourData.attachmentThreshold;
                bool      skipDrawOrder   = inputWeight < clipBehaviourData.drawOrderThreshold;


                if (spineAnimation != null)
                {
                    //Debug.LogFormat("{0} - {1}", i, animation.name);

                    if (Mathf.Approximately(inputWeight, 0))
                    {
                        if (lastInputWeights[i] > 0)
                        {
                            if (isUpperTrack)
                            {
                                foreach (var spineTimeline in spineAnimation.timelines)
                                {
                                    if (!frameAppliedProperties.Contains(spineTimeline.PropertyId))
                                    {
                                        spineTimeline.Apply(skeleton, 0, 0, null, 0, MixPose.Setup, MixDirection.Out);
                                    }
                                    frameAppliedProperties.Add(spineTimeline.PropertyId);
                                }
                                //Debug.Log("conditionally remove " + spineAnimation.name);
                            }
                            else
                            {
                                spineAnimation.SetKeyedItemsToSetupPose(skeleton);                                 // Animation last apply.
                                //Debug.Log("setkeyeditemstosetuppose " + spineAnimation.name);
                            }

                            inputWeight = 0f;
                        }
                        applyTime = lastTimes[i];
                        // Don't do else if input weight is <= 0. This is part of the Unity reference implementation.
                    }
                    else
                    {
//						if (isUpperTrack) {
//							Debug.Log(trackIndex + " applying " + spineAnimation.name + " " + Time.frameCount + " " + inputWeight);
//						}

                        float duration = spineAnimation.duration;
                        if (loop && duration != 0)
                        {
                            applyTime %= duration;
                            if (clipLastTime > 0)
                            {
                                clipLastTime %= duration;
                            }
                        }

                        // EXPERIMENTAL: Allow first animation to mix-in rather than do a flat Setup Pose override.
                        bool    isFirstOnLowestTrack = !isUpperTrack && i == 0 && (inputCount == 1 || playable.GetInputWeight(1) == 0);
                        MixPose animationPose        = MixPose.Setup;
                        MixPose trackCurrentMixType  = isUpperTrack ? MixPose.CurrentLayered : MixPose.Current;

                        //Animation.Apply();
                        foreach (var spineTimeline in spineAnimation.Timelines)
                        {
                            int pid = spineTimeline.PropertyId;

                            MixPose pose = animationPose;
                            if (isFirstOnLowestTrack)
                            {
                                pose = MixPose.CurrentLayered;
                            }
                            else if (currentInputs > 0 || isUpperTrack)
                            {
                                if (frameAppliedProperties.Contains(pid))
                                {
                                    pose = trackCurrentMixType;
                                }
                            }

                            MixDirection direction = MixDirection.In;
                            if (inputWeight < lastInputWeights[i])
                            {
                                direction = MixDirection.Out;
                            }

                            if (direction == MixDirection.In)
                            {
                                if (skipAttachments && spineTimeline is AttachmentTimeline)
                                {
                                    continue;
                                }
                                if (skipDrawOrder && spineTimeline is DrawOrderTimeline)
                                {
                                    continue;
                                }
                            }
                            else
                            {
                                if (skipAttachments && spineTimeline is AttachmentTimeline)
                                {
                                    pose      = MixPose.Setup;
                                    direction = MixDirection.Out;
                                }
                                if (skipDrawOrder && spineTimeline is DrawOrderTimeline)
                                {
                                    pose      = MixPose.Setup;
                                    direction = MixDirection.Out;
                                }
                            }

//							var rot = spineTimeline as RotateTimeline;
//							if (rot != null) {
//								var bone = skeleton.bones.Items[rot.boneIndex];
//								if (bone.data.name == "rear-upper-arm") {
//									Debug.Log(bone.rotation + " " + pose);
//									Debug.Log(frameAppliedProperties.Contains(pid));
//								}
//							}

                            // TODO: Handle RotateTimeline like AnimationState.
                            spineTimeline.Apply(skeleton, lastTimes[i], applyTime, clipEventBuffer, inputWeight, pose, direction);
                            frameAppliedProperties.Add(spineTimeline.PropertyId);
                        }

                        //Debug.LogFormat("Applying {0} at {1} as input [{2}] using {3} {4}", animation.Name, inputWeight, i, mixPose, mixDirection);

                        currentInputs++;
                    }
                }

                lastInputWeights[i] = inputWeight;
                lastTimes[i]        = applyTime;
            }

            return(currentInputs);
        }