dropdown list (EnumProperty) refreshed when object selected

Scripting in Blender with Python, and working on the API

Moderators: jesterKing, stiv

Post Reply
orimouse
Posts: 0
Joined: Wed Mar 20, 2013 1:35 am

dropdown list (EnumProperty) refreshed when object selected

Post by orimouse » Fri May 31, 2013 2:47 pm

Hi everyone,

I'm struggling for a few days with the EnumProperty... Hope someone could give me a hint !

Description:
I have a scene with 2 or more objects.
As the script runs, a panel appears with a dropdown list containing some properties of the current active object.

Problem :
When I select another object, the properties in the list doesn't update : the list still shows the properties of the previous object.

Work around :
I made a button to update the properties list and it works, but it's a bit... uncomfortable to have to click on it everytime you select another object.

Question :
Is there a way to make the list (created with EnumProperty) update by itself ? Like a 'new active object' event or so...
Maybe EnumProperty is the wrong way to achieve this ?

I'll be really thankfull for all your help/suggestions.

:)

CoDEmanX
Posts: 0
Joined: Sun Apr 05, 2009 7:42 pm
Location: Germany

Post by CoDEmanX » Fri May 31, 2013 11:49 pm

supply a callback function for items instead of a sequence of tupels

http://www.blender.org/documentation/bl ... umProperty
I'm sitting, waiting, wishing, building Blender in superstition...

orimouse
Posts: 0
Joined: Wed Mar 20, 2013 1:35 am

Post by orimouse » Sat Jun 01, 2013 2:09 am

Hello,

First, thank you for the link !

So here's the code I got for my example (the scene contains 2 objects, a 'Cube' and a 'Sphere'):

Code: Select all

import bpy
from bpy.props import *

properties = {
    'Cube': [('a', 'a', 'a'), ('b', 'b', 'b'), ('c', 'c', 'c')],
    'Sphere' : [('d', 'd', 'd'), ('e', 'e', 'e'), ('f', 'f', 'f'), ('g', 'g', 'g')]
}

  
def get_properties():
    
    obj = bpy.context.object
    obj_name = obj.name
    bpy.types.Object.Enum = properties[obj_name]

    return bpy.types.Object.Enum
    
def initSceneProperties(scn):
 
    bpy.types.Scene.MyEnum = EnumProperty(items=get_properties(), name="Dynamic enum")
    scn['MyEnum'] = 0
 

 
initSceneProperties(bpy.context.scene)
 
#
#    Menu in UI region
#


class UIPanel(bpy.types.Panel):
     bl_label = 'Dynamic Enum List'
     bl_space_type = 'VIEW_3D'
     bl_region_type = 'UI'
     
     def draw(self, context):
         layout = self.layout
         scn = bpy.context.scene
         
         layout.prop(scn, 'MyEnum')
         
bpy.utils.register_module(__name__)
But I still get the same problem, the list doesn't refresh when active object changes.
I can't figure out where I messed up...

Any idea ?

Thanks again for any help !

CoDEmanX
Posts: 0
Joined: Sun Apr 05, 2009 7:42 pm
Location: Germany

Post by CoDEmanX » Sat Jun 01, 2013 2:51 pm

you're supposed to suppy a callback function, what you do now is supplying the result of a function call - remove the () !
I'm sitting, waiting, wishing, building Blender in superstition...

orimouse
Posts: 0
Joined: Wed Mar 20, 2013 1:35 am

Post by orimouse » Sat Jun 01, 2013 3:44 pm

Hi,

I tried without the () and I got the following ValueError
bpy_struc "Scene" registration error: 'MyEnum' could not register

With () it works but doesn't refresh...

I've found this old thread and I'm now even not sure that EnumProperty can do what I want...

http://blenderartists.org/forum/showthr ... ost1825047

But I could update the EnumProperty list with a button.

With the thread above I'm a little lost...
Is it really possible doing clean dynamic lists with EnumProperty?

:?

CoDEmanX
Posts: 0
Joined: Sun Apr 05, 2009 7:42 pm
Location: Germany

Post by CoDEmanX » Sun Jun 02, 2013 12:10 am

sure it is, but i worry you need to redesign your whole concept.

If every object shall store an arbitrary amount of strings, you should register a CollectionProperty and use the base type bpy.types.PropertyGroup as type. It comes with a StringProperty ("name"), so you don't have to derive a class from PropertyGroup and declare a StringProperty yourself. You have to if you wanna store different property types of course, or if you need more than this one StringProperty.

Code: Select all

bpy.types.Object.your_collection = bpy.props.CollectionProperty(type=bpy.types.PropertyGroup)
Then, you add an item to the collection for every string you wanna store and set the "name" string prop to your string.

If you wanna show all collection entries in an EnumProp added to the UI, you would do something like

Code: Select all

def item_cb(self, context):
    return [(entry.name,)*3 for entry in context.object.your_collection]

EnumProperty(items=item_cb)

Two code examples, about dyn enum prop and collection prop:

http://pastebin.com/813DXRFu
http://pastebin.com/4tbjRXKR
I'm sitting, waiting, wishing, building Blender in superstition...

orimouse
Posts: 0
Joined: Wed Mar 20, 2013 1:35 am

Post by orimouse » Sun Jun 02, 2013 1:05 am

Wow that's perfect ! :D

I'm pretty new to all this and I love exploring and learning python scripting but the possibilities are so huge !!!

I was desperatly looking for some nice examples to understand the concept!

Really, many thanks for all your help!

:D

Post Reply