Set Modifier "Show in Edit Mode" Default to False

What the…?

Even though the Blender documentation (and the source code of a number of plugins in the app’s scripts > startup folder) state that the default setting for a new modifier is show_in_editmode = False, every time I add a modifier, this parameter is set to True, and I have to change it manually. Every. Time.

It’s a pain.

Is it my fault? Did I change a setting somewhere? Is it the Boxcutter Prefs? My friends, by this point I have not a flipping clue.

Ideally, I’d love to be able to click a checkbox in the Preferences window, or toggle a bool in a .py file in the app bundle somewhere, but those options haven’t presented themselves so far.

I dabbled with the code in How to set blender default properties in addons? but frankly, it’s over my head.

The path I’m on so far is this:

import bpy

modifiers = {
  'ArmatureModifier',
  'ArrayModifier',
  'BevelModifier',
  ...
}

# test if context = bpy.ops.object.modifier_add
    opsobj = bpy.ops.object
    cobmod = bpy.context.object.modifiers
    if opsobj.modifier_add(type=modifier):
        cobmod[modifier].show_in_editmode = False

but it’s obviously tangled up, and I suspect I may be heading down another dead end.

My brain is woozy.

So,

I thought I’d ask here and see if anyone already knows the obvious and simple solution that has so far evaded me.

Maybe it’s something to do with bpy.context.preferences.themes['Default'], or maybe it’s adding a .py file with params.modifiers.show_in_editmode = False to my user startup folder.

Any assistance would be appreciated.

The default for the base object type (bpy.types.Modifier) is indeed False, individual modifiers don’t have to adhere to that default when they’re implemented on the C side of things, however. For example, the Displace modifier (bpy.types.DisplaceModifier) inherits from the base Modifier object type, and doesn’t override the parameter to True like most other modifiers do. Unfortunately (or… fortunately, if you’re not a fan of verbosity), the API docs don’t mention when an inherited parameter’s default value is overridden so you either need to look at the C source for it, or just figure it out empirically.

If all you want to do is turn off show_in_editmode for every modifier why not just loop through the modifier stack and set the property that way?

eg)

for o in bpy.data.objects:
    try:
        for m in o.modifiers:
            m.show_in_editmode = False
    except AttributeError:
        pass # this object type doesn't have modifiers.. empties, lights, etc.

you could put that in an operator and then drop a button somewhere on your UI. it’s still a manual process but at least it’s just one click.

# test if context = bpy.ops.object.modifier_add

unfortunately there’s no true event->subscriber model in the blender api, so you have no way of knowing when a user is running an operator. The closest thing you have is the depsgraph update, or msgbus RNA subscriber system (which won’t work for modifiers, bpy_prop_collections in general).

If you really want a ‘first class’ way to handle the problem you’d have to rewrite the entire modifier panel- which is crazy, but isn’t actually as crazy as it sounds… @Symstract did just that with this addon: https://github.com/Symstract/modifier_list. Ironically, the modifier list addon lets you set certain defaults for addons, but not the show_in_editmode property. maybe you could convince somebody to add that feature to the addon, they have a thread here.

2 Likes

Thank you for such a comprehensive response. I appreciate the code snippet, the link to the add-on, and confirmation that the current version Blender doesn’t allow for the kind of universal overrides I’m looking for.

To expand on my problem, I use keyboard shortcuts and modifier stacks in Quick View to customize objects without requiring I open the Modifiers panel. But as I stated before, it’s irritating to then go into Edit mode and have verts obscured by a subsurf mod, or conflicting wireframes overlapping each other.

In a perfect world, there would be a way to create a listener that would recognize when add_modifier is called, and automatically flip the off switch without requiring I go to the Modifiers panel.

(I’m tempted to drop the suggestion on Right-Click Select, but just between you and me, my previous experience with them has been sort of unpleasantly condescending and passive-aggressive, so I’ve since avoided posting there. Life’s too short.)

I’ve been using an add-on – Tweaked Modifier Tools Addon – that customizes the Modifier panel in a way I really like, and includes a button that allows me to “hide in edit mode” all modifiers on a selected object. And if I Select All and hold Control when I click the button, I can apply it universally.

