自定义结束模态运算符 Blender Python

Custom End a Modal operator Blender Python

我有以下代码:

class audio_visualizer_create(bpy.types.Operator):
    bl_idname = "myop.audio_visualizer_create"
    bl_label = "Audio Visualizer Create"
    bl_description = ""
    bl_options = {"REGISTER"}


    @classmethod
    def poll(cls, context):
        return True

    def invoke(self, context, event):
        context.window_manager.modal_handler_add(self)
        scene = bpy.context.scene




        ##VARIABLES
        type = scene.audio_visualizer_type
        subtype = scene.audio_visualizer_subtype
        axis = scene.audio_visualizer_axis
        object = scene.audio_visualizer_other_sample_object
        scalex = scene.audio_visualizer_sample_object_scale[0]
        scaley = scene.audio_visualizer_sample_object_scale[1]
        scalez = scene.audio_visualizer_sample_object_scale[2]
        object = scene.audio_visualizer_other_sample_object
        bars = scene.audio_visualizer_bars_number

        print(bars)
        print(scaley)
        print(scene.audio_visualizer_bars_distance_weight)

        ##GETTING THE OBJECT
        if object == "OTHER":
            object = scene.audio_visualizer_other_sample_object

        ##Setting Up the bars
        total_lenght = (scaley*bars) + (scene.audio_visualizer_bars_distance_weight/100*(bars-1))

        for i in range(0, bars):
            bpy.ops.mesh.primitive_cube_add(radius=1, view_align=False, enter_editmode=False, location=(0, 0, 0), layers=bpy.context.scene.layers)
            bpy.context.object.scale = (scalex,scaley,scalez)
            bpy.context.object.location.y = total_lenght/bars*i


        is_finished = True

At this Point i want to finish the Modal Operator.

        return {"RUNNING_MODAL"}

    def modal(self, context, event):


        if event.type in {"ESC"}:
            print("You've Cancelled The Operation.")

            return {"CANCELLED"}

        if event.type in {"MIDDLEMOUSE", "RIGHTMOUSE", "LEFTMOUSE"}:
            return {"FINISHED"}

        return {"FINISHED"}

但是如果我把 return {"FINISHED"} 而不是 return {"RUNNING_MODAL"} blender 崩溃或冻结,有没有办法结束操作员?

首先,您展示的示例并没有从模态运算符中获益。模态运算符允许 3DView 在用户输入改变运算符的操作时更新。模态运算符的一个示例是刀工具,一旦启动它就会根据用户输入更改最终结果,同时它是 运行.

您的示例存在的问题是您在调用和模态中执行了错误的任务。 invoke() 应调用 modal_handler_add() 和 return {"RUNNING_MODAL"} 以表示应在运算符仍为 运行 时调用 modal()modal() 应该执行数据更改,returning {"RUNNING_MODAL"} 当它还在工作时 {"FINISHED"}{"CANCELLED"} 当它完成时。

对于模态运算符,modal() 就像一个循环,每次调用模态都会执行部分任务,并在每次调用之间更新视口并收集用户输入。您向运算符添加属性 class 以保存每个模态调用之间的状态信息。

移动鼠标时添加立方体的简单模态示例 -

class audio_visualizer_create(bpy.types.Operator):
    bl_idname = "myop.audio_visualizer_create"
    bl_label = "Audio Visualizer Create"
    bl_options = {"REGISTER"}

    first_mouse_x = bpy.props.IntProperty()
    first_value = bpy.props.FloatProperty()

    def modal(self, context, event):
        delta = 0
        if event.type == 'MOUSEMOVE':
            delta = event.mouse_x - self.first_mouse_x
        elif event.type in ['LEFTMOUSE','RIGHTMOUSE','ESC']:
            return {'FINISHED'}

        for i in range(delta//5):
            bpy.ops.mesh.primitive_cube_add(radius=1)
            s = i*0.1
            bpy.context.object.scale = (s,s,s)
            bpy.context.object.location.y = i

        return {"RUNNING_MODAL"}

    def invoke(self, context, event):
        self.first_mouse_x = event.mouse_x
        self.first_value = 0.0
        context.window_manager.modal_handler_add(self)

        return {"RUNNING_MODAL"}

此示例中的缺陷 - 每次调用 modal() 时,for 循环都会在每个位置创建一个立方体,从而导致在每个位置创建多个立方体。