Example #1
0
class connectGUI():
    def __init__(self, _client):
        # Ref
        self.client = _client

        # create a host button
        self.btnConnect = DirectButton(
            # Scale and position
            scale=0.25,
            pos=(0, 0, 0),
            # Text
            text="Connect",
            # Frame
            # Functionality
            command=self.connect)

        # create the IP input field
        self.txtIP = DirectEntry(
            # scale and position
            pos=(0, 0, -.35),
            scale=0.25,
            width=9,
            # Text
            text="",
            text_align=TextNode.ACenter,
            initialText="127.0.0.1",
            numLines=1,
            # Functionality
            command=self.connect,
            focusInCommand=self.clearText)

        self.hide()

    def show(self):
        self.btnConnect.show()
        self.txtIP.show()

    def hide(self):
        self.btnConnect.hide()
        self.txtIP.hide()

    def clearText(self):
        """Function to clear the text that was previously entered in the
        IP input field"""
        self.txtIP.enterText("")
        #TODO: Do something with the ip

    def connect(self, ip=None):
        """Function which will be called by pressing the connect button
        or hit enter while the focus is on the inut field"""
        if ip == None: ip = self.txtIP.get(True)
        if ip != "":
            if self.client.connectionMgr.connectToServer(ip, 5001):
                gui = lobbyGUI(self.client)
                self.client.gui.hide()
                gui.show()
            else:
                return
Example #2
0
class ThiefHud(GameHud):
    def __init__(self, clientState):
        super().__init__(clientState)
        self.entryLabel = self.label(text='', mayChange=True)

        self.entry = DirectEntry(
            initialText='Type card name...',
            scale=0.05,
            focus=1,
            command=self.useThiefAbility,
            focusInCommand=lambda: self.entry.enterText(''))

        self.entry.hide()

        self.thiefAbilityButton = self.button(
            text="Faction Ability",
            scale=1,
            pos=(0, 0, -1),
            parent=self.endTurnButton,
            command=self.onThiefAbilityButton)

    def useThiefAbility(self, cardname):
        toDiscard = self.toDiscard.getPythonTag('card')
        toSteal = self.toSteal.getPythonTag('card')
        base.clientActions.useThiefAbility(toDiscard, toSteal, cardname)
        base.audioMaster.thiefAbilitySound.play()
        base.mouseHandler.targeting = False
        self.entry.hide()

    def onThiefAbilityButton(self):
        def chooseTarget(target):
            if target is None:
                base.mouseHandler.targeting = False
                showCard(self.toDiscard)
                return
            elif target.getPythonTag('zone') is not base.enemy.facedowns:
                return
            self.toSteal = target
            self.entry.show()

        def chooseDiscard(target):
            if target is None:
                base.mouseHandler.targeting = False
                return
            elif target.getPythonTag('zone') is not base.player.hand:
                return
            self.toDiscard = target
            hideCard(target)
            base.mouseHandler.startTargeting("Choose a target.", chooseTarget)

        base.mouseHandler.startTargeting("Choose a card to discard.",
                                         chooseDiscard)

    def redraw(self):
        super().redraw()

        # TODO: kludge
        if hasattr(self, 'thiefAbilityButton'):
            self.thiefAbilityButton.show()
Example #3
0
class Entry(DirectObject):
    def __init__(self, placeholder, pos, on_enter, focus=False, sort_order=0):
        """
        Object of a simple entry field
        @param placeholder: text to appear in textbox automatically
        @type placeholder: string
        @param pos: where to place the textbox
        @type pos: (float, float, float)
        @param on_enter: function to call upon them submitting a response
        @type on_enter: function
        @param focus: Should the entry auto-focus?
        @type focus: bool
        @param sort_order: Where should Entry display? (Alert is at 1000)
        @type sort_order: int
        """
        DirectObject.__init__(self)
        self.accept('mouse1', self.click_out)
        self.placeholder = placeholder
        self.on_enter = on_enter
        self.entry = DirectEntry(initialText=self.placeholder,
                                 scale=0.05,
                                 focus=focus,
                                 focusOutCommand=self.focus_out,
                                 focusInCommand=self.focus_in,
                                 pos=pos,
                                 sortOrder=sort_order)

    def focus_out(self):
        if self.entry.get() == "":
            self.entry.enterText(self.placeholder)
        else:
            # they typed Something.
            # TODO validate
            self.on_enter(self.entry.get())

    def focus_in(self):
        self.entry.set("")

    def click_out(self):
        self.entry.setFocus()

    def destroy(self):
        self.entry.destroy()
        self.ignoreAll()
Example #4
0
class FileDialog(DirectObject):

    def __init__(self, title, initial_status, callback):
        self.frmLeft = -.7
        self.frmBottom = -.12
        self.frmRight = .7
        self.frmTop = .12
        
        self.frmWidth = self.frmRight - self.frmLeft
        self.frmHeight = self.frmTop - self.frmBottom
        
        self.title = title
        self.initial_status = initial_status
        self.callback = callback
        
        self.result = None
        self.done = 0
            
            
    def activate(self):
        # create main dialog frame
        # Note: frame position references the CENTER of the frame
        self.frm = DirectFrame(
            pos = (0,0,0),
            frameSize = (self.frmLeft, self.frmRight,self.frmBottom, self.frmTop),
            relief = DGG.RIDGE,
            borderWidth = (0.01, 0.01),
            frameColor = (0.6, 0.6, 0.6, 1.0))
        
        self.frm.reparentTo(base.aspect2d)
        
        # Note: wonderfully enough, label position on the other hand
        # references the CENTER of the LEFT border of the label!
        titleLabel = DirectLabel(text = self.title,
            scale = 0.04,
            frameColor = (0.5, 0.5, 0.5, 1),
            relief = DGG.RIDGE,
            borderWidth = (0.01, 0.01),
            text_align = TextNode.ALeft)
            
        titleLabel.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.045)
        titleLabel.reparentTo(self.frm)
        
        sc = .04     
        self.dir_edit_field = DirectEntry(
            text = '',      # prompt text
            scale = sc,
            frameColor = (0.65, 0.65, 0.65, 1),
            command=self.setText,
            width = 32,
            numLines = 1,
            focus = 1,
            focusInCommand=self.efFocusIn,
            )

        self.dir_edit_field.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.13)
        self.dir_edit_field.reparentTo(self.frm)

        self.statusLabel = DirectLabel(text = self.initial_status,
            scale = 0.04,
            frameColor = (0.6, 0.6, 0.6, 1),
            # relief = DGG.RIDGE,
            # borderWidth = (0.01, 0.01),
            text_align = TextNode.ALeft)
            
        self.statusLabel.setPos(-self.frmWidth/2+.02, 0, self.frmHeight/2-.2)
        self.statusLabel.reparentTo(self.frm)

    # call this if you need to run a form before your mainloop starts steppping the taskMgr
    def run(self):
        while self.done != 1:
            taskMgr.step()

        taskMgr.step()          # once more to make the last output from the dialog visible
                                # while we load a zone
        self.frm.removeNode()

    def end(self):
        self.frm.removeNode()
        

    # callback function to set  text: called by the Panda3d taskMgr when the user
    # has entered something into the DirectEntry widget
    def setText(self, textEntered):
        print 'dir_edit_field::setText:', textEntered
        self.done = self.callback(textEntered)
        if self.done != 1:
            self.dir_edit_field['focus'] = 1

                
    #clear the text
    def efFocusIn(self):
        print 'focus in'
        self.dir_edit_field.enterText('')
        
    def setStatus(self, status):
        self.statusLabel['text'] = status
Example #5
0
class MainMenu(DirectObject):
    """This class represents the main menu as seen directly after the
    application has been started"""
    def __init__(self):

        # loading music
        self.menuMusic = loader.loadMusic("music/01Menu.mp3")
        self.menuMusic.setLoop(True)

        # create a main frame as big as the window
        self.frameMain = DirectFrame(
            # set framesize the same size as the window
            frameSize = (base.a2dLeft, base.a2dRight,
                         base.a2dTop, base.a2dBottom),
            # position center
            pos = (0, 0, 0),
            # set tramsparent background color
            frameColor = (0.15, 0.15, 0.15, 1))
        #self.frameMain.reparentTo(render2d)

        self.menuBackground = OnscreenImage(
            image = 'gui/Background.png',
            scale = (1.66, 1, 1),
            pos = (0, 0, 0))
        self.menuBackground.reparentTo(self.frameMain)

        self.defaultBtnMap = base.loader.loadModel("gui/button_map")
        self.buttonGeom = (
            self.defaultBtnMap.find("**/button_ready"),
            self.defaultBtnMap.find("**/button_click"),
            self.defaultBtnMap.find("**/button_rollover"),
            self.defaultBtnMap.find("**/button_disabled"))
        self.defaultTxtMap = base.loader.loadModel("gui/textbox_map")
        self.textboxGeom = self.defaultTxtMap.find("**/textbox")

        monospace = loader.loadFont('gui/DejaVuSansMono.ttf')
        defaultFont = loader.loadFont('gui/eufm10.ttf')

        # create the title
        self.textscale = 0.25
        self.title = DirectLabel(
            # scale and position
            scale = self.textscale,
            pos = (0.0, 0.0, base.a2dTop - self.textscale),
            # frame
            frameColor = (0, 0, 0, 0),
            # Text
            text = "Dungeon Crawler",
            text_align = TextNode.ACenter,
            text_fg = (0.82,0.85,0.87,1),
            text_shadow = (0, 0, 0, 1),
            text_shadowOffset = (-0.02, -0.02),
            text_font = defaultFont)
        self.title.setTransparency(1)
        self.title.reparentTo(self.frameMain)

        # create a host button
        self.btnHostPos = Vec3(0, 0, .45)
        self.btnHostScale = 0.25
        self.btnHost = DirectButton(
            # Scale and position
            scale = self.btnHostScale,
            pos = self.btnHostPos,
            # Text
            text = "Host",
            text_scale = 0.8,
            text_pos = (0, -0.2),
            text_fg = (0.82,0.85,0.87,1),
            text_shadow = (0, 0, 0, 1),
            text_shadowOffset = (-0.02, -0.02),
            text_font = defaultFont,
            # Frame
            geom = self.buttonGeom,
            frameColor = (0, 0, 0, 0),
            relief = 0,
            pressEffect = False,
            # Functionality
            command = self.host,
            rolloverSound = None,
            clickSound = None)
        self.btnHost.setTransparency(1)
        self.btnHost.reparentTo(self.frameMain)

        # create a join button
        self.btnJoinPos = Vec3(0, 0, 0)
        self.btnJoinScale = 0.25
        self.btnJoin = DirectButton(
            scale = self.btnJoinScale,
            pos = self.btnJoinPos,
            text = "Join",
            text_scale = 0.8,
            text_pos = (0, -0.2),
            text_fg = (0.82,0.85,0.87,1),
            text_shadow = (0, 0, 0, 1),
            text_shadowOffset = (-0.02, -0.02),
            text_font = defaultFont,
            geom = self.buttonGeom,
            frameColor = (0, 0, 0, 0),
            relief = 0,
            pressEffect = False,
            command = self.join,
            rolloverSound = None,
            clickSound = None)
        self.btnJoin.setTransparency(1)
        self.btnJoin.reparentTo(self.frameMain)

        # create the IP input field
        self.txtIPPos = Vec3(0, 0, -.30)
        self.txtIPScale = 0.25
        self.txtIPWidth = 9
        self.txtIP = DirectEntry(
            # scale and position
            pos = self.txtIPPos,
            scale = self.txtIPScale,
            width = self.txtIPWidth,
            # Text
            entryFont = monospace,
            text_align = TextNode.ACenter,
            text = "",
            text_scale = 0.5,
            text_pos = (0, -0.2),
            text_fg = (0.82,0.85,0.87,1),
            text_shadow = (0, 0, 0, 1),
            text_shadowOffset = (0.04, 0.04),
            initialText = "127.0.0.1",
            numLines = 1,
            # Frame
            geom = self.textboxGeom,
            frameColor = (0, 0, 0, 0),
            relief = 0,
            # Functionality
            command = self.join,
            focusInCommand = self.clearText)
        self.txtIP.reparentTo(self.frameMain)

        # create an exit button
        self.btnExitPos = Vec3(0, 0, -.75)
        self.btnExitScale = 0.25
        self.btnExit = DirectButton(
            scale = self.btnExitScale,
            pos = self.btnExitPos,
            text = "Exit",
            text_scale = 0.8,
            text_pos = (0, -0.2),
            text_fg = (0.82,0.85,0.87,1),
            text_shadow = (0, 0, 0, 1),
            text_shadowOffset = (-0.02, -0.02),
            text_font = defaultFont,
            geom = self.buttonGeom,
            frameColor = (0, 0, 0, 0),
            relief = 0,
            pressEffect = False,
            command = lambda: base.messenger.send("escape"),
            rolloverSound = None,
            clickSound = None)
        self.btnExit.setTransparency(1)
        self.btnExit.reparentTo(self.frameMain)

        # create a mute checkbox
        self.cbVolumeMute = DirectCheckBox(
            # set size
            scale = (0.1, 0.1, 0.1),
            frameSize = (-1, 1, 1, -1),
            # functionality and visuals
            command = self.cbVolumeMute_CheckedChanged,
            isChecked = True,
            checkedImage = "gui/SoundSwitch_off.png",
            uncheckedImage = "gui/SoundSwitch_on.png",
            # mouse behaviour
            relief = 0,
            pressEffect = False,
            rolloverSound = None,
            clickSound = None
            )
        self.cbVolumeMute.setTransparency(1)
        self.cbVolumeMute.reparentTo(self.frameMain)
        self.cbVolumeMute.commandFunc(None)

        # catch window resizes and recalculate the aspectration
        self.accept("window-event", self.recalcAspectRatio)
        self.accept("showerror", self.showError)

        # show the menu right away
        self.show()

    def host(self):
        """Function which will be called by pressing the host button"""
        self.hide()
        base.messenger.send("start_server")

    def join(self, ip=None):
        """Function which will be called by pressing the join button"""
        if ip == None: ip = self.txtIP.get(True)
        if ip == "": return
        self.hide()
        base.messenger.send("start_client", [ip])

    def showError(self, msg):
        self.show()
        self.dialog = OkDialog(
            dialogName="ErrorDialog",
            text="Error: {}".format(msg),
            command=self.closeDialog)

    def closeDialog(self, args):
        self.dialog.hide()

    def show(self):
        """Show the GUI"""
        self.frameMain.show()
        self.menuMusic.play()

    def hide(self):
        """Hide the GUI"""
        self.frameMain.hide()
        self.menuMusic.stop()

    def clearText(self):
        """Function to clear the text that was previously entered in the
        IP input field"""
        self.txtIP.enterText("")

    def cbVolumeMute_CheckedChanged(self, checked):
        if bool(checked):
            base.disableAllAudio()
        else:
            base.enableAllAudio()

    def recalcAspectRatio(self, window):
        """get the new aspect ratio to resize the mainframe"""
        # set the mainframe size to the window borders again
        self.frameMain["frameSize"] = (
            base.a2dLeft, base.a2dRight,
            base.a2dTop, base.a2dBottom)

        # calculate new aspec tratio
        wp = window.getProperties()
        aspX = 1.0
        aspY = 1.0
        wpXSize = wp.getXSize()
        wpYSize = wp.getYSize()
        if wpXSize > wpYSize:
            aspX = wpXSize / float(wpYSize)
        else:
            aspY = wpYSize / float(wpXSize)
        # calculate new position/size/whatever of the gui items
        self.title.setPos(0.0, 0.0, base.a2dTop - self.textscale)
        self.menuBackground.setScale(1.0 * aspX, 1.0, 1.0 * aspY)
        self.cbVolumeMute.setPos(base.a2dRight - 0.15, 0, base.a2dBottom + 0.15)
