1  /**
2  * UniMove API - A Unity plugin
for the PlayStation Move motion controller
3  * Copyright (C)
2012, 2013, Copenhagen Game Collective (http://www.cphgc.org)
4  * Patrick Jarnfelt
5  * Douglas Wilson (http://www.doougle.net)
6  *
7  *
8  * All rights reserved.
9  *
10  * Redistribution and use
in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  *
13  *
1. Redistributions of source code must retain the above copyright
14  * notice,
this list of conditions and the following disclaimer.
15  *
16  *
2. Redistributions in binary form must reproduce the above copyright
17  * notice,
this list of conditions and the following disclaimer in the
18  * documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  **/

32
33  
/**
34  * IMPORTANT NOTES!
35  *
36  * -- This API has been compiled
for Mac OSX (10.7 and later) specifically.
37  *
38  * -- This API assumes that the controller has already been paired and connected
by Bluetooth beforehand.
39  * To pair a controller(s), use the Pairing Utility provided
by the PS Move API http://thp.io/2010/psmove/.
40  * To connect a controller
by Bluetooth, just press the PS button after pairing it.
41  * You can also use the controllers
by USB, but with limited functionality (see below).
42  *
43  * -- Features include:
44  *
45  * - Setting the RGB LED color and rumble intensity (USB and Bluetooth)
46  * - Read the status of the digital buttons (Bluetooth only)
47  * - Read the status of the analog trigger (Bluetooth only)
48  * - Read values
for the internal sensors (Bluetooth only):
49  * - accelorometer
50  * - gyroscope
51  * - magnetometer
52  * - temperature
53  * - battery level
54  *
55  * Please see the README
for more information!
56  **/

57
58 using
System;
59 using
UnityEngine;
60 using
System.Runtime.InteropServices;
61
62 #region
enums and structs
63
64 ///
<summary>
65 ///
The Move controller can be connected by USB and/or Bluetooth.
66 ///
</summary>
67 public
enum PSMoveConnectionType
68 {
69     Bluetooth,
70     USB,
71     Unknown,
72 };

73
74 // Not entirely sure why some of these buttons (R3/L3) are exposed...

75 public
enum PSMoveButton
76 {
77     L2 =
1 << 0x00,
78     R2 =
1 << 0x01,
79     L1 =
1 << 0x02,
80     R1 =
1 << 0x03,
81     Triangle =
1 << 0x04,
82     Circle =
1 << 0x05,
83     Cross =
1 << 0x06,
84     Square =
1 << 0x07,
85     Select =
1 << 0x08,
86     L3 =
1 << 0x09,
87     R3 =
1 << 0x0A,
88     Start =
1 << 0x0B,
89     Up =
1 << 0x0C,
90     Right =
1 << 0x0D,
91     Down =
1 << 0x0E,
92     Left =
1 << 0x0F,
93     PS =
1 << 0x10,
94     Move =
1 << 0x13,
95     Trigger =
1 << 0x14, /* We can use this value with IsButtonDown() (or the events) to get
96                              * a binary yes/no answer about
if the trigger button is down at all.
97                              * For the full integer/analog
value of the trigger, see the corresponding property below.
98                              */

99 };

100
101 // Used
by psmove_get_battery().
102 public
enum PSMove_Battery_Level {
103     Batt_MIN =
0x00, /*!< Battery is almost empty (< 20%) */
104     Batt_20Percent =
0x01, /*!< Battery has at least 20% remaining */
105     Batt_40Percent =
0x02, /*!< Battery has at least 40% remaining */
106     Batt_60Percent =
0x03, /*!< Battery has at least 60% remaining */
107     Batt_80Percent =
0x04, /*!< Battery has at least 80% remaining */
108     Batt_MAX =
0x05, /*!< Battery is fully charged (not on charger) */
109     Batt_CHARGING =
0xEE, /*!< Battery is currently being charged */
110     Batt_CHARGING_DONE =
0xEF, /*!< Battery is fully charged (on charger) */
111 };

