-- cgit v1.2.3 From 707220b150d57ce89dae8c0413b5d5f1fc580dd2 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 14 Jun 2010 02:03:01 +0000 Subject: gpencil simplified filtering, unbiased smoothing, and pen eraser that works --- source/blender/editors/gpencil/gpencil_paint.c | 89 ++++++++++++++------------ 1 file changed, 49 insertions(+), 40 deletions(-) diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index e06722c1af1..544d87333d8 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -184,25 +184,22 @@ static void gp_get_3d_reference (tGPsdata *p, float *vec) /* check if the current mouse position is suitable for adding a new point */ static short gp_stroke_filtermval (tGPsdata *p, int mval[2], int pmval[2]) { - int dx= abs(mval[0] - pmval[0]); - int dy= abs(mval[1] - pmval[1]); - /* if buffer is empty, just let this go through (i.e. so that dots will work) */ if (p->gpd->sbuffer_size == 0) return 1; + else { + /* check if the distance since the last point is significant enough + no need for abs() or sqrt(), and don't bother checking Manhattan distance (ok?) */ + + int dx= mval[0] - pmval[0]; + int dy= mval[1] - pmval[1]; - /* check if mouse moved at least certain distance on both axes (best case) */ - else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX)) - return 1; - - /* check if the distance since the last point is significant enough */ - // future optimisation: sqrt here may be too slow? - else if (sqrt(dx*dx + dy*dy) > MIN_EUCLIDEAN_PX) - return 1; - - /* mouse 'didn't move' */ - else - return 0; + if ((dx*dx + dy*dy) > (MIN_EUCLIDEAN_PX * MIN_EUCLIDEAN_PX)) + return 1; + } + + /* pencil 'didn't move' if we make it this far */ + return 0; } /* convert screen-coordinates to buffer-coordinates */ @@ -349,30 +346,44 @@ static short gp_stroke_addpoint (tGPsdata *p, int mval[2], float pressure) /* smooth a stroke (in buffer) before storing it */ static void gp_stroke_smooth (tGPsdata *p) { - bGPdata *gpd= p->gpd; - int i=0, cmx=gpd->sbuffer_size; - /* only smooth if smoothing is enabled, and we're not doing a straight line */ if (!(U.gp_settings & GP_PAINT_DOSMOOTH) || (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)) return; - - /* don't try if less than 2 points in buffer */ - if ((cmx <= 2) || (gpd->sbuffer == NULL)) - return; - - /* apply weighting-average (note doing this along path sequentially does introduce slight error) */ - for (i=0; i < gpd->sbuffer_size; i++) { - tGPspoint *pc= (((tGPspoint *)gpd->sbuffer) + i); - tGPspoint *pb= (i-1 > 0)?(pc-1):(pc); - tGPspoint *pa= (i-2 > 0)?(pc-2):(pb); - tGPspoint *pd= (i+1 < cmx)?(pc+1):(pc); - tGPspoint *pe= (i+2 < cmx)?(pc+2):(pd); + else { + bGPdata *gpd= p->gpd; + int num_points=gpd->sbuffer_size; - pc->x= (short)(0.1*pa->x + 0.2*pb->x + 0.4*pc->x + 0.2*pd->x + 0.1*pe->x); - pc->y= (short)(0.1*pa->y + 0.2*pb->y + 0.4*pc->y + 0.2*pd->y + 0.1*pe->y); + /* don't try if less than 5 points in buffer */ + if ((num_points <= 5) || (gpd->sbuffer == NULL)) + return; + else { + /* apply weighting-average (avoiding errors from sequential processing) */ + + tGPspoint *begin = (tGPspoint*)gpd->sbuffer + 2; + tGPspoint *end = (tGPspoint*)gpd->sbuffer + num_points - 2; + + tGPspoint orig_a = *(begin - 2); + tGPspoint orig_b = *(begin - 1); + + tGPspoint *c = begin; + tGPspoint *d = begin + 1; + tGPspoint *e = begin + 2; + + + for (; c < end; ++c, ++d, ++e) { + tGPspoint orig_c = *c; + + c->x= (short)(0.1*orig_a.x + 0.2*orig_b.x + 0.4*orig_c.x + 0.2*d->x + 0.1*e->x); + c->y= (short)(0.1*orig_a.y + 0.2*orig_b.y + 0.4*orig_c.y + 0.2*d->y + 0.1*e->y); + + orig_a = orig_b; + orig_b = orig_c; + } + } } } + /* simplify a stroke (in buffer) before storing it * - applies a reverse Chaikin filter * - code adapted from etch-a-ton branch (editarmature_sketch.c) @@ -385,12 +396,12 @@ static void gp_stroke_simplify (tGPsdata *p) short flag= gpd->sbuffer_sflag; short i, j; - /* only simplify if simlification is enabled, and we're not doing a straight line */ + /* only simplify if simplification is enabled, and we're not doing a straight line */ if (!(U.gp_settings & GP_PAINT_DOSIMPLIFY) || (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT)) return; /* don't simplify if less than 4 points in buffer */ - if ((num_points <= 2) || (old_points == NULL)) + if ((num_points < 4) || (old_points == NULL)) return; /* clear buffer (but don't free mem yet) so that we can write to it @@ -1283,8 +1294,10 @@ static void gpencil_draw_apply_event (bContext *C, wmOperator *op, wmEvent *even 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; } else p->pressure= 1.0f; @@ -1515,8 +1528,6 @@ static EnumPropertyItem prop_gpencil_drawmodes[] = { void GPENCIL_OT_draw (wmOperatorType *ot) { - PropertyRNA *prop; - /* identifiers */ ot->name= "Grease Pencil Draw"; ot->idname= "GPENCIL_OT_draw"; @@ -1533,8 +1544,6 @@ void GPENCIL_OT_draw (wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; /* settings for drawing */ - prop= RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to intepret mouse movements."); - RNA_def_property_flag(prop, PROP_HIDDEN); - + RNA_def_enum(ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to intepret mouse movements."); RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); } -- cgit v1.2.3 From da314f51bfab03252a7c530eeb3bbd5585327a25 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 19 Jun 2010 10:35:01 +0000 Subject: fixed tablet mouse spasm bug and refactored event handling --- intern/ghost/intern/GHOST_SystemCocoa.h | 20 +- intern/ghost/intern/GHOST_SystemCocoa.mm | 397 +++++++++++++++---------------- 2 files changed, 215 insertions(+), 202 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index b97c36f04a8..d05e19ba286 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -251,13 +251,27 @@ protected: virtual GHOST_TSuccess init(); /** - * Handles a tablet event. + * Handles a tablet pen event. * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) - * @param eventType The type of the event. It needs to be passed separately as it can be either directly in the event type, or as a subtype if combined with a mouse button event * @return Indication whether the event was handled. */ - GHOST_TSuccess handleTabletEvent(void *eventPtr, short eventType); + GHOST_TSuccess handleTabletEvent(void *eventPtr); + /** + * Handles a tablet proximity event. Sets pen or mouse ID for later events. + * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * @return Indication whether the event was handled. + */ + GHOST_TSuccess handleTabletProximity(void *eventPtr); + + /** Tablet Mouse and Pen IDs, used to correlate events with the tool that caused them. */ + int m_tablet_mouse_id; + int m_tablet_pen_id; + + static const int TOOL_ID_NONE = -1; + + GHOST_TTabletMode m_tablet_pen_mode; + /** * Handles a mouse event. * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 2cec24714be..3edd1bd0b94 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -31,6 +31,7 @@ /*For the currently not ported to Cocoa keyboard layout functions (64bit & 10.6 compatible)*/ #include +//#include #include #include @@ -553,6 +554,9 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() m_isGestureInProgress = false; m_cursorDelta_x=0; m_cursorDelta_y=0; + m_tablet_mouse_id = TOOL_ID_NONE; + m_tablet_pen_id = TOOL_ID_NONE; + m_tablet_pen_mode = GHOST_kTabletModeNone; m_outsideLoopEventProcessed = false; m_needDelayedApplicationBecomeActiveEventProcessing = false; m_displayManager = new GHOST_DisplayManagerCocoa (); @@ -575,10 +579,9 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() sysctl( mib, 2, rstring, &len, NULL, 0 ); //Hack on MacBook revision, as multitouch avail. function missing - if (strstr(rstring,"MacBookAir") || - (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9'))) - m_hasMultiTouchTrackpad = true; - else m_hasMultiTouchTrackpad = false; + m_hasMultiTouchTrackpad = + (strstr(rstring,"MacBookAir") || + (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9'))); free( rstring ); rstring = NULL; @@ -593,7 +596,6 @@ GHOST_SystemCocoa::~GHOST_SystemCocoa() GHOST_TSuccess GHOST_SystemCocoa::init() { - GHOST_TSuccess success = GHOST_System::init(); if (success) { //ProcessSerialNumber psn; @@ -879,104 +881,116 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) { bool anyProcessed = false; NSEvent *event; - - // SetMouseCoalescingEnabled(false, NULL); + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + //TODO : implement timer ?? - /*do { - GHOST_TimerManager* timerMgr = getTimerManager(); + do { + event = [NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate distantPast] + inMode:NSDefaultRunLoopMode + dequeue:YES]; + if (event==nil) + break; - if (waitForEvent) { - GHOST_TUns64 next = timerMgr->nextFireTime(); - double timeOut; - - if (next == GHOST_kFireTimeNever) { - timeOut = kEventDurationForever; - } else { - timeOut = (double)(next - getMilliSeconds())/1000.0; - if (timeOut < 0.0) - timeOut = 0.0; - } - - ::ReceiveNextEvent(0, NULL, timeOut, false, &event); - } - - if (timerMgr->fireTimers(getMilliSeconds())) { - anyProcessed = true; - }*/ + anyProcessed = true; - do { - NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; - event = [NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate distantPast] - inMode:NSDefaultRunLoopMode - dequeue:YES]; - if (event==nil) { - [pool drain]; + switch ([event type]) { + case NSKeyDown: + case NSKeyUp: + case NSFlagsChanged: + handleKeyEvent(event); + // resend to ensure Mac-wide events are handled + [NSApp sendEvent:event]; break; - } - - anyProcessed = true; - - switch ([event type]) { - case NSKeyDown: - case NSKeyUp: - case NSFlagsChanged: - handleKeyEvent(event); - - /* Support system-wide keyboard shortcuts, like Exposé, ...) =>included in always NSApp sendEvent */ - /* if (([event modifierFlags] & NSCommandKeyMask) || [event type] == NSFlagsChanged) { - [NSApp sendEvent:event]; - }*/ - break; - - case NSLeftMouseDown: - case NSLeftMouseUp: - case NSRightMouseDown: - case NSRightMouseUp: - case NSMouseMoved: - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSScrollWheel: - case NSOtherMouseDown: - case NSOtherMouseUp: - case NSOtherMouseDragged: - case NSEventTypeMagnify: - case NSEventTypeRotate: - case NSEventTypeBeginGesture: - case NSEventTypeEndGesture: - handleMouseEvent(event); - break; - - case NSTabletPoint: - case NSTabletProximity: - handleTabletEvent(event,[event type]); - break; - - /* Trackpad features, fired only from OS X 10.5.2 - case NSEventTypeGesture: - case NSEventTypeSwipe: - break; */ - - /*Unused events - NSMouseEntered = 8, - NSMouseExited = 9, - NSAppKitDefined = 13, - NSSystemDefined = 14, - NSApplicationDefined = 15, - NSPeriodic = 16, - NSCursorUpdate = 17,*/ - - default: - break; - } - //Resend event to NSApp to ensure Mac wide events are handled - [NSApp sendEvent:event]; - [pool drain]; - } while (event!= nil); - //} while (waitForEvent && !anyProcessed); Needed only for timer implementation + + case NSLeftMouseDown: + case NSLeftMouseUp: + case NSLeftMouseDragged: + + case NSRightMouseDown: + case NSRightMouseUp: + case NSRightMouseDragged: + + case NSOtherMouseDown: + case NSOtherMouseUp: + case NSOtherMouseDragged: + + case NSMouseMoved: + switch ([event subtype]) + { + case NSMouseEventSubtype: + handleMouseEvent(event); + break; + case NSTabletPointEventSubtype: + handleTabletEvent(event); + break; + case NSTabletProximityEventSubtype: + // I think only LMB down/up sends this + handleTabletProximity(event); + break; + + // Mac OS 10.6 introduces a Touch subtype + // that we ignore for now. + } + break; + + case NSScrollWheel: + handleMouseEvent(event); + break; + + case NSTabletProximity: + handleTabletProximity(event); + break; + + case NSTabletPoint: + if ([event deviceID] == m_tablet_pen_id) + handleTabletEvent(event); + else { + // Treat tablet mouse like any other mouse. + // TODO: teach Windows and Linux the same trick + + // It continues to send events even when still, to mimic the pen's + // ability to vary pressure without moving. Since the mouse is + // unable to vary its pressure, filter them out as noise! + + bool didMove = [event deltaX] != 0 and [event deltaY] != 0; + if (didMove) + handleMouseEvent(event); + // NSLeftMouseDown gets sent for the initial point, so this is safe. + } + break; + + case NSEventTypeMagnify: + case NSEventTypeRotate: + case NSEventTypeBeginGesture: + case NSEventTypeEndGesture: + handleMouseEvent(event); + // break out into handleGestureEvent? + break; + + /* Trackpad features, fired only from OS X 10.5.2 + case NSEventTypeGesture: + case NSEventTypeSwipe: + break; */ + + default: + break; + /* Unused events: + NSMouseEntered = 8, + NSMouseExited = 9, + NSAppKitDefined = 13, + NSSystemDefined = 14, + NSApplicationDefined = 15, + NSPeriodic = 16, + NSCursorUpdate = 17,*/ + } + } while (event != nil); + + [pool drain]; - if (m_needDelayedApplicationBecomeActiveEventProcessing) handleApplicationBecomeActiveEvent(); + if (m_needDelayedApplicationBecomeActiveEventProcessing) + handleApplicationBecomeActiveEvent(); if (m_outsideLoopEventProcessed) { m_outsideLoopEventProcessed = false; @@ -986,6 +1000,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) return anyProcessed; } + //Note: called from NSApplication delegate GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() { @@ -1360,57 +1375,81 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr) else return NO; } -GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventType) +GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) { NSEvent *event = (NSEvent *)eventPtr; - GHOST_IWindow* window; - - window = m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); + GHOST_WindowCocoa* window = (GHOST_WindowCocoa*) + m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); + if (!window) { //printf("\nW failure for event 0x%x",[event type]); return GHOST_kFailure; } - GHOST_TabletData& ct=((GHOST_WindowCocoa*)window)->GetCocoaTabletData(); - - switch (eventType) { - case NSTabletPoint: - ct.Pressure = [event pressure]; - ct.Xtilt = [event tilt].x; - ct.Ytilt = [event tilt].y; + GHOST_TabletData& ct = window->GetCocoaTabletData(); + + GHOST_TTabletMode active_tool; + int* tool_id_ptr; + + switch ([event pointingDeviceType]) + { + case NSPenPointingDevice: + active_tool = GHOST_kTabletModeStylus; + tool_id_ptr = &m_tablet_pen_id; break; - - case NSTabletProximity: - ct.Pressure = 0; - ct.Xtilt = 0; - ct.Ytilt = 0; - if ([event isEnteringProximity]) - { - //pointer is entering tablet area proximity - switch ([event pointingDeviceType]) { - case NSPenPointingDevice: - ct.Active = GHOST_kTabletModeStylus; - break; - case NSEraserPointingDevice: - ct.Active = GHOST_kTabletModeEraser; - break; - case NSCursorPointingDevice: - case NSUnknownPointingDevice: - default: - ct.Active = GHOST_kTabletModeNone; - break; - } - } else { - // pointer is leaving - return to mouse - ct.Active = GHOST_kTabletModeNone; - } + case NSEraserPointingDevice: + active_tool = GHOST_kTabletModeEraser; + tool_id_ptr = &m_tablet_pen_id; break; - - default: - GHOST_ASSERT(FALSE,"GHOST_SystemCocoa::handleTabletEvent : unknown event received"); - return GHOST_kFailure; + case NSCursorPointingDevice: + active_tool = GHOST_kTabletModeNone; + tool_id_ptr = &m_tablet_mouse_id; break; + default: + return GHOST_kFailure; // fail on unknown device + } + + if ([event isEnteringProximity]) { + *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; + + // this is a good place to remember the tool's capabilities + // (later though, after tablet mouse is fixed and coalescing is in place) + } + else { + *tool_id_ptr = TOOL_ID_NONE; + + ct.Active = GHOST_kTabletModeNone; + ct.Pressure = 0; + ct.Xtilt = 0; + ct.Ytilt = 0; + } + + return GHOST_kSuccess; +} + +GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) +{ + NSEvent *event = (NSEvent *)eventPtr; + GHOST_WindowCocoa* window = (GHOST_WindowCocoa*) + m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); + + if (!window) { + //printf("\nW failure for event 0x%x",[event type]); + return GHOST_kFailure; } + + GHOST_TabletData& ct = window->GetCocoaTabletData(); + + ct.Pressure = [event pressure]; + NSPoint tilt = [event tilt]; + ct.Xtilt = tilt.x; + ct.Ytilt = tilt.y; + return GHOST_kSuccess; } @@ -1418,9 +1457,9 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventT GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) { NSEvent *event = (NSEvent *)eventPtr; - GHOST_Window* window; - - window = (GHOST_Window*)m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); + GHOST_Window* window = + (GHOST_Window*)m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); + if (!window) { //printf("\nW failure for event 0x%x",[event type]); return GHOST_kFailure; @@ -1432,54 +1471,14 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) case NSRightMouseDown: case NSOtherMouseDown: pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber]))); - //Handle tablet events combined with mouse events - switch ([event subtype]) { - case NX_SUBTYPE_TABLET_POINT: - handleTabletEvent(eventPtr, NSTabletPoint); - break; - case NX_SUBTYPE_TABLET_PROXIMITY: - handleTabletEvent(eventPtr, NSTabletProximity); - break; - default: - //No tablet event included : do nothing - break; - } break; case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber]))); - //Handle tablet events combined with mouse events - switch ([event subtype]) { - case NX_SUBTYPE_TABLET_POINT: - handleTabletEvent(eventPtr, NSTabletPoint); - break; - case NX_SUBTYPE_TABLET_PROXIMITY: - handleTabletEvent(eventPtr, NSTabletProximity); - break; - default: - //No tablet event included : do nothing - break; - } break; - case NSLeftMouseDragged: - case NSRightMouseDragged: - case NSOtherMouseDragged: - //Handle tablet events combined with mouse events - switch ([event subtype]) { - case NX_SUBTYPE_TABLET_POINT: - handleTabletEvent(eventPtr, NSTabletPoint); - break; - case NX_SUBTYPE_TABLET_PROXIMITY: - handleTabletEvent(eventPtr, NSTabletProximity); - break; - default: - //No tablet event included : do nothing - break; - } - case NSMouseMoved: switch (window->getCursorGrabMode()) { case GHOST_kGrabHide: //Cursor hidden grab operation : no cursor move @@ -1501,6 +1500,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) NSPoint mousePos = [event locationInWindow]; GHOST_TInt32 x_mouse= mousePos.x; GHOST_TInt32 y_mouse= mousePos.y; + GHOST_TInt32 event_dx = [event deltaX]; + GHOST_TInt32 event_dy = -[event deltaY]; //Strange Apple implementation (inverted coordinates for the deltaY) ... GHOST_TInt32 x_accum, y_accum, x_cur, y_cur; GHOST_Rect bounds, windowBounds, correctedBounds; @@ -1508,7 +1509,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) if(window->getCursorGrabBounds(bounds)==GHOST_kFailure) window->getClientBounds(bounds); - //Switch back to Cocoa coordinates orientation (y=0 at botton,the same as blender internal btw!), and to client coordinates + //Switch back to Cocoa coordinates orientation (y=0 at bottom,the same as blender internal btw!), and to client coordinates window->getClientBounds(windowBounds); window->screenToClient(bounds.m_l,bounds.m_b, correctedBounds.m_l, correctedBounds.m_t); window->screenToClient(bounds.m_r, bounds.m_t, correctedBounds.m_r, correctedBounds.m_b); @@ -1517,14 +1518,14 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) //Update accumulation counts window->getCursorGrabAccum(x_accum, y_accum); - x_accum += [event deltaX]-m_cursorDelta_x; - y_accum += -[event deltaY]-m_cursorDelta_y; //Strange Apple implementation (inverted coordinates for the deltaY) ... + x_accum += event_dx - m_cursorDelta_x; + y_accum += event_dy - m_cursorDelta_y; window->setCursorGrabAccum(x_accum, y_accum); //Warp mouse cursor if needed - x_mouse += [event deltaX]-m_cursorDelta_x; - y_mouse += -[event deltaY]-m_cursorDelta_y; + x_mouse += event_dx - m_cursorDelta_x; + y_mouse += event_dy - m_cursorDelta_y; correctedBounds.wrapPoint(x_mouse, y_mouse, 2); //Compensate for mouse moved event taking cursor position set into account @@ -1555,16 +1556,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) case NSScrollWheel: { /* Send trackpad event if inside a trackpad gesture, send wheel event otherwise */ - if (!m_hasMultiTouchTrackpad || !m_isGestureInProgress) { - GHOST_TInt32 delta; - - double deltaF = [event deltaY]; - if (deltaF == 0.0) break; //discard trackpad delta=0 events - - delta = deltaF > 0.0 ? 1 : -1; - pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta)); - } - else { + if (m_hasMultiTouchTrackpad and m_isGestureInProgress) { NSPoint mousePos = [event locationInWindow]; double dx = [event deltaX]; double dy = -[event deltaY]; @@ -1584,22 +1576,29 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventScroll, mousePos.x, mousePos.y, dx, dy)); } + else { + GHOST_TInt32 delta; + + double deltaF = [event deltaY]; + if (deltaF == 0.0) break; //discard trackpad delta=0 events + + delta = deltaF > 0.0 ? 1 : -1; + pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta)); + } } break; case NSEventTypeMagnify: { NSPoint mousePos = [event locationInWindow]; - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, mousePos.x, mousePos.y, - [event magnification]*250.0 + 0.1, 0)); + pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, mousePos.x, mousePos.y, [event magnification]*250.0 + 0.1, 0)); } break; case NSEventTypeRotate: { NSPoint mousePos = [event locationInWindow]; - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, mousePos.x, mousePos.y, - -[event rotation] * 5.0, 0)); + pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, mousePos.x, mousePos.y, -[event rotation] * 5.0, 0)); } case NSEventTypeBeginGesture: m_isGestureInProgress = true; -- cgit v1.2.3 From 185c77989e2692c13b65cea0ca8c58c4dcb51a2e Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 25 Jun 2010 00:09:50 +0000 Subject: hint for mouse/pen input fidelity --- intern/ghost/GHOST_ISystem.h | 10 +++++++++- intern/ghost/intern/GHOST_System.cpp | 7 ++++++- intern/ghost/intern/GHOST_System.h | 8 ++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 8d80c74e140..1760fe30b7f 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -353,7 +353,15 @@ public: */ virtual GHOST_TSuccess getButtonState(GHOST_TButtonMask mask, bool& isDown) const = 0; - + /** Fidelity of mouse and pen input (this definition will probably live somewhere else)*/ + typedef enum { LO_FI, NORMAL_FI, HI_FI } InputFidelity; + + /** + * Requests input at a certain fidelity. Certain tools want very smooth input, others don't care. + * @param hint Desired fidelity of mouse and pen events. + */ + virtual void setInputFidelity(InputFidelity hint) = 0; + /*************************************************************************************** ** Access to clipboard. ***************************************************************************************/ diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index c89534e01c5..3cd3528eeb6 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -48,7 +48,7 @@ GHOST_System::GHOST_System() -: m_displayManager(0), m_timerManager(0), m_windowManager(0), m_eventManager(0), m_ndofManager(0) +: m_displayManager(0), m_timerManager(0), m_windowManager(0), m_eventManager(0), m_ndofManager(0), m_input_fidelity_hint(NORMAL_FI) { } @@ -271,6 +271,11 @@ GHOST_TSuccess GHOST_System::getButtonState(GHOST_TButtonMask mask, bool& isDown return success; } +void GHOST_System::setInputFidelity(InputFidelity hint) +{ + m_input_fidelity_hint = hint; +} + GHOST_TSuccess GHOST_System::init() { m_timerManager = new GHOST_TimerManager (); diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index d6c6a356323..6f570b33079 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -281,6 +281,12 @@ public: * @return Indication of success. */ virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const = 0; + + /** + * Requests input at a certain fidelity. Certain tools want very smooth input, others don't care. + * @param hint Desired fidelity of mouse and pen events. + */ + void setInputFidelity(InputFidelity hint); /** * Returns the selection buffer @@ -354,6 +360,8 @@ protected: /** Settings of the display before the display went fullscreen. */ GHOST_DisplaySetting m_preFullScreenSetting; + + InputFidelity m_input_fidelity_hint; }; inline GHOST_TimerManager* GHOST_System::getTimerManager() const -- cgit v1.2.3 From d5cdfb18f68bd86cdb060c54b7af57f46e67c4aa Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 26 Jun 2010 01:34:49 +0000 Subject: removed unused #include --- intern/ghost/GHOST_Rect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/ghost/GHOST_Rect.h b/intern/ghost/GHOST_Rect.h index e3d056dd467..c72b918d63e 100644 --- a/intern/ghost/GHOST_Rect.h +++ b/intern/ghost/GHOST_Rect.h @@ -228,7 +228,7 @@ inline void GHOST_Rect::unionPoint(GHOST_TInt32 x, GHOST_TInt32 y) if (y < m_t) m_t = y; if (y > m_b) m_b = y; } -#include + inline void GHOST_Rect::wrapPoint(GHOST_TInt32 &x, GHOST_TInt32 &y, GHOST_TInt32 ofs) { GHOST_TInt32 w= getWidth(); -- cgit v1.2.3 From 905fcc7b74f9d38a5449023d372b3d8fe34ee588 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 3 Jul 2010 03:53:06 +0000 Subject: guarding printf calls as MinGW (gcc 4.5) insists --- intern/ghost/intern/GHOST_DropTargetWin32.cpp | 2 ++ intern/ghost/intern/GHOST_WindowWin32.cpp | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp index 6470b406492..432a4f93b4d 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp +++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp @@ -377,7 +377,9 @@ int GHOST_DropTargetWin32::WideCharToANSI(LPCWSTR in, char * &out) out = (char*)::malloc(size); if (!out) { +#ifdef GHOST_DEBUG ::printf("\nmalloc failed!!!"); +#endif return 0; } diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index bbfa84dbae0..945e4c16a39 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -659,7 +659,9 @@ GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextTyp success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure; } else { +#ifdef GHOST_DEBUG printf("Failed to get a context....\n"); +#endif success = GHOST_kFailure; } } @@ -694,7 +696,9 @@ GHOST_TSuccess GHOST_WindowWin32::installDrawingContext(GHOST_TDrawingContextTyp success = ::wglMakeCurrent(m_hDC, m_hGlRc) == TRUE ? GHOST_kSuccess : GHOST_kFailure; } else { +#ifdef GHOST_DEBUG printf("Failed to get a context....\n"); +#endif success = GHOST_kFailure; } @@ -1160,5 +1164,3 @@ static int EnumPixelFormats(HDC hdc) { } return iPixelFormat; } - - -- cgit v1.2.3 From 09f6604241982dfbd852ff3e38ce7ccdf24b43ed Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 3 Jul 2010 06:58:29 +0000 Subject: preparing for NDOF overhaul --- intern/ghost/GHOST_Types.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index f7d0425aec8..4ec8e22a960 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -444,16 +444,24 @@ typedef struct { GHOST_TUns64 delta; } GHOST_TEventNDOFData; +typedef struct { + /** N-degree of freedom device data v3 [GSoC 2010]*/ + + // 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] + + float tx, ty, tz; /** -x left, +y forward, -z up */ + float rx, ry, rz; + GHOST_TInt16 buttons; +} GHOST_TEventNDOFData_3; + +// [mce] consider scrapping these, in favor of built-in SpaceNav handling. typedef int (*GHOST_NDOFLibraryInit_fp)(); typedef void (*GHOST_NDOFLibraryShutdown_fp)(void* deviceHandle); typedef void* (*GHOST_NDOFDeviceOpen_fp)(void* platformData); -// original patch windows callback. In mac os X version the callback is internal to the plug-in and post an event to main thead. -// not necessary faster, but better integration with other events. - -//typedef int (*GHOST_NDOFEventHandler_fp)(float* result7, void* deviceHandle, unsigned int message, unsigned int* wParam, unsigned long* lParam); -//typedef void (*GHOST_NDOFCallBack_fp)(GHOST_TEventNDOFDataV2 *VolDatas); - typedef struct { /** The key code. */ GHOST_TKey key; -- cgit v1.2.3 From 6365cb3fa8aabaaa1b8b881c3dc218c8e658f009 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 3 Jul 2010 07:03:21 +0000 Subject: much-improved tablet handling; hi-fi input for mouse/pen --- intern/ghost/intern/GHOST_SystemCocoa.h | 3 +- intern/ghost/intern/GHOST_SystemCocoa.mm | 127 +++++++++++++++++++++++++------ 2 files changed, 104 insertions(+), 26 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index d05e19ba286..0949dca5acc 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -270,6 +270,7 @@ protected: static const int TOOL_ID_NONE = -1; + /** Which end of the pen is active: tip or eraser? */ GHOST_TTabletMode m_tablet_pen_mode; /** @@ -292,7 +293,7 @@ protected: * @param y The y-coordinate of the cursor. * @return Indication of success. */ - GHOST_TSuccess setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); + GHOST_TSuccess setMouseCursorPosition(float x, float y); /** Start time at initialization. */ GHOST_TUns64 m_start_time; diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 3edd1bd0b94..91da1fb2d4b 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -1,4 +1,4 @@ -/** +/** * $Id$ * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -23,6 +23,7 @@ * * Contributor(s): Maarten Gribnau 05/2001 * Damien Plisson 09/2009 + * Mike Erwin 06/2010 * * ***** END GPL LICENSE BLOCK ***** */ @@ -587,6 +588,8 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() rstring = NULL; m_ignoreWindowSizedMessages = false; + + m_input_fidelity_hint = HI_FI; // just for testing... } GHOST_SystemCocoa::~GHOST_SystemCocoa() @@ -825,9 +828,9 @@ GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 return GHOST_kSuccess; } -GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) +GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(float xf, float yf) { - float xf=(float)x, yf=(float)y; +// float xf=(float)x, yf=(float)y; GHOST_WindowCocoa* window = (GHOST_WindowCocoa*)m_windowManager->getActiveWindow(); if (!window) return GHOST_kFailure; @@ -897,6 +900,9 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) switch ([event type]) { case NSKeyDown: + if ([event isARepeat]) + break; + // else fall through case NSKeyUp: case NSFlagsChanged: handleKeyEvent(event); @@ -907,15 +913,12 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) case NSLeftMouseDown: case NSLeftMouseUp: case NSLeftMouseDragged: - case NSRightMouseDown: case NSRightMouseUp: case NSRightMouseDragged: - case NSOtherMouseDown: case NSOtherMouseUp: case NSOtherMouseDragged: - case NSMouseMoved: switch ([event subtype]) { @@ -923,11 +926,15 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) handleMouseEvent(event); break; case NSTabletPointEventSubtype: - handleTabletEvent(event); + if ([event deviceID] == m_tablet_mouse_id) + handleMouseEvent(event); + else + handleTabletEvent(event); break; case NSTabletProximityEventSubtype: - // I think only LMB down/up sends this - handleTabletProximity(event); + // I think only LMB down/up sends this. + // Always preceded by a real NSTabletProximity event, so it's redundant. + // handleTabletProximity(event); break; // Mac OS 10.6 introduces a Touch subtype @@ -957,7 +964,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) bool didMove = [event deltaX] != 0 and [event deltaY] != 0; if (didMove) handleMouseEvent(event); - // NSLeftMouseDown gets sent for the initial point, so this is safe. + // LMB Down gets sent for the initial point (and LMB Up for the final), so this is safe. } break; @@ -1377,12 +1384,13 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr) GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) { + printf("tablet prox: "); NSEvent *event = (NSEvent *)eventPtr; GHOST_WindowCocoa* window = (GHOST_WindowCocoa*) m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); if (!window) { - //printf("\nW failure for event 0x%x",[event type]); + printf("\nW failure for event 0x%x",[event type]); return GHOST_kFailure; } @@ -1394,22 +1402,27 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) switch ([event pointingDeviceType]) { case NSPenPointingDevice: + printf("pen "); active_tool = GHOST_kTabletModeStylus; tool_id_ptr = &m_tablet_pen_id; break; case NSEraserPointingDevice: + printf("eraser "); active_tool = GHOST_kTabletModeEraser; tool_id_ptr = &m_tablet_pen_id; break; case NSCursorPointingDevice: + printf("cursor "); active_tool = GHOST_kTabletModeNone; tool_id_ptr = &m_tablet_mouse_id; break; default: + printf(" unknown device %d\n", [event pointingDeviceType]); return GHOST_kFailure; // fail on unknown device } if ([event isEnteringProximity]) { + printf("entering\n"); *tool_id_ptr = [event deviceID]; ct.Active = active_tool; @@ -1418,9 +1431,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) ct.Ytilt = 0; // this is a good place to remember the tool's capabilities - // (later though, after tablet mouse is fixed and coalescing is in place) + // (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; @@ -1434,7 +1448,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) { - NSEvent *event = (NSEvent *)eventPtr; + puts("tablet point"); + NSEvent *event = (NSEvent*)eventPtr; GHOST_WindowCocoa* window = (GHOST_WindowCocoa*) m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); @@ -1442,7 +1457,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) //printf("\nW failure for event 0x%x",[event type]); return GHOST_kFailure; } - + GHOST_TabletData& ct = window->GetCocoaTabletData(); ct.Pressure = [event pressure]; @@ -1450,46 +1465,107 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) 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]))); + break; + case NSLeftMouseUp: + if (m_input_fidelity_hint == HI_FI) + { + printf("hi-fi off\n"); + [NSEvent setMouseCoalescingEnabled:YES]; + } + 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)); + break; + } + } + return GHOST_kSuccess; } GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) { + printf("mouse "); NSEvent *event = (NSEvent *)eventPtr; GHOST_Window* window = (GHOST_Window*)m_windowManager->getWindowAssociatedWithOSWindow((void*)[event window]); if (!window) { - //printf("\nW failure for event 0x%x",[event type]); + printf("\nW failure for event 0x%x",[event type]); return GHOST_kFailure; } - + + static float warp_dx = 0, warp_dy = 0; // need to reset these. e.g. each grab operation should get its own. + // ^^ not currently useful, try m_cursorDelta_* instead. + switch ([event type]) { case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: + printf("button down\n"); + 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]))); break; case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: + printf("button up\n"); + if (m_input_fidelity_hint == HI_FI) + { + printf("hi-fi off\n"); + [NSEvent setMouseCoalescingEnabled:YES]; + } pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonUp, window, convertButton([event buttonNumber]))); + // cheap hack, should reset when grab ends. + warp_dx = warp_dy = 0; break; + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: case NSMouseMoved: + { + NSPoint mousePos = [event locationInWindow]; + float event_dx = [event deltaX]; + float event_dy = [event deltaY]; + + bool coalesced = [NSEvent isMouseCoalescingEnabled]; + if (not coalesced) + printf("[hi-fi] "); + printf("move <%.2f,%.2f> to (%.2f,%.2f)\n", event_dx, event_dy, mousePos.x, mousePos.y); + + event_dy = -event_dy; //Strange Apple implementation (inverted coordinates for the deltaY) ... + + switch (window->getCursorGrabMode()) { case GHOST_kGrabHide: //Cursor hidden grab operation : no cursor move { + printf(" - grab hide\n"); GHOST_TInt32 x_warp, y_warp, x_accum, y_accum; window->getCursorGrabInitPos(x_warp, y_warp); window->getCursorGrabAccum(x_accum, y_accum); - x_accum += [event deltaX]; - y_accum += -[event deltaY]; //Strange Apple implementation (inverted coordinates for the deltaY) ... + x_accum += event_dx; + y_accum += event_dy; window->setCursorGrabAccum(x_accum, y_accum); pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x_warp+x_accum, y_warp+y_accum)); @@ -1500,8 +1576,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) NSPoint mousePos = [event locationInWindow]; GHOST_TInt32 x_mouse= mousePos.x; GHOST_TInt32 y_mouse= mousePos.y; - GHOST_TInt32 event_dx = [event deltaX]; - GHOST_TInt32 event_dy = -[event deltaY]; //Strange Apple implementation (inverted coordinates for the deltaY) ... GHOST_TInt32 x_accum, y_accum, x_cur, y_cur; GHOST_Rect bounds, windowBounds, correctedBounds; @@ -1509,7 +1583,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) if(window->getCursorGrabBounds(bounds)==GHOST_kFailure) window->getClientBounds(bounds); - //Switch back to Cocoa coordinates orientation (y=0 at bottom,the same as blender internal btw!), and to client coordinates + //Switch back to Cocoa coordinates orientation (y=0 at botton,the same as blender internal btw!), and to client coordinates window->getClientBounds(windowBounds); window->screenToClient(bounds.m_l,bounds.m_b, correctedBounds.m_l, correctedBounds.m_t); window->screenToClient(bounds.m_r, bounds.m_t, correctedBounds.m_r, correctedBounds.m_b); @@ -1519,7 +1593,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) //Update accumulation counts window->getCursorGrabAccum(x_accum, y_accum); x_accum += event_dx - m_cursorDelta_x; - y_accum += event_dy - m_cursorDelta_y; + y_accum += event_dy - m_cursorDelta_y; window->setCursorGrabAccum(x_accum, y_accum); @@ -1544,15 +1618,18 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) default: { //Normal cursor operation: send mouse position in window - NSPoint mousePos = [event locationInWindow]; pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, mousePos.x, mousePos.y)); m_cursorDelta_x=0; m_cursorDelta_y=0; //Mouse motion occured between two cursor warps, so we can reset the delta counter + + warp_dx = 0; + warp_dy = 0; } break; } break; - + } + case NSScrollWheel: { /* Send trackpad event if inside a trackpad gesture, send wheel event otherwise */ @@ -1607,8 +1684,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) m_isGestureInProgress = false; break; default: + printf(" unknown event type %d\n", [event type]); return GHOST_kFailure; - break; } return GHOST_kSuccess; -- cgit v1.2.3 From 12d7b10c10fd3636a7cb61909f12e4e10e8fe73d Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 8 Jul 2010 01:53:36 +0000 Subject: added filtered event dispatch for lo-fi mouse/pen input --- intern/ghost/intern/GHOST_EventManager.cpp | 71 +++++++++++++++++++++++++++++- intern/ghost/intern/GHOST_EventManager.h | 8 ++++ intern/ghost/intern/GHOST_System.cpp | 10 ++--- intern/ghost/intern/GHOST_System.h | 1 + 4 files changed, 82 insertions(+), 8 deletions(-) diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp index 0eeb2245cd0..8f5b5e74339 100644 --- a/intern/ghost/intern/GHOST_EventManager.cpp +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -38,6 +38,10 @@ #include #include "GHOST_Debug.h" +// for testing lo-fi +#include "GHOST_EventPrinter.h" +#include +using namespace std; GHOST_EventManager::GHOST_EventManager() { @@ -81,7 +85,7 @@ GHOST_TUns32 GHOST_EventManager::getNumEvents(GHOST_TEventType type) GHOST_IEvent* GHOST_EventManager::peekEvent() { GHOST_IEvent* event = 0; - if (m_events.size() > 0) { + if (!m_events.empty()) { event = m_events.back(); } return event; @@ -104,6 +108,24 @@ 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 + bool handled = false; + if (event) { + TConsumerVector::iterator iter; + for (iter = m_consumers.begin(); iter != m_consumers.end(); iter++) { + if ((*iter)->processEvent(event)) { + handled = true; + // break; + } + } + } + return handled; +} + +#if 0 // disable to test a variant +bool GHOST_EventManager::dispatchEvent_original(GHOST_IEvent* event) { bool handled; if (event) { @@ -120,7 +142,7 @@ bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event) } return handled; } - +#endif bool GHOST_EventManager::dispatchEvent() { @@ -152,6 +174,51 @@ bool GHOST_EventManager::dispatchEvents() } +bool GHOST_EventManager::dispatchEvents_lo_fi() +{ + if (m_events.empty()) + return false; + + bool allHandled = true; + GHOST_IEvent* cursorMove = NULL; + GHOST_IEvent* event = NULL; + + GHOST_EventPrinter printer; + + // when Pen gets its own event type, track it alongside mouse moves + // they probably won't both be active, but you never know + + cout << "\n--- lo-fi dispatch ---"; + cout << "\ndiscard:"; + while ((event = popEvent()) != NULL) { + if (event->getType() == GHOST_kEventCursorMove) { + // just a simple (x,y) pair, nothing much to adjust + // discard the older event and keep the latest + if (cursorMove) { + printer.processEvent(cursorMove); + delete cursorMove; + } + cursorMove = event; + } + else // not a cursor move event + if (!dispatchEvent(event)) + allHandled = false; + } + + // finally dispatch the single cursor update + if (cursorMove) { + cout << "\nsend:"; + printer.processEvent(cursorMove); + if (!dispatchEvent(cursorMove)) + allHandled = false; + } + + cout << endl; + + return allHandled; +} + + GHOST_TSuccess GHOST_EventManager::addConsumer(GHOST_IEventConsumer* consumer) { GHOST_TSuccess success; diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h index 40ba133e8fd..5071adb1bd4 100644 --- a/intern/ghost/intern/GHOST_EventManager.h +++ b/intern/ghost/intern/GHOST_EventManager.h @@ -108,6 +108,14 @@ public: */ virtual bool dispatchEvents(); + /** + * Dispatches most events on the stack, consolidating cursor moves into a single move. + * The event stack will be empty afterwards. + * @return Indicates whether all events were handled by some consumer. + */ + bool dispatchEvents_lo_fi(); + + /** * Adds a consumer to the list of event consumers. * @param consumer The consumer added to the list. diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 3cd3528eeb6..25b55345d46 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -198,7 +198,10 @@ bool GHOST_System::dispatchEvents() { bool handled; if (m_eventManager) { - handled = m_eventManager->dispatchEvents(); + if (m_input_fidelity_hint == LO_FI) + handled = m_eventManager->dispatchEvents_lo_fi(); + else + handled = m_eventManager->dispatchEvents(); } else { handled = false; @@ -283,11 +286,6 @@ GHOST_TSuccess GHOST_System::init() m_eventManager = new GHOST_EventManager (); m_ndofManager = new GHOST_NDOFManager(); -#if 0 - if(m_ndofManager) - printf("ndof manager \n"); -#endif - #ifdef GHOST_DEBUG if (m_eventManager) { m_eventPrinter = new GHOST_EventPrinter(); diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index 6f570b33079..1aeb8597573 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -39,6 +39,7 @@ #include "GHOST_Buttons.h" #include "GHOST_ModifierKeys.h" #include "GHOST_EventManager.h" + #ifdef GHOST_DEBUG #include "GHOST_EventPrinter.h" #endif // GHOST_DEBUG -- cgit v1.2.3 From 56b287bfe6ec4be9a1b5a5ea36f330aec0bf61cf Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 15 Jul 2010 11:54:24 +0000 Subject: disabled lo-fi dispatch log to reduce event debugging noise --- intern/ghost/intern/GHOST_EventManager.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp index 8f5b5e74339..bc0d7ada74d 100644 --- a/intern/ghost/intern/GHOST_EventManager.cpp +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -183,19 +183,19 @@ bool GHOST_EventManager::dispatchEvents_lo_fi() GHOST_IEvent* cursorMove = NULL; GHOST_IEvent* event = NULL; - GHOST_EventPrinter printer; +// GHOST_EventPrinter printer; // when Pen gets its own event type, track it alongside mouse moves // they probably won't both be active, but you never know - cout << "\n--- lo-fi dispatch ---"; - cout << "\ndiscard:"; +// cout << "\n--- lo-fi dispatch ---"; +// cout << "\ndiscard:"; while ((event = popEvent()) != NULL) { if (event->getType() == GHOST_kEventCursorMove) { // just a simple (x,y) pair, nothing much to adjust // discard the older event and keep the latest if (cursorMove) { - printer.processEvent(cursorMove); +// printer.processEvent(cursorMove); delete cursorMove; } cursorMove = event; @@ -207,13 +207,13 @@ bool GHOST_EventManager::dispatchEvents_lo_fi() // finally dispatch the single cursor update if (cursorMove) { - cout << "\nsend:"; - printer.processEvent(cursorMove); +// cout << "\nsend:"; +// printer.processEvent(cursorMove); if (!dispatchEvent(cursorMove)) allHandled = false; } - cout << endl; +// cout << endl; return allHandled; } -- cgit v1.2.3 From 5b1925afba72dc4535cb889e50ecc642cf50c5b8 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 15 Jul 2010 12:12:52 +0000 Subject: Improved tablet support on Windows. Nice deep queue for input points. Much more is being captured now. WT_PACKET events are disabled until I can revisit in a day or two. Also added Wacom's driver wrappers, with their permission. These won't live here very long, but the WindowWin32 tablet code uses it for now. --- intern/ghost/intern/GHOST_WindowWin32.cpp | 81 ++++++------- intern/ghost/intern/GHOST_WindowWin32.h | 8 +- intern/ghost/intern/Utils.c | 182 ++++++++++++++++++++++++++++++ intern/ghost/intern/Utils.h | 94 +++++++++++++++ 4 files changed, 325 insertions(+), 40 deletions(-) create mode 100644 intern/ghost/intern/Utils.c create mode 100644 intern/ghost/intern/Utils.h diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 945e4c16a39..757d9d962fd 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -39,6 +39,10 @@ #include "GHOST_SystemWin32.h" #include "GHOST_DropTargetWin32.h" +//#include "wintab.h" // for tablets, naturally +#include "Utils.c" // that's right, .c, with permission from Wacom +#include // for debug, remove soon [mce] + // Need glew for some defines #include #include @@ -122,7 +126,7 @@ GHOST_WindowWin32::GHOST_WindowWin32( m_hasMouseCaptured(false), m_nPressedButtons(0), m_customCursor(0), - m_wintab(NULL), + m_wintab(false), m_tabletData(NULL), m_tablet(0), m_maxPressure(0), @@ -238,14 +242,11 @@ GHOST_WindowWin32::GHOST_WindowWin32( } } - m_wintab = ::LoadLibrary("Wintab32.dll"); + m_wintab = LoadWintab(); if (m_wintab) { - GHOST_WIN32_WTInfo fpWTInfo = ( GHOST_WIN32_WTInfo ) ::GetProcAddress( m_wintab, "WTInfoA" ); - GHOST_WIN32_WTOpen fpWTOpen = ( GHOST_WIN32_WTOpen ) ::GetProcAddress( m_wintab, "WTOpenA" ); - // let's see if we can initialize tablet here /* check if WinTab available. */ - if (fpWTInfo && fpWTInfo(0, 0, NULL)) { + if (gpWTInfoA(0, 0, NULL)) { // Now init the tablet LOGCONTEXT lc; AXIS TabletX, TabletY, Pressure, Orientation[3]; /* The maximum tablet size, pressure and orientation (tilt) */ @@ -253,26 +254,27 @@ GHOST_WindowWin32::GHOST_WindowWin32( // Open a Wintab context // Get default context information - fpWTInfo( WTI_DEFCONTEXT, 0, &lc ); + gpWTInfoA( WTI_DEFCONTEXT, 0, &lc ); // Open the context lc.lcPktData = PACKETDATA; lc.lcPktMode = PACKETMODE; - lc.lcOptions |= CXO_MESSAGES | CXO_SYSTEM; + lc.lcOptions |= /* CXO_MESSAGES | */ CXO_SYSTEM; + lc.lcOptions &= ~CXO_MESSAGES; /* Set the entire tablet as active */ - fpWTInfo(WTI_DEVICES,DVC_X,&TabletX); - fpWTInfo(WTI_DEVICES,DVC_Y,&TabletY); + gpWTInfoA(WTI_DEVICES,DVC_X,&TabletX); + gpWTInfoA(WTI_DEVICES,DVC_Y,&TabletY); /* get the max pressure, to divide into a float */ - BOOL pressureSupport = fpWTInfo (WTI_DEVICES, DVC_NPRESSURE, &Pressure); + BOOL pressureSupport = gpWTInfoA(WTI_DEVICES, DVC_NPRESSURE, &Pressure); if (pressureSupport) m_maxPressure = Pressure.axMax; else m_maxPressure = 0; /* get the max tilt axes, to divide into floats */ - BOOL tiltSupport = fpWTInfo (WTI_DEVICES, DVC_ORIENTATION, &Orientation); + BOOL tiltSupport = gpWTInfoA(WTI_DEVICES, DVC_ORIENTATION, &Orientation); if (tiltSupport) { /* does the tablet support azimuth ([0]) and altitude ([1]) */ if (Orientation[0].axResolution && Orientation[1].axResolution) { @@ -285,12 +287,16 @@ GHOST_WindowWin32::GHOST_WindowWin32( } } - if (fpWTOpen) { - m_tablet = fpWTOpen( m_hWnd, &lc, TRUE ); - if (m_tablet) { - m_tabletData = new GHOST_TabletData(); - m_tabletData->Active = GHOST_kTabletModeNone; - } + m_tablet = gpWTOpenA( m_hWnd, &lc, TRUE ); + if (m_tablet) { + m_tabletData = new GHOST_TabletData(); + m_tabletData->Active = GHOST_kTabletModeNone; + + // request a deep queue, to capture every pen point + int tabletQueueSize = 128; + while (!gpWTQueueSizeSet(m_tablet, tabletQueueSize)) + --tabletQueueSize; + printf("tablet queue size: %d\n", tabletQueueSize); } } } @@ -300,14 +306,12 @@ GHOST_WindowWin32::GHOST_WindowWin32( GHOST_WindowWin32::~GHOST_WindowWin32() { if (m_wintab) { - GHOST_WIN32_WTClose fpWTClose = ( GHOST_WIN32_WTClose ) ::GetProcAddress( m_wintab, "WTClose" ); - if (fpWTClose) { - if (m_tablet) - fpWTClose(m_tablet); - if (m_tabletData) - delete m_tabletData; - m_tabletData = NULL; - } + if (m_tablet) + gpWTClose(m_tablet); + if (m_tabletData) + delete m_tabletData; + m_tabletData = NULL; + UnloadWintab(); } if (m_customCursor) { DestroyCursor(m_customCursor); @@ -912,20 +916,16 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cur void GHOST_WindowWin32::processWin32TabletInitEvent() { if (m_wintab) { - GHOST_WIN32_WTInfo fpWTInfo = ( GHOST_WIN32_WTInfo ) ::GetProcAddress( m_wintab, "WTInfoA" ); - // let's see if we can initialize tablet here - /* check if WinTab available. */ - if (fpWTInfo) { AXIS Pressure, Orientation[3]; /* The maximum tablet size */ - BOOL pressureSupport = fpWTInfo (WTI_DEVICES, DVC_NPRESSURE, &Pressure); + BOOL pressureSupport = gpWTInfoA(WTI_DEVICES, DVC_NPRESSURE, &Pressure); if (pressureSupport) m_maxPressure = Pressure.axMax; else m_maxPressure = 0; - BOOL tiltSupport = fpWTInfo (WTI_DEVICES, DVC_ORIENTATION, &Orientation); + BOOL tiltSupport = gpWTInfoA(WTI_DEVICES, DVC_ORIENTATION, &Orientation); if (tiltSupport) { /* does the tablet support azimuth ([0]) and altitude ([1]) */ if (Orientation[0].axResolution && Orientation[1].axResolution) { @@ -938,17 +938,22 @@ void GHOST_WindowWin32::processWin32TabletInitEvent() } m_tabletData->Active = GHOST_kTabletModeNone; - } } } void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam) { - PACKET pkt; +// PACKET pkt; if (m_wintab) { - GHOST_WIN32_WTPacket fpWTPacket = ( GHOST_WIN32_WTPacket ) ::GetProcAddress( m_wintab, "WTPacket" ); - if (fpWTPacket) { - if (fpWTPacket((HCTX)lParam, wParam, &pkt)) { + printf("tablet event "); + PACKET pkt_buffer[128]; + int n = gpWTPacketsGet((HCTX)lParam, 128, pkt_buffer); + printf("(%d in queue) ", n); + for (int i = 0; i < n; ++i) { + PACKET& pkt = pkt_buffer[i]; + // "while" not "if" -- drain the queue! +// while (gpWTPacket((HCTX)lParam, wParam, &pkt)) { + putchar('.'); if (m_tabletData) { switch (pkt.pkCursor) { case 0: /* first device */ @@ -1008,7 +1013,7 @@ void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam) } } } - } + putchar('\n'); } } diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index a4d31f87ffa..da3c47c39ac 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -39,9 +39,10 @@ #include "GHOST_Window.h" +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include - #include #define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR) #define PACKETMODE PK_BUTTONS @@ -50,11 +51,13 @@ class GHOST_SystemWin32; class GHOST_DropTargetWin32; +/* // typedefs for WinTab functions to allow dynamic loading typedef UINT (API * GHOST_WIN32_WTInfo) ( UINT, UINT, LPVOID ); typedef HCTX (API * GHOST_WIN32_WTOpen) (HWND, LPLOGCONTEXTA, BOOL); typedef BOOL (API * GHOST_WIN32_WTClose) (HCTX); typedef BOOL (API * GHOST_WIN32_WTPacket) (HCTX, UINT, LPVOID); +*/ /** * GHOST window on M$ Windows OSs. @@ -328,7 +331,8 @@ protected: static const int s_maxTitleLength; /** WinTab dll handle */ - HMODULE m_wintab; +// HMODULE m_wintab; + bool m_wintab; /** Tablet data for GHOST */ GHOST_TabletData* m_tabletData; diff --git a/intern/ghost/intern/Utils.c b/intern/ghost/intern/Utils.c new file mode 100644 index 00000000000..05392793e21 --- /dev/null +++ b/intern/ghost/intern/Utils.c @@ -0,0 +1,182 @@ +/*---------------------------------------------------------------------------- + + NAME + Utils.c + + PURPOSE + Some general-purpose functions for the WinTab demos. + + COPYRIGHT + Copyright (c) Wacom Company, Ltd. 2010 All Rights Reserved + All rights reserved. + +---------------------------------------------------------------------------- */ + +#include "Utils.h" + +#ifdef WACOM_DEBUG + +void WacomTrace( char *lpszFormat, ...); + +#define WACOM_ASSERT( x ) assert( x ) +#define WACOM_TRACE(...) WacomTrace(__VA_ARGS__) +#else +#define WACOM_TRACE(...) +#define WACOM_ASSERT( x ) + +#endif // WACOM_DEBUG + +////////////////////////////////////////////////////////////////////////////// +HINSTANCE ghWintab = NULL; + +WTINFOA gpWTInfoA = NULL; +WTOPENA gpWTOpenA = NULL; +WTGETA gpWTGetA = NULL; +WTSETA gpWTSetA = NULL; +WTCLOSE gpWTClose = NULL; +WTPACKET gpWTPacket = NULL; +WTENABLE gpWTEnable = NULL; +WTOVERLAP gpWTOverlap = NULL; +WTSAVE gpWTSave = NULL; +WTCONFIG gpWTConfig = NULL; +WTRESTORE gpWTRestore = NULL; +WTEXTSET gpWTExtSet = NULL; +WTEXTGET gpWTExtGet = NULL; +WTQUEUESIZESET gpWTQueueSizeSet = NULL; +WTDATAPEEK gpWTDataPeek = NULL; +WTPACKETSGET gpWTPacketsGet = NULL; + +// TODO - add more wintab32 function pointers as needed + +char* pszProgramName = NULL; + +#define GETPROCADDRESS(type, func) \ + gp##func = (type)GetProcAddress(ghWintab, #func); \ + if (!gp##func){ WACOM_ASSERT(FALSE); UnloadWintab(); return FALSE; } + +////////////////////////////////////////////////////////////////////////////// +// Purpose +// Find wintab32.dll and load it. +// Find the exported functions we need from it. +// +// Returns +// TRUE on success. +// FALSE on failure. +// +BOOL LoadWintab( void ) +{ + ghWintab = LoadLibraryA( "Wintab32.dll" ); + if ( !ghWintab ) + { + DWORD err = GetLastError(); + WACOM_TRACE("LoadLibrary error: %i\n", err); + ShowError("Could not load Wintab32.dll"); + return FALSE; + } + + // Explicitly find the exported Wintab functions in which we are interested. + // We are using the ASCII, not unicode versions (where applicable). + GETPROCADDRESS( WTOPENA, WTOpenA ); + GETPROCADDRESS( WTINFOA, WTInfoA ); + GETPROCADDRESS( WTGETA, WTGetA ); + GETPROCADDRESS( WTSETA, WTSetA ); + GETPROCADDRESS( WTPACKET, WTPacket ); + GETPROCADDRESS( WTCLOSE, WTClose ); + GETPROCADDRESS( WTENABLE, WTEnable ); + GETPROCADDRESS( WTOVERLAP, WTOverlap ); + GETPROCADDRESS( WTSAVE, WTSave ); + GETPROCADDRESS( WTCONFIG, WTConfig ); + GETPROCADDRESS( WTRESTORE, WTRestore ); + GETPROCADDRESS( WTEXTSET, WTExtSet ); + GETPROCADDRESS( WTEXTGET, WTExtGet ); + GETPROCADDRESS( WTQUEUESIZESET, WTQueueSizeSet ); + GETPROCADDRESS( WTDATAPEEK, WTDataPeek ); + GETPROCADDRESS( WTPACKETSGET, WTPacketsGet ); + + + // TODO - don't forget to NULL out pointers in UnloadWintab(). + return TRUE; +} + + + +////////////////////////////////////////////////////////////////////////////// +// Purpose +// Uninitializes use of wintab32.dll +// +// Returns +// Nothing. +// +void UnloadWintab( void ) +{ + WACOM_TRACE( "UnloadWintab()\n" ); + + if ( ghWintab ) + { + FreeLibrary( ghWintab ); + ghWintab = NULL; + } + + gpWTOpenA = NULL; + gpWTClose = NULL; + gpWTInfoA = NULL; + gpWTPacket = NULL; + gpWTEnable = NULL; + gpWTOverlap = NULL; + gpWTSave = NULL; + gpWTConfig = NULL; + gpWTGetA = NULL; + gpWTSetA = NULL; + gpWTRestore = NULL; + gpWTExtSet = NULL; + gpWTExtGet = NULL; + gpWTQueueSizeSet = NULL; + gpWTDataPeek = NULL; + gpWTPacketsGet = NULL; +} + + + +////////////////////////////////////////////////////////////////////////////// +// Purpose +// Display error to user. +// +void ShowError( char *pszErrorMessage ) +{ + WACOM_TRACE( "ShowError()\n" ); + + WACOM_ASSERT( pszErrorMessage ); + + MessageBoxA( NULL, pszErrorMessage, gpszProgramName, MB_OK | MB_ICONHAND ); +} + + + +#ifdef WACOM_DEBUG + +////////////////////////////////////////////////////////////////////////////// + +void WacomTrace( char *lpszFormat, ...) +{ + char szTraceMessage[ 128 ]; + + int nBytesWritten; + + va_list args; + + WACOM_ASSERT( lpszFormat ); + + va_start( args, lpszFormat ); + + nBytesWritten = _vsnprintf( szTraceMessage, sizeof( szTraceMessage ) - 1, + lpszFormat, args ); + + if ( nBytesWritten > 0 ) + { + OutputDebugStringA( szTraceMessage ); + } + + va_end( args ); +} + +#endif // WACOM_DEBUG diff --git a/intern/ghost/intern/Utils.h b/intern/ghost/intern/Utils.h new file mode 100644 index 00000000000..e886389796f --- /dev/null +++ b/intern/ghost/intern/Utils.h @@ -0,0 +1,94 @@ +/*---------------------------------------------------------------------------- + + NAME + Utils.h + + PURPOSE + Defines for the general-purpose functions for the WinTab demos. + + COPYRIGHT + Copyright (c) Wacom Company, Ltd. 2010 All Rights Reserved + All rights reserved. + +---------------------------------------------------------------------------- */ +#pragma once + +#include +#include +#include +#include + +#include // NOTE: get from wactab header package + + +////////////////////////////////////////////////////////////////////////////// +#define WACOM_DEBUG + +// Ignore warnings about using unsafe string functions. +#pragma warning( disable : 4996 ) + +////////////////////////////////////////////////////////////////////////////// +// Function pointers to Wintab functions exported from wintab32.dll. +typedef UINT ( API * WTINFOA ) ( UINT, UINT, LPVOID ); +typedef HCTX ( API * WTOPENA )( HWND, LPLOGCONTEXTA, BOOL ); +typedef BOOL ( API * WTGETA ) ( HCTX, LPLOGCONTEXT ); +typedef BOOL ( API * WTSETA ) ( HCTX, LPLOGCONTEXT ); +typedef BOOL ( API * WTCLOSE ) ( HCTX ); +typedef BOOL ( API * WTENABLE ) ( HCTX, BOOL ); +typedef BOOL ( API * WTPACKET ) ( HCTX, UINT, LPVOID ); +typedef BOOL ( API * WTOVERLAP ) ( HCTX, BOOL ); +typedef BOOL ( API * WTSAVE ) ( HCTX, LPVOID ); +typedef BOOL ( API * WTCONFIG ) ( HCTX, HWND ); +typedef HCTX ( API * WTRESTORE ) ( HWND, LPVOID, BOOL ); +typedef BOOL ( API * WTEXTSET ) ( HCTX, UINT, LPVOID ); +typedef BOOL ( API * WTEXTGET ) ( HCTX, UINT, LPVOID ); +typedef BOOL ( API * WTQUEUESIZESET ) ( HCTX, int ); +typedef int ( API * WTDATAPEEK ) ( HCTX, UINT, UINT, int, LPVOID, LPINT); +typedef int ( API * WTPACKETSGET ) (HCTX, int, LPVOID); + +// TODO - add more wintab32 function defs as needed + +////////////////////////////////////////////////////////////////////////////// +extern char* gpszProgramName; + +// Loaded Wintab32 API functions. +extern HINSTANCE ghWintab; + +extern WTINFOA gpWTInfoA; +extern WTOPENA gpWTOpenA; +extern WTGETA gpWTGetA; +extern WTSETA gpWTSetA; +extern WTCLOSE gpWTClose; +extern WTPACKET gpWTPacket; +extern WTENABLE gpWTEnable; +extern WTOVERLAP gpWTOverlap; +extern WTSAVE gpWTSave; +extern WTCONFIG gpWTConfig; +extern WTRESTORE gpWTRestore; +extern WTEXTSET gpWTExtSet; +extern WTEXTGET gpWTExtGet; +extern WTQUEUESIZESET gpWTQueueSizeSet; +extern WTDATAPEEK gpWTDataPeek; +extern WTPACKETSGET gpWTPacketsGet; + +// TODO - add more wintab32 function pointers as needed + +////////////////////////////////////////////////////////////////////////////// +BOOL LoadWintab( void ); +void UnloadWintab( void ); + +void ShowError( char *pszErrorMessage ); + +////////////////////////////////////////////////////////////////////////////// +#ifdef WACOM_DEBUG + +void WacomTrace( char *lpszFormat, ...); + +#define WACOM_ASSERT( x ) assert( x ) +#define WACOM_TRACE(...) WacomTrace(__VA_ARGS__) +#else +#define WACOM_TRACE(...) +#define WACOM_ASSERT( x ) + +#endif // WACOM_DEBUG + -- cgit v1.2.3 From 7aa8ae37819b4a95910089c27fa1e6d704a0f907 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 15 Jul 2010 12:24:14 +0000 Subject: Hi-fi mouse input on Windows! The remains of a RawInput mouse attempt are included, but disabled. RawInput will still be used for multi-axis devices. Eliminated the need for several #defines by requiring WinXP or newer. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 422 ++++++++++++++++++++++++------ intern/ghost/intern/GHOST_SystemWin32.h | 34 ++- 2 files changed, 375 insertions(+), 81 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 76ce7703c06..76300b85242 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -37,6 +37,8 @@ #include "GHOST_SystemWin32.h" #include "GHOST_EventDragnDrop.h" +#include // for debug [mce] + // win64 doesn't define GWL_USERDATA #ifdef WIN32 #ifndef GWL_USERDATA @@ -49,31 +51,16 @@ * According to the docs the mouse wheel message is supported from windows 98 * upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the * wheel detent value are undefined. - */ + + [mce] able to remove this too? + #ifndef WM_MOUSEWHEEL #define WM_MOUSEWHEEL 0x020A #endif // WM_MOUSEWHEEL #ifndef WHEEL_DELTA -#define WHEEL_DELTA 120 /* Value for rolling one detent, (old convention! MS changed it) */ +#define WHEEL_DELTA 120 // Value for rolling one detent, (old convention! MS changed it) #endif // WHEEL_DELTA - -/* - * Defines for mouse buttons 4 and 5 aka xbutton1 and xbutton2. - * MSDN: Declared in Winuser.h, include Windows.h - * This does not seem to work with MinGW so we define our own here. */ -#ifndef XBUTTON1 -#define XBUTTON1 0x0001 -#endif // XBUTTON1 -#ifndef XBUTTON2 -#define XBUTTON2 0x0002 -#endif // XBUTTON2 -#ifndef WM_XBUTTONUP -#define WM_XBUTTONUP 524 -#endif // WM_XBUTTONUP -#ifndef WM_XBUTTONDOWN -#define WM_XBUTTONDOWN 523 -#endif // WM_XBUTTONDOWN #include "GHOST_Debug.h" #include "GHOST_DisplayManagerWin32.h" @@ -135,9 +122,31 @@ GHOST_SystemWin32::GHOST_SystemWin32() m_displayManager = new GHOST_DisplayManagerWin32 (); GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n"); m_displayManager->initialize(); - + // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32. OleInitialize(0); + + m_input_fidelity_hint = HI_FI; // just for testing... + +/* + // register for RawInput devices + RAWINPUTDEVICE devices[2]; + + // standard HID mouse + devices[0].usUsagePage = 0x01; + devices[0].usUsage = 0x02; + devices[0].dwFlags = 0; // RIDEV_NOLEGACY; // ignore legacy mouse messages + devices[0].hwndTarget = NULL; + + // multi-axis mouse (SpaceNavigator) + devices[1].usUsagePage = 0x01; + devices[1].usUsage = 0x08; + devices[1].dwFlags = 0; + devices[1].hwndTarget = NULL; + + if (RegisterRawInputDevices(devices, 2, sizeof(RAWINPUTDEVICE))) + puts("registered for raw mouse and multi-axis input"); +*/ } GHOST_SystemWin32::~GHOST_SystemWin32() @@ -513,13 +522,15 @@ GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, } -GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow) +GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow, int x, int y) { GHOST_TInt32 x_screen, y_screen; GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem()); GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow; - system->getCursorPosition(x_screen, y_screen); +// system->getCursorPosition(x_screen, y_screen); + x_screen = x; + y_screen = y; if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal) { @@ -546,7 +557,7 @@ GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new)); }else{ return new GHOST_EventCursor(system->getMilliSeconds(), - GHOST_kEventCursorMove, + type, window, x_screen + x_accum, y_screen + y_accum @@ -556,7 +567,7 @@ GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, } else { return new GHOST_EventCursor(system->getMilliSeconds(), - GHOST_kEventCursorMove, + type, window, x_screen, y_screen @@ -628,23 +639,199 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax) minmax->ptMinTrackSize.y=240; } +bool GHOST_SystemWin32::processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window, int& x, int& y) +{ + GHOST_IEvent* event = NULL; + bool eventSent = false; + + puts("BEGIN"); + + if (raw.header.dwType == RIM_TYPEMOUSE) + { + USHORT const& buttonFlags = raw.data.mouse.usButtonFlags; + if (buttonFlags) + { + printf("button flags: %04X\n", buttonFlags); + + if (buttonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) + { + puts("left button down"); + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft); + } + else if (buttonFlags & RI_MOUSE_LEFT_BUTTON_UP) + { + puts("left button up"); + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft); + } + + if (buttonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) + { + puts("right button down"); + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight); + } + else if (buttonFlags & RI_MOUSE_RIGHT_BUTTON_UP) + { + puts("right button up"); + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight); + } + + if (buttonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) + { + puts("middle button down"); + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle); + } + else if (buttonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) + { + puts("middle button up"); + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle); + } + + // similar for BUTTON_4 and BUTTON_5 + + if (buttonFlags & RI_MOUSE_WHEEL) + { + signed short wheelDelta = raw.data.mouse.usButtonData; + printf("wheel moved %+d\n", wheelDelta); + } + } + + int dx = raw.data.mouse.lLastX; // These might be in Mickeys, not pixels. + int dy = raw.data.mouse.lLastY; + if (dx || dy) + { + printf("mouse moved (%+d,%+d)\n", dx, dy); + x += dx; + x += dy; + event = processCursorEvent(GHOST_kEventCursorMove, window, x, y); + } + } + else + puts("exotic device!"); + + // assume only one event will come from this RawInput report + // test and adjust assumptions as needed! + + if (event) + { + pushEvent(event); + event = NULL; + eventSent = true; + } + + puts("END"); + + return eventSent; +} + +int GHOST_SystemWin32::getMoreMousePoints(int xLatest, int yLatest, int xPrev, int yPrev, GHOST_WindowWin32* window) + { + MOUSEMOVEPOINT point = { + xLatest & 0x0000FFFF, // confine to low word to make GetMouseMovePointsEx happy + yLatest & 0x0000FFFF, + 0, // time stamp unknown + NULL // no extra info + }; + + MOUSEMOVEPOINT morePoints[64]; + + int n = GetMouseMovePointsEx(sizeof(MOUSEMOVEPOINT), &point, morePoints, 64, GMMP_USE_DISPLAY_POINTS); + if (n == -1) + { + printf(" can't get more mouse points (error %d)\n", (int) GetLastError()); + return 0; + } + + // search for 'prev' point (we want only newer points) + for (int i = 1; i < n; ++i) + if (morePoints[i].x == xPrev && morePoints[i].y == yPrev) + { + n = i; // don't include found point (or more ancient points) + break; + } + + for (int i = n - 1; i > 0; --i) + { + signed short x = morePoints[i].x; + signed short y = morePoints[i].y; + + printf("> (%d,%d)\n", x, y); + + pushEvent(processCursorEvent(GHOST_kEventCursorMove, window, x, y)); + } + + return n; + } // END getMoreMousePoints LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - GHOST_Event* event = 0; LRESULT lResult = 0; GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem()); GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized") + // [mce] then why not register this function at the end of SystemWin32 constructor? + + bool handled = false; if (hwnd) { GHOST_WindowWin32* window = (GHOST_WindowWin32*)::GetWindowLong(hwnd, GWL_USERDATA); if (window) { + handled = system->handleEvent(window, msg, wParam, lParam); + + // take care of misc. cases that need hwnd + if (msg == WM_ACTIVATE) + /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL + will not be dispatched to OUR active window if we minimize one of OUR windows. */ + lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); + else if (msg == WM_PAINT) + /* An application sends the WM_PAINT message when the system or another application + * makes a request to paint a portion of an application's window. The message is sent + * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage + * function when the application obtains a WM_PAINT message by using the GetMessage or + * PeekMessage function. */ + ::ValidateRect(hwnd, NULL); + } + else { + // Event found for a window before the pointer to the class has been set. + GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n") + + /* These are events we typically miss at this point: + WM_GETMINMAXINFO 0x24 + WM_NCCREATE 0x81 + WM_NCCALCSIZE 0x83 + WM_CREATE 0x01 + We let DefWindowProc do the work. + */ + } + } + else { + // Events without valid hwnd + GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n") + } + + if (!handled) + lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); + + return lResult; +} + +bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM wParam, LPARAM lParam) + { + GHOST_Event* event = NULL; + bool eventSent = false; + + static int mousePosX = 0, mousePosY = 0; // track mouse position between calls + switch (msg) { //////////////////////////////////////////////////////////////////////// // Keyboard events, processed //////////////////////////////////////////////////////////////////////// case WM_KEYDOWN: - /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a + /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt * key is not pressed. */ @@ -660,33 +847,33 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, case VK_SHIFT: case VK_CONTROL: case VK_MENU: - if (!system->m_separateLeftRightInitialized) { + if (!m_separateLeftRightInitialized) { // Check whether this system supports separate left and right keys switch (wParam) { case VK_SHIFT: - system->m_separateLeftRight = + m_separateLeftRight = (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) || (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ? true : false; break; case VK_CONTROL: - system->m_separateLeftRight = + m_separateLeftRight = (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) || (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ? true : false; break; case VK_MENU: - system->m_separateLeftRight = + m_separateLeftRight = (HIBYTE(::GetKeyState(VK_LMENU)) != 0) || (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ? true : false; break; } - system->m_separateLeftRightInitialized = true; + m_separateLeftRightInitialized = true; } - system->processModifierKeys(window); + processModifierKeys(window); // Bypass call to DefWindowProc - return 0; + return true; default: event = processKeyEvent(window, true, wParam, lParam); if (!event) { @@ -704,9 +891,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, case VK_SHIFT: case VK_CONTROL: case VK_MENU: - system->processModifierKeys(window); + processModifierKeys(window); // Bypass call to DefWindowProc - return 0; + return true; default: event = processKeyEvent(window, false, wParam, lParam); if (!event) { @@ -718,6 +905,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, } break; +#if 0 // this code is illustrative; no need to compile //////////////////////////////////////////////////////////////////////// // Keyboard events, ignored //////////////////////////////////////////////////////////////////////// @@ -742,16 +930,21 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * a dead key that is pressed while holding down the alt key. */ break; +#endif // illustrative code + //////////////////////////////////////////////////////////////////////// // Tablet events, processed //////////////////////////////////////////////////////////////////////// case WT_PACKET: - ((GHOST_WindowWin32*)window)->processWin32TabletEvent(wParam, lParam); + puts("WT_PACKET"); + window->processWin32TabletEvent(wParam, lParam); break; case WT_CSRCHANGE: case WT_PROXIMITY: - ((GHOST_WindowWin32*)window)->processWin32TabletInitEvent(); + window->processWin32TabletInitEvent(); break; + +//#if 0 // this code has been replaced by RawInput (the WM_INPUT case) //////////////////////////////////////////////////////////////////////// // Mouse events, processed //////////////////////////////////////////////////////////////////////// @@ -795,14 +988,100 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton5); } break; +//#endif // replaced mouse code + case WM_MOUSEMOVE: - event = processCursorEvent(GHOST_kEventCursorMove, window); + { +// puts("WM_MOUSEMOVE"); + +// bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs + int tabletTool = GetMessageExtraInfo() & 0x7f; // true for tablet mouse, not just pen + if (tabletTool) + puts("(from tablet)"); + else + { + // these give window coords, we need view coords +// mousePosX = LOWORD(lParam); +// mousePosY = HIWORD(lParam); +// window->clientToScreen(mousePosX, mousePosY, mousePosX, mousePosY); + + int xPrev = mousePosX; + int yPrev = mousePosY; + window->clientToScreen(LOWORD(lParam), HIWORD(lParam), mousePosX, mousePosY); + // if (m_input_fidelity_hint == HI_FI) // can't access hint from static function + + putchar('\n'); + /* int n = */ getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); +// printf("%d more mouse points found\n", n); + printf(" (%d,%d)\n", mousePosX, mousePosY); + + event = processCursorEvent(GHOST_kEventCursorMove, window, mousePosX, mousePosY); + } break; + } + + case WM_INPUT: + puts("WM_INPUT"); +{ +/* + UINT dwSize; + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); + LPBYTE lpb = new BYTE[dwSize]; + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)); + RAWINPUT* raw = (RAWINPUT*)lpb; +*/ + + RAWINPUT raw; + RAWINPUT* raw_ptr = &raw; + UINT rawSize = sizeof(RAWINPUT); +// UINT bufferSize = rawSize; + + puts("processing first event:"); + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); + eventSent |= processRawInput(raw, window, mousePosX, mousePosY); + DefRawInputProc(&raw_ptr, 1, sizeof(RAWINPUTHEADER)); + +// GetRawInputBuffer(NULL, &bufferSize, sizeof(RAWINPUTHEADER)); +// UINT n = bufferSize / rawSize; +// printf("allocating %d bytes (room for %d events)\n", bufferSize, n); + + RAWINPUT rawBuffer[10];// = new RAWINPUT[n]; + rawSize *= 10; + while (true) + { + int n = GetRawInputBuffer(rawBuffer, &rawSize, sizeof(RAWINPUTHEADER)); + if (n == -1) + { + printf(" error %d\n", (int) GetLastError()); + break; + } + else if (n == 0) + { + //puts("no more events"); + putchar('\n'); + break; + } + else + { + printf("processing %d more events:\n", n); + for (int i = 0; i < n; ++i) + { + RAWINPUT const& raw = rawBuffer[i]; + eventSent |= processRawInput(raw, window, mousePosX, mousePosY); + } + + // clear processed events from the queue + DefRawInputProc((RAWINPUT**)&rawBuffer, n, sizeof(RAWINPUTHEADER)); + } + } // inf. loop +} + break; case WM_MOUSEWHEEL: - /* The WM_MOUSEWHEEL message is sent to the focus window - * when the mouse wheel is rotated. The DefWindowProc + puts("WM_MOUSEWHEEL"); + /* The WM_MOUSEWHEEL message is sent to the focus window + * when the mouse wheel is rotated. The DefWindowProc * function propagates the message to the window's parent. - * There should be no internal forwarding of the message, + * There should be no internal forwarding of the message, * since DefWindowProc propagates it up the parent chain * until it finds a window that processes it. */ @@ -827,6 +1106,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, } break; +#if 0 // this code is illustrative; no need to compile //////////////////////////////////////////////////////////////////////// // Mouse events, ignored //////////////////////////////////////////////////////////////////////// @@ -842,6 +1122,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * is sent to the window that has captured the mouse. */ break; +#endif // illustrative code //////////////////////////////////////////////////////////////////////// // Window events, processed @@ -858,19 +1139,15 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * the message is sent asynchronously, so the window is activated immediately. */ event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window); - /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL - will not be dispatched to OUR active window if we minimize one of OUR windows. */ - lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); break; case WM_PAINT: - /* An application sends the WM_PAINT message when the system or another application + /* An application sends the WM_PAINT message when the system or another application * makes a request to paint a portion of an application's window. The message is sent * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage * function when the application obtains a WM_PAINT message by using the GetMessage or * PeekMessage function. */ event = processWindowEvent(GHOST_kEventWindowUpdate, window); - ::ValidateRect(hwnd, NULL); break; case WM_GETMINMAXINFO: /* The WM_GETMINMAXINFO message is sent to a window when the size or @@ -906,6 +1183,8 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, */ event = processWindowEvent(GHOST_kEventWindowMove, window); break; + +#if 0 // this code is illustrative; no need to compile //////////////////////////////////////////////////////////////////////// // Window events, ignored //////////////////////////////////////////////////////////////////////// @@ -986,57 +1265,44 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * In GHOST, we let DefWindowProc call the timer callback. */ break; +#endif // illustrative code + +#if 0 // this is part of the 'old' NDOF system; new one coming soon! case WM_BLND_NDOF_AXIS: { GHOST_TEventNDOFData ndofdata; - system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata); - system->m_eventManager-> + m_ndofManager->GHOST_NDOFGetDatas(ndofdata); + m_eventManager-> pushEvent(new GHOST_EventNDOF( - system->getMilliSeconds(), - GHOST_kEventNDOFMotion, + getMilliSeconds(), + GHOST_kEventNDOFMotion, window, ndofdata)); } break; case WM_BLND_NDOF_BTN: { GHOST_TEventNDOFData ndofdata; - system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata); - system->m_eventManager-> + m_ndofManager->GHOST_NDOFGetDatas(ndofdata); + m_eventManager-> pushEvent(new GHOST_EventNDOF( - system->getMilliSeconds(), - GHOST_kEventNDOFButton, + getMilliSeconds(), + GHOST_kEventNDOFButton, window, ndofdata)); } break; +#endif // old NDOF } + + if (!eventSent) + if (event) { + pushEvent(event); + eventSent = true; } - else { - // Event found for a window before the pointer to the class has been set. - GHOST_PRINT("GHOST_SystemWin32::wndProc: GHOST window event before creation\n") - /* These are events we typically miss at this point: - WM_GETMINMAXINFO 0x24 - WM_NCCREATE 0x81 - WM_NCCALCSIZE 0x83 - WM_CREATE 0x01 - We let DefWindowProc do the work. - */ - } - } - else { - // Events without valid hwnd - GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n") - } - if (event) { - system->pushEvent(event); - } - else { - lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); - } - return lResult; + return eventSent; } -GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const +GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const { char *buffer; char *temp_buff; diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index e65393a4faa..2fe5e2f4d95 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -37,7 +37,10 @@ #error WIN32 only! #endif // WIN32 +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include +#include #include "GHOST_System.h" @@ -53,6 +56,8 @@ class GHOST_EventWheel; class GHOST_EventWindow; class GHOST_EventDragnDrop; +class GHOST_WindowWin32; + /** * WIN32 Implementation of GHOST_System class. * @see GHOST_System. @@ -258,9 +263,10 @@ protected: * Creates cursor event. * @param type The type of event to create. * @param window The window receiving the event (the active window). + * @param x,y Cursor position. * @return The event created. */ - static GHOST_EventCursor* processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow); + static GHOST_EventCursor* processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow, int x, int y); /** * Creates a mouse wheel event. @@ -287,12 +293,31 @@ protected: * @return The event created. */ static GHOST_Event* processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window); - /** + + /** * Handles minimum window size. * @param minmax The MINMAXINFO structure. */ static void processMinMaxInfo(MINMAXINFO * minmax); - + + /** + * Creates and sends mouse or multi-axis events. + * @param raw a single RawInput structure + * @param window The window receiving the event (the active window). + * @param x,y current mouse coordinates, which may be updated by this function + * @return Whether any events (possibly more than one) were created and sent. + */ + bool processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window, int& x, int& y); + + /** + * Creates and sends mouse events for mouse movements "in between" WM_MOUSEMOVEs. + * @param Latest screen coords from latest WM_MOUSEMOVE + * @param Prev screen coords from previous WM_MOUSEMOVE + * @param window The window receiving the event (the active window). + * @return How many events (possibly many) were created and sent. + */ + int getMoreMousePoints(int xLatest, int yLatest, int xPrev, int yPrev, GHOST_WindowWin32* window); + /** * Returns the local state of the modifier keys (from the message queue). * @param keys The state of the keys. @@ -311,6 +336,9 @@ protected: */ static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + // non-static version of WndProc + bool handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM wParam, LPARAM lParam); + /** The current state of the modifier keys. */ GHOST_ModifierKeys m_modifierKeys; /** State variable set at initialization. */ -- cgit v1.2.3 From f6730216e0b8d1f7a23fdf3e10565d0fc64c3f92 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 15 Jul 2010 12:30:16 +0000 Subject: Tweak Windows #includes to require WinXP or newer and speed up build times. --- intern/ghost/intern/GHOST_DisplayManagerWin32.cpp | 4 ++++ intern/ghost/intern/GHOST_DropTargetWin32.h | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp index 29d15d3e4de..916ddf81217 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp @@ -38,7 +38,11 @@ #include "GHOST_Debug.h" // We do not support multiple monitors at the moment + +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include + #define COMPILE_MULTIMON_STUBS #ifndef FREE_WINDOWS #include diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.h b/intern/ghost/intern/GHOST_DropTargetWin32.h index 6fbf33ce9f8..039c8e8a313 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.h +++ b/intern/ghost/intern/GHOST_DropTargetWin32.h @@ -28,7 +28,11 @@ #ifndef _GHOST_DROP_TARGET_WIN32_H_ #define _GHOST_DROP_TARGET_WIN32_H_ +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include +#include + #include #include #include "GHOST_WindowWin32.h" @@ -41,7 +45,7 @@ public: * Enables clients to get pointers to other interfaces on a given object * through the QueryInterface method, and manage the existence of the object * through the AddRef and Release methods. All other COM interfaces are - * inherited, directly or indirectly, from IUnknown. Therefore, the three + * inherited, directly or indirectly, from IUnknown. Therefore, the three * methods in IUnknown are the first entries in the VTable for every interface. */ HRESULT __stdcall QueryInterface (REFIID riid, void ** ppvObj); -- cgit v1.2.3 From 8a138f4ab2e871a062925044a80a97ae3349541b Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 17 Jul 2010 05:49:41 +0000 Subject: fixed misspelled variable in Wacom utility --- intern/ghost/intern/Utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/ghost/intern/Utils.c b/intern/ghost/intern/Utils.c index 05392793e21..d354750f7f6 100644 --- a/intern/ghost/intern/Utils.c +++ b/intern/ghost/intern/Utils.c @@ -48,7 +48,7 @@ WTPACKETSGET gpWTPacketsGet = NULL; // TODO - add more wintab32 function pointers as needed -char* pszProgramName = NULL; +char* gpszProgramName = NULL; #define GETPROCADDRESS(type, func) \ gp##func = (type)GetProcAddress(ghWintab, #func); \ -- cgit v1.2.3 From 14736cab162a93559bd8c12689356b94eaa2f9f3 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 17 Jul 2010 05:52:46 +0000 Subject: Added rudimentary SpaceNav event capture code for Windows. Disabled RawInput mouse code. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 112 ++++++++++++++++++++++++------ intern/ghost/intern/GHOST_SystemWin32.h | 2 +- 2 files changed, 90 insertions(+), 24 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 76300b85242..1b173208b18 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -128,25 +128,23 @@ GHOST_SystemWin32::GHOST_SystemWin32() m_input_fidelity_hint = HI_FI; // just for testing... -/* // register for RawInput devices - RAWINPUTDEVICE devices[2]; - + RAWINPUTDEVICE devices[1]; +/* // standard HID mouse devices[0].usUsagePage = 0x01; devices[0].usUsage = 0x02; devices[0].dwFlags = 0; // RIDEV_NOLEGACY; // ignore legacy mouse messages devices[0].hwndTarget = NULL; - +*/ // multi-axis mouse (SpaceNavigator) - devices[1].usUsagePage = 0x01; - devices[1].usUsage = 0x08; - devices[1].dwFlags = 0; - devices[1].hwndTarget = NULL; + devices[0].usUsagePage = 0x01; + devices[0].usUsage = 0x08; + devices[0].dwFlags = 0; + devices[0].hwndTarget = NULL; - if (RegisterRawInputDevices(devices, 2, sizeof(RAWINPUTDEVICE))) - puts("registered for raw mouse and multi-axis input"); -*/ + if (RegisterRawInputDevices(devices, 1, sizeof(RAWINPUTDEVICE))) + puts("registered for multi-axis input"); } GHOST_SystemWin32::~GHOST_SystemWin32() @@ -639,13 +637,14 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax) minmax->ptMinTrackSize.y=240; } -bool GHOST_SystemWin32::processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window, int& x, int& y) +bool GHOST_SystemWin32::processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window /*, int& x, int& y */ ) { GHOST_IEvent* event = NULL; bool eventSent = false; puts("BEGIN"); +#if 0 // now using the existing mouse button handlers, improved movement handler if (raw.header.dwType == RIM_TYPEMOUSE) { USHORT const& buttonFlags = raw.data.mouse.usButtonFlags; @@ -705,24 +704,89 @@ bool GHOST_SystemWin32::processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* int dy = raw.data.mouse.lLastY; if (dx || dy) { - printf("mouse moved (%+d,%+d)\n", dx, dy); + printf("mouse moved <%+d,%+d>\n", dx, dy); x += dx; x += dy; event = processCursorEvent(GHOST_kEventCursorMove, window, x, y); } } +#endif // unused experimental mouse code + + if (raw.header.dwType == RIM_TYPEHID) + { +// RID_DEVICE_INFO info; +// DWORD infoSize = sizeof(RID_DEVICE_INFO); +// int n = GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize); + // ... and so on + // I'll finish this device checking code later. Since we ask for only multi-axis input + // in the constructor, that's all we should get here. + +/* +Here's some handy info from http://www.linux-usb.org/usb.ids + +vendor ID +046d Logitech, Inc. + + device IDs + c623 3Dconnexion Space Traveller 3D Mouse + c625 3Dconnexion Space Pilot 3D Mouse + c626 3Dconnexion Space Navigator 3D Mouse + c627 3Dconnexion Space Explorer 3D Mouse + +No other registered devices use the c62_ space, so a simple mask will work! +*/ + + short t[3], r[3]; // defined here just for quick testing, + unsigned short buttons; // will maintain shared copy for all NDOF events + + // multiple events per RAWHID? MSDN hints at this. + printf("%d events\n", raw.data.hid.dwCount); + + BYTE const* data = &raw.data.hid.bRawData; +// MinGW's definition (below) doesn't agree with MSDN reference for bRawData: +// typedef struct tagRAWHID { +// DWORD dwSizeHid; +// DWORD dwCount; +// BYTE bRawData; +// } RAWHID,*PRAWHID,*LPRAWHID; + + BYTE packetType = data[0]; + switch (packetType) + { + case 1: // translation + memcpy(t, data + 1, sizeof(t)); + printf("T: %+5d %+5d %+5d\n", t[0], t[1], t[2]); + break; + case 2: // rotation + memcpy(r, data + 1, sizeof(r)); + printf("R: %+5d %+5d %+5d\n", r[0], r[1], r[2]); + break; + case 3: // buttons + memcpy(&buttons, data + 1, sizeof(buttons)); + printf("buttons:"); + if (buttons) + { + // work our way through the bit mask + for (int i = 0; i < 16; ++i) + if (buttons & (1 << i)) + printf(" %d", i + 1); + printf("\n"); + } else - puts("exotic device!"); + printf(" none\n"); + break; + } + } // assume only one event will come from this RawInput report // test and adjust assumptions as needed! - if (event) - { - pushEvent(event); - event = NULL; - eventSent = true; - } + if (event) + { + pushEvent(event); + event = NULL; + eventSent = true; + } puts("END"); @@ -944,7 +1008,6 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM window->processWin32TabletInitEvent(); break; -//#if 0 // this code has been replaced by RawInput (the WM_INPUT case) //////////////////////////////////////////////////////////////////////// // Mouse events, processed //////////////////////////////////////////////////////////////////////// @@ -1037,8 +1100,11 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM // UINT bufferSize = rawSize; puts("processing first event:"); + // I don't know if this is needed. Can we get by with just GetRawInputBuffer? + // Thought some mouse events were missing, so I put this in to be cautious. + // Test and remove if redundant. [mce] GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); - eventSent |= processRawInput(raw, window, mousePosX, mousePosY); + eventSent |= processRawInput(raw, window /*, mousePosX, mousePosY*/ ); DefRawInputProc(&raw_ptr, 1, sizeof(RAWINPUTHEADER)); // GetRawInputBuffer(NULL, &bufferSize, sizeof(RAWINPUTHEADER)); @@ -1067,7 +1133,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM for (int i = 0; i < n; ++i) { RAWINPUT const& raw = rawBuffer[i]; - eventSent |= processRawInput(raw, window, mousePosX, mousePosY); + eventSent |= processRawInput(raw, window /*, mousePosX, mousePosY*/ ); } // clear processed events from the queue diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 2fe5e2f4d95..8fae4d6ba78 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -307,7 +307,7 @@ protected: * @param x,y current mouse coordinates, which may be updated by this function * @return Whether any events (possibly more than one) were created and sent. */ - bool processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window, int& x, int& y); + bool processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window /*, int& x, int& y */ ); /** * Creates and sends mouse events for mouse movements "in between" WM_MOUSEMOVEs. -- cgit v1.2.3 From 1a27b5a74d5f82e9199073f5bd8326be0f6d05f6 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 22 Jul 2010 07:07:28 +0000 Subject: removed unused Macintosh Carbon code --- intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp | 174 ----- intern/ghost/intern/GHOST_DisplayManagerCarbon.h | 116 ---- intern/ghost/intern/GHOST_WindowCarbon.cpp | 743 --------------------- intern/ghost/intern/GHOST_WindowCarbon.h | 312 --------- 4 files changed, 1345 deletions(-) delete mode 100644 intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp delete mode 100644 intern/ghost/intern/GHOST_DisplayManagerCarbon.h delete mode 100644 intern/ghost/intern/GHOST_WindowCarbon.cpp delete mode 100644 intern/ghost/intern/GHOST_WindowCarbon.h diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp b/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp deleted file mode 100644 index 2c92ef0e2fa..00000000000 --- a/intern/ghost/intern/GHOST_DisplayManagerCarbon.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** - - * $Id$ - * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date September 21, 2001 - */ - -#include "GHOST_DisplayManagerCarbon.h" -#include "GHOST_Debug.h" - -// We do not support multiple monitors at the moment - - -GHOST_DisplayManagerCarbon::GHOST_DisplayManagerCarbon(void) -{ - if (::CGGetActiveDisplayList(0, NULL, &m_numDisplays) != CGDisplayNoErr) - { - m_numDisplays = 0; - m_displayIDs = NULL; - } - if (m_numDisplays > 0) - { - m_displayIDs = new CGDirectDisplayID [m_numDisplays]; - GHOST_ASSERT((m_displayIDs!=NULL), "GHOST_DisplayManagerCarbon::GHOST_DisplayManagerCarbon(): memory allocation failed"); - ::CGGetActiveDisplayList(m_numDisplays, m_displayIDs, &m_numDisplays); - } -} - - -GHOST_TSuccess GHOST_DisplayManagerCarbon::getNumDisplays(GHOST_TUns8& numDisplays) const -{ - numDisplays = (GHOST_TUns8) m_numDisplays; - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_DisplayManagerCarbon::getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const -{ - GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getNumDisplaySettings(): only main display is supported"); - - CFArrayRef displayModes; - displayModes = ::CGDisplayAvailableModes(m_displayIDs[display]); - CFIndex numModes = ::CFArrayGetCount(displayModes); - numSettings = (GHOST_TInt32)numModes; - - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_DisplayManagerCarbon::getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const -{ - GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getDisplaySetting(): only main display is supported"); - - CFArrayRef displayModes; - CGDirectDisplayID d = m_displayIDs[display]; - displayModes = ::CGDisplayAvailableModes(d); - //CFIndex numModes = ::CFArrayGetCount(displayModes);/*unused*/ - //GHOST_TInt32 numSettings = (GHOST_TInt32)numModes; /*unused*/ - CFDictionaryRef displayModeValues = (CFDictionaryRef)::CFArrayGetValueAtIndex(displayModes, index); - - setting.xPixels = getValue(displayModeValues, kCGDisplayWidth); - setting.yPixels = getValue(displayModeValues, kCGDisplayHeight); - setting.bpp = getValue(displayModeValues, kCGDisplayBitsPerPixel); - setting.frequency = getValue(displayModeValues, kCGDisplayRefreshRate); - -#ifdef GHOST_DEBUG - printf("display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", setting.xPixels, setting.yPixels, setting.bpp, setting.frequency); -#endif // GHOST_DEBUG - - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_DisplayManagerCarbon::getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const -{ - GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::getCurrentDisplaySetting(): only main display is supported"); - - CFDictionaryRef displayModeValues = ::CGDisplayCurrentMode(m_displayIDs[display]); - - setting.xPixels = getValue(displayModeValues, kCGDisplayWidth); - setting.yPixels = getValue(displayModeValues, kCGDisplayHeight); - setting.bpp = getValue(displayModeValues, kCGDisplayBitsPerPixel); - setting.frequency = getValue(displayModeValues, kCGDisplayRefreshRate); - -#ifdef GHOST_DEBUG - printf("current display mode: width=%d, height=%d, bpp=%d, frequency=%d\n", setting.xPixels, setting.yPixels, setting.bpp, setting.frequency); -#endif // GHOST_DEBUG - - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting) -{ - GHOST_ASSERT((display==kMainDisplay), "GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(): only main display is supported"); - -#ifdef GHOST_DEBUG - printf("GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(): requested settings:\n"); - printf(" setting.xPixels=%d\n", setting.xPixels); - printf(" setting.yPixels=%d\n", setting.yPixels); - printf(" setting.bpp=%d\n", setting.bpp); - printf(" setting.frequency=%d\n", setting.frequency); -#endif // GHOST_DEBUG - - CFDictionaryRef displayModeValues = ::CGDisplayBestModeForParametersAndRefreshRate( - m_displayIDs[display], - (size_t)setting.bpp, - (size_t)setting.xPixels, - (size_t)setting.yPixels, - (CGRefreshRate)setting.frequency, - NULL); - -#ifdef GHOST_DEBUG - printf("GHOST_DisplayManagerCarbon::setCurrentDisplaySetting(): switching to:\n"); - printf(" setting.xPixels=%d\n", getValue(displayModeValues, kCGDisplayWidth)); - printf(" setting.yPixels=%d\n", getValue(displayModeValues, kCGDisplayHeight)); - printf(" setting.bpp=%d\n", getValue(displayModeValues, kCGDisplayBitsPerPixel)); - printf(" setting.frequency=%d\n", getValue(displayModeValues, kCGDisplayRefreshRate)); -#endif // GHOST_DEBUG - - CGDisplayErr err = ::CGDisplaySwitchToMode(m_displayIDs[display], displayModeValues); - - return err == CGDisplayNoErr ? GHOST_kSuccess : GHOST_kFailure; -} - - -long GHOST_DisplayManagerCarbon::getValue(CFDictionaryRef values, CFStringRef key) const -{ - CFNumberRef numberValue = (CFNumberRef) CFDictionaryGetValue(values, key); - - if (!numberValue) - { - return -1; - } - - long intValue; - - if (!CFNumberGetValue(numberValue, kCFNumberLongType, &intValue)) - { - return -1; - } - - return intValue; -} - diff --git a/intern/ghost/intern/GHOST_DisplayManagerCarbon.h b/intern/ghost/intern/GHOST_DisplayManagerCarbon.h deleted file mode 100644 index 5571efb68cb..00000000000 --- a/intern/ghost/intern/GHOST_DisplayManagerCarbon.h +++ /dev/null @@ -1,116 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -/** - * @file GHOST_DisplayManagerCarbon.h - * Declaration of GHOST_DisplayManagerCarbon class. - */ - -#ifndef _GHOST_DISPLAY_MANAGER_CARBON_H_ -#define _GHOST_DISPLAY_MANAGER_CARBON_H_ - -#ifndef __APPLE__ -#error Apple only! -#endif // __APPLE__ - -#include "GHOST_DisplayManager.h" - -#define __CARBONSOUND__ -#include - -/** - * Manages system displays (Mac OSX/Carbon implementation). - * @see GHOST_DisplayManager - * @author Maarten Gribnau - * @date September 21, 2001 - */ -class GHOST_DisplayManagerCarbon : public GHOST_DisplayManager -{ -public: - /** - * Constructor. - */ - GHOST_DisplayManagerCarbon(void); - - /** - * Returns the number of display devices on this system. - * @param numDisplays The number of displays on this system. - * @return Indication of success. - */ - virtual GHOST_TSuccess getNumDisplays(GHOST_TUns8& numDisplays) const; - - /** - * Returns the number of display settings for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The number of settings of the display device with this index. - * @return Indication of success. - */ - virtual GHOST_TSuccess getNumDisplaySettings(GHOST_TUns8 display, GHOST_TInt32& numSettings) const; - - /** - * Returns the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param index The setting index to be returned. - * @param setting The setting of the display device with this index. - * @return Indication of success. - */ - virtual GHOST_TSuccess getDisplaySetting(GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting) const; - - /** - * Returns the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The current setting of the display device with this index. - * @return Indication of success. - */ - virtual GHOST_TSuccess getCurrentDisplaySetting(GHOST_TUns8 display, GHOST_DisplaySetting& setting) const; - - /** - * Changes the current setting for this display device. - * @param display The index of the display to query with 0 <= display < getNumDisplays(). - * @param setting The current setting of the display device with this index. - * @return Indication of success. - */ - virtual GHOST_TSuccess setCurrentDisplaySetting(GHOST_TUns8 display, const GHOST_DisplaySetting& setting); - -protected: - /** - * Returns a value from a dictionary. - * @param values Dictionary to return value from. - * @param key Key to return value for. - * @return The value for this key. - */ - long getValue(CFDictionaryRef values, CFStringRef key) const; - - /** Cached number of displays. */ - CGDisplayCount m_numDisplays; - /** Cached display id's for each display. */ - CGDirectDisplayID* m_displayIDs; -}; - - -#endif // _GHOST_DISPLAY_MANAGER_CARBON_H_ - diff --git a/intern/ghost/intern/GHOST_WindowCarbon.cpp b/intern/ghost/intern/GHOST_WindowCarbon.cpp deleted file mode 100644 index 376859d3e16..00000000000 --- a/intern/ghost/intern/GHOST_WindowCarbon.cpp +++ /dev/null @@ -1,743 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** - - * $Id$ - * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 10, 2001 - */ - -#include "GHOST_WindowCarbon.h" -#include "GHOST_Debug.h" - -AGLContext GHOST_WindowCarbon::s_firstaglCtx = NULL; -#ifdef GHOST_DRAW_CARBON_GUTTER -const GHOST_TInt32 GHOST_WindowCarbon::s_sizeRectSize = 16; -#endif //GHOST_DRAW_CARBON_GUTTER - -static const GLint sPreferredFormatWindow[8] = { -AGL_RGBA, -AGL_DOUBLEBUFFER, -AGL_ACCELERATED, -AGL_DEPTH_SIZE, 32, -AGL_NONE, -}; - -static const GLint sPreferredFormatFullScreen[9] = { -AGL_RGBA, -AGL_DOUBLEBUFFER, -AGL_ACCELERATED, -AGL_FULLSCREEN, -AGL_DEPTH_SIZE, 32, -AGL_NONE, -}; - - - -WindowRef ugly_hack=NULL; - -const EventTypeSpec kWEvents[] = { - { kEventClassWindow, kEventWindowZoom }, /* for new zoom behaviour */ -}; - -static OSStatus myWEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData) { - WindowRef mywindow; - GHOST_WindowCarbon *ghost_window; - OSStatus err; - int theState; - - if (::GetEventKind(event) == kEventWindowZoom) { - err = ::GetEventParameter (event,kEventParamDirectObject,typeWindowRef,NULL,sizeof(mywindow),NULL, &mywindow); - ghost_window = (GHOST_WindowCarbon *) GetWRefCon(mywindow); - theState = ghost_window->getMac_windowState(); - if (theState == 1) - ghost_window->setMac_windowState(2); - else if (theState == 2) - ghost_window->setMac_windowState(1); - - } - return eventNotHandledErr; -} - -GHOST_WindowCarbon::GHOST_WindowCarbon( - const STR_String& title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, - GHOST_TWindowState state, - GHOST_TDrawingContextType type, - const bool stereoVisual, - const GHOST_TUns16 numOfAASamples -) : - GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone), - m_windowRef(0), - m_grafPtr(0), - m_aglCtx(0), - m_customCursor(0), - m_fullScreenDirty(false) -{ - Str255 title255; - OSStatus err; - - //fprintf(stderr," main screen top %i left %i height %i width %i\n", top, left, height, width); - - if (state >= GHOST_kWindowState8Normal ) { - if(state == GHOST_kWindowState8Normal) state= GHOST_kWindowStateNormal; - else if(state == GHOST_kWindowState8Maximized) state= GHOST_kWindowStateMaximized; - else if(state == GHOST_kWindowState8Minimized) state= GHOST_kWindowStateMinimized; - else if(state == GHOST_kWindowState8FullScreen) state= GHOST_kWindowStateFullScreen; - - // state = state - 8; this was the simple version of above code, doesnt work in gcc 4.0 - - setMac_windowState(1); - } else - setMac_windowState(0); - - if (state != GHOST_kWindowStateFullScreen) { - Rect bnds = { top, left, top+height, left+width }; - // Boolean visible = (state == GHOST_kWindowStateNormal) || (state == GHOST_kWindowStateMaximized); /*unused*/ - gen2mac(title, title255); - - err = ::CreateNewWindow( kDocumentWindowClass, - kWindowStandardDocumentAttributes+kWindowLiveResizeAttribute, - &bnds, - &m_windowRef); - - if ( err != noErr) { - fprintf(stderr," error creating window %i \n",(int)err); - } else { - - ::SetWRefCon(m_windowRef,(SInt32)this); - setTitle(title); - err = InstallWindowEventHandler (m_windowRef, myWEventHandlerProc, GetEventTypeCount(kWEvents), kWEvents,NULL,NULL); - if ( err != noErr) { - fprintf(stderr," error creating handler %i \n",(int)err); - } else { - // ::TransitionWindow (m_windowRef,kWindowZoomTransitionEffect,kWindowShowTransitionAction,NULL); - ::ShowWindow(m_windowRef); - ::MoveWindow (m_windowRef, left, top,true); - - } - } - if (m_windowRef) { - m_grafPtr = ::GetWindowPort(m_windowRef); - setDrawingContextType(type); - updateDrawingContext(); - activateDrawingContext(); - } - if(ugly_hack==NULL) { - ugly_hack= m_windowRef; - // when started from commandline, window remains in the back... also for play anim - ProcessSerialNumber psn; - GetCurrentProcess(&psn); - SetFrontProcess(&psn); - } - } - else { - /* - Rect bnds = { top, left, top+height, left+width }; - gen2mac("", title255); - m_windowRef = ::NewCWindow( - nil, // Storage - &bnds, // Bounding rectangle of the window - title255, // Title of the window - 0, // Window initially visible - plainDBox, // procID - (WindowRef)-1L, // Put window before all other windows - 0, // Window has minimize box - (SInt32)this); // Store a pointer to the class in the refCon - */ - //GHOST_PRINT("GHOST_WindowCarbon::GHOST_WindowCarbon(): creating full-screen OpenGL context\n"); - setDrawingContextType(GHOST_kDrawingContextTypeOpenGL);;installDrawingContext(GHOST_kDrawingContextTypeOpenGL); - updateDrawingContext(); - activateDrawingContext(); - - m_tablet.Active = GHOST_kTabletModeNone; - } -} - - -GHOST_WindowCarbon::~GHOST_WindowCarbon() -{ - if (m_customCursor) delete m_customCursor; - - if(ugly_hack==m_windowRef) ugly_hack= NULL; - - // printf("GHOST_WindowCarbon::~GHOST_WindowCarbon(): removing drawing context\n"); - if(ugly_hack==NULL) setDrawingContextType(GHOST_kDrawingContextTypeNone); - if (m_windowRef) { - ::DisposeWindow(m_windowRef); - m_windowRef = 0; - } -} - -bool GHOST_WindowCarbon::getValid() const -{ - bool valid; - if (!m_fullScreen) { - valid = (m_windowRef != 0) && (m_grafPtr != 0) && ::IsValidWindowPtr(m_windowRef); - } - else { - valid = true; - } - return valid; -} - - -void GHOST_WindowCarbon::setTitle(const STR_String& title) -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setTitle(): window invalid") - Str255 title255; - gen2mac(title, title255); - ::SetWTitle(m_windowRef, title255); -} - - -void GHOST_WindowCarbon::getTitle(STR_String& title) const -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getTitle(): window invalid") - Str255 title255; - ::GetWTitle(m_windowRef, title255); - mac2gen(title255, title); -} - - -void GHOST_WindowCarbon::getWindowBounds(GHOST_Rect& bounds) const -{ - OSStatus success; - Rect rect; - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getWindowBounds(): window invalid") - success = ::GetWindowBounds(m_windowRef, kWindowStructureRgn, &rect); - bounds.m_b = rect.bottom; - bounds.m_l = rect.left; - bounds.m_r = rect.right; - bounds.m_t = rect.top; -} - - -void GHOST_WindowCarbon::getClientBounds(GHOST_Rect& bounds) const -{ - Rect rect; - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getClientBounds(): window invalid") - //::GetPortBounds(m_grafPtr, &rect); - ::GetWindowBounds(m_windowRef, kWindowContentRgn, &rect); - - bounds.m_b = rect.bottom; - bounds.m_l = rect.left; - bounds.m_r = rect.right; - bounds.m_t = rect.top; - - // Subtract gutter height from bottom -#ifdef GHOST_DRAW_CARBON_GUTTER - if ((bounds.m_b - bounds.m_t) > s_sizeRectSize) - { - bounds.m_b -= s_sizeRectSize; - } - else - { - bounds.m_t = bounds.m_b; - } -#endif //GHOST_DRAW_CARBON_GUTTER -} - - -GHOST_TSuccess GHOST_WindowCarbon::setClientWidth(GHOST_TUns32 width) -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientWidth(): window invalid") - GHOST_Rect cBnds, wBnds; - getClientBounds(cBnds); - if (((GHOST_TUns32)cBnds.getWidth()) != width) { - ::SizeWindow(m_windowRef, width, cBnds.getHeight(), true); - } - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_WindowCarbon::setClientHeight(GHOST_TUns32 height) -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientHeight(): window invalid") - GHOST_Rect cBnds, wBnds; - getClientBounds(cBnds); -#ifdef GHOST_DRAW_CARBON_GUTTER - if (((GHOST_TUns32)cBnds.getHeight()) != height+s_sizeRectSize) { - ::SizeWindow(m_windowRef, cBnds.getWidth(), height+s_sizeRectSize, true); - } -#else //GHOST_DRAW_CARBON_GUTTER - if (((GHOST_TUns32)cBnds.getHeight()) != height) { - ::SizeWindow(m_windowRef, cBnds.getWidth(), height, true); - } -#endif //GHOST_DRAW_CARBON_GUTTER - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_WindowCarbon::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setClientSize(): window invalid") - GHOST_Rect cBnds, wBnds; - getClientBounds(cBnds); -#ifdef GHOST_DRAW_CARBON_GUTTER - if ((((GHOST_TUns32)cBnds.getWidth()) != width) || - (((GHOST_TUns32)cBnds.getHeight()) != height+s_sizeRectSize)) { - ::SizeWindow(m_windowRef, width, height+s_sizeRectSize, true); - } -#else //GHOST_DRAW_CARBON_GUTTER - if ((((GHOST_TUns32)cBnds.getWidth()) != width) || - (((GHOST_TUns32)cBnds.getHeight()) != height)) { - ::SizeWindow(m_windowRef, width, height, true); - } -#endif //GHOST_DRAW_CARBON_GUTTER - return GHOST_kSuccess; -} - - -GHOST_TWindowState GHOST_WindowCarbon::getState() const -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::getState(): window invalid") - GHOST_TWindowState state; - if (::IsWindowVisible(m_windowRef) == false) { - state = GHOST_kWindowStateMinimized; - } - else if (::IsWindowInStandardState(m_windowRef, nil, nil)) { - state = GHOST_kWindowStateMaximized; - } - else { - state = GHOST_kWindowStateNormal; - } - return state; -} - - -void GHOST_WindowCarbon::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::screenToClient(): window invalid") - Point point; - point.h = inX; - point.v = inY; - GrafPtr oldPort; - ::GetPort(&oldPort); - ::SetPort(m_grafPtr); - ::GlobalToLocal(&point); - ::SetPort(oldPort); - outX = point.h; - outY = point.v; -} - - -void GHOST_WindowCarbon::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::clientToScreen(): window invalid") - Point point; - point.h = inX; - point.v = inY; - GrafPtr oldPort; - ::GetPort(&oldPort); - ::SetPort(m_grafPtr); - ::LocalToGlobal(&point); - ::SetPort(oldPort); - outX = point.h; - outY = point.v; -} - - -GHOST_TSuccess GHOST_WindowCarbon::setState(GHOST_TWindowState state) -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setState(): window invalid") - switch (state) { - case GHOST_kWindowStateMinimized: - ::HideWindow(m_windowRef); - break; - case GHOST_kWindowStateModified: - SetWindowModified(m_windowRef, 1); - break; - case GHOST_kWindowStateUnModified: - SetWindowModified(m_windowRef, 0); - break; - case GHOST_kWindowStateMaximized: - case GHOST_kWindowStateNormal: - default: - ::ShowWindow(m_windowRef); - break; - } - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_WindowCarbon::setOrder(GHOST_TWindowOrder order) -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::setOrder(): window invalid") - if (order == GHOST_kWindowOrderTop) { - //::BringToFront(m_windowRef); is wrong, front window should be active for input too - ::SelectWindow(m_windowRef); - } - else { - /* doesnt work if you do this with a mouseclick */ - ::SendBehind(m_windowRef, nil); - } - return GHOST_kSuccess; -} - -/*#define WAIT_FOR_VSYNC 1*/ -#ifdef WAIT_FOR_VSYNC -#include -#endif - -GHOST_TSuccess GHOST_WindowCarbon::swapBuffers() -{ -#ifdef WAIT_FOR_VSYNC -/* wait for vsync, to avoid tearing artifacts */ -long VBL = 1; -CGLSetParameter(CGLGetCurrentContext(), kCGLCPSwapInterval, &VBL); -#endif - - GHOST_TSuccess succeeded = GHOST_kSuccess; - if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { - if (m_aglCtx) { - ::aglSwapBuffers(m_aglCtx); - } - else { - succeeded = GHOST_kFailure; - } - } - return succeeded; -} - -GHOST_TSuccess GHOST_WindowCarbon::updateDrawingContext() -{ - GHOST_TSuccess succeeded = GHOST_kSuccess; - if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { - if (m_aglCtx) { - ::aglUpdateContext(m_aglCtx); - } - else { - succeeded = GHOST_kFailure; - } - } - return succeeded; -} - -GHOST_TSuccess GHOST_WindowCarbon::activateDrawingContext() -{ - GHOST_TSuccess succeeded = GHOST_kSuccess; - if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { - if (m_aglCtx) { - ::aglSetCurrentContext(m_aglCtx); -#ifdef GHOST_DRAW_CARBON_GUTTER - // Restrict drawing to non-gutter area - ::aglEnable(m_aglCtx, AGL_BUFFER_RECT); - GHOST_Rect bnds; - getClientBounds(bnds); - GLint b[4] = - { - bnds.m_l, - bnds.m_t+s_sizeRectSize, - bnds.m_r-bnds.m_l, - bnds.m_b-bnds.m_t - }; - GLboolean result = ::aglSetInteger(m_aglCtx, AGL_BUFFER_RECT, b); -#endif //GHOST_DRAW_CARBON_GUTTER - } - else { - succeeded = GHOST_kFailure; - } - } - return succeeded; -} - - -GHOST_TSuccess GHOST_WindowCarbon::installDrawingContext(GHOST_TDrawingContextType type) -{ - GHOST_TSuccess success = GHOST_kFailure; - switch (type) { - case GHOST_kDrawingContextTypeOpenGL: - { - if (!getValid()) break; - - AGLPixelFormat pixelFormat; - if (!m_fullScreen) { - pixelFormat = ::aglChoosePixelFormat(0, 0, sPreferredFormatWindow); - m_aglCtx = ::aglCreateContext(pixelFormat, s_firstaglCtx); - if (!m_aglCtx) break; - if (!s_firstaglCtx) s_firstaglCtx = m_aglCtx; - success = ::aglSetDrawable(m_aglCtx, m_grafPtr) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure; - } - else { - //GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL\n"); -GDHandle device=::GetMainDevice();pixelFormat=::aglChoosePixelFormat(&device,1,sPreferredFormatFullScreen); - m_aglCtx = ::aglCreateContext(pixelFormat, 0); - if (!m_aglCtx) break; - if (!s_firstaglCtx) s_firstaglCtx = m_aglCtx; - //GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): created OpenGL context\n"); - //::CGGetActiveDisplayList(0, NULL, &m_numDisplays) - success = ::aglSetFullScreen(m_aglCtx, m_fullScreenWidth, m_fullScreenHeight, 75, 0) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure; - /* - if (success == GHOST_kSuccess) { - GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL succeeded\n"); - } - else { - GHOST_PRINT("GHOST_WindowCarbon::installDrawingContext(): init full-screen OpenGL failed\n"); - } - */ - } - ::aglDestroyPixelFormat(pixelFormat); - } - break; - - case GHOST_kDrawingContextTypeNone: - success = GHOST_kSuccess; - break; - - default: - break; - } - return success; -} - - -GHOST_TSuccess GHOST_WindowCarbon::removeDrawingContext() -{ - GHOST_TSuccess success = GHOST_kFailure; - switch (m_drawingContextType) { - case GHOST_kDrawingContextTypeOpenGL: - if (m_aglCtx) { - aglSetCurrentContext(NULL); - aglSetDrawable(m_aglCtx, NULL); - //aglDestroyContext(m_aglCtx); - if (s_firstaglCtx == m_aglCtx) s_firstaglCtx = NULL; - success = ::aglDestroyContext(m_aglCtx) == GL_TRUE ? GHOST_kSuccess : GHOST_kFailure; - m_aglCtx = 0; - } - break; - case GHOST_kDrawingContextTypeNone: - success = GHOST_kSuccess; - break; - default: - break; - } - return success; -} - - -GHOST_TSuccess GHOST_WindowCarbon::invalidate() -{ - GHOST_ASSERT(getValid(), "GHOST_WindowCarbon::invalidate(): window invalid") - if (!m_fullScreen) { - Rect rect; - ::GetPortBounds(m_grafPtr, &rect); - ::InvalWindowRect(m_windowRef, &rect); - } - else { - //EventRef event; - //OSStatus status = ::CreateEvent(NULL, kEventClassWindow, kEventWindowUpdate, 0, 0, &event); - //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): created event " << status << " \n"); - //status = ::SetEventParameter(event, kEventParamDirectObject, typeWindowRef, sizeof(WindowRef), this); - //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): set event parameter " << status << " \n"); - //status = ::PostEventToQueue(::GetMainEventQueue(), event, kEventPriorityStandard); - //status = ::SendEventToEventTarget(event, ::GetApplicationEventTarget()); - //GHOST_PRINT("GHOST_WindowCarbon::invalidate(): added event to queue " << status << " \n"); - m_fullScreenDirty = true; - } - return GHOST_kSuccess; -} - - -void GHOST_WindowCarbon::gen2mac(const STR_String& in, Str255 out) const -{ - STR_String tempStr = in; - int num = tempStr.Length(); - if (num > 255) num = 255; - ::memcpy(out+1, tempStr.Ptr(), num); - out[0] = num; -} - - -void GHOST_WindowCarbon::mac2gen(const Str255 in, STR_String& out) const -{ - char tmp[256]; - ::memcpy(tmp, in+1, in[0]); - tmp[in[0]] = '\0'; - out = tmp; -} - -void GHOST_WindowCarbon::loadCursor(bool visible, GHOST_TStandardCursor cursor) const -{ - static bool systemCursorVisible = true; - - if (visible != systemCursorVisible) { - if (visible) { - ::ShowCursor(); - systemCursorVisible = true; - } - else { - ::HideCursor(); - systemCursorVisible = false; - } - } - - if (cursor == GHOST_kStandardCursorCustom && m_customCursor) { - ::SetCursor( m_customCursor ); - } else { - int carbon_cursor; - -#define GCMAP(ghostCursor, carbonCursor) case ghostCursor: carbon_cursor = carbonCursor; break - switch (cursor) { - default: - GCMAP( GHOST_kStandardCursorDefault, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorRightArrow, kThemeAliasArrowCursor); - GCMAP( GHOST_kStandardCursorLeftArrow, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorInfo, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorDestroy, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorHelp, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorCycle, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorSpray, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorWait, kThemeWatchCursor); - GCMAP( GHOST_kStandardCursorText, kThemeIBeamCursor); - GCMAP( GHOST_kStandardCursorCrosshair, kThemeCrossCursor); - GCMAP( GHOST_kStandardCursorUpDown, kThemeClosedHandCursor); - GCMAP( GHOST_kStandardCursorLeftRight, kThemeClosedHandCursor); - GCMAP( GHOST_kStandardCursorTopSide, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorBottomSide, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorLeftSide, kThemeResizeLeftCursor); - GCMAP( GHOST_kStandardCursorRightSide, kThemeResizeRightCursor); - GCMAP( GHOST_kStandardCursorTopLeftCorner, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorTopRightCorner, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorBottomRightCorner, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorBottomLeftCorner, kThemeArrowCursor); - GCMAP( GHOST_kStandardCursorCopy, kThemeCopyArrowCursor); - }; -#undef GCMAP - - ::SetThemeCursor(carbon_cursor); - } -} - - -bool GHOST_WindowCarbon::getFullScreenDirty() -{ - return m_fullScreen && m_fullScreenDirty; -} - - -GHOST_TSuccess GHOST_WindowCarbon::setWindowCursorVisibility(bool visible) -{ - if (::FrontWindow() == m_windowRef) { - loadCursor(visible, getCursorShape()); - } - - return GHOST_kSuccess; -} - -GHOST_TSuccess GHOST_WindowCarbon::setWindowCursorShape(GHOST_TStandardCursor shape) -{ - if (m_customCursor) { - delete m_customCursor; - m_customCursor = 0; - } - - if (::FrontWindow() == m_windowRef) { - loadCursor(getCursorVisibility(), shape); - } - - return GHOST_kSuccess; -} - -#if 0 -/** Reverse the bits in a GHOST_TUns8 */ -static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) -{ - ch= ((ch>>1)&0x55) | ((ch<<1)&0xAA); - ch= ((ch>>2)&0x33) | ((ch<<2)&0xCC); - ch= ((ch>>4)&0x0F) | ((ch<<4)&0xF0); - return ch; -} -#endif - - -/** Reverse the bits in a GHOST_TUns16 */ -static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt) -{ - shrt= ((shrt>>1)&0x5555) | ((shrt<<1)&0xAAAA); - shrt= ((shrt>>2)&0x3333) | ((shrt<<2)&0xCCCC); - shrt= ((shrt>>4)&0x0F0F) | ((shrt<<4)&0xF0F0); - shrt= ((shrt>>8)&0x00FF) | ((shrt<<8)&0xFF00); - return shrt; -} - -GHOST_TSuccess GHOST_WindowCarbon::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, - int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color) -{ - int y; - - if (m_customCursor) { - delete m_customCursor; - m_customCursor = 0; - } - - m_customCursor = new Cursor; - if (!m_customCursor) return GHOST_kFailure; - - for (y=0; y<16; y++) { -#if !defined(__LITTLE_ENDIAN__) - m_customCursor->data[y] = uns16ReverseBits((bitmap[2*y]<<0) | (bitmap[2*y+1]<<8)); - m_customCursor->mask[y] = uns16ReverseBits((mask[2*y]<<0) | (mask[2*y+1]<<8)); -#else - m_customCursor->data[y] = uns16ReverseBits((bitmap[2*y+1]<<0) | (bitmap[2*y]<<8)); - m_customCursor->mask[y] = uns16ReverseBits((mask[2*y+1]<<0) | (mask[2*y]<<8)); -#endif - - } - - m_customCursor->hotSpot.h = hotX; - m_customCursor->hotSpot.v = hotY; - - if (::FrontWindow() == m_windowRef) { - loadCursor(getCursorVisibility(), GHOST_kStandardCursorCustom); - } - - return GHOST_kSuccess; -} - -GHOST_TSuccess GHOST_WindowCarbon::setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], - GHOST_TUns8 mask[16][2], int hotX, int hotY) -{ - return setWindowCustomCursorShape((GHOST_TUns8*)bitmap, (GHOST_TUns8*) mask, 16, 16, hotX, hotY, 0, 1); -} - - -void GHOST_WindowCarbon::setMac_windowState(short value) -{ - mac_windowState = value; -} - -short GHOST_WindowCarbon::getMac_windowState() -{ - return mac_windowState; -} diff --git a/intern/ghost/intern/GHOST_WindowCarbon.h b/intern/ghost/intern/GHOST_WindowCarbon.h deleted file mode 100644 index 16d79b604dd..00000000000 --- a/intern/ghost/intern/GHOST_WindowCarbon.h +++ /dev/null @@ -1,312 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -/** - * @file GHOST_WindowCarbon.h - * Declaration of GHOST_WindowCarbon class. - */ - -#ifndef _GHOST_WINDOW_CARBON_H_ -#define _GHOST_WINDOW_CARBON_H_ - -#ifndef __APPLE__ -#error Apple OSX only! -#endif // __APPLE__ - -#include "GHOST_Window.h" -#include "STR_String.h" - -#define __CARBONSOUND__ -#include - -#include - - -/** - * Window on Mac OSX/Carbon. - * Carbon windows have a size widget in the lower right corner of the window. - * To force it to be visible, the height of the client rectangle is reduced so - * that applications do not draw in that area. GHOST will manage that area - * which is called the gutter. - * When OpenGL contexts are active, GHOST will use AGL_BUFFER_RECT to prevent - * OpenGL drawing outside the reduced client rectangle. - * @author Maarten Gribnau - * @date May 23, 2001 - */ -class GHOST_WindowCarbon : public GHOST_Window { -public: - /** - * Constructor. - * Creates a new window and opens it. - * To check if the window was created properly, use the getValid() method. - * @param title The text shown in the title bar of the window. - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state the window is initially opened with. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. - */ - GHOST_WindowCarbon( - const STR_String& title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, - GHOST_TWindowState state, - GHOST_TDrawingContextType type = GHOST_kDrawingContextTypeNone, - const bool stereoVisual = false, - const GHOST_TUns16 numOfAASamples = 0 - ); - - /** - * Destructor. - * Closes the window and disposes resources allocated. - */ - virtual ~GHOST_WindowCarbon(); - - /** - * Returns indication as to whether the window is valid. - * @return The validity of the window. - */ - virtual bool getValid() const; - - /** - * Sets the title displayed in the title bar. - * @param title The title to display in the title bar. - */ - virtual void setTitle(const STR_String& title); - - /** - * Returns the title displayed in the title bar. - * @param title The title displayed in the title bar. - */ - virtual void getTitle(STR_String& title) const; - - /** - * Returns the window rectangle dimensions. - * The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. - * @param bounds The bounding rectangle of the window. - */ - virtual void getWindowBounds(GHOST_Rect& bounds) const; - - /** - * Returns the client rectangle dimensions. - * The left and top members of the rectangle are always zero. - * @param bounds The bounding rectangle of the cleient area of the window. - */ - virtual void getClientBounds(GHOST_Rect& bounds) const; - - /** - * Resizes client rectangle width. - * @param width The new width of the client area of the window. - */ - virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width); - - /** - * Resizes client rectangle height. - * @param height The new height of the client area of the window. - */ - virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height); - - /** - * Resizes client rectangle. - * @param width The new width of the client area of the window. - * @param height The new height of the client area of the window. - */ - virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); - - /** - * Returns the state of the window (normal, minimized, maximized). - * @return The state of the window. - */ - virtual GHOST_TWindowState getState() const; - - /** - * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate on the screen. - * @param inY The y-coordinate on the screen. - * @param outX The x-coordinate in the client rectangle. - * @param outY The y-coordinate in the client rectangle. - */ - virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; - - /** - * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate in the client rectangle. - * @param inY The y-coordinate in the client rectangle. - * @param outX The x-coordinate on the screen. - * @param outY The y-coordinate on the screen. - */ - virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; - - /** - * Sets the state of the window (normal, minimized, maximized). - * @param state The state of the window. - * @return Indication of success. - */ - virtual GHOST_TSuccess setState(GHOST_TWindowState state); - - /** - * Sets the order of the window (bottom, top). - * @param order The order of the window. - * @return Indication of success. - */ - virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order); - - /** - * Swaps front and back buffers of a window. - * @return A boolean success indicator. - */ - virtual GHOST_TSuccess swapBuffers(); - - /** - * Updates the drawing context of this window. Needed - * whenever the window is changed. - * @return Indication of success. - */ - GHOST_TSuccess updateDrawingContext(); - - /** - * Activates the drawing context of this window. - * @return A boolean success indicator. - */ - virtual GHOST_TSuccess activateDrawingContext(); - - virtual void loadCursor(bool visible, GHOST_TStandardCursor cursor) const; - - /** - * Returns the dirty state of the window when in full-screen mode. - * @return Whether it is dirty. - */ - virtual bool getFullScreenDirty(); - - /* accessor for fullscreen window */ - virtual void setMac_windowState(short value); - virtual short getMac_windowState(); - - - const GHOST_TabletData* GetTabletData() - { return &m_tablet; } - - GHOST_TabletData& GetCarbonTabletData() - { return m_tablet; } -protected: - /** - * Tries to install a rendering context in this window. - * @param type The type of rendering context installed. - * @return Indication as to whether installation has succeeded. - */ - virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type); - - /** - * Removes the current drawing context. - * @return Indication as to whether removal has succeeded. - */ - virtual GHOST_TSuccess removeDrawingContext(); - - /** - * Invalidates the contents of this window. - * @return Indication of success. - */ - virtual GHOST_TSuccess invalidate(); - - /** - * Sets the cursor visibility on the window using - * native window system calls. - */ - virtual GHOST_TSuccess setWindowCursorVisibility(bool visible); - - /** - * Sets the cursor shape on the window using - * native window system calls. - */ - virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape); - - /** - * Sets the cursor shape on the window using - * native window system calls. - */ - virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, - int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color); - - virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY); - - /** - * Converts a string object to a Mac Pascal string. - * @param in The string object to be converted. - * @param out The converted string. - */ - virtual void gen2mac(const STR_String& in, Str255 out) const; - - /** - * Converts a Mac Pascal string to a string object. - * @param in The string to be converted. - * @param out The converted string object. - */ - virtual void mac2gen(const Str255 in, STR_String& out) const; - - WindowRef m_windowRef; - CGrafPtr m_grafPtr; - AGLContext m_aglCtx; - - /** The first created OpenGL context (for sharing display lists) */ - static AGLContext s_firstaglCtx; - - Cursor* m_customCursor; - - GHOST_TabletData m_tablet; - - /** When running in full-screen this tells whether to refresh the window. */ - bool m_fullScreenDirty; - - /** specific MacOs X full screen window setting as we use partially system mechanism - values : 0 not maximizable default - 1 normal state - 2 maximized state - - this will be reworked when rebuilding GHOST carbon to use new OS X apis - in order to be unified with GHOST fullscreen/maximised settings - - (lukep) - **/ - - short mac_windowState; - - - /** - * The width/height of the size rectangle in the lower right corner of a - * Mac/Carbon window. This is also the height of the gutter area. - */ -#ifdef GHOST_DRAW_CARBON_GUTTER - static const GHOST_TInt32 s_sizeRectSize; -#endif // GHOST_DRAW_CARBON_GUTTER -}; - -#endif // _GHOST_WINDOW_CARBON_H_ - -- cgit v1.2.3 From 8a4d43427d70f5099c1a472f6f816b16d6576508 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 22 Jul 2010 07:10:57 +0000 Subject: removed more unused Macintosh Carbon code --- intern/ghost/intern/GHOST_SystemCarbon.cpp | 1236 ---------------------------- intern/ghost/intern/GHOST_SystemCarbon.h | 298 ------- 2 files changed, 1534 deletions(-) delete mode 100644 intern/ghost/intern/GHOST_SystemCarbon.cpp delete mode 100644 intern/ghost/intern/GHOST_SystemCarbon.h diff --git a/intern/ghost/intern/GHOST_SystemCarbon.cpp b/intern/ghost/intern/GHOST_SystemCarbon.cpp deleted file mode 100644 index 5522a0736c4..00000000000 --- a/intern/ghost/intern/GHOST_SystemCarbon.cpp +++ /dev/null @@ -1,1236 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** - - * $Id$ - * Copyright (C) 2001 NaN Technologies B.V. - * @author Maarten Gribnau - * @date May 7, 2001 - */ - -#include -#include -#include "GHOST_SystemCarbon.h" - -#include "GHOST_DisplayManagerCarbon.h" -#include "GHOST_EventKey.h" -#include "GHOST_EventButton.h" -#include "GHOST_EventCursor.h" -#include "GHOST_EventWheel.h" -#include "GHOST_EventNDOF.h" - -#include "GHOST_TimerManager.h" -#include "GHOST_TimerTask.h" -#include "GHOST_WindowManager.h" -#include "GHOST_WindowCarbon.h" -#include "GHOST_NDOFManager.h" -#include "AssertMacros.h" - -#define GHOST_KEY_SWITCH(mac, ghost) { case (mac): ghostKey = (ghost); break; } - -/* blender class and types events */ -enum { - kEventClassBlender = 'blnd' -}; - -enum { - kEventBlenderNdofAxis = 1, - kEventBlenderNdofButtons = 2 -}; - -const EventTypeSpec kEvents[] = -{ - { kEventClassAppleEvent, kEventAppleEvent }, -/* - { kEventClassApplication, kEventAppActivated }, - { kEventClassApplication, kEventAppDeactivated }, -*/ - { kEventClassKeyboard, kEventRawKeyDown }, - { kEventClassKeyboard, kEventRawKeyRepeat }, - { kEventClassKeyboard, kEventRawKeyUp }, - { kEventClassKeyboard, kEventRawKeyModifiersChanged }, - - { kEventClassMouse, kEventMouseDown }, - { kEventClassMouse, kEventMouseUp }, - { kEventClassMouse, kEventMouseMoved }, - { kEventClassMouse, kEventMouseDragged }, - { kEventClassMouse, kEventMouseWheelMoved }, - - { kEventClassWindow, kEventWindowClickZoomRgn } , /* for new zoom behaviour */ - { kEventClassWindow, kEventWindowZoom }, /* for new zoom behaviour */ - { kEventClassWindow, kEventWindowExpand } , /* for new zoom behaviour */ - { kEventClassWindow, kEventWindowExpandAll }, /* for new zoom behaviour */ - - { kEventClassWindow, kEventWindowClose }, - { kEventClassWindow, kEventWindowActivated }, - { kEventClassWindow, kEventWindowDeactivated }, - { kEventClassWindow, kEventWindowUpdate }, - { kEventClassWindow, kEventWindowBoundsChanged }, - - { kEventClassBlender, kEventBlenderNdofAxis }, - { kEventClassBlender, kEventBlenderNdofButtons } - - - -}; - - - -static GHOST_TButtonMask convertButton(EventMouseButton button) -{ - switch (button) { - case kEventMouseButtonPrimary: - return GHOST_kButtonMaskLeft; - case kEventMouseButtonSecondary: - return GHOST_kButtonMaskRight; - case kEventMouseButtonTertiary: - default: - return GHOST_kButtonMaskMiddle; - } -} - -static GHOST_TKey convertKey(int rawCode) -{ - /* This bit of magic converts the rawCode into a virtual - * Mac key based on the current keyboard mapping, but - * without regard to the modifiers (so we don't get 'a' - * and 'A' for example. - */ - static UInt32 dummy= 0; - Handle transData = (Handle) GetScriptManagerVariable(smKCHRCache); - unsigned char vk = KeyTranslate(transData, rawCode, &dummy); - /* Map numpad based on rawcodes first, otherwise they - * look like non-numpad events. - * Added too: mapping the number keys, for french keyboards etc (ton) - */ - // printf("GHOST: vk: %d %c raw: %d\n", vk, vk, rawCode); - - switch (rawCode) { - case 18: return GHOST_kKey1; - case 19: return GHOST_kKey2; - case 20: return GHOST_kKey3; - case 21: return GHOST_kKey4; - case 23: return GHOST_kKey5; - case 22: return GHOST_kKey6; - case 26: return GHOST_kKey7; - case 28: return GHOST_kKey8; - case 25: return GHOST_kKey9; - case 29: return GHOST_kKey0; - - case 82: return GHOST_kKeyNumpad0; - case 83: return GHOST_kKeyNumpad1; - case 84: return GHOST_kKeyNumpad2; - case 85: return GHOST_kKeyNumpad3; - case 86: return GHOST_kKeyNumpad4; - case 87: return GHOST_kKeyNumpad5; - case 88: return GHOST_kKeyNumpad6; - case 89: return GHOST_kKeyNumpad7; - case 91: return GHOST_kKeyNumpad8; - case 92: return GHOST_kKeyNumpad9; - case 65: return GHOST_kKeyNumpadPeriod; - case 76: return GHOST_kKeyNumpadEnter; - case 69: return GHOST_kKeyNumpadPlus; - case 78: return GHOST_kKeyNumpadMinus; - case 67: return GHOST_kKeyNumpadAsterisk; - case 75: return GHOST_kKeyNumpadSlash; - } - - if ((vk >= 'a') && (vk <= 'z')) { - return (GHOST_TKey) (vk - 'a' + GHOST_kKeyA); - } else if ((vk >= '0') && (vk <= '9')) { - return (GHOST_TKey) (vk - '0' + GHOST_kKey0); - } else if (vk==16) { - switch (rawCode) { - case 122: return GHOST_kKeyF1; - case 120: return GHOST_kKeyF2; - case 99: return GHOST_kKeyF3; - case 118: return GHOST_kKeyF4; - case 96: return GHOST_kKeyF5; - case 97: return GHOST_kKeyF6; - case 98: return GHOST_kKeyF7; - case 100: return GHOST_kKeyF8; - case 101: return GHOST_kKeyF9; - case 109: return GHOST_kKeyF10; - case 103: return GHOST_kKeyF11; - case 111: return GHOST_kKeyF12; // Never get, is used for ejecting the CD! - } - } else { - switch (vk) { - case kUpArrowCharCode: return GHOST_kKeyUpArrow; - case kDownArrowCharCode: return GHOST_kKeyDownArrow; - case kLeftArrowCharCode: return GHOST_kKeyLeftArrow; - case kRightArrowCharCode: return GHOST_kKeyRightArrow; - - case kReturnCharCode: return GHOST_kKeyEnter; - case kBackspaceCharCode: return GHOST_kKeyBackSpace; - case kDeleteCharCode: return GHOST_kKeyDelete; - case kEscapeCharCode: return GHOST_kKeyEsc; - case kTabCharCode: return GHOST_kKeyTab; - case kSpaceCharCode: return GHOST_kKeySpace; - - case kHomeCharCode: return GHOST_kKeyHome; - case kEndCharCode: return GHOST_kKeyEnd; - case kPageUpCharCode: return GHOST_kKeyUpPage; - case kPageDownCharCode: return GHOST_kKeyDownPage; - - case '-': return GHOST_kKeyMinus; - case '=': return GHOST_kKeyEqual; - case ',': return GHOST_kKeyComma; - case '.': return GHOST_kKeyPeriod; - case '/': return GHOST_kKeySlash; - case ';': return GHOST_kKeySemicolon; - case '\'': return GHOST_kKeyQuote; - case '\\': return GHOST_kKeyBackslash; - case '[': return GHOST_kKeyLeftBracket; - case ']': return GHOST_kKeyRightBracket; - case '`': return GHOST_kKeyAccentGrave; - } - } - - // printf("GHOST: unknown key: %d %d\n", vk, rawCode); - - return GHOST_kKeyUnknown; -} - -/* MacOSX returns a Roman charset with kEventParamKeyMacCharCodes - * as defined here: http://developer.apple.com/documentation/mac/Text/Text-516.html - * I am not sure how international this works... - * For cross-platform convention, we'll use the Latin ascii set instead. - * As defined at: http://www.ramsch.org/martin/uni/fmi-hp/iso8859-1.html - * - */ -static unsigned char convertRomanToLatin(unsigned char ascii) -{ - - if(ascii<128) return ascii; - - switch(ascii) { - case 128: return 142; - case 129: return 143; - case 130: return 128; - case 131: return 201; - case 132: return 209; - case 133: return 214; - case 134: return 220; - case 135: return 225; - case 136: return 224; - case 137: return 226; - case 138: return 228; - case 139: return 227; - case 140: return 229; - case 141: return 231; - case 142: return 233; - case 143: return 232; - case 144: return 234; - case 145: return 235; - case 146: return 237; - case 147: return 236; - case 148: return 238; - case 149: return 239; - case 150: return 241; - case 151: return 243; - case 152: return 242; - case 153: return 244; - case 154: return 246; - case 155: return 245; - case 156: return 250; - case 157: return 249; - case 158: return 251; - case 159: return 252; - case 160: return 0; - case 161: return 176; - case 162: return 162; - case 163: return 163; - case 164: return 167; - case 165: return 183; - case 166: return 182; - case 167: return 223; - case 168: return 174; - case 169: return 169; - case 170: return 174; - case 171: return 180; - case 172: return 168; - case 173: return 0; - case 174: return 198; - case 175: return 216; - case 176: return 0; - case 177: return 177; - case 178: return 0; - case 179: return 0; - case 180: return 165; - case 181: return 181; - case 182: return 0; - case 183: return 0; - case 184: return 215; - case 185: return 0; - case 186: return 0; - case 187: return 170; - case 188: return 186; - case 189: return 0; - case 190: return 230; - case 191: return 248; - case 192: return 191; - case 193: return 161; - case 194: return 172; - case 195: return 0; - case 196: return 0; - case 197: return 0; - case 198: return 0; - case 199: return 171; - case 200: return 187; - case 201: return 201; - case 202: return 0; - case 203: return 192; - case 204: return 195; - case 205: return 213; - case 206: return 0; - case 207: return 0; - case 208: return 0; - case 209: return 0; - case 210: return 0; - - case 214: return 247; - - case 229: return 194; - case 230: return 202; - case 231: return 193; - case 232: return 203; - case 233: return 200; - case 234: return 205; - case 235: return 206; - case 236: return 207; - case 237: return 204; - case 238: return 211; - case 239: return 212; - case 240: return 0; - case 241: return 210; - case 242: return 218; - case 243: return 219; - case 244: return 217; - case 245: return 0; - case 246: return 0; - case 247: return 0; - case 248: return 0; - case 249: return 0; - case 250: return 0; - - - default: return 0; - } - -} - - -/***/ - -GHOST_SystemCarbon::GHOST_SystemCarbon() : - m_modifierMask(0) -{ - m_displayManager = new GHOST_DisplayManagerCarbon (); - GHOST_ASSERT(m_displayManager, "GHOST_SystemCarbon::GHOST_SystemCarbon(): m_displayManager==0\n"); - m_displayManager->initialize(); - - UnsignedWide micros; - ::Microseconds(µs); - m_start_time = UnsignedWideToUInt64(micros)/1000; - m_ignoreWindowSizedMessages = false; -} - -GHOST_SystemCarbon::~GHOST_SystemCarbon() -{ -} - - -GHOST_TUns64 GHOST_SystemCarbon::getMilliSeconds() const -{ - UnsignedWide micros; - ::Microseconds(µs); - UInt64 millis; - millis = UnsignedWideToUInt64(micros); - return (millis / 1000) - m_start_time; -} - - -GHOST_TUns8 GHOST_SystemCarbon::getNumDisplays() const -{ - // We do not support multiple monitors at the moment - return 1; -} - - -void GHOST_SystemCarbon::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const -{ - BitMap screenBits; - Rect bnds = GetQDGlobalsScreenBits(&screenBits)->bounds; - width = bnds.right - bnds.left; - height = bnds.bottom - bnds.top; -} - - -GHOST_IWindow* GHOST_SystemCarbon::createWindow( - const STR_String& title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, - GHOST_TWindowState state, - GHOST_TDrawingContextType type, - bool stereoVisual, - const GHOST_TUns16 numOfAASamples, - const GHOST_TEmbedderWindowID parentWindow -) -{ - GHOST_IWindow* window = 0; - - window = new GHOST_WindowCarbon (title, left, top, width, height, state, type); - - if (window) { - if (window->getValid()) { - // Store the pointer to the window - GHOST_ASSERT(m_windowManager, "m_windowManager not initialized"); - m_windowManager->addWindow(window); - m_windowManager->setActiveWindow(window); - pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window)); - } - else { - GHOST_PRINT("GHOST_SystemCarbon::createWindow(): window invalid\n"); - delete window; - window = 0; - } - } - else { - GHOST_PRINT("GHOST_SystemCarbon::createWindow(): could not create window\n"); - } - return window; -} - -GHOST_TSuccess GHOST_SystemCarbon::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual) -{ - GHOST_TSuccess success = GHOST_kFailure; - - // need yo make this Carbon all on 10.5 for fullscreen to work correctly - CGCaptureAllDisplays(); - - success = GHOST_System::beginFullScreen( setting, window, stereoVisual); - - if( success != GHOST_kSuccess ) { - // fullscreen failed for other reasons, release - CGReleaseAllDisplays(); - } - - return success; -} - -GHOST_TSuccess GHOST_SystemCarbon::endFullScreen(void) -{ - CGReleaseAllDisplays(); - return GHOST_System::endFullScreen(); -} - -/* this is an old style low level event queue. - As we want to handle our own timers, this is ok. - the full screen hack should be removed */ -bool GHOST_SystemCarbon::processEvents(bool waitForEvent) -{ - bool anyProcessed = false; - EventRef event; - -// SetMouseCoalescingEnabled(false, NULL); - - do { - GHOST_TimerManager* timerMgr = getTimerManager(); - - if (waitForEvent) { - GHOST_TUns64 next = timerMgr->nextFireTime(); - double timeOut; - - if (next == GHOST_kFireTimeNever) { - timeOut = kEventDurationForever; - } else { - timeOut = (double)(next - getMilliSeconds())/1000.0; - if (timeOut < 0.0) - timeOut = 0.0; - } - - ::ReceiveNextEvent(0, NULL, timeOut, false, &event); - } - - if (timerMgr->fireTimers(getMilliSeconds())) { - anyProcessed = true; - } - - if (getFullScreen()) { - // Check if the full-screen window is dirty - GHOST_IWindow* window = m_windowManager->getFullScreenWindow(); - if (((GHOST_WindowCarbon*)window)->getFullScreenDirty()) { - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) ); - anyProcessed = true; - } - } - - /* end loop when no more events available */ - while (::ReceiveNextEvent(0, NULL, 0, true, &event)==noErr) { - OSStatus status= ::SendEventToEventTarget(event, ::GetEventDispatcherTarget()); - if (status==noErr) { - anyProcessed = true; - } else { - UInt32 i= ::GetEventClass(event); - - /* Ignore 'cgs ' class, no documentation on what they - * are, but we get a lot of them - */ - if (i!='cgs ') { - if (i!='tblt') { // tablet event. we use the one packaged in the mouse event - ; //printf("Missed - Class: '%.4s', Kind: %d\n", &i, ::GetEventKind(event)); - } - } - } - ::ReleaseEvent(event); - } - } while (waitForEvent && !anyProcessed); - - return anyProcessed; -} - - -GHOST_TSuccess GHOST_SystemCarbon::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const -{ - Point mouseLoc; - // Get the position of the mouse in the active port - ::GetGlobalMouse(&mouseLoc); - // Convert the coordinates to screen coordinates - x = (GHOST_TInt32)mouseLoc.h; - y = (GHOST_TInt32)mouseLoc.v; - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_SystemCarbon::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) -{ - float xf=(float)x, yf=(float)y; - - CGAssociateMouseAndMouseCursorPosition(false); - CGSetLocalEventsSuppressionInterval(0); - CGWarpMouseCursorPosition(CGPointMake(xf, yf)); - CGAssociateMouseAndMouseCursorPosition(true); - -//this doesn't work properly, see game engine mouse-look scripts -// CGWarpMouseCursorPosition(CGPointMake(xf, yf)); - // this call below sends event, but empties other events (like shift) - // CGPostMouseEvent(CGPointMake(xf, yf), TRUE, 1, FALSE, 0); - - return GHOST_kSuccess; -} - - -GHOST_TSuccess GHOST_SystemCarbon::getModifierKeys(GHOST_ModifierKeys& keys) const -{ - UInt32 modifiers = ::GetCurrentKeyModifiers(); - - keys.set(GHOST_kModifierKeyCommand, (modifiers & cmdKey) ? true : false); - keys.set(GHOST_kModifierKeyLeftAlt, (modifiers & optionKey) ? true : false); - keys.set(GHOST_kModifierKeyLeftShift, (modifiers & shiftKey) ? true : false); - keys.set(GHOST_kModifierKeyLeftControl, (modifiers & controlKey) ? true : false); - - return GHOST_kSuccess; -} - - /* XXX, incorrect for multibutton mice */ -GHOST_TSuccess GHOST_SystemCarbon::getButtons(GHOST_Buttons& buttons) const -{ - Boolean theOnlyButtonIsDown = ::Button(); - buttons.clear(); - buttons.set(GHOST_kButtonMaskLeft, theOnlyButtonIsDown); - return GHOST_kSuccess; -} - -#define FIRSTFILEBUFLG 512 -static bool g_hasFirstFile = false; -static char g_firstFileBuf[512]; - -extern "C" int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG]) { - if (g_hasFirstFile) { - strncpy(buf, g_firstFileBuf, FIRSTFILEBUFLG - 1); - buf[FIRSTFILEBUFLG - 1] = '\0'; - return 1; - } else { - return 0; - } -} - -OSErr GHOST_SystemCarbon::sAEHandlerLaunch(const AppleEvent *event, AppleEvent *reply, SInt32 refCon) -{ - //GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon; - - return noErr; -} - -OSErr GHOST_SystemCarbon::sAEHandlerOpenDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon) -{ - //GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) refCon; - AEDescList docs; - SInt32 ndocs; - OSErr err; - - err = AEGetParamDesc(event, keyDirectObject, typeAEList, &docs); - if (err != noErr) return err; - - err = AECountItems(&docs, &ndocs); - if (err==noErr) { - int i; - - for (i=0; ipushEvent( new GHOST_Event(sys->getMilliSeconds(), GHOST_kEventQuit, NULL) ); - - return noErr; -} - - -GHOST_TSuccess GHOST_SystemCarbon::init() -{ - - GHOST_TSuccess success = GHOST_System::init(); - if (success) { - /* - * Initialize the cursor to the standard arrow shape (so that we can change it later on). - * This initializes the cursor's visibility counter to 0. - */ - ::InitCursor(); - - MenuRef windMenu; - ::CreateStandardWindowMenu(0, &windMenu); - ::InsertMenu(windMenu, 0); - ::DrawMenuBar(); - - ::InstallApplicationEventHandler(sEventHandlerProc, GetEventTypeCount(kEvents), kEvents, this, &m_handler); - - ::AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, sAEHandlerLaunch, (SInt32) this, false); - ::AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, sAEHandlerOpenDocs, (SInt32) this, false); - ::AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, sAEHandlerPrintDocs, (SInt32) this, false); - ::AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, sAEHandlerQuit, (SInt32) this, false); - - } - return success; -} - - -GHOST_TSuccess GHOST_SystemCarbon::exit() -{ - return GHOST_System::exit(); -} - - -OSStatus GHOST_SystemCarbon::handleWindowEvent(EventRef event) -{ - WindowRef windowRef; - GHOST_WindowCarbon *window; - OSStatus err = eventNotHandledErr; - - // Check if the event was send to a GHOST window - ::GetEventParameter(event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &windowRef); - window = (GHOST_WindowCarbon*) ::GetWRefCon(windowRef); - if (!validWindow(window)) { - return err; - } - - //if (!getFullScreen()) { - err = noErr; - switch(::GetEventKind(event)) - { - case kEventWindowClose: - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) ); - break; - case kEventWindowActivated: - m_windowManager->setActiveWindow(window); - window->loadCursor(window->getCursorVisibility(), window->getCursorShape()); - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) ); - break; - case kEventWindowDeactivated: - m_windowManager->setWindowInactive(window); - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) ); - break; - case kEventWindowUpdate: - //if (getFullScreen()) GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen update event\n"); - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) ); - break; - case kEventWindowBoundsChanged: - if (!m_ignoreWindowSizedMessages) - { - window->updateDrawingContext(); - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); - } - break; - default: - err = eventNotHandledErr; - break; - } -// } - //else { - //window = (GHOST_WindowCarbon*) m_windowManager->getFullScreenWindow(); - //GHOST_PRINT("GHOST_SystemCarbon::handleWindowEvent(): full-screen window event, " << window << "\n"); - //::RemoveEventFromQueue(::GetMainEventQueue(), event); - //} - - return err; -} - -OSStatus GHOST_SystemCarbon::handleTabletEvent(EventRef event) -{ - GHOST_IWindow* window = m_windowManager->getActiveWindow(); - TabletPointRec tabletPointRecord; - TabletProximityRec tabletProximityRecord; - UInt32 anInt32; - GHOST_TabletData& ct=((GHOST_WindowCarbon*)window)->GetCarbonTabletData(); - OSStatus err = eventNotHandledErr; - - ct.Pressure = 0; - ct.Xtilt = 0; - ct.Ytilt = 0; - - // is there an embedded tablet event inside this mouse event? - if(noErr == GetEventParameter(event, kEventParamTabletEventType, typeUInt32, NULL, sizeof(UInt32), NULL, (void *)&anInt32)) - { - // yes there is one! - // Embedded tablet events can either be a proximity or pointer event. - if(anInt32 == kEventTabletPoint) - { - //GHOST_PRINT("Embedded pointer event!\n"); - - // Extract the tablet Pointer Event. If there is no Tablet Pointer data - // in this event, then this call will return an error. Just ignore the - // error and go on. This can occur when a proximity event is embedded in - // a mouse event and you did not check the mouse event to see which type - // of tablet event was embedded. - if(noErr == GetEventParameter(event, kEventParamTabletPointRec, - typeTabletPointRec, NULL, - sizeof(TabletPointRec), - NULL, (void *)&tabletPointRecord)) - { - ct.Pressure = tabletPointRecord.pressure / 65535.0f; - ct.Xtilt = tabletPointRecord.tiltX / 32767.0f; /* can be positive or negative */ - ct.Ytilt = tabletPointRecord.tiltY / 32767.0f; /* can be positive or negative */ - } - } else { - //GHOST_PRINT("Embedded proximity event\n"); - - // Extract the Tablet Proximity record from the event. - if(noErr == GetEventParameter(event, kEventParamTabletProximityRec, - typeTabletProximityRec, NULL, - sizeof(TabletProximityRec), - NULL, (void *)&tabletProximityRecord)) - { - if (tabletProximityRecord.enterProximity) { - //pointer is entering tablet area proximity - - switch(tabletProximityRecord.pointerType) - { - case 1: /* stylus */ - ct.Active = GHOST_kTabletModeStylus; - break; - case 2: /* puck, not supported so far */ - ct.Active = GHOST_kTabletModeNone; - break; - case 3: /* eraser */ - ct.Active = GHOST_kTabletModeEraser; - break; - default: - ct.Active = GHOST_kTabletModeNone; - break; - } - } else { - // pointer is leaving - return to mouse - ct.Active = GHOST_kTabletModeNone; - } - } - } - err = noErr; - } - return err; -} - -OSStatus GHOST_SystemCarbon::handleMouseEvent(EventRef event) -{ - OSStatus err = eventNotHandledErr; - GHOST_IWindow* window = m_windowManager->getActiveWindow(); - UInt32 kind = ::GetEventKind(event); - - switch (kind) - { - case kEventMouseDown: - case kEventMouseUp: - // Handle Mac application responsibilities - if ((kind == kEventMouseDown) && handleMouseDown(event)) { - err = noErr; - } - else { - GHOST_TEventType type = (kind == kEventMouseDown) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp; - EventMouseButton button; - - /* Window still gets mouse up after command-H */ - if (m_windowManager->getActiveWindow()) { - // handle any tablet events that may have come with the mouse event (optional) - handleTabletEvent(event); - - ::GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); - pushEvent(new GHOST_EventButton(getMilliSeconds(), type, window, convertButton(button))); - err = noErr; - } - } - break; - - case kEventMouseMoved: - case kEventMouseDragged: { - Point mousePos; - - if (window) { - //handle any tablet events that may have come with the mouse event (optional) - handleTabletEvent(event); - - ::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePos); - pushEvent(new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, mousePos.h, mousePos.v)); - err = noErr; - } - break; - } - case kEventMouseWheelMoved: - { - OSStatus status; - //UInt32 modifiers; - EventMouseWheelAxis axis; - SInt32 delta; - //status = ::GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(modifiers), NULL, &modifiers); - //GHOST_ASSERT(status == noErr, "GHOST_SystemCarbon::handleMouseEvent(): GetEventParameter() failed"); - status = ::GetEventParameter(event, kEventParamMouseWheelAxis, typeMouseWheelAxis, NULL, sizeof(axis), NULL, &axis); - GHOST_ASSERT(status == noErr, "GHOST_SystemCarbon::handleMouseEvent(): GetEventParameter() failed"); - if (axis == kEventMouseWheelAxisY) - { - status = ::GetEventParameter(event, kEventParamMouseWheelDelta, typeLongInteger, NULL, sizeof(delta), NULL, &delta); - GHOST_ASSERT(status == noErr, "GHOST_SystemCarbon::handleMouseEvent(): GetEventParameter() failed"); - /* - * Limit mouse wheel delta to plus and minus one. - */ - delta = delta > 0 ? 1 : -1; - pushEvent(new GHOST_EventWheel(getMilliSeconds(), window, delta)); - err = noErr; - } - } - break; - } - - return err; -} - - -OSStatus GHOST_SystemCarbon::handleKeyEvent(EventRef event) -{ - OSStatus err = eventNotHandledErr; - GHOST_IWindow* window = m_windowManager->getActiveWindow(); - UInt32 kind = ::GetEventKind(event); - UInt32 modifiers; - UInt32 rawCode; - GHOST_TKey key; - unsigned char ascii; - - /* Can happen, very rarely - seems to only be when command-H makes - * the window go away and we still get an HKey up. - */ - if (!window) { - //::GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &rawCode); - //key = convertKey(rawCode); - return err; - } - - err = noErr; - switch (kind) { - case kEventRawKeyDown: - case kEventRawKeyRepeat: - case kEventRawKeyUp: - ::GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &rawCode); - ::GetEventParameter(event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &ascii); - - key = convertKey(rawCode); - ascii= convertRomanToLatin(ascii); - - // if (key!=GHOST_kKeyUnknown) { - GHOST_TEventType type; - if (kind == kEventRawKeyDown) { - type = GHOST_kEventKeyDown; - } else if (kind == kEventRawKeyRepeat) { - type = GHOST_kEventKeyDown; /* XXX, fixme */ - } else { - type = GHOST_kEventKeyUp; - } - pushEvent( new GHOST_EventKey( getMilliSeconds(), type, window, key, ascii) ); -// } - break; - - case kEventRawKeyModifiersChanged: - /* ugh */ - ::GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); - if ((modifiers & shiftKey) != (m_modifierMask & shiftKey)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & shiftKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) ); - } - if ((modifiers & controlKey) != (m_modifierMask & controlKey)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & controlKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftControl) ); - } - if ((modifiers & optionKey) != (m_modifierMask & optionKey)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & optionKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftAlt) ); - } - if ((modifiers & cmdKey) != (m_modifierMask & cmdKey)) { - pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & cmdKey)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) ); - } - - m_modifierMask = modifiers; - break; - - default: - err = eventNotHandledErr; - break; - } - - return err; -} - - -bool GHOST_SystemCarbon::handleMouseDown(EventRef event) -{ - WindowPtr window; - short part; - BitMap screenBits; - bool handled = true; - GHOST_WindowCarbon* ghostWindow; - Point mousePos = {0 , 0}; - - ::GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &mousePos); - - part = ::FindWindow(mousePos, &window); - ghostWindow = (GHOST_WindowCarbon*) ::GetWRefCon(window); - - switch (part) { - case inMenuBar: - handleMenuCommand(::MenuSelect(mousePos)); - break; - - case inDrag: - /* - * The DragWindow() routine creates a lot of kEventWindowBoundsChanged - * events. By setting m_ignoreWindowSizedMessages these are suppressed. - * @see GHOST_SystemCarbon::handleWindowEvent(EventRef event) - */ - /* even worse: scale window also generates a load of events, and nothing - is handled (read: client's event proc called) until you release mouse (ton) */ - - GHOST_ASSERT(validWindow(ghostWindow), "GHOST_SystemCarbon::handleMouseDown: invalid window"); - m_ignoreWindowSizedMessages = true; - ::DragWindow(window, mousePos, &GetQDGlobalsScreenBits(&screenBits)->bounds); - m_ignoreWindowSizedMessages = false; - - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, ghostWindow) ); - - break; - - case inContent: - if (window != ::FrontWindow()) { - ::SelectWindow(window); - /* - * We add a mouse down event on the newly actived window - */ - //GHOST_PRINT("GHOST_SystemCarbon::handleMouseDown(): adding mouse down event, " << ghostWindow << "\n"); - EventMouseButton button; - ::GetEventParameter(event, kEventParamMouseButton, typeMouseButton, NULL, sizeof(button), NULL, &button); - pushEvent(new GHOST_EventButton(getMilliSeconds(), GHOST_kEventButtonDown, ghostWindow, convertButton(button))); - } else { - handled = false; - } - break; - - case inGoAway: - GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0"); - if (::TrackGoAway(window, mousePos)) - { - // todo: add option-close, because itÿs in the HIG - // if (event.modifiers & optionKey) { - // Close the clean documents, others will be confirmed one by one. - //} - // else { - pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, ghostWindow)); - //} - } - break; - - case inGrow: - GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0"); - ::ResizeWindow(window, mousePos, NULL, NULL); - break; - - case inZoomIn: - case inZoomOut: - GHOST_ASSERT(ghostWindow, "GHOST_SystemCarbon::handleMouseEvent: ghostWindow==0"); - if (::TrackBox(window, mousePos, part)) { - int macState; - - macState = ghostWindow->getMac_windowState(); - if ( macState== 0) - ::ZoomWindow(window, part, true); - else - if (macState == 2) { // always ok - ::ZoomWindow(window, part, true); - ghostWindow->setMac_windowState(1); - } else { // need to force size again - // GHOST_TUns32 scr_x,scr_y; /*unused*/ - Rect outAvailableRect; - - ghostWindow->setMac_windowState(2); - ::GetAvailableWindowPositioningBounds ( GetMainDevice(), &outAvailableRect); - - //this->getMainDisplayDimensions(scr_x,scr_y); - ::SizeWindow (window, outAvailableRect.right-outAvailableRect.left,outAvailableRect.bottom-outAvailableRect.top-1,false); - ::MoveWindow (window, outAvailableRect.left, outAvailableRect.top,true); - } - - } - break; - - default: - handled = false; - break; - } - - return handled; -} - - -bool GHOST_SystemCarbon::handleMenuCommand(GHOST_TInt32 menuResult) -{ - short menuID; - short menuItem; - UInt32 command; - bool handled; - OSErr err; - - menuID = HiWord(menuResult); - menuItem = LoWord(menuResult); - - err = ::GetMenuItemCommandID(::GetMenuHandle(menuID), menuItem, &command); - - handled = false; - - if (err || command == 0) { - } - else { - switch(command) { - } - } - - ::HiliteMenu(0); - return handled; -} - - -OSStatus GHOST_SystemCarbon::sEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData) -{ - GHOST_SystemCarbon* sys = (GHOST_SystemCarbon*) userData; - OSStatus err = eventNotHandledErr; - GHOST_IWindow* window; - GHOST_TEventNDOFData data; - UInt32 kind; - - switch (::GetEventClass(event)) - { - case kEventClassAppleEvent: - EventRecord eventrec; - if (ConvertEventRefToEventRecord(event, &eventrec)) { - err = AEProcessAppleEvent(&eventrec); - } - break; - case kEventClassMouse: - err = sys->handleMouseEvent(event); - break; - case kEventClassWindow: - err = sys->handleWindowEvent(event); - break; - case kEventClassKeyboard: - err = sys->handleKeyEvent(event); - break; - case kEventClassBlender : - window = sys->m_windowManager->getActiveWindow(); - sys->m_ndofManager->GHOST_NDOFGetDatas(data); - kind = ::GetEventKind(event); - - switch (kind) - { - case 1: - sys->m_eventManager->pushEvent(new GHOST_EventNDOF(sys->getMilliSeconds(), GHOST_kEventNDOFMotion, window, data)); - // printf("motion\n"); - break; - case 2: - sys->m_eventManager->pushEvent(new GHOST_EventNDOF(sys->getMilliSeconds(), GHOST_kEventNDOFButton, window, data)); -// printf("button\n"); - break; - } - err = noErr; - break; - default : - ; - break; - } - - return err; -} - -GHOST_TUns8* GHOST_SystemCarbon::getClipboard(bool selection) const -{ - PasteboardRef inPasteboard; - PasteboardItemID itemID; - CFDataRef flavorData; - OSStatus err = noErr; - GHOST_TUns8 * temp_buff; - CFRange range; - OSStatus syncFlags; - - err = PasteboardCreate(kPasteboardClipboard, &inPasteboard); - if(err != noErr) { return NULL;} - - syncFlags = PasteboardSynchronize( inPasteboard ); - /* as we always get in a new string, we can safely ignore sync flags if not an error*/ - if(syncFlags <0) { return NULL;} - - - err = PasteboardGetItemIdentifier( inPasteboard, 1, &itemID ); - if(err != noErr) { return NULL;} - - err = PasteboardCopyItemFlavorData( inPasteboard, itemID, CFSTR("public.utf8-plain-text"), &flavorData); - if(err != noErr) { return NULL;} - - range = CFRangeMake(0, CFDataGetLength(flavorData)); - - temp_buff = (GHOST_TUns8*) malloc(range.length+1); - - CFDataGetBytes(flavorData, range, (UInt8*)temp_buff); - - temp_buff[range.length] = '\0'; - - if(temp_buff) { - return temp_buff; - } else { - return NULL; - } -} - -void GHOST_SystemCarbon::putClipboard(GHOST_TInt8 *buffer, bool selection) const -{ - if(selection) {return;} // for copying the selection, used on X11 - - PasteboardRef inPasteboard; - CFDataRef textData = NULL; - OSStatus err = noErr; /*For error checking*/ - OSStatus syncFlags; - - err = PasteboardCreate(kPasteboardClipboard, &inPasteboard); - if(err != noErr) { return;} - - syncFlags = PasteboardSynchronize( inPasteboard ); - /* as we always put in a new string, we can safely ignore sync flags */ - if(syncFlags <0) { return;} - - err = PasteboardClear( inPasteboard ); - if(err != noErr) { return;} - - textData = CFDataCreate(kCFAllocatorDefault, (UInt8*)buffer, strlen(buffer)); - - if (textData) { - err = PasteboardPutItemFlavor( inPasteboard, (PasteboardItemID)1, CFSTR("public.utf8-plain-text"), textData, 0); - if(err != noErr) { - if(textData) { CFRelease(textData);} - return; - } - } - - if(textData) { - CFRelease(textData); - } -} - -const GHOST_TUns8* GHOST_SystemCarbon::getSystemDir() const -{ - return (GHOST_TUns8*)"/Library/Application Support/Blender"; -} - -const GHOST_TUns8* GHOST_SystemCarbon::getUserDir() const -{ - static char usrPath[256] = ""; - char* env = getenv("HOME"); - - if (env) { - strncpy(usrPath, env, 245); - usrPath[245]=0; - strcat(usrPath, "/Library/Application Support/Blender"); - return (GHOST_TUns8*) usrPath; - } - else - return NULL; -} diff --git a/intern/ghost/intern/GHOST_SystemCarbon.h b/intern/ghost/intern/GHOST_SystemCarbon.h deleted file mode 100644 index ebd929749b6..00000000000 --- a/intern/ghost/intern/GHOST_SystemCarbon.h +++ /dev/null @@ -1,298 +0,0 @@ -/** - * $Id$ - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -/** - * @file GHOST_SystemCarbon.h - * Declaration of GHOST_SystemCarbon class. - */ - -#ifndef _GHOST_SYSTEM_CARBON_H_ -#define _GHOST_SYSTEM_CARBON_H_ - -#ifndef __APPLE__ -#error Apple OSX only! -#endif // __APPLE__ - -#define __CARBONSOUND__ -#include - -#include "GHOST_System.h" - -class GHOST_EventCursor; -class GHOST_EventKey; -class GHOST_EventWindow; - -/** - * OSX/Carbon Implementation of GHOST_System class. - * @see GHOST_System. - * @author Maarten Gribnau - * @date May 21, 2001 - */ -class GHOST_SystemCarbon : public GHOST_System { -public: - /** - * Constructor. - */ - GHOST_SystemCarbon(); - - /** - * Destructor. - */ - ~GHOST_SystemCarbon(); - - /*************************************************************************************** - ** Time(r) functionality - ***************************************************************************************/ - - /** - * Returns the system time. - * Returns the number of milliseconds since the start of the system process. - * Based on ANSI clock() routine. - * @return The number of milliseconds. - */ - virtual GHOST_TUns64 getMilliSeconds() const; - - /*************************************************************************************** - ** Display/window management functionality - ***************************************************************************************/ - - /** - * Returns the number of displays on this system. - * @return The number of displays. - */ - virtual GHOST_TUns8 getNumDisplays() const; - - /** - * Returns the dimensions of the main display on this system. - * @return The dimension of the main display. - */ - virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const; - - /** - * Create a new window. - * The new window is added to the list of windows managed. - * Never explicitly delete the window, use disposeWindow() instead. - * @param title The name of the window (displayed in the title bar of the window if the OS supports it). - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state of the window when opened. - * @param type The type of drawing context installed in this window. - * @param parentWindow Parent (embedder) window - * @return The new window (or 0 if creation failed). - */ - virtual GHOST_IWindow* createWindow( - const STR_String& title, - GHOST_TInt32 left, - GHOST_TInt32 top, - GHOST_TUns32 width, - GHOST_TUns32 height, - GHOST_TWindowState state, - GHOST_TDrawingContextType type, - const bool stereoVisual, - const GHOST_TUns16 numOfAASamples = 0, - const GHOST_TEmbedderWindowID parentWindow = 0 - ); - - virtual GHOST_TSuccess beginFullScreen( - const GHOST_DisplaySetting& setting, - GHOST_IWindow** window, - const bool stereoVisual - ); - - virtual GHOST_TSuccess endFullScreen( void ); - - /*************************************************************************************** - ** Event management functionality - ***************************************************************************************/ - - /** - * Gets events from the system and stores them in the queue. - * @param waitForEvent Flag to wait for an event (or return immediately). - * @return Indication of the presence of events. - */ - virtual bool processEvents(bool waitForEvent); - - /*************************************************************************************** - ** Cursor management functionality - ***************************************************************************************/ - - /** - * Returns the current location of the cursor (location in screen coordinates) - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. - */ - virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const; - - /** - * Updates the location of the cursor (location in screen coordinates). - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. - */ - virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); - - /*************************************************************************************** - ** Access to mouse button and keyboard states. - ***************************************************************************************/ - - /** - * Returns the state of all modifier keys. - * @param keys The state of all modifier keys (true == pressed). - * @return Indication of success. - */ - virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const; - - /** - * Returns the state of the mouse buttons (ouside the message queue). - * @param buttons The state of the buttons. - * @return Indication of success. - */ - virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const; - - /** - * Returns Clipboard data - * @param selection Indicate which buffer to return - * @return Returns the selected buffer - */ - virtual GHOST_TUns8* getClipboard(bool selection) const; - - /** - * Puts buffer to system clipboard - * @param buffer The buffer to be copied - * @param selection Indicates which buffer to copy too, only used on X11 - */ - virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const; - - /** - * Determine the base dir in which shared resources are located. It will first try to use - * "unpack and run" path, then look for properly installed path, not including versioning. - * @return Unsigned char string pointing to system dir (eg /usr/share/blender/). - */ - virtual const GHOST_TUns8* getSystemDir() const; - - /** - * Determine the base dir in which user configuration is stored, not including versioning. - * If needed, it will create the base directory. - * @return Unsigned char string pointing to user dir (eg ~/.blender/). - */ - virtual const GHOST_TUns8* getUserDir() const; - -protected: - /** - * Initializes the system. - * For now, it justs registers the window class (WNDCLASS). - * @return A success value. - */ - virtual GHOST_TSuccess init(); - - /** - * Closes the system down. - * @return A success value. - */ - virtual GHOST_TSuccess exit(); - - - /** - * Handles a tablet event. - * @param event A Mac event. - * @return Indication whether the event was handled. - */ - OSStatus handleTabletEvent(EventRef event); - /** - * Handles a mouse event. - * @param event A Mac event. - * @return Indication whether the event was handled. - */ - OSStatus handleMouseEvent(EventRef event); - - /** - * Handles a key event. - * @param event A Mac event. - * @return Indication whether the event was handled. - */ - OSStatus handleKeyEvent(EventRef event); - - /** - * Handles a window event. - * @param event A Mac event. - * @return Indication whether the event was handled. - */ - OSStatus handleWindowEvent(EventRef event); - - /** - * Handles all basic Mac application stuff for a mouse down event. - * @param event A Mac event. - * @return Indication whether the event was handled. - */ - bool handleMouseDown(EventRef event); - - /** - * Handles a Mac menu command. - * @param menuResult A Mac menu/item identifier. - * @return Indication whether the event was handled. - */ - bool handleMenuCommand(GHOST_TInt32 menuResult); - - /* callback for blender generated events */ -// static OSStatus blendEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData); - - - /** - * Callback for Carbon when it has events. - */ - static OSStatus sEventHandlerProc(EventHandlerCallRef handler, EventRef event, void* userData); - - /** Apple Event Handlers */ - static OSErr sAEHandlerLaunch(const AppleEvent *event, AppleEvent *reply, SInt32 refCon); - static OSErr sAEHandlerOpenDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon); - static OSErr sAEHandlerPrintDocs(const AppleEvent *event, AppleEvent *reply, SInt32 refCon); - static OSErr sAEHandlerQuit(const AppleEvent *event, AppleEvent *reply, SInt32 refCon); - - /** - * Callback for Mac Timer tasks that expire. - * @param tmTask Pointer to the timer task that expired. - */ - //static void s_timerCallback(TMTaskPtr tmTask); - - /** Event handler reference. */ - EventHandlerRef m_handler; - - /** Start time at initialization. */ - GHOST_TUns64 m_start_time; - - /** State of the modifiers. */ - UInt32 m_modifierMask; - - /** Ignores window size messages (when window is dragged). */ - bool m_ignoreWindowSizedMessages; -}; - -#endif // _GHOST_SYSTEM_CARBON_H_ - -- cgit v1.2.3 From b86a25efba0b5bd6d73b7207d726b67603caa934 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 22 Jul 2010 07:15:00 +0000 Subject: removed some NDOF plugin-related code --- intern/ghost/GHOST_C-api.h | 16 +--------------- intern/ghost/GHOST_ISystem.h | 15 --------------- intern/ghost/intern/GHOST_C-api.cpp | 18 +----------------- intern/ghost/intern/GHOST_System.cpp | 14 ++------------ intern/ghost/intern/GHOST_System.h | 20 -------------------- 5 files changed, 4 insertions(+), 79 deletions(-) diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index a5fec1f101c..a80a56207e7 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -280,21 +280,7 @@ extern GHOST_TSuccess GHOST_SetProgressBar(GHOST_WindowHandle windowhandle, floa * @param windowhandle The handle to the window */ extern GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle); - - -/*************************************************************************************** - ** N-degree of freedom device management functionality - ***************************************************************************************/ - -/** -* Open N-degree of freedom devices - */ -extern int GHOST_OpenNDOF(GHOST_SystemHandle systemhandle, - GHOST_WindowHandle windowhandle, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen - ); + /*************************************************************************************** ** Cursor management functionality diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index 1760fe30b7f..6f0adeb05b7 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -295,21 +295,6 @@ public: * @return Indication of success. */ virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer* consumer) = 0; - - /*************************************************************************************** - ** N-degree of freedom device management functionality - ***************************************************************************************/ - - /** - * Starts the N-degree of freedom device manager - */ - virtual int openNDOF(GHOST_IWindow*, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen - // original patch only - // GHOST_NDOFEventHandler_fp setNdofEventHandler - ) = 0; /*************************************************************************************** diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 9da20200f63..9c278f40282 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -263,22 +263,6 @@ GHOST_TSuccess GHOST_EndProgressBar(GHOST_WindowHandle windowhandle) } -int GHOST_OpenNDOF(GHOST_SystemHandle systemhandle, GHOST_WindowHandle windowhandle, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen) - //original patch only - /* GHOST_NDOFEventHandler_fp setNdofEventHandler)*/ -{ - GHOST_ISystem* system = (GHOST_ISystem*) systemhandle; - - return system->openNDOF((GHOST_IWindow*) windowhandle, - setNdofLibraryInit, setNdofLibraryShutdown, setNdofDeviceOpen); -// original patch -// setNdofLibraryInit, setNdofLibraryShutdown, setNdofDeviceOpen, setNdofEventHandler); -} - - GHOST_TStandardCursor GHOST_GetCursorShape(GHOST_WindowHandle windowhandle) { @@ -701,7 +685,7 @@ GHOST_TSuccess GHOST_InvalidateWindow(GHOST_WindowHandle windowhandle) return window->invalidate(); } - +// [mce] this is going away soon extern const GHOST_TabletData* GHOST_GetTabletData(GHOST_WindowHandle windowhandle) { return ((GHOST_IWindow*)windowhandle)->GetTabletData(); diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 25b55345d46..70ff5a02924 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -237,17 +237,6 @@ GHOST_TSuccess GHOST_System::pushEvent(GHOST_IEvent* event) return success; } -int GHOST_System::openNDOF(GHOST_IWindow* w, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen) -{ - return m_ndofManager->deviceOpen(w, - setNdofLibraryInit, - setNdofLibraryShutdown, - setNdofDeviceOpen); -} - GHOST_TSuccess GHOST_System::getModifierKeyState(GHOST_TModifierKeyMask mask, bool& isDown) const { @@ -284,7 +273,8 @@ GHOST_TSuccess GHOST_System::init() m_timerManager = new GHOST_TimerManager (); m_windowManager = new GHOST_WindowManager (); m_eventManager = new GHOST_EventManager (); - m_ndofManager = new GHOST_NDOFManager(); +// m_ndofManager = new GHOST_NDOFManager(); +// Each platform now has their own NDOFManager subclass #ifdef GHOST_DEBUG if (m_eventManager) { diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index 1aeb8597573..5940894ad27 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -184,26 +184,6 @@ public: virtual GHOST_TSuccess addEventConsumer(GHOST_IEventConsumer* consumer); - - /*************************************************************************************** - ** N-degree of freedom devcice management functionality - ***************************************************************************************/ - - /** Inherited from GHOST_ISystem - * Opens the N-degree of freedom device manager - * return 0 if device found, 1 otherwise - */ - virtual int openNDOF(GHOST_IWindow* w, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen); - -// original patch only -// GHOST_NDOFEventHandler_fp setNdofEventHandler); - - - - /*************************************************************************************** ** Cursor management functionality ***************************************************************************************/ -- cgit v1.2.3 From f0167c6a4117df275f85ce466c2067e0eda0e0e8 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 22 Jul 2010 07:18:12 +0000 Subject: get more mouse events only when in hi-fi mode --- intern/ghost/intern/GHOST_SystemWin32.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 1b173208b18..829f0997377 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -1074,8 +1074,13 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM // if (m_input_fidelity_hint == HI_FI) // can't access hint from static function putchar('\n'); - /* int n = */ getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); -// printf("%d more mouse points found\n", n); + + if (m_input_fidelity_hint == HI_FI) + { + /* int n = */ getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); + // printf("%d more mouse points found\n", n); + } + printf(" (%d,%d)\n", mousePosX, mousePosY); event = processCursorEvent(GHOST_kEventCursorMove, window, mousePosX, mousePosY); -- cgit v1.2.3 From 6c2dee0198fed174a55f65685d4e01752c987547 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 22 Jul 2010 07:23:41 +0000 Subject: revamped NDOF event system for ghost, added (untested) Mac support --- intern/ghost/GHOST_Types.h | 32 +++-- intern/ghost/intern/GHOST_EventNDOF.h | 45 +++---- intern/ghost/intern/GHOST_NDOFManager.cpp | 168 ++++++++++--------------- intern/ghost/intern/GHOST_NDOFManager.h | 40 +++--- intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp | 111 ++++++++++++++++ intern/ghost/intern/GHOST_NDOFManagerCocoa.h | 45 +++++++ 6 files changed, 284 insertions(+), 157 deletions(-) create mode 100644 intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp create mode 100644 intern/ghost/intern/GHOST_NDOFManagerCocoa.h diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 4ec8e22a960..66bfa0e469f 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -154,7 +154,8 @@ typedef enum { GHOST_kEventTrackpad, /// Trackpad event GHOST_kEventNDOFMotion, /// N degree of freedom device motion event - GHOST_kEventNDOFButton, /// N degree of freedom device button event + GHOST_kEventNDOFButtonDown,/// N degree of freedom device button events + GHOST_kEventNDOFButtonUp, GHOST_kEventKeyDown, GHOST_kEventKeyUp, @@ -432,17 +433,17 @@ typedef struct { // float dt; //} GHOST_TEventNDOFData; -typedef struct { - /** N-degree of freedom device data v2*/ - int changed; - GHOST_TUns64 client; - GHOST_TUns64 address; - GHOST_TInt16 tx, ty, tz; /** -x left, +y up, +z forward */ - GHOST_TInt16 rx, ry, rz; - GHOST_TInt16 buttons; - GHOST_TUns64 time; - GHOST_TUns64 delta; -} GHOST_TEventNDOFData; +// typedef struct { +// /** N-degree of freedom device data v2*/ +// int changed; +// GHOST_TUns64 client; +// GHOST_TUns64 address; +// GHOST_TInt16 tx, ty, tz; /** -x left, +y up, +z forward */ +// GHOST_TInt16 rx, ry, rz; +// GHOST_TInt16 buttons; +// GHOST_TUns64 time; +// GHOST_TUns64 delta; +// } GHOST_TEventNDOFData; typedef struct { /** N-degree of freedom device data v3 [GSoC 2010]*/ @@ -454,13 +455,8 @@ typedef struct { float tx, ty, tz; /** -x left, +y forward, -z up */ float rx, ry, rz; - GHOST_TInt16 buttons; -} GHOST_TEventNDOFData_3; +} GHOST_TEventNDOFData; -// [mce] consider scrapping these, in favor of built-in SpaceNav handling. -typedef int (*GHOST_NDOFLibraryInit_fp)(); -typedef void (*GHOST_NDOFLibraryShutdown_fp)(void* deviceHandle); -typedef void* (*GHOST_NDOFDeviceOpen_fp)(void* platformData); typedef struct { /** The key code. */ diff --git a/intern/ghost/intern/GHOST_EventNDOF.h b/intern/ghost/intern/GHOST_EventNDOF.h index 916fd7bbc08..c5d35126f01 100644 --- a/intern/ghost/intern/GHOST_EventNDOF.h +++ b/intern/ghost/intern/GHOST_EventNDOF.h @@ -26,32 +26,35 @@ #include "GHOST_Event.h" -/** - * N-degree of freedom device event. - */ -class GHOST_EventNDOF : public GHOST_Event + +class GHOST_EventNDOFMotion : public GHOST_Event { +protected: + GHOST_TEventNDOFData m_axisData; + public: - /** - * Constructor. - * @param msec The time this event was generated. - * @param type The type of this event. - * @param x The x-coordinate of the location the cursor was at at the time of the event. - * @param y The y-coordinate of the location the cursor was at at the time of the event. - */ - GHOST_EventNDOF(GHOST_TUns64 msec, GHOST_TEventType type, GHOST_IWindow* window, - GHOST_TEventNDOFData data) - : GHOST_Event(msec, type, window) - { - m_ndofEventData = data; - m_data = &m_ndofEventData; - } + 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: - /** translation & rotation from the device. */ - GHOST_TEventNDOFData m_ndofEventData; + GHOST_TUns16 m_buttonNumber; + +public: + GHOST_EventNDOFButton(GHOST_TUns64 time, GHOST_TUns16 buttonNumber, GHOST_TEventType upOrDown) + : GHOST_Event(time, upOrDown, NULL) + , m_buttonNumber(buttonNumber) +// , m_data(&m_buttonNumber) + { + m_data = &m_buttonNumber; + } }; #endif // _GHOST_EVENT_NDOF_H_ - diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 5e5f04d5bc9..787811fc69b 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -20,108 +20,70 @@ * ***** END GPL LICENSE BLOCK ***** */ -#include /* just for printf */ - #include "GHOST_NDOFManager.h" - - -// the variable is outside the class because it must be accessed from plugin -static volatile GHOST_TEventNDOFData currentNdofValues = {0,0,0,0,0,0,0,0,0,0,0}; - -#if !defined(_WIN32) && !defined(__APPLE__) -#include "GHOST_SystemX11.h" -#endif - -namespace -{ - GHOST_NDOFLibraryInit_fp ndofLibraryInit = 0; - GHOST_NDOFLibraryShutdown_fp ndofLibraryShutdown = 0; - GHOST_NDOFDeviceOpen_fp ndofDeviceOpen = 0; -} - -GHOST_NDOFManager::GHOST_NDOFManager() -{ - m_DeviceHandle = 0; - - // discover the API from the plugin - ndofLibraryInit = 0; - ndofLibraryShutdown = 0; - ndofDeviceOpen = 0; -} - -GHOST_NDOFManager::~GHOST_NDOFManager() -{ - if (ndofLibraryShutdown) - ndofLibraryShutdown(m_DeviceHandle); - - m_DeviceHandle = 0; -} - - -int -GHOST_NDOFManager::deviceOpen(GHOST_IWindow* window, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen) -{ - int Pid; +#include "GHOST_EventNDOF.h" + +GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) + : m_system(sys) +// , m_translation((short[]){0,0,0}) +// , m_rotation((short[]){0,0,0}) + , m_buttons(0) + , m_atRest(true) + { } + +void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time) + { + memcpy(m_translation, t, sizeof(m_translation)); + m_motionTime = time; + m_atRest = false; + } + +void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time) + { + memcpy(m_rotation, r, sizeof(m_rotation)); + m_motionTime = time; + m_atRest = false; + } + +void GHOST_NDOFManager::updateButtons(unsigned short buttons, GHOST_TUns64 time) + { + 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)); + } + + m_buttons = buttons; + } + +bool GHOST_NDOFManager::sendMotionEvent() + { + if (m_atRest) + return false; + + GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime); + GHOST_TEventNDOFData* data = (GHOST_TEventNDOFData*) event->getData(); + + const float scale = 1.f / 350.f; // SpaceNavigator sends +/- 350 usually + + // scale *= m_sensitivity; + + data->tx = scale * m_translation[0]; + data->ty = scale * m_translation[1]; + data->tz = scale * m_translation[2]; + + data->rx = scale * m_rotation[0]; + data->ry = scale * m_rotation[1]; + data->rz = scale * m_rotation[2]; + + m_system.pushEvent(event); + + // 'at rest' test goes at the end so that the first 'rest' event gets sent + m_atRest = m_rotation[0] == 0 && m_rotation[1] == 0 && m_rotation[2] == 0 && + m_translation[0] == 0 && m_translation[1] == 0 && m_translation[2] == 0; - ndofLibraryInit = setNdofLibraryInit; - ndofLibraryShutdown = setNdofLibraryShutdown; - ndofDeviceOpen = setNdofDeviceOpen; - - if (ndofLibraryInit && ndofDeviceOpen) - { - Pid= ndofLibraryInit(); -#if 0 - printf("%i client \n", Pid); -#endif - #if defined(_WIN32) || defined(__APPLE__) - m_DeviceHandle = ndofDeviceOpen((void *)¤tNdofValues); - #else - GHOST_SystemX11 *sys; - sys = static_cast(GHOST_ISystem::getSystem()); - void *ndofInfo = sys->prepareNdofInfo(¤tNdofValues); - m_DeviceHandle = ndofDeviceOpen(ndofInfo); - #endif - return (Pid > 0) ? 0 : 1; - - } else - return 1; -} - - -bool -GHOST_NDOFManager::available() const -{ - return m_DeviceHandle != 0; -} - -bool -GHOST_NDOFManager::event_present() const -{ - if( currentNdofValues.changed >0) { - printf("time %llu but%u x%i y%i z%i rx%i ry%i rz%i \n" , - currentNdofValues.time, currentNdofValues.buttons, - currentNdofValues.tx,currentNdofValues.ty,currentNdofValues.tz, - currentNdofValues.rx,currentNdofValues.ry,currentNdofValues.rz); - return true; - }else - return false; - -} - -void GHOST_NDOFManager::GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const -{ - datas.tx = currentNdofValues.tx; - datas.ty = currentNdofValues.ty; - datas.tz = currentNdofValues.tz; - datas.rx = currentNdofValues.rx; - datas.ry = currentNdofValues.ry; - datas.rz = currentNdofValues.rz; - datas.buttons = currentNdofValues.buttons; - datas.client = currentNdofValues.client; - datas.address = currentNdofValues.address; - datas.time = currentNdofValues.time; - datas.delta = currentNdofValues.delta; -} + return true; + } diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 4805707b37b..035f9f22f0a 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -24,28 +24,38 @@ #define _GHOST_NDOFMANAGER_H_ #include "GHOST_System.h" -#include "GHOST_IWindow.h" - class GHOST_NDOFManager { public: - GHOST_NDOFManager(); - virtual ~GHOST_NDOFManager(); - - int deviceOpen(GHOST_IWindow* window, - GHOST_NDOFLibraryInit_fp setNdofLibraryInit, - GHOST_NDOFLibraryShutdown_fp setNdofLibraryShutdown, - GHOST_NDOFDeviceOpen_fp setNdofDeviceOpen); - - void GHOST_NDOFGetDatas(GHOST_TEventNDOFData &datas) const; - - bool available() const; - bool event_present() const; + GHOST_NDOFManager(GHOST_System&); + + virtual ~GHOST_NDOFManager() {}; + + // whether multi-axis functionality is available (via the OS or driver) + // does not imply that a device is plugged in or being used + virtual bool available() = 0; + + // the latest raw data from the device + void updateTranslation(short t[3], GHOST_TUns64 time); + void updateRotation(short r[3], GHOST_TUns64 time); + // this one sends events immediately for changed buttons + void updateButtons(unsigned short b, GHOST_TUns64 time); + + // processes most recent raw data into an NDOFMotion event and sends it + // returns whether an event was sent + bool sendMotionEvent(); protected: - void* m_DeviceHandle; + GHOST_System& m_system; + + short m_translation[3]; + short m_rotation[3]; + unsigned short m_buttons; + + GHOST_TUns64 m_motionTime; + bool m_atRest; }; diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp b/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp new file mode 100644 index 00000000000..6eac4194560 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp @@ -0,0 +1,111 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "GHOST_NDOFManagerCocoa.h" +#include <3DconnexionClient/ConnexionClientAPI.h> +#include + +static void SpaceNavAdded(io_connect_t connection) + { + printf("SpaceNav added\n"); + } + +static void SpaceNavRemoved(io_connect_t connection) + { + printf("SpaceNav removed\n"); + } + +static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void *messageArgument) + { + GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem(); + GHOST_NDOFManager* manager = system->getNDOFManager(); + switch (messageType) + { + case kConnexionMsgDeviceState: + { + ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument; + switch (s->command) + { + case kConnexionCmdHandleAxis: + manager->updateTranslation(s->axis, s->time); + manager->updateRotation(s->axis + 3, s->time); + break; + + case kConnexionCmdHandleButtons: + manager->updateButtons(s->buttons, s->time); + break; + } + break; + } + case kConnexionMsgPrefsChanged: + printf("prefs changed\n"); // this includes app switches + break; + case kConnexionMsgDoAction: + printf("do action\n"); // no idea what this means + // 'calibrate device' in System Prefs sends this + break; + default: + printf(" mystery event\n"); + } + } + +GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) + : GHOST_NDOFManager(sys) + { + if (available()) + { + OSErr error = InstallConnexionHandlers(SpaceNavEvent, SpaceNavAdded, SpaceNavRemoved); + if (error) + { + printf(" error = %d\n", error); + return; + } + +// char* name = "\pBlender"; +// name[0] = 7; // convert to Pascal string + + m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pBlender"/*name*/, + kConnexionClientModeTakeOver, kConnexionMaskAll); + + printf("client id = %d\n", m_clientID); + } + else + { + printf(" SpaceNav driver not found\n"); + // This isn't a hard error, just means the user doesn't have a SpaceNavigator. + } + } + +GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() + { + UnregisterConnexionClient(m_clientID); + CleanupConnexionHandlers(); + } + +bool GHOST_NDOFManagerCocoa::available() + { + extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); +// [mce] C likes the above line, but Obj-C++ does not. Make sure it works for +// machines without the driver installed! Try it on the QuickSilver. + + return InstallConnexionHandlers != NULL; + } diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h new file mode 100644 index 00000000000..07c4ceb7a60 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h @@ -0,0 +1,45 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef _GHOST_NDOFMANAGERCOCOA_H_ +#define _GHOST_NDOFMANAGERCOCOA_H_ + +#include "GHOST_NDOFManager.h" + + +class GHOST_NDOFManagerCocoa : public GHOST_NDOFManager +{ +public: + GHOST_NDOFManagerCocoa(GHOST_System&); + + ~GHOST_NDOFManagerCocoa(); + + // whether multi-axis functionality is available (via the OS or driver) + // does not imply that a device is plugged in or being used + bool available(); + +private: + unsigned short m_clientID; +}; + + +#endif -- cgit v1.2.3 From 195ad03901e4e3e639ce89fec42118e975356064 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 22 Jul 2010 09:30:01 +0000 Subject: more preliminary NDOF handling stuff (untested) --- intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp | 9 +-- intern/ghost/intern/GHOST_NDOFManagerCocoa.h | 2 + intern/ghost/intern/GHOST_NDOFManagerWin32.h | 46 +++++++++++++++ intern/ghost/intern/GHOST_NDOFManagerX11.h | 46 +++++++++++++++ intern/ghost/intern/GHOST_SystemCocoa.mm | 11 +--- intern/ghost/intern/GHOST_SystemWin32.cpp | 19 +++++-- intern/ghost/intern/GHOST_SystemX11.cpp | 78 +++++++++++++++++--------- intern/ghost/intern/GHOST_SystemX11.h | 3 +- 8 files changed, 166 insertions(+), 48 deletions(-) create mode 100644 intern/ghost/intern/GHOST_NDOFManagerWin32.h create mode 100644 intern/ghost/intern/GHOST_NDOFManagerX11.h diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp b/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp index 6eac4194560..0196b2974dd 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp @@ -80,10 +80,8 @@ GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) return; } -// char* name = "\pBlender"; -// name[0] = 7; // convert to Pascal string - - m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pBlender"/*name*/, + // Pascal string *and* a four-letter constant. How old-skool. + m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pBlender", kConnexionClientModeTakeOver, kConnexionMaskAll); printf("client id = %d\n", m_clientID); @@ -104,8 +102,5 @@ GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() bool GHOST_NDOFManagerCocoa::available() { extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); -// [mce] C likes the above line, but Obj-C++ does not. Make sure it works for -// machines without the driver installed! Try it on the QuickSilver. - return InstallConnexionHandlers != NULL; } diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h index 07c4ceb7a60..4f2a2274e35 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h @@ -25,6 +25,8 @@ #include "GHOST_NDOFManager.h" +// Event capture is handled within the NDOFManager on Macintosh, +// so there's no need for SystemCocoa to look for them. class GHOST_NDOFManagerCocoa : public GHOST_NDOFManager { diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.h b/intern/ghost/intern/GHOST_NDOFManagerWin32.h new file mode 100644 index 00000000000..a09808dbe38 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.h @@ -0,0 +1,46 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef _GHOST_NDOFMANAGERWIN32_H_ +#define _GHOST_NDOFMANAGERWIN32_H_ + +#include "GHOST_NDOFManager.h" + + +class GHOST_NDOFManagerWin32 : public GHOST_NDOFManager +{ +public: + GHOST_NDOFManagerWin32(GHOST_System& sys) + : GHOST_NDOFManager(sys) + {} + + // whether multi-axis functionality is available (via the OS or driver) + // does not imply that a device is plugged in or being used + bool available() + { + // always available since RawInput is built into Windows + return true; + } +}; + + +#endif diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.h b/intern/ghost/intern/GHOST_NDOFManagerX11.h new file mode 100644 index 00000000000..8f9c819a481 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.h @@ -0,0 +1,46 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef _GHOST_NDOFMANAGERX11_H_ +#define _GHOST_NDOFMANAGERX11_H_ + +#include "GHOST_NDOFManager.h" + + +class GHOST_NDOFManagerX11 : public GHOST_NDOFManager +{ +public: + GHOST_NDOFManagerX11(GHOST_System& sys) + : GHOST_NDOFManager(sys) + {} + + // whether multi-axis functionality is available (via the OS or driver) + // does not imply that a device is plugged in or being used + bool available() + { + // never available since I've not yet written it! + return false; + } +}; + + +#endif diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 91da1fb2d4b..1ab0794548e 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -54,7 +54,7 @@ #include "GHOST_TimerTask.h" #include "GHOST_WindowManager.h" #include "GHOST_WindowCocoa.h" -#include "GHOST_NDOFManager.h" +#include "GHOST_NDOFManagerCocoa.h" #include "AssertMacros.h" #pragma mark KeyMap, mouse converters @@ -601,13 +601,8 @@ GHOST_TSuccess GHOST_SystemCocoa::init() { GHOST_TSuccess success = GHOST_System::init(); if (success) { - //ProcessSerialNumber psn; - - //Carbon stuff to move window & menu to foreground - /*if (!GetCurrentProcess(&psn)) { - TransformProcessType(&psn, kProcessTransformToForegroundApplication); - SetFrontProcess(&psn); - }*/ + + m_ndofManager = new GHOST_NDOFManagerCocoa(*this); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; if (NSApp == nil) { diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 829f0997377..14b6b16e6fb 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -73,7 +73,7 @@ #include "GHOST_TimerManager.h" #include "GHOST_WindowManager.h" #include "GHOST_WindowWin32.h" -#include "GHOST_NDOFManager.h" +#include "GHOST_NDOFManagerWin32.h" // Key code values not found in winuser.h #ifndef VK_MINUS @@ -347,6 +347,8 @@ GHOST_TSuccess GHOST_SystemWin32::init() { GHOST_TSuccess success = GHOST_System::init(); + m_ndofManager = new GHOST_NDOFManagerWin32(*this); + /* Disable scaling on high DPI displays on Vista */ HMODULE user32 = ::LoadLibraryA("user32.dll"); typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)(); @@ -736,9 +738,6 @@ vendor ID No other registered devices use the c62_ space, so a simple mask will work! */ - short t[3], r[3]; // defined here just for quick testing, - unsigned short buttons; // will maintain shared copy for all NDOF events - // multiple events per RAWHID? MSDN hints at this. printf("%d events\n", raw.data.hid.dwCount); @@ -754,14 +753,24 @@ No other registered devices use the c62_ space, so a simple mask will work! switch (packetType) { case 1: // translation + { + short t[3]; memcpy(t, data + 1, sizeof(t)); printf("T: %+5d %+5d %+5d\n", t[0], t[1], t[2]); + m_ndofManager->updateTranslation(t, getMilliseconds()); break; + } case 2: // rotation + { + short r[3]; memcpy(r, data + 1, sizeof(r)); printf("R: %+5d %+5d %+5d\n", r[0], r[1], r[2]); + m_ndofManager->updateRotation(r, getMilliseconds()); break; + } case 3: // buttons + { + unsigned short buttons; memcpy(&buttons, data + 1, sizeof(buttons)); printf("buttons:"); if (buttons) @@ -774,7 +783,9 @@ No other registered devices use the c62_ space, so a simple mask will work! } else printf(" none\n"); + m_ndofManager->updateButtons(buttons, getMilliseconds()); break; + } } } diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 1ae9b666c6b..a70162a5039 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -38,14 +38,14 @@ #include "GHOST_EventButton.h" #include "GHOST_EventWheel.h" #include "GHOST_EventNDOF.h" -#include "GHOST_NDOFManager.h" +#include "GHOST_NDOFManagerX11.h" #include "GHOST_DisplayManagerX11.h" #include "GHOST_Debug.h" #include #include -#include /* allow detectable autorepeate */ +#include /* allow detectable autorepeat */ #ifdef __sgi @@ -67,10 +67,11 @@ #include // for fprintf only #include // for exit +// [mce] these are for communication with the plugin typedef struct NDOFPlatformInfo { Display *display; Window window; - volatile GHOST_TEventNDOFData *currValues; +// volatile GHOST_TEventNDOFData *currValues; Atom cmdAtom; Atom motionAtom; Atom btnPressAtom; @@ -79,7 +80,6 @@ typedef struct NDOFPlatformInfo { static NDOFPlatformInfo sNdofInfo = {NULL, 0, NULL, 0, 0, 0, 0}; - //these are for copy and select copy static char *txt_cut_buffer= NULL; static char *txt_select_buffer= NULL; @@ -142,7 +142,7 @@ GHOST_SystemX11( m_start_time = GHOST_TUns64(tv.tv_sec*1000 + tv.tv_usec/1000); - /* use detectable autorepeate, mac and windows also do this */ + /* use detectable autorepeat, mac and windows also do this */ int use_xkb; int xkb_opcode, xkb_event, xkb_error; int xkb_major = XkbMajorVersion, xkb_minor = XkbMinorVersion; @@ -168,6 +168,9 @@ init( GHOST_TSuccess success = GHOST_System::init(); if (success) { + + m_ndofManager = new GHOST_NDOFManagerX11; + m_displayManager = new GHOST_DisplayManagerX11(this); if (m_displayManager) { @@ -246,9 +249,6 @@ createWindow( GHOST_WindowX11 * window = 0; if (!m_display) return 0; - - - window = new GHOST_WindowX11 ( this,m_display,title, left, top, width, height, state, parentWindow, type, stereoVisual @@ -628,29 +628,49 @@ GHOST_SystemX11::processEvent(XEvent *xe) } else #endif if (sNdofInfo.currValues) { - static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0}; +// static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0}; if (xcme.message_type == sNdofInfo.motionAtom) { - data.changed = 1; - data.delta = xcme.data.s[8] - data.time; - data.time = xcme.data.s[8]; - data.tx = xcme.data.s[2] >> 2; - data.ty = xcme.data.s[3] >> 2; - data.tz = xcme.data.s[4] >> 2; - data.rx = xcme.data.s[5]; - data.ry = xcme.data.s[6]; - data.rz =-xcme.data.s[7]; - g_event = new GHOST_EventNDOF(getMilliSeconds(), - GHOST_kEventNDOFMotion, - window, data); +// data.changed = 1; +// data.delta = xcme.data.s[8] - data.time; +// data.time = xcme.data.s[8]; +// data.tx = xcme.data.s[2] >> 2; +// data.ty = xcme.data.s[3] >> 2; +// data.tz = xcme.data.s[4] >> 2; +// data.rx = xcme.data.s[5]; +// data.ry = xcme.data.s[6]; +// data.rz =-xcme.data.s[7]; + + short t[3], r[3]; + t[0] = xcme.data.s[2] >> 2; + t[1] = xcme.data.s[3] >> 2; + t[2] = xcme.data.s[4] >> 2; + r[0] = xcme.data.s[5]; + r[1] = xcme.data.s[6]; + r[2] =-xcme.data.s[7]; + + // [mce] look into this soon, as in find out why some values + // are shifted and where this message originates. + + m_ndofManager->updateTranslation(t, getMilliseconds); + m_ndofManager->updateRotation(r, getMilliseconds); + +// g_event = new GHOST_EventNDOF(getMilliSeconds(), +// GHOST_kEventNDOFMotion, +// window, data); + } else if (xcme.message_type == sNdofInfo.btnPressAtom) { - data.changed = 2; - data.delta = xcme.data.s[8] - data.time; - data.time = xcme.data.s[8]; - data.buttons = xcme.data.s[2]; - g_event = new GHOST_EventNDOF(getMilliSeconds(), - GHOST_kEventNDOFButton, - window, data); +// data.changed = 2; +// data.delta = xcme.data.s[8] - data.time; +// data.time = xcme.data.s[8]; +// data.buttons = xcme.data.s[2]; + + unsigned short buttons = xcme.data.s[2]; + m_ndofManager->updateButtons(buttons, getMilliseconds()); + +// g_event = new GHOST_EventNDOF(getMilliSeconds(), +// GHOST_kEventNDOFButton, +// window, data); } } else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) { XWindowAttributes attr; @@ -814,6 +834,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) } } +/* void * GHOST_SystemX11:: prepareNdofInfo(volatile GHOST_TEventNDOFData *currentNdofValues) @@ -825,6 +846,7 @@ prepareNdofInfo(volatile GHOST_TEventNDOFData *currentNdofValues) sNdofInfo.currValues = currentNdofValues; return (void*)&sNdofInfo; } +*/ GHOST_TSuccess GHOST_SystemX11:: diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index ee6cbedb2ae..d00f83aa8ea 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -202,10 +202,12 @@ public: return m_display; } +/* [mce] is this needed? void * prepareNdofInfo( volatile GHOST_TEventNDOFData *current_values ); +*/ /* Helped function for get data from the clipboard. */ void getClipboard_xcout(XEvent evt, Atom sel, Atom target, @@ -317,4 +319,3 @@ private : }; #endif - -- cgit v1.2.3 From 47ea957c9d91ec03aeceaf241d9cd5b898ba811c Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 23 Jul 2010 06:36:08 +0000 Subject: provided a way for NDOF manager to poke SystemCocoa about out-of-loop events --- intern/ghost/intern/GHOST_SystemCocoa.h | 12 ++++++++---- intern/ghost/intern/GHOST_SystemCocoa.mm | 7 +++++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index 0949dca5acc..08cb5037981 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -234,14 +234,18 @@ public: * @return Indication whether the event was handled. */ GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window); - + /** * Handles the Cocoa event telling the application has become active (again) * @return Indication whether the event was handled. */ GHOST_TSuccess handleApplicationBecomeActiveEvent(); - - + + /** + * External objects should call this when they send an event outside processEvents. + */ + void notifyExternalEventProcessed(); + protected: /** * Initializes the system. @@ -298,7 +302,7 @@ protected: /** Start time at initialization. */ GHOST_TUns64 m_start_time; - /** Event has been processed directly by Cocoa and has sent a ghost event to be dispatched */ + /** Event has been processed directly by Cocoa (or NDOF manager) and has sent a ghost event to be dispatched */ bool m_outsideLoopEventProcessed; /** Raised window is not yet known by the window manager, so delay application become active event handling */ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 1ab0794548e..05bc93f937d 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -994,6 +994,8 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) if (m_needDelayedApplicationBecomeActiveEventProcessing) handleApplicationBecomeActiveEvent(); +// m_outsideLoopEventProcessed |= m_ndofManager->sendMotionEvent(); + if (m_outsideLoopEventProcessed) { m_outsideLoopEventProcessed = false; return true; @@ -1038,6 +1040,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() return GHOST_kSuccess; } +void GHOST_SystemCocoa::notifyExternalEventProcessed() +{ + m_outsideLoopEventProcessed = true; +} + //Note: called from NSWindow delegate GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window) { -- cgit v1.2.3 From 6216199af8d5046d25a2b74983cc2f86904f0553 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 23 Jul 2010 06:45:59 +0000 Subject: SpaceNav event capture for MacOS, dispatch for all platforms. To compile this, you need their Mac driver installed and to send '-weak_framework 3DconnexionClient' to the linker. I'm also exploring a HID Manager version, bypassing their driver (and any licensing issues). --- intern/ghost/intern/GHOST_NDOFManager.cpp | 3 +++ intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp | 15 +++++++++++---- intern/ghost/intern/GHOST_System.cpp | 3 +++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 787811fc69b..120805733b4 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -79,6 +79,9 @@ 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); + fflush(stdout); + m_system.pushEvent(event); // 'at rest' test goes at the end so that the first 'rest' event gets sent diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp b/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp index 0196b2974dd..c4a8a2f1831 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp @@ -21,8 +21,12 @@ */ #include "GHOST_NDOFManagerCocoa.h" -#include <3DconnexionClient/ConnexionClientAPI.h> -#include +#include "GHOST_SystemCocoa.h" + +extern "C" { + #include <3DconnexionClient/ConnexionClientAPI.h> + #include + } static void SpaceNavAdded(io_connect_t connection) { @@ -36,7 +40,7 @@ static void SpaceNavRemoved(io_connect_t connection) static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void *messageArgument) { - GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem(); + GHOST_SystemCocoa* system = (GHOST_SystemCocoa*) GHOST_ISystem::getSystem(); GHOST_NDOFManager* manager = system->getNDOFManager(); switch (messageType) { @@ -48,10 +52,12 @@ static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void * case kConnexionCmdHandleAxis: manager->updateTranslation(s->axis, s->time); manager->updateRotation(s->axis + 3, s->time); + system->notifyExternalEventProcessed(); break; case kConnexionCmdHandleButtons: manager->updateButtons(s->buttons, s->time); + system->notifyExternalEventProcessed(); break; } break; @@ -101,6 +107,7 @@ GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() bool GHOST_NDOFManagerCocoa::available() { - extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); +// extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); +// ^-- not needed since the entire framework is weak-linked return InstallConnexionHandlers != NULL; } diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 70ff5a02924..4e0888a87a7 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -196,6 +196,9 @@ bool GHOST_System::getFullScreen(void) bool GHOST_System::dispatchEvents() { + // NDOF Motion event is sent only once per dispatch, so do it now: + m_ndofManager->sendMotionEvent(); + bool handled; if (m_eventManager) { if (m_input_fidelity_hint == LO_FI) -- cgit v1.2.3 From c4c46e4403826a850b4f2fe735ee38560235c95c Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 23 Jul 2010 10:03:22 +0000 Subject: mostly formatting: put SystemCocoa on a diet of a thousand tabs, also spotted and fixed a leaky switch-case (trackpad gesture for 'rotate') --- intern/ghost/intern/GHOST_SystemCocoa.mm | 581 +++++++++++++++---------------- 1 file changed, 282 insertions(+), 299 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 05bc93f937d..3ab69ac3f64 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -235,8 +235,8 @@ static GHOST_TButtonMask convertButton(int button) * @return Ghost key code */ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) -{ - +{ + //printf("\nrecvchar %c 0x%x",recvChar,recvChar); switch (rawCode) { /*Physical keycodes not used due to map changes in int'l keyboards @@ -266,7 +266,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) case kVK_ANSI_X: return GHOST_kKeyX; case kVK_ANSI_Y: return GHOST_kKeyY; case kVK_ANSI_Z: return GHOST_kKeyZ;*/ - + /* Numbers keys mapped to handle some int'l keyboard (e.g. French)*/ case kVK_ISO_Section: return GHOST_kKeyUnknown; case kVK_ANSI_1: return GHOST_kKey1; @@ -279,7 +279,7 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) case kVK_ANSI_8: return GHOST_kKey8; case kVK_ANSI_9: return GHOST_kKey9; case kVK_ANSI_0: return GHOST_kKey0; - + case kVK_ANSI_Keypad0: return GHOST_kKeyNumpad0; case kVK_ANSI_Keypad1: return GHOST_kKeyNumpad1; case kVK_ANSI_Keypad2: return GHOST_kKeyNumpad2; @@ -318,24 +318,24 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) case kVK_F18: return GHOST_kKeyF18; case kVK_F19: return GHOST_kKeyF19; case kVK_F20: return GHOST_kKeyF20; - + case kVK_UpArrow: return GHOST_kKeyUpArrow; case kVK_DownArrow: return GHOST_kKeyDownArrow; case kVK_LeftArrow: return GHOST_kKeyLeftArrow; case kVK_RightArrow: return GHOST_kKeyRightArrow; - + case kVK_Return: return GHOST_kKeyEnter; case kVK_Delete: return GHOST_kKeyBackSpace; case kVK_ForwardDelete: return GHOST_kKeyDelete; case kVK_Escape: return GHOST_kKeyEsc; case kVK_Tab: return GHOST_kKeyTab; case kVK_Space: return GHOST_kKeySpace; - + case kVK_Home: return GHOST_kKeyHome; case kVK_End: return GHOST_kKeyEnd; case kVK_PageUp: return GHOST_kKeyUpPage; case kVK_PageDown: return GHOST_kKeyDownPage; - + /*case kVK_ANSI_Minus: return GHOST_kKeyMinus; case kVK_ANSI_Equal: return GHOST_kKeyEqual; case kVK_ANSI_Comma: return GHOST_kKeyComma; @@ -347,12 +347,12 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) case kVK_ANSI_LeftBracket: return GHOST_kKeyLeftBracket; case kVK_ANSI_RightBracket: return GHOST_kKeyRightBracket; case kVK_ANSI_Grave: return GHOST_kKeyAccentGrave;*/ - + case kVK_VolumeUp: case kVK_VolumeDown: case kVK_Mute: return GHOST_kKeyUnknown; - + default: /* alphanumerical or punctuation key that is remappable in int'l keyboards */ if ((recvChar >= 'A') && (recvChar <= 'Z')) { @@ -363,42 +363,38 @@ static GHOST_TKey convertKey(int rawCode, unichar recvChar, UInt16 keyAction) #if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 KeyboardLayoutRef keyLayout; UCKeyboardLayout *uchrData; - + KLGetCurrentKeyboardLayout(&keyLayout); KLGetKeyboardLayoutProperty(keyLayout, kKLuchrData, (const void **) &uchrData); /*get actual character value of the "remappable" keys in int'l keyboards, if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger), then fallback on using the received charactersIgnoringModifiers */ - if (uchrData) - { + if (uchrData) { UInt32 deadKeyState=0; UniCharCount actualStrLength=0; - + UCKeyTranslate(uchrData, rawCode, keyAction, 0, - LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar); - - } + LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar); + } #else /* Leopard and Snow Leopard 64bit compatible API*/ CFDataRef uchrHandle; /*the keyboard layout*/ TISInputSourceRef kbdTISHandle; - + kbdTISHandle = TISCopyCurrentKeyboardLayoutInputSource(); uchrHandle = (CFDataRef)TISGetInputSourceProperty(kbdTISHandle,kTISPropertyUnicodeKeyLayoutData); CFRelease(kbdTISHandle); - + /*get actual character value of the "remappable" keys in int'l keyboards, if keyboard layout is not correctly reported (e.g. some non Apple keyboards in Tiger), then fallback on using the received charactersIgnoringModifiers */ - if (uchrHandle) - { + if (uchrHandle) { UInt32 deadKeyState=0; UniCharCount actualStrLength=0; - + UCKeyTranslate((UCKeyboardLayout*)CFDataGetBytePtr(uchrHandle), rawCode, keyAction, 0, LMGetKbdType(), kUCKeyTranslateNoDeadKeysBit, &deadKeyState, 1, &actualStrLength, &recvChar); - } #endif switch (recvChar) { @@ -476,9 +472,9 @@ int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op) { int result; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + result = fromcocoa_request_qtcodec_settings(C, op); - + [pool drain]; return result; } @@ -549,7 +545,7 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() struct timeval boottime; size_t len; char *rstring = NULL; - + m_modifierMask =0; m_pressedMouseButtons =0; m_isGestureInProgress = false; @@ -568,27 +564,27 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() mib[0] = CTL_KERN; mib[1] = KERN_BOOTTIME; len = sizeof(struct timeval); - + sysctl(mib, 2, &boottime, &len, NULL, 0); m_start_time = ((boottime.tv_sec*1000)+(boottime.tv_usec/1000)); - + //Detect multitouch trackpad mib[0] = CTL_HW; mib[1] = HW_MODEL; sysctl( mib, 2, NULL, &len, NULL, 0 ); rstring = (char*)malloc( len ); sysctl( mib, 2, rstring, &len, NULL, 0 ); - + //Hack on MacBook revision, as multitouch avail. function missing m_hasMultiTouchTrackpad = (strstr(rstring,"MacBookAir") || (strstr(rstring,"MacBook") && (rstring[strlen(rstring)-3]>='5') && (rstring[strlen(rstring)-3]<='9'))); - + free( rstring ); rstring = NULL; - + m_ignoreWindowSizedMessages = false; - + m_input_fidelity_hint = HI_FI; // just for testing... } @@ -599,63 +595,63 @@ GHOST_SystemCocoa::~GHOST_SystemCocoa() GHOST_TSuccess GHOST_SystemCocoa::init() { - GHOST_TSuccess success = GHOST_System::init(); - if (success) { + GHOST_TSuccess success = GHOST_System::init(); + if (success) { m_ndofManager = new GHOST_NDOFManagerCocoa(*this); NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; if (NSApp == nil) { [NSApplication sharedApplication]; - + if ([NSApp mainMenu] == nil) { NSMenu *mainMenubar = [[NSMenu alloc] init]; NSMenuItem *menuItem; NSMenu *windowMenu; NSMenu *appMenu; - + //Create the application menu appMenu = [[NSMenu alloc] initWithTitle:@"Blender"]; - + [appMenu addItemWithTitle:@"About Blender" action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; [appMenu addItem:[NSMenuItem separatorItem]]; - + menuItem = [appMenu addItemWithTitle:@"Hide Blender" action:@selector(hide:) keyEquivalent:@"h"]; [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; - + menuItem = [appMenu addItemWithTitle:@"Hide others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask | NSCommandKeyMask)]; - + [appMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - + menuItem = [appMenu addItemWithTitle:@"Quit Blender" action:@selector(terminate:) keyEquivalent:@"q"]; [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; - + menuItem = [[NSMenuItem alloc] init]; [menuItem setSubmenu:appMenu]; - + [mainMenubar addItem:menuItem]; [menuItem release]; [NSApp performSelector:@selector(setAppleMenu:) withObject:appMenu]; //Needed for 10.5 [appMenu release]; - + //Create the window menu windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - + menuItem = [windowMenu addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; - + [windowMenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""]; - + menuItem = [windowMenu addItemWithTitle:@"Close" action:@selector(performClose:) keyEquivalent:@"w"]; [menuItem setKeyEquivalentModifierMask:NSCommandKeyMask]; - + menuItem = [[NSMenuItem alloc] init]; [menuItem setSubmenu:windowMenu]; - + [mainMenubar addItem:menuItem]; [menuItem release]; - + [NSApp setMainMenu:mainMenubar]; [NSApp setWindowsMenu:windowMenu]; [windowMenu release]; @@ -666,12 +662,12 @@ GHOST_TSuccess GHOST_SystemCocoa::init() [appDelegate setSystemCocoa:this]; [NSApp setDelegate:appDelegate]; } - + [NSApp finishLaunching]; - + [pool drain]; - } - return success; + } + return success; } @@ -681,11 +677,10 @@ GHOST_TUns64 GHOST_SystemCocoa::getMilliSeconds() const { //Cocoa equivalent exists in 10.6 ([[NSProcessInfo processInfo] systemUptime]) struct timeval currentTime; - + gettimeofday(¤tTime, NULL); - + //Return timestamp of system uptime - return ((currentTime.tv_sec*1000)+(currentTime.tv_usec/1000)-m_start_time); } @@ -708,11 +703,11 @@ void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; //Get visible frame, that is frame excluding dock and top menu bar NSRect frame = [[NSScreen mainScreen] visibleFrame]; - + //Returns max window contents (excluding title bar...) NSRect contentRect = [NSWindow contentRectForFrameRect:frame styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)]; - + width = contentRect.size.width; height = contentRect.size.height; @@ -721,7 +716,7 @@ void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns GHOST_IWindow* GHOST_SystemCocoa::createWindow( - const STR_String& title, + const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, @@ -733,59 +728,58 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( const GHOST_TEmbedderWindowID parentWindow ) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_IWindow* window = 0; - + //Get the available rect for including window contents NSRect frame = [[NSScreen mainScreen] visibleFrame]; NSRect contentRect = [NSWindow contentRectForFrameRect:frame styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask)]; - + //Ensures window top left is inside this available rect left = left > contentRect.origin.x ? left : contentRect.origin.x; top = top > contentRect.origin.y ? top : contentRect.origin.y; - + window = new GHOST_WindowCocoa (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples); - if (window) { - if (window->getValid()) { - // Store the pointer to the window - GHOST_ASSERT(m_windowManager, "m_windowManager not initialized"); - m_windowManager->addWindow(window); - m_windowManager->setActiveWindow(window); + if (window) { + if (window->getValid()) { + // Store the pointer to the window + GHOST_ASSERT(m_windowManager, "m_windowManager not initialized"); + m_windowManager->addWindow(window); + m_windowManager->setActiveWindow(window); //Need to tell window manager the new window is the active one (Cocoa does not send the event activate upon window creation) - pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window)); + pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window)); pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window)); - - } - else { - GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n"); - delete window; - window = 0; - } - } + } + else { + GHOST_PRINT("GHOST_SystemCocoa::createWindow(): window invalid\n"); + delete window; + window = 0; + } + } else { GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n"); } [pool drain]; - return window; + return window; } GHOST_TSuccess GHOST_SystemCocoa::beginFullScreen(const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual) -{ +{ GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow(); *window = currentWindow; - + if(!currentWindow) return GHOST_kFailure; - + return currentWindow->setState(GHOST_kWindowStateFullScreen); } GHOST_TSuccess GHOST_SystemCocoa::endFullScreen(void) -{ +{ GHOST_IWindow* currentWindow = m_windowManager->getActiveWindow(); if(!currentWindow) return GHOST_kFailure; - + return currentWindow->setState(GHOST_kWindowStateNormal); } @@ -796,12 +790,13 @@ GHOST_TSuccess GHOST_SystemCocoa::endFullScreen(void) */ GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const { - NSPoint mouseLoc = [NSEvent mouseLocation]; - - // Returns the mouse location in screen coordinates - x = (GHOST_TInt32)mouseLoc.x; - y = (GHOST_TInt32)mouseLoc.y; - return GHOST_kSuccess; + NSPoint mouseLoc = [NSEvent mouseLocation]; + + // Returns the mouse location in screen coordinates + x = (GHOST_TInt32)mouseLoc.x; + y = (GHOST_TInt32)mouseLoc.y; + + return GHOST_kSuccess; } /** @@ -814,12 +809,12 @@ GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 if (!window) return GHOST_kFailure; setMouseCursorPosition(x, y); - + //Force mouse move event (not pushed by Cocoa) window->screenToClient(x, y, wx, wy); pushEvent(new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, wx,wy)); m_outsideLoopEventProcessed = true; - + return GHOST_kSuccess; } @@ -832,18 +827,18 @@ GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(float xf, float yf) NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSScreen *windowScreen = window->getScreen(); NSRect screenRect = [windowScreen frame]; - + //Set position relative to current screen xf -= screenRect.origin.x; yf -= screenRect.origin.y; - + //Quartz Display Services uses the old coordinates (top left origin) yf = screenRect.size.height -yf; - + CGDisplayMoveCursorToPoint((CGDirectDisplayID)[[[windowScreen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue], CGPointMake(xf, yf)); [pool drain]; - return GHOST_kSuccess; + return GHOST_kSuccess; } @@ -853,19 +848,19 @@ GHOST_TSuccess GHOST_SystemCocoa::getModifierKeys(GHOST_ModifierKeys& keys) cons keys.set(GHOST_kModifierKeyLeftAlt, (m_modifierMask & NSAlternateKeyMask) ? true : false); keys.set(GHOST_kModifierKeyLeftShift, (m_modifierMask & NSShiftKeyMask) ? true : false); keys.set(GHOST_kModifierKeyLeftControl, (m_modifierMask & NSControlKeyMask) ? true : false); - - return GHOST_kSuccess; + + return GHOST_kSuccess; } GHOST_TSuccess GHOST_SystemCocoa::getButtons(GHOST_Buttons& buttons) const { buttons.clear(); - buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft); + buttons.set(GHOST_kButtonMaskLeft, m_pressedMouseButtons & GHOST_kButtonMaskLeft); buttons.set(GHOST_kButtonMaskRight, m_pressedMouseButtons & GHOST_kButtonMaskRight); buttons.set(GHOST_kButtonMaskMiddle, m_pressedMouseButtons & GHOST_kButtonMaskMiddle); buttons.set(GHOST_kButtonMaskButton4, m_pressedMouseButtons & GHOST_kButtonMaskButton4); buttons.set(GHOST_kButtonMaskButton5, m_pressedMouseButtons & GHOST_kButtonMaskButton5); - return GHOST_kSuccess; + return GHOST_kSuccess; } @@ -975,10 +970,10 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) case NSEventTypeGesture: case NSEventTypeSwipe: break; */ - + default: break; - /* Unused events: + /* Unused events: NSMouseEntered = 8, NSMouseExited = 9, NSAppKitDefined = 13, @@ -988,20 +983,18 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) NSCursorUpdate = 17,*/ } } while (event != nil); - + [pool drain]; - + if (m_needDelayedApplicationBecomeActiveEventProcessing) handleApplicationBecomeActiveEvent(); - -// m_outsideLoopEventProcessed |= m_ndofManager->sendMotionEvent(); - + if (m_outsideLoopEventProcessed) { m_outsideLoopEventProcessed = false; return true; } - - return anyProcessed; + + return anyProcessed; } @@ -1012,7 +1005,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() //(that is when update events are sent to another application) unsigned int modifiers; GHOST_IWindow* window = m_windowManager->getActiveWindow(); - + if (!window) { m_needDelayedApplicationBecomeActiveEventProcessing = true; return GHOST_kFailure; @@ -1020,7 +1013,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() else m_needDelayedApplicationBecomeActiveEventProcessing = false; modifiers = [[[NSApplication sharedApplication] currentEvent] modifierFlags]; - + if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) { pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) ); } @@ -1033,9 +1026,9 @@ GHOST_TSuccess GHOST_SystemCocoa::handleApplicationBecomeActiveEvent() if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) { pushEvent( new GHOST_EventKey(getMilliSeconds(), (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) ); } - + m_modifierMask = modifiers; - + m_outsideLoopEventProcessed = true; return GHOST_kSuccess; } @@ -1051,37 +1044,36 @@ GHOST_TSuccess GHOST_SystemCocoa::handleWindowEvent(GHOST_TEventType eventType, if (!validWindow(window)) { return GHOST_kFailure; } - switch(eventType) - { - case GHOST_kEventWindowClose: - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) ); - break; - case GHOST_kEventWindowActivate: - m_windowManager->setActiveWindow(window); - window->loadCursor(window->getCursorVisibility(), window->getCursorShape()); - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) ); - break; - case GHOST_kEventWindowDeactivate: - m_windowManager->setWindowInactive(window); - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) ); - break; - case GHOST_kEventWindowUpdate: - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) ); - break; - case GHOST_kEventWindowMove: - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window) ); - break; - case GHOST_kEventWindowSize: - if (!m_ignoreWindowSizedMessages) - { - window->updateDrawingContext(); - pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); - } - break; - default: - return GHOST_kFailure; - break; - } + + switch(eventType) { + case GHOST_kEventWindowClose: + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window) ); + break; + case GHOST_kEventWindowActivate: + m_windowManager->setActiveWindow(window); + window->loadCursor(window->getCursorVisibility(), window->getCursorShape()); + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window) ); + break; + case GHOST_kEventWindowDeactivate: + m_windowManager->setWindowInactive(window); + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window) ); + break; + case GHOST_kEventWindowUpdate: + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window) ); + break; + case GHOST_kEventWindowMove: + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window) ); + break; + case GHOST_kEventWindowSize: + if (!m_ignoreWindowSizedMessages) { + window->updateDrawingContext(); + pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); + } + break; + default: + return GHOST_kFailure; + break; + } m_outsideLoopEventProcessed = true; return GHOST_kSuccess; @@ -1094,76 +1086,76 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType if (!validWindow(window)) { return GHOST_kFailure; } - switch(eventType) - { + + switch(eventType) { case GHOST_kEventDraggingEntered: case GHOST_kEventDraggingUpdated: case GHOST_kEventDraggingExited: pushEvent(new GHOST_EventDragnDrop(getMilliSeconds(),eventType,draggedObjectType,window,mouseX,mouseY,NULL)); break; - + case GHOST_kEventDraggingDropDone: { GHOST_TUns8 * temp_buff; GHOST_TStringArray *strArray; NSArray *droppedArray; - size_t pastedTextSize; + size_t pastedTextSize; NSString *droppedStr; GHOST_TEventDataPtr eventData; int i; if (!data) return GHOST_kFailure; - + switch (draggedObjectType) { case GHOST_kDragnDropTypeFilenames: droppedArray = (NSArray*)data; - + strArray = (GHOST_TStringArray*)malloc(sizeof(GHOST_TStringArray)); if (!strArray) return GHOST_kFailure; - + strArray->count = [droppedArray count]; if (strArray->count == 0) return GHOST_kFailure; - + strArray->strings = (GHOST_TUns8**) malloc(strArray->count*sizeof(GHOST_TUns8*)); - + for (i=0;icount;i++) { droppedStr = [droppedArray objectAtIndex:i]; - + pastedTextSize = [droppedStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; - temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); - + temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); + if (!temp_buff) { strArray->count = i; break; } - + strncpy((char*)temp_buff, [droppedStr cStringUsingEncoding:NSUTF8StringEncoding], pastedTextSize); temp_buff[pastedTextSize] = '\0'; - + strArray->strings[i] = temp_buff; } - eventData = (GHOST_TEventDataPtr) strArray; + eventData = (GHOST_TEventDataPtr) strArray; break; - + case GHOST_kDragnDropTypeString: droppedStr = (NSString*)data; pastedTextSize = [droppedStr lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; - + temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); - + if (temp_buff == NULL) { return GHOST_kFailure; } - + strncpy((char*)temp_buff, [droppedStr cStringUsingEncoding:NSUTF8StringEncoding], pastedTextSize); - + temp_buff[pastedTextSize] = '\0'; - + eventData = (GHOST_TEventDataPtr) temp_buff; break; - + case GHOST_kDragnDropTypeBitmap: { NSImage *droppedImg = (NSImage*)data; @@ -1176,13 +1168,13 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType NSBitmapImageRep *blBitmapFormatImageRGB,*blBitmapFormatImageRGBA,*bitmapImage=nil; NSEnumerator *enumerator; NSImageRep *representation; - + ibuf = IMB_allocImBuf (imgSize.width , imgSize.height, 32, IB_rect, 0); if (!ibuf) { [droppedImg release]; return GHOST_kFailure; } - + /*Get the bitmap of the image*/ enumerator = [[droppedImg representations] objectEnumerator]; while ((representation = [enumerator nextObject])) { @@ -1192,7 +1184,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType } } if (bitmapImage == nil) return GHOST_kFailure; - + if (([bitmapImage bitsPerPixel] == 32) && (([bitmapImage bitmapFormat] & 0x5) == 0) && ![bitmapImage isPlanar]) { /* Try a fast copy if the image is a meshed RGBA 32bit bitmap*/ @@ -1207,11 +1199,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType else { /* Tell cocoa image resolution is same as current system one */ [bitmapImage setSize:imgSize]; - + /* Convert the image in a RGBA 32bit format */ - /* As Core Graphics does not support contextes with non premutliplied alpha, + /* As Core Graphics does not support contexts with non premutliplied alpha, we need to get alpha key values in a separate batch */ - + /* First get RGB values w/o Alpha to avoid pre-multiplication, 32bit but last byte is unused */ blBitmapFormatImageRGB = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:imgSize.width @@ -1221,12 +1213,12 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType bitmapFormat:(NSBitmapFormat)0 bytesPerRow:4*imgSize.width bitsPerPixel:32/*RGB format padded to 32bits*/]; - + [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:blBitmapFormatImageRGB]]; [bitmapImage draw]; [NSGraphicsContext restoreGraphicsState]; - + rasterRGB = (GHOST_TUns8*)[blBitmapFormatImageRGB bitmapData]; if (rasterRGB == NULL) { [bitmapImage release]; @@ -1234,7 +1226,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType [droppedImg release]; return GHOST_kFailure; } - + /* Then get Alpha values by getting the RGBA image (that is premultiplied btw) */ blBitmapFormatImageRGBA = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL pixelsWide:imgSize.width @@ -1244,12 +1236,12 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType bitmapFormat:(NSBitmapFormat)0 bytesPerRow:4*imgSize.width bitsPerPixel:32/* RGBA */]; - + [NSGraphicsContext saveGraphicsState]; [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithBitmapImageRep:blBitmapFormatImageRGBA]]; [bitmapImage draw]; [NSGraphicsContext restoreGraphicsState]; - + rasterRGBA = (GHOST_TUns8*)[blBitmapFormatImageRGBA bitmapData]; if (rasterRGBA == NULL) { [bitmapImage release]; @@ -1258,37 +1250,37 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType [droppedImg release]; return GHOST_kFailure; } - + /*Copy the image to ibuf, flipping it vertically*/ toIBuf = (GHOST_TUns8*)ibuf->rect; for (y = 0; y < imgSize.height; y++) { for (x = 0; x < imgSize.width; x++) { to_i = (imgSize.height-y-1)*imgSize.width + x; from_i = y*imgSize.width + x; - + toIBuf[4*to_i] = rasterRGB[4*from_i]; /* R */ toIBuf[4*to_i+1] = rasterRGB[4*from_i+1]; /* G */ toIBuf[4*to_i+2] = rasterRGB[4*from_i+2]; /* B */ toIBuf[4*to_i+3] = rasterRGBA[4*from_i+3]; /* A */ } } - + [blBitmapFormatImageRGB release]; [blBitmapFormatImageRGBA release]; [droppedImg release]; } - + eventData = (GHOST_TEventDataPtr) ibuf; - } break; - + } + default: return GHOST_kFailure; break; } pushEvent(new GHOST_EventDragnDrop(getMilliSeconds(),eventType,draggedObjectType,window,mouseX,mouseY,eventData)); - } break; + } default: return GHOST_kFailure; } @@ -1300,11 +1292,11 @@ GHOST_TSuccess GHOST_SystemCocoa::handleDraggingEvent(GHOST_TEventType eventType GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest() { GHOST_Window* window = (GHOST_Window*)m_windowManager->getActiveWindow(); - + //Discard quit event if we are in cursor grab sequence if (window && (window->getCursorGrabMode() != GHOST_kGrabDisable) && (window->getCursorGrabMode() != GHOST_kGrabNormal)) return GHOST_kExitCancel; - + //Check open windows if some changes are not saved if (m_windowManager->getAnyModifiedState()) { @@ -1328,7 +1320,7 @@ GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest() m_outsideLoopEventProcessed = true; return GHOST_kExitNow; } - + return GHOST_kExitCancel; } @@ -1340,11 +1332,11 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr) char * temp_buff; size_t filenameTextSize; GHOST_Window* window= (GHOST_Window*)m_windowManager->getActiveWindow(); - + if (!window) { return NO; } - + //Discard event if we are in cursor grab sequence, it'll lead to "stuck cursor" situation if the alert panel is raised if (window && (window->getCursorGrabMode() != GHOST_kGrabDisable) && (window->getCursorGrabMode() != GHOST_kGrabNormal)) return GHOST_kExitCancel; @@ -1366,15 +1358,15 @@ bool GHOST_SystemCocoa::handleOpenDocumentRequest(void *filepathStr) if (confirmOpen == NSAlertAlternateReturn) { filenameTextSize = [filepath lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding]; - + temp_buff = (char*) malloc(filenameTextSize+1); - + if (temp_buff == NULL) { return GHOST_kFailure; } - + strncpy(temp_buff, [filepath cStringUsingEncoding:NSISOLatin1StringEncoding], filenameTextSize); - + temp_buff[filenameTextSize] = '\0'; pushEvent(new GHOST_EventString(getMilliSeconds(),GHOST_kEventOpenMainFile,window,(GHOST_TEventDataPtr) temp_buff)); @@ -1395,7 +1387,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) printf("\nW failure for event 0x%x",[event type]); return GHOST_kFailure; } - + GHOST_TabletData& ct = window->GetCocoaTabletData(); GHOST_TTabletMode active_tool; @@ -1461,7 +1453,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr) } GHOST_TabletData& ct = window->GetCocoaTabletData(); - + ct.Pressure = [event pressure]; NSPoint tilt = [event tilt]; ct.Xtilt = tilt.x; @@ -1512,8 +1504,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) static float warp_dx = 0, warp_dy = 0; // need to reset these. e.g. each grab operation should get its own. // ^^ not currently useful, try m_cursorDelta_* instead. - switch ([event type]) - { + switch ([event type]) { case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: @@ -1525,7 +1516,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) } pushEvent(new GHOST_EventButton([event timestamp]*1000, GHOST_kEventButtonDown, window, convertButton([event buttonNumber]))); break; - + case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: @@ -1539,7 +1530,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) // cheap hack, should reset when grab ends. warp_dx = warp_dy = 0; break; - + case NSLeftMouseDragged: case NSRightMouseDragged: case NSOtherMouseDragged: @@ -1556,128 +1547,121 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) event_dy = -event_dy; //Strange Apple implementation (inverted coordinates for the deltaY) ... - switch (window->getCursorGrabMode()) { case GHOST_kGrabHide: //Cursor hidden grab operation : no cursor move - { + { printf(" - grab hide\n"); GHOST_TInt32 x_warp, y_warp, x_accum, y_accum; - + window->getCursorGrabInitPos(x_warp, y_warp); - + window->getCursorGrabAccum(x_accum, y_accum); x_accum += event_dx; y_accum += event_dy; window->setCursorGrabAccum(x_accum, y_accum); - + pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x_warp+x_accum, y_warp+y_accum)); - } break; + } case GHOST_kGrabWrap: //Wrap cursor at area/window boundaries - { + { NSPoint mousePos = [event locationInWindow]; GHOST_TInt32 x_mouse= mousePos.x; GHOST_TInt32 y_mouse= mousePos.y; GHOST_TInt32 x_accum, y_accum, x_cur, y_cur; GHOST_Rect bounds, windowBounds, correctedBounds; - + /* fallback to window bounds */ if(window->getCursorGrabBounds(bounds)==GHOST_kFailure) window->getClientBounds(bounds); - + //Switch back to Cocoa coordinates orientation (y=0 at botton,the same as blender internal btw!), and to client coordinates window->getClientBounds(windowBounds); window->screenToClient(bounds.m_l,bounds.m_b, correctedBounds.m_l, correctedBounds.m_t); window->screenToClient(bounds.m_r, bounds.m_t, correctedBounds.m_r, correctedBounds.m_b); correctedBounds.m_b = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_b; correctedBounds.m_t = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_t; - + //Update accumulation counts window->getCursorGrabAccum(x_accum, y_accum); x_accum += event_dx - m_cursorDelta_x; y_accum += event_dy - m_cursorDelta_y; window->setCursorGrabAccum(x_accum, y_accum); - - + //Warp mouse cursor if needed x_mouse += event_dx - m_cursorDelta_x; y_mouse += event_dy - m_cursorDelta_y; correctedBounds.wrapPoint(x_mouse, y_mouse, 2); - + //Compensate for mouse moved event taking cursor position set into account m_cursorDelta_x = x_mouse-mousePos.x; m_cursorDelta_y = y_mouse-mousePos.y; - + //Set new cursor position window->clientToScreen(x_mouse, y_mouse, x_cur, y_cur); setMouseCursorPosition(x_cur, y_cur); /* wrap */ - + //Post event window->getCursorGrabInitPos(x_cur, y_cur); pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, x_cur + x_accum, y_cur + y_accum)); - } + break; + } default: - { //Normal cursor operation: send mouse position in window pushEvent(new GHOST_EventCursor([event timestamp]*1000, GHOST_kEventCursorMove, window, mousePos.x, mousePos.y)); m_cursorDelta_x=0; m_cursorDelta_y=0; //Mouse motion occured between two cursor warps, so we can reset the delta counter - warp_dx = 0; warp_dy = 0; - } - break; - } - break; - } + } // END cursor grab mode + break; + } // END mouse moved case NSScrollWheel: - { - /* Send trackpad event if inside a trackpad gesture, send wheel event otherwise */ - if (m_hasMultiTouchTrackpad and m_isGestureInProgress) { - NSPoint mousePos = [event locationInWindow]; - double dx = [event deltaX]; - double dy = -[event deltaY]; - - const double deltaMax = 50.0; - - if ((dx == 0) && (dy == 0)) break; - - /* Quadratic acceleration */ - dx = dx*(fabs(dx)+0.5); - if (dx<0.0) dx-=0.5; else dx+=0.5; - if (dx< -deltaMax) dx= -deltaMax; else if (dx>deltaMax) dx=deltaMax; - - dy = dy*(fabs(dy)+0.5); - if (dy<0.0) dy-=0.5; else dy+=0.5; - if (dy< -deltaMax) dy= -deltaMax; else if (dy>deltaMax) dy=deltaMax; - - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventScroll, mousePos.x, mousePos.y, dx, dy)); - } - else { - GHOST_TInt32 delta; - - double deltaF = [event deltaY]; - if (deltaF == 0.0) break; //discard trackpad delta=0 events - - delta = deltaF > 0.0 ? 1 : -1; - pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta)); - } + /* Send trackpad event if inside a trackpad gesture, send wheel event otherwise */ + if (m_hasMultiTouchTrackpad and m_isGestureInProgress) { + NSPoint mousePos = [event locationInWindow]; + double dx = [event deltaX]; + double dy = -[event deltaY]; + + const double deltaMax = 50.0; + + if ((dx == 0) && (dy == 0)) break; + + /* Quadratic acceleration */ + dx = dx*(fabs(dx)+0.5); + if (dx<0.0) dx-=0.5; else dx+=0.5; + if (dx< -deltaMax) dx= -deltaMax; else if (dx>deltaMax) dx=deltaMax; + + dy = dy*(fabs(dy)+0.5); + if (dy<0.0) dy-=0.5; else dy+=0.5; + if (dy< -deltaMax) dy= -deltaMax; else if (dy>deltaMax) dy=deltaMax; + + pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventScroll, mousePos.x, mousePos.y, dx, dy)); + } + else { + GHOST_TInt32 delta; + + double deltaF = [event deltaY]; + if (deltaF == 0.0) break; //discard trackpad delta=0 events + + delta = deltaF > 0.0 ? 1 : -1; + pushEvent(new GHOST_EventWheel([event timestamp]*1000, window, delta)); } break; - + case NSEventTypeMagnify: { - NSPoint mousePos = [event locationInWindow]; - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, mousePos.x, mousePos.y, [event magnification]*250.0 + 0.1, 0)); - } + NSPoint mousePos = [event locationInWindow]; + pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventMagnify, mousePos.x, mousePos.y, [event magnification]*250.0 + 0.1, 0)); break; - + } case NSEventTypeRotate: { - NSPoint mousePos = [event locationInWindow]; - pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, mousePos.x, mousePos.y, -[event rotation] * 5.0, 0)); + NSPoint mousePos = [event locationInWindow]; + pushEvent(new GHOST_EventTrackpad([event timestamp]*1000, window, GHOST_kTrackpadEventRotate, mousePos.x, mousePos.y, -[event rotation] * 5.0, 0)); + break; } case NSEventTypeBeginGesture: m_isGestureInProgress = true; @@ -1688,8 +1672,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) default: printf(" unknown event type %d\n", [event type]); return GHOST_kFailure; - } - + } + return GHOST_kSuccess; } @@ -1710,7 +1694,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) //printf("\nW failure for event 0x%x",[event type]); return GHOST_kFailure; } - + switch ([event type]) { case NSKeyDown: case NSKeyUp: @@ -1723,7 +1707,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) keyCode = convertKey([event keyCode],0, [event type] == NSKeyDown?kUCKeyActionDown:kUCKeyActionUp); - + characters = [event characters]; if ([characters length]>0) { //Check for dead keys //Convert characters to iso latin 1 encoding @@ -1735,7 +1719,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) } else ascii= 0; - + if ((keyCode == GHOST_kKeyQ) && (m_modifierMask & NSCommandKeyMask)) break; //Cmd-Q is directly handled by Cocoa @@ -1747,10 +1731,10 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) //printf("\nKey up rawCode=0x%x charsIgnoringModifiers=%c keyCode=%u ascii=%i %c",[event keyCode],[charsIgnoringModifiers length]>0?[charsIgnoringModifiers characterAtIndex:0]:' ',keyCode,ascii,ascii); } break; - + case NSFlagsChanged: modifiers = [event modifierFlags]; - + if ((modifiers & NSShiftKeyMask) != (m_modifierMask & NSShiftKeyMask)) { pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSShiftKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyLeftShift) ); } @@ -1763,65 +1747,64 @@ GHOST_TSuccess GHOST_SystemCocoa::handleKeyEvent(void *eventPtr) if ((modifiers & NSCommandKeyMask) != (m_modifierMask & NSCommandKeyMask)) { pushEvent( new GHOST_EventKey([event timestamp]*1000, (modifiers & NSCommandKeyMask)?GHOST_kEventKeyDown:GHOST_kEventKeyUp, window, GHOST_kKeyCommand) ); } - + m_modifierMask = modifiers; break; - + default: return GHOST_kFailure; break; } - + return GHOST_kSuccess; } - #pragma mark Clipboard get/set GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const { GHOST_TUns8 * temp_buff; size_t pastedTextSize; - + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; - + if (pasteBoard == nil) { [pool drain]; return NULL; } - + NSArray *supportedTypes = [NSArray arrayWithObjects: NSStringPboardType, nil]; - + NSString *bestType = [[NSPasteboard generalPasteboard] availableTypeFromArray:supportedTypes]; - + if (bestType == nil) { [pool drain]; return NULL; } - + NSString * textPasted = [pasteBoard stringForType:NSStringPboardType]; if (textPasted == nil) { [pool drain]; return NULL; } - + pastedTextSize = [textPasted lengthOfBytesUsingEncoding:NSISOLatin1StringEncoding]; - + temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); if (temp_buff == NULL) { [pool drain]; return NULL; } - + strncpy((char*)temp_buff, [textPasted cStringUsingEncoding:NSISOLatin1StringEncoding], pastedTextSize); - + temp_buff[pastedTextSize] = '\0'; [pool drain]; @@ -1836,26 +1819,26 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const { NSString *textToCopy; - + if(selection) {return;} // for copying the selection, used on X11 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; - + if (pasteBoard == nil) { [pool drain]; return; } - + NSArray *supportedTypes = [NSArray arrayWithObject:NSStringPboardType]; - + [pasteBoard declareTypes:supportedTypes owner:nil]; - + textToCopy = [NSString stringWithCString:buffer encoding:NSISOLatin1StringEncoding]; - + [pasteBoard setString:textToCopy forType:NSStringPboardType]; - + [pool drain]; } @@ -1868,23 +1851,23 @@ const GHOST_TUns8* GHOST_SystemCocoa::getSystemDir() const NSFileManager *fileManager; NSString *basePath; NSArray *paths; - + paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSLocalDomainMask, YES); - + if ([paths count] > 0) basePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"Blender"]; else { //Fall back to standard unix path in case of issue basePath = @"/usr/share/blender"; } - + /* Ensure path exists, creates it if needed */ fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:basePath isDirectory:NULL]) { [fileManager createDirectoryAtPath:basePath attributes:nil]; } - + strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]); - + [pool drain]; return tempPath; } @@ -1904,15 +1887,15 @@ const GHOST_TUns8* GHOST_SystemCocoa::getUserDir() const else { //Fall back to HOME in case of issue basePath = [NSHomeDirectory() stringByAppendingPathComponent:@".blender"]; } - + /* Ensure path exists, creates it if needed */ fileManager = [NSFileManager defaultManager]; if (![fileManager fileExistsAtPath:basePath isDirectory:NULL]) { [fileManager createDirectoryAtPath:basePath attributes:nil]; } - + strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]); - + [pool drain]; return tempPath; } -- cgit v1.2.3 From a51ebf247fe97bd40e04d1d24dbb89e200e9fc09 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 24 Jul 2010 06:49:24 +0000 Subject: Renamed Mac file to exclude it from Windows build. Revoke this cowardly commit once I figure out how to properly fix the build script! --- intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 113 ++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 intern/ghost/intern/GHOST_NDOFManagerCocoa.mm diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm new file mode 100644 index 00000000000..c4a8a2f1831 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -0,0 +1,113 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "GHOST_NDOFManagerCocoa.h" +#include "GHOST_SystemCocoa.h" + +extern "C" { + #include <3DconnexionClient/ConnexionClientAPI.h> + #include + } + +static void SpaceNavAdded(io_connect_t connection) + { + printf("SpaceNav added\n"); + } + +static void SpaceNavRemoved(io_connect_t connection) + { + printf("SpaceNav removed\n"); + } + +static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void *messageArgument) + { + GHOST_SystemCocoa* system = (GHOST_SystemCocoa*) GHOST_ISystem::getSystem(); + GHOST_NDOFManager* manager = system->getNDOFManager(); + switch (messageType) + { + case kConnexionMsgDeviceState: + { + ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument; + switch (s->command) + { + case kConnexionCmdHandleAxis: + manager->updateTranslation(s->axis, s->time); + manager->updateRotation(s->axis + 3, s->time); + system->notifyExternalEventProcessed(); + break; + + case kConnexionCmdHandleButtons: + manager->updateButtons(s->buttons, s->time); + system->notifyExternalEventProcessed(); + break; + } + break; + } + case kConnexionMsgPrefsChanged: + printf("prefs changed\n"); // this includes app switches + break; + case kConnexionMsgDoAction: + printf("do action\n"); // no idea what this means + // 'calibrate device' in System Prefs sends this + break; + default: + printf(" mystery event\n"); + } + } + +GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) + : GHOST_NDOFManager(sys) + { + if (available()) + { + OSErr error = InstallConnexionHandlers(SpaceNavEvent, SpaceNavAdded, SpaceNavRemoved); + if (error) + { + printf(" error = %d\n", error); + return; + } + + // Pascal string *and* a four-letter constant. How old-skool. + m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pBlender", + kConnexionClientModeTakeOver, kConnexionMaskAll); + + printf("client id = %d\n", m_clientID); + } + else + { + printf(" SpaceNav driver not found\n"); + // This isn't a hard error, just means the user doesn't have a SpaceNavigator. + } + } + +GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() + { + UnregisterConnexionClient(m_clientID); + CleanupConnexionHandlers(); + } + +bool GHOST_NDOFManagerCocoa::available() + { +// extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); +// ^-- not needed since the entire framework is weak-linked + return InstallConnexionHandlers != NULL; + } -- cgit v1.2.3 From a7ba245fe39b73fc31010c647e9698dea326202b Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 24 Jul 2010 11:06:08 +0000 Subject: Activated NDOF capture for Windows. Robust++ for generic NDOF manager. Removed experimental Win32 mouse and NDOF code now that good solutions are in place. Cleaned up formatting. --- intern/ghost/intern/GHOST_NDOFManager.cpp | 16 +- intern/ghost/intern/GHOST_SystemWin32.cpp | 994 +++++++++++++----------------- intern/ghost/intern/GHOST_SystemWin32.h | 6 +- 3 files changed, 434 insertions(+), 582 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 120805733b4..8cc4a02f51b 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -15,21 +15,26 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Contributor(s): none yet. + * Contributor(s): Mike Erwin, July 2010. * * ***** END GPL LICENSE BLOCK ***** */ #include "GHOST_NDOFManager.h" #include "GHOST_EventNDOF.h" +#include // for memory functions +#include // for debug tracing GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) : m_system(sys) -// , m_translation((short[]){0,0,0}) -// , m_rotation((short[]){0,0,0}) , m_buttons(0) , m_atRest(true) - { } + { + // to avoid the rare situation where one triple is updated and + // the other is not, initialize them both here: + memset(m_translation, 0, sizeof(m_translation)); + memset(m_rotation, 0, sizeof(m_rotation)); + } void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time) { @@ -68,7 +73,9 @@ bool GHOST_NDOFManager::sendMotionEvent() GHOST_TEventNDOFData* data = (GHOST_TEventNDOFData*) event->getData(); const float scale = 1.f / 350.f; // SpaceNavigator sends +/- 350 usually + // 350 according to their developer's guide; others recommend 500 as comfortable + // possible future enhancement // scale *= m_sensitivity; data->tx = scale * m_translation[0]; @@ -80,7 +87,6 @@ bool GHOST_NDOFManager::sendMotionEvent() 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); - fflush(stdout); m_system.pushEvent(event); diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 14b6b16e6fb..1363e4f604b 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -27,7 +27,6 @@ */ /** - * $Id$ * Copyright (C) 2001 NaN Technologies B.V. * @author Maarten Gribnau @@ -47,28 +46,12 @@ #endif #endif -/* - * According to the docs the mouse wheel message is supported from windows 98 - * upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the - * wheel detent value are undefined. - - [mce] able to remove this too? - -#ifndef WM_MOUSEWHEEL -#define WM_MOUSEWHEEL 0x020A -#endif // WM_MOUSEWHEEL -#ifndef WHEEL_DELTA -#define WHEEL_DELTA 120 // Value for rolling one detent, (old convention! MS changed it) -#endif // WHEEL_DELTA - */ - #include "GHOST_Debug.h" #include "GHOST_DisplayManagerWin32.h" #include "GHOST_EventButton.h" #include "GHOST_EventCursor.h" #include "GHOST_EventKey.h" #include "GHOST_EventWheel.h" -#include "GHOST_EventNDOF.h" #include "GHOST_TimerTask.h" #include "GHOST_TimerManager.h" #include "GHOST_WindowManager.h" @@ -130,13 +113,7 @@ GHOST_SystemWin32::GHOST_SystemWin32() // register for RawInput devices RAWINPUTDEVICE devices[1]; -/* - // standard HID mouse - devices[0].usUsagePage = 0x01; - devices[0].usUsage = 0x02; - devices[0].dwFlags = 0; // RIDEV_NOLEGACY; // ignore legacy mouse messages - devices[0].hwndTarget = NULL; -*/ + // multi-axis mouse (SpaceNavigator) devices[0].usUsagePage = 0x01; devices[0].usUsage = 0x08; @@ -396,6 +373,7 @@ GHOST_TSuccess GHOST_SystemWin32::init() GHOST_TSuccess GHOST_SystemWin32::exit() { + // [mce] since this duplicates its super, why bother? return GHOST_System::exit(); } @@ -522,15 +500,10 @@ GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, } -GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow, int x, int y) +GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow, int x_screen, int y_screen) { - GHOST_TInt32 x_screen, y_screen; GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem()); GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow; - -// system->getCursorPosition(x_screen, y_screen); - x_screen = x; - y_screen = y; if(window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal) { @@ -639,81 +612,10 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax) minmax->ptMinTrackSize.y=240; } -bool GHOST_SystemWin32::processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window /*, int& x, int& y */ ) +bool GHOST_SystemWin32::processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window) { - GHOST_IEvent* event = NULL; bool eventSent = false; - puts("BEGIN"); - -#if 0 // now using the existing mouse button handlers, improved movement handler - if (raw.header.dwType == RIM_TYPEMOUSE) - { - USHORT const& buttonFlags = raw.data.mouse.usButtonFlags; - if (buttonFlags) - { - printf("button flags: %04X\n", buttonFlags); - - if (buttonFlags & RI_MOUSE_LEFT_BUTTON_DOWN) - { - puts("left button down"); - window->registerMouseClickEvent(true); - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft); - } - else if (buttonFlags & RI_MOUSE_LEFT_BUTTON_UP) - { - puts("left button up"); - window->registerMouseClickEvent(false); - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft); - } - - if (buttonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN) - { - puts("right button down"); - window->registerMouseClickEvent(true); - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight); - } - else if (buttonFlags & RI_MOUSE_RIGHT_BUTTON_UP) - { - puts("right button up"); - window->registerMouseClickEvent(false); - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight); - } - - if (buttonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN) - { - puts("middle button down"); - window->registerMouseClickEvent(true); - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle); - } - else if (buttonFlags & RI_MOUSE_MIDDLE_BUTTON_UP) - { - puts("middle button up"); - window->registerMouseClickEvent(false); - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle); - } - - // similar for BUTTON_4 and BUTTON_5 - - if (buttonFlags & RI_MOUSE_WHEEL) - { - signed short wheelDelta = raw.data.mouse.usButtonData; - printf("wheel moved %+d\n", wheelDelta); - } - } - - int dx = raw.data.mouse.lLastX; // These might be in Mickeys, not pixels. - int dy = raw.data.mouse.lLastY; - if (dx || dy) - { - printf("mouse moved <%+d,%+d>\n", dx, dy); - x += dx; - x += dy; - event = processCursorEvent(GHOST_kEventCursorMove, window, x, y); - } - } -#endif // unused experimental mouse code - if (raw.header.dwType == RIM_TYPEHID) { // RID_DEVICE_INFO info; @@ -738,16 +640,20 @@ vendor ID No other registered devices use the c62_ space, so a simple mask will work! */ + // The NDOF manager sends button changes immediately, and *pretends* to + // send motion. Mark as 'sent' so motion will always get dispatched. + eventSent = true; + // multiple events per RAWHID? MSDN hints at this. - printf("%d events\n", raw.data.hid.dwCount); + printf("%d events\n", (int)raw.data.hid.dwCount); BYTE const* data = &raw.data.hid.bRawData; -// MinGW's definition (below) doesn't agree with MSDN reference for bRawData: -// typedef struct tagRAWHID { -// DWORD dwSizeHid; -// DWORD dwCount; -// BYTE bRawData; -// } RAWHID,*PRAWHID,*LPRAWHID; + // MinGW's definition (below) doesn't agree with MSDN reference for bRawData: + // typedef struct tagRAWHID { + // DWORD dwSizeHid; + // DWORD dwCount; + // BYTE bRawData; // <== isn't this s'posed to be a BYTE*? + // } RAWHID,*PRAWHID,*LPRAWHID; BYTE packetType = data[0]; switch (packetType) @@ -756,16 +662,20 @@ No other registered devices use the c62_ space, so a simple mask will work! { short t[3]; memcpy(t, data + 1, sizeof(t)); - printf("T: %+5d %+5d %+5d\n", t[0], t[1], t[2]); - m_ndofManager->updateTranslation(t, getMilliseconds()); + // too much noise -- disable for now + // printf("T: %+5d %+5d %+5d\n", t[0], t[1], t[2]); + m_ndofManager->updateTranslation(t, getMilliSeconds()); + // wariness of alignment issues prevents me from saying it this way: + // m_ndofManager->updateTranslation((short*)(data + 1), getMilliSeconds()); + // though it probably (94.7%) works fine break; } case 2: // rotation { short r[3]; memcpy(r, data + 1, sizeof(r)); - printf("R: %+5d %+5d %+5d\n", r[0], r[1], r[2]); - m_ndofManager->updateRotation(r, getMilliseconds()); + // printf("R: %+5d %+5d %+5d\n", r[0], r[1], r[2]); + m_ndofManager->updateRotation(r, getMilliSeconds()); break; } case 3: // buttons @@ -783,24 +693,11 @@ No other registered devices use the c62_ space, so a simple mask will work! } else printf(" none\n"); - m_ndofManager->updateButtons(buttons, getMilliseconds()); + m_ndofManager->updateButtons(buttons, getMilliSeconds()); break; } } } - - // assume only one event will come from this RawInput report - // test and adjust assumptions as needed! - - if (event) - { - pushEvent(event); - event = NULL; - eventSent = true; - } - - puts("END"); - return eventSent; } @@ -823,6 +720,7 @@ int GHOST_SystemWin32::getMoreMousePoints(int xLatest, int yLatest, int xPrev, i } // search for 'prev' point (we want only newer points) + // TODO: detect & ignore points that don't belong to our window for (int i = 1; i < n; ++i) if (morePoints[i].x == xPrev && morePoints[i].y == yPrev) { @@ -835,13 +733,14 @@ int GHOST_SystemWin32::getMoreMousePoints(int xLatest, int yLatest, int xPrev, i signed short x = morePoints[i].x; signed short y = morePoints[i].y; - printf("> (%d,%d)\n", x, y); - + // uncomment here and in WM_MOUSEMOVE handler to show effectiveness of hi-fi input + // printf("> (%d,%d)\n", x, y); + pushEvent(processCursorEvent(GHOST_kEventCursorMove, window, x, y)); } return n; - } // END getMoreMousePoints + } LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -901,479 +800,426 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM static int mousePosX = 0, mousePosY = 0; // track mouse position between calls - switch (msg) { - //////////////////////////////////////////////////////////////////////// - // Keyboard events, processed - //////////////////////////////////////////////////////////////////////// - case WM_KEYDOWN: - /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a - * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt - * key is not pressed. - */ - case WM_SYSKEYDOWN: - /* The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when - * the user presses the F10 key (which activates the menu bar) or holds down the - * alt key and then presses another key. It also occurs when no window currently - * has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the - * active window. The window that receives the message can distinguish between these - * two contexts by checking the context code in the lKeyData parameter. - */ - switch (wParam) { - case VK_SHIFT: - case VK_CONTROL: - case VK_MENU: - if (!m_separateLeftRightInitialized) { - // Check whether this system supports separate left and right keys - switch (wParam) { - case VK_SHIFT: - m_separateLeftRight = - (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) || - (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ? - true : false; - break; - case VK_CONTROL: - m_separateLeftRight = - (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) || - (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ? - true : false; - break; - case VK_MENU: - m_separateLeftRight = - (HIBYTE(::GetKeyState(VK_LMENU)) != 0) || - (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ? - true : false; - break; - } - m_separateLeftRightInitialized = true; - } - processModifierKeys(window); - // Bypass call to DefWindowProc - return true; - default: - event = processKeyEvent(window, true, wParam, lParam); - if (!event) { - GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") - GHOST_PRINT(msg) - GHOST_PRINT(" key ignored\n") - } - break; + switch (msg) { + //////////////////////////////////////////////////////////////////////// + // Keyboard events, processed + //////////////////////////////////////////////////////////////////////// + case WM_KEYDOWN: + /* The WM_KEYDOWN message is posted to the window with the keyboard focus when a + * nonsystem key is pressed. A nonsystem key is a key that is pressed when the alt + * key is not pressed. + */ + case WM_SYSKEYDOWN: + /* The WM_SYSKEYDOWN message is posted to the window with the keyboard focus when + * the user presses the F10 key (which activates the menu bar) or holds down the + * alt key and then presses another key. It also occurs when no window currently + * has the keyboard focus; in this case, the WM_SYSKEYDOWN message is sent to the + * active window. The window that receives the message can distinguish between these + * two contexts by checking the context code in the lKeyData parameter. + */ + switch (wParam) { + case VK_SHIFT: + case VK_CONTROL: + case VK_MENU: + if (!m_separateLeftRightInitialized) { + // Check whether this system supports separate left and right keys + switch (wParam) { + case VK_SHIFT: + m_separateLeftRight = + (HIBYTE(::GetKeyState(VK_LSHIFT)) != 0) || + (HIBYTE(::GetKeyState(VK_RSHIFT)) != 0) ? + true : false; + break; + case VK_CONTROL: + m_separateLeftRight = + (HIBYTE(::GetKeyState(VK_LCONTROL)) != 0) || + (HIBYTE(::GetKeyState(VK_RCONTROL)) != 0) ? + true : false; + break; + case VK_MENU: + m_separateLeftRight = + (HIBYTE(::GetKeyState(VK_LMENU)) != 0) || + (HIBYTE(::GetKeyState(VK_RMENU)) != 0) ? + true : false; + break; } + m_separateLeftRightInitialized = true; + } + processModifierKeys(window); + // Bypass call to DefWindowProc + return true; + default: + event = processKeyEvent(window, true, wParam, lParam); + if (!event) { + GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") + GHOST_PRINT(msg) + GHOST_PRINT(" key ignored\n") + } break; + } + break; - case WM_KEYUP: - case WM_SYSKEYUP: - switch (wParam) { - case VK_SHIFT: - case VK_CONTROL: - case VK_MENU: - processModifierKeys(window); - // Bypass call to DefWindowProc - return true; - default: - event = processKeyEvent(window, false, wParam, lParam); - if (!event) { - GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") - GHOST_PRINT(msg) - GHOST_PRINT(" key ignored\n") - } - break; + case WM_KEYUP: + case WM_SYSKEYUP: + switch (wParam) { + case VK_SHIFT: + case VK_CONTROL: + case VK_MENU: + processModifierKeys(window); + // Bypass call to DefWindowProc + return true; + default: + event = processKeyEvent(window, false, wParam, lParam); + if (!event) { + GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") + GHOST_PRINT(msg) + GHOST_PRINT(" key ignored\n") } break; + } + break; #if 0 // this code is illustrative; no need to compile - //////////////////////////////////////////////////////////////////////// - // Keyboard events, ignored - //////////////////////////////////////////////////////////////////////// - case WM_CHAR: - /* The WM_CHAR message is posted to the window with the keyboard focus when - * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR - * contains the character code of the key that was pressed. - */ - case WM_DEADCHAR: - /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a - * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR - * specifies a character code generated by a dead key. A dead key is a key that - * generates a character, such as the umlaut (double-dot), that is combined with - * another character to form a composite character. For example, the umlaut-O - * character (Ù) is generated by typing the dead key for the umlaut character, and - * then typing the O key. - */ - case WM_SYSDEADCHAR: - /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when - * a WM_SYSKEYDOWN message is translated by the TranslateMessage function. - * WM_SYSDEADCHAR specifies the character code of a system dead key - that is, - * a dead key that is pressed while holding down the alt key. - */ - break; + //////////////////////////////////////////////////////////////////////// + // Keyboard events, ignored + //////////////////////////////////////////////////////////////////////// + case WM_CHAR: + /* The WM_CHAR message is posted to the window with the keyboard focus when + * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR + * contains the character code of the key that was pressed. + */ + case WM_DEADCHAR: + /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a + * WM_KEYUP message is translated by the TranslateMessage function. WM_DEADCHAR + * specifies a character code generated by a dead key. A dead key is a key that + * generates a character, such as the umlaut (double-dot), that is combined with + * another character to form a composite character. For example, the umlaut-O + * character (Ù) is generated by typing the dead key for the umlaut character, and + * then typing the O key. + */ + case WM_SYSDEADCHAR: + /* The WM_SYSDEADCHAR message is sent to the window with the keyboard focus when + * a WM_SYSKEYDOWN message is translated by the TranslateMessage function. + * WM_SYSDEADCHAR specifies the character code of a system dead key - that is, + * a dead key that is pressed while holding down the alt key. + */ + break; #endif // illustrative code - //////////////////////////////////////////////////////////////////////// - // Tablet events, processed - //////////////////////////////////////////////////////////////////////// - case WT_PACKET: - puts("WT_PACKET"); - window->processWin32TabletEvent(wParam, lParam); - break; - case WT_CSRCHANGE: - case WT_PROXIMITY: - window->processWin32TabletInitEvent(); - break; + //////////////////////////////////////////////////////////////////////// + // Tablet events, processed + //////////////////////////////////////////////////////////////////////// + case WT_PACKET: + puts("WT_PACKET"); + window->processWin32TabletEvent(wParam, lParam); + break; + case WT_CSRCHANGE: + case WT_PROXIMITY: + window->processWin32TabletInitEvent(); + break; - //////////////////////////////////////////////////////////////////////// - // Mouse events, processed - //////////////////////////////////////////////////////////////////////// - case WM_LBUTTONDOWN: - window->registerMouseClickEvent(true); - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft); - break; - case WM_MBUTTONDOWN: - window->registerMouseClickEvent(true); - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle); - break; - case WM_RBUTTONDOWN: - window->registerMouseClickEvent(true); - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight); - break; - case WM_XBUTTONDOWN: - window->registerMouseClickEvent(true); - if ((short) HIWORD(wParam) == XBUTTON1){ - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton4); - }else if((short) HIWORD(wParam) == XBUTTON2){ - event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton5); - } - break; - case WM_LBUTTONUP: - window->registerMouseClickEvent(false); - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft); - break; - case WM_MBUTTONUP: - window->registerMouseClickEvent(false); - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle); - break; - case WM_RBUTTONUP: - window->registerMouseClickEvent(false); - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight); - break; - case WM_XBUTTONUP: - window->registerMouseClickEvent(false); - if ((short) HIWORD(wParam) == XBUTTON1){ - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton4); - }else if((short) HIWORD(wParam) == XBUTTON2){ - event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton5); - } - break; -//#endif // replaced mouse code + //////////////////////////////////////////////////////////////////////// + // Mouse events, processed + //////////////////////////////////////////////////////////////////////// + case WM_LBUTTONDOWN: + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskLeft); + break; + case WM_MBUTTONDOWN: + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskMiddle); + break; + case WM_RBUTTONDOWN: + window->registerMouseClickEvent(true); + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskRight); + break; + case WM_XBUTTONDOWN: + window->registerMouseClickEvent(true); + if ((short) HIWORD(wParam) == XBUTTON1){ + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton4); + }else if((short) HIWORD(wParam) == XBUTTON2){ + event = processButtonEvent(GHOST_kEventButtonDown, window, GHOST_kButtonMaskButton5); + } + break; + case WM_LBUTTONUP: + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskLeft); + break; + case WM_MBUTTONUP: + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskMiddle); + break; + case WM_RBUTTONUP: + window->registerMouseClickEvent(false); + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskRight); + break; + case WM_XBUTTONUP: + window->registerMouseClickEvent(false); + if ((short) HIWORD(wParam) == XBUTTON1){ + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton4); + }else if((short) HIWORD(wParam) == XBUTTON2){ + event = processButtonEvent(GHOST_kEventButtonUp, window, GHOST_kButtonMaskButton5); + } + break; - case WM_MOUSEMOVE: - { -// puts("WM_MOUSEMOVE"); + case WM_MOUSEMOVE: + { + // bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs + int tabletTool = GetMessageExtraInfo() & 0x7f; // true for tablet mouse, not just pen + if (tabletTool) + puts("(from tablet)"); + else + { + int xPrev = mousePosX; + int yPrev = mousePosY; + // window coordinates are passed in via lParam + window->clientToScreen(LOWORD(lParam), HIWORD(lParam), mousePosX, mousePosY); -// bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs - int tabletTool = GetMessageExtraInfo() & 0x7f; // true for tablet mouse, not just pen - if (tabletTool) - puts("(from tablet)"); - else - { - // these give window coords, we need view coords -// mousePosX = LOWORD(lParam); -// mousePosY = HIWORD(lParam); -// window->clientToScreen(mousePosX, mousePosY, mousePosX, mousePosY); - - int xPrev = mousePosX; - int yPrev = mousePosY; - window->clientToScreen(LOWORD(lParam), HIWORD(lParam), mousePosX, mousePosY); - // if (m_input_fidelity_hint == HI_FI) // can't access hint from static function - - putchar('\n'); - - if (m_input_fidelity_hint == HI_FI) - { - /* int n = */ getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); - // printf("%d more mouse points found\n", n); - } - - printf(" (%d,%d)\n", mousePosX, mousePosY); - - event = processCursorEvent(GHOST_kEventCursorMove, window, mousePosX, mousePosY); - } - break; + // putchar('\n'); + + if (m_input_fidelity_hint == HI_FI) + { + /* int n = */ getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); + // printf("%d more mouse points found\n", n); } - case WM_INPUT: - puts("WM_INPUT"); -{ -/* - UINT dwSize; - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER)); - LPBYTE lpb = new BYTE[dwSize]; - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)); - RAWINPUT* raw = (RAWINPUT*)lpb; -*/ + // uncomment here and in getMoreMousePoints to show effectiveness of hi-fi input + // printf(" (%d,%d)\n", mousePosX, mousePosY); - RAWINPUT raw; - RAWINPUT* raw_ptr = &raw; - UINT rawSize = sizeof(RAWINPUT); -// UINT bufferSize = rawSize; - - puts("processing first event:"); - // I don't know if this is needed. Can we get by with just GetRawInputBuffer? - // Thought some mouse events were missing, so I put this in to be cautious. - // Test and remove if redundant. [mce] - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); - eventSent |= processRawInput(raw, window /*, mousePosX, mousePosY*/ ); - DefRawInputProc(&raw_ptr, 1, sizeof(RAWINPUTHEADER)); - -// GetRawInputBuffer(NULL, &bufferSize, sizeof(RAWINPUTHEADER)); -// UINT n = bufferSize / rawSize; -// printf("allocating %d bytes (room for %d events)\n", bufferSize, n); - - RAWINPUT rawBuffer[10];// = new RAWINPUT[n]; - rawSize *= 10; - while (true) - { - int n = GetRawInputBuffer(rawBuffer, &rawSize, sizeof(RAWINPUTHEADER)); - if (n == -1) - { - printf(" error %d\n", (int) GetLastError()); - break; - } - else if (n == 0) - { - //puts("no more events"); - putchar('\n'); + event = processCursorEvent(GHOST_kEventCursorMove, window, mousePosX, mousePosY); + } break; } - else + + case WM_INPUT: { - printf("processing %d more events:\n", n); - for (int i = 0; i < n; ++i) - { - RAWINPUT const& raw = rawBuffer[i]; - eventSent |= processRawInput(raw, window /*, mousePosX, mousePosY*/ ); - } + puts("WM_INPUT"); - // clear processed events from the queue - DefRawInputProc((RAWINPUT**)&rawBuffer, n, sizeof(RAWINPUTHEADER)); - } - } // inf. loop -} - break; - case WM_MOUSEWHEEL: - puts("WM_MOUSEWHEEL"); - /* The WM_MOUSEWHEEL message is sent to the focus window - * when the mouse wheel is rotated. The DefWindowProc - * function propagates the message to the window's parent. - * There should be no internal forwarding of the message, - * since DefWindowProc propagates it up the parent chain - * until it finds a window that processes it. - */ - event = processWheelEvent(window, wParam, lParam); + #define RAWCOUNT 10 + // just a guess that we'll receive up to 10 event reports + // the following code fetches all available, 10 at a time + RAWINPUT rawBuffer[RAWCOUNT]; + + while (true) + { + UINT rawSize = sizeof(rawBuffer); + int n = GetRawInputBuffer(rawBuffer, &rawSize, sizeof(RAWINPUTHEADER)); + if (n == -1) + { + printf(" error %d\n", (int) GetLastError()); break; - case WM_SETCURSOR: - /* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor - * to move within a window and mouse input is not captured. - * This means we have to set the cursor shape every time the mouse moves! - * The DefWindowProc function uses this message to set the cursor to an - * arrow if it is not in the client area. - */ - if (LOWORD(lParam) == HTCLIENT) { - // Load the current cursor - window->loadCursor(window->getCursorVisibility(), window->getCursorShape()); - // Bypass call to DefWindowProc - return 0; - } - else { - // Outside of client area show standard cursor - window->loadCursor(true, GHOST_kStandardCursorDefault); } + else if (n == 0) + { + putchar('\n'); break; + } + else + { + printf("processing %d events:\n", n); + for (int i = 0; i < n; ++i) + { + RAWINPUT const& raw = rawBuffer[i]; + eventSent |= processRawInput(raw, window); + } + + // clear processed events from the queue + DefRawInputProc((RAWINPUT**)&rawBuffer, n, sizeof(RAWINPUTHEADER)); + } + } + break; + } + case WM_MOUSEWHEEL: + puts("WM_MOUSEWHEEL"); + /* The WM_MOUSEWHEEL message is sent to the focus window + * when the mouse wheel is rotated. The DefWindowProc + * function propagates the message to the window's parent. + * There should be no internal forwarding of the message, + * since DefWindowProc propagates it up the parent chain + * until it finds a window that processes it. + */ + event = processWheelEvent(window, wParam, lParam); + break; + case WM_SETCURSOR: + /* The WM_SETCURSOR message is sent to a window if the mouse causes the cursor + * to move within a window and mouse input is not captured. + * This means we have to set the cursor shape every time the mouse moves! + * The DefWindowProc function uses this message to set the cursor to an + * arrow if it is not in the client area. + */ + if (LOWORD(lParam) == HTCLIENT) { + // Load the current cursor + window->loadCursor(window->getCursorVisibility(), window->getCursorShape()); + // Bypass call to DefWindowProc + return 0; + } + else { + // Outside of client area show standard cursor + window->loadCursor(true, GHOST_kStandardCursorDefault); + } + break; #if 0 // this code is illustrative; no need to compile - //////////////////////////////////////////////////////////////////////// - // Mouse events, ignored - //////////////////////////////////////////////////////////////////////// - case WM_NCMOUSEMOVE: - /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved - * within the nonclient area of the window. This message is posted to the window - * that contains the cursor. If a window has captured the mouse, this message is not posted. - */ - case WM_NCHITTEST: - /* The WM_NCHITTEST message is sent to a window when the cursor moves, or - * when a mouse button is pressed or released. If the mouse is not captured, - * the message is sent to the window beneath the cursor. Otherwise, the message - * is sent to the window that has captured the mouse. - */ - break; + //////////////////////////////////////////////////////////////////////// + // Mouse events, ignored + //////////////////////////////////////////////////////////////////////// + case WM_NCMOUSEMOVE: + /* The WM_NCMOUSEMOVE message is posted to a window when the cursor is moved + * within the nonclient area of the window. This message is posted to the window + * that contains the cursor. If a window has captured the mouse, this message is not posted. + */ + case WM_NCHITTEST: + /* The WM_NCHITTEST message is sent to a window when the cursor moves, or + * when a mouse button is pressed or released. If the mouse is not captured, + * the message is sent to the window beneath the cursor. Otherwise, the message + * is sent to the window that has captured the mouse. + */ + break; #endif // illustrative code - //////////////////////////////////////////////////////////////////////// - // Window events, processed - //////////////////////////////////////////////////////////////////////// - case WM_CLOSE: - /* The WM_CLOSE message is sent as a signal that a window or an application should terminate. */ - event = processWindowEvent(GHOST_kEventWindowClose, window); - break; - case WM_ACTIVATE: - /* The WM_ACTIVATE message is sent to both the window being activated and the window being - * deactivated. If the windows use the same input queue, the message is sent synchronously, - * first to the window procedure of the top-level window being deactivated, then to the window - * procedure of the top-level window being activated. If the windows use different input queues, - * the message is sent asynchronously, so the window is activated immediately. - */ - event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window); - break; - case WM_PAINT: - /* An application sends the WM_PAINT message when the system or another application - * makes a request to paint a portion of an application's window. The message is sent - * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage - * function when the application obtains a WM_PAINT message by using the GetMessage or - * PeekMessage function. - */ - event = processWindowEvent(GHOST_kEventWindowUpdate, window); - break; - case WM_GETMINMAXINFO: - /* The WM_GETMINMAXINFO message is sent to a window when the size or - * position of the window is about to change. An application can use - * this message to override the window's default maximized size and - * position, or its default minimum or maximum tracking size. - */ - processMinMaxInfo((MINMAXINFO *) lParam); - /* Let DefWindowProc handle it. */ - break; - case WM_SIZE: - /* The WM_SIZE message is sent to a window after its size has changed. - * The WM_SIZE and WM_MOVE messages are not sent if an application handles the - * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient - * to perform any move or size change processing during the WM_WINDOWPOSCHANGED - * message without calling DefWindowProc. - */ - event = processWindowEvent(GHOST_kEventWindowSize, window); - break; - case WM_CAPTURECHANGED: - window->lostMouseCapture(); - break; - case WM_MOVING: - /* The WM_MOVING message is sent to a window that the user is moving. By processing - * this message, an application can monitor the size and position of the drag rectangle - * and, if needed, change its size or position. - */ - case WM_MOVE: - /* The WM_SIZE and WM_MOVE messages are not sent if an application handles the - * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient - * to perform any move or size change processing during the WM_WINDOWPOSCHANGED - * message without calling DefWindowProc. - */ - event = processWindowEvent(GHOST_kEventWindowMove, window); - break; + //////////////////////////////////////////////////////////////////////// + // Window events, processed + //////////////////////////////////////////////////////////////////////// + case WM_CLOSE: + /* The WM_CLOSE message is sent as a signal that a window or an application should terminate. */ + event = processWindowEvent(GHOST_kEventWindowClose, window); + break; + case WM_ACTIVATE: + /* The WM_ACTIVATE message is sent to both the window being activated and the window being + * deactivated. If the windows use the same input queue, the message is sent synchronously, + * first to the window procedure of the top-level window being deactivated, then to the window + * procedure of the top-level window being activated. If the windows use different input queues, + * the message is sent asynchronously, so the window is activated immediately. + */ + event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window); + break; + case WM_PAINT: + /* An application sends the WM_PAINT message when the system or another application + * makes a request to paint a portion of an application's window. The message is sent + * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage + * function when the application obtains a WM_PAINT message by using the GetMessage or + * PeekMessage function. + */ + event = processWindowEvent(GHOST_kEventWindowUpdate, window); + break; + case WM_GETMINMAXINFO: + /* The WM_GETMINMAXINFO message is sent to a window when the size or + * position of the window is about to change. An application can use + * this message to override the window's default maximized size and + * position, or its default minimum or maximum tracking size. + */ + processMinMaxInfo((MINMAXINFO *) lParam); + /* Let DefWindowProc handle it. */ + break; + case WM_SIZE: + /* The WM_SIZE message is sent to a window after its size has changed. + * The WM_SIZE and WM_MOVE messages are not sent if an application handles the + * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient + * to perform any move or size change processing during the WM_WINDOWPOSCHANGED + * message without calling DefWindowProc. + */ + event = processWindowEvent(GHOST_kEventWindowSize, window); + break; + case WM_CAPTURECHANGED: + window->lostMouseCapture(); + break; + case WM_MOVING: + /* The WM_MOVING message is sent to a window that the user is moving. By processing + * this message, an application can monitor the size and position of the drag rectangle + * and, if needed, change its size or position. + */ + case WM_MOVE: + /* The WM_SIZE and WM_MOVE messages are not sent if an application handles the + * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient + * to perform any move or size change processing during the WM_WINDOWPOSCHANGED + * message without calling DefWindowProc. + */ + event = processWindowEvent(GHOST_kEventWindowMove, window); + break; #if 0 // this code is illustrative; no need to compile - //////////////////////////////////////////////////////////////////////// - // Window events, ignored - //////////////////////////////////////////////////////////////////////// - case WM_WINDOWPOSCHANGED: - /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place - * in the Z order has changed as a result of a call to the SetWindowPos function or - * another window-management function. - * The WM_SIZE and WM_MOVE messages are not sent if an application handles the - * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient - * to perform any move or size change processing during the WM_WINDOWPOSCHANGED - * message without calling DefWindowProc. - */ - case WM_ERASEBKGND: - /* An application sends the WM_ERASEBKGND message when the window background must be - * erased (for example, when a window is resized). The message is sent to prepare an - * invalidated portion of a window for painting. - */ - case WM_NCPAINT: - /* An application sends the WM_NCPAINT message to a window when its frame must be painted. */ - case WM_NCACTIVATE: - /* The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed - * to indicate an active or inactive state. - */ - case WM_DESTROY: - /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window - * procedure of the window being destroyed after the window is removed from the screen. - * This message is sent first to the window being destroyed and then to the child windows - * (if any) as they are destroyed. During the processing of the message, it can be assumed - * that all child windows still exist. - */ - case WM_NCDESTROY: - /* The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The - * DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY - * message. WM_DESTROY is used to free the allocated memory object associated with the window. - */ - case WM_KILLFOCUS: - /* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. */ - case WM_SHOWWINDOW: - /* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */ - case WM_WINDOWPOSCHANGING: - /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in - * the Z order is about to change as a result of a call to the SetWindowPos function or - * another window-management function. - */ - case WM_SETFOCUS: - /* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */ - case WM_ENTERSIZEMOVE: - /* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving - * or sizing modal loop. The window enters the moving or sizing modal loop when the user - * clicks the window's title bar or sizing border, or when the window passes the - * WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the - * message specifies the SC_MOVE or SC_SIZE value. The operation is complete when - * DefWindowProc returns. - */ - break; - - //////////////////////////////////////////////////////////////////////// - // Other events - //////////////////////////////////////////////////////////////////////// - case WM_GETTEXT: - /* An application sends a WM_GETTEXT message to copy the text that - * corresponds to a window into a buffer provided by the caller. - */ - case WM_ACTIVATEAPP: - /* The WM_ACTIVATEAPP message is sent when a window belonging to a - * different application than the active window is about to be activated. - * The message is sent to the application whose window is being activated - * and to the application whose window is being deactivated. - */ - case WM_TIMER: - /* The WIN32 docs say: - * The WM_TIMER message is posted to the installing thread's message queue - * when a timer expires. You can process the message by providing a WM_TIMER - * case in the window procedure. Otherwise, the default window procedure will - * call the TimerProc callback function specified in the call to the SetTimer - * function used to install the timer. - * - * In GHOST, we let DefWindowProc call the timer callback. - */ - break; + //////////////////////////////////////////////////////////////////////// + // Window events, ignored + //////////////////////////////////////////////////////////////////////// + case WM_WINDOWPOSCHANGED: + /* The WM_WINDOWPOSCHANGED message is sent to a window whose size, position, or place + * in the Z order has changed as a result of a call to the SetWindowPos function or + * another window-management function. + * The WM_SIZE and WM_MOVE messages are not sent if an application handles the + * WM_WINDOWPOSCHANGED message without calling DefWindowProc. It is more efficient + * to perform any move or size change processing during the WM_WINDOWPOSCHANGED + * message without calling DefWindowProc. + */ + case WM_ERASEBKGND: + /* An application sends the WM_ERASEBKGND message when the window background must be + * erased (for example, when a window is resized). The message is sent to prepare an + * invalidated portion of a window for painting. + */ + case WM_NCPAINT: + /* An application sends the WM_NCPAINT message to a window when its frame must be painted. */ + case WM_NCACTIVATE: + /* The WM_NCACTIVATE message is sent to a window when its nonclient area needs to be changed + * to indicate an active or inactive state. + */ + case WM_DESTROY: + /* The WM_DESTROY message is sent when a window is being destroyed. It is sent to the window + * procedure of the window being destroyed after the window is removed from the screen. + * This message is sent first to the window being destroyed and then to the child windows + * (if any) as they are destroyed. During the processing of the message, it can be assumed + * that all child windows still exist. + */ + case WM_NCDESTROY: + /* The WM_NCDESTROY message informs a window that its nonclient area is being destroyed. The + * DestroyWindow function sends the WM_NCDESTROY message to the window following the WM_DESTROY + * message. WM_DESTROY is used to free the allocated memory object associated with the window. + */ + case WM_KILLFOCUS: + /* The WM_KILLFOCUS message is sent to a window immediately before it loses the keyboard focus. */ + case WM_SHOWWINDOW: + /* The WM_SHOWWINDOW message is sent to a window when the window is about to be hidden or shown. */ + case WM_WINDOWPOSCHANGING: + /* The WM_WINDOWPOSCHANGING message is sent to a window whose size, position, or place in + * the Z order is about to change as a result of a call to the SetWindowPos function or + * another window-management function. + */ + case WM_SETFOCUS: + /* The WM_SETFOCUS message is sent to a window after it has gained the keyboard focus. */ + case WM_ENTERSIZEMOVE: + /* The WM_ENTERSIZEMOVE message is sent one time to a window after it enters the moving + * or sizing modal loop. The window enters the moving or sizing modal loop when the user + * clicks the window's title bar or sizing border, or when the window passes the + * WM_SYSCOMMAND message to the DefWindowProc function and the wParam parameter of the + * message specifies the SC_MOVE or SC_SIZE value. The operation is complete when + * DefWindowProc returns. + */ + break; + + //////////////////////////////////////////////////////////////////////// + // Other events + //////////////////////////////////////////////////////////////////////// + case WM_GETTEXT: + /* An application sends a WM_GETTEXT message to copy the text that + * corresponds to a window into a buffer provided by the caller. + */ + case WM_ACTIVATEAPP: + /* The WM_ACTIVATEAPP message is sent when a window belonging to a + * different application than the active window is about to be activated. + * The message is sent to the application whose window is being activated + * and to the application whose window is being deactivated. + */ + case WM_TIMER: + /* The WIN32 docs say: + * The WM_TIMER message is posted to the installing thread's message queue + * when a timer expires. You can process the message by providing a WM_TIMER + * case in the window procedure. Otherwise, the default window procedure will + * call the TimerProc callback function specified in the call to the SetTimer + * function used to install the timer. + * + * In GHOST, we let DefWindowProc call the timer callback. + */ + break; #endif // illustrative code - -#if 0 // this is part of the 'old' NDOF system; new one coming soon! - case WM_BLND_NDOF_AXIS: - { - GHOST_TEventNDOFData ndofdata; - m_ndofManager->GHOST_NDOFGetDatas(ndofdata); - m_eventManager-> - pushEvent(new GHOST_EventNDOF( - getMilliSeconds(), - GHOST_kEventNDOFMotion, - window, ndofdata)); - } - break; - case WM_BLND_NDOF_BTN: - { - GHOST_TEventNDOFData ndofdata; - m_ndofManager->GHOST_NDOFGetDatas(ndofdata); - m_eventManager-> - pushEvent(new GHOST_EventNDOF( - getMilliSeconds(), - GHOST_kEventNDOFButton, - window, ndofdata)); - } - break; -#endif // old NDOF - } + } if (!eventSent) if (event) { diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 8fae4d6ba78..abf6886deea 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -304,10 +304,9 @@ protected: * Creates and sends mouse or multi-axis events. * @param raw a single RawInput structure * @param window The window receiving the event (the active window). - * @param x,y current mouse coordinates, which may be updated by this function * @return Whether any events (possibly more than one) were created and sent. */ - bool processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window /*, int& x, int& y */ ); + bool processRawInput(RAWINPUT const& raw, GHOST_WindowWin32* window); /** * Creates and sends mouse events for mouse movements "in between" WM_MOUSEMOVEs. @@ -333,10 +332,11 @@ protected: /** * Windows call back routine for our window class. + * This handles general errors, then passes control to handleEvent. */ static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - // non-static version of WndProc + /** Non-static version of WndProc. */ bool handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM wParam, LPARAM lParam); /** The current state of the modifier keys. */ -- cgit v1.2.3 From b0193772dae9cbb9a52cd18355393b16a6e5001c Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 25 Jul 2010 08:38:13 +0000 Subject: removing Mac C++ file (contents same as Obj-C++ file), since TortoiseSVN's 'rename' forgot to do it --- intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp | 113 ------------------------- 1 file changed, 113 deletions(-) delete mode 100644 intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp b/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp deleted file mode 100644 index c4a8a2f1831..00000000000 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include "GHOST_NDOFManagerCocoa.h" -#include "GHOST_SystemCocoa.h" - -extern "C" { - #include <3DconnexionClient/ConnexionClientAPI.h> - #include - } - -static void SpaceNavAdded(io_connect_t connection) - { - printf("SpaceNav added\n"); - } - -static void SpaceNavRemoved(io_connect_t connection) - { - printf("SpaceNav removed\n"); - } - -static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void *messageArgument) - { - GHOST_SystemCocoa* system = (GHOST_SystemCocoa*) GHOST_ISystem::getSystem(); - GHOST_NDOFManager* manager = system->getNDOFManager(); - switch (messageType) - { - case kConnexionMsgDeviceState: - { - ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument; - switch (s->command) - { - case kConnexionCmdHandleAxis: - manager->updateTranslation(s->axis, s->time); - manager->updateRotation(s->axis + 3, s->time); - system->notifyExternalEventProcessed(); - break; - - case kConnexionCmdHandleButtons: - manager->updateButtons(s->buttons, s->time); - system->notifyExternalEventProcessed(); - break; - } - break; - } - case kConnexionMsgPrefsChanged: - printf("prefs changed\n"); // this includes app switches - break; - case kConnexionMsgDoAction: - printf("do action\n"); // no idea what this means - // 'calibrate device' in System Prefs sends this - break; - default: - printf(" mystery event\n"); - } - } - -GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) - : GHOST_NDOFManager(sys) - { - if (available()) - { - OSErr error = InstallConnexionHandlers(SpaceNavEvent, SpaceNavAdded, SpaceNavRemoved); - if (error) - { - printf(" error = %d\n", error); - return; - } - - // Pascal string *and* a four-letter constant. How old-skool. - m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pBlender", - kConnexionClientModeTakeOver, kConnexionMaskAll); - - printf("client id = %d\n", m_clientID); - } - else - { - printf(" SpaceNav driver not found\n"); - // This isn't a hard error, just means the user doesn't have a SpaceNavigator. - } - } - -GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() - { - UnregisterConnexionClient(m_clientID); - CleanupConnexionHandlers(); - } - -bool GHOST_NDOFManagerCocoa::available() - { -// extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); -// ^-- not needed since the entire framework is weak-linked - return InstallConnexionHandlers != NULL; - } -- cgit v1.2.3 From f399481251a4d375a494517925c64b3b3c6db7e8 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 7 Aug 2010 10:57:15 +0000 Subject: SpaceNav turntable and fit in 3D view. Tablet data rides with cursor/button events (incomplete! Mac-only for now). Grease pencil works better with pen. --- intern/ghost/GHOST_Types.h | 100 ++-- intern/ghost/intern/GHOST_EventButton.h | 2 +- intern/ghost/intern/GHOST_EventCursor.h | 1 + intern/ghost/intern/GHOST_EventManager.cpp | 4 +- intern/ghost/intern/GHOST_EventNDOF.h | 48 +- intern/ghost/intern/GHOST_NDOFManager.cpp | 41 +- intern/ghost/intern/GHOST_NDOFManager.h | 4 + intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 10 +- intern/ghost/intern/GHOST_SystemCocoa.h | 16 +- intern/ghost/intern/GHOST_SystemCocoa.mm | 62 ++- intern/ghost/intern/GHOST_WindowCocoa.h | 8 +- intern/ghost/intern/GHOST_WindowCocoa.mm | 109 ++-- source/blender/blenlib/intern/math_rotation.c | 6 +- source/blender/editors/gpencil/gpencil_paint.c | 14 +- source/blender/editors/space_view3d/view3d_edit.c | 565 ++++++--------------- .../blender/editors/space_view3d/view3d_intern.h | 4 +- source/blender/editors/space_view3d/view3d_ops.c | 8 +- source/blender/makesdna/DNA_view3d_types.h | 16 +- source/blender/windowmanager/WM_types.h | 14 + .../blender/windowmanager/intern/wm_event_system.c | 512 +++++++++++-------- source/blender/windowmanager/intern/wm_window.c | 3 - source/blender/windowmanager/wm.h | 1 - source/blender/windowmanager/wm_event_types.h | 59 ++- 23 files changed, 764 insertions(+), 843 deletions(-) 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; - -public: - GHOST_EventNDOFMotion(GHOST_TUns64 time) - : GHOST_Event(time, GHOST_kEventNDOFMotion, NULL) -// , m_data(&m_axisData) - { - m_data = &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; + } + }; + 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 */ - -- cgit v1.2.3 From ced1bd9e7dd5bc3e14d7f0f5e09a7b65f3ea2be2 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 8 Aug 2010 05:08:35 +0000 Subject: Windows shell/IE #define. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 1 + intern/ghost/intern/GHOST_SystemWin32.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index cada3f68975..c1c6f874222 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -38,6 +38,7 @@ #include // for debug [mce] +#define _WIN32_IE 0x501 /* shipped before XP, so doesn't impose additional req'm'ts */ #include diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 9febe7779bc..03bf6f08df8 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -35,12 +35,12 @@ #ifndef WIN32 #error WIN32 only! -#endif // WIN32 +#endif #define _WIN32_WINNT 0x501 // require Windows XP or newer #define WIN32_LEAN_AND_MEAN #include -#include +#include // for drag-n-drop #include "GHOST_System.h" -- cgit v1.2.3 From 4bf887d4d3592e955144388305ae801040a57701 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 10 Aug 2010 09:51:22 +0000 Subject: SpaceNav works in 3D view on Windows. Cleaned up related WIP code. --- intern/ghost/GHOST_ISystem.h | 1 - intern/ghost/intern/GHOST_EventManager.cpp | 22 ++++------ intern/ghost/intern/GHOST_EventManager.h | 35 ++++++---------- intern/ghost/intern/GHOST_NDOFManager.cpp | 14 +++---- intern/ghost/intern/GHOST_System.cpp | 15 +++---- intern/ghost/intern/GHOST_SystemWin32.cpp | 47 +++++++++++++++------- intern/ghost/intern/GHOST_WindowManager.cpp | 2 +- source/blender/editors/space_view3d/view3d_edit.c | 3 +- .../blender/windowmanager/intern/wm_event_system.c | 1 - 9 files changed, 67 insertions(+), 73 deletions(-) diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index ab974508145..b759b98f0bc 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -400,4 +400,3 @@ protected: }; #endif // _GHOST_ISYSTEM_H_ - diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp index b566c1e38c8..7fd3a0971a5 100644 --- a/intern/ghost/intern/GHOST_EventManager.cpp +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -39,14 +39,9 @@ #include "GHOST_Debug.h" // for testing lo-fi -#include "GHOST_EventPrinter.h" -#include -using namespace std; - -GHOST_EventManager::GHOST_EventManager() -{ -} - +// #include "GHOST_EventPrinter.h" +// #include +// using namespace std; GHOST_EventManager::~GHOST_EventManager() { @@ -110,14 +105,12 @@ 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 (no it doesn't) bool handled = false; if (event) { TConsumerVector::iterator iter; for (iter = m_consumers.begin(); iter != m_consumers.end(); iter++) { if ((*iter)->processEvent(event)) { handled = true; - // break; } } } @@ -125,7 +118,7 @@ bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event) } #if 0 // disable to test a variant -bool GHOST_EventManager::dispatchEvent_original(GHOST_IEvent* event) +bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event) /* original version */ { bool handled; if (event) { @@ -190,6 +183,7 @@ bool GHOST_EventManager::dispatchEvents_lo_fi() // cout << "\n--- lo-fi dispatch ---"; // cout << "\ndiscard:"; + while ((event = popEvent()) != NULL) { if (event->getType() == GHOST_kEventCursorMove) { // just a simple (x,y) pair, nothing much to adjust @@ -204,7 +198,7 @@ bool GHOST_EventManager::dispatchEvents_lo_fi() if (!dispatchEvent(event)) allHandled = false; } - + // finally dispatch the single cursor update if (cursorMove) { // cout << "\nsend:"; @@ -268,7 +262,7 @@ void GHOST_EventManager::removeWindowEvents(GHOST_IWindow* window) GHOST_IEvent* event = *iter; if (event->getWindow() == window) { - GHOST_PRINT("GHOST_EventManager::removeWindowEvents(): removing event\n"); + GHOST_PRINT("GHOST_EventManager::removeWindowEvents(): removing event\n"); /* * Found an event for this window, remove it. * The iterator will become invalid. @@ -293,7 +287,7 @@ void GHOST_EventManager::removeTypeEvents(GHOST_TEventType type, GHOST_IWindow* GHOST_IEvent* event = *iter; if ((event->getType() == type) && (!window || (event->getWindow() == window))) { - GHOST_PRINT("GHOST_EventManager::removeTypeEvents(): removing event\n"); + GHOST_PRINT("GHOST_EventManager::removeTypeEvents(): removing event\n"); /* * Found an event of this type for the window, remove it. * The iterator will become invalid. diff --git a/intern/ghost/intern/GHOST_EventManager.h b/intern/ghost/intern/GHOST_EventManager.h index 5071adb1bd4..c73abed2f7e 100644 --- a/intern/ghost/intern/GHOST_EventManager.h +++ b/intern/ghost/intern/GHOST_EventManager.h @@ -53,32 +53,32 @@ public: /** * Constructor. */ - GHOST_EventManager(); + GHOST_EventManager() {}; /** * Destructor. */ - virtual ~GHOST_EventManager(); + ~GHOST_EventManager(); /** * Returns the number of events currently on the stack. * @return The number of events on the stack. */ - virtual GHOST_TUns32 getNumEvents(); + GHOST_TUns32 getNumEvents(); /** * Returns the number of events of a certain type currently on the stack. * @param type The type of events to be counted. * @return The number of events on the stack of this type. */ - virtual GHOST_TUns32 getNumEvents(GHOST_TEventType type); + GHOST_TUns32 getNumEvents(GHOST_TEventType type); /** * Return the event at the top of the stack without removal. * Do not delete the event! * @return The event at the top of the stack. */ - virtual GHOST_IEvent* peekEvent(); + GHOST_IEvent* peekEvent(); /** * Pushes an event on the stack. @@ -86,27 +86,27 @@ public: * Do not delete the event! * @param event The event to push on the stack. */ - virtual GHOST_TSuccess pushEvent(GHOST_IEvent* event); + GHOST_TSuccess pushEvent(GHOST_IEvent* event); /** * Dispatches the given event directly, bypassing the event stack. * @return Indication as to whether any of the consumers handled the event. */ - virtual bool dispatchEvent(GHOST_IEvent* event); + bool dispatchEvent(GHOST_IEvent* event); /** * Dispatches the event at the back of the stack. * The event will be removed from the stack. * @return Indication as to whether any of the consumers handled the event. */ - virtual bool dispatchEvent(); + bool dispatchEvent(); /** * Dispatches all the events on the stack. * The event stack will be empty afterwards. * @return Indication as to whether any of the consumers handled the events. */ - virtual bool dispatchEvents(); + bool dispatchEvents(); /** * Dispatches most events on the stack, consolidating cursor moves into a single move. @@ -115,29 +115,25 @@ public: */ bool dispatchEvents_lo_fi(); - /** * Adds a consumer to the list of event consumers. * @param consumer The consumer added to the list. * @return Indication as to whether addition has succeeded. */ - virtual GHOST_TSuccess addConsumer(GHOST_IEventConsumer* consumer); + GHOST_TSuccess addConsumer(GHOST_IEventConsumer* consumer); /** * Removes a consumer from the list of event consumers. * @param consumer The consumer removed from the list. * @return Indication as to whether removal has succeeded. */ - virtual GHOST_TSuccess removeConsumer(GHOST_IEventConsumer* consumer); + GHOST_TSuccess removeConsumer(GHOST_IEventConsumer* consumer); /** * Removes all events for a window from the stack. * @param window The window to remove events for. */ - virtual void - removeWindowEvents( - GHOST_IWindow* window - ); + void removeWindowEvents(GHOST_IWindow* window); /** * Removes all events of a certain type from the stack. @@ -146,11 +142,7 @@ public: * @param type The type of events to be removed. * @param window The window to remove the events for. */ - virtual void - removeTypeEvents( - GHOST_TEventType type, - GHOST_IWindow* window = 0 - ); + void removeTypeEvents(GHOST_TEventType type, GHOST_IWindow* window = 0); protected: /** @@ -179,4 +171,3 @@ protected: }; #endif // _GHOST_EVENT_MANAGER_H_ - diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 1c00e991520..b14274278ad 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -55,8 +55,7 @@ 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(); + GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); unsigned short diff = m_buttons ^ buttons; @@ -70,10 +69,9 @@ void GHOST_NDOFManager::updateButtons(unsigned short buttons, GHOST_TUns64 time) 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"); + // printf("sending button %d %s\n", data->button, (data->action == GHOST_kPress) ? "pressed" : "released"); m_system.pushEvent(event); } @@ -87,8 +85,7 @@ bool GHOST_NDOFManager::sendMotionEvent() if (m_atRest) return false; - GHOST_System* system = (GHOST_System*) GHOST_System::getSystem(); - GHOST_IWindow* window = system->getWindowManager()->getActiveWindow(); + GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, window); GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData(); @@ -109,11 +106,10 @@ bool GHOST_NDOFManager::sendMotionEvent() 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); +// printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", +// data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, data->dt); m_system.pushEvent(event); diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 4e0888a87a7..a6b4e104c90 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -37,7 +37,6 @@ #include "GHOST_System.h" #include -#include /* just for printf */ #include "GHOST_DisplayManager.h" #include "GHOST_EventManager.h" @@ -196,18 +195,16 @@ bool GHOST_System::getFullScreen(void) bool GHOST_System::dispatchEvents() { + bool handled = false; + // NDOF Motion event is sent only once per dispatch, so do it now: - m_ndofManager->sendMotionEvent(); + handled |= m_ndofManager->sendMotionEvent(); - bool handled; if (m_eventManager) { if (m_input_fidelity_hint == LO_FI) - handled = m_eventManager->dispatchEvents_lo_fi(); + handled |= m_eventManager->dispatchEvents_lo_fi(); else - handled = m_eventManager->dispatchEvents(); - } - else { - handled = false; + handled |= m_eventManager->dispatchEvents(); } m_timerManager->fireTimers(getMilliSeconds()); @@ -276,8 +273,6 @@ GHOST_TSuccess GHOST_System::init() m_timerManager = new GHOST_TimerManager (); m_windowManager = new GHOST_WindowManager (); m_eventManager = new GHOST_EventManager (); -// m_ndofManager = new GHOST_NDOFManager(); -// Each platform now has their own NDOFManager subclass #ifdef GHOST_DEBUG if (m_eventManager) { diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index c1c6f874222..bb9b3ec450e 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -38,7 +38,7 @@ #include // for debug [mce] -#define _WIN32_IE 0x501 /* shipped before XP, so doesn't impose additional req'm'ts */ +#define _WIN32_IE 0x501 /* shipped before XP, so doesn't impose additional requirements */ #include @@ -113,7 +113,7 @@ GHOST_SystemWin32::GHOST_SystemWin32() // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32. OleInitialize(0); - m_input_fidelity_hint = HI_FI; // just for testing... + m_input_fidelity_hint = LO_FI; // just for testing... // register for RawInput devices RAWINPUTDEVICE devices[1]; @@ -180,10 +180,8 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow( window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples); if (window) { if (window->getValid()) { - // Store the pointer to the window -// if (state != GHOST_kWindowStateFullScreen) { - m_windowManager->addWindow(window); -// } + m_windowManager->addWindow(window); + m_windowManager->setActiveWindow(window); } else { // An invalid window could be one that was used to test for AA @@ -595,7 +593,15 @@ GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, bool k GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window) { - return new GHOST_Event(getSystem()->getMilliSeconds(), type, window); + GHOST_System* system = (GHOST_System*)getSystem(); + + if (type == GHOST_kEventWindowActivate) + { + puts("activating window"); + system->getWindowManager()->setActiveWindow(window); + } + + return new GHOST_Event(system->getMilliSeconds(), type, window); } GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType, @@ -645,13 +651,12 @@ vendor ID No other registered devices use the c62_ space, so a simple mask will work! */ - // The NDOF manager sends button changes immediately, and *pretends* to // send motion. Mark as 'sent' so motion will always get dispatched. eventSent = true; // multiple events per RAWHID? MSDN hints at this. - printf("%d events\n", (int)raw.data.hid.dwCount); + // printf("%d events\n", (int)raw.data.hid.dwCount); BYTE const* data = &raw.data.hid.bRawData; // MinGW's definition (below) doesn't agree with MSDN reference for bRawData: @@ -688,6 +693,7 @@ No other registered devices use the c62_ space, so a simple mask will work! { unsigned short buttons; memcpy(&buttons, data + 1, sizeof(buttons)); +#if 0 printf("buttons:"); if (buttons) { @@ -699,6 +705,7 @@ No other registered devices use the c62_ space, so a simple mask will work! } else printf(" none\n"); +#endif m_ndofManager->updateButtons(buttons, getMilliSeconds()); break; } @@ -999,8 +1006,20 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM case WM_INPUT: { - puts("WM_INPUT"); + // Raw mouse input benefitted from the buffered method, + // but SpaceNav gets along fine (better, even) grabbing single events. + RAWINPUT raw; + RAWINPUT* raw_ptr = &raw; + UINT rawSize = sizeof(RAWINPUT); + + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); + eventSent |= processRawInput(raw, window); + + // necessary? + // DefRawInputProc(&raw_ptr, 1, sizeof(RAWINPUTHEADER)); + +#if 0 #define RAWCOUNT 10 // just a guess that we'll receive up to 10 event reports // the following code fetches all available, 10 at a time @@ -1028,20 +1047,20 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM RAWINPUT const& raw = rawBuffer[i]; eventSent |= processRawInput(raw, window); } - + // clear processed events from the queue DefRawInputProc((RAWINPUT**)&rawBuffer, n, sizeof(RAWINPUTHEADER)); } } +#endif break; } case WM_MOUSEWHEEL: - puts("WM_MOUSEWHEEL"); /* The WM_MOUSEWHEEL message is sent to the focus window * when the mouse wheel is rotated. The DefWindowProc * function propagates the message to the window's parent. * There should be no internal forwarding of the message, - * since DefWindowProc propagates it up the parent chain + * since DefWindowProc propagates it up the parent chain * until it finds a window that processes it. */ event = processWheelEvent(window, wParam, lParam); @@ -1102,7 +1121,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM case WM_PAINT: /* An application sends the WM_PAINT message when the system or another application * makes a request to paint a portion of an application's window. The message is sent - * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage + * when the UpdateWindow or RedrawWindow function is called, or by the DispatchMessage * function when the application obtains a WM_PAINT message by using the GetMessage or * PeekMessage function. */ diff --git a/intern/ghost/intern/GHOST_WindowManager.cpp b/intern/ghost/intern/GHOST_WindowManager.cpp index 1ac357ac97f..aa932663e16 100644 --- a/intern/ghost/intern/GHOST_WindowManager.cpp +++ b/intern/ghost/intern/GHOST_WindowManager.cpp @@ -212,4 +212,4 @@ bool GHOST_WindowManager::getAnyModifiedState() } return isAnyModified; -} \ No newline at end of file +} diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 8dd901d9e54..874a2f778f5 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -27,7 +27,6 @@ */ #include -#include #include #include @@ -879,6 +878,7 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } +#if 0 static int viewndof_invoke_1st_try(bContext *C, wmOperator *op, wmEvent *event) { wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; @@ -961,6 +961,7 @@ static int viewndof_invoke_2nd_try(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } +#endif void VIEW3D_OT_ndof(struct wmOperatorType *ot) { diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index e281e65539e..bce1cc22f7f 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -29,7 +29,6 @@ #include #include #include -#include // [mce] debug, remove when finished #include "DNA_listBase.h" #include "DNA_screen_types.h" -- cgit v1.2.3 From 1c2d36344ca1dbeb8e1517c3e58590728109eccc Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 10 Aug 2010 09:56:39 +0000 Subject: Linux compiles again, no SpaceNav yet. --- intern/ghost/intern/GHOST_SystemX11.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index e658df3ce95..dc519039af6 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -75,7 +75,7 @@ typedef struct NDOFPlatformInfo { Display *display; Window window; -// volatile GHOST_TEventNDOFData *currValues; + volatile GHOST_TEventNDOFMotionData *currValues; Atom cmdAtom; Atom motionAtom; Atom btnPressAtom; @@ -173,7 +173,7 @@ init( if (success) { - m_ndofManager = new GHOST_NDOFManagerX11; + m_ndofManager = new GHOST_NDOFManagerX11(*this); m_displayManager = new GHOST_DisplayManagerX11(this); @@ -656,8 +656,8 @@ GHOST_SystemX11::processEvent(XEvent *xe) // [mce] look into this soon, as in find out why some values // are shifted and where this message originates. - m_ndofManager->updateTranslation(t, getMilliseconds); - m_ndofManager->updateRotation(r, getMilliseconds); + m_ndofManager->updateTranslation(t, getMilliSeconds()); + m_ndofManager->updateRotation(r, getMilliSeconds()); // g_event = new GHOST_EventNDOF(getMilliSeconds(), // GHOST_kEventNDOFMotion, @@ -670,7 +670,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) // data.buttons = xcme.data.s[2]; unsigned short buttons = xcme.data.s[2]; - m_ndofManager->updateButtons(buttons, getMilliseconds()); + m_ndofManager->updateButtons(buttons, getMilliSeconds()); // g_event = new GHOST_EventNDOF(getMilliSeconds(), // GHOST_kEventNDOFButton, -- cgit v1.2.3 From 485d1ef06ebd3d25945b14f7987ce84016b5d311 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 12 Aug 2010 04:03:40 +0000 Subject: Updated Win32 tablet code. --- intern/ghost/intern/GHOST_System.cpp | 30 +-- intern/ghost/intern/GHOST_SystemWin32.cpp | 104 ++++---- intern/ghost/intern/GHOST_SystemWin32.h | 7 +- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 300 +++++++++++++++++++++++ intern/ghost/intern/GHOST_TabletManagerWin32.h | 82 +++++++ intern/ghost/intern/GHOST_WindowCocoa.mm | 2 - intern/ghost/intern/GHOST_WindowWin32.cpp | 53 ++-- intern/ghost/intern/GHOST_WindowWin32.h | 57 +++-- intern/ghost/intern/Utils.c | 182 -------------- intern/ghost/intern/Utils.h | 94 ------- 10 files changed, 518 insertions(+), 393 deletions(-) create mode 100644 intern/ghost/intern/GHOST_TabletManagerWin32.cpp create mode 100644 intern/ghost/intern/GHOST_TabletManagerWin32.h delete mode 100644 intern/ghost/intern/Utils.c delete mode 100644 intern/ghost/intern/Utils.h diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index a6b4e104c90..ea12421b53c 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -291,29 +291,15 @@ GHOST_TSuccess GHOST_System::init() GHOST_TSuccess GHOST_System::exit() { - if (getFullScreen()) { + if (getFullScreen()) endFullScreen(); - } - if (m_displayManager) { - delete m_displayManager; - m_displayManager = 0; - } - if (m_windowManager) { - delete m_windowManager; - m_windowManager = 0; - } - if (m_timerManager) { - delete m_timerManager; - m_timerManager = 0; - } - if (m_eventManager) { - delete m_eventManager; - m_eventManager = 0; - } - if (m_ndofManager) { - delete m_ndofManager; - m_ndofManager = 0; - } + + delete m_displayManager; + delete m_windowManager; + delete m_timerManager; + delete m_eventManager; + delete m_ndofManager; + return GHOST_kSuccess; } diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index bb9b3ec450e..9797b5c2924 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -44,10 +44,10 @@ // win64 doesn't define GWL_USERDATA #ifdef WIN32 -#ifndef GWL_USERDATA -#define GWL_USERDATA GWLP_USERDATA -#define GWL_WNDPROC GWLP_WNDPROC -#endif + #ifndef GWL_USERDATA + #define GWL_USERDATA GWLP_USERDATA + #define GWL_WNDPROC GWLP_WNDPROC + #endif #endif #include "GHOST_Debug.h" @@ -61,44 +61,45 @@ #include "GHOST_WindowManager.h" #include "GHOST_WindowWin32.h" #include "GHOST_NDOFManagerWin32.h" +#include "GHOST_TabletManagerWin32.h" // Key code values not found in winuser.h #ifndef VK_MINUS -#define VK_MINUS 0xBD -#endif // VK_MINUS + #define VK_MINUS 0xBD +#endif #ifndef VK_SEMICOLON -#define VK_SEMICOLON 0xBA -#endif // VK_SEMICOLON + #define VK_SEMICOLON 0xBA +#endif #ifndef VK_PERIOD -#define VK_PERIOD 0xBE -#endif // VK_PERIOD + #define VK_PERIOD 0xBE +#endif #ifndef VK_COMMA -#define VK_COMMA 0xBC -#endif // VK_COMMA + #define VK_COMMA 0xBC +#endif #ifndef VK_QUOTE -#define VK_QUOTE 0xDE -#endif // VK_QUOTE + #define VK_QUOTE 0xDE +#endif #ifndef VK_BACK_QUOTE -#define VK_BACK_QUOTE 0xC0 -#endif // VK_BACK_QUOTE + #define VK_BACK_QUOTE 0xC0 +#endif #ifndef VK_SLASH -#define VK_SLASH 0xBF -#endif // VK_SLASH + #define VK_SLASH 0xBF +#endif #ifndef VK_BACK_SLASH -#define VK_BACK_SLASH 0xDC -#endif // VK_BACK_SLASH + #define VK_BACK_SLASH 0xDC +#endif #ifndef VK_EQUALS -#define VK_EQUALS 0xBB -#endif // VK_EQUALS + #define VK_EQUALS 0xBB +#endif #ifndef VK_OPEN_BRACKET -#define VK_OPEN_BRACKET 0xDB -#endif // VK_OPEN_BRACKET + #define VK_OPEN_BRACKET 0xDB +#endif #ifndef VK_CLOSE_BRACKET -#define VK_CLOSE_BRACKET 0xDD -#endif // VK_CLOSE_BRACKET + #define VK_CLOSE_BRACKET 0xDD +#endif #ifndef VK_GR_LESS -#define VK_GR_LESS 0xE2 -#endif // VK_GR_LESS + #define VK_GR_LESS 0xE2 +#endif GHOST_SystemWin32::GHOST_SystemWin32() @@ -106,14 +107,14 @@ GHOST_SystemWin32::GHOST_SystemWin32() m_separateLeftRight(false), m_separateLeftRightInitialized(false) { - m_displayManager = new GHOST_DisplayManagerWin32 (); + m_displayManager = new GHOST_DisplayManagerWin32; GHOST_ASSERT(m_displayManager, "GHOST_SystemWin32::GHOST_SystemWin32(): m_displayManager==0\n"); m_displayManager->initialize(); // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32. OleInitialize(0); - m_input_fidelity_hint = LO_FI; // just for testing... + m_input_fidelity_hint = HI_FI; // just for testing... // register for RawInput devices RAWINPUTDEVICE devices[1]; @@ -132,6 +133,8 @@ GHOST_SystemWin32::~GHOST_SystemWin32() { // Shutdown COM OleUninitialize(); + + delete m_tabletManager; } @@ -176,16 +179,19 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow( GHOST_TWindowState state, GHOST_TDrawingContextType type, bool stereoVisual, const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow ) { - GHOST_Window* window = 0; - window = new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples); + GHOST_WindowWin32* window = + new GHOST_WindowWin32 (this, title, left, top, width, height, state, type, stereoVisual, numOfAASamples); + if (window) { if (window->getValid()) { m_windowManager->addWindow(window); m_windowManager->setActiveWindow(window); + if (m_tabletManager->available()) + window->becomeTabletAware(m_tabletManager); } else { // An invalid window could be one that was used to test for AA - GHOST_Window *other_window = ((GHOST_WindowWin32*)window)->getNextWindow(); + GHOST_WindowWin32* other_window = (GHOST_WindowWin32*) window->getNextWindow(); delete window; window = 0; @@ -329,6 +335,7 @@ GHOST_TSuccess GHOST_SystemWin32::init() GHOST_TSuccess success = GHOST_System::init(); m_ndofManager = new GHOST_NDOFManagerWin32(*this); + m_tabletManager = new GHOST_TabletManagerWin32; /* Disable scaling on high DPI displays on Vista */ HMODULE user32 = ::LoadLibraryA("user32.dll"); @@ -374,14 +381,6 @@ GHOST_TSuccess GHOST_SystemWin32::init() return success; } - -GHOST_TSuccess GHOST_SystemWin32::exit() -{ - // [mce] since this duplicates its super, why bother? - return GHOST_System::exit(); -} - - GHOST_TKey GHOST_SystemWin32::convertKey(WPARAM wParam, LPARAM lParam) const { GHOST_TKey key; @@ -497,9 +496,17 @@ void GHOST_SystemWin32::processModifierKeys(GHOST_IWindow *window) ((GHOST_SystemWin32*)getSystem())->storeModifierKeys(newModifiers); } +bool eventIsFromTablet() + { + // bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs + return GetMessageExtraInfo() & 0x7f; // true for tablet mouse, not just pen + } GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask) { + if (eventIsFromTablet()) + return NULL; + return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask); } @@ -924,11 +931,13 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM //////////////////////////////////////////////////////////////////////// case WT_PACKET: puts("WT_PACKET"); - window->processWin32TabletEvent(wParam, lParam); + // window->processWin32TabletEvent(wParam, lParam); + m_tabletManager->processPackets(window); break; case WT_CSRCHANGE: case WT_PROXIMITY: - window->processWin32TabletInitEvent(); + // window->processWin32TabletInitEvent(); + m_tabletManager->changeTool(window); break; //////////////////////////////////////////////////////////////////////// @@ -977,11 +986,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM case WM_MOUSEMOVE: { - // bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs - int tabletTool = GetMessageExtraInfo() & 0x7f; // true for tablet mouse, not just pen - if (tabletTool) - puts("(from tablet)"); - else + if (!eventIsFromTablet()) { int xPrev = mousePosX; int yPrev = mousePosY; @@ -992,7 +997,8 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM if (m_input_fidelity_hint == HI_FI) { - /* int n = */ getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); + // int n = + getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); // printf("%d more mouse points found\n", n); } diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 03bf6f08df8..877b3306572 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -57,6 +57,7 @@ class GHOST_EventWindow; class GHOST_EventDragnDrop; class GHOST_WindowWin32; +class GHOST_TabletManagerWin32; /** * WIN32 Implementation of GHOST_System class. @@ -236,7 +237,7 @@ protected: * Closes the system down. * @return A success value. */ - virtual GHOST_TSuccess exit(); +// virtual GHOST_TSuccess exit(); /** * Converts raw WIN32 key codes from the wndproc to GHOST keys. @@ -356,7 +357,8 @@ protected: bool m_separateLeftRight; /** Stores the initialization state of the member m_leftRightDistinguishable. */ bool m_separateLeftRightInitialized; - + + GHOST_TabletManagerWin32* m_tabletManager; }; inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const @@ -370,4 +372,3 @@ inline void GHOST_SystemWin32::storeModifierKeys(const GHOST_ModifierKeys& keys) } #endif // _GHOST_SYSTEM_WIN32_H_ - diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp new file mode 100644 index 00000000000..c82ef574b4a --- /dev/null +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -0,0 +1,300 @@ +#include "GHOST_TabletManagerWin32.h" +#include "GHOST_WindowWin32.h" +#include +#include + +#define PACKETDATA PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE +#define PACKETTILT PKEXT_ABSOLUTE +#define PACKETMODE PK_BUTTONS + +#include "pktdef.h" + +#define MAX_QUEUE_SIZE 128 + +GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() + { + resetActiveTool(); + + // open WinTab + lib_Wintab = LoadLibrary("wintab32.dll"); + + if (lib_Wintab) + { + // connect function pointers + func_Open = (WTOPENA) GetProcAddress(lib_Wintab,"WTOpenA"); + func_Close = (WTCLOSE) GetProcAddress(lib_Wintab,"WTClose"); + func_Info = (WTINFOA) GetProcAddress(lib_Wintab,"WTInfoA"); + func_QueueSizeSet = (WTQUEUESIZESET) GetProcAddress(lib_Wintab,"WTQueueSizeSet"); + func_PacketsGet = (WTPACKETSGET) GetProcAddress(lib_Wintab,"WTPacketsGet"); + + WORD specV, implV; + func_Info(WTI_INTERFACE, IFC_SPECVERSION, &specV); + func_Info(WTI_INTERFACE, IFC_IMPLVERSION, &implV); + printf("Wintab version %d.%d (%d.%d)\n", + HIBYTE(specV), LOBYTE(specV), HIBYTE(implV), LOBYTE(implV)); + + // query for overall capabilities and ranges + char tabletName[LC_NAMELEN]; + if (func_Info(WTI_DEVICES, DVC_NAME, tabletName)) + puts(tabletName); + + AXIS xRange, yRange; + func_Info(WTI_DEVICES, DVC_X, &xRange); + func_Info(WTI_DEVICES, DVC_Y, &yRange); + + printf("active area: %dx%d\n", xRange.axMax, yRange.axMax); + + AXIS pressureRange; + hasPressure = func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange) && pressureRange.axMax != 0; + + printf("pressure sensitivity: "); + if (hasPressure) + { + printf("%d to %d\n", pressureRange.axMin, pressureRange.axMax); + pressureScale = 1.f / pressureRange.axMax; + } + else + { + printf("none\n"); + pressureScale = 0.f; + } + + AXIS tiltRange; + hasTilt = func_Info(WTI_DEVICES, DVC_ORIENTATION, &tiltRange) && tiltRange.axMax != 0; + + printf("tilt sensitivity: "); + if (hasTilt) + { + printf("%d to %d\n", tiltRange.axMin, tiltRange.axMax); + tiltScale = 1.f / tiltRange.axMax; + } + else + { + printf("none\n"); + tiltScale = 0.f; + } + } + } + +GHOST_TabletManagerWin32::~GHOST_TabletManagerWin32() + { + // close WinTab + FreeLibrary(lib_Wintab); + } + +bool GHOST_TabletManagerWin32::available() + { + return lib_Wintab // driver installed + && func_Info(0,0,NULL); // tablet plugged in + } + +void GHOST_TabletManagerWin32::resetActiveTool() + { + activeTool.type = TABLET_NONE; + activeTool.hasPressure = false; + activeTool.hasTilt = false; + } + +HCTX GHOST_TabletManagerWin32::contextForWindow(GHOST_WindowWin32* window) + { + std::map::iterator i = contexts.find(window); + if (i == contexts.end()) + return 0; // not found + else + return i->second; + } + +void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) + { + if (contextForWindow(window) != 0) + // this window already has a tablet context + return; + + // set up context + LOGCONTEXT archetype; + func_Info(WTI_DEFCONTEXT, 0, &archetype); + + strcpy(archetype.lcName, "merwin special"); + archetype.lcPktData = PACKETDATA; + archetype.lcPktMode = PACKETMODE; + archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES; + +// BEGIN from Wacom's TILTTEST.c + /* output the data in screen coords */ + archetype.lcOutOrgX = archetype.lcOutOrgY = 0; + archetype.lcOutExtX = GetSystemMetrics(SM_CXSCREEN); + /* move origin to upper left */ + archetype.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN); +// END + + // open the context + HCTX context = func_Open(window->getHWND(), &archetype, TRUE); + + // request a deep packet queue + int tabletQueueSize = MAX_QUEUE_SIZE; + while (!func_QueueSizeSet(context, tabletQueueSize)) + --tabletQueueSize; + printf("tablet queue size: %d\n", tabletQueueSize); + + contexts[window] = context; + } + +void GHOST_TabletManagerWin32::closeForWindow(GHOST_WindowWin32* window) + { + HCTX context = contextForWindow(window); + + if (context) + { + func_Close(context); + // also remove it from our books: + contexts.erase(contexts.find(window)); + } + } + +void GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) + { + HCTX context = contextForWindow(window); + + if (context) + { + PACKET packets[MAX_QUEUE_SIZE]; + int n = func_PacketsGet(context, MAX_QUEUE_SIZE, packets); + printf("processing %d packets from ", n); + + // every packet from a WT_PACKET message comes from the same tool + switch (packets[0].pkCursor) { + case 0: /* first device */ + case 3: /* second device */ + activeTool.type = TABLET_MOUSE; + puts("mouse"); + break; + case 1: + case 4: + activeTool.type = TABLET_PEN; + puts("pen"); + break; + case 2: + case 5: + activeTool.type = TABLET_ERASER; + puts("eraser"); + break; + } + + for (int i = 0; i < n; ++i) + { + PACKET const& packet = packets[i]; + TabletToolData data = {activeTool}; + int x = packet.pkX; + int y = packet.pkY; + + if (data.tool.hasPressure) + { + if (packet.pkNormalPressure) + data.pressure = pressureScale * packet.pkNormalPressure; + else + data.tool.hasPressure = false; + } + + if (data.tool.hasTilt) + { + data.tilt_x = tiltScale * packet.pkTilt.tiltX; + data.tilt_y = tiltScale * packet.pkTilt.tiltY; + } + + printf(" %.3f @ (%d,%d) /%.2f,%.2f/\n", data.pressure, x, y, data.tilt_x, data.tilt_y); + } + } + } + +void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window) + { + HCTX context = contextForWindow(window); + + if (context) + { + puts("-- changing tool --"); + + if (hasPressure) + { + puts(" - pressure"); + activeTool.hasPressure = true; // not necessarily, but good enough for testing + } + + if (hasTilt) + { + puts(" - tilt"); + activeTool.hasTilt = true; + } + +#if 0 +#define kTransducerDeviceIdBitMask 0x0001 +#define kTransducerAbsXBitMask 0x0002 +#define kTransducerAbsYBitMask 0x0004 +#define kTransducerVendor1BitMask 0x0008 +#define kTransducerVendor2BitMask 0x0010 +#define kTransducerVendor3BitMask 0x0020 +#define kTransducerButtonsBitMask 0x0040 +#define kTransducerTiltXBitMask 0x0080 +#define kTransducerTiltYBitMask 0x0100 +#define kTransducerAbsZBitMask 0x0200 +#define kTransducerPressureBitMask 0x0400 +#define kTransducerTangentialPressureBitMask 0x0800 +#define kTransducerOrientInfoBitMask 0x1000 +#define kTransducerRotationBitMask 0x2000 + + // this is what I really want to know: +// UINT active; +// UINT active2 = func_Info(WTI_CURSORS, CSR_ACTIVE, &active); +// printf("active: %d %d\n", active, active2); + + WTPKT toolData; + func_Info(WTI_CURSORS, CSR_PKTDATA, &toolData); + activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; + activeTool.hasTilt = toolData & PK_ORIENTATION; + +// UINT cap; +// UINT cap2 = func_Info(WTI_CURSORS, CSR_CAPABILITIES, &cap); + // capabilities same as Mac tablet code? Let's see... + // int cap = CGEventGetIntegerValueField(event, kCGTabletProximityEventCapabilityMask); + printf("cursor capabilities: %d %d\n", cap, cap2); + + if (cap & kTransducerDeviceIdBitMask) + printf(" - device id\n"); + if (cap & kTransducerAbsXBitMask) + printf(" - abs x\n"); + if (cap & kTransducerAbsYBitMask) + printf(" - abs y\n"); + if (cap & kTransducerAbsZBitMask) + printf(" - abs z\n"); + if (cap & kTransducerVendor1BitMask) + printf(" - vendor 1\n"); + if (cap & kTransducerVendor2BitMask) + printf(" - vendor 2\n"); + if (cap & kTransducerVendor3BitMask) + printf(" - vendor 3\n"); + if (cap & kTransducerButtonsBitMask) + printf(" - buttons\n"); + if (cap & kTransducerTiltXBitMask) + { + printf(" - tilt x\n"); + hasTilt = true; + } + if (cap & kTransducerTiltYBitMask) + { + printf(" - tilt y\n"); + hasTilt = true; + } + if (cap & kTransducerPressureBitMask) + { + printf(" - pressure\n"); + hasPressure = true; + } + if (cap & kTransducerTangentialPressureBitMask) + printf(" - tangential pressure\n"); + if (cap & kTransducerOrientInfoBitMask) + printf(" - orientation\n"); + if (cap & kTransducerRotationBitMask) + printf(" - rotation\n"); +#endif + } + } diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h new file mode 100644 index 00000000000..d6b8b1c058a --- /dev/null +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -0,0 +1,82 @@ +// safe & friendly Wintab wrapper +// by Mike Erwin, July 2010 + +#ifndef GHOST_TABLET_MANAGER_WIN32_H +#define GHOST_TABLET_MANAGER_WIN32_H + +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN +#include +#include "wintab.h" +#include + +class GHOST_WindowWin32; + +// BEGIN from Wacom's Utils.h +typedef UINT ( API * WTINFOA ) ( UINT, UINT, LPVOID ); +typedef HCTX ( API * WTOPENA ) ( HWND, LPLOGCONTEXTA, BOOL ); +typedef BOOL ( API * WTCLOSE ) ( HCTX ); +typedef BOOL ( API * WTQUEUESIZESET ) ( HCTX, int ); +typedef int ( API * WTPACKETSGET ) ( HCTX, int, LPVOID ); +// END + +typedef enum { TABLET_NONE, TABLET_PEN, TABLET_ERASER, TABLET_MOUSE } TabletToolType; + +typedef struct + { + TabletToolType type : 6; // plenty of room to grow + + // capabilities + bool hasPressure : 1; + bool hasTilt : 1; + + } TabletTool; + + +typedef struct + { + TabletTool tool; + + float pressure; + float tilt_x, tilt_y; + + } TabletToolData; + + +class GHOST_TabletManagerWin32 + { + // the Wintab library + HINSTANCE lib_Wintab; // or HMODULE? + + // WinTab function pointers + WTOPENA func_Open; + WTCLOSE func_Close; + WTINFOA func_Info; + WTQUEUESIZESET func_QueueSizeSet; + WTPACKETSGET func_PacketsGet; + + // tablet attributes + bool hasPressure; + float pressureScale; + bool hasTilt; + float tiltScale; + + // candidates for a base class: + TabletTool activeTool; + void resetActiveTool(); + + // book-keeping + std::map contexts; + HCTX contextForWindow(GHOST_WindowWin32*); + +public: + GHOST_TabletManagerWin32(); + ~GHOST_TabletManagerWin32(); + bool available(); // another base class candidate + void openForWindow(GHOST_WindowWin32* window); + void closeForWindow(GHOST_WindowWin32* window); + void processPackets(GHOST_WindowWin32* window); + void changeTool(GHOST_WindowWin32* window); + }; + +#endif diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 23535ba2f59..c7ec3b398c8 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -854,8 +854,6 @@ GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges) return GHOST_Window::setModifiedState(isUnsavedChanges); } - - GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index bf250938af1..361223a2cc8 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -38,9 +38,7 @@ #include "GHOST_WindowWin32.h" #include "GHOST_SystemWin32.h" #include "GHOST_DropTargetWin32.h" - -//#include "wintab.h" // for tablets, naturally -#include "Utils.c" // that's right, .c, with permission from Wacom +#include "GHOST_TabletManagerWin32.h" #include // for debug, remove soon [mce] // Need glew for some defines @@ -50,19 +48,19 @@ // MSVC6 still doesn't define M_PI #ifndef M_PI -#define M_PI 3.1415926536 + #define M_PI 3.1415926536 #endif // Some more multisample defines #define WGL_SAMPLE_BUFERS_ARB 0x2041 -#define WGL_SAMPLES_ARB 0x2042 +#define WGL_SAMPLES_ARB 0x2042 // win64 doesn't define GWL_USERDATA #ifdef WIN32 -#ifndef GWL_USERDATA -#define GWL_USERDATA GWLP_USERDATA -#define GWL_WNDPROC GWLP_WNDPROC -#endif + #ifndef GWL_USERDATA + #define GWL_USERDATA GWLP_USERDATA + #define GWL_WNDPROC GWLP_WNDPROC + #endif #endif LPCSTR GHOST_WindowWin32::s_windowClassName = "GHOST_WindowClass"; @@ -121,15 +119,16 @@ GHOST_WindowWin32::GHOST_WindowWin32( GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual,numOfAASamples), m_system(system), + m_tabletManager(NULL), m_hDC(0), m_hGlRc(0), m_hasMouseCaptured(false), m_nPressedButtons(0), m_customCursor(0), - m_wintab(false), - m_tabletData(NULL), - m_tablet(0), - m_maxPressure(0), +// m_wintab(false), +// m_tabletData(NULL), +// m_tablet(0), +// m_maxPressure(0), m_multisample(numOfAASamples), m_multisampleEnabled(msEnabled), m_msPixelFormat(msPixelFormat), @@ -175,10 +174,8 @@ GHOST_WindowWin32::GHOST_WindowWin32( s_windowClassName, // pointer to registered class name title, // pointer to window name WS_OVERLAPPEDWINDOW, // window style - left, // horizontal position of window - top, // vertical position of window - width, // window width - height, // window height + left, top, // window position + width, height, // window size 0, // handle to parent or owner window 0, // handle to menu or child-window identifier ::GetModuleHandle(0), // handle to application instance @@ -189,10 +186,8 @@ GHOST_WindowWin32::GHOST_WindowWin32( s_windowClassName, // pointer to registered class name title, // pointer to window name WS_POPUP | WS_MAXIMIZE, // window style - left, // horizontal position of window - top, // vertical position of window - width, // window width - height, // window height + left, top, // window position + width, height, // window size 0, // handle to parent or owner window 0, // handle to menu or child-window identifier ::GetModuleHandle(0), // handle to application instance @@ -242,6 +237,7 @@ GHOST_WindowWin32::GHOST_WindowWin32( } } +#if 0 m_wintab = LoadWintab(); if (m_wintab) { // let's see if we can initialize tablet here @@ -300,11 +296,13 @@ GHOST_WindowWin32::GHOST_WindowWin32( } } } +#endif } GHOST_WindowWin32::~GHOST_WindowWin32() { +#if 0 if (m_wintab) { if (m_tablet) gpWTClose(m_tablet); @@ -313,6 +311,11 @@ GHOST_WindowWin32::~GHOST_WindowWin32() m_tabletData = NULL; UnloadWintab(); } +#endif + + if (m_tabletManager) + m_tabletManager->closeForWindow(this); + if (m_customCursor) { DestroyCursor(m_customCursor); m_customCursor = NULL; @@ -913,6 +916,13 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cur return GHOST_kSuccess; } +void GHOST_WindowWin32::becomeTabletAware(GHOST_TabletManagerWin32* manager) +{ + m_tabletManager = manager; + m_tabletManager->openForWindow(this); +} + +#if 0 void GHOST_WindowWin32::processWin32TabletInitEvent() { if (m_wintab) { @@ -1016,6 +1026,7 @@ void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam) putchar('\n'); } } +#endif /** Reverse the bits in a GHOST_TUns8 */ static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index da3c47c39ac..6cb68d2ff52 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -34,8 +34,8 @@ #define _GHOST_WINDOW_WIN32_H_ #ifndef WIN32 -#error WIN32 only! -#endif // WIN32 + #error WIN32 only! +#endif #include "GHOST_Window.h" @@ -43,13 +43,16 @@ #define WIN32_LEAN_AND_MEAN #include +/* #include #define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR) #define PACKETMODE PK_BUTTONS #include +*/ class GHOST_SystemWin32; class GHOST_DropTargetWin32; +class GHOST_TabletManagerWin32; /* // typedefs for WinTab functions to allow dynamic loading @@ -105,7 +108,6 @@ public: * Returns the window to replace this one if it's getting replaced * @return The window replacing this one. */ - GHOST_Window *getNextWindow(); /** @@ -249,10 +251,12 @@ public: void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const; const GHOST_TabletData* GetTabletData() - { return m_tabletData; } + { return NULL; /*m_tabletData;*/ } - void processWin32TabletInitEvent(); - void processWin32TabletEvent(WPARAM wParam, LPARAM lParam); +// void processWin32TabletInitEvent(); +// void processWin32TabletEvent(WPARAM wParam, LPARAM lParam); + + void becomeTabletAware(GHOST_TabletManagerWin32*); protected: GHOST_TSuccess initMultisample(PIXELFORMATDESCRIPTOR pfd); @@ -293,37 +297,50 @@ protected: * Sets the cursor shape on the window using * native window system calls. */ - virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY); + virtual GHOST_TSuccess setWindowCustomCursorShape( + GHOST_TUns8 bitmap[16][2], + GHOST_TUns8 mask[16][2], + int hotX, int hotY + ); virtual GHOST_TSuccess setWindowCustomCursorShape( GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, - int sizex, - int sizey, - int hotX, - int hotY, - int fg_color, - int bg_color - ); - + int sizex, int sizey, + int hotX, int hotY, + int fg_color, int bg_color + ); + /** Pointer to system */ GHOST_SystemWin32 * m_system; + /** Pointer to COM IDropTarget implementor */ GHOST_DropTargetWin32 * m_dropTarget; + + /** Graphics tablet manager. System owns this, Window needs access to it. */ + GHOST_TabletManagerWin32* m_tabletManager; + /** Window handle. */ HWND m_hWnd; + /** Device context handle. */ HDC m_hDC; + /** OpenGL rendering context. */ HGLRC m_hGlRc; + /** The first created OpenGL context (for sharing display lists) */ static HGLRC s_firsthGLRc; + /** The first created device context handle. */ static HDC s_firstHDC; + /** Flag for if window has captured the mouse */ bool m_hasMouseCaptured; + /** Count of number of pressed buttons */ int m_nPressedButtons; + /** HCURSOR structure of the custom cursor */ HCURSOR m_customCursor; @@ -332,15 +349,15 @@ protected: /** WinTab dll handle */ // HMODULE m_wintab; - bool m_wintab; +// bool m_wintab; /** Tablet data for GHOST */ - GHOST_TabletData* m_tabletData; +// GHOST_TabletData* m_tabletData; /** Stores the Tablet context if detected Tablet features using WinTab.dll */ - HCTX m_tablet; - LONG m_maxPressure; - LONG m_maxAzimuth, m_maxAltitude; +// HCTX m_tablet; +// LONG m_maxPressure; +// LONG m_maxAzimuth, m_maxAltitude; /** Preferred number of samples */ GHOST_TUns16 m_multisample; diff --git a/intern/ghost/intern/Utils.c b/intern/ghost/intern/Utils.c deleted file mode 100644 index d354750f7f6..00000000000 --- a/intern/ghost/intern/Utils.c +++ /dev/null @@ -1,182 +0,0 @@ -/*---------------------------------------------------------------------------- - - NAME - Utils.c - - PURPOSE - Some general-purpose functions for the WinTab demos. - - COPYRIGHT - Copyright (c) Wacom Company, Ltd. 2010 All Rights Reserved - All rights reserved. - ----------------------------------------------------------------------------- */ - -#include "Utils.h" - -#ifdef WACOM_DEBUG - -void WacomTrace( char *lpszFormat, ...); - -#define WACOM_ASSERT( x ) assert( x ) -#define WACOM_TRACE(...) WacomTrace(__VA_ARGS__) -#else -#define WACOM_TRACE(...) -#define WACOM_ASSERT( x ) - -#endif // WACOM_DEBUG - -////////////////////////////////////////////////////////////////////////////// -HINSTANCE ghWintab = NULL; - -WTINFOA gpWTInfoA = NULL; -WTOPENA gpWTOpenA = NULL; -WTGETA gpWTGetA = NULL; -WTSETA gpWTSetA = NULL; -WTCLOSE gpWTClose = NULL; -WTPACKET gpWTPacket = NULL; -WTENABLE gpWTEnable = NULL; -WTOVERLAP gpWTOverlap = NULL; -WTSAVE gpWTSave = NULL; -WTCONFIG gpWTConfig = NULL; -WTRESTORE gpWTRestore = NULL; -WTEXTSET gpWTExtSet = NULL; -WTEXTGET gpWTExtGet = NULL; -WTQUEUESIZESET gpWTQueueSizeSet = NULL; -WTDATAPEEK gpWTDataPeek = NULL; -WTPACKETSGET gpWTPacketsGet = NULL; - -// TODO - add more wintab32 function pointers as needed - -char* gpszProgramName = NULL; - -#define GETPROCADDRESS(type, func) \ - gp##func = (type)GetProcAddress(ghWintab, #func); \ - if (!gp##func){ WACOM_ASSERT(FALSE); UnloadWintab(); return FALSE; } - -////////////////////////////////////////////////////////////////////////////// -// Purpose -// Find wintab32.dll and load it. -// Find the exported functions we need from it. -// -// Returns -// TRUE on success. -// FALSE on failure. -// -BOOL LoadWintab( void ) -{ - ghWintab = LoadLibraryA( "Wintab32.dll" ); - if ( !ghWintab ) - { - DWORD err = GetLastError(); - WACOM_TRACE("LoadLibrary error: %i\n", err); - ShowError("Could not load Wintab32.dll"); - return FALSE; - } - - // Explicitly find the exported Wintab functions in which we are interested. - // We are using the ASCII, not unicode versions (where applicable). - GETPROCADDRESS( WTOPENA, WTOpenA ); - GETPROCADDRESS( WTINFOA, WTInfoA ); - GETPROCADDRESS( WTGETA, WTGetA ); - GETPROCADDRESS( WTSETA, WTSetA ); - GETPROCADDRESS( WTPACKET, WTPacket ); - GETPROCADDRESS( WTCLOSE, WTClose ); - GETPROCADDRESS( WTENABLE, WTEnable ); - GETPROCADDRESS( WTOVERLAP, WTOverlap ); - GETPROCADDRESS( WTSAVE, WTSave ); - GETPROCADDRESS( WTCONFIG, WTConfig ); - GETPROCADDRESS( WTRESTORE, WTRestore ); - GETPROCADDRESS( WTEXTSET, WTExtSet ); - GETPROCADDRESS( WTEXTGET, WTExtGet ); - GETPROCADDRESS( WTQUEUESIZESET, WTQueueSizeSet ); - GETPROCADDRESS( WTDATAPEEK, WTDataPeek ); - GETPROCADDRESS( WTPACKETSGET, WTPacketsGet ); - - - // TODO - don't forget to NULL out pointers in UnloadWintab(). - return TRUE; -} - - - -////////////////////////////////////////////////////////////////////////////// -// Purpose -// Uninitializes use of wintab32.dll -// -// Returns -// Nothing. -// -void UnloadWintab( void ) -{ - WACOM_TRACE( "UnloadWintab()\n" ); - - if ( ghWintab ) - { - FreeLibrary( ghWintab ); - ghWintab = NULL; - } - - gpWTOpenA = NULL; - gpWTClose = NULL; - gpWTInfoA = NULL; - gpWTPacket = NULL; - gpWTEnable = NULL; - gpWTOverlap = NULL; - gpWTSave = NULL; - gpWTConfig = NULL; - gpWTGetA = NULL; - gpWTSetA = NULL; - gpWTRestore = NULL; - gpWTExtSet = NULL; - gpWTExtGet = NULL; - gpWTQueueSizeSet = NULL; - gpWTDataPeek = NULL; - gpWTPacketsGet = NULL; -} - - - -////////////////////////////////////////////////////////////////////////////// -// Purpose -// Display error to user. -// -void ShowError( char *pszErrorMessage ) -{ - WACOM_TRACE( "ShowError()\n" ); - - WACOM_ASSERT( pszErrorMessage ); - - MessageBoxA( NULL, pszErrorMessage, gpszProgramName, MB_OK | MB_ICONHAND ); -} - - - -#ifdef WACOM_DEBUG - -////////////////////////////////////////////////////////////////////////////// - -void WacomTrace( char *lpszFormat, ...) -{ - char szTraceMessage[ 128 ]; - - int nBytesWritten; - - va_list args; - - WACOM_ASSERT( lpszFormat ); - - va_start( args, lpszFormat ); - - nBytesWritten = _vsnprintf( szTraceMessage, sizeof( szTraceMessage ) - 1, - lpszFormat, args ); - - if ( nBytesWritten > 0 ) - { - OutputDebugStringA( szTraceMessage ); - } - - va_end( args ); -} - -#endif // WACOM_DEBUG diff --git a/intern/ghost/intern/Utils.h b/intern/ghost/intern/Utils.h deleted file mode 100644 index e886389796f..00000000000 --- a/intern/ghost/intern/Utils.h +++ /dev/null @@ -1,94 +0,0 @@ -/*---------------------------------------------------------------------------- - - NAME - Utils.h - - PURPOSE - Defines for the general-purpose functions for the WinTab demos. - - COPYRIGHT - Copyright (c) Wacom Company, Ltd. 2010 All Rights Reserved - All rights reserved. - ----------------------------------------------------------------------------- */ -#pragma once - -#include -#include -#include -#include - -#include // NOTE: get from wactab header package - - -////////////////////////////////////////////////////////////////////////////// -#define WACOM_DEBUG - -// Ignore warnings about using unsafe string functions. -#pragma warning( disable : 4996 ) - -////////////////////////////////////////////////////////////////////////////// -// Function pointers to Wintab functions exported from wintab32.dll. -typedef UINT ( API * WTINFOA ) ( UINT, UINT, LPVOID ); -typedef HCTX ( API * WTOPENA )( HWND, LPLOGCONTEXTA, BOOL ); -typedef BOOL ( API * WTGETA ) ( HCTX, LPLOGCONTEXT ); -typedef BOOL ( API * WTSETA ) ( HCTX, LPLOGCONTEXT ); -typedef BOOL ( API * WTCLOSE ) ( HCTX ); -typedef BOOL ( API * WTENABLE ) ( HCTX, BOOL ); -typedef BOOL ( API * WTPACKET ) ( HCTX, UINT, LPVOID ); -typedef BOOL ( API * WTOVERLAP ) ( HCTX, BOOL ); -typedef BOOL ( API * WTSAVE ) ( HCTX, LPVOID ); -typedef BOOL ( API * WTCONFIG ) ( HCTX, HWND ); -typedef HCTX ( API * WTRESTORE ) ( HWND, LPVOID, BOOL ); -typedef BOOL ( API * WTEXTSET ) ( HCTX, UINT, LPVOID ); -typedef BOOL ( API * WTEXTGET ) ( HCTX, UINT, LPVOID ); -typedef BOOL ( API * WTQUEUESIZESET ) ( HCTX, int ); -typedef int ( API * WTDATAPEEK ) ( HCTX, UINT, UINT, int, LPVOID, LPINT); -typedef int ( API * WTPACKETSGET ) (HCTX, int, LPVOID); - -// TODO - add more wintab32 function defs as needed - -////////////////////////////////////////////////////////////////////////////// -extern char* gpszProgramName; - -// Loaded Wintab32 API functions. -extern HINSTANCE ghWintab; - -extern WTINFOA gpWTInfoA; -extern WTOPENA gpWTOpenA; -extern WTGETA gpWTGetA; -extern WTSETA gpWTSetA; -extern WTCLOSE gpWTClose; -extern WTPACKET gpWTPacket; -extern WTENABLE gpWTEnable; -extern WTOVERLAP gpWTOverlap; -extern WTSAVE gpWTSave; -extern WTCONFIG gpWTConfig; -extern WTRESTORE gpWTRestore; -extern WTEXTSET gpWTExtSet; -extern WTEXTGET gpWTExtGet; -extern WTQUEUESIZESET gpWTQueueSizeSet; -extern WTDATAPEEK gpWTDataPeek; -extern WTPACKETSGET gpWTPacketsGet; - -// TODO - add more wintab32 function pointers as needed - -////////////////////////////////////////////////////////////////////////////// -BOOL LoadWintab( void ); -void UnloadWintab( void ); - -void ShowError( char *pszErrorMessage ); - -////////////////////////////////////////////////////////////////////////////// -#ifdef WACOM_DEBUG - -void WacomTrace( char *lpszFormat, ...); - -#define WACOM_ASSERT( x ) assert( x ) -#define WACOM_TRACE(...) WacomTrace(__VA_ARGS__) -#else -#define WACOM_TRACE(...) -#define WACOM_ASSERT( x ) - -#endif // WACOM_DEBUG - -- cgit v1.2.3 From 1232bb69236094f4ac7e5a419b17784b5ea11b83 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 12 Aug 2010 13:04:00 +0000 Subject: Better Intuos4 support on Windows. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 40 ++- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 363 +++++++++++++---------- intern/ghost/intern/GHOST_TabletManagerWin32.h | 37 ++- 3 files changed, 266 insertions(+), 174 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 9797b5c2924..e71a4b9e803 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -140,7 +140,9 @@ GHOST_SystemWin32::~GHOST_SystemWin32() GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const { - // Hardware does not support high resolution timers. We will use GetTickCount instead then. + // If hardware does not support high resolution timers, + // we will use GetTickCount instead. + if (!m_hasPerformanceCounter) { return ::GetTickCount(); } @@ -153,7 +155,7 @@ GHOST_TUns64 GHOST_SystemWin32::getMilliSeconds() const __int64 delta = 1000*(count-m_start); GHOST_TUns64 t = (GHOST_TUns64)(delta/m_freq); - return t; + return t; } @@ -174,7 +176,7 @@ void GHOST_SystemWin32::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns GHOST_IWindow* GHOST_SystemWin32::createWindow( - const STR_String& title, + const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, bool stereoVisual, const GHOST_TUns16 numOfAASamples, const GHOST_TEmbedderWindowID parentWindow ) @@ -195,7 +197,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow( delete window; window = 0; - + // If another window is found, let the wm know about that one, but not the old one if (other_window) { @@ -222,7 +224,7 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent) #else GHOST_TUns64 next = timerMgr->nextFireTime(); GHOST_TInt64 maxSleep = next - getMilliSeconds(); - + if (next == GHOST_kFireTimeNever) { ::WaitMessage(); } else if(maxSleep >= 0.0) { @@ -565,7 +567,7 @@ GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WP { // short fwKeys = LOWORD(wParam); // key flags int zDelta = (short) HIWORD(wParam); // wheel rotation - + // zDelta /= WHEEL_DELTA; // temporary fix below: microsoft now has added more precision, making the above division not work if (zDelta <= 0 ) zDelta= -1; else zDelta= 1; @@ -930,14 +932,22 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM // Tablet events, processed //////////////////////////////////////////////////////////////////////// case WT_PACKET: - puts("WT_PACKET"); + // puts("WT_PACKET"); // window->processWin32TabletEvent(wParam, lParam); - m_tabletManager->processPackets(window); + m_tabletManager->processPackets((HCTX)lParam); break; case WT_CSRCHANGE: + m_tabletManager->changeTool((HCTX)lParam, wParam); + break; case WT_PROXIMITY: + // description was weird.. give me numbers! + // printf("prox: %d %d\n", LOWORD(lParam), HIWORD(lParam)); + if (LOWORD(lParam) == 0) + { + puts("-- dropping tool --"); + m_tabletManager->dropTool(); + } // window->processWin32TabletInitEvent(); - m_tabletManager->changeTool(window); break; //////////////////////////////////////////////////////////////////////// @@ -997,9 +1007,15 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM if (m_input_fidelity_hint == HI_FI) { - // int n = - getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); - // printf("%d more mouse points found\n", n); + int buttons; + getButtons(buttons); + // don't bother grabbing extra mouse motion unless we're in a stroke + if (buttons) + { + // int n = + getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); + // printf("%d more mouse points found\n", n); + } } // uncomment here and in getMoreMousePoints to show effectiveness of hi-fi input diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp index c82ef574b4a..f152d4586c2 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -2,18 +2,19 @@ #include "GHOST_WindowWin32.h" #include #include +#include -#define PACKETDATA PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE -#define PACKETTILT PKEXT_ABSOLUTE -#define PACKETMODE PK_BUTTONS +#define PACKETDATA PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION +#define PACKETMODE PK_BUTTONS +// #define PACKETTILT PKEXT_ABSOLUTE #include "pktdef.h" -#define MAX_QUEUE_SIZE 128 +#define MAX_QUEUE_SIZE 100 GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() { - resetActiveTool(); + dropTool(); // open WinTab lib_Wintab = LoadLibrary("wintab32.dll"); @@ -26,11 +27,12 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() func_Info = (WTINFOA) GetProcAddress(lib_Wintab,"WTInfoA"); func_QueueSizeSet = (WTQUEUESIZESET) GetProcAddress(lib_Wintab,"WTQueueSizeSet"); func_PacketsGet = (WTPACKETSGET) GetProcAddress(lib_Wintab,"WTPacketsGet"); + func_Packet = (WTPACKET) GetProcAddress(lib_Wintab,"WTPacket"); WORD specV, implV; func_Info(WTI_INTERFACE, IFC_SPECVERSION, &specV); func_Info(WTI_INTERFACE, IFC_IMPLVERSION, &implV); - printf("Wintab version %d.%d (%d.%d)\n", + printf("WinTab version %d.%d (%d.%d)\n", HIBYTE(specV), LOBYTE(specV), HIBYTE(implV), LOBYTE(implV)); // query for overall capabilities and ranges @@ -44,8 +46,11 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() printf("active area: %dx%d\n", xRange.axMax, yRange.axMax); + func_Info(WTI_DEVICES, DVC_NCSRTYPES, &cursorCount); + func_Info(WTI_DEVICES, DVC_FIRSTCSR, &cursorBase); + AXIS pressureRange; - hasPressure = func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange) && pressureRange.axMax != 0; + hasPressure = func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange);// && pressureRange.axMax != 0; printf("pressure sensitivity: "); if (hasPressure) @@ -59,20 +64,71 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() pressureScale = 0.f; } - AXIS tiltRange; - hasTilt = func_Info(WTI_DEVICES, DVC_ORIENTATION, &tiltRange) && tiltRange.axMax != 0; + printf("tilt sensitivity:\n"); + AXIS tiltRange[3]; + hasTilt = func_Info(WTI_DEVICES, DVC_ORIENTATION, tiltRange); - printf("tilt sensitivity: "); if (hasTilt) { - printf("%d to %d\n", tiltRange.axMin, tiltRange.axMax); - tiltScale = 1.f / tiltRange.axMax; + // cheat by using available data from Intuos4. test on other tablets!!! + azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution); + altitudeScale = 1.f / tiltRange[1].axMax; + printf("azi scale %f\n", azimuthScale); + printf("alt scale %f\n", altitudeScale); + + // leave this code in place to help support tablets I haven't tested + const char* axisName[] = {"azimuth","altitude","twist"}; + const char* unitName[] = {NULL,"inch","cm","circle"}; + for (int i = 0; i < 3; ++i) + { + AXIS const& t = tiltRange[i]; + if (t.axResolution) + printf("%s: %d to %d values per %d.%d %s\n", + axisName[i], t.axMin, t.axMax, + HIWORD(t.axResolution), LOWORD(t.axResolution), + unitName[t.axUnits]); + } } else { printf("none\n"); - tiltScale = 0.f; } + +#if 0 // WTX_TILT -- cartesian tilt extension, no conversion needed + // this isn't working for [mce], so let it rest for now + printf("raw tilt sensitivity:\n"); + hasTilt = false; + UINT tag = 0; + UINT extensionCount; + func_Info(WTI_INTERFACE, IFC_NEXTENSIONS, &extensionCount); +// for (UINT i = 0; func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); ++i) + for (UINT i = 0; i < extensionCount; ++i) + { + printf("trying extension %d\n", i); + func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); + if (tag == WTX_TILT) + { + hasTilt = true; + break; + } + } + + if (hasTilt) + { + func_Info(WTI_EXTENSIONS + tag, EXT_MASK, &tiltMask); + AXIS tiltRange[2]; + func_Info(WTI_EXTENSIONS + tag, EXT_AXES, tiltRange); + printf("%d to %d along x\n", tiltRange[0].axMin, tiltRange[0].axMax); + printf("%d to %d along y\n", tiltRange[1].axMin, tiltRange[1].axMax); + tiltScaleX = 1.f / tiltRange[0].axMax; + tiltScaleY = 1.f / tiltRange[1].axMax; + } + else + { + printf("none\n"); + tiltScaleX = tiltScaleY = 0.f; + } +#endif // WTX_TILT } } @@ -88,13 +144,6 @@ bool GHOST_TabletManagerWin32::available() && func_Info(0,0,NULL); // tablet plugged in } -void GHOST_TabletManagerWin32::resetActiveTool() - { - activeTool.type = TABLET_NONE; - activeTool.hasPressure = false; - activeTool.hasTilt = false; - } - HCTX GHOST_TabletManagerWin32::contextForWindow(GHOST_WindowWin32* window) { std::map::iterator i = contexts.find(window); @@ -112,20 +161,20 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) // set up context LOGCONTEXT archetype; - func_Info(WTI_DEFCONTEXT, 0, &archetype); + func_Info(WTI_DEFSYSCTX, 0, &archetype); - strcpy(archetype.lcName, "merwin special"); + strcpy(archetype.lcName, "blender special"); archetype.lcPktData = PACKETDATA; archetype.lcPktMode = PACKETMODE; - archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES; + archetype.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES; -// BEGIN from Wacom's TILTTEST.c - /* output the data in screen coords */ - archetype.lcOutOrgX = archetype.lcOutOrgY = 0; - archetype.lcOutExtX = GetSystemMetrics(SM_CXSCREEN); - /* move origin to upper left */ - archetype.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN); -// END +/* + if (hasTilt) + { + archetype.lcPktData |= tiltMask; + archetype.lcMoveMask |= tiltMask; + } +*/ // open the context HCTX context = func_Open(window->getHWND(), &archetype, TRUE); @@ -151,150 +200,160 @@ void GHOST_TabletManagerWin32::closeForWindow(GHOST_WindowWin32* window) } } -void GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) +void GHOST_TabletManagerWin32::convertTilt(ORIENTATION const& ort, TabletToolData& data) { - HCTX context = contextForWindow(window); + // this code used to live in GHOST_WindowWin32 + // now it lives here + + float vecLen; + float altRad, azmRad; /* in radians */ + + /* + from the wintab spec: + orAzimuth Specifies the clockwise rotation of the + cursor about the z axis through a full circular range. + + orAltitude Specifies the angle with the x-y plane + through a signed, semicircular range. Positive values + specify an angle upward toward the positive z axis; + negative values specify an angle downward toward the negative z axis. + + wintab.h defines .orAltitude as a UINT but documents .orAltitude + as positive for upward angles and negative for downward angles. + WACOM uses negative altitude values to show that the pen is inverted; + therefore we cast .orAltitude as an (int) and then use the absolute value. + */ + + /* convert raw fixed point data to radians */ + altRad = fabs(ort.orAltitude) * altitudeScale * M_PI/2.0; + azmRad = ort.orAzimuth * azimuthScale * M_PI*2.0; + + /* find length of the stylus' projected vector on the XY plane */ + vecLen = cos(altRad); + + /* from there calculate X and Y components based on azimuth */ + data.tilt_x = sin(azmRad) * vecLen; + data.tilt_y = sin(M_PI/2.0 - azmRad) * vecLen; + } - if (context) +void GHOST_TabletManagerWin32::processPackets(HCTX context) + { + PACKET packets[MAX_QUEUE_SIZE]; + int n = func_PacketsGet(context, MAX_QUEUE_SIZE, packets); +// printf("processing %d packets\n", n); + + for (int i = 0; i < n; ++i) { - PACKET packets[MAX_QUEUE_SIZE]; - int n = func_PacketsGet(context, MAX_QUEUE_SIZE, packets); - printf("processing %d packets from ", n); + PACKET const& packet = packets[i]; + TabletToolData data = {activeTool}; + int x = packet.pkX; + int y = packet.pkY; + + if (activeTool.type == TABLET_MOUSE) + if (x == prevMouseX && y == prevMouseY) + // don't send any "mouse hasn't moved" events + continue; + else { + prevMouseX = x; + prevMouseY = y; + } // every packet from a WT_PACKET message comes from the same tool - switch (packets[0].pkCursor) { - case 0: /* first device */ - case 3: /* second device */ - activeTool.type = TABLET_MOUSE; - puts("mouse"); + switch (activeTool.type) + { + case TABLET_MOUSE: + printf("mouse"); break; - case 1: - case 4: - activeTool.type = TABLET_PEN; - puts("pen"); + case TABLET_PEN: + printf("pen"); break; - case 2: - case 5: - activeTool.type = TABLET_ERASER; - puts("eraser"); + case TABLET_ERASER: + printf("eraser"); break; - } + default: + printf("???"); + } - for (int i = 0; i < n; ++i) - { - PACKET const& packet = packets[i]; - TabletToolData data = {activeTool}; - int x = packet.pkX; - int y = packet.pkY; + printf(" (%d,%d)", x, y); - if (data.tool.hasPressure) + if (activeTool.hasPressure) + { + if (packet.pkNormalPressure) { - if (packet.pkNormalPressure) - data.pressure = pressureScale * packet.pkNormalPressure; - else - data.tool.hasPressure = false; + data.pressure = pressureScale * packet.pkNormalPressure; + printf(" %d%%", (int)(100 * data.pressure)); } + else + data.tool.hasPressure = false; + } - if (data.tool.hasTilt) - { - data.tilt_x = tiltScale * packet.pkTilt.tiltX; - data.tilt_y = tiltScale * packet.pkTilt.tiltY; - } + if (activeTool.hasTilt) + { + // ORIENTATION const& tilt = packet.pkOrientation; + // printf(" /%d,%d/", tilt.orAzimuth, tilt.orAltitude); + convertTilt(packet.pkOrientation, data); - printf(" %.3f @ (%d,%d) /%.2f,%.2f/\n", data.pressure, x, y, data.tilt_x, data.tilt_y); + // data.tilt_x = tiltScaleX * packet.pkTilt.tiltX; + // data.tilt_y = tiltScaleY * packet.pkTilt.tiltY; + printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); } + + putchar('\n'); } } -void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window) +void GHOST_TabletManagerWin32::changeTool(HCTX context, UINT serialNumber) { - HCTX context = contextForWindow(window); + puts("-- changing tool --"); - if (context) - { - puts("-- changing tool --"); + dropTool(); - if (hasPressure) - { - puts(" - pressure"); - activeTool.hasPressure = true; // not necessarily, but good enough for testing - } + PACKET packet; + func_Packet(context, serialNumber, &packet); + UINT cursor = (packet.pkCursor - cursorBase) % cursorCount; - if (hasTilt) - { - puts(" - tilt"); - activeTool.hasTilt = true; - } + printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursor); -#if 0 -#define kTransducerDeviceIdBitMask 0x0001 -#define kTransducerAbsXBitMask 0x0002 -#define kTransducerAbsYBitMask 0x0004 -#define kTransducerVendor1BitMask 0x0008 -#define kTransducerVendor2BitMask 0x0010 -#define kTransducerVendor3BitMask 0x0020 -#define kTransducerButtonsBitMask 0x0040 -#define kTransducerTiltXBitMask 0x0080 -#define kTransducerTiltYBitMask 0x0100 -#define kTransducerAbsZBitMask 0x0200 -#define kTransducerPressureBitMask 0x0400 -#define kTransducerTangentialPressureBitMask 0x0800 -#define kTransducerOrientInfoBitMask 0x1000 -#define kTransducerRotationBitMask 0x2000 - - // this is what I really want to know: -// UINT active; -// UINT active2 = func_Info(WTI_CURSORS, CSR_ACTIVE, &active); -// printf("active: %d %d\n", active, active2); - - WTPKT toolData; - func_Info(WTI_CURSORS, CSR_PKTDATA, &toolData); - activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; - activeTool.hasTilt = toolData & PK_ORIENTATION; - -// UINT cap; -// UINT cap2 = func_Info(WTI_CURSORS, CSR_CAPABILITIES, &cap); - // capabilities same as Mac tablet code? Let's see... - // int cap = CGEventGetIntegerValueField(event, kCGTabletProximityEventCapabilityMask); - printf("cursor capabilities: %d %d\n", cap, cap2); - - if (cap & kTransducerDeviceIdBitMask) - printf(" - device id\n"); - if (cap & kTransducerAbsXBitMask) - printf(" - abs x\n"); - if (cap & kTransducerAbsYBitMask) - printf(" - abs y\n"); - if (cap & kTransducerAbsZBitMask) - printf(" - abs z\n"); - if (cap & kTransducerVendor1BitMask) - printf(" - vendor 1\n"); - if (cap & kTransducerVendor2BitMask) - printf(" - vendor 2\n"); - if (cap & kTransducerVendor3BitMask) - printf(" - vendor 3\n"); - if (cap & kTransducerButtonsBitMask) - printf(" - buttons\n"); - if (cap & kTransducerTiltXBitMask) - { - printf(" - tilt x\n"); - hasTilt = true; - } - if (cap & kTransducerTiltYBitMask) - { - printf(" - tilt y\n"); - hasTilt = true; - } - if (cap & kTransducerPressureBitMask) - { - printf(" - pressure\n"); - hasPressure = true; - } - if (cap & kTransducerTangentialPressureBitMask) - printf(" - tangential pressure\n"); - if (cap & kTransducerOrientInfoBitMask) - printf(" - orientation\n"); - if (cap & kTransducerRotationBitMask) - printf(" - rotation\n"); -#endif + switch (cursor) + { + case 0: // older Intuos tablets can track two cursors at once + case 3: // so we test for both here + activeTool.type = TABLET_MOUSE; + break; + case 1: + case 4: + activeTool.type = TABLET_PEN; + break; + case 2: + case 5: + activeTool.type = TABLET_ERASER; + break; + default: + activeTool.type = TABLET_NONE; } + + WTPKT toolData; + func_Info(WTI_CURSORS + cursor, CSR_PKTDATA, &toolData); + activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; + activeTool.hasTilt = toolData & PK_ORIENTATION; +// activeTool.hasTilt = toolData & tiltMask; + + if (activeTool.hasPressure) + puts(" - pressure"); + + if (activeTool.hasTilt) + puts(" - tilt"); + + // and just for fun: + if (toolData & PK_BUTTONS) + puts(" - buttons"); + } + +void GHOST_TabletManagerWin32::dropTool() + { + activeTool.type = TABLET_NONE; + activeTool.hasPressure = false; + activeTool.hasTilt = false; + + prevMouseX = prevMouseY = 0; } diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h index d6b8b1c058a..1a046974649 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.h +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -18,13 +18,14 @@ typedef HCTX ( API * WTOPENA ) ( HWND, LPLOGCONTEXTA, BOOL ); typedef BOOL ( API * WTCLOSE ) ( HCTX ); typedef BOOL ( API * WTQUEUESIZESET ) ( HCTX, int ); typedef int ( API * WTPACKETSGET ) ( HCTX, int, LPVOID ); +typedef BOOL ( API * WTPACKET ) ( HCTX, UINT, LPVOID ); // END typedef enum { TABLET_NONE, TABLET_PEN, TABLET_ERASER, TABLET_MOUSE } TabletToolType; typedef struct { - TabletToolType type : 6; // plenty of room to grow + TabletToolType type : 4; // plenty of room to grow // capabilities bool hasPressure : 1; @@ -46,7 +47,7 @@ typedef struct class GHOST_TabletManagerWin32 { // the Wintab library - HINSTANCE lib_Wintab; // or HMODULE? + HMODULE lib_Wintab; // WinTab function pointers WTOPENA func_Open; @@ -54,29 +55,45 @@ class GHOST_TabletManagerWin32 WTINFOA func_Info; WTQUEUESIZESET func_QueueSizeSet; WTPACKETSGET func_PacketsGet; + WTPACKET func_Packet; // tablet attributes bool hasPressure; float pressureScale; bool hasTilt; - float tiltScale; - - // candidates for a base class: + float azimuthScale; + float altitudeScale; +// float tiltScaleX; +// float tiltScaleY; +// UINT tiltMask; + UINT cursorCount; + UINT cursorBase; + + // candidate for a base class: TabletTool activeTool; - void resetActiveTool(); + + int prevMouseX; + int prevMouseY; // book-keeping std::map contexts; HCTX contextForWindow(GHOST_WindowWin32*); + void convertTilt(ORIENTATION const&, TabletToolData&); + public: GHOST_TabletManagerWin32(); ~GHOST_TabletManagerWin32(); + bool available(); // another base class candidate - void openForWindow(GHOST_WindowWin32* window); - void closeForWindow(GHOST_WindowWin32* window); - void processPackets(GHOST_WindowWin32* window); - void changeTool(GHOST_WindowWin32* window); + + void openForWindow(GHOST_WindowWin32*); + void closeForWindow(GHOST_WindowWin32*); + + void processPackets(HCTX); + + void changeTool(HCTX, UINT serialNumber); + void dropTool(); }; #endif -- cgit v1.2.3 From fc5c4d98f4a52b7e405efed307427ace4a593f7b Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 12 Aug 2010 14:02:38 +0000 Subject: Minor cleanup of Windows tablet code. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 5 ----- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 11 +++++++---- intern/ghost/intern/GHOST_TabletManagerWin32.h | 20 +++++++++++++++++++- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index e71a4b9e803..ee2484ec1dd 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -932,22 +932,17 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM // Tablet events, processed //////////////////////////////////////////////////////////////////////// case WT_PACKET: - // puts("WT_PACKET"); - // window->processWin32TabletEvent(wParam, lParam); m_tabletManager->processPackets((HCTX)lParam); break; case WT_CSRCHANGE: m_tabletManager->changeTool((HCTX)lParam, wParam); break; case WT_PROXIMITY: - // description was weird.. give me numbers! - // printf("prox: %d %d\n", LOWORD(lParam), HIWORD(lParam)); if (LOWORD(lParam) == 0) { puts("-- dropping tool --"); m_tabletManager->dropTool(); } - // window->processWin32TabletInitEvent(); break; //////////////////////////////////////////////////////////////////////// diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp index f152d4586c2..864cf632d06 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -1,3 +1,6 @@ +// safe & friendly WinTab wrapper +// by Mike Erwin, July 2010 + #include "GHOST_TabletManagerWin32.h" #include "GHOST_WindowWin32.h" #include @@ -73,8 +76,6 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() // cheat by using available data from Intuos4. test on other tablets!!! azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution); altitudeScale = 1.f / tiltRange[1].axMax; - printf("azi scale %f\n", azimuthScale); - printf("alt scale %f\n", altitudeScale); // leave this code in place to help support tablets I haven't tested const char* axisName[] = {"azimuth","altitude","twist"}; @@ -101,8 +102,8 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() UINT tag = 0; UINT extensionCount; func_Info(WTI_INTERFACE, IFC_NEXTENSIONS, &extensionCount); -// for (UINT i = 0; func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); ++i) for (UINT i = 0; i < extensionCount; ++i) +// for (UINT i = 0; func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); ++i) { printf("trying extension %d\n", i); func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); @@ -299,6 +300,8 @@ void GHOST_TabletManagerWin32::processPackets(HCTX context) } putchar('\n'); + + // at this point, construct a GHOST event and push it into the queue! } } @@ -312,7 +315,7 @@ void GHOST_TabletManagerWin32::changeTool(HCTX context, UINT serialNumber) func_Packet(context, serialNumber, &packet); UINT cursor = (packet.pkCursor - cursorBase) % cursorCount; - printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursor); + // printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursor); switch (cursor) { diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h index 1a046974649..5686684e12a 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.h +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -1,4 +1,4 @@ -// safe & friendly Wintab wrapper +// safe & friendly WinTab wrapper // by Mike Erwin, July 2010 #ifndef GHOST_TABLET_MANAGER_WIN32_H @@ -96,4 +96,22 @@ public: void dropTool(); }; +/* +The tablet manager is driven by the following Windows event processing code: + +case WT_PACKET: + m_tabletManager->processPackets((HCTX)lParam); + break; +case WT_CSRCHANGE: + m_tabletManager->changeTool((HCTX)lParam, wParam); + break; +case WT_PROXIMITY: + if (LOWORD(lParam) == 0) + { + puts("-- dropping tool --"); + m_tabletManager->dropTool(); + } + break; +*/ + #endif -- cgit v1.2.3 From 7428380cc366025ae51f6245a5d0a837a7210c8d Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 13 Aug 2010 00:34:57 +0000 Subject: still working on tablet for Windows... --- intern/ghost/intern/GHOST_Buttons.cpp | 5 + intern/ghost/intern/GHOST_Buttons.h | 9 +- intern/ghost/intern/GHOST_SystemWin32.cpp | 11 +- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 194 +++++++++++++++-------- intern/ghost/intern/GHOST_TabletManagerWin32.h | 2 +- 5 files changed, 150 insertions(+), 71 deletions(-) diff --git a/intern/ghost/intern/GHOST_Buttons.cpp b/intern/ghost/intern/GHOST_Buttons.cpp index edccb24d5a1..8b46d777dbb 100644 --- a/intern/ghost/intern/GHOST_Buttons.cpp +++ b/intern/ghost/intern/GHOST_Buttons.cpp @@ -71,4 +71,9 @@ void GHOST_Buttons::clear() m_ButtonRight = false; } +bool GHOST_Buttons::anyDown() const +{ + return m_ButtonLeft || m_ButtonMiddle || m_ButtonRight; +} + GHOST_Buttons::~GHOST_Buttons() {} diff --git a/intern/ghost/intern/GHOST_Buttons.h b/intern/ghost/intern/GHOST_Buttons.h index 3dd10af0112..b35f68e4400 100644 --- a/intern/ghost/intern/GHOST_Buttons.h +++ b/intern/ghost/intern/GHOST_Buttons.h @@ -67,8 +67,13 @@ struct GHOST_Buttons { /** * Sets the state of all buttons to up. */ - virtual void clear(); - + virtual void clear(); + + /** + * Are any buttons currently pressed? + */ + bool anyDown() const; + GHOST_TUns8 m_ButtonLeft : 1; GHOST_TUns8 m_ButtonMiddle : 1; GHOST_TUns8 m_ButtonRight : 1; diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index ee2484ec1dd..b8673ef3963 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -506,8 +506,9 @@ bool eventIsFromTablet() GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask) { - if (eventIsFromTablet()) - return NULL; + puts("ghost button event"); +// if (eventIsFromTablet()) +// return NULL; return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask); } @@ -932,7 +933,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM // Tablet events, processed //////////////////////////////////////////////////////////////////////// case WT_PACKET: - m_tabletManager->processPackets((HCTX)lParam); + m_tabletManager->processPackets(window); break; case WT_CSRCHANGE: m_tabletManager->changeTool((HCTX)lParam, wParam); @@ -1002,10 +1003,10 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM if (m_input_fidelity_hint == HI_FI) { - int buttons; + GHOST_Buttons buttons; getButtons(buttons); // don't bother grabbing extra mouse motion unless we're in a stroke - if (buttons) + if (buttons.anyDown()) { // int n = getMoreMousePoints(mousePosX, mousePosY, xPrev, yPrev, window); diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp index 864cf632d06..0b69dcb300d 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -3,6 +3,9 @@ #include "GHOST_TabletManagerWin32.h" #include "GHOST_WindowWin32.h" +#include "GHOST_System.h" +#include "GHOST_EventCursor.h" +#include "GHOST_EventButton.h" #include #include #include @@ -162,20 +165,39 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) // set up context LOGCONTEXT archetype; - func_Info(WTI_DEFSYSCTX, 0, &archetype); +// func_Info(WTI_DEFSYSCTX, 0, &archetype); + func_Info(WTI_DEFCONTEXT, 0, &archetype); strcpy(archetype.lcName, "blender special"); archetype.lcPktData = PACKETDATA; archetype.lcPktMode = PACKETMODE; - archetype.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES; - -/* - if (hasTilt) +// archetype.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES; + archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES | CXO_CSRMESSAGES; + + // we want first 5 buttons + archetype.lcBtnDnMask = 0x1f; + archetype.lcBtnUpMask = 0x1f; + +// BEGIN derived from Wacom's TILTTEST.C: + AXIS TabletX, TabletY; + func_Info(WTI_DEVICES,DVC_X,&TabletX); + func_Info(WTI_DEVICES,DVC_Y,&TabletY); + archetype.lcInOrgX = 0; + archetype.lcInOrgY = 0; + archetype.lcInExtX = TabletX.axMax; + archetype.lcInExtY = TabletY.axMax; + /* output the data in screen coords */ + archetype.lcOutOrgX = archetype.lcOutOrgY = 0; + archetype.lcOutExtX = GetSystemMetrics(SM_CXSCREEN); + /* move origin to upper left */ + archetype.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN); +// END + +/* if (hasTilt) { archetype.lcPktData |= tiltMask; archetype.lcMoveMask |= tiltMask; - } -*/ + } */ // open the context HCTX context = func_Open(window->getHWND(), &archetype, TRUE); @@ -237,71 +259,117 @@ void GHOST_TabletManagerWin32::convertTilt(ORIENTATION const& ort, TabletToolDat data.tilt_y = sin(M_PI/2.0 - azmRad) * vecLen; } -void GHOST_TabletManagerWin32::processPackets(HCTX context) +void GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) { - PACKET packets[MAX_QUEUE_SIZE]; - int n = func_PacketsGet(context, MAX_QUEUE_SIZE, packets); -// printf("processing %d packets\n", n); + HCTX context = contextForWindow(window); - for (int i = 0; i < n; ++i) + if (context) { - PACKET const& packet = packets[i]; - TabletToolData data = {activeTool}; - int x = packet.pkX; - int y = packet.pkY; - - if (activeTool.type == TABLET_MOUSE) - if (x == prevMouseX && y == prevMouseY) - // don't send any "mouse hasn't moved" events - continue; - else { - prevMouseX = x; - prevMouseY = y; - } - - // every packet from a WT_PACKET message comes from the same tool - switch (activeTool.type) - { - case TABLET_MOUSE: - printf("mouse"); - break; - case TABLET_PEN: - printf("pen"); - break; - case TABLET_ERASER: - printf("eraser"); - break; - default: - printf("???"); - } - - printf(" (%d,%d)", x, y); - - if (activeTool.hasPressure) + PACKET packets[MAX_QUEUE_SIZE]; + int n = func_PacketsGet(context, MAX_QUEUE_SIZE, packets); + // printf("processing %d packets\n", n); + + for (int i = 0; i < n; ++i) { - if (packet.pkNormalPressure) + PACKET const& packet = packets[i]; + TabletToolData data = {activeTool}; + int x = packet.pkX; + int y = packet.pkY; + + if (activeTool.type == TABLET_MOUSE) + if (x == prevMouseX && y == prevMouseY) + // don't send any "mouse hasn't moved" events + continue; + else { + prevMouseX = x; + prevMouseY = y; + } + + // every packet from a WT_PACKET message comes from the same tool + switch (activeTool.type) { - data.pressure = pressureScale * packet.pkNormalPressure; - printf(" %d%%", (int)(100 * data.pressure)); + case TABLET_MOUSE: + printf("mouse"); + break; + case TABLET_PEN: + printf("pen"); + break; + case TABLET_ERASER: + printf("eraser"); + break; + default: + printf("???"); } - else - data.tool.hasPressure = false; - } + + printf(" (%d,%d)", x, y); + + if (activeTool.hasPressure) + { + if (packet.pkNormalPressure) + { + data.pressure = pressureScale * packet.pkNormalPressure; + printf(" %d%%", (int)(100 * data.pressure)); + } + else + data.tool.hasPressure = false; + } + + if (activeTool.hasTilt) + { + // ORIENTATION const& tilt = packet.pkOrientation; + // printf(" /%d,%d/", tilt.orAzimuth, tilt.orAltitude); + convertTilt(packet.pkOrientation, data); + + // data.tilt_x = tiltScaleX * packet.pkTilt.tiltX; + // data.tilt_y = tiltScaleY * packet.pkTilt.tiltY; + printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); + } + + putchar('\n'); - if (activeTool.hasTilt) - { - // ORIENTATION const& tilt = packet.pkOrientation; - // printf(" /%d,%d/", tilt.orAzimuth, tilt.orAltitude); - convertTilt(packet.pkOrientation, data); + // at this point, construct a GHOST event and push it into the queue! + // (having trouble with Wacom mouse scaling, so ignore it for now) - // data.tilt_x = tiltScaleX * packet.pkTilt.tiltX; - // data.tilt_y = tiltScaleY * packet.pkTilt.tiltY; - printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); +// if (activeTool.type == TABLET_PEN || activeTool.type == TABLET_ERASER) + { + GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem(); + + if (packet.pkButtons) + { + // which button? + GHOST_TButtonMask e_button; + int buttonNumber = LOWORD(packet.pkButtons); + e_button = (GHOST_TButtonMask) buttonNumber; + + // pressed or released? + GHOST_TEventType e_action; + int buttonAction = HIWORD(packet.pkButtons); + if (buttonAction == TBN_DOWN) + e_action = GHOST_kEventButtonDown; + else + e_action = GHOST_kEventButtonUp; + + printf("button %d %s\n", buttonNumber, buttonAction == TBN_DOWN ? "down" : "up"); + + GHOST_EventButton* e = new GHOST_EventButton(system->getMilliSeconds(), e_action, window, e_button); + +// system->pushEvent(e); + } + else + { + GHOST_EventCursor* e = new GHOST_EventCursor(system->getMilliSeconds(), GHOST_kEventCursorMove, window, x, y); + + // use older TabletData struct for testing until mine is in place + GHOST_TabletData& e_data = ((GHOST_TEventCursorData*) e->getData())->tablet; + e_data.Active = (GHOST_TTabletMode) data.tool.type; + e_data.Pressure = data.pressure; + e_data.Xtilt = data.tilt_x; + e_data.Ytilt = data.tilt_y; + +// system->pushEvent(e); + } + } } - - putchar('\n'); - - // at this point, construct a GHOST event and push it into the queue! } } diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h index 5686684e12a..290798a6bfb 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.h +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -90,7 +90,7 @@ public: void openForWindow(GHOST_WindowWin32*); void closeForWindow(GHOST_WindowWin32*); - void processPackets(HCTX); + void processPackets(GHOST_WindowWin32*); void changeTool(HCTX, UINT serialNumber); void dropTool(); -- cgit v1.2.3 From 91e2a5517190b532a78515956391d2e699ae88b8 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 14 Aug 2010 21:01:09 +0000 Subject: continued Win32 tablet hackery --- intern/ghost/intern/GHOST_Buttons.cpp | 5 +- intern/ghost/intern/GHOST_SystemWin32.cpp | 39 ++- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 313 +++++++++++++-------- intern/ghost/intern/GHOST_TabletManagerWin32.h | 21 +- .../blender/windowmanager/intern/wm_event_system.c | 35 +-- 5 files changed, 244 insertions(+), 169 deletions(-) diff --git a/intern/ghost/intern/GHOST_Buttons.cpp b/intern/ghost/intern/GHOST_Buttons.cpp index 8b46d777dbb..5a1f5dea430 100644 --- a/intern/ghost/intern/GHOST_Buttons.cpp +++ b/intern/ghost/intern/GHOST_Buttons.cpp @@ -35,6 +35,7 @@ GHOST_Buttons::GHOST_Buttons() clear(); } +GHOST_Buttons::~GHOST_Buttons() {} bool GHOST_Buttons::get(GHOST_TButtonMask mask) const { @@ -73,7 +74,5 @@ void GHOST_Buttons::clear() bool GHOST_Buttons::anyDown() const { - return m_ButtonLeft || m_ButtonMiddle || m_ButtonRight; + return m_ButtonLeft || m_ButtonMiddle || m_ButtonRight; } - -GHOST_Buttons::~GHOST_Buttons() {} diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index b8673ef3963..0f567dec4e2 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -247,6 +247,9 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent) } } while (waitForEvent && !anyProcessed); + if (m_tabletManager->processPackets()) + anyProcessed = true; + return anyProcessed; } @@ -500,15 +503,28 @@ void GHOST_SystemWin32::processModifierKeys(GHOST_IWindow *window) bool eventIsFromTablet() { - // bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs - return GetMessageExtraInfo() & 0x7f; // true for tablet mouse, not just pen + // this (apparently) gives the packet serial number, which only tablet events have + return GetMessageExtraInfo() != 0; +// bool IsFromPen = ((GetMessageExtraInfo() & 0xFF515700) == 0xFF515700); // this only works on TabletPCs +// static int all_magic = 0; +// int magic = GetMessageExtraInfo(); +// all_magic |= magic; +// printf("from tablet? %08x %08x\n", magic, all_magic); +// return magic & 0x7f; // true for tablet mouse, not just pen } GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_IWindow *window, GHOST_TButtonMask mask) { - puts("ghost button event"); -// if (eventIsFromTablet()) -// return NULL; + if (eventIsFromTablet()) + return NULL; + + static GHOST_Buttons buttons; + if (type == GHOST_kEventButtonUp && !buttons.get(mask)) + // discard rogue button up events (probably from tablet) + return NULL; + buttons.set(mask, type == GHOST_kEventButtonDown); + + printf("system button %d %s\n", mask, (type == GHOST_kEventButtonDown) ? "down" : (type == GHOST_kEventButtonUp) ? "up" : "???"); return new GHOST_EventButton (getSystem()->getMilliSeconds(), type, window, mask); } @@ -516,6 +532,8 @@ GHOST_EventButton* GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, GHOST_EventCursor* GHOST_SystemWin32::processCursorEvent(GHOST_TEventType type, GHOST_IWindow *Iwindow, int x_screen, int y_screen) { + printf("system cursor (%d,%d)\n", x_screen, y_screen); + GHOST_SystemWin32 * system = ((GHOST_SystemWin32 * ) getSystem()); GHOST_WindowWin32 * window = ( GHOST_WindowWin32 * ) Iwindow; @@ -933,10 +951,11 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM // Tablet events, processed //////////////////////////////////////////////////////////////////////// case WT_PACKET: + puts("WT_PACKET"); m_tabletManager->processPackets(window); break; case WT_CSRCHANGE: - m_tabletManager->changeTool((HCTX)lParam, wParam); + m_tabletManager->changeTool(window, wParam); break; case WT_PROXIMITY: if (LOWORD(lParam) == 0) @@ -1034,8 +1053,10 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); eventSent |= processRawInput(raw, window); - // necessary? - // DefRawInputProc(&raw_ptr, 1, sizeof(RAWINPUTHEADER)); + if (processRawInput(raw, window)) + eventSent = true; +// else +// DefRawInputProc(&raw_ptr, 1, sizeof(RAWINPUTHEADER)); #if 0 #define RAWCOUNT 10 @@ -1067,7 +1088,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM } // clear processed events from the queue - DefRawInputProc((RAWINPUT**)&rawBuffer, n, sizeof(RAWINPUTHEADER)); + // DefRawInputProc((RAWINPUT**)&rawBuffer, n, sizeof(RAWINPUTHEADER)); } } #endif diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp index 0b69dcb300d..9278ad2f48e 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -11,14 +11,28 @@ #include #define PACKETDATA PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION -#define PACKETMODE PK_BUTTONS +#define PACKETMODE 0 /*PK_BUTTONS*/ // #define PACKETTILT PKEXT_ABSOLUTE #include "pktdef.h" #define MAX_QUEUE_SIZE 100 +static void print(AXIS const& t, char const* label = NULL) + { + const char* unitName[] = {"dinosaur","inch","cm","circle"}; + + if (label) + printf("%s: ", label); + + printf("%d to %d, %d.%d per %s\n", + t.axMin, t.axMax, + HIWORD(t.axResolution), LOWORD(t.axResolution), + unitName[t.axUnits]); + } + GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() + : activeWindow(NULL) { dropTool(); @@ -46,56 +60,45 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() if (func_Info(WTI_DEVICES, DVC_NAME, tabletName)) puts(tabletName); + puts("active tablet area"); AXIS xRange, yRange; func_Info(WTI_DEVICES, DVC_X, &xRange); func_Info(WTI_DEVICES, DVC_Y, &yRange); + print(xRange,"x"); print(yRange,"y"); - printf("active area: %dx%d\n", xRange.axMax, yRange.axMax); func_Info(WTI_DEVICES, DVC_NCSRTYPES, &cursorCount); func_Info(WTI_DEVICES, DVC_FIRSTCSR, &cursorBase); + puts("pressure sensitivity"); AXIS pressureRange; hasPressure = func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange);// && pressureRange.axMax != 0; + print(pressureRange); - printf("pressure sensitivity: "); if (hasPressure) - { - printf("%d to %d\n", pressureRange.axMin, pressureRange.axMax); pressureScale = 1.f / pressureRange.axMax; - } else - { - printf("none\n"); pressureScale = 0.f; - } - printf("tilt sensitivity:\n"); + puts("tilt sensitivity"); AXIS tiltRange[3]; hasTilt = func_Info(WTI_DEVICES, DVC_ORIENTATION, tiltRange); if (hasTilt) { - // cheat by using available data from Intuos4. test on other tablets!!! - azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution); - altitudeScale = 1.f / tiltRange[1].axMax; - // leave this code in place to help support tablets I haven't tested const char* axisName[] = {"azimuth","altitude","twist"}; - const char* unitName[] = {NULL,"inch","cm","circle"}; for (int i = 0; i < 3; ++i) - { - AXIS const& t = tiltRange[i]; - if (t.axResolution) - printf("%s: %d to %d values per %d.%d %s\n", - axisName[i], t.axMin, t.axMax, - HIWORD(t.axResolution), LOWORD(t.axResolution), - unitName[t.axUnits]); - } + print(tiltRange[i], axisName[i]); + + // cheat by using available data from Intuos4. test on other tablets!!! + azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution); + altitudeScale = 1.f / tiltRange[1].axMax; } else { - printf("none\n"); + puts("none"); + azimuthScale = altitudeScale = 0.f; } #if 0 // WTX_TILT -- cartesian tilt extension, no conversion needed @@ -106,7 +109,6 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() UINT extensionCount; func_Info(WTI_INTERFACE, IFC_NEXTENSIONS, &extensionCount); for (UINT i = 0; i < extensionCount; ++i) -// for (UINT i = 0; func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); ++i) { printf("trying extension %d\n", i); func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); @@ -119,17 +121,17 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() if (hasTilt) { - func_Info(WTI_EXTENSIONS + tag, EXT_MASK, &tiltMask); AXIS tiltRange[2]; func_Info(WTI_EXTENSIONS + tag, EXT_AXES, tiltRange); - printf("%d to %d along x\n", tiltRange[0].axMin, tiltRange[0].axMax); - printf("%d to %d along y\n", tiltRange[1].axMin, tiltRange[1].axMax); + print("x", tiltRange[0]); + print("y", tiltRange[1]); tiltScaleX = 1.f / tiltRange[0].axMax; tiltScaleY = 1.f / tiltRange[1].axMax; + func_Info(WTI_EXTENSIONS + tag, EXT_MASK, &tiltMask); } else { - printf("none\n"); + puts("none"); tiltScaleX = tiltScaleY = 0.f; } #endif // WTX_TILT @@ -165,18 +167,27 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) // set up context LOGCONTEXT archetype; -// func_Info(WTI_DEFSYSCTX, 0, &archetype); - func_Info(WTI_DEFCONTEXT, 0, &archetype); + func_Info(WTI_DEFSYSCTX, 0, &archetype); +// func_Info(WTI_DEFCONTEXT, 0, &archetype); strcpy(archetype.lcName, "blender special"); - archetype.lcPktData = PACKETDATA; - archetype.lcPktMode = PACKETMODE; -// archetype.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES; - archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES | CXO_CSRMESSAGES; + WTPKT packetData = PACKETDATA; + if (!hasPressure) + packetData &= ~PK_NORMAL_PRESSURE; + if (!hasTilt) + packetData &= ~PK_ORIENTATION; + archetype.lcPktData = packetData; + + archetype.lcPktMode = PACKETMODE; + archetype.lcOptions |= /*CXO_MESSAGES |*/ CXO_CSRMESSAGES; +// archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES | CXO_CSRMESSAGES; + +#if PACKETMODE & PK_BUTTONS // we want first 5 buttons archetype.lcBtnDnMask = 0x1f; archetype.lcBtnUpMask = 0x1f; +#endif // BEGIN derived from Wacom's TILTTEST.C: AXIS TabletX, TabletY; @@ -259,16 +270,23 @@ void GHOST_TabletManagerWin32::convertTilt(ORIENTATION const& ort, TabletToolDat data.tilt_y = sin(M_PI/2.0 - azmRad) * vecLen; } -void GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) +bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) { + if (window == NULL) + window = activeWindow; + HCTX context = contextForWindow(window); + bool anyProcessed = false; + if (context) { +// PACKET packet; +// func_Packet(context, serialNumber, &packet); PACKET packets[MAX_QUEUE_SIZE]; int n = func_PacketsGet(context, MAX_QUEUE_SIZE, packets); - // printf("processing %d packets\n", n); - +// printf("processing %d packets\n", n); + for (int i = 0; i < n; ++i) { PACKET const& packet = packets[i]; @@ -277,15 +295,20 @@ void GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) int y = packet.pkY; if (activeTool.type == TABLET_MOUSE) - if (x == prevMouseX && y == prevMouseY) + if (x == prevMouseX && y == prevMouseY && packet.pkButtons == prevButtons) // don't send any "mouse hasn't moved" events continue; else { prevMouseX = x; prevMouseY = y; } - - // every packet from a WT_PACKET message comes from the same tool + + anyProcessed = true; + + // Since we're using a digitizing context, we need to + // move the on-screen cursor ourselves. + // SetCursorPos(x, y); + switch (activeTool.type) { case TABLET_MOUSE: @@ -316,108 +339,159 @@ void GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) if (activeTool.hasTilt) { - // ORIENTATION const& tilt = packet.pkOrientation; - // printf(" /%d,%d/", tilt.orAzimuth, tilt.orAltitude); - convertTilt(packet.pkOrientation, data); - + ORIENTATION const& o = packet.pkOrientation; + + if (o.orAzimuth || o.orAltitude) + { + convertTilt(o, data); + printf(" /%d,%d/", o.orAzimuth, o.orAltitude); + printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); + if (fabs(data.tilt_x) < 0.001 && fabs(data.tilt_x) < 0.001) + { + // really should fix the initial test for activeTool.hasTilt, + // not apply a band-aid here. + data.tool.hasTilt = false; + data.tilt_x = 0.f; + data.tilt_y = 0.f; + } + } + else + data.tool.hasTilt = false; + // data.tilt_x = tiltScaleX * packet.pkTilt.tiltX; // data.tilt_y = tiltScaleY * packet.pkTilt.tiltY; - printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); } - - putchar('\n'); // at this point, construct a GHOST event and push it into the queue! - // (having trouble with Wacom mouse scaling, so ignore it for now) -// if (activeTool.type == TABLET_PEN || activeTool.type == TABLET_ERASER) - { - GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem(); + GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem(); - if (packet.pkButtons) - { - // which button? - GHOST_TButtonMask e_button; - int buttonNumber = LOWORD(packet.pkButtons); - e_button = (GHOST_TButtonMask) buttonNumber; - - // pressed or released? - GHOST_TEventType e_action; - int buttonAction = HIWORD(packet.pkButtons); - if (buttonAction == TBN_DOWN) - e_action = GHOST_kEventButtonDown; - else - e_action = GHOST_kEventButtonUp; - - printf("button %d %s\n", buttonNumber, buttonAction == TBN_DOWN ? "down" : "up"); - - GHOST_EventButton* e = new GHOST_EventButton(system->getMilliSeconds(), e_action, window, e_button); - -// system->pushEvent(e); - } + // any buttons changed? + #if PACKETMODE & PK_BUTTONS + // relative buttons mode + if (packet.pkButtons) + { + // which button? + GHOST_TButtonMask e_button; + int buttonNumber = LOWORD(packet.pkButtons); + e_button = (GHOST_TButtonMask) buttonNumber; + + // pressed or released? + GHOST_TEventType e_action; + int buttonAction = HIWORD(packet.pkButtons); + if (buttonAction == TBN_DOWN) + e_action = GHOST_kEventButtonDown; else + e_action = GHOST_kEventButtonUp; + + printf(" button %d %s\n", buttonNumber, buttonAction == TBN_DOWN ? "down" : "up"); + + GHOST_EventButton* e = new GHOST_EventButton(system->getMilliSeconds(), e_action, window, e_button); + + system->pushEvent(e); + } + #else + // absolute buttons mode + UINT diff = prevButtons ^ packet.pkButtons; + if (diff) + { + for (int i = 0; i < 32 /*GHOST_kButtonNumMasks*/; ++i) { - GHOST_EventCursor* e = new GHOST_EventCursor(system->getMilliSeconds(), GHOST_kEventCursorMove, window, x, y); + UINT mask = 1 << i; + + if (diff & mask) + { + GHOST_TButtonMask e_button = (GHOST_TButtonMask) i; + GHOST_TEventType e_action = (packet.pkButtons & mask) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp; - // use older TabletData struct for testing until mine is in place - GHOST_TabletData& e_data = ((GHOST_TEventCursorData*) e->getData())->tablet; - e_data.Active = (GHOST_TTabletMode) data.tool.type; - e_data.Pressure = data.pressure; - e_data.Xtilt = data.tilt_x; - e_data.Ytilt = data.tilt_y; + GHOST_EventButton* e = new GHOST_EventButton(system->getMilliSeconds(), e_action, window, e_button); + GHOST_TabletData& e_data = ((GHOST_TEventButtonData*) e->getData())->tablet; + e_data.Active = (GHOST_TTabletMode) data.tool.type; + e_data.Pressure = data.pressure; + e_data.Xtilt = data.tilt_x; + e_data.Ytilt = data.tilt_y; -// system->pushEvent(e); + printf(" button %d %s\n", i, (e_action == GHOST_kEventButtonDown) ? "down" : "up"); + + system->pushEvent(e); + } } + + prevButtons = packet.pkButtons; + } + #endif + else + { + GHOST_EventCursor* e = new GHOST_EventCursor(system->getMilliSeconds(), GHOST_kEventCursorMove, window, x, y); + + // use older TabletData struct for testing until mine is in place + GHOST_TabletData& e_data = ((GHOST_TEventCursorData*) e->getData())->tablet; + e_data.Active = (GHOST_TTabletMode) data.tool.type; + e_data.Pressure = data.pressure; + e_data.Xtilt = data.tilt_x; + e_data.Ytilt = data.tilt_y; + + puts(" move"); + + system->pushEvent(e); } } } + return anyProcessed; } -void GHOST_TabletManagerWin32::changeTool(HCTX context, UINT serialNumber) +void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window, UINT serialNumber) { puts("-- changing tool --"); dropTool(); - PACKET packet; - func_Packet(context, serialNumber, &packet); - UINT cursor = (packet.pkCursor - cursorBase) % cursorCount; - - // printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursor); + HCTX context = contextForWindow(window); - switch (cursor) + if (context) { - case 0: // older Intuos tablets can track two cursors at once - case 3: // so we test for both here - activeTool.type = TABLET_MOUSE; - break; - case 1: - case 4: - activeTool.type = TABLET_PEN; - break; - case 2: - case 5: - activeTool.type = TABLET_ERASER; - break; - default: - activeTool.type = TABLET_NONE; + activeWindow = window; + + PACKET packet; + func_Packet(context, serialNumber, &packet); + UINT cursor = (packet.pkCursor - cursorBase) % cursorCount; + + // printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursor); + + switch (cursor) + { + case 0: // older Intuos tablets can track two cursors at once + case 3: // so we test for both here + activeTool.type = TABLET_MOUSE; + break; + case 1: + case 4: + activeTool.type = TABLET_PEN; + break; + case 2: + case 5: + activeTool.type = TABLET_ERASER; + break; + default: + activeTool.type = TABLET_NONE; + } + + WTPKT toolData; + func_Info(WTI_CURSORS + packet.pkCursor, CSR_PKTDATA, &toolData); + activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; + activeTool.hasTilt = toolData & PK_ORIENTATION; + // activeTool.hasTilt = toolData & tiltMask; + + if (activeTool.hasPressure) + puts(" - pressure"); + + if (activeTool.hasTilt) + puts(" - tilt"); + + // and just for fun: + if (toolData & PK_BUTTONS) + puts(" - buttons"); } - - WTPKT toolData; - func_Info(WTI_CURSORS + cursor, CSR_PKTDATA, &toolData); - activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; - activeTool.hasTilt = toolData & PK_ORIENTATION; -// activeTool.hasTilt = toolData & tiltMask; - - if (activeTool.hasPressure) - puts(" - pressure"); - - if (activeTool.hasTilt) - puts(" - tilt"); - - // and just for fun: - if (toolData & PK_BUTTONS) - puts(" - buttons"); } void GHOST_TabletManagerWin32::dropTool() @@ -427,4 +501,7 @@ void GHOST_TabletManagerWin32::dropTool() activeTool.hasTilt = false; prevMouseX = prevMouseY = 0; + prevButtons = 0; + + activeWindow = NULL; } diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h index 290798a6bfb..c23c2bc3cb5 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.h +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -69,15 +69,16 @@ class GHOST_TabletManagerWin32 UINT cursorCount; UINT cursorBase; - // candidate for a base class: + // book-keeping + std::map contexts; + HCTX contextForWindow(GHOST_WindowWin32*); + + GHOST_WindowWin32* activeWindow; TabletTool activeTool; int prevMouseX; int prevMouseY; - - // book-keeping - std::map contexts; - HCTX contextForWindow(GHOST_WindowWin32*); + UINT prevButtons; void convertTilt(ORIENTATION const&, TabletToolData&); @@ -90,9 +91,11 @@ public: void openForWindow(GHOST_WindowWin32*); void closeForWindow(GHOST_WindowWin32*); - void processPackets(GHOST_WindowWin32*); + // returns whether any packets resulted in GHOST events + bool processPackets(GHOST_WindowWin32* = NULL); +// void processPacket(GHOST_WindowWin32*, UINT serialNumber); - void changeTool(HCTX, UINT serialNumber); + void changeTool(GHOST_WindowWin32*, UINT serialNumber); void dropTool(); }; @@ -100,10 +103,10 @@ public: The tablet manager is driven by the following Windows event processing code: case WT_PACKET: - m_tabletManager->processPackets((HCTX)lParam); + m_tabletManager->processPackets(window); break; case WT_CSRCHANGE: - m_tabletManager->changeTool((HCTX)lParam, wParam); + m_tabletManager->changeTool(window, wParam); break; case WT_PROXIMITY: if (LOWORD(lParam) == 0) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index bce1cc22f7f..6a2102633c3 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1977,7 +1977,7 @@ int WM_modal_tweak_exit(wmEvent *evt, int tweak_event) if(evt->val==tweak_modal) return 1; default: - /* this case is when modal callcback didnt get started with a tweak */ + /* this case is when modal callback didnt get started with a tweak */ if(evt->val) return 1; } @@ -2062,28 +2062,6 @@ static int convert_key(GHOST_TKey key) } } -#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) { @@ -2100,7 +2078,7 @@ static void attach_tablet_data(wmEvent* event, const GHOST_TabletData* ghost) event->customdata = data; event->customdatafree = 1; - printf("+ pressure = %.2f tilt = %.2f %2f\n", data->Pressure, data->Xtilt, data->Ytilt); + // printf("+ pressure = %.2f tilt = %.2f %.2f\n", data->Pressure, data->Xtilt, data->Ytilt); } } @@ -2165,7 +2143,7 @@ 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 (or milliseconds?), from ghost */ +/* time is in milliseconds, from ghost */ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int time, void *customdata) { wmWindow *owin; @@ -2205,7 +2183,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int t lastevent->type = INBETWEEN_MOUSEMOVE; 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 */ @@ -2218,7 +2195,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int t oevent.y=owin->eventstate->y= event.y; oevent.type= MOUSEMOVE; - // update_tablet_data(owin, &oevent); wm_event_add(owin, &oevent); } } @@ -2263,7 +2239,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int t case GHOST_kEventButtonDown: case GHOST_kEventButtonUp: { GHOST_TEventButtonData *bd= customdata; - event.val= (type==GHOST_kEventButtonDown) ? KM_PRESS:KM_RELEASE; /* Note!, this starts as 0/1 but later is converted to KM_PRESS/KM_RELEASE by tweak */ + event.val= (type==GHOST_kEventButtonDown) ? KM_PRESS:KM_RELEASE; + /* Note!, this starts as 0/1 but later is converted to KM_PRESS/KM_RELEASE by tweak */ if (bd->button == GHOST_kButtonMaskLeft) event.type= LEFTMOUSE; @@ -2287,12 +2264,10 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int t oevent.val= event.val; attach_tablet_data(&oevent, &(bd->tablet)); - // update_tablet_data(owin, &oevent); wm_event_add(owin, &oevent); } else { attach_tablet_data(&event, &(bd->tablet)); - // update_tablet_data(win, &event); wm_event_add(win, &event); } -- cgit v1.2.3 From 0473790bbeb24dd1fec1314f9a8e12b2fb155734 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 14 Aug 2010 23:33:22 +0000 Subject: removed gpencil Manhattan distance from user prefs. updated ghost build script. --- intern/ghost/SConscript | 2 +- release/scripts/ui/space_userpref.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript index 65c00b16373..f6b818c0efc 100644 --- a/intern/ghost/SConscript +++ b/intern/ghost/SConscript @@ -11,7 +11,7 @@ if window_system == 'darwin': sources += env.Glob('intern/*.mm') -pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_Window', 'GHOST_DropTarget'] +pf = ['GHOST_DisplayManager', 'GHOST_System', 'GHOST_Window', 'GHOST_DropTarget','GHOST_TabletManager'] defs=['_USE_MATH_DEFINES'] if window_system in ('linux2', 'openbsd3', 'sunos5', 'freebsd6', 'irix6', 'aix4', 'aix5'): diff --git a/release/scripts/ui/space_userpref.py b/release/scripts/ui/space_userpref.py index 6f521ede722..4383f9a597c 100644 --- a/release/scripts/ui/space_userpref.py +++ b/release/scripts/ui/space_userpref.py @@ -277,7 +277,8 @@ class USERPREF_PT_edit(bpy.types.Panel): col = row.column() col.label(text="Grease Pencil:") - col.prop(edit, "grease_pencil_manhattan_distance", text="Manhattan Distance") + #[mce] not used in this branch + #col.prop(edit, "grease_pencil_manhattan_distance", text="Manhattan Distance") col.prop(edit, "grease_pencil_euclidean_distance", text="Euclidean Distance") #col.prop(edit, "grease_pencil_simplify_stroke", text="Simplify Stroke") col.prop(edit, "grease_pencil_eraser_radius", text="Eraser Radius") -- cgit v1.2.3 From 2c468d9e5a60b60ab70d1daabc3833d3e90d35eb Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 15 Aug 2010 11:02:03 +0000 Subject: Further hacking on Windows tablet code. More accurate detection of certain tablet tools (mice, etc.). Made tablet mouse/pen buttons play nice with GHOST. Removed old code from WindowWin32. --- intern/ghost/GHOST_IWindow.h | 10 +- intern/ghost/intern/GHOST_SystemWin32.cpp | 13 +- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 299 +++++++++++++++++------ intern/ghost/intern/GHOST_TabletManagerWin32.h | 27 +- intern/ghost/intern/GHOST_WindowWin32.cpp | 182 -------------- intern/ghost/intern/GHOST_WindowWin32.h | 33 --- 6 files changed, 254 insertions(+), 310 deletions(-) diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index 83757b17e8b..a6832868e8a 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -227,13 +227,15 @@ public: * @param data The window user data. */ virtual void setUserData(const GHOST_TUserDataPtr userData) = 0; - + /** * Returns the tablet data (pressure etc). * @return The tablet data (pressure etc). */ - virtual const GHOST_TabletData* GetTabletData() = 0; - + virtual const GHOST_TabletData* GetTabletData() + { return NULL; } + /* this function is targeted for removal by significant-bit */ + /*************************************************************************************** ** Progress bar functionality ***************************************************************************************/ @@ -304,8 +306,6 @@ public: * @return Indication of success. */ virtual GHOST_TSuccess setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_Rect *bounds) { return GHOST_kSuccess; }; - }; #endif // _GHOST_IWINDOW_H_ - diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 0f567dec4e2..11ba695a4f9 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -247,8 +247,12 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent) } } while (waitForEvent && !anyProcessed); - if (m_tabletManager->processPackets()) - anyProcessed = true; +// Handle tablet input either here (polling) +// or after WT_PACKET messages (event driven) +// -- not both! + +// if (m_tabletManager->processPackets()) +// anyProcessed = true; return anyProcessed; } @@ -951,7 +955,6 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM // Tablet events, processed //////////////////////////////////////////////////////////////////////// case WT_PACKET: - puts("WT_PACKET"); m_tabletManager->processPackets(window); break; case WT_CSRCHANGE: @@ -1011,7 +1014,9 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM case WM_MOUSEMOVE: { - if (!eventIsFromTablet()) + if (!eventIsFromTablet() && !m_tabletManager->anyButtonsDown()) + // Even with careful checking, a stray cursor event sneaks through just before each + // tablet mouse/pen button up event. Keep clean separation between tablet and mouse! { int xPrev = mousePosX; int yPrev = mousePosY; diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp index 9278ad2f48e..a34d6730cee 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -10,8 +10,8 @@ #include #include -#define PACKETDATA PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION -#define PACKETMODE 0 /*PK_BUTTONS*/ +#define PACKETDATA (PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION) +#define PACKETMODE (0 /*PK_BUTTONS*/) // #define PACKETTILT PKEXT_ABSOLUTE #include "pktdef.h" @@ -31,6 +31,29 @@ static void print(AXIS const& t, char const* label = NULL) unitName[t.axUnits]); } +static void print(WTPKT packet) + { + if (packet == 0) + puts("- nothing special"); + else + { + if (packet & PK_CONTEXT) puts("- reporting context"); + if (packet & PK_STATUS) puts("- status bits"); + if (packet & PK_TIME) puts("- time stamp"); + if (packet & PK_CHANGED) puts("- change bit vector"); + if (packet & PK_SERIAL_NUMBER) puts("- packet serial number"); + if (packet & PK_CURSOR) puts("- reporting cursor"); + if (packet & PK_BUTTONS) puts("- buttons"); + if (packet & PK_X) puts("- x axis"); + if (packet & PK_Y) puts("- y axis"); + if (packet & PK_Z) puts("- z axis"); + if (packet & PK_NORMAL_PRESSURE) puts("- tip pressure"); + if (packet & PK_TANGENT_PRESSURE) puts("- barrel pressure"); + if (packet & PK_ORIENTATION) puts("- orientation/tilt"); + if (packet & PK_ROTATION) puts("- rotation"); + } + } + GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() : activeWindow(NULL) { @@ -49,40 +72,32 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() func_PacketsGet = (WTPACKETSGET) GetProcAddress(lib_Wintab,"WTPacketsGet"); func_Packet = (WTPACKET) GetProcAddress(lib_Wintab,"WTPacket"); - WORD specV, implV; - func_Info(WTI_INTERFACE, IFC_SPECVERSION, &specV); - func_Info(WTI_INTERFACE, IFC_IMPLVERSION, &implV); - printf("WinTab version %d.%d (%d.%d)\n", - HIBYTE(specV), LOBYTE(specV), HIBYTE(implV), LOBYTE(implV)); - - // query for overall capabilities and ranges - char tabletName[LC_NAMELEN]; - if (func_Info(WTI_DEVICES, DVC_NAME, tabletName)) - puts(tabletName); - - puts("active tablet area"); - AXIS xRange, yRange; - func_Info(WTI_DEVICES, DVC_X, &xRange); - func_Info(WTI_DEVICES, DVC_Y, &yRange); - print(xRange,"x"); print(yRange,"y"); - - + puts("\n-- essential tablet info --"); func_Info(WTI_DEVICES, DVC_NCSRTYPES, &cursorCount); func_Info(WTI_DEVICES, DVC_FIRSTCSR, &cursorBase); - puts("pressure sensitivity"); + func_Info(WTI_DEVICES, DVC_PKTDATA, &allTools); + puts("\nall tools have"); print(allTools); + func_Info(WTI_DEVICES, DVC_CSRDATA, &someTools); + puts("some tools also have"); print(someTools); + + puts("\npressure sensitivity"); AXIS pressureRange; - hasPressure = func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange);// && pressureRange.axMax != 0; - print(pressureRange); + hasPressure = (allTools|someTools) & PK_NORMAL_PRESSURE + && func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange); if (hasPressure) + { + print(pressureRange); pressureScale = 1.f / pressureRange.axMax; + } else pressureScale = 0.f; - puts("tilt sensitivity"); + puts("\ntilt sensitivity"); AXIS tiltRange[3]; - hasTilt = func_Info(WTI_DEVICES, DVC_ORIENTATION, tiltRange); + hasTilt = (allTools|someTools) & PK_ORIENTATION + && func_Info(WTI_DEVICES, DVC_ORIENTATION, &tiltRange); if (hasTilt) { @@ -103,7 +118,7 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() #if 0 // WTX_TILT -- cartesian tilt extension, no conversion needed // this isn't working for [mce], so let it rest for now - printf("raw tilt sensitivity:\n"); + puts("\nraw tilt sensitivity"); hasTilt = false; UINT tag = 0; UINT extensionCount; @@ -135,6 +150,8 @@ GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() tiltScaleX = tiltScaleY = 0.f; } #endif // WTX_TILT + + getExtraInfo(); } } @@ -144,6 +161,83 @@ GHOST_TabletManagerWin32::~GHOST_TabletManagerWin32() FreeLibrary(lib_Wintab); } +void GHOST_TabletManagerWin32::getExtraInfo() + { + puts("\n-- extra tablet info --"); + + WORD specV, implV; + func_Info(WTI_INTERFACE, IFC_SPECVERSION, &specV); + func_Info(WTI_INTERFACE, IFC_IMPLVERSION, &implV); + printf("WinTab version %d.%d (%d.%d)\n", + HIBYTE(specV), LOBYTE(specV), HIBYTE(implV), LOBYTE(implV)); + + UINT ndevices, ncursors; + func_Info(WTI_INTERFACE, IFC_NDEVICES, &ndevices); + func_Info(WTI_INTERFACE, IFC_NCURSORS, &ncursors); + + printf("%d tablets, %d tools\n", ndevices, ncursors); + if (ndevices > 1) + ; // support this? + + // query for overall capabilities and ranges + char tabletName[LC_NAMELEN]; + if (func_Info(WTI_DEVICES, DVC_NAME, tabletName)) + puts(tabletName); + + puts("\nactive tablet area"); + AXIS xRange, yRange; + func_Info(WTI_DEVICES, DVC_X, &xRange); + func_Info(WTI_DEVICES, DVC_Y, &yRange); + print(xRange,"x"); print(yRange,"y"); + + putchar('\n'); + + UINT extensionCount; + func_Info(WTI_INTERFACE, IFC_NEXTENSIONS, &extensionCount); + for (UINT i = 0; i < extensionCount; ++i) + { + TCHAR name[40]; + func_Info(WTI_EXTENSIONS + i, EXT_NAME, name); + printf("extension %d: %s\n", i, name); + } + +// for (int i = cursorBase; i < cursorBase + cursorCount; ++i) + for (UINT i = 0; i < ncursors; ++i) + { + // what can each cursor do? + + UINT physID; + func_Info(WTI_CURSORS + i, CSR_PHYSID, &physID); + if (physID == 0) + // each 'real' cursor has a physical ID + // (on Intuos at least, test on Graphire also) + continue; + + TCHAR name[40]; + func_Info(WTI_CURSORS + i, CSR_NAME, name); + printf("\ncursor %d: %s\n", i, name); + + BOOL active; + func_Info(WTI_CURSORS + i, CSR_ACTIVE, &active); + printf("active: %s\n", active ? "yes" : "no"); + + WTPKT packet; + func_Info(WTI_CURSORS + i, CSR_PKTDATA, &packet); + // only report the 'special' bits that distinguish this cursor from the rest + puts("packet support"); print(packet & someTools); + + puts("buttons:"); + BYTE buttons; + BYTE sysButtonMap[32]; + func_Info(WTI_CURSORS + i, CSR_BUTTONS, &buttons); + func_Info(WTI_CURSORS + i, CSR_SYSBTNMAP, sysButtonMap); + for (int i = 0; i < buttons; ++i) + printf(" %d -> %d\n", i, sysButtonMap[i]); + } + + putchar('\n'); + } + bool GHOST_TabletManagerWin32::available() { return lib_Wintab // driver installed @@ -169,6 +263,7 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) LOGCONTEXT archetype; func_Info(WTI_DEFSYSCTX, 0, &archetype); // func_Info(WTI_DEFCONTEXT, 0, &archetype); +// func_Info(WTI_DSCTXS, 0, &archetype); strcpy(archetype.lcName, "blender special"); @@ -180,8 +275,8 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) archetype.lcPktData = packetData; archetype.lcPktMode = PACKETMODE; - archetype.lcOptions |= /*CXO_MESSAGES |*/ CXO_CSRMESSAGES; -// archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES | CXO_CSRMESSAGES; +// archetype.lcOptions |= CXO_CSRMESSAGES; // <-- lean mean version + archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES | CXO_CSRMESSAGES; #if PACKETMODE & PK_BUTTONS // we want first 5 buttons @@ -220,6 +315,7 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) printf("tablet queue size: %d\n", tabletQueueSize); contexts[window] = context; + activeWindow = window; } void GHOST_TabletManagerWin32::closeForWindow(GHOST_WindowWin32* window) @@ -231,6 +327,8 @@ void GHOST_TabletManagerWin32::closeForWindow(GHOST_WindowWin32* window) func_Close(context); // also remove it from our books: contexts.erase(contexts.find(window)); + if (activeWindow == window) + activeWindow = NULL; } } @@ -270,6 +368,28 @@ void GHOST_TabletManagerWin32::convertTilt(ORIENTATION const& ort, TabletToolDat data.tilt_y = sin(M_PI/2.0 - azmRad) * vecLen; } +bool GHOST_TabletManagerWin32::convertButton(const UINT button, GHOST_TButtonMask& ghost) + { + switch (sysButtonMap[button]) + { + case 1: + ghost = GHOST_kButtonMaskLeft; + break; + case 4: + ghost = GHOST_kButtonMaskRight; + break; + case 7: + ghost = GHOST_kButtonMaskMiddle; + break; + // sorry, no Button4 or Button5 + // they each map to 0 (unused) + default: + return false; + }; + + return true; + } + bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) { if (window == NULL) @@ -305,7 +425,7 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) anyProcessed = true; - // Since we're using a digitizing context, we need to + // If we're using a digitizing context, we need to // move the on-screen cursor ourselves. // SetCursorPos(x, y); @@ -344,8 +464,6 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) if (o.orAzimuth || o.orAltitude) { convertTilt(o, data); - printf(" /%d,%d/", o.orAzimuth, o.orAltitude); - printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); if (fabs(data.tilt_x) < 0.001 && fabs(data.tilt_x) < 0.001) { // really should fix the initial test for activeTool.hasTilt, @@ -354,6 +472,11 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) data.tilt_x = 0.f; data.tilt_y = 0.f; } + else + { + // printf(" /%d,%d/", o.orAzimuth, o.orAltitude); + printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); + } } else data.tool.hasTilt = false; @@ -367,8 +490,7 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem(); // any buttons changed? - #if PACKETMODE & PK_BUTTONS - // relative buttons mode + #if PACKETMODE & PK_BUTTONS // relative buttons mode if (packet.pkButtons) { // which button? @@ -390,8 +512,7 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) system->pushEvent(e); } - #else - // absolute buttons mode + #else // absolute buttons mode UINT diff = prevButtons ^ packet.pkButtons; if (diff) { @@ -401,19 +522,23 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) if (diff & mask) { - GHOST_TButtonMask e_button = (GHOST_TButtonMask) i; - GHOST_TEventType e_action = (packet.pkButtons & mask) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp; - - GHOST_EventButton* e = new GHOST_EventButton(system->getMilliSeconds(), e_action, window, e_button); - GHOST_TabletData& e_data = ((GHOST_TEventButtonData*) e->getData())->tablet; - e_data.Active = (GHOST_TTabletMode) data.tool.type; - e_data.Pressure = data.pressure; - e_data.Xtilt = data.tilt_x; - e_data.Ytilt = data.tilt_y; - - printf(" button %d %s\n", i, (e_action == GHOST_kEventButtonDown) ? "down" : "up"); - - system->pushEvent(e); + GHOST_TButtonMask e_button; + if (convertButton(i, e_button)) + { + GHOST_TEventType e_action = (packet.pkButtons & mask) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp; + + GHOST_EventButton* e = new GHOST_EventButton(system->getMilliSeconds(), e_action, window, e_button); + GHOST_TabletData& e_data = ((GHOST_TEventButtonData*) e->getData())->tablet; + e_data.Active = (GHOST_TTabletMode) data.tool.type; + e_data.Pressure = data.pressure; + e_data.Xtilt = data.tilt_x; + e_data.Ytilt = data.tilt_y; + + printf(" button %d %s\n", i, (e_action == GHOST_kEventButtonDown) ? "down" : "up"); + + system->pushEvent(e); + } + else puts(" mystery button (discarded)"); } } @@ -451,14 +576,14 @@ void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window, UINT serial if (context) { activeWindow = window; - + PACKET packet; func_Packet(context, serialNumber, &packet); - UINT cursor = (packet.pkCursor - cursorBase) % cursorCount; - - // printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursor); - - switch (cursor) + + // try one way to classify cursor + UINT cursorType = (packet.pkCursor - cursorBase) % cursorCount; + printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursorType); + switch (cursorType) { case 0: // older Intuos tablets can track two cursors at once case 3: // so we test for both here @@ -475,22 +600,55 @@ void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window, UINT serial default: activeTool.type = TABLET_NONE; } - + + // now try another way + func_Info(WTI_CURSORS + packet.pkCursor, CSR_TYPE, &cursorType); + switch (cursorType & 0xf06) + { + case 0x802: + puts("general stylus"); + break; + case 0x902: + puts("airbrush"); + break; + case 0x804: + puts("art pen"); + break; + case 0x004: + puts("4D mouse"); + break; + case 0x006: + puts("5-button puck"); + break; + default: + puts("???"); + } + WTPKT toolData; func_Info(WTI_CURSORS + packet.pkCursor, CSR_PKTDATA, &toolData); - activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; - activeTool.hasTilt = toolData & PK_ORIENTATION; - // activeTool.hasTilt = toolData & tiltMask; - - if (activeTool.hasPressure) - puts(" - pressure"); - - if (activeTool.hasTilt) - puts(" - tilt"); - - // and just for fun: - if (toolData & PK_BUTTONS) - puts(" - buttons"); + // discard any stray capabilities + // (sometimes cursors claim to be able to do things + // that their tablet doesn't support) + toolData &= (allTools|someTools); + // only report the 'special' bits that distinguish this cursor from the rest + puts("packet support"); print(toolData & someTools); + putchar('\n'); + + if (activeTool.type == TABLET_MOUSE) + { + // don't always trust CSR_PKTDATA! + activeTool.hasPressure = false; + activeTool.hasTilt = false; + } + else + { + activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; + activeTool.hasTilt = toolData & PK_ORIENTATION; + // activeTool.hasTilt = toolData & tiltMask; + } + + // remember user's custom button assignments for this tool + func_Info(WTI_CURSORS + packet.pkCursor, CSR_SYSBTNMAP, sysButtonMap); } } @@ -505,3 +663,8 @@ void GHOST_TabletManagerWin32::dropTool() activeWindow = NULL; } + +bool GHOST_TabletManagerWin32::anyButtonsDown() + { + return prevButtons != 0; + } diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h index c23c2bc3cb5..835711bb6c4 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.h +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -10,6 +10,7 @@ #include "wintab.h" #include +#include "GHOST_Types.h" class GHOST_WindowWin32; // BEGIN from Wacom's Utils.h @@ -57,6 +58,8 @@ class GHOST_TabletManagerWin32 WTPACKETSGET func_PacketsGet; WTPACKET func_Packet; + void getExtraInfo(); // to help support new/untested tablets + // tablet attributes bool hasPressure; float pressureScale; @@ -68,6 +71,8 @@ class GHOST_TabletManagerWin32 // UINT tiltMask; UINT cursorCount; UINT cursorBase; + WTPKT allTools; // standard info available from any tool (mouse/pen/etc.) + WTPKT someTools; // extra info available from only some tools // book-keeping std::map contexts; @@ -75,12 +80,14 @@ class GHOST_TabletManagerWin32 GHOST_WindowWin32* activeWindow; TabletTool activeTool; + BYTE sysButtonMap[32]; // user's custom button assignments for active tool int prevMouseX; int prevMouseY; UINT prevButtons; void convertTilt(ORIENTATION const&, TabletToolData&); + bool convertButton(const UINT button, GHOST_TButtonMask&); public: GHOST_TabletManagerWin32(); @@ -97,24 +104,8 @@ public: void changeTool(GHOST_WindowWin32*, UINT serialNumber); void dropTool(); - }; -/* -The tablet manager is driven by the following Windows event processing code: - -case WT_PACKET: - m_tabletManager->processPackets(window); - break; -case WT_CSRCHANGE: - m_tabletManager->changeTool(window, wParam); - break; -case WT_PROXIMITY: - if (LOWORD(lParam) == 0) - { - puts("-- dropping tool --"); - m_tabletManager->dropTool(); - } - break; -*/ + bool anyButtonsDown(); + }; #endif diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index 361223a2cc8..98609926fe8 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -125,10 +125,6 @@ GHOST_WindowWin32::GHOST_WindowWin32( m_hasMouseCaptured(false), m_nPressedButtons(0), m_customCursor(0), -// m_wintab(false), -// m_tabletData(NULL), -// m_tablet(0), -// m_maxPressure(0), m_multisample(numOfAASamples), m_multisampleEnabled(msEnabled), m_msPixelFormat(msPixelFormat), @@ -236,83 +232,11 @@ GHOST_WindowWin32::GHOST_WindowWin32( m_hWnd = 0; } } - -#if 0 - m_wintab = LoadWintab(); - if (m_wintab) { - // let's see if we can initialize tablet here - /* check if WinTab available. */ - if (gpWTInfoA(0, 0, NULL)) { - // Now init the tablet - LOGCONTEXT lc; - AXIS TabletX, TabletY, Pressure, Orientation[3]; /* The maximum tablet size, pressure and orientation (tilt) */ - - // Open a Wintab context - - // Get default context information - gpWTInfoA( WTI_DEFCONTEXT, 0, &lc ); - - // Open the context - lc.lcPktData = PACKETDATA; - lc.lcPktMode = PACKETMODE; - lc.lcOptions |= /* CXO_MESSAGES | */ CXO_SYSTEM; - lc.lcOptions &= ~CXO_MESSAGES; - - /* Set the entire tablet as active */ - gpWTInfoA(WTI_DEVICES,DVC_X,&TabletX); - gpWTInfoA(WTI_DEVICES,DVC_Y,&TabletY); - - /* get the max pressure, to divide into a float */ - BOOL pressureSupport = gpWTInfoA(WTI_DEVICES, DVC_NPRESSURE, &Pressure); - if (pressureSupport) - m_maxPressure = Pressure.axMax; - else - m_maxPressure = 0; - - /* get the max tilt axes, to divide into floats */ - BOOL tiltSupport = gpWTInfoA(WTI_DEVICES, DVC_ORIENTATION, &Orientation); - if (tiltSupport) { - /* does the tablet support azimuth ([0]) and altitude ([1]) */ - if (Orientation[0].axResolution && Orientation[1].axResolution) { - /* all this assumes the minimum is 0 */ - m_maxAzimuth = Orientation[0].axMax; - m_maxAltitude = Orientation[1].axMax; - } - else { /* no so dont do tilt stuff */ - m_maxAzimuth = m_maxAltitude = 0; - } - } - - m_tablet = gpWTOpenA( m_hWnd, &lc, TRUE ); - if (m_tablet) { - m_tabletData = new GHOST_TabletData(); - m_tabletData->Active = GHOST_kTabletModeNone; - - // request a deep queue, to capture every pen point - int tabletQueueSize = 128; - while (!gpWTQueueSizeSet(m_tablet, tabletQueueSize)) - --tabletQueueSize; - printf("tablet queue size: %d\n", tabletQueueSize); - } - } - } -#endif } GHOST_WindowWin32::~GHOST_WindowWin32() { -#if 0 - if (m_wintab) { - if (m_tablet) - gpWTClose(m_tablet); - if (m_tabletData) - delete m_tabletData; - m_tabletData = NULL; - UnloadWintab(); - } -#endif - if (m_tabletManager) m_tabletManager->closeForWindow(this); @@ -922,112 +846,6 @@ void GHOST_WindowWin32::becomeTabletAware(GHOST_TabletManagerWin32* manager) m_tabletManager->openForWindow(this); } -#if 0 -void GHOST_WindowWin32::processWin32TabletInitEvent() -{ - if (m_wintab) { - // let's see if we can initialize tablet here - AXIS Pressure, Orientation[3]; /* The maximum tablet size */ - - BOOL pressureSupport = gpWTInfoA(WTI_DEVICES, DVC_NPRESSURE, &Pressure); - if (pressureSupport) - m_maxPressure = Pressure.axMax; - else - m_maxPressure = 0; - - BOOL tiltSupport = gpWTInfoA(WTI_DEVICES, DVC_ORIENTATION, &Orientation); - if (tiltSupport) { - /* does the tablet support azimuth ([0]) and altitude ([1]) */ - if (Orientation[0].axResolution && Orientation[1].axResolution) { - m_maxAzimuth = Orientation[0].axMax; - m_maxAltitude = Orientation[1].axMax; - } - else { /* no so dont do tilt stuff */ - m_maxAzimuth = m_maxAltitude = 0; - } - } - - m_tabletData->Active = GHOST_kTabletModeNone; - } -} - -void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam) -{ -// PACKET pkt; - if (m_wintab) { - printf("tablet event "); - PACKET pkt_buffer[128]; - int n = gpWTPacketsGet((HCTX)lParam, 128, pkt_buffer); - printf("(%d in queue) ", n); - for (int i = 0; i < n; ++i) { - PACKET& pkt = pkt_buffer[i]; - // "while" not "if" -- drain the queue! -// while (gpWTPacket((HCTX)lParam, wParam, &pkt)) { - putchar('.'); - if (m_tabletData) { - switch (pkt.pkCursor) { - case 0: /* first device */ - case 3: /* second device */ - m_tabletData->Active = GHOST_kTabletModeNone; /* puck - not yet supported */ - break; - case 1: - case 4: - m_tabletData->Active = GHOST_kTabletModeStylus; /* stylus */ - break; - case 2: - case 5: - m_tabletData->Active = GHOST_kTabletModeEraser; /* eraser */ - break; - } - if (m_maxPressure > 0) { - m_tabletData->Pressure = (float)pkt.pkNormalPressure / (float)m_maxPressure; - } else { - m_tabletData->Pressure = 1.0f; - } - - if ((m_maxAzimuth > 0) && (m_maxAltitude > 0)) { - ORIENTATION ort = pkt.pkOrientation; - float vecLen; - float altRad, azmRad; /* in radians */ - - /* - from the wintab spec: - orAzimuth Specifies the clockwise rotation of the - cursor about the z axis through a full circular range. - - orAltitude Specifies the angle with the x-y plane - through a signed, semicircular range. Positive values - specify an angle upward toward the positive z axis; - negative values specify an angle downward toward the negative z axis. - - wintab.h defines .orAltitude as a UINT but documents .orAltitude - as positive for upward angles and negative for downward angles. - WACOM uses negative altitude values to show that the pen is inverted; - therefore we cast .orAltitude as an (int) and then use the absolute value. - */ - - /* convert raw fixed point data to radians */ - altRad = (float)((fabs((float)ort.orAltitude)/(float)m_maxAltitude) * M_PI/2.0); - azmRad = (float)(((float)ort.orAzimuth/(float)m_maxAzimuth) * M_PI*2.0); - - /* find length of the stylus' projected vector on the XY plane */ - vecLen = cos(altRad); - - /* from there calculate X and Y components based on azimuth */ - m_tabletData->Xtilt = sin(azmRad) * vecLen; - m_tabletData->Ytilt = (float)(sin(M_PI/2.0 - azmRad) * vecLen); - - } else { - m_tabletData->Xtilt = 0.0f; - m_tabletData->Ytilt = 0.0f; - } - } - } - putchar('\n'); - } -} -#endif - /** Reverse the bits in a GHOST_TUns8 */ static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch) { diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 6cb68d2ff52..9b2a89cfa2f 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -43,25 +43,10 @@ #define WIN32_LEAN_AND_MEAN #include -/* -#include -#define PACKETDATA (PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR) -#define PACKETMODE PK_BUTTONS -#include -*/ - class GHOST_SystemWin32; class GHOST_DropTargetWin32; class GHOST_TabletManagerWin32; -/* -// typedefs for WinTab functions to allow dynamic loading -typedef UINT (API * GHOST_WIN32_WTInfo) ( UINT, UINT, LPVOID ); -typedef HCTX (API * GHOST_WIN32_WTOpen) (HWND, LPLOGCONTEXTA, BOOL); -typedef BOOL (API * GHOST_WIN32_WTClose) (HCTX); -typedef BOOL (API * GHOST_WIN32_WTPacket) (HCTX, UINT, LPVOID); -*/ - /** * GHOST window on M$ Windows OSs. * @author Maarten Gribnau @@ -250,12 +235,6 @@ public: */ void loadCursor(bool visible, GHOST_TStandardCursor cursorShape) const; - const GHOST_TabletData* GetTabletData() - { return NULL; /*m_tabletData;*/ } - -// void processWin32TabletInitEvent(); -// void processWin32TabletEvent(WPARAM wParam, LPARAM lParam); - void becomeTabletAware(GHOST_TabletManagerWin32*); protected: @@ -347,18 +326,6 @@ protected: static LPCSTR s_windowClassName; static const int s_maxTitleLength; - /** WinTab dll handle */ -// HMODULE m_wintab; -// bool m_wintab; - - /** Tablet data for GHOST */ -// GHOST_TabletData* m_tabletData; - - /** Stores the Tablet context if detected Tablet features using WinTab.dll */ -// HCTX m_tablet; -// LONG m_maxPressure; -// LONG m_maxAzimuth, m_maxAltitude; - /** Preferred number of samples */ GHOST_TUns16 m_multisample; -- cgit v1.2.3 From 4bfd915f9c1e2de30617683e2415d6d65bda4627 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 16 Aug 2010 18:59:36 +0000 Subject: pencils down! additional Windows Wacom wackiness. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 27 ++++-- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 111 ++++++++++++++++++----- intern/ghost/intern/GHOST_TabletManagerWin32.h | 33 ++++++- 3 files changed, 138 insertions(+), 33 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 11ba695a4f9..0315fa5870a 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -841,7 +841,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM wParam, LPARAM lParam) { GHOST_Event* event = NULL; - bool eventSent = false; + bool eventHandled = false; static int mousePosX = 0, mousePosY = 0; // track mouse position between calls @@ -1014,10 +1014,19 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM case WM_MOUSEMOVE: { - if (!eventIsFromTablet() && !m_tabletManager->anyButtonsDown()) + if (!eventIsFromTablet()) + { // Even with careful checking, a stray cursor event sneaks through just before each // tablet mouse/pen button up event. Keep clean separation between tablet and mouse! - { + if (m_tabletManager->anyButtonsDown()) + { + // tablet manager handles all its own cursor moves. + // ignore 'regular' mouse while a tablet tool is being used. + DefWindowProc(window->getHWND(), WM_MOUSEMOVE, wParam, lParam); + eventHandled = true; + break; + } + int xPrev = mousePosX; int yPrev = mousePosY; // window coordinates are passed in via lParam @@ -1056,10 +1065,10 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM UINT rawSize = sizeof(RAWINPUT); GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); - eventSent |= processRawInput(raw, window); + eventHandled |= processRawInput(raw, window); if (processRawInput(raw, window)) - eventSent = true; + eventHandled = true; // else // DefRawInputProc(&raw_ptr, 1, sizeof(RAWINPUTHEADER)); @@ -1089,7 +1098,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM for (int i = 0; i < n; ++i) { RAWINPUT const& raw = rawBuffer[i]; - eventSent |= processRawInput(raw, window); + eventHandled |= processRawInput(raw, window); } // clear processed events from the queue @@ -1290,13 +1299,13 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM #endif // illustrative code } - if (!eventSent) + if (!eventHandled) if (event) { pushEvent(event); - eventSent = true; + eventHandled = true; } - return eventSent; + return eventHandled; } GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp index a34d6730cee..868b5dcc162 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -171,27 +171,6 @@ void GHOST_TabletManagerWin32::getExtraInfo() printf("WinTab version %d.%d (%d.%d)\n", HIBYTE(specV), LOBYTE(specV), HIBYTE(implV), LOBYTE(implV)); - UINT ndevices, ncursors; - func_Info(WTI_INTERFACE, IFC_NDEVICES, &ndevices); - func_Info(WTI_INTERFACE, IFC_NCURSORS, &ncursors); - - printf("%d tablets, %d tools\n", ndevices, ncursors); - if (ndevices > 1) - ; // support this? - - // query for overall capabilities and ranges - char tabletName[LC_NAMELEN]; - if (func_Info(WTI_DEVICES, DVC_NAME, tabletName)) - puts(tabletName); - - puts("\nactive tablet area"); - AXIS xRange, yRange; - func_Info(WTI_DEVICES, DVC_X, &xRange); - func_Info(WTI_DEVICES, DVC_Y, &yRange); - print(xRange,"x"); print(yRange,"y"); - - putchar('\n'); - UINT extensionCount; func_Info(WTI_INTERFACE, IFC_NEXTENSIONS, &extensionCount); for (UINT i = 0; i < extensionCount; ++i) @@ -201,8 +180,84 @@ void GHOST_TabletManagerWin32::getExtraInfo() printf("extension %d: %s\n", i, name); } -// for (int i = cursorBase; i < cursorBase + cursorCount; ++i) - for (UINT i = 0; i < ncursors; ++i) + UINT deviceCount, cursorCount; + func_Info(WTI_INTERFACE, IFC_NDEVICES, &deviceCount); + func_Info(WTI_INTERFACE, IFC_NCURSORS, &cursorCount); + + printf("%d tablets, %d tools\n", deviceCount, cursorCount); + if (deviceCount > 1) + ; // support this? + + for (UINT i = 0; i < deviceCount; ++i) + { + Tablet tablet; + + // query for overall capabilities and ranges + char tabletName[LC_NAMELEN]; + if (func_Info(WTI_DEVICES, DVC_NAME, tabletName)) + printf("tablet %d: %s\n", i, tabletName); + + puts("\nactive tablet area"); + AXIS xRange, yRange; + func_Info(WTI_DEVICES + i, DVC_X, &xRange); + func_Info(WTI_DEVICES + i, DVC_Y, &yRange); + tablet.size_x = xRange.axMax; + tablet.size_y = yRange.axMax; + print(xRange,"x"); print(yRange,"y"); + + func_Info(WTI_DEVICES + i, DVC_NCSRTYPES, &cursorCount); + func_Info(WTI_DEVICES + i, DVC_FIRSTCSR, &cursorBase); + tablet.cursorBase = cursorBase; + tablet.cursorCount = cursorCount; + printf("owns tools %d to %d\n", cursorBase, cursorBase + cursorCount - 1); + + func_Info(WTI_DEVICES + i, DVC_PKTDATA, &allTools); + puts("\nall tools have"); print(allTools); + func_Info(WTI_DEVICES + i, DVC_CSRDATA, &someTools); + puts("some tools also have"); print(someTools); + + puts("\npressure sensitivity"); + AXIS pressureRange; + hasPressure = (allTools|someTools) & PK_NORMAL_PRESSURE + && func_Info(WTI_DEVICES + i, DVC_NPRESSURE, &pressureRange); + + if (hasPressure) + { + print(pressureRange); + pressureScale = 1.f / pressureRange.axMax; + } + else + pressureScale = 0.f; + + puts("\ntilt sensitivity"); + AXIS tiltRange[3]; + hasTilt = (allTools|someTools) & PK_ORIENTATION + && func_Info(WTI_DEVICES + i, DVC_ORIENTATION, &tiltRange); + + if (hasTilt) + { + // leave this code in place to help support tablets I haven't tested + const char* axisName[] = {"azimuth","altitude","twist"}; + for (int i = 0; i < 3; ++i) + print(tiltRange[i], axisName[i]); + + // cheat by using available data from Intuos4. test on other tablets!!! + // azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution); + // altitudeScale = 1.f / tiltRange[1].axMax; + + azimuthScale = 1.f / tiltRange[0].axMax; + altitudeScale = 1.f / tiltRange[1].axMax; + } + else + { + puts("none"); + azimuthScale = altitudeScale = 0.f; + } + + tablets.push_back(tablet); + } + + for (UINT i = 0; i < cursorCount; ++i) { // what can each cursor do? @@ -415,6 +470,13 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) int y = packet.pkY; if (activeTool.type == TABLET_MOUSE) + { + // until scaling is working better, use system cursor position instead + POINT systemPos; + GetCursorPos(&systemPos); + x = systemPos.x; + y = systemPos.y; + if (x == prevMouseX && y == prevMouseY && packet.pkButtons == prevButtons) // don't send any "mouse hasn't moved" events continue; @@ -422,6 +484,7 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) prevMouseX = x; prevMouseY = y; } + } anyProcessed = true; @@ -601,6 +664,7 @@ void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window, UINT serial activeTool.type = TABLET_NONE; } +//#if 0 // now try another way func_Info(WTI_CURSORS + packet.pkCursor, CSR_TYPE, &cursorType); switch (cursorType & 0xf06) @@ -623,6 +687,7 @@ void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window, UINT serial default: puts("???"); } +//#endif WTPKT toolData; func_Info(WTI_CURSORS + packet.pkCursor, CSR_PKTDATA, &toolData); diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h index 835711bb6c4..df6f43d0460 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.h +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -9,6 +9,7 @@ #include #include "wintab.h" #include +#include #include "GHOST_Types.h" class GHOST_WindowWin32; @@ -22,6 +23,10 @@ typedef int ( API * WTPACKETSGET ) ( HCTX, int, LPVOID ); typedef BOOL ( API * WTPACKET ) ( HCTX, UINT, LPVOID ); // END +// TabletToolData (and its components) are meant to replace GHOST_TabletData +// and its customdata analogue in the window manager. For now it's confined to the +// TabletManager. + typedef enum { TABLET_NONE, TABLET_PEN, TABLET_ERASER, TABLET_MOUSE } TabletToolType; typedef struct @@ -31,7 +36,7 @@ typedef struct // capabilities bool hasPressure : 1; bool hasTilt : 1; - + } TabletTool; @@ -45,6 +50,30 @@ typedef struct } TabletToolData; +// "Tablet" structure is not active by pencils down +// but will be soon. + +struct Tablet + { + bool hasPressure; + float pressureScale; + + bool hasTilt; + float azimuthScale; + float altitudeScale; + + UINT size_x, size_y; + + UINT cursorCount; + UINT cursorBase; + + WTPKT allTools; // standard info available from any tool (mouse/pen/etc.) + WTPKT someTools; // extra info available from only some tools + + bool ownsCursor(UINT x) + { return (x - cursorBase) < cursorCount; } + }; + class GHOST_TabletManagerWin32 { // the Wintab library @@ -78,6 +107,8 @@ class GHOST_TabletManagerWin32 std::map contexts; HCTX contextForWindow(GHOST_WindowWin32*); + std::vector tablets; + GHOST_WindowWin32* activeWindow; TabletTool activeTool; BYTE sysButtonMap[32]; // user's custom button assignments for active tool -- cgit v1.2.3 From a7f2cbc88f4e55fb3ed7b5ba54383d38acea089b Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 14 Dec 2010 22:43:52 +0000 Subject: As-yet uncommitted changes from end of summer. General code cleanup Mac-side, removed some unnecessary NSAutoreleasePool guards, etc. By no means complete -- just wanted to get this in and do a fresh checkout on another machine. --- intern/ghost/GHOST_ISystem.h | 2 +- intern/ghost/intern/GHOST_Buttons.cpp | 47 ++- intern/ghost/intern/GHOST_SystemCocoa.h | 276 ++++++++-------- intern/ghost/intern/GHOST_SystemCocoa.mm | 94 +----- intern/ghost/intern/GHOST_WindowCocoa.h | 171 +++++----- intern/ghost/intern/GHOST_WindowCocoa.mm | 523 ++++++++++++++----------------- 6 files changed, 499 insertions(+), 614 deletions(-) diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index b759b98f0bc..c0a9defaaae 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -27,7 +27,7 @@ */ /** * @file GHOST_ISystem.h - * Main interface file for C++ Api with declaration of GHOST_ISystem interface + * Main interface file for C++ API with declaration of GHOST_ISystem interface * class. * Contains the doxygen documentation main page. */ diff --git a/intern/ghost/intern/GHOST_Buttons.cpp b/intern/ghost/intern/GHOST_Buttons.cpp index 5a1f5dea430..87b0813648b 100644 --- a/intern/ghost/intern/GHOST_Buttons.cpp +++ b/intern/ghost/intern/GHOST_Buttons.cpp @@ -29,7 +29,6 @@ #include "GHOST_Buttons.h" - GHOST_Buttons::GHOST_Buttons() { clear(); @@ -39,37 +38,37 @@ GHOST_Buttons::~GHOST_Buttons() {} bool GHOST_Buttons::get(GHOST_TButtonMask mask) const { - switch (mask) { - case GHOST_kButtonMaskLeft: - return m_ButtonLeft; - case GHOST_kButtonMaskMiddle: - return m_ButtonMiddle; - case GHOST_kButtonMaskRight: - return m_ButtonRight; - default: - return false; - } + switch (mask) { + case GHOST_kButtonMaskLeft: + return m_ButtonLeft; + case GHOST_kButtonMaskMiddle: + return m_ButtonMiddle; + case GHOST_kButtonMaskRight: + return m_ButtonRight; + default: + return false; + } } void GHOST_Buttons::set(GHOST_TButtonMask mask, bool down) { - switch (mask) { - case GHOST_kButtonMaskLeft: - m_ButtonLeft = down; break; - case GHOST_kButtonMaskMiddle: - m_ButtonMiddle = down; break; - case GHOST_kButtonMaskRight: - m_ButtonRight = down; break; - default: - break; - } + switch (mask) { + case GHOST_kButtonMaskLeft: + m_ButtonLeft = down; break; + case GHOST_kButtonMaskMiddle: + m_ButtonMiddle = down; break; + case GHOST_kButtonMaskRight: + m_ButtonRight = down; break; + default: + break; + } } void GHOST_Buttons::clear() { - m_ButtonLeft = false; - m_ButtonMiddle = false; - m_ButtonRight = false; + m_ButtonLeft = false; + m_ButtonMiddle = false; + m_ButtonRight = false; } bool GHOST_Buttons::anyDown() const diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index c84c69707ad..de835ad7768 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -21,13 +21,14 @@ * * The Original Code is: all of this file. * - * Contributor(s): Maarten Gribnau 05/2001 - * Damien Plisson 09/2009 + * Contributor(s): Maarten Gribnau 05/2001 + * Damien Plisson 09/2009 * * ***** END GPL LICENSE BLOCK ***** */ + /** - * @file GHOST_SystemCocoa.h + * @file GHOST_SystemCocoa.h * Declaration of GHOST_SystemCocoa class. */ @@ -44,20 +45,20 @@ class GHOST_EventCursor; class GHOST_EventKey; class GHOST_EventWindow; class GHOST_WindowCocoa; - +class NSAutoreleasePool; // actually Obj-C, but GHOST_ISystem.cpp doesn't understand @class syntax class GHOST_SystemCocoa : public GHOST_System { public: - /** - * Constructor. - */ - GHOST_SystemCocoa(); - - /** - * Destructor. - */ - ~GHOST_SystemCocoa(); - + /** + * Constructor. + */ + GHOST_SystemCocoa(); + + /** + * Destructor. + */ + ~GHOST_SystemCocoa(); + /*************************************************************************************** ** Time(r) functionality ***************************************************************************************/ @@ -68,7 +69,7 @@ public: * Based on ANSI clock() routine. * @return The number of milliseconds. */ - virtual GHOST_TUns64 getMilliSeconds() const; + GHOST_TUns64 getMilliSeconds() const; /*************************************************************************************** ** Display/window management functionality @@ -78,31 +79,30 @@ public: * Returns the number of displays on this system. * @return The number of displays. */ - virtual GHOST_TUns8 getNumDisplays() const; + GHOST_TUns8 getNumDisplays() const; /** * Returns the dimensions of the main display on this system. - * @return The dimension of the main display. */ - virtual void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const; - + void getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const; + /** * Create a new window. - * The new window is added to the list of windows managed. + * The new window is added to the list of windows managed. * Never explicitly delete the window, use disposeWindow() instead. - * @param title The name of the window (displayed in the title bar of the window if the OS supports it). - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state of the window when opened. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. - * @param numOfAASamples Number of samples used for AA (zero if no AA) - * @param parentWindow Parent (embedder) window - * @return The new window (or 0 if creation failed). + * @param title The name of the window (displayed in the title bar of the window if the OS supports it). + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state of the window when opened. + * @param type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + * @param numOfAASamples Number of samples used for AA (zero if no AA) + * @param parentWindow Parent (embedder) window + * @return The new window (or 0 if creation failed). */ - virtual GHOST_IWindow* createWindow( + GHOST_IWindow* createWindow( const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, @@ -114,166 +114,166 @@ public: const GHOST_TUns16 numOfAASamples = 0, const GHOST_TEmbedderWindowID parentWindow = 0 ); - - virtual GHOST_TSuccess beginFullScreen( + + GHOST_TSuccess beginFullScreen( const GHOST_DisplaySetting& setting, GHOST_IWindow** window, const bool stereoVisual ); - - virtual GHOST_TSuccess endFullScreen( void ); - + + GHOST_TSuccess endFullScreen( void ); + /*************************************************************************************** ** Event management functionality ***************************************************************************************/ /** * Gets events from the system and stores them in the queue. - * @param waitForEvent Flag to wait for an event (or return immediately). - * @return Indication of the presence of events. + * @param waitForEvent Flag to wait for an event (or return immediately). + * @return Indication of the presence of events. */ - virtual bool processEvents(bool waitForEvent); - + bool processEvents(bool waitForEvent); + /** * Handle User request to quit, from Menu bar Quit, and Cmd+Q * Display alert panel if changes performed since last save */ GHOST_TUns8 handleQuitRequest(); - + /** * Handle Cocoa openFile event * Display confirmation request panel if changes performed since last save */ - bool handleOpenDocumentRequest(void *filepathStr); - + bool handleOpenDocumentRequest(void *filepathStr); + /** - * Handles a drag'n'drop destination event. Called by GHOST_WindowCocoa window subclass - * @param eventType The type of drag'n'drop event - * @param draggedObjectType The type object concerned (currently array of file names, string, TIFF image) - * @param mouseX x mouse coordinate (in cocoa base window coordinates) - * @param mouseY y mouse coordinate - * @param window The window on which the event occurred - * @return Indication whether the event was handled. - */ + * Handles a drag'n'drop destination event. Called by GHOST_WindowCocoa window subclass + * @param eventType The type of drag'n'drop event + * @param draggedObjectType The type object concerned (currently array of file names, string, TIFF image) + * @param mouseX x mouse coordinate (in cocoa base window coordinates) + * @param mouseY y mouse coordinate + * @param window The window on which the event occurred + * @return Indication whether the event was handled. + */ GHOST_TSuccess handleDraggingEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType, - GHOST_WindowCocoa* window, int mouseX, int mouseY, void* data); - + GHOST_WindowCocoa* window, int mouseX, int mouseY, void* data); + /*************************************************************************************** ** Cursor management functionality ***************************************************************************************/ /** * Returns the current location of the cursor (location in screen coordinates) - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. */ - virtual GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const; + GHOST_TSuccess getCursorPosition(GHOST_TInt32& x, GHOST_TInt32& y) const; /** * Updates the location of the cursor (location in screen coordinates). - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. */ - virtual GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); - + GHOST_TSuccess setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y); + /*************************************************************************************** ** Access to mouse button and keyboard states. ***************************************************************************************/ /** * Returns the state of all modifier keys. - * @param keys The state of all modifier keys (true == pressed). - * @return Indication of success. + * @param keys The state of all modifier keys (true == pressed). + * @return Indication of success. */ - virtual GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const; + GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const; /** * Returns the state of the mouse buttons (ouside the message queue). - * @param buttons The state of the buttons. - * @return Indication of success. + * @param buttons The state of the buttons. + * @return Indication of success. */ - virtual GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const; + GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const; /** * Returns Clipboard data - * @param selection Indicate which buffer to return - * @return Returns the selected buffer + * @param selection Indicate which buffer to return + * @return Returns the selected buffer */ - virtual GHOST_TUns8* getClipboard(bool selection) const; - + GHOST_TUns8* getClipboard(bool selection) const; + /** * Puts buffer to system clipboard - * @param buffer The buffer to be copied - * @param selection Indicates which buffer to copy too, only used on X11 + * @param buffer The buffer to be copied + * @param selection Indicates which buffer to copy too, only used on X11 */ - virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const; + void putClipboard(GHOST_TInt8 *buffer, bool selection) const; /** * Determine the base dir in which shared resources are located. It will first try to use * "unpack and run" path, then look for properly installed path, not including versioning. * @return Unsigned char string pointing to system dir (eg /usr/share/blender/). */ - virtual const GHOST_TUns8* getSystemDir() const; + const GHOST_TUns8* getSystemDir() const; /** * Determine the base dir in which user configuration is stored, not including versioning. * If needed, it will create the base directory. * @return Unsigned char string pointing to user dir (eg ~/.blender/). */ - virtual const GHOST_TUns8* getUserDir() const; + const GHOST_TUns8* getUserDir() const; /** - * Determine the directory of the current binary - * @return Unsigned char string pointing to the binary dir - */ - virtual const GHOST_TUns8* getBinaryDir() const; + * Determine the directory of the current binary + * @return Unsigned char string pointing to the binary dir + */ + const GHOST_TUns8* getBinaryDir() const; /** - * Handles a window event. Called by GHOST_WindowCocoa window delegate - * @param eventType The type of window event - * @param window The window on which the event occurred - * @return Indication whether the event was handled. - */ - GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window); + * Handles a window event. Called by GHOST_WindowCocoa window delegate + * @param eventType The type of window event + * @param window The window on which the event occurred + * @return Indication whether the event was handled. + */ + GHOST_TSuccess handleWindowEvent(GHOST_TEventType eventType, GHOST_WindowCocoa* window); /** - * Handles the Cocoa event telling the application has become active (again) - * @return Indication whether the event was handled. - */ - GHOST_TSuccess handleApplicationBecomeActiveEvent(); + * Handles the Cocoa event telling the application has become active (again) + * @return Indication whether the event was handled. + */ + GHOST_TSuccess handleApplicationBecomeActiveEvent(); /** - * External objects should call this when they send an event outside processEvents. - */ + * External objects should call this when they send an event outside processEvents. + */ void notifyExternalEventProcessed(); protected: /** * Initializes the system. * For now, it justs registers the window class (WNDCLASS). - * @return A success value. + * @return A success value. + */ + GHOST_TSuccess init(); + + /** + * Handles a tablet pen event. + * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * @return Indication whether the event was handled. + */ + GHOST_TSuccess handleTabletEvent(void *eventPtr); + + /** + * Helps handleTabletEvent function. */ - virtual GHOST_TSuccess init(); - - /** - * Handles a tablet pen event. - * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) - * @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. - * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) - * @return Indication whether the event was handled. - */ + * Handles a tablet proximity event. Sets pen or mouse ID for later events. + * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * @return Indication whether the event was handled. + */ GHOST_TSuccess handleTabletProximity(void *eventPtr); /** Tablet Mouse and Pen IDs, used to correlate events with the tool that caused them. */ @@ -286,24 +286,24 @@ protected: GHOST_TTabletMode m_tablet_pen_mode; /** - * Handles a mouse event. - * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) - * @return Indication whether the event was handled. - */ - GHOST_TSuccess handleMouseEvent(void *eventPtr); - - /** - * Handles a key event. - * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) - * @return Indication whether the event was handled. - */ - GHOST_TSuccess handleKeyEvent(void *eventPtr); - + * Handles a mouse event. + * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * @return Indication whether the event was handled. + */ + GHOST_TSuccess handleMouseEvent(void *eventPtr); + + /** + * Handles a key event. + * @param eventPtr An NSEvent pointer (casted to void* to enable compilation in standard C++) + * @return Indication whether the event was handled. + */ + GHOST_TSuccess handleKeyEvent(void *eventPtr); + /** * Performs the actual cursor position update (location in screen coordinates). - * @param x The x-coordinate of the cursor. - * @param y The y-coordinate of the cursor. - * @return Indication of success. + * @param x The x-coordinate of the cursor. + * @param y The y-coordinate of the cursor. + * @return Indication of success. */ GHOST_TSuccess setMouseCursorPosition(float x, float y); @@ -313,29 +313,31 @@ protected: /** Event has been processed directly by Cocoa (or NDOF manager) and has sent a ghost event to be dispatched */ bool m_outsideLoopEventProcessed; - + /** Raised window is not yet known by the window manager, so delay application become active event handling */ bool m_needDelayedApplicationBecomeActiveEventProcessing; - + /** Mouse buttons state */ GHOST_TUns32 m_pressedMouseButtons; - - /** State of the modifiers. */ - GHOST_TUns32 m_modifierMask; - /** Ignores window size messages (when window is dragged). */ - bool m_ignoreWindowSizedMessages; - + /** State of the modifiers. */ + GHOST_TUns32 m_modifierMask; + + /** Ignores window size messages (when window is dragged). */ + bool m_ignoreWindowSizedMessages; + /** Stores the mouse cursor delta due to setting a new cursor position * Needed because cocoa event delta cursor move takes setCursorPosition changes too. */ GHOST_TInt32 m_cursorDelta_x, m_cursorDelta_y; - + /** Multitouch trackpad availability */ bool m_hasMultiTouchTrackpad; - + /** Multitouch gesture in progress, useful to distinguish trackpad from mouse scroll events */ bool m_isGestureInProgress; + + NSAutoreleasePool* m_pool; }; #endif // _GHOST_SYSTEM_COCOA_H_ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index b0c7f10f329..2075058b32e 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -466,19 +466,12 @@ extern "C" { struct bContext; struct wmOperator; extern int fromcocoa_request_qtcodec_settings(bContext *C, wmOperator *op); - - -int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op) -{ - int result; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - result = fromcocoa_request_qtcodec_settings(C, op); - - [pool drain]; - return result; -} -}; + + int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op) + { + return fromcocoa_request_qtcodec_settings(C, op); + } +} // "C" #endif @@ -541,6 +534,8 @@ int cocoa_request_qtcodec_settings(bContext *C, wmOperator *op) GHOST_SystemCocoa::GHOST_SystemCocoa() { + m_pool = [[NSAutoreleasePool alloc] init]; + int mib[2]; struct timeval boottime; size_t len; @@ -556,7 +551,7 @@ GHOST_SystemCocoa::GHOST_SystemCocoa() m_tablet_pen_mode = GHOST_kTabletModeNone; m_outsideLoopEventProcessed = false; m_needDelayedApplicationBecomeActiveEventProcessing = false; - m_displayManager = new GHOST_DisplayManagerCocoa (); + m_displayManager = new GHOST_DisplayManagerCocoa; GHOST_ASSERT(m_displayManager, "GHOST_SystemCocoa::GHOST_SystemCocoa(): m_displayManager==0\n"); m_displayManager->initialize(); @@ -602,7 +597,6 @@ GHOST_TSuccess GHOST_SystemCocoa::init() m_ndofManager = new GHOST_NDOFManagerCocoa(*this); - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; if (NSApp == nil) { [NSApplication sharedApplication]; @@ -666,8 +660,6 @@ GHOST_TSuccess GHOST_SystemCocoa::init() } [NSApp finishLaunching]; - - [pool drain]; } return success; } @@ -696,18 +688,12 @@ GHOST_TUns8 GHOST_SystemCocoa::getNumDisplays() const { //Note that OS X supports monitor hot plug // We do not support multiple monitors at the moment - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - GHOST_TUns8 count = [[NSScreen screens] count]; - - [pool drain]; - return count; + return [[NSScreen screens] count]; } void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns32& height) const { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; //Get visible frame, that is frame excluding dock and top menu bar NSRect frame = [[NSScreen mainScreen] visibleFrame]; @@ -717,8 +703,6 @@ void GHOST_SystemCocoa::getMainDisplayDimensions(GHOST_TUns32& width, GHOST_TUns width = contentRect.size.width; height = contentRect.size.height; - - [pool drain]; } @@ -735,7 +719,6 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( const GHOST_TEmbedderWindowID parentWindow ) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; GHOST_IWindow* window = 0; //Get the available rect for including window contents @@ -768,7 +751,6 @@ GHOST_IWindow* GHOST_SystemCocoa::createWindow( else { GHOST_PRINT("GHOST_SystemCocoa::createWindow(): could not create window\n"); } - [pool drain]; return window; } @@ -789,8 +771,6 @@ GHOST_TSuccess GHOST_SystemCocoa::endFullScreen(void) return currentWindow->setState(GHOST_kWindowStateNormal); } - - /** * @note : returns coordinates in Cocoa screen coordinates @@ -835,7 +815,7 @@ GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(float xf, float yf) GHOST_WindowCocoa* window = (GHOST_WindowCocoa*)m_windowManager->getActiveWindow(); if (!window) return GHOST_kFailure; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSScreen *windowScreen = window->getScreen(); NSRect screenRect = [windowScreen frame]; @@ -848,7 +828,7 @@ GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(float xf, float yf) CGDisplayMoveCursorToPoint((CGDirectDisplayID)[[[windowScreen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue], CGPointMake(xf, yf)); - [pool drain]; +// [pool drain]; return GHOST_kSuccess; } @@ -995,8 +975,6 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) } } while (event != nil); - [pool drain]; - if (m_needDelayedApplicationBecomeActiveEventProcessing) handleApplicationBecomeActiveEvent(); @@ -1005,6 +983,9 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent) return true; } + [pool drain]; // for this event processing thread + [m_pool drain]; // for main thread + return anyProcessed; } @@ -1404,9 +1385,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) return GHOST_kFailure; } -// don't involve the window! -// GHOST_TabletData& ct = window->GetCocoaTabletData(); - GHOST_TTabletMode active_tool; int* tool_id_ptr; @@ -1438,11 +1416,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) 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 } else { @@ -1450,11 +1423,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletProximity(void *eventPtr) *tool_id_ptr = TOOL_ID_NONE; m_tablet_pen_mode = GHOST_kTabletModeNone; - -// ct.Active = GHOST_kTabletModeNone; -// ct.Pressure = 0; -// ct.Xtilt = 0; -// ct.Ytilt = 0; } return GHOST_kSuccess; @@ -1485,16 +1453,6 @@ 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: @@ -1814,12 +1772,9 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const GHOST_TUns8 * temp_buff; size_t pastedTextSize; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; if (pasteBoard == nil) { - [pool drain]; return NULL; } @@ -1830,14 +1785,12 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const availableTypeFromArray:supportedTypes]; if (bestType == nil) { - [pool drain]; return NULL; } NSString * textPasted = [pasteBoard stringForType:NSStringPboardType]; if (textPasted == nil) { - [pool drain]; return NULL; } @@ -1846,7 +1799,6 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const temp_buff = (GHOST_TUns8*) malloc(pastedTextSize+1); if (temp_buff == NULL) { - [pool drain]; return NULL; } @@ -1854,8 +1806,6 @@ GHOST_TUns8* GHOST_SystemCocoa::getClipboard(bool selection) const temp_buff[pastedTextSize] = '\0'; - [pool drain]; - if(temp_buff) { return temp_buff; } else { @@ -1869,12 +1819,9 @@ void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const if(selection) {return;} // for copying the selection, used on X11 - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; if (pasteBoard == nil) { - [pool drain]; return; } @@ -1885,8 +1832,6 @@ void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const textToCopy = [NSString stringWithCString:buffer encoding:NSISOLatin1StringEncoding]; [pasteBoard setString:textToCopy forType:NSStringPboardType]; - - [pool drain]; } #pragma mark Base directories retrieval @@ -1894,7 +1839,6 @@ void GHOST_SystemCocoa::putClipboard(GHOST_TInt8 *buffer, bool selection) const const GHOST_TUns8* GHOST_SystemCocoa::getSystemDir() const { static GHOST_TUns8 tempPath[512] = ""; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *basePath; NSArray *paths; @@ -1903,20 +1847,17 @@ const GHOST_TUns8* GHOST_SystemCocoa::getSystemDir() const if ([paths count] > 0) basePath = [paths objectAtIndex:0]; else { - [pool drain]; return NULL; } strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]); - [pool drain]; return tempPath; } const GHOST_TUns8* GHOST_SystemCocoa::getUserDir() const { static GHOST_TUns8 tempPath[512] = ""; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *basePath; NSArray *paths; @@ -1925,31 +1866,26 @@ const GHOST_TUns8* GHOST_SystemCocoa::getUserDir() const if ([paths count] > 0) basePath = [paths objectAtIndex:0]; else { - [pool drain]; return NULL; } strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]); - [pool drain]; return tempPath; } const GHOST_TUns8* GHOST_SystemCocoa::getBinaryDir() const { static GHOST_TUns8 tempPath[512] = ""; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *basePath; basePath = [[NSBundle mainBundle] bundlePath]; if (basePath == nil) { - [pool drain]; return NULL; } strcpy((char*)tempPath, [basePath cStringUsingEncoding:NSASCIIStringEncoding]); - [pool drain]; return tempPath; } diff --git a/intern/ghost/intern/GHOST_WindowCocoa.h b/intern/ghost/intern/GHOST_WindowCocoa.h index c8285547e99..82955e2ce63 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.h +++ b/intern/ghost/intern/GHOST_WindowCocoa.h @@ -25,6 +25,7 @@ * * ***** END GPL LICENSE BLOCK ***** */ + /** * @file GHOST_WindowCocoa.h * Declaration of GHOST_WindowCocoa class. @@ -34,13 +35,14 @@ #define _GHOST_WINDOW_COCOA_H_ #ifndef __APPLE__ -#error Apple OSX only! -#endif // __APPLE__ + #error Apple OSX only! +#endif #include "GHOST_Window.h" #include "STR_String.h" @class CocoaWindow; +@class NSAutoreleasePool; class GHOST_SystemCocoa; @@ -52,8 +54,8 @@ class GHOST_SystemCocoa; * which is called the gutter. * When OpenGL contexts are active, GHOST will use AGL_BUFFER_RECT to prevent * OpenGL drawing outside the reduced client rectangle. - * @author Maarten Gribnau - * @date May 23, 2001 + * @author Maarten Gribnau + * @date May 23, 2001 */ class GHOST_WindowCocoa : public GHOST_Window { public: @@ -61,16 +63,16 @@ public: * Constructor. * Creates a new window and opens it. * To check if the window was created properly, use the getValid() method. - * @param systemCocoa The associated system class to forward events to - * @param title The text shown in the title bar of the window. - * @param left The coordinate of the left edge of the window. - * @param top The coordinate of the top edge of the window. - * @param width The width the window. - * @param height The height the window. - * @param state The state the window is initially opened with. - * @param type The type of drawing context installed in this window. - * @param stereoVisual Stereo visual for quad buffered stereo. - * @param numOfAASamples Number of samples used for AA (zero if no AA) + * @param systemCocoa The associated system class to forward events to + * @param title The text shown in the title bar of the window. + * @param left The coordinate of the left edge of the window. + * @param top The coordinate of the top edge of the window. + * @param width The width the window. + * @param height The height the window. + * @param state The state the window is initially opened with. + * @param type The type of drawing context installed in this window. + * @param stereoVisual Stereo visual for quad buffered stereo. + * @param numOfAASamples Number of samples used for AA (zero if no AA) */ GHOST_WindowCocoa( GHOST_SystemCocoa *systemCocoa, @@ -89,121 +91,121 @@ public: * Destructor. * Closes the window and disposes resources allocated. */ - virtual ~GHOST_WindowCocoa(); + ~GHOST_WindowCocoa(); /** * Returns indication as to whether the window is valid. * @return The validity of the window. */ - virtual bool getValid() const; + bool getValid() const; /** * Returns the associated NSWindow object * @return The associated NSWindow object */ - virtual void* getOSWindow() const; + void* getOSWindow() const; /** * Sets the title displayed in the title bar. * @param title The title to display in the title bar. */ - virtual void setTitle(const STR_String& title); + void setTitle(const STR_String& title); /** * Returns the title displayed in the title bar. * @param title The title displayed in the title bar. */ - virtual void getTitle(STR_String& title) const; + void getTitle(STR_String& title) const; /** * Returns the window rectangle dimensions. * The dimensions are given in screen coordinates that are relative to the upper-left corner of the screen. * @param bounds The bounding rectangle of the window. */ - virtual void getWindowBounds(GHOST_Rect& bounds) const; - + void getWindowBounds(GHOST_Rect& bounds) const; + /** * Returns the client rectangle dimensions. * The left and top members of the rectangle are always zero. * @param bounds The bounding rectangle of the cleient area of the window. */ - virtual void getClientBounds(GHOST_Rect& bounds) const; + void getClientBounds(GHOST_Rect& bounds) const; /** * Resizes client rectangle width. * @param width The new width of the client area of the window. */ - virtual GHOST_TSuccess setClientWidth(GHOST_TUns32 width); + GHOST_TSuccess setClientWidth(GHOST_TUns32 width); /** * Resizes client rectangle height. * @param height The new height of the client area of the window. */ - virtual GHOST_TSuccess setClientHeight(GHOST_TUns32 height); + GHOST_TSuccess setClientHeight(GHOST_TUns32 height); /** * Resizes client rectangle. - * @param width The new width of the client area of the window. - * @param height The new height of the client area of the window. + * @param width The new width of the client area of the window. + * @param height The new height of the client area of the window. */ - virtual GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); + GHOST_TSuccess setClientSize(GHOST_TUns32 width, GHOST_TUns32 height); /** * Returns the state of the window (normal, minimized, maximized). * @return The state of the window. */ - virtual GHOST_TWindowState getState() const; + GHOST_TWindowState getState() const; /** * Sets the window "modified" status, indicating unsaved changes * @param isUnsavedChanges Unsaved changes or not * @return Indication of success. */ - virtual GHOST_TSuccess setModifiedState(bool isUnsavedChanges); - + GHOST_TSuccess setModifiedState(bool isUnsavedChanges); + /** * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate on the screen. - * @param inY The y-coordinate on the screen. - * @param outX The x-coordinate in the client rectangle. - * @param outY The y-coordinate in the client rectangle. + * @param inX The x-coordinate on the screen. + * @param inY The y-coordinate on the screen. + * @param outX The x-coordinate in the client rectangle. + * @param outY The y-coordinate in the client rectangle. */ - virtual void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; + void screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; /** * Converts a point in screen coordinates to client rectangle coordinates - * @param inX The x-coordinate in the client rectangle. - * @param inY The y-coordinate in the client rectangle. - * @param outX The x-coordinate on the screen. - * @param outY The y-coordinate on the screen. + * @param inX The x-coordinate in the client rectangle. + * @param inY The y-coordinate in the client rectangle. + * @param outX The x-coordinate on the screen. + * @param outY The y-coordinate on the screen. */ - virtual void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; + void clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const; /** * Gets the screen the window is displayed in * @return The NSScreen object */ NSScreen* getScreen(); - + /** * Sets the state of the window (normal, minimized, maximized). - * @param state The state of the window. - * @return Indication of success. + * @param state The state of the window. + * @return Indication of success. */ - virtual GHOST_TSuccess setState(GHOST_TWindowState state); + GHOST_TSuccess setState(GHOST_TWindowState state); /** * Sets the order of the window (bottom, top). - * @param order The order of the window. - * @return Indication of success. + * @param order The order of the window. + * @return Indication of success. */ - virtual GHOST_TSuccess setOrder(GHOST_TWindowOrder order); + GHOST_TSuccess setOrder(GHOST_TWindowOrder order); /** * Swaps front and back buffers of a window. - * @return A boolean success indicator. + * @return A boolean success indicator. */ - virtual GHOST_TSuccess swapBuffers(); + GHOST_TSuccess swapBuffers(); /** * Updates the drawing context of this window. Needed @@ -216,87 +218,84 @@ public: * Activates the drawing context of this window. * @return A boolean success indicator. */ - virtual GHOST_TSuccess activateDrawingContext(); + GHOST_TSuccess activateDrawingContext(); - virtual void loadCursor(bool visible, GHOST_TStandardCursor cursor) const; - - - const GHOST_TabletData* GetTabletData() - { return NULL; } + void loadCursor(bool visible, GHOST_TStandardCursor cursor) const; /** * Sets the progress bar value displayed in the window/application icon - * @param progress The progress % (0.0 to 1.0) + * @param progress The progress % (0.0 to 1.0) */ - virtual GHOST_TSuccess setProgressBar(float progress); - + GHOST_TSuccess setProgressBar(float progress); + /** * Hides the progress bar icon */ - virtual GHOST_TSuccess endProgressBar(); + GHOST_TSuccess endProgressBar(); + protected: /** * Tries to install a rendering context in this window. - * @param type The type of rendering context installed. - * @return Indication as to whether installation has succeeded. + * @param type The type of rendering context installed. + * @return Indication as to whether installation has succeeded. */ - virtual GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type); + GHOST_TSuccess installDrawingContext(GHOST_TDrawingContextType type); /** * Removes the current drawing context. - * @return Indication as to whether removal has succeeded. + * @return Indication as to whether removal has succeeded. */ - virtual GHOST_TSuccess removeDrawingContext(); + GHOST_TSuccess removeDrawingContext(); /** * Invalidates the contents of this window. - * @return Indication of success. + * @return Indication of success. */ - virtual GHOST_TSuccess invalidate(); + GHOST_TSuccess invalidate(); /** * Sets the cursor visibility on the window using * native window system calls. */ - virtual GHOST_TSuccess setWindowCursorVisibility(bool visible); - + GHOST_TSuccess setWindowCursorVisibility(bool visible); + /** * Sets the cursor grab on the window using * native window system calls. */ - virtual GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode); - + GHOST_TSuccess setWindowCursorGrab(GHOST_TGrabCursorMode mode); + /** * Sets the cursor shape on the window using * native window system calls. */ - virtual GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape); + GHOST_TSuccess setWindowCursorShape(GHOST_TStandardCursor shape); /** * Sets the cursor shape on the window using * native window system calls. */ - virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, - int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color); - - virtual GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY); + GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, + int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color); + + GHOST_TSuccess setWindowCustomCursorShape(GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY); - /** The window containing the OpenGL view */ - CocoaWindow *m_window; - - /** The openGL view */ + /** The window containing the OpenGL view */ + CocoaWindow *m_window; + + /** The OpenGL view */ NSOpenGLView *m_openGLView; - /** The opgnGL drawing context */ + /** The OpenGL drawing context */ NSOpenGLContext *m_openGLContext; - - /** The mother SystemCocoa class to send events */ - GHOST_SystemCocoa *m_systemCocoa; - + /** The first created OpenGL context (for sharing display lists) */ static NSOpenGLContext *s_firstOpenGLcontext; - - NSCursor* m_customCursor; + + /** The mother SystemCocoa class to send events */ + GHOST_SystemCocoa *m_ghostSystem; + + NSCursor* m_customCursor; }; #endif // _GHOST_WINDOW_COCOA_H_ diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index c7ec3b398c8..aea59de51cd 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -21,8 +21,8 @@ * * The Original Code is: all of this file. * - * Contributor(s): Maarten Gribnau 05/2001 - Damien Plisson 10/2009 + * Contributor(s): Maarten Gribnau 05/2001 + Damien Plisson 10/2009 * * ***** END GPL LICENSE BLOCK ***** */ @@ -30,15 +30,11 @@ #include #ifndef MAC_OS_X_VERSION_10_6 -//Use of the SetSystemUIMode function (64bit compatible) -#include + //Use of the SetSystemUIMode function (64bit compatible) + #include #endif #include -/***** Multithreaded opengl code : uncomment for enabling -#include -*/ - #include "GHOST_WindowCocoa.h" #include "GHOST_SystemCocoa.h" @@ -56,17 +52,18 @@ extern "C" { extern void wm_event_do_handlers(bContext *C); extern void wm_event_do_notifiers(bContext *C); extern void wm_draw_update(bContext *C); -};*/ +}*/ + @interface CocoaWindowDelegate : NSObject #ifdef MAC_OS_X_VERSION_10_6 - + #endif { - GHOST_SystemCocoa *systemCocoa; - GHOST_WindowCocoa *associatedWindow; + GHOST_SystemCocoa *ghostSystem; + GHOST_WindowCocoa *ghostWindow; } -- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa; +- (void)setSystem:(GHOST_SystemCocoa *)sysCocoa ghostWindow:(GHOST_WindowCocoa *)winCocoa; - (void)windowWillClose:(NSNotification *)notification; - (void)windowDidBecomeKey:(NSNotification *)notification; - (void)windowDidResignKey:(NSNotification *)notification; @@ -77,40 +74,40 @@ extern "C" { @end @implementation CocoaWindowDelegate : NSObject -- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa +- (void)setSystem:(GHOST_SystemCocoa *)sys ghostWindow:(GHOST_WindowCocoa *)win { - systemCocoa = sysCocoa; - associatedWindow = winCocoa; + ghostSystem = sys; + ghostWindow = win; } - (void)windowWillClose:(NSNotification *)notification { - systemCocoa->handleWindowEvent(GHOST_kEventWindowClose, associatedWindow); + ghostSystem->handleWindowEvent(GHOST_kEventWindowClose, ghostWindow); } - (void)windowDidBecomeKey:(NSNotification *)notification { - systemCocoa->handleWindowEvent(GHOST_kEventWindowActivate, associatedWindow); + ghostSystem->handleWindowEvent(GHOST_kEventWindowActivate, ghostWindow); } - (void)windowDidResignKey:(NSNotification *)notification { - systemCocoa->handleWindowEvent(GHOST_kEventWindowDeactivate, associatedWindow); + ghostSystem->handleWindowEvent(GHOST_kEventWindowDeactivate, ghostWindow); } - (void)windowDidExpose:(NSNotification *)notification { - systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, associatedWindow); + ghostSystem->handleWindowEvent(GHOST_kEventWindowUpdate, ghostWindow); } - (void)windowDidMove:(NSNotification *)notification { - systemCocoa->handleWindowEvent(GHOST_kEventWindowMove, associatedWindow); + ghostSystem->handleWindowEvent(GHOST_kEventWindowMove, ghostWindow); } - (void)windowWillMove:(NSNotification *)notification { - systemCocoa->handleWindowEvent(GHOST_kEventWindowMove, associatedWindow); + ghostSystem->handleWindowEvent(GHOST_kEventWindowMove, ghostWindow); } - (void)windowDidResize:(NSNotification *)notification @@ -119,13 +116,13 @@ extern "C" { //if (![[notification object] inLiveResize]) { //Send event only once, at end of resize operation (when user has released mouse button) #endif - systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, associatedWindow); + ghostSystem->handleWindowEvent(GHOST_kEventWindowSize, ghostWindow); #ifdef MAC_OS_X_VERSION_10_6 //} #endif /* Live resize ugly patch. Needed because live resize runs in a modal loop, not letting main loop run - if ([[notification object] inLiveResize]) { - systemCocoa->dispatchEvents(); + if ([[notification object] inLiveResize]) { + ghostSystem->dispatchEvents(); wm_window_timer(ghostC); wm_event_do_handlers(ghostC); wm_event_do_notifiers(ghostC); @@ -138,17 +135,17 @@ extern "C" { //We need to subclass it to tell that even borderless (fullscreen), it can become key (receive user events) @interface CocoaWindow: NSWindow { - GHOST_SystemCocoa *systemCocoa; - GHOST_WindowCocoa *associatedWindow; + GHOST_SystemCocoa *ghostSystem; + GHOST_WindowCocoa *ghostWindow; GHOST_TDragnDropTypes m_draggedObjectType; } -- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa; +- (void)setSystem:(GHOST_SystemCocoa *)sys ghostWindow:(GHOST_WindowCocoa *)win; @end @implementation CocoaWindow -- (void)setSystemAndWindowCocoa:(GHOST_SystemCocoa *)sysCocoa windowCocoa:(GHOST_WindowCocoa *)winCocoa +- (void)setSystem:(GHOST_SystemCocoa *)sys ghostWindow:(GHOST_WindowCocoa *)win { - systemCocoa = sysCocoa; - associatedWindow = winCocoa; + ghostSystem = sys; + ghostWindow = win; } -(BOOL)canBecomeKeyWindow @@ -162,13 +159,18 @@ 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; + 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; + + ghostWindow->setAcceptDragOperation(TRUE); //Drag operation is accepted by default + ghostSystem->handleDraggingEvent(GHOST_kEventDraggingEntered, m_draggedObjectType, ghostWindow, mouseLocation.x, mouseLocation.y, nil); - associatedWindow->setAcceptDragOperation(TRUE); //Drag operation is accepted by default - systemCocoa->handleDraggingEvent(GHOST_kEventDraggingEntered, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil); return NSDragOperationCopy; } @@ -181,22 +183,19 @@ extern "C" { { NSPoint mouseLocation = [sender draggingLocation]; - systemCocoa->handleDraggingEvent(GHOST_kEventDraggingUpdated, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, nil); - return associatedWindow->canAcceptDragOperation()?NSDragOperationCopy:NSDragOperationNone; + ghostSystem->handleDraggingEvent(GHOST_kEventDraggingUpdated, m_draggedObjectType, ghostWindow, mouseLocation.x, mouseLocation.y, nil); + return ghostWindow->canAcceptDragOperation()?NSDragOperationCopy:NSDragOperationNone; } - (void)draggingExited:(id < NSDraggingInfo >)sender { - systemCocoa->handleDraggingEvent(GHOST_kEventDraggingExited, m_draggedObjectType, associatedWindow, 0, 0, nil); + ghostSystem->handleDraggingEvent(GHOST_kEventDraggingExited, m_draggedObjectType, ghostWindow, 0, 0, nil); m_draggedObjectType = GHOST_kDragnDropTypeUnknown; } - (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender { - if (associatedWindow->canAcceptDragOperation()) - return YES; - else - return NO; + return ghostWindow->canAcceptDragOperation(); } - (BOOL)performDragOperation:(id < NSDraggingInfo >)sender @@ -224,7 +223,7 @@ extern "C" { return NO; break; } - systemCocoa->handleDraggingEvent(GHOST_kEventDraggingDropDone, m_draggedObjectType, associatedWindow, mouseLocation.x, mouseLocation.y, (void*)data); + ghostSystem->handleDraggingEvent(GHOST_kEventDraggingDropDone, m_draggedObjectType, ghostWindow, mouseLocation.x, mouseLocation.y, (void*)data); return YES; } @@ -234,11 +233,11 @@ extern "C" { #pragma mark NSOpenGLView subclass //We need to subclass it in order to give Cocoa the feeling key events are trapped -@interface CocoaOpenGLView : NSOpenGLView +@interface BlenderGLView : NSOpenGLView { } @end -@implementation CocoaOpenGLView +@implementation BlenderGLView - (BOOL)acceptsFirstResponder { @@ -288,7 +287,7 @@ extern "C" { NSOpenGLContext* GHOST_WindowCocoa::s_firstOpenGLcontext = nil; GHOST_WindowCocoa::GHOST_WindowCocoa( - GHOST_SystemCocoa *systemCocoa, + GHOST_SystemCocoa *ghostSystem, const STR_String& title, GHOST_TInt32 left, GHOST_TInt32 top, @@ -297,48 +296,43 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( GHOST_TWindowState state, GHOST_TDrawingContextType type, const bool stereoVisual, const GHOST_TUns16 numOfAASamples -) : - GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual, numOfAASamples), - m_customCursor(0) + ) + : GHOST_Window(title, left, top, width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual, numOfAASamples) + , m_ghostSystem(ghostSystem) + , m_customCursor(0) { - NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[40]; - NSOpenGLPixelFormat *pixelFormat = nil; - int i; +// m_pool = [[NSAutoreleasePool alloc] init]; - m_systemCocoa = systemCocoa; m_fullScreen = false; + NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[20]; + NSOpenGLPixelFormat *pixelFormat = nil; + 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; + NSRect rect = NSMakeRect(left,top,width,height); m_window = [[CocoaWindow alloc] initWithContentRect:rect - styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask - backing:NSBackingStoreBuffered defer:NO]; + styleMask:NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask + backing:NSBackingStoreBuffered defer:NO]; if (m_window == nil) { [pool drain]; return; } - [m_window setSystemAndWindowCocoa:systemCocoa windowCocoa:this]; + [m_window setSystemAndWindowCocoa:ghostSystem windowCocoa:this]; - //Forbid to resize the window below the blender defined minimum one - minSize.width = 320; - minSize.height = 240; - [m_window setContentMinSize:minSize]; + // Forbid to resize the window below the blender defined minimum one + [m_window setContentMinSize:NSMakeSize(320,240)]; - setTitle(title); + // simplify drawing since each window contains only our OpenGL view + [m_window useOptimizedDrawing:YES]; + setTitle(title); // Pixel Format Attributes for the windowed NSOpenGLContext - i=0; + int i = 0; pixelFormatAttrsWindow[i++] = NSOpenGLPFADoubleBuffer; // Guarantees the back buffer contents to be valid after a call to NSOpenGLContext object’s flushBuffer @@ -346,14 +340,14 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( 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; + int firstMultiSampleAttribute = i; + if (numOfAASamples>0) { // Multisample anti-aliasing pixelFormatAttrsWindow[i++] = NSOpenGLPFAMultisample; @@ -374,25 +368,8 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( //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; - + pixelFormatAttrsWindow[firstMultiSampleAttribute] = (NSOpenGLPixelFormatAttribute) 0; pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttrsWindow]; - } if (numOfAASamples>0) { //Set m_numOfAASamples to the actual value @@ -405,8 +382,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( } //Creates the OpenGL View inside the window - m_openGLView = [[CocoaOpenGLView alloc] initWithFrame:rect - pixelFormat:pixelFormat]; + m_openGLView = [[BlenderGLView alloc] initWithFrame:rect pixelFormat:pixelFormat]; [pixelFormat release]; @@ -424,13 +400,13 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( activateDrawingContext(); CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init]; - [windowDelegate setSystemAndWindowCocoa:systemCocoa windowCocoa:this]; + [windowDelegate setSystemAndWindowCocoa:ghostSystem windowCocoa:this]; [m_window setDelegate:windowDelegate]; [m_window setAcceptsMouseMovedEvents:YES]; - [m_window registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, - NSStringPboardType, NSTIFFPboardType, nil]]; + [m_window registerForDraggedTypes:[NSArray arrayWithObjects: + NSFilenamesPboardType, NSStringPboardType, NSTIFFPboardType, nil]]; if (state == GHOST_kWindowStateFullScreen) setState(GHOST_kWindowStateFullScreen); @@ -443,7 +419,7 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa() { if (m_customCursor) delete m_customCursor; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLView release]; if (m_window) { @@ -458,7 +434,8 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa() if ([windowsList count]) { [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil]; } - [pool drain]; + +// [pool drain]; } #pragma mark accessors @@ -479,21 +456,18 @@ void GHOST_WindowCocoa::setTitle(const STR_String& title) NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *windowTitle = [[NSString alloc] initWithUTF8String:title]; - + //Set associated file if applicable if ([windowTitle hasPrefix:@"Blender"]) { NSRange fileStrRange; - NSString *associatedFileName; - int len; - + fileStrRange.location = [windowTitle rangeOfString:@"["].location+1; - len = [windowTitle rangeOfString:@"]"].location - fileStrRange.location; - - if (len >0) - { + int len = [windowTitle rangeOfString:@"]"].location - fileStrRange.location; + + if (len >0) { fileStrRange.length = len; - associatedFileName = [windowTitle substringWithRange:fileStrRange]; + NSString* associatedFileName = [windowTitle substringWithRange:fileStrRange]; @try { [m_window setRepresentedFilename:associatedFileName]; } @@ -506,13 +480,11 @@ void GHOST_WindowCocoa::setTitle(const STR_String& title) [m_window setTitle:windowTitle]; [m_window setRepresentedFilename:@""]; } - } else { [m_window setTitle:windowTitle]; [m_window setRepresentedFilename:@""]; } - [windowTitle release]; [pool drain]; } @@ -520,16 +492,20 @@ void GHOST_WindowCocoa::setTitle(const STR_String& title) void GHOST_WindowCocoa::getTitle(STR_String& title) const { - GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid") + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getTitle(): window invalid") NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +/* NSString *windowTitle = [m_window title]; if (windowTitle != nil) { title = [windowTitle UTF8String]; } - +*/ + + title = [[m_window title] UTF8String]; + [pool drain]; } @@ -539,8 +515,6 @@ void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const NSRect rect; GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getWindowBounds(): window invalid") - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSRect screenSize = [[m_window screen] visibleFrame]; rect = [m_window frame]; @@ -549,28 +523,23 @@ void GHOST_WindowCocoa::getWindowBounds(GHOST_Rect& bounds) const bounds.m_l = rect.origin.x -screenSize.origin.x; bounds.m_r = rect.origin.x-screenSize.origin.x + rect.size.width; bounds.m_t = screenSize.size.height - (rect.origin.y + rect.size.height -screenSize.origin.y); - - [pool drain]; } void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const { - NSRect rect; GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::getClientBounds(): window invalid") - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + if (!m_fullScreen) { NSRect screenSize = [[m_window screen] visibleFrame]; //Max window contents as screen size (excluding title bar...) NSRect contentRect = [CocoaWindow contentRectForFrameRect:screenSize - styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)]; + styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)]; + + NSRect rect = [m_window contentRectForFrameRect:[m_window frame]]; - rect = [m_window contentRectForFrameRect:[m_window frame]]; - bounds.m_b = contentRect.size.height - (rect.origin.y -contentRect.origin.y); bounds.m_l = rect.origin.x -contentRect.origin.x; bounds.m_r = rect.origin.x-contentRect.origin.x + rect.size.width; @@ -578,20 +547,19 @@ void GHOST_WindowCocoa::getClientBounds(GHOST_Rect& bounds) const } else { NSRect screenSize = [[m_window screen] frame]; - + bounds.m_b = screenSize.origin.y + screenSize.size.height; bounds.m_l = screenSize.origin.x; bounds.m_r = screenSize.origin.x + screenSize.size.width; bounds.m_t = screenSize.origin.y; } - [pool drain]; } GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientWidth(): window invalid") - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); if (((GHOST_TUns32)cBnds.getWidth()) != width) { @@ -600,7 +568,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width) size.height=cBnds.getHeight(); [m_window setContentSize:size]; } - [pool drain]; + return GHOST_kSuccess; } @@ -608,7 +576,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientWidth(GHOST_TUns32 width) GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientHeight(): window invalid") - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); if (((GHOST_TUns32)cBnds.getHeight()) != height) { @@ -617,7 +585,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height) size.height=height; [m_window setContentSize:size]; } - [pool drain]; + return GHOST_kSuccess; } @@ -625,7 +593,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientHeight(GHOST_TUns32 height) GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 height) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setClientSize(): window invalid") - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + GHOST_Rect cBnds, wBnds; getClientBounds(cBnds); if ((((GHOST_TUns32)cBnds.getWidth()) != width) || @@ -635,7 +603,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setClientSize(GHOST_TUns32 width, GHOST_TUns32 size.height=height; [m_window setContentSize:size]; } - [pool drain]; + return GHOST_kSuccess; } @@ -665,15 +633,11 @@ GHOST_TWindowState GHOST_WindowCocoa::getState() const void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::screenToClient(): window invalid") - - NSPoint screenCoord; - NSPoint baseCoord; - - screenCoord.x = inX; - screenCoord.y = inY; - - baseCoord = [m_window convertScreenToBase:screenCoord]; - + + NSPoint screenCoord = {inX, inY}; + + NSPoint baseCoord = [m_window convertScreenToBase:screenCoord]; + outX = baseCoord.x; outY = baseCoord.y; } @@ -682,15 +646,11 @@ void GHOST_WindowCocoa::screenToClient(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST void GHOST_WindowCocoa::clientToScreen(GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY) const { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::clientToScreen(): window invalid") - - NSPoint screenCoord; - NSPoint baseCoord; - - baseCoord.x = inX; - baseCoord.y = inY; - - screenCoord = [m_window convertBaseToScreen:baseCoord]; - + + NSPoint baseCoord = {inX, inY}; + + NSPoint screenCoord = [m_window convertBaseToScreen:baseCoord]; + outX = screenCoord.x; outY = screenCoord.y; } @@ -710,19 +670,18 @@ NSScreen* GHOST_WindowCocoa::getScreen() GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setState(): window invalid") - switch (state) { + switch (state) { case GHOST_kWindowStateMinimized: - [m_window miniaturize:nil]; - break; + [m_window miniaturize:nil]; + break; case GHOST_kWindowStateMaximized: [m_window zoom:nil]; break; - case GHOST_kWindowStateFullScreen: if (!m_fullScreen) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + //This status change needs to be done before Cocoa call to enter fullscreen mode //to give window delegate hint not to forward its deactivation to ghost wm that doesn't know view/window difference m_fullScreen = true; @@ -759,10 +718,10 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) [tmpWindow setReleasedWhenClosed:NO]; [tmpWindow setAcceptsMouseMovedEvents:YES]; [tmpWindow setDelegate:[m_window delegate]]; - + //Assign the openGL view to the new window [tmpWindow setContentView:m_openGLView]; - + //Show the new window [tmpWindow makeKeyAndOrderFront:nil]; //Close and release old window @@ -771,10 +730,9 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) [m_window release]; m_window = tmpWindow; #endif - //Tell WM of view new size - m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, this); - + m_ghostSystem->handleWindowEvent(GHOST_kEventWindowSize, this); + [pool drain]; } break; @@ -807,20 +765,20 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) } //Create a fullscreen borderless window CocoaWindow *tmpWindow = [[CocoaWindow alloc] - initWithContentRect:[[m_window screen] frame] - styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask) - backing:NSBackingStoreBuffered - defer:YES]; + initWithContentRect:[[m_window screen] frame] + styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask) + backing:NSBackingStoreBuffered + defer:YES]; //Copy current window parameters [tmpWindow setTitle:[m_window title]]; [tmpWindow setRepresentedFilename:[m_window representedFilename]]; [tmpWindow setReleasedWhenClosed:NO]; [tmpWindow setAcceptsMouseMovedEvents:YES]; [tmpWindow setDelegate:[m_window delegate]]; - + //Assign the openGL view to the new window [tmpWindow setContentView:m_openGLView]; - + //Show the new window [tmpWindow makeKeyAndOrderFront:nil]; //Close and release old window @@ -829,53 +787,51 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state) [m_window release]; m_window = tmpWindow; #endif - //Tell WM of view new size - m_systemCocoa->handleWindowEvent(GHOST_kEventWindowSize, this); - + m_ghostSystem->handleWindowEvent(GHOST_kEventWindowSize, this); + [pool drain]; } - else if ([m_window isMiniaturized]) + else if ([m_window isMiniaturized]) [m_window deminiaturize:nil]; else if ([m_window isZoomed]) [m_window zoom:nil]; - break; - } - return GHOST_kSuccess; + break; + } + return GHOST_kSuccess; } GHOST_TSuccess GHOST_WindowCocoa::setModifiedState(bool isUnsavedChanges) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + [m_window setDocumentEdited:isUnsavedChanges]; - + [pool drain]; + return GHOST_Window::setModifiedState(isUnsavedChanges); } GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::setOrder(): window invalid") - if (order == GHOST_kWindowOrderTop) { + if (order == GHOST_kWindowOrderTop) { [m_window makeKeyAndOrderFront:nil]; - } - else { - NSArray *windowsList; - + } + else { [m_window orderBack:nil]; - + //Check for other blender opened windows and make the frontmost key - windowsList = [NSApp orderedWindows]; + NSArray* windowsList = [NSApp orderedWindows]; if ([windowsList count]) { [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil]; } - } - + } + [pool drain]; - return GHOST_kSuccess; + return GHOST_kSuccess; } #pragma mark Drawing context @@ -884,15 +840,19 @@ GHOST_TSuccess GHOST_WindowCocoa::setOrder(GHOST_TWindowOrder order) GHOST_TSuccess GHOST_WindowCocoa::swapBuffers() { - if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { - if (m_openGLContext != nil) { + GHOST_TSuccess success = GHOST_kFailure; + + if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { + if (m_openGLContext != nil) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLContext flushBuffer]; [pool drain]; - return GHOST_kSuccess; - } - } - return GHOST_kFailure; + success = GHOST_kSuccess; + } + } + +// [m_pool drain]; // needed to put this in a function that is called regularly + return success; } GHOST_TSuccess GHOST_WindowCocoa::updateDrawingContext() @@ -912,12 +872,12 @@ GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext() { if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { if (m_openGLContext != nil) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLContext makeCurrentContext]; - + // Disable AA by default if (m_numOfAASamples > 0) glDisable(GL_MULTISAMPLE_ARB); - [pool drain]; +// [pool drain]; return GHOST_kSuccess; } } @@ -928,35 +888,34 @@ GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext() GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextType type) { GHOST_TSuccess success = GHOST_kFailure; - - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + +// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSOpenGLPixelFormat *pixelFormat; NSOpenGLContext *tmpOpenGLContext; - + /***** Multithreaded opengl code : uncomment for enabling CGLContextObj cglCtx; */ - + switch (type) { case GHOST_kDrawingContextTypeOpenGL: if (!getValid()) break; - + pixelFormat = [m_openGLView pixelFormat]; tmpOpenGLContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat - shareContext:s_firstOpenGLcontext]; + shareContext:s_firstOpenGLcontext]; if (tmpOpenGLContext == nil) { success = GHOST_kFailure; break; } - + //Switch openGL to multhreaded mode - /******* Multithreaded opengl code : uncomment for enabling + /******* Multithreaded opengl code : uncomment for enabling */ cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj]; if (CGLEnable(cglCtx, kCGLCEMPEngine) == kCGLNoError) printf("\nSwitched openGL to multithreaded mode"); - */ - + if (!s_firstOpenGLcontext) s_firstOpenGLcontext = tmpOpenGLContext; #ifdef WAIT_FOR_VSYNC { @@ -967,25 +926,25 @@ GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextTyp #endif [m_openGLView setOpenGLContext:tmpOpenGLContext]; [tmpOpenGLContext setView:m_openGLView]; - + m_openGLContext = tmpOpenGLContext; break; - + case GHOST_kDrawingContextTypeNone: success = GHOST_kSuccess; break; - + default: break; } - [pool drain]; +// [pool drain]; return success; } GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext() { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; switch (m_drawingContextType) { case GHOST_kDrawingContextTypeOpenGL: if (m_openGLContext) @@ -994,14 +953,14 @@ GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext() if (s_firstOpenGLcontext == m_openGLContext) s_firstOpenGLcontext = nil; m_openGLContext = nil; } - [pool drain]; +// [pool drain]; return GHOST_kSuccess; case GHOST_kDrawingContextTypeNone: - [pool drain]; +// [pool drain]; return GHOST_kSuccess; break; default: - [pool drain]; +// [pool drain]; return GHOST_kFailure; } } @@ -1010,9 +969,9 @@ GHOST_TSuccess GHOST_WindowCocoa::removeDrawingContext() GHOST_TSuccess GHOST_WindowCocoa::invalidate() { GHOST_ASSERT(getValid(), "GHOST_WindowCocoa::invalidate(): window invalid") - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; +// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLView setNeedsDisplay:YES]; - [pool drain]; +// [pool drain]; return GHOST_kSuccess; } @@ -1021,36 +980,36 @@ GHOST_TSuccess GHOST_WindowCocoa::invalidate() GHOST_TSuccess GHOST_WindowCocoa::setProgressBar(float progress) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + if ((progress >=0.0) && (progress <=1.0)) { NSImage* dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128,128)]; - + [dockIcon lockFocus]; - NSRect progressBox = {{4, 4}, {120, 16}}; - - [[NSImage imageNamed:@"NSApplicationIcon"] dissolveToPoint:NSZeroPoint fraction:1.0]; - - // Track & Outline - [[NSColor blackColor] setFill]; - NSRectFill(progressBox); - - [[NSColor whiteColor] set]; - NSFrameRect(progressBox); - - // Progress fill - progressBox = NSInsetRect(progressBox, 1, 1); - [[NSColor knobColor] setFill]; - progressBox.size.width = progressBox.size.width * progress; + NSRect progressBox = {{4, 4}, {120, 16}}; + + [[NSImage imageNamed:@"NSApplicationIcon"] dissolveToPoint:NSZeroPoint fraction:1.0]; + + // Track & Outline + [[NSColor blackColor] setFill]; NSRectFill(progressBox); - + + [[NSColor whiteColor] set]; + NSFrameRect(progressBox); + + // Progress fill + progressBox = NSInsetRect(progressBox, 1, 1); + [[NSColor knobColor] setFill]; + progressBox.size.width = progressBox.size.width * progress; + NSRectFill(progressBox); + [dockIcon unlockFocus]; - + [NSApp setApplicationIconImage:dockIcon]; [dockIcon release]; - + m_progressBarVisible = true; } - + [pool drain]; return GHOST_kSuccess; } @@ -1060,16 +1019,16 @@ GHOST_TSuccess GHOST_WindowCocoa::endProgressBar() { if (!m_progressBarVisible) return GHOST_kFailure; m_progressBarVisible = false; - + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + NSImage* dockIcon = [[NSImage alloc] initWithSize:NSMakeSize(128,128)]; [dockIcon lockFocus]; [[NSImage imageNamed:@"NSApplicationIcon"] dissolveToPoint:NSZeroPoint fraction:1.0]; [dockIcon unlockFocus]; [NSApp setApplicationIconImage:dockIcon]; [dockIcon release]; - + [pool drain]; return GHOST_kSuccess; } @@ -1081,9 +1040,9 @@ GHOST_TSuccess GHOST_WindowCocoa::endProgressBar() void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) const { static bool systemCursorVisible = true; - + NSCursor *tmpCursor =nil; - + if (visible != systemCursorVisible) { if (visible) { [NSCursor unhide]; @@ -1126,6 +1085,7 @@ void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) c case GHOST_kStandardCursorRightSide: tmpCursor = [NSCursor resizeRightCursor]; break; +#if 0 // illustrative code -- no need to compile case GHOST_kStandardCursorRightArrow: case GHOST_kStandardCursorInfo: case GHOST_kStandardCursorLeftArrow: @@ -1139,10 +1099,11 @@ void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) c case GHOST_kStandardCursorBottomLeftCorner: case GHOST_kStandardCursorCopy: case GHOST_kStandardCursorDefault: +#endif default: tmpCursor = [NSCursor arrowCursor]; break; - }; + } } [tmpCursor set]; } @@ -1151,13 +1112,10 @@ void GHOST_WindowCocoa::loadCursor(bool visible, GHOST_TStandardCursor cursor) c GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; - if ([m_window isVisible]) { loadCursor(visible, getCursorShape()); } - - [pool drain]; + return GHOST_kSuccess; } @@ -1165,30 +1123,27 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible) GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode) { GHOST_TSuccess err = GHOST_kSuccess; - + if (mode != GHOST_kGrabDisable) { //No need to perform grab without warp as it is always on in OS X if(mode != GHOST_kGrabNormal) { GHOST_TInt32 x_old,y_old; - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - m_systemCocoa->getCursorPosition(x_old,y_old); + m_ghostSystem->getCursorPosition(x_old,y_old); screenToClient(x_old, y_old, m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]); //Warp position is stored in client (window base) coordinates setCursorGrabAccum(0, 0); - + if(mode == GHOST_kGrabHide) { setWindowCursorVisibility(false); } - + //Make window key if it wasn't to get the mouse move events [m_window makeKeyWindow]; - + //Dissociate cursor position even for warp mode, to allow mouse acceleration to work even when warping the cursor err = CGAssociateMouseAndMouseCursorPosition(false) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure; - - [pool drain]; } } else { @@ -1197,7 +1152,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode //No need to set again cursor position, as it has not changed for Cocoa setWindowCursorVisibility(true); } - + err = CGAssociateMouseAndMouseCursorPosition(true) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure; /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */ setCursorGrabAccum(0, 0); @@ -1205,11 +1160,9 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode } return err; } - + GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - if (m_customCursor) { [m_customCursor release]; m_customCursor = nil; @@ -1218,8 +1171,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor sha if ([m_window isVisible]) { loadCursor(getCursorVisibility(), shape); } - - [pool drain]; + return GHOST_kSuccess; } @@ -1245,7 +1197,7 @@ static GHOST_TUns16 uns16ReverseBits(GHOST_TUns16 shrt) } GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, - int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color) + int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color) { int y,nbUns16; NSPoint hotSpotPoint; @@ -1253,31 +1205,29 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCustomCursorShape(GHOST_TUns8 *bitmap NSImage *cursorImage; NSSize imSize; GHOST_TUns16 *cursorBitmap; - - + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - + if (m_customCursor) { [m_customCursor release]; m_customCursor = nil; } - - - cursorImageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:nil - pixelsWide:sizex - pixelsHigh:sizey - bitsPerSample:1 - samplesPerPixel:2 - hasAlpha:YES - isPlanar:YES - colorSpaceName:NSDeviceWhiteColorSpace - bytesPerRow:(sizex/8 + (sizex%8 >0 ?1:0)) - bitsPerPixel:1]; - - + + cursorImageRep = [[NSBitmapImageRep alloc] + initWithBitmapDataPlanes:nil + pixelsWide:sizex + pixelsHigh:sizey + bitsPerSample:1 + samplesPerPixel:2 + hasAlpha:YES + isPlanar:YES + colorSpaceName:NSDeviceWhiteColorSpace + bytesPerRow:(sizex/8 + (sizex%8 >0 ?1:0)) + bitsPerPixel:1]; + cursorBitmap = (GHOST_TUns16*)[cursorImageRep bitmapData]; nbUns16 = [cursorImageRep bytesPerPlane]/2; - + for (y=0; y Date: Fri, 17 Dec 2010 00:13:23 +0000 Subject: late summer -- overhauled tablet-handling for Windows --- intern/ghost/intern/GHOST_SystemWin32.cpp | 2 +- intern/ghost/intern/GHOST_TabletManagerWin32.cpp | 671 ++++++++++------------- intern/ghost/intern/GHOST_TabletManagerWin32.h | 68 +-- 3 files changed, 326 insertions(+), 415 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 0315fa5870a..cc0e0cb2bec 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -1022,7 +1022,7 @@ bool GHOST_SystemWin32::handleEvent(GHOST_WindowWin32* window, UINT msg, WPARAM { // tablet manager handles all its own cursor moves. // ignore 'regular' mouse while a tablet tool is being used. - DefWindowProc(window->getHWND(), WM_MOUSEMOVE, wParam, lParam); + // DefWindowProc(window->getHWND(), WM_MOUSEMOVE, wParam, lParam); eventHandled = true; break; } diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp index 868b5dcc162..0b2e49fbacc 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.cpp @@ -10,13 +10,29 @@ #include #include -#define PACKETDATA (PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION) -#define PACKETMODE (0 /*PK_BUTTONS*/) -// #define PACKETTILT PKEXT_ABSOLUTE +#define MAX_QUEUE_SIZE 100 -#include "pktdef.h" +static bool wintab_initialized = false; -#define MAX_QUEUE_SIZE 100 +// BEGIN from Wacom's Utils.h +typedef UINT ( API * WTINFOA ) ( UINT, UINT, LPVOID ); +typedef HCTX ( API * WTOPENA ) ( HWND, LPLOGCONTEXTA, BOOL ); +typedef BOOL ( API * WTCLOSE ) ( HCTX ); +typedef BOOL ( API * WTQUEUESIZESET ) ( HCTX, int ); +typedef int ( API * WTPACKETSGET ) ( HCTX, int, LPVOID ); +typedef BOOL ( API * WTPACKET ) ( HCTX, UINT, LPVOID ); +// END + +// the Wintab library +static HMODULE lib_Wintab; + +// WinTab function pointers +static WTOPENA func_Open; +static WTCLOSE func_Close; +static WTINFOA func_Info; +static WTQUEUESIZESET func_QueueSizeSet; +static WTPACKETSGET func_PacketsGet; +static WTPACKET func_Packet; static void print(AXIS const& t, char const* label = NULL) { @@ -54,121 +70,225 @@ static void print(WTPKT packet) } } -GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() - : activeWindow(NULL) +Tablet::Tablet(int tabletID) + : id(tabletID) { - dropTool(); + GHOST_ASSERT(wintab_initialized, "Tablet objects should only be created by TabletManager"); + + // query for overall capabilities and ranges + func_Info(WTI_DEVICES, DVC_NAME, name); + printf("\n-- tablet %d: %s --\n", id, name); + + puts("\nactive tablet area"); + AXIS xRange, yRange; + func_Info(WTI_DEVICES + id, DVC_X, &xRange); + func_Info(WTI_DEVICES + id, DVC_Y, &yRange); + print(xRange,"x"); print(yRange,"y"); + size_x = xRange.axMax; + size_y = yRange.axMax; + + func_Info(WTI_DEVICES + id, DVC_NCSRTYPES, &cursorCount); + func_Info(WTI_DEVICES + id, DVC_FIRSTCSR, &cursorBase); + printf("\nowns tools %d to %d\n", cursorBase, cursorBase + cursorCount - 1); + + func_Info(WTI_DEVICES + id, DVC_PKTDATA, &(allTools)); + puts("\nall tools have"); print(allTools); + func_Info(WTI_DEVICES + id, DVC_CSRDATA, &(someTools)); + puts("some tools also have"); print(someTools); + + puts("\npressure sensitivity"); + AXIS pressureRange; + hasPressure = (allTools|someTools) & PK_NORMAL_PRESSURE + && func_Info(WTI_DEVICES + id, DVC_NPRESSURE, &pressureRange) + && pressureRange.axMax; + + if (hasPressure) + { + print(pressureRange); + pressureScale = 1.f / pressureRange.axMax; + } + else + pressureScale = 0.f; - // open WinTab - lib_Wintab = LoadLibrary("wintab32.dll"); + puts("\ntilt sensitivity"); + AXIS tiltRange[3]; + hasTilt = (allTools|someTools) & PK_ORIENTATION + && func_Info(WTI_DEVICES + id, DVC_ORIENTATION, tiltRange) + && tiltRange[0].axResolution && tiltRange[1].axResolution; - if (lib_Wintab) + if (hasTilt) { - // connect function pointers - func_Open = (WTOPENA) GetProcAddress(lib_Wintab,"WTOpenA"); - func_Close = (WTCLOSE) GetProcAddress(lib_Wintab,"WTClose"); - func_Info = (WTINFOA) GetProcAddress(lib_Wintab,"WTInfoA"); - func_QueueSizeSet = (WTQUEUESIZESET) GetProcAddress(lib_Wintab,"WTQueueSizeSet"); - func_PacketsGet = (WTPACKETSGET) GetProcAddress(lib_Wintab,"WTPacketsGet"); - func_Packet = (WTPACKET) GetProcAddress(lib_Wintab,"WTPacket"); + // leave this code in place to help support tablets I haven't tested + const char* axisName[] = {"azimuth","altitude","twist"}; + for (int i = 0; i < 3; ++i) + print(tiltRange[i], axisName[i]); - puts("\n-- essential tablet info --"); - func_Info(WTI_DEVICES, DVC_NCSRTYPES, &cursorCount); - func_Info(WTI_DEVICES, DVC_FIRSTCSR, &cursorBase); + azimuthScale = 1.f / tiltRange[0].axMax; + altitudeScale = 1.f / tiltRange[1].axMax; + } + else + { + puts("none"); + azimuthScale = altitudeScale = 0.f; + } - func_Info(WTI_DEVICES, DVC_PKTDATA, &allTools); - puts("\nall tools have"); print(allTools); - func_Info(WTI_DEVICES, DVC_CSRDATA, &someTools); - puts("some tools also have"); print(someTools); + for (UINT i = cursorBase; i < cursorBase + cursorCount; ++i) + { + // what can each cursor do? - puts("\npressure sensitivity"); - AXIS pressureRange; - hasPressure = (allTools|someTools) & PK_NORMAL_PRESSURE - && func_Info(WTI_DEVICES, DVC_NPRESSURE, &pressureRange); + UINT physID; + func_Info(WTI_CURSORS + i, CSR_PHYSID, &physID); + if (physID == 0) + // each 'real' cursor has a physical ID + // (on Wacom at least, not tested with other vendors) + continue; - if (hasPressure) - { - print(pressureRange); - pressureScale = 1.f / pressureRange.axMax; - } - else - pressureScale = 0.f; + TCHAR name[40]; + func_Info(WTI_CURSORS + i, CSR_NAME, name); + printf("\ncursor %d: %s\n", i, name); - puts("\ntilt sensitivity"); - AXIS tiltRange[3]; - hasTilt = (allTools|someTools) & PK_ORIENTATION - && func_Info(WTI_DEVICES, DVC_ORIENTATION, &tiltRange); + // always returns 'yes' so don't bother + // BOOL active; + // func_Info(WTI_CURSORS + i, CSR_ACTIVE, &active); + // printf("active: %s\n", active ? "yes" : "no"); - if (hasTilt) - { - // leave this code in place to help support tablets I haven't tested - const char* axisName[] = {"azimuth","altitude","twist"}; - for (int i = 0; i < 3; ++i) - print(tiltRange[i], axisName[i]); - - // cheat by using available data from Intuos4. test on other tablets!!! - azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution); - altitudeScale = 1.f / tiltRange[1].axMax; - } - else + WTPKT packet; + func_Info(WTI_CURSORS + i, CSR_PKTDATA, &packet); + // only report the 'special' bits that distinguish this cursor from the rest + puts("packet support"); print(packet & someTools); + + puts("buttons:"); + BYTE buttons; + BYTE sysButtonMap[32]; + func_Info(WTI_CURSORS + i, CSR_BUTTONS, &buttons); + func_Info(WTI_CURSORS + i, CSR_SYSBTNMAP, sysButtonMap); + for (int i = 0; i < buttons; ++i) + printf(" %d -> %d\n", i, sysButtonMap[i]); + } + } + +bool Tablet::ownsCursor(int cursor) + { + return (cursor - cursorBase) < cursorCount; + } + +TabletTool Tablet::toolForCursor(int cursor) + { + TabletTool tool = {TABLET_NONE,false,false}; + if (ownsCursor(cursor)) + { + // try one way to classify cursor + UINT cursorType = (cursor - cursorBase) % cursorCount; + printf("%d mod %d = %d\n", cursor - cursorBase, cursorCount, cursorType); + switch (cursorType) { - puts("none"); - azimuthScale = altitudeScale = 0.f; + case 0: // older Intuos tablets can track two cursors at once + case 3: // so we test for both here + tool.type = TABLET_MOUSE; + break; + case 1: + case 4: + tool.type = TABLET_PEN; + break; + case 2: + case 5: + tool.type = TABLET_ERASER; + break; + default: + tool.type = TABLET_NONE; } -#if 0 // WTX_TILT -- cartesian tilt extension, no conversion needed - // this isn't working for [mce], so let it rest for now - puts("\nraw tilt sensitivity"); - hasTilt = false; - UINT tag = 0; - UINT extensionCount; - func_Info(WTI_INTERFACE, IFC_NEXTENSIONS, &extensionCount); - for (UINT i = 0; i < extensionCount; ++i) + #if 0 + // now try another way + func_Info(WTI_CURSORS + cursor, CSR_TYPE, &cursorType); + switch (cursorType & 0xf06) { - printf("trying extension %d\n", i); - func_Info(WTI_EXTENSIONS + i, EXT_TAG, &tag); - if (tag == WTX_TILT) - { - hasTilt = true; + case 0x802: + puts("general stylus"); break; - } + case 0x902: + puts("airbrush"); + break; + case 0x804: + puts("art pen"); + break; + case 0x004: + puts("4D mouse"); + break; + case 0x006: + puts("5-button puck"); + break; + default: + puts("???"); } + #endif - if (hasTilt) + WTPKT toolData; + func_Info(WTI_CURSORS + cursor, CSR_PKTDATA, &toolData); + // discard any stray capabilities + // (sometimes cursors claim to be able to do things + // that their tablet doesn't support) + toolData &= (allTools|someTools); + // only report the 'special' bits that distinguish this cursor from the rest + puts("packet support"); print(toolData & someTools); + putchar('\n'); + + if (tool.type == TABLET_MOUSE) { - AXIS tiltRange[2]; - func_Info(WTI_EXTENSIONS + tag, EXT_AXES, tiltRange); - print("x", tiltRange[0]); - print("y", tiltRange[1]); - tiltScaleX = 1.f / tiltRange[0].axMax; - tiltScaleY = 1.f / tiltRange[1].axMax; - func_Info(WTI_EXTENSIONS + tag, EXT_MASK, &tiltMask); + // don't always trust CSR_PKTDATA! + tool.hasPressure = false; + tool.hasTilt = false; } else { - puts("none"); - tiltScaleX = tiltScaleY = 0.f; + tool.hasPressure = toolData & PK_NORMAL_PRESSURE; + tool.hasTilt = toolData & PK_ORIENTATION; } -#endif // WTX_TILT + } + + return tool; + } + +GHOST_TabletManagerWin32::GHOST_TabletManagerWin32() + : activeWindow(NULL) + { + dropTool(); + + // open WinTab + GHOST_ASSERT(!wintab_initialized,"There should be only one TabletManagerWin32 object"); + lib_Wintab = LoadLibrary("wintab32.dll"); + + if (lib_Wintab) + { + // connect function pointers + func_Open = (WTOPENA) GetProcAddress(lib_Wintab,"WTOpenA"); + func_Close = (WTCLOSE) GetProcAddress(lib_Wintab,"WTClose"); + func_Info = (WTINFOA) GetProcAddress(lib_Wintab,"WTInfoA"); + func_QueueSizeSet = (WTQUEUESIZESET) GetProcAddress(lib_Wintab,"WTQueueSizeSet"); + func_PacketsGet = (WTPACKETSGET) GetProcAddress(lib_Wintab,"WTPacketsGet"); + func_Packet = (WTPACKET) GetProcAddress(lib_Wintab,"WTPacket"); + + wintab_initialized = true; - getExtraInfo(); + getHardwareInfo(); } } GHOST_TabletManagerWin32::~GHOST_TabletManagerWin32() { // close WinTab + wintab_initialized = false; FreeLibrary(lib_Wintab); } -void GHOST_TabletManagerWin32::getExtraInfo() +void GHOST_TabletManagerWin32::getHardwareInfo() { - puts("\n-- extra tablet info --"); + puts("\n-- graphics tablet info --"); WORD specV, implV; func_Info(WTI_INTERFACE, IFC_SPECVERSION, &specV); func_Info(WTI_INTERFACE, IFC_IMPLVERSION, &implV); - printf("WinTab version %d.%d (%d.%d)\n", + printf("WinTab version %d.%d (%d.%d)\n\n", HIBYTE(specV), LOBYTE(specV), HIBYTE(implV), LOBYTE(implV)); UINT extensionCount; @@ -183,113 +303,17 @@ void GHOST_TabletManagerWin32::getExtraInfo() UINT deviceCount, cursorCount; func_Info(WTI_INTERFACE, IFC_NDEVICES, &deviceCount); func_Info(WTI_INTERFACE, IFC_NCURSORS, &cursorCount); + printf("\n%d tablets, %d tools\n", deviceCount, cursorCount); - printf("%d tablets, %d tools\n", deviceCount, cursorCount); if (deviceCount > 1) ; // support this? for (UINT i = 0; i < deviceCount; ++i) { - Tablet tablet; - - // query for overall capabilities and ranges - char tabletName[LC_NAMELEN]; - if (func_Info(WTI_DEVICES, DVC_NAME, tabletName)) - printf("tablet %d: %s\n", i, tabletName); - - puts("\nactive tablet area"); - AXIS xRange, yRange; - func_Info(WTI_DEVICES + i, DVC_X, &xRange); - func_Info(WTI_DEVICES + i, DVC_Y, &yRange); - tablet.size_x = xRange.axMax; - tablet.size_y = yRange.axMax; - print(xRange,"x"); print(yRange,"y"); - - func_Info(WTI_DEVICES + i, DVC_NCSRTYPES, &cursorCount); - func_Info(WTI_DEVICES + i, DVC_FIRSTCSR, &cursorBase); - tablet.cursorBase = cursorBase; - tablet.cursorCount = cursorCount; - printf("owns tools %d to %d\n", cursorBase, cursorBase + cursorCount - 1); - - func_Info(WTI_DEVICES + i, DVC_PKTDATA, &allTools); - puts("\nall tools have"); print(allTools); - func_Info(WTI_DEVICES + i, DVC_CSRDATA, &someTools); - puts("some tools also have"); print(someTools); - - puts("\npressure sensitivity"); - AXIS pressureRange; - hasPressure = (allTools|someTools) & PK_NORMAL_PRESSURE - && func_Info(WTI_DEVICES + i, DVC_NPRESSURE, &pressureRange); - - if (hasPressure) - { - print(pressureRange); - pressureScale = 1.f / pressureRange.axMax; - } - else - pressureScale = 0.f; - - puts("\ntilt sensitivity"); - AXIS tiltRange[3]; - hasTilt = (allTools|someTools) & PK_ORIENTATION - && func_Info(WTI_DEVICES + i, DVC_ORIENTATION, &tiltRange); - - if (hasTilt) - { - // leave this code in place to help support tablets I haven't tested - const char* axisName[] = {"azimuth","altitude","twist"}; - for (int i = 0; i < 3; ++i) - print(tiltRange[i], axisName[i]); - - // cheat by using available data from Intuos4. test on other tablets!!! - // azimuthScale = 1.f / HIWORD(tiltRange[1].axResolution); - // altitudeScale = 1.f / tiltRange[1].axMax; - - azimuthScale = 1.f / tiltRange[0].axMax; - altitudeScale = 1.f / tiltRange[1].axMax; - } - else - { - puts("none"); - azimuthScale = altitudeScale = 0.f; - } - + Tablet tablet(i); tablets.push_back(tablet); } - for (UINT i = 0; i < cursorCount; ++i) - { - // what can each cursor do? - - UINT physID; - func_Info(WTI_CURSORS + i, CSR_PHYSID, &physID); - if (physID == 0) - // each 'real' cursor has a physical ID - // (on Intuos at least, test on Graphire also) - continue; - - TCHAR name[40]; - func_Info(WTI_CURSORS + i, CSR_NAME, name); - printf("\ncursor %d: %s\n", i, name); - - BOOL active; - func_Info(WTI_CURSORS + i, CSR_ACTIVE, &active); - printf("active: %s\n", active ? "yes" : "no"); - - WTPKT packet; - func_Info(WTI_CURSORS + i, CSR_PKTDATA, &packet); - // only report the 'special' bits that distinguish this cursor from the rest - puts("packet support"); print(packet & someTools); - - puts("buttons:"); - BYTE buttons; - BYTE sysButtonMap[32]; - func_Info(WTI_CURSORS + i, CSR_BUTTONS, &buttons); - func_Info(WTI_CURSORS + i, CSR_SYSBTNMAP, sysButtonMap); - for (int i = 0; i < buttons; ++i) - printf(" %d -> %d\n", i, sysButtonMap[i]); - } - putchar('\n'); } @@ -314,35 +338,29 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) // this window already has a tablet context return; + int id = 0; // for testing... + // set up context LOGCONTEXT archetype; - func_Info(WTI_DEFSYSCTX, 0, &archetype); +// func_Info(WTI_DEFSYSCTX, 0, &archetype); // func_Info(WTI_DEFCONTEXT, 0, &archetype); -// func_Info(WTI_DSCTXS, 0, &archetype); + func_Info(WTI_DSCTXS + id, 0, &archetype); strcpy(archetype.lcName, "blender special"); - WTPKT packetData = PACKETDATA; - if (!hasPressure) - packetData &= ~PK_NORMAL_PRESSURE; - if (!hasTilt) - packetData &= ~PK_ORIENTATION; - archetype.lcPktData = packetData; - + archetype.lcPktData = PACKETDATA; archetype.lcPktMode = PACKETMODE; + archetype.lcMoveMask = PACKETDATA; + // archetype.lcOptions |= CXO_CSRMESSAGES; // <-- lean mean version archetype.lcOptions |= CXO_SYSTEM | CXO_MESSAGES | CXO_CSRMESSAGES; -#if PACKETMODE & PK_BUTTONS - // we want first 5 buttons - archetype.lcBtnDnMask = 0x1f; - archetype.lcBtnUpMask = 0x1f; -#endif + archetype.lcSysMode = 1; // relative mode (mouse acts like mouse?) // BEGIN derived from Wacom's TILTTEST.C: AXIS TabletX, TabletY; - func_Info(WTI_DEVICES,DVC_X,&TabletX); - func_Info(WTI_DEVICES,DVC_Y,&TabletY); + func_Info(WTI_DEVICES + id,DVC_X,&TabletX); + func_Info(WTI_DEVICES + id,DVC_Y,&TabletY); archetype.lcInOrgX = 0; archetype.lcInOrgY = 0; archetype.lcInExtX = TabletX.axMax; @@ -354,12 +372,6 @@ void GHOST_TabletManagerWin32::openForWindow(GHOST_WindowWin32* window) archetype.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN); // END -/* if (hasTilt) - { - archetype.lcPktData |= tiltMask; - archetype.lcMoveMask |= tiltMask; - } */ - // open the context HCTX context = func_Open(window->getHWND(), &archetype, TRUE); @@ -387,40 +399,74 @@ void GHOST_TabletManagerWin32::closeForWindow(GHOST_WindowWin32* window) } } -void GHOST_TabletManagerWin32::convertTilt(ORIENTATION const& ort, TabletToolData& data) +void Tablet::attachData(PACKET const& packet, TabletToolData& data) { - // this code used to live in GHOST_WindowWin32 - // now it lives here - - float vecLen; - float altRad, azmRad; /* in radians */ - - /* - from the wintab spec: - orAzimuth Specifies the clockwise rotation of the - cursor about the z axis through a full circular range. - - orAltitude Specifies the angle with the x-y plane - through a signed, semicircular range. Positive values - specify an angle upward toward the positive z axis; - negative values specify an angle downward toward the negative z axis. - - wintab.h defines .orAltitude as a UINT but documents .orAltitude - as positive for upward angles and negative for downward angles. - WACOM uses negative altitude values to show that the pen is inverted; - therefore we cast .orAltitude as an (int) and then use the absolute value. - */ - - /* convert raw fixed point data to radians */ - altRad = fabs(ort.orAltitude) * altitudeScale * M_PI/2.0; - azmRad = ort.orAzimuth * azimuthScale * M_PI*2.0; - - /* find length of the stylus' projected vector on the XY plane */ - vecLen = cos(altRad); - - /* from there calculate X and Y components based on azimuth */ - data.tilt_x = sin(azmRad) * vecLen; - data.tilt_y = sin(M_PI/2.0 - azmRad) * vecLen; + if (data.tool.hasPressure) + { + if (packet.pkNormalPressure) + { + data.pressure = pressureScale * packet.pkNormalPressure; + printf(" %d%%", (int)(100 * data.pressure)); + } + else + data.tool.hasPressure = false; + } + + if (data.tool.hasTilt) + { + ORIENTATION const& o = packet.pkOrientation; + if (o.orAzimuth || o.orAltitude) + { + // this code used to live in GHOST_WindowWin32 + // now it lives here + + float vecLen; + float altRad, azmRad; /* in radians */ + + /* + from the wintab spec: + orAzimuth Specifies the clockwise rotation of the + cursor about the z axis through a full circular range. + + orAltitude Specifies the angle with the x-y plane + through a signed, semicircular range. Positive values + specify an angle upward toward the positive z axis; + negative values specify an angle downward toward the negative z axis. + + wintab.h defines .orAltitude as a UINT but documents .orAltitude + as positive for upward angles and negative for downward angles. + WACOM uses negative altitude values to show that the pen is inverted; + therefore we cast .orAltitude as an (int) and then use the absolute value. + */ + + /* convert raw fixed point data to radians */ + altRad = fabs(o.orAltitude) * altitudeScale * M_PI/2.0; + azmRad = o.orAzimuth * azimuthScale * M_PI*2.0; + + /* find length of the stylus' projected vector on the XY plane */ + vecLen = cos(altRad); + + /* from there calculate X and Y components based on azimuth */ + data.tilt_x = sin(azmRad) * vecLen; + data.tilt_y = sin(M_PI/2.0 - azmRad) * vecLen; + + if (fabs(data.tilt_x) < 0.001 && fabs(data.tilt_x) < 0.001) + { + // really should fix the initial test for tool.hasTilt, + // not apply a band-aid here. + data.tool.hasTilt = false; + data.tilt_x = 0.f; + data.tilt_y = 0.f; + } + else + { + // printf(" /%d,%d/", o.orAzimuth, o.orAltitude); + printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); + } + } + else + data.tool.hasTilt = false; + } } bool GHOST_TabletManagerWin32::convertButton(const UINT button, GHOST_TButtonMask& ghost) @@ -466,16 +512,17 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) { PACKET const& packet = packets[i]; TabletToolData data = {activeTool}; + int x = packet.pkX; int y = packet.pkY; if (activeTool.type == TABLET_MOUSE) { // until scaling is working better, use system cursor position instead - POINT systemPos; - GetCursorPos(&systemPos); - x = systemPos.x; - y = systemPos.y; +// POINT systemPos; +// GetCursorPos(&systemPos); +// x = systemPos.x; +// y = systemPos.y; if (x == prevMouseX && y == prevMouseY && packet.pkButtons == prevButtons) // don't send any "mouse hasn't moved" events @@ -509,73 +556,14 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) printf(" (%d,%d)", x, y); - if (activeTool.hasPressure) - { - if (packet.pkNormalPressure) - { - data.pressure = pressureScale * packet.pkNormalPressure; - printf(" %d%%", (int)(100 * data.pressure)); - } - else - data.tool.hasPressure = false; - } - - if (activeTool.hasTilt) - { - ORIENTATION const& o = packet.pkOrientation; - - if (o.orAzimuth || o.orAltitude) - { - convertTilt(o, data); - if (fabs(data.tilt_x) < 0.001 && fabs(data.tilt_x) < 0.001) - { - // really should fix the initial test for activeTool.hasTilt, - // not apply a band-aid here. - data.tool.hasTilt = false; - data.tilt_x = 0.f; - data.tilt_y = 0.f; - } - else - { - // printf(" /%d,%d/", o.orAzimuth, o.orAltitude); - printf(" /%.2f,%.2f/", data.tilt_x, data.tilt_y); - } - } - else - data.tool.hasTilt = false; - // data.tilt_x = tiltScaleX * packet.pkTilt.tiltX; - // data.tilt_y = tiltScaleY * packet.pkTilt.tiltY; - } + activeTablet->attachData(packet, data); // at this point, construct a GHOST event and push it into the queue! GHOST_System* system = (GHOST_System*) GHOST_ISystem::getSystem(); // any buttons changed? - #if PACKETMODE & PK_BUTTONS // relative buttons mode - if (packet.pkButtons) - { - // which button? - GHOST_TButtonMask e_button; - int buttonNumber = LOWORD(packet.pkButtons); - e_button = (GHOST_TButtonMask) buttonNumber; - - // pressed or released? - GHOST_TEventType e_action; - int buttonAction = HIWORD(packet.pkButtons); - if (buttonAction == TBN_DOWN) - e_action = GHOST_kEventButtonDown; - else - e_action = GHOST_kEventButtonUp; - - printf(" button %d %s\n", buttonNumber, buttonAction == TBN_DOWN ? "down" : "up"); - - GHOST_EventButton* e = new GHOST_EventButton(system->getMilliSeconds(), e_action, window, e_button); - - system->pushEvent(e); - } - #else // absolute buttons mode UINT diff = prevButtons ^ packet.pkButtons; if (diff) { @@ -607,7 +595,6 @@ bool GHOST_TabletManagerWin32::processPackets(GHOST_WindowWin32* window) prevButtons = packet.pkButtons; } - #endif else { GHOST_EventCursor* e = new GHOST_EventCursor(system->getMilliSeconds(), GHOST_kEventCursorMove, window, x, y); @@ -643,77 +630,17 @@ void GHOST_TabletManagerWin32::changeTool(GHOST_WindowWin32* window, UINT serial PACKET packet; func_Packet(context, serialNumber, &packet); - // try one way to classify cursor - UINT cursorType = (packet.pkCursor - cursorBase) % cursorCount; - printf("%d mod %d = %d\n", packet.pkCursor - cursorBase, cursorCount, cursorType); - switch (cursorType) - { - case 0: // older Intuos tablets can track two cursors at once - case 3: // so we test for both here - activeTool.type = TABLET_MOUSE; - break; - case 1: - case 4: - activeTool.type = TABLET_PEN; - break; - case 2: - case 5: - activeTool.type = TABLET_ERASER; - break; - default: - activeTool.type = TABLET_NONE; - } - -//#if 0 - // now try another way - func_Info(WTI_CURSORS + packet.pkCursor, CSR_TYPE, &cursorType); - switch (cursorType & 0xf06) - { - case 0x802: - puts("general stylus"); - break; - case 0x902: - puts("airbrush"); - break; - case 0x804: - puts("art pen"); - break; - case 0x004: - puts("4D mouse"); - break; - case 0x006: - puts("5-button puck"); - break; - default: - puts("???"); - } -//#endif - - WTPKT toolData; - func_Info(WTI_CURSORS + packet.pkCursor, CSR_PKTDATA, &toolData); - // discard any stray capabilities - // (sometimes cursors claim to be able to do things - // that their tablet doesn't support) - toolData &= (allTools|someTools); - // only report the 'special' bits that distinguish this cursor from the rest - puts("packet support"); print(toolData & someTools); - putchar('\n'); + for (std::vector::iterator i = tablets.begin(); i != tablets.end(); ++i) + if (i->ownsCursor(packet.pkCursor)) + { + activeTablet = &(*i); + activeTool = i->toolForCursor(packet.pkCursor); - if (activeTool.type == TABLET_MOUSE) - { - // don't always trust CSR_PKTDATA! - activeTool.hasPressure = false; - activeTool.hasTilt = false; - } - else - { - activeTool.hasPressure = toolData & PK_NORMAL_PRESSURE; - activeTool.hasTilt = toolData & PK_ORIENTATION; - // activeTool.hasTilt = toolData & tiltMask; - } + // remember user's custom button assignments for this tool + func_Info(WTI_CURSORS + packet.pkCursor, CSR_SYSBTNMAP, sysButtonMap); - // remember user's custom button assignments for this tool - func_Info(WTI_CURSORS + packet.pkCursor, CSR_SYSBTNMAP, sysButtonMap); + break; + } } } @@ -722,10 +649,10 @@ void GHOST_TabletManagerWin32::dropTool() activeTool.type = TABLET_NONE; activeTool.hasPressure = false; activeTool.hasTilt = false; - + prevMouseX = prevMouseY = 0; prevButtons = 0; - + activeWindow = NULL; } diff --git a/intern/ghost/intern/GHOST_TabletManagerWin32.h b/intern/ghost/intern/GHOST_TabletManagerWin32.h index df6f43d0460..eda2ed9611a 100644 --- a/intern/ghost/intern/GHOST_TabletManagerWin32.h +++ b/intern/ghost/intern/GHOST_TabletManagerWin32.h @@ -7,21 +7,16 @@ #define _WIN32_WINNT 0x501 // require Windows XP or newer #define WIN32_LEAN_AND_MEAN #include -#include "wintab.h" #include #include - #include "GHOST_Types.h" + class GHOST_WindowWin32; -// BEGIN from Wacom's Utils.h -typedef UINT ( API * WTINFOA ) ( UINT, UINT, LPVOID ); -typedef HCTX ( API * WTOPENA ) ( HWND, LPLOGCONTEXTA, BOOL ); -typedef BOOL ( API * WTCLOSE ) ( HCTX ); -typedef BOOL ( API * WTQUEUESIZESET ) ( HCTX, int ); -typedef int ( API * WTPACKETSGET ) ( HCTX, int, LPVOID ); -typedef BOOL ( API * WTPACKET ) ( HCTX, UINT, LPVOID ); -// END +#include "wintab.h" +#define PACKETDATA (PK_CURSOR | PK_X | PK_Y | PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION) +#define PACKETMODE (0) +#include "pktdef.h" // TabletToolData (and its components) are meant to replace GHOST_TabletData // and its customdata analogue in the window manager. For now it's confined to the @@ -49,12 +44,11 @@ typedef struct } TabletToolData; - -// "Tablet" structure is not active by pencils down -// but will be soon. - -struct Tablet +class Tablet { + int id; + TCHAR name[40]; + bool hasPressure; float pressureScale; @@ -70,38 +64,28 @@ struct Tablet WTPKT allTools; // standard info available from any tool (mouse/pen/etc.) WTPKT someTools; // extra info available from only some tools - bool ownsCursor(UINT x) - { return (x - cursorBase) < cursorCount; } +public: + Tablet(int tabletID); + bool ownsCursor(int cursor); + TabletTool toolForCursor(int cursor); + + void attachData(PACKET const&, TabletToolData&); }; class GHOST_TabletManagerWin32 { - // the Wintab library - HMODULE lib_Wintab; - - // WinTab function pointers - WTOPENA func_Open; - WTCLOSE func_Close; - WTINFOA func_Info; - WTQUEUESIZESET func_QueueSizeSet; - WTPACKETSGET func_PacketsGet; - WTPACKET func_Packet; - - void getExtraInfo(); // to help support new/untested tablets + void getHardwareInfo(); // to help support new/untested tablets // tablet attributes - bool hasPressure; - float pressureScale; - bool hasTilt; - float azimuthScale; - float altitudeScale; -// float tiltScaleX; -// float tiltScaleY; -// UINT tiltMask; - UINT cursorCount; - UINT cursorBase; - WTPKT allTools; // standard info available from any tool (mouse/pen/etc.) - WTPKT someTools; // extra info available from only some tools +// bool hasPressure; +// float pressureScale; +// bool hasTilt; +// float azimuthScale; +// float altitudeScale; +// UINT cursorCount; +// UINT cursorBase; +// WTPKT allTools; // standard info available from any tool (mouse/pen/etc.) +// WTPKT someTools; // extra info available from only some tools // book-keeping std::map contexts; @@ -110,6 +94,7 @@ class GHOST_TabletManagerWin32 std::vector tablets; GHOST_WindowWin32* activeWindow; + Tablet* activeTablet; TabletTool activeTool; BYTE sysButtonMap[32]; // user's custom button assignments for active tool @@ -117,7 +102,6 @@ class GHOST_TabletManagerWin32 int prevMouseY; UINT prevButtons; - void convertTilt(ORIENTATION const&, TabletToolData&); bool convertButton(const UINT button, GHOST_TButtonMask&); public: -- cgit v1.2.3 From 50186191d998d6ab51b547d94461c8d0625f3ce0 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 21 Jan 2011 09:56:41 +0000 Subject: enabled multithread GL engine + minor cleanup --- intern/ghost/intern/GHOST_SystemCocoa.h | 6 +++--- intern/ghost/intern/GHOST_WindowCocoa.mm | 37 +++++++++++--------------------- 2 files changed, 16 insertions(+), 27 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h index de835ad7768..09af9387951 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.h +++ b/intern/ghost/intern/GHOST_SystemCocoa.h @@ -53,7 +53,7 @@ public: * Constructor. */ GHOST_SystemCocoa(); - + /** * Destructor. */ @@ -263,7 +263,7 @@ protected: * @return Indication whether the event was handled. */ GHOST_TSuccess handleTabletEvent(void *eventPtr); - + /** * Helps handleTabletEvent function. */ @@ -336,7 +336,7 @@ protected: /** Multitouch gesture in progress, useful to distinguish trackpad from mouse scroll events */ bool m_isGestureInProgress; - + NSAutoreleasePool* m_pool; }; diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index aea59de51cd..5bb85eaf1e7 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -34,7 +34,7 @@ #include #endif -#include +#include // standard OpenGL + Mac CGL #include "GHOST_WindowCocoa.h" #include "GHOST_SystemCocoa.h" @@ -321,7 +321,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( return; } - [m_window setSystemAndWindowCocoa:ghostSystem windowCocoa:this]; + [m_window setSystem:ghostSystem ghostWindow:this]; // Forbid to resize the window below the blender defined minimum one [m_window setContentMinSize:NSMakeSize(320,240)]; @@ -400,7 +400,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( activateDrawingContext(); CocoaWindowDelegate *windowDelegate = [[CocoaWindowDelegate alloc] init]; - [windowDelegate setSystemAndWindowCocoa:ghostSystem windowCocoa:this]; + [windowDelegate setSystem:ghostSystem ghostWindow:this]; [m_window setDelegate:windowDelegate]; [m_window setAcceptsMouseMovedEvents:YES]; @@ -419,7 +419,6 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa() { if (m_customCursor) delete m_customCursor; -// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLView release]; if (m_window) { @@ -434,8 +433,6 @@ GHOST_WindowCocoa::~GHOST_WindowCocoa() if ([windowsList count]) { [[windowsList objectAtIndex:0] makeKeyAndOrderFront:nil]; } - -// [pool drain]; } #pragma mark accessors @@ -851,7 +848,6 @@ GHOST_TSuccess GHOST_WindowCocoa::swapBuffers() } } -// [m_pool drain]; // needed to put this in a function that is called regularly return success; } @@ -872,12 +868,10 @@ GHOST_TSuccess GHOST_WindowCocoa::activateDrawingContext() { if (m_drawingContextType == GHOST_kDrawingContextTypeOpenGL) { if (m_openGLContext != nil) { -// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [m_openGLContext makeCurrentContext]; // Disable AA by default if (m_numOfAASamples > 0) glDisable(GL_MULTISAMPLE_ARB); -// [pool drain]; return GHOST_kSuccess; } } @@ -889,15 +883,9 @@ GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextTyp { GHOST_TSuccess success = GHOST_kFailure; -// NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSOpenGLPixelFormat *pixelFormat; NSOpenGLContext *tmpOpenGLContext; - /***** Multithreaded opengl code : uncomment for enabling - CGLContextObj cglCtx; - */ - switch (type) { case GHOST_kDrawingContextTypeOpenGL: if (!getValid()) break; @@ -910,20 +898,21 @@ GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextTyp break; } - //Switch openGL to multhreaded mode - /******* Multithreaded opengl code : uncomment for enabling */ - cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj]; + /******* Multithreaded OpenGL code : uncomment for enabling */ + CGLContextObj cglCtx = (CGLContextObj)[tmpOpenGLContext CGLContextObj]; if (CGLEnable(cglCtx, kCGLCEMPEngine) == kCGLNoError) - printf("\nSwitched openGL to multithreaded mode"); + printf("\nUsing multithreaded OpenGL engine.\n"); if (!s_firstOpenGLcontext) s_firstOpenGLcontext = tmpOpenGLContext; -#ifdef WAIT_FOR_VSYNC - { + + #ifdef WAIT_FOR_VSYNC + { GLint swapInt = 1; /* wait for vsync, to avoid tearing artifacts */ [tmpOpenGLContext setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; - } -#endif + } + #endif + [m_openGLView setOpenGLContext:tmpOpenGLContext]; [tmpOpenGLContext setView:m_openGLView]; @@ -937,7 +926,7 @@ GHOST_TSuccess GHOST_WindowCocoa::installDrawingContext(GHOST_TDrawingContextTyp default: break; } -// [pool drain]; + return success; } -- cgit v1.2.3 From 162795cffec42cbd3c426c62b7eae2992b93a7cb Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 21 Jan 2011 09:59:58 +0000 Subject: applied SpaceNav patch from Tom Acunzo --- source/blender/editors/space_view3d/view3d_edit.c | 85 +++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 874a2f778f5..2c00d2dcba4 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -833,6 +833,7 @@ float ndof_to_angle_axis(const float ndof[3], float axis[3]) return angular_velocity; } +#if 0 // my version static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) { wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; @@ -877,6 +878,90 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) ED_region_tag_redraw(CTX_wm_region(C)); return OPERATOR_FINISHED; } +#endif + +// Tom's version +static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + + float phi, q1[4]; + float m[3][3]; + float m_inv[3][3]; + float xvec[3] = {1,0,0}; + float yvec[3] = {0,1,0}; + float vec[3]; + float mat[3][3]; + const float rotaSensitivity = 0.007; + const float tranSensitivity = 0.120; + + ARegion *ar= CTX_wm_region(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + View3D *v3d = CTX_wm_view3d(C); + + float dt = ndof->dt; + + if (dt > 0.25f) { + /* this is probably the first event for this motion, so set dt to something reasonable */ + dt = 0.0125f; + } + + /* 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); + + //if(rv3d->persp=!= RV3D_PERSP) //Camera control not supported yet + /* Lock fixed views out of using rotation controls */ + if(rv3d->view!=RV3D_VIEW_FRONT && rv3d->view!=RV3D_VIEW_BACK) + if(rv3d->view!=RV3D_VIEW_TOP && rv3d->view!=RV3D_VIEW_BOTTOM) + if(rv3d->view!=RV3D_VIEW_RIGHT && rv3d->view!=RV3D_VIEW_LEFT) { + // Perform the up/down rotation + phi = (rotaSensitivity+dt) * -ndof->rx; + q1[0] = cos(phi); + mul_v3_v3fl(q1+1, xvec, sin(phi)); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); + + // Perform the left/right rotation + mul_m3_v3(m_inv,yvec); + phi = (rotaSensitivity+dt) * ndof->ry; + q1[0] = cos(phi); + mul_v3_v3fl(q1+1, yvec, sin(phi)); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); + + // Perform the orbital rotation + phi = (rotaSensitivity+dt) * ndof->rz; + q1[0] = cos(phi); + q1[1] = q1[2] = 0.0; + q1[3] = sin(phi); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); + } + + // Perform Pan translation + vec[0]= (tranSensitivity+dt) * ndof->tx; + vec[1]= (tranSensitivity+dt) * ndof->tz; + //vec[2]= 0.0f;//tranSensitivity * ndof->ty; + //window_to_3d_delta(ar, vec, -ndof->tx, -ndof->tz); // experimented a little instead of above + copy_m3_m4(mat, rv3d->viewinv); + mat[2][2] = 0.0f; + mul_m3_v3(mat, vec); + // translate the view + add_v3_v3(rv3d->ofs, vec); + + // Perform Zoom translation + if (ndof->ty!=0.0f){ // TODO - need to add limits to prevent flipping past gridlines + rv3d->dist += (tranSensitivity+dt)* ndof->ty; + // printf("dist %5.3f view %d grid %f\n",rv3d->dist,rv3d->view,v3d->grid); + } + + //printf("Trans tx:%5.2f ty:%5.2f tz:%5.2f \n",ndof->tx, ndof->ty, ndof->tz); + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; +} #if 0 static int viewndof_invoke_1st_try(bContext *C, wmOperator *op, wmEvent *event) -- cgit v1.2.3 From 6132f8c4b49991ad7c60e15bfda6360a95a234aa Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 21 Jan 2011 10:11:26 +0000 Subject: applied Linux SpaceNav patch from Rafael Ortis --- CMakeLists.txt | 7 +++- intern/ghost/intern/GHOST_NDOFManager.h | 2 +- intern/ghost/intern/GHOST_NDOFManagerX11.h | 58 ++++++++++++++++++++++++++++-- intern/ghost/intern/GHOST_SystemX11.cpp | 25 ++++++++----- intern/ghost/intern/GHOST_SystemX11.h | 14 ++++++++ intern/ghost/intern/GHOST_WindowX11.cpp | 20 +++++++++-- 6 files changed, 111 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 87265e959e5..4cc42ba9944 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,6 +118,9 @@ OPTION(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the rayt OPTION(WITH_CXX_GUARDEDALLOC "Enable GuardedAlloc for C++ memory allocation tracking" OFF) OPTION(WITH_INSTALL "Install accompanying scripts and language files needed to run blender" ON) OPTION(WITH_PYTHON_INSTALL "Copy system python into the blender install folder" ON) +IF(UNIX AND NOT APPLE) +OPTION(WITH_SPACENAV "Support for NDOF devices in Linux" ON) +ENDIF(UNIX AND NOT APPLE) IF(APPLE) OPTION(WITH_COCOA "Use Cocoa framework instead of deprecated Carbon" ON) @@ -301,7 +304,9 @@ IF(UNIX AND NOT APPLE) IF(CMAKE_SYSTEM_NAME MATCHES "Linux") # BSD's dont use libdl.so SET(LLIBS "${LLIBS} -ldl") - + IF(WITH_SPACENAV) + SET(LLIBS "${LLIBS} -lspnav") + ENDIF(WITH_SPACENAV) # binreloc is linux only SET(BINRELOC ${CMAKE_SOURCE_DIR}/extern/binreloc) SET(BINRELOC_INC ${BINRELOC}/include) diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 9d0bfa3b789..f4adb4cab1d 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -45,7 +45,7 @@ public: // processes most recent raw data into an NDOFMotion event and sends it // returns whether an event was sent - bool sendMotionEvent(); + virtual bool sendMotionEvent(); protected: GHOST_System& m_system; diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.h b/intern/ghost/intern/GHOST_NDOFManagerX11.h index 8f9c819a481..4c89bfe0ca6 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.h +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.h @@ -24,21 +24,75 @@ #define _GHOST_NDOFMANAGERX11_H_ #include "GHOST_NDOFManager.h" - +#include "GHOST_Types.h" +#include "GHOST_WindowX11.h" +#include "GHOST_EventNDOF.h" +#include +#include class GHOST_NDOFManagerX11 : public GHOST_NDOFManager { +GHOST_WindowX11 * m_ghost_window_x11; + public: GHOST_NDOFManagerX11(GHOST_System& sys) : GHOST_NDOFManager(sys) {} + void setGHOSTWindowX11(GHOST_WindowX11 * w){ + if (m_ghost_window_x11 == NULL) + m_ghost_window_x11 = w; + } + + GHOST_WindowX11 * getGHOSTWindowX11(){ + return m_ghost_window_x11; + } + // whether multi-axis functionality is available (via the OS or driver) // does not imply that a device is plugged in or being used bool available() { // never available since I've not yet written it! - return false; + return true; + } + + virtual bool sendMotionEvent() + { + if (m_atRest) + return false; + + GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, getGHOSTWindowX11()); + GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData(); + + const float scale = 1.f/350.f; // SpaceNavigator sends +/- 350 usually + // 350 according to their developer's guide; others recommend 500 as comfortable + + // possible future enhancement + // scale *= m_sensitivity; + + data->tx = -scale * m_translation[0]; + data->ty = scale * m_translation[1]; + data->tz = scale * m_translation[2]; + + data->rx = scale * m_rotation[0]; + data->ry = scale * m_rotation[1]; + data->rz = scale * m_rotation[2]; + + data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds + + m_prevMotionTime = m_motionTime; + + printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", + data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, data->dt); + + if (!m_system.pushEvent(event)) + return false; + + // 'at rest' test goes at the end so that the first 'rest' event gets sent + m_atRest = m_rotation[0] == 0 && m_rotation[1] == 0 && m_rotation[2] == 0 && + m_translation[0] == 0 && m_translation[1] == 0 && m_translation[2] == 0; + + return true; } }; diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index dc519039af6..b389d25a7fe 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -267,6 +267,7 @@ createWindow( m_windowManager->addWindow(window); pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); + } else { delete window; @@ -631,10 +632,11 @@ GHOST_SystemX11::processEvent(XEvent *xe) ); } else #endif - if (sNdofInfo.currValues) { + if (m_ndofManager->available()) { + // static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0}; - if (xcme.message_type == sNdofInfo.motionAtom) - { + if (xcme.message_type == sNdofInfo.motionAtom + || xcme.message_type == motion_event){ // data.changed = 1; // data.delta = xcme.data.s[8] - data.time; // data.time = xcme.data.s[8]; @@ -646,9 +648,9 @@ GHOST_SystemX11::processEvent(XEvent *xe) // data.rz =-xcme.data.s[7]; short t[3], r[3]; - t[0] = xcme.data.s[2] >> 2; - t[1] = xcme.data.s[3] >> 2; - t[2] = xcme.data.s[4] >> 2; + t[0] = xcme.data.s[2]; + t[1] = xcme.data.s[3]; + t[2] = xcme.data.s[4]; r[0] = xcme.data.s[5]; r[1] = xcme.data.s[6]; r[2] =-xcme.data.s[7]; @@ -663,7 +665,8 @@ GHOST_SystemX11::processEvent(XEvent *xe) // GHOST_kEventNDOFMotion, // window, data); - } else if (xcme.message_type == sNdofInfo.btnPressAtom) { + } else if (xcme.message_type == sNdofInfo.btnPressAtom + || xcme.message_type == button_press_event) { // data.changed = 2; // data.delta = xcme.data.s[8] - data.time; // data.time = xcme.data.s[8]; @@ -803,7 +806,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) XFlush(m_display); break; } - + default: { if(xe->type == window->GetXTablet().MotionEvent) { @@ -1505,3 +1508,9 @@ const GHOST_TUns8* GHOST_SystemX11::getBinaryDir() const return NULL; } +void GHOST_SystemX11::createNDOFAtoms(Display * display){ + motion_event = XInternAtom(display, "MotionEvent", True); + button_press_event = XInternAtom(display, "ButtonPressEvent", True); + button_release_event = XInternAtom(display, "ButtonReleaseEvent", True); + command_event = XInternAtom(display, "CommandEvent", True); +} diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index e4b02d192e8..4479dca5ecd 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -214,6 +214,12 @@ public: unsigned char **txt, unsigned long *len, unsigned int *context) const; + /** + * Create the atoms used by ndof events + * @param display Current display + */ + void createNDOFAtoms(Display * display); + /** * Returns unsinged char from CUT_BUFFER0 * @param selection Get selection, X11 only feature @@ -276,6 +282,14 @@ public: Atom m_incr; Atom m_utf8_string; + /** + * Atoms for NDOF + */ + Atom motion_event; + Atom button_press_event; + Atom button_release_event; + Atom command_event; + private : Display * m_display; diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 60e12ff78df..5ce5a66bfba 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -35,6 +35,10 @@ #include #include +// libspnav +#include +#include "GHOST_NDOFManagerX11.h" + #if defined(__sun__) || defined( __sun ) || defined (__sparc) || defined (__sparc__) || defined (_AIX) #include #endif @@ -269,6 +273,11 @@ GHOST_WindowX11( CWBorderPixel|CWColormap|CWEventMask, &xattributes ); + if (spnav_x11_open(m_display, m_window) == -1) { + fprintf(stderr, "failed to connect to the space navigator daemon\n"); + } else { + m_system->createNDOFAtoms(m_display); + } } else { Window root_return; @@ -297,12 +306,12 @@ GHOST_WindowX11( m_visual->visual, CWBorderPixel|CWColormap|CWEventMask, &xattributes - ); + + ); XSelectInput(m_display , parentWindow, SubstructureNotifyMask); - } - + /* * One of the problem with WM-spec is that can't set a property * to a window that isn't mapped. That is why we can't "just @@ -428,6 +437,8 @@ GHOST_WindowX11( XMapWindow(m_display, m_window); GHOST_PRINT("Mapped window\n"); + + ((GHOST_NDOFManagerX11 *)m_system->getNDOFManager())->setGHOSTWindowX11(this);; XFlush(m_display); } @@ -1258,6 +1269,9 @@ GHOST_WindowX11:: if(m_xtablet.StylusDevice) XCloseDevice(m_display, m_xtablet.StylusDevice); + /*close ndof */ + spnav_close(); + if(m_xtablet.EraserDevice) XCloseDevice(m_display, m_xtablet.EraserDevice); -- cgit v1.2.3 -- cgit v1.2.3 From 30fb5710b68e37f20fb58cfb687d341119ffc5bb Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 10 Jun 2011 01:34:53 +0000 Subject: Made WinXP or later required, SpaceNav (almost) working on Windows --- intern/ghost/intern/GHOST_DisplayManagerWin32.cpp | 5 +- intern/ghost/intern/GHOST_DropTargetWin32.h | 1 - intern/ghost/intern/GHOST_SystemPathsWin32.cpp | 5 - intern/ghost/intern/GHOST_SystemPathsWin32.h | 2 + intern/ghost/intern/GHOST_SystemWin32.cpp | 323 ++++++++++++++-------- intern/ghost/intern/GHOST_SystemWin32.h | 52 ++-- intern/ghost/intern/GHOST_TaskbarWin32.h | 10 +- intern/ghost/intern/GHOST_WindowWin32.h | 14 +- 8 files changed, 259 insertions(+), 153 deletions(-) diff --git a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp index 30d9aa31207..47f748927ab 100644 --- a/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_DisplayManagerWin32.cpp @@ -35,8 +35,11 @@ #include "GHOST_DisplayManagerWin32.h" #include "GHOST_Debug.h" -// We do not support multiple monitors at the moment +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include + +// We do not support multiple monitors at the moment #define COMPILE_MULTIMON_STUBS #ifndef FREE_WINDOWS #include diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.h b/intern/ghost/intern/GHOST_DropTargetWin32.h index 0a553b6701e..980e9f9fe9b 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.h +++ b/intern/ghost/intern/GHOST_DropTargetWin32.h @@ -33,7 +33,6 @@ #ifndef _GHOST_DROP_TARGET_WIN32_H_ #define _GHOST_DROP_TARGET_WIN32_H_ -#include #include #include #include "GHOST_WindowWin32.h" diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp index becccc2c29f..ae376bc37a5 100644 --- a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp @@ -32,12 +32,7 @@ #include "GHOST_SystemPathsWin32.h" -#define WIN32_LEAN_AND_MEAN -#ifdef _WIN32_IE -#undef _WIN32_IE -#endif #define _WIN32_IE 0x0501 -#include #include #if defined(__MINGW32__) || defined(__CYGWIN__) diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.h b/intern/ghost/intern/GHOST_SystemPathsWin32.h index 67cc2140e0e..3de7bbf934e 100644 --- a/intern/ghost/intern/GHOST_SystemPathsWin32.h +++ b/intern/ghost/intern/GHOST_SystemPathsWin32.h @@ -38,6 +38,8 @@ #error WIN32 only! #endif // WIN32 +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include #include "GHOST_SystemPaths.h" diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 143f7e97f2d..ee6f52a03aa 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -39,21 +39,16 @@ * @date May 7, 2001 */ +#ifdef BF_GHOST_DEBUG #include - -#ifdef FREE_WINDOWS -# define WINVER 0x0501 /* GetConsoleWindow() for MinGW */ #endif +#include // [mce] temporary debug, remove soon! + #include "GHOST_SystemWin32.h" #include "GHOST_EventDragnDrop.h" -#define WIN32_LEAN_AND_MEAN -#ifdef _WIN32_IE -#undef _WIN32_IE -#endif -#define _WIN32_IE 0x0501 -#include +#define _WIN32_IE 0x0501 /* shipped before XP, so doesn't impose additional requirements */ #include // win64 doesn't define GWL_USERDATA @@ -64,6 +59,7 @@ #endif #endif +#if 0 // shouldn't be needed... /* * According to the docs the mouse wheel message is supported from windows 98 * upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the @@ -94,18 +90,20 @@ #define WM_XBUTTONDOWN 523 #endif // WM_XBUTTONDOWN +#endif // ^^^ removed code + #include "GHOST_Debug.h" #include "GHOST_DisplayManagerWin32.h" #include "GHOST_EventButton.h" #include "GHOST_EventCursor.h" #include "GHOST_EventKey.h" #include "GHOST_EventWheel.h" -#include "GHOST_EventNDOF.h" +//#include "GHOST_EventNDOF.h" #include "GHOST_TimerTask.h" #include "GHOST_TimerManager.h" #include "GHOST_WindowManager.h" #include "GHOST_WindowWin32.h" -#include "GHOST_NDOFManager.h" +#include "GHOST_NDOFManagerWin32.h" // Key code values not found in winuser.h #ifndef VK_MINUS @@ -158,6 +156,7 @@ #define VK_MEDIA_PLAY_PAUSE 0xB3 #endif // VK_MEDIA_PLAY_PAUSE +#if 0 /* Initiates WM_INPUT messages from keyboard That way GHOST can retrieve true keys @@ -170,6 +169,27 @@ GHOST_TInt32 GHOST_SystemWin32::initKeyboardRawInput(void) return RegisterRawInputDevices(&device, 1, sizeof(device)); }; +#endif + +static void initRawInput() +{ + RAWINPUTDEVICE devices[2]; + memset(devices, 0, 2 * sizeof(RAWINPUTDEVICE)); + + // multi-axis mouse (SpaceNavigator) + devices[0].usUsagePage = 0x01; + devices[0].usUsage = 0x08; + + // Initiates WM_INPUT messages from keyboard + // That way GHOST can retrieve true keys + devices[1].usUsagePage = 0x01; + devices[1].usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */ + + if (RegisterRawInputDevices(devices, 2, sizeof(RAWINPUTDEVICE))) + puts("registered for RawInput (spacenav & keyboard)"); + else + printf("could not register for RawInput: %d\n", (int)GetLastError()); +} GHOST_SystemWin32::GHOST_SystemWin32() : m_hasPerformanceCounter(false), m_freq(0), m_start(0) @@ -186,6 +206,8 @@ GHOST_SystemWin32::GHOST_SystemWin32() this->handleKeyboardChange(); // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32. OleInitialize(0); + + m_ndofManager = new GHOST_NDOFManagerWin32(*this); } GHOST_SystemWin32::~GHOST_SystemWin32() @@ -193,6 +215,7 @@ GHOST_SystemWin32::~GHOST_SystemWin32() // Shutdown COM OleUninitialize(); toggleConsole(1); + delete m_ndofManager; } @@ -384,22 +407,23 @@ GHOST_TSuccess GHOST_SystemWin32::init() GHOST_TSuccess success = GHOST_System::init(); /* Disable scaling on high DPI displays on Vista */ + HMODULE user32 = ::LoadLibraryA("user32.dll"); typedef BOOL (WINAPI * LPFNSETPROCESSDPIAWARE)(); LPFNSETPROCESSDPIAWARE SetProcessDPIAware = (LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware"); if (SetProcessDPIAware) SetProcessDPIAware(); - #ifdef NEED_RAW_PROC - pRegisterRawInputDevices = (LPFNDLLRRID)GetProcAddress(user32, "RegisterRawInputDevices"); - pGetRawInputData = (LPFNDLLGRID)GetProcAddress(user32, "GetRawInputData"); - #else +// #ifdef NEED_RAW_PROC +// pRegisterRawInputDevices = (LPFNDLLRRID)GetProcAddress(user32, "RegisterRawInputDevices"); +// pGetRawInputData = (LPFNDLLGRID)GetProcAddress(user32, "GetRawInputData"); +// #else FreeLibrary(user32); - #endif +// #endif /* Initiates WM_INPUT messages from keyboard */ - initKeyboardRawInput(); - +// initKeyboardRawInput(); + initRawInput(); // Determine whether this system has a high frequency performance counter. */ m_hasPerformanceCounter = ::QueryPerformanceFrequency((LARGE_INTEGER*)&m_freq) == TRUE; @@ -440,104 +464,90 @@ GHOST_TSuccess GHOST_SystemWin32::init() GHOST_TSuccess GHOST_SystemWin32::exit() { - #ifdef NEED_RAW_PROC - FreeLibrary(user32); - #endif +// #ifdef NEED_RAW_PROC +// FreeLibrary(user32); +// #endif return GHOST_System::exit(); } -GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, int * keyDown, char * vk) +GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int * keyDown, char * vk) { - unsigned int size = 0; - char * data; +// unsigned int size = 0; +// char * data; GHOST_TKey key = GHOST_kKeyUnknown; if(!keyDown) return GHOST_kKeyUnknown; - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, 0, &size, sizeof(RAWINPUTHEADER)); + GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); - if((data = (char*)malloc(size)) && - GetRawInputData((HRAWINPUT)lParam, RID_INPUT, data, &size, sizeof(RAWINPUTHEADER))) + GHOST_ModifierKeys modifiers; + system->retrieveModifierKeys(modifiers); + + *keyDown = !(raw.data.keyboard.Flags & RI_KEY_BREAK); + key = this->convertKey(window, raw.data.keyboard.VKey, raw.data.keyboard.MakeCode, (raw.data.keyboard.Flags&(RI_KEY_E1|RI_KEY_E0))); + + // extra handling of modifier keys: don't send repeats out from GHOST + if(key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt) { - RAWINPUT ri; - memcpy(&ri,data,(size < sizeof(ri)) ? size : sizeof(ri)); - - if (ri.header.dwType == RIM_TYPEKEYBOARD) - { - GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); - - GHOST_ModifierKeys modifiers; - system->retrieveModifierKeys(modifiers); - - *keyDown = !(ri.data.keyboard.Flags & RI_KEY_BREAK); - key = this->convertKey(window, ri.data.keyboard.VKey, ri.data.keyboard.MakeCode, (ri.data.keyboard.Flags&(RI_KEY_E1|RI_KEY_E0))); - - // extra handling of modifier keys: don't send repeats out from GHOST - if(key >= GHOST_kKeyLeftShift && key <= GHOST_kKeyRightAlt) - { - bool changed = false; - GHOST_TModifierKeyMask modifier; - switch(key) { - case GHOST_kKeyLeftShift: - { - changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != (bool)*keyDown); - modifier = GHOST_kModifierKeyLeftShift; - } - break; - case GHOST_kKeyRightShift: - { - changed = (modifiers.get(GHOST_kModifierKeyRightShift) != (bool)*keyDown); - modifier = GHOST_kModifierKeyRightShift; - } - break; - case GHOST_kKeyLeftControl: - { - changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != (bool)*keyDown); - modifier = GHOST_kModifierKeyLeftControl; - } - break; - case GHOST_kKeyRightControl: - { - changed = (modifiers.get(GHOST_kModifierKeyRightControl) != (bool)*keyDown); - modifier = GHOST_kModifierKeyRightControl; - } - break; - case GHOST_kKeyLeftAlt: - { - changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != (bool)*keyDown); - modifier = GHOST_kModifierKeyLeftAlt; - } - break; - case GHOST_kKeyRightAlt: - { - changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != (bool)*keyDown); - modifier = GHOST_kModifierKeyRightAlt; - } - break; - default: break; + bool changed = false; + GHOST_TModifierKeyMask modifier; + switch(key) { + case GHOST_kKeyLeftShift: + { + changed = (modifiers.get(GHOST_kModifierKeyLeftShift) != (bool)*keyDown); + modifier = GHOST_kModifierKeyLeftShift; } - - if(changed) + break; + case GHOST_kKeyRightShift: { - modifiers.set(modifier, (bool)*keyDown); - system->storeModifierKeys(modifiers); + changed = (modifiers.get(GHOST_kModifierKeyRightShift) != (bool)*keyDown); + modifier = GHOST_kModifierKeyRightShift; } - else + break; + case GHOST_kKeyLeftControl: { - key = GHOST_kKeyUnknown; + changed = (modifiers.get(GHOST_kModifierKeyLeftControl) != (bool)*keyDown); + modifier = GHOST_kModifierKeyLeftControl; } - } - + break; + case GHOST_kKeyRightControl: + { + changed = (modifiers.get(GHOST_kModifierKeyRightControl) != (bool)*keyDown); + modifier = GHOST_kModifierKeyRightControl; + } + break; + case GHOST_kKeyLeftAlt: + { + changed = (modifiers.get(GHOST_kModifierKeyLeftAlt) != (bool)*keyDown); + modifier = GHOST_kModifierKeyLeftAlt; + } + break; + case GHOST_kKeyRightAlt: + { + changed = (modifiers.get(GHOST_kModifierKeyRightAlt) != (bool)*keyDown); + modifier = GHOST_kModifierKeyRightAlt; + } + break; + default: break; + } + + if(changed) + { + modifiers.set(modifier, (bool)*keyDown); + system->storeModifierKeys(modifiers); + } + else + { + key = GHOST_kKeyUnknown; + } + } - if(vk) *vk = ri.data.keyboard.VKey; - }; - }; - free(data); + if(vk) *vk = raw.data.keyboard.VKey; return key; } @@ -741,12 +751,13 @@ GHOST_EventWheel* GHOST_SystemWin32::processWheelEvent(GHOST_IWindow *window, WP } -GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam) +GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINPUT const& raw) { int keyDown=0; char vk; GHOST_SystemWin32 * system = (GHOST_SystemWin32 *)getSystem(); - GHOST_TKey key = system->hardKey(window, wParam, lParam, &keyDown, &vk); + GHOST_TKey key = system->hardKey(window, raw, &keyDown, &vk); +// GHOST_TKey key = system->hardKey(window, wParam, lParam, &keyDown, &vk); GHOST_EventKey* event; if (key != GHOST_kKeyUnknown) { char ascii = '\0'; @@ -799,9 +810,74 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax) minmax->ptMinTrackSize.y=240; } +bool GHOST_SystemWin32::processNDOF(/*GHOST_WindowWin32* window,*/ RAWINPUT const& raw) +{ + bool eventSent = false; + + // The NDOF manager sends button changes immediately, and *pretends* to + // send motion. Mark as 'sent' so motion will always get dispatched. + eventSent = true; + + BYTE const* data = &raw.data.hid.bRawData; + // MinGW's definition (below) doesn't agree with MSDN reference for bRawData: + // typedef struct tagRAWHID { + // DWORD dwSizeHid; + // DWORD dwCount; + // BYTE bRawData; // <== isn't this s'posed to be a BYTE*? + // } RAWHID,*PRAWHID,*LPRAWHID; + + BYTE packetType = data[0]; + switch (packetType) + { + case 1: // translation + { + short t[3]; + memcpy(t, data + 1, sizeof(t)); + // too much noise -- disable for now + printf("T: %+5d %+5d %+5d\n", t[0], t[1], t[2]); + m_ndofManager->updateTranslation(t, getMilliSeconds()); + // wariness of alignment issues prevents me from saying it this way: + // m_ndofManager->updateTranslation((short*)(data + 1), getMilliSeconds()); + // though it probably (94.7%) works fine + break; + } + case 2: // rotation + { + short r[3]; + memcpy(r, data + 1, sizeof(r)); + printf("R: %+5d %+5d %+5d\n", r[0], r[1], r[2]); + m_ndofManager->updateRotation(r, getMilliSeconds()); + break; + } + case 3: // buttons + { + unsigned short buttons; + memcpy(&buttons, data + 1, sizeof(buttons)); + + printf("buttons:"); + if (buttons) + { + // work our way through the bit mask + for (int i = 0; i < 16; ++i) + if (buttons & (1 << i)) + printf(" %d", i + 1); + printf("\n"); + } + else + printf(" none\n"); + + m_ndofManager->updateButtons(buttons, getMilliSeconds()); + break; + } + } + return eventSent; +} + LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { GHOST_Event* event = 0; + bool eventHandled = false; + LRESULT lResult = 0; GHOST_SystemWin32* system = ((GHOST_SystemWin32*)getSystem()); GHOST_ASSERT(system, "GHOST_SystemWin32::s_wndProc(): system not initialized") @@ -818,18 +894,36 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, // Keyboard events, processed //////////////////////////////////////////////////////////////////////// case WM_INPUT: + { // check WM_INPUT from input sink when ghost window is not in the foreground if (wParam == RIM_INPUTSINK) { if (GetFocus() != hwnd) // WM_INPUT message not for this window return 0; - } //else wPAram == RIM_INPUT - event = processKeyEvent(window, wParam, lParam); - if (!event) { - GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") - GHOST_PRINT(msg) - GHOST_PRINT(" key ignored\n") + } //else wParam == RIM_INPUT + + RAWINPUT raw; + RAWINPUT* raw_ptr = &raw; + UINT rawSize = sizeof(RAWINPUT); + + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, raw_ptr, &rawSize, sizeof(RAWINPUTHEADER)); + + switch (raw.header.dwType) + { + case RIM_TYPEKEYBOARD: + event = processKeyEvent(window, raw); + if (!event) { + GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ") + GHOST_PRINT(msg) + GHOST_PRINT(" key ignored\n") + } + break; + case RIM_TYPEHID: + if (system->processNDOF(/*window,*/ raw)) + eventHandled = true; + break; } - break; + break; + } //////////////////////////////////////////////////////////////////////// // Keyboard events, ignored //////////////////////////////////////////////////////////////////////// @@ -839,9 +933,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, case WM_SYSKEYUP: /* These functions were replaced by WM_INPUT*/ case WM_CHAR: - /* The WM_CHAR message is posted to the window with the keyboard focus when - * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR - * contains the character code of the key that was pressed. + /* The WM_CHAR message is posted to the window with the keyboard focus when + * a WM_KEYDOWN message is translated by the TranslateMessage function. WM_CHAR + * contains the character code of the key that was pressed. */ case WM_DEADCHAR: /* The WM_DEADCHAR message is posted to the window with the keyboard focus when a @@ -1122,6 +1216,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * In GHOST, we let DefWindowProc call the timer callback. */ break; +#if 0 // old NDOF code case WM_BLND_NDOF_AXIS: { GHOST_TEventNDOFData ndofdata; @@ -1144,6 +1239,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, window, ndofdata)); } break; +#endif // old NDOF code } } else { @@ -1163,12 +1259,21 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n") } +// if (event) { +// system->pushEvent(event); +// } +// else { +// lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); +// } + if (event) { system->pushEvent(event); + eventHandled = true; } - else { + + if (!eventHandled) lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); - } + return lResult; } diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index 729ad56d875..cfb88bace10 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -38,7 +38,11 @@ #error WIN32 only! #endif // WIN32 +//#undef _WIN32_WINNT +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include +#include // for drag-n-drop #include "GHOST_System.h" @@ -46,6 +50,8 @@ # define __int64 long long #endif +/* RawInput definitions should not be needed, due to WinXP requirement + #ifndef WM_INPUT #define WM_INPUT 0x00FF #endif @@ -76,8 +82,6 @@ typedef struct tagRAWINPUTDEVICE { HWND hwndTarget; } RAWINPUTDEVICE; - - typedef struct tagRAWINPUTHEADER { DWORD dwType; DWORD dwSize; @@ -134,6 +138,7 @@ typedef BOOL (WINAPI * LPFNDLLRRID)(RAWINPUTDEVICE*,UINT, UINT); typedef UINT (WINAPI * LPFNDLLGRID)(HRAWINPUT, UINT, LPVOID, PUINT, UINT); #define GetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader) ((pGetRawInputData)?pGetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader):(UINT)-1) #endif +*/ class GHOST_EventButton; class GHOST_EventCursor; @@ -314,14 +319,13 @@ protected: /** * Catches raw WIN32 key codes from WM_INPUT in the wndproc. - * @param window-> The window for this handling - * @param wParam The wParam from the wndproc - * @param lParam The lParam from the wndproc + * @param window The window for this handling + * @param raw RawInput structure with detailed info about the key event * @param keyDown Pointer flag that specify if a key is down * @param vk Pointer to virtual key * @return The GHOST key (GHOST_kKeyUnknown if no match). */ - virtual GHOST_TKey hardKey(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam, int * keyDown, char * vk); + virtual GHOST_TKey hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int * keyDown, char * vk); /** * Creates modifier key event(s) and updates the key data stored locally (m_modifierKeys). @@ -362,10 +366,9 @@ protected: * In most cases this is a straightforward conversion of key codes. * For the modifier keys however, we want to distinguish left and right keys. * @param window The window receiving the event (the active window). - * @param wParam The wParam from the wndproc - * @param lParam The lParam from the wndproc + * @param raw RawInput structure with detailed info about the key event */ - static GHOST_EventKey* processKeyEvent(GHOST_IWindow *window, WPARAM wParam, LPARAM lParam); + static GHOST_EventKey* processKeyEvent(GHOST_IWindow *window, RAWINPUT const& raw); /** * Process special keys (VK_OEM_*), to see if current key layout @@ -383,12 +386,23 @@ protected: * @return The event created. */ static GHOST_Event* processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window); - /** + + /** * Handles minimum window size. * @param minmax The MINMAXINFO structure. */ static void processMinMaxInfo(MINMAXINFO * minmax); - + + /** + * Handles Motion and Button events from a SpaceNavigator or related device. + * Instead of returning an event object, this function communicates directly + * with the GHOST_NDOFManager. + * @param window The window receiving the event (the active window). + * @param raw RawInput structure with detailed info about the NDOF event + * @return Whether an event was generated and sent. + */ + bool processNDOF(/*GHOST_IWindow *window,*/ RAWINPUT const& raw); + /** * Returns the local state of the modifier keys (from the message queue). * @param keys The state of the keys. @@ -415,7 +429,7 @@ protected: /** * Initiates WM_INPUT messages from keyboard */ - GHOST_TInt32 initKeyboardRawInput(void); +// GHOST_TInt32 initKeyboardRawInput(void); /** * Toggles console @@ -447,13 +461,13 @@ protected: int m_consoleStatus; /** handle for user32.dll*/ - HMODULE user32; - #ifdef NEED_RAW_PROC - /* pointer to RegisterRawInputDevices function */ - LPFNDLLRRID pRegisterRawInputDevices; - /* pointer to GetRawInputData function */ - LPFNDLLGRID pGetRawInputData; - #endif +// HMODULE user32; +// #ifdef NEED_RAW_PROC +// /* pointer to RegisterRawInputDevices function */ +// LPFNDLLRRID pRegisterRawInputDevices; +// /* pointer to GetRawInputData function */ +// LPFNDLLGRID pGetRawInputData; +// #endif }; inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const diff --git a/intern/ghost/intern/GHOST_TaskbarWin32.h b/intern/ghost/intern/GHOST_TaskbarWin32.h index ef9ebdf5860..eddff8bb91b 100644 --- a/intern/ghost/intern/GHOST_TaskbarWin32.h +++ b/intern/ghost/intern/GHOST_TaskbarWin32.h @@ -3,20 +3,16 @@ */ #ifndef GHOST_TASKBARWIN32_H_ #define GHOST_TASKBARWIN32_H_ + #ifndef WIN32 #error WIN32 only! #endif // WIN32 +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include #include -/* MinGW needs it */ -#ifdef FREE_WINDOWS -#ifdef WINVER -#undef WINVER -#endif -#define WINVER 0x0501 -#endif /* FREE_WINDOWS */ // ITaskbarList, ITaskbarList2 and ITaskbarList3 might be missing, present here in that case. // Note, ITaskbarList3 is supported only since Windows 7, though. Check for that is done in diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index 4055c3acf56..70914d9d2ef 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -39,19 +39,11 @@ #endif // WIN32 #include "GHOST_Window.h" +#include "GHOST_TaskbarWin32.h" -/* MinGW needs it */ -#ifdef FREE_WINDOWS -#ifdef WINVER -#undef WINVER -#endif -#define WINVER 0x0501 -#endif - - - +#define _WIN32_WINNT 0x501 // require Windows XP or newer +#define WIN32_LEAN_AND_MEAN #include -#include "GHOST_TaskbarWin32.h" #include -- cgit v1.2.3 From 7b124242e7a2f5138f245af6af506081b83e5103 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 11 Jun 2011 00:25:48 +0000 Subject: SpaceNav works on Linux --- intern/ghost/GHOST_Types.h | 5 -- intern/ghost/intern/GHOST_EventManager.cpp | 3 +- intern/ghost/intern/GHOST_NDOFManager.cpp | 39 ++++++++-- intern/ghost/intern/GHOST_NDOFManager.h | 20 ++--- intern/ghost/intern/GHOST_NDOFManagerX11.cpp | 86 ++++++++++++++++++++++ intern/ghost/intern/GHOST_NDOFManagerX11.h | 80 +++----------------- intern/ghost/intern/GHOST_SystemWin32.cpp | 1 - intern/ghost/intern/GHOST_SystemX11.cpp | 28 +++++-- intern/ghost/intern/GHOST_SystemX11.h | 4 + source/blender/editors/space_view3d/view3d_edit.c | 8 +- .../blender/windowmanager/intern/wm_event_system.c | 6 +- source/blender/windowmanager/intern/wm_window.c | 4 +- 12 files changed, 178 insertions(+), 106 deletions(-) create mode 100644 intern/ghost/intern/GHOST_NDOFManagerX11.cpp diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index 7fa94b14716..bc731a43ae7 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -47,11 +47,6 @@ 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 - #if defined(WIN32) && !defined(FREE_WINDOWS) typedef __int64 GHOST_TInt64; typedef unsigned __int64 GHOST_TUns64; diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp index 1483555c362..62d55a69f1f 100644 --- a/intern/ghost/intern/GHOST_EventManager.cpp +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -42,7 +42,7 @@ #include "GHOST_EventManager.h" #include #include "GHOST_Debug.h" - +#include // [mce] temp debug GHOST_EventManager::GHOST_EventManager() { @@ -111,6 +111,7 @@ GHOST_TSuccess GHOST_EventManager::pushEvent(GHOST_IEvent* event) bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event) { bool handled; + printf("dispatching %d\n", event->getType()); if (event) { handled = true; TConsumerVector::iterator iter; diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 1042398650e..a181b3b20bd 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -16,7 +16,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Contributor(s): - * Mike Erwin + * Mike Erwin * * ***** END GPL LICENSE BLOCK ***** */ @@ -54,11 +54,32 @@ void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time) m_atRest = false; } -void GHOST_NDOFManager::updateButtons(unsigned short buttons, GHOST_TUns64 time) +void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 time) { GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); - unsigned short diff = m_buttons ^ buttons; + GHOST_EventNDOFButton* event = new GHOST_EventNDOFButton(time, window); + GHOST_TEventNDOFButtonData* data = (GHOST_TEventNDOFButtonData*) event->getData(); + + data->action = press ? GHOST_kPress : GHOST_kRelease; + data->button = button_number + 1; + + printf("sending button %d %s\n", data->button, (data->action == GHOST_kPress) ? "pressed" : "released"); + + m_system.pushEvent(event); + + unsigned short mask = 1 << button_number; + if (press) + m_buttons |= mask; // set this button's bit + else + m_buttons &= ~mask; // clear this button's bit + } + +void GHOST_NDOFManager::updateButtons(unsigned short button_bits, GHOST_TUns64 time) + { + GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); + + unsigned short diff = m_buttons ^ button_bits; for (int i = 0; i < 16; ++i) { @@ -69,16 +90,16 @@ void GHOST_NDOFManager::updateButtons(unsigned short buttons, GHOST_TUns64 time) GHOST_EventNDOFButton* event = new GHOST_EventNDOFButton(time, window); GHOST_TEventNDOFButtonData* data = (GHOST_TEventNDOFButtonData*) event->getData(); - data->action = (buttons & mask) ? GHOST_kPress : GHOST_kRelease; + data->action = (button_bits & mask) ? GHOST_kPress : GHOST_kRelease; data->button = i + 1; - // printf("sending button %d %s\n", data->button, (data->action == GHOST_kPress) ? "pressed" : "released"); + printf("sending button %d %s\n", data->button, (data->action == GHOST_kPress) ? "pressed" : "released"); m_system.pushEvent(event); } } - m_buttons = buttons; + m_buttons = button_bits; } bool GHOST_NDOFManager::sendMotionEvent() @@ -109,14 +130,16 @@ bool GHOST_NDOFManager::sendMotionEvent() m_prevMotionTime = m_motionTime; - // printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", - // data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, data->dt); + printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", + data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, data->dt); m_system.pushEvent(event); // 'at rest' test goes at the end so that the first 'rest' event gets sent m_atRest = m_rotation[0] == 0 && m_rotation[1] == 0 && m_rotation[2] == 0 && m_translation[0] == 0 && m_translation[1] == 0 && m_translation[2] == 0; + // this needs to be aware of calibration -- 0.01 0.01 0.03 might be 'rest' return true; } + diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index f4adb4cab1d..f70cebe09e2 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -15,7 +15,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Contributor(s): none yet. + * Contributor(s): + * Mike Erwin * * ***** END GPL LICENSE BLOCK ***** */ @@ -40,27 +41,28 @@ public: // the latest raw data from the device void updateTranslation(short t[3], GHOST_TUns64 time); void updateRotation(short r[3], GHOST_TUns64 time); - // this one sends events immediately for changed buttons - void updateButtons(unsigned short b, GHOST_TUns64 time); + // send events immediately for changed buttons + void updateButton(int button_number, bool press, GHOST_TUns64 time); + void updateButtons(unsigned short button_bits, GHOST_TUns64 time); // processes most recent raw data into an NDOFMotion event and sends it // returns whether an event was sent - virtual bool sendMotionEvent(); + bool sendMotionEvent(); protected: GHOST_System& m_system; short m_translation[3]; short m_rotation[3]; - unsigned short m_buttons; + unsigned short m_buttons; // bit field - GHOST_TUns64 m_motionTime; + GHOST_TUns64 m_motionTime; // in milliseconds GHOST_TUns64 m_prevMotionTime; // time of most recent Motion event sent bool m_atRest; - void updateMotionTime(GHOST_TUns64 t); - void resetMotion(); +// void updateMotionTime(GHOST_TUns64 t); +// void resetMotion(); }; - #endif + diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp new file mode 100644 index 00000000000..4e37c02d141 --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp @@ -0,0 +1,86 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): + * Mike Erwin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "GHOST_NDOFManagerX11.h" +#include "GHOST_SystemX11.h" +#include +#include + + +GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys) + : GHOST_NDOFManager(sys) + { + if (spnav_open() != -1) + { + m_available = true; + } + else + { + printf(" SpaceNav driver not found\n"); + // This isn't a hard error, just means the user doesn't have a SpaceNavigator. + m_available = false; + } + } + +GHOST_NDOFManagerX11::~GHOST_NDOFManagerX11() + { + if (m_available) + { + spnav_remove_events(SPNAV_EVENT_ANY); // ask nuclear if this is needed + spnav_close(); + } + } + +bool GHOST_NDOFManagerX11::available() + { + return m_available; + } + +bool GHOST_NDOFManagerX11::processEvents() + { + GHOST_TUns64 now = m_system.getMilliSeconds(); + + bool anyProcessed = false; + spnav_event e; + while (spnav_poll_event(&e)) + { + switch (e.type) + { + case SPNAV_EVENT_MOTION: + { + short t[3] = {e.motion.x, e.motion.y, e.motion.z}; + short r[3] = {e.motion.rx, e.motion.ry, e.motion.rz}; + + updateTranslation(t, now); + updateRotation(r, now); + break; + } + case SPNAV_EVENT_BUTTON: + updateButton(e.button.bnum, e.button.press, now); + break; + } + anyProcessed = true; + } + return anyProcessed; + } + diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.h b/intern/ghost/intern/GHOST_NDOFManagerX11.h index 4c89bfe0ca6..cf6f1d00cba 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.h +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.h @@ -15,7 +15,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Contributor(s): none yet. + * Contributor(s): + * Mike Erwin * * ***** END GPL LICENSE BLOCK ***** */ @@ -24,77 +25,18 @@ #define _GHOST_NDOFMANAGERX11_H_ #include "GHOST_NDOFManager.h" -#include "GHOST_Types.h" -#include "GHOST_WindowX11.h" -#include "GHOST_EventNDOF.h" -#include -#include class GHOST_NDOFManagerX11 : public GHOST_NDOFManager -{ -GHOST_WindowX11 * m_ghost_window_x11; - + { public: - GHOST_NDOFManagerX11(GHOST_System& sys) - : GHOST_NDOFManager(sys) - {} - - void setGHOSTWindowX11(GHOST_WindowX11 * w){ - if (m_ghost_window_x11 == NULL) - m_ghost_window_x11 = w; - } - - GHOST_WindowX11 * getGHOSTWindowX11(){ - return m_ghost_window_x11; - } - - // whether multi-axis functionality is available (via the OS or driver) - // does not imply that a device is plugged in or being used - bool available() - { - // never available since I've not yet written it! - return true; - } - - virtual bool sendMotionEvent() - { - if (m_atRest) - return false; - - GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, getGHOSTWindowX11()); - GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData(); - - const float scale = 1.f/350.f; // SpaceNavigator sends +/- 350 usually - // 350 according to their developer's guide; others recommend 500 as comfortable - - // possible future enhancement - // scale *= m_sensitivity; - - data->tx = -scale * m_translation[0]; - data->ty = scale * m_translation[1]; - data->tz = scale * m_translation[2]; - - data->rx = scale * m_rotation[0]; - data->ry = scale * m_rotation[1]; - data->rz = scale * m_rotation[2]; - - data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds - - m_prevMotionTime = m_motionTime; - - printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", - data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, data->dt); - - if (!m_system.pushEvent(event)) - return false; - - // 'at rest' test goes at the end so that the first 'rest' event gets sent - m_atRest = m_rotation[0] == 0 && m_rotation[1] == 0 && m_rotation[2] == 0 && - m_translation[0] == 0 && m_translation[1] == 0 && m_translation[2] == 0; - - return true; - } -}; + GHOST_NDOFManagerX11(GHOST_System&); + ~GHOST_NDOFManagerX11(); + bool available(); + bool processEvents(); +private: + bool m_available; + }; #endif + diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index ee6f52a03aa..37efb6493bf 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -215,7 +215,6 @@ GHOST_SystemWin32::~GHOST_SystemWin32() // Shutdown COM OleUninitialize(); toggleConsole(1); - delete m_ndofManager; } diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index c53bf7de36c..5e59ac91809 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -42,8 +42,7 @@ #include "GHOST_EventKey.h" #include "GHOST_EventButton.h" #include "GHOST_EventWheel.h" -#include "GHOST_EventNDOF.h" -#include "GHOST_NDOFManager.h" +#include "GHOST_NDOFManagerX11.h" #include "GHOST_DisplayManagerX11.h" #include "GHOST_Debug.h" @@ -76,6 +75,8 @@ #include // for fprintf only #include // for exit +#if 0 // obsolete SpaceNav code + typedef struct NDOFPlatformInfo { Display *display; Window window; @@ -88,6 +89,7 @@ typedef struct NDOFPlatformInfo { static NDOFPlatformInfo sNdofInfo = {NULL, 0, NULL, 0, 0, 0, 0}; +#endif //these are for copy and select copy static char *txt_cut_buffer= NULL; @@ -177,6 +179,7 @@ init( GHOST_TSuccess success = GHOST_System::init(); if (success) { + m_ndofManager = new GHOST_NDOFManagerX11(*this); m_displayManager = new GHOST_DisplayManagerX11(this); if (m_displayManager) { @@ -270,7 +273,7 @@ createWindow( if (window->getValid()) { // Store the pointer to the window m_windowManager->addWindow(window); - + m_windowManager->setActiveWindow(window); pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window) ); } else { @@ -381,8 +384,6 @@ lastEventTime(Time default_time) { return data.timestamp; } - - bool GHOST_SystemX11:: processEvents( @@ -423,6 +424,11 @@ processEvents( if (generateWindowExposeEvents()) { anyProcessed = true; } + + if (dynamic_cast(m_ndofManager)->processEvents()) { + anyProcessed = true; + } + } while (waitForEvent && !anyProcessed); return anyProcessed; @@ -636,6 +642,9 @@ GHOST_SystemX11::processEvent(XEvent *xe) ); } else #endif + +#if 0 // obsolete SpaceNav code + if (sNdofInfo.currValues) { static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0}; if (xcme.message_type == sNdofInfo.motionAtom) @@ -661,7 +670,10 @@ GHOST_SystemX11::processEvent(XEvent *xe) GHOST_kEventNDOFButton, window, data); } - } else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) { + +#endif + + if (((Atom)xcme.data.l[0]) == m_wm_take_focus) { XWindowAttributes attr; Window fwin; int revert_to; @@ -829,6 +841,8 @@ GHOST_SystemX11::processEvent(XEvent *xe) } } +#if 0 // obsolete SpaceNav code + void * GHOST_SystemX11:: prepareNdofInfo(volatile GHOST_TEventNDOFData *currentNdofValues) @@ -841,6 +855,8 @@ prepareNdofInfo(volatile GHOST_TEventNDOFData *currentNdofValues) return (void*)&sNdofInfo; } +#endif + GHOST_TSuccess GHOST_SystemX11:: getModifierKeys( diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 0b001273634..e551b5fb2fe 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -203,11 +203,15 @@ public: return m_display; } +#if 0 // obsolete SpaceNav code + void * prepareNdofInfo( volatile GHOST_TEventNDOFData *current_values ); +#endif + /* Helped function for get data from the clipboard. */ void getClipboard_xcout(XEvent evt, Atom sel, Atom target, unsigned char **txt, unsigned long *len, diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 315c8b39f44..76d595c275b 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -958,10 +958,6 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) 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]; @@ -970,6 +966,10 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) const float sensitivity = 0.035; + if (dt > 0.25f) + /* this is probably the first event for this motion, so set dt to something reasonable */ + dt = 0.0125f; + /* Get the 3x3 matrix and its inverse from the quaternion */ quat_to_mat3(m,rv3d->viewquat); invert_m3_m3(m_inv,m); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 96071bc442b..56805aa3d3f 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2375,7 +2375,9 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U { wmWindow *owin; wmEvent event, *evt= win->eventstate; - + + printf("ghost (%d) --> wm\n", type); + /* initialize and copy state (only mouse x y and modifiers) */ event= *evt; @@ -2579,6 +2581,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U } case GHOST_kEventNDOFMotion: { + puts("ndof motion in wm"); event.type = NDOF_MOTION; attach_ndof_data(&event, customdata); wm_event_add(win, &event); @@ -2588,6 +2591,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U case GHOST_kEventNDOFButton: { GHOST_TEventNDOFButtonData* e = customdata; + puts("ndof button in wm"); event.type = NDOF_BUTTON_NONE + e->button; diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 9ee39132521..7524174c345 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -621,12 +621,12 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) if (!ghostwin) { // XXX - should be checked, why are we getting an event here, and // what is it? - + puts(" event has no window"); return 1; } else if (!GHOST_ValidWindow(g_system, ghostwin)) { // XXX - should be checked, why are we getting an event here, and // what is it? - + puts(" event has invalid window"); return 1; } else { win= GHOST_GetWindowUserData(ghostwin); -- cgit v1.2.3 From 6c7daf58be5b11c7905d8cddb3c35aecd82d92c2 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 11 Jun 2011 00:58:49 +0000 Subject: one small change -- SpaceNav works on Windows --- intern/ghost/intern/GHOST_SystemWin32.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 37efb6493bf..141609cf0a2 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -266,6 +266,7 @@ GHOST_IWindow* GHOST_SystemWin32::createWindow( // Store the pointer to the window // if (state != GHOST_kWindowStateFullScreen) { m_windowManager->addWindow(window); + m_windowManager->setActiveWindow(window); // } } else { @@ -786,7 +787,15 @@ GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINP GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_IWindow* window) { - return new GHOST_Event(getSystem()->getMilliSeconds(), type, window); + GHOST_System* system = (GHOST_System*)getSystem(); + + if (type == GHOST_kEventWindowActivate) + { + puts("activating window"); + system->getWindowManager()->setActiveWindow(window); + } + + return new GHOST_Event(system->getMilliSeconds(), type, window); } GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType, -- cgit v1.2.3 From 450f176a8f7d545dc866aecea768b16d200aa910 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 11 Jun 2011 02:26:28 +0000 Subject: split Win32 NDOF manager into 2 files to fix Mac scons build --- intern/ghost/intern/GHOST_NDOFManagerWin32.cpp | 37 ++++++++++++++++++++++++++ intern/ghost/intern/GHOST_NDOFManagerWin32.h | 13 ++------- 2 files changed, 39 insertions(+), 11 deletions(-) create mode 100644 intern/ghost/intern/GHOST_NDOFManagerWin32.cpp diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp new file mode 100644 index 00000000000..d7285d568de --- /dev/null +++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp @@ -0,0 +1,37 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): + * Mike Erwin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "GHOST_NDOFManagerWin32.h" + + +GHOST_NDOFManagerWin32::GHOST_NDOFManagerWin32(GHOST_System& sys) + : GHOST_NDOFManager(sys) + {} + +// whether multi-axis functionality is available (via the OS or driver) +// does not imply that a device is plugged in or being used +bool GHOST_NDOFManagerWin32::available() + { + // always available since RawInput is built into Windows + return true; + } diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.h b/intern/ghost/intern/GHOST_NDOFManagerWin32.h index 0570eefa951..3802a6de93d 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerWin32.h +++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.h @@ -30,17 +30,8 @@ class GHOST_NDOFManagerWin32 : public GHOST_NDOFManager { public: - GHOST_NDOFManagerWin32(GHOST_System& sys) - : GHOST_NDOFManager(sys) - {} - - // whether multi-axis functionality is available (via the OS or driver) - // does not imply that a device is plugged in or being used - bool available() - { - // always available since RawInput is built into Windows - return true; - } + GHOST_NDOFManagerWin32(GHOST_System&); + bool available(); }; -- cgit v1.2.3 From 6aa77771443391c827268ef0eac7a5e4382a3e44 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Wed, 15 Jun 2011 02:40:25 +0000 Subject: removed temporary debug logging --- intern/ghost/intern/GHOST_EventManager.cpp | 1 - source/blender/windowmanager/intern/wm_event_system.c | 4 ---- 2 files changed, 5 deletions(-) diff --git a/intern/ghost/intern/GHOST_EventManager.cpp b/intern/ghost/intern/GHOST_EventManager.cpp index 62d55a69f1f..86b87973038 100644 --- a/intern/ghost/intern/GHOST_EventManager.cpp +++ b/intern/ghost/intern/GHOST_EventManager.cpp @@ -111,7 +111,6 @@ GHOST_TSuccess GHOST_EventManager::pushEvent(GHOST_IEvent* event) bool GHOST_EventManager::dispatchEvent(GHOST_IEvent* event) { bool handled; - printf("dispatching %d\n", event->getType()); if (event) { handled = true; TConsumerVector::iterator iter; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 56805aa3d3f..b41eebc5298 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2376,8 +2376,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U wmWindow *owin; wmEvent event, *evt= win->eventstate; - printf("ghost (%d) --> wm\n", type); - /* initialize and copy state (only mouse x y and modifiers) */ event= *evt; @@ -2581,7 +2579,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U } case GHOST_kEventNDOFMotion: { - puts("ndof motion in wm"); event.type = NDOF_MOTION; attach_ndof_data(&event, customdata); wm_event_add(win, &event); @@ -2591,7 +2588,6 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U case GHOST_kEventNDOFButton: { GHOST_TEventNDOFButtonData* e = customdata; - puts("ndof button in wm"); event.type = NDOF_BUTTON_NONE + e->button; -- cgit v1.2.3 From 04584806ccb5559cef3468d7fd71c0e3aa13639e Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Wed, 15 Jun 2011 16:05:10 +0000 Subject: handle up to 32 buttons (up from 16), for SpacePilot PRO --- intern/ghost/intern/GHOST_NDOFManager.cpp | 7 +++---- intern/ghost/intern/GHOST_NDOFManager.h | 5 ++--- intern/ghost/intern/GHOST_NDOFManagerX11.cpp | 1 - intern/ghost/intern/GHOST_SystemWin32.cpp | 24 ++++++++++++------------ 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index a181b3b20bd..158fb4d1029 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -75,13 +75,13 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 m_buttons &= ~mask; // clear this button's bit } -void GHOST_NDOFManager::updateButtons(unsigned short button_bits, GHOST_TUns64 time) +void GHOST_NDOFManager::updateButtons(unsigned button_bits, GHOST_TUns64 time) { GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); - unsigned short diff = m_buttons ^ button_bits; + unsigned diff = m_buttons ^ button_bits; - for (int i = 0; i < 16; ++i) + for (int i = 0; i <= 31; ++i) { unsigned short mask = 1 << i; @@ -142,4 +142,3 @@ bool GHOST_NDOFManager::sendMotionEvent() return true; } - diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index f70cebe09e2..c2bd7a336e7 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -43,7 +43,7 @@ public: void updateRotation(short r[3], GHOST_TUns64 time); // send events immediately for changed buttons void updateButton(int button_number, bool press, GHOST_TUns64 time); - void updateButtons(unsigned short button_bits, GHOST_TUns64 time); + void updateButtons(unsigned button_bits, GHOST_TUns64 time); // processes most recent raw data into an NDOFMotion event and sends it // returns whether an event was sent @@ -54,7 +54,7 @@ protected: short m_translation[3]; short m_rotation[3]; - unsigned short m_buttons; // bit field + unsigned m_buttons; // bit field GHOST_TUns64 m_motionTime; // in milliseconds GHOST_TUns64 m_prevMotionTime; // time of most recent Motion event sent @@ -65,4 +65,3 @@ protected: }; #endif - diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp index 4e37c02d141..99ee29d8a17 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp @@ -83,4 +83,3 @@ bool GHOST_NDOFManagerX11::processEvents() } return anyProcessed; } - diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 141609cf0a2..69ced683435 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -859,20 +859,20 @@ bool GHOST_SystemWin32::processNDOF(/*GHOST_WindowWin32* window,*/ RAWINPUT cons } case 3: // buttons { - unsigned short buttons; + unsigned buttons; memcpy(&buttons, data + 1, sizeof(buttons)); - printf("buttons:"); - if (buttons) - { - // work our way through the bit mask - for (int i = 0; i < 16; ++i) - if (buttons & (1 << i)) - printf(" %d", i + 1); - printf("\n"); - } - else - printf(" none\n"); +// printf("buttons:"); +// if (buttons) +// { +// // work our way through the bit mask +// for (int i = 0; i < 16; ++i) +// if (buttons & (1 << i)) +// printf(" %d", i + 1); +// printf("\n"); +// } +// else +// printf(" none\n"); m_ndofManager->updateButtons(buttons, getMilliSeconds()); break; -- cgit v1.2.3 From 060e2b295bb6159e94abef03299846f99f431b34 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Wed, 15 Jun 2011 19:45:00 +0000 Subject: mapping HID button codes -> functions, for SpaceNavigator and SpaceExplorer --- intern/ghost/intern/GHOST_NDOFManager.cpp | 147 +++++++++++++++++++++++++----- intern/ghost/intern/GHOST_NDOFManager.h | 60 +++++++++++- 2 files changed, 179 insertions(+), 28 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 158fb4d1029..e9097ff63bf 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -23,12 +23,83 @@ #include "GHOST_NDOFManager.h" #include "GHOST_EventNDOF.h" +#include "GHOST_EventKey.h" #include "GHOST_WindowManager.h" #include // for memory functions #include // for debug tracing + + +const char* ndof_button_names[] = { + // used internally, never sent + "NDOF_BUTTON_NONE", + // these two are available from any 3Dconnexion device + "NDOF_BUTTON_MENU", + "NDOF_BUTTON_FIT", + // standard views + "NDOF_BUTTON_TOP", + "NDOF_BUTTON_BOTTOM", + "NDOF_BUTTON_LEFT", + "NDOF_BUTTON_RIGHT", + "NDOF_BUTTON_FRONT", + "NDOF_BUTTON_BACK", + // more views + "NDOF_BUTTON_ISO1", + "NDOF_BUTTON_ISO2", + // 90 degree rotations + "NDOF_BUTTON_ROLL_CW", + "NDOF_BUTTON_ROLL_CCW", + "NDOF_BUTTON_SPIN_CW", + "NDOF_BUTTON_SPIN_CCW", + "NDOF_BUTTON_TILT_CW", + "NDOF_BUTTON_TILT_CCW", + // device control + "NDOF_BUTTON_ROTATE", + "NDOF_BUTTON_PANZOOM", + "NDOF_BUTTON_DOMINANT", + "NDOF_BUTTON_PLUS", + "NDOF_BUTTON_MINUS", + // general-purpose buttons + "NDOF_BUTTON_1", + "NDOF_BUTTON_2", + "NDOF_BUTTON_3", + "NDOF_BUTTON_4", + "NDOF_BUTTON_5", + "NDOF_BUTTON_6", + "NDOF_BUTTON_7", + "NDOF_BUTTON_8", + "NDOF_BUTTON_9", + "NDOF_BUTTON_10", + }; + +const NDOF_ButtonT SpaceNavigator_HID_to_function[2] = + { + NDOF_BUTTON_MENU, + NDOF_BUTTON_FIT + }; + +const NDOF_ButtonT SpaceExplorer_HID_to_function[16] = + { + NDOF_BUTTON_1, + NDOF_BUTTON_2, + NDOF_BUTTON_TOP, + NDOF_BUTTON_LEFT, + NDOF_BUTTON_RIGHT, + NDOF_BUTTON_FRONT, + NDOF_BUTTON_NONE, // esc key + NDOF_BUTTON_NONE, // alt key + NDOF_BUTTON_NONE, // shift key + NDOF_BUTTON_NONE, // ctrl key + NDOF_BUTTON_FIT, + NDOF_BUTTON_MENU, + NDOF_BUTTON_PLUS, + NDOF_BUTTON_MINUS, + NDOF_BUTTON_ROTATE + }; + GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) : m_system(sys) + , m_deviceType(SpaceExplorer) // set it manually, until device detection code is in place , m_buttons(0) , m_motionTime(1000) // one full second (operators should filter out such large time deltas) , m_prevMotionTime(0) @@ -54,52 +125,82 @@ void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time) m_atRest = false; } -void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 time) +void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, bool press, GHOST_TUns64 time, GHOST_IWindow* window) { - GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); - GHOST_EventNDOFButton* event = new GHOST_EventNDOFButton(time, window); GHOST_TEventNDOFButtonData* data = (GHOST_TEventNDOFButtonData*) event->getData(); data->action = press ? GHOST_kPress : GHOST_kRelease; - data->button = button_number + 1; + data->button = button; - printf("sending button %d %s\n", data->button, (data->action == GHOST_kPress) ? "pressed" : "released"); + printf("sending %s %s\n", ndof_button_names[button], press ? "pressed" : "released"); m_system.pushEvent(event); + } - unsigned short mask = 1 << button_number; +void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key, bool press, GHOST_TUns64 time, GHOST_IWindow* window) + { + GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp; + GHOST_EventKey* event = new GHOST_EventKey(time, type, window, key); + + m_system.pushEvent(event); + } + +void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 time) + { + GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); + + switch (m_deviceType) + { + case SpaceNavigator: + sendButtonEvent(SpaceNavigator_HID_to_function[button_number], press, time, window); + break; + case SpaceExplorer: + switch (button_number) + { + case 6: + sendKeyEvent(GHOST_kKeyEsc, press, time, window); + break; + case 7: + sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); + break; + case 8: + sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); + break; + case 9: + sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); + break; + default: + sendButtonEvent(SpaceExplorer_HID_to_function[button_number], press, time, window); + } + break; + case SpacePilot: + printf("button %d %s\n", button, press ? "pressed" : "released"); + // sendButtonEvent(SpacePilot_HID_to_function(button_number), press, time, window); + break; + } + + int mask = 1 << button_number; if (press) m_buttons |= mask; // set this button's bit else m_buttons &= ~mask; // clear this button's bit } -void GHOST_NDOFManager::updateButtons(unsigned button_bits, GHOST_TUns64 time) +void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time) { - GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); - - unsigned diff = m_buttons ^ button_bits; + int diff = m_buttons ^ button_bits; - for (int i = 0; i <= 31; ++i) + for (int button_number = 0; button_number <= 31; ++button_number) { - unsigned short mask = 1 << i; + int mask = 1 << button_number; if (diff & mask) { - GHOST_EventNDOFButton* event = new GHOST_EventNDOFButton(time, window); - GHOST_TEventNDOFButtonData* data = (GHOST_TEventNDOFButtonData*) event->getData(); - - data->action = (button_bits & mask) ? GHOST_kPress : GHOST_kRelease; - data->button = i + 1; - - printf("sending button %d %s\n", data->button, (data->action == GHOST_kPress) ? "pressed" : "released"); - - m_system.pushEvent(event); + bool press = button_bits & mask; + updateButton(button_number, press, time); } } - - m_buttons = button_bits; } bool GHOST_NDOFManager::sendMotionEvent() diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index c2bd7a336e7..eb04ca654ee 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -27,6 +27,53 @@ #include "GHOST_System.h" +// --- the following type definitions will find a home somewhere else once finished --- + +typedef enum { SpaceNavigator, SpaceExplorer, SpacePilot } NDOF_DeviceT; + +// NDOF device button event types +typedef enum { + // used internally, never sent + NDOF_BUTTON_NONE, + // these two are available from any 3Dconnexion device + NDOF_BUTTON_MENU, + NDOF_BUTTON_FIT, + // standard views + NDOF_BUTTON_TOP, + NDOF_BUTTON_BOTTOM, + NDOF_BUTTON_LEFT, + NDOF_BUTTON_RIGHT, + NDOF_BUTTON_FRONT, + NDOF_BUTTON_BACK, + // more views + NDOF_BUTTON_ISO1, + NDOF_BUTTON_ISO2, + // 90 degree rotations + NDOF_BUTTON_ROLL_CW, + NDOF_BUTTON_ROLL_CCW, + NDOF_BUTTON_SPIN_CW, + NDOF_BUTTON_SPIN_CCW, + NDOF_BUTTON_TILT_CW, + NDOF_BUTTON_TILT_CCW, + // device control + NDOF_BUTTON_ROTATE, + NDOF_BUTTON_PANZOOM, + NDOF_BUTTON_DOMINANT, + NDOF_BUTTON_PLUS, + NDOF_BUTTON_MINUS, + // general-purpose buttons + NDOF_BUTTON_1, + NDOF_BUTTON_2, + NDOF_BUTTON_3, + NDOF_BUTTON_4, + NDOF_BUTTON_5, + NDOF_BUTTON_6, + NDOF_BUTTON_7, + NDOF_BUTTON_8, + NDOF_BUTTON_9, + NDOF_BUTTON_10, + } NDOF_ButtonT; + class GHOST_NDOFManager { public: @@ -43,25 +90,28 @@ public: void updateRotation(short r[3], GHOST_TUns64 time); // send events immediately for changed buttons void updateButton(int button_number, bool press, GHOST_TUns64 time); - void updateButtons(unsigned button_bits, GHOST_TUns64 time); + void updateButtons(int button_bits, GHOST_TUns64 time); // processes most recent raw data into an NDOFMotion event and sends it // returns whether an event was sent bool sendMotionEvent(); +private: + void sendButtonEvent(NDOF_ButtonT, bool press, GHOST_TUns64 time, GHOST_IWindow*); + void sendKeyEvent(GHOST_TKey, bool press, GHOST_TUns64 time, GHOST_IWindow*); + protected: GHOST_System& m_system; + NDOF_DeviceT m_deviceType; + short m_translation[3]; short m_rotation[3]; - unsigned m_buttons; // bit field + int m_buttons; // bit field GHOST_TUns64 m_motionTime; // in milliseconds GHOST_TUns64 m_prevMotionTime; // time of most recent Motion event sent bool m_atRest; - -// void updateMotionTime(GHOST_TUns64 t); -// void resetMotion(); }; #endif -- cgit v1.2.3 From d5cafb808f24c8f4caa50a222fd10d2e0c9966c0 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Wed, 15 Jun 2011 19:57:10 +0000 Subject: fixed typos, renamed the HID -> function lookup tables --- intern/ghost/intern/GHOST_NDOFManager.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index e9097ff63bf..78760cedd54 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -30,7 +30,7 @@ -const char* ndof_button_names[] = { +static const char* ndof_button_names[] = { // used internally, never sent "NDOF_BUTTON_NONE", // these two are available from any 3Dconnexion device @@ -72,13 +72,13 @@ const char* ndof_button_names[] = { "NDOF_BUTTON_10", }; -const NDOF_ButtonT SpaceNavigator_HID_to_function[2] = +static const NDOF_ButtonT SpaceNavigator_HID_map[2] = { NDOF_BUTTON_MENU, NDOF_BUTTON_FIT }; -const NDOF_ButtonT SpaceExplorer_HID_to_function[16] = +static const NDOF_ButtonT SpaceExplorer_HID_map[16] = { NDOF_BUTTON_1, NDOF_BUTTON_2, @@ -153,7 +153,7 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 switch (m_deviceType) { case SpaceNavigator: - sendButtonEvent(SpaceNavigator_HID_to_function[button_number], press, time, window); + sendButtonEvent(SpaceNavigator_HID_map[button_number], press, time, window); break; case SpaceExplorer: switch (button_number) @@ -171,12 +171,12 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; default: - sendButtonEvent(SpaceExplorer_HID_to_function[button_number], press, time, window); + sendButtonEvent(SpaceExplorer_HID_map[button_number], press, time, window); } break; case SpacePilot: - printf("button %d %s\n", button, press ? "pressed" : "released"); - // sendButtonEvent(SpacePilot_HID_to_function(button_number), press, time, window); + printf("button %d %s\n", button_number, press ? "pressed" : "released"); + // sendButtonEvent(SpacePilot_HID_map[button_number], press, time, window); break; } -- cgit v1.2.3 From d7ef491845460ab2cf839c096e43672beec11944 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Wed, 15 Jun 2011 20:56:42 +0000 Subject: cleaned up event logging, added HID -> function table for SpacePilot PRO --- intern/ghost/intern/GHOST_NDOFManager.cpp | 88 +++++++++++++++++++++++-------- intern/ghost/intern/GHOST_NDOFManager.h | 3 ++ intern/ghost/intern/GHOST_SystemWin32.cpp | 24 ++------- 3 files changed, 73 insertions(+), 42 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 78760cedd54..20baa6f725e 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -28,8 +28,7 @@ #include // for memory functions #include // for debug tracing - - +#ifdef DEBUG_NDOF_BUTTONS static const char* ndof_button_names[] = { // used internally, never sent "NDOF_BUTTON_NONE", @@ -71,14 +70,15 @@ static const char* ndof_button_names[] = { "NDOF_BUTTON_9", "NDOF_BUTTON_10", }; +#endif -static const NDOF_ButtonT SpaceNavigator_HID_map[2] = +static const NDOF_ButtonT SpaceNavigator_HID_map[] = { NDOF_BUTTON_MENU, NDOF_BUTTON_FIT }; -static const NDOF_ButtonT SpaceExplorer_HID_map[16] = +static const NDOF_ButtonT SpaceExplorer_HID_map[] = { NDOF_BUTTON_1, NDOF_BUTTON_2, @@ -97,9 +97,44 @@ static const NDOF_ButtonT SpaceExplorer_HID_map[16] = NDOF_BUTTON_ROTATE }; +static const NDOF_ButtonT SpacePilot_HID_map[] = + { + NDOF_BUTTON_MENU, + NDOF_BUTTON_FIT, + NDOF_BUTTON_TOP, + NDOF_BUTTON_LEFT, + NDOF_BUTTON_RIGHT, + NDOF_BUTTON_FRONT, + NDOF_BUTTON_BOTTOM, + NDOF_BUTTON_BACK, + NDOF_BUTTON_ROLL_CW, + NDOF_BUTTON_ROLL_CCW, + NDOF_BUTTON_ISO1, + NDOF_BUTTON_ISO2, + NDOF_BUTTON_1, + NDOF_BUTTON_2, + NDOF_BUTTON_3, + NDOF_BUTTON_4, + NDOF_BUTTON_5, + NDOF_BUTTON_6, + NDOF_BUTTON_7, + NDOF_BUTTON_8, + NDOF_BUTTON_9, + NDOF_BUTTON_10, + NDOF_BUTTON_NONE, // esc key + NDOF_BUTTON_NONE, // alt key + NDOF_BUTTON_NONE, // shift key + NDOF_BUTTON_NONE, // ctrl key + NDOF_BUTTON_ROTATE, + NDOF_BUTTON_PANZOOM, + NDOF_BUTTON_DOMINANT, + NDOF_BUTTON_PLUS, + NDOF_BUTTON_MINUS + }; + GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) : m_system(sys) - , m_deviceType(SpaceExplorer) // set it manually, until device detection code is in place + , m_deviceType(SpacePilot) // set it manually, until device detection code is in place , m_buttons(0) , m_motionTime(1000) // one full second (operators should filter out such large time deltas) , m_prevMotionTime(0) @@ -133,7 +168,9 @@ void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, bool press, GHOST_T data->action = press ? GHOST_kPress : GHOST_kRelease; data->button = button; - printf("sending %s %s\n", ndof_button_names[button], press ? "pressed" : "released"); + #ifdef DEBUG_NDOF_BUTTONS + printf("%s %s\n", ndof_button_names[button], press ? "pressed" : "released"); + #endif m_system.pushEvent(event); } @@ -143,6 +180,10 @@ void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key, bool press, GHOST_TUns64 ti GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp; GHOST_EventKey* event = new GHOST_EventKey(time, type, window, key); + #ifdef DEBUG_NDOF_BUTTONS + printf("keyboard %s\n", press ? "down" : "up"); + #endif + m_system.pushEvent(event); } @@ -150,6 +191,10 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 { GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); + #ifdef DEBUG_NDOF_BUTTONS + printf("button %d -> ", button_number); + #endif + switch (m_deviceType) { case SpaceNavigator: @@ -158,25 +203,22 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 case SpaceExplorer: switch (button_number) { - case 6: - sendKeyEvent(GHOST_kKeyEsc, press, time, window); - break; - case 7: - sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); - break; - case 8: - sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); - break; - case 9: - sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); - break; - default: - sendButtonEvent(SpaceExplorer_HID_map[button_number], press, time, window); + case 6: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; + case 7: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; + case 8: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; + case 9: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; + default: sendButtonEvent(SpaceExplorer_HID_map[button_number], press, time, window); } break; case SpacePilot: - printf("button %d %s\n", button_number, press ? "pressed" : "released"); - // sendButtonEvent(SpacePilot_HID_map[button_number], press, time, window); + switch (button_number) + { + case 22: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; + case 23: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; + case 24: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; + case 25: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; + default: sendButtonEvent(SpacePilot_HID_map[button_number], press, time, window); + } break; } @@ -231,8 +273,10 @@ bool GHOST_NDOFManager::sendMotionEvent() m_prevMotionTime = m_motionTime; + #ifdef DEBUG_NDOF_MOTION printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, data->dt); + #endif m_system.pushEvent(event); diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index eb04ca654ee..ab27fc32f84 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -29,6 +29,9 @@ // --- the following type definitions will find a home somewhere else once finished --- +// #define DEBUG_NDOF_MOTION +#define DEBUG_NDOF_BUTTONS + typedef enum { SpaceNavigator, SpaceExplorer, SpacePilot } NDOF_DeviceT; // NDOF device button event types diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 69ced683435..4548d6b34eb 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -841,40 +841,24 @@ bool GHOST_SystemWin32::processNDOF(/*GHOST_WindowWin32* window,*/ RAWINPUT cons { short t[3]; memcpy(t, data + 1, sizeof(t)); - // too much noise -- disable for now - printf("T: %+5d %+5d %+5d\n", t[0], t[1], t[2]); m_ndofManager->updateTranslation(t, getMilliSeconds()); // wariness of alignment issues prevents me from saying it this way: // m_ndofManager->updateTranslation((short*)(data + 1), getMilliSeconds()); - // though it probably (94.7%) works fine + // though it probably (94.7%) would work fine break; } case 2: // rotation { short r[3]; memcpy(r, data + 1, sizeof(r)); - printf("R: %+5d %+5d %+5d\n", r[0], r[1], r[2]); m_ndofManager->updateRotation(r, getMilliSeconds()); break; } case 3: // buttons { - unsigned buttons; - memcpy(&buttons, data + 1, sizeof(buttons)); - -// printf("buttons:"); -// if (buttons) -// { -// // work our way through the bit mask -// for (int i = 0; i < 16; ++i) -// if (buttons & (1 << i)) -// printf(" %d", i + 1); -// printf("\n"); -// } -// else -// printf(" none\n"); - - m_ndofManager->updateButtons(buttons, getMilliSeconds()); + int button_bits; + memcpy(&button_bits, data + 1, sizeof(button_bits)); + m_ndofManager->updateButtons(button_bits, getMilliSeconds()); break; } } -- cgit v1.2.3 From 18b5dac5cad91abf4787d7fd7a06029a02b6609d Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 16 Jun 2011 19:45:38 +0000 Subject: Standard views (front, top, etc.) work from buttons on SpaceExplorer and SpacePilotPro. Linux can now determine which NDOF device is plugged in. --- intern/ghost/intern/GHOST_NDOFManager.cpp | 14 +++--- intern/ghost/intern/GHOST_NDOFManager.h | 2 +- intern/ghost/intern/GHOST_NDOFManagerX11.cpp | 28 ++++++++++++ source/blender/editors/space_view3d/view3d_ops.c | 8 +++- source/blender/windowmanager/wm_event_types.h | 58 ++++++++++++++++-------- 5 files changed, 84 insertions(+), 26 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 20baa6f725e..5c2ca658fdb 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -97,7 +97,7 @@ static const NDOF_ButtonT SpaceExplorer_HID_map[] = NDOF_BUTTON_ROTATE }; -static const NDOF_ButtonT SpacePilot_HID_map[] = +static const NDOF_ButtonT SpacePilotPro_HID_map[] = { NDOF_BUTTON_MENU, NDOF_BUTTON_FIT, @@ -134,7 +134,7 @@ static const NDOF_ButtonT SpacePilot_HID_map[] = GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) : m_system(sys) - , m_deviceType(SpacePilot) // set it manually, until device detection code is in place + , m_deviceType(NDOF_UnknownDevice) // each platform needs its own device detection code , m_buttons(0) , m_motionTime(1000) // one full second (operators should filter out such large time deltas) , m_prevMotionTime(0) @@ -197,10 +197,10 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 switch (m_deviceType) { - case SpaceNavigator: + case NDOF_SpaceNavigator: sendButtonEvent(SpaceNavigator_HID_map[button_number], press, time, window); break; - case SpaceExplorer: + case NDOF_SpaceExplorer: switch (button_number) { case 6: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; @@ -210,16 +210,18 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 default: sendButtonEvent(SpaceExplorer_HID_map[button_number], press, time, window); } break; - case SpacePilot: + case NDOF_SpacePilotPro: switch (button_number) { case 22: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; case 23: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; case 24: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; case 25: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; - default: sendButtonEvent(SpacePilot_HID_map[button_number], press, time, window); + default: sendButtonEvent(SpacePilotPro_HID_map[button_number], press, time, window); } break; + case NDOF_UnknownDevice: + printf("button %d on unknown device (not sent)\n", button_number); } int mask = 1 << button_number; diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index ab27fc32f84..564b0f6f239 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -32,7 +32,7 @@ // #define DEBUG_NDOF_MOTION #define DEBUG_NDOF_BUTTONS -typedef enum { SpaceNavigator, SpaceExplorer, SpacePilot } NDOF_DeviceT; +typedef enum { NDOF_UnknownDevice, NDOF_SpaceNavigator, NDOF_SpaceExplorer, NDOF_SpacePilotPro } NDOF_DeviceT; // NDOF device button event types typedef enum { diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp index 99ee29d8a17..49372e8502d 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp @@ -33,6 +33,34 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys) if (spnav_open() != -1) { m_available = true; + + // determine exactly which device is plugged in + + #define MAX_LINE_LENGTH 100 + + // look for USB devices with Logitech's vendor ID + FILE* command_output = popen("lsusb -d 046d:","r"); + if (command_output) + { + char line[MAX_LINE_LENGTH] = {0}; + while (fgets(line, MAX_LINE_LENGTH, command_output)) + { + unsigned short vendor_id = 0, product_id = 0; + if (sscanf(line, "Bus %*d Device %*d: ID %hx:%hx", &vendor_id, &product_id) == 2) + { + // the following code will live in the base class + // once all platforms have device detection + switch (product_id) + { + case 0xc626: m_deviceType = NDOF_SpaceNavigator; break; + case 0xc627: m_deviceType = NDOF_SpaceExplorer; break; + case 0xc629: m_deviceType = NDOF_SpacePilotPro; break; + default: printf("unknown product ID: %04x\n", product_id); + } + } + } + pclose(command_output); + } } else { diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 3e99c6992d1..2dd560a6408 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -163,8 +163,14 @@ void view3d_keymap(wmKeyConfig *keyconf) 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); + WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BACK, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BACK); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_LEFT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_LEFT); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_RIGHT); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_TOP); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BOTTOM, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BOTTOM); /* numpad view hotkeys*/ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD0, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_CAMERA); diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 748f5018e1a..ed500ccd5c5 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -79,25 +79,47 @@ #define INBETWEEN_MOUSEMOVE 17 /* NDOF (from SpaceNavigator & friends) */ -#define NDOF_MOTION 0x12 +#define NDOF_MOTION 0x12 // keep in sync with GHOST_NDOFManager.h enum { - NDOF_BUTTON_NONE = NDOF_MOTION, /* never sent, used internally */ - NDOF_BUTTON1, - NDOF_BUTTON2/*, the following buttons will be supported soon... - NDOF_BUTTON3, and possibly get meaningful names - 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*/ + // used internally, never sent + NDOF_BUTTON_NONE = NDOF_MOTION, + // these two are available from any 3Dconnexion device + NDOF_BUTTON_MENU, + NDOF_BUTTON_FIT, + // standard views + NDOF_BUTTON_TOP, + NDOF_BUTTON_BOTTOM, + NDOF_BUTTON_LEFT, + NDOF_BUTTON_RIGHT, + NDOF_BUTTON_FRONT, + NDOF_BUTTON_BACK, + // more views + NDOF_BUTTON_ISO1, + NDOF_BUTTON_ISO2, + // 90 degree rotations + NDOF_BUTTON_ROLL_CW, + NDOF_BUTTON_ROLL_CCW, + NDOF_BUTTON_SPIN_CW, + NDOF_BUTTON_SPIN_CCW, + NDOF_BUTTON_TILT_CW, + NDOF_BUTTON_TILT_CCW, + // device control + NDOF_BUTTON_ROTATE, + NDOF_BUTTON_PANZOOM, + NDOF_BUTTON_DOMINANT, + NDOF_BUTTON_PLUS, + NDOF_BUTTON_MINUS, + // general-purpose buttons + NDOF_BUTTON_1, + NDOF_BUTTON_2, + NDOF_BUTTON_3, + NDOF_BUTTON_4, + NDOF_BUTTON_5, + NDOF_BUTTON_6, + NDOF_BUTTON_7, + NDOF_BUTTON_8, + NDOF_BUTTON_9, + NDOF_BUTTON_10, }; -- cgit v1.2.3 From b13e12a7bbbc35e94cd8ad262f6ffe90196593f3 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 17 Jun 2011 16:10:06 +0000 Subject: NDOF device detection on Mac -- phase 1 --- intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 42 ++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index 75a96556ff1..23848c80803 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -29,17 +29,33 @@ extern "C" { #include } -static void SpaceNavAdded(io_connect_t connection) +static void NDOF_DeviceAdded(io_connect_t connection) { - printf("SpaceNav added\n"); // change these: printf --> informational reports + printf("ndof device added\n"); // change these: printf --> informational reports + + // determine exactly which device is plugged in + ConnexionDevicePrefs p; + ConnexionGetCurrentDevicePrefs(kDevID_AnyDevice, &p); + printf("device type %d: %s\n", p.deviceID, + p.deviceID == kDevID_SpaceNavigator ? "SpaceNavigator" : + p.deviceID == kDevID_SpaceNavigatorNB ? "SpaceNavigator for Notebooks" : + p.deviceID == kDevID_SpaceExplorer ? "SpaceExplorer" : + "unknown"); + + // try a more "standard" way + int result = 0; + ConnexionControl(kConnexionCtlGetDeviceID, 0, &result); + unsigned short vendorID = result >> 16; + unsigned short productID = result & 0xffff; + printf("vendor %04hx:%04hx product\n", vendorID, productID); } -static void SpaceNavRemoved(io_connect_t connection) +static void NDOF_DeviceRemoved(io_connect_t connection) { - printf("SpaceNav removed\n"); + printf("ndof device removed\n"); } -static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void* messageArgument) +static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, void* messageArgument) { GHOST_SystemCocoa* system = (GHOST_SystemCocoa*) GHOST_ISystem::getSystem(); GHOST_NDOFManager* manager = system->getNDOFManager(); @@ -60,12 +76,24 @@ static void SpaceNavEvent(io_connect_t connection, natural_t messageType, void* break; case kConnexionCmdHandleButtons: + + // s->buttons field has only 16 bits, not enough for SpacePilotPro + // look at raw USB report for more button bits + printf("button bits = ["); + for (int i = 0; i < 8; ++i) + printf("%02x", s->report[i]); + printf("]\n"); + manager->updateButtons(s->buttons, now); system->notifyExternalEventProcessed(); break; + case kConnexionCmdAppSpecific: + printf("app-specific command: param=%hd value=%d\n", s->param, s->value); + break; + default: - printf("device state command %d\n", s->command); + printf(" mystery command %d\n", s->command); } break; } @@ -87,7 +115,7 @@ GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) { if (available()) { - OSErr error = InstallConnexionHandlers(SpaceNavEvent, SpaceNavAdded, SpaceNavRemoved); + OSErr error = InstallConnexionHandlers(NDOF_DeviceEvent, NDOF_DeviceAdded, NDOF_DeviceRemoved); if (error) { printf(" error = %d\n", error); -- cgit v1.2.3 From e7591d177bc054c429b026d05c4df3fa65b8fb32 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 17 Jun 2011 19:48:26 +0000 Subject: finished Mac NDOF device detection, moved core device ID to base NDOFManager, clarified info/error messages --- intern/ghost/intern/GHOST_NDOFManager.cpp | 24 ++++++++++-- intern/ghost/intern/GHOST_NDOFManager.h | 17 ++++++-- intern/ghost/intern/GHOST_NDOFManagerCocoa.h | 2 +- intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 56 ++++++++++++++++----------- intern/ghost/intern/GHOST_NDOFManagerX11.cpp | 16 ++------ intern/ghost/intern/GHOST_NDOFManagerX11.h | 3 ++ 6 files changed, 74 insertions(+), 44 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 5c2ca658fdb..a2b9a53a51c 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -146,6 +146,24 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) memset(m_rotation, 0, sizeof(m_rotation)); } +void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short product_id) + { + switch (vendor_id) + { + case 0x046d: // Logitech (3Dconnexion) + switch (product_id) + { + case 0xc626: m_deviceType = NDOF_SpaceNavigator; break; + case 0xc627: m_deviceType = NDOF_SpaceExplorer; break; + case 0xc629: m_deviceType = NDOF_SpacePilotPro; break; + default: printf("ndof: unknown Logitech product %04hx\n", product_id); + } + break; + default: + printf("ndof: unknown vendor %04hx\n", vendor_id); + } + } + void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time) { memcpy(m_translation, t, sizeof(m_translation)); @@ -192,7 +210,7 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); #ifdef DEBUG_NDOF_BUTTONS - printf("button %d -> ", button_number); + printf("ndof: button %d -> ", button_number); #endif switch (m_deviceType) @@ -221,7 +239,7 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 } break; case NDOF_UnknownDevice: - printf("button %d on unknown device (not sent)\n", button_number); + printf("ndof: button %d on unknown device (ignoring)\n", button_number); } int mask = 1 << button_number; @@ -276,7 +294,7 @@ bool GHOST_NDOFManager::sendMotionEvent() m_prevMotionTime = m_motionTime; #ifdef DEBUG_NDOF_MOTION - printf("sending T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", + printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, data->dt); #endif diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 564b0f6f239..846b10fb454 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -88,22 +88,31 @@ public: // does not imply that a device is plugged in or being used virtual bool available() = 0; - // the latest raw data from the device + // each platform's device detection should call this + // use standard USB/HID identifiers + void setDevice(unsigned short vendor_id, unsigned short product_id); + + // the latest raw axis data from the device void updateTranslation(short t[3], GHOST_TUns64 time); void updateRotation(short r[3], GHOST_TUns64 time); - // send events immediately for changed buttons + + // the latest raw button data from the device + // use HID button encoding (not NDOF_ButtonT) void updateButton(int button_number, bool press, GHOST_TUns64 time); void updateButtons(int button_bits, GHOST_TUns64 time); + // NDOFButton events are sent immediately - // processes most recent raw data into an NDOFMotion event and sends it + // processes and sends most recent raw data as an NDOFMotion event // returns whether an event was sent bool sendMotionEvent(); +protected: + private: void sendButtonEvent(NDOF_ButtonT, bool press, GHOST_TUns64 time, GHOST_IWindow*); void sendKeyEvent(GHOST_TKey, bool press, GHOST_TUns64 time, GHOST_IWindow*); -protected: + GHOST_System& m_system; NDOF_DeviceT m_deviceType; diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h index efe840bab4a..d8711e915f6 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h @@ -26,7 +26,7 @@ #include "GHOST_NDOFManager.h" -// Event capture is handled within the NDOFManager on Macintosh, +// Event capture is handled within the NDOF manager on Macintosh, // so there's no need for SystemCocoa to look for them. class GHOST_NDOFManagerCocoa : public GHOST_NDOFManager diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index 23848c80803..b92e8112c02 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -29,11 +29,15 @@ extern "C" { #include } +// static functions need to talk to these objects: +static GHOST_SystemCocoa* ghost_system = NULL; +static GHOST_NDOFManager* ndof_manager = NULL; + static void NDOF_DeviceAdded(io_connect_t connection) { - printf("ndof device added\n"); // change these: printf --> informational reports + printf("ndof: device added\n"); // change these: printf --> informational reports - // determine exactly which device is plugged in +#if 0 // device preferences will be useful soon, but not for hardware model detection ConnexionDevicePrefs p; ConnexionGetCurrentDevicePrefs(kDevID_AnyDevice, &p); printf("device type %d: %s\n", p.deviceID, @@ -41,72 +45,72 @@ static void NDOF_DeviceAdded(io_connect_t connection) p.deviceID == kDevID_SpaceNavigatorNB ? "SpaceNavigator for Notebooks" : p.deviceID == kDevID_SpaceExplorer ? "SpaceExplorer" : "unknown"); +#endif - // try a more "standard" way + // determine exactly which device is plugged in int result = 0; ConnexionControl(kConnexionCtlGetDeviceID, 0, &result); unsigned short vendorID = result >> 16; unsigned short productID = result & 0xffff; - printf("vendor %04hx:%04hx product\n", vendorID, productID); + + ndof_manager->setDevice(vendorID, productID); } static void NDOF_DeviceRemoved(io_connect_t connection) { - printf("ndof device removed\n"); + printf("ndof: device removed\n"); } static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, void* messageArgument) { - GHOST_SystemCocoa* system = (GHOST_SystemCocoa*) GHOST_ISystem::getSystem(); - GHOST_NDOFManager* manager = system->getNDOFManager(); switch (messageType) { case kConnexionMsgDeviceState: { ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument; - GHOST_TUns64 now = system->getMilliSeconds(); + GHOST_TUns64 now = ghost_system->getMilliSeconds(); switch (s->command) { case kConnexionCmdHandleAxis: - manager->updateTranslation(s->axis, now); - manager->updateRotation(s->axis + 3, now); - system->notifyExternalEventProcessed(); + ndof_manager->updateTranslation(s->axis, now); + ndof_manager->updateRotation(s->axis + 3, now); + ghost_system->notifyExternalEventProcessed(); break; case kConnexionCmdHandleButtons: // s->buttons field has only 16 bits, not enough for SpacePilotPro // look at raw USB report for more button bits - printf("button bits = ["); + printf("ndof: button bits = ["); for (int i = 0; i < 8; ++i) printf("%02x", s->report[i]); printf("]\n"); - manager->updateButtons(s->buttons, now); - system->notifyExternalEventProcessed(); + ndof_manager->updateButtons(s->buttons, now); + ghost_system->notifyExternalEventProcessed(); break; case kConnexionCmdAppSpecific: - printf("app-specific command: param=%hd value=%d\n", s->param, s->value); + printf("ndof: app-specific command, param = %hd, value = %d\n", s->param, s->value); break; default: - printf(" mystery command %d\n", s->command); + printf("ndof: mystery device command %d\n", s->command); } break; } case kConnexionMsgPrefsChanged: - printf("prefs changed\n"); // this includes app switches + printf("ndof: prefs changed\n"); // this includes app switches break; case kConnexionMsgDoAction: - printf("do action\n"); // no idea what this means + printf("ndof: do action\n"); // no idea what this means // 'calibrate device' in System Prefs sends this // 3Dx header file says to ignore these break; default: - printf(" mystery event\n"); + printf("ndof: mystery event %d\n", messageType); } } @@ -115,10 +119,14 @@ GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) { if (available()) { + // give static functions something to talk to: + ghost_system = dynamic_cast(&sys); + ndof_manager = this; + OSErr error = InstallConnexionHandlers(NDOF_DeviceEvent, NDOF_DeviceAdded, NDOF_DeviceRemoved); if (error) { - printf(" error = %d\n", error); + printf("ndof: error %d while installing handlers\n", error); return; } @@ -126,12 +134,12 @@ GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pblender", kConnexionClientModeTakeOver, kConnexionMaskAll); - printf("client id = %d\n", m_clientID); + printf("ndof: client id = %d\n", m_clientID); } else { - printf(" SpaceNav driver not found\n"); - // This isn't a hard error, just means the user doesn't have a SpaceNavigator. + printf("ndof: 3Dx driver not found\n"); + // This isn't a hard error, just means the user doesn't have a 3D mouse. } } @@ -139,6 +147,8 @@ GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() { UnregisterConnexionClient(m_clientID); CleanupConnexionHandlers(); + ghost_system = NULL; + ndof_manager = NULL; } bool GHOST_NDOFManagerCocoa::available() diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp index 49372e8502d..40a0a75ab82 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp @@ -47,26 +47,16 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys) { unsigned short vendor_id = 0, product_id = 0; if (sscanf(line, "Bus %*d Device %*d: ID %hx:%hx", &vendor_id, &product_id) == 2) - { - // the following code will live in the base class - // once all platforms have device detection - switch (product_id) - { - case 0xc626: m_deviceType = NDOF_SpaceNavigator; break; - case 0xc627: m_deviceType = NDOF_SpaceExplorer; break; - case 0xc629: m_deviceType = NDOF_SpacePilotPro; break; - default: printf("unknown product ID: %04x\n", product_id); - } - } + setDevice(vendor_id, product_id); } pclose(command_output); } } else { - printf(" SpaceNav driver not found\n"); - // This isn't a hard error, just means the user doesn't have a SpaceNavigator. m_available = false; + printf("ndof: spacenavd not found\n"); + // This isn't a hard error, just means the user doesn't have a 3D mouse. } } diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.h b/intern/ghost/intern/GHOST_NDOFManagerX11.h index cf6f1d00cba..def311d51e2 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.h +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.h @@ -26,6 +26,9 @@ #include "GHOST_NDOFManager.h" +// Event capture is handled within the NDOF manager on Linux, +// so there's no need for SystemX11 to look for them. + class GHOST_NDOFManagerX11 : public GHOST_NDOFManager { public: -- cgit v1.2.3 From d53801e8f63074ee9d9d2cd926491d70b5d62226 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 17 Jun 2011 21:04:23 +0000 Subject: updated Mac code to work with latest 3Dx beta driver -- all buttons work now --- intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 43 +++++++++++++++------------ 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index b92e8112c02..6e392a7c2f8 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -33,18 +33,17 @@ extern "C" { static GHOST_SystemCocoa* ghost_system = NULL; static GHOST_NDOFManager* ndof_manager = NULL; +// 3Dconnexion drivers before 10.x are "old" +// not all buttons will work +static bool has_old_driver = true; + static void NDOF_DeviceAdded(io_connect_t connection) { printf("ndof: device added\n"); // change these: printf --> informational reports -#if 0 // device preferences will be useful soon, but not for hardware model detection +#if 0 // device preferences will be useful soon ConnexionDevicePrefs p; ConnexionGetCurrentDevicePrefs(kDevID_AnyDevice, &p); - printf("device type %d: %s\n", p.deviceID, - p.deviceID == kDevID_SpaceNavigator ? "SpaceNavigator" : - p.deviceID == kDevID_SpaceNavigatorNB ? "SpaceNavigator for Notebooks" : - p.deviceID == kDevID_SpaceExplorer ? "SpaceExplorer" : - "unknown"); #endif // determine exactly which device is plugged in @@ -80,18 +79,12 @@ static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, voi break; case kConnexionCmdHandleButtons: - - // s->buttons field has only 16 bits, not enough for SpacePilotPro - // look at raw USB report for more button bits - printf("ndof: button bits = ["); - for (int i = 0; i < 8; ++i) - printf("%02x", s->report[i]); - printf("]\n"); - - ndof_manager->updateButtons(s->buttons, now); + { + int button_bits = has_old_driver ? s->buttons8 : s->buttons; + ndof_manager->updateButtons(button_bits, now); ghost_system->notifyExternalEventProcessed(); break; - + } case kConnexionCmdAppSpecific: printf("ndof: app-specific command, param = %hd, value = %d\n", s->param, s->value); break; @@ -104,9 +97,13 @@ static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, voi case kConnexionMsgPrefsChanged: printf("ndof: prefs changed\n"); // this includes app switches break; - case kConnexionMsgDoAction: - printf("ndof: do action\n"); // no idea what this means - // 'calibrate device' in System Prefs sends this + case kConnexionMsgCalibrateDevice: + printf("ndof: calibrate\n"); // but what should blender do? + break; + case kConnexionMsgDoMapping: + printf("ndof: driver did something\n"); + // sent when the driver itself consumes an NDOF event + // and performs whatever action is set in user prefs // 3Dx header file says to ignore these break; default: @@ -135,6 +132,14 @@ GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) kConnexionClientModeTakeOver, kConnexionMaskAll); printf("ndof: client id = %d\n", m_clientID); + + if (SetConnexionClientButtonMask != NULL) + { + has_old_driver = false; + SetConnexionClientButtonMask(m_clientID, kConnexionMaskAllButtons); + } + else + printf("ndof: old 3Dx driver installed, some buttons may not work\n"); } else { -- cgit v1.2.3 From 56e312a88e3a8da8c7c74cf69defd9f074c4b5b9 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 17 Jun 2011 22:19:16 +0000 Subject: filled out USB product IDs for all 3Dconnexion devices --- intern/ghost/intern/GHOST_NDOFManager.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index a2b9a53a51c..8cd5728601d 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -26,7 +26,7 @@ #include "GHOST_EventKey.h" #include "GHOST_WindowManager.h" #include // for memory functions -#include // for debug tracing +#include // for error/info reporting #ifdef DEBUG_NDOF_BUTTONS static const char* ndof_button_names[] = { @@ -150,12 +150,19 @@ void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ { switch (vendor_id) { - case 0x046d: // Logitech (3Dconnexion) + case 0x046D: // Logitech (3Dconnexion) switch (product_id) { - case 0xc626: m_deviceType = NDOF_SpaceNavigator; break; - case 0xc627: m_deviceType = NDOF_SpaceExplorer; break; - case 0xc629: m_deviceType = NDOF_SpacePilotPro; break; + // -- current devices -- + case 0xC626: m_deviceType = NDOF_SpaceNavigator; break; + case 0xC628: m_deviceType = NDOF_SpaceNavigator; /* for Notebooks */ break; + case 0xC627: m_deviceType = NDOF_SpaceExplorer; break; + case 0xC629: m_deviceType = NDOF_SpacePilotPro; break; + + // -- older devices -- + case 0xC623: puts("ndof: SpaceTraveler not supported, please file a bug report"); break; + case 0xC625: puts("ndof: SpacePilot not supported, please file a bug report"); break; + default: printf("ndof: unknown Logitech product %04hx\n", product_id); } break; -- cgit v1.2.3 From ebc2f7064d6d55d8760427529a520d044ea9cce1 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 17 Jun 2011 22:45:33 +0000 Subject: tiny fix for Linux --- intern/ghost/intern/GHOST_NDOFManager.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 846b10fb454..9e4ceab2d55 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -107,14 +107,13 @@ public: bool sendMotionEvent(); protected: + GHOST_System& m_system; private: void sendButtonEvent(NDOF_ButtonT, bool press, GHOST_TUns64 time, GHOST_IWindow*); void sendKeyEvent(GHOST_TKey, bool press, GHOST_TUns64 time, GHOST_IWindow*); - GHOST_System& m_system; - NDOF_DeviceT m_deviceType; short m_translation[3]; -- cgit v1.2.3 From 598c54f0e916b9f5dc6d39bf9827bfd7f98bbec3 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 18 Jun 2011 16:50:54 +0000 Subject: ndof device detection on Windows, safer button handling --- intern/ghost/intern/GHOST_NDOFManager.cpp | 36 ++++++++++++++++++---- intern/ghost/intern/GHOST_NDOFManager.h | 2 ++ intern/ghost/intern/GHOST_SystemWin32.cpp | 50 +++++++++++++++++++++++++------ intern/ghost/intern/GHOST_SystemWin32.h | 3 +- 4 files changed, 74 insertions(+), 17 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 8cd5728601d..3bb1d990f28 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -134,7 +134,9 @@ static const NDOF_ButtonT SpacePilotPro_HID_map[] = GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) : m_system(sys) - , m_deviceType(NDOF_UnknownDevice) // each platform needs its own device detection code + , m_deviceType(NDOF_UnknownDevice) // each platform has its own device detection code + , m_buttonCount(0) + , m_buttonMask(0) , m_buttons(0) , m_motionTime(1000) // one full second (operators should filter out such large time deltas) , m_prevMotionTime(0) @@ -154,10 +156,26 @@ void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ switch (product_id) { // -- current devices -- - case 0xC626: m_deviceType = NDOF_SpaceNavigator; break; - case 0xC628: m_deviceType = NDOF_SpaceNavigator; /* for Notebooks */ break; - case 0xC627: m_deviceType = NDOF_SpaceExplorer; break; - case 0xC629: m_deviceType = NDOF_SpacePilotPro; break; + case 0xC626: + m_deviceType = NDOF_SpaceNavigator; + m_buttonCount = 2; +// m_buttonMask = 0x3; // 2 buttons + break; + case 0xC628: + m_deviceType = NDOF_SpaceNavigator; // for Notebooks + m_buttonCount = 2; +// m_buttonMask = 0x3; // 2 buttons + break; + case 0xC627: + m_deviceType = NDOF_SpaceExplorer; + m_buttonCount = 15; +// m_buttonMask = 0x7FFF; // 15 buttons + break; + case 0xC629: + m_deviceType = NDOF_SpacePilotPro; + m_buttonCount = 29; +// m_buttonMask = 0x1FFFFFFF; // 29 buttons + break; // -- older devices -- case 0xC623: puts("ndof: SpaceTraveler not supported, please file a bug report"); break; @@ -169,6 +187,9 @@ void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ default: printf("ndof: unknown vendor %04hx\n", vendor_id); } + + m_buttonMask = ~(-1 << m_buttonCount); + printf("ndof: %d buttons -> %X\n", m_buttonCount, m_buttonMask); } void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time) @@ -217,7 +238,8 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); #ifdef DEBUG_NDOF_BUTTONS - printf("ndof: button %d -> ", button_number); + if (m_deviceType != NDOF_UnknownDevice) + printf("ndof: button %d -> ", button_number); #endif switch (m_deviceType) @@ -258,6 +280,8 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time) { + button_bits &= m_buttonMask; // discard any "garbage" bits + int diff = m_buttons ^ button_bits; for (int button_number = 0; button_number <= 31; ++button_number) diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 9e4ceab2d55..1a25c60f456 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -115,6 +115,8 @@ private: NDOF_DeviceT m_deviceType; + int m_buttonCount; + int m_buttonMask; short m_translation[3]; short m_rotation[3]; diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 4548d6b34eb..76508158a14 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -818,9 +818,28 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax) minmax->ptMinTrackSize.y=240; } -bool GHOST_SystemWin32::processNDOF(/*GHOST_WindowWin32* window,*/ RAWINPUT const& raw) +bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) { bool eventSent = false; + GHOST_TUns64 now = getMilliSeconds(); + + static bool firstEvent = true; + if (firstEvent) + { // determine exactly which device is plugged in + RID_DEVICE_INFO info; + unsigned infoSize = sizeof(RID_DEVICE_INFO); + info.cbSize = infoSize; + + GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize); + if (info.dwType == RIM_TYPEHID) + { + printf("hardware ID = %08X:%08X\n", info.hid.dwVendorId, info.hid.dwProductId); + m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId); + } + else puts(" not a HID device... mouse/kb perhaps?"); + + firstEvent = false; + } // The NDOF manager sends button changes immediately, and *pretends* to // send motion. Mark as 'sent' so motion will always get dispatched. @@ -839,26 +858,39 @@ bool GHOST_SystemWin32::processNDOF(/*GHOST_WindowWin32* window,*/ RAWINPUT cons { case 1: // translation { - short t[3]; - memcpy(t, data + 1, sizeof(t)); - m_ndofManager->updateTranslation(t, getMilliSeconds()); + short axis_data[3]; + memcpy(axis_data, data + 1, sizeof(axis_data)); + m_ndofManager->updateTranslation(axis_data, now); // wariness of alignment issues prevents me from saying it this way: // m_ndofManager->updateTranslation((short*)(data + 1), getMilliSeconds()); // though it probably (94.7%) would work fine + + if (raw.data.hid.dwSizeHid == 13) + { // this report also includes rotation + puts("ndof: combined T + R"); + memcpy(axis_data, data + 7, sizeof(axis_data)); + m_ndofManager->updateRotation(axis_data, now); + } break; } case 2: // rotation { - short r[3]; - memcpy(r, data + 1, sizeof(r)); - m_ndofManager->updateRotation(r, getMilliSeconds()); + short axis_data[3]; + memcpy(axis_data, data + 1, sizeof(axis_data)); + m_ndofManager->updateRotation(axis_data, now); break; } case 3: // buttons { + // I'm getting garbage bits -- examine whole report: + printf("ndof: HID report for buttons ["); + for (int i = 0; i < raw.data.hid.dwSizeHid; ++i) + printf(" %02X", data[i]); + printf(" ]\n"); + int button_bits; memcpy(&button_bits, data + 1, sizeof(button_bits)); - m_ndofManager->updateButtons(button_bits, getMilliSeconds()); + m_ndofManager->updateButtons(button_bits, now); break; } } @@ -910,7 +942,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, } break; case RIM_TYPEHID: - if (system->processNDOF(/*window,*/ raw)) + if (system->processNDOF(raw)) eventHandled = true; break; } diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index cfb88bace10..dae8bf9a31a 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -397,11 +397,10 @@ protected: * Handles Motion and Button events from a SpaceNavigator or related device. * Instead of returning an event object, this function communicates directly * with the GHOST_NDOFManager. - * @param window The window receiving the event (the active window). * @param raw RawInput structure with detailed info about the NDOF event * @return Whether an event was generated and sent. */ - bool processNDOF(/*GHOST_IWindow *window,*/ RAWINPUT const& raw); + bool processNDOF(RAWINPUT const& raw); /** * Returns the local state of the modifier keys (from the message queue). -- cgit v1.2.3 From 412da91a472deeb62574e35908b349b952b4a109 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 18 Jun 2011 19:40:30 +0000 Subject: SpacePilotPro has 31 buttons, not 29 -- '+' and '-' work again --- intern/ghost/intern/GHOST_NDOFManager.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 3bb1d990f28..b8c1d13679d 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -159,22 +159,18 @@ void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ case 0xC626: m_deviceType = NDOF_SpaceNavigator; m_buttonCount = 2; -// m_buttonMask = 0x3; // 2 buttons break; case 0xC628: m_deviceType = NDOF_SpaceNavigator; // for Notebooks m_buttonCount = 2; -// m_buttonMask = 0x3; // 2 buttons break; case 0xC627: m_deviceType = NDOF_SpaceExplorer; m_buttonCount = 15; -// m_buttonMask = 0x7FFF; // 15 buttons break; case 0xC629: m_deviceType = NDOF_SpacePilotPro; - m_buttonCount = 29; -// m_buttonMask = 0x1FFFFFFF; // 29 buttons + m_buttonCount = 31; break; // -- older devices -- -- cgit v1.2.3 From e46e2d9d5400729da2980cc5b1f2e24df9207c5a Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 18 Jun 2011 20:30:09 +0000 Subject: resolved collision among WM event types, ndof no longer encroaches on keyboard turf --- source/blender/windowmanager/wm_event_types.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index ed500ccd5c5..210dd902b99 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -78,8 +78,13 @@ #define WHEELOUTMOUSE 13 #define INBETWEEN_MOUSEMOVE 17 -/* NDOF (from SpaceNavigator & friends) */ -#define NDOF_MOTION 0x12 // keep in sync with GHOST_NDOFManager.h + +/* NDOF (from SpaceNavigator & friends) + These should be kept in sync with GHOST_NDOFManager.h + Ordering matters, exact values do not. */ + +#define NDOF_MOTION 400 + enum { // used internally, never sent NDOF_BUTTON_NONE = NDOF_MOTION, -- cgit v1.2.3 From 85051eff69cdd9ea535fac207c48340064518aba Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 18 Jun 2011 20:32:14 +0000 Subject: disabled debug logging now that a workaround is in place (Win32 ndof buttons) --- intern/ghost/intern/GHOST_SystemWin32.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 76508158a14..71be69bb9fb 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -833,7 +833,7 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize); if (info.dwType == RIM_TYPEHID) { - printf("hardware ID = %08X:%08X\n", info.hid.dwVendorId, info.hid.dwProductId); + // printf("hardware ID = %04X:%04X\n", info.hid.dwVendorId, info.hid.dwProductId); m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId); } else puts(" not a HID device... mouse/kb perhaps?"); @@ -882,11 +882,13 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) } case 3: // buttons { + #if 0 // I'm getting garbage bits -- examine whole report: printf("ndof: HID report for buttons ["); for (int i = 0; i < raw.data.hid.dwSizeHid; ++i) printf(" %02X", data[i]); printf(" ]\n"); + #endif int button_bits; memcpy(&button_bits, data + 1, sizeof(button_bits)); -- cgit v1.2.3 From 015b0ea00afc4f12be5fc830152930cd9bbb6dac Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 20 Jun 2011 01:54:49 +0000 Subject: small fix to turntable mode, first attempt at trackball code, ndof now respects view locking and updates 'User Persp' etc. --- intern/ghost/intern/GHOST_NDOFManager.cpp | 9 +- source/blender/editors/space_view3d/view3d_edit.c | 110 +++++++++++++++------- 2 files changed, 85 insertions(+), 34 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index b8c1d13679d..2ee87aee412 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -175,7 +175,9 @@ void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ // -- older devices -- case 0xC623: puts("ndof: SpaceTraveler not supported, please file a bug report"); break; + // no buttons? case 0xC625: puts("ndof: SpacePilot not supported, please file a bug report"); break; + // 21 buttons default: printf("ndof: unknown Logitech product %04hx\n", product_id); } @@ -185,7 +187,10 @@ void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ } m_buttonMask = ~(-1 << m_buttonCount); - printf("ndof: %d buttons -> %X\n", m_buttonCount, m_buttonMask); + + #ifdef DEBUG_NDOF_BUTTONS + printf("ndof: %d buttons -> hex:%X\n", m_buttonCount, m_buttonMask); + #endif } void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time) @@ -312,7 +317,7 @@ bool GHOST_NDOFManager::sendMotionEvent() data->ty = scale * m_translation[1]; data->tz = scale * m_translation[2]; - data->rx = scale * m_rotation[0]; + data->rx = -scale * m_rotation[0]; data->ry = scale * m_rotation[1]; data->rz = scale * m_rotation[2]; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 76d595c275b..d1be99ce7ee 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -954,46 +954,92 @@ 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); - - /* 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; + float sensitivity = 1.f; /* ooh, magic number! + const float sensitivity = 0.035; /* ooh, magic number! + there will be several of these as interactions get tuned */ + float dt = ndof->dt; if (dt > 0.25f) /* this is probably the first event for this motion, so set dt to something reasonable */ + /* TODO: replace such guesswork with a flag or field from the NDOF manager */ dt = 0.0125f; - /* 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); + RegionView3D* rv3d = CTX_wm_region_view3d(C); - /* 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); + int /* bool */ has_rotation = rv3d->viewlock != RV3D_LOCKED && (ndof->rx || ndof->ry || ndof->rz); + if (has_rotation) + rv3d->view = RV3D_VIEW_USER; + + if (has_rotation) { + if (U.flag & USER_TRACKBALL) { + /* TODO: write trackball code! */ + + float axis[3] = {ndof->rx, ndof->ry, ndof->rz}; + float angle = sensitivity * dt * ndof_to_angle_axis(axis, axis); + float rotation[4], rotationconj[4]; + float view[4], viewconj[4]; + + // convert to quaternion + axis_angle_to_quat(rotation, axis, angle); + + // extract rotation component of viewquat + copy_qt_qt(view, rv3d->viewquat); + invert_qt(view); + normalize_qt(view); + copy_qt_qt(viewconj, view); + conjugate_qt(viewconj); + + // transform device rotation into view's frame of reference + // rotation(view) = view * rotation(world) * viewconj + mul_qt_qtqt(rotation, rotation, viewconj); + mul_qt_qtqt(rotation, view, rotation); + + // apply rotation to obtain new viewpoint +// copy_qt_qt(rotationconj, rotation); +// conjugate_qt(rotationconj); +// mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotationconj); +// mul_qt_qtqt(rv3d->viewquat, rotation, rv3d->viewquat); + mul_qt_qtqt(rv3d->viewquat, rotation, rv3d->viewquat); + + // this is *close* to trackball behavior + // rotation axis needs to remain fixed relative to viewpoint, not world coordinates + + ED_region_tag_redraw(CTX_wm_region(C)); + + } else { + /* 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}; + + /* 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 * dt * 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 * dt * 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)); + } + } - ED_region_tag_redraw(CTX_wm_region(C)); return OPERATOR_FINISHED; - } +} // Tom's version #if 0 -- cgit v1.2.3 From 0faeffb8a57493b6ccebc87decfed54c51152af0 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Mon, 20 Jun 2011 13:04:11 +0000 Subject: Compile fix. Note that var introduction must happen at start of code block. --- source/blender/editors/space_view3d/view3d_edit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index d1be99ce7ee..d506c4a5636 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -952,11 +952,13 @@ float ndof_to_angle_axis(const float ndof[3], float axis[3]) // Mike's version static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) { + RegionView3D* rv3d = CTX_wm_region_view3d(C); wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; float sensitivity = 1.f; /* ooh, magic number! const float sensitivity = 0.035; /* ooh, magic number! there will be several of these as interactions get tuned */ + int /* bool */ has_rotation = rv3d->viewlock != RV3D_LOCKED && (ndof->rx || ndof->ry || ndof->rz); float dt = ndof->dt; if (dt > 0.25f) @@ -964,9 +966,7 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) /* TODO: replace such guesswork with a flag or field from the NDOF manager */ dt = 0.0125f; - RegionView3D* rv3d = CTX_wm_region_view3d(C); - int /* bool */ has_rotation = rv3d->viewlock != RV3D_LOCKED && (ndof->rx || ndof->ry || ndof->rz); if (has_rotation) rv3d->view = RV3D_VIEW_USER; -- cgit v1.2.3 From 4030f82aadec55add812043a355b4bd11210c10c Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 20 Jun 2011 21:34:23 +0000 Subject: ndof trackball works... somehow --- source/blender/editors/space_view3d/view3d_edit.c | 75 +++++++++++++---------- 1 file changed, 43 insertions(+), 32 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index d506c4a5636..048742fa392 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -949,6 +949,25 @@ float ndof_to_angle_axis(const float ndof[3], float axis[3]) return angular_velocity; } +void ndof_to_quat(wmNDOFMotionData* ndof, float q[4]) + { + const float x = ndof->rx; + const float y = ndof->ry; + const float z = ndof->rz; + + float angular_velocity = sqrtf(x*x + y*y + z*z); + float angle = ndof->dt * angular_velocity; + + // combined scaling factor -- normalize axis while converting to quaternion + float scale = sin(0.5f * angle) / angular_velocity; + + // convert axis-angle to quaternion + q[0] = cos(0.5f * angle); + q[1] = scale * x; + q[2] = scale * y; + q[3] = scale * z; + } + // Mike's version static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) { @@ -964,7 +983,7 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) if (dt > 0.25f) /* this is probably the first event for this motion, so set dt to something reasonable */ /* TODO: replace such guesswork with a flag or field from the NDOF manager */ - dt = 0.0125f; + ndof->dt = dt = 0.0125f; if (has_rotation) @@ -972,37 +991,29 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) if (has_rotation) { if (U.flag & USER_TRACKBALL) { - /* TODO: write trackball code! */ - - float axis[3] = {ndof->rx, ndof->ry, ndof->rz}; - float angle = sensitivity * dt * ndof_to_angle_axis(axis, axis); - float rotation[4], rotationconj[4]; - float view[4], viewconj[4]; - - // convert to quaternion - axis_angle_to_quat(rotation, axis, angle); - - // extract rotation component of viewquat - copy_qt_qt(view, rv3d->viewquat); - invert_qt(view); - normalize_qt(view); - copy_qt_qt(viewconj, view); - conjugate_qt(viewconj); - - // transform device rotation into view's frame of reference - // rotation(view) = view * rotation(world) * viewconj - mul_qt_qtqt(rotation, rotation, viewconj); - mul_qt_qtqt(rotation, view, rotation); - - // apply rotation to obtain new viewpoint -// copy_qt_qt(rotationconj, rotation); -// conjugate_qt(rotationconj); -// mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotationconj); -// mul_qt_qtqt(rv3d->viewquat, rotation, rv3d->viewquat); - mul_qt_qtqt(rv3d->viewquat, rotation, rv3d->viewquat); - - // this is *close* to trackball behavior - // rotation axis needs to remain fixed relative to viewpoint, not world coordinates + + float rot[4]; + float view_inv[4], view_inv_conj[4]; + + ndof_to_quat(ndof, rot); + + // swap y and z -- not sure why, but it works + { + float temp = -rot[2]; // also invert device y + rot[2] = rot[3]; + rot[3] = temp; + } + + invert_qt_qt(view_inv, rv3d->viewquat); + copy_qt_qt(view_inv_conj, view_inv); + conjugate_qt(view_inv_conj); + + // transform rotation from view to world coordinates + mul_qt_qtqt(rot, view_inv, rot); + mul_qt_qtqt(rot, rot, view_inv_conj); + + // apply rotation + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); ED_region_tag_redraw(CTX_wm_region(C)); -- cgit v1.2.3 From ec48695de1600bdf1592c1351f6239150cd26852 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 25 Jun 2011 18:48:53 +0000 Subject: suppressed annoying log in Mac NDOF system --- intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index 6e392a7c2f8..919e4e37f16 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -101,7 +101,7 @@ static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, voi printf("ndof: calibrate\n"); // but what should blender do? break; case kConnexionMsgDoMapping: - printf("ndof: driver did something\n"); + // printf("ndof: driver did something\n"); // sent when the driver itself consumes an NDOF event // and performs whatever action is set in user prefs // 3Dx header file says to ignore these -- cgit v1.2.3 From 651df035f790b6e82dec074972aad52d616b2d47 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 25 Jun 2011 18:50:03 +0000 Subject: baby steps toward an NDOF popup menu --- source/blender/windowmanager/intern/wm_operators.c | 47 +++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 1b7333024e7..e36849e103c 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1374,6 +1374,48 @@ static void WM_OT_search_menu(wmOperatorType *ot) ot->poll= wm_search_menu_poll; } +// BEGIN ndof menu -- experimental! + +static int wm_ndof_menu_poll(bContext *C) +{ + if(CTX_wm_window(C)==NULL) + return 0; + + // if menu is already pulled up, another button press should dismiss it + // not sure if that behavior should go here or elsewhere... + + puts("ndof: menu poll"); + return 1; +} + +static int wm_ndof_menu_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) +{ + puts("ndof: menu exec"); + return OPERATOR_FINISHED; +} + +static int wm_ndof_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + puts("ndof: menu invoke"); + + uiPupMenuNotice(C, "Hello!"); + + return OPERATOR_CANCELLED; +} + +static void WM_OT_ndof_menu(wmOperatorType *ot) +{ + puts("ndof: registering menu operator"); + ot->name= "NDOF Menu"; + ot->idname= "WM_OT_ndof_menu"; + + ot->invoke= wm_ndof_menu_invoke; + ot->exec= wm_ndof_menu_exec; + ot->poll= wm_ndof_menu_poll; +} + +// END ndof menu + static int wm_call_menu_exec(bContext *C, wmOperator *op) { char idname[BKE_ST_MAXNAME]; @@ -3403,6 +3445,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_debug_menu); WM_operatortype_append(WM_OT_splash); WM_operatortype_append(WM_OT_search_menu); + WM_operatortype_append(WM_OT_ndof_menu); WM_operatortype_append(WM_OT_call_menu); WM_operatortype_append(WM_OT_radial_control); #if defined(WIN32) @@ -3623,7 +3666,9 @@ void wm_window_keymap(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "WM_OT_redraw_timer", TKEY, KM_PRESS, KM_ALT|KM_CTRL, 0); WM_keymap_verify_item(keymap, "WM_OT_debug_menu", DKEY, KM_PRESS, KM_ALT|KM_CTRL, 0); WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_PRESS, 0, 0); - + + WM_keymap_add_item(keymap, "WM_OT_ndof_menu", NDOF_BUTTON_MENU, KM_PRESS, 0, 0); + /* Space switching */ -- cgit v1.2.3 From e61063f04296d4af023718485ba0ac52b7a42a5a Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 25 Jun 2011 18:51:29 +0000 Subject: NDOF pan/zoom/fit working in image/uv editor --- source/blender/editors/space_image/image_intern.h | 1 + source/blender/editors/space_image/image_ops.c | 54 +++++++++++++++++++++++ source/blender/editors/space_image/space_image.c | 4 ++ 3 files changed, 59 insertions(+) diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index e9e77ddf430..399157da85c 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -73,6 +73,7 @@ void IMAGE_OT_view_zoom(struct wmOperatorType *ot); void IMAGE_OT_view_zoom_in(struct wmOperatorType *ot); void IMAGE_OT_view_zoom_out(struct wmOperatorType *ot); void IMAGE_OT_view_zoom_ratio(struct wmOperatorType *ot); +void IMAGE_OT_view_ndof(struct wmOperatorType *ot); void IMAGE_OT_new(struct wmOperatorType *ot); void IMAGE_OT_open(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 10b8cb238aa..fc7b84e21ae 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -437,6 +437,60 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot) "Factor", "Zoom factor, values higher than 1.0 zoom in, lower values zoom out.", -FLT_MAX, FLT_MAX); } +/********************** NDOF operator *********************/ + +/* Combined pan/zoom from a 3D mouse device. + * Y zooms, XZ pans + * "view" (not "paper") control -- user moves the viewpoint, not the image being viewed + * that explains the negative signs in the code below + */ + +static int view_ndof_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + SpaceImage *sima= CTX_wm_space_image(C); + ARegion *ar= CTX_wm_region(C); + + wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + + float dt = ndof->dt > 0.25f ? 0.0125f : ndof->dt; + /* this is probably the first event for this motion, so set dt to something reasonable + * TODO: replace such guesswork with a flag or field from the NDOF manager + */ + + /* tune these until it feels right */ + const float zoom_sensitivity = 0.5f; + const float pan_sensitivity = 300.f; + + float pan_x = pan_sensitivity * dt * -ndof->tx / sima->zoom; + float pan_y = pan_sensitivity * dt * -ndof->tz / sima->zoom; + + /* "mouse zoom" factor = 1 + (dx + dy) / 300 + * what about "ndof zoom" factor? should behave like this: + * at rest -> factor = 1 + * move forward -> factor > 1 + * move backward -> factor < 1 + */ + float zoom_factor = 1.f + zoom_sensitivity * dt * -ndof->ty; + + sima_zoom_set_factor(sima, ar, zoom_factor); + sima->xof += pan_x; + sima->yof += pan_y; + + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; +} + +void IMAGE_OT_view_ndof(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "NDOF Pan/Zoom"; + ot->idname= "IMAGE_OT_view_ndof"; + + /* api callbacks */ + ot->invoke= view_ndof_invoke; +} + /********************** view all operator *********************/ /* Updates the fields of the View2D member of the SpaceImage struct. diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 2e9544f5d20..afab4ede229 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -469,6 +469,7 @@ static void image_operatortypes(void) WM_operatortype_append(IMAGE_OT_view_zoom_in); WM_operatortype_append(IMAGE_OT_view_zoom_out); WM_operatortype_append(IMAGE_OT_view_zoom_ratio); + WM_operatortype_append(IMAGE_OT_view_ndof); WM_operatortype_append(IMAGE_OT_new); WM_operatortype_append(IMAGE_OT_open); @@ -518,6 +519,9 @@ static void image_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MOUSEPAN, 0, 0, 0); + WM_keymap_add_item(keymap, "IMAGE_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); // or view selected? + WM_keymap_add_item(keymap, "IMAGE_OT_view_ndof", NDOF_MOTION, 0, 0, 0); + WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0); -- cgit v1.2.3 From b8e8f8064dd14a0031cbef50d89c13c868c910cd Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 25 Jun 2011 18:53:06 +0000 Subject: NDOF zoom for orbit modes (trackball/turntable) in 3D view --- source/blender/editors/space_view3d/view3d_edit.c | 100 +++++++--------------- 1 file changed, 32 insertions(+), 68 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 048742fa392..bd44378c9aa 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -949,6 +949,15 @@ float ndof_to_angle_axis(const float ndof[3], float axis[3]) return angular_velocity; } +float ndof_to_angular_velocity(wmNDOFMotionData* ndof, float axis[3]) + { + const float x = ndof->rx; + const float y = ndof->ry; + const float z = ndof->rz; + + return sqrtf(x*x + y*y + z*z); + } + void ndof_to_quat(wmNDOFMotionData* ndof, float q[4]) { const float x = ndof->rx; @@ -974,10 +983,12 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) RegionView3D* rv3d = CTX_wm_region_view3d(C); wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; - float sensitivity = 1.f; /* ooh, magic number! - const float sensitivity = 0.035; /* ooh, magic number! - there will be several of these as interactions get tuned */ - int /* bool */ has_rotation = rv3d->viewlock != RV3D_LOCKED && (ndof->rx || ndof->ry || ndof->rz); + // tune these until everything feels right + float rot_sensitivity = 1.f; + float zoom_sensitivity = 1.f; + + // rather have bool, but... + int has_rotation = rv3d->viewlock != RV3D_LOCKED && (ndof->rx || ndof->ry || ndof->rz); float dt = ndof->dt; if (dt > 0.25f) @@ -986,16 +997,29 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) ndof->dt = dt = 0.0125f; - if (has_rotation) - rv3d->view = RV3D_VIEW_USER; + if (ndof->ty) { + // Zoom! + // velocity should be proportional to the linear velocity attained by rotational motion of same strength + // [got that?] + // proportional to s = r * theta + + float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->ty; + rv3d->dist += zoom_distance; + + ED_region_tag_redraw(CTX_wm_region(C)); + } if (has_rotation) { + + rv3d->view = RV3D_VIEW_USER; + if (U.flag & USER_TRACKBALL) { float rot[4]; float view_inv[4], view_inv_conj[4]; ndof_to_quat(ndof, rot); + // scale by rot_sensitivity? // swap y and z -- not sure why, but it works { @@ -1033,13 +1057,13 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) mul_m3_v3(m_inv,xvec); /* Perform the up/down rotation */ - phi = sensitivity * dt * ndof->rx; + phi = rot_sensitivity * dt * 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 * dt * ndof->rz; + phi = rot_sensitivity * dt * ndof->rz; q1[0] = cos(phi); q1[1] = q1[2] = 0.0; q1[3] = sin(phi); @@ -1160,66 +1184,6 @@ static int viewndof_invoke_1st_try(bContext *C, wmOperator *op, wmEvent *event) 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; -} #endif void VIEW3D_OT_ndof(struct wmOperatorType *ot) -- cgit v1.2.3 From edd5980436cdfe9ca7a7a2a75b6dff2129b72275 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 27 Jun 2011 20:12:10 +0000 Subject: now using blender view coordinates for ndof input -- core and Linux in place --- intern/ghost/intern/GHOST_NDOFManager.cpp | 7 +-- intern/ghost/intern/GHOST_NDOFManager.h | 10 +++- intern/ghost/intern/GHOST_NDOFManagerX11.cpp | 13 ++++- source/blender/editors/space_image/image_ops.c | 8 +-- source/blender/editors/space_view3d/view3d_edit.c | 68 ++++++----------------- 5 files changed, 43 insertions(+), 63 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 2ee87aee412..a15f480d647 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -307,17 +307,16 @@ bool GHOST_NDOFManager::sendMotionEvent() 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 + const float scale = 1.f / 350.f; // 3Dconnexion devices send +/- 350 usually // 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]; - data->rx = -scale * m_rotation[0]; + data->rx = scale * m_rotation[0]; data->ry = scale * m_rotation[1]; data->rz = scale * m_rotation[2]; diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 1a25c60f456..ab1ad49dea1 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -29,7 +29,7 @@ // --- the following type definitions will find a home somewhere else once finished --- -// #define DEBUG_NDOF_MOTION +#define DEBUG_NDOF_MOTION #define DEBUG_NDOF_BUTTONS typedef enum { NDOF_UnknownDevice, NDOF_SpaceNavigator, NDOF_SpaceExplorer, NDOF_SpacePilotPro } NDOF_DeviceT; @@ -93,6 +93,14 @@ public: void setDevice(unsigned short vendor_id, unsigned short product_id); // the latest raw axis data from the device + // NOTE: axis data should be in blender view coordinates + // +X is to the right + // +Y is up + // +Z is out of the screen + // for rotations, look from origin to each +axis + // rotations are + when CCW, - when CW + // each platform is responsible for getting axis data into this form + // these values should not be scaled (just shuffled or flipped) void updateTranslation(short t[3], GHOST_TUns64 time); void updateRotation(short r[3], GHOST_TUns64 time); diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp index 40a0a75ab82..8b001693a81 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp @@ -86,8 +86,17 @@ bool GHOST_NDOFManagerX11::processEvents() { case SPNAV_EVENT_MOTION: { - short t[3] = {e.motion.x, e.motion.y, e.motion.z}; - short r[3] = {e.motion.rx, e.motion.ry, e.motion.rz}; +// "natural" device coords +// short t[3] = {e.motion.x, e.motion.y, e.motion.z}; +// short r[3] = {e.motion.rx, e.motion.ry, e.motion.rz}; + +// blender world coords +// short t[3] = {e.motion.x, e.motion.z, e.motion.y}; +// short r[3] = {-e.motion.rx, -e.motion.rz, -e.motion.ry}; + +// blender view coords + short t[3] = {e.motion.x, e.motion.y, -e.motion.z}; + short r[3] = {-e.motion.rx, -e.motion.ry, e.motion.rz}; updateTranslation(t, now); updateRotation(r, now); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index fc7b84e21ae..77fb129e278 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -440,7 +440,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot) /********************** NDOF operator *********************/ /* Combined pan/zoom from a 3D mouse device. - * Y zooms, XZ pans + * Z zooms, XY pans * "view" (not "paper") control -- user moves the viewpoint, not the image being viewed * that explains the negative signs in the code below */ @@ -461,8 +461,8 @@ static int view_ndof_invoke(bContext *C, wmOperator *op, wmEvent *event) const float zoom_sensitivity = 0.5f; const float pan_sensitivity = 300.f; - float pan_x = pan_sensitivity * dt * -ndof->tx / sima->zoom; - float pan_y = pan_sensitivity * dt * -ndof->tz / sima->zoom; + float pan_x = pan_sensitivity * dt * ndof->tx / sima->zoom; + float pan_y = pan_sensitivity * dt * ndof->ty / sima->zoom; /* "mouse zoom" factor = 1 + (dx + dy) / 300 * what about "ndof zoom" factor? should behave like this: @@ -470,7 +470,7 @@ static int view_ndof_invoke(bContext *C, wmOperator *op, wmEvent *event) * move forward -> factor > 1 * move backward -> factor < 1 */ - float zoom_factor = 1.f + zoom_sensitivity * dt * -ndof->ty; + float zoom_factor = 1.f + zoom_sensitivity * dt * -ndof->tz; sima_zoom_set_factor(sima, ar, zoom_factor); sima->xof += pan_x; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index bd44378c9aa..0e82581e411 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1003,10 +1003,10 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) // [got that?] // proportional to s = r * theta - float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->ty; + float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz; rv3d->dist += zoom_distance; - ED_region_tag_redraw(CTX_wm_region(C)); + ED_region_tag_redraw(CTX_wm_region(C)); } if (has_rotation) { @@ -1020,13 +1020,7 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) ndof_to_quat(ndof, rot); // scale by rot_sensitivity? - - // swap y and z -- not sure why, but it works - { - float temp = -rot[2]; // also invert device y - rot[2] = rot[3]; - rot[3] = temp; - } + // mul_qt_fl(rot, rot_sensitivity); invert_qt_qt(view_inv, rv3d->viewquat); copy_qt_qt(view_inv_conj, view_inv); @@ -1043,31 +1037,26 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) } else { /* 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 angle, rot[4]; float xvec[3] = {1,0,0}; - /* 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); + float view_inv[4]/*, view_inv_conj[4]*/; + invert_qt_qt(view_inv, rv3d->viewquat); + mul_qt_v3(view_inv, xvec); /* Perform the up/down rotation */ - phi = rot_sensitivity * dt * ndof->rx; - q1[0] = cos(phi); - mul_v3_v3fl(q1+1, xvec, sin(phi)); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); + angle = rot_sensitivity * dt * ndof->rx; + rot[0] = cos(angle); + mul_v3_v3fl(rot+1, xvec, sin(angle)); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); /* Perform the orbital rotation */ - phi = rot_sensitivity * dt * ndof->rz; - q1[0] = cos(phi); - q1[1] = q1[2] = 0.0; - q1[3] = sin(phi); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); + angle = rot_sensitivity * dt * ndof->ry; + rot[0] = cos(angle); + rot[1] = rot[2] = 0.0; + rot[3] = sin(angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); ED_region_tag_redraw(CTX_wm_region(C)); } @@ -1161,31 +1150,6 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) } #endif -#if 0 -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; -} -#endif - void VIEW3D_OT_ndof(struct wmOperatorType *ot) { /* identifiers */ -- cgit v1.2.3 From 0f8a1ed8af11bf7cea9d36330d55fe0e6d15f695 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 27 Jun 2011 20:18:04 +0000 Subject: removed unneeded cleanup code on Linux --- intern/ghost/intern/GHOST_NDOFManagerX11.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp index 8b001693a81..cc2b2f785ea 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp @@ -63,10 +63,7 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys) GHOST_NDOFManagerX11::~GHOST_NDOFManagerX11() { if (m_available) - { - spnav_remove_events(SPNAV_EVENT_ANY); // ask nuclear if this is needed spnav_close(); - } } bool GHOST_NDOFManagerX11::available() -- cgit v1.2.3 From 798f59fe6810a77ce0903f3dd5650d5777a5e5ba Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 27 Jun 2011 20:44:23 +0000 Subject: Mac ndof using blender view coordinates + small but important typo fixed --- intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 9 ++++++--- source/blender/editors/space_view3d/view3d_edit.c | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index 919e4e37f16..e32c21eab15 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -73,11 +73,14 @@ static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, voi switch (s->command) { case kConnexionCmdHandleAxis: - ndof_manager->updateTranslation(s->axis, now); - ndof_manager->updateRotation(s->axis + 3, now); + { + short t[3] = {s->axis[0], -(s->axis[2]), s->axis[1]}; + short r[3] = {-(s->axis[3]), s->axis[5], -(s->axis[4])}; + ndof_manager->updateTranslation(t, now); + ndof_manager->updateRotation(r, now); ghost_system->notifyExternalEventProcessed(); break; - + } case kConnexionCmdHandleButtons: { int button_bits = has_old_driver ? s->buttons8 : s->buttons; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 0e82581e411..15c3d9da84f 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -997,11 +997,11 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) ndof->dt = dt = 0.0125f; - if (ndof->ty) { + if (ndof->tz) { // Zoom! // velocity should be proportional to the linear velocity attained by rotational motion of same strength // [got that?] - // proportional to s = r * theta + // proportional to arclength = radius * angle float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz; rv3d->dist += zoom_distance; -- cgit v1.2.3 From 5c2e4318b5c29baa55d0ba524d37788caeffbebe Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 27 Jun 2011 21:52:33 +0000 Subject: Windows ndof now uses blender view coordinates --- intern/ghost/intern/GHOST_SystemWin32.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 71be69bb9fb..b9e50e43000 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -858,26 +858,25 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) { case 1: // translation { - short axis_data[3]; - memcpy(axis_data, data + 1, sizeof(axis_data)); - m_ndofManager->updateTranslation(axis_data, now); - // wariness of alignment issues prevents me from saying it this way: - // m_ndofManager->updateTranslation((short*)(data + 1), getMilliSeconds()); - // though it probably (94.7%) would work fine + short* axis = (short*)(data + 1); + short t[3] = {axis[0], -axis[2], axis[1]}; + m_ndofManager->updateTranslation(t, now); if (raw.data.hid.dwSizeHid == 13) { // this report also includes rotation + short r[3] = {-axis[3], axis[5], -axis[4]}; + m_ndofManager->updateRotation(r, now); + + // I've never gotten one of these, has anyone else? puts("ndof: combined T + R"); - memcpy(axis_data, data + 7, sizeof(axis_data)); - m_ndofManager->updateRotation(axis_data, now); } break; } case 2: // rotation { - short axis_data[3]; - memcpy(axis_data, data + 1, sizeof(axis_data)); - m_ndofManager->updateRotation(axis_data, now); + short* axis = (short*)(data + 1); + short r[3] = {-axis[0], axis[2], -axis[1]}; + m_ndofManager->updateRotation(r, now); break; } case 3: // buttons -- cgit v1.2.3 From 30b4ff8949089ebb00a77356cecae0f31c80e0a9 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 27 Jun 2011 23:24:24 +0000 Subject: first attempt at CMake fix (untested) --- CMakeLists.txt | 15 +++++++++++++++ intern/ghost/CMakeLists.txt | 8 +++++++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f99136097c..935918a9326 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,6 +155,7 @@ option(WITH_LZO "Enable fast LZO compression (used for pointcache)" ON option(WITH_LZMA "Enable best LZMA compression, (used for pointcache)" ON) # Misc +option(WITH_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON) option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON) if(UNIX AND NOT APPLE) option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON) @@ -418,6 +419,15 @@ if(UNIX AND NOT APPLE) unset(JEMALLOC) endif() + if (WITH_NDOF) + if(CMAKE_SYSTEM_NAME MATCHES "Linux") + set(NDOF /usr) + set(NDOF_INC ${NDOF}/include) + set(NDOF_LIB spnav) + set(NDOF_LIBPATH ${FFTW3}/lib) + endif() + endif() + # OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed set(LLIBS "-lutil -lc -lm -lpthread -lstdc++") @@ -960,6 +970,11 @@ elseif(APPLE) set(TIFF_LIBPATH ${TIFF}/lib) endif() + if (WITH_NDOF) + # GHOST_NDOFManagerCocoa.mm needs "-fpascal-strings" + # linker needs "-weak_framework 3DconnexionClient" + endif() + set(EXETYPE MACOSX_BUNDLE) set(CMAKE_C_FLAGS_DEBUG "-fno-strict-aliasing -g") diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 922f6918392..24553a348ac 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -131,11 +131,13 @@ elseif(APPLE) intern/GHOST_SystemCocoa.mm intern/GHOST_SystemPathsCocoa.mm intern/GHOST_WindowCocoa.mm - + intern/GHOST_NDOFManagerCocoa.mm + intern/GHOST_DisplayManagerCocoa.h intern/GHOST_SystemCocoa.h intern/GHOST_SystemPathsCocoa.h intern/GHOST_WindowCocoa.h + intern/GHOST_NDOFManagerCocoa.h ) else() list(APPEND SRC @@ -168,11 +170,13 @@ elseif(UNIX) intern/GHOST_SystemX11.cpp intern/GHOST_SystemPathsX11.cpp intern/GHOST_WindowX11.cpp + intern/GHOST_NDOFManagerX11.cpp intern/GHOST_DisplayManagerX11.h intern/GHOST_SystemX11.h intern/GHOST_SystemPathsX11.h intern/GHOST_WindowX11.h + intern/GHOST_NDOFManagerX11.h ) if(NOT WITH_INSTALL_PORTABLE) @@ -197,6 +201,7 @@ elseif(WIN32) intern/GHOST_SystemPathsWin32.cpp intern/GHOST_WindowWin32.cpp intern/GHOST_DropTargetWin32.cpp + intern/GHOST_NDOFManagerWin32.cpp intern/GHOST_DisplayManagerWin32.h intern/GHOST_DropTargetWin32.h @@ -204,6 +209,7 @@ elseif(WIN32) intern/GHOST_SystemPathsWin32.h intern/GHOST_WindowWin32.h intern/GHOST_TaskbarWin32.h + intern/GHOST_NDOFManagerWin32.h ) endif() -- cgit v1.2.3 From 446be5216483a89a046355928f204c4779e936f9 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 28 Jun 2011 15:57:39 +0000 Subject: made Pascal string less intrusive to build systems --- build_files/scons/config/darwin-config.py | 1 - intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py index 231525993e1..ca99357330f 100644 --- a/build_files/scons/config/darwin-config.py +++ b/build_files/scons/config/darwin-config.py @@ -298,7 +298,6 @@ if WITH_BF_QUICKTIME == True: if WITH_BF_SPACENAV: PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS + ['-weak_framework','3DconnexionClient'] - CXXFLAGS = CXXFLAGS + ['-fpascal-strings'] # they use an old-skool Mac programming style #note to build succesfully on 10.3.9 SDK you need to patch 10.3.9 by adding the SystemStubs.a lib from 10.4 LLIBS = ['stdc++', 'SystemStubs'] diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index e32c21eab15..826d0c6b319 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -131,7 +131,7 @@ GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) } // Pascal string *and* a four-letter constant. How old-skool. - m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\pblender", + m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\007blender", kConnexionClientModeTakeOver, kConnexionMaskAll); printf("ndof: client id = %d\n", m_clientID); -- cgit v1.2.3 From 4178b662ccb99240ad8528577f040dc00c3c78dd Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 28 Jun 2011 15:59:46 +0000 Subject: enabled pan/zoom in rotation-locked 3D views + small cleanup --- intern/ghost/intern/GHOST_NDOFManager.h | 4 +-- source/blender/editors/space_view3d/view3d_edit.c | 31 +++++++++++++++-------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index ab1ad49dea1..2a7ecd90025 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -29,8 +29,8 @@ // --- the following type definitions will find a home somewhere else once finished --- -#define DEBUG_NDOF_MOTION -#define DEBUG_NDOF_BUTTONS +//#define DEBUG_NDOF_MOTION +//#define DEBUG_NDOF_BUTTONS typedef enum { NDOF_UnknownDevice, NDOF_SpaceNavigator, NDOF_SpaceExplorer, NDOF_SpacePilotPro } NDOF_DeviceT; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 15c3d9da84f..b334ed91df6 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -931,7 +931,7 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) // 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]) +static float ndof_to_angle_axis(const float ndof[3], float axis[3]) { const float x = ndof[0]; const float y = ndof[1]; @@ -949,7 +949,7 @@ float ndof_to_angle_axis(const float ndof[3], float axis[3]) return angular_velocity; } -float ndof_to_angular_velocity(wmNDOFMotionData* ndof, float axis[3]) +static float ndof_to_angular_velocity(wmNDOFMotionData* ndof) { const float x = ndof->rx; const float y = ndof->ry; @@ -958,7 +958,7 @@ float ndof_to_angular_velocity(wmNDOFMotionData* ndof, float axis[3]) return sqrtf(x*x + y*y + z*z); } -void ndof_to_quat(wmNDOFMotionData* ndof, float q[4]) +static void ndof_to_quat(wmNDOFMotionData* ndof, float q[4]) { const float x = ndof->rx; const float y = ndof->ry; @@ -984,8 +984,9 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; // tune these until everything feels right - float rot_sensitivity = 1.f; - float zoom_sensitivity = 1.f; + const float rot_sensitivity = 1.f; + const float zoom_sensitivity = 1.f; + const float pan_sensitivity = 1.f; // rather have bool, but... int has_rotation = rv3d->viewlock != RV3D_LOCKED && (ndof->rx || ndof->ry || ndof->rz); @@ -1005,8 +1006,20 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz; rv3d->dist += zoom_distance; + } + + if (rv3d->viewlock == RV3D_LOCKED) { + /* rotation not allowed -- explore panning options instead */ + float view_inv[4]; + float pan_vec[3] = {ndof->tx, ndof->ty, 0}; + mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt); + + /* transform motion from view to world coordinates */ + invert_qt_qt(view_inv, rv3d->viewquat); + mul_qt_v3(view_inv, pan_vec); - ED_region_tag_redraw(CTX_wm_region(C)); + /* move center of view opposite of hand motion (camera mode, not object mode) */ + sub_v3_v3(rv3d->ofs, pan_vec); } if (has_rotation) { @@ -1033,8 +1046,6 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) // apply rotation mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); - ED_region_tag_redraw(CTX_wm_region(C)); - } else { /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */ float angle, rot[4]; @@ -1057,11 +1068,11 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) rot[1] = rot[2] = 0.0; rot[3] = sin(angle); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); - - ED_region_tag_redraw(CTX_wm_region(C)); } } + ED_region_tag_redraw(CTX_wm_region(C)); + return OPERATOR_FINISHED; } -- cgit v1.2.3 From bca3da4fb0108e972ba99bea7278ae54e6f6287a Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 28 Jun 2011 21:20:47 +0000 Subject: updated build script for SpaceNav on Linux -- was foolishly relying on user-config.py --- build_files/scons/config/linux2-config.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build_files/scons/config/linux2-config.py b/build_files/scons/config/linux2-config.py index bc2917055fb..bf87889751c 100644 --- a/build_files/scons/config/linux2-config.py +++ b/build_files/scons/config/linux2-config.py @@ -192,6 +192,10 @@ WITH_BF_OPENMP = True WITH_BF_RAYOPTIMIZATION = True BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-pthread'] +#SpaceNavigator and friends +WITH_BF_NDOF = True +BF_NDOF_LIB = 'spnav' + ## CC = 'gcc' CXX = 'g++' @@ -223,6 +227,8 @@ CXX_WARN = ['-Wno-invalid-offsetof', '-Wno-sign-compare'] ##FIX_STUBS_WARNINGS = -Wno-unused LLIBS = ['util', 'c', 'm', 'dl', 'pthread', 'stdc++'] +if WITH_BF_NDOF: + LLIBS = LLIBS + [BF_NDOF_LIB]; ##LOPTS = --dynamic ##DYNLDFLAGS = -shared $(LDFLAGS) -- cgit v1.2.3 From e41a7b6f6360cc7c04938d40b1f76aca39d7a0aa Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 1 Jul 2011 00:58:47 +0000 Subject: tiny compile fix for PowerMac --- intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index 826d0c6b319..1c8730a2804 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -47,7 +47,7 @@ static void NDOF_DeviceAdded(io_connect_t connection) #endif // determine exactly which device is plugged in - int result = 0; + SInt32 result = 0; ConnexionControl(kConnexionCtlGetDeviceID, 0, &result); unsigned short vendorID = result >> 16; unsigned short productID = result & 0xffff; -- cgit v1.2.3 From 20de4f27b6be5b4494e1338fe737cf2df42a283e Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 1 Jul 2011 01:00:20 +0000 Subject: ndof popup menu (experimental (mostly harmless)) --- source/blender/windowmanager/intern/wm_operators.c | 99 ++++++++++++++++++++-- 1 file changed, 94 insertions(+), 5 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index e36849e103c..7d6a50043b5 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1376,6 +1376,61 @@ static void WM_OT_search_menu(wmOperatorType *ot) // BEGIN ndof menu -- experimental! +static uiBlock* wm_block_ndof_menu_1st(bContext* C, ARegion* ar, void* UNUSED(arg_op)) +{ + uiBlock* block; + uiBut* but; + + block = uiBeginBlock(C, ar, "ndof_popup_menu", UI_EMBOSS); + uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT); +// uiBlockSetDirection(block, UI_DOWN); +// uiBlockBeginAlign(block); + + // uiItemBooleanO(block->curlayout, "enable pan/zoom", ICON_NDOF_TRANS, "toggle_ndof_pan_zoom_enabled", "ndof_pan_zoom_enabled", 1); + // uiBlock is used as an opaque type in this file, so can't use members... + + int foo = 333; + uiDefButI(block, TOG, 0, "foo", 10, 10, 9*UI_UNIT_X, UI_UNIT_Y, &foo, 0.f, 1.f, 0.1f, 0.9f, "15%"); + // uiDefBut(block, TOG, 0, "enable pan/zoom", 0, 0, 10, 10, NULL, 0.f, 1.f, 0.f, 1.f, "don't talk to strangers"); + +// uiBlockEndAlign(block); +// uiBoundsBlock(block, 6); + uiEndBlock(C, block); + + return block; +} + +static uiBlock *wm_block_ndof_menu(bContext *C, ARegion *ar, void *UNUSED(arg_op)) +{ + static char search[256]= ""; + wmEvent event; + wmWindow *win= CTX_wm_window(C); + uiBlock *block; + uiBut *but; + + block= uiBeginBlock(C, ar, "ndof_popup", UI_EMBOSS); +// uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT); + uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_POPUP|UI_BLOCK_MOVEMOUSE_QUIT); + + but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 9*UI_UNIT_X, UI_UNIT_Y, 0, 0, ""); + uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); + + /* fake button, it holds space for search items */ + uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 9*UI_UNIT_X, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + + uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */ + uiEndBlock(C, block); + + event= *(win->eventstate); /* XXX huh huh? make api call */ + event.type= EVT_BUT_OPEN; + event.val= KM_PRESS; + event.customdata= but; + event.customdatafree= FALSE; + wm_event_add(win, &event); + + return block; +} + static int wm_ndof_menu_poll(bContext *C) { if(CTX_wm_window(C)==NULL) @@ -1396,11 +1451,45 @@ static int wm_ndof_menu_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) static int wm_ndof_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { - puts("ndof: menu invoke"); + printf("ndof: menu invoked in "); - uiPupMenuNotice(C, "Hello!"); + switch (CTX_wm_area(C)->spacetype) // diff spaces can have diff 3d mouse options + { + case SPACE_VIEW3D: + puts("3D area"); + break; + case SPACE_IMAGE: + puts("image area"); + break; + default: + puts("some iNDOFferent area"); + } + +// uiPupMenuNotice(C, "Hello!"); // <-- this works +// uiPupBlock(C, wm_block_ndof_menu, op); // <-- no luck! +// ui_popup_menu_create(C, NULL, NULL, NULL, NULL, "Hello!"); // <-- this works + + uiPopupMenu* pup = uiPupMenuBegin(C,"3D mouse settings",ICON_NDOF_TURN); + uiLayout* layout = uiPupMenuLayout(pup); + + //uiBlock* block = uiLayoutGetBlock(layout); + //int foo = 1; + //uiDefButI(block, TOG, 0, "foo", 10, 10, 9*UI_UNIT_X, UI_UNIT_Y, &foo, 0.f, 1.f, 0.1f, 0.9f, "15%"); - return OPERATOR_CANCELLED; + uiItemS(layout); // separator + + uiItemBooleanO(layout, "enable pan/zoom", ICON_NDOF_TRANS, "ndof_toggle_pan_zoom_enabled", "ndof_pan_zoom_enabled", 1); + uiItemBooleanO(layout, "enable rotation", ICON_NDOF_TURN, "ndof_toggle_rotation_enabled", "ndof_rotation_enabled", 1); + uiItemFloatO(layout, "sensitivity", 0, "ndof_adjust_sensitivity", "ndof_sensitivity", 1.f); + uiItemV(layout,"sensitivity",ICON_NDOF_TRANS, 1); + + uiItemS(layout); + uiItemL(layout, "3D navigation mode", ICON_NDOF_FLY); + uiItemL(layout, "...", 0); + + uiPupMenuEnd(C,pup); + + return OPERATOR_CANCELLED; // <-- correct? } static void WM_OT_ndof_menu(wmOperatorType *ot) @@ -1410,8 +1499,8 @@ static void WM_OT_ndof_menu(wmOperatorType *ot) ot->idname= "WM_OT_ndof_menu"; ot->invoke= wm_ndof_menu_invoke; - ot->exec= wm_ndof_menu_exec; - ot->poll= wm_ndof_menu_poll; +// ot->exec= wm_ndof_menu_exec; +// ot->poll= wm_ndof_menu_poll; } // END ndof menu -- cgit v1.2.3 From 893bf5f81a2a7b7306461cd3c9b5c00b1796bb2d Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 1 Jul 2011 03:44:03 +0000 Subject: verbose ndof event trace for a tester --- intern/ghost/intern/GHOST_NDOFManager.h | 4 ++-- source/blender/editors/space_view3d/view3d_edit.c | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 2a7ecd90025..ab1ad49dea1 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -29,8 +29,8 @@ // --- the following type definitions will find a home somewhere else once finished --- -//#define DEBUG_NDOF_MOTION -//#define DEBUG_NDOF_BUTTONS +#define DEBUG_NDOF_MOTION +#define DEBUG_NDOF_BUTTONS typedef enum { NDOF_UnknownDevice, NDOF_SpaceNavigator, NDOF_SpaceExplorer, NDOF_SpacePilotPro } NDOF_DeviceT; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index b334ed91df6..42a41be05e0 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -997,6 +997,11 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) /* TODO: replace such guesswork with a flag or field from the NDOF manager */ ndof->dt = dt = 0.0125f; + #define DEBUG_NDOF_MOTION + #ifdef DEBUG_NDOF_MOTION + printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n", + ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt); + #endif if (ndof->tz) { // Zoom! -- cgit v1.2.3 From abd4a881dba7a554caa8cb7d48d2dceb2f27d9a8 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 1 Jul 2011 03:54:23 +0000 Subject: ndof device detection now visible in log --- intern/ghost/intern/GHOST_NDOFManager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index a15f480d647..54192c0d669 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -157,18 +157,22 @@ void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ { // -- current devices -- case 0xC626: + puts("ndof: using SpaceNavigator"); m_deviceType = NDOF_SpaceNavigator; m_buttonCount = 2; break; case 0xC628: + puts("ndof: using SpaceNavigator for Notebooks"); m_deviceType = NDOF_SpaceNavigator; // for Notebooks m_buttonCount = 2; break; case 0xC627: + puts("ndof: using SpaceExplorer"); m_deviceType = NDOF_SpaceExplorer; m_buttonCount = 15; break; case 0xC629: + puts("ndof: using SpacePilotPro"); m_deviceType = NDOF_SpacePilotPro; m_buttonCount = 31; break; -- cgit v1.2.3 From 14c72f379cea8be411e649f08fd5ac9f8943e56d Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 1 Jul 2011 21:51:44 +0000 Subject: implemented ndof 'dead zone' around home position, fixed X11 active window determination, removed old X11 ndof code --- intern/ghost/intern/GHOST_NDOFManager.cpp | 11 +++-- intern/ghost/intern/GHOST_SystemX11.cpp | 56 ++++------------------ intern/ghost/intern/GHOST_SystemX11.h | 9 ---- source/blender/windowmanager/intern/wm_operators.c | 24 +++++----- 4 files changed, 31 insertions(+), 69 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 54192c0d669..4d2f06f8191 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -27,6 +27,7 @@ #include "GHOST_WindowManager.h" #include // for memory functions #include // for error/info reporting +#include #ifdef DEBUG_NDOF_BUTTONS static const char* ndof_button_names[] = { @@ -301,6 +302,12 @@ void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time) } } +static bool atHomePosition(GHOST_TEventNDOFMotionData* ndof, float threshold) + { + #define HOME(foo) (fabsf(ndof->foo) < threshold) + return HOME(tx) && HOME(ty) && HOME(tz) && HOME(rx) && HOME(ry) && HOME(rz); + } + bool GHOST_NDOFManager::sendMotionEvent() { if (m_atRest) @@ -336,9 +343,7 @@ bool GHOST_NDOFManager::sendMotionEvent() 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; - // this needs to be aware of calibration -- 0.01 0.01 0.03 might be 'rest' + m_atRest = atHomePosition(data, 0.05f); return true; } diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 5e59ac91809..4c62e5e62b4 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -75,22 +75,6 @@ #include // for fprintf only #include // for exit -#if 0 // obsolete SpaceNav code - -typedef struct NDOFPlatformInfo { - Display *display; - Window window; - volatile GHOST_TEventNDOFData *currValues; - Atom cmdAtom; - Atom motionAtom; - Atom btnPressAtom; - Atom btnRelAtom; -} NDOFPlatformInfo; - -static NDOFPlatformInfo sNdofInfo = {NULL, 0, NULL, 0, 0, 0, 0}; - -#endif - //these are for copy and select copy static char *txt_cut_buffer= NULL; static char *txt_select_buffer= NULL; @@ -612,6 +596,8 @@ GHOST_SystemX11::processEvent(XEvent *xe) case FocusOut: { XFocusChangeEvent &xfe = xe->xfocus; + + printf("X: focus %s for window %d\n", xfe.type == FocusIn ? "in" : "out", (int) xfe.window); // May have to look at the type of event and filter some // out. @@ -643,36 +629,6 @@ GHOST_SystemX11::processEvent(XEvent *xe) } else #endif -#if 0 // obsolete SpaceNav code - - if (sNdofInfo.currValues) { - static GHOST_TEventNDOFData data = {0,0,0,0,0,0,0,0,0,0,0}; - if (xcme.message_type == sNdofInfo.motionAtom) - { - data.changed = 1; - data.delta = xcme.data.s[8] - data.time; - data.time = xcme.data.s[8]; - data.tx = xcme.data.s[2] >> 2; - data.ty = xcme.data.s[3] >> 2; - data.tz = xcme.data.s[4] >> 2; - data.rx = xcme.data.s[5]; - data.ry = xcme.data.s[6]; - data.rz =-xcme.data.s[7]; - g_event = new GHOST_EventNDOF(getMilliSeconds(), - GHOST_kEventNDOFMotion, - window, data); - } else if (xcme.message_type == sNdofInfo.btnPressAtom) { - data.changed = 2; - data.delta = xcme.data.s[8] - data.time; - data.time = xcme.data.s[8]; - data.buttons = xcme.data.s[2]; - g_event = new GHOST_EventNDOF(getMilliSeconds(), - GHOST_kEventNDOFButton, - window, data); - } - -#endif - if (((Atom)xcme.data.l[0]) == m_wm_take_focus) { XWindowAttributes attr; Window fwin; @@ -730,6 +686,14 @@ GHOST_SystemX11::processEvent(XEvent *xe) xce.y_root ); } + + printf("X: %s window %d\n", xce.type == EnterNotify ? "entering" : "leaving", (int) xce.window); + + if (xce.type == EnterNotify) + m_windowManager->setActiveWindow(window); + else + m_windowManager->setWindowInactive(window); + break; } case MapNotify: diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index e551b5fb2fe..f70f67dec18 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -203,15 +203,6 @@ public: return m_display; } -#if 0 // obsolete SpaceNav code - - void * - prepareNdofInfo( - volatile GHOST_TEventNDOFData *current_values - ); - -#endif - /* Helped function for get data from the clipboard. */ void getClipboard_xcout(XEvent evt, Atom sel, Atom target, unsigned char **txt, unsigned long *len, diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 7d6a50043b5..6fb6a8dcf1f 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1376,6 +1376,7 @@ static void WM_OT_search_menu(wmOperatorType *ot) // BEGIN ndof menu -- experimental! +#if 0 static uiBlock* wm_block_ndof_menu_1st(bContext* C, ARegion* ar, void* UNUSED(arg_op)) { uiBlock* block; @@ -1448,9 +1449,17 @@ static int wm_ndof_menu_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) puts("ndof: menu exec"); return OPERATOR_FINISHED; } +#endif static int wm_ndof_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { +// uiPupMenuNotice(C, "Hello!"); // <-- this works +// uiPupBlock(C, wm_block_ndof_menu, op); // <-- no luck! +// ui_popup_menu_create(C, NULL, NULL, NULL, NULL, "Hello!"); // <-- this works + + uiPopupMenu* pup = uiPupMenuBegin(C,"3D mouse settings",ICON_NDOF_TURN); + uiLayout* layout = uiPupMenuLayout(pup); + printf("ndof: menu invoked in "); switch (CTX_wm_area(C)->spacetype) // diff spaces can have diff 3d mouse options @@ -1465,12 +1474,6 @@ static int wm_ndof_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even puts("some iNDOFferent area"); } -// uiPupMenuNotice(C, "Hello!"); // <-- this works -// uiPupBlock(C, wm_block_ndof_menu, op); // <-- no luck! -// ui_popup_menu_create(C, NULL, NULL, NULL, NULL, "Hello!"); // <-- this works - - uiPopupMenu* pup = uiPupMenuBegin(C,"3D mouse settings",ICON_NDOF_TURN); - uiLayout* layout = uiPupMenuLayout(pup); //uiBlock* block = uiLayoutGetBlock(layout); //int foo = 1; @@ -1495,12 +1498,11 @@ static int wm_ndof_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even static void WM_OT_ndof_menu(wmOperatorType *ot) { puts("ndof: registering menu operator"); - ot->name= "NDOF Menu"; - ot->idname= "WM_OT_ndof_menu"; + + ot->name = "NDOF Menu"; + ot->idname = "WM_OT_ndof_menu"; - ot->invoke= wm_ndof_menu_invoke; -// ot->exec= wm_ndof_menu_exec; -// ot->poll= wm_ndof_menu_poll; + ot->invoke = wm_ndof_menu_invoke; } // END ndof menu -- cgit v1.2.3 From e3c89a127de7cabb32d89ff696d6d840ff23b123 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Wed, 6 Jul 2011 17:10:38 +0000 Subject: refitted old ndof fly code for 2.5, removed crusty old code --- source/blender/editors/space_view3d/view3d_edit.c | 641 ++++++---------------- 1 file changed, 174 insertions(+), 467 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 42a41be05e0..5a0c233edfa 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -929,6 +929,7 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; } +#if 0 // NDOF utility functions // returns angular velocity (0..1), fills axis of rotation // (shouldn't live in this file!) static float ndof_to_angle_axis(const float ndof[3], float axis[3]) @@ -957,6 +958,7 @@ static float ndof_to_angular_velocity(wmNDOFMotionData* ndof) return sqrtf(x*x + y*y + z*z); } +#endif static void ndof_to_quat(wmNDOFMotionData* ndof, float q[4]) { @@ -977,8 +979,11 @@ static void ndof_to_quat(wmNDOFMotionData* ndof, float q[4]) q[3] = scale * z; } -// Mike's version -static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) +// Mike's original version: +// -- "orbit" navigation (trackball/turntable) +// -- zooming +// -- panning in rotationally-locked views +static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) { RegionView3D* rv3d = CTX_wm_region_view3d(C); wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; @@ -1023,7 +1028,7 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) invert_qt_qt(view_inv, rv3d->viewquat); mul_qt_v3(view_inv, pan_vec); - /* move center of view opposite of hand motion (camera mode, not object mode) */ + /* move center of view opposite of hand motion (this is camera mode, not object mode) */ sub_v3_v3(rv3d->ofs, pan_vec); } @@ -1057,7 +1062,7 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) float xvec[3] = {1,0,0}; /* Determine the direction of the x vector (for rotating up and down) */ - float view_inv[4]/*, view_inv_conj[4]*/; + float view_inv[4]; invert_qt_qt(view_inv, rv3d->viewquat); mul_qt_v3(view_inv, xvec); @@ -1081,90 +1086,183 @@ static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } -// Tom's version -#if 0 -static int viewndof_invoke(bContext *C, wmOperator *op, wmEvent *event) +#if 0 // not ready +static int ndof_fly_invoke(bContext *C, wmOperator *op, wmEvent *event) { + RegionView3D* rv3d = CTX_wm_region_view3d(C); wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; - - float phi, q1[4]; - float m[3][3]; - float m_inv[3][3]; - float xvec[3] = {1,0,0}; - float yvec[3] = {0,1,0}; - float vec[3]; - float mat[3][3]; - const float rotaSensitivity = 0.007; - const float tranSensitivity = 0.120; - - ARegion *ar= CTX_wm_region(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); - View3D *v3d = CTX_wm_view3d(C); - + + const int shouldRotate = 0, shouldMove = 1; + float dt = ndof->dt; - - if (dt > 0.25f) { + if (dt > 0.25f) /* this is probably the first event for this motion, so set dt to something reasonable */ - dt = 0.0125f; + /* TODO: replace such guesswork with a flag or field from the NDOF manager */ + ndof->dt = dt = 0.0125f; + + if (shouldRotate) + { + const float turn_sensitivity = 1.f; + + float rot[4]; + ndof_to_quat(ndof, rot); + + rv3d->view = RV3D_VIEW_USER; + } + + if (shouldMove) + { + const float forward_sensitivity = 1.f; + const float vertical_sensitivity = 1.f; + const float lateral_sensitivity = 1.f; + + float trans[3] = { + lateral_sensitivity * dt * ndof->tx, + vertical_sensitivity * dt * ndof->ty, + forward_sensitivity * rv3d->dist * dt * ndof->tz + }; + } + + ED_region_tag_redraw(CTX_wm_region(C)); + + return OPERATOR_FINISHED; +} +#endif + +// BEGIN old fly code +// derived from blender 2.4 + +static void getndof(wmNDOFMotionData* indof, float* outdof) +{ + // Rotations feel relatively faster than translations only in fly mode, so + // we have no choice but to fix that here (not in the plugins) + const float turn_sensitivity = 0.8f; + + const float forward_sensitivity = 2.5f; + const float vertical_sensitivity = 1.6f; + const float lateral_sensitivity = 2.5f; + + const float dt = (indof->dt < 0.25f) ? indof->dt : 0.0125f; + // this is probably the first event for this motion, so set dt to something reasonable + // TODO: replace such guesswork with a flag or field from the NDOF manager + + outdof[0] = lateral_sensitivity * dt * indof->tx; + outdof[1] = vertical_sensitivity * dt * indof->ty; + outdof[2] = forward_sensitivity * dt * indof->tz; + + outdof[3] = turn_sensitivity * dt * indof->rx; + outdof[4] = turn_sensitivity * dt * indof->ry; + outdof[5] = turn_sensitivity * dt * indof->rz; +} + +// statics for controlling rv3d->dist corrections. +// viewmoveNDOF zeros and adjusts rv3d->ofs. +// viewmove restores based on dz_flag state. + +static int dz_flag = 0; +static float m_dist; + +static void mouse_rotation_workaround_push(RegionView3D* rv3d) +{ + // 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. + + float mat[3][3]; + float upvec[3]; + + 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; } - /* 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); - - //if(rv3d->persp=!= RV3D_PERSP) //Camera control not supported yet - /* Lock fixed views out of using rotation controls */ - if(rv3d->view!=RV3D_VIEW_FRONT && rv3d->view!=RV3D_VIEW_BACK) - if(rv3d->view!=RV3D_VIEW_TOP && rv3d->view!=RV3D_VIEW_BOTTOM) - if(rv3d->view!=RV3D_VIEW_RIGHT && rv3d->view!=RV3D_VIEW_LEFT) { - // Perform the up/down rotation - phi = (rotaSensitivity+dt) * -ndof->rx; - q1[0] = cos(phi); - mul_v3_v3fl(q1+1, xvec, sin(phi)); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); - - // Perform the left/right rotation - mul_m3_v3(m_inv,yvec); - phi = (rotaSensitivity+dt) * ndof->ry; - q1[0] = cos(phi); - mul_v3_v3fl(q1+1, yvec, sin(phi)); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); - - // Perform the orbital rotation - phi = (rotaSensitivity+dt) * ndof->rz; - q1[0] = cos(phi); - q1[1] = q1[2] = 0.0; - q1[3] = sin(phi); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); - } + // this is still needed in version 2.5 [mce] + // warning! current viewmove does not look at dz_flag or m_dist + // don't expect 2D mouse to work properly right after using 3D mouse +} + +static void mouse_rotation_workaround_pop(RegionView3D* rv3d) +{ + if (dz_flag) { + dz_flag = 0; + rv3d->dist = m_dist; + } +} + +static int ndof_oldfly_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + RegionView3D* rv3d = CTX_wm_region_view3d(C); + wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + + float phi; + float dval[6]; + float tvec[3], rvec[3]; + float q1[4]; + float mat[3][3]; + + // fetch the current state of the ndof device + getndof(ndof, dval); - // Perform Pan translation - vec[0]= (tranSensitivity+dt) * ndof->tx; - vec[1]= (tranSensitivity+dt) * ndof->tz; - //vec[2]= 0.0f;//tranSensitivity * ndof->ty; - //window_to_3d_delta(ar, vec, -ndof->tx, -ndof->tz); // experimented a little instead of above + // force perspective mode. This is a hack and is + // incomplete. It doesn't actually affect 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 + mouse_rotation_workaround_push(rv3d); + + // Apply rotation + rvec[0] = dval[3]; + rvec[1] = dval[4]; + rvec[2] = 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, vec); - // translate the view - add_v3_v3(rv3d->ofs, vec); + mul_m3_v3(mat, rvec); - // Perform Zoom translation - if (ndof->ty!=0.0f){ // TODO - need to add limits to prevent flipping past gridlines - rv3d->dist += (tranSensitivity+dt)* ndof->ty; - // printf("dist %5.3f view %d grid %f\n",rv3d->dist,rv3d->view,v3d->grid); + // 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); } - //printf("Trans tx:%5.2f ty:%5.2f tz:%5.2f \n",ndof->tx, ndof->ty, ndof->tz); - ED_region_tag_redraw(ar); - + // 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); + + mouse_rotation_workaround_pop(rv3d); + + // back to 2.5 land! + ED_region_tag_redraw(CTX_wm_region(C)); return OPERATOR_FINISHED; } -#endif + +// END old fly code void VIEW3D_OT_ndof(struct wmOperatorType *ot) { @@ -1174,7 +1272,8 @@ void VIEW3D_OT_ndof(struct wmOperatorType *ot) ot->idname = "VIEW3D_OT_ndof"; /* api callbacks */ - ot->invoke = viewndof_invoke; + ot->invoke = ndof_oldfly_invoke; +// ot->invoke = ndof_orbit_invoke; ot->poll = ED_operator_view3d_active; /* flags */ @@ -3448,398 +3547,6 @@ int ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], cons return (*depth==FLT_MAX) ? 0:1; } -/* ********************* 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 - -#if 0 -static float ndof_axis_scale[6] = { - +0.01, // Tx - +0.01, // Tz - +0.01, // Ty - +0.0015, // Rx - +0.0015, // Rz - +0.0015 // Ry -}; - -static 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 UNUSED(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 UNUSED(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 { - copy_v3_v3(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); -} -#endif // if 0, unused NDof code - - /* Gets the view trasnformation from a camera * currently dosnt take camzoom into account * -- cgit v1.2.3 From 50ef78cdb8d9d746785bb03a296666dd15123e90 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Wed, 6 Jul 2011 18:50:59 +0000 Subject: various fixes to enable MSVC build, removed crusty old Win32 ndof code --- intern/ghost/intern/GHOST_DropTargetWin32.cpp | 1 + intern/ghost/intern/GHOST_NDOFManager.h | 2 +- intern/ghost/intern/GHOST_SystemWin32.cpp | 129 ++++------------------ intern/ghost/intern/GHOST_SystemWin32.h | 106 ------------------ source/blender/editors/space_view3d/view3d_edit.c | 2 +- 5 files changed, 25 insertions(+), 215 deletions(-) diff --git a/intern/ghost/intern/GHOST_DropTargetWin32.cpp b/intern/ghost/intern/GHOST_DropTargetWin32.cpp index 2e77da42b31..99990a46c2a 100644 --- a/intern/ghost/intern/GHOST_DropTargetWin32.cpp +++ b/intern/ghost/intern/GHOST_DropTargetWin32.cpp @@ -33,6 +33,7 @@ #include "GHOST_Debug.h" #include "GHOST_DropTargetWin32.h" +#include #ifdef GHOST_DEBUG // utility diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index ab1ad49dea1..155510d6d7f 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -29,7 +29,7 @@ // --- the following type definitions will find a home somewhere else once finished --- -#define DEBUG_NDOF_MOTION +//#define DEBUG_NDOF_MOTION #define DEBUG_NDOF_BUTTONS typedef enum { NDOF_UnknownDevice, NDOF_SpaceNavigator, NDOF_SpaceExplorer, NDOF_SpacePilotPro } NDOF_DeviceT; diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index b9e50e43000..8f7f56eb7ff 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -59,46 +59,12 @@ #endif #endif -#if 0 // shouldn't be needed... -/* - * According to the docs the mouse wheel message is supported from windows 98 - * upwards. Leaving WINVER at default value, the WM_MOUSEWHEEL message and the - * wheel detent value are undefined. - */ -#ifndef WM_MOUSEWHEEL -#define WM_MOUSEWHEEL 0x020A -#endif // WM_MOUSEWHEEL -#ifndef WHEEL_DELTA -#define WHEEL_DELTA 120 /* Value for rolling one detent, (old convention! MS changed it) */ -#endif // WHEEL_DELTA - -/* - * Defines for mouse buttons 4 and 5 aka xbutton1 and xbutton2. - * MSDN: Declared in Winuser.h, include Windows.h - * This does not seem to work with MinGW so we define our own here. - */ -#ifndef XBUTTON1 -#define XBUTTON1 0x0001 -#endif // XBUTTON1 -#ifndef XBUTTON2 -#define XBUTTON2 0x0002 -#endif // XBUTTON2 -#ifndef WM_XBUTTONUP -#define WM_XBUTTONUP 524 -#endif // WM_XBUTTONUP -#ifndef WM_XBUTTONDOWN -#define WM_XBUTTONDOWN 523 -#endif // WM_XBUTTONDOWN - -#endif // ^^^ removed code - #include "GHOST_Debug.h" #include "GHOST_DisplayManagerWin32.h" #include "GHOST_EventButton.h" #include "GHOST_EventCursor.h" #include "GHOST_EventKey.h" #include "GHOST_EventWheel.h" -//#include "GHOST_EventNDOF.h" #include "GHOST_TimerTask.h" #include "GHOST_TimerManager.h" #include "GHOST_WindowManager.h" @@ -156,27 +122,12 @@ #define VK_MEDIA_PLAY_PAUSE 0xB3 #endif // VK_MEDIA_PLAY_PAUSE -#if 0 -/* - Initiates WM_INPUT messages from keyboard - That way GHOST can retrieve true keys -*/ -GHOST_TInt32 GHOST_SystemWin32::initKeyboardRawInput(void) -{ - RAWINPUTDEVICE device = {0}; - device.usUsagePage = 0x01; /* usUsagePage & usUsage for keyboard*/ - device.usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */ - - return RegisterRawInputDevices(&device, 1, sizeof(device)); -}; -#endif - static void initRawInput() { RAWINPUTDEVICE devices[2]; memset(devices, 0, 2 * sizeof(RAWINPUTDEVICE)); - // multi-axis mouse (SpaceNavigator) + // multi-axis mouse (SpaceNavigator, etc.) devices[0].usUsagePage = 0x01; devices[0].usUsage = 0x08; @@ -414,15 +365,7 @@ GHOST_TSuccess GHOST_SystemWin32::init() (LPFNSETPROCESSDPIAWARE)GetProcAddress(user32, "SetProcessDPIAware"); if (SetProcessDPIAware) SetProcessDPIAware(); -// #ifdef NEED_RAW_PROC -// pRegisterRawInputDevices = (LPFNDLLRRID)GetProcAddress(user32, "RegisterRawInputDevices"); -// pGetRawInputData = (LPFNDLLGRID)GetProcAddress(user32, "GetRawInputData"); -// #else - FreeLibrary(user32); -// #endif - - /* Initiates WM_INPUT messages from keyboard */ -// initKeyboardRawInput(); + FreeLibrary(user32); initRawInput(); // Determine whether this system has a high frequency performance counter. */ @@ -464,17 +407,11 @@ GHOST_TSuccess GHOST_SystemWin32::init() GHOST_TSuccess GHOST_SystemWin32::exit() { -// #ifdef NEED_RAW_PROC -// FreeLibrary(user32); -// #endif - return GHOST_System::exit(); } GHOST_TKey GHOST_SystemWin32::hardKey(GHOST_IWindow *window, RAWINPUT const& raw, int * keyDown, char * vk) { -// unsigned int size = 0; -// char * data; GHOST_TKey key = GHOST_kKeyUnknown; @@ -757,7 +694,6 @@ GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINP char vk; GHOST_SystemWin32 * system = (GHOST_SystemWin32 *)getSystem(); GHOST_TKey key = system->hardKey(window, raw, &keyDown, &vk); -// GHOST_TKey key = system->hardKey(window, wParam, lParam, &keyDown, &vk); GHOST_EventKey* event; if (key != GHOST_kKeyUnknown) { char ascii = '\0'; @@ -832,11 +768,9 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) GetRawInputDeviceInfo(raw.header.hDevice, RIDI_DEVICEINFO, &info, &infoSize); if (info.dwType == RIM_TYPEHID) - { - // printf("hardware ID = %04X:%04X\n", info.hid.dwVendorId, info.hid.dwProductId); m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId); - } - else puts(" not a HID device... mouse/kb perhaps?"); + else + puts(" not a HID device... mouse/kb perhaps?"); firstEvent = false; } @@ -845,13 +779,25 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) // send motion. Mark as 'sent' so motion will always get dispatched. eventSent = true; +#ifdef _MSC_VER + // using Microsoft compiler & header files + // they invented the RawInput API, so this version is (probably) correct + BYTE const* data = raw.data.hid.bRawData; + // struct RAWHID { + // DWORD dwSizeHid; + // DWORD dwCount; + // BYTE bRawData[1]; + // }; +#else + // MinGW's definition (below) doesn't agree, so we need a slight + // workaround until it's fixed BYTE const* data = &raw.data.hid.bRawData; - // MinGW's definition (below) doesn't agree with MSDN reference for bRawData: - // typedef struct tagRAWHID { - // DWORD dwSizeHid; - // DWORD dwCount; - // BYTE bRawData; // <== isn't this s'posed to be a BYTE*? - // } RAWHID,*PRAWHID,*LPRAWHID; + // struct RAWHID { + // DWORD dwSizeHid; + // DWORD dwCount; + // BYTE bRawData; // <== isn't this s'posed to be a BYTE*? + // }; +#endif BYTE packetType = data[0]; switch (packetType) @@ -1241,30 +1187,6 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * In GHOST, we let DefWindowProc call the timer callback. */ break; -#if 0 // old NDOF code - case WM_BLND_NDOF_AXIS: - { - GHOST_TEventNDOFData ndofdata; - system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata); - system->m_eventManager-> - pushEvent(new GHOST_EventNDOF( - system->getMilliSeconds(), - GHOST_kEventNDOFMotion, - window, ndofdata)); - } - break; - case WM_BLND_NDOF_BTN: - { - GHOST_TEventNDOFData ndofdata; - system->m_ndofManager->GHOST_NDOFGetDatas(ndofdata); - system->m_eventManager-> - pushEvent(new GHOST_EventNDOF( - system->getMilliSeconds(), - GHOST_kEventNDOFButton, - window, ndofdata)); - } - break; -#endif // old NDOF code } } else { @@ -1284,13 +1206,6 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, GHOST_PRINT("GHOST_SystemWin32::wndProc: event without window\n") } -// if (event) { -// system->pushEvent(event); -// } -// else { -// lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); -// } - if (event) { system->pushEvent(event); eventHandled = true; diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index dae8bf9a31a..c5dff27dace 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -38,7 +38,6 @@ #error WIN32 only! #endif // WIN32 -//#undef _WIN32_WINNT #define _WIN32_WINNT 0x501 // require Windows XP or newer #define WIN32_LEAN_AND_MEAN #include @@ -50,96 +49,6 @@ # define __int64 long long #endif -/* RawInput definitions should not be needed, due to WinXP requirement - -#ifndef WM_INPUT -#define WM_INPUT 0x00FF -#endif -#ifndef RID_INPUT -#define RID_INPUT 0x10000003 -#endif -#ifndef RIM_INPUTSINK -#define RIM_INPUTSINK 0x1 -#endif -#ifndef RI_KEY_BREAK -#define RI_KEY_BREAK 0x1 -#endif -#ifndef RI_KEY_E0 -#define RI_KEY_E0 0x2 -#endif -#ifndef RI_KEY_E1 -#define RI_KEY_E1 0x4 -#endif -#ifndef RIM_TYPEMOUSE -#define RIM_TYPEMOUSE 0x0 -#define RIM_TYPEKEYBOARD 0x1 -#define RIM_TYPEHID 0x2 - -typedef struct tagRAWINPUTDEVICE { - USHORT usUsagePage; - USHORT usUsage; - DWORD dwFlags; - HWND hwndTarget; -} RAWINPUTDEVICE; - -typedef struct tagRAWINPUTHEADER { - DWORD dwType; - DWORD dwSize; - HANDLE hDevice; - WPARAM wParam; -} RAWINPUTHEADER; - -typedef struct tagRAWMOUSE { - USHORT usFlags; - union { - ULONG ulButtons; - struct { - USHORT usButtonFlags; - USHORT usButtonData; - }; - }; - ULONG ulRawButtons; - LONG lLastX; - LONG lLastY; - ULONG ulExtraInformation; -} RAWMOUSE; - -typedef struct tagRAWKEYBOARD { - USHORT MakeCode; - USHORT Flags; - USHORT Reserved; - USHORT VKey; - UINT Message; - ULONG ExtraInformation; -} RAWKEYBOARD; - -typedef struct tagRAWHID { - DWORD dwSizeHid; - DWORD dwCount; - BYTE bRawData[1]; -} RAWHID; - -typedef struct tagRAWINPUT { - RAWINPUTHEADER header; - union { - RAWMOUSE mouse; - RAWKEYBOARD keyboard; - RAWHID hid; - } data; -} RAWINPUT; - -DECLARE_HANDLE(HRAWINPUT); -#endif - -#ifdef FREE_WINDOWS -#define NEED_RAW_PROC -typedef BOOL (WINAPI * LPFNDLLRRID)(RAWINPUTDEVICE*,UINT, UINT); - -typedef UINT (WINAPI * LPFNDLLGRID)(HRAWINPUT, UINT, LPVOID, PUINT, UINT); -#define GetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader) ((pGetRawInputData)?pGetRawInputData(hRawInput, uiCommand, pData, pcbSize, cbSizeHeader):(UINT)-1) -#endif -*/ - class GHOST_EventButton; class GHOST_EventCursor; class GHOST_EventKey; @@ -425,11 +334,6 @@ protected: */ static LRESULT WINAPI s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - /** - * Initiates WM_INPUT messages from keyboard - */ -// GHOST_TInt32 initKeyboardRawInput(void); - /** * Toggles console * @action 0 - Hides @@ -458,15 +362,6 @@ protected: /** Console status */ int m_consoleStatus; - - /** handle for user32.dll*/ -// HMODULE user32; -// #ifdef NEED_RAW_PROC -// /* pointer to RegisterRawInputDevices function */ -// LPFNDLLRRID pRegisterRawInputDevices; -// /* pointer to GetRawInputData function */ -// LPFNDLLGRID pGetRawInputData; -// #endif }; inline void GHOST_SystemWin32::retrieveModifierKeys(GHOST_ModifierKeys& keys) const @@ -500,4 +395,3 @@ inline void GHOST_SystemWin32::handleKeyboardChange(void) } } #endif // _GHOST_SYSTEM_WIN32_H_ - diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 5a0c233edfa..2d8c14b29f3 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1002,7 +1002,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) /* TODO: replace such guesswork with a flag or field from the NDOF manager */ ndof->dt = dt = 0.0125f; - #define DEBUG_NDOF_MOTION + //#define DEBUG_NDOF_MOTION #ifdef DEBUG_NDOF_MOTION printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n", ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt); -- cgit v1.2.3 From b2eb2a00f104ae4d201ab58f83623e36ba45aef8 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 14 Jul 2011 03:27:33 +0000 Subject: introduce variables for ndof settings --- source/blender/makesdna/DNA_userdef_types.h | 18 ++++++++++++++++-- source/blender/makesrna/intern/rna_userdef.c | 23 +++++++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 50e66f91028..78bc1c73ec9 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -365,7 +365,7 @@ typedef struct UserDef { short recent_files; /* maximum number of recently used files to remember */ short smooth_viewtx; /* miliseconds to spend spinning the view */ short glreslimit; - short ndof_pan, ndof_rotate; +/* short ndof_pan, ndof_rotate; */ short curssize; short color_picker_type; short ipo_new; /* interpolation mode for newly added F-Curves */ @@ -375,7 +375,10 @@ typedef struct UserDef { short scrcastwait; /* milliseconds between screencast snapshots */ short widget_unit; /* defaults to 20 for 72 DPI setting */ - short pad[3]; + short pad[1]; + + float ndof_sensitivity; /* overall sensitivity of 3D mouse */ + int ndof_flag; /* flags for 3D mouse */ char versemaster[160]; char verseuser[160]; @@ -578,6 +581,17 @@ extern UserDef U; /* from blenkernel blender.c */ #define TH_OLDSKOOL 3 #define TH_SHADED 4 +/* ndof_flag (3D mouse options) */ +#define NDOF_SHOW_GUIDE (1 << 0) +#define NDOF_FLY_HELICOPTER (1 << 1) +#define NDOF_LOCK_HORIZON (1 << 2) +/* the following might not need to be saved between sessions, + but they do need to live somewhere accessible... +#define NDOF_SHOULD_PAN (1 << 3) +#define NDOF_SHOULD_ZOOM (1 << 4) +#define NDOF_SHOULD_ROTATE (1 << 5) +*/ + #ifdef __cplusplus } #endif diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index b67805c97b9..86b88718ba8 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2705,7 +2705,9 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "dragthreshold"); RNA_def_property_range(prop, 3, 40); RNA_def_property_ui_text(prop, "Drag Threshold", "Amount of pixels you have to drag before dragging UI items happens"); - + + /* 3D mouse settings */ +/* prop= RNA_def_property(srna, "ndof_pan_speed", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "ndof_pan"); RNA_def_property_range(prop, 0, 200); @@ -2715,7 +2717,24 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "ndof_rotate"); RNA_def_property_range(prop, 0, 200); RNA_def_property_ui_text(prop, "NDof Rotation Speed", "The overall rotation speed of an NDOF device, as percent of standard"); - +*/ + prop= RNA_def_property(srna, "ndof_sensitivity", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.25f, 4.0f); + RNA_def_property_ui_text(prop, "3D Mouse Sensitivity", "Baseline sensitivity of the 3D Mouse"); + + prop= RNA_def_property(srna, "ndof_show_guide", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_SHOW_GUIDE); + RNA_def_property_ui_text(prop, "Show 3D Mouse Guide", "Visualize the center and axis of rotation (or projected position in fly mode)"); + + prop= RNA_def_property(srna, "ndof_lock_horizon", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_LOCK_HORIZON); + RNA_def_property_ui_text(prop, "Lock Horizon", "Keep horizon level while flying with 3D Mouse"); + + prop= RNA_def_property(srna, "ndof_fly_helicopter", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_FLY_HELICOPTER); + RNA_def_property_ui_text(prop, "Helicopter Fly Mode", ""); + + prop= RNA_def_property(srna, "mouse_double_click_time", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dbl_click_time"); RNA_def_property_range(prop, 1, 1000); -- cgit v1.2.3 From 44d2e6eb109889f49fb9935d05ef201127d15805 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 14 Jul 2011 03:28:31 +0000 Subject: disable old ndof fly (new stuff en route from another machine) --- source/blender/editors/space_view3d/view3d_edit.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 2d8c14b29f3..fc84944da02 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1127,7 +1127,6 @@ static int ndof_fly_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } -#endif // BEGIN old fly code // derived from blender 2.4 @@ -1263,6 +1262,7 @@ static int ndof_oldfly_invoke(bContext *C, wmOperator *op, wmEvent *event) } // END old fly code +#endif void VIEW3D_OT_ndof(struct wmOperatorType *ot) { @@ -1272,8 +1272,8 @@ void VIEW3D_OT_ndof(struct wmOperatorType *ot) ot->idname = "VIEW3D_OT_ndof"; /* api callbacks */ - ot->invoke = ndof_oldfly_invoke; -// ot->invoke = ndof_orbit_invoke; +// ot->invoke = ndof_oldfly_invoke; + ot->invoke = ndof_orbit_invoke; ot->poll = ED_operator_view3d_active; /* flags */ -- cgit v1.2.3 From cc1ba4569ccdb77a9371140def316caecac71da5 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 14 Jul 2011 21:20:45 +0000 Subject: more consistent and modal-friendly ndof events, fly mode v1 --- intern/ghost/GHOST_Types.h | 24 ++- intern/ghost/intern/GHOST_NDOFManager.cpp | 96 ++++++++--- intern/ghost/intern/GHOST_NDOFManager.h | 9 +- source/blender/editors/space_view3d/view3d_edit.c | 182 +++++++++++++-------- source/blender/editors/space_view3d/view3d_fly.c | 149 +++++++++++++++-- .../blender/editors/space_view3d/view3d_intern.h | 3 + source/blender/windowmanager/WM_types.h | 27 +-- .../blender/windowmanager/intern/wm_event_system.c | 2 + 8 files changed, 361 insertions(+), 131 deletions(-) diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index bc731a43ae7..85f73a25b47 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -434,14 +434,24 @@ typedef struct { GHOST_TUns8 **strings; } GHOST_TStringArray; +typedef enum { + GHOST_kNotStarted, + GHOST_kStarting, + GHOST_kInProgress, + GHOST_kFinishing, + GHOST_kFinished + } GHOST_TProgress; + 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) + /** N-degree of freedom device data v3 [GSoC 2010] */ + // Each component normally ranges from -1 to +1, but can exceed that. + // These use blender standard view coordinates, with positive rotations being CCW about the axis. + float tx, ty, tz; // translation + 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 + GHOST_TProgress progress; // Starting, InProgress or Finishing (for modal handlers) } GHOST_TEventNDOFMotionData; typedef enum { GHOST_kPress, GHOST_kRelease } GHOST_TButtonAction; diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 4d2f06f8191..e001540aa95 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -29,6 +29,12 @@ #include // for error/info reporting #include +#ifdef DEBUG_NDOF_MOTION +// printable version of each GHOST_TProgress value +static const char* progress_string[] = + {"not started","starting","in progress","finishing","finished"}; +#endif + #ifdef DEBUG_NDOF_BUTTONS static const char* ndof_button_names[] = { // used internally, never sent @@ -139,9 +145,10 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) , m_buttonCount(0) , m_buttonMask(0) , m_buttons(0) - , m_motionTime(1000) // one full second (operators should filter out such large time deltas) + , m_motionTime(0) , m_prevMotionTime(0) - , m_atRest(true) + , m_motionState(GHOST_kNotStarted) + , m_motionEventPending(false) { // to avoid the rare situation where one triple is updated and // the other is not, initialize them both here: @@ -179,10 +186,16 @@ void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ break; // -- older devices -- - case 0xC623: puts("ndof: SpaceTraveler not supported, please file a bug report"); break; - // no buttons? - case 0xC625: puts("ndof: SpacePilot not supported, please file a bug report"); break; - // 21 buttons + // keep unknown device type so rogue button events will get discarded + // "mystery device" owners can help build another HID_map for their hardware + case 0xC623: + puts("ndof: SpaceTraveler not supported, please file a bug report"); + m_buttonCount = 8; + break; + case 0xC625: + puts("ndof: SpacePilot not supported, please file a bug report"); + m_buttonCount = 21; + break; default: printf("ndof: unknown Logitech product %04hx\n", product_id); } @@ -198,18 +211,41 @@ void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ #endif } +void GHOST_NDOFManager::updateMotionState() + { + if (m_motionEventPending) + return; + + switch (m_motionState) + { + case GHOST_kFinished: + case GHOST_kNotStarted: + m_motionState = GHOST_kStarting; + break; + case GHOST_kStarting: + m_motionState = GHOST_kInProgress; + break; + default: + // InProgress remains InProgress + // should never be Finishing + break; + } + + m_motionEventPending = true; + } + void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time) { memcpy(m_translation, t, sizeof(m_translation)); m_motionTime = time; - m_atRest = false; + updateMotionState(); } void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time) { memcpy(m_rotation, r, sizeof(m_rotation)); m_motionTime = time; - m_atRest = false; + updateMotionState(); } void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, bool press, GHOST_TUns64 time, GHOST_IWindow* window) @@ -290,7 +326,7 @@ void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time) int diff = m_buttons ^ button_bits; - for (int button_number = 0; button_number <= 31; ++button_number) + for (int button_number = 0; button_number < m_buttonCount; ++button_number) { int mask = 1 << button_number; @@ -302,15 +338,21 @@ void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time) } } -static bool atHomePosition(GHOST_TEventNDOFMotionData* ndof, float threshold) +static bool atHomePosition(GHOST_TEventNDOFMotionData* ndof) { - #define HOME(foo) (fabsf(ndof->foo) < threshold) + #define HOME(foo) (ndof->foo == 0) return HOME(tx) && HOME(ty) && HOME(tz) && HOME(rx) && HOME(ry) && HOME(rz); } +static bool nearHomePosition(GHOST_TEventNDOFMotionData* ndof, float threshold) + { + #define HOME1(foo) (fabsf(ndof->foo) < threshold) + return HOME1(tx) && HOME1(ty) && HOME1(tz) && HOME1(rx) && HOME1(ry) && HOME1(rz); + } + bool GHOST_NDOFManager::sendMotionEvent() { - if (m_atRest) + if (m_motionState == GHOST_kFinished || m_motionState == GHOST_kNotStarted) return false; GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); @@ -320,7 +362,7 @@ bool GHOST_NDOFManager::sendMotionEvent() const float scale = 1.f / 350.f; // 3Dconnexion devices send +/- 350 usually - // possible future enhancement + // probable future enhancement // scale *= m_sensitivity; data->tx = scale * m_translation[0]; @@ -331,19 +373,35 @@ bool GHOST_NDOFManager::sendMotionEvent() data->ry = scale * m_rotation[1]; data->rz = scale * m_rotation[2]; - data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds + if (m_motionState == GHOST_kStarting) + // prev motion time will be ancient, so just make up something reasonable + data->dt = 0.0125f; + else + data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds m_prevMotionTime = m_motionTime; + // 'at rest' test goes at the end so that the first 'rest' event gets sent + if (atHomePosition(data)) +// if (nearHomePosition(data, 0.05f)) // Linux & Windows have trouble w/ calibration + { + data->progress = GHOST_kFinishing; + // for internal state, skip Finishing & jump to Finished + m_motionState = GHOST_kFinished; + } + else + data->progress = m_motionState; // Starting or InProgress + #ifdef DEBUG_NDOF_MOTION - printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", - data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, data->dt); + printf("ndof %s: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", + progress_string[data->progress], + data->tx, data->ty, data->tz, + data->rx, data->ry, data->rz, + data->dt); #endif m_system.pushEvent(event); - - // 'at rest' test goes at the end so that the first 'rest' event gets sent - m_atRest = atHomePosition(data, 0.05f); + m_motionEventPending = false; return true; } diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 155510d6d7f..cabff22fca7 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -27,9 +27,7 @@ #include "GHOST_System.h" -// --- the following type definitions will find a home somewhere else once finished --- - -//#define DEBUG_NDOF_MOTION +#define DEBUG_NDOF_MOTION #define DEBUG_NDOF_BUTTONS typedef enum { NDOF_UnknownDevice, NDOF_SpaceNavigator, NDOF_SpaceExplorer, NDOF_SpacePilotPro } NDOF_DeviceT; @@ -120,7 +118,7 @@ protected: private: void sendButtonEvent(NDOF_ButtonT, bool press, GHOST_TUns64 time, GHOST_IWindow*); void sendKeyEvent(GHOST_TKey, bool press, GHOST_TUns64 time, GHOST_IWindow*); - + void updateMotionState(); NDOF_DeviceT m_deviceType; int m_buttonCount; @@ -132,7 +130,8 @@ private: GHOST_TUns64 m_motionTime; // in milliseconds GHOST_TUns64 m_prevMotionTime; // time of most recent Motion event sent - bool m_atRest; + GHOST_TProgress m_motionState; + bool m_motionEventPending; }; #endif diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index fc84944da02..bfbff8a4906 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -929,10 +929,30 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; } -#if 0 // NDOF utility functions +// NDOF utility functions +// (should these functions live in this file?) +float ndof_to_angle_axis(struct wmNDOFMotionData* ndof, float axis[3]) + { + const float x = ndof->rx; + const float y = ndof->ry; + const float z = ndof->rz; + + float angular_velocity = sqrtf(x*x + y*y + z*z); + float angle = ndof->dt * angular_velocity; + + float scale = 1.f / angular_velocity; + + // normalize + axis[0] = scale * x; + axis[1] = scale * y; + axis[2] = scale * z; + + return angle; + } + +#if 0 // unused utility functions // returns angular velocity (0..1), fills axis of rotation -// (shouldn't live in this file!) -static float ndof_to_angle_axis(const float ndof[3], float axis[3]) +float ndof_to_angle_axis(const float ndof[3], float axis[3]) { const float x = ndof[0]; const float y = ndof[1]; @@ -960,7 +980,7 @@ static float ndof_to_angular_velocity(wmNDOFMotionData* ndof) } #endif -static void ndof_to_quat(wmNDOFMotionData* ndof, float q[4]) +void ndof_to_quat(struct wmNDOFMotionData* ndof, float q[4]) { const float x = ndof->rx; const float y = ndof->ry; @@ -988,6 +1008,8 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) RegionView3D* rv3d = CTX_wm_region_view3d(C); wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + const float dt = ndof->dt; + // tune these until everything feels right const float rot_sensitivity = 1.f; const float zoom_sensitivity = 1.f; @@ -996,12 +1018,6 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) // rather have bool, but... int has_rotation = rv3d->viewlock != RV3D_LOCKED && (ndof->rx || ndof->ry || ndof->rz); - float dt = ndof->dt; - if (dt > 0.25f) - /* this is probably the first event for this motion, so set dt to something reasonable */ - /* TODO: replace such guesswork with a flag or field from the NDOF manager */ - ndof->dt = dt = 0.0125f; - //#define DEBUG_NDOF_MOTION #ifdef DEBUG_NDOF_MOTION printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n", @@ -1086,41 +1102,109 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } -#if 0 // not ready +#if 0 +// statics for controlling rv3d->dist corrections. +// viewmoveNDOF zeros and adjusts rv3d->ofs. +// viewmove restores based on dz_flag state. + +static int dz_flag = 0; +static float m_dist; + +static void mouse_rotation_workaround_push(RegionView3D* rv3d) +{ + // 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. + + float mat[3][3]; + float upvec[3]; + + 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; + } + + // this is still needed in version 2.5 [mce] + // warning! current viewmove does not look at dz_flag or m_dist + // don't expect 2D mouse to work properly right after using 3D mouse +} + +static void mouse_rotation_workaround_pop(RegionView3D* rv3d) +{ + if (dz_flag) { + dz_flag = 0; + rv3d->dist = m_dist; + } +} + static int ndof_fly_invoke(bContext *C, wmOperator *op, wmEvent *event) { RegionView3D* rv3d = CTX_wm_region_view3d(C); wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; - const int shouldRotate = 0, shouldMove = 1; + const int shouldRotate = 1, shouldTranslate = 0; + + const float dt = ndof->dt; - float dt = ndof->dt; - if (dt > 0.25f) - /* this is probably the first event for this motion, so set dt to something reasonable */ - /* TODO: replace such guesswork with a flag or field from the NDOF manager */ - ndof->dt = dt = 0.0125f; + float view_inv[4]; + invert_qt_qt(view_inv, rv3d->viewquat); if (shouldRotate) { const float turn_sensitivity = 1.f; float rot[4]; + float view_inv_conj[4]; + mouse_rotation_workaround_push(rv3d); + ndof_to_quat(ndof, rot); + copy_qt_qt(view_inv_conj, view_inv); + conjugate_qt(view_inv_conj); + + // transform rotation from view to world coordinates + mul_qt_qtqt(rot, view_inv, rot); + mul_qt_qtqt(rot, rot, view_inv_conj); + + // apply rotation to view offset (focal point) + mul_qt_v3(rot, rv3d->ofs); +// mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); + rv3d->view = RV3D_VIEW_USER; } - if (shouldMove) + if (shouldTranslate) { const float forward_sensitivity = 1.f; const float vertical_sensitivity = 1.f; const float lateral_sensitivity = 1.f; - + float trans[3] = { - lateral_sensitivity * dt * ndof->tx, - vertical_sensitivity * dt * ndof->ty, - forward_sensitivity * rv3d->dist * dt * ndof->tz + lateral_sensitivity * ndof->tx, + vertical_sensitivity * ndof->ty, + forward_sensitivity * ndof->tz }; + +// mul_v3_fl(trans, rv3d->dist * dt); + mul_v3_fl(trans, dt); + + /* transform motion from view to world coordinates */ + mul_qt_v3(view_inv, trans); + + /* move center of view opposite of hand motion (this is camera mode, not object mode) */ + sub_v3_v3(rv3d->ofs, trans); } ED_region_tag_redraw(CTX_wm_region(C)); @@ -1141,9 +1225,7 @@ static void getndof(wmNDOFMotionData* indof, float* outdof) const float vertical_sensitivity = 1.6f; const float lateral_sensitivity = 2.5f; - const float dt = (indof->dt < 0.25f) ? indof->dt : 0.0125f; - // this is probably the first event for this motion, so set dt to something reasonable - // TODO: replace such guesswork with a flag or field from the NDOF manager + const float dt = indof->dt; outdof[0] = lateral_sensitivity * dt * indof->tx; outdof[1] = vertical_sensitivity * dt * indof->ty; @@ -1154,51 +1236,6 @@ static void getndof(wmNDOFMotionData* indof, float* outdof) outdof[5] = turn_sensitivity * dt * indof->rz; } -// statics for controlling rv3d->dist corrections. -// viewmoveNDOF zeros and adjusts rv3d->ofs. -// viewmove restores based on dz_flag state. - -static int dz_flag = 0; -static float m_dist; - -static void mouse_rotation_workaround_push(RegionView3D* rv3d) -{ - // 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. - - float mat[3][3]; - float upvec[3]; - - 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; - } - - // this is still needed in version 2.5 [mce] - // warning! current viewmove does not look at dz_flag or m_dist - // don't expect 2D mouse to work properly right after using 3D mouse -} - -static void mouse_rotation_workaround_pop(RegionView3D* rv3d) -{ - if (dz_flag) { - dz_flag = 0; - rv3d->dist = m_dist; - } -} static int ndof_oldfly_invoke(bContext *C, wmOperator *op, wmEvent *event) { @@ -1254,7 +1291,7 @@ static int ndof_oldfly_invoke(bContext *C, wmOperator *op, wmEvent *event) // translate the view sub_v3_v3(rv3d->ofs, tvec); - mouse_rotation_workaround_pop(rv3d); +// mouse_rotation_workaround_pop(rv3d); // back to 2.5 land! ED_region_tag_redraw(CTX_wm_region(C)); @@ -1272,8 +1309,9 @@ void VIEW3D_OT_ndof(struct wmOperatorType *ot) ot->idname = "VIEW3D_OT_ndof"; /* api callbacks */ -// ot->invoke = ndof_oldfly_invoke; ot->invoke = ndof_orbit_invoke; +// ot->invoke = ndof_fly_invoke; +// ot->invoke = ndof_oldfly_invoke; ot->poll = ED_operator_view3d_active; /* flags */ diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index ed1ed5b3881..00adfa13e28 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -158,7 +158,9 @@ typedef struct FlyInfo { short state; short use_precision; short redraw; - int mval[2]; + + int mval[2]; /* latest 2D mouse values */ + wmNDOFMotionData* ndof; /* latest 3D mouse values */ /* fly state state */ float speed; /* the speed the view is moving per redraw */ @@ -257,6 +259,8 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even fly->ar = CTX_wm_region(C); fly->scene= CTX_data_scene(C); + puts("\n-- fly begin --"); + if(fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->id.lib) { BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library"); return FALSE; @@ -282,12 +286,14 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even fly->zlock_momentum=0.0f; fly->grid= 1.0f; fly->use_precision= 0; + fly->redraw= 1; fly->dvec_prev[0]= fly->dvec_prev[1]= fly->dvec_prev[2]= 0.0f; fly->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); VECCOPY2D(fly->mval, event->mval) + fly->ndof = NULL; fly->time_lastdraw= fly->time_lastwheel= PIL_check_seconds_timer(); @@ -329,8 +335,17 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even /* perspective or ortho */ if (fly->rv3d->persp==RV3D_ORTHO) fly->rv3d->persp= RV3D_PERSP; /*if ortho projection, make perspective */ + copy_qt_qt(fly->rot_backup, fly->rv3d->viewquat); copy_v3_v3(fly->ofs_backup, fly->rv3d->ofs); + + /* the dist defines a vector that is infront of the offset + to rotate the view about. + this is no good for fly mode because we + want to rotate about the viewers center. + but to correct the dist removal we must + alter offset so the view doesn't jump. */ + fly->rv3d->dist= 0.0f; upvec[2]= fly->dist_backup; /*x and y are 0*/ @@ -338,7 +353,6 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even sub_v3_v3(fly->rv3d->ofs, upvec); /*Done with correcting for the dist*/ } - /* center the mouse, probably the UI mafia are against this but without its quite annoying */ WM_cursor_warp(CTX_wm_window(C), fly->ar->winrct.xmin + fly->ar->winx/2, fly->ar->winrct.ymin + fly->ar->winy/2); @@ -356,6 +370,8 @@ static int flyEnd(bContext *C, FlyInfo *fly) if(fly->state == FLY_RUNNING) return OPERATOR_RUNNING_MODAL; + puts("\n-- fly end --"); + WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), fly->timer); ED_region_draw_cb_exit(fly->ar->type, fly->draw_handle_pixel); @@ -401,6 +417,9 @@ static int flyEnd(bContext *C, FlyInfo *fly) if(fly->obtfm) MEM_freeN(fly->obtfm); + if(fly->ndof) + MEM_freeN(fly->ndof); + if(fly->state == FLY_CONFIRM) { MEM_freeN(fly); return OPERATOR_FINISHED; @@ -412,12 +431,46 @@ static int flyEnd(bContext *C, FlyInfo *fly) static void flyEvent(FlyInfo *fly, wmEvent *event) { - if (event->type == TIMER && event->customdata == fly->timer) { - fly->redraw = 1; - } - else if (event->type == MOUSEMOVE) { + if (event->type == MOUSEMOVE) { VECCOPY2D(fly->mval, event->mval); - } /* handle modal keymap first */ + } + else if (event->type == NDOF_MOTION) { + // do these automagically get delivered? yes. + // puts("ndof motion detected in fly mode!"); + // static const char* tag_name = "3D mouse position"; + + wmNDOFMotionData* incoming_ndof = (wmNDOFMotionData*) event->customdata; + switch (incoming_ndof->progress) + { + case P_STARTING: + // start keeping track of 3D mouse position + puts("start keeping track of 3D mouse position"); + // fall through... + case P_IN_PROGRESS: + // update 3D mouse position + putchar('.'); fflush(stdout); + if (fly->ndof == NULL) + // fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); + fly->ndof = MEM_dupallocN(incoming_ndof); + // fly->ndof = malloc(sizeof(wmNDOFMotionData)); + else + memcpy(fly->ndof, incoming_ndof, sizeof(wmNDOFMotionData)); + break; + case P_FINISHING: + // stop keeping track of 3D mouse position + puts("stop keeping track of 3D mouse position"); + if (fly->ndof) + { + MEM_freeN(fly->ndof); + // free(fly->ndof); + fly->ndof = NULL; + } + break; + default: + ; // should always be one of the above 3 + } + } + /* handle modal keymap first */ else if (event->type == EVT_MODAL_MAP) { switch (event->val) { case FLY_MODAL_CANCEL: @@ -528,7 +581,6 @@ static void flyEvent(FlyInfo *fly, wmEvent *event) case FLY_MODAL_PRECISION_DISABLE: fly->use_precision= FALSE; break; - } } } @@ -567,16 +619,12 @@ static int flyApply(bContext *C, FlyInfo *fly) unsigned char apply_rotation= 1; /* if the user presses shift they can look about without movinf the direction there looking*/ + static unsigned int iteration = 1; + printf("fly timer %d\n", iteration++); + if(fly->root_parent) ED_view3d_to_m4(prev_view_mat, fly->rv3d->ofs, fly->rv3d->viewquat, fly->rv3d->dist); - /* the dist defines a vector that is infront of the offset - to rotate the view about. - this is no good for fly mode because we - want to rotate about the viewers center. - but to correct the dist removal we must - alter offset so the view doesn't jump. */ - xmargin= ar->winx/20.0f; ymargin= ar->winy/20.0f; @@ -622,6 +670,8 @@ static int flyApply(bContext *C, FlyInfo *fly) float time_redraw; float time_redraw_clamped; + fly->redraw= 1; + time_current= PIL_check_seconds_timer(); time_redraw= (float)(time_current - fly->time_lastdraw); time_redraw_clamped= MIN2(0.05f, time_redraw); /* clamt the redraw time to avoid jitter in roll correction */ @@ -854,11 +904,69 @@ static int flyApply(bContext *C, FlyInfo *fly) copy_v3_v3(fly->dvec_prev, dvec); } -/* moved to flyEnd() */ - return OPERATOR_FINISHED; } +static int flyApply_ndof(bContext *C, FlyInfo *fly) +{ + // shorthand for oft-used variables + wmNDOFMotionData* ndof = fly->ndof; + const float dt = ndof->dt; + RegionView3D* rv3d = fly->rv3d; + + const int shouldRotate = 1, shouldTranslate = 1; + + float view_inv[4]; + invert_qt_qt(view_inv, rv3d->viewquat); + + if (shouldRotate) + { + const float turn_sensitivity = 1.f; + + float rotation[4]; + float axis[3]; + float angle = turn_sensitivity * ndof_to_angle_axis(ndof, axis); + + // transform rotation axis from view to world coordinates + mul_qt_v3(view_inv, axis); + + // apply rotation to view + axis_angle_to_quat(rotation, axis, angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); + + rv3d->view = RV3D_VIEW_USER; + + fly->redraw = 1; + } + + if (shouldTranslate) + { + const float forward_sensitivity = 1.f; + const float vertical_sensitivity = 0.4f; + const float lateral_sensitivity = 0.6f; + + float speed = 10.f; // blender units per second + // ^^ this is ok for default cube scene, but should scale with.. something + + float trans[3] = { + lateral_sensitivity * ndof->tx, + vertical_sensitivity * ndof->ty, + forward_sensitivity * ndof->tz + }; + + mul_v3_fl(trans, speed * dt); + + // transform motion from view to world coordinates + mul_qt_v3(view_inv, trans); + + // move center of view opposite of hand motion (this is camera mode, not object mode) + sub_v3_v3(rv3d->ofs, trans); + + fly->redraw = 1; + } + + return OPERATOR_FINISHED; +} static int fly_invoke(bContext *C, wmOperator *op, wmEvent *event) @@ -908,7 +1016,12 @@ static int fly_modal(bContext *C, wmOperator *op, wmEvent *event) flyEvent(fly, event); - if(event->type==TIMER && event->customdata == fly->timer) + if (fly->ndof) // 3D mouse overrules [2D mouse + timer] + { + if (event->type==NDOF_MOTION) + flyApply_ndof(C, fly); + } + else if (event->type==TIMER && event->customdata == fly->timer) flyApply(C, fly); do_draw |= fly->redraw; diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 1a148481031..3658a481bdf 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -51,6 +51,7 @@ struct ARegionType; struct bPoseChannel; struct bAnimVizSettings; struct bMotionPath; +struct wmNDOFMotionData; #define BL_NEAR_CLIP 0.001 @@ -92,6 +93,8 @@ void VIEW3D_OT_zoom_border(struct wmOperatorType *ot); void VIEW3D_OT_drawtype(struct wmOperatorType *ot); void view3d_boxview_copy(ScrArea *sa, ARegion *ar); +void ndof_to_quat(struct wmNDOFMotionData* ndof, float q[4]); +float ndof_to_angle_axis(struct wmNDOFMotionData* ndof, float axis[3]); /* view3d_fly.c */ void view3d_keymap(struct wmKeyConfig *keyconf); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 26c394a2ad3..7476410ec19 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -377,17 +377,24 @@ typedef struct wmTabletData { float Ytilt; /* as above */ } wmTabletData; -typedef struct { +typedef enum { // motion progress, for modal handlers + P_NOT_STARTED, + P_STARTING, // <-- + P_IN_PROGRESS, // <-- only these are sent for NDOF motion + P_FINISHING, // <-- + P_FINISHED + } wmProgress; + +typedef struct wmNDOFMotionData { /* 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) + // Each component normally ranges from -1 to +1, but can exceed that. + // These use blender standard view coordinates, with positive rotations being CCW about the axis. + float tx, ty, tz; // translation + 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 + wmProgress progress; // is this the first event, the last, or one of many in between? } wmNDOFMotionData; typedef struct wmTimer { diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index b41eebc5298..c2df53c9e91 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2324,6 +2324,8 @@ static void attach_ndof_data(wmEvent* event, const GHOST_TEventNDOFMotionData* g data->dt = ghost->dt; + data->progress = (wmProgress) ghost->progress; + event->custom = EVT_DATA_NDOF_MOTION; event->customdata = data; event->customdatafree = 1; -- cgit v1.2.3 From b0c8abf04e6af902827913e09c245efa690ce5c4 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 14 Jul 2011 22:01:09 +0000 Subject: removed unused ndof code --- intern/ghost/intern/GHOST_NDOFManager.h | 2 +- source/blender/editors/space_view3d/view3d_edit.c | 234 +--------------------- 2 files changed, 2 insertions(+), 234 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index cabff22fca7..79e3a4eb4c8 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -27,7 +27,7 @@ #include "GHOST_System.h" -#define DEBUG_NDOF_MOTION +// #define DEBUG_NDOF_MOTION #define DEBUG_NDOF_BUTTONS typedef enum { NDOF_UnknownDevice, NDOF_SpaceNavigator, NDOF_SpaceExplorer, NDOF_SpacePilotPro } NDOF_DeviceT; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index bfbff8a4906..0c07df9fd01 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -950,36 +950,6 @@ float ndof_to_angle_axis(struct wmNDOFMotionData* ndof, float axis[3]) return angle; } -#if 0 // unused utility functions -// returns angular velocity (0..1), fills axis of rotation -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 float ndof_to_angular_velocity(wmNDOFMotionData* ndof) - { - const float x = ndof->rx; - const float y = ndof->ry; - const float z = ndof->rz; - - return sqrtf(x*x + y*y + z*z); - } -#endif - void ndof_to_quat(struct wmNDOFMotionData* ndof, float q[4]) { const float x = ndof->rx; @@ -999,11 +969,10 @@ void ndof_to_quat(struct wmNDOFMotionData* ndof, float q[4]) q[3] = scale * z; } -// Mike's original version: +static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) // -- "orbit" navigation (trackball/turntable) // -- zooming // -- panning in rotationally-locked views -static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) { RegionView3D* rv3d = CTX_wm_region_view3d(C); wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; @@ -1102,205 +1071,6 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } -#if 0 -// statics for controlling rv3d->dist corrections. -// viewmoveNDOF zeros and adjusts rv3d->ofs. -// viewmove restores based on dz_flag state. - -static int dz_flag = 0; -static float m_dist; - -static void mouse_rotation_workaround_push(RegionView3D* rv3d) -{ - // 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. - - float mat[3][3]; - float upvec[3]; - - 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; - } - - // this is still needed in version 2.5 [mce] - // warning! current viewmove does not look at dz_flag or m_dist - // don't expect 2D mouse to work properly right after using 3D mouse -} - -static void mouse_rotation_workaround_pop(RegionView3D* rv3d) -{ - if (dz_flag) { - dz_flag = 0; - rv3d->dist = m_dist; - } -} - -static int ndof_fly_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - RegionView3D* rv3d = CTX_wm_region_view3d(C); - wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; - - const int shouldRotate = 1, shouldTranslate = 0; - - const float dt = ndof->dt; - - float view_inv[4]; - invert_qt_qt(view_inv, rv3d->viewquat); - - if (shouldRotate) - { - const float turn_sensitivity = 1.f; - - float rot[4]; - float view_inv_conj[4]; - mouse_rotation_workaround_push(rv3d); - - ndof_to_quat(ndof, rot); - - copy_qt_qt(view_inv_conj, view_inv); - conjugate_qt(view_inv_conj); - - // transform rotation from view to world coordinates - mul_qt_qtqt(rot, view_inv, rot); - mul_qt_qtqt(rot, rot, view_inv_conj); - - // apply rotation to view offset (focal point) - mul_qt_v3(rot, rv3d->ofs); -// mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); - - rv3d->view = RV3D_VIEW_USER; - } - - if (shouldTranslate) - { - const float forward_sensitivity = 1.f; - const float vertical_sensitivity = 1.f; - const float lateral_sensitivity = 1.f; - - float trans[3] = { - lateral_sensitivity * ndof->tx, - vertical_sensitivity * ndof->ty, - forward_sensitivity * ndof->tz - }; - -// mul_v3_fl(trans, rv3d->dist * dt); - mul_v3_fl(trans, dt); - - /* transform motion from view to world coordinates */ - mul_qt_v3(view_inv, trans); - - /* move center of view opposite of hand motion (this is camera mode, not object mode) */ - sub_v3_v3(rv3d->ofs, trans); - } - - ED_region_tag_redraw(CTX_wm_region(C)); - - return OPERATOR_FINISHED; -} - -// BEGIN old fly code -// derived from blender 2.4 - -static void getndof(wmNDOFMotionData* indof, float* outdof) -{ - // Rotations feel relatively faster than translations only in fly mode, so - // we have no choice but to fix that here (not in the plugins) - const float turn_sensitivity = 0.8f; - - const float forward_sensitivity = 2.5f; - const float vertical_sensitivity = 1.6f; - const float lateral_sensitivity = 2.5f; - - const float dt = indof->dt; - - outdof[0] = lateral_sensitivity * dt * indof->tx; - outdof[1] = vertical_sensitivity * dt * indof->ty; - outdof[2] = forward_sensitivity * dt * indof->tz; - - outdof[3] = turn_sensitivity * dt * indof->rx; - outdof[4] = turn_sensitivity * dt * indof->ry; - outdof[5] = turn_sensitivity * dt * indof->rz; -} - - -static int ndof_oldfly_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - RegionView3D* rv3d = CTX_wm_region_view3d(C); - wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; - - float phi; - float dval[6]; - float tvec[3], rvec[3]; - float q1[4]; - float mat[3][3]; - - // fetch the current state of the ndof device - getndof(ndof, dval); - - // force perspective mode. This is a hack and is - // incomplete. It doesn't actually affect 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 - mouse_rotation_workaround_push(rv3d); - - // Apply rotation - rvec[0] = dval[3]; - rvec[1] = dval[4]; - rvec[2] = 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); - -// mouse_rotation_workaround_pop(rv3d); - - // back to 2.5 land! - ED_region_tag_redraw(CTX_wm_region(C)); - return OPERATOR_FINISHED; -} - -// END old fly code -#endif - void VIEW3D_OT_ndof(struct wmOperatorType *ot) { /* identifiers */ @@ -1310,8 +1080,6 @@ void VIEW3D_OT_ndof(struct wmOperatorType *ot) /* api callbacks */ ot->invoke = ndof_orbit_invoke; -// ot->invoke = ndof_fly_invoke; -// ot->invoke = ndof_oldfly_invoke; ot->poll = ED_operator_view3d_active; /* flags */ -- cgit v1.2.3 From 3ad978ea8ec425e000fd1d79944b47b037f2f3f6 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 18 Jul 2011 22:37:48 +0000 Subject: switched off ndof fly logging (receiving end) --- source/blender/editors/space_view3d/view3d_fly.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 00adfa13e28..ec17aa9586f 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -29,6 +29,8 @@ /* defines VIEW3D_OT_fly modal operator */ +// #define NDOF_FLY_DEBUG + #include "DNA_anim_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" @@ -259,7 +261,9 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even fly->ar = CTX_wm_region(C); fly->scene= CTX_data_scene(C); + #ifdef NDOF_FLY_DEBUG puts("\n-- fly begin --"); + #endif if(fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->id.lib) { BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library"); @@ -370,7 +374,9 @@ static int flyEnd(bContext *C, FlyInfo *fly) if(fly->state == FLY_RUNNING) return OPERATOR_RUNNING_MODAL; + #ifdef NDOF_FLY_DEBUG puts("\n-- fly end --"); + #endif WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), fly->timer); @@ -444,11 +450,15 @@ static void flyEvent(FlyInfo *fly, wmEvent *event) { case P_STARTING: // start keeping track of 3D mouse position + #ifdef NDOF_FLY_DEBUG puts("start keeping track of 3D mouse position"); + #endif // fall through... case P_IN_PROGRESS: // update 3D mouse position + #ifdef NDOF_FLY_DEBUG putchar('.'); fflush(stdout); + #endif if (fly->ndof == NULL) // fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); fly->ndof = MEM_dupallocN(incoming_ndof); @@ -458,7 +468,9 @@ static void flyEvent(FlyInfo *fly, wmEvent *event) break; case P_FINISHING: // stop keeping track of 3D mouse position + #ifdef NDOF_FLY_DEBUG puts("stop keeping track of 3D mouse position"); + #endif if (fly->ndof) { MEM_freeN(fly->ndof); @@ -619,8 +631,10 @@ static int flyApply(bContext *C, FlyInfo *fly) unsigned char apply_rotation= 1; /* if the user presses shift they can look about without movinf the direction there looking*/ + #ifdef NDOF_FLY_DEBUG static unsigned int iteration = 1; printf("fly timer %d\n", iteration++); + #endif if(fly->root_parent) ED_view3d_to_m4(prev_view_mat, fly->rv3d->ofs, fly->rv3d->viewquat, fly->rv3d->dist); -- cgit v1.2.3 From 5f47123fded84fed85d6a0713f814c99f68c1ce7 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 18 Jul 2011 22:42:09 +0000 Subject: consistent Starting/InProgress/Finishing ndof events with dead-zone filtering --- intern/ghost/intern/GHOST_NDOFManager.cpp | 117 ++++++++++++++++----------- intern/ghost/intern/GHOST_NDOFManager.h | 18 ++++- intern/ghost/intern/GHOST_NDOFManagerX11.cpp | 2 + intern/ghost/intern/GHOST_SystemX11.cpp | 5 +- 4 files changed, 91 insertions(+), 51 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index e001540aa95..06c792128cd 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -149,6 +149,7 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) , m_prevMotionTime(0) , m_motionState(GHOST_kNotStarted) , m_motionEventPending(false) + , m_deadZone(0.f) { // to avoid the rare situation where one triple is updated and // the other is not, initialize them both here: @@ -201,7 +202,7 @@ void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ } break; default: - printf("ndof: unknown vendor %04hx\n", vendor_id); + printf("ndof: unknown device %04hx:%04hx\n", vendor_id, product_id); } m_buttonMask = ~(-1 << m_buttonCount); @@ -211,41 +212,18 @@ void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ #endif } -void GHOST_NDOFManager::updateMotionState() - { - if (m_motionEventPending) - return; - - switch (m_motionState) - { - case GHOST_kFinished: - case GHOST_kNotStarted: - m_motionState = GHOST_kStarting; - break; - case GHOST_kStarting: - m_motionState = GHOST_kInProgress; - break; - default: - // InProgress remains InProgress - // should never be Finishing - break; - } - - m_motionEventPending = true; - } - void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time) { memcpy(m_translation, t, sizeof(m_translation)); m_motionTime = time; - updateMotionState(); + m_motionEventPending = true; } void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time) { memcpy(m_rotation, r, sizeof(m_rotation)); m_motionTime = time; - updateMotionState(); + m_motionEventPending = true; } void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, bool press, GHOST_TUns64 time, GHOST_IWindow* window) @@ -338,6 +316,20 @@ void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time) } } +void GHOST_NDOFManager::setDeadZone(float dz) + { + if (dz < 0.f) + // negative values don't make sense, so clamp at zero + dz = 0.f; + else if (dz > 0.5f) + // warn the rogue user/programmer, but allow it + printf("ndof: dead zone of %.2f is rather high...\n", dz); + + m_deadZone = dz; + + printf("ndof: dead zone set to %.2f\n", dz); + } + static bool atHomePosition(GHOST_TEventNDOFMotionData* ndof) { #define HOME(foo) (ndof->foo == 0) @@ -346,16 +338,25 @@ static bool atHomePosition(GHOST_TEventNDOFMotionData* ndof) static bool nearHomePosition(GHOST_TEventNDOFMotionData* ndof, float threshold) { - #define HOME1(foo) (fabsf(ndof->foo) < threshold) - return HOME1(tx) && HOME1(ty) && HOME1(tz) && HOME1(rx) && HOME1(ry) && HOME1(rz); + if (threshold == 0.f) + return atHomePosition(ndof); + else + { + #define HOME1(foo) (fabsf(ndof->foo) < threshold) + return HOME1(tx) && HOME1(ty) && HOME1(tz) && HOME1(rx) && HOME1(ry) && HOME1(rz); + } } bool GHOST_NDOFManager::sendMotionEvent() { - if (m_motionState == GHOST_kFinished || m_motionState == GHOST_kNotStarted) + if (!m_motionEventPending) return false; + m_motionEventPending = false; // any pending motion is handled right now + GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); + if (window == NULL) + return false; // delivery will fail, so don't bother sending GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, window); GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData(); @@ -363,7 +364,7 @@ bool GHOST_NDOFManager::sendMotionEvent() const float scale = 1.f / 350.f; // 3Dconnexion devices send +/- 350 usually // probable future enhancement - // scale *= m_sensitivity; + // scale *= U.ndof_sensitivity; data->tx = scale * m_translation[0]; data->ty = scale * m_translation[1]; @@ -373,35 +374,57 @@ bool GHOST_NDOFManager::sendMotionEvent() data->ry = scale * m_rotation[1]; data->rz = scale * m_rotation[2]; - if (m_motionState == GHOST_kStarting) - // prev motion time will be ancient, so just make up something reasonable - data->dt = 0.0125f; - else - data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds + data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds - m_prevMotionTime = m_motionTime; + bool handMotion = !nearHomePosition(data, m_deadZone); - // 'at rest' test goes at the end so that the first 'rest' event gets sent - if (atHomePosition(data)) -// if (nearHomePosition(data, 0.05f)) // Linux & Windows have trouble w/ calibration + // determine what kind of motion event to send (Starting, InProgress, Finishing) + // and where that leaves this NDOF manager (NotStarted, InProgress, Finished) + switch (m_motionState) { - data->progress = GHOST_kFinishing; - // for internal state, skip Finishing & jump to Finished - m_motionState = GHOST_kFinished; + case GHOST_kNotStarted: + case GHOST_kFinished: + if (handMotion) + { + data->progress = GHOST_kStarting; + m_motionState = GHOST_kInProgress; + // prev motion time will be ancient, so just make up something reasonable + data->dt = 0.0125f; + } + else + { + // send no event and keep current state + delete event; + return false; + } + break; + case GHOST_kInProgress: + if (handMotion) + { + data->progress = GHOST_kInProgress; + // keep InProgress state + } + else + { + data->progress = GHOST_kFinishing; + m_motionState = GHOST_kFinished; + } + break; } - else - data->progress = m_motionState; // Starting or InProgress #ifdef DEBUG_NDOF_MOTION - printf("ndof %s: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", - progress_string[data->progress], + printf("ndof motion sent -- %s\n", progress_string[data->progress]); + + // show details about this motion event + printf(" T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", data->tx, data->ty, data->tz, data->rx, data->ry, data->rz, data->dt); #endif m_system.pushEvent(event); - m_motionEventPending = false; + + m_prevMotionTime = m_motionTime; return true; } diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 79e3a4eb4c8..9c67daa4412 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -30,7 +30,12 @@ // #define DEBUG_NDOF_MOTION #define DEBUG_NDOF_BUTTONS -typedef enum { NDOF_UnknownDevice, NDOF_SpaceNavigator, NDOF_SpaceExplorer, NDOF_SpacePilotPro } NDOF_DeviceT; +typedef enum { + NDOF_UnknownDevice, // <-- motion will work fine, buttons are ignored + NDOF_SpaceNavigator, + NDOF_SpaceExplorer, + NDOF_SpacePilotPro + } NDOF_DeviceT; // NDOF device button event types typedef enum { @@ -50,6 +55,7 @@ typedef enum { NDOF_BUTTON_ISO1, NDOF_BUTTON_ISO2, // 90 degree rotations + // these don't all correspond to physical buttons NDOF_BUTTON_ROLL_CW, NDOF_BUTTON_ROLL_CCW, NDOF_BUTTON_SPIN_CW, @@ -63,6 +69,7 @@ typedef enum { NDOF_BUTTON_PLUS, NDOF_BUTTON_MINUS, // general-purpose buttons + // TODO: expose these to keymap editor so users can assign functions NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_3, @@ -90,6 +97,12 @@ public: // use standard USB/HID identifiers void setDevice(unsigned short vendor_id, unsigned short product_id); + // filter out small/accidental/uncalibrated motions by + // setting up a "dead zone" around home position + // set to 0 to disable + // 0.1 is a safe and reasonable value + void setDeadZone(float); + // the latest raw axis data from the device // NOTE: axis data should be in blender view coordinates // +X is to the right @@ -118,7 +131,6 @@ protected: private: void sendButtonEvent(NDOF_ButtonT, bool press, GHOST_TUns64 time, GHOST_IWindow*); void sendKeyEvent(GHOST_TKey, bool press, GHOST_TUns64 time, GHOST_IWindow*); - void updateMotionState(); NDOF_DeviceT m_deviceType; int m_buttonCount; @@ -130,8 +142,10 @@ private: GHOST_TUns64 m_motionTime; // in milliseconds GHOST_TUns64 m_prevMotionTime; // time of most recent Motion event sent + GHOST_TProgress m_motionState; bool m_motionEventPending; + float m_deadZone; // discard motion with each component < this }; #endif diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp index cc2b2f785ea..a823c3c8a81 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp @@ -34,6 +34,8 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys) { m_available = true; + setDeadZone(0.1f); // how to calibrate on Linux? throw away slight motion! + // determine exactly which device is plugged in #define MAX_LINE_LENGTH 100 diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 4c62e5e62b4..f9b365fd62e 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -597,7 +597,8 @@ GHOST_SystemX11::processEvent(XEvent *xe) { XFocusChangeEvent &xfe = xe->xfocus; - printf("X: focus %s for window %d\n", xfe.type == FocusIn ? "in" : "out", (int) xfe.window); + // TODO: make sure this is the correct place for activate/deactivate + // printf("X: focus %s for window %d\n", xfe.type == FocusIn ? "in" : "out", (int) xfe.window); // May have to look at the type of event and filter some // out. @@ -687,7 +688,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) ); } - printf("X: %s window %d\n", xce.type == EnterNotify ? "entering" : "leaving", (int) xce.window); + // printf("X: %s window %d\n", xce.type == EnterNotify ? "entering" : "leaving", (int) xce.window); if (xce.type == EnterNotify) m_windowManager->setActiveWindow(window); -- cgit v1.2.3 From 7f74abeaca38d0c1634a8d0532bb38877a1f730e Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 19 Jul 2011 04:12:49 +0000 Subject: translated ndof menu from C to Python, enabled helicopter fly mode --- release/scripts/startup/bl_ui/space_view3d.py | 19 +++++++ source/blender/editors/space_view3d/view3d_fly.c | 9 +++ source/blender/windowmanager/intern/wm_operators.c | 64 +++++++--------------- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 02004283264..a8a15b674b0 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -352,6 +352,25 @@ class VIEW3D_MT_view_navigation(bpy.types.Menu): layout.operator("view3d.fly") +class VIEW3D_MT_ndof_settings(bpy.types.Menu): + bl_label = "3D Mouse Settings" + + def draw(self, context): + layout = self.layout + input_prefs = context.user_preferences.inputs + + layout.separator() + layout.prop(input_prefs, "ndof_sensitivity") + + if context.space_data.type == 'VIEW_3D': + layout.separator() + layout.prop(input_prefs, "ndof_show_guide") + + layout.separator() + layout.prop(input_prefs, "ndof_fly_helicopter", icon='NDOF_FLY') + layout.prop(input_prefs, "ndof_lock_horizon", icon='NDOF_DOM') + + class VIEW3D_MT_view_align(bpy.types.Menu): bl_label = "Align View" diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index ec17aa9586f..8269d0e7cd3 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -973,6 +973,15 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) // transform motion from view to world coordinates mul_qt_v3(view_inv, trans); + // int fly_mode = TRUE; + int fly_mode = U.ndof_flag & NDOF_FLY_HELICOPTER; + // could also use RNA to get a simple boolean value + + if (fly_mode) + { + trans[2] = speed * dt * vertical_sensitivity * ndof->ty; + } + // move center of view opposite of hand motion (this is camera mode, not object mode) sub_v3_v3(rv3d->ofs, trans); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 6fb6a8dcf1f..7e93c2d5f46 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1401,37 +1401,6 @@ static uiBlock* wm_block_ndof_menu_1st(bContext* C, ARegion* ar, void* UNUSED(ar return block; } -static uiBlock *wm_block_ndof_menu(bContext *C, ARegion *ar, void *UNUSED(arg_op)) -{ - static char search[256]= ""; - wmEvent event; - wmWindow *win= CTX_wm_window(C); - uiBlock *block; - uiBut *but; - - block= uiBeginBlock(C, ar, "ndof_popup", UI_EMBOSS); -// uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT); - uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_POPUP|UI_BLOCK_MOVEMOUSE_QUIT); - - but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 9*UI_UNIT_X, UI_UNIT_Y, 0, 0, ""); - uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); - - /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 9*UI_UNIT_X, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); - - uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */ - uiEndBlock(C, block); - - event= *(win->eventstate); /* XXX huh huh? make api call */ - event.type= EVT_BUT_OPEN; - event.val= KM_PRESS; - event.customdata= but; - event.customdatafree= FALSE; - wm_event_add(win, &event); - - return block; -} - static int wm_ndof_menu_poll(bContext *C) { if(CTX_wm_window(C)==NULL) @@ -1453,6 +1422,11 @@ static int wm_ndof_menu_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) static int wm_ndof_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { + uiPupMenuInvoke(C,"VIEW3D_MT_ndof_settings"); + + return OPERATOR_CANCELLED; // <-- correct? + +/* // uiPupMenuNotice(C, "Hello!"); // <-- this works // uiPupBlock(C, wm_block_ndof_menu, op); // <-- no luck! // ui_popup_menu_create(C, NULL, NULL, NULL, NULL, "Hello!"); // <-- this works @@ -1460,12 +1434,25 @@ static int wm_ndof_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even uiPopupMenu* pup = uiPupMenuBegin(C,"3D mouse settings",ICON_NDOF_TURN); uiLayout* layout = uiPupMenuLayout(pup); + uiItemS(layout); // separator + uiItemFloatO(layout, "sensitivity", 0, 0, "ndof_sensitivity", 1.f); + // do I have to look specifically in "UserPreferences" for ndof_sensitivity property? + + // trial & error -- ok, mostly error +// uiItemBooleanO(layout, "enable pan/zoom", ICON_NDOF_TRANS, "ndof_toggle_pan_zoom_enabled", "ndof_pan_zoom_enabled", 1); +// uiItemBooleanO(layout, "enable rotation", ICON_NDOF_TURN, "ndof_toggle_rotation_enabled", "ndof_rotation_enabled", 1); +// uiItemV(layout,"sensitivity",ICON_NDOF_TRANS, 1); + printf("ndof: menu invoked in "); switch (CTX_wm_area(C)->spacetype) // diff spaces can have diff 3d mouse options { case SPACE_VIEW3D: puts("3D area"); + uiItemS(layout); + uiItemL(layout, "3D navigation mode", 0); + uiItemBooleanO(layout, "helicopter", ICON_NDOF_FLY, 0, "ndof_fly_helicopter", 1); + uiItemBooleanO(layout, "lock horizon", ICON_NDOF_DOM, 0, "ndof_lock_horizon", 1); break; case SPACE_IMAGE: puts("image area"); @@ -1474,25 +1461,12 @@ static int wm_ndof_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even puts("some iNDOFferent area"); } - //uiBlock* block = uiLayoutGetBlock(layout); //int foo = 1; //uiDefButI(block, TOG, 0, "foo", 10, 10, 9*UI_UNIT_X, UI_UNIT_Y, &foo, 0.f, 1.f, 0.1f, 0.9f, "15%"); - - uiItemS(layout); // separator - - uiItemBooleanO(layout, "enable pan/zoom", ICON_NDOF_TRANS, "ndof_toggle_pan_zoom_enabled", "ndof_pan_zoom_enabled", 1); - uiItemBooleanO(layout, "enable rotation", ICON_NDOF_TURN, "ndof_toggle_rotation_enabled", "ndof_rotation_enabled", 1); - uiItemFloatO(layout, "sensitivity", 0, "ndof_adjust_sensitivity", "ndof_sensitivity", 1.f); - uiItemV(layout,"sensitivity",ICON_NDOF_TRANS, 1); - - uiItemS(layout); - uiItemL(layout, "3D navigation mode", ICON_NDOF_FLY); - uiItemL(layout, "...", 0); uiPupMenuEnd(C,pup); - - return OPERATOR_CANCELLED; // <-- correct? +*/ } static void WM_OT_ndof_menu(wmOperatorType *ot) -- cgit v1.2.3 From c89379e7e15aeb50a7d7106218821a17e5a7dac9 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 19 Jul 2011 22:40:22 +0000 Subject: ndof fly: better sharing of control between 2D and 3D mouse, compile fix for MSVC, lock horizon implemented --- source/blender/editors/space_view3d/view3d_fly.c | 77 ++++++++++++++++-------- 1 file changed, 52 insertions(+), 25 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 8269d0e7cd3..6955aefcb9e 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -477,6 +477,8 @@ static void flyEvent(FlyInfo *fly, wmEvent *event) // free(fly->ndof); fly->ndof = NULL; } + /* update the time else the view will jump when 2D mouse/timer resume */ + fly->time_lastdraw= PIL_check_seconds_timer(); break; default: ; // should always be one of the above 3 @@ -933,26 +935,6 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) float view_inv[4]; invert_qt_qt(view_inv, rv3d->viewquat); - if (shouldRotate) - { - const float turn_sensitivity = 1.f; - - float rotation[4]; - float axis[3]; - float angle = turn_sensitivity * ndof_to_angle_axis(ndof, axis); - - // transform rotation axis from view to world coordinates - mul_qt_v3(view_inv, axis); - - // apply rotation to view - axis_angle_to_quat(rotation, axis, angle); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); - - rv3d->view = RV3D_VIEW_USER; - - fly->redraw = 1; - } - if (shouldTranslate) { const float forward_sensitivity = 1.f; @@ -973,12 +955,10 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) // transform motion from view to world coordinates mul_qt_v3(view_inv, trans); - // int fly_mode = TRUE; - int fly_mode = U.ndof_flag & NDOF_FLY_HELICOPTER; - // could also use RNA to get a simple boolean value - - if (fly_mode) + if (U.ndof_flag & NDOF_FLY_HELICOPTER) + // could also use RNA to get a simple boolean value { + // replace world z component with device y (yes it makes sense) trans[2] = speed * dt * vertical_sensitivity * ndof->ty; } @@ -988,6 +968,53 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) fly->redraw = 1; } + if (shouldRotate) + { + const float turn_sensitivity = 1.f; + + float rotation[4]; + float axis[3]; + float angle = turn_sensitivity * ndof_to_angle_axis(ndof, axis); + + // transform rotation axis from view to world coordinates + mul_qt_v3(view_inv, axis); + + // apply rotation to view + axis_angle_to_quat(rotation, axis, angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); + + if (U.ndof_flag & NDOF_LOCK_HORIZON) + // force an upright viewpoint + // TODO: make this less... sudden + { + float view_horizon[3] = {1, 0, 0}; // view +x + float view_direction[3] = {0, 0, -1}; // view -z (into screen) + + // find new inverse since viewquat has changed + invert_qt_qt(view_inv, rv3d->viewquat); + + // transform view vectors to world coordinates + mul_qt_v3(view_inv, view_horizon); + mul_qt_v3(view_inv, view_direction); + + // find difference between view & world horizons + // true horizon lives in world xy plane, so look only at difference in z + angle = -asinf(view_horizon[2]); + + #ifdef NDOF_FLY_DEBUG + printf("lock horizon: adjusting %.1f degrees\n\n", RAD2DEG(angle)); + #endif + + // rotate view so view horizon = world horizon + axis_angle_to_quat(rotation, view_direction, angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); + } + + rv3d->view = RV3D_VIEW_USER; + + fly->redraw = 1; + } + return OPERATOR_FINISHED; } -- cgit v1.2.3 From b326a6841ecae45a59ba14f51741e66788961cea Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Thu, 21 Jul 2011 20:54:47 +0000 Subject: Simple ifndef guards, so we don't get redefines. --- intern/ghost/intern/GHOST_SystemPathsWin32.cpp | 2 ++ intern/ghost/intern/GHOST_SystemWin32.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp index ae376bc37a5..523d119c7e7 100644 --- a/intern/ghost/intern/GHOST_SystemPathsWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemPathsWin32.cpp @@ -32,7 +32,9 @@ #include "GHOST_SystemPathsWin32.h" +#ifndef _WIN32_IE #define _WIN32_IE 0x0501 +#endif #include #if defined(__MINGW32__) || defined(__CYGWIN__) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index d5dd77b7c83..2a3eb74d1e2 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -48,7 +48,9 @@ #include "GHOST_SystemWin32.h" #include "GHOST_EventDragnDrop.h" +#ifndef _WIN32_IE #define _WIN32_IE 0x0501 /* shipped before XP, so doesn't impose additional requirements */ +#endif #include // win64 doesn't define GWL_USERDATA -- cgit v1.2.3 From 1cce0dd505b72b1e1b2188c9f72fa73d73e6ec4d Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Thu, 21 Jul 2011 20:57:23 +0000 Subject: Prepare for NDOF event handling all the way to keymaps (and keymap editor). --- source/blender/windowmanager/wm_event_types.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index 210dd902b99..579f20ca605 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -125,6 +125,7 @@ enum { NDOF_BUTTON_8, NDOF_BUTTON_9, NDOF_BUTTON_10, + NDOF_LAST }; @@ -290,8 +291,11 @@ enum { /* test whether the event is tweak event */ #define ISTWEAK(event) (event >= EVT_TWEAK_L && event <= EVT_GESTURE) + /* test whether the event is a NDOF event */ +#define ISNDOF(event) (event >= NDOF_MOTION && event < NDOF_LAST) + /* test whether event type is acceptable as hotkey, excluding modifiers */ -#define ISHOTKEY(event) ((ISKEYBOARD(event) || ISMOUSE(event)) && event!=ESCKEY && !(event>=LEFTCTRLKEY && event<=LEFTSHIFTKEY) && !(event>=UNKNOWNKEY && event<=GRLESSKEY)) +#define ISHOTKEY(event) ((ISKEYBOARD(event) || ISMOUSE(event) || ISNDOF(event)) && event!=ESCKEY && !(event>=LEFTCTRLKEY && event<=LEFTSHIFTKEY) && !(event>=UNKNOWNKEY && event<=GRLESSKEY)) /* **************** BLENDER GESTURE EVENTS (0x5000) **************** */ -- cgit v1.2.3 From 6cd4716d1a55d9f1b407d0196604f31aabec6c5a Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 21 Jul 2011 21:34:28 +0000 Subject: enable CMake builds with spacenav (contributed by Kevin Cozens) --- CMakeLists.txt | 2 +- build_files/cmake/macros.cmake | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb59b35f406..19d9ea942a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -457,7 +457,7 @@ if(UNIX AND NOT APPLE) set(NDOF /usr) set(NDOF_INC ${NDOF}/include) set(NDOF_LIB spnav) - set(NDOF_LIBPATH ${FFTW3}/lib) + set(NDOF_LIBPATH ${NDOF}/lib) endif() endif() diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 34301458a06..3de9db6dac9 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -193,6 +193,9 @@ macro(SETUP_LIBDIRS) if(WITH_MEM_JEMALLOC) link_directories(${JEMALLOC_LIBPATH}) endif() + if(WITH_NDOF) + link_directories(${NDOF_LIBPATH}) + endif() if(WIN32 AND NOT UNIX) link_directories(${PTHREADS_LIBPATH}) @@ -314,6 +317,10 @@ macro(setup_liblinks if(WITH_MEM_JEMALLOC) target_link_libraries(${target} ${JEMALLOC_LIBRARIES}) endif() + if(WITH_NDOF) + target_link_libraries(${target} ${NDOF_LIBRARY}) + endif() + if(WIN32 AND NOT UNIX) target_link_libraries(${target} ${PTHREADS_LIBRARIES}) endif() -- cgit v1.2.3 From 2258afc1be78a2cd629f0efb8e5d69acc4c58d2c Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Thu, 21 Jul 2011 21:40:00 +0000 Subject: Handle NDOF events on RNA side for windowmanager. --- source/blender/makesrna/intern/rna_wm.c | 88 ++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 7ea4701dec3..31e1d73c8de 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -106,6 +106,46 @@ EnumPropertyItem event_timer_type_items[]= { {TIMER2, "TIMER2", 0, "Timer 2", ""}, {0, NULL, 0, NULL, NULL}}; +EnumPropertyItem event_ndof_type_items[]= { + /* buttons on all 3dconnexion devices */ + {NDOF_BUTTON_MENU, "NDOF_BUTTON_MENU", 0, "Menu", ""}, + {NDOF_BUTTON_FIT, "NDOF_BUTTON_FIT", 0, "Fit", ""}, + /* view buttons */ + {NDOF_BUTTON_TOP, "NDOF_BUTTON_TOP", 0, "Top", ""}, + {NDOF_BUTTON_BOTTOM, "NDOF_BUTTON_BOTTOM", 0, "Bottom", ""}, + {NDOF_BUTTON_LEFT, "NDOF_BUTTON_LEFT", 0, "Left", ""}, + {NDOF_BUTTON_RIGHT, "NDOF_BUTTON_RIGHT", 0, "Right", ""}, + {NDOF_BUTTON_FRONT, "NDOF_BUTTON_FRONT", 0, "Front", ""}, + {NDOF_BUTTON_BACK, "NDOF_BUTTON_BACK", 0, "Back", ""}, + /* more views */ + {NDOF_BUTTON_ISO1, "NDOF_BUTTON_ISO1", 0, "ISO 1", ""}, + {NDOF_BUTTON_ISO2, "NDOF_BUTTON_ISO2", 0, "ISO 2", ""}, + /* 90 degree rotations */ + {NDOF_BUTTON_ROLL_CW, "NDOF_BUTTON_ROLL_CW", 0, "Roll CW", ""}, + {NDOF_BUTTON_ROLL_CCW, "NDOF_BUTTON_ROLL_CCW", 0, "Roll CCW", ""}, + {NDOF_BUTTON_SPIN_CW, "NDOF_BUTTON_SPIN_CW", 0, "Spin CW", ""}, + {NDOF_BUTTON_SPIN_CCW, "NDOF_BUTTON_SPIN_CCW", 0, "Spin CCW", ""}, + {NDOF_BUTTON_TILT_CW, "NDOF_BUTTON_TILT_CW", 0, "Tilt CW", ""}, + {NDOF_BUTTON_TILT_CCW, "NDOF_BUTTON_TILT_CCW", 0, "Tilt CCW", ""}, + /* device control */ + {NDOF_BUTTON_ROTATE, "NDOF_BUTTON_ROTATE", 0, "Rotate", ""}, + {NDOF_BUTTON_PANZOOM, "NDOF_BUTTON_PANZOOM", 0, "Pan/Zoom", ""}, + {NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "Dominant", ""}, + {NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "Plus", ""}, + {NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "Minus", ""}, + /* general-purpose buttons */ + {NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "Button 1", ""}, + {NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "Button 2", ""}, + {NDOF_BUTTON_3, "NDOF_BUTTON_3", 0, "Button 3", ""}, + {NDOF_BUTTON_4, "NDOF_BUTTON_4", 0, "Button 4", ""}, + {NDOF_BUTTON_5, "NDOF_BUTTON_5", 0, "Button 5", ""}, + {NDOF_BUTTON_6, "NDOF_BUTTON_6", 0, "Button 6", ""}, + {NDOF_BUTTON_7, "NDOF_BUTTON_7", 0, "Button 7", ""}, + {NDOF_BUTTON_8, "NDOF_BUTTON_8", 0, "Button 8", ""}, + {NDOF_BUTTON_9, "NDOF_BUTTON_9", 0, "Button 9", ""}, + {NDOF_BUTTON_10, "NDOF_BUTTON_10", 0, "Button 10", ""}, + {0, NULL, 0, NULL, NULL}}; + /* not returned: CAPSLOCKKEY, UNKNOWNKEY */ EnumPropertyItem event_type_items[] = { @@ -256,6 +296,44 @@ EnumPropertyItem event_type_items[] = { {TIMER0, "TIMER0", 0, "Timer 0", ""}, {TIMER1, "TIMER1", 0, "Timer 1", ""}, {TIMER2, "TIMER2", 0, "Timer 2", ""}, + {0, "", 0, NULL, NULL}, + /* buttons on all 3dconnexion devices */ + {NDOF_BUTTON_MENU, "NDOF_BUTTON_MENU", 0, "Menu", ""}, + {NDOF_BUTTON_FIT, "NDOF_BUTTON_FIT", 0, "Fit", ""}, + /* view buttons */ + {NDOF_BUTTON_TOP, "NDOF_BUTTON_TOP", 0, "Top", ""}, + {NDOF_BUTTON_BOTTOM, "NDOF_BUTTON_BOTTOM", 0, "Bottom", ""}, + {NDOF_BUTTON_LEFT, "NDOF_BUTTON_LEFT", 0, "Left", ""}, + {NDOF_BUTTON_RIGHT, "NDOF_BUTTON_RIGHT", 0, "Right", ""}, + {NDOF_BUTTON_FRONT, "NDOF_BUTTON_FRONT", 0, "Front", ""}, + {NDOF_BUTTON_BACK, "NDOF_BUTTON_BACK", 0, "Back", ""}, + /* more views */ + {NDOF_BUTTON_ISO1, "NDOF_BUTTON_ISO1", 0, "ISO 1", ""}, + {NDOF_BUTTON_ISO2, "NDOF_BUTTON_ISO2", 0, "ISO 2", ""}, + /* 90 degree rotations */ + {NDOF_BUTTON_ROLL_CW, "NDOF_BUTTON_ROLL_CW", 0, "Roll CW", ""}, + {NDOF_BUTTON_ROLL_CCW, "NDOF_BUTTON_ROLL_CCW", 0, "Roll CCW", ""}, + {NDOF_BUTTON_SPIN_CW, "NDOF_BUTTON_SPIN_CW", 0, "Spin CW", ""}, + {NDOF_BUTTON_SPIN_CCW, "NDOF_BUTTON_SPIN_CCW", 0, "Spin CCW", ""}, + {NDOF_BUTTON_TILT_CW, "NDOF_BUTTON_TILT_CW", 0, "Tilt CW", ""}, + {NDOF_BUTTON_TILT_CCW, "NDOF_BUTTON_TILT_CCW", 0, "Tilt CCW", ""}, + /* device control */ + {NDOF_BUTTON_ROTATE, "NDOF_BUTTON_ROTATE", 0, "Rotate", ""}, + {NDOF_BUTTON_PANZOOM, "NDOF_BUTTON_PANZOOM", 0, "Pan/Zoom", ""}, + {NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "Dominant", ""}, + {NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "Plus", ""}, + {NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "Minus", ""}, + /* general-purpose buttons */ + {NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "Button 1", ""}, + {NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "Button 2", ""}, + {NDOF_BUTTON_3, "NDOF_BUTTON_3", 0, "Button 3", ""}, + {NDOF_BUTTON_4, "NDOF_BUTTON_4", 0, "Button 4", ""}, + {NDOF_BUTTON_5, "NDOF_BUTTON_5", 0, "Button 5", ""}, + {NDOF_BUTTON_6, "NDOF_BUTTON_6", 0, "Button 6", ""}, + {NDOF_BUTTON_7, "NDOF_BUTTON_7", 0, "Button 7", ""}, + {NDOF_BUTTON_8, "NDOF_BUTTON_8", 0, "Button 8", ""}, + {NDOF_BUTTON_9, "NDOF_BUTTON_9", 0, "Button 9", ""}, + {NDOF_BUTTON_10, "NDOF_BUTTON_10", 0, "Button 10", ""}, {0, NULL, 0, NULL, NULL}}; EnumPropertyItem keymap_propvalue_items[] = { @@ -303,6 +381,7 @@ EnumPropertyItem wm_report_items[] = { #define KMI_TYPE_TWEAK 2 #define KMI_TYPE_TEXTINPUT 3 #define KMI_TYPE_TIMER 4 +#define KMI_TYPE_NDOF 5 #ifdef RNA_RUNTIME @@ -433,6 +512,7 @@ static int rna_wmKeyMapItem_map_type_get(PointerRNA *ptr) if(ISKEYBOARD(kmi->type)) return KMI_TYPE_KEYBOARD; if(ISTWEAK(kmi->type)) return KMI_TYPE_TWEAK; if(ISMOUSE(kmi->type)) return KMI_TYPE_MOUSE; + if(ISNDOF(kmi->type)) return KMI_TYPE_NDOF; if(kmi->type == KM_TEXTINPUT) return KMI_TYPE_TEXTINPUT; return KMI_TYPE_KEYBOARD; } @@ -464,6 +544,10 @@ static void rna_wmKeyMapItem_map_type_set(PointerRNA *ptr, int value) kmi->type= TIMER; kmi->val= KM_NOTHING; break; + case KMI_TYPE_NDOF: + kmi->type = NDOF_BUTTON_MENU; + kmi->val = KM_NOTHING; + break; } } } @@ -475,6 +559,7 @@ static EnumPropertyItem *rna_KeyMapItem_type_itemf(bContext *UNUSED(C), PointerR if(map_type == KMI_TYPE_MOUSE) return event_mouse_type_items; if(map_type == KMI_TYPE_TWEAK) return event_tweak_type_items; if(map_type == KMI_TYPE_TIMER) return event_timer_type_items; + if(map_type == KMI_TYPE_NDOF) return event_ndof_type_items; else return event_type_items; } @@ -482,7 +567,7 @@ static EnumPropertyItem *rna_KeyMapItem_value_itemf(bContext *UNUSED(C), Pointer { int map_type= rna_wmKeyMapItem_map_type_get(ptr); - if(map_type == KMI_TYPE_MOUSE || map_type == KMI_TYPE_KEYBOARD) return event_keymouse_value_items; + if(map_type == KMI_TYPE_MOUSE || map_type == KMI_TYPE_KEYBOARD || map_type == KMI_TYPE_NDOF) return event_keymouse_value_items; if(map_type == KMI_TYPE_TWEAK) return event_tweak_value_items; else return event_value_items; } @@ -1653,6 +1738,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) {KMI_TYPE_KEYBOARD, "KEYBOARD", 0, "Keyboard", ""}, {KMI_TYPE_TWEAK, "TWEAK", 0, "Tweak", ""}, {KMI_TYPE_MOUSE, "MOUSE", 0, "Mouse", ""}, + {KMI_TYPE_NDOF, "NDOF", 0, "NDOF", ""}, {KMI_TYPE_TEXTINPUT, "TEXTINPUT", 0, "Text Input", ""}, {KMI_TYPE_TIMER, "TIMER", 0, "Timer", ""}, {0, NULL, 0, NULL, NULL}}; -- cgit v1.2.3 From 407a2a8439f61922139a3c5d1607818234924fe1 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 21 Jul 2011 21:40:04 +0000 Subject: tweaked ephemeral ndof data types --- source/blender/editors/space_view3d/view3d_fly.c | 18 +++++++++++++----- source/blender/makesdna/DNA_userdef_types.h | 5 ++--- source/blender/makesdna/DNA_view3d_types.h | 7 +++---- source/blender/makesrna/intern/rna_userdef.c | 16 +++------------- 4 files changed, 21 insertions(+), 25 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 6955aefcb9e..1122438da96 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -929,8 +929,15 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) wmNDOFMotionData* ndof = fly->ndof; const float dt = ndof->dt; RegionView3D* rv3d = fly->rv3d; + const int flag = U.ndof_flag; - const int shouldRotate = 1, shouldTranslate = 1; + const int shouldRotate = TRUE, + shouldTranslate = TRUE; + + // const int shouldRotate = flag & NDOF_SHOULD_ROTATE, + // shouldTranslate = flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM); + // might also be something in FlyInfo that restricts motion + // if so, change these ^^ float view_inv[4]; invert_qt_qt(view_inv, rv3d->viewquat); @@ -955,7 +962,7 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) // transform motion from view to world coordinates mul_qt_v3(view_inv, trans); - if (U.ndof_flag & NDOF_FLY_HELICOPTER) + if (flag & NDOF_FLY_HELICOPTER) // could also use RNA to get a simple boolean value { // replace world z component with device y (yes it makes sense) @@ -981,9 +988,9 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) // apply rotation to view axis_angle_to_quat(rotation, axis, angle); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); - if (U.ndof_flag & NDOF_LOCK_HORIZON) + if (flag & NDOF_LOCK_HORIZON) // force an upright viewpoint // TODO: make this less... sudden { @@ -992,6 +999,7 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) // find new inverse since viewquat has changed invert_qt_qt(view_inv, rv3d->viewquat); + // could apply reverse rotation to existing view_inv to save a few cycles // transform view vectors to world coordinates mul_qt_v3(view_inv, view_horizon); @@ -1007,7 +1015,7 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) // rotate view so view horizon = world horizon axis_angle_to_quat(rotation, view_direction, angle); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); } rv3d->view = RV3D_VIEW_USER; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index a94c10a7aa0..6fbdb9842d6 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -365,7 +365,6 @@ typedef struct UserDef { short recent_files; /* maximum number of recently used files to remember */ short smooth_viewtx; /* miliseconds to spend spinning the view */ short glreslimit; -/* short ndof_pan, ndof_rotate; */ short curssize; short color_picker_type; short ipo_new; /* interpolation mode for newly added F-Curves */ @@ -586,11 +585,11 @@ extern UserDef U; /* from blenkernel blender.c */ #define NDOF_FLY_HELICOPTER (1 << 1) #define NDOF_LOCK_HORIZON (1 << 2) /* the following might not need to be saved between sessions, - but they do need to live somewhere accessible... + but they do need to live somewhere accessible... */ #define NDOF_SHOULD_PAN (1 << 3) #define NDOF_SHOULD_ZOOM (1 << 4) #define NDOF_SHOULD_ROTATE (1 << 5) -*/ + #ifdef __cplusplus } diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 7379493003d..27ffc6d856b 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -190,11 +190,10 @@ typedef struct View3D { /* drawflags, denoting state */ short zbuf, transp, xray; - char ndofmode; /* mode of transform for 6DOF devices -1 not found, 0 normal, 1 fly, 2 ob transform */ - char ndoffilter; /* filter for 6DOF devices 0 normal, 1 dominant */ - + char pad3[2]; + void *properties_storage; /* Nkey panel stores stuff here (runtime only!) */ - + /* XXX depricated? */ struct bGPdata *gpd; /* Grease-Pencil Data (annotation layers) */ diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 664cb7732f9..50b5e99804c 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2739,24 +2739,14 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Drag Threshold", "Amount of pixels you have to drag before dragging UI items happens"); /* 3D mouse settings */ -/* - prop= RNA_def_property(srna, "ndof_pan_speed", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "ndof_pan"); - RNA_def_property_range(prop, 0, 200); - RNA_def_property_ui_text(prop, "NDof Pan Speed", "The overall panning speed of an NDOF device, as percent of standard"); - - prop= RNA_def_property(srna, "ndof_rotate_speed", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "ndof_rotate"); - RNA_def_property_range(prop, 0, 200); - RNA_def_property_ui_text(prop, "NDof Rotation Speed", "The overall rotation speed of an NDOF device, as percent of standard"); -*/ prop= RNA_def_property(srna, "ndof_sensitivity", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.25f, 4.0f); - RNA_def_property_ui_text(prop, "3D Mouse Sensitivity", "Baseline sensitivity of the 3D Mouse"); + RNA_def_property_ui_text(prop, "Sensitivity", "Overall sensitivity of the 3D Mouse"); prop= RNA_def_property(srna, "ndof_show_guide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_SHOW_GUIDE); - RNA_def_property_ui_text(prop, "Show 3D Mouse Guide", "Visualize the center and axis of rotation (or projected position in fly mode)"); + RNA_def_property_ui_text(prop, "Show Navigation Guide", "Display the center and axis during rotation"); + /* TODO: update description when fly-mode visuals are in place ("projected position in fly mode")*/ prop= RNA_def_property(srna, "ndof_lock_horizon", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_LOCK_HORIZON); -- cgit v1.2.3 From 32004f11aaca7d52de2eaaf319dc0ed11b1bb5ff Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Thu, 21 Jul 2011 21:43:42 +0000 Subject: Keymap editor now understands NDOF (button) events too. --- release/scripts/startup/bl_ui/space_userpref_keymap.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/space_userpref_keymap.py b/release/scripts/startup/bl_ui/space_userpref_keymap.py index 85764c55304..8faf1afab63 100644 --- a/release/scripts/startup/bl_ui/space_userpref_keymap.py +++ b/release/scripts/startup/bl_ui/space_userpref_keymap.py @@ -271,6 +271,8 @@ class InputKeyMapPanel: row.prop(kmi, "type", text="", full_event=True) elif map_type == 'MOUSE': row.prop(kmi, "type", text="", full_event=True) + if map_type == 'NDOF': + row.prop(kmi, "type", text="", full_event=True) elif map_type == 'TWEAK': subrow = row.row() subrow.prop(kmi, "type", text="") @@ -306,7 +308,7 @@ class InputKeyMapPanel: sub = split.column() subrow = sub.row(align=True) - if map_type == 'KEYBOARD': + if map_type in ('KEYBOARD', 'NDOF'): subrow.prop(kmi, "type", text="", event=True) subrow.prop(kmi, "value", text="") elif map_type == 'MOUSE': -- cgit v1.2.3 From 7b1bb26135442a63b6f20f14a04ead0453e0958a Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Thu, 21 Jul 2011 22:26:58 +0000 Subject: Show NDOF sensitivity field in userprefs --- release/scripts/startup/bl_ui/space_userpref.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 139b3205835..f35ad71202c 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -817,12 +817,9 @@ class USERPREF_PT_input(bpy.types.Panel, InputKeyMapPanel): #sub.prop(view, "wheel_scroll_lines", text="Scroll Lines") col.separator() - ''' not implemented yet sub = col.column() sub.label(text="NDOF Device:") - sub.prop(inputs, "ndof_pan_speed", text="Pan Speed") - sub.prop(inputs, "ndof_rotate_speed", text="Orbit Speed") - ''' + sub.prop(inputs, "ndof_sensitivity", text="NDOF Sensitivity") row.separator() -- cgit v1.2.3 From 8c5f028f4a8600e961fa0dbe4a884261f10f8098 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Fri, 22 Jul 2011 14:13:28 +0000 Subject: Fix compile error due to faulty merge. --- intern/ghost/intern/GHOST_SystemX11.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index ef182a36539..517c3a1ebac 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -75,6 +75,9 @@ #include // for fprintf only #include // for exit +static GHOST_TKey +convertXKey(KeySym key); + //these are for copy and select copy static char *txt_cut_buffer= NULL; static char *txt_select_buffer= NULL; -- cgit v1.2.3 From 5fae765187b98b6a35c9f674e61bd1a26d09b0c0 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 23 Jul 2011 21:29:19 +0000 Subject: more cautious device detection, minor cleanup --- intern/ghost/intern/GHOST_NDOFManager.cpp | 20 ++++++++++++------ intern/ghost/intern/GHOST_NDOFManager.h | 2 +- intern/ghost/intern/GHOST_NDOFManagerX11.cpp | 31 ++++++++++++++-------------- intern/ghost/intern/GHOST_NDOFManagerX11.h | 2 ++ 4 files changed, 32 insertions(+), 23 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 06c792128cd..69100fefd31 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -157,7 +157,7 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) memset(m_rotation, 0, sizeof(m_rotation)); } -void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short product_id) +bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short product_id) { switch (vendor_id) { @@ -198,18 +198,26 @@ void GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ m_buttonCount = 21; break; - default: printf("ndof: unknown Logitech product %04hx\n", product_id); + default: + printf("ndof: unknown Logitech product %04hx\n", product_id); } break; default: printf("ndof: unknown device %04hx:%04hx\n", vendor_id, product_id); } - m_buttonMask = ~(-1 << m_buttonCount); + if (m_deviceType == NDOF_UnknownDevice) + return false; + else + { + m_buttonMask = ~(-1 << m_buttonCount); - #ifdef DEBUG_NDOF_BUTTONS - printf("ndof: %d buttons -> hex:%X\n", m_buttonCount, m_buttonMask); - #endif + #ifdef DEBUG_NDOF_BUTTONS + printf("ndof: %d buttons -> hex:%X\n", m_buttonCount, m_buttonMask); + #endif + + return true; + } } void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time) diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 9c67daa4412..d259967daa9 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -95,7 +95,7 @@ public: // each platform's device detection should call this // use standard USB/HID identifiers - void setDevice(unsigned short vendor_id, unsigned short product_id); + bool setDevice(unsigned short vendor_id, unsigned short product_id); // filter out small/accidental/uncalibrated motions by // setting up a "dead zone" around home position diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp index a823c3c8a81..233a9b367f1 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp @@ -29,14 +29,13 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys) : GHOST_NDOFManager(sys) + , m_available(false) { + setDeadZone(0.1f); // how to calibrate on Linux? throw away slight motion! + if (spnav_open() != -1) { - m_available = true; - - setDeadZone(0.1f); // how to calibrate on Linux? throw away slight motion! - - // determine exactly which device is plugged in + // determine exactly which device (if any) is plugged in #define MAX_LINE_LENGTH 100 @@ -49,14 +48,17 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys) { unsigned short vendor_id = 0, product_id = 0; if (sscanf(line, "Bus %*d Device %*d: ID %hx:%hx", &vendor_id, &product_id) == 2) - setDevice(vendor_id, product_id); + if (setDevice(vendor_id, product_id)) + { + m_available = true; + break; // stop looking once the first 3D mouse is found + } } pclose(command_output); } } else { - m_available = false; printf("ndof: spacenavd not found\n"); // This isn't a hard error, just means the user doesn't have a 3D mouse. } @@ -73,6 +75,11 @@ bool GHOST_NDOFManagerX11::available() return m_available; } +//bool GHOST_NDOFManagerX11::identifyDevice() +// { +// +// } + bool GHOST_NDOFManagerX11::processEvents() { GHOST_TUns64 now = m_system.getMilliSeconds(); @@ -85,15 +92,7 @@ bool GHOST_NDOFManagerX11::processEvents() { case SPNAV_EVENT_MOTION: { -// "natural" device coords -// short t[3] = {e.motion.x, e.motion.y, e.motion.z}; -// short r[3] = {e.motion.rx, e.motion.ry, e.motion.rz}; - -// blender world coords -// short t[3] = {e.motion.x, e.motion.z, e.motion.y}; -// short r[3] = {-e.motion.rx, -e.motion.rz, -e.motion.ry}; - -// blender view coords + // convert to blender view coords short t[3] = {e.motion.x, e.motion.y, -e.motion.z}; short r[3] = {-e.motion.rx, -e.motion.ry, e.motion.rz}; diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.h b/intern/ghost/intern/GHOST_NDOFManagerX11.h index def311d51e2..5e1c9d91074 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.h +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.h @@ -38,6 +38,8 @@ public: bool processEvents(); private: +// bool identifyDevice(); + bool m_available; }; -- cgit v1.2.3 From ff5a49b8161734424b3d8c83c67a5e26b9b16a1e Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 23 Jul 2011 21:33:04 +0000 Subject: another CMake build fix (contributed by Kevin Cozens) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 19d9ea942a3..764e9f93414 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -456,7 +456,7 @@ if(UNIX AND NOT APPLE) if(CMAKE_SYSTEM_NAME MATCHES "Linux") set(NDOF /usr) set(NDOF_INC ${NDOF}/include) - set(NDOF_LIB spnav) + set(NDOF_LIBRARY spnav) set(NDOF_LIBPATH ${NDOF}/lib) endif() endif() -- cgit v1.2.3 From b9f3ff5435d78b4538b417849edf60238fa54e34 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 23 Jul 2011 21:55:52 +0000 Subject: removed ancient ndof global, removed my own attempt at a C popup menu (the Python one works) --- source/blender/blenkernel/BKE_global.h | 5 -- source/blender/windowmanager/intern/wm_init_exit.c | 2 - source/blender/windowmanager/intern/wm_operators.c | 98 +--------------------- 3 files changed, 3 insertions(+), 102 deletions(-) diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index d21b0428d76..17876c6ec9d 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -92,9 +92,6 @@ typedef struct Global { /* save the allowed windowstate of blender when using -W or -w */ int windowstate; - - /* ndof device found ? */ - int ndofdevice; } Global; /* **************** GLOBAL ********************* */ @@ -174,5 +171,3 @@ extern Global G; #endif #endif - - diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index ed28696ef69..7dd865984b3 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -182,8 +182,6 @@ void WM_init(bContext *C, int argc, const char **argv) ED_preview_init_dbase(); - G.ndofdevice = -1; /* XXX bad initializer, needs set otherwise buttons show! */ - WM_read_history(); /* allow a path of "", this is what happens when making a new file */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 32d2adffb01..44e42966c77 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1411,113 +1411,22 @@ static void WM_OT_search_menu(wmOperatorType *ot) ot->poll= wm_search_menu_poll; } -// BEGIN ndof menu -- experimental! - -#if 0 -static uiBlock* wm_block_ndof_menu_1st(bContext* C, ARegion* ar, void* UNUSED(arg_op)) -{ - uiBlock* block; - uiBut* but; - - block = uiBeginBlock(C, ar, "ndof_popup_menu", UI_EMBOSS); - uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT); -// uiBlockSetDirection(block, UI_DOWN); -// uiBlockBeginAlign(block); - - // uiItemBooleanO(block->curlayout, "enable pan/zoom", ICON_NDOF_TRANS, "toggle_ndof_pan_zoom_enabled", "ndof_pan_zoom_enabled", 1); - // uiBlock is used as an opaque type in this file, so can't use members... - - int foo = 333; - uiDefButI(block, TOG, 0, "foo", 10, 10, 9*UI_UNIT_X, UI_UNIT_Y, &foo, 0.f, 1.f, 0.1f, 0.9f, "15%"); - // uiDefBut(block, TOG, 0, "enable pan/zoom", 0, 0, 10, 10, NULL, 0.f, 1.f, 0.f, 1.f, "don't talk to strangers"); - -// uiBlockEndAlign(block); -// uiBoundsBlock(block, 6); - uiEndBlock(C, block); - - return block; -} - -static int wm_ndof_menu_poll(bContext *C) -{ - if(CTX_wm_window(C)==NULL) - return 0; - - // if menu is already pulled up, another button press should dismiss it - // not sure if that behavior should go here or elsewhere... - - puts("ndof: menu poll"); - return 1; -} - -static int wm_ndof_menu_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) -{ - puts("ndof: menu exec"); - return OPERATOR_FINISHED; -} -#endif - static int wm_ndof_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { uiPupMenuInvoke(C,"VIEW3D_MT_ndof_settings"); + return OPERATOR_FINISHED; // <-- correct? return OPERATOR_CANCELLED; // <-- correct? - -/* -// uiPupMenuNotice(C, "Hello!"); // <-- this works -// uiPupBlock(C, wm_block_ndof_menu, op); // <-- no luck! -// ui_popup_menu_create(C, NULL, NULL, NULL, NULL, "Hello!"); // <-- this works - - uiPopupMenu* pup = uiPupMenuBegin(C,"3D mouse settings",ICON_NDOF_TURN); - uiLayout* layout = uiPupMenuLayout(pup); - - uiItemS(layout); // separator - uiItemFloatO(layout, "sensitivity", 0, 0, "ndof_sensitivity", 1.f); - // do I have to look specifically in "UserPreferences" for ndof_sensitivity property? - - // trial & error -- ok, mostly error -// uiItemBooleanO(layout, "enable pan/zoom", ICON_NDOF_TRANS, "ndof_toggle_pan_zoom_enabled", "ndof_pan_zoom_enabled", 1); -// uiItemBooleanO(layout, "enable rotation", ICON_NDOF_TURN, "ndof_toggle_rotation_enabled", "ndof_rotation_enabled", 1); -// uiItemV(layout,"sensitivity",ICON_NDOF_TRANS, 1); - - printf("ndof: menu invoked in "); - - switch (CTX_wm_area(C)->spacetype) // diff spaces can have diff 3d mouse options - { - case SPACE_VIEW3D: - puts("3D area"); - uiItemS(layout); - uiItemL(layout, "3D navigation mode", 0); - uiItemBooleanO(layout, "helicopter", ICON_NDOF_FLY, 0, "ndof_fly_helicopter", 1); - uiItemBooleanO(layout, "lock horizon", ICON_NDOF_DOM, 0, "ndof_lock_horizon", 1); - break; - case SPACE_IMAGE: - puts("image area"); - break; - default: - puts("some iNDOFferent area"); - } - - //uiBlock* block = uiLayoutGetBlock(layout); - //int foo = 1; - //uiDefButI(block, TOG, 0, "foo", 10, 10, 9*UI_UNIT_X, UI_UNIT_Y, &foo, 0.f, 1.f, 0.1f, 0.9f, "15%"); - - uiPupMenuEnd(C,pup); -*/ } static void WM_OT_ndof_menu(wmOperatorType *ot) { - puts("ndof: registering menu operator"); - ot->name = "NDOF Menu"; ot->idname = "WM_OT_ndof_menu"; ot->invoke = wm_ndof_menu_invoke; } -// END ndof menu - static int wm_call_menu_exec(bContext *C, wmOperator *op) { char idname[BKE_ST_MAXNAME]; @@ -3782,13 +3691,12 @@ void wm_window_keymap(wmKeyConfig *keyconf) /* debug/testing */ WM_keymap_verify_item(keymap, "WM_OT_redraw_timer", TKEY, KM_PRESS, KM_ALT|KM_CTRL, 0); WM_keymap_verify_item(keymap, "WM_OT_debug_menu", DKEY, KM_PRESS, KM_ALT|KM_CTRL, 0); - WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_PRESS, 0, 0); + /* menus that can be accessed anywhere in blender */ + WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "WM_OT_ndof_menu", NDOF_BUTTON_MENU, KM_PRESS, 0, 0); /* Space switching */ - - kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F2KEY, KM_PRESS, KM_SHIFT, 0); /* new in 2.5x, was DXF export */ RNA_string_set(kmi->ptr, "data_path", "area.type"); RNA_string_set(kmi->ptr, "value", "LOGIC_EDITOR"); -- cgit v1.2.3 From ed232c756d25f5fe16370c7eba332f2d78cd128e Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 24 Jul 2011 00:40:39 +0000 Subject: ndof overall sensitivity is now live --- source/blender/windowmanager/intern/wm_event_system.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 26d72906ece..ad8df1ef0bb 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2314,13 +2314,15 @@ static void attach_ndof_data(wmEvent* event, const GHOST_TEventNDOFMotionData* g { wmNDOFMotionData* data = MEM_mallocN(sizeof(wmNDOFMotionData), "customdata NDOF"); - data->tx = ghost->tx; - data->ty = ghost->ty; - data->tz = ghost->tz; + const float s = U.ndof_sensitivity; - data->rx = ghost->rx; - data->ry = ghost->ry; - data->rz = ghost->rz; + data->tx = s * ghost->tx; + data->ty = s * ghost->ty; + data->tz = s * ghost->tz; + + data->rx = s * ghost->rx; + data->ry = s * ghost->ry; + data->rz = s * ghost->rz; data->dt = ghost->dt; -- cgit v1.2.3 From c2c62134ccd97eef06822f4c414585bf5d455e16 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 24 Jul 2011 00:52:18 +0000 Subject: minor cleanup of Mac ndof manager --- intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index 1c8730a2804..995f73955f2 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -41,7 +41,7 @@ static void NDOF_DeviceAdded(io_connect_t connection) { printf("ndof: device added\n"); // change these: printf --> informational reports -#if 0 // device preferences will be useful soon +#if 0 // device preferences will be useful some day ConnexionDevicePrefs p; ConnexionGetCurrentDevicePrefs(kDevID_AnyDevice, &p); #endif @@ -74,10 +74,13 @@ static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, voi { case kConnexionCmdHandleAxis: { + // convert to blender view coordinates short t[3] = {s->axis[0], -(s->axis[2]), s->axis[1]}; short r[3] = {-(s->axis[3]), s->axis[5], -(s->axis[4])}; + ndof_manager->updateTranslation(t, now); ndof_manager->updateRotation(r, now); + ghost_system->notifyExternalEventProcessed(); break; } @@ -98,7 +101,8 @@ static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, voi break; } case kConnexionMsgPrefsChanged: - printf("ndof: prefs changed\n"); // this includes app switches + // printf("ndof: prefs changed\n"); // this includes app switches + // TODO: look through updated prefs for things blender cares about break; case kConnexionMsgCalibrateDevice: printf("ndof: calibrate\n"); // but what should blender do? @@ -134,7 +138,7 @@ GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\007blender", kConnexionClientModeTakeOver, kConnexionMaskAll); - printf("ndof: client id = %d\n", m_clientID); + // printf("ndof: client id = %d\n", m_clientID); if (SetConnexionClientButtonMask != NULL) { @@ -161,7 +165,8 @@ GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() bool GHOST_NDOFManagerCocoa::available() { -// extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); -// ^-- not needed since the entire framework is weak-linked + // extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); + // ^^ not needed since the entire framework is weak-linked return InstallConnexionHandlers != NULL; + // this means that the driver is installed and dynamically linked to blender } -- cgit v1.2.3 From 1ca4f1ba1c48b9afa46c85ce9010829a26194632 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 24 Jul 2011 08:02:42 +0000 Subject: sculpt/paint while using 3D mouse --- source/blender/editors/gpencil/gpencil_paint.c | 12 ++++++++++++ source/blender/editors/sculpt_paint/paint_stroke.c | 3 +++ 2 files changed, 15 insertions(+) diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index f4da734473d..28a54b20277 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1617,6 +1617,18 @@ static int gpencil_draw_modal (bContext *C, wmOperator *op, wmEvent *event) tGPsdata *p= op->customdata; int estate = OPERATOR_PASS_THROUGH; /* default exit state - not handled, so let others have a share of the pie */ + // if (event->type == NDOF_MOTION) + // return OPERATOR_PASS_THROUGH; + // ------------------------------- + // [mce] Not quite what I was looking + // for, but a good start! GP continues to + // draw on the screen while the 3D mouse + // moves the viewpoint. Problem is that + // the stroke is converted to 3D only after + // it is finished. This approach should work + // better in tools that immediately apply + // in 3D space. + //printf("\tGP - handle modal event...\n"); /* exit painting mode (and/or end current stroke) */ diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 7ddf5dff000..bddb30a4262 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -832,6 +832,9 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) float mouse[2]; int first= 0; + if (event->type == NDOF_MOTION) + return OPERATOR_PASS_THROUGH; + if(!stroke->stroke_started) { stroke->last_mouse_position[0] = event->x; stroke->last_mouse_position[1] = event->y; -- cgit v1.2.3 From c4bda1370c9528e2035c1d91df126dd4ea789d69 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Sun, 24 Jul 2011 08:37:43 +0000 Subject: Add mapping for front/right/top aligned to selected object. --- source/blender/editors/space_view3d/view3d_ops.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 2dd560a6408..963e7aeeb95 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -221,6 +221,17 @@ void view3d_keymap(wmKeyConfig *keyconf) RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_BOTTOM); RNA_boolean_set(kmi->ptr, "align_active", TRUE); + /* 3D mouse align */ + kmi= WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, KM_SHIFT, 0); + RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_FRONT); + RNA_boolean_set(kmi->ptr, "align_active", TRUE); + kmi= WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, KM_SHIFT, 0); + RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_RIGHT); + RNA_boolean_set(kmi->ptr, "align_active", TRUE); + kmi= WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, KM_SHIFT, 0); + RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_TOP); + RNA_boolean_set(kmi->ptr, "align_active", TRUE); + WM_keymap_add_item(keymap, "VIEW3D_OT_localview", PADSLASHKEY, KM_PRESS, 0, 0); /* layers, shift + alt are properties set in invoke() */ -- cgit v1.2.3 From 6149526aac7a10034ce369147c8c7962f8ed4e35 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Sun, 24 Jul 2011 08:50:09 +0000 Subject: Default for ndof_sensitivity to 1.0 in case 0.0 is found on start. --- source/blender/editors/interface/resources.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 3f825762d74..276e1b3dc61 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1583,6 +1583,9 @@ void init_userdef_do_versions(void) if (U.anisotropic_filter <= 0) U.anisotropic_filter = 1; + if (U.ndof_sensitivity == 0.0) + U.ndof_sensitivity = 1.0f; + /* funny name, but it is GE stuff, moves userdef stuff to engine */ // XXX space_set_commmandline_options(); /* this timer uses U */ -- cgit v1.2.3 From abf658d36785e3fb0fe458ba7ee9b22987a9c036 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 25 Jul 2011 00:00:53 +0000 Subject: removed old ndof transform stuff, added experimental ndof nav during transform (might disable for release) --- source/blender/editors/transform/transform.c | 127 +---------------------- source/blender/editors/transform/transform_ops.c | 6 ++ 2 files changed, 11 insertions(+), 122 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index d3a30991aa6..81aade5ca64 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1006,9 +1006,11 @@ int transformEvent(TransInfo *t, wmEvent *event) else view_editmove(event->type); t->redraw= 1; break; -// case NDOFMOTION: -// viewmoveNDOF(1); - // break; +#if 0 + case NDOF_MOTION: + // should have been caught by tranform_modal + return OPERATOR_PASS_THROUGH; +#endif default: handled = 0; break; @@ -1017,43 +1019,6 @@ int transformEvent(TransInfo *t, wmEvent *event) // Numerical input events t->redraw |= handleNumInput(&(t->num), event); - // NDof input events - switch(handleNDofInput(&(t->ndof), event)) - { - case NDOF_CONFIRM: - if ((t->options & CTX_NDOF) == 0) - { - /* Confirm on normal transform only */ - t->state = TRANS_CONFIRM; - } - break; - case NDOF_CANCEL: - if (t->options & CTX_NDOF) - { - /* Cancel on pure NDOF transform */ - t->state = TRANS_CANCEL; - } - else - { - /* Otherwise, just redraw, NDof input was cancelled */ - t->redraw |= TREDRAW_HARD; - } - break; - case NDOF_NOMOVE: - if (t->options & CTX_NDOF) - { - /* Confirm on pure NDOF transform */ - t->state = TRANS_CONFIRM; - } - break; - case NDOF_REFRESH: - t->redraw |= TREDRAW_HARD; - break; - default: - handled = 0; - break; - } - // Snapping events t->redraw |= handleSnapping(t, event); @@ -2886,10 +2851,6 @@ void initRotation(TransInfo *t) setInputPostFct(&t->mouse, postInputRotation); initMouseInputMode(t, &t->mouse, INPUT_ANGLE); - t->ndof.axis = 16; - /* Scale down and flip input for rotation */ - t->ndof.factor[0] = -0.2f; - t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; @@ -3161,8 +3122,6 @@ int Rotation(TransInfo *t, const int UNUSED(mval[2])) final = t->values[0]; - applyNDofInput(&t->ndof, &final); - snapGrid(t, &final); if ((t->con.mode & CON_APPLY) && t->con.applyRot) { @@ -3216,11 +3175,6 @@ void initTrackball(TransInfo *t) initMouseInputMode(t, &t->mouse, INPUT_TRACKBALL); - t->ndof.axis = 40; - /* Scale down input for rotation */ - t->ndof.factor[0] = 0.2f; - t->ndof.factor[1] = 0.2f; - t->idx_max = 1; t->num.idx_max = 1; t->snap[0] = 0.0f; @@ -3276,8 +3230,6 @@ int Trackball(TransInfo *t, const int UNUSED(mval[2])) phi[0] = t->values[0]; phi[1] = t->values[1]; - applyNDofInput(&t->ndof, phi); - snapGrid(t, phi); if (hasNumInput(&t->num)) { @@ -3331,8 +3283,6 @@ void initTranslation(TransInfo *t) t->num.flag = 0; t->num.idx_max = t->idx_max; - t->ndof.axis = (t->flag & T_2D_EDIT)? 1|2: 1|2|4; - if(t->spacetype == SPACE_VIEW3D) { RegionView3D *rv3d = t->ar->regiondata; @@ -3507,7 +3457,6 @@ int Translation(TransInfo *t, const int UNUSED(mval[2])) headerTranslation(t, pvec, str); } else { - applyNDofInput(&t->ndof, t->values); snapGrid(t, t->values); applyNumInput(&t->num, t->values); if (hasNumInput(&t->num)) { @@ -3616,10 +3565,6 @@ void initTilt(TransInfo *t) initMouseInputMode(t, &t->mouse, INPUT_ANGLE); - t->ndof.axis = 16; - /* Scale down and flip input for rotation */ - t->ndof.factor[0] = -0.2f; - t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; @@ -3643,8 +3588,6 @@ int Tilt(TransInfo *t, const int UNUSED(mval[2])) final = t->values[0]; - applyNDofInput(&t->ndof, &final); - snapGrid(t, &final); if (hasNumInput(&t->num)) { @@ -3759,10 +3702,6 @@ void initPushPull(TransInfo *t) initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE); - t->ndof.axis = 4; - /* Flip direction */ - t->ndof.factor[0] = -1.0f; - t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; @@ -3783,8 +3722,6 @@ int PushPull(TransInfo *t, const int UNUSED(mval[2])) distance = t->values[0]; - applyNDofInput(&t->ndof, &distance); - snapGrid(t, &distance); applyNumInput(&t->num, &distance); @@ -5309,8 +5246,6 @@ void initSeqSlide(TransInfo *t) t->num.flag = 0; t->num.idx_max = t->idx_max; - t->ndof.axis = 1|2; - t->snap[0] = 0.0f; t->snap[1] = floor(t->scene->r.frs_sec / t->scene->r.frs_sec_base); t->snap[2] = 10.0f; @@ -5365,7 +5300,6 @@ int SeqSlide(TransInfo *t, const int UNUSED(mval[2])) VECCOPY(t->values, tvec); } else { - applyNDofInput(&t->ndof, t->values); snapGrid(t, t->values); applyNumInput(&t->num, t->values); } @@ -5925,54 +5859,3 @@ void BIF_TransformSetUndo(char *UNUSED(str)) // TRANSFORM_FIX_ME //Trans.undostr= str; } - - -#if 0 // TRANSFORM_FIX_ME -static void NDofTransform(void) -{ - float fval[7]; - float maxval = 50.0f; // also serves as threshold - int axis = -1; - int mode = 0; - int i; - - getndof(fval); - - for(i = 0; i < 6; i++) - { - float val = fabs(fval[i]); - if (val > maxval) - { - axis = i; - maxval = val; - } - } - - switch(axis) - { - case -1: - /* No proper axis found */ - break; - case 0: - case 1: - case 2: - mode = TFM_TRANSLATION; - break; - case 4: - mode = TFM_ROTATION; - break; - case 3: - case 5: - mode = TFM_TRACKBALL; - break; - default: - printf("ndof: what we are doing here ?"); - } - - if (mode != 0) - { - initTransform(mode, CTX_NDOF); - Transform(); - } -} -#endif diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 7bdf6c909d9..0b0b22fb689 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -360,6 +360,12 @@ static int transform_modal(bContext *C, wmOperator *op, wmEvent *event) TransInfo *t = op->customdata; + if (event->type == NDOF_MOTION) + { + // puts("transform_modal: passing through NDOF_MOTION"); + return OPERATOR_PASS_THROUGH; + } + /* XXX insert keys are called here, and require context */ t->context= C; exit_code = transformEvent(t, event); -- cgit v1.2.3 From 73417bfbb564a2e5b1b203e436994ea8b7f3c535 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 25 Jul 2011 00:03:07 +0000 Subject: spoof MOUSEMOVE after NDOF_MOTION event, added comments --- source/blender/editors/sculpt_paint/paint_stroke.c | 4 ++++ source/blender/windowmanager/intern/wm_event_system.c | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index bddb30a4262..09873566d4a 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -832,6 +832,10 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) float mouse[2]; int first= 0; + // let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously! + // this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it + // since the 2D deltas are zero -- code in this file needs to be updated to use the + // post-NDOF_MOTION MOUSEMOVE if (event->type == NDOF_MOTION) return OPERATOR_PASS_THROUGH; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index ad8df1ef0bb..322cd3b5642 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1815,7 +1815,10 @@ void wm_event_do_handlers(bContext *C) /* for regions having custom cursors */ wm_paintcursor_test(C, event); } - + else if (event->type==NDOF_MOTION) { + win->addmousemove = TRUE; + } + for(sa= win->screen->areabase.first; sa; sa= sa->next) { if(wm_event_inside_i(event, &sa->totrct)) { CTX_wm_area_set(C, sa); @@ -1879,7 +1882,10 @@ void wm_event_do_handlers(bContext *C) if(doit && win->screen && win->screen->subwinactive != win->screen->mainwin) { win->eventstate->prevx= event->x; win->eventstate->prevy= event->y; + //printf("win->eventstate->prev = %d %d\n", event->x, event->y); } + else + ;//printf("not setting prev to %d %d\n", event->x, event->y); } /* store last event for this window */ @@ -1922,6 +1928,7 @@ void wm_event_do_handlers(bContext *C) /* only add mousemove when queue was read entirely */ if(win->addmousemove && win->eventstate) { wmEvent tevent= *(win->eventstate); + //printf("adding MOUSEMOVE %d %d\n", tevent.x, tevent.y); tevent.type= MOUSEMOVE; tevent.prevx= tevent.x; tevent.prevy= tevent.y; @@ -2408,6 +2415,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U update_tablet_data(win, &event); wm_event_add(win, &event); + + //printf("sending MOUSEMOVE %d %d\n", event.x, event.y); /* also add to other window if event is there, this makes overdraws disappear nicely */ /* it remaps mousecoord to other window in event */ @@ -2586,6 +2595,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U attach_ndof_data(&event, customdata); wm_event_add(win, &event); + //printf("sending NDOF_MOTION, prev = %d %d\n", event.x, event.y); + break; } -- cgit v1.2.3 From e31fef1d94c38f4701f12d7f264fe145446f08b6 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 25 Jul 2011 00:10:42 +0000 Subject: set default values for all other ndof flags --- source/blender/editors/interface/resources.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 276e1b3dc61..5f405a5f51e 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1583,8 +1583,11 @@ void init_userdef_do_versions(void) if (U.anisotropic_filter <= 0) U.anisotropic_filter = 1; - if (U.ndof_sensitivity == 0.0) + if (U.ndof_sensitivity == 0.0f) { U.ndof_sensitivity = 1.0f; + U.ndof_flag = NDOF_SHOW_GUIDE | NDOF_LOCK_HORIZON | + NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM | NDOF_SHOULD_ROTATE; + } /* funny name, but it is GE stuff, moves userdef stuff to engine */ // XXX space_set_commmandline_options(); -- cgit v1.2.3 From c692351fdfe96ec396af9f9c1dfc92ae4e8ee5c6 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 25 Jul 2011 00:20:45 +0000 Subject: added option to invert axes for orbiting (part 1 of 2) --- source/blender/editors/space_view3d/view3d_edit.c | 14 ++++++++++++-- source/blender/makesdna/DNA_userdef_types.h | 11 +++++++++++ source/blender/makesrna/intern/rna_userdef.c | 6 +++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 0c07df9fd01..aabacadf3db 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1019,6 +1019,8 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) if (has_rotation) { + const int invert = U.ndof_flag & NDOF_ORBIT_INVERT_AXES; + rv3d->view = RV3D_VIEW_USER; if (U.flag & USER_TRACKBALL) { @@ -1027,8 +1029,8 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) float view_inv[4], view_inv_conj[4]; ndof_to_quat(ndof, rot); - // scale by rot_sensitivity? - // mul_qt_fl(rot, rot_sensitivity); + // mul_qt_fl(rot, rot_sensitivity * (invert ? -1.f : 1.f)); + // ^^ no apparent effect invert_qt_qt(view_inv, rv3d->viewquat); copy_qt_qt(view_inv_conj, view_inv); @@ -1038,6 +1040,10 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) mul_qt_qtqt(rot, view_inv, rot); mul_qt_qtqt(rot, rot, view_inv_conj); + // if (invert) + // invert_qt(rot); + // ^^ argh!! this does something crazy + // apply rotation mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); @@ -1053,12 +1059,16 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) /* Perform the up/down rotation */ angle = rot_sensitivity * dt * ndof->rx; + if (invert) + angle = -angle; rot[0] = cos(angle); mul_v3_v3fl(rot+1, xvec, sin(angle)); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); /* Perform the orbital rotation */ angle = rot_sensitivity * dt * ndof->ry; + if (invert) + angle = -angle; rot[0] = cos(angle); rot[1] = rot[2] = 0.0; rot[3] = sin(angle); diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 6fbdb9842d6..12f8cd656a0 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -589,6 +589,17 @@ extern UserDef U; /* from blenkernel blender.c */ #define NDOF_SHOULD_PAN (1 << 3) #define NDOF_SHOULD_ZOOM (1 << 4) #define NDOF_SHOULD_ROTATE (1 << 5) +/* orbit navigation modes + only two options, so it's sort of a hyrbrid bool/enum + if ((U.ndof_flag & NDOF_ORBIT_MODE) == NDOF_OM_OBJECT)... */ +/* +#define NDOF_ORBIT_MODE (1 << 6) +#define NDOF_OM_TARGETCAMERA 0 +#define NDOF_OM_OBJECT NDOF_ORBIT_MODE +*/ +/* actually... users probably don't care about what the mode + is called, just that it feels right */ +#define NDOF_ORBIT_INVERT_AXES (1 << 6) #ifdef __cplusplus diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 50b5e99804c..7a9193571fd 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2748,13 +2748,17 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Navigation Guide", "Display the center and axis during rotation"); /* TODO: update description when fly-mode visuals are in place ("projected position in fly mode")*/ + prop= RNA_def_property(srna, "ndof_orbit_invert_axes", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_ORBIT_INVERT_AXES); + RNA_def_property_ui_text(prop, "Invert Axes", "Toggle between moving the viewpoint or moving the scene being viewed"); + prop= RNA_def_property(srna, "ndof_lock_horizon", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_LOCK_HORIZON); RNA_def_property_ui_text(prop, "Lock Horizon", "Keep horizon level while flying with 3D Mouse"); prop= RNA_def_property(srna, "ndof_fly_helicopter", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_FLY_HELICOPTER); - RNA_def_property_ui_text(prop, "Helicopter Fly Mode", ""); + RNA_def_property_ui_text(prop, "Helicopter Mode", "Device up/down directly controls your Z position"); prop= RNA_def_property(srna, "mouse_double_click_time", PROP_INT, PROP_NONE); -- cgit v1.2.3 From 876e0c2a8beb8111bb5c4c3d135fa44134c37d7d Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 25 Jul 2011 00:21:35 +0000 Subject: updated ndof popup menu (part 2 of 2) --- release/scripts/startup/bl_ui/space_view3d.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index e1d31b53359..b31618cfad0 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -369,6 +369,11 @@ class VIEW3D_MT_ndof_settings(bpy.types.Menu): layout.prop(input_prefs, "ndof_show_guide") layout.separator() + layout.label(text="orbit options") + layout.prop(input_prefs, "ndof_orbit_invert_axes") + + layout.separator() + layout.label(text="fly options") layout.prop(input_prefs, "ndof_fly_helicopter", icon='NDOF_FLY') layout.prop(input_prefs, "ndof_lock_horizon", icon='NDOF_DOM') -- cgit v1.2.3 From 4b8233423bea092d5af4affe14290095dbd701ef Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Mon, 25 Jul 2011 03:13:15 +0000 Subject: invert axes option affects trackball navigation --- source/blender/editors/space_view3d/view3d_edit.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index aabacadf3db..0aceb3bc1ca 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1029,9 +1029,12 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) float view_inv[4], view_inv_conj[4]; ndof_to_quat(ndof, rot); - // mul_qt_fl(rot, rot_sensitivity * (invert ? -1.f : 1.f)); + // mul_qt_fl(rot, rot_sensitivity); // ^^ no apparent effect + if (invert) + invert_qt(rot); + invert_qt_qt(view_inv, rv3d->viewquat); copy_qt_qt(view_inv_conj, view_inv); conjugate_qt(view_inv_conj); @@ -1040,10 +1043,6 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) mul_qt_qtqt(rot, view_inv, rot); mul_qt_qtqt(rot, rot, view_inv_conj); - // if (invert) - // invert_qt(rot); - // ^^ argh!! this does something crazy - // apply rotation mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); -- cgit v1.2.3 From 72f70874bb3477a0861735d612e0c15c931ff7e5 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 26 Jul 2011 02:35:46 +0000 Subject: experimental onscreen rotation guide --- source/blender/editors/space_view3d/view3d_draw.c | 59 +++++++ source/blender/editors/space_view3d/view3d_edit.c | 206 ++++++++++++---------- source/blender/editors/space_view3d/view3d_fly.c | 2 + source/blender/makesdna/DNA_view3d_types.h | 6 +- 4 files changed, 181 insertions(+), 92 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index d2ff6eef097..f1909bb4049 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -675,6 +675,60 @@ static void draw_view_axis(RegionView3D *rv3d) glDisable(GL_BLEND); } +/* draw center and axis of rotation for ongoing 3D mouse navigation */ +static void draw_rotation_guide(RegionView3D *rv3d) +{ + float o[3]; // center of rotation + float end[3]; // endpoints for drawing + + float color[4] = {1,1,0,1}; // bright yellow so it stands out during development + + negate_v3_v3(o, rv3d->ofs); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glShadeModel(GL_SMOOTH); + glPointSize(5); + glEnable(GL_POINT_SMOOTH); + + if (rv3d->rot_angle != 0.f) { + float scaled_axis[3]; + mul_v3_v3fl(scaled_axis, rv3d->rot_axis, 3.f); + + glBegin(GL_LINE_STRIP); + color[3] = 0; // more transparent toward the ends + glColor4fv(color); + add_v3_v3v3(end, o, scaled_axis); + glVertex3fv(end); + + color[3] = 0.2f + rv3d->rot_angle; // more opaque toward the center + glColor4fv(color); + glVertex3fv(o); + + color[3] = 0; + glColor4fv(color); + sub_v3_v3v3(end, o, scaled_axis); + glVertex3fv(end); + glEnd(); + + color[3] = 1; // solid dot + } + else + color[3] = 0.5; // see-through dot + + glColor4fv(color); + glBegin(GL_POINTS); + glVertex3fv(o); + glEnd(); + + // find screen coordinates for rotation center, then draw pretty icon + // mul_m4_v3(rv3d->persinv, rot_center); + // UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN); + // ^^ just playing around, does not work + + glDisable(GL_BLEND); + glDisable(GL_POINT_SMOOTH); +} static void draw_view_icon(RegionView3D *rv3d) { @@ -2618,6 +2672,11 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) BDR_drawSketch(C); } +#if 0 // not yet... + if (U.ndof_flag & NDOF_SHOW_GUIDE) + draw_rotation_guide(rv3d); +#endif + ED_region_pixelspace(ar); // retopo_paint_view_update(v3d); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 0aceb3bc1ca..75e20ad565e 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -977,101 +977,125 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) RegionView3D* rv3d = CTX_wm_region_view3d(C); wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; - const float dt = ndof->dt; + rv3d->rot_angle = 0.f; // off by default, until changed later this function - // tune these until everything feels right - const float rot_sensitivity = 1.f; - const float zoom_sensitivity = 1.f; - const float pan_sensitivity = 1.f; - - // rather have bool, but... - int has_rotation = rv3d->viewlock != RV3D_LOCKED && (ndof->rx || ndof->ry || ndof->rz); - - //#define DEBUG_NDOF_MOTION - #ifdef DEBUG_NDOF_MOTION - printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n", - ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt); - #endif - - if (ndof->tz) { - // Zoom! - // velocity should be proportional to the linear velocity attained by rotational motion of same strength - // [got that?] - // proportional to arclength = radius * angle - - float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz; - rv3d->dist += zoom_distance; - } - - if (rv3d->viewlock == RV3D_LOCKED) { - /* rotation not allowed -- explore panning options instead */ + if (ndof->progress != P_FINISHING) { + const float dt = ndof->dt; + + // tune these until everything feels right + const float rot_sensitivity = 1.f; + const float zoom_sensitivity = 1.f; + const float pan_sensitivity = 1.f; + + // rather have bool, but... + int has_rotation = rv3d->viewlock != RV3D_LOCKED && (ndof->rx || ndof->ry || ndof->rz); + float view_inv[4]; - float pan_vec[3] = {ndof->tx, ndof->ty, 0}; - mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt); - - /* transform motion from view to world coordinates */ invert_qt_qt(view_inv, rv3d->viewquat); - mul_qt_v3(view_inv, pan_vec); - - /* move center of view opposite of hand motion (this is camera mode, not object mode) */ - sub_v3_v3(rv3d->ofs, pan_vec); - } - - if (has_rotation) { - - const int invert = U.ndof_flag & NDOF_ORBIT_INVERT_AXES; - - rv3d->view = RV3D_VIEW_USER; - - if (U.flag & USER_TRACKBALL) { - - float rot[4]; - float view_inv[4], view_inv_conj[4]; - - ndof_to_quat(ndof, rot); - // mul_qt_fl(rot, rot_sensitivity); - // ^^ no apparent effect - - if (invert) - invert_qt(rot); - - invert_qt_qt(view_inv, rv3d->viewquat); - copy_qt_qt(view_inv_conj, view_inv); - conjugate_qt(view_inv_conj); - - // transform rotation from view to world coordinates - mul_qt_qtqt(rot, view_inv, rot); - mul_qt_qtqt(rot, rot, view_inv_conj); - - // apply rotation - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); - - } else { - /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */ - float angle, rot[4]; - float xvec[3] = {1,0,0}; - - /* Determine the direction of the x vector (for rotating up and down) */ - float view_inv[4]; + + //#define DEBUG_NDOF_MOTION + #ifdef DEBUG_NDOF_MOTION + printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n", + ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt); + #endif + + if (ndof->tz) { + // Zoom! + // velocity should be proportional to the linear velocity attained by rotational motion of same strength + // [got that?] + // proportional to arclength = radius * angle + + float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz; + rv3d->dist += zoom_distance; + } + + if (rv3d->viewlock == RV3D_LOCKED) { + /* rotation not allowed -- explore panning options instead */ + float pan_vec[3] = {ndof->tx, ndof->ty, 0}; + mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt); + + /* transform motion from view to world coordinates */ invert_qt_qt(view_inv, rv3d->viewquat); - mul_qt_v3(view_inv, xvec); - - /* Perform the up/down rotation */ - angle = rot_sensitivity * dt * ndof->rx; - if (invert) - angle = -angle; - rot[0] = cos(angle); - mul_v3_v3fl(rot+1, xvec, sin(angle)); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); - - /* Perform the orbital rotation */ - angle = rot_sensitivity * dt * ndof->ry; - if (invert) - angle = -angle; - rot[0] = cos(angle); - rot[1] = rot[2] = 0.0; - rot[3] = sin(angle); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); + mul_qt_v3(view_inv, pan_vec); + + /* move center of view opposite of hand motion (this is camera mode, not object mode) */ + sub_v3_v3(rv3d->ofs, pan_vec); + } + + if (has_rotation) { + + const int invert = U.ndof_flag & NDOF_ORBIT_INVERT_AXES; + + rv3d->view = RV3D_VIEW_USER; + + if (U.flag & USER_TRACKBALL) { + float rot[4]; + #if 0 // -------------------------- Mike's nifty original version + float view_inv_conj[4]; + + ndof_to_quat(ndof, rot); + // mul_qt_fl(rot, rot_sensitivity); + // ^^ no apparent effect + + if (invert) + invert_qt(rot); + + copy_qt_qt(view_inv_conj, view_inv); + conjugate_qt(view_inv_conj); + + // transform rotation from view to world coordinates + mul_qt_qtqt(rot, view_inv, rot); + mul_qt_qtqt(rot, rot, view_inv_conj); + #else // ---------------------------------------- Mike's revised version + float axis[3]; + float angle = rot_sensitivity * ndof_to_angle_axis(ndof, axis); + + if (invert) + angle = -angle; + + // update the onscreen doo-dad + rv3d->rot_angle = angle; + copy_v3_v3(rv3d->rot_axis, axis); + + // transform rotation axis from view to world coordinates + mul_qt_v3(view_inv, axis); + + axis_angle_to_quat(rot, axis, angle); + #endif // -------------------------------------------- + // apply rotation + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); + } else { + /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */ + float angle, rot[4]; + float xvec[3] = {1,0,0}; + + /* Determine the direction of the x vector (for rotating up and down) */ + mul_qt_v3(view_inv, xvec); + + /* Perform the up/down rotation */ + angle = rot_sensitivity * dt * ndof->rx; + if (invert) + angle = -angle; + rot[0] = cos(angle); + mul_v3_v3fl(rot+1, xvec, sin(angle)); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); + + /* Perform the orbital rotation */ + angle = rot_sensitivity * dt * ndof->ry; + if (invert) + angle = -angle; + + // update the onscreen doo-dad + rv3d->rot_angle = angle; + rv3d->rot_axis[0] = 0; + rv3d->rot_axis[1] = 0; + rv3d->rot_axis[2] = 1; + + rot[0] = cos(angle); + rot[1] = rot[2] = 0.0; + rot[3] = sin(angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); + } } } diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 1122438da96..c7ebc296896 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -942,6 +942,8 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) float view_inv[4]; invert_qt_qt(view_inv, rv3d->viewquat); + rv3d->rot_angle = 0; // disable onscreen rotation doo-dad + if (shouldTranslate) { const float forward_sensitivity = 1.f; diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 27ffc6d856b..89b8bad2806 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -130,7 +130,11 @@ typedef struct RegionView3D { float twangle[3]; - float padf; + /* active rotation from NDOF or elsewhere */ + float rot_angle; + float rot_axis[3]; + + char pad2[4]; } RegionView3D; -- cgit v1.2.3 From 37aa6a5e3d5d5fdd8e9ec0779cdfa831a084b01f Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 26 Jul 2011 16:17:00 +0000 Subject: onscreen ndof rotation guide (center + axis) --- source/blender/editors/space_view3d/view3d_draw.c | 16 ++++++++++++---- source/blender/editors/space_view3d/view3d_edit.c | 6 +++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index f1909bb4049..2b863bf794c 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -690,10 +690,13 @@ static void draw_rotation_guide(RegionView3D *rv3d) glShadeModel(GL_SMOOTH); glPointSize(5); glEnable(GL_POINT_SMOOTH); + glDepthMask(0); // don't overwrite zbuf if (rv3d->rot_angle != 0.f) { + // -- draw rotation axis -- float scaled_axis[3]; - mul_v3_v3fl(scaled_axis, rv3d->rot_axis, 3.f); + const float scale = rv3d->dist; + mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale); glBegin(GL_LINE_STRIP); color[3] = 0; // more transparent toward the ends @@ -701,7 +704,10 @@ static void draw_rotation_guide(RegionView3D *rv3d) add_v3_v3v3(end, o, scaled_axis); glVertex3fv(end); - color[3] = 0.2f + rv3d->rot_angle; // more opaque toward the center + // color[3] = 0.2f + fabsf(rv3d->rot_angle); // modulate opacity with angle + // ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 + + color[3] = 0.5f; // more opaque toward the center glColor4fv(color); glVertex3fv(o); @@ -716,6 +722,7 @@ static void draw_rotation_guide(RegionView3D *rv3d) else color[3] = 0.5; // see-through dot + // -- draw rotation center -- glColor4fv(color); glBegin(GL_POINTS); glVertex3fv(o); @@ -728,6 +735,7 @@ static void draw_rotation_guide(RegionView3D *rv3d) glDisable(GL_BLEND); glDisable(GL_POINT_SMOOTH); + glDepthMask(1); } static void draw_view_icon(RegionView3D *rv3d) @@ -2672,10 +2680,10 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) BDR_drawSketch(C); } -#if 0 // not yet... +//#if 0 // not yet... if (U.ndof_flag & NDOF_SHOW_GUIDE) draw_rotation_guide(rv3d); -#endif +//#endif ED_region_pixelspace(ar); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 75e20ad565e..999120a0987 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1053,13 +1053,13 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) if (invert) angle = -angle; + // transform rotation axis from view to world coordinates + mul_qt_v3(view_inv, axis); + // update the onscreen doo-dad rv3d->rot_angle = angle; copy_v3_v3(rv3d->rot_axis, axis); - // transform rotation axis from view to world coordinates - mul_qt_v3(view_inv, axis); - axis_angle_to_quat(rot, axis, angle); #endif // -------------------------------------------- // apply rotation -- cgit v1.2.3 From f54068719f8f1965ffd3584f9f8ad53b3c7f9602 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 26 Jul 2011 22:43:07 +0000 Subject: shift-motion to pan with 3D mouse --- source/blender/editors/space_view3d/view3d_edit.c | 81 ++++++++++++++++++++-- .../blender/editors/space_view3d/view3d_intern.h | 3 +- source/blender/editors/space_view3d/view3d_ops.c | 6 +- 3 files changed, 83 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 999120a0987..b343718d39b 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -1104,12 +1104,12 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } -void VIEW3D_OT_ndof(struct wmOperatorType *ot) +void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot) { /* identifiers */ - ot->name = "Navigate view"; - ot->description = "Navigate the view using a 3D mouse."; - ot->idname = "VIEW3D_OT_ndof"; + ot->name = "NDOF Orbit View"; + ot->description = "Explore every angle of an object using the 3D mouse."; + ot->idname = "VIEW3D_OT_ndof_orbit"; /* api callbacks */ ot->invoke = ndof_orbit_invoke; @@ -1119,6 +1119,79 @@ void VIEW3D_OT_ndof(struct wmOperatorType *ot) ot->flag = 0; } +static int ndof_pan_invoke(bContext *C, wmOperator *op, wmEvent *event) +// -- "pan" navigation +// -- zoom or dolly? +{ + RegionView3D* rv3d = CTX_wm_region_view3d(C); + wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + + rv3d->rot_angle = 0.f; // we're panning here! so erase any leftover rotation from other operators + + if (ndof->progress != P_FINISHING) { + const float dt = ndof->dt; + float view_inv[4]; +#if 0 // ------------------------------------------- zoom with Z + // tune these until everything feels right + const float zoom_sensitivity = 1.f; + const float pan_sensitivity = 1.f; + + float pan_vec[3] = { + ndof->tx, ndof->ty, 0 + }; + + // "zoom in" or "translate"? depends on zoom mode in user settings? + if (ndof->tz) { + float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz; + rv3d->dist += zoom_distance; + } + + mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt); +#else // ------------------------------------------------------- dolly with Z + float speed = 10.f; // blender units per second + // ^^ this is ok for default cube scene, but should scale with.. something + + // tune these until everything feels right + const float forward_sensitivity = 1.f; + const float vertical_sensitivity = 0.4f; + const float lateral_sensitivity = 0.6f; + + float pan_vec[3] = { + lateral_sensitivity * ndof->tx, + vertical_sensitivity * ndof->ty, + forward_sensitivity * ndof->tz + }; + + mul_v3_fl(pan_vec, speed * dt); +#endif + /* transform motion from view to world coordinates */ + invert_qt_qt(view_inv, rv3d->viewquat); + mul_qt_v3(view_inv, pan_vec); + + /* move center of view opposite of hand motion (this is camera mode, not object mode) */ + sub_v3_v3(rv3d->ofs, pan_vec); + } + + ED_region_tag_redraw(CTX_wm_region(C)); + + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "NDOF Pan View"; + ot->description = "Position your viewpoint with the 3D mouse."; + ot->idname = "VIEW3D_OT_ndof_pan"; + + /* api callbacks */ + ot->invoke = ndof_pan_invoke; + ot->poll = ED_operator_view3d_active; + + /* flags */ + ot->flag = 0; +} + /* ************************ viewmove ******************************** */ diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 28e0e48f220..c4207b0ce25 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -73,7 +73,8 @@ void VIEW3D_OT_dolly(struct wmOperatorType *ot); void VIEW3D_OT_zoom_camera_1_to_1(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_ndof_orbit(struct wmOperatorType *ot); +void VIEW3D_OT_ndof_pan(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); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 963e7aeeb95..e47cb1db753 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -64,7 +64,8 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_zoom); WM_operatortype_append(VIEW3D_OT_zoom_camera_1_to_1); WM_operatortype_append(VIEW3D_OT_dolly); - WM_operatortype_append(VIEW3D_OT_ndof); + WM_operatortype_append(VIEW3D_OT_ndof_orbit); + WM_operatortype_append(VIEW3D_OT_ndof_pan); WM_operatortype_append(VIEW3D_OT_view_all); WM_operatortype_append(VIEW3D_OT_viewnumpad); WM_operatortype_append(VIEW3D_OT_view_orbit); @@ -163,7 +164,8 @@ void view3d_keymap(wmKeyConfig *keyconf) 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_ndof", NDOF_MOTION, 0, 0, 0); + WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit", NDOF_MOTION, 0, 0, 0); + WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_pan", NDOF_MOTION, 0, KM_SHIFT, 0); WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BACK, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BACK); -- cgit v1.2.3 From 73a9ce7ec04bd1170b292c8f2c83a8c5c10a95ad Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Wed, 27 Jul 2011 07:42:53 +0000 Subject: svn merge -r38558:38752 https://svn.blender.org/svnroot/bf-blender/trunk/blender . --- CMakeLists.txt | 1 + doc/python_api/examples/mathutils.Vector.py | 13 +- intern/audaspace/OpenAL/AUD_OpenALDevice.cpp | 18 +- intern/audaspace/OpenAL/AUD_OpenALDevice.h | 2 +- release/scripts/modules/bpy/path.py | 2 +- release/scripts/modules/bpy_extras/view3d_utils.py | 10 +- release/scripts/modules/bpy_types.py | 14 +- .../scripts/startup/bl_operators/add_mesh_torus.py | 17 +- release/scripts/startup/bl_operators/image.py | 34 ++-- release/scripts/startup/bl_operators/mesh.py | 8 +- release/scripts/startup/bl_operators/object.py | 127 ++++++++---- .../scripts/startup/bl_operators/object_align.py | 119 ++++++----- .../startup/bl_operators/object_quick_effects.py | 134 ++++++++----- .../bl_operators/object_randomize_transform.py | 89 ++++++--- release/scripts/startup/bl_operators/presets.py | 53 +++-- .../bl_operators/screen_play_rendered_anim.py | 68 ++++--- .../startup/bl_operators/uvcalc_smart_project.py | 4 +- release/scripts/startup/bl_ui/properties_world.py | 6 +- release/scripts/startup/bl_ui/space_image.py | 4 + release/scripts/startup/bl_ui/space_info.py | 6 +- release/scripts/startup/bl_ui/space_text.py | 60 +++--- release/scripts/startup/bl_ui/space_view3d.py | 31 ++- .../scripts/startup/bl_ui/space_view3d_toolbar.py | 3 +- release/scripts/templates/panel_simple.py | 33 ---- release/scripts/templates/ui_menu.py | 49 +++++ release/scripts/templates/ui_menu_simple.py | 26 +++ release/scripts/templates/ui_panel_simple.py | 34 ++++ source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/BKE_effect.h | 1 + source/blender/blenkernel/CMakeLists.txt | 4 + source/blender/blenkernel/SConscript | 1 + source/blender/blenkernel/intern/effect.c | 23 +-- source/blender/blenkernel/intern/seqeffects.c | 2 +- source/blender/blenkernel/intern/text.c | 10 +- source/blender/blenkernel/intern/writeavi.c | 7 +- .../blender/blenkernel/intern/writeframeserver.c | 2 + source/blender/editors/armature/editarmature.c | 2 - source/blender/editors/include/ED_node.h | 3 + .../blender/editors/interface/interface_handlers.c | 11 +- .../blender/editors/interface/interface_layout.c | 12 +- source/blender/editors/interface/interface_panel.c | 4 +- .../blender/editors/interface/interface_regions.c | 11 ++ .../editors/interface/interface_templates.c | 20 +- source/blender/editors/object/object_add.c | 4 +- source/blender/editors/object/object_edit.c | 12 +- source/blender/editors/render/render_shading.c | 2 +- source/blender/editors/space_image/image_ops.c | 6 +- source/blender/editors/space_node/drawnode.c | 15 +- source/blender/editors/space_node/node_draw.c | 13 +- source/blender/editors/space_node/node_edit.c | 150 +++++++++++++- .../editors/space_sequencer/sequencer_add.c | 6 +- source/blender/editors/space_text/text_ops.c | 21 +- source/blender/editors/space_view3d/view3d_edit.c | 1 - .../blender/editors/space_view3d/view3d_header.c | 11 -- source/blender/editors/transform/transform.c | 2 +- source/blender/editors/transform/transform.h | 2 +- .../editors/transform/transform_conversions.c | 14 +- .../blender/editors/transform/transform_generics.c | 2 +- source/blender/editors/transform/transform_ops.c | 2 + source/blender/editors/transform/transform_snap.c | 13 +- source/blender/editors/util/undo.c | 8 +- source/blender/editors/uvedit/uvedit_ops.c | 131 ++++++++++++ source/blender/gpu/intern/gpu_material.c | 2 +- source/blender/imbuf/IMB_imbuf.h | 2 +- source/blender/imbuf/intern/filter.c | 219 +++++++++++---------- source/blender/makesdna/DNA_node_types.h | 4 + source/blender/makesdna/DNA_scene_types.h | 5 +- source/blender/makesrna/intern/CMakeLists.txt | 4 + source/blender/makesrna/intern/SConscript | 2 + source/blender/makesrna/intern/rna_access.c | 6 +- source/blender/makesrna/intern/rna_object_api.c | 2 +- source/blender/makesrna/intern/rna_scene.c | 10 +- source/blender/makesrna/intern/rna_wm.c | 2 +- source/blender/python/mathutils/mathutils.h | 2 + source/blender/python/mathutils/mathutils_Matrix.c | 14 +- .../python/mathutils/mathutils_Quaternion.c | 26 ++- source/blender/python/mathutils/mathutils_Vector.c | 80 +++++++- .../blender/render/intern/source/convertblender.c | 12 +- source/blender/render/intern/source/rendercore.c | 22 +-- source/blender/windowmanager/WM_api.h | 1 + source/blender/windowmanager/intern/wm.c | 6 + source/blenderplayer/bad_level_call_stubs/stubs.c | 1 - source/gameengine/Expressions/PyObjectPlus.cpp | 38 +--- source/gameengine/Expressions/PyObjectPlus.h | 1 + .../gameengine/GameLogic/Joystick/SCA_Joystick.cpp | 4 +- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 2 +- source/tests/CMakeLists.txt | 12 +- 87 files changed, 1346 insertions(+), 628 deletions(-) delete mode 100644 release/scripts/templates/panel_simple.py create mode 100644 release/scripts/templates/ui_menu.py create mode 100644 release/scripts/templates/ui_menu_simple.py create mode 100644 release/scripts/templates/ui_panel_simple.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 764e9f93414..9f833aef31e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -155,6 +155,7 @@ option(WITH_IMAGE_DDS "Enable DDS Image Support" ON) option(WITH_IMAGE_CINEON "Enable CINEON and DPX Image Support" ON) option(WITH_IMAGE_HDR "Enable HDR Image Support" ON) option(WITH_IMAGE_REDCODE "Enable RedCode Image Support" OFF) +option(WITH_IMAGE_FRAMESERVER "Enable image FrameServer Support for rendering" ON) # Audio/Video format support option(WITH_CODEC_FFMPEG "Enable FFMPeg Support (http://ffmpeg.org)" OFF) diff --git a/doc/python_api/examples/mathutils.Vector.py b/doc/python_api/examples/mathutils.Vector.py index 880b4ef2590..bf1fc70353f 100644 --- a/doc/python_api/examples/mathutils.Vector.py +++ b/doc/python_api/examples/mathutils.Vector.py @@ -1,15 +1,15 @@ import mathutils # zero length vector -vec = mathutils.Vector((0, 0, 1)) +vec = mathutils.Vector((0.0, 0.0, 1.0)) # unit length vector vec_a = vec.copy().normalize() -vec_b = mathutils.Vector((0, 1, 2)) +vec_b = mathutils.Vector((0.0, 1.0, 2.0)) -vec2d = mathutils.Vector((1, 2)) -vec3d = mathutils.Vector((1, 0, 0)) +vec2d = mathutils.Vector((1.0, 2.0)) +vec3d = mathutils.Vector((1.0, 0.0, 0.0)) vec4d = vec_a.to_4d() # other mathutuls types @@ -34,9 +34,9 @@ vec_a + vec_b vec_a - vec_b vec_a * vec_b vec_a * 10.0 -vec_a * matrix +matrix * vec_a +quat * vec_a vec_a * vec_b -vec_a * quat -vec_a @@ -44,6 +44,7 @@ vec_a * quat x = vec_a[0] len(vec) vec_a[:] = vec_b +vec_a[:] = 1.0, 2.0, 3.0 vec2d[:] = vec3d[:2] diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp index b9e30bbf62a..71e7b7677e8 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.cpp @@ -105,12 +105,15 @@ void* AUD_openalRunThread(void* device) return NULL; } -void AUD_OpenALDevice::start() +void AUD_OpenALDevice::start(bool join) { lock(); if(!m_playing) { + if(join) + pthread_join(m_thread, NULL); + pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); @@ -271,8 +274,8 @@ void AUD_OpenALDevice::updateStreams() // stop thread if(m_playingSounds->empty() || (cerr != ALC_NO_ERROR)) { - unlock(); m_playing = false; + unlock(); pthread_exit(NULL); } @@ -366,6 +369,8 @@ AUD_OpenALDevice::AUD_OpenALDevice(AUD_DeviceSpecs specs, int buffersize) pthread_mutex_init(&m_mutex, &attr); pthread_mutexattr_destroy(&attr); + + start(false); } AUD_OpenALDevice::~AUD_OpenALDevice() @@ -414,13 +419,8 @@ AUD_OpenALDevice::~AUD_OpenALDevice() alcProcessContext(m_context); // wait for the thread to stop - if(m_playing) - { - unlock(); - pthread_join(m_thread, NULL); - } - else - unlock(); + unlock(); + pthread_join(m_thread, NULL); delete m_playingSounds; delete m_pausedSounds; diff --git a/intern/audaspace/OpenAL/AUD_OpenALDevice.h b/intern/audaspace/OpenAL/AUD_OpenALDevice.h index 3bbbe85d7e6..127f69beca8 100644 --- a/intern/audaspace/OpenAL/AUD_OpenALDevice.h +++ b/intern/audaspace/OpenAL/AUD_OpenALDevice.h @@ -106,7 +106,7 @@ private: /** * Starts the streaming thread. */ - void start(); + void start(bool join = true); /** * Checks if a handle is valid. diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py index f6254efac2e..eb1a5ffc455 100644 --- a/release/scripts/modules/bpy/path.py +++ b/release/scripts/modules/bpy/path.py @@ -239,4 +239,4 @@ def basename(path): Use for Windows compatibility. """ - return _os.path.basename(path[2:] if path.startswith("//") else path) + return _os.path.basename(path[2:] if path[:2] in {"//", b"//"} else path) diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py index c0c0f9186bd..5796abce72c 100644 --- a/release/scripts/modules/bpy_extras/view3d_utils.py +++ b/release/scripts/modules/bpy_extras/view3d_utils.py @@ -50,11 +50,11 @@ def region_2d_to_vector_3d(region, rv3d, coord): -0.5 )) - w = (out[0] * persinv[0][3]) + \ - (out[1] * persinv[1][3]) + \ - (out[2] * persinv[2][3]) + persinv[3][3] + w = ((out[0] * persinv[0][3]) + + (out[1] * persinv[1][3]) + + (out[2] * persinv[2][3]) + persinv[3][3]) - return ((out * persinv) / w) - rv3d.view_matrix.inverted()[3].xyz + return ((persinv * out) / w) - rv3d.view_matrix.inverted()[3].xyz else: return rv3d.view_matrix.inverted()[2].xyz.normalized() @@ -116,7 +116,7 @@ def location_3d_to_region_2d(region, rv3d, coord): """ from mathutils import Vector - prj = Vector((coord[0], coord[1], coord[2], 1.0)) * rv3d.perspective_matrix + prj = rv3d.perspective_matrix * Vector((coord[0], coord[1], coord[2], 1.0)) if prj.w > 0.0: width_half = region.width / 2.0 height_half = region.height / 2.0 diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index f2cd46b20ae..8766c873dd8 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -144,21 +144,21 @@ class _GenericBone: """ Vector pointing down the x-axis of the bone. """ from mathutils import Vector - return Vector((1.0, 0.0, 0.0)) * self.matrix.to_3x3() + return self.matrix.to_3x3() * Vector((1.0, 0.0, 0.0)) @property def y_axis(self): """ Vector pointing down the x-axis of the bone. """ from mathutils import Vector - return Vector((0.0, 1.0, 0.0)) * self.matrix.to_3x3() + return self.matrix.to_3x3() * Vector((0.0, 1.0, 0.0)) @property def z_axis(self): """ Vector pointing down the x-axis of the bone. """ from mathutils import Vector - return Vector((0.0, 0.0, 1.0)) * self.matrix.to_3x3() + return self.matrix.to_3x3() * Vector((0.0, 0.0, 1.0)) @property def basename(self): @@ -294,9 +294,9 @@ class EditBone(StructRNA, _GenericBone, metaclass=StructMetaPropGroup): :type roll: bool """ from mathutils import Vector - z_vec = Vector((0.0, 0.0, 1.0)) * self.matrix.to_3x3() - self.tail = self.tail * matrix - self.head = self.head * matrix + z_vec = self.matrix.to_3x3() * Vector((0.0, 0.0, 1.0)) + self.tail = matrix * self.tail + self.head = matrix * self.head if scale: scalar = matrix.median_scale @@ -304,7 +304,7 @@ class EditBone(StructRNA, _GenericBone, metaclass=StructMetaPropGroup): self.tail_radius *= scalar if roll: - self.align_roll(z_vec * matrix) + self.align_roll(matrix * z_vec) def ord_ind(i1, i2): diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py index 6ab803cc469..27a6d21d519 100644 --- a/release/scripts/startup/bl_operators/add_mesh_torus.py +++ b/release/scripts/startup/bl_operators/add_mesh_torus.py @@ -16,7 +16,7 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# import bpy import mathutils @@ -40,8 +40,10 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg): for minor_index in range(minor_seg): angle = 2 * pi * minor_index / minor_seg - vec = Vector((major_rad + (cos(angle) * minor_rad), 0.0, - (sin(angle) * minor_rad))) * quat + vec = quat * Vector((major_rad + (cos(angle) * minor_rad), + 0.0, + (sin(angle) * minor_rad), + )) verts.extend(vec[:]) @@ -72,7 +74,11 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg): return verts, faces -from bpy.props import FloatProperty, IntProperty, BoolProperty, FloatVectorProperty +from bpy.props import (FloatProperty, + IntProperty, + BoolProperty, + FloatVectorProperty, + ) class AddTorus(bpy.types.Operator): @@ -82,7 +88,8 @@ class AddTorus(bpy.types.Operator): bl_options = {'REGISTER', 'UNDO'} major_radius = FloatProperty(name="Major Radius", - description="Radius from the origin to the center of the cross sections", + description=("Radius from the origin to the " + "center of the cross sections"), default=1.0, min=0.01, max=100.0) minor_radius = FloatProperty(name="Minor Radius", description="Radius of the torus' cross section", diff --git a/release/scripts/startup/bl_operators/image.py b/release/scripts/startup/bl_operators/image.py index 4bb53f776ba..23bafe2eaae 100644 --- a/release/scripts/startup/bl_operators/image.py +++ b/release/scripts/startup/bl_operators/image.py @@ -16,7 +16,7 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# import bpy from bpy.props import StringProperty @@ -28,7 +28,11 @@ class EditExternally(bpy.types.Operator): bl_label = "Image Edit Externally" bl_options = {'REGISTER'} - filepath = StringProperty(name="File Path", description="Path to an image file", maxlen=1024, default="") + filepath = StringProperty( + name="File Path", + description="Path to an image file", + maxlen=1024, + ) def _editor_guess(self, context): import sys @@ -57,10 +61,13 @@ class EditExternally(bpy.types.Operator): def execute(self, context): import os import subprocess - filepath = bpy.path.abspath(self.filepath) + filepath = os.path.normpath(bpy.path.abspath(self.filepath)) if not os.path.exists(filepath): - self.report({'ERROR'}, "Image path %r not found, image may be packed or unsaved." % filepath) + self.report({'ERROR'}, + "Image path %r not found, image may be packed or " + "unsaved." % filepath) + return {'CANCELLED'} cmd = self._editor_guess(context) + [filepath] @@ -70,7 +77,10 @@ class EditExternally(bpy.types.Operator): except: import traceback traceback.print_exc() - self.report({'ERROR'}, "Image editor not found, please specify in User Preferences > File") + self.report({'ERROR'}, + "Image editor not found, " + "please specify in User Preferences > File") + return {'CANCELLED'} return {'FINISHED'} @@ -104,7 +114,9 @@ class SaveDirty(bpy.types.Operator): if "\\" not in filepath and "/" not in filepath: self.report({'WARNING'}, "Invalid path: " + filepath) elif filepath in unique_paths: - self.report({'WARNING'}, "Path used by more then one image: " + filepath) + self.report({'WARNING'}, + "Path used by more then one image: %r" % + filepath) else: unique_paths.add(filepath) image.save() @@ -142,14 +154,14 @@ class ProjectEdit(bpy.types.Operator): filepath = os.path.basename(bpy.data.filepath) filepath = os.path.splitext(filepath)[0] - # filepath = bpy.path.clean_name(filepath) # fixes rubbish, needs checking + # fixes rubbish, needs checking + # filepath = bpy.path.clean_name(filepath) - if filepath.startswith(".") or filepath == "": - # TODO, have a way to check if the file is saved, assume startup.blend + if bpy.data.is_saved: + filepath = "//" + filepath + else: tmpdir = context.user_preferences.filepaths.temporary_directory filepath = os.path.join(tmpdir, "project_edit") - else: - filepath = "//" + filepath obj = context.object diff --git a/release/scripts/startup/bl_operators/mesh.py b/release/scripts/startup/bl_operators/mesh.py index 03b0e469310..344b238709f 100644 --- a/release/scripts/startup/bl_operators/mesh.py +++ b/release/scripts/startup/bl_operators/mesh.py @@ -16,7 +16,7 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# import bpy @@ -111,7 +111,8 @@ class MeshMirrorUV(bpy.types.Operator): #for i, v in enumerate(mesh.vertices): vmap = {} - for mirror_a, mirror_b in (mirror_gt, mirror_lt), (mirror_lt, mirror_gt): + for mirror_a, mirror_b in ((mirror_gt, mirror_lt), + (mirror_lt, mirror_gt)): for co, i in mirror_a.items(): nco = (-co[0], co[1], co[2]) j = mirror_b.get(nco) @@ -120,7 +121,8 @@ class MeshMirrorUV(bpy.types.Operator): active_uv_layer = mesh.uv_textures.active.data fuvs = [(uv.uv1, uv.uv2, uv.uv3, uv.uv4) for uv in active_uv_layer] - fuvs_cpy = [(uv[0].copy(), uv[1].copy(), uv[2].copy(), uv[3].copy()) for uv in fuvs] + fuvs_cpy = [(uv[0].copy(), uv[1].copy(), uv[2].copy(), uv[3].copy()) + for uv in fuvs] # as a list faces = mesh.faces[:] diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index 0342a14a1b2..0f0491e249e 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -28,9 +28,22 @@ class SelectPattern(bpy.types.Operator): bl_label = "Select Pattern" bl_options = {'REGISTER', 'UNDO'} - pattern = StringProperty(name="Pattern", description="Name filter using '*' and '?' wildcard chars", maxlen=32, default="*") - case_sensitive = BoolProperty(name="Case Sensitive", description="Do a case sensitive compare", default=False) - extend = BoolProperty(name="Extend", description="Extend the existing selection", default=True) + pattern = StringProperty( + name="Pattern", + description="Name filter using '*' and '?' wildcard chars", + maxlen=32, + default="*", + ) + case_sensitive = BoolProperty( + name="Case Sensitive", + description="Do a case sensitive compare", + default=False, + ) + extend = BoolProperty( + name="Extend", + description="Extend the existing selection", + default=True, + ) def execute(self, context): @@ -39,7 +52,8 @@ class SelectPattern(bpy.types.Operator): if self.case_sensitive: pattern_match = fnmatch.fnmatchcase else: - pattern_match = lambda a, b: fnmatch.fnmatchcase(a.upper(), b.upper()) + pattern_match = (lambda a, b: + fnmatch.fnmatchcase(a.upper(), b.upper())) obj = context.object if obj and obj.mode == 'POSE': @@ -98,14 +112,19 @@ class SelectHierarchy(bpy.types.Operator): bl_label = "Select Hierarchy" bl_options = {'REGISTER', 'UNDO'} - direction = EnumProperty(items=( - ('PARENT', "Parent", ""), - ('CHILD', "Child", "")), - name="Direction", - description="Direction to select in the hierarchy", - default='PARENT') + direction = EnumProperty( + items=(('PARENT', "Parent", ""), + ('CHILD', "Child", ""), + ), + name="Direction", + description="Direction to select in the hierarchy", + default='PARENT') - extend = BoolProperty(name="Extend", description="Extend the existing selection", default=False) + extend = BoolProperty( + name="Extend", + description="Extend the existing selection", + default=False, + ) @classmethod def poll(cls, context): @@ -163,7 +182,12 @@ class SubdivisionSet(bpy.types.Operator): level = IntProperty(name="Level", default=1, min=-100, max=100, soft_min=-6, soft_max=6) - relative = BoolProperty(name="Relative", description="Apply the subsurf level as an offset relative to the current level", default=False) + relative = BoolProperty( + name="Relative", + description=("Apply the subsurf level as an offset " + "relative to the current level"), + default=False, + ) @classmethod def poll(cls, context): @@ -215,7 +239,8 @@ class SubdivisionSet(bpy.types.Operator): mod = obj.modifiers.new("Subsurf", 'SUBSURF') mod.levels = level except: - self.report({'WARNING'}, "Modifiers cannot be added to object: " + obj.name) + self.report({'WARNING'}, + "Modifiers cannot be added to object: " + obj.name) for obj in context.selected_editable_objects: set_object_subd(obj) @@ -224,23 +249,37 @@ class SubdivisionSet(bpy.types.Operator): class ShapeTransfer(bpy.types.Operator): - '''Copy another selected objects active shape to this one by applying the relative offsets''' + '''Copy another selected objects active shape to this one by ''' \ + '''applying the relative offsets''' bl_idname = "object.shape_key_transfer" bl_label = "Transfer Shape Key" bl_options = {'REGISTER', 'UNDO'} - mode = EnumProperty(items=( - ('OFFSET', "Offset", "Apply the relative positional offset"), - ('RELATIVE_FACE', "Relative Face", "Calculate the geometricly relative position (using faces)."), - ('RELATIVE_EDGE', "Relative Edge", "Calculate the geometricly relative position (using edges).")), - name="Transformation Mode", - description="Method to apply relative shape positions to the new shape", - default='OFFSET') - - use_clamp = BoolProperty(name="Clamp Offset", - description="Clamp the transformation to the distance each vertex moves in the original shape.", - default=False) + mode = EnumProperty( + items=(('OFFSET', + "Offset", + "Apply the relative positional offset", + ), + ('RELATIVE_FACE', + "Relative Face", + "Calculate relative position (using faces).", + ), + ('RELATIVE_EDGE', + "Relative Edge", + "Calculate relative position (using edges).", + ), + ), + name="Transformation Mode", + description="Relative shape positions to the new shape method", + default='OFFSET', + ) + use_clamp = BoolProperty( + name="Clamp Offset", + description=("Clamp the transformation to the distance each " + "vertex moves in the original shape."), + default=False, + ) def _main(self, ob_act, objects, mode='OFFSET', use_clamp=False): @@ -272,13 +311,16 @@ class ShapeTransfer(bpy.types.Operator): orig_shape_coords = me_cos(ob_act.active_shape_key.data) orig_normals = me_nos(me.vertices) - # orig_coords = me_cos(me.vertices) # the actual mverts location isnt as relyable as the base shape :S + # the actual mverts location isnt as relyable as the base shape :S + # orig_coords = me_cos(me.vertices) orig_coords = me_cos(me.shape_keys.key_blocks[0].data) for ob_other in objects: me_other = ob_other.data if len(me_other.vertices) != len(me.vertices): - self.report({'WARNING'}, "Skipping '%s', vertex count differs" % ob_other.name) + self.report({'WARNING'}, + ("Skipping '%s', " + "vertex count differs") % ob_other.name) continue target_normals = me_nos(me_other.vertices) @@ -395,7 +437,10 @@ class ShapeTransfer(bpy.types.Operator): if 1: # swap from/to, means we cant copy to many at once. if len(objects) != 1: - self.report({'ERROR'}, "Expected one other selected mesh object to copy from") + self.report({'ERROR'}, + ("Expected one other selected " + "mesh object to copy from")) + return {'CANCELLED'} ob_act, objects = objects[0], [ob_act] @@ -429,11 +474,14 @@ class JoinUVs(bpy.types.Operator): bpy.ops.object.mode_set(mode='OBJECT', toggle=False) if not mesh.uv_textures: - self.report({'WARNING'}, "Object: %s, Mesh: '%s' has no UVs\n" % (obj.name, mesh.name)) + self.report({'WARNING'}, + "Object: %s, Mesh: '%s' has no UVs" + % (obj.name, mesh.name)) else: len_faces = len(mesh.faces) - uv_array = array.array('f', [0.0] * 8) * len_faces # seems to be the fastest way to create an array + # seems to be the fastest way to create an array + uv_array = array.array('f', [0.0] * 8) * len_faces mesh.uv_textures.active.data.foreach_get("uv_raw", uv_array) objects = context.selected_editable_objects[:] @@ -454,7 +502,8 @@ class JoinUVs(bpy.types.Operator): else: uv_other = mesh_other.uv_textures.active if not uv_other: - uv_other = mesh_other.uv_textures.new() # should return the texture it adds + # should return the texture it adds + uv_other = mesh_other.uv_textures.new() # finally do the copy uv_other.data.foreach_set("uv_raw", uv_array) @@ -482,14 +531,18 @@ class MakeDupliFace(bpy.types.Operator): SCALE_FAC = 0.01 offset = 0.5 * SCALE_FAC - base_tri = Vector((-offset, -offset, 0.0)), Vector((offset, -offset, 0.0)), Vector((offset, offset, 0.0)), Vector((-offset, offset, 0.0)) + base_tri = (Vector((-offset, -offset, 0.0)), + Vector((+offset, -offset, 0.0)), + Vector((+offset, +offset, 0.0)), + Vector((-offset, +offset, 0.0)), + ) def matrix_to_quat(matrix): # scale = matrix.median_scale trans = matrix.to_translation() rot = matrix.to_3x3() # also contains scale - return [(b * rot) + trans for b in base_tri] + return [(rot * b) + trans for b in base_tri] scene = bpy.context.scene linked = {} for obj in bpy.context.selected_objects: @@ -498,7 +551,10 @@ class MakeDupliFace(bpy.types.Operator): linked.setdefault(data, []).append(obj) for data, objects in linked.items(): - face_verts = [axis for obj in objects for v in matrix_to_quat(obj.matrix_world) for axis in v] + face_verts = [axis for obj in objects + for v in matrix_to_quat(obj.matrix_world) + for axis in v] + faces = list(range(len(face_verts) // 3)) mesh = bpy.data.meshes.new(data.name + "_dupli") @@ -535,7 +591,8 @@ class MakeDupliFace(bpy.types.Operator): class IsolateTypeRender(bpy.types.Operator): - '''Hide unselected render objects of same type as active by setting the hide render flag''' + '''Hide unselected render objects of same type as active ''' \ + '''by setting the hide render flag''' bl_idname = "object.isolate_type_render" bl_label = "Restrict Render Unselected" bl_options = {'REGISTER', 'UNDO'} diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py index d215f3476cf..8fe606399b4 100644 --- a/release/scripts/startup/bl_operators/object_align.py +++ b/release/scripts/startup/bl_operators/object_align.py @@ -16,102 +16,107 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# import bpy from mathutils import Vector def GlobalBB_LQ(bb_world): - + # Initialize the variables with the 8th vertex - left, right, front, back, down, up =\ - bb_world[7][0],\ - bb_world[7][0],\ - bb_world[7][1],\ - bb_world[7][1],\ - bb_world[7][2],\ - bb_world[7][2] - + left, right, front, back, down, up = (bb_world[7][0], + bb_world[7][0], + bb_world[7][1], + bb_world[7][1], + bb_world[7][2], + bb_world[7][2], + ) + # Test against the other 7 verts for i in range (7): - + # X Range val = bb_world[i][0] if val < left: left = val - + if val > right: right = val - + # Y Range val = bb_world[i][1] if val < front: front = val - + if val > back: back = val - + # Z Range val = bb_world[i][2] if val < down: down = val - + if val > up: up = val - + return (Vector((left, front, up)), Vector((right, back, down))) def GlobalBB_HQ(obj): - + matrix_world = obj.matrix_world.copy() - + # Initialize the variables with the last vertex - + verts = obj.data.vertices - - val = verts[-1].co * matrix_world - - left, right, front, back, down, up =\ - val[0],\ - val[0],\ - val[1],\ - val[1],\ - val[2],\ - val[2] - + + val = matrix_world * verts[-1].co + + left, right, front, back, down, up = (val[0], + val[0], + val[1], + val[1], + val[2], + val[2], + ) + # Test against all other verts for i in range (len(verts)-1): - - vco = verts[i].co * matrix_world - + + vco = matrix_world * verts[i].co + # X Range val = vco[0] if val < left: left = val - + if val > right: right = val - + # Y Range val = vco[1] if val < front: front = val - + if val > back: back = val - + # Z Range val = vco[2] if val < down: down = val - + if val > up: up = val - - return (Vector((left, front, up)), Vector((right, back, down))) + return Vector((left, front, up)), Vector((right, back, down)) -def align_objects(align_x, align_y, align_z, align_mode, relative_to, bb_quality): + +def align_objects(align_x, + align_y, + align_z, + align_mode, + relative_to, + bb_quality): cursor = bpy.context.scene.cursor_location @@ -123,20 +128,20 @@ def align_objects(align_x, align_y, align_z, align_mode, relative_to, bb_quality objs = [] for obj in bpy.context.selected_objects: - matrix_world = obj.matrix_world - bb_world = [Vector(v[:]) * matrix_world for v in obj.bound_box] + matrix_world = obj.matrix_world.copy() + bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box] objs.append((obj, bb_world)) if not objs: return False for obj, bb_world in objs: - + if bb_quality: GBB = GlobalBB_HQ(obj) else: GBB = GlobalBB_LQ(bb_world) - + Left_Front_Up = GBB[0] Right_Back_Down = GBB[1] @@ -193,13 +198,14 @@ def align_objects(align_x, align_y, align_z, align_mode, relative_to, bb_quality # Main Loop for obj, bb_world in objs: - bb_world = [Vector(v[:]) * obj.matrix_world for v in obj.bound_box] - + matrix_world = obj.matrix_world.copy() + bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box] + if bb_quality: GBB = GlobalBB_HQ(obj) else: GBB = GlobalBB_LQ(bb_world) - + Left_Front_Up = GBB[0] Right_Back_Down = GBB[1] @@ -339,8 +345,10 @@ class AlignObjects(bpy.types.Operator): bb_quality = BoolProperty( name="High Quality", - description="Enables high quality calculation of the bounding box for perfect results on complex shape meshes with rotation/scale (Slow)", - default=False) + description=("Enables high quality calculation of the " + "bounding box for perfect results on complex " + "shape meshes with rotation/scale (Slow)"), + default=True) align_mode = EnumProperty(items=( ('OPT_1', "Negative Sides", ""), @@ -374,10 +382,15 @@ class AlignObjects(bpy.types.Operator): def execute(self, context): align_axis = self.align_axis - ret = align_objects('X' in align_axis, 'Y' in align_axis, 'Z' in align_axis, self.align_mode, self.relative_to, self.bb_quality) + ret = align_objects('X' in align_axis, + 'Y' in align_axis, + 'Z' in align_axis, + self.align_mode, + self.relative_to, + self.bb_quality) if not ret: self.report({'WARNING'}, "No objects with bound-box selected") return {'CANCELLED'} else: - return {'FINISHED'} \ No newline at end of file + return {'FINISHED'} diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py index 074f204d50e..ef10bfd737d 100644 --- a/release/scripts/startup/bl_operators/object_quick_effects.py +++ b/release/scripts/startup/bl_operators/object_quick_effects.py @@ -16,11 +16,16 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# from mathutils import Vector import bpy -from bpy.props import BoolProperty, EnumProperty, IntProperty, FloatProperty, FloatVectorProperty +from bpy.props import (BoolProperty, + EnumProperty, + IntProperty, + FloatProperty, + FloatVectorProperty, + ) def object_ensure_material(obj, mat_name): @@ -61,7 +66,8 @@ class QuickFur(bpy.types.Operator): def execute(self, context): fake_context = bpy.context.copy() - mesh_objects = [obj for obj in context.selected_objects if obj.type == 'MESH'] + mesh_objects = [obj for obj in context.selected_objects + if obj.type == 'MESH'] if not mesh_objects: self.report({'ERROR'}, "Select at least one mesh object.") @@ -92,7 +98,8 @@ class QuickFur(bpy.types.Operator): psys.settings.child_type = 'INTERPOLATED' obj.data.materials.append(mat) - obj.particle_systems[-1].settings.material = len(obj.data.materials) + obj.particle_systems[-1].settings.material = \ + len(obj.data.materials) return {'FINISHED'} @@ -149,7 +156,10 @@ class QuickExplode(bpy.types.Operator): for obj in mesh_objects: if obj.particle_systems: - self.report({'ERROR'}, "Object %r already has a particle system" % obj.name) + self.report({'ERROR'}, + "Object %r already has a " + "particle system" % obj.name) + return {'CANCELLED'} if self.fade: @@ -184,9 +194,7 @@ class QuickExplode(bpy.types.Operator): if self.fade: explode.show_dead = False - bpy.ops.mesh.uv_texture_add(fake_context) - uv = obj.data.uv_textures[-1] - uv.name = "Explode fade" + uv = obj.data.uv_textures.new("Explode fade") explode.particle_uv = uv.name mat = object_ensure_material(obj, "Explode Fade") @@ -247,7 +255,7 @@ class QuickExplode(bpy.types.Operator): def obj_bb_minmax(obj, min_co, max_co): for i in range(0, 8): - bb_vec = Vector(obj.bound_box[i]) * obj.matrix_world + bb_vec = obj.matrix_world * Vector(obj.bound_box[i]) min_co[0] = min(bb_vec[0], min_co[0]) min_co[1] = min(bb_vec[1], min_co[1]) @@ -262,21 +270,26 @@ class QuickSmoke(bpy.types.Operator): bl_label = "Quick Smoke" bl_options = {'REGISTER', 'UNDO'} - style = EnumProperty(items=( - ('STREAM', "Stream", ""), - ('PUFF', "Puff", ""), - ('FIRE', "Fire", "")), - name="Smoke Style", - description="", - default='STREAM') - - show_flows = BoolProperty(name="Render Smoke Objects", - description="Keep the smoke objects visible during rendering.", - default=False) + style = EnumProperty( + items=(('STREAM', "Stream", ""), + ('PUFF', "Puff", ""), + ('FIRE', "Fire", ""), + ), + name="Smoke Style", + description="", + default='STREAM', + ) + + show_flows = BoolProperty( + name="Render Smoke Objects", + description="Keep the smoke objects visible during rendering.", + default=False, + ) def execute(self, context): fake_context = bpy.context.copy() - mesh_objects = [obj for obj in context.selected_objects if obj.type == 'MESH'] + mesh_objects = [obj for obj in context.selected_objects + if obj.type == 'MESH'] min_co = Vector((100000.0, 100000.0, 100000.0)) max_co = -min_co @@ -336,21 +349,25 @@ class QuickSmoke(bpy.types.Operator): mat.volume.density = 0 mat.volume.density_scale = 5 - mat.texture_slots.add() - mat.texture_slots[0].texture = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA') - mat.texture_slots[0].texture.voxel_data.domain_object = obj - mat.texture_slots[0].use_map_color_emission = False - mat.texture_slots[0].use_map_density = True + tex = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA') + tex.voxel_data.domain_object = obj + + tex_slot = mat.texture_slots.add() + tex_slot.texture = tex + tex_slot.use_map_color_emission = False + tex_slot.use_map_density = True # for fire add a second texture for emission and emission color if self.style == 'FIRE': mat.volume.emission = 5 - mat.texture_slots.add() - mat.texture_slots[1].texture = bpy.data.textures.new("Smoke Heat", 'VOXEL_DATA') - mat.texture_slots[1].texture.voxel_data.domain_object = obj - mat.texture_slots[1].texture.use_color_ramp = True + tex = bpy.data.textures.new("Smoke Heat", 'VOXEL_DATA') + tex.voxel_data.domain_object = obj + tex.use_color_ramp = True + + tex_slot = mat.texture_slots.add() + tex_slot.texture = tex - ramp = mat.texture_slots[1].texture.color_ramp + ramp = tex.color_ramp elem = ramp.elements.new(0.333) elem.color[0] = elem.color[3] = 1 @@ -371,28 +388,38 @@ class QuickFluid(bpy.types.Operator): bl_label = "Quick Fluid" bl_options = {'REGISTER', 'UNDO'} - style = EnumProperty(items=( - ('INFLOW', "Inflow", ""), - ('BASIC', "Basic", "")), + style = EnumProperty( + items=(('INFLOW', "Inflow", ""), + ('BASIC', "Basic", ""), + ), name="Fluid Style", description="", - default='BASIC') - - initial_velocity = FloatVectorProperty(name="Initial Velocity", - description="Initial velocity of the fluid", - default=(0.0, 0.0, 0.0), min=-100.0, max=100.0, subtype='VELOCITY') - - show_flows = BoolProperty(name="Render Fluid Objects", - description="Keep the fluid objects visible during rendering.", - default=False) - - start_baking = BoolProperty(name="Start Fluid Bake", - description="Start baking the fluid immediately after creating the domain object.", - default=False) + default='BASIC', + ) + initial_velocity = FloatVectorProperty( + name="Initial Velocity", + description="Initial velocity of the fluid", + default=(0.0, 0.0, 0.0), + min=-100.0, + max=100.0, + subtype='VELOCITY', + ) + show_flows = BoolProperty( + name="Render Fluid Objects", + description="Keep the fluid objects visible during rendering.", + default=False, + ) + start_baking = BoolProperty( + name="Start Fluid Bake", + description=("Start baking the fluid immediately " + "after creating the domain object"), + default=False, + ) def execute(self, context): fake_context = bpy.context.copy() - mesh_objects = [obj for obj in context.selected_objects if (obj.type == 'MESH' and not 0 in obj.dimensions)] + mesh_objects = [obj for obj in context.selected_objects + if (obj.type == 'MESH' and not 0.0 in obj.dimensions)] min_co = Vector((100000, 100000, 100000)) max_co = Vector((-100000, -100000, -100000)) @@ -405,7 +432,8 @@ class QuickFluid(bpy.types.Operator): # make each selected object a fluid bpy.ops.object.modifier_add(fake_context, type='FLUID_SIMULATION') - # fluid has to be before constructive modifiers, so it might not be the last modifier + # fluid has to be before constructive modifiers, + # so it might not be the last modifier for mod in obj.modifiers: if mod.type == 'FLUID_SIMULATION': break @@ -429,10 +457,14 @@ class QuickFluid(bpy.types.Operator): obj = context.active_object obj.name = "Fluid Domain" - # give the fluid some room below the flows and scale with initial velocity + # give the fluid some room below the flows + # and scale with initial velocity v = 0.5 * self.initial_velocity obj.location = 0.5 * (max_co + min_co) + Vector((0.0, 0.0, -1.0)) + v - obj.scale = 0.5 * (max_co - min_co) + Vector((1.0, 1.0, 2.0)) + Vector((abs(v[0]), abs(v[1]), abs(v[2]))) + obj.scale = (0.5 * (max_co - min_co) + + Vector((1.0, 1.0, 2.0)) + + Vector((abs(v[0]), abs(v[1]), abs(v[2]))) + ) # setup smoke domain bpy.ops.object.modifier_add(type='FLUID_SIMULATION') diff --git a/release/scripts/startup/bl_operators/object_randomize_transform.py b/release/scripts/startup/bl_operators/object_randomize_transform.py index 9dc5086086f..b94c4f06cd3 100644 --- a/release/scripts/startup/bl_operators/object_randomize_transform.py +++ b/release/scripts/startup/bl_operators/object_randomize_transform.py @@ -16,7 +16,7 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# import bpy @@ -93,40 +93,69 @@ class RandomizeLocRotSize(bpy.types.Operator): bl_label = "Randomize Transform" bl_options = {'REGISTER', 'UNDO'} - random_seed = IntProperty(name="Random Seed", - description="Seed value for the random generator", - default=0, min=0, max=1000) - - use_delta = BoolProperty(name="Transform Delta", - description="Randomize delta transform values instead of regular transform", default=False) - - use_loc = BoolProperty(name="Randomize Location", - description="Randomize the location values", default=True) - - loc = FloatVectorProperty(name="Location", - description="Maximun distance the objects can spread over each axis", - default=(0.0, 0.0, 0.0), min=-100.0, max=100.0, subtype='TRANSLATION') - - use_rot = BoolProperty(name="Randomize Rotation", - description="Randomize the rotation values", default=True) - - rot = FloatVectorProperty(name="Rotation", - description="Maximun rotation over each axis", - default=(0.0, 0.0, 0.0), min=-180.0, max=180.0, subtype='TRANSLATION') - - use_scale = BoolProperty(name="Randomize Scale", - description="Randomize the scale values", default=True) - - scale_even = BoolProperty(name="Scale Even", - description="Use the same scale value for all axis", default=False) + random_seed = IntProperty( + name="Random Seed", + description="Seed value for the random generator", + min=0, + max=1000, + default=0, + ) + use_delta = BoolProperty( + name="Transform Delta", + description=("Randomize delta transform values " + "instead of regular transform"), + default=False, + ) + use_loc = BoolProperty( + name="Randomize Location", + description="Randomize the location values", + default=True, + ) + loc = FloatVectorProperty( + name="Location", + description=("Maximun distance the objects " + "can spread over each axis"), + min=-100.0, + max=100.0, + default=(0.0, 0.0, 0.0), + subtype='TRANSLATION', + ) + use_rot = BoolProperty( + name="Randomize Rotation", + description="Randomize the rotation values", + default=True, + ) + rot = FloatVectorProperty( + name="Rotation", + description="Maximun rotation over each axis", + min=-180.0, + max=180.0, + default=(0.0, 0.0, 0.0), + subtype='TRANSLATION', + ) + use_scale = BoolProperty( + name="Randomize Scale", + description="Randomize the scale values", + default=True, + ) + scale_even = BoolProperty( + name="Scale Even", + description="Use the same scale value for all axis", + default=False, + ) '''scale_min = FloatProperty(name="Minimun Scale Factor", description="Lowest scale percentage possible", default=0.15, min=-1.0, max=1.0, precision=3)''' - scale = FloatVectorProperty(name="Scale", - description="Maximum scale randomization over each axis", - default=(0.0, 0.0, 0.0), min=-100.0, max=100.0, subtype='TRANSLATION') + scale = FloatVectorProperty( + name="Scale", + description="Maximum scale randomization over each axis", + min=-100.0, + max=100.0, + default=(0.0, 0.0, 0.0), + subtype='TRANSLATION', + ) def execute(self, context): from math import radians diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py index f3c799c9ac2..fbcc327c3bd 100644 --- a/release/scripts/startup/bl_operators/presets.py +++ b/release/scripts/startup/bl_operators/presets.py @@ -16,7 +16,7 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# import bpy @@ -30,8 +30,15 @@ class AddPresetBase(): # bl_label = "Add a Python Preset" bl_options = {'REGISTER'} # only because invoke_props_popup requires. - name = bpy.props.StringProperty(name="Name", description="Name of the preset, used to make the path name", maxlen=64, default="") - remove_active = bpy.props.BoolProperty(default=False, options={'HIDDEN'}) + name = bpy.props.StringProperty( + name="Name", + description="Name of the preset, used to make the path name", + maxlen=64, + ) + remove_active = bpy.props.BoolProperty( + default=False, + options={'HIDDEN'}, + ) @staticmethod def as_filename(name): # could reuse for other presets @@ -54,7 +61,10 @@ class AddPresetBase(): filename = self.as_filename(name) - target_path = bpy.utils.user_resource('SCRIPTS', os.path.join("presets", self.preset_subdir), create=True) + target_path = os.path.join("presets", self.preset_subdir) + target_path = bpy.utils.user_resource('SCRIPTS', + target_path, + create=True) if not target_path: self.report({'WARNING'}, "Failed to create presets path") @@ -95,7 +105,9 @@ class AddPresetBase(): filepath = bpy.utils.preset_find(preset_active, self.preset_subdir) if not filepath: - filepath = bpy.utils.preset_find(preset_active, self.preset_subdir, display_name=True) + filepath = bpy.utils.preset_find(preset_active, + self.preset_subdir, + display_name=True) if not filepath: return {'CANCELLED'} @@ -133,8 +145,15 @@ class ExecutePreset(bpy.types.Operator): bl_idname = "script.execute_preset" bl_label = "Execute a Python Preset" - filepath = bpy.props.StringProperty(name="Path", description="Path of the Python file to execute", maxlen=512, default="") - menu_idname = bpy.props.StringProperty(name="Menu ID Name", description="ID name of the menu this was called from", default="") + filepath = bpy.props.StringProperty( + name="Path", + description="Path of the Python file to execute", + maxlen=512, + ) + menu_idname = bpy.props.StringProperty( + name="Menu ID Name", + description="ID name of the menu this was called from", + ) def execute(self, context): from os.path import basename @@ -182,7 +201,10 @@ class AddPresetSSS(AddPresetBase, bpy.types.Operator): preset_menu = "MATERIAL_MT_sss_presets" preset_defines = [ - "material = (bpy.context.material.active_node_material if bpy.context.material.active_node_material else bpy.context.material)" + ("material = " + "bpy.context.material.active_node_material " + "if bpy.context.material.active_node_material " + "else bpy.context.material") ] preset_values = [ @@ -306,7 +328,11 @@ class AddPresetOperator(AddPresetBase, bpy.types.Operator): bl_label = "Operator Preset" preset_menu = "WM_MT_operator_presets" - operator = bpy.props.StringProperty(name="Operator", maxlen=64, options={'HIDDEN'}) + operator = bpy.props.StringProperty( + name="Operator", + maxlen=64, + options={'HIDDEN'}, + ) # XXX, not ideal preset_defines = [ @@ -322,12 +348,15 @@ class AddPresetOperator(AddPresetBase, bpy.types.Operator): properties_blacklist = bpy.types.Operator.bl_rna.properties.keys() prefix, suffix = self.operator.split("_OT_", 1) - operator_rna = getattr(getattr(bpy.ops, prefix.lower()), suffix).get_rna().bl_rna + op = getattr(getattr(bpy.ops, prefix.lower()), suffix) + operator_rna = op.get_rna().bl_rna + del op ret = [] for prop_id, prop in operator_rna.properties.items(): - if (not (prop.is_hidden or prop.is_skip_save)) and prop_id not in properties_blacklist: - ret.append("op.%s" % prop_id) + if not (prop.is_hidden or prop.is_skip_save): + if prop_id not in properties_blacklist: + ret.append("op.%s" % prop_id) return ret diff --git a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py index 910ccf96c0e..4b3435eacbe 100644 --- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py +++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py @@ -1,27 +1,23 @@ -# ***** BEGIN GPL LICENSE BLOCK ***** +# ##### BEGIN GPL LICENSE BLOCK ##### # -# Script copyright (C) Campbell J Barton +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. # -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ***** END GPL LICENCE BLOCK ***** +# ##### END GPL LICENSE BLOCK ##### -# +# -# History -# # Originally written by Matt Ebb import bpy @@ -46,8 +42,10 @@ def guess_player_path(preset): player_path = "djv_view" if sys.platform == "darwin": - # TODO, crummy supporting only 1 version, could find the newest installed version - test_path = '/Applications/djv-0.8.2.app/Contents/Resources/bin/djv_view' + # TODO, crummy supporting only 1 version, + # could find the newest installed version + test_path = ("/Applications/djv-0.8.2.app" + "/Contents/Resources/bin/djv_view") if os.path.exists(test_path): player_path = test_path @@ -60,6 +58,9 @@ def guess_player_path(preset): elif preset == 'MPLAYER': player_path = "mplayer" + else: + player_path = "" + return player_path @@ -82,10 +83,10 @@ class PlayRenderedAnim(bpy.types.Operator): is_movie = rd.is_movie_format # try and guess a command line if it doesn't exist - if player_path == '': + if player_path == "": player_path = guess_player_path(preset) - if is_movie == False and preset in ('FRAMECYCLER', 'RV', 'MPLAYER'): + if is_movie == False and preset in {'FRAMECYCLER', 'RV', 'MPLAYER'}: # replace the number with '#' file_a = rd.frame_path(frame=0) @@ -95,11 +96,11 @@ class PlayRenderedAnim(bpy.types.Operator): while len(file_a) == len(file_b): frame_tmp = (frame_tmp * 10) + 9 - print(frame_tmp) file_b = rd.frame_path(frame=frame_tmp) file_b = rd.frame_path(frame=int(frame_tmp / 10)) - file = "".join((c if file_b[i] == c else "#") for i, c in enumerate(file_a)) + file = ("".join((c if file_b[i] == c else "#") + for i, c in enumerate(file_a))) else: # works for movies and images file = rd.frame_path(frame=scene.frame_start) @@ -112,7 +113,7 @@ class PlayRenderedAnim(bpy.types.Operator): opts = ["-a", "-f", str(rd.fps), str(rd.fps_base), file] cmd.extend(opts) elif preset == 'DJV': - opts = [file, "-playback_speed", str(rd.fps)] + opts = [file, "-playback_speed", "%d" % int(rd.fps / rd.fps_base)] cmd.extend(opts) elif preset == 'FRAMECYCLER': opts = [file, "%d-%d" % (scene.frame_start, scene.frame_end)] @@ -125,18 +126,25 @@ class PlayRenderedAnim(bpy.types.Operator): if is_movie: opts.append(file) else: - opts.append("mf://%s" % file.replace("#", "?")) - opts += ["-mf", "fps=%.4f" % (rd.fps / rd.fps_base)] + opts += [("mf://%s" % file.replace("#", "?")), + "-mf", + "fps=%.4f" % (rd.fps / rd.fps_base), + ] + opts += ["-loop", "0", "-really-quiet", "-fs"] cmd.extend(opts) else: # 'CUSTOM' cmd.append(file) # launch it + print("Executing command:\n %r" % " ".join(cmd)) + try: process = subprocess.Popen(cmd) - except: - pass - #raise OSError("Couldn't find an external animation player.") + except Exception as e: + import traceback + self.report({'ERROR'}, + "Couldn't run external animation player with command " + "%r\n%s" % (" ".join(cmd), str(e))) return {'FINISHED'} diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py index 9c3be84b807..851f33bde11 100644 --- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py +++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py @@ -243,7 +243,7 @@ def testNewVecLs2DRotIsBetter(vecs, mat=-1, bestAreaSoFar = -1): # Do this allong the way if mat != -1: - v = vecs[i] = v*mat + v = vecs[i] = mat * v x= v.x y= v.y if x +# import bpy @@ -33,19 +33,21 @@ class TEXT_HT_header(bpy.types.Header): row.template_header() if context.area.show_menus: - sub = row.row(align=True) - sub.menu("TEXT_MT_view") - sub.menu("TEXT_MT_text") + row.menu("TEXT_MT_view") + row.menu("TEXT_MT_text") + if text: - sub.menu("TEXT_MT_edit") - sub.menu("TEXT_MT_format") + row.menu("TEXT_MT_edit") + row.menu("TEXT_MT_format") + + row.menu("TEXT_MT_templates") if text and text.is_modified: - row = layout.row() - row.alert = True - row.operator("text.resolve_conflict", text="", icon='HELP') + sub = row.row() + sub.alert = True + sub.operator("text.resolve_conflict", text="", icon='HELP') - layout.template_ID(st, "text", new="text.new", unlink="text.unlink") + row.template_ID(st, "text", new="text.new", unlink="text.unlink") row = layout.row(align=True) row.prop(st, "show_line_numbers", text="") @@ -63,11 +65,13 @@ class TEXT_HT_header(bpy.types.Header): row = layout.row() if text.filepath: if text.is_dirty: - row.label(text="File: *%s (unsaved)" % text.filepath) + row.label(text="File: *%r (unsaved)" % text.filepath) else: - row.label(text="File: %s" % text.filepath) + row.label(text="File: %r" % text.filepath) else: - row.label(text="Text: External" if text.library else "Text: Internal") + row.label(text="Text: External" + if text.library + else "Text: Internal") class TEXT_PT_properties(bpy.types.Panel): @@ -150,8 +154,12 @@ class TEXT_MT_view(bpy.types.Menu): layout.separator() - layout.operator("text.move", text="Top of File").type = 'FILE_TOP' - layout.operator("text.move", text="Bottom of File").type = 'FILE_BOTTOM' + layout.operator("text.move", + text="Top of File", + ).type = 'FILE_TOP' + layout.operator("text.move", + text="Bottom of File", + ).type = 'FILE_BOTTOM' class TEXT_MT_text(bpy.types.Menu): @@ -185,19 +193,15 @@ class TEXT_MT_text(bpy.types.Menu): # XXX uiMenuItemO(head, 0, "text.refresh_pyconstraints"); #endif - layout.separator() - - layout.menu("TEXT_MT_templates") - class TEXT_MT_templates(bpy.types.Menu): - ''' - Creates the menu items by scanning scripts/templates - ''' - bl_label = "Script Templates" + bl_label = "Templates" def draw(self, context): - self.path_menu(bpy.utils.script_paths("templates"), "text.open", {"internal": True}) + self.path_menu(bpy.utils.script_paths("templates"), + "text.open", + {"internal": True}, + ) class TEXT_MT_edit_select(bpy.types.Menu): @@ -246,8 +250,12 @@ class TEXT_MT_edit_to3d(bpy.types.Menu): def draw(self, context): layout = self.layout - layout.operator("text.to_3d_object", text="One Object").split_lines = False - layout.operator("text.to_3d_object", text="One Object Per Line").split_lines = True + layout.operator("text.to_3d_object", + text="One Object", + ).split_lines = False + layout.operator("text.to_3d_object", + text="One Object Per Line", + ).split_lines = True class TEXT_MT_edit(bpy.types.Menu): diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index b31618cfad0..ee0ca94f54e 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -54,21 +54,13 @@ class VIEW3D_HT_header(bpy.types.Header): sub.menu("VIEW3D_MT_object") row = layout.row() - row.template_header_3D() - - # do in C for now since these buttons cant be both toggle AND exclusive. - ''' - if obj and obj.mode == 'EDIT' and obj.type == 'MESH': - row_sub = row.row(align=True) - row_sub.prop(toolsettings, "mesh_select_mode", text="", index=0, icon='VERTEXSEL') - row_sub.prop(toolsettings, "mesh_select_mode", text="", index=1, icon='EDGESEL') - row_sub.prop(toolsettings, "mesh_select_mode", text="", index=2, icon='FACESEL') - ''' + # Contains buttons like Mode, Pivot, Manipulator, Layer, Mesh Select Mode... + row.template_header_3D() if obj: # Particle edit if obj.mode == 'PARTICLE_EDIT': - row.prop(toolsettings.particle_edit, "select_mode", text="", expand=True, toggle=True) + row.prop(toolsettings.particle_edit, "select_mode", text="", expand=True) # Occlude geometry if view.viewport_shade in {'SOLID', 'SHADED', 'TEXTURED'} and (obj.mode == 'PARTICLE_EDIT' or (obj.mode == 'EDIT' and obj.type == 'MESH')): @@ -87,19 +79,22 @@ class VIEW3D_HT_header(bpy.types.Header): row.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True) # Snap + snap_element = toolsettings.snap_element row = layout.row(align=True) row.prop(toolsettings, "use_snap", text="") row.prop(toolsettings, "snap_element", text="", icon_only=True) - if toolsettings.snap_element != 'INCREMENT': + if snap_element != 'INCREMENT': row.prop(toolsettings, "snap_target", text="") - if obj and obj.mode == 'OBJECT': - row.prop(toolsettings, "use_snap_align_rotation", text="") - if toolsettings.snap_element == 'VOLUME': + if obj: + if obj.mode == 'OBJECT': + row.prop(toolsettings, "use_snap_align_rotation", text="") + elif obj.mode == 'EDIT': + row.prop(toolsettings, "use_snap_self", text="") + + if snap_element == 'VOLUME': row.prop(toolsettings, "use_snap_peel_object", text="") - elif toolsettings.snap_element == 'FACE': + elif snap_element == 'FACE': row.prop(toolsettings, "use_snap_project", text="") - if toolsettings.use_snap_project and obj.mode == 'EDIT': - row.prop(toolsettings, "use_snap_project_self", text="") # OpenGL render row = layout.row(align=True) diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index e1efeed87ea..19c3224f138 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -116,7 +116,8 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, bpy.types.Panel): col.operator("transform.translate") col.operator("transform.rotate") col.operator("transform.resize", text="Scale") - col.operator("transform.shrink_fatten", text="Along Normal") + col.operator("transform.shrink_fatten", text="Shrink/Fatten") + col.operator("transform.push_pull", text="Push/Pull") col = layout.column(align=True) col.label(text="Deform:") diff --git a/release/scripts/templates/panel_simple.py b/release/scripts/templates/panel_simple.py deleted file mode 100644 index e5bf70cb654..00000000000 --- a/release/scripts/templates/panel_simple.py +++ /dev/null @@ -1,33 +0,0 @@ -import bpy - - -class OBJECT_PT_hello(bpy.types.Panel): - bl_label = "Hello World Panel" - bl_space_type = "PROPERTIES" - bl_region_type = "WINDOW" - bl_context = "object" - - def draw(self, context): - layout = self.layout - - obj = context.object - - row = layout.row() - row.label(text="Hello world!", icon='WORLD_DATA') - - row = layout.row() - row.label(text="Active object is: " + obj.name) - row = layout.row() - row.prop(obj, "name") - - -def register(): - bpy.utils.register_class(OBJECT_PT_hello) - - -def unregister(): - bpy.utils.unregister_class(OBJECT_PT_hello) - - -if __name__ == "__main__": - register() diff --git a/release/scripts/templates/ui_menu.py b/release/scripts/templates/ui_menu.py new file mode 100644 index 00000000000..d3923b5b083 --- /dev/null +++ b/release/scripts/templates/ui_menu.py @@ -0,0 +1,49 @@ +import bpy + + +class CustomMenu(bpy.types.Menu): + bl_label = "Custom Menu" + bl_idname = "OBJECT_MT_custom_menu" + + def draw(self, context): + layout = self.layout + + layout.operator("wm.open_mainfile") + layout.operator("wm.save_as_mainfile").copy = True + + layout.operator("object.shade_smooth") + + layout.label(text="Hello world!", icon='WORLD_DATA') + + # use an operator enum property to populate a submenu + layout.operator_menu_enum("object.select_by_type", + property="type", + text="Select All by Type...", + ) + + # call another menu + layout.operator("wm.call_menu", text="Unwrap").name = "VIEW3D_MT_uv_map" + + +def draw_item(self, context): + layout = self.layout + layout.menu(CustomMenu.bl_idname) + + +def register(): + bpy.utils.register_class(CustomMenu) + + # lets add ourselves to the main header + bpy.types.INFO_HT_header.append(draw_item) + + +def unregister(): + bpy.utils.unregister_class(CustomMenu) + + bpy.types.INFO_HT_header.remove(draw_item) + +if __name__ == "__main__": + register() + + # The menu can also be called from scripts + bpy.ops.wm.call_menu(name=CustomMenu.bl_idname) diff --git a/release/scripts/templates/ui_menu_simple.py b/release/scripts/templates/ui_menu_simple.py new file mode 100644 index 00000000000..2129dfd81a4 --- /dev/null +++ b/release/scripts/templates/ui_menu_simple.py @@ -0,0 +1,26 @@ +import bpy + + +class SimpleCustomMenu(bpy.types.Menu): + bl_label = "Simple Custom Menu" + bl_idname = "OBJECT_MT_simple_custom_menu" + + def draw(self, context): + layout = self.layout + + layout.operator("wm.open_mainfile") + layout.operator("wm.save_as_mainfile") + + +def register(): + bpy.utils.register_class(SimpleCustomMenu) + + +def unregister(): + bpy.utils.unregister_class(SimpleCustomMenu) + +if __name__ == "__main__": + register() + + # The menu can also be called from scripts + bpy.ops.wm.call_menu(name=SimpleCustomMenu.bl_idname) diff --git a/release/scripts/templates/ui_panel_simple.py b/release/scripts/templates/ui_panel_simple.py new file mode 100644 index 00000000000..cde6126b626 --- /dev/null +++ b/release/scripts/templates/ui_panel_simple.py @@ -0,0 +1,34 @@ +import bpy + + +class HelloWorldPanel(bpy.types.Panel): + bl_label = "Hello World Panel" + bl_idname = "OBJECT_PT_hello" + bl_space_type = "PROPERTIES" + bl_region_type = "WINDOW" + bl_context = "object" + + def draw(self, context): + layout = self.layout + + obj = context.object + + row = layout.row() + row.label(text="Hello world!", icon='WORLD_DATA') + + row = layout.row() + row.label(text="Active object is: " + obj.name) + row = layout.row() + row.prop(obj, "name") + + +def register(): + bpy.utils.register_class(HelloWorldPanel) + + +def unregister(): + bpy.utils.unregister_class(HelloWorldPanel) + + +if __name__ == "__main__": + register() diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 25fb6f9f9ff..18f6ad21333 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -53,7 +53,7 @@ extern "C" { /* can be left blank, otherwise a,b,c... etc with no quotes */ #define BLENDER_VERSION_CHAR a /* alpha/beta/rc/release, docs use this */ -#define BLENDER_VERSION_CYCLE release +#define BLENDER_VERSION_CYCLE beta struct ListBase; struct MemFile; diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index 97ac711651b..12f9383cefb 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -105,6 +105,7 @@ typedef struct EffectorCache { /* precalculated for guides */ struct GuideEffectorData *guide_data; float guide_loc[4], guide_dir[3], guide_radius; + float velocity[3]; float frame; int flag; diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 9a384c40e24..defcef58463 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -279,6 +279,10 @@ if(WITH_IMAGE_CINEON) add_definitions(-DWITH_CINEON) endif() +if(WITH_IMAGE_FRAMESERVER) + add_definitions(-DWITH_FRAMESERVER) +endif() + if(WITH_IMAGE_HDR) add_definitions(-DWITH_HDR) endif() diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 36afce7946c..5ea42ee65ae 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -22,6 +22,7 @@ incs += ' ' + env['BF_ZLIB_INC'] defs = [ 'GLEW_STATIC' ] defs.append('WITH_SMOKE') # TODO, make optional +defs.append('WITH_FRAMESERVER') # TODO, make optional if env['WITH_BF_PYTHON']: incs += ' ../python' diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index ee46bef6038..4b95c44f55f 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -241,6 +241,16 @@ static void precalculate_effector(EffectorCache *eff) } else if(eff->psys) psys_update_particle_tree(eff->psys, eff->scene->r.cfra); + + /* Store object velocity */ + if(eff->ob) { + float old_vel[3]; + + where_is_object_time(eff->scene, eff->ob, cfra - 1.0f); + copy_v3_v3(old_vel, eff->ob->obmat[3]); + where_is_object_time(eff->scene, eff->ob, cfra); + sub_v3_v3v3(eff->velocity, eff->ob->obmat[3], old_vel); + } } static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd) { @@ -680,10 +690,6 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin Object *ob = eff->ob; Object obcopy = *ob; - /* XXX this is not thread-safe, but used from multiple threads by - particle system */ - where_is_object_time(eff->scene, ob, cfra); - /* use z-axis as normal*/ normalize_v3_v3(efd->nor, ob->obmat[2]); @@ -702,13 +708,8 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin VECCOPY(efd->loc, ob->obmat[3]); } - if(real_velocity) { - VECCOPY(efd->vel, ob->obmat[3]); - - where_is_object_time(eff->scene, ob, cfra - 1.0f); - - sub_v3_v3v3(efd->vel, efd->vel, ob->obmat[3]); - } + if(real_velocity) + copy_v3_v3(efd->vel, eff->velocity); *eff->ob = obcopy; diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index fbb5a77fa04..8c19b0c15c3 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -2373,7 +2373,7 @@ static void RVBlurBitmap2_float ( float* map, int width,int height, /* Blancmange (bmange@airdmhor.gen.nz) */ k = -1.0f/(2.0f*(float)M_PI*blur*blur); - fval=0; + for (ix = 0;ix< halfWidth;ix++){ weight = (float)exp(k*(ix*ix)); filter[halfWidth - ix] = weight; diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index da329503c9f..2c507370288 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -400,7 +400,13 @@ Text *add_text(const char *file, const char *relpath) llen++; } - if (llen!=0 || ta->nlines==0) { + /* create new line in cases: + - rest of line (if last line in file hasn't got \n terminator). + in this case content of such line would be used to fill text line buffer + - file is empty. in this case new line is needed to start editing from. + - last characted in buffer is \n. in this case new line is needed to + deal with newline at end of file. (see [#28087]) (sergey) */ + if (llen!=0 || ta->nlines==0 || buffer[len-1]=='\n') { tmp= (TextLine*) MEM_mallocN(sizeof(TextLine), "textline"); tmp->line= (char*) MEM_mallocN(llen+1, "textline_string"); tmp->format= NULL; @@ -1417,6 +1423,8 @@ void txt_insert_buf(Text *text, const char *in_buffer) } undoing= u; + + (void)count; } /******************/ diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index ba7f9bdd415..769a3f9b11e 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -105,13 +105,18 @@ bMovieHandle *BKE_get_movie_handle(int imtype) mh.get_movie_path = filepath_ffmpeg; } #endif +#ifdef WITH_FRAMESERVER if (imtype == R_FRAMESERVER) { mh.start_movie = start_frameserver; mh.append_movie = append_frameserver; mh.end_movie = end_frameserver; mh.get_next_frame = frameserver_loop; } - +#endif + + /* incase all above are disabled */ + (void)imtype; + return &mh; } diff --git a/source/blender/blenkernel/intern/writeframeserver.c b/source/blender/blenkernel/intern/writeframeserver.c index 2239f6d3147..d13d15d1269 100644 --- a/source/blender/blenkernel/intern/writeframeserver.c +++ b/source/blender/blenkernel/intern/writeframeserver.c @@ -22,6 +22,7 @@ * */ +#ifdef WITH_FRAMESERVER #include #include @@ -381,3 +382,4 @@ void end_frameserver(void) shutdown_socket_system(); } +#endif /* WITH_FRAMESERVER */ diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 20352206121..628cdbf21e9 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -1478,10 +1478,8 @@ static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *e bArmature *arm; EditBone *bone, *curBone, *next; int extend= RNA_boolean_get(op->ptr, "extend"); - ARegion *ar; Object *obedit= CTX_data_edit_object(C); arm= obedit->data; - ar= CTX_wm_region(C); view3d_operator_needs_opengl(C); diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 829ad3217a9..dfa457c22de 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -39,6 +39,7 @@ struct Tex; struct bContext; struct bNode; struct ID; +struct ScrArea; /* drawnode.c */ void ED_init_node_butfuncs(void); @@ -51,6 +52,8 @@ void ED_node_generic_update(struct Main *bmain, struct bNodeTree *ntree, struct void ED_node_shader_default(struct Material *ma); void ED_node_composit_default(struct Scene *sce); void ED_node_texture_default(struct Tex *tex); +void ED_node_link_intersect_test(struct ScrArea *sa, int test); +void ED_node_link_insert(struct ScrArea *sa); /* node ops.c */ void ED_operatormacros_node(void); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index e9ec4ccc66d..c5275ea98b5 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1879,7 +1879,6 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle if(but->autocomplete_func || data->searchbox) { changed= ui_textedit_autocomplete(C, but, data); update= 1; /* do live update for tab key */ - retval= WM_UI_HANDLER_BREAK; } /* the hotkey here is not well defined, was G.qual so we check all */ else if(event->shift || event->ctrl || event->alt || event->oskey) { @@ -2325,8 +2324,8 @@ static float ui_numedit_apply_snapf(uiBut *but, float tempf, float softmin, floa if(fac != 1.0f) { /* snap in unit-space */ tempf /= fac; - softmin /= fac; - softmax /= fac; + /* softmin /= fac; */ /* UNUSED */ + /* softmax /= fac; */ /* UNUSED */ softrange /= fac; } @@ -3469,13 +3468,13 @@ static int ui_numedit_but_CURVE(uiBut *but, uiHandleButtonData *data, int snap, CurveMapping *cumap= (CurveMapping*)but->poin; CurveMap *cuma= cumap->cm+cumap->cur; CurveMapPoint *cmp= cuma->curve; - float fx, fy, zoomx, zoomy, offsx, offsy; + float fx, fy, zoomx, zoomy /*, offsx, offsy */ /* UNUSED */; int a, changed= 0; zoomx= (but->x2-but->x1)/(cumap->curr.xmax-cumap->curr.xmin); zoomy= (but->y2-but->y1)/(cumap->curr.ymax-cumap->curr.ymin); - offsx= cumap->curr.xmin; - offsy= cumap->curr.ymin; + /* offsx= cumap->curr.xmin; */ + /* offsy= cumap->curr.ymin; */ if(snap) { float d[2]; diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 79a90fb9d1d..2f0bcc9d5b4 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -149,10 +149,10 @@ typedef struct uiLayoutItemBx { uiBut *roundbox; } uiLayoutItemBx; -typedef struct uiLayoutItemSplt { +typedef struct uiLayoutItemSplit { uiLayout litem; float percentage; -} uiLayoutItemSplt; +} uiLayoutItemSplit; typedef struct uiLayoutItemRoot { uiLayout litem; @@ -1615,7 +1615,7 @@ static void ui_litem_layout_row(uiLayout *litem) int x, y, w, tot, totw, neww, itemw, minw, itemh, offset; int fixedw, freew, fixedx, freex, flag= 0, lastw= 0; - x= litem->x; + /* x= litem->x; */ /* UNUSED */ y= litem->y; w= litem->w; totw= 0; @@ -2020,7 +2020,7 @@ static void ui_litem_estimate_split(uiLayout *litem) static void ui_litem_layout_split(uiLayout *litem) { - uiLayoutItemSplt *split= (uiLayoutItemSplt*)litem; + uiLayoutItemSplit *split= (uiLayoutItemSplit*)litem; uiItem *item; float percentage; const int tot= BLI_countlist(&litem->items); @@ -2242,9 +2242,9 @@ uiLayout *uiLayoutOverlap(uiLayout *layout) uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align) { - uiLayoutItemSplt *split; + uiLayoutItemSplit *split; - split= MEM_callocN(sizeof(uiLayoutItemSplt), "uiLayoutItemSplt"); + split= MEM_callocN(sizeof(uiLayoutItemSplit), "uiLayoutItemSplit"); split->litem.item.type= ITEM_LAYOUT_SPLIT; split->litem.root= layout->root; split->litem.align= align; diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 9ed3cabb4cb..3b20533dcd4 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -575,8 +575,8 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, rcti *rect) ui_draw_tria_rect(&itemrect, 'h'); else ui_draw_tria_rect(&itemrect, 'v'); - - + + (void)ofsx; } /************************** panel alignment *************************/ diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 62043f240e4..9e7717260e6 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -484,6 +484,17 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) } } } + else if (ELEM(but->type, MENU, PULLDOWN)) { + if ((U.flag & USER_TOOLTIPS_PYTHON) == 0) { + if(but->menu_create_func && WM_menutype_contains((MenuType *)but->poin)) { + MenuType *mt= (MenuType *)but->poin; + BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), "Python: %s", mt->idname); + data->color[data->totline]= 0x888888; + data->totline++; + } + } + + } assert(data->totline < MAX_TOOLTIP_LINES); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 25dbb68a258..34315494e14 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -851,7 +851,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr) /* verify we have valid data */ if(!RNA_struct_is_a(ptr->type, &RNA_Modifier)) { - RNA_warning("uiTemplateModifier: expected modifier on object.\n"); + RNA_warning("uiTemplateModifier: Expected modifier on object.\n"); return NULL; } @@ -859,7 +859,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr) md= ptr->data; if(!ob || !(GS(ob->id.name) == ID_OB)) { - RNA_warning("uiTemplateModifier: expected modifier on object.\n"); + RNA_warning("uiTemplateModifier: Expected modifier on object.\n"); return NULL; } @@ -976,9 +976,6 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) block= uiLayoutGetBlock(box); /* Draw constraint header */ - - /* rounded header */ - // rb_col= (con->flag & CONSTRAINT_ACTIVE)?50:20; // UNUSED /* open/close */ uiBlockSetEmboss(block, UI_EMBOSSN); @@ -1083,7 +1080,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr) /* verify we have valid data */ if(!RNA_struct_is_a(ptr->type, &RNA_Constraint)) { - RNA_warning("uiTemplateConstraint: expected constraint on object.\n"); + RNA_warning("uiTemplateConstraint: Expected constraint on object.\n"); return NULL; } @@ -1091,7 +1088,7 @@ uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr) con= ptr->data; if(!ob || !(GS(ob->id.name) == ID_OB)) { - RNA_warning("uiTemplateConstraint: expected constraint on object.\n"); + RNA_warning("uiTemplateConstraint: Expected constraint on object.\n"); return NULL; } @@ -1137,7 +1134,7 @@ void uiTemplatePreview(uiLayout *layout, ID *id, int show_buttons, ID *parent, M PointerRNA texture_ptr; if(id && !ELEM4(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA)) { - RNA_warning("uiTemplatePreview: expected ID of type material, texture, lamp or world.\n"); + RNA_warning("uiTemplatePreview: Expected ID of type material, texture, lamp or world.\n"); return; } @@ -2171,14 +2168,14 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * if(prop) { type= RNA_property_type(prop); if(type != PROP_COLLECTION) { - RNA_warning("uiTemplateList: expected collection property.\n"); + RNA_warning("uiTemplateList: Expected collection property.\n"); return; } } activetype= RNA_property_type(activeprop); if(activetype != PROP_INT) { - RNA_warning("uiTemplateList: expected integer property.\n"); + RNA_warning("uiTemplateList: Expected integer property.\n"); return; } @@ -2200,7 +2197,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * /* create list items */ RNA_PROP_BEGIN(ptr, itemptr, prop) { /* create button */ - if(i == 9) + if(!(i % 9)) row= uiLayoutRow(col, 0); icon= list_item_icon_get(C, &itemptr, rnaicon, 1); @@ -2215,7 +2212,6 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * } else if(listtype == 'c') { /* compact layout */ - found= 0; row= uiLayoutRow(layout, 1); diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 7ca172c6945..f5f97c6a5f6 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -806,14 +806,14 @@ static int object_delete_exec(bContext *C, wmOperator *UNUSED(op)) { Main *bmain= CTX_data_main(C); Scene *scene= CTX_data_scene(C); - int islamp= 0; + /* int islamp= 0; */ /* UNUSED */ if(CTX_data_edit_object(C)) return OPERATOR_CANCELLED; CTX_DATA_BEGIN(C, Base*, base, selected_bases) { - if(base->object->type==OB_LAMP) islamp= 1; + /* if(base->object->type==OB_LAMP) islamp= 1; */ /* deselect object -- it could be used in other scenes */ base->object->flag &= ~SELECT; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 29a740affc5..395705dc029 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -2162,16 +2162,20 @@ static int game_property_copy_exec(bContext *C, wmOperator *op) } CTX_DATA_END; } } - else if (ELEM(type, COPY_PROPERTIES_REPLACE, COPY_PROPERTIES_MERGE)) { + + else { CTX_DATA_BEGIN(C, Object*, ob_iter, selected_editable_objects) { if (ob != ob_iter) { if (ob->data != ob_iter->data){ - if (type == 2) {/* merge */ + if (type == COPY_PROPERTIES_REPLACE) + copy_properties( &ob_iter->prop, &ob->prop ); + + /* merge - the default when calling with no argument */ + else { for(prop = ob->prop.first; prop; prop= prop->next ) { set_ob_property(ob_iter, prop); } - } else /* replace */ - copy_properties( &ob_iter->prop, &ob->prop ); + } } } } diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index fdd53d27b02..cfed2750e18 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -108,7 +108,7 @@ void OBJECT_OT_material_slot_add(wmOperatorType *ot) /* identifiers */ ot->name= "Add Material Slot"; ot->idname= "OBJECT_OT_material_slot_add"; - ot->description="Add a new material slot or duplicate the selected one"; + ot->description="Add a new material slot"; /* api callbacks */ ot->exec= material_slot_add_exec; diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 77fb129e278..204d5dfb1b1 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -554,7 +554,7 @@ static int view_selected_exec(bContext *C, wmOperator *UNUSED(op)) Scene *scene; Object *obedit; Image *ima; - float size, min[2], max[2], d[2]; + float size, min[2], max[2], d[2], aspx, aspy; int width, height; /* retrieve state */ @@ -565,6 +565,10 @@ static int view_selected_exec(bContext *C, wmOperator *UNUSED(op)) ima= ED_space_image(sima); ED_space_image_size(sima, &width, &height); + ED_image_aspect(ima, &aspx, &aspy); + + width= width*aspx; + height= height*aspy; /* get bounds */ if(!ED_uvedit_minmax(scene, ima, obedit, min, max)) diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 1bf2c3d89bd..50e657bbb61 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1869,10 +1869,17 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link) else { /* check cyclic */ if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) { - if(link->fromnode->flag & SELECT) - th_col1= TH_EDGE_SELECT; - if(link->tonode->flag & SELECT) - th_col2= TH_EDGE_SELECT; + /* special indicated link, on drop-node */ + if(link->flag & NODE_LINKFLAG_HILITE) { + th_col1= th_col2= TH_ACTIVE; + } + else { + /* regular link */ + if(link->fromnode->flag & SELECT) + th_col1= TH_EDGE_SELECT; + if(link->tonode->flag & SELECT) + th_col2= TH_EDGE_SELECT; + } do_shaded= 1; do_triple= 1; } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index cd1fa5c16a7..950b3c72fe7 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -781,14 +781,15 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, ""); } { /* always hide/reveal unused sockets */ - int shade; - - iconofs-=iconbutw; // XXX re-enable - /*if(node_has_hidden_sockets(node)) + /* int shade; + if(node_has_hidden_sockets(node)) shade= -40; - else*/ - shade= -90; + else + shade= -90; */ + + iconofs-=iconbutw; + uiDefIconBut(node->block, LABEL, B_REDR, ICON_PLUS, iconofs, rct->ymax-NODE_DY, iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, ""); } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index abc7b273ec9..4230a43d2ec 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -2492,6 +2492,151 @@ void NODE_OT_links_cut(wmOperatorType *ot) RNA_def_int(ot->srna, "cursor", BC_KNIFECURSOR, 0, INT_MAX, "Cursor", "", 0, INT_MAX); } +/* ********************* automatic node insert on dragging ******************* */ + +/* assumes sockets in list */ +static bNodeSocket *socket_best_match(ListBase *sockets, int type) +{ + bNodeSocket *sock; + + /* first, match type */ + for(sock= sockets->first; sock; sock= sock->next) + if(!(sock->flag & SOCK_HIDDEN)) + if(type == sock->type) + return sock; + + /* then just use first unhidden socket */ + for(sock= sockets->first; sock; sock= sock->next) + if(!(sock->flag & SOCK_HIDDEN)) + return sock; + + /* OK, let's unhide proper one */ + for(sock= sockets->first; sock; sock= sock->next) { + if(type == sock->type) { + sock->flag &= ~SOCK_HIDDEN; + return sock; + } + } + + /* just the first */ + sock= sockets->first; + sock->flag &= ~SOCK_HIDDEN; + + return sockets->first; +} + +/* prevent duplicate testing code below */ +static SpaceNode *ed_node_link_conditions(ScrArea *sa, bNode **select) +{ + SpaceNode *snode= sa?sa->spacedata.first:NULL; + bNode *node; + bNodeLink *link; + + /* no unlucky accidents */ + if(sa==NULL || sa->spacetype!=SPACE_NODE) return NULL; + + *select= NULL; + + for(node= snode->edittree->nodes.first; node; node= node->next) { + if(node->flag & SELECT) { + if(*select) + break; + else + *select= node; + } + } + /* only one selected */ + if(node || *select==NULL) return NULL; + + /* correct node */ + if((*select)->inputs.first==NULL || (*select)->outputs.first==NULL) return NULL; + + /* test node for links */ + for(link= snode->edittree->links.first; link; link=link->next) { + if(link->tonode == *select || link->fromnode == *select) + return NULL; + } + + return snode; +} + +/* assumes link with NODE_LINKFLAG_HILITE set */ +void ED_node_link_insert(ScrArea *sa) +{ + bNode *node, *select; + SpaceNode *snode= ed_node_link_conditions(sa, &select); + bNodeLink *link; + bNodeSocket *sockto; + + if(snode==NULL) return; + + /* get the link */ + for(link= snode->edittree->links.first; link; link=link->next) + if(link->flag & NODE_LINKFLAG_HILITE) + break; + + if(link) { + node= link->tonode; + sockto= link->tosock; + + link->tonode= select; + link->tosock= socket_best_match(&select->inputs, link->fromsock->type); + link->flag &= ~NODE_LINKFLAG_HILITE; + + nodeAddLink(snode->edittree, select, socket_best_match(&select->outputs, sockto->type), node, sockto); + ntreeSolveOrder(snode->edittree); /* needed for pointers */ + snode_tag_changed(snode, select); + ED_node_changed_update(snode->id, select); + } +} + + +/* test == 0, clear all intersect flags */ +void ED_node_link_intersect_test(ScrArea *sa, int test) +{ + bNode *select; + SpaceNode *snode= ed_node_link_conditions(sa, &select); + bNodeLink *link, *selink=NULL; + float mcoords[6][2]; + + if(snode==NULL) return; + + /* clear flags */ + for(link= snode->edittree->links.first; link; link=link->next) + link->flag &= ~NODE_LINKFLAG_HILITE; + + if(test==0) return; + + /* okay, there's 1 node, without links, now intersect */ + mcoords[0][0]= select->totr.xmin; + mcoords[0][1]= select->totr.ymin; + mcoords[1][0]= select->totr.xmax; + mcoords[1][1]= select->totr.ymin; + mcoords[2][0]= select->totr.xmax; + mcoords[2][1]= select->totr.ymax; + mcoords[3][0]= select->totr.xmin; + mcoords[3][1]= select->totr.ymax; + mcoords[4][0]= select->totr.xmin; + mcoords[4][1]= select->totr.ymin; + mcoords[5][0]= select->totr.xmax; + mcoords[5][1]= select->totr.ymax; + + /* we only tag a single link for intersect now */ + /* idea; use header dist when more? */ + for(link= snode->edittree->links.first; link; link=link->next) { + + if(cut_links_intersect(link, mcoords, 5)) { /* intersect code wants edges */ + if(selink) + break; + selink= link; + } + } + + if(link==NULL && selink) + selink->flag |= NODE_LINKFLAG_HILITE; +} + + /* ******************************** */ // XXX some code needing updating to operators... @@ -2914,7 +3059,8 @@ void NODE_OT_delete(wmOperatorType *ot) /* note: in cmp_util.c is similar code, for node_compo_pass_on() */ /* used for disabling node (similar code in node_draw.c for disable line) */ -static void node_delete_reconnect(bNodeTree* tree, bNode* node) { +static void node_delete_reconnect(bNodeTree* tree, bNode* node) +{ bNodeLink *link, *next; bNodeSocket *valsocket= NULL, *colsocket= NULL, *vecsocket= NULL; bNodeSocket *deliveringvalsocket= NULL, *deliveringcolsocket= NULL, *deliveringvecsocket= NULL; @@ -3142,3 +3288,5 @@ void NODE_OT_add_file(wmOperatorType *ot) RNA_def_string(ot->srna, "name", "Image", 24, "Name", "Datablock name to assign."); } + + diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index f6e3dc3dd0a..36e334990cb 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -303,7 +303,7 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad Scene *scene= CTX_data_scene(C); /* only for sound */ Editing *ed= seq_give_editing(scene, TRUE); SeqLoadInfo seq_load; - Sequence *seq; + /* Sequence *seq; */ /* UNUSED */ int tot_files; seq_load_operator_info(&seq_load, op); @@ -324,13 +324,13 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad RNA_string_get(&itemptr, "name", file_only); BLI_join_dirfile(seq_load.path, sizeof(seq_load.path), dir_only, file_only); - seq= seq_load_func(C, ed->seqbasep, &seq_load); + /* seq= */ seq_load_func(C, ed->seqbasep, &seq_load); } RNA_END; } else { /* single file */ - seq= seq_load_func(C, ed->seqbasep, &seq_load); + /* seq= */ seq_load_func(C, ed->seqbasep, &seq_load); } if (seq_load.tot_success==0) { diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 2bd6bd624df..13eb24ed1f2 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -36,6 +36,7 @@ #include #include /* ispunct */ #include +#include #include "MEM_guardedalloc.h" @@ -449,15 +450,14 @@ static void txt_write_file(Text *text, ReportList *reports) FILE *fp; TextLine *tmp; struct stat st; - int res; - char file[FILE_MAXDIR+FILE_MAXFILE]; + char filepath[FILE_MAXDIR+FILE_MAXFILE]; - BLI_strncpy(file, text->name, FILE_MAXDIR+FILE_MAXFILE); - BLI_path_abs(file, G.main->name); + BLI_strncpy(filepath, text->name, FILE_MAXDIR+FILE_MAXFILE); + BLI_path_abs(filepath, G.main->name); - fp= fopen(file, "w"); + fp= fopen(filepath, "w"); if(fp==NULL) { - BKE_report(reports, RPT_ERROR, "Unable to save file."); + BKE_reportf(reports, RPT_ERROR, "Unable to save \"%s\": %s.", filepath, errno ? strerror(errno) : "Unknown error writing file"); return; } @@ -471,8 +471,13 @@ static void txt_write_file(Text *text, ReportList *reports) fclose (fp); - res= stat(file, &st); - text->mtime= st.st_mtime; + if(stat(filepath, &st) == 0) { + text->mtime= st.st_mtime; + } + else { + text->mtime= 0; + BKE_reportf(reports, RPT_WARNING, "Unable to stat \"%s\": %s.", filepath, errno ? strerror(errno) : "Unknown error starrng file"); + } if(text->flags & TXT_ISDIRTY) text->flags ^= TXT_ISDIRTY; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index b343718d39b..94224698063 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -129,7 +129,6 @@ void ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d) } else { ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist); - root_parent= v3d->camera; DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); WM_main_add_notifier(NC_OBJECT|ND_TRANSFORM, v3d->camera); } diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 75c8d5cae73..ae80a554e08 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -505,17 +505,6 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) uiItemR(row, &v3dptr, "pivot_point", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); uiItemR(row, &v3dptr, "use_pivot_point_align", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); - /* NDOF */ - /* Not implemented yet - if (G.ndofdevice ==0 ) { - uiDefIconTextButC(block, ICONTEXTROW,B_NDOF, ICON_NDOF_TURN, ndof_pup(), 0,0,UI_UNIT_X+10,UI_UNIT_Y, &(v3d->ndofmode), 0, 3.0, 0, 0, "Ndof mode"); - - uiDefIconButC(block, TOG, B_NDOF, ICON_NDOF_DOM, - 0,0,UI_UNIT_X,UI_UNIT_Y, - &v3d->ndoffilter, 0, 1, 0, 0, "dominant axis"); - } - */ - /* Transform widget / manipulators */ row= uiLayoutRow(layout, 1); uiItemR(row, &v3dptr, "show_manipulator", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 81aade5ca64..7f8d5976e86 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -969,7 +969,7 @@ int transformEvent(TransInfo *t, wmEvent *event) break; case OKEY: if (t->flag & T_PROP_EDIT && event->shift) { - t->prop_mode = (t->prop_mode + 1) % 6; + t->prop_mode = (t->prop_mode + 1) % PROP_MODE_MAX; calculatePropRatio(t); t->redraw |= TREDRAW_HARD; } diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index d8e750acb88..d8e42488787 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -96,7 +96,7 @@ typedef struct TransSnap { short modeSelect; short align; char project; - char project_self; + char snap_self; short peel; short status; float snapPoint[3]; /* snapping from this point */ diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 16bfc75c979..0a5e290643a 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -87,6 +87,7 @@ #include "ED_object.h" #include "ED_markers.h" #include "ED_mesh.h" +#include "ED_node.h" #include "ED_types.h" #include "ED_uvedit.h" #include "ED_curve.h" /* for ED_curve_editnurbs */ @@ -2182,6 +2183,12 @@ void flushTransNodes(TransInfo *t) td->loc2d[0]= td->loc[0]; td->loc2d[1]= td->loc[1]; } + + /* handle intersection with noodles */ + if(t->total==1) { + ED_node_link_intersect_test(t->sa, 1); + } + } /* *** SEQUENCE EDITOR *** */ @@ -4756,7 +4763,12 @@ void special_aftertrans_update(bContext *C, TransInfo *t) } else if (t->spacetype == SPACE_NODE) { - /* pass */ + if(cancelled == 0) + ED_node_link_insert(t->sa); + + /* clear link line */ + ED_node_link_intersect_test(t->sa, 0); + } else if (t->spacetype == SPACE_ACTION) { SpaceAction *saction= (SpaceAction *)t->sa->spacedata.first; diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 20a26d8c58d..6d0a978700f 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1070,7 +1070,7 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) } } // Need stuff to take it from edit mesh or whatnot here - else + else if (t->spacetype == SPACE_VIEW3D) { if (t->obedit && t->obedit->type == OB_MESH && (((Mesh *)t->obedit->data)->editflag & ME_EDIT_MIRROR_X)) { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 0b0b22fb689..a779982099e 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -960,6 +960,8 @@ void transform_keymap_for_space(wmKeyConfig *keyconf, wmKeyMap *keymap, int spac WM_keymap_add_item(keymap, OP_RESIZE, SKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, OP_SHEAR, SKEY, KM_PRESS, KM_ALT|KM_CTRL|KM_SHIFT, 0); + WM_keymap_add_item(keymap, "TRANSFORM_OT_mirror", MKEY, KM_PRESS, KM_CTRL, 0); km = WM_keymap_add_item(keymap, "WM_OT_context_toggle", TABKEY, KM_PRESS, KM_SHIFT, 0); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index d9d9b0f9102..933d90ebbf2 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -392,7 +392,7 @@ static void initSnappingMode(TransInfo *t) } else { - t->tsnap.modeSelect = t->tsnap.project_self ? SNAP_ALL : SNAP_NOT_OBEDIT; + t->tsnap.modeSelect = t->tsnap.snap_self ? SNAP_ALL : SNAP_NOT_OBEDIT; } } /* Particles edit mode*/ @@ -458,9 +458,9 @@ void initSnapping(TransInfo *t, wmOperator *op) t->tsnap.project = RNA_boolean_get(op->ptr, "use_snap_project"); } - if (RNA_struct_find_property(op->ptr, "use_snap_project_self")) + if (RNA_struct_find_property(op->ptr, "use_snap_self")) { - t->tsnap.project = RNA_boolean_get(op->ptr, "use_snap_project_self"); + t->tsnap.snap_self = RNA_boolean_get(op->ptr, "use_snap_self"); } } } @@ -473,7 +473,7 @@ void initSnapping(TransInfo *t, wmOperator *op) t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) == SCE_SNAP_ROTATE); t->tsnap.project = ((t->settings->snap_flag & SCE_SNAP_PROJECT) == SCE_SNAP_PROJECT); - t->tsnap.project_self = !((t->settings->snap_flag & SCE_SNAP_PROJECT_NO_SELF) == SCE_SNAP_PROJECT_NO_SELF); + t->tsnap.snap_self = !((t->settings->snap_flag & SCE_SNAP_NO_SELF) == SCE_SNAP_NO_SELF); t->tsnap.peel = ((t->settings->snap_flag & SCE_SNAP_PROJECT) == SCE_SNAP_PROJECT); } @@ -1944,6 +1944,11 @@ static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], Gea int i; float asp[3] = {1.0f, 1.0f, 1.0f}; // TODO: Remove hard coded limit here (3) + if(max_index > 3) { + printf("applyGrid: invalid index %d, clamping\n", max_index); + max_index= 3; + } + // Early bailing out if no need to snap if (fac[action] == 0.0f) return; diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c index 8a6ec7f75db..a2381a208ef 100644 --- a/source/blender/editors/util/undo.c +++ b/source/blender/editors/util/undo.c @@ -358,19 +358,25 @@ int ED_undo_operator_repeat(bContext *C, struct wmOperator *op) ret= 1; } } + else { + if (G.f & G_DEBUG) { + printf("redo_cb: WM_operator_repeat_check returned false %s\n", op->type->name); + } + } /* set region back */ CTX_wm_region_set(C, ar); } else { if (G.f & G_DEBUG) { - printf("redo_cb: WM_operator_repeat_check returned false %s\n", op->type->name); + printf("redo_cb: ED_undo_operator_repeat called with NULL 'op'\n"); } } return ret; } + void ED_undo_operator_repeat_cb(bContext *C, void *arg_op, void *UNUSED(arg_unused)) { ED_undo_operator_repeat(C, (wmOperator *)arg_op); diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index c09f8cff02d..70659994c55 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -1057,6 +1057,134 @@ static void weld_align_uv(bContext *C, int tool) } } + if(tool == 's' || tool == 't' || tool == 'u') { + /* pass 1&2 variables */ + int i, j; + int starttmpl= -1, connectedtostarttmpl= -1, startcorner; + int endtmpl= -1, connectedtoendtmpl= -1, endcorner; + MTFace *startface, *endface; + int itmpl, jtmpl; + EditVert *eve; + int pass; /* first 2 passes find endpoints, 3rd pass moves middle points, 4th pass is fail-on-face-selected */ + EditFace *startefa, *endefa; + + /* pass 3 variables */ + float startx, starty, firstm, firstb, midx, midy; + float endx, endy, secondm, secondb, midmovedx, midmovedy; + float IsVertical_check= -1; + float IsHorizontal_check= -1; + + for(i= 0, eve= em->verts.first; eve; eve= eve->next, i++) /* give each point a unique name */ + eve->tmp.l= i; + for(pass= 1; pass <= 3; pass++) { /* do this for each endpoint */ + if(pass == 3){ /* calculate */ + startx= startface->uv[startcorner][0]; + starty= startface->uv[startcorner][1]; + endx= endface->uv[endcorner][0]; + endy= endface->uv[endcorner][1]; + firstm= (endy-starty)/(endx-startx); + firstb= starty-(firstm*startx); + secondm= -1.0f/firstm; + if(startx == endx) IsVertical_check= startx; + if(starty == endy) IsHorizontal_check= starty; + } + for(efa= em->faces.first; efa; efa= efa->next) { /* for each face */ + tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); /* get face */ + if(uvedit_face_visible(scene, ima, efa, tf)) { /* if you can see it */ + if(uvedit_face_selected(scene, efa, tf)) { /* if the face is selected, get out now! */ + pass= 4; + break; + } + for(i= 0; (i < 3 || (i == 3 && efa->v4)); i++) { /* for each point of the face */ + itmpl= (*(&efa->v1 + i))->tmp.l; /* get unique name for points */ + if(pass == 3) { /* move */ + if(uvedit_uv_selected(scene, efa, tf, i)) { + if(!(itmpl == starttmpl || itmpl == endtmpl)) { + if(IsVertical_check != -1) tf->uv[i][0]= IsVertical_check; + if(IsHorizontal_check != -1) tf->uv[i][1]= IsHorizontal_check; + if((IsVertical_check == -1) && (IsHorizontal_check == -1)) { + midx= tf->uv[i][0]; + midy= tf->uv[i][1]; + if(tool == 's') { + secondb= midy-(secondm*midx); + midmovedx= (secondb-firstb)/(firstm-secondm); + midmovedy= (secondm*midmovedx)+secondb; + tf->uv[i][0]= midmovedx; + tf->uv[i][1]= midmovedy; + } + else if(tool == 't') { + tf->uv[i][0]= (midy-firstb)/firstm; /* midmovedx */ + } + else if(tool == 'u') { + tf->uv[i][1]= (firstm*midx)+firstb; /* midmovedy */ + } + } + } + } + } + else { + for(j= 0; (j < 3 || (j == 3 && efa->v4)); j++) { /* also for each point on the face */ + jtmpl= (*(&efa->v1 + j))->tmp.l; + if(i != j && (!efa->v4 || ABS(i-j) != 2)) { /* if the points are connected */ + /* quad (0,1,2,3) 0,1 0,3 1,0 1,2 2,1 2,3 3,0 3,2 + * triangle (0,1,2) 0,1 0,2 1,0 1,2 2,0 2,1 */ + if(uvedit_uv_selected(scene, efa, tf, i) && uvedit_uv_selected(scene, efa, tf, j)) { + /* if the edge is selected */ + if(pass == 1) { /* if finding first endpoint */ + if(starttmpl == -1) { /* if the first endpoint isn't found yet */ + starttmpl= itmpl; /* set unique name for endpoint */ + connectedtostarttmpl= jtmpl; + /* get point that endpoint is connected to */ + startface= tf; /* get face it's on */ + startcorner= i; /* what corner of the face? */ + startefa= efa; + efa= em->faces.first; + tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + i= -1; + break; + } + if(starttmpl == itmpl && jtmpl != connectedtostarttmpl) { + starttmpl= -1; /* not an endpoint */ + efa= startefa; + tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + i= startcorner; + break; + } + } + else if(pass == 2) { /* if finding second endpoint */ + if(endtmpl == -1 && itmpl != starttmpl) { + endtmpl= itmpl; + connectedtoendtmpl= jtmpl; + endface= tf; + endcorner= i; + endefa= efa; + efa= em->faces.first; + tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + i= -1; + break; + } + if(endtmpl == itmpl && jtmpl != connectedtoendtmpl) { + endtmpl= -1; + efa= endefa; + tf= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); + i= endcorner; + break; + } + } + } + } + } + } + } + } + } + if(pass == 2 && (starttmpl == -1 || endtmpl == -1)) { + /* if endpoints aren't found */ + pass=4; + } + } + } + uvedit_live_unwrap_update(sima, scene, obedit); DAG_id_tag_update(obedit->data, 0); WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data); @@ -1074,6 +1202,9 @@ static int align_exec(bContext *C, wmOperator *op) static void UV_OT_align(wmOperatorType *ot) { static EnumPropertyItem axis_items[] = { + {'s', "ALIGN_S", 0, "Straighten", "Align UVs along the line defined by the endpoints"}, + {'t', "ALIGN_T", 0, "Straighten X", "Align UVs along the line defined by the endpoints along the X axis"}, + {'u', "ALIGN_U", 0, "Straighten Y", "Align UVs along the line defined by the endpoints along the Y axis"}, {'a', "ALIGN_AUTO", 0, "Align Auto", "Automatically choose the axis on which there is most alignment already"}, {'x', "ALIGN_X", 0, "Align X", "Align UVs on X axis"}, {'y', "ALIGN_Y", 0, "Align Y", "Align UVs on Y axis"}, diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 3804aad6848..806c70d841f 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -671,7 +671,7 @@ static void shade_one_light(GPUShadeInput *shi, GPUShadeResult *shr, GPULamp *la i = is; GPU_link(mat, "shade_visifac", i, visifac, shi->refl, &i); - vn = shi->vn; + /*if(ma->mode & MA_TANGENT_VN) GPU_link(mat, "shade_tangent_v_spec", GPU_attribute(CD_TANGENT, ""), &vn);*/ diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index ff01e3a8a1e..36123592c54 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -252,7 +252,7 @@ void IMB_filter(struct ImBuf *ibuf); void IMB_filterN(struct ImBuf *out, struct ImBuf *in); void IMB_mask_filter_extend(char *mask, int width, int height); void IMB_mask_clear(struct ImBuf *ibuf, char *mask, int val); -void IMB_filter_extend(struct ImBuf *ibuf, char *mask); +void IMB_filter_extend(struct ImBuf *ibuf, char *mask, int filter); void IMB_makemipmap(struct ImBuf *ibuf, int use_filter); void IMB_remakemipmap(struct ImBuf *ibuf, int use_filter); struct ImBuf *IMB_getmipmap(struct ImBuf *ibuf, int level); diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index d12360e5a7e..1644e653df4 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -21,7 +21,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Morten Mikkelsen. * * ***** END GPL LICENSE BLOCK ***** * filter.c @@ -326,121 +326,132 @@ void IMB_mask_clear(ImBuf *ibuf, char *mask, int val) } } -#define EXTEND_PIXEL(color, w) if((color)[3]) {r+= w*(color)[0]; g+= w*(color)[1]; b+= w*(color)[2]; a+= w*(color)[3]; tot+=w;} +static int filter_make_index(const int x, const int y, const int w, const int h) +{ + if(x<0 || x>=w || y<0 || y>=h) return -1; /* return bad index */ + else return y*w+x; +} + +static int check_pixel_assigned(const void *buffer, const char *mask, const int index, const int depth, const int is_float) +{ + int res = 0; + + if(index>=0) { + const int alpha_index = depth*index+(depth-1); + + if(mask!=NULL) { + res = mask[index]!=0 ? 1 : 0; + } + else if( (is_float && ((const float *) buffer)[alpha_index]!=0.0f) || + (!is_float && ((const unsigned char *) buffer)[alpha_index]!=0) ) { + res=1; + } + } + + return res; +} /* if alpha is zero, it checks surrounding pixels and averages color. sets new alphas to 1.0 * * When a mask is given, only effect pixels with a mask value of 1, defined as BAKE_MASK_MARGIN in rendercore.c * */ -void IMB_filter_extend(struct ImBuf *ibuf, char *mask) +void IMB_filter_extend(struct ImBuf *ibuf, char *mask, int filter) { - register char *row1, *row2, *row3; - register char *cp; - int rowlen, x, y; - - rowlen= ibuf->x; - - - if (ibuf->rect_float) { - float *temprect; - float *row1f, *row2f, *row3f; - float *fp; - temprect= MEM_dupallocN(ibuf->rect_float); - - for(y=1; y<=ibuf->y; y++) { - /* setup rows */ - row1f= (float *)(temprect + (y-2)*rowlen*4); - row2f= row1f + 4*rowlen; - row3f= row2f + 4*rowlen; - if(y==1) - row1f= row2f; - else if(y==ibuf->y) - row3f= row2f; - - fp= (float *)(ibuf->rect_float + (y-1)*rowlen*4); - - for(x=0; xx; + const int height= ibuf->y; + const int depth= 4; /* always 4 channels */ + const int chsize= ibuf->rect_float ? sizeof(float) : sizeof(unsigned char); + const int bsize= width*height*depth*chsize; + const int is_float= ibuf->rect_float!=NULL; + void *dstbuf= (void *) MEM_dupallocN(ibuf->rect_float ? (void *) ibuf->rect_float : (void *) ibuf->rect); + char *dstmask= mask==NULL ? NULL : (char *) MEM_dupallocN(mask); + void *srcbuf= ibuf->rect_float ? (void *) ibuf->rect_float : (void *) ibuf->rect; + char *srcmask= mask; + int cannot_early_out= 1, r, n, k, i, j, c; + float weight[25]; + + /* build a weights buffer */ + n= 2; + k= 0; + for(i = -n; i <= n; i++) + for(j = -n; j <= n; j++) + weight[k++] = sqrt((float) i * i + j * j); + + /* run passes */ + for(r = 0; cannot_early_out == 1 && r < filter; r++) { + int x, y; + cannot_early_out = 0; + + for(y= 0; y 255 ? 255 : (acc[c] < 0 ? 0 : ((unsigned char) (acc[c]+0.5f))); + } + } + + if(dstmask!=NULL) dstmask[index]=FILTER_MASK_MARGIN; /* assigned */ + cannot_early_out = 1; + } } } - fp+=4; - - if(x!=0) { - row1f+=4; row2f+=4; row3f+=4; - } } } - MEM_freeN(temprect); - } - else if(ibuf->rect) { - int *temprect; - - /* make a copy, to prevent flooding */ - temprect= MEM_dupallocN(ibuf->rect); - - for(y=1; y<=ibuf->y; y++) { - /* setup rows */ - row1= (char *)(temprect + (y-2)*rowlen); - row2= row1 + 4*rowlen; - row3= row2 + 4*rowlen; - if(y==1) - row1= row2; - else if(y==ibuf->y) - row3= row2; - - cp= (char *)(ibuf->rect + (y-1)*rowlen); - - for(x=0; xflag */ +#define NODE_LINKFLAG_HILITE 1 + /* the basis for a Node tree, all links and nodes reside internal here */ /* only re-usable node trees are in the library though, materials and textures allocate own tree struct */ typedef struct bNodeTree { diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 3c14dacf973..2211f93a8ae 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1074,7 +1074,7 @@ typedef struct Scene { #define SCE_SNAP_ROTATE 2 #define SCE_SNAP_PEEL_OBJECT 4 #define SCE_SNAP_PROJECT 8 -#define SCE_SNAP_PROJECT_NO_SELF 16 +#define SCE_SNAP_NO_SELF 16 /* toolsettings->snap_target */ #define SCE_SNAP_TARGET_CLOSEST 0 #define SCE_SNAP_TARGET_CENTER 1 @@ -1107,7 +1107,8 @@ typedef struct Scene { #define PROP_SHARP 3 #define PROP_LIN 4 #define PROP_CONST 5 -#define PROP_RANDOM 6 +#define PROP_RANDOM 6 +#define PROP_MODE_MAX 7 /* toolsettings->proportional */ #define PROP_EDIT_OFF 0 diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index c9865bf3df4..cb593e7deab 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -171,6 +171,10 @@ if(WITH_IMAGE_HDR) add_definitions(-DWITH_HDR) endif() +if(WITH_IMAGE_FRAMESERVER) + add_definitions(-DWITH_FRAMESERVER) +endif() + if(WITH_AUDASPACE) add_definitions(-DWITH_AUDASPACE) endif() diff --git a/source/blender/makesrna/intern/SConscript b/source/blender/makesrna/intern/SConscript index 421c3a60691..5e43ed9b2fb 100644 --- a/source/blender/makesrna/intern/SConscript +++ b/source/blender/makesrna/intern/SConscript @@ -54,6 +54,8 @@ if env['WITH_BF_CINEON']: if env['WITH_BF_HDR']: defs.append('WITH_HDR') +defs.append('WITH_FRAMESERVER') # TODO, make optional + if env['WITH_BF_FFMPEG']: defs.append('WITH_FFMPEG') incs += ' ' + env['BF_FFMPEG_INC'] diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index d9fbdd7caf2..dcf2400b9ba 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -4407,15 +4407,15 @@ ParameterList *RNA_parameter_list_create(ParameterList *parms, PointerRNA *UNUSE if(!(parm->flag & PROP_REQUIRED) && !(parm->flag & PROP_DYNAMIC)) { switch(parm->type) { case PROP_BOOLEAN: - if(parm->arraydimension) memcpy(data, &((BooleanPropertyRNA*)parm)->defaultarray, size); + if(parm->arraydimension) memcpy(data, ((BooleanPropertyRNA*)parm)->defaultarray, size); else memcpy(data, &((BooleanPropertyRNA*)parm)->defaultvalue, size); break; case PROP_INT: - if(parm->arraydimension) memcpy(data, &((IntPropertyRNA*)parm)->defaultarray, size); + if(parm->arraydimension) memcpy(data, ((IntPropertyRNA*)parm)->defaultarray, size); else memcpy(data, &((IntPropertyRNA*)parm)->defaultvalue, size); break; case PROP_FLOAT: - if(parm->arraydimension) memcpy(data, &((FloatPropertyRNA*)parm)->defaultarray, size); + if(parm->arraydimension) memcpy(data, ((FloatPropertyRNA*)parm)->defaultarray, size); else memcpy(data, &((FloatPropertyRNA*)parm)->defaultvalue, size); break; case PROP_ENUM: diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 9018fd8c71a..21fa28af01a 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -544,7 +544,7 @@ void RNA_api_object(StructRNA *srna) /* location of point for test and max distance */ parm= RNA_def_float_vector(func, "point", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4); RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_float(func, "max_dist", sqrt(FLT_MAX), 0.0, FLT_MAX, "", "", 0.0, FLT_MAX); + RNA_def_float(func, "max_dist", sqrt(FLT_MAX), 0.0, FLT_MAX, "", "", 0.0, FLT_MAX); /* return location and normal */ parm= RNA_def_float_vector(func, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "The location on the object closest to the point", -1e4, 1e4); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 662ce04552e..f4028e45e96 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -135,7 +135,9 @@ EnumPropertyItem image_type_items[] = { #endif {R_AVIJPEG, "AVI_JPEG", ICON_FILE_MOVIE, "AVI JPEG", "Output video in AVI JPEG format"}, {R_AVIRAW, "AVI_RAW", ICON_FILE_MOVIE, "AVI Raw", "Output video in AVI Raw format"}, +#ifdef WITH_FRAMESERVER {R_FRAMESERVER, "FRAMESERVER", ICON_FILE_SCRIPT, "Frame Server", "Output image to a frameserver"}, +#endif #ifdef WITH_FFMPEG {R_H264, "H264", ICON_FILE_MOVIE, "H.264", "Output video in H.264 format"}, {R_FFMPEG, "FFMPEG", ICON_FILE_MOVIE, "MPEG", "Output video in MPEG format"}, @@ -1176,9 +1178,9 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_icon(prop, ICON_RETOPO, 0); RNA_def_property_update(prop, NC_SCENE|ND_TOOLSETTINGS, NULL); /* header redraw */ - prop= RNA_def_property(srna, "use_snap_project_self", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "snap_flag", SCE_SNAP_PROJECT_NO_SELF); - RNA_def_property_ui_text(prop, "Project to Self", "Project into its self (editmode)"); + prop= RNA_def_property(srna, "use_snap_self", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "snap_flag", SCE_SNAP_NO_SELF); + RNA_def_property_ui_text(prop, "Project to Self", "Snap onto its self (editmode)"); RNA_def_property_ui_icon(prop, ICON_ORTHO, 0); RNA_def_property_update(prop, NC_SCENE|ND_TOOLSETTINGS, NULL); /* header redraw */ @@ -2813,7 +2815,7 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop= RNA_def_property(srna, "bake_margin", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "bake_filter"); - RNA_def_property_range(prop, 0, 32); + RNA_def_property_range(prop, 0, 64); RNA_def_property_ui_text(prop, "Margin", "Amount of pixels to extend the baked result with, as post process filter"); prop= RNA_def_property(srna, "bake_distance", PROP_FLOAT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 31e1d73c8de..a046be59ab5 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -1025,7 +1025,7 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * rna_Operator_unregister(bmain, ot->ext.srna); } - /* create a new menu type */ + /* create a new operator type */ dummyot.ext.srna= RNA_def_struct(&BLENDER_RNA, dummyot.idname, "Operator"); RNA_def_struct_flag(dummyot.ext.srna, STRUCT_NO_IDPROPERTIES); /* operator properties are registered separately */ dummyot.ext.data= data; diff --git a/source/blender/python/mathutils/mathutils.h b/source/blender/python/mathutils/mathutils.h index 7454cfe78b3..b798b5e7003 100644 --- a/source/blender/python/mathutils/mathutils.h +++ b/source/blender/python/mathutils/mathutils.h @@ -108,4 +108,6 @@ int _BaseMathObject_WriteIndexCallback(BaseMathObject *self, int index); int mathutils_array_parse(float *array, int array_min, int array_max, PyObject *value, const char *error_prefix); int mathutils_any_to_rotmat(float rmat[3][3], PyObject *value, const char *error_prefix); +int column_vector_multiplication(float rvec[4], VectorObject *vec, MatrixObject *mat); + #endif /* MATHUTILS_H */ diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index 76a0994c3aa..3953171f263 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -1612,8 +1612,20 @@ static PyObject *Matrix_mul(PyObject *m1, PyObject *m2) } } else if(mat1) { + /*VEC * MATRIX */ + if(VectorObject_Check(m2)) { + VectorObject *vec2= (VectorObject *)m2; + float tvec[4]; + if(BaseMath_ReadCallback(vec2) == -1) + return NULL; + if(column_vector_multiplication(tvec, vec2, mat1) == -1) { + return NULL; + } + + return newVectorObject(tvec, vec2->size, Py_NEW, Py_TYPE(m2)); + } /*FLOAT/INT * MATRIX */ - if (((scalar= PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred())==0) { + else if (((scalar= PyFloat_AsDouble(m2)) == -1.0f && PyErr_Occurred())==0) { return matrix_mul_float(mat1, scalar); } } diff --git a/source/blender/python/mathutils/mathutils_Quaternion.c b/source/blender/python/mathutils/mathutils_Quaternion.c index 3b05b9a250b..2be258a1ef0 100644 --- a/source/blender/python/mathutils/mathutils_Quaternion.c +++ b/source/blender/python/mathutils/mathutils_Quaternion.c @@ -753,8 +753,30 @@ static PyObject *Quaternion_mul(PyObject *q1, PyObject *q2) return quat_mul_float(quat2, scalar); } } - else if (quat1) { /* QUAT*FLOAT */ - if((((scalar= PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred())==0)) { + else if (quat1) { + /* QUAT * VEC */ + if (VectorObject_Check(q2)) { + VectorObject *vec2 = (VectorObject *)q2; + float tvec[3]; + + if(vec2->size != 3) { + PyErr_SetString(PyExc_ValueError, + "Vector multiplication: " + "only 3D vector rotations (with quats) " + "currently supported"); + return NULL; + } + if(BaseMath_ReadCallback(vec2) == -1) { + return NULL; + } + + copy_v3_v3(tvec, vec2->vec); + mul_qt_v3(quat1->quat, tvec); + + return newVectorObject(tvec, 3, Py_NEW, Py_TYPE(vec2)); + } + /* QUAT * FLOAT */ + else if((((scalar= PyFloat_AsDouble(q2)) == -1.0f && PyErr_Occurred())==0)) { return quat_mul_float(quat1, scalar); } } diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index e2c958adaa5..a954c07c98d 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -37,6 +37,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +extern void PyC_LineSpit(void); + #define MAX_DIMENSIONS 4 /* Swizzle axes get packed into a single value that is used as a closure. Each @@ -1081,7 +1083,7 @@ static PyObject *Vector_isub(PyObject *v1, PyObject *v2) * note: vector/matrix multiplication IS NOT COMMUTATIVE!!!! * note: assume read callbacks have been done first. */ -static int column_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject* vec, MatrixObject * mat) +int column_vector_multiplication(float rvec[MAX_DIMENSIONS], VectorObject* vec, MatrixObject * mat) { float vec_cpy[MAX_DIMENSIONS]; double dot = 0.0f; @@ -1159,8 +1161,29 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2) } else if (vec1) { if (MatrixObject_Check(v2)) { + extern void PyC_LineSpit(void); + /* VEC * MATRIX */ + /* this is deprecated!, use the reverse instead */ float tvec[MAX_DIMENSIONS]; + + +/* ------ to be removed ------*/ +#ifndef MATH_STANDALONE +#ifdef WITH_ASSERT_ABORT + PyErr_SetString(PyExc_ValueError, + "(Vector * Matrix) is now removed, reverse the " + "order (promoted to an Error for Debug builds)"); + return NULL; +#else + printf("Warning: (Vector * Matrix) is now deprecated, " + "reverse the multiplication order in the script.\n"); + PyC_LineSpit(); +#endif +#endif /* ifndef MATH_STANDALONE */ +/* ------ to be removed ------*/ + + if(BaseMath_ReadCallback((MatrixObject *)v2) == -1) return NULL; if(column_vector_multiplication(tvec, vec1, (MatrixObject*)v2) == -1) { @@ -1183,6 +1206,24 @@ static PyObject *Vector_mul(PyObject *v1, PyObject *v2) if(BaseMath_ReadCallback(quat2) == -1) { return NULL; } + + +/* ------ to be removed ------*/ +#ifndef MATH_STANDALONE +#ifdef WITH_ASSERT_ABORT + PyErr_SetString(PyExc_ValueError, + "(Vector * Quat) is now removed, reverse the " + "order (promoted to an Error for Debug builds)"); + return NULL; +#else + printf("Warning: (Vector * Quat) is now deprecated, " + "reverse the multiplication order in the script.\n"); + PyC_LineSpit(); +#endif +#endif /* ifndef MATH_STANDALONE */ +/* ------ to be removed ------*/ + + copy_v3_v3(tvec, vec1->vec); mul_qt_v3(quat2->quat, tvec); return newVectorObject(tvec, 3, Py_NEW, Py_TYPE(vec1)); @@ -1226,6 +1267,24 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) if(column_vector_multiplication(rvec, vec, (MatrixObject*)v2) == -1) return NULL; + +/* ------ to be removed ------*/ +#ifndef MATH_STANDALONE +#ifdef WITH_ASSERT_ABORT + PyErr_SetString(PyExc_ValueError, + "(Vector *= Matrix) is now removed, reverse the " + "order (promoted to an Error for Debug builds) " + "and uses the non in-place multiplication."); + return NULL; +#else + printf("Warning: (Vector *= Matrix) is now deprecated, " + "reverse the (non in-place) multiplication order in the script.\n"); + PyC_LineSpit(); +#endif +#endif /* ifndef MATH_STANDALONE */ +/* ------ to be removed ------*/ + + memcpy(vec->vec, rvec, sizeof(float) * vec->size); } else if (QuaternionObject_Check(v2)) { @@ -1242,6 +1301,25 @@ static PyObject *Vector_imul(PyObject *v1, PyObject *v2) if(BaseMath_ReadCallback(quat2) == -1) { return NULL; } + + +/* ------ to be removed ------*/ +#ifndef MATH_STANDALONE +#ifdef WITH_ASSERT_ABORT + PyErr_SetString(PyExc_ValueError, + "(Vector *= Quat) is now removed, reverse the " + "order (promoted to an Error for Debug builds) " + "and uses the non in-place multiplication."); + return NULL; +#else + printf("Warning: (Vector *= Quat) is now deprecated, " + "reverse the (non in-place) multiplication order in the script.\n"); + PyC_LineSpit(); +#endif +#endif /* ifndef MATH_STANDALONE */ +/* ------ to be removed ------*/ + + mul_qt_v3(quat2->quat, vec->vec); } else if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* VEC *= FLOAT */ diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 583b792f240..b385b507707 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -3375,7 +3375,7 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) /* test for 100% transparant */ ok= 1; - if(ma->alpha==0.0f && ma->spectra==0.0f && ma->filter==0.0f && (ma->mode & MA_TRANSP)) { + if(ma->alpha==0.0f && ma->spectra==0.0f && ma->filter==0.0f && (ma->mode & MA_TRANSP) && (ma->mode & MA_RAYMIRROR)==0) { ok= 0; /* texture on transparency? */ for(a=0; amain= bmain; @@ -5778,6 +5778,14 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, if(re->r.mode & R_RAYTRACE) makeraytree(re); + /* point density texture */ + if(!re->test_break(re->tbh)) + make_pointdensities(re); + + /* voxel data texture */ + if(!re->test_break(re->tbh)) + make_voxeldata(re); + /* occlusion */ if((re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) && !re->test_break(re->tbh)) if(re->wrld.ao_gather_method == WO_AOGATHER_APPROX) diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index 3aca334cffe..a7e19c8db4f 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -2577,27 +2577,7 @@ void RE_bake_ibuf_filter(ImBuf *ibuf, char *mask, const int filter) /* Margin */ if(filter) { - char *temprect; - int i; - - /* extend the mask +2 pixels from the image, - * this is so colors dont blend in from outside */ - - for(i=0; i< filter; i++) - IMB_mask_filter_extend(mask, ibuf->x, ibuf->y); - - temprect = MEM_dupallocN(mask); - - /* expand twice to clear this many pixels, so they blend back in */ - IMB_mask_filter_extend(temprect, ibuf->x, ibuf->y); - IMB_mask_filter_extend(temprect, ibuf->x, ibuf->y); - - /* clear all pixels in the margin */ - IMB_mask_clear(ibuf, temprect, FILTER_MASK_MARGIN); - MEM_freeN(temprect); - - for(i= 0; i < filter; i++) - IMB_filter_extend(ibuf, mask); + IMB_filter_extend(ibuf, mask, filter); } /* if the bake results in new alpha then change the image setting */ diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 67294a8eb53..e6325e2101a 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -272,6 +272,7 @@ void WM_operator_py_idname(char *to, const char *from); /* *************** menu types ******************** */ struct MenuType *WM_menutype_find(const char *idname, int quiet); int WM_menutype_add(struct MenuType* mt); +int WM_menutype_contains(struct MenuType* mt); void WM_menutype_freelink(struct MenuType* mt); void WM_menutype_free(void); diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index bcd5cf38f88..a535c0bc1f8 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -175,6 +175,12 @@ int WM_menutype_add(MenuType* mt) return 1; } +/* inefficient but only used for tooltip code */ +int WM_menutype_contains(MenuType* mt) +{ + return (mt != NULL && BLI_findindex(&menutypes, mt) != -1); +} + void WM_menutype_freelink(MenuType* mt) { BLI_freelinkN(&menutypes, mt); diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 7bf5fe9dde3..548d272ffd2 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -136,7 +136,6 @@ int RE_RenderInProgress(struct Render *re){return 0;} struct Scene *RE_GetScene(struct Render *re){return (struct Scene *) NULL;} void RE_Database_Free(struct Render *re){} void RE_FreeRender(struct Render *re){} -void RE_shade_external(struct Render *re, struct ShadeInput *shi, struct ShadeResult *shr){} void RE_DataBase_GetView(struct Render *re, float mat[][4]){} int externtex(struct MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *tb, float *ta){return 0;} float texture_value_blend(float tex, float out, float fact, float facg, int blendtype, int flip){return 0.0f;} diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index 3a25df73f9b..92be769ed71 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -1184,46 +1184,10 @@ void PyObjectPlus::SetDeprecationWarnings(bool ignoreDeprecationWarnings) m_ignore_deprecation_warnings = ignoreDeprecationWarnings; } -void PyDebugLine() -{ - // import sys; print '\t%s:%d' % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_lineno) - - PyObject *getframe, *frame; - PyObject *f_lineno, *f_code, *co_filename; - - getframe = PySys_GetObject((char *)"_getframe"); // borrowed - if (getframe) { - frame = PyObject_CallObject(getframe, NULL); - if (frame) { - f_lineno= PyObject_GetAttrString(frame, "f_lineno"); - f_code= PyObject_GetAttrString(frame, "f_code"); - if (f_lineno && f_code) { - co_filename= ((PyCodeObject *)f_code)->co_filename; /* borrow */ - if (co_filename) { - - printf("\t%s:%d\n", _PyUnicode_AsString(co_filename), (int)PyLong_AsSsize_t(f_lineno)); - - Py_DECREF(f_lineno); - Py_DECREF(f_code); - Py_DECREF(frame); - return; - } - } - - Py_XDECREF(f_lineno); - Py_XDECREF(f_code); - Py_DECREF(frame); - } - - } - PyErr_Clear(); - printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n"); -} - void PyObjectPlus::ShowDeprecationWarning_func(const char* old_way,const char* new_way) { printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way); - PyDebugLine(); + PyC_LineSpit(); } void PyObjectPlus::ClearDeprecationWarning() diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 587f3e4ef35..51cfb5471c0 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -55,6 +55,7 @@ #ifdef USE_MATHUTILS extern "C" { #include "../../blender/python/mathutils/mathutils.h" /* so we can have mathutils callbacks */ +#include "../../blender/python/generic/py_capi_utils.h" /* for PyC_LineSpit only */ } #endif diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp index 0e08f157a6a..48ba09e67d2 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp @@ -89,7 +89,7 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex ) { int i; // do this once only - if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1 ){ + if(SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO) == -1 ){ echo("Error-Initializing-SDL: " << SDL_GetError()); return NULL; } @@ -124,7 +124,7 @@ void SCA_Joystick::ReleaseInstance() m_instance[i]= NULL; } - SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO); #endif } } diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index ea0b00e52fd..0aa36b4cd5f 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -1220,7 +1220,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) projmat.setValue(m_overrideCamProjMat.getPointer()); cam->SetProjectionMatrix(projmat); } - } else if (cam->hasValidProjectionMatrix() && !cam->GetViewport() ) + } else if (cam->hasValidProjectionMatrix()) { m_rasterizer->SetProjectionMatrix(cam->GetProjectionMatrix()); } else diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt index d1696223ec6..8fd0d6e7099 100644 --- a/source/tests/CMakeLists.txt +++ b/source/tests/CMakeLists.txt @@ -196,7 +196,7 @@ add_test(export_x3d_cube ${TEST_BLENDER_EXE} --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py -- --run={'FINISHED'}&bpy.ops.export_scene.x3d\(filepath='${TEST_OUT_DIR}/export_x3d_cube.x3d',use_selection=False\) --md5_source=${TEST_OUT_DIR}/export_x3d_cube.x3d - --md5=6ae36be272d6f84c697e84a8b6463273 --md5_method=FILE + --md5=5e804c689896116331fa190a9fabbad4 --md5_method=FILE ) add_test(export_x3d_nurbs ${TEST_BLENDER_EXE} @@ -212,7 +212,7 @@ add_test(export_x3d_all_objects ${TEST_BLENDER_EXE} --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py -- --run={'FINISHED'}&bpy.ops.export_scene.x3d\(filepath='${TEST_OUT_DIR}/export_x3d_all_objects.x3d',use_selection=False\) --md5_source=${TEST_OUT_DIR}/export_x3d_all_objects.x3d - --md5=bba48ca191e8891adb27c59ed4ce4735 --md5_method=FILE + --md5=2809ec13a4cab55d265ce7525c5db1b7 --md5_method=FILE ) @@ -261,7 +261,7 @@ add_test(export_3ds_all_objects ${TEST_BLENDER_EXE} --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py -- --run={'FINISHED'}&bpy.ops.export_scene.autodesk_3ds\(filepath='${TEST_OUT_DIR}/export_3ds_all_objects.3ds',use_selection=False\) --md5_source=${TEST_OUT_DIR}/export_3ds_all_objects.3ds - --md5=cdf8fa8475fda0b9ef565ac09339254b --md5_method=FILE + --md5=0940ea889498cd437d503670738639ae --md5_method=FILE ) @@ -273,7 +273,7 @@ add_test(export_fbx_cube ${TEST_BLENDER_EXE} --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py -- --run={'FINISHED'}&bpy.ops.export_scene.fbx\(filepath='${TEST_OUT_DIR}/export_fbx_cube.fbx',use_selection=False,use_metadata=False\) --md5_source=${TEST_OUT_DIR}/export_fbx_cube.fbx - --md5=642a5a1fa199d5b9bbf1643519ae974d --md5_method=FILE + --md5=83dca99a0cb338852b8c85951a44c68a --md5_method=FILE ) add_test(export_fbx_nurbs ${TEST_BLENDER_EXE} @@ -281,7 +281,7 @@ add_test(export_fbx_nurbs ${TEST_BLENDER_EXE} --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py -- --run={'FINISHED'}&bpy.ops.export_scene.fbx\(filepath='${TEST_OUT_DIR}/export_fbx_nurbs.fbx',use_selection=False,use_metadata=False\) --md5_source=${TEST_OUT_DIR}/export_fbx_nurbs.fbx - --md5=ec1e8965bdbc3bf70707d77f82c2cb9c --md5_method=FILE + --md5=c7d9491ffa6264e820ed1e12df63f871 --md5_method=FILE ) add_test(export_fbx_all_objects ${TEST_BLENDER_EXE} @@ -289,5 +289,5 @@ add_test(export_fbx_all_objects ${TEST_BLENDER_EXE} --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py -- --run={'FINISHED'}&bpy.ops.export_scene.fbx\(filepath='${TEST_OUT_DIR}/export_fbx_all_objects.fbx',use_selection=False,use_metadata=False\) --md5_source=${TEST_OUT_DIR}/export_fbx_all_objects.fbx - --md5=af3b65665687ac92e4aba07b017d87fe --md5_method=FILE + --md5=22867f82e1615fd1eae18cfaac8ba035 --md5_method=FILE ) -- cgit v1.2.3 From d55f6c64a24c9e8e46f2a7d33da17aff24ce6d1a Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Thu, 28 Jul 2011 13:44:36 +0000 Subject: speed button mapping to ndof sensitivity change operator. --- source/blender/windowmanager/intern/wm_operators.c | 47 +++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 44e42966c77..1b48e36d2b7 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3432,7 +3432,34 @@ static void WM_OT_memory_statistics(wmOperatorType *ot) } /* ******************************************************* */ - + +static int wm_ndof_sensitivity_exec(bContext *UNUSED(C), wmOperator *op) +{ + float change = 0.1f; + int dir = 1; + if(RNA_boolean_get(op->ptr, "decrease")) + dir = -1; + if(RNA_boolean_get(op->ptr, "fast")) + change = 1.0f; + + + U.ndof_sensitivity += (dir * change); + printf("new sensitivity: %f\n", U.ndof_sensitivity); + return OPERATOR_FINISHED; +} + +static void WM_OT_ndof_sensitivity_change(wmOperatorType *ot) +{ + ot->name= "Change NDOF sensitivity"; + ot->idname= "WM_OT_ndof_sensitivity_change"; + ot->description="Change NDOF sensitivity"; + + ot->exec= wm_ndof_sensitivity_exec; + + RNA_def_boolean(ot->srna, "decrease", 1, "Decrease NDOF sensitivity", "If true then action decreases NDOF sensitivity instead of increasing"); + RNA_def_boolean(ot->srna, "fast", 0, "Fast NDOF sensitivity change", "If true then action change with factor 1.0, otherwise 0.1"); +} +/* ******************************************************* */ /* called on initialize WM_exit() */ void wm_operatortype_free(void) { @@ -3472,6 +3499,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_ndof_menu); WM_operatortype_append(WM_OT_call_menu); WM_operatortype_append(WM_OT_radial_control); + WM_operatortype_append(WM_OT_ndof_sensitivity_change); #if defined(WIN32) WM_operatortype_append(WM_OT_console_toggle); #endif @@ -3740,6 +3768,23 @@ void wm_window_keymap(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F12KEY, KM_PRESS, KM_SHIFT, 0); RNA_string_set(kmi->ptr, "data_path", "area.type"); RNA_string_set(kmi->ptr, "value", "DOPESHEET_EDITOR"); + + /* ndof speed */ + kmi= WM_keymap_add_item(keymap, "WM_OT_ndof_sensitivity_change", NDOF_BUTTON_PLUS, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "decrease", FALSE); + RNA_boolean_set(kmi->ptr, "fast", FALSE); + + kmi= WM_keymap_add_item(keymap, "WM_OT_ndof_sensitivity_change", NDOF_BUTTON_MINUS, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "decrease", TRUE); + RNA_boolean_set(kmi->ptr, "fast", FALSE); + + kmi= WM_keymap_add_item(keymap, "WM_OT_ndof_sensitivity_change", NDOF_BUTTON_PLUS, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "decrease", FALSE); + RNA_boolean_set(kmi->ptr, "fast", TRUE); + + kmi= WM_keymap_add_item(keymap, "WM_OT_ndof_sensitivity_change", NDOF_BUTTON_MINUS, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "decrease", TRUE); + RNA_boolean_set(kmi->ptr, "fast", TRUE); gesture_circle_modal_keymap(keyconf); gesture_border_modal_keymap(keyconf); -- cgit v1.2.3 From b8dcf3a662f35fef388294c635386b952f6bf981 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 28 Jul 2011 14:28:27 +0000 Subject: Fix part of #27944: color managment discrepancy in GLSL materials with nodes. --- source/blender/gpu/intern/gpu_material.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 806c70d841f..274884000db 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1371,9 +1371,6 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) mat->obcolalpha = 1; GPU_link(mat, "shade_alpha_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined); } - - if(gpu_do_color_management(mat)) - GPU_link(mat, "linearrgb_to_srgb", shr->combined, &shr->combined); } static GPUNodeLink *GPU_blender_material(GPUMaterial *mat, Material *ma) @@ -1408,6 +1405,10 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) GPU_material_output_link(mat, outlink); } + if(gpu_do_color_management(mat)) + if(mat->outlink) + GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink); + /*if(!GPU_material_construct_end(mat)) { GPU_material_free(mat); mat= NULL; -- cgit v1.2.3 From 6d2754e07d0785e30c75cf6498b94f1fb5f54f46 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 28 Jul 2011 15:51:59 +0000 Subject: Fix #27719: custom RNA properties fail to update drivers. Hopefully this is not too slow, but now we do a dependency graph tag also for these in addition to regular ID properties, not sure how to get around it. --- source/blender/makesrna/intern/rna_access.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index dcf2400b9ba..e71be8c153e 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -1364,13 +1364,13 @@ static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerR if(prop->noteflag) WM_main_add_notifier(prop->noteflag, ptr->id.data); } - else { + + if(!is_rna || (prop->flag & PROP_IDPROPERTY)) { /* WARNING! This is so property drivers update the display! * not especially nice */ DAG_id_tag_update(ptr->id.data, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); WM_main_add_notifier(NC_WINDOW, NULL); } - } /* must keep in sync with 'rna_property_update' -- cgit v1.2.3 From 336a47cdcf909864e080d9917cbc04bd7134da1f Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Thu, 28 Jul 2011 18:19:15 +0000 Subject: * Code cleanup A row with alignment for 1 property = useless: ;-) --- release/scripts/startup/bl_ui/properties_data_empty.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py index 5a0d327f90d..42b0af7eaf5 100644 --- a/release/scripts/startup/bl_ui/properties_data_empty.py +++ b/release/scripts/startup/bl_ui/properties_data_empty.py @@ -41,11 +41,9 @@ class DATA_PT_empty(DataButtonsPanel, bpy.types.Panel): layout.prop(ob, "empty_draw_type", text="Display") if ob.empty_draw_type == 'IMAGE': - # layout.template_image(ob, "data", None) layout.template_ID(ob, "data", open="image.open", unlink="image.unlink") - row = layout.row(align=True) - row.prop(ob, "color", text="Transparency", index=3, slider=True) + layout.prop(ob, "color", text="Transparency", index=3, slider=True) row = layout.row(align=True) row.prop(ob, "empty_image_offset", text="Offset X", index=0) row.prop(ob, "empty_image_offset", text="Offset Y", index=1) -- cgit v1.2.3 From 26589497529ca3c8da85391d4976d286a371e258 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 29 Jul 2011 01:24:03 +0000 Subject: pep8 cleanup, also print message when attempting to run in animation player mode. --- build_files/cmake/cmake_consistency_check.py | 12 ++++---- build_files/cmake/cmake_netbeans_project.py | 13 ++++++++- build_files/cmake/cmake_qtcreator_project.py | 12 +++++++- doc/python_api/examples/bge.constraints.py | 12 ++++---- doc/python_api/examples/bge.texture.1.py | 16 ++++++----- doc/python_api/examples/bge.texture.py | 10 +++---- doc/python_api/examples/blf.py | 15 ++++++---- release/scripts/modules/addon_utils.py | 1 + release/scripts/modules/bpy/__init__.py | 1 + release/scripts/modules/bpy_extras/io_utils.py | 17 ++++++++---- release/scripts/modules/bpy_extras/mesh_utils.py | 32 +++++++++++++--------- .../scripts/startup/bl_operators/object_align.py | 6 ++-- release/scripts/startup/bl_ui/properties_world.py | 2 +- release/scripts/startup/bl_ui/space_info.py | 2 +- release/scripts/startup/bl_ui/space_node.py | 2 +- release/scripts/startup/bl_ui/space_userpref.py | 1 - release/scripts/startup/bl_ui/space_view3d.py | 2 +- .../scripts/startup/bl_ui/space_view3d_toolbar.py | 1 + release/scripts/templates/batch_export.py | 2 +- release/scripts/templates/ui_menu.py | 4 +-- source/blender/windowmanager/intern/wm_init_exit.c | 3 +- source/creator/creator.c | 7 +++-- source/tests/check_deprecated.py | 13 ++++++--- 23 files changed, 118 insertions(+), 68 deletions(-) diff --git a/build_files/cmake/cmake_consistency_check.py b/build_files/cmake/cmake_consistency_check.py index 4b35e34a5cd..ba71603b007 100755 --- a/build_files/cmake/cmake_consistency_check.py +++ b/build_files/cmake/cmake_consistency_check.py @@ -42,9 +42,9 @@ def replace_line(f, i, text, keep_indent=True): l = data[i] ws = l[:len(l) - len(l.lstrip())] - + data[i] = "%s%s\n" % (ws, text) - + file_handle = open(f, 'w') file_handle.writelines(data) file_handle.close() @@ -182,13 +182,13 @@ def cmake_get_src(f): if new_path_rel != l: print("overly relative path:\n %s:%d\n %s\n %s" % (f, i, l, new_path_rel)) - + ## Save time. just replace the line # replace_line(f, i - 1, new_path_rel) - + else: raise Exception("non existant include %s:%d -> %s" % (f, i, new_file)) - + # print(new_file) global_h.update(set(sources_h)) @@ -206,7 +206,7 @@ def cmake_get_src(f): if ff not in sources_c: print(" missing: " + ff) ''' - + # reset sources_h[:] = [] sources_c[:] = [] diff --git a/build_files/cmake/cmake_netbeans_project.py b/build_files/cmake/cmake_netbeans_project.py index 6afca8f3b6a..8060574580c 100755 --- a/build_files/cmake/cmake_netbeans_project.py +++ b/build_files/cmake/cmake_netbeans_project.py @@ -30,7 +30,18 @@ Example linux usage Windows not supported so far """ -from project_info import * +from project_info import (SIMPLE_PROJECTFILE, + SOURCE_DIR, + CMAKE_DIR, + PROJECT_DIR, + source_list, + is_project_file, + is_c_header, + is_py, + cmake_advanced_info, + cmake_compiler_defines, + ) + import os from os.path import join, dirname, normpath, relpath, exists diff --git a/build_files/cmake/cmake_qtcreator_project.py b/build_files/cmake/cmake_qtcreator_project.py index 3de15567727..d8993c3197a 100755 --- a/build_files/cmake/cmake_qtcreator_project.py +++ b/build_files/cmake/cmake_qtcreator_project.py @@ -31,7 +31,17 @@ example linux usage python .~/blenderSVN/blender/build_files/cmake/cmake_qtcreator_project.py ~/blenderSVN/cmake """ -from project_info import * +from project_info import (SIMPLE_PROJECTFILE, + SOURCE_DIR, + CMAKE_DIR, + PROJECT_DIR, + source_list, + is_project_file, + is_c_header, + is_py, + cmake_advanced_info, + cmake_compiler_defines, + ) import os import sys diff --git a/doc/python_api/examples/bge.constraints.py b/doc/python_api/examples/bge.constraints.py index 4cd967310cc..de2f7e0a39d 100644 --- a/doc/python_api/examples/bge.constraints.py +++ b/doc/python_api/examples/bge.constraints.py @@ -8,11 +8,11 @@ from bge import constraints # get object list objects = logic.getCurrentScene().objects - + # get object named Object1 and Object 2 object_1 = objects["Object1"] object_2 = objects["Object2"] - + # want to use Edge constraint type constraint_type = 2 @@ -31,7 +31,7 @@ edge_angle_y = 1.0 edge_angle_z = 0.0 # create an edge constraint -constraints.createConstraint( physics_id_1, physics_id_2, - constraint_type, - edge_position_x, edge_position_y, edge_position_z, - edge_angle_x, edge_angle_y, edge_angle_z ) +constraints.createConstraint(physics_id_1, physics_id_2, + constraint_type, + edge_position_x, edge_position_y, edge_position_z, + edge_angle_x, edge_angle_y, edge_angle_z) diff --git a/doc/python_api/examples/bge.texture.1.py b/doc/python_api/examples/bge.texture.1.py index 74b37e72994..faa0ae736e8 100644 --- a/doc/python_api/examples/bge.texture.1.py +++ b/doc/python_api/examples/bge.texture.1.py @@ -6,29 +6,31 @@ createTexture() and removeTexture() are to be called from a module Python Controller. """ from bge import logic -from bge import texture +from bge import texture + def createTexture(cont): """Create a new Dynamic Texture""" object = cont.owner - + # get the reference pointer (ID) of the internal texture ID = texture.materialID(obj, 'IMoriginal.png') - - # create a texture object + + # create a texture object object_texture = texture.Texture(object, ID) - + # create a new source with an external image url = logic.expandPath("//newtexture.jpg") new_source = texture.ImageFFmpeg(url) - + # the texture has to be stored in a permanent Python object logic.texture = object_texture - + # update/replace the texture logic.texture.source = new_source logic.texture.refresh(False) + def removeTexture(cont): """Delete the Dynamic Texture, reversing back the final to its original state.""" try: diff --git a/doc/python_api/examples/bge.texture.py b/doc/python_api/examples/bge.texture.py index 0ec9aa16bca..70e4d6d9377 100644 --- a/doc/python_api/examples/bge.texture.py +++ b/doc/python_api/examples/bge.texture.py @@ -9,14 +9,14 @@ from bge import logic cont = logic.getCurrentController() obj = cont.owner - -# the creation of the texture must be done once: save the + +# the creation of the texture must be done once: save the # texture object in an attribute of bge.logic module makes it persistent if not hasattr(logic, 'video'): - + # identify a static texture by name matID = texture.materialID(obj, 'IMvideo.png') - + # create a dynamic texture that will replace the static texture logic.video = texture.Texture(obj, matID) @@ -24,7 +24,7 @@ if not hasattr(logic, 'video'): movie = logic.expandPath('//trailer_400p.ogg') logic.video.source = texture.VideoFFmpeg(movie) logic.video.source.scale = True - + # quick off the movie, but it wont play in the background logic.video.source.play() diff --git a/doc/python_api/examples/blf.py b/doc/python_api/examples/blf.py index 3ab7f789ce8..f6e87cf488d 100644 --- a/doc/python_api/examples/blf.py +++ b/doc/python_api/examples/blf.py @@ -1,6 +1,7 @@ """ Hello World Text Example ++++++++++++++++++++++++ + Blender Game Engine example of using the blf module. For this module to work we need to use the OpenGL wrapper :class:`~bgl` as well. """ @@ -11,31 +12,33 @@ from bge import logic import bgl import blf + def init(): """init function - runs once""" # create a new font object, use external ttf file font_path = logic.expandPath('//Zeyada.ttf') - # store the font indice - to use later + # store the font indice - to use later logic.font_id = blf.load(font_path) - # set the font drawing routine to run every frame + # set the font drawing routine to run every frame scene = logic.getCurrentScene() - scene.post_draw=[write] + scene.post_draw = [write] + def write(): """write on screen""" width = render.getWindowWidth() height = render.getWindowHeight() - + # OpenGL setup bgl.glMatrixMode(bgl.GL_PROJECTION) bgl.glLoadIdentity() bgl.gluOrtho2D(0, width, 0, height) bgl.glMatrixMode(bgl.GL_MODELVIEW) bgl.glLoadIdentity() - + # BLF drawing routine font_id = logic.font_id - blf.position(font_id, (width*0.2), (height*0.3), 0) + blf.position(font_id, (width * 0.2), (height * 0.3), 0) blf.size(font_id, 50, 72) blf.draw(font_id, "Hello World") diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py index cf74282d064..5aed0581ea9 100644 --- a/release/scripts/modules/addon_utils.py +++ b/release/scripts/modules/addon_utils.py @@ -33,6 +33,7 @@ import bpy as _bpy error_duplicates = False + def paths(): # RELEASE SCRIPTS: official scripts distributed in Blender releases paths = _bpy.utils.script_paths("addons") diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py index 9c48dc89f83..0add2b3e6cd 100644 --- a/release/scripts/modules/bpy/__init__.py +++ b/release/scripts/modules/bpy/__init__.py @@ -43,6 +43,7 @@ from . import utils, path, ops # fake operator module ops = ops.ops_fake_module + def _main(): import sys as _sys diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py index bd01897c639..0a3f1392653 100644 --- a/release/scripts/modules/bpy_extras/io_utils.py +++ b/release/scripts/modules/bpy_extras/io_utils.py @@ -159,14 +159,19 @@ def axis_conversion(from_forward='Y', from_up='Z', to_forward='Y', to_up='Z'): raise Exception("invalid axis arguments passed, " "can't use up/forward on the same axis.") - value = reduce(int.__or__, (_axis_convert_num[a] << (i * 3) for i, a in enumerate((from_forward, from_up, to_forward, to_up)))) + value = reduce(int.__or__, (_axis_convert_num[a] << (i * 3) + for i, a in enumerate((from_forward, + from_up, + to_forward, + to_up, + )))) for i, axis_lut in enumerate(_axis_convert_lut): if value in axis_lut: return Matrix(_axis_convert_matrix[i]) assert(0) - + def axis_conversion_ensure(operator, forward_attr, up_attr): """ Function to ensure an operator has valid axis conversion settings, intended @@ -174,9 +179,9 @@ def axis_conversion_ensure(operator, forward_attr, up_attr): :arg operator: the operator to access axis attributes from. :type operator: :class:`Operator` - :arg forward_attr: + :arg forward_attr: attribute storing the forward axis :type forward_attr: string - :arg up_attr: the directory the *filepath* will be referenced from (normally the export path). + :arg up_attr: attribute storing the up axis :type up_attr: string :return: True if the value was modified. :rtype: boolean @@ -184,9 +189,9 @@ def axis_conversion_ensure(operator, forward_attr, up_attr): def validate(axis_forward, axis_up): if axis_forward[-1] == axis_up[-1]: axis_up = axis_up[0:-1] + 'XYZ'[('XYZ'.index(axis_up[-1]) + 1) % 3] - + return axis_forward, axis_up - + change = False axis = getattr(operator, forward_attr), getattr(operator, up_attr) diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py index c42d3d0236a..ecd620ff2c9 100644 --- a/release/scripts/modules/bpy_extras/mesh_utils.py +++ b/release/scripts/modules/bpy_extras/mesh_utils.py @@ -170,8 +170,8 @@ def edge_loops_from_faces(mesh, faces=None, seams=()): # from knowing the last 2, look for th next. ed_adj = edges[context_loop[-1]] if len(ed_adj) != 2: - - if other_dir and flipped == False: # the original edge had 2 other edges + # the original edge had 2 other edges + if other_dir and flipped == False: flipped = True # only flip the list once context_loop.reverse() ed_adj[:] = [] @@ -259,13 +259,15 @@ def edge_loops_from_edges(mesh, edges=None): def ngon_tesselate(from_data, indices, fix_loops=True): ''' - Takes a polyline of indices (fgon) - and returns a list of face indicie lists. - Designed to be used for importers that need indices for an fgon to create from existing verts. + Takes a polyline of indices (fgon) and returns a list of face + indicie lists. Designed to be used for importers that need indices for an + fgon to create from existing verts. from_data: either a mesh, or a list/tuple of vectors. - indices: a list of indices to use this list is the ordered closed polyline to fill, and can be a subset of the data given. - fix_loops: If this is enabled polylines that use loops to make multiple polylines are delt with correctly. + indices: a list of indices to use this list is the ordered closed polyline + to fill, and can be a subset of the data given. + fix_loops: If this is enabled polylines that use loops to make multiple + polylines are delt with correctly. ''' from mathutils.geometry import tesselate_polygon @@ -276,7 +278,8 @@ def ngon_tesselate(from_data, indices, fix_loops=True): return [] def mlen(co): - return abs(co[0]) + abs(co[1]) + abs(co[2]) # manhatten length of a vector, faster then length + # manhatten length of a vector, faster then length + return abs(co[0]) + abs(co[1]) + abs(co[2]) def vert_treplet(v, i): return v, vector_to_tuple(v, 6), i, mlen(v) @@ -296,7 +299,8 @@ def ngon_tesselate(from_data, indices, fix_loops=True): else: verts = [from_data.vertices[i].co for ii, i in enumerate(indices)] - for i in range(len(verts) - 1, 0, -1): # same as reversed(xrange(1, len(verts))): + # same as reversed(range(1, len(verts))): + for i in range(len(verts) - 1, 0, -1): if verts[i][1] == verts[i - 1][0]: verts.pop(i - 1) @@ -304,14 +308,16 @@ def ngon_tesselate(from_data, indices, fix_loops=True): else: ''' - Seperate this loop into multiple loops be finding edges that are used twice - This is used by lightwave LWO files a lot + Seperate this loop into multiple loops be finding edges that are + used twice. This is used by lightwave LWO files a lot ''' if type(from_data) in (tuple, list): - verts = [vert_treplet(Vector(from_data[i]), ii) for ii, i in enumerate(indices)] + verts = [vert_treplet(Vector(from_data[i]), ii) + for ii, i in enumerate(indices)] else: - verts = [vert_treplet(from_data.vertices[i].co, ii) for ii, i in enumerate(indices)] + verts = [vert_treplet(from_data.vertices[i].co, ii) + for ii, i in enumerate(indices)] edges = [(i, i - 1) for i in range(len(verts))] if edges: diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py index 8fe606399b4..7fd769c40c9 100644 --- a/release/scripts/startup/bl_operators/object_align.py +++ b/release/scripts/startup/bl_operators/object_align.py @@ -21,6 +21,7 @@ import bpy from mathutils import Vector + def GlobalBB_LQ(bb_world): # Initialize the variables with the 8th vertex @@ -33,7 +34,7 @@ def GlobalBB_LQ(bb_world): ) # Test against the other 7 verts - for i in range (7): + for i in range(7): # X Range val = bb_world[i][0] @@ -61,6 +62,7 @@ def GlobalBB_LQ(bb_world): return (Vector((left, front, up)), Vector((right, back, down))) + def GlobalBB_HQ(obj): matrix_world = obj.matrix_world.copy() @@ -80,7 +82,7 @@ def GlobalBB_HQ(obj): ) # Test against all other verts - for i in range (len(verts)-1): + for i in range(len(verts) - 1): vco = matrix_world * verts[i].co diff --git a/release/scripts/startup/bl_ui/properties_world.py b/release/scripts/startup/bl_ui/properties_world.py index 0272667e754..c577af01374 100644 --- a/release/scripts/startup/bl_ui/properties_world.py +++ b/release/scripts/startup/bl_ui/properties_world.py @@ -93,7 +93,7 @@ class WORLD_PT_world(WorldButtonsPanel, bpy.types.Panel): col.prop(world, "zenith_color") col.active = world.use_sky_blend row.column().prop(world, "ambient_color") - + row = layout.row() row.prop(world, "exposure") row.prop(world, "color_range") diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index cda37b3119a..f66cee7f431 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -60,7 +60,7 @@ class INFO_HT_header(bpy.types.Header): layout.template_running_jobs() layout.template_reports_banner() - + row = layout.row(align=True) row.operator("wm.splash", text="", icon='BLENDER', emboss=False) row.label(text=scene.statistics()) diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 831fd359782..2088d8798f2 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -135,7 +135,7 @@ class NODE_MT_node(bpy.types.Menu): layout.operator("transform.resize") layout.separator() - + layout.operator("node.duplicate_move") layout.operator("node.delete") layout.operator("node.delete_reconnect") diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 139b3205835..576709c6072 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1020,7 +1020,6 @@ class USERPREF_PT_addons(bpy.types.Panel): for i in range(4 - tot_row): split.separator() - # Append missing scripts # First collect scripts that are used but have no script file. module_names = {mod.__name__ for mod, info in addons} diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index acb0499c40f..083c330f61d 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -55,7 +55,7 @@ class VIEW3D_HT_header(bpy.types.Header): row = layout.row() # Contains buttons like Mode, Pivot, Manipulator, Layer, Mesh Select Mode... - row.template_header_3D() + row.template_header_3D() if obj: # Particle edit diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 19c3224f138..91cfd22b3d6 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -58,6 +58,7 @@ def draw_gpencil_tools(context, layout): row = col.row() row.prop(context.tool_settings, "use_grease_pencil_sessions") + # ********** default tools for objectmode **************** class VIEW3D_PT_tools_objectmode(View3DPanel, bpy.types.Panel): diff --git a/release/scripts/templates/batch_export.py b/release/scripts/templates/batch_export.py index aa0e601725b..45d26f4b525 100644 --- a/release/scripts/templates/batch_export.py +++ b/release/scripts/templates/batch_export.py @@ -26,7 +26,7 @@ for obj in selection: # bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True) obj.select = False - + print("written:", fn) for obj in selection: diff --git a/release/scripts/templates/ui_menu.py b/release/scripts/templates/ui_menu.py index d3923b5b083..d3c94b86809 100644 --- a/release/scripts/templates/ui_menu.py +++ b/release/scripts/templates/ui_menu.py @@ -26,8 +26,8 @@ class CustomMenu(bpy.types.Menu): def draw_item(self, context): - layout = self.layout - layout.menu(CustomMenu.bl_idname) + layout = self.layout + layout.menu(CustomMenu.bl_idname) def register(): diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index ed28696ef69..4c280fe4341 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -155,7 +155,8 @@ void WM_init(bContext *C, int argc, const char **argv) BPY_python_start(argc, argv); BPY_driver_reset(); - BPY_app_handlers_reset(); + BPY_app_handlers_reset(); /* causes addon callbacks to be freed [#28068], + * but this is actually what we want. */ BPY_modules_load_user(C); #else (void)argc; /* unused */ diff --git a/source/creator/creator.c b/source/creator/creator.c index fddd6d286db..36209dbda78 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -434,9 +434,12 @@ static int playback_mode(int UNUSED(argc), const char **UNUSED(argv), void *UNUS { /* not if -b was given first */ if (G.background == 0) { - -// XXX playanim(argc, argv); /* not the same argc and argv as before */ +#if 0 /* TODO, bring player back? */ + playanim(argc, argv); /* not the same argc and argv as before */ +#else + fprintf(stderr, "Playback mode not supported in blender 2.5x\n"); exit(0); +#endif } return -2; diff --git a/source/tests/check_deprecated.py b/source/tests/check_deprecated.py index 11c7ce646b9..856e1f6d272 100644 --- a/source/tests/check_deprecated.py +++ b/source/tests/check_deprecated.py @@ -28,6 +28,7 @@ SKIP_DIRS = ("extern", os.path.join("source", "tests"), # not this dir ) + def is_c_header(filename): ext = splitext(filename)[1] return (ext in (".h", ".hpp", ".hxx")) @@ -41,13 +42,16 @@ def is_c(filename): def is_c_any(filename): return is_c(filename) or is_c_header(filename) + def is_py(filename): ext = splitext(filename)[1] return (ext == ".py") + def is_source_any(filename): return is_c_any(filename) or is_py(filename) + def source_list(path, filename_check=None): for dirpath, dirnames, filenames in os.walk(path): @@ -67,7 +71,7 @@ def deprecations(): /* *DEPRECATED* 2011/7/17 bgl.Buffer.list info text */ Or... - + # *DEPRECATED* 2010/12/22 some.py.func more info */ """ @@ -105,12 +109,12 @@ def deprecations(): if len(data) != 3: print(" poorly formatting line:\n" " %r:%d\n" - " %s"% + " %s" % (fn, i + 1, l) ) else: data = datetime.datetime(*tuple([int(w) for w in data])) - + deprecations_ls.append((data, (fn, i + 1), info)) except: print("Error file - %r:%d" % (fn, i + 1)) @@ -123,10 +127,11 @@ def deprecations(): return deprecations_ls + def main(): import datetime now = datetime.datetime.now()\ - + deps = deprecations() print("\nAll deprecations...") -- cgit v1.2.3 From fb738f4929e88b21ebcfb724ae3f460ef6e0f949 Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Fri, 29 Jul 2011 07:14:03 +0000 Subject: When relinking node group outputs from sockets of different type, automatically change the output to the source type. Feature request by Daniel Salazar. --- source/blender/editors/space_node/node_edit.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 18d4d85e3ff..c719f749582 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -2216,6 +2216,12 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event) /* we might need to remove a link */ if(in_out==SOCK_OUT) node_remove_extra_links(snode, link->tosock, link); + + /* when linking to group outputs, update the socket type */ + /* XXX this should all be part of a generic update system */ + if (!link->tonode) { + link->tosock->type = link->fromsock->type; + } } else if (outside_group_rect(snode) && (link->tonode || link->fromnode)) { /* automatically add new group socket */ -- cgit v1.2.3 From 24def76ac899e106b4a04364504ba0cbc100d7f7 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Fri, 29 Jul 2011 07:58:03 +0000 Subject: svn merge -r38753:38813 https://svn.blender.org/svnroot/bf-blender/trunk/blender . --- build_files/cmake/cmake_consistency_check.py | 12 +-- build_files/cmake/cmake_netbeans_project.py | 13 ++- build_files/cmake/cmake_qtcreator_project.py | 12 ++- doc/python_api/examples/bge.constraints.py | 12 +-- doc/python_api/examples/bge.texture.1.py | 16 ++-- doc/python_api/examples/bge.texture.py | 10 +- doc/python_api/examples/blf.py | 15 +-- doc/python_api/sphinx_doc_gen.sh | 7 +- release/scripts/modules/addon_utils.py | 1 + release/scripts/modules/bpy/__init__.py | 1 + release/scripts/modules/bpy_extras/io_utils.py | 19 ++-- release/scripts/modules/bpy_extras/mesh_utils.py | 32 ++++--- release/scripts/startup/bl_operators/object.py | 105 ++++++++++++++++----- .../scripts/startup/bl_operators/object_align.py | 6 +- .../bl_operators/screen_play_rendered_anim.py | 26 +++++ .../scripts/startup/bl_ui/properties_data_empty.py | 4 +- .../startup/bl_ui/properties_data_modifier.py | 1 + release/scripts/startup/bl_ui/properties_world.py | 2 +- release/scripts/startup/bl_ui/space_info.py | 2 +- release/scripts/startup/bl_ui/space_node.py | 2 +- release/scripts/startup/bl_ui/space_userpref.py | 1 - release/scripts/startup/bl_ui/space_view3d.py | 2 +- .../scripts/startup/bl_ui/space_view3d_toolbar.py | 1 + release/scripts/templates/batch_export.py | 2 +- release/scripts/templates/ui_menu.py | 4 +- source/blender/blenkernel/intern/cdderivedmesh.c | 2 + source/blender/blenkernel/intern/customdata.c | 1 - source/blender/blenkernel/intern/material.c | 2 +- source/blender/blenkernel/intern/multires.c | 18 ++-- source/blender/collada/MaterialExporter.cpp | 32 ++++++- source/blender/collada/MaterialExporter.h | 3 + source/blender/editors/interface/resources.c | 9 +- source/blender/editors/space_node/node_edit.c | 8 +- .../editors/space_sequencer/sequencer_add.c | 33 +++++-- source/blender/editors/transform/transform_snap.c | 21 +++-- source/blender/gpu/intern/gpu_material.c | 7 +- source/blender/makesdna/DNA_modifier_types.h | 1 + source/blender/makesrna/intern/rna_access.c | 4 +- source/blender/makesrna/intern/rna_modifier.c | 5 + source/blender/windowmanager/intern/wm_init_exit.c | 3 +- source/creator/creator.c | 7 +- source/tests/check_deprecated.py | 13 ++- 42 files changed, 341 insertions(+), 136 deletions(-) diff --git a/build_files/cmake/cmake_consistency_check.py b/build_files/cmake/cmake_consistency_check.py index 4b35e34a5cd..ba71603b007 100755 --- a/build_files/cmake/cmake_consistency_check.py +++ b/build_files/cmake/cmake_consistency_check.py @@ -42,9 +42,9 @@ def replace_line(f, i, text, keep_indent=True): l = data[i] ws = l[:len(l) - len(l.lstrip())] - + data[i] = "%s%s\n" % (ws, text) - + file_handle = open(f, 'w') file_handle.writelines(data) file_handle.close() @@ -182,13 +182,13 @@ def cmake_get_src(f): if new_path_rel != l: print("overly relative path:\n %s:%d\n %s\n %s" % (f, i, l, new_path_rel)) - + ## Save time. just replace the line # replace_line(f, i - 1, new_path_rel) - + else: raise Exception("non existant include %s:%d -> %s" % (f, i, new_file)) - + # print(new_file) global_h.update(set(sources_h)) @@ -206,7 +206,7 @@ def cmake_get_src(f): if ff not in sources_c: print(" missing: " + ff) ''' - + # reset sources_h[:] = [] sources_c[:] = [] diff --git a/build_files/cmake/cmake_netbeans_project.py b/build_files/cmake/cmake_netbeans_project.py index 6afca8f3b6a..8060574580c 100755 --- a/build_files/cmake/cmake_netbeans_project.py +++ b/build_files/cmake/cmake_netbeans_project.py @@ -30,7 +30,18 @@ Example linux usage Windows not supported so far """ -from project_info import * +from project_info import (SIMPLE_PROJECTFILE, + SOURCE_DIR, + CMAKE_DIR, + PROJECT_DIR, + source_list, + is_project_file, + is_c_header, + is_py, + cmake_advanced_info, + cmake_compiler_defines, + ) + import os from os.path import join, dirname, normpath, relpath, exists diff --git a/build_files/cmake/cmake_qtcreator_project.py b/build_files/cmake/cmake_qtcreator_project.py index 3de15567727..d8993c3197a 100755 --- a/build_files/cmake/cmake_qtcreator_project.py +++ b/build_files/cmake/cmake_qtcreator_project.py @@ -31,7 +31,17 @@ example linux usage python .~/blenderSVN/blender/build_files/cmake/cmake_qtcreator_project.py ~/blenderSVN/cmake """ -from project_info import * +from project_info import (SIMPLE_PROJECTFILE, + SOURCE_DIR, + CMAKE_DIR, + PROJECT_DIR, + source_list, + is_project_file, + is_c_header, + is_py, + cmake_advanced_info, + cmake_compiler_defines, + ) import os import sys diff --git a/doc/python_api/examples/bge.constraints.py b/doc/python_api/examples/bge.constraints.py index 4cd967310cc..de2f7e0a39d 100644 --- a/doc/python_api/examples/bge.constraints.py +++ b/doc/python_api/examples/bge.constraints.py @@ -8,11 +8,11 @@ from bge import constraints # get object list objects = logic.getCurrentScene().objects - + # get object named Object1 and Object 2 object_1 = objects["Object1"] object_2 = objects["Object2"] - + # want to use Edge constraint type constraint_type = 2 @@ -31,7 +31,7 @@ edge_angle_y = 1.0 edge_angle_z = 0.0 # create an edge constraint -constraints.createConstraint( physics_id_1, physics_id_2, - constraint_type, - edge_position_x, edge_position_y, edge_position_z, - edge_angle_x, edge_angle_y, edge_angle_z ) +constraints.createConstraint(physics_id_1, physics_id_2, + constraint_type, + edge_position_x, edge_position_y, edge_position_z, + edge_angle_x, edge_angle_y, edge_angle_z) diff --git a/doc/python_api/examples/bge.texture.1.py b/doc/python_api/examples/bge.texture.1.py index 74b37e72994..faa0ae736e8 100644 --- a/doc/python_api/examples/bge.texture.1.py +++ b/doc/python_api/examples/bge.texture.1.py @@ -6,29 +6,31 @@ createTexture() and removeTexture() are to be called from a module Python Controller. """ from bge import logic -from bge import texture +from bge import texture + def createTexture(cont): """Create a new Dynamic Texture""" object = cont.owner - + # get the reference pointer (ID) of the internal texture ID = texture.materialID(obj, 'IMoriginal.png') - - # create a texture object + + # create a texture object object_texture = texture.Texture(object, ID) - + # create a new source with an external image url = logic.expandPath("//newtexture.jpg") new_source = texture.ImageFFmpeg(url) - + # the texture has to be stored in a permanent Python object logic.texture = object_texture - + # update/replace the texture logic.texture.source = new_source logic.texture.refresh(False) + def removeTexture(cont): """Delete the Dynamic Texture, reversing back the final to its original state.""" try: diff --git a/doc/python_api/examples/bge.texture.py b/doc/python_api/examples/bge.texture.py index 0ec9aa16bca..70e4d6d9377 100644 --- a/doc/python_api/examples/bge.texture.py +++ b/doc/python_api/examples/bge.texture.py @@ -9,14 +9,14 @@ from bge import logic cont = logic.getCurrentController() obj = cont.owner - -# the creation of the texture must be done once: save the + +# the creation of the texture must be done once: save the # texture object in an attribute of bge.logic module makes it persistent if not hasattr(logic, 'video'): - + # identify a static texture by name matID = texture.materialID(obj, 'IMvideo.png') - + # create a dynamic texture that will replace the static texture logic.video = texture.Texture(obj, matID) @@ -24,7 +24,7 @@ if not hasattr(logic, 'video'): movie = logic.expandPath('//trailer_400p.ogg') logic.video.source = texture.VideoFFmpeg(movie) logic.video.source.scale = True - + # quick off the movie, but it wont play in the background logic.video.source.play() diff --git a/doc/python_api/examples/blf.py b/doc/python_api/examples/blf.py index 3ab7f789ce8..f6e87cf488d 100644 --- a/doc/python_api/examples/blf.py +++ b/doc/python_api/examples/blf.py @@ -1,6 +1,7 @@ """ Hello World Text Example ++++++++++++++++++++++++ + Blender Game Engine example of using the blf module. For this module to work we need to use the OpenGL wrapper :class:`~bgl` as well. """ @@ -11,31 +12,33 @@ from bge import logic import bgl import blf + def init(): """init function - runs once""" # create a new font object, use external ttf file font_path = logic.expandPath('//Zeyada.ttf') - # store the font indice - to use later + # store the font indice - to use later logic.font_id = blf.load(font_path) - # set the font drawing routine to run every frame + # set the font drawing routine to run every frame scene = logic.getCurrentScene() - scene.post_draw=[write] + scene.post_draw = [write] + def write(): """write on screen""" width = render.getWindowWidth() height = render.getWindowHeight() - + # OpenGL setup bgl.glMatrixMode(bgl.GL_PROJECTION) bgl.glLoadIdentity() bgl.gluOrtho2D(0, width, 0, height) bgl.glMatrixMode(bgl.GL_MODELVIEW) bgl.glLoadIdentity() - + # BLF drawing routine font_id = logic.font_id - blf.position(font_id, (width*0.2), (height*0.3), 0) + blf.position(font_id, (width * 0.2), (height * 0.3), 0) blf.size(font_id, 50, 72) blf.draw(font_id, "Hello World") diff --git a/doc/python_api/sphinx_doc_gen.sh b/doc/python_api/sphinx_doc_gen.sh index 5f23ca395b6..a3befe1b7cb 100755 --- a/doc/python_api/sphinx_doc_gen.sh +++ b/doc/python_api/sphinx_doc_gen.sh @@ -38,8 +38,11 @@ cp $SPHINXBASE/sphinx-out/contents.html $SPHINXBASE/sphinx-out/index.html ssh $SSH_USER@emo.blender.org 'rm -rf '$SSH_UPLOAD_FULL'/*' rsync --progress -avze "ssh -p 22" $SPHINXBASE/sphinx-out/* $SSH_HOST:$SSH_UPLOAD_FULL/ -# symlink the dir to a static URL -ssh $SSH_USER@emo.blender.org 'rm '$SSH_UPLOAD'/250PythonDoc && ln -s '$SSH_UPLOAD_FULL' '$SSH_UPLOAD'/250PythonDoc' +## symlink the dir to a static URL +#ssh $SSH_USER@emo.blender.org 'rm '$SSH_UPLOAD'/250PythonDoc && ln -s '$SSH_UPLOAD_FULL' '$SSH_UPLOAD'/250PythonDoc' + +# better redirect +ssh $SSH_USER@emo.blender.org 'echo "Redirecting...Redirecting..." > '$SSH_UPLOAD'/250PythonDoc/index.html' # pdf sphinx-build -b latex $SPHINXBASE/sphinx-in $SPHINXBASE/sphinx-out diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py index cf74282d064..5aed0581ea9 100644 --- a/release/scripts/modules/addon_utils.py +++ b/release/scripts/modules/addon_utils.py @@ -33,6 +33,7 @@ import bpy as _bpy error_duplicates = False + def paths(): # RELEASE SCRIPTS: official scripts distributed in Blender releases paths = _bpy.utils.script_paths("addons") diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py index 9c48dc89f83..0add2b3e6cd 100644 --- a/release/scripts/modules/bpy/__init__.py +++ b/release/scripts/modules/bpy/__init__.py @@ -43,6 +43,7 @@ from . import utils, path, ops # fake operator module ops = ops.ops_fake_module + def _main(): import sys as _sys diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py index 9545e20b025..0a3f1392653 100644 --- a/release/scripts/modules/bpy_extras/io_utils.py +++ b/release/scripts/modules/bpy_extras/io_utils.py @@ -159,14 +159,19 @@ def axis_conversion(from_forward='Y', from_up='Z', to_forward='Y', to_up='Z'): raise Exception("invalid axis arguments passed, " "can't use up/forward on the same axis.") - value = reduce(int.__or__, (_axis_convert_num[a] << (i * 3) for i, a in enumerate((from_forward, from_up, to_forward, to_up)))) + value = reduce(int.__or__, (_axis_convert_num[a] << (i * 3) + for i, a in enumerate((from_forward, + from_up, + to_forward, + to_up, + )))) for i, axis_lut in enumerate(_axis_convert_lut): if value in axis_lut: return Matrix(_axis_convert_matrix[i]) assert(0) - + def axis_conversion_ensure(operator, forward_attr, up_attr): """ Function to ensure an operator has valid axis conversion settings, intended @@ -174,9 +179,9 @@ def axis_conversion_ensure(operator, forward_attr, up_attr): :arg operator: the operator to access axis attributes from. :type operator: :class:`Operator` - :arg forward_attr: + :arg forward_attr: attribute storing the forward axis :type forward_attr: string - :arg up_attr: the directory the *filepath* will be referenced from (normally the export path). + :arg up_attr: attribute storing the up axis :type up_attr: string :return: True if the value was modified. :rtype: boolean @@ -184,9 +189,9 @@ def axis_conversion_ensure(operator, forward_attr, up_attr): def validate(axis_forward, axis_up): if axis_forward[-1] == axis_up[-1]: axis_up = axis_up[0:-1] + 'XYZ'[('XYZ'.index(axis_up[-1]) + 1) % 3] - + return axis_forward, axis_up - + change = False axis = getattr(operator, forward_attr), getattr(operator, up_attr) @@ -203,7 +208,7 @@ def axis_conversion_ensure(operator, forward_attr, up_attr): # return a tuple (free, object list), free is True if memory should be freed later with free_derived_objects() def create_derived_objects(scene, ob): - if ob.parent and ob.parent.dupli_type != 'NONE': + if ob.parent and ob.parent.dupli_type in {'VERTS', 'FACES'}: return False, None if ob.dupli_type != 'NONE': diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py index c42d3d0236a..ecd620ff2c9 100644 --- a/release/scripts/modules/bpy_extras/mesh_utils.py +++ b/release/scripts/modules/bpy_extras/mesh_utils.py @@ -170,8 +170,8 @@ def edge_loops_from_faces(mesh, faces=None, seams=()): # from knowing the last 2, look for th next. ed_adj = edges[context_loop[-1]] if len(ed_adj) != 2: - - if other_dir and flipped == False: # the original edge had 2 other edges + # the original edge had 2 other edges + if other_dir and flipped == False: flipped = True # only flip the list once context_loop.reverse() ed_adj[:] = [] @@ -259,13 +259,15 @@ def edge_loops_from_edges(mesh, edges=None): def ngon_tesselate(from_data, indices, fix_loops=True): ''' - Takes a polyline of indices (fgon) - and returns a list of face indicie lists. - Designed to be used for importers that need indices for an fgon to create from existing verts. + Takes a polyline of indices (fgon) and returns a list of face + indicie lists. Designed to be used for importers that need indices for an + fgon to create from existing verts. from_data: either a mesh, or a list/tuple of vectors. - indices: a list of indices to use this list is the ordered closed polyline to fill, and can be a subset of the data given. - fix_loops: If this is enabled polylines that use loops to make multiple polylines are delt with correctly. + indices: a list of indices to use this list is the ordered closed polyline + to fill, and can be a subset of the data given. + fix_loops: If this is enabled polylines that use loops to make multiple + polylines are delt with correctly. ''' from mathutils.geometry import tesselate_polygon @@ -276,7 +278,8 @@ def ngon_tesselate(from_data, indices, fix_loops=True): return [] def mlen(co): - return abs(co[0]) + abs(co[1]) + abs(co[2]) # manhatten length of a vector, faster then length + # manhatten length of a vector, faster then length + return abs(co[0]) + abs(co[1]) + abs(co[2]) def vert_treplet(v, i): return v, vector_to_tuple(v, 6), i, mlen(v) @@ -296,7 +299,8 @@ def ngon_tesselate(from_data, indices, fix_loops=True): else: verts = [from_data.vertices[i].co for ii, i in enumerate(indices)] - for i in range(len(verts) - 1, 0, -1): # same as reversed(xrange(1, len(verts))): + # same as reversed(range(1, len(verts))): + for i in range(len(verts) - 1, 0, -1): if verts[i][1] == verts[i - 1][0]: verts.pop(i - 1) @@ -304,14 +308,16 @@ def ngon_tesselate(from_data, indices, fix_loops=True): else: ''' - Seperate this loop into multiple loops be finding edges that are used twice - This is used by lightwave LWO files a lot + Seperate this loop into multiple loops be finding edges that are + used twice. This is used by lightwave LWO files a lot ''' if type(from_data) in (tuple, list): - verts = [vert_treplet(Vector(from_data[i]), ii) for ii, i in enumerate(indices)] + verts = [vert_treplet(Vector(from_data[i]), ii) + for ii, i in enumerate(indices)] else: - verts = [vert_treplet(from_data.vertices[i].co, ii) for ii, i in enumerate(indices)] + verts = [vert_treplet(from_data.vertices[i].co, ii) + for ii, i in enumerate(indices)] edges = [(i, i - 1) for i in range(len(verts))] if edges: diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index 0f0491e249e..627a1530fe1 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -16,7 +16,7 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# import bpy from bpy.props import StringProperty, BoolProperty, EnumProperty, IntProperty @@ -54,21 +54,35 @@ class SelectPattern(bpy.types.Operator): else: pattern_match = (lambda a, b: fnmatch.fnmatchcase(a.upper(), b.upper())) - + is_ebone = False obj = context.object if obj and obj.mode == 'POSE': items = obj.data.bones + if not self.extend: + bpy.ops.pose.select_all(action='DESELECT') elif obj and obj.type == 'ARMATURE' and obj.mode == 'EDIT': items = obj.data.edit_bones + if not self.extend: + bpy.ops.armature.select_all(action='DESELECT') + is_ebone = True else: items = context.visible_objects + if not self.extend: + bpy.ops.object.select_all(action='DESELECT') # Can be pose bones or objects for item in items: if pattern_match(item.name, self.pattern): item.select = True - elif not self.extend: - item.select = False + + # hrmf, perhaps there should be a utility function for this. + if is_ebone: + item.select_head = True + item.select_tail = True + if item.use_connect: + item_parent = item.parent + if item_parent is not None: + item_parent.select_tail = True return {'FINISHED'} @@ -107,7 +121,8 @@ class SelectCamera(bpy.types.Operator): class SelectHierarchy(bpy.types.Operator): - '''Select object relative to the active objects position in the hierarchy''' + '''Select object relative to the active objects position''' \ + '''in the hierarchy''' bl_idname = "object.select_hierarchy" bl_label = "Select Hierarchy" bl_options = {'REGISTER', 'UNDO'} @@ -332,53 +347,90 @@ class ShapeTransfer(bpy.types.Operator): ob_add_shape(ob_other, orig_key_name) # editing the final coords, only list that stores wrapped coords - target_shape_coords = [v.co for v in ob_other.active_shape_key.data] + target_shape_coords = [v.co for v in + ob_other.active_shape_key.data] median_coords = [[] for i in range(len(me.vertices))] # Method 1, edge if mode == 'OFFSET': for i, vert_cos in enumerate(median_coords): - vert_cos.append(target_coords[i] + (orig_shape_coords[i] - orig_coords[i])) + vert_cos.append(target_coords[i] + + (orig_shape_coords[i] - orig_coords[i])) elif mode == 'RELATIVE_FACE': for face in me.faces: i1, i2, i3, i4 = face.vertices_raw if i4 != 0: pt = barycentric_transform(orig_shape_coords[i1], - orig_coords[i4], orig_coords[i1], orig_coords[i2], - target_coords[i4], target_coords[i1], target_coords[i2]) + orig_coords[i4], + orig_coords[i1], + orig_coords[i2], + target_coords[i4], + target_coords[i1], + target_coords[i2], + ) median_coords[i1].append(pt) pt = barycentric_transform(orig_shape_coords[i2], - orig_coords[i1], orig_coords[i2], orig_coords[i3], - target_coords[i1], target_coords[i2], target_coords[i3]) + orig_coords[i1], + orig_coords[i2], + orig_coords[i3], + target_coords[i1], + target_coords[i2], + target_coords[i3], + ) median_coords[i2].append(pt) pt = barycentric_transform(orig_shape_coords[i3], - orig_coords[i2], orig_coords[i3], orig_coords[i4], - target_coords[i2], target_coords[i3], target_coords[i4]) + orig_coords[i2], + orig_coords[i3], + orig_coords[i4], + target_coords[i2], + target_coords[i3], + target_coords[i4], + ) median_coords[i3].append(pt) pt = barycentric_transform(orig_shape_coords[i4], - orig_coords[i3], orig_coords[i4], orig_coords[i1], - target_coords[i3], target_coords[i4], target_coords[i1]) + orig_coords[i3], + orig_coords[i4], + orig_coords[i1], + target_coords[i3], + target_coords[i4], + target_coords[i1], + ) median_coords[i4].append(pt) else: pt = barycentric_transform(orig_shape_coords[i1], - orig_coords[i3], orig_coords[i1], orig_coords[i2], - target_coords[i3], target_coords[i1], target_coords[i2]) + orig_coords[i3], + orig_coords[i1], + orig_coords[i2], + target_coords[i3], + target_coords[i1], + target_coords[i2], + ) median_coords[i1].append(pt) pt = barycentric_transform(orig_shape_coords[i2], - orig_coords[i1], orig_coords[i2], orig_coords[i3], - target_coords[i1], target_coords[i2], target_coords[i3]) + orig_coords[i1], + orig_coords[i2], + orig_coords[i3], + target_coords[i1], + target_coords[i2], + target_coords[i3], + ) median_coords[i2].append(pt) pt = barycentric_transform(orig_shape_coords[i3], - orig_coords[i2], orig_coords[i3], orig_coords[i1], - target_coords[i2], target_coords[i3], target_coords[i1]) + orig_coords[i2], + orig_coords[i3], + orig_coords[i1], + target_coords[i2], + target_coords[i3], + target_coords[i1], + ) median_coords[i3].append(pt) elif mode == 'RELATIVE_EDGE': @@ -416,7 +468,8 @@ class ShapeTransfer(bpy.types.Operator): if use_clamp: # clamp to the same movement as the original # breaks copy between different scaled meshes. - len_from = (orig_shape_coords[i] - orig_coords[i]).length + len_from = (orig_shape_coords[i] - + orig_coords[i]).length ofs = co - target_coords[i] ofs.length = len_from co = target_coords[i] + ofs @@ -498,7 +551,13 @@ class JoinUVs(bpy.types.Operator): mesh_other.tag = True if len(mesh_other.faces) != len_faces: - self.report({'WARNING'}, "Object: %s, Mesh: '%s' has %d faces, expected %d\n" % (obj_other.name, mesh_other.name, len(mesh_other.faces), len_faces)) + self.report({'WARNING'}, "Object: %s, Mesh: " + "'%s' has %d faces, expected %d\n" + % (obj_other.name, + mesh_other.name, + len(mesh_other.faces), + len_faces), + ) else: uv_other = mesh_other.uv_textures.active if not uv_other: diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py index 8fe606399b4..7fd769c40c9 100644 --- a/release/scripts/startup/bl_operators/object_align.py +++ b/release/scripts/startup/bl_operators/object_align.py @@ -21,6 +21,7 @@ import bpy from mathutils import Vector + def GlobalBB_LQ(bb_world): # Initialize the variables with the 8th vertex @@ -33,7 +34,7 @@ def GlobalBB_LQ(bb_world): ) # Test against the other 7 verts - for i in range (7): + for i in range(7): # X Range val = bb_world[i][0] @@ -61,6 +62,7 @@ def GlobalBB_LQ(bb_world): return (Vector((left, front, up)), Vector((right, back, down))) + def GlobalBB_HQ(obj): matrix_world = obj.matrix_world.copy() @@ -80,7 +82,7 @@ def GlobalBB_HQ(obj): ) # Test against all other verts - for i in range (len(verts)-1): + for i in range(len(verts) - 1): vco = matrix_world * verts[i].co diff --git a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py index 4b3435eacbe..a38d817d738 100644 --- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py +++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py @@ -110,6 +110,31 @@ class PlayRenderedAnim(bpy.types.Operator): cmd = [player_path] # extra options, fps controls etc. if preset == 'BLENDER24': + # ----------------------------------------------------------------- + # Check blender is not 2.5x until it supports playback again + try: + process = subprocess.Popen([player_path, '--version'], + stdout=subprocess.PIPE, + ) + except: + # ignore and allow the main execution to catch the problem. + process = None + + if process is not None: + process.wait() + out = process.stdout.read() + process.stdout.close() + out_split = out.strip().split() + if out_split[0] == b'Blender': + if not out_split[1].startswith(b'2.4'): + self.report({'ERROR'}, + "Blender %s doesn't support playback: %r" % + (out_split[1].decode(), player_path)) + return {'CANCELLED'} + del out, out_split + del process + # ----------------------------------------------------------------- + opts = ["-a", "-f", str(rd.fps), str(rd.fps_base), file] cmd.extend(opts) elif preset == 'DJV': @@ -146,5 +171,6 @@ class PlayRenderedAnim(bpy.types.Operator): self.report({'ERROR'}, "Couldn't run external animation player with command " "%r\n%s" % (" ".join(cmd), str(e))) + return {'CANCELLED'} return {'FINISHED'} diff --git a/release/scripts/startup/bl_ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py index 5a0d327f90d..42b0af7eaf5 100644 --- a/release/scripts/startup/bl_ui/properties_data_empty.py +++ b/release/scripts/startup/bl_ui/properties_data_empty.py @@ -41,11 +41,9 @@ class DATA_PT_empty(DataButtonsPanel, bpy.types.Panel): layout.prop(ob, "empty_draw_type", text="Display") if ob.empty_draw_type == 'IMAGE': - # layout.template_image(ob, "data", None) layout.template_ID(ob, "data", open="image.open", unlink="image.unlink") - row = layout.row(align=True) - row.prop(ob, "color", text="Transparency", index=3, slider=True) + layout.prop(ob, "color", text="Transparency", index=3, slider=True) row = layout.row(align=True) row.prop(ob, "empty_image_offset", text="Offset X", index=0) row.prop(ob, "empty_image_offset", text="Offset Y", index=1) diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index ce6d0990f05..0a4d0b60514 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -394,6 +394,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel): col.operator("object.multires_higher_levels_delete", text="Delete Higher") col.operator("object.multires_reshape", text="Reshape") col.operator("object.multires_base_apply", text="Apply Base") + col.prop(md, "use_subsurf_uv") col.prop(md, "show_only_control_edges") layout.separator() diff --git a/release/scripts/startup/bl_ui/properties_world.py b/release/scripts/startup/bl_ui/properties_world.py index 0272667e754..c577af01374 100644 --- a/release/scripts/startup/bl_ui/properties_world.py +++ b/release/scripts/startup/bl_ui/properties_world.py @@ -93,7 +93,7 @@ class WORLD_PT_world(WorldButtonsPanel, bpy.types.Panel): col.prop(world, "zenith_color") col.active = world.use_sky_blend row.column().prop(world, "ambient_color") - + row = layout.row() row.prop(world, "exposure") row.prop(world, "color_range") diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index cda37b3119a..f66cee7f431 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -60,7 +60,7 @@ class INFO_HT_header(bpy.types.Header): layout.template_running_jobs() layout.template_reports_banner() - + row = layout.row(align=True) row.operator("wm.splash", text="", icon='BLENDER', emboss=False) row.label(text=scene.statistics()) diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 831fd359782..2088d8798f2 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -135,7 +135,7 @@ class NODE_MT_node(bpy.types.Menu): layout.operator("transform.resize") layout.separator() - + layout.operator("node.duplicate_move") layout.operator("node.delete") layout.operator("node.delete_reconnect") diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index f35ad71202c..933579f5c1e 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1017,7 +1017,6 @@ class USERPREF_PT_addons(bpy.types.Panel): for i in range(4 - tot_row): split.separator() - # Append missing scripts # First collect scripts that are used but have no script file. module_names = {mod.__name__ for mod, info in addons} diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index ee0ca94f54e..f96a758e7ce 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -55,7 +55,7 @@ class VIEW3D_HT_header(bpy.types.Header): row = layout.row() # Contains buttons like Mode, Pivot, Manipulator, Layer, Mesh Select Mode... - row.template_header_3D() + row.template_header_3D() if obj: # Particle edit diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 19c3224f138..91cfd22b3d6 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -58,6 +58,7 @@ def draw_gpencil_tools(context, layout): row = col.row() row.prop(context.tool_settings, "use_grease_pencil_sessions") + # ********** default tools for objectmode **************** class VIEW3D_PT_tools_objectmode(View3DPanel, bpy.types.Panel): diff --git a/release/scripts/templates/batch_export.py b/release/scripts/templates/batch_export.py index aa0e601725b..45d26f4b525 100644 --- a/release/scripts/templates/batch_export.py +++ b/release/scripts/templates/batch_export.py @@ -26,7 +26,7 @@ for obj in selection: # bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True) obj.select = False - + print("written:", fn) for obj in selection: diff --git a/release/scripts/templates/ui_menu.py b/release/scripts/templates/ui_menu.py index d3923b5b083..d3c94b86809 100644 --- a/release/scripts/templates/ui_menu.py +++ b/release/scripts/templates/ui_menu.py @@ -26,8 +26,8 @@ class CustomMenu(bpy.types.Menu): def draw_item(self, context): - layout = self.layout - layout.menu(CustomMenu.bl_idname) + layout = self.layout + layout.menu(CustomMenu.bl_idname) def register(): diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 3abfa05e1fd..662c872b7f1 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1287,6 +1287,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang); offset += sizeof(float)*4; } + (void)offset; } curface++; if(mface->v4) { @@ -1327,6 +1328,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int (*setMaterial)(int, vo QUATCOPY((float *)&varray[elementsize*curface*3+offset+elementsize*2], tang); offset += sizeof(float)*4; } + (void)offset; } curface++; i++; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 45faba8439c..8d19322c0db 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -466,7 +466,6 @@ static void layerInterp_mdisps(void **sources, float *UNUSED(weights), MDisps tris[2]; int vindex[4] = {0}; - S = 0; for(i = 0; i < 2; i++) for(y = 0; y < 4; y++) for(x = 0; x < 4; x++) diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 962c7fd5e86..3f01c55e935 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -550,7 +550,7 @@ Material *material_pop_id(ID *id, int index) Material **mat; if(index + 1 != (*totcol)) - memmove((*matar), (*matar) + 1, sizeof(void *) * ((*totcol) - (index + 1))); + memmove((*matar)+index, (*matar)+(index+1), sizeof(void *) * ((*totcol) - (index + 1))); (*totcol)--; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index d833c184274..88a670ecb22 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -465,12 +465,13 @@ static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lv return multires_dm_create_from_derived(&mmd, 1, dm, ob, 0, 0); } -static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple, int optimal) +static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple, int optimal, int plain_uv) { SubsurfModifierData smd= {{NULL}}; smd.levels = smd.renderLevels = lvl; - smd.flags |= eSubsurfModifierFlag_SubsurfUv; + if(!plain_uv) + smd.flags |= eSubsurfModifierFlag_SubsurfUv; if(simple) smd.subdivType = ME_SIMPLE_SUBSURF; if(optimal) @@ -591,7 +592,7 @@ void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob) /* subdivide the mesh to highest level without displacements */ cddm = CDDM_from_mesh(me, NULL); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - origdm = subsurf_dm_create_local(ob, cddm, totlvl, 0, 0); + origdm = subsurf_dm_create_local(ob, cddm, totlvl, 0, 0, mmd->flags & eMultiresModifierFlag_PlainUv); cddm->release(cddm); /* calc disps */ @@ -626,7 +627,7 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl /* create subsurf DM from original mesh at high level */ cddm = CDDM_from_mesh(me, NULL); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0); + highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv); /* create multires DM from original mesh at low level */ lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple); @@ -830,7 +831,7 @@ static void multiresModifier_update(DerivedMesh *dm) else cddm = CDDM_from_mesh(me, NULL); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple, 0); + highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv); /* create multires DM from original mesh and displacements */ lowdm = multires_dm_create_local(ob, cddm, lvl, totlvl, mmd->simple); @@ -884,7 +885,7 @@ static void multiresModifier_update(DerivedMesh *dm) else cddm = CDDM_from_mesh(me, NULL); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0); + subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv); cddm->release(cddm); multiresModifier_disp_run(dm, me, 1, 0, subdm->getGridData(subdm), mmd->totlvl); @@ -927,7 +928,8 @@ DerivedMesh *multires_dm_create_from_derived(MultiresModifierData *mmd, int loca return dm; result = subsurf_dm_create_local(ob, dm, lvl, - mmd->simple, mmd->flags & eMultiresModifierFlag_ControlEdges); + mmd->simple, mmd->flags & eMultiresModifierFlag_ControlEdges, + mmd->flags & eMultiresModifierFlag_PlainUv); if(!local_mmd) { ccgdm = (CCGDerivedMesh*)result; @@ -1633,7 +1635,7 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) MEM_freeN(vertCos); /* scaled ccgDM for tangent space of object with applied scale */ - dm= subsurf_dm_create_local(ob, cddm, high_mmd.totlvl, high_mmd.simple, 0); + dm= subsurf_dm_create_local(ob, cddm, high_mmd.totlvl, high_mmd.simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv); cddm->release(cddm); /*numGrids= dm->getNumGrids(dm);*/ /*UNUSED*/ diff --git a/source/blender/collada/MaterialExporter.cpp b/source/blender/collada/MaterialExporter.cpp index a44fa6802f2..9d29177578d 100644 --- a/source/blender/collada/MaterialExporter.cpp +++ b/source/blender/collada/MaterialExporter.cpp @@ -37,12 +37,36 @@ MaterialsExporter::MaterialsExporter(COLLADASW::StreamWriter *sw): COLLADASW::Li void MaterialsExporter::exportMaterials(Scene *sce, bool export_selected) { - openLibrary(); + if(hasMaterials(sce)) { + openLibrary(); - MaterialFunctor mf; - mf.forEachMaterialInScene(sce, *this, export_selected); + MaterialFunctor mf; + mf.forEachMaterialInScene(sce, *this, export_selected); - closeLibrary(); + closeLibrary(); + } +} + + +bool MaterialsExporter::hasMaterials(Scene *sce) +{ + Base *base = (Base *)sce->base.first; + + while(base) { + Object *ob= base->object; + int a; + for(a = 0; a < ob->totcol; a++) + { + Material *ma = give_current_material(ob, a+1); + + // no material, but check all of the slots + if (!ma) continue; + + return true; + } + base= base->next; + } + return false; } void MaterialsExporter::operator()(Material *ma, Object *ob) diff --git a/source/blender/collada/MaterialExporter.h b/source/blender/collada/MaterialExporter.h index 0a7a276d857..c080e4b0596 100644 --- a/source/blender/collada/MaterialExporter.h +++ b/source/blender/collada/MaterialExporter.h @@ -51,6 +51,9 @@ public: MaterialsExporter(COLLADASW::StreamWriter *sw); void exportMaterials(Scene *sce, bool export_selected); void operator()(Material *ma, Object *ob); + +private: + bool hasMaterials(Scene *sce); }; // used in forEachMaterialInScene diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 5f405a5f51e..cdc839e084a 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1115,10 +1115,11 @@ void init_userdef_do_versions(void) } if(U.pad_rot_angle==0) U.pad_rot_angle= 15; - - if(U.flag & USER_CUSTOM_RANGE) - vDM_ColorBand_store(&U.coba_weight); /* signal for derivedmesh to use colorband */ - + + /* signal for derivedmesh to use colorband */ + /* run incase this was on and is now off in the user prefs [#28096] */ + vDM_ColorBand_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight):NULL); + if (bmain->versionfile <= 191) { strcpy(U.plugtexdir, U.textudir); strcpy(U.sounddir, "/"); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 4230a43d2ec..c719f749582 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -1101,7 +1101,7 @@ void NODE_OT_backimage_move(wmOperatorType *ot) ot->cancel= snode_bg_viewmove_cancel; /* flags */ - ot->flag= OPTYPE_BLOCKING; + ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; } static int backimage_zoom(bContext *C, wmOperator *op) @@ -2216,6 +2216,12 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event) /* we might need to remove a link */ if(in_out==SOCK_OUT) node_remove_extra_links(snode, link->tosock, link); + + /* when linking to group outputs, update the socket type */ + /* XXX this should all be part of a generic update system */ + if (!link->tonode) { + link->tosock->type = link->fromsock->type; + } } else if (outside_group_rect(snode) && (link->tonode || link->fromnode)) { /* automatically add new group socket */ diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 36e334990cb..b105b2507ab 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -101,6 +101,8 @@ static void sequencer_generic_props__internal(wmOperatorType *ot, int flag) RNA_def_boolean(ot->srna, "replace_sel", 1, "Replace Selection", "replace the current selection"); + RNA_def_boolean(ot->srna, "overlap", 0, "Allow Overlap", "Don't correct overlap on new sequence strips"); + if(flag & SEQPROP_FILES) RNA_def_collection_runtime(ot->srna, "files", &RNA_OperatorFileListElement, "Files", ""); } @@ -250,7 +252,11 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op) seq_active_set(scene, seq); seq->flag |= SELECT; } - + + if(RNA_boolean_get(op->ptr, "overlap") == FALSE) { + if(seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq, scene); + } + WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -303,8 +309,9 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad Scene *scene= CTX_data_scene(C); /* only for sound */ Editing *ed= seq_give_editing(scene, TRUE); SeqLoadInfo seq_load; - /* Sequence *seq; */ /* UNUSED */ + Sequence *seq; int tot_files; + const short overlap= RNA_boolean_get(op->ptr, "overlap"); seq_load_operator_info(&seq_load, op); @@ -324,13 +331,21 @@ static int sequencer_add_generic_strip_exec(bContext *C, wmOperator *op, SeqLoad RNA_string_get(&itemptr, "name", file_only); BLI_join_dirfile(seq_load.path, sizeof(seq_load.path), dir_only, file_only); - /* seq= */ seq_load_func(C, ed->seqbasep, &seq_load); + seq= seq_load_func(C, ed->seqbasep, &seq_load); + + if(overlap == FALSE) { + if(seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq, scene); + } } RNA_END; } else { /* single file */ - /* seq= */ seq_load_func(C, ed->seqbasep, &seq_load); + seq= seq_load_func(C, ed->seqbasep, &seq_load); + + if(overlap == FALSE) { + if(seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq, scene); + } } if (seq_load.tot_success==0) { @@ -506,7 +521,11 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) /* last active name */ strncpy(ed->act_imagedir, strip->dir, FILE_MAXDIR-1); - + + if(RNA_boolean_get(op->ptr, "overlap") == FALSE) { + if(seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq, scene); + } + WM_event_add_notifier(C, NC_SCENE|ND_SEQUENCER, scene); return OPERATOR_FINISHED; @@ -656,7 +675,9 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op) } } - if(seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq, scene); + if(RNA_boolean_get(op->ptr, "overlap") == FALSE) { + if(seq_test_overlap(ed->seqbasep, seq)) shuffle_seq(ed->seqbasep, seq, scene); + } update_changed_seq_and_deps(scene, seq, 1, 1); /* runs calc_sequence */ diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 933d90ebbf2..ca89670dedb 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -467,14 +467,17 @@ void initSnapping(TransInfo *t, wmOperator *op) /* use scene defaults only when transform is modal */ else if (t->flag & T_MODAL) { - if (ts->snap_flag & SCE_SNAP) { - t->modifiers |= MOD_SNAP; - } + if(ELEM(t->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) + { + if (ts->snap_flag & SCE_SNAP) { + t->modifiers |= MOD_SNAP; + } - t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) == SCE_SNAP_ROTATE); - t->tsnap.project = ((t->settings->snap_flag & SCE_SNAP_PROJECT) == SCE_SNAP_PROJECT); - t->tsnap.snap_self = !((t->settings->snap_flag & SCE_SNAP_NO_SELF) == SCE_SNAP_NO_SELF); - t->tsnap.peel = ((t->settings->snap_flag & SCE_SNAP_PROJECT) == SCE_SNAP_PROJECT); + t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) == SCE_SNAP_ROTATE); + t->tsnap.project = ((t->settings->snap_flag & SCE_SNAP_PROJECT) == SCE_SNAP_PROJECT); + t->tsnap.snap_self = !((t->settings->snap_flag & SCE_SNAP_NO_SELF) == SCE_SNAP_NO_SELF); + t->tsnap.peel = ((t->settings->snap_flag & SCE_SNAP_PROJECT) == SCE_SNAP_PROJECT); + } } t->tsnap.target = snap_target; @@ -1944,9 +1947,9 @@ static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], Gea int i; float asp[3] = {1.0f, 1.0f, 1.0f}; // TODO: Remove hard coded limit here (3) - if(max_index > 3) { + if(max_index > 2) { printf("applyGrid: invalid index %d, clamping\n", max_index); - max_index= 3; + max_index= 2; } // Early bailing out if no need to snap diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 806c70d841f..274884000db 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1371,9 +1371,6 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) mat->obcolalpha = 1; GPU_link(mat, "shade_alpha_obcolor", shr->combined, GPU_builtin(GPU_OBCOLOR), &shr->combined); } - - if(gpu_do_color_management(mat)) - GPU_link(mat, "linearrgb_to_srgb", shr->combined, &shr->combined); } static GPUNodeLink *GPU_blender_material(GPUMaterial *mat, Material *ma) @@ -1408,6 +1405,10 @@ GPUMaterial *GPU_material_from_blender(Scene *scene, Material *ma) GPU_material_output_link(mat, outlink); } + if(gpu_do_color_management(mat)) + if(mat->outlink) + GPU_link(mat, "linearrgb_to_srgb", mat->outlink, &mat->outlink); + /*if(!GPU_material_construct_end(mat)) { GPU_material_free(mat); mat= NULL; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index d2d8e014015..3787675f339 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -624,6 +624,7 @@ typedef struct MultiresModifierData { typedef enum { eMultiresModifierFlag_ControlEdges = (1<<0), + eMultiresModifierFlag_PlainUv = (1<<1), } MultiresModifierFlag; typedef struct FluidsimModifierData { diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index dcf2400b9ba..e71be8c153e 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -1364,13 +1364,13 @@ static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerR if(prop->noteflag) WM_main_add_notifier(prop->noteflag, ptr->id.data); } - else { + + if(!is_rna || (prop->flag & PROP_IDPROPERTY)) { /* WARNING! This is so property drivers update the display! * not especially nice */ DAG_id_tag_update(ptr->id.data, OB_RECALC_OB|OB_RECALC_DATA|OB_RECALC_TIME); WM_main_add_notifier(NC_WINDOW, NULL); } - } /* must keep in sync with 'rna_property_update' diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index d2c1b862fee..ba655915fb6 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -805,6 +805,11 @@ static void rna_def_modifier_multires(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flags", eMultiresModifierFlag_ControlEdges); RNA_def_property_ui_text(prop, "Optimal Display", "Skip drawing/rendering of interior subdivided edges"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + + prop= RNA_def_property(srna, "use_subsurf_uv", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flags", eMultiresModifierFlag_PlainUv); + RNA_def_property_ui_text(prop, "Subdivide UVs", "Use subsurf to subdivide UVs"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); } static void rna_def_modifier_lattice(BlenderRNA *brna) diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 7dd865984b3..e22829577f4 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -155,7 +155,8 @@ void WM_init(bContext *C, int argc, const char **argv) BPY_python_start(argc, argv); BPY_driver_reset(); - BPY_app_handlers_reset(); + BPY_app_handlers_reset(); /* causes addon callbacks to be freed [#28068], + * but this is actually what we want. */ BPY_modules_load_user(C); #else (void)argc; /* unused */ diff --git a/source/creator/creator.c b/source/creator/creator.c index fddd6d286db..36209dbda78 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -434,9 +434,12 @@ static int playback_mode(int UNUSED(argc), const char **UNUSED(argv), void *UNUS { /* not if -b was given first */ if (G.background == 0) { - -// XXX playanim(argc, argv); /* not the same argc and argv as before */ +#if 0 /* TODO, bring player back? */ + playanim(argc, argv); /* not the same argc and argv as before */ +#else + fprintf(stderr, "Playback mode not supported in blender 2.5x\n"); exit(0); +#endif } return -2; diff --git a/source/tests/check_deprecated.py b/source/tests/check_deprecated.py index 11c7ce646b9..856e1f6d272 100644 --- a/source/tests/check_deprecated.py +++ b/source/tests/check_deprecated.py @@ -28,6 +28,7 @@ SKIP_DIRS = ("extern", os.path.join("source", "tests"), # not this dir ) + def is_c_header(filename): ext = splitext(filename)[1] return (ext in (".h", ".hpp", ".hxx")) @@ -41,13 +42,16 @@ def is_c(filename): def is_c_any(filename): return is_c(filename) or is_c_header(filename) + def is_py(filename): ext = splitext(filename)[1] return (ext == ".py") + def is_source_any(filename): return is_c_any(filename) or is_py(filename) + def source_list(path, filename_check=None): for dirpath, dirnames, filenames in os.walk(path): @@ -67,7 +71,7 @@ def deprecations(): /* *DEPRECATED* 2011/7/17 bgl.Buffer.list info text */ Or... - + # *DEPRECATED* 2010/12/22 some.py.func more info */ """ @@ -105,12 +109,12 @@ def deprecations(): if len(data) != 3: print(" poorly formatting line:\n" " %r:%d\n" - " %s"% + " %s" % (fn, i + 1, l) ) else: data = datetime.datetime(*tuple([int(w) for w in data])) - + deprecations_ls.append((data, (fn, i + 1), info)) except: print("Error file - %r:%d" % (fn, i + 1)) @@ -123,10 +127,11 @@ def deprecations(): return deprecations_ls + def main(): import datetime now = datetime.datetime.now()\ - + deps = deprecations() print("\nAll deprecations...") -- cgit v1.2.3 From 6b987910e43ff5f91512a3c361ea3141590d4e45 Mon Sep 17 00:00:00 2001 From: Alexander Kuznetsov Date: Fri, 29 Jul 2011 20:21:37 +0000 Subject: Patch [#27925] by Andrew Cox and me Modifier key sticks after Alt-tab on Win32 --- intern/ghost/intern/GHOST_SystemWin32.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index ace6cc0e0cf..4f0e7d8e604 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -989,11 +989,16 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * procedure of the top-level window being activated. If the windows use different input queues, * the message is sent asynchronously, so the window is activated immediately. */ + { + GHOST_ModifierKeys modifiers; + modifiers.clear(); + system->storeModifierKeys(modifiers); event = processWindowEvent(LOWORD(wParam) ? GHOST_kEventWindowActivate : GHOST_kEventWindowDeactivate, window); /* WARNING: Let DefWindowProc handle WM_ACTIVATE, otherwise WM_MOUSEWHEEL will not be dispatched to OUR active window if we minimize one of OUR windows. */ lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); break; + } case WM_PAINT: /* An application sends the WM_PAINT message when the system or another application * makes a request to paint a portion of an application's window. The message is sent -- cgit v1.2.3 From 99997ccd181a6fcae5288fbd67a8eb32c71e9e3e Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Fri, 29 Jul 2011 20:46:30 +0000 Subject: Fix for [#28117] Diffuse reflection IPO curve not imported correctly from 2.49b files --- source/blender/blenkernel/intern/ipo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 4f921f005f4..2ae6f533bd4 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -518,7 +518,7 @@ static const char *material_adrcodes_to_paths (int adrcode, int *array_index) return "alpha"; case MA_REF: - return "diffuse_reflection"; + return "diffuse_intensity"; case MA_EMIT: return "emit"; -- cgit v1.2.3 From 6a27da310c61b3372d565060506221a5afb9fe43 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Fri, 29 Jul 2011 20:59:46 +0000 Subject: While looking at the bug report, found some more issues... This is the result of RNA renaming at it's glance. ;-) --- source/blender/blenkernel/intern/ipo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 2ae6f533bd4..104ce2b3b32 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -527,7 +527,7 @@ static const char *material_adrcodes_to_paths (int adrcode, int *array_index) return "ambient"; case MA_SPEC: - return "specular_reflection"; + return "specular_intensity"; case MA_HARD: return "specular_hardness"; @@ -551,13 +551,13 @@ static const char *material_adrcodes_to_paths (int adrcode, int *array_index) return "raytrace_mirror.fresnel"; case MA_FRESMIRI: - return "raytrace_mirror.fresnel_fac"; + return "raytrace_mirror.fresnel_factor"; case MA_FRESTRA: return "raytrace_transparency.fresnel"; case MA_FRESTRAI: - return "raytrace_transparency.fresnel_fac"; + return "raytrace_transparency.fresnel_factor"; case MA_ADD: return "halo.add"; -- cgit v1.2.3 From aec91c0cf530d637a15c95cf1e4d0e27a7660a4c Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Fri, 29 Jul 2011 21:07:51 +0000 Subject: ndof sensitivity operator follows power curve and respects min/max --- source/blender/windowmanager/intern/wm_operators.c | 37 +++++++++++++++++----- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 1b48e36d2b7..d813fd913ab 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3435,16 +3435,36 @@ static void WM_OT_memory_statistics(wmOperatorType *ot) static int wm_ndof_sensitivity_exec(bContext *UNUSED(C), wmOperator *op) { - float change = 0.1f; - int dir = 1; - if(RNA_boolean_get(op->ptr, "decrease")) - dir = -1; + const float min = 0.25f, max = 4.f; // TODO: get these from RNA property + float change; + float sensitivity = U.ndof_sensitivity; + if(RNA_boolean_get(op->ptr, "fast")) - change = 1.0f; + change = 0.5f; // 50% change + else + change = 0.1f; // 10% + if(RNA_boolean_get(op->ptr, "decrease")) + { + sensitivity -= sensitivity * change; + if (sensitivity < min) + sensitivity = min; + } + else + { + sensitivity += sensitivity * change; + if (sensitivity > max) + sensitivity = max; + } + + if (sensitivity != U.ndof_sensitivity) + { + U.ndof_sensitivity = sensitivity; + printf("new sensitivity: %f\n", U.ndof_sensitivity); + } + else + printf("same sensitivity: %f\n", U.ndof_sensitivity); - U.ndof_sensitivity += (dir * change); - printf("new sensitivity: %f\n", U.ndof_sensitivity); return OPERATOR_FINISHED; } @@ -3457,8 +3477,9 @@ static void WM_OT_ndof_sensitivity_change(wmOperatorType *ot) ot->exec= wm_ndof_sensitivity_exec; RNA_def_boolean(ot->srna, "decrease", 1, "Decrease NDOF sensitivity", "If true then action decreases NDOF sensitivity instead of increasing"); - RNA_def_boolean(ot->srna, "fast", 0, "Fast NDOF sensitivity change", "If true then action change with factor 1.0, otherwise 0.1"); + RNA_def_boolean(ot->srna, "fast", 0, "Fast NDOF sensitivity change", "If true then sensitivity changes 50%, otherwise 10%"); } + /* ******************************************************* */ /* called on initialize WM_exit() */ void wm_operatortype_free(void) -- cgit v1.2.3 From 632f59c7bce051f359e57bf872fb624cb6643d87 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 30 Jul 2011 05:23:10 +0000 Subject: improved visual rotation guide --- source/blender/editors/space_view3d/view3d_draw.c | 51 +++++++++++++++++++---- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 2b863bf794c..6e3f6549ba3 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -681,7 +681,7 @@ static void draw_rotation_guide(RegionView3D *rv3d) float o[3]; // center of rotation float end[3]; // endpoints for drawing - float color[4] = {1,1,0,1}; // bright yellow so it stands out during development + float color[4] = {0.f ,0.4235f, 1.f, 1.f}; // bright blue so it matches device LEDs negate_v3_v3(o, rv3d->ofs); @@ -699,7 +699,7 @@ static void draw_rotation_guide(RegionView3D *rv3d) mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale); glBegin(GL_LINE_STRIP); - color[3] = 0; // more transparent toward the ends + color[3] = 0.f; // more transparent toward the ends glColor4fv(color); add_v3_v3v3(end, o, scaled_axis); glVertex3fv(end); @@ -711,16 +711,52 @@ static void draw_rotation_guide(RegionView3D *rv3d) glColor4fv(color); glVertex3fv(o); - color[3] = 0; + color[3] = 0.f; glColor4fv(color); sub_v3_v3v3(end, o, scaled_axis); glVertex3fv(end); glEnd(); - color[3] = 1; // solid dot + // -- draw ring around rotation center -- + { + #define ROT_AXIS_DETAIL 13 + const float s = 0.05f * scale; + const float step = 2.f * M_PI / ROT_AXIS_DETAIL; + float angle; + int i; + + float q[4]; // rotate ring so it's perpendicular to axis + const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f; + if (!upright) + { + const float up[3] = {0.f, 0.f, 1.f}; + float vis_angle, vis_axis[3]; + + cross_v3_v3v3(vis_axis, up, rv3d->rot_axis); + vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis)); + axis_angle_to_quat(q, vis_axis, vis_angle); + } + + color[3] = 0.25f; // somewhat faint + glColor4fv(color); + glBegin(GL_LINE_LOOP); + for (i = 0, angle = 0.f; i < ROT_AXIS_DETAIL; ++i, angle += step) + { + float p[3] = { s * cosf(angle), s * sinf(angle), 0.f }; + + if (!upright) + mul_qt_v3(q, p); + + add_v3_v3(p, o); + glVertex3fv(p); + } + glEnd(); + } + + color[3] = 1.f; // solid dot } else - color[3] = 0.5; // see-through dot + color[3] = 0.5f; // see-through dot // -- draw rotation center -- glColor4fv(color); @@ -2680,10 +2716,9 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) BDR_drawSketch(C); } -//#if 0 // not yet... - if (U.ndof_flag & NDOF_SHOW_GUIDE) + if ((U.ndof_flag & NDOF_SHOW_GUIDE) && (rv3d->viewlock != RV3D_LOCKED) && (rv3d->persp != RV3D_CAMOB)) + // TODO: draw something else (but not this) during fly mode draw_rotation_guide(rv3d); -//#endif ED_region_pixelspace(ar); -- cgit v1.2.3 From f66ec41b6a3b74f079c19494357c268e1ab39e85 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 30 Jul 2011 09:24:10 +0000 Subject: quiet some compiler warnings & fix possible (but unlikely) crash. also added GPLv2+ header to resources.c. --- source/blender/blenlib/intern/BLI_args.c | 6 ++++-- source/blender/editors/curve/editcurve.c | 15 ++++++++------ source/blender/editors/interface/interface_anim.c | 24 +++++++++++++++++++++++ source/blender/editors/interface/resources.c | 7 ++++--- source/blender/editors/object/object_relations.c | 6 +++--- 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/source/blender/blenlib/intern/BLI_args.c b/source/blender/blenlib/intern/BLI_args.c index 7bc93a3d3a0..5f31565d65b 100644 --- a/source/blender/blenlib/intern/BLI_args.c +++ b/source/blender/blenlib/intern/BLI_args.c @@ -290,8 +290,10 @@ void BLI_argsParse(struct bArgs *ba, int pass, BA_ArgCallback default_cb, void * } i += retval; } else if (retval == -1){ - if (a->key->pass != -1) - ba->passes[i] = pass; + if (a) { + if (a->key->pass != -1) + ba->passes[i] = pass; + } break; } } diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 06d88b16fa8..8b9477adf92 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -6544,12 +6544,15 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob) BLI_assert(!"invalid nurbs type"); return NULL; } - - /* always do: */ - nu->flag |= CU_SMOOTH; - - test2DNurb(nu); - + + BLI_assert(nu != NULL); + + if(nu) { /* should always be set */ + nu->flag |= CU_SMOOTH; + + test2DNurb(nu); + } + return nu; } diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 75e7ee701a2..03003173e20 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -1,3 +1,27 @@ +/* + * $Id: + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + /** \file blender/editors/interface/interface_anim.c * \ingroup edinterface */ diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 56ef5e9e8cc..2b4003c7af0 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1,6 +1,3 @@ -/** \file blender/editors/interface/resources.c - * \ingroup edinterface - */ /* * $Id$ * @@ -33,6 +30,10 @@ * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ +/** \file blender/editors/interface/resources.c + * \ingroup edinterface + */ + #include #include #include diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index f21241b6e7a..0fb7cf8b640 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1096,7 +1096,7 @@ static int move_to_layer_exec(bContext *C, wmOperator *op) Scene *scene= CTX_data_scene(C); View3D *v3d= CTX_wm_view3d(C); unsigned int lay, local; - int islamp= 0; + /* int islamp= 0; */ /* UNUSED */ lay= move_to_layer_init(C, op); lay &= 0xFFFFFF; @@ -1112,7 +1112,7 @@ static int move_to_layer_exec(bContext *C, wmOperator *op) base->object->lay= lay; base->object->flag &= ~SELECT; base->flag &= ~SELECT; - if(base->object->type==OB_LAMP) islamp= 1; + /* if(base->object->type==OB_LAMP) islamp= 1; */ } CTX_DATA_END; } @@ -1124,7 +1124,7 @@ static int move_to_layer_exec(bContext *C, wmOperator *op) local= base->lay & 0xFF000000; base->lay= lay + local; base->object->lay= lay; - if(base->object->type==OB_LAMP) islamp= 1; + /* if(base->object->type==OB_LAMP) islamp= 1; */ } CTX_DATA_END; } -- cgit v1.2.3 From 681b26a48ef5f83c2f0941707324b76d57c77f68 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sat, 30 Jul 2011 10:14:50 +0000 Subject: Bugfix #28109 Old issue with OSX Cocoa code: shift+scrollwheel should send a 'horizontal wheel' event to Blender. Blender only recognizes scroll events in general though. The old code then just didn't send an event at all, not passing on shift+scrolls. Now the scroll event is sent anyway, relying on Blender's keymapping to define what to do with shift+scroll. This fixes things like shift+scroll to scale ListBox widgets. --- intern/ghost/intern/GHOST_SystemCocoa.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index bb3d6e3aee3..5c88523d406 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -1560,6 +1560,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr) GHOST_TInt32 delta; double deltaF = [event deltaY]; + + if (deltaF == 0.0) deltaF = [event deltaX]; // make blender decide if it's horizontal scroll if (deltaF == 0.0) break; //discard trackpad delta=0 events delta = deltaF > 0.0 ? 1 : -1; -- cgit v1.2.3 From d163ce55953bd04b42c2c79f6729e47228c01a9a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 30 Jul 2011 13:18:04 +0000 Subject: bpy fix for crash/assert on running dir() on a non collection property + some other minor corrections. --- source/blender/editors/transform/transform.c | 2 +- source/blender/makesrna/intern/rna_wm_api.c | 2 +- source/blender/python/intern/bpy_rna.c | 10 +++++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index eea77e36f7c..59e9e681e2b 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -4659,7 +4659,7 @@ static int createSlideVerts(TransInfo *t) #define EDGE_SLIDE_MIN 30 if (len_squared_v2v2(start, end) < (EDGE_SLIDE_MIN * EDGE_SLIDE_MIN)) { if(ABS(start[0]-end[0]) + ABS(start[1]-end[1]) < 4.0f) { - /* even more exceptional case, points are ontop of eachother */ + /* even more exceptional case, points are ontop of each other */ end[0]= start[0]; end[1]= start[1] + EDGE_SLIDE_MIN; } diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index e250cc84aa3..d44b68950f7 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -205,7 +205,7 @@ void RNA_api_operator(StructRNA *srna) /* check */ func= RNA_def_function(srna, "check", NULL); - RNA_def_function_ui_description(func, "Check the operator settings."); + RNA_def_function_ui_description(func, "Check the operator settings, return True to signal a change to redraw."); RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); parm= RNA_def_pointer(func, "context", "Context", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL); diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 6e1b9c807f3..2dcfe3731c7 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -3262,11 +3262,15 @@ static PyObject *pyrna_prop_dir(BPy_PropertyRNA *self) * */ ret= PyList_New(0); - if (!BPy_PropertyRNA_CheckExact(self)) + if (!BPy_PropertyRNA_CheckExact(self)) { pyrna_dir_members_py(ret, (PyObject *)self); + } - if(RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) - pyrna_dir_members_rna(ret, &r_ptr); + if(RNA_property_type(self->prop) == PROP_COLLECTION) { + if(RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { + pyrna_dir_members_rna(ret, &r_ptr); + } + } return ret; } -- cgit v1.2.3 From 805a169f7065222ce047d950c55b585b36bc4b24 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sat, 30 Jul 2011 15:45:27 +0000 Subject: Bugfix #28121 Linked Library objects or object->data should not allow to go to sculptmode. Also cleaned up mode menu with invalid entries then. --- source/blender/editors/screen/screen_ops.c | 2 +- source/blender/editors/space_view3d/view3d_header.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 68326edfb11..1410331700f 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -301,7 +301,7 @@ int ED_operator_object_active_editable(bContext *C) int ED_operator_object_active_editable_mesh(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW) && ob->type == OB_MESH); + return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW) && ob->type == OB_MESH && !(((ID *)ob->data)->lib)); } int ED_operator_object_active_editable_font(bContext *C) diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index ae80a554e08..5b95ae63e56 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -280,7 +280,8 @@ static char *view3d_modeselect_pup(Scene *scene) str += sprintf(str, formatstr, "Object Mode", OB_MODE_OBJECT, ICON_OBJECT_DATA); - if(ob==NULL) return string; + if(ob==NULL || ob->data==NULL) return string; + if(ob->id.lib || ((ID *)ob->data)->lib) return string; /* if active object is editable */ if ( ((ob->type == OB_MESH) -- cgit v1.2.3 From 6e788c37df2d5209d66bcf7e3d19bd08cd583667 Mon Sep 17 00:00:00 2001 From: Alexander Kuznetsov Date: Sat, 30 Jul 2011 19:09:34 +0000 Subject: Hides console on win32 even if python path is 2 or more lines Adding tlhelp32.h header --- intern/ghost/intern/GHOST_SystemWin32.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 4f0e7d8e604..95b3456ce3b 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -55,6 +55,7 @@ #define _WIN32_IE 0x0501 #include #include +#include // win64 doesn't define GWL_USERDATA #ifdef WIN32 @@ -1242,8 +1243,32 @@ int GHOST_SystemWin32::toggleConsole(int action) { case 3: //hide if no console { - CONSOLE_SCREEN_BUFFER_INFO csbi = {{0}}; - if(!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi) || csbi.dwCursorPosition.X || csbi.dwCursorPosition.Y>1) + DWORD sp = GetCurrentProcessId(); + HANDLE ptree = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + PROCESSENTRY32 e = {0}; e.dwSize = sizeof(PROCESSENTRY32); + + if( Process32First(ptree, &e)) { + do { //Searches for Blender's PROCESSENTRY32 + if (e.th32ProcessID == sp) { + sp = e.th32ParentProcessID; + Process32First(ptree, &e); + do { //Got parent id, searches for its PROCESSENTRY32 + if (e.th32ProcessID == sp) { + if(strcmp("explorer.exe",e.szExeFile)==0) + { //If explorer, hide cmd + ShowWindow(GetConsoleWindow(),SW_HIDE); + m_consoleStatus = 0; + } + break; + } + + } while( Process32Next(ptree, &e)); + break; + } + } while( Process32Next(ptree, &e)); + } + + CloseHandle(ptree); break; } case 0: //hide -- cgit v1.2.3 From dfc661565a4c4d1d4caa3872fb5d7936fb1f0fd8 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Sat, 30 Jul 2011 23:16:22 +0000 Subject: patch [#27909] Added constants in bge.constraints by Solano Felicio (solano) + some changes in rst I named all the BGE modules with their actual names (e.g. Rasterizer, Video Texture, ...). so in the API index.html page they look more like the other Blender modules. I did the same for the bgl module. For bge.constraints this patch exposes the constants values for debug mode and createConstraints (they were hardcoded innts before). + making all the "todo" and #comments into rst comments (.. comments) Thanks Solano, it's great to get help to those tasks :) --- doc/python_api/rst/bge.constraints.rst | 236 +++++++++++++++++---- doc/python_api/rst/bge.events.rst | 2 +- doc/python_api/rst/bge.logic.rst | 2 +- doc/python_api/rst/bge.render.rst | 2 +- doc/python_api/rst/bge.texture.rst | 6 +- doc/python_api/rst/bge.types.rst | 2 +- doc/python_api/rst/bgl.rst | 2 +- .../gameengine/Ketsji/KX_PyConstraintBinding.cpp | 30 ++- 8 files changed, 230 insertions(+), 52 deletions(-) diff --git a/doc/python_api/rst/bge.constraints.rst b/doc/python_api/rst/bge.constraints.rst index 882bbc39b9f..2e7bc2daed4 100644 --- a/doc/python_api/rst/bge.constraints.rst +++ b/doc/python_api/rst/bge.constraints.rst @@ -1,28 +1,47 @@ -Game Engine bge.constraints Module +Physics Constraints (bge.constraints) ================================== -.. note:: - This documentation is still very weak, and needs some help! - -.. function:: createConstraint([obj1, [obj2, [restLength, [restitution, [damping]]]]]) +.. function:: createConstraint(physicsid, physicsid2, constrainttype, [pivotX, pivotY, pivotZ, [axisX, axisY, axisZ, [flag]]]]) Creates a constraint. - :arg obj1: first object on Constraint - :type obj1: :class:'bge.types.KX_GameObject' #I think, there is no error when I use one + :arg physicsid: the physics id of the first object in constraint + :type physicsid: int - :arg obj2: second object on Constraint - :type obj2: :class:'bge.types.KX_GameObject' #too + :arg physicsid2: the physics id of the second object in constraint + :type physicsid2: int - :arg restLength: #to be filled - :type restLength: float + :arg constrainttype: the type of the constraint. The constraint types are: - :arg restitution: #to be filled - :type restitution: float + - :class:`POINTTOPOINT_CONSTRAINT` + - :class:`LINEHINGE_CONSTRAINT` + - :class:`ANGULAR_CONSTRAINT` + - :class:`CONETWIST_CONSTRAINT` + - :class:`VEHICLE_CONSTRAINT` - :arg damping: #to be filled - :type damping: float + :type constrainttype: int + + :arg pivotX: pivot X position + :type pivotX: float + + :arg pivotY: pivot Y position + :type pivotY: float + + :arg pivotZ: pivot Z position + :type pivotZ: float + + :arg axisX: X axis + :type axisX: float + + :arg axisY: Y axis + :type axisY: float + + :arg axisZ: Z axis + :type axisZ: float + + :arg flag: .. to do + :type flag: int .. attribute:: error @@ -49,7 +68,7 @@ Game Engine bge.constraints Module :type constraintId: int :return: a vehicle constraint object. - :rtype: :class:'KX_VehicleWrapper' + :rtype: :class:`bge.types.KX_VehicleWrapper` .. function:: removeConstraint(constraintId) @@ -60,10 +79,10 @@ Game Engine bge.constraints Module .. function:: setCcdMode(ccdMode) - ..note:: + .. note:: Very experimental, not recommended - Sets the CCD mode in the Physics Environment. + Sets the CCD (Continous Colision Detection) mode in the Physics Environment. :arg ccdMode: The new CCD mode. :type ccdMode: int @@ -73,21 +92,21 @@ Game Engine bge.constraints Module .. note:: Reasonable default is 0.02 (if units are meters) - Sets the contact breaking treshold in the Physics Environment. + Sets tresholds to do with contact point management. :arg breakingTreshold: The new contact breaking treshold. :type breakingTreshold: float .. function:: setDeactivationAngularTreshold(angularTreshold) - Sets the deactivation angular treshold. + Sets the angular velocity treshold. :arg angularTreshold: New deactivation angular treshold. :type angularTreshold: float .. function:: setDeactivationLinearTreshold(linearTreshold) - Sets the deactivation linear treshold. + Sets the linear velocity treshold. :arg linearTreshold: New deactivation linear treshold. :type linearTreshold: float @@ -104,21 +123,20 @@ Game Engine bge.constraints Module Sets the debug mode. Debug modes: - - No debug: 0 - - Draw wireframe: 1 - - Draw Aabb: 2 #What's Aabb? - - Draw freatures text: 4 - - Draw contact points: 8 - - No deactivation: 16 - - No help text: 32 - - Draw text: 64 - - Profile timings: 128 - - Enable sat comparision: 256 - - Disable Bullet LCP: 512 - - Enable CCD: 1024 - - Draw Constraints: #(1 << 11) = ? - - Draw Constraint Limits: #(1 << 12) = ? - - Fast Wireframe: #(1 << 13) = ? + - :class:`DBG_NODEBUG` + - :class:`DBG_DRAWWIREFRAME` + - :class:`DBG_DRAWAABB` + - :class:`DBG_DRAWFREATURESTEXT` + - :class:`DBG_DRAWCONTACTPOINTS` + - :class:`DBG_NOHELPTEXT` + - :class:`DBG_DRAWTEXT` + - :class:`DBG_PROFILETIMINGS` + - :class:`DBG_ENABLESATCOMPARISION` + - :class:`DBG_DISABLEBULLETLCP` + - :class:`DBG_ENABLECCD` + - :class:`DBG_DRAWCONSTRAINTS` + - :class:`DBG_DRAWCONSTRAINTLIMITS` + - :class:`DBG_FASTWIREFRAME` :arg mode: The new debug mode. :type mode: int @@ -138,7 +156,10 @@ Game Engine bge.constraints Module .. function:: setLinearAirDamping(damping) - Not implemented. + .. note:: + Not implemented. + + Sets the linear air damping for rigidbodies. .. function:: setNumIterations(numiter) @@ -156,10 +177,10 @@ Game Engine bge.constraints Module .. function:: setSolverDamping(damping) - ..note:: + .. note:: Very experimental, not recommended - Sets the solver damping. + Sets the damper constant of a penalty based solver. :arg damping: New damping for the solver. :type damping: float @@ -169,7 +190,7 @@ Game Engine bge.constraints Module .. note:: Very experimental, not recommended - Sets the solver tau. + Sets the spring constant of a penalty based solver. :arg tau: New tau for the solver. :type tau: float @@ -189,7 +210,7 @@ Game Engine bge.constraints Module .. note:: Very experimental, not recommended - Sets the sor constant. + Sets the successive overrelaxation constant. :arg sor: New sor value. :type sor: float @@ -197,3 +218,136 @@ Game Engine bge.constraints Module .. function:: setUseEpa(epa) Not implemented. + +.. data:: DBG_NODEBUG + + .. note:: + Debug mode to be used with function :class:`setDebugMode` + + No debug. + +.. data:: DBG_DRAWWIREFRAME + + .. note:: + Debug mode to be used with function :class:`setDebugMode` + + Draw wireframe in debug. + +.. data:: DBG_DRAWAABB + + .. note:: + Debug mode to be used with function :class:`setDebugMode` + + Draw Axis Aligned Bounding Box in debug. + +.. data:: DBG_DRAWFREATURESTEXT + + .. note:: + Debug mode to be used with function :class:`setDebugMode` + + Draw freatures text in debug. + +.. data:: DBG_DRAWCONTACTPOINTS + + .. note:: + Debug mode to be used with function :class:`setDebugMode` + + Draw contact points in debug. + +.. data:: DBG_NOHELPTEXT + + .. note:: + Debug mode to be used with function :class:`setDebugMode` + + Debug without help text. + +.. data:: DBG_DRAWTEXT + + .. note:: + Debug mode to be used with function :class:`setDebugMode` + + Draw text in debug. + +.. data:: DBG_PROFILETIMINGS + + .. note:: + Debug mode to be used with function :class:`setDebugMode` + + Draw profile timings in debug. + +.. data:: DBG_ENABLESATCOMPARISION + + .. note:: + Debug mode to be used with function :class:`setDebugMode` + + Enable sat comparision in debug. + +.. data:: DBG_DISABLEBULLETLCP + + .. note:: + Debug mode to be used with function :class:`setDebugMode` + + Disable Bullet LCP. + +.. data:: DBG_ENABLECCD + + .. note:: + Debug mode to be used with function :class:`setDebugMode` + + Enable Continous Colision Detection in debug. + +.. data:: DBG_DRAWCONSTRAINTS + + .. note:: + Debug mode to be used with function :class:`setDebugMode` + + Draw constraints in debug. + +.. data:: DBG_DRAWCONSTRAINTLIMITS + + .. note:: + Debug mode to be used with function :class:`setDebugMode` + + Draw constraint limits in debug. + +.. data:: DBG_FASTWIREFRAME + + .. note:: + Debug mode to be used with function :class:`setDebugMode` + + Draw a fast wireframe in debug. + +.. data:: POINTTOPOINT_CONSTRAINT + + .. note:: + Constraint type to be used with function :class:`createConstraint` + + .. to do + +.. data:: LINEHINGE_CONSTRAINT + + .. note:: + Constraint type to be used with function :class:`createConstraint` + + .. to do + +.. data:: ANGULAR_CONSTRAINT + + .. note:: + Constraint type to be used with function :class:`createConstraint` + + .. to do + +.. data:: CONETWIST_CONSTRAINT + + .. note:: + Constraint type to be used with function :class:`createConstraint` + + .. to do + +.. data:: VEHICLE_CONSTRAINT + + .. note:: + Constraint type to be used with function :class:`createConstraint` + + .. to do diff --git a/doc/python_api/rst/bge.events.rst b/doc/python_api/rst/bge.events.rst index cc76ecded85..f6f465d0cd3 100644 --- a/doc/python_api/rst/bge.events.rst +++ b/doc/python_api/rst/bge.events.rst @@ -1,5 +1,5 @@ -Game Engine bge.events Module +Game Keys (bge.events) ============================= ***** diff --git a/doc/python_api/rst/bge.logic.rst b/doc/python_api/rst/bge.logic.rst index f7163ea928e..53a2362b8d9 100644 --- a/doc/python_api/rst/bge.logic.rst +++ b/doc/python_api/rst/bge.logic.rst @@ -1,5 +1,5 @@ -Game Engine bge.logic Module +Game Logic (bge.logic) ============================ ***** Intro diff --git a/doc/python_api/rst/bge.render.rst b/doc/python_api/rst/bge.render.rst index 9f17455601b..f56b3d619ad 100644 --- a/doc/python_api/rst/bge.render.rst +++ b/doc/python_api/rst/bge.render.rst @@ -1,5 +1,5 @@ -Game Engine bge.render Module +Rasterizer (bge.render) ============================= ***** diff --git a/doc/python_api/rst/bge.texture.rst b/doc/python_api/rst/bge.texture.rst index 996f79a313a..53de315fa75 100644 --- a/doc/python_api/rst/bge.texture.rst +++ b/doc/python_api/rst/bge.texture.rst @@ -1,11 +1,7 @@ -Game Engine bge.texture Module +Video Texture (bge.texture) ============================== -.. note:: - This documentation is still very weak, and needs some help! Right now they are mostly a collection - of the docstrings found in the bge.texture source code + some random places filled with text. - ***** Intro ***** diff --git a/doc/python_api/rst/bge.types.rst b/doc/python_api/rst/bge.types.rst index e42b362c771..1e9e1cca58e 100644 --- a/doc/python_api/rst/bge.types.rst +++ b/doc/python_api/rst/bge.types.rst @@ -1,5 +1,5 @@ -Game Engine bge.types Module +Game Types (bge.types) ============================= .. module:: bge.types diff --git a/doc/python_api/rst/bgl.rst b/doc/python_api/rst/bgl.rst index 76b7442f2c5..ef15d31f43e 100644 --- a/doc/python_api/rst/bgl.rst +++ b/doc/python_api/rst/bgl.rst @@ -1,5 +1,5 @@ -bgl module (OpenGL wrapper) +OpenGL Wrapper (bgl) =========================== .. module:: bgl diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 12024657149..843dbe21995 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -38,12 +38,18 @@ #include "KX_PhysicsObjectWrapper.h" #include "PHY_IPhysicsController.h" #include "PHY_IVehicle.h" +#include "PHY_DynamicTypes.h" #include "MT_Matrix3x3.h" #include "PyObjectPlus.h" +#include "LinearMath/btIDebugDraw.h" + #ifdef WITH_PYTHON +// macro copied from KX_PythonInit.cpp +#define KX_MACRO_addTypesToDict(dict, name, name2) PyDict_SetItemString(dict, #name, item=PyLong_FromSsize_t(name2)); Py_DECREF(item) + // nasty glob variable to connect scripting language // if there is a better way (without global), please do so! static PHY_IPhysicsEnvironment* g_CurrentActivePhysicsEnvironment = NULL; @@ -662,6 +668,7 @@ PyObject* initPythonConstraintBinding() PyObject* ErrorObject; PyObject* m; PyObject* d; + PyObject* item; /* Use existing module where possible * be careful not to init any runtime vars after this */ @@ -683,7 +690,28 @@ PyObject* initPythonConstraintBinding() PyDict_SetItemString(d, "error", ErrorObject); Py_DECREF(ErrorObject); - // XXXX Add constants here + //Debug Modes constants to be used with setDebugMode() python function + KX_MACRO_addTypesToDict(d, DBG_NODEBUG, btIDebugDraw::DBG_NoDebug); + KX_MACRO_addTypesToDict(d, DBG_DRAWWIREFRAME, btIDebugDraw::DBG_DrawWireframe); + KX_MACRO_addTypesToDict(d, DBG_DRAWAABB, btIDebugDraw::DBG_DrawAabb); + KX_MACRO_addTypesToDict(d, DBG_DRAWFREATURESTEXT, btIDebugDraw::DBG_DrawFeaturesText); + KX_MACRO_addTypesToDict(d, DBG_DRAWCONTACTPOINTS, btIDebugDraw::DBG_DrawContactPoints); + KX_MACRO_addTypesToDict(d, DBG_NOHELPTEXT, btIDebugDraw::DBG_NoHelpText); + KX_MACRO_addTypesToDict(d, DBG_DRAWTEXT, btIDebugDraw::DBG_DrawText); + KX_MACRO_addTypesToDict(d, DBG_PROFILETIMINGS, btIDebugDraw::DBG_ProfileTimings); + KX_MACRO_addTypesToDict(d, DBG_ENABLESATCOMPARISION, btIDebugDraw::DBG_EnableSatComparison); + KX_MACRO_addTypesToDict(d, DBG_DISABLEBULLETLCP, btIDebugDraw::DBG_DisableBulletLCP); + KX_MACRO_addTypesToDict(d, DBG_ENABLECDD, btIDebugDraw::DBG_EnableCCD); + KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTS, btIDebugDraw::DBG_DrawConstraints); + KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTLIMITS, btIDebugDraw::DBG_DrawConstraintLimits); + KX_MACRO_addTypesToDict(d, DBG_FASTWIREFRAME, btIDebugDraw::DBG_FastWireframe); + + //Constraint types to be used with createConstraint() python function + KX_MACRO_addTypesToDict(d, POINTTOPOINT_CONSTRAINT, PHY_POINT2POINT_CONSTRAINT); + KX_MACRO_addTypesToDict(d, LINEHINGE_CONSTRAINT, PHY_LINEHINGE_CONSTRAINT); + KX_MACRO_addTypesToDict(d, ANGULAR_CONSTRAINT, PHY_ANGULAR_CONSTRAINT); + KX_MACRO_addTypesToDict(d, CONETWIST_CONSTRAINT, PHY_CONE_TWIST_CONSTRAINT); + KX_MACRO_addTypesToDict(d, VEHICLE_CONSTRAINT, PHY_VEHICLE_CONSTRAINT); // Check for errors if (PyErr_Occurred()) -- cgit v1.2.3 From 601eb684208eb3f5e8025b81be30817b87daeb98 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 31 Jul 2011 02:03:21 +0000 Subject: Added SkinNode DNA and customdata. --- source/blender/blenkernel/intern/customdata.c | 21 ++++++++++++++++----- source/blender/makesdna/DNA_customdata_types.h | 4 +++- source/blender/makesdna/DNA_meshdata_types.h | 5 +++++ 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 8d19322c0db..1f18c78d070 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -805,7 +805,15 @@ static void layerDefault_mcol(void *data, int count) mcol[i] = default_mcol; } - +static void layerDefault_skin(void *data, int count) +{ + SkinNode *n = data; + int i; + + for(i = 0; i < count; i++) { + n[i].radius = 1; + } +} static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL}, @@ -843,7 +851,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { layerSwap_mcol, layerDefault_mcol}, {sizeof(MCol)*4, "MCol", 4, "TexturedCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, - {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL} + {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + {sizeof(SkinNode), "SkinNode", 1, "Skin", NULL, NULL, NULL, NULL, layerDefault_skin} }; static const char *LAYERTYPENAMES[CD_NUMTYPES] = { @@ -851,7 +860,7 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = { /* 5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags", /* 10-14 */ "CDMFloatProperty", "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", /* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDisps", - /* 20-23 */"CDWeightMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco" + /* 20-24 */ "CDWeightMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco", "CDSkinNode" }; const CustomDataMask CD_MASK_BAREMESH = @@ -859,10 +868,12 @@ const CustomDataMask CD_MASK_BAREMESH = const CustomDataMask CD_MASK_MESH = CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | - CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS; + CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS | + CD_MASK_SKIN_NODE; const CustomDataMask CD_MASK_EDITMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | - CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS; + CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS | + CD_MASK_SKIN_NODE; const CustomDataMask CD_MASK_DERIVEDMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_CLOTH_ORCO | diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index cdfcf465c6c..061e9460956 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -92,7 +92,8 @@ typedef struct CustomData { #define CD_ID_MCOL 21 #define CD_TEXTURE_MCOL 22 #define CD_CLOTH_ORCO 23 -#define CD_NUMTYPES 24 +#define CD_SKIN_NODE 24 +#define CD_NUMTYPES 25 /* Bits for CustomDataMask */ #define CD_MASK_MVERT (1 << CD_MVERT) @@ -117,6 +118,7 @@ typedef struct CustomData { #define CD_MASK_MDISPS (1 << CD_MDISPS) #define CD_MASK_WEIGHT_MCOL (1 << CD_WEIGHT_MCOL) #define CD_MASK_CLOTH_ORCO (1 << CD_CLOTH_ORCO) +#define CD_MASK_SKIN_NODE (1 << CD_SKIN_NODE) /* CustomData.flag */ diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index e3510b3a25a..a71c4970eb5 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -184,6 +184,11 @@ typedef struct PartialVisibility { unsigned int totface, totedge, totvert, pad; } PartialVisibility; +typedef struct SkinNode { + float radius; + int pad; +} SkinNode; + /* mvert->flag (1=SELECT) */ #define ME_SPHERETEST 2 #define ME_VERT_TMP_TAG 4 -- cgit v1.2.3 From cae05598b1d10a70a0e37f28b6e49a5b5715a30f Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 31 Jul 2011 02:03:28 +0000 Subject: Added DNA and RNA for skin modifier, stubbed in skin modifier functions --- source/blender/makesdna/DNA_modifier_types.h | 14 +++++ source/blender/makesrna/intern/rna_modifier.c | 15 +++++ source/blender/modifiers/CMakeLists.txt | 1 + source/blender/modifiers/MOD_modifiertypes.h | 1 + source/blender/modifiers/intern/MOD_skin.c | 88 +++++++++++++++++++++++++++ source/blender/modifiers/intern/MOD_util.c | 1 + 6 files changed, 120 insertions(+) create mode 100644 source/blender/modifiers/intern/MOD_skin.c diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 3787675f339..483bd339b3d 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -71,6 +71,7 @@ typedef enum ModifierType { eModifierType_Solidify, eModifierType_Screw, eModifierType_Warp, + eModifierType_Skin, NUM_MODIFIER_TYPES } ModifierType; @@ -785,4 +786,17 @@ typedef enum { /* PROP_RANDOM not used */ } WarpModifierFalloff; +typedef enum SkinModifierFlags { + MOD_SKIN_DRAW_SKIN = (1<<0), + MOD_SKIN_DRAW_NODES = (1<<1), +} SkinModifierFlags; + +typedef struct SkinModifierData { + ModifierData modifier; + float threshold; + int subdiv; + int flag; + int pad; +} SkinModifierData; + #endif diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index ba655915fb6..b4a4c593ba9 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -68,6 +68,7 @@ EnumPropertyItem modifier_type_items[] ={ {eModifierType_Solidify, "SOLIDIFY", ICON_MOD_SOLIDIFY, "Solidify", ""}, {eModifierType_Subsurf, "SUBSURF", ICON_MOD_SUBSURF, "Subdivision Surface", ""}, {eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""}, + {eModifierType_Skin, "SKIN", ICON_MOD_ARMATURE, "Skin", ""}, {0, "", 0, "Deform", ""}, {eModifierType_Armature, "ARMATURE", ICON_MOD_ARMATURE, "Armature", ""}, {eModifierType_Cast, "CAST", ICON_MOD_CAST, "Cast", ""}, @@ -183,6 +184,8 @@ static StructRNA* rna_Modifier_refine(struct PointerRNA *ptr) return &RNA_ScrewModifier; case eModifierType_Warp: return &RNA_WarpModifier; + case eModifierType_Skin: + return &RNA_SkinModifier; default: return &RNA_Modifier; } @@ -2412,6 +2415,17 @@ static void rna_def_modifier_screw(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update");*/ } +static void rna_def_modifier_skin(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna= RNA_def_struct(brna, "SkinModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Skin Modifier", "Generate Skin"); + RNA_def_struct_sdna(srna, "SkinModifierData"); + RNA_def_struct_ui_icon(srna, ICON_MOD_ARMATURE); +} + void RNA_def_modifier(BlenderRNA *brna) { StructRNA *srna; @@ -2509,6 +2523,7 @@ void RNA_def_modifier(BlenderRNA *brna) rna_def_modifier_smoke(brna); rna_def_modifier_solidify(brna); rna_def_modifier_screw(brna); + rna_def_modifier_skin(brna); } #endif diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index d1f153265ac..7db03f48631 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -70,6 +70,7 @@ set(SRC intern/MOD_shapekey.c intern/MOD_shrinkwrap.c intern/MOD_simpledeform.c + intern/MOD_skin.c intern/MOD_smoke.c intern/MOD_smooth.c intern/MOD_softbody.c diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h index 4e44a226c64..329037ee210 100644 --- a/source/blender/modifiers/MOD_modifiertypes.h +++ b/source/blender/modifiers/MOD_modifiertypes.h @@ -72,6 +72,7 @@ extern ModifierTypeInfo modifierType_ShapeKey; extern ModifierTypeInfo modifierType_Solidify; extern ModifierTypeInfo modifierType_Screw; extern ModifierTypeInfo modifierType_Warp; +extern ModifierTypeInfo modifierType_Skin; /* MOD_util.c */ void modifier_type_init(ModifierTypeInfo *types[]); diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c new file mode 100644 index 00000000000..adc47f32c9c --- /dev/null +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -0,0 +1,88 @@ +/* +* $Id$ +* +* ***** BEGIN GPL LICENSE BLOCK ***** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* ***** END GPL LICENSE BLOCK ***** +* +*/ + +/** \file blender/modifiers/intern/MOD_skin.c + * \ingroup modifiers + */ + + +#include + +#include "BKE_cdderivedmesh.h" +#include "BKE_modifier.h" + +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" + +#include "MOD_util.h" + +static void initData(ModifierData *md) +{ + SkinModifierData *smd = (SkinModifierData*)md; + + smd->threshold = 0; + smd->subdiv = 1; + smd->flag = MOD_SKIN_DRAW_NODES; +} + +static void copyData(ModifierData *md, ModifierData *target) +{ + SkinModifierData *smd = (SkinModifierData*) md; + SkinModifierData *tsmd = (SkinModifierData*) target; + + tsmd->threshold = smd->threshold; + tsmd->subdiv = smd->subdiv; + tsmd->flag = smd->flag; +} + +static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, + int useRenderParams, int isFinalCalc) +{ + return dm; +} + + +ModifierTypeInfo modifierType_Skin = { + /* name */ "Skin", + /* structName */ "SkinModifierData", + /* structSize */ sizeof(SkinModifierData), + /* type */ eModifierTypeType_Constructive, + /* flags */ eModifierTypeFlag_AcceptsMesh, + + /* copyData */ copyData, + /* deformVerts */ NULL, + /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, + /* deformMatricesEM */ NULL, + /* applyModifier */ applyModifier, + /* applyModifierEM */ NULL, + /* initData */ initData, + /* requiredDataMask */ NULL, + /* freeData */ NULL, + /* isDisabled */ NULL, + /* updateDepgraph */ NULL, + /* dependsOnTime */ NULL, + /* dependsOnNormals */ NULL, + /* foreachObjectLink */ NULL, + /* foreachIDLink */ NULL, +}; diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index e9b835eab81..e823a347ced 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -295,5 +295,6 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(Solidify); INIT_TYPE(Screw); INIT_TYPE(Warp); + INIT_TYPE(Skin); #undef INIT_TYPE } -- cgit v1.2.3 From ccf186017aca1e38b55c51eea919faed122284cf Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 31 Jul 2011 02:03:33 +0000 Subject: Added stub for Skin modifier UI --- release/scripts/startup/bl_ui/properties_data_modifier.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 0a4d0b60514..248c5219fe0 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -736,5 +736,8 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel): col.prop(md, "width", slider=True) col.prop(md, "narrowness", slider=True) + def SKIN(self, layout, ob, md): + pass + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) -- cgit v1.2.3 From cff57b14a122a7925d8fb6aeb0ecd53984fa0c58 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 31 Jul 2011 02:03:39 +0000 Subject: Imported bsphere.c, mostly ifdef'd out for now --- source/blender/blenkernel/CMakeLists.txt | 1 + source/blender/blenkernel/intern/bsphere.c | 1178 +++++++++++++++++++++++++ source/blender/blenkernel/intern/customdata.c | 2 +- 3 files changed, 1180 insertions(+), 1 deletion(-) create mode 100644 source/blender/blenkernel/intern/bsphere.c diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index defcef58463..e549a205325 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -81,6 +81,7 @@ set(SRC intern/boids.c intern/booleanops_mesh.c intern/brush.c + intern/bsphere.c intern/bullet.c intern/bvhutils.c intern/cdderivedmesh.c diff --git a/source/blender/blenkernel/intern/bsphere.c b/source/blender/blenkernel/intern/bsphere.c new file mode 100644 index 00000000000..d8a75f62172 --- /dev/null +++ b/source/blender/blenkernel/intern/bsphere.c @@ -0,0 +1,1178 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2011 by Nicholas Bishop + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" + +#include "BLI_utildefines.h" +#include "BLI_heap.h" +#include "BLI_ghash.h" +#include "BLI_listbase.h" +#include "BLI_math.h" + +#include "BKE_cdderivedmesh.h" +#include "BKE_DerivedMesh.h" +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_subsurf.h" + +#include + +typedef struct Tri { + struct Tri *next, *prev; + unsigned int v[3]; + float no[3]; + float area; + int marked; +} Tri; + +typedef struct Edge { + struct Edge *next, *prev; + unsigned int v[2]; + Tri *tri[2]; +} Edge; + +/* note: a `frame' is four vertices (contiguous within the MVert + array), stored simply as the index of the first vertex */ + +static void create_frame(float frame[4][3], const float co[3], float radius, + const float mat[3][3], float x_offset) +{ + float rx[3], ry[3], rz[3]; + int i; + + mul_v3_v3fl(ry, mat[1], radius); + mul_v3_v3fl(rz, mat[2], radius); + + add_v3_v3v3(frame[3], co, ry); + add_v3_v3v3(frame[3], frame[3], rz); + + sub_v3_v3v3(frame[2], co, ry); + add_v3_v3v3(frame[2], frame[2], rz); + + sub_v3_v3v3(frame[1], co, ry); + sub_v3_v3v3(frame[1], frame[1], rz); + + add_v3_v3v3(frame[0], co, ry); + sub_v3_v3v3(frame[0], frame[0], rz); + + mul_v3_v3fl(rx, mat[0], x_offset); + for(i = 0; i < 4; i++) + add_v3_v3v3(frame[i], frame[i], rx); +} + +static void create_mid_frame(float frame[4][3], + const float co1[3], const float co2[3], + const SkinNode *n1, const SkinNode *n2, + const float mat[3][3]) +{ + create_frame(frame, co1, (n1->radius + n2->radius) / 2, + mat, len_v3v3(co1, co2) / 2); +} + +static void add_face(MFace *mface, int *totface, + int v1, int v2, int v3, int v4) +{ + MFace *f; + + f = &mface[*totface]; + f->v1 = v1; + f->v2 = v2; + f->v3 = v3; + f->v4 = v4 == -1 ? 0 : v4; + if(!v4) { + f->v1 = v3; + f->v2 = v4; + f->v3 = v1; + f->v4 = v2; + } + (*totface)++; +} + +static void connect_frames(MFace *mface, int *totface, int frame1, int frame2) +{ + int i; + + for(i = 0; i < 4; i++) { + add_face(mface, totface, + frame2 + i, + frame2 + (i+1) % 4, + frame1 + (i+1) % 4, + frame1 + i); + } +} + +static Tri *add_triangle(ListBase *tris, MVert *mvert, int v1, int v2, int v3) +{ + Tri *t; + + t = MEM_callocN(sizeof(Tri), "add_triangle.tri"); + t->v[0] = v1; + t->v[1] = v2; + t->v[2] = v3; + BLI_addtail(tris, t); + + normal_tri_v3(t->no, mvert[t->v[0]].co, mvert[t->v[1]].co, mvert[t->v[2]].co); + t->area = area_tri_v3(mvert[t->v[0]].co, mvert[t->v[1]].co, mvert[t->v[2]].co); + + return t; +} + +static int point_tri_side(const Tri *t, MVert *mvert, int v) +{ + float p[3], d; + sub_v3_v3v3(p, mvert[v].co, mvert[t->v[0]].co); + d = dot_v3v3(t->no, p); + if(d < 0) return -1; + else if(d > 0) return 1; + else return 0; +} + +static int mark_v_outside_tris(ListBase *tris, MVert *mvert, int v) +{ + Tri *t; + int outside = 0; + + /* probably there's a much better way to do this */ + for(t = tris->first; t; t = t->next) { + if((t->marked = point_tri_side(t, mvert, v) > 0)) + outside = 1; + } + return outside; +} + +static int edge_match(int e1_0, int e1_1, const unsigned int e2[2]) +{ + /* XXX: maybe isn't necesseary to check both directions? */ + return (e1_0 == e2[0] && e1_1 == e2[1]) || + (e1_0 == e2[1] && e1_1 == e2[0]); +} + +/* returns true if the edge (e1, e2) is already in edges; that edge is + deleted here as well. if not found just returns 0 */ +static int check_for_dup(ListBase *edges, unsigned int e1, unsigned int e2) +{ + Edge *e, *next; + + for(e = edges->first; e; e = next) { + next = e->next; + + if(edge_match(e1, e2, e->v)) { + /* remove the interior edge */ + BLI_freelinkN(edges, e); + return 1; + } + } + + return 0; +} + +static void expand_boundary_edges(ListBase *edges, Tri *t) +{ + Edge *new; + int i; + + /* insert each triangle edge into the boundary list; if any of + its edges are already in there, remove the edge entirely */ + for(i = 0; i < 3; i++) { + if(!check_for_dup(edges, t->v[i], t->v[(i+1)%3])) { + new = MEM_callocN(sizeof(Edge), "Edge"); + new->v[0] = t->v[i]; + new->v[1] = t->v[(i+1)%3]; + BLI_addtail(edges, new); + } + } +} + +static int tri_matches_frame(const Tri *t, int frame) +{ + int i, j, match = 0; + for(i = 0; i < 3; i++) { + for(j = 0; j < 4; j++) { + if(t->v[i] == frame + j) { + match++; + if(match >= 3) + return 1; + } + } + } + return 0; +} + +static void quad_from_tris(const Edge *e, int ndx[4]) +{ + int i, j, opp = -1; + + /* find what the second tri has that the first doesn't */ + for(i = 0; i < 3; i++) { + if(e->tri[1]->v[i] != e->tri[0]->v[0] && + e->tri[1]->v[i] != e->tri[0]->v[1] && + e->tri[1]->v[i] != e->tri[0]->v[2]) { + opp = e->tri[1]->v[i]; + break; + } + } + assert(opp != -1); + + for(i = 0, j = 0; i < 3; i++, j++) { + ndx[j] = e->tri[0]->v[i]; + /* when the triangle edge cuts across our quad-to-be, + throw in the second triangle's vertex */ + if((e->tri[0]->v[i] == e->v[0] || e->tri[0]->v[i] == e->v[1]) && + (e->tri[0]->v[(i+1)%3] == e->v[0] || e->tri[0]->v[(i+1)%3] == e->v[1])) { + j++; + ndx[j] = opp; + } + } +} + +static void add_quad_from_tris(MFace *mface, int *totface, const Edge *e) +{ + int ndx[4]; + + quad_from_tris(e, ndx); + + add_face(mface, totface, ndx[0], ndx[1], ndx[2], ndx[3]); +} + +static GHash *calc_edges(ListBase *tris) +{ + GHash *adj; + ListBase *edges; + Edge *e; + Tri *t; + int i, e1, e2; + + /* XXX: vertex range might be a little funky? so using a + hash here */ + adj = BLI_ghash_new(BLI_ghashutil_inthash, + BLI_ghashutil_intcmp, + "calc_edges adj"); + + for(t = tris->first; t; t = t->next) { + for(i = 0; i < 3; i++) { + e1 = t->v[i]; + e2 = t->v[(i+1)%3]; + assert(e1 != e2); + if(e1 > e2) + SWAP(int, e1, e2); + + edges = BLI_ghash_lookup(adj, SET_INT_IN_POINTER(e1)); + if(!edges) { + edges = MEM_callocN(sizeof(ListBase), + "calc_edges ListBase"); + BLI_ghash_insert(adj, SET_INT_IN_POINTER(e1), edges); + } + + /* find the edge in the adjacency list */ + for(e = edges->first; e; e = e->next) { + assert(e->v[0] == e1); + if(e->v[1] == e2) + break; + } + + /* if not found, create the edge */ + if(!e) { + e = MEM_callocN(sizeof(Edge), "calc_edges Edge"); + e->v[0] = e1; + e->v[1] = e2; + BLI_addtail(edges, e); + } + + /* should never be more than two faces + attached to an edge here */ + assert(!e->tri[0] || !e->tri[1]); + + if(!e->tri[0]) + e->tri[0] = t; + else if(!e->tri[1]) + e->tri[1] = t; + } + } + + return adj; +} + +static int is_quad_symmetric(const MVert *mvert, const Edge *e) +{ + int ndx[4]; + float a[3]; + + quad_from_tris(e, ndx); + + copy_v3_v3(a, mvert[ndx[0]].co); + a[0] = -a[0]; + + if(len_v3v3(a, mvert[ndx[1]].co) < FLT_EPSILON) { + copy_v3_v3(a, mvert[ndx[2]].co); + a[0] = -a[0]; + if(len_v3v3(a, mvert[ndx[3]].co) < FLT_EPSILON) + return 1; + } + else if(len_v3v3(a, mvert[ndx[3]].co) < FLT_EPSILON) { + copy_v3_v3(a, mvert[ndx[2]].co); + a[0] = -a[0]; + if(len_v3v3(a, mvert[ndx[1]].co) < FLT_EPSILON) + return 1; + } + + return 0; +} + +static void output_hull(const MVert *mvert, MFace *mface, int *totface, ListBase *tris) +{ + Heap *heap; + GHash *adj; + GHashIterator *iter; + ListBase *edges; + Edge *e; + Tri *t; + float score; + + heap = BLI_heap_new(); + adj = calc_edges(tris); + + /* unmark all triangles */ + for(t = tris->first; t; t = t->next) + t->marked = 0; + + /* build heap */ + iter = BLI_ghashIterator_new(adj); + while(!BLI_ghashIterator_isDone(iter)) { + edges = BLI_ghashIterator_getValue(iter); + for(e = edges->first; e; e = e->next) { + /* only care if the edge is used by more than + one triangle */ + if(e->tri[0] && e->tri[1]) { + score = (e->tri[0]->area + e->tri[1]->area) * + dot_v3v3(e->tri[0]->no, e->tri[1]->no); + + /* increase score if the triangles + form a symmetric quad */ + if(is_quad_symmetric(mvert, e)) + score *= 10; + + BLI_heap_insert(heap, -score, e); + } + } + + BLI_ghashIterator_step(iter); + } + BLI_ghashIterator_free(iter); + + while(!BLI_heap_empty(heap)) { + e = BLI_heap_popmin(heap); + + /* if both triangles still free, outupt as a quad */ + if(!e->tri[0]->marked && !e->tri[1]->marked) { + add_quad_from_tris(mface, totface, e); + e->tri[0]->marked = 1; + e->tri[1]->marked = 1; + } + } + + /* free edge list */ + iter = BLI_ghashIterator_new(adj); + while(!BLI_ghashIterator_isDone(iter)) { + edges = BLI_ghashIterator_getValue(iter); + BLI_freelistN(edges); + MEM_freeN(edges); + BLI_ghashIterator_step(iter); + } + BLI_ghashIterator_free(iter); + BLI_ghash_free(adj, NULL, NULL); + BLI_heap_free(heap, NULL); + + /* write out any remaining triangles */ + for(t = tris->first; t; t = t->next) { + if(!t->marked) + add_face(mface, totface, t->v[0], t->v[1], t->v[2], -1); + } +} + +/* for vertex `v', find which triangles must be deleted to extend the + hull; find the boundary edges of that hole so that it can be filled + with connections to the new vertex, and update the `tri' list to + delete the marked triangles */ +static void add_point(ListBase *tris, MVert *mvert, int v) +{ + ListBase edges = {NULL, NULL}; + Tri *t, *next; + Edge *e; + + for(t = tris->first; t; t = next) { + next = t->next; + + /* check if triangle is `visible' to v */ + if(t->marked) { + expand_boundary_edges(&edges, t); + /* remove the triangle */ + BLI_freelinkN(tris, t); + } + } + + /* fill hole boundary with triangles to new point */ + for(e = edges.first; e; e = e->next) + add_triangle(tris, mvert, e->v[0], e->v[1], v); + BLI_freelistN(&edges); +} + +static void build_hull(MFace *mface, int *totface, + MVert *mvert, int *frames, int totframe) +{ + ListBase tris = {NULL, NULL}; + Tri *t, *next; + int i, j; + + /* use first frame to make initial degenerate pyramid */ + add_triangle(&tris, mvert, frames[0], frames[0] + 1, frames[0] + 2); + add_triangle(&tris, mvert, frames[0] + 1, frames[0], frames[0] + 3); + add_triangle(&tris, mvert, frames[0] + 2, frames[0] + 1, frames[0] + 3); + add_triangle(&tris, mvert, frames[0], frames[0] + 2, frames[0] + 3); + + for(i = 1; i < totframe; i++) { + for(j = 0; j < 4; j++) { + int v = frames[i] + j; + + /* ignore point already inside hull */ + if(mark_v_outside_tris(&tris, mvert, v)) { + /* expand hull and delete interior triangles */ + add_point(&tris, mvert, v); + } + } + } + + /* remove triangles that would fill the original frames */ + for(t = tris.first; t; t = next) { + next = t->next; + + for(i = 0; i < totframe; i++) { + if(tri_matches_frame(t, frames[i])) { + BLI_freelinkN(&tris, t); + break; + } + } + } + + output_hull(mvert, mface, totface, &tris); + + BLI_freelistN(&tris); +} + +/* test: build hull on origdm */ +#if 0 +static DerivedMesh *test_hull(DerivedMesh *origdm) +{ + DerivedMesh *dm; + MVert *mvert, *origmvert; + MFace *mface; + int *frames; + int totvert = 0, totface = 0, totframe, i; + + /* TODO */ + totface = 2000; + totvert = origdm->getNumVerts(origdm); + dm = CDDM_new(totvert, 0, totface); + + mvert = CDDM_get_verts(dm); + mface = CDDM_get_faces(dm); + + origmvert = CDDM_get_verts(origdm); + for(i = 0; i < totvert; i++) + mvert[i] = origmvert[i]; + + assert(totvert % 4 == 0); + totframe = totvert / 4; + + frames = MEM_callocN(sizeof(int) * totframe, "frames"); + for(i = 0; i < totframe; i++) + frames[i] = i*4; + + totface = 0; + build_hull(mface, &totface, mvert, frames, totframe); + + CDDM_calc_edges(dm); + //CDDM_calc_normals(dm); + + MEM_freeN(frames); + + return dm; +} +#endif + +/* TODO */ +static void calc_edge_mat(float mat[3][3], const float a[3], const float b[3]) +{ + float Z[3] = {0, 0, 1}; + float dot; + + /* x = edge direction */ + sub_v3_v3v3(mat[0], b, a); + normalize_v3(mat[0]); + + dot = dot_v3v3(mat[0], Z); + if(dot > -1 + FLT_EPSILON && dot < 1 - FLT_EPSILON) { + /* y = Z cross x */ + cross_v3_v3v3(mat[1], Z, mat[0]); + normalize_v3(mat[1]); + + /* z = x cross y */ + cross_v3_v3v3(mat[2], mat[0], mat[1]); + normalize_v3(mat[2]); + } + else { + mat[1][0] = 1; + mat[1][1] = 0; + mat[1][2] = 0; + mat[2][0] = 0; + mat[2][1] = 1; + mat[2][2] = 0; + } +} + +/* BMesh paper */ +#if 0 +static float calc_R_sub_i_squared(const BSphereNode *n) +{ + const float alpha = 1.5; + //const float alpha = 1; + const float R_sub_i = n->size[0] * alpha; + return R_sub_i * R_sub_i; +} + +/* equation (2) */ +static float calc_r_squared(const float v[3], const BSphereNode *n) +{ + return len_squared_v3v3(v, n->co); +} + +/* equation (1) */ +static float calc_f_sub_i(const float v[3], const BSphereNode *n) +{ + float r_squared; + float R_sub_i_squared; + + r_squared = calc_r_squared(v, n); + R_sub_i_squared = calc_R_sub_i_squared(n); + + if(r_squared <= R_sub_i_squared) + return powf(1.0f - (r_squared / R_sub_i_squared), 2); + else + return 0; +} + +/* equation (3) */ +static float calc_I(const float x[3], float T, const ListBase *base) +{ + BSphereNode *n; + float a = -T; + + for(n = base->first; n; n = n->next) { + a += calc_I(x, 0, &n->children); + a += calc_f_sub_i(x, n); + } + + //printf("calc_I: %f, %f\n", -T, a); + + return a; +} + +/* kinda my own guess here */ +static void calc_gradient(float g[3], const float x[3], const ListBase *base) +{ + BSphereNode *n; + + for(n = base->first; n; n = n->next) { + float R_sub_i_squared = calc_R_sub_i_squared(n); + float dist = len_v3v3(x, n->co); + float f = calc_f_sub_i(x, n); + float d = 1.0f / R_sub_i_squared; + float tmp[3]; + + /* XXX: other possibilities... */ + if(f > 0) { + sub_v3_v3v3(tmp, x, n->co); + mul_v3_fl(tmp, -4*d * (1 - d * dist)); + + /* not sure if I'm doing this right; intent is + to flip direction when x is `beneath' the + level set */ + if(len_v3v3(x, n->co) > n->size[0]) + negate_v3(tmp); + + add_v3_v3(g, tmp); + } + + calc_gradient(g, x, &n->children); + } +} + +/* equation (5) */ +static float calc_F(const float x[3], const float K[2], float T, const ListBase *base) +{ + float f_of_K; + float I_target; + + /* TODO */ + f_of_K = 1.0f / (1 + fabs(K[0]) + fabs(K[1])); + //f_of_K = 1; + + /* TODO */ + I_target = 0; + + return (calc_I(x, T, base) - I_target) /*TODO: * f_of_K*/; +} + +static float smallest_radius(const ListBase *base) +{ + BSphereNode *n; + float s = FLT_MAX, t; + + for(n = base->first; n; n = n->next) { + if(n->size[0] < s) + s = n->size[0]; + if((t = smallest_radius(&n->children)) < s) + s = t; + } + + return s; +} + +/* equation (7) */ +static float calc_delta_t(float F_max, float k, const ListBase *base, int print) +{ + float min_r_sub_i; + float step; + + min_r_sub_i = smallest_radius(base); + step = min_r_sub_i / powf(2, k); + + if(print) { + printf("min_r: %f, 2^k=%f, step=%f\n", min_r_sub_i, powf(2, k), step); + } + + return step / F_max; +} + +/* equation (6) */ +static float evolve_x(float x[3], const float K[2], float T, + int k, const ListBase *base, int i, float F_max) +{ + float tmp[3], no[3]; + float F, dt; + + F = calc_F(x, K, T, base); + + if(F < FLT_EPSILON) { + //printf("stability reached for ndx=%d\n", i); + return 0; + } + + /* TODO ;-) */ + if(F > F_max) + F_max = F; + + dt = calc_delta_t(F_max, k, base, 0); + + dt = F / 2; + + if(i == 0) + ;//printf("F=%.3f, dt=%.3f\n", F, calc_delta_t(F_max, k, base, 1)); + + zero_v3(no); + calc_gradient(no, x, base); + normalize_v3(no); + negate_v3(no); + + mul_v3_v3fl(tmp, no, F * dt); + add_v3_v3(x, tmp); + + return F_max; +} + +static void bsphere_evolve(MVert *mvert, int totvert, const ListBase *base, + float T, int steps, float subdiv_level) +{ + int i, s; + + for(i = 0; i < totvert; i++) { + float F_max = 0; + /* TODO: for now just doing a constant number of steps */ + for(s = 0; s < steps; s++) { + /* TODO */ + float K[2] = {0, 0}; + + F_max = evolve_x(mvert[i].co, K, T, subdiv_level, base, i, F_max); + } + } +} +#endif + +typedef enum { + START_CAP = 1, + END_CAP = 2, + NODE_BISECT = 4, + CHILD_EDGE_BISECT = 8, + + IN_FRAME = 16, + OUT_FRAME = 32, +} FrameFlag; + +typedef struct { + int totframe; + int outbase; + FrameFlag flag; + float co[0][4][3]; +} Frames; + +static Frames *frames_create(FrameFlag flag) +{ + Frames *frames; + int totframe; + totframe = (!!(flag & START_CAP) + !!(flag & END_CAP) + + !!(flag & NODE_BISECT) + !!(flag & CHILD_EDGE_BISECT)); + assert(totframe); + frames = MEM_callocN(sizeof(Frames) + sizeof(float)*totframe*4*3, + "frames_create.frames"); + frames->totframe = totframe; + frames->flag = flag; + assert((flag & (END_CAP|CHILD_EDGE_BISECT)) != (END_CAP|CHILD_EDGE_BISECT)); + return frames; +} + +static int frame_offset(Frames *frames, FrameFlag flag) +{ + int n = 0; + + assert(flag == IN_FRAME || flag == OUT_FRAME || + !(flag & (IN_FRAME|OUT_FRAME))); + + if(flag == IN_FRAME) + return 0; + else if(flag == OUT_FRAME) + return frames->totframe-1; + + assert((flag & frames->flag) == flag); + + if(flag == START_CAP) return n; + if(frames->flag & START_CAP) n++; + + if(flag == NODE_BISECT) return n; + if(frames->flag & NODE_BISECT) n++; + + if(flag == END_CAP) return n; + if(frames->flag & END_CAP) n++; + + if(flag == CHILD_EDGE_BISECT) return n; + if(frames->flag & CHILD_EDGE_BISECT) n++; + + assert(!"bad frame offset flag"); +} + +static int frame_base(Frames *frames, FrameFlag flag) +{ + return frames->outbase + 4*frame_offset(frames, flag); +} + +static void *frame_co(Frames *frames, FrameFlag flag) +{ + return frames->co[frame_offset(frames, flag)]; +} + +static int frames_totvert(Frames *frames) +{ + return frames->totframe*4; +} + +#if 0 +static int bsphere_build_frames(BSphereNode *n, GHash *ghash, + float (*parent_mat)[3], FrameFlag flag); + +/* builds the `cap' of polygons for the end of a BSphere chain */ +static int bsphere_end_node_frames(BSphereNode *n, + GHash *ghash, + float parent_mat[3][3], + FrameFlag flag) +{ + Frames *frames; + float rad; + + assert(flag == 0 || flag == START_CAP); + frames = frames_create(NODE_BISECT|END_CAP|flag, n, ghash); + + /* TODO */ + rad = n->size[0]; + + if(flag & START_CAP) + create_frame(frame_co(frames, START_CAP), n, parent_mat, -rad, rad); + + /* frame to bisect the node */ + create_frame(frame_co(frames, NODE_BISECT), n, parent_mat, 0, rad); + + /* frame to cap end node */ + create_frame(frame_co(frames, END_CAP), n, parent_mat, rad, rad); + + return frames_totvert(frames); +} + +static int bsphere_connection_node_frames(BSphereNode *n, + GHash *ghash, + float parent_mat[3][3], + FrameFlag flag) +{ + Frames *frames; + BSphereNode *child; + float childmat[3][3], nodemat[3][3], axis[3], angle, rad, child_rad; + int totvert; + + assert(flag == 0 || flag == START_CAP); + + child = n->children.first; + + /* if child is not a branch node, bisect the child edge */ + if(BLI_countlist(&child->children) <= 1) + flag |= CHILD_EDGE_BISECT; + + frames = frames_create(NODE_BISECT|flag, n, ghash); + totvert = frames_totvert(frames); + + /* TODO */ + rad = n->size[0]; + child_rad = child->size[0]; + + /* build matrix to give to child */ + sub_v3_v3v3(childmat[0], child->co, n->co); + normalize_v3(childmat[0]); + angle = angle_normalized_v3v3(parent_mat[0], childmat[0]); + cross_v3_v3v3(axis, parent_mat[0], childmat[0]); + normalize_v3(axis); + rotate_normalized_v3_v3v3fl(childmat[1], parent_mat[1], axis, angle); + rotate_normalized_v3_v3v3fl(childmat[2], parent_mat[2], axis, angle); + + /* build child */ + totvert += bsphere_build_frames(child, ghash, childmat, 0); + + /* frame that bisects the node */ + angle /= 2; + copy_v3_v3(nodemat[0], parent_mat[0]); + rotate_normalized_v3_v3v3fl(nodemat[1], parent_mat[1], axis, angle); + rotate_normalized_v3_v3v3fl(nodemat[2], parent_mat[2], axis, angle); + create_frame(frame_co(frames, NODE_BISECT), n, nodemat, 0, rad); + + if(flag & START_CAP) + create_frame(frame_co(frames, START_CAP), n, nodemat, -rad, rad); + + if(flag & CHILD_EDGE_BISECT) + create_mid_frame(frame_co(frames, CHILD_EDGE_BISECT), n, child, childmat); + + return totvert; +} + +static int bsphere_branch_node_frames(BSphereNode *n, GHash *ghash) +{ + BSphereNode *child; + int totvert = 0; + float rad; + + rad = n->size[0]; + + /* build children */ + for(child = n->children.first; child; child = child->next) { + float childmat[3][3]; + + calc_edge_mat(childmat, n->co, child->co); + + totvert += bsphere_build_frames(child, ghash, childmat, 0); + } + + /* TODO: for now, builds no frames of its own */ + + return totvert; +} + +static int bsphere_build_frames(BSphereNode *n, GHash *ghash, + float parent_mat[3][3], FrameFlag flag) +{ + BSphereNode *child; + + child = n->children.first; + + if(!child) + return bsphere_end_node_frames(n, ghash, parent_mat, flag); + else if(!child->next) + return bsphere_connection_node_frames(n, ghash, parent_mat, flag); + else + return bsphere_branch_node_frames(n, ghash); +} + +static GHash *bsphere_frames(BSphere *bs, int *totvert) +{ + GHash *ghash; + BSphereNode *n, *child; + + ghash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, + "bsphere_frames.ghash"); + (*totvert) = 0; + + for(n = bs->rootbase.first; n; n = n->next) { + float mat[3][3]; + + child = n->children.first; + if(!child || (child && child->next)) { + set_v3(mat[0], 0, 0, 1); + set_v3(mat[1], 1, 0, 0); + set_v3(mat[2], 0, 1, 0); + } + else if(!child->next) { + calc_edge_mat(mat, n->co, child->co); + } + + (*totvert) += bsphere_build_frames(n, ghash, mat, START_CAP); + } + + return ghash; +} + +static void output_frames(Frames *frames, MVert *mvert, MFace *mface, + int *totvert, int *totface) +{ + int b, i, j; + + frames->outbase = (*totvert); + for(i = 0; i < frames->totframe; i++) { + for(j = 0; j < 4; j++) { + copy_v3_v3(mvert[(*totvert)].co, frames->co[i][j]); + (*totvert)++; + } + + if(i > 0) { + connect_frames(mface, totface, + frames->outbase + 4*(i-1), + frames->outbase + 4*i); + } + } + + if(frames->flag & START_CAP) { + b = frame_base(frames, START_CAP); + add_face(mface, totface, b, b+1, b+2, b+3); + } + if(frames->flag & END_CAP) { + b = frame_base(frames, END_CAP); + add_face(mface, totface, b+3, b+2, b+1, b+0); + } +} + +static void bsphere_build_skin(BSphereNode *parent, ListBase *base, + GHash *frames, MVert *mvert, + MFace *mface, int *totvert, int *totface) +{ + BSphereNode *n, *child; + Frames *node_frames, *child_frames, *parent_frames; + int *hull_frames, totchild, i; + + for(n = base->first; n; n = n->next) { + if((node_frames = BLI_ghash_lookup(frames, n))) + output_frames(node_frames, mvert, mface, totvert, totface); + + bsphere_build_skin(n, &n->children, frames, mvert, mface, totvert, totface); + + child = n->children.first; + if(child && !child->next) { + child_frames = BLI_ghash_lookup(frames, child); + if(child_frames) { + connect_frames(mface, totface, + frame_base(node_frames, OUT_FRAME), + frame_base(child_frames, IN_FRAME)); + } + } + else if(child && child->next) { + totchild = BLI_countlist(&n->children); + hull_frames = MEM_callocN(sizeof(int) * (1+totchild), + "bsphere_build_skin.hull_frames"); + i = 0; + for(child = n->children.first; child; child = child->next) { + child_frames = BLI_ghash_lookup(frames, child); + assert(child_frames); + hull_frames[i++] = frame_base(child_frames, IN_FRAME); + } + parent_frames = BLI_ghash_lookup(frames, parent); + if(parent_frames) + hull_frames[i] = frame_base(parent_frames, OUT_FRAME); + else + totchild--; + build_hull(mface, totface, mvert, hull_frames, totchild+1); + MEM_freeN(hull_frames); + } + } +} + +static DerivedMesh *bsphere_base_skin(BSphere *bs) +{ + DerivedMesh *dm; + GHash *ghash; + MVert *mvert; + MFace *mface; + int totvert, totface = 0; + + /* no nodes, nothing to do */ + if(!bs->rootbase.first) + return NULL; + + /* could probably do all this in one fell [recursive] swoop + using some tricksies and clevers, but multiple passes is + easier :) */ + ghash = bsphere_frames(bs, &totvert); + + totface = totvert * 1.5; + /* XXX: sizes OK? */ + dm = CDDM_new(totvert, 0, totface); + + mvert = CDDM_get_verts(dm); + mface = CDDM_get_faces(dm); + + totvert = totface = 0; + bsphere_build_skin(NULL, &bs->rootbase, ghash, mvert, mface, &totvert, &totface); + BLI_ghash_free(ghash, NULL, (void*)MEM_freeN); + + CDDM_lower_num_verts(dm, totvert); + CDDM_lower_num_faces(dm, totface); + + CDDM_calc_edges(dm); + CDDM_calc_normals(dm); + + return dm; +} + +/* generate random points (just for testing) */ +DerivedMesh *bsphere_random_points(BSphere *UNUSED(bs)) +{ + DerivedMesh *dm; + MVert *mvert; + const int totvert = 1;//50000; + int i; + + dm = CDDM_new(totvert, 0, 0); + + mvert = CDDM_get_verts(dm); + + srand(1); + for(i = 0; i < totvert; i++) { + mvert[i].co[0] = rand() / (float)RAND_MAX - 0.5; + mvert[i].co[1] = rand() / (float)RAND_MAX - 0.5; + mvert[i].co[2] = rand() / (float)RAND_MAX - 0.5; + } + + return dm; +} + +DerivedMesh *bsphere_test_surface(BSphere *bs, DerivedMesh *input) +{ + DerivedMesh *dm; + MVert *mvert; + + if(!input) + return NULL; + + dm = CDDM_copy(input); + mvert = CDDM_get_verts(dm); + bsphere_evolve(mvert, input->getNumVerts(input), &bs->rootbase, + bs->skin_threshold, bs->evolve, 2); + + return dm; +} + +DerivedMesh *bsphere_test_gradient(BSphere *bs, DerivedMesh *input) +{ + DerivedMesh *dm; + MVert *mvert; + MEdge *medge; + int totvert; + int i; + + if(!input) + return NULL; + + totvert = input->getNumVerts(input); + dm = CDDM_new(totvert*2, totvert, 0); + + mvert = CDDM_get_verts(dm); + medge = CDDM_get_edges(dm); + + memcpy(mvert, CDDM_get_verts(input), sizeof(MVert) * totvert); + + for(i = 0; i < totvert; i++) { + const float *b = mvert[i].co; + float *g = mvert[totvert+i].co; + float K[2] = {0, 0}; + + zero_v3(g); + calc_gradient(g, b, &bs->rootbase); + normalize_v3(g); + + mul_v3_fl(g, -calc_F(b, K, bs->skin_threshold, &bs->rootbase)); + add_v3_v3(g, b); + + medge[i].v1 = i; + medge[i].v2 = totvert+i; + } + + return dm; +} + +DerivedMesh *bsphere_get_skin_dm(BSphere *bs) +{ + DerivedMesh *dm, *subdm; + + dm = bsphere_base_skin(bs); + + /* subdivide once */ + if(dm && bs->subdiv_level > 0) { + SubsurfModifierData smd; + + memset(&smd, 0, sizeof(smd)); + smd.subdivType = ME_CC_SUBSURF; + smd.levels = bs->subdiv_level; + subdm = subsurf_make_derived_from_derived(dm, &smd, 0, 0, 0, 0); + dm->release(dm); + /* for convenience, convert back to cddm (could use ccgdm + later for better performance though? (TODO)) */ + dm = CDDM_copy(subdm); + subdm->release(subdm); + + bsphere_evolve(CDDM_get_verts(dm), dm->getNumVerts(dm), &bs->rootbase, + bs->skin_threshold, bs->evolve, bs->subdiv_level); + } + + return dm; +} +#endif diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 1f18c78d070..b9d6badfbe9 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -811,7 +811,7 @@ static void layerDefault_skin(void *data, int count) int i; for(i = 0; i < count; i++) { - n[i].radius = 1; + n[i].radius = 0.25; } } -- cgit v1.2.3 From 6c3bb8b9030a86388d42a752b0cba2826630c4c6 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 31 Jul 2011 02:03:48 +0000 Subject: EditMesh-based skin node drawing --- .../startup/bl_ui/properties_data_modifier.py | 3 - source/blender/blenkernel/CMakeLists.txt | 1 - source/blender/blenkernel/intern/bsphere.c | 1178 -------------------- source/blender/blenkernel/intern/customdata.c | 21 +- source/blender/makesdna/DNA_customdata_types.h | 4 +- source/blender/makesdna/DNA_meshdata_types.h | 5 - source/blender/makesdna/DNA_modifier_types.h | 14 - source/blender/makesrna/intern/rna_modifier.c | 15 - source/blender/modifiers/CMakeLists.txt | 1 - source/blender/modifiers/MOD_modifiertypes.h | 1 - source/blender/modifiers/intern/MOD_skin.c | 88 -- source/blender/modifiers/intern/MOD_util.c | 1 - 12 files changed, 6 insertions(+), 1326 deletions(-) delete mode 100644 source/blender/blenkernel/intern/bsphere.c delete mode 100644 source/blender/modifiers/intern/MOD_skin.c diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 248c5219fe0..0a4d0b60514 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -736,8 +736,5 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel): col.prop(md, "width", slider=True) col.prop(md, "narrowness", slider=True) - def SKIN(self, layout, ob, md): - pass - if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index e549a205325..defcef58463 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -81,7 +81,6 @@ set(SRC intern/boids.c intern/booleanops_mesh.c intern/brush.c - intern/bsphere.c intern/bullet.c intern/bvhutils.c intern/cdderivedmesh.c diff --git a/source/blender/blenkernel/intern/bsphere.c b/source/blender/blenkernel/intern/bsphere.c deleted file mode 100644 index d8a75f62172..00000000000 --- a/source/blender/blenkernel/intern/bsphere.c +++ /dev/null @@ -1,1178 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2011 by Nicholas Bishop - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include "MEM_guardedalloc.h" - -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_modifier_types.h" - -#include "BLI_utildefines.h" -#include "BLI_heap.h" -#include "BLI_ghash.h" -#include "BLI_listbase.h" -#include "BLI_math.h" - -#include "BKE_cdderivedmesh.h" -#include "BKE_DerivedMesh.h" -#include "BKE_global.h" -#include "BKE_library.h" -#include "BKE_main.h" -#include "BKE_subsurf.h" - -#include - -typedef struct Tri { - struct Tri *next, *prev; - unsigned int v[3]; - float no[3]; - float area; - int marked; -} Tri; - -typedef struct Edge { - struct Edge *next, *prev; - unsigned int v[2]; - Tri *tri[2]; -} Edge; - -/* note: a `frame' is four vertices (contiguous within the MVert - array), stored simply as the index of the first vertex */ - -static void create_frame(float frame[4][3], const float co[3], float radius, - const float mat[3][3], float x_offset) -{ - float rx[3], ry[3], rz[3]; - int i; - - mul_v3_v3fl(ry, mat[1], radius); - mul_v3_v3fl(rz, mat[2], radius); - - add_v3_v3v3(frame[3], co, ry); - add_v3_v3v3(frame[3], frame[3], rz); - - sub_v3_v3v3(frame[2], co, ry); - add_v3_v3v3(frame[2], frame[2], rz); - - sub_v3_v3v3(frame[1], co, ry); - sub_v3_v3v3(frame[1], frame[1], rz); - - add_v3_v3v3(frame[0], co, ry); - sub_v3_v3v3(frame[0], frame[0], rz); - - mul_v3_v3fl(rx, mat[0], x_offset); - for(i = 0; i < 4; i++) - add_v3_v3v3(frame[i], frame[i], rx); -} - -static void create_mid_frame(float frame[4][3], - const float co1[3], const float co2[3], - const SkinNode *n1, const SkinNode *n2, - const float mat[3][3]) -{ - create_frame(frame, co1, (n1->radius + n2->radius) / 2, - mat, len_v3v3(co1, co2) / 2); -} - -static void add_face(MFace *mface, int *totface, - int v1, int v2, int v3, int v4) -{ - MFace *f; - - f = &mface[*totface]; - f->v1 = v1; - f->v2 = v2; - f->v3 = v3; - f->v4 = v4 == -1 ? 0 : v4; - if(!v4) { - f->v1 = v3; - f->v2 = v4; - f->v3 = v1; - f->v4 = v2; - } - (*totface)++; -} - -static void connect_frames(MFace *mface, int *totface, int frame1, int frame2) -{ - int i; - - for(i = 0; i < 4; i++) { - add_face(mface, totface, - frame2 + i, - frame2 + (i+1) % 4, - frame1 + (i+1) % 4, - frame1 + i); - } -} - -static Tri *add_triangle(ListBase *tris, MVert *mvert, int v1, int v2, int v3) -{ - Tri *t; - - t = MEM_callocN(sizeof(Tri), "add_triangle.tri"); - t->v[0] = v1; - t->v[1] = v2; - t->v[2] = v3; - BLI_addtail(tris, t); - - normal_tri_v3(t->no, mvert[t->v[0]].co, mvert[t->v[1]].co, mvert[t->v[2]].co); - t->area = area_tri_v3(mvert[t->v[0]].co, mvert[t->v[1]].co, mvert[t->v[2]].co); - - return t; -} - -static int point_tri_side(const Tri *t, MVert *mvert, int v) -{ - float p[3], d; - sub_v3_v3v3(p, mvert[v].co, mvert[t->v[0]].co); - d = dot_v3v3(t->no, p); - if(d < 0) return -1; - else if(d > 0) return 1; - else return 0; -} - -static int mark_v_outside_tris(ListBase *tris, MVert *mvert, int v) -{ - Tri *t; - int outside = 0; - - /* probably there's a much better way to do this */ - for(t = tris->first; t; t = t->next) { - if((t->marked = point_tri_side(t, mvert, v) > 0)) - outside = 1; - } - return outside; -} - -static int edge_match(int e1_0, int e1_1, const unsigned int e2[2]) -{ - /* XXX: maybe isn't necesseary to check both directions? */ - return (e1_0 == e2[0] && e1_1 == e2[1]) || - (e1_0 == e2[1] && e1_1 == e2[0]); -} - -/* returns true if the edge (e1, e2) is already in edges; that edge is - deleted here as well. if not found just returns 0 */ -static int check_for_dup(ListBase *edges, unsigned int e1, unsigned int e2) -{ - Edge *e, *next; - - for(e = edges->first; e; e = next) { - next = e->next; - - if(edge_match(e1, e2, e->v)) { - /* remove the interior edge */ - BLI_freelinkN(edges, e); - return 1; - } - } - - return 0; -} - -static void expand_boundary_edges(ListBase *edges, Tri *t) -{ - Edge *new; - int i; - - /* insert each triangle edge into the boundary list; if any of - its edges are already in there, remove the edge entirely */ - for(i = 0; i < 3; i++) { - if(!check_for_dup(edges, t->v[i], t->v[(i+1)%3])) { - new = MEM_callocN(sizeof(Edge), "Edge"); - new->v[0] = t->v[i]; - new->v[1] = t->v[(i+1)%3]; - BLI_addtail(edges, new); - } - } -} - -static int tri_matches_frame(const Tri *t, int frame) -{ - int i, j, match = 0; - for(i = 0; i < 3; i++) { - for(j = 0; j < 4; j++) { - if(t->v[i] == frame + j) { - match++; - if(match >= 3) - return 1; - } - } - } - return 0; -} - -static void quad_from_tris(const Edge *e, int ndx[4]) -{ - int i, j, opp = -1; - - /* find what the second tri has that the first doesn't */ - for(i = 0; i < 3; i++) { - if(e->tri[1]->v[i] != e->tri[0]->v[0] && - e->tri[1]->v[i] != e->tri[0]->v[1] && - e->tri[1]->v[i] != e->tri[0]->v[2]) { - opp = e->tri[1]->v[i]; - break; - } - } - assert(opp != -1); - - for(i = 0, j = 0; i < 3; i++, j++) { - ndx[j] = e->tri[0]->v[i]; - /* when the triangle edge cuts across our quad-to-be, - throw in the second triangle's vertex */ - if((e->tri[0]->v[i] == e->v[0] || e->tri[0]->v[i] == e->v[1]) && - (e->tri[0]->v[(i+1)%3] == e->v[0] || e->tri[0]->v[(i+1)%3] == e->v[1])) { - j++; - ndx[j] = opp; - } - } -} - -static void add_quad_from_tris(MFace *mface, int *totface, const Edge *e) -{ - int ndx[4]; - - quad_from_tris(e, ndx); - - add_face(mface, totface, ndx[0], ndx[1], ndx[2], ndx[3]); -} - -static GHash *calc_edges(ListBase *tris) -{ - GHash *adj; - ListBase *edges; - Edge *e; - Tri *t; - int i, e1, e2; - - /* XXX: vertex range might be a little funky? so using a - hash here */ - adj = BLI_ghash_new(BLI_ghashutil_inthash, - BLI_ghashutil_intcmp, - "calc_edges adj"); - - for(t = tris->first; t; t = t->next) { - for(i = 0; i < 3; i++) { - e1 = t->v[i]; - e2 = t->v[(i+1)%3]; - assert(e1 != e2); - if(e1 > e2) - SWAP(int, e1, e2); - - edges = BLI_ghash_lookup(adj, SET_INT_IN_POINTER(e1)); - if(!edges) { - edges = MEM_callocN(sizeof(ListBase), - "calc_edges ListBase"); - BLI_ghash_insert(adj, SET_INT_IN_POINTER(e1), edges); - } - - /* find the edge in the adjacency list */ - for(e = edges->first; e; e = e->next) { - assert(e->v[0] == e1); - if(e->v[1] == e2) - break; - } - - /* if not found, create the edge */ - if(!e) { - e = MEM_callocN(sizeof(Edge), "calc_edges Edge"); - e->v[0] = e1; - e->v[1] = e2; - BLI_addtail(edges, e); - } - - /* should never be more than two faces - attached to an edge here */ - assert(!e->tri[0] || !e->tri[1]); - - if(!e->tri[0]) - e->tri[0] = t; - else if(!e->tri[1]) - e->tri[1] = t; - } - } - - return adj; -} - -static int is_quad_symmetric(const MVert *mvert, const Edge *e) -{ - int ndx[4]; - float a[3]; - - quad_from_tris(e, ndx); - - copy_v3_v3(a, mvert[ndx[0]].co); - a[0] = -a[0]; - - if(len_v3v3(a, mvert[ndx[1]].co) < FLT_EPSILON) { - copy_v3_v3(a, mvert[ndx[2]].co); - a[0] = -a[0]; - if(len_v3v3(a, mvert[ndx[3]].co) < FLT_EPSILON) - return 1; - } - else if(len_v3v3(a, mvert[ndx[3]].co) < FLT_EPSILON) { - copy_v3_v3(a, mvert[ndx[2]].co); - a[0] = -a[0]; - if(len_v3v3(a, mvert[ndx[1]].co) < FLT_EPSILON) - return 1; - } - - return 0; -} - -static void output_hull(const MVert *mvert, MFace *mface, int *totface, ListBase *tris) -{ - Heap *heap; - GHash *adj; - GHashIterator *iter; - ListBase *edges; - Edge *e; - Tri *t; - float score; - - heap = BLI_heap_new(); - adj = calc_edges(tris); - - /* unmark all triangles */ - for(t = tris->first; t; t = t->next) - t->marked = 0; - - /* build heap */ - iter = BLI_ghashIterator_new(adj); - while(!BLI_ghashIterator_isDone(iter)) { - edges = BLI_ghashIterator_getValue(iter); - for(e = edges->first; e; e = e->next) { - /* only care if the edge is used by more than - one triangle */ - if(e->tri[0] && e->tri[1]) { - score = (e->tri[0]->area + e->tri[1]->area) * - dot_v3v3(e->tri[0]->no, e->tri[1]->no); - - /* increase score if the triangles - form a symmetric quad */ - if(is_quad_symmetric(mvert, e)) - score *= 10; - - BLI_heap_insert(heap, -score, e); - } - } - - BLI_ghashIterator_step(iter); - } - BLI_ghashIterator_free(iter); - - while(!BLI_heap_empty(heap)) { - e = BLI_heap_popmin(heap); - - /* if both triangles still free, outupt as a quad */ - if(!e->tri[0]->marked && !e->tri[1]->marked) { - add_quad_from_tris(mface, totface, e); - e->tri[0]->marked = 1; - e->tri[1]->marked = 1; - } - } - - /* free edge list */ - iter = BLI_ghashIterator_new(adj); - while(!BLI_ghashIterator_isDone(iter)) { - edges = BLI_ghashIterator_getValue(iter); - BLI_freelistN(edges); - MEM_freeN(edges); - BLI_ghashIterator_step(iter); - } - BLI_ghashIterator_free(iter); - BLI_ghash_free(adj, NULL, NULL); - BLI_heap_free(heap, NULL); - - /* write out any remaining triangles */ - for(t = tris->first; t; t = t->next) { - if(!t->marked) - add_face(mface, totface, t->v[0], t->v[1], t->v[2], -1); - } -} - -/* for vertex `v', find which triangles must be deleted to extend the - hull; find the boundary edges of that hole so that it can be filled - with connections to the new vertex, and update the `tri' list to - delete the marked triangles */ -static void add_point(ListBase *tris, MVert *mvert, int v) -{ - ListBase edges = {NULL, NULL}; - Tri *t, *next; - Edge *e; - - for(t = tris->first; t; t = next) { - next = t->next; - - /* check if triangle is `visible' to v */ - if(t->marked) { - expand_boundary_edges(&edges, t); - /* remove the triangle */ - BLI_freelinkN(tris, t); - } - } - - /* fill hole boundary with triangles to new point */ - for(e = edges.first; e; e = e->next) - add_triangle(tris, mvert, e->v[0], e->v[1], v); - BLI_freelistN(&edges); -} - -static void build_hull(MFace *mface, int *totface, - MVert *mvert, int *frames, int totframe) -{ - ListBase tris = {NULL, NULL}; - Tri *t, *next; - int i, j; - - /* use first frame to make initial degenerate pyramid */ - add_triangle(&tris, mvert, frames[0], frames[0] + 1, frames[0] + 2); - add_triangle(&tris, mvert, frames[0] + 1, frames[0], frames[0] + 3); - add_triangle(&tris, mvert, frames[0] + 2, frames[0] + 1, frames[0] + 3); - add_triangle(&tris, mvert, frames[0], frames[0] + 2, frames[0] + 3); - - for(i = 1; i < totframe; i++) { - for(j = 0; j < 4; j++) { - int v = frames[i] + j; - - /* ignore point already inside hull */ - if(mark_v_outside_tris(&tris, mvert, v)) { - /* expand hull and delete interior triangles */ - add_point(&tris, mvert, v); - } - } - } - - /* remove triangles that would fill the original frames */ - for(t = tris.first; t; t = next) { - next = t->next; - - for(i = 0; i < totframe; i++) { - if(tri_matches_frame(t, frames[i])) { - BLI_freelinkN(&tris, t); - break; - } - } - } - - output_hull(mvert, mface, totface, &tris); - - BLI_freelistN(&tris); -} - -/* test: build hull on origdm */ -#if 0 -static DerivedMesh *test_hull(DerivedMesh *origdm) -{ - DerivedMesh *dm; - MVert *mvert, *origmvert; - MFace *mface; - int *frames; - int totvert = 0, totface = 0, totframe, i; - - /* TODO */ - totface = 2000; - totvert = origdm->getNumVerts(origdm); - dm = CDDM_new(totvert, 0, totface); - - mvert = CDDM_get_verts(dm); - mface = CDDM_get_faces(dm); - - origmvert = CDDM_get_verts(origdm); - for(i = 0; i < totvert; i++) - mvert[i] = origmvert[i]; - - assert(totvert % 4 == 0); - totframe = totvert / 4; - - frames = MEM_callocN(sizeof(int) * totframe, "frames"); - for(i = 0; i < totframe; i++) - frames[i] = i*4; - - totface = 0; - build_hull(mface, &totface, mvert, frames, totframe); - - CDDM_calc_edges(dm); - //CDDM_calc_normals(dm); - - MEM_freeN(frames); - - return dm; -} -#endif - -/* TODO */ -static void calc_edge_mat(float mat[3][3], const float a[3], const float b[3]) -{ - float Z[3] = {0, 0, 1}; - float dot; - - /* x = edge direction */ - sub_v3_v3v3(mat[0], b, a); - normalize_v3(mat[0]); - - dot = dot_v3v3(mat[0], Z); - if(dot > -1 + FLT_EPSILON && dot < 1 - FLT_EPSILON) { - /* y = Z cross x */ - cross_v3_v3v3(mat[1], Z, mat[0]); - normalize_v3(mat[1]); - - /* z = x cross y */ - cross_v3_v3v3(mat[2], mat[0], mat[1]); - normalize_v3(mat[2]); - } - else { - mat[1][0] = 1; - mat[1][1] = 0; - mat[1][2] = 0; - mat[2][0] = 0; - mat[2][1] = 1; - mat[2][2] = 0; - } -} - -/* BMesh paper */ -#if 0 -static float calc_R_sub_i_squared(const BSphereNode *n) -{ - const float alpha = 1.5; - //const float alpha = 1; - const float R_sub_i = n->size[0] * alpha; - return R_sub_i * R_sub_i; -} - -/* equation (2) */ -static float calc_r_squared(const float v[3], const BSphereNode *n) -{ - return len_squared_v3v3(v, n->co); -} - -/* equation (1) */ -static float calc_f_sub_i(const float v[3], const BSphereNode *n) -{ - float r_squared; - float R_sub_i_squared; - - r_squared = calc_r_squared(v, n); - R_sub_i_squared = calc_R_sub_i_squared(n); - - if(r_squared <= R_sub_i_squared) - return powf(1.0f - (r_squared / R_sub_i_squared), 2); - else - return 0; -} - -/* equation (3) */ -static float calc_I(const float x[3], float T, const ListBase *base) -{ - BSphereNode *n; - float a = -T; - - for(n = base->first; n; n = n->next) { - a += calc_I(x, 0, &n->children); - a += calc_f_sub_i(x, n); - } - - //printf("calc_I: %f, %f\n", -T, a); - - return a; -} - -/* kinda my own guess here */ -static void calc_gradient(float g[3], const float x[3], const ListBase *base) -{ - BSphereNode *n; - - for(n = base->first; n; n = n->next) { - float R_sub_i_squared = calc_R_sub_i_squared(n); - float dist = len_v3v3(x, n->co); - float f = calc_f_sub_i(x, n); - float d = 1.0f / R_sub_i_squared; - float tmp[3]; - - /* XXX: other possibilities... */ - if(f > 0) { - sub_v3_v3v3(tmp, x, n->co); - mul_v3_fl(tmp, -4*d * (1 - d * dist)); - - /* not sure if I'm doing this right; intent is - to flip direction when x is `beneath' the - level set */ - if(len_v3v3(x, n->co) > n->size[0]) - negate_v3(tmp); - - add_v3_v3(g, tmp); - } - - calc_gradient(g, x, &n->children); - } -} - -/* equation (5) */ -static float calc_F(const float x[3], const float K[2], float T, const ListBase *base) -{ - float f_of_K; - float I_target; - - /* TODO */ - f_of_K = 1.0f / (1 + fabs(K[0]) + fabs(K[1])); - //f_of_K = 1; - - /* TODO */ - I_target = 0; - - return (calc_I(x, T, base) - I_target) /*TODO: * f_of_K*/; -} - -static float smallest_radius(const ListBase *base) -{ - BSphereNode *n; - float s = FLT_MAX, t; - - for(n = base->first; n; n = n->next) { - if(n->size[0] < s) - s = n->size[0]; - if((t = smallest_radius(&n->children)) < s) - s = t; - } - - return s; -} - -/* equation (7) */ -static float calc_delta_t(float F_max, float k, const ListBase *base, int print) -{ - float min_r_sub_i; - float step; - - min_r_sub_i = smallest_radius(base); - step = min_r_sub_i / powf(2, k); - - if(print) { - printf("min_r: %f, 2^k=%f, step=%f\n", min_r_sub_i, powf(2, k), step); - } - - return step / F_max; -} - -/* equation (6) */ -static float evolve_x(float x[3], const float K[2], float T, - int k, const ListBase *base, int i, float F_max) -{ - float tmp[3], no[3]; - float F, dt; - - F = calc_F(x, K, T, base); - - if(F < FLT_EPSILON) { - //printf("stability reached for ndx=%d\n", i); - return 0; - } - - /* TODO ;-) */ - if(F > F_max) - F_max = F; - - dt = calc_delta_t(F_max, k, base, 0); - - dt = F / 2; - - if(i == 0) - ;//printf("F=%.3f, dt=%.3f\n", F, calc_delta_t(F_max, k, base, 1)); - - zero_v3(no); - calc_gradient(no, x, base); - normalize_v3(no); - negate_v3(no); - - mul_v3_v3fl(tmp, no, F * dt); - add_v3_v3(x, tmp); - - return F_max; -} - -static void bsphere_evolve(MVert *mvert, int totvert, const ListBase *base, - float T, int steps, float subdiv_level) -{ - int i, s; - - for(i = 0; i < totvert; i++) { - float F_max = 0; - /* TODO: for now just doing a constant number of steps */ - for(s = 0; s < steps; s++) { - /* TODO */ - float K[2] = {0, 0}; - - F_max = evolve_x(mvert[i].co, K, T, subdiv_level, base, i, F_max); - } - } -} -#endif - -typedef enum { - START_CAP = 1, - END_CAP = 2, - NODE_BISECT = 4, - CHILD_EDGE_BISECT = 8, - - IN_FRAME = 16, - OUT_FRAME = 32, -} FrameFlag; - -typedef struct { - int totframe; - int outbase; - FrameFlag flag; - float co[0][4][3]; -} Frames; - -static Frames *frames_create(FrameFlag flag) -{ - Frames *frames; - int totframe; - totframe = (!!(flag & START_CAP) + !!(flag & END_CAP) + - !!(flag & NODE_BISECT) + !!(flag & CHILD_EDGE_BISECT)); - assert(totframe); - frames = MEM_callocN(sizeof(Frames) + sizeof(float)*totframe*4*3, - "frames_create.frames"); - frames->totframe = totframe; - frames->flag = flag; - assert((flag & (END_CAP|CHILD_EDGE_BISECT)) != (END_CAP|CHILD_EDGE_BISECT)); - return frames; -} - -static int frame_offset(Frames *frames, FrameFlag flag) -{ - int n = 0; - - assert(flag == IN_FRAME || flag == OUT_FRAME || - !(flag & (IN_FRAME|OUT_FRAME))); - - if(flag == IN_FRAME) - return 0; - else if(flag == OUT_FRAME) - return frames->totframe-1; - - assert((flag & frames->flag) == flag); - - if(flag == START_CAP) return n; - if(frames->flag & START_CAP) n++; - - if(flag == NODE_BISECT) return n; - if(frames->flag & NODE_BISECT) n++; - - if(flag == END_CAP) return n; - if(frames->flag & END_CAP) n++; - - if(flag == CHILD_EDGE_BISECT) return n; - if(frames->flag & CHILD_EDGE_BISECT) n++; - - assert(!"bad frame offset flag"); -} - -static int frame_base(Frames *frames, FrameFlag flag) -{ - return frames->outbase + 4*frame_offset(frames, flag); -} - -static void *frame_co(Frames *frames, FrameFlag flag) -{ - return frames->co[frame_offset(frames, flag)]; -} - -static int frames_totvert(Frames *frames) -{ - return frames->totframe*4; -} - -#if 0 -static int bsphere_build_frames(BSphereNode *n, GHash *ghash, - float (*parent_mat)[3], FrameFlag flag); - -/* builds the `cap' of polygons for the end of a BSphere chain */ -static int bsphere_end_node_frames(BSphereNode *n, - GHash *ghash, - float parent_mat[3][3], - FrameFlag flag) -{ - Frames *frames; - float rad; - - assert(flag == 0 || flag == START_CAP); - frames = frames_create(NODE_BISECT|END_CAP|flag, n, ghash); - - /* TODO */ - rad = n->size[0]; - - if(flag & START_CAP) - create_frame(frame_co(frames, START_CAP), n, parent_mat, -rad, rad); - - /* frame to bisect the node */ - create_frame(frame_co(frames, NODE_BISECT), n, parent_mat, 0, rad); - - /* frame to cap end node */ - create_frame(frame_co(frames, END_CAP), n, parent_mat, rad, rad); - - return frames_totvert(frames); -} - -static int bsphere_connection_node_frames(BSphereNode *n, - GHash *ghash, - float parent_mat[3][3], - FrameFlag flag) -{ - Frames *frames; - BSphereNode *child; - float childmat[3][3], nodemat[3][3], axis[3], angle, rad, child_rad; - int totvert; - - assert(flag == 0 || flag == START_CAP); - - child = n->children.first; - - /* if child is not a branch node, bisect the child edge */ - if(BLI_countlist(&child->children) <= 1) - flag |= CHILD_EDGE_BISECT; - - frames = frames_create(NODE_BISECT|flag, n, ghash); - totvert = frames_totvert(frames); - - /* TODO */ - rad = n->size[0]; - child_rad = child->size[0]; - - /* build matrix to give to child */ - sub_v3_v3v3(childmat[0], child->co, n->co); - normalize_v3(childmat[0]); - angle = angle_normalized_v3v3(parent_mat[0], childmat[0]); - cross_v3_v3v3(axis, parent_mat[0], childmat[0]); - normalize_v3(axis); - rotate_normalized_v3_v3v3fl(childmat[1], parent_mat[1], axis, angle); - rotate_normalized_v3_v3v3fl(childmat[2], parent_mat[2], axis, angle); - - /* build child */ - totvert += bsphere_build_frames(child, ghash, childmat, 0); - - /* frame that bisects the node */ - angle /= 2; - copy_v3_v3(nodemat[0], parent_mat[0]); - rotate_normalized_v3_v3v3fl(nodemat[1], parent_mat[1], axis, angle); - rotate_normalized_v3_v3v3fl(nodemat[2], parent_mat[2], axis, angle); - create_frame(frame_co(frames, NODE_BISECT), n, nodemat, 0, rad); - - if(flag & START_CAP) - create_frame(frame_co(frames, START_CAP), n, nodemat, -rad, rad); - - if(flag & CHILD_EDGE_BISECT) - create_mid_frame(frame_co(frames, CHILD_EDGE_BISECT), n, child, childmat); - - return totvert; -} - -static int bsphere_branch_node_frames(BSphereNode *n, GHash *ghash) -{ - BSphereNode *child; - int totvert = 0; - float rad; - - rad = n->size[0]; - - /* build children */ - for(child = n->children.first; child; child = child->next) { - float childmat[3][3]; - - calc_edge_mat(childmat, n->co, child->co); - - totvert += bsphere_build_frames(child, ghash, childmat, 0); - } - - /* TODO: for now, builds no frames of its own */ - - return totvert; -} - -static int bsphere_build_frames(BSphereNode *n, GHash *ghash, - float parent_mat[3][3], FrameFlag flag) -{ - BSphereNode *child; - - child = n->children.first; - - if(!child) - return bsphere_end_node_frames(n, ghash, parent_mat, flag); - else if(!child->next) - return bsphere_connection_node_frames(n, ghash, parent_mat, flag); - else - return bsphere_branch_node_frames(n, ghash); -} - -static GHash *bsphere_frames(BSphere *bs, int *totvert) -{ - GHash *ghash; - BSphereNode *n, *child; - - ghash = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, - "bsphere_frames.ghash"); - (*totvert) = 0; - - for(n = bs->rootbase.first; n; n = n->next) { - float mat[3][3]; - - child = n->children.first; - if(!child || (child && child->next)) { - set_v3(mat[0], 0, 0, 1); - set_v3(mat[1], 1, 0, 0); - set_v3(mat[2], 0, 1, 0); - } - else if(!child->next) { - calc_edge_mat(mat, n->co, child->co); - } - - (*totvert) += bsphere_build_frames(n, ghash, mat, START_CAP); - } - - return ghash; -} - -static void output_frames(Frames *frames, MVert *mvert, MFace *mface, - int *totvert, int *totface) -{ - int b, i, j; - - frames->outbase = (*totvert); - for(i = 0; i < frames->totframe; i++) { - for(j = 0; j < 4; j++) { - copy_v3_v3(mvert[(*totvert)].co, frames->co[i][j]); - (*totvert)++; - } - - if(i > 0) { - connect_frames(mface, totface, - frames->outbase + 4*(i-1), - frames->outbase + 4*i); - } - } - - if(frames->flag & START_CAP) { - b = frame_base(frames, START_CAP); - add_face(mface, totface, b, b+1, b+2, b+3); - } - if(frames->flag & END_CAP) { - b = frame_base(frames, END_CAP); - add_face(mface, totface, b+3, b+2, b+1, b+0); - } -} - -static void bsphere_build_skin(BSphereNode *parent, ListBase *base, - GHash *frames, MVert *mvert, - MFace *mface, int *totvert, int *totface) -{ - BSphereNode *n, *child; - Frames *node_frames, *child_frames, *parent_frames; - int *hull_frames, totchild, i; - - for(n = base->first; n; n = n->next) { - if((node_frames = BLI_ghash_lookup(frames, n))) - output_frames(node_frames, mvert, mface, totvert, totface); - - bsphere_build_skin(n, &n->children, frames, mvert, mface, totvert, totface); - - child = n->children.first; - if(child && !child->next) { - child_frames = BLI_ghash_lookup(frames, child); - if(child_frames) { - connect_frames(mface, totface, - frame_base(node_frames, OUT_FRAME), - frame_base(child_frames, IN_FRAME)); - } - } - else if(child && child->next) { - totchild = BLI_countlist(&n->children); - hull_frames = MEM_callocN(sizeof(int) * (1+totchild), - "bsphere_build_skin.hull_frames"); - i = 0; - for(child = n->children.first; child; child = child->next) { - child_frames = BLI_ghash_lookup(frames, child); - assert(child_frames); - hull_frames[i++] = frame_base(child_frames, IN_FRAME); - } - parent_frames = BLI_ghash_lookup(frames, parent); - if(parent_frames) - hull_frames[i] = frame_base(parent_frames, OUT_FRAME); - else - totchild--; - build_hull(mface, totface, mvert, hull_frames, totchild+1); - MEM_freeN(hull_frames); - } - } -} - -static DerivedMesh *bsphere_base_skin(BSphere *bs) -{ - DerivedMesh *dm; - GHash *ghash; - MVert *mvert; - MFace *mface; - int totvert, totface = 0; - - /* no nodes, nothing to do */ - if(!bs->rootbase.first) - return NULL; - - /* could probably do all this in one fell [recursive] swoop - using some tricksies and clevers, but multiple passes is - easier :) */ - ghash = bsphere_frames(bs, &totvert); - - totface = totvert * 1.5; - /* XXX: sizes OK? */ - dm = CDDM_new(totvert, 0, totface); - - mvert = CDDM_get_verts(dm); - mface = CDDM_get_faces(dm); - - totvert = totface = 0; - bsphere_build_skin(NULL, &bs->rootbase, ghash, mvert, mface, &totvert, &totface); - BLI_ghash_free(ghash, NULL, (void*)MEM_freeN); - - CDDM_lower_num_verts(dm, totvert); - CDDM_lower_num_faces(dm, totface); - - CDDM_calc_edges(dm); - CDDM_calc_normals(dm); - - return dm; -} - -/* generate random points (just for testing) */ -DerivedMesh *bsphere_random_points(BSphere *UNUSED(bs)) -{ - DerivedMesh *dm; - MVert *mvert; - const int totvert = 1;//50000; - int i; - - dm = CDDM_new(totvert, 0, 0); - - mvert = CDDM_get_verts(dm); - - srand(1); - for(i = 0; i < totvert; i++) { - mvert[i].co[0] = rand() / (float)RAND_MAX - 0.5; - mvert[i].co[1] = rand() / (float)RAND_MAX - 0.5; - mvert[i].co[2] = rand() / (float)RAND_MAX - 0.5; - } - - return dm; -} - -DerivedMesh *bsphere_test_surface(BSphere *bs, DerivedMesh *input) -{ - DerivedMesh *dm; - MVert *mvert; - - if(!input) - return NULL; - - dm = CDDM_copy(input); - mvert = CDDM_get_verts(dm); - bsphere_evolve(mvert, input->getNumVerts(input), &bs->rootbase, - bs->skin_threshold, bs->evolve, 2); - - return dm; -} - -DerivedMesh *bsphere_test_gradient(BSphere *bs, DerivedMesh *input) -{ - DerivedMesh *dm; - MVert *mvert; - MEdge *medge; - int totvert; - int i; - - if(!input) - return NULL; - - totvert = input->getNumVerts(input); - dm = CDDM_new(totvert*2, totvert, 0); - - mvert = CDDM_get_verts(dm); - medge = CDDM_get_edges(dm); - - memcpy(mvert, CDDM_get_verts(input), sizeof(MVert) * totvert); - - for(i = 0; i < totvert; i++) { - const float *b = mvert[i].co; - float *g = mvert[totvert+i].co; - float K[2] = {0, 0}; - - zero_v3(g); - calc_gradient(g, b, &bs->rootbase); - normalize_v3(g); - - mul_v3_fl(g, -calc_F(b, K, bs->skin_threshold, &bs->rootbase)); - add_v3_v3(g, b); - - medge[i].v1 = i; - medge[i].v2 = totvert+i; - } - - return dm; -} - -DerivedMesh *bsphere_get_skin_dm(BSphere *bs) -{ - DerivedMesh *dm, *subdm; - - dm = bsphere_base_skin(bs); - - /* subdivide once */ - if(dm && bs->subdiv_level > 0) { - SubsurfModifierData smd; - - memset(&smd, 0, sizeof(smd)); - smd.subdivType = ME_CC_SUBSURF; - smd.levels = bs->subdiv_level; - subdm = subsurf_make_derived_from_derived(dm, &smd, 0, 0, 0, 0); - dm->release(dm); - /* for convenience, convert back to cddm (could use ccgdm - later for better performance though? (TODO)) */ - dm = CDDM_copy(subdm); - subdm->release(subdm); - - bsphere_evolve(CDDM_get_verts(dm), dm->getNumVerts(dm), &bs->rootbase, - bs->skin_threshold, bs->evolve, bs->subdiv_level); - } - - return dm; -} -#endif diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index b9d6badfbe9..8d19322c0db 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -805,15 +805,7 @@ static void layerDefault_mcol(void *data, int count) mcol[i] = default_mcol; } -static void layerDefault_skin(void *data, int count) -{ - SkinNode *n = data; - int i; - - for(i = 0; i < count; i++) { - n[i].radius = 0.25; - } -} + static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL}, @@ -851,8 +843,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { layerSwap_mcol, layerDefault_mcol}, {sizeof(MCol)*4, "MCol", 4, "TexturedCol", NULL, NULL, layerInterp_mcol, layerSwap_mcol, layerDefault_mcol}, - {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, - {sizeof(SkinNode), "SkinNode", 1, "Skin", NULL, NULL, NULL, NULL, layerDefault_skin} + {sizeof(float)*3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL} }; static const char *LAYERTYPENAMES[CD_NUMTYPES] = { @@ -860,7 +851,7 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = { /* 5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags", /* 10-14 */ "CDMFloatProperty", "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", /* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDisps", - /* 20-24 */ "CDWeightMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco", "CDSkinNode" + /* 20-23 */"CDWeightMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco" }; const CustomDataMask CD_MASK_BAREMESH = @@ -868,12 +859,10 @@ const CustomDataMask CD_MASK_BAREMESH = const CustomDataMask CD_MASK_MESH = CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | - CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS | - CD_MASK_SKIN_NODE; + CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS; const CustomDataMask CD_MASK_EDITMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | - CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS | - CD_MASK_SKIN_NODE; + CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS; const CustomDataMask CD_MASK_DERIVEDMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_CLOTH_ORCO | diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 061e9460956..cdfcf465c6c 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -92,8 +92,7 @@ typedef struct CustomData { #define CD_ID_MCOL 21 #define CD_TEXTURE_MCOL 22 #define CD_CLOTH_ORCO 23 -#define CD_SKIN_NODE 24 -#define CD_NUMTYPES 25 +#define CD_NUMTYPES 24 /* Bits for CustomDataMask */ #define CD_MASK_MVERT (1 << CD_MVERT) @@ -118,7 +117,6 @@ typedef struct CustomData { #define CD_MASK_MDISPS (1 << CD_MDISPS) #define CD_MASK_WEIGHT_MCOL (1 << CD_WEIGHT_MCOL) #define CD_MASK_CLOTH_ORCO (1 << CD_CLOTH_ORCO) -#define CD_MASK_SKIN_NODE (1 << CD_SKIN_NODE) /* CustomData.flag */ diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index a71c4970eb5..e3510b3a25a 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -184,11 +184,6 @@ typedef struct PartialVisibility { unsigned int totface, totedge, totvert, pad; } PartialVisibility; -typedef struct SkinNode { - float radius; - int pad; -} SkinNode; - /* mvert->flag (1=SELECT) */ #define ME_SPHERETEST 2 #define ME_VERT_TMP_TAG 4 diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 483bd339b3d..3787675f339 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -71,7 +71,6 @@ typedef enum ModifierType { eModifierType_Solidify, eModifierType_Screw, eModifierType_Warp, - eModifierType_Skin, NUM_MODIFIER_TYPES } ModifierType; @@ -786,17 +785,4 @@ typedef enum { /* PROP_RANDOM not used */ } WarpModifierFalloff; -typedef enum SkinModifierFlags { - MOD_SKIN_DRAW_SKIN = (1<<0), - MOD_SKIN_DRAW_NODES = (1<<1), -} SkinModifierFlags; - -typedef struct SkinModifierData { - ModifierData modifier; - float threshold; - int subdiv; - int flag; - int pad; -} SkinModifierData; - #endif diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index b4a4c593ba9..ba655915fb6 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -68,7 +68,6 @@ EnumPropertyItem modifier_type_items[] ={ {eModifierType_Solidify, "SOLIDIFY", ICON_MOD_SOLIDIFY, "Solidify", ""}, {eModifierType_Subsurf, "SUBSURF", ICON_MOD_SUBSURF, "Subdivision Surface", ""}, {eModifierType_UVProject, "UV_PROJECT", ICON_MOD_UVPROJECT, "UV Project", ""}, - {eModifierType_Skin, "SKIN", ICON_MOD_ARMATURE, "Skin", ""}, {0, "", 0, "Deform", ""}, {eModifierType_Armature, "ARMATURE", ICON_MOD_ARMATURE, "Armature", ""}, {eModifierType_Cast, "CAST", ICON_MOD_CAST, "Cast", ""}, @@ -184,8 +183,6 @@ static StructRNA* rna_Modifier_refine(struct PointerRNA *ptr) return &RNA_ScrewModifier; case eModifierType_Warp: return &RNA_WarpModifier; - case eModifierType_Skin: - return &RNA_SkinModifier; default: return &RNA_Modifier; } @@ -2415,17 +2412,6 @@ static void rna_def_modifier_screw(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update");*/ } -static void rna_def_modifier_skin(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - - srna= RNA_def_struct(brna, "SkinModifier", "Modifier"); - RNA_def_struct_ui_text(srna, "Skin Modifier", "Generate Skin"); - RNA_def_struct_sdna(srna, "SkinModifierData"); - RNA_def_struct_ui_icon(srna, ICON_MOD_ARMATURE); -} - void RNA_def_modifier(BlenderRNA *brna) { StructRNA *srna; @@ -2523,7 +2509,6 @@ void RNA_def_modifier(BlenderRNA *brna) rna_def_modifier_smoke(brna); rna_def_modifier_solidify(brna); rna_def_modifier_screw(brna); - rna_def_modifier_skin(brna); } #endif diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 7db03f48631..d1f153265ac 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -70,7 +70,6 @@ set(SRC intern/MOD_shapekey.c intern/MOD_shrinkwrap.c intern/MOD_simpledeform.c - intern/MOD_skin.c intern/MOD_smoke.c intern/MOD_smooth.c intern/MOD_softbody.c diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h index 329037ee210..4e44a226c64 100644 --- a/source/blender/modifiers/MOD_modifiertypes.h +++ b/source/blender/modifiers/MOD_modifiertypes.h @@ -72,7 +72,6 @@ extern ModifierTypeInfo modifierType_ShapeKey; extern ModifierTypeInfo modifierType_Solidify; extern ModifierTypeInfo modifierType_Screw; extern ModifierTypeInfo modifierType_Warp; -extern ModifierTypeInfo modifierType_Skin; /* MOD_util.c */ void modifier_type_init(ModifierTypeInfo *types[]); diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c deleted file mode 100644 index adc47f32c9c..00000000000 --- a/source/blender/modifiers/intern/MOD_skin.c +++ /dev/null @@ -1,88 +0,0 @@ -/* -* $Id$ -* -* ***** BEGIN GPL LICENSE BLOCK ***** -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software Foundation, -* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -* -* ***** END GPL LICENSE BLOCK ***** -* -*/ - -/** \file blender/modifiers/intern/MOD_skin.c - * \ingroup modifiers - */ - - -#include - -#include "BKE_cdderivedmesh.h" -#include "BKE_modifier.h" - -#include "DNA_mesh_types.h" -#include "DNA_object_types.h" - -#include "MOD_util.h" - -static void initData(ModifierData *md) -{ - SkinModifierData *smd = (SkinModifierData*)md; - - smd->threshold = 0; - smd->subdiv = 1; - smd->flag = MOD_SKIN_DRAW_NODES; -} - -static void copyData(ModifierData *md, ModifierData *target) -{ - SkinModifierData *smd = (SkinModifierData*) md; - SkinModifierData *tsmd = (SkinModifierData*) target; - - tsmd->threshold = smd->threshold; - tsmd->subdiv = smd->subdiv; - tsmd->flag = smd->flag; -} - -static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm, - int useRenderParams, int isFinalCalc) -{ - return dm; -} - - -ModifierTypeInfo modifierType_Skin = { - /* name */ "Skin", - /* structName */ "SkinModifierData", - /* structSize */ sizeof(SkinModifierData), - /* type */ eModifierTypeType_Constructive, - /* flags */ eModifierTypeFlag_AcceptsMesh, - - /* copyData */ copyData, - /* deformVerts */ NULL, - /* deformMatrices */ NULL, - /* deformVertsEM */ NULL, - /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, - /* applyModifierEM */ NULL, - /* initData */ initData, - /* requiredDataMask */ NULL, - /* freeData */ NULL, - /* isDisabled */ NULL, - /* updateDepgraph */ NULL, - /* dependsOnTime */ NULL, - /* dependsOnNormals */ NULL, - /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, -}; diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index e823a347ced..e9b835eab81 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -295,6 +295,5 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(Solidify); INIT_TYPE(Screw); INIT_TYPE(Warp); - INIT_TYPE(Skin); #undef INIT_TYPE } -- cgit v1.2.3 From 670f58023c478995ed055e194482ab288db436a7 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 31 Jul 2011 02:34:53 +0000 Subject: == PBVH == OK, after that failure of committing a bunch of old junk, hopefully this is what I actually meant to commit :) * Added big comments to some of the fields in struct PBVHNode. I always forget the details of these, so finally wrote it down properly. * Changed types of PBVHNode.face_vert_indices and PBVHNode.flag to better reflect their contents. * There should be no functional changes here. --- source/blender/blenlib/intern/pbvh.c | 83 +++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 20 deletions(-) diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c index 85d79ae3b85..0613765b868 100644 --- a/source/blender/blenlib/intern/pbvh.c +++ b/source/blender/blenlib/intern/pbvh.c @@ -26,7 +26,6 @@ - #include "DNA_meshdata_types.h" #include "MEM_guardedalloc.h" @@ -85,25 +84,61 @@ struct PBVHNode { /* Opaque handle for drawing code */ void *draw_buffers; - int *vert_indices; - /* Voxel bounds */ BB vb; BB orig_vb; - /* For internal nodes */ + /* For internal nodes, the offset of the children in the PBVH + 'nodes' array. */ int children_offset; - /* Pointer into bvh prim_indices */ - int *prim_indices; - int *face_vert_indices; + /* Pointer into the PBVH prim_indices array and the number of + primitives used by this leaf node. + Used for leaf nodes in both mesh- and multires-based PBVHs. + */ + int *prim_indices; unsigned int totprim; + + /* Array of indices into the mesh's MVert array. Contains the + indices of all vertices used by faces that are within this + node's bounding box. + + Note that a vertex might be used by a multiple faces, and + these faces might be in different leaf nodes. Such a vertex + will appear in the vert_indices array of each of those leaf + nodes. + + In order to support cases where you want access to multiple + nodes' vertices without duplication, the vert_indices array + is ordered such that the first part of the array, up to + index 'uniq_verts', contains "unique" vertex indices. These + vertices might not be truly unique to this node, but if + they appear in another node's vert_indices array, they will + be above that node's 'uniq_verts' value. + + Used for leaf nodes in a mesh-based PBVH (not multires.) + */ + int *vert_indices; unsigned int uniq_verts, face_verts; - char flag; + /* An array mapping face corners into the vert_indices + array. The array is sized to match 'totprim', and each of + the face's corners gets an index into the vert_indices + array, in the same order as the corners in the original + MFace. The fourth value should not be used if the original + face is a triangle. + + Used for leaf nodes in a mesh-based PBVH (not multires.) + */ + int (*face_vert_indices)[4]; + + /* Indicates whether this node is a leaf or not; also used for + marking various updates that need to be applied. */ + PBVHNodeFlags flag : 8; - float tmin; // used for raycasting, is how close bb is to the ray point + /* Used for raycasting: how close bb is to the ray point. */ + float tmin; int proxy_count; PBVHProxyNode* proxies; @@ -339,15 +374,15 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) node->uniq_verts = node->face_verts = 0; totface= node->totprim; - node->face_vert_indices = MEM_callocN(sizeof(int) * - 4*totface, "bvh node face vert indices"); + node->face_vert_indices = MEM_callocN(sizeof(int) * 4*totface, + "bvh node face vert indices"); for(i = 0; i < totface; ++i) { MFace *f = bvh->faces + node->prim_indices[i]; int sides = f->v4 ? 4 : 3; for(j = 0; j < sides; ++j) { - node->face_vert_indices[i*4 + j]= + node->face_vert_indices[i][j]= map_insert_vert(bvh, map, &node->face_verts, &node->uniq_verts, (&f->v1)[j]); } @@ -373,9 +408,17 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) BLI_ghashIterator_free(iter); - for(i = 0; i < totface*4; ++i) - if(node->face_vert_indices[i] < 0) - node->face_vert_indices[i]= -node->face_vert_indices[i] + node->uniq_verts - 1; + for(i = 0; i < totface; ++i) { + MFace *f = bvh->faces + node->prim_indices[i]; + int sides = f->v4 ? 4 : 3; + + for(j = 0; j < sides; ++j) { + if(node->face_vert_indices[i][j] < 0) + node->face_vert_indices[i][j]= + -node->face_vert_indices[i][j] + + node->uniq_verts - 1; + } + } if(!G.background) { node->draw_buffers = @@ -1340,20 +1383,20 @@ int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], if(bvh->faces) { MVert *vert = bvh->verts; int *faces= node->prim_indices; - int *face_verts= node->face_vert_indices; int totface= node->totprim; int i; for(i = 0; i < totface; ++i) { MFace *f = bvh->faces + faces[i]; + int *face_verts = node->face_vert_indices[i]; if(origco) { /* intersect with backuped original coordinates */ hit |= ray_face_intersection(ray_start, ray_normal, - origco[face_verts[i*4+0]], - origco[face_verts[i*4+1]], - origco[face_verts[i*4+2]], - f->v4? origco[face_verts[i*4+3]]: NULL, + origco[face_verts[0]], + origco[face_verts[1]], + origco[face_verts[2]], + f->v4? origco[face_verts[3]]: NULL, dist); } else { -- cgit v1.2.3 From 4745e3da129fcf208e72d11e60e53a339c275fd7 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 31 Jul 2011 03:06:00 +0000 Subject: improved ndof fly: precision mode, camera position, camera animation --- source/blender/editors/space_view3d/view3d_fly.c | 244 +++++++++++++---------- 1 file changed, 136 insertions(+), 108 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index c7ebc296896..34e355c977e 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -599,6 +599,75 @@ static void flyEvent(FlyInfo *fly, wmEvent *event) } } + +static void move_camera(bContext* C, RegionView3D* rv3d, FlyInfo* fly, int orientationChanged, int positionChanged) +{ + /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */ + + View3D* v3d = fly->v3d; + Scene *scene= fly->scene; + ID *id_key; + + /* transform the parent or the camera? */ + if(fly->root_parent) { + Object *ob_update; + + float view_mat[4][4]; + float prev_view_mat[4][4]; + float prev_view_imat[4][4]; + float diff_mat[4][4]; + float parent_mat[4][4]; + + ED_view3d_to_m4(prev_view_mat, fly->rv3d->ofs, fly->rv3d->viewquat, fly->rv3d->dist); + invert_m4_m4(prev_view_imat, prev_view_mat); + ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); + mul_m4_m4m4(diff_mat, prev_view_imat, view_mat); + mul_m4_m4m4(parent_mat, fly->root_parent->obmat, diff_mat); + object_apply_mat4(fly->root_parent, parent_mat, TRUE, FALSE); + + // where_is_object(scene, fly->root_parent); + + ob_update= v3d->camera->parent; + while(ob_update) { + DAG_id_tag_update(&ob_update->id, OB_RECALC_OB); + ob_update= ob_update->parent; + } + + id_key= &fly->root_parent->id; + } + else { + float view_mat[4][4]; + ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); + object_apply_mat4(v3d->camera, view_mat, TRUE, FALSE); + id_key= &v3d->camera->id; + } + + /* record the motion */ + if (autokeyframe_cfra_can_key(scene, id_key)) { + ListBase dsources = {NULL, NULL}; + + /* add datasource override for the camera object */ + ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL); + + /* insert keyframes + * 1) on the first frame + * 2) on each subsequent frame + * TODO: need to check in future that frame changed before doing this + */ + if (orientationChanged) { + KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation"); + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); + } + if (positionChanged) { + KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Location"); + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); + } + + /* free temp data */ + BLI_freelistN(&dsources); + } +} + static int flyApply(bContext *C, FlyInfo *fly) { @@ -611,11 +680,7 @@ static int flyApply(bContext *C, FlyInfo *fly) a fly loop where the user can move move the view as if they are flying */ RegionView3D *rv3d= fly->rv3d; - View3D *v3d = fly->v3d; ARegion *ar = fly->ar; - Scene *scene= fly->scene; - - float prev_view_mat[4][4]; float mat[3][3], /* 3x3 copy of the view matrix so we can move allong the view axis */ dvec[3]={0,0,0}, /* this is the direction thast added to the view offset per redraw */ @@ -638,8 +703,6 @@ static int flyApply(bContext *C, FlyInfo *fly) printf("fly timer %d\n", iteration++); #endif - if(fly->root_parent) - ED_view3d_to_m4(prev_view_mat, fly->rv3d->ofs, fly->rv3d->viewquat, fly->rv3d->dist); xmargin= ar->winx/20.0f; ymargin= ar->winy/20.0f; @@ -756,7 +819,7 @@ static int flyApply(bContext *C, FlyInfo *fly) mul_m3_v3(mat, upvec); } - axis_angle_to_quat( tmp_quat, upvec, (float)moffset[0] * time_redraw * FLY_ROTATE_FAC); /* Rotate about the relative up vec */ + axis_angle_to_quat(tmp_quat, upvec, (float)moffset[0] * time_redraw * FLY_ROTATE_FAC); /* Rotate about the relative up vec */ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); if (fly->xlock) fly->xlock = 2;/*check for rotation*/ @@ -850,69 +913,9 @@ static int flyApply(bContext *C, FlyInfo *fly) ED_area_headerprint(fly->ar, "FlyKeys Speed:(+/- | Wheel), Upright Axis:X off/Z off, Slow:Shift, Direction:WASDRF, Ok:LMB, Pan:MMB, Cancel:RMB"); #endif - /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */ - if (rv3d->persp==RV3D_CAMOB) { - ID *id_key; - /* transform the parent or the camera? */ - if(fly->root_parent) { - Object *ob_update; - - float view_mat[4][4]; - float prev_view_imat[4][4]; - float diff_mat[4][4]; - float parent_mat[4][4]; - - invert_m4_m4(prev_view_imat, prev_view_mat); - ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); - mul_m4_m4m4(diff_mat, prev_view_imat, view_mat); - mul_m4_m4m4(parent_mat, fly->root_parent->obmat, diff_mat); - object_apply_mat4(fly->root_parent, parent_mat, TRUE, FALSE); - - // where_is_object(scene, fly->root_parent); - - ob_update= v3d->camera->parent; - while(ob_update) { - DAG_id_tag_update(&ob_update->id, OB_RECALC_OB); - ob_update= ob_update->parent; - } - - copy_m4_m4(prev_view_mat, view_mat); - - id_key= &fly->root_parent->id; + if (rv3d->persp==RV3D_CAMOB) + move_camera(C, rv3d, fly, (fly->xlock || fly->zlock || moffset[0] || moffset[1]), fly->speed); - } - else { - float view_mat[4][4]; - ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); - object_apply_mat4(v3d->camera, view_mat, TRUE, FALSE); - id_key= &v3d->camera->id; - } - - /* record the motion */ - if (autokeyframe_cfra_can_key(scene, id_key)) { - ListBase dsources = {NULL, NULL}; - - /* add datasource override for the camera object */ - ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL); - - /* insert keyframes - * 1) on the first frame - * 2) on each subsequent frame - * TODO: need to check in future that frame changed before doing this - */ - if (fly->xlock || fly->zlock || moffset[0] || moffset[1]) { - KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation"); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); - } - if (fly->speed) { - KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Location"); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); - } - - /* free temp data */ - BLI_freelistN(&dsources); - } - } } else /*were not redrawing but we need to update the time else the view will jump */ fly->time_lastdraw= PIL_check_seconds_timer(); @@ -931,13 +934,8 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) RegionView3D* rv3d = fly->rv3d; const int flag = U.ndof_flag; - const int shouldRotate = TRUE, - shouldTranslate = TRUE; - - // const int shouldRotate = flag & NDOF_SHOULD_ROTATE, - // shouldTranslate = flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM); - // might also be something in FlyInfo that restricts motion - // if so, change these ^^ + int shouldRotate = (flag & NDOF_SHOULD_ROTATE) && (fly->pan_view == FALSE), + shouldTranslate = (flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM)); float view_inv[4]; invert_qt_qt(view_inv, rv3d->viewquat); @@ -959,22 +957,36 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) forward_sensitivity * ndof->tz }; + if (fly->use_precision) + speed *= 0.2f; + mul_v3_fl(trans, speed * dt); // transform motion from view to world coordinates mul_qt_v3(view_inv, trans); if (flag & NDOF_FLY_HELICOPTER) - // could also use RNA to get a simple boolean value { // replace world z component with device y (yes it makes sense) trans[2] = speed * dt * vertical_sensitivity * ndof->ty; } - // move center of view opposite of hand motion (this is camera mode, not object mode) - sub_v3_v3(rv3d->ofs, trans); + if (rv3d->persp==RV3D_CAMOB) { + // respect camera position locks + Object *lock_ob= fly->root_parent ? fly->root_parent : fly->v3d->camera; + if (lock_ob->protectflag & OB_LOCK_LOCX) trans[0] = 0.0; + if (lock_ob->protectflag & OB_LOCK_LOCY) trans[1] = 0.0; + if (lock_ob->protectflag & OB_LOCK_LOCZ) trans[2] = 0.0; + } - fly->redraw = 1; + if (trans[0] || trans[1] || trans[2]) + { + // move center of view opposite of hand motion (this is camera mode, not object mode) + sub_v3_v3(rv3d->ofs, trans); + shouldTranslate = TRUE; + } + else + shouldTranslate = FALSE; } if (shouldRotate) @@ -985,44 +997,60 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) float axis[3]; float angle = turn_sensitivity * ndof_to_angle_axis(ndof, axis); - // transform rotation axis from view to world coordinates - mul_qt_v3(view_inv, axis); + if (fabsf(angle) > 0.0001f) + { + shouldRotate = TRUE; - // apply rotation to view - axis_angle_to_quat(rotation, axis, angle); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); + if (fly->use_precision) + angle *= 0.2f; - if (flag & NDOF_LOCK_HORIZON) - // force an upright viewpoint - // TODO: make this less... sudden - { - float view_horizon[3] = {1, 0, 0}; // view +x - float view_direction[3] = {0, 0, -1}; // view -z (into screen) + // transform rotation axis from view to world coordinates + mul_qt_v3(view_inv, axis); - // find new inverse since viewquat has changed - invert_qt_qt(view_inv, rv3d->viewquat); - // could apply reverse rotation to existing view_inv to save a few cycles + // apply rotation to view + axis_angle_to_quat(rotation, axis, angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); - // transform view vectors to world coordinates - mul_qt_v3(view_inv, view_horizon); - mul_qt_v3(view_inv, view_direction); + if (flag & NDOF_LOCK_HORIZON) + // force an upright viewpoint + // TODO: make this less... sudden + { + float view_horizon[3] = {1, 0, 0}; // view +x + float view_direction[3] = {0, 0, -1}; // view -z (into screen) - // find difference between view & world horizons - // true horizon lives in world xy plane, so look only at difference in z - angle = -asinf(view_horizon[2]); + // find new inverse since viewquat has changed + invert_qt_qt(view_inv, rv3d->viewquat); + // could apply reverse rotation to existing view_inv to save a few cycles - #ifdef NDOF_FLY_DEBUG - printf("lock horizon: adjusting %.1f degrees\n\n", RAD2DEG(angle)); - #endif + // transform view vectors to world coordinates + mul_qt_v3(view_inv, view_horizon); + mul_qt_v3(view_inv, view_direction); - // rotate view so view horizon = world horizon - axis_angle_to_quat(rotation, view_direction, angle); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); + // find difference between view & world horizons + // true horizon lives in world xy plane, so look only at difference in z + angle = -asinf(view_horizon[2]); + + #ifdef NDOF_FLY_DEBUG + printf("lock horizon: adjusting %.1f degrees\n\n", RAD2DEG(angle)); + #endif + + // rotate view so view horizon = world horizon + axis_angle_to_quat(rotation, view_direction, angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); + } + + rv3d->view = RV3D_VIEW_USER; } + else + shouldRotate = FALSE; + } - rv3d->view = RV3D_VIEW_USER; + if (shouldTranslate || shouldRotate) + { + fly->redraw = TRUE; - fly->redraw = 1; + if (rv3d->persp==RV3D_CAMOB) + move_camera(C, rv3d, fly, shouldRotate, shouldTranslate); } return OPERATOR_FINISHED; -- cgit v1.2.3 From f4293067c1420827ddfa62e62430870c6b790a8a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 31 Jul 2011 03:15:37 +0000 Subject: py api: sphinx doc corrections, pep8 cleanup and style edits, also added __all__ to some modules which were missing it. --- build_files/cmake/cmake_consistency_check.py | 2 +- build_files/cmake/cmake_netbeans_project.py | 2 +- build_files/cmake/cmake_qtcreator_project.py | 2 +- doc/python_api/rst/bge.constraints.rst | 2 +- doc/python_api/rst/bge.events.rst | 2 +- doc/python_api/rst/bge.logic.rst | 3 +- doc/python_api/rst/bge.render.rst | 12 +- doc/python_api/rst/bge.texture.rst | 2 +- doc/python_api/rst/bge.types.rst | 2 +- doc/python_api/rst/bgl.rst | 7 +- doc/python_api/sphinx_doc_gen.py | 19 ++- release/scripts/modules/addon_utils.py | 45 ++++-- release/scripts/modules/bpy/__init__.py | 7 +- release/scripts/modules/bpy/path.py | 86 +++++++---- release/scripts/modules/bpy/utils.py | 81 +++++++--- release/scripts/modules/bpy_extras/__init__.py | 4 +- release/scripts/modules/bpy_extras/image_utils.py | 19 ++- release/scripts/modules/bpy_extras/io_utils.py | 169 ++++++++++++++++----- release/scripts/modules/bpy_extras/mesh_utils.py | 2 +- release/scripts/modules/bpy_extras/object_utils.py | 41 +++-- release/scripts/modules/bpy_extras/view3d_utils.py | 18 ++- release/scripts/modules/keyingsets_utils.py | 9 +- source/blender/python/intern/bpy_rna.c | 4 +- 23 files changed, 381 insertions(+), 159 deletions(-) diff --git a/build_files/cmake/cmake_consistency_check.py b/build_files/cmake/cmake_consistency_check.py index ba71603b007..880cb582f1e 100755 --- a/build_files/cmake/cmake_consistency_check.py +++ b/build_files/cmake/cmake_consistency_check.py @@ -39,7 +39,7 @@ def replace_line(f, i, text, keep_indent=True): file_handle = open(f, 'r') data = file_handle.readlines() file_handle.close() - + l = data[i] ws = l[:len(l) - len(l.lstrip())] diff --git a/build_files/cmake/cmake_netbeans_project.py b/build_files/cmake/cmake_netbeans_project.py index 8060574580c..02dfec06c0b 100755 --- a/build_files/cmake/cmake_netbeans_project.py +++ b/build_files/cmake/cmake_netbeans_project.py @@ -37,7 +37,7 @@ from project_info import (SIMPLE_PROJECTFILE, source_list, is_project_file, is_c_header, - is_py, + # is_py, cmake_advanced_info, cmake_compiler_defines, ) diff --git a/build_files/cmake/cmake_qtcreator_project.py b/build_files/cmake/cmake_qtcreator_project.py index d8993c3197a..2a2774c9944 100755 --- a/build_files/cmake/cmake_qtcreator_project.py +++ b/build_files/cmake/cmake_qtcreator_project.py @@ -33,7 +33,7 @@ example linux usage from project_info import (SIMPLE_PROJECTFILE, SOURCE_DIR, - CMAKE_DIR, + # CMAKE_DIR, PROJECT_DIR, source_list, is_project_file, diff --git a/doc/python_api/rst/bge.constraints.rst b/doc/python_api/rst/bge.constraints.rst index 2e7bc2daed4..12ce8617457 100644 --- a/doc/python_api/rst/bge.constraints.rst +++ b/doc/python_api/rst/bge.constraints.rst @@ -1,6 +1,6 @@ Physics Constraints (bge.constraints) -================================== +===================================== .. function:: createConstraint(physicsid, physicsid2, constrainttype, [pivotX, pivotY, pivotZ, [axisX, axisY, axisZ, [flag]]]]) diff --git a/doc/python_api/rst/bge.events.rst b/doc/python_api/rst/bge.events.rst index f6f465d0cd3..074e928f0d8 100644 --- a/doc/python_api/rst/bge.events.rst +++ b/doc/python_api/rst/bge.events.rst @@ -1,6 +1,6 @@ Game Keys (bge.events) -============================= +====================== ***** Intro diff --git a/doc/python_api/rst/bge.logic.rst b/doc/python_api/rst/bge.logic.rst index 53a2362b8d9..128f87f76bd 100644 --- a/doc/python_api/rst/bge.logic.rst +++ b/doc/python_api/rst/bge.logic.rst @@ -1,6 +1,7 @@ Game Logic (bge.logic) -============================ +====================== + ***** Intro ***** diff --git a/doc/python_api/rst/bge.render.rst b/doc/python_api/rst/bge.render.rst index f56b3d619ad..10514049a8a 100644 --- a/doc/python_api/rst/bge.render.rst +++ b/doc/python_api/rst/bge.render.rst @@ -1,6 +1,6 @@ Rasterizer (bge.render) -============================= +======================= ***** Intro @@ -16,8 +16,8 @@ Intro import bge.render import bge.logic - # SCALE sets the speed of motion - SCALE=[1, 0.5] + # scale sets the speed of motion + scale = 1.0, 0.5 co = bge.logic.getCurrentController() obj = co.getOwner() @@ -27,8 +27,8 @@ Intro # Transform the mouse coordinates to see how far the mouse has moved. def mousePos(): - x = (bge.render.getWindowWidth()/2 - mouse.getXPosition())*SCALE[0] - y = (bge.render.getWindowHeight()/2 - mouse.getYPosition())*SCALE[1] + x = (bge.render.getWindowWidth() / 2 - mouse.getXPosition()) * scale[0] + y = (bge.render.getWindowHeight() / 2 - mouse.getYPosition()) * scale[1] return (x, y) pos = mousePos() @@ -43,7 +43,7 @@ Intro bge.logic.addActiveActuator(wmotion, True) # Centre the mouse - bge.render.setMousePosition(bge.render.getWindowWidth()/2, bge.render.getWindowHeight()/2) + bge.render.setMousePosition(bge.render.getWindowWidth() / 2, bge.render.getWindowHeight() / 2) ********* Constants diff --git a/doc/python_api/rst/bge.texture.rst b/doc/python_api/rst/bge.texture.rst index 53de315fa75..f3e9f98dded 100644 --- a/doc/python_api/rst/bge.texture.rst +++ b/doc/python_api/rst/bge.texture.rst @@ -1,6 +1,6 @@ Video Texture (bge.texture) -============================== +=========================== ***** Intro diff --git a/doc/python_api/rst/bge.types.rst b/doc/python_api/rst/bge.types.rst index 1e9e1cca58e..36ef9154e17 100644 --- a/doc/python_api/rst/bge.types.rst +++ b/doc/python_api/rst/bge.types.rst @@ -1,6 +1,6 @@ Game Types (bge.types) -============================= +====================== .. module:: bge.types diff --git a/doc/python_api/rst/bgl.rst b/doc/python_api/rst/bgl.rst index ef15d31f43e..236bfafb295 100644 --- a/doc/python_api/rst/bgl.rst +++ b/doc/python_api/rst/bgl.rst @@ -1,6 +1,6 @@ OpenGL Wrapper (bgl) -=========================== +==================== .. module:: bgl @@ -71,8 +71,8 @@ OpenGL}" and the online NeHe tutorials are two of the best resources. .. seealso:: `OpenGL Docs `_ :type mode: Enumerated constant - :arg mode: Specifies the primitive that will be create from vertices between glBegin and - glEnd. + :arg mode: Specifies the primitive that will be create from vertices between + glBegin and glEnd. .. function:: glBindTexture(target, texture): @@ -1886,4 +1886,3 @@ class Buffer: the Buffer. If a template is not passed in all fields will be initialized to 0. :rtype: Buffer object :return: The newly created buffer as a PyObject. - diff --git a/doc/python_api/sphinx_doc_gen.py b/doc/python_api/sphinx_doc_gen.py index 6b514cf9eb1..f8561c719bc 100644 --- a/doc/python_api/sphinx_doc_gen.py +++ b/doc/python_api/sphinx_doc_gen.py @@ -416,6 +416,7 @@ def pymodule2sphinx(BASEPATH, module_name, module, title): del key, descr classes = [] + submodules = [] for attribute in module_dir: if not attribute.startswith("_"): @@ -437,6 +438,8 @@ def pymodule2sphinx(BASEPATH, module_name, module, title): py_c_func2sphinx("", fw, module_name, None, attribute, value, is_class=False) elif value_type == type: classes.append((attribute, value)) + elif issubclass(value_type, types.ModuleType): + submodules.append((attribute, value)) elif value_type in (bool, int, float, str, tuple): # constant, not much fun we can do here except to list it. # TODO, figure out some way to document these! @@ -444,12 +447,26 @@ def pymodule2sphinx(BASEPATH, module_name, module, title): write_indented_lines(" ", fw, "constant value %s" % repr(value), False) fw("\n") else: - print("\tnot documenting %s.%s" % (module_name, attribute)) + print("\tnot documenting %s.%s of %r type" % (module_name, attribute, value_type.__name__)) continue attribute_set.add(attribute) # TODO, more types... + # TODO, bpy_extras does this already, mathutils not. + """ + if submodules: + fw("\n" + "**********\n" + "Submodules\n" + "**********\n" + "\n" + ) + for attribute, submod in submodules: + fw("* :mod:`%s.%s`\n" % (module_name, attribute)) + fw("\n") + """ + # write collected classes now for (type_name, value) in classes: # May need to be its own function diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py index 5aed0581ea9..22936f4c209 100644 --- a/release/scripts/modules/addon_utils.py +++ b/release/scripts/modules/addon_utils.py @@ -16,7 +16,7 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# __all__ = ( "paths", @@ -26,7 +26,7 @@ __all__ = ( "disable", "reset_all", "module_bl_info", -) + ) import bpy as _bpy @@ -129,7 +129,12 @@ def modules(module_cache): error_duplicates = True elif mod.__time__ != os.path.getmtime(mod_path): - print("reloading addon:", mod_name, mod.__time__, os.path.getmtime(mod_path), mod_path) + print("reloading addon:", + mod_name, + mod.__time__, + os.path.getmtime(mod_path), + mod_path, + ) del module_cache[mod_name] mod = None @@ -144,7 +149,9 @@ def modules(module_cache): del modules_stale mod_list = list(module_cache.values()) - mod_list.sort(key=lambda mod: (mod.bl_info['category'], mod.bl_info['name'])) + mod_list.sort(key=lambda mod: (mod.bl_info['category'], + mod.bl_info['name'], + )) return mod_list @@ -164,8 +171,9 @@ def check(module_name): loaded_state = mod and getattr(mod, "__addon_enabled__", Ellipsis) if loaded_state is Ellipsis: - print("Warning: addon-module %r found module but without" - " __addon_enabled__ field, possible name collision from file: %r" % + print("Warning: addon-module %r found module " + "but without __addon_enabled__ field, " + "possible name collision from file: %r" % (module_name, getattr(mod, "__file__", ""))) loaded_state = False @@ -208,7 +216,8 @@ def enable(module_name, default_set=True): return None mod.__addon_enabled__ = False - # Split registering up into 3 steps so we can undo if it fails par way through + # Split registering up into 3 steps so we can undo + # if it fails par way through. # 1) try import try: mod = __import__(module_name) @@ -255,8 +264,9 @@ def disable(module_name, default_set=True): import sys mod = sys.modules.get(module_name) - # possible this addon is from a previous session and didnt load a module this time. - # so even if the module is not found, still disable the addon in the user prefs. + # possible this addon is from a previous session and didnt load a + # module this time. So even if the module is not found, still disable + # the addon in the user prefs. if mod: mod.__addon_enabled__ = False @@ -311,7 +321,22 @@ def reset_all(reload_scripts=False): disable(mod_name) -def module_bl_info(mod, info_basis={"name": "", "author": "", "version": (), "blender": (), "api": 0, "location": "", "description": "", "wiki_url": "", "tracker_url": "", "support": 'COMMUNITY', "category": "", "warning": "", "show_expanded": False}): +def module_bl_info(mod, info_basis={"name": "", + "author": "", + "version": (), + "blender": (), + "api": 0, + "location": "", + "description": "", + "wiki_url": "", + "tracker_url": "", + "support": 'COMMUNITY', + "category": "", + "warning": "", + "show_expanded": False, + } + ): + addon_info = getattr(mod, "bl_info", {}) # avoid re-initializing diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py index 0add2b3e6cd..a43b42e49a1 100644 --- a/release/scripts/modules/bpy/__init__.py +++ b/release/scripts/modules/bpy/__init__.py @@ -16,7 +16,7 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# """ Give access to blender data and utility functions. @@ -31,7 +31,7 @@ __all__ = ( "props", "types", "utils", -) + ) # internal blender C module @@ -49,7 +49,8 @@ def _main(): # Possibly temp. addons path from os.path import join, dirname, normpath - _sys.path.append(normpath(join(dirname(__file__), "..", "..", "addons", "modules"))) + _sys.path.append(normpath(join(dirname(__file__), + "..", "..", "addons", "modules"))) # if "-d" in sys.argv: # Enable this to measure startup speed if 0: diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py index eb1a5ffc455..a01745fec0a 100644 --- a/release/scripts/modules/bpy/path.py +++ b/release/scripts/modules/bpy/path.py @@ -16,26 +16,44 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# """ This module has a similar scope to os.path, containing utility functions for dealing with paths in Blender. """ +__all__ = ( + "abspath", + "basename", + "clean_name", + "display_name", + "display_name_from_filepath", + "ensure_ext", + "is_subdir", + "module_names", + "relpath", + "resolve_ncase", + ) + import bpy as _bpy import os as _os def abspath(path, start=None): """ - Returns the absolute path relative to the current blend file using the "//" prefix. + Returns the absolute path relative to the current blend file + using the "//" prefix. - :arg start: Relative to this path, when not set the current filename is used. + :arg start: Relative to this path, + when not set the current filename is used. :type start: string """ if path.startswith("//"): - return _os.path.join(_os.path.dirname(_bpy.data.filepath) if start is None else start, path[2:]) + return _os.path.join(_os.path.dirname(_bpy.data.filepath) + if start is None else start, + path[2:], + ) return path @@ -44,7 +62,8 @@ def relpath(path, start=None): """ Returns the path relative to the current blend file using the "//" prefix. - :arg start: Relative to this path, when not set the current filename is used. + :arg start: Relative to this path, + when not set the current filename is used. :type start: string """ if not path.startswith("//"): @@ -68,27 +87,28 @@ def is_subdir(path, directory): def clean_name(name, replace="_"): """ - Returns a name with characters replaced that may cause problems under various circumstances, such as writing to a file. + Returns a name with characters replaced that + may cause problems under various circumstances, + such as writing to a file. All characters besides A-Z/a-z, 0-9 are replaced with "_" or the replace argument if defined. """ - unclean_chars = \ - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\ - \x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\ - \x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\ - \x2e\x2f\x3a\x3b\x3c\x3d\x3e\x3f\x40\x5b\x5c\x5d\x5e\x60\x7b\ - \x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\ - \x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\ - \x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\ - \xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\ - \xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\ - \xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\ - \xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\ - \xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\ - \xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe" - - for ch in unclean_chars: + bad_chars = ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e" + "\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d" + "\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c" + "\x2e\x2f\x3a\x3b\x3c\x3d\x3e\x3f\x40\x5b\x5c\x5d\x5e\x60\x7b" + "\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a" + "\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99" + "\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8" + "\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7" + "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6" + "\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5" + "\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4" + "\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3" + "\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe") + + for ch in bad_chars: name = name.replace(ch, replace) return name @@ -96,8 +116,9 @@ def clean_name(name, replace="_"): def display_name(name): """ Creates a display string from name to be used menus and the user interface. - Capitalize the first letter in all lowercase names, mixed case names are kept as is. - Intended for use with filenames and module names. + Capitalize the first letter in all lowercase names, + mixed case names are kept as is. Intended for use with + filenames and module names. """ name_base = _os.path.splitext(name)[0] @@ -115,9 +136,11 @@ def display_name(name): def display_name_from_filepath(name): """ - Returns the path stripped of directort and extension, ensured to be utf8 compatible. + Returns the path stripped of directort and extension, + ensured to be utf8 compatible. """ - return _os.path.splitext(basename(name))[0].encode("utf8", "replace").decode("utf8") + name = _os.path.splitext(basename(name))[0] + return name.encode("utf8", "replace").decode("utf8") def resolve_ncase(path): @@ -132,7 +155,8 @@ def resolve_ncase(path): if not path or os.path.exists(path): return path, True - filename = os.path.basename(path) # filename may be a directory or a file + # filename may be a directory or a file + filename = os.path.basename(path) dirpath = os.path.dirname(path) suffix = path[:0] # "" but ensure byte/str match @@ -190,7 +214,9 @@ def ensure_ext(filepath, ext, case_sensitive=False): import os fn_base, fn_ext = os.path.splitext(filepath) if fn_base and fn_ext: - if (case_sensitive and ext == fn_ext) or (ext.lower() == fn_ext.lower()): + if ((case_sensitive and ext == fn_ext) or + (ext.lower() == fn_ext.lower())): + return filepath else: return fn_base + ext @@ -228,7 +254,9 @@ def module_names(path, recursive=False): modules.append((filename, fullpath)) if recursive: for mod_name, mod_path in module_names(directory, True): - modules.append(("%s.%s" % (filename, mod_name), mod_path)) + modules.append(("%s.%s" % (filename, mod_name), + mod_path, + )) return modules diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py index 57d3e6dd703..a6304378cc4 100644 --- a/release/scripts/modules/bpy/utils.py +++ b/release/scripts/modules/bpy/utils.py @@ -16,13 +16,33 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# """ This module contains utility functions specific to blender but not assosiated with blenders internal data. """ +__all__ = ( + "blend_paths", + "keyconfig_set", + "load_scripts", + "modules_from_path", + "preset_find", + "preset_paths", + "refresh_script_paths", + "register_class", + "register_module", + "resource_path", + "script_paths", + "smpte_from_frame", + "smpte_from_seconds", + "unregister_class", + "unregister_module", + "user_resource", + "user_script_path", + ) + from _bpy import register_class, unregister_class, blend_paths, resource_path from _bpy import script_paths as _bpy_script_paths from _bpy import user_resource as _user_resource @@ -42,7 +62,8 @@ def _test_import(module_name, loaded_modules): if module_name in loaded_modules: return None if "." in module_name: - print("Ignoring '%s', can't import files containing multiple periods." % module_name) + print("Ignoring '%s', can't import files containing " + "multiple periods." % module_name) return None if use_time: @@ -74,7 +95,8 @@ def modules_from_path(path, loaded_modules): :arg path: this path is scanned for scripts and packages. :type path: string - :arg loaded_modules: already loaded module names, files matching these names will be ignored. + :arg loaded_modules: already loaded module names, files matching these + names will be ignored. :type loaded_modules: set :return: all loaded modules. :rtype: list @@ -97,13 +119,17 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): """ Load scripts and run each modules register function. - :arg reload_scripts: Causes all scripts to have their unregister method called before loading. + :arg reload_scripts: Causes all scripts to have their unregister method + called before loading. :type reload_scripts: bool - :arg refresh_scripts: only load scripts which are not already loaded as modules. + :arg refresh_scripts: only load scripts which are not already loaded + as modules. :type refresh_scripts: bool """ use_time = _bpy.app.debug + prefs = _bpy.context.user_preferences + if use_time: import time t_main = time.time() @@ -116,10 +142,11 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): if reload_scripts: _bpy_types.TypeMap.clear() - # just unload, dont change user defaults, this means we can sync to reload. - # note that they will only actually reload of the modification time changes. - # this `wont` work for packages so... its not perfect. - for module_name in [ext.module for ext in _bpy.context.user_preferences.addons]: + # just unload, dont change user defaults, this means we can sync + # to reload. note that they will only actually reload of the + # modification time changes. This `wont` work for packages so... + # its not perfect. + for module_name in [ext.module for ext in prefs.addons]: _addon_utils.disable(module_name, default_set=False) def register_module_call(mod): @@ -131,7 +158,9 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): import traceback traceback.print_exc() else: - print("\nWarning! '%s' has no register function, this is now a requirement for registerable scripts." % mod.__file__) + print("\nWarning! '%s' has no register function, " + "this is now a requirement for registerable scripts." % + mod.__file__) def unregister_module_call(mod): unregister = getattr(mod, "unregister", None) @@ -172,7 +201,8 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): if reload_scripts: # module names -> modules - _global_loaded_modules[:] = [_sys.modules[mod_name] for mod_name in _global_loaded_modules] + _global_loaded_modules[:] = [_sys.modules[mod_name] + for mod_name in _global_loaded_modules] # loop over and unload all scripts _global_loaded_modules.reverse() @@ -201,7 +231,8 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): _addon_utils.reset_all(reload_scripts) # run the active integration preset - filepath = preset_find(_bpy.context.user_preferences.inputs.active_keyconfig, "keyconfig") + filepath = preset_find(prefs.inputs.active_keyconfig, "keyconfig") + if filepath: keyconfig_set(filepath) @@ -214,12 +245,16 @@ def load_scripts(reload_scripts=False, refresh_scripts=False): # base scripts -_scripts = _os.path.join(_os.path.dirname(__file__), _os.path.pardir, _os.path.pardir) +_scripts = _os.path.join(_os.path.dirname(__file__), + _os.path.pardir, + _os.path.pardir, + ) _scripts = (_os.path.normpath(_scripts), ) def user_script_path(): - path = _bpy.context.user_preferences.filepaths.script_directory + prefs = _bpy.context.user_preferences + path = prefs.filepaths.script_directory if path: path = _os.path.normpath(path) @@ -236,22 +271,25 @@ def script_paths(subdir=None, user_pref=True, all=False): :type subdir: string :arg user_pref: Include the user preference script path. :type user_pref: bool - :arg all: Include local, user and system paths rather just the paths blender uses. + :arg all: Include local, user and system paths rather just the paths + blender uses. :type all: bool :return: script paths. :rtype: list """ scripts = list(_scripts) + prefs = _bpy.context.user_preferences # add user scripts dir if user_pref: - user_script_path = _bpy.context.user_preferences.filepaths.script_directory + user_script_path = prefs.filepaths.script_directory else: user_script_path = None if all: # all possible paths - base_paths = tuple(_os.path.join(resource_path(res), "scripts") for res in ('LOCAL', 'USER', 'SYSTEM')) + base_paths = tuple(_os.path.join(resource_path(res), "scripts") + for res in ('LOCAL', 'USER', 'SYSTEM')) else: # only paths blender uses base_paths = _bpy_script_paths() @@ -426,7 +464,8 @@ def user_resource(type, path="", create=False): :type type: string :arg subdir: Optional subdirectory. :type subdir: string - :arg create: Treat the path as a directory and create it if its not existing. + :arg create: Treat the path as a directory and create + it if its not existing. :type create: boolean :return: a path. :rtype: string @@ -477,7 +516,8 @@ def register_module(module, verbose=False): try: register_class(cls) except: - print("bpy.utils.register_module(): failed to registering class %r" % cls) + print("bpy.utils.register_module(): " + "failed to registering class %r" % cls) import traceback traceback.print_exc() if verbose: @@ -495,7 +535,8 @@ def unregister_module(module, verbose=False): try: unregister_class(cls) except: - print("bpy.utils.unregister_module(): failed to unregistering class %r" % cls) + print("bpy.utils.unregister_module(): " + "failed to unregistering class %r" % cls) import traceback traceback.print_exc() if verbose: diff --git a/release/scripts/modules/bpy_extras/__init__.py b/release/scripts/modules/bpy_extras/__init__.py index 06d41fa670e..d853d5fda10 100644 --- a/release/scripts/modules/bpy_extras/__init__.py +++ b/release/scripts/modules/bpy_extras/__init__.py @@ -16,7 +16,7 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# """ Utility modules assosiated with the bpy module. @@ -28,4 +28,4 @@ __all__ = ( "image_utils", "mesh_utils", "view3d_utils", -) + ) diff --git a/release/scripts/modules/bpy_extras/image_utils.py b/release/scripts/modules/bpy_extras/image_utils.py index e56c1c651c4..eab75c3bd16 100644 --- a/release/scripts/modules/bpy_extras/image_utils.py +++ b/release/scripts/modules/bpy_extras/image_utils.py @@ -16,11 +16,11 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# __all__ = ( "load_image", -) + ) # limited replacement for BPyImage.comprehensiveImageLoad @@ -33,8 +33,8 @@ def load_image(imagepath, verbose=False, ): """ - Return an image from the file path with options to search multiple paths and - return a placeholder if its not found. + Return an image from the file path with options to search multiple paths + and return a placeholder if its not found. :arg filepath: The image filename If a path precedes it, this will be searched as well. @@ -51,9 +51,10 @@ def load_image(imagepath, :type recursive: bool :arg ncase_cmp: on non windows systems, find the correct case for the file. :type ncase_cmp: bool - :arg convert_callback: a function that takes an existing path and returns a new one. - Use this when loading image formats blender may not support, the CONVERT_CALLBACK - can take the path for a GIF (for example), convert it to a PNG and return the PNG's path. + :arg convert_callback: a function that takes an existing path and returns + a new one. Use this when loading image formats blender may not support, + the CONVERT_CALLBACK can take the path for a GIF (for example), + convert it to a PNG and return the PNG's path. For formats blender can read, simply return the path that is given. :type convert_callback: function :return: an image or None @@ -92,7 +93,9 @@ def load_image(imagepath, for filepath_test in variants: if ncase_cmp: - ncase_variants = filepath_test, bpy.path.resolve_ncase(filepath_test) + ncase_variants = (filepath_test, + bpy.path.resolve_ncase(filepath_test), + ) else: ncase_variants = (filepath_test, ) diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py index 0a3f1392653..f476b371d0c 100644 --- a/release/scripts/modules/bpy_extras/io_utils.py +++ b/release/scripts/modules/bpy_extras/io_utils.py @@ -16,7 +16,7 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# __all__ = ( "ExportHelper", @@ -31,15 +31,25 @@ __all__ = ( "path_reference_copy", "path_reference_mode", "unique_name" -) + ) import bpy from bpy.props import StringProperty, BoolProperty, EnumProperty class ExportHelper: - filepath = StringProperty(name="File Path", description="Filepath used for exporting the file", maxlen=1024, default="", subtype='FILE_PATH') - check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'}) + filepath = StringProperty( + name="File Path", + description="Filepath used for exporting the file", + maxlen=1024, + subtype='FILE_PATH', + ) + check_existing = BoolProperty( + name="Check Existing", + description="Check and warn on overwriting existing files", + default=True, + options={'HIDDEN'}, + ) # subclasses can override with decorator # True == use ext, False == no ext, None == do nothing. @@ -65,7 +75,10 @@ class ExportHelper: if check_extension is None: return False - filepath = bpy.path.ensure_ext(self.filepath, self.filename_ext if check_extension else "") + filepath = bpy.path.ensure_ext(self.filepath, + self.filename_ext + if check_extension + else "") if filepath != self.filepath: self.filepath = filepath @@ -75,7 +88,12 @@ class ExportHelper: class ImportHelper: - filepath = StringProperty(name="File Path", description="Filepath used for importing the file", maxlen=1024, default="", subtype='FILE_PATH') + filepath = StringProperty( + name="File Path", + description="Filepath used for importing the file", + maxlen=1024, + subtype='FILE_PATH', + ) def invoke(self, context, event): context.window_manager.fileselect_add(self) @@ -116,29 +134,75 @@ _axis_convert_matrix = ( # where all 4 values are or'd into a single value... # (i1<<0 | i1<<3 | i1<<6 | i1<<9) _axis_convert_lut = ( - {0x8C8, 0x4D0, 0x2E0, 0xAE8, 0x701, 0x511, 0x119, 0xB29, 0x682, 0x88A, 0x09A, 0x2A2, 0x80B, 0x413, 0x223, 0xA2B, 0x644, 0x454, 0x05C, 0xA6C, 0x745, 0x94D, 0x15D, 0x365}, - {0xAC8, 0x8D0, 0x4E0, 0x2E8, 0x741, 0x951, 0x159, 0x369, 0x702, 0xB0A, 0x11A, 0x522, 0xA0B, 0x813, 0x423, 0x22B, 0x684, 0x894, 0x09C, 0x2AC, 0x645, 0xA4D, 0x05D, 0x465}, - {0x4C8, 0x2D0, 0xAE0, 0x8E8, 0x681, 0x291, 0x099, 0x8A9, 0x642, 0x44A, 0x05A, 0xA62, 0x40B, 0x213, 0xA23, 0x82B, 0x744, 0x354, 0x15C, 0x96C, 0x705, 0x50D, 0x11D, 0xB25}, - {0x2C8, 0xAD0, 0x8E0, 0x4E8, 0x641, 0xA51, 0x059, 0x469, 0x742, 0x34A, 0x15A, 0x962, 0x20B, 0xA13, 0x823, 0x42B, 0x704, 0xB14, 0x11C, 0x52C, 0x685, 0x28D, 0x09D, 0x8A5}, - {0x708, 0xB10, 0x120, 0x528, 0x8C1, 0xAD1, 0x2D9, 0x4E9, 0x942, 0x74A, 0x35A, 0x162, 0x64B, 0xA53, 0x063, 0x46B, 0x804, 0xA14, 0x21C, 0x42C, 0x885, 0x68D, 0x29D, 0x0A5}, - {0xB08, 0x110, 0x520, 0x728, 0x941, 0x151, 0x359, 0x769, 0x802, 0xA0A, 0x21A, 0x422, 0xA4B, 0x053, 0x463, 0x66B, 0x884, 0x094, 0x29C, 0x6AC, 0x8C5, 0xACD, 0x2DD, 0x4E5}, - {0x508, 0x710, 0xB20, 0x128, 0x881, 0x691, 0x299, 0x0A9, 0x8C2, 0x4CA, 0x2DA, 0xAE2, 0x44B, 0x653, 0xA63, 0x06B, 0x944, 0x754, 0x35C, 0x16C, 0x805, 0x40D, 0x21D, 0xA25}, - {0x108, 0x510, 0x720, 0xB28, 0x801, 0x411, 0x219, 0xA29, 0x882, 0x08A, 0x29A, 0x6A2, 0x04B, 0x453, 0x663, 0xA6B, 0x8C4, 0x4D4, 0x2DC, 0xAEC, 0x945, 0x14D, 0x35D, 0x765}, - {0x748, 0x350, 0x160, 0x968, 0xAC1, 0x2D1, 0x4D9, 0x8E9, 0xA42, 0x64A, 0x45A, 0x062, 0x68B, 0x293, 0x0A3, 0x8AB, 0xA04, 0x214, 0x41C, 0x82C, 0xB05, 0x70D, 0x51D, 0x125}, - {0x948, 0x750, 0x360, 0x168, 0xB01, 0x711, 0x519, 0x129, 0xAC2, 0x8CA, 0x4DA, 0x2E2, 0x88B, 0x693, 0x2A3, 0x0AB, 0xA44, 0x654, 0x45C, 0x06C, 0xA05, 0x80D, 0x41D, 0x225}, - {0x348, 0x150, 0x960, 0x768, 0xA41, 0x051, 0x459, 0x669, 0xA02, 0x20A, 0x41A, 0x822, 0x28B, 0x093, 0x8A3, 0x6AB, 0xB04, 0x114, 0x51C, 0x72C, 0xAC5, 0x2CD, 0x4DD, 0x8E5}, - {0x148, 0x950, 0x760, 0x368, 0xA01, 0x811, 0x419, 0x229, 0xB02, 0x10A, 0x51A, 0x722, 0x08B, 0x893, 0x6A3, 0x2AB, 0xAC4, 0x8D4, 0x4DC, 0x2EC, 0xA45, 0x04D, 0x45D, 0x665}, - {0x688, 0x890, 0x0A0, 0x2A8, 0x4C1, 0x8D1, 0xAD9, 0x2E9, 0x502, 0x70A, 0xB1A, 0x122, 0x74B, 0x953, 0x163, 0x36B, 0x404, 0x814, 0xA1C, 0x22C, 0x445, 0x64D, 0xA5D, 0x065}, - {0x888, 0x090, 0x2A0, 0x6A8, 0x501, 0x111, 0xB19, 0x729, 0x402, 0x80A, 0xA1A, 0x222, 0x94B, 0x153, 0x363, 0x76B, 0x444, 0x054, 0xA5C, 0x66C, 0x4C5, 0x8CD, 0xADD, 0x2E5}, - {0x288, 0x690, 0x8A0, 0x0A8, 0x441, 0x651, 0xA59, 0x069, 0x4C2, 0x2CA, 0xADA, 0x8E2, 0x34B, 0x753, 0x963, 0x16B, 0x504, 0x714, 0xB1C, 0x12C, 0x405, 0x20D, 0xA1D, 0x825}, - {0x088, 0x290, 0x6A0, 0x8A8, 0x401, 0x211, 0xA19, 0x829, 0x442, 0x04A, 0xA5A, 0x662, 0x14B, 0x353, 0x763, 0x96B, 0x4C4, 0x2D4, 0xADC, 0x8EC, 0x505, 0x10D, 0xB1D, 0x725}, - {0x648, 0x450, 0x060, 0xA68, 0x2C1, 0x4D1, 0x8D9, 0xAE9, 0x282, 0x68A, 0x89A, 0x0A2, 0x70B, 0x513, 0x123, 0xB2B, 0x204, 0x414, 0x81C, 0xA2C, 0x345, 0x74D, 0x95D, 0x165}, - {0xA48, 0x650, 0x460, 0x068, 0x341, 0x751, 0x959, 0x169, 0x2C2, 0xACA, 0x8DA, 0x4E2, 0xB0B, 0x713, 0x523, 0x12B, 0x284, 0x694, 0x89C, 0x0AC, 0x205, 0xA0D, 0x81D, 0x425}, - {0x448, 0x050, 0xA60, 0x668, 0x281, 0x091, 0x899, 0x6A9, 0x202, 0x40A, 0x81A, 0xA22, 0x50B, 0x113, 0xB23, 0x72B, 0x344, 0x154, 0x95C, 0x76C, 0x2C5, 0x4CD, 0x8DD, 0xAE5}, - {0x048, 0xA50, 0x660, 0x468, 0x201, 0xA11, 0x819, 0x429, 0x342, 0x14A, 0x95A, 0x762, 0x10B, 0xB13, 0x723, 0x52B, 0x2C4, 0xAD4, 0x8DC, 0x4EC, 0x285, 0x08D, 0x89D, 0x6A5}, - {0x808, 0xA10, 0x220, 0x428, 0x101, 0xB11, 0x719, 0x529, 0x142, 0x94A, 0x75A, 0x362, 0x8CB, 0xAD3, 0x2E3, 0x4EB, 0x044, 0xA54, 0x65C, 0x46C, 0x085, 0x88D, 0x69D, 0x2A5}, - {0xA08, 0x210, 0x420, 0x828, 0x141, 0x351, 0x759, 0x969, 0x042, 0xA4A, 0x65A, 0x462, 0xACB, 0x2D3, 0x4E3, 0x8EB, 0x084, 0x294, 0x69C, 0x8AC, 0x105, 0xB0D, 0x71D, 0x525}, - {0x408, 0x810, 0xA20, 0x228, 0x081, 0x891, 0x699, 0x2A9, 0x102, 0x50A, 0x71A, 0xB22, 0x4CB, 0x8D3, 0xAE3, 0x2EB, 0x144, 0x954, 0x75C, 0x36C, 0x045, 0x44D, 0x65D, 0xA65}, + {0x8C8, 0x4D0, 0x2E0, 0xAE8, 0x701, 0x511, 0x119, 0xB29, 0x682, 0x88A, + 0x09A, 0x2A2, 0x80B, 0x413, 0x223, 0xA2B, 0x644, 0x454, 0x05C, 0xA6C, + 0x745, 0x94D, 0x15D, 0x365}, + {0xAC8, 0x8D0, 0x4E0, 0x2E8, 0x741, 0x951, 0x159, 0x369, 0x702, 0xB0A, + 0x11A, 0x522, 0xA0B, 0x813, 0x423, 0x22B, 0x684, 0x894, 0x09C, 0x2AC, + 0x645, 0xA4D, 0x05D, 0x465}, + {0x4C8, 0x2D0, 0xAE0, 0x8E8, 0x681, 0x291, 0x099, 0x8A9, 0x642, 0x44A, + 0x05A, 0xA62, 0x40B, 0x213, 0xA23, 0x82B, 0x744, 0x354, 0x15C, 0x96C, + 0x705, 0x50D, 0x11D, 0xB25}, + {0x2C8, 0xAD0, 0x8E0, 0x4E8, 0x641, 0xA51, 0x059, 0x469, 0x742, 0x34A, + 0x15A, 0x962, 0x20B, 0xA13, 0x823, 0x42B, 0x704, 0xB14, 0x11C, 0x52C, + 0x685, 0x28D, 0x09D, 0x8A5}, + {0x708, 0xB10, 0x120, 0x528, 0x8C1, 0xAD1, 0x2D9, 0x4E9, 0x942, 0x74A, + 0x35A, 0x162, 0x64B, 0xA53, 0x063, 0x46B, 0x804, 0xA14, 0x21C, 0x42C, + 0x885, 0x68D, 0x29D, 0x0A5}, + {0xB08, 0x110, 0x520, 0x728, 0x941, 0x151, 0x359, 0x769, 0x802, 0xA0A, + 0x21A, 0x422, 0xA4B, 0x053, 0x463, 0x66B, 0x884, 0x094, 0x29C, 0x6AC, + 0x8C5, 0xACD, 0x2DD, 0x4E5}, + {0x508, 0x710, 0xB20, 0x128, 0x881, 0x691, 0x299, 0x0A9, 0x8C2, 0x4CA, + 0x2DA, 0xAE2, 0x44B, 0x653, 0xA63, 0x06B, 0x944, 0x754, 0x35C, 0x16C, + 0x805, 0x40D, 0x21D, 0xA25}, + {0x108, 0x510, 0x720, 0xB28, 0x801, 0x411, 0x219, 0xA29, 0x882, 0x08A, + 0x29A, 0x6A2, 0x04B, 0x453, 0x663, 0xA6B, 0x8C4, 0x4D4, 0x2DC, 0xAEC, + 0x945, 0x14D, 0x35D, 0x765}, + {0x748, 0x350, 0x160, 0x968, 0xAC1, 0x2D1, 0x4D9, 0x8E9, 0xA42, 0x64A, + 0x45A, 0x062, 0x68B, 0x293, 0x0A3, 0x8AB, 0xA04, 0x214, 0x41C, 0x82C, + 0xB05, 0x70D, 0x51D, 0x125}, + {0x948, 0x750, 0x360, 0x168, 0xB01, 0x711, 0x519, 0x129, 0xAC2, 0x8CA, + 0x4DA, 0x2E2, 0x88B, 0x693, 0x2A3, 0x0AB, 0xA44, 0x654, 0x45C, 0x06C, + 0xA05, 0x80D, 0x41D, 0x225}, + {0x348, 0x150, 0x960, 0x768, 0xA41, 0x051, 0x459, 0x669, 0xA02, 0x20A, + 0x41A, 0x822, 0x28B, 0x093, 0x8A3, 0x6AB, 0xB04, 0x114, 0x51C, 0x72C, + 0xAC5, 0x2CD, 0x4DD, 0x8E5}, + {0x148, 0x950, 0x760, 0x368, 0xA01, 0x811, 0x419, 0x229, 0xB02, 0x10A, + 0x51A, 0x722, 0x08B, 0x893, 0x6A3, 0x2AB, 0xAC4, 0x8D4, 0x4DC, 0x2EC, + 0xA45, 0x04D, 0x45D, 0x665}, + {0x688, 0x890, 0x0A0, 0x2A8, 0x4C1, 0x8D1, 0xAD9, 0x2E9, 0x502, 0x70A, + 0xB1A, 0x122, 0x74B, 0x953, 0x163, 0x36B, 0x404, 0x814, 0xA1C, 0x22C, + 0x445, 0x64D, 0xA5D, 0x065}, + {0x888, 0x090, 0x2A0, 0x6A8, 0x501, 0x111, 0xB19, 0x729, 0x402, 0x80A, + 0xA1A, 0x222, 0x94B, 0x153, 0x363, 0x76B, 0x444, 0x054, 0xA5C, 0x66C, + 0x4C5, 0x8CD, 0xADD, 0x2E5}, + {0x288, 0x690, 0x8A0, 0x0A8, 0x441, 0x651, 0xA59, 0x069, 0x4C2, 0x2CA, + 0xADA, 0x8E2, 0x34B, 0x753, 0x963, 0x16B, 0x504, 0x714, 0xB1C, 0x12C, + 0x405, 0x20D, 0xA1D, 0x825}, + {0x088, 0x290, 0x6A0, 0x8A8, 0x401, 0x211, 0xA19, 0x829, 0x442, 0x04A, + 0xA5A, 0x662, 0x14B, 0x353, 0x763, 0x96B, 0x4C4, 0x2D4, 0xADC, 0x8EC, + 0x505, 0x10D, 0xB1D, 0x725}, + {0x648, 0x450, 0x060, 0xA68, 0x2C1, 0x4D1, 0x8D9, 0xAE9, 0x282, 0x68A, + 0x89A, 0x0A2, 0x70B, 0x513, 0x123, 0xB2B, 0x204, 0x414, 0x81C, 0xA2C, + 0x345, 0x74D, 0x95D, 0x165}, + {0xA48, 0x650, 0x460, 0x068, 0x341, 0x751, 0x959, 0x169, 0x2C2, 0xACA, + 0x8DA, 0x4E2, 0xB0B, 0x713, 0x523, 0x12B, 0x284, 0x694, 0x89C, 0x0AC, + 0x205, 0xA0D, 0x81D, 0x425}, + {0x448, 0x050, 0xA60, 0x668, 0x281, 0x091, 0x899, 0x6A9, 0x202, 0x40A, + 0x81A, 0xA22, 0x50B, 0x113, 0xB23, 0x72B, 0x344, 0x154, 0x95C, 0x76C, + 0x2C5, 0x4CD, 0x8DD, 0xAE5}, + {0x048, 0xA50, 0x660, 0x468, 0x201, 0xA11, 0x819, 0x429, 0x342, 0x14A, + 0x95A, 0x762, 0x10B, 0xB13, 0x723, 0x52B, 0x2C4, 0xAD4, 0x8DC, 0x4EC, + 0x285, 0x08D, 0x89D, 0x6A5}, + {0x808, 0xA10, 0x220, 0x428, 0x101, 0xB11, 0x719, 0x529, 0x142, 0x94A, + 0x75A, 0x362, 0x8CB, 0xAD3, 0x2E3, 0x4EB, 0x044, 0xA54, 0x65C, 0x46C, + 0x085, 0x88D, 0x69D, 0x2A5}, + {0xA08, 0x210, 0x420, 0x828, 0x141, 0x351, 0x759, 0x969, 0x042, 0xA4A, + 0x65A, 0x462, 0xACB, 0x2D3, 0x4E3, 0x8EB, 0x084, 0x294, 0x69C, 0x8AC, + 0x105, 0xB0D, 0x71D, 0x525}, + {0x408, 0x810, 0xA20, 0x228, 0x081, 0x891, 0x699, 0x2A9, 0x102, 0x50A, + 0x71A, 0xB22, 0x4CB, 0x8D3, 0xAE3, 0x2EB, 0x144, 0x954, 0x75C, 0x36C, + 0x045, 0x44D, 0x65D, 0xA65}, ) _axis_convert_num = {'X': 0, 'Y': 1, 'Z': 2, '-X': 3, '-Y': 4, '-Z': 5} @@ -206,7 +270,8 @@ def axis_conversion_ensure(operator, forward_attr, up_attr): return False -# return a tuple (free, object list), free is True if memory should be freed later with free_derived_objects() +# return a tuple (free, object list), free is True if memory should be freed +# later with free_derived_objects() def create_derived_objects(scene, ob): if ob.parent and ob.parent.dupli_type in {'VERTS', 'FACES'}: return False, None @@ -254,31 +319,45 @@ path_reference_mode = EnumProperty( description="Method used to reference paths", items=(('AUTO', "Auto", "Use Relative paths with subdirectories only"), ('ABSOLUTE', "Absolute", "Always write absolute paths"), - ('RELATIVE', "Relative", "Always write relative patsh (where possible)"), - ('MATCH', "Match", "Match Absolute/Relative setting with input path"), + ('RELATIVE', "Relative", "Always write relative patsh " + "(where possible)"), + ('MATCH', "Match", "Match Absolute/Relative " + "setting with input path"), ('STRIP', "Strip Path", "Filename only"), - ('COPY', "Copy", "copy the file to the destination path (or subdirectory)"), + ('COPY', "Copy", "copy the file to the destination path " + "(or subdirectory)"), ), default='AUTO' ) -def path_reference(filepath, base_src, base_dst, mode='AUTO', copy_subdir="", copy_set=None): +def path_reference(filepath, + base_src, + base_dst, + mode='AUTO', + copy_subdir="", + copy_set=None, + ): """ Return a filepath relative to a destination directory, for use with exporters. - :arg filepath: the file path to return, supporting blenders relative '//' prefix. + :arg filepath: the file path to return, + supporting blenders relative '//' prefix. :type filepath: string - :arg base_src: the directory the *filepath* is relative too (normally the blend file). + :arg base_src: the directory the *filepath* is relative too + (normally the blend file). :type base_src: string - :arg base_dst: the directory the *filepath* will be referenced from (normally the export path). + :arg base_dst: the directory the *filepath* will be referenced from + (normally the export path). :type base_dst: string - :arg mode: the method used get the path in ['AUTO', 'ABSOLUTE', 'RELATIVE', 'MATCH', 'STRIP', 'COPY'] + :arg mode: the method used get the path in + ['AUTO', 'ABSOLUTE', 'RELATIVE', 'MATCH', 'STRIP', 'COPY'] :type mode: string :arg copy_subdir: the subdirectory of *base_dst* to use when mode='COPY'. :type copy_subdir: string - :arg copy_set: collect from/to pairs when mode='COPY', pass to *path_reference_copy* when exportign is done. + :arg copy_set: collect from/to pairs when mode='COPY', + pass to *path_reference_copy* when exportign is done. :type copy_set: set :return: the new filepath. :rtype: string @@ -292,7 +371,9 @@ def path_reference(filepath, base_src, base_dst, mode='AUTO', copy_subdir="", co elif mode == 'MATCH': mode = 'RELATIVE' if is_relative else 'ABSOLUTE' elif mode == 'AUTO': - mode = 'RELATIVE' if bpy.path.is_subdir(filepath, base_dst) else 'ABSOLUTE' + mode = ('RELATIVE' + if bpy.path.is_subdir(filepath, base_dst) + else 'ABSOLUTE') elif mode == 'COPY': if copy_subdir: subdir_abs = os.path.join(os.path.normpath(base_dst), copy_subdir) @@ -367,7 +448,8 @@ def unique_name(key, name, name_dict, name_max=-1, clean_func=None): if name_new is None: count = 1 name_dict_values = name_dict.values() - name_new = name_new_orig = name if clean_func is None else clean_func(name) + name_new = name_new_orig = (name if clean_func is None + else clean_func(name)) if name_max == -1: while name_new in name_dict_values: @@ -377,7 +459,10 @@ def unique_name(key, name, name_dict, name_max=-1, clean_func=None): name_new = name_new[:name_max] while name_new in name_dict_values: count_str = "%03d" % count - name_new = "%.*s.%s" % (name_max - (len(count_str) + 1), name_new_orig, count_str) + name_new = "%.*s.%s" % (name_max - (len(count_str) + 1), + name_new_orig, + count_str, + ) count += 1 name_dict[key] = name_new diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py index ecd620ff2c9..f9400674138 100644 --- a/release/scripts/modules/bpy_extras/mesh_utils.py +++ b/release/scripts/modules/bpy_extras/mesh_utils.py @@ -26,7 +26,7 @@ __all__ = ( "edge_loops_from_edges", "ngon_tesselate", "face_random_points", -) + ) def mesh_linked_faces(mesh): diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py index 51a8d4b5e23..ba2db0a4e55 100644 --- a/release/scripts/modules/bpy_extras/object_utils.py +++ b/release/scripts/modules/bpy_extras/object_utils.py @@ -16,12 +16,12 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# __all__ = ( "add_object_align_init", "object_data_add", -) + ) import bpy @@ -39,42 +39,49 @@ def add_object_align_init(context, operator): :return: the matrix from the context and settings. :rtype: :class:`Matrix` """ + + from mathutils import Matrix, Vector, Euler + properties = operator.properties + space_data = context.space_data if space_data.type != 'VIEW_3D': space_data = None # location - if operator and operator.properties.is_property_set("location"): - location = mathutils.Matrix.Translation(mathutils.Vector(operator.properties.location)) + if operator and properties.is_property_set("location"): + location = Matrix.Translation(Vector(properties.location)) else: if space_data: # local view cursor is detected below - location = mathutils.Matrix.Translation(space_data.cursor_location) + location = Matrix.Translation(space_data.cursor_location) else: - location = mathutils.Matrix.Translation(context.scene.cursor_location) + location = Matrix.Translation(context.scene.cursor_location) if operator: - operator.properties.location = location.to_translation() + properties.location = location.to_translation() # rotation view_align = (context.user_preferences.edit.object_align == 'VIEW') view_align_force = False if operator: - if operator.properties.is_property_set("view_align"): + if properties.is_property_set("view_align"): view_align = view_align_force = operator.view_align else: - operator.properties.view_align = view_align + properties.view_align = view_align - if operator and operator.properties.is_property_set("rotation") and not view_align_force: - rotation = mathutils.Euler(operator.properties.rotation).to_matrix().to_4x4() + if operator and (properties.is_property_set("rotation") and + not view_align_force): + + rotation = Euler(properties.rotation).to_matrix().to_4x4() else: if view_align and space_data: - rotation = space_data.region_3d.view_matrix.to_3x3().inverted().to_4x4() + rotation = space_data.region_3d.view_matrix.to_3x3().inverted() + rotation.resize_4x4() else: rotation = mathutils.Matrix() # set the operator properties if operator: - operator.properties.rotation = rotation.to_euler() + properties.rotation = rotation.to_euler() return location * rotation @@ -114,14 +121,18 @@ def object_data_add(context, obdata, operator=None): # XXX # caused because entering editmodedoes not add a empty undo slot! if context.user_preferences.edit.use_enter_edit_mode: - if not (obj_act and obj_act.mode == 'EDIT' and obj_act.type == obj_new.type): + if not (obj_act and + obj_act.mode == 'EDIT' and + obj_act.type == obj_new.type): + _obdata = bpy.data.meshes.new(obdata.name) obj_act = bpy.data.objects.new(_obdata.name, _obdata) obj_act.matrix_world = obj_new.matrix_world scene.objects.link(obj_act) scene.objects.active = obj_act bpy.ops.object.mode_set(mode='EDIT') - bpy.ops.ed.undo_push(message="Enter Editmode") # need empty undo step + # need empty undo step + bpy.ops.ed.undo_push(message="Enter Editmode") # XXX if obj_act and obj_act.mode == 'EDIT' and obj_act.type == obj_new.type: diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py index 5796abce72c..26325633a05 100644 --- a/release/scripts/modules/bpy_extras/view3d_utils.py +++ b/release/scripts/modules/bpy_extras/view3d_utils.py @@ -16,13 +16,13 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# __all__ = ( "region_2d_to_vector_3d", "region_2d_to_location_3d", "location_3d_to_region_2d", -) + ) def region_2d_to_vector_3d(region, rv3d, coord): @@ -90,15 +90,23 @@ def region_2d_to_location_3d(region, rv3d, coord, depth_location): origin_start = rv3d.view_matrix.inverted()[3].to_3d() origin_end = origin_start + coord_vec view_vec = rv3d.view_matrix.inverted()[2] - return intersect_line_plane(origin_start, origin_end, depth_location, view_vec, 1) + return intersect_line_plane(origin_start, + origin_end, + depth_location, + view_vec, 1, + ) else: dx = (2.0 * coord[0] / region.width) - 1.0 dy = (2.0 * coord[1] / region.height) - 1.0 persinv = persmat.inverted() viewinv = rv3d.view_matrix.inverted() - origin_start = (persinv[0].xyz * dx) + (persinv[1].xyz * dy) + viewinv[3].xyz + origin_start = ((persinv[0].xyz * dx) + + (persinv[1].xyz * dy) + viewinv[3].xyz) origin_end = origin_start + coord_vec - return intersect_point_line(depth_location, origin_start, origin_end)[0] + return intersect_point_line(depth_location, + origin_start, + origin_end, + )[0] def location_3d_to_region_2d(region, rv3d, coord): diff --git a/release/scripts/modules/keyingsets_utils.py b/release/scripts/modules/keyingsets_utils.py index dc61ce2a4af..03400edc904 100644 --- a/release/scripts/modules/keyingsets_utils.py +++ b/release/scripts/modules/keyingsets_utils.py @@ -16,14 +16,14 @@ # # ##### END GPL LICENSE BLOCK ##### -# +# # This file defines a set of methods that are useful for various # Relative Keying Set (RKS) related operations, such as: callbacks # for polling, iterator callbacks, and also generate callbacks. # All of these can be used in conjunction with the others. -__all__ = [ +__all__ = ( "path_add_property", "RKS_POLL_selected_objects", "RKS_POLL_selected_bones", @@ -33,7 +33,7 @@ __all__ = [ "RKS_GEN_location", "RKS_GEN_rotation", "RKS_GEN_scaling", -] + ) import bpy @@ -75,7 +75,8 @@ def RKS_POLL_selected_bones(ksi, context): # selected bones or objects def RKS_POLL_selected_items(ksi, context): - return RKS_POLL_selected_bones(ksi, context) or RKS_POLL_selected_objects(ksi, context) + return (RKS_POLL_selected_bones(ksi, context) or + RKS_POLL_selected_objects(ksi, context)) ########################### # Iterator Callbacks diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 2dcfe3731c7..502b25842de 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -6411,7 +6411,9 @@ PyDoc_STRVAR(pyrna_register_class_doc, " If the class has a *register* class method it will be called\n" " before registration.\n" "\n" -" .. note:: :exc:`ValueError` exception is raised if the class is not a\n" +" .. note::\n" +"\n" +" :exc:`ValueError` exception is raised if the class is not a\n" " subclass of a registerable blender class.\n" "\n" ); -- cgit v1.2.3 From e8c3c4097a146b059fa52893a2a1b6e89cdb3094 Mon Sep 17 00:00:00 2001 From: "Guillermo S. Romero" Date: Sun, 31 Jul 2011 06:03:14 +0000 Subject: SVN maintenance. --- source/blender/editors/interface/interface_anim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 03003173e20..d9691819b29 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -1,5 +1,5 @@ /* - * $Id: + * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * -- cgit v1.2.3 From 679b528177a29a1008efe26daeebef31d73978c1 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 31 Jul 2011 06:26:03 +0000 Subject: fix for immobile camera (NDOF_SHOULD_ROTATE etc.) -- should revisit later --- source/blender/editors/space_view3d/view3d_fly.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 34e355c977e..38d93ab59f3 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -29,7 +29,7 @@ /* defines VIEW3D_OT_fly modal operator */ -// #define NDOF_FLY_DEBUG +//#define NDOF_FLY_DEBUG #include "DNA_anim_types.h" #include "DNA_scene_types.h" @@ -145,7 +145,6 @@ void fly_modal_keymap(wmKeyConfig *keyconf) /* assign map to operators */ WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly"); - } typedef struct FlyInfo { @@ -670,7 +669,6 @@ static void move_camera(bContext* C, RegionView3D* rv3d, FlyInfo* fly, int orien static int flyApply(bContext *C, FlyInfo *fly) { - #define FLY_ROTATE_FAC 2.5f /* more is faster */ #define FLY_ZUP_CORRECT_FAC 0.1f /* amount to correct per step */ #define FLY_ZUP_CORRECT_ACCEL 0.05f /* increase upright momentum each step */ @@ -934,13 +932,16 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) RegionView3D* rv3d = fly->rv3d; const int flag = U.ndof_flag; - int shouldRotate = (flag & NDOF_SHOULD_ROTATE) && (fly->pan_view == FALSE), - shouldTranslate = (flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM)); +// int shouldRotate = (flag & NDOF_SHOULD_ROTATE) && (fly->pan_view == FALSE), +// shouldTranslate = (flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM)); + + int shouldRotate = (fly->pan_view == FALSE), + shouldTranslate = TRUE; float view_inv[4]; invert_qt_qt(view_inv, rv3d->viewquat); - rv3d->rot_angle = 0; // disable onscreen rotation doo-dad + rv3d->rot_angle = 0.f; // disable onscreen rotation doo-dad if (shouldTranslate) { @@ -974,9 +975,9 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) if (rv3d->persp==RV3D_CAMOB) { // respect camera position locks Object *lock_ob= fly->root_parent ? fly->root_parent : fly->v3d->camera; - if (lock_ob->protectflag & OB_LOCK_LOCX) trans[0] = 0.0; - if (lock_ob->protectflag & OB_LOCK_LOCY) trans[1] = 0.0; - if (lock_ob->protectflag & OB_LOCK_LOCZ) trans[2] = 0.0; + if (lock_ob->protectflag & OB_LOCK_LOCX) trans[0] = 0.f; + if (lock_ob->protectflag & OB_LOCK_LOCY) trans[1] = 0.f; + if (lock_ob->protectflag & OB_LOCK_LOCZ) trans[2] = 0.f; } if (trans[0] || trans[1] || trans[2]) @@ -1015,8 +1016,8 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) // force an upright viewpoint // TODO: make this less... sudden { - float view_horizon[3] = {1, 0, 0}; // view +x - float view_direction[3] = {0, 0, -1}; // view -z (into screen) + float view_horizon[3] = {1.f, 0.f, 0.f}; // view +x + float view_direction[3] = {0.f, 0.f, -1.f}; // view -z (into screen) // find new inverse since viewquat has changed invert_qt_qt(view_inv, rv3d->viewquat); @@ -1124,6 +1125,7 @@ static int fly_modal(bContext *C, wmOperator *op, wmEvent *event) WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, fly_object); } + // puts("redraw!"); // too frequent, fix tomorrow. ED_region_tag_redraw(CTX_wm_region(C)); } -- cgit v1.2.3 From c19e88ac26e266bd8ba7a6f15c45e3447ac5624c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 31 Jul 2011 07:45:54 +0000 Subject: fix for building without bullet --- source/gameengine/Ketsji/KX_PyConstraintBinding.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 843dbe21995..a7d213bff79 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -43,7 +43,9 @@ #include "PyObjectPlus.h" -#include "LinearMath/btIDebugDraw.h" +#ifdef USE_BULLET +# include "LinearMath/btIDebugDraw.h" +#endif #ifdef WITH_PYTHON @@ -690,6 +692,7 @@ PyObject* initPythonConstraintBinding() PyDict_SetItemString(d, "error", ErrorObject); Py_DECREF(ErrorObject); +#ifdef USE_BULLET //Debug Modes constants to be used with setDebugMode() python function KX_MACRO_addTypesToDict(d, DBG_NODEBUG, btIDebugDraw::DBG_NoDebug); KX_MACRO_addTypesToDict(d, DBG_DRAWWIREFRAME, btIDebugDraw::DBG_DrawWireframe); @@ -705,6 +708,7 @@ PyObject* initPythonConstraintBinding() KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTS, btIDebugDraw::DBG_DrawConstraints); KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTLIMITS, btIDebugDraw::DBG_DrawConstraintLimits); KX_MACRO_addTypesToDict(d, DBG_FASTWIREFRAME, btIDebugDraw::DBG_FastWireframe); +#endif // USE_BULLET //Constraint types to be used with createConstraint() python function KX_MACRO_addTypesToDict(d, POINTTOPOINT_CONSTRAINT, PHY_POINT2POINT_CONSTRAINT); -- cgit v1.2.3 From c7a1a191532721e3a88cb412537027fa4dfca641 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 31 Jul 2011 07:54:24 +0000 Subject: whitespace edits, had odd space/tab mix --- .../gameengine/Ketsji/KX_PyConstraintBinding.cpp | 325 ++++++++++----------- 1 file changed, 157 insertions(+), 168 deletions(-) diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index a7d213bff79..0600e59a1ec 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -92,8 +92,8 @@ static char gPyGetAppliedImpulse__doc__[] = "getAppliedImpulse(int constraintId) static PyObject* gPySetGravity(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { float x,y,z; if (PyArg_ParseTuple(args,"fff",&x,&y,&z)) @@ -109,8 +109,8 @@ static PyObject* gPySetGravity(PyObject* self, } static PyObject* gPySetDebugMode(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { int mode; if (PyArg_ParseTuple(args,"i",&mode)) @@ -132,8 +132,8 @@ static PyObject* gPySetDebugMode(PyObject* self, static PyObject* gPySetNumTimeSubSteps(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { int substep; if (PyArg_ParseTuple(args,"i",&substep)) @@ -151,8 +151,8 @@ static PyObject* gPySetNumTimeSubSteps(PyObject* self, static PyObject* gPySetNumIterations(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { int iter; if (PyArg_ParseTuple(args,"i",&iter)) @@ -169,10 +169,9 @@ static PyObject* gPySetNumIterations(PyObject* self, } - static PyObject* gPySetDeactivationTime(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { float deactive_time; if (PyArg_ParseTuple(args,"f",&deactive_time)) @@ -190,8 +189,8 @@ static PyObject* gPySetDeactivationTime(PyObject* self, static PyObject* gPySetDeactivationLinearTreshold(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { float linearDeactivationTreshold; if (PyArg_ParseTuple(args,"f",&linearDeactivationTreshold)) @@ -209,8 +208,8 @@ static PyObject* gPySetDeactivationLinearTreshold(PyObject* self, static PyObject* gPySetDeactivationAngularTreshold(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { float angularDeactivationTreshold; if (PyArg_ParseTuple(args,"f",&angularDeactivationTreshold)) @@ -227,8 +226,8 @@ static PyObject* gPySetDeactivationAngularTreshold(PyObject* self, } static PyObject* gPySetContactBreakingTreshold(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { float contactBreakingTreshold; if (PyArg_ParseTuple(args,"f",&contactBreakingTreshold)) @@ -246,8 +245,8 @@ static PyObject* gPySetContactBreakingTreshold(PyObject* self, static PyObject* gPySetCcdMode(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { float ccdMode; if (PyArg_ParseTuple(args,"f",&ccdMode)) @@ -264,8 +263,8 @@ static PyObject* gPySetCcdMode(PyObject* self, } static PyObject* gPySetSorConstant(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { float sor; if (PyArg_ParseTuple(args,"f",&sor)) @@ -282,8 +281,8 @@ static PyObject* gPySetSorConstant(PyObject* self, } static PyObject* gPySetSolverTau(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { float tau; if (PyArg_ParseTuple(args,"f",&tau)) @@ -301,8 +300,8 @@ static PyObject* gPySetSolverTau(PyObject* self, static PyObject* gPySetSolverDamping(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { float damping; if (PyArg_ParseTuple(args,"f",&damping)) @@ -319,8 +318,8 @@ static PyObject* gPySetSolverDamping(PyObject* self, } static PyObject* gPySetLinearAirDamping(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { float damping; if (PyArg_ParseTuple(args,"f",&damping)) @@ -338,8 +337,8 @@ static PyObject* gPySetLinearAirDamping(PyObject* self, static PyObject* gPySetUseEpa(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { int epa; if (PyArg_ParseTuple(args,"i",&epa)) @@ -355,8 +354,8 @@ static PyObject* gPySetUseEpa(PyObject* self, Py_RETURN_NONE; } static PyObject* gPySetSolverType(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { int solverType; if (PyArg_ParseTuple(args,"i",&solverType)) @@ -375,8 +374,8 @@ static PyObject* gPySetSolverType(PyObject* self, static PyObject* gPyGetVehicleConstraint(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { #if defined(_WIN64) __int64 constraintid; @@ -406,9 +405,6 @@ static PyObject* gPyGetVehicleConstraint(PyObject* self, } - - - static PyObject* gPyCreateConstraint(PyObject* self, PyObject* args, PyObject* kwds) @@ -433,48 +429,48 @@ static PyObject* gPyCreateConstraint(PyObject* self, success = PyArg_ParseTuple(args,"lli",&physicsid,&physicsid2,&constrainttype); #endif } - else - if (len ==6) - { + else { + if (len ==6) { #if defined(_WIN64) - success = PyArg_ParseTuple(args,"LLifff",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ); + success = PyArg_ParseTuple(args,"LLifff",&physicsid,&physicsid2,&constrainttype, + &pivotX,&pivotY,&pivotZ); #else - success = PyArg_ParseTuple(args,"llifff",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ); + success = PyArg_ParseTuple(args,"llifff",&physicsid,&physicsid2,&constrainttype, + &pivotX,&pivotY,&pivotZ); #endif - } - else if (len == 9) - { + } + else if (len == 9) + { #if defined(_WIN64) - success = PyArg_ParseTuple(args,"LLiffffff",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ); + success = PyArg_ParseTuple(args,"LLiffffff",&physicsid,&physicsid2,&constrainttype, + &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ); #else - success = PyArg_ParseTuple(args,"lliffffff",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ); + success = PyArg_ParseTuple(args,"lliffffff",&physicsid,&physicsid2,&constrainttype, + &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ); #endif - - } - else if (len == 10) - { + + } + else if (len == 10) + { #if defined(_WIN64) - success = PyArg_ParseTuple(args,"LLiffffffi",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag); + success = PyArg_ParseTuple(args,"LLiffffffi",&physicsid,&physicsid2,&constrainttype, + &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag); #else - success = PyArg_ParseTuple(args,"lliffffffi",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag); + success = PyArg_ParseTuple(args,"lliffffffi",&physicsid,&physicsid2,&constrainttype, + &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag); #endif - } - else if (len==4) - { + } + else if (len==4) + { #if defined(_WIN64) - success = PyArg_ParseTuple(args,"LLii",&physicsid,&physicsid2,&constrainttype,&extrainfo); + success = PyArg_ParseTuple(args,"LLii",&physicsid,&physicsid2,&constrainttype,&extrainfo); #else - success = PyArg_ParseTuple(args,"llii",&physicsid,&physicsid2,&constrainttype,&extrainfo); + success = PyArg_ParseTuple(args,"llii",&physicsid,&physicsid2,&constrainttype,&extrainfo); #endif - pivotX=extrainfo; + pivotX=extrainfo; + } } - + if (success) { if (PHY_GetActiveEnvironment()) @@ -498,20 +494,18 @@ static PyObject* gPyCreateConstraint(PyObject* self, MT_Vector3 axis0 = localCFrame.getColumn(0); MT_Vector3 axis1 = localCFrame.getColumn(1); MT_Vector3 axis2 = localCFrame.getColumn(2); - - constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype, - pivotX,pivotY,pivotZ, - (float)axis0.x(),(float)axis0.y(),(float)axis0.z(), - (float)axis1.x(),(float)axis1.y(),(float)axis1.z(), - (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),flag); - } else - { + constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype, + pivotX,pivotY,pivotZ, + (float)axis0.x(),(float)axis0.y(),(float)axis0.z(), + (float)axis1.x(),(float)axis1.y(),(float)axis1.z(), + (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),flag); + } + else { constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,pivotX,pivotY,pivotZ,axisX,axisY,axisZ,0); } KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment()); - return wrap->NewProxy(true); } @@ -530,8 +524,8 @@ static PyObject* gPyCreateConstraint(PyObject* self, static PyObject* gPyGetAppliedImpulse(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { float appliedImpulse = 0.f; @@ -557,8 +551,8 @@ static PyObject* gPyGetAppliedImpulse(PyObject* self, static PyObject* gPyRemoveConstraint(PyObject* self, - PyObject* args, - PyObject* kwds) + PyObject* args, + PyObject* kwds) { #if defined(_WIN64) __int64 constraintid; @@ -585,7 +579,7 @@ static PyObject* gPyExportBulletFile(PyObject*, PyObject* args) char* filename; if (!PyArg_ParseTuple(args,"s:exportBulletFile",&filename)) return NULL; - + if (PHY_GetActiveEnvironment()) { PHY_GetActiveEnvironment()->exportFile(filename); @@ -594,62 +588,61 @@ static PyObject* gPyExportBulletFile(PyObject*, PyObject* args) } static struct PyMethodDef physicsconstraints_methods[] = { - {"setGravity",(PyCFunction) gPySetGravity, - METH_VARARGS, (const char *)gPySetGravity__doc__}, - {"setDebugMode",(PyCFunction) gPySetDebugMode, - METH_VARARGS, (const char *)gPySetDebugMode__doc__}, - - /// settings that influence quality of the rigidbody dynamics - {"setNumIterations",(PyCFunction) gPySetNumIterations, - METH_VARARGS, (const char *)gPySetNumIterations__doc__}, - - {"setNumTimeSubSteps",(PyCFunction) gPySetNumTimeSubSteps, - METH_VARARGS, (const char *)gPySetNumTimeSubSteps__doc__}, - - {"setDeactivationTime",(PyCFunction) gPySetDeactivationTime, - METH_VARARGS, (const char *)gPySetDeactivationTime__doc__}, - - {"setDeactivationLinearTreshold",(PyCFunction) gPySetDeactivationLinearTreshold, - METH_VARARGS, (const char *)gPySetDeactivationLinearTreshold__doc__}, - {"setDeactivationAngularTreshold",(PyCFunction) gPySetDeactivationAngularTreshold, - METH_VARARGS, (const char *)gPySetDeactivationAngularTreshold__doc__}, - - {"setContactBreakingTreshold",(PyCFunction) gPySetContactBreakingTreshold, - METH_VARARGS, (const char *)gPySetContactBreakingTreshold__doc__}, - {"setCcdMode",(PyCFunction) gPySetCcdMode, - METH_VARARGS, (const char *)gPySetCcdMode__doc__}, - {"setSorConstant",(PyCFunction) gPySetSorConstant, - METH_VARARGS, (const char *)gPySetSorConstant__doc__}, - {"setSolverTau",(PyCFunction) gPySetSolverTau, - METH_VARARGS, (const char *)gPySetSolverTau__doc__}, - {"setSolverDamping",(PyCFunction) gPySetSolverDamping, - METH_VARARGS, (const char *)gPySetSolverDamping__doc__}, - - {"setLinearAirDamping",(PyCFunction) gPySetLinearAirDamping, - METH_VARARGS, (const char *)gPySetLinearAirDamping__doc__}, - - {"setUseEpa",(PyCFunction) gPySetUseEpa, - METH_VARARGS, (const char *)gPySetUseEpa__doc__}, + {"setGravity",(PyCFunction) gPySetGravity, + METH_VARARGS, (const char*)gPySetGravity__doc__}, + {"setDebugMode",(PyCFunction) gPySetDebugMode, + METH_VARARGS, (const char *)gPySetDebugMode__doc__}, + + /// settings that influence quality of the rigidbody dynamics + {"setNumIterations",(PyCFunction) gPySetNumIterations, + METH_VARARGS, (const char *)gPySetNumIterations__doc__}, + + {"setNumTimeSubSteps",(PyCFunction) gPySetNumTimeSubSteps, + METH_VARARGS, (const char *)gPySetNumTimeSubSteps__doc__}, + + {"setDeactivationTime",(PyCFunction) gPySetDeactivationTime, + METH_VARARGS, (const char *)gPySetDeactivationTime__doc__}, + + {"setDeactivationLinearTreshold",(PyCFunction) gPySetDeactivationLinearTreshold, + METH_VARARGS, (const char *)gPySetDeactivationLinearTreshold__doc__}, + {"setDeactivationAngularTreshold",(PyCFunction) gPySetDeactivationAngularTreshold, + METH_VARARGS, (const char *)gPySetDeactivationAngularTreshold__doc__}, + + {"setContactBreakingTreshold",(PyCFunction) gPySetContactBreakingTreshold, + METH_VARARGS, (const char *)gPySetContactBreakingTreshold__doc__}, + {"setCcdMode",(PyCFunction) gPySetCcdMode, + METH_VARARGS, (const char *)gPySetCcdMode__doc__}, + {"setSorConstant",(PyCFunction) gPySetSorConstant, + METH_VARARGS, (const char *)gPySetSorConstant__doc__}, + {"setSolverTau",(PyCFunction) gPySetSolverTau, + METH_VARARGS, (const char *)gPySetSolverTau__doc__}, + {"setSolverDamping",(PyCFunction) gPySetSolverDamping, + METH_VARARGS, (const char *)gPySetSolverDamping__doc__}, + + {"setLinearAirDamping",(PyCFunction) gPySetLinearAirDamping, + METH_VARARGS, (const char *)gPySetLinearAirDamping__doc__}, + + {"setUseEpa",(PyCFunction) gPySetUseEpa, + METH_VARARGS, (const char *)gPySetUseEpa__doc__}, {"setSolverType",(PyCFunction) gPySetSolverType, - METH_VARARGS, (const char *)gPySetSolverType__doc__}, + METH_VARARGS, (const char *)gPySetSolverType__doc__}, - {"createConstraint",(PyCFunction) gPyCreateConstraint, - METH_VARARGS, (const char *)gPyCreateConstraint__doc__}, - {"getVehicleConstraint",(PyCFunction) gPyGetVehicleConstraint, - METH_VARARGS, (const char *)gPyGetVehicleConstraint__doc__}, + {"createConstraint",(PyCFunction) gPyCreateConstraint, + METH_VARARGS, (const char *)gPyCreateConstraint__doc__}, + {"getVehicleConstraint",(PyCFunction) gPyGetVehicleConstraint, + METH_VARARGS, (const char *)gPyGetVehicleConstraint__doc__}, - {"removeConstraint",(PyCFunction) gPyRemoveConstraint, - METH_VARARGS, (const char *)gPyRemoveConstraint__doc__}, + {"removeConstraint",(PyCFunction) gPyRemoveConstraint, + METH_VARARGS, (const char *)gPyRemoveConstraint__doc__}, {"getAppliedImpulse",(PyCFunction) gPyGetAppliedImpulse, - METH_VARARGS, (const char *)gPyGetAppliedImpulse__doc__}, - - {"exportBulletFile",(PyCFunction)gPyExportBulletFile, - METH_VARARGS, "export a .bullet file"}, + METH_VARARGS, (const char *)gPyGetAppliedImpulse__doc__}, + {"exportBulletFile",(PyCFunction)gPyExportBulletFile, + METH_VARARGS, "export a .bullet file"}, - //sentinel - { NULL, (PyCFunction) NULL, 0, NULL } + //sentinel + { NULL, (PyCFunction) NULL, 0, NULL } }; static struct PyModuleDef PhysicsConstraints_module_def = { @@ -664,13 +657,13 @@ static struct PyModuleDef PhysicsConstraints_module_def = { 0, /* m_free */ }; -PyObject* initPythonConstraintBinding() +PyObject* initPythonConstraintBinding() { - PyObject* ErrorObject; - PyObject* m; - PyObject* d; - PyObject* item; + PyObject* ErrorObject; + PyObject* m; + PyObject* d; + PyObject* item; /* Use existing module where possible * be careful not to init any runtime vars after this */ @@ -686,44 +679,43 @@ PyObject* initPythonConstraintBinding() PyDict_SetItemString(PySys_GetObject("modules"), PhysicsConstraints_module_def.m_name, m); } - // Add some symbolic constants to the module - d = PyModule_GetDict(m); - ErrorObject = PyUnicode_FromString("PhysicsConstraints.error"); - PyDict_SetItemString(d, "error", ErrorObject); - Py_DECREF(ErrorObject); + // Add some symbolic constants to the module + d = PyModule_GetDict(m); + ErrorObject = PyUnicode_FromString("PhysicsConstraints.error"); + PyDict_SetItemString(d, "error", ErrorObject); + Py_DECREF(ErrorObject); #ifdef USE_BULLET - //Debug Modes constants to be used with setDebugMode() python function - KX_MACRO_addTypesToDict(d, DBG_NODEBUG, btIDebugDraw::DBG_NoDebug); - KX_MACRO_addTypesToDict(d, DBG_DRAWWIREFRAME, btIDebugDraw::DBG_DrawWireframe); - KX_MACRO_addTypesToDict(d, DBG_DRAWAABB, btIDebugDraw::DBG_DrawAabb); - KX_MACRO_addTypesToDict(d, DBG_DRAWFREATURESTEXT, btIDebugDraw::DBG_DrawFeaturesText); - KX_MACRO_addTypesToDict(d, DBG_DRAWCONTACTPOINTS, btIDebugDraw::DBG_DrawContactPoints); - KX_MACRO_addTypesToDict(d, DBG_NOHELPTEXT, btIDebugDraw::DBG_NoHelpText); - KX_MACRO_addTypesToDict(d, DBG_DRAWTEXT, btIDebugDraw::DBG_DrawText); - KX_MACRO_addTypesToDict(d, DBG_PROFILETIMINGS, btIDebugDraw::DBG_ProfileTimings); - KX_MACRO_addTypesToDict(d, DBG_ENABLESATCOMPARISION, btIDebugDraw::DBG_EnableSatComparison); - KX_MACRO_addTypesToDict(d, DBG_DISABLEBULLETLCP, btIDebugDraw::DBG_DisableBulletLCP); - KX_MACRO_addTypesToDict(d, DBG_ENABLECDD, btIDebugDraw::DBG_EnableCCD); - KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTS, btIDebugDraw::DBG_DrawConstraints); - KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTLIMITS, btIDebugDraw::DBG_DrawConstraintLimits); - KX_MACRO_addTypesToDict(d, DBG_FASTWIREFRAME, btIDebugDraw::DBG_FastWireframe); + //Debug Modes constants to be used with setDebugMode() python function + KX_MACRO_addTypesToDict(d, DBG_NODEBUG, btIDebugDraw::DBG_NoDebug); + KX_MACRO_addTypesToDict(d, DBG_DRAWWIREFRAME, btIDebugDraw::DBG_DrawWireframe); + KX_MACRO_addTypesToDict(d, DBG_DRAWAABB, btIDebugDraw::DBG_DrawAabb); + KX_MACRO_addTypesToDict(d, DBG_DRAWFREATURESTEXT, btIDebugDraw::DBG_DrawFeaturesText); + KX_MACRO_addTypesToDict(d, DBG_DRAWCONTACTPOINTS, btIDebugDraw::DBG_DrawContactPoints); + KX_MACRO_addTypesToDict(d, DBG_NOHELPTEXT, btIDebugDraw::DBG_NoHelpText); + KX_MACRO_addTypesToDict(d, DBG_DRAWTEXT, btIDebugDraw::DBG_DrawText); + KX_MACRO_addTypesToDict(d, DBG_PROFILETIMINGS, btIDebugDraw::DBG_ProfileTimings); + KX_MACRO_addTypesToDict(d, DBG_ENABLESATCOMPARISION, btIDebugDraw::DBG_EnableSatComparison); + KX_MACRO_addTypesToDict(d, DBG_DISABLEBULLETLCP, btIDebugDraw::DBG_DisableBulletLCP); + KX_MACRO_addTypesToDict(d, DBG_ENABLECDD, btIDebugDraw::DBG_EnableCCD); + KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTS, btIDebugDraw::DBG_DrawConstraints); + KX_MACRO_addTypesToDict(d, DBG_DRAWCONSTRAINTLIMITS, btIDebugDraw::DBG_DrawConstraintLimits); + KX_MACRO_addTypesToDict(d, DBG_FASTWIREFRAME, btIDebugDraw::DBG_FastWireframe); #endif // USE_BULLET - //Constraint types to be used with createConstraint() python function - KX_MACRO_addTypesToDict(d, POINTTOPOINT_CONSTRAINT, PHY_POINT2POINT_CONSTRAINT); - KX_MACRO_addTypesToDict(d, LINEHINGE_CONSTRAINT, PHY_LINEHINGE_CONSTRAINT); - KX_MACRO_addTypesToDict(d, ANGULAR_CONSTRAINT, PHY_ANGULAR_CONSTRAINT); - KX_MACRO_addTypesToDict(d, CONETWIST_CONSTRAINT, PHY_CONE_TWIST_CONSTRAINT); - KX_MACRO_addTypesToDict(d, VEHICLE_CONSTRAINT, PHY_VEHICLE_CONSTRAINT); + //Constraint types to be used with createConstraint() python function + KX_MACRO_addTypesToDict(d, POINTTOPOINT_CONSTRAINT, PHY_POINT2POINT_CONSTRAINT); + KX_MACRO_addTypesToDict(d, LINEHINGE_CONSTRAINT, PHY_LINEHINGE_CONSTRAINT); + KX_MACRO_addTypesToDict(d, ANGULAR_CONSTRAINT, PHY_ANGULAR_CONSTRAINT); + KX_MACRO_addTypesToDict(d, CONETWIST_CONSTRAINT, PHY_CONE_TWIST_CONSTRAINT); + KX_MACRO_addTypesToDict(d, VEHICLE_CONSTRAINT, PHY_VEHICLE_CONSTRAINT); - // Check for errors - if (PyErr_Occurred()) - { - Py_FatalError("can't initialize module PhysicsConstraints"); - } + // Check for errors + if (PyErr_Occurred()) { + Py_FatalError("can't initialize module PhysicsConstraints"); + } - return d; + return d; } @@ -741,7 +733,4 @@ PHY_IPhysicsEnvironment* PHY_GetActiveEnvironment() return g_CurrentActivePhysicsEnvironment; } - - #endif // WITH_PYTHON - -- cgit v1.2.3 From f4a1dc4c8dd353aa614bc7c00846e5076ddc2dc2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 31 Jul 2011 07:58:50 +0000 Subject: when converting curves from poly -> nurbs, dont enable Bezier-U flag. Not sure why this was enabled, possibly from copy/paste with bezier->nurbs code? If you have meny poly lines there was no nice way to convert these into a smoothed nurbs curve. Ran into this when trying to convert generated ivy into smooth nurbs. --- source/blender/editors/curve/editcurve.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 8b9477adf92..210f36ca074 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -3432,7 +3432,6 @@ static int convertspline(short type, Nurb *nu) nu->type = CU_NURBS; nu->orderu= 4; nu->flagu &= CU_NURB_CYCLIC; /* disable all flags except for cyclic */ - nu->flagu |= CU_NURB_BEZIER; nurbs_knot_calc_u(nu); a= nu->pntsu*nu->pntsv; bp= nu->bp; -- cgit v1.2.3 From 432bd158fbdb9d56f9499dcc0e465f4e148abbf3 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Sun, 31 Jul 2011 11:12:38 +0000 Subject: bugfix [#28111] material.pop breaks mt->mat_nr create a new parameter for materials.pop() to not remove material slot. this way the mat_nr is still the old one. for the default behaviour we now have material remapping (i.e. data_delete_material_index_id(id, index)). This new function is brought from the material_slot remove function. --- source/blender/blenkernel/BKE_material.h | 2 +- source/blender/blenkernel/intern/material.c | 101 +++++++++++++++++----------- source/blender/blenkernel/intern/mesh.c | 4 +- source/blender/makesrna/intern/rna_ID.c | 1 + 4 files changed, 66 insertions(+), 42 deletions(-) diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index c445408609c..88965d12e4a 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -78,7 +78,7 @@ int object_remove_material_slot(struct Object *ob); /* rna api */ void material_append_id(struct ID *id, struct Material *ma); -struct Material *material_pop_id(struct ID *id, int index); +struct Material *material_pop_id(struct ID *id, int index, int remove_material_slot); /* rendering */ diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 3f01c55e935..1f2544c9706 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -61,7 +61,7 @@ #include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_node.h" - +#include "BKE_curve.h" #include "GPU_material.h" @@ -515,6 +515,37 @@ short *give_totcolp_id(ID *id) return NULL; } +void data_delete_material_index_id(ID *id, int index) +{ + Mesh *me; + Curve *cu; + Nurb *nu; + int curvetype; + + switch(GS(id->name)) { + case ID_ME: + me=(Mesh *)id; + mesh_delete_material_index(me, index); + break; + case ID_CU: + cu= (Curve *)id; + nu= cu->nurb.first; + + curvetype=curve_type(cu); + if (!ELEM(curvetype, OB_CURVE, OB_SURF)) + return; + + while (nu) { + if(nu->mat_nr && nu->mat_nr>=index) { + nu->mat_nr--; + if (curvetype == OB_CURVE) nu->charidx--; + } + nu= nu->next; + } + break; + } +} + void material_append_id(ID *id, Material *ma) { Material ***matar; @@ -532,7 +563,7 @@ void material_append_id(ID *id, Material *ma) } } -Material *material_pop_id(ID *id, int index) +Material *material_pop_id(ID *id, int index, int remove_material_slot) { Material *ret= NULL; Material ***matar; @@ -540,27 +571,36 @@ Material *material_pop_id(ID *id, int index) short *totcol= give_totcolp_id(id); if(index >= 0 && index < (*totcol)) { ret= (*matar)[index]; - id_us_min((ID *)ret); - if(*totcol <= 1) { - *totcol= 0; - MEM_freeN(*matar); - *matar= NULL; - } - else { - Material **mat; - - if(index + 1 != (*totcol)) - memmove((*matar)+index, (*matar)+(index+1), sizeof(void *) * ((*totcol) - (index + 1))); + id_us_min((ID *)ret); - (*totcol)--; - - mat= MEM_callocN(sizeof(void *) * (*totcol), "newmatar"); - memcpy(mat, *matar, sizeof(void *) * (*totcol)); - MEM_freeN(*matar); + if (remove_material_slot) { + if(*totcol <= 1) { + *totcol= 0; + MEM_freeN(*matar); + *matar= NULL; + } + else { + Material **mat; + if(index + 1 != (*totcol)) + memmove((*matar)+index, (*matar)+(index+1), sizeof(void *) * ((*totcol) - (index + 1))); + + (*totcol)--; + + mat= MEM_callocN(sizeof(void *) * (*totcol), "newmatar"); + memcpy(mat, *matar, sizeof(void *) * (*totcol)); + MEM_freeN(*matar); + + *matar= mat; + test_object_materials(id); + } - *matar= mat; - test_object_materials(id); + /* decrease mat_nr index */ + data_delete_material_index_id(id, index); } + + /* don't remove material slot, only clear it*/ + else + (*matar)[index]= NULL; } } @@ -1025,8 +1065,6 @@ int object_remove_material_slot(Object *ob) { Material *mao, ***matarar; Object *obt; - Curve *cu; - Nurb *nu; short *totcolp; int a, actcol; @@ -1086,23 +1124,8 @@ int object_remove_material_slot(Object *ob) } /* check indices from mesh */ - - if(ob->type==OB_MESH) { - Mesh *me= get_mesh(ob); - mesh_delete_material_index(me, actcol-1); - freedisplist(&ob->disp); - } - else if ELEM(ob->type, OB_CURVE, OB_SURF) { - cu= ob->data; - nu= cu->nurb.first; - - while(nu) { - if(nu->mat_nr && nu->mat_nr>=actcol-1) { - nu->mat_nr--; - if (ob->type == OB_CURVE) nu->charidx--; - } - nu= nu->next; - } + if (ELEM3(ob->type, OB_MESH, OB_CURVE, OB_SURF)) { + data_delete_material_index_id(&ob->id, actcol-1); freedisplist(&ob->disp); } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 45a60b842a7..32819226361 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1254,10 +1254,10 @@ void mesh_to_curve(Scene *scene, Object *ob) void mesh_delete_material_index(Mesh *me, int index) { + MFace *mf; int i; - for (i=0; itotface; i++) { - MFace *mf = &((MFace*) me->mface)[i]; + for (i=0, mf=me->mface; itotface; i++, mf++) { if (mf->mat_nr && mf->mat_nr>=index) mf->mat_nr--; } diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 3ce84e3a19f..6d7fc0ee57b 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -418,6 +418,7 @@ static void rna_def_ID_materials(BlenderRNA *brna) RNA_def_function_ui_description(func, "Remove a material from the data block."); parm= RNA_def_int(func, "index", 0, 0, INT_MAX, "", "Index of material to remove.", 0, INT_MAX); RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_boolean(func, "remove_material_slot", 1, "", "Remove the material slot and assign 1st material to old faces."); parm= RNA_def_pointer(func, "material", "Material", "", "Material to remove."); RNA_def_function_return(func, parm); } -- cgit v1.2.3 From 5b3bb373432d5b0b9c4ab1135a6f344831cb83a9 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Sun, 31 Jul 2011 11:21:48 +0000 Subject: reverting part of #38876 (whitespace edits) the new if/else nesting introduced in the previous commit makes no sense. (since I was here I add a comment for extrainfo and did some small cleanup) --- .../gameengine/Ketsji/KX_PyConstraintBinding.cpp | 56 +++++++++++----------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 0600e59a1ec..fde127b7ef5 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -429,46 +429,46 @@ static PyObject* gPyCreateConstraint(PyObject* self, success = PyArg_ParseTuple(args,"lli",&physicsid,&physicsid2,&constrainttype); #endif } - else { - if (len ==6) { + else if (len == 6) + { #if defined(_WIN64) - success = PyArg_ParseTuple(args,"LLifff",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ); + success = PyArg_ParseTuple(args,"LLifff",&physicsid,&physicsid2,&constrainttype, + &pivotX,&pivotY,&pivotZ); #else - success = PyArg_ParseTuple(args,"llifff",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ); + success = PyArg_ParseTuple(args,"llifff",&physicsid,&physicsid2,&constrainttype, + &pivotX,&pivotY,&pivotZ); #endif - } - else if (len == 9) - { + } + else if (len == 9) + { #if defined(_WIN64) - success = PyArg_ParseTuple(args,"LLiffffff",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ); + success = PyArg_ParseTuple(args,"LLiffffff",&physicsid,&physicsid2,&constrainttype, + &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ); #else - success = PyArg_ParseTuple(args,"lliffffff",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ); + success = PyArg_ParseTuple(args,"lliffffff",&physicsid,&physicsid2,&constrainttype, + &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ); #endif - - } - else if (len == 10) - { + } + else if (len == 10) + { #if defined(_WIN64) - success = PyArg_ParseTuple(args,"LLiffffffi",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag); + success = PyArg_ParseTuple(args,"LLiffffffi",&physicsid,&physicsid2,&constrainttype, + &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag); #else - success = PyArg_ParseTuple(args,"lliffffffi",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag); + success = PyArg_ParseTuple(args,"lliffffffi",&physicsid,&physicsid2,&constrainttype, + &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag); #endif - } - else if (len==4) - { + } + + /* XXX extrainfo seems to be nothing implemented. right now it works as a pivot with [X,0,0] */ + else if (len == 4) + { #if defined(_WIN64) - success = PyArg_ParseTuple(args,"LLii",&physicsid,&physicsid2,&constrainttype,&extrainfo); + success = PyArg_ParseTuple(args,"LLii",&physicsid,&physicsid2,&constrainttype,&extrainfo); #else - success = PyArg_ParseTuple(args,"llii",&physicsid,&physicsid2,&constrainttype,&extrainfo); + success = PyArg_ParseTuple(args,"llii",&physicsid,&physicsid2,&constrainttype,&extrainfo); #endif - pivotX=extrainfo; - } + pivotX=extrainfo; } if (success) -- cgit v1.2.3 From c74bb09584371520b9b557cbaa8ae13356bf5e1a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 31 Jul 2011 12:43:41 +0000 Subject: fix for material slot removal (r38879) - The object ID was being passed to the data_delete_material_index_id() from object_remove_material_slot(), rather then the object data. (so the material slot fix wouldnt run in that case). - add support for fixing text object materials too. --- source/blender/blenkernel/BKE_curve.h | 1 + source/blender/blenkernel/intern/curve.c | 25 ++++++++++++++++++++++++ source/blender/blenkernel/intern/material.c | 30 +++++++---------------------- source/blender/makesrna/intern/rna_ID.c | 5 +++-- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 0491116d199..557ce417b14 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -115,5 +115,6 @@ int minmax_curve(struct Curve *cu, float min[3], float max[3]); int curve_center_median(struct Curve *cu, float cent[3]); int curve_center_bounds(struct Curve *cu, float cent[3]); void curve_translate(struct Curve *cu, float offset[3], int do_keys); +void curve_delete_material_index(struct Curve *cu, int index); #endif diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 202a3f28d9a..66ab11938f3 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -3259,3 +3259,28 @@ void curve_translate(Curve *cu, float offset[3], int do_keys) } } } + +void curve_delete_material_index(Curve *cu, int index) +{ + const int curvetype= curve_type(cu); + + if(curvetype == OB_FONT) { + struct CharInfo *info= cu->strinfo; + int i; + for(i= cu->len-1; i >= 0; i--, info++) { + if (info->mat_nr && info->mat_nr>=index) { + info->mat_nr--; + } + } + } + else { + Nurb *nu; + + for (nu= cu->nurb.first; nu; nu= nu->next) { + if(nu->mat_nr && nu->mat_nr>=index) { + nu->mat_nr--; + if (curvetype == OB_CURVE) nu->charidx--; + } + } + } +} diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 1f2544c9706..9c455e84109 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -517,31 +517,15 @@ short *give_totcolp_id(ID *id) void data_delete_material_index_id(ID *id, int index) { - Mesh *me; - Curve *cu; - Nurb *nu; - int curvetype; - switch(GS(id->name)) { case ID_ME: - me=(Mesh *)id; - mesh_delete_material_index(me, index); + mesh_delete_material_index((Mesh *)id, index); break; case ID_CU: - cu= (Curve *)id; - nu= cu->nurb.first; - - curvetype=curve_type(cu); - if (!ELEM(curvetype, OB_CURVE, OB_SURF)) - return; - - while (nu) { - if(nu->mat_nr && nu->mat_nr>=index) { - nu->mat_nr--; - if (curvetype == OB_CURVE) nu->charidx--; - } - nu= nu->next; - } + curve_delete_material_index((Curve *)id, index); + break; + case ID_MB: + /* meta-elems dont have materials atm */ break; } } @@ -1124,8 +1108,8 @@ int object_remove_material_slot(Object *ob) } /* check indices from mesh */ - if (ELEM3(ob->type, OB_MESH, OB_CURVE, OB_SURF)) { - data_delete_material_index_id(&ob->id, actcol-1); + if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + data_delete_material_index_id((ID *)ob->data, actcol-1); freedisplist(&ob->disp); } diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 6d7fc0ee57b..8d57403ec35 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -35,6 +35,7 @@ #include "DNA_ID.h" #include "DNA_vfont_types.h" +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "WM_types.h" @@ -416,9 +417,9 @@ static void rna_def_ID_materials(BlenderRNA *brna) func= RNA_def_function(srna, "pop", "material_pop_id"); RNA_def_function_ui_description(func, "Remove a material from the data block."); - parm= RNA_def_int(func, "index", 0, 0, INT_MAX, "", "Index of material to remove.", 0, INT_MAX); + parm= RNA_def_int(func, "index", 0, 0, MAXMAT, "", "Index of material to remove.", 0, MAXMAT); RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_boolean(func, "remove_material_slot", 1, "", "Remove the material slot and assign 1st material to old faces."); + RNA_def_boolean(func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned."); parm= RNA_def_pointer(func, "material", "Material", "", "Material to remove."); RNA_def_function_return(func, parm); } -- cgit v1.2.3 From 2620bd0ade3451ee3dc3df7da6166335d46393d2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 31 Jul 2011 12:46:34 +0000 Subject: fix for error in recent commit. --- release/scripts/modules/bpy_extras/object_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/scripts/modules/bpy_extras/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py index ba2db0a4e55..790f5ba48cb 100644 --- a/release/scripts/modules/bpy_extras/object_utils.py +++ b/release/scripts/modules/bpy_extras/object_utils.py @@ -41,7 +41,7 @@ def add_object_align_init(context, operator): """ from mathutils import Matrix, Vector, Euler - properties = operator.properties + properties = operator.properties if operator is not None else None space_data = context.space_data if space_data.type != 'VIEW_3D': -- cgit v1.2.3 From 5c8344bcc9f8f2c319346420766d9e4110beb607 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sun, 31 Jul 2011 16:26:02 +0000 Subject: Bug fix: loading a file that had particles using a dupligroup from a liblinked file without the library file being present crashed --- source/blender/blenloader/intern/readfile.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 4ad99c02b2d..0633794c6ed 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3162,7 +3162,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main) if(part->effector_weights) part->effector_weights->group = newlibadr(fd, part->id.lib, part->effector_weights->group); - if(part->dupliweights.first) { + if(part->dupliweights.first && part->dup_group) { int index_ok = 0; /* check for old files without indices (all indexes 0) */ dw = part->dupliweights.first; @@ -3193,6 +3193,9 @@ static void lib_link_particlesettings(FileData *fd, Main *main) dw->ob = newlibadr(fd, part->id.lib, dw->ob); } } + else { + part->dupliweights.first = part->dupliweights.last = NULL; + } if(part->boids) { BoidState *state = part->boids->states.first; -- cgit v1.2.3 From 19b38034f989089e359b9a4ea1e65fcbe8ffa18c Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 31 Jul 2011 22:59:36 +0000 Subject: support for older SpacePilot (sans Pro), minor tidying --- intern/ghost/intern/GHOST_NDOFManager.cpp | 59 ++++++++++++++++++++++++++----- intern/ghost/intern/GHOST_NDOFManager.h | 11 ++++-- 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 69100fefd31..bda30ce8d83 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -139,6 +139,33 @@ static const NDOF_ButtonT SpacePilotPro_HID_map[] = NDOF_BUTTON_MINUS }; +static const NDOF_ButtonT SpacePilot_HID_map[] = +// this is the older SpacePilot (sans Pro) +// thanks to polosson for the info in this table + { + NDOF_BUTTON_1, + NDOF_BUTTON_2, + NDOF_BUTTON_3, + NDOF_BUTTON_4, + NDOF_BUTTON_5, + NDOF_BUTTON_6, + NDOF_BUTTON_TOP, + NDOF_BUTTON_LEFT, + NDOF_BUTTON_RIGHT, + NDOF_BUTTON_FRONT, + NDOF_BUTTON_NONE, // esc key + NDOF_BUTTON_NONE, // alt key + NDOF_BUTTON_NONE, // shift key + NDOF_BUTTON_NONE, // ctrl key + NDOF_BUTTON_FIT, + NDOF_BUTTON_MENU, + NDOF_BUTTON_PLUS, + NDOF_BUTTON_MINUS, + NDOF_BUTTON_DOMINANT, + NDOF_BUTTON_ROTATE, + NDOF_BUTTON_NONE // the CONFIG button -- what does it do? + }; + GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) : m_system(sys) , m_deviceType(NDOF_UnknownDevice) // each platform has its own device detection code @@ -159,6 +186,9 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short product_id) { + // default to NDOF_UnknownDevice so rogue button events will get discarded + // "mystery device" owners can help build a HID_map for their hardware + switch (vendor_id) { case 0x046D: // Logitech (3Dconnexion) @@ -187,16 +217,16 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ break; // -- older devices -- - // keep unknown device type so rogue button events will get discarded - // "mystery device" owners can help build another HID_map for their hardware + case 0xC625: + puts("ndof: using SpacePilot"); + m_deviceType = NDOF_SpacePilot; + m_buttonCount = 21; + break; + case 0xC623: puts("ndof: SpaceTraveler not supported, please file a bug report"); m_buttonCount = 8; break; - case 0xC625: - puts("ndof: SpacePilot not supported, please file a bug report"); - m_buttonCount = 21; - break; default: printf("ndof: unknown Logitech product %04hx\n", product_id); @@ -295,6 +325,17 @@ void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 default: sendButtonEvent(SpacePilotPro_HID_map[button_number], press, time, window); } break; + case NDOF_SpacePilot: + switch (button_number) + { + case 10: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; + case 11: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; + case 12: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; + case 13: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; + case 20: puts("ndof: ignoring CONFIG button"); break; + default: sendButtonEvent(SpacePilot_HID_map[button_number], press, time, window); + } + break; case NDOF_UnknownDevice: printf("ndof: button %d on unknown device (ignoring)\n", button_number); } @@ -369,10 +410,10 @@ bool GHOST_NDOFManager::sendMotionEvent() GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, window); GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData(); - const float scale = 1.f / 350.f; // 3Dconnexion devices send +/- 350 usually + // scale axis values here to normalize them to around +/- 1 + // they are scaled again for overall sensitivity in the WM based on user prefs - // probable future enhancement - // scale *= U.ndof_sensitivity; + const float scale = 1.f / 350.f; // 3Dconnexion devices send +/- 350 usually data->tx = scale * m_translation[0]; data->ty = scale * m_translation[1]; diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index d259967daa9..ce0c3e96171 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -32,9 +32,15 @@ typedef enum { NDOF_UnknownDevice, // <-- motion will work fine, buttons are ignored + + // current devices NDOF_SpaceNavigator, NDOF_SpaceExplorer, - NDOF_SpacePilotPro + NDOF_SpacePilotPro, + + // older devices + NDOF_SpacePilot + } NDOF_DeviceT; // NDOF device button event types @@ -69,7 +75,7 @@ typedef enum { NDOF_BUTTON_PLUS, NDOF_BUTTON_MINUS, // general-purpose buttons - // TODO: expose these to keymap editor so users can assign functions + // users can assign functions via keymap editor NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_3, @@ -80,6 +86,7 @@ typedef enum { NDOF_BUTTON_8, NDOF_BUTTON_9, NDOF_BUTTON_10, + } NDOF_ButtonT; class GHOST_NDOFManager -- cgit v1.2.3 From f48b9062619ecc685e81dca12d588f5524efe41d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 1 Aug 2011 02:52:08 +0000 Subject: fix for failure to create curve knots when both endpoint and bezier U were enabled. use default when invalid settings given. removed odd/annoying bit shifting of the flagu/v for such basic function made code hard to understand and would fail if new flags were added. --- source/blender/blenkernel/intern/curve.c | 35 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 66ab11938f3..07e450479e4 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -580,29 +580,24 @@ void addNurbPointsBezier(Nurb *nu, int number) /* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline calculations ~~~~~~~~~~~ */ -static void calcknots(float *knots, short aantal, short order, short type) -/* knots: number of pnts NOT corrected for cyclic */ -/* type; 0: uniform, 1: endpoints, 2: bezier */ +static void calcknots(float *knots, const short aantal, const short order, const short flag) { + /* knots: number of pnts NOT corrected for cyclic */ + const int t= aantal + order; float k; - int a, t; - - t = aantal+order; - if(type==0) { + int a; - for(a=0;a=order && a<=aantal) k+= 1.0f; } - } - else if(type==2) { - /* Warning, the order MUST be 2 or 4, if this is not enforced, the displist will be corrupt */ + break; + case CU_NURB_BEZIER: + /* Warning, the order MUST be 2 or 4, + * if this is not enforced, the displist will be corrupt */ if(order==4) { k= 0.34; for(a=0;aknotsu, nu->pntsu, nu->orderu, 0); /* cyclic should be uniform */ makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu); } else { - calcknots(nu->knotsu, nu->pntsu, nu->orderu, nu->flagu>>1); + calcknots(nu->knotsu, nu->pntsu, nu->orderu, nu->flagu); } } else nu->knotsu= NULL; @@ -675,7 +676,7 @@ static void makeknots(Nurb *nu, short uv) calcknots(nu->knotsv, nu->pntsv, nu->orderv, 0); /* cyclic should be uniform */ makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv); } else { - calcknots(nu->knotsv, nu->pntsv, nu->orderv, nu->flagv>>1); + calcknots(nu->knotsv, nu->pntsv, nu->orderv, nu->flagv); } } else nu->knotsv= NULL; -- cgit v1.2.3 From 9da712a581f59fc7794151fe5f07a4fb396881f2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 1 Aug 2011 02:58:44 +0000 Subject: replace dutch variable name 'aantal' with 'tot' --- source/blender/blenkernel/intern/curve.c | 16 ++++++++-------- source/blender/blenkernel/intern/key.c | 8 ++++---- source/blender/editors/space_view3d/view3d_select.c | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 07e450479e4..7aa28c3f681 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -580,19 +580,19 @@ void addNurbPointsBezier(Nurb *nu, int number) /* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline calculations ~~~~~~~~~~~ */ -static void calcknots(float *knots, const short aantal, const short order, const short flag) +static void calcknots(float *knots, const short tot, const short order, const short flag) { /* knots: number of pnts NOT corrected for cyclic */ - const int t= aantal + order; + const int tot_order= tot + order; float k; int a; switch(flag & (CU_NURB_ENDPOINT|CU_NURB_BEZIER)) { case CU_NURB_ENDPOINT: k= 0.0; - for(a=1;a<=t;a++) { + for(a=1; a <= tot_order; a++) { knots[a-1]= k; - if(a>=order && a<=aantal) k+= 1.0f; + if(a >= order && a <= tot) k+= 1.0f; } break; case CU_NURB_BEZIER: @@ -600,15 +600,15 @@ static void calcknots(float *knots, const short aantal, const short order, const * if this is not enforced, the displist will be corrupt */ if(order==4) { k= 0.34; - for(a=0;a=order && a<=aantal) k+= 0.5f; + for(a=0; a < tot_order; a++) { + if(a >= order && a <= tot) k+= 0.5f; knots[a]= floorf(k); } } @@ -617,7 +617,7 @@ static void calcknots(float *knots, const short aantal, const short order, const } break; default: - for(a=0;aselcol; - aantal= (size-1)/2; + len= (size-1)/2; rc= 0; dirvec[0][0]= 1; @@ -910,7 +910,7 @@ static unsigned int samplerect(unsigned int *buf, int size, unsigned int dontdo) bufmin= buf; bufmax= buf+ size*size; - buf+= aantal*size+ aantal; + buf+= len*size+ len; for(tel=1;tel<=size;tel++) { -- cgit v1.2.3 From af39f2636019e387dc9f572249c09ad9cf9631bc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 1 Aug 2011 05:25:30 +0000 Subject: fix, uvproject modifier wasn't copying the uv layer name, also edit var names from recent commit to better fit with other functions. --- source/blender/blenkernel/intern/curve.c | 16 ++++++++-------- source/blender/modifiers/intern/MOD_uvproject.c | 2 ++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 7aa28c3f681..eb364af6ff8 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -580,19 +580,19 @@ void addNurbPointsBezier(Nurb *nu, int number) /* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline calculations ~~~~~~~~~~~ */ -static void calcknots(float *knots, const short tot, const short order, const short flag) +static void calcknots(float *knots, const short pnts, const short order, const short flag) { /* knots: number of pnts NOT corrected for cyclic */ - const int tot_order= tot + order; + const int pnts_order= pnts + order; float k; int a; switch(flag & (CU_NURB_ENDPOINT|CU_NURB_BEZIER)) { case CU_NURB_ENDPOINT: k= 0.0; - for(a=1; a <= tot_order; a++) { + for(a=1; a <= pnts_order; a++) { knots[a-1]= k; - if(a >= order && a <= tot) k+= 1.0f; + if(a >= order && a <= pnts) k+= 1.0f; } break; case CU_NURB_BEZIER: @@ -600,15 +600,15 @@ static void calcknots(float *knots, const short tot, const short order, const sh * if this is not enforced, the displist will be corrupt */ if(order==4) { k= 0.34; - for(a=0; a < tot_order; a++) { + for(a=0; a < pnts_order; a++) { knots[a]= floorf(k); k+= (1.0f/3.0f); } } else if(order==3) { k= 0.6f; - for(a=0; a < tot_order; a++) { - if(a >= order && a <= tot) k+= 0.5f; + for(a=0; a < pnts_order; a++) { + if(a >= order && a <= pnts) k+= 0.5f; knots[a]= floorf(k); } } @@ -617,7 +617,7 @@ static void calcknots(float *knots, const short tot, const short order, const sh } break; default: - for(a=0; a < tot_order; a++) { + for(a=0; a < pnts_order; a++) { knots[a]= (float)a; } break; diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index a5d2e0b38c7..922ae8c1e92 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -42,6 +42,7 @@ #include "DNA_object_types.h" #include "BLI_math.h" +#include "BLI_string.h" #include "BLI_uvproject.h" #include "BLI_utildefines.h" @@ -83,6 +84,7 @@ static void copyData(ModifierData *md, ModifierData *target) tumd->aspecty = umd->aspecty; tumd->scalex = umd->scalex; tumd->scaley = umd->scaley; + BLI_strncpy(tumd->uvlayer_name, umd->uvlayer_name, sizeof(umd->uvlayer_name)); } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md)) -- cgit v1.2.3 From dde50cc39ff4e066a9ec9c216f2bd24c4f8b789e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 1 Aug 2011 06:11:41 +0000 Subject: add sse flags for cmake/msvc --- CMakeLists.txt | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d4489a8c76b..455c3070e8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1054,20 +1054,34 @@ if(APPLE OR WIN32) endif() endif() +# See TEST_SSE_SUPPORT() for how this is defined. + if(WITH_RAYOPTIMIZATION) if(CMAKE_COMPILER_IS_GNUCC) - if(SUPPORT_SSE_BUILD) - set(PLATFORM_CFLAGS " -msse ${PLATFORM_CFLAGS}") - add_definitions(-D__SSE__ -D__MMX__) - endif() - if(SUPPORT_SSE2_BUILD) - set(PLATFORM_CFLAGS " -msse2 ${PLATFORM_CFLAGS}") - add_definitions(-D__SSE2__) - if(NOT SUPPORT_SSE_BUILD) # dont double up - add_definitions(-D__MMX__) - endif() + set(_sse "-msse") + set(_sse2 "-msse2") + elseif(MSVC) + set(_sse "/arch:SSE") + set(_sse2 "/arch:SSE2") + else() + message(WARNING "SSE flags for this compiler not known") + set(_sse) + set(_sse2) + endif() + + if(SUPPORT_SSE_BUILD) + set(PLATFORM_CFLAGS " ${_sse} ${PLATFORM_CFLAGS}") + add_definitions(-D__SSE__ -D__MMX__) + endif() + if(SUPPORT_SSE2_BUILD) + set(PLATFORM_CFLAGS " ${_sse2} ${PLATFORM_CFLAGS}") + add_definitions(-D__SSE2__) + if(NOT SUPPORT_SSE_BUILD) # dont double up + add_definitions(-D__MMX__) endif() endif() + unset(_sse) + unset(_sse2) endif() if(WITH_IMAGE_OPENJPEG) -- cgit v1.2.3 From cd793378dbe7b761e22b2c48540ff2afc92e22ad Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 1 Aug 2011 06:50:24 +0000 Subject: fix [#28112] Vertex paint crash --- source/blender/blenkernel/intern/DerivedMesh.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index d9c98bc0200..62b8830de20 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1883,7 +1883,9 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos /* set the DerivedMesh to only copy needed data */ mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link); - DM_set_only_copy(dm, mask); + /* needMapping check here fixes bug [#28112], otherwise its + * possible that it wont be copied */ + DM_set_only_copy(dm, mask | (needMapping ? CD_MASK_ORIGINDEX : 0)); /* add cloth rest shape key if need */ if(mask & CD_MASK_CLOTH_ORCO) -- cgit v1.2.3 From 2f3685615f90777b6a174fa54de13b1c67eefb61 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 1 Aug 2011 06:55:05 +0000 Subject: fix for template --- release/scripts/templates/addon_add_object.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/scripts/templates/addon_add_object.py b/release/scripts/templates/addon_add_object.py index 67e033271f4..98517fd97a0 100644 --- a/release/scripts/templates/addon_add_object.py +++ b/release/scripts/templates/addon_add_object.py @@ -35,7 +35,7 @@ def add_object(self, context): mesh.from_pydata(verts, edges, faces) # useful for development when the mesh may be invalid. # mesh.validate(verbose=True) - add_object_data(context, mesh_data, operator=self) + add_object_data(context, mesh, operator=self) class OBJECT_OT_add_object(bpy.types.Operator, AddObjectHelper): -- cgit v1.2.3 From c965d1d2ccfd57926476cb5c091afa35c6de217f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 1 Aug 2011 08:53:57 +0000 Subject: fix [#28061] Texture (paint) bleeding on edges respect clamp u/v image options. --- source/blender/editors/sculpt_paint/paint_image.c | 26 +++++++++++++++++------ 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index c9a6aa87cd0..32004fd4525 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -2187,7 +2187,7 @@ static int IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot) /* One of the most important function for projectiopn painting, since it selects the pixels to be added into each bucket. * initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */ -static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, const ImBuf *ibuf) +static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, const ImBuf *ibuf, const short clamp_u, const short clamp_v) { /* Projection vars, to get the 3D locations into screen space */ MemArena *arena = ps->arena_mt[thread_index]; @@ -2304,14 +2304,24 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i if (pixel_bounds_array(uv_clip, &bounds_px, ibuf->x, ibuf->y, uv_clip_tot)) { - + + if(clamp_u) { + CLAMP(bounds_px.xmin, 0, ibuf->x); + CLAMP(bounds_px.xmax, 0, ibuf->x); + } + + if(clamp_v) { + CLAMP(bounds_px.ymin, 0, ibuf->y); + CLAMP(bounds_px.ymax, 0, ibuf->y); + } + /* clip face and */ has_isect = 0; for (y = bounds_px.ymin; y < bounds_px.ymax; y++) { //uv[1] = (((float)y) + 0.5f) / (float)ibuf->y; uv[1] = (float)y / ibuf_yf; /* use pixel offset UV coords instead */ - + has_x_isect = 0; for (x = bounds_px.xmin; x < bounds_px.xmax; x++) { //uv[0] = (((float)x) + 0.5f) / ibuf->x; @@ -2630,6 +2640,7 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index LinkNode *node; int face_index, image_index=0; ImBuf *ibuf = NULL; + Image *ima = NULL; MTFace *tf; Image *tpage_last = NULL; @@ -2638,9 +2649,10 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index if (ps->image_tot==1) { /* Simple loop, no context switching */ ibuf = ps->projImages[0].ibuf; - + ima = ps->projImages[0].ima; + for (node = ps->bucketFaces[bucket_index]; node; node= node->next) { - project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf); + project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V); } } else { @@ -2659,14 +2671,14 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index for (image_index=0; image_index < ps->image_tot; image_index++) { if (ps->projImages[image_index].ima == tpage_last) { ibuf = ps->projImages[image_index].ibuf; + ima = ps->projImages[image_index].ima; break; } } } /* context switching done */ - project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf); - + project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V); } } -- cgit v1.2.3 From db494472ac02ff73dbc0984940e7758321e5642d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 2 Aug 2011 02:28:37 +0000 Subject: don't include fcurve modifiers when getting an actions frame range. could too easily give a range of 600,000 which would make exporters hang. --- source/blender/makesrna/intern/rna_action.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 7fdb96fda6e..cfedee3c6cd 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -191,8 +191,9 @@ static void rna_Action_active_pose_marker_index_range(PointerRNA *ptr, int *min, static void rna_Action_frame_range_get(PointerRNA *ptr,float *values) -{ - calc_action_range(ptr->id.data, values, values+1, 1); +{ /* don't include modifiers because they too easily can have very large + * ranges: MINAFRAMEF to MAXFRAMEF. */ + calc_action_range(ptr->id.data, values, values+1, FALSE); } -- cgit v1.2.3 From fcd7d2b486f2435907423188ffdfe2840c966b0b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 2 Aug 2011 05:52:27 +0000 Subject: NDOF related edits - fix for building without NDOF on X11 - quiet some warnings --- CMakeLists.txt | 6 ++-- build_files/cmake/macros.cmake | 4 +-- intern/ghost/CMakeLists.txt | 35 ++++++++++++++++++---- intern/ghost/SConscript | 3 ++ intern/ghost/intern/GHOST_System.cpp | 8 ++++- intern/ghost/intern/GHOST_SystemX11.cpp | 4 +++ source/blender/editors/space_image/image_ops.c | 2 +- source/blender/editors/space_view3d/view3d_edit.c | 4 +-- source/blender/windowmanager/intern/wm_operators.c | 2 +- 9 files changed, 52 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ac6d67cd1c..fe86aaf9b26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,7 +179,7 @@ option(WITH_LZO "Enable fast LZO compression (used for pointcache)" ON option(WITH_LZMA "Enable best LZMA compression, (used for pointcache)" ON) # Misc -option(WITH_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON) +option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON) option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON) if(UNIX AND NOT APPLE) option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON) @@ -453,7 +453,7 @@ if(UNIX AND NOT APPLE) endif() endif() - if (WITH_NDOF) + if (WITH_INPUT_NDOF) if(CMAKE_SYSTEM_NAME MATCHES "Linux") set(NDOF /usr) set(NDOF_INC ${NDOF}/include) @@ -1039,7 +1039,7 @@ elseif(APPLE) set(TIFF_LIBPATH ${TIFF}/lib) endif() - if (WITH_NDOF) + if (WITH_INPUT_NDOF) # linker needs "-weak_framework 3DconnexionClient" endif() diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 3de9db6dac9..c53f52b7bae 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -193,7 +193,7 @@ macro(SETUP_LIBDIRS) if(WITH_MEM_JEMALLOC) link_directories(${JEMALLOC_LIBPATH}) endif() - if(WITH_NDOF) + if(WITH_INPUT_NDOF) link_directories(${NDOF_LIBPATH}) endif() @@ -317,7 +317,7 @@ macro(setup_liblinks if(WITH_MEM_JEMALLOC) target_link_libraries(${target} ${JEMALLOC_LIBRARIES}) endif() - if(WITH_NDOF) + if(WITH_INPUT_NDOF) target_link_libraries(${target} ${NDOF_LIBRARY}) endif() diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index b69dff607e8..86829c892ed 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -97,6 +97,9 @@ if(WITH_GHOST_DEBUG) add_definitions(-DWITH_GHOST_DEBUG) endif() +if(WITH_INPUT_NDOF) + add_definitions(-DWITH_INPUT_NDOF) +endif() if(WITH_HEADLESS OR WITH_GHOST_SDL) if(WITH_HEADLESS) @@ -158,14 +161,21 @@ elseif(APPLE) intern/GHOST_SystemCocoa.mm intern/GHOST_SystemPathsCocoa.mm intern/GHOST_WindowCocoa.mm - intern/GHOST_NDOFManagerCocoa.mm intern/GHOST_DisplayManagerCocoa.h intern/GHOST_SystemCocoa.h intern/GHOST_SystemPathsCocoa.h intern/GHOST_WindowCocoa.h - intern/GHOST_NDOFManagerCocoa.h ) + + if(WITH_INPUT_NDOF) + list(APPEND SRC + intern/GHOST_NDOFManagerCocoa.mm + + intern/GHOST_NDOFManagerCocoa.h + ) + endif() + else() list(APPEND SRC intern/GHOST_DisplayManagerCarbon.cpp @@ -199,13 +209,11 @@ elseif(UNIX) intern/GHOST_SystemX11.cpp intern/GHOST_SystemPathsX11.cpp intern/GHOST_WindowX11.cpp - intern/GHOST_NDOFManagerX11.cpp intern/GHOST_DisplayManagerX11.h intern/GHOST_SystemX11.h intern/GHOST_SystemPathsX11.h intern/GHOST_WindowX11.h - intern/GHOST_NDOFManagerX11.h ) if(NOT WITH_INSTALL_PORTABLE) @@ -219,6 +227,14 @@ elseif(UNIX) ) endif() + if(WITH_INPUT_NDOF) + list(APPEND SRC + intern/GHOST_NDOFManagerX11.cpp + + intern/GHOST_NDOFManagerX11.h + ) + endif() + elseif(WIN32) if(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX") @@ -234,7 +250,6 @@ elseif(WIN32) intern/GHOST_SystemPathsWin32.cpp intern/GHOST_WindowWin32.cpp intern/GHOST_DropTargetWin32.cpp - intern/GHOST_NDOFManagerWin32.cpp intern/GHOST_DisplayManagerWin32.h intern/GHOST_DropTargetWin32.h @@ -242,8 +257,16 @@ elseif(WIN32) intern/GHOST_SystemPathsWin32.h intern/GHOST_WindowWin32.h intern/GHOST_TaskbarWin32.h - intern/GHOST_NDOFManagerWin32.h ) + + if(WITH_INPUT_NDOF) + list(APPEND SRC + intern/GHOST_NDOFManagerWin32.cpp + + intern/GHOST_NDOFManagerWin32.h + ) + endif() + endif() blender_add_lib(bf_intern_ghost "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript index 3dec748ce31..d65eb0caab6 100644 --- a/intern/ghost/SConscript +++ b/intern/ghost/SConscript @@ -78,6 +78,9 @@ if env['BF_GHOST_DEBUG']: else: sources.remove('intern' + os.sep + 'GHOST_EventPrinter.cpp') +if env['WITH_BF_3DMOUSE']: + defs.append('WITH_INPUT_NDOF') + if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'): incs = env['BF_WINTAB_INC'] + ' ' + incs diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 792adba7ce3..f601031f2b6 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -46,7 +46,13 @@ GHOST_System::GHOST_System() -: m_displayManager(0), m_timerManager(0), m_windowManager(0), m_eventManager(0), m_ndofManager(0) + : m_displayManager(0), + m_timerManager(0), + m_windowManager(0), + m_eventManager(0) +#ifdef WITH_INPUT_NDOF + , m_ndofManager(0) +#endif { } diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 517c3a1ebac..105f71b514f 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -167,7 +167,9 @@ init( GHOST_TSuccess success = GHOST_System::init(); if (success) { +#ifdef WITH_INPUT_NDOF m_ndofManager = new GHOST_NDOFManagerX11(*this); +#endif m_displayManager = new GHOST_DisplayManagerX11(this); if (m_displayManager) { @@ -414,9 +416,11 @@ processEvents( anyProcessed = true; } +#ifdef WITH_INPUT_NDOF if (dynamic_cast(m_ndofManager)->processEvents()) { anyProcessed = true; } +#endif } while (waitForEvent && !anyProcessed); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 204d5dfb1b1..a7c90bb0aed 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -445,7 +445,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot) * that explains the negative signs in the code below */ -static int view_ndof_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) { SpaceImage *sima= CTX_wm_space_image(C); ARegion *ar= CTX_wm_region(C); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 94224698063..09e703d6ce0 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -968,7 +968,7 @@ void ndof_to_quat(struct wmNDOFMotionData* ndof, float q[4]) q[3] = scale * z; } -static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) // -- "orbit" navigation (trackball/turntable) // -- zooming // -- panning in rotationally-locked views @@ -1118,7 +1118,7 @@ void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot) ot->flag = 0; } -static int ndof_pan_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) // -- "pan" navigation // -- zoom or dolly? { diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index d813fd913ab..d9c3300fcef 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1411,7 +1411,7 @@ static void WM_OT_search_menu(wmOperatorType *ot) ot->poll= wm_search_menu_poll; } -static int wm_ndof_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int wm_ndof_menu_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) { uiPupMenuInvoke(C,"VIEW3D_MT_ndof_settings"); -- cgit v1.2.3 From baa37b1b464d8f05bf5d788ec66ae46bdc675a0f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 2 Aug 2011 06:32:53 +0000 Subject: more cmake/x11 edits - added includes for spnav - added FindSpacenav.cmake which allows using spacenav from a nonstandard path. - remove NDOF_LIBPATH, use a full library path instead. --- CMakeLists.txt | 15 ++++-- build_files/cmake/Modules/FindSpacenav.cmake | 70 ++++++++++++++++++++++++++++ build_files/cmake/macros.cmake | 5 +- intern/ghost/CMakeLists.txt | 3 ++ 4 files changed, 84 insertions(+), 9 deletions(-) create mode 100644 build_files/cmake/Modules/FindSpacenav.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index fe86aaf9b26..d95cbb6e536 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -454,11 +454,15 @@ if(UNIX AND NOT APPLE) endif() if (WITH_INPUT_NDOF) - if(CMAKE_SYSTEM_NAME MATCHES "Linux") - set(NDOF /usr) - set(NDOF_INC ${NDOF}/include) - set(NDOF_LIBRARY spnav) - set(NDOF_LIBPATH ${NDOF}/lib) + find_package(Spacenav) + if(NOT SPACENAV_FOUND) + set(WITH_INPUT_NDOF OFF) + endif() + + # use generic names within blenders buildsystem. + if(SPACENAV_FOUND) + set(NDOF_INCLUDE_DIRS ${SPACENAV_INCLUDE_DIRS}) + set(NDOF_LIBRARIES ${SPACENAV_LIBRARIES}) endif() endif() @@ -1334,6 +1338,7 @@ if(FIRST_RUN) info_cfg_option(WITH_OPENCOLLADA) info_cfg_option(WITH_FFTW3) info_cfg_option(WITH_INTERNATIONAL) + info_cfg_option(WITH_INPUT_NDOF) info_cfg_text("Compiler Options:") info_cfg_option(WITH_BUILDINFO) diff --git a/build_files/cmake/Modules/FindSpacenav.cmake b/build_files/cmake/Modules/FindSpacenav.cmake new file mode 100644 index 00000000000..206f3611ed6 --- /dev/null +++ b/build_files/cmake/Modules/FindSpacenav.cmake @@ -0,0 +1,70 @@ +# - Find Spacenav library +# Find the native Spacenav includes and library +# This module defines +# SPACENAV_INCLUDE_DIRS, where to find spnav.h, Set when +# SPACENAV_INCLUDE_DIR is found. +# SPACENAV_LIBRARIES, libraries to link against to use Spacenav. +# SPACENAV_ROOT_DIR, The base directory to search for Spacenav. +# This can also be an environment variable. +# SPACENAV_FOUND, If false, do not try to use Spacenav. +# +# also defined, but not for general use are +# SPACENAV_LIBRARY, where to find the Spacenav library. + +#============================================================================= +# Copyright 2011 Blender Foundation. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= + +# If SPACENAV_ROOT_DIR was defined in the environment, use it. +IF(NOT SPACENAV_ROOT_DIR AND NOT $ENV{SPACENAV_ROOT_DIR} STREQUAL "") + SET(SPACENAV_ROOT_DIR $ENV{SPACENAV_ROOT_DIR}) +ENDIF() + +SET(_spacenav_SEARCH_DIRS + ${SPACENAV_ROOT_DIR} + /usr/local + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave +) + +FIND_PATH(SPACENAV_INCLUDE_DIR + NAMES + spnav.h + HINTS + ${_spacenav_SEARCH_DIRS} + PATH_SUFFIXES + include +) + +FIND_LIBRARY(SPACENAV_LIBRARY + NAMES + spnav + HINTS + ${_spacenav_SEARCH_DIRS} + PATH_SUFFIXES + lib64 lib + ) + +# handle the QUIETLY and REQUIRED arguments and set SPACENAV_FOUND to TRUE if +# all listed variables are TRUE +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Spacenav DEFAULT_MSG + SPACENAV_LIBRARY SPACENAV_INCLUDE_DIR) + +IF(SPACENAV_FOUND) + SET(SPACENAV_LIBRARIES ${SPACENAV_LIBRARY}) + SET(SPACENAV_INCLUDE_DIRS ${SPACENAV_INCLUDE_DIR}) +ENDIF(SPACENAV_FOUND) + +MARK_AS_ADVANCED( + SPACENAV_INCLUDE_DIR + SPACENAV_LIBRARY +) diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index c53f52b7bae..ed200abd419 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -193,9 +193,6 @@ macro(SETUP_LIBDIRS) if(WITH_MEM_JEMALLOC) link_directories(${JEMALLOC_LIBPATH}) endif() - if(WITH_INPUT_NDOF) - link_directories(${NDOF_LIBPATH}) - endif() if(WIN32 AND NOT UNIX) link_directories(${PTHREADS_LIBPATH}) @@ -318,7 +315,7 @@ macro(setup_liblinks target_link_libraries(${target} ${JEMALLOC_LIBRARIES}) endif() if(WITH_INPUT_NDOF) - target_link_libraries(${target} ${NDOF_LIBRARY}) + target_link_libraries(${target} ${NDOF_LIBRARIES}) endif() if(WIN32 AND NOT UNIX) diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 86829c892ed..2180ddbe567 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -99,6 +99,9 @@ endif() if(WITH_INPUT_NDOF) add_definitions(-DWITH_INPUT_NDOF) + list(APPEND INC_SYS + ${NDOF_INCLUDE_DIRS} + ) endif() if(WITH_HEADLESS OR WITH_GHOST_SDL) -- cgit v1.2.3 From ed306416f5db7516be502b69b677e90a332c3b91 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 2 Aug 2011 06:40:40 +0000 Subject: replace WM_OT_ndof_menu with a key->menu assignment. --- source/blender/windowmanager/intern/wm_operators.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index d9c3300fcef..7dc4bfb65a6 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1411,22 +1411,6 @@ static void WM_OT_search_menu(wmOperatorType *ot) ot->poll= wm_search_menu_poll; } -static int wm_ndof_menu_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) -{ - uiPupMenuInvoke(C,"VIEW3D_MT_ndof_settings"); - - return OPERATOR_FINISHED; // <-- correct? - return OPERATOR_CANCELLED; // <-- correct? -} - -static void WM_OT_ndof_menu(wmOperatorType *ot) -{ - ot->name = "NDOF Menu"; - ot->idname = "WM_OT_ndof_menu"; - - ot->invoke = wm_ndof_menu_invoke; -} - static int wm_call_menu_exec(bContext *C, wmOperator *op) { char idname[BKE_ST_MAXNAME]; @@ -3517,7 +3501,6 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_debug_menu); WM_operatortype_append(WM_OT_splash); WM_operatortype_append(WM_OT_search_menu); - WM_operatortype_append(WM_OT_ndof_menu); WM_operatortype_append(WM_OT_call_menu); WM_operatortype_append(WM_OT_radial_control); WM_operatortype_append(WM_OT_ndof_sensitivity_change); @@ -3743,7 +3726,7 @@ void wm_window_keymap(wmKeyConfig *keyconf) /* menus that can be accessed anywhere in blender */ WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "WM_OT_ndof_menu", NDOF_BUTTON_MENU, KM_PRESS, 0, 0); + WM_keymap_add_menu(keymap, "VIEW3D_MT_ndof_settings", NDOF_BUTTON_MENU, KM_PRESS, 0, 0); /* Space switching */ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F2KEY, KM_PRESS, KM_SHIFT, 0); /* new in 2.5x, was DXF export */ -- cgit v1.2.3 From 2e860a3e85d1f1045d15b525e3a88d3e8fbb6adf Mon Sep 17 00:00:00 2001 From: Jiri Hnidek Date: Tue, 2 Aug 2011 07:02:40 +0000 Subject: - Blender could be build with scons again. --- SConstruct | 1 + build_files/scons/tools/btools.py | 4 +++- intern/ghost/intern/GHOST_NDOFManager.cpp | 6 +++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/SConstruct b/SConstruct index 053f414c954..e27f8eae367 100644 --- a/SConstruct +++ b/SConstruct @@ -241,6 +241,7 @@ if 'blenderlite' in B.targets: target_env_defs['BF_BUILDINFO'] = False target_env_defs['BF_NO_ELBEEM'] = True target_env_defs['WITH_BF_PYTHON'] = False + target_env_defs['WITH_BF_3DMOUSE'] = False # Merge blenderlite, let command line to override for k,v in target_env_defs.iteritems(): diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index 677ddab8db5..a96bf8ce4cc 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -136,7 +136,7 @@ def validate_arguments(args, bc): 'BF_NO_ELBEEM', 'WITH_BF_CXX_GUARDEDALLOC', 'WITH_BF_JEMALLOC', 'WITH_BF_STATICJEMALLOC', 'BF_JEMALLOC', 'BF_JEMALLOC_INC', 'BF_JEMALLOC_LIBPATH', 'BF_JEMALLOC_LIB', 'BF_JEMALLOC_LIB_STATIC', - 'BUILDBOT_BRANCH' + 'BUILDBOT_BRANCH', 'WITH_BF_3DMOUSE' ] # Have options here that scons expects to be lists @@ -437,6 +437,8 @@ def read_opts(env, cfg, args): (BoolVariable('WITH_BF_PLAYER', 'Build blenderplayer if true', False)), (BoolVariable('WITH_BF_NOBLENDER', 'Do not build blender if true', False)), + (BoolVariable('WITH_BF_3DMOUSE', 'Build blender with support of 3D mouses', False)), + ('CFLAGS', 'C only flags', []), ('CCFLAGS', 'Generic C and C++ flags', []), ('CXXFLAGS', 'C++ only flags', []), diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 4694afaf24f..72b0dba297a 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -185,10 +185,10 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) memset(m_translation, 0, sizeof(m_translation)); memset(m_rotation, 0, sizeof(m_rotation)); - #ifdef WITH_BF_3DMOUSE - puts("WITH_BF_3DMOUSE is defined!"); + #ifdef WITH_INPUT_NDOF + puts("WITH_INPUT_NDOF is defined!"); #else - puts("WITH_BF_3DMOUSE is not defined."); + puts("WITH_INPUT_NDOF is not defined."); #endif } -- cgit v1.2.3 From 70b4758ff8756a55a1c88156a852b80a0d3c2ef9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 2 Aug 2011 07:08:22 +0000 Subject: Made wmNDOFMotionData use a vector rather then xyz members, makes it nicer to use with math functions. ndof_to_angle_axis and ndof_to_quat now use math functions. --- .../scripts/startup/bl_ui/space_userpref_keymap.py | 4 +- source/blender/editors/space_image/image_ops.c | 6 +-- source/blender/editors/space_view3d/view3d_edit.c | 63 +++++++--------------- source/blender/editors/space_view3d/view3d_fly.c | 8 +-- source/blender/editors/transform/transform_ops.c | 6 +-- source/blender/windowmanager/WM_types.h | 4 +- .../blender/windowmanager/intern/wm_event_system.c | 12 ++--- 7 files changed, 39 insertions(+), 64 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_userpref_keymap.py b/release/scripts/startup/bl_ui/space_userpref_keymap.py index 8faf1afab63..8fed3a934d9 100644 --- a/release/scripts/startup/bl_ui/space_userpref_keymap.py +++ b/release/scripts/startup/bl_ui/space_userpref_keymap.py @@ -271,7 +271,7 @@ class InputKeyMapPanel: row.prop(kmi, "type", text="", full_event=True) elif map_type == 'MOUSE': row.prop(kmi, "type", text="", full_event=True) - if map_type == 'NDOF': + elif map_type == 'NDOF': row.prop(kmi, "type", text="", full_event=True) elif map_type == 'TWEAK': subrow = row.row() @@ -308,7 +308,7 @@ class InputKeyMapPanel: sub = split.column() subrow = sub.row(align=True) - if map_type in ('KEYBOARD', 'NDOF'): + if map_type in {'KEYBOARD', 'NDOF'}: subrow.prop(kmi, "type", text="", event=True) subrow.prop(kmi, "value", text="") elif map_type == 'MOUSE': diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index a7c90bb0aed..6e84c1a7f0c 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -461,8 +461,8 @@ static int view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) const float zoom_sensitivity = 0.5f; const float pan_sensitivity = 300.f; - float pan_x = pan_sensitivity * dt * ndof->tx / sima->zoom; - float pan_y = pan_sensitivity * dt * ndof->ty / sima->zoom; + float pan_x = pan_sensitivity * dt * ndof->tvec[0] / sima->zoom; + float pan_y = pan_sensitivity * dt * ndof->tvec[1] / sima->zoom; /* "mouse zoom" factor = 1 + (dx + dy) / 300 * what about "ndof zoom" factor? should behave like this: @@ -470,7 +470,7 @@ static int view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) * move forward -> factor > 1 * move backward -> factor < 1 */ - float zoom_factor = 1.f + zoom_sensitivity * dt * -ndof->tz; + float zoom_factor = 1.f + zoom_sensitivity * dt * -ndof->tvec[2]; sima_zoom_set_factor(sima, ar, zoom_factor); sima->xof += pan_x; diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 09e703d6ce0..8d77aeaea1b 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -931,42 +931,18 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) // NDOF utility functions // (should these functions live in this file?) float ndof_to_angle_axis(struct wmNDOFMotionData* ndof, float axis[3]) - { - const float x = ndof->rx; - const float y = ndof->ry; - const float z = ndof->rz; - - float angular_velocity = sqrtf(x*x + y*y + z*z); - float angle = ndof->dt * angular_velocity; - - float scale = 1.f / angular_velocity; - - // normalize - axis[0] = scale * x; - axis[1] = scale * y; - axis[2] = scale * z; - - return angle; - } +{ + return ndof->dt * normalize_v3_v3(axis, ndof->rvec); +} void ndof_to_quat(struct wmNDOFMotionData* ndof, float q[4]) - { - const float x = ndof->rx; - const float y = ndof->ry; - const float z = ndof->rz; - - float angular_velocity = sqrtf(x*x + y*y + z*z); - float angle = ndof->dt * angular_velocity; - - // combined scaling factor -- normalize axis while converting to quaternion - float scale = sin(0.5f * angle) / angular_velocity; +{ + float axis[3]; + float angle; - // convert axis-angle to quaternion - q[0] = cos(0.5f * angle); - q[1] = scale * x; - q[2] = scale * y; - q[3] = scale * z; - } + angle= ndof_to_angle_axis(ndof, axis); + axis_angle_to_quat(q, axis, angle); +} static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) // -- "orbit" navigation (trackball/turntable) @@ -987,7 +963,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event const float pan_sensitivity = 1.f; // rather have bool, but... - int has_rotation = rv3d->viewlock != RV3D_LOCKED && (ndof->rx || ndof->ry || ndof->rz); + int has_rotation = rv3d->viewlock != RV3D_LOCKED && !is_zero_v3(ndof->rvec); float view_inv[4]; invert_qt_qt(view_inv, rv3d->viewquat); @@ -998,19 +974,19 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt); #endif - if (ndof->tz) { + if (ndof->tvec[2]) { // Zoom! // velocity should be proportional to the linear velocity attained by rotational motion of same strength // [got that?] // proportional to arclength = radius * angle - float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz; + float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tvec[2]; rv3d->dist += zoom_distance; } if (rv3d->viewlock == RV3D_LOCKED) { /* rotation not allowed -- explore panning options instead */ - float pan_vec[3] = {ndof->tx, ndof->ty, 0}; + float pan_vec[3] = {ndof->tvec[0], ndof->tvec[1], 0.0f}; mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt); /* transform motion from view to world coordinates */ @@ -1072,7 +1048,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event mul_qt_v3(view_inv, xvec); /* Perform the up/down rotation */ - angle = rot_sensitivity * dt * ndof->rx; + angle = rot_sensitivity * dt * ndof->rvec[0]; if (invert) angle = -angle; rot[0] = cos(angle); @@ -1080,7 +1056,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); /* Perform the orbital rotation */ - angle = rot_sensitivity * dt * ndof->ry; + angle = rot_sensitivity * dt * ndof->rvec[1]; if (invert) angle = -angle; @@ -1155,11 +1131,10 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) const float vertical_sensitivity = 0.4f; const float lateral_sensitivity = 0.6f; - float pan_vec[3] = { - lateral_sensitivity * ndof->tx, - vertical_sensitivity * ndof->ty, - forward_sensitivity * ndof->tz - }; + float pan_vec[3] = {lateral_sensitivity * ndof->tvec[0], + vertical_sensitivity * ndof->tvec[1], + forward_sensitivity * ndof->tvec[2] + }; mul_v3_fl(pan_vec, speed * dt); #endif diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 38d93ab59f3..5c53faf96a6 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -953,9 +953,9 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) // ^^ this is ok for default cube scene, but should scale with.. something float trans[3] = { - lateral_sensitivity * ndof->tx, - vertical_sensitivity * ndof->ty, - forward_sensitivity * ndof->tz + lateral_sensitivity * ndof->tvec[0], + vertical_sensitivity * ndof->tvec[1], + forward_sensitivity * ndof->tvec[2] }; if (fly->use_precision) @@ -969,7 +969,7 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) if (flag & NDOF_FLY_HELICOPTER) { // replace world z component with device y (yes it makes sense) - trans[2] = speed * dt * vertical_sensitivity * ndof->ty; + trans[2] = speed * dt * vertical_sensitivity * ndof->tvec[1]; } if (rv3d->persp==RV3D_CAMOB) { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index a779982099e..0efd25c4faa 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -361,10 +361,10 @@ static int transform_modal(bContext *C, wmOperator *op, wmEvent *event) TransInfo *t = op->customdata; if (event->type == NDOF_MOTION) - { - // puts("transform_modal: passing through NDOF_MOTION"); + { + /* puts("transform_modal: passing through NDOF_MOTION"); */ return OPERATOR_PASS_THROUGH; - } + } /* XXX insert keys are called here, and require context */ t->context= C; diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 7476410ec19..7fd52e89a5f 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -389,8 +389,8 @@ typedef struct wmNDOFMotionData { /* awfully similar to GHOST_TEventNDOFMotionData... */ // Each component normally ranges from -1 to +1, but can exceed that. // These use blender standard view coordinates, with positive rotations being CCW about the axis. - float tx, ty, tz; // translation - float rx, ry, rz; // rotation: + float tvec[3]; // translation + float rvec[3]; // 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 diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 322cd3b5642..0abae2e06b7 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2323,13 +2323,13 @@ static void attach_ndof_data(wmEvent* event, const GHOST_TEventNDOFMotionData* g const float s = U.ndof_sensitivity; - data->tx = s * ghost->tx; - data->ty = s * ghost->ty; - data->tz = s * ghost->tz; + data->tvec[0]= s * ghost->tx; + data->tvec[1]= s * ghost->ty; + data->tvec[2]= s * ghost->tz; - data->rx = s * ghost->rx; - data->ry = s * ghost->ry; - data->rz = s * ghost->rz; + data->rvec[0]= s * ghost->rx; + data->rvec[1]= s * ghost->ry; + data->rvec[2]= s * ghost->rz; data->dt = ghost->dt; -- cgit v1.2.3 From d4a6884fcfbedcb1b13f65b071bfcf1e04f3ef9d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 2 Aug 2011 07:49:34 +0000 Subject: add back timer based redraw, not sure why this was removed r38908. Zealous redraws now use commented define. --- source/blender/editors/space_view3d/view3d_fly.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index 5c53faf96a6..ca64476b35e 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -30,6 +30,7 @@ /* defines VIEW3D_OT_fly modal operator */ //#define NDOF_FLY_DEBUG +//#define NDOF_FLY_DRAW_TOOMUCH // is this needed for ndof? - commented so redraw doesnt thrash - campbell #include "DNA_anim_types.h" #include "DNA_scene_types.h" @@ -289,8 +290,10 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even fly->zlock_momentum=0.0f; fly->grid= 1.0f; fly->use_precision= 0; - fly->redraw= 1; +#ifdef NDOF_FLY_DRAW_TOOMUCH + fly->redraw= 1; +#endif fly->dvec_prev[0]= fly->dvec_prev[1]= fly->dvec_prev[2]= 0.0f; fly->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); @@ -436,7 +439,10 @@ static int flyEnd(bContext *C, FlyInfo *fly) static void flyEvent(FlyInfo *fly, wmEvent *event) { - if (event->type == MOUSEMOVE) { + if (event->type == TIMER && event->customdata == fly->timer) { + fly->redraw = 1; + } + else if (event->type == MOUSEMOVE) { VECCOPY2D(fly->mval, event->mval); } else if (event->type == NDOF_MOTION) { @@ -746,9 +752,9 @@ static int flyApply(bContext *C, FlyInfo *fly) double time_current; /*time how fast it takes for us to redraw, this is so simple scenes dont fly too fast */ float time_redraw; float time_redraw_clamped; - +#ifdef NDOF_FLY_DRAW_TOOMUCH fly->redraw= 1; - +#endif time_current= PIL_check_seconds_timer(); time_redraw= (float)(time_current - fly->time_lastdraw); time_redraw_clamped= MIN2(0.05f, time_redraw); /* clamt the redraw time to avoid jitter in roll correction */ @@ -1125,7 +1131,7 @@ static int fly_modal(bContext *C, wmOperator *op, wmEvent *event) WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, fly_object); } - // puts("redraw!"); // too frequent, fix tomorrow. + // puts("redraw!"); // too frequent, commented with NDOF_FLY_DRAW_TOOMUCH for now ED_region_tag_redraw(CTX_wm_region(C)); } -- cgit v1.2.3 From 078dff64d2963e56675e490927d675c13626a956 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 2 Aug 2011 08:12:50 +0000 Subject: no functional changes. style edits, also renamed ndof_to_angle_axis --> ndof_to_axis_angle --- source/blender/editors/space_view3d/view3d_edit.c | 6 +- source/blender/editors/space_view3d/view3d_fly.c | 237 +++++++++++---------- .../blender/editors/space_view3d/view3d_intern.h | 2 +- 3 files changed, 126 insertions(+), 119 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 8d77aeaea1b..e6fd9e8867b 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -930,7 +930,7 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) // NDOF utility functions // (should these functions live in this file?) -float ndof_to_angle_axis(struct wmNDOFMotionData* ndof, float axis[3]) +float ndof_to_axis_angle(struct wmNDOFMotionData* ndof, float axis[3]) { return ndof->dt * normalize_v3_v3(axis, ndof->rvec); } @@ -940,7 +940,7 @@ void ndof_to_quat(struct wmNDOFMotionData* ndof, float q[4]) float axis[3]; float angle; - angle= ndof_to_angle_axis(ndof, axis); + angle= ndof_to_axis_angle(ndof, axis); axis_angle_to_quat(q, axis, angle); } @@ -1023,7 +1023,7 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event mul_qt_qtqt(rot, rot, view_inv_conj); #else // ---------------------------------------- Mike's revised version float axis[3]; - float angle = rot_sensitivity * ndof_to_angle_axis(ndof, axis); + float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis); if (invert) angle = -angle; diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index ca64476b35e..046037a092f 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -109,7 +109,7 @@ void fly_modal_keymap(wmKeyConfig *keyconf) wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "View3D Fly Modal"); /* this function is called for each spacetype, only needs to add map once */ - if(keymap) return; + if (keymap) return; keymap= WM_modalkeymap_add(keyconf, "View3D Fly Modal", modal_items); @@ -261,21 +261,21 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even fly->ar = CTX_wm_region(C); fly->scene= CTX_data_scene(C); - #ifdef NDOF_FLY_DEBUG +#ifdef NDOF_FLY_DEBUG puts("\n-- fly begin --"); - #endif +#endif - if(fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->id.lib) { + if (fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->id.lib) { BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library"); return FALSE; } - if(fly->v3d->ob_centre) { + if (fly->v3d->ob_centre) { BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view is locked to an object"); return FALSE; } - if(fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->constraints.first) { + if (fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->constraints.first) { BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints"); return FALSE; } @@ -319,7 +319,7 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even fly->dist_backup= fly->rv3d->dist; if (fly->rv3d->persp==RV3D_CAMOB) { Object *ob_back; - if((U.uiflag & USER_CAM_LOCK_NO_PARENT)==0 && (fly->root_parent=fly->v3d->camera->parent)) { + if ((U.uiflag & USER_CAM_LOCK_NO_PARENT)==0 && (fly->root_parent=fly->v3d->camera->parent)) { while(fly->root_parent->parent) fly->root_parent= fly->root_parent->parent; ob_back= fly->root_parent; @@ -337,7 +337,8 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even negate_v3_v3(fly->rv3d->ofs, fly->v3d->camera->obmat[3]); fly->rv3d->dist=0.0; - } else { + } + else { /* perspective or ortho */ if (fly->rv3d->persp==RV3D_ORTHO) fly->rv3d->persp= RV3D_PERSP; /*if ortho projection, make perspective */ @@ -373,12 +374,12 @@ static int flyEnd(bContext *C, FlyInfo *fly) float upvec[3]; - if(fly->state == FLY_RUNNING) + if (fly->state == FLY_RUNNING) return OPERATOR_RUNNING_MODAL; - #ifdef NDOF_FLY_DEBUG +#ifdef NDOF_FLY_DEBUG puts("\n-- fly end --"); - #endif +#endif WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), fly->timer); @@ -390,14 +391,14 @@ static int flyEnd(bContext *C, FlyInfo *fly) /* Revert to original view? */ if (fly->persp_backup==RV3D_CAMOB) { /* a camera view */ Object *ob_back; - if(fly->root_parent)ob_back= fly->root_parent; - else ob_back= fly->v3d->camera; + ob_back= (fly->root_parent) ? fly->root_parent : fly->v3d->camera; /* store the original camera loc and rot */ object_tfm_restore(ob_back, fly->obtfm); DAG_id_tag_update(&ob_back->id, OB_RECALC_OB); - } else { + } + else { /* Non Camera we need to reset the view back to the original location bacause the user canceled*/ copy_qt_qt(rv3d->viewquat, fly->rot_backup); copy_v3_v3(rv3d->ofs, fly->ofs_backup); @@ -422,13 +423,13 @@ static int flyEnd(bContext *C, FlyInfo *fly) rv3d->rflag &= ~RV3D_NAVIGATING; //XXX2.5 BIF_view3d_previewrender_signal(fly->sa, PR_DBASE|PR_DISPRECT); /* not working at the moment not sure why */ - if(fly->obtfm) + if (fly->obtfm) MEM_freeN(fly->obtfm); - if(fly->ndof) + if (fly->ndof) MEM_freeN(fly->ndof); - if(fly->state == FLY_CONFIRM) { + if (fly->state == FLY_CONFIRM) { MEM_freeN(fly); return OPERATOR_FINISHED; } @@ -451,37 +452,37 @@ static void flyEvent(FlyInfo *fly, wmEvent *event) // static const char* tag_name = "3D mouse position"; wmNDOFMotionData* incoming_ndof = (wmNDOFMotionData*) event->customdata; - switch (incoming_ndof->progress) - { + switch (incoming_ndof->progress) { case P_STARTING: // start keeping track of 3D mouse position - #ifdef NDOF_FLY_DEBUG +#ifdef NDOF_FLY_DEBUG puts("start keeping track of 3D mouse position"); - #endif +#endif // fall through... case P_IN_PROGRESS: // update 3D mouse position - #ifdef NDOF_FLY_DEBUG +#ifdef NDOF_FLY_DEBUG putchar('.'); fflush(stdout); - #endif - if (fly->ndof == NULL) +#endif + if (fly->ndof == NULL) { // fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); fly->ndof = MEM_dupallocN(incoming_ndof); // fly->ndof = malloc(sizeof(wmNDOFMotionData)); - else + } + else { memcpy(fly->ndof, incoming_ndof, sizeof(wmNDOFMotionData)); + } break; case P_FINISHING: // stop keeping track of 3D mouse position - #ifdef NDOF_FLY_DEBUG +#ifdef NDOF_FLY_DEBUG puts("stop keeping track of 3D mouse position"); - #endif - if (fly->ndof) - { +#endif + if (fly->ndof) { MEM_freeN(fly->ndof); // free(fly->ndof); fly->ndof = NULL; - } + } /* update the time else the view will jump when 2D mouse/timer resume */ fly->time_lastdraw= PIL_check_seconds_timer(); break; @@ -511,7 +512,9 @@ static void flyEvent(FlyInfo *fly, wmEvent *event) /*Mouse wheel delays range from 0.5==slow to 0.01==fast*/ time_wheel = 1.0f + (10.0f - (20.0f * MIN2(time_wheel, 0.5f))); /* 0-0.5 -> 0-5.0 */ - if (fly->speed<0.0f) fly->speed= 0.0f; + if (fly->speed < 0.0f) { + fly->speed= 0.0f; + } else { if (event->shift) fly->speed += fly->grid*time_wheel * 0.1f; @@ -530,7 +533,9 @@ static void flyEvent(FlyInfo *fly, wmEvent *event) fly->time_lastwheel = time_currwheel; time_wheel = 1.0f + (10.0f - (20.0f * MIN2(time_wheel, 0.5f))); /* 0-0.5 -> 0-5.0 */ - if (fly->speed>0) fly->speed=0; + if (fly->speed > 0.0f) { + fly->speed=0; + } else { if (event->shift) fly->speed-= fly->grid*time_wheel * 0.1f; @@ -614,7 +619,7 @@ static void move_camera(bContext* C, RegionView3D* rv3d, FlyInfo* fly, int orien ID *id_key; /* transform the parent or the camera? */ - if(fly->root_parent) { + if (fly->root_parent) { Object *ob_update; float view_mat[4][4]; @@ -702,10 +707,10 @@ static int flyApply(bContext *C, FlyInfo *fly) unsigned char apply_rotation= 1; /* if the user presses shift they can look about without movinf the direction there looking*/ - #ifdef NDOF_FLY_DEBUG +#ifdef NDOF_FLY_DEBUG static unsigned int iteration = 1; printf("fly timer %d\n", iteration++); - #endif +#endif xmargin= ar->winx/20.0f; @@ -736,18 +741,18 @@ static int flyApply(bContext *C, FlyInfo *fly) * * the mouse moves isnt linear */ - if(moffset[0]) { + if (moffset[0]) { moffset[0] /= ar->winx - (xmargin*2); moffset[0] *= fabsf(moffset[0]); } - if(moffset[1]) { + if (moffset[1]) { moffset[1] /= ar->winy - (ymargin*2); moffset[1] *= fabsf(moffset[1]); } /* Should we redraw? */ - if(fly->speed != 0.0f || moffset[0] || moffset[1] || fly->zlock || fly->xlock || dvec[0] || dvec[1] || dvec[2] ) { + if (fly->speed != 0.0f || moffset[0] || moffset[1] || fly->zlock || fly->xlock || dvec[0] || dvec[1] || dvec[2] ) { float dvec_tmp[3]; double time_current; /*time how fast it takes for us to redraw, this is so simple scenes dont fly too fast */ float time_redraw; @@ -781,8 +786,8 @@ static int flyApply(bContext *C, FlyInfo *fly) mul_m3_v3(mat, dvec_tmp); mul_v3_fl(dvec_tmp, time_redraw * 200.0f * fly->grid); - - } else { + } + else { float roll; /* similar to the angle between the camera's up and the Z-up, but its very rough so just roll*/ /* rotate about the X axis- look up/down */ @@ -803,23 +808,24 @@ static int flyApply(bContext *C, FlyInfo *fly) if (moffset[0]) { /* if we're upside down invert the moffset */ - upvec[0]=0; - upvec[1]=1; - upvec[2]=0; + upvec[0]= 0.0f; + upvec[1]= 1.0f; + upvec[2]= 0.0f; mul_m3_v3(mat, upvec); - if(upvec[2] < 0.0f) + if (upvec[2] < 0.0f) moffset[0]= -moffset[0]; /* make the lock vectors */ if (fly->zlock) { - upvec[0]=0; - upvec[1]=0; - upvec[2]=1; - } else { - upvec[0]=0; - upvec[1]=1; - upvec[2]=0; + upvec[0]= 0.0f; + upvec[1]= 0.0f; + upvec[2]= 1.0f; + } + else { + upvec[0]= 0.0f; + upvec[1]= 1.0f; + upvec[2]= 0.0f; mul_m3_v3(mat, upvec); } @@ -831,25 +837,26 @@ static int flyApply(bContext *C, FlyInfo *fly) } if (fly->zlock==2) { - upvec[0]=1; - upvec[1]=0; - upvec[2]=0; + upvec[0]= 1.0f; + upvec[1]= 0.0f; + upvec[2]= 0.0f; mul_m3_v3(mat, upvec); /*make sure we have some z rolling*/ if (fabsf(upvec[2]) > 0.00001f) { - roll= upvec[2]*5; - upvec[0]=0; /*rotate the view about this axis*/ - upvec[1]=0; - upvec[2]=1; + roll= upvec[2] * 5.0f; + upvec[0]= 0.0f; /*rotate the view about this axis*/ + upvec[1]= 0.0f; + upvec[2]= 1.0f; mul_m3_v3(mat, upvec); axis_angle_to_quat( tmp_quat, upvec, roll*time_redraw_clamped*fly->zlock_momentum * FLY_ZUP_CORRECT_FAC); /* Rotate about the relative up vec */ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); fly->zlock_momentum += FLY_ZUP_CORRECT_ACCEL; - } else { - fly->zlock=1; /* dont check until the view rotates again */ + } + else { + fly->zlock= 1; /* dont check until the view rotates again */ fly->zlock_momentum= 0.0f; } } @@ -860,8 +867,8 @@ static int flyApply(bContext *C, FlyInfo *fly) upvec[2]=1; mul_m3_v3(mat, upvec); /*make sure we have some z rolling*/ - if (fabs(upvec[2]) > 0.00001) { - roll= upvec[2] * -5; + if (fabs(upvec[2]) > 0.00001f) { + roll= upvec[2] * -5.0f; upvec[0]= 1.0f; /*rotate the view about this axis*/ upvec[1]= 0.0f; @@ -873,7 +880,8 @@ static int flyApply(bContext *C, FlyInfo *fly) mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); fly->xlock_momentum += 0.05f; - } else { + } + else { fly->xlock=1; /* see above */ fly->xlock_momentum= 0.0f; } @@ -920,9 +928,11 @@ static int flyApply(bContext *C, FlyInfo *fly) if (rv3d->persp==RV3D_CAMOB) move_camera(C, rv3d, fly, (fly->xlock || fly->zlock || moffset[0] || moffset[1]), fly->speed); - } else - /*were not redrawing but we need to update the time else the view will jump */ + } + else { + /* we're not redrawing but we need to update the time else the view will jump */ fly->time_lastdraw= PIL_check_seconds_timer(); + } /* end drawing */ copy_v3_v3(fly->dvec_prev, dvec); } @@ -932,14 +942,14 @@ static int flyApply(bContext *C, FlyInfo *fly) static int flyApply_ndof(bContext *C, FlyInfo *fly) { - // shorthand for oft-used variables + /* shorthand for oft-used variables */ wmNDOFMotionData* ndof = fly->ndof; const float dt = ndof->dt; RegionView3D* rv3d = fly->rv3d; const int flag = U.ndof_flag; -// int shouldRotate = (flag & NDOF_SHOULD_ROTATE) && (fly->pan_view == FALSE), -// shouldTranslate = (flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM)); +/* int shouldRotate = (flag & NDOF_SHOULD_ROTATE) && (fly->pan_view == FALSE), + shouldTranslate = (flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM)); */ int shouldRotate = (fly->pan_view == FALSE), shouldTranslate = TRUE; @@ -949,14 +959,13 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) rv3d->rot_angle = 0.f; // disable onscreen rotation doo-dad - if (shouldTranslate) - { + if (shouldTranslate) { const float forward_sensitivity = 1.f; const float vertical_sensitivity = 0.4f; const float lateral_sensitivity = 0.6f; - float speed = 10.f; // blender units per second - // ^^ this is ok for default cube scene, but should scale with.. something + float speed = 10.f; /* blender units per second */ + /* ^^ this is ok for default cube scene, but should scale with.. something */ float trans[3] = { lateral_sensitivity * ndof->tvec[0], @@ -972,11 +981,10 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) // transform motion from view to world coordinates mul_qt_v3(view_inv, trans); - if (flag & NDOF_FLY_HELICOPTER) - { - // replace world z component with device y (yes it makes sense) + if (flag & NDOF_FLY_HELICOPTER) { + /* replace world z component with device y (yes it makes sense) */ trans[2] = speed * dt * vertical_sensitivity * ndof->tvec[1]; - } + } if (rv3d->persp==RV3D_CAMOB) { // respect camera position locks @@ -986,79 +994,77 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) if (lock_ob->protectflag & OB_LOCK_LOCZ) trans[2] = 0.f; } - if (trans[0] || trans[1] || trans[2]) - { + if (!is_zero_v3(trans)) { // move center of view opposite of hand motion (this is camera mode, not object mode) sub_v3_v3(rv3d->ofs, trans); shouldTranslate = TRUE; - } - else + } + else { shouldTranslate = FALSE; } + } - if (shouldRotate) - { + if (shouldRotate) { const float turn_sensitivity = 1.f; float rotation[4]; float axis[3]; - float angle = turn_sensitivity * ndof_to_angle_axis(ndof, axis); + float angle = turn_sensitivity * ndof_to_axis_angle(ndof, axis); - if (fabsf(angle) > 0.0001f) - { + if (fabsf(angle) > 0.0001f) { shouldRotate = TRUE; if (fly->use_precision) angle *= 0.2f; - // transform rotation axis from view to world coordinates + /* transform rotation axis from view to world coordinates */ mul_qt_v3(view_inv, axis); // apply rotation to view axis_angle_to_quat(rotation, axis, angle); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); - if (flag & NDOF_LOCK_HORIZON) - // force an upright viewpoint - // TODO: make this less... sudden - { - float view_horizon[3] = {1.f, 0.f, 0.f}; // view +x - float view_direction[3] = {0.f, 0.f, -1.f}; // view -z (into screen) + if (flag & NDOF_LOCK_HORIZON) { + /* force an upright viewpoint + * TODO: make this less... sudden */ + float view_horizon[3] = {1.f, 0.f, 0.f}; /* view +x */ + float view_direction[3] = {0.f, 0.f, -1.f}; /* view -z (into screen) */ - // find new inverse since viewquat has changed + /* find new inverse since viewquat has changed */ invert_qt_qt(view_inv, rv3d->viewquat); - // could apply reverse rotation to existing view_inv to save a few cycles + /* could apply reverse rotation to existing view_inv to save a few cycles */ - // transform view vectors to world coordinates + /* transform view vectors to world coordinates */ mul_qt_v3(view_inv, view_horizon); mul_qt_v3(view_inv, view_direction); - // find difference between view & world horizons - // true horizon lives in world xy plane, so look only at difference in z + /* find difference between view & world horizons + * true horizon lives in world xy plane, so look only at difference in z */ angle = -asinf(view_horizon[2]); - #ifdef NDOF_FLY_DEBUG +#ifdef NDOF_FLY_DEBUG printf("lock horizon: adjusting %.1f degrees\n\n", RAD2DEG(angle)); - #endif +#endif - // rotate view so view horizon = world horizon + /* rotate view so view horizon = world horizon */ axis_angle_to_quat(rotation, view_direction, angle); mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); - } + } rv3d->view = RV3D_VIEW_USER; - } - else + } + else { shouldRotate = FALSE; } + } - if (shouldTranslate || shouldRotate) - { + if (shouldTranslate || shouldRotate) { fly->redraw = TRUE; - if (rv3d->persp==RV3D_CAMOB) + if (rv3d->persp==RV3D_CAMOB) { move_camera(C, rv3d, fly, shouldRotate, shouldTranslate); } + } return OPERATOR_FINISHED; } @@ -1069,14 +1075,14 @@ static int fly_invoke(bContext *C, wmOperator *op, wmEvent *event) RegionView3D *rv3d= CTX_wm_region_view3d(C); FlyInfo *fly; - if(rv3d->viewlock) + if (rv3d->viewlock) return OPERATOR_CANCELLED; fly= MEM_callocN(sizeof(FlyInfo), "FlyOperation"); op->customdata= fly; - if(initFlyInfo(C, fly, op, event)==FALSE) { + if (initFlyInfo(C, fly, op, event)==FALSE) { MEM_freeN(op->customdata); return OPERATOR_CANCELLED; } @@ -1111,23 +1117,24 @@ static int fly_modal(bContext *C, wmOperator *op, wmEvent *event) flyEvent(fly, event); - if (fly->ndof) // 3D mouse overrules [2D mouse + timer] - { - if (event->type==NDOF_MOTION) + if (fly->ndof) { /* 3D mouse overrules [2D mouse + timer] */ + if (event->type==NDOF_MOTION) { flyApply_ndof(C, fly); } - else if (event->type==TIMER && event->customdata == fly->timer) + } + else if (event->type==TIMER && event->customdata == fly->timer) { flyApply(C, fly); + } do_draw |= fly->redraw; exit_code = flyEnd(C, fly); - if(exit_code!=OPERATOR_RUNNING_MODAL) + if (exit_code!=OPERATOR_RUNNING_MODAL) do_draw= TRUE; - if(do_draw) { - if(rv3d->persp==RV3D_CAMOB) { + if (do_draw) { + if (rv3d->persp==RV3D_CAMOB) { WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, fly_object); } diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index c4207b0ce25..ab3ce37ff15 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -95,7 +95,7 @@ void VIEW3D_OT_drawtype(struct wmOperatorType *ot); void view3d_boxview_copy(ScrArea *sa, ARegion *ar); void ndof_to_quat(struct wmNDOFMotionData* ndof, float q[4]); -float ndof_to_angle_axis(struct wmNDOFMotionData* ndof, float axis[3]); +float ndof_to_axis_angle(struct wmNDOFMotionData* ndof, float axis[3]); /* view3d_fly.c */ void view3d_keymap(struct wmKeyConfig *keyconf); -- cgit v1.2.3 From 9e0113890eae1876f05904848f88cd14a8fd9686 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 2 Aug 2011 09:06:55 +0000 Subject: 3D Mouse support on for windows/msvc by default. --- build_files/scons/config/win32-vc-config.py | 2 ++ build_files/scons/config/win64-vc-config.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/build_files/scons/config/win32-vc-config.py b/build_files/scons/config/win32-vc-config.py index 89b246cb39f..5a91852052d 100644 --- a/build_files/scons/config/win32-vc-config.py +++ b/build_files/scons/config/win32-vc-config.py @@ -149,6 +149,8 @@ BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include' BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser MathMLSolver xml2 pcre buffer ftoa UTF' BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib' +WITH_BF_3DMOUSE = True + #Ray trace optimization WITH_BF_RAYOPTIMIZATION = True BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE'] diff --git a/build_files/scons/config/win64-vc-config.py b/build_files/scons/config/win64-vc-config.py index 67db1c441d7..6717f12fcf8 100644 --- a/build_files/scons/config/win64-vc-config.py +++ b/build_files/scons/config/win64-vc-config.py @@ -153,6 +153,8 @@ BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include' BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser MathMLSolver xml2 pcre buffer ftoa UTF' BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib' +WITH_BF_3DMOUSE = True + #Ray trace optimization WITH_BF_RAYOPTIMIZATION = True BF_RAYOPTIMIZATION_SSE_FLAGS = ['/arch:SSE','/arch:SSE2'] -- cgit v1.2.3 From 28ed1b6745eae712a097442f40949d7ff0e879e3 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 2 Aug 2011 09:07:24 +0000 Subject: tabs -> spaces --- intern/ghost/SConscript | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript index d65eb0caab6..1ed8ea9706e 100644 --- a/intern/ghost/SConscript +++ b/intern/ghost/SConscript @@ -76,10 +76,11 @@ else: if env['BF_GHOST_DEBUG']: defs.append('WITH_GHOST_DEBUG') else: - sources.remove('intern' + os.sep + 'GHOST_EventPrinter.cpp') + sources.remove('intern' + os.sep + 'GHOST_EventPrinter.cpp') if env['WITH_BF_3DMOUSE']: - defs.append('WITH_INPUT_NDOF') + defs.append('WITH_INPUT_NDOF') + if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'): incs = env['BF_WINTAB_INC'] + ' ' + incs -- cgit v1.2.3 From 1828e37794b33b3fd8bfabd00ffcbfe4fb774377 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 2 Aug 2011 09:09:07 +0000 Subject: Turn off ndof button debug --- intern/ghost/intern/GHOST_NDOFManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.h b/intern/ghost/intern/GHOST_NDOFManager.h index 859cb64b859..5bdbe7a6833 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.h +++ b/intern/ghost/intern/GHOST_NDOFManager.h @@ -30,7 +30,7 @@ // #define DEBUG_NDOF_MOTION -#define DEBUG_NDOF_BUTTONS +// #define DEBUG_NDOF_BUTTONS typedef enum { NDOF_UnknownDevice, // <-- motion will work fine, buttons are ignored -- cgit v1.2.3 From f1c68bdbec98edfd212e80aa7a80fe1f93c4a100 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 2 Aug 2011 09:12:58 +0000 Subject: Don't show NDOF guide by default. --- source/blender/editors/interface/resources.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 16f3789ecb1..0c755180b3a 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1587,7 +1587,7 @@ void init_userdef_do_versions(void) if (U.ndof_sensitivity == 0.0f) { U.ndof_sensitivity = 1.0f; - U.ndof_flag = NDOF_SHOW_GUIDE | NDOF_LOCK_HORIZON | + U.ndof_flag = NDOF_LOCK_HORIZON | NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM | NDOF_SHOULD_ROTATE; } -- cgit v1.2.3 From 73fc78c5d81920fc4b3dbcb8fcf4fdc6ab6dd3d6 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 2 Aug 2011 09:18:21 +0000 Subject: Debug print removed. --- source/blender/windowmanager/intern/wm_operators.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 7dc4bfb65a6..a47dfacf358 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3428,26 +3428,20 @@ static int wm_ndof_sensitivity_exec(bContext *UNUSED(C), wmOperator *op) else change = 0.1f; // 10% - if(RNA_boolean_get(op->ptr, "decrease")) - { + if(RNA_boolean_get(op->ptr, "decrease")) { sensitivity -= sensitivity * change; if (sensitivity < min) sensitivity = min; - } - else - { + } + else { sensitivity += sensitivity * change; if (sensitivity > max) sensitivity = max; - } + } - if (sensitivity != U.ndof_sensitivity) - { + if (sensitivity != U.ndof_sensitivity) { U.ndof_sensitivity = sensitivity; - printf("new sensitivity: %f\n", U.ndof_sensitivity); - } - else - printf("same sensitivity: %f\n", U.ndof_sensitivity); + } return OPERATOR_FINISHED; } -- cgit v1.2.3 From c1cf646bb7deed6e318701597f605e12851cc534 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 2 Aug 2011 09:36:44 +0000 Subject: whitespace --- intern/ghost/intern/GHOST_System.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index f62c0984c80..9fb36292c2b 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -318,8 +318,8 @@ protected: /** The event manager. */ GHOST_EventManager* m_eventManager; - /** The N-degree of freedom device manager */ - GHOST_NDOFManager* m_ndofManager; + /** The N-degree of freedom device manager */ + GHOST_NDOFManager* m_ndofManager; /** Prints all the events. */ #ifdef GHOST_DEBUG -- cgit v1.2.3 From 69b4962fc06726aa3ea31b70554fa2cb1f04d2aa Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 2 Aug 2011 10:20:47 +0000 Subject: Properly disable NDOF code when WITH_INPUT_NDOF is not define. --- intern/ghost/intern/GHOST_System.cpp | 4 ++++ intern/ghost/intern/GHOST_System.h | 6 ++++++ intern/ghost/intern/GHOST_SystemCocoa.mm | 2 ++ intern/ghost/intern/GHOST_SystemWin32.cpp | 8 +++++++- 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index f601031f2b6..64c2c218a07 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -202,10 +202,12 @@ bool GHOST_System::dispatchEvents() { bool handled = false; +#ifdef WITH_INPUT_NDOF // NDOF Motion event is sent only once per dispatch, so do it now: if (m_ndofManager) { handled |= m_ndofManager->sendMotionEvent(); } +#endif if (m_eventManager) { handled |= m_eventManager->dispatchEvents(); @@ -319,10 +321,12 @@ GHOST_TSuccess GHOST_System::exit() delete m_eventManager; m_eventManager = 0; } +#ifdef WITH_INPUT_NDOF if (m_ndofManager) { delete m_ndofManager; m_ndofManager = 0; } +#endif return GHOST_kSuccess; } diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index 9fb36292c2b..c1e70916be6 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -249,11 +249,13 @@ public: */ virtual inline GHOST_WindowManager* getWindowManager() const; +#ifdef WITH_INPUT_NDOF /** * Returns a pointer to our n-degree of freedeom manager. * @return A pointer to our n-degree of freedeom manager. */ virtual inline GHOST_NDOFManager* getNDOFManager() const; +#endif /** * Returns the state of all modifier keys. @@ -318,8 +320,10 @@ protected: /** The event manager. */ GHOST_EventManager* m_eventManager; +#ifdef WITH_INPUT_NDOF /** The N-degree of freedom device manager */ GHOST_NDOFManager* m_ndofManager; +#endif /** Prints all the events. */ #ifdef GHOST_DEBUG @@ -345,10 +349,12 @@ inline GHOST_WindowManager* GHOST_System::getWindowManager() const return m_windowManager; } +#ifdef WITH_INPUT_NDOF inline GHOST_NDOFManager* GHOST_System::getNDOFManager() const { return m_ndofManager; } +#endif #endif // _GHOST_SYSTEM_H_ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 8f2df4c396d..17f0f2d6ecd 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -597,7 +597,9 @@ GHOST_TSuccess GHOST_SystemCocoa::init() GHOST_TSuccess success = GHOST_System::init(); if (success) { +#ifdef WITH_INPUT_NDOF m_ndofManager = new GHOST_NDOFManagerCocoa(*this); +#endif //ProcessSerialNumber psn; diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 1b43fa92bb2..4af5643eb75 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -161,7 +161,9 @@ GHOST_SystemWin32::GHOST_SystemWin32() // Require COM for GHOST_DropTargetWin32 created in GHOST_WindowWin32. OleInitialize(0); +#ifdef WITH_INPUT_NDOF m_ndofManager = new GHOST_NDOFManagerWin32(*this); +#endif } GHOST_SystemWin32::~GHOST_SystemWin32() @@ -757,6 +759,7 @@ void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO * minmax) minmax->ptMinTrackSize.y=240; } +#ifdef WITH_INPUT_NDOF bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) { bool eventSent = false; @@ -773,7 +776,7 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) if (info.dwType == RIM_TYPEHID) m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId); else - puts(" not a HID device... mouse/kb perhaps?"); + puts(" not a HID device... mouse/kb perhaps?"); firstEvent = false; } @@ -846,6 +849,7 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) } return eventSent; } +#endif // WITH_INPUT_NDOF LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -892,8 +896,10 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, } break; case RIM_TYPEHID: +#ifdef WITH_INPUT_NDOF if (system->processNDOF(raw)) eventHandled = true; +#endif break; } break; -- cgit v1.2.3 From 08426ec2e73164e709f2b020042f26af7b0ad5c5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 2 Aug 2011 10:21:25 +0000 Subject: fix [#28148] User Preferences Scripts Path not working --- release/scripts/startup/bl_ui/space_userpref.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 933579f5c1e..1feb1eec0c5 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -878,7 +878,7 @@ class USERPREF_PT_addons(bpy.types.Panel): if not user_addon_paths: user_script_path = bpy.utils.user_script_path() if user_script_path is not None: - user_addon_paths.append(os.path.join(user_script_path(), "addons")) + user_addon_paths.append(os.path.join(user_script_path, "addons")) user_addon_paths.append(os.path.join(bpy.utils.resource_path('USER'), "scripts", "addons")) for path in user_addon_paths: -- cgit v1.2.3 From 6bc101fa7e9a51bdcd27a0bcf6d7d26fbe733c5b Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 2 Aug 2011 10:26:20 +0000 Subject: Indentation changes --- intern/ghost/intern/GHOST_SystemWin32.cpp | 39 +++++++++++++++---------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 4af5643eb75..c985c6dd0a6 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -766,8 +766,7 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) GHOST_TUns64 now = getMilliSeconds(); static bool firstEvent = true; - if (firstEvent) - { // determine exactly which device is plugged in + if (firstEvent) { // determine exactly which device is plugged in RID_DEVICE_INFO info; unsigned infoSize = sizeof(RID_DEVICE_INFO); info.cbSize = infoSize; @@ -776,23 +775,23 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) if (info.dwType == RIM_TYPEHID) m_ndofManager->setDevice(info.hid.dwVendorId, info.hid.dwProductId); else - puts(" not a HID device... mouse/kb perhaps?"); + puts(" not a HID device... mouse/kb perhaps?"); firstEvent = false; - } + } // The NDOF manager sends button changes immediately, and *pretends* to // send motion. Mark as 'sent' so motion will always get dispatched. eventSent = true; #ifdef _MSC_VER - // using Microsoft compiler & header files - // they invented the RawInput API, so this version is (probably) correct + // using Microsoft compiler & header files + // they invented the RawInput API, so this version is (probably) correct BYTE const* data = raw.data.hid.bRawData; // struct RAWHID { - // DWORD dwSizeHid; - // DWORD dwCount; - // BYTE bRawData[1]; + // DWORD dwSizeHid; + // DWORD dwCount; + // BYTE bRawData[1]; // }; #else // MinGW's definition (below) doesn't agree, so we need a slight @@ -807,46 +806,46 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) BYTE packetType = data[0]; switch (packetType) - { + { case 1: // translation - { + { short* axis = (short*)(data + 1); short t[3] = {axis[0], -axis[2], axis[1]}; m_ndofManager->updateTranslation(t, now); if (raw.data.hid.dwSizeHid == 13) - { // this report also includes rotation + { // this report also includes rotation short r[3] = {-axis[3], axis[5], -axis[4]}; m_ndofManager->updateRotation(r, now); // I've never gotten one of these, has anyone else? puts("ndof: combined T + R"); - } - break; } + break; + } case 2: // rotation - { + { short* axis = (short*)(data + 1); short r[3] = {-axis[0], axis[2], -axis[1]}; m_ndofManager->updateRotation(r, now); break; - } + } case 3: // buttons - { - #if 0 + { +#if 0 // I'm getting garbage bits -- examine whole report: printf("ndof: HID report for buttons ["); for (int i = 0; i < raw.data.hid.dwSizeHid; ++i) printf(" %02X", data[i]); printf(" ]\n"); - #endif +#endif int button_bits; memcpy(&button_bits, data + 1, sizeof(button_bits)); m_ndofManager->updateButtons(button_bits, now); break; - } } + } return eventSent; } #endif // WITH_INPUT_NDOF -- cgit v1.2.3 From 467475590e5c6595fefccd77e028ca611c15863f Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 2 Aug 2011 10:39:46 +0000 Subject: Some more silencing. Enable with BF_GHOST_DEBUG --- intern/ghost/intern/GHOST_NDOFManager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 72b0dba297a..5a0f14c85a3 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -23,6 +23,7 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "GHOST_Debug.h" #include "GHOST_NDOFManager.h" #include "GHOST_EventNDOF.h" #include "GHOST_EventKey.h" @@ -186,9 +187,9 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) memset(m_rotation, 0, sizeof(m_rotation)); #ifdef WITH_INPUT_NDOF - puts("WITH_INPUT_NDOF is defined!"); + GHOST_PRINT("WITH_INPUT_NDOF is defined!"); #else - puts("WITH_INPUT_NDOF is not defined."); + GHOST_PRINT("WITH_INPUT_NDOF is not defined."); #endif } -- cgit v1.2.3 From 7561d10c2e6782965755a04b7b417be52cc16f25 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 2 Aug 2011 10:50:22 +0000 Subject: Don't include NDOF files when disabled. --- intern/ghost/SConscript | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript index 1ed8ea9706e..45a1f44d579 100644 --- a/intern/ghost/SConscript +++ b/intern/ghost/SConscript @@ -80,6 +80,17 @@ else: if env['WITH_BF_3DMOUSE']: defs.append('WITH_INPUT_NDOF') +else: + sources.remove('intern' + os.sep + 'GHOST_NDOFManager.cpp') + try: + if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'): + sources.remove('intern' + os.sep + 'GHOST_NDOFManagerWin32.cpp') + elif window_system=='darwin': + sources.remove('intern' + os.sep + 'GHOST_NDOFManagerCocoa.mm') + else: + sources.remove('intern' + os.sep + 'GHOST_NDOFManagerX11.mm') + except ValueError: + pass if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'): -- cgit v1.2.3 From de0db6c8daaf4f6276b43bd4c78d623fdb0eafb9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 2 Aug 2011 10:56:09 +0000 Subject: unit arg for FloatVectorProeprty --- source/blender/python/intern/bpy_props.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 0ba80bf0850..a0ad1ff7850 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -326,6 +326,11 @@ static int bpy_prop_callback_assign(struct PropertyRNA *prop, PyObject *update_c " :type description: string\n" \ +#define BPY_PROPDEF_UNIT_DOC \ +" :arg unit: Enumerator in ['NONE', 'LENGTH', 'AREA', 'VOLUME', 'ROTATION', 'TIME', 'VELOCITY', 'ACCELERATION'].\n" \ +" :type unit: string\n" \ + + #define BPY_PROPDEF_UPDATE_DOC \ " :arg update: function to be called when this value is modified,\n" \ " This function must take 2 values (self, context) and return None.\n" \ @@ -639,8 +644,7 @@ BPY_PROPDEF_DESC_DOC " :type options: set\n" " :arg subtype: Enumerator in ['UNSIGNED', 'PERCENTAGE', 'FACTOR', 'ANGLE', 'TIME', 'DISTANCE', 'NONE'].\n" " :type subtype: string\n" -" :arg unit: Enumerator in ['NONE', 'LENGTH', 'AREA', 'VOLUME', 'ROTATION', 'TIME', 'VELOCITY', 'ACCELERATION'].\n" -" :type unit: string\n" +BPY_PROPDEF_UNIT_DOC BPY_PROPDEF_UPDATE_DOC ); static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) @@ -679,7 +683,7 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) BPY_PROPDEF_SUBTYPE_CHECK(FloatProperty, property_flag_items, property_subtype_number_items) if(pyunit && RNA_enum_value_from_id(property_unit_items, pyunit, &unit)==0) { - PyErr_Format(PyExc_TypeError, "FloatProperty(unit='%s'): invalid unit"); + PyErr_Format(PyExc_TypeError, "FloatProperty(unit='%s'): invalid unit", pyunit); return NULL; } @@ -716,6 +720,7 @@ BPY_PROPDEF_DESC_DOC " :type options: set\n" " :arg subtype: Enumerator in ['COLOR', 'TRANSLATION', 'DIRECTION', 'VELOCITY', 'ACCELERATION', 'MATRIX', 'EULER', 'QUATERNION', 'AXISANGLE', 'XYZ', 'COLOR_GAMMA', 'LAYER', 'NONE'].\n" " :type subtype: string\n" +BPY_PROPDEF_UNIT_DOC " :arg size: Vector dimensions in [1, and " STRINGIFY(PYRNA_STACK_ARRAY) "].\n" " :type size: int\n" BPY_PROPDEF_UPDATE_DOC @@ -727,7 +732,7 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec BPY_PROPDEF_HEAD(FloatVectorProperty) if(srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "size", "update", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "unit", "size", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, step=3, def[PYRNA_STACK_ARRAY]={0.0f}; @@ -738,15 +743,17 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec int opts=0; char *pysubtype= NULL; int subtype= PROP_NONE; + char *pyunit= NULL; + int unit= PROP_UNIT_NONE; PyObject *update_cb= NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, - "s#|ssOfffffiO!siO:FloatVectorProperty", + "s#|ssOfffffiO!ssiO:FloatVectorProperty", (char **)kwlist, &id, &id_len, &name, &description, &pydef, &min, &max, &soft_min, &soft_max, &step, &precision, &PySet_Type, - &pyopts, &pysubtype, &size, + &pyopts, &pysubtype, &pyunit, &size, &update_cb)) { return NULL; @@ -754,6 +761,11 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec BPY_PROPDEF_SUBTYPE_CHECK(FloatVectorProperty, property_flag_items, property_subtype_array_items) + if(pyunit && RNA_enum_value_from_id(property_unit_items, pyunit, &unit)==0) { + PyErr_Format(PyExc_TypeError, "FloatVectorProperty(unit='%s'): invalid unit", pyunit); + return NULL; + } + if(size < 1 || size > PYRNA_STACK_ARRAY) { PyErr_Format(PyExc_TypeError, "FloatVectorProperty(size=%d): size must be between 0 and " STRINGIFY(PYRNA_STACK_ARRAY), size); return NULL; @@ -766,7 +778,7 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec return NULL; } - prop= RNA_def_property(srna, id, PROP_FLOAT, subtype); + prop= RNA_def_property(srna, id, PROP_FLOAT, subtype | unit); RNA_def_property_array(prop, size); if(pydef) RNA_def_property_float_array_default(prop, def); RNA_def_property_range(prop, min, max); -- cgit v1.2.3 From 222190c618b74e0d2a9a2f5f8aded6544b6bef0b Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 2 Aug 2011 14:45:35 +0000 Subject: typo fix --- intern/ghost/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript index 45a1f44d579..761cbe56344 100644 --- a/intern/ghost/SConscript +++ b/intern/ghost/SConscript @@ -88,7 +88,7 @@ else: elif window_system=='darwin': sources.remove('intern' + os.sep + 'GHOST_NDOFManagerCocoa.mm') else: - sources.remove('intern' + os.sep + 'GHOST_NDOFManagerX11.mm') + sources.remove('intern' + os.sep + 'GHOST_NDOFManagerX11.cpp') except ValueError: pass -- cgit v1.2.3 From 9026dc6ee4b16f9a9db73eee09f2f397012268d2 Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Tue, 2 Aug 2011 17:00:44 +0000 Subject: Fixed a few small typos. Kent --- release/scripts/modules/bpy/path.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py index a01745fec0a..284fef97795 100644 --- a/release/scripts/modules/bpy/path.py +++ b/release/scripts/modules/bpy/path.py @@ -136,7 +136,7 @@ def display_name(name): def display_name_from_filepath(name): """ - Returns the path stripped of directort and extension, + Returns the path stripped of directory and extension, ensured to be utf8 compatible. """ name = _os.path.splitext(basename(name))[0] @@ -204,7 +204,7 @@ def resolve_ncase(path): def ensure_ext(filepath, ext, case_sensitive=False): """ - Return the path with the extension added its its not alredy set. + Return the path with the extension added if it is not already set. :arg ext: The extension to check for. :type ext: string -- cgit v1.2.3 From b2959e55f543c5979e7f03f77aec6fe342c6559f Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Tue, 2 Aug 2011 17:35:07 +0000 Subject: Fixes an issue with OSX Lion Also cleaned up the python detection for OSX Kent --- CMakeLists.txt | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d95cbb6e536..2d104ebfcea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -910,28 +910,15 @@ elseif(APPLE) endif() if(WITH_PYTHON) - set(PYTHON_VERSION 3.2) - if(PYTHON_VERSION MATCHES 3.2) - # we use precompiled libraries for py 3.2 and up by default + # we use precompiled libraries for py 3.2 and up by default - # normally cached but not since we include them with blender - set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}") - # set(PYTHON_BINARY "${LIBDIR}/python/bin/python${PYTHON_VERSION}") # not used yet - set(PYTHON_LIBRARY python${PYTHON_VERSION}) - set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}") - # set(PYTHON_LINKFLAGS "-u _PyMac_Error") # won't build with this enabled - else() - # otherwise, use custom system framework - # *not used but maintained incase some dev wants to* - - set(PYTHON "/System/Library/Frameworks/Python.framework/Versions/" CACHE PATH) - set(PYTHON_INCLUDE_DIR "${PYTHON}${PYTHON_VERSION}/include/python${PYTHON_VERSION}" CACHE PATH) - # set(PYTHON_BINARY ${PYTHON}${PYTHON_VERSION}/bin/python${PYTHON_VERSION}) # not used yet - set(PYTHON_LIBRARY "" CACHE FILEPATH) - set(PYTHON_LIBPATH "${PYTHON}${PYTHON_VERSION}/lib/python${PYTHON_VERSION}/config" CACHE PATH) - set(PYTHON_LINKFLAGS "-u _PyMac_Error -framework System -framework Python" CACHE STRING) - unset(PYTHON) - endif() + # normally cached but not since we include them with blender + set(PYTHON_VERSION 3.2) + set(PYTHON_INCLUDE_DIR "${LIBDIR}/python/include/python${PYTHON_VERSION}") + # set(PYTHON_BINARY "${LIBDIR}/python/bin/python${PYTHON_VERSION}") # not used yet + set(PYTHON_LIBRARY python${PYTHON_VERSION}) + set(PYTHON_LIBPATH "${LIBDIR}/python/lib/python${PYTHON_VERSION}") + # set(PYTHON_LINKFLAGS "-u _PyMac_Error") # won't build with this enabled # uncached vars set(PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIR}") @@ -986,7 +973,17 @@ elseif(APPLE) set(SAMPLERATE_LIBPATH ${SAMPLERATE}/lib) endif() - set(PLATFORM_LINKLIBS stdc++ SystemStubs) + find_library(SYSTEMSTUBS_LIBRARY + NAMES + SystemStubs + PATHS + ) + mark_as_advanced(SYSTEMSTUBS_LIBRARY) + if(SYSTEMSTUBS_LIBRARY) + set(PLATFORM_LINKLIBS stdc++ SystemStubs) + else() + set(PLATFORM_LINKLIBS stdc++) + endif() if(WITH_COCOA) set(PLATFORM_CFLAGS "-pipe -funsigned-char -DGHOST_COCOA") -- cgit v1.2.3 From 6a37c2411512569a93017b1b200971935c919491 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 2 Aug 2011 17:40:27 +0000 Subject: fix for xvid encoding preset giving a python error --- release/scripts/presets/ffmpeg/xvid.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/release/scripts/presets/ffmpeg/xvid.py b/release/scripts/presets/ffmpeg/xvid.py index fa64562e566..c006ba267cc 100644 --- a/release/scripts/presets/ffmpeg/xvid.py +++ b/release/scripts/presets/ffmpeg/xvid.py @@ -1,8 +1,7 @@ import bpy is_ntsc = (bpy.context.scene.render.fps != 25) -bpy.context.scene.render.ffmpeg_format = "AVI" -bpy.context.scene.render.ffmpeg_codec = "XVID" +bpy.context.scene.render.ffmpeg_format = "XVID" if is_ntsc: bpy.context.scene.render.ffmpeg_gopsize = 18 -- cgit v1.2.3 From 13eefec9ddcc5f5dc7a7328ed5f24c1dd4a000fd Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 2 Aug 2011 17:59:43 +0000 Subject: More flexible configuration for 3dmouse library for scons. Needed for release environment and buildbot. Buildbot rules would be updated with next commit after environment will be tested. --- build_files/scons/config/linux2-config.py | 6 ++++-- build_files/scons/tools/Blender.py | 11 +++++++++++ build_files/scons/tools/btools.py | 6 ++++++ intern/ghost/SConscript | 3 +++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/build_files/scons/config/linux2-config.py b/build_files/scons/config/linux2-config.py index 6fb9090b022..d8e227cfb21 100644 --- a/build_files/scons/config/linux2-config.py +++ b/build_files/scons/config/linux2-config.py @@ -194,7 +194,11 @@ BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-pthread'] #SpaceNavigator and friends WITH_BF_3DMOUSE = True +BF_3DMOUSE = '/usr' +BF_3DMOUSE_INC = '${BF_3DMOUSE}/include' +BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib' BF_3DMOUSE_LIB = 'spnav' +BF_3DMOUSE_LIB_STATIC = '${BF_3DMOUSE_LIBPATH}/libspnav.a' ## CC = 'gcc' @@ -227,8 +231,6 @@ CXX_WARN = ['-Wno-invalid-offsetof', '-Wno-sign-compare'] ##FIX_STUBS_WARNINGS = -Wno-unused LLIBS = ['util', 'c', 'm', 'dl', 'pthread', 'stdc++'] -if WITH_BF_3DMOUSE: - LLIBS = LLIBS + [BF_3DMOUSE_LIB]; ##LOPTS = --dynamic ##DYNLDFLAGS = -shared $(LDFLAGS) diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py index 75af7e47edd..6fae2785192 100644 --- a/build_files/scons/tools/Blender.py +++ b/build_files/scons/tools/Blender.py @@ -206,6 +206,12 @@ def setup_staticlibs(lenv): if lenv['WITH_BF_STATICJEMALLOC']: statlibs += Split(lenv['BF_JEMALLOC_LIB_STATIC']) + if lenv['OURPLATFORM']=='linux2': + if lenv['WITH_BF_3DMOUSE']: + libincs += Split(lenv['BF_3DMOUSE_LIBPATH']) + if lenv['WITH_BF_STATIC3DMOUSE']: + statlibs += Split(lenv['BF_3DMOUSE_LIB_STATIC']) + return statlibs, libincs def setup_syslibs(lenv): @@ -271,6 +277,11 @@ def setup_syslibs(lenv): if not lenv['WITH_BF_STATICJEMALLOC']: syslibs += Split(lenv['BF_JEMALLOC_LIB']) + if lenv['OURPLATFORM']=='linux2': + if lenv['WITH_BF_3DMOUSE']: + if not lenv['WITH_BF_STATIC3DMOUSE']: + syslibs += Split(lenv['BF_3DMOUSE_LIB']) + syslibs += lenv['LLIBS'] return syslibs diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index a96bf8ce4cc..b20f3ede68d 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -438,6 +438,12 @@ def read_opts(env, cfg, args): (BoolVariable('WITH_BF_NOBLENDER', 'Do not build blender if true', False)), (BoolVariable('WITH_BF_3DMOUSE', 'Build blender with support of 3D mouses', False)), + (BoolVariable('WITH_BF_STATIC3DMOUSE', 'Staticly link to 3d mouse library', False)), + ('BF_3DMOUSE', '3d mouse library base path', ''), + ('BF_3DMOUSE_INC', '3d mouse library include path', ''), + ('BF_3DMOUSE_LIB', '3d mouse library', ''), + ('BF_3DMOUSE_LIBPATH', '3d mouse library path', ''), + ('BF_3DMOUSE_LIB_STATIC', '3d mouse static library', ''), ('CFLAGS', 'C only flags', []), ('CCFLAGS', 'Generic C and C++ flags', []), diff --git a/intern/ghost/SConscript b/intern/ghost/SConscript index 761cbe56344..234fc0a172e 100644 --- a/intern/ghost/SConscript +++ b/intern/ghost/SConscript @@ -80,6 +80,9 @@ else: if env['WITH_BF_3DMOUSE']: defs.append('WITH_INPUT_NDOF') + + if env['OURPLATFORM']=='linux2': + incs += ' ' + env['BF_3DMOUSE_INC'] else: sources.remove('intern' + os.sep + 'GHOST_NDOFManager.cpp') try: -- cgit v1.2.3 From a9b093d9eb378016c3ca0300104bdf2263cfa0b6 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Tue, 2 Aug 2011 18:16:48 +0000 Subject: Changes for buildbot rules to use propper spnav library path. --- build_files/buildbot/config/user-config-i686.py | 6 ++++++ build_files/buildbot/config/user-config-player-i686.py | 6 ++++++ build_files/buildbot/config/user-config-player-x86_64.py | 6 ++++++ build_files/buildbot/config/user-config-x86_64.py | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/build_files/buildbot/config/user-config-i686.py b/build_files/buildbot/config/user-config-i686.py index 1ad6c5d22fe..07dc4a9d831 100644 --- a/build_files/buildbot/config/user-config-i686.py +++ b/build_files/buildbot/config/user-config-i686.py @@ -81,6 +81,12 @@ WITH_BF_STATICJEMALLOC = True BF_JEMALLOC = '/home/sources/staticlibs/jemalloc' BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib32' +# Use 3d mouse library +WITH_BF_3DMOUSE = True +WITH_BF_STATIC3DMOUSE = True +BF_3DMOUSE = '/home/sources/staticlibs/spnav' +BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib32' + # Compilation and optimization BF_DEBUG = False REL_CFLAGS = ['-O2'] diff --git a/build_files/buildbot/config/user-config-player-i686.py b/build_files/buildbot/config/user-config-player-i686.py index 241f5a79983..ab31c6ce8a7 100644 --- a/build_files/buildbot/config/user-config-player-i686.py +++ b/build_files/buildbot/config/user-config-player-i686.py @@ -65,6 +65,12 @@ WITH_BF_STATICJEMALLOC = True BF_JEMALLOC = '/home/sources/staticlibs/jemalloc' BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib32' +# Use 3d mouse library +WITH_BF_3DMOUSE = True +WITH_BF_STATIC3DMOUSE = True +BF_3DMOUSE = '/home/sources/staticlibs/spnav' +BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib32' + # Compilation and optimization BF_DEBUG = False REL_CFLAGS = ['-O2'] diff --git a/build_files/buildbot/config/user-config-player-x86_64.py b/build_files/buildbot/config/user-config-player-x86_64.py index d51894b26cf..601b2c3ca1a 100644 --- a/build_files/buildbot/config/user-config-player-x86_64.py +++ b/build_files/buildbot/config/user-config-player-x86_64.py @@ -65,6 +65,12 @@ WITH_BF_STATICJEMALLOC = True BF_JEMALLOC = '/home/sources/staticlibs/jemalloc' BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib64' +# Use 3d mouse library +WITH_BF_3DMOUSE = True +WITH_BF_STATIC3DMOUSE = True +BF_3DMOUSE = '/home/sources/staticlibs/spnav' +BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib64' + # Compilation and optimization BF_DEBUG = False REL_CFLAGS = ['-O2'] diff --git a/build_files/buildbot/config/user-config-x86_64.py b/build_files/buildbot/config/user-config-x86_64.py index 3eaadd99d45..9c569ff4458 100644 --- a/build_files/buildbot/config/user-config-x86_64.py +++ b/build_files/buildbot/config/user-config-x86_64.py @@ -81,6 +81,12 @@ WITH_BF_STATICJEMALLOC = True BF_JEMALLOC = '/home/sources/staticlibs/jemalloc' BF_JEMALLOC_LIBPATH = '${BF_JEMALLOC}/lib64' +# Use 3d mouse library +WITH_BF_3DMOUSE = True +WITH_BF_STATIC3DMOUSE = True +BF_3DMOUSE = '/home/sources/staticlibs/spnav' +BF_3DMOUSE_LIBPATH = '${BF_3DMOUSE}/lib64' + # Compilation and optimization BF_DEBUG = False REL_CFLAGS = ['-O2'] -- cgit v1.2.3 From 5c36b753242be5830764ee41e2f6db4ae776f30a Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 2 Aug 2011 18:33:39 +0000 Subject: Simple argument to be able to explicitely tell the bitness you want to build Blender in. python scons\scons.py BF_BITNESS=32 python scons\scons.py BF_BITNESS=64 So from now on for Windows you don't have to run a specific win32 or win64 Python version to get the Blender version you want. If you omit the BF_BITNESS flag the bitness as per Python version will be used as before. Note that this is an argument, so works *only* on the command-line, not in your user-config.py --- SConstruct | 5 +++++ build_files/scons/tools/btools.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index e27f8eae367..dbeabb5c2ef 100644 --- a/SConstruct +++ b/SConstruct @@ -111,6 +111,11 @@ btools.print_targets(B.targets, B.bc) # handling cmd line arguments & config file +# bitness stuff +tempbitness = int(B.arguments.get('BF_BITNESS', bitness)) # default to bitness found as per starting python +if tempbitness in (32, 64): # only set if 32 or 64 has been given + bitness = int(tempbitness) + # first check cmdline for toolset and we create env to work on quickie = B.arguments.get('BF_QUICK', None) quickdebug = B.arguments.get('BF_QUICKDEBUG', None) diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index b20f3ede68d..66f0494b1dd 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -159,7 +159,7 @@ def validate_arguments(args, bc): 'BF_BSC', 'BF_CONFIG', 'BF_PRIORITYLIST', 'BF_BUILDINFO','CC', 'CXX', 'BF_QUICKDEBUG', 'BF_LISTDEBUG', 'LCGDIR', 'BF_X264_CONFIG', 'BF_XVIDCORE_CONFIG', - 'BF_UNIT_TEST'] + 'BF_UNIT_TEST', 'BF_BITNESS'] okdict = {} -- cgit v1.2.3 From 4fc56e39bdc381bc45af6da13df7d09d10e4156f Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Tue, 2 Aug 2011 18:56:03 +0000 Subject: Patch by oenvoyage - olivier amrein, thanks a lot! * Material Diffuse Ramp was not greyed out when shadeless was enabled. --- release/scripts/startup/bl_ui/properties_material.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py index 2a52ae23782..296c05d78f5 100644 --- a/release/scripts/startup/bl_ui/properties_material.py +++ b/release/scripts/startup/bl_ui/properties_material.py @@ -247,15 +247,17 @@ class MATERIAL_PT_diffuse(MaterialButtonsPanel, bpy.types.Panel): row.prop(mat, "diffuse_fresnel_factor", text="Factor") if mat.use_diffuse_ramp: - layout.separator() - layout.template_color_ramp(mat, "diffuse_ramp", expand=True) - layout.separator() + col = layout.column() + col.active = (not mat.use_shadeless) + col.separator() + col.template_color_ramp(mat, "diffuse_ramp", expand=True) + col.separator() - row = layout.row() + row = col.row() row.prop(mat, "diffuse_ramp_input", text="Input") row.prop(mat, "diffuse_ramp_blend", text="Blend") - layout.prop(mat, "diffuse_ramp_factor", text="Factor") + col.prop(mat, "diffuse_ramp_factor", text="Factor") class MATERIAL_PT_specular(MaterialButtonsPanel, bpy.types.Panel): -- cgit v1.2.3 From 3af9651b903e05cea956f2358394fec3e0c81ef6 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Tue, 2 Aug 2011 22:50:06 +0000 Subject: ndof changes: turned off 3D mouse during transform, removed timing bug in image/uv, added option for zoom axis (up/down vs. forward/backward) --- source/blender/editors/space_image/image_ops.c | 9 ++------ source/blender/editors/transform/transform_ops.c | 6 ++++++ source/blender/makesdna/DNA_userdef_types.h | 3 +++ .../blender/windowmanager/intern/wm_event_system.c | 25 +++++++++++++++++----- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 6e84c1a7f0c..1f37583b445 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -452,14 +452,9 @@ static int view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; - float dt = ndof->dt > 0.25f ? 0.0125f : ndof->dt; - /* this is probably the first event for this motion, so set dt to something reasonable - * TODO: replace such guesswork with a flag or field from the NDOF manager - */ - /* tune these until it feels right */ - const float zoom_sensitivity = 0.5f; - const float pan_sensitivity = 300.f; + const float zoom_sensitivity = 0.5f; // 50% per second (I think) + const float pan_sensitivity = 300.f; // screen pixels per second float pan_x = pan_sensitivity * dt * ndof->tvec[0] / sima->zoom; float pan_y = pan_sensitivity * dt * ndof->tvec[1] / sima->zoom; diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 0efd25c4faa..fb40cee95fb 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -360,11 +360,17 @@ static int transform_modal(bContext *C, wmOperator *op, wmEvent *event) TransInfo *t = op->customdata; + #if 0 + // stable 2D mouse coords map to different 3D coords while the 3D mouse is active + // in other words, 2D deltas are no longer good enough! + // disable until individual 'transformers' behave better + if (event->type == NDOF_MOTION) { /* puts("transform_modal: passing through NDOF_MOTION"); */ return OPERATOR_PASS_THROUGH; } + #endif /* XXX insert keys are called here, and require context */ t->context= C; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 12f8cd656a0..0bf812f1ec2 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -600,6 +600,9 @@ extern UserDef U; /* from blenkernel blender.c */ /* actually... users probably don't care about what the mode is called, just that it feels right */ #define NDOF_ORBIT_INVERT_AXES (1 << 6) +/* zoom is up/down if this flag is set (otherwise forward/backward) */ +#define NDOF_ZOOM_UPDOWN (1 << 7) +#define NDOF_INVERT_ZOOM (1 << 8) #ifdef __cplusplus diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 0abae2e06b7..9a25c4b581d 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2324,12 +2324,27 @@ static void attach_ndof_data(wmEvent* event, const GHOST_TEventNDOFMotionData* g const float s = U.ndof_sensitivity; data->tvec[0]= s * ghost->tx; - data->tvec[1]= s * ghost->ty; - data->tvec[2]= s * ghost->tz; - data->rvec[0]= s * ghost->rx; - data->rvec[1]= s * ghost->ry; - data->rvec[2]= s * ghost->rz; + + if (U.ndof_flags & NDOF_ZOOM_UPDOWN) + { + // swap Y and Z + data->tvec[1]= s * ghost->tz; + data->tvec[2]= s * ghost->ty; + + // should this affect rotation also? + // initial guess is 'yes', but get user feedback immediately! + data->rvec[1]= s * ghost->rz; + data->rvec[2]= s * ghost->ry; + } + else + { + data->tvec[1]= s * ghost->ty; + data->tvec[2]= s * ghost->tz; + + data->rvec[1]= s * ghost->ry; + data->rvec[2]= s * ghost->rz; + } data->dt = ghost->dt; -- cgit v1.2.3 From 17133e1a1d737771c6afcb701c1a32f035bf03c6 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 2 Aug 2011 23:49:07 +0000 Subject: Compile fix. --- source/blender/editors/space_image/image_ops.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 1f37583b445..e0ebde589a8 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -452,6 +452,7 @@ static int view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + float dt = ndof->dt; /* tune these until it feels right */ const float zoom_sensitivity = 0.5f; // 50% per second (I think) const float pan_sensitivity = 300.f; // screen pixels per second -- cgit v1.2.3 From dc4b104e60d99176fbe32c06dff0b190b3313e3d Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 2 Aug 2011 23:52:07 +0000 Subject: typo fix. --- source/blender/windowmanager/intern/wm_event_system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 9a25c4b581d..2f0c1a72be9 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2326,7 +2326,7 @@ static void attach_ndof_data(wmEvent* event, const GHOST_TEventNDOFMotionData* g data->tvec[0]= s * ghost->tx; data->rvec[0]= s * ghost->rx; - if (U.ndof_flags & NDOF_ZOOM_UPDOWN) + if (U.ndof_flag & NDOF_ZOOM_UPDOWN) { // swap Y and Z data->tvec[1]= s * ghost->tz; -- cgit v1.2.3 From 6233430c2378dc25671426a569ca084f914dda48 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Wed, 3 Aug 2011 05:01:55 +0000 Subject: compensate for lack of 3D mouse calibration on Windows --- intern/ghost/intern/GHOST_NDOFManagerWin32.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp index 099b163edeb..bd86c03d8e9 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp @@ -28,7 +28,9 @@ GHOST_NDOFManagerWin32::GHOST_NDOFManagerWin32(GHOST_System& sys) : GHOST_NDOFManager(sys) - {} + { + setDeadZone(0.1f); + } // whether multi-axis functionality is available (via the OS or driver) // does not imply that a device is plugged in or being used -- cgit v1.2.3 From a10245a1fa0243cc2e8bb739b589693fc26aa2c8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 3 Aug 2011 05:32:07 +0000 Subject: fix [#28151] export OBJ don't save the extension also correct some typos --- doc/python_api/blender-org/static/default.css_t | 2 +- release/scripts/modules/bpy_extras/io_utils.py | 35 ++++++++++++++++------- source/blender/editors/space_view3d/view3d_view.c | 2 +- source/blender/render/intern/source/rendercore.c | 2 +- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/doc/python_api/blender-org/static/default.css_t b/doc/python_api/blender-org/static/default.css_t index 6f3f25d8a6a..e6fe922e3af 100644 --- a/doc/python_api/blender-org/static/default.css_t +++ b/doc/python_api/blender-org/static/default.css_t @@ -219,7 +219,7 @@ div.sphinxsidebarwrapper.fixed { } {%- if theme_stickysidebar|tobool %} -/* this is nice, but it it leads to hidden headings when jumping +/* this is nice, but it leads to hidden headings when jumping to an anchor */ /* div.related { diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py index f476b371d0c..45664384efa 100644 --- a/release/scripts/modules/bpy_extras/io_utils.py +++ b/release/scripts/modules/bpy_extras/io_utils.py @@ -37,6 +37,15 @@ import bpy from bpy.props import StringProperty, BoolProperty, EnumProperty +def _check_axis_conversion(op): + if hasattr(op, "axis_forward") and hasattr(op, "axis_up"): + return axis_conversion_ensure(op, + "axis_forward", + "axis_up", + ) + return False + + class ExportHelper: filepath = StringProperty( name="File Path", @@ -70,21 +79,22 @@ class ExportHelper: return {'RUNNING_MODAL'} def check(self, context): + change_ext = False + change_axis = _check_axis_conversion(self) + check_extension = self.check_extension - if check_extension is None: - return False + if check_extension is not None: + filepath = bpy.path.ensure_ext(self.filepath, + self.filename_ext + if check_extension + else "") - filepath = bpy.path.ensure_ext(self.filepath, - self.filename_ext - if check_extension - else "") + if filepath != self.filepath: + self.filepath = filepath + change_ext = True - if filepath != self.filepath: - self.filepath = filepath - return True - - return False + return (change_ext or change_axis) class ImportHelper: @@ -99,6 +109,9 @@ class ImportHelper: context.window_manager.fileselect_add(self) return {'RUNNING_MODAL'} + def check(self, context): + return _check_axis_conversion(self) + # Axis conversion function, not pretty LUT # use lookup tabes to convert between any axis diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index eeaf87757ce..ed0b2645c99 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1190,7 +1190,7 @@ int ED_view3d_lock(RegionView3D *rv3d) return TRUE; } -/* dont set windows active in in here, is used by renderwin too */ +/* dont set windows active in here, is used by renderwin too */ void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d) { if(rv3d->persp==RV3D_CAMOB) { /* obs/camera */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index a7e19c8db4f..c08d6c0f456 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -730,7 +730,7 @@ static void atm_tile(RenderPart *pa, RenderLayer *rl) if(zpass==NULL) return; - /* check for at least one sun lamp that its atmosphere flag is is enabled */ + /* check for at least one sun lamp that its atmosphere flag is enabled */ for(go=R.lights.first; go; go= go->next) { lar= go->lampren; if(lar->type==LA_SUN && lar->sunsky && (lar->sunsky->effect_type & LA_SUN_EFFECT_AP)) -- cgit v1.2.3 From 6c9d0f2b7a8c3b0b6a0b501461e4fe62def60b05 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 3 Aug 2011 06:27:44 +0000 Subject: whitespace edits. --- intern/ghost/intern/GHOST_NDOFManager.cpp | 202 ++++++++++++------------- intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 64 ++++---- intern/ghost/intern/GHOST_NDOFManagerWin32.cpp | 10 +- intern/ghost/intern/GHOST_NDOFManagerX11.cpp | 62 ++++---- intern/ghost/intern/GHOST_NDOFManagerX11.h | 10 +- 5 files changed, 165 insertions(+), 183 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 5a0f14c85a3..e608301bbcd 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -79,17 +79,15 @@ static const char* ndof_button_names[] = { "NDOF_BUTTON_8", "NDOF_BUTTON_9", "NDOF_BUTTON_10", - }; +}; #endif -static const NDOF_ButtonT SpaceNavigator_HID_map[] = - { +static const NDOF_ButtonT SpaceNavigator_HID_map[] = { NDOF_BUTTON_MENU, NDOF_BUTTON_FIT - }; +}; -static const NDOF_ButtonT SpaceExplorer_HID_map[] = - { +static const NDOF_ButtonT SpaceExplorer_HID_map[] = { NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_TOP, @@ -105,10 +103,9 @@ static const NDOF_ButtonT SpaceExplorer_HID_map[] = NDOF_BUTTON_PLUS, NDOF_BUTTON_MINUS, NDOF_BUTTON_ROTATE - }; +}; -static const NDOF_ButtonT SpacePilotPro_HID_map[] = - { +static const NDOF_ButtonT SpacePilotPro_HID_map[] = { NDOF_BUTTON_MENU, NDOF_BUTTON_FIT, NDOF_BUTTON_TOP, @@ -140,12 +137,11 @@ static const NDOF_ButtonT SpacePilotPro_HID_map[] = NDOF_BUTTON_DOMINANT, NDOF_BUTTON_PLUS, NDOF_BUTTON_MINUS - }; +}; -static const NDOF_ButtonT SpacePilot_HID_map[] = -// this is the older SpacePilot (sans Pro) -// thanks to polosson for the info in this table - { +/* this is the older SpacePilot (sans Pro) + * thanks to polosson for the info in this table */ +static const NDOF_ButtonT SpacePilot_HID_map[] = { NDOF_BUTTON_1, NDOF_BUTTON_2, NDOF_BUTTON_3, @@ -167,7 +163,7 @@ static const NDOF_ButtonT SpacePilot_HID_map[] = NDOF_BUTTON_DOMINANT, NDOF_BUTTON_ROTATE, NDOF_BUTTON_NONE // the CONFIG button -- what does it do? - }; +}; GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) : m_system(sys) @@ -180,29 +176,27 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) , m_motionState(GHOST_kNotStarted) , m_motionEventPending(false) , m_deadZone(0.f) - { +{ // to avoid the rare situation where one triple is updated and // the other is not, initialize them both here: memset(m_translation, 0, sizeof(m_translation)); memset(m_rotation, 0, sizeof(m_rotation)); - #ifdef WITH_INPUT_NDOF +#ifdef WITH_INPUT_NDOF GHOST_PRINT("WITH_INPUT_NDOF is defined!"); - #else +#else GHOST_PRINT("WITH_INPUT_NDOF is not defined."); - #endif - } +#endif +} bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short product_id) - { +{ // default to NDOF_UnknownDevice so rogue button events will get discarded // "mystery device" owners can help build a HID_map for their hardware - switch (vendor_id) - { + switch (vendor_id) { case 0x046D: // Logitech (3Dconnexion) - switch (product_id) - { + switch (product_id) { // -- current devices -- case 0xC626: puts("ndof: using SpaceNavigator"); @@ -225,7 +219,7 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ m_buttonCount = 31; break; - // -- older devices -- + // -- older devices -- case 0xC625: puts("ndof: using SpacePilot"); m_deviceType = NDOF_SpacePilot; @@ -239,182 +233,183 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ default: printf("ndof: unknown Logitech product %04hx\n", product_id); - } + } break; default: printf("ndof: unknown device %04hx:%04hx\n", vendor_id, product_id); - } + } - if (m_deviceType == NDOF_UnknownDevice) + if (m_deviceType == NDOF_UnknownDevice) { return false; - else - { + } + else { m_buttonMask = ~(-1 << m_buttonCount); - #ifdef DEBUG_NDOF_BUTTONS +#ifdef DEBUG_NDOF_BUTTONS printf("ndof: %d buttons -> hex:%X\n", m_buttonCount, m_buttonMask); - #endif +#endif return true; - } } +} void GHOST_NDOFManager::updateTranslation(short t[3], GHOST_TUns64 time) - { +{ memcpy(m_translation, t, sizeof(m_translation)); m_motionTime = time; m_motionEventPending = true; - } +} void GHOST_NDOFManager::updateRotation(short r[3], GHOST_TUns64 time) - { +{ memcpy(m_rotation, r, sizeof(m_rotation)); m_motionTime = time; m_motionEventPending = true; - } +} void GHOST_NDOFManager::sendButtonEvent(NDOF_ButtonT button, bool press, GHOST_TUns64 time, GHOST_IWindow* window) - { +{ GHOST_EventNDOFButton* event = new GHOST_EventNDOFButton(time, window); GHOST_TEventNDOFButtonData* data = (GHOST_TEventNDOFButtonData*) event->getData(); data->action = press ? GHOST_kPress : GHOST_kRelease; data->button = button; - #ifdef DEBUG_NDOF_BUTTONS +#ifdef DEBUG_NDOF_BUTTONS printf("%s %s\n", ndof_button_names[button], press ? "pressed" : "released"); - #endif +#endif m_system.pushEvent(event); - } +} void GHOST_NDOFManager::sendKeyEvent(GHOST_TKey key, bool press, GHOST_TUns64 time, GHOST_IWindow* window) - { +{ GHOST_TEventType type = press ? GHOST_kEventKeyDown : GHOST_kEventKeyUp; GHOST_EventKey* event = new GHOST_EventKey(time, type, window, key); - #ifdef DEBUG_NDOF_BUTTONS +#ifdef DEBUG_NDOF_BUTTONS printf("keyboard %s\n", press ? "down" : "up"); - #endif +#endif m_system.pushEvent(event); - } +} void GHOST_NDOFManager::updateButton(int button_number, bool press, GHOST_TUns64 time) - { +{ GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); - #ifdef DEBUG_NDOF_BUTTONS +#ifdef DEBUG_NDOF_BUTTONS if (m_deviceType != NDOF_UnknownDevice) printf("ndof: button %d -> ", button_number); - #endif +#endif - switch (m_deviceType) - { + switch (m_deviceType) { case NDOF_SpaceNavigator: sendButtonEvent(SpaceNavigator_HID_map[button_number], press, time, window); break; case NDOF_SpaceExplorer: - switch (button_number) - { + switch (button_number) { case 6: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; case 7: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; case 8: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; case 9: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; default: sendButtonEvent(SpaceExplorer_HID_map[button_number], press, time, window); - } + } break; case NDOF_SpacePilotPro: - switch (button_number) - { + switch (button_number) { case 22: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; case 23: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; case 24: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; case 25: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; default: sendButtonEvent(SpacePilotPro_HID_map[button_number], press, time, window); - } + } break; case NDOF_SpacePilot: - switch (button_number) - { + switch (button_number) { case 10: sendKeyEvent(GHOST_kKeyEsc, press, time, window); break; case 11: sendKeyEvent(GHOST_kKeyLeftAlt, press, time, window); break; case 12: sendKeyEvent(GHOST_kKeyLeftShift, press, time, window); break; case 13: sendKeyEvent(GHOST_kKeyLeftControl, press, time, window); break; case 20: puts("ndof: ignoring CONFIG button"); break; default: sendButtonEvent(SpacePilot_HID_map[button_number], press, time, window); - } + } break; case NDOF_UnknownDevice: printf("ndof: button %d on unknown device (ignoring)\n", button_number); - } + } int mask = 1 << button_number; - if (press) + if (press) { m_buttons |= mask; // set this button's bit - else + } + else { m_buttons &= ~mask; // clear this button's bit } +} void GHOST_NDOFManager::updateButtons(int button_bits, GHOST_TUns64 time) - { +{ button_bits &= m_buttonMask; // discard any "garbage" bits int diff = m_buttons ^ button_bits; - for (int button_number = 0; button_number < m_buttonCount; ++button_number) - { + for (int button_number = 0; button_number < m_buttonCount; ++button_number) { int mask = 1 << button_number; - if (diff & mask) - { + if (diff & mask) { bool press = button_bits & mask; updateButton(button_number, press, time); - } } } +} void GHOST_NDOFManager::setDeadZone(float dz) - { - if (dz < 0.f) +{ + if (dz < 0.f) { // negative values don't make sense, so clamp at zero dz = 0.f; - else if (dz > 0.5f) + } + else if (dz > 0.5f) { // warn the rogue user/programmer, but allow it printf("ndof: dead zone of %.2f is rather high...\n", dz); - + } m_deadZone = dz; printf("ndof: dead zone set to %.2f\n", dz); - } +} static bool atHomePosition(GHOST_TEventNDOFMotionData* ndof) - { - #define HOME(foo) (ndof->foo == 0) +{ +#define HOME(foo) (ndof->foo == 0) return HOME(tx) && HOME(ty) && HOME(tz) && HOME(rx) && HOME(ry) && HOME(rz); - } +#undef HOME +} static bool nearHomePosition(GHOST_TEventNDOFMotionData* ndof, float threshold) - { - if (threshold == 0.f) +{ + if (threshold == 0.f) { return atHomePosition(ndof); - else - { - #define HOME1(foo) (fabsf(ndof->foo) < threshold) + } + else { +#define HOME1(foo) (fabsf(ndof->foo) < threshold) return HOME1(tx) && HOME1(ty) && HOME1(tz) && HOME1(rx) && HOME1(ry) && HOME1(rz); - } +#undef HOME1 } +} bool GHOST_NDOFManager::sendMotionEvent() - { +{ if (!m_motionEventPending) return false; m_motionEventPending = false; // any pending motion is handled right now GHOST_IWindow* window = m_system.getWindowManager()->getActiveWindow(); - if (window == NULL) + + if (window == NULL) { return false; // delivery will fail, so don't bother sending + } GHOST_EventNDOFMotion* event = new GHOST_EventNDOFMotion(m_motionTime, window); GHOST_TEventNDOFMotionData* data = (GHOST_TEventNDOFMotionData*) event->getData(); @@ -438,51 +433,46 @@ bool GHOST_NDOFManager::sendMotionEvent() // determine what kind of motion event to send (Starting, InProgress, Finishing) // and where that leaves this NDOF manager (NotStarted, InProgress, Finished) - switch (m_motionState) - { + switch (m_motionState) { case GHOST_kNotStarted: case GHOST_kFinished: - if (handMotion) - { + if (handMotion) { data->progress = GHOST_kStarting; m_motionState = GHOST_kInProgress; // prev motion time will be ancient, so just make up something reasonable data->dt = 0.0125f; - } - else - { + } + else { // send no event and keep current state delete event; return false; - } + } break; case GHOST_kInProgress: - if (handMotion) - { + if (handMotion) { data->progress = GHOST_kInProgress; // keep InProgress state - } - else - { + } + else { data->progress = GHOST_kFinishing; m_motionState = GHOST_kFinished; - } + } break; - } + } - #ifdef DEBUG_NDOF_MOTION +#ifdef DEBUG_NDOF_MOTION printf("ndof motion sent -- %s\n", progress_string[data->progress]); // show details about this motion event printf(" T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f\n", - data->tx, data->ty, data->tz, - data->rx, data->ry, data->rz, - data->dt); - #endif + data->tx, data->ty, data->tz, + data->rx, data->ry, data->rz, + data->dt); +#endif m_system.pushEvent(event); m_prevMotionTime = m_motionTime; return true; - } +} diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index 07811c563ec..53a991a7396 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -40,7 +40,7 @@ static GHOST_NDOFManager* ndof_manager = NULL; static bool has_old_driver = true; static void NDOF_DeviceAdded(io_connect_t connection) - { +{ printf("ndof: device added\n"); // change these: printf --> informational reports #if 0 // device preferences will be useful some day @@ -55,27 +55,27 @@ static void NDOF_DeviceAdded(io_connect_t connection) unsigned short productID = result & 0xffff; ndof_manager->setDevice(vendorID, productID); - } +} static void NDOF_DeviceRemoved(io_connect_t connection) - { +{ printf("ndof: device removed\n"); - } +} static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, void* messageArgument) - { +{ switch (messageType) - { + { case kConnexionMsgDeviceState: - { + { ConnexionDeviceState* s = (ConnexionDeviceState*)messageArgument; GHOST_TUns64 now = ghost_system->getMilliSeconds(); switch (s->command) - { + { case kConnexionCmdHandleAxis: - { + { // convert to blender view coordinates short t[3] = {s->axis[0], -(s->axis[2]), s->axis[1]}; short r[3] = {-(s->axis[3]), s->axis[5], -(s->axis[4])}; @@ -85,23 +85,23 @@ static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, voi ghost_system->notifyExternalEventProcessed(); break; - } + } case kConnexionCmdHandleButtons: - { + { int button_bits = has_old_driver ? s->buttons8 : s->buttons; ndof_manager->updateButtons(button_bits, now); ghost_system->notifyExternalEventProcessed(); break; - } + } case kConnexionCmdAppSpecific: printf("ndof: app-specific command, param = %hd, value = %d\n", s->param, s->value); break; default: printf("ndof: mystery device command %d\n", s->command); - } - break; } + break; + } case kConnexionMsgPrefsChanged: // printf("ndof: prefs changed\n"); // this includes app switches // TODO: look through updated prefs for things blender cares about @@ -117,58 +117,56 @@ static void NDOF_DeviceEvent(io_connect_t connection, natural_t messageType, voi break; default: printf("ndof: mystery event %d\n", messageType); - } } +} GHOST_NDOFManagerCocoa::GHOST_NDOFManagerCocoa(GHOST_System& sys) - : GHOST_NDOFManager(sys) - { + : GHOST_NDOFManager(sys) +{ if (available()) - { + { // give static functions something to talk to: ghost_system = dynamic_cast(&sys); ndof_manager = this; OSErr error = InstallConnexionHandlers(NDOF_DeviceEvent, NDOF_DeviceAdded, NDOF_DeviceRemoved); - if (error) - { + if (error) { printf("ndof: error %d while installing handlers\n", error); return; - } + } // Pascal string *and* a four-letter constant. How old-skool. m_clientID = RegisterConnexionClient('blnd', (UInt8*) "\007blender", - kConnexionClientModeTakeOver, kConnexionMaskAll); + kConnexionClientModeTakeOver, kConnexionMaskAll); // printf("ndof: client id = %d\n", m_clientID); - if (SetConnexionClientButtonMask != NULL) - { + if (SetConnexionClientButtonMask != NULL) { has_old_driver = false; SetConnexionClientButtonMask(m_clientID, kConnexionMaskAllButtons); - } - else + } + else { printf("ndof: old 3Dx driver installed, some buttons may not work\n"); } - else - { + } + else { printf("ndof: 3Dx driver not found\n"); // This isn't a hard error, just means the user doesn't have a 3D mouse. - } } +} GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() - { +{ UnregisterConnexionClient(m_clientID); CleanupConnexionHandlers(); ghost_system = NULL; ndof_manager = NULL; - } +} bool GHOST_NDOFManagerCocoa::available() - { +{ // extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); // ^^ not needed since the entire framework is weak-linked return InstallConnexionHandlers != NULL; // this means that the driver is installed and dynamically linked to blender - } +} diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp index bd86c03d8e9..57d84ec14d4 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp @@ -27,15 +27,15 @@ GHOST_NDOFManagerWin32::GHOST_NDOFManagerWin32(GHOST_System& sys) - : GHOST_NDOFManager(sys) - { + : GHOST_NDOFManager(sys) +{ setDeadZone(0.1f); - } +} // whether multi-axis functionality is available (via the OS or driver) // does not imply that a device is plugged in or being used bool GHOST_NDOFManagerWin32::available() - { +{ // always available since RawInput is built into Windows return true; - } +} diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp index 8043af2760e..099fa15d179 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp @@ -30,70 +30,64 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys) - : GHOST_NDOFManager(sys) - , m_available(false) - { + : + GHOST_NDOFManager(sys), + m_available(false) +{ setDeadZone(0.1f); // how to calibrate on Linux? throw away slight motion! - if (spnav_open() != -1) - { + if (spnav_open() != -1) { // determine exactly which device (if any) is plugged in - #define MAX_LINE_LENGTH 100 +#define MAX_LINE_LENGTH 100 // look for USB devices with Logitech's vendor ID FILE* command_output = popen("lsusb -d 046d:","r"); - if (command_output) - { + if (command_output) { char line[MAX_LINE_LENGTH] = {0}; - while (fgets(line, MAX_LINE_LENGTH, command_output)) - { + while (fgets(line, MAX_LINE_LENGTH, command_output)) { unsigned short vendor_id = 0, product_id = 0; if (sscanf(line, "Bus %*d Device %*d: ID %hx:%hx", &vendor_id, &product_id) == 2) - if (setDevice(vendor_id, product_id)) - { + if (setDevice(vendor_id, product_id)) { m_available = true; break; // stop looking once the first 3D mouse is found - } - } - pclose(command_output); + } } + pclose(command_output); } - else - { + } + else { printf("ndof: spacenavd not found\n"); // This isn't a hard error, just means the user doesn't have a 3D mouse. - } } +} GHOST_NDOFManagerX11::~GHOST_NDOFManagerX11() - { +{ if (m_available) spnav_close(); - } +} bool GHOST_NDOFManagerX11::available() - { +{ return m_available; - } +} //bool GHOST_NDOFManagerX11::identifyDevice() -// { +//{ // -// } +//} bool GHOST_NDOFManagerX11::processEvents() - { +{ GHOST_TUns64 now = m_system.getMilliSeconds(); bool anyProcessed = false; spnav_event e; - while (spnav_poll_event(&e)) - { - switch (e.type) - { + while (spnav_poll_event(&e)) { + switch (e.type) { case SPNAV_EVENT_MOTION: - { + { // convert to blender view coords short t[3] = {e.motion.x, e.motion.y, -e.motion.z}; short r[3] = {-e.motion.rx, -e.motion.ry, e.motion.rz}; @@ -101,12 +95,12 @@ bool GHOST_NDOFManagerX11::processEvents() updateTranslation(t, now); updateRotation(r, now); break; - } + } case SPNAV_EVENT_BUTTON: updateButton(e.button.bnum, e.button.press, now); break; - } - anyProcessed = true; } - return anyProcessed; + anyProcessed = true; } + return anyProcessed; +} diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.h b/intern/ghost/intern/GHOST_NDOFManagerX11.h index 175041b21e9..82bd256c707 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.h +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.h @@ -28,11 +28,11 @@ #include "GHOST_NDOFManager.h" -// Event capture is handled within the NDOF manager on Linux, -// so there's no need for SystemX11 to look for them. +/* Event capture is handled within the NDOF manager on Linux, + * so there's no need for SystemX11 to look for them. */ class GHOST_NDOFManagerX11 : public GHOST_NDOFManager - { +{ public: GHOST_NDOFManagerX11(GHOST_System&); ~GHOST_NDOFManagerX11(); @@ -40,10 +40,10 @@ public: bool processEvents(); private: -// bool identifyDevice(); + // bool identifyDevice(); bool m_available; - }; +}; #endif -- cgit v1.2.3 From 9cf3bcd414bc0a6df0abc451040bc3098fe81e5d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 3 Aug 2011 06:30:19 +0000 Subject: add note in scene.frame_current that frace_set() updates animation data. --- source/blender/makesrna/intern/rna_scene.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index f4028e45e96..b3d8bc8ea18 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -3251,7 +3251,7 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "r.cfra"); RNA_def_property_range(prop, MINAFRAME, MAXFRAME); RNA_def_property_int_funcs(prop, NULL, "rna_Scene_current_frame_set", NULL); - RNA_def_property_ui_text(prop, "Current Frame", "Current Frame"); + RNA_def_property_ui_text(prop, "Current Frame", "Current Frame, to update animation data from python frame_set() instead"); RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_update(prop, NC_SCENE|ND_FRAME, "rna_Scene_frame_update"); -- cgit v1.2.3 From 3b541b259fc3591bf72605e5442701691190ad74 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Wed, 3 Aug 2011 06:42:55 +0000 Subject: removed attempted WITH_BF_3DMOUSE detection, fixed just one indention (left the others in their ugly new state) --- intern/ghost/intern/GHOST_NDOFManager.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index e608301bbcd..db87e1f8fc5 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -181,12 +181,6 @@ GHOST_NDOFManager::GHOST_NDOFManager(GHOST_System& sys) // the other is not, initialize them both here: memset(m_translation, 0, sizeof(m_translation)); memset(m_rotation, 0, sizeof(m_rotation)); - -#ifdef WITH_INPUT_NDOF - GHOST_PRINT("WITH_INPUT_NDOF is defined!"); -#else - GHOST_PRINT("WITH_INPUT_NDOF is not defined."); -#endif } bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short product_id) @@ -219,7 +213,7 @@ bool GHOST_NDOFManager::setDevice(unsigned short vendor_id, unsigned short produ m_buttonCount = 31; break; - // -- older devices -- + // -- older devices -- case 0xC625: puts("ndof: using SpacePilot"); m_deviceType = NDOF_SpacePilot; -- cgit v1.2.3 From 02ab2b473cfad725f42a67699a7afedc90c512e3 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Wed, 3 Aug 2011 07:08:28 +0000 Subject: Debug print removed. --- intern/ghost/intern/GHOST_SystemWin32.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index c985c6dd0a6..bbf8efeaee3 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -730,11 +730,9 @@ GHOST_Event* GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, GHOST_ { GHOST_System* system = (GHOST_System*)getSystem(); - if (type == GHOST_kEventWindowActivate) - { - puts("activating window"); + if (type == GHOST_kEventWindowActivate) { system->getWindowManager()->setActiveWindow(window); - } + } return new GHOST_Event(system->getMilliSeconds(), type, window); } -- cgit v1.2.3 From d4909c56285a68562e8763f2f2fe40ec5c5297fe Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 3 Aug 2011 07:30:24 +0000 Subject: - Do not add GHOST_NDOFManager.cpp to list of sources if NDOF is disabled in CMake. - Added "default" section to switch in sendMotionEvent. It's what strict gcc rules don't like much and it's And it's good practice in general, imo. --- intern/ghost/CMakeLists.txt | 11 ++++++++--- intern/ghost/intern/GHOST_NDOFManager.cpp | 2 ++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 2180ddbe567..d7658c50a36 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -44,7 +44,6 @@ set(SRC intern/GHOST_ISystem.cpp intern/GHOST_ISystemPaths.cpp intern/GHOST_ModifierKeys.cpp - intern/GHOST_NDOFManager.cpp intern/GHOST_Path-api.cpp intern/GHOST_Path-api.cpp intern/GHOST_Rect.cpp @@ -74,12 +73,10 @@ set(SRC intern/GHOST_EventDragnDrop.h intern/GHOST_EventKey.h intern/GHOST_EventManager.h - intern/GHOST_EventNDOF.h intern/GHOST_EventString.h intern/GHOST_EventTrackpad.h intern/GHOST_EventWheel.h intern/GHOST_ModifierKeys.h - intern/GHOST_NDOFManager.h intern/GHOST_System.h intern/GHOST_SystemPaths.h intern/GHOST_TimerManager.h @@ -99,6 +96,14 @@ endif() if(WITH_INPUT_NDOF) add_definitions(-DWITH_INPUT_NDOF) + + list(APPEND SRC + intern/GHOST_NDOFManager.cpp + + intern/GHOST_EventNDOF.h + intern/GHOST_NDOFManager.h + ) + list(APPEND INC_SYS ${NDOF_INCLUDE_DIRS} ) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index db87e1f8fc5..855e27b9964 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -452,6 +452,8 @@ bool GHOST_NDOFManager::sendMotionEvent() m_motionState = GHOST_kFinished; } break; + default: + break; } #ifdef DEBUG_NDOF_MOTION -- cgit v1.2.3 From e320db106691a6912fca05f6a8dfb09a3d4f2128 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 3 Aug 2011 08:02:32 +0000 Subject: fix [#28135] Edge slide changes UV --- source/blender/editors/include/ED_transform.h | 1 + source/blender/editors/transform/transform.c | 14 ++++++-------- source/blender/editors/transform/transform_generics.c | 16 ++++++++++++++++ source/blender/editors/transform/transform_ops.c | 7 ++++++- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index d4d7f971b74..00ae7dda2e3 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -148,6 +148,7 @@ void BIF_selectOrientation(void); #define P_ALIGN_SNAP (P_GEO_SNAP|(1 << 5)) #define P_CONSTRAINT (1 << 6) #define P_OPTIONS (1 << 7) +#define P_CORRECT_UV (1 << 8) void Transform_Properties(struct wmOperatorType *ot, int flags); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 92ac8471172..39e26bc6436 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -4243,7 +4243,7 @@ static int createSlideVerts(TransInfo *t) /* UV correction vars */ GHash **uvarray= NULL; SlideData *sld = MEM_callocN(sizeof(*sld), "sld"); - int uvlay_tot= CustomData_number_of_layers(&em->fdata, CD_MTFACE); + const int uvlay_tot= (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) ? CustomData_number_of_layers(&em->fdata, CD_MTFACE) : 0; int uvlay_idx; TransDataSlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL; RegionView3D *v3d = t->ar ? t->ar->regiondata : NULL; /* background mode support */ @@ -4615,7 +4615,7 @@ static int createSlideVerts(TransInfo *t) sld->end[0] = (int) end[0]; sld->end[1] = (int) end[1]; - if (uvlay_tot) { // XXX && (scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) { + if (uvlay_tot) { int maxnum = 0; uvarray = MEM_callocN( uvlay_tot * sizeof(GHash *), "SlideUVs Array"); @@ -4805,8 +4805,6 @@ void initEdgeSlide(TransInfo *t) int doEdgeSlide(TransInfo *t, float perc) { - Mesh *me= t->obedit->data; - EditMesh *em = me->edit_mesh; SlideData *sld = t->customData; EditVert *ev, *nearest = sld->nearest; EditVert *centerVert, *upVert, *downVert; @@ -4817,7 +4815,7 @@ int doEdgeSlide(TransInfo *t, float perc) int prop=1, flip=0; /* UV correction vars */ GHash **uvarray= sld->uvhash; - int uvlay_tot= CustomData_number_of_layers(&em->fdata, CD_MTFACE); + const int uvlay_tot= sld->uvlay_tot; int uvlay_idx; TransDataSlideUv *suv; float uv_tmp[2]; @@ -4843,7 +4841,7 @@ int doEdgeSlide(TransInfo *t, float perc) tempev = editedge_getOtherVert((perc>=0)?tempsv->up:tempsv->down, ev); interp_v3_v3v3(ev->co, tempsv->origvert.co, tempev->co, fabs(perc)); - if (uvlay_tot) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + if (uvlay_tot) { for (uvlay_idx=0; uvlay_idxfuv_list && suv->uv_up && suv->uv_down) { @@ -4873,7 +4871,7 @@ int doEdgeSlide(TransInfo *t, float perc) if(newlen < 0.0f) {newlen = 0.0;} if(flip == 0) { interp_v3_v3v3(ev->co, editedge_getOtherVert(tempsv->down,ev)->co, editedge_getOtherVert(tempsv->up,ev)->co, fabs(newlen)); - if (uvlay_tot) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + if (uvlay_tot) { /* dont do anything if no UVs */ for (uvlay_idx=0; uvlay_idxco, editedge_getOtherVert(tempsv->up,ev)->co, editedge_getOtherVert(tempsv->down,ev)->co, fabs(newlen)); - if (uvlay_tot) { // XXX scene->toolsettings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT) { + if (uvlay_tot) { /* dont do anything if no UVs */ for (uvlay_idx=0; uvlay_idxoptions |= CTX_NO_PET; } } + + /* initialize UV transform from */ + if (RNA_struct_find_property(op->ptr, "correct_uv")) { + if(RNA_property_is_set(op->ptr, "correct_uv")) { + if(RNA_boolean_get(op->ptr, "correct_uv")) { + t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT; + } + else { + t->settings->uvcalc_flag &= ~UVCALC_TRANSFORM_CORRECT; + } + } + else { + RNA_boolean_set(op->ptr, "correct_uv", t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT); + } + } + } else if(t->spacetype==SPACE_IMAGE) { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index fb40cee95fb..54e0b31e201 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -508,6 +508,11 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) RNA_def_boolean(ot->srna, "texture_space", 0, "Edit Object data texture space", ""); } + if (flags & P_CORRECT_UV) + { + RNA_def_boolean(ot->srna, "correct_uv", 0, "Correct UV coords when transforming", ""); + } + // Add confirm method all the time. At the end because it's not really that important and should be hidden only in log, not in keymap edit /*prop =*/ RNA_def_boolean(ot->srna, "release_confirm", 0, "Confirm on Release", "Always confirm operation when releasing button"); //RNA_def_property_flag(prop, PROP_HIDDEN); @@ -755,7 +760,7 @@ void TRANSFORM_OT_edge_slide(struct wmOperatorType *ot) RNA_def_float_factor(ot->srna, "value", 0, -1.0f, 1.0f, "Factor", "", -1.0f, 1.0f); - Transform_Properties(ot, P_MIRROR|P_SNAP); + Transform_Properties(ot, P_MIRROR|P_SNAP|P_CORRECT_UV); } void TRANSFORM_OT_edge_crease(struct wmOperatorType *ot) -- cgit v1.2.3 From fd35ee8422eee72beacab896e21a6e554a8ba853 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 3 Aug 2011 09:07:30 +0000 Subject: - Switch linux buildbot to FFmpeg-0.8.1 - Enable FFmpeg for blenderplayer for linux buildbot. --- build_files/buildbot/config/user-config-i686.py | 2 +- build_files/buildbot/config/user-config-player-i686.py | 13 ++++++++++++- build_files/buildbot/config/user-config-player-x86_64.py | 13 ++++++++++++- build_files/buildbot/config/user-config-x86_64.py | 2 +- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/build_files/buildbot/config/user-config-i686.py b/build_files/buildbot/config/user-config-i686.py index 07dc4a9d831..e09fecede59 100644 --- a/build_files/buildbot/config/user-config-i686.py +++ b/build_files/buildbot/config/user-config-i686.py @@ -22,7 +22,7 @@ BF_EXPAT_LIB = '' WITH_BF_FFMPEG = True WITH_BF_STATICFFMPEG = True -BF_FFMPEG = '/home/sources/staticlibs/ffmpeg' +BF_FFMPEG = '/home/sources/staticlibs/ffmpeg-0.8' BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib32' BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \ '${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \ diff --git a/build_files/buildbot/config/user-config-player-i686.py b/build_files/buildbot/config/user-config-player-i686.py index ab31c6ce8a7..279f2d66804 100644 --- a/build_files/buildbot/config/user-config-player-i686.py +++ b/build_files/buildbot/config/user-config-player-i686.py @@ -13,7 +13,18 @@ WITH_BF_STATICPYTHON = True WITH_BF_COLLADA = False # FFMPEG configuration -WITH_BF_FFMPEG = False +WITH_BF_FFMPEG = True +WITH_BF_STATICFFMPEG = True + +BF_FFMPEG = '/home/sources/staticlibs/ffmpeg-0.8' +BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib32' +BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \ + '${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \ + '${BF_FFMPEG_LIBPATH}/libxvidcore.a ${BF_FFMPEG_LIBPATH}/libx264.a ${BF_FFMPEG_LIBPATH}/libmp3lame.a ' + \ + '${BF_FFMPEG_LIBPATH}/libvpx.a ${BF_FFMPEG_LIBPATH}/libvorbis.a ${BF_FFMPEG_LIBPATH}/libogg.a ' + \ + '${BF_FFMPEG_LIBPATH}/libvorbisenc.a ${BF_FFMPEG_LIBPATH}/libtheora.a ' + \ + '${BF_FFMPEG_LIBPATH}/libschroedinger-1.0.a ${BF_FFMPEG_LIBPATH}/liborc-0.4.a ${BF_FFMPEG_LIBPATH}/libdirac_encoder.a ' + \ + '${BF_FFMPEG_LIBPATH}/libfaad.a' # Don't depend on system's libstdc++ WITH_BF_STATICCXX = True diff --git a/build_files/buildbot/config/user-config-player-x86_64.py b/build_files/buildbot/config/user-config-player-x86_64.py index 601b2c3ca1a..d1914338510 100644 --- a/build_files/buildbot/config/user-config-player-x86_64.py +++ b/build_files/buildbot/config/user-config-player-x86_64.py @@ -13,7 +13,18 @@ WITH_BF_STATICPYTHON = True WITH_BF_COLLADA = False # FFMPEG configuration -WITH_BF_FFMPEG = False +WITH_BF_FFMPEG = True +WITH_BF_STATICFFMPEG = True + +BF_FFMPEG = '/home/sources/staticlibs/ffmpeg-0.8' +BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib64' +BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \ + '${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \ + '${BF_FFMPEG_LIBPATH}/libxvidcore.a ${BF_FFMPEG_LIBPATH}/libx264.a ${BF_FFMPEG_LIBPATH}/libmp3lame.a ' + \ + '${BF_FFMPEG_LIBPATH}/libvpx.a ${BF_FFMPEG_LIBPATH}/libvorbis.a ${BF_FFMPEG_LIBPATH}/libogg.a ' + \ + '${BF_FFMPEG_LIBPATH}/libvorbisenc.a ${BF_FFMPEG_LIBPATH}/libtheora.a ' + \ + '${BF_FFMPEG_LIBPATH}/libschroedinger-1.0.a ${BF_FFMPEG_LIBPATH}/liborc-0.4.a ${BF_FFMPEG_LIBPATH}/libdirac_encoder.a ' + \ + '${BF_FFMPEG_LIBPATH}/libfaad.a' # Don't depend on system's libstdc++ WITH_BF_STATICCXX = True diff --git a/build_files/buildbot/config/user-config-x86_64.py b/build_files/buildbot/config/user-config-x86_64.py index 9c569ff4458..bdba8892bf8 100644 --- a/build_files/buildbot/config/user-config-x86_64.py +++ b/build_files/buildbot/config/user-config-x86_64.py @@ -22,7 +22,7 @@ BF_EXPAT_LIB = '' WITH_BF_FFMPEG = True WITH_BF_STATICFFMPEG = True -BF_FFMPEG = '/home/sources/staticlibs/ffmpeg' +BF_FFMPEG = '/home/sources/staticlibs/ffmpeg-0.8' BF_FFMPEG_LIBPATH = '${BF_FFMPEG}/lib64' BF_FFMPEG_LIB_STATIC = '${BF_FFMPEG_LIBPATH}/libavformat.a ${BF_FFMPEG_LIBPATH}/libswscale.a ' + \ '${BF_FFMPEG_LIBPATH}/libavcodec.a ${BF_FFMPEG_LIBPATH}/libavdevice.a ${BF_FFMPEG_LIBPATH}/libavutil.a ' + \ -- cgit v1.2.3 From 461bb17d31cc17c07a4b00437b5b90d58f14a894 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 3 Aug 2011 09:28:16 +0000 Subject: fix [#27965] VSE: no visual feedback on locked strips added xpm -> opengl stipple conversion script. --- source/blender/editors/include/BIF_glutil.h | 2 ++ source/blender/editors/screen/glutil.c | 38 ++++++++++++++++++++++ .../editors/space_sequencer/sequencer_draw.c | 19 +++++++++++ 3 files changed, 59 insertions(+) diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h index c9615204607..27bd31c20ff 100644 --- a/source/blender/editors/include/BIF_glutil.h +++ b/source/blender/editors/include/BIF_glutil.h @@ -52,6 +52,8 @@ void fdrawXORcirc(float xofs, float yofs, float rad); /* glStipple defines */ extern unsigned char stipple_halftone[128]; extern unsigned char stipple_quarttone[128]; +extern unsigned char stipple_diag_stripes_pos[128]; +extern unsigned char stipple_diag_stripes_neg[128]; /** * Draw a lined (non-looping) arc with the given diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 2918c98c84a..f56ae17d366 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -92,6 +92,44 @@ GLubyte stipple_quarttone[128] = { 136,136,136,136,0,0,0,0,34,34,34,34,0,0,0,0}; +GLubyte stipple_diag_stripes_pos[128] = { + 0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe, + 0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8, + 0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0, + 0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80, + 0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01, + 0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07, + 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f, + 0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f, + 0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe, + 0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8, + 0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0, + 0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80, + 0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01, + 0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07, + 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f, + 0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f}; + + +GLubyte stipple_diag_stripes_neg[128] = { + 0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01, + 0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07, + 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f, + 0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f, + 0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe, + 0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8, + 0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0, + 0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80, + 0xff, 0x00, 0xff, 0x00, 0xfe, 0x01, 0xfe, 0x01, + 0xfc, 0x03, 0xfc, 0x03, 0xf8, 0x07, 0xf8, 0x07, + 0xf0, 0x0f, 0xf0, 0x0f, 0xe0, 0x1f, 0xe0, 0x1f, + 0xc0, 0x3f, 0xc0, 0x3f, 0x80, 0x7f, 0x80, 0x7f, + 0x00, 0xff, 0x00, 0xff, 0x01, 0xfe, 0x01, 0xfe, + 0x03, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x07, 0xf8, + 0x0f, 0xf0, 0x0f, 0xf0, 0x1f, 0xe0, 0x1f, 0xe0, + 0x3f, 0xc0, 0x3f, 0xc0, 0x7f, 0x80, 0x7f, 0x80}; + + void fdrawbezier(float vec[4][3]) { float dist; diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 594d2942e8f..98687bb90e0 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -639,6 +639,25 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline /* draw sound wave */ if(seq->type == SEQ_SOUND) drawseqwave(scene, seq, x1, y1, x2, y2, (ar->v2d.cur.xmax - ar->v2d.cur.xmin)/ar->winx); + /* draw lock */ + if(seq->flag & SEQ_LOCK) { + glEnable(GL_POLYGON_STIPPLE); + glEnable(GL_BLEND); + + /* light stripes */ + glColor4ub(255, 255, 255, 32); + glPolygonStipple(stipple_diag_stripes_pos); + glRectf(x1, y1, x2, y2); + + /* dark stripes */ + glColor4ub(0, 0, 0, 32); + glPolygonStipple(stipple_diag_stripes_neg); + glRectf(x1, y1, x2, y2); + + glDisable(GL_POLYGON_STIPPLE); + glDisable(GL_BLEND); + } + get_seq_color3ubv(scene, seq, col); if (G.moving && (seq->flag & SELECT)) { if(seq->flag & SEQ_OVERLAP) { -- cgit v1.2.3 From 2c4357c1e10df65089459e048c44ff9c99b8ffd9 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 3 Aug 2011 10:50:21 +0000 Subject: - Move list of FFmpeg DLLs to be installed from SConstruct to conficuration variable BF_FFMPEG_DDL. This would allow to use different FFmpeg in buildbot. - Added some 3DMOUSE variables to list of command line options. Now 3dmouse related-settings can be set from command line. --- SConstruct | 6 +----- build_files/scons/config/win32-vc-config.py | 1 + build_files/scons/config/win64-vc-config.py | 1 + build_files/scons/tools/btools.py | 5 +++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/SConstruct b/SConstruct index dbeabb5c2ef..529f6daeef1 100644 --- a/SConstruct +++ b/SConstruct @@ -664,11 +664,7 @@ if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'): dllsources.append('${LCGDIR}/sndfile/lib/libsndfile-1.dll') if env['WITH_BF_FFMPEG']: - dllsources += ['${BF_FFMPEG_LIBPATH}/avcodec-52.dll', - '${BF_FFMPEG_LIBPATH}/avformat-52.dll', - '${BF_FFMPEG_LIBPATH}/avdevice-52.dll', - '${BF_FFMPEG_LIBPATH}/avutil-50.dll', - '${BF_FFMPEG_LIBPATH}/swscale-0.dll'] + dllsources += env['BF_FFMPEG_DLL'].split() # Since the thumb handler is loaded by Explorer, architecture is # strict: the x86 build fails on x64 Windows. We need to ship diff --git a/build_files/scons/config/win32-vc-config.py b/build_files/scons/config/win32-vc-config.py index 5a91852052d..4baada7f9bf 100644 --- a/build_files/scons/config/win32-vc-config.py +++ b/build_files/scons/config/win32-vc-config.py @@ -7,6 +7,7 @@ BF_FFMPEG = LIBDIR +'/ffmpeg' BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}/include/msvc' BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' BF_FFMPEG_LIB = 'avformat-52.lib avcodec-52.lib avdevice-52.lib avutil-50.lib swscale-0.lib' +BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-52.dll ${BF_FFMPEG_LIBPATH}/avcodec-52.dll ${BF_FFMPEG_LIBPATH}/avdevice-52.dll ${BF_FFMPEG_LIBPATH}/avutil-50.dll ${BF_FFMPEG_LIBPATH}/swscale-0.dll' BF_PYTHON = LIBDIR + '/python' BF_PYTHON_VERSION = '3.2' diff --git a/build_files/scons/config/win64-vc-config.py b/build_files/scons/config/win64-vc-config.py index 6717f12fcf8..db7c8d09af8 100644 --- a/build_files/scons/config/win64-vc-config.py +++ b/build_files/scons/config/win64-vc-config.py @@ -7,6 +7,7 @@ BF_FFMPEG = LIBDIR +'/ffmpeg' BF_FFMPEG_INC = '${BF_FFMPEG}/include ${BF_FFMPEG}/include/msvc ' BF_FFMPEG_LIBPATH='${BF_FFMPEG}/lib' BF_FFMPEG_LIB = 'avformat-52.lib avcodec-52.lib avdevice-52.lib avutil-50.lib swscale-0.lib' +BF_FFMPEG_DLL = '${BF_FFMPEG_LIBPATH}/avformat-52.dll ${BF_FFMPEG_LIBPATH}/avcodec-52.dll ${BF_FFMPEG_LIBPATH}/avdevice-52.dll ${BF_FFMPEG_LIBPATH}/avutil-50.dll ${BF_FFMPEG_LIBPATH}/swscale-0.dll' BF_PYTHON = LIBDIR + '/python' BF_PYTHON_VERSION = '3.2' diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index 66f0494b1dd..9b911b9d6f0 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -87,7 +87,7 @@ def validate_arguments(args, bc): 'BF_PTHREADS', 'BF_PTHREADS_INC', 'BF_PTHREADS_LIB', 'BF_PTHREADS_LIBPATH', 'WITH_BF_OPENEXR', 'BF_OPENEXR', 'BF_OPENEXR_INC', 'BF_OPENEXR_LIB', 'BF_OPENEXR_LIBPATH', 'WITH_BF_STATICOPENEXR', 'BF_OPENEXR_LIB_STATIC', 'WITH_BF_DDS', 'WITH_BF_CINEON', 'WITH_BF_HDR', - 'WITH_BF_FFMPEG', 'BF_FFMPEG_LIB','BF_FFMPEG_EXTRA', 'BF_FFMPEG', 'BF_FFMPEG_INC', + 'WITH_BF_FFMPEG', 'BF_FFMPEG_LIB','BF_FFMPEG_EXTRA', 'BF_FFMPEG', 'BF_FFMPEG_INC', 'BF_FFMPEG_DLL', 'WITH_BF_STATICFFMPEG', 'BF_FFMPEG_LIB_STATIC', 'WITH_BF_OGG', 'BF_OGG', 'BF_OGG_LIB', 'WITH_BF_JPEG', 'BF_JPEG', 'BF_JPEG_INC', 'BF_JPEG_LIB', 'BF_JPEG_LIBPATH', @@ -136,7 +136,7 @@ def validate_arguments(args, bc): 'BF_NO_ELBEEM', 'WITH_BF_CXX_GUARDEDALLOC', 'WITH_BF_JEMALLOC', 'WITH_BF_STATICJEMALLOC', 'BF_JEMALLOC', 'BF_JEMALLOC_INC', 'BF_JEMALLOC_LIBPATH', 'BF_JEMALLOC_LIB', 'BF_JEMALLOC_LIB_STATIC', - 'BUILDBOT_BRANCH', 'WITH_BF_3DMOUSE' + 'BUILDBOT_BRANCH', 'WITH_BF_3DMOUSE', 'WITH_BF_STATIC3DMOUSE', 'BF_3DMOUSE', 'BF_3DMOUSE_INC', 'BF_3DMOUSE_LIB', 'BF_3DMOUSE_LIBPATH', 'BF_3DMOUSE_LIB_STATIC' ] # Have options here that scons expects to be lists @@ -291,6 +291,7 @@ def read_opts(env, cfg, args): (BoolVariable('WITH_BF_FFMPEG', 'Use FFMPEG if true', False)), ('BF_FFMPEG', 'FFMPEG base path', ''), ('BF_FFMPEG_LIB', 'FFMPEG library', ''), + ('BF_FFMPEG_DLL', 'FFMPEG dll libraries to be installed', ''), ('BF_FFMPEG_EXTRA', 'FFMPEG flags that must be preserved', ''), ('BF_FFMPEG_INC', 'FFMPEG includes', ''), -- cgit v1.2.3 From df6dfb93b2a8194b3e96167e1b5eba54b07882c9 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 3 Aug 2011 11:10:19 +0000 Subject: Switch windows buildbot to new FFmpeg 0.8.1. Hope it'll work because i haven't got buildbot slave by hand. --- build_files/buildbot/slave_compile.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py index e74d889c243..5aa39db68f9 100644 --- a/build_files/buildbot/slave_compile.py +++ b/build_files/buildbot/slave_compile.py @@ -108,5 +108,29 @@ else: sys.exit(0) else: + # Switch to new FFmpeg library + if builder.find('win') != -1: + if builder.find('win32') != -1: + LCGDIR = '#../lib/windows' + elif builder.find('win64') != -1: + LCGDIR = '#../lib/win64' + + all_ffmpeg_libs = ['avcodec-53', + 'avdevice-53', + 'avformat-53', + 'avutil-51', + 'swscale-2'] + + ffmpeg_lib = [] + ffmpeg_dll = [] + + for lib in all_ffmpeg_libs: + ffmpeg_lib.append(lib + '.lib') + ffmpeg_dll.append('${BF_FFMPEG_LIBPATH}/' + lib + '.lib') + + scons_options.append('BF_FFMPEG=' + LCGDIR + '/ffmpeg-0.8') + scons_options.append('BF_FFMPEG_LIB=' + (' '.join(ffmpeg_lib))) + scons_options.append('BF_FFMPEG_DLL=' + (' '.join(ffmpeg_dll))) + retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options) sys.exit(retcode) -- cgit v1.2.3 From f1fb54e126824ff38b8bf26fa80f3f46c886bd45 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 3 Aug 2011 11:47:03 +0000 Subject: Switch slave_pack to use new FFmpeg for windows. --- build_files/buildbot/slave_pack.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/build_files/buildbot/slave_pack.py b/build_files/buildbot/slave_pack.py index 4c19b723fc8..3a3fffc02b4 100644 --- a/build_files/buildbot/slave_pack.py +++ b/build_files/buildbot/slave_pack.py @@ -72,6 +72,30 @@ if builder.find('scons') != -1: retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options) sys.exit(retcode) else: + # Switch to new FFmpeg library + if builder.find('win') != -1: + if builder.find('win32') != -1: + LCGDIR = '#../lib/windows' + elif builder.find('win64') != -1: + LCGDIR = '#../lib/win64' + + all_ffmpeg_libs = ['avcodec-53', + 'avdevice-53', + 'avformat-53', + 'avutil-51', + 'swscale-2'] + + ffmpeg_lib = [] + ffmpeg_dll = [] + + for lib in all_ffmpeg_libs: + ffmpeg_lib.append(lib + '.lib') + ffmpeg_dll.append('${BF_FFMPEG_LIBPATH}/' + lib + '.lib') + + scons_options.append('BF_FFMPEG=' + LCGDIR + '/ffmpeg-0.8') + scons_options.append('BF_FFMPEG_LIB=' + (' '.join(ffmpeg_lib))) + scons_options.append('BF_FFMPEG_DLL=' + (' '.join(ffmpeg_dll))) + retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options) sys.exit(retcode) -- cgit v1.2.3 From aac8bab1729e55f0e77ca43373d44d614f2cb828 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 3 Aug 2011 12:20:07 +0000 Subject: Fixing terrible typo. --- build_files/buildbot/slave_compile.py | 2 +- build_files/buildbot/slave_pack.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py index 5aa39db68f9..55e418ec733 100644 --- a/build_files/buildbot/slave_compile.py +++ b/build_files/buildbot/slave_compile.py @@ -126,7 +126,7 @@ else: for lib in all_ffmpeg_libs: ffmpeg_lib.append(lib + '.lib') - ffmpeg_dll.append('${BF_FFMPEG_LIBPATH}/' + lib + '.lib') + ffmpeg_dll.append('${BF_FFMPEG_LIBPATH}/' + lib + '.dll') scons_options.append('BF_FFMPEG=' + LCGDIR + '/ffmpeg-0.8') scons_options.append('BF_FFMPEG_LIB=' + (' '.join(ffmpeg_lib))) diff --git a/build_files/buildbot/slave_pack.py b/build_files/buildbot/slave_pack.py index 3a3fffc02b4..fd3ff1fbee7 100644 --- a/build_files/buildbot/slave_pack.py +++ b/build_files/buildbot/slave_pack.py @@ -90,7 +90,7 @@ if builder.find('scons') != -1: for lib in all_ffmpeg_libs: ffmpeg_lib.append(lib + '.lib') - ffmpeg_dll.append('${BF_FFMPEG_LIBPATH}/' + lib + '.lib') + ffmpeg_dll.append('${BF_FFMPEG_LIBPATH}/' + lib + '.dll') scons_options.append('BF_FFMPEG=' + LCGDIR + '/ffmpeg-0.8') scons_options.append('BF_FFMPEG_LIB=' + (' '.join(ffmpeg_lib))) -- cgit v1.2.3 From 36887bbc8205daa96b4ee3844a14ec5543f1f051 Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Wed, 3 Aug 2011 12:57:38 +0000 Subject: Add BF_BITNESS for win32/win64 --- build_files/buildbot/slave_compile.py | 4 ++++ build_files/buildbot/slave_pack.py | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py index 55e418ec733..9dd39ccd308 100644 --- a/build_files/buildbot/slave_compile.py +++ b/build_files/buildbot/slave_compile.py @@ -108,12 +108,14 @@ else: sys.exit(0) else: + bitness = '32' # Switch to new FFmpeg library if builder.find('win') != -1: if builder.find('win32') != -1: LCGDIR = '#../lib/windows' elif builder.find('win64') != -1: LCGDIR = '#../lib/win64' + bitness = '64' all_ffmpeg_libs = ['avcodec-53', 'avdevice-53', @@ -132,5 +134,7 @@ else: scons_options.append('BF_FFMPEG_LIB=' + (' '.join(ffmpeg_lib))) scons_options.append('BF_FFMPEG_DLL=' + (' '.join(ffmpeg_dll))) + scons_options.append('BF_BITNESS='+bitness) + retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options) sys.exit(retcode) diff --git a/build_files/buildbot/slave_pack.py b/build_files/buildbot/slave_pack.py index fd3ff1fbee7..e779b10bd2a 100644 --- a/build_files/buildbot/slave_pack.py +++ b/build_files/buildbot/slave_pack.py @@ -72,12 +72,14 @@ if builder.find('scons') != -1: retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options) sys.exit(retcode) else: + bitness = '32' # Switch to new FFmpeg library if builder.find('win') != -1: if builder.find('win32') != -1: LCGDIR = '#../lib/windows' elif builder.find('win64') != -1: LCGDIR = '#../lib/win64' + bitness = '64' all_ffmpeg_libs = ['avcodec-53', 'avdevice-53', @@ -96,6 +98,8 @@ if builder.find('scons') != -1: scons_options.append('BF_FFMPEG_LIB=' + (' '.join(ffmpeg_lib))) scons_options.append('BF_FFMPEG_DLL=' + (' '.join(ffmpeg_dll))) + scons_options.append('BF_BITNESS='+bitness) + retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options) sys.exit(retcode) -- cgit v1.2.3 From 289ef16fcf94573e8bef9def40a3f48afaf3077c Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Wed, 3 Aug 2011 13:00:11 +0000 Subject: Add win64_scons builder --- build_files/buildbot/master.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/build_files/buildbot/master.cfg b/build_files/buildbot/master.cfg index fd712f1b832..1e70ec5e13e 100644 --- a/build_files/buildbot/master.cfg +++ b/build_files/buildbot/master.cfg @@ -116,6 +116,7 @@ add_builder(c, 'linux_x86_64_scons', '', generic_builder) add_builder(c, 'salad_linux_x86_64_scons', '', generic_builder, 'soc-2011-salad') add_builder(c, 'win32_scons', 'windows', generic_builder) add_builder(c, 'salad_win32_scons', 'windows', generic_builder, 'soc-2011-salad') +add_builder(c, 'win64_scons', 'windows', generic_builder) #add_builder(c, 'freebsd_i386_cmake', '', generic_builder) #add_builder(c, 'freebsd_x86_64_cmake', '', generic_builder) -- cgit v1.2.3 From 01b105faa5a11cbb8f3cf2cc09430b2d1218e6fd Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 3 Aug 2011 13:31:33 +0000 Subject: Cmake: compile with NDOF default off. This is a dependency on code that's not in our svn. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d104ebfcea..aba96f6dd85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,7 +179,7 @@ option(WITH_LZO "Enable fast LZO compression (used for pointcache)" ON option(WITH_LZMA "Enable best LZMA compression, (used for pointcache)" ON) # Misc -option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON) +option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" OFF) option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON) if(UNIX AND NOT APPLE) option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON) -- cgit v1.2.3 From d795a78cb72d4c002af321dffde470dc5e3b267f Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Wed, 3 Aug 2011 14:04:48 +0000 Subject: Default to False for WITH_BF_3DMOUSE, since needs separate package installed. --- build_files/scons/config/darwin-config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py index 4a4bc4acd67..00b0c6ebf00 100644 --- a/build_files/scons/config/darwin-config.py +++ b/build_files/scons/config/darwin-config.py @@ -266,7 +266,7 @@ elif MACOSX_ARCHITECTURE == 'x86_64': BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-msse2'] # SpaceNavigator and related 3D mice -WITH_BF_3DMOUSE = True +WITH_BF_3DMOUSE = False ############################################################################# ################### various compile settings and flags ################## -- cgit v1.2.3 From 48a699d15bf2c2cf366b4361a24bda55fe5bbd3e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 3 Aug 2011 14:18:02 +0000 Subject: enable NDOF by default with cmake again, but check if it can be found on OSX, if not disable. I cant test this but at least if I made a mistake it will just not find the SDK and disable. an osx dev needs to test. --- CMakeLists.txt | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aba96f6dd85..a0a0359d8d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,7 +179,7 @@ option(WITH_LZO "Enable fast LZO compression (used for pointcache)" ON option(WITH_LZMA "Enable best LZMA compression, (used for pointcache)" ON) # Misc -option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" OFF) +option(WITH_INPUT_NDOF "Enable NDOF input devices (SpaceNavigator and friends)" ON) option(WITH_RAYOPTIMIZATION "Enable use of SIMD (SSE) optimizations for the raytracer" ON) if(UNIX AND NOT APPLE) option(WITH_INSTALL_PORTABLE "Install redistributeable runtime, otherwise install into CMAKE_INSTALL_PREFIX" ON) @@ -998,9 +998,24 @@ elseif(APPLE) elseif(WITH_CODEC_QUICKTIME) set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -framework QuickTime") endif() + + # XXX - SOME MAC DEV PLEASE TEST WITH THE SDK INSTALLED! + # ALSO SHOULD BE MOVED INTO OWN MODULE WHEN FUNCTIONAL + if(WITH_INPUT_NDOF) + # This thread it *should* work and check the framework - campbell + # http://www.cmake.org/pipermail/cmake/2005-December/007740.html + find_library(3D_CONNEXION_CLIENT_LIBRARY + NAMES 3DconnexionClient + ) + if(NOT 3D_CONNEXION_CLIENT_LIBRARY) + set(WITH_INPUT_NDOF OFF) + endif() + endif() + else() set(PLATFORM_CFLAGS "-pipe -funsigned-char") set(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime") + set(WITH_INPUT_NDOF OFF) # unsupported endif() if(WITH_OPENCOLLADA) -- cgit v1.2.3 From 9eef0646d4fc5344e85e8e4eae63795ffd4b766b Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 3 Aug 2011 14:21:49 +0000 Subject: Crash in MMB moves (etc): commit of today was reading NULL pointer. --- source/blender/editors/transform/transform_generics.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index f8df4e4ee75..c81c398e696 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -887,6 +887,7 @@ void resetTransRestrictions(TransInfo *t) t->flag &= ~T_ALL_RESTRICTIONS; } +/* the *op can be NULL */ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) { Scene *sce = CTX_data_scene(C); @@ -1015,7 +1016,7 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) } /* initialize UV transform from */ - if (RNA_struct_find_property(op->ptr, "correct_uv")) { + if (op && RNA_struct_find_property(op->ptr, "correct_uv")) { if(RNA_property_is_set(op->ptr, "correct_uv")) { if(RNA_boolean_get(op->ptr, "correct_uv")) { t->settings->uvcalc_flag |= UVCALC_TRANSFORM_CORRECT; -- cgit v1.2.3 From 79c87852d2a2b07ba3cb411e00fd0fb4aaee008a Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Wed, 3 Aug 2011 17:58:06 +0000 Subject: Add .py extension if it is missing from keymap file. This is for bug #28141 While not really a bug, it makes it a lot easyer to use if it has the exension. (Isn't hidden from the user when they try to load it...) Kent --- release/scripts/startup/bl_ui/space_userpref_keymap.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_userpref_keymap.py b/release/scripts/startup/bl_ui/space_userpref_keymap.py index 8fed3a934d9..585c3cffcb9 100644 --- a/release/scripts/startup/bl_ui/space_userpref_keymap.py +++ b/release/scripts/startup/bl_ui/space_userpref_keymap.py @@ -592,6 +592,9 @@ class WM_OT_keyconfig_export(bpy.types.Operator): if not self.filepath: raise Exception("Filepath not set") + if not self.filepath.endswith('.py'): + self.filepath += '.py' + f = open(self.filepath, "w") if not f: raise Exception("Could not open file") -- cgit v1.2.3 From e5e6f91856efe3d78eab747c25be4e1d0a5988ef Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 4 Aug 2011 01:56:36 +0000 Subject: fix [#28114] Render Crash existing check for driver to use GIL was not thread safe and could cause, details in the report. This bug was caused by a check to avoid hanging, a fix for [#27683] that worked in 2.4x because the UI didn't use python to draw while rendering. Apply a different fix for [#27683], when calling an operator, call PyEval_SaveThread(), then PyEval_RestoreThread() so the GIL can be aquired by threads started by the operator - in this case bake starting a thread that evaluates drivers. --- source/blender/python/intern/bpy_driver.c | 17 ++++++++++------- source/blender/python/intern/bpy_operator.c | 21 ++++++++++++++++++++- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index bcd5df97c2c..d68fd9a9111 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -41,8 +41,6 @@ #include "bpy_driver.h" -#include "../generic/py_capi_utils.h" - /* for pydrivers (drivers using one-line Python expressions to express relationships between targets) */ PyObject *bpy_pydriver_Dict= NULL; @@ -89,7 +87,7 @@ int bpy_pydriver_create_dict(void) void BPY_driver_reset(void) { PyGILState_STATE gilstate; - int use_gil= !PYC_INTERPRETER_ACTIVE; + int use_gil= 1; /* !PYC_INTERPRETER_ACTIVE; */ if(use_gil) gilstate= PyGILState_Ensure(); @@ -120,9 +118,14 @@ static void pydriver_error(ChannelDriver *driver) /* This evals py driver expressions, 'expr' is a Python expression that * should evaluate to a float number, which is returned. * - * note: PyGILState_Ensure() isnt always called because python can call the - * bake operator which intern starts a thread which calls scene update which - * does a driver update. to avoid a deadlock check PYC_INTERPRETER_ACTIVE if PyGILState_Ensure() is needed. + * (old)note: PyGILState_Ensure() isnt always called because python can call + * the bake operator which intern starts a thread which calls scene update + * which does a driver update. to avoid a deadlock check PYC_INTERPRETER_ACTIVE + * if PyGILState_Ensure() is needed - see [#27683] + * + * (new)note: checking if python is running is not threadsafe [#28114] + * now release the GIL on python operator execution instead, using + * PyEval_SaveThread() / PyEval_RestoreThread() so we dont lock up blender. */ float BPY_driver_exec(ChannelDriver *driver) { @@ -149,7 +152,7 @@ float BPY_driver_exec(ChannelDriver *driver) return 0.0f; } - use_gil= !PYC_INTERPRETER_ACTIVE; + use_gil= 1; /* !PYC_INTERPRETER_ACTIVE; */ if(use_gil) gilstate= PyGILState_Ensure(); diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index b8883e655f2..4a17c45ae38 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -55,6 +55,10 @@ #include "BKE_report.h" #include "BKE_context.h" +/* so operators called can spawn threads which aquire the GIL */ +#define BPY_RELEASE_GIL + + static PyObject *pyop_poll(PyObject *UNUSED(self), PyObject *args) { wmOperatorType *ot; @@ -219,7 +223,22 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args) reports= MEM_mallocN(sizeof(ReportList), "wmOperatorReportList"); BKE_reports_init(reports, RPT_STORE | RPT_OP_HOLD); /* own so these dont move into global reports */ - operator_ret= WM_operator_call_py(C, ot, context, &ptr, reports); +#ifdef BPY_RELEASE_GIL + /* release GIL, since a thread could be started from an operator + * that updates a driver */ + /* note: I havve not seen any examples of code that does this + * so it may not be officially supported but seems to work ok. */ + { + PyThreadState *ts= PyEval_SaveThread(); +#endif + + operator_ret= WM_operator_call_py(C, ot, context, &ptr, reports); + +#ifdef BPY_RELEASE_GIL + /* regain GIL */ + PyEval_RestoreThread(ts); + } +#endif error_val= BPy_reports_to_error(reports, PyExc_RuntimeError, FALSE); -- cgit v1.2.3 From a6fed14da4569380cecac3154482d0e6e54d1433 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Thu, 4 Aug 2011 03:14:00 +0000 Subject: stricter guards for disabling NDOF code (will test in 3.. 2.. 1..) --- intern/ghost/intern/GHOST_NDOFManagerWin32.cpp | 6 +++- intern/ghost/intern/GHOST_NDOFManagerWin32.h | 8 +++-- intern/ghost/intern/GHOST_SystemWin32.cpp | 43 ++++++++++++++------------ 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp index 57d84ec14d4..fd62e845f7d 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.cpp @@ -22,7 +22,9 @@ * * ***** END GPL LICENSE BLOCK ***** */ - + +#ifdef WITH_INPUT_NDOF // use contents of this file + #include "GHOST_NDOFManagerWin32.h" @@ -39,3 +41,5 @@ bool GHOST_NDOFManagerWin32::available() // always available since RawInput is built into Windows return true; } + +#endif // WITH_INPUT_NDOF diff --git a/intern/ghost/intern/GHOST_NDOFManagerWin32.h b/intern/ghost/intern/GHOST_NDOFManagerWin32.h index 31f7e074cd6..9f3eddeb3c8 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerWin32.h +++ b/intern/ghost/intern/GHOST_NDOFManagerWin32.h @@ -22,10 +22,13 @@ * * ***** END GPL LICENSE BLOCK ***** */ - + + #ifndef _GHOST_NDOFMANAGERWIN32_H_ #define _GHOST_NDOFMANAGERWIN32_H_ +#ifdef WITH_INPUT_NDOF + #include "GHOST_NDOFManager.h" @@ -37,4 +40,5 @@ public: }; -#endif +#endif // WITH_INPUT_NDOF +#endif // #include guard diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index bbf8efeaee3..38f3985b139 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -62,7 +62,6 @@ #endif #endif -#include "GHOST_Debug.h" #include "GHOST_DisplayManagerWin32.h" #include "GHOST_EventButton.h" #include "GHOST_EventCursor.h" @@ -72,7 +71,10 @@ #include "GHOST_TimerManager.h" #include "GHOST_WindowManager.h" #include "GHOST_WindowWin32.h" + +#ifdef WITH_INPUT_NDOF #include "GHOST_NDOFManagerWin32.h" +#endif // Key code values not found in winuser.h #ifndef VK_MINUS @@ -127,22 +129,32 @@ static void initRawInput() { - RAWINPUTDEVICE devices[2]; - memset(devices, 0, 2 * sizeof(RAWINPUTDEVICE)); +#ifdef WITH_INPUT_NDOF +#define DEVICE_COUNT 2 +#else +#define DEVICE_COUNT 1 +#endif - // multi-axis mouse (SpaceNavigator, etc.) - devices[0].usUsagePage = 0x01; - devices[0].usUsage = 0x08; + RAWINPUTDEVICE devices[DEVICE_COUNT]; + memset(devices, 0, DEVICE_COUNT * sizeof(RAWINPUTDEVICE)); // Initiates WM_INPUT messages from keyboard // That way GHOST can retrieve true keys + devices[0].usUsagePage = 0x01; + devices[0].usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */ + +#ifdef WITH_INPUT_NDOF + // multi-axis mouse (SpaceNavigator, etc.) devices[1].usUsagePage = 0x01; - devices[1].usUsage = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */ + devices[1].usUsage = 0x08; +#endif - if (RegisterRawInputDevices(devices, 2, sizeof(RAWINPUTDEVICE))) - puts("registered for RawInput (spacenav & keyboard)"); + if (RegisterRawInputDevices(devices, DEVICE_COUNT, sizeof(RAWINPUTDEVICE))) + ; // yay! else printf("could not register for RawInput: %d\n", (int)GetLastError()); + +#undef DEVICE_COUNT } GHOST_SystemWin32::GHOST_SystemWin32() @@ -808,6 +820,7 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) case 1: // translation { short* axis = (short*)(data + 1); + // massage into blender view coords (same goes for rotation) short t[3] = {axis[0], -axis[2], axis[1]}; m_ndofManager->updateTranslation(t, now); @@ -830,14 +843,6 @@ bool GHOST_SystemWin32::processNDOF(RAWINPUT const& raw) } case 3: // buttons { -#if 0 - // I'm getting garbage bits -- examine whole report: - printf("ndof: HID report for buttons ["); - for (int i = 0; i < raw.data.hid.dwSizeHid; ++i) - printf(" %02X", data[i]); - printf(" ]\n"); -#endif - int button_bits; memcpy(&button_bits, data + 1, sizeof(button_bits)); m_ndofManager->updateButtons(button_bits, now); @@ -892,12 +897,12 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, GHOST_PRINT(" key ignored\n") } break; - case RIM_TYPEHID: #ifdef WITH_INPUT_NDOF + case RIM_TYPEHID: if (system->processNDOF(raw)) eventHandled = true; -#endif break; +#endif } break; } -- cgit v1.2.3 From af786843b05ce434d46c2036643aefb7bbaa92b6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 4 Aug 2011 08:46:17 +0000 Subject: patch from jensverwiebe to disable ndof if header is not found. --- SConstruct | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/SConstruct b/SConstruct index 529f6daeef1..4f920190276 100644 --- a/SConstruct +++ b/SConstruct @@ -253,6 +253,15 @@ if 'blenderlite' in B.targets: if k not in B.arguments: env[k] = v +# detect presence of 3D_CONNEXION_CLIENT_LIBRARY for OSX +if env['OURPLATFORM']=='darwin': + envi = Environment() + conf = Configure(envi) + if not conf.CheckCHeader('ConnexionClientAPI.h'): # CheckCXXHeader if it is c++ ! + print "3D_CONNEXION_CLIENT_LIBRARY not found, disabling WITH_BF_3DMOUSE" # avoid build errors ! + env['WITH_BF_3DMOUSE'] = 0 + envi = conf.Finish() + if env['WITH_BF_OPENMP'] == 1: if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): -- cgit v1.2.3 From 0578d55f1ef700b96ae8a8c33c1f8b54a200c7d9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 4 Aug 2011 09:47:09 +0000 Subject: when appending with a NULL context dont print warnigns about scene not being set - was annoying for BGE LibLoad. --- source/blender/blenloader/intern/readfile.c | 36 ++++++++++++++++------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 0633794c6ed..0a24dfaed72 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -13047,10 +13047,10 @@ static void append_do_cursor(Scene *scene, Library *curlib, short flag) } } +/* Context == NULL signifies not to do any scene manipulation */ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, int idcode, short flag) { Main *mainvar; - Scene *scene= CTX_data_scene(C); Library *curlib; /* make main consistent */ @@ -13079,22 +13079,28 @@ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, in lib_verify_nodetree(mainvar, FALSE); fix_relpaths_library(G.main->name, mainvar); /* make all relative paths, relative to the open blend file */ - /* give a base to loose objects. If group append, do it for objects too */ - if(scene) { - const short is_link= (flag & FILE_LINK) != 0; - if(idcode==ID_SCE) { - /* dont instance anything when linking in scenes, assume the scene its self instances the data */ - } - else { - give_base_to_objects(mainvar, scene, curlib, idcode, is_link); + if(C) { + Scene *scene= CTX_data_scene(C); - if (flag & FILE_GROUP_INSTANCE) { - give_base_to_groups(mainvar, scene); + /* give a base to loose objects. If group append, do it for objects too */ + if(scene) { + const short is_link= (flag & FILE_LINK) != 0; + if(idcode==ID_SCE) { + /* dont instance anything when linking in scenes, assume the scene its self instances the data */ + } + else { + give_base_to_objects(mainvar, scene, curlib, idcode, is_link); + + if (flag & FILE_GROUP_INSTANCE) { + give_base_to_groups(mainvar, scene); + } } } - } - else { - printf("library_append_end, scene is NULL (objects wont get bases)\n"); + else { + printf("library_append_end, scene is NULL (objects wont get bases)\n"); + } + + append_do_cursor(scene, curlib, flag); } /* has been removed... erm, why? s..ton) */ /* 20040907: looks like they are give base already in append_named_part(); -Nathan L */ @@ -13105,8 +13111,6 @@ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, in blo_freefiledata( *fd ); *fd = NULL; } - - append_do_cursor(scene, curlib, flag); } void BLO_library_append_end(const bContext *C, struct Main *mainl, BlendHandle** bh, int idcode, short flag) -- cgit v1.2.3 From f3c40df5e334f8a1f106fe71e44c8035ddcac7b1 Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Thu, 4 Aug 2011 09:47:40 +0000 Subject: rst API doc fixes: literalincluding bge.texture and bge.constraints examples + bgl fixes --- doc/python_api/rst/bge.constraints.rst | 4 ++++ doc/python_api/rst/bge.texture.rst | 4 ++++ doc/python_api/rst/bgl.rst | 7 +++++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/python_api/rst/bge.constraints.rst b/doc/python_api/rst/bge.constraints.rst index 12ce8617457..da0a358dfed 100644 --- a/doc/python_api/rst/bge.constraints.rst +++ b/doc/python_api/rst/bge.constraints.rst @@ -2,6 +2,10 @@ Physics Constraints (bge.constraints) ===================================== +.. module:: bge.constraints + +.. literalinclude:: ../examples/bge.constraints.py + .. function:: createConstraint(physicsid, physicsid2, constrainttype, [pivotX, pivotY, pivotZ, [axisX, axisY, axisZ, [flag]]]]) Creates a constraint. diff --git a/doc/python_api/rst/bge.texture.rst b/doc/python_api/rst/bge.texture.rst index f3e9f98dded..0b32c7a393b 100644 --- a/doc/python_api/rst/bge.texture.rst +++ b/doc/python_api/rst/bge.texture.rst @@ -36,6 +36,10 @@ When the texture object is deleted, the new texture is deleted and the old textu .. module:: bge.texture +.. literalinclude:: ../examples/bge.texture.py + +.. literalinclude:: ../examples/bge.texture.1.py + .. class:: VideoFFmpeg(file [, capture=-1, rate=25.0, width=0, height=0]) FFmpeg video source diff --git a/doc/python_api/rst/bgl.rst b/doc/python_api/rst/bgl.rst index 236bfafb295..5f3158bf5dd 100644 --- a/doc/python_api/rst/bgl.rst +++ b/doc/python_api/rst/bgl.rst @@ -15,7 +15,7 @@ collections of tutorials. The "red book": "I{OpenGL Programming Guide: The Official Guide to Learning OpenGL}" and the online NeHe tutorials are two of the best resources. -..note:: +.. note:: You can use the :class:`Image` type to load and set textures. See :class:`Image.gl_load` and :class:`Image.gl_load`, for example. @@ -1386,7 +1386,7 @@ OpenGL}" and the online NeHe tutorials are two of the best resources. bgl.glGetFloatv(bgl.GL_MODELVIEW_MATRIX, view_matrix) f = 1.0 / view_matrix[0] - # Instead of the usual glRasterPos2i(xval, yval) + # Instead of the usual glRasterPos2i(xval, yval) bgl.glRasterPos2f(xval * f, yval * f) @@ -1848,10 +1848,13 @@ class Buffer: .. code-block:: python import bgl + myByteBuffer = bgl.Buffer(bgl.GL_BYTE, [32, 32]) bgl.glGetPolygonStipple(myByteBuffer) + print(myByteBuffer.dimensions) print(myByteBuffer.to_list()) + sliceBuffer = myByteBuffer[0:16] print(sliceBuffer) -- cgit v1.2.3 From 9da70f74d37c7c0001a2705afc8fe5044f63bb0a Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Thu, 4 Aug 2011 10:05:14 +0000 Subject: UserPref/Node editor feature: Change the level of noodle curving. Some people like curved lines, other hate them. This commit will let the user change the level of curving. In UserPreferences=>Themes=>Node editor=>Noodle curving the level can be modified. Allowed range is 0-10 with the default on 5 The patch will default everything to the way blender works ATM. File subversion has been increased otherwise older 258 files got straight lines. The data is stored in the ThemeSpace.noodle_curving the bezierdrawing is done in the drawnode. Also tested the Line cut tool --- source/blender/editors/include/UI_resources.h | 4 +++- source/blender/editors/interface/resources.c | 14 ++++++++++++-- source/blender/editors/space_node/drawnode.c | 4 ++-- source/blender/makesdna/DNA_userdef_types.h | 2 +- source/blender/makesrna/intern/rna_userdef.c | 7 +++++++ 5 files changed, 25 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 2311aafbb17..d0c2b387445 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -242,7 +242,9 @@ enum { TH_DRAWEXTRA_EDGELEN, TH_DRAWEXTRA_FACEAREA, - TH_DRAWEXTRA_FACEANG + TH_DRAWEXTRA_FACEANG, + + TH_NODE_CURVING }; /* XXX WARNING: previous is saved in file, so do not change order! */ diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 0c755180b3a..f58383830cb 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -360,7 +360,9 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo cp= ts->syntaxv; break; case TH_NODE_GROUP: cp= ts->syntaxc; break; - + case TH_NODE_CURVING: + cp= &ts->noodle_curving; break; + case TH_SEQ_MOVIE: cp= ts->movie; break; case TH_SEQ_IMAGE: @@ -787,6 +789,7 @@ void ui_theme_init_default(void) SETCOL(btheme->tnode.syntaxb, 108, 105, 111, 255); /* operator */ SETCOL(btheme->tnode.syntaxv, 104, 106, 117, 255); /* generator */ SETCOL(btheme->tnode.syntaxc, 105, 117, 110, 255); /* group */ + btheme->tnode.noodle_curving = 5; /* space logic */ btheme->tlogic= btheme->tv3d; @@ -1553,7 +1556,14 @@ void init_userdef_do_versions(void) /* clear "AUTOKEY_FLAG_ONLYKEYINGSET" flag from userprefs, so that it doesn't linger around from old configs like a ghost */ U.autokey_flag &= ~AUTOKEY_FLAG_ONLYKEYINGSET; } - + + if (bmain->versionfile < 258 || (bmain->versionfile == 258 && bmain->subversionfile < 2)) { + bTheme *btheme; + for(btheme= U.themes.first; btheme; btheme= btheme->next) { + btheme->tnode.noodle_curving = 5; + } + } + /* GL Texture Garbage Collection (variable abused above!) */ if (U.textimeout == 0) { U.texcollectrate = 60; diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 50e657bbb61..c32d05e9c30 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -1768,8 +1768,8 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa vec[3][0]= snode->mx; vec[3][1]= snode->my; } - - dist= 0.5f*ABS(vec[0][0] - vec[3][0]); + + dist= UI_GetThemeValue(TH_NODE_CURVING)*0.10f*ABS(vec[0][0] - vec[3][0]); /* check direction later, for top sockets */ vec[1][0]= vec[0][0]+dist; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 0bf812f1ec2..aa6da3aaeca 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -220,7 +220,7 @@ typedef struct ThemeSpace { char console_cursor[4]; char vertex_size, outline_width, facedot_size; - char bpad; + char noodle_curving; char syntaxl[4], syntaxn[4], syntaxb[4]; // syntax for textwindow and nodes char syntaxv[4], syntaxc[4]; diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 7a9193571fd..a1a99c34e70 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -1351,6 +1351,13 @@ static void rna_def_userdef_theme_space_node(BlenderRNA *brna) RNA_def_property_array(prop, 3); RNA_def_property_ui_text(prop, "Group Node", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop= RNA_def_property(srna, "noodle_curving", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "noodle_curving"); + RNA_def_property_int_default(prop, 5); + RNA_def_property_range(prop, 0, 10); + RNA_def_property_ui_text(prop, "Noodle curving", "Curving of the noodle"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_theme_space_logic(BlenderRNA *brna) -- cgit v1.2.3 From cdea64e32cbe1a8b9c9312b04cf15b0ac3daf685 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 4 Aug 2011 11:27:13 +0000 Subject: remove append to cursor code, wasnt used and made some naive assumptions about object locations. --- source/blender/blenloader/intern/readfile.c | 49 ----------------------------- source/blender/makesdna/DNA_space_types.h | 2 +- 2 files changed, 1 insertion(+), 50 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 0a24dfaed72..d60ac492f97 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -12999,53 +12999,6 @@ Main* BLO_library_append_begin(const bContext *C, BlendHandle** bh, const char * return library_append_begin(C, &fd, filepath); } -static void append_do_cursor(Scene *scene, Library *curlib, short flag) -{ - Base *centerbase; - Object *ob; - float *curs, centerloc[3], vec[3], min[3], max[3]; - int count= 0; - - /* when not linking (appending)... */ - if(flag & FILE_LINK) - return; - - /* we're not appending at cursor */ - if((flag & FILE_ATCURSOR) == 0) - return; - - /* find the center of everything appended */ - INIT_MINMAX(min, max); - centerbase= (scene->base.first); - while(centerbase) { - if(centerbase->object->id.lib==curlib && centerbase->object->parent==NULL) { - VECCOPY(vec, centerbase->object->loc); - DO_MINMAX(vec, min, max); - count++; - } - centerbase= centerbase->next; - } - /* we haven't found any objects to move to cursor */ - if(!count) - return; - - /* move from the center of the appended objects to cursor */ - mid_v3_v3v3(centerloc, min, max); - curs = scene->cursor; - VECSUB(centerloc,curs,centerloc); - - /* now translate the center of the objects */ - centerbase= (scene->base.first); - while(centerbase) { - if(centerbase->object->id.lib==curlib && centerbase->object->parent==NULL) { - ob= centerbase->object; - ob->loc[0] += centerloc[0]; - ob->loc[1] += centerloc[1]; - ob->loc[2] += centerloc[2]; - } - centerbase= centerbase->next; - } -} /* Context == NULL signifies not to do any scene manipulation */ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, int idcode, short flag) @@ -13099,8 +13052,6 @@ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, in else { printf("library_append_end, scene is NULL (objects wont get bases)\n"); } - - append_do_cursor(scene, curlib, flag); } /* has been removed... erm, why? s..ton) */ /* 20040907: looks like they are give base already in append_named_part(); -Nathan L */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index ff9f2269f53..1549bd71748 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -703,7 +703,7 @@ enum FileSortTypeE { #define FILE_HIDE_DOT (1<<3) #define FILE_AUTOSELECT (1<<4) #define FILE_ACTIVELAY (1<<5) -#define FILE_ATCURSOR (1<<6) +/* #define FILE_ATCURSOR (1<<6) */ /* deprecated */ #define FILE_DIRSEL_ONLY (1<<7) #define FILE_FILTER (1<<8) #define FILE_BOOKMARKS (1<<9) -- cgit v1.2.3 From 26fe903502368f1a255f44bbc75e308e08a5d659 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Thu, 4 Aug 2011 12:19:50 +0000 Subject: Typo when reading line curving. The subversion is 1, so smaller than 1 should be converted --- source/blender/editors/interface/resources.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index f58383830cb..32e87b3a793 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1557,7 +1557,7 @@ void init_userdef_do_versions(void) U.autokey_flag &= ~AUTOKEY_FLAG_ONLYKEYINGSET; } - if (bmain->versionfile < 258 || (bmain->versionfile == 258 && bmain->subversionfile < 2)) { + if (bmain->versionfile < 258 || (bmain->versionfile == 258 && bmain->subversionfile < 1)) { bTheme *btheme; for(btheme= U.themes.first; btheme; btheme= btheme->next) { btheme->tnode.noodle_curving = 5; -- cgit v1.2.3 From 36bf4385c2c2a1d3f462d30138b6815287d8e548 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 4 Aug 2011 13:22:38 +0000 Subject: fix for building with clang. makesrna wasnt linking with sqrt --- source/blender/makesrna/intern/rna_object_api.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index 21fa28af01a..d48f1c93da8 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -45,9 +45,9 @@ // #include "ED_mesh.h" -#include "BLI_math.h" #ifdef RNA_RUNTIME +#include "BLI_math.h" #include "BKE_main.h" #include "BKE_global.h" @@ -544,7 +544,8 @@ void RNA_api_object(StructRNA *srna) /* location of point for test and max distance */ parm= RNA_def_float_vector(func, "point", 3, NULL, -FLT_MAX, FLT_MAX, "", "", -1e4, 1e4); RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_float(func, "max_dist", sqrt(FLT_MAX), 0.0, FLT_MAX, "", "", 0.0, FLT_MAX); + /* default is sqrt(FLT_MAX) */ + RNA_def_float(func, "max_dist", 1.844674352395373e+19, 0.0, FLT_MAX, "", "", 0.0, FLT_MAX); /* return location and normal */ parm= RNA_def_float_vector(func, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "The location on the object closest to the point", -1e4, 1e4); -- cgit v1.2.3 From f77af0a8cef8e7be6245c6f4c52dd05f6c7a387f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 5 Aug 2011 05:26:19 +0000 Subject: change BLO_library_append_begin to take a main argument rather then a context, means the BGE doesnt need to make a new empty context just to pass as an arg. added doxygen description too. this quiets the print when the BGE does linking. --- source/blender/blenloader/BLO_readfile.h | 16 ++++++++++------ source/blender/blenloader/intern/readfile.c | 7 +++---- source/blender/python/intern/bpy_library.c | 3 ++- source/blender/windowmanager/intern/wm_operators.c | 2 +- source/gameengine/Converter/KX_BlenderSceneConverter.cpp | 14 +++++--------- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index 85d4b936c51..47931477728 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -211,7 +211,16 @@ int BLO_has_bfile_extension(char *str); */ int BLO_is_a_library(const char *path, char *dir, char *group); -struct Main* BLO_library_append_begin(const struct bContext *C, BlendHandle** bh, const char *filepath); + +/** + * Initialize the BlendHandle for appending or linking library data. + * + * @param mainvar The current main database eg G.main or CTX_data_main(C). + * @param bh A blender file handle as returned by BLO_blendhandle_from_file or BLO_blendhandle_from_memory. + * @param filepath Used for relative linking, copied to the lib->name + * @return the library Main, to be passed to BLO_library_append_named_part as mainl. + */ +struct Main* BLO_library_append_begin(struct Main *mainvar, BlendHandle** bh, const char *filepath); /** @@ -243,11 +252,6 @@ void BLO_library_append_end(const struct bContext *C, struct Main *mainl, BlendH void *BLO_library_read_struct(struct FileData *fd, struct BHead *bh, const char *blockname); -/* deprecated */ -#if 1 -void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, int idcode, short flag, struct Main *mainvar, struct Scene *scene, struct ReportList *reports); -#endif - BlendFileData* blo_read_blendafterruntime(int file, char *name, int actualsize, struct ReportList *reports); #ifdef __cplusplus diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index d60ac492f97..44c8ca97be9 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -12975,9 +12975,8 @@ static void append_id_part(FileData *fd, Main *mainvar, ID *id, ID **id_r) /* common routine to append/link something from a library */ -static Main* library_append_begin(const bContext *C, FileData **fd, const char *filepath) +static Main* library_append_begin(Main *mainvar, FileData **fd, const char *filepath) { - Main *mainvar= CTX_data_main(C); Main *mainl; /* make mains */ @@ -12993,10 +12992,10 @@ static Main* library_append_begin(const bContext *C, FileData **fd, const char * return mainl; } -Main* BLO_library_append_begin(const bContext *C, BlendHandle** bh, const char *filepath) +Main* BLO_library_append_begin(Main *mainvar, BlendHandle** bh, const char *filepath) { FileData *fd= (FileData*)(*bh); - return library_append_begin(C, &fd, filepath); + return library_append_begin(mainvar, &fd, filepath); } diff --git a/source/blender/python/intern/bpy_library.c b/source/blender/python/intern/bpy_library.c index 85bffb5a8cc..4ce3e0356e2 100644 --- a/source/blender/python/intern/bpy_library.c +++ b/source/blender/python/intern/bpy_library.c @@ -39,6 +39,7 @@ #include "BKE_library.h" #include "BKE_idcode.h" #include "BKE_report.h" +#include "BKE_context.h" #include "BLI_utildefines.h" #include "BLI_string.h" @@ -317,7 +318,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) flag_all_listbases_ids(LIB_PRE_EXISTING, 1); /* here appending/linking starts */ - mainl= BLO_library_append_begin(BPy_GetContext(), &(self->blo_handle), self->relpath); + mainl= BLO_library_append_begin(CTX_data_main(BPy_GetContext()), &(self->blo_handle), self->relpath); { int i= 0, code; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index a47dfacf358..5a05be0fefc 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1690,7 +1690,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) flag_all_listbases_ids(LIB_PRE_EXISTING, 1); /* here appending/linking starts */ - mainl = BLO_library_append_begin(C, &bh, libname); + mainl = BLO_library_append_begin(bmain, &bh, libname); if(totfiles == 0) { BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag); } diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 58089cc4b2d..b04a0d24e78 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -950,7 +950,6 @@ bool KX_BlenderSceneConverter::LinkBlendFilePath(const char *path, char *group, bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) { - bContext *C; Main *main_newlib; /* stored as a dynamic 'main' until we free it */ Main *main_tmp= NULL; /* created only for linking, then freed */ LinkNode *names = NULL; @@ -981,12 +980,10 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha } main_newlib= (Main *)MEM_callocN( sizeof(Main), "BgeMain"); - C= CTX_create(); - CTX_data_main_set(C, main_newlib); BKE_reports_init(&reports, RPT_STORE); /* here appending/linking starts */ - main_tmp = BLO_library_append_begin(C, &bpy_openlib, (char *)path); + main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); int totnames_dummy; names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode, &totnames_dummy); @@ -1000,11 +997,11 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ - BLO_library_append_end(C, main_tmp, &bpy_openlib, idcode, flag); + BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag); /* now do another round of linking for Scenes so all actions are properly loaded */ if (idcode==ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { - main_tmp = BLO_library_append_begin(C, &bpy_openlib, (char *)path); + main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); int totnames_dummy; names = BLO_blendhandle_get_datablock_names( bpy_openlib, ID_AC, &totnames_dummy); @@ -1018,12 +1015,11 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ - BLO_library_append_end(C, main_tmp, &bpy_openlib, ID_AC, flag); + BLO_library_append_end(NULL, main_tmp, &bpy_openlib, ID_AC, flag); } BLO_blendhandle_close(bpy_openlib); - - CTX_free(C); + BKE_reports_clear(&reports); /* done linking */ -- cgit v1.2.3 From 82e863bdae70b1297318aa7fd98f72cab074ef66 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 5 Aug 2011 06:06:15 +0000 Subject: fix [#28102] Typing 'C:' into the file selector's directory asks to make a new directory. --- source/blender/editors/space_file/file_ops.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 77524c7e117..d4253495e97 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -64,6 +64,7 @@ #include #include #include +#include /* for events */ #define NOTACTIVEFILE 0 @@ -1079,8 +1080,18 @@ static void file_expand_directory(bContext *C) } #ifdef WIN32 - if (sfile->params->dir[0] == '\0') + if (sfile->params->dir[0] == '\0') { get_default_root(sfile->params->dir); + } + /* change "C:" --> "C:\", [#28102] */ + else if ( (isalpha(sfile->params->dir[0]) && + (sfile->params->dir[1] == ':')) && + (sfile->params->dir[2] == '\0') + + ) { + sfile->params->dir[2]= '\\'; + sfile->params->dir[3]= '\0'; + } #endif } } -- cgit v1.2.3 From c946969bb90c177319c183e7155c6f360230ea2f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 5 Aug 2011 06:09:30 +0000 Subject: fix for possible uninitialized RNA strings, when RNA_string_get property is not found, initialize the string to "". --- source/blender/makesrna/intern/rna_access.c | 7 +++++-- source/blender/windowmanager/intern/wm_operators.c | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index e71be8c153e..f1056c86a4c 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -4007,10 +4007,13 @@ void RNA_string_get(PointerRNA *ptr, const char *name, char *value) { PropertyRNA *prop= RNA_struct_find_property(ptr, name); - if(prop) + if(prop) { RNA_property_string_get(ptr, prop, value); - else + } + else { printf("RNA_string_get: %s.%s not found.\n", ptr->type->identifier, name); + value[0]= '\0'; + } } char *RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen) diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 5a05be0fefc..7238cede2cc 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1621,7 +1621,6 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) int idcode, totfiles=0; short flag; - name[0] = '\0'; RNA_string_get(op->ptr, "filename", name); RNA_string_get(op->ptr, "directory", dir); -- cgit v1.2.3 From f48631e9a4afb8d7d4ab4e15963b38ba75605f68 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 5 Aug 2011 06:26:54 +0000 Subject: fix [#28160] Pressing Y on an image sequence to seperate the images takes them out of their meta strips dont show a popup anymore, was silly because you had to change the value for before anything was done, can use f6 redo popup instead, sequencer should eventually have a view3d operator redo panel. --- source/blender/editors/space_sequencer/sequencer_edit.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index b7a7b6b5412..6a69d32d307 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -1785,7 +1785,7 @@ static int sequencer_separate_images_exec(bContext *C, wmOperator *op) se = give_stripelem(seq, cfra); seq_new= seq_dupli_recursive(scene, scene, seq, SEQ_DUPE_UNIQUE_NAME); - BLI_addtail(&ed->seqbase, seq_new); + BLI_addtail(ed->seqbasep, seq_new); seq_new->start= start_ofs; seq_new->type= SEQ_IMAGE; @@ -1839,7 +1839,6 @@ void SEQUENCER_OT_images_separate(wmOperatorType *ot) ot->description="On image sequences strips, it return a strip for each image"; /* api callbacks */ - ot->invoke= WM_operator_props_popup; ot->exec= sequencer_separate_images_exec; ot->poll= sequencer_edit_poll; -- cgit v1.2.3 From ad7ea2f89205dd67b84ec76d70352ad56004293a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 5 Aug 2011 09:04:11 +0000 Subject: get a tad more vertical space in the toolbar. --- release/scripts/startup/bl_ui/space_view3d_toolbar.py | 10 ++++++---- source/blender/editors/curve/editfont.c | 6 +++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 91cfd22b3d6..85dd6f7da5e 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -88,8 +88,9 @@ class VIEW3D_PT_tools_objectmode(View3DPanel, bpy.types.Panel): col = layout.column(align=True) col.label(text="Shading:") - col.operator("object.shade_smooth", text="Smooth") - col.operator("object.shade_flat", text="Flat") + row = col.row(align=True) + row.operator("object.shade_smooth", text="Smooth") + row.operator("object.shade_flat", text="Flat") draw_keyframing_tools(context, layout) @@ -155,8 +156,9 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, bpy.types.Panel): col = layout.column(align=True) col.label(text="Shading:") - col.operator("mesh.faces_shade_smooth", text="Smooth") - col.operator("mesh.faces_shade_flat", text="Flat") + row = col.row(align=True) + row.operator("mesh.faces_shade_smooth", text="Smooth") + row.operator("mesh.faces_shade_flat", text="Flat") draw_repeat_tools(context, layout) diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 649ff9e953a..6c95df53d39 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -1649,10 +1649,10 @@ static int open_exec(bContext *C, wmOperator *op) VFont *font; PropertyPointerRNA *pprop; PointerRNA idptr; - char str[FILE_MAX]; - RNA_string_get(op->ptr, "filepath", str); + char filepath[FILE_MAX]; + RNA_string_get(op->ptr, "filepath", filepath); - font = load_vfont(str); + font= load_vfont(filepath); if(!font) { if(op->customdata) MEM_freeN(op->customdata); -- cgit v1.2.3 From a157112ac5c6465fd8d9518af87ce86a5250eeba Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 5 Aug 2011 10:45:32 +0000 Subject: fix for icon scaling with the DPI setting - icons were scaling by the sqrt(dpi)/8.48528, but infact they only need to be scaled by (dpi/72). - UI_icon_get_width value was being used without multiplying by dpi scale. --- source/blender/editors/include/UI_interface.h | 3 +++ source/blender/editors/interface/interface_handlers.c | 2 +- source/blender/editors/interface/interface_icons.c | 3 ++- source/blender/editors/interface/interface_widgets.c | 15 +++++++-------- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 61e19655f8d..1bae6ce0214 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -164,6 +164,9 @@ typedef struct uiLayout uiLayout; /* scale fixed button widths by this to account for DPI * 8.4852 == sqrtf(72.0f)) */ #define UI_DPI_FAC (sqrtf((float)U.dpi) / 8.48528137423857f) +#define UI_DPI_ICON_FAC (((float)U.dpi) / 72.0f) +/* 16 to copy ICON_DEFAULT_HEIGHT */ +#define UI_DPI_ICON_SIZE ((float)16 * UI_DPI_ICON_FAC) /* Button types, bits stored in 1 value... and a short even! - bits 0-4: bitnr (0-31) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index c5275ea98b5..b3272a2e3d4 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1290,7 +1290,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, sho else if(ELEM(but->type, TEX, SEARCH_MENU)) { startx += 5; if (but->flag & UI_HAS_ICON) - startx += 16; + startx += UI_DPI_ICON_SIZE; } /* mouse dragged outside the widget to the left */ diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 3bf2a9ddd02..412c0233c35 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -742,6 +742,7 @@ static DrawInfo *icon_create_drawinfo(void) return di; } +/* note!, returns unscaled by DPI, may need to multiply result by UI_DPI_ICON_FAC */ int UI_icon_get_width(int icon_id) { Icon *icon = NULL; @@ -952,7 +953,7 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al Icon *icon = NULL; DrawInfo *di = NULL; IconImage *iimg; - float fdraw_size= UI_DPI_FAC*draw_size; + float fdraw_size= UI_DPI_ICON_FAC*draw_size; int w, h; icon = BKE_icon_get(icon_id); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 25a64994f5c..d235fd0c16a 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -771,7 +771,6 @@ static void widget_draw_preview(BIFIconID icon, float UNUSED(alpha), rcti *rect) /* icons have been standardized... and this call draws in untransformed coordinates */ -#define ICON_HEIGHT UI_DPI_FAC*16.0f static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, rcti *rect) { @@ -791,15 +790,15 @@ static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, rcti *rect if(aspect != but->aspect) { /* prevent scaling up icon in pupmenu */ if (aspect < 1.0f) { - height= ICON_HEIGHT; + height= UI_DPI_ICON_SIZE; aspect = 1.0f; } else - height= ICON_HEIGHT/aspect; + height= UI_DPI_ICON_SIZE/aspect; } else - height= ICON_HEIGHT; + height= UI_DPI_ICON_SIZE; /* calculate blend color */ if ELEM4(but->type, TOG, ROW, TOGN, LISTROW) { @@ -866,7 +865,7 @@ static void ui_text_leftclip(uiFontStyle *fstyle, uiBut *but, rcti *rect) int border= (but->flag & UI_BUT_ALIGN_RIGHT)? 8: 10; int okwidth= rect->xmax-rect->xmin - border; - if (but->flag & UI_HAS_ICON) okwidth -= 16; + if (but->flag & UI_HAS_ICON) okwidth -= UI_DPI_ICON_SIZE; /* need to set this first */ uiStyleFontSet(fstyle); @@ -1149,7 +1148,7 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB if (but->flag & UI_HAS_ICON) { widget_draw_icon(but, but->icon+but->iconadd, 1.0f, rect); - rect->xmin += UI_icon_get_width(but->icon+but->iconadd); + rect->xmin += (int)((float)UI_icon_get_width(but->icon+but->iconadd) * UI_DPI_ICON_FAC); if(but->editstr || (but->flag & UI_TEXT_LEFT)) rect->xmin += 5; @@ -3133,7 +3132,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic /* text location offset */ rect->xmin+=5; - if(iconid) rect->xmin+= ICON_HEIGHT; + if(iconid) rect->xmin+= UI_DPI_ICON_SIZE; /* cut string in 2 parts? */ cpoin= strchr(name, '|'); @@ -3158,7 +3157,7 @@ void ui_draw_menu_item(uiFontStyle *fstyle, rcti *rect, const char *name, int ic if(iconid) { int xs= rect->xmin+4; - int ys= 1 + (rect->ymin+rect->ymax- ICON_HEIGHT)/2; + int ys= 1 + (rect->ymin+rect->ymax- UI_DPI_ICON_SIZE)/2; glEnable(GL_BLEND); UI_icon_draw_aspect(xs, ys, iconid, 1.2f, 0.5f); /* XXX scale weak get from fstyle? */ glDisable(GL_BLEND); -- cgit v1.2.3 From a6b677c81d3eb64c66b23ba83b268748b7f09009 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 5 Aug 2011 12:07:05 +0000 Subject: patch from jensverwiebe to scons to be compatible with gcc llvm. people who copy the darwin-config.py to their user-config.py should update. --- build_files/scons/config/darwin-config.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py index 00b0c6ebf00..2df2e1ae956 100644 --- a/build_files/scons/config/darwin-config.py +++ b/build_files/scons/config/darwin-config.py @@ -21,14 +21,16 @@ cmd = 'uname -p' MAC_PROC=commands.getoutput(cmd) cmd = 'uname -r' cmd_res=commands.getoutput(cmd) -if cmd_res[0]=='7': +if cmd_res[:2]=='7': MAC_CUR_VER='10.3' -elif cmd_res[0]=='8': +elif cmd_res[:2]=='8': MAC_CUR_VER='10.4' -elif cmd_res[0]=='9': +elif cmd_res[:2]=='9': MAC_CUR_VER='10.5' -elif cmd_res[0]=='10': +elif cmd_res[:2]=='10': MAC_CUR_VER='10.6' +elif cmd_res[:2]=='11': + MAC_CUR_VER='10.7' if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'ppc64': USE_QTKIT=True # Carbon quicktime is not available for 64bit @@ -37,8 +39,8 @@ if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'ppc64': # Default target OSX settings per architecture # Can be customized -if MACOSX_ARCHITECTURE == 'ppc': -# ppc release are now made for 10.4 +if MACOSX_ARCHITECTURE == 'ppc' and MAC_CUR_VER == '10.4': +# all releases are now made for 10.5 ! # MAC_MIN_VERS = '10.3' # MACOSX_SDK='/Developer/SDKs/MacOSX10.3.9.sdk' # LCGDIR = '#../lib/darwin-6.1-powerpc' @@ -50,13 +52,21 @@ if MACOSX_ARCHITECTURE == 'ppc': LCGDIR = '#../lib/darwin-8.0.0-powerpc' CC = 'gcc-4.0' CXX = 'g++-4.0' -elif MACOSX_ARCHITECTURE == 'i386': +elif MACOSX_ARCHITECTURE == 'i386' and MAC_CUR_VER == '10.4': MAC_MIN_VERS = '10.4' MACOSX_DEPLOYMENT_TARGET = '10.4' MACOSX_SDK='/Developer/SDKs/MacOSX10.4u.sdk' LCGDIR = '#../lib/darwin-8.x.i386' CC = 'gcc-4.0' CXX = 'g++-4.0' +elif MAC_CUR_VER >= '10.6': + # OSX 10.6 and 10.7 developer tools don´t come with sdk < 10.6 anymore ! + MAC_MIN_VERS = '10.6' + MACOSX_DEPLOYMENT_TARGET = '10.6' + MACOSX_SDK='/Developer/SDKs/MacOSX10.6.sdk' + LCGDIR = '#../lib/darwin-9.x.universal' + CC = 'llvm-gcc-4.2' + CXX = 'llvm-g++-4.2' else : MAC_MIN_VERS = '10.5' MACOSX_DEPLOYMENT_TARGET = '10.5' @@ -71,8 +81,8 @@ LIBDIR = '${LCGDIR}' ################### Dependency settings ################## ############################################################################# -#Defaults openMP to true if compiler (currently only gcc 4.2) handles it -if CC == 'gcc-4.2': +#Defaults openMP to true if compiler handles it +if CC == 'gcc-4.2' or CC == 'llvm-gcc-4.2': WITH_BF_OPENMP = True # multithreading for fluids, cloth and smoke else: WITH_BF_OPENMP = False -- cgit v1.2.3 From db319f8544a908a280a92550fc4c2cc706fc12e2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 5 Aug 2011 14:53:13 +0000 Subject: move the ndof menu into the userpref's since it adjusts preferences, also renamed VIEW3D_MT_ndof_settings -> USERPREF_MT_ndof_settings since it has no view3d specific settings. --- release/scripts/startup/bl_ui/space_userpref.py | 25 ++++++++++++++++++++++ release/scripts/startup/bl_ui/space_view3d.py | 24 --------------------- source/blender/windowmanager/intern/wm_operators.c | 2 +- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 1feb1eec0c5..e27bd8ef07a 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -755,6 +755,31 @@ class USERPREF_PT_file(bpy.types.Panel): from bl_ui.space_userpref_keymap import InputKeyMapPanel +class USERPREF_MT_ndof_settings(bpy.types.Menu): + # accessed from the window keybindings in C (only) + bl_label = "3D Mouse Settings" + + def draw(self, context): + layout = self.layout + input_prefs = context.user_preferences.inputs + + layout.separator() + layout.prop(input_prefs, "ndof_sensitivity") + + if context.space_data.type == 'VIEW_3D': + layout.separator() + layout.prop(input_prefs, "ndof_show_guide") + + layout.separator() + layout.label(text="orbit options") + layout.prop(input_prefs, "ndof_orbit_invert_axes") + + layout.separator() + layout.label(text="fly options") + layout.prop(input_prefs, "ndof_fly_helicopter", icon='NDOF_FLY') + layout.prop(input_prefs, "ndof_lock_horizon", icon='NDOF_DOM') + + class USERPREF_PT_input(bpy.types.Panel, InputKeyMapPanel): bl_space_type = 'USER_PREFERENCES' bl_label = "Input" diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index f96a758e7ce..083c330f61d 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -349,30 +349,6 @@ class VIEW3D_MT_view_navigation(bpy.types.Menu): layout.operator("view3d.fly") -class VIEW3D_MT_ndof_settings(bpy.types.Menu): - bl_label = "3D Mouse Settings" - - def draw(self, context): - layout = self.layout - input_prefs = context.user_preferences.inputs - - layout.separator() - layout.prop(input_prefs, "ndof_sensitivity") - - if context.space_data.type == 'VIEW_3D': - layout.separator() - layout.prop(input_prefs, "ndof_show_guide") - - layout.separator() - layout.label(text="orbit options") - layout.prop(input_prefs, "ndof_orbit_invert_axes") - - layout.separator() - layout.label(text="fly options") - layout.prop(input_prefs, "ndof_fly_helicopter", icon='NDOF_FLY') - layout.prop(input_prefs, "ndof_lock_horizon", icon='NDOF_DOM') - - class VIEW3D_MT_view_align(bpy.types.Menu): bl_label = "Align View" diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 7238cede2cc..cea2d6b3fe5 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3719,7 +3719,7 @@ void wm_window_keymap(wmKeyConfig *keyconf) /* menus that can be accessed anywhere in blender */ WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_PRESS, 0, 0); - WM_keymap_add_menu(keymap, "VIEW3D_MT_ndof_settings", NDOF_BUTTON_MENU, KM_PRESS, 0, 0); + WM_keymap_add_menu(keymap, "USERPREF_MT_ndof_settings", NDOF_BUTTON_MENU, KM_PRESS, 0, 0); /* Space switching */ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F2KEY, KM_PRESS, KM_SHIFT, 0); /* new in 2.5x, was DXF export */ -- cgit v1.2.3 From 85fe36ab611aae8b47089c24110d4d176bc8143c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 5 Aug 2011 16:21:37 +0000 Subject: pyrna - add own callable function type rather then using a standard python method, gives small speedup drawing buttons since every layout.prop/col/operator/menu etc creates and throws away one of these. --- source/blender/python/intern/bpy_rna.c | 135 +++++++++++++++++++++++++-------- source/blender/python/intern/bpy_rna.h | 10 +++ 2 files changed, 115 insertions(+), 30 deletions(-) diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 502b25842de..d517205e2fe 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -908,6 +908,13 @@ static PyObject *pyrna_prop_repr(BPy_PropertyRNA *self) return ret; } + +static PyObject *pyrna_func_repr(BPy_FunctionRNA *self) +{ + return PyUnicode_FromFormat("<%.200s %.200s.%.200s()>", Py_TYPE(self)->tp_name, RNA_struct_identifier(self->ptr.type), RNA_function_identifier(self->func)); +} + + static long pyrna_struct_hash(BPy_StructRNA *self) { return _Py_HashPointer(self->ptr.data); @@ -1344,36 +1351,16 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const cha return error_val; } -static PyObject *pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw); -static PyObject *pyrna_func_to_py(BPy_DummyPointerRNA *pyrna, FunctionRNA *func) +static PyObject *pyrna_func_to_py(PointerRNA *ptr, FunctionRNA *func) { - static PyMethodDef func_meth= {"", (PyCFunction)pyrna_func_call, METH_VARARGS|METH_KEYWORDS, "python rna function"}; - PyObject *self; - PyObject *ret; - - if(func==NULL) { - PyErr_Format(PyExc_RuntimeError, - "%.200s: type attempted to get NULL function", - RNA_struct_identifier(pyrna->ptr.type)); - return NULL; - } - - self= PyTuple_New(2); - - PyTuple_SET_ITEM(self, 0, (PyObject *)pyrna); - Py_INCREF(pyrna); - - PyTuple_SET_ITEM(self, 1, PyCapsule_New((void *)func, NULL, NULL)); - - ret= PyCFunction_New(&func_meth, self); - Py_DECREF(self); - - return ret; + BPy_FunctionRNA* pyfunc= (BPy_FunctionRNA *) PyObject_NEW(BPy_FunctionRNA, &pyrna_func_Type); + pyfunc->ptr= *ptr; + pyfunc->func= func; + return (PyObject *)pyfunc; } - static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix) { /* XXX hard limits should be checked here */ @@ -3001,7 +2988,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) } /* RNA function only if callback is declared (no optional functions) */ else if ((func= RNA_struct_find_function(&self->ptr, name)) && RNA_function_defined(func)) { - ret= pyrna_func_to_py((BPy_DummyPointerRNA *)self, func); + ret= pyrna_func_to_py(&self->ptr, func); } else if (self->ptr.type == &RNA_Context) { bContext *C= self->ptr.data; @@ -3303,7 +3290,7 @@ static PyObject *pyrna_prop_collection_getattro(BPy_PropertyRNA *self, PyObject } else if ((func= RNA_struct_find_function(&r_ptr, name))) { PyObject *self_collection= pyrna_struct_CreatePyObject(&r_ptr); - ret= pyrna_func_to_py((BPy_DummyPointerRNA *)self_collection, func); + ret= pyrna_func_to_py(&((BPy_DummyPointerRNA *)self_collection)->ptr, func); Py_DECREF(self_collection); return ret; @@ -4257,11 +4244,11 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat return ret; } -static PyObject *pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw) +static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject *kw) { /* Note, both BPy_StructRNA and BPy_PropertyRNA can be used here */ - PointerRNA *self_ptr= &(((BPy_DummyPointerRNA *)PyTuple_GET_ITEM(self, 0))->ptr); - FunctionRNA *self_func= PyCapsule_GetPointer(PyTuple_GET_ITEM(self, 1), NULL); + PointerRNA *self_ptr= &self->ptr; + FunctionRNA *self_func= self->func; PointerRNA funcptr; ParameterList parms; @@ -5045,6 +5032,91 @@ static PyTypeObject pyrna_prop_collection_idprop_Type= { NULL }; +/*-----------------------BPy_PropertyRNA method def------------------------------*/ +PyTypeObject pyrna_func_Type= { + PyVarObject_HEAD_INIT(NULL, 0) + "bpy_func", /* tp_name */ + sizeof(BPy_FunctionRNA), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + NULL, /* tp_dealloc */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + NULL, /* tp_compare */ /* DEPRECATED in python 3.0! */ + (reprfunc) pyrna_func_repr, /* tp_repr */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + NULL, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + (ternaryfunc)pyrna_func_call, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + + /* will only use these if this is a subtype of a py class */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ + + /*** weak reference enabler ***/ +#ifdef USE_WEAKREFS + offsetof(BPy_PropertyRNA, in_weakreflist), /* long tp_weaklistoffset; */ +#else + 0, +#endif + + /*** Added in release 2.2 ***/ + /* Iterators */ + NULL, /* getiterfunc tp_iter; */ + NULL, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + NULL, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL +}; + #ifdef USE_PYRNA_ITER /* --- collection iterator: start --- */ /* wrap rna collection iterator functions */ @@ -5516,6 +5588,9 @@ void BPY_rna_init(void) if(PyType_Ready(&pyrna_prop_collection_idprop_Type) < 0) return; + if(PyType_Ready(&pyrna_func_Type) < 0) + return; + #ifdef USE_PYRNA_ITER if(PyType_Ready(&pyrna_prop_collection_iter_Type) < 0) return; diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 5db352af53d..3796984ea81 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -71,6 +71,7 @@ extern PyTypeObject pyrna_struct_Type; extern PyTypeObject pyrna_prop_Type; extern PyTypeObject pyrna_prop_array_Type; extern PyTypeObject pyrna_prop_collection_Type; +extern PyTypeObject pyrna_func_Type; #define BPy_StructRNA_Check(v) (PyObject_TypeCheck(v, &pyrna_struct_Type)) #define BPy_StructRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_struct_Type) @@ -142,6 +143,15 @@ typedef struct { CollectionPropertyIterator iter; } BPy_PropertyCollectionIterRNA; +typedef struct { + PyObject_HEAD /* required python macro */ +#ifdef USE_WEAKREFS + PyObject *in_weakreflist; +#endif + PointerRNA ptr; + FunctionRNA *func; +} BPy_FunctionRNA; + /* cheap trick */ #define BPy_BaseTypeRNA BPy_PropertyRNA -- cgit v1.2.3 From 3a82a690abca993866c30f03696e8d2415455f64 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 5 Aug 2011 16:29:38 +0000 Subject: ifdef out support for for python owning and freeing BPy_StructRNA because this is only used for doc generation and it makes _every_ blender/python instance 4 bytes bigger - vertex/bezier point/object/scene/group etc. --- source/blender/python/intern/bpy_operator.c | 2 ++ source/blender/python/intern/bpy_rna.c | 4 ++++ source/blender/python/intern/bpy_rna.h | 8 ++++++++ 3 files changed, 14 insertions(+) diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index 4a17c45ae38..4b05a9c0c72 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -397,7 +397,9 @@ static PyObject *pyop_getrna(PyObject *UNUSED(self), PyObject *value) pyrna= (BPy_StructRNA *)pyrna_struct_CreatePyObject(&ptr); +#ifdef PYRNA_FREE_SUPPORT pyrna->freeptr= TRUE; +#endif return (PyObject *)pyrna; } diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index d517205e2fe..4447a0476f4 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -957,11 +957,13 @@ static int pyrna_struct_clear(BPy_StructRNA *self) /* use our own dealloc so we can free a property if we use one */ static void pyrna_struct_dealloc(BPy_StructRNA *self) { +#ifdef PYRNA_FREE_SUPPORT if (self->freeptr && self->ptr.data) { IDP_FreeProperty(self->ptr.data); MEM_freeN(self->ptr.data); self->ptr.data= NULL; } +#endif /* PYRNA_FREE_SUPPORT */ #ifdef USE_WEAKREFS if (self->in_weakreflist != NULL) { @@ -5495,7 +5497,9 @@ PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr) } pyrna->ptr= *ptr; +#ifdef PYRNA_FREE_SUPPORT pyrna->freeptr= FALSE; +#endif #ifdef USE_PYRNA_STRUCT_REFERENCE pyrna->reference= NULL; diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index 3796984ea81..30f6c02115a 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -62,6 +62,11 @@ #if defined(USE_PYRNA_INVALIDATE_GC) && defined(USE_PYRNA_INVALIDATE_WEAKREF) #error "Only 1 reference check method at a time!" #endif + +/* only used by operator introspection get_rna(), this is only used for doc gen + * so prefer the leak to the memory bloat for now. */ +// #define PYRNA_FREE_SUPPORT + /* --- end bpy build options --- */ struct ID; @@ -108,7 +113,10 @@ typedef struct { * hold onto the collection iterator to prevent it from freeing allocated data we may use */ PyObject *reference; #endif /* !USE_PYRNA_STRUCT_REFERENCE */ + +#ifdef PYRNA_FREE_SUPPORT int freeptr; /* needed in some cases if ptr.data is created on the fly, free when deallocing */ +#endif /* PYRNA_FREE_SUPPORT */ } BPy_StructRNA; typedef struct { -- cgit v1.2.3 From 4d319f8059fb66cd05ef42defc967f6bc7f93859 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 5 Aug 2011 17:39:44 +0000 Subject: fix for GHOST/SDL key input with uppercase keys. --- intern/ghost/intern/GHOST_SystemSDL.cpp | 43 ++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp index 2c61acc2d93..69a9f936cf6 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cpp +++ b/intern/ghost/intern/GHOST_SystemSDL.cpp @@ -180,6 +180,7 @@ convertSDLKey(SDL_Scancode key) GXMAP(type,SDL_SCANCODE_RCTRL, GHOST_kKeyRightControl); GXMAP(type,SDL_SCANCODE_LALT, GHOST_kKeyLeftAlt); GXMAP(type,SDL_SCANCODE_RALT, GHOST_kKeyRightAlt); + GXMAP(type,SDL_SCANCODE_LGUI, GHOST_kKeyOS); GXMAP(type,SDL_SCANCODE_RGUI, GHOST_kKeyOS); GXMAP(type,SDL_SCANCODE_INSERT, GHOST_kKeyInsert); @@ -228,6 +229,7 @@ convertSDLKey(SDL_Scancode key) GXMAP(type,SDL_SCANCODE_AUDIONEXT, GHOST_kKeyMediaLast); default: + printf("Unknown\n"); type= GHOST_kKeyUnknown; break; } @@ -372,6 +374,7 @@ GHOST_SystemSDL::processEvent(SDL_Event *sdl_event) case SDL_KEYUP: { SDL_KeyboardEvent &sdl_sub_evt= sdl_event->key; + SDL_Keycode sym= sdl_sub_evt.keysym.sym; GHOST_TEventType type= (sdl_sub_evt.state == SDL_PRESSED) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp; GHOST_WindowSDL *window= findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID)); @@ -379,7 +382,45 @@ GHOST_SystemSDL::processEvent(SDL_Event *sdl_event) GHOST_TKey gkey= convertSDLKey(sdl_sub_evt.keysym.scancode); /* note, the sdl_sub_evt.keysym.sym is truncated, for unicode support ghost has to be modified */ - g_event= new GHOST_EventKey(getMilliSeconds(), type, window, gkey, sdl_sub_evt.keysym.sym); + if(sym > 127) { + sym= 0; + } + else { + if(sdl_sub_evt.keysym.mod & (KMOD_LSHIFT|KMOD_RSHIFT)) { + /* lame US keyboard assumptions */ + if(sym >= 'a' && sym <= ('a' + 32)) { + sym -= 32; + } + else { + switch(sym) { + case '`': sym= '~'; break; + case '1': sym= '!'; break; + case '2': sym= '@'; break; + case '3': sym= '#'; break; + case '4': sym= '$'; break; + case '5': sym= '%'; break; + case '6': sym= '^'; break; + case '7': sym= '&'; break; + case '8': sym= '*'; break; + case '9': sym= '('; break; + case '0': sym= ')'; break; + case '-': sym= '_'; break; + case '=': sym= '+'; break; + case '[': sym= '{'; break; + case ']': sym= '}'; break; + case '\\': sym= '|'; break; + case ';': sym= ':'; break; + case '\'': sym= '"'; break; + case ',': sym= '<'; break; + case '.': sym= '>'; break; + case '/': sym= '?'; break; + default: break; + } + } + } + } + + g_event= new GHOST_EventKey(getMilliSeconds(), type, window, gkey, sym); } break; } -- cgit v1.2.3 From 7368298a45f96667a548e10cfe9d227fcf18e114 Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Fri, 5 Aug 2011 19:55:36 +0000 Subject: Messed up char was causing problems on windows even though it was in the comments. Kent --- build_files/scons/config/darwin-config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py index 2df2e1ae956..560b6d9cb60 100644 --- a/build_files/scons/config/darwin-config.py +++ b/build_files/scons/config/darwin-config.py @@ -60,7 +60,7 @@ elif MACOSX_ARCHITECTURE == 'i386' and MAC_CUR_VER == '10.4': CC = 'gcc-4.0' CXX = 'g++-4.0' elif MAC_CUR_VER >= '10.6': - # OSX 10.6 and 10.7 developer tools don´t come with sdk < 10.6 anymore ! + # OSX 10.6 and 10.7 developer tools do not come with sdk < 10.6 anymore ! MAC_MIN_VERS = '10.6' MACOSX_DEPLOYMENT_TARGET = '10.6' MACOSX_SDK='/Developer/SDKs/MacOSX10.6.sdk' -- cgit v1.2.3 From e6e4c7ef8bd53b06c879302bbfd3d6a00c6c48af Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 5 Aug 2011 20:45:26 +0000 Subject: KEYMAP REFACTORING Diff Keymaps User edited keymaps now no longer override the builtin keymaps entirely, but rather save only the difference and reapply those changes. This means they can stay better in sync when the builtin keymaps change. The diff/patch algorithm is not perfect, but better for the common case where only a few items are changed rather than entire keymaps The main weakness is that if a builtin keymap item changes, user modification of that item may need to be redone in some cases. Keymap Editor The most noticeable change here is that there is no longer an "Edit" button for keymaps, all are editable immediately, but a "Restore" buttons shows for keymaps and items that have been edited. Shortcuts for addons can also be edited in the keymap editor. Addons Addons now should only modify the new addon keyconfiguration, the keymap items there will be added to the builtin ones for handling events, and not get lost when starting new files. Example code of register/unregister: km = wm.keyconfigs.addon.keymaps.new("3D View", space_type="VIEW_3D") km.keymap_items.new('my.operator', 'ESC', 'PRESS') km = wm.keyconfigs.addon.keymaps["3D View"] km.keymap_items.remove(km.keymap_items["my.operator"]) Compatibility The changes made are not forward compatible, i.e. if you save user preferences with newer versions, older versions will not have key configuration changes that were made. --- .../scripts/startup/bl_ui/space_userpref_keymap.py | 53 +- source/blender/blenkernel/intern/blender.c | 33 +- source/blender/blenloader/intern/readfile.c | 40 +- source/blender/blenloader/intern/writefile.c | 24 +- .../blender/editors/interface/interface_handlers.c | 25 +- source/blender/editors/interface/resources.c | 2 +- source/blender/makesdna/DNA_userdef_types.h | 3 +- source/blender/makesdna/DNA_windowmanager_types.h | 24 +- source/blender/makesrna/intern/rna_internal.h | 3 + source/blender/makesrna/intern/rna_scene.c | 2 +- source/blender/makesrna/intern/rna_userdef.c | 6 - source/blender/makesrna/intern/rna_wm.c | 247 ++----- source/blender/makesrna/intern/rna_wm_api.c | 183 +++++- source/blender/windowmanager/WM_api.h | 44 +- source/blender/windowmanager/WM_keymap.h | 104 +++ source/blender/windowmanager/intern/wm.c | 10 +- .../blender/windowmanager/intern/wm_event_system.c | 6 + source/blender/windowmanager/intern/wm_files.c | 13 +- source/blender/windowmanager/intern/wm_keymap.c | 718 ++++++++++++++++----- source/blenderplayer/bad_level_call_stubs/stubs.c | 2 + 20 files changed, 1043 insertions(+), 499 deletions(-) create mode 100644 source/blender/windowmanager/WM_keymap.h diff --git a/release/scripts/startup/bl_ui/space_userpref_keymap.py b/release/scripts/startup/bl_ui/space_userpref_keymap.py index 585c3cffcb9..5658cc96281 100644 --- a/release/scripts/startup/bl_ui/space_userpref_keymap.py +++ b/release/scripts/startup/bl_ui/space_userpref_keymap.py @@ -188,10 +188,10 @@ class InputKeyMapPanel: if km.is_modal: row.label(text="", icon='LINKED') - if km.is_user_defined: + if km.is_user_modified: row.operator("wm.keymap_restore", text="Restore") else: - row.operator("wm.keymap_edit", text="Edit") + row.label() if km.show_expanded_children: if children: @@ -212,7 +212,6 @@ class InputKeyMapPanel: # "Add New" at end of keymap item list col = self.indented_layout(col, level + 1) subcol = col.split(percentage=0.2).column() - subcol.enabled = km.is_user_defined subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN') col.separator() @@ -243,7 +242,7 @@ class InputKeyMapPanel: col = self.indented_layout(layout, level) - if km.is_user_defined: + if kmi.show_expanded: col = col.column(align=True) box = col.box() else: @@ -256,7 +255,6 @@ class InputKeyMapPanel: row.prop(kmi, "show_expanded", text="", emboss=False) row = split.row() - row.enabled = km.is_user_defined row.prop(kmi, "active", text="", emboss=False) if km.is_modal: @@ -265,7 +263,6 @@ class InputKeyMapPanel: row.label(text=kmi.name) row = split.row() - row.enabled = km.is_user_defined row.prop(kmi, "map_type", text="") if map_type == 'KEYBOARD': row.prop(kmi, "type", text="", full_event=True) @@ -282,18 +279,17 @@ class InputKeyMapPanel: else: row.label() - if not kmi.is_user_defined: + if (not kmi.is_user_defined) and kmi.is_user_modified: op = row.operator("wm.keyitem_restore", text="", icon='BACK') op.item_id = kmi.id - op = row.operator("wm.keyitem_remove", text="", icon='X') - op.item_id = kmi.id + else: + op = row.operator("wm.keyitem_remove", text="", icon='X') + op.item_id = kmi.id # Expanded, additional event settings if kmi.show_expanded: box = col.box() - box.enabled = km.is_user_defined - if map_type not in {'TEXTINPUT', 'TIMER'}: split = box.split(percentage=0.4) sub = split.row() @@ -352,10 +348,10 @@ class InputKeyMapPanel: row.label() row.label() - if km.is_user_defined: + if km.is_user_modified: row.operator("wm.keymap_restore", text="Restore") else: - row.operator("wm.keymap_edit", text="Edit") + row.label() for kmi in filtered_items: self.draw_kmi(display_keymaps, kc, km, kmi, col, 1) @@ -363,7 +359,6 @@ class InputKeyMapPanel: # "Add New" at end of keymap item list col = self.indented_layout(layout, 1) subcol = col.split(percentage=0.2).column() - subcol.enabled = km.is_user_defined subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN') def draw_hierarchy(self, display_keymaps, layout): @@ -372,8 +367,7 @@ class InputKeyMapPanel: def draw_keymaps(self, context, layout): wm = context.window_manager - kc = wm.keyconfigs.active - defkc = wm.keyconfigs.default + kc = wm.keyconfigs.user col = layout.column() sub = col.column() @@ -398,7 +392,7 @@ class InputKeyMapPanel: col.separator() - display_keymaps = _merge_keymaps(kc, defkc) + display_keymaps = _merge_keymaps(kc, kc) if context.space_data.filter_text != "": filter_text = context.space_data.filter_text.lower() self.draw_filtered(display_keymaps, filter_text, col) @@ -609,7 +603,7 @@ class WM_OT_keyconfig_export(bpy.types.Operator): # Generate a list of keymaps to export: # - # First add all user_defined keymaps (found in inputs.edited_keymaps list), + # First add all user_modified keymaps (found in keyconfigs.user.keymaps list), # then add all remaining keymaps from the currently active custom keyconfig. # # This will create a final list of keymaps that can be used as a 'diff' against @@ -619,7 +613,9 @@ class WM_OT_keyconfig_export(bpy.types.Operator): class FakeKeyConfig(): keymaps = [] edited_kc = FakeKeyConfig() - edited_kc.keymaps.extend(context.user_preferences.inputs.edited_keymaps) + for km in wm.keyconfigs.user.keymaps: + if km.is_user_modified: + edited_kc.keymaps.append(km) # merge edited keymaps with non-default keyconfig, if it exists if kc != wm.keyconfigs.default: export_keymaps = _merge_keymaps(edited_kc, kc) @@ -669,17 +665,6 @@ class WM_OT_keyconfig_export(bpy.types.Operator): return {'RUNNING_MODAL'} -class WM_OT_keymap_edit(bpy.types.Operator): - "Edit stored key map" - bl_idname = "wm.keymap_edit" - bl_label = "Edit Key Map" - - def execute(self, context): - km = context.keymap - km.copy_to_user() - return {'FINISHED'} - - class WM_OT_keymap_restore(bpy.types.Operator): "Restore key map(s)" bl_idname = "wm.keymap_restore" @@ -691,7 +676,7 @@ class WM_OT_keymap_restore(bpy.types.Operator): wm = context.window_manager if self.all: - for km in wm.keyconfigs.default.keymaps: + for km in wm.keyconfigs.user.keymaps: km.restore_to_default() else: km = context.keymap @@ -710,13 +695,13 @@ class WM_OT_keyitem_restore(bpy.types.Operator): @classmethod def poll(cls, context): keymap = getattr(context, "keymap", None) - return keymap and keymap.is_user_defined + return keymap def execute(self, context): km = context.keymap kmi = km.keymap_items.from_id(self.item_id) - if not kmi.is_user_defined: + if (not kmi.is_user_defined) and kmi.is_user_modified: km.restore_item_to_default(kmi) return {'FINISHED'} @@ -753,7 +738,7 @@ class WM_OT_keyitem_remove(bpy.types.Operator): @classmethod def poll(cls, context): - return hasattr(context, "keymap") and context.keymap.is_user_defined + return hasattr(context, "keymap") def execute(self, context): km = context.keymap diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 8b4bbbd3c83..7e2097d1233 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -330,28 +330,45 @@ static int handle_subversion_warning(Main *main) return 1; } +static void keymap_item_free(wmKeyMapItem *kmi) +{ + if(kmi->properties) { + IDP_FreeProperty(kmi->properties); + MEM_freeN(kmi->properties); + } + if(kmi->ptr) + MEM_freeN(kmi->ptr); +} + void BKE_userdef_free(void) { wmKeyMap *km; wmKeyMapItem *kmi; + wmKeyMapDiffItem *kmdi; - for(km=U.keymaps.first; km; km=km->next) { - for(kmi=km->items.first; kmi; kmi=kmi->next) { - if(kmi->properties) { - IDP_FreeProperty(kmi->properties); - MEM_freeN(kmi->properties); + for(km=U.user_keymaps.first; km; km=km->next) { + for(kmdi=km->diff_items.first; kmdi; kmdi=kmdi->next) { + if(kmdi->add_item) { + keymap_item_free(kmdi->add_item); + MEM_freeN(kmdi->add_item); + } + if(kmdi->remove_item) { + keymap_item_free(kmdi->remove_item); + MEM_freeN(kmdi->remove_item); } - if(kmi->ptr) - MEM_freeN(kmi->ptr); } + for(kmi=km->items.first; kmi; kmi=kmi->next) + keymap_item_free(kmi); + + BLI_freelistN(&km->diff_items); BLI_freelistN(&km->items); } BLI_freelistN(&U.uistyles); BLI_freelistN(&U.uifonts); BLI_freelistN(&U.themes); - BLI_freelistN(&U.keymaps); + BLI_freelistN(&U.user_keymaps); BLI_freelistN(&U.addons); } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 44c8ca97be9..bd12677485c 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4726,6 +4726,8 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm) wm->keyconfigs.first= wm->keyconfigs.last= NULL; wm->defaultconf= NULL; + wm->addonconf= NULL; + wm->userconf= NULL; wm->jobs.first= wm->jobs.last= NULL; wm->drags.first= wm->drags.last= NULL; @@ -11762,33 +11764,57 @@ static void lib_link_all(FileData *fd, Main *main) lib_link_library(fd, main); /* only init users */ } +static void direct_link_keymapitem(FileData *fd, wmKeyMapItem *kmi) +{ + kmi->properties= newdataadr(fd, kmi->properties); + if(kmi->properties) + IDP_DirectLinkProperty(kmi->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); + kmi->ptr= NULL; + kmi->flag &= ~KMI_UPDATE; +} static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead) { UserDef *user; wmKeyMap *keymap; wmKeyMapItem *kmi; + wmKeyMapDiffItem *kmdi; bfd->user= user= read_struct(fd, bhead, "user def"); /* read all data into fd->datamap */ bhead= read_data_into_oldnewmap(fd, bhead, "user def"); + if(user->keymaps.first) { + /* backwards compatibility */ + user->user_keymaps= user->keymaps; + user->keymaps.first= user->keymaps.last= NULL; + } + link_list(fd, &user->themes); - link_list(fd, &user->keymaps); + link_list(fd, &user->user_keymaps); link_list(fd, &user->addons); - for(keymap=user->keymaps.first; keymap; keymap=keymap->next) { + for(keymap=user->user_keymaps.first; keymap; keymap=keymap->next) { keymap->modal_items= NULL; keymap->poll= NULL; + keymap->flag &= ~KEYMAP_UPDATE; + link_list(fd, &keymap->diff_items); link_list(fd, &keymap->items); - for(kmi=keymap->items.first; kmi; kmi=kmi->next) { - kmi->properties= newdataadr(fd, kmi->properties); - if(kmi->properties) - IDP_DirectLinkProperty(kmi->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); - kmi->ptr= NULL; + + for(kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next) { + kmdi->remove_item= newdataadr(fd, kmdi->remove_item); + kmdi->add_item= newdataadr(fd, kmdi->add_item); + + if(kmdi->remove_item) + direct_link_keymapitem(fd, kmdi->remove_item); + if(kmdi->add_item) + direct_link_keymapitem(fd, kmdi->add_item); } + + for(kmi=keymap->items.first; kmi; kmi=kmi->next) + direct_link_keymapitem(fd, kmi); } // XXX diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index bf86527b9d3..7d65248c0e9 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -717,11 +717,19 @@ static void write_renderinfo(WriteData *wd, Main *mainvar) /* for renderdeamon } } +static void write_keymapitem(WriteData *wd, wmKeyMapItem *kmi) +{ + writestruct(wd, DATA, "wmKeyMapItem", 1, kmi); + if(kmi->properties) + IDP_WriteProperty(kmi->properties, wd); +} + static void write_userdef(WriteData *wd) { bTheme *btheme; wmKeyMap *keymap; wmKeyMapItem *kmi; + wmKeyMapDiffItem *kmdi; bAddon *bext; uiStyle *style; @@ -730,15 +738,19 @@ static void write_userdef(WriteData *wd) for(btheme= U.themes.first; btheme; btheme=btheme->next) writestruct(wd, DATA, "bTheme", 1, btheme); - for(keymap= U.keymaps.first; keymap; keymap=keymap->next) { + for(keymap= U.user_keymaps.first; keymap; keymap=keymap->next) { writestruct(wd, DATA, "wmKeyMap", 1, keymap); - for(kmi=keymap->items.first; kmi; kmi=kmi->next) { - writestruct(wd, DATA, "wmKeyMapItem", 1, kmi); - - if(kmi->properties) - IDP_WriteProperty(kmi->properties, wd); + for(kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next) { + writestruct(wd, DATA, "wmKeyMapDiffItem", 1, kmdi); + if(kmdi->remove_item) + write_keymapitem(wd, kmdi->remove_item); + if(kmdi->add_item) + write_keymapitem(wd, kmdi->add_item); } + + for(kmi=keymap->items.first; kmi; kmi=kmi->next) + write_keymapitem(wd, kmi); } for(bext= U.addons.first; bext; bext=bext->next) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index b3272a2e3d4..d8d8354b0b9 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -4067,7 +4067,6 @@ static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event)) /* complex code to change name of button */ if(WM_key_event_operator_string(C, but->optype->idname, but->opcontext, prop, buf, sizeof(buf))) { - wmKeyMap *km= NULL; char *butstr_orig; // XXX but->str changed... should not, remove the hotkey from it @@ -4080,10 +4079,6 @@ static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event)) but->str= but->strdata; ui_check_but(but); - - /* set the keymap editable else the key wont save */ - WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, 1, &km); - WM_keymap_copy_to_user(km); } else { /* shortcut was removed */ @@ -4095,6 +4090,7 @@ static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event)) static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg) { + wmWindowManager *wm= CTX_wm_manager(C); uiBlock *block; uiBut *but = (uiBut *)arg; wmKeyMap *km; @@ -4107,7 +4103,7 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg) kmi = WM_keymap_item_find_id(km, kmi_id); - RNA_pointer_create(NULL, &RNA_KeyMapItem, kmi, &ptr); + RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); uiBlockSetHandleFunc(block, but_shortcut_name_func, but); @@ -4126,6 +4122,7 @@ static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg) static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg) { + wmWindowManager *wm= CTX_wm_manager(C); uiBlock *block; uiBut *but = (uiBut *)arg; wmKeyMap *km; @@ -4134,19 +4131,25 @@ static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg) uiLayout *layout; uiStyle *style= U.uistyles.first; IDProperty *prop= (but->opptr)? but->opptr->data: NULL; + int kmi_id; /* XXX this guess_opname can potentially return a different keymap than being found on adding later... */ km = WM_keymap_guess_opname(C, but->optype->idname); kmi = WM_keymap_add_item(km, but->optype->idname, AKEY, KM_PRESS, 0, 0); + kmi_id = kmi->id; - if (prop) { + /* copy properties, prop can be NULL for reset */ + if(prop) prop= IDP_CopyProperty(prop); - } - - /* prop can be NULL */ WM_keymap_properties_reset(kmi, prop); - RNA_pointer_create(NULL, &RNA_KeyMapItem, kmi, &ptr); + /* update and get pointers again */ + WM_keyconfig_update(wm); + + km = WM_keymap_guess_opname(C, but->optype->idname); + kmi = WM_keymap_item_find_id(km, kmi_id); + + RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); uiBlockSetHandleFunc(block, but_shortcut_name_func, but); diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 32e87b3a793..f3db6ad11ae 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1425,7 +1425,7 @@ void init_userdef_do_versions(void) if (bmain->versionfile < 250 || (bmain->versionfile == 250 && bmain->subversionfile < 8)) { wmKeyMap *km; - for(km=U.keymaps.first; km; km=km->next) { + for(km=U.user_keymaps.first; km; km=km->next) { if (strcmp(km->idname, "Armature_Sketch")==0) strcpy(km->idname, "Armature Sketch"); else if (strcmp(km->idname, "View3D")==0) diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index aa6da3aaeca..a555a196060 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -341,7 +341,8 @@ typedef struct UserDef { struct ListBase themes; struct ListBase uifonts; struct ListBase uistyles; - struct ListBase keymaps; + struct ListBase keymaps; /* deprecated in favor of user_keymaps */ + struct ListBase user_keymaps; struct ListBase addons; char keyconfigstr[64]; diff --git a/source/blender/makesdna/DNA_windowmanager_types.h b/source/blender/makesdna/DNA_windowmanager_types.h index 31e59f18626..1f0ae28a00d 100644 --- a/source/blender/makesdna/DNA_windowmanager_types.h +++ b/source/blender/makesdna/DNA_windowmanager_types.h @@ -144,7 +144,9 @@ typedef struct wmWindowManager { ListBase drags; /* active dragged items */ ListBase keyconfigs; /* known key configurations */ - struct wmKeyConfig *defaultconf; /* default configuration, not saved */ + struct wmKeyConfig *defaultconf; /* default configuration */ + struct wmKeyConfig *addonconf; /* addon configuration */ + struct wmKeyConfig *userconf; /* user configuration */ ListBase timers; /* active timers */ struct wmTimer *autosavetimer; /* timer for auto save */ @@ -239,15 +241,26 @@ typedef struct wmKeyMapItem { struct PointerRNA *ptr; /* rna pointer to access properties */ } wmKeyMapItem; +/* used instead of wmKeyMapItem for diff keymaps */ +typedef struct wmKeyMapDiffItem { + struct wmKeyMapDiffItem *next, *prev; + + wmKeyMapItem *remove_item; + wmKeyMapItem *add_item; +} wmKeyMapDiffItem; + /* wmKeyMapItem.flag */ -#define KMI_INACTIVE 1 -#define KMI_EXPANDED 2 +#define KMI_INACTIVE 1 +#define KMI_EXPANDED 2 +#define KMI_USER_MODIFIED 4 +#define KMI_UPDATE 8 /* stored in WM, the actively used keymaps */ typedef struct wmKeyMap { struct wmKeyMap *next, *prev; ListBase items; + ListBase diff_items; char idname[64]; /* global editor keymaps, or for more per space/region */ short spaceid; /* same IDs as in DNA_space_types.h */ @@ -263,9 +276,12 @@ typedef struct wmKeyMap { /* wmKeyMap.flag */ #define KEYMAP_MODAL 1 /* modal map, not using operatornames */ -#define KEYMAP_USER 2 /* user created keymap */ +#define KEYMAP_USER 2 /* user keymap */ #define KEYMAP_EXPANDED 4 #define KEYMAP_CHILDREN_EXPANDED 8 +#define KEYMAP_DIFF 16 /* diff keymap for user preferences */ +#define KEYMAP_USER_MODIFIED 32 /* keymap has user modifications */ +#define KEYMAP_UPDATE 64 typedef struct wmKeyConfig { struct wmKeyConfig *next, *prev; diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 9175806e2bb..c0ae7b02b1a 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -238,9 +238,12 @@ void RNA_api_image(struct StructRNA *srna); void RNA_api_operator(struct StructRNA *srna); void RNA_api_macro(struct StructRNA *srna); void RNA_api_keyconfig(struct StructRNA *srna); +void RNA_api_keyconfigs(struct StructRNA *srna); void RNA_api_keyingset(struct StructRNA *srna); void RNA_api_keymap(struct StructRNA *srna); +void RNA_api_keymaps(struct StructRNA *srna); void RNA_api_keymapitem(struct StructRNA *srna); +void RNA_api_keymapitems(struct StructRNA *srna); void RNA_api_area(struct StructRNA *srna); void RNA_api_main(struct StructRNA *srna); void RNA_api_material(StructRNA *srna); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index b3d8bc8ea18..29cfc695911 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1409,7 +1409,7 @@ void rna_def_render_layer_common(StructRNA *srna, int scene) prop= RNA_def_property(srna, "layers_zmask", PROP_BOOLEAN, PROP_LAYER); RNA_def_property_boolean_sdna(prop, NULL, "lay_zmask", 1); RNA_def_property_array(prop, 20); - RNA_def_property_ui_text(prop, "Zmask Layers", "Zmask scene layers"); + RNA_def_property_ui_text(prop, "Zmask Layers", "Zmask scene layers for solid faces"); if(scene) RNA_def_property_update(prop, NC_SCENE|ND_RENDER_OPTIONS, NULL); else RNA_def_property_clear_flag(prop, PROP_EDITABLE); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index a1a99c34e70..b3dbafeab7d 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2795,12 +2795,6 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_range(prop, 0, 32); RNA_def_property_ui_text(prop, "Wheel Scroll Lines", "The number of lines scrolled at a time with the mouse wheel"); - /* U.keymaps - custom keymaps that have been edited from default configs */ - prop= RNA_def_property(srna, "edited_keymaps", PROP_COLLECTION, PROP_NONE); - RNA_def_property_collection_sdna(prop, NULL, "keymaps", NULL); - RNA_def_property_struct_type(prop, "KeyMap"); - RNA_def_property_ui_text(prop, "Edited Keymaps", ""); - prop= RNA_def_property(srna, "active_keyconfig", PROP_STRING, PROP_DIRPATH); RNA_def_property_string_sdna(prop, NULL, "keyconfigstr"); RNA_def_property_ui_text(prop, "Key Config", "The name of the active key configuration"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index a046be59ab5..307cf0e175a 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -578,22 +578,6 @@ static EnumPropertyItem *rna_KeyMapItem_propvalue_itemf(bContext *C, PointerRNA wmKeyConfig *kc; wmKeyMap *km; - /* check user keymaps */ - for(km=U.keymaps.first; km; km=km->next) { - wmKeyMapItem *kmi; - for (kmi=km->items.first; kmi; kmi=kmi->next) { - if (kmi == ptr->data) { - if (!km->modal_items) { - if (!WM_keymap_user_init(wm, km)) { - return keymap_propvalue_items; /* ERROR */ - } - } - - return km->modal_items; - } - } - } - for(kc=wm->keyconfigs.first; kc; kc=kc->next) { for(km=kc->keymaps.first; km; km=km->next) { /* only check if it's a modal keymap */ @@ -654,12 +638,13 @@ static PointerRNA rna_WindowManager_active_keyconfig_get(PointerRNA *ptr) return rna_pointer_inherit_refine(ptr, &RNA_KeyConfig, kc); } -static void rna_WindowManager_active_keyconfig_set(PointerRNA *UNUSED(ptr), PointerRNA value) +static void rna_WindowManager_active_keyconfig_set(PointerRNA *ptr, PointerRNA value) { + wmWindowManager *wm= ptr->data; wmKeyConfig *kc= value.data; if(kc) - BLI_strncpy(U.keyconfigstr, kc->idname, sizeof(U.keyconfigstr)); + WM_keyconfig_set_active(wm, kc->idname); } static void rna_wmKeyMapItem_idname_get(PointerRNA *ptr, char *value) @@ -1130,93 +1115,6 @@ static StructRNA* rna_MacroOperator_refine(PointerRNA *opr) return (op->type && op->type->ext.srna)? op->type->ext.srna: &RNA_Macro; } -static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km, ReportList *reports, const char *idname, int type, int value, int any, int shift, int ctrl, int alt, int oskey, int keymodifier) -{ -// wmWindowManager *wm = CTX_wm_manager(C); - char idname_bl[OP_MAX_TYPENAME]; - int modifier= 0; - - /* only on non-modal maps */ - if (km->flag & KEYMAP_MODAL) { - BKE_report(reports, RPT_ERROR, "Not a non-modal keymap."); - return NULL; - } - - WM_operator_bl_idname(idname_bl, idname); - - if(shift) modifier |= KM_SHIFT; - if(ctrl) modifier |= KM_CTRL; - if(alt) modifier |= KM_ALT; - if(oskey) modifier |= KM_OSKEY; - - if(any) modifier = KM_ANY; - - return WM_keymap_add_item(km, idname_bl, type, value, modifier, keymodifier); -} - -static wmKeyMapItem *rna_KeyMap_item_new_modal(wmKeyMap *km, bContext *C, ReportList *reports, const char *propvalue_str, int type, int value, int any, int shift, int ctrl, int alt, int oskey, int keymodifier) -{ - wmWindowManager *wm = CTX_wm_manager(C); - int modifier= 0; - int propvalue = 0; - - /* only modal maps */ - if ((km->flag & KEYMAP_MODAL) == 0) { - BKE_report(reports, RPT_ERROR, "Not a modal keymap."); - return NULL; - } - - if (!km->modal_items) { - if(!WM_keymap_user_init(wm, km)) { - BKE_report(reports, RPT_ERROR, "User defined keymap doesn't correspond to a system keymap."); - return NULL; - } - } - - if (!km->modal_items) { - BKE_report(reports, RPT_ERROR, "No property values defined."); - return NULL; - } - - - if(RNA_enum_value_from_id(km->modal_items, propvalue_str, &propvalue)==0) { - BKE_report(reports, RPT_WARNING, "Property value not in enumeration."); - } - - if(shift) modifier |= KM_SHIFT; - if(ctrl) modifier |= KM_CTRL; - if(alt) modifier |= KM_ALT; - if(oskey) modifier |= KM_OSKEY; - - if(any) modifier = KM_ANY; - - return WM_modalkeymap_add_item(km, type, value, modifier, keymodifier, propvalue); -} - -static wmKeyMap *rna_keymap_new(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid, int modal) -{ - if (modal == 0) { - return WM_keymap_find(keyconf, idname, spaceid, regionid); - } else { - return WM_modalkeymap_add(keyconf, idname, NULL); /* items will be lazy init */ - } -} - -static wmKeyMap *rna_keymap_find(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid) -{ - return WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid); -} - -static wmKeyMap *rna_keymap_find_modal(wmKeyConfig *UNUSED(keyconf), const char *idname) -{ - wmOperatorType *ot = WM_operatortype_find(idname, 0); - - if (!ot) - return NULL; - else - return ot->modalkeymap; -} - /* just to work around 'const char *' warning and to ensure this is a python op */ static void rna_Operator_bl_idname_set(PointerRNA *ptr, const char *value) { @@ -1242,6 +1140,12 @@ static void rna_Operator_bl_description_set(PointerRNA *ptr, const char *value) else assert(!"setting the bl_description on a non-builtin operator"); } +static void rna_KeyMapItem_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + wmKeyMapItem *kmi= ptr->data; + WM_keyconfig_update_tag(NULL, kmi); +} + #else /* RNA_RUNTIME */ static void rna_def_operator(BlenderRNA *brna) @@ -1566,9 +1470,6 @@ static void rna_def_wm_keyconfigs(BlenderRNA *brna, PropertyRNA *cprop) StructRNA *srna; PropertyRNA *prop; - FunctionRNA *func; - PropertyRNA *parm; - RNA_def_property_srna(cprop, "KeyConfigurations"); srna= RNA_def_struct(brna, "KeyConfigurations", NULL); RNA_def_struct_sdna(srna, "wmWindowManager"); @@ -1578,23 +1479,24 @@ static void rna_def_wm_keyconfigs(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_property_struct_type(prop, "KeyConfig"); RNA_def_property_pointer_funcs(prop, "rna_WindowManager_active_keyconfig_get", "rna_WindowManager_active_keyconfig_set", NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Active KeyConfig", "Active wm KeyConfig"); + RNA_def_property_ui_text(prop, "Active KeyConfig", "Active key configuration (preset)"); prop= RNA_def_property(srna, "default", PROP_POINTER, PROP_NEVER_NULL); RNA_def_property_pointer_sdna(prop, NULL, "defaultconf"); RNA_def_property_struct_type(prop, "KeyConfig"); - RNA_def_property_ui_text(prop, "Default Key Configuration", ""); + RNA_def_property_ui_text(prop, "Default Key Configuration", "Default builtin key configuration"); + + prop= RNA_def_property(srna, "addon", PROP_POINTER, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "addonconf"); + RNA_def_property_struct_type(prop, "KeyConfig"); + RNA_def_property_ui_text(prop, "Addon Key Configuration", "Key configuration that can be extended by addons, and is added to the active configuration when handling events"); + + prop= RNA_def_property(srna, "user", PROP_POINTER, PROP_NEVER_NULL); + RNA_def_property_pointer_sdna(prop, NULL, "userconf"); + RNA_def_property_struct_type(prop, "KeyConfig"); + RNA_def_property_ui_text(prop, "User Key Configuration", "Final key configuration that combines keymaps from the active and addon configurations, and can be edited by the user"); - /* funcs */ - func= RNA_def_function(srna, "new", "WM_keyconfig_new_user"); // add_keyconfig - parm= RNA_def_string(func, "name", "", 0, "Name", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_pointer(func, "keyconfig", "KeyConfig", "Key Configuration", "Added key configuration."); - RNA_def_function_return(func, parm); - - func= RNA_def_function(srna, "remove", "WM_keyconfig_remove"); // remove_keyconfig - parm= RNA_def_pointer(func, "keyconfig", "KeyConfig", "Key Configuration", "Removed key configuration."); - RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_api_keyconfigs(srna); } static void rna_def_windowmanager(BlenderRNA *brna) @@ -1631,107 +1533,30 @@ static void rna_def_windowmanager(BlenderRNA *brna) static void rna_def_keymap_items(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; -// PropertyRNA *prop; - - FunctionRNA *func; - PropertyRNA *parm; RNA_def_property_srna(cprop, "KeyMapItems"); srna= RNA_def_struct(brna, "KeyMapItems", NULL); RNA_def_struct_sdna(srna, "wmKeyMap"); RNA_def_struct_ui_text(srna, "KeyMap Items", "Collection of keymap items"); - func= RNA_def_function(srna, "new", "rna_KeyMap_item_new"); - RNA_def_function_flag(func, FUNC_USE_REPORTS); - parm= RNA_def_string(func, "idname", "", 0, "Operator Identifier", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_enum(func, "type", event_type_items, 0, "Type", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_enum(func, "value", event_value_items, 0, "Value", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_boolean(func, "any", 0, "Any", ""); - RNA_def_boolean(func, "shift", 0, "Shift", ""); - RNA_def_boolean(func, "ctrl", 0, "Ctrl", ""); - RNA_def_boolean(func, "alt", 0, "Alt", ""); - RNA_def_boolean(func, "oskey", 0, "OS Key", ""); - RNA_def_enum(func, "key_modifier", event_type_items, 0, "Key Modifier", ""); - parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item."); - RNA_def_function_return(func, parm); - - func= RNA_def_function(srna, "new_modal", "rna_KeyMap_item_new_modal"); - RNA_def_function_flag(func, FUNC_USE_CONTEXT|FUNC_USE_REPORTS); - parm= RNA_def_string(func, "propvalue", "", 0, "Property Value", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_enum(func, "type", event_type_items, 0, "Type", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_enum(func, "value", event_value_items, 0, "Value", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_boolean(func, "any", 0, "Any", ""); - RNA_def_boolean(func, "shift", 0, "Shift", ""); - RNA_def_boolean(func, "ctrl", 0, "Ctrl", ""); - RNA_def_boolean(func, "alt", 0, "Alt", ""); - RNA_def_boolean(func, "oskey", 0, "OS Key", ""); - RNA_def_enum(func, "key_modifier", event_type_items, 0, "Key Modifier", ""); - parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item."); - RNA_def_function_return(func, parm); - - func= RNA_def_function(srna, "remove", "WM_keymap_remove_item"); - parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - - func= RNA_def_function(srna, "from_id", "WM_keymap_item_find_id"); - parm= RNA_def_property(func, "id", PROP_INT, PROP_NONE); - RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_property_ui_text(parm, "id", "ID of the item"); - parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); - RNA_def_function_return(func, parm); - + RNA_api_keymapitems(srna); } static void rna_def_wm_keymaps(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; - //PropertyRNA *prop; - - FunctionRNA *func; - PropertyRNA *parm; - RNA_def_property_srna(cprop, "KeyMaps"); srna= RNA_def_struct(brna, "KeyMaps", NULL); RNA_def_struct_sdna(srna, "wmKeyConfig"); RNA_def_struct_ui_text(srna, "Key Maps", "Collection of keymaps"); - func= RNA_def_function(srna, "new", "rna_keymap_new"); // add_keymap - parm= RNA_def_string(func, "name", "", 0, "Name", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_enum(func, "space_type", space_type_items, SPACE_EMPTY, "Space Type", ""); - RNA_def_enum(func, "region_type", region_type_items, RGN_TYPE_WINDOW, "Region Type", ""); - RNA_def_boolean(func, "modal", 0, "Modal", ""); - parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Added key map."); - RNA_def_function_return(func, parm); - - func= RNA_def_function(srna, "find", "rna_keymap_find"); // find_keymap - parm= RNA_def_string(func, "name", "", 0, "Name", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_enum(func, "space_type", space_type_items, SPACE_EMPTY, "Space Type", ""); - RNA_def_enum(func, "region_type", region_type_items, RGN_TYPE_WINDOW, "Region Type", ""); - parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Corresponding key map."); - RNA_def_function_return(func, parm); - - func= RNA_def_function(srna, "find_modal", "rna_keymap_find_modal"); // find_keymap_modal - parm= RNA_def_string(func, "name", "", 0, "Operator Name", ""); - RNA_def_property_flag(parm, PROP_REQUIRED); - parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Corresponding key map."); - RNA_def_function_return(func, parm); - + RNA_api_keymaps(srna); } static void rna_def_keyconfig(BlenderRNA *brna) { StructRNA *srna; - // FunctionRNA *func; - // PropertyRNA *parm; PropertyRNA *prop; static EnumPropertyItem map_type_items[] = { @@ -1794,8 +1619,8 @@ static void rna_def_keyconfig(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Items", "Items in the keymap, linking an operator to an input event"); rna_def_keymap_items(brna, prop); - prop= RNA_def_property(srna, "is_user_defined", PROP_BOOLEAN, PROP_NEVER_NULL); - RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYMAP_USER); + prop= RNA_def_property(srna, "is_user_modified", PROP_BOOLEAN, PROP_NEVER_NULL); + RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYMAP_USER_MODIFIED); RNA_def_property_ui_text(prop, "User Defined", "Keymap is defined by the user"); prop= RNA_def_property(srna, "is_modal", PROP_BOOLEAN, PROP_NONE); @@ -1826,6 +1651,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Identifier", "Identifier of operator to call on input event"); RNA_def_property_string_funcs(prop, "rna_wmKeyMapItem_idname_get", "rna_wmKeyMapItem_idname_length", "rna_wmKeyMapItem_idname_set"); RNA_def_struct_name_property(srna, prop); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -1836,62 +1662,73 @@ static void rna_def_keyconfig(BlenderRNA *brna) RNA_def_property_struct_type(prop, "OperatorProperties"); RNA_def_property_pointer_funcs(prop, "rna_KeyMapItem_properties_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "Properties", "Properties to set when the operator is called"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "map_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "maptype"); RNA_def_property_enum_items(prop, map_type_items); RNA_def_property_enum_funcs(prop, "rna_wmKeyMapItem_map_type_get", "rna_wmKeyMapItem_map_type_set", NULL); RNA_def_property_ui_text(prop, "Map Type", "Type of event mapping"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type"); RNA_def_property_enum_items(prop, event_type_items); RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_KeyMapItem_type_itemf"); RNA_def_property_ui_text(prop, "Type", "Type of event"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "value", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "val"); RNA_def_property_enum_items(prop, event_value_items); RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_KeyMapItem_value_itemf"); RNA_def_property_ui_text(prop, "Value", ""); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "id", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "id"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "id", "ID of the item"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "any", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_any_getf", "rna_KeyMapItem_any_setf"); RNA_def_property_ui_text(prop, "Any", "Any modifier keys pressed"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "shift", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "shift", 0); // RNA_def_property_enum_sdna(prop, NULL, "shift"); // RNA_def_property_enum_items(prop, keymap_modifiers_items); RNA_def_property_ui_text(prop, "Shift", "Shift key pressed"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "ctrl", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ctrl", 0); // RNA_def_property_enum_sdna(prop, NULL, "ctrl"); // RNA_def_property_enum_items(prop, keymap_modifiers_items); RNA_def_property_ui_text(prop, "Ctrl", "Control key pressed"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "alt", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "alt", 0); // RNA_def_property_enum_sdna(prop, NULL, "alt"); // RNA_def_property_enum_items(prop, keymap_modifiers_items); RNA_def_property_ui_text(prop, "Alt", "Alt key pressed"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "oskey", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "oskey", 0); // RNA_def_property_enum_sdna(prop, NULL, "oskey"); // RNA_def_property_enum_items(prop, keymap_modifiers_items); RNA_def_property_ui_text(prop, "OS Key", "Operating system key pressed"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "key_modifier", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "keymodifier"); RNA_def_property_enum_items(prop, event_type_items); RNA_def_property_ui_text(prop, "Key Modifier", "Regular key pressed as a modifier"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", KMI_EXPANDED); @@ -1903,15 +1740,21 @@ static void rna_def_keyconfig(BlenderRNA *brna) RNA_def_property_enum_items(prop, keymap_propvalue_items); RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_KeyMapItem_propvalue_itemf"); RNA_def_property_ui_text(prop, "Property Value", "The value this event translates to in a modal keymap"); + RNA_def_property_update(prop, 0, "rna_KeyMapItem_update"); prop= RNA_def_property(srna, "active", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", KMI_INACTIVE); RNA_def_property_ui_text(prop, "Active", "Activate or deactivate item"); RNA_def_property_ui_icon(prop, ICON_CHECKBOX_DEHLT, 1); + prop= RNA_def_property(srna, "is_user_modified", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", KMI_USER_MODIFIED); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text(prop, "User Modified", "Is this keymap item modified by the user"); + prop= RNA_def_property(srna, "is_user_defined", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "User Defined", "Is this keymap item user defined (doesn't just override a builtin item)"); + RNA_def_property_ui_text(prop, "User Defined", "Is this keymap item user defined (doesn't just replace a builtin item)"); RNA_def_property_boolean_funcs(prop, "rna_KeyMapItem_userdefined_get", NULL); RNA_api_keymapitem(srna); diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index d44b68950f7..89e946f498a 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -84,6 +84,85 @@ void rna_event_timer_remove(struct wmWindowManager *wm, wmTimer *timer) WM_event_remove_timer(wm, timer->win, timer); } +static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km, ReportList *reports, const char *idname, int type, int value, int any, int shift, int ctrl, int alt, int oskey, int keymodifier) +{ +// wmWindowManager *wm = CTX_wm_manager(C); + char idname_bl[OP_MAX_TYPENAME]; + int modifier= 0; + + /* only on non-modal maps */ + if (km->flag & KEYMAP_MODAL) { + BKE_report(reports, RPT_ERROR, "Not a non-modal keymap."); + return NULL; + } + + WM_operator_bl_idname(idname_bl, idname); + + if(shift) modifier |= KM_SHIFT; + if(ctrl) modifier |= KM_CTRL; + if(alt) modifier |= KM_ALT; + if(oskey) modifier |= KM_OSKEY; + + if(any) modifier = KM_ANY; + + return WM_keymap_add_item(km, idname_bl, type, value, modifier, keymodifier); +} + +static wmKeyMapItem *rna_KeyMap_item_new_modal(wmKeyMap *km, ReportList *reports, const char *propvalue_str, int type, int value, int any, int shift, int ctrl, int alt, int oskey, int keymodifier) +{ + int modifier= 0; + int propvalue = 0; + + /* only modal maps */ + if ((km->flag & KEYMAP_MODAL) == 0) { + BKE_report(reports, RPT_ERROR, "Not a modal keymap."); + return NULL; + } + + if (!km->modal_items) { + BKE_report(reports, RPT_ERROR, "No property values defined."); + return NULL; + } + + + if(RNA_enum_value_from_id(km->modal_items, propvalue_str, &propvalue)==0) { + BKE_report(reports, RPT_WARNING, "Property value not in enumeration."); + } + + if(shift) modifier |= KM_SHIFT; + if(ctrl) modifier |= KM_CTRL; + if(alt) modifier |= KM_ALT; + if(oskey) modifier |= KM_OSKEY; + + if(any) modifier = KM_ANY; + + return WM_modalkeymap_add_item(km, type, value, modifier, keymodifier, propvalue); +} + +static wmKeyMap *rna_keymap_new(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid, int modal) +{ + if (modal == 0) { + return WM_keymap_find(keyconf, idname, spaceid, regionid); + } else { + return WM_modalkeymap_add(keyconf, idname, NULL); /* items will be lazy init */ + } +} + +static wmKeyMap *rna_keymap_find(wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid) +{ + return WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid); +} + +static wmKeyMap *rna_keymap_find_modal(wmKeyConfig *UNUSED(keyconf), const char *idname) +{ + wmOperatorType *ot = WM_operatortype_find(idname, 0); + + if (!ot) + return NULL; + else + return ot->modalkeymap; +} + #else #define WM_GEN_INVOKE_EVENT (1<<0) @@ -301,11 +380,8 @@ void RNA_api_keymap(StructRNA *srna) parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Active key map."); RNA_def_function_return(func, parm); - func= RNA_def_function(srna, "copy_to_user", "WM_keymap_copy_to_user"); - parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "User editable key map."); - RNA_def_function_return(func, parm); - - RNA_def_function(srna, "restore_to_default", "WM_keymap_restore_to_default"); + func= RNA_def_function(srna, "restore_to_default", "WM_keymap_restore_to_default"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); func= RNA_def_function(srna, "restore_item_to_default", "rna_keymap_restore_item_to_default"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); @@ -324,5 +400,102 @@ void RNA_api_keymapitem(StructRNA *srna) parm= RNA_def_boolean(func, "result", 0, "Comparison result", ""); RNA_def_function_return(func, parm); } + +void RNA_api_keymapitems(StructRNA *srna) +{ + FunctionRNA *func; + PropertyRNA *parm; + + func= RNA_def_function(srna, "new", "rna_KeyMap_item_new"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm= RNA_def_string(func, "idname", "", 0, "Operator Identifier", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_enum(func, "type", event_type_items, 0, "Type", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_enum(func, "value", event_value_items, 0, "Value", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_boolean(func, "any", 0, "Any", ""); + RNA_def_boolean(func, "shift", 0, "Shift", ""); + RNA_def_boolean(func, "ctrl", 0, "Ctrl", ""); + RNA_def_boolean(func, "alt", 0, "Alt", ""); + RNA_def_boolean(func, "oskey", 0, "OS Key", ""); + RNA_def_enum(func, "key_modifier", event_type_items, 0, "Key Modifier", ""); + parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "new_modal", "rna_KeyMap_item_new_modal"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + parm= RNA_def_string(func, "propvalue", "", 0, "Property Value", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_enum(func, "type", event_type_items, 0, "Type", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_enum(func, "value", event_value_items, 0, "Value", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_boolean(func, "any", 0, "Any", ""); + RNA_def_boolean(func, "shift", 0, "Shift", ""); + RNA_def_boolean(func, "ctrl", 0, "Ctrl", ""); + RNA_def_boolean(func, "alt", 0, "Alt", ""); + RNA_def_boolean(func, "oskey", 0, "OS Key", ""); + RNA_def_enum(func, "key_modifier", event_type_items, 0, "Key Modifier", ""); + parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", "Added key map item."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "remove", "WM_keymap_remove_item"); + parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + + func= RNA_def_function(srna, "from_id", "WM_keymap_item_find_id"); + parm= RNA_def_property(func, "id", PROP_INT, PROP_NONE); + RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_property_ui_text(parm, "id", "ID of the item"); + parm= RNA_def_pointer(func, "item", "KeyMapItem", "Item", ""); + RNA_def_function_return(func, parm); +} + +void RNA_api_keymaps(StructRNA *srna) +{ + FunctionRNA *func; + PropertyRNA *parm; + + func= RNA_def_function(srna, "new", "rna_keymap_new"); // add_keymap + parm= RNA_def_string(func, "name", "", 0, "Name", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_enum(func, "space_type", space_type_items, SPACE_EMPTY, "Space Type", ""); + RNA_def_enum(func, "region_type", region_type_items, RGN_TYPE_WINDOW, "Region Type", ""); + RNA_def_boolean(func, "modal", 0, "Modal", ""); + parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Added key map."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "find", "rna_keymap_find"); // find_keymap + parm= RNA_def_string(func, "name", "", 0, "Name", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_enum(func, "space_type", space_type_items, SPACE_EMPTY, "Space Type", ""); + RNA_def_enum(func, "region_type", region_type_items, RGN_TYPE_WINDOW, "Region Type", ""); + parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Corresponding key map."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "find_modal", "rna_keymap_find_modal"); // find_keymap_modal + parm= RNA_def_string(func, "name", "", 0, "Operator Name", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_pointer(func, "keymap", "KeyMap", "Key Map", "Corresponding key map."); + RNA_def_function_return(func, parm); +} + +void RNA_api_keyconfigs(StructRNA *srna) +{ + FunctionRNA *func; + PropertyRNA *parm; + + func= RNA_def_function(srna, "new", "WM_keyconfig_new_user"); // add_keyconfig + parm= RNA_def_string(func, "name", "", 0, "Name", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm= RNA_def_pointer(func, "keyconfig", "KeyConfig", "Key Configuration", "Added key configuration."); + RNA_def_function_return(func, parm); + + func= RNA_def_function(srna, "remove", "WM_keyconfig_remove"); // remove_keyconfig + parm= RNA_def_pointer(func, "keyconfig", "KeyConfig", "Key Configuration", "Removed key configuration."); + RNA_def_property_flag(parm, PROP_REQUIRED); +} + #endif diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index e6325e2101a..42c3096dfc9 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -41,6 +41,7 @@ /* dna-savable wmStructs here */ #include "DNA_windowmanager_types.h" +#include "WM_keymap.h" #ifdef __cplusplus extern "C" { @@ -114,50 +115,9 @@ void WM_paint_cursor_end(struct wmWindowManager *wm, void *handle); void WM_cursor_warp (struct wmWindow *win, int x, int y); - /* keyconfig and keymap */ -wmKeyConfig *WM_keyconfig_new (struct wmWindowManager *wm, const char *idname); -wmKeyConfig *WM_keyconfig_new_user(struct wmWindowManager *wm, const char *idname); -void WM_keyconfig_remove (struct wmWindowManager *wm, struct wmKeyConfig *keyconf); -void WM_keyconfig_free (struct wmKeyConfig *keyconf); -void WM_keyconfig_userdef(void); - -void WM_keymap_init (struct bContext *C); -void WM_keymap_free (struct wmKeyMap *keymap); - -wmKeyMapItem *WM_keymap_verify_item(struct wmKeyMap *keymap, const char *idname, int type, - int val, int modifier, int keymodifier); -wmKeyMapItem *WM_keymap_add_item(struct wmKeyMap *keymap, const char *idname, int type, - int val, int modifier, int keymodifier); -wmKeyMapItem *WM_keymap_add_menu(struct wmKeyMap *keymap, const char *idname, int type, - int val, int modifier, int keymodifier); - -void WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); -char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len); - -wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid); -wmKeyMap *WM_keymap_find(struct wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid); -wmKeyMap *WM_keymap_find_all(const struct bContext *C, const char *idname, int spaceid, int regionid); -wmKeyMap *WM_keymap_active(struct wmWindowManager *wm, struct wmKeyMap *keymap); -wmKeyMap *WM_keymap_guess_opname(const struct bContext *C, const char *opname); -int WM_keymap_user_init(struct wmWindowManager *wm, struct wmKeyMap *keymap); -wmKeyMap *WM_keymap_copy_to_user(struct wmKeyMap *keymap); -void WM_keymap_restore_to_default(struct wmKeyMap *keymap); -void WM_keymap_properties_reset(struct wmKeyMapItem *kmi, struct IDProperty *properties); -void WM_keymap_restore_item_to_default(struct bContext *C, struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); - -wmKeyMapItem *WM_keymap_item_find_id(struct wmKeyMap *keymap, int id); -int WM_keymap_item_compare(struct wmKeyMapItem *k1, struct wmKeyMapItem *k2); + /* event map */ int WM_userdef_event_map(int kmitype); -wmKeyMap *WM_modalkeymap_add(struct wmKeyConfig *keyconf, const char *idname, struct EnumPropertyItem *items); -wmKeyMap *WM_modalkeymap_get(struct wmKeyConfig *keyconf, const char *idname); -wmKeyMapItem *WM_modalkeymap_add_item(struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value); -void WM_modalkeymap_assign(struct wmKeyMap *km, const char *opname); - -const char *WM_key_event_string(short type); -int WM_key_event_operator_id(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, int hotkey, struct wmKeyMap **keymap_r); -char *WM_key_event_operator_string(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, char *str, int len); - /* handlers */ struct wmEventHandler *WM_event_add_keymap_handler(ListBase *handlers, wmKeyMap *keymap); diff --git a/source/blender/windowmanager/WM_keymap.h b/source/blender/windowmanager/WM_keymap.h new file mode 100644 index 00000000000..e00cd288c9a --- /dev/null +++ b/source/blender/windowmanager/WM_keymap.h @@ -0,0 +1,104 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2007 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef WM_KEYMAP_H +#define WM_KEYMAP_H + +/** \file WM_keymap.h + * \ingroup wm + */ + +/* dna-savable wmStructs here */ +#include "DNA_windowmanager_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct EnumPropertyItem; + +/* Key Configuration */ + +wmKeyConfig *WM_keyconfig_new (struct wmWindowManager *wm, const char *idname); +wmKeyConfig *WM_keyconfig_new_user(struct wmWindowManager *wm, const char *idname); +void WM_keyconfig_remove (struct wmWindowManager *wm, struct wmKeyConfig *keyconf); +void WM_keyconfig_free (struct wmKeyConfig *keyconf); + +void WM_keyconfig_set_active(struct wmWindowManager *wm, const char *idname); + +void WM_keyconfig_update(struct wmWindowManager *wm); +void WM_keyconfig_update_tag(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); + +/* Keymap */ + +void WM_keymap_init (struct bContext *C); +void WM_keymap_free (struct wmKeyMap *keymap); + +wmKeyMapItem *WM_keymap_verify_item(struct wmKeyMap *keymap, const char *idname, int type, + int val, int modifier, int keymodifier); +wmKeyMapItem *WM_keymap_add_item(struct wmKeyMap *keymap, const char *idname, int type, + int val, int modifier, int keymodifier); +wmKeyMapItem *WM_keymap_add_menu(struct wmKeyMap *keymap, const char *idname, int type, + int val, int modifier, int keymodifier); + +void WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); +char *WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len); + +wmKeyMap *WM_keymap_list_find(ListBase *lb, const char *idname, int spaceid, int regionid); +wmKeyMap *WM_keymap_find(struct wmKeyConfig *keyconf, const char *idname, int spaceid, int regionid); +wmKeyMap *WM_keymap_find_all(const struct bContext *C, const char *idname, int spaceid, int regionid); +wmKeyMap *WM_keymap_active(struct wmWindowManager *wm, struct wmKeyMap *keymap); +wmKeyMap *WM_keymap_guess_opname(const struct bContext *C, const char *opname); + +wmKeyMapItem *WM_keymap_item_find_id(struct wmKeyMap *keymap, int id); +int WM_keymap_item_compare(struct wmKeyMapItem *k1, struct wmKeyMapItem *k2); + +/* Modal Keymap */ + +wmKeyMap *WM_modalkeymap_add(struct wmKeyConfig *keyconf, const char *idname, struct EnumPropertyItem *items); +wmKeyMap *WM_modalkeymap_get(struct wmKeyConfig *keyconf, const char *idname); +wmKeyMapItem *WM_modalkeymap_add_item(struct wmKeyMap *km, int type, int val, int modifier, int keymodifier, int value); +void WM_modalkeymap_assign(struct wmKeyMap *km, const char *opname); + +/* Keymap Editor */ + +void WM_keymap_restore_to_default(struct wmKeyMap *keymap, struct bContext *C); +void WM_keymap_properties_reset(struct wmKeyMapItem *kmi, struct IDProperty *properties); +void WM_keymap_restore_item_to_default(struct bContext *C, struct wmKeyMap *keymap, struct wmKeyMapItem *kmi); + +/* Key Event */ + +const char *WM_key_event_string(short type); +int WM_key_event_operator_id(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, int hotkey, struct wmKeyMap **keymap_r); +char *WM_key_event_operator_string(const struct bContext *C, const char *opname, int opcontext, struct IDProperty *properties, char *str, int len); + +#ifdef __cplusplus +} +#endif + +#endif /* WM_KEYMAP_H */ + diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index a535c0bc1f8..1d5cf1cdc53 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -210,12 +210,18 @@ void WM_keymap_init(bContext *C) if(!wm->defaultconf) wm->defaultconf= WM_keyconfig_new(wm, "Blender"); + if(!wm->addonconf) + wm->addonconf= WM_keyconfig_new(wm, "Blender Addon"); + if(!wm->userconf) + wm->userconf= WM_keyconfig_new(wm, "Blender User"); - if(wm && CTX_py_init_get(C) && (wm->initialized & WM_INIT_KEYMAP) == 0) { + if(CTX_py_init_get(C) && (wm->initialized & WM_INIT_KEYMAP) == 0) { /* create default key config */ wm_window_keymap(wm->defaultconf); ED_spacetypes_keymap(wm->defaultconf); - WM_keyconfig_userdef(); + + WM_keyconfig_update_tag(NULL, NULL); + WM_keyconfig_update(wm); wm->initialized |= WM_INIT_KEYMAP; } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 2f0c1a72be9..0dac0bd7401 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1735,6 +1735,9 @@ void wm_event_do_handlers(bContext *C) wmWindowManager *wm= CTX_wm_manager(C); wmWindow *win; + /* update key configuration before handling events */ + WM_keyconfig_update(wm); + for(win= wm->windows.first; win; win= win->next) { wmEvent *event; @@ -1938,6 +1941,9 @@ void wm_event_do_handlers(bContext *C) CTX_wm_window_set(C, NULL); } + + /* update key configuration after handling events */ + WM_keyconfig_update(wm); } /* ********** filesector handling ************ */ diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 27fc0caeccc..20f9d2237c2 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -224,6 +224,14 @@ static void wm_window_match_do(bContext *C, ListBase *oldwmlist) oldwm= oldwmlist->first; wm= G.main->wm.first; + /* move addon key configuration to new wm, to preserve their keymaps */ + if(oldwm->addonconf) { + wm->addonconf= oldwm->addonconf; + BLI_remlink(&oldwm->keyconfigs, oldwm->addonconf); + oldwm->addonconf= NULL; + BLI_addtail(&wm->keyconfigs, wm->addonconf); + } + /* ensure making new keymaps and set space types */ wm->initialized= 0; wm->winactive= NULL; @@ -794,11 +802,14 @@ int WM_write_homefile(bContext *C, wmOperator *op) wmWindow *win= CTX_wm_window(C); char filepath[FILE_MAXDIR+FILE_MAXFILE]; int fileflags; - + /* check current window and close it if temp */ if(win->screen->temp) wm_window_close(C, wm, win); + /* update keymaps in user preferences */ + WM_keyconfig_update(wm); + BLI_make_file_string("/", filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_STARTUP_FILE); printf("trying to save homefile at %s ", filepath); diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 1720c738dd7..bf48f0e21e4 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -61,14 +61,67 @@ #include "wm_event_system.h" #include "wm_event_types.h" -/* ********************* key config ***********************/ +/******************************* Keymap Item ********************************** + * Item in a keymap, that maps from an event to an operator or modal map item */ -static void keymap_properties_set(wmKeyMapItem *kmi) +static wmKeyMapItem *wm_keymap_item_copy(wmKeyMapItem *kmi) +{ + wmKeyMapItem *kmin = MEM_dupallocN(kmi); + + kmin->prev= kmin->next= NULL; + kmin->flag &= ~KMI_UPDATE; + + if(kmin->properties) { + kmin->ptr= MEM_callocN(sizeof(PointerRNA), "UserKeyMapItemPtr"); + WM_operator_properties_create(kmin->ptr, kmin->idname); + + kmin->properties= IDP_CopyProperty(kmin->properties); + kmin->ptr->data= kmin->properties; + } + + return kmin; +} + +static void wm_keymap_item_free(wmKeyMapItem *kmi) +{ + /* not kmi itself */ + if(kmi->ptr) { + WM_operator_properties_free(kmi->ptr); + MEM_freeN(kmi->ptr); + } +} + +static void wm_keymap_item_properties_set(wmKeyMapItem *kmi) { WM_operator_properties_alloc(&(kmi->ptr), &(kmi->properties), kmi->idname); WM_operator_properties_sanitize(kmi->ptr, 1); } +static int wm_keymap_item_equals_result(wmKeyMapItem *a, wmKeyMapItem *b) +{ + if(strcmp(a->idname, b->idname) != 0) + return 0; + + if(!((a->ptr==NULL && b->ptr==NULL) || + (a->ptr && b->ptr && IDP_EqualsProperties(a->ptr->data, b->ptr->data)))) + return 0; + + return (a->propvalue == b->propvalue); +} + +static int wm_keymap_item_equals(wmKeyMapItem *a, wmKeyMapItem *b) +{ + return (wm_keymap_item_equals_result(a, b) && + a->type == b->type && + a->val == b->val && + a->shift == b->shift && + a->ctrl == b->ctrl && + a->alt == b->alt && + a->oskey == b->oskey && + a->keymodifier == b->keymodifier && + a->maptype == b->maptype); +} + /* properties can be NULL, otherwise the arg passed is used and ownership is given to the kmi */ void WM_keymap_properties_reset(wmKeyMapItem *kmi, struct IDProperty *properties) { @@ -78,9 +131,41 @@ void WM_keymap_properties_reset(wmKeyMapItem *kmi, struct IDProperty *properties kmi->ptr = NULL; kmi->properties = properties; - keymap_properties_set(kmi); + wm_keymap_item_properties_set(kmi); +} + +/**************************** Keymap Diff Item ********************************* + * Item in a diff keymap, used for saving diff of keymaps in user preferences */ + +static wmKeyMapDiffItem *wm_keymap_diff_item_copy(wmKeyMapDiffItem *kmdi) +{ + wmKeyMapDiffItem *kmdin = MEM_dupallocN(kmdi); + + kmdin->next = kmdin->prev = NULL; + if(kmdi->add_item) + kmdin->add_item = wm_keymap_item_copy(kmdi->add_item); + if(kmdi->remove_item) + kmdin->remove_item = wm_keymap_item_copy(kmdi->remove_item); + + return kmdin; +} + +static void wm_keymap_diff_item_free(wmKeyMapDiffItem *kmdi) +{ + if(kmdi->remove_item) { + wm_keymap_item_free(kmdi->remove_item); + MEM_freeN(kmdi->remove_item); + } + if(kmdi->add_item) { + wm_keymap_item_free(kmdi->add_item); + MEM_freeN(kmdi->add_item); + } } +/***************************** Key Configuration ****************************** + * List of keymaps for all editors, modes, ... . There is a builtin default key + * configuration, a user key configuration, and other preset configurations. */ + wmKeyConfig *WM_keyconfig_new(wmWindowManager *wm, const char *idname) { wmKeyConfig *keyconf; @@ -106,6 +191,7 @@ void WM_keyconfig_remove(wmWindowManager *wm, wmKeyConfig *keyconf) if (keyconf) { if (strncmp(U.keyconfigstr, keyconf->idname, sizeof(U.keyconfigstr)) == 0) { BLI_strncpy(U.keyconfigstr, wm->defaultconf->idname, sizeof(U.keyconfigstr)); + WM_keyconfig_update_tag(NULL, NULL); } BLI_remlink(&wm->keyconfigs, keyconf); @@ -125,21 +211,6 @@ void WM_keyconfig_free(wmKeyConfig *keyconf) MEM_freeN(keyconf); } -void WM_keyconfig_userdef(void) -{ - wmKeyMap *km; - wmKeyMapItem *kmi; - - for(km=U.keymaps.first; km; km=km->next) { - /* modal keymaps don't have operator properties */ - if ((km->flag & KEYMAP_MODAL) == 0) { - for(kmi=km->items.first; kmi; kmi=kmi->next) { - keymap_properties_set(kmi); - } - } - } -} - static wmKeyConfig *wm_keyconfig_list_find(ListBase *lb, char *idname) { wmKeyConfig *kc; @@ -151,23 +222,84 @@ static wmKeyConfig *wm_keyconfig_list_find(ListBase *lb, char *idname) return NULL; } -/* ************************ free ************************* */ +wmKeyConfig *WM_keyconfig_active(wmWindowManager *wm) +{ + wmKeyConfig *keyconf; -void WM_keymap_free(wmKeyMap *keymap) + /* first try from preset */ + keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr); + if(keyconf) + return keyconf; + + /* otherwise use default */ + return wm->defaultconf; +} + +void WM_keyconfig_set_active(wmWindowManager *wm, const char *idname) { - wmKeyMapItem *kmi; + /* setting a different key configuration as active: we ensure all is + updated properly before and after making the change */ + + WM_keyconfig_update(wm); + + BLI_strncpy(U.keyconfigstr, idname, sizeof(U.keyconfigstr)); + + WM_keyconfig_update_tag(NULL, NULL); + WM_keyconfig_update(wm); +} + +/********************************** Keymap ************************************* + * List of keymap items for one editor, mode, modal operator, ... */ + +static wmKeyMap *wm_keymap_new(const char *idname, int spaceid, int regionid) +{ + wmKeyMap *km= MEM_callocN(sizeof(struct wmKeyMap), "keymap list"); + + BLI_strncpy(km->idname, idname, KMAP_MAX_NAME); + km->spaceid= spaceid; + km->regionid= regionid; + + return km; +} + +static wmKeyMap *wm_keymap_copy(wmKeyMap *keymap) +{ + wmKeyMap *keymapn = MEM_dupallocN(keymap); + wmKeyMapItem *kmi, *kmin; + wmKeyMapDiffItem *kmdi, *kmdin; + + keymapn->modal_items= keymap->modal_items; + keymapn->poll= keymap->poll; + keymapn->items.first= keymapn->items.last= NULL; + keymapn->flag &= ~(KEYMAP_UPDATE|KEYMAP_EXPANDED); + + for(kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next) { + kmdin= wm_keymap_diff_item_copy(kmdi); + BLI_addtail(&keymapn->items, kmdin); + } for(kmi=keymap->items.first; kmi; kmi=kmi->next) { - if(kmi->ptr) { - WM_operator_properties_free(kmi->ptr); - MEM_freeN(kmi->ptr); - } + kmin= wm_keymap_item_copy(kmi); + BLI_addtail(&keymapn->items, kmin); } - BLI_freelistN(&keymap->items); + return keymapn; } -/* ***************** generic call, exported **************** */ +void WM_keymap_free(wmKeyMap *keymap) +{ + wmKeyMapItem *kmi; + wmKeyMapDiffItem *kmdi; + + for(kmdi=keymap->diff_items.first; kmdi; kmdi=kmdi->next) + wm_keymap_diff_item_free(kmdi); + + for(kmi=keymap->items.first; kmi; kmi=kmi->next) + wm_keymap_item_free(kmi); + + BLI_freelistN(&keymap->diff_items); + BLI_freelistN(&keymap->items); +} static void keymap_event_set(wmKeyMapItem *kmi, short type, short val, int modifier, short keymodifier) { @@ -229,7 +361,7 @@ wmKeyMapItem *WM_keymap_verify_item(wmKeyMap *keymap, const char *idname, int ty keymap_item_set_id(keymap, kmi); keymap_event_set(kmi, type, val, modifier, keymodifier); - keymap_properties_set(kmi); + wm_keymap_item_properties_set(kmi); } return kmi; } @@ -243,10 +375,12 @@ wmKeyMapItem *WM_keymap_add_item(wmKeyMap *keymap, const char *idname, int type, BLI_strncpy(kmi->idname, idname, OP_MAX_TYPENAME); keymap_event_set(kmi, type, val, modifier, keymodifier); - keymap_properties_set(kmi); + wm_keymap_item_properties_set(kmi); keymap_item_set_id(keymap, kmi); + WM_keyconfig_update_tag(keymap, kmi); + return kmi; } @@ -266,6 +400,232 @@ void WM_keymap_remove_item(wmKeyMap *keymap, wmKeyMapItem *kmi) MEM_freeN(kmi->ptr); } BLI_freelinkN(&keymap->items, kmi); + + WM_keyconfig_update_tag(keymap, kmi); + } +} + +/************************** Keymap Diff and Patch **************************** + * Rather than saving the entire keymap for user preferences, we only save a + * diff so that changes in the defaults get synced. This system is not perfect + * but works better than overriding the keymap entirely when only few items + * are changed. */ + +static void wm_keymap_addon_add(wmKeyMap *keymap, wmKeyMap *addonmap) +{ + wmKeyMapItem *kmi, *kmin; + + for(kmi=addonmap->items.first; kmi; kmi=kmi->next) { + kmin = wm_keymap_item_copy(kmi); + keymap_item_set_id(keymap, kmin); + BLI_addhead(&keymap->items, kmin); + } +} + +static wmKeyMapItem *wm_keymap_find_item_equals(wmKeyMap *km, wmKeyMapItem *needle) +{ + wmKeyMapItem *kmi; + + for(kmi=km->items.first; kmi; kmi=kmi->next) + if(wm_keymap_item_equals(kmi, needle)) + return kmi; + + return NULL; +} + +static wmKeyMapItem *wm_keymap_find_item_equals_result(wmKeyMap *km, wmKeyMapItem *needle) +{ + wmKeyMapItem *kmi; + + for(kmi=km->items.first; kmi; kmi=kmi->next) + if(wm_keymap_item_equals_result(kmi, needle)) + return kmi; + + return NULL; +} + +static void wm_keymap_diff(wmKeyMap *diff_km, wmKeyMap *from_km, wmKeyMap *to_km, wmKeyMap *orig_km, wmKeyMap *addon_km) +{ + wmKeyMapItem *kmi, *to_kmi, *orig_kmi; + wmKeyMapDiffItem *kmdi; + + for(kmi=from_km->items.first; kmi; kmi=kmi->next) { + to_kmi = WM_keymap_item_find_id(to_km, kmi->id); + + if(!to_kmi) { + /* remove item */ + kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); + kmdi->remove_item = wm_keymap_item_copy(kmi); + BLI_addtail(&diff_km->diff_items, kmdi); + } + else if(to_kmi && !wm_keymap_item_equals(kmi, to_kmi)) { + /* replace item */ + kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); + kmdi->remove_item = wm_keymap_item_copy(kmi); + kmdi->add_item = wm_keymap_item_copy(to_kmi); + BLI_addtail(&diff_km->diff_items, kmdi); + } + + /* sync expanded flag back to original so we don't loose it on repatch */ + if(to_kmi) { + orig_kmi = WM_keymap_item_find_id(orig_km, kmi->id); + + if(!orig_kmi) + orig_kmi = wm_keymap_find_item_equals(addon_km, kmi); + + if(orig_kmi) { + orig_kmi->flag &= ~KMI_EXPANDED; + orig_kmi->flag |= (to_kmi->flag & KMI_EXPANDED); + } + } + } + + for(kmi=to_km->items.first; kmi; kmi=kmi->next) { + if(kmi->id < 0) { + /* add item */ + kmdi = MEM_callocN(sizeof(wmKeyMapDiffItem), "wmKeyMapDiffItem"); + kmdi->add_item = wm_keymap_item_copy(kmi); + BLI_addtail(&diff_km->diff_items, kmdi); + } + } +} + +static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km) +{ + wmKeyMapDiffItem *kmdi; + wmKeyMapItem *kmi_remove, *kmi_add; + + for(kmdi=diff_km->diff_items.first; kmdi; kmdi=kmdi->next) { + /* find item to remove */ + kmi_remove = NULL; + if(kmdi->remove_item) { + kmi_remove = wm_keymap_find_item_equals(km, kmdi->remove_item); + if(!kmi_remove) + kmi_remove = wm_keymap_find_item_equals_result(km, kmdi->remove_item); + } + + /* add item */ + if(kmdi->add_item) { + /* only if nothing to remove or item to remove found */ + if(!kmdi->remove_item || kmi_remove) { + kmi_add = wm_keymap_item_copy(kmdi->add_item); + kmi_add->flag |= KMI_USER_MODIFIED; + + if(kmi_remove) { + kmi_add->flag &= ~KMI_EXPANDED; + kmi_add->flag |= (kmi_remove->flag & KMI_EXPANDED); + kmi_add->id = kmi_remove->id; + BLI_insertlinkbefore(&km->items, kmi_remove, kmi_add); + } + else { + keymap_item_set_id(km, kmi_add); + BLI_addtail(&km->items, kmi_add); + } + } + } + + /* remove item */ + if(kmi_remove) { + wm_keymap_item_free(kmi_remove); + BLI_freelinkN(&km->items, kmi_remove); + } + } +} + +static void wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *usermap) +{ + wmKeyMap *km; + int expanded = 0; + + /* remove previous keymap in list, we will replace it */ + km = WM_keymap_list_find(lb, defaultmap->idname, defaultmap->spaceid, defaultmap->regionid); + if(km) { + expanded = (km->flag & (KEYMAP_EXPANDED|KEYMAP_CHILDREN_EXPANDED)); + WM_keymap_free(km); + BLI_freelinkN(lb, km); + } + + /* copy new keymap from an existing one */ + if(usermap && !(usermap->flag & KEYMAP_DIFF)) { + /* for compatibiltiy with old user preferences with non-diff + keymaps we override the original entirely */ + wmKeyMapItem *kmi, *orig_kmi; + + km = wm_keymap_copy(usermap); + km->modal_items = defaultmap->modal_items; + km->poll = defaultmap->poll; + + /* try to find corresponding id's for items */ + for(kmi=km->items.first; kmi; kmi=kmi->next) { + orig_kmi = wm_keymap_find_item_equals(defaultmap, kmi); + if(!orig_kmi) + orig_kmi = wm_keymap_find_item_equals_result(defaultmap, kmi); + + if(orig_kmi) + kmi->id = orig_kmi->id; + else + kmi->id = -(km->kmi_id++); + } + + km->flag |= KEYMAP_UPDATE; /* update again to create diff */ + } + else + km = wm_keymap_copy(defaultmap); + + /* add addon keymap items */ + if(addonmap) + wm_keymap_addon_add(km, addonmap); + + /* tag as being user edited */ + if(usermap) + km->flag |= KEYMAP_USER_MODIFIED; + km->flag |= KEYMAP_USER|expanded; + + /* apply user changes of diff keymap */ + if(usermap && (usermap->flag & KEYMAP_DIFF)) + wm_keymap_patch(km, usermap); + + /* add to list */ + BLI_addtail(lb, km); +} + +static void wm_keymap_diff_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *km) +{ + wmKeyMap *diffmap, *prevmap, *origmap; + + /* create temporary default + addon keymap for diff */ + origmap = defaultmap; + + if(addonmap) { + defaultmap = wm_keymap_copy(defaultmap); + wm_keymap_addon_add(defaultmap, addonmap); + } + + /* remove previous diff keymap in list, we will replace it */ + prevmap = WM_keymap_list_find(lb, km->idname, km->spaceid, km->regionid); + if(prevmap) { + WM_keymap_free(prevmap); + BLI_freelinkN(lb, prevmap); + } + + /* create diff keymap */ + diffmap= wm_keymap_new(km->idname, km->spaceid, km->regionid); + diffmap->flag |= KEYMAP_DIFF; + wm_keymap_diff(diffmap, defaultmap, km, origmap, addonmap); + + /* add to list if not empty */ + if(diffmap->diff_items.first) { + BLI_addtail(lb, diffmap); + } + else { + WM_keymap_free(diffmap); + MEM_freeN(diffmap); + } + + /* free temporary default map */ + if(addonmap) { + WM_keymap_free(defaultmap); + MEM_freeN(defaultmap); } } @@ -292,11 +652,10 @@ wmKeyMap *WM_keymap_find(wmKeyConfig *keyconf, const char *idname, int spaceid, wmKeyMap *km= WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid); if(km==NULL) { - km= MEM_callocN(sizeof(struct wmKeyMap), "keymap list"); - BLI_strncpy(km->idname, idname, KMAP_MAX_NAME); - km->spaceid= spaceid; - km->regionid= regionid; + km= wm_keymap_new(idname, spaceid, regionid); BLI_addtail(&keyconf->keymaps, km); + + WM_keyconfig_update_tag(km, NULL); } return km; @@ -304,29 +663,9 @@ wmKeyMap *WM_keymap_find(wmKeyConfig *keyconf, const char *idname, int spaceid, wmKeyMap *WM_keymap_find_all(const bContext *C, const char *idname, int spaceid, int regionid) { - wmWindowManager *wm = CTX_wm_manager(C); - wmKeyConfig *keyconf; - wmKeyMap *km; - - /* first user defined keymaps */ - km= WM_keymap_list_find(&U.keymaps, idname, spaceid, regionid); - if (km) - return km; - - /* then user key config */ - keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr); - if(keyconf) { - km= WM_keymap_list_find(&keyconf->keymaps, idname, spaceid, regionid); - if (km) - return km; - } - - /* then use default */ - km= WM_keymap_list_find(&wm->defaultconf->keymaps, idname, spaceid, regionid); - if (km) - return km; - else - return NULL; + wmWindowManager *wm= CTX_wm_manager(C); + + return WM_keymap_list_find(&wm->userconf->keymaps, idname, spaceid, regionid); } /* ****************** modal keymaps ************ */ @@ -366,6 +705,8 @@ wmKeyMapItem *WM_modalkeymap_add_item(wmKeyMap *km, int type, int val, int modif keymap_item_set_id(km, kmi); + WM_keyconfig_update_tag(km, kmi); + return kmi; } @@ -588,169 +929,209 @@ int WM_keymap_item_compare(wmKeyMapItem *k1, wmKeyMapItem *k2) return 1; } -/* ***************** user preferences ******************* */ +/************************* Update Final Configuration ************************* + * On load or other changes, the final user key configuration is rebuilt from + * the preset, addon and user preferences keymaps. We also test if the final + * configuration changed and write the changes to the user preferences. */ + +static int WM_KEYMAP_UPDATE = 0; -int WM_keymap_user_init(wmWindowManager *wm, wmKeyMap *keymap) +void WM_keyconfig_update_tag(wmKeyMap *km, wmKeyMapItem *kmi) { - wmKeyConfig *keyconf; - wmKeyMap *km; + /* quick tag to do delayed keymap updates */ + WM_KEYMAP_UPDATE= 1; - if(!keymap) - return 0; + if(km) + km->flag |= KEYMAP_UPDATE; + if(kmi) + kmi->flag |= KMI_UPDATE; +} - /* init from user key config */ - keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr); - if(keyconf) { - km= WM_keymap_list_find(&keyconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); - if(km) { - keymap->poll= km->poll; /* lazy init */ - keymap->modal_items= km->modal_items; - return 1; - } - } +static int wm_keymap_test_and_clear_update(wmKeyMap *km) +{ + wmKeyMapItem *kmi; + int update; + + update= (km->flag & KEYMAP_UPDATE); + km->flag &= ~KEYMAP_UPDATE; - /* or from default */ - km= WM_keymap_list_find(&wm->defaultconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); - if(km) { - keymap->poll= km->poll; /* lazy init */ - keymap->modal_items= km->modal_items; - return 1; + for(kmi=km->items.first; kmi; kmi=kmi->next) { + update= update || (kmi->flag & KMI_UPDATE); + kmi->flag &= ~KMI_UPDATE; } - - return 0; + + return update; } -wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap) +static wmKeyMap *wm_keymap_preset(wmWindowManager *wm, wmKeyMap *km) { - wmKeyConfig *keyconf; - wmKeyMap *km; + wmKeyConfig *keyconf= WM_keyconfig_active(wm); + wmKeyMap *keymap; + keymap= WM_keymap_list_find(&keyconf->keymaps, km->idname, km->spaceid, km->regionid); if(!keymap) - return NULL; - - /* first user defined keymaps */ - km= WM_keymap_list_find(&U.keymaps, keymap->idname, keymap->spaceid, keymap->regionid); - if(km) { - km->poll= keymap->poll; /* lazy init */ - km->modal_items= keymap->modal_items; - return km; - } - - /* then user key config */ - keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr); - if(keyconf) { - km= WM_keymap_list_find(&keyconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); - if(km) { - km->poll= keymap->poll; /* lazy init */ - km->modal_items= keymap->modal_items; - return km; - } - } + keymap= WM_keymap_list_find(&wm->defaultconf->keymaps, km->idname, km->spaceid, km->regionid); - /* then use default */ - km= WM_keymap_list_find(&wm->defaultconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); - return km; + return keymap; } -wmKeyMap *WM_keymap_copy_to_user(wmKeyMap *keymap) +void WM_keyconfig_update(wmWindowManager *wm) { - wmKeyMap *usermap; + wmKeyMap *km, *defaultmap, *addonmap, *usermap; wmKeyMapItem *kmi; + wmKeyMapDiffItem *kmdi; + int compat_update = 0; - usermap= WM_keymap_list_find(&U.keymaps, keymap->idname, keymap->spaceid, keymap->regionid); - - /* XXX this function is only used by RMB setting hotkeys, and it clears maps on 2nd try this way */ - if(keymap==usermap) - return keymap; + if(!WM_KEYMAP_UPDATE) + return; - if(!usermap) { - /* not saved yet, duplicate existing */ - usermap= MEM_dupallocN(keymap); - usermap->modal_items= NULL; - usermap->poll= NULL; - usermap->flag |= KEYMAP_USER; + /* update operator properties for non-modal user keymaps */ + for(km=U.user_keymaps.first; km; km=km->next) { + if((km->flag & KEYMAP_MODAL) == 0) { + for(kmdi=km->diff_items.first; kmdi; kmdi=kmdi->next) { + if(kmdi->add_item) + wm_keymap_item_properties_set(kmdi->add_item); + if(kmdi->remove_item) + wm_keymap_item_properties_set(kmdi->remove_item); + } - BLI_addtail(&U.keymaps, usermap); + for(kmi=km->items.first; kmi; kmi=kmi->next) + wm_keymap_item_properties_set(kmi); + } } - else { - /* already saved, free items for re-copy */ - WM_keymap_free(usermap); + + /* update U.user_keymaps with user key configuration changes */ + for(km=wm->userconf->keymaps.first; km; km=km->next) { + /* only diff if the user keymap was modified */ + if(wm_keymap_test_and_clear_update(km)) { + /* find keymaps */ + defaultmap= wm_keymap_preset(wm, km); + addonmap= WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid); + + /* diff */ + wm_keymap_diff_update(&U.user_keymaps, defaultmap, addonmap, km); + } } - BLI_duplicatelist(&usermap->items, &keymap->items); + /* create user key configuration from preset + addon + user preferences */ + for(km=wm->defaultconf->keymaps.first; km; km=km->next) { + /* find keymaps */ + defaultmap= wm_keymap_preset(wm, km); + addonmap= WM_keymap_list_find(&wm->addonconf->keymaps, km->idname, km->spaceid, km->regionid); + usermap= WM_keymap_list_find(&U.user_keymaps, km->idname, km->spaceid, km->regionid); - for(kmi=usermap->items.first; kmi; kmi=kmi->next) { - if(kmi->properties) { - kmi->ptr= MEM_callocN(sizeof(PointerRNA), "UserKeyMapItemPtr"); - WM_operator_properties_create(kmi->ptr, kmi->idname); + /* add */ + wm_keymap_patch_update(&wm->userconf->keymaps, defaultmap, addonmap, usermap); - kmi->properties= IDP_CopyProperty(kmi->properties); - kmi->ptr->data= kmi->properties; - } + /* in case of old non-diff keymaps, force extra update to create diffs */ + compat_update = compat_update || (usermap && !(usermap->flag & KEYMAP_DIFF)); } - for(kmi=keymap->items.first; kmi; kmi=kmi->next) - kmi->flag &= ~KMI_EXPANDED; + WM_KEYMAP_UPDATE= 0; + + if(compat_update) { + WM_keyconfig_update_tag(NULL, NULL); + WM_keyconfig_update(wm); + } +} + +/********************************* Event Handling ***************************** + * Handlers have pointers to the keymap in the default configuration. During + * event handling this function is called to get the keymap from the final + * configuration. */ + +wmKeyMap *WM_keymap_active(wmWindowManager *wm, wmKeyMap *keymap) +{ + wmKeyMap *km; + + if(!keymap) + return NULL; + + /* first user defined keymaps */ + km= WM_keymap_list_find(&wm->userconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); + + if(km) + return km; - return usermap; + return keymap; } +/******************************* Keymap Editor ******************************** + * In the keymap editor the user key configuration is edited. */ + void WM_keymap_restore_item_to_default(bContext *C, wmKeyMap *keymap, wmKeyMapItem *kmi) { wmWindowManager *wm = CTX_wm_manager(C); - wmKeyConfig *keyconf; - wmKeyMap *km = NULL; + wmKeyMap *defaultmap, *addonmap; + wmKeyMapItem *orig; - /* look in user key config */ - keyconf= wm_keyconfig_list_find(&wm->keyconfigs, U.keyconfigstr); - if(keyconf) { - km= WM_keymap_list_find(&keyconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); - } + if(!keymap) + return; + + /* construct default keymap from preset + addons */ + defaultmap= wm_keymap_preset(wm, keymap); + addonmap= WM_keymap_list_find(&wm->addonconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); - if (!km) { - /* or from default */ - km= WM_keymap_list_find(&wm->defaultconf->keymaps, keymap->idname, keymap->spaceid, keymap->regionid); + if(addonmap) { + defaultmap = wm_keymap_copy(defaultmap); + wm_keymap_addon_add(defaultmap, addonmap); } - if (km) { - wmKeyMapItem *orig = WM_keymap_item_find_id(km, kmi->id); + /* find original item */ + orig = WM_keymap_item_find_id(defaultmap, kmi->id); - if (orig) { - if(strcmp(orig->idname, kmi->idname) != 0) { - BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname)); + if(orig) { + /* restore to original */ + if(strcmp(orig->idname, kmi->idname) != 0) { + BLI_strncpy(kmi->idname, orig->idname, sizeof(kmi->idname)); + WM_keymap_properties_reset(kmi, NULL); + } - WM_keymap_properties_reset(kmi, NULL); - } - - if (orig->properties) { - kmi->properties= IDP_CopyProperty(orig->properties); - kmi->ptr->data= kmi->properties; + if (orig->properties) { + if(kmi->properties) { + IDP_FreeProperty(kmi->properties); + MEM_freeN(kmi->properties); + kmi->properties= NULL; } - kmi->propvalue = orig->propvalue; - kmi->type = orig->type; - kmi->val = orig->val; - kmi->shift = orig->shift; - kmi->ctrl = orig->ctrl; - kmi->alt = orig->alt; - kmi->oskey = orig->oskey; - kmi->keymodifier = orig->keymodifier; - kmi->maptype = orig->maptype; - + kmi->properties= IDP_CopyProperty(orig->properties); + kmi->ptr->data= kmi->properties; } + kmi->propvalue = orig->propvalue; + kmi->type = orig->type; + kmi->val = orig->val; + kmi->shift = orig->shift; + kmi->ctrl = orig->ctrl; + kmi->alt = orig->alt; + kmi->oskey = orig->oskey; + kmi->keymodifier = orig->keymodifier; + kmi->maptype = orig->maptype; + + WM_keyconfig_update_tag(keymap, kmi); + } + + /* free temporary keymap */ + if(addonmap) { + WM_keymap_free(defaultmap); + MEM_freeN(defaultmap); } } -void WM_keymap_restore_to_default(wmKeyMap *keymap) +void WM_keymap_restore_to_default(wmKeyMap *keymap, bContext *C) { + wmWindowManager *wm = CTX_wm_manager(C); wmKeyMap *usermap; - usermap= WM_keymap_list_find(&U.keymaps, keymap->idname, keymap->spaceid, keymap->regionid); + /* remove keymap from U.user_keymaps and update */ + usermap= WM_keymap_list_find(&U.user_keymaps, keymap->idname, keymap->spaceid, keymap->regionid); if(usermap) { WM_keymap_free(usermap); - BLI_freelinkN(&U.keymaps, usermap); + BLI_freelinkN(&U.user_keymaps, usermap); + + WM_keyconfig_update_tag(NULL, NULL); + WM_keyconfig_update(wm); } } @@ -951,3 +1332,4 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname) return km; } + diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 548d272ffd2..983d4ecf5f8 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -208,10 +208,12 @@ struct wmKeyMap *WM_keymap_list_find(struct ListBase *lb, char *idname, int spac struct wmKeyConfig *WM_keyconfig_new(struct wmWindowManager *wm, char *idname){return (struct wmKeyConfig *) NULL;} struct wmKeyConfig *WM_keyconfig_new_user(struct wmWindowManager *wm, char *idname){return (struct wmKeyConfig *) NULL;} void WM_keyconfig_remove(struct wmWindowManager *wm, char *idname){} +void WM_keyconfig_set_active(struct wmWindowManager *wm, const char *idname) {} void WM_keymap_remove_item(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi){} void WM_keymap_restore_to_default(struct wmKeyMap *keymap){} void WM_keymap_restore_item_to_default(struct bContext *C, struct wmKeyMap *keymap, struct wmKeyMapItem *kmi){} void WM_keymap_properties_reset(struct wmKeyMapItem *kmi){} +void WM_keyconfig_update_tag(struct wmKeyMap *keymap, struct wmKeyMapItem *kmi) {} int WM_keymap_user_init(struct wmWindowManager *wm, struct wmKeyMap *keymap) {return 0;} int WM_keymap_item_compare(struct wmKeyMapItem *k1, struct wmKeyMapItem *k2){return 0;} -- cgit v1.2.3 From d78be1f76209bed9924ff2439ac3f817aee7966c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 6 Aug 2011 04:19:30 +0000 Subject: remove copy modifiers function, now handled in link data operator. --- source/blender/editors/object/object_edit.c | 107 +--------------------------- 1 file changed, 3 insertions(+), 104 deletions(-) diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 395705dc029..c8d38218533 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1049,109 +1049,6 @@ static void copymenu_logicbricks(Scene *scene, View3D *v3d, Object *ob) } } -static void copymenu_modifiers(Main *bmain, Scene *scene, View3D *v3d, Object *ob) -{ - Base *base; - int i, event; - char str[512]; - const char *errorstr= NULL; - - strcpy(str, "Copy Modifiers %t"); - - sprintf(str+strlen(str), "|All%%x%d|%%l", NUM_MODIFIER_TYPES); - - for (i=eModifierType_None+1; iflags&eModifierTypeFlag_AcceptsCVs) || - (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) { - sprintf(str+strlen(str), "|%s%%x%d", mti->name, i); - } - } - - event = pupmenu(str); - if(event<=0) return; - - for (base= FIRSTBASE; base; base= base->next) { - if(base->object != ob) { - if(TESTBASELIB(v3d, base)) { - - base->object->recalc |= OB_RECALC_OB|OB_RECALC_DATA; - - if (base->object->type==ob->type) { - /* copy all */ - if (event==NUM_MODIFIER_TYPES) { - ModifierData *md; - object_free_modifiers(base->object); - - for (md=ob->modifiers.first; md; md=md->next) { - ModifierData *nmd = NULL; - - if(ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_ParticleInstance)) continue; - - if(md->type == eModifierType_Collision) - continue; - - nmd = modifier_new(md->type); - modifier_copyData(md, nmd); - BLI_addtail(&base->object->modifiers, nmd); - modifier_unique_name(&base->object->modifiers, nmd); - } - - copy_object_particlesystems(base->object, ob); - copy_object_softbody(base->object, ob); - } else { - /* copy specific types */ - ModifierData *md, *mdn; - - /* remove all with type 'event' */ - for (md=base->object->modifiers.first; md; md=mdn) { - mdn= md->next; - if(md->type==event) { - BLI_remlink(&base->object->modifiers, md); - modifier_free(md); - } - } - - /* copy all with type 'event' */ - for (md=ob->modifiers.first; md; md=md->next) { - if (md->type==event) { - - mdn = modifier_new(event); - BLI_addtail(&base->object->modifiers, mdn); - modifier_unique_name(&base->object->modifiers, mdn); - - modifier_copyData(md, mdn); - } - } - - if(event == eModifierType_ParticleSystem) { - object_free_particlesystems(base->object); - copy_object_particlesystems(base->object, ob); - } - else if(event == eModifierType_Softbody) { - object_free_softbody(base->object); - copy_object_softbody(base->object, ob); - } - } - } - else - errorstr= "Did not copy modifiers to other Object types"; - } - } - } - -// if(errorstr) notice(errorstr); - - DAG_scene_sort(bmain, scene); - -} - /* both pointers should exist */ static void copy_texture_space(Object *to, Object *ob) { @@ -1196,6 +1093,7 @@ static void copy_texture_space(Object *to, Object *ob) } +/* UNUSED, keep incase we want to copy functionality for use elsewhere */ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) { Object *ob; @@ -1221,7 +1119,8 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) return; } else if(event==24) { - copymenu_modifiers(bmain, scene, v3d, ob); + /* moved to object_link_modifiers */ + /* copymenu_modifiers(bmain, scene, v3d, ob); */ return; } -- cgit v1.2.3 From dc4dede8029801580683551b39f967c206720736 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 6 Aug 2011 06:38:18 +0000 Subject: for UI text drawing use BLF_ascender(fs->uifont_id) rather then BLF_height(fs->uifont_id, "2"), while profiling draw noticed that the hash lookup on the character and utf8 next were being called on every text draw, use BLF_ascender since it doesn't do any lookups. --- source/blender/editors/interface/interface_style.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c index 5f2a757d2e3..8d4b4209120 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.c @@ -149,9 +149,9 @@ void uiStyleFontDrawExt(uiFontStyle *fs, rcti *rect, const char *str, int xofs=0, yofs; uiStyleFontSet(fs); - - height= BLF_height(fs->uifont_id, "2"); /* correct offset is on baseline, the j is below that */ - yofs= floor( 0.5f*(rect->ymax - rect->ymin - height)); + + height= BLF_ascender(fs->uifont_id); + yofs= ceil( 0.5f*(rect->ymax - rect->ymin - height)); if(fs->align==UI_STYLE_TEXT_CENTER) { xofs= floor( 0.5f*(rect->xmax - rect->xmin - BLF_width(fs->uifont_id, str))); @@ -206,9 +206,9 @@ void uiStyleFontDrawRotated(uiFontStyle *fs, rcti *rect, const char *str) uiStyleFontSet(fs); - height= BLF_height(fs->uifont_id, "2"); /* correct offset is on baseline, the j is below that */ + height= BLF_ascender(fs->uifont_id); /* becomes x-offset when rotated */ - xofs= floor( 0.5f*(rect->ymax - rect->ymin - height)) + 1; + xofs= ceil( 0.5f*(rect->ymax - rect->ymin - height)); /* ignore UI_STYLE, always aligned to top */ -- cgit v1.2.3 From 2f5809d8317e8dd7a3e4edc30a6f709fb632bb83 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 6 Aug 2011 14:57:55 +0000 Subject: make ui_def_but_rna into 2 functions, once which takes a prop, another which takes a propname, no functional change yet but lets us avoid duplicate hash lookups. --- source/blender/editors/interface/interface.c | 238 ++++++++++++++------------- 1 file changed, 128 insertions(+), 110 deletions(-) diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 8aed0d58a07..78e24c3bccb 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2490,138 +2490,141 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, return but; } -static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *str, int x1, int y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip) +/* ui_def_but_rna_propname and ui_def_but_rna + * both take the same args except for propname vs prop, this is done so we can + * avoid an extra lookup on 'prop' when its already available. + * + * When this kind of change won't disrupt branches, best look into making more + * of our UI functions take prop rather then propname. + */ + +#define UI_DEF_BUT_RNA_DISABLE(but) \ + but->flag |= UI_BUT_DISABLED; \ + but->lock = 1; \ + but->lockstr = "" + + +static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *str, int x1, int y1, short x2, short y2, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip) { uiBut *but; - PropertyRNA *prop; PropertyType proptype; int freestr= 0, icon= 0; - prop= RNA_struct_find_property(ptr, propname); + proptype= RNA_property_type(prop); - if(prop) { - proptype= RNA_property_type(prop); - - /* use rna values if parameters are not specified */ - if(!str) { - if(type == MENU && proptype == PROP_ENUM) { - EnumPropertyItem *item; - DynStr *dynstr; - int i, totitem, value, free; - - RNA_property_enum_items(block->evil_C, ptr, prop, &item, &totitem, &free); - value= RNA_property_enum_get(ptr, prop); - - dynstr= BLI_dynstr_new(); - BLI_dynstr_appendf(dynstr, "%s%%t", RNA_property_ui_name(prop)); - for(i=0; ievil_C, ptr, prop, &item, &totitem, &free); + value= RNA_property_enum_get(ptr, prop); + + dynstr= BLI_dynstr_new(); + BLI_dynstr_appendf(dynstr, "%s%%t", RNA_property_ui_name(prop)); + for(i=0; ievil_C, ptr, prop, &item, &totitem, &free); - for(i=0; ievil_C, ptr, prop, &item, &totitem, &free); + for(i=0; itype), propname); - str= propname; } /* now create button */ but= ui_def_but(block, type, retval, str, x1, y1, x2, y2, NULL, min, max, a1, a2, tip); - if(prop) { - but->rnapoin= *ptr; - but->rnaprop= prop; + but->rnapoin= *ptr; + but->rnaprop= prop; - if(RNA_property_array_length(&but->rnapoin, but->rnaprop)) - but->rnaindex= index; - else - but->rnaindex= 0; - } + if(RNA_property_array_length(&but->rnapoin, but->rnaprop)) + but->rnaindex= index; + else + but->rnaindex= 0; if(icon) { but->icon= (BIFIconID)icon; @@ -2629,10 +2632,8 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s but->flag|= UI_ICON_LEFT; } - if (!prop || !RNA_property_editable(&but->rnapoin, prop)) { - but->flag |= UI_BUT_DISABLED; - but->lock = 1; - but->lockstr = ""; + if (!RNA_property_editable(&but->rnapoin, prop)) { + UI_DEF_BUT_RNA_DISABLE(but); } /* If this button uses units, calculate the step from this */ @@ -2645,6 +2646,23 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s return but; } +static uiBut *ui_def_but_rna_propname(uiBlock *block, int type, int retval, const char *str, int x1, int y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip) +{ + PropertyRNA *prop= RNA_struct_find_property(ptr, propname); + uiBut *but; + + if(prop) { + but= ui_def_but_rna(block, type, retval, str, x1, y1, x2, y2, ptr, prop, index, min, max, a1, a2, tip); + } + else { + but= ui_def_but(block, type, retval, propname, x1, y1, x2, y2, NULL, min, max, a1, a2, tip); + + UI_DEF_BUT_RNA_DISABLE(but); + } + + return but; +} + static uiBut *ui_def_but_operator(uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x1, int y1, short x2, short y2, const char *tip) { uiBut *but; @@ -2857,7 +2875,7 @@ uiBut *uiDefButR(uiBlock *block, int type, int retval, const char *str, int x1, { uiBut *but; - but= ui_def_but_rna(block, type, retval, str, x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip); + but= ui_def_but_rna_propname(block, type, retval, str, x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip); if(but) ui_check_but(but); @@ -2942,7 +2960,7 @@ uiBut *uiDefIconButR(uiBlock *block, int type, int retval, int icon, int x1, int { uiBut *but; - but= ui_def_but_rna(block, type, retval, "", x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip); + but= ui_def_but_rna_propname(block, type, retval, "", x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip); if(but) { if(icon) { but->icon= (BIFIconID) icon; @@ -3027,7 +3045,7 @@ uiBut *uiDefIconTextButR(uiBlock *block, int type, int retval, int icon, const c { uiBut *but; - but= ui_def_but_rna(block, type, retval, str, x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip); + but= ui_def_but_rna_propname(block, type, retval, str, x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip); if(but) { if(icon) { but->icon= (BIFIconID) icon; -- cgit v1.2.3 From 79e359f92af3b26d10c3f65ba9548863b7010546 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 6 Aug 2011 16:00:00 +0000 Subject: rna/ui: avoid duplicate property gHash lookups by passing the property when its already been found. added _prop suffix to ui functions which take a prop rather then a propname, may change this later since its not that nice but for gsoc branches this keeps existing UI functions working the same. --- source/blender/editors/include/UI_interface.h | 3 + source/blender/editors/interface/interface.c | 102 +++++++++------------ .../blender/editors/interface/interface_layout.c | 18 ++-- .../blender/editors/interface/interface_regions.c | 29 +++--- .../editors/interface/interface_templates.c | 14 +-- source/blender/editors/interface/interface_utils.c | 43 ++++----- 6 files changed, 95 insertions(+), 114 deletions(-) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 1bae6ce0214..3fe012ea73e 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -410,6 +410,7 @@ uiBut *uiDefButBitS(uiBlock *block, int type, int bit, int retval, const char *s uiBut *uiDefButC(uiBlock *block, int type, int retval, const char *str, int x1, int y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, const char *tip); uiBut *uiDefButBitC(uiBlock *block, int type, int bit, int retval, const char *str, int x1, int y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, const char *tip); uiBut *uiDefButR(uiBlock *block, int type, int retval, const char *str, int x1, int y1, short x2, short y2, struct PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip); +uiBut *uiDefButR_prop(uiBlock *block, int type, int retval, const char *str, int x1, int y1, short x2, short y2, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip); uiBut *uiDefButO(uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x1, int y1, short x2, short y2, const char *tip); uiBut *uiDefButTextO(uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x1, int y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, const char *tip); @@ -429,6 +430,7 @@ uiBut *uiDefIconButBitS(uiBlock *block, int type, int bit, int retval, int icon, uiBut *uiDefIconButC(uiBlock *block, int type, int retval, int icon, int x1, int y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, const char *tip); uiBut *uiDefIconButBitC(uiBlock *block, int type, int bit, int retval, int icon, int x1, int y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, const char *tip); uiBut *uiDefIconButR(uiBlock *block, int type, int retval, int icon, int x1, int y1, short x2, short y2, struct PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip); +uiBut *uiDefIconButR_prop(uiBlock *block, int type, int retval, int icon, int x1, int y1, short x2, short y2, struct PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip); uiBut *uiDefIconButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, int x1, int y1, short x2, short y2, const char *tip); uiBut *uiDefIconTextBut(uiBlock *block, @@ -447,6 +449,7 @@ uiBut *uiDefIconTextButBitS(uiBlock *block, int type, int bit, int retval, int i uiBut *uiDefIconTextButC(uiBlock *block, int type, int retval, int icon, const char *str, int x1, int y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, const char *tip); uiBut *uiDefIconTextButBitC(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x1, int y1, short x2, short y2, char *poin, float min, float max, float a1, float a2, const char *tip); uiBut *uiDefIconTextButR(uiBlock *block, int type, int retval, int icon, const char *str, int x1, int y1, short x2, short y2, struct PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip); +uiBut *uiDefIconTextButR_prop(uiBlock *block, int type, int retval, int icon, const char *str, int x1, int y1, short x2, short y2, struct PointerRNA *ptr, struct PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip); uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, const char *str, int x1, int y1, short x2, short y2, const char *tip); /* for passing inputs to ButO buttons */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 78e24c3bccb..e31e3a26b40 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2830,6 +2830,16 @@ static void autocomplete_id(bContext *C, char *str, void *arg_v) } } +static void ui_check_but_and_iconize(uiBut *but, int icon) +{ + if(icon) { + but->icon= (BIFIconID) icon; + but->flag|= UI_HAS_ICON; + } + + ui_check_but(but); +} + static uiBut *uiDefButBit(uiBlock *block, int type, int bit, int retval, const char *str, int x1, int y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, const char *tip) { int bitIdx= findBitIndex(bit); @@ -2874,31 +2884,29 @@ uiBut *uiDefButBitC(uiBlock *block, int type, int bit, int retval, const char *s uiBut *uiDefButR(uiBlock *block, int type, int retval, const char *str, int x1, int y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip) { uiBut *but; - but= ui_def_but_rna_propname(block, type, retval, str, x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip); - if(but) - ui_check_but(but); - + ui_check_but(but); + return but; +} +uiBut *uiDefButR_prop(uiBlock *block, int type, int retval, const char *str, int x1, int y1, short x2, short y2, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip) +{ + uiBut *but; + but= ui_def_but_rna(block, type, retval, str, x1, y1, x2, y2, ptr, prop, index, min, max, a1, a2, tip); + ui_check_but(but); return but; } uiBut *uiDefButO(uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x1, int y1, short x2, short y2, const char *tip) { uiBut *but; - but= ui_def_but_operator(block, type, opname, opcontext, str, x1, y1, x2, y2, tip); - if(but) - ui_check_but(but); - + ui_check_but(but); return but; } uiBut *uiDefButTextO(uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x1, int y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, const char *tip) { uiBut *but= ui_def_but_operator_text(block, type, opname, opcontext, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip); - - if(but) - ui_check_but(but); - + ui_check_but(but); return but; } @@ -2906,12 +2914,7 @@ uiBut *uiDefButTextO(uiBlock *block, int type, const char *opname, int opcontext uiBut *uiDefIconBut(uiBlock *block, int type, int retval, int icon, int x1, int y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, const char *tip) { uiBut *but= ui_def_but(block, type, retval, "", x1, y1, x2, y2, poin, min, max, a1, a2, tip); - - but->icon= (BIFIconID) icon; - but->flag|= UI_HAS_ICON; - - ui_check_but(but); - + ui_check_but_and_iconize(but, icon); return but; } static uiBut *uiDefIconButBit(uiBlock *block, int type, int bit, int retval, int icon, int x1, int y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, const char *tip) @@ -2959,29 +2962,22 @@ uiBut *uiDefIconButBitC(uiBlock *block, int type, int bit, int retval, int icon, uiBut *uiDefIconButR(uiBlock *block, int type, int retval, int icon, int x1, int y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip) { uiBut *but; - but= ui_def_but_rna_propname(block, type, retval, "", x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip); - if(but) { - if(icon) { - but->icon= (BIFIconID) icon; - but->flag|= UI_HAS_ICON; - } - ui_check_but(but); - } - + ui_check_but_and_iconize(but, icon); + return but; +} +uiBut *uiDefIconButR_prop(uiBlock *block, int type, int retval, int icon, int x1, int y1, short x2, short y2, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip) +{ + uiBut *but; + but= ui_def_but_rna(block, type, retval, "", x1, y1, x2, y2, ptr, prop, index, min, max, a1, a2, tip); + ui_check_but_and_iconize(but, icon); return but; } uiBut *uiDefIconButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, int x1, int y1, short x2, short y2, const char *tip) { uiBut *but; - but= ui_def_but_operator(block, type, opname, opcontext, "", x1, y1, x2, y2, tip); - if(but) { - but->icon= (BIFIconID) icon; - but->flag|= UI_HAS_ICON; - ui_check_but(but); - } - + ui_check_but_and_iconize(but, icon); return but; } @@ -2989,14 +2985,8 @@ uiBut *uiDefIconButO(uiBlock *block, int type, const char *opname, int opcontext uiBut *uiDefIconTextBut(uiBlock *block, int type, int retval, int icon, const char *str, int x1, int y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, const char *tip) { uiBut *but= ui_def_but(block, type, retval, str, x1, y1, x2, y2, poin, min, max, a1, a2, tip); - - but->icon= (BIFIconID) icon; - but->flag|= UI_HAS_ICON; - + ui_check_but_and_iconize(but, icon); but->flag|= UI_ICON_LEFT; - - ui_check_but(but); - return but; } static uiBut *uiDefIconTextButBit(uiBlock *block, int type, int bit, int retval, int icon, const char *str, int x1, int y1, short x2, short y2, void *poin, float min, float max, float a1, float a2, const char *tip) @@ -3044,31 +3034,25 @@ uiBut *uiDefIconTextButBitC(uiBlock *block, int type, int bit, int retval, int i uiBut *uiDefIconTextButR(uiBlock *block, int type, int retval, int icon, const char *str, int x1, int y1, short x2, short y2, PointerRNA *ptr, const char *propname, int index, float min, float max, float a1, float a2, const char *tip) { uiBut *but; - but= ui_def_but_rna_propname(block, type, retval, str, x1, y1, x2, y2, ptr, propname, index, min, max, a1, a2, tip); - if(but) { - if(icon) { - but->icon= (BIFIconID) icon; - but->flag|= UI_HAS_ICON; - } - but->flag|= UI_ICON_LEFT; - ui_check_but(but); - } - + ui_check_but_and_iconize(but, icon); + but->flag|= UI_ICON_LEFT; + return but; +} +uiBut *uiDefIconTextButR_prop(uiBlock *block, int type, int retval, int icon, const char *str, int x1, int y1, short x2, short y2, PointerRNA *ptr, PropertyRNA *prop, int index, float min, float max, float a1, float a2, const char *tip) +{ + uiBut *but; + but= ui_def_but_rna(block, type, retval, str, x1, y1, x2, y2, ptr, prop, index, min, max, a1, a2, tip); + ui_check_but_and_iconize(but, icon); + but->flag|= UI_ICON_LEFT; return but; } uiBut *uiDefIconTextButO(uiBlock *block, int type, const char *opname, int opcontext, int icon, const char *str, int x1, int y1, short x2, short y2, const char *tip) { uiBut *but; - but= ui_def_but_operator(block, type, opname, opcontext, str, x1, y1, x2, y2, tip); - if(but) { - but->icon= (BIFIconID) icon; - but->flag|= UI_HAS_ICON; - but->flag|= UI_ICON_LEFT; - ui_check_but(but); - } - + ui_check_but_and_iconize(but, icon); + but->flag|= UI_ICON_LEFT; return but; } diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 2f0bcc9d5b4..85cc944f03b 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -419,7 +419,7 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in } } else if(subtype == PROP_DIRECTION) { - uiDefButR(block, BUT_NORMAL, 0, name, x, y, UI_UNIT_X*3, UI_UNIT_Y*3, ptr, RNA_property_identifier(prop), 0, 0, 0, -1, -1, NULL); + uiDefButR_prop(block, BUT_NORMAL, 0, name, x, y, UI_UNIT_X*3, UI_UNIT_Y*3, ptr, prop, 0, 0, 0, -1, -1, NULL); } else { if(ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA) && !expand) @@ -461,11 +461,9 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt { uiBut *but; EnumPropertyItem *item; - const char *identifier; const char *name; int a, totitem, itemw, icon, value, free; - identifier= RNA_property_identifier(prop); RNA_property_enum_items(block->evil_C, ptr, prop, &item, &totitem, &free); uiBlockSetCurLayout(block, ui_item_local_sublayout(layout, layout, 1)); @@ -479,11 +477,11 @@ static void ui_item_enum_expand(uiLayout *layout, uiBlock *block, PointerRNA *pt itemw= ui_text_icon_width(block->curlayout, name, icon, 0); if(icon && name[0] && !icon_only) - but= uiDefIconTextButR(block, ROW, 0, icon, name, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL); + but= uiDefIconTextButR_prop(block, ROW, 0, icon, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL); else if(icon) - but= uiDefIconButR(block, ROW, 0, icon, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL); + but= uiDefIconButR_prop(block, ROW, 0, icon, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL); else - but= uiDefButR(block, ROW, 0, name, 0, 0, itemw, h, ptr, identifier, -1, 0, value, -1, -1, NULL); + but= uiDefButR_prop(block, ROW, 0, name, 0, 0, itemw, h, ptr, prop, -1, 0, value, -1, -1, NULL); if(ui_layout_local_dir(layout) != UI_LAYOUT_HORIZONTAL) but->flag |= UI_TEXT_LEFT; @@ -540,7 +538,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n WM_OP_INVOKE_DEFAULT, ICON_FILESEL, x, y, UI_UNIT_X, h, NULL); } else if(flag & UI_ITEM_R_EVENT) { - uiDefButR(block, KEYEVT, 0, name, x, y, w, h, ptr, RNA_property_identifier(prop), index, 0, 0, -1, -1, NULL); + uiDefButR_prop(block, KEYEVT, 0, name, x, y, w, h, ptr, prop, index, 0, 0, -1, -1, NULL); } else if(flag & UI_ITEM_R_FULL_EVENT) { if(RNA_struct_is_a(ptr->type, &RNA_KeyMapItem)) { @@ -548,7 +546,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n WM_keymap_item_to_string(ptr->data, buf, sizeof(buf)); - but= uiDefButR(block, HOTKEYEVT, 0, buf, x, y, w, h, ptr, RNA_property_identifier(prop), 0, 0, 0, -1, -1, NULL); + but= uiDefButR_prop(block, HOTKEYEVT, 0, buf, x, y, w, h, ptr, prop, 0, 0, 0, -1, -1, NULL); uiButSetFunc(but, ui_keymap_but_cb, but, NULL); if (flag & UI_ITEM_R_IMMEDIATE) uiButSetFlag(but, UI_BUT_IMMEDIATE); @@ -1008,11 +1006,11 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index const char *identifier= RNA_property_identifier(prop); if(icon && name[0] && !icon_only) - uiDefIconTextButR(block, ROW, 0, icon, name, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL); + uiDefIconTextButR_prop(block, ROW, 0, icon, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL); else if(icon) uiDefIconButR(block, ROW, 0, icon, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL); else - uiDefButR(block, ROW, 0, name, 0, 0, w, h, ptr, identifier, -1, 0, value, -1, -1, NULL); + uiDefButR_prop(block, ROW, 0, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL); } /* expanded enum */ else if(type == PROP_ENUM && (expand || RNA_property_flag(prop) & PROP_ENUM_FLAG)) diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 9e7717260e6..f7460e77030 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -1934,31 +1934,31 @@ static void do_picker_new_mode_cb(bContext *UNUSED(C), void *bt1, void *UNUSED(a #define PICKER_TOTAL_W (PICKER_W+PICKER_SPACE+PICKER_BAR) -static void circle_picker(uiBlock *block, PointerRNA *ptr, const char *propname) +static void circle_picker(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop) { uiBut *bt; /* HS circle */ - bt= uiDefButR(block, HSVCIRCLE, 0, "", 0, 0, PICKER_H, PICKER_W, ptr, propname, 0, 0.0, 0.0, 0, 0, "Color"); + bt= uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, PICKER_H, PICKER_W, ptr, prop, 0, 0.0, 0.0, 0, 0, "Color"); uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); /* value */ - bt= uiDefButR(block, HSVCUBE, 0, "", PICKER_W+PICKER_SPACE,0,PICKER_BAR,PICKER_H, ptr, propname, 0, 0.0, 0.0, UI_GRAD_V_ALT, 0, "Value"); + bt= uiDefButR_prop(block, HSVCUBE, 0, "", PICKER_W+PICKER_SPACE,0,PICKER_BAR,PICKER_H, ptr, prop, 0, 0.0, 0.0, UI_GRAD_V_ALT, 0, "Value"); uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); } -static void square_picker(uiBlock *block, PointerRNA *ptr, const char *propname, int type) +static void square_picker(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int type) { uiBut *bt; int bartype = type + 3; /* HS square */ - bt= uiDefButR(block, HSVCUBE, 0, "", 0, PICKER_BAR+PICKER_SPACE, PICKER_TOTAL_W, PICKER_H, ptr, propname, 0, 0.0, 0.0, type, 0, "Color"); + bt= uiDefButR_prop(block, HSVCUBE, 0, "", 0, PICKER_BAR+PICKER_SPACE, PICKER_TOTAL_W, PICKER_H, ptr, prop, 0, 0.0, 0.0, type, 0, "Color"); uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); /* value */ - bt= uiDefButR(block, HSVCUBE, 0, "", 0, 0, PICKER_TOTAL_W, PICKER_BAR, ptr, propname, 0, 0.0, 0.0, bartype, 0, "Value"); + bt= uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, PICKER_TOTAL_W, PICKER_BAR, ptr, prop, 0, 0.0, 0.0, bartype, 0, "Value"); uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); } @@ -1973,7 +1973,6 @@ static void uiBlockPicker(uiBlock *block, float *rgb, PointerRNA *ptr, PropertyR static char hexcol[128]; float rgb_gamma[3]; float min, max, step, precision; - const char *propname = RNA_property_identifier(prop); float *hsv= ui_block_hsv_get(block); ui_block_hsv_get(block); @@ -1999,16 +1998,16 @@ static void uiBlockPicker(uiBlock *block, float *rgb, PointerRNA *ptr, PropertyR switch (U.color_picker_type) { case USER_CP_CIRCLE: - circle_picker(block, ptr, propname); + circle_picker(block, ptr, prop); break; case USER_CP_SQUARE_SV: - square_picker(block, ptr, propname, UI_GRAD_SV); + square_picker(block, ptr, prop, UI_GRAD_SV); break; case USER_CP_SQUARE_HS: - square_picker(block, ptr, propname, UI_GRAD_HS); + square_picker(block, ptr, prop, UI_GRAD_HS); break; case USER_CP_SQUARE_HV: - square_picker(block, ptr, propname, UI_GRAD_HV); + square_picker(block, ptr, prop, UI_GRAD_HV); break; } @@ -2027,11 +2026,11 @@ static void uiBlockPicker(uiBlock *block, float *rgb, PointerRNA *ptr, PropertyR /* RGB values */ uiBlockBeginAlign(block); - bt= uiDefButR(block, NUMSLI, 0, "R ", 0, -60, butwidth, UI_UNIT_Y, ptr, propname, 0, 0.0, 0.0, 0, 3, "Red"); + bt= uiDefButR_prop(block, NUMSLI, 0, "R ", 0, -60, butwidth, UI_UNIT_Y, ptr, prop, 0, 0.0, 0.0, 0, 3, "Red"); uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); - bt= uiDefButR(block, NUMSLI, 0, "G ", 0, -80, butwidth, UI_UNIT_Y, ptr, propname, 1, 0.0, 0.0, 0, 3, "Green"); + bt= uiDefButR_prop(block, NUMSLI, 0, "G ", 0, -80, butwidth, UI_UNIT_Y, ptr, prop, 1, 0.0, 0.0, 0, 3, "Green"); uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); - bt= uiDefButR(block, NUMSLI, 0, "B ", 0, -100, butwidth, UI_UNIT_Y, ptr, propname, 2, 0.0, 0.0, 0, 3, "Blue"); + bt= uiDefButR_prop(block, NUMSLI, 0, "B ", 0, -100, butwidth, UI_UNIT_Y, ptr, prop, 2, 0.0, 0.0, 0, 3, "Blue"); uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); // could use uiItemFullR(col, ptr, prop, -1, 0, UI_ITEM_R_EXPAND|UI_ITEM_R_SLIDER, "", ICON_NONE); @@ -2048,7 +2047,7 @@ static void uiBlockPicker(uiBlock *block, float *rgb, PointerRNA *ptr, PropertyR uiBlockEndAlign(block); if(rgb[3] != FLT_MAX) { - bt= uiDefButR(block, NUMSLI, 0, "A ", 0, -120, butwidth, UI_UNIT_Y, ptr, propname, 3, 0.0, 0.0, 0, 0, "Alpha"); + bt= uiDefButR_prop(block, NUMSLI, 0, "A ", 0, -120, butwidth, UI_UNIT_Y, ptr, prop, 3, 0.0, 0.0, 0, 0, "Alpha"); uiButSetFunc(bt, do_picker_rna_cb, bt, NULL); } else { diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 34315494e14..2d443bbfcd0 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1884,7 +1884,7 @@ void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propnam col = uiLayoutColumn(layout, 0); row= uiLayoutRow(col, 1); - but= uiDefButR(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, propname, -1, 0.0, 0.0, 0, 0, ""); + but= uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, 0, 0, ""); if(lock) { but->flag |= UI_BUT_COLOR_LOCK; @@ -1903,7 +1903,7 @@ void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propnam uiItemS(row); if (value_slider) - uiDefButR(block, HSVCUBE, 0, "", WHEEL_SIZE+6, 0, 14, WHEEL_SIZE, ptr, propname, -1, softmin, softmax, UI_GRAD_V_ALT, 0, ""); + uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE+6, 0, 14, WHEEL_SIZE, ptr, prop, -1, softmin, softmax, UI_GRAD_V_ALT, 0, ""); } /********************* Layer Buttons Template ************************/ @@ -2034,7 +2034,7 @@ static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int return rnaicon; } -static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, int rnaicon, PointerRNA *activeptr, const char *activepropname) +static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop) { uiBlock *block= uiLayoutGetBlock(layout); uiBut *but; @@ -2048,7 +2048,7 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe /* list item behind label & other buttons */ sub= uiLayoutRow(overlap, 0); - but= uiDefButR(block, LISTROW, 0, "", 0,0, UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, ""); + but= uiDefButR_prop(block, LISTROW, 0, "", 0,0, UI_UNIT_X*10,UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, ""); uiButSetFlag(but, UI_BUT_NO_TOOLTIP); sub= uiLayoutRow(overlap, 0); @@ -2201,7 +2201,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * row= uiLayoutRow(col, 0); icon= list_item_icon_get(C, &itemptr, rnaicon, 1); - but= uiDefIconButR(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, ""); + but= uiDefIconButR_prop(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, ""); uiButSetFlag(but, UI_BUT_NO_TOOLTIP); @@ -2241,7 +2241,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * /* next/prev button */ sprintf(str, "%d :", i); - but= uiDefIconTextButR(block, NUM, 0, 0, str, 0,0,UI_UNIT_X*5,UI_UNIT_Y, activeptr, activepropname, 0, 0, 0, 0, 0, ""); + but= uiDefIconTextButR_prop(block, NUM, 0, 0, str, 0,0,UI_UNIT_X*5,UI_UNIT_Y, activeptr, activeprop, 0, 0, 0, 0, 0, ""); if(i == 0) uiButSetFlag(but, UI_BUT_DISABLED); } @@ -2280,7 +2280,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char * /* create list items */ RNA_PROP_BEGIN(ptr, itemptr, prop) { if(i >= pa->list_scroll && ilist_scroll+items) - list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activepropname); + list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activeprop); i++; } diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 1ec125c2f26..f660dbb9edd 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -51,56 +51,53 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int index, const char *name, int icon, int x1, int y1, int x2, int y2) { uiBut *but=NULL; - const char *propname= RNA_property_identifier(prop); - char prop_item[MAX_IDPROP_NAME+4]; /* size of the ID prop name + room for [""] */ - int arraylen= RNA_property_array_length(ptr, prop); - - /* support for custom props */ - if(RNA_property_is_idprop(prop)) { - sprintf(prop_item, "[\"%s\"]", propname); - propname= prop_item; - } switch(RNA_property_type(prop)) { - case PROP_BOOLEAN: { + case PROP_BOOLEAN: + { + int arraylen= RNA_property_array_length(ptr, prop); if(arraylen && index == -1) return NULL; if(icon && name && name[0] == '\0') - but= uiDefIconButR(block, ICONTOG, 0, icon, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + but= uiDefIconButR_prop(block, ICONTOG, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); else if(icon) - but= uiDefIconTextButR(block, ICONTOG, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + but= uiDefIconTextButR_prop(block, ICONTOG, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); else - but= uiDefButR(block, OPTION, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + but= uiDefButR_prop(block, OPTION, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); break; } case PROP_INT: case PROP_FLOAT: + { + int arraylen= RNA_property_array_length(ptr, prop); + if(arraylen && index == -1) { if(ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA)) - but= uiDefButR(block, COL, 0, name, x1, y1, x2, y2, ptr, propname, 0, 0, 0, -1, -1, NULL); + but= uiDefButR_prop(block, COL, 0, name, x1, y1, x2, y2, ptr, prop, 0, 0, 0, -1, -1, NULL); } else if(RNA_property_subtype(prop) == PROP_PERCENTAGE || RNA_property_subtype(prop) == PROP_FACTOR) - but= uiDefButR(block, NUMSLI, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + but= uiDefButR_prop(block, NUMSLI, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); else - but= uiDefButR(block, NUM, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + but= uiDefButR_prop(block, NUM, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); break; + } case PROP_ENUM: if(icon && name && name[0] == '\0') - but= uiDefIconButR(block, MENU, 0, icon, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + but= uiDefIconButR_prop(block, MENU, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); else if(icon) - but= uiDefIconTextButR(block, MENU, 0, icon, NULL, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + but= uiDefIconTextButR_prop(block, MENU, 0, icon, NULL, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); else - but= uiDefButR(block, MENU, 0, NULL, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + but= uiDefButR_prop(block, MENU, 0, NULL, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); break; case PROP_STRING: if(icon && name && name[0] == '\0') - but= uiDefIconButR(block, TEX, 0, icon, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + but= uiDefIconButR_prop(block, TEX, 0, icon, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); else if(icon) - but= uiDefIconTextButR(block, TEX, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + but= uiDefIconTextButR_prop(block, TEX, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); else - but= uiDefButR(block, TEX, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + but= uiDefButR_prop(block, TEX, 0, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); break; case PROP_POINTER: { PointerRNA pptr; @@ -112,7 +109,7 @@ uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int ind if(icon == ICON_DOT) icon= 0; - but= uiDefIconTextButR(block, IDPOIN, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL); + but= uiDefIconTextButR_prop(block, IDPOIN, 0, icon, name, x1, y1, x2, y2, ptr, prop, index, 0, 0, -1, -1, NULL); break; } case PROP_COLLECTION: { -- cgit v1.2.3 From 5dd2b3e06f0164bf4313a172240ad7f4d37bacbe Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 6 Aug 2011 22:31:16 +0000 Subject: fixed crash when NDOF operators were called without an NDOF_MOTION event --- source/blender/editors/space_image/image_ops.c | 49 ++-- source/blender/editors/space_view3d/view3d_edit.c | 318 +++++++++++----------- 2 files changed, 185 insertions(+), 182 deletions(-) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index e0ebde589a8..ea8c7fc0cfa 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -447,34 +447,41 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot) static int view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) { - SpaceImage *sima= CTX_wm_space_image(C); - ARegion *ar= CTX_wm_region(C); + if (event->type != NDOF_MOTION) + return OPERATOR_CANCELLED; + else { + SpaceImage *sima= CTX_wm_space_image(C); + ARegion *ar= CTX_wm_region(C); - wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; - float dt = ndof->dt; - /* tune these until it feels right */ - const float zoom_sensitivity = 0.5f; // 50% per second (I think) - const float pan_sensitivity = 300.f; // screen pixels per second + float dt = ndof->dt; + /* tune these until it feels right */ + const float zoom_sensitivity = 0.5f; // 50% per second (I think) + const float pan_sensitivity = 300.f; // screen pixels per second - float pan_x = pan_sensitivity * dt * ndof->tvec[0] / sima->zoom; - float pan_y = pan_sensitivity * dt * ndof->tvec[1] / sima->zoom; + float pan_x = pan_sensitivity * dt * ndof->tvec[0] / sima->zoom; + float pan_y = pan_sensitivity * dt * ndof->tvec[1] / sima->zoom; - /* "mouse zoom" factor = 1 + (dx + dy) / 300 - * what about "ndof zoom" factor? should behave like this: - * at rest -> factor = 1 - * move forward -> factor > 1 - * move backward -> factor < 1 - */ - float zoom_factor = 1.f + zoom_sensitivity * dt * -ndof->tvec[2]; + /* "mouse zoom" factor = 1 + (dx + dy) / 300 + * what about "ndof zoom" factor? should behave like this: + * at rest -> factor = 1 + * move forward -> factor > 1 + * move backward -> factor < 1 + */ + float zoom_factor = 1.f + zoom_sensitivity * dt * -ndof->tvec[2]; - sima_zoom_set_factor(sima, ar, zoom_factor); - sima->xof += pan_x; - sima->yof += pan_y; + if (U.ndof_flag & NDOF_ZOOM_INVERT) + zoom_factor = -zoom_factor; - ED_region_tag_redraw(ar); + sima_zoom_set_factor(sima, ar, zoom_factor); + sima->xof += pan_x; + sima->yof += pan_y; - return OPERATOR_FINISHED; + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; + } } void IMAGE_OT_view_ndof(wmOperatorType *ot) diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index e6fd9e8867b..3e6bbc13334 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -949,134 +949,125 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event // -- zooming // -- panning in rotationally-locked views { - RegionView3D* rv3d = CTX_wm_region_view3d(C); - wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + if (event->type != NDOF_MOTION) + return OPERATOR_CANCELLED; + else { + RegionView3D* rv3d = CTX_wm_region_view3d(C); + wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; - rv3d->rot_angle = 0.f; // off by default, until changed later this function + rv3d->rot_angle = 0.f; // off by default, until changed later this function - if (ndof->progress != P_FINISHING) { - const float dt = ndof->dt; - - // tune these until everything feels right - const float rot_sensitivity = 1.f; - const float zoom_sensitivity = 1.f; - const float pan_sensitivity = 1.f; - - // rather have bool, but... - int has_rotation = rv3d->viewlock != RV3D_LOCKED && !is_zero_v3(ndof->rvec); - - float view_inv[4]; - invert_qt_qt(view_inv, rv3d->viewquat); - - //#define DEBUG_NDOF_MOTION - #ifdef DEBUG_NDOF_MOTION - printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n", - ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt); - #endif - - if (ndof->tvec[2]) { - // Zoom! - // velocity should be proportional to the linear velocity attained by rotational motion of same strength - // [got that?] - // proportional to arclength = radius * angle - - float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tvec[2]; - rv3d->dist += zoom_distance; - } - - if (rv3d->viewlock == RV3D_LOCKED) { - /* rotation not allowed -- explore panning options instead */ - float pan_vec[3] = {ndof->tvec[0], ndof->tvec[1], 0.0f}; - mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt); - - /* transform motion from view to world coordinates */ + if (ndof->progress != P_FINISHING) { + const float dt = ndof->dt; + + // tune these until everything feels right + const float rot_sensitivity = 1.f; + const float zoom_sensitivity = 1.f; + const float pan_sensitivity = 1.f; + + // rather have bool, but... + int has_rotation = rv3d->viewlock != RV3D_LOCKED && !is_zero_v3(ndof->rvec); + + float view_inv[4]; invert_qt_qt(view_inv, rv3d->viewquat); - mul_qt_v3(view_inv, pan_vec); - - /* move center of view opposite of hand motion (this is camera mode, not object mode) */ - sub_v3_v3(rv3d->ofs, pan_vec); - } - - if (has_rotation) { - - const int invert = U.ndof_flag & NDOF_ORBIT_INVERT_AXES; - - rv3d->view = RV3D_VIEW_USER; - - if (U.flag & USER_TRACKBALL) { - float rot[4]; - #if 0 // -------------------------- Mike's nifty original version - float view_inv_conj[4]; - - ndof_to_quat(ndof, rot); - // mul_qt_fl(rot, rot_sensitivity); - // ^^ no apparent effect - - if (invert) - invert_qt(rot); - - copy_qt_qt(view_inv_conj, view_inv); - conjugate_qt(view_inv_conj); - - // transform rotation from view to world coordinates - mul_qt_qtqt(rot, view_inv, rot); - mul_qt_qtqt(rot, rot, view_inv_conj); - #else // ---------------------------------------- Mike's revised version - float axis[3]; - float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis); - - if (invert) - angle = -angle; - - // transform rotation axis from view to world coordinates - mul_qt_v3(view_inv, axis); - - // update the onscreen doo-dad - rv3d->rot_angle = angle; - copy_v3_v3(rv3d->rot_axis, axis); - - axis_angle_to_quat(rot, axis, angle); - #endif // -------------------------------------------- - // apply rotation - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); - } else { - /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */ - float angle, rot[4]; - float xvec[3] = {1,0,0}; - - /* Determine the direction of the x vector (for rotating up and down) */ - mul_qt_v3(view_inv, xvec); - - /* Perform the up/down rotation */ - angle = rot_sensitivity * dt * ndof->rvec[0]; - if (invert) - angle = -angle; - rot[0] = cos(angle); - mul_v3_v3fl(rot+1, xvec, sin(angle)); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); - - /* Perform the orbital rotation */ - angle = rot_sensitivity * dt * ndof->rvec[1]; - if (invert) - angle = -angle; - - // update the onscreen doo-dad - rv3d->rot_angle = angle; - rv3d->rot_axis[0] = 0; - rv3d->rot_axis[1] = 0; - rv3d->rot_axis[2] = 1; - - rot[0] = cos(angle); - rot[1] = rot[2] = 0.0; - rot[3] = sin(angle); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); + + //#define DEBUG_NDOF_MOTION + #ifdef DEBUG_NDOF_MOTION + printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n", + ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt); + #endif + + if (ndof->tvec[2]) { + // Zoom! + // velocity should be proportional to the linear velocity attained by rotational motion of same strength + // [got that?] + // proportional to arclength = radius * angle + + float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tvec[2]; + + if (U.ndof_flag & NDOF_ZOOM_INVERT) + zoom_distance = -zoom_distance; + + rv3d->dist += zoom_distance; + } + + if (rv3d->viewlock == RV3D_LOCKED) { + /* rotation not allowed -- explore panning options instead */ + float pan_vec[3] = {ndof->tvec[0], ndof->tvec[1], 0.0f}; + mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt); + + /* transform motion from view to world coordinates */ + invert_qt_qt(view_inv, rv3d->viewquat); + mul_qt_v3(view_inv, pan_vec); + + /* move center of view opposite of hand motion (this is camera mode, not object mode) */ + sub_v3_v3(rv3d->ofs, pan_vec); + } + + if (has_rotation) { + + const int invert = U.ndof_flag & NDOF_ORBIT_INVERT_AXES; + + rv3d->view = RV3D_VIEW_USER; + + if (U.flag & USER_TRACKBALL) { + float rot[4]; + float axis[3]; + float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis); + + if (invert) + angle = -angle; + + // transform rotation axis from view to world coordinates + mul_qt_v3(view_inv, axis); + + // update the onscreen doo-dad + rv3d->rot_angle = angle; + copy_v3_v3(rv3d->rot_axis, axis); + + axis_angle_to_quat(rot, axis, angle); + + // apply rotation + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); + } else { + /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */ + float angle, rot[4]; + float xvec[3] = {1,0,0}; + + /* Determine the direction of the x vector (for rotating up and down) */ + mul_qt_v3(view_inv, xvec); + + /* Perform the up/down rotation */ + angle = rot_sensitivity * dt * ndof->rvec[0]; + if (invert) + angle = -angle; + rot[0] = cos(angle); + mul_v3_v3fl(rot+1, xvec, sin(angle)); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); + + /* Perform the orbital rotation */ + angle = rot_sensitivity * dt * ndof->rvec[1]; + if (invert) + angle = -angle; + + // update the onscreen doo-dad + rv3d->rot_angle = angle; + rv3d->rot_axis[0] = 0; + rv3d->rot_axis[1] = 0; + rv3d->rot_axis[2] = 1; + + rot[0] = cos(angle); + rot[1] = rot[2] = 0.0; + rot[3] = sin(angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); + } } } - } - ED_region_tag_redraw(CTX_wm_region(C)); + ED_region_tag_redraw(CTX_wm_region(C)); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; + } } void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot) @@ -1098,57 +1089,62 @@ static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) // -- "pan" navigation // -- zoom or dolly? { - RegionView3D* rv3d = CTX_wm_region_view3d(C); - wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + if (event->type != NDOF_MOTION) + return OPERATOR_CANCELLED; + else { + RegionView3D* rv3d = CTX_wm_region_view3d(C); + wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + - rv3d->rot_angle = 0.f; // we're panning here! so erase any leftover rotation from other operators + rv3d->rot_angle = 0.f; // we're panning here! so erase any leftover rotation from other operators - if (ndof->progress != P_FINISHING) { - const float dt = ndof->dt; - float view_inv[4]; + if (ndof->progress != P_FINISHING) { + const float dt = ndof->dt; + float view_inv[4]; #if 0 // ------------------------------------------- zoom with Z - // tune these until everything feels right - const float zoom_sensitivity = 1.f; - const float pan_sensitivity = 1.f; - - float pan_vec[3] = { - ndof->tx, ndof->ty, 0 - }; - - // "zoom in" or "translate"? depends on zoom mode in user settings? - if (ndof->tz) { - float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz; - rv3d->dist += zoom_distance; - } - - mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt); + // tune these until everything feels right + const float zoom_sensitivity = 1.f; + const float pan_sensitivity = 1.f; + + float pan_vec[3] = { + ndof->tx, ndof->ty, 0 + }; + + // "zoom in" or "translate"? depends on zoom mode in user settings? + if (ndof->tz) { + float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz; + rv3d->dist += zoom_distance; + } + + mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt); #else // ------------------------------------------------------- dolly with Z - float speed = 10.f; // blender units per second - // ^^ this is ok for default cube scene, but should scale with.. something + float speed = 10.f; // blender units per second + // ^^ this is ok for default cube scene, but should scale with.. something - // tune these until everything feels right - const float forward_sensitivity = 1.f; - const float vertical_sensitivity = 0.4f; - const float lateral_sensitivity = 0.6f; + // tune these until everything feels right + const float forward_sensitivity = 1.f; + const float vertical_sensitivity = 0.4f; + const float lateral_sensitivity = 0.6f; - float pan_vec[3] = {lateral_sensitivity * ndof->tvec[0], - vertical_sensitivity * ndof->tvec[1], - forward_sensitivity * ndof->tvec[2] - }; + float pan_vec[3] = {lateral_sensitivity * ndof->tvec[0], + vertical_sensitivity * ndof->tvec[1], + forward_sensitivity * ndof->tvec[2] + }; - mul_v3_fl(pan_vec, speed * dt); + mul_v3_fl(pan_vec, speed * dt); #endif - /* transform motion from view to world coordinates */ - invert_qt_qt(view_inv, rv3d->viewquat); - mul_qt_v3(view_inv, pan_vec); + /* transform motion from view to world coordinates */ + invert_qt_qt(view_inv, rv3d->viewquat); + mul_qt_v3(view_inv, pan_vec); - /* move center of view opposite of hand motion (this is camera mode, not object mode) */ - sub_v3_v3(rv3d->ofs, pan_vec); - } + /* move center of view opposite of hand motion (this is camera mode, not object mode) */ + sub_v3_v3(rv3d->ofs, pan_vec); + } - ED_region_tag_redraw(CTX_wm_region(C)); + ED_region_tag_redraw(CTX_wm_region(C)); - return OPERATOR_FINISHED; + return OPERATOR_FINISHED; + } } void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot) -- cgit v1.2.3 From 6c821f4078414c81128ebf0d35187054df238371 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sat, 6 Aug 2011 23:13:36 +0000 Subject: stricter NDOF guards for Windows (forgot in earlier commit) --- build_files/scons/config/darwin-config.py | 1 + intern/ghost/intern/GHOST_SystemWin32.h | 2 ++ source/blender/makesdna/DNA_userdef_types.h | 2 +- source/blender/makesrna/intern/rna_userdef.c | 13 +++++++++++++ source/blender/windowmanager/intern/wm_event_system.c | 12 +++++++----- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py index 560b6d9cb60..97e8e90e574 100644 --- a/build_files/scons/config/darwin-config.py +++ b/build_files/scons/config/darwin-config.py @@ -21,6 +21,7 @@ cmd = 'uname -p' MAC_PROC=commands.getoutput(cmd) cmd = 'uname -r' cmd_res=commands.getoutput(cmd) +MAC_CUR_VER='10.5' # by default (test below fails on my 10.5 PowerPC) if cmd_res[:2]=='7': MAC_CUR_VER='10.3' elif cmd_res[:2]=='8': diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h index c5dff27dace..858312b3eb1 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.h +++ b/intern/ghost/intern/GHOST_SystemWin32.h @@ -302,6 +302,7 @@ protected: */ static void processMinMaxInfo(MINMAXINFO * minmax); +#ifdef WITH_INPUT_NDOF /** * Handles Motion and Button events from a SpaceNavigator or related device. * Instead of returning an event object, this function communicates directly @@ -310,6 +311,7 @@ protected: * @return Whether an event was generated and sent. */ bool processNDOF(RAWINPUT const& raw); +#endif /** * Returns the local state of the modifier keys (from the message queue). diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index a555a196060..556f554eb98 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -603,7 +603,7 @@ extern UserDef U; /* from blenkernel blender.c */ #define NDOF_ORBIT_INVERT_AXES (1 << 6) /* zoom is up/down if this flag is set (otherwise forward/backward) */ #define NDOF_ZOOM_UPDOWN (1 << 7) -#define NDOF_INVERT_ZOOM (1 << 8) +#define NDOF_ZOOM_INVERT (1 << 8) #ifdef __cplusplus diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index b3dbafeab7d..57044188dd9 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2746,19 +2746,32 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Drag Threshold", "Amount of pixels you have to drag before dragging UI items happens"); /* 3D mouse settings */ + /* global options */ prop= RNA_def_property(srna, "ndof_sensitivity", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0.25f, 4.0f); RNA_def_property_ui_text(prop, "Sensitivity", "Overall sensitivity of the 3D Mouse"); + prop= RNA_def_property(srna, "ndof_zoom_updown", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_ZOOM_UPDOWN); + RNA_def_property_ui_text(prop, "Zoom = Up/Down", "Zoom using up/down on the device (otherwise forward/backward)"); + + prop= RNA_def_property(srna, "ndof_zoom_invert", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_ZOOM_INVERT); + RNA_def_property_ui_text(prop, "Invert Zoom", "Zoom using opposite direction"); + + /* 3D view */ prop= RNA_def_property(srna, "ndof_show_guide", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_SHOW_GUIDE); RNA_def_property_ui_text(prop, "Show Navigation Guide", "Display the center and axis during rotation"); /* TODO: update description when fly-mode visuals are in place ("projected position in fly mode")*/ + /* 3D view: orbit */ prop= RNA_def_property(srna, "ndof_orbit_invert_axes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_ORBIT_INVERT_AXES); RNA_def_property_ui_text(prop, "Invert Axes", "Toggle between moving the viewpoint or moving the scene being viewed"); + /* in 3Dx docs, this is called 'object mode' vs. 'target camera mode' + /* 3D view: fly */ prop= RNA_def_property(srna, "ndof_lock_horizon", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_LOCK_HORIZON); RNA_def_property_ui_text(prop, "Lock Horizon", "Keep horizon level while flying with 3D Mouse"); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 0dac0bd7401..258d6bbc025 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2330,26 +2330,28 @@ static void attach_ndof_data(wmEvent* event, const GHOST_TEventNDOFMotionData* g const float s = U.ndof_sensitivity; data->tvec[0]= s * ghost->tx; + data->rvec[0]= s * ghost->rx; + data->rvec[1]= s * ghost->ry; + data->rvec[2]= s * ghost->rz; if (U.ndof_flag & NDOF_ZOOM_UPDOWN) { - // swap Y and Z + // rotate so Y is where Z was (maintain handed-ness) data->tvec[1]= s * ghost->tz; - data->tvec[2]= s * ghost->ty; + data->tvec[2]= s * -ghost->ty; // should this affect rotation also? // initial guess is 'yes', but get user feedback immediately! +#if 0 // after turning this on, my guess becomes 'no' data->rvec[1]= s * ghost->rz; data->rvec[2]= s * ghost->ry; +#endif } else { data->tvec[1]= s * ghost->ty; data->tvec[2]= s * ghost->tz; - - data->rvec[1]= s * ghost->ry; - data->rvec[2]= s * ghost->rz; } data->dt = ghost->dt; -- cgit v1.2.3 From 117ec4a91ac996480611788998645bd6de40d706 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 7 Aug 2011 04:22:33 +0000 Subject: comment unused vars --- source/blender/editors/interface/interface_handlers.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index d8d8354b0b9..6f3ca2bf003 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -2856,7 +2856,7 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, wmEvent *event) { - int mx, my, click= 0; + int mx, my /*, click= 0 */; int retval= WM_UI_HANDLER_CONTINUE; int horizontal= (but->x2 - but->x1 > but->y2 - but->y1); @@ -2878,8 +2878,10 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); retval= WM_UI_HANDLER_BREAK; } - else if(ELEM(event->type, PADENTER, RETKEY) && event->val==KM_PRESS) + /* UNUSED - otherwise code is ok, add back if needed */ + /* else if(ELEM(event->type, PADENTER, RETKEY) && event->val==KM_PRESS) click= 1; + */ } } else if(data->state == BUTTON_STATE_NUM_EDITING) { @@ -3677,6 +3679,9 @@ static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButt return WM_UI_HANDLER_BREAK; } + /* UNUSED but keep for now */ + (void)changed; + return WM_UI_HANDLER_CONTINUE; } @@ -3691,12 +3696,12 @@ static int ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int mx Histogram *hist = (Histogram *)but->poin; /* rcti rect; */ int changed= 1; - float dx, dy, yfac=1.f; + float /* dx, */ dy, yfac=1.f; /* UNUSED */ /* rect.xmin= but->x1; rect.xmax= but->x2; */ /* rect.ymin= but->y1; rect.ymax= but->y2; */ - dx = mx - data->draglastx; + /* dx = mx - data->draglastx; */ /* UNUSED */ dy = my - data->draglasty; @@ -3774,12 +3779,12 @@ static int ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx, Scopes *scopes = (Scopes *)but->poin; /* rcti rect; */ int changed= 1; - float dx, dy, yfac=1.f; + float /* dx, */ dy /* , yfac=1.f */; /* UNUSED */ /* rect.xmin= but->x1; rect.xmax= but->x2; */ /* rect.ymin= but->y1; rect.ymax= but->y2; */ - dx = mx - data->draglastx; + /* dx = mx - data->draglastx; */ /* UNUSED */ dy = my - data->draglasty; @@ -3788,7 +3793,7 @@ static int ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx, scopes->wavefrm_height = (but->y2 - but->y1) + (data->dragstarty - my); } else { /* scale waveform values */ - yfac = scopes->wavefrm_yfac; + /* yfac = scopes->wavefrm_yfac; */ /* UNUSED */ scopes->wavefrm_yfac += dy/200.0f; CLAMP(scopes->wavefrm_yfac, 0.5f, 2.f); -- cgit v1.2.3 From 38280ba38ed48d45e782e989a32b33510432d172 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 7 Aug 2011 04:55:58 +0000 Subject: fix [#28172] Cannot restore Add-ons tab in user preferences after a failed attempt to install an add-on. non utf8 addons would make the addon UI vanish, now give a message in the console and UI. --- release/scripts/modules/addon_utils.py | 25 +++++++++++++++++++++++-- release/scripts/startup/bl_ui/space_userpref.py | 6 ++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py index 22936f4c209..0c5ef69e805 100644 --- a/release/scripts/modules/addon_utils.py +++ b/release/scripts/modules/addon_utils.py @@ -32,6 +32,7 @@ import bpy as _bpy error_duplicates = False +error_encoding = False def paths(): @@ -51,14 +52,18 @@ def paths(): def modules(module_cache): global error_duplicates + global error_encoding import os error_duplicates = False + error_encoding = False path_list = paths() # fake module importing def fake_module(mod_name, mod_path, speedy=True): + global error_encoding + if _bpy.app.debug: print("fake_module", mod_path, mod_name) import ast @@ -69,12 +74,28 @@ def modules(module_cache): line_iter = iter(file_mod) l = "" while not l.startswith("bl_info"): - l = line_iter.readline() + try: + l = line_iter.readline() + except UnicodeDecodeError as e: + if not error_encoding: + error_encoding = True + print("Error reading file as UTF-8:", mod_path, e) + file_mod.close() + return None + if len(l) == 0: break while l.rstrip(): lines.append(l) - l = line_iter.readline() + try: + l = line_iter.readline() + except UnicodeDecodeError as e: + if not error_encoding: + error_encoding = True + print("Error reading file as UTF-8:", mod_path, e) + file_mod.close() + return None + data = "".join(lines) else: diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index e27bd8ef07a..e6fd8dcb949 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -949,6 +949,12 @@ class USERPREF_PT_addons(bpy.types.Panel): "(see console for details)", ) + if addon_utils.error_encoding: + self.draw_error(col, + "One or more addons do not have UTF-8 encoding\n" + "(see console for details)", + ) + filter = context.window_manager.addon_filter search = context.window_manager.addon_search.lower() support = context.window_manager.addon_support -- cgit v1.2.3 From a02d7c1ba76adbf3ff432111af4c3c81a0812c3a Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 7 Aug 2011 11:01:55 +0000 Subject: Fix #28169: keymap bug when using a preset configuration, e.g. object mode keymap was also being used in edit mode. --- source/blender/windowmanager/intern/wm_keymap.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index bf48f0e21e4..2fb0a1b2ab9 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -532,7 +532,7 @@ static void wm_keymap_patch(wmKeyMap *km, wmKeyMap *diff_km) } } -static void wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *usermap) +static wmKeyMap *wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *usermap) { wmKeyMap *km; int expanded = 0; @@ -552,8 +552,6 @@ static void wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap wmKeyMapItem *kmi, *orig_kmi; km = wm_keymap_copy(usermap); - km->modal_items = defaultmap->modal_items; - km->poll = defaultmap->poll; /* try to find corresponding id's for items */ for(kmi=km->items.first; kmi; kmi=kmi->next) { @@ -587,6 +585,8 @@ static void wm_keymap_patch_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap /* add to list */ BLI_addtail(lb, km); + + return km; } static void wm_keymap_diff_update(ListBase *lb, wmKeyMap *defaultmap, wmKeyMap *addonmap, wmKeyMap *km) @@ -977,7 +977,7 @@ static wmKeyMap *wm_keymap_preset(wmWindowManager *wm, wmKeyMap *km) void WM_keyconfig_update(wmWindowManager *wm) { - wmKeyMap *km, *defaultmap, *addonmap, *usermap; + wmKeyMap *km, *defaultmap, *addonmap, *usermap, *kmn; wmKeyMapItem *kmi; wmKeyMapDiffItem *kmdi; int compat_update = 0; @@ -1021,7 +1021,12 @@ void WM_keyconfig_update(wmWindowManager *wm) usermap= WM_keymap_list_find(&U.user_keymaps, km->idname, km->spaceid, km->regionid); /* add */ - wm_keymap_patch_update(&wm->userconf->keymaps, defaultmap, addonmap, usermap); + kmn= wm_keymap_patch_update(&wm->userconf->keymaps, defaultmap, addonmap, usermap); + + if(kmn) { + kmn->modal_items= km->modal_items; + kmn->poll= km->poll; + } /* in case of old non-diff keymaps, force extra update to create diffs */ compat_update = compat_update || (usermap && !(usermap->flag & KEYMAP_DIFF)); -- cgit v1.2.3 From 0dea4df76442ffce1e0e7162fab103f6cca99b12 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 7 Aug 2011 14:57:25 +0000 Subject: Changed do_version condition for noodle_curving. It should be re-set to 5 for files saved in 2.58.1 release. --- source/blender/editors/interface/resources.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index f3db6ad11ae..e71f709f89b 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1557,7 +1557,7 @@ void init_userdef_do_versions(void) U.autokey_flag &= ~AUTOKEY_FLAG_ONLYKEYINGSET; } - if (bmain->versionfile < 258 || (bmain->versionfile == 258 && bmain->subversionfile < 1)) { + if (bmain->versionfile < 258 || (bmain->versionfile == 258 && bmain->subversionfile < 2)) { bTheme *btheme; for(btheme= U.themes.first; btheme; btheme= btheme->next) { btheme->tnode.noodle_curving = 5; -- cgit v1.2.3 From bf23acf3bb8ae43e6a50108a00e7572fe35edea4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 7 Aug 2011 15:06:35 +0000 Subject: fix for building ndof with cmake on osx --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index a0a0359d8d7..cf083b87bc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1010,6 +1010,10 @@ elseif(APPLE) if(NOT 3D_CONNEXION_CLIENT_LIBRARY) set(WITH_INPUT_NDOF OFF) endif() + + if(WITH_INPUT_NDOF) + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework 3DconnexionClient") + endif() endif() else() -- cgit v1.2.3 From 6a0bbfd0e47e81fcb66cc91291adbcf1e6e87284 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 7 Aug 2011 16:29:05 +0000 Subject: fixed ndof library detect for Mac SCons, ndof enabled by default (disabled if lib not found), minor cleanup --- SConstruct | 9 ++++----- build_files/scons/config/darwin-config.py | 14 +++++++------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/SConstruct b/SConstruct index 4f920190276..b422892680d 100644 --- a/SConstruct +++ b/SConstruct @@ -255,13 +255,12 @@ if 'blenderlite' in B.targets: # detect presence of 3D_CONNEXION_CLIENT_LIBRARY for OSX if env['OURPLATFORM']=='darwin': - envi = Environment() - conf = Configure(envi) - if not conf.CheckCHeader('ConnexionClientAPI.h'): # CheckCXXHeader if it is c++ ! + # for now, Mac builders must download and install the driver framework from 3Dconnexion + # necessary header file lives here when installed: + # /Library/Frameworks/3DconnexionClient.framework/Versions/Current/Headers/ConnexionClientAPI.h + if not os.path.exists('/Library/Frameworks/3DconnexionClient.framework'): print "3D_CONNEXION_CLIENT_LIBRARY not found, disabling WITH_BF_3DMOUSE" # avoid build errors ! env['WITH_BF_3DMOUSE'] = 0 - envi = conf.Finish() - if env['WITH_BF_OPENMP'] == 1: if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py index 97e8e90e574..a8bad81324c 100644 --- a/build_files/scons/config/darwin-config.py +++ b/build_files/scons/config/darwin-config.py @@ -199,7 +199,7 @@ BF_GETTEXT_INC = '${BF_GETTEXT}/include' BF_GETTEXT_LIB = 'intl' BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' -WITH_BF_GAMEENGINE=True +WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = False WITH_BF_BULLET = True @@ -277,7 +277,7 @@ elif MACOSX_ARCHITECTURE == 'x86_64': BF_RAYOPTIMIZATION_SSE_FLAGS = ['-msse','-msse2'] # SpaceNavigator and related 3D mice -WITH_BF_3DMOUSE = False +WITH_BF_3DMOUSE = True ############################################################################# ################### various compile settings and flags ################## @@ -296,13 +296,13 @@ CPPFLAGS = []+ARCH_FLAGS CCFLAGS = ['-pipe','-funsigned-char']+ARCH_FLAGS CXXFLAGS = ['-pipe','-funsigned-char']+ARCH_FLAGS -if WITH_GHOST_COCOA==True: +if WITH_GHOST_COCOA: PLATFORM_LINKFLAGS = ['-fexceptions','-framework','CoreServices','-framework','Foundation','-framework','IOKit','-framework','AppKit','-framework','Cocoa','-framework','Carbon','-framework','AudioUnit','-framework','AudioToolbox','-framework','CoreAudio','-framework','OpenAL']+ARCH_FLAGS else: PLATFORM_LINKFLAGS = ['-fexceptions','-framework','CoreServices','-framework','Foundation','-framework','IOKit','-framework','AppKit','-framework','Carbon','-framework','AGL','-framework','AudioUnit','-framework','AudioToolbox','-framework','CoreAudio','-framework','OpenAL']+ARCH_FLAGS -if WITH_BF_QUICKTIME == True: - if USE_QTKIT == True: +if WITH_BF_QUICKTIME: + if USE_QTKIT: PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QTKit'] else: PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QuickTime'] @@ -313,14 +313,14 @@ if WITH_BF_3DMOUSE: #note to build succesfully on 10.3.9 SDK you need to patch 10.3.9 by adding the SystemStubs.a lib from 10.4 LLIBS = ['stdc++', 'SystemStubs'] -# some flags shuffling for different Os versions +# some flags shuffling for different OS versions if MAC_MIN_VERS == '10.3': CFLAGS = ['-fuse-cxa-atexit']+CFLAGS CXXFLAGS = ['-fuse-cxa-atexit']+CXXFLAGS PLATFORM_LINKFLAGS = ['-fuse-cxa-atexit']+PLATFORM_LINKFLAGS LLIBS.append('crt3.o') -if USE_SDK==True: +if USE_SDK: SDK_FLAGS=['-isysroot', MACOSX_SDK,'-mmacosx-version-min='+MAC_MIN_VERS,'-arch',MACOSX_ARCHITECTURE] PLATFORM_LINKFLAGS = ['-mmacosx-version-min='+MAC_MIN_VERS,'-Wl','-isysroot',MACOSX_SDK,'-arch',MACOSX_ARCHITECTURE]+PLATFORM_LINKFLAGS CCFLAGS=SDK_FLAGS+CCFLAGS -- cgit v1.2.3 From 479c203dad2868da012bff884dade573d6254993 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 7 Aug 2011 16:44:10 +0000 Subject: stricter WITH_INPUT_NDOF guards, general cleanup --- intern/ghost/intern/GHOST_NDOFManager.cpp | 20 ++++++++++---------- intern/ghost/intern/GHOST_NDOFManagerCocoa.h | 7 +++++-- intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 6 +++++- intern/ghost/intern/GHOST_NDOFManagerX11.cpp | 25 ++++++++++++------------- intern/ghost/intern/GHOST_NDOFManagerX11.h | 7 ++++--- intern/ghost/intern/GHOST_SystemCocoa.mm | 9 +++++---- intern/ghost/intern/GHOST_SystemX11.cpp | 20 +++----------------- 7 files changed, 44 insertions(+), 50 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 855e27b9964..a24ccc3ff6c 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -375,7 +375,7 @@ void GHOST_NDOFManager::setDeadZone(float dz) static bool atHomePosition(GHOST_TEventNDOFMotionData* ndof) { -#define HOME(foo) (ndof->foo == 0) +#define HOME(foo) (ndof->foo == 0.f) return HOME(tx) && HOME(ty) && HOME(tz) && HOME(rx) && HOME(ry) && HOME(rz); #undef HOME } @@ -386,9 +386,9 @@ static bool nearHomePosition(GHOST_TEventNDOFMotionData* ndof, float threshold) return atHomePosition(ndof); } else { -#define HOME1(foo) (fabsf(ndof->foo) < threshold) - return HOME1(tx) && HOME1(ty) && HOME1(tz) && HOME1(rx) && HOME1(ry) && HOME1(rz); -#undef HOME1 +#define HOME(foo) (fabsf(ndof->foo) < threshold) + return HOME(tx) && HOME(ty) && HOME(tz) && HOME(rx) && HOME(ry) && HOME(rz); +#undef HOME } } @@ -423,17 +423,17 @@ bool GHOST_NDOFManager::sendMotionEvent() data->dt = 0.001f * (m_motionTime - m_prevMotionTime); // in seconds - bool handMotion = !nearHomePosition(data, m_deadZone); + bool weHaveMotion = !nearHomePosition(data, m_deadZone); // determine what kind of motion event to send (Starting, InProgress, Finishing) // and where that leaves this NDOF manager (NotStarted, InProgress, Finished) switch (m_motionState) { case GHOST_kNotStarted: case GHOST_kFinished: - if (handMotion) { + if (weHaveMotion) { data->progress = GHOST_kStarting; m_motionState = GHOST_kInProgress; - // prev motion time will be ancient, so just make up something reasonable + // prev motion time will be ancient, so just make up a reasonable time delta data->dt = 0.0125f; } else { @@ -443,9 +443,9 @@ bool GHOST_NDOFManager::sendMotionEvent() } break; case GHOST_kInProgress: - if (handMotion) { + if (weHaveMotion) { data->progress = GHOST_kInProgress; - // keep InProgress state + // remain 'InProgress' } else { data->progress = GHOST_kFinishing; @@ -453,7 +453,7 @@ bool GHOST_NDOFManager::sendMotionEvent() } break; default: - break; + ; // will always be one of the above } #ifdef DEBUG_NDOF_MOTION diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h index 27397b711b7..e9897f30104 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.h +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.h @@ -22,10 +22,12 @@ * * ***** END GPL LICENSE BLOCK ***** */ - + #ifndef _GHOST_NDOFMANAGERCOCOA_H_ #define _GHOST_NDOFMANAGERCOCOA_H_ +#ifdef WITH_INPUT_NDOF + #include "GHOST_NDOFManager.h" // Event capture is handled within the NDOF manager on Macintosh, @@ -47,4 +49,5 @@ private: }; -#endif +#endif // WITH_INPUT_NDOF +#endif // #include guard diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index 53a991a7396..1d90b6daa68 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -22,7 +22,9 @@ * * ***** END GPL LICENSE BLOCK ***** */ - + +#ifdef WITH_INPUT_NDOF + #include "GHOST_NDOFManagerCocoa.h" #include "GHOST_SystemCocoa.h" @@ -170,3 +172,5 @@ bool GHOST_NDOFManagerCocoa::available() return InstallConnexionHandlers != NULL; // this means that the driver is installed and dynamically linked to blender } + +#endif // WITH_INPUT_NDOF diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp index 099fa15d179..4dd53319039 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.cpp +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.cpp @@ -22,7 +22,9 @@ * * ***** END GPL LICENSE BLOCK ***** */ - + +#ifdef WITH_INPUT_NDOF + #include "GHOST_NDOFManagerX11.h" #include "GHOST_SystemX11.h" #include @@ -34,14 +36,14 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys) GHOST_NDOFManager(sys), m_available(false) { - setDeadZone(0.1f); // how to calibrate on Linux? throw away slight motion! + setDeadZone(0.1f); /* how to calibrate on Linux? throw away slight motion! */ if (spnav_open() != -1) { - // determine exactly which device (if any) is plugged in + /* determine exactly which device (if any) is plugged in */ #define MAX_LINE_LENGTH 100 - // look for USB devices with Logitech's vendor ID + /* look for USB devices with Logitech's vendor ID */ FILE* command_output = popen("lsusb -d 046d:","r"); if (command_output) { char line[MAX_LINE_LENGTH] = {0}; @@ -50,15 +52,15 @@ GHOST_NDOFManagerX11::GHOST_NDOFManagerX11(GHOST_System& sys) if (sscanf(line, "Bus %*d Device %*d: ID %hx:%hx", &vendor_id, &product_id) == 2) if (setDevice(vendor_id, product_id)) { m_available = true; - break; // stop looking once the first 3D mouse is found + break; /* stop looking once the first 3D mouse is found */ } } pclose(command_output); } } else { - printf("ndof: spacenavd not found\n"); - // This isn't a hard error, just means the user doesn't have a 3D mouse. + puts("ndof: spacenavd not found"); + /* This isn't a hard error, just means the user doesn't have a 3D mouse. */ } } @@ -73,11 +75,6 @@ bool GHOST_NDOFManagerX11::available() return m_available; } -//bool GHOST_NDOFManagerX11::identifyDevice() -//{ -// -//} - bool GHOST_NDOFManagerX11::processEvents() { GHOST_TUns64 now = m_system.getMilliSeconds(); @@ -88,7 +85,7 @@ bool GHOST_NDOFManagerX11::processEvents() switch (e.type) { case SPNAV_EVENT_MOTION: { - // convert to blender view coords + /* convert to blender view coords */ short t[3] = {e.motion.x, e.motion.y, -e.motion.z}; short r[3] = {-e.motion.rx, -e.motion.ry, e.motion.rz}; @@ -104,3 +101,5 @@ bool GHOST_NDOFManagerX11::processEvents() } return anyProcessed; } + +#endif /* WITH_INPUT_NDOF */ diff --git a/intern/ghost/intern/GHOST_NDOFManagerX11.h b/intern/ghost/intern/GHOST_NDOFManagerX11.h index 82bd256c707..0a549753756 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerX11.h +++ b/intern/ghost/intern/GHOST_NDOFManagerX11.h @@ -26,6 +26,8 @@ #ifndef _GHOST_NDOFMANAGERX11_H_ #define _GHOST_NDOFMANAGERX11_H_ +#ifdef WITH_INPUT_NDOF + #include "GHOST_NDOFManager.h" /* Event capture is handled within the NDOF manager on Linux, @@ -40,10 +42,9 @@ public: bool processEvents(); private: - // bool identifyDevice(); - bool m_available; }; -#endif +#endif /* WITH_INPUT_NDOF */ +#endif /* #include guard */ diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm index 17f0f2d6ecd..303c2b24497 100644 --- a/intern/ghost/intern/GHOST_SystemCocoa.mm +++ b/intern/ghost/intern/GHOST_SystemCocoa.mm @@ -21,8 +21,8 @@ * * The Original Code is: all of this file. * - * Contributor(s): Maarten Gribnau 05/2001 - * Damien Plisson 09/2009 + * Contributors: Maarten Gribnau 05/2001 + * Damien Plisson 09/2009 * * ***** END GPL LICENSE BLOCK ***** */ @@ -43,16 +43,17 @@ #include "GHOST_EventButton.h" #include "GHOST_EventCursor.h" #include "GHOST_EventWheel.h" -#include "GHOST_EventNDOF.h" #include "GHOST_EventTrackpad.h" #include "GHOST_EventDragnDrop.h" #include "GHOST_EventString.h" - #include "GHOST_TimerManager.h" #include "GHOST_TimerTask.h" #include "GHOST_WindowManager.h" #include "GHOST_WindowCocoa.h" +#ifdef WITH_INPUT_NDOF #include "GHOST_NDOFManagerCocoa.h" +#endif + #include "AssertMacros.h" #pragma mark KeyMap, mouse converters diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 105f71b514f..d5100e589f2 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -42,8 +42,10 @@ #include "GHOST_EventKey.h" #include "GHOST_EventButton.h" #include "GHOST_EventWheel.h" -#include "GHOST_NDOFManagerX11.h" #include "GHOST_DisplayManagerX11.h" +#ifdef WITH_INPUT_NDOF +#include "GHOST_NDOFManagerX11.h" +#endif #include "GHOST_Debug.h" @@ -815,22 +817,6 @@ GHOST_SystemX11::processEvent(XEvent *xe) } } -#if 0 // obsolete SpaceNav code - - void * -GHOST_SystemX11:: -prepareNdofInfo(volatile GHOST_TEventNDOFData *currentNdofValues) -{ - const vector& v(m_windowManager->getWindows()); - if (v.size() > 0) - sNdofInfo.window = static_cast(v[0])->getXWindow(); - sNdofInfo.display = m_display; - sNdofInfo.currValues = currentNdofValues; - return (void*)&sNdofInfo; -} - -#endif - GHOST_TSuccess GHOST_SystemX11:: getModifierKeys( -- cgit v1.2.3 From 577293569a0e7ba8fdb0411401c86fc1bd5dcbde Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 7 Aug 2011 16:54:40 +0000 Subject: scons patch from jensverwiebe fix a silly bug in version detection, - added an OSX sdk-check jensverwiebe, needs to get commit access!, but will apply his patches for now. --- SConstruct | 9 +++++- build_files/scons/config/darwin-config.py | 54 +++++++++++++++++-------------- build_files/scons/tools/btools.py | 4 ++- 3 files changed, 41 insertions(+), 26 deletions(-) diff --git a/SConstruct b/SConstruct index b422892680d..b35f3fdbf7b 100644 --- a/SConstruct +++ b/SConstruct @@ -253,8 +253,15 @@ if 'blenderlite' in B.targets: if k not in B.arguments: env[k] = v -# detect presence of 3D_CONNEXION_CLIENT_LIBRARY for OSX +# Extended OSX_SDK and 3D_CONNEXION_CLIENT_LIBRARY detection for OSX if env['OURPLATFORM']=='darwin': + print B.bc.OKGREEN + "Detected Xcode version: -- " + B.bc.ENDC + env['XCODE_CUR_VER'][:9] + " --" + print "Available " + env['MACOSX_SDK_CHECK'] + if not 'Mac OS X 10.5' in env['MACOSX_SDK_CHECK']: + print B.bc.OKGREEN + "MacOSX10.5.sdk not available:" + B.bc.ENDC + " using MacOSX10.6.sdk" + else: + print B.bc.OKGREEN + "Found recommended sdk :" + B.bc.ENDC + " using MacOSX10.5.sdk" + # for now, Mac builders must download and install the driver framework from 3Dconnexion # necessary header file lives here when installed: # /Library/Frameworks/3DconnexionClient.framework/Versions/Current/Headers/ConnexionClientAPI.h diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py index a8bad81324c..0c851e43825 100644 --- a/build_files/scons/config/darwin-config.py +++ b/build_files/scons/config/darwin-config.py @@ -1,9 +1,7 @@ # # Note : if you want to alter this file -# copy it as a whole in the upper folder -# as user-config.py -# dont create a new file with only some -# vars changed. +# setup a user-config.py in main directory +# and set the wanted values there import commands @@ -21,17 +19,23 @@ cmd = 'uname -p' MAC_PROC=commands.getoutput(cmd) cmd = 'uname -r' cmd_res=commands.getoutput(cmd) -MAC_CUR_VER='10.5' # by default (test below fails on my 10.5 PowerPC) -if cmd_res[:2]=='7': + +if cmd_res[:1]=='7': MAC_CUR_VER='10.3' -elif cmd_res[:2]=='8': +elif cmd_res[:1]=='8': MAC_CUR_VER='10.4' -elif cmd_res[:2]=='9': +elif cmd_res[:1]=='9': MAC_CUR_VER='10.5' elif cmd_res[:2]=='10': MAC_CUR_VER='10.6' elif cmd_res[:2]=='11': MAC_CUR_VER='10.7' +cmd = 'xcodebuild -version' +cmd_xcode=commands.getoutput(cmd) +XCODE_CUR_VER=cmd_xcode +cmd = 'xcodebuild -showsdks' +cmd_sdk=commands.getoutput(cmd) +MACOSX_SDK_CHECK=cmd_sdk if MACOSX_ARCHITECTURE == 'x86_64' or MACOSX_ARCHITECTURE == 'ppc64': USE_QTKIT=True # Carbon quicktime is not available for 64bit @@ -60,21 +64,23 @@ elif MACOSX_ARCHITECTURE == 'i386' and MAC_CUR_VER == '10.4': LCGDIR = '#../lib/darwin-8.x.i386' CC = 'gcc-4.0' CXX = 'g++-4.0' -elif MAC_CUR_VER >= '10.6': - # OSX 10.6 and 10.7 developer tools do not come with sdk < 10.6 anymore ! - MAC_MIN_VERS = '10.6' - MACOSX_DEPLOYMENT_TARGET = '10.6' - MACOSX_SDK='/Developer/SDKs/MacOSX10.6.sdk' - LCGDIR = '#../lib/darwin-9.x.universal' - CC = 'llvm-gcc-4.2' - CXX = 'llvm-g++-4.2' else : - MAC_MIN_VERS = '10.5' - MACOSX_DEPLOYMENT_TARGET = '10.5' - MACOSX_SDK='/Developer/SDKs/MacOSX10.5.sdk' - LCGDIR = '#../lib/darwin-9.x.universal' - CC = 'gcc-4.2' - CXX = 'g++-4.2' + if 'Mac OS X 10.5' in MACOSX_SDK_CHECK: + # OSX 10.5/6 with Xcode 3.x + MAC_MIN_VERS = '10.5' + MACOSX_DEPLOYMENT_TARGET = '10.5' + MACOSX_SDK='/Developer/SDKs/MacOSX10.5.sdk' + LCGDIR = '#../lib/darwin-9.x.universal' + CC = 'gcc-4.2' + CXX = 'g++-4.2' + else: + # OSX 10.6/7 with Xcode 4.x + MAC_MIN_VERS = '10.6' + MACOSX_DEPLOYMENT_TARGET = '10.6' + MACOSX_SDK='/Developer/SDKs/MacOSX10.6.sdk' + LCGDIR = '#../lib/darwin-9.x.universal' + CC = 'gcc-4.2' + CXX = 'g++-4.2' LIBDIR = '${LCGDIR}' @@ -200,7 +206,7 @@ BF_GETTEXT_LIB = 'intl' BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' WITH_BF_GAMEENGINE = True -WITH_BF_PLAYER = False +WITH_BF_PLAYER = True WITH_BF_BULLET = True BF_BULLET = '#extern/bullet2/src' @@ -251,7 +257,7 @@ BF_OPENGL_LIBPATH = '/System/Library/Frameworks/OpenGL.framework/Libraries' BF_OPENGL_LINKFLAGS = ['-framework', 'OpenGL'] #OpenCollada flags -WITH_BF_COLLADA = False +WITH_BF_COLLADA = True BF_COLLADA = '#source/blender/collada' BF_COLLADA_INC = '${BF_COLLADA}' BF_COLLADA_LIB = 'bf_collada' diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index 9b911b9d6f0..25e0582c536 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -149,7 +149,7 @@ def validate_arguments(args, bc): 'BF_PROFILE_CFLAGS', 'BF_PROFILE_CCFLAGS', 'BF_PROFILE_CXXFLAGS', 'BF_PROFILE_LINKFLAGS', 'BF_DEBUG_CFLAGS', 'BF_DEBUG_CCFLAGS', 'BF_DEBUG_CXXFLAGS', 'C_WARN', 'CC_WARN', 'CXX_WARN', - 'LLIBS', 'PLATFORM_LINKFLAGS','MACOSX_ARCHITECTURE', + 'LLIBS', 'PLATFORM_LINKFLAGS','MACOSX_ARCHITECTURE', 'MACOSX_SDK_CHECK', 'XCODE_CUR_VER', ] @@ -462,6 +462,8 @@ def read_opts(env, cfg, args): ('LLIBS', 'Platform libs', []), ('PLATFORM_LINKFLAGS', 'Platform linkflags', []), ('MACOSX_ARCHITECTURE', 'python_arch.zip select', ''), + ('MACOSX_SDK_CHECK', 'detect available OSX sdk`s', ''), + ('XCODE_CUR_VER', 'detect XCode version', ''), (BoolVariable('BF_PROFILE', 'Add profiling information if true', False)), ('BF_PROFILE_CFLAGS', 'C only profiling flags', []), -- cgit v1.2.3 From 3a55da7616fa5613b8a95a591059bb55102dbfb4 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 7 Aug 2011 17:01:44 +0000 Subject: removed old ndof transform code, to be replaced with modern stuff in 2.6 --- source/blender/editors/transform/CMakeLists.txt | 1 - source/blender/editors/transform/transform.c | 5 - source/blender/editors/transform/transform.h | 26 ---- .../blender/editors/transform/transform_generics.c | 1 - .../editors/transform/transform_ndofinput.c | 162 --------------------- source/blender/editors/transform/transform_ops.c | 7 +- 6 files changed, 2 insertions(+), 200 deletions(-) delete mode 100644 source/blender/editors/transform/transform_ndofinput.c diff --git a/source/blender/editors/transform/CMakeLists.txt b/source/blender/editors/transform/CMakeLists.txt index 283b09f42e4..e44cc1f5df3 100644 --- a/source/blender/editors/transform/CMakeLists.txt +++ b/source/blender/editors/transform/CMakeLists.txt @@ -41,7 +41,6 @@ set(SRC transform_generics.c transform_input.c transform_manipulator.c - transform_ndofinput.c transform_ops.c transform_orientations.c transform_snap.c diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 39e26bc6436..c1c812e8c68 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1006,11 +1006,6 @@ int transformEvent(TransInfo *t, wmEvent *event) else view_editmove(event->type); t->redraw= 1; break; -#if 0 - case NDOF_MOTION: - // should have been caught by tranform_modal - return OPERATOR_PASS_THROUGH; -#endif default: handled = 0; break; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index d8e42488787..485344875d4 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -67,14 +67,6 @@ struct wmTimer; struct ARegion; struct ReportList; -typedef struct NDofInput { - int flag; - int axis; - float fval[7]; - float factor[3]; -} NDofInput; - - /* The ctrl value has different meaning: 0 : No value has been typed @@ -273,7 +265,6 @@ typedef struct TransInfo { TransCon con; /* transformed constraint */ TransSnap tsnap; NumInput num; /* numerical input */ - NDofInput ndof; /* ndof input */ MouseInput mouse; /* mouse input */ char redraw; /* redraw flag */ float prop_size; /* proportional circle radius */ @@ -340,9 +331,6 @@ typedef struct TransInfo { /* ******************** Macros & Prototypes *********************** */ -/* NDOFINPUT FLAGS */ -#define NDOF_INIT 1 - /* transinfo->state */ #define TRANS_STARTING 0 #define TRANS_RUNNING 1 @@ -683,20 +671,6 @@ void calculatePropRatio(TransInfo *t); void getViewVector(TransInfo *t, float coord[3], float vec[3]); -/*********************** NDofInput ********************************/ - -void initNDofInput(NDofInput *n); -int hasNDofInput(NDofInput *n); -void applyNDofInput(NDofInput *n, float *vec); -int handleNDofInput(NDofInput *n, struct wmEvent *event); - -/* handleNDofInput return values */ -#define NDOF_REFRESH 1 -#define NDOF_NOMOVE 2 -#define NDOF_CONFIRM 3 -#define NDOF_CANCEL 4 - - /*********************** Transform Orientations ******************************/ void initTransformOrientation(struct bContext *C, TransInfo *t); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index c81c398e696..306796efee9 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1165,7 +1165,6 @@ int initTransInfo (bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) setTransformViewMatrices(t); initNumInput(&t->num); - initNDofInput(&t->ndof); return 1; } diff --git a/source/blender/editors/transform/transform_ndofinput.c b/source/blender/editors/transform/transform_ndofinput.c deleted file mode 100644 index c5946163770..00000000000 --- a/source/blender/editors/transform/transform_ndofinput.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is: all of this file. - * - * Contributor(s): Martin Poirier - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/editors/transform/transform_ndofinput.c - * \ingroup edtransform - */ - - - #include /* fabs */ -#include /* for sprintf */ - -#include "BLI_utildefines.h" - -#include "BKE_global.h" /* for G */ - /* ABS */ - -#include "WM_types.h" - -#include "transform.h" - -#if 0 -static int updateNDofMotion(NDofInput *n); // return 0 when motion is null -#endif -static void resetNDofInput(NDofInput *n); - -void initNDofInput(NDofInput *n) -{ - int i; - - n->flag = 0; - n->axis = 0; - - resetNDofInput(n); - - for(i = 0; i < 3; i++) - { - n->factor[i] = 1.0f; - } -} - -static void resetNDofInput(NDofInput *n) -{ - int i; - for(i = 0; i < 6; i++) - { - n->fval[i] = 0.0f; - } -} - - -int handleNDofInput(NDofInput *UNUSED(n), wmEvent *UNUSED(event)) -{ - int retval = 0; - // TRANSFORM_FIX_ME -#if 0 - switch(event) - { - case NDOFMOTION: - if (updateNDofMotion(n) == 0) - { - retval = NDOF_NOMOVE; - } - else - { - retval = NDOF_REFRESH; - } - break; - case NDOFBUTTON: - if (val == 1) - { - retval = NDOF_CONFIRM; - } - else if (val == 2) - { - retval = NDOF_CANCEL; - resetNDofInput(n); - n->flag &= ~NDOF_INIT; - } - break; - } -#endif - return retval; -} - -int hasNDofInput(NDofInput *n) -{ - return (n->flag & NDOF_INIT) == NDOF_INIT; -} - -void applyNDofInput(NDofInput *n, float *vec) -{ - if (hasNDofInput(n)) - { - int i, j; - - for (i = 0, j = 0; i < 6; i++) - { - if (n->axis & (1 << i)) - { - vec[j] = n->fval[i] * n->factor[j]; - j++; - } - } - } -} - -// TRANSFORM_FIX_ME -#if 0 - -static int updateNDofMotion(NDofInput *n) -{ - float fval[7]; - int i; - int retval = 0; - - getndof(fval); - - if (G.vd->ndoffilter) - filterNDOFvalues(fval); - - for(i = 0; i < 6; i++) - { - if (!retval && fval[i] != 0.0f) - { - retval = 1; - } - - n->fval[i] += fval[i] / 1024.0f; - } - - n->flag |= NDOF_INIT; - - return retval; -} -#endif - - - - diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 54e0b31e201..231293024f0 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -360,17 +360,14 @@ static int transform_modal(bContext *C, wmOperator *op, wmEvent *event) TransInfo *t = op->customdata; - #if 0 +#if 0 // stable 2D mouse coords map to different 3D coords while the 3D mouse is active // in other words, 2D deltas are no longer good enough! // disable until individual 'transformers' behave better if (event->type == NDOF_MOTION) - { - /* puts("transform_modal: passing through NDOF_MOTION"); */ return OPERATOR_PASS_THROUGH; - } - #endif +#endif /* XXX insert keys are called here, and require context */ t->context= C; -- cgit v1.2.3 From f12df1e3863ca2043947c64786e0f3c7f0fccca0 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 7 Aug 2011 17:22:47 +0000 Subject: ndof data change: operators can access values as vectors or components, as both are handy --- source/blender/windowmanager/WM_types.h | 10 +++++-- .../blender/windowmanager/intern/wm_event_system.c | 33 ++++++++++++---------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 7fd52e89a5f..697133bb163 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -389,8 +389,14 @@ typedef struct wmNDOFMotionData { /* awfully similar to GHOST_TEventNDOFMotionData... */ // Each component normally ranges from -1 to +1, but can exceed that. // These use blender standard view coordinates, with positive rotations being CCW about the axis. - float tvec[3]; // translation - float rvec[3]; // rotation: + union { + float tvec[3]; // translation + struct { float tx, ty, tz; }; + }; + union { + float rvec[3]; // rotation: + struct { float rx, ry, rz; }; + }; // axis = (rx,ry,rz).normalized // amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg] float dt; // time since previous NDOF Motion event diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 258d6bbc025..c1fd903c479 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2329,29 +2329,32 @@ static void attach_ndof_data(wmEvent* event, const GHOST_TEventNDOFMotionData* g const float s = U.ndof_sensitivity; - data->tvec[0]= s * ghost->tx; + data->tx = s * ghost->tx; - data->rvec[0]= s * ghost->rx; - data->rvec[1]= s * ghost->ry; - data->rvec[2]= s * ghost->rz; + data->rx = s * ghost->rx; + data->rx = s * ghost->ry; + data->rx = s * ghost->rz; if (U.ndof_flag & NDOF_ZOOM_UPDOWN) { - // rotate so Y is where Z was (maintain handed-ness) - data->tvec[1]= s * ghost->tz; - data->tvec[2]= s * -ghost->ty; - - // should this affect rotation also? - // initial guess is 'yes', but get user feedback immediately! -#if 0 // after turning this on, my guess becomes 'no' - data->rvec[1]= s * ghost->rz; - data->rvec[2]= s * ghost->ry; + /* rotate so Y is where Z was */ + data->ty = s * ghost->tz; + data->tz = s * ghost->ty; + /* maintain handed-ness? or just do what feels right? */ + + /* should this affect rotation also? + * initial guess is 'yes', but get user feedback immediately! + */ +#if 0 + /* after turning this on, my guess becomes 'no' */ + data->ry = s * ghost->rz; + data->rz = s * ghost->ry; #endif } else { - data->tvec[1]= s * ghost->ty; - data->tvec[2]= s * ghost->tz; + data->ty = s * ghost->ty; + data->tz = s * ghost->tz; } data->dt = ghost->dt; -- cgit v1.2.3 From 5681380db0f46ec16f942ecba9002061ce37b87d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 7 Aug 2011 17:38:36 +0000 Subject: simplify x11 path code, had unneeded NULL checks and std namespace --- intern/ghost/intern/GHOST_SystemPathsX11.cpp | 19 +++++++------------ source/blender/windowmanager/intern/wm_event_system.c | 4 ++-- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemPathsX11.cpp b/intern/ghost/intern/GHOST_SystemPathsX11.cpp index dd8935732c5..135f5c42dc5 100644 --- a/intern/ghost/intern/GHOST_SystemPathsX11.cpp +++ b/intern/ghost/intern/GHOST_SystemPathsX11.cpp @@ -43,7 +43,11 @@ #include // for fprintf only #include // for exit -using namespace std; +#ifdef PREFIX +static const char *static_path= PREFIX "/share" ; +#else +static const char *static_path= NULL; +#endif GHOST_SystemPathsX11::GHOST_SystemPathsX11() { @@ -56,21 +60,12 @@ GHOST_SystemPathsX11::~GHOST_SystemPathsX11() const GHOST_TUns8* GHOST_SystemPathsX11::getSystemDir() const { /* no prefix assumes a portable build which only uses bundled scripts */ -#ifdef PREFIX - return (GHOST_TUns8*) PREFIX "/share"; -#else - return NULL; -#endif + return (const GHOST_TUns8 *)static_path; } const GHOST_TUns8* GHOST_SystemPathsX11::getUserDir() const { - const char* env = getenv("HOME"); - if(env) { - return (GHOST_TUns8*) env; - } else { - return NULL; - } + return (const GHOST_TUns8 *)getenv("HOME"); } const GHOST_TUns8* GHOST_SystemPathsX11::getBinaryDir() const diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index c1fd903c479..413ff181f11 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2332,8 +2332,8 @@ static void attach_ndof_data(wmEvent* event, const GHOST_TEventNDOFMotionData* g data->tx = s * ghost->tx; data->rx = s * ghost->rx; - data->rx = s * ghost->ry; - data->rx = s * ghost->rz; + data->ry = s * ghost->ry; + data->rz = s * ghost->rz; if (U.ndof_flag & NDOF_ZOOM_UPDOWN) { -- cgit v1.2.3 From 28ae6d85fee9ec32c7a16b9fa004ba6fef3d84f8 Mon Sep 17 00:00:00 2001 From: Mike Erwin Date: Sun, 7 Aug 2011 18:57:39 +0000 Subject: fixed typo --- source/blender/makesrna/intern/rna_userdef.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 57044188dd9..a685c6deb34 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2769,7 +2769,7 @@ static void rna_def_userdef_input(BlenderRNA *brna) prop= RNA_def_property(srna, "ndof_orbit_invert_axes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_ORBIT_INVERT_AXES); RNA_def_property_ui_text(prop, "Invert Axes", "Toggle between moving the viewpoint or moving the scene being viewed"); - /* in 3Dx docs, this is called 'object mode' vs. 'target camera mode' + /* in 3Dx docs, this is called 'object mode' vs. 'target camera mode' */ /* 3D view: fly */ prop= RNA_def_property(srna, "ndof_lock_horizon", PROP_BOOLEAN, PROP_NONE); -- cgit v1.2.3 From fad243a4bfd0414b0f8656c570c23ba72012cd40 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sun, 7 Aug 2011 22:48:04 +0000 Subject: Mac Compile fix for ndof, by jensverwiebe. Thanks! --- SConstruct | 4 +++- build_files/scons/config/darwin-config.py | 8 +++++--- build_files/scons/tools/btools.py | 3 ++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/SConstruct b/SConstruct index b35f3fdbf7b..7b25f744103 100644 --- a/SConstruct +++ b/SConstruct @@ -265,9 +265,11 @@ if env['OURPLATFORM']=='darwin': # for now, Mac builders must download and install the driver framework from 3Dconnexion # necessary header file lives here when installed: # /Library/Frameworks/3DconnexionClient.framework/Versions/Current/Headers/ConnexionClientAPI.h - if not os.path.exists('/Library/Frameworks/3DconnexionClient.framework'): + if env['WITH_BF_3DMOUSE'] == 1 and not os.path.exists('/Library/Frameworks/3DconnexionClient.framework'): print "3D_CONNEXION_CLIENT_LIBRARY not found, disabling WITH_BF_3DMOUSE" # avoid build errors ! env['WITH_BF_3DMOUSE'] = 0 + env['FOUND_NDOF_DRIVERS'] = 0 + if env['WITH_BF_OPENMP'] == 1: if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py index 0c851e43825..29695896921 100644 --- a/build_files/scons/config/darwin-config.py +++ b/build_files/scons/config/darwin-config.py @@ -1,7 +1,9 @@ # # Note : if you want to alter this file -# setup a user-config.py in main directory -# and set the wanted values there +# copy it as a whole in the upper folder +# as user-config.py +# dont create a new file with only some +# vars changed. import commands @@ -313,7 +315,7 @@ if WITH_BF_QUICKTIME: else: PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS+['-framework','QuickTime'] -if WITH_BF_3DMOUSE: +if FOUND_NDOF_DRIVERS: PLATFORM_LINKFLAGS = PLATFORM_LINKFLAGS + ['-weak_framework','3DconnexionClient'] #note to build succesfully on 10.3.9 SDK you need to patch 10.3.9 by adding the SystemStubs.a lib from 10.4 diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index 25e0582c536..aac16555df9 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -136,7 +136,7 @@ def validate_arguments(args, bc): 'BF_NO_ELBEEM', 'WITH_BF_CXX_GUARDEDALLOC', 'WITH_BF_JEMALLOC', 'WITH_BF_STATICJEMALLOC', 'BF_JEMALLOC', 'BF_JEMALLOC_INC', 'BF_JEMALLOC_LIBPATH', 'BF_JEMALLOC_LIB', 'BF_JEMALLOC_LIB_STATIC', - 'BUILDBOT_BRANCH', 'WITH_BF_3DMOUSE', 'WITH_BF_STATIC3DMOUSE', 'BF_3DMOUSE', 'BF_3DMOUSE_INC', 'BF_3DMOUSE_LIB', 'BF_3DMOUSE_LIBPATH', 'BF_3DMOUSE_LIB_STATIC' + 'BUILDBOT_BRANCH', 'WITH_BF_3DMOUSE', 'FOUND_NDOF_DRIVERS', 'WITH_BF_STATIC3DMOUSE', 'BF_3DMOUSE', 'BF_3DMOUSE_INC', 'BF_3DMOUSE_LIB', 'BF_3DMOUSE_LIBPATH', 'BF_3DMOUSE_LIB_STATIC' ] # Have options here that scons expects to be lists @@ -439,6 +439,7 @@ def read_opts(env, cfg, args): (BoolVariable('WITH_BF_NOBLENDER', 'Do not build blender if true', False)), (BoolVariable('WITH_BF_3DMOUSE', 'Build blender with support of 3D mouses', False)), + (BoolVariable('FOUND_NDOF_DRIVERS', 'We detected NDOF libs or framework', False)), (BoolVariable('WITH_BF_STATIC3DMOUSE', 'Staticly link to 3d mouse library', False)), ('BF_3DMOUSE', '3d mouse library base path', ''), ('BF_3DMOUSE_INC', '3d mouse library include path', ''), -- cgit v1.2.3 From 0160901c90f0db6ad615af31dd8c9201b660257f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 8 Aug 2011 03:31:25 +0000 Subject: - update X3D and FBX testing checksums - building with GHOST/SDL now adds the PREFIX - image.external_edit operator errors out if the filepath isnt set (was annoying and loaded gimp while running tests) --- intern/ghost/CMakeLists.txt | 20 ++++++++++++-------- release/scripts/startup/bl_operators/image.py | 10 ++++++++-- source/tests/CMakeLists.txt | 14 +++++++------- 3 files changed, 27 insertions(+), 17 deletions(-) diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index d7658c50a36..bdda0f3382e 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -149,6 +149,10 @@ if(WITH_HEADLESS OR WITH_GHOST_SDL) intern/GHOST_SystemPathsX11.cpp intern/GHOST_SystemPathsX11.h ) + + if(NOT WITH_INSTALL_PORTABLE) + add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}") + endif() elseif(WIN32) list(APPEND SRC @@ -204,10 +208,6 @@ elseif(APPLE) elseif(UNIX) - if(WITH_X11_XINPUT) - add_definitions(-DWITH_X11_XINPUT) - endif() - list(APPEND INC_SYS ${X11_X11_INCLUDE_PATH} ) @@ -224,10 +224,6 @@ elseif(UNIX) intern/GHOST_WindowX11.h ) - if(NOT WITH_INSTALL_PORTABLE) - add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}") - endif() - if(X11_XF86keysym_INCLUDE_PATH) add_definitions(-DWITH_XF86KEYSYM) list(APPEND INC_SYS @@ -243,6 +239,14 @@ elseif(UNIX) ) endif() + if(NOT WITH_INSTALL_PORTABLE) + add_definitions(-DPREFIX="${CMAKE_INSTALL_PREFIX}") + endif() + + if(WITH_X11_XINPUT) + add_definitions(-DWITH_X11_XINPUT) + endif() + elseif(WIN32) if(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX") diff --git a/release/scripts/startup/bl_operators/image.py b/release/scripts/startup/bl_operators/image.py index 23bafe2eaae..aca9b581b97 100644 --- a/release/scripts/startup/bl_operators/image.py +++ b/release/scripts/startup/bl_operators/image.py @@ -61,13 +61,19 @@ class EditExternally(bpy.types.Operator): def execute(self, context): import os import subprocess - filepath = os.path.normpath(bpy.path.abspath(self.filepath)) + + filepath = self.filepath + + if not filepath: + self.report({'ERROR'}, "Image path not set") + return {'CANCELLED'} + + filepath = os.path.normpath(bpy.path.abspath(filepath)) if not os.path.exists(filepath): self.report({'ERROR'}, "Image path %r not found, image may be packed or " "unsaved." % filepath) - return {'CANCELLED'} cmd = self._editor_guess(context) + [filepath] diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt index 8fd0d6e7099..3f802642d33 100644 --- a/source/tests/CMakeLists.txt +++ b/source/tests/CMakeLists.txt @@ -111,7 +111,7 @@ add_test(export_obj_all_objects ${TEST_BLENDER_EXE} --run={'FINISHED'}&bpy.ops.export_scene.obj\(filepath='${TEST_OUT_DIR}/export_obj_all_objects.obj',use_selection=False,use_nurbs=True\) --md5_source=${TEST_OUT_DIR}/export_obj_all_objects.obj --md5_source=${TEST_OUT_DIR}/export_obj_all_objects.mtl - --md5=01c123948efadc6a71ab2c09a5925756 --md5_method=FILE + --md5=04b3ed97cede07a19548fc518ce9f8ca --md5_method=FILE ) @@ -196,7 +196,7 @@ add_test(export_x3d_cube ${TEST_BLENDER_EXE} --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py -- --run={'FINISHED'}&bpy.ops.export_scene.x3d\(filepath='${TEST_OUT_DIR}/export_x3d_cube.x3d',use_selection=False\) --md5_source=${TEST_OUT_DIR}/export_x3d_cube.x3d - --md5=5e804c689896116331fa190a9fabbad4 --md5_method=FILE + --md5=2621d8cc2cc1d34f6711c54519907dac --md5_method=FILE ) add_test(export_x3d_nurbs ${TEST_BLENDER_EXE} @@ -204,7 +204,7 @@ add_test(export_x3d_nurbs ${TEST_BLENDER_EXE} --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py -- --run={'FINISHED'}&bpy.ops.export_scene.x3d\(filepath='${TEST_OUT_DIR}/export_x3d_nurbs.x3d',use_selection=False\) --md5_source=${TEST_OUT_DIR}/export_x3d_nurbs.x3d - --md5=2d5bcf43cf7b6fbbef1c8cc566968fe5 --md5_method=FILE + --md5=d56b3736bab063d101d42079bd276f01 --md5_method=FILE ) add_test(export_x3d_all_objects ${TEST_BLENDER_EXE} @@ -212,7 +212,7 @@ add_test(export_x3d_all_objects ${TEST_BLENDER_EXE} --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py -- --run={'FINISHED'}&bpy.ops.export_scene.x3d\(filepath='${TEST_OUT_DIR}/export_x3d_all_objects.x3d',use_selection=False\) --md5_source=${TEST_OUT_DIR}/export_x3d_all_objects.x3d - --md5=2809ec13a4cab55d265ce7525c5db1b7 --md5_method=FILE + --md5=0914c9a7fcdbfc5741c1269497e9068b --md5_method=FILE ) @@ -273,7 +273,7 @@ add_test(export_fbx_cube ${TEST_BLENDER_EXE} --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py -- --run={'FINISHED'}&bpy.ops.export_scene.fbx\(filepath='${TEST_OUT_DIR}/export_fbx_cube.fbx',use_selection=False,use_metadata=False\) --md5_source=${TEST_OUT_DIR}/export_fbx_cube.fbx - --md5=83dca99a0cb338852b8c85951a44c68a --md5_method=FILE + --md5=86da2495dffd7c270e682f599be6b3d1 --md5_method=FILE ) add_test(export_fbx_nurbs ${TEST_BLENDER_EXE} @@ -281,7 +281,7 @@ add_test(export_fbx_nurbs ${TEST_BLENDER_EXE} --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py -- --run={'FINISHED'}&bpy.ops.export_scene.fbx\(filepath='${TEST_OUT_DIR}/export_fbx_nurbs.fbx',use_selection=False,use_metadata=False\) --md5_source=${TEST_OUT_DIR}/export_fbx_nurbs.fbx - --md5=c7d9491ffa6264e820ed1e12df63f871 --md5_method=FILE + --md5=88a263ddb5181e6522dc214debb92ced --md5_method=FILE ) add_test(export_fbx_all_objects ${TEST_BLENDER_EXE} @@ -289,5 +289,5 @@ add_test(export_fbx_all_objects ${TEST_BLENDER_EXE} --python ${CMAKE_CURRENT_LIST_DIR}/bl_test.py -- --run={'FINISHED'}&bpy.ops.export_scene.fbx\(filepath='${TEST_OUT_DIR}/export_fbx_all_objects.fbx',use_selection=False,use_metadata=False\) --md5_source=${TEST_OUT_DIR}/export_fbx_all_objects.fbx - --md5=22867f82e1615fd1eae18cfaac8ba035 --md5_method=FILE + --md5=e6f75fe7de9aa366896456e13eafc76a --md5_method=FILE ) -- cgit v1.2.3 From 22d2764d50f8571c0bbcdb4e7c944ba02763b43c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 8 Aug 2011 05:21:37 +0000 Subject: use static sets rather then tuples, python optimizes this case. minor change to lightmap unpack collecting unique meshes. --- release/scripts/modules/bpy_extras/io_utils.py | 2 +- release/scripts/modules/bpy_extras/mesh_utils.py | 4 ++-- release/scripts/modules/bpyml.py | 2 +- release/scripts/modules/bpyml_ui.py | 6 +++--- release/scripts/modules/rna_info.py | 8 ++++---- release/scripts/startup/bl_operators/uvcalc_lightmap.py | 2 +- release/scripts/startup/bl_operators/wm.py | 4 ++-- release/scripts/startup/bl_ui/properties_particle.py | 4 ++-- release/scripts/templates/operator_modal.py | 2 +- release/scripts/templates/operator_modal_draw.py | 2 +- release/scripts/templates/operator_modal_view3d.py | 2 +- source/tests/bl_run_operators.py | 2 +- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py index 45664384efa..bb4e95c051f 100644 --- a/release/scripts/modules/bpy_extras/io_utils.py +++ b/release/scripts/modules/bpy_extras/io_utils.py @@ -379,7 +379,7 @@ def path_reference(filepath, is_relative = filepath.startswith("//") filepath_abs = os.path.normpath(bpy.path.abspath(filepath, base_src)) - if mode in ('ABSOLUTE', 'RELATIVE', 'STRIP'): + if mode in {'ABSOLUTE', 'RELATIVE', 'STRIP'}: pass elif mode == 'MATCH': mode = 'RELATIVE' if is_relative else 'ABSOLUTE' diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py index f9400674138..c965169ff04 100644 --- a/release/scripts/modules/bpy_extras/mesh_utils.py +++ b/release/scripts/modules/bpy_extras/mesh_utils.py @@ -294,7 +294,7 @@ def ngon_tesselate(from_data, indices, fix_loops=True): ''' Normal single concave loop filling ''' - if type(from_data) in (tuple, list): + if type(from_data) in {tuple, list}: verts = [Vector(from_data[i]) for ii, i in enumerate(indices)] else: verts = [from_data.vertices[i].co for ii, i in enumerate(indices)] @@ -312,7 +312,7 @@ def ngon_tesselate(from_data, indices, fix_loops=True): used twice. This is used by lightwave LWO files a lot ''' - if type(from_data) in (tuple, list): + if type(from_data) in {tuple, list}: verts = [vert_treplet(Vector(from_data[i]), ii) for ii, i in enumerate(indices)] else: diff --git a/release/scripts/modules/bpyml.py b/release/scripts/modules/bpyml.py index fdf5172a0b3..42d2bf94fba 100644 --- a/release/scripts/modules/bpyml.py +++ b/release/scripts/modules/bpyml.py @@ -120,7 +120,7 @@ def fromxml(data): py_item = (xml_node.tagName, _fromxml_kwargs(xml_node), []) #_fromxml_iter(py_item, xml_node.childNodes) for xml_node_child in xml_node.childNodes: - if xml_node_child.nodeType not in (xml_node_child.TEXT_NODE, xml_node_child.COMMENT_NODE): + if xml_node_child.nodeType not in {xml_node_child.TEXT_NODE, xml_node_child.COMMENT_NODE}: py_item[CHILDREN].append(_fromxml(xml_node_child)) return py_item diff --git a/release/scripts/modules/bpyml_ui.py b/release/scripts/modules/bpyml_ui.py index 5df04b8bf34..f4b6de23dbb 100644 --- a/release/scripts/modules/bpyml_ui.py +++ b/release/scripts/modules/bpyml_ui.py @@ -40,13 +40,13 @@ def _parse_rna(prop, value): elif prop.type == 'INT': value = int(value) elif prop.type == 'BOOLEAN': - if value in (True, False): + if value in {True, False}: pass else: - if value not in ("True", "False"): + if value not in {"True", "False"}: raise Exception("invalid bool value: %s" % value) value = bool(value == "True") - elif prop.type in ('STRING', 'ENUM'): + elif prop.type in {'STRING', 'ENUM'}: pass elif prop.type == 'POINTER': value = eval("_bpy." + value) diff --git a/release/scripts/modules/rna_info.py b/release/scripts/modules/rna_info.py index 93a344f4b09..943f86adecb 100644 --- a/release/scripts/modules/rna_info.py +++ b/release/scripts/modules/rna_info.py @@ -148,7 +148,7 @@ class InfoStructRNA: import types functions = [] for identifier, attr in self._get_py_visible_attrs(): - if type(attr) in (types.FunctionType, types.MethodType): + if type(attr) in {types.FunctionType, types.MethodType}: functions.append((identifier, attr)) return functions @@ -156,7 +156,7 @@ class InfoStructRNA: import types functions = [] for identifier, attr in self._get_py_visible_attrs(): - if type(attr) in (types.BuiltinMethodType, types.BuiltinFunctionType): + if type(attr) in {types.BuiltinMethodType, types.BuiltinFunctionType}: functions.append((identifier, attr)) return functions @@ -260,7 +260,7 @@ class InfoPropertyRNA: if self.array_length: type_str += " array of %d items" % (self.array_length) - if self.type in ("float", "int"): + if self.type in {"float", "int"}: type_str += " in [%s, %s]" % (range_str(self.min), range_str(self.max)) elif self.type == "enum": if self.is_enum_flag: @@ -595,7 +595,7 @@ def BuildRNAInfo(): for prop in rna_info.properties: # ERROR CHECK default = prop.default - if type(default) in (float, int): + if type(default) in {float, int}: if default < prop.min or default > prop.max: print("\t %s.%s, %s not in [%s - %s]" % (rna_info.identifier, prop.identifier, default, prop.min, prop.max)) diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py index 9ae0cd0ddf9..2f1acf0a5dc 100644 --- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py +++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py @@ -520,7 +520,7 @@ def unwrap(operator, context, **kwargs): if obj and obj.type == 'MESH': meshes = [obj.data] else: - meshes = {me.name: me for obj in context.selected_objects if obj.type == 'MESH' for me in (obj.data,) if not me.library if len(me.faces)}.values() + meshes = list({me for obj in context.selected_objects if obj.type == 'MESH' for me in (obj.data,) if me.faces and me.library is None}) if not meshes: operator.report({'ERROR'}, "No mesh object.") diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index af33e45668c..f9327aa6c40 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -586,7 +586,7 @@ class WM_OT_context_modal_mouse(bpy.types.Operator): self._values_clear() return {'FINISHED'} - elif event_type in ('RIGHTMOUSE', 'ESC'): + elif event_type in {'RIGHTMOUSE', 'ESC'}: self._values_restore() return {'FINISHED'} @@ -839,7 +839,7 @@ class WM_OT_properties_edit(bpy.types.Operator): prop_ui = rna_idprop_ui_prop_get(item, prop) - if prop_type in (float, int): + if prop_type in {float, int}: prop_ui['soft_min'] = prop_ui['min'] = prop_type(self.min) prop_ui['soft_max'] = prop_ui['max'] = prop_type(self.max) diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index 4c92296dacd..2870aab75ef 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -462,7 +462,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel): col.prop(part, "mass") col.prop(part, "use_multiply_size_mass", text="Multiply mass with size") - if part.physics_type in ('NEWTON', 'FLUID'): + if part.physics_type in {'NEWTON', 'FLUID'}: split = layout.split() col = split.column() @@ -921,7 +921,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel, bpy.types.Panel): col = row.column() col.label(text="") - if part.render_type in ('OBJECT', 'GROUP') and not part.use_advanced_hair: + if part.render_type in {'OBJECT', 'GROUP'} and not part.use_advanced_hair: row = layout.row(align=True) row.prop(part, "particle_size") row.prop(part, "size_random", slider=True) diff --git a/release/scripts/templates/operator_modal.py b/release/scripts/templates/operator_modal.py index 78dbd4c6b43..ed98c2cf50e 100644 --- a/release/scripts/templates/operator_modal.py +++ b/release/scripts/templates/operator_modal.py @@ -18,7 +18,7 @@ class ModalOperator(bpy.types.Operator): elif event.type == 'LEFTMOUSE': return {'FINISHED'} - elif event.type in ('RIGHTMOUSE', 'ESC'): + elif event.type in {'RIGHTMOUSE', 'ESC'}: context.object.location.x = self.first_value return {'CANCELLED'} diff --git a/release/scripts/templates/operator_modal_draw.py b/release/scripts/templates/operator_modal_draw.py index e7a1f6e4ffe..b3d525a59bf 100644 --- a/release/scripts/templates/operator_modal_draw.py +++ b/release/scripts/templates/operator_modal_draw.py @@ -45,7 +45,7 @@ class ModalDrawOperator(bpy.types.Operator): context.region.callback_remove(self._handle) return {'FINISHED'} - elif event.type in ('RIGHTMOUSE', 'ESC'): + elif event.type in {'RIGHTMOUSE', 'ESC'}: context.region.callback_remove(self._handle) return {'CANCELLED'} diff --git a/release/scripts/templates/operator_modal_view3d.py b/release/scripts/templates/operator_modal_view3d.py index c494f121017..925449835ca 100644 --- a/release/scripts/templates/operator_modal_view3d.py +++ b/release/scripts/templates/operator_modal_view3d.py @@ -29,7 +29,7 @@ class ViewOperator(bpy.types.Operator): context.area.header_text_set() return {'FINISHED'} - elif event.type in ('RIGHTMOUSE', 'ESC'): + elif event.type in {'RIGHTMOUSE', 'ESC'}: rv3d.view_location = self._initial_location context.area.header_text_set() return {'CANCELLED'} diff --git a/source/tests/bl_run_operators.py b/source/tests/bl_run_operators.py index 668b4e69228..b64055df252 100644 --- a/source/tests/bl_run_operators.py +++ b/source/tests/bl_run_operators.py @@ -70,7 +70,7 @@ def run_ops(operators, setup_func=None): setup_func() - for mode in ('EXEC_DEFAULT', 'INVOKE_DEFAULT'): + for mode in {'EXEC_DEFAULT', 'INVOKE_DEFAULT'}: try: op(mode) except: -- cgit v1.2.3 From 349c838996a5d042bb3ebb06162ab9b2c6716fdd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 8 Aug 2011 05:43:04 +0000 Subject: add missing header to cmake files (else some IDE's wont index it) --- build_files/buildbot/slave_compile.py | 2 +- build_files/buildbot/slave_pack.py | 2 +- build_files/cmake/macros.cmake | 7 +++++++ source/blender/windowmanager/CMakeLists.txt | 1 + 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/build_files/buildbot/slave_compile.py b/build_files/buildbot/slave_compile.py index 9dd39ccd308..b83a65f2466 100644 --- a/build_files/buildbot/slave_compile.py +++ b/build_files/buildbot/slave_compile.py @@ -134,7 +134,7 @@ else: scons_options.append('BF_FFMPEG_LIB=' + (' '.join(ffmpeg_lib))) scons_options.append('BF_FFMPEG_DLL=' + (' '.join(ffmpeg_dll))) - scons_options.append('BF_BITNESS='+bitness) + scons_options.append('BF_BITNESS=' + bitness) retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options) sys.exit(retcode) diff --git a/build_files/buildbot/slave_pack.py b/build_files/buildbot/slave_pack.py index e779b10bd2a..5fdeb4a8ad5 100644 --- a/build_files/buildbot/slave_pack.py +++ b/build_files/buildbot/slave_pack.py @@ -98,7 +98,7 @@ if builder.find('scons') != -1: scons_options.append('BF_FFMPEG_LIB=' + (' '.join(ffmpeg_lib))) scons_options.append('BF_FFMPEG_DLL=' + (' '.join(ffmpeg_dll))) - scons_options.append('BF_BITNESS='+bitness) + scons_options.append('BF_BITNESS=' + bitness) retcode = subprocess.call(['python', 'scons/scons.py'] + scons_options) sys.exit(retcode) diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index ed200abd419..27694bcb875 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -62,6 +62,10 @@ macro(blender_include_dirs foreach(_INC ${ARGV}) get_filename_component(_ABS_INC ${_INC} ABSOLUTE) list(APPEND _ALL_INCS ${_ABS_INC}) + # for checking for invalid includes, disable for regular use + ##if(NOT EXISTS "${_ABS_INC}/") + ## message(FATAL_ERROR "Include not found: ${_ABS_INC}/") + ##endif() endforeach() include_directories(${_ALL_INCS}) unset(_INC) @@ -75,6 +79,9 @@ macro(blender_include_dirs_sys foreach(_INC ${ARGV}) get_filename_component(_ABS_INC ${_INC} ABSOLUTE) list(APPEND _ALL_INCS ${_ABS_INC}) + ##if(NOT EXISTS "${_ABS_INC}/") + ## message(FATAL_ERROR "Include not found: ${_ABS_INC}/") + ##endif() endforeach() include_directories(SYSTEM ${_ALL_INCS}) unset(_INC) diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index 20ac3ba7077..dc83e29b497 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -67,6 +67,7 @@ set(SRC intern/wm_window.c WM_api.h + WM_keymap.h WM_types.h wm.h wm_cursors.h -- cgit v1.2.3 From 8eec116d0e752a02f664364aa062b23843d2d05a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 8 Aug 2011 06:54:07 +0000 Subject: add missing keys for ghost/sdl --- intern/ghost/intern/GHOST_SystemSDL.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp index 69a9f936cf6..cd7efba592b 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cpp +++ b/intern/ghost/intern/GHOST_SystemSDL.cpp @@ -167,6 +167,8 @@ convertSDLKey(SDL_Scancode key) GXMAP(type,SDL_SCANCODE_APOSTROPHE, GHOST_kKeyQuote); GXMAP(type,SDL_SCANCODE_GRAVE, GHOST_kKeyAccentGrave); GXMAP(type,SDL_SCANCODE_MINUS, GHOST_kKeyMinus); + GXMAP(type,SDL_SCANCODE_EQUALS, GHOST_kKeyEqual); + GXMAP(type,SDL_SCANCODE_SLASH, GHOST_kKeySlash); GXMAP(type,SDL_SCANCODE_BACKSLASH, GHOST_kKeyBackslash); GXMAP(type,SDL_SCANCODE_KP_EQUALS, GHOST_kKeyEqual); @@ -198,6 +200,7 @@ convertSDLKey(SDL_Scancode key) GXMAP(type,SDL_SCANCODE_CAPSLOCK, GHOST_kKeyCapsLock); GXMAP(type,SDL_SCANCODE_SCROLLLOCK, GHOST_kKeyScrollLock); GXMAP(type,SDL_SCANCODE_NUMLOCKCLEAR, GHOST_kKeyNumLock); + GXMAP(type,SDL_SCANCODE_PRINTSCREEN, GHOST_kKeyPrintScreen); /* keypad events */ -- cgit v1.2.3 From cc0ec3aa33e09b964cc6f4d0c8d253671ebebf4a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 8 Aug 2011 08:22:01 +0000 Subject: fix [#28178] make single user copy of object data doesn't work --- source/blender/editors/include/ED_object.h | 2 +- .../editors/interface/interface_templates.c | 38 +++++++++++++--------- source/blender/editors/object/object_relations.c | 14 ++++++++ source/blender/makesrna/RNA_access.h | 1 + 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 28d0a9520b2..c646ec55506 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -108,7 +108,7 @@ int ED_object_add_generic_get_opts(struct bContext *C, struct wmOperator *op, fl struct Object *ED_object_add_type(struct bContext *C, int type, float *loc, float *rot, int enter_editmode, unsigned int layer); void ED_object_single_users(struct Main *bmain, struct Scene *scene, int full); - +void ED_object_single_user(struct Scene *scene, struct Object *ob); /* object motion paths */ void ED_objects_clear_paths(struct bContext *C); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 2d443bbfcd0..35125d1483e 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -53,6 +53,7 @@ #include "BKE_displist.h" #include "ED_screen.h" +#include "ED_object.h" #include "ED_render.h" #include "RNA_access.h" @@ -275,18 +276,28 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) break; case UI_ID_ALONE: if(id) { + const int do_scene_obj= (GS(id->name) == ID_OB) && + (template->ptr.type == &RNA_SceneObjects); + /* make copy */ - if(id_copy(id, &newid, 0) && newid) { - /* copy animation actions too */ - BKE_copy_animdata_id_action(id); - /* us is 1 by convention, but RNA_property_pointer_set - will also incremement it, so set it to zero */ - newid->us= 0; - - /* assign copy */ - RNA_id_pointer_create(newid, &idptr); - RNA_property_pointer_set(&template->ptr, template->prop, idptr); - RNA_property_update(C, &template->ptr, template->prop); + if(do_scene_obj) { + Scene *scene= CTX_data_scene(C); + ED_object_single_user(scene, (struct Object *)id); + WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene); + } + else { + if(id_copy(id, &newid, 0) && newid) { + /* copy animation actions too */ + BKE_copy_animdata_id_action(id); + /* us is 1 by convention, but RNA_property_pointer_set + will also incremement it, so set it to zero */ + newid->us= 0; + + /* assign copy */ + RNA_id_pointer_create(newid, &idptr); + RNA_property_pointer_set(&template->ptr, template->prop, idptr); + RNA_property_update(C, &template->ptr, template->prop); + } } } break; @@ -404,10 +415,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str sprintf(str, "%d", id->us); - if(id->us<10) - but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy."); - else - but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X+10,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy."); + but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X + ((id->us < 10) ? 0:10), UI_UNIT_Y, NULL, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy."); uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE)); if(!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib) || !editable) diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 0fb7cf8b640..225e6e73563 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1402,6 +1402,20 @@ static void single_object_users(Scene *scene, View3D *v3d, int flag) set_sca_new_poins(); } +/* not an especially efficient function, only added so the single user + * button can be functional.*/ +void ED_object_single_user(Scene *scene, Object *ob) +{ + Base *base; + + for(base= FIRSTBASE; base; base= base->next) { + if(base->object == ob) base->flag |= OB_DONE; + else base->flag &= ~OB_DONE; + } + + single_object_users(scene, NULL, OB_DONE); +} + static void new_id_matar(Material **matar, int totcol) { ID *id; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 882fbce9271..0033a1ff437 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -392,6 +392,7 @@ extern StructRNA RNA_Scene; extern StructRNA RNA_SceneGameData; extern StructRNA RNA_SceneRenderLayer; extern StructRNA RNA_SceneSequence; +extern StructRNA RNA_SceneObjects; extern StructRNA RNA_Scopes; extern StructRNA RNA_Screen; extern StructRNA RNA_ScrewModifier; -- cgit v1.2.3 From 24acf58fc47f1ed6132bcaa07b86b756e1b3194a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 8 Aug 2011 09:01:09 +0000 Subject: quiet harmless py resource warning - file opened but not closed. --- release/scripts/startup/bl_ui/space_userpref_keymap.py | 2 ++ source/blender/editors/interface/interface_templates.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/release/scripts/startup/bl_ui/space_userpref_keymap.py b/release/scripts/startup/bl_ui/space_userpref_keymap.py index 5658cc96281..9736ea5bc22 100644 --- a/release/scripts/startup/bl_ui/space_userpref_keymap.py +++ b/release/scripts/startup/bl_ui/space_userpref_keymap.py @@ -545,9 +545,11 @@ class WM_OT_keyconfig_import(bpy.types.Operator): if not self.filepath: raise Exception("Filepath not set") + # simply check we can open f = open(self.filepath, "r") if not f: raise Exception("Could not open file") + f.close() config_name = basename(self.filepath) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 35125d1483e..305a4a8b3d6 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -277,7 +277,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) case UI_ID_ALONE: if(id) { const int do_scene_obj= (GS(id->name) == ID_OB) && - (template->ptr.type == &RNA_SceneObjects); + (template->ptr.type == &RNA_SceneObjects); /* make copy */ if(do_scene_obj) { -- cgit v1.2.3 From 64a298645f91e2ae4a64891fec68e76a712f145c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 8 Aug 2011 09:09:44 +0000 Subject: report error on installign keymaps rather then raising an exception. --- .../scripts/startup/bl_ui/space_userpref_keymap.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_userpref_keymap.py b/release/scripts/startup/bl_ui/space_userpref_keymap.py index 9736ea5bc22..f63da6551de 100644 --- a/release/scripts/startup/bl_ui/space_userpref_keymap.py +++ b/release/scripts/startup/bl_ui/space_userpref_keymap.py @@ -542,24 +542,24 @@ class WM_OT_keyconfig_import(bpy.types.Operator): def execute(self, context): from os.path import basename import shutil - if not self.filepath: - raise Exception("Filepath not set") - # simply check we can open - f = open(self.filepath, "r") - if not f: - raise Exception("Could not open file") - f.close() + if not self.filepath: + self.report({'ERROR'}, "Filepath not set") + return {'CANCELLED'} config_name = basename(self.filepath) path = bpy.utils.user_resource('SCRIPTS', os.path.join("presets", "keyconfig"), create=True) path = os.path.join(path, config_name) - if self.keep_original: - shutil.copy(self.filepath, path) - else: - shutil.move(self.filepath, path) + try: + if self.keep_original: + shutil.copy(self.filepath, path) + else: + shutil.move(self.filepath, path) + except Exception as e: + self.report({'ERROR'}, "Installing keymap failed: %s" % e) + return {'CANCELLED'} # sneaky way to check we're actually running the code. bpy.utils.keyconfig_set(path) -- cgit v1.2.3 From 85b77c931d2de579671dbe68640341407f91ecb2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 8 Aug 2011 14:50:10 +0000 Subject: fix [#28183] Wavefront OBJ import has no preset saving --- .../blender/editors/interface/interface_layout.c | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 85cc944f03b..df654cf3645 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -2745,6 +2745,25 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,in uiItemL(layout, "* Redo Unsupported *", ICON_NONE); // XXX, could give some nicer feedback or not show redo panel at all? } + /* menu */ + if(op->type->flag & OPTYPE_PRESET) { + /* XXX, no simple way to get WM_MT_operator_presets.bl_label from python! Label remains the same always! */ + PointerRNA op_ptr; + uiLayout *row; + + row= uiLayoutRow(layout, TRUE); + uiItemM(row, (bContext *)C, "WM_MT_operator_presets", NULL, ICON_NONE); + + WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add"); + RNA_string_set(&op_ptr, "operator", op->type->idname); + op_ptr= uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMIN, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); + + WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add"); + RNA_string_set(&op_ptr, "operator", op->type->idname); + RNA_boolean_set(&op_ptr, "remove_active", 1); + op_ptr= uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMOUT, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); + } + if(op->type->ui) { op->layout= layout; op->type->ui((bContext*)C, op); @@ -2759,25 +2778,6 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op,in RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); - /* menu */ - if(op->type->flag & OPTYPE_PRESET) { - /* XXX, no simple way to get WM_MT_operator_presets.bl_label from python! Label remains the same always! */ - PointerRNA op_ptr; - uiLayout *row; - - row= uiLayoutRow(layout, TRUE); - uiItemM(row, (bContext *)C, "WM_MT_operator_presets", NULL, ICON_NONE); - - WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add"); - RNA_string_set(&op_ptr, "operator", op->type->idname); - op_ptr= uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMIN, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); - - WM_operator_properties_create(&op_ptr, "WM_OT_operator_preset_add"); - RNA_string_set(&op_ptr, "operator", op->type->idname); - RNA_boolean_set(&op_ptr, "remove_active", 1); - op_ptr= uiItemFullO(row, "WM_OT_operator_preset_add", "", ICON_ZOOMOUT, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0); - } - /* main draw call */ empty= uiDefAutoButsRNA(layout, &ptr, check_prop, label_align) == 0; -- cgit v1.2.3 From ffd5fa3eea5a724df0ebb14da2aa6f54768277d3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 9 Aug 2011 07:09:49 +0000 Subject: off by 1 error with number keys in ghost/sdl --- intern/ghost/intern/GHOST_SystemSDL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp index cd7efba592b..aebb94d5cdf 100644 --- a/intern/ghost/intern/GHOST_SystemSDL.cpp +++ b/intern/ghost/intern/GHOST_SystemSDL.cpp @@ -146,7 +146,7 @@ convertSDLKey(SDL_Scancode key) if ((key >= SDL_SCANCODE_A) && (key <= SDL_SCANCODE_Z)) { type= GHOST_TKey( key - SDL_SCANCODE_A + int(GHOST_kKeyA)); } else if ((key >= SDL_SCANCODE_1) && (key <= SDL_SCANCODE_0)) { - type= GHOST_TKey(key - SDL_SCANCODE_1 + int(GHOST_kKey0)); + type= (key == SDL_SCANCODE_0) ? GHOST_kKey0 : GHOST_TKey(key - SDL_SCANCODE_1 + int(GHOST_kKey1)); } else if ((key >= SDL_SCANCODE_F1) && (key <= SDL_SCANCODE_F12)) { type= GHOST_TKey(key - SDL_SCANCODE_F1 + int(GHOST_kKeyF1)); } else if ((key >= SDL_SCANCODE_F13) && (key <= SDL_SCANCODE_F24)) { -- cgit v1.2.3 From 2dfc51388c7f67a271a4765d2492ab3cb36c2814 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Tue, 9 Aug 2011 07:33:51 +0000 Subject: Blender 2.59: * Update the readme file * Update link to release logs, they point to http://www.blender.org/development/release-logs/blender-259/ now --- release/scripts/startup/bl_ui/space_info.py | 2 +- release/text/readme.html | 12 ++++++------ source/blender/windowmanager/intern/wm_operators.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index f66cee7f431..ee214bd4178 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -352,7 +352,7 @@ class INFO_MT_help(bpy.types.Menu): layout = self.layout layout.operator("wm.url_open", text="Manual", icon='HELP').url = 'http://wiki.blender.org/index.php/Doc:Manual' - layout.operator("wm.url_open", text="Release Log", icon='URL').url = 'http://www.blender.org/development/release-logs/blender-258/' + layout.operator("wm.url_open", text="Release Log", icon='URL').url = 'http://www.blender.org/development/release-logs/blender-259/' layout.separator() diff --git a/release/text/readme.html b/release/text/readme.html index 2b5a4071a7f..95094b9c0cb 100644 --- a/release/text/readme.html +++ b/release/text/readme.html @@ -12,22 +12,22 @@ -

Blender 2.58

+

Blender 2.59


About

Welcome to Blender, the free, open source 3D application for modeling, animation, rendering, compositing, video editing and game creation. Blender is available for Linux, Mac OS X, Windows, Solaris and FreeBSD and has a large world-wide community.

Blender can be used freely for any purpose, including commercial use and distribution. It's free and open-source software, released under the GNU GPL licence. The entire source code is available on our website.

For more information, visit blender.org.


-

2.58

-

The Blender Foundation and online developer community is proud to present Blender 2.58. This release is the second official stable release of the Blender 2.5 series, and represents the culmination of many years of redesign and development work. More information about this release.

+

2.59

+

The Blender Foundation and online developer community is proud to present Blender 2.59. This release is the third official stable release of the Blender 2.5 series, and represents the culmination of many years of redesign and development work. More information about this release.

What to Expect:

• Big improvements - This is our most exciting version to date, already a significant improvement in many ways over 2.49

• Missing/Incomplete Features - Although most of it is there, not all functionality from pre-2.5 versions has been restored yet. Some functionality may be re-implemented a different way.

• Changes - If you're used to the old Blenders, Blender 2.5 may seem quite different at first, but it won't be long before it grows on you even more than before.


Bugs

-

Although Blender 2.58 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender 2.58. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.

+

Although Blender 2.59 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender 2.59. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.


Package Contents

The downloaded Blender package includes:

@@ -51,11 +51,11 @@

Links

Users:

General information www.blender.org
- Full release log www.blender.org/development/release-logs/blender-258/
+ Full release log www.blender.org/development/release-logs/blender-259/
Tutorials www.blender.org/education-help/
Manual wiki.blender.org/index.php/Doc:Manual
User Forum www.blenderartists.org
- IRC #blender on irc.freenode.net
+ IRC #blenderchat on irc.freenode.net

Developers:

Development www.blender.org/development/
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index cea2d6b3fe5..610a962ba62 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1247,7 +1247,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar col = uiLayoutColumn(split, 0); uiItemL(col, "Links", ICON_NONE); uiItemStringO(col, "Donations", ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/blenderorg/blender-foundation/donation-payment/"); - uiItemStringO(col, "Release Log", ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/release-logs/blender-258/"); + uiItemStringO(col, "Release Log", ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/development/release-logs/blender-259/"); uiItemStringO(col, "Manual", ICON_URL, "WM_OT_url_open", "url", "http://wiki.blender.org/index.php/Doc:2.5/Manual"); uiItemStringO(col, "Blender Website", ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/"); uiItemStringO(col, "User Community", ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/community/user-community/"); // -- cgit v1.2.3 From f98e2161d0ae0d4b90d0602fd11aa100856d0e48 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 9 Aug 2011 07:48:40 +0000 Subject: change doxygen string to 2.59 --- doc/doxygen/Doxyfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index 79b3f1a4160..b4d3b14b9dd 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = Blender # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = "V2.58" +PROJECT_NUMBER = "V2.59" # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer -- cgit v1.2.3 From 08e184f3022494e1c834c22a25f7a23d2312e9d8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 9 Aug 2011 13:50:27 +0000 Subject: note to address issue raised by report [#28190]. --- doc/python_api/rst/bge.logic.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/python_api/rst/bge.logic.rst b/doc/python_api/rst/bge.logic.rst index 128f87f76bd..7c392901eec 100644 --- a/doc/python_api/rst/bge.logic.rst +++ b/doc/python_api/rst/bge.logic.rst @@ -217,6 +217,12 @@ General functions Loads a scene into the game engine. + .. note:: + + This function is not effective immediately, the scene is queued + and added on the next logic cycle where it will be available + from `getSceneList` + :arg name: The name of the scene :type name: string :arg overlay: Overlay or underlay (optional) -- cgit v1.2.3 From da6bc69ca9c79ad351950b0df7acdd6483fbc8c3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 9 Aug 2011 14:16:22 +0000 Subject: fix [#28191] Exception when enabling a script for a newer Blender build --- doc/python_api/rst/bge.logic.rst | 4 ++-- release/scripts/startup/bl_ui/space_userpref.py | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/doc/python_api/rst/bge.logic.rst b/doc/python_api/rst/bge.logic.rst index 7c392901eec..798491b4710 100644 --- a/doc/python_api/rst/bge.logic.rst +++ b/doc/python_api/rst/bge.logic.rst @@ -220,8 +220,8 @@ General functions .. note:: This function is not effective immediately, the scene is queued - and added on the next logic cycle where it will be available - from `getSceneList` + and added on the next logic cycle where it will be available + from `getSceneList` :arg name: The name of the scene :type name: string diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index e6fd8dcb949..944f5aaf4c1 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -1076,17 +1076,25 @@ class WM_OT_addon_enable(bpy.types.Operator): bl_idname = "wm.addon_enable" bl_label = "Enable Add-On" - module = StringProperty(name="Module", description="Module name of the addon to enable") + module = StringProperty( + name="Module", + description="Module name of the addon to enable", + ) def execute(self, context): mod = addon_utils.enable(self.module) if mod: - # check if add-on is written for current blender version, or raise a warning info = addon_utils.module_bl_info(mod) - if info.get("blender", (0, 0, 0)) > bpy.app.version: - self.report("WARNING','This script was written for a newer version of Blender and might not function (correctly).\nThe script is enabled though.") + info_ver = info.get("blender", (0, 0, 0)) + + if info_ver > bpy.app.version: + self.report({'WARNING'}, ("This script was written Blender " + "version %d.%d.%d and might not " + "function (correctly).\n" + "The script is enabled though.") % + info_ver) return {'FINISHED'} else: return {'CANCELLED'} -- cgit v1.2.3 From 22694c993a7e32767db4719e9fa37e93445b66a8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 9 Aug 2011 14:50:40 +0000 Subject: fix [#28186] textboxes properties not animatable --- release/scripts/startup/bl_ui/properties_data_curve.py | 2 +- source/blender/makesrna/intern/rna_curve.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index 3c88127c724..a0aacc4cec8 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -361,7 +361,7 @@ class DATA_PT_paragraph(CurveButtonsPanel, bpy.types.Panel): col.prop(text, "offset_y", text="Y") -class DATA_PT_textboxes(CurveButtonsPanel, bpy.types.Panel): +class DATA_PT_text_boxes(CurveButtonsPanel, bpy.types.Panel): bl_label = "Text Boxes" @classmethod diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index 260d483b9d2..599d36ec8b8 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -651,7 +651,7 @@ static char *rna_TextBox_path(PointerRNA *ptr) int index= (int)(tb - cu->tb); if (index >= 0 && index < cu->totbox) - return BLI_sprintfN("textboxes[%d]", index); + return BLI_sprintfN("text_boxes[%d]", index); else return BLI_strdup(""); } -- cgit v1.2.3