source: trunk/src/testing/dim/devices/puck.py @ 4

Revision 4, 7.4 KB checked in by ajaworski, 13 years ago (diff)

Added modified SAGE sources

Line 
1############################################################################
2#
3# DIM - A Direct Interaction Manager for SAGE
4# Copyright (C) 2007 Electronic Visualization Laboratory,
5# University of Illinois at Chicago
6#
7# All rights reserved.
8#
9# Redistribution and use in source and binary forms, with or without
10# modification, are permitted provided that the following conditions are met:
11#
12#  * Redistributions of source code must retain the above copyright
13#    notice, this list of conditions and the following disclaimer.
14#  * Redistributions in binary form must reproduce the above
15#    copyright notice, this list of conditions and the following disclaimer
16#    in the documentation and/or other materials provided with the distribution.
17#  * Neither the name of the University of Illinois at Chicago nor
18#    the names of its contributors may be used to endorse or promote
19#    products derived from this software without specific prior written permission.
20#
21# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32#
33# Direct questions, comments etc about SAGE UI to www.evl.uic.edu/cavern/forum
34#
35# Author: Ratko Jagodic
36#       
37############################################################################
38
39
40
41import device
42from globals import *
43from math import cos, sin, radians
44
45
46def makeNew(deviceId):
47    """ this is how we instantiate the device object from
48        the main program that loads this plugin """
49    return Puck(deviceId)
50
51
52# what each puck does
53PAN_PUCK = [1, 3]
54ROTATE_PUCK = [2]
55ZOOM_PUCK = [4]
56SPECIAL_PUCK = [5]
57
58
59# puck types
60DOWN = 2
61UP = 1
62
63
64class Puck(device.Device):
65   
66    def __init__(self, deviceId):
67        device.Device.__init__(self, "puck", deviceId, needPointer=True)
68       
69        # current state of the device
70        self.puckType = 1
71        self.x = 0   # position in SAGE coords
72        self.y = 0   # position in SAGE coords
73        self.clickX = 0  # where the click happened
74        self.clickY = 0  # where the click happened
75        self.angle = 0   # current angle
76        self.prevDx = 0  # used for zoom
77        self.prevDy = 0
78        puckName = deviceId.split(":")[1]
79        self.puckId = int(puckName[ len(puckName)-1 ])   # the actual puckId from the tracker
80
81        if self.puckId in SPECIAL_PUCK:
82            self.specialDevice = True     # e.g. a magic carpet lens... generates different events
83
84
85    def onPointerAdded(self, pointerOverlay):
86        """ overriden so that we can set the correct pointer shape
87            for the event that this puck produces """
88        self.pointer = pointerOverlay
89
90        if self.puckId in PAN_PUCK:
91            self.pointer.setAnalogEvent(EVT_PAN)
92        elif self.puckId in ZOOM_PUCK:
93            self.pointer.setAnalogEvent(EVT_ZOOM)
94        elif self.puckId in ROTATE_PUCK:
95            self.pointer.setAnalogEvent(EVT_ROTATE)
96           
97
98    def onMessage(self, data, firstMsg=False):
99        tokens = data.split()
100        puckId =   int(tokens[1].strip())
101        x =      float(tokens[2].strip())
102        y =      float(tokens[3].strip())
103        angle =  float(tokens[4].strip())+90
104        puckType = int(tokens[5].strip())
105
106        # always convert to SAGE coords first
107        x = int(round(float(x) * self.displayBounds.getWidth()))
108        y = int(round(float(y) * self.displayBounds.getHeight()))
109
110        ## # if in local mode, convert to local coords based on bounds
111##         if not self.globalMode:
112##             x = float(x - self.bounds.left) / self.bounds.getWidth()
113##             y = float(y - self.bounds.bottom) / self.bounds.getHeight()
114
115        # set the correct state for the first msg
116        ## if firstMsg:
117##             self.x = x
118##             self.y = y
119##             self.angle = angle
120##             self.puckType = puckType
121##             if self.pointer:
122##                 self.pointer.movePointer(self.x, self.y)
123##                 self.pointer.pointerAngle(int(self.angle))
124##             return
125
126
127        # click
128        if (self.puckType != puckType) and (self.puckId not in SPECIAL_PUCK):
129            self.clickX, self.clickY = x, y
130            self.prevDy = self.prevDx = 0
131            self.puckType = puckType
132            forEvt = 0
133            if self.puckId in PAN_PUCK or self.dragMode: 
134                forEvt = 31000+EVT_PAN
135            elif self.puckId in ROTATE_PUCK:
136                forEvt = 31000+EVT_ROTATE
137            elif self.puckId in ZOOM_PUCK:
138                forEvt = 31000+EVT_ZOOM
139               
140            self.postEvtClick(x, y, 1, puckType==DOWN, forEvt)  # if puckType=2, isDown=True
141       
142       
143        # move
144        dx = dy = 0
145        if self.x != x or self.y != y:
146            dx = x - self.x ;  self.x = x
147            dy = y - self.y ;  self.y = y
148
149            if puckType == UP:    # no buttons pressed
150                self.postEvtMove(self.x, self.y, dx, dy)
151
152            elif puckType == DOWN:  # button pressed means different things depending on the puck
153                if self.puckId in PAN_PUCK or self.dragMode: 
154                    self.postEvtAnalog1(self.clickX, self.clickY, dx, dy, 0)
155                elif self.puckId in ROTATE_PUCK:
156                    self.postEvtAnalog2(self.clickX, self.clickY, dx, dy, 0)
157                elif self.puckId in ZOOM_PUCK:
158                    dx = self.x - self.clickX  # accumulated dx,dy from the click pos
159                    dy = self.y - self.clickY
160                    dx, dy = self.__rotatePoints(dx, dy)
161                    self.postEvtAnalog3(self.clickX, self.clickY, dx-self.prevDx, dy-self.prevDy, 0)
162                    self.prevDx = dx
163                    self.prevDy = dy
164                   
165                   
166            # move the pointer
167            if self.pointer: self.pointer.movePointer(self.x, self.y)       
168
169
170        # rotation
171        if self.angle != angle:
172            da = angle - self.angle
173            self.angle = angle
174            if da < -300:    # we went over the zero degree line counterclockwise, a hack
175                da = 360 + da
176            elif da > 300:   # we went over the zero degree line clockwise, a hack
177                da = (360 - da)*(-1)
178
179            if self.pointer: self.pointer.pointerAngle(int(self.angle))
180
181            # convert to normalized angle
182            da = (da/360.0)
183
184            # send the events based on which puck this is
185            #if self.puckId in ROTATE_PUCK and self.puckType == 2:
186            #    self.postEvtAnalog2(self.x, self.y, 0, 0, da)
187            #elif self.puckId in ZOOM_PUCK:
188            #    self.postEvtAnalog3(self.x, self.y, da, da, da)
189
190
191    def __rotatePoints(self, x, y):
192        """ rotate a point around origin... used for making
193            rotation events orientation independent """
194        a = -radians(self.angle)
195        newX = x*cos(a) - y*sin(a)
196        newY = x*sin(a) + y*cos(a)
197        return newX, newY
198   
Note: See TracBrowser for help on using the repository browser.