112
113 public
enum PSMove_Frame {
114     Frame_FirstHalf =
0, /*!< The older frame */
115     Frame_SecondHalf,
/*!< The most recent frame */
116 };

117
118 public
class UniMoveButtonEventArgs : EventArgs
119 {
120     
public readonly PSMoveButton button;
121
122     
public UniMoveButtonEventArgs(PSMoveButton button)
123     {
124         
this.button = button;
125     }
126 }

127
128 #endregion
129
130 public
class UniMoveController : MonoBehaviour
131 {
132     
#region private instance variables
133     
134     ///
<summary>
135     ///
The handle for this controller. This pointer is what the psmove library uses for reading data via the hid library.
136     ///
</summary>
137     
private IntPtr handle;
138     
private bool disconnected = false;
139     
140     
private float timeElapsed = 0.0f;
141     
private float updateRate = 0.05f; // The default update rate is 50 milliseconds
142     
143     
private static float MIN_UPDATE_RATE = 0.02f; // You probably don't want to update the controller more frequently than every 20 milliseconds
144     
145     
private float trigger = 0f;
146     
private uint currentButtons = 0;
147     
private uint prevButtons = 0;
148     
149     
private Vector3 rawAccel = Vector3.down;
150     
private Vector3 accel = Vector3.down;
151     
private Vector3 magnet = Vector3.zero;
152     
private Vector3 rawGyro = Vector3.zero;
153     
private Vector3 gyro = Vector3.zero;
154     
155     
// TODO: These values still need to be implemented, so we don't expose them publicly
156     
private PSMove_Battery_Level battery = PSMove_Battery_Level.Batt_20Percent;
157     
private float temperature = 0f;
158     
159     ///
<summary>
160     ///
Event fired when the controller disconnects unexpectedly (i.e. on going out of range).
161     ///
</summary>
162     
public event EventHandler OnControllerDisconnected;
163     
164     
#endregion
165     ///
<summary>
166     ///
Returns whether the connecting succeeded or not.
167     ///

168     ///
NOTE! This function does NOT pair the controller by Bluetooth.
169     ///
If the controller is not already paired, it can only be connected by USB.
170     ///
See README for more information.
171     ///
</summary>
172     
public bool Init(int index)
173     {
174         handle = psmove_connect_by_id(index);
175         
176         
// Error check the result!
177         
if (handle == IntPtr.Zero) return false;
178         
179         
// Make sure the connection is actually sending data. If not, this is probably a controller
180         
// you need to remove manually from the OSX Bluetooth Control Panel, then re-connect.
181         
return (psmove_update_leds(handle) != 0);
182     }

183     
184     ///
<summary>
185     ///
Static function that returns the number of *all* controller connections.
186     ///
This count will tally both USB and Bluetooth connections.
187     ///
Note that one physical controller, then, might register multiple connections.
188     ///
To discern between different connection types, see the ConnectionType property below.
189     ///
</summary>
190     
public static int GetNumConnected()
191     {
192         
return psmove_count_connected();
193     }

194     
195     ///
<summary>
196     ///
The amount of time, in seconds, between update calls.
197     ///
The faster this rate, the more responsive the controllers will be.
198     ///
However, update too fast and your computer won't be able to keep up (see below).
199     ///
You almost certainly don't want to make this faster than 20 milliseconds (0.02f).
200     ///

201     ///
NOTE! We find that slower/older computers can have trouble keeping up with a fast update rate,
202     ///
especially the more controllers that are connected. See the README for more information.
203     ///
</summary>
204     
public float UpdateRate
205     {
206         
get { return this.updateRate; }
207         
set { updateRate = Math.Max(value, MIN_UPDATE_RATE); } // Clamp negative values up to 0
208     }
209     
210     
void Update()
211     {
212         
if (disconnected) return;
213         
214         
// we want to update the previous buttons outside the update restriction so,
215         
// we only get one button event pr. unity update frame
216         prevButtons = currentButtons;
217         
218         timeElapsed += Time.deltaTime;
219         
220         
221         
// Here we manually enforce updates only every updateRate amount of time
222         
// The reason we don't just do this in FixedUpdate is so the main program's FixedUpdate rate
223         
// can be set independently of the controllers' update rate.
224         
225         
if (timeElapsed < updateRate) return;
226         
else timeElapsed = 0.0f;
227         
228         
uint buttons = 0;
229         
230         
// NOTE! There is potentially data waiting in queue.
231         
// We need to poll *all* of it by calling psmove_poll() until the queue is empty. Otherwise, data might begin to build up.
232         
while (psmove_poll(handle) > 0)
233         {
234             
// We are interested in every button press between the last update and this one:
235             buttons = buttons | psmove_get_buttons(handle);
236             
237             
// The events are not really working from the PS Move Api. So we do our own with the prevButtons
238             
//psmove_get_button_events(handle, ref pressed, ref released);
239         }
240         currentButtons = buttons;
241
242         
243         
// For acceleration, gyroscope, and magnetometer values, we look at only the last value in the queue.
244         
// We could in theory average all the acceleration (and other) values in the queue for a "smoothing" effect, but we've chosen not to.
245         ProcessData();
246         
247         
// Send a report to the controller to update the LEDs and rumble.
248         
if (psmove_update_leds(handle) == 0)
249         {
250             
// If it returns zero, the controller must have disconnected (i.e. out of battery or out of range),
251             
// so we should fire off any events and disconnect it.
252             OnControllerDisconnected(
this, new EventArgs());
253             Disconnect();
254         }
255     }
256     
257     
void OnApplicationQuit()
258     {
259         Disconnect();
260     }

261     
262     ///
<summary>
263     ///
Returns true if "button" is currently down.
264     ///
</summary
265     
public bool GetButton(PSMoveButton b)
266     {
267         
if (disconnected) return false;
268         
269         
return ((currentButtons & (uint)b) != 0);
270     }

271
272     ///
<summary>
273     ///
Returns true if "button" is pressed down this instant.
274     ///
</summary
275     
public bool GetButtonDown(PSMoveButton b)
276     {
277         
if (disconnected) return false;
278         
return ((prevButtons & (uint)b) == 0) && ((currentButtons & (uint)b) != 0);
279     }

280
281     ///
<summary>
282     ///
Returns true if "button" is released this instant.
283     ///
</summary
284     
public bool GetButtonUp(PSMoveButton b)
285     {
286         
if (disconnected) return false;
287         
288         
return ((prevButtons & (uint)b) != 0) && ((currentButtons & (uint)b) == 0);
289     }

290     ///
<summary>
291     ///
Disconnect the controller
292     ///
</summary>
293
294     
public void Disconnect()
295     {
296         disconnected =
true;
297         SetLED(
0,0,0);
298         SetRumble(
0);
299         psmove_disconnect(handle);
300     }

301     
302     ///
<summary>
303     ///
Whether or not the controller has been disconnected
304     ///
</summary
305     
public bool Disconnected
306     {
307         
get { return disconnected; }
308     }

309     
310     ///
<summary>
311     ///
Sets the amount of rumble
312     ///
</summary>
313     ///
<param name="rumble">the rumble amount (0-1)</param>
314     
public void SetRumble(float rumble)
315     {
316         
if (disconnected) return;
317         
318         
// Clamp value between 0 and 1:
319         
byte rumbleByte = (byte) (Math.Min(Math.Max(rumble, 0f), 1f) * 255);
320         
321         psmove_set_rumble(handle, (
char)rumbleByte);
322     }

323     
324     ///
<summary>
325     ///
Sets the LED color
326     ///
</summary>
327     ///
<param name="color">Unity's Color type</param>
328     
public void SetLED(Color color)
329     {
330         
if (disconnected) return;
331         
332         psmove_set_leds(handle, (
char)(color.r * 255), (char)(color.g * 255), (char)(color.b * 255));
333     }

334     
335     ///
<summary>
336     ///
Sets the LED color
337     ///
</summary>
338     ///
<param name="r">Red value of the LED color (0-255)</param>
339     ///
<param name="g">Green value of the LED color (0-255)</param>
340     ///
<param name="b">Blue value of the LED color (0-255)</param>
341     
public void SetLED(byte r, byte g, byte b)
342     {
343         
if (disconnected) return;
344         
345         psmove_set_leds(handle, (
char)r, (char)g, (char)b);
346     }

347     
348     ///
<summary>
349     ///
Value of the analog trigger button (between 0 and 1)
350     ///
</summary
351     
public float Trigger
352     {
353         
get { return trigger; }
354     }

355     
356     ///
<summary>
357     ///
The 3-axis acceleration values.
358     ///
</summary>
359     
public Vector3 RawAcceleration
360     {
361         
get { return rawAccel; }
362     }

363     
364     ///
<summary>
365     ///
The 3-axis acceleration values, roughly scaled between -3g to 3g (where 1g is Earth's gravity).
366     ///
</summary>
367     
public Vector3 Acceleration
368     {
369         
get { return accel; }
370     }

371     
372     ///
<summary>
373     ///
The raw values of the 3-axis gyroscope.
374     ///
</summary>
375     
public Vector3 RawGyroscope
376     {
377         
get { return rawGyro; }
378     }

379     ///
<summary>
380     ///
The raw values of the 3-axis gyroscope.
381     ///
</summary>
382     
public Vector3 Gyro
383     {
384         
get { return gyro; }
385     }

386     
387     ///
<summary>
388     ///
The raw values of the 3-axis magnetometer.
389     ///
To be honest, we don't fully understand what the magnetometer does.
390     ///
The C API on which this code is based warns that this isn't fully tested.
391     ///
</summary>
392     
public Vector3 Magnetometer
393     {
394         
get { return magnet; }
395     }

396     
397     ///
<summary>
398     ///
The battery level
399     ///
</summary>
400     
public PSMove_Battery_Level Battery
401     {
402         
get { return battery; }
403     }

404     
405     ///
<summary>
406     ///
The temperature in Celcius
407     ///
</summary>
408     
public float Temperature
409     {
410         
get { return temperature; }
411     }
412     
413     
/* TODO: These two values still need to be implemented, so we don't expose them publicly... yet!
414
415     
public float Battery
416     {
417         
get { return this.battery; }
418     }
419     
420     
public float Temperature
421     {
422         
get { return this.temperature; }
423     }
424     */

425     
426     
public PSMoveConnectionType ConnectionType
427     {
428         
get { return psmove_connection_type(handle); }
429     }
430     
431     
#region private methods
432     
433     ///
<summary>
434     ///
Process all the raw data on the Playstation Move controller
435     ///
</summary>
436     
private void ProcessData()
437     {
438         trigger = ((
int)psmove_get_trigger(handle)) / 255f;
439         
440         
int x = 0, y = 0, z = 0;
441         
442         psmove_get_accelerometer(handle,
ref x, ref y, ref z);
443         
444         rawAccel.x = x;
445         rawAccel.y = y;
446         rawAccel.z = z;
447         
448         
449         
float ax = 0, ay = 0, az = 0;
450         psmove_get_accelerometer_frame(handle, PSMove_Frame.Frame_SecondHalf,
ref ax, ref ay, ref az);
451         
452         accel.x = ax;
453         accel.y = ay;
454         accel.z = az;
455         
456         psmove_get_gyroscope(handle,
ref x, ref y, ref z );
457         
458         rawGyro.x = x;
459         rawGyro.y = y;
460         rawGyro.z = z;
461         
462         
463         
float gx = 0, gy = 0, gz = 0;
464         psmove_get_gyroscope_frame(handle, PSMove_Frame.Frame_SecondHalf,
ref gx, ref gy, ref gz);
465         
466         gyro.x = gx;
467         gyro.y = gy;
468         gyro.z = gz;
469         
470         
471         
472         psmove_get_magnetometer(handle,
ref x, ref y, ref z );
473         
474         
// TODO: Should these values be converted into a more human-understandable range?
475         magnet.x = x;
476         magnet.y = y;
477         magnet.z = z;
478         
479         battery = psmove_get_battery(handle);
480         
481         temperature = psmove_get_temperature(handle);
482         
483     }
484     
#endregion
485     
486     
487     
#region importfunctions
488     
489     
/* The following functions are bindings to Thomas Perl's C API for the PlayStation Move (http://thp.io/2010/psmove/)
490      * See README
for more details.
491      *
492      * NOTE! We have included bindings
for the psmove_pair() function, even though we don't use it here
493      * See README and Pairing Utility code
for more about pairing.
494      *
495      * TODO: Expose hooks to psmove_get_btaddr() and psmove_set_btadd()
496      * These functions are already called
by psmove_pair(), so unless you need to do something special, you won't need them.
497      */

498     
499     
[DllImport("libpsmoveapi")]
500     
private static extern int psmove_count_connected();
501     
502     
[DllImport("libpsmoveapi")]
503     
private static extern IntPtr psmove_connect();
504     
505     
[DllImport("libpsmoveapi")]
506     
private static extern IntPtr psmove_connect_by_id(int id);
507     
508     
[DllImport("libpsmoveapi")]
509     
private static extern int psmove_pair(IntPtr move);
510     
511     
[DllImport("libpsmoveapi")]
512     
private static extern PSMoveConnectionType psmove_connection_type(IntPtr move);
513     
514     
[DllImport("libpsmoveapi")]
515     
private static extern int psmove_has_calibration(IntPtr move);
516     
517     
[DllImport("libpsmoveapi")]
518     
private static extern void psmove_set_leds(IntPtr move, char r, char g, char b);
519     
520     
[DllImport("libpsmoveapi")]
521     
private static extern int psmove_update_leds(IntPtr move);
522     
523     
[DllImport("libpsmoveapi")]
524     
private static extern void psmove_set_rumble(IntPtr move, char rumble);
525     
526     
[DllImport("libpsmoveapi")]
527     
private static extern uint psmove_poll(IntPtr move);
528         
529     
[DllImport("libpsmoveapi")]
530     
private static extern uint psmove_get_buttons(IntPtr move);
531     
532     
[DllImport("libpsmoveapi")]
533     
private static extern uint psmove_get_button_events(IntPtr move, ref uint pressed, ref uint released);
534         
535     
[DllImport("libpsmoveapi")]
536     
private static extern char psmove_get_trigger(IntPtr move);
537     
538     
[DllImport("libpsmoveapi")]
539     
private static extern float psmove_get_temperature(IntPtr move);
540     
541     
[DllImport("libpsmoveapi")]
542     
private static extern PSMove_Battery_Level psmove_get_battery(IntPtr move);
543     
544     
[DllImport("libpsmoveapi")]
545     
private static extern void psmove_get_accelerometer(IntPtr move, ref int ax, ref int ay, ref int az);
546     
547     
[DllImport("libpsmoveapi")]
548     
private static extern void psmove_get_accelerometer_frame(IntPtr move,PSMove_Frame frame, ref float ax, ref float ay, ref float az);
549     
550     
[DllImport("libpsmoveapi")]
551     
private static extern void psmove_get_gyroscope(IntPtr move, ref int gx, ref int gy, ref int gz);
552     
553     
[DllImport("libpsmoveapi")]
554     
private static extern void psmove_get_gyroscope_frame(IntPtr move,PSMove_Frame frame, ref float gx, ref float gy, ref float gz);
555     
556     
[DllImport("libpsmoveapi")]
557     
private static extern void psmove_get_magnetometer(IntPtr move, ref int mx, ref int my, ref int mz);
558     
559     
[DllImport("libpsmoveapi")]
560     
private static extern void psmove_disconnect(IntPtr move);
561     
562     
#endregion
563 }


* Copyright (C) 2012, 2013, Copenhagen Game Collective (http:www.cphgc.org)

* Douglas Wilson (http:www.doougle.net)

* To pair a controller(s), use the Pairing Utility provided by the PS Move API http:thp.io2010psmove.

The Move controller can be connected by USB andor Bluetooth.

Not entirely sure why some of these buttons (R3L3) are exposed...

Used by psmove_get_battery().

The handle for this controller. This pointer is what the psmove library uses for reading data via the hid library.

private float updateRate = 0.05f; The default update rate is 50 milliseconds

private static float MIN_UPDATE_RATE = 0.02f; You probably don't want to update the controller more frequently than every 20 milliseconds

TODO: These values still need to be implemented, so we don't expose them publicly

Event fired when the controller disconnects unexpectedly (i.e. on going out of range).

Returns whether the connecting succeeded or not.

NOTE! This function does NOT pair the controller by Bluetooth.

If the controller is not already paired, it can only be connected by USB.

See README for more information.

Error check the result!

Make sure the connection is actually sending data. If not, this is probably a controller

you need to remove manually from the OSX Bluetooth Control Panel, then re-connect.

Static function that returns the number of *all* controller connections.

This count will tally both USB and Bluetooth connections.

Note that one physical controller, then, might register multiple connections.

To discern between different connection types, see the ConnectionType property below.

The amount of time, in seconds, between update calls.

The faster this rate, the more responsive the controllers will be.

However, update too fast and your computer won't be able to keep up (see below).

You almost certainly don't want to make this faster than 20 milliseconds (0.02f).

NOTE! We find that slowerolder computers can have trouble keeping up with a fast update rate,

especially the more controllers that are connected. See the README for more information.

set { updateRate = Math.Max(value, MIN_UPDATE_RATE); } Clamp negative values up to 0

we want to update the previous buttons outside the update restriction so,

we only get one button event pr. unity update frame

Here we manually enforce updates only every updateRate amount of time

The reason we don't just do this in FixedUpdate is so the main program's FixedUpdate rate

can be set independently of the controllers' update rate.

NOTE! There is potentially data waiting in queue.

We need to poll *all* of it by calling psmove_poll() until the queue is empty. Otherwise, data might begin to build up.

We are interested in every button press between the last update and this one:

The events are not really working from the PS Move Api. So we do our own with the prevButtons

psmove_get_button_events(handle, ref pressed, ref released);

For acceleration, gyroscope, and magnetometer values, we look at only the last value in the queue.

We could in theory average all the acceleration (and other) values in the queue for a "smoothing" effect, but we've chosen not to.

Send a report to the controller to update the LEDs and rumble.

If it returns zero, the controller must have disconnected (i.e. out of battery or out of range),

so we should fire off any events and disconnect it.

Returns true if "button" is currently down.

Returns true if "button" is pressed down this instant.

Returns true if "button" is released this instant.

Disconnect the controller

Whether or not the controller has been disconnected

Sets the amount of rumble

the rumble amount (0-1)

Clamp value between 0 and 1:

Sets the LED color

Unity's Color type

Sets the LED color

Red value of the LED color (0-255)

Green value of the LED color (0-255)

Blue value of the LED color (0-255)

Value of the analog trigger button (between 0 and 1)

The 3-axis acceleration values.

The 3-axis acceleration values, roughly scaled between -3g to 3g (where 1g is Earth's gravity).

The raw values of the 3-axis gyroscope.

The raw values of the 3-axis gyroscope.

The raw values of the 3-axis magnetometer.

To be honest, we don't fully understand what the magnetometer does.

The C API on which this code is based warns that this isn't fully tested.

The battery level

The temperature in Celcius

Process all the raw data on the Playstation Move controller

TODO: Should these values be converted into a more human-understandable range?

* The following functions are bindings to Thomas Perl's C API for the PlayStation Move (http:thp.io2010psmove)




trò chơi game bóng rổ full code 33.533 lượt xem

Gõ tìm kiếm nhanh...