Iam searching for a method to get a EnumProperty by the type of the object (Lamp, Geo, Camera) thats selected in the viewport.

E.g. If the selected object is a lamp, it would be nice the enum dynamically adds new properties to the existing ones, like Energy and Color.

Here is my Code:

bl_info = {
    "name": "tester",
    "description": "",
    "author": "",
    "version": (0, 0, 1),
    "blender": (2, 7, 0),
    "location": "3D View > Toolbox",
    "warning": "", # used for warning icon and text in addons panel
    "wiki_url": "",
    "tracker_url": "",
    "category": "Test"
    }


import bpy
import re
import math
from mathutils import Vector
from math import pi

from bpy.types import Panel
from bpy.props import (StringProperty,
                       BoolProperty,
                       IntProperty,
                       FloatProperty,
                       FloatVectorProperty,
                       EnumProperty,
                       PointerProperty,
                       )
from bpy.types import (Operator,
                       AddonPreferences,
                       PropertyGroup,
                       )


# ------------------------------------------------------------------------
#    store properties in the active scene
# ------------------------------------------------------------------------

class mySettings(PropertyGroup):

    # apply values to LOC ROT SCL
    TransformationProperty_ = EnumProperty(
        name="Apply Data to:",
        description="Apply Data to attribute.",
        items=(('LOC', "Location", ""),
               ('ROT', "Rotation", ""),
               ('SCL', "Scale", "")),
        default='LOC',
        )


# ------------------------------------------------------------------------
#    myTool in objectmode
# ------------------------------------------------------------------------

class myTool_panel_objectMode:
    bl_label = "myTool"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    #bl_context = "objectmode"

    @classmethod
    def poll(self,context):
        #scene = context.scene
        return context.active_object is not None

    def draw(self, context):
        layout = self.layout
        scene = context.scene
        mytool = scene.myTool

        row = layout.row()
        col = layout.column(align=True)
        rowsub = col.row(align=True)
        rowsub.prop(mytool, "TransformationProperty_", text="")


# ------------------------------------------------------------------------
#     classes for new tab system since 2.7.0
# ------------------------------------------------------------------------

class myTool_ObjectMode(Panel, myTool_panel_objectMode):
    bl_category = "Test"
    bl_idname = "my_objectmode"
    bl_context = "objectmode"


# ------------------------------------------------------------------------
# register and unregister functions
# ------------------------------------------------------------------------

def register():
    bpy.utils.register_module(__name__)
    bpy.types.Scene.myTool = PointerProperty(type=mySettings)

def unregister():
    bpy.utils.unregister_module(__name__)
    bpy.types.Scene.myTool

if __name__ == "__main__":
    register()

Thanks in Advance,
Christian


Thanks for this great explanation CoDEmanX! Code works nicely and logic makes sense to me. Also thanks for your BTW - never thougt about Blender/Python conventions - nice to know.

For those who wants a multiple selection callback, Ive updated the code a bit:

bl_info = {
    "name": "tester",
    "description": "",
    "author": "",
    "version": (0, 0, 3),
    "blender": (2, 70, 0),
    "location": "3D View > Toolbox",
    "warning": "", # used for warning icon and text in addons panel
    "wiki_url": "",
    "tracker_url": "",
    "category": "Test"
}

import bpy
import re
import math
from mathutils import Vector
from math import pi

from bpy.props import (StringProperty,
                       BoolProperty,
                       IntProperty,
                       FloatProperty,
                       FloatVectorProperty,
                       EnumProperty,
                       PointerProperty,
                       )
from bpy.types import (Panel,
                       Operator,
                       AddonPreferences,
                       PropertyGroup,
                       )


# ------------------------------------------------------------------------------------------------
# get object type list
# ------------------------------------------------------------------------------------------------

def get_object_type_list(object_list):
    objectTypes = []
    for i in object_list:
        objectTypes.append(bpy.data.objects[i.name].type)

    return list(set(objectTypes))

# ------------------------------------------------------------------------
#    store properties in the active scene
# ------------------------------------------------------------------------

def my_settings_callback(scene, context):

    items = [
        ('LOC', "Location", ""),
        ('ROT', "Rotation", ""),
        ('SCL', "Scale", ""),
    ]

    # get selection
    selection = bpy.context.selected_objects

    # get selection type list
    selection_types = get_object_type_list(selection)

    if len(selection_types) == 1:

        # check for lamps
        if selection_types[0] == 'LAMP':
            items.append(('NRG', "Energy", ""))
            items.append(('COL', "Color", ""))

    return items