Example #6
0
class ConsoleWindow(DirectObject.DirectObject):
    console_output = None
    gui_key = PANDA3D_CONSOLE_TOGGLE_KEY
    autocomplete_key = PANDA3D_CONSOLE_AUTOCOMPLETE_KEY
    autohelp_key = PANDA3D_CONSOLE_AUTOHELP_KEY
    # change size of text and number of characters on one line
    # scale of frame (must be small (0.0x)
    scale = PANDA3D_CONSOLE_SCALE
    # to define a special font, if loading fails the default font is used
    # (without warning)
    font = PANDA3D_CONSOLE_FONT
    fontWidth = PANDA3D_CONSOLE_FONT_WIDTH
    # frame position and size (vertical & horizontal)
    h_pos = PANDA3D_CONSOLE_HORIZONTAL_POS
    h_size = PANDA3D_CONSOLE_HORIZONTAL_SIZE
    # v_size + v_pos should not exceed 2.0, else parts of the interface
    # will not be visible
    # space above the frame (must be below 2.0, best between 0.0 and 1.0)
    v_pos = PANDA3D_CONSOLE_VERTICAL_POS
    # vertical size of the frame (must be at max 2.0, best between 0.5 and 2.0)
    v_size = PANDA3D_CONSOLE_VERTICAL_SIZE
    linelength = int((h_size / scale - 5) / fontWidth)
    textBuffer = list()
    MAX_BUFFER_LINES = 5000
    commandPos = 0
    _iconsole = None
    _commandBuffer = ''
    logger.debug("max number of characters on a length:", linelength)
    numlines = int(v_size / scale - 5)
    defaultTextColor = (0.0, 0.0, 0.0, 1.0)
    autoCompleteColor = (0.9, 0.9, 0.9, 1.0)
    consoleFrame = None
    commandList = []
    maxCommandHistory = 10000
    textBufferPos = -1
    clipboardTextLines = None
    clipboardTextRaw = None

    def __init__(self, parent):
        global base
        if not logger.isEnabledFor(logging.DEBUG):
            global CONSOLE_MESSAGE
            CONSOLE_MESSAGE = '''
----------------- Ship's Interface version 3.0.9_749 -------------------
Direct Ship Interface Enabled.
Please use caution.  Irresponsible use of this console may result in the ship's AI refusing access to this interface.

type 'help' for basic commands.
-------------------------------------------------------------------------'''

        # change up from parent/IC
        self.parent = parent
        localenv = globals()
        localenv['gameroot'] = self.parent
        self._iconsole = customConsoleClass(localsEnv=localenv)

        # line wrapper
        self.linewrap = textwrap.TextWrapper()
        self.linewrap.width = self.linelength

        # calculate window size
        # left   = (self.h_pos) / self.scale
        # right  = (self.h_pos + self.h_size) / self.scale
        # bottom = (self.v_pos) / self.scale
        # top    = (self.v_pos + self.v_size) /self.scale

        # panda3d interface
        self.consoleFrame = DirectFrame(relief=DGG.GROOVE,
                                        frameColor=(200, 200, 200, 0.5),
                                        scale=self.scale,
                                        frameSize=(0, self.h_size / self.scale,
                                                   0,
                                                   self.v_size / self.scale))

        self.windowEvent(base.win)
        fixedWidthFont = None
        try:
            # try to load the defined font
            fixedWidthFont = parent.loader.loadFont(self.font)
        except Exception:
            traceback.print_exc()
            # if font is not valid use default font
            logger.warn('could not load the defined font %s" % str(self.font')
            fixedWidthFont = DGG.getDefaultFont()

        # text lines
        self._visibleLines = list(
            OnscreenText(parent=self.consoleFrame,
                         text="",
                         pos=(1, -i + 3 + self.numlines),
                         align=TextNode.ALeft,
                         mayChange=1,
                         scale=1.0,
                         fg=self.defaultTextColor)
            for i in range(self.numlines))
        map(lambda x: x.setFont(fixedWidthFont), self._visibleLines)

        # text entry line
        self.consoleEntry = DirectEntry(self.consoleFrame,
                                        text="",
                                        command=self.submitTrigger,
                                        width=self.h_size / self.scale - 2,
                                        pos=(1, 0, 1.5),
                                        initialText="",
                                        numLines=1,
                                        focus=1,
                                        entryFont=fixedWidthFont)

        # self.console_output = ConsoleOutput(testme=True)
        self.echo(CONSOLE_MESSAGE)
        self.clipboard = pyperclip

    def windowEvent(self, window):
        """
        This is a special callback.
        It is called when the panda window is modified.
        """
        wp = window.getProperties()
        width = wp.getXSize() / float(wp.getYSize())
        height = wp.getYSize() / float(wp.getXSize())
        if width > height:
            height = 1.0
        else:
            width = 1.0
        # aligned to center
        consolePos = Vec3(-self.h_size / 2, 0, -self.v_size / 2)
        # aligned to left bottom
        # consolePos = Vec3(-width+self.h_pos, 0, -height+self.v_pos)
        # aligned to right top
        # consolePos = Vec3(width-self.h_size, 0, height-self.v_size)
        # set position
        self.consoleFrame.setPos(consolePos)

    def submitTrigger(self, cmdtext):
        # set to last message
        # clear line
        self.consoleEntry.enterText('')
        self.focus()
        # add text entered to user command list & remove oldest entry
        self.commandList.append(cmdtext)
        self.commandPos += 1
        self._commandBuffer = ''
        logger.debug('CP {}'.format(self.commandPos))
        # push to interp
        for text, pre, color in self._iconsole.push(cmdtext):
            self.echo(text, pre, color)

    # set up console controls
    def mapControls(self):
        hidden = self.consoleFrame.isHidden()
        self.consoleEntry['focus'] != hidden
        if hidden:
            self.ignoreAll()
        else:
            self.accept('page_up', self.scroll, [-5])
            self.accept('page_up-repeat', self.scroll, [-5])
            self.accept('page_down', self.scroll, [5])
            self.accept('page_down-repeat', self.scroll, [5])
            self.accept('window-event', self.windowEvent)
            self.accept('arrow_up', self.scrollCmd, [-1])
            self.accept('arrow_down', self.scrollCmd, [1])
            self.accept(self.gui_key, self.toggleConsole)
            self.accept('escape', self.toggleConsole)
            self.accept(self.autocomplete_key, self.autocomplete)
            self.accept(self.autohelp_key, self.autohelp)

            # accept v, c and x, where c & x copy's the whole console text
            # messenger.toggleVerbose()
            # for osx use ('meta')
            if sys.platform == 'darwin':
                self.accept('meta', self.unfocus)
                self.accept('meta-up', self.focus)
                self.accept('meta-c', self.copy)
                self.accept('meta-x', self.cut)
                self.accept('meta-v', self.paste)
            # for windows use ('control')
            if sys.platform == 'win32' or sys.platform == 'linux2':
                self.accept('control', self.unfocus)
                self.accept('control-up', self.focus)
                self.accept('control-c', self.copy)
                self.accept('control-x', self.cut)
                self.accept('control-v', self.paste)

    # toggle the gui console
    def toggleConsole(self, hide=False):
        if hide:
            self.consoleFrame.hide()
            self.ignoreAll()
            # express hide, don't call setControls()
            return

        if self.consoleFrame.is_hidden():
            self.consoleFrame.show()
            self.parent.setControls(self)
        else:
            self.consoleFrame.hide()
            self.ignoreAll()
            self.parent.setControls()

    def scroll(self, step):
        newpos = self.textBufferPos + step
        if newpos < 0 or newpos >= len(self.textBuffer):
            # no... no... I no think so
            return
        self.textBufferPos = newpos
        self.redrawConsole()

    def redrawConsole(self):
        windowstart = max(self.textBufferPos - len(self._visibleLines) + 1, 0)
        windowend = min(
            len(self._visibleLines) + windowstart, len(self.textBuffer))
        logger.debug('windowS: {} WindowE: {}'.format(windowstart, windowend))
        for lineNumber, (lineText, color) in \
                enumerate(self.textBuffer[
                    windowstart:
                    windowend]):
            logger.debug("LN {}, LEN {}".format(lineNumber,
                                                len(self.textBuffer)))
            self._visibleLines[lineNumber].setText(lineText)
            self._visibleLines[lineNumber]['fg'] = color

    def scrollCmd(self, step):
        if not self.commandList:  # 0 or null - nothing to scroll
            return
        # should we update a temp buffer?
        if self.commandPos == len(self.commandList):
            if step > 0:
                self.consoleEntry.set(self._commandBuffer)
                return
            else:
                tmp = self.consoleEntry.get()
                if self.commandList[-1] != tmp:
                    self._commandBuffer = tmp
        self.commandPos += step
        if self.commandPos >= len(self.commandList):
            self.commandPos = len(self.commandList) - 1
            self.consoleEntry.set(self._commandBuffer)
            self.consoleEntry.setCursorPosition(
                len(self.commandList[self.commandPos]))
        elif self.commandPos < 0:
            self.commandPos = -1
            # No need to change anything, can't go past the beginning
            return
        # finally, just set it
        self.consoleEntry.set(self.commandList[self.commandPos])
        self.consoleEntry.setCursorPosition(
            len(self.commandList[self.commandPos]))

    def autocomplete(self):
        currentText = self.consoleEntry.get()
        currentPos = self.consoleEntry.guiItem.getCursorPosition()
        newText = self._iconsole.autocomplete(currentText, currentPos)
        if newText[-1] and newText[-1] != currentText:
            self.consoleEntry.set(newText[-1])
            self.consoleEntry.setCursorPosition(len(newText))

    def autohelp(self):
        currentText = self.consoleEntry.get()
        currentPos = self.consoleEntry.guiItem.getCursorPosition()
        self.parent.autohelp(currentText, currentPos)

    def unfocus(self):
        self.consoleEntry['focus'] = 0

    def focus(self):
        self.consoleEntry['focus'] = 1

    def copy(self):
        copy = self.consoleEntry.get()
        pyperclip.copy(copy)

    def paste(self):
        oldCursorPos = self.consoleEntry.guiItem.getCursorPosition()
        self.clipboardTextRaw = pyperclip.paste()

        # compose new text line
        oldText = self.consoleEntry.get()
        newText = oldText[0:oldCursorPos] + self.clipboardTextRaw + oldText[
            oldCursorPos:]

        self.clipboardTextLines = newText.split(os.linesep)

        for i in range(len(self.clipboardTextLines) - 1):
            currentLine = self.clipboardTextLines[i]
            # we only want printable characters
            currentLine = re.sub(
                r'[^' + re.escape(string.printable[:95]) + ']', "",
                currentLine)

            # set new text and position
            self.consoleEntry.set(currentLine)
            self.submitTrigger(currentLine)
        currentLine = self.clipboardTextLines[-1]
        currentLine = re.sub(r'[^' + re.escape(string.printable[:95]) + ']',
                             "", currentLine)
        self.consoleEntry.set(currentLine)
        self.consoleEntry.setCursorPosition(len(self.consoleEntry.get()))
        self.focus()

    def cut(self):
        pyperclip.copy(self.consoleEntry.get())
        self.consoleEntry.enterText('')
        self.focus()

    def echo(self, output, pre='*', color=defaultTextColor):
        if logger.isEnabledFor(logging.DEBUG):
            logger.debug('output: {}'.format(pprint.pformat(output)))
        for line in output.split('\n'):
            fmtline = "{}{}".format(pre, line)
            logger.debug(fmtline)
            if len(line) > 0:
                self.write_to_panel(fmtline, color)

    def write_to_panel(self, output, color=defaultTextColor):
        # remove not printable characters (which can be input by console input)
        output = re.sub(r'[^%s]' % re.escape(string.printable[:95]), "",
                        output)
        logger.debug('write_to_panel: output="{}"'.format(output))
        splitLines = self.linewrap.wrap(output)
        logger.debug('write_to_panel: splitLines="{}"'.format(splitLines))
        for line in splitLines:
            self.textBuffer.append([line, color])
            if len(self.textBuffer) > self.MAX_BUFFER_LINES:
                self.textBuffer.pop(0)
            else:
                self.textBufferPos += 1

        self.redrawConsole()
class DeveloperConsole(InteractiveInterpreter, DirectObject):
    """The name says it all."""
    def __init__(self, xml):
        sys.stdout = PseudoFile(self.writeOut)
        sys.stderr = PseudoFile(self.writeErr)
        tpErr = TextProperties()
        tpErr.setTextColor(1, 0.5, 0.5, 1)
        TextPropertiesManager.getGlobalPtr().setProperties("err", tpErr)
        font = loader.loadFont("cmss12")
        self.frame = DirectFrame(parent=base.a2dTopCenter,
                                 text_align=TextNode.ALeft,
                                 text_pos=(-base.getAspectRatio() +
                                           TEXT_MARGIN[0], TEXT_MARGIN[1]),
                                 text_scale=0.05,
                                 text_fg=(1, 1, 1, 1),
                                 frameSize=(-2.0, 2.0, -0.5, 0.0),
                                 frameColor=(0, 0, 0, 0.5),
                                 text='',
                                 text_font=font)
        self.entry = DirectEntry(parent=base.a2dTopLeft,
                                 command=self.command,
                                 scale=0.05,
                                 width=1000.0,
                                 pos=(-0.02, 0, -0.48),
                                 relief=None,
                                 text_pos=(1.5, 0, 0),
                                 text_fg=(1, 1, 0.5, 1),
                                 rolloverSound=None,
                                 clickSound=None,
                                 text_font=font)
        self.otext = OnscreenText(parent=self.entry,
                                  scale=1,
                                  align=TextNode.ALeft,
                                  pos=(1, 0, 0),
                                  fg=(1, 1, 0.5, 1),
                                  text=':',
                                  font=font)
        self.lines = [''] * 9
        self.commands = []  # All previously sent commands
        self.cscroll = None  # Index of currently navigated command, None if current
        self.command = ''  # Currently entered command
        self.block = ''  # Temporarily stores a block of commands
        self.hide()
        self.initialized = False

        self.toggleKeys = manager.controls.registerKeyAll(
            "Toggle Console", "`", self.toggle, self)

    def reload(self, xml):
        pass

    def prevCommand(self):
        if self.hidden:
            return
        if len(self.commands) == 0:
            return
        if self.cscroll == None:
            self.cscroll = len(self.commands)
            self.command = self.entry.get()
        elif self.cscroll <= 0:
            return
        else:
            self.commands[self.cscroll] = self.entry.get()
        self.cscroll -= 1
        self.entry.set(self.commands[self.cscroll])
        self.entry.setCursorPosition(len(self.commands[self.cscroll]))

    def nextCommand(self):
        if self.hidden:
            return
        if len(self.commands) == 0:
            return
        if self.cscroll == None:
            return
        self.commands[self.cscroll] = self.entry.get()
        self.cscroll += 1
        if self.cscroll >= len(self.commands):
            self.cscroll = None
            self.entry.set(self.command)
            self.entry.setCursorPosition(len(self.command))
        else:
            self.entry.set(self.commands[self.cscroll])
            self.entry.setCursorPosition(len(self.commands[self.cscroll]))

    def writeOut(self, line, copy=True):
        if copy:
            sys.__stdout__.write(line)
        lines = line.split('\n')
        firstline = lines.pop(0)
        self.lines[-1] += firstline
        self.lines += lines
        self.frame['text'] = '\n'.join(self.lines[-9:])

    def writeErr(self, line, copy=True):
        if copy:
            sys.__stderr__.write(line)
        line = '\1err\1%s\2' % line
        lines = line.split('\n')
        firstline = lines.pop(0)
        self.lines[-1] += firstline
        self.lines += lines
        self.frame['text'] = '\n'.join(self.lines[-9:])

    def command(self, text):
        if not self.hidden:
            self.cscroll = None
            self.command = ''
            self.entry.set('')
            self.entry['focus'] = True
            self.writeOut(self.otext['text'] + ' ' + text + '\n', False)
            if text != '' and (len(self.commands) == 0
                               or self.commands[-1] != text):
                self.commands.append(text)

            # Insert plugins into the local namespace
            locals = __main__.__dict__
            for plugin in manager.getNamed().keys():
                locals[plugin] = manager.getNamed()[plugin]
            locals['panda3d'] = panda3d

            #register custom commands
            locals['reload'] = manager.reload
            locals['load'] = manager.transition
            locals['wireframe'] = base.toggleWireframe
            locals['trigger'] = events.triggerEvent

            # Run it and print the output.
            if not self.initialized:
                InteractiveInterpreter.__init__(self, locals=locals)
                self.initialized = True
            try:
                if self.runsource(self.block + '\n' + text) and text != '':
                    self.otext['text'] = '.'
                    self.block += '\n' + text
                else:
                    self.otext['text'] = ':'
                    self.block = ''
            except Exception:  # Not just "except", it will also catch SystemExit
                # Whoops! Print out a traceback.
                self.writeErr(traceback.format_exc())

    def toggle(self):
        #remove toggle key from entry
        if self.entry['focus']:
            for gtype in self.toggleKeys.keys():
                key = self.toggleKeys[gtype]
                entryLen = len(self.entry.get(True))
                if self.entry.get(True)[entryLen - len(key):entryLen] == key:
                    self.entry.enterText(
                        self.entry.get(True)[:entryLen - len(key)])
        if self.hidden:
            self.show()
        else:
            self.hide()

    def start(self):
        return
        #self.toggle()

    def stop(self):
        return
        #self.toggle()

    def show(self):
        self.accept('arrow_up', self.prevCommand)
        self.accept('arrow_up-repeat', self.prevCommand)
        self.accept('arrow_down', self.nextCommand)
        self.accept('arrow_down-repeat', self.nextCommand)
        self.hidden = False
        self.entry['focus'] = True
        self.frame.show()
        self.entry.show()
        self.otext.show()

    def hide(self):
        self.ignoreAll()
        self.hidden = True
        self.entry['focus'] = False
        self.frame.hide()
        self.entry.hide()
        self.otext.hide()

    def destroy(self):
        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__
        self.ignoreAll()
        self.frame.destroy()
        self.entry.destroy()
        self.otext.destroy()
class PlacerToolSpinner(DirectFrame):
    def __init__(self,
                 parent=render2d,
                 pos=(0.0, 0.0, 0.0),
                 scale=1.0,
                 value=0,
                 callback=None,
                 increment=0.01):
        DirectFrame.__init__(self, parent, pos=pos, scale=1.0)
        self.increment = increment
        self.value = Decimal(value)
        self.callback = callback

        self.display = DirectEntry(parent=self,
                                   relief=None,
                                   initialText="%.2f" % value,
                                   scale=1,
                                   text_scale=0.055,
                                   text_align=TextNode.ACenter,
                                   pos=(0.0, 0.0, 0.0),
                                   frameColor=(0.8, 0.8, 0.5, 1),
                                   borderWidth=(0.1, 0.1),
                                   numLines=1,
                                   width=6,
                                   frameSize=(-0.1, 0.1, -0.1, 0.1),
                                   cursorKeys=1)
        self.display.bind(DGG.TYPE, self.typeCallback)
        # This allows the text box to handle mouse events
        self.display.guiItem.setActive(True)

        gui = loader.loadModel('phase_3/models/gui/tt_m_gui_mat_mainGui.bam')
        image = (gui.find('**/tt_t_gui_mat_shuffleArrowUp'),
                 gui.find('**/tt_t_gui_mat_shuffleArrowDown'),
                 gui.find('**/tt_t_gui_mat_shuffleArrowUp'),
                 gui.find('**/tt_t_gui_mat_shuffleArrowDisabled'))
        self.upArrow = DirectButton(self,
                                    relief=None,
                                    image=image,
                                    image_scale=(0.6, 0.6, 0.6),
                                    image1_scale=(0.7, 0.7, 0.7),
                                    image2_scale=(0.7, 0.7, 0.7),
                                    pos=(0.0, 0.0, 0.08),
                                    command=self.__handleUpClicked)
        self.upArrow.setR(90)
        self.downArrow = DirectButton(self,
                                      relief=None,
                                      image=image,
                                      image_scale=(0.6, 0.6, 0.6),
                                      image1_scale=(0.7, 0.7, 0.7),
                                      image2_scale=(0.7, 0.7, 0.7),
                                      pos=(0.0, 0.0, -0.05),
                                      command=self.__handleDownClicked)
        self.downArrow.setR(-90)

    def typeCallback(self, e):
        if self.display is None:
            return
        value = self.display.get()
        value = re.sub("[^0-9\.-]", "", value)
        if value == '':
            value = '000.00'
        elif value == '-':
            return
        if '.' not in value:
            try:
                value = int(value)
            except:
                return
        else:
            try:
                value = '%.2f' % float(value)
            except:
                return
        self.setValue(value)

    def setValue(self, value):
        getcontext().prec = 2
        self.value = Decimal(value)
        self.display.enterText('%.2f' % float(value))
        if self.callback:
            self.callback(self.value)

    def __handleUpClicked(self):
        getcontext().prec = 2
        self.setValue(float(self.value) + float(self.increment))

    def __handleDownClicked(self):
        getcontext().prec = 2
        self.setValue(float(self.value) - float(self.increment))
Example #9
0
class FileDialog(DirectObject):
    def __init__(self, title, initial_status, callback):
        self.frmLeft = -.7
        self.frmBottom = -.12
        self.frmRight = .7
        self.frmTop = .12

        self.frmWidth = self.frmRight - self.frmLeft
        self.frmHeight = self.frmTop - self.frmBottom

        self.title = title
        self.initial_status = initial_status
        self.callback = callback

        self.result = None
        self.done = 0

    def activate(self):
        # create main dialog frame
        # Note: frame position references the CENTER of the frame
        self.frm = DirectFrame(pos=(0, 0, 0),
                               frameSize=(self.frmLeft, self.frmRight,
                                          self.frmBottom, self.frmTop),
                               relief=DGG.RIDGE,
                               borderWidth=(0.01, 0.01),
                               frameColor=(0.6, 0.6, 0.6, 1.0))

        self.frm.reparentTo(base.aspect2d)

        # Note: wonderfully enough, label position on the other hand
        # references the CENTER of the LEFT border of the label!
        titleLabel = DirectLabel(text=self.title,
                                 scale=0.04,
                                 frameColor=(0.5, 0.5, 0.5, 1),
                                 relief=DGG.RIDGE,
                                 borderWidth=(0.01, 0.01),
                                 text_align=TextNode.ALeft)

        titleLabel.setPos(-self.frmWidth / 2 + .02, 0,
                          self.frmHeight / 2 - .045)
        titleLabel.reparentTo(self.frm)

        sc = .04
        self.dir_edit_field = DirectEntry(
            text='',  # prompt text
            scale=sc,
            frameColor=(0.65, 0.65, 0.65, 1),
            command=self.setText,
            width=32,
            numLines=1,
            focus=1,
            focusInCommand=self.efFocusIn,
        )

        self.dir_edit_field.setPos(-self.frmWidth / 2 + .02, 0,
                                   self.frmHeight / 2 - .13)
        self.dir_edit_field.reparentTo(self.frm)

        self.statusLabel = DirectLabel(
            text=self.initial_status,
            scale=0.04,
            frameColor=(0.6, 0.6, 0.6, 1),
            # relief = DGG.RIDGE,
            # borderWidth = (0.01, 0.01),
            text_align=TextNode.ALeft)

        self.statusLabel.setPos(-self.frmWidth / 2 + .02, 0,
                                self.frmHeight / 2 - .2)
        self.statusLabel.reparentTo(self.frm)

    # call this if you need to run a form before your mainloop starts steppping the taskMgr
    def run(self):
        while self.done != 1:
            taskMgr.step()

        taskMgr.step(
        )  # once more to make the last output from the dialog visible
        # while we load a zone
        self.frm.removeNode()

    def end(self):
        self.frm.removeNode()

    # callback function to set  text: called by the Panda3d taskMgr when the user
    # has entered something into the DirectEntry widget
    def setText(self, textEntered):
        print 'dir_edit_field::setText:', textEntered
        self.done = self.callback(textEntered)
        if self.done != 1:
            self.dir_edit_field['focus'] = 1

    #clear the text
    def efFocusIn(self):
        print 'focus in'
        self.dir_edit_field.enterText('')

    def setStatus(self, status):
        self.statusLabel['text'] = status
Example #10
0
class Chat(object):
    """Handles all chat."""

    def __init__(self, game):
        self.game = game
        self.lines = []
        self.whisperTarget = None

        props = base.win.getProperties()
        ratio = float(props.getXSize()) / props.getYSize()

        self.frame = DirectFrame(frameColor=(0, 0, 0, 0), frameSize=(0, 1, 0, 1), pos=(-ratio, 0, -1))

        self.text = OnscreenText(
            text="",
            pos=(0.01, 0.45),
            scale=0.05,
            fg=(1, 1, 1, 1),
            bg=(0, 0, 0, 0.2),
            parent=self.frame,
            align=TextNode.ALeft,
            mayChange=True,
        )

        self.entry = DirectEntry(
            parent=self.frame, text="", scale=0.05, pos=(0.01, 0, 0.02), initialText="", width=26, numLines=1
        )

        self.targetText = OnscreenText(
            text="",
            pos=(1.34, 0.025),
            scale=0.05,
            fg=(1, 1, 1, 1),
            bg=(0, 0, 0, 0.4),
            parent=self.frame,
            align=TextNode.ALeft,
            mayChange=True,
        )

        base.accept("t", self.startChatting)
        base.accept("shift-t", self.startChatting)
        base.accept("y", self.startWhispering)
        base.accept("shift-y", self.startWhispering)
        base.accept("arrow_up", lambda: self.changeTarget(1))
        base.accept("shift-arrow_up", lambda: self.changeTarget(1))
        base.accept("arrow_down", lambda: self.changeTarget(-1))
        base.accept("shift-arrow_down", lambda: self.changeTarget(-1))
        base.accept("enter", self.sendChat)
        base.accept("shift-enter", self.sendChat)

    def startChatting(self):
        if not self.game.isChatting:
            self.game.isChatting = True

            # focus on the DirectEntry
            self.entry["focus"] = 1

            # reset whisper target (just in case)
            self.whisperTarget = None

            # enable UI mode
            if self.game.camera is not None:
                self.game.camera.showMouse()

    def startWhispering(self):
        if not self.game.isChatting:
            if not self.game.characters:
                self.addLine("<<System>> Nobody to whisper!")
            else:
                self.startChatting()
                self.changeTarget(0)

    def changeTarget(self, amt):
        if self.game.isChatting:
            targets = self.game.characters.keys()
            targets.sort()

            # find target (or the closest id before target, or 0)
            index = 0
            match = False
            for i in range(len(targets)):
                if targets[i] < self.whisperTarget:
                    index = i
                elif targets[i] == self.whisperTarget:
                    index = i
                    match = True
                    break
                else:
                    break

            # if not found but going back 1 anyway, set amt to 0
            if not match and amt == -1:
                amt = 0

            # set new whisper target
            index = (index + amt) % len(targets)
            self.whisperTarget = targets[index]
            self.targetText.setText("to: " + str(self.game.characters[self.whisperTarget].name))

    def sendChat(self):
        if self.game.isChatting:
            message = self.entry.get().strip()
            if len(message) > 0:
                # figure out target
                target = ""
                if self.whisperTarget in self.game.characters:
                    target = self.game.characters[self.whisperTarget].name

                # submit message
                self.game.main.cManager.sendRequest(Constants.C_CHAT, {"message": message, "target": target})

            # stop chatting
            self.stopChatting()

    def stopChatting(self):
        if self.game.isChatting:
            self.game.isChatting = False

            # disable chat entry
            self.entry["focus"] = 0

            # clear text box
            self.entry.enterText("")

            # remove whisper target
            self.whisperTarget = None
            self.targetText.setText("")

            # disable UI mode
            if self.game.camera is not None:
                self.game.camera.hideMouse()

    def addLine(self, line):
        self.lines.append(line)
        self.text.setText("\n".join(self.lines[-8:]))
Example #11
0
class MainMenu():
	def __init__(self, showbase):
		self.showbase = showbase
		
		self.status = OnscreenText(text = "", pos = Vec3(0, -0.35, 0), scale = 0.05, fg = (1, 0, 0, 1), align = TextNode.ACenter, mayChange = True)
		
		self.background = DirectFrame(
			frameSize = (-1, 1, -1, 1),
			frameTexture  = 'media/gui/mainmenu/menu.png',
			parent = self.showbase.render2d,
		)

		self.title = OnscreenText(
			text   = 'Main Menu',
			fg     = (1, 1, 1, 1),
			parent = self.background,
			pos    = (-0.6, 0.1),
			scale  = 0.06
		)

		self.ip = '127.0.0.1' # Should make this write to file... so that the user can save ip's...
		# yep thats a good idea, there will be a few things i guess that need to be done like this
		# like settings and keys and whatnot
		
		# Buttons
		self.buttons = []
		serverButtons = Vec3(-0.60, 0, -0.79)
		# Host
		self.params = ['3', '8']
		p = serverButtons + Vec3(-0.25, 0, 0)
		self.hostButton = DirectButton(text = 'Host', pos = p,  scale = 0.048, relief = DGG.GROOVE, command = self.showbase.hostGame, extraArgs = [self.params])
		self.buttons.append(self.hostButton)
		# Join
		p = serverButtons + Vec3(0.0, 0.0, 0.0)
		self.joinButton = DirectButton(text = 'Join', pos = p, scale = 0.048, relief = DGG.GROOVE, command = self.joinServer)
		self.buttons.append(self.joinButton)
		# Refresh
		if self.showbase.online:
			p = serverButtons + Vec3(0.25, 0, 0)
			self.refreshButton = DirectButton(text = "Refresh", pos = p, scale = 0.048, relief = DGG.GROOVE, command = self.refreshStart)
			self.buttons.append(self.refreshButton)
			self.refreshStart()
			
			chatFrameCenter = (0.0, 0.325)
			chatFrameSize = (2.5, 1.2)
			self.chat = DirectFrame(
							frameColor = (0, 0, 0, 1),
							frameSize = (chatFrameSize[0] / 2, -chatFrameSize[0] / 2,  chatFrameSize[1] / 2, -chatFrameSize[1] / 2),
							pos = (chatFrameCenter[0], 0, chatFrameCenter[1])
						)
			
			channelFrameSize = (chatFrameSize[0] / 4, chatFrameSize[1])
			channelFrameCenter = (- chatFrameSize[0] / 2 + channelFrameSize[0] / 2, 0)
			numItemsVisible = 8
			itemHeight = channelFrameSize[1] / (numItemsVisible + 1)
			self.channels = DirectScrolledList(
								parent = self.chat,
								pos = (channelFrameCenter[0], 0, channelFrameCenter[1]),
								frameSize = (-channelFrameSize[0] / 2, channelFrameSize[0] / 2, channelFrameSize[1] / 2, -channelFrameSize[1] / 2),
								frameColor = (1, 0, 0, 0.5),
								numItemsVisible = numItemsVisible,
								forceHeight = itemHeight,

								#itemFrame_frameSize = (-channelFrameSize[0] / 2.1, channelFrameSize[0] / 2.1, itemHeight, -channelFrameSize[1] + itemHeight),
								itemFrame_pos = (0, 0, channelFrameSize[1] / 2 - itemHeight),

								decButton_pos = (-0.2, 0, channelFrameCenter[1] - channelFrameSize[1] / 2 + itemHeight / 4),
								decButton_text = 'Prev',
								decButton_text_scale = 0.05,
								decButton_borderWidth = (0.005, 0.005),

								incButton_pos = (0.2, 0, channelFrameCenter[1] - channelFrameSize[1] / 2 + itemHeight / 4),
								incButton_text = 'Next',
								incButton_text_scale = 0.05,
								incButton_borderWidth = (0.005, 0.005),
							)

			b1 = DirectButton(text = ("Button1", "click!", "roll", "disabled"),
								text_scale = 0.1, borderWidth = (0.01, 0.01),
								relief = 2)
			
			b2 = DirectButton(text = ("Button2", "click!", "roll", "disabled"),
								text_scale = 0.1, borderWidth = (0.01, 0.01),
								relief = 2)
			
			l1 = DirectLabel(text = "Test1", text_scale = 0.1)
			l2 = DirectLabel(text = "Test2", text_scale = 0.1)
			l3 = DirectLabel(text = "Test3", text_scale = 0.1)

			self.channels.addItem(b1)
			self.channels.addItem(b2)
			self.channels.addItem(l1)
			self.channels.addItem(l2)
			self.channels.addItem(l3)

			for fruit in ['apple', 'pear', 'banana', 'orange', 'cake', 'chocolate']:
				l = DirectLabel(text = fruit, text_scale = 0.1)
				self.channels.addItem(l) 
			# need to add the chat stuff
			# i guess have like a chat manager which will hold an array of 'chat_instances'
			# and the chat manager can sort out which is displayed and which channel the text is sent from/received to
			# a bit more thinking needs to be done i guess
			# can discuss sometime (not really that important now :P)
			
			# also i guess the layout and shit will need to be sorted (for whoever is doing the designing)
			
			# current games list (need to implement this)
			# it should send a query to the master server to get the current list (just ip's atmo i guess)
			
			# options shit aswell needs to be sorted
			# maybe just an overlay or something
			
			# functionality for the host button (popup an overlay that will be able to set options and then 'start_game' button
			# then should auto connect and go to lobby (will be same as for all clients, except have a couple of different buttons i guess)
			# close game instead of disconnect, start game instead of ready (greyed until all others are ready), kick button i suppose
			
			# once the options are set the 'server_inst' should be started on the local computer (which will broadcast to master server, once host can successfully connect)
			# then game client will move to pregame state (connect to the server, and wait for others and ready)
		else:
			self.entry = DirectEntry(
							focusInCommand = self.clearText,
							frameSize   = (-3, 3, -.5, 1),
							initialText = self.ip,
							parent      = self.buttons[0],
							pos         = (0, -0.6, -1.5),
							text_align  = TextNode.ACenter,
						)
		self.hide()

	def refreshStart(self):
		self.refreshButton["state"] = DGG.DISABLED
		if self.showbase.authCon.getConnected():
			self.servers = []
			self.showbase.authCon.sendData('serverQuery')
			self.showbase.taskMgr.doMethodLater(0.25, self.queryServers, 'Server Query')

	def queryServers(self, task):
		finished = False
		temp = self.showbase.authCon.getData()
		for package in temp:
			if len(package) == 2:
				# Handle Server Query
				if package[0] == 'server':
					self.servers.append(package[1])
					print package[1]
				elif package[0] == 'final':
					self.refreshButton["state"] = DGG.NORMAL
					finished = True
				else:
					self.showbase.authCon.passData(package)
		if finished:
			return task.done
		return task.cont

	def joinChat(self):
		pass
		# Let the client mini auth with the lobby server(lobby_loop) by "Logging into the chat"
		# Since everything will be in the main menu? like a main chat window.. something similar to HoN i guess?
		# When the player opens the Join game by button, a list will be send from the lobby server telling it what games are active.
		# Then the player picks one and it connects via the host name/ip or whatever.
		# While this is busy happening the client stays connected to the lobby server.
		
	def joinServer(self):
		if self.showbase.online:
			self.ip = '127.0.0.1'
		else:
			self.ip = self.entry.get()
		self.status.setText('Attempting to join server @ ' + self.ip + '...')
		# attempt to connect to the game server
		self.showbase.client = Client(self.showbase, self.ip, 9099, compress = True)
		if self.showbase.client.getConnected():
			print 'Connected to server, Awaiting authentication...'
			self.showbase.client.sendData(('username', self.showbase.username))
			self.showbase.taskMgr.add(self.authorizationListener, 'Authorization Listener')
		else:
			self.status.setText('Could not Connect...')

	def authorizationListener(self, task):
		temp = self.showbase.client.getData()
		auth = False
		if temp != []:
			for package in temp:
				if len(package) == 2:
					if package[0] == 'auth':
						print 'Authentication Successful'
						auth = True
					elif package[0] == 'fail':
						self.status.setText('Authentication failed on server...')
						return task.done
					else:
						self.showbase.client.passData(package)
		if auth:
			self.showbase.startPregame()
			return task.done
		return task.again

	def clearText(self):
		self.entry.enterText('')

	def hide(self):
		self.showbase.taskMgr.remove('Server Query Timeout')
		self.background.hide()
		for b in self.buttons:
			b.hide()
		self.status.hide()
		if self.showbase.online:
			self.chat.hide()
			self.channels.hide()
		else:
			self.entry.hide()

	def show(self):
		self.background.show()
		for b in self.buttons:
			b.show()
		self.status.show()
		if self.showbase.online:
			self.chat.show()
			self.channels.show()
		else:
			self.entry.show()
