Messing with my Wacom tablet and Irrlicht I found that there weren't any simple ways to grab any kind of additional tablet data ( Pressure, tilt, etc. ) in Irr.
Using the standard WinTab API, there are basically two ways to access this data.
The first approach is calling a function along the line of getMessage() to read pending messages from the buffer.
The second approach is much like you would make a global key-hook. You basically your register thread at the system to make it pass all event to your message handler.
Since I wanted to make things as easy as possible, I decided to go with the second approach.
After a bit of research I easily managed to integrate WinTab into Irrlicht.
Lets start with the ingredients:
1 Irrlicht ( You should have this already )
1 WinTab ( Can be found here: http://www.wacomeng.com/devsupport/down ... kit126.zip )
And now for mixing it all together.
Lets start by making a folder name wintab in your irrlicht source folder.
Then put in the wintab.h, pktdef.h and wintab32.lib into the folder.
This is primarily for the sake of everything being in a place where we can find it. I you want to experiment here, go ahead.
Next we go over to the Irrlicht Include folder to do some initial preparation for our tablet event packets.
Open the IEventReceiver.h file.
At the top we start by adding a new enum, to make it detectable that we've received a tablet event:
Code: Select all
namespace irr
{
//! Enumeration for all event types there are.
enum EEVENT_TYPE
{
[...]
//! A user event with user data. This is not used by Irrlicht and can be used
//! to send user specific data though the system.
EET_USER_EVENT,
//! A Tablet event. Hurray ! :D
EET_TABLET_INPUT_EVENT
};Before closing IEventReceiver.h we go down a bit further and find the declaring of the struct holding the event data.
Here we add our own struct to keep the data while the event is passed through the system.
Code: Select all
struct SEvent
{
EEVENT_TYPE EventType;
union
{
[...]
struct
{
//! Some user specified data as int
s32 UserData1;
//! Another user specified data as int
s32 UserData2;
//! Some user specified data as float
f32 UserData3;
} UserEvent;
struct
{
//! Cursor position on the screen
s32 X;
s32 Y;
s32 Z;
//! Cursor type ( Stylus, Eraser ... )
u32 Cursor;
//! Buttons pressed
u32 Buttons;
//! Normal and Tangent Pressure
u32 NormalPressure;
u32 TangentPressure;
//! Orientation - data structure specifies the orientation of the cursor with respect to the tablet.
struct
{
s32 Azimuth;
s32 Altitude;
s32 Twist;
} Orientation;
} TabletInput;
};
};Next we go to CIrrDeviceW32.h in the Irrlicht Source folder.
At the top we include the WinTab files and declare a tablet handle, and the content of our original packet ( what we what the system to tell us about the tablet ).
Code: Select all
// Message packet structure
#define PACKETDATA ( PK_X | PK_Y | PK_Z | PK_BUTTONS | PK_CURSOR | PK_NORMAL_PRESSURE | PK_TANGENT_PRESSURE | PK_ORIENTATION )
#define PACKETMODE 0
#include "wintab/wintab.h"
#include "wintab/pktdef.h"
HCTX hTab = NULL; /* Handle for Tablet Context */Code: Select all
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
[...]
switch (message)
{
[...]
case WT_PACKET:
PACKET pkt;
if( WTPacket( (HCTX)lParam, wParam, &pkt ) )
{
event.EventType = irr::EET_TABLET_INPUT_EVENT;
event.TabletInput.X = (irr::u32)pkt.pkX;
event.TabletInput.Y = (irr::u32)pkt.pkY;
event.TabletInput.Z = (irr::u32)pkt.pkZ;
event.TabletInput.Cursor = pkt.pkCursor;
event.TabletInput.Buttons = pkt.pkButtons;
event.TabletInput.NormalPressure = pkt.pkNormalPressure;
event.TabletInput.TangentPressure = pkt.pkTangentPressure;
event.TabletInput.Orientation.Azimuth = pkt.pkOrientation.orAzimuth;
event.TabletInput.Orientation.Altitude = pkt.pkOrientation.orAltitude;
event.TabletInput.Orientation.Twist = pkt.pkOrientation.orTwist;
dev = getDeviceFromHWnd(hWnd);
if( dev )
dev->postEventFromUser(event);
}
break;The last thing we need to do is add the part that registers the thread to receive the tablet input packets form the system.
So, now scroll down a bit further and add:
Code: Select all
//! constructor
CIrrDeviceWin32::CIrrDeviceWin32(video::E_DRIVER_TYPE driverType,
core::dimension2d<s32> windowSize,
u32 bits, bool fullscreen,
bool stencilbuffer, bool vsync,
bool antiAlias,
bool highPrecisionFPU,
IEventReceiver* receiver,
HWND externalWindow,
const char* version)
: CIrrDeviceStub(version, receiver), HWnd(0), ChangedToFullScreen(false),
FullScreen(fullscreen), IsNonNTWindows(false), Resized(false),
ExternalWindow(false), Win32CursorControl(0)
{
[ ... ]
// attach external window
if (externalWindow)
{
HWnd = externalWindow;
RECT r;
GetWindowRect(HWnd, &r);
windowSize.Width = r.right - r.left;
windowSize.Height = r.bottom - r.top;
fullscreen = false;
ExternalWindow = true;
}
[ START ]
LOGCONTEXT lcMine; /* The context of the tablet */
AXIS TabletX, TabletY; /* The maximum tablet size */
/* get default region */
WTInfo( WTI_DEFCONTEXT, 0, &lcMine );
/* modify the digitizing region */
wsprintf( lcMine.lcName, "Irrlicht Digitizing %x", hInstance );
lcMine.lcOptions |= CXO_MESSAGES | CXO_SYSTEM;
// lcMine.lcMsgBase = WT_DEFBASE;
lcMine.lcPktData = PACKETDATA;
lcMine.lcPktMode = PACKETMODE;
lcMine.lcMoveMask = PACKETDATA;
lcMine.lcBtnUpMask = lcMine.lcBtnDnMask;
/* Set the entire tablet as active */
WTInfo(WTI_DEVICES,DVC_X,&TabletX);
WTInfo(WTI_DEVICES,DVC_Y,&TabletY);
lcMine.lcInOrgX = 0;
lcMine.lcInOrgY = 0;
lcMine.lcInExtX = TabletX.axMax;
lcMine.lcInExtY = TabletY.axMax;
/* output the data in screen coords */
lcMine.lcOutOrgX = lcMine.lcOutOrgY = 0;
lcMine.lcOutExtX = GetSystemMetrics(SM_CXSCREEN);
/* move origin to upper left */
lcMine.lcOutExtY = -GetSystemMetrics(SM_CYSCREEN);
/* open the region */
hTab = WTOpen( HWnd, &lcMine, TRUE );
[ END ]
// create cursor control
Win32CursorControl = new CCursorControl(windowSize, HWnd, fullscreen);
CursorControl = Win32CursorControl;
[ ... ]
}Compile Irrlicht and include the updated include files in your project and you should be able to receive the new event packets just as well as any other kind.
I'm getting sleepy now, so I'll leave it at that, but if you see any mistakes please leave a note, and I'll update the post.
I'll probably be back in a tad to update it a bit further anyways.
Oh yeah, unfortunately the WinTab API only seems to target the Windows platform, so no Linux support yet.
If you - unlike me - are a Linux guy/girl and have a tablet or just for some reason know how to implement Linux support, please share with us
Enjoy!
/Saku ( aka Wice on #Irrlicht
04-10-2007: Corrected some fatal mistakes and typos in the guide - everything should be able to compile and link now..