using System; using System.Collections; using UnityEngine; namespace Com.LuisPedroFonseca.ProCamera2D { #if UNITY_5_3_OR_NEWER [HelpURLAttribute("http://www.procamera2d.com/user-guide/extension-forward-focus/")] #endif public class ProCamera2DForwardFocus : BasePC2D, IPreMover { public static string ExtensionName = "Forward Focus"; const float EPSILON = .001f; public bool Progressive = true; public float SpeedMultiplier = 1f; public float TransitionSmoothness = .5f; public bool MaintainInfluenceOnStop = true; public Vector2 MovementThreshold = Vector2.zero; [RangeAttribute(EPSILON, .5f)] public float LeftFocus = .25f; [RangeAttribute(EPSILON, .5f)] public float RightFocus = .25f; [RangeAttribute(EPSILON, .5f)] public float TopFocus = .25f; [RangeAttribute(EPSILON, .5f)] public float BottomFocus = .25f; float _hVel; float _hVelSmooth; float _vVel; float _vVelSmooth; float _targetHVel; float _targetVVel; bool _isFirstHorizontalCameraMovement; bool _isFirstVerticalCameraMovement; bool __enabled; override protected void Awake() { base.Awake(); StartCoroutine(Enable()); ProCamera2D.AddPreMover(this); } protected override void OnDestroy() { base.OnDestroy(); if(ProCamera2D) ProCamera2D.RemovePreMover(this); } #region IPreMover implementation public void PreMove(float deltaTime) { if(__enabled && enabled) ApplyInfluence(deltaTime); } public int PrMOrder { get { return _prmOrder; } set { _prmOrder = value; } } int _prmOrder = 2000; #endregion override public void OnReset() { _hVel = 0; _hVelSmooth = 0; _vVel = 0; _vVelSmooth = 0; _targetHVel = 0; _targetVVel = 0; _isFirstHorizontalCameraMovement = false; _isFirstVerticalCameraMovement = false; __enabled = false; StartCoroutine(Enable()); } IEnumerator Enable() { yield return new WaitForEndOfFrame(); __enabled = true; } void ApplyInfluence(float deltaTime) { var currentHVel = Vector3H(ProCamera2D.TargetsMidPoint) - Vector3H(ProCamera2D.PreviousTargetsMidPoint); if (Mathf.Abs(currentHVel) < MovementThreshold.x) currentHVel = 0f; else currentHVel /= deltaTime; var currentVVel = Vector3V(ProCamera2D.TargetsMidPoint) - Vector3V(ProCamera2D.PreviousTargetsMidPoint); if (Mathf.Abs(currentVVel) < MovementThreshold.y) currentVVel = 0f; else currentVVel /= deltaTime; if (Progressive) { currentHVel = Mathf.Clamp(currentHVel * SpeedMultiplier, -LeftFocus * ProCamera2D.ScreenSizeInWorldCoordinates.x, RightFocus * ProCamera2D.ScreenSizeInWorldCoordinates.x); currentVVel = Mathf.Clamp(currentVVel * SpeedMultiplier, -BottomFocus * ProCamera2D.ScreenSizeInWorldCoordinates.y, TopFocus * ProCamera2D.ScreenSizeInWorldCoordinates.y); if (MaintainInfluenceOnStop) { if ((Mathf.Sign(currentHVel) == 1 && currentHVel < _hVel) || (Mathf.Sign(currentHVel) == -1 && currentHVel > _hVel) || (Mathf.Abs(currentHVel) < EPSILON)) { currentHVel = _hVel; } if ((Mathf.Sign(currentVVel) == 1 && currentVVel < _vVel) || (Mathf.Sign(currentVVel) == -1 && currentVVel > _vVel) || (Mathf.Abs(currentVVel) < EPSILON)) { currentVVel = _vVel; } } } else { if (MaintainInfluenceOnStop) { bool switchedHorizontalDirection; if (!_isFirstHorizontalCameraMovement && !(Mathf.Abs(currentHVel) < EPSILON)) { _isFirstHorizontalCameraMovement = true; switchedHorizontalDirection = true; } else { switchedHorizontalDirection = Mathf.Sign(currentHVel) != Mathf.Sign(_targetHVel); } if (!(Mathf.Abs(currentHVel) < EPSILON) && switchedHorizontalDirection) { _targetHVel = (currentHVel < 0f ? -LeftFocus : RightFocus) * ProCamera2D.ScreenSizeInWorldCoordinates.x; } currentHVel = _targetHVel; bool switchedVerticalDirection; if (!_isFirstVerticalCameraMovement && !(Mathf.Abs(currentVVel) < EPSILON)) { _isFirstVerticalCameraMovement = true; switchedVerticalDirection = true; } else { switchedVerticalDirection = Mathf.Sign(currentVVel) != Mathf.Sign(_targetVVel); } if (!(Mathf.Abs(currentVVel) < EPSILON) && switchedVerticalDirection) { _targetVVel = (currentVVel < 0f ? -BottomFocus : TopFocus) * ProCamera2D.ScreenSizeInWorldCoordinates.y; } currentVVel = _targetVVel; } else { if (!(Mathf.Abs(currentHVel) < EPSILON)) currentHVel = (currentHVel < 0f ? -LeftFocus : RightFocus) * ProCamera2D.ScreenSizeInWorldCoordinates.x; else currentHVel = 0; if (!(Mathf.Abs(currentVVel) < EPSILON)) currentVVel = (currentVVel < 0f ? -BottomFocus : TopFocus) * ProCamera2D.ScreenSizeInWorldCoordinates.y; else currentVVel = 0; } } // We need to clamp the values again to account for camera zooms currentHVel = Mathf.Clamp(currentHVel, -LeftFocus * ProCamera2D.ScreenSizeInWorldCoordinates.x, RightFocus * ProCamera2D.ScreenSizeInWorldCoordinates.x); currentVVel = Mathf.Clamp(currentVVel, -BottomFocus * ProCamera2D.ScreenSizeInWorldCoordinates.y, TopFocus * ProCamera2D.ScreenSizeInWorldCoordinates.y); // Smooth the values _hVel = Mathf.SmoothDamp(_hVel, currentHVel, ref _hVelSmooth, TransitionSmoothness, float.MaxValue, deltaTime); _vVel = Mathf.SmoothDamp(_vVel, currentVVel, ref _vVelSmooth, TransitionSmoothness, float.MaxValue, deltaTime); // Apply the influence ProCamera2D.ApplyInfluence(new Vector2(_hVel, _vVel)); } #if UNITY_EDITOR override protected void DrawGizmos() { base.DrawGizmos(); var gameCamera = ProCamera2D.GetComponent(); var cameraDimensions = gameCamera.orthographic ? Utils.GetScreenSizeInWorldCoords(gameCamera) : Utils.GetScreenSizeInWorldCoords(gameCamera, Mathf.Abs(Vector3D(transform.localPosition))); float cameraDepthOffset = Vector3D(ProCamera2D.transform.localPosition) + Mathf.Abs(Vector3D(transform.localPosition)) * Vector3D(ProCamera2D.transform.forward); var cameraCenter = VectorHVD(Vector3H(transform.position), Vector3V(transform.position), cameraDepthOffset); Gizmos.color = EditorPrefsX.GetColor(PrefsData.ForwardFocusColorKey, PrefsData.ForwardFocusColorValue); if (LeftFocus > EPSILON) { Gizmos.DrawRay(VectorHVD(Vector3H(transform.position) + cameraDimensions.x * LeftFocus, Vector3V(transform.position) - cameraDimensions.y / 2, cameraDepthOffset), transform.up * cameraDimensions.y); Utils.DrawArrowForGizmo(cameraCenter + VectorHV(cameraDimensions.x * LeftFocus, 0), -transform.right * .3f); } if (RightFocus > EPSILON) { Gizmos.DrawRay(VectorHVD(Vector3H(transform.position) - cameraDimensions.x * RightFocus, Vector3V(transform.position) - cameraDimensions.y / 2, cameraDepthOffset), transform.up * cameraDimensions.y); Utils.DrawArrowForGizmo(cameraCenter - VectorHV(cameraDimensions.x * RightFocus, 0), transform.right * .3f); } if (TopFocus > EPSILON) { Gizmos.DrawRay(VectorHVD(Vector3H(transform.position) - cameraDimensions.x / 2, Vector3V(transform.position) - cameraDimensions.y * TopFocus, cameraDepthOffset), transform.right * cameraDimensions.x); Utils.DrawArrowForGizmo(cameraCenter - VectorHV(0, cameraDimensions.y * TopFocus), transform.up * .3f); } if (BottomFocus > EPSILON) { Gizmos.DrawRay(VectorHVD(Vector3H(transform.position) - cameraDimensions.x / 2, Vector3V(transform.position) + cameraDimensions.y * BottomFocus, cameraDepthOffset), transform.right * cameraDimensions.x); Utils.DrawArrowForGizmo(cameraCenter + VectorHV(0, cameraDimensions.y * BottomFocus), -transform.up * .3f); } } #endif } }