Example #12
0
class MainScreen():
    def __init__(self):

        self.txtPlayerName = DirectEntry(
            text="",
            scale=0.08,
            pos=(-0.15, 0, 0.6),
            initialText="Name",
            numLines = 1,
            width = 4,
            focus=False,
            focusInCommand=self.__clearText,
            focusOutCommand=self.__checkText)

        self.btnStart = DirectButton(
            text = "Start",
            # size of the button
            scale = (0.25, 0.25, 0.25),
            # set no relief
            relief = 1,
            frameColor = (0,0,0,0),
            # No sink in when press
            pressEffect = False,
            # position on the window
            pos = (0, 0, .3),
            # the event which is thrown on clickSound
            command = self.btnStart_Click,
            # sounds that should be played
            rolloverSound = None,
            clickSound = None)
        self.btnStart.setTransparency(1)

        self.btnHighscore = DirectButton(
            text = "Highscore",
            # size of the button
            scale = (0.25, 0.25, 0.25),
            # set no relief
            relief = 1,
            frameColor = (0,0,0,0),
            # No sink in when press
            pressEffect = False,
            # position on the window
            pos = (0, 0, 0),
            # the event which is thrown on clickSound
            command = self.btnHighscore_Click,
            # sounds that should be played
            rolloverSound = None,
            clickSound = None)
        self.btnHighscore.setTransparency(1)

        self.btnQuit = DirectButton(
            text = "Quit",
            # size of the button
            scale = (0.25, 0.25, 0.25),
            # set no relief
            relief = 1,
            frameColor = (0,0,0,0),
            # No sink in when press
            pressEffect = False,
            # position on the window
            pos = (0, 0, -.3),
            # the event which is thrown on clickSound
            command = self.btnQuit_Click,
            # sounds that should be played
            rolloverSound = None,
            clickSound = None)
        self.btnQuit.setTransparency(1)

    def show(self):
        self.txtPlayerName.show()
        self.btnStart.show()
        self.btnHighscore.show()
        self.btnQuit.show()

    def hide(self):
        self.txtPlayerName.hide()
        self.btnStart.hide()
        self.btnHighscore.hide()
        self.btnQuit.hide()


    def __clearText(self):
        if self.txtPlayerName.get() == "" or \
               self.txtPlayerName.get() == "Name":
            self.txtPlayerName.enterText("")

    def __checkText(self):
        if self.txtPlayerName.get() == "":
            self.txtPlayerName.enterText("Name")

    def btnStart_Click(self):
        self.hide()
        base.messenger.send("MainMenu_start")

    def btnHighscore_Click(self):
        self.hide()
        base.messenger.send("Highscore_show")

    def btnQuit_Click(self):
        base.messenger.send("MainMenu_quit")

    def getPlayername(self):
        return self.txtPlayerName.get()
Example #13
0
class MainMenu():
    def __init__(self, showbase):
        self.showbase = showbase

        self.status = OnscreenText(text="",
                                   pos=Vec3(0, -0.35, 0),
                                   scale=0.05,
                                   fg=(1, 0, 0, 1),
                                   align=TextNode.ACenter,
                                   mayChange=True)

        self.background = DirectFrame(
            frameSize=(-1, 1, -1, 1),
            frameTexture='media/gui/mainmenu/menu.png',
            parent=self.showbase.render2d,
        )

        self.title = OnscreenText(text='Main Menu',
                                  fg=(1, 1, 1, 1),
                                  parent=self.background,
                                  pos=(-0.6, 0.1),
                                  scale=0.06)

        self.ip = '127.0.0.1'  # Should make this write to file... so that the user can save ip's...
        # yep thats a good idea, there will be a few things i guess that need to be done like this
        # like settings and keys and whatnot

        # Buttons
        self.buttons = []
        serverButtons = Vec3(-0.60, 0, -0.79)
        # Host
        self.params = ['3', '8']
        p = serverButtons + Vec3(-0.25, 0, 0)
        self.hostButton = DirectButton(text='Host',
                                       pos=p,
                                       scale=0.048,
                                       relief=DGG.GROOVE,
                                       command=self.showbase.hostGame,
                                       extraArgs=[self.params])
        self.buttons.append(self.hostButton)
        # Join
        p = serverButtons + Vec3(0.0, 0.0, 0.0)
        self.joinButton = DirectButton(text='Join',
                                       pos=p,
                                       scale=0.048,
                                       relief=DGG.GROOVE,
                                       command=self.joinServer)
        self.buttons.append(self.joinButton)
        # Refresh
        if self.showbase.online:
            p = serverButtons + Vec3(0.25, 0, 0)
            self.refreshButton = DirectButton(text="Refresh",
                                              pos=p,
                                              scale=0.048,
                                              relief=DGG.GROOVE,
                                              command=self.refreshStart)
            self.buttons.append(self.refreshButton)
            self.refreshStart()

            chatFrameCenter = (0.0, 0.325)
            chatFrameSize = (2.5, 1.2)
            self.chat = DirectFrame(
                frameColor=(0, 0, 0, 1),
                frameSize=(chatFrameSize[0] / 2, -chatFrameSize[0] / 2,
                           chatFrameSize[1] / 2, -chatFrameSize[1] / 2),
                pos=(chatFrameCenter[0], 0, chatFrameCenter[1]))

            channelFrameSize = (chatFrameSize[0] / 4, chatFrameSize[1])
            channelFrameCenter = (-chatFrameSize[0] / 2 +
                                  channelFrameSize[0] / 2, 0)
            numItemsVisible = 8
            itemHeight = channelFrameSize[1] / (numItemsVisible + 1)
            self.channels = DirectScrolledList(
                parent=self.chat,
                pos=(channelFrameCenter[0], 0, channelFrameCenter[1]),
                frameSize=(-channelFrameSize[0] / 2, channelFrameSize[0] / 2,
                           channelFrameSize[1] / 2, -channelFrameSize[1] / 2),
                frameColor=(1, 0, 0, 0.5),
                numItemsVisible=numItemsVisible,
                forceHeight=itemHeight,

                #itemFrame_frameSize = (-channelFrameSize[0] / 2.1, channelFrameSize[0] / 2.1, itemHeight, -channelFrameSize[1] + itemHeight),
                itemFrame_pos=(0, 0, channelFrameSize[1] / 2 - itemHeight),
                decButton_pos=(-0.2, 0, channelFrameCenter[1] -
                               channelFrameSize[1] / 2 + itemHeight / 4),
                decButton_text='Prev',
                decButton_text_scale=0.05,
                decButton_borderWidth=(0.005, 0.005),
                incButton_pos=(0.2, 0, channelFrameCenter[1] -
                               channelFrameSize[1] / 2 + itemHeight / 4),
                incButton_text='Next',
                incButton_text_scale=0.05,
                incButton_borderWidth=(0.005, 0.005),
            )

            b1 = DirectButton(text=("Button1", "click!", "roll", "disabled"),
                              text_scale=0.1,
                              borderWidth=(0.01, 0.01),
                              relief=2)

            b2 = DirectButton(text=("Button2", "click!", "roll", "disabled"),
                              text_scale=0.1,
                              borderWidth=(0.01, 0.01),
                              relief=2)

            l1 = DirectLabel(text="Test1", text_scale=0.1)
            l2 = DirectLabel(text="Test2", text_scale=0.1)
            l3 = DirectLabel(text="Test3", text_scale=0.1)

            self.channels.addItem(b1)
            self.channels.addItem(b2)
            self.channels.addItem(l1)
            self.channels.addItem(l2)
            self.channels.addItem(l3)

            for fruit in [
                    'apple', 'pear', 'banana', 'orange', 'cake', 'chocolate'
            ]:
                l = DirectLabel(text=fruit, text_scale=0.1)
                self.channels.addItem(l)
            # need to add the chat stuff
            # i guess have like a chat manager which will hold an array of 'chat_instances'
            # and the chat manager can sort out which is displayed and which channel the text is sent from/received to
            # a bit more thinking needs to be done i guess
            # can discuss sometime (not really that important now :P)

            # also i guess the layout and shit will need to be sorted (for whoever is doing the designing)

            # current games list (need to implement this)
            # it should send a query to the master server to get the current list (just ip's atmo i guess)

            # options shit aswell needs to be sorted
            # maybe just an overlay or something

            # functionality for the host button (popup an overlay that will be able to set options and then 'start_game' button
            # then should auto connect and go to lobby (will be same as for all clients, except have a couple of different buttons i guess)
            # close game instead of disconnect, start game instead of ready (greyed until all others are ready), kick button i suppose

            # once the options are set the 'server_inst' should be started on the local computer (which will broadcast to master server, once host can successfully connect)
            # then game client will move to pregame state (connect to the server, and wait for others and ready)
        else:
            self.entry = DirectEntry(
                focusInCommand=self.clearText,
                frameSize=(-3, 3, -.5, 1),
                initialText=self.ip,
                parent=self.buttons[0],
                pos=(0, -0.6, -1.5),
                text_align=TextNode.ACenter,
            )
        self.hide()

    def refreshStart(self):
        self.refreshButton["state"] = DGG.DISABLED
        if self.showbase.authCon.getConnected():
            self.servers = []
            self.showbase.authCon.sendData('serverQuery')
            self.showbase.taskMgr.doMethodLater(0.25, self.queryServers,
                                                'Server Query')

    def queryServers(self, task):
        finished = False
        temp = self.showbase.authCon.getData()
        for package in temp:
            if len(package) == 2:
                # Handle Server Query
                if package[0] == 'server':
                    self.servers.append(package[1])
                    print package[1]
                elif package[0] == 'final':
                    self.refreshButton["state"] = DGG.NORMAL
                    finished = True
                else:
                    self.showbase.authCon.passData(package)
        if finished:
            return task.done
        return task.cont

    def joinChat(self):
        pass
        # Let the client mini auth with the lobby server(lobby_loop) by "Logging into the chat"
        # Since everything will be in the main menu? like a main chat window.. something similar to HoN i guess?
        # When the player opens the Join game by button, a list will be send from the lobby server telling it what games are active.
        # Then the player picks one and it connects via the host name/ip or whatever.
        # While this is busy happening the client stays connected to the lobby server.

    def joinServer(self):
        if self.showbase.online:
            self.ip = '127.0.0.1'
        else:
            self.ip = self.entry.get()
        self.status.setText('Attempting to join server @ ' + self.ip + '...')
        # attempt to connect to the game server
        self.showbase.client = Client(self.showbase,
                                      self.ip,
                                      9099,
                                      compress=True)
        if self.showbase.client.getConnected():
            print 'Connected to server, Awaiting authentication...'
            self.showbase.client.sendData(('username', self.showbase.username))
            self.showbase.taskMgr.add(self.authorizationListener,
                                      'Authorization Listener')
        else:
            self.status.setText('Could not Connect...')

    def authorizationListener(self, task):
        temp = self.showbase.client.getData()
        auth = False
        if temp != []:
            for package in temp:
                if len(package) == 2:
                    if package[0] == 'auth':
                        print 'Authentication Successful'
                        auth = True
                    elif package[0] == 'fail':
                        self.status.setText(
                            'Authentication failed on server...')
                        return task.done
                    else:
                        self.showbase.client.passData(package)
        if auth:
            self.showbase.startPregame()
            return task.done
        return task.again

    def clearText(self):
        self.entry.enterText('')

    def hide(self):
        self.showbase.taskMgr.remove('Server Query Timeout')
        self.background.hide()
        for b in self.buttons:
            b.hide()
        self.status.hide()
        if self.showbase.online:
            self.chat.hide()
            self.channels.hide()
        else:
            self.entry.hide()

    def show(self):
        self.background.show()
        for b in self.buttons:
            b.show()
        self.status.show()
        if self.showbase.online:
            self.chat.show()
            self.channels.show()
        else:
            self.entry.show()
