Writing a Macro in Python - Wondering if what I want to do is a major or minor task

I went in a different direction and used a DialogOperator. While I can’t make it work from the object context menu (I’ve asked about that under the Python tag), I was trying to reduce pointer movement. (I use a 4K screen and sometimes it’s a long way from an object I’m working with to the Blender menu.)

I’m now using this script as an add-on. It appends the item to the end of the Object View Menu (and I added it to my Quick Menu). Using the DialogOperator saves me mouse movement, since the dialog pops up under my pointer. Since I use this with my quick menu, it’s very little mouse movement to do the scaling work.

I have 3 items I would still like to work out:

  1. I used an unregister() function the way I’ve seen it done in examples, so it should work, but I get an error if I call it. (However, when I have it installed as an add-on, and uncheck the box so it’s removed, I don’t get an error.) I’ve posted about that in another thread (as yet unanswered).

  2. As mentioned, if I use the Object Context Menu (VIEW3D_MT_object_context_menu) and pick this from that menu, the dialog never opens up. I can’t find out why. I’ve asked about it here.

  3. I want to add another button to the DialogOperator and have it trigger a cancel function. I know you can cancel with , but I’d like a button on the dialog box because often I tend to think more with the pointer than hitting a key on the keyboard. I’ve tried to find out how to add a button to the box, but I see very little that is both recent and useful for this.

Okay, so here’s the updated script, with comments:

#=============================================================================================
#Shrinkage Scaler (Add-on for Blender)
#
#Used for designing clay molds. Clays always shrink when fired. (Side note: For most pottery
#work, you make the piece, fire it to bisque it, so it's hard and moisture is removed, then put
#the glaze on, then fire again. Most clays will shrink from 8-12%, some shrink more.)
#If a mold is needed, then the size of the mold can depend on the shrinkage rate for the clay.
#
#For example, if Standard Clay's 182 will shrink 11% at cone 8. So the mold for something that
#will be fired at cone 8 needs to be made so when the clay it's used on shrinks 11%, it'll be
#the size needed. Note this means the mold has to be more than 11% bigger than the final size.
#The size can be figured out by 100 / (100 - shrink rate), or, for this, 100 / (100 - 11), or
#100/89, which comes out to 112.359550561798% of the intended size.
#
#This adds a function to the object menu "Shrinkage Scaler", that, when picked, brings up a
#dialog with one INT object in it. It defaults to 10. Select the shrinkage rate from there.
#The amount to scale up, so it will shrink to the right size, is calculated, and the selected
#object is scaled up as needed.
#
#TODO:
# * Make work from object context menu
# * Add Cancel button
#
#=============================================================================================
import bpy

bl_info = {
	"name" : "Shrinkage Scaler",
	"blender" : (4, 0, 2),
	"category" : "Object"
	}


class ShrinkageScalerDialog(bpy.types.Operator):
	bl_idname = "object.dialog_operator"
	bl_label = "Shrinkage Scaler"

	shrink_rate: bpy.props.IntProperty(name="Clay Shrink Rate",
		description="Shrinkage rate for clay body",
		default=10, min=0, max=90, subtype='PERCENTAGE')

	def execute(self, context):
		expand = 100 / (100 - self.shrink_rate)
		message = "Using shrinkage rate of %s and expansion rate of %s" % (self.shrink_rate, expand)
		self.report({'INFO'}, message)
		sel_objs = [obj for obj in bpy.context.selected_objects if obj.type == 'MESH']
		# bpy.ops.object.select_all(action='DESELECT')
		for obj in sel_objs:
			s = obj.scale
			obj.scale = (s[0] * expand, s[1] * expand, s[2] * expand)
		return {'FINISHED'}

	def invoke(self, context, event):
		wm = context.window_manager
		return wm.invoke_props_dialog(self)

# Only needed if you want to add into a dynamic menu.
def menu_func(self, context):
    self.layout.operator(ShrinkageScalerDialog.bl_idname, text=ShrinkageScalerDialog.bl_label)

def register():
    bpy.utils.register_class(ShrinkageScalerDialog)
    bpy.types.VIEW3D_MT_object.append(menu_func)
    # bpy.types.VIEW3D_MT_object_context_menu.append(menu_func)

def unregister():
    bpy.utils.unregister_class(ShrinkageScalerDialog)
    bpy.types.VIEW3D_MT_object.remove(menu_func)
    # bpy.types.VIEW3D_MT_object_context_menu.remove(menu_func)

if __name__ == "__main__":
    register()
    # unregister()