text: #!/bin/env python
  
  # Automatically translated python version of 
  # OpenSceneGraph example program "osgimagesequence"
  # !!! This program will need manual tuning before it will work. !!!
  
  import sys
  
  from osgpypp import osg
  from osgpypp import osgDB
  from osgpypp import osgViewer
  
  
  # Translated from file 'osgimagesequence.cpp'
  
  # OpenSceneGraph example, osgtexture3D.
  #*
  #*  Permission is hereby granted, free of charge, to any person obtaining a copy
  #*  of this software and associated documentation files (the "Software"), to deal
  #*  in the Software without restriction, including without limitation the rights
  #*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  #*  copies of the Software, and to permit persons to whom the Software is
  #*  furnished to do so, subject to the following conditions:
  #*
  #*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  #*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  #*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  #*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  #*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  #*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  #*  THE SOFTWARE.
  #
  
  #include <osg/Node>
  #include <osg/Geometry>
  #include <osg/Notify>
  #include <osg/Texture1D>
  #include <osg/Texture2D>
  #include <osg/Texture3D>
  #include <osg/TextureRectangle>
  #include <osg/ImageSequence>
  #include <osg/Geode>
  
  #include <osgDB/Registry>
  #include <osgDB/ReadFile>
  #include <osgDB/WriteFile>
  #include <osgDB/FileNameUtils>
  #include <osgDB/FileUtils>
  
  
  #include <osgViewer/Viewer>
  #include <osgViewer/ViewerEventHandlers>
  
  #include <iostream>
  
  
  static osgDB.DirectoryContents getSuitableFiles(osg.ArgumentParser arguments)
      files = osgDB.DirectoryContents()
      for(int i=1 i<arguments.argc() ++i)
          if osgDB.fileType(arguments[i]) == osgDB.DIRECTORY :
              directory = arguments[i]
              dc = osgDB.getSortedDirectoryContents(directory)
              
              for(osgDB.DirectoryContents.iterator itr = dc.begin() itr  not = dc.end() ++itr)
                  full_file_name = directory + "/" + (*itr)
                  ext = osgDB.getLowerCaseFileExtension(full_file_name)
                  if ext == "jpg" :  or  (ext == "png")  or  (ext == "gif")  or   (ext == "rgb")  or  (ext == "dds")  :
                      files.push_back(full_file_name)
          else:
              files.push_back(arguments[i])
      return files
  
  
  #
  # A simple demo demonstrating how to set on an animated texture using an osg.ImageSequence
  #
  
  def createState(arguments):
  
      
      imageSequence = osg.ImageSequence()
  
      preLoad = True
          
      while arguments.read("--page-and-discard") :
          imageSequence.setMode(osg.ImageSequence.PAGE_AND_DISCARD_USED_IMAGES)
          preLoad = False
      
      while arguments.read("--page-and-retain") :
          imageSequence.setMode(osg.ImageSequence.PAGE_AND_RETAIN_IMAGES)
          preLoad = False
      
      while arguments.read("--preload") :
          imageSequence.setMode(osg.ImageSequence.PRE_LOAD_ALL_IMAGES)
          preLoad = True
      
      length = -1.0
      while arguments.read("--length",length) : 
      
      fps = 30.0
      while arguments.read("--fps",fps) : 
  
      files = getSuitableFiles(arguments)
      if  not files.empty() :
          for(osgDB.DirectoryContents.iterator itr = files.begin()
              not = files.end()
              ++itr)
              filename = *itr
              if preLoad :
                  image = osgDB.readImageFile(filename)
                  if image.valid() :
                      imageSequence.addImage(image)
              else:
                  imageSequence.addImageFile(filename)
  
          
          if length>0.0 :
              imageSequence.setLength(length)
          else:
              maxNum = imageSequence.getNumImageData()
              imageSequence.setLength(double(maxNum)*(1.0/fps))
      else:
          if length>0.0 :
              imageSequence.setLength(length)
          else:
              imageSequence.setLength(4.0)
          imageSequence.addImage(osgDB.readImageFile("Cubemap_axis/posx.png"))
          imageSequence.addImage(osgDB.readImageFile("Cubemap_axis/negx.png"))
          imageSequence.addImage(osgDB.readImageFile("Cubemap_axis/posy.png"))
          imageSequence.addImage(osgDB.readImageFile("Cubemap_axis/negy.png"))
          imageSequence.addImage(osgDB.readImageFile("Cubemap_axis/posz.png"))
          imageSequence.addImage(osgDB.readImageFile("Cubemap_axis/negz.png"))
          
      # start the image sequence playing
      imageSequence.play()
  
  #if 1
      texture = osg.Texture2D()
      texture.setFilter(osg.Texture.MIN_FILTER,osg.Texture.LINEAR)
      texture.setFilter(osg.Texture.MAG_FILTER,osg.Texture.LINEAR)
      texture.setWrap(osg.Texture.WRAP_R,osg.Texture.REPEAT)
      texture.setResizeNonPowerOfTwoHint(False)
      texture.setImage(imageSequence)
      #texture.setTextureSize(512,512)
  #else:
      texture = osg.TextureRectangle()
      texture.setFilter(osg.Texture.MIN_FILTER,osg.Texture.LINEAR)
      texture.setFilter(osg.Texture.MAG_FILTER,osg.Texture.LINEAR)
      texture.setWrap(osg.Texture.WRAP_R,osg.Texture.REPEAT)
      texture.setImage(imageSequence)
      #texture.setTextureSize(512,512)
  #endif
  
      # create the StateSet to store the texture data
      stateset = osg.StateSet()
  
      stateset.setTextureAttributeAndModes(0,texture,osg.StateAttribute.ON)
  
      return stateset
  
  def createModel(arguments):
  
      
  
      # create the geometry of the model, just a simple 2d quad right now.    
      geode = osg.Geode()
      geode.addDrawable(osg.createTexturedQuadGeometry(osg.Vec3(0.0,0.0,0.0), osg.Vec3(1.0,0.0,0.0), osg.Vec3(0.0,0.0,1.0)))
  
      geode.setStateSet(createState(arguments))
      
      return geode
  
  
  
  s_imageStream = 0
  class MovieEventHandler (osgGA.GUIEventHandler) :
  
      MovieEventHandler():_playToggle(True),_trackMouse(False) 
      
      def setMouseTracking(track):
      
           _trackMouse = track 
      def getMouseTracking():
           return _trackMouse 
      
      set = void(osg.Node* node)
  
      def setTrackMouse(tm):
  
          
          if tm==_trackMouse : return
  
          _trackMouse = tm
  
          print "tracking mouse: ", "ON" : "OFF"), std: if ((_trackMouse) else endl
  
          for(ImageStreamList.iterator itr=_imageStreamList.begin()
              not = _imageStreamList.end()
              ++itr)
              if *itr :.getStatus()==osg.ImageStream.PLAYING :
                  (*itr).pause()
              else:
                  (*itr).play()
  
  
      def getTrackMouse():
  
           return _trackMouse 
  
      handle = virtual bool( osgGA.GUIEventAdapter ea,osgGA.GUIActionAdapter aa, osg.Object*, osg.NodeVisitor* nv)
      
      virtual void getUsage(osg.ApplicationUsage usage) 
  
      typedef std.vector< osg.observer_ptr<osg.ImageStream> > ImageStreamList
      
      class ImageStreamPlaybackSpeedData :
  fps = double()
          lastData = unsigned char*()
          double timeStamp, lastOutput
          
          ImageStreamPlaybackSpeedData() : fps(0), lastData(NULL), timeStamp(0), lastOutput(0) 
          
      
      
      typedef std.vector< ImageStreamPlaybackSpeedData > ImageStreamPlayBackSpeedList
  
      virtual ~MovieEventHandler() 
  
      class FindImageStreamsVisitor (osg.NodeVisitor) :
          FindImageStreamsVisitor(ImageStreamList imageStreamList):
              _imageStreamList(imageStreamList) 
              
          def apply(geode):
              
              
              apply(geode.getStateSet())
  
              for(unsigned int i=0i<geode.getNumDrawables()++i)
                  apply(geode.getDrawable(i).getStateSet())
          
              traverse(geode)
  
          def apply(node):
  
              
              apply(node.getStateSet())
              traverse(node)
          
          inline void apply(osg.StateSet* stateset)
              if  not stateset : return
              
              attr = stateset.getTextureAttribute(0,osg.StateAttribute.TEXTURE)
              if attr :
                  texture2D = dynamic_cast<osg.Texture2D*>(attr)
                  if texture2D : apply(dynamic_cast<osg.ImageStream*>(texture2D.getImage()))
  
                  textureRec = dynamic_cast<osg.TextureRectangle*>(attr)
                  if textureRec : apply(dynamic_cast<osg.ImageStream*>(textureRec.getImage()))
          
          inline void apply(osg.ImageStream* imagestream)
              if imagestream :
                  _imageStreamList.push_back(imagestream) 
                  s_imageStream = imagestream
          
          _imageStreamList = ImageStreamList()
      
          operator = ( FindImageStreamsVisitor)  return *this 
      
  
  
      _playToggle = bool()
      _trackMouse = bool()
      _imageStreamList = ImageStreamList()
      _imageStreamPlayBackSpeedList = ImageStreamPlayBackSpeedList()
      
  
  
  
  
  void MovieEventHandler.set(osg.Node* node)
      _imageStreamList.clear()
      if node :
          fisv = FindImageStreamsVisitor(_imageStreamList)
          node.accept(fisv)
      _imageStreamPlayBackSpeedList.resize(_imageStreamList.size())
  
  
  bool MovieEventHandler.handle( osgGA.GUIEventAdapter ea,osgGA.GUIActionAdapter aa, osg.Object*, osg.NodeVisitor* nv)
      switch(ea.getEventType())
          case(osgGA.GUIEventAdapter.FRAME):
                  t = ea.getTime()
                  printed = bool(False)
                  
                  fps_itr = _imageStreamPlayBackSpeedList.begin()
                  for(ImageStreamList.iterator itr=_imageStreamList.begin()
                      not = _imageStreamList.end()
                      ++itr, ++fps_itr)
                      if *itr :.getStatus()==osg.ImageStream.PLAYING :  and  ((*itr).data()  not = (*fps_itr).lastData) :
                          data = ImageStreamPlaybackSpeedData(*fps_itr)
                          dt =  t - data.timeStamp if ((data.timeStamp > 0)) else  1/60.0
                          data.lastData = (*itr).data()
                          data.fps = (*fps_itr).fps * 0.8 + 0.2 * (1/dt)
                          data.timeStamp = t
                          
                          if t-data.lastOutput > 1 :
                              print data.fps, " "
                              data.lastOutput = t
                              printed = True
                          
                  if printed : 
                      print std.endl
              break
          case(osgGA.GUIEventAdapter.MOVE):
                  if _trackMouse :
                      for(ImageStreamList.iterator itr=_imageStreamList.begin()
                          not = _imageStreamList.end()
                          ++itr)
                          dt = (*itr).getLength() * ((1.0+ea.getXnormalized()) / 2.0)
                          (*itr).seek(dt)
                          print "seeking to ", dt, " length: ", (*itr).getLength()
                  return False
              
          case(osgGA.GUIEventAdapter.KEYDOWN):
              if ea.getKey()==ord("p") :
                  for(ImageStreamList.iterator itr=_imageStreamList.begin()
                      not = _imageStreamList.end()
                      ++itr)
                      if *itr :.getStatus()==osg.ImageStream.PLAYING :
                          # playing, so pause
                          print "Pause"
                          (*itr).pause()
                      else:
                          # playing, so pause
                          print "Play"
                          (*itr).play()
                  return True
              elif ea.getKey()==ord("r") :
                  for(ImageStreamList.iterator itr=_imageStreamList.begin()
                      not = _imageStreamList.end()
                      ++itr)
                      print "Restart"
                      (*itr).rewind()
                  return True
              elif ea.getKey()==ord("L") :
                  for(ImageStreamList.iterator itr=_imageStreamList.begin()
                      not = _imageStreamList.end()
                      ++itr)
                      if *itr :.getLoopingMode() == osg.ImageStream.LOOPING :
                          print "Toggle Looping Off"
                          (*itr).setLoopingMode( osg.ImageStream.NO_LOOPING )
                      else:
                          print "Toggle Looping On"
                          (*itr).setLoopingMode( osg.ImageStream.LOOPING )
                  return True
              elif ea.getKey() == ord("i") : 
                  setTrackMouse( not _trackMouse)
                  
                  
              return False
  
          default:
              return False
  
      return False
  
  void MovieEventHandler.getUsage(osg.ApplicationUsage usage) 
      usage.addKeyboardMouseBinding("i","toggle interactive mode, scrub via mouse-move")
      usage.addKeyboardMouseBinding("p","Play/Pause movie")
      usage.addKeyboardMouseBinding("r","Restart movie")
      usage.addKeyboardMouseBinding("l","Toggle looping of movie")
  
  
  
  
  def main(argv):
  
  
  
  
      
      arguments = osg.ArgumentParser(argv)
  
      # construct the viewer.
      viewer = osgViewer.Viewer(arguments)
  
      filename = str()
      arguments.read("-o",filename)
  
      # create a model from the images and pass it to the viewer.
      viewer.setSceneData(createModel(arguments))
  
      # pass the model to the MovieEventHandler so it can pick out ImageStream's to manipulate.
      meh = MovieEventHandler()
      meh.set( viewer.getSceneData() )
  
      if arguments.read("--track-mouse") : meh.setTrackMouse(True)
      
      viewer.addEventHandler( meh )
  
      viewer.addEventHandler( osgViewer.StatsHandler())
  
      if  not filename.empty() :
          osgDB.writeNodeFile(*viewer.getSceneData(),filename)
  
      return viewer.run()
  
  
  if __name__ == "__main__":
      main(sys.argv)
  