4.14. spacedevice — Wrapper around the 3Dconnexion Developer’s Kits

The spacedevice module allows applications to support 3D input devices such as a SpaceMouse or a SpaceBall. The module wraps the 3DxWare SDK by 3Dconnexion. For a more detailed description of the SDK see the documentation that is part of the SDK.

The module has to be used in conjunction with a GUI toolkit as there must be a window that receives the 3D input device events. In principle, any GUI toolkit can be used as long as it allows obtaining the native window handle and accessing system events. The steps necessary to use a 3D input device are as follows:

  1. Create a SpaceDevice object.
  2. Open the device using the open method. This requires a window handle of the window that will receive the SpaceDevice events.
  3. For every system event received call the translateWin32Event method and check if the event was generated by a SpaceDevice. If it was, check for the event type and process the event.
  4. When the application terminates, call the close() method to close the device.
cgkit.spacedevice.available()

Returns True if the module functionality is available. Currently, this function will only return True under Windows and if the functionality was enabled during compilation.

If this function returns False, an exception will be raised whenever you try to instantiate a class from this module.

class cgkit.spacedevice.SpaceDevice

The SpaceDevice class provides the interface to the 3DxWare library that is used to communicate with the 3D input device. The constructor of this class calls the SDK function SiInitialize() to initialize the 3DxWare library. The destructor closes the device if it is open and calls SiTerminate().

SpaceDevice.open(appname, hwnd, devID=SI_ANY_DEVICE)

Establish a connection to a 3D input device. appname is a string containing the application name, hwnd is the native window handle (as an integer) of the window that should receive the events. devID is the device id. An exception is thrown if a connection cannot be established.

This method calls the SDK functions SiOpenWinInit() and SiOpen().

SpaceDevice.close()

Close the connection to a device. The function returns immediately if there is no open connection.

This method calls the SDK function SiClose().

SpaceDevice.translateWin32Event(msgid, wparam, lparam)

Translates a Win32 event into a SpaceDevice event. The return value is a tuple (RetVal, EventType, Data).

RetVal is an object of type RetVal that represents an enumeration. It is RetVal.IS_EVENT if the event was generated by a 3D input device, otherwise it is RetVal.NOT_EVENT.

EventType is an object of type EventType that again represents an enumeration. It can take one of the following values:

  • EventType.BUTTON_EVENT
  • EventType.MOTION_EVENT
  • EventType.ZERO_EVENT
  • EventType.EXCEPTION_EVENT

The contents of the third value, Data, depend on the event type:

Event type Data
BUTTON_EVENT (pressed, released)
MOTION_EVENT (translation, rotation, period)
ZERO_EVENT None
EXCEPTION_EVENT None

pressed and released are each lists that contain the numbers of the button that were either pressed or released. translation is a 3-tuple containing the translation vector and rotation is a 3-tuple containing the rotation vector. period contains the time in milliseconds since the last device event.

This method calls the SDK functions SiGetEventWinInit() and SiGetEvent().

SpaceDevice.beep(s)

Causes the device to emit a sequence of tones and pauses that is encoded in the string s. Lowercase letters represent a tone, uppercase letters represent a pause. The closer the letter is to the beginning of the alphabet the shorter the pause or tone.

This method calls the SDK function SiBeep().

SpaceDevice.getDeviceID()

Return the device id of the currently open device.

This method calls the SDK function SiGetDeviceID().

SpaceDevice.getDeviceInfo()

Return information about the currently open device. The return value is a 5-tuple (device type, numButtons, numDegrees, canBeep, firmware).

This method calls the SDK function SiGetDeviceInfo().

SpaceDevice.getDriverInfo()

Return version information about the driver. The return value is a 5-tuple (major, minor, build, versionstr, datestr).

This method calls the SDK function SiGetDriverInfo().

SpaceDevice.getNumDevices()

Return the number of input devices detected by the driver.

This method calls the SDK function SiGetNumDevices().

SpaceDevice.rezero()

Causes the input device’s current setting to be defined as the rest position.

This method calls the SDK function SiRezero().

SpaceDevice.setUIMode(show)

