Ejemplo n.º 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
Ejemplo n.º 2
0
class ClientPageGui(ThanksPageGui):
    def __init__(self, mdt, menu):
        self.ent = None
        ThanksPageGui.__init__(self, mdt, menu)

    def build_page(self):
        menu_gui = self.menu.gui
        menu_args = self.menu.gui.menu_args
        txt = OnscreenText(text=_('Client'), pos=(0, .4), **menu_gui.text_args)
        widgets = [txt]
        self.ent = DirectEntry(scale=.12,
                               pos=(-.68, 1, .2),
                               entryFont=menu_args.font,
                               width=12,
                               frameColor=menu_args.btn_color,
                               initialText=_('insert the server address'))
        self.ent.onscreenText['fg'] = menu_args.text_fg
        btn = DirectButton(text=_('Connect'),
                           pos=(0, 1, -.2),
                           command=self.connect,
                           **menu_gui.btn_args)
        widgets += [self.ent, btn]
        map(self.add_widget, widgets)
        ThanksPageGui.build_page(self)

    def connect(self):
        menu_gui = self.menu.gui
        try:
            eng.log(self.ent.get())
            Client().start(self.mdt.event.process_msg, self.ent.get())
            menu_args = self.menu.gui.menu_args
            self.add_widget(
                OnscreenText(text=_('Waiting for the server'),
                             scale=.12,
                             pos=(0, -.5),
                             font=menu_gui.font,
                             fg=menu_args.text_fg))
        except ClientError:
            txt = OnscreenText(_('Error'),
                               pos=(0, -.05),
                               fg=(1, 0, 0, 1),
                               scale=.16,
                               font=menu_gui.menu_args.font)
            eng.do_later(5, txt.destroy)
Ejemplo n.º 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()
Ejemplo n.º 4
0
class NamePicker:
    def __init__(self):
        self.instructions = OnscreenText(text='Type your name',
                                         scale=0.1,
                                         fg=(1, 1, 1, 1),
                                         pos=(0, 0.8, 0.8),
                                         shadow=(0, 0, 0, 1))
        self.nameEntry = DirectEntry(focus=1,
                                     initialText='Toon',
                                     width=10,
                                     scale=0.1,
                                     pos=(-0.5, 0.3, 0.3),
                                     command=self.confirmNameAndContinue)
        self.confirmBtn = DirectButton(text='Confirm',
                                       scale=0.1,
                                       pos=(0, 0.1, 0.1),
                                       command=self.confirmNameAndContinue,
                                       extraArgs=[self.nameEntry.get()])

    def confirmNameAndContinue(self, textEntered):
        try:
            self.badName_lbl.remove()
            del self.badName_lbl
        except:
            pass

        if self.nameEntry.get().isspace() or len(self.nameEntry.get()) <= 0:
            self.badName_lbl = OnscreenText(text=CIGlobals.InvalidName,
                                            scale=0.09,
                                            fg=(1, 0, 0, 1),
                                            pos=(0, -0.1, -0.1),
                                            shadow=(0, 0, 0, 1))
            return
        self.instructions.remove()
        self.nameEntry.remove()
        self.confirmBtn.remove()
        try:
            self.badName_lbl.remove()
        except:
            pass

        messenger.send('nameConfirmed', [self.nameEntry.get()])
Ejemplo n.º 5
0
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))
Ejemplo n.º 6
0
class DeveloperConsole(InteractiveInterpreter, DirectObject):
    """The name says it all."""
    def __init__(self, manager, 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)
        self.manager = manager
        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

    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__
            locals['manager'] = self.manager
            for plugin in self.manager.named.keys():
                locals[plugin] = self.manager.named[plugin]
            locals['panda3d'] = panda3d

            # 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):
        if self.hidden:
            self.show()
        else:
            self.hide()

    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()
