소스 검색

direct: More reduction of reliance on builtins, mypy fixes

rdb 2 년 전
부모
커밋
c00f3b18f5

+ 187 - 166
direct/src/directtools/DirectCameraControl.py

@@ -1,6 +1,7 @@
 import math
 import math
 from panda3d.core import BitMask32, Mat4, NodePath, Point3, VBase3, Vec3, Vec4, rad2Deg
 from panda3d.core import BitMask32, Mat4, NodePath, Point3, VBase3, Vec3, Vec4, rad2Deg
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
+from direct.showbase import ShowBaseGlobal
 from .DirectUtil import CLAMP, useDirectRenderStyle
 from .DirectUtil import CLAMP, useDirectRenderStyle
 from .DirectGeometry import getCrankAngle, getScreenXY
 from .DirectGeometry import getCrankAngle, getScreenXY
 from . import DirectGlobals as DG
 from . import DirectGlobals as DG
@@ -26,7 +27,7 @@ class DirectCameraControl(DirectObject):
         self.orthoViewRoll = 0.0
         self.orthoViewRoll = 0.0
         self.lastView = 0
         self.lastView = 0
         self.coa = Point3(0, 100, 0)
         self.coa = Point3(0, 100, 0)
-        self.coaMarker = base.loader.loadModel('models/misc/sphere')
+        self.coaMarker = ShowBaseGlobal.loader.loadModel('models/misc/sphere')
         self.coaMarker.setName('DirectCameraCOAMarker')
         self.coaMarker.setName('DirectCameraCOAMarker')
         self.coaMarker.setTransparency(1)
         self.coaMarker.setTransparency(1)
         self.coaMarker.setColor(1, 0, 0, 0)
         self.coaMarker.setColor(1, 0, 0, 0)
@@ -37,8 +38,8 @@ class DirectCameraControl(DirectObject):
         self.fLockCOA = 0
         self.fLockCOA = 0
         self.nullHitPointCount = 0
         self.nullHitPointCount = 0
         self.cqEntries = []
         self.cqEntries = []
-        self.coaMarkerRef = base.direct.group.attachNewNode('coaMarkerRef')
-        self.camManipRef = base.direct.group.attachNewNode('camManipRef')
+        self.coaMarkerRef = ShowBaseGlobal.direct.group.attachNewNode('coaMarkerRef')
+        self.camManipRef = ShowBaseGlobal.direct.group.attachNewNode('camManipRef')
         self.switchDirBelowZero = True
         self.switchDirBelowZero = True
         self.manipulateCameraTask = None
         self.manipulateCameraTask = None
         self.manipulateCameraInterval = None
         self.manipulateCameraInterval = None
@@ -112,11 +113,6 @@ class DirectCameraControl(DirectObject):
         self.perspCollPlane2 = None # [gjeon] used for new LE
         self.perspCollPlane2 = None # [gjeon] used for new LE
 
 
     def toggleMarkerVis(self):
     def toggleMarkerVis(self):
-##        if base.direct.cameraControl.coaMarker.isHidden():
-##            base.direct.cameraControl.coaMarker.show()
-##        else:
-##            base.direct.cameraControl.coaMarker.hide()
-
         if self.coaMarker.isHidden():
         if self.coaMarker.isHidden():
             self.coaMarker.show()
             self.coaMarker.show()
         else:
         else:
@@ -132,11 +128,14 @@ class DirectCameraControl(DirectObject):
             # Hide the marker for this kind of motion
             # Hide the marker for this kind of motion
             self.coaMarker.hide()
             self.coaMarker.hide()
             # Record time of start of mouse interaction
             # Record time of start of mouse interaction
+            base = ShowBaseGlobal.base
             self.startT = base.clock.getFrameTime()
             self.startT = base.clock.getFrameTime()
             self.startF = base.clock.getFrameCount()
             self.startF = base.clock.getFrameCount()
             # If the cam is orthogonal, spawn differentTask
             # If the cam is orthogonal, spawn differentTask
-            if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView and\
-               base.direct.camera.getName() != 'persp':
+            direct = ShowBaseGlobal.direct
+            if hasattr(direct, "manipulationControl") and \
+               direct.manipulationControl.fMultiView and \
+               direct.camera.getName() != 'persp':
                 self.spawnOrthoZoom()
                 self.spawnOrthoZoom()
             else:
             else:
                 # Start manipulation
                 # Start manipulation
@@ -167,7 +166,9 @@ class DirectCameraControl(DirectObject):
 
 
     def mouseFlyStart(self, modifiers):
     def mouseFlyStart(self, modifiers):
         # Record undo point
         # Record undo point
-        # base.direct.pushUndo([base.direct.camera])            # Wasteful use of undo
+        base = ShowBaseGlobal.base
+        direct = ShowBaseGlobal.direct
+        #direct.pushUndo([direct.camera])            # Wasteful use of undo
         if self.useMayaCamControls and modifiers == 4:          # alt is down, use maya controls
         if self.useMayaCamControls and modifiers == 4:          # alt is down, use maya controls
             # Hide the marker for this kind of motion
             # Hide the marker for this kind of motion
             self.coaMarker.hide()
             self.coaMarker.hide()
@@ -176,15 +177,16 @@ class DirectCameraControl(DirectObject):
             self.startF = base.clock.getFrameCount()
             self.startF = base.clock.getFrameCount()
             # Start manipulation
             # Start manipulation
             # If the cam is orthogonal, spawn differentTask
             # If the cam is orthogonal, spawn differentTask
-            if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView and\
-               base.direct.camera.getName() != 'persp':
+            if hasattr(direct, "manipulationControl") and \
+               direct.manipulationControl.fMultiView and \
+               direct.camera.getName() != 'persp':
                 self.spawnOrthoTranslate()
                 self.spawnOrthoTranslate()
             else:
             else:
                 self.spawnXZTranslate()
                 self.spawnXZTranslate()
             self.altDown = 1
             self.altDown = 1
         elif not self.useMayaCamControls:
         elif not self.useMayaCamControls:
             # Where are we in the display region?
             # Where are we in the display region?
-            if ((abs(base.direct.dr.mouseX) < 0.9) and (abs(base.direct.dr.mouseY) < 0.9)):
+            if abs(direct.dr.mouseX) < 0.9 and abs(direct.dr.mouseY) < 0.9:
                 # MOUSE IS IN CENTRAL REGION
                 # MOUSE IS IN CENTRAL REGION
                 # Hide the marker for this kind of motion
                 # Hide the marker for this kind of motion
                 self.coaMarker.hide()
                 self.coaMarker.hide()
@@ -194,19 +196,18 @@ class DirectCameraControl(DirectObject):
                 # Start manipulation
                 # Start manipulation
                 self.spawnXZTranslateOrHPanYZoom()
                 self.spawnXZTranslateOrHPanYZoom()
                 # END MOUSE IN CENTRAL REGION
                 # END MOUSE IN CENTRAL REGION
+            elif abs(direct.dr.mouseX) > 0.9 and abs(direct.dr.mouseY) > 0.9:
+                # Mouse is in corners, spawn roll task
+                self.spawnMouseRollTask()
             else:
             else:
-                if ((abs(base.direct.dr.mouseX) > 0.9) and
-                    (abs(base.direct.dr.mouseY) > 0.9)):
-                    # Mouse is in corners, spawn roll task
-                    self.spawnMouseRollTask()
-                else:
-                    # Mouse is in outer frame, spawn mouseRotateTask
-                    self.spawnMouseRotateTask()
+                # Mouse is in outer frame, spawn mouseRotateTask
+                self.spawnMouseRotateTask()
         if not modifiers == 4:
         if not modifiers == 4:
             self.altDown = 0
             self.altDown = 0
 
 
     def mouseFlyStop(self):
     def mouseFlyStop(self):
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()
+        base = ShowBaseGlobal.base
         stopT = base.clock.getFrameTime()
         stopT = base.clock.getFrameTime()
         deltaT = stopT - self.startT
         deltaT = stopT - self.startT
         stopF = base.clock.getFrameCount()
         stopF = base.clock.getFrameCount()
@@ -215,7 +216,8 @@ class DirectCameraControl(DirectObject):
         # if not self.useMayaCamControls and (deltaT <= 0.25) or (deltaF <= 1):
         # if not self.useMayaCamControls and (deltaT <= 0.25) or (deltaF <= 1):
 
 
         # Do this when not trying to manipulate camera
         # Do this when not trying to manipulate camera
-        if not self.altDown and len(base.direct.selected.getSelectedAsList()) == 0:
+        direct = ShowBaseGlobal.direct
+        if not self.altDown and len(direct.selected.getSelectedAsList()) == 0:
             # Check for a hit point based on
             # Check for a hit point based on
             # current mouse position
             # current mouse position
             # Allow intersection with unpickable objects
             # Allow intersection with unpickable objects
@@ -224,13 +226,13 @@ class DirectCameraControl(DirectObject):
             skipFlags = DG.SKIP_HIDDEN | DG.SKIP_BACKFACE
             skipFlags = DG.SKIP_HIDDEN | DG.SKIP_BACKFACE
             # Skip camera (and its children), unless control key is pressed
             # Skip camera (and its children), unless control key is pressed
             skipFlags |= DG.SKIP_CAMERA * (1 - base.getControl())
             skipFlags |= DG.SKIP_CAMERA * (1 - base.getControl())
-            self.computeCOA(base.direct.iRay.pickGeom(skipFlags = skipFlags))
+            self.computeCOA(direct.iRay.pickGeom(skipFlags = skipFlags))
             # Record reference point
             # Record reference point
             self.coaMarkerRef.setPosHprScale(base.cam, 0, 0, 0, 0, 0, 0, 1, 1, 1)
             self.coaMarkerRef.setPosHprScale(base.cam, 0, 0, 0, 0, 0, 0, 1, 1, 1)
             # Record entries
             # Record entries
             self.cqEntries = []
             self.cqEntries = []
-            for i in range(base.direct.iRay.getNumEntries()):
-                self.cqEntries.append(base.direct.iRay.getEntry(i))
+            for i in range(direct.iRay.getNumEntries()):
+                self.cqEntries.append(direct.iRay.getEntry(i))
         # Show the marker
         # Show the marker
         self.coaMarker.show()
         self.coaMarker.show()
         # Resize it
         # Resize it
@@ -251,7 +253,7 @@ class DirectCameraControl(DirectObject):
         # Spawn the new task
         # Spawn the new task
         t = Task.Task(self.XZTranslateOrHPanYZoomTask)
         t = Task.Task(self.XZTranslateOrHPanYZoomTask)
         # For HPanYZoom
         # For HPanYZoom
-        t.zoomSF = Vec3(self.coaMarker.getPos(base.direct.camera)).length()
+        t.zoomSF = Vec3(self.coaMarker.getPos(ShowBaseGlobal.direct.camera)).length()
         self.__startManipulateCamera(task = t)
         self.__startManipulateCamera(task = t)
 
 
     def spawnXZTranslateOrHPPan(self):
     def spawnXZTranslateOrHPPan(self):
@@ -277,7 +279,7 @@ class DirectCameraControl(DirectObject):
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()
         # Spawn new task
         # Spawn new task
         t = Task.Task(self.HPanYZoomTask)
         t = Task.Task(self.HPanYZoomTask)
-        t.zoomSF = Vec3(self.coaMarker.getPos(base.direct.camera)).length()
+        t.zoomSF = Vec3(self.coaMarker.getPos(ShowBaseGlobal.direct.camera)).length()
         self.__startManipulateCamera(task = t)
         self.__startManipulateCamera(task = t)
 
 
     def spawnOrthoZoom(self):
     def spawnOrthoZoom(self):
@@ -294,13 +296,13 @@ class DirectCameraControl(DirectObject):
         self.__startManipulateCamera(func = self.HPPanTask)
         self.__startManipulateCamera(func = self.HPPanTask)
 
 
     def XZTranslateOrHPanYZoomTask(self, state):
     def XZTranslateOrHPanYZoomTask(self, state):
-        if base.direct.fShift:
+        if ShowBaseGlobal.direct.fShift:
             return self.XZTranslateTask(state)
             return self.XZTranslateTask(state)
         else:
         else:
             return self.HPanYZoomTask(state)
             return self.HPanYZoomTask(state)
 
 
     def XZTranslateOrHPPanTask(self, state):
     def XZTranslateOrHPPanTask(self, state):
-        if base.direct.fShift:
+        if ShowBaseGlobal.direct.fShift:
             # Panning action
             # Panning action
             return self.HPPanTask(state)
             return self.HPPanTask(state)
         else:
         else:
@@ -308,43 +310,46 @@ class DirectCameraControl(DirectObject):
             return self.XZTranslateTask(state)
             return self.XZTranslateTask(state)
 
 
     def XZTranslateTask(self, state):
     def XZTranslateTask(self, state):
-        coaDist = Vec3(self.coaMarker.getPos(base.direct.camera)).length()
-        xlateSF = coaDist / base.direct.dr.near
-        base.direct.camera.setPos(base.direct.camera,
-                             (-0.5 * base.direct.dr.mouseDeltaX *
-                              base.direct.dr.nearWidth *
+        direct = ShowBaseGlobal.direct
+        coaDist = Vec3(self.coaMarker.getPos(direct.camera)).length()
+        xlateSF = coaDist / direct.dr.near
+        direct.camera.setPos(direct.camera,
+                             (-0.5 * direct.dr.mouseDeltaX *
+                              direct.dr.nearWidth *
                               xlateSF),
                               xlateSF),
                              0.0,
                              0.0,
-                             (-0.5 * base.direct.dr.mouseDeltaY *
-                              base.direct.dr.nearHeight *
+                             (-0.5 * direct.dr.mouseDeltaY *
+                              direct.dr.nearHeight *
                               xlateSF))
                               xlateSF))
         return Task.cont
         return Task.cont
 
 
     def OrthoTranslateTask(self, state):
     def OrthoTranslateTask(self, state):
         # create ray from the camera to detect 3d position
         # create ray from the camera to detect 3d position
-        iRay = SelectionRay(base.direct.camera)
-        iRay.collider.setFromLens(base.direct.camNode, base.direct.dr.mouseX, base.direct.dr.mouseY)
+        direct = ShowBaseGlobal.direct
+        iRay = SelectionRay(direct.camera)
+        iRay.collider.setFromLens(direct.camNode, direct.dr.mouseX, direct.dr.mouseY)
         #iRay.collideWithBitMask(1)
         #iRay.collideWithBitMask(1)
         iRay.collideWithBitMask(BitMask32.bit(21))
         iRay.collideWithBitMask(BitMask32.bit(21))
-        iRay.ct.traverse(base.direct.grid)
+        iRay.ct.traverse(direct.grid)
 
 
         entry = iRay.getEntry(0)
         entry = iRay.getEntry(0)
         hitPt = entry.getSurfacePoint(entry.getFromNodePath())
         hitPt = entry.getSurfacePoint(entry.getFromNodePath())
         iRay.collisionNodePath.removeNode()
         iRay.collisionNodePath.removeNode()
         del iRay
         del iRay
         if hasattr(state, 'prevPt'):
         if hasattr(state, 'prevPt'):
-            base.direct.camera.setPos(base.direct.camera, (state.prevPt - hitPt))
+            direct.camera.setPos(direct.camera, (state.prevPt - hitPt))
         state.prevPt = hitPt
         state.prevPt = hitPt
         return Task.cont
         return Task.cont
 
 
     def HPanYZoomTask(self, state):
     def HPanYZoomTask(self, state):
         # If the cam is orthogonal, don't rotate or zoom.
         # If the cam is orthogonal, don't rotate or zoom.
-        if (hasattr(base.direct.cam.node(), "getLens") and
-            base.direct.cam.node().getLens().__class__.__name__ == "OrthographicLens"):
+        direct = ShowBaseGlobal.direct
+        if (hasattr(direct.cam.node(), "getLens") and
+            direct.cam.node().getLens().__class__.__name__ == "OrthographicLens"):
             return
             return
 
 
-        if base.direct.fControl:
-            moveDir = Vec3(self.coaMarker.getPos(base.direct.camera))
+        if direct.fControl:
+            moveDir = Vec3(self.coaMarker.getPos(direct.camera))
             # If marker is behind camera invert vector
             # If marker is behind camera invert vector
             if moveDir[1] < 0.0:
             if moveDir[1] < 0.0:
                 moveDir.assign(moveDir * -1)
                 moveDir.assign(moveDir * -1)
@@ -353,18 +358,18 @@ class DirectCameraControl(DirectObject):
             moveDir = Vec3(Y_AXIS)
             moveDir = Vec3(Y_AXIS)
 
 
         if self.useMayaCamControls: # use maya controls
         if self.useMayaCamControls: # use maya controls
-            moveDir.assign(moveDir * ((base.direct.dr.mouseDeltaX -1.0 * base.direct.dr.mouseDeltaY)
+            moveDir.assign(moveDir * ((direct.dr.mouseDeltaX -1.0 * direct.dr.mouseDeltaY)
                                     * state.zoomSF))
                                     * state.zoomSF))
             hVal = 0.0
             hVal = 0.0
         else:
         else:
-            moveDir.assign(moveDir * (-1.0 * base.direct.dr.mouseDeltaY *
+            moveDir.assign(moveDir * (-1.0 * direct.dr.mouseDeltaY *
                                         state.zoomSF))
                                         state.zoomSF))
-            if base.direct.dr.mouseDeltaY > 0.0:
+            if direct.dr.mouseDeltaY > 0.0:
                 moveDir.setY(moveDir[1] * 1.0)
                 moveDir.setY(moveDir[1] * 1.0)
 
 
-            hVal = 0.5 * base.direct.dr.mouseDeltaX * base.direct.dr.fovH
+            hVal = 0.5 * direct.dr.mouseDeltaX * direct.dr.fovH
 
 
-        base.direct.camera.setPosHpr(base.direct.camera,
+        direct.camera.setPosHpr(direct.camera,
                                 moveDir[0],
                                 moveDir[0],
                                 moveDir[1],
                                 moveDir[1],
                                 moveDir[2],
                                 moveDir[2],
@@ -372,39 +377,42 @@ class DirectCameraControl(DirectObject):
                                 0.0, 0.0)
                                 0.0, 0.0)
         if self.lockRoll:
         if self.lockRoll:
             # flatten roll
             # flatten roll
-            base.direct.camera.setR(0)
+            direct.camera.setR(0)
 
 
         return Task.cont
         return Task.cont
 
 
     def OrthoZoomTask(self, state):
     def OrthoZoomTask(self, state):
-        filmSize = base.direct.camNode.getLens().getFilmSize()
-        factor = (base.direct.dr.mouseDeltaX -1.0 * base.direct.dr.mouseDeltaY) * 0.1
-        x = base.direct.dr.getWidth()
-        y = base.direct.dr.getHeight()
-        base.direct.dr.orthoFactor -= factor
-        if base.direct.dr.orthoFactor < 0:
-            base.direct.dr.orthoFactor = 0.0001
-        base.direct.dr.updateFilmSize(x, y)
+        direct = ShowBaseGlobal.direct
+        filmSize = direct.camNode.getLens().getFilmSize()
+        factor = (direct.dr.mouseDeltaX -1.0 * direct.dr.mouseDeltaY) * 0.1
+        x = direct.dr.getWidth()
+        y = direct.dr.getHeight()
+        direct.dr.orthoFactor -= factor
+        if direct.dr.orthoFactor < 0:
+            direct.dr.orthoFactor = 0.0001
+        direct.dr.updateFilmSize(x, y)
         return Task.cont
         return Task.cont
 
 
     def HPPanTask(self, state):
     def HPPanTask(self, state):
-        base.direct.camera.setHpr(base.direct.camera,
-                             (0.5 * base.direct.dr.mouseDeltaX *
-                              base.direct.dr.fovH),
-                             (-0.5 * base.direct.dr.mouseDeltaY *
-                              base.direct.dr.fovV),
+        direct = ShowBaseGlobal.direct
+        direct.camera.setHpr(direct.camera,
+                             (0.5 * direct.dr.mouseDeltaX *
+                              direct.dr.fovH),
+                             (-0.5 * direct.dr.mouseDeltaY *
+                              direct.dr.fovV),
                              0.0)
                              0.0)
         return Task.cont
         return Task.cont
 
 
     def spawnMouseRotateTask(self):
     def spawnMouseRotateTask(self):
         # Kill any existing tasks
         # Kill any existing tasks
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()
+        direct = ShowBaseGlobal.direct
         if self.perspCollPlane:
         if self.perspCollPlane:
-            iRay = SelectionRay(base.direct.camera)
-            iRay.collider.setFromLens(base.direct.camNode, 0.0, 0.0)
+            iRay = SelectionRay(direct.camera)
+            iRay.collider.setFromLens(direct.camNode, 0.0, 0.0)
             iRay.collideWithBitMask(1)
             iRay.collideWithBitMask(1)
 
 
-            if base.direct.camera.getPos().getZ() >=0:
+            if direct.camera.getPos().getZ() >=0:
                 iRay.ct.traverse(self.perspCollPlane)
                 iRay.ct.traverse(self.perspCollPlane)
             else:
             else:
                 iRay.ct.traverse(self.perspCollPlane2)
                 iRay.ct.traverse(self.perspCollPlane2)
@@ -415,7 +423,7 @@ class DirectCameraControl(DirectObject):
 
 
                 # create a temp nodePath to get the position
                 # create a temp nodePath to get the position
                 np = NodePath('temp')
                 np = NodePath('temp')
-                np.setPos(base.direct.camera, hitPt)
+                np.setPos(direct.camera, hitPt)
                 self.coaMarkerPos = np.getPos()
                 self.coaMarkerPos = np.getPos()
                 np.removeNode()
                 np.removeNode()
                 self.coaMarker.setPos(self.coaMarkerPos)
                 self.coaMarker.setPos(self.coaMarkerPos)
@@ -425,9 +433,9 @@ class DirectCameraControl(DirectObject):
 
 
         # Set at markers position in render coordinates
         # Set at markers position in render coordinates
         self.camManipRef.setPos(self.coaMarkerPos)
         self.camManipRef.setPos(self.coaMarkerPos)
-        self.camManipRef.setHpr(base.direct.camera, DG.ZERO_POINT)
+        self.camManipRef.setHpr(direct.camera, DG.ZERO_POINT)
         t = Task.Task(self.mouseRotateTask)
         t = Task.Task(self.mouseRotateTask)
-        if abs(base.direct.dr.mouseX) > 0.9:
+        if abs(direct.dr.mouseX) > 0.9:
             t.constrainedDir = 'y'
             t.constrainedDir = 'y'
         else:
         else:
             t.constrainedDir = 'x'
             t.constrainedDir = 'x'
@@ -435,36 +443,37 @@ class DirectCameraControl(DirectObject):
 
 
     def mouseRotateTask(self, state):
     def mouseRotateTask(self, state):
         # If the cam is orthogonal, don't rotate.
         # If the cam is orthogonal, don't rotate.
-        if (hasattr(base.direct.cam.node(), "getLens") and
-            base.direct.cam.node().getLens().__class__.__name__ == "OrthographicLens"):
+        direct = ShowBaseGlobal.direct
+        if (hasattr(direct.cam.node(), "getLens") and
+            direct.cam.node().getLens().__class__.__name__ == "OrthographicLens"):
             return
             return
         # If moving outside of center, ignore motion perpendicular to edge
         # If moving outside of center, ignore motion perpendicular to edge
-        if ((state.constrainedDir == 'y') and (abs(base.direct.dr.mouseX) > 0.9)):
+        if ((state.constrainedDir == 'y') and (abs(direct.dr.mouseX) > 0.9)):
             deltaX = 0
             deltaX = 0
-            deltaY = base.direct.dr.mouseDeltaY
-        elif ((state.constrainedDir == 'x') and (abs(base.direct.dr.mouseY) > 0.9)):
-            deltaX = base.direct.dr.mouseDeltaX
+            deltaY = direct.dr.mouseDeltaY
+        elif ((state.constrainedDir == 'x') and (abs(direct.dr.mouseY) > 0.9)):
+            deltaX = direct.dr.mouseDeltaX
             deltaY = 0
             deltaY = 0
         else:
         else:
