// NOTE: This function is called at runtime and edit time. Keep that in mind when setting the values of properties. public override void ProcessFrame(Playable playable, FrameData info, object playerData) { int inputCount = playable.GetInputCount(); for (int i = 0; i < inputCount; i++) { float inputWeight = playable.GetInputWeight(i); if (inputWeight > 0.001f && !played.Contains(i)) { played.Add(i); ScriptPlayable <ShowAlertBehaviour> inputPlayable = (ScriptPlayable <ShowAlertBehaviour>)playable.GetInput(i); ShowAlertBehaviour input = inputPlayable.GetBehaviour(); var message = input.message; var duration = input.useTextLengthForDuration ? 0 : (float)inputPlayable.GetDuration(); if (Application.isPlaying) { DialogueManager.ShowAlert(message, duration); } else { PreviewUI.ShowMessage(message, duration, -1); } } else if (inputWeight <= 0.001f && played.Contains(i)) { played.Remove(i); } } }
// NOTE: This function is called at runtime and edit time. Keep that in mind when setting the values of properties. public override void ProcessFrame(Playable playable, FrameData info, object playerData) { TextMesh trackBinding = playerData as TextMesh; if (!trackBinding) { return; } int inputCount = playable.GetInputCount(); for (int i = 0; i < inputCount; i++) { float inputWeight = playable.GetInputWeight(i); if (inputWeight < 1f) { continue; } ScriptPlayable <FadeAnimationBehaviour> inputPlayable = (ScriptPlayable <FadeAnimationBehaviour>)playable.GetInput(i); FadeAnimationBehaviour input = inputPlayable.GetBehaviour(); // Use the above variables to process each frame of this playable. double w = inputPlayable.GetTime() / inputPlayable.GetDuration(); Color color = trackBinding.color; color.a = input.Alpha.Evaluate((float)w); trackBinding.color = color; } }
//Happens every frame in Edit mode. //Uses transform.position of the units to approximate what they would do in Play mode with the NavMeshAgent private void ProcessEditModeFrame(Playable playable) { previousInputFinalPositions = defaultPositions; int inputCount = playable.GetInputCount(); int unitCount = trackBinding.units.Count; for (int i = 0; i < inputCount; i++) { float inputWeight = playable.GetInputWeight(i); ScriptPlayable <AICommandBehaviour> inputPlayable = (ScriptPlayable <AICommandBehaviour>)playable.GetInput(i); AICommandBehaviour input = inputPlayable.GetBehaviour(); //Some actionTypes have special needs switch (input.commandType) { case AICommand.CommandType.Die: case AICommand.CommandType.Stop: //Do nothing if it's a Die or Stop action continue; //Will skip to the next input clip in the for loop above case AICommand.CommandType.AttackTarget: //Force the finalPosition to the attack target in case of an Attack action if (input.targetUnit != null) { input.targetPosition = input.targetUnit.transform.position; } break; } //Create an array of final positions for the entire Platoon finalPositions = trackBinding.GetFormationPositions(input.targetPosition); if (inputWeight > 0f) { double progress = inputPlayable.GetTime() / inputPlayable.GetDuration(); newPositions = new Vector3[unitCount]; for (int j = 0; j < unitCount; j++) { newPositions[j] = Vector3.Lerp(previousInputFinalPositions[j], finalPositions[j], (float)progress); } trackBinding.SetPositions(newPositions); continue; } else { previousInputFinalPositions = finalPositions; //cached to act as initial position for the next input } } }
// NOTE: This function is called at runtime and edit time. Keep that in mind when setting the values of properties. public override void ProcessFrame(Playable playable, FrameData info, object playerData) { MeshRenderer trackBinding = playerData as MeshRenderer; if (!trackBinding) { return; } Material material = trackBinding.sharedMaterial; if (!material) { return; } int clipsCountOnCurrentTrack = playable.GetInputCount(); //how many clips on current track //Debug.Log(clipsCountOnCurrentTrack); float currentFrameValue = 0; int nameHash = -1; float totalWeight = 0; for (int i = 0; i < clipsCountOnCurrentTrack; i++) { float inputWeight = playable.GetInputWeight(i); totalWeight += inputWeight; ScriptPlayable <MaterialFloatControlBehaviour> inputPlayable = (ScriptPlayable <MaterialFloatControlBehaviour>)playable.GetInput(i); MaterialFloatControlBehaviour input = inputPlayable.GetBehaviour(); if (string.IsNullOrEmpty(input.attributeName)) { continue; } nameHash = Shader.PropertyToID(input.attributeName); float normalisedTime = (float)(inputPlayable.GetTime() / inputPlayable.GetDuration()); float tweenProgress = input.currentCurve.Evaluate(normalisedTime); currentFrameValue += ((1 - tweenProgress) * input.initialValue + tweenProgress * input.targetValue) * inputWeight; } if (nameHash != -1) { float originalValue = material.GetFloat(nameHash); material.SetFloat(nameHash, originalValue * (1 - totalWeight) + currentFrameValue); } }
public override void ProcessFrame(Playable playable, FrameData info, object playerData) { base.ProcessFrame(playable, info, playerData); if (MainCamera == null) { return; } int activeInputs = 0; ClipInfo clipA = new ClipInfo(); ClipInfo clipB = new ClipInfo(); Texture2D overlayTexture = null; for (int i = 0; i < playable.GetInputCount(); ++i) { float weight = playable.GetInputWeight(i); ScriptPlayable <CameraFadePlayableBehaviour> clip = (ScriptPlayable <CameraFadePlayableBehaviour>)playable.GetInput(i); CameraFadePlayableBehaviour shot = clip.GetBehaviour(); if (shot != null && shot.IsValid && playable.GetPlayState() == PlayState.Playing && weight > 0.0001f) { clipA = clipB; clipB.weight = weight; clipB.localTime = clip.GetTime(); clipB.duration = clip.GetDuration(); clipB.overlayTexture = shot.overlayTexture; if (++activeInputs == 2) { break; } } } overlayTexture = (clipB.overlayTexture != null) ? clipB.overlayTexture : clipA.overlayTexture; float _weight = clipB.weight; MainCamera.SetTimelineFadeOverride(overlayTexture, _weight); }
// NOTE: This function is called at runtime and edit time. Keep that in mind when setting the values of properties. public override void ProcessFrame(Playable playable, FrameData info, object playerData) { LocalTimeComponet trackBinding = playerData as LocalTimeComponet; if (!trackBinding) { return; } int inputCount = playable.GetInputCount(); var maxWeight = 0f; var time = 0f; var duration = 0f; for (int i = 0; i < inputCount; i++) { var weight = playable.GetInputWeight(i); if (Mathf.Approximately(weight, 0)) { continue; } ScriptPlayable <LocalTimeBehaviour> inputPlayable = (ScriptPlayable <LocalTimeBehaviour>)playable.GetInput(i); LocalTimeBehaviour input = inputPlayable.GetBehaviour(); // Use the above variables to process each frame of this playable. // NOTE: gam0022 単純なブレンドが難しい値は最もウェイトが高いクリップを採用 if (weight > maxWeight) { time = (float)inputPlayable.GetTime(); duration = (float)inputPlayable.GetDuration(); maxWeight = weight; } } trackBinding.ApplyTime(time, duration); }
public override void ProcessFrame(Playable playable, FrameData info, object playerData) { if (m_GameObject == null) { m_GameObject = (GameObject)playerData; } ; if (m_GameObject == null) { return; } int inputCount = playable.GetInputCount(); for (int i = 0; i < inputCount; i++) { float _weight = playable.GetInputWeight(i); ScriptPlayable <SkillShotPlayable> _shotPlayable = (ScriptPlayable <SkillShotPlayable>)playable.GetInput(i); SkillShotPlayable _shotbehaviour = _shotPlayable.GetBehaviour(); float normalizedTime = (float)(_shotPlayable.GetTime() / _shotPlayable.GetDuration()); } }
public override void ProcessFrame(Playable playable, FrameData info, object playerData) { Transform trackBinding = playerData as Transform; if (trackBinding == null) { return; } Vector3 defaultPosition = trackBinding.position; Quaternion defaultRotation = trackBinding.rotation; int inputCount = playable.GetInputCount(); float positionTotalWeight = 0f; float rotationTotalWeight = 0f; Vector3 blendedPosition = Vector3.zero; Quaternion blendedRotation = new Quaternion(0f, 0f, 0f, 0f); for (int i = 0; i < inputCount; i++) { ScriptPlayable <TransformTweenBehaviour> playableInput = (ScriptPlayable <TransformTweenBehaviour>)playable.GetInput(i); TransformTweenBehaviour input = playableInput.GetBehaviour(); if (input.endLocation == null) { continue; } float inputWeight = playable.GetInputWeight(i); if (!m_FirstFrameHappened && !input.startLocation) { input.startingPosition = defaultPosition; input.startingRotation = defaultRotation; } float normalisedTime = (float)(playableInput.GetTime() / playableInput.GetDuration()); float tweenProgress = input.EvaluateCurrentCurve(normalisedTime); if (input.tweenPosition) { positionTotalWeight += inputWeight; blendedPosition += Vector3.Lerp(input.startingPosition, input.endLocation.position, tweenProgress) * inputWeight; } if (input.tweenRotation) { rotationTotalWeight += inputWeight; Quaternion desiredRotation = Quaternion.Lerp(input.startingRotation, input.endLocation.rotation, tweenProgress); desiredRotation = NormalizeQuaternion(desiredRotation); if (Quaternion.Dot(blendedRotation, desiredRotation) < 0f) { desiredRotation = ScaleQuaternion(desiredRotation, -1f); } desiredRotation = ScaleQuaternion(desiredRotation, inputWeight); blendedRotation = AddQuaternions(blendedRotation, desiredRotation); } } blendedPosition += defaultPosition * (1f - positionTotalWeight); Quaternion weightedDefaultRotation = ScaleQuaternion(defaultRotation, 1f - rotationTotalWeight); blendedRotation = AddQuaternions(blendedRotation, weightedDefaultRotation); trackBinding.position = blendedPosition; trackBinding.rotation = blendedRotation; m_FirstFrameHappened = true; }
public override void ProcessFrame(Playable playable, FrameData info, object playerData) { base.ProcessFrame(playable, info, playerData); if (MainCamera == null) { return; } int activeInputs = 0; ClipInfo clipA = new ClipInfo(); ClipInfo clipB = new ClipInfo(); float shakeIntensity = 0f; for (int i = 0; i < playable.GetInputCount(); ++i) { float weight = playable.GetInputWeight(i); ScriptPlayable <MainCameraPlayableBehaviour> clip = (ScriptPlayable <MainCameraPlayableBehaviour>)playable.GetInput(i); MainCameraPlayableBehaviour shot = clip.GetBehaviour(); if (shot != null) { callCustomEvents = shot.callCustomEvents; } if (shot != null && shot.IsValid && playable.GetPlayState() == PlayState.Playing && weight > 0.0001f) { clipA = clipB; clipB.camera = shot.gameCamera; clipB.weight = weight; clipB.localTime = clip.GetTime(); clipB.duration = clip.GetDuration(); clipB.shakeIntensity = shot.shakeIntensity; if (++activeInputs == 2) { break; } } } // Figure out which clip is incoming bool incomingIsB = clipB.weight >= 1 || clipB.localTime < clipB.duration / 2; if (activeInputs == 2) { if (clipB.localTime > clipA.localTime) { incomingIsB = true; } else if (clipB.localTime < clipA.localTime) { incomingIsB = false; } else { incomingIsB = clipB.duration >= clipA.duration; } } shakeIntensity = incomingIsB ? clipB.shakeIntensity : clipA.shakeIntensity; _Camera cameraA = incomingIsB ? clipA.camera : clipB.camera; _Camera cameraB = incomingIsB ? clipB.camera : clipA.camera; float camWeightB = incomingIsB ? clipB.weight : 1 - clipB.weight; if (cameraB == null) { cameraB = cameraA; cameraA = null; camWeightB = 1f - camWeightB; } if (incomingIsB) { shakeIntensity = (clipA.shakeIntensity * (1f - camWeightB)) + (clipB.shakeIntensity * camWeightB); } else { shakeIntensity = (clipB.shakeIntensity * (1f - camWeightB)) + (clipA.shakeIntensity * camWeightB); } MainCamera.SetTimelineOverride(cameraA, cameraB, camWeightB, shakeIntensity); if (callCustomEvents) { _Camera thisFrameCamera = (incomingIsB) ? cameraB : cameraA; if (thisFrameCamera != lastFrameCamera) { KickStarter.eventManager.Call_OnSwitchCamera(lastFrameCamera, thisFrameCamera, 0f); lastFrameCamera = thisFrameCamera; } } }
public override void ProcessFrame(Playable playable, FrameData info, object playerData) { Transform targetTransform = playerData as Transform; if (targetTransform == null) { return; } Vector3 originalPosition = targetTransform.position; Quaternion originalRotation = targetTransform.rotation; Vector3 originalScale = targetTransform.localScale; Vector3 originalEulerAngles = targetTransform.localEulerAngles; Vector3 outputPosition = Vector3.zero; Quaternion outputRotation = new Quaternion(0f, 0f, 0f, 0f); Vector3 outputScale = Vector3.zero; Vector3 outputEulerAngles = Vector3.zero; float positionWeight = 0f; float rotationWeight = 0f; float scaleWeight = 0f; int inputCount = playable.GetInputCount(); for (int i = 0; i < inputCount; i++) { ScriptPlayable <EZTransformTweenBehaviour> inputPlayable = (ScriptPlayable <EZTransformTweenBehaviour>)playable.GetInput(i); EZTransformTweenBehaviour inputBehaviour = inputPlayable.GetBehaviour(); if (inputBehaviour.endPoint == null) { continue; } float inputWeight = playable.GetInputWeight(i); if (!started && !inputBehaviour.startPoint) { inputBehaviour.startPosition = originalPosition; inputBehaviour.startRotation = originalRotation; inputBehaviour.startScale = originalScale; } float normalizedTime = (float)(inputPlayable.GetTime() / inputPlayable.GetDuration()); float process = inputBehaviour.curve.Evaluate(normalizedTime); if (inputBehaviour.tweenPosition) { positionWeight += inputWeight; outputPosition += Vector3.Lerp(inputBehaviour.startPosition, inputBehaviour.endPoint.position, process) * inputWeight; } if (inputBehaviour.tweenRotation) { rotationWeight += inputWeight; Quaternion targetRotation = Quaternion.Lerp(inputBehaviour.startRotation, inputBehaviour.endPoint.rotation, process); #if UNITY_2018_1 targetRotation = targetRotation.Normalize(); #else targetRotation.Normalize(); #endif if (Quaternion.Dot(outputRotation, targetRotation) < 0f) { targetRotation = targetRotation.Scale(-1f); } targetRotation = targetRotation.Scale(inputWeight); outputRotation = outputRotation.Add(targetRotation); outputEulerAngles += Vector3.Lerp(inputBehaviour.startEulerAngles, inputBehaviour.endEulerAngles, process) * inputWeight; } if (inputBehaviour.tweenScale) { scaleWeight += inputWeight; outputScale += Vector3.Lerp(inputBehaviour.startScale, inputBehaviour.endPoint.localScale, process) * inputWeight; } } targetTransform.position = outputPosition + originalPosition * (1f - positionWeight); if (eulerRotation) { targetTransform.localEulerAngles = outputEulerAngles + originalEulerAngles * (1f - rotationWeight); } else { targetTransform.rotation = outputRotation.Add(originalRotation.Scale(1f - rotationWeight)); } targetTransform.localScale = outputScale + originalScale * (1f - scaleWeight); started = true; }
// NOTE: This function is called at runtime and edit time. Keep that in mind when setting the values of properties. public override void ProcessFrame(Playable playable, FrameData info, object playerData) { var skeletonAnimation = playerData as SkeletonAnimation; var skeletonGraphic = playerData as SkeletonGraphic; animationStateComponent = playerData as IAnimationStateComponent; var skeletonComponent = playerData as ISkeletonComponent; if (animationStateComponent.IsNullOrDestroyed() || skeletonComponent == null) { return; } var skeleton = skeletonComponent.Skeleton; var state = animationStateComponent.AnimationState; if (!Application.isPlaying) { #if SPINE_EDITMODEPOSE PreviewEditModePose(playable, skeletonComponent, animationStateComponent, skeletonAnimation, skeletonGraphic); #endif return; } int inputCount = playable.GetInputCount(); // Ensure correct buffer size. if (this.lastInputWeights == null || this.lastInputWeights.Length < inputCount) { this.lastInputWeights = new float[inputCount]; for (int i = 0; i < inputCount; i++) { this.lastInputWeights[i] = default(float); } } var lastInputWeights = this.lastInputWeights; int numStartingClips = 0; bool anyClipPlaying = false; // Check all clips. If a clip that was weight 0 turned into weight 1, call SetAnimation. for (int i = 0; i < inputCount; i++) { float lastInputWeight = lastInputWeights[i]; float inputWeight = playable.GetInputWeight(i); bool clipStarted = lastInputWeight == 0 && inputWeight > 0; if (inputWeight > 0) { anyClipPlaying = true; } lastInputWeights[i] = inputWeight; if (clipStarted && numStartingClips < 2) { ScriptPlayable <SpineAnimationStateBehaviour> clipPlayable = (ScriptPlayable <SpineAnimationStateBehaviour>)playable.GetInput(i); startingClips[numStartingClips++] = clipPlayable; } } // unfortunately order of clips can be wrong when two start at the same time, we have to sort clips if (numStartingClips == 2) { ScriptPlayable <SpineAnimationStateBehaviour> clipPlayable0 = startingClips[0]; ScriptPlayable <SpineAnimationStateBehaviour> clipPlayable1 = startingClips[1]; if (clipPlayable0.GetDuration() > clipPlayable1.GetDuration()) // swap, clip 0 ends after clip 1 { startingClips[0] = clipPlayable1; startingClips[1] = clipPlayable0; } } for (int j = 0; j < numStartingClips; ++j) { ScriptPlayable <SpineAnimationStateBehaviour> clipPlayable = startingClips[j]; SpineAnimationStateBehaviour clipData = clipPlayable.GetBehaviour(); pauseWithDirector = !clipData.dontPauseWithDirector; endAtClipEnd = !clipData.dontEndWithClip; endMixOutDuration = clipData.endMixOutDuration; if (clipData.animationReference == null) { float mixDuration = clipData.customDuration ? GetCustomMixDuration(clipData) : state.Data.DefaultMix; state.SetEmptyAnimation(trackIndex, mixDuration); } else { if (clipData.animationReference.Animation != null) { TrackEntry currentEntry = state.GetCurrent(trackIndex); Spine.TrackEntry trackEntry; float customMixDuration = clipData.customDuration ? GetCustomMixDuration(clipData) : 0.0f; if (currentEntry == null && customMixDuration > 0) { state.SetEmptyAnimation(trackIndex, 0); // ease in requires empty animation trackEntry = state.AddAnimation(trackIndex, clipData.animationReference.Animation, clipData.loop, 0); } else { trackEntry = state.SetAnimation(trackIndex, clipData.animationReference.Animation, clipData.loop); } trackEntry.EventThreshold = clipData.eventThreshold; trackEntry.DrawOrderThreshold = clipData.drawOrderThreshold; trackEntry.TrackTime = (float)clipPlayable.GetTime() * (float)clipPlayable.GetSpeed(); trackEntry.TimeScale = (float)clipPlayable.GetSpeed(); trackEntry.AttachmentThreshold = clipData.attachmentThreshold; trackEntry.HoldPrevious = clipData.holdPrevious; if (clipData.customDuration) { trackEntry.MixDuration = customMixDuration; } timelineStartedTrackEntry = trackEntry; } //else Debug.LogWarningFormat("Animation named '{0}' not found", clipData.animationName); } // Ensure that the first frame ends with an updated mesh. if (skeletonAnimation) { skeletonAnimation.Update(0); skeletonAnimation.LateUpdate(); } else if (skeletonGraphic) { skeletonGraphic.Update(0); skeletonGraphic.LateUpdate(); } } startingClips[0] = startingClips[1] = ScriptPlayable <SpineAnimationStateBehaviour> .Null; if (lastAnyClipPlaying && !anyClipPlaying) { HandleClipEnd(); } this.lastAnyClipPlaying = anyClipPlaying; }
public override void ProcessFrame(Playable playable, FrameData info, object playerData) { Transform targetTransform = playerData as Transform; if (targetTransform == null) { return; } Vector3 originalPosition = targetTransform.position; Quaternion originalRotation = targetTransform.rotation; Vector3 originalScale = targetTransform.localScale; Vector3 outputPosition = Vector3.zero; Quaternion outputRotation = new Quaternion(0f, 0f, 0f, 0f); Vector3 outputScale = Vector3.zero; float positionWeight = 0f; float rotationWeight = 0f; float scaleWeight = 0f; int inputCount = playable.GetInputCount(); for (int i = 0; i < inputCount; i++) { ScriptPlayable <EZTransformTweenBehaviour> inputPlayable = (ScriptPlayable <EZTransformTweenBehaviour>)playable.GetInput(i); EZTransformTweenBehaviour inputBehaviour = inputPlayable.GetBehaviour(); float inputWeight = playable.GetInputWeight(i); if (!started && !inputBehaviour.startPoint) { inputBehaviour.startPosition = originalPosition; inputBehaviour.startRotation = originalRotation; inputBehaviour.startScale = originalScale; } float normalizedTime = (float)(inputPlayable.GetTime() / inputPlayable.GetDuration()); float process = inputBehaviour.curve.Evaluate(normalizedTime); if (inputBehaviour.tweenPosition && inputBehaviour.endPoint != null) { positionWeight += inputWeight; outputPosition += Vector3.Lerp(inputBehaviour.startPosition, inputBehaviour.endPoint.position, process) * inputWeight; } if (inputBehaviour.tweenRotation) { if (inputBehaviour.endPoint != null) { rotationWeight += inputWeight; Quaternion targetRotation = Quaternion.Lerp(inputBehaviour.startRotation, inputBehaviour.endPoint.rotation, process); outputRotation = QuaternionExt.Cumulate(outputRotation, targetRotation.Scale(inputWeight)); } } if (inputBehaviour.tweenScale && inputBehaviour.endPoint != null) { scaleWeight += inputWeight; outputScale += Vector3.Lerp(inputBehaviour.startScale, inputBehaviour.endPoint.localScale, process) * inputWeight; } } if (positionWeight > 1e-5) { targetTransform.position = outputPosition + originalPosition * (1f - positionWeight); } if (rotationWeight > 1e-5) { targetTransform.rotation = QuaternionExt.Cumulate(outputRotation, originalRotation.Scale(1f - rotationWeight)); } if (scaleWeight > 1e-5) { targetTransform.localScale = outputScale + originalScale * (1f - scaleWeight); } started = true; }
public override void ProcessFrame(Playable playable, FrameData info, object playerData) { base.ProcessFrame(playable, info, playerData); if (_character == null) { GameObject characterObject = playerData as GameObject; if (characterObject) { _character = characterObject.GetComponent <AC.Char>(); } } if (_character) { int activeInputs = 0; ClipInfo clipA = new ClipInfo(); ClipInfo clipB = new ClipInfo(); Transform headTurnTarget = null; Vector3 headTurnOffset = Vector3.zero; for (int i = 0; i < playable.GetInputCount(); ++i) { float weight = playable.GetInputWeight(i); ScriptPlayable <HeadTurnPlayableBehaviour> clip = (ScriptPlayable <HeadTurnPlayableBehaviour>)playable.GetInput(i); HeadTurnPlayableBehaviour shot = clip.GetBehaviour(); if (shot != null && shot.IsValid && playable.GetPlayState() == PlayState.Playing && weight > 0.0001f) { clipA = clipB; clipB.weight = weight; clipB.localTime = clip.GetTime(); clipB.duration = clip.GetDuration(); clipB.headTurnTarget = shot.headTurnTarget; clipB.headTurnOffset = shot.headTurnOffset; if (++activeInputs == 2) { break; } } } headTurnTarget = (clipB.headTurnTarget) ? clipB.headTurnTarget : clipA.headTurnTarget; float _weight = clipB.weight; if (clipA.headTurnTarget) { headTurnOffset = (clipB.headTurnOffset * clipB.weight) + (clipA.headTurnOffset * clipA.weight); } else { headTurnOffset = clipB.headTurnOffset; } _character.SetTimelineHeadTurnOverride(headTurnTarget, headTurnOffset, _weight); } }
/// <summary> /// Prepare a fragment of AnimationState that blends to produce the current timeline state. /// </summary> private AnimationState InitializeAnimationState(Playable playable, object playerData) { bool firstTime = affectedSkeletonAnimation == null && affectedSkeletonGraphic == null; if (firstTime) { var skeletonAnimation = playerData as SkeletonAnimation; var skeletonGraphic = playerData as SkeletonGraphic; var hasSkeletonDataAsset = playerData as IHasSkeletonDataAsset; //Make this once and keep clearing it instead. //This implies we will not ever change skeleton data mid-timeline. (unlikely?) animationState = new AnimationState(hasSkeletonDataAsset.SkeletonDataAsset.GetAnimationStateData()); isSkeletonGraphic = skeletonGraphic != null; if (!isSkeletonGraphic) { affectedSkeletonAnimation = skeletonAnimation; //Prevent regular update from interfering. originalFreezeState = skeletonAnimation.enabled; skeletonAnimation.enabled = false; } else { affectedSkeletonGraphic = skeletonGraphic; //Prevent regular update from interfering. originalFreezeState = skeletonGraphic.freeze; skeletonGraphic.freeze = true; } } animationState.SetEmptyAnimation(trackIndex, mixDuration: 0); // Find at most 2 blended clips that is affecting the playhead. // Spine could mix 3 clips but timeline's interface allows only 2 naturally. int inputCount = playable.GetInputCount(); bool foundFirst = false; bool foundSecond = false; for (int i = 0; i < inputCount; i++) { float inputWeight = playable.GetInputWeight(i); if (inputWeight == 0) { continue; } ScriptPlayable <SpineTimelineClipBehaviour> clip = (ScriptPlayable <SpineTimelineClipBehaviour>)playable.GetInput(i); SpineTimelineClipBehaviour clipData = clip.GetBehaviour(); var playheadFromClipBegin = clip.GetTime(); var clipDuration = clip.GetDuration(); if (clipData.animationReference == null) { continue; } Animation toAdd = clipData.animationReference.Animation; //Debug.Log($"{i} {playheadFromClipBegin} {inputWeight} {toAdd.Name} {toAdd.Duration}"); if (!foundFirst) { TrackEntry entry = animationState.SetAnimation(trackIndex, toAdd, clipData.loop); entry.TrackTime = (float)playheadFromClipBegin; entry.AllowImmediateQueue(); foundFirst = true; } else if (!foundSecond) { //WIP? Apparently this produces a weird mix, I am not sure it is correct or not. TrackEntry entry = animationState.SetAnimation(trackIndex, toAdd, clipData.loop); entry.MixTime = (float)playheadFromClipBegin; entry.MixDuration = 1f; foundSecond = true; break; } } return(animationState); }
public override void ProcessFrame(Playable playable, FrameData info, object playerData) { base.ProcessFrame(playable, info, playerData); if (MainCamera == null) { return; } int activeInputs = 0; ClipInfo clipA = new ClipInfo(); ClipInfo clipB = new ClipInfo(); for (int i = 0; i < playable.GetInputCount(); ++i) { float weight = playable.GetInputWeight(i); ScriptPlayable <MainCameraPlayableBehaviour> clip = (ScriptPlayable <MainCameraPlayableBehaviour>)playable.GetInput(i); MainCameraPlayableBehaviour shot = clip.GetBehaviour(); if (shot != null && shot.IsValid && playable.GetPlayState() == PlayState.Playing && weight > 0.0001f) { clipA = clipB; clipB.camera = shot.gameCamera; clipB.weight = weight; clipB.localTime = clip.GetTime(); clipB.duration = clip.GetDuration(); if (++activeInputs == 2) { break; } } } // Figure out which clip is incoming bool incomingIsB = clipB.weight >= 1 || clipB.localTime < clipB.duration / 2; if (activeInputs == 2) { if (clipB.localTime > clipA.localTime) { incomingIsB = true; } else if (clipB.localTime < clipA.localTime) { incomingIsB = false; } else { incomingIsB = clipB.duration >= clipA.duration; } } _Camera cameraA = incomingIsB ? clipA.camera : clipB.camera; _Camera cameraB = incomingIsB ? clipB.camera : clipA.camera; float camWeightB = incomingIsB ? clipB.weight : 1 - clipB.weight; if (cameraB == null) { cameraB = cameraA; cameraA = null; camWeightB = 1f - camWeightB; } MainCamera.SetTimelineOverride(cameraA, cameraB, camWeightB); }