I am building an add-on and here is a skeleton of the same with the relevant parts (it is fully functional, you can just copy-paste the code given below and test it yourself). I am running into issues when I try to adjust some parameters of the operator from Adjust Last Operation (or from the operator box that appears in the bottom-left corner after the operator has just run).
What this example operator does: There are 2 inputs, an object and a scale factor. The operator will scale the selected object by the given scale factor. Simple one, just for an example purpose.
Problem description: I have added an object picker in my operator UI to select an object. Once I select the object and execute the operator, if I try to change the object from the Adjust Last Operation window, the change does not take effect. I want to know how to modify this code so that I can use an object picker as well as change the selection later to re-run the operator on another object, like we can do with most operators.
Since as a new user I am not allowed to add more screenshots, here is just one screenshot of my test add-on (Screenshot is taken in 4.0 Alpha but this problem occurs in other versions as well like 3.6 etc).
As you can see, in spite of changing the selection to UV Sphere, the selection actually does not change, it still shows Cube and no change happens to the Sphere. However, if I change the Scale factor, it takes effect. So the way my object picker is implemented through a Pointer property, may have a problem. You can run the code below and test it.
Here is the fully functional code for this example:
import bpy
class Object_OT_My_Test_Op(bpy.types.Operator):
bl_idname = "object.my_test_op"
bl_label = "My Test Op"
bl_options = {'REGISTER', 'UNDO'}
scale: bpy.props.IntProperty(name="Scale", default=2, min=1, max=100)
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False # No animation.
layout.prop(context.scene, "my_object", text="Object")
layout.prop(self, 'scale')
def invoke(self, context, event):
return_code = context.window_manager.invoke_props_dialog(self, width = 250)
return return_code
def execute(self, context):
my_object = context.scene.my_object
scale = self.scale
if (my_object is None): # Display an error message and exit.
self.report({'ERROR'}, "No object is selected")
return {'CANCELLED'}
# Add the scale factor to the selected object.
my_object.scale = [scale, scale, scale]
# Tell Blender that the operator finished successfully.
return {'FINISHED'}
def register():
bpy.utils.register_class(Object_OT_My_Test_Op)
bpy.types.Scene.my_object = bpy.props.PointerProperty(type=bpy.types.Object)
def unregister():
bpy.utils.unregister_class(Object_OT_My_Test_Op)
del bpy.types.Scene.my_object
if __name__ == "__main__":
register()
bpy.ops.object.my_test_op("INVOKE_DEFAULT")
What solution I have tried: I tried to modify this code to avoid any Pointer property. I used a String property within the operator itself to hold the selected object name. Then I displayed the object picker using prop_search() like below.
Property declaration:
object_name: bpy.props.StringProperty(name="Object", default="")
Within the draw method:
layout.prop_search(self, "object_name", context.scene, "objects")
Within the Execute method:
my_object = bpy.data.objects[object_name]
It works fine and I can also change the selection from Adjust Last Operation, but here the problem is, the eye-dropper does not show in the selection box. I need that eye-dropper, so this solution does not work for me. Also, I need a poll function to limit the selection within a specific group of objects. This is not possible with prop_search(), so I have to go with the Pointer property. Can someone please suggest how to get the Adjust Last Operation thing working correctly with a Pointer property?