Example #14
0
class ColourChannel(DirectObject):
    __slider_edit_callback: Callable[['ColourChannel', float], None]
    __entry_edit_callback: Callable[['ColourChannel', float], None]

    __frame: DirectFrame
    __label: DirectLabel
    __slider: DirectSlider
    __entry: DirectEntry
    __disable_frame_overlay: DirectButton
    __enabled: bool

    def __init__(self, parent: DirectFrame, text: str, value: float,
                 slider_edit_callback: Callable[['ColourChannel', float],
                                                None],
                 entry_edit_callback: Callable[['ColourChannel', float], None],
                 mouse1_press_callbacks: List[Callable[[], None]]):
        self.__frame = DirectFrame(parent=parent)
        self.__slider_edit_callback = slider_edit_callback
        self.__entry_edit_callback = entry_edit_callback

        self.__label = DirectLabel(parent=self.__frame,
                                   text=text,
                                   text_fg=WHITE,
                                   text_bg=WINDOW_BG_COLOUR,
                                   pos=(-0.5, 0.0, 0.0),
                                   scale=(0.1, 1.0, 0.1))

        self.__slider = DirectSlider(parent=self.__frame,
                                     orientation=DGG.HORIZONTAL,
                                     borderWidth=(0.0, 0.0),
                                     frameColor=WIDGET_BG_COLOUR,
                                     frameSize=(-1.0, 1.0, -0.4, 0.4),
                                     thumb_frameSize=(-0.075, 0.075, -0.2,
                                                      0.2),
                                     value=value,
                                     pos=(0.05, 0.0, 0.0255),
                                     scale=(0.45, 1.0, 0.5))

        self.__entry_hovered = False
        mouse1_press_callbacks.append(self.__entry_mouse_click_callback)
        self.__entry = DirectEntry(parent=self.__frame,
                                   frameColor=WIDGET_BG_COLOUR,
                                   text_fg=WHITE,
                                   initialText=str(value),
                                   scale=0.1,
                                   width=3,
                                   suppressKeys=True,
                                   pos=(0.55, 0.0, -0.01105))
        self.__entry.bind(DGG.EXIT, self.__entry_exit_callback)
        self.__entry.bind(DGG.ENTER, self.__entry_enter_callback)
        self.__entry.bind(DGG.B1PRESS, self.__entry_mouse_click_callback)
        self.accept("mouse1", self.__entry_mouse_click_callback)

        self.__disable_frame_overlay = DirectButton(parent=self.__frame,
                                                    frameColor=TRANSPARENT,
                                                    borderWidth=(0.0, 0.0),
                                                    frameSize=(-0.6, 0.9, -0.2,
                                                               0.2),
                                                    suppressMouse=True)
        self.__disable_frame_overlay.hide()
        self.__enabled = True

        self.__set_callbacks()

    def __entry_exit_callback(self, *discard) -> None:
        self.__entry_hovered = False

    def __entry_enter_callback(self, *discard) -> None:
        self.__entry_hovered = True

    def __entry_mouse_click_callback(self, *discard) -> None:
        if self.__entry_hovered:
            s = self.__entry.get()
            try:
                f = float(s)
            except:
                return
            self.__entry_edit_callback(self, f)
        else:
            self.__entry['focus'] = False

    def __unset_callbacks(self):
        self.__slider['command'] = None
        self.__entry['command'] = None

    def __set_callbacks(self):
        def slider_callback() -> None:
            self.__slider_edit_callback(self, self.__slider['value'])

        def entry_callback(s) -> None:
            try:
                f = float(s)
            except:
                return
            self.__entry_edit_callback(self, f)

        self.__slider['command'] = slider_callback
        self.__entry['command'] = entry_callback

    @property
    def frame(self) -> DirectFrame:
        return self.__frame

    def update_slider(self, value: float):
        if not self.__enabled:
            return
        self.__unset_callbacks()
        self.__slider['value'] = value
        self.__set_callbacks()

    def update_entry(self, value: float):
        if not self.__enabled:
            return
        self.__unset_callbacks()
        self.__entry.enterText(f'{value:.3f}')
        self.__set_callbacks()

    def update(self, value: float):
        self.update_slider(value)
        self.update_entry(value)

    @property
    def value(self) -> float:
        return self.__slider['value']

    @property
    def enabled(self) -> str:
        return 'enabled'

    @enabled.setter
    def enabled(self, enabled: bool) -> None:
        if self.__enabled == enabled:
            return
        self.__enabled = enabled
        if enabled:
            self.__disable_frame_overlay.hide()
        else:
            self.__disable_frame_overlay.show()

    @enabled.getter
    def enabled(self) -> bool:
        return self.__enabled
Example #15
0
class MyApp(ShowBase):    
    def __init__(self):
        """
        Initialize the MyApp class, including defining the GUI objects and layout.
        Inherits from ShowBase.
        """
        
        # Because MyApp inherits from ShowBase, ShowBase needs to be initialized also (?) 
        ShowBase.__init__(self)
        
        # doesn't disable the mouse, only disables the default setting of the mouse controlling the camera 
        # can't import base and showbase at the same time. showbase is moreimportant right now.
        #base.disableMouse()
        
        # prints the coords of direct gui objects (DGO) when 'P' key is pressed or LMB is clicked
        self.accept("p", self.getDGOcoords)
        self.accept("mouse1", self.getDGOcoords) # only catches mouse when clicked on not gui elements >:|
                
        # add frmChatBox
        self.frmChatBox = DirectFrame(frameColor=(0, 255, 0, 1), frameSize=(-0.5, 0.5, -0.25, 0.25), pos=(0, 0, 0))
        
        ### Add some gui objects and parent them to 'frmChatBox'. They move relative to 'frmChatBox', but are positioned relative to aspect2d. WHY??
        ### Solution might be to create the frame at 0,0,0 and the DGOs relative to it (currently at 0,0,0) THEN move the frame.
        ### TODO: get mouse coords on screen to help with sizing DGOs? 
        
        # add button
        btnClear = DirectButton(pos=(-0.15,0,-0.95),text = ("Clear", "CLEAR", "Clear", "disabled"), scale=.05, command=self.clearText, parent=self.frmChatBox)
        
        # add text entry box
        self.txtEntry = DirectEntry(text = "",pos=(-0.99,0,-0.95),scale=.05,command=self.setTextBox,initialText="Type Something", numLines = 2, focus=1, parent=self.frmChatBox)
        
        # add button 
        btnCommit = DirectButton(pos=(-0.35,0,-0.95),text = ("Commit", "COMMIT", "Commit", "disabled"), scale=.05, command=self.changeText, parent=self.frmChatBox)
        
        # define some text to be used in 
        bk_text = "This is my Demo"
        
        # add text label, not parented to 'frmChatBox'
        self.lblLabel = DirectLabel(text = bk_text, pos = (0.95, 0, -0.95), scale = 0.07, text_fg=(1,0.5,0.5,1), text_bg=(0,0,0,1), textMayChange=1)       
    

    def changeText(self):
        """ 
        Gets the text from input box "txtEntry" and sets it as the text of label "lblLabel"
        """
        bk_text = self.txtEntry.get()
        self.lblLabel['text'] = bk_text
        
        
    def setTextBox(self, textEntered):
        """
        Sets the text of label "textObject" to the value passed
        """
        self.textObject['text'] = textEntered
        
        
    def clearText(self):
        """
        Clears the text entry box
        """
        self.txtEntry.enterText('')
        
        
    def getDGOcoords(self):
        """
        Prints the coordinates of DirectGUI objects
        """
        for child in self.frmChatBox.getChildren():
            if "Direct" in str(child):
                print child, "  position = ", child.getPos() 
                print child, "  scale = ", child.getScale()
        print "-" * 10
Example #16
0
class ChatBox(DirectObject):
    
    MESSAGE_LIFE = 10
    MAX_NUM_MESSAGES = 15
    
    (TYPE_GLOBAL,
     TYPE_TEAM,
     TYPE_CONSOLE) = range(3)
     
    messageTypeToPrefix = { TYPE_GLOBAL : 'Global:', 
                            TYPE_TEAM : 'Team:',
                            TYPE_CONSOLE : 'Console' }
    
    def __init__(self):
        self.textNodes = []
        self.messageType = None
        
        self.rootFrame = DirectFrame(pos = (0.03, 0, 0.2),
                                 frameColor = (0, 0, 0, 0),
                                 frameSize = (0, 1, 0, 1),
                                 parent = base.a2dBottomLeft)
        self.rootFrame.setBin('fixed', GUIOrder.ORDER[GUIOrder.CHAT])
        
        self.entryFrame = DirectFrame(pos = (0, 0, 0),
                                 frameColor = (0, 0, 0, 0.1),
                                 frameSize = (0, 1, 0, 0.1),
                                 parent = self.rootFrame)
        
        self.chatarea = DirectEntry(width = 27,
                                    scale = Settings.CHAT_HEIGHT,
                                    pos = (0, 0, 0),
                                    frameColor = (0, 0, 0, 0),
                                    text_fg = (1, 1, 1, 1),
                                    numLines = 1,
                                    cursorKeys = 1,
                                    rolloverSound = None,
                                    clickSound = None,
                                    focus = 0,
                                    command = self.OnChatEntered,
                                    parent = self.entryFrame)
        
        self.typeText = OnscreenText(text = '', 
                                     pos = (0, Settings.CHAT_HEIGHT + 0.01), 
                                     scale = Settings.CHAT_HEIGHT,
                                     fg = (1, 1, 1, 1),
                                     mayChange = True,
                                     align = TextNode.ALeft,
                                     parent = self.entryFrame)
        
        self.displayFrame = DirectFrame(pos = (0, 0, 0.1),
                                 frameColor = (0, 0, 0, 0),
                                 frameSize = (0, 1, 0, 0.42),
                                 parent = self.rootFrame)
        
        self.chatarea.enterText('')
        self.entryFrame.hide()
        self.chatarea['focus'] = 0
        self.chatarea.setFocus()    
        
    def OnChatEntered(self, enteredText):
        enteredText = enteredText.strip()
        self.Hide()
        if(len(enteredText) > 0):
            ChatEnteredEvent(self.messageType, enteredText).Fire()
        
    def AddMessage(self, prefix, prefixColor, message):
        parent = self.displayFrame.attachNewNode('messageParent')
        
        prefixTextNode = TextNode('prefixMessage')
        prefixTextNode.setText(prefix)
        prefixTextNode.setTextColor(prefixColor)
        prefixTextNode.setShadow(0.05, 0.05)
        prefixTextNode.setShadowColor(Globals.COLOR_BLACK)
        prefixTextNodePath = parent.attachNewNode(prefixTextNode)
        prefixTextNodePath.setScale(Settings.CHAT_HEIGHT)
        
        messageTextNode = TextNode('prefixMessage')
        messageTextNode.setText(message)
        messageTextNode.setTextColor(1, 1, 1, 1)
        messageTextNode.setShadow(0.05, 0.05)
        messageTextNode.setShadowColor(Globals.COLOR_BLACK)
        messageTextNodePath = parent.attachNewNode(messageTextNode)
        messageTextNodePath.setScale(Settings.CHAT_HEIGHT)
        messageTextNodePath.setPos(Vec3(prefixTextNode.calcWidth(prefix) * Settings.CHAT_HEIGHT, 0, 0))
        
        taskMgr.remove('HideMessageLog')
        taskMgr.doMethodLater(ChatBox.MESSAGE_LIFE, self.HideMessageLog, 'HideMessageLog') 
        self.ShowMessageLog()
        
        self.textNodes.append(parent)
        
        if(len(self.textNodes) > ChatBox.MAX_NUM_MESSAGES):
            self.RemoveMessage(self.textNodes[0])
            
        self.RedrawMessages()
        
    def RedrawMessages(self):
        n = len(self.textNodes)
        for i, textNode in enumerate(self.textNodes):
            LerpPosInterval(textNode, 0.5, (0, 0, (n-i) * (Settings.CHAT_HEIGHT + 0.01))).start()
            
    def RemoveMessage(self, textNode):
        self.textNodes.remove(textNode)
        textNode.removeNode()
        
    def HideMessageLog(self, task = None):
        self.displayFrame.hide()
        
    def ShowMessageLog(self):
        self.displayFrame.show()
        
    def Hide(self):
        self.chatarea.enterText('')
        self.entryFrame.hide()
        self.chatarea['focus'] = 0
        self.chatarea.setFocus()
        self.HideMessageLog()
        ChatCloseEvent().Fire()
        
    def Show(self, messageType):
        self.messageType = messageType
        self.entryFrame.show()
        self.chatarea['focus'] = 1
        self.chatarea.setFocus()
        self.typeText.setText(ChatBox.GetPrefix(self.messageType))
        self.ShowMessageLog()
        ChatOpenEvent().Fire()
        
    def EnableKeyboardListening(self):
        self.acceptOnce('escape', self.Hide)
        
    def DisableKeyboardListening(self):
        self.ignoreAll()
        
    @staticmethod
    def GetPrefix(messageType):
        return ChatBox.messageTypeToPrefix[messageType]
    
    def Destroy(self):
        taskMgr.remove('HideMessageLog')
        self.rootFrame.destroy()
        self.entryFrame.destroy()
        self.chatarea.destroy()
        self.typeText.destroy()
        self.displayFrame.destroy()
        self.ignoreAll()
        
  def __call__(self): return self.impl()
    
class _GetchUnix:
  def __init__(self):
    import tty, sys, termios # import termios now or else you'll get the Unix version on the Mac
  def __call__(self):
    import sys, tty, termios
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
      tty.setraw(sys.stdin.fileno())
      ch = sys.stdin.read(1)
    finally:
      termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch
class _GetchWindows:
  def __init__(self):
    import msvcrt
  def __call__(self):
    import msvcrt
    return msvcrt.getch()

class _GetchMacCarbon:
  """
  A function which returns the current ASCII key that is down;
  if no ASCII key is down, the null string is returned.  The
  page http://www.mactech.com/macintosh-c/chap02-1.html was
  very helpful in figuring out how to do this.
  """
  def __init__(self):
    import Carbon
    Carbon.Evt #see if it has this (in Unix, it doesn't)
  def __call__(self):
    import Carbon
    if Carbon.Evt.EventAvail(0x0008)[0]==0: # 0x0008 is the keyDownMask
      return ''
    else:
      #
      # The event contains the following info:
      # (what,msg,when,where,mod)=Carbon.Evt.GetNextEvent(0x0008)[1]
      #
      # The message (msg) contains the ASCII char which is
      # extracted with the 0x000000FF charCodeMask; this
      # number is converted to an ASCII character with chr() and
      # returned
      #
      (what,msg,when,where,mod)=Carbon.Evt.GetNextEvent(0x0008)[1]
      return chr(msg & 0x000000FF)

# ---- character reading from console - END ----





class pandaInteractiveConsole( InteractiveConsole, DirectObject.DirectObject ):
  def __init__( self, locals, interfaces=GUI|CONSOLE ):
    print "I: pandaInteractiveConsole.__init__"
    
    InteractiveConsole.__init__( self, locals )
   
    self.guiEnabled = (interfaces & GUI)
    if self.guiEnabled:
      print "I:  - GUI enabled"
      
      top = 1/SCALE - (V_SPACE/SCALE)
      bottom = 1/SCALE - (V_SPACE/SCALE) - (V_SIZE/SCALE)
      # panda3d interface
      self.consoleFrame = DirectFrame( relief = DGG.GROOVE
        , frameColor = (200, 200, 200, 0.85), scale=SCALE
        , frameSize = (-1/SCALE, 1/SCALE, top, bottom))
      self.accept( "f1", self.toggleConsole )
      # text entry line
      self.consoleEntry = DirectEntry( self.consoleFrame, text = "", command=self.setText, width = 1/SCALE*2-2
        , pos =(-1/SCALE+1,0,bottom+1), initialText="", numLines = 1, focus=1)
      # output lines
      self.consoleOutputList = list()
      for i in xrange( NUMLINES ):
        label = OnscreenText( parent = self.consoleFrame, text = "", pos = (-1/SCALE+1, bottom+1+NUMLINES-i) #-1-i)
          , align=TextNode.ALeft, mayChange=1, scale=1.0)
        self.consoleOutputList.append( label )
        self.toggleConsole()
        
    self.consoleEnabled = (interfaces & CONSOLE)
    self.stdout = sys.stdout
    if self.consoleEnabled:
      print "I:  - Console enabled"
      # function to read the keyboard inputs
      self.readKey = _Getch()
      
      # redirect input and output
      self.stdout = sys.stdout
      sys.stdout = self
      if sys.platform == 'linux2' or sys.platform == 'darwin':
        self.setConsoleNonBlocking( self.stdout )
    
    self.write( "D: myInteractiveConsole.__init__\n" )
    # buffer of current text
    self.linebuffer = ''
    self.linebufferPos = 0
  
  def setConsoleBlocking( self, fd_in ):
    fd = fd_in.fileno()
    fl = fcntl.fcntl(fd, fcntl.F_GETFL)
    try:
    	fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.FNDELAY)
    except:
      pass
  
  def setConsoleNonBlocking( self, fd_in ):
    fd = fd_in.fileno()
    fl = fcntl.fcntl(fd, fcntl.F_GETFL)
    try:
      fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
    except:
      self.write( "D: console init failed\n" )
      self.setConsoleBlocking( fd )
    
    '''
    # set read non blocking
    fd = sys.stdin.fileno()
    self.oldterm = termios.tcgetattr(fd)
    newattr = self.oldterm
    self.oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
    newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
    termios.tcsetattr(fd, termios.TCSANOW, newattr)
    fcntl.fcntl(fd, fcntl.F_SETFL, self.oldflags | os.O_NONBLOCK)
    '''
  
  def __del__( self ):
    if self.consoleEnabled:
      sys.stdout = self.stdout
      if sys.platform == 'linux2' or sys.platform == 'darwin':
        self.write( "setting old terminal settings\n" )
        fd = sys.stdin.fileno()
        termios.tcsetattr(fd, termios.TCSAFLUSH, self.oldterm)
        fcntl.fcntl(fd, fcntl.F_SETFL, self.oldflags)
  
  def toggleConsole( self ):
    self.consoleFrame.toggleVis()
    self.consoleEntry['focus'] != self.consoleFrame.isHidden
  
  def setText(self, textEntered):
    self.write( ">%s" % textEntered )
    output = self.push( textEntered )
    # clear line
    self.consoleEntry.enterText('')
    self.consoleEntry['focus'] = 1
  
  def writeP3dConsole( self, printString ):
    # remove carriage returns (causes disort in output)
    printString = printString.strip()
    # remove not printable characters (which can be input by console input)
    printString = re.sub( r"[^%s]" % string.printable, "", printString )
    # only write lines which contain something
    if printString.strip() != '':
      while len(printString) > LINELENGTH:
        writeString = printString[0:LINELENGTH]
        printString = printString[LINELENGTH:]
        # output on panda3d interface
        for i in xrange( NUMLINES-1 ):
          self.consoleOutputList[i].setText( self.consoleOutputList[i+1].getText() )
        self.consoleOutputList[NUMLINES-1].setText( writeString )
      # output on panda3d interface
      for i in xrange( NUMLINES-1 ):
        self.consoleOutputList[i].setText( self.consoleOutputList[i+1].getText() )
      self.consoleOutputList[NUMLINES-1].setText( printString )
  
  def write( self, string ):
    # write a text the console
    try:
      if self.consoleEnabled:
        # output on console
        self.stdout.write( string )
