Interactive/SaveShotsFromDir.py

# (C) Copyright 2009 Autodesk, Inc.  All rights reserved.
#
# Use of this software is subject to the terms of the Autodesk license
# agreement provided at the time of installation or download, or which
# otherwise accompanies this software in either electronic or hard copy
# form.

# Empty means use the location of this file
TheSceneDirectory = ""

# What size for images (still shots)
TheImageWidth = 512
TheImageHeight = 512

# What size for movies (other shots)
TheMovieWidth = 320
TheMovieHeight = 240
TheMovieFramesPerSecond = 24
TheMovieCompression = ('Full Frames (Uncompressed)',7500)

# Raytracing (True) or not (False).  It will use the
# scene parameters.
TheUseRaytracing = False

# What format for the image file
TheImageExtension = "png"

# What anti-aliasing quality (0 - 9)
TheAALevel = 4

# Add some text info to the image
TheAddTitle = True
TheTitleLarge = ("C:/WINDOWS/Fonts/arial.ttf", 24)
TheTitleSmall = ("C:/WINDOWS/Fonts/arial.ttf", 12)
TheTextAreaHeight = 32 # Needs to be > of large and 2*small

# Find all A3S files in the directory (either the one where the script is,
# if "TheSceneDirectory" is empty, or the specified one), open them,
# save images for each shot (still in the same directory) and quit.
#
# Run with Showcase -script SaveShotsFromDir.py or by dragging
# SaveShotsFromDir.py and dropping it onto the Showcase executable.

# ---------------------------------------------------------------------

from   ScriptRunner       import ScriptRunner

from PIL import Image, ImageFont, ImageDraw
import os.path, glob
import ShotIO

class SimpleExample( ScriptRunner ):
    def __init__( self, scriptName, args ):
        (self.myDir, f) = os.path.split(scriptName)
        if TheSceneDirectory != "" and os.path.isdir(TheSceneDirectory):
            self.myDir = TheSceneDirectory
        ScriptRunner.__init__( self, scriptName, args )


    def Main( self ):
        files = self.findFiles()
        self.announce( "Processing files %s" % (files) )
        for f in files:
            self.announce( "Processing: %s" % (f) )
            self.process( f )
            self.announce( "Completed: %s" % (f) )
        self.announce( "All completed" )
        self.sendMessage('QUIT', ())


    def findFiles(self):
        if os.path.isdir(self.myDir):
            files = glob.glob(os.path.join(self.myDir, "*.a3s"))
        else:
            files = ()
        return files


    def process(self,sceneFile):
        self.sendMessageSync('APPLICATION_LOAD_SCENE', (sceneFile, ),
                             userTimeout=3600)
        if TheUseRaytracing:
            self.sendMessageSync('RT_SWITCH_REQUEST', (True,))

        (imageDir, imageRoot) = os.path.split(sceneFile)
        (imageRoot, ext) = os.path.splitext(imageRoot)
        self.processShots( imageDir, imageRoot )

        if TheUseRaytracing:
            self.sendMessageSync('RT_SWITCH_REQUEST', (False,))

        # Close and get ready for the next one
        self.sendMessageSync( 'APPLICATION_CLOSE_SCENE', () )


    def processShots(self, imageDir, imageRoot):
        # Using TheImageHeight, TheImageWidth, TheImageExtension, TheAALevel

        if self.document().has(ShotIO.id):
            width = TheImageWidth
            height = TheImageHeight
            if TheAddTitle:
                fntS = ImageFont.truetype(TheTitleSmall[0],TheTitleSmall[1])
                fntL = ImageFont.truetype(TheTitleLarge[0],TheTitleLarge[1])
            self.announce( "Shots on %s in %s" % (imageRoot, imageDir) )
            for s in self.document().get(ShotIO.id).shots:
                if s.getShotType() != "ShotStill":
                    self.processMovie(s, imageDir, imageRoot)
                    continue

                f = os.path.join( imageDir, "%s_%s.%s" % (imageRoot,
                                                          s.getLabel(),
                                                          TheImageExtension) )
                self.announce( "Position shot %s" % (s.getLabel()) )
                self.sendMessageSync( 'SHOT_PLAY_SINGLE', ( s.getName(),False),
                                      userTimeout=3600 )
                self.announce( "Saving image of shot %s (%s) to %s" % \
                               (s.getLabel(),s.getName(),f) )
                self.sendMessageSync( 'SAVE_SCREENSHOT_AT_RESOLUTION',
                                      (f,width, height,
                                       3, TheAALevel, False,) )

                if TheAddTitle:
                    TheTextAreaHeight = 32

                    pk = s.getParameters()['Keyframe']
                    navState = pk[0]
                    dispState = pk[1]
                    pos = navState.getPosition()
                    la = navState.getLookAt()

                    text = s.getLabel()
                    text1 = "Camera%s" % (str(pos))
                    text2 = "Look at %s" % (str(la))
                    imgT = Image.new('RGBA', (width, TheTextAreaHeight),
                                     (255,255,255,0))
                    drawT = ImageDraw.Draw(imgT)
                    drawT.fontmode = "0"
                    drawT.text((0,0), text1, font=fntS, fill=(0,0,0))
                    drawT.text((0,TheTextAreaHeight/2), text2, font=fntS, fill=(0,0,0))

                    imgB = Image.new('RGBA', (width, TheTextAreaHeight),
                                     (255,255,255,0))
                    drawB = ImageDraw.Draw(imgB)
                    drawB.fontmode = "0"
                    drawB.text((0,0), text, font=fntL, fill=(0,0,0))

                    im = Image.open(f)

                    res = Image.new('RGBA', (width, height+64), (0,0,0,0))
                    res.paste( imgT, (0,0,width,TheTextAreaHeight) )
                    res.paste( im, (0,TheTextAreaHeight,
                                    width, height+TheTextAreaHeight) )
                    res.paste( imgB, (0,height+TheTextAreaHeight,
                                      width,height+2*TheTextAreaHeight) )
                    res.save(f,'png')


    def processMovie( self, s, imageDir, imageRoot ):
        f = os.path.join( imageDir, "%s_%s" % (imageRoot, s.getLabel()) )
        self.announce( "Saving movie of shot %s (%s) to %s" % \
                       (s.getLabel(),s.getName(),f) )
        self.sendMessageSync( 'SAVE_SHOT_AS_MOVIE_AT_RESOLUTION',
                              (TheMovieWidth, TheMovieHeight,
                               TheMovieFramesPerSecond, 0,
                               TheAALevel, False,
                               f, s.getName(),
                               TheMovieCompression,
                               (None,None,("","",False))),
                              userConditions="SHOT_PLAYING_DONE",
                              userTimeout=3600)


    def announce( self, m ):
        print m
        self.sendMessage( 'STATUSBAR_SET_TEXT', (m,) )


# ===============================================================
def instantiate( scriptName, args ):
    return SimpleExample( scriptName, args )
# ===============================================================