I have created a panel in the Properties area in which the user can specify various parameters and then press a button to create the object. I am trying to write a Python code to allow the user to modify an object that was previously created using either the same panel or a new modify object panel. Two parts of this task are giving me trouble:
- Identifying the object that has been selected. The problem is that if I click on the screen so that no object is selected, when I do bpy.context.active_object, I still get the most recent object selected. Also, if I deselect all the objects using bpy.context.active_object.select_set(False), I still get the last object selected as the active object. If I can determine whether or not an object is selected, I can determine whether or not to edit an object or create a new object.
- If an object has been selected and is going to be modified, I would like the geometric properties of that object to appear in the panel. I can't retrieve the properties of a selected object in a draw method, so I am thinking that a modal operator may be the answer. I am including my code with a simple operator and a panel. After I create the operator, the modal operator will respond the next time I click on the object, but the code returns 'FINISHED', so it only detects selecting the object once and then, even if I modify the scene properties, they are displayed in the panel.
Here is my code:
import bpy from bpy.props import FloatProperty bpy.types.Scene.length = bpy.props.FloatProperty(name = "length",default = 2) bpy.types.Scene.height = bpy.props.FloatProperty(name = "height",default = 1) bpy.types.Scene.width = bpy.props.FloatProperty(name = "width",default = 1) class DrawBlock(bpy.types.Operator): """A rectangular prism""" bl_idname = "myops.draw_block" bl_label = "Edit Block" bl_description = "Draw a rectangular prism" bl_options = {'REGISTER', 'UNDO'} height: FloatProperty (name="height") length: FloatProperty (name="length") width: FloatProperty (name="width") def new_block(self,context): width = bpy.context.scene.width height = bpy.context.scene.height length = bpy.context.scene.length bpy.ops.mesh.primitive_cube_add() obj=bpy.context.active_object obj.dimensions=(width,length,height) obj.location.z=obj.location.z+height/2 obj.name="Block" def execute(self,context): obj = bpy.context.active_object if obj: w = bpy.context.scene.width h = bpy.context.scene.height length = bpy.context.scene.length obj.dimensions=(w,length,h) else: self.new_block(context) return {'FINISHED'} def modal(self, context, event): obj=bpy.context.active_object if obj: print("object selected: ",obj) bpy.context.scene.width=obj.dimensions.x bpy.context.scene.length=obj.dimensions.y bpy.context.scene.height=obj.dimensions.z return {'FINISHED'} elif event.type in {'RIGHTMOUSE', 'ESC'}: print("cancelled operation") return {'CANCELLED'} else: return {'PASS_THROUGH'} return {'RUNNING_MODAL'} def invoke(self,context,event): print("inboke block") self.new_block(context) context.window_manager.modal_handler_add(self) return{'RUNNING_MODAL'} class SCENE_PT_Build(bpy.types.Panel): """Creates a Panel in the scene context of the properties editor""" bl_label = "Build Menu" bl_idname = "SCENE_PT_build" bl_space_type = 'PROPERTIES' bl_region_type = 'WINDOW' bl_context = "scene" def draw(self, context): layout = self.layout scene = context.scene obj = context.active_object row=layout.row() row.label(text="block geometry:") row=layout.row() row.prop(scene, "length") row=layout.row() row.prop(scene, "width") row = layout.row() row.prop(scene, "height") row=layout.row() button_text="New Block" if obj: buttom_text="Edit Block" row.operator("myops.draw_block",text=button_text) def register(): bpy.utils.register_class(SCENE_PT_Build) bpy.utils.register_class(DrawBlock) def unregister(): bpy.utils.unregister_class(DrawBlock) bpy.utils.unregister_class(SCENE_PT_Build) if __name__ == "__main__": register() I am not sure why the line obj=context.object does not seem to get any objects. I think that a similar line in my real code does.
I am happy to learn about more effective ways of accomplishing this. I have tried using the adjust last operation menu, but I think I have too many parameters for that to be worthwhile.