So I do have a partial solution available to me. It’s just not automatic, which is what I’ve become conditioned to in the age of computers.

But I like your script, so I’ll probably go ahead and make it an add-on for the Properties panel. Even though this is a very esoteric tweak, I may post it here, just so the one other person in the world who has the same issue gets some love.

Once again, thanks for such a thorough and helpful reply. Namaste!

Oh well if you’re just adding modifiers via hotkeys that makes things way simpler. You could just use a small ‘wrapper’ operator, and then just point your hotkeys to your operator instead of the built-in one.
Here’s a wrapper operator that does just that:

import bpy

class OBJECT_OT_add_modifier(bpy.types.Operator):
    bl_idname = "object.add_modifier"
    bl_label = "Add Modifier"
    bl_description = "Add a modifier with option to have show_in_editmode disabled by default"
    bl_options={'REGISTER', 'UNDO'}
    
    modifier_type: bpy.props.EnumProperty(items=[
        ('SUBSURF', 'Subdivision Surface', ''),
        ('BEVEL', 'Bevel', ''),
        # add whatever ones you care about. here's the full list:
        # ('DATA_TRANSFER', 'MESH_CACHE', 'MESH_SEQUENCE_CACHE', 'NORMAL_EDIT', 'WEIGHTED_NORMAL', 'UV_PROJECT', 'UV_WARP', 'VERTEX_WEIGHT_EDIT', 'VERTEX_WEIGHT_MIX', 'VERTEX_WEIGHT_PROXIMITY', 'ARRAY', 'BEVEL', 'BOOLEAN', 'BUILD', 'DECIMATE', 'EDGE_SPLIT', 'NODES', 'MASK', 'MIRROR', 'MESH_TO_VOLUME', 'MULTIRES', 'REMESH', 'SCREW', 'SKIN', 'SOLIDIFY', 'SUBSURF', 'TRIANGULATE', 'VOLUME_TO_MESH', 'WELD', 'WIREFRAME', 'ARMATURE', 'CAST', 'CURVE', 'DISPLACE', 'HOOK', 'LAPLACIANDEFORM', 'LATTICE', 'MESH_DEFORM', 'SHRINKWRAP', 'SIMPLE_DEFORM', 'SMOOTH', 'CORRECTIVE_SMOOTH', 'LAPLACIANSMOOTH', 'SURFACE_DEFORM', 'WARP', 'WAVE', 'VOLUME_DISPLACE', 'CLOTH', 'COLLISION', 'DYNAMIC_PAINT', 'EXPLODE', 'FLUID', 'OCEAN', 'PARTICLE_INSTANCE', 'PARTICLE_SYSTEM', 'SOFT_BODY', 'SURFACE')
    ])

    show_in_editmode: bpy.props.BoolProperty(name="Show in Edit Mode", default=False)

    @classmethod
    def poll(cls, context):
        return context.object.type == 'MESH'

    def execute(self, context):
        m = context.active_object.modifiers.new(self.modifier_type, self.modifier_type)
        m.show_in_editmode = self.show_in_editmode
        return {'FINISHED'}

def register():
    bpy.utils.register_class(OBJECT_OT_add_modifier)

def unregister():
    bpy.utils.unregister_class(OBJECT_OT_add_modifier)

if __name__ == "__main__":
    register()

just set your hotkeys to object.add_modifier, and then adjust the dropdown to whichever modifier that hotkey is supposed to add.

This is nice! I can add the subdiv with this, and then adjust the levels using the standard system hotkeys.

Some of the hotkeys and Quick Favorites I’m using are more complicated, like HardOps Spherize. For that, maybe I copy/paste the operators for the original and make a new add-on with tweaks.

A bit of work, but may be worth playing with. :+1:

I’ve been playing with your code, and snagged this trick from HardOps to add more tweaks that are only applied to the appropriate modifier:

    def execute(self, context):
        m = context.active_object.modifiers.new(self.modifier_type, self.modifier_type)
        m.show_in_editmode = False
        context.object.cycles.use_adaptive_subdivision = True
        if hasattr(m, 'levels'):
            m.levels = 2
        if hasattr(m, 'miter_outer'):
            m.miter_outer = 'MITER_ARC'
        return {'FINISHED'}