Initial commit
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
public class CameraControl : MonoBehaviour
|
||||
{
|
||||
[Header("Dependencies")]
|
||||
private BaseInputProvider inputProvider;
|
||||
|
||||
[Header("Settings")]
|
||||
public Transform pivotPoint;
|
||||
public LayerMask obstacleLayer;
|
||||
|
||||
[Header("Speeds")]
|
||||
public float panSpeed = 0.5f;
|
||||
public float rotateSpeed = 5.0f;
|
||||
public float zoomSpeed = 5.0f;
|
||||
public float minZoom = 2.0f;
|
||||
public float maxZoom = 50.0f;
|
||||
|
||||
[Header("Smoothness")]
|
||||
public bool enableSmoothing = true;
|
||||
public float smoothTime = 0.1f;
|
||||
|
||||
// ---- Internal State ----
|
||||
private Vector3 _targetPosition;
|
||||
private Quaternion _targetRotation;
|
||||
private float _targetZoom;
|
||||
private Vector3 _currentVelocity;
|
||||
|
||||
private bool _isPanning;
|
||||
private bool _isOrbiting;
|
||||
private Vector2 _cursorScreenPos; // kept up to date by OnCursorMoved
|
||||
|
||||
private Camera _cam;
|
||||
|
||||
public bool isInputLocked = false;
|
||||
|
||||
private bool isInitialized = false;
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Lifecycle
|
||||
// -------------------------------------------------------
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_cam = GetComponent<Camera>();
|
||||
if (pivotPoint == null)
|
||||
{
|
||||
var pivotObj = new GameObject("CameraPivot");
|
||||
pivotObj.transform.position = transform.position + transform.forward * 10f;
|
||||
pivotPoint = pivotObj.transform;
|
||||
}
|
||||
|
||||
_targetPosition = pivotPoint.position;
|
||||
_targetRotation = pivotPoint.rotation;
|
||||
_targetZoom = Vector3.Distance(transform.position, pivotPoint.position);
|
||||
|
||||
inputProvider = InputProviderManager.getInstance()?.getCurrentInputProvider();
|
||||
|
||||
inputProvider.OnCursorMoved.AddListener(OnCursorMoved);
|
||||
inputProvider.OnCursorDelta.AddListener(OnCursorDelta);
|
||||
inputProvider.OnPanStart.AddListener(OnPanStart);
|
||||
inputProvider.OnPanEnd.AddListener(OnPanEnd);
|
||||
inputProvider.OnRotateStart.AddListener(OnRotateStart);
|
||||
inputProvider.OnRotateEnd.AddListener(OnRotateEnd);
|
||||
inputProvider.OnZoom.AddListener(OnZoom);
|
||||
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (!isInitialized) return;
|
||||
|
||||
inputProvider.OnCursorMoved.AddListener(OnCursorMoved);
|
||||
inputProvider.OnCursorDelta.AddListener(OnCursorDelta);
|
||||
inputProvider.OnPanStart.AddListener(OnPanStart);
|
||||
inputProvider.OnPanEnd.AddListener(OnPanEnd);
|
||||
inputProvider.OnRotateStart.AddListener(OnRotateStart);
|
||||
inputProvider.OnRotateEnd.AddListener(OnRotateEnd);
|
||||
inputProvider.OnZoom.AddListener(OnZoom);
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
inputProvider.OnCursorMoved.RemoveListener(OnCursorMoved);
|
||||
inputProvider.OnCursorDelta.RemoveListener(OnCursorDelta);
|
||||
inputProvider.OnPanStart.RemoveListener(OnPanStart);
|
||||
inputProvider.OnPanEnd.RemoveListener(OnPanEnd);
|
||||
inputProvider.OnRotateStart.RemoveListener(OnRotateStart);
|
||||
inputProvider.OnRotateEnd.RemoveListener(OnRotateEnd);
|
||||
inputProvider.OnZoom.RemoveListener(OnZoom);
|
||||
}
|
||||
|
||||
private void LateUpdate() => ApplyMovement();
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Input event handlers
|
||||
// -------------------------------------------------------
|
||||
|
||||
private void OnCursorMoved(Vector2 screenPos)
|
||||
{
|
||||
_cursorScreenPos = screenPos;
|
||||
}
|
||||
|
||||
private void OnPanStart(Vector2 cursorScreenPos)
|
||||
{
|
||||
if (isInputLocked) return;
|
||||
|
||||
Ray ray = _cam.ScreenPointToRay(cursorScreenPos);
|
||||
_isPanning = !Physics.Raycast(ray, out _, 1000f, obstacleLayer);
|
||||
}
|
||||
|
||||
private void OnPanEnd() => _isPanning = false;
|
||||
|
||||
private void OnRotateStart()
|
||||
{
|
||||
if (!isInputLocked) _isOrbiting = true;
|
||||
}
|
||||
|
||||
private void OnRotateEnd() => _isOrbiting = false;
|
||||
|
||||
private void OnCursorDelta(Vector2 delta)
|
||||
{
|
||||
if (_isPanning)
|
||||
{
|
||||
if (!InputModeManager.Is(InputMode.Camera)) return;
|
||||
Vector3 move = -transform.right * (delta.x * panSpeed * 0.01f)
|
||||
+ -transform.up * (delta.y * panSpeed * 0.01f);
|
||||
_targetPosition += move;
|
||||
}
|
||||
|
||||
if (_isOrbiting)
|
||||
{
|
||||
float mouseX = delta.x * rotateSpeed;
|
||||
float mouseY = -delta.y * rotateSpeed;
|
||||
|
||||
Vector3 euler = _targetRotation.eulerAngles;
|
||||
euler.y += mouseX;
|
||||
euler.x += mouseY;
|
||||
|
||||
if (euler.x > 180f) euler.x -= 360f;
|
||||
euler.x = Mathf.Clamp(euler.x, -85f, 85f);
|
||||
|
||||
_targetRotation = Quaternion.Euler(euler);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnZoom(float scrollValue)
|
||||
{
|
||||
if (!InputModeManager.Is(InputMode.Camera)) return;
|
||||
|
||||
_targetZoom -= scrollValue * zoomSpeed * 0.05f;
|
||||
_targetZoom = Mathf.Clamp(_targetZoom, minZoom, maxZoom);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Movement application (unchanged logic)
|
||||
// -------------------------------------------------------
|
||||
|
||||
private void ApplyMovement()
|
||||
{
|
||||
if (enableSmoothing)
|
||||
{
|
||||
pivotPoint.position = Vector3.SmoothDamp(
|
||||
pivotPoint.position, _targetPosition, ref _currentVelocity, smoothTime);
|
||||
|
||||
pivotPoint.rotation = Quaternion.Slerp(
|
||||
pivotPoint.rotation, _targetRotation, Time.deltaTime * (1f / smoothTime));
|
||||
}
|
||||
else
|
||||
{
|
||||
pivotPoint.position = _targetPosition;
|
||||
pivotPoint.rotation = _targetRotation;
|
||||
}
|
||||
|
||||
transform.position = pivotPoint.position - pivotPoint.forward * _targetZoom;
|
||||
transform.LookAt(pivotPoint);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Public API
|
||||
// -------------------------------------------------------
|
||||
|
||||
public void SnapToDirection(Vector3 direction)
|
||||
{
|
||||
Vector3 cameraUp = Mathf.Abs(Vector3.Dot(direction, Vector3.up)) > 0.99f
|
||||
? Vector3.forward
|
||||
: Vector3.up;
|
||||
|
||||
_targetRotation = Quaternion.LookRotation(direction, cameraUp);
|
||||
_targetPosition = pivotPoint.position;
|
||||
_currentVelocity = Vector3.zero;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
// Gizmos
|
||||
// -------------------------------------------------------
|
||||
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
if (pivotPoint == null) return;
|
||||
|
||||
Gizmos.color = Color.yellow;
|
||||
Gizmos.DrawWireSphere(pivotPoint.position, 0.5f);
|
||||
Gizmos.DrawLine(transform.position, pivotPoint.position);
|
||||
|
||||
Gizmos.color = Color.cyan;
|
||||
Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
|
||||
Gizmos.DrawFrustum(Vector3.zero, GetComponent<Camera>().fieldOfView, maxZoom, minZoom, 1.0f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ff809502f69bf4419a49383fe2deff4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "Scripts.Camera",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:d5be31af97e8e5e458cc6c5d560bb7cc"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7239d94c510c9fd4da3ba5963eadd5d6
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,132 @@
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
public class ViewCubeController : MonoBehaviour
|
||||
{
|
||||
[Header("References")]
|
||||
public Camera mainCam; // The Base Camera
|
||||
public Camera viewCubeCam; // The Overlay Camera/Texture Camera
|
||||
private CameraControl CameraController; // Your camera movement script
|
||||
public RawImage viewCubeImage;
|
||||
private EventTrigger eventTrigger;
|
||||
private bool isPointerInViewCube = false;
|
||||
|
||||
[Header("Settings")]
|
||||
private Transform cubeContainer;
|
||||
public LayerMask viewCubeLayer;
|
||||
|
||||
// NEW: We need the RectTransform to calculate positions correctly
|
||||
private RectTransform rawImageRect;
|
||||
// NEW: Store the last ray for debugging in Gizmos
|
||||
private Ray debugRay;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
cubeContainer = transform;
|
||||
if (mainCam) CameraController = mainCam.GetComponent<CameraControl>();
|
||||
|
||||
// Cache the RectTransform so we can access width/height later
|
||||
rawImageRect = viewCubeImage.GetComponent<RectTransform>();
|
||||
|
||||
eventTrigger = viewCubeImage.GetComponent<EventTrigger>();
|
||||
|
||||
EventTrigger.Entry entry = new EventTrigger.Entry();
|
||||
entry.eventID = EventTriggerType.PointerEnter;
|
||||
entry.callback.AddListener((data) => { isPointerInViewCube = true; });
|
||||
eventTrigger.triggers.Add(entry);
|
||||
|
||||
entry = new EventTrigger.Entry();
|
||||
entry.eventID = EventTriggerType.PointerExit;
|
||||
entry.callback.AddListener((data) => { isPointerInViewCube = false; });
|
||||
eventTrigger.triggers.Add(entry);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
RotateCube();
|
||||
|
||||
if (CameraController != null)
|
||||
{
|
||||
CameraController.isInputLocked = isPointerInViewCube;
|
||||
}
|
||||
|
||||
if (isPointerInViewCube)
|
||||
{
|
||||
CalculateCurrentRay();
|
||||
}
|
||||
|
||||
DetectClick();
|
||||
}
|
||||
|
||||
void RotateCube()
|
||||
{
|
||||
if (mainCam == null || cubeContainer == null) return;
|
||||
cubeContainer.rotation = mainCam.transform.rotation;
|
||||
}
|
||||
|
||||
// NEW FUNCTION: Handles the math to convert Screen Pixels -> UI Pixels -> Camera Ray
|
||||
void CalculateCurrentRay()
|
||||
{
|
||||
Vector2 localPoint;
|
||||
// 1. Convert Screen Mouse Point to a point inside the RawImage rectangle
|
||||
// The 'null' param works for "Screen Space - Overlay" canvas.
|
||||
// If your canvas is "Screen Space - Camera", pass the UI Camera instead of null.
|
||||
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
||||
rawImageRect,
|
||||
Input.mousePosition,
|
||||
null,
|
||||
out localPoint))
|
||||
{
|
||||
// 2. Normalize positions to 0-1 range (Viewport coordinates)
|
||||
// LocalPoint (0,0) is the center of the image. We shift it by +0.5 to make (0,0) the bottom-left.
|
||||
float normalizedX = (localPoint.x / rawImageRect.rect.width) + 0.5f;
|
||||
float normalizedY = (localPoint.y / rawImageRect.rect.height) + 0.5f;
|
||||
|
||||
// 3. Create the ray from the ViewCube Camera using these coordinates
|
||||
debugRay = viewCubeCam.ViewportPointToRay(new Vector3(normalizedX, normalizedY, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void DetectClick()
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0) && isPointerInViewCube)
|
||||
{
|
||||
// We use the ray calculated in CalculateCurrentRay()
|
||||
if (Physics.Raycast(debugRay, out RaycastHit hit, 100f, viewCubeLayer))
|
||||
{
|
||||
Debug.Log("View Cube Hit: " + hit.collider.name);
|
||||
|
||||
Vector3 targetDir = Vector3.zero;
|
||||
|
||||
switch (hit.collider.name)
|
||||
{
|
||||
case "Front": targetDir = Vector3.forward; break;
|
||||
case "Back": targetDir = Vector3.back; break;
|
||||
case "Left": targetDir = Vector3.left; break;
|
||||
case "Right": targetDir = Vector3.right; break;
|
||||
case "Top": targetDir = Vector3.up; break;
|
||||
case "Bottom": targetDir = Vector3.down; break;
|
||||
}
|
||||
|
||||
if (targetDir != Vector3.zero && CameraController != null)
|
||||
{
|
||||
CameraController.SnapToDirection(targetDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DRAW GIZMOS: This will now draw the ray based on where your mouse is hovering
|
||||
private void OnDrawGizmos()
|
||||
{
|
||||
if (viewCubeCam == null) return;
|
||||
|
||||
Gizmos.color = Color.red;
|
||||
// Draw the ray stored in debugRay
|
||||
Gizmos.DrawLine(debugRay.origin, debugRay.origin + debugRay.direction * 100f);
|
||||
// Draw a small sphere at the ray start point to confirm it's coming from the camera
|
||||
Gizmos.DrawSphere(debugRay.origin, 0.2f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1705a4f5a2431a740a1ff509d1051cc4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user