revamped NDOF event system for ghost, added (untested) Mac support

This commit is contained in:
Mike Erwin
2010-07-22 07:23:41 +00:00
parent f0167c6a41
commit 6c2dee0198
6 changed files with 275 additions and 148 deletions

View File

@@ -154,7 +154,8 @@ typedef enum {
GHOST_kEventTrackpad, /// Trackpad event
GHOST_kEventNDOFMotion, /// N degree of freedom device motion event
GHOST_kEventNDOFButton, /// N degree of freedom device button event
GHOST_kEventNDOFButtonDown,/// N degree of freedom device button events
GHOST_kEventNDOFButtonUp,
GHOST_kEventKeyDown,
GHOST_kEventKeyUp,
@@ -432,17 +433,17 @@ typedef struct {
// float dt;
//} GHOST_TEventNDOFData;
typedef struct {
/** N-degree of freedom device data v2*/
int changed;
GHOST_TUns64 client;
GHOST_TUns64 address;
GHOST_TInt16 tx, ty, tz; /** -x left, +y up, +z forward */
GHOST_TInt16 rx, ry, rz;
GHOST_TInt16 buttons;
GHOST_TUns64 time;
GHOST_TUns64 delta;
} GHOST_TEventNDOFData;
// typedef struct {
// /** N-degree of freedom device data v2*/
// int changed;
// GHOST_TUns64 client;
// GHOST_TUns64 address;
// GHOST_TInt16 tx, ty, tz; /** -x left, +y up, +z forward */
// GHOST_TInt16 rx, ry, rz;
// GHOST_TInt16 buttons;
// GHOST_TUns64 time;
// GHOST_TUns64 delta;
// } GHOST_TEventNDOFData;
typedef struct {
/** N-degree of freedom device data v3 [GSoC 2010]*/
@@ -454,13 +455,8 @@ typedef struct {
float tx, ty, tz; /** -x left, +y forward, -z up */
float rx, ry, rz;
GHOST_TInt16 buttons;
} GHOST_TEventNDOFData_3;
} GHOST_TEventNDOFData;
// [mce] consider scrapping these, in favor of built-in SpaceNav handling.
typedef int (*GHOST_NDOFLibraryInit_fp)();
typedef void (*GHOST_NDOFLibraryShutdown_fp)(void* deviceHandle);
typedef void* (*GHOST_NDOFDeviceOpen_fp)(void* platformData);
typedef struct {
/** The key code. */

View File

@@ -26,32 +26,35 @@
#include "GHOST_Event.h"
/**
* N-degree of freedom device event.
*/
class GHOST_EventNDOF : public GHOST_Event
{
public:
/**
* Constructor.
* @param msec The time this event was generated.
* @param type The type of this event.
* @param x The x-coordinate of the location the cursor was at at the time of the event.
* @param y The y-coordinate of the location the cursor was at at the time of the event.
*/
GHOST_EventNDOF(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window,
GHOST_TEventNDOFData data)
: GHOST_Event(msec, type, window)
{
m_ndofEventData = data;
m_data = &m_ndofEventData;
}
class GHOST_EventNDOFMotion : public GHOST_Event
{
protected:
/** translation & rotation from the device. */
GHOST_TEventNDOFData m_ndofEventData;
GHOST_TEventNDOFData m_axisData;
public:
GHOST_EventNDOFMotion(GHOST_TUns64 time)
: GHOST_Event(time, GHOST_kEventNDOFMotion, NULL)
// , m_data(&m_axisData)
{
m_data = &m_axisData;
}
};
class GHOST_EventNDOFButton : public GHOST_Event
{
protected:
GHOST_TUns16 m_buttonNumber;
public:
GHOST_EventNDOFButton(GHOST_TUns64 time, GHOST_TUns16 buttonNumber, GHOST_TEventType upOrDown)
: GHOST_Event(time, upOrDown, NULL)
, m_buttonNumber(buttonNumber)
// , m_data(&m_buttonNumber)
{
m_data = &m_buttonNumber;
}
};
#endif // _GHOST_EVENT_NDOF_H_

View File

@@ -20,108 +20,70 @@
* ***** END GPL LICENSE BLOCK *****
*/
#include <stdio.h> /* just for printf */
#include "GHOST_NDOFManager.h"
#include "GHOST_EventNDOF.h"
GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys)
: m_system(sys)
// , m_translation((short[]){0,0,0})
// , m_rotation((short[]){0,0,0})
, m_buttons(0)
, m_atRest(true)
{ }
// the variable is outside the class because it must be accessed from plugin
static volatile GHOST_TEventNDOFData currentNdofValues = {0,0,0,0,0,0,0,0,0,0,0};
void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time)
{
memcpy(m_translation, t, sizeof(m_translation));
m_motionTime = time;
m_atRest = false;
}
#if !defined(_WIN32) && !defined(__APPLE__)
#include "GHOST_SystemX11.h"
#endif
void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time)
{
memcpy(m_rotation, r, sizeof(m_rotation));
m_motionTime = time;
m_atRest = false;
}
namespace
{
GHOST_NDOFLibraryInit_fp ndofLibraryInit = 0;
GHOST_NDOFLibraryShutdown_fp ndofLibraryShutdown = 0;
GHOST_NDOFDeviceOpen_fp ndofDeviceOpen = 0;
}
void GHOST_NDOFManager::updateButtons(unsigned short buttons, GHOST_TUns64 time)
{
unsigned short diff = m_buttons ^ buttons;
for (int i = 0; i < 16; ++i)
{
unsigned short mask = 1 << i;
if (diff & mask)
m_system.pushEvent(new GHOST_EventNDOFButton(time, i + 1,
(buttons & mask) ? GHOST_kEventNDOFButtonDown : GHOST_kEventNDOFButtonUp));
}
GHOST_NDOFManager::GHOST_NDOFManager()
{
m_DeviceHandle = 0;
m_buttons = buttons;
}
// discover the API from the plugin
ndofLibraryInit = 0;
ndofLibraryShutdown = 0;
ndofDeviceOpen = 0;
}
bool GHOST_NDOFManager::sendMotionEvent()
{
if (m_atRest)
return false;
GHOST_NDOFManager::~GHOST_NDOFManager()
{
if (ndofLibraryShutdown)
ndofLibraryShutdown(m_DeviceHandle);
GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime);
GHOST_TEventNDOFData* data = (GHOST_TEventNDOFData*) event->getData();
m_DeviceHandle = 0;
}
const float scale = 1.f / 350.f; // SpaceNavigator sends +/- 350 usually
// scale *= m_sensitivity;
int
GHOST_NDOFManager::deviceOpen(GHOST_IWindow* window,
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen)
{
int Pid;
data->tx = scale * m_translation[0];
data->ty = scale * m_translation[1];
data->tz = scale * m_translation[2];
data->rx = scale * m_rotation[0];
data->ry = scale * m_rotation[1];
data->rz = scale * m_rotation[2];
m_system.pushEvent(event);
// 'at rest' test goes at the end so that the first 'rest' event gets sent
m_atRest = m_rotation[0] == 0 && m_rotation[1] == 0 && m_rotation[2] == 0 &&
m_translation[0] == 0 && m_translation[1] == 0 && m_translation[2] == 0;
ndofLibraryInit = setNdofLibraryInit;
ndofLibraryShutdown = setNdofLibraryShutdown;
ndofDeviceOpen = setNdofDeviceOpen;
if (ndofLibraryInit && ndofDeviceOpen)
{
Pid= ndofLibraryInit();
#if 0
printf("%i client \n", Pid);
#endif
#if defined(_WIN32) || defined(__APPLE__)
m_DeviceHandle = ndofDeviceOpen((void *)&currentNdofValues);
#else
GHOST_SystemX11 *sys;
sys = static_cast<GHOST_SystemX11*>(GHOST_ISystem::getSystem());
void *ndofInfo = sys->prepareNdofInfo(&currentNdofValues);
m_DeviceHandle = ndofDeviceOpen(ndofInfo);
#endif
return (Pid > 0) ? 0 : 1;
} else
return 1;
}
bool
GHOST_NDOFManager::available() const
{
return m_DeviceHandle != 0;
}
bool
GHOST_NDOFManager::event_present() const
{
if( currentNdofValues.changed >0) {
printf("time %llu but%u x%i y%i z%i rx%i ry%i rz%i \n" ,
currentNdofValues.time, currentNdofValues.buttons,
currentNdofValues.tx,currentNdofValues.ty,currentNdofValues.tz,
currentNdofValues.rx,currentNdofValues.ry,currentNdofValues.rz);
return true;
}else
return false;
}
void GHOST_NDOFManager::GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const
{
datas.tx = currentNdofValues.tx;
datas.ty = currentNdofValues.ty;
datas.tz = currentNdofValues.tz;
datas.rx = currentNdofValues.rx;
datas.ry = currentNdofValues.ry;
datas.rz = currentNdofValues.rz;
datas.buttons = currentNdofValues.buttons;
datas.client = currentNdofValues.client;
datas.address = currentNdofValues.address;
datas.time = currentNdofValues.time;
datas.delta = currentNdofValues.delta;
}
return true;
}

