In my addon panel, how can I have an object selection box? And what data type would I use to store the the selected object?
It should look like this:
In my addon panel, how can I have an object selection box? And what data type would I use to store the the selected object?
It should look like this:
Building off of the answer by @CoDEmanX, here's a simple example:
import bpy
class OBJECT_PT_HelloWorldPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Hello World Panel"
bl_idname = "OBJECT_PT_hello"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
def draw(self, context):
layout = self.layout
scene = context.scene
layout.prop_search(scene, "theChosenObject", scene, "objects")
def register():
bpy.utils.register_module(__name__)
bpy.types.Scene.theChosenObject = bpy.props.StringProperty()
def unregister():
bpy.utils.unregister_module(__name__)
del bpy.types.Object.theChosenObject
if __name__ == "__main__":
register()
which gives:
The prop_search
command lets the user choose one item from a bpy "collection" (in this case, the collection context.scene.objects
) and saves the name of that item into a string (the string context.scene.theChosenObject
).
If you need to use the object in a different part of script. Use
scene = context.scene
obj = scene.objects[scene.theChosenObject]
By the way, if you had wanted a "Materials Selection Box", you could have used
layout.prop_search(scene, "theChosenMaterial", bpy.data, "materials")
and similarly for textures, meshes, or any other bpy collection.
We are only saving the name of the object (for example, scene.theChosenObject
could be 'Cube'
). If the user changes the name of the object, scene.theChosenObject
will not change and you will not be able to use it to reference the object anymore.
See here for more on this problem.
scene.object[scene.theChosenObject]
rather than scene.object(scene.theChosenObject)
?
$\endgroup$
Commented
Mar 23, 2014 at 15:15
unregister
should del
property from the Scene
, not from the Object
? i.e del bpy.types.Scene.theChosenObject
$\endgroup$
Use prop_search(), a StringProperty
and a CollectionProperty
.
import bpy
enum_items = (
('FOO', 'Foo', ''),
('BAR', 'Bar', '')
)
class HelloWorldPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Hello World Panel"
bl_idname = "OBJECT_PT_hello"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
def draw(self, context):
layout = self.layout
obj = context.object
col = layout.column()
col.prop_search(context.scene, "coll_string", context.scene, "coll", icon='OBJECT_DATA')
def populate_coll(scene):
bpy.app.handlers.scene_update_pre.remove(populate_coll)
scene.coll.clear()
for identifier, name, description in enum_items:
scene.coll.add().name = name
def register():
bpy.utils.register_module(__name__)
bpy.types.Scene.coll = bpy.props.CollectionProperty(
type=bpy.types.PropertyGroup
)
bpy.types.Scene.coll_string = bpy.props.StringProperty()
# Hack for testing
bpy.app.handlers.scene_update_pre.append(populate_coll)
def unregister():
bpy.utils.unregister_module(__name__)
del bpy.types.Scene.coll
del bpy.types.Scene.coll_string
if __name__ == "__main__":
register()
For limitations please read:
Is it possible to use bpy.props.PointerProperty to store a pointer to an object?
Here is an updated answer built on previously accepted answer.
Since 2.79, you can use bpy.props.PointerProperty
to store references to blender data blocks.
You can then use prop
instead of prop_search
for selection box. prop_search
is still useful if you want to select from a specific collection.
This solves the problem of modifying the object ( for example if you rename the object, the property will be updated). Also, deleting the object will not delete its data as, long as it is referenced somewhere. After all its references are removed, it gets deleted on file reload.
import bpy
class OBJECT_PT_HelloWorldPanel(bpy.types.Panel):
"""Creates a Panel in the Object properties window"""
bl_label = "Hello World Panel"
bl_idname = "OBJECT_PT_hello"
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "object"
def draw(self, context):
layout = self.layout
layout.prop(context.scene, "theChosenObject")
def register():
bpy.utils.register_module(__name__)
bpy.types.Scene.theChosenObject = PointerProperty(type=bpy.types.Object)
def unregister():
bpy.utils.unregister_module(__name__)
del bpy.types.Object.theChosenObject
if __name__ == "__main__":
register()