ShowBase.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. from PandaModules import *
  2. from DirectNotifyGlobal import *
  3. from MessengerGlobal import *
  4. from TaskManagerGlobal import *
  5. from EventManagerGlobal import *
  6. from PythonUtil import *
  7. from ParticleManagerGlobal import *
  8. from PhysicsManagerGlobal import *
  9. import Task
  10. import EventManager
  11. import math
  12. import sys
  13. import LinearEulerIntegrator
  14. import ClockObject
  15. globalClock = ClockObject.ClockObject.getGlobalClock()
  16. class ShowBase:
  17. notify = None
  18. def __init__(self):
  19. # Get the dconfig object
  20. self.config = ConfigConfigureGetConfigConfigShowbase
  21. # Store dconfig variables
  22. self.wantTk = self.config.GetBool('want-tk', 0)
  23. self.wantSound = self.config.GetBool('want-sound', 1)
  24. self.wantDIRECT = self.config.GetBool('want-directtools', 0)
  25. self.wantStats = self.config.GetBool('want-stats', 0)
  26. import Loader
  27. self.initialState = NodeAttributes()
  28. # Set a default "off color" (i.e. use poly color) for color transitions
  29. self.initialState.setAttribute(ColorTransition.getClassType(),
  30. ColorAttribute())
  31. self.renderTop = NodePath(NamedNode('renderTop'))
  32. self.render = self.renderTop.attachNewNode('render')
  33. self.hidden = NodePath(NamedNode('hidden'))
  34. # This will be the list of cameras, one per display region
  35. # For now, we only have one display region, so just create the
  36. # default camera
  37. self.camera = self.render.attachNewNode('camera')
  38. # And put it in the list
  39. self.cameraList = [ self.camera ]
  40. self.dataRoot = NodePath(NamedNode('dataRoot'), DataRelation.getClassType())
  41. self.dataUnused = NodePath(NamedNode('dataUnused'), DataRelation.getClassType())
  42. self.pipe = makeGraphicsPipe()
  43. self.win = makeGraphicsWindow(self.pipe,
  44. self.renderTop.node(),
  45. self.camera.node(),
  46. self.dataRoot.node(),
  47. self.initialState)
  48. # This is a list of cams associated with the display region's cameras
  49. self.camList = []
  50. for camera in self.cameraList:
  51. self.camList.append( camera.find('**/+Camera') )
  52. # Set the default camera
  53. self.cam = self.camera.find('**/+Camera')
  54. # Set up a 2-d layer for drawing things behind Gui labels.
  55. self.render2d = NodePath(setupPanda2d(self.win, "render2d"))
  56. # Set up another 2-d layer for drawing the Gui labels themselves.
  57. self.renderGui = NodePath(setupPanda2d(self.win, "renderGui"))
  58. # Set up an auxiliary 3-d layer for rendering floating heads
  59. # or other 3-d objects on top of text or widgets in the 2-d
  60. # layer. We set it up with a camera that specifically shares
  61. # the projection with the default camera, so that when we
  62. # change the default camera's parameters, it changes this one
  63. # too.
  64. self.renderAux = NodePath(NamedNode('renderAux'))
  65. self.camAux = self.renderAux.attachNewNode(Camera('camAux'))
  66. self.camAux.node().shareProjection(self.cam.node().getProjection())
  67. addRenderLayer(self.win, self.renderAux.node(), self.camAux.node())
  68. # We create both a MouseAndKeyboard object and a MouseWatcher object
  69. # for the window. The MouseAndKeyboard generates mouse events and
  70. # mouse button/keyboard events; the MouseWatcher passes them through
  71. # unchanged when the mouse is not over a 2-d button, and passes
  72. # nothing through when the mouse *is* over a 2-d button. Therefore,
  73. # objects that don't want to get events when the mouse is over a
  74. # button, like the driveInterface, should be parented to
  75. # mouseWatcher, while objects that want events in all cases, like the
  76. # chat interface, should be parented to mak.
  77. self.mak = self.dataRoot.attachNewNode(MouseAndKeyboard(self.win, 0, 'mak'))
  78. self.mouseWatcher = self.mak.attachNewNode(MouseWatcher('mouseWatcher'))
  79. self.trackball = self.dataUnused.attachNewNode(Trackball('trackball'))
  80. self.drive = self.dataUnused.attachNewNode(DriveInterface('drive'))
  81. self.mouse2cam = self.dataUnused.attachNewNode(Transform2SG('mouse2cam'))
  82. self.mouse2cam.node().setArc(self.camera.getBottomArc())
  83. self.useDrive()
  84. self.buttonThrower = self.mouseWatcher.attachNewNode(ButtonThrower())
  85. if (ShowBase.notify == None):
  86. ShowBase.notify = directNotify.newCategory("ShowBase")
  87. self.loader = Loader.Loader(self)
  88. self.eventMgr = eventMgr
  89. self.messenger = messenger
  90. self.taskMgr = taskMgr
  91. # Particle manager
  92. self.particleMgr = particleMgr
  93. self.particleMgr.setFrameStepping(1)
  94. self.particleMgrEnabled = 0
  95. # Physics manager
  96. self.physicsMgr = physicsMgr
  97. self.integrator = LinearEulerIntegrator.LinearEulerIntegrator()
  98. self.physicsMgr.attachLinearIntegrator(self.integrator)
  99. self.physicsMgrEnabled = 0
  100. self.createAudioManager()
  101. self.createRootPanel()
  102. self.createStats()
  103. self.restart()
  104. def enableParticles(self):
  105. """enableParticles(self)"""
  106. self.particleMgrEnabled = 1
  107. self.physicsMgrEnabled = 1
  108. self.taskMgr.removeTasksNamed('manager-update')
  109. self.taskMgr.spawnTaskNamed(Task.Task(self.__updateManagers),
  110. 'manager-update')
  111. def disableParticles(self):
  112. """enableParticles(self)"""
  113. self.particleMgrEnabled = 0
  114. self.physicsMgrEnabled = 0
  115. self.taskMgr.removeTasksNamed('manager-update')
  116. def __updateManagers(self, state):
  117. """__updateManagers(self)"""
  118. dt = min(globalClock.getDt(), 0.1)
  119. if (self.particleMgrEnabled == 1):
  120. self.particleMgr.doParticles(dt)
  121. if (self.physicsMgrEnabled == 1):
  122. self.physicsMgr.doPhysics(dt)
  123. return Task.cont
  124. def createStats(self):
  125. # You must specify a pstats-host in your configrc
  126. # The default is localhost
  127. if self.wantStats:
  128. PStatClient.getGlobalPstats().connect()
  129. def createAudioManager(self):
  130. if self.wantSound:
  131. AudioManager.spawnUpdate()
  132. def createRootPanel(self):
  133. if self.wantTk:
  134. from TkGlobal import *
  135. self.tkroot = Pmw.initialise()
  136. else:
  137. self.tkroot = None
  138. def igloop(self, state):
  139. self.win.update()
  140. return Task.cont
  141. def restart(self):
  142. self.shutdown()
  143. self.taskMgr.spawnTaskNamed(Task.Task(self.igloop), 'igloop')
  144. self.eventMgr.restart()
  145. def shutdown(self):
  146. self.taskMgr.removeTasksNamed('igloop')
  147. self.eventMgr.shutdown()
  148. def toggleBackface(self):
  149. toggleBackface(self.initialState)
  150. def toggleTexture(self):
  151. toggleTexture(self.initialState)
  152. def toggleWireframe(self):
  153. toggleWireframe(self.initialState)
  154. def disableMouse(self):
  155. self.drive.reparentTo(self.dataUnused)
  156. self.trackball.reparentTo(self.dataUnused)
  157. self.mouse2cam.reparentTo(self.dataUnused)
  158. self.mouseInterface = None
  159. self.mouseInterfaceNode = None
  160. def setMouseOnArc(self, newArc):
  161. self.mouse2cam.node().setArc(newArc)
  162. def useDrive(self):
  163. """
  164. Toggle mouse action to drive mode
  165. """
  166. # Get rid of the trackball
  167. self.trackball.reparentTo(self.dataUnused)
  168. # Update the mouseInterface to point to the drive
  169. self.mouseInterface = self.drive
  170. self.mouseInterfaceNode = self.mouseInterface.getBottomNode()
  171. self.drive.node().reset()
  172. self.drive.reparentTo(self.mouseWatcher)
  173. # Hookup the drive to the camera
  174. self.mouse2cam.reparentTo(self.drive)
  175. # Set the height to a good eyeheight
  176. self.drive.node().setZ(4.0)
  177. def useTrackball(self):
  178. """
  179. Toggle mouse action to trackball mode
  180. """
  181. # Get rid of the drive
  182. self.drive.reparentTo(self.dataUnused)
  183. # Update the mouseInterface to point to the trackball
  184. self.mouseInterface = self.trackball
  185. self.mouseInterfaceNode = self.mouseInterface.getBottomNode()
  186. # Hookup the trackball to the camera
  187. self.trackball.reparentTo(self.mouseWatcher)
  188. self.mouse2cam.reparentTo(self.trackball)
  189. def run(self):
  190. self.taskMgr.run()