using NightclubArcadia.Player;
using NightclubArcadia.Player.Math;
using UnityEngine;
namespace NightclubArcadia.Cinematics
{
///
/// Converts mouse drag-pan into CameraRigAnchor manual offset with recenter rules.
///
public sealed class CameraPanInput : MonoBehaviour
{
[SerializeField] Camera brainCamera;
[SerializeField] CameraRigAnchor anchor;
[SerializeField] CameraStateDirector stateDirector;
[SerializeField] PlayerPointerInput pointerInput;
[SerializeField] float panMetresPerPixel = 0.02f;
[SerializeField] float maxPanDistance = 12f;
[SerializeField] float recenterDelay = 2.5f;
[SerializeField] float recenterSmoothTime = 0.8f;
[SerializeField] float movementRecenterDelay = 0.4f;
float releaseTimer = float.MaxValue;
Vector3 recenterVelocity;
Vector3 camRight;
Vector3 camForward;
bool basisInitialized;
public bool IsManualPanActive => pointerInput != null && pointerInput.IsPanning || releaseTimer < recenterDelay;
void Awake()
{
if (anchor == null)
{
anchor = GetComponent();
}
if (stateDirector == null)
{
stateDirector = GetComponent();
}
if (brainCamera == null)
{
brainCamera = Camera.main;
}
}
void Start()
{
if (pointerInput == null)
{
var player = GameObject.FindGameObjectWithTag("Player");
if (player != null)
{
pointerInput = player.GetComponent();
}
}
if (pointerInput != null)
{
pointerInput.PanDelta += OnPanDelta;
pointerInput.PanEnded += OnPanEnded;
}
}
void OnDestroy()
{
if (pointerInput != null)
{
pointerInput.PanDelta -= OnPanDelta;
pointerInput.PanEnded -= OnPanEnded;
}
}
void Update()
{
if (anchor == null || stateDirector == null)
{
return;
}
if (stateDirector.AllowsManualPan && pointerInput != null && pointerInput.IsPanning)
{
releaseTimer = 0f;
}
else if (releaseTimer < recenterDelay)
{
releaseTimer += Time.deltaTime;
}
if (ShouldShortenRecenter())
{
releaseTimer = Mathf.Max(releaseTimer, recenterDelay - movementRecenterDelay);
}
if (!stateDirector.AllowsManualPan)
{
return;
}
if (releaseTimer >= recenterDelay && (pointerInput == null || !pointerInput.IsPanning))
{
anchor.ManualPanOffset = Vector3.SmoothDamp(
anchor.ManualPanOffset,
Vector3.zero,
ref recenterVelocity,
recenterSmoothTime);
}
anchor.ClampManualPan(maxPanDistance);
}
void OnPanDelta(Vector2 delta)
{
if (stateDirector == null || !stateDirector.AllowsManualPan || anchor == null)
{
return;
}
EnsureCameraBasis();
anchor.Nudge(MotionInputMath.ScreenDeltaToWorldPan(delta, camRight, camForward, panMetresPerPixel));
anchor.ClampManualPan(maxPanDistance);
}
void OnPanEnded()
{
releaseTimer = 0f;
}
bool ShouldShortenRecenter()
{
var player = GameObject.FindGameObjectWithTag("Player");
if (player == null)
{
return false;
}
var arbiter = player.GetComponent();
return arbiter != null && arbiter.ActiveSource != MotionSource.None;
}
void EnsureCameraBasis()
{
if (brainCamera == null)
{
brainCamera = Camera.main;
}
if (brainCamera == null)
{
return;
}
if (!basisInitialized)
{
camRight = brainCamera.transform.right;
camForward = brainCamera.transform.forward;
basisInitialized = true;
}
}
}
}