1
1
using HTC . UnityPlugin . Utility ;
2
+ using HTC . UnityPlugin . Vive ;
2
3
using System ;
3
4
using UnityEngine ;
4
5
using UnityEngine . Events ;
5
6
using UnityEngine . EventSystems ;
7
+ using UnityEngine . Serialization ;
6
8
7
9
// demonstrate of dragging things useing built in EventSystem handlers
8
- public class Draggable : MonoBehaviour
10
+ public class Draggable : GrabbableBase < Draggable . Grabber >
9
11
, IInitializePotentialDragHandler
10
12
, IBeginDragHandler
11
13
, IDragHandler
@@ -14,55 +16,131 @@ public class Draggable : MonoBehaviour
14
16
[ Serializable ]
15
17
public class UnityEventDraggable : UnityEvent < Draggable > { }
16
18
17
- public const float MIN_FOLLOWING_DURATION = 0.02f ;
18
- public const float DEFAULT_FOLLOWING_DURATION = 0.04f ;
19
- public const float MAX_FOLLOWING_DURATION = 0.5f ;
19
+ public class Grabber : IGrabber
20
+ {
21
+ private static ObjectPool < Grabber > m_pool ;
22
+
23
+ public static Grabber Get ( PointerEventData eventData )
24
+ {
25
+ if ( m_pool == null )
26
+ {
27
+ m_pool = new ObjectPool < Grabber > ( ( ) => new Grabber ( ) ) ;
28
+ }
29
+
30
+ var grabber = m_pool . Get ( ) ;
31
+ grabber . eventData = eventData ;
32
+ return grabber ;
33
+ }
34
+
35
+ public static void Release ( Grabber grabber )
36
+ {
37
+ grabber . eventData = null ;
38
+ m_pool . Release ( grabber ) ;
39
+ }
40
+
41
+ public PointerEventData eventData { get ; private set ; }
42
+
43
+ public RigidPose grabberOrigin
44
+ {
45
+ get
46
+ {
47
+ var cam = eventData . pointerPressRaycast . module . eventCamera ;
48
+ var ray = cam . ScreenPointToRay ( eventData . position ) ;
49
+ return new RigidPose ( ray . origin , Quaternion . LookRotation ( ray . direction , cam . transform . up ) ) ;
50
+ }
51
+ }
52
+
53
+ public RigidPose grabOffset { get { return grabber2hit * hit2pivot ; } set { } }
20
54
21
- private OrderedIndexedTable < PointerEventData , RigidPose > eventList = new OrderedIndexedTable < PointerEventData , RigidPose > ( ) ;
55
+ public RigidPose grabber2hit { get ; set ; }
22
56
23
- public float initGrabDistance = 0.5f ;
57
+ public RigidPose hit2pivot { get ; set ; }
58
+
59
+ public float hitDistance
60
+ {
61
+ get { return grabber2hit . pos . z ; }
62
+ set
63
+ {
64
+ var p = grabber2hit ;
65
+ p . pos . z = value ;
66
+ grabber2hit = p ;
67
+ }
68
+ }
69
+ }
70
+
71
+ private IndexedTable < PointerEventData , Grabber > m_eventGrabberSet ;
72
+
73
+ [ FormerlySerializedAs ( "initGrabDistance" ) ]
74
+ [ SerializeField ]
75
+ private float m_initGrabDistance = 0.5f ;
24
76
[ Range ( MIN_FOLLOWING_DURATION , MAX_FOLLOWING_DURATION ) ]
25
- public float followingDuration = DEFAULT_FOLLOWING_DURATION ;
26
- public bool overrideMaxAngularVelocity = true ;
27
- public bool unblockableGrab = true ;
77
+ [ FormerlySerializedAs ( "followingDuration" ) ]
78
+ [ SerializeField ]
79
+ private float m_followingDuration = DEFAULT_FOLLOWING_DURATION ;
80
+ [ FormerlySerializedAs ( "overrideMaxAngularVelocity" ) ]
81
+ [ SerializeField ]
82
+ private bool m_overrideMaxAngularVelocity = true ;
83
+ [ FormerlySerializedAs ( "unblockableGrab" ) ]
84
+ [ SerializeField ]
85
+ private bool m_unblockableGrab = true ;
86
+ [ FormerlySerializedAs ( "afterGrabbed" ) ]
87
+ [ SerializeField ]
88
+ private UnityEventDraggable m_afterGrabbed = new UnityEventDraggable ( ) ;
89
+ [ FormerlySerializedAs ( "beforeRelease" ) ]
90
+ [ SerializeField ]
91
+ private UnityEventDraggable m_beforeRelease = new UnityEventDraggable ( ) ;
92
+ [ FormerlySerializedAs ( "onDrop" ) ]
93
+ [ SerializeField ]
94
+ private UnityEventDraggable m_onDrop = new UnityEventDraggable ( ) ; // change rigidbody drop velocity here
28
95
29
- public UnityEventDraggable afterDragged = new UnityEventDraggable ( ) ;
30
- public UnityEventDraggable beforeRelease = new UnityEventDraggable ( ) ;
31
- public UnityEventDraggable onDrop = new UnityEventDraggable ( ) ; // change rigidbody drop velocity here
96
+ public bool isDragged { get { return isGrabbed ; } }
32
97
33
- private RigidPose m_prevPose = RigidPose . identity ; // last frame world pose
98
+ public PointerEventData draggedEvent { get { return isGrabbed ? currentGrabber . eventData : null ; } }
34
99
35
- public bool isDragged { get { return eventList . Count > 0 ; } }
100
+ public float initGrabDistance { get { return m_initGrabDistance ; } set { m_initGrabDistance = value ; } }
36
101
37
- public PointerEventData draggedEvent { get { return isDragged ? eventList . GetLastKey ( ) : null ; } }
102
+ public override float followingDuration { get { return m_followingDuration ; } set { m_followingDuration = Mathf . Clamp ( value , MIN_FOLLOWING_DURATION , MAX_FOLLOWING_DURATION ) ; } }
38
103
39
- // effected rigidbody
40
- public Rigidbody rigid { get ; set ; }
104
+ public override bool overrideMaxAngularVelocity { get { return m_overrideMaxAngularVelocity ; } set { m_overrideMaxAngularVelocity = value ; } }
41
105
42
- private bool moveByVelocity { get { return ! unblockableGrab && rigid != null && ! rigid . isKinematic ; } }
106
+ public bool unblockableGrab { get { return m_unblockableGrab ; } set { m_unblockableGrab = value ; } }
43
107
44
- private RigidPose GetEventPose ( PointerEventData eventData )
108
+ public UnityEventDraggable afterGrabbed { get { return m_afterGrabbed ; } }
109
+
110
+ public UnityEventDraggable beforeRelease { get { return m_beforeRelease ; } }
111
+
112
+ public UnityEventDraggable onDrop { get { return m_onDrop ; } }
113
+
114
+ private bool moveByVelocity { get { return ! unblockableGrab && grabRigidbody != null && ! grabRigidbody . isKinematic ; } }
115
+
116
+ [ Obsolete ( "Use grabRigidbody instead" ) ]
117
+ public Rigidbody rigid { get { return grabRigidbody ; } set { grabRigidbody = value ; } }
118
+
119
+ protected override void Awake ( )
45
120
{
46
- var cam = eventData . pointerPressRaycast . module . eventCamera ;
47
- var ray = cam . ScreenPointToRay ( eventData . position ) ;
48
- return new RigidPose ( ray . origin , Quaternion . LookRotation ( ray . direction , cam . transform . up ) ) ;
121
+ base . Awake ( ) ;
122
+
123
+ afterGrabberGrabbed += ( ) => m_afterGrabbed . Invoke ( this ) ;
124
+ beforeGrabberReleased += ( ) => m_beforeRelease . Invoke ( this ) ;
125
+ onGrabberDrop += ( ) => m_onDrop . Invoke ( this ) ;
49
126
}
50
127
51
- protected virtual void Awake ( )
128
+ protected virtual void OnDisable ( )
52
129
{
53
- rigid = GetComponent < Rigidbody > ( ) ;
130
+ ClearGrabbers ( true ) ;
131
+ ClearEventGrabberSet ( ) ;
54
132
}
55
133
56
- protected virtual void OnDisable ( )
134
+ private void ClearEventGrabberSet ( )
57
135
{
58
- if ( isDragged && beforeRelease != null )
136
+ if ( m_eventGrabberSet == null ) { return ; }
137
+
138
+ for ( int i = m_eventGrabberSet . Count - 1 ; i >= 0 ; -- i )
59
139
{
60
- beforeRelease . Invoke ( this ) ;
140
+ Grabber . Release ( m_eventGrabberSet . GetValueByIndex ( i ) ) ;
61
141
}
62
142
63
- eventList . Clear ( ) ;
64
-
65
- DoDrop ( ) ;
143
+ m_eventGrabberSet . Clear ( ) ;
66
144
}
67
145
68
146
public virtual void OnInitializePotentialDrag ( PointerEventData eventData )
@@ -72,119 +150,67 @@ public virtual void OnInitializePotentialDrag(PointerEventData eventData)
72
150
73
151
public virtual void OnBeginDrag ( PointerEventData eventData )
74
152
{
75
- var casterPose = GetEventPose ( eventData ) ;
76
- var offsetPose = new RigidPose ( ) ;
153
+ var hitDistance = 0f ;
154
+
77
155
switch ( eventData . button )
78
156
{
79
157
case PointerEventData . InputButton . Middle :
80
158
case PointerEventData . InputButton . Right :
81
- {
82
- var hitResult = eventData . pointerPressRaycast ;
83
- var hitPose = new RigidPose ( hitResult . worldPosition , casterPose . rot ) ;
84
-
85
- var caster2hit = new RigidPose ( Vector3 . forward * Mathf . Min ( hitResult . distance , initGrabDistance ) , Quaternion . identity ) ;
86
- var hit2center = RigidPose . FromToPose ( hitPose , new RigidPose ( transform ) ) ;
87
-
88
- offsetPose = caster2hit * hit2center ;
89
- break ;
90
- }
159
+ hitDistance = Mathf . Min ( eventData . pointerPressRaycast . distance , m_initGrabDistance ) ;
160
+ break ;
91
161
case PointerEventData . InputButton . Left :
162
+ hitDistance = eventData . pointerPressRaycast . distance ;
163
+ break ;
92
164
default :
93
- {
94
- offsetPose = RigidPose . FromToPose ( casterPose , new RigidPose ( transform ) ) ;
95
- break ;
96
- }
165
+ return ;
97
166
}
98
167
99
- if ( eventData != draggedEvent && beforeRelease != null )
100
- {
101
- beforeRelease . Invoke ( this ) ;
102
- }
168
+ var grabber = Grabber . Get ( eventData ) ;
169
+ grabber . grabber2hit = new RigidPose ( new Vector3 ( 0f , 0f , hitDistance ) , Quaternion . identity ) ;
170
+ grabber . hit2pivot = RigidPose . FromToPose ( grabber . grabberOrigin * grabber . grabber2hit , new RigidPose ( transform ) ) ;
103
171
104
- eventList . AddUniqueKey ( eventData , offsetPose ) ;
172
+ if ( m_eventGrabberSet == null ) { m_eventGrabberSet = new IndexedTable < PointerEventData , Grabber > ( ) ; }
173
+ m_eventGrabberSet . Add ( eventData , grabber ) ;
105
174
106
- if ( afterDragged != null )
107
- {
108
- afterDragged . Invoke ( this ) ;
109
- }
175
+ AddGrabber ( grabber ) ;
110
176
}
111
177
112
178
protected virtual void FixedUpdate ( )
113
179
{
114
- if ( ! isDragged ) { return ; }
115
-
116
- if ( moveByVelocity )
180
+ if ( isGrabbed && moveByVelocity )
117
181
{
118
- // if rigidbody exists, follow eventData caster using physics
119
- var casterPose = GetEventPose ( draggedEvent ) ;
120
- var offsetPose = eventList . GetLastValue ( ) ;
121
-
122
- var targetPose = casterPose * offsetPose ;
123
- RigidPose . SetRigidbodyVelocity ( rigid , rigid . position , targetPose . pos , followingDuration ) ;
124
- RigidPose . SetRigidbodyAngularVelocity ( rigid , rigid . rotation , targetPose . rot , followingDuration , overrideMaxAngularVelocity ) ;
182
+ OnGrabRigidbody ( ) ;
125
183
}
126
184
}
127
185
128
- public virtual void OnDrag ( PointerEventData eventData )
186
+ protected virtual void Update ( )
129
187
{
130
- if ( eventData != draggedEvent ) { return ; }
188
+ if ( ! isGrabbed ) { return ; }
131
189
132
190
if ( ! moveByVelocity )
133
191
{
134
- // if rigidbody doen't exist, just move transform to eventData caster's pose
135
- var casterPose = GetEventPose ( eventData ) ;
136
- var offsetPose = eventList . GetLastValue ( ) ;
137
-
138
- m_prevPose = new RigidPose ( transform ) ;
139
-
140
- if ( rigid != null )
141
- {
142
- rigid . velocity = Vector3 . zero ;
143
- rigid . angularVelocity = Vector3 . zero ;
144
- }
145
-
146
- var targetPose = casterPose * offsetPose ;
147
- transform . position = targetPose . pos ;
148
- transform . rotation = targetPose . rot ;
192
+ RecordLatestPosesForDrop ( Time . time , 0.05f ) ;
193
+ OnGrabTransform ( ) ;
149
194
}
150
- }
151
195
152
- public virtual void OnEndDrag ( PointerEventData eventData )
153
- {
154
- var released = eventData == draggedEvent ;
155
- if ( released && beforeRelease != null )
156
- {
157
- beforeRelease . Invoke ( this ) ;
158
- }
159
-
160
- eventList . Remove ( eventData ) ;
161
-
162
- if ( isDragged )
163
- {
164
- if ( released && afterDragged != null )
165
- {
166
- afterDragged . Invoke ( this ) ;
167
- }
168
- }
169
- else
196
+ var scrollDelta = currentGrabber . eventData . scrollDelta * 0.01f ;
197
+ if ( scrollDelta != Vector2 . zero )
170
198
{
171
- DoDrop ( ) ;
199
+ currentGrabber . hitDistance = Mathf . Max ( 0f , currentGrabber . hitDistance + scrollDelta . y ) ;
172
200
}
173
201
}
174
202
175
- private void DoDrop ( )
203
+ public virtual void OnDrag ( PointerEventData eventData ) { }
204
+
205
+ public virtual void OnEndDrag ( PointerEventData eventData )
176
206
{
177
- if ( ! moveByVelocity && rigid != null && ! rigid . isKinematic && m_prevPose != RigidPose . identity )
178
- {
179
- RigidPose . SetRigidbodyVelocity ( rigid , m_prevPose . pos , transform . position , Time . deltaTime ) ;
180
- RigidPose . SetRigidbodyAngularVelocity ( rigid , m_prevPose . rot , transform . rotation , Time . deltaTime , overrideMaxAngularVelocity ) ;
207
+ if ( m_eventGrabberSet == null ) { return ; }
181
208
182
- m_prevPose = RigidPose . identity ;
183
- }
209
+ Grabber grabber ;
210
+ if ( ! m_eventGrabberSet . TryGetValue ( eventData , out grabber ) ) { return ; }
184
211
185
- if ( onDrop != null )
186
- {
187
- onDrop . Invoke ( this ) ;
188
- }
212
+ RemoveGrabber ( grabber ) ;
213
+ m_eventGrabberSet . Remove ( eventData ) ;
214
+ Grabber . Release ( grabber ) ;
189
215
}
190
216
}
0 commit comments