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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release/scripts/startup/bl_operators/object.py')
-rw-r--r--release/scripts/startup/bl_operators/object.py305
1 files changed, 236 insertions, 69 deletions
diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py
index 0342a14a1b2..6c9f27afaa5 100644
--- a/release/scripts/startup/bl_operators/object.py
+++ b/release/scripts/startup/bl_operators/object.py
@@ -16,21 +16,35 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
+from bpy.types import Operator
from bpy.props import StringProperty, BoolProperty, EnumProperty, IntProperty
-class SelectPattern(bpy.types.Operator):
+class SelectPattern(Operator):
'''Select object matching a naming pattern'''
bl_idname = "object.select_pattern"
bl_label = "Select Pattern"
bl_options = {'REGISTER', 'UNDO'}
- pattern = StringProperty(name="Pattern", description="Name filter using '*' and '?' wildcard chars", maxlen=32, default="*")
- case_sensitive = BoolProperty(name="Case Sensitive", description="Do a case sensitive compare", default=False)
- extend = BoolProperty(name="Extend", description="Extend the existing selection", default=True)
+ pattern = StringProperty(
+ name="Pattern",
+ description="Name filter using '*' and '?' wildcard chars",
+ maxlen=32,
+ default="*",
+ )
+ case_sensitive = BoolProperty(
+ name="Case Sensitive",
+ description="Do a case sensitive compare",
+ default=False,
+ )
+ extend = BoolProperty(
+ name="Extend",
+ description="Extend the existing selection",
+ default=True,
+ )
def execute(self, context):
@@ -39,22 +53,37 @@ class SelectPattern(bpy.types.Operator):
if self.case_sensitive:
pattern_match = fnmatch.fnmatchcase
else:
- pattern_match = lambda a, b: fnmatch.fnmatchcase(a.upper(), b.upper())
-
+ pattern_match = (lambda a, b:
+ fnmatch.fnmatchcase(a.upper(), b.upper()))
+ is_ebone = False
obj = context.object
if obj and obj.mode == 'POSE':
items = obj.data.bones
+ if not self.extend:
+ bpy.ops.pose.select_all(action='DESELECT')
elif obj and obj.type == 'ARMATURE' and obj.mode == 'EDIT':
items = obj.data.edit_bones
+ if not self.extend:
+ bpy.ops.armature.select_all(action='DESELECT')
+ is_ebone = True
else:
items = context.visible_objects
+ if not self.extend:
+ bpy.ops.object.select_all(action='DESELECT')
# Can be pose bones or objects
for item in items:
if pattern_match(item.name, self.pattern):
item.select = True
- elif not self.extend:
- item.select = False
+
+ # hrmf, perhaps there should be a utility function for this.
+ if is_ebone:
+ item.select_head = True
+ item.select_tail = True
+ if item.use_connect:
+ item_parent = item.parent
+ if item_parent is not None:
+ item_parent.select_tail = True
return {'FINISHED'}
@@ -71,7 +100,7 @@ class SelectPattern(bpy.types.Operator):
row.prop(self, "extend")
-class SelectCamera(bpy.types.Operator):
+class SelectCamera(Operator):
'''Select object matching a naming pattern'''
bl_idname = "object.select_camera"
bl_label = "Select Camera"
@@ -92,20 +121,26 @@ class SelectCamera(bpy.types.Operator):
return {'FINISHED'}
-class SelectHierarchy(bpy.types.Operator):
- '''Select object relative to the active objects position in the hierarchy'''
+class SelectHierarchy(Operator):
+ '''Select object relative to the active objects position''' \
+ '''in the hierarchy'''
bl_idname = "object.select_hierarchy"
bl_label = "Select Hierarchy"
bl_options = {'REGISTER', 'UNDO'}
- direction = EnumProperty(items=(
- ('PARENT', "Parent", ""),
- ('CHILD', "Child", "")),
- name="Direction",
- description="Direction to select in the hierarchy",
- default='PARENT')
+ direction = EnumProperty(
+ items=(('PARENT', "Parent", ""),
+ ('CHILD', "Child", ""),
+ ),
+ name="Direction",
+ description="Direction to select in the hierarchy",
+ default='PARENT')
- extend = BoolProperty(name="Extend", description="Extend the existing selection", default=False)
+ extend = BoolProperty(
+ name="Extend",
+ description="Extend the existing selection",
+ default=False,
+ )
@classmethod
def poll(cls, context):
@@ -153,17 +188,26 @@ class SelectHierarchy(bpy.types.Operator):
return {'CANCELLED'}
-class SubdivisionSet(bpy.types.Operator):
+class SubdivisionSet(Operator):
'''Sets a Subdivision Surface Level (1-5)'''
bl_idname = "object.subdivision_set"
bl_label = "Subdivision Set"
bl_options = {'REGISTER', 'UNDO'}
- level = IntProperty(name="Level",
- default=1, min=-100, max=100, soft_min=-6, soft_max=6)
+ level = IntProperty(
+ name="Level",
+ min=-100, max=100,
+ soft_min=-6, soft_max=6,
+ default=1,
+ )
- relative = BoolProperty(name="Relative", description="Apply the subsurf level as an offset relative to the current level", default=False)
+ relative = BoolProperty(
+ name="Relative",
+ description=("Apply the subsurf level as an offset "
+ "relative to the current level"),
+ default=False,
+ )
@classmethod
def poll(cls, context):
@@ -215,7 +259,8 @@ class SubdivisionSet(bpy.types.Operator):
mod = obj.modifiers.new("Subsurf", 'SUBSURF')
mod.levels = level
except:
- self.report({'WARNING'}, "Modifiers cannot be added to object: " + obj.name)
+ self.report({'WARNING'},
+ "Modifiers cannot be added to object: " + obj.name)
for obj in context.selected_editable_objects:
set_object_subd(obj)
@@ -223,24 +268,38 @@ class SubdivisionSet(bpy.types.Operator):
return {'FINISHED'}
-class ShapeTransfer(bpy.types.Operator):
- '''Copy another selected objects active shape to this one by applying the relative offsets'''
+class ShapeTransfer(Operator):
+ '''Copy another selected objects active shape to this one by ''' \
+ '''applying the relative offsets'''
bl_idname = "object.shape_key_transfer"
bl_label = "Transfer Shape Key"
bl_options = {'REGISTER', 'UNDO'}
- mode = EnumProperty(items=(
- ('OFFSET', "Offset", "Apply the relative positional offset"),
- ('RELATIVE_FACE', "Relative Face", "Calculate the geometricly relative position (using faces)."),
- ('RELATIVE_EDGE', "Relative Edge", "Calculate the geometricly relative position (using edges).")),
- name="Transformation Mode",
- description="Method to apply relative shape positions to the new shape",
- default='OFFSET')
-
- use_clamp = BoolProperty(name="Clamp Offset",
- description="Clamp the transformation to the distance each vertex moves in the original shape.",
- default=False)
+ mode = EnumProperty(
+ items=(('OFFSET',
+ "Offset",
+ "Apply the relative positional offset",
+ ),
+ ('RELATIVE_FACE',
+ "Relative Face",
+ "Calculate relative position (using faces).",
+ ),
+ ('RELATIVE_EDGE',
+ "Relative Edge",
+ "Calculate relative position (using edges).",
+ ),
+ ),
+ name="Transformation Mode",
+ description="Relative shape positions to the new shape method",
+ default='OFFSET',
+ )
+ use_clamp = BoolProperty(
+ name="Clamp Offset",
+ description=("Clamp the transformation to the distance each "
+ "vertex moves in the original shape."),
+ default=False,
+ )
def _main(self, ob_act, objects, mode='OFFSET', use_clamp=False):
@@ -272,13 +331,16 @@ class ShapeTransfer(bpy.types.Operator):
orig_shape_coords = me_cos(ob_act.active_shape_key.data)
orig_normals = me_nos(me.vertices)
- # orig_coords = me_cos(me.vertices) # the actual mverts location isnt as relyable as the base shape :S
+ # the actual mverts location isnt as relyable as the base shape :S
+ # orig_coords = me_cos(me.vertices)
orig_coords = me_cos(me.shape_keys.key_blocks[0].data)
for ob_other in objects:
me_other = ob_other.data
if len(me_other.vertices) != len(me.vertices):
- self.report({'WARNING'}, "Skipping '%s', vertex count differs" % ob_other.name)
+ self.report({'WARNING'},
+ ("Skipping '%s', "
+ "vertex count differs") % ob_other.name)
continue
target_normals = me_nos(me_other.vertices)
@@ -290,53 +352,90 @@ class ShapeTransfer(bpy.types.Operator):
ob_add_shape(ob_other, orig_key_name)
# editing the final coords, only list that stores wrapped coords
- target_shape_coords = [v.co for v in ob_other.active_shape_key.data]
+ target_shape_coords = [v.co for v in
+ ob_other.active_shape_key.data]
median_coords = [[] for i in range(len(me.vertices))]
# Method 1, edge
if mode == 'OFFSET':
for i, vert_cos in enumerate(median_coords):
- vert_cos.append(target_coords[i] + (orig_shape_coords[i] - orig_coords[i]))
+ vert_cos.append(target_coords[i] +
+ (orig_shape_coords[i] - orig_coords[i]))
elif mode == 'RELATIVE_FACE':
for face in me.faces:
i1, i2, i3, i4 = face.vertices_raw
if i4 != 0:
pt = barycentric_transform(orig_shape_coords[i1],
- orig_coords[i4], orig_coords[i1], orig_coords[i2],
- target_coords[i4], target_coords[i1], target_coords[i2])
+ orig_coords[i4],
+ orig_coords[i1],
+ orig_coords[i2],
+ target_coords[i4],
+ target_coords[i1],
+ target_coords[i2],
+ )
median_coords[i1].append(pt)
pt = barycentric_transform(orig_shape_coords[i2],
- orig_coords[i1], orig_coords[i2], orig_coords[i3],
- target_coords[i1], target_coords[i2], target_coords[i3])
+ orig_coords[i1],
+ orig_coords[i2],
+ orig_coords[i3],
+ target_coords[i1],
+ target_coords[i2],
+ target_coords[i3],
+ )
median_coords[i2].append(pt)
pt = barycentric_transform(orig_shape_coords[i3],
- orig_coords[i2], orig_coords[i3], orig_coords[i4],
- target_coords[i2], target_coords[i3], target_coords[i4])
+ orig_coords[i2],
+ orig_coords[i3],
+ orig_coords[i4],
+ target_coords[i2],
+ target_coords[i3],
+ target_coords[i4],
+ )
median_coords[i3].append(pt)
pt = barycentric_transform(orig_shape_coords[i4],
- orig_coords[i3], orig_coords[i4], orig_coords[i1],
- target_coords[i3], target_coords[i4], target_coords[i1])
+ orig_coords[i3],
+ orig_coords[i4],
+ orig_coords[i1],
+ target_coords[i3],
+ target_coords[i4],
+ target_coords[i1],
+ )
median_coords[i4].append(pt)
else:
pt = barycentric_transform(orig_shape_coords[i1],
- orig_coords[i3], orig_coords[i1], orig_coords[i2],
- target_coords[i3], target_coords[i1], target_coords[i2])
+ orig_coords[i3],
+ orig_coords[i1],
+ orig_coords[i2],
+ target_coords[i3],
+ target_coords[i1],
+ target_coords[i2],
+ )
median_coords[i1].append(pt)
pt = barycentric_transform(orig_shape_coords[i2],
- orig_coords[i1], orig_coords[i2], orig_coords[i3],
- target_coords[i1], target_coords[i2], target_coords[i3])
+ orig_coords[i1],
+ orig_coords[i2],
+ orig_coords[i3],
+ target_coords[i1],
+ target_coords[i2],
+ target_coords[i3],
+ )
median_coords[i2].append(pt)
pt = barycentric_transform(orig_shape_coords[i3],
- orig_coords[i2], orig_coords[i3], orig_coords[i1],
- target_coords[i2], target_coords[i3], target_coords[i1])
+ orig_coords[i2],
+ orig_coords[i3],
+ orig_coords[i1],
+ target_coords[i2],
+ target_coords[i3],
+ target_coords[i1],
+ )
median_coords[i3].append(pt)
elif mode == 'RELATIVE_EDGE':
@@ -374,7 +473,8 @@ class ShapeTransfer(bpy.types.Operator):
if use_clamp:
# clamp to the same movement as the original
# breaks copy between different scaled meshes.
- len_from = (orig_shape_coords[i] - orig_coords[i]).length
+ len_from = (orig_shape_coords[i] -
+ orig_coords[i]).length
ofs = co - target_coords[i]
ofs.length = len_from
co = target_coords[i] + ofs
@@ -395,7 +495,10 @@ class ShapeTransfer(bpy.types.Operator):
if 1: # swap from/to, means we cant copy to many at once.
if len(objects) != 1:
- self.report({'ERROR'}, "Expected one other selected mesh object to copy from")
+ self.report({'ERROR'},
+ ("Expected one other selected "
+ "mesh object to copy from"))
+
return {'CANCELLED'}
ob_act, objects = objects[0], [ob_act]
@@ -409,7 +512,7 @@ class ShapeTransfer(bpy.types.Operator):
return self._main(ob_act, objects, self.mode, self.use_clamp)
-class JoinUVs(bpy.types.Operator):
+class JoinUVs(Operator):
'''Copy UV Layout to objects with matching geometry'''
bl_idname = "object.join_uvs"
bl_label = "Join as UVs"
@@ -429,11 +532,14 @@ class JoinUVs(bpy.types.Operator):
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
if not mesh.uv_textures:
- self.report({'WARNING'}, "Object: %s, Mesh: '%s' has no UVs\n" % (obj.name, mesh.name))
+ self.report({'WARNING'},
+ "Object: %s, Mesh: '%s' has no UVs"
+ % (obj.name, mesh.name))
else:
len_faces = len(mesh.faces)
- uv_array = array.array('f', [0.0] * 8) * len_faces # seems to be the fastest way to create an array
+ # seems to be the fastest way to create an array
+ uv_array = array.array('f', [0.0] * 8) * len_faces
mesh.uv_textures.active.data.foreach_get("uv_raw", uv_array)
objects = context.selected_editable_objects[:]
@@ -450,11 +556,18 @@ class JoinUVs(bpy.types.Operator):
mesh_other.tag = True
if len(mesh_other.faces) != len_faces:
- self.report({'WARNING'}, "Object: %s, Mesh: '%s' has %d faces, expected %d\n" % (obj_other.name, mesh_other.name, len(mesh_other.faces), len_faces))
+ self.report({'WARNING'}, "Object: %s, Mesh: "
+ "'%s' has %d faces, expected %d\n"
+ % (obj_other.name,
+ mesh_other.name,
+ len(mesh_other.faces),
+ len_faces),
+ )
else:
uv_other = mesh_other.uv_textures.active
if not uv_other:
- uv_other = mesh_other.uv_textures.new() # should return the texture it adds
+ # should return the texture it adds
+ uv_other = mesh_other.uv_textures.new()
# finally do the copy
uv_other.data.foreach_set("uv_raw", uv_array)
@@ -467,7 +580,7 @@ class JoinUVs(bpy.types.Operator):
return {'FINISHED'}
-class MakeDupliFace(bpy.types.Operator):
+class MakeDupliFace(Operator):
'''Make linked objects into dupli-faces'''
bl_idname = "object.make_dupli_face"
bl_label = "Make Dupli-Face"
@@ -482,14 +595,18 @@ class MakeDupliFace(bpy.types.Operator):
SCALE_FAC = 0.01
offset = 0.5 * SCALE_FAC
- base_tri = Vector((-offset, -offset, 0.0)), Vector((offset, -offset, 0.0)), Vector((offset, offset, 0.0)), Vector((-offset, offset, 0.0))
+ base_tri = (Vector((-offset, -offset, 0.0)),
+ Vector((+offset, -offset, 0.0)),
+ Vector((+offset, +offset, 0.0)),
+ Vector((-offset, +offset, 0.0)),
+ )
def matrix_to_quat(matrix):
# scale = matrix.median_scale
trans = matrix.to_translation()
rot = matrix.to_3x3() # also contains scale
- return [(b * rot) + trans for b in base_tri]
+ return [(rot * b) + trans for b in base_tri]
scene = bpy.context.scene
linked = {}
for obj in bpy.context.selected_objects:
@@ -498,7 +615,10 @@ class MakeDupliFace(bpy.types.Operator):
linked.setdefault(data, []).append(obj)
for data, objects in linked.items():
- face_verts = [axis for obj in objects for v in matrix_to_quat(obj.matrix_world) for axis in v]
+ face_verts = [axis for obj in objects
+ for v in matrix_to_quat(obj.matrix_world)
+ for axis in v]
+
faces = list(range(len(face_verts) // 3))
mesh = bpy.data.meshes.new(data.name + "_dupli")
@@ -534,8 +654,9 @@ class MakeDupliFace(bpy.types.Operator):
return {'FINISHED'}
-class IsolateTypeRender(bpy.types.Operator):
- '''Hide unselected render objects of same type as active by setting the hide render flag'''
+class IsolateTypeRender(Operator):
+ '''Hide unselected render objects of same type as active ''' \
+ '''by setting the hide render flag'''
bl_idname = "object.isolate_type_render"
bl_label = "Restrict Render Unselected"
bl_options = {'REGISTER', 'UNDO'}
@@ -554,7 +675,7 @@ class IsolateTypeRender(bpy.types.Operator):
return {'FINISHED'}
-class ClearAllRestrictRender(bpy.types.Operator):
+class ClearAllRestrictRender(Operator):
'''Reveal all render objects by setting the hide render flag'''
bl_idname = "object.hide_render_clear_all"
bl_label = "Clear All Restrict Render"
@@ -564,3 +685,49 @@ class ClearAllRestrictRender(bpy.types.Operator):
for obj in context.scene.objects:
obj.hide_render = False
return {'FINISHED'}
+
+
+class TransformsToDeltasAnim(Operator):
+ '''Convert object animation for normal transforms to delta transforms'''
+ bl_idname = "object.anim_transforms_to_deltas"
+ bl_label = "Animated Transforms to Deltas"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ @classmethod
+ def poll(cls, context):
+ obs = context.selected_editable_objects
+ return (obs is not None)
+
+ def execute(self, context):
+ for obj in context.selected_editable_objects:
+ # get animation data
+ adt = obj.animation_data
+ if (adt is None) or (adt.action is None):
+ self.report({'WARNING'},
+ "No animation data to convert on object: %r" %
+ obj.name)
+ continue
+
+ # if F-Curve uses standard transform path
+ # just append "delta_" to this path
+ for fcu in adt.action.fcurves:
+ if fcu.data_path == "location":
+ fcu.data_path = "delta_location"
+ obj.location.zero()
+ elif fcu.data_path == "rotation_euler":
+ fcu.data_path = "delta_rotation_euler"
+ obj.rotation_euler.zero()
+ elif fcu.data_path == "rotation_quaternion":
+ fcu.data_path = "delta_rotation_quaternion"
+ obj.rotation_quaternion.identity()
+ # XXX: currently not implemented
+ # elif fcu.data_path == "rotation_axis_angle":
+ # fcu.data_path = "delta_rotation_axis_angle"
+ elif fcu.data_path == "scale":
+ fcu.data_path = "delta_scale"
+ obj.scale = 1.0, 1.0, 1.0
+
+ # hack: force animsys flush by changing frame, so that deltas get run
+ context.scene.frame_set(context.scene.frame_current)
+
+ return {'FINISHED'}