You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			428 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C#
		
	
		
		
			
		
	
	
			428 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C#
		
	
| 
								 
											1 year ago
										 
									 | 
							
								using UnityEngine;
							 | 
						||
| 
								 | 
							
								using System.Collections;
							 | 
						||
| 
								 | 
							
								using System.Collections.Generic;
							 | 
						||
| 
								 | 
							
								using RootMotion;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace RootMotion.FinalIK {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/// <summary>
							 | 
						||
| 
								 | 
							
									/// Managing Interactions for a single FBBIK effector.
							 | 
						||
| 
								 | 
							
									/// </summary>
							 | 
						||
| 
								 | 
							
									[System.Serializable]
							 | 
						||
| 
								 | 
							
									public class InteractionEffector {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// The type of the effector
							 | 
						||
| 
								 | 
							
										public FullBodyBipedEffector effectorType { get; private set; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Has the interaction been paused?
							 | 
						||
| 
								 | 
							
										public bool isPaused { get; private set; }
							 | 
						||
| 
								 | 
							
										// The current InteractionObject (null if there is no interaction going on)
							 | 
						||
| 
								 | 
							
										public InteractionObject interactionObject { get; private set; }
							 | 
						||
| 
								 | 
							
										// Is this InteractionEffector currently in the middle of an interaction?
							 | 
						||
| 
								 | 
							
										public bool inInteraction { get { return interactionObject != null; }}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Internal values
							 | 
						||
| 
								 | 
							
										private Poser poser;
							 | 
						||
| 
								 | 
							
										private IKEffector effector;
							 | 
						||
| 
								 | 
							
										private float timer, length, weight, fadeInSpeed, defaultPositionWeight, defaultRotationWeight, defaultPull, defaultReach, defaultPush, defaultPushParent, defaultBendGoalWeight, defaultPoserWeight, resetTimer;
							 | 
						||
| 
								 | 
							
										private bool positionWeightUsed, rotationWeightUsed, pullUsed, reachUsed, pushUsed, pushParentUsed, bendGoalWeightUsed, poserUsed;
							 | 
						||
| 
								 | 
							
										private bool pickedUp, defaults, pickUpOnPostFBBIK;
							 | 
						||
| 
								 | 
							
										private Vector3 pickUpPosition, pausePositionRelative;
							 | 
						||
| 
								 | 
							
										private Quaternion pickUpRotation, pauseRotationRelative;
							 | 
						||
| 
								 | 
							
										private InteractionTarget interactionTarget;
							 | 
						||
| 
								 | 
							
										private Transform target;
							 | 
						||
| 
								 | 
							
										private List<bool> triggered = new List<bool>();
							 | 
						||
| 
								 | 
							
										private InteractionSystem interactionSystem;
							 | 
						||
| 
								 | 
							
										private bool started;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// The custom constructor
							 | 
						||
| 
								 | 
							
										public InteractionEffector (FullBodyBipedEffector effectorType) {
							 | 
						||
| 
								 | 
							
											this.effectorType = effectorType;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Initiate this, get the default values
							 | 
						||
| 
								 | 
							
										public void Initiate(InteractionSystem interactionSystem) {
							 | 
						||
| 
								 | 
							
											this.interactionSystem = interactionSystem;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Find the effector if we haven't already
							 | 
						||
| 
								 | 
							
											effector = interactionSystem.ik.solver.GetEffector(effectorType);
							 | 
						||
| 
								 | 
							
											poser = effector.bone.GetComponent<Poser>();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											StoreDefaults();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        /// <summary>
							 | 
						||
| 
								 | 
							
								        /// Store the default values to which the effector will be reset to after an interaction has ended.
							 | 
						||
| 
								 | 
							
								        /// </summary>
							 | 
						||
| 
								 | 
							
										public void StoreDefaults() {
							 | 
						||
| 
								 | 
							
								            if (interactionSystem == null) return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											defaultPositionWeight = interactionSystem.ik.solver.GetEffector(effectorType).positionWeight;
							 | 
						||
| 
								 | 
							
											defaultRotationWeight = interactionSystem.ik.solver.GetEffector(effectorType).rotationWeight;
							 | 
						||
| 
								 | 
							
											defaultPoserWeight = poser != null? poser.weight: 0f;
							 | 
						||
| 
								 | 
							
											defaultPull = interactionSystem.ik.solver.GetChain(effectorType).pull;
							 | 
						||
| 
								 | 
							
											defaultReach = interactionSystem.ik.solver.GetChain(effectorType).reach;
							 | 
						||
| 
								 | 
							
											defaultPush = interactionSystem.ik.solver.GetChain(effectorType).push;
							 | 
						||
| 
								 | 
							
											defaultPushParent = interactionSystem.ik.solver.GetChain(effectorType).pushParent;
							 | 
						||
| 
								 | 
							
								            defaultBendGoalWeight = interactionSystem.ik.solver.GetChain(effectorType).bendConstraint.weight;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Interpolate to default values when currently not in interaction
							 | 
						||
| 
								 | 
							
										public bool ResetToDefaults(float speed, float deltaTime) {
							 | 
						||
| 
								 | 
							
											if (inInteraction) return false;
							 | 
						||
| 
								 | 
							
											if (isPaused) return false;
							 | 
						||
| 
								 | 
							
											if (defaults) return false; 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											resetTimer = Mathf.MoveTowards(resetTimer, 0f, deltaTime * speed);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Pull and Reach
							 | 
						||
| 
								 | 
							
											if (effector.isEndEffector) {
							 | 
						||
| 
								 | 
							
												if (pullUsed) interactionSystem.ik.solver.GetChain(effectorType).pull = Mathf.Lerp(defaultPull, interactionSystem.ik.solver.GetChain(effectorType).pull, resetTimer);
							 | 
						||
| 
								 | 
							
												if (reachUsed) interactionSystem.ik.solver.GetChain(effectorType).reach = Mathf.Lerp(defaultReach, interactionSystem.ik.solver.GetChain(effectorType).reach, resetTimer);
							 | 
						||
| 
								 | 
							
												if (pushUsed) interactionSystem.ik.solver.GetChain(effectorType).push = Mathf.Lerp(defaultPush, interactionSystem.ik.solver.GetChain(effectorType).push, resetTimer);
							 | 
						||
| 
								 | 
							
												if (pushParentUsed) interactionSystem.ik.solver.GetChain(effectorType).pushParent = Mathf.Lerp(defaultPushParent, interactionSystem.ik.solver.GetChain(effectorType).pushParent, resetTimer);
							 | 
						||
| 
								 | 
							
								                if (bendGoalWeightUsed) interactionSystem.ik.solver.GetChain(effectorType).bendConstraint.weight = Mathf.Lerp(defaultBendGoalWeight, interactionSystem.ik.solver.GetChain(effectorType).bendConstraint.weight, resetTimer);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Effector weights
							 | 
						||
| 
								 | 
							
											if (positionWeightUsed) effector.positionWeight = Mathf.Lerp(defaultPositionWeight, effector.positionWeight, resetTimer);
							 | 
						||
| 
								 | 
							
											if (rotationWeightUsed) effector.rotationWeight = Mathf.Lerp(defaultRotationWeight, effector.rotationWeight, resetTimer);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (resetTimer <= 0f) {
							 | 
						||
| 
								 | 
							
												pullUsed = false;
							 | 
						||
| 
								 | 
							
												reachUsed = false;
							 | 
						||
| 
								 | 
							
												pushUsed = false;
							 | 
						||
| 
								 | 
							
												pushParentUsed = false;
							 | 
						||
| 
								 | 
							
												positionWeightUsed = false;
							 | 
						||
| 
								 | 
							
												rotationWeightUsed = false;
							 | 
						||
| 
								 | 
							
								                bendGoalWeightUsed = false;
							 | 
						||
| 
								 | 
							
												poserUsed = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												defaults = true;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return true;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Pause this interaction
							 | 
						||
| 
								 | 
							
										public bool Pause() {
							 | 
						||
| 
								 | 
							
											if (!inInteraction) return false;
							 | 
						||
| 
								 | 
							
											isPaused = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											pausePositionRelative = target.InverseTransformPoint(effector.position);
							 | 
						||
| 
								 | 
							
											pauseRotationRelative = Quaternion.Inverse(target.rotation) * effector.rotation;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (interactionSystem.OnInteractionPause != null) {
							 | 
						||
| 
								 | 
							
												interactionSystem.OnInteractionPause(effectorType, interactionObject);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return true;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Resume a paused interaction
							 | 
						||
| 
								 | 
							
										public bool Resume() {
							 | 
						||
| 
								 | 
							
											if (!inInteraction) return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											isPaused = false;
							 | 
						||
| 
								 | 
							
											if (interactionSystem.OnInteractionResume != null) interactionSystem.OnInteractionResume(effectorType, interactionObject);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return true;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Start interaction
							 | 
						||
| 
								 | 
							
								        public bool Start(InteractionObject interactionObject, string tag, float fadeInTime, bool interrupt)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            // Get the InteractionTarget
							 | 
						||
| 
								 | 
							
								            InteractionTarget interactionTarget = null;
							 | 
						||
| 
								 | 
							
								            target = interactionObject.GetTarget(effectorType, tag);
							 | 
						||
| 
								 | 
							
								            if (target != null) interactionTarget = target.GetComponent<InteractionTarget>();
							 | 
						||
| 
								 | 
							
								            
							 | 
						||
| 
								 | 
							
								            return Start(interactionObject, interactionTarget, fadeInTime, interrupt);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        public bool Start(InteractionObject interactionObject, InteractionTarget interactionTarget, float fadeInTime, bool interrupt)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								            this.interactionTarget = interactionTarget;
							 | 
						||
| 
								 | 
							
								            
							 | 
						||
| 
								 | 
							
								            // If not in interaction, set effector positions to their bones
							 | 
						||
| 
								 | 
							
								            if (!inInteraction)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                effector.position = effector.bone.position;
							 | 
						||
| 
								 | 
							
								                effector.rotation = effector.bone.rotation;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            else
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                if (!interrupt) return false;
							 | 
						||
| 
								 | 
							
								                else defaults = false;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								            
							 | 
						||
| 
								 | 
							
								            target = interactionTarget != null? interactionTarget.transform: interactionObject.transform;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // Start the interaction
							 | 
						||
| 
								 | 
							
								            this.interactionObject = interactionObject;
							 | 
						||
| 
								 | 
							
								            if (interactionSystem.OnInteractionStart != null) interactionSystem.OnInteractionStart(effectorType, interactionObject);
							 | 
						||
| 
								 | 
							
								            interactionObject.OnStartInteraction(interactionSystem);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // Cleared triggered events
							 | 
						||
| 
								 | 
							
								            triggered.Clear();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            for (int i = 0; i < interactionObject.events.Length; i++)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                triggered.Add(false);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // See which InteractionObject.WeightCurve.Types are used
							 | 
						||
| 
								 | 
							
								            positionWeightUsed = interactionObject.CurveUsed(InteractionObject.WeightCurve.Type.PositionWeight);
							 | 
						||
| 
								 | 
							
								            rotationWeightUsed = interactionObject.CurveUsed(InteractionObject.WeightCurve.Type.RotationWeight);
							 | 
						||
| 
								 | 
							
								            pullUsed = interactionObject.CurveUsed(InteractionObject.WeightCurve.Type.Pull);
							 | 
						||
| 
								 | 
							
								            reachUsed = interactionObject.CurveUsed(InteractionObject.WeightCurve.Type.Reach);
							 | 
						||
| 
								 | 
							
								            pushUsed = interactionObject.CurveUsed(InteractionObject.WeightCurve.Type.Push);
							 | 
						||
| 
								 | 
							
								            pushParentUsed = interactionObject.CurveUsed(InteractionObject.WeightCurve.Type.PushParent);
							 | 
						||
| 
								 | 
							
								            bendGoalWeightUsed = interactionObject.CurveUsed(InteractionObject.WeightCurve.Type.BendGoalWeight);
							 | 
						||
| 
								 | 
							
								            poserUsed = poser != null && interactionObject.CurveUsed(InteractionObject.WeightCurve.Type.PoserWeight);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // Posing the hand/foot
							 | 
						||
| 
								 | 
							
								            if (poser != null && poserUsed)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								                if (poser.poseRoot == null) poser.weight = 0f;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                if (interactionTarget != null)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
													if (interactionTarget.usePoser)
							 | 
						||
| 
								 | 
							
													{
							 | 
						||
| 
								 | 
							
														poser.poseRoot = target.transform;
							 | 
						||
| 
								 | 
							
														poser.AutoMapping(interactionTarget.bones);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
								                } else
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    poser.poseRoot = null;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                //if (interactionTarget != null) poser.poseRoot = target.transform;
							 | 
						||
| 
								 | 
							
								                //else poser.poseRoot = null;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                poser.AutoMapping();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (defaults) StoreDefaults();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // Reset internal values
							 | 
						||
| 
								 | 
							
								            timer = 0f;
							 | 
						||
| 
								 | 
							
								            weight = 0f;
							 | 
						||
| 
								 | 
							
								            fadeInSpeed = fadeInTime > 0f ? 1f / fadeInTime : 1000f;
							 | 
						||
| 
								 | 
							
								            length = interactionObject.length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            isPaused = false;
							 | 
						||
| 
								 | 
							
								            pickedUp = false;
							 | 
						||
| 
								 | 
							
								            pickUpPosition = Vector3.zero;
							 | 
						||
| 
								 | 
							
								            pickUpRotation = Quaternion.identity;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (interactionTarget != null) interactionTarget.RotateTo(effector.bone);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            started = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            return true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Update the (possibly) ongoing interaction
							 | 
						||
| 
								 | 
							
										public void Update(Transform root, float speed, float deltaTime) {
							 | 
						||
| 
								 | 
							
											if (!inInteraction) {
							 | 
						||
| 
								 | 
							
												// If the InteractionObject has been destroyed, reset to defaults
							 | 
						||
| 
								 | 
							
												if (started) {
							 | 
						||
| 
								 | 
							
													isPaused = false;
							 | 
						||
| 
								 | 
							
													pickedUp = false;
							 | 
						||
| 
								 | 
							
													defaults = false;
							 | 
						||
| 
								 | 
							
													resetTimer = 1f;
							 | 
						||
| 
								 | 
							
													started = false;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												return;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Rotate target
							 | 
						||
| 
								 | 
							
											if (interactionTarget != null && !interactionTarget.rotateOnce) interactionTarget.RotateTo(effector.bone);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (isPaused) {
							 | 
						||
| 
								 | 
							
								                if (!pickedUp)
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                    effector.position = target.TransformPoint(pausePositionRelative);
							 | 
						||
| 
								 | 
							
								                    effector.rotation = target.rotation * pauseRotationRelative;
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
												// Apply the current interaction state to the solver
							 | 
						||
| 
								 | 
							
												interactionObject.Apply(interactionSystem.ik.solver, effectorType, interactionTarget, timer, weight, true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												return;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Advance the interaction timer and weight
							 | 
						||
| 
								 | 
							
											timer += deltaTime * speed * (interactionTarget != null? interactionTarget.interactionSpeedMlp: 1f);
							 | 
						||
| 
								 | 
							
											weight = Mathf.Clamp(weight + deltaTime * fadeInSpeed * speed, 0f, 1f);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Interaction events
							 | 
						||
| 
								 | 
							
											bool pickUp = false;
							 | 
						||
| 
								 | 
							
											bool pause = false;
							 | 
						||
| 
								 | 
							
											TriggerUntriggeredEvents(true, out pickUp, out pause);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Effector target positions and rotations
							 | 
						||
| 
								 | 
							
											Vector3 targetPosition = pickedUp? interactionSystem.transform.TransformPoint(pickUpPosition): target.position;
							 | 
						||
| 
								 | 
							
											Quaternion targetRotation = pickedUp? interactionSystem.transform.rotation * pickUpRotation: target.rotation;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Interpolate effector position and rotation
							 | 
						||
| 
								 | 
							
											effector.position = Vector3.Lerp(effector.bone.position, targetPosition, weight);
							 | 
						||
| 
								 | 
							
											effector.rotation = Quaternion.Lerp(effector.bone.rotation, targetRotation, weight);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Apply the current interaction state to the solver
							 | 
						||
| 
								 | 
							
											interactionObject.Apply(interactionSystem.ik.solver, effectorType, interactionTarget, timer, weight, false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (pickUp) PickUp(root);
							 | 
						||
| 
								 | 
							
								            if (pause) Pause();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            // Hand poser weight
							 | 
						||
| 
								 | 
							
								            float poserWeight = interactionObject.GetValue (InteractionObject.WeightCurve.Type.PoserWeight, interactionTarget, timer);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (poser != null && poserUsed) {
							 | 
						||
| 
								 | 
							
												poser.weight = Mathf.Lerp (poser.weight, poserWeight, weight);
							 | 
						||
| 
								 | 
							
											} else {
							 | 
						||
| 
								 | 
							
												if (poserWeight > 0f) {
							 | 
						||
| 
								 | 
							
													Warning.Log("InteractionObject " + interactionObject.name + " has a curve/multipler for Poser Weight, but the bone of effector " + effectorType.ToString() + " has no HandPoser/GenericPoser attached.", effector.bone);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (timer >= length) Stop();
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Get the normalized progress of the interaction
							 | 
						||
| 
								 | 
							
										public float progress {
							 | 
						||
| 
								 | 
							
											get {
							 | 
						||
| 
								 | 
							
												if (!inInteraction) return 0f;
							 | 
						||
| 
								 | 
							
												if (length == 0f) return 0f;
							 | 
						||
| 
								 | 
							
												return timer / length;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Go through all the InteractionObject events to trigger the ones that have not yet triggered
							 | 
						||
| 
								 | 
							
										private void TriggerUntriggeredEvents(bool checkTime, out bool pickUp, out bool pause) {
							 | 
						||
| 
								 | 
							
											pickUp = false;
							 | 
						||
| 
								 | 
							
											pause = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											for (int i = 0; i < triggered.Count; i++) {
							 | 
						||
| 
								 | 
							
												// If this event has not been triggered by this effector
							 | 
						||
| 
								 | 
							
												if (!triggered[i]) {
							 | 
						||
| 
								 | 
							
													
							 | 
						||
| 
								 | 
							
													// If time has passed...
							 | 
						||
| 
								 | 
							
													if (!checkTime || interactionObject.events[i].time < timer) {
							 | 
						||
| 
								 | 
							
														
							 | 
						||
| 
								 | 
							
														// Activate the event
							 | 
						||
| 
								 | 
							
														interactionObject.events[i].Activate(effector.bone);
							 | 
						||
| 
								 | 
							
														
							 | 
						||
| 
								 | 
							
														// Picking up
							 | 
						||
| 
								 | 
							
														if (interactionObject.events[i].pickUp) {
							 | 
						||
| 
								 | 
							
															if (timer >= interactionObject.events[i].time) timer = interactionObject.events[i].time;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															pickUp = true;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														
							 | 
						||
| 
								 | 
							
														// Pausing
							 | 
						||
| 
								 | 
							
														if (interactionObject.events[i].pause) {
							 | 
						||
| 
								 | 
							
															if (timer >= interactionObject.events[i].time) timer = interactionObject.events[i].time;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
															pause = true;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
														
							 | 
						||
| 
								 | 
							
														if (interactionSystem.OnInteractionEvent != null) interactionSystem.OnInteractionEvent(effectorType, interactionObject, interactionObject.events[i]);
							 | 
						||
| 
								 | 
							
														
							 | 
						||
| 
								 | 
							
														triggered[i] = true;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Trigger the interaction object
							 | 
						||
| 
								 | 
							
										private void PickUp(Transform root) {
							 | 
						||
| 
								 | 
							
											// Picking up the object
							 | 
						||
| 
								 | 
							
											pickUpPosition = root.InverseTransformPoint(effector.position);
							 | 
						||
| 
								 | 
							
											pickUpRotation = Quaternion.Inverse(interactionSystem.transform.rotation) * effector.rotation;
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
											pickUpOnPostFBBIK = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											pickedUp = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											var rigidbody = interactionObject.targetsRoot.GetComponent<Rigidbody>();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (rigidbody != null) {
							 | 
						||
| 
								 | 
							
												if (!rigidbody.isKinematic) {
							 | 
						||
| 
								 | 
							
													rigidbody.isKinematic = true;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                // Ignore collisions between the character and the colliders of the interaction object
							 | 
						||
| 
								 | 
							
								                var rootCollider = root.GetComponent<Collider>();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												if (rootCollider != null) {
							 | 
						||
| 
								 | 
							
													var colliders = interactionObject.targetsRoot.GetComponentsInChildren<Collider>();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
													foreach (Collider collider in colliders) {
							 | 
						||
| 
								 | 
							
														if (!collider.isTrigger && collider.enabled) Physics.IgnoreCollision(rootCollider, collider);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
											if (interactionSystem.OnInteractionPickUp != null) interactionSystem.OnInteractionPickUp(effectorType, interactionObject);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Stop the interaction
							 | 
						||
| 
								 | 
							
										public bool Stop() {
							 | 
						||
| 
								 | 
							
											if (!inInteraction) return false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											bool pickUp = false;
							 | 
						||
| 
								 | 
							
											bool pause = false;
							 | 
						||
| 
								 | 
							
											TriggerUntriggeredEvents(false, out pickUp, out pause);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (interactionSystem.OnInteractionStop != null) interactionSystem.OnInteractionStop(effectorType, interactionObject);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Reset the interaction target
							 | 
						||
| 
								 | 
							
											if (interactionTarget != null) interactionTarget.ResetRotation();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Reset the internal values
							 | 
						||
| 
								 | 
							
											interactionObject = null;
							 | 
						||
| 
								 | 
							
											weight = 0f;
							 | 
						||
| 
								 | 
							
											timer = 0f;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											isPaused = false;
							 | 
						||
| 
								 | 
							
											target = null;
							 | 
						||
| 
								 | 
							
											defaults = false;
							 | 
						||
| 
								 | 
							
											resetTimer = 1f;
							 | 
						||
| 
								 | 
							
											//if (poser != null && !pickedUp) poser.weight = 0f;
							 | 
						||
| 
								 | 
							
											pickedUp = false;
							 | 
						||
| 
								 | 
							
											started = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											return true;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Called after FBBIK update
							 | 
						||
| 
								 | 
							
										public void OnPostFBBIK() {
							 | 
						||
| 
								 | 
							
											if (!inInteraction) return;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Rotate the hands/feet to the RotateBoneWeight curve
							 | 
						||
| 
								 | 
							
											float rotateBoneWeight = interactionObject.GetValue(InteractionObject.WeightCurve.Type.RotateBoneWeight, interactionTarget, timer) * weight;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											if (rotateBoneWeight > 0f) {
							 | 
						||
| 
								 | 
							
												Quaternion r = pickedUp? interactionSystem.transform.rotation * pickUpRotation: effector.rotation;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												Quaternion targetRotation = Quaternion.Slerp(effector.bone.rotation, r, rotateBoneWeight * rotateBoneWeight);
							 | 
						||
| 
								 | 
							
												effector.bone.localRotation = Quaternion.Inverse(effector.bone.parent.rotation) * targetRotation;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// Positioning the interaction object to the effector (not the bone, because it is still at its animated translation)
							 | 
						||
| 
								 | 
							
											if (pickUpOnPostFBBIK) {
							 | 
						||
| 
								 | 
							
												Vector3 bonePosition = effector.bone.position;
							 | 
						||
| 
								 | 
							
												effector.bone.position = interactionSystem.transform.TransformPoint(pickUpPosition);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												interactionObject.targetsRoot.parent = effector.bone;
							 | 
						||
| 
								 | 
							
												
							 | 
						||
| 
								 | 
							
												effector.bone.position = bonePosition;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												pickUpOnPostFBBIK = false;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |