diff options
author | Mike Erwin <significant.bit@gmail.com> | 2011-06-09 01:18:03 +0400 |
---|---|---|
committer | Mike Erwin <significant.bit@gmail.com> | 2011-06-09 01:18:03 +0400 |
commit | e75ff53452d6c989e2846521f5d00523bc90906a (patch) | |
tree | 869f0b62410d6efe24a9900dda0b84796b3cec12 /intern/ghost | |
parent | e2e0bc2c444dfa333d7c5c174a851c271fcd4732 (diff) | |
parent | 6132f8c4b49991ad7c60e15bfda6360a95a234aa (diff) |
migrated NDOF code from soc-2010-merwin, SpaceNavigator now works on Mac blender
Diffstat (limited to 'intern/ghost')
-rw-r--r-- | intern/ghost/GHOST_C-api.h | 15 | ||||
-rw-r--r-- | intern/ghost/GHOST_ISystem.h | 16 | ||||
-rw-r--r-- | intern/ghost/GHOST_Types.h | 44 | ||||
-rw-r--r-- | intern/ghost/SConscript | 2 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_C-api.cpp | 17 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_EventNDOF.h | 56 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_NDOFManager.cpp | 204 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_NDOFManager.h | 49 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_NDOFManagerCocoa.h | 48 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 121 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_NDOFManagerWin32.h | 47 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_NDOFManagerX11.h | 100 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_System.cpp | 31 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_System.h | 19 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemCocoa.h | 7 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemCocoa.mm | 10 |
16 files changed, 506 insertions, 280 deletions
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index 75837239c4a..a315dfa85e9 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -288,21 +288,6 @@ extern GHOST_TSuccess GHOST_SetProgressBar(GHOST_WindowHandle windowhandle, floa * @param windowhandle The handle to the window */ extern GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle); - - -/*************************************************************************************** - ** N-degree of freedom device management functionality - ***************************************************************************************/ - -/** -* Open N-degree of freedom devices - */ -extern int GHOST_OpenNDOF(GHOST_SystemHandle systemhandle, - GHOST_WindowHandle windowhandle, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen - ); /*************************************************************************************** ** Cursor management functionality diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 69e10070be5..015ae780bea 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -298,22 +298,6 @@ public: */ virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer* consumer) = 0; - /*************************************************************************************** - ** N-degree of freedom device management functionality - ***************************************************************************************/ - - /** - * Starts the N-degree of freedom device manager - */ - virtual int openNDOF(GHOST_IWindow*, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen - // original patch only - // GHOST_NDOFEventHandler_fp setNdofEventHandler - ) = 0; - - /*************************************************************************************** ** Cursor management functionality ***************************************************************************************/ diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 705f4916619..7fa94b14716 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -439,37 +439,23 @@ typedef struct { GHOST_TUns8 **strings; } GHOST_TStringArray; - -/* original patch used floats, but the driver return ints and uns. We will calibrate in view, no sense on doing conversions twice */ -/* as all USB device controls are likely to use ints, this is also more future proof */ -//typedef struct { -// /** N-degree of freedom device data */ -// float tx, ty, tz; /** -x left, +y up, +z forward */ -// float rx, ry, rz; -// float dt; -//} GHOST_TEventNDOFData; +typedef struct { + /** N-degree of freedom device data v3 [GSoC 2010]*/ + /* Each component normally ranges from -1 to +1, but can exceed that. */ + float tx, ty, tz; /* translation: -x left, +y forward, -z up */ + float rx, ry, rz; /* rotation: + axis = (rx,ry,rz).normalized + amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg] */ + float dt; // time since previous NDOF Motion event (or zero if this is the first) +} GHOST_TEventNDOFMotionData; + +typedef enum { GHOST_kPress, GHOST_kRelease } GHOST_TButtonAction; + // good for mouse or other buttons too, hmmm? 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 int (*GHOST_NDOFLibraryInit_fp)(void); -typedef void (*GHOST_NDOFLibraryShutdown_fp)(void* deviceHandle); -typedef void* (*GHOST_NDOFDeviceOpen_fp)(void* platformData); - -// original patch windows callback. In mac os X version the callback is internal to the plug-in and post an event to main thead. -// not necessary faster, but better integration with other events. - -//typedef int (*GHOST_NDOFEventHandler_fp)(float* result7, void* deviceHandle, unsigned int message, unsigned int* wParam, unsigned long* lParam); -//typedef void (*GHOST_NDOFCallBack_fp)(GHOST_TEventNDOFDataV2 *VolDatas); + GHOST_TButtonAction action; + short button; +} GHOST_TEventNDOFButtonData; typedef struct { /** The key code. */ diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript index b67545f216a..3b144ba95cb 100644 --- a/intern/ghost/SConscript +++ b/intern/ghost/SConscript @@ -11,7 +11,7 @@ if window_system == 'darwin': sources += env.Glob('intern/*.mm') -pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_SystemPaths', 'GHOST_Window', 'GHOST_DropTarget'] +pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_SystemPaths', 'GHOST_Window', 'GHOST_DropTarget', 'GHOST_NDOFManager'] defs=['_USE_MATH_DEFINES'] if window_system in ('linux2', 'openbsd3', 'sunos5', 'freebsd7', 'freebsd8', 'freebsd9', 'irix6', 'aix4', 'aix5'): diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 7ba8d7db411..6332d72a42f 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -275,23 +275,6 @@ GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle) } -int GHOST_OpenNDOF(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen) - //original patch only - /* GHOST_NDOFEventHandler_fp setNdofEventHandler)*/ -{ - GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; - - return system->openNDOF((GHOST_IWindow*) windowhandle, - setNdofLibraryInit, setNdofLibraryShutdown, setNdofDeviceOpen); -// original patch -// setNdofLibraryInit, setNdofLibraryShutdown, setNdofDeviceOpen, setNdofEventHandler); -} - - - GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandle) { GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; diff --git a/intern/ghost/intern/GHOST_EventNDOF.h b/intern/ghost/intern/GHOST_EventNDOF.h index 70861b08fc6..394aff0493f 100644 --- a/intern/ghost/intern/GHOST_EventNDOF.h +++ b/intern/ghost/intern/GHOST_EventNDOF.h @@ -19,11 +19,6 @@ * * ***** END GPL LICENSE BLOCK ***** */ - -/** \file ghost/intern/GHOST_EventNDOF.h - * \ingroup GHOST - */ - #ifndef _GHOST_EVENT_NDOF_H_ @@ -31,32 +26,33 @@ #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; - } -protected: - /** translation & rotation from the device. */ - GHOST_TEventNDOFData m_ndofEventData; -}; +class GHOST_EventNDOFMotion : public GHOST_Event + { + protected: + GHOST_TEventNDOFMotionData m_axisData; + + public: + GHOST_EventNDOFMotion(GHOST_TUns64 time, GHOST_IWindow* window) + : GHOST_Event(time, GHOST_kEventNDOFMotion, window) + { + m_data = &m_axisData; + } + }; + + +class GHOST_EventNDOFButton : public GHOST_Event + { + protected: + GHOST_TEventNDOFButtonData m_buttonData; + + public: + GHOST_EventNDOFButton(GHOST_TUns64 time, GHOST_IWindow* window) + : GHOST_Event(time, GHOST_kEventNDOFButton, window) + { + m_data = &m_buttonData; + } + }; #endif // _GHOST_EVENT_NDOF_H_ - diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 7721b1708f9..1042398650e 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -15,120 +15,108 @@ * 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. + * Contributor(s): + * Mike Erwin * * ***** END GPL LICENSE BLOCK ***** */ -/** \file ghost/intern/GHOST_NDOFManager.cpp - * \ingroup GHOST - */ +#include "GHOST_NDOFManager.h" +#include "GHOST_EventNDOF.h" +#include "GHOST_WindowManager.h" +#include <string.h> // for memory functions +#include <stdio.h> // for debug tracing + +GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) + : m_system(sys) + , m_buttons(0) + , m_motionTime(1000) // one full second (operators should filter out such large time deltas) + , m_prevMotionTime(0) + , m_atRest(true) + { + // to avoid the rare situation where one triple is updated and + // the other is not, initialize them both here: + memset(m_translation, 0, sizeof(m_translation)); + memset(m_rotation, 0, sizeof(m_rotation)); + } + +void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time) + { + memcpy(m_translation, t, sizeof(m_translation)); + m_motionTime = time; + m_atRest = false; + } + +void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time) + { + memcpy(m_rotation, r, sizeof(m_rotation)); + m_motionTime = time; + m_atRest = false; + } + +void GHOST_NDOFManager::updateButtons(unsigned short buttons, GHOST_TUns64 time) + { + GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); + + unsigned short diff = m_buttons ^ buttons; + + for (int i = 0; i < 16; ++i) + { + unsigned short mask = 1 << i; + + if (diff & mask) + { + GHOST_EventNDOFButton* event = new GHOST_EventNDOFButton(time, window); + GHOST_TEventNDOFButtonData* data = (GHOST_TEventNDOFButtonData*) event->getData(); + + data->action = (buttons & mask) ? GHOST_kPress : GHOST_kRelease; + data->button = i + 1; + // printf("sending button %d %s\n", data->button, (data->action == GHOST_kPress) ? "pressed" : "released"); -#include <stdio.h> /* just for printf */ + m_system.pushEvent(event); + } + } -#include "GHOST_NDOFManager.h" + m_buttons = buttons; + } +bool GHOST_NDOFManager::sendMotionEvent() + { + if (m_atRest) + return false; -// 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}; - -#if !defined(_WIN32) && !defined(__APPLE__) -#include "GHOST_SystemX11.h" -#endif - -namespace -{ - GHOST_NDOFLibraryInit_fp ndofLibraryInit = 0; - GHOST_NDOFLibraryShutdown_fp ndofLibraryShutdown = 0; - GHOST_NDOFDeviceOpen_fp ndofDeviceOpen = 0; -} - -GHOST_NDOFManager::GHOST_NDOFManager() -{ - m_DeviceHandle = 0; - - // discover the API from the plugin - ndofLibraryInit = 0; - ndofLibraryShutdown = 0; - ndofDeviceOpen = 0; -} - -GHOST_NDOFManager::~GHOST_NDOFManager() -{ - if (ndofLibraryShutdown) - ndofLibraryShutdown(m_DeviceHandle); - - m_DeviceHandle = 0; -} - - -int -GHOST_NDOFManager::deviceOpen(GHOST_IWindow* window, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen) -{ - int Pid; - - ndofLibraryInit = setNdofLibraryInit; - ndofLibraryShutdown = setNdofLibraryShutdown; - ndofDeviceOpen = setNdofDeviceOpen; - - if (ndofLibraryInit && ndofDeviceOpen) - { - Pid= ndofLibraryInit(); -#if 0 - printf("%i client \n", Pid); -#endif - #if defined(WITH_HEADLESS) - /* do nothing */ - #elif defined(_WIN32) || defined(__APPLE__) - m_DeviceHandle = ndofDeviceOpen((void *)¤tNdofValues); - #else - GHOST_SystemX11 *sys; - sys = static_cast<GHOST_SystemX11*>(GHOST_ISystem::getSystem()); - void *ndofInfo = sys->prepareNdofInfo(¤tNdofValues); - 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; -} + GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); + + GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, window); + GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData(); + + const float scale = 1.f / 350.f; // SpaceNavigator sends +/- 350 usually + // 350 according to their developer's guide; others recommend 500 as comfortable + + // possible future enhancement + // scale *= m_sensitivity; + + 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]; + + data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds + + m_prevMotionTime = m_motionTime; + + // printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", + // data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, data->dt); + + 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; + + return true; + } diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index c9e09370e09..f4adb4cab1d 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -19,38 +19,47 @@ * * ***** END GPL LICENSE BLOCK ***** */ - -/** \file ghost/intern/GHOST_NDOFManager.h - * \ingroup GHOST - */ - #ifndef _GHOST_NDOFMANAGER_H_ #define _GHOST_NDOFMANAGER_H_ #include "GHOST_System.h" -#include "GHOST_IWindow.h" - class GHOST_NDOFManager { public: - GHOST_NDOFManager(); - virtual ~GHOST_NDOFManager(); - - 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; + GHOST_NDOFManager(GHOST_System&); + + 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 + virtual 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; + GHOST_TUns64 m_prevMotionTime; // time of most recent Motion event sent + bool m_atRest; + + void updateMotionTime(GHOST_TUns64 t); + void resetMotion(); }; diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h new file mode 100644 index 00000000000..efe840bab4a --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h @@ -0,0 +1,48 @@ +/* + * ***** 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): + * Mike Erwin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef _GHOST_NDOFMANAGERCOCOA_H_ +#define _GHOST_NDOFMANAGERCOCOA_H_ + +#include "GHOST_NDOFManager.h" + +// Event capture is handled within the NDOFManager on Macintosh, +// so there's no need for SystemCocoa to look for them. + +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 diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm new file mode 100644 index 00000000000..75a96556ff1 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -0,0 +1,121 @@ +/* + * ***** 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): + * Mike Erwin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "GHOST_NDOFManagerCocoa.h" +#include "GHOST_SystemCocoa.h" + +extern "C" { + #include <3DconnexionClient/ConnexionClientAPI.h> + #include <stdio.h> + } + +static void SpaceNavAdded(io_connect_t connection) + { + printf("SpaceNav added\n"); // change these: printf --> informational reports + } + +static void SpaceNavRemoved(io_connect_t connection) + { + printf("SpaceNav removed\n"); + } + +static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void* messageArgument) + { + GHOST_SystemCocoa* system = (GHOST_SystemCocoa*) GHOST_ISystem::getSystem(); + GHOST_NDOFManager* manager = system->getNDOFManager(); + switch (messageType) + { + case kConnexionMsgDeviceState: + { + ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument; + + GHOST_TUns64 now = system->getMilliSeconds(); + + switch (s->command) + { + case kConnexionCmdHandleAxis: + manager->updateTranslation(s->axis, now); + manager->updateRotation(s->axis + 3, now); + system->notifyExternalEventProcessed(); + break; + + case kConnexionCmdHandleButtons: + manager->updateButtons(s->buttons, now); + system->notifyExternalEventProcessed(); + break; + + default: + printf("device state command %d\n", s->command); + } + 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 + // 3Dx header file says to ignore these + 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; + } + + // Pascal string *and* a four-letter constant. How old-skool. + m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pblender", + 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)); +// ^-- not needed since the entire framework is weak-linked + return InstallConnexionHandlers != NULL; + } diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.h b/intern/ghost/intern/GHOST_NDOFManagerWin32.h new file mode 100644 index 00000000000..0570eefa951 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.h @@ -0,0 +1,47 @@ +/* + * ***** 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): + * Mike Erwin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef _GHOST_NDOFMANAGERWIN32_H_ +#define _GHOST_NDOFMANAGERWIN32_H_ + +#include "GHOST_NDOFManager.h" + + +class GHOST_NDOFManagerWin32 : public GHOST_NDOFManager +{ +public: + GHOST_NDOFManagerWin32(GHOST_System& sys) + : GHOST_NDOFManager(sys) + {} + + // 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() + { + // always available since RawInput is built into Windows + return true; + } +}; + + +#endif diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.h b/intern/ghost/intern/GHOST_NDOFManagerX11.h new file mode 100644 index 00000000000..4c89bfe0ca6 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.h @@ -0,0 +1,100 @@ +/* + * ***** 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_NDOFMANAGERX11_H_ +#define _GHOST_NDOFMANAGERX11_H_ + +#include "GHOST_NDOFManager.h" +#include "GHOST_Types.h" +#include "GHOST_WindowX11.h" +#include "GHOST_EventNDOF.h" +#include <X11/Xlib.h> +#include <stdio.h> + +class GHOST_NDOFManagerX11 : public GHOST_NDOFManager +{ +GHOST_WindowX11 * m_ghost_window_x11; + +public: + GHOST_NDOFManagerX11(GHOST_System& sys) + : GHOST_NDOFManager(sys) + {} + + void setGHOSTWindowX11(GHOST_WindowX11 * w){ + if (m_ghost_window_x11 == NULL) + m_ghost_window_x11 = w; + } + + GHOST_WindowX11 * getGHOSTWindowX11(){ + return m_ghost_window_x11; + } + + // 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() + { + // never available since I've not yet written it! + return true; + } + + virtual bool sendMotionEvent() + { + if (m_atRest) + return false; + + GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, getGHOSTWindowX11()); + GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData(); + + const float scale = 1.f/350.f; // SpaceNavigator sends +/- 350 usually + // 350 according to their developer's guide; others recommend 500 as comfortable + + // possible future enhancement + // scale *= m_sensitivity; + + 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]; + + data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds + + m_prevMotionTime = m_motionTime; + + printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", + data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, data->dt); + + if (!m_system.pushEvent(event)) + return false; + + // '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; + + return true; + } +}; + + +#endif diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index cb3e97fc574..792adba7ce3 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -194,12 +194,15 @@ bool GHOST_System::getFullScreen(void) bool GHOST_System::dispatchEvents() { - bool handled; - if (m_eventManager) { - handled = m_eventManager->dispatchEvents(); + bool handled = false; + + // NDOF Motion event is sent only once per dispatch, so do it now: + if (m_ndofManager) { + handled |= m_ndofManager->sendMotionEvent(); } - else { - handled = false; + + if (m_eventManager) { + handled |= m_eventManager->dispatchEvents(); } m_timerManager->fireTimers(getMilliSeconds()); @@ -243,18 +246,6 @@ GHOST_TSuccess GHOST_System::pushEvent(GHOST_IEvent* event) return success; } -int GHOST_System::openNDOF(GHOST_IWindow* w, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen) -{ - return m_ndofManager->deviceOpen(w, - setNdofLibraryInit, - setNdofLibraryShutdown, - setNdofDeviceOpen); -} - - GHOST_TSuccess GHOST_System::getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const { GHOST_ModifierKeys keys; @@ -285,12 +276,6 @@ GHOST_TSuccess GHOST_System::init() m_timerManager = new GHOST_TimerManager (); m_windowManager = new GHOST_WindowManager (); m_eventManager = new GHOST_EventManager (); - m_ndofManager = new GHOST_NDOFManager(); - -#if 0 - if(m_ndofManager) - printf("ndof manager \n"); -#endif #ifdef GHOST_DEBUG if (m_eventManager) { diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index b5c64bfceb6..f62c0984c80 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -191,25 +191,6 @@ public: virtual GHOST_TSuccess removeEventConsumer(GHOST_IEventConsumer* consumer); /*************************************************************************************** - ** N-degree of freedom devcice management functionality - ***************************************************************************************/ - - /** Inherited from GHOST_ISystem - * Opens the N-degree of freedom device manager - * return 0 if device found, 1 otherwise - */ - virtual int openNDOF(GHOST_IWindow* w, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen); - -// original patch only -// GHOST_NDOFEventHandler_fp setNdofEventHandler); - - - - - /*************************************************************************************** ** Cursor management functionality ***************************************************************************************/ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index e7a8178a382..882c365cdb1 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -229,6 +229,11 @@ public: GHOST_TSuccess handleApplicationBecomeActiveEvent(); /** + * External objects should call this when they send an event outside processEvents. + */ + void notifyExternalEventProcessed(); + + /** * @see GHOST_ISystem */ int toggleConsole(int action) { return 0; } @@ -275,7 +280,7 @@ protected: /** Start time at initialization. */ GHOST_TUns64 m_start_time; - /** Event has been processed directly by Cocoa and has sent a ghost event to be dispatched */ + /** Event has been processed directly by Cocoa (or NDOF manager) and has sent a ghost event to be dispatched */ bool m_outsideLoopEventProcessed; /** Raised window is not yet known by the window manager, so delay application become active event handling */ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index bf401138cf1..1cc692e7b78 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -52,7 +52,7 @@ #include "GHOST_TimerTask.h" #include "GHOST_WindowManager.h" #include "GHOST_WindowCocoa.h" -#include "GHOST_NDOFManager.h" +#include "GHOST_NDOFManagerCocoa.h" #include "AssertMacros.h" #pragma mark KeyMap, mouse converters @@ -596,6 +596,9 @@ GHOST_TSuccess GHOST_SystemCocoa::init() GHOST_TSuccess success = GHOST_System::init(); if (success) { + + m_ndofManager = new GHOST_NDOFManagerCocoa(*this); + //ProcessSerialNumber psn; //Carbon stuff to move window & menu to foreground @@ -1027,6 +1030,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() return GHOST_kSuccess; } +void GHOST_SystemCocoa::notifyExternalEventProcessed() +{ + m_outsideLoopEventProcessed = true; +} + //Note: called from NSWindow delegate GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window) { |