Edit. I think I may have solved this in a slightly different way. I can now join the objects together without much issue. Please note that I've updated the script for blender 2.8 also. I've added the script below this text but kept all the original stuff for historic purposes. Thanks to everyone who helped out on this :)
class SameJoin(Operator):
"""Select and Join Similarly Named objects"""
bl_idname = "same.join"
bl_label = "Join Similar"
bl_description = 'joins objects who\'s names are the same'
bl_options = {'REGISTER', 'UNDO'}
def execute(self, context):
"""gets all the names of everything in the scene
and then updates the names without their object ids
so they can be joined as same name items"""
for obj in bpy.context.selected_objects:
namestore_1 = obj.name
namestore_1A = re.sub('[^a-zA-Z]+', '', namestore_1)
print(namestore_1A)
context.view_layer.objects.active = obj
for ob in bpy.context.scene.objects:
namestore_2 = ob.name
namestore_2A = re.sub('[^a-zA-Z]+', '', namestore_2)
print(namestore_2A)
"""makes sure all objects are mesh before
performing mesh operation"""
if ob.type == 'MESH':
if str(namestore_1A) == (namestore_2A):
ob.select_set(True)
else:
ob.select_set(False)
for selected in bpy.context.selected_objects:
try:
if selected.type == 'MESH':
bpy.ops.object.join()
self.report({'INFO',}, 'Objects joined')
except:
self.report({'INFO',}, 'Object not joined')
return {'FINISHED'}
I've read the other threads related to this subject and have almost gotten to the end. I have quite a specific query though that I can't seem to find answered exactly so here goes....
I'm trying to have create GUI for my script which joins objects whos names are similar, to a certain number of characters.
See the script below.
import bpy
from bpy.types import Panel, Operator
from bpy.props import *
#Select and Join Similarly Named objects
charlen = 15
class SameJoin(Operator):
bl_idname = "same.join"
bl_label = "Join SameName"
bl_description = 'This tool will allow you to join,objects who\'s names have the same sequential characters up to a certain number of characters.'
bl_options = {'REGISTER', 'UNDO'}
#description
charln = IntProperty(
name="Character Match Value",
description="Number of characters to match with other objects name in scene before joining",
min=1, max=30,
default=15,
soft_min=1,
soft_max=30,
)
def joinsame(self, charln):
for obj in bpy.context.selected_objects:
namestore_1 = obj.name[:charlen]
bpy.context.scene.objects.active = obj
for ob in bpy.context.scene.objects:
namestore_2 = ob.name[:charlen]
if ob.type == 'MESH':
if str(namestore_1) == (namestore_2):
ob.select = True
else:
ob.select = False
for selected in bpy.context.selected_objects:
if selected.type == 'MESH':
bpy.ops.object.join()
def execute(self, context):
self.joinsame(self.charln)
self.report({'INFO'}, 'similar joined')
return {'FINISHED'}
class JoinSame(bpy.types.Panel):
#"""A custom panel in the Viewport Toolbar"""
bl_label = "JoinSameName"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_context = "objectmode"
bl_category = "JoinSame"
def draw(self, context):
layout = self.layout
row = layout.row()
row.label(text = "Selected Object")
row = layout.row()
row.label(text = "Name match = %s characters" % (charlen))
row = layout.row()
row.operator("same.join", text = "1. Join SameName")
def register():
bpy.utils.register_class(SameJoin)
bpy.utils.register_class(JoinSame)
def unregister():
bpy.utils.unregister_class(SameJoin)
bpy.util.unregister_class(JoinSame)
if __name__ == "__main__":
register()
Sorry in advance for how ugly my code is.
The problem I'm having at the moment is that 1. you have to push the button before the number slider appears so the user has no idea that they have the option till the objects are all joined (we're talking lists of tens of thousands of objects here so updating dynamically doesnt seem like a good idea) 2.I'd much rather the slider sat above the button and was there from the begining.
Is any of this possible?
Thanks in advance for any help at all. I know this is a long one...