From 83bdf81f5fda9d33960280d322207f361b74fe87 Mon Sep 17 00:00:00 2001 From: meta-androcto Date: Tue, 25 Apr 2017 20:54:55 +1000 Subject: curve extra objects: bounce spline, spirofit, catenary update --- .../add_curve_spirofit_bouncespline.py | 869 +++++++++++++++------ 1 file changed, 616 insertions(+), 253 deletions(-) (limited to 'add_curve_extra_objects') diff --git a/add_curve_extra_objects/add_curve_spirofit_bouncespline.py b/add_curve_extra_objects/add_curve_spirofit_bouncespline.py index 7be535ab..f40c7680 100644 --- a/add_curve_extra_objects/add_curve_spirofit_bouncespline.py +++ b/add_curve_extra_objects/add_curve_spirofit_bouncespline.py @@ -18,12 +18,12 @@ bl_info = { - "name": "SpiroFit and BounceSpline", + "name": "SpiroFit, BounceSpline and Catenary", "author": "Antonio Osprite, Liero, Atom, Jimmy Hazevoet", "version": (0, 2, 0), "blender": (2, 78, 0), - "location": "Toolshelf > Misc Tab", - "description": "SpiroFit and BounceSpline adds splines to Mesh", + "location": "Toolshelf > Create Tab", + "description": "SpiroFit and BounceSpline adds splines to selected mesh", "warning": "", "wiki_url": "", "category": "Object", @@ -37,6 +37,7 @@ from bpy.props import ( FloatProperty, IntProperty, ) +from bpy.types import Operator from mathutils import ( Matrix, Vector, @@ -44,14 +45,14 @@ from mathutils import ( from math import ( sin, cos, - pi + pi, + sqrt, + pow ) -from bpy.types import Operator import random as r - # ------------------------------------------------------------ -# + def use_random_seed(seed): r.seed(seed) return @@ -60,18 +61,26 @@ def use_random_seed(seed): # Generate new curve object from given points # ------------------------------------------------------------ -def add_curve_object(verts, matrix, - x_ray=False, - spline_type='BEZIER', - spline_resolution=12, - bevel=0.0, - bevel_resolution=0, - spline_random_radius=0.0): - - curve = bpy.data.curves.new('Spline','CURVE') +def add_curve_object( + verts, + matrix, + spline_name="Spline", + x_ray=False, + spline_type='BEZIER', + spline_resolution=12, + bevel=0.0, + bevel_resolution=0, + extrude=0.0, + spline_random_radius=0.0, + twist_mode='MINIMUM', + twist_smooth=0.0, + tilt=0.0 + ): + + curve = bpy.data.curves.new(spline_name,'CURVE') curve.dimensions = '3D' spline = curve.splines.new(spline_type) - cur = bpy.data.objects.new('Curve',curve) + cur = bpy.data.objects.new(spline_name,curve) if spline_type == 'BEZIER': spline.bezier_points.add(int(len(verts)-1)) @@ -80,6 +89,7 @@ def add_curve_object(verts, matrix, spline.bezier_points[i].handle_right_type = 'AUTO' spline.bezier_points[i].handle_left_type = 'AUTO' spline.bezier_points[i].radius += r.random() * spline_random_radius + spline.bezier_points[i].tilt = tilt else: spline.points.add(int(len(verts)-1)) for i in range(len(verts)): @@ -91,16 +101,44 @@ def add_curve_object(verts, matrix, cur.data.fill_mode = 'FULL' cur.data.bevel_depth = bevel cur.data.bevel_resolution = bevel_resolution - cur.matrix_world = matrix - if x_ray: + cur.data.extrude = extrude + cur.data.twist_mode = twist_mode + cur.data.twist_smooth = twist_smooth + if matrix is None: + cur.select = True + bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS') + cur.select = False + else: + cur.matrix_world = matrix + if x_ray is True: cur.show_x_ray = x_ray return +#------------------------------------------------------------ +def draw_spline_settings(self, context): + layout = self.layout + col = layout.column(align=True) + col.prop(self, 'spline_type') + col.separator() + col.prop(self, 'resolution_u') + col.prop(self, 'bevel') + col.prop(self, 'bevel_res') + if self.spline_type == 'BEZIER': + col.prop(self, 'random_radius') + col.prop(self, 'extrude') + col.separator() + col.prop(self, 'twist_mode') + col.separator() + if self.twist_mode == 'TANGENT': + col.prop(self, 'twist_smooth') + col.prop(self, 'tilt') + # ------------------------------------------------------------ # Spirofit, original blender 2.45 script by: Antonio Osprite # http://www.kino3d.com/forum/viewtopic.php?t=5374 # ------------------------------------------------------------ +# Build a spiral that fit the active object def distance(v1, v2): d = (Vector(v1) - Vector(v2)).length @@ -114,26 +152,16 @@ def spiral_point(step, radius, z_coord, spires, waves, wave_height, rndm): return [x, y, z] -# ray cast def object_mapping_ray_cast(obj, vert, center, offset): - intersections = [] ray = Vector(vert) orig = Vector(center) direction = ray - orig poly = obj.data.polygons - for f in poly: - foo, hit, nor, index = obj.ray_cast(orig, direction) - if hit: - intersections.append(hit + offset * nor) - - if len(intersections) > 0: - mapped = min([(distance(i, vert), i) for i in intersections])[1] - else: - mapped = orig + foo, hit, nor, index = obj.ray_cast(orig, direction) + mapped = hit + offset * nor return [mapped[0], mapped[1], mapped[2]] -# closest point def object_mapping_closest_point(obj, vert, offset): cpom = obj.closest_point_on_mesh(vert) mapped = cpom[1] + cpom[2] * offset @@ -141,15 +169,15 @@ def object_mapping_closest_point(obj, vert, offset): def spirofit_spline(obj, - spires=4, spire_resolution=4, + spires=4, + offset=0.0, waves=0, wave_height=0.0, rndm_spire=0.0, - offset=0.0, + direction=False, map_method='RAYCAST'): - points = [] bb = obj.bound_box bb_xmin = min([ v[0] for v in bb ]) bb_ymin = min([ v[1] for v in bb ]) @@ -163,20 +191,16 @@ def spirofit_spline(obj, cx = (bb_xmax + bb_xmin) / 2.0 cy = (bb_ymax + bb_ymin) / 2.0 center = [cx, cy, bb_zmin] - - cp = spiral_point(bb_zmin, radius, bb_zmin, spires, waves, wave_height, 0) - if map_method == 'RAYCAST': - cp = object_mapping_ray_cast(obj, cp, center, offset) - elif map_method == 'CLOSESTPOINT': - cp = object_mapping_closest_point(obj, cp, offset) + points = [] steps = spires * spire_resolution - for i in range(1, steps + 1): + for i in range(steps + 1): t = bb_zmin + (2 * pi / steps) * i z = bb_zmin + (float(height) / steps) * i center = [cx, cy, z] - - cp = spiral_point(t, radius, z, spires, waves, wave_height, rndm_spire) + if direction is True: + t = -t + cp = spiral_point(-t, radius, z, spires, waves, wave_height, rndm_spire) if map_method == 'RAYCAST': cp = object_mapping_ray_cast(obj, cp, center, offset) elif map_method == 'CLOSESTPOINT': @@ -185,7 +209,6 @@ def spirofit_spline(obj, points.append(cp) return points - # ------------------------------------------------------------ class SpiroFitSpline(bpy.types.Operator): @@ -195,107 +218,148 @@ class SpiroFitSpline(bpy.types.Operator): bl_options = {'REGISTER', 'UNDO', 'PRESET'} map_method = bpy.props.EnumProperty( - name="Mapping Method", - default='CLOSESTPOINT', - description="Mapping method", - items=[('RAYCAST', 'Ray cast', 'Ray cast'), - ('CLOSESTPOINT', 'Closest point', 'Closest point')] - ) - + name="Mapping Method", + default='RAYCAST', + description="Mapping method", + items=[('RAYCAST', 'Ray cast', 'Ray casting'), + ('CLOSESTPOINT', 'Closest point', 'Closest point on mesh')] + ) + direction = bpy.props.BoolProperty( + name="Direction", + description="Spire direction", + default=False + ) spire_resolution = bpy.props.IntProperty( - name="Spire Resolution", - default=8, - min=3, - max=256, - soft_max=128, - description="Spire resolution for one turn" - ) + name="Spire Resolution", + default=8, + min=3, + max=256, + soft_max=128, + description="Number of steps for one turn" + ) spires = bpy.props.IntProperty( - name="Spires", - default=4, - min=1, - max=512, - soft_max=256, - description="Number of spire turns" - ) + name="Spires", + default=4, + min=1, + max=512, + soft_max=256, + description="Number of turns" + ) + offset = bpy.props.FloatProperty( + name="Offset", + default=0.0, + precision=3, + description="Use normal direction to offset spline" + ) waves = bpy.props.IntProperty( - name="Waves", - default=0, - min=0, - description="Waves amount" - ) + name="Waves", + default=0, + min=0, + description="Waves amount" + ) wave_height = bpy.props.FloatProperty( - name="Wave intensity", - default=0.1, - min=0.0, - description="Wave intensity scale" - ) + name="Wave Intensity", + default=0.25, + min=0.0, + precision=3, + description="Wave intensity scale" + ) rndm_spire = bpy.props.FloatProperty( - name="Randomize", - default=0.0, - min=0.0, - description="Randomize spire" - ) - offset = bpy.props.FloatProperty( - name="Offset", - default=0.0, - description="Use normal direction to offset spline" - ) + name="Randomise", + default=0.0, + min=0.0, + precision=3, + description="Randomise spire" + ) + + spline_name = bpy.props.StringProperty( + name="Name", + default="SpiroFit" + ) spline_type = bpy.props.EnumProperty( - name="Spline type", - default='BEZIER', - description="Spline type", - items=[('POLY', 'Poly', 'POLY'), - ('BEZIER', 'Bezier', 'BEZIER')] - ) - spline_resolution = bpy.props.IntProperty( - name="Resolution u", - default=12, - min=0, - max=64, - description="Curve resolution u" - ) + name="Spline Type", + default='BEZIER', + description="Spline type", + items=[('POLY', 'Poly', 'Poly spline'), + ('BEZIER', 'Bezier', 'Bezier spline')] + ) + resolution_u = bpy.props.IntProperty( + name="Resolution U", + default=12, + min=0, + max=64, + description="Curve resolution u" + ) bevel = bpy.props.FloatProperty( - name="Bevel radius", - default=0.0, - min=0.0, - precision=3, - description="Bevel depth" - ) + name="Bevel Radius", + default=0.0, + min=0.0, + precision=3, + description="Bevel depth" + ) bevel_res = bpy.props.IntProperty( - name="Bevel resolution", - default=0, - min=0, - max=32, - description="Bevel resolution" - ) - spline_random_radius = bpy.props.FloatProperty( - name="Random bevel radius", - default=0.0, - min=0.0, - description="Random radius amount" - ) - random_seed = bpy.props.IntProperty( - name="Random seed", - default=2, - min=0, - description="Random seed number" - ) + name="Bevel Resolution", + default=0, + min=0, + max=32, + description="Bevel resolution" + ) + random_radius = bpy.props.FloatProperty( + name="Randomise Radius", + default=0.0, + min=0.0, + precision=3, + description="Random radius amount" + ) + extrude = bpy.props.FloatProperty( + name="Extrude", + default=0.0, + min=0.0, + precision=3, + description="Extrude amount" + ) + twist_mode = bpy.props.EnumProperty( + name="Twisting", + default='MINIMUM', + description="Twist method, type of tilt calculation", + items=[('Z_UP', "Z-Up", 'Z Up'), + ('MINIMUM', "Minimum", 'Minimum'), + ('TANGENT', "Tangent", 'Tangent')] + ) + twist_smooth = bpy.props.FloatProperty( + name="Smooth", + default=0.0, + min=0.0, + precision=3, + description="Twist smoothing amount for tangents" + ) + tilt = bpy.props.FloatProperty( + name="Tilt", + default=0.0, + precision=3, + description="Spline handle tilt" + ) x_ray = bpy.props.BoolProperty( - name="X-Ray", - default=True, - description = "Make the object draw in front of others" - ) + name="X-Ray", + default=True, + description = "Make the object draw in front of others" + ) + random_seed = bpy.props.IntProperty( + name="Random Seed", + default=1, + min=0, + description="Random seed number" + ) refresh = bpy.props.BoolProperty( - name="Refresh", - description="Refresh spline", - default=False - ) + name="Refresh", + description="Refresh spline", + default=False + ) auto_refresh = bpy.props.BoolProperty( - name="Auto", - description="Auto refresh spline", - default=True - ) + name="Auto", + description="Auto refresh spline", + default=True + ) @classmethod @@ -327,24 +391,32 @@ class SpiroFitSpline(bpy.types.Operator): if self.random_seed: use_random_seed(self.random_seed) - points = spirofit_spline(obj, - self.spires, + points = spirofit_spline( + obj, self.spire_resolution, + self.spires, + self.offset, self.waves, self.wave_height, self.rndm_spire, - self.offset, + self.direction, self.map_method ) - add_curve_object(points, + add_curve_object( + points, matrix, + self.spline_name, self.x_ray, self.spline_type, - self.spline_resolution, + self.resolution_u, self.bevel, self.bevel_res, - self.spline_random_radius + self.extrude, + self.random_radius, + self.twist_mode, + self.twist_smooth, + self.tilt ) if self.auto_refresh is False: @@ -367,27 +439,24 @@ class SpiroFitSpline(bpy.types.Operator): row.prop(self, 'auto_refresh', toggle=True, icon='AUTO', text="") row.prop(self, 'refresh', toggle=True, icon='FILE_REFRESH', text="") row.separator() - properties = row.operator('object.add_spirofit_spline', text="Add New") + row.operator('object.add_spirofit_spline', text="Add New") + + col = layout.column(align=True) + col.prop(self, 'spline_name') col.separator() - col = layout.column(align=False) col.prop(self, 'map_method') - col = layout.column(align=True) + col.separator() col.prop(self, 'spire_resolution') - col.prop(self, 'spires') + row = col.row(align=True).split(0.9,align=True) + row.prop(self, 'spires') + row.prop(self, 'direction', toggle=True, text="", icon='ARROW_LEFTRIGHT') col.prop(self, 'offset') col.prop(self, 'waves') col.prop(self, 'wave_height') col.prop(self, 'rndm_spire') col.prop(self, 'random_seed') - col.separator() - col = layout.column(align=True) - col.prop(self, 'spline_type') - col.separator() - col.prop(self, 'spline_resolution') - col.prop(self, 'bevel') - if self.spline_type == 'BEZIER': - col.prop(self, 'spline_random_radius') - col.prop(self, 'bevel_res') + + draw_spline_settings(self, context) # ------------------------------------------------------------ @@ -395,6 +464,7 @@ class SpiroFitSpline(bpy.types.Operator): # Original script by Liero and Atom # https://blenderartists.org/forum/showthread.php?331750-Fiber-Mesh-Emulation # ------------------------------------------------------------ + def noise(var=1): rand = Vector((r.gauss(0,1), r.gauss(0,1), r.gauss(0,1))) vec = rand.normalized() * var @@ -440,7 +510,6 @@ def bounce_spline(obj, return points return points - # ------------------------------------------------------------ class BounceSpline(bpy.types.Operator): @@ -449,95 +518,131 @@ class BounceSpline(bpy.types.Operator): bl_description="Fill selected mesh with a bounce spline" bl_options = {'REGISTER', 'UNDO', 'PRESET'} - random_seed = bpy.props.IntProperty( - name="Random seed", - default=1, - min=0, - description="Random seed number" - ) bounce_number = bpy.props.IntProperty( - name="Bounces", - default=500, - min=1, - max=99999, - soft_max=9999, - description="Number of Bounces" - ) + name="Bounces", + default=500, + min=1, + max=99999, + soft_max=9999, + description="Number of bounces" + ) ang_noise = bpy.props.FloatProperty( - name="Angular noise", - default=0.25, - min=0.0, - description="Add some noise to ray direction" - ) + name="Angular Noise", + default=0.25, + min=0.0, + precision=3, + description="Add some noise to ray direction" + ) offset = bpy.props.FloatProperty( - name="Offset", - default=0.0, - description="Use normal direction to offset spline" - ) + name="Offset", + default=0.0, + precision=3, + description="Use normal direction to offset spline" + ) extra = bpy.props.IntProperty( - name="Extra", - default=50, - min=0, - max=1000, - soft_min=0, - soft_max=500, - description="Number of extra tries if it fails to hit mesh" - ) + name="Extra", + default=50, + min=0, + max=1000, + soft_min=0, + soft_max=500, + description="Number of extra tries if it fails to hit mesh" + ) active_face = bpy.props.BoolProperty( - name="Active face", - default=False, - description = "Starts from active face or a random one" - ) + name="Active Face", + default=False, + description = "Starts from active face or a random one" + ) + + spline_name = bpy.props.StringProperty( + name="Name", + default="BounceSpline" + ) spline_type = bpy.props.EnumProperty( - name="Spline type", - default='BEZIER', - description="Spline type", - items=[('POLY', 'Poly', 'POLY'), - ('BEZIER', 'Bezier', 'BEZIER')] - ) - spline_resolution = bpy.props.IntProperty( - name="Resolution u", - default=12, - min=0, - max=64, - description="Curve resolution u" - ) + name="Spline Type", + default='BEZIER', + description="Spline type", + items=[('POLY', 'Poly', 'Poly spline'), + ('BEZIER', 'Bezier', 'Bezier spline')] + ) + resolution_u = bpy.props.IntProperty( + name="Resolution U", + default=12, + min=0, + max=64, + description="Curve resolution u" + ) bevel = bpy.props.FloatProperty( - name="Bevel radius", - default=0.0, - min=0.0, - precision=3, - description="Bevel depth" - ) - + name="Bevel Radius", + default=0.0, + min=0.0, + precision=3, + description="Bevel depth" + ) bevel_res = bpy.props.IntProperty( - name="Bevel resolution", - default=0, - min=0, - max=32, - description="Bevel resolution" - ) - spline_random_radius = bpy.props.FloatProperty( - name="Random bevel radius", - default=0.0, - min=0.0, - description="Random radius amount" - ) + name="Bevel Resolution", + default=0, + min=0, + max=32, + description="Bevel resolution" + ) + random_radius = bpy.props.FloatProperty( + name="Randomise Radius", + default=0.0, + min=0.0, + precision=3, + description="Random radius amount" + ) + extrude = bpy.props.FloatProperty( + name="Extrude", + default=0.0, + min=0.0, + precision=3, + description="Extrude amount" + ) + twist_mode = bpy.props.EnumProperty( + name="Twisting", + default='MINIMUM', + description="Twist method, type of tilt calculation", + items=[('Z_UP', "Z-Up", 'Z Up'), + ('MINIMUM', "Minimum", 'Minimum'), + ('TANGENT', "Tangent", 'Tangent')] + ) + twist_smooth = bpy.props.FloatProperty( + name="Smooth", + default=0.0, + min=0.0, + precision=3, + description="Twist smoothing amount for tangents" + ) + tilt = bpy.props.FloatProperty( + name="Tilt", + default=0.0, + precision=3, + description="Spline handle tilt" + ) x_ray = bpy.props.BoolProperty( - name="X-Ray", - default=True, - description = "Make the object draw in front of others" - ) + name="X-Ray", + default=True, + description = "Make the object draw in front of others" + ) + random_seed = bpy.props.IntProperty( + name="Random Seed", + default=1, + min=0, + description="Random seed number" + ) refresh = bpy.props.BoolProperty( - name="Refresh", - description="Refresh spline", - default=False - ) + name="Refresh", + description="Refresh spline", + default=False + ) auto_refresh = bpy.props.BoolProperty( - name="Auto", - description="Auto refresh spline", - default=True - ) + name="Auto", + description="Auto refresh spline", + default=True + ) + @classmethod def poll(self, context): @@ -567,21 +672,30 @@ class BounceSpline(bpy.types.Operator): if self.random_seed: use_random_seed(self.random_seed) - points = bounce_spline(obj, + points = bounce_spline( + obj, self.bounce_number, self.ang_noise, self.offset, self.extra, - self.active_face) + self.active_face + ) - add_curve_object(points, + add_curve_object( + points, obj.matrix_world, + self.spline_name, self.x_ray, self.spline_type, - self.spline_resolution, + self.resolution_u, self.bevel, self.bevel_res, - self.spline_random_radius) + self.extrude, + self.random_radius, + self.twist_mode, + self.twist_smooth, + self.tilt + ) if self.auto_refresh is False: self.refresh = False @@ -594,7 +708,6 @@ class BounceSpline(bpy.types.Operator): layout = self.layout col = layout.column(align=True) row = col.row(align=True) - row.prop(self, 'x_ray', toggle=True) row.separator() if self.auto_refresh is False: @@ -604,26 +717,272 @@ class BounceSpline(bpy.types.Operator): row.prop(self, 'auto_refresh', toggle=True, icon='AUTO', text="") row.prop(self, 'refresh', toggle=True, icon='FILE_REFRESH', text="") row.separator() - properties = row.operator('object.add_bounce_spline', text="Add New") - col.separator() + row.operator('object.add_bounce_spline', text="Add New") + col = layout.column(align=True) - row = col.row(align=True) + col.prop(self, 'spline_name') + col.separator() col.prop(self, 'bounce_number') - col.prop(self, 'ang_noise') + row = col.row(align=True).split(0.9, align=True) + row.prop(self, 'ang_noise') + row.prop(self, 'active_face', toggle=True, text="", icon='FACESEL') col.prop(self, 'offset') col.prop(self, 'extra') col.prop(self, 'random_seed') - col.separator() - col.prop(self, 'active_face', toggle=False) + + draw_spline_settings(self, context) + + +#------------------------------------------------------------ +# Hang Catenary curve between two selected objects +#------------------------------------------------------------ + +def catenary_curve( + start=[-2, 0, 2], + end=[2, 0, 2], + steps=24, + a=2.0 + ): + + points=[] + lx = end[0] - start[0] + ly = end[1] - start[1] + lr = sqrt(pow(lx, 2) + pow(ly, 2)) + lv = lr / 2 - (end[2] - start[2]) * a / lr + zv = start[2] - pow(lv, 2) / (2 * a) + slx = lx / steps + sly = ly / steps + slr = lr / steps + i = 0 + while i <= steps: + x = start[0] + i * slx + y = start[1] + i * sly + z = zv+pow((i * slr) - lv, 2) / (2 * a) + points.append([x, y, z]) + i += 1 + return points + +#------------------------------------------------------------ +class CatenaryCurve(bpy.types.Operator): + bl_idname = "object.add_catenary_curve" + bl_label = "Catenary" + bl_description="Hang a catenary curve between two selected objects" + bl_options = {'REGISTER', 'UNDO', 'PRESET'} + + start_location = bpy.props.StringProperty( + name="Start", + default="", + description="Catenary start location", + ) + end_location = bpy.props.StringProperty( + name="End", + default="", + description="Catenary end location", + ) + steps = bpy.props.IntProperty( + name="Steps", + description="Resolution of the curve", + default=24, + min=2, + max=256, + ) + var_a = bpy.props.FloatProperty( + name="a", + description="Catenary variable a", + precision=3, + default=2.0, + min=0.0, soft_min=0.01, + max=100.0, soft_max=10.0 + ) + + spline_name = bpy.props.StringProperty( + name="Name", + default="Catenary" + ) + spline_type = bpy.props.EnumProperty( + name="Spline Type", + default='BEZIER', + description="Spline type", + items=[('POLY', 'Poly', 'Poly spline'), + ('BEZIER', 'Bezier', 'Bezier spline')] + ) + resolution_u = bpy.props.IntProperty( + name="Resolution U", + default=12, + min=0, + max=64, + description="Curve resolution u" + ) + bevel = bpy.props.FloatProperty( + name="Bevel Radius", + default=0.0, + min=0.0, + precision=3, + description="Bevel depth" + ) + bevel_res = bpy.props.IntProperty( + name="Bevel Resolution", + default=0, + min=0, + max=32, + description="Bevel resolution" + ) + random_radius = bpy.props.FloatProperty( + name="Randomise Radius", + default=0.0, + min=0.0, + precision=3, + description="Random radius amount" + ) + extrude = bpy.props.FloatProperty( + name="Extrude", + default=0.0, + min=0.0, + precision=3, + description="Extrude amount" + ) + twist_mode = bpy.props.EnumProperty( + name="Twisting", + default='MINIMUM', + description="Twist method, type of tilt calculation", + items=[('Z_UP', "Z-Up", 'Z Up'), + ('MINIMUM', "Minimum", 'Minimum'), + ('TANGENT', "Tangent", 'Tangent')] + ) + twist_smooth = bpy.props.FloatProperty( + name="Smooth", + default=0.0, + min=0.0, + precision=3, + description="Twist smoothing amount for tangents" + ) + tilt = bpy.props.FloatProperty( + name="Tilt", + default=0.0, + precision=3, + description="Spline handle tilt" + ) + x_ray = bpy.props.BoolProperty( + name="X-Ray", + default=False, + description = "Make the object draw in front of others" + ) + random_seed = bpy.props.IntProperty( + name="Random Seed", + default=1, + min=0, + description="Random seed number" + ) + refresh = bpy.props.BoolProperty( + name="Refresh", + description="Refresh spline", + default=False + ) + auto_refresh = bpy.props.BoolProperty( + name="Auto", + description="Auto refresh spline", + default=True + ) + + def draw(self, context): + scene = bpy.context.scene + layout = self.layout + col = layout.column(align=True) + row = col.row(align=True) + row.prop(self, 'x_ray', toggle=True) + row.separator() + if self.auto_refresh is False: + self.refresh = False + elif self.auto_refresh is True: + self.refresh = True + row.prop(self, 'auto_refresh', toggle=True, icon='AUTO', text="") + row.prop(self, 'refresh', toggle=True, icon='FILE_REFRESH', text="") + row.separator() + row.operator('object.add_catenary_curve', text="Add New") + col = layout.column(align=True) - col.prop(self, 'spline_type') + col.prop(self, 'spline_name') + col.separator() + col.prop_search(self, "start_location", scene, "objects") + col.prop_search(self, "end_location", scene, "objects") col.separator() - col.prop(self, 'spline_resolution') - col.prop(self, 'bevel') - if self.spline_type == 'BEZIER': - col.prop(self, 'spline_random_radius') - col.prop(self, 'bevel_res') + col.prop(self, 'steps') + col.prop(self, 'var_a') + draw_spline_settings(self, context) + + col = layout.column(align=True) + col.prop(self, 'random_seed') + + + @classmethod + def poll(self, context): + ob = context.active_object + return (ob is not None) + + + def invoke(self, context, event): + self.refresh = True + return self.execute(context) + + + def execute(self, context): + if not self.refresh: + return {'PASS_THROUGH'} + + undo = context.user_preferences.edit.use_global_undo + context.user_preferences.edit.use_global_undo = False + + if self.random_seed: + use_random_seed(self.random_seed) + + matrix = None + + try: + ob1 = bpy.data.objects[self.start_location] + ob2 = bpy.data.objects[self.end_location] + start = ob1.location + end = ob2.location + if end == start: + start = [-2, 0, 2] + end= [2, 0, 2] + sel = bpy.context.selected_objects + for o in sel: + o.select = False + ob1.select = True + ob2.select = True + except: + start = [-2, 0, 2] + end= [2, 0, 2] + + points = catenary_curve( + start, + end, + self.steps, + self.var_a + ) + + add_curve_object( + points, + matrix, + self.spline_name, + self.x_ray, + self.spline_type, + self.resolution_u, + self.bevel, + self.bevel_res, + self.extrude, + self.random_radius, + self.twist_mode, + self.twist_smooth, + self.tilt + ) + + if self.auto_refresh is False: + self.refresh = False + + context.user_preferences.edit.use_global_undo = undo + return {'FINISHED'} # ------------------------------------------------------------ # Tools Panel > Misc @@ -643,8 +1002,9 @@ class SplinePanel( bpy.types.Panel ): col = self.layout.column() col.operator(SpiroFitSpline.bl_idname, icon="FORCE_MAGNETIC") col.operator(BounceSpline.bl_idname, icon="FORCE_HARMONIC") + col.operator(CatenaryCurve.bl_idname, icon="FORCE_CURVE") -# ------------------------------------------------------------ # icon="CURVE_DATA" +# ------------------------------------------------------------ # Menu: Add > Curve > # ------------------------------------------------------------ @@ -652,6 +1012,7 @@ class SplinePanel( bpy.types.Panel ): def menu_func(self, context): self.layout.operator(SpiroFitSpline.bl_idname, icon="PLUGIN") self.layout.operator(BounceSpline.bl_idname, icon="PLUGIN") + self.layout.operator(CatenaryCurve.bl_idname, icon="PLUGIN") ''' # ------------------------------------------------------------ @@ -659,15 +1020,17 @@ def menu_func(self, context): # ------------------------------------------------------------ def register(): + bpy.utils.register_class(SplinePanel) bpy.utils.register_class(SpiroFitSpline) bpy.utils.register_class(BounceSpline) - bpy.utils.register_class(SplinePanel) + bpy.utils.register_class(CatenaryCurve) #bpy.types.INFO_MT_curve_add.append(menu_func) def unregister(): + bpy.utils.unregister_class(SplinePanel) bpy.utils.unregister_class(SpiroFitSpline) bpy.utils.unregister_class(BounceSpline) - bpy.utils.unregister_class(SplinePanel) + bpy.utils.unregister_class(CatenaryCurve) #bpy.types.INFO_MT_curve_add.remove(menu_func) if __name__ == "__main__": -- cgit v1.2.3