示例#1
0
    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)
示例#2
0
    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)
示例#3
0
 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)
示例#5
0
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)
示例#6
0
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
示例#7
0
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