diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 66bfa0e469f..952c1860dc1 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -29,27 +29,22 @@ #ifndef _GHOST_TYPES_H_ #define _GHOST_TYPES_H_ -typedef char GHOST_TInt8; -typedef unsigned char GHOST_TUns8; -typedef short GHOST_TInt16; -typedef unsigned short GHOST_TUns16; -typedef int GHOST_TInt32; -typedef unsigned int GHOST_TUns32; - -#ifdef WIN32 -#define WM_BLND_NDOF_AXIS WM_USER + 1 -#define WM_BLND_NDOF_BTN WM_USER + 2 -#endif +typedef char GHOST_TInt8; +typedef unsigned char GHOST_TUns8; +typedef short GHOST_TInt16; +typedef unsigned short GHOST_TUns16; +typedef int GHOST_TInt32; +typedef unsigned int GHOST_TUns32; #if defined(WIN32) && !defined(FREE_WINDOWS) -typedef __int64 GHOST_TInt64; -typedef unsigned __int64 GHOST_TUns64; + typedef __int64 GHOST_TInt64; + typedef unsigned __int64 GHOST_TUns64; #else -typedef long long GHOST_TInt64; -typedef unsigned long long GHOST_TUns64; + typedef long long GHOST_TInt64; + typedef unsigned long long GHOST_TUns64; #endif -typedef void* GHOST_TUserDataPtr; +typedef void* GHOST_TUserDataPtr; typedef enum { @@ -154,8 +149,7 @@ typedef enum { GHOST_kEventTrackpad, /// Trackpad event GHOST_kEventNDOFMotion, /// N degree of freedom device motion event - GHOST_kEventNDOFButtonDown,/// N degree of freedom device button events - GHOST_kEventNDOFButtonUp, + GHOST_kEventNDOFButton, GHOST_kEventKeyDown, GHOST_kEventKeyUp, @@ -276,7 +270,6 @@ typedef enum { GHOST_kKeyRightBracket = ']', GHOST_kKeyBackslash = 0x5C, GHOST_kKeyAccentGrave = '`', - GHOST_kKeyLeftShift = 0x100, GHOST_kKeyRightShift, @@ -284,8 +277,8 @@ typedef enum { GHOST_kKeyRightControl, GHOST_kKeyLeftAlt, GHOST_kKeyRightAlt, - GHOST_kKeyCommand, // APPLE only! - GHOST_kKeyGrLess , // German PC only! + GHOST_kKeyCommand, // APPLE only! + GHOST_kKeyGrLess, // German PC only! GHOST_kKeyCapsLock, GHOST_kKeyNumLock, @@ -365,11 +358,17 @@ typedef struct { GHOST_TInt32 x; /** The y-coordinate of the cursor position. */ GHOST_TInt32 y; + + GHOST_TabletData tablet; + } GHOST_TEventCursorData; typedef struct { /** The mask of the mouse button. */ GHOST_TButtonMask button; + + GHOST_TabletData tablet; + } GHOST_TEventButtonData; typedef struct { @@ -384,7 +383,6 @@ typedef enum { GHOST_kTrackpadEventSwipe, /* Reserved, not used for now */ GHOST_kTrackpadEventMagnify } GHOST_TTrackpadEventSubTypes; - typedef struct { /** The event subtype */ @@ -423,40 +421,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 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]*/ + /* 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) - // Fairly close to raw device data. - // Each component normally ranges from -1 to +1, but can exceed that. - // rot axis = (rx,ry,rz).normalized - // rot amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg] +} GHOST_TEventNDOFMotionData; - float tx, ty, tz; /** -x left, +y forward, -z up */ - float rx, ry, rz; -} GHOST_TEventNDOFData; +typedef enum { GHOST_kPress, GHOST_kRelease } GHOST_TButtonAction; // good for mouse or other buttons too, hmmm? +typedef struct { + GHOST_TButtonAction action; + short button; +} GHOST_TEventNDOFButtonData; typedef struct { /** The key code. */ @@ -478,13 +459,13 @@ typedef struct { #ifdef _WIN32 -typedef long GHOST_TEmbedderWindowID; + typedef long GHOST_TEmbedderWindowID; #endif // _WIN32 #ifndef _WIN32 -// I can't use "Window" from "" because it conflits with Window defined in winlay.h -typedef int GHOST_TEmbedderWindowID; -#endif // _WIN32 + // I can't use "Window" from "" because it conflits with Window defined in winlay.h + typedef int GHOST_TEmbedderWindowID; +#endif /** * A timer task callback routine. @@ -492,12 +473,11 @@ typedef int GHOST_TEmbedderWindowID; * @param time The current time. */ #ifdef __cplusplus -class GHOST_ITimerTask; -typedef void (*GHOST_TimerProcPtr)(GHOST_ITimerTask* task, GHOST_TUns64 time); + class GHOST_ITimerTask; + typedef void (*GHOST_TimerProcPtr)(GHOST_ITimerTask* task, GHOST_TUns64 time); #else -struct GHOST_TimerTaskHandle__; -typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__* task, GHOST_TUns64 time); + struct GHOST_TimerTaskHandle__; + typedef void (*GHOST_TimerProcPtr)(struct GHOST_TimerTaskHandle__* task, GHOST_TUns64 time); #endif #endif // _GHOST_TYPES_H_ - diff --git a/intern/ghost/intern/GHOST_EventButton.h b/intern/ghost/intern/GHOST_EventButton.h index d8631ea47e4..b33095a8efe 100644 --- a/intern/ghost/intern/GHOST_EventButton.h +++ b/intern/ghost/intern/GHOST_EventButton.h @@ -55,6 +55,7 @@ public: : GHOST_Event(time, type, window) { m_buttonEventData.button = button; + m_buttonEventData.tablet.Active = GHOST_kTabletModeNone; m_data = &m_buttonEventData; } @@ -64,4 +65,3 @@ protected: }; #endif // _GHOST_EVENT_BUTTON_H_ - diff --git a/intern/ghost/intern/GHOST_EventCursor.h b/intern/ghost/intern/GHOST_EventCursor.h index 5390e3b2253..e324cf6e9fa 100644 --- a/intern/ghost/intern/GHOST_EventCursor.h +++ b/intern/ghost/intern/GHOST_EventCursor.h @@ -55,6 +55,7 @@ public: { m_cursorEventData.x = x; m_cursorEventData.y = y; + m_cursorEventData.tablet.Active = GHOST_kTabletModeNone; m_data = &m_cursorEventData; } diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp index bc0d7ada74d..b566c1e38c8 100644 --- a/intern/ghost/intern/GHOST_EventManager.cpp +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -110,7 +110,7 @@ GHOST_TSuccess GHOST_EventManager::pushEvent(GHOST_IEvent* event) bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event) { // [mce] this variant switches the "handled" flag to work as described in the header - // it also stops after the first consumer has handled the event + // it also stops after the first consumer has handled the event (no it doesn't) bool handled = false; if (event) { TConsumerVector::iterator iter; @@ -322,7 +322,7 @@ GHOST_IEvent* GHOST_EventManager::popEvent() void GHOST_EventManager::disposeEvents() { - while (m_events.size() > 0) { + while (!m_events.empty()) { GHOST_ASSERT(m_events[0], "invalid event"); delete m_events[0]; m_events.pop_front(); diff --git a/intern/ghost/intern/GHOST_EventNDOF.h b/intern/ghost/intern/GHOST_EventNDOF.h index c5d35126f01..394aff0493f 100644 --- a/intern/ghost/intern/GHOST_EventNDOF.h +++ b/intern/ghost/intern/GHOST_EventNDOF.h @@ -28,33 +28,31 @@ class GHOST_EventNDOFMotion : public GHOST_Event -{ -protected: - GHOST_TEventNDOFData m_axisData; + { + protected: + GHOST_TEventNDOFMotionData m_axisData; + + public: + GHOST_EventNDOFMotion(GHOST_TUns64 time, GHOST_IWindow* window) + : GHOST_Event(time, GHOST_kEventNDOFMotion, window) + { + m_data = &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; - } -}; + { + 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 8cc4a02f51b..1c00e991520 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -22,12 +22,15 @@ #include "GHOST_NDOFManager.h" #include "GHOST_EventNDOF.h" +#include "GHOST_WindowManager.h" #include // for memory functions #include // 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 @@ -52,13 +55,28 @@ void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time) void GHOST_NDOFManager::updateButtons(unsigned short buttons, GHOST_TUns64 time) { + GHOST_System* system = (GHOST_System*) GHOST_System::getSystem(); + GHOST_IWindow* window = system->getWindowManager()->getActiveWindow(); + 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_EventNDOFButton* event = new GHOST_EventNDOFButton(time, window); + GHOST_TEventNDOFButtonData* data = (GHOST_TEventNDOFButtonData*) event->getData(); + + data->action = (buttons & mask) ? GHOST_kPress : GHOST_kRelease; +// data->pressed = buttons & mask; + data->button = i + 1; + +// printf("sending button %d %s\n", data->button, (data->action == GHOST_kPress) ? "pressed" : "released"); + + m_system.pushEvent(event); + } } m_buttons = buttons; @@ -69,8 +87,11 @@ bool GHOST_NDOFManager::sendMotionEvent() if (m_atRest) return false; - GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime); - GHOST_TEventNDOFData* data = (GHOST_TEventNDOFData*) event->getData(); + GHOST_System* system = (GHOST_System*) GHOST_System::getSystem(); + GHOST_IWindow* window = 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 @@ -78,7 +99,7 @@ bool GHOST_NDOFManager::sendMotionEvent() // possible future enhancement // scale *= m_sensitivity; - data->tx = scale * m_translation[0]; + data->tx = -scale * m_translation[0]; data->ty = scale * m_translation[1]; data->tz = scale * m_translation[2]; @@ -86,13 +107,19 @@ bool GHOST_NDOFManager::sendMotionEvent() data->ry = scale * m_rotation[1]; data->rz = scale * m_rotation[2]; - printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f)\n", data->tx, data->ty, data->tz, data->rx, data->ry, data->rz); + data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds + + printf("dt = %d ms\n", (int)(m_motionTime - m_prevMotionTime)); + + m_prevMotionTime = m_motionTime; + +// printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f)\n", data->tx, data->ty, data->tz, data->rx, data->ry, data->rz); 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 035f9f22f0a..9d0bfa3b789 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -55,7 +55,11 @@ protected: 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.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index c4a8a2f1831..b29cbb6d0ce 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -47,16 +47,20 @@ static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void * case kConnexionMsgDeviceState: { ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument; + + GHOST_TUns64 now = system->getMilliSeconds(); + switch (s->command) { case kConnexionCmdHandleAxis: - manager->updateTranslation(s->axis, s->time); - manager->updateRotation(s->axis + 3, s->time); +// manager->updateTranslation(s->axis, s->time); + manager->updateTranslation(s->axis, now); + manager->updateRotation(s->axis + 3, now); system->notifyExternalEventProcessed(); break; case kConnexionCmdHandleButtons: - manager->updateButtons(s->buttons, s->time); + manager->updateButtons(s->buttons, now); system->notifyExternalEventProcessed(); break; } diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index 97b9cb2804d..c84c69707ad 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -35,11 +35,8 @@ #define _GHOST_SYSTEM_COCOA_H_ #ifndef __APPLE__ -#error Apple OSX only! -#endif // __APPLE__ - -//#define __CARBONSOUND__ - + #error Apple OSX only! +#endif #include "GHOST_System.h" @@ -266,6 +263,11 @@ protected: * @return Indication whether the event was handled. */ GHOST_TSuccess handleTabletEvent(void *eventPtr); + + /** + * Helps handleTabletEvent function. + */ + void fillTabletData(GHOST_TabletData& tablet, void* event_ptr); /** * Handles a tablet proximity event. Sets pen or mouse ID for later events. @@ -307,7 +309,8 @@ protected: /** Start time at initialization. */ GHOST_TUns64 m_start_time; - + double m_start_time_2; + /** Event has been processed directly by Cocoa (or NDOF manager) and has sent a ghost event to be dispatched */ bool m_outsideLoopEventProcessed; @@ -336,4 +339,3 @@ protected: }; #endif // _GHOST_SYSTEM_COCOA_H_ - diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index b8eee5ed7e0..b17f7ab7c2e 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -568,6 +568,8 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() sysctl(mib, 2, &boottime, &len, NULL, 0); m_start_time = ((boottime.tv_sec*1000)+(boottime.tv_usec/1000)); + m_start_time_2 = CFAbsoluteTimeGetCurrent(); + //Detect multitouch trackpad mib[0] = CTL_HW; mib[1] = HW_MODEL; @@ -675,6 +677,7 @@ GHOST_TSuccess GHOST_SystemCocoa::init() GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const { +/* //Cocoa equivalent exists in 10.6 ([[NSProcessInfo processInfo] systemUptime]) struct timeval currentTime; @@ -682,6 +685,10 @@ GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const //Return timestamp of system uptime return ((currentTime.tv_sec*1000)+(currentTime.tv_usec/1000)-m_start_time); +*/ + + double now = CFAbsoluteTimeGetCurrent(); + return 1000 * (now - m_start_time_2); } @@ -1392,7 +1399,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) return GHOST_kFailure; } - GHOST_TabletData& ct = window->GetCocoaTabletData(); +// don't involve the window! +// GHOST_TabletData& ct = window->GetCocoaTabletData(); GHOST_TTabletMode active_tool; int* tool_id_ptr; @@ -1423,27 +1431,43 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) printf("entering\n"); *tool_id_ptr = [event deviceID]; - ct.Active = active_tool; - ct.Pressure = (active_tool == GHOST_kTabletModeNone) ? /*mouse*/ 1 : /*pen*/ 0; - ct.Xtilt = 0; - ct.Ytilt = 0; + m_tablet_pen_mode = active_tool; + +// ct.Active = active_tool; +// ct.Pressure = (active_tool == GHOST_kTabletModeNone) ? /*mouse*/ 1 : /*pen*/ 0; +// ct.Xtilt = 0; +// ct.Ytilt = 0; // this is a good place to remember the tool's capabilities - // (later though, after tablet mouse is fixed and (not) coalescing is in place) } else { printf("leaving\n"); *tool_id_ptr = TOOL_ID_NONE; - ct.Active = GHOST_kTabletModeNone; - ct.Pressure = 0; - ct.Xtilt = 0; - ct.Ytilt = 0; + m_tablet_pen_mode = GHOST_kTabletModeNone; + +// ct.Active = GHOST_kTabletModeNone; +// ct.Pressure = 0; +// ct.Xtilt = 0; +// ct.Ytilt = 0; } return GHOST_kSuccess; } +void GHOST_SystemCocoa::fillTabletData(GHOST_TabletData& tablet, void* event_ptr) + { + NSEvent* event = (NSEvent*)event_ptr; + NSPoint tilt = [event tilt]; + + tablet.Active = m_tablet_pen_mode; + tablet.Pressure = [event pressure]; + tablet.Xtilt = tilt.x; + tablet.Ytilt = tilt.y; + + printf("> pressure = %.2f tilt = %.2f %2f\n", tablet.Pressure, tablet.Xtilt, tablet.Ytilt); + } + GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) { puts("tablet point"); @@ -1456,35 +1480,49 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) return GHOST_kFailure; } +/* + // don't involve the window! GHOST_TabletData& ct = window->GetCocoaTabletData(); ct.Pressure = [event pressure]; NSPoint tilt = [event tilt]; ct.Xtilt = tilt.x; ct.Ytilt = tilt.y; +*/ switch ([event type]) { case NSLeftMouseDown: + { if (m_input_fidelity_hint == HI_FI) { printf("hi-fi on\n"); [NSEvent setMouseCoalescingEnabled:NO]; } - pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber]))); + GHOST_EventButton* e = new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber])); + GHOST_TEventButtonData* data = (GHOST_TEventButtonData*) e->getData(); + fillTabletData(data->tablet, event); + pushEvent(e); break; + } case NSLeftMouseUp: + { if (m_input_fidelity_hint == HI_FI) { printf("hi-fi off\n"); [NSEvent setMouseCoalescingEnabled:YES]; } + // no tablet data needed for 'pen up' pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber]))); break; + } default: { NSPoint pos = [event locationInWindow]; - pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, pos.x, pos.y)); + GHOST_EventCursor* e = new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, pos.x, pos.y); + GHOST_TEventCursorData* data = (GHOST_TEventCursorData*) e->getData(); + fillTabletData(data->tablet, event); + pushEvent(e); break; } } diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index 7948e88e1ab..c8285547e99 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -222,11 +222,8 @@ public: const GHOST_TabletData* GetTabletData() - { return &m_tablet; } + { return NULL; } - GHOST_TabletData& GetCocoaTabletData() - { return m_tablet; } - /** * Sets the progress bar value displayed in the window/application icon * @param progress The progress % (0.0 to 1.0) @@ -300,9 +297,6 @@ protected: static NSOpenGLContext *s_firstOpenGLcontext; NSCursor* m_customCursor; - - GHOST_TabletData m_tablet; }; #endif // _GHOST_WINDOW_COCOA_H_ - diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index a97f7621bb0..23535ba2f59 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -39,7 +39,7 @@ #include */ - + #include "GHOST_WindowCocoa.h" #include "GHOST_SystemCocoa.h" #include "GHOST_Debug.h" @@ -161,12 +161,12 @@ extern "C" { { NSPoint mouseLocation = [sender draggingLocation]; NSPasteboard *draggingPBoard = [sender draggingPasteboard]; - + if ([[draggingPBoard types] containsObject:NSTIFFPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeBitmap; else if ([[draggingPBoard types] containsObject:NSFilenamesPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeFilenames; else if ([[draggingPBoard types] containsObject:NSStringPboardType]) m_draggedObjectType = GHOST_kDragnDropTypeString; else return NSDragOperationNone; - + associatedWindow->setAcceptDragOperation(TRUE); //Drag operation is accepted by default systemCocoa->handleDraggingEvent(GHOST_kEventDraggingEntered, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil); return NSDragOperationCopy; @@ -180,7 +180,7 @@ extern "C" { - (NSDragOperation)draggingUpdated:(id < NSDraggingInfo >)sender { NSPoint mouseLocation = [sender draggingLocation]; - + systemCocoa->handleDraggingEvent(GHOST_kEventDraggingUpdated, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil); return associatedWindow->canAcceptDragOperation()?NSDragOperationCopy:NSDragOperationNone; } @@ -205,7 +205,7 @@ extern "C" { NSPasteboard *draggingPBoard = [sender draggingPasteboard]; NSImage *droppedImg; id data; - + switch (m_draggedObjectType) { case GHOST_kDragnDropTypeBitmap: if([NSImage canInitWithPasteboard:draggingPBoard]) { @@ -242,7 +242,7 @@ extern "C" { - (BOOL)acceptsFirstResponder { - return YES; + return YES; } //The trick to prevent Cocoa from complaining (beeping) @@ -254,10 +254,10 @@ extern "C" { - (BOOL)performKeyEquivalent:(NSEvent *)theEvent { NSString *chars = [theEvent charactersIgnoringModifiers]; - + if ([chars length] <1) return NO; - + //Let cocoa handle menu shortcuts switch ([chars characterAtIndex:0]) { case 'q': @@ -277,7 +277,7 @@ extern "C" { - (BOOL)isOpaque { - return YES; + return YES; } @end @@ -304,22 +304,21 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[40]; NSOpenGLPixelFormat *pixelFormat = nil; int i; - + m_systemCocoa = systemCocoa; m_fullScreen = false; - + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - //Creates the window NSRect rect; NSSize minSize; - + rect.origin.x = left; rect.origin.y = top; rect.size.width = width; rect.size.height = height; - + m_window = [[CocoaWindow alloc] initWithContentRect:rect styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask backing:NSBackingStoreBuffered defer:NO]; @@ -327,75 +326,75 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( [pool drain]; return; } - + [m_window setSystemAndWindowCocoa:systemCocoa windowCocoa:this]; - + //Forbid to resize the window below the blender defined minimum one minSize.width = 320; minSize.height = 240; [m_window setContentMinSize:minSize]; - + setTitle(title); - - + + // Pixel Format Attributes for the windowed NSOpenGLContext i=0; pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer; - + // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object’s flushBuffer // needed for 'Draw Overlap' drawing method pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore; - + pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated; //pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize; pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32; - - + + if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo; - + if (numOfAASamples>0) { // Multisample anti-aliasing pixelFormatAttrsWindow[i++] = NSOpenGLPFAMultisample; - + pixelFormatAttrsWindow[i++] = NSOpenGLPFASampleBuffers; pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 1; - + pixelFormatAttrsWindow[i++] = NSOpenGLPFASamples; pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) numOfAASamples; - + pixelFormatAttrsWindow[i++] = NSOpenGLPFANoRecovery; } - + pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0; - + pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow]; - - + + //Fall back to no multisampling if Antialiasing init failed if (pixelFormat == nil) { i=0; pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer; - + // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object’s flushBuffer // needed for 'Draw Overlap' drawing method pixelFormatAttrsWindow[i++] = NSOpenGLPFABackingStore; - + pixelFormatAttrsWindow[i++] = NSOpenGLPFAAccelerated; //pixelFormatAttrsWindow[i++] = NSOpenGLPFAAllowOfflineRenderers,; // Removed to allow 10.4 builds, and 2 GPUs rendering is not used anyway - + pixelFormatAttrsWindow[i++] = NSOpenGLPFADepthSize; pixelFormatAttrsWindow[i++] = (NSOpenGLPixelFormatAttribute) 32; - + if (stereoVisual) pixelFormatAttrsWindow[i++] = NSOpenGLPFAStereo; - + pixelFormatAttrsWindow[i] = (NSOpenGLPixelFormatAttribute) 0; - + pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow]; - + } - + if (numOfAASamples>0) { //Set m_numOfAASamples to the actual value GLint gli; [pixelFormat getValues:&gli forAttribute:NSOpenGLPFASamples forVirtualScreen:0]; @@ -404,40 +403,38 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( printf("GHOST_Window could be created with anti-aliasing of only %i samples\n",m_numOfAASamples); } } - + //Creates the OpenGL View inside the window m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect pixelFormat:pixelFormat]; - + [pixelFormat release]; - + m_openGLContext = [m_openGLView openGLContext]; //This context will be replaced by the proper one just after - + [m_window setContentView:m_openGLView]; [m_window setInitialFirstResponder:m_openGLView]; - + [m_window setReleasedWhenClosed:NO]; //To avoid bad pointer exception in case of user closing the window - + [m_window makeKeyAndOrderFront:nil]; - + setDrawingContextType(type); updateDrawingContext(); activateDrawingContext(); - - m_tablet.Active = GHOST_kTabletModeNone; - + CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init]; [windowDelegate setSystemAndWindowCocoa:systemCocoa windowCocoa:this]; [m_window setDelegate:windowDelegate]; - + [m_window setAcceptsMouseMovedEvents:YES]; - + [m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSStringPboardType, NSTIFFPboardType, nil]]; - + if (state == GHOST_kWindowStateFullScreen) setState(GHOST_kWindowStateFullScreen); - + [pool drain]; } @@ -448,14 +445,14 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa() NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLView release]; - + if (m_window) { [m_window close]; [[m_window delegate] release]; [m_window release]; m_window = nil; } - + //Check for other blender opened windows and make the frontmost key NSArray *windowsList = [NSApp orderedWindows]; if ([windowsList count]) { @@ -478,7 +475,7 @@ void* GHOST_WindowCocoa::getOSWindow() const void GHOST_WindowCocoa::setTitle(const STR_String& title) { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setTitle(): window invalid") NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *windowTitle = [[NSString alloc] initWithUTF8String:title]; diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 6b5bf7743ef..ad6ce5c4448 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -132,7 +132,6 @@ void mul_fac_qt_fl(float *q, float fac) q[1]*= si; q[2]*= si; q[3]*= si; - } void quat_to_mat3(float m[][3], float *q) @@ -308,7 +307,6 @@ void mat3_to_quat_is_ok(float q[4], float wmat[3][3]) mul_qt_qtqt(q, q1, q2); } - void normalize_qt(float *q) { float len; @@ -585,7 +583,7 @@ void axis_angle_to_quat(float q[4], float axis[3], float angle) } /* Quaternions to Axis Angle */ -void quat_to_axis_angle(float axis[3], float *angle,float q[4]) +void quat_to_axis_angle(float axis[3], float *angle, float q[4]) { float ha, si; @@ -687,7 +685,7 @@ void mat4_to_axis_angle(float axis[3], float *angle,float mat[4][4]) } /****************************** Vector/Rotation ******************************/ -/* TODO: the following calls should probably be depreceated sometime */ +/* TODO: the following calls should probably be deprecated sometime */ /* 3x3 matrix to axis angle */ void mat3_to_vec_rot(float axis[3], float *angle,float mat[3][3]) diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 7656295fd61..68ae37a0a56 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1233,6 +1233,8 @@ static int gpencil_draw_cancel (bContext *C, wmOperator *op) /* create a new stroke point at the point indicated by the painting context */ static void gpencil_draw_apply (bContext *C, wmOperator *op, tGPsdata *p) { + printf("< pressure = %.2f\n", p->pressure); + /* handle drawing/erasing -> test for erasing first */ if (p->paintmode == GP_PAINTMODE_ERASER) { /* do 'live' erasing now */ @@ -1245,6 +1247,7 @@ static void gpencil_draw_apply (bContext *C, wmOperator *op, tGPsdata *p) } /* only add current point to buffer if mouse moved (even though we got an event, it might be just noise) */ else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { + /* try to add point */ short ok= gp_stroke_addpoint(p, p->mval, p->pressure); @@ -1293,11 +1296,18 @@ static void gpencil_draw_apply_event (bContext *C, wmOperator *op, wmEvent *even wmTabletData *wmtab= event->customdata; tablet= (wmtab->Active != EVT_TABLET_NONE); - p->pressure= wmtab->Pressure; - if (wmtab->Active == EVT_TABLET_ERASER) + + + if (wmtab->Active == EVT_TABLET_ERASER) { // TODO... this should get caught by the keymaps which call drawing in the first place // .. but until that's possible, duct tape the eraser function back on p->paintmode = GP_PAINTMODE_ERASER; + p->pressure = wmtab->Pressure; + } + else { + /* 20% to 200% of normal mouse-based strength */ + p->pressure = 1.8 * wmtab->Pressure + 0.2; + } } else p->pressure= 1.0f; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index bce4a7e8f58..981b45c7396 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -313,7 +313,7 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) QUATCOPY(vod->oldquat, rv3d->viewquat); vod->origx= vod->oldx= event->x; vod->origy= vod->oldy= event->y; - vod->origkey= event->type; /* the key that triggered the operator. */ + vod->origkey= event->type; /* the key that triggered the operator. */ vod->use_dyn_ofs= (U.uiflag & USER_ORBIT_SELECTION) ? 1:0; if (vod->use_dyn_ofs) { @@ -351,7 +351,7 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) sub_v3_v3v3(my_pivot, rv3d->ofs, upvec); negate_v3(my_pivot); /* ofs is flipped */ - /* find a new ofs value that is allong the view axis (rather then the mouse location) */ + /* find a new ofs value that is along the view axis (rather then the mouse location) */ closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin); vod->dist0 = rv3d->dist = len_v3v3(my_pivot, dvec); @@ -498,7 +498,6 @@ void viewrotate_modal_keymap(wmKeyConfig *keyconf) /* assign map to operators */ WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate"); - } static void viewrotate_apply(ViewOpsData *vod, int x, int y) @@ -602,7 +601,6 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) int i; float viewmat[3][3]; - quat_to_mat3( viewmat,rv3d->viewquat); for (i = 0 ; i < 39; i++){ @@ -759,7 +757,6 @@ static int view3d_rotate_poll(bContext *C) void VIEW3D_OT_rotate(wmOperatorType *ot) { - /* identifiers */ ot->name= "Rotate view"; ot->description = "Rotate the view"; @@ -774,6 +771,169 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; } +// returns angular velocity (0..1), fills axis of rotation +// (shouldn't live in this file!) +float ndof_to_angle_axis(const float ndof[3], float axis[3]) + { + const float x = ndof[0]; + const float y = ndof[1]; + const float z = ndof[2]; + + float angular_velocity = sqrtf(x*x + y*y + z*z); + + float scale = 1.f / angular_velocity; + + // normalize + axis[0] = scale * x; + axis[1] = scale * y; + axis[2] = scale * z; + + return angular_velocity; + } + +static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + + float dt = ndof->dt; + + RegionView3D* rv3d = CTX_wm_region_view3d(C); + + if (dt > 0.25f) + /* this is probably the first event for this motion, so set dt to something reasonable */ + dt = 0.0125f; + + /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */ + float phi, q1[4]; + float m[3][3]; + float m_inv[3][3]; + float xvec[3] = {1,0,0}; + + const float sensitivity = 0.035; + + /* Get the 3x3 matrix and its inverse from the quaternion */ + quat_to_mat3(m,rv3d->viewquat); + invert_m3_m3(m_inv,m); + + /* Determine the direction of the x vector (for rotating up and down) */ + /* This can likely be computed directly from the quaternion. */ + mul_m3_v3(m_inv,xvec); + + /* Perform the up/down rotation */ + phi = sensitivity * -ndof->rx; + q1[0] = cos(phi); + mul_v3_v3fl(q1+1, xvec, sin(phi)); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); + + /* Perform the orbital rotation */ + phi = sensitivity * ndof->rz; + q1[0] = cos(phi); + q1[1] = q1[2] = 0.0; + q1[3] = sin(phi); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); + + ED_region_tag_redraw(CTX_wm_region(C)); + return OPERATOR_FINISHED; + } + +static int viewndof_invoke_1st_try(bContext *C, wmOperator *op, wmEvent *event) +{ + wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + + float dt = ndof->dt; + + RegionView3D *rv3d= CTX_wm_region_view3d(C); + + if (dt > 0.25f) + /* this is probably the first event for this motion, so set dt to something reasonable */ + dt = 0.0125f; + + /* very simple for now, move viewpoint along world axes */ + rv3d->ofs[0] += dt * ndof->tx; + rv3d->ofs[1] += dt * ndof->ty; + rv3d->ofs[2] += dt * ndof->tz; + +// request_depth_update(CTX_wm_region_view3d(C)); /* need this? */ + ED_region_tag_redraw(CTX_wm_region(C)); + + return OPERATOR_FINISHED; +} + +static int viewndof_invoke_2nd_try(bContext *C, wmOperator *op, wmEvent *event) +{ + wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + + float dt = ndof->dt; + + RegionView3D* rv3d = CTX_wm_region_view3d(C); + + if (dt > 0.25f) + /* this is probably the first event for this motion, so set dt to something reasonable */ + dt = 0.0125f; + + float axis[3]; + float angle = ndof_to_angle_axis(&(ndof->rx), axis); + + float eyeball_q[4];// = {0.f}; + +// float* eyeball_v = eyeball_q + 1; + + axis_angle_to_quat(eyeball_q, axis, angle); + + float eye_conj[4]; + copy_qt_qt(eye_conj, eyeball_q); + conjugate_qt(eye_conj); + +// float mat[3][3]; +// quat_to_mat3(mat, rv3d->viewquat); +/* + eyeball_v[0] = dt * ndof->tx; + eyeball_v[1] = dt * ndof->ty; + eyeball_v[2] = dt * ndof->tz; +*/ +// mul_m3_v3(mat, eyeball_vector); +// mul_qt_v3(rv3d->viewquat, eyeball_vector); + + // doesn't this transform v? + // v' = (q)(v)(~q) + + float view_q[4]; + copy_qt_qt(view_q, rv3d->viewquat); + +// float q_conj[4]; +// copy_qt_qt(q_conj, q); +// conjugate_qt(q_conj); + + mul_qt_qtqt(view_q, eyeball_q, view_q); + mul_qt_qtqt(view_q, view_q, eye_conj); + +// mul_qt_qtqt(eyeball_q, q, eyeball_q); +// mul_qt_qtqt(eyeball_q, eyeball_q, q_conj); + +// add_v3_v3(rv3d->ofs, eyeball_v); + + copy_qt_qt(rv3d->viewquat, view_q); + + ED_region_tag_redraw(CTX_wm_region(C)); + + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_ndof(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Navigate view"; + ot->description = "Navigate the view using a 3D mouse."; + ot->idname = "VIEW3D_OT_ndof"; + + /* api callbacks */ + ot->invoke = viewndof_invoke; + ot->poll = ED_operator_view3d_active; + + /* flags */ + ot->flag = 0; +} + /* ************************ viewmove ******************************** */ @@ -839,7 +999,6 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y) static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event) { - ViewOpsData *vod= op->customdata; short event_code= VIEW_PASS; @@ -2650,397 +2809,3 @@ int view_autodist_depth(struct ARegion *ar, short *mval, int margin, float *dept return (*depth==FLT_MAX) ? 0:1; return 0; } - -/* ********************* NDOF ************************ */ -/* note: this code is confusing and unclear... (ton) */ -/* **************************************************** */ - -// ndof scaling will be moved to user setting. -// In the mean time this is just a place holder. - -// Note: scaling in the plugin and ghostwinlay.c -// should be removed. With driver default setting, -// each axis returns approx. +-200 max deflection. - -// The values I selected are based on the older -// polling i/f. With event i/f, the sensistivity -// can be increased for improved response from -// small deflections of the device input. - - -// lukep notes : i disagree on the range. -// the normal 3Dconnection driver give +/-400 -// on defaut range in other applications -// and up to +/- 1000 if set to maximum -// because i remove the scaling by delta, -// which was a bad idea as it depend of the system -// speed and os, i changed the scaling values, but -// those are still not ok - - -float ndof_axis_scale[6] = { - +0.01, // Tx - +0.01, // Tz - +0.01, // Ty - +0.0015, // Rx - +0.0015, // Rz - +0.0015 // Ry -}; - -void filterNDOFvalues(float *sbval) -{ - int i=0; - float max = 0.0; - - for (i =0; i<6;i++) - if (fabs(sbval[i]) > max) - max = fabs(sbval[i]); - for (i =0; i<6;i++) - if (fabs(sbval[i]) != max ) - sbval[i]=0.0; -} - -// statics for controlling rv3d->dist corrections. -// viewmoveNDOF zeros and adjusts rv3d->ofs. -// viewmove restores based on dz_flag state. - -int dz_flag = 0; -float m_dist; - -void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int mode) -{ - RegionView3D *rv3d= ar->regiondata; - int i; - float phi; - float dval[7]; - // static fval[6] for low pass filter; device input vector is dval[6] - static float fval[6]; - float tvec[3],rvec[3]; - float q1[4]; - float mat[3][3]; - float upvec[3]; - - - /*---------------------------------------------------- - * sometimes this routine is called from headerbuttons - * viewmove needs to refresh the screen - */ -// XXX areawinset(ar->win); - - - // fetch the current state of the ndof device -// XXX getndof(dval); - - if (v3d->ndoffilter) - filterNDOFvalues(fval); - - // Scale input values - -// if(dval[6] == 0) return; // guard against divide by zero - - for(i=0;i<6;i++) { - - // user scaling - dval[i] = dval[i] * ndof_axis_scale[i]; - } - - - // low pass filter with zero crossing reset - - for(i=0;i<6;i++) { - if((dval[i] * fval[i]) >= 0) - dval[i] = (fval[i] * 15 + dval[i]) / 16; - else - fval[i] = 0; - } - - - // force perspective mode. This is a hack and is - // incomplete. It doesn't actually effect the view - // until the first draw and doesn't update the menu - // to reflect persp mode. - - rv3d->persp = RV3D_PERSP; - - - // Correct the distance jump if rv3d->dist != 0 - - // This is due to a side effect of the original - // mouse view rotation code. The rotation point is - // set a distance in front of the viewport to - // make rotating with the mouse look better. - // The distance effect is written at a low level - // in the view management instead of the mouse - // view function. This means that all other view - // movement devices must subtract this from their - // view transformations. - - if(rv3d->dist != 0.0) { - dz_flag = 1; - m_dist = rv3d->dist; - upvec[0] = upvec[1] = 0; - upvec[2] = rv3d->dist; - copy_m3_m4(mat, rv3d->viewinv); - mul_m3_v3(mat, upvec); - sub_v3_v3(rv3d->ofs, upvec); - rv3d->dist = 0.0; - } - - - // Apply rotation - // Rotations feel relatively faster than translations only in fly mode, so - // we have no choice but to fix that here (not in the plugins) - rvec[0] = -0.5 * dval[3]; - rvec[1] = -0.5 * dval[4]; - rvec[2] = -0.5 * dval[5]; - - // rotate device x and y by view z - - copy_m3_m4(mat, rv3d->viewinv); - mat[2][2] = 0.0f; - mul_m3_v3(mat, rvec); - - // rotate the view - - phi = normalize_v3(rvec); - if(phi != 0) { - axis_angle_to_quat(q1,rvec,phi); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); - } - - - // Apply translation - - tvec[0] = dval[0]; - tvec[1] = dval[1]; - tvec[2] = -dval[2]; - - // the next three lines rotate the x and y translation coordinates - // by the current z axis angle - - copy_m3_m4(mat, rv3d->viewinv); - mat[2][2] = 0.0f; - mul_m3_v3(mat, tvec); - - // translate the view - - sub_v3_v3(rv3d->ofs, tvec); - - - /*---------------------------------------------------- - * refresh the screen XXX - */ - - // update render preview window - -// XXX BIF_view3d_previewrender_signal(ar, PR_DBASE|PR_DISPRECT); -} - -void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int mode) -{ - RegionView3D *rv3d= ar->regiondata; - float fval[7]; - float dvec[3]; - float sbadjust = 1.0f; - float len; - short use_sel = 0; - Object *ob = OBACT; - float m[3][3]; - float m_inv[3][3]; - float xvec[3] = {1,0,0}; - float yvec[3] = {0,-1,0}; - float zvec[3] = {0,0,1}; - float phi; - float q1[4]; - float obofs[3]; - float reverse; - //float diff[4]; - float d, curareaX, curareaY; - float mat[3][3]; - float upvec[3]; - - /* Sensitivity will control how fast the view rotates. The value was - * obtained experimentally by tweaking until the author didn't get dizzy watching. - * Perhaps this should be a configurable user parameter. - */ - float psens = 0.005f * (float) U.ndof_pan; /* pan sensitivity */ - float rsens = 0.005f * (float) U.ndof_rotate; /* rotate sensitivity */ - float zsens = 0.3f; /* zoom sensitivity */ - - const float minZoom = -30.0f; - const float maxZoom = 300.0f; - - //reset view type - rv3d->view = 0; -//printf("passing here \n"); -// - if (scene->obedit==NULL && ob && !(ob->mode & OB_MODE_POSE)) { - use_sel = 1; - } - - if((dz_flag)||rv3d->dist==0) { - dz_flag = 0; - rv3d->dist = m_dist; - upvec[0] = upvec[1] = 0; - upvec[2] = rv3d->dist; - copy_m3_m4(mat, rv3d->viewinv); - mul_m3_v3(mat, upvec); - add_v3_v3(rv3d->ofs, upvec); - } - - /*---------------------------------------------------- - * sometimes this routine is called from headerbuttons - * viewmove needs to refresh the screen - */ -// XXX areawinset(curarea->win); - - /*---------------------------------------------------- - * record how much time has passed. clamp at 10 Hz - * pretend the previous frame occurred at the clamped time - */ -// now = PIL_check_seconds_timer(); - // frametime = (now - prevTime); - // if (frametime > 0.1f){ /* if more than 1/10s */ - // frametime = 1.0f/60.0; /* clamp at 1/60s so no jumps when starting to move */ -// } -// prevTime = now; - // sbadjust *= 60 * frametime; /* normalize ndof device adjustments to 100Hz for framerate independence */ - - /* fetch the current state of the ndof device & enforce dominant mode if selected */ -// XXX getndof(fval); - if (v3d->ndoffilter) - filterNDOFvalues(fval); - - - // put scaling back here, was previously in ghostwinlay - fval[0] = fval[0] * (1.0f/600.0f); - fval[1] = fval[1] * (1.0f/600.0f); - fval[2] = fval[2] * (1.0f/1100.0f); - fval[3] = fval[3] * 0.00005f; - fval[4] =-fval[4] * 0.00005f; - fval[5] = fval[5] * 0.00005f; - fval[6] = fval[6] / 1000000.0f; - - // scale more if not in perspective mode - if (rv3d->persp == RV3D_ORTHO) { - fval[0] = fval[0] * 0.05f; - fval[1] = fval[1] * 0.05f; - fval[2] = fval[2] * 0.05f; - fval[3] = fval[3] * 0.9f; - fval[4] = fval[4] * 0.9f; - fval[5] = fval[5] * 0.9f; - zsens *= 8; - } - - /* set object offset */ - if (ob) { - obofs[0] = -ob->obmat[3][0]; - obofs[1] = -ob->obmat[3][1]; - obofs[2] = -ob->obmat[3][2]; - } - else { - VECCOPY(obofs, rv3d->ofs); - } - - /* calc an adjustment based on distance from camera - disabled per patch 14402 */ - d = 1.0f; - -/* if (ob) { - sub_v3_v3v3(diff, obofs, rv3d->ofs); - d = len_v3(diff); - } -*/ - - reverse = (rv3d->persmat[2][1] < 0.0f) ? -1.0f : 1.0f; - - /*---------------------------------------------------- - * ndof device pan - */ - psens *= 1.0f + d; - curareaX = sbadjust * psens * fval[0]; - curareaY = sbadjust * psens * fval[1]; - dvec[0] = curareaX * rv3d->persinv[0][0] + curareaY * rv3d->persinv[1][0]; - dvec[1] = curareaX * rv3d->persinv[0][1] + curareaY * rv3d->persinv[1][1]; - dvec[2] = curareaX * rv3d->persinv[0][2] + curareaY * rv3d->persinv[1][2]; - add_v3_v3(rv3d->ofs, dvec); - - /*---------------------------------------------------- - * ndof device dolly - */ - len = zsens * sbadjust * fval[2]; - - if (rv3d->persp==RV3D_CAMOB) { - if(rv3d->persp==RV3D_CAMOB) { /* This is stupid, please fix - TODO */ - rv3d->camzoom+= 10.0f * -len; - } - if (rv3d->camzoom < minZoom) rv3d->camzoom = minZoom; - else if (rv3d->camzoom > maxZoom) rv3d->camzoom = maxZoom; - } - else if ((rv3d->dist> 0.001*v3d->grid) && (rv3d->dist<10.0*v3d->far)) { - rv3d->dist*=(1.0 + len); - } - - - /*---------------------------------------------------- - * ndof device turntable - * derived from the turntable code in viewmove - */ - - /* Get the 3x3 matrix and its inverse from the quaternion */ - quat_to_mat3( m,rv3d->viewquat); - invert_m3_m3(m_inv,m); - - /* Determine the direction of the x vector (for rotating up and down) */ - /* This can likely be compuated directly from the quaternion. */ - mul_m3_v3(m_inv,xvec); - mul_m3_v3(m_inv,yvec); - mul_m3_v3(m_inv,zvec); - - /* Perform the up/down rotation */ - phi = sbadjust * rsens * /*0.5f * */ fval[3]; /* spin vertically half as fast as horizontally */ - q1[0] = cos(phi); - mul_v3_v3fl(q1+1, xvec, sin(phi)); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); - - if (use_sel) { - conjugate_qt(q1); /* conj == inv for unit quat */ - sub_v3_v3(rv3d->ofs, obofs); - mul_qt_v3(q1, rv3d->ofs); - add_v3_v3(rv3d->ofs, obofs); - } - - /* Perform the orbital rotation */ - /* Perform the orbital rotation - If the seen Up axis is parallel to the zoom axis, rotation should be - achieved with a pure Roll motion (no Spin) on the device. When you start - to tilt, moving from Top to Side view, Spinning will increasingly become - more relevant while the Roll component will decrease. When a full - Side view is reached, rotations around the world's Up axis are achieved - with a pure Spin-only motion. In other words the control of the spinning - around the world's Up axis should move from the device's Spin axis to the - device's Roll axis depending on the orientation of the world's Up axis - relative to the screen. */ - //phi = sbadjust * rsens * reverse * fval[4]; /* spin the knob, y axis */ - phi = sbadjust * rsens * (yvec[2] * fval[4] + zvec[2] * fval[5]); - q1[0] = cos(phi); - q1[1] = q1[2] = 0.0; - q1[3] = sin(phi); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); - - if (use_sel) { - conjugate_qt(q1); - sub_v3_v3(rv3d->ofs, obofs); - mul_qt_v3(q1, rv3d->ofs); - add_v3_v3(rv3d->ofs, obofs); - } - - /*---------------------------------------------------- - * refresh the screen - */ -// XXX scrarea_do_windraw(curarea); -} - - - - diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 846300ff9a6..ca75eb81724 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -71,6 +71,7 @@ void view3d_keymap(struct wmKeyConfig *keyconf); void VIEW3D_OT_zoom(struct wmOperatorType *ot); void VIEW3D_OT_move(struct wmOperatorType *ot); void VIEW3D_OT_rotate(struct wmOperatorType *ot); +void VIEW3D_OT_ndof(struct wmOperatorType *ot); void VIEW3D_OT_view_all(struct wmOperatorType *ot); void VIEW3D_OT_viewnumpad(struct wmOperatorType *ot); void VIEW3D_OT_view_selected(struct wmOperatorType *ot); @@ -98,8 +99,6 @@ void draw_motion_path_instance(Scene *scene, View3D *v3d, struct ARegion *ar, struct bAnimVizSettings *avs, struct bMotionPath *mpath); void draw_motion_paths_cleanup(Scene *scene, View3D *v3d, struct ARegion *ar); - - /* drawobject.c */ void draw_object(Scene *scene, struct ARegion *ar, View3D *v3d, Base *base, int flag); int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt); @@ -192,4 +191,3 @@ void draw_volume(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, st #endif /* ED_VIEW3D_INTERN_H */ - diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 22fab5887ee..dced49494ca 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -28,6 +28,7 @@ #include #include +#include // [mce] debug, remove when finished #include "MEM_guardedalloc.h" @@ -61,6 +62,7 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_rotate); WM_operatortype_append(VIEW3D_OT_move); WM_operatortype_append(VIEW3D_OT_zoom); + WM_operatortype_append(VIEW3D_OT_ndof); WM_operatortype_append(VIEW3D_OT_view_all); WM_operatortype_append(VIEW3D_OT_viewnumpad); WM_operatortype_append(VIEW3D_OT_view_orbit); @@ -155,12 +157,17 @@ void view3d_keymap(wmKeyConfig *keyconf) RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", HOMEKEY, KM_PRESS, 0, 0)->ptr, "center", 0); /* only without camera view */ RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", CKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "center", 1); + /* 3D mouse */ + WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON1, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "VIEW3D_OT_ndof", NDOF_MOTION, 0, 0, 0); + /* numpad view hotkeys*/ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD0, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_CAMERA); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD1, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", PAD2, KM_PRESS, 0, 0)->ptr, "type", V3D_VIEW_STEPDOWN); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD3, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_RIGHT); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", PAD4, KM_PRESS, 0, 0)->ptr, "type", V3D_VIEW_STEPLEFT); + WM_keymap_add_item(keymap, "VIEW3D_OT_view_persportho", PAD5, KM_PRESS, 0, 0); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", PAD6, KM_PRESS, 0, 0)->ptr, "type", V3D_VIEW_STEPRIGHT); @@ -300,4 +307,3 @@ void view3d_keymap(wmKeyConfig *keyconf) viewmove_modal_keymap(keyconf); viewzoom_modal_keymap(keyconf); } - diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index c5516a3bff5..23934f665c5 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -47,10 +47,10 @@ struct wmTimer; /* This is needed to not let VC choke on near and far... old * proprietary MS extensions... */ #ifdef WIN32 -#undef near -#undef far -#define near clipsta -#define far clipend + #undef near + #undef far + #define near clipsta + #define far clipend #endif #include "DNA_listBase.h" @@ -137,12 +137,12 @@ typedef struct View3D { float blockscale; short blockhandler[8]; - float viewquat[4], dist, pad1; /* XXX depricated */ + float viewquat[4], dist, pad1; /* XXX deprecated */ int lay_used; /* used while drawing */ - short persp; /* XXX depricated */ - short view; /* XXX depricated */ + short persp; /* XXX deprecated */ + short view; /* XXX deprecated */ struct Object *camera, *ob_centre; @@ -298,5 +298,3 @@ typedef struct View3D { #define V3D_BGPIC_EXPANDED 2 #endif - - diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index c84a5e64889..e6e75bf793c 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -346,6 +346,7 @@ typedef struct wmEvent { } wmEvent; /* ************** custom wmEvent data ************** */ + typedef struct wmTabletData { int Active; /* 0=EVT_TABLET_NONE, 1=EVT_TABLET_STYLUS, 2=EVT_TABLET_ERASER */ float Pressure; /* range 0.0 (not touching) to 1.0 (full pressure) */ @@ -371,6 +372,19 @@ typedef struct wmTimer { int sleep; /* internal, put timers to sleep when needed */ } wmTimer; +typedef struct { + /* awfully similar to GHOST_TEventNDOFMotionData... */ + + /* 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) +} wmNDOFMotionData; + typedef struct wmOperatorType { struct wmOperatorType *next, *prev; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 63dcda3c12e..030ce7fa888 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -29,6 +29,7 @@ #include #include #include +#include // [mce] debug, remove when finished #include "DNA_listBase.h" #include "DNA_screen_types.h" @@ -99,7 +100,7 @@ void wm_event_free(wmEvent *event) void wm_event_free_all(wmWindow *win) { wmEvent *event; - + while((event= win->queue.first)) { BLI_remlink(&win->queue, event); wm_event_free(event); @@ -115,7 +116,7 @@ static int wm_test_duplicate_notifier(wmWindowManager *wm, unsigned int type, vo for(note=wm->queue.first; note; note=note->next) if((note->category|note->data|note->subtype|note->action) == type && note->reference == reference) return 1; - + return 0; } @@ -123,20 +124,20 @@ static int wm_test_duplicate_notifier(wmWindowManager *wm, unsigned int type, vo void WM_event_add_notifier(const bContext *C, unsigned int type, void *reference) { wmNotifier *note= MEM_callocN(sizeof(wmNotifier), "notifier"); - + note->wm= CTX_wm_manager(C); BLI_addtail(¬e->wm->queue, note); - + note->window= CTX_wm_window(C); - + if(CTX_wm_region(C)) note->swinid= CTX_wm_region(C)->swinid; - + note->category= type & NOTE_CATEGORY; note->data= type & NOTE_DATA; note->subtype= type & NOTE_SUBTYPE; note->action= type & NOTE_ACTION; - + note->reference= reference; } @@ -147,15 +148,15 @@ void WM_main_add_notifier(unsigned int type, void *reference) if(wm && !wm_test_duplicate_notifier(wm, type, reference)) { wmNotifier *note= MEM_callocN(sizeof(wmNotifier), "notifier"); - + note->wm= wm; BLI_addtail(¬e->wm->queue, note); - + note->category= type & NOTE_CATEGORY; note->data= type & NOTE_DATA; note->subtype= type & NOTE_SUBTYPE; note->action= type & NOTE_ACTION; - + note->reference= reference; } } @@ -177,13 +178,13 @@ void wm_event_do_notifiers(bContext *C) if(wm==NULL) return; - + /* cache & catch WM level notifiers, such as frame change, scene/screen set */ for(win= wm->windows.first; win; win= win->next) { int do_anim= 0; - + CTX_wm_window_set(C, win); - + for(note= wm->queue.first; note; note= next) { next= note->next; @@ -219,13 +220,12 @@ void wm_event_do_notifiers(bContext *C) } else if(note->data==ND_FRAME) do_anim= 1; - + if(note->action == NA_REMOVED) { ED_screen_delete_scene(C, note->reference); // XXX hrms, think this over! if(G.f & G_DEBUG) printf("scene delete %p\n", note->reference); } - } } if(ELEM5(note->category, NC_SCENE, NC_OBJECT, NC_GEOM, NC_SCENE, NC_WM)) { @@ -245,13 +245,13 @@ void wm_event_do_notifiers(bContext *C) } } } - + /* the notifiers are sent without context, to keep it clean */ while( (note=wm_notifier_next(wm)) ) { wmWindow *win; - + for(win= wm->windows.first; win; win= win->next) { - + /* filter out notifiers */ if(note->category==NC_SCREEN && note->reference && note->reference!=win->screen); else if(note->category==NC_SCENE && note->reference && note->reference!=win->screen->scene); @@ -268,7 +268,7 @@ void wm_event_do_notifiers(bContext *C) for(ar=win->screen->regionbase.first; ar; ar= ar->next) { ED_region_do_listen(ar, note); } - + for(sa= win->screen->areabase.first; sa; sa= sa->next) { ED_area_do_listen(sa, note); for(ar=sa->regionbase.first; ar; ar= ar->next) { @@ -277,14 +277,14 @@ void wm_event_do_notifiers(bContext *C) } } } - + MEM_freeN(note); } - + /* cached: editor refresh callbacks now, they get context */ for(win= wm->windows.first; win; win= win->next) { ScrArea *sa; - + CTX_wm_window_set(C, win); for(sa= win->screen->areabase.first; sa; sa= sa->next) { if(sa->do_refresh) { @@ -292,7 +292,7 @@ void wm_event_do_notifiers(bContext *C) ED_area_do_refresh(C, sa); } } - + /* XXX make lock in future, or separated derivedmesh users in scene */ if(!G.rendering) /* depsgraph & animation: update tagged datablocks */ @@ -310,7 +310,7 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve ARegion *region= CTX_wm_region(C); ARegion *menu= CTX_wm_menu(C); int retval; - + /* we set context to where ui handler came from */ if(handler->ui_area) CTX_wm_area_set(C, handler->ui_area); if(handler->ui_region) CTX_wm_region_set(C, handler->ui_region); @@ -362,14 +362,14 @@ static void wm_handler_ui_cancel(bContext *C) int WM_operator_poll(bContext *C, wmOperatorType *ot) { wmOperatorTypeMacro *otmacro; - + for(otmacro= ot->macro.first; otmacro; otmacro= otmacro->next) { wmOperatorType *ot= WM_operatortype_find(otmacro->idname, 0); if(0==WM_operator_poll(C, ot)) return 0; } - + /* python needs operator type, so we added exception for it */ if(ot->pyop_poll) return ot->pyop_poll(C, ot); @@ -391,7 +391,7 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, int pop wmWindowManager *wm = CTX_wm_manager(C); ReportList *reports = CTX_wm_reports(C); char *buf; - + if(popup) if(op->reports->list.first) uiPupMenuReports(C, op->reports); @@ -399,7 +399,7 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, int pop if(retval & OPERATOR_FINISHED) { if(G.f & G_DEBUG) wm_operator_print(op); /* todo - this print may double up, might want to check more flags then the FINISHED */ - + if (op->type->flag & OPTYPE_REGISTER) { /* Report the python string representation of the operator */ buf = WM_operator_pystring(C, op->type, op->ptr, 1); @@ -410,16 +410,16 @@ static void wm_operator_reports(bContext *C, wmOperator *op, int retval, int pop if (op->reports->list.first) { ReportTimerInfo *rti; - + /* add reports to the global list, otherwise they are not seen */ addlisttolist(&CTX_wm_reports(C)->list, &op->reports->list); - + /* After adding reports to the global list, reset the report timer. */ WM_event_remove_timer(wm, NULL, reports->reporttimer); - + /* Records time since last report was added */ reports->reporttimer= WM_event_add_timer(wm, CTX_wm_window(C), TIMER, 0.02); - + rti = MEM_callocN(sizeof(ReportTimerInfo), "ReportTimerInfo"); reports->reporttimer->customdata = rti; } @@ -457,13 +457,13 @@ static int wm_operator_exec(bContext *C, wmOperator *op, int repeat) { wmWindowManager *wm= CTX_wm_manager(C); int retval= OPERATOR_CANCELLED; - + if(op==NULL || op->type==NULL) return retval; - + if(0==WM_operator_poll(C, op->type)) return retval; - + if(op->type->exec) { if(op->type->flag & OPTYPE_UNDO) wm->op_undo_depth++; @@ -473,17 +473,16 @@ static int wm_operator_exec(bContext *C, wmOperator *op, int repeat) if(op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) wm->op_undo_depth--; } - + if (retval & (OPERATOR_FINISHED|OPERATOR_CANCELLED) && repeat == 0) wm_operator_reports(C, op, retval, 0); - + if(retval & OPERATOR_FINISHED) wm_operator_finished(C, op, repeat); else if(repeat==0) WM_operator_free(op); - + return retval | OPERATOR_HANDLED; - } /* for running operators with frozen context (modal handlers, menus) */ @@ -501,11 +500,11 @@ int WM_operator_repeat(bContext *C, wmOperator *op) static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot, PointerRNA *properties, ReportList *reports) { wmOperator *op= MEM_callocN(sizeof(wmOperator), ot->idname); /* XXX operatortype names are static still. for debug */ - + /* XXX adding new operator could be function, only happens here now */ op->type= ot; BLI_strncpy(op->idname, ot->idname, OP_MAX_TYPENAME); - + /* initialize properties, either copy or create */ op->ptr= MEM_callocN(sizeof(PointerRNA), "wmOperatorPtrRNA"); if(properties && properties->data) { @@ -525,20 +524,19 @@ static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot, P op->reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList"); BKE_reports_init(op->reports, RPT_STORE|RPT_FREE); } - + /* recursive filling of operator macro list */ if(ot->macro.first) { static wmOperator *motherop= NULL; wmOperatorTypeMacro *otmacro; int root = 0; - + /* ensure all ops are in execution order in 1 list */ if(motherop==NULL) { motherop = op; root = 1; } - /* if properties exist, it will contain everything needed */ if (properties) { otmacro= ot->macro.first; @@ -573,11 +571,11 @@ static wmOperator *wm_operator_create(wmWindowManager *wm, wmOperatorType *ot, P opm->opm= motherop; /* pointer to mom, for modal() */ } } - + if (root) motherop= NULL; } - + WM_operator_properties_sanitize(op->ptr, 0); return op; @@ -600,10 +598,10 @@ int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, PointerR if(WM_operator_poll(C, ot)) { wmOperator *op= wm_operator_create(wm, ot, properties, reports); /* if reports==NULL, theyll be initialized */ - + if((G.f & G_DEBUG) && event && event->type!=MOUSEMOVE) printf("handle evt %d win %d op %s\n", event?event->type:0, CTX_wm_screen(C)->subwinactive, ot->idname); - + if(op->type->invoke && event) { wm_region_mouse_co(C, event); @@ -626,14 +624,13 @@ int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, PointerR } else printf("invalid operator call %s\n", ot->idname); /* debug, important to leave a while, should never happen */ - + /* Note, if the report is given as an argument then assume the caller will deal with displaying them * currently python only uses this */ if (!(retval & OPERATOR_HANDLED) && retval & (OPERATOR_FINISHED|OPERATOR_CANCELLED)) /* only show the report if the report list was not given in the function */ wm_operator_reports(C, op, retval, (reports==NULL)); - - + if(retval & OPERATOR_HANDLED) ; /* do nothing, wm_operator_exec() has been called somewhere */ else if(retval & OPERATOR_FINISHED) { @@ -708,7 +705,7 @@ static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, int contex } switch(context) { - + case WM_OP_EXEC_REGION_WIN: case WM_OP_INVOKE_REGION_WIN: case WM_OP_EXEC_REGION_CHANNELS: @@ -727,36 +724,36 @@ static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, int contex case WM_OP_EXEC_REGION_CHANNELS: case WM_OP_INVOKE_REGION_CHANNELS: type = RGN_TYPE_CHANNELS; - + case WM_OP_EXEC_REGION_PREVIEW: case WM_OP_INVOKE_REGION_PREVIEW: type = RGN_TYPE_PREVIEW; break; - + case WM_OP_EXEC_REGION_WIN: case WM_OP_INVOKE_REGION_WIN: default: type = RGN_TYPE_WINDOW; break; } - + if(!(ar && ar->regiontype == type) && area) { ARegion *ar1= BKE_area_find_region_type(area, type); if(ar1) CTX_wm_region_set(C, ar1); } - + retval= wm_operator_invoke(C, ot, event, properties, reports); - + /* set region back */ CTX_wm_region_set(C, ar); - + return retval; } case WM_OP_EXEC_AREA: case WM_OP_INVOKE_AREA: { - /* remove region from context */ + /* remove region from context */ ARegion *ar= CTX_wm_region(C); CTX_wm_region_set(C, NULL); @@ -785,7 +782,7 @@ static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, int contex return wm_operator_invoke(C, ot, event, properties, reports); } } - + return 0; } @@ -828,13 +825,13 @@ int WM_operator_call_py(bContext *C, wmOperatorType *ot, int context, PointerRNA #endif retval= wm_operator_call_internal(C, ot, context, properties, reports); - + /* keep the reports around if needed later */ if (retval & OPERATOR_RUNNING_MODAL || ot->flag & OPTYPE_REGISTER) { reports->flag |= RPT_FREE; } - + return retval; } @@ -851,13 +848,13 @@ void wm_event_free_handler(wmEventHandler *handler) static void wm_handler_op_context(bContext *C, wmEventHandler *handler) { bScreen *screen= CTX_wm_screen(C); - + if(screen && handler->op) { if(handler->op_area==NULL) CTX_wm_area_set(C, NULL); else { ScrArea *sa; - + for(sa= screen->areabase.first; sa; sa= sa->next) if(sa==handler->op_area) break; @@ -886,16 +883,16 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers) { wmEventHandler *handler; wmWindowManager *wm= CTX_wm_manager(C); - + /* C is zero on freeing database, modal handlers then already were freed */ while((handler=handlers->first)) { BLI_remlink(handlers, handler); - + if(handler->op) { if(handler->op->type->cancel) { ScrArea *area= CTX_wm_area(C); ARegion *region= CTX_wm_region(C); - + wm_handler_op_context(C, handler); if(handler->op->type->flag & OPTYPE_UNDO) @@ -917,7 +914,7 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers) ScrArea *area= CTX_wm_area(C); ARegion *region= CTX_wm_region(C); ARegion *menu= CTX_wm_menu(C); - + if(handler->ui_area) CTX_wm_area_set(C, handler->ui_area); if(handler->ui_region) CTX_wm_region_set(C, handler->ui_region); if(handler->ui_menu) CTX_wm_menu_set(C, handler->ui_menu); @@ -942,45 +939,45 @@ int WM_userdef_event_map(int kmitype) return LEFTMOUSE; else return RIGHTMOUSE; - + case ACTIONMOUSE: if(U.flag & USER_LMOUSESELECT) return RIGHTMOUSE; else return LEFTMOUSE; - + case WHEELOUTMOUSE: if(U.uiflag & USER_WHEELZOOMDIR) return WHEELUPMOUSE; else return WHEELDOWNMOUSE; - + case WHEELINMOUSE: if(U.uiflag & USER_WHEELZOOMDIR) return WHEELDOWNMOUSE; else return WHEELUPMOUSE; - + case EVT_TWEAK_A: if(U.flag & USER_LMOUSESELECT) return EVT_TWEAK_R; else return EVT_TWEAK_L; - + case EVT_TWEAK_S: if(U.flag & USER_LMOUSESELECT) return EVT_TWEAK_L; else return EVT_TWEAK_R; } - + return kmitype; } static void wm_eventemulation(wmEvent *event) { static int mmb_emulated = 0; /* this should be in a data structure somwhere */ - + /* middlemouse emulation */ if(U.flag & USER_TWOBUTTONMOUSE) { if(event->type == LEFTMOUSE && (event->alt || mmb_emulated == KM_PRESS)) { @@ -1032,10 +1029,10 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) if(ISTEXTINPUT(winevent->type) && winevent->ascii) return 1; if(kmitype!=KM_ANY) if(winevent->type!=kmitype) return 0; - + if(kmi->val!=KM_ANY) if(winevent->val!=kmi->val) return 0; - + /* modifiers also check bits, so it allows modifier order */ if(kmi->shift!=KM_ANY) if(winevent->shift != kmi->shift && !(winevent->shift & kmi->shift)) return 0; @@ -1045,16 +1042,16 @@ static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) if(winevent->alt != kmi->alt && !(winevent->alt & kmi->alt)) return 0; if(kmi->oskey!=KM_ANY) if(winevent->oskey != kmi->oskey && !(winevent->oskey & kmi->oskey)) return 0; - + if(kmi->keymodifier) if(winevent->keymodifier!=kmi->keymodifier) return 0; - + /* key modifiers always check when event has it */ /* otherwise regular keypresses with keymodifier still work */ if(winevent->keymodifier) if(ISTEXTINPUT(winevent->type)) if(winevent->keymodifier!=kmi->keymodifier) return 0; - + return 1; } @@ -1077,7 +1074,6 @@ static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *eve for(kmi= keymap->items.first; kmi; kmi= kmi->next) { if(wm_eventmatch(event, kmi)) { - event->type= EVT_MODAL_MAP; event->val= kmi->propvalue; } @@ -1089,7 +1085,7 @@ static void wm_event_modalkeymap(const bContext *C, wmOperator *op, wmEvent *eve static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHandler *handler, wmEvent *event, PointerRNA *properties) { int retval= OPERATOR_PASS_THROUGH; - + /* derived, modal or blocking operator */ if(handler->op) { wmOperator *op= handler->op; @@ -1100,11 +1096,11 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand wmWindowManager *wm= CTX_wm_manager(C); ScrArea *area= CTX_wm_area(C); ARegion *region= CTX_wm_region(C); - + wm_handler_op_context(C, handler); wm_region_mouse_co(C, event); wm_event_modalkeymap(C, op, event); - + if(ot->flag & OPTYPE_UNDO) wm->op_undo_depth++; @@ -1122,11 +1118,11 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand /* this special cases is for areas and regions that get removed */ CTX_wm_area_set(C, NULL); CTX_wm_region_set(C, NULL); - } + } if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) wm_operator_reports(C, op, retval, 0); - + if(retval & OPERATOR_FINISHED) { wm_operator_finished(C, op, 0); handler->op= NULL; @@ -1135,18 +1131,17 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand WM_operator_free(op); handler->op= NULL; } - + /* remove modal handler, operator itself should have been cancelled and freed */ if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) { WM_cursor_ungrab(CTX_wm_window(C)); BLI_remlink(handlers, handler); wm_event_free_handler(handler); - + /* prevent silly errors from operator users */ //retval &= ~OPERATOR_PASS_THROUGH; } - } else printf("wm_handler_operator_call error\n"); @@ -1178,18 +1173,18 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa wmWindowManager *wm= CTX_wm_manager(C); SpaceFile *sfile; int action= WM_HANDLER_CONTINUE; - + if(event->type != EVT_FILESELECT) return action; if(handler->op != (wmOperator *)event->customdata) return action; - + switch(event->val) { case EVT_FILESELECT_OPEN: case EVT_FILESELECT_FULL_OPEN: - { + { ScrArea *sa; - + /* sa can be null when window A is active, but mouse is over window B */ /* in this case, open file select in original window A */ if (handler->op_area == NULL) { @@ -1197,37 +1192,37 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa sa = (ScrArea *)screen->areabase.first; } else sa = handler->op_area; - + if(event->val==EVT_FILESELECT_OPEN) ED_area_newspace(C, sa, SPACE_FILE); else ED_screen_full_newspace(C, sa, SPACE_FILE); /* sets context */ - + /* settings for filebrowser, sfile is not operator owner but sends events */ sa = CTX_wm_area(C); sfile= (SpaceFile*)sa->spacedata.first; sfile->op= handler->op; ED_fileselect_set_params(sfile); - + action= WM_HANDLER_BREAK; } break; - + case EVT_FILESELECT_EXEC: case EVT_FILESELECT_CANCEL: { /* XXX validate area and region? */ bScreen *screen= CTX_wm_screen(C); - + if(screen != handler->filescreen) ED_screen_full_prevspace(C, CTX_wm_area(C)); else ED_area_prevspace(C, CTX_wm_area(C)); - + /* remlink now, for load file case */ BLI_remlink(handlers, handler); - + wm_handler_op_context(C, handler); /* needed for uiPupMenuReports */ @@ -1253,11 +1248,11 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa if(handler->op->type->flag & OPTYPE_UNDO && CTX_wm_manager(C) == wm) wm->op_undo_depth--; - + if (retval & OPERATOR_FINISHED) if(G.f & G_DEBUG) wm_operator_print(handler->op); - + if(wm->op_undo_depth == 0) if(handler->op->type->flag & OPTYPE_UNDO) ED_undo_push_op(C, handler->op); @@ -1299,14 +1294,14 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa } CTX_wm_area_set(C, NULL); - + wm_event_free_handler(handler); - + action= WM_HANDLER_BREAK; } break; } - + return action; } @@ -1358,7 +1353,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) if(handler_boundbox_test(handler, event)) { /* in advance to avoid access to freed event on window close */ always_pass= wm_event_always_pass(event); - + /* modal+blocking handler */ if(handler->flag & WM_HANDLER_BLOCKING) action |= WM_HANDLER_BREAK; @@ -1366,13 +1361,13 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) if(handler->keymap) { wmKeyMap *keymap= WM_keymap_active(wm, handler->keymap); wmKeyMapItem *kmi; - + if(!keymap->poll || keymap->poll(C)) { for(kmi= keymap->items.first; kmi; kmi= kmi->next) { if(wm_eventmatch(event, kmi)) { - + event->keymap_idname= kmi->idname; /* weak, but allows interactive callback to not use rawkey */ - + action |= wm_handler_operator_call(C, handlers, handler, event, kmi->ptr); if(action & WM_HANDLER_BREAK) /* not always_pass here, it denotes removed handler */ break; @@ -1398,7 +1393,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) for(drag= lb->first; drag; drag= drag->next) { if(drop->poll(C, drag, event)) { drop->copy(drag, drop); - + wm_operator_invoke(C, drop->ot, event, drop->ptr, NULL); action |= WM_HANDLER_BREAK; } @@ -1419,7 +1414,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) break; } } - + /* fileread case */ if(CTX_wm_window(C)==NULL) return action; @@ -1443,7 +1438,6 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) action |= wm_handlers_do(C, event, handlers); } - /* revert value if not handled */ if (wm_action_not_handled(action)) { event->val = KM_RELEASE; @@ -1473,7 +1467,7 @@ static ScrArea *area_event_inside(bContext *C, int x, int y) { bScreen *screen= CTX_wm_screen(C); ScrArea *sa; - + if(screen) for(sa= screen->areabase.first; sa; sa= sa->next) if(BLI_in_rcti(&sa->totrct, x, y)) @@ -1486,7 +1480,7 @@ static ARegion *region_event_inside(bContext *C, int x, int y) bScreen *screen= CTX_wm_screen(C); ScrArea *area= CTX_wm_area(C); ARegion *ar; - + if(screen && area) for(ar= area->regionbase.first; ar; ar= ar->next) if(BLI_in_rcti(&ar->winrct, x, y)) @@ -1512,21 +1506,21 @@ static void wm_paintcursor_tag(bContext *C, wmPaintCursor *pc, ARegion *ar) static void wm_paintcursor_test(bContext *C, wmEvent *event) { wmWindowManager *wm= CTX_wm_manager(C); - + if(wm->paintcursors.first) { ARegion *ar= CTX_wm_region(C); if(ar) wm_paintcursor_tag(C, wm->paintcursors.first, ar); - + /* if previous position was not in current region, we have to set a temp new context */ if(ar==NULL || !BLI_in_rcti(&ar->winrct, event->prevx, event->prevy)) { ScrArea *sa= CTX_wm_area(C); - + CTX_wm_area_set(C, area_event_inside(C, event->prevx, event->prevy)); CTX_wm_region_set(C, region_event_inside(C, event->prevx, event->prevy)); wm_paintcursor_tag(C, wm->paintcursors.first, CTX_wm_region(C)); - + CTX_wm_area_set(C, sa); CTX_wm_region_set(C, ar); } @@ -1536,7 +1530,7 @@ static void wm_paintcursor_test(bContext *C, wmEvent *event) static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *event) { if(wm->drags.first==NULL) return; - + if(event->type==MOUSEMOVE) win->screen->do_draw_drag= 1; else if(event->type==ESCKEY) { @@ -1545,24 +1539,24 @@ static void wm_event_drag_test(wmWindowManager *wm, wmWindow *win, wmEvent *even } else if(event->type==LEFTMOUSE && event->val==KM_RELEASE) { event->type= EVT_DROP; - + /* create customdata, first free existing */ if(event->customdata) { if(event->customdatafree) MEM_freeN(event->customdata); } - + event->custom= EVT_DATA_LISTBASE; event->customdata= &wm->drags; event->customdatafree= 1; - + /* clear drop icon */ win->screen->do_draw_drag= 1; - + /* restore cursor (disabled, see wm_dragdrop.c) */ // WM_cursor_restore(win); } - + /* overlap fails otherwise */ if(win->screen->do_draw_drag) if(win->drawmethod == USER_DRAW_OVERLAP) @@ -1579,24 +1573,24 @@ void wm_event_do_handlers(bContext *C) for(win= wm->windows.first; win; win= win->next) { wmEvent *event; - + if( win->screen==NULL ) wm_event_free_all(win); else { Scene* scene = win->screen->scene; - + if(scene) { int playing = sound_scene_playing(win->screen->scene); - + if(playing != -1) { CTX_wm_window_set(C, win); CTX_wm_screen_set(C, win->screen); CTX_data_scene_set(C, scene); - + if(((playing == 1) && (!win->screen->animtimer)) || ((playing == 0) && (win->screen->animtimer))){ ED_screen_animation_play(C, -1, 1); } - + if(playing == 0) { int ncfra = sound_sync_scene(scene) * FPS + 0.5; if(ncfra != scene->r.cfra) { @@ -1605,41 +1599,41 @@ void wm_event_do_handlers(bContext *C) WM_event_add_notifier(C, NC_WINDOW, NULL); } } - + CTX_data_scene_set(C, NULL); CTX_wm_screen_set(C, NULL); CTX_wm_window_set(C, NULL); } } } - + while( (event= win->queue.first) ) { int action = WM_HANDLER_CONTINUE; if((G.f & G_DEBUG) && event && !ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE)) printf("pass on evt %d val %d\n", event->type, event->val); - + wm_eventemulation(event); CTX_wm_window_set(C, win); - + /* we let modal handlers get active area/region, also wm_paintcursor_test needs it */ CTX_wm_area_set(C, area_event_inside(C, event->x, event->y)); CTX_wm_region_set(C, region_event_inside(C, event->x, event->y)); - + /* MVC demands to not draw in event handlers... but we need to leave it for ogl selecting etc */ wm_window_make_drawable(C, win); - + /* first we do priority handlers, modal + some limited keymaps */ action |= wm_handlers_do(C, event, &win->modalhandlers); - + /* fileread case */ if(CTX_wm_window(C)==NULL) return; - + /* check dragging, creates new event or frees, adds draw tag */ wm_event_drag_test(wm, win, event); - + /* builtin tweak, if action is break it removes tweak */ wm_tweakevent_test(C, event, action); @@ -1647,7 +1641,7 @@ void wm_event_do_handlers(bContext *C) ScrArea *sa; ARegion *ar; int doit= 0; - + /* XXX to solve, here screen handlers? */ if(event->type==MOUSEMOVE) { /* state variables in screen, cursors */ @@ -1664,18 +1658,18 @@ void wm_event_do_handlers(bContext *C) for(ar=sa->regionbase.first; ar; ar= ar->next) { if(wm_event_inside_i(event, &ar->winrct)) { CTX_wm_region_set(C, ar); - + /* does polls for drop regions and checks uibuts */ /* need to be here to make sure region context is true */ if(ELEM(event->type, MOUSEMOVE, EVT_DROP)) { wm_region_mouse_co(C, event); wm_drags_check_ops(C, event); } - + action |= wm_handlers_do(C, event, &ar->handlers); - + doit |= (BLI_in_rcti(&ar->winrct, event->x, event->y)); - + if(action & WM_HANDLER_BREAK) break; } @@ -1692,7 +1686,7 @@ void wm_event_do_handlers(bContext *C) /* NOTE: do not escape on WM_HANDLER_BREAK, mousemove needs handled for previous area */ } } - + if((action & WM_HANDLER_BREAK) == 0) { /* also some non-modal handlers need active area/region */ CTX_wm_area_set(C, area_event_inside(C, event->x, event->y)); @@ -1712,7 +1706,7 @@ void wm_event_do_handlers(bContext *C) win->eventstate->prevy= event->y; } } - + /* store last event for this window */ /* mousemove and timer events don't overwrite last type */ if (event->type != MOUSEMOVE && !ISTIMER(event->type)) { @@ -1747,9 +1741,9 @@ void wm_event_do_handlers(bContext *C) /* unlink and free here, blender-quit then frees all */ BLI_remlink(&win->queue, event); wm_event_free(event); - + } - + /* only add mousemove when queue was read entirely */ if(win->addmousemove && win->eventstate) { wmEvent event= *(win->eventstate); @@ -1759,7 +1753,7 @@ void wm_event_do_handlers(bContext *C) wm_event_add(win, &event); win->addmousemove= 0; } - + CTX_wm_window_set(C, NULL); } } @@ -1770,10 +1764,10 @@ void WM_event_fileselect_event(bContext *C, void *ophandle, int eventval) { /* add to all windows! */ wmWindow *win; - + for(win= CTX_wm_manager(C)->windows.first; win; win= win->next) { wmEvent event= *win->eventstate; - + event.type= EVT_FILESELECT; event.val= eventval; event.customdata= ophandle; // only as void pointer type check @@ -1795,15 +1789,15 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op) wmEventHandler *handler= MEM_callocN(sizeof(wmEventHandler), "fileselect handler"); wmWindow *win= CTX_wm_window(C); int full= 1; // XXX preset? - + handler->type= WM_HANDLER_FILESELECT; handler->op= op; handler->op_area= CTX_wm_area(C); handler->op_region= CTX_wm_region(C); handler->filescreen= CTX_wm_screen(C); - + BLI_addhead(&win->modalhandlers, handler); - + WM_event_fileselect_event(C, op, full?EVT_FILESELECT_FULL_OPEN:EVT_FILESELECT_OPEN); } @@ -1817,7 +1811,7 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op) { wmEventHandler *handler= MEM_callocN(sizeof(wmEventHandler), "event modal handler"); wmWindow *win= CTX_wm_window(C); - + /* operator was part of macro */ if(op->opm) { /* give the mother macro to the handler */ @@ -1827,10 +1821,10 @@ wmEventHandler *WM_event_add_modal_handler(bContext *C, wmOperator *op) } else handler->op= op; - + handler->op_area= CTX_wm_area(C); /* means frozen screen context for modal handlers! */ handler->op_region= CTX_wm_region(C); - + BLI_addhead(&win->modalhandlers, handler); return handler; @@ -1849,7 +1843,7 @@ wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap for(handler= handlers->first; handler; handler= handler->next) if(handler->keymap==keymap) return handler; - + handler= MEM_callocN(sizeof(wmEventHandler), "event keymap handler"); BLI_addtail(handlers, handler); handler->keymap= keymap; @@ -1861,20 +1855,20 @@ wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap wmEventHandler *WM_event_add_keymap_handler_priority(ListBase *handlers, wmKeyMap *keymap, int priority) { wmEventHandler *handler; - + WM_event_remove_keymap_handler(handlers, keymap); - + handler= MEM_callocN(sizeof(wmEventHandler), "event keymap handler"); BLI_addhead(handlers, handler); handler->keymap= keymap; - + return handler; } wmEventHandler *WM_event_add_keymap_handler_bb(ListBase *handlers, wmKeyMap *keymap, rcti *bblocal, rcti *bbwin) { wmEventHandler *handler= WM_event_add_keymap_handler(handlers, keymap); - + if(handler) { handler->bblocal= bblocal; handler->bbwin= bbwin; @@ -1885,7 +1879,7 @@ wmEventHandler *WM_event_add_keymap_handler_bb(ListBase *handlers, wmKeyMap *key void WM_event_remove_keymap_handler(ListBase *handlers, wmKeyMap *keymap) { wmEventHandler *handler; - + for(handler= handlers->first; handler; handler= handler->next) { if(handler->keymap==keymap) { BLI_remlink(handlers, handler); @@ -1904,16 +1898,16 @@ wmEventHandler *WM_event_add_ui_handler(const bContext *C, ListBase *handlers, w handler->ui_area= (C)? CTX_wm_area(C): NULL; handler->ui_region= (C)? CTX_wm_region(C): NULL; handler->ui_menu= (C)? CTX_wm_menu(C): NULL; - + BLI_addhead(handlers, handler); - + return handler; } void WM_event_remove_ui_handler(ListBase *handlers, wmUIHandlerFunc func, wmUIHandlerRemoveFunc remove, void *userdata) { wmEventHandler *handler; - + for(handler= handlers->first; handler; handler= handler->next) { if(handler->ui_handle == func && handler->ui_remove == remove && handler->ui_userdata == userdata) { BLI_remlink(handlers, handler); @@ -1931,13 +1925,13 @@ wmEventHandler *WM_event_add_dropbox_handler(ListBase *handlers, ListBase *dropb for(handler= handlers->first; handler; handler= handler->next) if(handler->dropboxes==dropboxes) return handler; - + handler= MEM_callocN(sizeof(wmEventHandler), "dropbox handler"); - + /* dropbox stored static, no free or copy */ handler->dropboxes= dropboxes; BLI_addhead(handlers, handler); - + return handler; } @@ -1966,7 +1960,7 @@ void WM_event_remove_handler(ListBase *handlers, wmEventHandler *handler) void WM_event_add_mousemove(bContext *C) { wmWindow *window= CTX_wm_window(C); - + window->addmousemove= 1; } @@ -1976,7 +1970,7 @@ int WM_modal_tweak_exit(wmEvent *evt, int tweak_event) /* user preset or keymap? dunno... */ // XXX WTH is this? int tweak_modal= (U.flag & USER_RELEASECONFIRM)==0; - + switch(tweak_event) { case EVT_TWEAK_L: case EVT_TWEAK_M: @@ -2010,7 +2004,7 @@ static int convert_key(GHOST_TKey key) case GHOST_kKeyLinefeed: return LINEFEEDKEY; case GHOST_kKeyClear: return 0; case GHOST_kKeyEnter: return RETKEY; - + case GHOST_kKeyEsc: return ESCKEY; case GHOST_kKeySpace: return SPACEKEY; case GHOST_kKeyQuote: return QUOTEKEY; @@ -2018,15 +2012,15 @@ static int convert_key(GHOST_TKey key) case GHOST_kKeyMinus: return MINUSKEY; case GHOST_kKeyPeriod: return PERIODKEY; case GHOST_kKeySlash: return SLASHKEY; - + case GHOST_kKeySemicolon: return SEMICOLONKEY; case GHOST_kKeyEqual: return EQUALKEY; - + case GHOST_kKeyLeftBracket: return LEFTBRACKETKEY; case GHOST_kKeyRightBracket: return RIGHTBRACKETKEY; case GHOST_kKeyBackslash: return BACKSLASHKEY; case GHOST_kKeyAccentGrave: return ACCENTGRAVEKEY; - + case GHOST_kKeyLeftShift: return LEFTSHIFTKEY; case GHOST_kKeyRightShift: return RIGHTSHIFTKEY; case GHOST_kKeyLeftControl: return LEFTCTRLKEY; @@ -2034,93 +2028,135 @@ static int convert_key(GHOST_TKey key) case GHOST_kKeyCommand: return COMMANDKEY; case GHOST_kKeyLeftAlt: return LEFTALTKEY; case GHOST_kKeyRightAlt: return RIGHTALTKEY; - + case GHOST_kKeyCapsLock: return CAPSLOCKKEY; case GHOST_kKeyNumLock: return 0; case GHOST_kKeyScrollLock: return 0; - + case GHOST_kKeyLeftArrow: return LEFTARROWKEY; case GHOST_kKeyRightArrow: return RIGHTARROWKEY; case GHOST_kKeyUpArrow: return UPARROWKEY; case GHOST_kKeyDownArrow: return DOWNARROWKEY; - + case GHOST_kKeyPrintScreen: return 0; case GHOST_kKeyPause: return PAUSEKEY; - + case GHOST_kKeyInsert: return INSERTKEY; case GHOST_kKeyDelete: return DELKEY; case GHOST_kKeyHome: return HOMEKEY; case GHOST_kKeyEnd: return ENDKEY; case GHOST_kKeyUpPage: return PAGEUPKEY; case GHOST_kKeyDownPage: return PAGEDOWNKEY; - + case GHOST_kKeyNumpadPeriod: return PADPERIOD; case GHOST_kKeyNumpadEnter: return PADENTER; case GHOST_kKeyNumpadPlus: return PADPLUSKEY; case GHOST_kKeyNumpadMinus: return PADMINUS; case GHOST_kKeyNumpadAsterisk: return PADASTERKEY; case GHOST_kKeyNumpadSlash: return PADSLASHKEY; - + case GHOST_kKeyGrLess: return GRLESSKEY; - + default: return UNKNOWNKEY; /* GHOST_kKeyUnknown */ } } } +#if 0 /* adds customdata to event */ static void update_tablet_data(wmWindow *win, wmEvent *event) { const GHOST_TabletData *td= GHOST_GetTabletData(win->ghostwin); - + /* if there's tablet data from an active tablet device then add it */ if ((td != NULL) && td->Active != GHOST_kTabletModeNone) { struct wmTabletData *wmtab= MEM_mallocN(sizeof(wmTabletData), "customdata tablet"); - + wmtab->Active = (int)td->Active; wmtab->Pressure = td->Pressure; wmtab->Xtilt = td->Xtilt; wmtab->Ytilt = td->Ytilt; - + event->custom= EVT_DATA_TABLET; event->customdata= wmtab; event->customdatafree= 1; } } +#endif + +/* adds customdata to event */ +static void attach_tablet_data(wmEvent* event, const GHOST_TabletData* ghost) +{ + if (ghost->Active != GHOST_kTabletModeNone) + { + wmTabletData* data = MEM_mallocN(sizeof(wmTabletData), "customdata tablet"); + + data->Active = ghost->Active; + data->Pressure = ghost->Pressure; + data->Xtilt = ghost->Xtilt; + data->Ytilt = ghost->Ytilt; + + event->custom = EVT_DATA_TABLET; + event->customdata = data; + event->customdatafree = 1; + + printf("+ pressure = %.2f tilt = %.2f %2f\n", data->Pressure, data->Xtilt, data->Ytilt); + } +} + +/* adds customdata to event */ +static void attach_ndof_data(wmEvent* event, const GHOST_TEventNDOFMotionData* ghost) +{ + wmNDOFMotionData* data = MEM_mallocN(sizeof(wmNDOFMotionData), "customdata NDOF"); + + data->tx = ghost->tx; + data->ty = ghost->ty; + data->tz = ghost->tz; + + data->rx = ghost->rx; + data->ry = ghost->ry; + data->rz = ghost->rz; + + data->dt = ghost->dt; + + event->custom = EVT_DATA_NDOF_MOTION; + event->customdata = data; + event->customdatafree = 1; +} /* imperfect but probably usable... draw/enable drags to other windows */ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *evt) { short mx= evt->x, my= evt->y; - + if(wm->windows.first== wm->windows.last) return NULL; - + /* top window bar... */ if(mx<0 || my<0 || mx>win->sizex || my>win->sizey+30) { wmWindow *owin; wmEventHandler *handler; - + /* let's skip windows having modal handlers now */ /* potential XXX ugly... I wouldn't have added a modalhandlers list (introduced in rev 23331, ton) */ for(handler= win->modalhandlers.first; handler; handler= handler->next) if(handler->ui_handle || handler->op) return NULL; - + /* to desktop space */ mx+= win->posx; my+= win->posy; - + /* check other windows to see if it has mouse inside */ for(owin= wm->windows.first; owin; owin= owin->next) { - + if(owin!=win) { if(mx-owin->posx >= 0 && my-owin->posy >= 0 && mx-owin->posx <= owin->sizex && my-owin->posy <= owin->sizey) { evt->x= mx-owin->posx; evt->y= my-owin->posy; - + return owin; } } @@ -2130,34 +2166,34 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi } /* windows store own event queues, no bContext here */ -/* time is in 1000s of seconds, from ghost */ +/* time is in 1000s of seconds (or milliseconds?), from ghost */ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int time, void *customdata) { wmWindow *owin; wmEvent event, *evt= win->eventstate; - + /* initialize and copy state (only mouse x y and modifiers) */ event= *evt; - + switch (type) { /* mouse move */ case GHOST_kEventCursorMove: { if(win->active) { GHOST_TEventCursorData *cd= customdata; wmEvent *lastevent= win->queue.last; - + #if defined(__APPLE__) && defined(GHOST_COCOA) //Cocoa already uses coordinates with y=0 at bottom, and returns inwindow coordinates on mouse moved event evt->x= cd->x; evt->y= cd->y; #else int cx, cy; - + GHOST_ScreenToClient(win->ghostwin, cd->x, cd->y, &cx, &cy); evt->x= cx; evt->y= (win->sizey-1) - cy; #endif - + event.x= evt->x; event.y= evt->y; @@ -2169,23 +2205,23 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int t if(lastevent && lastevent->type == MOUSEMOVE) lastevent->type = INBETWEEN_MOUSEMOVE; - update_tablet_data(win, &event); + attach_tablet_data(&event, &(cd->tablet)); + // update_tablet_data(win, &event); wm_event_add(win, &event); - + /* also add to other window if event is there, this makes overdraws disappear nicely */ /* it remaps mousecoord to other window in event */ owin= wm_event_cursor_other_windows(wm, win, &event); if(owin) { wmEvent oevent= *(owin->eventstate); - + oevent.x=owin->eventstate->x= event.x; oevent.y=owin->eventstate->y= event.y; oevent.type= MOUSEMOVE; - - update_tablet_data(owin, &oevent); + + // update_tablet_data(owin, &oevent); wm_event_add(owin, &oevent); } - } break; } @@ -2218,8 +2254,9 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int t // Use prevx/prevy so we can calculate the delta later event.prevx= event.x - pd->deltaX; event.prevy= event.y - pd->deltaY; - - update_tablet_data(win, &event); + + // [mce] tablet never sends trackpad events. + // update_tablet_data(win, &event); wm_event_add(win, &event); break; } @@ -2239,25 +2276,27 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int t event.type= BUTTON5MOUSE; else event.type= MIDDLEMOUSE; - + /* add to other window if event is there (not to both!) */ owin= wm_event_cursor_other_windows(wm, win, &event); if(owin) { wmEvent oevent= *(owin->eventstate); - + oevent.x= event.x; oevent.y= event.y; oevent.type= event.type; oevent.val= event.val; - - update_tablet_data(owin, &oevent); + + attach_tablet_data(&oevent, &(bd->tablet)); + // update_tablet_data(owin, &oevent); wm_event_add(owin, &oevent); } else { - update_tablet_data(win, &event); + attach_tablet_data(&event, &(bd->tablet)); + // update_tablet_data(win, &event); wm_event_add(win, &event); } - + break; } /* keyboard */ @@ -2267,11 +2306,11 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int t event.type= convert_key(kd->key); event.ascii= kd->ascii; event.val= (type==GHOST_kEventKeyDown)?KM_PRESS:KM_RELEASE; - + /* exclude arrow keys, esc, etc from text input */ if(type==GHOST_kEventKeyUp || (event.ascii<32 && event.ascii>0)) event.ascii= '\0'; - + /* modifiers */ if (event.type==LEFTSHIFTKEY || event.type==RIGHTSHIFTKEY) { event.shift= evt->shift= (event.val==KM_PRESS); @@ -2306,29 +2345,30 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int t key we don't want the key modifier */ if(event.keymodifier == event.type) event.keymodifier= 0; - + /* if test_break set, it catches this. XXX Keep global for now? */ if(event.type==ESCKEY) G.afbreek= 1; - + wm_event_add(win, &event); - + break; } - + case GHOST_kEventWheel: { GHOST_TEventWheelData* wheelData = customdata; - + if (wheelData->z > 0) event.type= WHEELUPMOUSE; else event.type= WHEELDOWNMOUSE; - + event.val= KM_PRESS; wm_event_add(win, &event); - + break; } + case GHOST_kEventTimer: { event.type= TIMER; event.custom= EVT_DATA_TIMER; @@ -2338,6 +2378,36 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int t break; } + case GHOST_kEventNDOFMotion: { + event.type = NDOF_MOTION; + attach_ndof_data(&event, customdata); + wm_event_add(win, &event); + + break; + } + + case GHOST_kEventNDOFButton: { + GHOST_TEventNDOFButtonData* e = customdata; + + event.type = NDOF_BUTTON_NONE + e->button; + + switch (e->action) { + case GHOST_kPress: + event.val = KM_PRESS; + break; + case GHOST_kRelease: + event.val = KM_RELEASE; + break; + } + + event.custom = 0; + event.customdata = NULL; + + wm_event_add(win, &event); + + break; + } + case GHOST_kEventUnknown: case GHOST_kNumEventTypes: break; @@ -2347,8 +2417,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int t wm_event_add(win, &event); break; - } - } } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index e4bb5b797d3..d9dad900632 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -796,8 +796,6 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) } } - - break; } @@ -805,7 +803,6 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) wm_event_add_ghostevent(wm, win, type, time, data); break; } - } return 1; } diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index 7228a6dcd93..bbf9ed9af6a 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -83,4 +83,3 @@ extern int circle_select_size; #endif #endif /* WM_H */ - diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 6cb3971bd21..9db84bf7795 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -36,42 +36,66 @@ #define WM_EVENT_TYPES_H /* customdata type */ -#define EVT_DATA_TABLET 1 -#define EVT_DATA_GESTURE 2 -#define EVT_DATA_TIMER 3 -#define EVT_DATA_LISTBASE 4 +#define EVT_DATA_TABLET 1 +#define EVT_DATA_GESTURE 2 +#define EVT_DATA_TIMER 3 +#define EVT_DATA_LISTBASE 4 +#define EVT_DATA_NDOF_MOTION 5 /* tablet active, matches GHOST_TTabletMode */ +/* [mce] also matches my own TabletTool.type */ #define EVT_TABLET_NONE 0 #define EVT_TABLET_STYLUS 1 #define EVT_TABLET_ERASER 2 -#define MOUSEX 0x004 -#define MOUSEY 0x005 +/* [mce] what are these for? */ +#define MOUSEX 0x004 +#define MOUSEY 0x005 /* MOUSE : 0x00x */ -#define LEFTMOUSE 0x001 -#define MIDDLEMOUSE 0x002 -#define RIGHTMOUSE 0x003 -#define MOUSEMOVE 0x004 +#define LEFTMOUSE 0x001 +#define MIDDLEMOUSE 0x002 +#define RIGHTMOUSE 0x003 +#define MOUSEMOVE 0x004 /* only use if you want user option switch possible */ #define ACTIONMOUSE 0x005 #define SELECTMOUSE 0x006 /* Extra mouse buttons */ -#define BUTTON4MOUSE 0x007 +#define BUTTON4MOUSE 0x007 #define BUTTON5MOUSE 0x008 /* Extra trackpad gestures */ #define MOUSEPAN 0x00e #define MOUSEZOOM 0x00f #define MOUSEROTATE 0x010 /* defaults from ghost */ -#define WHEELUPMOUSE 0x00a +#define WHEELUPMOUSE 0x00a #define WHEELDOWNMOUSE 0x00b /* mapped with userdef */ #define WHEELINMOUSE 0x00c #define WHEELOUTMOUSE 0x00d #define INBETWEEN_MOUSEMOVE 0x011 +/* NDOF (from SpaceNavigator & friends) */ +#define NDOF_MOTION 0x12 +enum { + NDOF_BUTTON_NONE = NDOF_MOTION, /* never sent, used during translation */ + NDOF_BUTTON1, + NDOF_BUTTON2/*, + NDOF_BUTTON3, + NDOF_BUTTON4, + NDOF_BUTTON5, + NDOF_BUTTON6, + NDOF_BUTTON7, + NDOF_BUTTON8, + NDOF_BUTTON9, + NDOF_BUTTON10, + NDOF_BUTTON11, + NDOF_BUTTON12, + NDOF_BUTTON13, + NDOF_BUTTON14, + NDOF_BUTTON15, + NDOF_BUTTON16*/ + }; /* SYSTEM : 0x01xx */ #define INPUTCHANGE 0x0103 /* input connected or disconnected */ @@ -126,9 +150,9 @@ #define CAPSLOCKKEY 211 #define LEFTCTRLKEY 212 -#define LEFTALTKEY 213 -#define RIGHTALTKEY 214 -#define RIGHTCTRLKEY 215 +#define LEFTALTKEY 213 +#define RIGHTALTKEY 214 +#define RIGHTCTRLKEY 215 #define RIGHTSHIFTKEY 216 #define LEFTSHIFTKEY 217 @@ -169,8 +193,8 @@ #define PADPERIOD 199 -#define PADSLASHKEY 161 -#define PADASTERKEY 160 +#define PADSLASHKEY 161 +#define PADASTERKEY 160 #define PADMINUS 162 #define PADENTER 163 @@ -299,4 +323,3 @@ #endif /* WM_EVENT_TYPES_H */ -