[Bf-extensions-cvs] [d2f6cf92] master: Addon: Curve Tools: Made changes from Lichtso github

Vladimir Spivakcwolf3d noreply at git.blender.org
Thu Jan 7 18:06:56 CET 2021


Commit: d2f6cf924a622dd28ab4bee4e3a74792bce1eebc
Author: Vladimir Spivak(cwolf3d)
Date:   Thu Jan 7 19:05:54 2021 +0200
Branches: master
https://developer.blender.org/rBAd2f6cf924a622dd28ab4bee4e3a74792bce1eebc

Addon: Curve Tools: Made changes from Lichtso github

===================================================================

M	curve_tools/__init__.py
M	curve_tools/cad.py
M	curve_tools/internal.py
M	curve_tools/toolpath.py

===================================================================

diff --git a/curve_tools/__init__.py b/curve_tools/__init__.py
index 4a9d283c..d7ce3736 100644
--- a/curve_tools/__init__.py
+++ b/curve_tools/__init__.py
@@ -25,11 +25,10 @@ bl_info = {
     "name": "Curve Tools",
     "description": "Adds some functionality for bezier/nurbs curve/surface modeling",
     "author": "Mackraken",
-    "version": (0, 4, 4),
+    "version": (0, 4, 5),
     "blender": (2, 80, 0),
     "location": "View3D > Tool Shelf > Edit Tab",
     "warning": "WIP",
-    "doc_url": "",
     "doc_url": "{BLENDER_MANUAL_URL}/addons/add_curve/curve_tools.html",
     "category": "Add Curve",
 }
diff --git a/curve_tools/cad.py b/curve_tools/cad.py
index e46af8d3..dd11b4c7 100644
--- a/curve_tools/cad.py
+++ b/curve_tools/cad.py
@@ -72,7 +72,6 @@ class Boolean(bpy.types.Operator):
         current_mode = bpy.context.object.mode
 
         bpy.ops.object.mode_set(mode = 'EDIT')
-
         if bpy.context.object.data.dimensions != '2D':
             self.report({'WARNING'}, 'Can only be applied in 2D')
             return {'CANCELLED'}
@@ -116,7 +115,7 @@ class HandleProjection(bpy.types.Operator):
 
     @classmethod
     def poll(cls, context):
-        return internal.curveObject()
+        return util.Selected1OrMoreCurves()
 
     def execute(self, context):
         segments = internal.bezierSegments(bpy.context.object.data.splines, True)
@@ -132,54 +131,34 @@ class MergeEnds(bpy.types.Operator):
     bl_description = bl_label = 'Merge Ends'
     bl_options = {'REGISTER', 'UNDO'}
 
+    max_dist: bpy.props.FloatProperty(name='Distance', description='Threshold of the maximum distance at which two control points are merged', unit='LENGTH', min=0.0, default=0.1)
+
     @classmethod
     def poll(cls, context):
         return util.Selected1OrMoreCurves()
 
     def execute(self, context):
-        points = []
-        selected_splines = []
-        is_last_point = []
-        for spline in bpy.context.object.data.splines:
-            if spline.type != 'BEZIER' or spline.use_cyclic_u:
+        splines = [spline for spline in internal.getSelectedSplines(True, False) if spline.use_cyclic_u == False]
+
+        while len(splines) > 0:
+            spline = splines.pop()
+            closest_pair = ([spline, spline], [spline.bezier_points[0], spline.bezier_points[-1]], [False, True])
+            min_dist = (spline.bezier_points[0].co-spline.bezier_points[-1].co).length
+            for other_spline in splines:
+                for j in range(-1, 1):
+                    for i in range(-1, 1):
+                        dist = (spline.bezier_points[i].co-other_spline.bezier_points[j].co).length
+                        if min_dist > dist:
+                            min_dist = dist
+                            closest_pair = ([spline, other_spline], [spline.bezier_points[i], other_spline.bezier_points[j]], [i == -1, j == -1])
+            if min_dist > self.max_dist:
                 continue
-            if spline.bezier_points[0].select_control_point:
-                points.append(spline.bezier_points[0])
-                selected_splines.append(spline)
-                is_last_point.append(False)
-            if spline.bezier_points[-1].select_control_point:
-                points.append(spline.bezier_points[-1])
-                selected_splines.append(spline)
-                is_last_point.append(True)
-
-        if len(points) != 2:
-            self.report({'WARNING'}, 'Invalid selection')
-            return {'CANCELLED'}
+            if closest_pair[0][0] != closest_pair[0][1]:
+                splines.remove(closest_pair[0][1])
+            spline = internal.mergeEnds(closest_pair[0], closest_pair[1], closest_pair[2])
+            if spline.use_cyclic_u == False:
+                splines.append(spline)
 
-        if is_last_point[0]:
-            points[1], points[0] = points[0], points[1]
-            selected_splines[1], selected_splines[0] = selected_splines[0], selected_splines[1]
-            is_last_point[1], is_last_point[0] = is_last_point[0], is_last_point[1]
-
-        points[0].handle_left_type = 'FREE'
-        points[0].handle_right_type = 'FREE'
-        new_co = (points[0].co+points[1].co)*0.5
-        handle = (points[1].handle_left if is_last_point[1] else points[1].handle_right)+new_co-points[1].co
-        if is_last_point[0]:
-            points[0].handle_left += new_co-points[0].co
-            points[0].handle_right = handle
-        else:
-            points[0].handle_right += new_co-points[0].co
-            points[0].handle_left = handle
-        points[0].co = new_co
-
-        point_index = 0 if selected_splines[0] == selected_splines[1] else len(selected_splines[1].bezier_points)
-        bpy.ops.curve.make_segment()
-        point = selected_splines[0].bezier_points[point_index]
-        point.select_control_point = False
-        point.select_left_handle = False
-        point.select_right_handle = False
-        bpy.ops.curve.delete()
         return {'FINISHED'}
 
 class Subdivide(bpy.types.Operator):
