Last active
March 3, 2016 09:23
-
-
Save squarednob/5fc65f3d314c0657b966 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import bpy | |
def dupliOnCurve(curve_length_effect=None, replace=None): | |
''' | |
When you want to duplicate an object on object: Simply do "object > make links > object data". | |
The function is optimised for an object to duplicate on curves, althoubh it can be used to duplicate on objects. | |
Usage: | |
1. Multiple selecte curves, and lastly select an object as an object to be duplicated. | |
2. Paste the code on text editor which can be found in scripting layout. | |
Arguments: | |
curve_length_rate: | |
How intense the length of curve affect the scale of duplicated object. 0 is no effect. | |
Default is 0. | |
replace: | |
If True, the selected curves will be removed, and only the duplicated objects reimans. | |
If False, the selected curves won't be removed. | |
''' | |
# Default value of curve_length_rate is 0. | |
if curve_length_effect == None: | |
curve_length_effect = 0 | |
else: | |
curve_length_effect = curve_length_effect | |
# Default value of replace is False. | |
if replace == True: | |
replace == True | |
else: | |
replace = False | |
# Name of lastly selected active object to be duplicated. | |
active_object_name = bpy.context.scene.objects.active.name | |
# Name list of selected curves/objects, except for lastly selected active object. | |
selected_object_names = [obj.name for obj in bpy.context.selected_objects if obj.name != active_object_name] | |
# List of edge lengths for curves/objects. | |
edge_length_list = [] | |
# Convert the selected curves into objects, and add the edge lenght to edge_length_list. | |
for selected_object_name in selected_object_names: | |
# Asign each selected object. | |
selected_object = bpy.data.objects[selected_object_name] | |
# If replace == False, the original curve/object is duplicated. | |
# (it's not duplication of selected object on curves, just for keeping original curves). | |
if replace == False: | |
_makeDupli(selected_object) | |
# If it's curve, convert the curve into object. | |
if selected_object.type == "CURVE": | |
_curveToMesh(selected_object) | |
# calculate the lenght of edge, then append it to edge_length_list. | |
if curve_length_effect != 0: | |
edge_length = _getLength(selected_object) | |
edge_length_list.append(edge_length) | |
# Calculate average edge length. | |
avarage_edge_length = sum(edge_length_list)/len(edge_length_list) | |
# Re-select and change their scale relfecting edge length. | |
bpy.ops.object.select_all(action='DESELECT') | |
for i, selected_object_name in enumerate(selected_object_names): | |
selected_object = bpy.data.objects[selected_object_name] | |
selected_object.select = True | |
# Effect for scale = curve_length_effect * (its edge length - average edge lenght) - average edge length. | |
try: | |
scale_rate = curve_length_effect * (edge_length_list[i] - avarage_edge_length) / avarage_edge_length | |
# When avarage_edge_length is 0, set scale_rate=0. | |
except ZeroDivisionError: | |
scale_rate = 0 | |
# Change scaled of selected object into the same as scale of duplicated object + scale_rate. | |
selected_object.scale.x = bpy.data.objects[active_object_name].scale.x + scale_rate | |
selected_object.scale.y = bpy.data.objects[active_object_name].scale.y + scale_rate | |
selected_object.scale.z = bpy.data.objects[active_object_name].scale.z + scale_rate | |
# Re-activate the object which was selected as active object at first. | |
bpy.context.scene.objects.active = bpy.data.objects[active_object_name] | |
# Duplicate active object on the curves by linking the data to them. | |
bpy.ops.object.make_links_data(type='OBDATA') | |
# Duplicate curves to keep original curves. | |
def _makeDupli(selected_object): | |
bpy.ops.object.select_all(action='DESELECT') | |
selected_object.select = True | |
# Make duplication. | |
bpy.ops.object.duplicate_move() | |
bpy.ops.object.select_all(action='DESELECT') | |
# Convert curve into mesh. | |
def _curveToMesh(selected_object): | |
# Select and active only the curve per loop. | |
bpy.ops.object.select_all(action='DESELECT') | |
selected_object.select = True | |
bpy.context.scene.objects.active = selected_object | |
# Convert curve into mesh. | |
bpy.ops.object.convert(target='MESH', keep_original=False) | |
bpy.ops.object.select_all(action='DESELECT') | |
# Calculate edge length of a curve. | |
def _getLength(selected_object): | |
bpy.ops.object.select_all(action='DESELECT') | |
selected_object.select = True | |
bpy.context.scene.objects.active = selected_object | |
# Temporary duplicate it. | |
bpy.ops.object.duplicate_move() | |
try: | |
# Change origin to center to calculate the lenght easily. | |
bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) | |
# Calculate the edge length. | |
mesh_data = bpy.context.active_object.data | |
edge_length = 0 | |
for edge in mesh_data.edges: | |
vert0 = mesh_data.vertices[edge.vertices[0]].co | |
vert1 = mesh_data.vertices[edge.vertices[1]].co | |
edge_length += (vert0-vert1).length | |
# When the length cannot be calculated, set 0. | |
except: | |
edge_length = 0 | |
# Delete temporal duplicated object. | |
bpy.ops.object.delete() | |
bpy.ops.object.select_all(action='DESELECT') | |
return edge_length | |
# Execute. | |
dupliOnCurve(curve_length_effect=0.5, replace=False) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment