//------------------------------------------------------------------------- // Clip Mixing //------------------------------------------------------------------------- /// <summary> /// Mix a single clip. /// </summary> /// <param name="playable">The track's playable</param> /// <param name="player">The player character</param> /// <param name="clipIndex">The index of the clip to mix</param> private void MixSingle(Playable playable, PlayerCharacter player, int clipIndex) { PoseInfo pose = TimelineTools.GetClipInfo <PoseInfo>(playable, clipIndex); player.gameObject.SetActive(pose.Active); if (PoseTools.IsAbsolute(pose)) // Absolute { MixAbsolute(player, (AbsolutePoseInfo)pose); } else // Relative { VirtualSnapshot.RestoreTransform(player); MixRelative(player, (RelativePoseInfo)pose); } StateDriver driver = GetDriver(pose); UpdateFacing(player, pose); UpdateState(player, driver, playable, pose); }
//------------------------------------------------------------------------- // Playable API //------------------------------------------------------------------------- /// <summary> /// Process a single frame of animation. /// </summary> /// <param name="playable">The playable this mixer is for.</param> /// <param name="info">Extra information about this frame.</param> /// <param name="playerData">Data bound to the track that this mixer is on.</param> public override void ProcessFrame(Playable playable, FrameData info, object playerData) { PlayerCharacter player = playerData != null ? (PlayerCharacter)playerData : GameManager.Player; if (player == null) { player = GameObject.FindObjectOfType <PlayerCharacter>(true); } if (TimelineTools.IsSingleClipPlaying(playable, out int clipIndex)) { MixSingle(playable, player, clipIndex); } else { TimelineTools.FindClipsToMix(playable, out int clipIndexA, out int clipIndexB); if (TimelineTools.ClipsAreValid(clipIndexA, clipIndexB)) { MixMultiple(playable, player, clipIndexA, clipIndexB); } } }
/// <summary> /// Mix together two active clips based on what type of clips they are. /// </summary> /// <param name="playable">The track's playable</param> /// <param name="player">The player character</param> /// <param name="clipIndexA">The index of the first clip to mix</param> /// <param name="clipIndexB">The index of the second clip to mix</param> private void MixMultiple(Playable playable, PlayerCharacter player, int clipIndexA, int clipIndexB) { PoseInfo poseA = TimelineTools.GetClipInfo <PoseInfo>(playable, clipIndexA); float weightA = playable.GetInputWeight(clipIndexA); PoseInfo poseB = TimelineTools.GetClipInfo <PoseInfo>(playable, clipIndexB); float weightB = playable.GetInputWeight(clipIndexB); // Mix together clips based on their typing. if (PoseTools.IsAbsolute(poseA) && PoseTools.IsAbsolute(poseB)) { MixAbsolute(player, (AbsolutePoseInfo)poseA, weightA); MixAbsolute(player, (AbsolutePoseInfo)poseB, weightB); } else if (PoseTools.IsRelative(poseA) && PoseTools.IsRelative(poseB)) { VirtualSnapshot.RestoreTransform(player); RelativePoseInfo mixed = new RelativePoseInfo(); mixed.Position = poseA.Position * weightA + poseB.Position * weightB; mixed.Rotation = poseA.Rotation * weightA + poseB.Rotation * weightB; mixed.Scale = poseA.Scale * weightA + poseB.Scale * weightB; MixRelative(player, mixed); } else { MixAbsoluteRelative(player, poseA, weightA, poseB, weightB); } // Apply player facing and FSM state based on which pose is weighted heavier. PoseInfo dominantPose = weightA > weightB ? poseA : poseB; player.gameObject.SetActive(dominantPose.Active); StateDriver driver = GetDriver(dominantPose); UpdateFacing(player, dominantPose); UpdateState(player, driver, playable, dominantPose); }