class DeveloperConsole(InteractiveInterpreter, DirectObject):
    """The name says it all."""
    def __init__(self, xml):
        sys.stdout = PseudoFile(self.writeOut)
        sys.stderr = PseudoFile(self.writeErr)
        tpErr = TextProperties()
        tpErr.setTextColor(1, 0.5, 0.5, 1)
        TextPropertiesManager.getGlobalPtr().setProperties("err", tpErr)
        font = loader.loadFont("cmss12")
        self.frame = DirectFrame(parent=base.a2dTopCenter, text_align=TextNode.ALeft, text_pos=(-base.getAspectRatio() + TEXT_MARGIN[0], TEXT_MARGIN[1]), text_scale=0.05, text_fg=(1, 1, 1, 1), frameSize=(-2.0, 2.0, -0.5, 0.0), frameColor=(0, 0, 0, 0.5), text='', text_font=font)
        self.entry = DirectEntry(parent=base.a2dTopLeft, command=self.command, scale=0.05, width=1000.0, pos=(-0.02, 0, -0.48), relief=None, text_pos=(1.5, 0, 0), text_fg=(1, 1, 0.5, 1), rolloverSound=None, clickSound=None, text_font=font)
        self.otext = OnscreenText(parent=self.entry, scale=1, align=TextNode.ALeft, pos=(1, 0, 0), fg=(1, 1, 0.5, 1), text=':', font=font)
        self.lines = [''] * 9
        self.commands = []  # All previously sent commands
        self.cscroll = None  # Index of currently navigated command, None if current
        self.command = ''   # Currently entered command
        self.block = ''     # Temporarily stores a block of commands
        self.hide()
        self.initialized = False

        self.toggleKeys = manager.controls.registerKeyAll("Toggle Console", "`", self.toggle, self)

    def reload(self, xml):
        pass

    def prevCommand(self):
        if self.hidden:
            return
        if len(self.commands) == 0:
            return
        if self.cscroll == None:
            self.cscroll = len(self.commands)
            self.command = self.entry.get()
        elif self.cscroll <= 0:
            return
        else:
            self.commands[self.cscroll] = self.entry.get()
        self.cscroll -= 1
        self.entry.set(self.commands[self.cscroll])
        self.entry.setCursorPosition(len(self.commands[self.cscroll]))

    def nextCommand(self):
        if self.hidden:
            return
        if len(self.commands) == 0:
            return
        if self.cscroll == None:
            return
        self.commands[self.cscroll] = self.entry.get()
        self.cscroll += 1
        if self.cscroll >= len(self.commands):
            self.cscroll = None
            self.entry.set(self.command)
            self.entry.setCursorPosition(len(self.command))
        else:
            self.entry.set(self.commands[self.cscroll])
            self.entry.setCursorPosition(len(self.commands[self.cscroll]))

    def writeOut(self, line, copy=True):
        if copy:
            sys.__stdout__.write(line)
        lines = line.split('\n')
        firstline = lines.pop(0)
        self.lines[-1] += firstline
        self.lines += lines
        self.frame['text'] = '\n'.join(self.lines[-9:])

    def writeErr(self, line, copy=True):
        if copy:
            sys.__stderr__.write(line)
        line = '\1err\1%s\2' % line
        lines = line.split('\n')
        firstline = lines.pop(0)
        self.lines[-1] += firstline
        self.lines += lines
        self.frame['text'] = '\n'.join(self.lines[-9:])

    def command(self, text):
        if not self.hidden:
            self.cscroll = None
            self.command = ''
            self.entry.set('')
            self.entry['focus'] = True
            self.writeOut(self.otext['text'] + ' ' + text + '\n', False)
            if text != '' and (len(self.commands) == 0 or self.commands[-1] != text):
                self.commands.append(text)

            # Insert plugins into the local namespace
            locals = __main__.__dict__
            for plugin in manager.getNamed().keys():
                locals[plugin] = manager.getNamed()[plugin]
            locals['panda3d'] = panda3d

            #register custom commands
            locals['reload'] = manager.reload
            locals['load'] = manager.transition
            locals['wireframe'] = base.toggleWireframe
            locals['trigger'] = events.triggerEvent

            # Run it and print the output.
            if not self.initialized:
                InteractiveInterpreter.__init__(self, locals=locals)
                self.initialized = True
            try:
                if self.runsource(self.block + '\n' + text) and text != '':
                    self.otext['text'] = '.'
                    self.block += '\n' + text
                else:
                    self.otext['text'] = ':'
                    self.block = ''
            except Exception:  # Not just "except", it will also catch SystemExit
                # Whoops! Print out a traceback.
                self.writeErr(traceback.format_exc())

    def toggle(self):
        #remove toggle key from entry
        if self.entry['focus']:
            for gtype in self.toggleKeys.keys():
                key = self.toggleKeys[gtype]
                entryLen = len(self.entry.get(True))
                if self.entry.get(True)[entryLen - len(key):entryLen] == key:
                    self.entry.enterText(self.entry.get(True)[:entryLen - len(key)])
        if self.hidden:
            self.show()
        else:
            self.hide()

    def start(self):
        return
        #self.toggle()

    def stop(self):
        return
        #self.toggle()

    def show(self):
        self.accept('arrow_up', self.prevCommand)
        self.accept('arrow_up-repeat', self.prevCommand)
        self.accept('arrow_down', self.nextCommand)
        self.accept('arrow_down-repeat', self.nextCommand)
        self.hidden = False
        self.entry['focus'] = True
        self.frame.show()
        self.entry.show()
        self.otext.show()

    def hide(self):
        self.ignoreAll()
        self.hidden = True
        self.entry['focus'] = False
        self.frame.hide()
        self.entry.hide()
        self.otext.hide()

    def destroy(self):
        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__
        self.ignoreAll()
        self.frame.destroy()
        self.entry.destroy()
        self.otext.destroy()
Example #19
0
class Login(object):
    def __init__(self, main):
        self.main = main

        self.frame = None
        self.title = None
        self.error = None
        self.username = None
        self.userTextbox = None
        self.password = None
        self.passTextbox = None
        self.cpassword = None
        self.cpassTextbox = None
        self.submitBtn = None
        self.registerBtn = None
        self.cancelBtn = None

    # login screen
    def createLoginWindow(self):
        self.frame = DirectFrame(frameColor = (0, 0, 0, 1),
                                 frameSize = (-1.35, 1.35, -1, 1),
                                 pos = (0, 0, 0))

        self.title = OnscreenText(text = 'Login',
                                  pos = (0, 0.3),
                                  scale = 0.15,
                                  fg = (1, 0.5, 0.5, 1),
                                  align = TextNode.ACenter,
                                  parent = self.frame,
                                  mayChange = False)

        # username
        self.username = OnscreenText(text = 'Username:'******'',
                                       scale = 0.05,
                                       pos = (0.1, 0, 0),
                                       initialText = '[username]',
                                       numLines = 1,
                                       focus = 1,
                                       focusInCommand = self.userTextFocus,
                                       focusOutCommand = self.userTextBlur)

        # password
        self.password = OnscreenText(text = 'Password:'******'',
                                       scale = 0.05,
                                       pos = (0.1, 0, -0.2),
                                       initialText = '[password]',
                                       numLines = 1,
                                       focus = 0,
                                       focusInCommand = self.passTextFocus,
                                       focusOutCommand = self.passTextBlur)

        # buttons
        self.submitBtn = DirectButton(self.frame, # parent
                                      text = 'Login',
                                      scale = 0.08,
                                      command = self.clickedSubmit,
                                      pos = (0.8, 0.0, -0.90),
                                      text_bg = (1, 0.5, 0.5, 1),
								      relief = None)
        self.registerBtn = DirectButton(self.frame, # parent
                                        text = 'Register',
                                        scale = 0.08,
                                        command = self.clickedRegister,
                                        pos = (0.5, 0.0, -0.90),
                                        text_bg = (1, 0.5, 0.5, 1),
								        relief = None)
        self.cancelBtn = DirectButton(self.frame, # parent
                                      text = 'Cancel',
                                      scale = 0.08,
                                      command = self.clickedCancel,
                                      pos = (0.2, 0.0, -0.90),
                                      text_bg = (1, 0.5, 0.5, 1),
								      relief = None)

    def destroyLoginWindow(self):
        self.frame.destroy()
        self.frame = None
        self.title = None
        self.error = None
        self.username = None
        self.userTextbox = None
        self.password = None
        self.passTextbox = None
        self.submitBtn = None
        self.registerBtn =  None
        self.cancelBtn =  None

    # register screen
    def createRegisterWindow(self):
        self.frame = DirectFrame(frameColor = (0, 0, 0, 1),
                                 frameSize = (-1.35, 1.35, -1, 1),
                                 pos = (0, 0, 0))

        self.title = OnscreenText(text = 'Register',
                                  pos = (0, 0.3),
                                  scale = 0.15,
                                  fg = (1, 0.5, 0.5, 1),
                                  align = TextNode.ACenter,
                                  parent = self.frame,
                                  mayChange = False)

        # username
        self.username = OnscreenText(text = 'Username:'******'',
                                       scale = 0.05,
                                       pos = (0.1, 0, 0),
                                       initialText = '[username]',
                                       numLines = 1,
                                       focus = 1,
                                       focusInCommand = self.userTextFocus,
                                       focusOutCommand = self.userTextBlur)

        # password
        self.password = OnscreenText(text = 'Password:'******'',
                                       scale = 0.05,
                                       pos = (0.1, 0, -0.2),
                                       initialText = '[password]',
                                       numLines = 1,
                                       focus = 0,
                                       focusInCommand = self.passTextFocus,
                                       focusOutCommand = self.passTextBlur)

        # confirm password
        self.cpassword = OnscreenText(text = 'Confirm Password:'******'',
                                        scale = 0.05,
                                        pos = (0.1, 0, -0.4),
                                        initialText = '[confirm password]',
                                        numLines = 1,
                                        focus = 0,
                                        focusInCommand = self.cpassTextFocus,
                                        focusOutCommand = self.cpassTextBlur)

        # buttons
        self.registerBtn =  DirectButton(self.frame, # parent
                                         text = 'Register',
                                         scale = 0.08,
                                         command = self.clickedRegRegister,
                                         pos = (0.8, 0.0, -0.90),
                                         text_bg = (1, 0.5, 0.5, 1),
								         relief = None)
        self.cancelBtn =  DirectButton(self.frame, # parent
                                       text = 'Cancel',
                                       scale = 0.08,
                                       command = self.clickedRegCancel,
                                       pos=(0.2, 0.0, -0.90),
                                       text_bg = (1, 0.5, 0.5, 1),
								       relief = None)

    def destroyRegisterWindow(self):
        self.frame.destroy()
        self.frame = None
        self.title = None
        self.error = None
        self.username = None
        self.userTextbox = None
        self.password = None
        self.passTextbox = None
        self.cpassword = None
        self.cpassTextbox = None
        self.registerBtn = None
        self.cancelBtn = None

    # error message helper
    def displayError(self, msg):
        if self.frame is None: return
        if self.error is not None: self.error.destroy()
        self.error = OnscreenText(text = msg,
                                  pos = (0, -0.65),
                                  scale = 0.06,
                                  fg = (1, 0.5, 0.5, 1),
                                  align = TextNode.ACenter,
                                  parent = self.frame,
                                  mayChange = False)

    # userTextbox handlers
    def userTextFocus(self):
        if self.userTextbox.get() == '[username]': self.userTextbox.enterText('')

    def userTextBlur(self):
        if self.userTextbox.get().strip() == '': self.userTextbox.enterText('[username]')

    # passTextbox handlers
    def passTextFocus(self):
        if self.passTextbox.get() == '[password]': self.passTextbox.enterText('')

    def passTextBlur(self):
        if self.passTextbox.get().strip() == '': self.passTextbox.enterText('[password]')

    # cpassTextbox handlers
    def cpassTextFocus(self):
        if self.cpassTextbox.get() == '[confirm password]': self.cpassTextbox.enterText('')

    def cpassTextBlur(self):
        if self.cpassTextbox.get().strip() == '': self.cpassTextbox.enterText('[confirm password]')

    # login button handlers
    def clickedSubmit(self):
        username = self.userTextbox.get().strip()
        password = self.passTextbox.get().strip()
        if username != '' and password != '':
            self.main.cManager.sendRequest(Constants.C_AUTH, {'username': username, 'password': password})
        else:
            self.displayError('Please enter a username and password.')

    def clickedRegister(self):
        self.destroyLoginWindow()
        self.createRegisterWindow()

    def clickedCancel(self):
        exit()

    # register button handlers
    def clickedRegRegister(self):
        username = self.userTextbox.get().strip()
        password = self.passTextbox.get().strip()
        cpass = self.cpassTextbox.get().strip()
        if username != '':
            if password != '':
                if cpass == password:
                    self.main.cManager.sendRequest(Constants.C_REGISTER, {'username': username, 'password': password})
                    self.destroyRegisterWindow()
                    self.createLoginWindow()
                else:
                    self.displayError('Your passwords do not match.')
            else:
                self.displayError('Please enter a password.')
        else:
            self.displayError('Please enter a username.')

    def clickedRegCancel(self):
        self.destroyRegisterWindow()
        self.createLoginWindow()
Example #20
0
class MyApp(ShowBase):
    def __init__(self):
        """
        Initialize the MyApp class, including defining the GUI objects and layout.
        Inherits from ShowBase.
        """

        # Because MyApp inherits from ShowBase, ShowBase needs to be initialized also (?)
        ShowBase.__init__(self)

        # doesn't disable the mouse, only disables the default setting of the mouse controlling the camera
        # can't import base and showbase at the same time. showbase is moreimportant right now.
        #base.disableMouse()

        # prints the coords of direct gui objects (DGO) when 'P' key is pressed or LMB is clicked
        self.accept("p", self.getDGOcoords)
        self.accept(
            "mouse1", self.getDGOcoords
        )  # only catches mouse when clicked on not gui elements >:|

        # add frmChatBox
        self.frmChatBox = DirectFrame(frameColor=(0, 255, 0, 1),
                                      frameSize=(-0.5, 0.5, -0.25, 0.25),
                                      pos=(0, 0, 0))

        ### Add some gui objects and parent them to 'frmChatBox'. They move relative to 'frmChatBox', but are positioned relative to aspect2d. WHY??
        ### Solution might be to create the frame at 0,0,0 and the DGOs relative to it (currently at 0,0,0) THEN move the frame.
        ### TODO: get mouse coords on screen to help with sizing DGOs?

        # add button
        btnClear = DirectButton(pos=(-0.15, 0, -0.95),
                                text=("Clear", "CLEAR", "Clear", "disabled"),
                                scale=.05,
                                command=self.clearText,
                                parent=self.frmChatBox)

        # add text entry box
        self.txtEntry = DirectEntry(text="",
                                    pos=(-0.99, 0, -0.95),
                                    scale=.05,
                                    command=self.setTextBox,
                                    initialText="Type Something",
                                    numLines=2,
                                    focus=1,
                                    parent=self.frmChatBox)

        # add button
        btnCommit = DirectButton(pos=(-0.35, 0, -0.95),
                                 text=("Commit", "COMMIT", "Commit",
                                       "disabled"),
                                 scale=.05,
                                 command=self.changeText,
                                 parent=self.frmChatBox)

        # define some text to be used in
        bk_text = "This is my Demo"

        # add text label, not parented to 'frmChatBox'
        self.lblLabel = DirectLabel(text=bk_text,
                                    pos=(0.95, 0, -0.95),
                                    scale=0.07,
                                    text_fg=(1, 0.5, 0.5, 1),
                                    text_bg=(0, 0, 0, 1),
                                    textMayChange=1)

    def changeText(self):
        """ 
        Gets the text from input box "txtEntry" and sets it as the text of label "lblLabel"
        """
        bk_text = self.txtEntry.get()
        self.lblLabel['text'] = bk_text

    def setTextBox(self, textEntered):
        """
        Sets the text of label "textObject" to the value passed
        """
        self.textObject['text'] = textEntered

    def clearText(self):
        """
        Clears the text entry box
        """
        self.txtEntry.enterText('')

    def getDGOcoords(self):
        """
        Prints the coordinates of DirectGUI objects
        """
        for child in self.frmChatBox.getChildren():
            if "Direct" in str(child):
                print child, "  position = ", child.getPos()
                print child, "  scale = ", child.getScale()
        print "-" * 10