Ejemplo n.º 7
0
class DeveloperConsole(InteractiveInterpreter, DirectObject):
    def __init__(self):
        sys.stdout = PseudoFile(self.write_out)
        sys.stderr = PseudoFile(self.write_err)
        tp_err = TextProperties()
        tp_err.setTextColor(1, 0.5, 0.5, 1)
        TextPropertiesManager.getGlobalPtr().setProperties('err', tp_err)
        font = loader.loadFont('cmss12')
        self.frame = DirectFrame(parent=base.a2dTopCenter,
                                 text_align=TextNode.ALeft,
                                 text_pos=(base.a2dLeft + TEXT_MARGIN[0],
                                           TEXT_MARGIN[1]),
                                 text_scale=0.05,
                                 text_fg=(1, 1, 1, 1),
                                 frameSize=(-2.0, 2.0, -1, 0.0),
                                 frameColor=(0, 0, 0, 0.5),
                                 text='',
                                 text_font=font,
                                 sortOrder=4)
        self.entry = DirectEntry(parent=base.a2dTopLeft,
                                 command=self.command,
                                 scale=0.05,
                                 width=1000.0,
                                 pos=(-0.02, 0, -0.98),
                                 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 = [''] * 19
        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

    def prev_command(self):
        if self.hidden:
            return
        if len(self.commands) == 0:
            return
        if self.cscroll is 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 next_command(self):
        if self.hidden:
            return
        if len(self.commands) == 0:
            return
        if self.cscroll is 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 write_out(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[-19:])

    def write_err(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[-19:])

    def command(self, text):
        if self.hidden:
            return

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

        if not self.initialized:
            InteractiveInterpreter.__init__(self)
            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:
            self.write_err(traceback.format_exc())

    def toggle(self):
        if self.hidden:
            self.show()
        else:
            self.hide()

    def show(self):
        self.accept('arrow_up', self.prev_command)
        self.accept('arrow_up-repeat', self.prev_command)
        self.accept('arrow_down', self.next_command)
        self.accept('arrow_down-repeat', self.next_command)
        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.entry.set(self.entry.get()[:-1])
        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()
Ejemplo n.º 8
0
class Pregame():
    def __init__(self, showbase):
        self.showbase = showbase

        self.ready = False

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

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

        self.buttons = []
        controlButtons = Vec3(-0.60, 0, -0.79)
        # Toggle ready
        p = controlButtons + Vec3(-0.25, 0, 0)
        self.toggleReadyButton = DirectButton(
            text='Ready/Unready',
            pos=p,
            scale=0.048,
            relief=DGG.GROOVE,
            command=self.toggleReady,
        )
        self.buttons.append(self.toggleReadyButton)
        # Disconnect
        p = controlButtons + Vec3(0.0, 0.0, 0.0)
        self.disconnectButton = DirectButton(
            text='Disconnect',
            pos=p,
            scale=0.048,
            relief=DGG.GROOVE,
            command=self.disconnect,
        )
        self.buttons.append(self.disconnectButton)

        # Send message
        p = controlButtons + Vec3(0.25, 0.0, 0.0)
        self.sendMessageButton = DirectButton(
            text='Send Message',
            pos=p,
            scale=0.048,
            relief=DGG.GROOVE,
            command=self.sendMessage,
            extraArgs=[''],
        )
        self.buttons.append(self.sendMessageButton)
        # Message input
        self.message = DirectEntry(
            command=self.sendMessage,
            focusInCommand=self.clearText,
            frameSize=(-3, 3, -.5, 1),
            initialText='',
            parent=self.buttons[2],
            pos=(0, -0.6, -1.5),
            text_align=TextNode.ACenter,
        )

        self.showbase.gameData = GameData()

        self.showbase.users = []

        self.hide()

    def clearText(self):
        self.message.set('')

    def reset(self):
        self.messages = []
        self.showbase.users = []

    def updateLobby(self, task):
        temp = self.showbase.client.getData()
        for package in temp:
            if len(package) == 2:
                print 'Received: ', str(package)
                if package[0] == 'chat':
                    if len(package[1]) == 2:
                        self.messages.append(package[1])
                        print self.messages
                elif package[0] == 'client':
                    self.showbase.users.append(User(package[1]))
                    for user in self.showbase.users:
                        print user.name, user.ready
                    print 'all users'
                elif package[0] == 'ready':
                    for user in self.showbase.users:
                        if user.name == package[1][0]:
                            user.ready = package[1][1]
                    for user in self.showbase.users:
                        print user.name, user.ready
                    print 'all users'
                elif package[0] == 'disconnect':
                    for user in self.showbase.users:
                        if user.name == package[1]:
                            self.showbase.users.remove(user)
                    for user in self.showbase.users:
                        print user.name, user.ready
                    print 'all users'
                elif package[0] == 'gamedata':
                    self.showbase.gameData.unpackageData(package[1])
                elif package[0] == 'state':
                    print 'state: ', package[1]
                    if package[1] == 'preround':
                        self.showbase.startRound()
                        return task.done
        return task.again

    def toggleReady(self):
        self.ready = not self.ready
        self.showbase.client.sendData(('ready', self.ready))

    def disconnect(self):
        self.showbase.client.sendData(('disconnect', 'disconnect'))
        self.showbase.authCon = self.showbase.client
        self.showbase.returnToMenu()

    def sendMessage(self, message):
        if message == '':
            message = self.message.get()
        if message != '':
            self.showbase.client.sendData(('chat', message))
            self.message.set('')

    def hide(self):
        self.background.hide()
        self.message.hide()
        for b in self.buttons:
            b.hide()

        self.showbase.taskMgr.remove('Update Lobby')

    def show(self):
        self.background.show()
        self.message.show()
        for b in self.buttons:
            b.show()

        # Add the game loop procedure to the task manager.
        self.showbase.taskMgr.add(self.updateLobby, 'Update Lobby')
Ejemplo n.º 9
0
class Pregame():
	def __init__(self, showbase):
		self.showbase = showbase
		
		self.ready = False

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

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

		self.buttons = []
		controlButtons = Vec3(-0.60, 0, -0.79)
		# Toggle ready
		p = controlButtons + Vec3(-0.25, 0, 0)
		self.toggleReadyButton = DirectButton(
			text = 'Ready/Unready',
			pos = p,
			scale = 0.048,
			relief = DGG.GROOVE,
			command = self.toggleReady,
		)
		self.buttons.append(self.toggleReadyButton)
		# Disconnect
		p = controlButtons + Vec3(0.0, 0.0, 0.0)
		self.disconnectButton = DirectButton(
			text = 'Disconnect',
			pos = p,
			scale = 0.048,
			relief = DGG.GROOVE,
			command = self.disconnect,
		)
		self.buttons.append(self.disconnectButton)

		# Send message
		p = controlButtons + Vec3(0.25, 0.0, 0.0)
		self.sendMessageButton = DirectButton(
			text = 'Send Message',
			pos = p,
			scale = 0.048,
			relief = DGG.GROOVE,
			command = self.sendMessage,
			extraArgs = [''],
		)
		self.buttons.append(self.sendMessageButton)
		# Message input
		self.message = DirectEntry(
			command = self.sendMessage,
			focusInCommand = self.clearText,
			frameSize   = (-3, 3, -.5, 1),
			initialText = '',
			parent      = self.buttons[2],
			pos         = (0, -0.6, -1.5),
			text_align  = TextNode.ACenter,
		)

		self.showbase.gameData = GameData()

		self.showbase.users = []

		self.hide()

	def clearText(self):
		self.message.set('')

	def reset(self):
		self.messages = []
		self.showbase.users = []

	def updateLobby(self, task):
		temp = self.showbase.client.getData()
		for package in temp:
			if len(package) == 2:
				print 'Received: ', str(package)
				if package[0] == 'chat':
					if len(package[1]) == 2:
						self.messages.append(package[1])
						print self.messages
				elif package[0] == 'client':
					self.showbase.users.append(User(package[1]))
					for user in self.showbase.users:
						print user.name, user.ready
					print 'all users'
				elif package[0] == 'ready':
					for user in self.showbase.users:
						if user.name == package[1][0]:
							user.ready = package[1][1]
					for user in self.showbase.users:
						print user.name, user.ready
					print 'all users'
				elif package[0] == 'disconnect':
					for user in self.showbase.users:
						if user.name == package[1]:
							self.showbase.users.remove(user)
					for user in self.showbase.users:
						print user.name, user.ready
					print 'all users'
				elif package[0] == 'gamedata':
					self.showbase.gameData.unpackageData(package[1])
				elif package[0] == 'state':
					print 'state: ', package[1]
					if package[1] == 'preround':
						self.showbase.startRound()
						return task.done
		return task.again
	
	def toggleReady(self):
		self.ready = not self.ready
		self.showbase.client.sendData(('ready', self.ready))
		
	def disconnect(self):
		self.showbase.client.sendData(('disconnect', 'disconnect'))
		self.showbase.authCon = self.showbase.client
		self.showbase.returnToMenu()
	
	def sendMessage(self, message):
		if message == '':
			message = self.message.get()
		if message != '':
			self.showbase.client.sendData(('chat', message))
			self.message.set('')

	def hide(self):
		self.background.hide()
		self.message.hide()
		for b in self.buttons:
			b.hide()

		self.showbase.taskMgr.remove('Update Lobby')
	
	def show(self):
		self.background.show()
		self.message.show()
		for b in self.buttons:
			b.show()

		# Add the game loop procedure to the task manager.
		self.showbase.taskMgr.add(self.updateLobby, 'Update Lobby')
Ejemplo n.º 10
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()
Ejemplo n.º 11
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
Ejemplo n.º 12
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
Ejemplo n.º 13
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)
Ejemplo n.º 14
0
class Login():
	def __init__(self, showbase):
		self.showbase = showbase
		
		self.background = DirectFrame(
			frameSize = (-1, 1, -1, 1),
			frameTexture  = 'media/gui/login/bg.png',
			parent = self.showbase.render2d,
		)

		### CONFIG LOADER ###
		config = ConfigParser.RawConfigParser()
		config.read('master.cfg')
		self.LOGIN_IP = config.get('MASTER SERVER CONNECTION', 'masterIp')
		self.LOGIN_PORT = config.getint('MASTER SERVER CONNECTION', 'masterPort')

		config = ConfigParser.RawConfigParser()
		config.read('client.cfg')
		self.storeUsername = config.getint('USERDATA', 'storeUsername')
		if self.storeUsername == 1:
			self.username = config.get('USERDATA', 'username')
		else:
			self.username = ''
		self.storePassword = config.getint('USERDATA', 'storePassword')
		if self.storePassword == 1:
			self.password = config.get('USERDATA', 'password')
		else:
			self.password = ''
		### CONFIG END ###

		self.loginScreen("Press 'Enter' to login")
		# draws the login screen

		self.usernameBox['focus'] = 1
		# sets the cursor to the username field by default

		self.showbase.accept('tab', self.cycleLoginBox)
		self.showbase.accept('shift-tab', self.cycleLoginBox)
		# enables the user to cycle through the text fields with the tab key
		# this is a standard feature on most login forms

		self.showbase.accept('enter', self.attemptLogin)         
		# submits the login form, or you can just click the Login button
		
		# checking variable to stop multiple presses of the button spawn multiple tasks
		self.requestAttempt = False
		
		self.showbase.authCon = Client(self.showbase, self.LOGIN_IP, self.LOGIN_PORT, compress = True)
		if not self.showbase.authCon.getConnected():
			self.updateStatus("Could not connect to the Login server\nOFFLINE MODE")
			self.showbase.online = False

	def updateConfig(self):
		config = ConfigParser.RawConfigParser()
		config.read('client.cfg')
		config.set('USERDATA', 'storeUsername', self.usernameStoreBox["indicatorValue"])
		config.set('USERDATA', 'storePassword', self.passwordStoreBox["indicatorValue"])
		if self.usernameStoreBox["indicatorValue"] == 1:
			config.set('USERDATA', 'username', self.usernameBox.get())
		if self.passwordStoreBox["indicatorValue"] == 1:
			config.set('USERDATA', 'password', self.passwordBox.get())
		with open('client.cfg', 'wb') as configfile:
			config.write(configfile)
	
	def loginScreen(self, statusText):
		# creates a basic login screen that asks for a username/password
		
		boxloc = Vec3(0.0, 0.0, 0.0)
		# all items in the login form will have a position relative to this
		# this makes it easier to shift the entire form around once we have
		# some graphics to display with it without having to change the
		# positioning of every form element

		# p is the position of the form element relative to the boxloc
		# coordinates set above it is changed for every form element
		p = boxloc + Vec3(-0.22, 0.09, 0.0)                                 
		self.usernameText = OnscreenText(text = "Username:"******"Username: "******"", pos = p, scale=.04, initialText = self.username, numLines = 1)
		# Username textbox where you type in your username
		
		p = boxloc + Vec3(0.4, 0.0, 0.09)
		self.usernameStoreBox = DirectCheckButton(text = "Save Username?", pos = p, scale = .04, indicatorValue = self.storeUsername)
		# Toggle to save/not save your username
		
		p = boxloc + Vec3(-0.22, 0.0, 0.0)       
		self.passwordText = OnscreenText(text = "Password:"******"Password: "******"", pos = p, scale = .04, initialText = self.password, numLines = 1, obscured = 1)
		# Password textbox where you type in your password
		# Note - obscured = 1 denotes that all text entered will be replaced
		# with a * like a standard password box
		
		p = boxloc + Vec3(0.4, 0.0, 0.0)
		self.passwordStoreBox = DirectCheckButton(text = "Save Password?", pos = p, scale = .04, indicatorValue = self.storePassword)
		# Toggle to save/not save your username
		
		p = boxloc + Vec3(0, 0, -0.090)
		self.loginButton = DirectButton(text = "Login", pos = p, scale = 0.048, relief = DGG.GROOVE, command = self.attemptLogin)
		# The 'Quit' button that will trigger the Quit function
		# when clicked
		
		p = boxloc + Vec3(0.95, 0, -0.9)
		self.createAccButton = DirectButton(text = "Create Account", scale = 0.050, pos = p, relief = DGG.GROOVE, command = self.attemptCreateAccount)
		# Made a quick button for adding accounts. Its fugly

		p = boxloc + Vec3(1.20, 0, -0.9)
		self.quitButton = DirectButton(text = "Quit", pos = p, scale = 0.048, relief = DGG.GROOVE, command = self.showbase.quit)
		# The 'Quit' button that will trigger the Quit function
		# when clicked
		
		p = boxloc + Vec3(0, -0.4, 0)
		self.statusText = OnscreenText(text = statusText, pos = p, scale = 0.043, fg = (1, 0.5, 0, 1), align = TextNode.ACenter)
		# A simple text object that you can display an error/status messages
		# to the user

	def updateStatus(self, statusText):
		self.statusText.setText(statusText)
		# all this does is change the status text.

	def checkBoxes(self):
		# checks to make sure the user inputed a username and password:
		#       if they didn't it will spit out an error message
		self.updateStatus("")
		if self.usernameBox.get() == "":
			if self.passwordBox.get() == "":
				self.updateStatus("You must enter a username and password before logging in.")
			else:
				self.updateStatus("You must specify a username")
				self.passwordBox['focus'] = 0
				self.usernameBox['focus'] = 1
			return False
		elif self.passwordBox.get() == "":
			self.updateStatus("You must enter a password")
			self.usernameBox['focus'] = 0
			self.passwordBox['focus'] = 1
			return False
		# if both boxes are filled then return True
		return True

	def attemptLogin(self):
		if self.checkBoxes():
			self.showbase.username = self.usernameBox.get()
			self.updateStatus("Attempting to login...")
			self.request(self.usernameBox.get(), self.passwordBox.get(), 'client')
			
	def attemptCreateAccount(self):
		if self.checkBoxes():
			self.updateStatus("Attempting to create account and login...")
			self.request(self.usernameBox.get(), self.passwordBox.get(), 'create')
	
	def request(self, username, password, request):
		if not self.requestAttempt:
			# attempt to connect again if it failed on startup
			if self.showbase.authCon.getConnected():
				self.requestAttempt = True
				self.loginButton["state"] = DGG.DISABLED
				self.createAccButton["state"] = DGG.DISABLED
				self.showbase.authCon.sendData((request, (username, password)))
				self.showbase.username = username
				self.showbase.online = True
				self.showbase.taskMgr.doMethodLater(0.2, self.responseReader, 'Update Login')
			else:
				# client not connected to login/auth server so display message
				self.updateStatus("Offline Mode")
				self.showbase.username = username
				self.showbase.online = False
				self.updateConfig()
				self.showbase.startMainmenu()
	
	def responseReader(self, task):
		if task.time > 2.5:
			self.loginButton["state"] = DGG.NORMAL
			self.createAccButton["state"] = DGG.NORMAL
			self.updateStatus("Timeout from Login server")
			return task.done
		else:
			temp = self.showbase.authCon.getData()
			for package in temp:
				if len(package) == 2:
					print "Received: " + str(package)
					print "Connected to login server"
					if package[0] == 'loginFailed':
						print "Login failed: ", package[1]
						if package[1] == 'username':
							self.updateStatus("Username Doesnt Exist")
							self.passwordBox.set("")
							self.usernameBox.set("")
							self.passwordBox['focus'] = 0
							self.usernameBox['focus'] = 1
						elif package[1] == 'password':
							self.updateStatus("Password Incorrect")
							self.passwordBox.set("")
							self.usernameBox['focus'] = 0
							self.passwordBox['focus'] = 1
						elif package[1] == 'logged':
							self.updateStatus("Username already logged in")
						self.requestAttempt = False
						self.loginButton["state"] = DGG.NORMAL
						self.createAccButton["state"] = DGG.NORMAL
						return task.done
					elif package[0] == 'loginValid':
						print "Login valid: ", package[1]
						self.updateStatus(package[1])
						self.updateConfig()
						self.showbase.startMainmenu()
						return task.done
					elif package[0] == 'createFailed':
						print "Create failed: ", package[1]
						if package[1] == 'exists':
							self.updateStatus("Username Already Exists")
							self.passwordBox.set("")
							self.usernameBox.set("")
							self.passwordBox['focus'] = 0
							self.usernameBox['focus'] = 1
						self.requestAttempt = False
						self.loginButton["state"] = DGG.NORMAL
						self.createAccButton["state"] = DGG.NORMAL
						return task.done
					elif package[0] == 'createSuccess':
						print "Create success", package[1]
						self.updateStatus("Account Created Successfully")
						self.requestAttempt = False
						self.attemptLogin()
						return task.done
			return task.cont
		
	def cycleLoginBox(self):
		# function is triggered by the tab key so you can cycle between
		# the two input fields like on most login screens
		if self.passwordBox['focus'] == 1:
			self.passwordBox['focus'] = 0
			self.usernameBox['focus'] = 1
		elif self.usernameBox['focus'] == 1:
			self.usernameBox['focus'] = 0
			self.passwordBox['focus'] = 1
		# IMPORTANT: When you change the focus to one of the text boxes,
		# you have to unset the focus on the other textbox.  If you do not
		# do this Panda seems to get confused.
	
	def hide(self):
		self.background.destroy()
		self.usernameText.destroy()
		self.usernameBox.destroy()
		self.usernameStoreBox.destroy()
		self.passwordText.destroy()
		self.passwordBox.destroy()
		self.passwordStoreBox.destroy()
		self.loginButton.destroy()
		self.quitButton.destroy()
		self.createAccButton.destroy()
		self.statusText.destroy()
		
		self.showbase.ignore('tab')
		self.showbase.ignore('shift-tab')
		self.showbase.ignore('enter') 
Ejemplo n.º 15
0
class FrameAutenticacao(object):
    '''
    FrameAutenticacao
    '''

    def __init__(self, parent = None, **kw):
        self.__qtd_conexao = 0        
        
        self.__frmAuth = DirectFrame( frameColor = (0,0,0,.3),
                                      frameSize  = (-.5,.5,0,0.45), 
                                      pos        = (0,0,-.1),                                      
                                      enableEdit = 1 )        
        
        self.__lblLogin = DirectLabel( text       = "Login: "******"Senha: ",
                                       scale      = 0.05,
                                       pos        = (-0.3, 0, 0.2),
                                       frameColor = (0,0,0,0),
                                       text_fg    = (1,1,1,1) )        
        
        self.__etySenha = DirectEntry( scale          = 0.05,
                                       width          = 12,                                       
                                       pos            = (-.2, 0, 0.2),
                                       cursorKeys     = 1, 
                                       obscured       = 1,                                    
                                       focusInCommand = self.__command_clear_senha)
        
        
        self.__btnEntrar = DirectButton( frameColor    = (0,0,0,1),
                                         text          = "Entrar",
                                         scale         = 0.06,                                                                                
                                         pos           = (0.3, 0, 0.1),
                                         text_fg       = (1,1,1,1),                                                                                   
                                         rolloverSound = None,
                                         clickSound    = None,
                                         command       = self.__command_entrar)
        
        self.__lblLogin.reparentTo(self.__frmAuth)
        self.__etyLogin.reparentTo(self.__frmAuth)
        self.__lblSenha.reparentTo(self.__frmAuth)
        self.__etySenha.reparentTo(self.__frmAuth)        
        self.__btnEntrar.reparentTo(self.__frmAuth)
        
        self.__etyLogin.set("viner")
        self.__etySenha.set("viner")
    
    def __command_clear_senha(self):
        self.__etySenha.set("")
    
    def __command_entrar(self, txt = None):                
        login = self.__etyLogin.get()
        senha = self.__etySenha.get()
                
        valido = True
        
        if login == "":
            addMensagem("O campo Login e obrigatorio !", COR_BRANCO)
            valido = False
            
        if senha == "":
            addMensagem("O campo Senha e obrigatorio !", COR_BRANCO)
            valido = False
        
        if valido:
            self.__btnEntrar["state"] = DGG.DISABLED
                        
            taskMgr.add( self.__task_conectar_servidor,
                         'ConectarServidor',
                          extraArgs=[login,senha],
                          appendTask=True)                            
            
            #inicia_nova_thread(1, 0, "Conectar Servidor", self.__conectar_servidor, login, senha)
                        
    def __task_conectar_servidor(self, login, senha, task):            
                
        if self.__qtd_conexao < TENTATIVAS:                                        
            
            if vinerOnline.flg_conectado == vinerOnline.ERROLOGIN:
                vinerOnline.flg_conectado = vinerOnline.DESCONECT
                
                self.__btnEntrar["state"] = DGG.NORMAL
                self.__qtd_conexao        = 0
                                
                addMensagem('Login ou senha invalido', COR_VERMELHO)
                
                self.__etyLogin.setFocus()
                                
            elif vinerOnline.flg_conectado == vinerOnline.CONECTADO:
                #addMensagem("Conectado 12 !!!")
                #self.destroy()
                pass
                
            else:
                vinerOnline.conectar_servidor(login, senha)
                self.__qtd_conexao += 1
                
                taskMgr.doMethodLater( INTERVALO_TENTATIVAS,
                                   self.__task_conectar_servidor, 
                                   'ConectarServidorLater',
                                   extraArgs = [login,senha],
                                   appendTask = True)
                
                msg = "Tentativa %s/5 -  Conectando..." % (self.__qtd_conexao)
                addMensagem(msg, COR_BRANCO)                                            
                
        else:
            vinerOnline.flg_conectado = vinerOnline.DESCONECT
            self.__btnEntrar["state"] = DGG.NORMAL
            self.__qtd_conexao        = 0            
            addMensagem("Servidor nao encontrado", COR_VERMELHO)                        
            
        
        return task.done
        
    def destroy(self):        
        self.__frmAuth.destroy()
        
        del self.__lblLogin
        del self.__etyLogin
        del self.__lblSenha
        del self.__etySenha        
        del self.__btnEntrar
        del self.__frmAuth
            
Ejemplo n.º 16
0
class EntyButtonFrame(object):
    def __init__(self,
                 parent=None,
                 scale=.05,
                 limitText=100,
                 frameSize=(0, 1.3, 0.11, .2),
                 pos=(0, 0, .1)):

        self.__show = True

        self.frmMsg = DirectFrame(parent=parent,
                                  frameColor=(0, 0, 0, .5),
                                  frameSize=frameSize,
                                  pos=pos,
                                  enableEdit=1)

        self.etyMsg = DirectEntry(frameColor=(1, 1, 1, .5),
                                  scale=scale,
                                  width=22,
                                  numLines=1,
                                  pos=(.02, 0, .14),
                                  cursorKeys=1,
                                  focus=1,
                                  command=self.__command_enviar_msg,
                                  focusInCommand=self.__command_clear_msg)

        self.btnMsgr = DirectButton(frameColor=(0, 0, 0, 1),
                                    text="Enviar",
                                    scale=scale,
                                    pos=(1.21, 0, .14),
                                    text_fg=(1, 1, 1, 1),
                                    rolloverSound=None,
                                    clickSound=None,
                                    command=self.__command_enviar_msg)

        self.etyMsg.reparentTo(self.frmMsg)
        self.btnMsgr.reparentTo(self.frmMsg)

        self.hide()

    def hide(self):
        self.frmMsg.hide()
        self.__show = False

    def show(self):
        self.frmMsg.show()
        self.__show = True

        self.etyMsg.setFocus()

    def isShowing(self):
        return self.__show

    def __command_clear_msg(self):
        self.etyMsg.set("")

    def __command_enviar_msg(self, txt=None):

        msg = self.etyMsg.get()

        if msg != "":
            vinerOnline.envia_pacote_server(0, ACAO_SERVER_falar, [msg])
            self.__command_clear_msg()
            self.etyMsg.setFocus()
        return False
Ejemplo n.º 17
0
class NamePicker():
    """
        A UI element that lets the players pick their name.
        Also has a confirmation element to the right of the entry box.
    """
    def __init__(self, classSelectionMenu):
        self._classSelectionMenu = classSelectionMenu
        self._nameEntry = None
        self._confirmButton = None
        self._rootFrame = None
        self._font = loader.loadFont(PIERCEROMAN_FONT)
        self._draw()

    def _draw(self):
        winWidth = base.getAspectRatio() * 2
        winHeight = 2
        # Draw container:
        frameHeight = winHeight * NPKR_HEIGHT_PERCENTAGE
        frameWidth = winWidth * NPKR_WIDTH_PERCENTAGE
        cFCenterY = -winHeight / 2 + frameHeight / 2
        self._rootFrame = DirectFrame(
            pos=(0, 0, cFCenterY),
            frameSize=(-frameWidth / 2, frameWidth / 2, -frameHeight / 2,
                       frameHeight / 2),
            frameTexture=IMG_GRADIENT_1)
        self._rootFrame.setTransparency(TransparencyAttrib.MAlpha)
        # Draw Name Entry:
        entryWidth = self._rootFrame.getWidth() * NPKR_ENTRY_WIDTH_PERCENTAGE
        entryHeight = self._rootFrame.getHeight()
        entryCX = -(self._rootFrame.getWidth() - entryWidth) / 2
        self._nameEntry = DirectEntry(
            parent=self._rootFrame,
            pos=(entryCX, 0, 0),
            frameSize=(-entryWidth / 2, entryWidth / 2, -entryHeight / 2,
                       entryHeight / 2),
            frameColor=(0.25, 0.25, 0.25, 1),
            text_align=TextNode.ACenter,
            text_font=self._font,
            text_scale=NPKR_ENTRY_FONT_SIZE,
            text_pos=NPKR_ENTRY_FONT_OFFSET,
            initialText=NPKR_ENTRY_INITIAL_TEXT,
            numLines=1,
            focusOutCommand=self._syncName,
            focusInCommand=self._checkPlaceholderText,
            command=self._syncName,
            frameTexture=UI_WINDOW)
        # Draw Confirm Button:
        confirmWidth = self._rootFrame.getWidth()\
                            * (1-NPKR_ENTRY_WIDTH_PERCENTAGE)
        confirmHeight = self._rootFrame.getHeight()
        confirmCX = (self._rootFrame.getWidth() - confirmWidth) / 2
        self._confirmButton = DirectButton(
            parent=self._rootFrame,
            pos=(confirmCX, 0, 0),
            frameSize=(-confirmWidth / 2, confirmWidth / 2, -confirmHeight / 2,
                       confirmHeight / 2),
            command=self._onConfirmPressed,
            text_font=self._font,
            text_scale=NPKR_BUTTON_FONT_SIZE,
            text_pos=NPKR_BUTTON_FONT_OFFSET,
            text="Create Character",
            borderWidth=NPKR_BUTTON_BORDER_WIDTH)

    def getName(self):
        return str(self._nameEntry.get())

    def _onConfirmPressed(self):
        """ Reroutes this input to the parent ClassSelectionMenu """
        self._classSelectionMenu.createCharacter()

    def _checkPlaceholderText(self):
        """
            Makes the nameEntry behave more like a real name entry by removing
             the placeholder text when the player begins to interact.
        """
        # If the text entered is the placeholder text, simply remove it:
        if self._nameEntry.get() == NPKR_ENTRY_INITIAL_TEXT:
            self._nameEntry.set("")

    def _syncName(self, extraArgs=None):
        """ Syncs name with this game's host/client manager """
        self._classSelectionMenu.syncInfo(cName=self.getName())

    def close(self):
        self._rootFrame.destroy()  # Destroy ui
        del self  # Destroy this instance
