3
$\begingroup$

This question already has an answer here:

I made a small operator which lets you change the ui_type.

The question is how can I change this menu, not only the layout but also the spawn position? I want it to behave the same way when you click the adjust last operation operator.

import bpy 


class SM_change_area_type(bpy.types.Operator):

    bl_idname = 'sop.sm_change_area_type'
    bl_label = "S.Menu Change Area Type"
    bl_description = 'best description ever'
    bl_options = {'REGISTER', 'UNDO'}

    areas = [
        ("VIEW_3D","View 3D",""),
        ("VIEW","Image Editor",""),
        ("UV","UV Editor",""),

    ]
    #ShaderNodeTree, CompositorNodeTree, TextureNodeTree
    type_enum: bpy.props.EnumProperty(name="Areas", items=areas)
    chose_from_list: bpy.props.BoolProperty(name="Chose area Type:", default=True)
    a_type: bpy.props.StringProperty(name="Change area to:", default='UV')
    test: bpy.props.StringProperty(name="test:")


    def execute(self, context):
        context = bpy.context
        area = context.area

        # check if True: get area type from enum else: get area type from string (string has to be set)
        if self.chose_from_list is True:
            self.a_type = self.type_enum
            self.test = area.ui_type
            if self.a_type == "":
                self.report({'ERROR'}, "'a_type' Not Set Operator Cancelled")
                return {'CANCELLED'}
            else:
                area.ui_type = self.a_type
        else:
            if self.a_type == "":
                self.report({'ERROR'}, "'a_type' Not Set Operator Cancelled")
                return {'CANCELLED'}
            else:
                area.ui_type = self.a_type

        return {'FINISHED'}

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



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



if __name__ == "__main__":
    register()
$\endgroup$

marked as duplicate by Community Mar 31 at 14:49

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

2
+50
$\begingroup$

I guess what you want is a property confirm dialog. You basically just have to add a new 'invoke' and a 'draw' method. Note that I removed == (python strings can be "falsy") as well as bad references like bpy.context in your 'execute' method.

import bpy
from bpy.types import Operator

class WM_OT_my_popup(Operator):
    bl_idname = "custom.my_popup"
    bl_label = "Area Operator"
    bl_options = {'REGISTER'}

    areas = [
        ("VIEW_3D","View 3D",""),
        ("VIEW","Image Editor",""),
        ("UV","UV Editor","")]

    my_enum: bpy.props.EnumProperty(name="Areas", items=areas)
    my_bool: bpy.props.BoolProperty(name="Chose area Type", default=True)
    my_type: bpy.props.StringProperty(name="Change area to", default='UV')

    def execute(self, context):
        area = context.area
        if self.my_bool:
            self.my_type = self.my_enum

            if not self.my_type:
                self.report({'ERROR'}, "")
                return {'CANCELLED'}
            else:
                area.ui_type = self.my_type
        else:
            if not self.my_type:
                self.report({'ERROR'}, "")
                return {'CANCELLED'}
            else:
                area.ui_type = self.my_type

        return {'FINISHED'}

    def invoke(self, context, event):                
        return context.window_manager.invoke_props_dialog(self, width=400)

    def check(self, context):
        return True

    def draw(self, context):
        scn = context.scene
        layout = self.layout
        row = layout.row().prop(self, "my_enum") 
        row = layout.row()
        row.prop(self, "my_bool") 
        row.prop(self, "my_type")


classes = (
    WM_OT_my_popup,
)

def register():
    from bpy.utils import register_class
    for cls in classes:
        register_class(cls)

def unregister():
    from bpy.utils import unregister_class
    for cls in reversed(classes):
        unregister_class(cls)



if __name__ == "__main__":
    register()

    # test call
    bpy.ops.custom.my_popup('INVOKE_DEFAULT') 

Tip: Blender enforces naming conventions as of 2.8x:

The class name convention is: UPPER_CASE_{SEPARATOR}_mixed_case, in the case of a menu the regular expression is: [A-Z][A-Z0-9_]*MT[A-Za-z0-9_]+

Related:

$\endgroup$

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