Browse Source

Changes to reflect new specification of modifiers for mouse/kb events
Update to use new ka option of directdserver
Fix to joybox code

Mark Mine 23 years ago
parent
commit
03ec124072

+ 8 - 3
direct/src/cluster/ClusterClient.py

@@ -26,14 +26,19 @@ class ClusterClient(DirectObject.DirectObject):
         self.daemon.listenTo(clusterDaemonPort)
         # Contact server daemons and start up remote server application
         for serverConfig in configList:
+            # First kill existing application
+            self.daemon.tellServer(serverConfig.serverName,
+                                   clusterDaemonPort,
+                                   'ka')
+            # Now start up new application
             serverCommand = (SERVER_STARTUP_STRING %
                              (serverConfig.serverPort,
                               clusterSyncFlag,
                               clusterDaemonClient,
                               clusterDaemonPort))
-            self.daemon.clientReady(serverConfig.serverName,
-                                    clusterDaemonPort,
-                                    serverCommand)
+            self.daemon.tellServer(serverConfig.serverName,
+                                   clusterDaemonPort,
+                                   serverCommand)
         if not self.daemon.waitForServers(len(configList)):
             print 'Cluster Client, no response from servers'
         self.qcm=QueuedConnectionManager()

+ 23 - 23
direct/src/cluster/ClusterConfig.py

@@ -39,29 +39,29 @@ ClientConfigs = {
                               'pos' : Vec3(0),
                               'hpr' : Vec3(0)}
                              ],
-    'cavetestsmall'   : [{'display name' : 'la',
-                          'pos' : Vec3(-0.105, -0.020, 5.000),
-                          'hpr' : Vec3(51.213, 0.000, 0.000),
-                          'focal length' : 0.809,
-                          'film size' : (1.000, 0.831),
-                          'film offset' : (0.000, 0.173),
-                          },
-                         {'display name' : 'lb',
-                          'display mode' : 'client',
-                          'pos' : Vec3(-0.105, -0.020, 5.000),
-                          'hpr' : Vec3(-0.370, 0.000, 0.000),
-                          'focal length' : 0.815,
-                          'film size' : (1.000, 0.831),
-                          'film offset' : (0.000, 0.173),
-                          },
-                         {'display name' : 'lc',
-                          'pos' : Vec3(-0.105, -0.020, 5.000),
-                          'hpr' : Vec3(-51.675, 0.000, 0.000),
-                          'focal length' : 0.820,
-                          'film size' : (1.000, 0.830),
-                          'film offset' : (-0.000, 0.173),
-                          },
-                         ],
+    'cavetest3'   : [{'display name' : 'la',
+                      'pos' : Vec3(-0.105, -0.020, 5.000),
+                      'hpr' : Vec3(51.213, 0.000, 0.000),
+                      'focal length' : 0.809,
+                      'film size' : (1.000, 0.831),
+                      'film offset' : (0.000, 0.173),
+                      },
+                     {'display name' : 'lb',
+                      'display mode' : 'client',
+                      'pos' : Vec3(-0.105, -0.020, 5.000),
+                      'hpr' : Vec3(-0.370, 0.000, 0.000),
+                      'focal length' : 0.815,
+                      'film size' : (1.000, 0.831),
+                      'film offset' : (0.000, 0.173),
+                      },
+                     {'display name' : 'lc',
+                      'pos' : Vec3(-0.105, -0.020, 5.000),
+                      'hpr' : Vec3(-51.675, 0.000, 0.000),
+                      'focal length' : 0.820,
+                      'film size' : (1.000, 0.830),
+                      'film offset' : (-0.000, 0.173),
+                      },
+                     ],
     'cavetest'        : [{'display name' : 'la',
                           'pos' : Vec3(-0.105, -0.020, 5.000),
                           'hpr' : Vec3(51.213, 0.000, 0.000),

+ 2 - 1
direct/src/cluster/ClusterMsgs.py

@@ -22,8 +22,9 @@ CLUSTER_EXIT = 100
 CLUSTER_SERVER_PORT = 1970
 CLUSTER_DAEMON_PORT = 8001
 
+# Precede command string with ! to tell server to execute command string
 SERVER_STARTUP_STRING = (
-    'bash ppython -c ' + 
+    '!bash ppython -c ' + 
     '"import __builtin__; ' +
     '__builtin__.clusterServerPort = %s;' +
     '__builtin__.clusterSyncFlag = %d;' +

+ 5 - 5
direct/src/directdevices/DirectDeviceManager.py

@@ -93,13 +93,13 @@ class DirectAnalogs(AnalogNode, DirectObject):
         self.nodePath = myBase.dataRoot.attachNewNode(self)
         # See if any of the general analog parameters are dconfig'd
         self.analogDeadband = myBase.config.GetFloat('vrpn-analog-deadband',
-                                                       ANALOG_DEADBAND)
+                                                     ANALOG_DEADBAND)
         self.analogMin = myBase.config.GetFloat('vrpn-analog-min',
-                                                  ANALOG_MIN)
+                                                ANALOG_MIN)
         self.analogMax = myBase.config.GetFloat('vrpn-analog-max',
-                                                  ANALOG_MAX)
-        self.analogMax = myBase.config.GetFloat('vrpn-analog-center',
-                                                  ANALOG_CENTER)
+                                                ANALOG_MAX)
+        self.analogCenter = myBase.config.GetFloat('vrpn-analog-center',
+                                                   ANALOG_CENTER)
         self.analogRange = self.analogMax - self.analogMin
 
     

