2

Is there a way to do this?

For example, adding a subdivision modifier on the default cube then Alt+D to instance it. Going back to the first object, I'm unable to apply the modifiers.

I know that there are other ways such as making the object single user or simply deleting it but i was hoping there is a way to simply apply modifiers without doing the above.

Wonkey
  • 248
  • 3
  • 18
  • Why not to Shift+D ... Since you want to Apply (make real) modifier, object is not instance anyway. Can you explain deeper case it comes usedull for you? Thank you – vklidu Jan 15 '22 at 07:56
  • you can't because Blender doesn't know what to do, as both the 2 objects share the same mesh is it also supposed to apply the modifier for the other instance? – moonboots Jan 15 '22 at 08:54
  • I am testing a way to do this now. It works with your exact case above https://blender.stackexchange.com/questions/262406/apply-modifiers-to-instanced-objects-works-looking-for-help-bughunting-speed-i – Fae Corrigan May 02 '22 at 15:04

1 Answers1

0

This theoretically works for everything but geometry nodes

import bpy
import itertools

#todo: displace (needs a lot of work with coordinates)

def compareModifiers(original,test):

#BOOLEAN,BUILD,NODES (geo nodes), MASK,VOLUME_TO_MESH
modifierWhitelist = ("BEVEL" , "DECIMATE" , "SKIN", "SOLIDIFY","EDGE_SPLIT","REMESH","SKIN","SUBSURF",
    "TRIANGULATE","WELD","WIREFRAME","ARRAY","MIRROR","SCREW", "MULTIRES", "SMOOTH", "CORRECTIVE_SMOOTH",
    "LAPLACIANSMOOTH","SIMPLE_DEFORM") #starting with screw there are issues////
#return all(mod_equality(m, test.modifiers[i])
#            for i,m in enumerate(original.modifiers)) #check if the modifiers are the same
for (mod,mod1) in zip(original.modifiers,test.modifiers):
    modType = getattr(mod,"type",True)
    mod1Type = getattr(mod1,"type",True)
    if not (modType==mod1Type):
        print("modtype issue")
        return False

    if modType == "MIRROR":
        if getattr(mod,"mirror_object",True) != None:
            print("mirror failure")
            return False

    if modType == "ARRAY":
        if getattr(mod,"use_object_offset",True) == True:
            print("array failure")
            return False
    if modType == "SCREW":
        if getattr(mod,"object",True) != None:
            print("screw failure")
            return False

    if modType == "SIMPLE_DEFORM":

        if getattr(mod,"origin",True) != None:
            print("simple deform failure")

            return False

    if modType not in modifierWhitelist:
        print(modType)
        print("unsupported modifiers used by objects. making them unique")
        return False
        #if modType == "

    for att in mod.bl_rna.properties.keys(): #we are in one of the whitelisted mods, making sure all attributes are the same
        #ignore name field
        #print(att)
        if att == "name":
            continue
        if att == "custom_profile":
            continue #TODO this is a bodge. The custom profiles are links to objects, not values, so more parsing is required
        #print(att)
        #print(str(att)+"  :  " + str(getattr(mod,att,True)) + "  :  " + str(getattr(mod1,att,True)) + "   :   " + str(getattr(mod,att,True) == getattr(mod1,att,True)))
        if att == "use_axis": #mirror modifier att fix
            print(tuple(getattr(mod,att,True)))
            print(tuple(getattr(mod1,att,True)))
            if (tuple(getattr(mod,att,True))) == tuple(getattr(mod1,att,True)):
                continue
            else:
                print("use axis failue")
                return False


        if att == "use_bisect_axis": #mirror modifier att fix
            if (tuple(getattr(mod,att,True))) == tuple(getattr(mod1,att,True)):
                continue
            else:
                print("bisect axis failure")
                return False

        if att == "use_bisect_flip_axis": #mirror modifier att fix
            if (tuple(getattr(mod,att,True))) == tuple(getattr(mod1,att,True)):
                continue
            else:
                print("flip axis failure")
                return False

        if att == "limits": #simple deform fix
            if (tuple(getattr(mod,att,True))) == tuple(getattr(mod1,att,True)):
                continue
            else:
                print("limits failure")
                return False

        if att == "lock": #simple deform fix
            if (tuple(getattr(mod,att,True))) == tuple(getattr(mod1,att,True)):
                continue
            else:
                print("lock failure")
                return False


        if getattr(mod,att,True) != getattr(mod1,att,True):
            print("mod attr equality failure:  " + str(att))
            return False



print("passed all tests")
return True

objects = bpy.context.selected_objects checkedObjects = objects affectMeshesOutsideSelection = False

if affectMeshesOutsideSelection: print("affect outside meshes") checkedObjects = bpy.context.objects

while len(objects)>0:

currentObject = objects[0]
similarObjects = []
similarObjects.append(currentObject)



for o in checkedObjects:
    print("testing object   "+str(o))
    if o.data == currentObject.data:
        print("dataCheck")
        if compareModifiers(currentObject,o):
            print("modCheck")
            similarObjects.append(o)

currentObject.data = currentObject.data.copy()
depsgraph = bpy.context.evaluated_depsgraph_get()
object_eval = currentObject.evaluated_get(depsgraph)
mesh_from_eval = bpy.data.meshes.new_from_object(object_eval)

currentObject.data = mesh_from_eval
currentObject.modifiers.clear()
print("current object = " + str(currentObject))
print("similar Objects = " + str(similarObjects))
for o in similarObjects:
     o.modifiers.clear()
     o.data = currentObject.data




for o in similarObjects:
    try:
        objects.remove(o)
    except:
        #the only exception this can throw is that o is not in objects
        pass
print("objects remaining  " + str(objects))



currentObject =[] similarObjects = [] objects = []