using UnityEngine; using Lean.Common; using FSA = UnityEngine.Serialization.FormerlySerializedAsAttribute; namespace Lean.Touch { /// This component allows you to translate the current GameObject along the specified surface. [ExecuteInEditMode] [HelpURL(LeanTouch.PlusHelpUrlPrefix + "LeanDragTranslateAlong")] [AddComponentMenu(LeanTouch.ComponentPathPrefix + "Drag Translate Along")] public class LeanDragTranslateAlong : MonoBehaviour { /// If you want this component to work on a different Transform, then specify it here. This can be used to improve organization if your GameObject already has many components. /// None/null = Current Transform. public Transform Target { set { target = value; } get { return target; } } [FSA("Target")] [SerializeField] private Transform target; /// The method used to find fingers to use with this component. See LeanFingerFilter documentation for more information. public LeanFingerFilter Use = new LeanFingerFilter(true); /// The method used to find world coordinates from a finger. See LeanScreenDepth documentation for more information. public LeanScreenDepth ScreenDepth = new LeanScreenDepth(LeanScreenDepth.ConversionType.DepthIntercept); /// If your ScreenDepth settings cause the position values to clamp, there will be a difference between where the finger is and where the object is. Should this difference be tracked? public bool TrackScreenPosition { set { trackScreenPosition = value; } get { return trackScreenPosition; } } [FSA("TrackScreenPosition")] [SerializeField] private bool trackScreenPosition = true; /// If you want this component to change smoothly over time, then this allows you to control how quick the changes reach their target value. /// -1 = Instantly change. /// 1 = Slowly change. /// 10 = Quickly change. public float Damping { set { damping = value; } get { return damping; } } [FSA("Damping")] [FSA("Dampening")] [SerializeField] private float damping = -1.0f; [System.NonSerialized] private Vector2 deltaDifference; [SerializeField] private Vector3 remainingDelta; /// If you've set Use to ManuallyAddedFingers, then you can call this method to manually add a finger. public void AddFinger(LeanFinger finger) { Use.AddFinger(finger); } /// If you've set Use to ManuallyAddedFingers, then you can call this method to manually remove a finger. public void RemoveFinger(LeanFinger finger) { Use.RemoveFinger(finger); } /// If you've set Use to ManuallyAddedFingers, then you can call this method to manually remove all fingers. public void RemoveAllFingers() { Use.RemoveAllFingers(); } #if UNITY_EDITOR protected virtual void Reset() { Use.UpdateRequiredSelectable(gameObject); } #endif protected virtual void Awake() { Use.UpdateRequiredSelectable(gameObject); } protected virtual void Update() { var finalTransform = target != null ? target : transform; // Store smoothed position var smoothPosition = finalTransform.localPosition; // Snap to target finalTransform.localPosition += remainingDelta; // Store old position var oldPosition = finalTransform.localPosition; // Update to new position UpdateTranslation(); // Shift delta by old new delta remainingDelta += finalTransform.localPosition - oldPosition; // Get t value var factor = LeanHelper.GetDampenFactor(damping, Time.deltaTime); // Dampen remainingDelta var newDelta = Vector3.Lerp(remainingDelta, Vector3.zero, factor); // Shift this position by the change in delta finalTransform.localPosition = smoothPosition + remainingDelta - newDelta; // Update remainingDelta with the dampened value remainingDelta = newDelta; } private void UpdateTranslation() { var finalTransform = target != null ? target : transform; // Get the fingers we want to use var fingers = Use.UpdateAndGetFingers(); // Calculate the screenDelta value based on these fingers and make sure there is movement var screenDelta = LeanGesture.GetScreenDelta(fingers); if (screenDelta != Vector2.zero) { // Make sure the camera exists var camera = LeanHelper.GetCamera(ScreenDepth.Camera, gameObject); if (camera != null) { var worldPosition = finalTransform.position; var oldScreenPoint = camera.WorldToScreenPoint(worldPosition); if (trackScreenPosition == true) { if (ScreenDepth.TryConvert(ref worldPosition, oldScreenPoint + (Vector3)(screenDelta + deltaDifference), gameObject) == true) { finalTransform.position = worldPosition; } var newScreenPoint = camera.WorldToScreenPoint(worldPosition); var oldNewDelta = (Vector2)(newScreenPoint - oldScreenPoint); deltaDifference += screenDelta - oldNewDelta; } else { if (ScreenDepth.TryConvert(ref worldPosition, oldScreenPoint + (Vector3)screenDelta, gameObject) == true) { finalTransform.position = worldPosition; } } } else { Debug.LogError("Failed to find camera. Either tag your cameras MainCamera, or set one in this component.", this); } } } } } #if UNITY_EDITOR namespace Lean.Touch.Editor { using TARGET = LeanDragTranslateAlong; [UnityEditor.CanEditMultipleObjects] [UnityEditor.CustomEditor(typeof(TARGET))] public class LeanDragTranslateAlong_Editor : LeanEditor { protected override void OnInspector() { TARGET tgt; TARGET[] tgts; GetTargets(out tgt, out tgts); Draw("target", "This allows you to control how quickly the target value is reached."); Draw("Use"); Draw("ScreenDepth"); Draw("trackScreenPosition", "If your ScreenDepth settings cause the position values to clamp, there will be a difference between where the finger is and where the object is. Should this difference be tracked?"); Draw("damping", "If you want this component to change smoothly over time, then this allows you to control how quick the changes reach their target value.\n\n-1 = Instantly change.\n\n1 = Slowly change.\n\n10 = Quickly change."); } } } #endif