class MySettings(PropertyGroup):

    # apply values to LOC ROT SCL
    transform = EnumProperty(
        name="Apply Data to:",
        description="Apply Data to attribute.",
        items=my_settings_callback
        )


# ------------------------------------------------------------------------
#    myTool in objectmode
# ------------------------------------------------------------------------

class OBJECT_PT_my_panel(Panel):
    bl_idname = "OBJECT_PT_my_panel"
    bl_label = "My Panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "TESTER"
    bl_context = "objectmode"

    @classmethod
    def poll(self,context):
        return context.object is not None

    def draw(self, context):
        layout = self.layout
        scene = context.scene
        mytool = scene.my_tool

        layout.prop(mytool, "transform", text="")

        # print selected property
        print (mytool.transform)


# ------------------------------------------------------------------------
# register and unregister functions
# ------------------------------------------------------------------------

def register():
    bpy.utils.register_module(__name__)
    bpy.types.Scene.my_tool = PointerProperty(type=MySettings)

def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.Scene.my_tool

if __name__ == "__main__":
    register()

Thanks again,
Christian

up vote 10 down vote accepted

You can supply EnumProperty() with a callback function for the items-argument and create a list of tuples based on context:

bl_info = {
    "name": "tester",
    "description": "",
    "author": "",
    "version": (0, 0, 2),
    "blender": (2, 70, 0),
    "location": "3D View > Toolbox",
    "warning": "", # used for warning icon and text in addons panel
    "wiki_url": "",
    "tracker_url": "",
    "category": "Test"
}

import bpy
import re
import math
from mathutils import Vector
from math import pi

from bpy.props import (StringProperty,
                       BoolProperty,
                       IntProperty,
                       FloatProperty,
                       FloatVectorProperty,
                       EnumProperty,
                       PointerProperty,
                       )
from bpy.types import (Panel,
                       Operator,
                       AddonPreferences,
                       PropertyGroup,
                       )


# ------------------------------------------------------------------------
#    store properties in the active scene
# ------------------------------------------------------------------------

def my_settings_callback(scene, context):

    items = [
        ('LOC', "Location", ""),
        ('ROT', "Rotation", ""),
        ('SCL', "Scale", ""),
    ]

    ob = context.object
    if ob is not None:
        if ob.type == 'LAMP':
            items.append(('NRG', "Energy", ""))
            items.append(('COL', "Color", ""))

    return items

class MySettings(PropertyGroup):

    # apply values to LOC ROT SCL
    transform = EnumProperty(
        name="Apply Data to:",
        description="Apply Data to attribute.",
        items=my_settings_callback
        )


# ------------------------------------------------------------------------
#    myTool in objectmode
# ------------------------------------------------------------------------

class OBJECT_PT_my_panel(Panel):
    bl_idname = "OBJECT_PT_my_panel"
    bl_label = "My Panel"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "Tools"
    bl_context = "objectmode"

    @classmethod
    def poll(self,context):
        return context.object is not None

    def draw(self, context):
        layout = self.layout
        scene = context.scene
        mytool = scene.my_tool

        layout.prop(mytool, "transform", text="")


# ------------------------------------------------------------------------
# register and unregister functions
# ------------------------------------------------------------------------

def register():
    bpy.utils.register_module(__name__)
    bpy.types.Scene.my_tool = PointerProperty(type=MySettings)

def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.Scene.my_tool

if __name__ == "__main__":
    register()

Note that if you select a Lamp, set the property to e.g. Color and then select a non-lamp object, the enum will show no label in the panel, but return LOC (the first item) to a script. If you select a Lamp object again, it will return COL again!

You can not set a default item if a dynamic enum is used.

http://www.blender.org/documentation/blender_python_api_2_70a_release/bpy.props.html#bpy.props.EnumProperty

BTW:

  • Your Blender version tuple is wrong, it needs to be (2, 70, 0)
  • You don't need an extra class to support vertical tabs
  • In unregister(), the del keyword is missing to remove the PointerProperty
  • Blender / Python conventions are to use snake_case for names like bl_idname, but CamelCase for e.g. classes (with capital first letter)

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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