import bpy from bpy.props import EnumProperty available_objects = [] def availableObjects(self, context): available_objects.clear() for ob in bpy.data.objects: name = ob.name available_objects.append((name, name, name)) return available_objects class TestCase(bpy.types.Operator): bl_idname = "object.testcase" bl_label = "TestCase" bl_options = {'REGISTER', 'UNDO'} objects = EnumProperty(name="Objects", items = availableObjects)if we hover the mouse over the second or third option we see that the description shows garbage, i.e. the description part of another item!
The really annoying part is that even if we make a full copy of the object's name (with
ob.name[:]
) the problem isn't solved. So probably the internal callback code trashes memory even outside its own allocated memory. def availableObjects(self, context): available_objects.clear() for ob in bpy.data.objects: name = ob.name[:] # a copy, not just a reference available_objects.append((name, name, name)) return available_objectsA way around this is to let the callback just return a list that is filled with values outside the callback code, for example in the code thst is executed when the user clicks on the menu item that selects the addon:
available_objects = [] def availableObjectsInit(self, context): available_objects.clear() for ob in bpy.data.objects: name = ob.name[:] # a copy, not just a reference available_objects.append((name, name, name)) return available_objects class TestCase(bpy.types.Operator): ... stuff omitted ... objects = EnumProperty(name="Objects", items = lambda self,context: available_objects) def menu_func(self, context): availableObjectsInit(self, context) self.layout.operator(TestCase.bl_idname, text="TestCase",icon='PLUGIN') def register(): bpy.utils.register_module(__name__) bpy.types.VIEW3D_MT_object.append(menu_func)This is usable even if the addon changes the number of objects. The only downside is that the code isn't reentrant because in its present form does not guard thread access to the global variable but as far as I know the Blender UI runs as part of a single Python interpreter so there's only one thread, which renders this point moot. The other issue is that it looks ugly, but as long as it works that's a minor issue :-) Note: you might wonder why we need the lambda here but that's because if we would point to just the list here, the list would be empty at the point where the EnumProperty was defined and apparently it makes a copy of that list so it would stay empty.
No comments:
Post a Comment