merge with trunk r38787
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
#
|
||||
# ##### END GPL LICENSE BLOCK #####
|
||||
|
||||
# <pep8 compliant>
|
||||
# <pep8-80 compliant>
|
||||
|
||||
import bpy
|
||||
from bpy.props import StringProperty, BoolProperty, EnumProperty, IntProperty
|
||||
@@ -29,9 +29,22 @@ class SelectPattern(bpy.types.Operator):
|
||||
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):
|
||||
|
||||
@@ -40,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'}
|
||||
|
||||
@@ -94,19 +122,25 @@ class SelectCamera(bpy.types.Operator):
|
||||
|
||||
|
||||
class SelectHierarchy(bpy.types.Operator):
|
||||
'''Select object relative to the active objects position in the hierarchy'''
|
||||
'''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):
|
||||
@@ -164,7 +198,11 @@ class SubdivisionSet(bpy.types.Operator):
|
||||
level = IntProperty(name=_("Level"),
|
||||
default=1, min=-100, max=100, soft_min=-6, soft_max=6)
|
||||
|
||||
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):
|
||||
@@ -216,7 +254,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)
|
||||
@@ -225,23 +264,36 @@ class SubdivisionSet(bpy.types.Operator):
|
||||
|
||||
|
||||
class ShapeTransfer(bpy.types.Operator):
|
||||
'''Copy another selected objects active shape to this one by applying the relative offsets'''
|
||||
'''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):
|
||||
|
||||
@@ -273,13 +325,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)
|
||||
@@ -291,53 +346,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':
|
||||
@@ -375,7 +467,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
|
||||
@@ -396,7 +489,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]
|
||||
|
||||
@@ -430,11 +526,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[:]
|
||||
@@ -451,11 +550,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)
|
||||
@@ -483,14 +589,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:
|
||||
@@ -499,7 +609,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")
|
||||
@@ -536,7 +649,8 @@ class MakeDupliFace(bpy.types.Operator):
|
||||
|
||||
|
||||
class IsolateTypeRender(bpy.types.Operator):
|
||||
'''Hide unselected render objects of same type as active by setting the hide render flag'''
|
||||
'''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'}
|
||||
|
||||
Reference in New Issue
Block a user