2
$\begingroup$

Fellow pythons, greetings. I am trying to create a dynamic Enum property that lists all objects on the scene with a certain custom property. However, whenever a new object is created on the scene (and thus enum is changed automatically including the order of the items in it), it shuffles the values of already selected properties and breaks my whole script workflow. Is there a way to avoid that or use anything else to perform a similar task?

Here is my code:

###############################
## Portal plane
###############################

def GetGroupObjectsReferences(self, context):

    groups = []
    groups.append(('0', "None", "")) # setting a default entry as a first element of our enum

    for obj in bpy.context.scene.objects:
        if obj.WowWMOGroup.Enabled:
            groups.append((obj.name, obj.name, ""))

    return groups

''' 
def UpdateFirstGroupObjectReference(self, context):

    if context.object.WowPortalPlane.First == context.object.WowPortalPlane.Second and context.object.WowPortalPlane.First != '0':
        context.object.WowPortalPlane.Second = '0'          

def UpdateSecondGroupObjectReference(self, context):

    if context.object.WowPortalPlane.Second == context.object.WowPortalPlane.First and context.object.WowPortalPlane.Second != '0':
        context.object.WowPortalPlane.First = '0'
'''


class WowPortalPlanePanel(bpy.types.Panel):
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"
    bl_label = "Wow Portal Plane"
    bl_options = {'DEFAULT_CLOSED'}

    def draw_header(self, context):
        layout = self.layout
        self.layout.prop(context.object.WowPortalPlane, "Enabled")

    def draw(self, context):
        layout = self.layout
        row = layout.row()
        layout.enabled = context.object.WowPortalPlane.Enabled
        self.layout.prop(context.object.WowPortalPlane, "First")
        self.layout.prop(context.object.WowPortalPlane, "Second")     

    @classmethod
    def poll(cls, context):
        return (context.object is not None and context.object.data is not None and isinstance(context.object.data,bpy.types.Mesh))

class WowPortalPlanePropertyGroup(bpy.types.PropertyGroup):
    Enabled = bpy.props.BoolProperty(name="", description="Enable wow WMO group properties")
    First = bpy.props.EnumProperty(items=GetGroupObjectsReferences, name="First group", description="First group")
    Second = bpy.props.EnumProperty(items=GetGroupObjectsReferences, name="Second group", description="Second group")
    PortalID = bpy.props.IntProperty(name="Portal's ID", description="Portal ID")

def RegisterWowPortalPlaneProperties():
    bpy.types.Object.WowPortalPlane = bpy.props.PointerProperty(type=WowPortalPlanePropertyGroup)

def UnregisterWowPortalPlaneProperties():
    bpy.types.Object.WowPortalPlane = None

Thank you in advance for help.

$\endgroup$
1
$\begingroup$

Since Blender 2.79 you can do the following.

###############################
## Portal plane
###############################

def is_wowgroup_enabled(self, obj):
    return obj.WowWMOGroup.Enabled


class WowPortalPlanePanel(bpy.types.Panel):
    bl_space_type = "PROPERTIES"
    bl_region_type = "WINDOW"
    bl_context = "object"
    bl_label = "Wow Portal Plane"
    bl_options = {'DEFAULT_CLOSED'}

    def draw_header(self, context):
        layout = self.layout
        self.layout.prop(context.object.WowPortalPlane, "Enabled")

    def draw(self, context):
        layout = self.layout
        row = layout.row()
        layout.enabled = context.object.WowPortalPlane.Enabled
        self.layout.prop(context.object.WowPortalPlane, "First")
        self.layout.prop(context.object.WowPortalPlane, "Second")     

    @classmethod
    def poll(cls, context):
        return (context.object is not None and context.object.data is not None and isinstance(context.object.data,bpy.types.Mesh))


class WowPortalPlanePropertyGroup(bpy.types.PropertyGroup):
    Enabled = bpy.props.BoolProperty(name="", description="Enable wow WMO group properties")
    First = bpy.props.PointerProperty(type=bpy.types.Object, poll=is_wowgroup_enabled, name="First group", description="First group")
    Second = bpy.props.PointerProperty(type=bpy.types.Object, poll=is_wowgroup_enabled, name="Second group", description="Second group")
    PortalID = bpy.props.IntProperty(name="Portal's ID", description="Portal ID")


def RegisterWowPortalPlaneProperties():
    bpy.types.Object.WowPortalPlane = bpy.props.PointerProperty(type=WowPortalPlanePropertyGroup)


def UnregisterWowPortalPlaneProperties():
    bpy.types.Object.WowPortalPlane = None
$\endgroup$
  • $\begingroup$ this is awesome - in the documentation of the "poll" attribute for PointerProperty (docs.blender.org/api/2.79/bpy.props.html) i cannot find what the first argument refers to. is that the propertygroup or the original object? $\endgroup$ – IARI Jun 4 '18 at 11:04
0
$\begingroup$

Got an explanation and fix :

Blender stores enum properties as an integer internally. If you specify a list of items, the integer values will just be the location of the item in the list, which can change if you change the number of items. This is not considered a bug. Possible solutions are:

  • Explicitly specify an unique integer value for each item that you can guarantee stays the same, for example: ('NAME', 'Name', 'A description', 35)
  • Use a StringProperty instead, perhaps combined with prop_search to show a list of items in the UI.
  • In the upcoming Blender 2.79, PointerProperty will support pointing to datablocks (D113).

(from https://developer.blender.org/T51452)

$\endgroup$

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.