VanguardReMaster/client/Assets/Vanguard/Runtime/Board3D/View/BoardCameraRig.cs

133 lines
4.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
namespace Vanguard.Board3D
{
/// <summary>
/// Ограниченная орбита камеры: ПКМ — поворот, СКМ — панорама,
/// колесо — зум. Левая кнопка остаётся картам и UI.
/// </summary>
public sealed class BoardCameraRig : MonoBehaviour
{
private PlaymatLayoutConfig _config;
private Vector3 _target;
private float _distance = 15f;
private float _yaw;
private float _pitch = 35f;
private bool _orbiting;
private bool _panning;
private Vector2 _lastPointer;
public void Configure(PlaymatLayoutConfig config)
{
_config = config != null ? config : PlaymatLayoutConfig.Default;
_target = _config.cameraTarget;
var offset = _config.cameraPosition - _target;
_distance = Mathf.Clamp(
offset.magnitude,
_config.zoomMin,
_config.zoomMax);
_pitch = Mathf.Clamp(
Mathf.Asin(Mathf.Clamp(offset.y / Mathf.Max(0.001f, _distance), -1f, 1f))
* Mathf.Rad2Deg,
_config.orbitPitchMin,
_config.orbitPitchMax);
_yaw = Mathf.Atan2(-offset.x, -offset.z) * Mathf.Rad2Deg;
_yaw = Mathf.Clamp(_yaw, -_config.orbitYawLimit, _config.orbitYawLimit);
Apply();
}
private void Update()
{
if (_config == null)
return;
var mouse = Mouse.current;
if (mouse == null)
return;
var pointer = mouse.position.ReadValue();
var overUi = IsPointerOverUi();
if (mouse.rightButton.wasPressedThisFrame && !overUi)
{
_orbiting = true;
_lastPointer = pointer;
}
if (mouse.rightButton.wasReleasedThisFrame)
_orbiting = false;
if (_orbiting && mouse.rightButton.isPressed)
{
var delta = pointer - _lastPointer;
_lastPointer = pointer;
_yaw = Mathf.Clamp(
_yaw + (delta.x * 0.18f),
-_config.orbitYawLimit,
_config.orbitYawLimit);
_pitch = Mathf.Clamp(
_pitch - (delta.y * 0.16f),
_config.orbitPitchMin,
_config.orbitPitchMax);
Apply();
}
if (mouse.middleButton.wasPressedThisFrame && !overUi)
{
_panning = true;
_lastPointer = pointer;
}
if (mouse.middleButton.wasReleasedThisFrame)
_panning = false;
if (_panning && mouse.middleButton.isPressed)
{
var delta = pointer - _lastPointer;
_lastPointer = pointer;
var rotation = Quaternion.Euler(_pitch, _yaw, 0f);
var right = rotation * Vector3.right;
var forward = rotation * Vector3.forward;
right.y = 0f;
forward.y = 0f;
right.Normalize();
forward.Normalize();
var scale = _config.panSpeed * _distance;
_target -= (right * (delta.x * scale)) + (forward * (delta.y * scale));
_target.x = Mathf.Clamp(_target.x, -2.5f, 2.5f);
_target.z = Mathf.Clamp(_target.z, -2f, 2f);
Apply();
}
var scroll = mouse.scroll.ReadValue().y;
if (!overUi && Mathf.Abs(scroll) > 0.01f)
{
_distance = Mathf.Clamp(
_distance - (scroll * _config.zoomSpeed),
_config.zoomMin,
_config.zoomMax);
Apply();
}
}
private void Apply()
{
var rotation = Quaternion.Euler(_pitch, _yaw, 0f);
transform.rotation = rotation;
transform.position = _target - (rotation * Vector3.forward * _distance);
var camera = GetComponent<Camera>();
if (camera != null)
camera.fieldOfView = _config.cameraFov;
}
private static bool IsPointerOverUi()
{
var eventSystem = EventSystem.current;
return eventSystem != null && eventSystem.IsPointerOverGameObject();
}
}
}