Ejemplo n.º 18
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()
Ejemplo n.º 19
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)
Ejemplo n.º 20
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()
class JoinGameDialogue():
    """
        The options pop-up used when the player presses the MainMenu's
         "Join Party" button.
        The client can be configured in many ways, including:
         * Display Name
         * Host IP Address
         * Game Password
    """
    def __init__(self, confirmHandler):
        # Draw this GUI on object creation.
        self._confirmHandler = confirmHandler  # The callback handler to this GUI
        self._ipAddressEntry = None  # Reference to the IP Address Text Entry
        self._userNameEntry = None  # Reference to the User Name Text Entry
        self._font = loader.loadFont(PIERCEROMAN_FONT)
        self._elements = []
        self._draw()

    def _draw(self):
        """
            Draws this JoinGameDialogue
        """

        winWidth = base.getAspectRatio() * 2
        winHeight = 2
        # Draw translucent background frame to block clicks:
        blockingFrame = DirectFrame(parent=base.a2dTopLeft,
                                    frameSize=(0, winWidth, -winHeight, 0),
                                    frameColor=(0, 0, 0, 0.5))
        # Draw Main Dialogue Frame:
        dFOffsetY = 0.05
        dFSizeX, dFSizeY = winWidth * (3 / 5), winHeight * (2 / 3)
        dialogueFrame = DirectFrame(pos=(-dFSizeX / 2, 0,
                                         dFSizeY / 2 + dFOffsetY),
                                    frameSize=(0, dFSizeX, -dFSizeY, 0),
                                    frameTexture=UI_WINDOW)
        dialogueFrame.setTransparency(TransparencyAttrib.MAlpha)
        # Draw Title Text:
        verticalMargin = 0.102
        titleWidth = dFSizeX
        titleHeight = 0.15
        titleFontSize = (0.15, 0.15)
        dialogueTitle = DirectLabel(parent=dialogueFrame,
                                    pos=(dFSizeX / 2, 0, -verticalMargin),
                                    frameSize=(-titleWidth / 2, titleWidth / 2,
                                               -titleHeight / 2,
                                               titleHeight / 2),
                                    frameTexture=IMG_GRADIENT_1,
                                    text_align=TextNode.ACenter,
                                    text_font=self._font,
                                    text_scale=titleFontSize,
                                    text_pos=PIERCEROMAN_OFFSET_MC,
                                    text="Join Party Configuration")

        self._drawControls(dialogueFrame)  # Draw options for the pop-up frame.

        # Draw Back Button:
        buttonVerticalMargin = 0.203
        buttonHeight = 0.2
        buttonPosY = -1 - buttonVerticalMargin
        sidesMargin = 0.1
        buttonWidth = dFSizeX / 2 - sidesMargin / 2
        backButton = DirectButton(parent=dialogueFrame,
                                  pos=(dFSizeX / 2 - buttonWidth / 2, 0,
                                       -1 - buttonVerticalMargin),
                                  frameSize=(-buttonWidth / 2, buttonWidth / 2,
                                             -buttonHeight / 2,
                                             buttonHeight / 2),
                                  command=self.close,
                                  text="Back",
                                  text_font=self._font,
                                  text_scale=JOPTS_BUTON_FONT_SIZE,
                                  text_pos=JOPTS_BUTON_FONT_OFFSET,
                                  borderWidth=JOPTS_BUTTON_BORDER_WIDTH)
        # Draw Connect Button:
        connButton = DirectButton(parent=dialogueFrame,
                                  pos=(dFSizeX / 2 + buttonWidth / 2, 0,
                                       -1 - buttonVerticalMargin),
                                  frameSize=(-buttonWidth / 2, buttonWidth / 2,
                                             -buttonHeight / 2,
                                             buttonHeight / 2),
                                  command=self._onConnectButton,
                                  text_font=self._font,
                                  text="Connect",
                                  text_scale=JOPTS_BUTON_FONT_SIZE,
                                  text_pos=JOPTS_BUTON_FONT_OFFSET,
                                  borderWidth=JOPTS_BUTTON_BORDER_WIDTH)
        # Add parent elements to be deleted in self.close()
        self._elements.extend([blockingFrame, dialogueFrame])

    def _drawControls(self, dialogueFrame):
        """ Draw Helper that draws client settings controls """
        iTopMrgn = JOPTS_CONTROL_TOP_MARGIN
        spacing = JOPTS_CONTROL_SPACING
        height = JOPTS_CONTROL_HEIGHT
        width = dialogueFrame.getWidth()
        # Create containers for UI:
        ipFrame = DirectFrame(parent=dialogueFrame,
                              pos=(width / 2, 0, -iTopMrgn - spacing),
                              frameSize=(-width / 2, width / 2, -height / 2,
                                         height / 2),
                              frameTexture=UI_WINDOW)
        #nameFrame = DirectFrame(parent=dialogueFrame,
        #                        pos=(width/2, 0, -iTopMrgn - spacing * 2),
        #                        frameSize=(-width/2, width/2, -height/2,
        #                                   height/2))
        # Create the UI:
        ctrlWidth = ipFrame.getWidth() * (1 / 3)
        ctrlFontSize = (0.15, 0.15)
        self._ipAddressEntry = DirectEntry(parent=ipFrame,
                                           pos=(ctrlWidth / 2 - ctrlWidth * 1,
                                                0, 0),
                                           frameSize=(0, ctrlWidth * 2,
                                                      -height / 2, height / 2),
                                           frameColor=(0, 0, 0, 0),
                                           text_font=self._font,
                                           text_scale=ctrlFontSize,
                                           text_pos=PIERCEROMAN_OFFSET_MC,
                                           initialText=DEFAULT_IP_ADDRESS,
                                           width=8,
                                           cursorKeys=1,
                                           numLines=1)
        ipLabel = DirectLabel(parent=ipFrame,
                              pos=(ctrlWidth - ctrlWidth * 2, 0, 0),
                              frameSize=(-ctrlWidth / 2, ctrlWidth / 2,
                                         -height / 2, height / 2),
                              text="Host IP:",
                              text_font=self._font,
                              text_scale=ctrlFontSize,
                              text_pos=PIERCEROMAN_OFFSET_MC,
                              frameTexture=(IMG_GRADIENT_1))
        """self._userNameEntry = DirectEntry(parent=nameFrame,
                              pos=(ctrlWidth/2-ctrlWidth*1, 0, 0),
                              frameSize=(0, ctrlWidth*2, -height/2, height/2),
                              text_font=self._font,
                              text_scale=ctrlFontSize,
                              text_pos=PIERCEROMAN_OFFSET_MC,
                              width=8,
                              cursorKeys=1,
                              numLines=1)"""
        """
        nmLabel = DirectLabel(parent=nameFrame,
                              pos=(ctrlWidth-ctrlWidth*2, 0, 0),
                              frameSize=(-ctrlWidth/2, ctrlWidth/2, -height/2,
                                         height/2),
                              text="User Name:",
                              text_font=self._font,
                              text_scale=(0.12, 0.12),
                              text_pos=PIERCEROMAN_OFFSET_MC,
                              frameColor=(0.25,0.5,0.5,1))"""
        #TODO Change above to a server-password system

    def _onConnectButton(self):
        """
            Called when the connect button is pressed.
            Read the user's inputs and tell the gameManager to create a client.
        """
        targetIP = str(self._ipAddressEntry.get())
        #userName = self._userNameEntry.get()
        self._confirmHandler(targetIP)

    def close(self):
        """
            Closes this window and deletes all elements inside.
        """
        for element in self._elements:
            element.destroy()
        del self  # Destroy this instance