Change the state of the driver menu window from within an application. The function has to be called before a call to open(). show is a boolean that specifies if the driver menu should be displayed or not.

This method calls the function SiSetUiMode().

Note

The module uses the SDK by 3Dconnexion which can be found at http://www.3dconnexion.com/sdk.htm. The following is the copyright information of the SDK:

(C) 1998-2001 3Dconnexion

Permission to use, copy, modify, and distribute this software for all purposes and without fees is hereby granted provided that this copyright notice appears in all copies. Permission to modify this software is granted and 3Dconnexion will support such modifications only if said modifications are approved by 3Dconnexion

4.14.1. Example

Here is a code example that uses pygame (you need at least version 1.7.1) as GUI toolkit. It simply prints the input device events to the console.

######################################################################
# SpaceDevice demo
#
# This demo demonstrates the usage of the SpaceDevice object in the
# cgkit.spacedevice module which can be used to access events from
# a SpaceMouse or SpaceBall. You can use this module to add support
# for a SpaceDevice in your own Python application. The demo simply
# prints the events generated from a SpaceDevice to the console.
#
# This demo uses pygame as GUI toolkit (v1.7.1 is required).
# You can use any other GUI toolkit as long as it 1) lets you obtain
# the native window handle of a window and 2) provides access to
# system events.
######################################################################

import sys
import pygame
from pygame.locals import *
from cgkit import spacedevice

# handleSystemEvent
def handleSystemEvent(evt):
    """Handle a system event.

    evt is a pygame event object that contains a system event. The function
    first checks if the event was generated by a SpaceDevice and if it was,
    it prints the event data.
    """
    # sdev is the global SpaceDevice object
    global sdev

    # Translate the system event into a SpaceDevice event...
    res, evttype, data = sdev.translateWin32Event(evt.msg, evt.wparam, evt.lparam)
    # Check if the event actually was an event generated from
    # the SpaceMouse or SpaceBall...
    print res
    if res!=spacedevice.RetVal.IS_EVENT:
        return

    # Motion event?
    if evttype==spacedevice.EventType.MOTION_EVENT:
        t,r,period = data
        print "Motion: trans:%s rot:%s period:%d"%(t, r, period)
    # Button event?
    elif evttype==spacedevice.EventType.BUTTON_EVENT:
        pressed, released = data
        print "Button: pressed:%s released:%s"%(pressed, released)
    # Zero event?
    elif evttype==spacedevice.EventType.ZERO_EVENT:
        print "Zero"

######################################################################

# Check if cgkit was compiled with SpaceDevice support...
if not spacedevice.available():
    print "No SpaceDevice functionality available"
    sys.exit(1)

# Initialize pygame...
passed, failed = pygame.init()
if failed>0:
    print "Error initializing pygame"
    sys.exit(1)

# Open a window...
pygame.display.set_caption("SpaceDevice demo")
srf = pygame.display.set_mode((640,480))

# Enable system events...
pygame.event.set_allowed(SYSWMEVENT)

# Initialize the Space Device...
sdev = spacedevice.SpaceDevice()
info = pygame.display.get_wm_info()
hwnd = info["window"]
sdev.open("Demo", hwnd)

# Print some information about the driver and the device...
major, minor, build, versionstr, datestr = sdev.getDriverInfo()
print "Driver info:"
print "------------"
print "%s, v%d.%d.%d, %s\n"%(versionstr, major, minor, build, datestr)

devtyp, numbuttons, numdegrees, canbeep, firmware = sdev.getDeviceInfo()
print "Device info:"
print "------------"
print "Device ID:",sdev.getDeviceID()
print "Type     :",devtyp
print "#Buttons :",numbuttons
print "#Degrees :",numdegrees
print "Can beep :",canbeep
print "Firmware :",firmware
print ""

# Event loop...
running = True
while running:

    # Get a list of events...
    events = pygame.event.get()

    # Process the events...
    for evt in events:

        # Close button?
        if evt.type==QUIT:
            running=False

        # Escape key?
        elif evt.type==KEYDOWN and evt.key==27:
            running=False

        # System event?
        elif evt.type==SYSWMEVENT:
            handleSystemEvent(evt)

# Close the SpaceDevice
sdev.close()