X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ec873c943d71f0d5f13e3398557071448cda6c23..a4027e74873007e3430af3bd77019bcab76f6c04:/wxPython/demo/Joystick.py diff --git a/wxPython/demo/Joystick.py b/wxPython/demo/Joystick.py deleted file mode 100644 index c94e215507..0000000000 --- a/wxPython/demo/Joystick.py +++ /dev/null @@ -1,1107 +0,0 @@ -#---------------------------------------------------------------------------- -# Name: Joystick.py -# Purpose: Demonstrate use of wx.Joystick -# -# Author: Jeff Grimmett (grimmtoo@softhome.net), adapted from original -# .wdr-derived demo -# -# Created: 02-Jan-2004 -# RCS-ID: $Id$ -# Copyright: -# Licence: wxWindows license -#---------------------------------------------------------------------------- -# - -import math -import wx - -haveJoystick = True -if wx.Platform == "__WXMAC__": - haveJoystick = False - -#---------------------------------------------------------------------------- - -# Once all supported versions of Python support 32-bit integers on all -# platforms, this can go up to 32. -MAX_BUTTONS = 16 - -#---------------------------------------------------------------------------- - -class Label(wx.StaticText): - # A derived StaticText that always aligns right and renders - # in a bold font. - def __init__(self, parent, label): - wx.StaticText.__init__(self, parent, -1, label, style=wx.ALIGN_RIGHT) - - self.SetFont( - wx.Font( - parent.GetFont().GetPointSize(), - parent.GetFont().GetFamily(), - parent.GetFont().GetStyle(), - wx.BOLD - )) - -#---------------------------------------------------------------------------- - - -class JoyGauge(wx.Panel): - def __init__(self, parent, stick): - - self.stick = stick - size = (100,100) - - wx.Panel.__init__(self, parent, -1, size=size) - - self.Bind(wx.EVT_PAINT, self.OnPaint) - self.Bind(wx.EVT_SIZE, self.OnSize) - self.Bind(wx.EVT_ERASE_BACKGROUND, lambda e: None) - - self.buffer = wx.EmptyBitmap(*size) - dc = wx.BufferedDC(None, self.buffer) - self.DrawFace(dc) - self.DrawJoystick(dc) - - - def OnSize(self, event): - # The face Bitmap init is done here, to make sure the buffer is always - # the same size as the Window - w, h = self.GetClientSize() - self.buffer = wx.EmptyBitmap(w,h) - dc = wx.BufferedDC(wx.ClientDC(self), self.buffer) - self.DrawFace(dc) - self.DrawJoystick(dc) - - - def DrawFace(self, dc): - dc.SetBackground(wx.Brush(self.GetBackgroundColour())) - dc.Clear() - - - def OnPaint(self, evt): - # When dc is destroyed it will blit self.buffer to the window, - # since no other drawing is needed we'll just return and let it - # do it's thing - dc = wx.BufferedPaintDC(self, self.buffer) - - - def DrawJoystick(self, dc): - # draw the guage as a maxed square in the center of this window. - w, h = self.GetClientSize() - edgeSize = min(w, h) - - xorigin = (w - edgeSize) / 2 - yorigin = (h - edgeSize) / 2 - center = edgeSize / 2 - - # Restrict our drawing activities to the square defined - # above. - dc.SetClippingRegion(xorigin, yorigin, edgeSize, edgeSize) - - # Optimize drawing a bit (for Win) - dc.BeginDrawing() - - dc.SetBrush(wx.Brush(wx.Colour(251, 252, 237))) - dc.DrawRectangle(xorigin, yorigin, edgeSize, edgeSize) - - dc.SetPen(wx.Pen(wx.BLACK, 1, wx.DOT_DASH)) - - dc.DrawLine(xorigin, yorigin + center, xorigin + edgeSize, yorigin + center) - dc.DrawLine(xorigin + center, yorigin, xorigin + center, yorigin + edgeSize) - - if self.stick: - # Get the joystick position as a float - joyx = float(self.stick.GetPosition().x) - joyy = float(self.stick.GetPosition().y) - - # Get the joystick range of motion - xmin = self.stick.GetXMin() - xmax = self.stick.GetXMax() - if xmin < 0: - xmax += abs(xmin) - joyx += abs(xmin) - xmin = 0 - xrange = max(xmax - xmin, 1) - - ymin = self.stick.GetYMin() - ymax = self.stick.GetYMax() - if ymin < 0: - ymax += abs(ymin) - joyy += abs(ymin) - ymin = 0 - yrange = max(ymax - ymin, 1) - - # calc a ratio of our range versus the joystick range - xratio = float(edgeSize) / xrange - yratio = float(edgeSize) / yrange - - # calc the displayable value based on position times ratio - xval = int(joyx * xratio) - yval = int(joyy * yratio) - - # and normalize the value from our brush's origin - x = xval + xorigin - y = yval + yorigin - - # Now to draw it. - dc.SetPen(wx.Pen(wx.RED, 2)) - dc.CrossHair(x, y) - - # Turn off drawing optimization - dc.EndDrawing() - - - def Update(self): - dc = wx.BufferedDC(wx.ClientDC(self), self.buffer) - self.DrawFace(dc) - self.DrawJoystick(dc) - - -#---------------------------------------------------------------------------- - -class JoyPanel(wx.Panel): - def __init__(self, parent, stick): - - self.stick = stick - - wx.Panel.__init__(self, parent, -1) - - sizer = wx.BoxSizer(wx.VERTICAL) - - fn = wx.Font( - parent.GetFont().GetPointSize() + 3, - parent.GetFont().GetFamily(), - parent.GetFont().GetStyle(), - wx.BOLD - ) - - t = wx.StaticText(self, -1, "X - Y Axes", style = wx.ALIGN_CENTRE) - t.SetFont(fn) - sizer.Add(t, 0, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER | wx.ALIGN_CENTER_HORIZONTAL, 1) - - self.control = JoyGauge(self, self.stick) - sizer.Add(self.control, 1, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER | wx.ALIGN_CENTER_HORIZONTAL, 1) - - self.SetSizer(sizer) - sizer.Fit(self) - - def Update(self): - self.control.Update() - - -#---------------------------------------------------------------------------- - -class POVGauge(wx.Panel): - # - # Display the current postion of the POV control - # - def __init__(self, parent, stick): - - self.stick = stick - self.size = (100, 100) - self.avail = False - self.fourDir = False - self.cts = False - - wx.Panel.__init__(self, parent, -1, size=self.size) - - self.Bind(wx.EVT_PAINT, self.OnPaint) - self.Bind(wx.EVT_SIZE, self.OnSize) - self.Bind(wx.EVT_ERASE_BACKGROUND, lambda e: None) - - self.buffer = wx.EmptyBitmap(*self.size) - dc = wx.BufferedDC(None, self.buffer) - self.DrawFace(dc) - self.DrawPOV(dc) - - - def OnSize(self, event): - # calculate the size of our display and make a buffer for it. - w, h = self.GetClientSize() - s = min(w, h) - self.size = (s, s) - self.buffer = wx.EmptyBitmap(w,h) - dc = wx.BufferedDC(wx.ClientDC(self), self.buffer) - self.DrawFace(dc) - self.DrawPOV(dc) - - - def DrawFace(self, dc): - dc.SetBackground(wx.Brush(self.GetBackgroundColour())) - dc.Clear() - - - def OnPaint(self, evt): - # When dc is destroyed it will blit self.buffer to the window, - # since no other drawing is needed we'll just return and let it - # do it's thing - dc = wx.BufferedPaintDC(self, self.buffer) - - - def DrawPOV(self, dc): - # draw the guage as a maxed circle in the center of this window. - w, h = self.GetClientSize() - diameter = min(w, h) - - xorigin = (w - diameter) / 2 - yorigin = (h - diameter) / 2 - xcenter = xorigin + diameter / 2 - ycenter = yorigin + diameter / 2 - - # Optimize drawing a bit (for Win) - dc.BeginDrawing() - - # our 'raster'. - dc.SetBrush(wx.Brush(wx.WHITE)) - dc.DrawCircle(xcenter, ycenter, diameter/2) - dc.SetBrush(wx.Brush(wx.BLACK)) - dc.DrawCircle(xcenter, ycenter, 10) - - # fancy decorations - dc.SetPen(wx.Pen(wx.BLACK, 1, wx.DOT_DASH)) - dc.DrawLine(xorigin, ycenter, xorigin + diameter, ycenter) - dc.DrawLine(xcenter, yorigin, xcenter, yorigin + diameter) - - if self.stick: - if self.avail: - - pos = -1 - - # use the appropriate function to get the POV position - if self.fourDir: - pos = self.stick.GetPOVPosition() - - if self.cts: - pos = self.stick.GetPOVCTSPosition() - - # trap invalid values - if 0 <= pos <= 36000: - vector = 30 - else: - vector = 0 - - # rotate CCW by 90 so that 0 is up. - pos = (pos / 100) - 90 - - # Normalize - if pos < 0: - pos = pos + 360 - - # Stolen from wx.lib.analogclock :-) - radiansPerDegree = math.pi / 180 - pointX = int(round(vector * math.cos(pos * radiansPerDegree))) - pointY = int(round(vector * math.sin(pos * radiansPerDegree))) - - # normalise value to match our actual center. - nx = pointX + xcenter - ny = pointY + ycenter - - # Draw the line - dc.SetPen(wx.Pen(wx.BLUE, 2)) - dc.DrawLine(xcenter, ycenter, nx, ny) - - # And a little thing to show the endpoint - dc.SetBrush(wx.Brush(wx.BLUE)) - dc.DrawCircle(nx, ny, 8) - - # Turn off drawing optimization - dc.EndDrawing() - - - def Update(self): - dc = wx.BufferedDC(wx.ClientDC(self), self.buffer) - self.DrawFace(dc) - self.DrawPOV(dc) - - - def Calibrate(self): - s = self.stick - self.avail = s.HasPOV() - self.fourDir = s.HasPOV4Dir() - self.cts = s.HasPOVCTS() - - -#---------------------------------------------------------------------------- - -class POVStatus(wx.Panel): - # - # Displays static info about the POV control - # - def __init__(self, parent, stick): - - self.stick = stick - - wx.Panel.__init__(self, parent, -1, size=(100, 100)) - - sizer = wx.BoxSizer(wx.VERTICAL) - sizer.Add((20,20)) - - self.avail = wx.CheckBox(self, -1, "Available") - sizer.Add(self.avail, 0, wx.ALL | wx.EXPAND | wx.ALIGN_LEFT, 2) - - self.fourDir = wx.CheckBox(self, -1, "4-Way Only") - sizer.Add(self.fourDir, 0, wx.ALL | wx.EXPAND | wx.ALIGN_LEFT, 2) - - self.cts = wx.CheckBox(self, -1, "Continuous") - sizer.Add(self.cts, 0, wx.ALL | wx.EXPAND | wx.ALIGN_LEFT, 2) - - self.SetSizer(sizer) - sizer.Fit(self) - - # Effectively makes the checkboxes read-only. - self.Bind(wx.EVT_CHECKBOX, self.Calibrate) - - - def Calibrate(self, evt=None): - s = self.stick - self.avail.SetValue(s.HasPOV()) - self.fourDir.SetValue(s.HasPOV4Dir()) - self.cts.SetValue(s.HasPOVCTS()) - - -#---------------------------------------------------------------------------- - -class POVPanel(wx.Panel): - def __init__(self, parent, stick): - - self.stick = stick - - wx.Panel.__init__(self, parent, -1, size=(100, 100)) - - sizer = wx.BoxSizer(wx.HORIZONTAL) - gsizer = wx.BoxSizer(wx.VERTICAL) - - sizer.Add((25,25)) - - fn = wx.Font( - parent.GetFont().GetPointSize() + 3, - parent.GetFont().GetFamily(), - parent.GetFont().GetStyle(), - wx.BOLD - ) - t = wx.StaticText(self, -1, "POV Control", style = wx.ALIGN_CENTER) - t.SetFont(fn) - gsizer.Add(t, 0, wx.ALL | wx.EXPAND, 1) - - self.display = POVGauge(self, stick) - gsizer.Add(self.display, 1, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 1) - sizer.Add(gsizer, 1, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 1) - - self.status = POVStatus(self, stick) - sizer.Add(self.status, 1, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 1) - - self.SetSizer(sizer) - sizer.Fit(self) - - - def Calibrate(self): - self.display.Calibrate() - self.status.Calibrate() - - - def Update(self): - self.display.Update() - - -#---------------------------------------------------------------------------- - -class LED(wx.Panel): - def __init__(self, parent, number): - - self.state = -1 - self.size = (20, 20) - self.number = number - - self.fn = wx.Font( - parent.GetFont().GetPointSize() - 1, - parent.GetFont().GetFamily(), - parent.GetFont().GetStyle(), - wx.BOLD - ) - - wx.Panel.__init__(self, parent, -1, size=self.size) - - self.Bind(wx.EVT_PAINT, self.OnPaint) - self.Bind(wx.EVT_SIZE, self.OnSize) - self.Bind(wx.EVT_ERASE_BACKGROUND, lambda e: None) - - self.buffer = wx.EmptyBitmap(*self.size) - dc = wx.BufferedDC(None, self.buffer) - self.DrawFace(dc) - self.DrawLED(dc) - - - def OnSize(self, event): - # calculate the size of our display. - w, h = self.GetClientSize() - s = min(w, h) - self.size = (s, s) - self.buffer = wx.EmptyBitmap(*self.size) - dc = wx.BufferedDC(wx.ClientDC(self), self.buffer) - self.DrawFace(dc) - self.DrawLED(dc) - - - def DrawFace(self, dc): - dc.SetBackground(wx.Brush(self.GetBackgroundColour())) - dc.Clear() - - - def OnPaint(self, evt): - # When dc is destroyed it will blit self.buffer to the window, - # since no other drawing is needed we'll just return and let it - # do it's thing - dc = wx.BufferedPaintDC(self, self.buffer) - - - def DrawLED(self, dc): - # bitmap size - bw, bh = self.size - - # center of bitmap - center = bw / 2 - - # calc the 0, 0 origin of the bitmap - xorigin = center - (bw / 2) - yorigin = center - (bh / 2) - - # Optimize drawing a bit (for Win) - dc.BeginDrawing() - - # our 'raster'. - if self.state == 0: - dc.SetBrush(wx.Brush(wx.RED)) - elif self.state == 1: - dc.SetBrush(wx.Brush(wx.GREEN)) - else: - dc.SetBrush(wx.Brush(wx.BLACK)) - - dc.DrawCircle(center, center, bw/2) - - txt = str(self.number) - - # Set the font for the DC ... - dc.SetFont(self.fn) - # ... and calculate how much space our value - # will take up. - fw, fh = dc.GetTextExtent(txt) - - # Calc the center of the LED, and from that - # derive the origin of our value. - tx = center - (fw/2) - ty = center - (fh/2) - - # I draw the value twice so as to give it a pseudo-shadow. - # This is (mostly) because I'm too lazy to figure out how - # to blit my text onto the gauge using one of the logical - # functions. The pseudo-shadow gives the text contrast - # regardless of whether the bar is under it or not. - dc.SetTextForeground(wx.WHITE) - dc.DrawText(txt, tx, ty) - - # Turn off drawing optimization - dc.EndDrawing() - - - def Update(self): - dc = wx.BufferedDC(wx.ClientDC(self), self.buffer) - self.DrawFace(dc) - self.DrawLED(dc) - - -#---------------------------------------------------------------------------- - -class JoyButtons(wx.Panel): - def __init__(self, parent, stick): - - self.stick = stick - self.leds = {} - - wx.Panel.__init__(self, parent, -1) - - tsizer = wx.BoxSizer(wx.VERTICAL) - - fn = wx.Font( - parent.GetFont().GetPointSize() + 3, - parent.GetFont().GetFamily(), - parent.GetFont().GetStyle(), - wx.BOLD - ) - - t = wx.StaticText(self, -1, "Buttons", style = wx.ALIGN_LEFT) - t.SetFont(fn) - tsizer.Add(t, 0, wx.ALL | wx.EXPAND | wx.ALIGN_LEFT, 1) - - sizer = wx.FlexGridSizer(4, 16, 2, 2) - - fn.SetPointSize(parent.GetFont().GetPointSize() + 1) - - for i in range(0, MAX_BUTTONS): - t = LED(self, i) - self.leds[i] = t - sizer.Add(t, 1, wx.ALL|wx.ALIGN_CENTER|wx.ALIGN_CENTER_VERTICAL, 1) - sizer.AddGrowableCol(i) - - tsizer.Add(sizer, 1, wx.ALL | wx.EXPAND | wx.ALIGN_LEFT, 1) - - self.SetSizer(tsizer) - tsizer.Fit(self) - - def Calibrate(self): - for i in range(0, MAX_BUTTONS): - self.leds[i].state = -1 - - t = self.stick.GetNumberButtons() - - for i in range(0, t): - self.leds[i].state = 0 - - def Update(self): - t = self.stick.GetButtonState() - - for i in range(0, MAX_BUTTONS): - if self.leds[i].state == 1: - self.leds[i].state = 0 - - if (t & (1< - -

wx.Joystick

-This demo illustrates the use of the wx.Joystick class, which is an interface to -one or more joysticks attached to your system. - -

The data that can be retrieved from the joystick comes in four basic flavors. -All of these are illustrated in the demo. In fact, this demo illustrates everything -you can get from the wx.Joystick control. - -

- -

Getting data from the joystick can be event-driven thanks to four event types associated -with wx.JoystickEvent, or the joystick can be polled programatically to get data on -a regular basis. - -

Data types

- -Data from the joystick comes in two flavors: that which defines the boundaries, and that -which defines the current state of the stick. Thus, we have Get*Max() and Get*Min() -methods for all axes, the max number of axes, the max number of buttons, and so on. In -general, this data can be read once and stored to speed computation up. - -

Analog Input

- -Analog input (the axes) is delivered as a whole, positive number. If you need to know -if the axis is at zero (centered) or not, you will first have to calculate that center -based on the max and min values. The demo shows a bar graph for each axis expressed -in native numerical format, plus a 'centered' X-Y axis compass showing the relationship -of that input to the calculated stick position. - -Analog input may be jumpy and spurious, so the control has a means of 'smoothing' the -analog data by setting a movement threshold. This demo sets the threshold to 10, but -you can set it at any valid value between the min and max. - -

Button Input

