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
$\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 '21 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 '21 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 '21 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 '21 at 8:16
  • $\begingroup$ I see, thanks for you help! $\endgroup$ Sep 28 '21 at 8:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.