2

I baked a very heavy simulation that toke like 1 and an half hour, but I forgot that simulation had to start from frame 100 because, before starting, there should be some camera movements, but I forgot it and now simulation starts from frame 0 and I haven't time. Should I bake it again from frame 100 or is there a way I can start the animation from frame -100?

Arisyn ILY
  • 115
  • 6

1 Answers1

3

Update: the previous version actually didn't work (because I forgot the most important part, frame_set()), sorry for any confusions caused.

Enable negative frames in your project: Selecting Negative frames in timeline, then click on the stopwatch ⏱ icon to be able to preview those frames in viewport: , then add necessary animations and use the script below.

import bpy

start = bpy.context.scene.frame_preview_start # or just input the starting frame manually here end = -1 # or maybe you want bpy.context.scene.frame_end or frame_preview_end renders_path = "/tmp/" filename = "{}.png" negative_char = "_" # minus sign sorts poorly together with positive numbers

class Negative_Render(bpy.types.Operator): """Render negative frames without hanging the interface adapted code from https://blender.stackexchange.com/q/71454/60486 """ bl_idname = "render.negative" bl_label = "Render negative frames"

# Define some variables to register
_timer = None
current_frame = start
last_frame = end
stop = None
rendering = None

# Define the handler functions. I use pre and post to know if Blender "is rendering"
def pre(self, scene, context=None):
    self.rendering = True

def post(self, scene, context=None):
    self.current_frame += 1
    self.rendering = False

def cancelled(self, scene, context=None):
    self.stop = True

def add_handlers(self, context):
    bpy.app.handlers.render_pre.append(self.pre)
    bpy.app.handlers.render_post.append(self.post)
    bpy.app.handlers.render_cancel.append(self.cancelled)

    # The timer gets created and the modal handler is added to the window manager
    self._timer = context.window_manager.event_timer_add(0.1, window=context.window)
    context.window_manager.modal_handler_add(self)

def remove_handlers(self, context):
    bpy.app.handlers.render_pre.remove(self.pre)
    bpy.app.handlers.render_post.remove(self.post)
    bpy.app.handlers.render_cancel.remove(self.cancelled)
    context.window_manager.event_timer_remove(self._timer)

def execute(self, context):
    # Define the variables during execution. This allows
    # to define when called from a button
    self.stop = False
    self.rendering = False
    self.add_handlers(context)
    return {"RUNNING_MODAL"}

def modal(self, context, event):
    if event.type == 'TIMER': # This event is signaled every 100 ms
                              # and will start the render if available
        if self.stop:
            # Cancelled:
            self.remove_handlers(context)
            return {"CANCELLED"}
        if self.current_frame > end:
            # Finished:
            self.remove_handlers(context)
            return {"FINISHED"}
        if self.rendering is False: # Nothing is currently rendering.
                                      # Proceed to render.
            sc = context.scene
            name = negative_char if self.current_frame < 0 else ""
            name += f"{abs(self.current_frame):03d}"
            sc.render.filepath = renders_path + filename.format(name)
            sc.frame_set(self.current_frame)
            bpy.ops.render.render("INVOKE_DEFAULT", write_still=True)

    return {"PASS_THROUGH"}
    # This is very important! If we used "RUNNING_MODAL", this new modal function
    # would prevent the use of the X button to cancel rendering, because this
    # button is managed by the modal function of the render operator,
    # not this new operator!

def register(): bpy.utils.register_class(Negative_Render)

def unregister(): bpy.utils.unregister_class(Negative_Render)

if name == "main": register() bpy.ops.render.negative() # Test call

I adapted the script from:

Is it possible to make a sequence of renders and give the user the option to cancel the process through the UI at any given time?

Markus von Broady
  • 36,563
  • 3
  • 30
  • 99