ViewPort.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. """
  2. Contains classes useful for 3D viewports.
  3. Originally written by pro-rsoft,
  4. Modified by gjeon.
  5. Modified by Summer 2010 Carnegie Mellon University ETC PandaLE team: fixed a bug in Viewport.Close
  6. """
  7. __all__ = ["Viewport", "ViewportManager"]
  8. from direct.showbase.DirectObject import DirectObject
  9. from direct.directtools.DirectGrid import DirectGrid
  10. from direct.showbase.ShowBase import WindowControls
  11. from direct.directtools.DirectGlobals import *
  12. from WxPandaWindow import WxPandaWindow
  13. from panda3d.core import OrthographicLens, Point3, Plane, CollisionPlane, CollisionNode, NodePath
  14. import wx
  15. HORIZONTAL = wx.SPLIT_HORIZONTAL
  16. VERTICAL = wx.SPLIT_VERTICAL
  17. CREATENEW = 99
  18. VPLEFT = 10
  19. VPFRONT = 11
  20. VPTOP = 12
  21. VPPERSPECTIVE = 13
  22. class ViewportManager:
  23. """Manages the global viewport stuff."""
  24. viewports = []
  25. gsg = None
  26. @staticmethod
  27. def initializeAll(*args, **kwargs):
  28. """Calls initialize() on all the viewports."""
  29. for v in ViewportManager.viewports:
  30. v.initialize(*args, **kwargs)
  31. @staticmethod
  32. def updateAll(*args, **kwargs):
  33. """Calls Update() on all the viewports."""
  34. for v in ViewportManager.viewports:
  35. v.Update(*args, **kwargs)
  36. @staticmethod
  37. def layoutAll(*args, **kwargs):
  38. """Calls Layout() on all the viewports."""
  39. for v in ViewportManager.viewports:
  40. v.Layout(*args, **kwargs)
  41. class Viewport(WxPandaWindow, DirectObject):
  42. """Class representing a 3D Viewport."""
  43. CREATENEW = CREATENEW
  44. VPLEFT = VPLEFT
  45. VPFRONT = VPFRONT
  46. VPTOP = VPTOP
  47. VPPERSPECTIVE = VPPERSPECTIVE
  48. def __init__(self, name, *args, **kwargs):
  49. self.name = name
  50. DirectObject.__init__(self)
  51. kwargs['gsg'] = ViewportManager.gsg
  52. WxPandaWindow.__init__(self, *args, **kwargs)
  53. ViewportManager.viewports.append(self)
  54. if ViewportManager.gsg == None:
  55. ViewportManager.gsg = self.win.getGsg()
  56. self.camera = None
  57. self.lens = None
  58. self.camPos = None
  59. self.camLookAt = None
  60. self.initialized = False
  61. self.grid = None
  62. self.collPlane = None
  63. def initialize(self):
  64. self.Update()
  65. if self.win:
  66. self.cam2d = base.makeCamera2d(self.win)
  67. self.cam2d.node().setCameraMask(LE_CAM_MASKS[self.name])
  68. self.cam = base.camList[-1]
  69. self.camera = render.attachNewNode(self.name)
  70. #self.camera.setName(self.name)
  71. #self.camera.reparentTo(render)
  72. self.cam.reparentTo(self.camera)
  73. self.camNode = self.cam.node()
  74. self.camNode.setCameraMask(LE_CAM_MASKS[self.name])
  75. self.bt = base.setupMouse(self.win, True)
  76. self.bt.node().setPrefix('_le_%s_'%self.name[:3])
  77. mw = self.bt.getParent()
  78. mk = mw.getParent()
  79. winCtrl = WindowControls(
  80. self.win, mouseWatcher=mw,
  81. cam=self.camera,
  82. camNode = self.camNode,
  83. cam2d=None,
  84. mouseKeyboard =mk,
  85. grid = self.grid)
  86. base.setupWindowControls(winCtrl)
  87. self.initialized = True
  88. if self.lens != None: self.cam.node().setLens(self.lens)
  89. if self.camPos != None: self.camera.setPos(self.camPos)
  90. if self.camLookAt != None: self.camera.lookAt(self.camLookAt)
  91. self.camLens = self.camNode.getLens()
  92. if self.name in ['top', 'front', 'left']:
  93. x = self.ClientSize.GetWidth() * 0.1
  94. y = self.ClientSize.GetHeight() * 0.1
  95. self.camLens.setFilmSize(x, y)
  96. self.Bind(wx.EVT_SIZE, self.onSize)
  97. ## self.accept("wheel_down", self.zoomOut)
  98. ## self.accept("wheel_up", self.zoomIn)
  99. ## self.accept("page_down", self.zoomOut)
  100. ## self.accept("page_down-repeat", self.zoomOut)
  101. ## self.accept("page_up", self.zoomIn)
  102. ## self.accept("page_up-repeat", self.zoomIn)
  103. #self.accept("mouse3", self.onRightDown)
  104. def Close(self):
  105. """Closes the viewport."""
  106. if self.initialized:
  107. wx.Window.Close(self)
  108. #base.closeWindow(self.win)
  109. ViewportManager.viewports.remove(self)
  110. def onSize(self, evt):
  111. """Invoked when the viewport is resized."""
  112. WxPandaWindow.onSize(self, evt)
  113. if self.win != None:
  114. newWidth = self.ClientSize.GetWidth()
  115. newHeight = self.ClientSize.GetHeight()
  116. if hasattr(base, "direct") and base.direct:
  117. for dr in base.direct.drList:
  118. if dr.camNode == self.camNode:
  119. dr.updateFilmSize(newWidth, newHeight)
  120. break
  121. def onRightDown(self, evt = None):
  122. """Invoked when the viewport is right-clicked."""
  123. if evt == None:
  124. mpos = wx.GetMouseState()
  125. mpos = self.ScreenToClient((mpos.x, mpos.y))
  126. else:
  127. mpos = evt.GetPosition()
  128. self.Update()
  129. #self.PopupMenu(self.menu, mpos)
  130. #self.menu.Destroy()
  131. def zoomOut(self):
  132. self.camera.setY(self.camera, -MOUSE_ZOO_SPEED)
  133. def zoomIn(self):
  134. self.camera.setY(self.camera, MOUSE_ZOOM_SPEED)
  135. @staticmethod
  136. def make(parent, vpType = None):
  137. """Safe constructor that also takes CREATENEW, VPLEFT, VPTOP, etc."""
  138. if vpType == None or vpType == CREATENEW:
  139. return Viewport(parent)
  140. if isinstance(vpType, Viewport): return vpType
  141. if vpType == VPLEFT: return Viewport.makeLeft(parent)
  142. if vpType == VPFRONT: return Viewport.makeFront(parent)
  143. if vpType == VPTOP: return Viewport.makeTop(parent)
  144. if vpType == VPPERSPECTIVE: return Viewport.makePerspective(parent)
  145. raise TypeError("Unknown viewport type: %s" % vpType)
  146. @staticmethod
  147. def makeOrthographic(parent, name, campos):
  148. v = Viewport(name, parent)
  149. v.lens = OrthographicLens()
  150. v.lens.setFilmSize(30)
  151. v.camPos = campos
  152. v.camLookAt = Point3(0, 0, 0)
  153. v.grid = DirectGrid(parent=render)
  154. if name == 'left':
  155. v.grid.setHpr(0, 0, 90)
  156. collPlane = CollisionNode('LeftGridCol')
  157. collPlane.addSolid(CollisionPlane(Plane(1, 0, 0, 0)))
  158. collPlane.setIntoCollideMask(BitMask32.bit(21))
  159. v.collPlane = NodePath(collPlane)
  160. v.collPlane.wrtReparentTo(v.grid)
  161. #v.grid.gridBack.findAllMatches("**/+GeomNode")[0].setName("_leftViewGridBack")
  162. LE_showInOneCam(v.grid, name)
  163. elif name == 'front':
  164. v.grid.setHpr(90, 0, 90)
  165. collPlane = CollisionNode('FrontGridCol')
  166. collPlane.addSolid(CollisionPlane(Plane(0, -1, 0, 0)))
  167. collPlane.setIntoCollideMask(BitMask32.bit(21))
  168. v.collPlane = NodePath(collPlane)
  169. v.collPlane.wrtReparentTo(v.grid)
  170. #v.grid.gridBack.findAllMatches("**/+GeomNode")[0].setName("_frontViewGridBack")
  171. LE_showInOneCam(v.grid, name)
  172. else:
  173. collPlane = CollisionNode('TopGridCol')
  174. collPlane.addSolid(CollisionPlane(Plane(0, 0, 1, 0)))
  175. collPlane.setIntoCollideMask(BitMask32.bit(21))
  176. v.collPlane = NodePath(collPlane)
  177. v.collPlane.reparentTo(v.grid)
  178. #v.grid.gridBack.findAllMatches("**/+GeomNode")[0].setName("_topViewGridBack")
  179. LE_showInOneCam(v.grid, name)
  180. return v
  181. @staticmethod
  182. def makePerspective(parent):
  183. v = Viewport('persp', parent)
  184. v.camPos = Point3(-19, -19, 19)
  185. v.camLookAt = Point3(0, 0, 0)
  186. v.grid = DirectGrid(parent=render)
  187. collPlane = CollisionNode('PerspGridCol')
  188. collPlane.addSolid(CollisionPlane(Plane(0, 0, 1, 0)))
  189. #oldBitmask = collPlane.getIntoCollideMask()
  190. #collPlane.setIntoCollideMask(BitMask32.bit(21)|oldBitmask)
  191. collPlane.setIntoCollideMask(BitMask32.bit(21))
  192. v.collPlane = NodePath(collPlane)
  193. v.collPlane.reparentTo(v.grid)
  194. collPlane2 = CollisionNode('PerspGridCol2')
  195. collPlane2.addSolid(CollisionPlane(Plane(0, 0, -1, 0)))
  196. #oldBitmask = collPlane2.getIntoCollideMask()
  197. #collPlane2.setIntoCollideMask(BitMask32.bit(21)|oldBitmask)
  198. collPlane2.setIntoCollideMask(BitMask32.bit(21))
  199. v.collPlane2 = NodePath(collPlane2)
  200. v.collPlane2.reparentTo(v.grid)
  201. #v.grid.gridBack.findAllMatches("**/+GeomNode")[0].setName("_perspViewGridBack")
  202. LE_showInOneCam(v.grid, 'persp')
  203. return v
  204. @staticmethod
  205. def makeLeft(parent): return Viewport.makeOrthographic(parent, 'left', Point3(600, 0, 0))
  206. @staticmethod
  207. def makeFront(parent): return Viewport.makeOrthographic(parent, 'front', Point3(0, -600, 0))
  208. @staticmethod
  209. def makeTop(parent): return Viewport.makeOrthographic(parent, 'top', Point3(0, 0, 600))