- compile fix for msvc 6 which doesn't declare M_PI at all it seems.
[blender.git] / intern / ghost / intern / GHOST_WindowWin32.cpp
index 290289201eaae1bbdbd0c4e1929feb06f39fe7ee..ac17338d66a96d10f9b827670679523aabb6f1d6 100644 (file)
 #include <string.h>
 #include "GHOST_WindowWin32.h"
 #include <GL/gl.h>
+#include <math.h>
+
+// MSVC6 still doesn't define M_PI
+#ifndef M_PI
+#define M_PI 3.1415926536
+#endif
 
 LPCSTR GHOST_WindowWin32::s_windowClassName = "GHOST_WindowClass";
 const int GHOST_WindowWin32::s_maxTitleLength = 128;
@@ -99,7 +105,11 @@ GHOST_WindowWin32::GHOST_WindowWin32(
        m_hGlRc(0),
        m_hasMouseCaptured(false),
        m_nPressedButtons(0),
-       m_customCursor(0)
+       m_customCursor(0),
+       m_tabletData(NULL),
+       m_tablet(0),
+       m_wintab(NULL),
+       m_maxPressure(0)
 {
        if (state != GHOST_kWindowStateFullScreen) {
                        /* Convert client size into window size */
@@ -159,11 +169,83 @@ GHOST_WindowWin32::GHOST_WindowWin32(
                // Force an initial paint of the window
                ::UpdateWindow(m_hWnd);
        }
+
+       m_wintab = ::LoadLibrary("Wintab32.dll");
+       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)) {
+                       // 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
+                       fpWTInfo( WTI_DEFCONTEXT, 0, &lc );
+
+                       // Open the context
+                       lc.lcPktData = PACKETDATA;
+                       lc.lcPktMode = PACKETMODE;
+                       lc.lcOptions |= CXO_MESSAGES | CXO_SYSTEM;
+
+                       /* Set the entire tablet as active */
+                       fpWTInfo(WTI_DEVICES,DVC_X,&TabletX);
+                       fpWTInfo(WTI_DEVICES,DVC_Y,&TabletY);
+
+                       /* get the max pressure, to divide into a float */
+                       BOOL pressureSupport = fpWTInfo (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);
+                       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;
+                               }
+                       }
+
+                       lc.lcInOrgX = 0;
+                       lc.lcInOrgY = 0;
+                       lc.lcInExtX = TabletX.axMax;
+                       lc.lcInExtY = TabletY.axMax;
+
+                       if (fpWTOpen) {
+                               m_tablet = fpWTOpen( m_hWnd, &lc, TRUE );
+                               if (m_tablet) {
+                                       m_tabletData = new GHOST_TabletData();
+                                       m_tabletData->Active = 0;
+                               }
+                       }
+               }
+       }
 }
 
 
 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_customCursor) {
                DestroyCursor(m_customCursor);
                m_customCursor = NULL;
@@ -563,6 +645,108 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorShape(GHOST_TStandardCursor cur
 
        return GHOST_kSuccess;
 }
+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);
+                       if (pressureSupport)
+                               m_maxPressure = Pressure.axMax;
+                       else
+                               m_maxPressure = 0;
+                       
+                       BOOL tiltSupport = fpWTInfo (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 = 0;
+               }
+       }
+}
+
+void GHOST_WindowWin32::processWin32TabletEvent(WPARAM wParam, LPARAM lParam)
+{
+       PACKET pkt;
+       if (m_wintab) {
+               GHOST_WIN32_WTPacket fpWTPacket = ( GHOST_WIN32_WTPacket ) ::GetProcAddress( m_wintab, "WTPacket" );
+               if (fpWTPacket) {
+                       if (fpWTPacket((HCTX)lParam, wParam, &pkt)) {
+                               if (m_tabletData) {
+                                       switch (pkt.pkCursor) {
+                                               case 0: /* first device */
+                                               case 3: /* second device */
+                                                       m_tabletData->Active = 0; /* puck - not yet supported */
+                                                       break;
+                                               case 1:
+                                               case 4:
+                                                       m_tabletData->Active = 1; /* stylus */
+                                                       break;
+                                               case 2:
+                                               case 5:
+                                                       m_tabletData->Active = 2; /* 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 = (fabs((float)ort.orAltitude)/(float)m_maxAltitude) * M_PI/2.0;
+                                               azmRad = ((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 = sin(M_PI/2.0 - azmRad) * vecLen;
+
+                                       } else {
+                                               m_tabletData->Xtilt = 0.0f;
+                                               m_tabletData->Ytilt = 0.0f;
+                                       }
+                               }
+                       }
+               }
+       }
+}
 
 /** Reverse the bits in a GHOST_TUns8 */
 static GHOST_TUns8 uns8ReverseBits(GHOST_TUns8 ch)