- -Button state is retrieved as one int that contains each button state mapped to a bit. -You get the state of a button by AND-ing its bit against the returned value, in the form - -
-     # assume buttonState is what the stick returned, and buttonBit 
-     # is the bit you want to examine
-     
-     if (buttonState & ( 1 << buttonBit )) :
-         # button pressed, do something with it
-
- -

The problem here is that some OSs return a 32-bit value for up to 32 buttons -(imagine that stick!). Python V2.3 will generate an exception for bit -values over 30. For that reason, this demo is limited to 16 buttons. - -

Note that more than one button can be pressed at a time, so be sure to check all of them! - - -

POV Input

- -POV hats come in two flavors: four-way, and continuous. four-way POVs are restricted to -the cardinal points of the compass; continuous, or CTS POV hats can deliver input in -.01 degree increments, theoreticaly. The data is returned as a whole number; the last -two digits are considered to be to the right of the decimal point, so in order to -use this information, you need to divide by 100 right off the bat. - -

Different methods are provided to retrieve the POV data for a CTS hat -versus a four-way hat. - -

Caveats

- -The wx.Joystick control is in many ways incomplete at the C++ library level, but it is -not insurmountable. In short, while the joystick interface can be event-driven, -the wx.JoystickEvent class lacks event binders for all event types. Thus, you cannot -rely on wx.JoystickEvents to tell you when something has changed, necessarilly. - - - -

Fortunately, there is an easy workaround. In the top level frame, create a wx.Timer -that will poll the stick at a set interval. Of course, if you do this, you might as -well forgo catching wxEVT_JOYSTICK_* events at all and rely on the timer to do the -polling. - -

Ideally, the timer should be a one-shot; after it fires, collect and process data as -needed, then re-start the timer, possibly using wx.CallAfter(). - - - -""" - -#---------------------------------------------------------------------------- - -if __name__ == '__main__': - import sys,os - import run - run.main(['', os.path.basename(sys.argv[0])] + sys.argv[1:])