class Save: def __init__(self, nodes, connections, exceptionSave=False): self.dlgOverwrite = None self.dlgOverwriteShadow = None self.jsonElements = JSONTools().get(nodes, connections) if exceptionSave: tmpPath = os.path.join(tempfile.gettempdir(), "NEExceptionSave.json") self.__executeSave(True, tmpPath) logging.info("Wrote crash session file to {}".format(tmpPath)) else: self.browser = DirectFolderBrowser(self.save, True, defaultFilename="project.json") def save(self, doSave): if doSave: path = self.browser.get() path = os.path.expanduser(path) path = os.path.expandvars(path) if os.path.exists(path): self.dlgOverwrite = YesNoDialog( text="File already Exist.\nOverwrite?", relief=DGG.RIDGE, frameColor=(1, 1, 1, 1), frameSize=(-0.5, 0.5, -0.3, 0.2), sortOrder=1, button_relief=DGG.FLAT, button_frameColor=(0.8, 0.8, 0.8, 1), command=self.__executeSave, extraArgs=[path], scale=300, pos=(base.getSize()[0] / 2, 0, -base.getSize()[1] / 2), parent=base.pixel2d) self.dlgOverwriteShadow = DirectFrame( pos=(base.getSize()[0] / 2 + 10, 0, -base.getSize()[1] / 2 - 10), sortOrder=0, frameColor=(0, 0, 0, 0.5), frameSize=self.dlgOverwrite.bounds, scale=300, parent=base.pixel2d) self.dlgOverwrite.setBin("gui-popup", 1) else: self.__executeSave(True, path) base.messenger.send("setLastPath", [path]) self.browser.destroy() del self.browser def __executeSave(self, overwrite, path): if self.dlgOverwrite is not None: self.dlgOverwrite.destroy() if self.dlgOverwriteShadow is not None: self.dlgOverwriteShadow.destroy() if not overwrite: return with open(path, 'w') as outfile: json.dump(self.jsonElements, outfile, indent=2)
class InviteDialog(GameObject, Subject): def __init__(self, menu_props, from_, roomname): Subject.__init__(self) GameObject.__init__(self) self.from_ = from_ self.roomname = roomname self.dialog = YesNoDialog( base.a2dBottomLeft, text=_('%s has invited you to a match, do you agree?') % from_, text_wordwrap=16, text_fg=menu_props.text_active_col, text_font=menu_props.font, pad=(.03, .03), topPad=0, midPad=.01, relief=FLAT, frameColor=(.8, .8, .8, .9), button_relief=FLAT, button_frameColor=(.2, .2, .2, .2), button_text_fg=menu_props.text_active_col, button_text_font=menu_props.font, buttonValueList=['yes', 'no'], command=self.on_btn) size = self.dialog['frameSize'] self.dialog.set_pos(-size[0] + .05, 1, -size[2] + .05) self.eng.log('created dialog ' + self.dialog['text']) def on_btn(self, val): self.eng.log('invite button ' + val) self.notify('on_invite_answer', self.from_, self.roomname, val == 'yes') def destroy(self): self.eng.log('destroyed dialog ' + self.dialog['text']) self.dialog = self.dialog.destroy() Subject.destroy(self) GameObject.destroy(self)
class FriendDialog(GameObject, Subject): def __init__(self, menu_props, user): Subject.__init__(self) GameObject.__init__(self) self.user = user self.dialog = YesNoDialog( base.a2dBottomLeft, text=_('%s wants to be a (XMPP) friend of you, do you agree?') % user, text_wordwrap=16, text_fg=menu_props.text_active_col, text_font=menu_props.font, pad=(.03, .03), topPad=0, midPad=.01, relief=FLAT, frameColor=(.8, .8, .8, .9), button_relief=FLAT, button_frameColor=(.2, .2, .2, .2), button_text_fg=menu_props.text_active_col, button_text_font=menu_props.font, buttonValueList=['yes', 'no'], command=self.on_btn) size = self.dialog['frameSize'] self.dialog.set_pos(-size[0] + .05, 1, -size[2] + .05) self.eng.log('created dialog ' + self.dialog['text']) def on_btn(self, val): self.eng.log('friend button ' + val) self.notify('on_friend_answer', self.user, val == 'yes') def destroy(self): self.eng.log('destroyed dialog ' + self.dialog['text']) self.dialog = self.dialog.destroy() Subject.destroy(self) GameObject.destroy(self)
class ExporterProject: def __init__(self, fileName, guiElementsDict, getEditorFrame, usePixel2D, exceptionSave=False, autosave=False, tooltip=None): self.guiElementsDict = guiElementsDict self.getEditorFrame = getEditorFrame self.usePixel2D = usePixel2D self.isAutosave = False if exceptionSave: self.excSave() return if autosave: self.isAutosave = True self.autoSave(fileName) return self.dlgPathSelect = PathSelect(self.save, "Save Project File", "Save file path", "Save", fileName, tooltip) def excSave(self): self.dlgOverwrite = None self.dlgOverwriteShadow = None tmpPath = os.path.join(tempfile.gettempdir(), "DGDExceptionSave.json") self.__executeSave(True, tmpPath) logging.info("Wrote crash session file to {}".format(tmpPath)) def autoSave(self, fileName=""): self.dlgOverwrite = None self.dlgOverwriteShadow = None if fileName == "": fileName = os.path.join(tempfile.gettempdir(), "DGDAutosave.json") self.__executeSave(True, fileName) logging.info("Wrote autosave file to {}".format(fileName)) def save(self, doSave): if doSave: self.dlgOverwrite = None self.dlgOverwriteShadow = None path = self.dlgPathSelect.getPath() path = os.path.expanduser(path) path = os.path.expandvars(path) if os.path.exists(path): self.dlgOverwrite = YesNoDialog( text="File already Exist.\nOverwrite?", relief=DGG.RIDGE, frameColor=(1, 1, 1, 1), frameSize=(-0.5, 0.5, -0.3, 0.2), sortOrder=1, button_relief=DGG.FLAT, button_frameColor=(0.8, 0.8, 0.8, 1), command=self.__executeSave, extraArgs=[path], scale=300, pos=(base.getSize()[0] / 2, 0, -base.getSize()[1] / 2), parent=base.pixel2d) self.dlgOverwriteShadow = DirectFrame( pos=(base.getSize()[0] / 2 + 10, 0, -base.getSize()[1] / 2 - 10), sortOrder=0, frameColor=(0, 0, 0, 0.5), frameSize=self.dlgOverwrite.bounds, scale=300, parent=base.pixel2d) else: self.__executeSave(True, path) base.messenger.send("setLastPath", [path]) self.dlgPathSelect.destroy() del self.dlgPathSelect def __executeSave(self, overwrite, path): if self.dlgOverwrite is not None: self.dlgOverwrite.destroy() if self.dlgOverwriteShadow is not None: self.dlgOverwriteShadow.destroy() if not overwrite: return jsonTools = JSONTools() jsonElements = jsonTools.getProjectJSON(self.guiElementsDict, self.getEditorFrame, self.usePixel2D) with open(path, 'w') as outfile: json.dump(jsonElements, outfile, indent=2) if not self.isAutosave: base.messenger.send("clearDirtyFlag")
class ExporterPy: functionMapping = { "base":{"initialText":"get"}, "text":{"align":"align", "scale":"scale", "pos":"pos", "fg":"fg", "bg":"bg"}} # list of control names starting with the following will be ignored ignoreControls = ["item", "cancelframe", "popupMarker", "popupMenu"] # list of control names staritng with the following will always be included explIncludeControls = ["itemFrame"] def __init__(self, saveFile, guiElementsDict, customWidgetHandler, getEditorFrame, tooltip, usePixel2D): self.guiElementsDict = guiElementsDict self.customWidgetHandler = customWidgetHandler jsonTools = JSONTools() self.jsonFileContent = jsonTools.getProjectJSON(self.guiElementsDict, getEditorFrame, usePixel2D) self.jsonElements = self.jsonFileContent["ComponentList"] self.createdParents = ["root"] self.postponedElements = {} self.postSetupCalling = [] self.radiobuttonDict = {} self.customWidgetAddDict = {} importStatements = { "DirectButton":"from direct.gui.DirectButton import DirectButton", "DirectEntry":"from direct.gui.DirectEntry import DirectEntry", "DirectEntryScroll":"from direct.gui.DirectEntryScroll import DirectEntryScroll", "DirectCheckBox":"from direct.gui.DirectCheckBox import DirectCheckBox", "DirectCheckButton":"from direct.gui.DirectCheckButton import DirectCheckButton", "DirectOptionMenu":"from direct.gui.DirectOptionMenu import DirectOptionMenu", "DirectRadioButton":"from direct.gui.DirectRadioButton import DirectRadioButton", "DirectSlider":"from direct.gui.DirectSlider import DirectSlider", "DirectScrollBar":"from direct.gui.DirectScrollBar import DirectScrollBar", "DirectScrolledList":"from direct.gui.DirectScrolledList import DirectScrolledList", "DirectScrolledListItem":"from direct.gui.DirectScrolledList import DirectScrolledListItem", "DirectLabel":"from direct.gui.DirectLabel import DirectLabel", "DirectWaitBar":"from direct.gui.DirectWaitBar import DirectWaitBar", "OkDialog":"from direct.gui.DirectDialog import OkDialog", "OkCancelDialog":"from direct.gui.DirectDialog import OkCancelDialog", "YesNoDialog":"from direct.gui.DirectDialog import YesNoDialog", "YesNoCancelDialog":"from direct.gui.DirectDialog import YesNoCancelDialog", "RetryCancelDialog":"from direct.gui.DirectDialog import RetryCancelDialog", "DirectFrame":"from direct.gui.DirectFrame import DirectFrame", "DirectScrolledFrame":"from direct.gui.DirectScrolledFrame import DirectScrolledFrame", } self.content = """#!/usr/bin/python # -*- coding: utf-8 -*- # This file was created using the DirectGUI Designer from direct.gui import DirectGuiGlobals as DGG """ usedImports = [] for name, elementInfo in self.guiElementsDict.items(): if elementInfo.type not in usedImports: if elementInfo.type in importStatements: self.content = "{}\n{}".format(self.content, importStatements[elementInfo.type]) else: self.content = "{}\n{}".format(self.content, elementInfo.customImportPath) usedImports.append(elementInfo.type) self.content += """ from panda3d.core import ( LPoint3f, LVecBase3f, LVecBase4f, TextNode )""" if ConfigVariableBool("create-executable-scripts", False).getValue(): self.content += """ # We need showbase to make this script directly runnable from direct.showbase.ShowBase import ShowBase""" self.content += """ class GUI: def __init__(self, rootParent=None): """ #self.__createStructuredElements("root", visualEditor.getCanvas()) for name, elementInfo in self.jsonElements.items(): self.content += self.__createElement(name, elementInfo) self.content += "\n" for line in self.postSetupCalling: self.content += line + "\n" for radioButton, others in self.radiobuttonDict.items(): self.content += " "*8 + "{}.setOthers([".format(radioButton) for other in others: self.content += other + "," self.content += "])\n" topLevelItems = [] for name, elementInfo in self.jsonElements.items(): widget = self.customWidgetHandler.getWidget(elementInfo["type"]) if widget is not None: if name not in self.customWidgetAddDict: continue for element in self.customWidgetAddDict[name]: if widget.addItemFunction is not None: self.content += " "*8 + "self.{}.{}({})\n".format(name, widget.addItemFunction, element) if elementInfo["parent"] == "root": topLevelItems.append(name) # Create helper functions for toplevel elements if len(topLevelItems) > 0: self.content += "\n" self.content += " "*4 + "def show(self):\n" for name in topLevelItems: self.content += " "*8 + "self.{}.show()\n".format(name) self.content += "\n" self.content += " "*4 + "def hide(self):\n" for name in topLevelItems: self.content += " "*8 + "self.{}.hide()\n".format(name) self.content += "\n" self.content += " "*4 + "def destroy(self):\n" for name in topLevelItems: self.content += " "*8 + "self.{}.destroy()\n".format(name) # Make script executable if desired if ConfigVariableBool("create-executable-scripts", False).getValue(): self.content += """ # Create a ShowBase instance to make this gui directly runnable app = ShowBase()\n""" if usePixel2D: self.content += "GUI(app.pixel2d)\n" else: self.content += "GUI()\n" self.content += "app.run()\n" self.dlgPathSelect = PathSelect( self.save, "Save Python File", "Save file path", "Save", saveFile, tooltip) def save(self, doSave): if doSave: self.dlgOverwrite = None self.dlgOverwriteShadow = None path = self.dlgPathSelect.getPath() path = os.path.expanduser(path) path = os.path.expandvars(path) if os.path.exists(path): self.dlgOverwrite = YesNoDialog( text="File already Exist.\nOverwrite?", relief=DGG.RIDGE, frameColor=(1,1,1,1), frameSize=(-0.5,0.5,-0.3,0.2), sortOrder=1, button_relief=DGG.FLAT, button_frameColor=(0.8, 0.8, 0.8, 1), command=self.__executeSave, extraArgs=[path], scale=300, pos=(base.getSize()[0]/2, 0, -base.getSize()[1]/2), parent=base.pixel2d) self.dlgOverwriteShadow = DirectFrame( pos=(base.getSize()[0]/2 + 10, 0, -base.getSize()[1]/2 - 10), sortOrder=0, frameColor=(0,0,0,0.5), frameSize=self.dlgOverwrite.bounds, scale=300, parent=base.pixel2d) else: self.__executeSave(True, path) base.messenger.send("setLastPath", [path]) self.dlgPathSelect.destroy() del self.dlgPathSelect def __executeSave(self, overwrite, path): if self.dlgOverwrite is not None: self.dlgOverwrite.destroy() if self.dlgOverwriteShadow is not None: self.dlgOverwriteShadow.destroy() if not overwrite: return with open(path, 'w') as outfile: outfile.write(self.content) def __createElement(self, name, elementInfo): extraOptions = "" for optionName, optionValue in elementInfo["extraOptions"].items(): extraOptions += " "*12 + "{}={},\n".format(optionName, optionValue) elementCode = """ self.{} = {}( {}{}{}{} )\n""".format( name, elementInfo["type"], self.__writeElementOptions(name, elementInfo), " "*12 + "command={},\n".format(elementInfo["command"]) if elementInfo["command"] is not None else "", " "*12 + "extraArgs=[{}],\n".format(elementInfo["extraArgs"]) if elementInfo["extraArgs"] is not None else "", extraOptions, ) if elementInfo["element"]["transparency"] != "M_none": elementCode += " "*8 +"self.{}.setTransparency({})\n".format(name, elementInfo["element"]["transparency"]) if elementInfo["type"] == "DirectScrolledListItem": self.postSetupCalling.append(" "*8 + "self.{}.addItem(self.{})".format(elementInfo["parent"], name)) return elementCode def __writeElementOptions(self, name, elementInfo): elementOptions = "" indent = " "*12 if elementInfo["type"] == "DirectOptionMenu": elementOptions += indent + "items=['item1'],\n" for optionKey, optionValue in elementInfo["element"].items(): if optionKey == "others": others = [] for other in optionValue: others.append("self.{}".format(other)) self.radiobuttonDict["self.{}".format(name)] = others continue elif optionKey == "transparency": continue elementOptions += indent + optionKey + "=" + optionValue + ",\n" if elementInfo["parent"] != "root": self.canvasParents = [ "a2dTopCenter","a2dBottomCenter","a2dLeftCenter","a2dRightCenter", "a2dTopLeft","a2dTopRight","a2dBottomLeft","a2dBottomRight"] if elementInfo["parent"] in self.jsonElements and self.jsonElements[elementInfo["parent"]]["type"] == "DirectScrollFrame": # use the canvas as parent elementOptions += indent + "parent=self." + elementInfo["parent"] + ".getCanvas(),\n" elif elementInfo["parent"] in self.jsonElements and self.customWidgetHandler.getWidget(self.jsonElements[elementInfo["parent"]]["type"]) is not None: widget = self.customWidgetHandler.getWidget(self.jsonElements[elementInfo["parent"]]["type"]) if widget.addItemFunction is not None: if elementInfo["parent"] in self.customWidgetAddDict: self.customWidgetAddDict[elementInfo["parent"]].append("self.{}".format(name)) else: self.customWidgetAddDict[elementInfo["parent"]] = ["self.{}".format(name)] elif elementInfo["parent"] in self.canvasParents: elementOptions += indent + "parent=base." + elementInfo["parent"] + ",\n" else: elementOptions += indent + "parent=self." + elementInfo["parent"] + ",\n" else: # use the parent passed to the class elementOptions += indent + "parent=rootParent,\n" return elementOptions
class GameScreenHandler(DirectObject, GameScreen): def __init__(self): GameScreen.__init__(self) self.btnContinue.hide() self.mainChar = Character(self.frmContent.getCanvas(), (0,0,0), "mainChar", "mike") self.mainChar.animate("idle", "l", 3) self.mainChar.btn.reparentTo(self.frmContent.getCanvas(), 100) self.chapter = None self.inventory = Inventory(self.frmInventory) self.accept("quitGame", self.askQuit) self.accept("toggleAudio", self.toggleAudio) self.accept("switchToChapter", self.switchToChapter) self.accept("showText", self.showText) self.accept("showNote", self.showNote) self.accept("addInventory", self.addInventory) self.accept("getInventory", self.getInventory) self.accept("moveChar", self.mainChar.moveTo) self.accept("stopChar", self.mainChar.stop) self.accept("animateChar", self.mainChar.animate) if base.AppHasAudioFocus: self.btnAudioToggle["text"] = "Audio On" else: self.btnAudioToggle["text"] = "Audio Off" self.chapter = levelTree["chapter1"](self.frmContent.getCanvas()) self.mainChar.btn.setPos(self.chapter.startPos) LerpColorInterval(self.frmFadeOverlay, 2.0, (0,0,0,0)).start() def askQuit(self): self.yesNoDialog = YesNoDialog( text="Realy Quit?", command=self.quitGame) def quitGame(self, yes): self.yesNoDialog.destroy() if yes: self.ignoreAll() self.mainChar.stop() self.mainChar.destroy() self.chapter.destroy() base.messenger.send("exit") def toggleAudio(self): if base.AppHasAudioFocus: base.disableAllAudio() self.btnAudioToggle["text"] = "Audio Off" else: base.enableAllAudio() self.btnAudioToggle["text"] = "Audio On" def setChapter(self, chapterName): if self.chapter is not None: del self.chapter self.chapter = None self.chapter = levelTree[chapterName](self.frmContent.getCanvas()) def switchToChapter(self, chapterName): switchTo = Sequence( LerpColorInterval(self.frmFadeOverlay, 2.0, (0,0,0,1), (0,0,0,0)), Func(self.chapter.destroy), Func(self.setChapter, chapterName), Func(self.setStarPos), LerpColorInterval(self.frmFadeOverlay, 2.0, (0,0,0,0)), ) switchTo.start() def setStarPos(self): self.mainChar.setStart(self.chapter.startPos) def showNote(self, text): self.lblStory["text"] = text base.messenger.send("continue") def showText(self, textQueue): self.btnContinue.show() self.textQueue = textQueue self.accept("story_continue", self.nextText) self.nextText() def nextText(self): if len(self.textQueue) <= 0: base.messenger.send("continue") self.ignore("story_continue") self.lblStory["text"] = "" self.btnContinue.hide() return text = self.textQueue[0] self.lblStory["text"] = text del self.textQueue[0] def addInventory(self, itemKey, itemImage): self.inventory.addItem(itemKey, itemImage) def getInventory(self): base.messenger.send("inventoryRequest", [self.inventory.inventoryList])