def downloadNextFile(self, task): while self.nextNewsFile < len(self.newsFiles) and 'aaver' in self.newsFiles[self.nextNewsFile]: self.nextNewsFile += 1 if self.nextNewsFile >= len(self.newsFiles): self.notify.info('Done downloading news.') self.percentDownloaded = 1 del self.newsFiles del self.nextNewsFile del self.newsUrl del self.newsDir del self.ch del self.url if hasattr(self, 'filename'): del self.filename self.redownloadingNews = False if self.active: self.parseNewsContent() return task.done self.percentDownloaded = float(self.nextNewsFile) / float(len(self.newsFiles)) self.filename = self.newsFiles[self.nextNewsFile] self.nextNewsFile += 1 self.url = self.newsUrl + self.filename localFilename = Filename(self.newsDir, self.filename) self.notify.info('testing for %s' % localFilename.getFullpath()) doc = DocumentSpec(self.url) if self.filename in self.newsCache: size, date = self.newsCache[self.filename] if date and localFilename.exists() and (size == 0 or localFilename.getFileSize() == size): doc.setDate(date) doc.setRequestMode(doc.RMNewer) self.ch.beginGetDocument(doc) self.ch.downloadToFile(localFilename) taskMgr.remove(self.RedownloadTaskName) taskMgr.add(self.downloadCurrentFileTask, self.RedownloadTaskName)
def downloadNextFile(self, task): while self.nextNewsFile < len(self.newsFiles) and "aaver" in self.newsFiles[self.nextNewsFile]: self.nextNewsFile += 1 if self.nextNewsFile >= len(self.newsFiles): self.notify.info("Done downloading news.") self.percentDownloaded = 1 del self.newsFiles del self.nextNewsFile del self.newsUrl del self.newsDir del self.ch del self.url if hasattr(self, "filename"): del self.filename self.redownloadingNews = False if self.active: self.parseNewsContent() return task.done self.percentDownloaded = float(self.nextNewsFile) / float(len(self.newsFiles)) self.filename = self.newsFiles[self.nextNewsFile] self.nextNewsFile += 1 self.url = self.newsUrl + self.filename localFilename = Filename(self.newsDir, self.filename) self.notify.info("testing for %s" % localFilename.getFullpath()) doc = DocumentSpec(self.url) if self.filename in self.newsCache: size, date = self.newsCache[self.filename] if date and localFilename.exists() and (size == 0 or localFilename.getFileSize() == size): doc.setDate(date) doc.setRequestMode(doc.RMNewer) self.ch.beginGetDocument(doc) self.ch.downloadToFile(localFilename) taskMgr.remove(self.RedownloadTaskName) taskMgr.add(self.downloadCurrentFileTask, self.RedownloadTaskName)
def getResourceFullPath(self, filename): vfs = VirtualFileSystem.getGlobalPtr() resFile = Filename(filename) if vfs.exists(resFile): searchPath = DSearchPath() searchPath.appendDirectory(self.mountPoint) # if the filename was resolved, resFile is updated to include the full path if vfs.resolveFilename(resFile, searchPath): return resFile.getFullpath()
class EditorApp(AppShell): appversion = "cvs" appname = "Panda Editor" copyright = "Copyright (c) Carnegie Mellon University.\nAll rights reserved." contactname = "pro-rsoft" contactemail = "*****@*****.**" frameWidth = defWP.getXSize() frameHeight = defWP.getYSize() def __init__(self, editorInstance): """EditorApp constructor.""" # Instance of the editor self.editorInstance = editorInstance # Create the Wx app self.wxApp = wx.App(redirect = False) self.wxApp.SetAppName("Panda Editor") self.wxApp.SetClassName("PEditor") self.modified = True self.filename = Filename() # Initialize the app shell and add some controls AppShell.__init__(self, title = "Panda Editor", pos = origin) self.splitter1 = wx.SplitterWindow(self, style = wx.SP_3D | wx.SP_BORDER) self.splitter1.SetMinimumPaneSize(1) self.splitter2 = wx.SplitterWindow(self.splitter1, style = wx.SP_3D | wx.SP_BORDER) self.splitter2.SetMinimumPaneSize(1) self.leftBarSplitter = wx.SplitterWindow(self.splitter2, style = wx.SP_3D | wx.SP_BORDER) self.leftBarSplitter.SetMinimumPaneSize(1) #self.rightBarSplitter = wx.SplitterWindow(self.splitter1, style = wx.SP_3D | wx.SP_BORDER) #self.rightBarSplitter.SetMinimumPaneSize(1) self.sceneGraphTree = SceneGraphTree(self.leftBarSplitter) self.propertyGrid = PropertyGrid(self.leftBarSplitter) self.textureManager = TextureManager(self.splitter1, style = wx.SP_3D | wx.SUNKEN_BORDER) self.view = Viewport.makePerspective(self.splitter2) sizer = wx.BoxSizer(wx.VERTICAL) assert self.leftBarSplitter.SplitHorizontally(self.sceneGraphTree, self.propertyGrid) assert self.splitter2.SplitVertically(self.leftBarSplitter, self.view, 200) #assert self.rightBarSplitter.SplitHorizontally(self.textureManager, None) assert self.splitter1.SplitVertically(self.splitter2, self.textureManager, -200) sizer.Add(self.splitter1, 1, wx.EXPAND, 0) self.splitter1.Unsplit() # Yes, I know this looks odd. self.SetSizer(sizer); self.Layout() self.initialize() self.splitter2.SetSashPosition(200) # Setup some events base.accept("c", self.onCenterTrackball) base.accept(EVENT_MODELCONTROLLER_SELECTED_OBJECT_CHANGE, self.onModelSelect) # If a model-translate-rotate-scale tool is selected the automatic mouse # movement has to be disable to prevent camera & object movement. # Hmm doesnt really work as well... (camera is still moved) base.accept(EVENT_MODELCONTROLLER_EDITTOOL_SELECTED, lambda x=None:base.disableMouse()) base.accept(EVENT_MODELCONTROLLER_EDITTOOL_DESELECTED, lambda x=None:base.enableMouse()) base.accept(EVENT_MODELCONTROLLER_FULL_REFRESH, self.__setattr__, ["modified", True]) # The object has been modified in the scene, this event happens every frame #base.accept(EVENT_MODELCONTROLLER_FAST_REFRESH, ) # The editor has been disabled, collisions etc are deleted #base.accept(EDITOR_TOGGLE_OFF_EVENT, ) # The editor has been enabled, collisions etc are created. # This event happens shortly after the wxgui has been created #base.accept(EDITOR_TOGGLE_ON_EVENT, ) def appInit(self): print "I: EditorApp.appInit" """Overridden from WxAppShell.py.""" # Create a new event loop (to overide default wxEventLoop) self.evtLoop = wx.EventLoop() self.oldLoop = wx.EventLoop.GetActive() wx.EventLoop.SetActive(self.evtLoop) taskMgr.add(self.wxStep, "evtLoopTask") def createMenuBar(self): """Overridden from WxAppShell.py.""" # File menu self.menuFile = wx.Menu() self.menuBar.Append(self.menuFile, "&File") self.Bind(wx.EVT_MENU, self.onNew, self.menuFile.Append(wx.ID_NEW, "&New")) self.Bind(wx.EVT_MENU, self.onOpen, self.menuFile.Append(wx.ID_OPEN, "&Open")) self.Bind(wx.EVT_MENU, self.onSave, self.menuFile.Append(wx.ID_SAVE, "&Save")) self.Bind(wx.EVT_MENU, self.onSaveAs, self.menuFile.Append(wx.ID_SAVEAS, "Save &As...")) self.menuFile.AppendSeparator() self.Bind(wx.EVT_MENU, self.quit, self.menuFile.Append(wx.ID_EXIT, "&Quit")) # Edit menu #self.menuEdit = wx.Menu() #self.menuBar.Append(self.menuEdit, "&Edit") #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_UNDO, "&Undo")) #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_REDO, "&Redo")) #self.menuEdit.AppendSeparator() #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_CUT, "Cu&t")) #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_COPY, "&Copy")) #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_PASTE, "&Paste")) #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_DELETE, "&Delete")) #self.menuEdit.AppendSeparator() #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_SELECTALL, "Select &All")) #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_ANY, "Select &None")) # View menu self.menuView = wx.Menu() self.menuBar.Append(self.menuView, "&View") self.Bind(wx.EVT_MENU, self.onToggleGrid, self.menuView.AppendCheckItem(ID_ENABLE_GRID, "E&nable Grid")) self.Bind(wx.EVT_MENU, self.onCenterTrackball, self.menuView.Append(wx.ID_ANY, "&Center Model")) self.menuBar.Check(ID_ENABLE_GRID, True) # Create menu self.menuCreate = wx.Menu() self.menuBar.Append(self.menuCreate, "&Create") self.Bind(wx.EVT_MENU, self.onCreateObject, self.menuCreate.Append(ID_MODEL, "&Model...")) self.Bind(wx.EVT_MENU, self.onCreateObject, self.menuCreate.Append(ID_TERRAIN, "&Terrain...")) self.menuCreateLight = wx.Menu() self.Bind(wx.EVT_MENU, self.onCreateObject, self.menuCreateLight.Append(ID_AMBIENT, "&Ambient")) self.Bind(wx.EVT_MENU, self.onCreateObject, self.menuCreateLight.Append(ID_DIRECTIONAL, "&Directional")) self.Bind(wx.EVT_MENU, self.onCreateObject, self.menuCreateLight.Append(ID_POINT, "&Point")) self.Bind(wx.EVT_MENU, self.onCreateObject, self.menuCreateLight.Append(ID_SPOT, "&Spotlight")) self.menuCreate.AppendSubMenu(self.menuCreateLight, "&Light") # Viewports menu self.menuViewports = wx.Menu() self.menuBar.Append(self.menuViewports, "View&ports") self.Bind(wx.EVT_MENU, self.onChangeViewports, self.menuViewports.AppendRadioItem(ID_SINGLE_VIEWPORT, "&Single Viewport")) self.Bind(wx.EVT_MENU, self.onChangeViewports, self.menuViewports.AppendRadioItem(ID_4x4_GRID, "4x4 &Grid")) self.Bind(wx.EVT_MENU, self.onChangeViewports, self.menuViewports.AppendRadioItem(ID_2_HORIZONTAL, "2 &Horizontal")) self.Bind(wx.EVT_MENU, self.onChangeViewports, self.menuViewports.AppendRadioItem(ID_2_VERTICAL, "2 &Vertical")) self.menuBar.Check(ID_SINGLE_VIEWPORT, True) self.menuViewports.AppendSeparator() self.viewportMenus = [] def createInterface(self): """Overridden from WxAppShell.py.""" self.CreateStatusBar() self.SetStatusText("Welcome to the Panda3D Editor") self.Update() def initialize(self): """Initializes the viewports and editor.""" print "I: EditorApp.initialize" self.Update() ViewportManager.updateAll() self.wxStep() ViewportManager.initializeAll() self.reloadViewportMenus() #self.editorInstance.toggle("WorldEditMode") # Position the camera if base.trackball != None: base.trackball.node().setPos(0, 30, 0) base.trackball.node().setHpr(0, 15, 0) # Load the direct things self.grid = DirectGrid(parent = render) self.sceneGraphTree.reload() if not isinstance(self.view, Viewport): self.view.center() # Initialize some stuff self.editorInstance.toggleEditmode(True) def reloadViewportMenus(self): """Reloads the viewport menus.""" # Add the individual viewport menus for m in self.viewportMenus: m.Destroy() self.viewportMenus = [] collect() #for v in range(len(ViewportManager.viewports)): # self.viewportMenus.append(self.menuViewports.AppendSubMenu(ViewportMenu(ViewportManager.viewports[v]), "Viewport %d" % (v + 1))) def wxStep(self, task = None): """A step in the WX event loop. You can either call this yourself or use as task.""" while self.evtLoop.Pending(): self.evtLoop.Dispatch() self.wxApp.ProcessIdle() if task != None: return task.cont def onModelSelect(self, model): """Invoked when a model is selected. Shows/hides the texture panel.""" if model == None and self.splitter1.IsSplit(): self.splitter1.Unsplit() elif model != None and not self.splitter1.IsSplit(): assert self.splitter1.SplitVertically(self.splitter2, self.textureManager, -200) def onDestroy(self, evt): """Invoked when the window is destroyed.""" wx.EventLoop.SetActive(self.oldLoop) def onNew(self, evt = None): self.filename = Filename() self.modified = True self.SetTitle("Panda Editor") self.editorInstance.destroyAllModels() def onOpen(self, evt = None): filter = "Panda3D Egg Scene Format (*.egs)|*.[eE][gG][sS];*.egs" #filter += "|Panda3D Compressed Egg Format (*.egg.pz)|*.[eE][gG][gG].[pP][zZ];*.egg.pz" #filter += "|Panda3D Binary Format (*.bam)|*.[bB][aA][mM];*.bam" #filter += "|Panda3D Compressed Binary Format (*.bam)|*.[bB][aA][mM].[pP][zZ];*.bam.pz" ''' # disabled by hypnos, making the loading work filter += "|MultiGen (*.flt)|*.[fF][lL][tT]" filter += "|Lightwave (*.lwo)|*.[lL][wW][oO]" filter += "|AutoCAD (*.dxf)|*.[dD][xX][fF]" filter += "|VRML (*.wrl)|*.[wW][rR][lL]" filter += "|DirectX (*.x)|*.[xX]" filter += "|COLLADA (*.dae)|*.[dD][aA][eE]" ''' dlg = wx.FileDialog(self, "Load file", "", "", filter, wx.OPEN) try: if dlg.ShowModal() == wx.ID_OK: #self.filename = Filename.fromOsSpecific(dlg.GetPath()) p3dFilename = Filename.fromOsSpecific(dlg.GetPath()) self.filename = str(dlg.GetPath()) self.SetTitle(p3dFilename.getBasename() + " - Panda Editor") self.modified = False self.editorInstance.loadEggModelsFile( self.filename ) # Reset the camera if base.trackball != None: base.trackball.node().setPos(0, 30, 0) base.trackball.node().setHpr(0, 15, 0) self.onCenterTrackball() if p3dFilename.getExtension().lower() != "bam": self.filename = Filename() self.modified = True self.sceneGraphTree.reload() finally: dlg.Destroy() def onSave(self, evt = None): if not self.modified: return if self.filename == None or self.filename.empty(): self.onSaveAs(evt) else: dlg = wx.FileDialog(self, "Save file", "", "", "Panda3D Binary Format (*.bam)|.[bB][aA][mM];*.bam", wx.SAVE | wx.FD_OVERWRITE_PROMPT) try: if dlg.ShowModal() == wx.ID_OK: self.filename = Filename.fromOsSpecific(dlg.GetPath()) self.SetTitle(self.filename.getBasename() + " - Panda Editor") self.modified = False self.editorInstance.saveEggModelsFile(self.filename.getFullpath()) finally: dlg.Destroy() def onSaveAs(self, evt = None): dlg = wx.FileDialog(self, "Save file as", "", "", "Panda3D Binary Format (*.bam)|.[bB][aA][mM];*.bam", wx.SAVE | wx.FD_OVERWRITE_PROMPT) try: if dlg.ShowModal() == wx.ID_OK: self.onNew() self.filename = Filename.fromOsSpecific(dlg.GetPath()) self.SetTitle(self.filename.getBasename() + " - Panda Editor") self.modified = False self.editorInstance.saveEggModelsFile(self.filename.getFullpath()) finally: dlg.Destroy() def onCreateObject(self, e): """Invoked when the user hits one of the buttons in the "Create" menu.""" modelParent = modelController.getSelectedObject() if modelParent == None: modelParent = render objectInstance = None if e.Id == ID_NODEPATH: objectInstance = NodePathWrapper.onCreateInstance(modelParent) elif e.Id == ID_MODEL: filter = "Panda3D Egg Format (*.egg)|*.[eE][gG][gG];*.egg" filter += "|Panda3D Binary Format (*.bam)|*.[bB][aA][mM];*.bam" filter += "|MultiGen (*.flt)|*.[fF][lL][tT];*.flt" filter += "|Lightwave (*.lwo)|*.[lL][wW][oO];*.lwo" filter += "|AutoCAD (*.dxf)|*.[dD][xX][fF];*.dxf" filter += "|VRML (*.wrl)|*.[wW][rR][lL];*.wrl" filter += "|DirectX (*.x)|*.[xX];*.x" filter += "|COLLADA (*.dae)|*.[dD][aA][eE];*.dae" dlg = wx.FileDialog(self, "Select model", "", "", filter, wx.OPEN) try: if dlg.ShowModal() == wx.ID_OK: objectInstance = NodePathWrapper.onCreateInstance(modelParent, Filename.fromOsSpecific(dlg.GetPath()).getFullpath()) finally: dlg.Destroy() elif e.Id == ID_TERRAIN: filter = "Portable Network Graphics (*.png)|*.[pP][nN][gG];*.png" dlg = wx.FileDialog(self, "Select heightfield", "", "", filter, wx.OPEN) try: if dlg.ShowModal() == wx.ID_OK: objectInstance = GeoMipTerrainNodeWrapper.onCreateInstance(modelParent, Filename.fromOsSpecific(dlg.GetPath()).getFullpath()) finally: dlg.Destroy() elif e.Id == ID_AMBIENT: objectInstance = AmbientLightNodeWrapper.onCreateInstance(modelParent) elif e.Id == ID_DIRECTIONAL: objectInstance = DirectionalLightNodeWrapper.onCreateInstance(modelParent) elif e.Id == ID_POINT: objectInstance = PointLightNodeWrapper.onCreateInstance(modelParent) elif e.Id == ID_SPOT: objectInstance = SpotLightNodeWrapper.onCreateInstance(modelParent) if objectInstance != None: objectInstance.reparentTo(modelParent) objectInstance.enableEditmode() modelController.selectObject(objectInstance) messenger.send(EVENT_SCENEGRAPH_REFRESH) def onChangeViewports(self, e): """Invoked when the user changes viewport layout.""" self.Update() sashpos = self.splitter2.GetSashPosition() if e.Id == ID_SINGLE_VIEWPORT: if isinstance(self.view, Viewport): return self.view.close() self.view = Viewport.makePerspective(self.splitter2) elif e.Id == ID_4x4_GRID: if isinstance(self.view, ViewportGrid): return self.view.close() self.view = ViewportGrid(self.splitter2, [[Viewport.VPTOP, Viewport.VPFRONT], [Viewport.VPLEFT, Viewport.VPPERSPECTIVE]]) self.view.center() else: if e.Id == ID_2_HORIZONTAL: orientation = wx.SPLIT_HORIZONTAL elif e.Id == ID_2_VERTICAL: orientation = wx.SPLIT_VERTICAL else: return if isinstance(self.view, ViewportSplitter) and not isinstance(self.view, ViewportGrid): if self.view.GetSplitMode() == orientation: return self.view.close() self.view.split(Viewport.VPTOP, Viewport.VPPERSPECTIVE, orientation) else: self.view.close() self.view = ViewportSplitter(self.splitter2, Viewport.VPTOP, Viewport.VPPERSPECTIVE, orientation) self.splitter2.Unsplit() assert self.splitter2.SplitVertically(self.leftBarSplitter, self.view, sashpos) # Reload the menus collect() self.reloadViewportMenus() # Make sure the viewports are initialized correctly self.Update() ViewportManager.updateAll() self.wxStep() ViewportManager.initializeAll() messenger.send("window-event") def onToggleGrid(self, evt = None): """Toggles the grid on/off.""" if evt.GetEventObject().IsChecked(ID_ENABLE_GRID): self.grid.enable() else: self.grid.disable() def onCenterTrackball(self, evt = None): """Center the trackball, like 'c' does in pview.""" gbv = render.getBounds(); # Determine the bounding sphere around the object. if gbv.isInfinite(): return if gbv.isEmpty(): return # The BoundingVolume might be a sphere (it's likely), but since it # might not, we'll take no chances and make our own sphere. sphere = BoundingSphere(gbv.getApproxCenter(), 0.0) if (not sphere.extendBy(gbv)): return radius = 50.0 # Loop through the windows/viewports for w in WindowManager.windows: # Choose a suitable distance to view the whole volume in our frame. # This is based on the camera lens in use. fov = w.camLens.getFov(); distance = radius / tan(deg2Rad(min(fov[0], fov[1]) / 2.0)); # Ensure the far plane is far enough back to see the entire object. idealFarPlane = distance + radius * 1.5; w.camLens.setFar(max(w.camLens.getDefaultFar(), idealFarPlane)); # And that the near plane is far enough forward. w.camLens.setNear(min(w.camLens.getDefaultNear(), radius - sphere.getRadius())) w.trackball.node().setOrigin(sphere.getCenter()) w.trackball.node().setPos(Vec3.forward() * distance) # Also set the movement scale on the trackball to be consistent # with the size of the model and the lens field-of-view. w.trackball.node().setForwardScale(distance * 0.006)
class EditorApp(AppShell): appversion = "cvs" appname = "Panda Editor" copyright = "Copyright (c) Carnegie Mellon University.\nAll rights reserved." contactname = "pro-rsoft" contactemail = "*****@*****.**" frameWidth = defWP.getXSize() frameHeight = defWP.getYSize() def __init__(self, editorInstance): """EditorApp constructor.""" # Instance of the editor self.editorInstance = editorInstance # Create the Wx app self.wxApp = wx.App(redirect=False) self.wxApp.SetAppName("Panda Editor") self.wxApp.SetClassName("PEditor") self.modified = True self.filename = Filename() # Initialize the app shell and add some controls AppShell.__init__(self, title="Panda Editor", pos=origin) self.splitter1 = wx.SplitterWindow(self, style=wx.SP_3D | wx.SP_BORDER) self.splitter1.SetMinimumPaneSize(1) self.splitter2 = wx.SplitterWindow(self.splitter1, style=wx.SP_3D | wx.SP_BORDER) self.splitter2.SetMinimumPaneSize(1) self.leftBarSplitter = wx.SplitterWindow(self.splitter2, style=wx.SP_3D | wx.SP_BORDER) self.leftBarSplitter.SetMinimumPaneSize(1) #self.rightBarSplitter = wx.SplitterWindow(self.splitter1, style = wx.SP_3D | wx.SP_BORDER) #self.rightBarSplitter.SetMinimumPaneSize(1) self.sceneGraphTree = SceneGraphTree(self.leftBarSplitter) self.propertyGrid = PropertyGrid(self.leftBarSplitter) self.textureManager = TextureManager(self.splitter1, style=wx.SP_3D | wx.SUNKEN_BORDER) self.view = Viewport.makePerspective(self.splitter2) sizer = wx.BoxSizer(wx.VERTICAL) assert self.leftBarSplitter.SplitHorizontally(self.sceneGraphTree, self.propertyGrid) assert self.splitter2.SplitVertically(self.leftBarSplitter, self.view, 200) #assert self.rightBarSplitter.SplitHorizontally(self.textureManager, None) assert self.splitter1.SplitVertically(self.splitter2, self.textureManager, -200) sizer.Add(self.splitter1, 1, wx.EXPAND, 0) self.splitter1.Unsplit() # Yes, I know this looks odd. self.SetSizer(sizer) self.Layout() self.initialize() self.splitter2.SetSashPosition(200) # Setup some events base.accept("c", self.onCenterTrackball) base.accept(EVENT_MODELCONTROLLER_SELECTED_OBJECT_CHANGE, self.onModelSelect) # If a model-translate-rotate-scale tool is selected the automatic mouse # movement has to be disable to prevent camera & object movement. # Hmm doesnt really work as well... (camera is still moved) base.accept(EVENT_MODELCONTROLLER_EDITTOOL_SELECTED, lambda x=None: base.disableMouse()) base.accept(EVENT_MODELCONTROLLER_EDITTOOL_DESELECTED, lambda x=None: base.enableMouse()) base.accept(EVENT_MODELCONTROLLER_FULL_REFRESH, self.__setattr__, ["modified", True]) # The object has been modified in the scene, this event happens every frame #base.accept(EVENT_MODELCONTROLLER_FAST_REFRESH, ) # The editor has been disabled, collisions etc are deleted #base.accept(EDITOR_TOGGLE_OFF_EVENT, ) # The editor has been enabled, collisions etc are created. # This event happens shortly after the wxgui has been created #base.accept(EDITOR_TOGGLE_ON_EVENT, ) def appInit(self): print "I: EditorApp.appInit" """Overridden from WxAppShell.py.""" # Create a new event loop (to overide default wxEventLoop) self.evtLoop = wx.EventLoop() self.oldLoop = wx.EventLoop.GetActive() wx.EventLoop.SetActive(self.evtLoop) taskMgr.add(self.wxStep, "evtLoopTask") def createMenuBar(self): """Overridden from WxAppShell.py.""" # File menu self.menuFile = wx.Menu() self.menuBar.Append(self.menuFile, "&File") self.Bind(wx.EVT_MENU, self.onNew, self.menuFile.Append(wx.ID_NEW, "&New")) self.Bind(wx.EVT_MENU, self.onOpen, self.menuFile.Append(wx.ID_OPEN, "&Open")) self.Bind(wx.EVT_MENU, self.onSave, self.menuFile.Append(wx.ID_SAVE, "&Save")) self.Bind(wx.EVT_MENU, self.onSaveAs, self.menuFile.Append(wx.ID_SAVEAS, "Save &As...")) self.menuFile.AppendSeparator() self.Bind(wx.EVT_MENU, self.quit, self.menuFile.Append(wx.ID_EXIT, "&Quit")) # Edit menu #self.menuEdit = wx.Menu() #self.menuBar.Append(self.menuEdit, "&Edit") #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_UNDO, "&Undo")) #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_REDO, "&Redo")) #self.menuEdit.AppendSeparator() #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_CUT, "Cu&t")) #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_COPY, "&Copy")) #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_PASTE, "&Paste")) #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_DELETE, "&Delete")) #self.menuEdit.AppendSeparator() #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_SELECTALL, "Select &All")) #self.Bind(wx.EVT_MENU, self.quit, self.menuEdit.Append(wx.ID_ANY, "Select &None")) # View menu self.menuView = wx.Menu() self.menuBar.Append(self.menuView, "&View") self.Bind( wx.EVT_MENU, self.onToggleGrid, self.menuView.AppendCheckItem(ID_ENABLE_GRID, "E&nable Grid")) self.Bind(wx.EVT_MENU, self.onCenterTrackball, self.menuView.Append(wx.ID_ANY, "&Center Model")) self.menuBar.Check(ID_ENABLE_GRID, True) # Create menu self.menuCreate = wx.Menu() self.menuBar.Append(self.menuCreate, "&Create") self.Bind(wx.EVT_MENU, self.onCreateObject, self.menuCreate.Append(ID_MODEL, "&Model...")) self.Bind(wx.EVT_MENU, self.onCreateObject, self.menuCreate.Append(ID_TERRAIN, "&Terrain...")) self.menuCreateLight = wx.Menu() self.Bind(wx.EVT_MENU, self.onCreateObject, self.menuCreateLight.Append(ID_AMBIENT, "&Ambient")) self.Bind(wx.EVT_MENU, self.onCreateObject, self.menuCreateLight.Append(ID_DIRECTIONAL, "&Directional")) self.Bind(wx.EVT_MENU, self.onCreateObject, self.menuCreateLight.Append(ID_POINT, "&Point")) self.Bind(wx.EVT_MENU, self.onCreateObject, self.menuCreateLight.Append(ID_SPOT, "&Spotlight")) self.menuCreate.AppendSubMenu(self.menuCreateLight, "&Light") # Viewports menu self.menuViewports = wx.Menu() self.menuBar.Append(self.menuViewports, "View&ports") self.Bind( wx.EVT_MENU, self.onChangeViewports, self.menuViewports.AppendRadioItem(ID_SINGLE_VIEWPORT, "&Single Viewport")) self.Bind(wx.EVT_MENU, self.onChangeViewports, self.menuViewports.AppendRadioItem(ID_4x4_GRID, "4x4 &Grid")) self.Bind( wx.EVT_MENU, self.onChangeViewports, self.menuViewports.AppendRadioItem(ID_2_HORIZONTAL, "2 &Horizontal")) self.Bind( wx.EVT_MENU, self.onChangeViewports, self.menuViewports.AppendRadioItem(ID_2_VERTICAL, "2 &Vertical")) self.menuBar.Check(ID_SINGLE_VIEWPORT, True) self.menuViewports.AppendSeparator() self.viewportMenus = [] def createInterface(self): """Overridden from WxAppShell.py.""" self.CreateStatusBar() self.SetStatusText("Welcome to the Panda3D Editor") self.Update() def initialize(self): """Initializes the viewports and editor.""" print "I: EditorApp.initialize" self.Update() ViewportManager.updateAll() self.wxStep() ViewportManager.initializeAll() self.reloadViewportMenus() #self.editorInstance.toggle("WorldEditMode") # Position the camera if base.trackball != None: base.trackball.node().setPos(0, 30, 0) base.trackball.node().setHpr(0, 15, 0) # Load the direct things self.grid = DirectGrid(parent=render) self.sceneGraphTree.reload() if not isinstance(self.view, Viewport): self.view.center() # Initialize some stuff self.editorInstance.toggleEditmode(True) def reloadViewportMenus(self): """Reloads the viewport menus.""" # Add the individual viewport menus for m in self.viewportMenus: m.Destroy() self.viewportMenus = [] collect() #for v in range(len(ViewportManager.viewports)): # self.viewportMenus.append(self.menuViewports.AppendSubMenu(ViewportMenu(ViewportManager.viewports[v]), "Viewport %d" % (v + 1))) def wxStep(self, task=None): """A step in the WX event loop. You can either call this yourself or use as task.""" while self.evtLoop.Pending(): self.evtLoop.Dispatch() self.wxApp.ProcessIdle() if task != None: return task.cont def onModelSelect(self, model): """Invoked when a model is selected. Shows/hides the texture panel.""" if model == None and self.splitter1.IsSplit(): self.splitter1.Unsplit() elif model != None and not self.splitter1.IsSplit(): assert self.splitter1.SplitVertically(self.splitter2, self.textureManager, -200) def onDestroy(self, evt): """Invoked when the window is destroyed.""" wx.EventLoop.SetActive(self.oldLoop) def onNew(self, evt=None): self.filename = Filename() self.modified = True self.SetTitle("Panda Editor") self.editorInstance.destroyAllModels() def onOpen(self, evt=None): filter = "Panda3D Egg Scene Format (*.egs)|*.[eE][gG][sS];*.egs" #filter += "|Panda3D Compressed Egg Format (*.egg.pz)|*.[eE][gG][gG].[pP][zZ];*.egg.pz" #filter += "|Panda3D Binary Format (*.bam)|*.[bB][aA][mM];*.bam" #filter += "|Panda3D Compressed Binary Format (*.bam)|*.[bB][aA][mM].[pP][zZ];*.bam.pz" ''' # disabled by hypnos, making the loading work filter += "|MultiGen (*.flt)|*.[fF][lL][tT]" filter += "|Lightwave (*.lwo)|*.[lL][wW][oO]" filter += "|AutoCAD (*.dxf)|*.[dD][xX][fF]" filter += "|VRML (*.wrl)|*.[wW][rR][lL]" filter += "|DirectX (*.x)|*.[xX]" filter += "|COLLADA (*.dae)|*.[dD][aA][eE]" ''' dlg = wx.FileDialog(self, "Load file", "", "", filter, wx.OPEN) try: if dlg.ShowModal() == wx.ID_OK: #self.filename = Filename.fromOsSpecific(dlg.GetPath()) p3dFilename = Filename.fromOsSpecific(dlg.GetPath()) self.filename = str(dlg.GetPath()) self.SetTitle(p3dFilename.getBasename() + " - Panda Editor") self.modified = False self.editorInstance.loadEggModelsFile(self.filename) # Reset the camera if base.trackball != None: base.trackball.node().setPos(0, 30, 0) base.trackball.node().setHpr(0, 15, 0) self.onCenterTrackball() if p3dFilename.getExtension().lower() != "bam": self.filename = Filename() self.modified = True self.sceneGraphTree.reload() finally: dlg.Destroy() def onSave(self, evt=None): if not self.modified: return if self.filename == None or self.filename.empty(): self.onSaveAs(evt) else: dlg = wx.FileDialog( self, "Save file", "", "", "Panda3D Binary Format (*.bam)|.[bB][aA][mM];*.bam", wx.SAVE | wx.FD_OVERWRITE_PROMPT) try: if dlg.ShowModal() == wx.ID_OK: self.filename = Filename.fromOsSpecific(dlg.GetPath()) self.SetTitle(self.filename.getBasename() + " - Panda Editor") self.modified = False self.editorInstance.saveEggModelsFile( self.filename.getFullpath()) finally: dlg.Destroy() def onSaveAs(self, evt=None): dlg = wx.FileDialog( self, "Save file as", "", "", "Panda3D Binary Format (*.bam)|.[bB][aA][mM];*.bam", wx.SAVE | wx.FD_OVERWRITE_PROMPT) try: if dlg.ShowModal() == wx.ID_OK: self.onNew() self.filename = Filename.fromOsSpecific(dlg.GetPath()) self.SetTitle(self.filename.getBasename() + " - Panda Editor") self.modified = False self.editorInstance.saveEggModelsFile( self.filename.getFullpath()) finally: dlg.Destroy() def onCreateObject(self, e): """Invoked when the user hits one of the buttons in the "Create" menu.""" modelParent = modelController.getSelectedObject() if modelParent == None: modelParent = render objectInstance = None if e.Id == ID_NODEPATH: objectInstance = NodePathWrapper.onCreateInstance(modelParent) elif e.Id == ID_MODEL: filter = "Panda3D Egg Format (*.egg)|*.[eE][gG][gG];*.egg" filter += "|Panda3D Binary Format (*.bam)|*.[bB][aA][mM];*.bam" filter += "|MultiGen (*.flt)|*.[fF][lL][tT];*.flt" filter += "|Lightwave (*.lwo)|*.[lL][wW][oO];*.lwo" filter += "|AutoCAD (*.dxf)|*.[dD][xX][fF];*.dxf" filter += "|VRML (*.wrl)|*.[wW][rR][lL];*.wrl" filter += "|DirectX (*.x)|*.[xX];*.x" filter += "|COLLADA (*.dae)|*.[dD][aA][eE];*.dae" dlg = wx.FileDialog(self, "Select model", "", "", filter, wx.OPEN) try: if dlg.ShowModal() == wx.ID_OK: objectInstance = NodePathWrapper.onCreateInstance( modelParent, Filename.fromOsSpecific(dlg.GetPath()).getFullpath()) finally: dlg.Destroy() elif e.Id == ID_TERRAIN: filter = "Portable Network Graphics (*.png)|*.[pP][nN][gG];*.png" dlg = wx.FileDialog(self, "Select heightfield", "", "", filter, wx.OPEN) try: if dlg.ShowModal() == wx.ID_OK: objectInstance = GeoMipTerrainNodeWrapper.onCreateInstance( modelParent, Filename.fromOsSpecific(dlg.GetPath()).getFullpath()) finally: dlg.Destroy() elif e.Id == ID_AMBIENT: objectInstance = AmbientLightNodeWrapper.onCreateInstance( modelParent) elif e.Id == ID_DIRECTIONAL: objectInstance = DirectionalLightNodeWrapper.onCreateInstance( modelParent) elif e.Id == ID_POINT: objectInstance = PointLightNodeWrapper.onCreateInstance( modelParent) elif e.Id == ID_SPOT: objectInstance = SpotLightNodeWrapper.onCreateInstance(modelParent) if objectInstance != None: objectInstance.reparentTo(modelParent) objectInstance.enableEditmode() modelController.selectObject(objectInstance) messenger.send(EVENT_SCENEGRAPH_REFRESH) def onChangeViewports(self, e): """Invoked when the user changes viewport layout.""" self.Update() sashpos = self.splitter2.GetSashPosition() if e.Id == ID_SINGLE_VIEWPORT: if isinstance(self.view, Viewport): return self.view.close() self.view = Viewport.makePerspective(self.splitter2) elif e.Id == ID_4x4_GRID: if isinstance(self.view, ViewportGrid): return self.view.close() self.view = ViewportGrid( self.splitter2, [[Viewport.VPTOP, Viewport.VPFRONT], [Viewport.VPLEFT, Viewport.VPPERSPECTIVE]]) self.view.center() else: if e.Id == ID_2_HORIZONTAL: orientation = wx.SPLIT_HORIZONTAL elif e.Id == ID_2_VERTICAL: orientation = wx.SPLIT_VERTICAL else: return if isinstance(self.view, ViewportSplitter) and not isinstance( self.view, ViewportGrid): if self.view.GetSplitMode() == orientation: return self.view.close() self.view.split(Viewport.VPTOP, Viewport.VPPERSPECTIVE, orientation) else: self.view.close() self.view = ViewportSplitter(self.splitter2, Viewport.VPTOP, Viewport.VPPERSPECTIVE, orientation) self.splitter2.Unsplit() assert self.splitter2.SplitVertically(self.leftBarSplitter, self.view, sashpos) # Reload the menus collect() self.reloadViewportMenus() # Make sure the viewports are initialized correctly self.Update() ViewportManager.updateAll() self.wxStep() ViewportManager.initializeAll() messenger.send("window-event") def onToggleGrid(self, evt=None): """Toggles the grid on/off.""" if evt.GetEventObject().IsChecked(ID_ENABLE_GRID): self.grid.enable() else: self.grid.disable() def onCenterTrackball(self, evt=None): """Center the trackball, like 'c' does in pview.""" gbv = render.getBounds() # Determine the bounding sphere around the object. if gbv.isInfinite(): return if gbv.isEmpty(): return # The BoundingVolume might be a sphere (it's likely), but since it # might not, we'll take no chances and make our own sphere. sphere = BoundingSphere(gbv.getApproxCenter(), 0.0) if (not sphere.extendBy(gbv)): return radius = 50.0 # Loop through the windows/viewports for w in WindowManager.windows: # Choose a suitable distance to view the whole volume in our frame. # This is based on the camera lens in use. fov = w.camLens.getFov() distance = radius / tan(deg2Rad(min(fov[0], fov[1]) / 2.0)) # Ensure the far plane is far enough back to see the entire object. idealFarPlane = distance + radius * 1.5 w.camLens.setFar(max(w.camLens.getDefaultFar(), idealFarPlane)) # And that the near plane is far enough forward. w.camLens.setNear( min(w.camLens.getDefaultNear(), radius - sphere.getRadius())) w.trackball.node().setOrigin(sphere.getCenter()) w.trackball.node().setPos(Vec3.forward() * distance) # Also set the movement scale on the trackball to be consistent # with the size of the model and the lens field-of-view. w.trackball.node().setForwardScale(distance * 0.006)
class Project: def __init__(self, filename, name=""): self.filename = filename #absolute self.dir = Filename(filename.getDirname()) #[Zeina]CONSIDER: the sceneFilename can be changed to starting sceneFile or default sceneFile #The default scene file cannot be deleted. #self.sceneFilename = None #Filename(filename.getBasenameWoExtension() + '.scene') self.sceneName = None self.scenes = {} #key:Scene Name, value:Scene Filename self.scenesOrder = [] self.filenameIndexes = {} #self.addScene(filename.getBasenameWoExtension(), self.sceneFilename) self.journalFilename = Filename(filename.getBasenameWoExtension() + '.journal') self.inventoryMapFilename = Filename( filename.getBasenameWoExtension() + '.inventory') self.name = name try: f = open(filename.toOsSpecific()) self.decode(f) f.close() except IOError: pass self.addScene() #if self.scenes.has_key("startScene"): # self.sceneName = "startScene" #create the folder structure if not os.path.isdir(self.dir.toOsSpecific()): os.makedirs(self.dir.toOsSpecific()) for d in ('Models', 'Textures', 'Models/Thumbnails', 'Textures/Thumbnails', 'Shaders', 'Sounds', 'Journal_Entries', 'Conversations', 'Scripts'): dir = os.path.join(self.dir.toOsSpecific(), d) if not os.path.isdir(dir): os.mkdir(dir) self.lib = Library.Library(self.dir) def decode(self, xmlFile): doc = xml.dom.minidom.parse(xmlFile) root = doc.childNodes[0] startingSceneName = None for n in root.childNodes: if n.localName == "Name": self.name = n.childNodes[0].data.strip() elif n.localName == "StartingSceneName": startingSceneName = n.childNodes[0].data.strip() elif n.localName == "SceneFile": for m in n.childNodes: if (m.localName == "Name"): name = str(m.childNodes[0].data.strip()) if (m.localName == "Filepath"): filepath = Filename(m.childNodes[0].data.strip()) self.addScene(name, filepath) #self.sceneFilename = Filename(n.childNodes[0].data.strip()) elif n.localName == "JournalFile": self.journalFilename = Filename(n.childNodes[0].data.strip()) if (startingSceneName != None): self.sceneName = startingSceneName def encode(self): doc = xml.dom.minidom.Document() root = doc.createElement("Project") doc.appendChild(root) name = doc.createElement("Name") name.appendChild(doc.createTextNode(self.name)) root.appendChild(name) startingSceneName = doc.createElement("StartingSceneName") #startingSceneName = doc.createElement("Name") startingSceneName.appendChild(doc.createTextNode(self.sceneName)) #startingSceneFile.appendChild(startingSceneName) root.appendChild(startingSceneName) for s in self.scenesOrder: sceneFile = doc.createElement("SceneFile") sceneName = doc.createElement("Name") sceneName.appendChild(doc.createTextNode(s)) sceneFile.appendChild(sceneName) sceneFilepath = doc.createElement("Filepath") sceneFilepath.appendChild( doc.createTextNode(self.scenes[s].getFullpath())) sceneFile.appendChild(sceneFilepath) root.appendChild(sceneFile) journalFile = doc.createElement("JournalFile") journalFile.appendChild( doc.createTextNode(self.journalFilename.getFullpath())) root.appendChild(journalFile) inventoryMapFile = doc.createElement("InventoryMapFile") inventoryMapFile.appendChild( doc.createTextNode(self.inventoryMapFilename.getFullpath())) root.appendChild(inventoryMapFile) return doc.toprettyxml() def saveToFile(self): xmlText = self.encode() try: f = open(self.filename.toOsSpecific(), "w") f.write(xmlText) f.close() except IOError: raise ProjectSaveError(self.filename.toOsSpecific()) def saveAs(self, newDir, newName, keepOld=False): if keepOld: shutil.copytree(self.dir.toOsSpecific(), newDir.toOsSpecific()) else: if not os.path.exists(newDir.toOsSpecific()): os.makedirs(newDir.toOsSpecific()) for x in os.listdir(self.dir.toOsSpecific()): shutil.move((self.dir + '/' + x).toOsSpecific(), (newDir + '/' + x).toOsSpecific()) #make sure everything in the new directory is not marked read only for root, dirs, files in os.walk(newDir.toOsSpecific()): for name in files: os.chmod(os.path.join(root, name), stat.S_IWRITE) newFilename = newDir + '/' + newName + '.proj' newSceneFilename = Filename(newName + '.scene') newJournalFilename = Filename(newName + '.journal') newInventoryMapFilename = Filename(newName + '.inventory') f = Filename(self.filename) f.setDirname(newDir.getFullpath()) f2 = Filename(self.scenes[self.sceneName]) #self.sceneFilename) f2.setDirname(newDir.getFullpath()) f3 = Filename(self.journalFilename) f3.setDirname(newDir.getFullpath()) f4 = Filename(self.inventoryMapFilename) f4.setDirname(newDir.getFullpath()) #make sure we don't end up with a project or scene file with the old name #in the new directory if os.path.exists(f.toOsSpecific()): os.remove(f.toOsSpecific()) if os.path.exists(f2.toOsSpecific()): os.remove(f2.toOsSpecific()) if os.path.exists(f3.toOsSpecific()): os.remove(f3.toOsSpecific()) if os.path.exists(f4.toOsSpecific()): os.remove(f4.toOsSpecific()) self.name = newName self.dir = newDir self.filename = newFilename #self.scenes["default"] = newSceneFilename #self.sceneFilename = newSceneFilename self.journalFilename = newJournalFilename self.inventoryMapFilename = newInventoryMapFilename self.lib.moveTo(newDir) self.saveToFile() def addScene(self, name=None, sceneFile=None): if (name == None): suffix = len(self.scenes) defaultname = "default_" name = defaultname + str(suffix) sceneFile = Filename(name + ".scene") f = Filename(sceneFile) f.setDirname(self.dir.getFullpath()) while (os.path.exists(f.toOsSpecific()) or self.filenameIndexes.has_key( sceneFile.getBasenameWoExtension())): suffix += 1 name = defaultname + str(suffix) sceneFile = Filename(name + ".scene") f = Filename(sceneFile) f.setDirname(self.dir.getFullpath()) #if there is a name but no sceneFile given for that name #create a file with that name #TO DO: make it more error prone, for example this is not checking #if the file with the name already exist in the folder. This part may not be #be used at all but should be thought about. if (sceneFile == None): sceneFile = Filename(name + ".scene") self.scenes[name] = sceneFile self.filenameIndexes[sceneFile.getBasenameWoExtension()] = sceneFile if (len(self.scenes) == 1): #self.sceneFilename = sceneFile self.sceneName = name #f = Filename(sceneFile) #f.setDirname(self.dir.getFullpath()) self.scenesOrder = sorted(self.scenes) return (name, sceneFile) def getOpeningScene(self): return self.scenes[self.sceneName] def getScene(self, sceneName): if self.scenes.has_key(sceneName): return self.scenes[sceneName] else: print "There is no scene under name ", sceneName, " in the project." return None def renameScene(self, name, newName): if (self.getScene(newName) != None): raise DuplicateNameError(newName, name, newName) #print name," ", newName sceneFile = self.getScene(name) del self.scenes[name] self.scenes[newName] = sceneFile if (self.sceneName == name): self.sceneName = newName self.scenesOrder = sorted(self.scenes) Debug.debug(__name__, str(self.scenes)) Debug.debug(__name__, str(self.scenesOrder)) def removeScene(self, sceneName, delFile=False): if (len(self.scenes) == 1): raise SceneDeleteError() else: #delete the file in the folder too. if delFile: toDel = Filename(self.dir.getFullpath() + '/' + self.scenes[sceneName].getFullpath()) try: os.remove(toDel.toOsSpecific()) except OSError as e: pass if (self.sceneName == sceneName): self.sceneName = self.scenesOrder[0] #self.sceneFilename = self.scenes[self.sceneName] del self.filenameIndexes[ self.scenes[sceneName].getBasenameWoExtension()] del self.scenes[sceneName] self.scenesOrder = sorted(self.scenes) def setOpeningScene(self, name): self.sceneName = name
class Project: def __init__(self, filename, name = ""): self.filename = filename #absolute self.dir = Filename(filename.getDirname()) #[Zeina]CONSIDER: the sceneFilename can be changed to starting sceneFile or default sceneFile #The default scene file cannot be deleted. #self.sceneFilename = None #Filename(filename.getBasenameWoExtension() + '.scene') self.sceneName = None self.scenes = {}#key:Scene Name, value:Scene Filename self.scenesOrder = [] self.filenameIndexes = {} #self.addScene(filename.getBasenameWoExtension(), self.sceneFilename) self.journalFilename = Filename(filename.getBasenameWoExtension() + '.journal') self.inventoryMapFilename = Filename(filename.getBasenameWoExtension()+'.inventory') self.name = name try: f = open(filename.toOsSpecific()) self.decode(f) f.close() except IOError: pass self.addScene() #if self.scenes.has_key("startScene"): # self.sceneName = "startScene" #create the folder structure if not os.path.isdir(self.dir.toOsSpecific()): os.makedirs(self.dir.toOsSpecific()) for d in ('Models','Textures', 'Models/Thumbnails', 'Textures/Thumbnails', 'Shaders', 'Sounds', 'Journal_Entries', 'Conversations', 'Scripts'): dir = os.path.join(self.dir.toOsSpecific(),d) if not os.path.isdir(dir): os.mkdir(dir) self.lib = Library.Library(self.dir) def decode(self, xmlFile): doc = xml.dom.minidom.parse(xmlFile) root = doc.childNodes[0] startingSceneName = None for n in root.childNodes: if n.localName == "Name": self.name = n.childNodes[0].data.strip() elif n.localName == "StartingSceneName": startingSceneName = n.childNodes[0].data.strip() elif n.localName == "SceneFile": for m in n.childNodes: if(m.localName == "Name"): name = str(m.childNodes[0].data.strip()) if(m.localName == "Filepath"): filepath = Filename(m.childNodes[0].data.strip()) self.addScene(name, filepath) #self.sceneFilename = Filename(n.childNodes[0].data.strip()) elif n.localName == "JournalFile": self.journalFilename = Filename(n.childNodes[0].data.strip()) if(startingSceneName != None): self.sceneName = startingSceneName def encode(self): doc = xml.dom.minidom.Document() root = doc.createElement("Project") doc.appendChild(root) name = doc.createElement("Name") name.appendChild(doc.createTextNode(self.name)) root.appendChild(name) startingSceneName = doc.createElement("StartingSceneName") #startingSceneName = doc.createElement("Name") startingSceneName.appendChild(doc.createTextNode(self.sceneName)) #startingSceneFile.appendChild(startingSceneName) root.appendChild(startingSceneName) for s in self.scenesOrder: sceneFile = doc.createElement("SceneFile") sceneName = doc.createElement("Name") sceneName.appendChild(doc.createTextNode(s)) sceneFile.appendChild(sceneName) sceneFilepath = doc.createElement("Filepath") sceneFilepath.appendChild(doc.createTextNode(self.scenes[s].getFullpath())) sceneFile.appendChild(sceneFilepath) root.appendChild(sceneFile) journalFile = doc.createElement("JournalFile") journalFile.appendChild(doc.createTextNode(self.journalFilename.getFullpath())) root.appendChild(journalFile) inventoryMapFile = doc.createElement("InventoryMapFile") inventoryMapFile.appendChild(doc.createTextNode(self.inventoryMapFilename.getFullpath())) root.appendChild(inventoryMapFile) return doc.toprettyxml() def saveToFile(self): xmlText = self.encode() try: f = open(self.filename.toOsSpecific(), "w") f.write(xmlText) f.close() except IOError: raise ProjectSaveError(self.filename.toOsSpecific()) def saveAs(self, newDir, newName, keepOld=False): if keepOld: shutil.copytree(self.dir.toOsSpecific(), newDir.toOsSpecific()) else: if not os.path.exists(newDir.toOsSpecific()): os.makedirs(newDir.toOsSpecific()) for x in os.listdir(self.dir.toOsSpecific()): shutil.move((self.dir + '/' + x).toOsSpecific(), (newDir + '/' + x).toOsSpecific()) #make sure everything in the new directory is not marked read only for root, dirs, files in os.walk(newDir.toOsSpecific()): for name in files: os.chmod(os.path.join(root, name), stat.S_IWRITE) newFilename = newDir + '/' +newName + '.proj' newSceneFilename = Filename(newName + '.scene') newJournalFilename = Filename(newName + '.journal') newInventoryMapFilename = Filename(newName + '.inventory') f = Filename(self.filename) f.setDirname(newDir.getFullpath()) f2 = Filename(self.scenes[self.sceneName])#self.sceneFilename) f2.setDirname(newDir.getFullpath()) f3 = Filename(self.journalFilename) f3.setDirname(newDir.getFullpath()) f4 = Filename(self.inventoryMapFilename) f4.setDirname(newDir.getFullpath()) #make sure we don't end up with a project or scene file with the old name #in the new directory if os.path.exists(f.toOsSpecific()): os.remove(f.toOsSpecific()) if os.path.exists(f2.toOsSpecific()): os.remove(f2.toOsSpecific()) if os.path.exists(f3.toOsSpecific()): os.remove(f3.toOsSpecific()) if os.path.exists(f4.toOsSpecific()): os.remove(f4.toOsSpecific()) self.name = newName self.dir = newDir self.filename = newFilename #self.scenes["default"] = newSceneFilename #self.sceneFilename = newSceneFilename self.journalFilename = newJournalFilename self.inventoryMapFilename = newInventoryMapFilename self.lib.moveTo(newDir) self.saveToFile() def addScene(self,name=None, sceneFile=None): if(name == None): suffix = len(self.scenes) defaultname = "default_" name = defaultname+str(suffix) sceneFile = Filename(name+".scene") f = Filename(sceneFile) f.setDirname(self.dir.getFullpath()) while(os.path.exists(f.toOsSpecific())or self.filenameIndexes.has_key(sceneFile.getBasenameWoExtension())): suffix += 1 name = defaultname+str(suffix) sceneFile = Filename(name+".scene") f = Filename(sceneFile) f.setDirname(self.dir.getFullpath()) #if there is a name but no sceneFile given for that name #create a file with that name #TO DO: make it more error prone, for example this is not checking #if the file with the name already exist in the folder. This part may not be #be used at all but should be thought about. if(sceneFile == None): sceneFile = Filename(name+".scene") self.scenes[name] = sceneFile self.filenameIndexes[sceneFile.getBasenameWoExtension()] = sceneFile if(len(self.scenes) == 1 ): #self.sceneFilename = sceneFile self.sceneName = name #f = Filename(sceneFile) #f.setDirname(self.dir.getFullpath()) self.scenesOrder = sorted(self.scenes) return (name,sceneFile) def getOpeningScene(self): return self.scenes[self.sceneName] def getScene(self,sceneName): if self.scenes.has_key(sceneName): return self.scenes[sceneName] else: print "There is no scene under name ", sceneName, " in the project." return None def renameScene(self, name, newName): if(self.getScene(newName)!= None): raise DuplicateNameError(newName,name, newName) #print name," ", newName sceneFile = self.getScene(name) del self.scenes[name] self.scenes[newName] = sceneFile if(self.sceneName == name): self.sceneName = newName self.scenesOrder = sorted(self.scenes) Debug.debug(__name__,str(self.scenes)) Debug.debug(__name__,str(self.scenesOrder)) def removeScene(self, sceneName, delFile = False): if(len(self.scenes)==1): raise SceneDeleteError() else: #delete the file in the folder too. if delFile: toDel = Filename(self.dir.getFullpath() + '/' + self.scenes[sceneName].getFullpath()) try: os.remove(toDel.toOsSpecific()) except OSError as e: pass if(self.sceneName == sceneName): self.sceneName = self.scenesOrder[0] #self.sceneFilename = self.scenes[self.sceneName] del self.filenameIndexes[self.scenes[sceneName].getBasenameWoExtension()] del self.scenes[sceneName] self.scenesOrder = sorted(self.scenes) def setOpeningScene(self, name): self.sceneName = name