9

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.

Dillz Sinden
  • 103
  • 1
  • 7
  • What are you asking? What happens instead of removing doubles from multiple objects when you run the code? – 10 Replies Nov 27 '16 at 20:02
  • 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.

    – Dillz Sinden Nov 27 '16 at 20:06
  • Include this information in your question. It is unclear what you are asking for without it. – 10 Replies Nov 27 '16 at 20:07

2 Answers2

14

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()
batFINGER
  • 84,216
  • 10
  • 108
  • 233
  • 2
    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.

    – Dillz Sinden Nov 28 '16 at 20:40
  • 1
    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. – batFINGER Nov 29 '16 at 11:00
  • 1
    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! – aliasguru Jul 18 '19 at 08:26
4

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()
Tak
  • 6,293
  • 7
  • 43
  • 85
  • 2
    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. – Dillz Sinden Nov 28 '16 at 20:26