From b044a473b9f42cf8ec89988a9cf067e0d477dfd3 Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 3 Oct 2005 15:11:51 +0000 Subject: [PATCH] add saveCubemap(); robustify screenshot methods --- direct/src/showbase/ShowBase.py | 126 +++++++++++++++++++++++++------- 1 file changed, 99 insertions(+), 27 deletions(-) diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 312f72007c..f6879fe202 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -1530,59 +1530,131 @@ class ShowBase(DirectObject.DirectObject): if self.camFrustumVis: self.camFrustumVis.removeNode() - def screenshot(self, namePrefix='screenshot'): - filename = self.win.saveScreenshotDefault(namePrefix) - if filename.empty(): - # The screenshot attempt failed for some reason. - return 0 + def screenshot(self, namePrefix = 'screenshot', + defaultFilename = 1, source = None): + """ Captures a screenshot from the main window or from the + specified window or Texture and writes it to a filename in the + current directory (or to a specified directory). + + If defaultFilename is True, the filename is synthesized by + appending namePrefix to a default filename suffix (including + the filename extension) specified in the Config variable + screenshot-filename. Otherwise, if defaultFilename is False, + the entire namePrefix is taken to be the filename to write, + and this string should include a suitable filename extension + that will be used to determine the type of image file to + write. + + Normally, the source is a GraphicsWindow, GraphicsBuffer or + DisplayRegion. If a Texture is supplied instead, it must have + a ram image (that is, if it was generated by + makeTextureBuffer() or makeCubeMap(), the parameter toRam + should have been set true). If it is a cube map texture as + generated by makeCubeMap(), namePrefix should contain the hash + mark ('#') character. """ + + if source == None: + source = self.win + + if defaultFilename: + filename = GraphicsOutput.makeScreenshotFilename(namePrefix) + else: + filename = Filename(namePrefix) + + if isinstance(source, Texture): + if source.getZSize() > 1: + saved = source.writePages(filename) + else: + saved = source.write(filename) + else: + saved = source.saveScreenshot(filename) # Announce to anybody that a screenshot has been taken messenger.send('screenshot', [filename]) - return 1 + + return saved + + def saveCubemap(self, namePrefix = 'cubemap_#.png', + defaultFilename = 0, source = None, + camera = None, size = 128, + cameraMask = BitMask32.allOn()): + + """ Similar to screenshot(), this sets up a temporary cube map + Texture which it uses to take a series of six snapshots of the + current scene, one in each of the six cube map directions. + This requires rendering a new frame. + + Unlike screenshot(), source may only be a GraphicsWindow, + GraphicsBuffer, or DisplayRegion; it may not be a Texture. + + camera should be the node to which the cubemap cameras will be + parented. The default is the camera associated with source, + if source is a DisplayRegion, or base.camera otherwise.""" + + if source == None: + source = base.win + + if camera == None: + if hasattr(source, "getCamera"): + camera = source.getCamera() + if camera == None: + camera = base.camera + + if hasattr(source, "getWindow"): + source = source.getWindow() + + rig = NodePath(namePrefix) + buffer = source.makeCubeMap(namePrefix, size, 1, rig, cameraMask) + if buffer == None: + raise StandardError, "Could not make cube map." + + # Now render a frame to fill up the texture. + rig.reparentTo(camera) + base.graphicsEngine.renderFrame() + + tex = buffer.getTexture() + saved = self.screenshot(namePrefix = namePrefix, + defaultFilename = defaultFilename, + source = tex) + + base.graphicsEngine.removeWindow(buffer) + rig.removeNode() + + return saved def movie(self, namePrefix = 'movie', duration = 1.0, fps = 30, - format = 'rgb', sd = 4, source = None): + format = 'png', sd = 4, source = None): """ - movie(namePrefix = 'movie', duration=1.0, fps=30, format='rgb', sd=4) - Spawn a task to capture a movie using the screenshot function. - namePrefix will be used to form output file names (can include path information (e.g. '/i/beta/frames/myMovie') - duration is the length of the movie in seconds - fps is the frame rate of the resulting movie - - format specifies output file format (e.g. rgb, bmp) + - format specifies output file format (e.g. png, bmp) - sd specifies number of significant digits for frame count in the - output file name (e.g. if sd = 4, movie_0001.rgb) + output file name (e.g. if sd = 4, movie_0001.png) - source is the Window, Buffer, DisplayRegion, or Texture from which to save the resulting images. The default is the main window. """ - if source == None: - source = self.win globalClock.setMode(ClockObject.MNonRealTime) globalClock.setDt(1.0/float(fps)) t = taskMgr.add(self._movieTask, namePrefix + '_task') - t.endT = globalClock.getFrameTime() + duration t.frameIndex = 1 + t.numFrames = int(duration * fps) t.source = source t.outputString = namePrefix + '_%0' + `sd` + 'd.' + format t.uponDeath = lambda state: globalClock.setMode(ClockObject.MNormal) def _movieTask(self, state): - currT = globalClock.getFrameTime() - if currT >= state.endT: + frameName = state.outputString % state.frameIndex + self.notify.info("Capturing frame: " + frameName) + self.screenshot(namePrefix = frameName, defaultFilename = 0, + source = state.source) + + state.frameIndex += 1 + if state.frameIndex > state.numFrames: return Task.done else: - frameName = state.outputString % state.frameIndex - self.notify.info("Capturing frame: " + frameName) - if isinstance(state.source, Texture): - if state.source.getZSize() > 1: - state.source.writePages(HashFilename(frameName)) - else: - state.source.write(Filename(frameName)) - else: - state.source.saveScreenshot(Filename(frameName)) - - state.frameIndex += 1 return Task.cont def __windowEvent(self, win):