@@ -219,7 +198,7 @@ class Array(bpy.types.Operator):
     bl_description = bl_label = 'Array'
     bl_options = {'REGISTER', 'UNDO'}
 
-    offset: bpy.props.FloatVectorProperty(name='Offset', unit='LENGTH', description='Vector between to copies', subtype='DIRECTION', default=(1.0, 0.0, 0.0), size=3)
+    offset: bpy.props.FloatVectorProperty(name='Offset', unit='LENGTH', description='Vector between to copies', subtype='DIRECTION', default=(0.0, 0.0, -1.0), size=3)
     count: bpy.props.IntProperty(name='Count', description='Number of copies', min=1, default=2)
     connect: bpy.props.BoolProperty(name='Connect', description='Concatenate individual copies', default=False)
     serpentine: bpy.props.BoolProperty(name='Serpentine', description='Switch direction of every second copy', default=False)
diff --git a/curve_tools/internal.py b/curve_tools/internal.py
index 96816189..149c31d9 100644
--- a/curve_tools/internal.py
+++ b/curve_tools/internal.py
@@ -637,6 +637,27 @@ def addBezierSpline(obj, cyclic, vertices, weights=None, select=False):
             point.handle_left_type = 'VECTOR'
     return spline
 
+def mergeEnds(splines, points, is_last_point):
+    bpy.ops.curve.select_all(action='DESELECT')
+    points[0].handle_left_type = points[0].handle_right_type = 'FREE'
+    new_co = (points[0].co+points[1].co)*0.5
+    handle = (points[1].handle_left if is_last_point[1] else points[1].handle_right)+new_co-points[1].co
+    points[0].select_left_handle = points[0].select_right_handle = True
+    if is_last_point[0]:
+        points[0].handle_left += new_co-points[0].co
+        points[0].handle_right = handle
+    else:
+        points[0].handle_right += new_co-points[0].co
+        points[0].handle_left = handle
+    points[0].co = new_co
+    points[0].select_control_point = points[1].select_control_point = True
+    bpy.ops.curve.make_segment()
+    spline = splines[0] if splines[0] in bpy.context.object.data.splines.values() else splines[1]
+    point = next(point for point in spline.bezier_points if point.select_left_handle)
+    point.select_left_handle = point.select_right_handle = point.select_control_point = False
+    bpy.ops.curve.delete()
+    return spline
+
 def polygonArcAt(center, radius, begin_angle, angle, step_angle, include_ends):
     vertices = []
     circle_samples = math.ceil(abs(angle)/step_angle)
@@ -807,7 +828,6 @@ def dogBone(spline, radius):
         vertices.append([next_segment_points[0], corner, next_segment_points[0]])
         vertices.append([corner, next_segment_points[0], next_segment_points[3]])
     iterateSpline(spline, handlePoint)
-    print(vertices)
     return vertices
 
 def discretizeCurve(spline, step_angle, samples):
diff --git a/curve_tools/toolpath.py b/curve_tools/toolpath.py
index fec6693a..2c409f1a 100644
--- a/curve_tools/toolpath.py
+++ b/curve_tools/toolpath.py
@@ -113,7 +113,14 @@ class SliceMesh(bpy.types.Operator):
         self.offset = 0.0
         self.slice_count = 3
         self.mode = 'PITCH'
-        self.execute(context)
+        self.input_obj = bpy.context.object
+        depsgraph = context.evaluated_depsgraph_get()
+        self.mesh = bmesh.new()
+        self.mesh.from_object(self.input_obj, depsgraph, deform=True, cage=False, face_normals=True)
+        self.mesh.transform(bpy.context.scene.cursor.matrix.inverted()@self.input_obj.matrix_world)
+        self.result = internal.addObject('CURVE', 'Slices')
+        self.result.matrix_world = bpy.context.scene.cursor.matrix
+        self.perform(context)
         context.window_manager.modal_handler_add(self)
         return {'RUNNING_MODAL'}
 
@@ -148,9 +155,12 @@ class SliceMesh(bpy.types.Operator):
                 self.mode = 'OFFSET'
                 return {'RUNNING_MODAL'}
             elif self.mode == 'OFFSET':
+                self.mesh.free()
                 return {'FINISHED'}
         elif event.type in {'RIGHTMOUSE', 'ESC'}:
+            self.mesh.free()
             bpy.context.scene.collection.objects.unlink(self.result)
+            bpy.context.view_layer.objects.active = self.input_obj
             return {'CANCELLED'}
         else:
             return {'PASS_THROUGH'}
@@ -158,16 +168,6 @@ class SliceMesh(bpy.types.Operator):
         self.perform(context)
         return {'RUNNING_MODAL'}
 
-    def execute(self, context):
-        depsgraph = context.evaluated_depsgraph_get()
-        self.mesh = bmesh.new()
-        self.mesh.from_object(bpy.context.object, depsgraph, deform=True, cage=False, face_normals=True)
-        self.mesh.transform(bpy.context.scene.cursor.matrix.inverted()@bpy.context.object.matrix_world)
-        self.result = internal.addObject('CURVE', 'Slices')
-        self.result.matrix_world = bpy.context.scene.cursor.matrix
-        self.perform(context)
-        return {'FINISHED'}
-
 class DogBone(bpy.types.Operator):
     bl_idname = 'curvetools.add_toolpath_dogbone'
     bl_description = bl_label = 'Dog Bone'



More information about the Bf-extensions-cvs mailing list