+ 10 - 15
direct/src/directdevices/DirectJoybox.py

@@ -1,7 +1,7 @@
 """ Class used to create and control joybox device """
 from PandaObject import *
 from DirectDeviceManager import *
-from DirectGeometry import *
+from DirectUtil import *
 import OnscreenText
 
 """
@@ -162,8 +162,7 @@ class DirectJoybox(PandaObject):
             else:
                 val = max(val - ANALOG_DEADBAND, 0.0)
             # Scale up rotating knob values
-            if (chan == 2) or (chan == 6):
-                print "got twist in unrolled!"
+            if (chan == L_TWIST) or (chan == R_TWIST):
                 val *= 3.0
             # Now clamp value between minVal and maxVal
             val = CLAMP(val, JOYBOX_MIN, JOYBOX_MAX)
@@ -219,14 +218,10 @@ class DirectJoybox(PandaObject):
         # Do nothing if no nodePath selected
         if self.nodePath == None:
             return
-        """
-        hprScale = (self.normalizeChannel(L_SLIDE, 0.1, 100) *
-                    DirectJoybox.hprMultiplier)
-        posScale = (self.normalizeChannel(R_SLIDE, 0.1, 100) *
-                    DirectJoybox.xyzMultiplier)
-        """
-        hprScale = (self.aList[L_SLIDE] + 1.0) * 50.0 * DirectJoybox.hprMultiplier
-        posScale = (self.aList[R_SLIDE] + 1.0) * 50.0 * DirectJoybox.xyzMultiplier
+        hprScale = ((self.aList[L_SLIDE] + 1.0) *
+                    50.0 * DirectJoybox.hprMultiplier)
+        posScale = ((self.aList[R_SLIDE] + 1.0) *
+                    50.0 * DirectJoybox.xyzMultiplier)
         def getAxisVal(index, s = self):
             try:
                 return s.aList[s.mapping[index]]
@@ -412,12 +407,12 @@ class DirectJoybox(PandaObject):
     def normalizeChannel(self, chan, minVal = -1, maxVal = 1):
         try:
             if (chan == L_TWIST) or (chan == R_TWIST):
-                print "in Joybox normalize channel: got *_TWIST!"
                 # These channels have reduced range
-                return self.analogs.normalize(self.analogs.getControlState(chan) * 3.0, minVal, maxVal)
+                return self.analogs.normalize(
+                    self.analogs.getControlState(chan) * 3.0, minVal, maxVal)
             else:
-                print "in Joybox normalize channel..."
-                return self.analogs.normalize(self.analogs.getControlState(chan), minVal, maxVal)
+                return self.analogs.normalize(
+                    self.analogs.getControlState(chan), minVal, maxVal)
         except IndexError:
             return 0.0
 

+ 5 - 4
direct/src/directtools/DirectCameraControl.py

@@ -1,4 +1,5 @@
 from PandaObject import *
+from DirectUtil import *
 from DirectGeometry import *
 
 CAM_MOVE_DURATION = 1.2
@@ -16,7 +17,7 @@ class DirectCameraControl(PandaObject):
         self.coaMarker = loader.loadModel('models/misc/sphere')
         self.coaMarker.setName('DirectCameraCOAMarker')
         self.coaMarker.setTransparency(1)
-        self.coaMarker.setColor(1,0,0)
+        self.coaMarker.setColor(1,0,0,0)
         self.coaMarker.setPos(0,100,0)
         useDirectRenderStyle(self.coaMarker)
         self.coaMarkerPos = Point3(0)
@@ -27,8 +28,8 @@ class DirectCameraControl(PandaObject):
         self.camManipRef = direct.group.attachNewNode('camManipRef')
         t = CAM_MOVE_DURATION
         self.actionEvents = [
-            ['DIRECT_mouse2', self.mouseFlyStart],
-            ['DIRECT_mouse2Up', self.mouseFlyStop],
+            ['DIRECT-mouse2', self.mouseFlyStart],
+            ['DIRECT-mouse2Up', self.mouseFlyStop],
             ['c', self.centerCamIn, 0.5],
             ['f', self.fitOnWidget],
             ['h', self.homeCam],
@@ -60,7 +61,7 @@ class DirectCameraControl(PandaObject):
         else:
             direct.cameraControl.coaMarker.hide()
 
-    def mouseFlyStart(self):
+    def mouseFlyStart(self, modifiers):
         # Record undo point
         direct.pushUndo([direct.camera])
         # Where are we in the display region?

+ 56 - 27
direct/src/directtools/DirectGeometry.py

@@ -1,17 +1,9 @@
 from PandaModules import *
 from PandaObject import *
+from DirectGlobals import *
+from DirectUtil import *
 import math
 
-X_AXIS = Vec3(1,0,0)
-Y_AXIS = Vec3(0,1,0)
-Z_AXIS = Vec3(0,0,1)
-NEG_X_AXIS = Vec3(-1,0,0)
-NEG_Y_AXIS = Vec3(0,-1,0)
-NEG_Z_AXIS = Vec3(0,0,-1)
-ZERO_VEC = ORIGIN = Vec3(0)
-UNIT_VEC = Vec3(1)
-ZERO_POINT = Point3(0)
-
 class LineNodePath(NodePath):
     def __init__(self, parent = None, name = None,
                  thickness = 1.0, colorVec = VBase4(1)):
@@ -141,18 +133,6 @@ def planeIntersect (lineOrigin, lineDir, planeOrigin, normal):
     hitPt = lineDir * t
     return hitPt + lineOrigin
 
-def ROUND_TO(value, divisor):
-    return round(value/float(divisor)) * divisor
-def ROUND_INT(val):
-    return int(round(val))
-def CLAMP(val, min, max):
-    if val < min:
-        return min
-    elif val > max:
-        return max
-    else:
-        return val
-
 def getNearProjectionPoint(nodePath):
     # Find the position of the projection of the specified node path
     # on the near plane
@@ -207,8 +187,57 @@ def relHpr(nodePath, base, h, p, r):
                     CSDefault)
     nodePath.setHpr(hpr)
 
-# Set direct drawing style for an object
-# Never light object or draw in wireframe
-def useDirectRenderStyle(nodePath):
-    nodePath.node().setAttrib(LightAttrib.makeAllOff())
-    nodePath.setRenderModeFilled()
+# Quaternion interpolation
+def qSlerp(startQuat, endQuat, t):
+    startQ = Quat(startQuat)
+    destQuat = Quat.identQuat()
+    # Calc dot product
+    cosOmega = (startQ.getI() * endQuat.getI() +
+                startQ.getJ() * endQuat.getJ() + 
+                startQ.getK() * endQuat.getK() +
+                startQ.getR() * endQuat.getR())
+    # If the above dot product is negative, it would be better to
+    # go between the negative of the initial and the final, so that
+    # we take the shorter path.  
+    if ( cosOmega < 0.0 ):
+        cosOmega *= -1
+        startQ.setI(-1 * startQ.getI())
+        startQ.setJ(-1 * startQ.getJ())
+        startQ.setK(-1 * startQ.getK())
+        startQ.setR(-1 * startQ.getR())
+    if ((1.0 + cosOmega) > Q_EPSILON):
+        # usual case
+        if ((1.0 - cosOmega) > Q_EPSILON):
+            # usual case
+            omega = math.acos(cosOmega)
+            sinOmega = math.sin(omega)
+            startScale = math.sin((1.0 - t) * omega)/sinOmega
+            endScale = math.sin(t * omega)/sinOmega
+        else:
+            # ends very close 
+            startScale = 1.0 - t
+            endScale = t
+        destQuat.setI(startScale * startQ.getI() +
+                      endScale * endQuat.getI())
+        destQuat.setJ(startScale * startQ.getJ() +
+                      endScale * endQuat.getJ())
+        destQuat.setK(startScale * startQ.getK() +
+                      endScale * endQuat.getK())
+        destQuat.setR(startScale * startQ.getR() +
+                      endScale * endQuat.getR())
+    else:
+        # ends nearly opposite
+        destQuat.setI(-startQ.getJ())
+        destQuat.setJ(startQ.getI())
+        destQuat.setK(-startQ.getR())
+        destQuat.setR(startQ.getK())
+        startScale = math.sin((0.5 - t) * math.pi)
+        endScale = math.sin(t * math.pi)
+        destQuat.setI(startScale * startQ.getI() +
+                      endScale * endQuat.getI())
+        destQuat.setJ(startScale * startQ.getJ() +
+                      endScale * endQuat.getJ())
+        destQuat.setK(startScale * startQ.getK() +
+                      endScale * endQuat.getK())
+    return destQuat
+

+ 1 - 0
direct/src/directtools/DirectGrid.py

@@ -1,4 +1,5 @@
 from PandaObject import *
+from DirectUtil import *
 from DirectGeometry import *
 
 class DirectGrid(NodePath,PandaObject):

+ 0 - 1
direct/src/directtools/DirectLights.py

@@ -1,5 +1,4 @@
 from PandaObject import *
-from DirectGeometry import *
 from string import lower
 
 class DirectLight(NodePath):

+ 5 - 6
direct/src/directtools/DirectManipulation.py

@@ -1,8 +1,8 @@
 from PandaObject import *
+from DirectGlobals import *
+from DirectUtil import *
 from DirectGeometry import *
 
-MANIPULATION_MOVE_DELAY = 0.65
-
 class DirectManipulationControl(PandaObject):
     def __init__(self):
         # Create the grid
@@ -24,8 +24,8 @@ class DirectManipulationControl(PandaObject):
         self.fScaling = 0
         self.mode = None
         self.actionEvents = [
-            ['DIRECT_mouse1', self.manipulationStart],
-            ['DIRECT_mouse1Up', self.manipulationStop],
+            ['DIRECT-mouse1', self.manipulationStart],
+            ['DIRECT-mouse1Up', self.manipulationStop],
             ['tab', self.toggleObjectHandlesMode],
             ['.', self.objectHandles.multiplyScalingFactorBy, 2.0],
             ['>', self.objectHandles.multiplyScalingFactorBy, 2.0],
@@ -35,12 +35,11 @@ class DirectManipulationControl(PandaObject):
             ['i', self.plantSelectedNodePath],
             ]
 
-    def manipulationStart(self):
+    def manipulationStart(self, modifiers):
         # Start out in select mode
         self.mode = 'select'
         # Check for a widget hit point
         node, hitPt, hitPtDist = direct.iRay.pickWidget()
-        print node, hitPt, hitPtDist
         # Did we hit a widget?
         if node:
             # Yes!

+ 2 - 3
direct/src/directtools/DirectSelection.py

@@ -1,11 +1,10 @@
 from PandaObject import *
+from DirectGlobals import *
+from DirectUtil import *
 from DirectGeometry import *
 from DirectSelection import *
 import __builtin__
 
-UNPICKABLE = ['x-disc-visible', 'y-disc-visible', 'z-disc-visible',
-              'gridBack', 'unpickable']
-
 # MRM: To do: handle broken node paths in selected and deselected dicts
 class DirectNodePath(NodePath):
     # A node path augmented with info, bounding box, and utility methods

+ 54 - 26
direct/src/directtools/DirectSession.py

@@ -1,4 +1,5 @@
 from PandaObject import *
+from DirectGlobals import *
 from DirectUtil import*
 from DirectCameraControl import *
 from DirectManipulation import *
@@ -18,8 +19,6 @@ import types
 import string
 import __builtin__
 
-DIRECT_FLASH_DURATION = 1.5
-
 class DirectSession(PandaObject):
 
     def __init__(self):
@@ -156,11 +155,19 @@ class DirectSession(PandaObject):
                           '[', '{', ']', '}',
                           'shift-a', 'b', 'l', 'shift-l', 'o', 'p', 'r',
                           'shift-r', 's', 't', 'v', 'w']
-        self.mouseEvents = ['mouse1', 'shift-mouse1', 'control-mouse1',
-                            'alt-mouse1', 'mouse1-up',
-                            'mouse2', 'shift-mouse2', 'control-mouse2',
-                            'alt-mouse2', 'mouse2-up',
-                            'mouse3', 'mouse3-up']
+        self.mouseEvents = ['mouse1', 'mouse1-up',
+                            'shift-mouse1', 'shift-mouse1-up',
+                            'control-mouse1', 'control-mouse1-up',
+                            'alt-mouse1', 'alt-mouse1-up',
+                            'mouse2', 'mouse2-up',
+                            'shift-mouse2', 'shift-mouse2-up',
+                            'control-mouse2', 'control-mouse2-up',
+                            'alt-mouse2', 'alt-mouse2-up',
+                            'mouse3', 'mouse3-up',
+                            'shift-mouse3', 'shift-mouse3-up',
+                            'control-mouse3', 'control-mouse3-up',
+                            'alt-mouse3', 'alt-mouse3-up',
+                            ]
 
         if base.wantTk:
             import TkGlobal
@@ -321,20 +328,21 @@ class DirectSession(PandaObject):
 
     def inputHandler(self, input):
         # Deal with keyboard and mouse input
-        if ((input == 'mouse1') or (input == 'shift-mouse1') or
-            (input == 'control-mouse1') or (input == 'alt-mouse1')):
-            messenger.send('DIRECT_mouse1')
-        elif input == 'mouse1-up':
-            messenger.send('DIRECT_mouse1Up')
-        elif ((input == 'mouse2') or (input == 'shift-mouse2') or
-              (input == 'control-mouse2') or (input == 'alt-mouse2')): 
-            messenger.send('DIRECT_mouse2')
+        if input == 'mouse1-up':
+            messenger.send('DIRECT-mouse1Up')
+        elif input.find('mouse1') != -1:
+            modifiers = self.getModifiers(input, 'mouse1')
+            messenger.send('DIRECT-mouse1', sentArgs = [modifiers])
         elif input == 'mouse2-up':
-            messenger.send('DIRECT_mouse2Up')
-        elif input == 'mouse3': 
-            messenger.send('DIRECT_mouse3')
+            messenger.send('DIRECT-mouse2Up')
+        elif input.find('mouse2') != -1:
+            modifiers = self.getModifiers(input, 'mouse2')
+            messenger.send('DIRECT-mouse2', sentArgs = [modifiers])
         elif input == 'mouse3-up':
-            messenger.send('DIRECT_mouse3Up')
+            messenger.send('DIRECT-mouse3Up')
+        elif input.find('mouse3') != -1:
+            modifiers = self.getModifiers(input, 'mouse3')
+            messenger.send('DIRECT-mouse3', sentArgs = [modifiers])
         elif input == 'shift':
             self.fShift = 1
         elif input == 'shift-up':
@@ -396,6 +404,26 @@ class DirectSession(PandaObject):
                          'shift-a', 'w'):
                 self.cluster.cmd('messenger.send("%s")' % input,0)
         
+    def getModifiers(self, input, base):
+        modifiers = DIRECT_NO_MOD
+        modifierString = input[: input.find(base)]
+        if modifierString.find('shift') != -1:
+            modifiers |= DIRECT_SHIFT_MOD
+        if modifierString.find('control') != -1:
+            modifiers |= DIRECT_CONTROL_MOD
+        if modifierString.find('alt') != -1:
+            modifiers |= DIRECT_ALT_MOD
+        return modifiers
+
+    def gotShift(self, modifiers):
+        return modifiers & DIRECT_SHIFT_MOD
+
+    def gotControl(self, modifiers):
+        return modifiers & DIRECT_CONTROL_MOD
+
+    def gotAlt(self, modifiers):
+        return modifiers & DIRECT_ALT_MOD
+
     def select(self, nodePath, fMultiSelect = 0, fResetAncestry = 1):
         dnp = self.selected.select(nodePath, fMultiSelect)
         if dnp:
@@ -761,12 +789,12 @@ class DisplayRegionList(PandaObject):
                     self.displayRegionLookup[camera.getName()]=i
                     i = i + 1
         self.accept("CamChange",self.camUpdate)
-        self.accept("DIRECT_mouse1",self.mouseUpdate)
-        self.accept("DIRECT_mouse2",self.mouseUpdate)
-        self.accept("DIRECT_mouse3",self.mouseUpdate)
-        self.accept("DIRECT_mouse1Up",self.mouseUpdate)
-        self.accept("DIRECT_mouse2Up",self.mouseUpdate)
-        self.accept("DIRECT_mouse3Up",self.mouseUpdate)
+        self.accept("DIRECT-mouse1",self.mouseUpdate)
+        self.accept("DIRECT-mouse2",self.mouseUpdate)
+        self.accept("DIRECT-mouse3",self.mouseUpdate)
+        self.accept("DIRECT-mouse1Up",self.mouseUpdate)
+        self.accept("DIRECT-mouse2Up",self.mouseUpdate)
+        self.accept("DIRECT-mouse3Up",self.mouseUpdate)
 
         #setting up array of camera nodes
         cameraList = []
@@ -813,7 +841,7 @@ class DisplayRegionList(PandaObject):
             for dr in self.displayRegionList:
                 dr.camUpdate()
 
-    def mouseUpdate(self):
+    def mouseUpdate(self, modifiers = DIRECT_NO_MOD):
         for dr in self.displayRegionList:
             dr.mouseUpdate()
         direct.dr = self.getCurrentDr()

+ 38 - 65
direct/src/directtools/DirectUtil.py

@@ -1,23 +1,42 @@
 from PandaObject import *
+from DirectGlobals import *
+
+# Routines to adjust values
+def ROUND_TO(value, divisor):
+    return round(value/float(divisor)) * divisor
+
+def ROUND_INT(val):
+    return int(round(val))
+
+def CLAMP(val, min, max):
+    if val < min:
+        return min
+    elif val > max:
+        return max
+    else:
+        return val
 
 # Create a tk compatible color string
 def getTkColorString(color):
-        def toHex(intVal):
-            val = int(round(intVal))
-            if val < 16:
-                return "0" + hex(val)[2:]
-            else:
-                return hex(val)[2:]
-        r = toHex(color[0])
-        g = toHex(color[1])
-        b = toHex(color[2])
-        return "#" + r + g + b
+    """ Print out a Tk compatible version of a color string """
+    def toHex(intVal):
+        val = int(round(intVal))
+        if val < 16:
+            return "0" + hex(val)[2:]
+        else:
+            return hex(val)[2:]
+    r = toHex(color[0])
+    g = toHex(color[1])
+    b = toHex(color[2])
+    return "#" + r + g + b
 
 ## Background Color ##
 def setBackgroundColor(r,g,b):
+    """ Wrapper function to set background color """
     base.win.getGsg().setColorClearValue(VBase4(r, g, b, 1.0))
 
 def lerpBackgroundColor(r,g,b,duration):
+    """ Function to lerp background color to a new value """
     def lerpColor(state):
         dt = globalClock.getDt()
         state.time += dt
@@ -38,61 +57,15 @@ def lerpBackgroundColor(r,g,b,duration):
     t.sc = base.win.getGsg().getColorClearValue()
     t.ec = VBase4(r,g,b,1)
 
-Q_EPSILON = 1e-10
-
-# Quaternion interpolation
-def qSlerp(startQuat, endQuat, t):
-    startQ = Quat(startQuat)
-    destQuat = Quat.identQuat()
-    # Calc dot product
-    cosOmega = (startQ.getI() * endQuat.getI() +
-                startQ.getJ() * endQuat.getJ() + 
-                startQ.getK() * endQuat.getK() +
-                startQ.getR() * endQuat.getR())
-    # If the above dot product is negative, it would be better to
-    # go between the negative of the initial and the final, so that
-    # we take the shorter path.  
-    if ( cosOmega < 0.0 ):
-        cosOmega *= -1
-        startQ.setI(-1 * startQ.getI())
-        startQ.setJ(-1 * startQ.getJ())
-        startQ.setK(-1 * startQ.getK())
-        startQ.setR(-1 * startQ.getR())
-    if ((1.0 + cosOmega) > Q_EPSILON):
-        # usual case
-        if ((1.0 - cosOmega) > Q_EPSILON):
-            # usual case
-            omega = math.acos(cosOmega)
-            sinOmega = math.sin(omega)
-            startScale = math.sin((1.0 - t) * omega)/sinOmega
-            endScale = math.sin(t * omega)/sinOmega
-        else:
-            # ends very close 
-            startScale = 1.0 - t
-            endScale = t
-        destQuat.setI(startScale * startQ.getI() +
-                      endScale * endQuat.getI())
-        destQuat.setJ(startScale * startQ.getJ() +
-                      endScale * endQuat.getJ())
-        destQuat.setK(startScale * startQ.getK() +
-                      endScale * endQuat.getK())
-        destQuat.setR(startScale * startQ.getR() +
-                      endScale * endQuat.getR())
-    else:
-        # ends nearly opposite
-        destQuat.setI(-startQ.getJ())
-        destQuat.setJ(startQ.getI())
-        destQuat.setK(-startQ.getR())
-        destQuat.setR(startQ.getK())
-        startScale = math.sin((0.5 - t) * math.pi)
-        endScale = math.sin(t * math.pi)
-        destQuat.setI(startScale * startQ.getI() +
-                      endScale * endQuat.getI())
-        destQuat.setJ(startScale * startQ.getJ() +
-                      endScale * endQuat.getJ())
-        destQuat.setK(startScale * startQ.getK() +
-                      endScale * endQuat.getK())
-    return destQuat
+# Set direct drawing style for an object
+# Never light object or draw in wireframe
+def useDirectRenderStyle(nodePath):
+    """
+    Function to force a node path to use direct render style:
+    no lighting, and no wireframe
+    """
+    nodePath.node().setAttrib(LightAttrib.makeAllOff())
+    nodePath.setRenderModeFilled()
 
 # File data util
 def getFileData(filename, separator = ','):

+ 1 - 1
direct/src/gui/DirectGuiBase.py

@@ -1,5 +1,5 @@
 from DirectGuiGlobals import *
-from DirectGeometry import ROUND_TO
+from DirectUtil import ROUND_TO
 import PandaObject
 import Task
 import string

+ 39 - 40
direct/src/leveleditor/LevelEditor.py

@@ -3,6 +3,7 @@ from PandaObject import *
 from PieMenu import *
 from DirectGuiGlobals import *
 from Tkinter import *
+from DirectUtil import *
 from DirectGeometry import *
 from SceneGraphExplorer import *
 from tkMessageBox import showinfo
@@ -494,10 +495,14 @@ class LevelEditor(NodePath, PandaObject):
             # Hot key actions
             ('a', self.autoPositionGrid),
             ('j', self.jumpToInsertionPoint),
-            ('left', self.keyboardXformSelected, ['left']),
-            ('right', self.keyboardXformSelected, ['right']),
-            ('up', self.keyboardXformSelected, ['up']),
-            ('down', self.keyboardXformSelected, ['down']),
+            ('left', self.keyboardXformSelected, ['left', 'xlate']),
+            ('right', self.keyboardXformSelected, ['right', 'xlate']),
+            ('up', self.keyboardXformSelected, ['up','xlate']),
+            ('down', self.keyboardXformSelected, ['down','xlate']),
+            ('control-left', self.keyboardXformSelected, ['left', 'rotate']),
+            ('control-right', self.keyboardXformSelected, ['right', 'rotate']),
+            ('control-up', self.keyboardXformSelected, ['up', 'rotate']),
+            ('control-down', self.keyboardXformSelected, ['down', 'rotate']),
             ('shift-s', self.placeSuitPoint),
             ('shift-c', self.placeBattleCell),
             ('o', self.addToLandmarkBlock),
@@ -967,14 +972,14 @@ class LevelEditor(NodePath, PandaObject):
         # Turn off player camera control
         base.disableMouse()
         # Handle mouse events for pie menus
-        self.accept('DIRECT_mouse3',self.levelHandleMouse3)
-        self.accept('DIRECT_mouse3Up',self.levelHandleMouse3Up)
+        self.accept('DIRECT-mouse3',self.levelHandleMouse3)
+        self.accept('DIRECT-mouse3Up',self.levelHandleMouse3Up)
 
     def disableMouse(self):
         """ Disable Pie Menu interaction """
         # Disable handling of mouse events
-        self.ignore('DIRECT_mouse3')
-        self.ignore('DIRECT_mouse3Up')
+        self.ignore('DIRECT-mouse3')
+        self.ignore('DIRECT-mouse3Up')
 
     # LEVEL OBJECT MANAGEMENT FUNCTIONS
     def findDNANode(self, nodePath):
@@ -1571,7 +1576,7 @@ class LevelEditor(NodePath, PandaObject):
         DNARemoveChildOfClass(parent, DNA_WINDOWS)
 
     # LEVEL-OBJECT MODIFICATION FUNCTIONS
-    def levelHandleMouse3(self):
+    def levelHandleMouse3(self, modifiers):
         # Initialize dna target
         self.DNATarget = None
         
@@ -1588,7 +1593,7 @@ class LevelEditor(NodePath, PandaObject):
         # Pick a menu based upon object type
         if DNAClassEqual(dnaObject, DNA_FLAT_BUILDING):
             # FLAT BUILDING OPERATIONS
-            menuMode, wallNum = self.getFlatBuildingMode(dnaObject)
+            menuMode, wallNum = self.getFlatBuildingMode(dnaObject, modifiers)
             # Check menuMode
             if menuMode == None:
                 return
@@ -1614,11 +1619,11 @@ class LevelEditor(NodePath, PandaObject):
         elif DNAClassEqual(dnaObject, DNA_PROP):
             # PROP OPERATIONS
             self.DNATarget = dnaObject
-            if direct.fControl:
+            if direct.gotControl(modifiers):
                 menuMode = 'prop_color'
-            elif direct.fAlt and self.panel.currentBaselineDNA:
+            elif direct.gotAlt(modifiers) and self.panel.currentBaselineDNA:
                 menuMode = 'baseline_style'
-            elif direct.fShift:
+            elif direct.gotShift(modifiers):
                 menuMode = 'sign_texture'
                 self.DNATarget = DNAGetChildOfClass(dnaObject, DNA_SIGN)
                 self.DNATargetParent = dnaObject
@@ -1627,7 +1632,7 @@ class LevelEditor(NodePath, PandaObject):
         elif DNAClassEqual(dnaObject, DNA_LANDMARK_BUILDING):
             # INSERT HERE
             # LANDMARK BUILDING OPERATIONS
-            menuMode = self.getLandmarkBuildingMode(dnaObject)
+            menuMode = self.getLandmarkBuildingMode(dnaObject, modifiers)
             if string.find(menuMode, 'door') >= 0:
                 self.DNATarget = DNAGetChildOfClass(dnaObject, DNA_DOOR)
                 self.DNATargetParent = dnaObject
@@ -1677,41 +1682,36 @@ class LevelEditor(NodePath, PandaObject):
         # Spawn active menu's task
         self.activeMenu.spawnPieMenuTask()
 
-    def getLandmarkBuildingMode(self, dnaObject):
+    def getLandmarkBuildingMode(self, dnaObject, modifiers):
         # Where are we hitting the building?
         hitPt = self.getWallIntersectionPoint(self.selectedNPRoot)
         if hitPt[2] < 10.0:
             # Do door operations
-            if direct.fControl:
+            if direct.gotControl(modifiers):
                 menuMode = 'door_color'
-            elif direct.fAlt:
+            elif direct.gotAlt(modifiers):
                 menuMode = 'door_orientation'
             else:
                 menuMode = 'door_texture'
         else:
             # Do sign operations
-            if direct.fControl:
+            if direct.gotControl(modifiers):
                 menuMode = 'sign_color'
-            elif direct.fAlt and self.panel.currentBaselineDNA:
+            elif direct.gotAlt(modifiers) and self.panel.currentBaselineDNA:
                 menuMode = 'baseline_style'
-            elif direct.fAlt:
+            elif direct.gotAlt(modifiers):
                 menuMode = 'sign_orientation'
             else:
                 menuMode = 'sign_texture'
         return menuMode
 
-    def getFlatBuildingMode(self, dnaObject):
+    def getFlatBuildingMode(self, dnaObject, modifiers):
         # Where are we hitting the building?
         hitPt = self.getWallIntersectionPoint(self.selectedNPRoot)
         wallNum = self.computeWallNum(dnaObject, hitPt)
         if wallNum < 0:
             # Do building related operations
-            """
-            if direct.fShift:
-                menuMode = 'building_type'
-            elif direct.fAlt:
-            """
-            if direct.fAlt:
+            if direct.gotAlt(modifiers):
                 menuMode = 'building_width'
             else:
                 menuMode = 'building_style_all'
@@ -1729,37 +1729,37 @@ class LevelEditor(NodePath, PandaObject):
             # Determine which zone you are pointing at
             if (zPt > 0.8):
                 # Do cornice operations
-                if direct.fControl:
+                if direct.gotControl(modifiers):
                     menuMode = 'cornice_color'
-                elif direct.fAlt:
+                elif direct.gotAlt(modifiers):
                     menuMode = 'cornice_orientation'
                 else:
                     menuMode = 'cornice_texture'
             elif ((xPt < 0.3) or (xPt > 0.7)):
                 # Do wall operations
-                if direct.fControl:
+                if direct.gotControl(modifiers):
                     menuMode = 'wall_color'
-                elif direct.fAlt:
+                elif direct.gotAlt(modifiers):
                     menuMode = 'wall_orientation'
-                elif direct.fShift:
+                elif direct.gotShift(modifiers):
                     menuMode = 'wall_texture'
                 else:
                     menuMode = 'wall_style'
             elif (zPt < 0.4):
                 # Do door operations
-                if direct.fControl:
+                if direct.gotControl(modifiers):
                     menuMode = 'door_color'
-                elif direct.fAlt:
+                elif direct.gotAlt(modifiers):
                     menuMode = 'door_orientation'
                 else:
                     menuMode = 'door_texture'
             else:
                 # Do window operations
-                if direct.fControl:
+                if direct.gotControl(modifiers):
                     menuMode = 'window_color'
-                elif direct.fAlt:
+                elif direct.gotAlt(modifiers):
                     menuMode = 'window_orientation'
-                elif direct.fShift:
+                elif direct.gotShift(modifiers):
                     menuMode = 'window_count'
                 else:
                     menuMode = 'window_texture'
@@ -2019,7 +2019,6 @@ class LevelEditor(NodePath, PandaObject):
             oldSnapAngle = direct.grid.snapAngle
             direct.grid.setSnapAngle(1.0)
         snapAngle = direct.grid.snapAngle
-        print direct.fShift, snapAngle
         # Compute new angle
         if ((arrowDirection == 'left') or (arrowDirection == 'up')):
             self.setLastAngle(self.getLastAngle() + snapAngle)
@@ -2091,8 +2090,8 @@ class LevelEditor(NodePath, PandaObject):
             # Use back door to set grid spacing to avoid grid update
             direct.grid.gridSpacing = oldGridSpacing
 
-    def keyboardXformSelected(self, arrowDirection):
-        if direct.fControl:
+    def keyboardXformSelected(self, arrowDirection, mode):
+        if mode == 'rotate':
             self.keyboardRotateSelected(arrowDirection)
         else:
             self.keyboardTranslateSelected(arrowDirection)

+ 2 - 1
direct/src/tkpanels/MopathRecorder.py

@@ -4,9 +4,10 @@
 from PandaObject import *
 from Tkinter import *
 from AppShell import *
+from DirectGlobals import *
+from DirectUtil import *
 from DirectGeometry import *
 from DirectSelection import *
-from DirectUtil import *
 from tkFileDialog import *
 import os
 import string

+ 0 - 1
direct/src/tkpanels/Placer.py

@@ -4,7 +4,6 @@
 from PandaObject import *
 from Tkinter import *
 from AppShell import *
-from DirectGeometry import *
 import Pmw
 import Dial
 import Floater