Files
ihob/Assets/ProCamera2D/Runtime/Code/Triggers/ProCamera2DTriggerBoundaries.cs

380 lines
16 KiB
C#
Raw Permalink Normal View History

2026-02-21 17:04:05 -08:00
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;
}
}
/// <summary>Internal use only. Use the property SetAsStartingBoundaries</summary>
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<ProCamera2DNumericBoundaries>();
NumericBoundaries = numericBoundaries == null ? ProCamera2D.gameObject.AddComponent<ProCamera2DNumericBoundaries>() : 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;
}
/// <summary>
/// Sets the Numeric Boundaries extension to the values of this trigger
/// </summary>
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<Camera>(), 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
}
}