在 Blender 完全加载后执行脚本

Execute script after Blender is fully loaded

如何在 Blender 完全加载后自动执行 python 脚本?

上下文

我的脚本根据种子生成场景。我想创建几千个图像,但由于 Blender 在一百代左右后泄漏内存,所以一切都变得非常慢并最终崩溃。我想通过每次会话仅创建 x 个图像并在每次会话后完全重新启动 Blender 来缓解问题。

问题

如果我手动加载 blend 文件并单击脚本编辑器中的播放按钮,一切都会按预期进行。当我尝试在启动后调用脚本时,它在 add_curve_spirals.py 行 184 中崩溃,因为 context.space_dataNone

由于手动启动脚本工作正常,问题是 Blender 处于某种错误状态。使用或不使用 GUI (--background) 启动它都不会影响这一点。

失败的解决方案

以上是我发现的自动执行脚本的所有方法。在每种情况下,脚本似乎都执行得太早/处于错误状态,并且都以相同的方式失败。

我想强调的是脚本不是这里的问题。即使我可以绕过特定行,也可能会出现许多类似的问题,我不想重写整个脚本。那么在正确的状态下自动调用它的最佳方法是什么?

事实证明,问题出在执行上下文上。这在手动调用定时事件后变得很清楚,例如场景完全加载后,定时事件仍然在错误的上下文中执行。

由于崩溃发生在 add_curve_spirals 插件中,解决方案是提供一个上下文覆盖运算符调用。我脚本的其余部分对上下文并不同样敏感,但工作得很好。

我不清楚我究竟应该如何覆盖上下文,但这目前有效(从互联网的其他部分收集,所以我不了解所有细节):

def get_context():
    # create a context that works when blender is executed from the command line.
    idx = bpy.context.window_manager.windows[:].index(bpy.context.window)
    window = bpy.context.window_manager.windows[idx]
    screen = window.screen
    views_3d = sorted(
            [a for a in screen.areas if a.type == 'VIEW_3D'],
            key=lambda a: (a.width * a.height))
    
    a = views_3d[0]
    # override
    o = {"window" : window,
         "screen" : screen,
         "area" : a,
         "space_data": a.spaces.active,
         "region" : a.regions[-1]
    }
    return o

最终调用:bpy.ops.curve.spirals(get_context(), spiral_type='ARCH', radius = radius, turns = turns, dif_z = dif_z, ...