Example #21
0
class GuiConsole(DirectObject.DirectObject):
    def __init__(self, class_parent, parent, h_size, v_size, aspect, hugpos):
        self.h_size = h_size
        self.v_size = v_size
        self.scale = 0.04
        self.parent = class_parent
        self.numlines = int(v_size / self.scale - 2)

        self.pos_min_x = 0
        self.pos_min_y = 0
        self.pos_max_x = self.h_size
        self.pos_max_y = 0.7

        if aspect > 0:
            self.pos_max_x /= aspect
        else:
            self.pos_max_y *= aspect

        self.consoleFrame = DirectFrame(relief=DGG.RIDGE,
                                        frameColor=(0, 0, 0, 0),
                                        scale=self.scale,
                                        frameSize=(0, self.h_size / self.scale,
                                                   0,
                                                   self.v_size / self.scale))

        if parent == base.a2dBottomLeft:  #@UndefinedVariable
            self.pos_min_x -= 1
            self.pos_min_y -= 1
            self.pos_max_x -= 1
            self.pos_max_y -= 1

        if hugpos == "bottom":
            self.consoleFrame.setPos(0, 0, GUI_BOTTOM_OFFSET - 0.085)
            self.pos_min_x = 0
            self.pos_min_y = GUI_BOTTOM_OFFSET - 0.085 - 0.07
            self.pos_max_x = self.h_size
            self.pos_max_y = GUI_BOTTOM_OFFSET - 0.085

        fixedWidthFont = loader.loadFont(GUI_FONT)  #@UndefinedVariable
        #fixedWidthFont.setPixelsPerUnit(60)
        #fixedWidthFont.setRenderMode(fixedWidthFont.RMSolid)
        if not fixedWidthFont.isValid():
            print "pandaInteractiveConsole.py :: could not load the defined font %s" % str(
                self.font)
            fixedWidthFont = DGG.getDefaultFont()

        #fixedWidthFont.setPageSize(512,512)
        #fixedWidthFont.setPixelsPerUnit(60)

        self.consoleEntry = DirectEntry(
            self.consoleFrame,
            text="",
            command=self.onEnterPress
            #, width       = self.h_size/self.scale -2
            ,
            pos=(0.01, 0, 0.02),
            initialText="Enter text...",
            numLines=1,
            focus=0,
            entryFont=fixedWidthFont,
            scale=1,
            frameColor=(0, 0, 0, 0.2),
            text_fg=(0, 1, 0, 1),
            text_shadow=(0, 0, 0, 1))

        #self.consoleEntry = DirectEntry(self.consoleFrame)

        self.consoleEntry["frameSize"] = (0, self.h_size / self.scale, 0, 1)
        self.consoleEntry["width"] = self.h_size / self.scale
        self.consoleEntry["focusInCommand"] = self.focusInCallback
        self.consoleEntry["focusOutCommand"] = self.focusOutCallback

        self.consoleFrame.reparentTo(parent)

        self.textBuffer = list()
        self.textBufferLength = 100
        for i in xrange(self.textBufferLength):
            self.textBuffer.append(['', (100, 100, 100, 1)])
        self.textBufferPos = self.textBufferLength - self.numlines

        # output lines
        self.consoleOutputList = list()
        for i in xrange(self.numlines):
            label = OnscreenText(parent=self.consoleFrame,
                                 text="",
                                 pos=(0, i + 1.5),
                                 align=TextNode.ALeft,
                                 mayChange=1,
                                 scale=1.0,
                                 fg=(100, 100, 100, 1),
                                 shadow=(0, 0, 0, 1))
            # , frame = (200,0,0,1) )
            label.setFont(fixedWidthFont)
            self.consoleOutputList.append(label)

        self.linelength = 57
        self.linewrap = textwrap.TextWrapper()
        self.linewrap.width = self.linelength
        self.toggleConsole()

    def focusInCallback(self):
        self.parent.parent.camera_manager.disableKeyMovement()

    def focusOutCallback(self):
        self.parent.parent.camera_manager.enableKeyMovement()

    def show(self):
        if self.consoleFrame.isHidden():
            self.consoleFrame.toggleVis()

    def hide(self):
        pass
        #if not self.consoleFrame.isHidden():
        #    self.consoleFrame.toggleVis()

    def toggleConsole(self):
        self.consoleFrame.toggleVis()
        hidden = self.consoleFrame.isHidden()
        #self.consoleEntry['focus'] != hidden
        if hidden:
            #self.ignoreAll()
            self.accept('control', self.toggleConsole)
            self.accept('enter', self.manageFocus)
            self.accept('escape', self.unfocus)
        else:
            #self.ignoreAll()
            #self.accept( 'page_up', self.scroll, [-5] )
            #self.accept( 'page_up-repeat', self.scroll, [-5] )
            #self.accept( 'page_down', self.scroll, [5] )
            #self.accept( 'page_down-repeat', self.scroll, [5] )
            #self.accept( 'window-event', self.windowEvent)

            #self.accept( 'arrow_up'  , self.scrollCmd, [ 1] )
            #self.accept( 'arrow_down', self.scrollCmd, [-1] )

            self.accept('control', self.toggleConsole)
            self.accept('enter', self.manageFocus)
            self.accept('escape', self.unfocus)
            #self.accept( self.autocomplete_key, self.autocomplete )
            #self.accept( self.autohelp_key, self.autohelp )

            # accept v, c and x, where c & x copy's the whole console text
            #messenger.toggleVerbose()
            #for osx use ('meta')
            #if sys.platform == 'darwin':
            #  self.accept( 'meta', self.unfocus )
            #  self.accept( 'meta-up', self.focus )
            #  self.accept( 'meta-c', self.copy )
            #  self.accept( 'meta-x', self.cut )
            #  self.accept( 'meta-v', self.paste )
            #for windows use ('control')
            #if sys.platform == 'win32' or sys.platform == 'linux2':
            #  self.accept( 'control', self.unfocus )
            #  self.accept( 'control-up', self.focus )
            #  self.accept( 'control-c', self.copy )
            #  self.accept( 'control-x', self.cut )
            #  self.accept( 'control-v', self.paste )

    def onEnterPress(self, textEntered):
        # set to last message
        self.textBufferPos = self.textBufferLength - self.numlines
        # clear line
        self.consoleEntry.enterText('')
        self.consoleOutput(textEntered, utils.CONSOLE_PLAYER1_TEXT)
        ClientMsg.chat(textEntered)
        self.focus()

    def manageFocus(self):
        if self.consoleFrame.isHidden():
            self.consoleFrame.toggleVis()

        if self.consoleEntry["focus"] == 0:
            self.focus()

    def consoleOutput(self, printString, msgType):
        if msgType == utils.CONSOLE_SYSTEM_ERROR:
            self.write(printString, utils.CONSOLE_SYSTEM_ERROR_TEXT_COLOR)
        elif msgType == utils.CONSOLE_SYSTEM_MESSAGE:
            self.write(printString, utils.CONSOLE_SYSTEM_MESSAGE_TEXT_COLOR)
        elif msgType == utils.CONSOLE_PLAYER1_TEXT:
            self.write(printString, utils.CONSOLE_PLAYER1_TEXT_COLOR)
        else:
            self.write(printString, utils.CONSOLE_PLAYER2_TEXT_COLOR)

    def write(self, printString, color=(100, 100, 100, 0.5)):
        # remove not printable characters (which can be input by console input)
        printString = re.sub(r'[^%s]' % re.escape(string.printable[:95]), "",
                             printString)

        splitLines = self.linewrap.wrap(printString)
        for line in splitLines:
            self.textBuffer.append([line, color])
            self.textBuffer.pop(0)

        self.updateOutput()

    def updateOutput(self):
        for lineNumber in xrange(self.numlines):
            lineText, color = self.textBuffer[lineNumber + self.textBufferPos]
            self.consoleOutputList[self.numlines - lineNumber -
                                   1].setText(lineText)
            self.consoleOutputList[self.numlines - lineNumber -
                                   1]['fg'] = color

    def focus(self):
        self.consoleEntry['focus'] = 1

    def unfocus(self):
        self.consoleEntry['focus'] = 0

    def getTightBounds(self):
        l, r, b, t = self.consoleFrame.getBounds()
        print l, r, b, t
        bottom_left = Point3(l, 0, b)
        top_right = Point3(r, 0, t)
        return (bottom_left, top_right)
Example #22
0
class ThiefHud(GameHud):
    def __init__(self):
        super().__init__()
        self.entryLabel = self.label(text='', mayChange=True)

        self.entry = DirectEntry(
            initialText='Type card name...',
            scale=0.05,
            focus=1,
            command=self.useThiefAbility,
            focusInCommand=lambda: self.entry.enterText(''))

        self.entry.hide()

        self.thiefAbilityButton = self.button(
            text="Faction Ability",
            scale=1,
            pos=(0, 0, -1),
            parent=self.endPhaseButton,
            command=self.onThiefAbilityButton)

    def useThiefAbility(self, cardname):
        try:
            cardId = next(c for c in base.enemy.deck
                          if c.name == cardname).cardId
        except StopIteration:
            print("That is not the name of an enemy card.")
        else:
            toDiscardIndex = base.player.hand.index(
                self.toDiscard.getPythonTag('card'))
            toStealIndex = base.enemy.facedowns.index(
                self.toSteal.getPythonTag('card'))
            base.networkManager.useThiefAbility(toDiscardIndex, cardId,
                                                toStealIndex)
            base.mouseHandler.targeting = False
            self.entry.hide()

    def onThiefAbilityButton(self):
        def chooseTarget(target):
            if target is None:
                base.mouseHandler.targeting = False
                showCard(self.toDiscard)
                return
            elif target.getPythonTag('zone') is not base.enemy.facedowns:
                return
            self.toSteal = target
            self.entry.show()

        def chooseDiscard(target):
            if target is None:
                base.mouseHandler.targeting = False
                return
            elif target.getPythonTag('zone') is not base.player.hand:
                return
            self.toDiscard = target
            hideCard(target)
            base.mouseHandler.startTargeting("Choose a target.", chooseTarget)

        base.mouseHandler.startTargeting("Choose a card to discard.",
                                         chooseDiscard)

    def redraw(self):
        super().redraw()

        # TODO: kludge
        if hasattr(self, 'thiefAbilityButton'):
            if base.game.phase == Phase.startOfTurn:
                self.thiefAbilityButton.show()
            else:
                self.thiefAbilityButton.hide()
Example #23
0
class panda3dIOClass( DirectObject.DirectObject ):
  # set gui key to None if you want to call toggleConsole from outside this class
  gui_key = CONSOLE_TOGGLE_KEY
  autocomplete_key = CONSOLE_AUTOCOMPLETE_KEY
  autohelp_key = CONSOLE_AUTOHELP_KEY
  
  scroll_up_repeat_key = CONSOLE_SCROLL_UP_KEY + "-repeat"
  scroll_down_repeat_key = CONSOLE_SCROLL_DOWN_KEY + "-repeat"
  
  # change size of text and number of characters on one line
  # scale of frame ( must be small (0.0x)
  scale = PANDA3D_CONSOLE_SCALE
  # to define a special font, if loading fails the default font is used (without warning)
  font = PANDA3D_CONSOLE_FONT
  fontWidth = PANDA3D_CONSOLE_FONT_WIDTH
  # frame position and size (vertical & horizontal)
  h_pos   = PANDA3D_CONSOLE_HORIZONTAL_POS
  h_size  = PANDA3D_CONSOLE_HORIZONTAL_SIZE
  # v_size + v_pos should not exceed 2.0, else parts of the interface will not be visible
  # space above the frame ( must be below 2.0, best between 0.0 and 1.0 )
  v_pos   = PANDA3D_CONSOLE_VERTICAL_POS
  # vertical size of the frame ( must be at max 2.0, best between 0.5 and 2.0 )
  v_size  = PANDA3D_CONSOLE_VERTICAL_SIZE
  linelength = int((h_size/scale - 5) / fontWidth)
  print "max number of characters on a length:", linelength
  numlines = int(v_size/scale - 5)
  defaultTextColor  = (0.0,0.0,0.0,1.0)
  autoCompleteColor = (0.9,0.9,0.9,1.0)
  def __init__( self, parent ):
    self.parent = parent
    
    # line wrapper
    self.linewrap = textwrap.TextWrapper()
    self.linewrap.width = self.linelength
    
    # calculate window size
    left   = (self.h_pos) / self.scale
    right  = (self.h_pos + self.h_size) / self.scale
    bottom = (self.v_pos) / self.scale
    top    = (self.v_pos + self.v_size) /self.scale
    
    # panda3d interface
    self.consoleFrame = DirectFrame ( relief = DGG.GROOVE
                                    , frameColor = (200, 200, 200, 0.5)
                                    , scale=self.scale
                                    , frameSize = (0, self.h_size / self.scale, 0, self.v_size / self.scale) )
    self.windowEvent( base.win )
    
    # try to load the defined font
    try:
      fixedWidthFont = loader.loadFont(self.font)
    except:
      print "pandaInteractiveConsole.py :: could not load the defined font %s" % str(self.font)
      fixedWidthFont = DGG.getDefaultFont()
    # if font is not valid use default font
    if not fixedWidthFont.isValid():
      if self.font is None:
        print "pandaInteractiveConsole.py :: could not load the defined font %s" % str(self.font)
      fixedWidthFont = DGG.getDefaultFont()
    
    # text entry line
    self.consoleEntry = DirectEntry ( self.consoleFrame
                                    , text        = ""
                                    , command     = self.onEnterPress
                                    , width       = self.h_size/self.scale - 2
                                    , pos         = (1, 0, 1.5)
                                    , initialText = ""
                                    , numLines    = 1
                                    , focus       = 1
                                    , entryFont   = fixedWidthFont)
    
    # output lines
    self.consoleOutputList = list()
    for i in xrange( self.numlines ):
      label = OnscreenText( parent = self.consoleFrame
                          , text = ""
                          , pos = (1, -i+3+self.numlines)
                          , align=TextNode.ALeft
                          , mayChange=1
                          , scale=1.0
                          , fg = self.defaultTextColor )
      label.setFont( fixedWidthFont )
      self.consoleOutputList.append( label )
    
    # list of the last commands of the user
    self.userCommandList = list()
    self.userCommandListLength = 100
    for i in xrange(self.userCommandListLength):
      self.userCommandList.append('')
    self.userCommandPos = 0
    
    # buffer for data
    self.textBuffer = list()
    self.textBufferLength = 1000
    for i in xrange(self.textBufferLength):
      self.textBuffer.append(['', DEFAULT_COLOR])
    self.textBufferPos = self.textBufferLength-self.numlines
    
    # toggle the window at least once to activate the events
    self.toggleConsole()
    self.toggleConsole()
    
    # call the help-command on start
    self.onEnterPress("help")
    
  
  
  # write a string to the panda3d console
  def write( self, printString, color=defaultTextColor ):
    # remove not printable characters (which can be input by console input)
    printString = re.sub( r'[^%s]' % re.escape(string.printable[:95]), "", printString)
    
    splitLines = self.linewrap.wrap(printString)
    for line in splitLines:
      self.textBuffer.append( [line, color] )
      self.textBuffer.pop(0)
    
    self.updateOutput()
  
  def updateOutput( self ):
    for lineNumber in xrange(self.numlines):
      lineText, color = self.textBuffer[lineNumber + self.textBufferPos]
      self.consoleOutputList[lineNumber].setText( lineText )
      self.consoleOutputList[lineNumber]['fg'] = color
  
  # toggle the gui console
  def toggleConsole( self ):
    self.consoleFrame.toggleVis()
    hidden = self.consoleFrame.isHidden()
    self.consoleEntry['focus'] != hidden
    if hidden:
      self.ignoreAll()
      self.accept( self.gui_key, self.toggleConsole )
      
      #playerController.enableInput()
      #unpause("v")
    else:
      self.ignoreAll()
      
      #playerController.disableInput()
      #pause("v")
      
      self.accept( CONSOLE_SCROLL_UP_KEY, self.scroll, [-5] )
      self.accept( self.scroll_up_repeat_key, self.scroll, [-5] )
      self.accept( CONSOLE_SCROLL_DOWN_KEY, self.scroll, [5] )
      self.accept( self.scroll_down_repeat_key, self.scroll, [5] )
      self.accept( 'window-event', self.windowEvent)
      
      self.accept( CONSOLE_PREVIOUS_COMMAND_KEY , self.scrollCmd, [ 1] )
      self.accept( CONSOLE_NEXT_COMMAND_KEY, self.scrollCmd, [-1] )
      
      self.accept( self.gui_key, self.toggleConsole )
      #self.accept( self.autocomplete_key, self.autocomplete )
      #self.accept( self.autohelp_key, self.autohelp )
      
      # accept v, c and x, where c & x copy's the whole console text
      #messenger.toggleVerbose()
      #for osx use ('meta')
      if sys.platform == 'darwin':
        self.accept( 'meta', self.unfocus )
        self.accept( 'meta-up', self.focus )
        self.accept( 'meta-c', self.copy )
        self.accept( 'meta-x', self.cut )
        self.accept( 'meta-v', self.paste )
      #for windows use ('control')
      if sys.platform == 'win32' or sys.platform == 'linux2':
        self.accept( 'control', self.unfocus )
        self.accept( 'control-up', self.focus )
        self.accept( 'control-c', self.copy )
        self.accept( 'control-x', self.cut )
        self.accept( 'control-v', self.paste )
  
  