-            deltaX = base.direct.dr.mouseDeltaX
-            deltaY = base.direct.dr.mouseDeltaY
-        if base.direct.fShift:
-            base.direct.camera.setHpr(base.direct.camera,
-                                 (deltaX * base.direct.dr.fovH),
-                                 (-deltaY * base.direct.dr.fovV),
+            deltaX = direct.dr.mouseDeltaX
+            deltaY = direct.dr.mouseDeltaY
+        if direct.fShift:
+            direct.camera.setHpr(direct.camera,
+                                 (deltaX * direct.dr.fovH),
+                                 (-deltaY * direct.dr.fovV),
                                  0.0)
                                  0.0)
             if self.lockRoll:
             if self.lockRoll:
                 # flatten roll
                 # flatten roll
-                base.direct.camera.setR(0)
+                direct.camera.setR(0)
             self.camManipRef.setPos(self.coaMarkerPos)
             self.camManipRef.setPos(self.coaMarkerPos)
-            self.camManipRef.setHpr(base.direct.camera, DG.ZERO_POINT)
+            self.camManipRef.setHpr(direct.camera, DG.ZERO_POINT)
         else:
         else:
-            if base.direct.camera.getPos().getZ() >=0 or not self.switchDirBelowZero:
+            if direct.camera.getPos().getZ() >=0 or not self.switchDirBelowZero:
                 dirX = -1
                 dirX = -1
             else:
             else:
                 dirX = 1
                 dirX = 1
 
 
