Newer
Older
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
"name": "Animated Render Baker",
"author": "Janne Karhu (jahka)",
"version": (1, 0),
"location": "Properties > Render > Bake Panel",
"description": "Renderbakes a series of frames",
"category": "Object",
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.6/Py/"
"Scripts/Object/Animated_Render_Baker",
"tracker_url": "https://developer.blender.org/T24836"}
import bpy
from bpy.props import IntProperty
class OBJECT_OT_animrenderbake(bpy.types.Operator):
bl_label = "Animated Render Bake"
bl_description= "Bake animated image textures of selected objects"
bl_idname = "object.anim_bake_image"
bl_register = True
def framefile(self, filepath, frame):
Set frame number to file name image.png -> image0013.png
import os
fn, ext = os.path.splitext(filepath)
return "%s%04d%s" % (fn, frame, ext)
def invoke(self, context, event):
import shutil
scene = context.scene
start = scene.animrenderbake_start
end = scene.animrenderbake_end
# Check for errors before starting
if start >= end:
self.report({'ERROR'}, "Start frame must be smaller than end frame")
return {'CANCELLED'}
selected = context.selected_objects
# Only single object baking for now
if scene.render.use_bake_selected_to_active:
if len(selected) > 2:
self.report({'ERROR'}, "Select only two objects for animated baking")
return {'CANCELLED'}
elif len(selected) > 1:
self.report({'ERROR'}, "Select only one object for animated baking")
return {'CANCELLED'}
if context.active_object.type != 'MESH':
self.report({'ERROR'}, "The baked object must be a mesh object")
return {'CANCELLED'}
if context.active_object.mode == 'EDIT':
self.report({'ERROR'}, "Can't bake in edit-mode")
return {'CANCELLED'}
# find the image that's used for rendering
# TODO: support multiple images per bake
for uvtex in context.active_object.data.uv_textures:
if uvtex.active_render == True:
for uvdata in uvtex.data:
if uvdata.image is not None:
if img is None:
self.report({'ERROR'}, "No valid image found to bake to")
return {'CANCELLED'}
if img.is_dirty:
self.report({'ERROR'}, "Save the image that's used for baking before use")
return {'CANCELLED'}
if img.packed_file is not None:
self.report({'ERROR'}, "Can't animation-bake packed file")
return {'CANCELLED'}
# make sure we have an absolute path so that copying works for sure
img_filepath_abs = bpy.path.abspath(img.filepath, library=img.library)
print("Animated baking for frames (%d - %d)" % (start, end))
for cfra in range(start, end + 1):
print("Baking frame %d" % cfra)
# update scene to new frame and bake to template image
scene.frame_set(cfra)
ret = bpy.ops.object.bake_image()
if 'CANCELLED' in ret:
return {'CANCELLED'}
# Currently the api doesn't allow img.save_as()
# so just save the template image as usual for
# every frame and copy to a file with frame specific filename
img_filepath_new = self.framefile(img_filepath_abs, cfra)
shutil.copyfile(img_filepath_abs, img_filepath_new)
print("Saved %r" % img_filepath_new)
print("Baking done!")
return{'FINISHED'}
def draw(self, context):
scene = context.scene
row = layout.row()
row.operator("object.anim_bake_image", text="Animated Bake", icon="RENDER_ANIMATION")
rowsub = row.row(align=True)
rowsub.prop(scene, "animrenderbake_start")
rowsub.prop(scene, "animrenderbake_end")
Janne Karhu
committed
Campbell Barton
committed
bpy.utils.register_module(__name__)
bpy.types.Scene.animrenderbake_start = IntProperty(
name="Start",
description="Start frame of the animated bake",
default=1)
bpy.types.Scene.animrenderbake_end = IntProperty(
name="End",
description="End frame of the animated bake",
default=250)
bpy.types.RENDER_PT_bake.prepend(draw)
Campbell Barton
committed
bpy.utils.unregister_module(__name__)
# restore original panel draw function
del bpy.types.Scene.animrenderbake_start
del bpy.types.Scene.animrenderbake_end
bpy.types.RENDER_PT_bake.remove(draw)