Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Spivak(cwolf3d) <cwolf3d@gmail.com>2021-01-07 20:05:54 +0300
committerVladimir Spivak(cwolf3d) <cwolf3d@gmail.com>2021-01-07 20:05:54 +0300
commitd2f6cf924a622dd28ab4bee4e3a74792bce1eebc (patch)
treeae7c3a547eee3549efea8b332e901c45996d44a7
parentcef282cc9acdc1eb4e77d92fa7631f47a47a867c (diff)
Addon: Curve Tools: Made changes from Lichtso github
-rw-r--r--curve_tools/__init__.py3
-rw-r--r--curve_tools/cad.py67
-rw-r--r--curve_tools/internal.py22
-rw-r--r--curve_tools/toolpath.py22
4 files changed, 56 insertions, 58 deletions
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'