This allows playblast of certain frames in blender while filling in the gaps automatically
The goal is to allow animator to work in spline yet make a playblast on two's (Tip from Joan Marc Fuentes)
TODO: put this in blender addon form.
TODO: allow it to use a keyed object to find frames to playblast ...
#Use and Modify at your own risk
#example usage it assumes first frame in list is starting frame: #naPlayblast( frames = [1,3,5], imageDir = "/Users/Nathaniel/Desktop/SINGLE_BLENDER_FACE_RIG/intro_blender_pipe/output/tmpPlayblast", fill = True)
#this example playblasts on twos #frames = range( bpy.context.scene.frame_start, bpy.context.scene.frame_end, 2) #naPlayblast( frames = frames, imageDir = "/Users/Nathaniel/Desktop/SINGLE_BLENDER_FACE_RIG/intro_blender_pipe/output/tmpPlayblast", fill = True) ##
import shutil
import os
import bpy
def naPlayblast( frames = [1,3,5], imageDir = "/Users/Nathaniel/Desktop/SINGLE_BLENDER_FACE_RIG/intro_blender_pipe/output/tmpPlayblast", fill = True):
if not os.path.exists( imageDir ):
print('cannot find output directory')
return
if frames[0] != bpy.context.scene.frame_start:
print('only works with starting frame given matches with timeline')
return
setImageExt()
#playblast chosen frames
for frame in frames:
bpy.context.scene.frame_set(frame)
imageName = getImageNameFromNumber(frame)
imagePath = os.path.join( imageDir, imageName )
bpy.data.scenes["Scene"].render.filepath = imagePath
bpy.ops.render.opengl(write_still=True)
#fill in missing frames
if fill:
missingInfoDict = getFillMissingFramesDictionary( frames )
fillMissingFrames( missingInfoDict, imageDir )
def setImageExt():
"""can change this for different image extension
"""
bpy.context.scene.render.image_settings.file_format = 'TIFF'
def getImageExt():
return 'tif'
def getImageNameFromNumber( frame = 1 ):
"""can change this to any image name formatting
"""
return 'img_%d.%s' %(frame, getImageExt() )
def getFillMissingFramesDictionary( sourceFrames = [1,3,5] ):
"""keys are source image name values list of destination image names needed to fill
#this gives info for filling in images
#ex result given [1,3,5] it assumes always beginning with start frame:
#{ 'img_1':['img_2'], 'img_3':[img_4] }
"""
startFrame = bpy.context.scene.frame_start
endFrame = bpy.context.scene.frame_end
if sourceFrames[0] != startFrame:
print( 'cannot handle source frames not starting at %d.' %startFrame)
return
result = {}
for i in range(0,len(sourceFrames)-1):
#print sourceFrames[i], range( sourceFrames[i]+1, sourceFrames[i+1] )
sImage = getImageNameFromNumber( sourceFrames[i] )
dImages = [ getImageNameFromNumber(x) for x in range( sourceFrames[i]+1, sourceFrames[i+1] ) ]
result[ sImage ] = dImages
#fill in up to total frames if needed
if sourceFrames[ len(sourceFrames) - 1 ] != endFrame:
sImage = getImageNameFromNumber( sourceFrames[len(sourceFrames)-1] )
dImages = [ getImageNameFromNumber(x) for x in range( sourceFrames[ len(sourceFrames)-1 ]+1, endFrame+1 ) ]
result[ sImage ] = dImages
return result
def fillMissingFrames( imgDict = { 'img_1':['img_2'], 'img_3':['img_4'] }, imgDir = '/Users/Nathaniel/Desktop/SINGLE_BLENDER_FACE_RIG/intro_blender_pipe/output/tmpPlayblast' ):
"""
this does actual copy of images
#given ex: { 'img_1':['img_2'], 'img_3':[img_4] }, imgDir = '/Users/Nathaniel/Desktop/SINGLE_BLENDER_FACE_RIG/intro_blender_pipe/output/tmpPlayblast'
"""
for sourceImage in imgDict.keys():
destinationImages = imgDict[sourceImage]
for dImage in destinationImages:
dImageFull = os.path.join( imgDir, dImage )
sImageFull = os.path.join( imgDir, sourceImage )
if not os.path.exists( sImageFull ):
print('could not find source image %s, skipping' %sImageFull)
continue
shutil.copy( sImageFull, dImageFull )
Happy Sketching!
Nate
#inspired by:
#Joan Marc Fuentes https://vimeo.com/88955189
#https://stackoverflow.com/questions/14982836/rendering-and-saving-images-through-blender-python
#https://blender.stackexchange.com/questions/1101/blender-rendering-automation-build-script
#https://blender.stackexchange.com/questions/27579/render-specific-frames-with-opengl-via-python/27640
#https://stackoverflow.com/questions/27515913/create-a-copy-of-an-image-python
#https://stackoverflow.com/questions/27678156/how-to-count-by-twos-with-pythons-range