Advertisement
Guest User

croxis

a guest
Jun 4th, 2009
154
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.29 KB | None | 0 0
  1. """
  2. Pixel based window system for Panda3D
  3. """
  4.  
  5. from pandac.PandaModules import TextNode
  6. from direct.gui.DirectGui import *
  7. from direct.showbase import DirectObject
  8. import direct.directbase.DirectStart
  9.  
  10. # Constants
  11. # Text heigh in px
  12. TEXT_HEIGHT = 25
  13. BUTTON_HEIGHT = 25
  14. ENTRY_HEIGHT = 25
  15.  
  16. # a task that keeps a node at the position of the mouse-cursor
  17. def mouseNodeTask( task ):
  18. if base.mouseWatcherNode.hasMouse():
  19. x=base.mouseWatcherNode.getMouseX()
  20. y=base.mouseWatcherNode.getMouseY()
  21. # the mouse position is read relative to render2d, so set it accordingly
  22. aspect2dMouseNode.setPos( render2d, x, 0, y )
  23. return task.cont
  24. # maybe we should check if aspect2d doesnt already contain the aspect2dMouseNode
  25. aspect2dMouseNode = aspect2d.attachNewNode( 'aspect2dMouseNode', sort = 999999 )
  26. taskMgr.add( mouseNodeTask, 'mouseNodeTask' )
  27.  
  28.  
  29. class Window(DirectObject.DirectObject):
  30. """
  31. Base window for pixel based GUI
  32. Positioning reparented to the bottom left corner of the screen.
  33. Based on Hypnos post here http://www.panda3d.org/phpbb2/viewtopic.php?t=4861
  34. """
  35. def __init__ (self, title="Title", size=(0,0), position=(0,0), center=False, xcenter=False, ycenter=False):
  36. """
  37. size: size in absolute pixlesish
  38. widgets: widgets contained in this window
  39. position: Window Coordinates in px
  40. center: If true the window will be initially drawn in the center of the screen overriding any position parameter
  41. xcenter: If true the widow will be centered on the xaxis
  42. ycenter: If true the window will be centered on the yaxis
  43. """
  44. # Accept main window resize events and redraws the widgets
  45. self.accept('window-event', self.draw)
  46.  
  47. self.title_height = 30
  48. # Generate title bar
  49. self.window_title = title
  50. self.widgets = {}
  51. self.size = size
  52.  
  53. # Main container
  54. if center:
  55. centerxpx = base.win.getXSize()/2
  56. centerypx = base.win.getYSize()/2
  57. self.windowPosition = [centerxpx, centerypx]
  58. elif xcenter:
  59. centerxpx = base.win.getXSize()/2
  60. self.windowPosition = [centerxpx, position[1]]
  61. elif ycenter:
  62. centerypx = base.win.getYSize()/2
  63. self.windowPosition = [position[0], centerypx]
  64. else:
  65. self.windowPosition = [position[0], position[1]]
  66.  
  67. xpos = self.px2float(self.windowPosition[0])
  68. ypos = self.px2float(self.windowPosition[1])
  69. self.window = DirectFrame(
  70. parent = base.a2dBottomLeft,
  71. pos = (xpos, 0, ypos)
  72. )
  73. print "Self.Window", self.window
  74. #self.window.initialiseoptions(self.window)
  75. self.window.setBin("gui-popup", 50)
  76.  
  77. # Title bar
  78. ypos = self.px2float(self.size[1]/2 + self.title_height/2)
  79. self.titleBar = DirectButton(
  80. parent = self.window,
  81. relief = DGG.FLAT,
  82. pos = (0, 0, ypos)
  83. )
  84. self.titleBar['frameColor'] = (.1,.7,.1,1)
  85. text = TextNode("WindowTitleTextNode")
  86. text.setText(title)
  87. text.setAlign(TextNode.ACenter)
  88. self.textNodePath = self.titleBar.attachNewNode(text)
  89. self.textNodePath.setScale(0.07)
  90.  
  91. self.titleBar.bind(DGG.B1PRESS,self.startWindowDrag)
  92.  
  93. # Set up
  94. self.draw()
  95.  
  96. def draw(self, args=None):
  97. """
  98. Draws the window
  99. """
  100. # Draw window
  101. left = -self.px2float(self.size[0]/2)
  102. right = -left
  103. bottom = -self.px2float(self.size[1]/2)
  104. top = -bottom
  105. print "Self.Window", self.window
  106. self.window['frameSize'] = (left, right, bottom, top)
  107.  
  108. # Rescale bottom for the title bar
  109. ypos = self.px2float(self.size[1]/2 + self.title_height/2)
  110. self.titleBar.setPos(0, 0, ypos)
  111. top = self.px2float(self.title_height/2)
  112. bottom = -top
  113. self.titleBar['frameSize'] = (left, right, bottom, top)
  114.  
  115. # Adjust title scale
  116. self.textNodePath.setScale(self.px2float(self.title_height/2))
  117. for widget in self.widgets:
  118. pos = self.widgets[widget]
  119. widget.setPos(self.px2float(pos[0]), 0, self.px2float(pos[1]))
  120. widget.setScale(self.px2float(BUTTON_HEIGHT)/2)
  121.  
  122. def px2float(self, px):
  123. """
  124. Converts an absolute pixel coordinate to the aspect2d float coordinate
  125. Aspect2d scale is dependent or width or height, whichever is shorter
  126. """
  127. # Find the shorter side and use that resolution
  128. xrez = base.win.getXSize()
  129. yrez = base.win.getYSize()
  130. if xrez > yrez:
  131. rez = yrez
  132. else:
  133. rez = xrez
  134. return float(px)/float(rez)*2
  135.  
  136. def float2px(self, value):
  137. """
  138. Converts aspect2d float to px vaule
  139. """
  140. # Find the shorter side and use that resolution
  141. xrez = base.win.getXSize()
  142. yrez = base.win.getYSize()
  143. if xrez > yrez:
  144. rez = yrez
  145. else:
  146. rez = xrez
  147. return float(value)*float(rez)*2
  148.  
  149. def startWindowDrag( self, param ):
  150. self.window.wrtReparentTo( aspect2dMouseNode )
  151. self.window.ignoreAll()
  152. self.window.accept( 'mouse1-up', self.stopWindowDrag )
  153. def stopWindowDrag( self, param=None ):
  154. # this is called 2 times (bug), so make sure it's not already parented to aspect2d
  155. if self.window.getParent() != base.a2dBottomLeft:
  156. self.window.wrtReparentTo( base.a2dBottomLeft )
  157.  
  158. def addButton(self, button, pos=(0,0)):
  159. """
  160. Adds a passed DirectButton
  161. """
  162. # TODO: Adjust coordinate system to bottom left instead of center
  163. HEIGHT = 40 # height of button in px
  164. button.reparentTo(self.window)
  165. button.setScale(self.px2float(BUTTON_HEIGHT)/2)
  166. button.setPos(self.px2float(pos[0]), 0, self.px2float(pos[1]))
  167. self.widgets[button] = pos
  168.  
  169. def addEntry(self, entry, pos = (0,0)):
  170. """
  171. Adds a passed DirectEntry
  172. """
  173. HEIGHT = 40 # height of button in px
  174. entry.reparentTo(self.window)
  175. entry.setScale(self.px2float(ENTRY_HEIGHT)/2)
  176. entry.setPos(self.px2float(pos[0]), 0, self.px2float(pos[1]))
  177. self.widgets[entry] = pos
  178.  
  179. def destroy(self):
  180. self.window.destroy()
  181.  
  182.  
  183. class DialogueWindow(Window):
  184. """
  185. Generates a dialogue window with custom Direct Objects
  186. Scales to encompass text and buttons
  187. """
  188. def __init__(self, text, title = "Title", buttons = [], entries = []):
  189. """
  190. text: Dialouge text
  191. title: window
  192. buttons: [{param1: value, param2: value}]
  193. title_height: Height in px
  194. padding:
  195. """
  196. Window.__init__(self, title=title, size=(0,0), center = True)
  197. #self.initialiseoptions(Window)
  198. self.textBox = DirectLabel(text = text, parent = self.window)
  199. self.padding = 5
  200. # Generate Forms
  201. x = 0
  202. for entry in entries:
  203. name = "Form" + str(x)
  204. # Checkers stuff
  205. try:
  206. command = entry['command']
  207. except:
  208. command = None
  209.  
  210. entry = DirectEntry(parent = self.window, command = command, pos = (0,0,0))
  211. self.addEntry(entry)
  212.  
  213. # Generate buttons
  214. x = 0
  215. for b in buttons:
  216. name = "Button" + str(x)
  217. try:
  218. text = b['text']
  219. except:
  220. text = None
  221. try:
  222. command = b['command']
  223. except:
  224. command = None
  225. button = DirectButton(parent = self.window, text = text, command = command, pos = (0,0,0))
  226. #button = DirectButton(parent = self.window, text = text, command = command)
  227. self.addButton(button)
  228.  
  229. #Calculate size and position elements
  230. # position variable is a moving variable for y-axis positioning of various items in float
  231. yPosition = 0
  232.  
  233. textScale = self.px2float(TEXT_HEIGHT/2)
  234. self.textBox.setScale(textScale)
  235. textBounds = self.textBox.getBounds()
  236. leftWindow = textBounds[0] * textScale
  237. rightWindow = textBounds[1] * textScale
  238. bottomWindow = textBounds[2] * textScale
  239. topWindow = textBounds[3] * textScale
  240.  
  241. yPosition -= bottomWindow - self.px2float(self.padding+20)
  242.  
  243. # Any entry fields
  244. for widget in self.widgets:
  245. if isinstance(widget, DirectEntry):
  246. widget.setPos(0,0, yPosition)
  247. yPosition -= widget.getBounds[2]
  248.  
  249. # Buttons will go under the text
  250. # Itterate through buttons, add their length plus padding
  251. length = self.px2float(self.padding)
  252. for widget in self.widgets:
  253. if isinstance(widget, DirectButton):
  254. bounds = widget.getBounds()
  255. length += bounds[0] - bounds[1]
  256. length += self.px2float(self.padding)
  257. # Reposition buttons, below text, going from left to right
  258. position = [-length/2, yPosition]
  259. #print 'Position', position
  260. for widget in self.widgets:
  261. if isinstance(widget, DirectButton):
  262. self.widgets[widget] = (self.float2px(position[0]), self.float2px(position[1]))
  263. #widget.setPos(position[0]/self.px2float(HEIGHT)/2, 0, position[1]/self.px2float(HEIGHT)/2)
  264. #widget.setPos(-10000, -1, -10000)
  265. #widget.place()
  266. #print 'GetPos', widget.getPos()
  267. #print 'GetScale', widget.getScale()
  268. print 'Button Position', (self.float2px(position[0]), self.float2px(position[1]))
  269. self.size = (self.float2px(rightWindow/2.0), 100)
  270. self.draw()
  271. class GUIController(DirectObject.DirectObject):
  272. '''
  273. Manages subwindows. Use this to make common windows to prevent import hell
  274. '''
  275. def __init__(self, script, language = "english"):
  276. """
  277. Script be the language database
  278. """
  279. self.accept('startIntro', self.intro)
  280. self.script = script
  281. self.language = language
  282.  
  283. def intro(self):
  284. text = "Test"
  285. self.dialog = DialogueWindow(
  286. text = text,
  287. title='Greetings',
  288. buttons = [{'text': "OK", 'command': self.intro2}])
  289. def intro2(self):
  290. print "Moving to next screen"
  291. self.dialog.window.destroy()
  292. text = self.script.getText('TXT_AI_GREET2', self.language)
  293. messenger.send('say',[text])
  294. self.dialog = DialogueWindow(
  295. text = text,
  296. title='Greetings',
  297. buttons = [{'text': self.script.getText('TXT_UI_OK', self.language), 'command': self.intro3}])
  298. def intro3(self):
  299. """
  300. Just tities up
  301. """
  302. # TODO: Get form window to finish these values
  303. self.playerName = 'fred'
  304. self.AIName = 'Ralf'
  305. print "Finished intro"
  306. self.dialog.window.destroy()
  307. messenger.send('sendNameRequest', [self.playerName, self.AIName])
  308.  
  309. def mainMenu(self):
  310. """
  311. Creates main menu
  312. """
  313. self.mainMenu = Window(title = "Open Outpost", size=(100, 100), center = True)
  314. newGame = DirectButton(text= "New Game", command=self.newGame)
  315. self.mainMenu.addButton(newGame, (0, 30))
  316.  
  317. def newGame(self):
  318. #self.mainMenu.window.destroy()
  319. self.mainMenu.destroy()
  320. messenger.send('startIntro')
  321.  
  322.  
  323. def main():
  324. gui = GUIController(None)
  325. #gui.intro()
  326. gui.mainMenu()
  327. run()
  328.  
  329.  
  330. if __name__ == '__main__':
  331. main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement