Fix : 풀스크린 에디터 버그 제거 및 카메라 조작감 개선
This commit is contained in:
parent
16625c95fa
commit
c1ae4b4379
@ -74,7 +74,9 @@ namespace FullscreenEditor {
|
||||
/// <param name="containerWindow">The ContainerWindow to freeze the repaints.</param>
|
||||
/// <param name="freeze">Wheter to freeze or unfreeze the container.</param>
|
||||
protected void SetFreezeContainer(ContainerWindow containerWindow, bool freeze) {
|
||||
containerWindow.InvokeMethod("SetFreezeDisplay", freeze);
|
||||
// SetFreezeDisplay was removed in Unity 6 - skip if not available
|
||||
if (containerWindow.HasMethod("SetFreezeDisplay", new[] { typeof(bool) }))
|
||||
containerWindow.InvokeMethod("SetFreezeDisplay", freeze);
|
||||
}
|
||||
|
||||
/// <summary>Method that will be called just before creating the ContainerWindow for this fullscreen.</summary>
|
||||
|
||||
@ -4,6 +4,7 @@ using UnityRawInput;
|
||||
using System.Linq;
|
||||
using Unity.Cinemachine;
|
||||
using Streamingle;
|
||||
using KindRetargeting;
|
||||
|
||||
public class CameraManager : MonoBehaviour, IController
|
||||
{
|
||||
@ -130,6 +131,11 @@ public class CameraManager : MonoBehaviour, IController
|
||||
public HotkeyCommand hotkey;
|
||||
[System.NonSerialized] public bool isEditingHotkey = false;
|
||||
|
||||
// 프리셋별 초기 상태 저장
|
||||
[System.NonSerialized] public Vector3 savedPosition;
|
||||
[System.NonSerialized] public Quaternion savedRotation;
|
||||
[System.NonSerialized] public bool hasSavedState = false;
|
||||
|
||||
public CameraPreset(CinemachineCamera camera)
|
||||
{
|
||||
virtualCamera = camera;
|
||||
@ -138,6 +144,21 @@ public class CameraManager : MonoBehaviour, IController
|
||||
}
|
||||
|
||||
public bool IsValid() => virtualCamera != null && hotkey != null;
|
||||
|
||||
public void SaveCurrentState()
|
||||
{
|
||||
if (virtualCamera == null) return;
|
||||
savedPosition = virtualCamera.transform.position;
|
||||
savedRotation = virtualCamera.transform.rotation;
|
||||
hasSavedState = true;
|
||||
}
|
||||
|
||||
public void RestoreSavedState()
|
||||
{
|
||||
if (!hasSavedState || virtualCamera == null) return;
|
||||
virtualCamera.transform.position = savedPosition;
|
||||
virtualCamera.transform.rotation = savedRotation;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -148,31 +169,49 @@ public class CameraManager : MonoBehaviour, IController
|
||||
|
||||
#region Fields
|
||||
[SerializeField] public List<CameraPreset> cameraPresets = new List<CameraPreset>();
|
||||
|
||||
|
||||
[Header("Camera Control Settings")]
|
||||
private float rotationSensitivity = 2f;
|
||||
private float panSpeed = 0.02f;
|
||||
private float zoomSpeed = 0.1f;
|
||||
private float orbitSpeed = 10f;
|
||||
|
||||
[SerializeField, Range(0.5f, 10f)] private float rotationSensitivity = 2f;
|
||||
[SerializeField, Range(0.005f, 0.1f)] private float panSpeed = 0.02f;
|
||||
[SerializeField, Range(0.05f, 0.5f)] private float zoomSpeed = 0.1f;
|
||||
[SerializeField, Range(1f, 20f)] private float orbitSpeed = 10f;
|
||||
|
||||
[Header("Smoothing")]
|
||||
[SerializeField, Range(0f, 0.95f)] private float movementSmoothing = 0.1f;
|
||||
[SerializeField, Range(0f, 0.95f)] private float rotationSmoothing = 0.1f;
|
||||
|
||||
[Header("Zoom Limits")]
|
||||
[SerializeField] private float minZoomDistance = 0.5f;
|
||||
[SerializeField] private float maxZoomDistance = 50f;
|
||||
|
||||
[Header("Rotation Target")]
|
||||
[Tooltip("체크하면 아바타 머리를 자동으로 찾아 회전 중심점으로 사용합니다.")]
|
||||
[SerializeField] private bool useAvatarHeadAsTarget = true;
|
||||
[Tooltip("수동으로 회전 중심점을 지정합니다. (useAvatarHeadAsTarget이 false일 때 사용)")]
|
||||
[SerializeField] private Transform manualRotationTarget;
|
||||
|
||||
private CinemachineCamera currentCamera;
|
||||
private InputHandler inputHandler;
|
||||
private CameraPreset currentPreset;
|
||||
private Vector3 rotationCenter = Vector3.zero;
|
||||
private float currentOrbitDistance = 0f;
|
||||
private float currentOrbitHeight = 0f;
|
||||
private Vector3 rotationStartPosition;
|
||||
private bool isRotating = false;
|
||||
|
||||
// 초기 카메라 상태 저장
|
||||
private Vector3 initialPosition;
|
||||
private Quaternion initialRotation;
|
||||
private bool isInitialStateSet = false;
|
||||
|
||||
|
||||
// 오빗 카메라 상태 (각도 기반)
|
||||
private float horizontalAngle;
|
||||
private float verticalAngle;
|
||||
private float currentDistance;
|
||||
private Vector3 focusPoint;
|
||||
|
||||
// 타겟 값 (스무딩용)
|
||||
private float targetHorizontalAngle;
|
||||
private float targetVerticalAngle;
|
||||
private float targetDistance;
|
||||
private Vector3 targetFocusPoint;
|
||||
|
||||
// 아바타 머리 추적
|
||||
private Transform avatarHeadTransform;
|
||||
|
||||
// 스트림덱 연동
|
||||
private StreamDeckServerManager streamDeckManager;
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
@ -186,15 +225,24 @@ public class CameraManager : MonoBehaviour, IController
|
||||
InitializeInputHandler();
|
||||
InitializeRawInput();
|
||||
InitializeCameraPresets();
|
||||
|
||||
|
||||
// StreamDeckServerManager 찾기
|
||||
streamDeckManager = FindObjectOfType<StreamDeckServerManager>();
|
||||
streamDeckManager = FindAnyObjectByType<StreamDeckServerManager>();
|
||||
if (streamDeckManager == null)
|
||||
{
|
||||
Debug.LogWarning("[CameraManager] StreamDeckServerManager를 찾을 수 없습니다. 스트림덱 연동이 비활성화됩니다.");
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Start에서 아바타 머리 다시 찾기 (다른 스크립트들이 초기화된 후)
|
||||
if (useAvatarHeadAsTarget && avatarHeadTransform == null)
|
||||
{
|
||||
FindAvatarHead();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (RawInput.IsRunning)
|
||||
@ -263,16 +311,71 @@ public class CameraManager : MonoBehaviour, IController
|
||||
{
|
||||
preset.hotkey.InitializeUnityKeys();
|
||||
}
|
||||
|
||||
Set(0);
|
||||
|
||||
// 초기 카메라 상태 저장
|
||||
if (currentCamera != null && !isInitialStateSet)
|
||||
|
||||
// 모든 프리셋의 초기 상태 저장
|
||||
foreach (var preset in cameraPresets.Where(p => p?.IsValid() == true))
|
||||
{
|
||||
initialPosition = currentCamera.transform.position;
|
||||
initialRotation = currentCamera.transform.rotation;
|
||||
isInitialStateSet = true;
|
||||
if (!preset.hasSavedState)
|
||||
{
|
||||
preset.SaveCurrentState();
|
||||
}
|
||||
}
|
||||
|
||||
// 아바타 머리 찾기
|
||||
FindAvatarHead();
|
||||
|
||||
Set(0);
|
||||
}
|
||||
|
||||
private void FindAvatarHead()
|
||||
{
|
||||
if (!useAvatarHeadAsTarget) return;
|
||||
|
||||
// CustomRetargetingScript를 가진 아바타 찾기
|
||||
var retargetingScripts = FindObjectsByType<CustomRetargetingScript>(FindObjectsSortMode.None);
|
||||
|
||||
foreach (var script in retargetingScripts)
|
||||
{
|
||||
if (script == null || !script.gameObject.activeInHierarchy) continue;
|
||||
|
||||
// targetAnimator가 설정되어 있으면 사용
|
||||
Animator animator = script.targetAnimator;
|
||||
|
||||
// targetAnimator가 null이면 같은 GameObject의 Animator 시도
|
||||
if (animator == null)
|
||||
{
|
||||
animator = script.GetComponent<Animator>();
|
||||
}
|
||||
|
||||
if (animator != null)
|
||||
{
|
||||
avatarHeadTransform = animator.GetBoneTransform(HumanBodyBones.Head);
|
||||
if (avatarHeadTransform != null)
|
||||
{
|
||||
Debug.Log($"[CameraManager] 아바타 머리를 회전 중심점으로 설정: {avatarHeadTransform.name}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.LogWarning("[CameraManager] 활성화된 아바타의 Head 본을 찾을 수 없습니다. 수동 타겟을 사용하거나 원점을 사용합니다.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 현재 회전 중심점을 반환합니다.
|
||||
/// 우선순위: 아바타 머리 > 수동 타겟 > 원점
|
||||
/// </summary>
|
||||
private Vector3 GetRotationCenter()
|
||||
{
|
||||
if (useAvatarHeadAsTarget && avatarHeadTransform != null)
|
||||
{
|
||||
return avatarHeadTransform.position;
|
||||
}
|
||||
else if (manualRotationTarget != null)
|
||||
{
|
||||
return manualRotationTarget.position;
|
||||
}
|
||||
return Vector3.zero;
|
||||
}
|
||||
|
||||
|
||||
@ -312,12 +415,36 @@ public class CameraManager : MonoBehaviour, IController
|
||||
#endregion
|
||||
|
||||
#region Camera Controls
|
||||
|
||||
/// <summary>
|
||||
/// 현재 카메라 위치에서 각도와 거리를 초기화합니다.
|
||||
/// </summary>
|
||||
private void InitializeOrbitState()
|
||||
{
|
||||
if (currentCamera == null) return;
|
||||
|
||||
focusPoint = GetRotationCenter();
|
||||
targetFocusPoint = focusPoint;
|
||||
|
||||
Vector3 direction = currentCamera.transform.position - focusPoint;
|
||||
currentDistance = direction.magnitude;
|
||||
targetDistance = currentDistance;
|
||||
|
||||
if (currentDistance > 0.01f)
|
||||
{
|
||||
direction.Normalize();
|
||||
horizontalAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg;
|
||||
verticalAngle = Mathf.Asin(Mathf.Clamp(direction.y, -1f, 1f)) * Mathf.Rad2Deg;
|
||||
}
|
||||
|
||||
targetHorizontalAngle = horizontalAngle;
|
||||
targetVerticalAngle = verticalAngle;
|
||||
}
|
||||
|
||||
private void HandleCameraControls()
|
||||
{
|
||||
if (!IsValidSetup) return;
|
||||
|
||||
var virtualCamera = currentCamera;
|
||||
if (virtualCamera == null) return;
|
||||
if (currentCamera == null) return;
|
||||
|
||||
// Alt+Q로 초기 위치로 복원
|
||||
if (Input.GetKey(KeyCode.LeftAlt) && Input.GetKeyDown(KeyCode.Q))
|
||||
@ -326,141 +453,166 @@ public class CameraManager : MonoBehaviour, IController
|
||||
return;
|
||||
}
|
||||
|
||||
HandleRotation(virtualCamera);
|
||||
HandlePanning(virtualCamera);
|
||||
HandleZooming(virtualCamera);
|
||||
HandleOrbiting(virtualCamera);
|
||||
HandleInput();
|
||||
UpdateCameraPosition();
|
||||
}
|
||||
|
||||
private void HandleRotation(CinemachineCamera virtualCamera)
|
||||
private void HandleInput()
|
||||
{
|
||||
Transform cameraTransform = virtualCamera.transform;
|
||||
|
||||
if (inputHandler.IsRightMouseHeld())
|
||||
// 입력 우선순위 처리: Orbit > AltRightZoom > Zoom > Rotation > Panning
|
||||
if (inputHandler.IsOrbitActive())
|
||||
{
|
||||
if (!isRotating)
|
||||
{
|
||||
// 회전 시작 시 현재 상태 저장
|
||||
isRotating = true;
|
||||
rotationStartPosition = cameraTransform.position;
|
||||
rotationCenter = new Vector3(0f, rotationStartPosition.y, 0f);
|
||||
|
||||
// 현재 카메라의 회전 중심점으로부터의 거리와 높이 계산
|
||||
Vector3 toCamera = cameraTransform.position - rotationCenter;
|
||||
currentOrbitDistance = new Vector3(toCamera.x, 0f, toCamera.z).magnitude;
|
||||
currentOrbitHeight = toCamera.y;
|
||||
}
|
||||
HandleOrbiting();
|
||||
}
|
||||
else if (inputHandler.IsCtrlRightZoomActive())
|
||||
{
|
||||
HandleCtrlRightZoom();
|
||||
}
|
||||
else if (inputHandler.IsZoomActive())
|
||||
{
|
||||
HandleDragZoom();
|
||||
}
|
||||
else if (inputHandler.IsRightMouseHeld())
|
||||
{
|
||||
HandleRotation();
|
||||
}
|
||||
else if (inputHandler.IsMiddleMouseHeld())
|
||||
{
|
||||
HandlePanning();
|
||||
}
|
||||
|
||||
Vector2 lookDelta = inputHandler.GetLookDelta();
|
||||
if (lookDelta.sqrMagnitude < float.Epsilon) return;
|
||||
|
||||
// 현재 회전값을 오일러 각도로 가져오기
|
||||
Vector3 currentEuler = cameraTransform.eulerAngles;
|
||||
|
||||
// Y축 회전만 적용 (수평 회전)
|
||||
float newY = currentEuler.y + lookDelta.x * rotationSensitivity;
|
||||
|
||||
// 회전 적용 (X축 회전은 0으로 고정)
|
||||
Quaternion targetRotation = Quaternion.Euler(0f, newY, 0f);
|
||||
|
||||
// 오비탈 회전을 위한 새로운 위치 계산
|
||||
Vector3 orbitPosition = targetRotation * Vector3.back * currentOrbitDistance;
|
||||
orbitPosition.y = currentOrbitHeight; // 높이 유지
|
||||
|
||||
// 회전 중심점을 기준으로 새로운 위치 설정
|
||||
cameraTransform.position = rotationCenter + orbitPosition;
|
||||
cameraTransform.rotation = targetRotation;
|
||||
// 휠 줌은 항상 처리
|
||||
HandleWheelZoom();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 우클릭 드래그: 수평 + 수직 회전 (현재 비활성화 - Alt+우클릭 사용)
|
||||
/// </summary>
|
||||
private void HandleRotation()
|
||||
{
|
||||
// 우클릭만으로는 회전하지 않음 - Alt+우클릭(Orbit)으로 대체
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alt + 우클릭: 자유 궤도 회전 (X, Y축)
|
||||
/// </summary>
|
||||
private void HandleOrbiting()
|
||||
{
|
||||
Vector2 delta = inputHandler.GetLookDelta();
|
||||
if (delta.sqrMagnitude < float.Epsilon) return;
|
||||
|
||||
// 회전 속도
|
||||
targetHorizontalAngle += delta.x * rotationSensitivity;
|
||||
targetVerticalAngle -= delta.y * rotationSensitivity;
|
||||
targetVerticalAngle = Mathf.Clamp(targetVerticalAngle, -80f, 80f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 휠클릭 드래그: 패닝 (초점 이동)
|
||||
/// </summary>
|
||||
private void HandlePanning()
|
||||
{
|
||||
Vector2 delta = inputHandler.GetLookDelta();
|
||||
if (delta.sqrMagnitude < float.Epsilon) return;
|
||||
|
||||
// 거리에 비례하여 패닝 속도 조절 - 0.2배
|
||||
float speedMultiplier = targetDistance * panSpeed * 0.175f;
|
||||
|
||||
// 카메라의 로컬 축 기준으로 초점 이동
|
||||
Vector3 right = currentCamera.transform.right;
|
||||
Vector3 up = currentCamera.transform.up;
|
||||
|
||||
Vector3 panOffset = (-right * delta.x - up * delta.y) * speedMultiplier;
|
||||
targetFocusPoint += panOffset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 마우스 휠: 줌
|
||||
/// </summary>
|
||||
private void HandleWheelZoom()
|
||||
{
|
||||
float scroll = inputHandler.GetZoomDelta();
|
||||
if (Mathf.Abs(scroll) < 0.01f) return;
|
||||
|
||||
// 거리에 비례하여 줌 속도 조절 (더 자연스러운 느낌) - 0.4배
|
||||
float zoomDelta = scroll * zoomSpeed * targetDistance * 0.4f;
|
||||
targetDistance -= zoomDelta;
|
||||
targetDistance = Mathf.Clamp(targetDistance, minZoomDistance, maxZoomDistance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ctrl + 좌클릭 드래그: 줌
|
||||
/// </summary>
|
||||
private void HandleDragZoom()
|
||||
{
|
||||
Vector2 delta = inputHandler.GetLookDelta();
|
||||
if (delta.sqrMagnitude < float.Epsilon) return;
|
||||
|
||||
float zoomDelta = delta.y * zoomSpeed * targetDistance * 0.5f;
|
||||
targetDistance -= zoomDelta;
|
||||
targetDistance = Mathf.Clamp(targetDistance, minZoomDistance, maxZoomDistance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ctrl + 우클릭 드래그: 줌 (밀기 = 확대, 당기기 = 축소)
|
||||
/// </summary>
|
||||
private void HandleCtrlRightZoom()
|
||||
{
|
||||
Vector2 delta = inputHandler.GetLookDelta();
|
||||
if (delta.sqrMagnitude < float.Epsilon) return;
|
||||
|
||||
// 위로 밀면 확대 (거리 감소), 아래로 밀면 축소 (거리 증가)
|
||||
float zoomDelta = delta.y * zoomSpeed * targetDistance * 0.5f;
|
||||
targetDistance -= zoomDelta;
|
||||
targetDistance = Mathf.Clamp(targetDistance, minZoomDistance, maxZoomDistance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 스무딩을 적용하여 카메라 위치 업데이트
|
||||
/// </summary>
|
||||
private void UpdateCameraPosition()
|
||||
{
|
||||
float dt = Time.deltaTime;
|
||||
|
||||
// 스무딩 적용
|
||||
if (movementSmoothing > 0.01f)
|
||||
{
|
||||
float smoothSpeed = (1f - movementSmoothing) * 15f;
|
||||
horizontalAngle = Mathf.Lerp(horizontalAngle, targetHorizontalAngle, dt * smoothSpeed);
|
||||
verticalAngle = Mathf.Lerp(verticalAngle, targetVerticalAngle, dt * smoothSpeed);
|
||||
currentDistance = Mathf.Lerp(currentDistance, targetDistance, dt * smoothSpeed);
|
||||
focusPoint = Vector3.Lerp(focusPoint, targetFocusPoint, dt * smoothSpeed);
|
||||
}
|
||||
else
|
||||
{
|
||||
isRotating = false;
|
||||
horizontalAngle = targetHorizontalAngle;
|
||||
verticalAngle = targetVerticalAngle;
|
||||
currentDistance = targetDistance;
|
||||
focusPoint = targetFocusPoint;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandlePanning(CinemachineCamera virtualCamera)
|
||||
{
|
||||
if (!inputHandler.IsMiddleMouseHeld()) return;
|
||||
// 구면 좌표계에서 카메라 위치 계산
|
||||
float horizontalRad = horizontalAngle * Mathf.Deg2Rad;
|
||||
float verticalRad = verticalAngle * Mathf.Deg2Rad;
|
||||
|
||||
Vector2 panDelta = inputHandler.GetLookDelta();
|
||||
if (panDelta.sqrMagnitude < float.Epsilon) return;
|
||||
Vector3 offset = new Vector3(
|
||||
Mathf.Sin(horizontalRad) * Mathf.Cos(verticalRad),
|
||||
Mathf.Sin(verticalRad),
|
||||
Mathf.Cos(horizontalRad) * Mathf.Cos(verticalRad)
|
||||
) * currentDistance;
|
||||
|
||||
Transform cameraTransform = virtualCamera.transform;
|
||||
|
||||
// 이동 적용 (카메라의 right와 up 방향으로 이동)
|
||||
Vector3 right = cameraTransform.right * -panDelta.x * panSpeed;
|
||||
Vector3 up = cameraTransform.up * -panDelta.y * panSpeed;
|
||||
|
||||
cameraTransform.position += right + up;
|
||||
}
|
||||
|
||||
private void HandleZooming(CinemachineCamera virtualCamera)
|
||||
{
|
||||
if (inputHandler.IsZoomActive())
|
||||
{
|
||||
// Ctrl + 좌클릭으로 줌
|
||||
Vector2 lookDelta = inputHandler.GetLookDelta();
|
||||
if (lookDelta.sqrMagnitude < float.Epsilon) return;
|
||||
|
||||
Transform cameraTransform = virtualCamera.transform;
|
||||
Vector3 forward = cameraTransform.forward * lookDelta.y * zoomSpeed * 10f;
|
||||
cameraTransform.position += forward;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 마우스 휠로 줌
|
||||
float zoomDelta = inputHandler.GetZoomDelta();
|
||||
if (Mathf.Abs(zoomDelta) <= 0.1f) return;
|
||||
|
||||
Transform cameraTransform = virtualCamera.transform;
|
||||
Vector3 forward = cameraTransform.forward * zoomDelta * zoomSpeed;
|
||||
cameraTransform.position += forward;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleOrbiting(CinemachineCamera virtualCamera)
|
||||
{
|
||||
if (!inputHandler.IsOrbitActive()) return;
|
||||
|
||||
Vector2 orbitDelta = inputHandler.GetLookDelta();
|
||||
if (orbitDelta.sqrMagnitude < float.Epsilon) return;
|
||||
|
||||
Transform cameraTransform = virtualCamera.transform;
|
||||
|
||||
// 현재 회전값을 오일러 각도로 가져오기
|
||||
Vector3 currentEuler = cameraTransform.eulerAngles;
|
||||
|
||||
// X축 회전값을 -80도에서 80도 사이로 제한하기 위해 360도 형식에서 변환
|
||||
float currentX = currentEuler.x;
|
||||
if (currentX > 180f) currentX -= 360f;
|
||||
|
||||
// 새로운 회전값 계산
|
||||
float newX = currentX - orbitDelta.y * orbitSpeed;
|
||||
float newY = currentEuler.y + orbitDelta.x * orbitSpeed;
|
||||
|
||||
// X축 회전 제한 (-80도 ~ 80도)
|
||||
newX = Mathf.Clamp(newX, -80f, 80f);
|
||||
|
||||
// 회전 적용
|
||||
Quaternion targetRotation = Quaternion.Euler(newX, newY, 0f);
|
||||
cameraTransform.rotation = targetRotation;
|
||||
|
||||
// 원점으로부터의 거리 유지
|
||||
float distance = cameraTransform.position.magnitude;
|
||||
|
||||
// 새로운 위치 계산 (원점으로부터의 거리 유지)
|
||||
Vector3 newPosition = targetRotation * Vector3.back * distance;
|
||||
cameraTransform.position = newPosition;
|
||||
currentCamera.transform.position = focusPoint + offset;
|
||||
currentCamera.transform.LookAt(focusPoint);
|
||||
}
|
||||
|
||||
private void RestoreInitialCameraState()
|
||||
{
|
||||
if (!isInitialStateSet || currentCamera == null) return;
|
||||
if (currentPreset == null || !currentPreset.hasSavedState) return;
|
||||
|
||||
currentCamera.transform.position = initialPosition;
|
||||
currentCamera.transform.rotation = initialRotation;
|
||||
|
||||
// 회전 중심점 초기화
|
||||
rotationCenter = new Vector3(0f, initialPosition.y, 0f);
|
||||
currentPreset.RestoreSavedState();
|
||||
|
||||
// 각도 상태 다시 초기화
|
||||
InitializeOrbitState();
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -494,15 +646,18 @@ public class CameraManager : MonoBehaviour, IController
|
||||
|
||||
currentPreset = newPreset;
|
||||
UpdateCameraPriorities(newPreset.virtualCamera);
|
||||
|
||||
|
||||
// 오빗 상태 초기화 (각도, 거리 계산)
|
||||
InitializeOrbitState();
|
||||
|
||||
OnCameraChanged?.Invoke(oldPreset, newPreset);
|
||||
|
||||
|
||||
// 스트림덱에 카메라 변경 알림 전송
|
||||
if (streamDeckManager != null)
|
||||
{
|
||||
streamDeckManager.NotifyCameraChanged();
|
||||
}
|
||||
|
||||
|
||||
Debug.Log($"[CameraManager] 카메라 전환 완료: {newCameraName}");
|
||||
}
|
||||
|
||||
|
||||
@ -8,14 +8,28 @@ public class InputHandler : MonoBehaviour
|
||||
private bool isMiddleMouseHeld;
|
||||
private bool isOrbitActive;
|
||||
private bool isZoomActive;
|
||||
|
||||
private bool isCtrlRightZoomActive;
|
||||
|
||||
// 현재 활성화된 입력 모드 (충돌 방지)
|
||||
private InputMode currentMode = InputMode.None;
|
||||
|
||||
private enum InputMode
|
||||
{
|
||||
None,
|
||||
Orbit, // Alt + 우클릭 또는 Alt + 좌클릭
|
||||
Zoom, // Ctrl + 좌클릭
|
||||
CtrlRightZoom, // Ctrl + 우클릭
|
||||
Rotation, // 우클릭
|
||||
Pan // 휠클릭
|
||||
}
|
||||
|
||||
// 카메라 컨트롤 시스템 참조
|
||||
private CameraControlSystem cameraControlSystem;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// CameraControlSystem 찾기
|
||||
cameraControlSystem = FindObjectOfType<CameraControlSystem>();
|
||||
cameraControlSystem = FindAnyObjectByType<CameraControlSystem>();
|
||||
if (cameraControlSystem == null)
|
||||
{
|
||||
Debug.LogWarning("[InputHandler] CameraControlSystem을 찾을 수 없습니다.");
|
||||
@ -24,11 +38,72 @@ public class InputHandler : MonoBehaviour
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// 마우스 버튼 상태 업데이트
|
||||
isRightMouseHeld = Input.GetMouseButton(1);
|
||||
isMiddleMouseHeld = Input.GetMouseButton(2);
|
||||
isOrbitActive = Input.GetKey(KeyCode.LeftAlt) && Input.GetMouseButton(0); // Alt + 좌클릭으로 궤도 회전
|
||||
isZoomActive = Input.GetKey(KeyCode.LeftControl) && Input.GetMouseButton(0); // Ctrl + 좌클릭으로 줌
|
||||
// 마우스 버튼 Raw 상태
|
||||
bool leftMouse = Input.GetMouseButton(0);
|
||||
bool rightMouse = Input.GetMouseButton(1);
|
||||
bool middleMouse = Input.GetMouseButton(2);
|
||||
bool altKey = Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt);
|
||||
bool ctrlKey = Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl);
|
||||
|
||||
// 모든 마우스 버튼이 해제되면 모드 리셋
|
||||
if (!leftMouse && !rightMouse && !middleMouse)
|
||||
{
|
||||
currentMode = InputMode.None;
|
||||
}
|
||||
|
||||
// 입력 우선순위에 따라 모드 결정 (이미 활성화된 모드가 없을 때만)
|
||||
if (currentMode == InputMode.None)
|
||||
{
|
||||
if (altKey && (rightMouse || leftMouse))
|
||||
{
|
||||
currentMode = InputMode.Orbit;
|
||||
}
|
||||
else if (ctrlKey && rightMouse)
|
||||
{
|
||||
currentMode = InputMode.CtrlRightZoom;
|
||||
}
|
||||
else if (ctrlKey && leftMouse)
|
||||
{
|
||||
currentMode = InputMode.Zoom;
|
||||
}
|
||||
else if (rightMouse)
|
||||
{
|
||||
currentMode = InputMode.Rotation;
|
||||
}
|
||||
else if (middleMouse)
|
||||
{
|
||||
currentMode = InputMode.Pan;
|
||||
}
|
||||
}
|
||||
|
||||
// 현재 모드에 따라 상태 설정
|
||||
isOrbitActive = (currentMode == InputMode.Orbit) && (rightMouse || leftMouse) && altKey;
|
||||
isZoomActive = (currentMode == InputMode.Zoom) && leftMouse && ctrlKey;
|
||||
isCtrlRightZoomActive = (currentMode == InputMode.CtrlRightZoom) && rightMouse && ctrlKey;
|
||||
isRightMouseHeld = (currentMode == InputMode.Rotation) && rightMouse;
|
||||
isMiddleMouseHeld = (currentMode == InputMode.Pan) && middleMouse;
|
||||
|
||||
// 모드가 해제되면 None으로 전환
|
||||
if (currentMode == InputMode.Orbit && ((!rightMouse && !leftMouse) || !altKey))
|
||||
{
|
||||
currentMode = InputMode.None;
|
||||
}
|
||||
else if (currentMode == InputMode.CtrlRightZoom && (!rightMouse || !ctrlKey))
|
||||
{
|
||||
currentMode = InputMode.None;
|
||||
}
|
||||
else if (currentMode == InputMode.Zoom && (!leftMouse || !ctrlKey))
|
||||
{
|
||||
currentMode = InputMode.None;
|
||||
}
|
||||
else if (currentMode == InputMode.Rotation && !rightMouse)
|
||||
{
|
||||
currentMode = InputMode.None;
|
||||
}
|
||||
else if (currentMode == InputMode.Pan && !middleMouse)
|
||||
{
|
||||
currentMode = InputMode.None;
|
||||
}
|
||||
|
||||
// 마우스 위치 업데이트
|
||||
lastMousePosition = Input.mousePosition;
|
||||
@ -39,6 +114,12 @@ public class InputHandler : MonoBehaviour
|
||||
public bool IsMiddleMouseHeld() => isMiddleMouseHeld;
|
||||
public bool IsOrbitActive() => isOrbitActive;
|
||||
public bool IsZoomActive() => isZoomActive;
|
||||
public bool IsCtrlRightZoomActive() => isCtrlRightZoomActive;
|
||||
|
||||
/// <summary>
|
||||
/// 현재 어떤 입력 모드도 활성화되지 않았는지 확인합니다.
|
||||
/// </summary>
|
||||
public bool IsIdle() => currentMode == InputMode.None;
|
||||
|
||||
public Vector2 GetLookDelta()
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user