2
$\begingroup$

I have a simple EnumProperty with let's say two buttons. Now i want to create a primitive with one of the buttons. But a click at the button does nothing. There is a bit missing. The operator needs to be executed. And i cannot find a code example how to do so.

How do i execute an operator from an EnumProperty? How do i give those buttons a functionality now?

import bpy

class LayoutDemoPanel(bpy.types.Panel):
    bl_label = "Test"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'

    def draw(self, context):
        layout = self.layout

        layout.label(text="Enum prop")

        scene = context.scene
        layout.prop(scene, "my_enum", expand=True)


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

    bpy.types.Scene.my_enum = bpy.props.EnumProperty(
            name = "My enum",
            description = "My enum description",
            items = [
                ("mesh.primitive_cube_add", "Cube", "Create a cube"),
                ("mesh.primitive_shpere_add", "Sphere", "Create a Sphere"),              
            ]
        )

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

    bpy.types.Scene.my_enum


if __name__ == "__main__":
    register()

enter image description here

$\endgroup$
  • $\begingroup$ An EnumProperty in Blender contains at least three sections. The first one is the unique ID, which is fed back to you if you ask for the value of it. The second one is the Label, the third one the description. So if you look at your code, your enumProp just has an ID which is by coincidence a path to an operator. But for Blender, this is just a string, it does nothing at all. $\endgroup$ – aliasguru Jan 7 '17 at 9:44
  • $\begingroup$ Yes, i realized this already. And my question is how do i tell Blender to do something here :) $\endgroup$ – Tiles Jan 7 '17 at 9:46
  • $\begingroup$ To make Blender do something on a change of the property, you could use the update or set functions: EnumProperty(items = [('ID', 'label', 'description')], update=myOwnUpdateMethod). But a much better way would be to write an own operator and place it as a button below the enum. $\endgroup$ – aliasguru Jan 7 '17 at 9:47
  • $\begingroup$ Examples are here: blender.org/api/blender_python_api_2_78a_release/… $\endgroup$ – aliasguru Jan 7 '17 at 9:50
  • $\begingroup$ Which did not help me. And so my question is how do i tell Blender to do something here :) - Update, what exactly does need to stand here when i want to create a cube? - The second option is no option really. I want the user to click at the enum buttons, not at buttons below. $\endgroup$ – Tiles Jan 7 '17 at 9:56
4
$\begingroup$

Try this

The following script basically does what you want, although I stick to my recommendation to NOT add primitives based on changes of enumerations. Those changes are also tracked when you set the enum value through python, so you might run into real nightmare further down the road. This is only one possible reason for using a dedicated operator with a button that runs it, but in the end it's up to you.

The script here is only modified in three details compared to your's:

  • I've added the update_enum method at the beginning, calling the operator
  • I've corrected a spelling mistake for the operator call to the uv_sphere_add function
  • I've added the call to the update_enum() function in your EnumProperty

Besides that, the code is the same as yours. Note that in case of the update_enum function, self is already the current scene, so I can happily access the current enum value using self.my_enum.

import bpy

def update_enum(self, context):
    # self = current scene in an EnumProperty callback!
    print(self.my_enum)
    eval('bpy.ops.%s()' % self.my_enum)


class LayoutDemoPanel(bpy.types.Panel):
    bl_label = "Test"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'

    def draw(self, context):
        layout = self.layout

        layout.label(text="Enum prop")

        scene = context.scene
        layout.prop(scene, "my_enum", expand=True)


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

    bpy.types.Scene.my_enum = bpy.props.EnumProperty(
            name = "My enum",
            description = "My enum description",
            items = [
                ("mesh.primitive_cube_add", "Cube", "Create a cube"),
                ("mesh.primitive_uv_sphere_add", "Sphere", "Create a Sphere"),              
            ],
            update=update_enum
        )

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

    bpy.types.Scene.my_enum


if __name__ == "__main__":
    register()
$\endgroup$
  • $\begingroup$ Great example, many thanks for the effort :) - Adding the primitives was just a test case. And i might follow your recommendation. Really looks like trouble ahead for what i wanted it to use. Nevertheless, Question answered. Thanks :) $\endgroup$ – Tiles Jan 7 '17 at 11:34

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.