Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """
- Pixel based window system for Panda3D
- """
- from pandac.PandaModules import TextNode
- from direct.gui.DirectGui import *
- from direct.showbase import DirectObject
- import direct.directbase.DirectStart
- # Constants
- # Text heigh in px
- TEXT_HEIGHT = 25
- BUTTON_HEIGHT = 25
- ENTRY_HEIGHT = 25
- # a task that keeps a node at the position of the mouse-cursor
- def mouseNodeTask( task ):
- if base.mouseWatcherNode.hasMouse():
- x=base.mouseWatcherNode.getMouseX()
- y=base.mouseWatcherNode.getMouseY()
- # the mouse position is read relative to render2d, so set it accordingly
- aspect2dMouseNode.setPos( render2d, x, 0, y )
- return task.cont
- # maybe we should check if aspect2d doesnt already contain the aspect2dMouseNode
- aspect2dMouseNode = aspect2d.attachNewNode( 'aspect2dMouseNode', sort = 999999 )
- taskMgr.add( mouseNodeTask, 'mouseNodeTask' )
- class Window(DirectObject.DirectObject):
- """
- Base window for pixel based GUI
- Positioning reparented to the bottom left corner of the screen.
- Based on Hypnos post here http://www.panda3d.org/phpbb2/viewtopic.php?t=4861
- """
- def __init__ (self, title="Title", size=(0,0), position=(0,0), center=False, xcenter=False, ycenter=False):
- """
- size: size in absolute pixlesish
- widgets: widgets contained in this window
- position: Window Coordinates in px
- center: If true the window will be initially drawn in the center of the screen overriding any position parameter
- xcenter: If true the widow will be centered on the xaxis
- ycenter: If true the window will be centered on the yaxis
- """
- # Accept main window resize events and redraws the widgets
- self.accept('window-event', self.draw)
- self.title_height = 30
- # Generate title bar
- self.window_title = title
- self.widgets = {}
- self.size = size
- # Main container
- if center:
- centerxpx = base.win.getXSize()/2
- centerypx = base.win.getYSize()/2
- self.windowPosition = [centerxpx, centerypx]
- elif xcenter:
- centerxpx = base.win.getXSize()/2
- self.windowPosition = [centerxpx, position[1]]
- elif ycenter:
- centerypx = base.win.getYSize()/2
- self.windowPosition = [position[0], centerypx]
- else:
- self.windowPosition = [position[0], position[1]]
- xpos = self.px2float(self.windowPosition[0])
- ypos = self.px2float(self.windowPosition[1])
- self.window = DirectFrame(
- parent = base.a2dBottomLeft,
- pos = (xpos, 0, ypos)
- )
- print "Self.Window", self.window
- #self.window.initialiseoptions(self.window)
- self.window.setBin("gui-popup", 50)
- # Title bar
- ypos = self.px2float(self.size[1]/2 + self.title_height/2)
- self.titleBar = DirectButton(
- parent = self.window,
- relief = DGG.FLAT,
- pos = (0, 0, ypos)
- )
- self.titleBar['frameColor'] = (.1,.7,.1,1)
- text = TextNode("WindowTitleTextNode")
- text.setText(title)
- text.setAlign(TextNode.ACenter)
- self.textNodePath = self.titleBar.attachNewNode(text)
- self.textNodePath.setScale(0.07)
- self.titleBar.bind(DGG.B1PRESS,self.startWindowDrag)
- # Set up
- self.draw()
- def draw(self, args=None):
- """
- Draws the window
- """
- # Draw window
- left = -self.px2float(self.size[0]/2)
- right = -left
- bottom = -self.px2float(self.size[1]/2)
- top = -bottom
- print "Self.Window", self.window
- self.window['frameSize'] = (left, right, bottom, top)
- # Rescale bottom for the title bar
- ypos = self.px2float(self.size[1]/2 + self.title_height/2)
- self.titleBar.setPos(0, 0, ypos)
- top = self.px2float(self.title_height/2)
- bottom = -top
- self.titleBar['frameSize'] = (left, right, bottom, top)
- # Adjust title scale
- self.textNodePath.setScale(self.px2float(self.title_height/2))
- for widget in self.widgets:
- pos = self.widgets[widget]
- widget.setPos(self.px2float(pos[0]), 0, self.px2float(pos[1]))
- widget.setScale(self.px2float(BUTTON_HEIGHT)/2)
- def px2float(self, px):
- """
- Converts an absolute pixel coordinate to the aspect2d float coordinate
- Aspect2d scale is dependent or width or height, whichever is shorter
- """
- # Find the shorter side and use that resolution
- xrez = base.win.getXSize()
- yrez = base.win.getYSize()
- if xrez > yrez:
- rez = yrez
- else:
- rez = xrez
- return float(px)/float(rez)*2
- def float2px(self, value):
- """
- Converts aspect2d float to px vaule
- """
- # Find the shorter side and use that resolution
- xrez = base.win.getXSize()
- yrez = base.win.getYSize()
- if xrez > yrez:
- rez = yrez
- else:
- rez = xrez
- return float(value)*float(rez)*2
- def startWindowDrag( self, param ):
- self.window.wrtReparentTo( aspect2dMouseNode )
- self.window.ignoreAll()
- self.window.accept( 'mouse1-up', self.stopWindowDrag )
- def stopWindowDrag( self, param=None ):
- # this is called 2 times (bug), so make sure it's not already parented to aspect2d
- if self.window.getParent() != base.a2dBottomLeft:
- self.window.wrtReparentTo( base.a2dBottomLeft )
- def addButton(self, button, pos=(0,0)):
- """
- Adds a passed DirectButton
- """
- # TODO: Adjust coordinate system to bottom left instead of center
- HEIGHT = 40 # height of button in px
- button.reparentTo(self.window)
- button.setScale(self.px2float(BUTTON_HEIGHT)/2)
- button.setPos(self.px2float(pos[0]), 0, self.px2float(pos[1]))
- self.widgets[button] = pos
- def addEntry(self, entry, pos = (0,0)):
- """
- Adds a passed DirectEntry
- """
- HEIGHT = 40 # height of button in px
- entry.reparentTo(self.window)
- entry.setScale(self.px2float(ENTRY_HEIGHT)/2)
- entry.setPos(self.px2float(pos[0]), 0, self.px2float(pos[1]))
- self.widgets[entry] = pos
- def destroy(self):
- self.window.destroy()
- class DialogueWindow(Window):
- """
- Generates a dialogue window with custom Direct Objects
- Scales to encompass text and buttons
- """
- def __init__(self, text, title = "Title", buttons = [], entries = []):
- """
- text: Dialouge text
- title: window
- buttons: [{param1: value, param2: value}]
- title_height: Height in px
- padding:
- """
- Window.__init__(self, title=title, size=(0,0), center = True)
- #self.initialiseoptions(Window)
- self.textBox = DirectLabel(text = text, parent = self.window)
- self.padding = 5
- # Generate Forms
- x = 0
- for entry in entries:
- name = "Form" + str(x)
- # Checkers stuff
- try:
- command = entry['command']
- except:
- command = None
- entry = DirectEntry(parent = self.window, command = command, pos = (0,0,0))
- self.addEntry(entry)
- # Generate buttons
- x = 0
- for b in buttons:
- name = "Button" + str(x)
- try:
- text = b['text']
- except:
- text = None
- try:
- command = b['command']
- except:
- command = None
- button = DirectButton(parent = self.window, text = text, command = command, pos = (0,0,0))
- #button = DirectButton(parent = self.window, text = text, command = command)
- self.addButton(button)
- #Calculate size and position elements
- # position variable is a moving variable for y-axis positioning of various items in float
- yPosition = 0
- textScale = self.px2float(TEXT_HEIGHT/2)
- self.textBox.setScale(textScale)
- textBounds = self.textBox.getBounds()
- leftWindow = textBounds[0] * textScale
- rightWindow = textBounds[1] * textScale
- bottomWindow = textBounds[2] * textScale
- topWindow = textBounds[3] * textScale
- yPosition -= bottomWindow - self.px2float(self.padding+20)
- # Any entry fields
- for widget in self.widgets:
- if isinstance(widget, DirectEntry):
- widget.setPos(0,0, yPosition)
- yPosition -= widget.getBounds[2]
- # Buttons will go under the text
- # Itterate through buttons, add their length plus padding
- length = self.px2float(self.padding)
- for widget in self.widgets:
- if isinstance(widget, DirectButton):
- bounds = widget.getBounds()
- length += bounds[0] - bounds[1]
- length += self.px2float(self.padding)
- # Reposition buttons, below text, going from left to right
- position = [-length/2, yPosition]
- #print 'Position', position
- for widget in self.widgets:
- if isinstance(widget, DirectButton):
- self.widgets[widget] = (self.float2px(position[0]), self.float2px(position[1]))
- #widget.setPos(position[0]/self.px2float(HEIGHT)/2, 0, position[1]/self.px2float(HEIGHT)/2)
- #widget.setPos(-10000, -1, -10000)
- #widget.place()
- #print 'GetPos', widget.getPos()
- #print 'GetScale', widget.getScale()
- print 'Button Position', (self.float2px(position[0]), self.float2px(position[1]))
- self.size = (self.float2px(rightWindow/2.0), 100)
- self.draw()
- class GUIController(DirectObject.DirectObject):
- '''
- Manages subwindows. Use this to make common windows to prevent import hell
- '''
- def __init__(self, script, language = "english"):
- """
- Script be the language database
- """
- self.accept('startIntro', self.intro)
- self.script = script
- self.language = language
- def intro(self):
- text = "Test"
- self.dialog = DialogueWindow(
- text = text,
- title='Greetings',
- buttons = [{'text': "OK", 'command': self.intro2}])
- def intro2(self):
- print "Moving to next screen"
- self.dialog.window.destroy()
- text = self.script.getText('TXT_AI_GREET2', self.language)
- messenger.send('say',[text])
- self.dialog = DialogueWindow(
- text = text,
- title='Greetings',
- buttons = [{'text': self.script.getText('TXT_UI_OK', self.language), 'command': self.intro3}])
- def intro3(self):
- """
- Just tities up
- """
- # TODO: Get form window to finish these values
- self.playerName = 'fred'
- self.AIName = 'Ralf'
- print "Finished intro"
- self.dialog.window.destroy()
- messenger.send('sendNameRequest', [self.playerName, self.AIName])
- def mainMenu(self):
- """
- Creates main menu
- """
- self.mainMenu = Window(title = "Open Outpost", size=(100, 100), center = True)
- newGame = DirectButton(text= "New Game", command=self.newGame)
- self.mainMenu.addButton(newGame, (0, 30))
- def newGame(self):
- #self.mainMenu.window.destroy()
- self.mainMenu.destroy()
- messenger.send('startIntro')
- def main():
- gui = GUIController(None)
- #gui.intro()
- gui.mainMenu()
- run()
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement