[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [31343] branches/soc-2010-merwin: Old Windows tablet code put out to pasture.

Mike Erwin significant.bit at gmail.com
Sun Aug 15 12:58:59 CEST 2010


Revision: 31343
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=31343
Author:   merwin
Date:     2010-08-15 12:58:59 +0200 (Sun, 15 Aug 2010)

Log Message:
-----------
Old Windows tablet code put out to pasture. This week's working notes.

Added Paths:
-----------
    branches/soc-2010-merwin/experimental/prev_tablet_win32.cpp
    branches/soc-2010-merwin/notes/week 12 notes.txt

Added: branches/soc-2010-merwin/experimental/prev_tablet_win32.cpp
===================================================================
--- branches/soc-2010-merwin/experimental/prev_tablet_win32.cpp	                        (rev 0)
+++ branches/soc-2010-merwin/experimental/prev_tablet_win32.cpp	2010-08-15 10:58:59 UTC (rev 31343)
@@ -0,0 +1,216 @@
+// This is the tablet-handling code that used to live in GHOST_WindowWin32.
+// For reference, study, and historical purposes.
+// [mce] = significant-bit
+
+
+// --- from header file ---
+
+#include <wintab.h>
+#define PACKETDATA	(PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR)
+#define PACKETMODE	PK_BUTTONS
+#include <pktdef.h>
+
+// 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);
+
+	const GHOST_TabletData* GetTabletData()
+	{ return m_tabletData; }
+
+	void processWin32TabletInitEvent();
+	void processWin32TabletEvent(WPARAM wParam, LPARAM lParam);
+
+	/** 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;
+
+
+// --- from constructor ---
+
+   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);
+			}
+		}
+	}
+
+
+// --- from destructor ---
+
+	if (m_wintab) {
+		if (m_tablet)
+			gpWTClose(m_tablet);
+		if (m_tabletData)
+			delete m_tabletData;
+		m_tabletData = NULL;
+      UnloadWintab();
+	}
+
+
+// --- whole functions ---
+
+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');
+	}
+}

Added: branches/soc-2010-merwin/notes/week 12 notes.txt
===================================================================
--- branches/soc-2010-merwin/notes/week 12 notes.txt	                        (rev 0)
+++ branches/soc-2010-merwin/notes/week 12 notes.txt	2010-08-15 10:58:59 UTC (rev 31343)
@@ -0,0 +1,329 @@
+7 August --
+
+Finally got Windows version compiling again. The platform config files moved during one of those merges, so my custom config had no effect. It's good now!
+
+Switched back to single-event handling for WM_INPUT. SpaceNav seems to like that better. Even at rest, it's saying T=(0,0.04,0.02) instead of just zero. So atRest isn't getting set properly. Also, events make it out of the NDOFManager (they're sent to the queue), but never arrive at the ghost -> wm rendezvous. Why not? It works fine on MacOS, just not on Windows.
+
+Fix these sort of things tomorrow. Now drive home and sleep!
+
+
+9 Aug --
+
+Got a good linux build on this machine. And yes, mouse input is just as smooth there as it is from my Mac and Windows work. Very nice! Still no SpaceNav on Linux; tonight I aim to finish SpaceNav support for Windows. Like I wrote before, events are captured and sent from the NDOF manager, they just don't show up on the other side for some reason.
+
+Device is reporting zero at home position today, so atRest works again. Weird.
+
+Apparently DefRawInputProc isn't necessary here. I guess there is no 'default' action for 3D mouse input as there is with a 2D mouse or keyboard. Good, I like streamlining the event-processing code.
+
+(I also like the 'clickety-clack' of the silicon graphics keyboard in the lab, the one used to type this sentence. Not quite the springy percussive IBM sound and feel of my youth, but a good enough substitute. My Apple Pro keyboard at home has gotten a bit hesitant lately. Time for a lube?)
+
+Windows builds are painfully slow on this old box. Time for a new one! Blender seemed more responsive and 'at home' on this same machine's Linux drive.
+
+I put a logger at the end of Win::processEvents, but the flood of 'no' is too much. Very much an event polling, not event driven system. Might need to use the return value from NDOFManager::sendMotionEvent.
+
+-- later --
+
+Windows ghost sends autorepeat keys as KeyDown. Mac ghost no longer does.
+
+NDOF Motion and Button events *are* being dispatched to the EventConsumers. Hmm... Maybe something in wm_event_add_ghostevent?
+
+I remember that while getting this to work on the Mac, the Window* was key. It didn't do anything without a target window. 
+
+	GHOST_IWindow* window = system->getWindowManager()->getActiveWindow();
+
+That was enough for MacOS. Is it not enough for Windows?
+
+WindowManager has setActiveWindow, maybe Win32 isn't using that properly. Where does Mac ghost call this function? It's in System::createWindow. Also pushes GHOST_kEventWindowActivate. The Windows version doesn't do these things. But... only on window creation? Frontmost window should always get the NDOF events. Make sure this happens!
+
+I see... Win32 ghost never sets 'active' with the window manager. Now it does! See if it works now... Nope. Why the hell not!?
+

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list