#  def autohelp( self ):
#    currentText = self.consoleEntry.get()
#    currentPos = self.consoleEntry.guiItem.getCursorPosition()
#    self.parent.autohelp( currentText, currentPos )
  
  def focus( self ):
    self.consoleEntry['focus'] = 1
  
  def unfocus( self ):
    self.consoleEntry['focus'] = 0
  
  def copy( self ):
    copy = self.consoleEntry.get()
    clipboard.setText( copy )
  
  def paste( self ):
    oldCursorPos = self.consoleEntry.guiItem.getCursorPosition()
    clipboardText = clipboard.getText()
    
    # compose new text line
    oldText = self.consoleEntry.get()
    newText = oldText[0:oldCursorPos] + clipboardText + oldText[oldCursorPos:]
    
    clipboardTextLines = newText.split(os.linesep)
    
    for i in xrange( len(clipboardTextLines)-1 ):
      currentLine = clipboardTextLines[i]
      # we only want printable characters
      currentLine = re.sub( r'[^' + re.escape(string.printable[:95]) + ']', "", currentLine)
      
      # set new text and position
      self.consoleEntry.set( currentLine )
      self.onEnterPress( currentLine )
    currentLine = clipboardTextLines[-1]
    currentLine = re.sub( r'[^' + re.escape(string.printable[:95]) + ']', "", currentLine)
    self.consoleEntry.set( currentLine )
    self.consoleEntry.setCursorPosition( len(self.consoleEntry.get()) )
    self.focus()
  
  def cut( self ):
    clipboard.setText( self.consoleEntry.get() )
    self.consoleEntry.enterText('')
    self.focus()
  
  def scroll( self, step ):
    self.textBufferPos += step
    self.textBufferPos = min( self.textBufferLength-self.numlines, max( 0, self.textBufferPos ) )
    self.updateOutput()
  
  def scrollCmd( self, step ):
    oldCmdPos = self.userCommandPos
    self.userCommandPos += step
    self.userCommandPos = min( self.userCommandListLength-1, max( 0, self.userCommandPos ) )
    self.userCommandList[oldCmdPos] = self.consoleEntry.get()
    newCmd = self.userCommandList[self.userCommandPos]
    self.consoleEntry.set( newCmd )
    self.consoleEntry.setCursorPosition( len(newCmd) )
  
  def onEnterPress( self, textEntered ):
    # set to last message
    self.textBufferPos = self.textBufferLength-self.numlines
    # clear line
    self.consoleEntry.enterText('')
    self.focus()
    # add text entered to user command list & remove oldest entry
    self.userCommandList.insert( 1, textEntered )
    self.userCommandList[0] = ''
    self.userCommandList.pop( -1 )
    self.userCommandPos = 0
    
    # call the interpreter to handle the input
    interpreter = cliClass()
    result = interpreter.interpreter(textEntered)
    # write the entered text to the output
    self.write(textEntered, (0.0, 0.0, 1, 1))
    print textEntered
    # write each line seperately to the output
    for line in result.split('\n'):
        line = "        " + line
        self.write(line, (0, 0, 0, 1))
        print line
  
  def windowEvent( self, window ):
    """
    This is a special callback.
    It is called when the panda window is modified.
    """
    wp = window.getProperties()
    width = wp.getXSize() / float(wp.getYSize())
    height = wp.getYSize() / float(wp.getXSize())
    if width > height:
      height = 1.0
    else:
      width = 1.0
    # aligned to center
    consolePos = Vec3(-self.h_size/2, 0, -self.v_size/2)
    # aligned to left bottom
    #consolePos = Vec3(-width+self.h_pos, 0, -height+self.v_pos)
    # aligned to right top
    #consolePos = Vec3(width-self.h_size, 0, height-self.v_size)
    # set position
    self.consoleFrame.setPos( consolePos )
Example #24
0
class panda3dIOClass(DirectObject.DirectObject):
    # set gui key to None if you want to call toggleConsole from outside this class
    gui_key = PANDA3D_CONSOLE_TOGGLE_KEY
    autocomplete_key = PANDA3D_CONSOLE_AUTOCOMPLETE_KEY
    autohelp_key = PANDA3d_CONSOLE_AUTOHELP_KEY
    # change size of text and number of characters on one line
    # scale of frame ( must be small (0.0x)
    scale = PANDA3D_CONSOLE_SCALE
    # to define a special font, if loading fails the default font is used (without warning)
    font = PANDA3D_CONSOLE_FONT
    fontWidth = PANDA3D_CONSOLE_FONT_WIDTH
    # frame position and size (vertical & horizontal)
    h_pos = PANDA3D_CONSOLE_HORIZONTAL_POS
    h_size = PANDA3D_CONSOLE_HORIZONTAL_SIZE
    # v_size + v_pos should not exceed 2.0, else parts of the interface will not be visible
    # space above the frame ( must be below 2.0, best between 0.0 and 1.0 )
    v_pos = PANDA3D_CONSOLE_VERTICAL_POS
    # vertical size of the frame ( must be at max 2.0, best between 0.5 and 2.0 )
    v_size = PANDA3D_CONSOLE_VERTICAL_SIZE
    linelength = int((h_size / scale - 5) / fontWidth)
    print "max number of characters on a length:", linelength
    numlines = int(v_size / scale - 5)
    defaultTextColor = (0.0, 0.0, 0.0, 1.0)
    autoCompleteColor = (0.9, 0.9, 0.9, 1.0)

    def __init__(self, parent):
        self.parent = parent

        # line wrapper
        self.linewrap = textwrap.TextWrapper()
        self.linewrap.width = self.linelength

        # calculate window size
        left = (self.h_pos) / self.scale
        right = (self.h_pos + self.h_size) / self.scale
        bottom = (self.v_pos) / self.scale
        top = (self.v_pos + self.v_size) / self.scale

        # panda3d interface
        self.consoleFrame = DirectFrame(
            relief=DGG.GROOVE,
            frameColor=(200, 200, 200, 0.5),
            scale=self.scale,
            frameSize=(0, self.h_size / self.scale, 0, self.v_size / self.scale),
        )
        self.windowEvent(base.win)

        # try to load the defined font
        fixedWidthFont = loader.loadFont(self.font)
        # if font is not valid use default font
        if not fixedWidthFont.isValid():
            if self.font is None:
                print "pandaInteractiveConsole.py :: could not load the defined font %s" % str(self.font)
            fixedWidthFont = DGG.getDefaultFont()

        # text entry line
        self.consoleEntry = DirectEntry(
            self.consoleFrame,
            text="",
            command=self.onEnterPress,
            width=self.h_size / self.scale - 2,
            pos=(1, 0, 1.5),
            initialText="",
            numLines=1,
            focus=1,
            entryFont=fixedWidthFont,
        )

        # output lines
        self.consoleOutputList = list()
        for i in xrange(self.numlines):
            label = OnscreenText(
                parent=self.consoleFrame,
                text="",
                pos=(1, -i + 3 + self.numlines),
                align=TextNode.ALeft,
                mayChange=1,
                scale=1.0,
                fg=self.defaultTextColor,
            )
            label.setFont(fixedWidthFont)
            self.consoleOutputList.append(label)

        # list of the last commands of the user
        self.userCommandList = list()
        self.userCommandListLength = 100
        for i in xrange(self.userCommandListLength):
            self.userCommandList.append("")
        self.userCommandPos = 0

        # buffer for data
        self.textBuffer = list()
        self.textBufferLength = 1000
        for i in xrange(self.textBufferLength):
            self.textBuffer.append(["", DEFAULT_COLOR])
        self.textBufferPos = self.textBufferLength - self.numlines

        # toggle the window at least once to activate the events
        self.toggleConsole()
        self.toggleConsole()

        self.help()

    def help(self):
        # output some info text about this module
        infoTxt = """ ------ Panda3dConsole ------
- press F10 to toggle it on/off
- use the usual copy, cut & paste keys
- page_up    : scrolls up
- page_down  : scrolls down
- arrow_up   : previous command
- arrow_down : next command
- BUGS       : if you paste a to long text, the entry blocks
         FIX : use cut to remove the whole line"""
        # for line in infoTxt.split('\n'):
        #  self.write( line, color=DEFAULT_COLOR )
        return infoTxt

    # write a string to the panda3d console
    def write(self, printString, color=defaultTextColor):
        # remove not printable characters (which can be input by console input)
        printString = re.sub(r"[^%s]" % re.escape(string.printable[:95]), "", printString)

        splitLines = self.linewrap.wrap(printString)
        for line in splitLines:
            self.textBuffer.append([line, color])
            self.textBuffer.pop(0)

        self.updateOutput()

    def updateOutput(self):
        for lineNumber in xrange(self.numlines):
            lineText, color = self.textBuffer[lineNumber + self.textBufferPos]
            self.consoleOutputList[lineNumber].setText(lineText)
            self.consoleOutputList[lineNumber]["fg"] = color

    # toggle the gui console
    def toggleConsole(self):
        self.consoleFrame.toggleVis()
        hidden = self.consoleFrame.isHidden()
        self.consoleEntry["focus"] != hidden
        if hidden:
            self.ignoreAll()
            self.accept(self.gui_key, self.toggleConsole)
        else:
            self.ignoreAll()
            self.accept("page_up", self.scroll, [-5])
            self.accept("page_up-repeat", self.scroll, [-5])
            self.accept("page_down", self.scroll, [5])
            self.accept("page_down-repeat", self.scroll, [5])
            self.accept("window-event", self.windowEvent)

            self.accept("arrow_up", self.scrollCmd, [1])
            self.accept("arrow_down", self.scrollCmd, [-1])

            self.accept(self.gui_key, self.toggleConsole)
            self.accept(self.autocomplete_key, self.autocomplete)
            self.accept(self.autohelp_key, self.autohelp)

            # accept v, c and x, where c & x copy's the whole console text
            # messenger.toggleVerbose()
            # for osx use ('meta')
            if sys.platform == "darwin":
                self.accept("meta", self.unfocus)
                self.accept("meta-up", self.focus)
                self.accept("meta-c", self.copy)
                self.accept("meta-x", self.cut)
                self.accept("meta-v", self.paste)
            # for windows use ('control')
            if sys.platform == "win32" or sys.platform == "linux2":
                self.accept("control", self.unfocus)
                self.accept("control-up", self.focus)
                self.accept("control-c", self.copy)
                self.accept("control-x", self.cut)
                self.accept("control-v", self.paste)

    def autocomplete(self):
        currentText = self.consoleEntry.get()
        currentPos = self.consoleEntry.guiItem.getCursorPosition()
        newText = self.parent.autocomplete(currentText, currentPos)
        if newText != currentText:
            self.consoleEntry.set(newText)
            self.consoleEntry.setCursorPosition(len(newText))

    def autohelp(self):
        currentText = self.consoleEntry.get()
        currentPos = self.consoleEntry.guiItem.getCursorPosition()
        self.parent.autohelp(currentText, currentPos)

    def focus(self):
        self.consoleEntry["focus"] = 1

    def unfocus(self):
        self.consoleEntry["focus"] = 0

    def copy(self):
        copy = self.consoleEntry.get()
        clipboard.setText(copy)

    def paste(self):
        oldCursorPos = self.consoleEntry.guiItem.getCursorPosition()
        clipboardText = clipboard.getText()

        # compose new text line
        oldText = self.consoleEntry.get()
        newText = oldText[0:oldCursorPos] + clipboardText + oldText[oldCursorPos:]

        clipboardTextLines = newText.split(os.linesep)

        for i in xrange(len(clipboardTextLines) - 1):
            currentLine = clipboardTextLines[i]
            # we only want printable characters
            currentLine = re.sub(r"[^" + re.escape(string.printable[:95]) + "]", "", currentLine)

            # set new text and position
            self.consoleEntry.set(currentLine)
            self.onEnterPress(currentLine)
        currentLine = clipboardTextLines[-1]
        currentLine = re.sub(r"[^" + re.escape(string.printable[:95]) + "]", "", currentLine)
        self.consoleEntry.set(currentLine)
        self.consoleEntry.setCursorPosition(len(self.consoleEntry.get()))
        self.focus()

    def cut(self):
        clipboard.setText(self.consoleEntry.get())
        self.consoleEntry.enterText("")
        self.focus()

    def scroll(self, step):
        self.textBufferPos += step
        self.textBufferPos = min(self.textBufferLength - self.numlines, max(0, self.textBufferPos))
        self.updateOutput()

    def scrollCmd(self, step):
        oldCmdPos = self.userCommandPos
        self.userCommandPos += step
        self.userCommandPos = min(self.userCommandListLength - 1, max(0, self.userCommandPos))
        self.userCommandList[oldCmdPos] = self.consoleEntry.get()
        newCmd = self.userCommandList[self.userCommandPos]
        self.consoleEntry.set(newCmd)
        self.consoleEntry.setCursorPosition(len(newCmd))

    def onEnterPress(self, textEntered):
        # set to last message
        self.textBufferPos = self.textBufferLength - self.numlines
        # clear line
        self.consoleEntry.enterText("")
        self.focus()
        # add text entered to user command list & remove oldest entry
        self.userCommandList.insert(1, textEntered)
        self.userCommandList[0] = ""
        self.userCommandList.pop(-1)
        self.userCommandPos = 0
        # call our parent
        self.parent.push(textEntered)

    def windowEvent(self, window):
        """
    This is a special callback.
    It is called when the panda window is modified.
    """
        wp = window.getProperties()
        width = wp.getXSize() / float(wp.getYSize())
        height = wp.getYSize() / float(wp.getXSize())
        if width > height:
            height = 1.0
        else:
            width = 1.0
        # aligned to center
        consolePos = Vec3(-self.h_size / 2, 0, -self.v_size / 2)
        # aligned to left bottom
        # consolePos = Vec3(-width+self.h_pos, 0, -height+self.v_pos)
        # aligned to right top
        # consolePos = Vec3(width-self.h_size, 0, height-self.v_size)
        # set position
        self.consoleFrame.setPos(consolePos)