View File

@@ -24,28 +24,38 @@
#define _GHOST_NDOFMANAGER_H_
#include "GHOST_System.h"
#include "GHOST_IWindow.h"
class GHOST_NDOFManager
{
public:
GHOST_NDOFManager();
virtual ~GHOST_NDOFManager();
GHOST_NDOFManager(GHOST_System&);
int deviceOpen(GHOST_IWindow* window,
GHOST_NDOFLibraryInit_fp setNdofLibraryInit,
GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown,
GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen);
void GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const;
bool available() const;
bool event_present() const;
virtual ~GHOST_NDOFManager() {};
// whether multi-axis functionality is available (via the OS or driver)
// does not imply that a device is plugged in or being used
virtual bool available() = 0;
// the latest raw data from the device
void updateTranslation(short t[3], GHOST_TUns64 time);
void updateRotation(short r[3], GHOST_TUns64 time);
// this one sends events immediately for changed buttons
void updateButtons(unsigned short b, GHOST_TUns64 time);
// processes most recent raw data into an NDOFMotion event and sends it
// returns whether an event was sent
bool sendMotionEvent();
protected:
void* m_DeviceHandle;
GHOST_System& m_system;
short m_translation[3];
short m_rotation[3];
unsigned short m_buttons;
GHOST_TUns64 m_motionTime;
bool m_atRest;
};

