using UnityEngine; using System.Collections; namespace Com.LuisPedroFonseca.ProCamera2D { [HelpURLAttribute("http://www.procamera2d.com/user-guide/trigger-boundaries/")] public class ProCamera2DTriggerBoundaries : BaseTrigger, IPositionOverrider { public static string TriggerName = "Boundaries Trigger"; public ProCamera2DNumericBoundaries NumericBoundaries; public bool AreBoundariesRelative = true; public bool UseTopBoundary = true; public float TopBoundary = 10; public bool UseBottomBoundary = true; public float BottomBoundary = -10; public bool UseLeftBoundary = true; public float LeftBoundary = -10; public bool UseRightBoundary = true; public float RightBoundary = 10; public float TransitionDuration = 1f; public EaseType TransitionEaseType; public bool ChangeZoom; public float TargetZoom = 1.5f; public float ZoomSmoothness = 1f; public bool IsCurrentTrigger { get { return NumericBoundaries.CurrentBoundariesTrigger._instanceID == _instanceID; } } public bool SetAsStartingBoundaries { set { if (value && !_setAsStartingBoundaries) { var allBoundariesTriggers = FindObjectsOfType(typeof(ProCamera2DTriggerBoundaries)); foreach (ProCamera2DTriggerBoundaries trigger in allBoundariesTriggers) { trigger.SetAsStartingBoundaries = false; } } _setAsStartingBoundaries = value; } get { return _setAsStartingBoundaries; } } /// Internal use only. Use the property SetAsStartingBoundaries public bool _setAsStartingBoundaries; float _initialCamSize; BoundariesAnimator _boundsAnim; float _targetTopBoundary; float _targetBottomBoundary; float _targetLeftBoundary; float _targetRightBoundary; bool _transitioning; Vector3 _newPos; protected override void Awake() { base.Awake(); ProCamera2D.AddPositionOverrider(this); } protected override void OnDestroy() { base.OnDestroy(); if(ProCamera2D) ProCamera2D.RemovePositionOverrider(this); } void Start() { if (ProCamera2D == null) return; if (NumericBoundaries == null) { var numericBoundaries = FindObjectOfType(); NumericBoundaries = numericBoundaries == null ? ProCamera2D.gameObject.AddComponent() : numericBoundaries; } _boundsAnim = new BoundariesAnimator(ProCamera2D, NumericBoundaries); _boundsAnim.OnTransitionStarted += () => { if (NumericBoundaries.OnBoundariesTransitionStarted != null) NumericBoundaries.OnBoundariesTransitionStarted(); }; _boundsAnim.OnTransitionFinished += () => { if (NumericBoundaries.OnBoundariesTransitionFinished != null) NumericBoundaries.OnBoundariesTransitionFinished(); }; GetTargetBoundaries(); if (SetAsStartingBoundaries) SetBoundaries(); _initialCamSize = ProCamera2D.ScreenSizeInWorldCoordinates.y * .5f; } #region IPositionOverrider implementation public Vector3 OverridePosition(float deltaTime, Vector3 originalPosition) { if (!enabled) return originalPosition; if (_transitioning) return _newPos; else return originalPosition; } public int POOrder { get { return _poOrder; } set { _poOrder = value; } } int _poOrder = 1000; #endregion protected override void EnteredTrigger() { base.EnteredTrigger(); if (NumericBoundaries.CurrentBoundariesTrigger != null) StartCoroutine(TurnOffPreviousTrigger(NumericBoundaries.CurrentBoundariesTrigger)); if ((NumericBoundaries.CurrentBoundariesTrigger != null && NumericBoundaries.CurrentBoundariesTrigger._instanceID != _instanceID) || NumericBoundaries.CurrentBoundariesTrigger == null) { NumericBoundaries.CurrentBoundariesTrigger = this; StartCoroutine (Transition ()); } } IEnumerator TurnOffPreviousTrigger(ProCamera2DTriggerBoundaries trigger) { yield return new WaitForEndOfFrame(); trigger._transitioning = false; } /// /// Sets the Numeric Boundaries extension to the values of this trigger /// public void SetBoundaries() { if (NumericBoundaries != null) { NumericBoundaries.CurrentBoundariesTrigger = this; NumericBoundaries.UseLeftBoundary = UseLeftBoundary; if (UseLeftBoundary) NumericBoundaries.LeftBoundary = NumericBoundaries.TargetLeftBoundary = _targetLeftBoundary; NumericBoundaries.UseRightBoundary = UseRightBoundary; if (UseRightBoundary) NumericBoundaries.RightBoundary = NumericBoundaries.TargetRightBoundary = _targetRightBoundary; NumericBoundaries.UseTopBoundary = UseTopBoundary; if (UseTopBoundary) NumericBoundaries.TopBoundary = NumericBoundaries.TargetTopBoundary = _targetTopBoundary; NumericBoundaries.UseBottomBoundary = UseBottomBoundary; if (UseBottomBoundary) NumericBoundaries.BottomBoundary = NumericBoundaries.TargetBottomBoundary = _targetBottomBoundary; } } void GetTargetBoundaries() { if (AreBoundariesRelative) { _targetTopBoundary = Vector3V(transform.position) + TopBoundary; _targetBottomBoundary = Vector3V(transform.position) + BottomBoundary; _targetLeftBoundary = Vector3H(transform.position) + LeftBoundary; _targetRightBoundary = Vector3H(transform.position) + RightBoundary; } else { _targetTopBoundary = TopBoundary; _targetBottomBoundary = BottomBoundary; _targetLeftBoundary = LeftBoundary; _targetRightBoundary = RightBoundary; } } IEnumerator Transition() { if (!UseTopBoundary && !UseBottomBoundary && !UseLeftBoundary && !UseRightBoundary) { NumericBoundaries.UseTopBoundary = false; NumericBoundaries.UseBottomBoundary = false; NumericBoundaries.UseLeftBoundary = false; NumericBoundaries.UseRightBoundary = false; yield break; } var position = transform.position; var topBoundary = AreBoundariesRelative ? position.y + TopBoundary : TopBoundary; var bottomBoundary = AreBoundariesRelative ? position.y + BottomBoundary : BottomBoundary; var leftBoundary = AreBoundariesRelative ? position.x + LeftBoundary : LeftBoundary; var rightBoundary = AreBoundariesRelative ? position.x + RightBoundary : RightBoundary; const float epsilon = 0.01f; // Avoid unnecessary transitions var skip = true; if (UseTopBoundary && (Mathf.Abs(NumericBoundaries.TopBoundary - topBoundary) > epsilon || !NumericBoundaries.UseTopBoundary)) skip = false; if (skip && UseBottomBoundary && (Mathf.Abs(NumericBoundaries.BottomBoundary - bottomBoundary) > epsilon || !NumericBoundaries.UseBottomBoundary)) skip = false; if (skip && UseLeftBoundary && (Mathf.Abs(NumericBoundaries.LeftBoundary - leftBoundary) > epsilon || !NumericBoundaries.UseLeftBoundary)) skip = false; if (skip && UseRightBoundary && (Mathf.Abs(NumericBoundaries.RightBoundary - rightBoundary) > epsilon || !NumericBoundaries.UseRightBoundary)) skip = false; if (skip) yield break; GetTargetBoundaries(); _boundsAnim.UseTopBoundary = UseTopBoundary; _boundsAnim.TopBoundary = _targetTopBoundary; _boundsAnim.UseBottomBoundary = UseBottomBoundary; _boundsAnim.BottomBoundary = _targetBottomBoundary; _boundsAnim.UseLeftBoundary = UseLeftBoundary; _boundsAnim.LeftBoundary = _targetLeftBoundary; _boundsAnim.UseRightBoundary = UseRightBoundary; _boundsAnim.RightBoundary = _targetRightBoundary; _boundsAnim.TransitionDuration = TransitionDuration; _boundsAnim.TransitionEaseType = TransitionEaseType; // Zoom if (ChangeZoom && _initialCamSize / TargetZoom != ProCamera2D.ScreenSizeInWorldCoordinates.y * .5f) ProCamera2D.UpdateScreenSize(_initialCamSize / TargetZoom, ZoomSmoothness, TransitionEaseType); // Move camera "manually" if (_boundsAnim.GetAnimsCount() > 1) { if (NumericBoundaries.MoveCameraToTargetRoutine != null) NumericBoundaries.StopCoroutine(NumericBoundaries.MoveCameraToTargetRoutine); NumericBoundaries.MoveCameraToTargetRoutine = NumericBoundaries.StartCoroutine(MoveCameraToTarget()); } // Start bounds animation yield return new WaitForEndOfFrame(); _boundsAnim.Transition(); } IEnumerator MoveCameraToTarget() { var initialCamPosH = Vector3H(ProCamera2D.LocalPosition); var initialCamPosV = Vector3V(ProCamera2D.LocalPosition); _newPos = VectorHVD(initialCamPosH, initialCamPosV, 0); _transitioning = true; var t = 0f; while (t <= 1.0f) { t += ProCamera2D.DeltaTime / TransitionDuration; var newPosH = Utils.EaseFromTo(initialCamPosH, ProCamera2D.CameraTargetPositionSmoothed.x, t, TransitionEaseType); var newPosV = Utils.EaseFromTo(initialCamPosV, ProCamera2D.CameraTargetPositionSmoothed.y, t, TransitionEaseType); LimitToNumericBoundaries(ref newPosH, ref newPosV); _newPos = VectorHVD(newPosH, newPosV, 0); yield return ProCamera2D.GetYield(); } NumericBoundaries.MoveCameraToTargetRoutine = null; _transitioning = false; } void LimitToNumericBoundaries(ref float horizontalPos, ref float verticalPos) { if (NumericBoundaries.UseLeftBoundary && horizontalPos - ProCamera2D.ScreenSizeInWorldCoordinates.x / 2 < NumericBoundaries.LeftBoundary) horizontalPos = NumericBoundaries.LeftBoundary + ProCamera2D.ScreenSizeInWorldCoordinates.x / 2; else if (NumericBoundaries.UseRightBoundary && horizontalPos + ProCamera2D.ScreenSizeInWorldCoordinates.x / 2 > NumericBoundaries.RightBoundary) horizontalPos = NumericBoundaries.RightBoundary - ProCamera2D.ScreenSizeInWorldCoordinates.x / 2; if (NumericBoundaries.UseBottomBoundary && verticalPos - ProCamera2D.ScreenSizeInWorldCoordinates.y / 2 < NumericBoundaries.BottomBoundary) verticalPos = NumericBoundaries.BottomBoundary + ProCamera2D.ScreenSizeInWorldCoordinates.y / 2; else if (NumericBoundaries.UseTopBoundary && verticalPos + ProCamera2D.ScreenSizeInWorldCoordinates.y / 2 > NumericBoundaries.TopBoundary) verticalPos = NumericBoundaries.TopBoundary - ProCamera2D.ScreenSizeInWorldCoordinates.y / 2; } #if UNITY_EDITOR protected override void DrawGizmos() { base.DrawGizmos(); float cameraDepthOffset = Vector3D(ProCamera2D.transform.localPosition) + Mathf.Abs(Vector3D(ProCamera2D.transform.localPosition)) * Vector3D(ProCamera2D.transform.forward); Gizmos.DrawIcon(VectorHVD(Vector3H(transform.position), Vector3V(transform.position), cameraDepthOffset - .01f * Mathf.Sign(Vector3D(ProCamera2D.transform.position))), "ProCamera2D/gizmo_icon_bg.png", false); if (UseTopBoundary) { Gizmos.DrawIcon(VectorHVD(Vector3H(transform.position), Vector3V(transform.position), cameraDepthOffset), "ProCamera2D/gizmo_icon_bound_top.png", false); } if (UseBottomBoundary) { Gizmos.DrawIcon(VectorHVD(Vector3H(transform.position), Vector3V(transform.position), cameraDepthOffset), "ProCamera2D/gizmo_icon_bound_bottom.png", false); } if (UseRightBoundary) { Gizmos.DrawIcon(VectorHVD(Vector3H(transform.position), Vector3V(transform.position), cameraDepthOffset), "ProCamera2D/gizmo_icon_bound_right.png", false); } if (UseLeftBoundary) { Gizmos.DrawIcon(VectorHVD(Vector3H(transform.position), Vector3V(transform.position), cameraDepthOffset), "ProCamera2D/gizmo_icon_bound_left.png", false); } if (SetAsStartingBoundaries) Gizmos.DrawIcon(VectorHVD(Vector3H(transform.position), Vector3V(transform.position), cameraDepthOffset), "ProCamera2D/gizmo_icon_start.png", false); } void OnDrawGizmosSelected() { if (ProCamera2D == null) return; float cameraDepthOffset = Vector3D(ProCamera2D.transform.localPosition) + Mathf.Abs(Vector3D(ProCamera2D.transform.localPosition)) * Vector3D(ProCamera2D.transform.forward); var cameraCenter = VectorHVD(Vector3H(transform.position), Vector3V(transform.position), cameraDepthOffset); var cameraDimensions = Utils.GetScreenSizeInWorldCoords(ProCamera2D.GetComponent(), Mathf.Abs(Vector3D(ProCamera2D.transform.localPosition))); GetTargetBoundaries(); Gizmos.color = EditorPrefsX.GetColor(PrefsData.BoundariesTriggerColorKey, PrefsData.BoundariesTriggerColorValue); if (UseTopBoundary) { Gizmos.DrawRay(VectorHVD(Vector3H(transform.position) - cameraDimensions.x / 2, _targetTopBoundary, cameraDepthOffset), ProCamera2D.transform.right * cameraDimensions.x); Utils.DrawArrowForGizmo(cameraCenter, VectorHV(0, _targetTopBoundary - Vector3V(transform.position))); } if (UseBottomBoundary) { Gizmos.DrawRay(VectorHVD(Vector3H(transform.position) - cameraDimensions.x / 2, _targetBottomBoundary, cameraDepthOffset), ProCamera2D.transform.right * cameraDimensions.x); Utils.DrawArrowForGizmo(cameraCenter, VectorHV(0, _targetBottomBoundary - Vector3V(transform.position))); } if (UseRightBoundary) { Gizmos.DrawRay(VectorHVD(_targetRightBoundary, Vector3V(transform.position) - cameraDimensions.y / 2, cameraDepthOffset), ProCamera2D.transform.up * cameraDimensions.y); Utils.DrawArrowForGizmo(cameraCenter, VectorHV(_targetRightBoundary - Vector3H(transform.position), 0)); } if (UseLeftBoundary) { Gizmos.DrawRay(VectorHVD(_targetLeftBoundary, Vector3V(transform.position) - cameraDimensions.y / 2, cameraDepthOffset), ProCamera2D.transform.up * cameraDimensions.y); Utils.DrawArrowForGizmo(cameraCenter, VectorHV(_targetLeftBoundary - Vector3H(transform.position), 0)); } } #endif } }