Fix io_anim_camera error exporting cameras with quotes in their name
[blender-addons.git] / curve_tools / remove_doubles.py
blobc63d82be08bf2ea1638ac2a5aedddb019d7a36ec
1 # SPDX-License-Identifier: GPL-2.0-or-later
3 import bpy, mathutils
4 from . import util
6 bl_info = {
7 'name': 'Curve Remove Doubles',
8 'author': 'Michael Soluyanov',
9 'version': (1, 1),
10 'blender': (2, 80, 0),
11 'location': 'View3D > Context menu (W/RMB) > Remove Doubles',
12 'description': 'Adds command "Remove Doubles" for curves',
13 'category': 'Add Curve'
16 def main(context, distance = 0.01):
18 selected_Curves = util.GetSelectedCurves()
19 if bpy.ops.object.mode_set.poll():
20 bpy.ops.object.mode_set(mode='EDIT')
22 for curve in selected_Curves:
23 bezier_dellist = []
24 dellist = []
26 for spline in curve.data.splines:
27 if spline.type == 'BEZIER':
28 if len(spline.bezier_points) > 1:
29 for i in range(0, len(spline.bezier_points)):
31 if i == 0:
32 ii = len(spline.bezier_points) - 1
33 else:
34 ii = i - 1
36 dot = spline.bezier_points[i];
37 dot1 = spline.bezier_points[ii];
39 while dot1 in bezier_dellist and i != ii:
40 ii -= 1
41 if ii < 0:
42 ii = len(spline.bezier_points)-1
43 dot1 = spline.bezier_points[ii]
45 if dot.select_control_point and dot1.select_control_point and (i!=0 or spline.use_cyclic_u):
47 if (dot.co-dot1.co).length < distance:
48 # remove points and recreate hangles
49 dot1.handle_right_type = "FREE"
50 dot1.handle_right = dot.handle_right
51 dot1.co = (dot.co + dot1.co) / 2
52 bezier_dellist.append(dot)
54 else:
55 # Handles that are on main point position converts to vector,
56 # if next handle are also vector
57 if dot.handle_left_type == 'VECTOR' and (dot1.handle_right - dot1.co).length < distance:
58 dot1.handle_right_type = "VECTOR"
59 if dot1.handle_right_type == 'VECTOR' and (dot.handle_left - dot.co).length < distance:
60 dot.handle_left_type = "VECTOR"
61 else:
62 if len(spline.points) > 1:
63 for i in range(0, len(spline.points)):
65 if i == 0:
66 ii = len(spline.points) - 1
67 else:
68 ii = i - 1
70 dot = spline.points[i];
71 dot1 = spline.points[ii];
73 while dot1 in dellist and i != ii:
74 ii -= 1
75 if ii < 0:
76 ii = len(spline.points)-1
77 dot1 = spline.points[ii]
79 if dot.select and dot1.select and (i!=0 or spline.use_cyclic_u):
81 if (dot.co-dot1.co).length < distance:
82 dot1.co = (dot.co + dot1.co) / 2
83 dellist.append(dot)
85 bpy.ops.curve.select_all(action = 'DESELECT')
87 for dot in bezier_dellist:
88 dot.select_control_point = True
90 for dot in dellist:
91 dot.select = True
93 bezier_count = len(bezier_dellist)
94 count = len(dellist)
96 bpy.ops.curve.delete(type = 'VERT')
98 bpy.ops.curve.select_all(action = 'DESELECT')
100 return bezier_count + count
104 class CurveRemvDbs(bpy.types.Operator):
105 """Merge consecutive points that are near to each other"""
106 bl_idname = 'curvetools.remove_doubles'
107 bl_label = 'Remove Doubles'
108 bl_options = {'REGISTER', 'UNDO'}
110 distance: bpy.props.FloatProperty(name = 'Distance', default = 0.01)
112 @classmethod
113 def poll(cls, context):
114 return util.Selected1OrMoreCurves()
116 def execute(self, context):
117 removed=main(context, self.distance)
118 self.report({'INFO'}, "Removed %d bezier points" % removed)
119 return {'FINISHED'}
123 def menu_func(self, context):
124 self.layout.operator(CurveRemvDbs.bl_idname, text='Remove Doubles')
126 def register():
127 bpy.utils.register_class(CurveRemvDbs)
128 bpy.types.VIEW3D_MT_edit_curve_context_menu.append(menu_func)
130 def unregister():
131 bpy.utils.unregister_class(CurveRemvDbs)
132 bpy.types.VIEW3D_MT_edit_curve_context_menu.remove(menu_func)
134 if __name__ == "__main__":
135 register()
137 operators = [CurveRemvDbs]