Skip to content

Instantly share code, notes, and snippets.

@RenaKunisaki
Created August 25, 2023 18:41
Show Gist options
  • Save RenaKunisaki/85b19fa4c0cfcdadfdd555376238bc31 to your computer and use it in GitHub Desktop.
Save RenaKunisaki/85b19fa4c0cfcdadfdd555376238bc31 to your computer and use it in GitHub Desktop.
Blender script to resume a bake
import bpy
""" Script to resume a physics bake from a specific time in Blender.
This addresses the incredible fact that there's apparently no way
to change a bake without re-baking the entire animation, even if
the change is halfway through. It also addresses the similarly
incredible fact that you can't play an animation to the end and not
have it automatically restart and discard all caches.
1. Make whatever change you need.
2. Go to the frame you need to rebake from.
3. Delete the bake. The dark red line at the bottom of the timeline
should become orange, indicating the bake is still cached.
4. Run the script.
5. Watch and wait until the end of the animation is reached.
6. Click "current cache to bake".
Pressing Escape will stop playback without discarding the cache,
allowing you to pause and resume baking freely.
Unfortunately this sometimes causes a glitch at the starting frame,
requiring you to rebake anyway. But this usually corrects itself
after a second or two, so you can still get a preview of the rest
of the animation before rebaking.
"""
START_FRAME = None
def when_done():
"""This runs when the bake finishes.
You can put a # in front of any line to disable it.
"\x07" should make the terminal beep.
"""
print("\x07" + "Finished! Start frame was:", START_FRAME) # print to console
bpy.ops.wm.save_mainfile() # save the file
pass # do nothing (a function must have at least one statement)
class ModalTimerOperator(bpy.types.Operator):
"""Operator which runs its self from a timer"""
bl_idname = "wm.modal_timer_operator"
bl_label = "Modal Timer Operator"
_timer = None
def modal(self, context, event):
C = bpy.context
if event.type in {'RIGHTMOUSE', 'ESC'}:
self.cancel(context)
return {'FINISHED'}
if event.type == 'TIMER':
iFrame = C.scene.frame_current + C.scene.frame_step
if iFrame > C.scene.frame_end: iFrame = C.scene.frame_end
print("Frame %9d of %9d" % (iFrame, C.scene.frame_end))
C.scene.frame_set(iFrame)
if iFrame >= C.scene.frame_end:
self.cancel(context)
when_done()
return {'FINISHED'}
return {'PASS_THROUGH'}
def execute(self, context):
global START_FRAME
START_FRAME = bpy.context.scene.frame_current
wm = context.window_manager
self._timer = wm.event_timer_add(time_step=0.1, window=context.window)
wm.modal_handler_add(self)
return {'RUNNING_MODAL'}
def cancel(self, context):
wm = context.window_manager
wm.event_timer_remove(self._timer)
def register():
bpy.utils.register_class(ModalTimerOperator)
def unregister():
bpy.utils.unregister_class(ModalTimerOperator)
if __name__ == "__main__":
register()
# test call
bpy.ops.wm.modal_timer_operator()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment