9
$\begingroup$

I'm trying to run the remove_doubles edit command on multiple selected objects. This is kinda what I got so far...

import bpy


class remDoubles(bpy.types.Operator):
    """Remove Doubles on multiple objects"""
    bl_label = "Remove Multiple Doubles"
    bl_idname = "object.remove_doubles_multi"
    bl_options = {'REGISTER', 'UNDO'}

    @classmethod
    def poll(cls, context):
        return len(context.selected_objects) > 0

    def execute(self, context):

        scene = bpy.context.scene
        sel = context.selected_objects

        for obj in sel:
            scene.objects.active = obj

            #do something here
            print(obj.name)
            bpy.ops.mesh.remove_doubles()

        return {"FINISHED"}

myobject = remDoubles()

myobject.execute()

My knowledge about classes isn't too great, please help.

My code needs some work, it just errors out giving a 'TypeError: bpy_struct.new(type): expected a single argument'

But what i intend doing is run through each object applying the remove doubles command for each.

$\endgroup$
3
  • $\begingroup$ What are you asking? What happens instead of removing doubles from multiple objects when you run the code? $\endgroup$
    – 10 Replies
    Nov 27, 2016 at 20:02
  • $\begingroup$ My code needs some work, it just errors out giving a 'TypeError: bpy_struct.__new__(type): expected a single argument' But what i intend doing is run through each object applying the remove doubles command for each. $\endgroup$ Nov 27, 2016 at 20:06
  • $\begingroup$ Include this information in your question. It is unclear what you are asking for without it. $\endgroup$
    – 10 Replies
    Nov 27, 2016 at 20:07

2 Answers 2

14
$\begingroup$

Firstly operators don't work in a usual create class instance way... the code below

myobject = remDoubles()
myobject.execute()

Will NOT work.

Have a look at the Hello World Example The HelloWorldOperatoroperator class is defined, registered (known to bpy.ops), then called using bpy.ops. "plus" the bl_idname.

In your example you would

bpy.utils.register_class(RemoveDoublesMulti) # changed to camel-case name

# test call to the newly defined operator
bpy.ops.object.remove_doubles_multi()

Using a bmesh approach avoids toggling in and out of edit mode, changing the context object ... etc. An alternative for execute:

import bpy
import bmesh

context = bpy.context

distance = 0.0 # remove doubles tolerance.
if True: #def execute(self, context):

    meshes = set(o.data for o in context.selected_objects
                      if o.type == 'MESH')

    bm = bmesh.new()

    for m in meshes:
        bm.from_mesh(m)
        bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=distance)
        bm.to_mesh(m)
        m.update()
        bm.clear()

    bm.free()
$\endgroup$
3
  • 2
    $\begingroup$ Thanks for clearing things up by explaining that the operators don't work as normal class instances. I will look into the example. The bmesh method really captivated me though as it is sooo fast so I'd do a little bit more research on that. BTW i did have to change the distance = distance to dist = distance. $\endgroup$ Nov 28, 2016 at 20:40
  • 1
    $\begingroup$ Fixed, thankyou. If you want to make a report sum(len(m.vertices) for m in meshes) will give you the total verts in all selected meshes. The difference in result when run before and after operator loop, gives total removed verts. $\endgroup$
    – batFINGER
    Nov 29, 2016 at 11:00
  • 1
    $\begingroup$ using the set() is to avoid running it again on instances of the same mesh used by other objects if I am not mistaken? Very clever! $\endgroup$
    – aliasguru
    Jul 18, 2019 at 8:26
4
$\begingroup$

Below is a simple script that will loop on the meshes you have in your scene and remove doubles from only the MESH objects.

import bpy

if bpy.context.selected_objects != []:
    for obj in bpy.context.selected_objects:
        if obj.type == 'MESH':
            print(obj.name)
            bpy.context.scene.objects.active = obj
            bpy.ops.object.editmode_toggle()
            bpy.ops.mesh.select_all(action='SELECT')
            bpy.ops.mesh.remove_doubles()
            bpy.ops.object.editmode_toggle()
$\endgroup$
1
  • 2
    $\begingroup$ Thank you so much for this. Though the bmesh method gets executed waaay faster, this has given me new insight for quickly running edit mode commands over multiple meshes. $\endgroup$ Nov 28, 2016 at 20:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .