Created
August 25, 2023 18:41
-
-
Save RenaKunisaki/85b19fa4c0cfcdadfdd555376238bc31 to your computer and use it in GitHub Desktop.
Blender script to resume a bake
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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