0
$\begingroup$

I have writen a large Python script in Blender that does automatic sewing. First I will import a 3D-body, then import a T-shirt that is meant to be sewed. Then I place the body between the front & back of the T-shirt, assign cloth and collision modifiers.

Until this step all is good, then I play the animation using the code below, and intended to wait for the animation to stop at frame 30 then only continue execute the function after_sew().

def sew(body_name, garment_name):
    body_obj = bpy.data.objects[body_name]
    garment_obj = bpy.data.objects[garment_name]
    s = bpy.context.scene
    s.frame_start = 1
    s.frame_end = 40
    s.frame_current = 1
    def stop_playback(scene):
        if scene.frame_current == 30:
            bpy.ops.screen.animation_cancel(restore_frame=False)
            end = time()
            print(f"Sewing completed in {round(end-start,2)} seconds.")
    bpy.app.handlers.frame_change_post.append(stop_playback)
    bpy.ops.screen.animation_play()

def after_sew():
    print("Sewing done")
    # Some other code

# Sewing
print("Now sewing... Please wait a few seconds.")
start = time()
sew(body_name, garment_name)
after_sew()

However, it is not going as expected. The script will call the sew() function, then execute after_sew() at the same time as animation is going. So I'm not able to get my desired output (at frame 30) in the after_sew() function.

I have searched for this, but this is about stopping animation after a certain time. For my case, I won't know how much time will be needed for animation depends on user device. Besides this I haven't found any relevant issue on BlenderSE. Maybe this is a really easy configuration but I just didn't manage to get it.

I also searched for this, no answer is provided except the author himself, but I don't really know how to use bake option.

$\endgroup$

1 Answer 1

1
$\begingroup$

It's looks like that you just need to invoke after_sew() in stop_playback:

def sew(body_name, garment_name):
    ....
    def stop_playback(scene):
        if scene.frame_current == 30:
            bpy.ops.screen.animation_cancel(restore_frame=False)
            end = time()
            print(f"Sewing completed in {round(end-start,2)} seconds.")
            after_sew() <---------------
    ....

def after_sew():
    ....

# Sewing
print("Now sewing... Please wait a few seconds.")
start = time()
sew(body_name, garment_name)

after_sew() goes after sew() as you want. But that you do not want is that stop_playback() invokes later on a frame change.

$\endgroup$
5
  • $\begingroup$ Hi @Crantisz thanks for your comment. What if I have more than one function after it? I would have after_sew() for beautify the shirt, and export() for export the model, for example. Is it possible to manipulate the handle so that the script won't continue before handle finish? $\endgroup$ Sep 28, 2021 at 8:08
  • $\begingroup$ and I kind of want to put all function after sewing below the sew() function instead of putting it in the handler function. That would makes the function flow more systematically. $\endgroup$ Sep 28, 2021 at 8:09
  • $\begingroup$ This is how it works. Blender launches sew(), then after_sew(), then after some time frame_change_post triggers, and stop_playback() invokes 30 times, until animation stops by your script. $\endgroup$
    – Crantisz
    Sep 28, 2021 at 8:13
  • 1
    $\begingroup$ So after_sew() goes after sew() as you want. But that you do not want is that stop_playback() invokes later on a frame change. $\endgroup$
    – Crantisz
    Sep 28, 2021 at 8:16
  • $\begingroup$ I see, thanks for you help! $\endgroup$ Sep 28, 2021 at 8:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .