-
Notifications
You must be signed in to change notification settings - Fork 1
/
VolumeGrabHandle.cs
136 lines (118 loc) · 5.16 KB
/
VolumeGrabHandle.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System.Collections;
using System.Collections.Generic;
using LC.UI;
using Unity.PolySpatial;
using UnityEngine;
using UnityEngine.InputSystem.LowLevel;
namespace LC.Interaction
{
[RequireComponent(typeof(BoxCollider))]
public class VolumeGrabHandle : DebuggableTouchReceiver
{
[Header("Volume Positioning Config")]
public float MinAngularSizeDegrees = 5f;
[Space(10f)]
[Tooltip("When the hand has moved by Reference Input Offset cm, the volume will move Refernece Output Offset m in the world-space direction")]
public float ReferenceInputOffsetCm = 30f;
[Tooltip("When the hand has moved by Reference Input Offset cm, the volume will move Refernece Output Offset m in the world-space direction")]
public float ReferenceOutputOffsetM = 3f;
public float MovementExponent = 5f;
[Space(10f)]
public float SmoothingSpeed = 8f;
public float MaxDistanceFromCamera = 10f;
private VolumeCamera _volume;
private bool _isGrabbed;
private bool _everGrabbed;
private bool _firstFrame;
private BoxCollider _boxCollider;
private Vector3 _defaultColliderSize;
private Vector3 _targetPosition;
private Vector3 _startPosition;
private Vector3 _startHandPosition;
private bool _recentering;
protected override void Awake()
{
base.Awake();
_volume = FindObjectOfType<VolumeCamera>();
_boxCollider = (BoxCollider)_collider;
_defaultColliderSize = _boxCollider.size;
OnTouchDown.AddListener(StartDragging);
OnDrag.AddListener(HandleDrag);
OnTouchUp.AddListener(StopDragging);
gameObject.SetActive(false);
}
public void Start()
{
VisionOsImmersiveMode.Instance.OnRecenterStart.AddListener(() =>
{
Debug.Log("Recenter Start");
_recentering = true;
});
VisionOsImmersiveMode.Instance.OnRecenter.AddListener(newPos =>
{
Debug.Log("Recenter End: " + newPos);
_targetPosition = newPos;
_recentering = false;
});
}
private void StartDragging(SpatialPointerState pointerState)
{
_isGrabbed = true;
_firstFrame = true;
_everGrabbed = true;
}
private void HandleDrag(SpatialPointerState pointerState)
{
if (!_isGrabbed) return;
if (_firstFrame) {
_startPosition = _volume.transform.position;
_startHandPosition = _volume.transform.InverseTransformPoint(pointerState.inputDevicePosition);
_targetPosition = _startPosition;
_firstFrame = false;
return;
}
var rawOffset = _volume.transform.InverseTransformPoint(pointerState.inputDevicePosition) - _startHandPosition;
var offsetMag = rawOffset.magnitude;
var offsetDir = rawOffset / offsetMag;
var scaledOffsetMag = GetMovementAmount(offsetMag);
var scaledOffset = offsetDir * scaledOffsetMag;
if (offsetMag <= 0f) scaledOffset = Vector3.zero;
_targetPosition = _startPosition - scaledOffset;
_targetPosition = ClampPosition(_targetPosition);
}
private void StopDragging()
{
_isGrabbed = false;
}
public void Update()
{
if (!_everGrabbed) return;
if (_recentering) return;
var lerp = Time.deltaTime * SmoothingSpeed;
_volume.transform.position = Vector3.Lerp(_volume.transform.position, _targetPosition, lerp);
//increase the size of the collider to maintain a constant angular size
var camPos = VisionOsTransforms.GetCameraPosition(true);
var width = Mathf.Max(_defaultColliderSize.x, 2f * (camPos - _volume.transform.position).magnitude * Mathf.Tan(MinAngularSizeDegrees));
var colliderScale = width / _defaultColliderSize.x;
var newSize = _defaultColliderSize * colliderScale;
_boxCollider.size = newSize;
}
private float GetMovementAmount(float inputAmount)
{
inputAmount = Mathf.Clamp(inputAmount, -ReferenceInputOffsetCm * 0.01f, ReferenceInputOffsetCm * 0.01f);
var wasNegative = inputAmount < 0f;
if (wasNegative) inputAmount *= -1f;
var value = ReferenceOutputOffsetM * Mathf.Pow(ReferenceInputOffsetCm, -MovementExponent) * Mathf.Pow(inputAmount * 100f, MovementExponent);
if (wasNegative) value *= -1f;
return value;
}
private Vector3 ClampPosition(Vector3 position)
{
var camPos = VisionOsTransforms.GetCameraPosition(true);
var cameraOffset = position - camPos;
if (cameraOffset.sqrMagnitude <= MaxDistanceFromCamera * MaxDistanceFromCamera) return position;
var dir = cameraOffset.normalized;
return camPos + dir * MaxDistanceFromCamera;
}
}
}