View File

@@ -0,0 +1,111 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "GHOST_NDOFManagerCocoa.h"
#include <3DconnexionClient/ConnexionClientAPI.h>
#include <stdio.h>
static void SpaceNavAdded(io_connect_t connection)
{
printf("SpaceNav added\n");
}
static void SpaceNavRemoved(io_connect_t connection)
{
printf("SpaceNav removed\n");
}
static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void *messageArgument)
{
GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem();
GHOST_NDOFManager* manager = system->getNDOFManager();
switch (messageType)
{
case kConnexionMsgDeviceState:
{
ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument;
switch (s->command)
{
case kConnexionCmdHandleAxis:
manager->updateTranslation(s->axis, s->time);
manager->updateRotation(s->axis + 3, s->time);
break;
case kConnexionCmdHandleButtons:
manager->updateButtons(s->buttons, s->time);
break;
}
break;
}
case kConnexionMsgPrefsChanged:
printf("prefs changed\n"); // this includes app switches
break;
case kConnexionMsgDoAction:
printf("do action\n"); // no idea what this means
// 'calibrate device' in System Prefs sends this
break;
default:
printf("<!> mystery event\n");
}
}
GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys)
: GHOST_NDOFManager(sys)
{
if (available())
{
OSErr error = InstallConnexionHandlers(SpaceNavEvent, SpaceNavAdded, SpaceNavRemoved);
if (error)
{
printf("<!> error = %d\n", error);
return;
}
// char* name = "\pBlender";
// name[0] = 7; // convert to Pascal string
m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pBlender"/*name*/,
kConnexionClientModeTakeOver, kConnexionMaskAll);
printf("client id = %d\n", m_clientID);
}
else
{
printf("<!> SpaceNav driver not found\n");
// This isn't a hard error, just means the user doesn't have a SpaceNavigator.
}
}
GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa()
{
UnregisterConnexionClient(m_clientID);
CleanupConnexionHandlers();
}
bool GHOST_NDOFManagerCocoa::available()
{
extern OSErr InstallConnexionHandlers() __attribute__((weak_import));
// [mce] C likes the above line, but Obj-C++ does not. Make sure it works for
// machines without the driver installed! Try it on the QuickSilver.
return InstallConnexionHandlers != NULL;
}

View File

@@ -0,0 +1,45 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef _GHOST_NDOFMANAGERCOCOA_H_
#define _GHOST_NDOFMANAGERCOCOA_H_
#include "GHOST_NDOFManager.h"
class GHOST_NDOFManagerCocoa : public GHOST_NDOFManager
{
public:
GHOST_NDOFManagerCocoa(GHOST_System&);
~GHOST_NDOFManagerCocoa();
// whether multi-axis functionality is available (via the OS or driver)
// does not imply that a device is plugged in or being used
bool available();
private:
unsigned short m_clientID;
};
#endif