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()
class Fighter(DirectObject): def __init__(self): base.disableMouse() # Carga el fondo del juego self.bg = loader.loadModel("models/plane") self.bg.reparentTo(camera) self.bg.setPos(0, 200, 0) self.bg.setScale(300, 0, 146) self.bg.setTexture(loader.loadTexture("models/Backgrounds/farback.png"), 1) # Inicializa el gestor de teclado y los objetos del juego self.inputManager = InputManager() # Inicializa el menu del juego self.inicializarMenu() self.marcador = None self.barraEnergia = None self.marcadorFinalNP = None self.entrada = None self.rankingNP = None self.mostrarMenuJuego() self.accept("m", self.cambiarMenuJuego) self.accept("q", self.salir) # Inicializa el menu def inicializarMenu(self): self.menuGraphics = loader.loadModel("models/MenuGraphics") self.fonts = {"silver" : loader.loadFont("fonts/LuconSilver"), "blue" : loader.loadFont("fonts/LuconBlue"), "orange" : loader.loadFont("fonts/LuconOrange")} self.menu = Menu(self.menuGraphics, self.fonts, self.inputManager) self.menu.initMenu([0, None, ["Nueva Partida", "Salir"], [[self.nuevaPartida], [self.salir]], [[None], [None]]]) # Comienza una partida def nuevaPartida(self): if (not self.marcadorFinalNP is None): self.marcadorFinalNP.detachNode() self.marcadorFinalNP.remove() if (not self.rankingNP is None): self.rankingNP.detachNode() self.rankingNP.remove() self.ship = Ship(self.inputManager) self.mostrarInfo() taskMgr.add(self.actualizarInfo, "Actualizar Puntuacion") # Inicializa y muestra el marcador del jugador def mostrarInfo(self): self.marcador = TextNode("Marcador") self.marcador.setText("Puntos: " + str(self.ship.puntos)) self.marcador.setCardColor(0, 0, 0, 1) self.marcador.setCardDecal(True) self.marcador.setCardAsMargin(0.4, 0.4, 0.4, 0.4) self.marcadorNP = aspect2d.attachNewNode(self.marcador) self.marcadorNP.reparentTo(base.a2dTopLeft) self.marcadorNP.setPos(0.02, 0, -0.05) self.marcadorNP.setScale(0.07) self.barraEnergia = DirectWaitBar(text = "Energia", value = 5, range = 5, scale = 0.3, pos = (0, 0, 0.95)) # Actualiza la puntuacion del jugador en pantalla def actualizarInfo(self, tarea): self.marcador.setText("Puntos: " + str(self.ship.puntos)) self.barraEnergia["value"] = self.ship.vida self.barraEnergia.setValue() # Termina la partida if (self.ship.terminarPartida): self.terminarPartida() return tarea.done return tarea.cont # Termina partida liberando recursos para poder empezar una nueva # sin reiniciar el juego def terminarPartida(self): # Solicita al usuario un nombre para la tabla de puntuaciones self.entrada = DirectEntry(width = 15, numLines = 1, scale = 0.07, cursorKeys = 1, frameSize = (0, 15, 0, 1), command = self.almacenarPuntuacion, pos = (-0.3, 0, 0.1), focus = True, text_pos = (0.2, 0.2)) self.puntos = self.ship.puntos self.ship.ship.detachNode() self.ship.ship.remove() taskMgr.remove("Mover Nave") taskMgr.remove("Generar Enemigos") taskMgr.remove("Comprobar Impactos") taskMgr.remove("Actualizar Puntuacion") taskMgr.remove("Explosionar*") self.mostrarFinPartida() # Libera los recursos de la partida que ha terminado self.ship.eliminarObjetos() del self.ship del self.menuGraphics del self.menu self.marcadorNP.detachNode() self.marcadorNP.remove() self.barraEnergia.destroy() del self.marcador del self.barraEnergia #self.inicializarMenu() # Almacena la puntuacion del jugador def almacenarPuntuacion(self, valor): self.crearBDD() db = sqlite3.connect("datos.db") cursor = db.cursor() parametros = (valor, self.puntos) cursor.execute("insert into puntuaciones values (?, ?)", parametros) db.commit() cursor.close() self.entrada.destroy() self.mostrarTopPuntuacion() self.inicializarMenu() # Crea la Base de Datos si no existe ya def crearBDD(self): db = sqlite3.connect("datos.db") cursor = db.cursor() args = ("puntuaciones",) cursor.execute("select name from sqlite_master where name = ?", args) if len(cursor.fetchall()) == 0: cursor.execute("create table puntuaciones (nombre text, puntuacion numeric)") db.commit() cursor.close() # Muestra las 10 mejores puntuaciones def mostrarTopPuntuacion(self): # Extrae las 10 mejores puntuaciones de la base de datos db = sqlite3.connect("datos.db") cursor = db.cursor() cursor.execute("select nombre, puntuacion from puntuaciones order by puntuacion desc limit 10") puntuaciones = cursor.fetchall() cursor.close() resultado = "-- MEJORES PUNTUACIONES --\n-Jugador- -Puntuacion-\n\n" for nombre, puntuacion in puntuaciones: resultado += nombre + " " + str(puntuacion) + "\n" # Muestra las 10 mejores puntuaciones self.ranking = TextNode("Ranking") self.ranking.setText(resultado) self.ranking.setCardColor(0, 0, 0, 1) self.ranking.setCardDecal(True) self.ranking.setCardAsMargin(0.4, 0.4, 0.4, 0.4) self.rankingNP = aspect2d.attachNewNode(self.ranking) self.rankingNP.reparentTo(base.a2dTopLeft) self.rankingNP.setPos(1, 0, -1) self.rankingNP.setScale(0.07) # Muestra el mensaje de fin de partida def mostrarFinPartida(self): self.marcadorFinal = TextNode("Marcador Final") self.marcadorFinal.setText("Game Over!\nPuntuacion: " + str(self.ship.puntos) +"\n\n" + "Escribe tu nombre:") self.marcadorFinal.setCardColor(0, 0, 0, 1) self.marcadorFinal.setCardDecal(True) self.marcadorFinal.setCardAsMargin(0.4, 0.4, 0.4, 0.4) self.marcadorFinalNP = aspect2d.attachNewNode(self.marcadorFinal) self.marcadorFinalNP.setPos(-0.3, 0, 0.5) self.marcadorFinalNP.setScale(0.07) # Muestra un menu con las opciones durante el juego def mostrarMenuJuego(self): self.textoMenu = {} self.textoMenu["titulo"] = OnscreenText(text = "", pos = (0, 0.92), scale = 0.08, fg = (1, 1, 1, 1), bg = (0, 0, 1, 0.7)) self.textoMenu["descripcion"] = OnscreenText(text = "", pos = (0, 0.84), scale = 0.05, fg = (1, 1, 0, 1), bg = (0, 0, 0, 0.5)) self.textoMenu["opciones"] = OnscreenText(text = "", pos = (-1.3, 0), scale = 0.05, fg = (1, 1, 1, 1), bg = (1, 0.3, 0, 0.6), align=TextNode.ALeft, wordwrap = 15) self.textoMenu["opciones"].setText("** OPCIONES **\n" + "m = ocultar menu\n" + "q = salir") # Inicialmente el menu se deja oculto for linea in self.textoMenu.values(): linea.hide() # Muestra / Oculta el menu de juego def cambiarMenuJuego(self): for linea in self.textoMenu.values(): if linea.isHidden(): linea.show() else: linea.hide() # Sale del juego def salir(self): print("Saliendo . . .") sys.exit()
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()
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()
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()
class ChatBox(DirectObject): MESSAGE_LIFE = 10 MAX_NUM_MESSAGES = 15 (TYPE_GLOBAL, TYPE_TEAM, TYPE_CONSOLE) = range(3) messageTypeToPrefix = { TYPE_GLOBAL : 'Global:', TYPE_TEAM : 'Team:', TYPE_CONSOLE : 'Console' } def __init__(self): self.textNodes = [] self.messageType = None self.rootFrame = DirectFrame(pos = (0.03, 0, 0.2), frameColor = (0, 0, 0, 0), frameSize = (0, 1, 0, 1), parent = base.a2dBottomLeft) self.rootFrame.setBin('fixed', GUIOrder.ORDER[GUIOrder.CHAT]) self.entryFrame = DirectFrame(pos = (0, 0, 0), frameColor = (0, 0, 0, 0.1), frameSize = (0, 1, 0, 0.1), parent = self.rootFrame) self.chatarea = DirectEntry(width = 27, scale = Settings.CHAT_HEIGHT, pos = (0, 0, 0), frameColor = (0, 0, 0, 0), text_fg = (1, 1, 1, 1), numLines = 1, cursorKeys = 1, rolloverSound = None, clickSound = None, focus = 0, command = self.OnChatEntered, parent = self.entryFrame) self.typeText = OnscreenText(text = '', pos = (0, Settings.CHAT_HEIGHT + 0.01), scale = Settings.CHAT_HEIGHT, fg = (1, 1, 1, 1), mayChange = True, align = TextNode.ALeft, parent = self.entryFrame) self.displayFrame = DirectFrame(pos = (0, 0, 0.1), frameColor = (0, 0, 0, 0), frameSize = (0, 1, 0, 0.42), parent = self.rootFrame) self.chatarea.enterText('') self.entryFrame.hide() self.chatarea['focus'] = 0 self.chatarea.setFocus() def OnChatEntered(self, enteredText): enteredText = enteredText.strip() self.Hide() if(len(enteredText) > 0): ChatEnteredEvent(self.messageType, enteredText).Fire() def AddMessage(self, prefix, prefixColor, message): parent = self.displayFrame.attachNewNode('messageParent') prefixTextNode = TextNode('prefixMessage') prefixTextNode.setText(prefix) prefixTextNode.setTextColor(prefixColor) prefixTextNode.setShadow(0.05, 0.05) prefixTextNode.setShadowColor(Globals.COLOR_BLACK) prefixTextNodePath = parent.attachNewNode(prefixTextNode) prefixTextNodePath.setScale(Settings.CHAT_HEIGHT) messageTextNode = TextNode('prefixMessage') messageTextNode.setText(message) messageTextNode.setTextColor(1, 1, 1, 1) messageTextNode.setShadow(0.05, 0.05) messageTextNode.setShadowColor(Globals.COLOR_BLACK) messageTextNodePath = parent.attachNewNode(messageTextNode) messageTextNodePath.setScale(Settings.CHAT_HEIGHT) messageTextNodePath.setPos(Vec3(prefixTextNode.calcWidth(prefix) * Settings.CHAT_HEIGHT, 0, 0)) taskMgr.remove('HideMessageLog') taskMgr.doMethodLater(ChatBox.MESSAGE_LIFE, self.HideMessageLog, 'HideMessageLog') self.ShowMessageLog() self.textNodes.append(parent) if(len(self.textNodes) > ChatBox.MAX_NUM_MESSAGES): self.RemoveMessage(self.textNodes[0]) self.RedrawMessages() def RedrawMessages(self): n = len(self.textNodes) for i, textNode in enumerate(self.textNodes): LerpPosInterval(textNode, 0.5, (0, 0, (n-i) * (Settings.CHAT_HEIGHT + 0.01))).start() def RemoveMessage(self, textNode): self.textNodes.remove(textNode) textNode.removeNode() def HideMessageLog(self, task = None): self.displayFrame.hide() def ShowMessageLog(self): self.displayFrame.show() def Hide(self): self.chatarea.enterText('') self.entryFrame.hide() self.chatarea['focus'] = 0 self.chatarea.setFocus() self.HideMessageLog() ChatCloseEvent().Fire() def Show(self, messageType): self.messageType = messageType self.entryFrame.show() self.chatarea['focus'] = 1 self.chatarea.setFocus() self.typeText.setText(ChatBox.GetPrefix(self.messageType)) self.ShowMessageLog() ChatOpenEvent().Fire() def EnableKeyboardListening(self): self.acceptOnce('escape', self.Hide) def DisableKeyboardListening(self): self.ignoreAll() @staticmethod def GetPrefix(messageType): return ChatBox.messageTypeToPrefix[messageType] def Destroy(self): taskMgr.remove('HideMessageLog') self.rootFrame.destroy() self.entryFrame.destroy() self.chatarea.destroy() self.typeText.destroy() self.displayFrame.destroy() self.ignoreAll()
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')
class TextEntry(object): """Enter Text using Keyboard, disable shortcut keys""" def __init__(self, path, mode, command, initialText='', title='Title', lines=1, width=20, x=0, z=0, font=5, titleWidth=30, textDelta=0.055): self.titleWidth = titleWidth self.textDelta = textDelta self.path = path self.mode = mode self.command = command self.initial = initialText self.title = title self.lines = lines self.width = width self.myEntry = None self.myTitle = None self.x = x self.z = z self.y = 0 self.scale = 0.03 self.font = '%s/star%s' % (self.path, font) self.myFont = loader.loadFont(self.font) self.setMyEntry() self.createTitleCard() def createTitleCard(self): """Default Title label""" self.myTitle = textonscreen.TextOnScreen(self.path, self.title, 0.025, 5, aspect2d) self.myTitle.writeTextToScreen(self.x + 0.01, 0, self.z + self.textDelta, self.titleWidth) self.myTitle.setTitleStyle() def setMyEntry(self): self.myEntry = DirectEntry(text='', scale=self.scale, command=self.onCommand, numLines=self.lines, width=self.width, pos=(self.x, self.y, self.z), entryFont=self.myFont, focusInCommand=self.onFocus, focusOutCommand=self.onOutFocus, frameColor=(0, 0, 0, .7), text_fg=(1, 1, 1, 1), initialText=self.initial, clickSound=self.mode.game.app.beep01Sound, rolloverSound=None) def onCommand(self, textEntered): self.setShortcuts() myMethod = getattr(self.mode, self.command) myMethod(textEntered) def destroy(self): self.myEntry.destroy() self.myTitle.destroy() def onFocus(self): self.ignoreShortcuts() self.mode.onEntryFocus() def onOutFocus(self): self.mode.setShortcuts() self.mode.onEntryOutFocus() def ignoreShortcuts(self): """Ignore all keyboard shortcuts created""" self.mode.game.app.ignoreAll() def setShortcuts(self): self.mode.setShortcuts()
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')
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