class DroneManager(DirectObject.DirectObject):
    def __init__(self, base, droneList, delay):
        self.base = base
        # the actual dimensions of the bcs drone lab in meters
        # self.roomSize = Vec3(3.40, 4.56, 2.56)
        # confined dimensions because the room and drone coordinates dont match up yet.
        # Also, flying near the windows/close to walls/too high often makes the llighthouse positioning system loose track
        self.roomSize = Vec3(1.5, 2.5, 1.7)
        self.initDrones(droneList)
        self.initUI()

        self.currentFormation = 0
        self.isRotating = False

        self.currentTimeslot = 0

        self.timeslotLengthMilli = delay

    def initDrones(self, droneList):
        """Initializes the drones defined in droneList."""
        self.isStarted = False
        self.isConnected = False
        self.drones = []  # this is the list of all drones
        self.currentDronePos = [
        ]  # this is the list of the most recent position that was sent by each drone

        if droneList == []:
            print("No drones to spawn")
        else:
            for i in range(0, len(droneList)):
                position = droneList[i][0]
                uri = droneList[i][1]
                self.drones.append(Drone(self, position, uri=uri))

        self.base.taskMgr.add(self.updateDronesTask, "UpdateDrones")
        self.base.taskMgr.add(self.updateTimeslotTask, "UpdateTimeslot")

    def updateDronesTask(self, task):
        """Run the update methods of all drones."""
        for drone in self.drones:
            drone.update()
        return task.cont

    def updateTimeslotTask(self, task):
        timeslotAmount = 2
        task.delayTime = self.timeslotLengthMilli / 1000

        self.currentTimeslot += 1
        if self.currentTimeslot >= timeslotAmount:
            self.currentTimeslot = 0

        for drone in self.drones:
            drone.updateSentPosition(self.currentTimeslot)

        return task.again

    def initUI(self):
        # initialize drone control panel
        buttonSize = (-4, 4, -.2, .8)
        buttonDistance = 0.15

        entrySize = (0, 2, -.2, .8)

        # frame = DirectFrame(frameColor=(.2, .2, .2, 1), frameSize=(-.5, .5, -.7, .15), pos=(-.9, 0, -.6), scale=.5)
        frame = DirectFrame(frameColor=(.2, .2, .2, 1),
                            frameSize=(-.5, .5, -.7, .15),
                            pos=(-.9, 0, -.4),
                            scale=.5)

        button = DirectButton(text="Start",
                              scale=.1,
                              frameSize=buttonSize,
                              command=self.startLandAll)
        button["extraArgs"] = [button]
        button.reparentTo(frame)

        button = DirectButton(text="Random Target",
                              scale=.1,
                              frameSize=buttonSize,
                              command=self.setRandomTargets)
        button.reparentTo(frame)
        button.setPos(Vec3(0, 0, -1 * buttonDistance))

        button = DirectButton(text="Stop",
                              scale=.1,
                              frameSize=buttonSize,
                              command=self.stopAll)
        button.reparentTo(frame)
        button.setPos(Vec3(0, 0, -2 * buttonDistance))

        button = DirectButton(text="Return",
                              scale=.1,
                              frameSize=buttonSize,
                              command=self.returnToWaitingPosition)
        button.reparentTo(frame)
        button.setPos(Vec3(0, 0, -3 * buttonDistance))

        button = DirectButton(text="Connect",
                              scale=.1,
                              frameSize=buttonSize,
                              command=self.toggleConnections)
        button["extraArgs"] = [button]
        button.reparentTo(frame)
        button.setPos(Vec3(0, 0, -4 * buttonDistance))

        button = DirectButton(text="Rotate",
                              scale=.1,
                              frameSize=buttonSize,
                              command=self.toggleRotation)
        button.reparentTo(frame)
        button.setPos(Vec3(0, 0, -5 * buttonDistance))

        button = DirectButton(text="Move",
                              scale=.1,
                              frameSize=buttonSize,
                              command=self.moveFormation)
        button.reparentTo(frame)
        button.setPos(Vec3(0, 0, -6 * buttonDistance))

        self.moveX = DirectEntry(text="",
                                 initialText="0",
                                 scale=.1,
                                 frameSize=entrySize)
        self.moveX.reparentTo(frame)
        self.moveX.setPos(Vec3(0.5, 0, -6 * buttonDistance))

        self.moveY = DirectEntry(text="",
                                 initialText="0",
                                 scale=.1,
                                 frameSize=entrySize)
        self.moveY.reparentTo(frame)
        self.moveY.setPos(Vec3(0.75, 0, -6 * buttonDistance))

        self.moveZ = DirectEntry(text="",
                                 initialText="0",
                                 scale=.1,
                                 frameSize=entrySize)
        self.moveZ.reparentTo(frame)
        self.moveZ.setPos(Vec3(1, 0, -6 * buttonDistance))

        self.rotSpeed = DirectEntry(text="",
                                    initialText="3",
                                    scale=.1,
                                    frameSize=entrySize)
        self.rotSpeed.reparentTo(frame)
        self.rotSpeed.setPos(Vec3(0.5, 0, -5 * buttonDistance))

        # initialize an UI element with all available formations
        loadFormationSelectionFrame(self)

    def startLandAll(self, button):
        if not self.isStarted:
            self.isStarted = True
            button["text"] = "Land"
            print("starting all")
            for drone in self.drones:
                pos = drone.getPos()
                drone.setTarget(target=Vec3(pos[0], pos[1], 1))
        else:
            self.isStarted = False
            button["text"] = "Start"
            print("landing all")
            for drone in self.drones:
                pos = drone.getPos()
                drone.setTarget(target=Vec3(pos[0], pos[1], 0))

    def returnToWaitingPosition(self):
        """Makes all drones hover above their starting position. Useful to make the drones land just where they started."""
        if not self.isStarted:
            print("can't return to waiting position, drones are not started")
            return
        print("returning to waiting positions")
        for drone in self.drones:
            drone.setTarget(drone.waitingPosition)

    def setRandomTargets(self):
        """Set random targets for all drones."""
        if not self.isStarted:
            print("can't set random targets, drones are not started")
            return
        print("setting random targets")
        for drone in self.drones:
            drone.setRandomTarget()

    def stopAll(self):
        """Stops all drones and makes them hover where they are."""
        if not self.isStarted:
            print("can't stop drones, drones are not started")
            return
        print("stopping drones")
        for drone in self.drones:
            drone.setTarget(target=drone.getPos())

    def toggleConnections(self, button):
        """Connects/Disconnects the virtual drones to/from the real drones."""
        # connect drones
        if not self.isConnected:
            self.isConnected = True
            button["text"] = "Disconnect"
            print("initializing drivers")
            cflib.crtp.init_drivers(enable_debug_driver=False)
            print("connecting drones")
            for drone in self.drones:
                drone.connect()
            # time.sleep(5)  # wait a moment so that the position estimator reports a consisten position
        # disconnect drones
        else:
            self.isConnected = False
            button["text"] = "Connect"
            print("disconnecting drones")
            for drone in self.drones:
                if drone.isConnected:
                    drone.disconnect()

    def applyFormation(self, formation):
        """Applies the supplied formation to the drones."""
        if not self.isStarted:
            print("Can't apply formation, drones are not started")
            return

        # name = formation[0]
        dronePositions = formation[1]
        requiredDrones = len(dronePositions)

        availableDrones = self.drones.__len__()
        maxNumber = availableDrones
        if requiredDrones > availableDrones:
            print(
                "The formation contains {0} points but there are only {1} available drones"
                .format(requiredDrones, availableDrones))

        if requiredDrones < availableDrones:
            print(
                "The formation contains {0} points but there are {1} available drones, some drones will remain stationary"
                .format(requiredDrones, availableDrones))
            maxNumber = requiredDrones

        # print("applying {} formation".format(formation[0]))
        for i in range(0, maxNumber):
            self.drones[i].setNewRandVec()
            self.drones[i].setTarget(
                Vec3(dronePositions[i, 0], dronePositions[i, 1],
                     dronePositions[i, 2]))

        self.currentFormation = formation

    def moveFormation(self):
        if (self.currentFormation == 0):
            return
        newFormation = self.currentFormation
        newFormation[1] += [
            float(self.moveX.get()),
            float(self.moveY.get()),
            float(self.moveZ.get())
        ]
        self.applyFormation(newFormation)

    def toggleRotation(self):
        if (self.currentFormation == 0):
            return
        if not self.isRotating:
            self.isRotating = True
            self.base.taskMgr.doMethodLater(0, self.rotateFormationTask,
                                            "RotateDrones")
        else:
            self.isRotating = False
            self.base.taskMgr.remove("RotateDrones")

    def rotateFormationTask(self, task):
        task.delayTime = 0.1
        newFormation = self.currentFormation
        speed = 2
        try:
            speed = float(self.rotSpeed.get())
        except:
            speed = 2
        r = R.from_euler('xyz', [0, 0, speed], degrees=True)
        newFormation[1] = r.apply(newFormation[1])
        self.applyFormation(newFormation)
        return task.again

    def getRandomRoomCoordinate(self) -> Vec3:
        """Returns random 3D coordinates withing the confines of the room."""
        newX = random.uniform(-self.roomSize.x / 2, self.roomSize.x / 2)
        newY = random.uniform(-self.roomSize.y / 2, self.roomSize.y / 2)
        newZ = random.uniform(0 + 0.3, self.roomSize.z)
        return Vec3(newX, newY, newZ)

    def getAllPositions(self):
        """Returns a list of the positions of all drones. Usefull when recording their paths for later."""
        lst = []
        for drone in self.drones:
            pos = drone.getPos()
            lst.append([pos.x, pos.y, pos.z])
        return lst

    def getAllVelocities(self):
        """Returns a list of the velocities of all drones. Usefull when recording their paths for later."""
        lst = []
        for drone in self.drones:
            vel = drone.getVel()
            lst.append([vel.x, vel.y, vel.z])
        return lst
