///
/// MIT License - Copyright(c) 2019 Ugo Belfiore
///
using UnityEngine;
namespace PerspectiveSwitcher
{
///
/// this script contain the logic of the transition between 2 camera
/// call ActiveCamera(CameraData cameraData) to activate the one you want
/// call StartTransition to see the transition between CameraOne and CameraTwo
/// call StartInverseTransition to see the opposite.
/// call ResetCamera if you want to reset the projection matrix and the transition
///
[RequireComponent(typeof(TransitionInformation)), ExecuteInEditMode]
public class PerspectiveSwitcher : MonoBehaviour
{
[SerializeField, Tooltip("Reference of a Transition")]
private TransitionInformation _transitionInformation;
[SerializeField, Tooltip("The camera you want to apply the effect")]
private Camera _mainCameraRef;
private CameraData _prevCameraChoosen;
private CameraData _nextCameraChoosen;
private FrequencyChrono _frequencyChrono = new FrequencyChrono();
private void Awake()
{
Init();
}
private void Init()
{
if (_mainCameraRef == null)
{
_mainCameraRef = Camera.main;
}
if (_transitionInformation == null)
{
_transitionInformation = gameObject.GetComponent();
}
ActiveCamera(_transitionInformation.CameraOne);
}
///
/// Active a camera
///
///
public void ActiveCamera(CameraData cameraData)
{
cameraData.Init();
cameraData.SetCameraDatas(_mainCameraRef);
}
///
/// start the transition from one to two
///
[ContextMenu("Start Transition")]
public void StartTransition()
{
ExecuteTransition(_transitionInformation.CameraOne, _transitionInformation.CameraTwo, _transitionInformation.TimeBlend, _mainCameraRef);
}
///
/// start the transition from two to one
///
[ContextMenu("Start Inverse Transition")]
public void StartInverseTransition()
{
ExecuteTransition(_transitionInformation.CameraTwo, _transitionInformation.CameraOne, _transitionInformation.TimeBlend, _mainCameraRef);
}
///
/// Execute a transition between the first one, and the second one, in timeBlend seconds.
///
/// first camera
/// second camera
/// time of the blend in seconds
public void ExecuteTransition(CameraData first, CameraData second, float timeBlend, Camera mainCamera)
{
_mainCameraRef = mainCamera;
_frequencyChrono.StartChrono(timeBlend, false);
_prevCameraChoosen = first;
_nextCameraChoosen = second;
_prevCameraChoosen.Init();
_nextCameraChoosen.Init();
_prevCameraChoosen.SetCameraDatas(_mainCameraRef);
}
[ContextMenu("Reset Camera")]
public void ResetTransition()
{
_mainCameraRef.ResetProjectionMatrix();
_frequencyChrono.Reset();
}
///
/// called even in play mode thanks to [ExecuteInEditMode]
///
private void Update()
{
DoTransition();
}
///
/// called every update, do the transition if the timer is ready
///
private void DoTransition()
{
SetFinalCameraIfChronoIsFinished();
EvaluateLerpTransition();
}
///
/// called one, when the chrono is finished
///
private void SetFinalCameraIfChronoIsFinished()
{
if (_frequencyChrono.IsFinished())
{
_nextCameraChoosen.SetCameraDatas(_mainCameraRef);
}
}
///
/// called every frame, evaluate the transition between the 2 cameras matrix
/// if the chrono is running
///
private void EvaluateLerpTransition()
{
//called every frame the chrono is running
if (_frequencyChrono.IsRunning())
{
float percentFromTime = _frequencyChrono.GetTimer() * 1 / _frequencyChrono.MaxTime;
float evaluateLerp = _transitionInformation.CurveEase.Evaluate(percentFromTime);
SetCameraLerp(_prevCameraChoosen, _nextCameraChoosen, evaluateLerp);
}
}
///
/// set the data of the camera from the lerp of 2 cameraDatas
///
/// CameraData From
/// CameraData To
/// time evaluated normalized, between 0 & 1
private void SetCameraLerp(CameraData one, CameraData two, float evaluatedTime)
{
_mainCameraRef.projectionMatrix = MatrixBlendData.DoMatrixTransition(evaluatedTime, one.Projection.GetSetuppedMatrix(), two.Projection.GetSetuppedMatrix());
}
}
}