-            wrt = base.direct.camera.getTransform(self.camManipRef)
+            wrt = direct.camera.getTransform(self.camManipRef)
             self.camManipRef.setHpr(self.camManipRef,
             self.camManipRef.setHpr(self.camManipRef,
                                     (dirX * deltaX * 180.0),
                                     (dirX * deltaX * 180.0),
                                     (deltaY * 180.0),
                                     (deltaY * 180.0),
@@ -473,20 +482,21 @@ class DirectCameraControl(DirectObject):
             if self.lockRoll:
             if self.lockRoll:
                 # flatten roll
                 # flatten roll
                 self.camManipRef.setR(0)
                 self.camManipRef.setR(0)
-            base.direct.camera.setTransform(self.camManipRef, wrt)
+            direct.camera.setTransform(self.camManipRef, wrt)
         return Task.cont
         return Task.cont
 
 
     def spawnMouseRollTask(self):
     def spawnMouseRollTask(self):
         # Kill any existing tasks
         # Kill any existing tasks
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()
         # Set at markers position in render coordinates
         # Set at markers position in render coordinates
+        direct = ShowBaseGlobal.direct
         self.camManipRef.setPos(self.coaMarkerPos)
         self.camManipRef.setPos(self.coaMarkerPos)
-        self.camManipRef.setHpr(base.direct.camera, DG.ZERO_POINT)
+        self.camManipRef.setHpr(direct.camera, DG.ZERO_POINT)
         t = Task.Task(self.mouseRollTask)
         t = Task.Task(self.mouseRollTask)
         t.coaCenter = getScreenXY(self.coaMarker)
         t.coaCenter = getScreenXY(self.coaMarker)
         t.lastAngle = getCrankAngle(t.coaCenter)
         t.lastAngle = getCrankAngle(t.coaCenter)
         # Store the camera/manipRef offset transform
         # Store the camera/manipRef offset transform
-        t.wrt = base.direct.camera.getTransform(self.camManipRef)
+        t.wrt = direct.camera.getTransform(self.camManipRef)
         self.__startManipulateCamera(task = t)
         self.__startManipulateCamera(task = t)
 
 
     def mouseRollTask(self, state):
     def mouseRollTask(self, state):
@@ -498,23 +508,23 @@ class DirectCameraControl(DirectObject):
         if self.lockRoll:
         if self.lockRoll:
             # flatten roll
             # flatten roll
             self.camManipRef.setR(0)
             self.camManipRef.setR(0)
-        base.direct.camera.setTransform(self.camManipRef, wrt)
+        ShowBaseGlobal.direct.camera.setTransform(self.camManipRef, wrt)
         return Task.cont
         return Task.cont
 
 
     def lockCOA(self):
     def lockCOA(self):
         self.fLockCOA = 1
         self.fLockCOA = 1
-        base.direct.message('COA Lock On')
+        ShowBaseGlobal.direct.message('COA Lock On')
 
 
     def unlockCOA(self):
     def unlockCOA(self):
         self.fLockCOA = 0
         self.fLockCOA = 0
-        base.direct.message('COA Lock Off')
+        ShowBaseGlobal.direct.message('COA Lock Off')
 
 
     def toggleCOALock(self):
     def toggleCOALock(self):
         self.fLockCOA = 1 - self.fLockCOA
         self.fLockCOA = 1 - self.fLockCOA
         if self.fLockCOA:
         if self.fLockCOA:
-            base.direct.message('COA Lock On')
+            ShowBaseGlobal.direct.message('COA Lock On')
         else:
         else:
-            base.direct.message('COA Lock Off')
+            ShowBaseGlobal.direct.message('COA Lock Off')
 
 
     def pickNextCOA(self):
     def pickNextCOA(self):
         """ Cycle through collision handler entries """
         """ Cycle through collision handler entries """
@@ -524,7 +534,7 @@ class DirectCameraControl(DirectObject):
             self.cqEntries = self.cqEntries[1:] + self.cqEntries[:1]
             self.cqEntries = self.cqEntries[1:] + self.cqEntries[:1]
             # Filter out object's under camera
             # Filter out object's under camera
             nodePath = entry.getIntoNodePath()
             nodePath = entry.getIntoNodePath()
-            if base.direct.camera not in nodePath.getAncestors():
+            if ShowBaseGlobal.direct.camera not in nodePath.getAncestors():
                 # Compute new hit point
                 # Compute new hit point
                 hitPt = entry.getSurfacePoint(entry.getFromNodePath())
                 hitPt = entry.getSurfacePoint(entry.getFromNodePath())
                 # Move coa marker to new point
                 # Move coa marker to new point
@@ -536,11 +546,11 @@ class DirectCameraControl(DirectObject):
 
 
     def computeCOA(self, entry):
     def computeCOA(self, entry):
         coa = Point3(0)
         coa = Point3(0)
-        dr = base.direct.drList.getCurrentDr()
+        dr = ShowBaseGlobal.direct.drList.getCurrentDr()
         if self.fLockCOA:
         if self.fLockCOA:
             # COA is locked, use existing point
             # COA is locked, use existing point
             # Use existing point
             # Use existing point
-            coa.assign(self.coaMarker.getPos(base.direct.camera))
+            coa.assign(self.coaMarker.getPos(ShowBaseGlobal.direct.camera))
             # Reset hit point count
             # Reset hit point count
             self.nullHitPointCount = 0
             self.nullHitPointCount = 0
         elif entry:
         elif entry:
@@ -553,7 +563,7 @@ class DirectCameraControl(DirectObject):
             if ((hitPtDist < (1.1 * dr.near)) or
             if ((hitPtDist < (1.1 * dr.near)) or
                 (hitPtDist > dr.far)):
                 (hitPtDist > dr.far)):
                 # Just use existing point
                 # Just use existing point
-                coa.assign(self.coaMarker.getPos(base.direct.camera))
+                coa.assign(self.coaMarker.getPos(ShowBaseGlobal.direct.camera))
             # Reset hit point count
             # Reset hit point count
             self.nullHitPointCount = 0
             self.nullHitPointCount = 0
         else:
         else:
@@ -565,7 +575,7 @@ class DirectCameraControl(DirectObject):
             # MRM: Would be nice to be able to control this
             # MRM: Would be nice to be able to control this
             # At least display it
             # At least display it
             dist = pow(10.0, self.nullHitPointCount)
             dist = pow(10.0, self.nullHitPointCount)
-            base.direct.message('COA Distance: ' + repr(dist))
+            ShowBaseGlobal.direct.message('COA Distance: ' + repr(dist))
             coa.set(0, dist, 0)
             coa.set(0, dist, 0)
         # Compute COA Dist
         # Compute COA Dist
         coaDist = Vec3(coa - DG.ZERO_POINT).length()
         coaDist = Vec3(coa - DG.ZERO_POINT).length()
@@ -583,7 +593,7 @@ class DirectCameraControl(DirectObject):
         if ref is None:
         if ref is None:
             # KEH: use the current display region
             # KEH: use the current display region
             # ref = base.cam
             # ref = base.cam
-            ref = base.direct.drList.getCurrentDr().cam
+            ref = ShowBaseGlobal.direct.drList.getCurrentDr().cam
         self.coaMarker.setPos(ref, self.coa)
         self.coaMarker.setPos(ref, self.coa)
         pos = self.coaMarker.getPos()
         pos = self.coaMarker.getPos()
         self.coaMarker.setPosHprScale(pos, Vec3(0), Vec3(1))
         self.coaMarker.setPosHprScale(pos, Vec3(0), Vec3(1))
@@ -598,10 +608,10 @@ class DirectCameraControl(DirectObject):
 
 
     def updateCoaMarkerSize(self, coaDist = None):
     def updateCoaMarkerSize(self, coaDist = None):
         if not coaDist:
         if not coaDist:
-            coaDist = Vec3(self.coaMarker.getPos(base.direct.camera)).length()
+            coaDist = Vec3(self.coaMarker.getPos(ShowBaseGlobal.direct.camera)).length()
         # Nominal size based on default 30 degree vertical FOV
         # Nominal size based on default 30 degree vertical FOV
         # Need to adjust size based on distance and current FOV
         # Need to adjust size based on distance and current FOV
-        sf = COA_MARKER_SF * coaDist * (base.direct.drList.getCurrentDr().fovV/30.0)
+        sf = COA_MARKER_SF * coaDist * (ShowBaseGlobal.direct.drList.getCurrentDr().fovV/30.0)
         if sf == 0.0:
         if sf == 0.0:
             sf = 0.1
             sf = 0.1
         self.coaMarker.setScale(sf)
         self.coaMarker.setScale(sf)
@@ -619,32 +629,36 @@ class DirectCameraControl(DirectObject):
 
 
     def homeCam(self):
     def homeCam(self):
         # Record undo point
         # Record undo point
-        base.direct.pushUndo([base.direct.camera])
-        base.direct.camera.reparentTo(render)
-        base.direct.camera.clearMat()
+        direct = ShowBaseGlobal.direct
+        direct.pushUndo([direct.camera])
+        direct.camera.reparentTo(ShowBaseGlobal.base.render)
+        direct.camera.clearMat()
         # Resize coa marker
         # Resize coa marker
         self.updateCoaMarkerSize()
         self.updateCoaMarkerSize()
 
 
     def uprightCam(self):
     def uprightCam(self):
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()
         # Record undo point
         # Record undo point
-        base.direct.pushUndo([base.direct.camera])
+        direct = ShowBaseGlobal.direct
+        direct.pushUndo([direct.camera])
         # Pitch camera till upright
         # Pitch camera till upright
-        currH = base.direct.camera.getH()
-        ival = base.direct.camera.hprInterval(CAM_MOVE_DURATION,
-                                              (currH, 0, 0),
-                                              other = render,
-                                              blendType = 'easeInOut',
-                                              name = 'manipulateCamera')
-        self.__startManipulateCamera(ival = ival)
+        currH = direct.camera.getH()
+        ival = direct.camera.hprInterval(CAM_MOVE_DURATION,
+                                         (currH, 0, 0),
+                                         other=ShowBaseGlobal.base.render,
+                                         blendType='easeInOut',
+                                         name='manipulateCamera')
+        self.__startManipulateCamera(ival=ival)
 
 
     def orbitUprightCam(self):
     def orbitUprightCam(self):
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()
         # Record undo point
         # Record undo point
-        base.direct.pushUndo([base.direct.camera])
+        direct = ShowBaseGlobal.direct
+        direct.pushUndo([direct.camera])
         # Transform camera z axis to render space
         # Transform camera z axis to render space
+        render = ShowBaseGlobal.base.render
         mCam2Render = Mat4(Mat4.identMat()) # [gjeon] fixed to give required argument
         mCam2Render = Mat4(Mat4.identMat()) # [gjeon] fixed to give required argument
-        mCam2Render.assign(base.direct.camera.getMat(render))
+        mCam2Render.assign(direct.camera.getMat(render))
         zAxis = Vec3(mCam2Render.xformVec(DG.Z_AXIS))
         zAxis = Vec3(mCam2Render.xformVec(DG.Z_AXIS))
         zAxis.normalize()
         zAxis.normalize()
         # Compute rotation angle needed to upright cam
         # Compute rotation angle needed to upright cam
@@ -665,8 +679,8 @@ class DirectCameraControl(DirectObject):
         self.camManipRef.setPos(self.coaMarker, Vec3(0))
         self.camManipRef.setPos(self.coaMarker, Vec3(0))
         self.camManipRef.setHpr(render, rotAngle, 0, 0)
         self.camManipRef.setHpr(render, rotAngle, 0, 0)
         # Reparent Cam to ref Coordinate system
         # Reparent Cam to ref Coordinate system
-        parent = base.direct.camera.getParent()
-        base.direct.camera.wrtReparentTo(self.camManipRef)
+        parent = direct.camera.getParent()
+        direct.camera.wrtReparentTo(self.camManipRef)
         # Rotate ref CS to final orientation
         # Rotate ref CS to final orientation
         ival = self.camManipRef.hprInterval(CAM_MOVE_DURATION,
         ival = self.camManipRef.hprInterval(CAM_MOVE_DURATION,
                                             (rotAngle, orbitAngle, 0),
                                             (rotAngle, orbitAngle, 0),
@@ -685,17 +699,18 @@ class DirectCameraControl(DirectObject):
     def centerCamIn(self, t):
     def centerCamIn(self, t):
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()
         # Record undo point
         # Record undo point
-        base.direct.pushUndo([base.direct.camera])
+        direct = ShowBaseGlobal.direct
+        direct.pushUndo([direct.camera])
         # Determine marker location
         # Determine marker location
-        markerToCam = self.coaMarker.getPos(base.direct.camera)
+        markerToCam = self.coaMarker.getPos(direct.camera)
         dist = Vec3(markerToCam - DG.ZERO_POINT).length()
         dist = Vec3(markerToCam - DG.ZERO_POINT).length()
         scaledCenterVec = Y_AXIS * dist
         scaledCenterVec = Y_AXIS * dist
         delta = markerToCam - scaledCenterVec
         delta = markerToCam - scaledCenterVec
-        self.camManipRef.setPosHpr(base.direct.camera, Point3(0), Point3(0))
-        ival = base.direct.camera.posInterval(CAM_MOVE_DURATION,
-                                              Point3(delta),
-                                              other = self.camManipRef,
-                                              blendType = 'easeInOut')
+        self.camManipRef.setPosHpr(direct.camera, Point3(0), Point3(0))
+        ival = direct.camera.posInterval(CAM_MOVE_DURATION,
+                                         Point3(delta),
+                                         other=self.camManipRef,
+                                         blendType='easeInOut')
         ival = Sequence(ival, Func(self.updateCoaMarkerSizeOnDeath),
         ival = Sequence(ival, Func(self.updateCoaMarkerSizeOnDeath),
                         name = 'manipulateCamera')
                         name = 'manipulateCamera')
         self.__startManipulateCamera(ival = ival)
         self.__startManipulateCamera(ival = ival)
@@ -703,17 +718,18 @@ class DirectCameraControl(DirectObject):
     def zoomCam(self, zoomFactor, t):
     def zoomCam(self, zoomFactor, t):
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()
         # Record undo point
         # Record undo point
-        base.direct.pushUndo([base.direct.camera])
+        direct = ShowBaseGlobal.direct
+        direct.pushUndo([direct.camera])
         # Find a point zoom factor times the current separation
         # Find a point zoom factor times the current separation
         # of the widget and cam
         # of the widget and cam
-        zoomPtToCam = self.coaMarker.getPos(base.direct.camera) * zoomFactor
+        zoomPtToCam = self.coaMarker.getPos(direct.camera) * zoomFactor
         # Put a target nodePath there
         # Put a target nodePath there
-        self.camManipRef.setPos(base.direct.camera, zoomPtToCam)
+        self.camManipRef.setPos(direct.camera, zoomPtToCam)
         # Move to that point
         # Move to that point
-        ival = base.direct.camera.posInterval(CAM_MOVE_DURATION,
-                                              DG.ZERO_POINT,
-                                              other = self.camManipRef,
-                                              blendType = 'easeInOut')
+        ival = direct.camera.posInterval(CAM_MOVE_DURATION,
+                                         DG.ZERO_POINT,
+                                         other=self.camManipRef,
+                                         blendType='easeInOut')
         ival = Sequence(ival, Func(self.updateCoaMarkerSizeOnDeath),
         ival = Sequence(ival, Func(self.updateCoaMarkerSizeOnDeath),
                         name = 'manipulateCamera')
                         name = 'manipulateCamera')
         self.__startManipulateCamera(ival = ival)
         self.__startManipulateCamera(ival = ival)
@@ -722,7 +738,8 @@ class DirectCameraControl(DirectObject):
         # Kill any existing tasks
         # Kill any existing tasks
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()
         # Record undo point
         # Record undo point
-        base.direct.pushUndo([base.direct.camera])
+        direct = ShowBaseGlobal.direct
+        direct.pushUndo([direct.camera])
         # Calc hprOffset
         # Calc hprOffset
         hprOffset = VBase3()
         hprOffset = VBase3()
         if view == 8:
         if view == 8:
@@ -751,7 +768,7 @@ class DirectCameraControl(DirectObject):
         self.camManipRef.setPosHpr(self.coaMarker, DG.ZERO_VEC,
         self.camManipRef.setPosHpr(self.coaMarker, DG.ZERO_VEC,
                                    hprOffset)
                                    hprOffset)
         # Scale center vec by current distance to target
         # Scale center vec by current distance to target
-        offsetDistance = Vec3(base.direct.camera.getPos(self.camManipRef) -
+        offsetDistance = Vec3(direct.camera.getPos(self.camManipRef) -
                               DG.ZERO_POINT).length()
                               DG.ZERO_POINT).length()
         scaledCenterVec = Y_AXIS * (-1.0 * offsetDistance)
         scaledCenterVec = Y_AXIS * (-1.0 * offsetDistance)
         # Now put the camManipRef at that point
         # Now put the camManipRef at that point
@@ -760,11 +777,11 @@ class DirectCameraControl(DirectObject):
                                    DG.ZERO_VEC)
                                    DG.ZERO_VEC)
         # Record view for next time around
         # Record view for next time around
         self.lastView = view
         self.lastView = view
-        ival = base.direct.camera.posHprInterval(CAM_MOVE_DURATION,
-                                                 pos = DG.ZERO_POINT,
-                                                 hpr = VBase3(0, 0, self.orthoViewRoll),
-                                                 other = self.camManipRef,
-                                                 blendType = 'easeInOut')
+        ival = direct.camera.posHprInterval(CAM_MOVE_DURATION,
+                                            pos=DG.ZERO_POINT,
+                                            hpr=VBase3(0, 0, self.orthoViewRoll),
+                                            other=self.camManipRef,
+                                            blendType='easeInOut')
         ival = Sequence(ival, Func(self.updateCoaMarkerSizeOnDeath),
         ival = Sequence(ival, Func(self.updateCoaMarkerSizeOnDeath),
                         name = 'manipulateCamera')
                         name = 'manipulateCamera')
         self.__startManipulateCamera(ival = ival)
         self.__startManipulateCamera(ival = ival)
@@ -774,15 +791,16 @@ class DirectCameraControl(DirectObject):
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()
 
 
         # Record undo point
         # Record undo point
-        base.direct.pushUndo([base.direct.camera])
+        direct = ShowBaseGlobal.direct
+        direct.pushUndo([direct.camera])
 
 
         # Coincident with widget
         # Coincident with widget
         self.camManipRef.setPos(self.coaMarker, DG.ZERO_POINT)
         self.camManipRef.setPos(self.coaMarker, DG.ZERO_POINT)
         # But aligned with render space
         # But aligned with render space
         self.camManipRef.setHpr(DG.ZERO_POINT)
         self.camManipRef.setHpr(DG.ZERO_POINT)
 
 
-        parent = base.direct.camera.getParent()
-        base.direct.camera.wrtReparentTo(self.camManipRef)
+        parent = direct.camera.getParent()
+        direct.camera.wrtReparentTo(self.camManipRef)
 
 
         ival = self.camManipRef.hprInterval(CAM_MOVE_DURATION,
         ival = self.camManipRef.hprInterval(CAM_MOVE_DURATION,
                                             VBase3(degrees, 0, 0),
                                             VBase3(degrees, 0, 0),
@@ -792,7 +810,7 @@ class DirectCameraControl(DirectObject):
         self.__startManipulateCamera(ival = ival)
         self.__startManipulateCamera(ival = ival)
 
 
     def reparentCam(self, parent):
     def reparentCam(self, parent):
-        base.direct.camera.wrtReparentTo(parent)
+        ShowBaseGlobal.direct.camera.wrtReparentTo(parent)
         self.updateCoaMarkerSize()
         self.updateCoaMarkerSize()
 
 
     def fitOnWidget(self, nodePath = 'None Given'):
     def fitOnWidget(self, nodePath = 'None Given'):
@@ -800,75 +818,78 @@ class DirectCameraControl(DirectObject):
         # stop any ongoing tasks
         # stop any ongoing tasks
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()
         # How big is the node?
         # How big is the node?
-        nodeScale = base.direct.widget.scalingNode.getScale(render)
+        direct = ShowBaseGlobal.direct
+        nodeScale = direct.widget.scalingNode.getScale(ShowBaseGlobal.base.render)
         maxScale = max(nodeScale[0], nodeScale[1], nodeScale[2])
         maxScale = max(nodeScale[0], nodeScale[1], nodeScale[2])
-        maxDim = min(base.direct.dr.nearWidth, base.direct.dr.nearHeight)
+        maxDim = min(direct.dr.nearWidth, direct.dr.nearHeight)
 
 
         # At what distance does the object fill 30% of the screen?
         # At what distance does the object fill 30% of the screen?
         # Assuming radius of 1 on widget
         # Assuming radius of 1 on widget
-        camY = base.direct.dr.near * (2.0 * maxScale)/(0.3 * maxDim)
+        camY = direct.dr.near * (2.0 * maxScale) / (0.3 * maxDim)
 
 
         # What is the vector through the center of the screen?
         # What is the vector through the center of the screen?
         centerVec = Y_AXIS * camY
         centerVec = Y_AXIS * camY
 
 
         # Where is the node relative to the viewpoint
         # Where is the node relative to the viewpoint
-        vWidget2Camera = base.direct.widget.getPos(base.direct.camera)
+        vWidget2Camera = direct.widget.getPos(direct.camera)
 
 
         # How far do you move the camera to be this distance from the node?
         # How far do you move the camera to be this distance from the node?
         deltaMove = vWidget2Camera - centerVec
         deltaMove = vWidget2Camera - centerVec
 
 
         # Move a target there
         # Move a target there
         try:
         try:
-            self.camManipRef.setPos(base.direct.camera, deltaMove)
+            self.camManipRef.setPos(direct.camera, deltaMove)
         except Exception:
         except Exception:
             #self.notify.debug
             #self.notify.debug
             pass
             pass
 
 
-        parent = base.direct.camera.getParent()
-        base.direct.camera.wrtReparentTo(self.camManipRef)
-        ival = base.direct.camera.posInterval(CAM_MOVE_DURATION,
-                                              Point3(0, 0, 0),
-                                              blendType = 'easeInOut')
+        parent = direct.camera.getParent()
+        direct.camera.wrtReparentTo(self.camManipRef)
+        ival = direct.camera.posInterval(CAM_MOVE_DURATION,
+                                         Point3(0, 0, 0),
+                                         blendType='easeInOut')
         ival = Sequence(ival, Func(self.reparentCam, parent),
         ival = Sequence(ival, Func(self.reparentCam, parent),
-                        name = 'manipulateCamera')
-        self.__startManipulateCamera(ival = ival)
+                        name='manipulateCamera')
+        self.__startManipulateCamera(ival=ival)
 
 
     def moveToFit(self):
     def moveToFit(self):
         # How big is the active widget?
         # How big is the active widget?
-        widgetScale = base.direct.widget.scalingNode.getScale(render)
+        direct = ShowBaseGlobal.direct
+        widgetScale = direct.widget.scalingNode.getScale(ShowBaseGlobal.base.render)
         maxScale = max(widgetScale[0], widgetScale[1], widgetScale[2])
         maxScale = max(widgetScale[0], widgetScale[1], widgetScale[2])
         # At what distance does the widget fill 50% of the screen?
         # At what distance does the widget fill 50% of the screen?
-        camY = ((2 * base.direct.dr.near * (1.5 * maxScale)) /
-                min(base.direct.dr.nearWidth, base.direct.dr.nearHeight))
+        camY = ((2 * direct.dr.near * (1.5 * maxScale)) /
+                min(direct.dr.nearWidth, direct.dr.nearHeight))
         # Find a point this distance along the Y axis
         # Find a point this distance along the Y axis
         # MRM: This needs to be generalized to support non uniform frusta
         # MRM: This needs to be generalized to support non uniform frusta
         centerVec = Y_AXIS * camY
         centerVec = Y_AXIS * camY
         # Before moving, record the relationship between the selected nodes
         # Before moving, record the relationship between the selected nodes
         # and the widget, so that this can be maintained
         # and the widget, so that this can be maintained
-        base.direct.selected.getWrtAll()
+        direct.selected.getWrtAll()
         # Push state onto undo stack
         # Push state onto undo stack
-        base.direct.pushUndo(base.direct.selected)
+        direct.pushUndo(direct.selected)
         # Remove the task to keep the widget attached to the object
         # Remove the task to keep the widget attached to the object
         taskMgr.remove('followSelectedNodePath')
         taskMgr.remove('followSelectedNodePath')
         # Spawn a task to keep the selected objects with the widget
         # Spawn a task to keep the selected objects with the widget
         taskMgr.add(self.stickToWidgetTask, 'stickToWidget')
         taskMgr.add(self.stickToWidgetTask, 'stickToWidget')
         # Spawn a task to move the widget
         # Spawn a task to move the widget
-        ival = base.direct.widget.posInterval(CAM_MOVE_DURATION,
-                                              Point3(centerVec),
-                                              other = base.direct.camera,
-                                              blendType = 'easeInOut')
+        ival = direct.widget.posInterval(CAM_MOVE_DURATION,
+                                         Point3(centerVec),
+                                         other=direct.camera,
+                                         blendType='easeInOut')
         ival = Sequence(ival, Func(lambda: taskMgr.remove('stickToWidget')),
         ival = Sequence(ival, Func(lambda: taskMgr.remove('stickToWidget')),
                         name = 'moveToFit')
                         name = 'moveToFit')
         ival.start()
         ival.start()
 
 
     def stickToWidgetTask(self, state):
     def stickToWidgetTask(self, state):
         # Move the objects with the widget
         # Move the objects with the widget
-        base.direct.selected.moveWrtWidgetAll()
+        ShowBaseGlobal.direct.selected.moveWrtWidgetAll()
         # Continue
         # Continue
         return Task.cont
         return Task.cont
 
 
     def enableMouseFly(self, fKeyEvents = 1):
     def enableMouseFly(self, fKeyEvents = 1):
         # disable C++ fly interface
         # disable C++ fly interface
+        base = ShowBaseGlobal.base
         base.disableMouse()
         base.disableMouse()
         # Enable events
         # Enable events
         for event in self.actionEvents:
         for event in self.actionEvents:
@@ -877,11 +898,11 @@ class DirectCameraControl(DirectObject):
             for event in self.keyEvents:
             for event in self.keyEvents:
                 self.accept(event[0], event[1], extraArgs = event[2:])
                 self.accept(event[0], event[1], extraArgs = event[2:])
         # Show marker
         # Show marker
-        self.coaMarker.reparentTo(base.direct.group)
+        self.coaMarker.reparentTo(ShowBaseGlobal.direct.group)
 
 
     def disableMouseFly(self):
     def disableMouseFly(self):
         # Hide the marker
         # Hide the marker
-        self.coaMarker.reparentTo(hidden)
+        self.coaMarker.reparentTo(ShowBaseGlobal.hidden)
         # Ignore events
         # Ignore events
         for event in self.actionEvents:
         for event in self.actionEvents:
             self.ignore(event[0])
             self.ignore(event[0])
@@ -890,7 +911,7 @@ class DirectCameraControl(DirectObject):
         # Kill tasks
         # Kill tasks
         self.removeManipulateCameraTask()
         self.removeManipulateCameraTask()
         taskMgr.remove('stickToWidget')
         taskMgr.remove('stickToWidget')
-        base.enableMouse()
+        ShowBaseGlobal.base.enableMouse()
 
 
     def removeManipulateCameraTask(self):
     def removeManipulateCameraTask(self):
         self.__stopManipulateCamera()
         self.__stopManipulateCamera()

+ 4 - 3
direct/src/directtools/DirectGrid.py

@@ -1,6 +1,7 @@
 import math
 import math
 from panda3d.core import NodePath, Point3, VBase4
 from panda3d.core import NodePath, Point3, VBase4
 from direct.showbase.DirectObject import DirectObject
 from direct.showbase.DirectObject import DirectObject
+from direct.showbase import ShowBaseGlobal
 from .DirectUtil import ROUND_TO, useDirectRenderStyle
 from .DirectUtil import ROUND_TO, useDirectRenderStyle
 from .DirectGeometry import LineNodePath
 from .DirectGeometry import LineNodePath
 
 
@@ -14,7 +15,7 @@ class DirectGrid(NodePath, DirectObject):
 
 
         # Load up grid parts to initialize grid object
         # Load up grid parts to initialize grid object
         # Polygon used to mark grid plane
         # Polygon used to mark grid plane
-        self.gridBack = base.loader.loadModel('models/misc/gridBack')
+        self.gridBack = ShowBaseGlobal.loader.loadModel('models/misc/gridBack')
         self.gridBack.reparentTo(self)
         self.gridBack.reparentTo(self)
         self.gridBack.setColor(*planeColor)
         self.gridBack.setColor(*planeColor)
 
 
@@ -36,7 +37,7 @@ class DirectGrid(NodePath, DirectObject):
         self.centerLines.setThickness(3)
         self.centerLines.setThickness(3)
 
 
         # Small marker to hilight snap-to-grid point
         # Small marker to hilight snap-to-grid point
-        self.snapMarker = base.loader.loadModel('models/misc/sphere')
+        self.snapMarker = ShowBaseGlobal.loader.loadModel('models/misc/sphere')
         self.snapMarker.node().setName('gridSnapMarker')
         self.snapMarker.node().setName('gridSnapMarker')
         self.snapMarker.reparentTo(self)
         self.snapMarker.reparentTo(self)
         self.snapMarker.setColor(1, 0, 0, 1)
         self.snapMarker.setColor(1, 0, 0, 1)
@@ -55,7 +56,7 @@ class DirectGrid(NodePath, DirectObject):
         if parent:
         if parent:
             self.reparentTo(parent)
             self.reparentTo(parent)
         else:
         else:
-            self.reparentTo(base.direct.group)
+            self.reparentTo(ShowBaseGlobal.direct.group)
 
 
         self.updateGrid()
         self.updateGrid()
         self.fEnabled = 1
         self.fEnabled = 1

+ 1 - 1
direct/src/directtools/DirectManipulation.py

@@ -1113,7 +1113,7 @@ class ObjectHandles(NodePath, DirectObject):
         NodePath.__init__(self)
         NodePath.__init__(self)
 
 
         # Load up object handles model and assign it to self
         # Load up object handles model and assign it to self
-        self.assign(ShowBaseGlobal.base.loader.loadModel('models/misc/objectHandles'))
+        self.assign(ShowBaseGlobal.loader.loadModel('models/misc/objectHandles'))
         self.setName(name)
         self.setName(name)
         self.scalingNode = NodePath(self)
         self.scalingNode = NodePath(self)
         self.scalingNode.setName('ohScalingNode')
         self.scalingNode.setName('ohScalingNode')

+ 12 - 4
direct/src/extensions_native/NodePath_extensions.py

@@ -435,7 +435,8 @@ Dtool_funcToMethod(iPosHprScale, NodePath)
 del iPosHprScale
 del iPosHprScale
 #####################################################################
 #####################################################################
 def place(self):
 def place(self):
-    base.startDirect(fWantTk = 1)
+    from direct.showbase import ShowBaseGlobal
+    ShowBaseGlobal.base.startDirect(fWantTk = 1)
     # Don't use a regular import, to prevent ModuleFinder from picking
     # Don't use a regular import, to prevent ModuleFinder from picking
     # it up as a dependency when building a .p3d package.
     # it up as a dependency when building a .p3d package.
     import importlib
     import importlib
@@ -446,7 +447,8 @@ Dtool_funcToMethod(place, NodePath)
 del place
 del place
 #####################################################################
 #####################################################################
 def explore(self):
 def explore(self):
-    base.startDirect(fWantTk = 1)
+    from direct.showbase import ShowBaseGlobal
+    ShowBaseGlobal.base.startDirect(fWantTk = 1)
     # Don't use a regular import, to prevent ModuleFinder from picking
     # Don't use a regular import, to prevent ModuleFinder from picking
     # it up as a dependency when building a .p3d package.
     # it up as a dependency when building a .p3d package.
     import importlib
     import importlib
@@ -457,7 +459,8 @@ Dtool_funcToMethod(explore, NodePath)
 del explore
 del explore
 #####################################################################
 #####################################################################
 def rgbPanel(self, cb = None):
 def rgbPanel(self, cb = None):
-    base.startTk()
+    from direct.showbase import ShowBaseGlobal
+    ShowBaseGlobal.base.startTk()
     # Don't use a regular import, to prevent ModuleFinder from picking
     # Don't use a regular import, to prevent ModuleFinder from picking
     # it up as a dependency when building a .p3d package.
     # it up as a dependency when building a .p3d package.
     import importlib
     import importlib
@@ -468,6 +471,8 @@ Dtool_funcToMethod(rgbPanel, NodePath)
 del rgbPanel
 del rgbPanel
 #####################################################################
 #####################################################################
 def select(self):
 def select(self):
+    from direct.showbase import ShowBaseGlobal
+    base = ShowBaseGlobal.base
     base.startDirect(fWantTk = 0)
     base.startDirect(fWantTk = 0)
     base.direct.select(self)
     base.direct.select(self)
 
 
@@ -475,6 +480,8 @@ Dtool_funcToMethod(select, NodePath)
 del select
 del select
 #####################################################################
 #####################################################################
 def deselect(self):
 def deselect(self):
+    from direct.showbase import ShowBaseGlobal
+    base = ShowBaseGlobal.base
     base.startDirect(fWantTk = 0)
     base.startDirect(fWantTk = 0)
     base.direct.deselect(self)
     base.direct.deselect(self)
 
 
@@ -676,7 +683,8 @@ def flattenMultitex(self, stateFrom = None, target = None,
     mr.setAllowTexMat(allowTexMat)
     mr.setAllowTexMat(allowTexMat)
 
 
     if win is None:
     if win is None:
-        win = base.win
+        from direct.showbase import ShowBaseGlobal
+        win = ShowBaseGlobal.base.win
 
 
     if stateFrom is None:
     if stateFrom is None:
         mr.scan(self)
         mr.scan(self)

+ 1 - 0
direct/src/showbase/ShowBase.py

@@ -431,6 +431,7 @@ class ShowBase(DirectObject.DirectObject):
         #: `.Loader.Loader` object.
         #: `.Loader.Loader` object.
         self.loader = Loader.Loader(self)
         self.loader = Loader.Loader(self)
         self.graphicsEngine.setDefaultLoader(self.loader.loader)
         self.graphicsEngine.setDefaultLoader(self.loader.loader)
+        ShowBaseGlobal.loader = self.loader
 
 
         #: The global event manager, as imported from `.EventManagerGlobal`.
         #: The global event manager, as imported from `.EventManagerGlobal`.
         self.eventMgr = eventMgr
         self.eventMgr = eventMgr

+ 3 - 0
direct/src/showbase/ShowBaseGlobal.py

@@ -19,6 +19,7 @@ from panda3d.core import VirtualFileSystem, Notify, ClockObject, PandaSystem
 from panda3d.core import ConfigPageManager, ConfigVariableManager, ConfigVariableBool
 from panda3d.core import ConfigPageManager, ConfigVariableManager, ConfigVariableBool
 from panda3d.core import NodePath, PGTop
 from panda3d.core import NodePath, PGTop
 from . import DConfig as config # pylint: disable=unused-import
 from . import DConfig as config # pylint: disable=unused-import
+from .Loader import Loader
 import warnings
 import warnings
 
 
 __dev__: bool = ConfigVariableBool('want-dev', __debug__).value
 __dev__: bool = ConfigVariableBool('want-dev', __debug__).value
@@ -61,6 +62,8 @@ aspect2d = render2d.attachNewNode(PGTop("aspect2d"))
 #: A dummy scene graph that is not being rendered by anything.
 #: A dummy scene graph that is not being rendered by anything.
 hidden = NodePath("hidden")
 hidden = NodePath("hidden")
 
 
+loader: Loader
+
 direct: "DirectSession"
 direct: "DirectSession"
 
 
 # Set direct notify categories now that we have config
 # Set direct notify categories now that we have config

+ 2 - 1
direct/src/showbase/TkGlobal.py

@@ -37,4 +37,5 @@ del bordercolors
 
 
 def spawnTkLoop():
 def spawnTkLoop():
     """Alias for :meth:`base.spawnTkLoop() <.ShowBase.spawnTkLoop>`."""
     """Alias for :meth:`base.spawnTkLoop() <.ShowBase.spawnTkLoop>`."""
-    base.spawnTkLoop()
+    from direct.showbase import ShowBaseGlobal
+    ShowBaseGlobal.base.spawnTkLoop()

+ 2 - 1
direct/src/showbase/WxGlobal.py

@@ -3,4 +3,5 @@
 
 
 def spawnWxLoop():
 def spawnWxLoop():
     """Alias for :meth:`base.spawnWxLoop() <.ShowBase.spawnWxLoop>`."""
     """Alias for :meth:`base.spawnWxLoop() <.ShowBase.spawnWxLoop>`."""
-    base.spawnWxLoop()
+    from direct.showbase import ShowBaseGlobal
+    ShowBaseGlobal.base.spawnWxLoop()

+ 2 - 0
direct/src/task/MiniTask.py

@@ -12,6 +12,8 @@ class MiniTask:
     done = 0
     done = 0
     cont = 1
     cont = 1
 
 
+    name: str
+
     def __init__(self, callback):
     def __init__(self, callback):
         self.__call__ = callback
         self.__call__ = callback
 
 

+ 4 - 5
direct/src/wxwidgets/WxAppShell.py

@@ -79,13 +79,12 @@ class WxAppShell(wx.Frame):
         self.onDestroy(event)
         self.onDestroy(event)
 
 
         # to close Panda
         # to close Panda
-        try:
-            base
-        except NameError:
+        from direct.showbase import ShowBaseGlobal
+        if hasattr(ShowBaseGlobal, 'base'):
+            ShowBaseGlobal.base.userExit()
+        else:
             sys.exit()
             sys.exit()
 
 
-        base.userExit()
-
     ### USER METHODS ###
     ### USER METHODS ###
     # To be overridden
     # To be overridden
     def appInit(self):
     def appInit(self):