Ejemplo n.º 23
0
class FrameAutenticacao(object):
    '''
    FrameAutenticacao
    '''
    def __init__(self, parent=None, **kw):
        self.__qtd_conexao = 0

        self.__frmAuth = DirectFrame(frameColor=(0, 0, 0, .3),
                                     frameSize=(-.5, .5, 0, 0.45),
                                     pos=(0, 0, -.1),
                                     enableEdit=1)

        self.__lblLogin = DirectLabel(text="Login: "******"Senha: ",
                                      scale=0.05,
                                      pos=(-0.3, 0, 0.2),
                                      frameColor=(0, 0, 0, 0),
                                      text_fg=(1, 1, 1, 1))

        self.__etySenha = DirectEntry(
            scale=0.05,
            width=12,
            pos=(-.2, 0, 0.2),
            cursorKeys=1,
            obscured=1,
            focusInCommand=self.__command_clear_senha)

        self.__btnEntrar = DirectButton(frameColor=(0, 0, 0, 1),
                                        text="Entrar",
                                        scale=0.06,
                                        pos=(0.3, 0, 0.1),
                                        text_fg=(1, 1, 1, 1),
                                        rolloverSound=None,
                                        clickSound=None,
                                        command=self.__command_entrar)

        self.__lblLogin.reparentTo(self.__frmAuth)
        self.__etyLogin.reparentTo(self.__frmAuth)
        self.__lblSenha.reparentTo(self.__frmAuth)
        self.__etySenha.reparentTo(self.__frmAuth)
        self.__btnEntrar.reparentTo(self.__frmAuth)

        self.__etyLogin.set("viner")
        self.__etySenha.set("viner")

    def __command_clear_senha(self):
        self.__etySenha.set("")

    def __command_entrar(self, txt=None):
        login = self.__etyLogin.get()
        senha = self.__etySenha.get()

        valido = True

        if login == "":
            addMensagem("O campo Login e obrigatorio !", COR_BRANCO)
            valido = False

        if senha == "":
            addMensagem("O campo Senha e obrigatorio !", COR_BRANCO)
            valido = False

        if valido:
            self.__btnEntrar["state"] = DGG.DISABLED

            taskMgr.add(self.__task_conectar_servidor,
                        'ConectarServidor',
                        extraArgs=[login, senha],
                        appendTask=True)

            #inicia_nova_thread(1, 0, "Conectar Servidor", self.__conectar_servidor, login, senha)

    def __task_conectar_servidor(self, login, senha, task):

        if self.__qtd_conexao < TENTATIVAS:

            if vinerOnline.flg_conectado == vinerOnline.ERROLOGIN:
                vinerOnline.flg_conectado = vinerOnline.DESCONECT

                self.__btnEntrar["state"] = DGG.NORMAL
                self.__qtd_conexao = 0

                addMensagem('Login ou senha invalido', COR_VERMELHO)

                self.__etyLogin.setFocus()

            elif vinerOnline.flg_conectado == vinerOnline.CONECTADO:
                #addMensagem("Conectado 12 !!!")
                #self.destroy()
                pass

            else:
                vinerOnline.conectar_servidor(login, senha)
                self.__qtd_conexao += 1

                taskMgr.doMethodLater(INTERVALO_TENTATIVAS,
                                      self.__task_conectar_servidor,
                                      'ConectarServidorLater',
                                      extraArgs=[login, senha],
                                      appendTask=True)

                msg = "Tentativa %s/5 -  Conectando..." % (self.__qtd_conexao)
                addMensagem(msg, COR_BRANCO)

        else:
            vinerOnline.flg_conectado = vinerOnline.DESCONECT
            self.__btnEntrar["state"] = DGG.NORMAL
            self.__qtd_conexao = 0
            addMensagem("Servidor nao encontrado", COR_VERMELHO)

        return task.done

    def destroy(self):
        self.__frmAuth.destroy()

        del self.__lblLogin
        del self.__etyLogin
        del self.__lblSenha
        del self.__etySenha
        del self.__btnEntrar
        del self.__frmAuth
Ejemplo n.º 24
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()
Ejemplo n.º 25
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:]))
Ejemplo n.º 26
0
class Start(DirectObject):
    def __init__(self, main):
        DirectObject.__init__(self)

        self.showbase = main

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

        self.username = "******"
        self.server = "localhost"

        self.loginScreen("Press 'Enter' to login")
        # draws the login screen

        self.usernameBox['focus'] = 1
        # sets the cursor to the username field by default

        self.accept('tab', self.cycleLoginBox)
        self.accept('shift-tab', self.cycleLoginBox)
        # enables the user to cycle through the text fields with the tab key
        # this is a standard feature on most login forms

        self.accept('enter', self.attemptConnect)
        # submits the login form, or you can just click the Login button

        # checking variable to stop multiple presses of the button spawn multiple tasks
        self.requestAttempt = False

        self.updateStatus("Type Server and Connect!")

    def cleanup(self):
        self.ignoreAll()
        self.removeAllTasks()

        self.background.destroy()
        self.usernameText.destroy()
        self.usernameBox.destroy()
        self.serverText.destroy()
        self.serverBox.destroy()
        self.loginButton.destroy()
        self.quitButton.destroy()
        self.statusText.destroy()

    def loginScreen(self, statusText):
        # creates a basic login screen that asks for a username/password

        boxloc = Vec3(0.0, 0.0, 0.0)
        # all items in the login form will have a position relative to this
        # this makes it easier to shift the entire form around once we have
        # some graphics to display with it without having to change the
        # positioning of every form element

        # p is the position of the form element relative to the boxloc
        # coordinates set above it is changed for every form element
        p = boxloc + Vec3(-0.22, 0.09, 0.0)
        self.usernameText = OnscreenText(text="Username:"******"Username: "******"",
                                       pos=p,
                                       scale=.04,
                                       initialText=self.username,
                                       numLines=1)
        # Username textbox where you type in your username

        p = boxloc + Vec3(-0.22, 0.0, 0.0)
        self.serverText = OnscreenText(text="Server:",
                                       pos=p,
                                       scale=0.05,
                                       bg=(0, 0, 0, 1),
                                       fg=(1, 1, 1, 1),
                                       align=TextNode.ARight)
        # "Server: " text that appears beside the server box

        p = boxloc + Vec3(-0.2, 0.0, 0.0)
        self.serverBox = DirectEntry(text="",
                                     pos=p,
                                     scale=.04,
                                     initialText=self.server,
                                     numLines=1)
        # server textbox where you type in the server

        p = boxloc + Vec3(0, 0, -0.090)
        self.loginButton = DirectButton(text="Login",
                                        pos=p,
                                        scale=0.048,
                                        relief=DGG.GROOVE,
                                        command=self.attemptConnect)
        # The 'Quit' button that will trigger the Quit function
        # when clicked

        p = boxloc + Vec3(1.20, 0, -0.9)
        self.quitButton = DirectButton(text="Quit",
                                       pos=p,
                                       scale=0.048,
                                       relief=DGG.GROOVE,
                                       command=self.showbase.quit)
        # The 'Quit' button that will trigger the Quit function
        # when clicked

        p = boxloc + Vec3(0, -0.4, 0)
        self.statusText = OnscreenText(text=statusText,
                                       pos=p,
                                       scale=0.043,
                                       fg=(1, 0.5, 0, 1),
                                       align=TextNode.ACenter)

    # A simple text object that you can display an error/status messages
    # to the user
    def updateStatus(self, statusText):
        self.statusText.setText(statusText)

    # all this does is change the status text.

    def checkBoxes(self):
        # checks to make sure the user inputed a username and server:
        #       if they didn't it will spit out an error message
        self.updateStatus("")
        if self.usernameBox.get() == "":
            if self.serverBox.get() == "":
                self.updateStatus(
                    "You must enter a username and server before connecting.")
            else:
                self.updateStatus("You must specify a username")
                self.serverBox['focus'] = 0
                self.usernameBox['focus'] = 1
            return False
        elif self.serverBox.get() == "":
            self.updateStatus("You must enter a server")
            self.usernameBox['focus'] = 0
            self.serverBox['focus'] = 1
            return False
        # if both boxes are filled then return True
        return True

    def attemptConnect(self):
        if self.checkBoxes():
            self.updateStatus("Attempting to connect...")
            self.joinServer(self.serverBox.get(), self.usernameBox.get())

    def joinServer(self, serverIp, username):
        self.ip = serverIp
        self.showbase.username = username
        self.updateStatus('Attempting to join server: ' + serverIp)
        # attempt to connect to the game server
        self.showbase.client = Client(self.ip, 9099, compress=True)
        if self.showbase.client.connected:
            print 'Connected to server, Awaiting authentication...'
            self.showbase.client.sendData(('username', self.showbase.username))
            self.showbase.taskMgr.add(self.authorizationListener,
                                      'Authorization Listener')
        else:
            self.updateStatus('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.updateStatus('Username already taken...')
                        return task.done
                    else:
                        self.showbase.client.passData(package)
        if auth:
            self.showbase.goToLobby()
            return task.done
        return task.again

    def cycleLoginBox(self):
        # function is triggered by the tab key so you can cycle between
        # the two input fields like on most login screens
        if self.serverBox['focus'] == 1:
            self.serverBox['focus'] = 0
            self.usernameBox['focus'] = 1
        elif self.usernameBox['focus'] == 1:
            self.usernameBox['focus'] = 0
            self.serverBox['focus'] = 1
Ejemplo n.º 27
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()
Ejemplo n.º 28
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
Ejemplo n.º 29
0
class DeveloperConsole(InteractiveInterpreter, DirectObject):
  """The name says it all."""
  def __init__(self):
    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
  
  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__
      #locals['manager'] = self.manager
      #for plugin in self.manager.named.keys():
      #  locals[plugin] = self.manager.named[plugin]
      locals['panda3d'] = panda3d
      
      # 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):
    if self.hidden:
      self.show()
    else:
      self.hide()

  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()
Ejemplo n.º 30
0
class Login():
    def __init__(self, showbase):
        self.showbase = showbase

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

        ### CONFIG LOADER ###
        config = ConfigParser.RawConfigParser()
        config.read('master.cfg')
        self.LOGIN_IP = config.get('MASTER SERVER CONNECTION', 'masterIp')
        self.LOGIN_PORT = config.getint('MASTER SERVER CONNECTION',
                                        'masterPort')

        config = ConfigParser.RawConfigParser()
        config.read('client.cfg')
        self.storeUsername = config.getint('USERDATA', 'storeUsername')
        if self.storeUsername == 1:
            self.username = config.get('USERDATA', 'username')
        else:
            self.username = ''
        self.storePassword = config.getint('USERDATA', 'storePassword')
        if self.storePassword == 1:
            self.password = config.get('USERDATA', 'password')
        else:
            self.password = ''
        ### CONFIG END ###

        self.loginScreen("Press 'Enter' to login")
        # draws the login screen

        self.usernameBox['focus'] = 1
        # sets the cursor to the username field by default

        self.showbase.accept('tab', self.cycleLoginBox)
        self.showbase.accept('shift-tab', self.cycleLoginBox)
        # enables the user to cycle through the text fields with the tab key
        # this is a standard feature on most login forms

        self.showbase.accept('enter', self.attemptLogin)
        # submits the login form, or you can just click the Login button

        # checking variable to stop multiple presses of the button spawn multiple tasks
        self.requestAttempt = False

        self.showbase.authCon = Client(self.showbase,
                                       self.LOGIN_IP,
                                       self.LOGIN_PORT,
                                       compress=True)
        if not self.showbase.authCon.getConnected():
            self.updateStatus(
                "Could not connect to the Login server\nOFFLINE MODE")
            self.showbase.online = False

    def updateConfig(self):
        config = ConfigParser.RawConfigParser()
        config.read('client.cfg')
        config.set('USERDATA', 'storeUsername',
                   self.usernameStoreBox["indicatorValue"])
        config.set('USERDATA', 'storePassword',
                   self.passwordStoreBox["indicatorValue"])
        if self.usernameStoreBox["indicatorValue"] == 1:
            config.set('USERDATA', 'username', self.usernameBox.get())
        if self.passwordStoreBox["indicatorValue"] == 1:
            config.set('USERDATA', 'password', self.passwordBox.get())
        with open('client.cfg', 'wb') as configfile:
            config.write(configfile)

    def loginScreen(self, statusText):
        # creates a basic login screen that asks for a username/password

        boxloc = Vec3(0.0, 0.0, 0.0)
        # all items in the login form will have a position relative to this
        # this makes it easier to shift the entire form around once we have
        # some graphics to display with it without having to change the
        # positioning of every form element

        # p is the position of the form element relative to the boxloc
        # coordinates set above it is changed for every form element
        p = boxloc + Vec3(-0.22, 0.09, 0.0)
        self.usernameText = OnscreenText(text="Username:"******"Username: "******"",
                                       pos=p,
                                       scale=.04,
                                       initialText=self.username,
                                       numLines=1)
        # Username textbox where you type in your username

        p = boxloc + Vec3(0.4, 0.0, 0.09)
        self.usernameStoreBox = DirectCheckButton(
            text="Save Username?",
            pos=p,
            scale=.04,
            indicatorValue=self.storeUsername)
        # Toggle to save/not save your username

        p = boxloc + Vec3(-0.22, 0.0, 0.0)
        self.passwordText = OnscreenText(text="Password:"******"Password: "******"",
                                       pos=p,
                                       scale=.04,
                                       initialText=self.password,
                                       numLines=1,
                                       obscured=1)
        # Password textbox where you type in your password
        # Note - obscured = 1 denotes that all text entered will be replaced
        # with a * like a standard password box

        p = boxloc + Vec3(0.4, 0.0, 0.0)
        self.passwordStoreBox = DirectCheckButton(
            text="Save Password?",
            pos=p,
            scale=.04,
            indicatorValue=self.storePassword)
        # Toggle to save/not save your username

        p = boxloc + Vec3(0, 0, -0.090)
        self.loginButton = DirectButton(text="Login",
                                        pos=p,
                                        scale=0.048,
                                        relief=DGG.GROOVE,
                                        command=self.attemptLogin)
        # The 'Quit' button that will trigger the Quit function
        # when clicked

        p = boxloc + Vec3(0.95, 0, -0.9)
        self.createAccButton = DirectButton(text="Create Account",
                                            scale=0.050,
                                            pos=p,
                                            relief=DGG.GROOVE,
                                            command=self.attemptCreateAccount)
        # Made a quick button for adding accounts. Its fugly

        p = boxloc + Vec3(1.20, 0, -0.9)
        self.quitButton = DirectButton(text="Quit",
                                       pos=p,
                                       scale=0.048,
                                       relief=DGG.GROOVE,
                                       command=self.showbase.quit)
        # The 'Quit' button that will trigger the Quit function
        # when clicked

        p = boxloc + Vec3(0, -0.4, 0)
        self.statusText = OnscreenText(text=statusText,
                                       pos=p,
                                       scale=0.043,
                                       fg=(1, 0.5, 0, 1),
                                       align=TextNode.ACenter)
        # A simple text object that you can display an error/status messages
        # to the user

    def updateStatus(self, statusText):
        self.statusText.setText(statusText)
        # all this does is change the status text.

    def checkBoxes(self):
        # checks to make sure the user inputed a username and password:
        #       if they didn't it will spit out an error message
        self.updateStatus("")
        if self.usernameBox.get() == "":
            if self.passwordBox.get() == "":
                self.updateStatus(
                    "You must enter a username and password before logging in."
                )
            else:
                self.updateStatus("You must specify a username")
                self.passwordBox['focus'] = 0
                self.usernameBox['focus'] = 1
            return False
        elif self.passwordBox.get() == "":
            self.updateStatus("You must enter a password")
            self.usernameBox['focus'] = 0
            self.passwordBox['focus'] = 1
            return False
        # if both boxes are filled then return True
        return True

    def attemptLogin(self):
        if self.checkBoxes():
            self.showbase.username = self.usernameBox.get()
            self.updateStatus("Attempting to login...")
            self.request(self.usernameBox.get(), self.passwordBox.get(),
                         'client')

    def attemptCreateAccount(self):
        if self.checkBoxes():
            self.updateStatus("Attempting to create account and login...")
            self.request(self.usernameBox.get(), self.passwordBox.get(),
                         'create')

    def request(self, username, password, request):
        if not self.requestAttempt:
            # attempt to connect again if it failed on startup
            if self.showbase.authCon.getConnected():
                self.requestAttempt = True
                self.loginButton["state"] = DGG.DISABLED
                self.createAccButton["state"] = DGG.DISABLED
                self.showbase.authCon.sendData((request, (username, password)))
                self.showbase.username = username
                self.showbase.online = True
                self.showbase.taskMgr.doMethodLater(0.2, self.responseReader,
                                                    'Update Login')
            else:
                # client not connected to login/auth server so display message
                self.updateStatus("Offline Mode")
                self.showbase.username = username
                self.showbase.online = False
                self.updateConfig()
                self.showbase.startMainmenu()

    def responseReader(self, task):
        if task.time > 2.5:
            self.loginButton["state"] = DGG.NORMAL
            self.createAccButton["state"] = DGG.NORMAL
            self.updateStatus("Timeout from Login server")
            return task.done
        else:
            temp = self.showbase.authCon.getData()
            for package in temp:
                if len(package) == 2:
                    print "Received: " + str(package)
                    print "Connected to login server"
                    if package[0] == 'loginFailed':
                        print "Login failed: ", package[1]
                        if package[1] == 'username':
                            self.updateStatus("Username Doesnt Exist")
                            self.passwordBox.set("")
                            self.usernameBox.set("")
                            self.passwordBox['focus'] = 0
                            self.usernameBox['focus'] = 1
                        elif package[1] == 'password':
                            self.updateStatus("Password Incorrect")
                            self.passwordBox.set("")
                            self.usernameBox['focus'] = 0
                            self.passwordBox['focus'] = 1
                        elif package[1] == 'logged':
                            self.updateStatus("Username already logged in")
                        self.requestAttempt = False
                        self.loginButton["state"] = DGG.NORMAL
                        self.createAccButton["state"] = DGG.NORMAL
                        return task.done
                    elif package[0] == 'loginValid':
                        print "Login valid: ", package[1]
                        self.updateStatus(package[1])
                        self.updateConfig()
                        self.showbase.startMainmenu()
                        return task.done
                    elif package[0] == 'createFailed':
                        print "Create failed: ", package[1]
                        if package[1] == 'exists':
                            self.updateStatus("Username Already Exists")
                            self.passwordBox.set("")
                            self.usernameBox.set("")
                            self.passwordBox['focus'] = 0
                            self.usernameBox['focus'] = 1
                        self.requestAttempt = False
                        self.loginButton["state"] = DGG.NORMAL
                        self.createAccButton["state"] = DGG.NORMAL
                        return task.done
                    elif package[0] == 'createSuccess':
                        print "Create success", package[1]
                        self.updateStatus("Account Created Successfully")
                        self.requestAttempt = False
                        self.attemptLogin()
                        return task.done
            return task.cont

    def cycleLoginBox(self):
        # function is triggered by the tab key so you can cycle between
        # the two input fields like on most login screens
        if self.passwordBox['focus'] == 1:
            self.passwordBox['focus'] = 0
            self.usernameBox['focus'] = 1
        elif self.usernameBox['focus'] == 1:
            self.usernameBox['focus'] = 0
            self.passwordBox['focus'] = 1
        # IMPORTANT: When you change the focus to one of the text boxes,
        # you have to unset the focus on the other textbox.  If you do not
        # do this Panda seems to get confused.

    def hide(self):
        self.background.destroy()
        self.usernameText.destroy()
        self.usernameBox.destroy()
        self.usernameStoreBox.destroy()
        self.passwordText.destroy()
        self.passwordBox.destroy()
        self.passwordStoreBox.destroy()
        self.loginButton.destroy()
        self.quitButton.destroy()
        self.createAccButton.destroy()
        self.statusText.destroy()

        self.showbase.ignore('tab')
        self.showbase.ignore('shift-tab')
        self.showbase.ignore('enter')
Ejemplo n.º 31
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 )
class AdminPage(BookPage):
    def __init__(self, book):
        BookPage.__init__(self, book, 'Admin Panel')
        self.fsm = ClassicFSM(
            'AdminPage',
            [
                State('off', self.enterOff, self.exitOff),
                State('basePage', self.enterBasePage, self.exitBasePage),
                State('kickSection', self.enterKickSection,
                      self.exitKickSection),
                #State('clickOnToon', self.enterClickOnToon, self.exitClickOnToon),
                State('sysMsgSection', self.enterSysMsgSection,
                      self.exitSysMsgSection)
            ],
            'off',
            'off')
        self.fsm.enterInitialState()

    def load(self):
        BookPage.load(self)
        icons = loader.loadModel('phase_4/models/gui/tfa_images.bam')
        self.icon = icons.find('**/hq-dialog-image')
        icons.detachNode()

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def enter(self):
        BookPage.enter(self)
        self.fsm.request('basePage')

    def exit(self):
        self.fsm.requestFinalState()
        BookPage.exit(self)

    def unload(self):
        del self.book
        del self.fsm
        BookPage.unload(self)

    def enterSysMsgSection(self):
        geom = CIGlobals.getDefaultBtnGeom()
        self.infoLbl = OnscreenText(
            text="Inform all online players about something.", pos=(0, 0.45))
        self.msgEntry = DirectEntry(
            initialText="System Message...",
            scale=0.055,
            width=15,
            numLines=4,
            command=self.sendSystemMessageCommand,
            focusInCommand=base.localAvatar.chatInput.disableKeyboardShortcuts,
            focusOutCommand=base.localAvatar.chatInput.enableKeyboardShortcuts,
            pos=(-0.4, 0, 0))
        self.sendBtn = DirectButton(
            geom=geom,
            text_scale=0.04,
            relief=None,
            scale=1.0,
            text="Send",
            pos=(0, 0, -0.35),
            text_pos=(0, -0.01),
            command=self.sendSystemMessageCommand,
        )
        self.cancelBtn = DirectButton(geom=geom,
                                      text_scale=0.04,
                                      relief=None,
                                      scale=1.0,
                                      text="Cancel",
                                      pos=(-0.45, 0.15, -0.55),
                                      text_pos=(0, -0.01),
                                      command=self.fsm.request,
                                      extraArgs=['basePage'])

    # Occasionally, extra arguments are sent and this extra variable must be here to capture them.
    def sendSystemMessageCommand(self, _=None):
        msg = self.msgEntry.get()
        DISTRICT_WIDE_MSG(msg)
        self.fsm.request('basePage')

    def exitSysMsgSection(self):
        self.infoLbl.destroy()
        del self.infoLbl
        self.msgEntry.destroy()
        del self.msgEntry
        self.sendBtn.destroy()
        del self.sendBtn
        self.cancelBtn.destroy()
        del self.cancelBtn

    def enterKickSection(self):
        geom = CIGlobals.getDefaultBtnGeom()
        self.infoLbl = OnscreenText(text="Kick or Ban?", pos=(0, 0.45))
        self.kickBtn = DirectButton(geom=geom,
                                    text_scale=0.04,
                                    relief=None,
                                    scale=1.0,
                                    text="Kick",
                                    pos=(0, 0, 0.1),
                                    text_pos=(0, -0.01),
                                    command=self.book.finishedResume,
                                    extraArgs=[KickBanDialog, [0]])
        self.banBtn = DirectButton(geom=geom,
                                   text_scale=0.04,
                                   relief=None,
                                   scale=1.0,
                                   text="Ban",
                                   pos=(0, 0, 0.0),
                                   text_pos=(0, -0.01),
                                   command=self.book.finishedResume,
                                   extraArgs=[KickBanDialog, [1]])
        self.cancelBtn = DirectButton(geom=geom,
                                      text_scale=0.04,
                                      relief=None,
                                      scale=1.0,
                                      text="Cancel",
                                      pos=(-0.45, 0.15, -0.45),
                                      text_pos=(0, -0.01),
                                      command=self.fsm.request,
                                      extraArgs=['basePage'])

    def exitKickSection(self):
        self.banBtn.destroy()
        del self.banBtn
        self.infoLbl.destroy()
        del self.infoLbl
        self.cancelBtn.destroy()
        del self.cancelBtn
        self.kickBtn.destroy()
        del self.kickBtn

    def enterBasePage(self):
        geom = CIGlobals.getDefaultBtnGeom()
        self.ghostBtn = DirectButton(geom=geom,
                                     text_scale=0.04,
                                     relief=None,
                                     scale=1.0,
                                     text="Toggle Ghost",
                                     pos=(-0.45, 0.15, 0.5),
                                     text_pos=(0, -0.01),
                                     command=TOGGLE_GHOST)
        self.bgBtn = DirectButton(geom=geom,
                                  text_scale=0.04,
                                  relief=None,
                                  scale=1.0,
                                  text="Toggle Background",
                                  pos=(-0.45, 0.15, 0.40),
                                  text_pos=(0, -0.01),
                                  command=self.toggleBackground)
        self.idBtn = DirectButton(geom=geom,
                                  text_scale=0.04,
                                  relief=None,
                                  scale=1.0,
                                  text="Toggle Player Ids",
                                  pos=(-0.45, 0.15, 0.3),
                                  text_pos=(0, -0.01),
                                  command=TOGGLE_PLAYER_IDS)
        self.kickBtn = DirectButton(geom=geom,
                                    text_scale=0.04,
                                    relief=None,
                                    scale=1.0,
                                    text="Kick/Ban Player",
                                    pos=(0.45, 0.15, 0.5),
                                    text_pos=(0, -0.01),
                                    command=self.openKickPage)
        self.systemMsgBtn = DirectButton(geom=geom,
                                         text_scale=0.04,
                                         relief=None,
                                         scale=1.0,
                                         text="System Message",
                                         pos=(-0.45, 0.15, 0.1),
                                         text_pos=(0, -0.01),
                                         command=self.openSysMsgPage)
        self.oobeBtn = DirectButton(geom=geom,
                                    text_scale=0.04,
                                    relief=None,
                                    scale=1.0,
                                    text="Toggle OOBE",
                                    pos=(-0.45, 0.15, 0.2),
                                    text_pos=(0, -0.01),
                                    command=base.oobe)
        self.directBtn = DirectButton(geom=geom,
                                      text_scale=0.04,
                                      relief=None,
                                      scale=1.0,
                                      text="Start DIRECT",
                                      pos=(-0.45, 0.15, 0.1),
                                      text_pos=(0, -0.01),
                                      command=self.doStartDirect)
        self.pstatsBtn = DirectButton(geom=geom,
                                      text_scale=0.04,
                                      relief=None,
                                      scale=1.0,
                                      text="Toggle PStats",
                                      pos=(-0.45, 0.15, 0.0),
                                      text_pos=(0, -0.01),
                                      command=self.togglePStats)
        self.pingBtn = DirectButton(geom=geom,
                                    text_scale=0.04,
                                    relief=None,
                                    scale=1.0,
                                    text="Toggle Ping",
                                    pos=(-0.45, 0.15, -0.1),
                                    text_pos=(0, -0.01),
                                    command=base.cr.togglePing)
        self.tokenBtn = DirectButton(geom=geom,
                                     text_scale=0.04,
                                     relief=None,
                                     scale=1.0,
                                     text="Modify Access Level",
                                     pos=(0.45, 0.15, 0.4),
                                     text_pos=(0, -0.01),
                                     command=self.book.finishedResume,
                                     extraArgs=[AdminTokenDialog, []])
        self.worldBtn = DirectButton(geom=geom,
                                     text_scale=0.04,
                                     relief=None,
                                     scale=1.0,
                                     text="Give World Access",
                                     pos=(0.45, 0.15, 0.3),
                                     text_pos=(0, -0.01),
                                     command=self.book.finishedResume,
                                     extraArgs=[WorldAccessDialog, []])
        self.allGagsBtn = DirectButton(geom=geom,
                                       text_scale=0.04,
                                       relief=None,
                                       scale=1.0,
                                       text="Restock All Gags",
                                       pos=(0.45, 0.15, 0.2),
                                       text_pos=(0, -0.01),
                                       command=SEND_REQ_UNLOCK_GAGS)

        self.allLaffBtn = DirectButton(geom=geom,
                                       text_scale=0.04,
                                       relief=None,
                                       scale=1.0,
                                       text="Refill Laff",
                                       pos=(0.45, 0.15, 0.1),
                                       text_pos=(0, -0.01),
                                       command=SEND_REQ_REFILL_LAFF)

        self.physDbgBtn = DirectButton(geom=geom,
                                       text_scale=0.039,
                                       relief=None,
                                       scale=1.0,
                                       text="Toggle Physics Debug",
                                       pos=(0.45, 0.15, 0.0),
                                       text_pos=(0, -0.01),
                                       command=self.togglePhysDbg)
        self.analyzeBtn = DirectButton(geom=geom,
                                       text_scale=0.04,
                                       relief=None,
                                       scale=1.0,
                                       text="Analyze Scene",
                                       pos=(0.45, 0.15, -0.1),
                                       text_pos=(0, -0.01),
                                       command=self.doAnalyzeScene)
        self.listBtn = DirectButton(geom=geom,
                                    text_scale=0.04,
                                    relief=None,
                                    scale=1.0,
                                    text="List Scene",
                                    pos=(0.45, 0.15, -0.2),
                                    text_pos=(0, -0.01),
                                    command=render.ls)
        self.noClipBtn = DirectButton(geom=geom,
                                      text_scale=0.04,
                                      relief=None,
                                      scale=1.0,
                                      text="Toggle No Clip",
                                      pos=(0.45, 0.15, -0.3),
                                      text_pos=(0, -0.01),
                                      command=self.toggleNoClip)
        base.cr.playGame.getPlace().maybeUpdateAdminPage()
        del geom

    def doStartDirect(self):
        base.startTk()
        base.startDirect()

    def doAnalyzeScene(self):
        render.analyze()

        ls = LineStream()
        sga = SceneGraphAnalyzer()
        sga.addNode(render.node())
        sga.write(ls)
        text = ""
        while ls.isTextAvailable():
            text += ls.getLine() + "\n"
        self.acceptOnce('analyzedone', self.__handleAnalyzeDone)
        self.analyzeDlg = GlobalDialog(message=text,
                                       style=Ok,
                                       doneEvent='analyzedone',
                                       text_scale=0.05)
        self.analyzeDlg.show()

    def __handleAnalyzeDone(self):
        self.analyzeDlg.cleanup()
        del self.analyzeDlg

    def toggleNoClip(self):
        ncl = not base.localAvatar.walkControls.controller.noClip
        base.localAvatar.walkControls.controller.noClip = ncl

        if ncl:
            base.cr.myDistrict.systemMessage("No Clip Enabled")
        else:
            base.cr.myDistrict.systemMessage("No Clip Disabled")

    def togglePhysDbg(self):
        base.setPhysicsDebug(not base.physicsDbgFlag)

    def togglePStats(self):
        if PStatClient.isConnected():
            PStatClient.disconnect()
        else:
            # in production, show stats viewer on the server
            if base.config.GetBool("pstats-view-on-server", False):
                PStatClient.connect("127.0.0.1" if not metadata.IS_PRODUCTION
                                    else "gameserver.coginvasion.online")
            else:
                PStatClient.connect("127.0.0.1")

    def toggleBackground(self):
        if render.isHidden():
            render.show()
        else:
            render.hide()
        if self.book.isBackgroundHidden():
            self.book.show()
            self.book.setBackgroundHidden(False)
        else:
            self.book.hide()
            self.book.setBackgroundHidden(True)

    def openKickPage(self):
        self.fsm.request('kickSection')

    def openSysMsgPage(self):
        self.fsm.request('sysMsgSection')

    def exitBasePage(self):
        self.noClipBtn.destroy()
        del self.noClipBtn
        self.systemMsgBtn.destroy()
        del self.systemMsgBtn
        self.idBtn.destroy()
        del self.idBtn
        self.kickBtn.destroy()
        del self.kickBtn
        self.bgBtn.destroy()
        del self.bgBtn
        self.ghostBtn.destroy()
        del self.ghostBtn
        self.oobeBtn.destroy()
        del self.oobeBtn
        self.tokenBtn.destroy()
        del self.tokenBtn
        self.worldBtn.destroy()
        del self.worldBtn
        self.allGagsBtn.destroy()
        del self.allGagsBtn
        self.allLaffBtn.destroy()
        del self.allLaffBtn
        self.physDbgBtn.destroy()
        del self.physDbgBtn
        self.analyzeBtn.destroy()
        del self.analyzeBtn
        if hasattr(self, 'analyzeDlg'):
            self.ignore('analyzedone')
            self.analyzeDlg.cleanup()
            del self.analyzeDlg
        self.directBtn.destroy()
        del self.directBtn
        self.listBtn.destroy()
        del self.listBtn
        self.pstatsBtn.destroy()
        del self.pstatsBtn
        self.pingBtn.destroy()
        del self.pingBtn