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:
Diffstat (limited to 'add_advanced_objects_menu/rope_alpha.py')
-rw-r--r--add_advanced_objects_menu/rope_alpha.py832
1 files changed, 832 insertions, 0 deletions
diff --git a/add_advanced_objects_menu/rope_alpha.py b/add_advanced_objects_menu/rope_alpha.py
new file mode 100644
index 00000000..904168a1
--- /dev/null
+++ b/add_advanced_objects_menu/rope_alpha.py
@@ -0,0 +1,832 @@
+# Copyright (c) 2012 Jorge Hernandez - Melendez
+
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# TODO : prop names into English, add missing tooltips
+
+bl_info = {
+ "name": "Rope Creator",
+ "description": "Dynamic rope (with cloth) creator",
+ "author": "Jorge Hernandez - Melenedez",
+ "version": (0, 2, 2),
+ "blender": (2, 7, 3),
+ "location": "Left Toolbar > ClothRope",
+ "warning": "",
+ "wiki_url": "",
+ "category": "Add Mesh"
+}
+
+
+import bpy
+from bpy.types import Operator
+from bpy.props import (
+ BoolProperty,
+ FloatProperty,
+ IntProperty,
+ )
+
+
+def desocultar(quien):
+ if quien == "todo":
+ for ob in bpy.data.objects:
+ ob.hide = False
+ else:
+ bpy.data.objects[quien].hide = False
+
+
+def deseleccionar_todo():
+ bpy.ops.object.select_all(action='DESELECT')
+
+
+def seleccionar_todo():
+ bpy.ops.object.select_all(action='SELECT')
+
+
+def salir_de_editmode():
+ if bpy.context.mode in ["EDIT", "EDIT_MESH", "EDIT_CURVE"]:
+ bpy.ops.object.mode_set(mode='OBJECT')
+
+
+# Clear scene:
+def reset_scene():
+ desocultar("todo")
+ # playback to the start
+ bpy.ops.screen.frame_jump(end=False)
+ try:
+ salir_de_editmode()
+ except:
+ pass
+ try:
+ area = bpy.context.area
+ # expand everything in the outliner to be able to select children
+ old_type = area.type
+ area.type = 'OUTLINER'
+ bpy.ops.outliner.expanded_toggle()
+
+ # restore the original context
+ area.type = old_type
+
+ seleccionar_todo()
+ bpy.ops.object.delete(use_global=False)
+
+ except Exception as e:
+ print("\n[rope_alpha]\nfunction: reset_scene\nError: %s" % e)
+
+
+def entrar_en_editmode():
+ if bpy.context.mode == "OBJECT":
+ bpy.ops.object.mode_set(mode='EDIT')
+
+
+def select_all_in_edit_mode(ob):
+ if ob.mode != 'EDIT':
+ entrar_en_editmode()
+ bpy.ops.mesh.select_all(action="DESELECT")
+ bpy.context.tool_settings.mesh_select_mode = (True, False, False)
+ salir_de_editmode()
+ for v in ob.data.vertices:
+ if not v.select:
+ v.select = True
+ entrar_en_editmode()
+
+
+def deselect_all_in_edit_mode(ob):
+ if ob.mode != 'EDIT':
+ entrar_en_editmode()
+ bpy.ops.mesh.select_all(action="DESELECT")
+ bpy.context.tool_settings.mesh_select_mode = (True, False, False)
+ salir_de_editmode()
+ for v in ob.data.vertices:
+ if not v.select:
+ v.select = False
+ entrar_en_editmode()
+
+
+def which_vertex_are_selected(ob):
+ for v in ob.data.vertices:
+ if v.select:
+ print(str(v.index))
+ print("Vertex " + str(v.index) + " is selected")
+
+
+def seleccionar_por_nombre(nombre):
+ scn = bpy.context.scene
+ bpy.data.objects[nombre].select = True
+
+ scn.objects.active = bpy.data.objects[nombre]
+
+
+def deseleccionar_por_nombre(nombre):
+ bpy.data.objects[nombre].select = False
+
+
+def crear_vertices(ob):
+ ob.data.vertices.add(1)
+ ob.data.update
+
+
+def borrar_elementos_seleccionados(tipo):
+ if tipo == "vertices":
+ bpy.ops.mesh.delete(type='VERT')
+
+
+def obtener_coords_vertex_seleccionados():
+ coordenadas_de_vertices = []
+ for ob in bpy.context.selected_objects:
+ if ob.type == 'MESH':
+ for v in ob.data.vertices:
+ if v.select:
+ coordenadas_de_vertices.append([v.co[0], v.co[1], v.co[2]])
+ return coordenadas_de_vertices[0]
+
+
+def crear_locator(pos):
+ bpy.ops.object.empty_add(
+ type='PLAIN_AXES', radius=1, view_align=False,
+ location=(pos[0], pos[1], pos[2]),
+ layers=(True, False, False, False, False, False, False,
+ False, False, False, False, False, False, False,
+ False, False, False, False, False, False)
+ )
+
+
+def extruir_vertices(longitud, cuantos_segmentos):
+ bpy.ops.mesh.extrude_region_move(
+ MESH_OT_extrude_region={"mirror": False},
+ TRANSFORM_OT_translate={
+ "value": (longitud / cuantos_segmentos, 0, 0),
+ "constraint_axis": (True, False, False),
+ "constraint_orientation": 'GLOBAL', "mirror": False,
+ "proportional": 'DISABLED', "proportional_edit_falloff": 'SMOOTH',
+ "proportional_size": 1, "snap": False, "snap_target": 'CLOSEST',
+ "snap_point": (0, 0, 0), "snap_align": False, "snap_normal": (0, 0, 0),
+ "gpencil_strokes": False, "texture_space": False,
+ "remove_on_cancel": False, "release_confirm": False
+ }
+ )
+
+
+def select_all_vertex_in_curve_bezier(bc):
+ for i in range(len(bc.data.splines[0].points)):
+ bc.data.splines[0].points[i].select = True
+
+
+def deselect_all_vertex_in_curve_bezier(bc):
+ for i in range(len(bc.data.splines[0].points)):
+ bc.data.splines[0].points[i].select = False
+
+
+def ocultar_relationships():
+ for area in bpy.context.screen.areas:
+ if area.type == 'VIEW_3D':
+ area.spaces[0].show_relationship_lines = False
+
+
+class ClothRope(Operator):
+ bl_idname = "clot.rope"
+ bl_label = "Rope Cloth"
+ bl_description = ("Create a new Scene with a Cloth modifier\n"
+ "Rope Simulation with hooked Helper Objects")
+
+ ropelenght = IntProperty(
+ name="Rope Length",
+ description="Length of the generated Rope",
+ default=5
+ )
+ ropesegments = IntProperty(
+ name="Rope Segments",
+ description="Number of the Rope Segments",
+ default=5
+ )
+ qcr = IntProperty(
+ name="Collision Quality",
+ description="Rope's Cloth modifier collsion quality",
+ min=1, max=20,
+ default=20
+ )
+ substeps = IntProperty(
+ name="Rope Substeps",
+ description="Rope's Cloth modifier quality",
+ min=4, max=80,
+ default=50
+ )
+ resrope = IntProperty(
+ name="Rope Resolution",
+ description="Rope's Bevel resolution",
+ default=5
+ )
+ radiusrope = FloatProperty(
+ name="Radius",
+ description="Rope's Radius",
+ min=0.04, max=1,
+ default=0.04
+ )
+ hide_emptys = BoolProperty(
+ name="Hide Empties",
+ description="Hide Helper Objects",
+ default=False
+ )
+
+ def execute(self, context):
+ # add a new scene
+ bpy.ops.scene.new(type="NEW")
+ scene = bpy.context.scene
+ scene.name = "Test Rope"
+ seleccionar_todo()
+ longitud = self.ropelenght
+
+ # For the middle to have x segments between the first and
+ # last point, must add 1 to the quantity:
+ cuantos_segmentos = self.ropesegments + 1
+ calidad_de_colision = self.qcr
+ substeps = self.substeps
+ deseleccionar_todo()
+ # collect the possible empties that already exist in the data
+ empties_prev = [obj.name for obj in bpy.data.objects if obj.type == "EMPTY"]
+
+ # create an empty that will be the parent of everything
+ bpy.ops.object.empty_add(
+ type='SPHERE', radius=1, view_align=False, location=(0, 0, 0),
+ layers=(True, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False,
+ False, False, False, False)
+ )
+ ob = bpy.context.selected_objects[0]
+ ob.name = "Rope"
+ # .001 and friends
+ rope_name = ob.name
+ deseleccionar_todo()
+
+ # create a plane and delete it
+ bpy.ops.mesh.primitive_plane_add(
+ radius=1, view_align=False, enter_editmode=False, location=(0, 0, 0),
+ layers=(True, False, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False,
+ False, False, False)
+ )
+ ob = bpy.context.selected_objects[0]
+ # rename:
+ ob.name = "cuerda"
+ # .001 and friends
+ cuerda_1_name = ob.name
+
+ entrar_en_editmode() # enter edit mode
+ select_all_in_edit_mode(ob)
+
+ borrar_elementos_seleccionados("vertices")
+ salir_de_editmode() # leave edit mode
+ crear_vertices(ob) # create a vertex
+
+ # Creating a Group for the PIN
+ # Group contains the vertices of the pin and the Group.001 contains the single main line
+ entrar_en_editmode() # enter edit mode
+ bpy.ops.object.vertex_group_add() # create a group
+ select_all_in_edit_mode(ob)
+ bpy.ops.object.vertex_group_assign() # assign it
+
+ salir_de_editmode() # leave edit mode
+ ob.vertex_groups[0].name = "Pin"
+ deseleccionar_todo()
+ seleccionar_por_nombre(cuerda_1_name)
+
+ # extrude vertices:
+ for i in range(cuantos_segmentos):
+ entrar_en_editmode()
+ extruir_vertices(longitud, cuantos_segmentos)
+ # delete the PIN group
+ bpy.ops.object.vertex_group_remove_from()
+ # get the direction to create the locator on it's position
+ pos = obtener_coords_vertex_seleccionados()
+
+ salir_de_editmode() # leave edit mode
+ # create locator at position
+ crear_locator(pos)
+ deseleccionar_todo()
+ seleccionar_por_nombre(cuerda_1_name)
+ deseleccionar_todo()
+
+ seleccionar_por_nombre(cuerda_1_name) # select the rope
+ entrar_en_editmode()
+
+ pos = obtener_coords_vertex_seleccionados() # get their positions
+ salir_de_editmode()
+ # create the last locator
+ crear_locator(pos)
+ deseleccionar_todo()
+ seleccionar_por_nombre(cuerda_1_name)
+ entrar_en_editmode() # enter edit mode
+ bpy.ops.object.vertex_group_add() # Creating Master guide group
+ select_all_in_edit_mode(ob)
+ bpy.ops.object.vertex_group_assign() # and assing it
+ ob.vertex_groups[1].name = "Guide_rope"
+
+ # extrude the Curve so it has a minumum thickness for collide
+ bpy.ops.mesh.extrude_region_move(
+ MESH_OT_extrude_region={"mirror": False},
+ TRANSFORM_OT_translate={
+ "value": (0, 0.005, 0), "constraint_axis": (False, True, False),
+ "constraint_orientation": 'GLOBAL', "mirror": False,
+ "proportional": 'DISABLED', "proportional_edit_falloff": 'SMOOTH',
+ "proportional_size": 1, "snap": False, "snap_target": 'CLOSEST',
+ "snap_point": (0, 0, 0), "snap_align": False, "snap_normal": (0, 0, 0),
+ "gpencil_strokes": False, "texture_space": False,
+ "remove_on_cancel": False, "release_confirm": False
+ }
+ )
+ bpy.ops.object.vertex_group_remove_from()
+ deselect_all_in_edit_mode(ob)
+ salir_de_editmode()
+ bpy.ops.object.modifier_add(type='CLOTH')
+ bpy.context.object.modifiers["Cloth"].settings.use_pin_cloth = True
+ bpy.context.object.modifiers["Cloth"].settings.vertex_group_mass = "Pin"
+ bpy.context.object.modifiers["Cloth"].collision_settings.collision_quality = calidad_de_colision
+ bpy.context.object.modifiers["Cloth"].settings.quality = substeps
+
+ # Duplicate to convert into Curve:
+ # select the vertices that are the part of the Group.001
+ seleccionar_por_nombre(cuerda_1_name)
+ entrar_en_editmode()
+ bpy.ops.mesh.select_all(action="DESELECT")
+ bpy.context.tool_settings.mesh_select_mode = (True, False, False)
+ salir_de_editmode()
+ gi = ob.vertex_groups["Guide_rope"].index # get group index
+
+ for v in ob.data.vertices:
+ for g in v.groups:
+ if g.group == gi: # compare with index in VertexGroupElement
+ v.select = True
+
+ # now we have to make a table of names of cuerdas to see which one will be new
+ cuerda_names = [obj.name for obj in bpy.data.objects if "cuerda" in obj.name]
+
+ entrar_en_editmode()
+
+ # we already have the selected guide:
+ # duplicate it:
+ bpy.ops.mesh.duplicate_move(
+ MESH_OT_duplicate={"mode": 1},
+ TRANSFORM_OT_translate={
+ "value": (0, 0, 0), "constraint_axis": (False, False, False),
+ "constraint_orientation": 'GLOBAL', "mirror": False,
+ "proportional": 'DISABLED', "proportional_edit_falloff": 'SMOOTH',
+ "proportional_size": 1, "snap": False, "snap_target": 'CLOSEST',
+ "snap_point": (0, 0, 0), "snap_align": False, "snap_normal": (0, 0, 0),
+ "gpencil_strokes": False, "texture_space": False,
+ "remove_on_cancel": False, "release_confirm": False
+ }
+ )
+ # separate the selections:
+ bpy.ops.mesh.separate(type='SELECTED')
+ salir_de_editmode()
+ deseleccionar_todo()
+
+ cuerda_2_name = "cuerda.001"
+ test = []
+ for obj in bpy.data.objects:
+ if "cuerda" in obj.name and obj.name not in cuerda_names:
+ cuerda_2_name = obj.name
+ test.append(obj.name)
+
+ seleccionar_por_nombre(cuerda_2_name)
+
+ # from the newly created curve remove the Cloth:
+ bpy.ops.object.modifier_remove(modifier="Cloth")
+ # convert the Curve:
+ bpy.ops.object.convert(target='CURVE')
+
+ # all Empties that are not previously present
+ emptys = []
+ for eo in bpy.data.objects:
+ if eo.type == 'EMPTY' and eo.name not in empties_prev:
+ if eo.name != rope_name:
+ emptys.append(eo)
+
+ # select and deselect:
+ bc = bpy.data.objects[cuerda_2_name]
+ n = 0
+
+ for e in emptys:
+ deseleccionar_todo()
+ seleccionar_por_nombre(e.name)
+ seleccionar_por_nombre(bc.name)
+ entrar_en_editmode()
+ deselect_all_vertex_in_curve_bezier(bc)
+ bc.data.splines[0].points[n].select = True
+ bpy.ops.object.hook_add_selob(use_bone=False)
+ salir_de_editmode()
+ n = n + 1
+
+ ob = bpy.data.objects[cuerda_1_name]
+ n = 0
+
+ for e in emptys:
+ deseleccionar_todo()
+ seleccionar_por_nombre(e.name)
+ seleccionar_por_nombre(ob.name)
+ entrar_en_editmode()
+ bpy.ops.mesh.select_all(action="DESELECT")
+ bpy.context.tool_settings.mesh_select_mode = (True, False, False)
+ salir_de_editmode()
+
+ for v in ob.data.vertices:
+ if v.select:
+ v.select = False
+ ob.data.vertices[n].select = True
+ entrar_en_editmode()
+ bpy.ops.object.vertex_parent_set()
+
+ salir_de_editmode()
+ n = n + 1
+
+ # hide the Empties:
+ deseleccionar_todo()
+
+ # all parented to the spherical empty:
+ seleccionar_por_nombre(cuerda_2_name)
+ seleccionar_por_nombre(cuerda_1_name)
+ seleccionar_por_nombre(rope_name)
+ bpy.ops.object.parent_set(type='OBJECT', keep_transform=True)
+ deseleccionar_todo()
+
+ # do not display the relations
+ ocultar_relationships()
+ seleccionar_por_nombre(cuerda_2_name)
+
+ # curved rope settings:
+ bpy.context.object.data.fill_mode = 'FULL'
+ bpy.context.object.data.bevel_depth = self.radiusrope
+ bpy.context.object.data.bevel_resolution = self.resrope
+
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ return context.window_manager.invoke_props_dialog(self, width=350)
+
+ def draw(self, context):
+ layout = self.layout
+ box = layout.box()
+ col = box.column(align=True)
+
+ col.label("Rope settings:")
+ rowsub0 = col.row()
+ rowsub0.prop(self, "ropelenght", text="Length")
+ rowsub0.prop(self, "ropesegments", text="Segments")
+ rowsub0.prop(self, "radiusrope", text="Radius")
+
+ col.label("Quality Settings:")
+ col.prop(self, "resrope", text="Resolution curve")
+ col.prop(self, "qcr", text="Quality Collision")
+ col.prop(self, "substeps", text="Substeps")
+
+
+class BallRope(Operator):
+ bl_idname = "ball.rope"
+ bl_label = "Wrecking Ball"
+ bl_description = ("Create a new Scene with a Rigid Body simulation of\n"
+ "Wrecking Ball on a rope")
+
+ # defaults rope ball
+ ropelenght2 = IntProperty(
+ name="Rope Length",
+ description="Length of the Wrecking Ball rope",
+ default=10
+ )
+ ropesegments2 = IntProperty(
+ name="Rope Segments",
+ description="Number of the Wrecking Ball rope segments",
+ min=0, max=999,
+ default=6
+ )
+ radiuscubes = FloatProperty(
+ name="Cube Radius",
+ description="Size of the Linked Cubes helpers",
+ default=0.5
+ )
+ radiusrope = FloatProperty(
+ name="Rope Radius",
+ description="Radius of the Rope",
+ default=0.4
+ )
+ worldsteps = IntProperty(
+ name="World Steps",
+ description="Rigid Body Solver world steps per second (update)",
+ min=60, max=1000,
+ default=250
+ )
+ solveriterations = IntProperty(
+ name="Solver Iterations",
+ description="How many times the Rigid Body Solver should run",
+ min=10, max=100,
+ default=50
+ )
+ massball = IntProperty(
+ name="Ball Mass",
+ description="Mass of the Wrecking Ball",
+ default=1
+ )
+ resrope = IntProperty(
+ name="Resolution",
+ description="Rope resolution",
+ default=4
+ )
+ grados = FloatProperty(
+ name="Degrees",
+ description="Angle of the Wrecking Ball compared to the Ground Plane",
+ default=45
+ )
+ separacion = FloatProperty(
+ name="Link Cubes Gap",
+ description="Space between the Rope's Linked Cubes",
+ default=0.1
+ )
+ hidecubes = BoolProperty(
+ name="Hide Link Cubes",
+ description="Hide helper geometry for the Rope",
+ default=False
+ )
+
+ def execute(self, context):
+ world_steps = self.worldsteps
+ solver_iterations = self.solveriterations
+ longitud = self.ropelenght2
+
+ # make a + 2, so the segments will be between the two end points...
+ segmentos = self.ropesegments2 + 2
+ offset_del_suelo = 1
+ offset_del_suelo_real = (longitud / 2) + (segmentos / 2)
+ radio = self.radiuscubes
+ radiorope = self.radiusrope
+ masa = self.massball
+ resolucion = self.resrope
+ rotrope = self.grados
+ separation = self.separacion
+ hidecubeslinks = self.hidecubes
+
+ # add new scene
+ bpy.ops.scene.new(type="NEW")
+ scene = bpy.context.scene
+ scene.name = "Test Ball"
+
+ # collect the possible constraint empties that already exist in the data
+ constraint_prev = [obj.name for obj in bpy.data.objects if
+ obj.type == "EMPTY" and "Constraint" in obj.name]
+ # floor:
+ bpy.ops.mesh.primitive_cube_add(
+ radius=1, view_align=False, enter_editmode=False, location=(0, 0, 0),
+ layers=(True, False, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False,
+ False, False, False)
+ )
+ bpy.context.object.scale.x = 10 + longitud
+ bpy.context.object.scale.y = 10 + longitud
+ bpy.context.object.scale.z = 0.05
+ bpy.context.object.name = "groundplane"
+ # The secret agents .001, 002 etc.
+ groundplane_name = bpy.context.object.name
+
+ bpy.ops.rigidbody.objects_add(type='PASSIVE')
+
+ # create the first cube:
+ cuboslink = []
+ n = 0
+ for i in range(segmentos):
+ # if 0 start from 1
+ if i == 0:
+ i = offset_del_suelo
+ else: # if it is not 0, add one so it doesn't step on the first one starting from 1
+ i = i + offset_del_suelo
+ separacion = longitud * 2 / segmentos # distance between linked cubes
+ bpy.ops.mesh.primitive_cube_add(
+ radius=1, view_align=False, enter_editmode=False,
+ location=(0, 0, i * separacion),
+ layers=(True, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False,
+ False, False, False, False)
+ )
+ bpy.ops.rigidbody.objects_add(type='ACTIVE')
+ bpy.context.object.name = "CubeLink"
+ if n != 0:
+ bpy.context.object.draw_type = 'WIRE'
+ bpy.context.object.hide_render = True
+ n += 1
+ bpy.context.object.scale.z = (longitud * 2) / (segmentos * 2) - separation
+ bpy.context.object.scale.x = radio
+ bpy.context.object.scale.y = radio
+ cuboslink.append(bpy.context.object)
+
+ for i in range(len(cuboslink)):
+ deseleccionar_todo()
+ if i != len(cuboslink) - 1:
+ nombre1 = cuboslink[i]
+ nombre2 = cuboslink[i + 1]
+ seleccionar_por_nombre(nombre1.name)
+ seleccionar_por_nombre(nombre2.name)
+ bpy.ops.rigidbody.connect()
+
+ # select by name
+ constraint_new = [
+ obj.name for obj in bpy.data.objects if
+ obj.type == "EMPTY" and "Constraint" in obj.name and
+ obj.name not in constraint_prev
+ ]
+
+ for names in constraint_new:
+ seleccionar_por_nombre(names)
+
+ for c in bpy.context.selected_objects:
+ c.rigid_body_constraint.type = 'POINT'
+ deseleccionar_todo()
+
+ # create a Bezier curve:
+ bpy.ops.curve.primitive_bezier_curve_add(
+ radius=1, view_align=False, enter_editmode=False, location=(0, 0, 0),
+ layers=(True, False, False, False, False, False, False, False, False,
+ False, False, False, False, False, False, False, False, False, False, False)
+ )
+ bpy.context.object.name = "Cuerda"
+ # Blender will automatically append the .001
+ # if it is already in data
+ real_name = bpy.context.object.name
+
+ for i in range(len(cuboslink)):
+ cubonombre = cuboslink[i].name
+ seleccionar_por_nombre(cubonombre)
+ seleccionar_por_nombre(real_name)
+ x = cuboslink[i].location[0]
+ y = cuboslink[i].location[1]
+ z = cuboslink[i].location[2]
+
+ # if it is 0 make it start from 1 as the offset from the ground...
+ if i == 0:
+ i = offset_del_suelo
+ else: # if it is not 0, add one so it doesn't step on the first one starting from 1
+ i = i + offset_del_suelo
+
+ salir_de_editmode()
+ entrar_en_editmode()
+
+ if i == 1:
+ # select all the vertices and delete them
+ select_all_vertex_in_curve_bezier(bpy.data.objects[real_name])
+ bpy.ops.curve.delete(type='VERT')
+ # create the first vertex:
+ bpy.ops.curve.vertex_add(location=(x, y, z))
+ else:
+ # extrude the rest:
+ bpy.ops.curve.extrude_move(
+ CURVE_OT_extrude={"mode": 'TRANSLATION'},
+ TRANSFORM_OT_translate={
+ "value": (0, 0, z / i),
+ "constraint_axis": (False, False, True),
+ "constraint_orientation": 'GLOBAL', "mirror": False,
+ "proportional": 'DISABLED', "proportional_edit_falloff": 'SMOOTH',
+ "proportional_size": 1, "snap": False, "snap_target": 'CLOSEST',
+ "snap_point": (0, 0, 0), "snap_align": False, "snap_normal": (0, 0, 0),
+ "gpencil_strokes": False, "texture_space": False,
+ "remove_on_cancel": False, "release_confirm": False
+ }
+ )
+ bpy.ops.object.hook_add_selob(use_bone=False)
+ salir_de_editmode()
+ bpy.context.object.data.bevel_resolution = resolucion
+ deseleccionar_todo()
+
+ # create a sphere ball:
+ deseleccionar_todo()
+ seleccionar_por_nombre(cuboslink[0].name)
+ entrar_en_editmode()
+ z = cuboslink[0].scale.z + longitud / 2
+ bpy.ops.view3d.snap_cursor_to_selected()
+ bpy.ops.mesh.primitive_uv_sphere_add(
+ view_align=False, enter_editmode=False,
+ layers=(True, False, False, False, False, False, False,
+ False, False, False, False, False, False, False,
+ False, False, False, False, False, False)
+ )
+ bpy.ops.transform.translate(
+ value=(0, 0, -z + 2), constraint_axis=(False, False, True),
+ constraint_orientation='GLOBAL', mirror=False, proportional='DISABLED',
+ proportional_edit_falloff='SMOOTH', proportional_size=1
+ )
+ bpy.ops.transform.resize(
+ value=(longitud / 2, longitud / 2, longitud / 2),
+ constraint_axis=(False, False, False),
+ constraint_orientation='GLOBAL',
+ mirror=False, proportional='DISABLED',
+ proportional_edit_falloff='SMOOTH', proportional_size=1
+ )
+ deselect_all_in_edit_mode(cuboslink[0])
+ salir_de_editmode()
+ bpy.ops.object.shade_smooth()
+ bpy.context.object.rigid_body.mass = masa
+ bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_MASS')
+
+ # move it all up a bit more:
+ seleccionar_todo()
+ deseleccionar_por_nombre(groundplane_name)
+ bpy.ops.transform.translate(
+ value=(0, 0, offset_del_suelo_real),
+ constraint_axis=(False, False, True),
+ constraint_orientation='GLOBAL', mirror=False,
+ proportional='DISABLED', proportional_edit_falloff='SMOOTH',
+ proportional_size=1
+ )
+
+ deseleccionar_todo()
+ seleccionar_por_nombre(cuboslink[-1].name)
+ bpy.ops.rigidbody.objects_add(type='PASSIVE')
+
+ bpy.context.scene.rigidbody_world.steps_per_second = world_steps
+ bpy.context.scene.rigidbody_world.solver_iterations = solver_iterations
+
+ # move everything from the top one:
+ seleccionar_por_nombre(cuboslink[-1].name)
+ bpy.ops.view3d.snap_cursor_to_selected()
+ seleccionar_todo()
+ deseleccionar_por_nombre(groundplane_name)
+ deseleccionar_por_nombre(cuboslink[-1].name)
+ bpy.context.space_data.pivot_point = 'CURSOR'
+ bpy.ops.transform.rotate(
+ value=rotrope, axis=(1, 0, 0),
+ constraint_axis=(True, False, False),
+ constraint_orientation='GLOBAL',
+ mirror=False, proportional='DISABLED',
+ proportional_edit_falloff='SMOOTH',
+ proportional_size=1
+ )
+ bpy.context.space_data.pivot_point = 'MEDIAN_POINT'
+ deseleccionar_todo()
+
+ seleccionar_por_nombre(real_name)
+ bpy.context.object.data.fill_mode = 'FULL'
+ bpy.context.object.data.bevel_depth = radiorope
+ for ob in bpy.data.objects:
+ if ob.name != cuboslink[0].name:
+ if ob.name.find("CubeLink") >= 0:
+ deseleccionar_todo()
+ seleccionar_por_nombre(ob.name)
+ if hidecubeslinks:
+ bpy.context.object.hide = True
+ ocultar_relationships()
+ deseleccionar_todo()
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ return context.window_manager.invoke_props_dialog(self, width=350)
+
+ def draw(self, context):
+ layout = self.layout
+ box = layout.box()
+ col = box.column(align=True)
+
+ col.label("Rope settings:")
+ rowsub0 = col.row()
+ rowsub0.prop(self, "hidecubes", text="Hide Link Cubes")
+
+ rowsub1 = col.row(align=True)
+ rowsub1.prop(self, "ropelenght2", text="Length")
+ rowsub1.prop(self, "ropesegments2", text="Segments")
+
+ rowsub2 = col.row(align=True)
+ rowsub2.prop(self, "radiuscubes", text="Radius Link Cubes")
+ rowsub2.prop(self, "radiusrope", text="Radius Rope")
+
+ rowsub3 = col.row(align=True)
+ rowsub3.prop(self, "grados", text="Degrees")
+ rowsub3.prop(self, "separacion", text="Separation Link Cubes")
+
+ col.label("Quality Settings:")
+ col.prop(self, "resrope", text="Resolution Rope")
+ col.prop(self, "massball", text="Ball Mass")
+ col.prop(self, "worldsteps", text="World Steps")
+ col.prop(self, "solveriterations", text="Solver Iterarions")
+
+
+# Register
+
+def register():
+ bpy.utils.register_module(__name__)
+
+
+def unregister():
+ bpy.utils.unregister_module(__name__)
+
+
+if __name__ == "__main__":
+ register()