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:
authorXiao Xiangquan <xiaoxiangquan@gmail.com>2011-07-29 21:42:53 +0400
committerXiao Xiangquan <xiaoxiangquan@gmail.com>2011-07-29 21:42:53 +0400
commit287b24926fefe078e4baae45808a5453b5c731bc (patch)
treee2336456d73c8b4bb5b9dad80cb475d5ea9c38d5 /release/scripts
parente382a373f5c26be3279ce91b119cce1b24bec388 (diff)
parentb948459031dd6d0f1ccc81d607a589fd7d1e8ab2 (diff)
merge with trunk r38787
Diffstat (limited to 'release/scripts')
-rw-r--r--release/scripts/modules/addon_utils.py12
-rw-r--r--release/scripts/modules/bpy/path.py11
-rw-r--r--release/scripts/modules/bpy/utils.py9
-rw-r--r--release/scripts/modules/bpy_extras/image_utils.py6
-rw-r--r--release/scripts/modules/bpy_extras/io_utils.py43
-rw-r--r--release/scripts/modules/bpy_extras/view3d_utils.py10
-rw-r--r--release/scripts/modules/bpy_types.py14
-rw-r--r--release/scripts/startup/bl_operators/add_mesh_torus.py17
-rw-r--r--release/scripts/startup/bl_operators/image.py33
-rw-r--r--release/scripts/startup/bl_operators/mesh.py8
-rw-r--r--release/scripts/startup/bl_operators/object.py230
-rw-r--r--release/scripts/startup/bl_operators/object_align.py214
-rw-r--r--release/scripts/startup/bl_operators/object_quick_effects.py135
-rw-r--r--release/scripts/startup/bl_operators/object_randomize_transform.py87
-rw-r--r--release/scripts/startup/bl_operators/presets.py69
-rw-r--r--release/scripts/startup/bl_operators/screen_play_rendered_anim.py94
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_smart_project.py14
-rw-r--r--release/scripts/startup/bl_operators/wm.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py5
-rw-r--r--release/scripts/startup/bl_ui/properties_world.py49
-rw-r--r--release/scripts/startup/bl_ui/space_image.py6
-rw-r--r--release/scripts/startup/bl_ui/space_info.py6
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py12
-rw-r--r--release/scripts/startup/bl_ui/space_text.py60
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py22
-rw-r--r--release/scripts/startup/bl_ui/space_userpref_keymap.py2
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py31
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py3
-rwxr-xr-xrelease/scripts/templates/batch_export.py33
-rwxr-xr-xrelease/scripts/templates/ui_menu.py49
-rwxr-xr-xrelease/scripts/templates/ui_menu_simple.py26
-rwxr-xr-x[-rw-r--r--]release/scripts/templates/ui_panel_simple.py (renamed from release/scripts/templates/panel_simple.py)7
33 files changed, 948 insertions, 372 deletions
diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py
index 07f1dc618dc..cf74282d064 100644
--- a/release/scripts/modules/addon_utils.py
+++ b/release/scripts/modules/addon_utils.py
@@ -31,6 +31,8 @@ __all__ = (
import bpy as _bpy
+error_duplicates = False
+
def paths():
# RELEASE SCRIPTS: official scripts distributed in Blender releases
paths = _bpy.utils.script_paths("addons")
@@ -47,8 +49,11 @@ def paths():
def modules(module_cache):
+ global error_duplicates
import os
+ error_duplicates = False
+
path_list = paths()
# fake module importing
@@ -117,7 +122,12 @@ def modules(module_cache):
modules_stale -= {mod_name}
mod = module_cache.get(mod_name)
if mod:
- if mod.__time__ != os.path.getmtime(mod_path):
+ if mod.__file__ != mod_path:
+ print("multiple addons with the same name:\n %r\n %r" %
+ (mod.__file__, mod_path))
+ error_duplicates = True
+
+ elif mod.__time__ != os.path.getmtime(mod_path):
print("reloading addon:", mod_name, mod.__time__, os.path.getmtime(mod_path), mod_path)
del module_cache[mod_name]
mod = None
diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py
index 5e95428f641..251fc947e94 100644
--- a/release/scripts/modules/bpy/path.py
+++ b/release/scripts/modules/bpy/path.py
@@ -117,7 +117,7 @@ def display_name_from_filepath(name):
"""
Returns the path stripped of directort and extension, ensured to be utf8 compatible.
"""
- return _os.path.splitext(_os.path.basename(name))[0].encode("utf8", "replace").decode("utf8")
+ return _os.path.splitext(basename(name))[0].encode("utf8", "replace").decode("utf8")
def resolve_ncase(path):
@@ -231,3 +231,12 @@ def module_names(path, recursive=False):
modules.append(("%s.%s" % (filename, mod_name), mod_path))
return modules
+
+
+def basename(path):
+ """
+ Equivalent to os.path.basename, but skips a "//" suffix.
+
+ Use for Windows compatibility.
+ """
+ return _os.path.basename(path[2:] if path[:2] in {"//", b"//"} else path)
diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py
index 7c0d3d24cba..57d3e6dd703 100644
--- a/release/scripts/modules/bpy/utils.py
+++ b/release/scripts/modules/bpy/utils.py
@@ -298,11 +298,18 @@ _presets = _os.path.join(_scripts[0], "presets") # FIXME - multiple paths
def preset_paths(subdir):
"""
Returns a list of paths for a specific preset.
+
+ :arg subdir: preset subdirectory (must not be an absolute path).
+ :type subdir: string
+ :return: script paths.
+ :rtype: list
"""
dirs = []
for path in script_paths("presets", all=True):
directory = _os.path.join(path, subdir)
- if _os.path.isdir(directory):
+ if not directory.startswith(path):
+ raise Exception("invalid subdir given %r" % subdir)
+ elif _os.path.isdir(directory):
dirs.append(directory)
return dirs
diff --git a/release/scripts/modules/bpy_extras/image_utils.py b/release/scripts/modules/bpy_extras/image_utils.py
index f91535a0ad4..e56c1c651c4 100644
--- a/release/scripts/modules/bpy_extras/image_utils.py
+++ b/release/scripts/modules/bpy_extras/image_utils.py
@@ -86,7 +86,9 @@ def load_image(imagepath,
variants = [imagepath]
if dirname:
- variants += [os.path.join(dirname, imagepath), os.path.join(dirname, os.path.basename(imagepath))]
+ variants += [os.path.join(dirname, imagepath),
+ os.path.join(dirname, bpy.path.basename(imagepath)),
+ ]
for filepath_test in variants:
if ncase_cmp:
@@ -99,7 +101,7 @@ def load_image(imagepath,
return _image_load(nfilepath)
if place_holder:
- image = bpy.data.images.new(os.path.basename(imagepath), 128, 128)
+ image = bpy.data.images.new(bpy.path.basename(imagepath), 128, 128)
# allow the path to be resolved later
image.filepath = imagepath
return image
diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py
index cfa2233f7b6..bd01897c639 100644
--- a/release/scripts/modules/bpy_extras/io_utils.py
+++ b/release/scripts/modules/bpy_extras/io_utils.py
@@ -22,6 +22,7 @@ __all__ = (
"ExportHelper",
"ImportHelper",
"axis_conversion",
+ "axis_conversion_ensure",
"create_derived_objects",
"free_derived_objects",
"unpack_list",
@@ -154,17 +155,55 @@ def axis_conversion(from_forward='Y', from_up='Z', to_forward='Y', to_up='Z'):
if from_forward == to_forward and from_up == to_up:
return Matrix().to_3x3()
+ if from_forward[-1] == from_up[-1] or to_forward[-1] == to_up[-1]:
+ raise Exception("invalid axis arguments passed, "
+ "can't use up/forward on the same axis.")
+
value = reduce(int.__or__, (_axis_convert_num[a] << (i * 3) for i, a in enumerate((from_forward, from_up, to_forward, to_up))))
for i, axis_lut in enumerate(_axis_convert_lut):
if value in axis_lut:
return Matrix(_axis_convert_matrix[i])
- assert("internal error")
+ assert(0)
+
+
+def axis_conversion_ensure(operator, forward_attr, up_attr):
+ """
+ Function to ensure an operator has valid axis conversion settings, intended
+ to be used from :class:`Operator.check`.
+
+ :arg operator: the operator to access axis attributes from.
+ :type operator: :class:`Operator`
+ :arg forward_attr:
+ :type forward_attr: string
+ :arg up_attr: the directory the *filepath* will be referenced from (normally the export path).
+ :type up_attr: string
+ :return: True if the value was modified.
+ :rtype: boolean
+ """
+ def validate(axis_forward, axis_up):
+ if axis_forward[-1] == axis_up[-1]:
+ axis_up = axis_up[0:-1] + 'XYZ'[('XYZ'.index(axis_up[-1]) + 1) % 3]
+
+ return axis_forward, axis_up
+
+ change = False
+
+ axis = getattr(operator, forward_attr), getattr(operator, up_attr)
+ axis_new = validate(*axis)
+
+ if axis != axis_new:
+ setattr(operator, forward_attr, axis_new[0])
+ setattr(operator, up_attr, axis_new[1])
+
+ return True
+ else:
+ return False
# return a tuple (free, object list), free is True if memory should be freed later with free_derived_objects()
def create_derived_objects(scene, ob):
- if ob.parent and ob.parent.dupli_type != 'NONE':
+ if ob.parent and ob.parent.dupli_type in {'VERTS', 'FACES'}:
return False, None
if ob.dupli_type != 'NONE':
diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py
index c0c0f9186bd..5796abce72c 100644
--- a/release/scripts/modules/bpy_extras/view3d_utils.py
+++ b/release/scripts/modules/bpy_extras/view3d_utils.py
@@ -50,11 +50,11 @@ def region_2d_to_vector_3d(region, rv3d, coord):
-0.5
))
- w = (out[0] * persinv[0][3]) + \
- (out[1] * persinv[1][3]) + \
- (out[2] * persinv[2][3]) + persinv[3][3]
+ w = ((out[0] * persinv[0][3]) +
+ (out[1] * persinv[1][3]) +
+ (out[2] * persinv[2][3]) + persinv[3][3])
- return ((out * persinv) / w) - rv3d.view_matrix.inverted()[3].xyz
+ return ((persinv * out) / w) - rv3d.view_matrix.inverted()[3].xyz
else:
return rv3d.view_matrix.inverted()[2].xyz.normalized()
@@ -116,7 +116,7 @@ def location_3d_to_region_2d(region, rv3d, coord):
"""
from mathutils import Vector
- prj = Vector((coord[0], coord[1], coord[2], 1.0)) * rv3d.perspective_matrix
+ prj = rv3d.perspective_matrix * Vector((coord[0], coord[1], coord[2], 1.0))
if prj.w > 0.0:
width_half = region.width / 2.0
height_half = region.height / 2.0
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index f2cd46b20ae..8766c873dd8 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -144,21 +144,21 @@ class _GenericBone:
""" Vector pointing down the x-axis of the bone.
"""
from mathutils import Vector
- return Vector((1.0, 0.0, 0.0)) * self.matrix.to_3x3()
+ return self.matrix.to_3x3() * Vector((1.0, 0.0, 0.0))
@property
def y_axis(self):
""" Vector pointing down the x-axis of the bone.
"""
from mathutils import Vector
- return Vector((0.0, 1.0, 0.0)) * self.matrix.to_3x3()
+ return self.matrix.to_3x3() * Vector((0.0, 1.0, 0.0))
@property
def z_axis(self):
""" Vector pointing down the x-axis of the bone.
"""
from mathutils import Vector
- return Vector((0.0, 0.0, 1.0)) * self.matrix.to_3x3()
+ return self.matrix.to_3x3() * Vector((0.0, 0.0, 1.0))
@property
def basename(self):
@@ -294,9 +294,9 @@ class EditBone(StructRNA, _GenericBone, metaclass=StructMetaPropGroup):
:type roll: bool
"""
from mathutils import Vector
- z_vec = Vector((0.0, 0.0, 1.0)) * self.matrix.to_3x3()
- self.tail = self.tail * matrix
- self.head = self.head * matrix
+ z_vec = self.matrix.to_3x3() * Vector((0.0, 0.0, 1.0))
+ self.tail = matrix * self.tail
+ self.head = matrix * self.head
if scale:
scalar = matrix.median_scale
@@ -304,7 +304,7 @@ class EditBone(StructRNA, _GenericBone, metaclass=StructMetaPropGroup):
self.tail_radius *= scalar
if roll:
- self.align_roll(z_vec * matrix)
+ self.align_roll(matrix * z_vec)
def ord_ind(i1, i2):
diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py
index 6ab803cc469..27a6d21d519 100644
--- a/release/scripts/startup/bl_operators/add_mesh_torus.py
+++ b/release/scripts/startup/bl_operators/add_mesh_torus.py
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
import mathutils
@@ -40,8 +40,10 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
for minor_index in range(minor_seg):
angle = 2 * pi * minor_index / minor_seg
- vec = Vector((major_rad + (cos(angle) * minor_rad), 0.0,
- (sin(angle) * minor_rad))) * quat
+ vec = quat * Vector((major_rad + (cos(angle) * minor_rad),
+ 0.0,
+ (sin(angle) * minor_rad),
+ ))
verts.extend(vec[:])
@@ -72,7 +74,11 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
return verts, faces
-from bpy.props import FloatProperty, IntProperty, BoolProperty, FloatVectorProperty
+from bpy.props import (FloatProperty,
+ IntProperty,
+ BoolProperty,
+ FloatVectorProperty,
+ )
class AddTorus(bpy.types.Operator):
@@ -82,7 +88,8 @@ class AddTorus(bpy.types.Operator):
bl_options = {'REGISTER', 'UNDO'}
major_radius = FloatProperty(name="Major Radius",
- description="Radius from the origin to the center of the cross sections",
+ description=("Radius from the origin to the "
+ "center of the cross sections"),
default=1.0, min=0.01, max=100.0)
minor_radius = FloatProperty(name="Minor Radius",
description="Radius of the torus' cross section",
diff --git a/release/scripts/startup/bl_operators/image.py b/release/scripts/startup/bl_operators/image.py
index 34c5b0d922a..a0267b8b947 100644
--- a/release/scripts/startup/bl_operators/image.py
+++ b/release/scripts/startup/bl_operators/image.py
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
from bpy.props import StringProperty
@@ -28,7 +28,11 @@ class EditExternally(bpy.types.Operator):
bl_label = "Image Edit Externally"
bl_options = {'REGISTER'}
- filepath = StringProperty(name="File Path", description="Path to an image file", maxlen=1024, default="")
+ filepath = StringProperty(
+ name="File Path",
+ description="Path to an image file",
+ maxlen=1024,
+ )
def _editor_guess(self, context):
import sys
@@ -57,10 +61,13 @@ class EditExternally(bpy.types.Operator):
def execute(self, context):
import os
import subprocess
- filepath = bpy.path.abspath(self.filepath)
+ filepath = os.path.normpath(bpy.path.abspath(self.filepath))
if not os.path.exists(filepath):
- self.report({'ERROR'}, "Image path %r not found, image may be packed or unsaved." % filepath)
+ self.report({'ERROR'},
+ "Image path %r not found, image may be packed or "
+ "unsaved." % filepath)
+
return {'CANCELLED'}
cmd = self._editor_guess(context) + [filepath]
@@ -70,7 +77,10 @@ class EditExternally(bpy.types.Operator):
except:
import traceback
traceback.print_exc()
- self.report({'ERROR'}, "Image editor not found, please specify in User Preferences > File")
+ self.report({'ERROR'},
+ "Image editor not found, "
+ "please specify in User Preferences > File")
+
return {'CANCELLED'}
return {'FINISHED'}
@@ -104,7 +114,9 @@ class SaveDirty(bpy.types.Operator):
if "\\" not in filepath and "/" not in filepath:
self.report({'WARNING'}, "Invalid path: " + filepath)
elif filepath in unique_paths:
- self.report({'WARNING'}, "Path used by more then one image: " + filepath)
+ self.report({'WARNING'},
+ "Path used by more then one image: %r" %
+ filepath)
else:
unique_paths.add(filepath)
image.save()
@@ -144,12 +156,11 @@ class ProjectEdit(bpy.types.Operator):
filepath = os.path.splitext(filepath)[0]
# filepath = bpy.path.clean_name(filepath) # fixes <memory> rubbish, needs checking
- if filepath.startswith(".") or filepath == "":
- # TODO, have a way to check if the file is saved, assume startup.blend
+ if bpy.data.is_saved:
+ filepath = "//" + filepath
+ else:
tmpdir = context.user_preferences.filepaths.temporary_directory
filepath = os.path.join(tmpdir, "project_edit")
- else:
- filepath = "//" + filepath
obj = context.object
@@ -163,7 +174,7 @@ class ProjectEdit(bpy.types.Operator):
filepath_final = filepath + ("%.3d.%s" % (i, EXT))
i += 1
- image_new.name = os.path.basename(filepath_final)
+ image_new.name = bpy.path.basename(filepath_final)
ProjectEdit._proj_hack[0] = image_new.name
image_new.filepath_raw = filepath_final # TODO, filepath raw is crummy
diff --git a/release/scripts/startup/bl_operators/mesh.py b/release/scripts/startup/bl_operators/mesh.py
index 03b0e469310..344b238709f 100644
--- a/release/scripts/startup/bl_operators/mesh.py
+++ b/release/scripts/startup/bl_operators/mesh.py
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
@@ -111,7 +111,8 @@ class MeshMirrorUV(bpy.types.Operator):
#for i, v in enumerate(mesh.vertices):
vmap = {}
- for mirror_a, mirror_b in (mirror_gt, mirror_lt), (mirror_lt, mirror_gt):
+ for mirror_a, mirror_b in ((mirror_gt, mirror_lt),
+ (mirror_lt, mirror_gt)):
for co, i in mirror_a.items():
nco = (-co[0], co[1], co[2])
j = mirror_b.get(nco)
@@ -120,7 +121,8 @@ class MeshMirrorUV(bpy.types.Operator):
active_uv_layer = mesh.uv_textures.active.data
fuvs = [(uv.uv1, uv.uv2, uv.uv3, uv.uv4) for uv in active_uv_layer]
- fuvs_cpy = [(uv[0].copy(), uv[1].copy(), uv[2].copy(), uv[3].copy()) for uv in fuvs]
+ fuvs_cpy = [(uv[0].copy(), uv[1].copy(), uv[2].copy(), uv[3].copy())
+ for uv in fuvs]
# as a list
faces = mesh.faces[:]
diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py
index 72e521be5cf..c0bd20b8910 100644
--- a/release/scripts/startup/bl_operators/object.py
+++ b/release/scripts/startup/bl_operators/object.py
@@ -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'}
diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py
index d662d292868..04a4d7d8f42 100644
--- a/release/scripts/startup/bl_operators/object_align.py
+++ b/release/scripts/startup/bl_operators/object_align.py
@@ -16,105 +16,211 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
from mathutils import Vector
from blf import gettext as _
+def GlobalBB_LQ(bb_world):
-def align_objects(align_x, align_y, align_z, align_mode, relative_to):
+ # Initialize the variables with the 8th vertex
+ left, right, front, back, down, up = (bb_world[7][0],
+ bb_world[7][0],
+ bb_world[7][1],
+ bb_world[7][1],
+ bb_world[7][2],
+ bb_world[7][2],
+ )
+
+ # Test against the other 7 verts
+ for i in range (7):
+
+ # X Range
+ val = bb_world[i][0]
+ if val < left:
+ left = val
+
+ if val > right:
+ right = val
+
+ # Y Range
+ val = bb_world[i][1]
+ if val < front:
+ front = val
+
+ if val > back:
+ back = val
+
+ # Z Range
+ val = bb_world[i][2]
+ if val < down:
+ down = val
+
+ if val > up:
+ up = val
+
+ return (Vector((left, front, up)), Vector((right, back, down)))
+
+def GlobalBB_HQ(obj):
+
+ matrix_world = obj.matrix_world.copy()
+
+ # Initialize the variables with the last vertex
+
+ verts = obj.data.vertices
+
+ val = matrix_world * verts[-1].co
+
+ left, right, front, back, down, up = (val[0],
+ val[0],
+ val[1],
+ val[1],
+ val[2],
+ val[2],
+ )
+
+ # Test against all other verts
+ for i in range (len(verts)-1):
+
+ vco = matrix_world * verts[i].co
+
+ # X Range
+ val = vco[0]
+ if val < left:
+ left = val
+
+ if val > right:
+ right = val
+
+ # Y Range
+ val = vco[1]
+ if val < front:
+ front = val
+
+ if val > back:
+ back = val
+
+ # Z Range
+ val = vco[2]
+ if val < down:
+ down = val
+
+ if val > up:
+ up = val
+
+ return Vector((left, front, up)), Vector((right, back, down))
+
+
+def align_objects(align_x,
+ align_y,
+ align_z,
+ align_mode,
+ relative_to,
+ bb_quality):
cursor = bpy.context.scene.cursor_location
- Left_Up_Front_SEL = [0.0, 0.0, 0.0]
- Right_Down_Back_SEL = [0.0, 0.0, 0.0]
+ Left_Front_Up_SEL = [0.0, 0.0, 0.0]
+ Right_Back_Down_SEL = [0.0, 0.0, 0.0]
flag_first = True
objs = []
for obj in bpy.context.selected_objects:
- matrix_world = obj.matrix_world
- bb_world = [Vector(v[:]) * matrix_world for v in obj.bound_box]
+ matrix_world = obj.matrix_world.copy()
+ bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box]
objs.append((obj, bb_world))
if not objs:
return False
for obj, bb_world in objs:
- Left_Up_Front = bb_world[1]
- Right_Down_Back = bb_world[7]
+
+ if bb_quality:
+ GBB = GlobalBB_HQ(obj)
+ else:
+ GBB = GlobalBB_LQ(bb_world)
+
+ Left_Front_Up = GBB[0]
+ Right_Back_Down = GBB[1]
# Active Center
if obj == bpy.context.active_object:
- center_active_x = (Left_Up_Front[0] + Right_Down_Back[0]) / 2.0
- center_active_y = (Left_Up_Front[1] + Right_Down_Back[1]) / 2.0
- center_active_z = (Left_Up_Front[2] + Right_Down_Back[2]) / 2.0
+ center_active_x = (Left_Front_Up[0] + Right_Back_Down[0]) / 2.0
+ center_active_y = (Left_Front_Up[1] + Right_Back_Down[1]) / 2.0
+ center_active_z = (Left_Front_Up[2] + Right_Back_Down[2]) / 2.0
- size_active_x = (Right_Down_Back[0] - Left_Up_Front[0]) / 2.0
- size_active_y = (Right_Down_Back[1] - Left_Up_Front[1]) / 2.0
- size_active_z = (Left_Up_Front[2] - Right_Down_Back[2]) / 2.0
+ size_active_x = (Right_Back_Down[0] - Left_Front_Up[0]) / 2.0
+ size_active_y = (Right_Back_Down[1] - Left_Front_Up[1]) / 2.0
+ size_active_z = (Left_Front_Up[2] - Right_Back_Down[2]) / 2.0
# Selection Center
if flag_first:
flag_first = False
- Left_Up_Front_SEL[0] = Left_Up_Front[0]
- Left_Up_Front_SEL[1] = Left_Up_Front[1]
- Left_Up_Front_SEL[2] = Left_Up_Front[2]
+ Left_Front_Up_SEL[0] = Left_Front_Up[0]
+ Left_Front_Up_SEL[1] = Left_Front_Up[1]
+ Left_Front_Up_SEL[2] = Left_Front_Up[2]
- Right_Down_Back_SEL[0] = Right_Down_Back[0]
- Right_Down_Back_SEL[1] = Right_Down_Back[1]
- Right_Down_Back_SEL[2] = Right_Down_Back[2]
+ Right_Back_Down_SEL[0] = Right_Back_Down[0]
+ Right_Back_Down_SEL[1] = Right_Back_Down[1]
+ Right_Back_Down_SEL[2] = Right_Back_Down[2]
else:
# X axis
- if Left_Up_Front[0] < Left_Up_Front_SEL[0]:
- Left_Up_Front_SEL[0] = Left_Up_Front[0]
+ if Left_Front_Up[0] < Left_Front_Up_SEL[0]:
+ Left_Front_Up_SEL[0] = Left_Front_Up[0]
# Y axis
- if Left_Up_Front[1] < Left_Up_Front_SEL[1]:
- Left_Up_Front_SEL[1] = Left_Up_Front[1]
+ if Left_Front_Up[1] < Left_Front_Up_SEL[1]:
+ Left_Front_Up_SEL[1] = Left_Front_Up[1]
# Z axis
- if Left_Up_Front[2] > Left_Up_Front_SEL[2]:
- Left_Up_Front_SEL[2] = Left_Up_Front[2]
+ if Left_Front_Up[2] > Left_Front_Up_SEL[2]:
+ Left_Front_Up_SEL[2] = Left_Front_Up[2]
# X axis
- if Right_Down_Back[0] > Right_Down_Back_SEL[0]:
- Right_Down_Back_SEL[0] = Right_Down_Back[0]
+ if Right_Back_Down[0] > Right_Back_Down_SEL[0]:
+ Right_Back_Down_SEL[0] = Right_Back_Down[0]
# Y axis
- if Right_Down_Back[1] > Right_Down_Back_SEL[1]:
- Right_Down_Back_SEL[1] = Right_Down_Back[1]
+ if Right_Back_Down[1] > Right_Back_Down_SEL[1]:
+ Right_Back_Down_SEL[1] = Right_Back_Down[1]
# Z axis
- if Right_Down_Back[2] < Right_Down_Back_SEL[2]:
- Right_Down_Back_SEL[2] = Right_Down_Back[2]
+ if Right_Back_Down[2] < Right_Back_Down_SEL[2]:
+ Right_Back_Down_SEL[2] = Right_Back_Down[2]
- center_sel_x = (Left_Up_Front_SEL[0] + Right_Down_Back_SEL[0]) / 2.0
- center_sel_y = (Left_Up_Front_SEL[1] + Right_Down_Back_SEL[1]) / 2.0
- center_sel_z = (Left_Up_Front_SEL[2] + Right_Down_Back_SEL[2]) / 2.0
+ center_sel_x = (Left_Front_Up_SEL[0] + Right_Back_Down_SEL[0]) / 2.0
+ center_sel_y = (Left_Front_Up_SEL[1] + Right_Back_Down_SEL[1]) / 2.0
+ center_sel_z = (Left_Front_Up_SEL[2] + Right_Back_Down_SEL[2]) / 2.0
# Main Loop
for obj, bb_world in objs:
- bb_world = [Vector(v[:]) * obj.matrix_world for v in obj.bound_box]
+ matrix_world = obj.matrix_world.copy()
+ bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box]
- Left_Up_Front = bb_world[1]
- Right_Down_Back = bb_world[7]
+ if bb_quality:
+ GBB = GlobalBB_HQ(obj)
+ else:
+ GBB = GlobalBB_LQ(bb_world)
+
+ Left_Front_Up = GBB[0]
+ Right_Back_Down = GBB[1]
- center_x = (Left_Up_Front[0] + Right_Down_Back[0]) / 2.0
- center_y = (Left_Up_Front[1] + Right_Down_Back[1]) / 2.0
- center_z = (Left_Up_Front[2] + Right_Down_Back[2]) / 2.0
+ center_x = (Left_Front_Up[0] + Right_Back_Down[0]) / 2.0
+ center_y = (Left_Front_Up[1] + Right_Back_Down[1]) / 2.0
+ center_z = (Left_Front_Up[2] + Right_Back_Down[2]) / 2.0
- positive_x = Right_Down_Back[0]
- positive_y = Right_Down_Back[1]
- positive_z = Left_Up_Front[2]
+ positive_x = Right_Back_Down[0]
+ positive_y = Right_Back_Down[1]
+ positive_z = Left_Front_Up[2]
- negative_x = Left_Up_Front[0]
- negative_y = Left_Up_Front[1]
- negative_z = Right_Down_Back[2]
+ negative_x = Left_Front_Up[0]
+ negative_y = Left_Front_Up[1]
+ negative_z = Right_Back_Down[2]
obj_loc = obj.location
@@ -229,7 +335,7 @@ def align_objects(align_x, align_y, align_z, align_mode, relative_to):
return True
-from bpy.props import EnumProperty
+from bpy.props import EnumProperty, BoolProperty
class AlignObjects(bpy.types.Operator):
@@ -238,6 +344,11 @@ class AlignObjects(bpy.types.Operator):
bl_label = _("Align Objects")
bl_options = {'REGISTER', 'UNDO'}
+ bb_quality = BoolProperty(
+ name=_("High Quality"),
+ description=_("Enables high quality calculation of the bounding box for perfect results on complex shape meshes with rotation/scale (Slow)"),
+ default=True)
+
align_mode = EnumProperty(items=(
('OPT_1', "Negative Sides", ""),
('OPT_2', "Centers", ""),
@@ -270,7 +381,12 @@ class AlignObjects(bpy.types.Operator):
def execute(self, context):
align_axis = self.align_axis
- ret = align_objects('X' in align_axis, 'Y' in align_axis, 'Z' in align_axis, self.align_mode, self.relative_to)
+ ret = align_objects('X' in align_axis,
+ 'Y' in align_axis,
+ 'Z' in align_axis,
+ self.align_mode,
+ self.relative_to,
+ self.bb_quality)
if not ret:
self.report({'WARNING'}, "No objects with bound-box selected")
diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py
index 074f204d50e..ba739648000 100644
--- a/release/scripts/startup/bl_operators/object_quick_effects.py
+++ b/release/scripts/startup/bl_operators/object_quick_effects.py
@@ -16,12 +16,17 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
from mathutils import Vector
import bpy
-from bpy.props import BoolProperty, EnumProperty, IntProperty, FloatProperty, FloatVectorProperty
-
+from bpy.props import (BoolProperty,
+ EnumProperty,
+ IntProperty,
+ FloatProperty,
+ FloatVectorProperty,
+ )
+from blf import gettext as _
def object_ensure_material(obj, mat_name):
""" Use an existing material or add a new one.
@@ -61,7 +66,8 @@ class QuickFur(bpy.types.Operator):
def execute(self, context):
fake_context = bpy.context.copy()
- mesh_objects = [obj for obj in context.selected_objects if obj.type == 'MESH']
+ mesh_objects = [obj for obj in context.selected_objects
+ if obj.type == 'MESH']
if not mesh_objects:
self.report({'ERROR'}, "Select at least one mesh object.")
@@ -92,7 +98,8 @@ class QuickFur(bpy.types.Operator):
psys.settings.child_type = 'INTERPOLATED'
obj.data.materials.append(mat)
- obj.particle_systems[-1].settings.material = len(obj.data.materials)
+ obj.particle_systems[-1].settings.material = \
+ len(obj.data.materials)
return {'FINISHED'}
@@ -149,7 +156,10 @@ class QuickExplode(bpy.types.Operator):
for obj in mesh_objects:
if obj.particle_systems:
- self.report({'ERROR'}, "Object %r already has a particle system" % obj.name)
+ self.report({'ERROR'},
+ "Object %r already has a "
+ "particle system" % obj.name)
+
return {'CANCELLED'}
if self.fade:
@@ -184,9 +194,7 @@ class QuickExplode(bpy.types.Operator):
if self.fade:
explode.show_dead = False
- bpy.ops.mesh.uv_texture_add(fake_context)
- uv = obj.data.uv_textures[-1]
- uv.name = "Explode fade"
+ uv = obj.data.uv_textures.new("Explode fade")
explode.particle_uv = uv.name
mat = object_ensure_material(obj, "Explode Fade")
@@ -247,7 +255,7 @@ class QuickExplode(bpy.types.Operator):
def obj_bb_minmax(obj, min_co, max_co):
for i in range(0, 8):
- bb_vec = Vector(obj.bound_box[i]) * obj.matrix_world
+ bb_vec = obj.matrix_world * Vector(obj.bound_box[i])
min_co[0] = min(bb_vec[0], min_co[0])
min_co[1] = min(bb_vec[1], min_co[1])
@@ -262,21 +270,26 @@ class QuickSmoke(bpy.types.Operator):
bl_label = "Quick Smoke"
bl_options = {'REGISTER', 'UNDO'}
- style = EnumProperty(items=(
- ('STREAM', "Stream", ""),
- ('PUFF', "Puff", ""),
- ('FIRE', "Fire", "")),
- name="Smoke Style",
- description="",
- default='STREAM')
-
- show_flows = BoolProperty(name="Render Smoke Objects",
- description="Keep the smoke objects visible during rendering.",
- default=False)
+ style = EnumProperty(
+ items=(('STREAM', "Stream", ""),
+ ('PUFF', "Puff", ""),
+ ('FIRE', "Fire", ""),
+ ),
+ name="Smoke Style",
+ description="",
+ default='STREAM',
+ )
+
+ show_flows = BoolProperty(
+ name=_("Render Smoke Objects"),
+ description=_("Keep the smoke objects visible during rendering."),
+ default=False,
+ )
def execute(self, context):
fake_context = bpy.context.copy()
- mesh_objects = [obj for obj in context.selected_objects if obj.type == 'MESH']
+ mesh_objects = [obj for obj in context.selected_objects
+ if obj.type == 'MESH']
min_co = Vector((100000.0, 100000.0, 100000.0))
max_co = -min_co
@@ -336,21 +349,25 @@ class QuickSmoke(bpy.types.Operator):
mat.volume.density = 0
mat.volume.density_scale = 5
- mat.texture_slots.add()
- mat.texture_slots[0].texture = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA')
- mat.texture_slots[0].texture.voxel_data.domain_object = obj
- mat.texture_slots[0].use_map_color_emission = False
- mat.texture_slots[0].use_map_density = True
+ tex = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA')
+ tex.voxel_data.domain_object = obj
+
+ tex_slot = mat.texture_slots.add()
+ tex_slot.texture = tex
+ tex_slot.use_map_color_emission = False
+ tex_slot.use_map_density = True
# for fire add a second texture for emission and emission color
if self.style == 'FIRE':
mat.volume.emission = 5
- mat.texture_slots.add()
- mat.texture_slots[1].texture = bpy.data.textures.new("Smoke Heat", 'VOXEL_DATA')
- mat.texture_slots[1].texture.voxel_data.domain_object = obj
- mat.texture_slots[1].texture.use_color_ramp = True
+ tex = bpy.data.textures.new("Smoke Heat", 'VOXEL_DATA')
+ tex.voxel_data.domain_object = obj
+ tex.use_color_ramp = True
+
+ tex_slot = mat.texture_slots.add()
+ tex_slot.texture = tex
- ramp = mat.texture_slots[1].texture.color_ramp
+ ramp = tex.color_ramp
elem = ramp.elements.new(0.333)
elem.color[0] = elem.color[3] = 1
@@ -371,28 +388,37 @@ class QuickFluid(bpy.types.Operator):
bl_label = "Quick Fluid"
bl_options = {'REGISTER', 'UNDO'}
- style = EnumProperty(items=(
- ('INFLOW', "Inflow", ""),
- ('BASIC', "Basic", "")),
+ style = EnumProperty(
+ items=(('INFLOW', "Inflow", ""),
+ ('BASIC', "Basic", ""),
+ ),
name="Fluid Style",
description="",
- default='BASIC')
-
- initial_velocity = FloatVectorProperty(name="Initial Velocity",
- description="Initial velocity of the fluid",
- default=(0.0, 0.0, 0.0), min=-100.0, max=100.0, subtype='VELOCITY')
-
- show_flows = BoolProperty(name="Render Fluid Objects",
- description="Keep the fluid objects visible during rendering.",
- default=False)
-
- start_baking = BoolProperty(name="Start Fluid Bake",
- description="Start baking the fluid immediately after creating the domain object.",
- default=False)
+ default='BASIC',
+ )
+ initial_velocity = FloatVectorProperty(
+ name=_("Initial Velocity"),
+ description=_("Initial velocity of the fluid"),
+ default=(0.0, 0.0, 0.0),
+ min=-100.0,
+ max=100.0,
+ subtype='VELOCITY',
+ )
+ show_flows = BoolProperty(
+ name=_("Render Fluid Objects"),
+ description=_("Keep the fluid objects visible during rendering."),
+ default=False,
+ )
+ start_baking = BoolProperty(
+ name=_("Start Fluid Bake"),
+ description=_("Start baking the fluid immediately after creating the domain object"),
+ default=False,
+ )
def execute(self, context):
fake_context = bpy.context.copy()
- mesh_objects = [obj for obj in context.selected_objects if (obj.type == 'MESH' and not 0 in obj.dimensions)]
+ mesh_objects = [obj for obj in context.selected_objects
+ if (obj.type == 'MESH' and not 0.0 in obj.dimensions)]
min_co = Vector((100000, 100000, 100000))
max_co = Vector((-100000, -100000, -100000))
@@ -405,7 +431,8 @@ class QuickFluid(bpy.types.Operator):
# make each selected object a fluid
bpy.ops.object.modifier_add(fake_context, type='FLUID_SIMULATION')
- # fluid has to be before constructive modifiers, so it might not be the last modifier
+ # fluid has to be before constructive modifiers,
+ # so it might not be the last modifier
for mod in obj.modifiers:
if mod.type == 'FLUID_SIMULATION':
break
@@ -429,10 +456,14 @@ class QuickFluid(bpy.types.Operator):
obj = context.active_object
obj.name = "Fluid Domain"
- # give the fluid some room below the flows and scale with initial velocity
+ # give the fluid some room below the flows
+ # and scale with initial velocity
v = 0.5 * self.initial_velocity
obj.location = 0.5 * (max_co + min_co) + Vector((0.0, 0.0, -1.0)) + v
- obj.scale = 0.5 * (max_co - min_co) + Vector((1.0, 1.0, 2.0)) + Vector((abs(v[0]), abs(v[1]), abs(v[2])))
+ obj.scale = (0.5 * (max_co - min_co) +
+ Vector((1.0, 1.0, 2.0)) +
+ Vector((abs(v[0]), abs(v[1]), abs(v[2])))
+ )
# setup smoke domain
bpy.ops.object.modifier_add(type='FLUID_SIMULATION')
diff --git a/release/scripts/startup/bl_operators/object_randomize_transform.py b/release/scripts/startup/bl_operators/object_randomize_transform.py
index d95a21cca81..acb988e147a 100644
--- a/release/scripts/startup/bl_operators/object_randomize_transform.py
+++ b/release/scripts/startup/bl_operators/object_randomize_transform.py
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
from blf import gettext as _
@@ -94,40 +94,67 @@ class RandomizeLocRotSize(bpy.types.Operator):
bl_label = _("Randomize Transform")
bl_options = {'REGISTER', 'UNDO'}
- random_seed = IntProperty(name="Random Seed",
- description="Seed value for the random generator",
- default=0, min=0, max=1000)
-
- use_delta = BoolProperty(name="Transform Delta",
- description="Randomize delta transform values instead of regular transform", default=False)
-
- use_loc = BoolProperty(name="Randomize Location",
- description="Randomize the location values", default=True)
-
- loc = FloatVectorProperty(name="Location",
- description="Maximun distance the objects can spread over each axis",
- default=(0.0, 0.0, 0.0), min=-100.0, max=100.0, subtype='TRANSLATION')
-
- use_rot = BoolProperty(name="Randomize Rotation",
- description="Randomize the rotation values", default=True)
-
- rot = FloatVectorProperty(name="Rotation",
- description="Maximun rotation over each axis",
- default=(0.0, 0.0, 0.0), min=-180.0, max=180.0, subtype='TRANSLATION')
-
- use_scale = BoolProperty(name="Randomize Scale",
- description="Randomize the scale values", default=True)
-
- scale_even = BoolProperty(name="Scale Even",
- description="Use the same scale value for all axis", default=False)
+ random_seed = IntProperty(
+ name=_("Random Seed"),
+ description=_("Seed value for the random generator"),
+ min=0,
+ max=1000,
+ default=0,
+ )
+ use_delta = BoolProperty(
+ name=_("Transform Delta"),
+ description=_("Randomize delta transform values instead of regular transform"),
+ default=False,
+ )
+ use_loc = BoolProperty(
+ name=_("Randomize Location"),
+ description=_("Randomize the location values"),
+ default=True,
+ )
+ loc = FloatVectorProperty(
+ name=_("Location"),
+ description=_("Maximun distance the objects can spread over each axis"),
+ min=-100.0,
+ max=100.0,
+ default=(0.0, 0.0, 0.0),
+ subtype='TRANSLATION',
+ )
+ use_rot = BoolProperty(
+ name=_("Randomize Rotation"),
+ description=_("Randomize the rotation values"),
+ default=True,
+ )
+ rot = FloatVectorProperty(
+ name=_("Rotation"),
+ description=_("Maximun rotation over each axis"),
+ min=-180.0,
+ max=180.0,
+ default=(0.0, 0.0, 0.0),
+ subtype='TRANSLATION',
+ )
+ use_scale = BoolProperty(
+ name=_("Randomize Scale"),
+ description=_("Randomize the scale values"),
+ default=True,
+ )
+ scale_even = BoolProperty(
+ name=_("Scale Even"),
+ description=_("Use the same scale value for all axis"),
+ default=False,
+ )
'''scale_min = FloatProperty(name="Minimun Scale Factor",
description="Lowest scale percentage possible",
default=0.15, min=-1.0, max=1.0, precision=3)'''
- scale = FloatVectorProperty(name="Scale",
- description="Maximum scale randomization over each axis",
- default=(0.0, 0.0, 0.0), min=-100.0, max=100.0, subtype='TRANSLATION')
+ scale = FloatVectorProperty(
+ name=_("Scale"),
+ description=_("Maximum scale randomization over each axis"),
+ min=-100.0,
+ max=100.0,
+ default=(0.0, 0.0, 0.0),
+ subtype='TRANSLATION',
+ )
def execute(self, context):
from math import radians
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index 6624c2ad288..31a6f421768 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
from blf import gettext as _
@@ -31,8 +31,15 @@ class AddPresetBase():
# bl_label = "Add a Python Preset"
bl_options = {'REGISTER'} # only because invoke_props_popup requires.
- name = bpy.props.StringProperty(name="Name", description="Name of the preset, used to make the path name", maxlen=64, default="")
- remove_active = bpy.props.BoolProperty(default=False, options={'HIDDEN'})
+ name = bpy.props.StringProperty(
+ name=_("Name"),
+ description=_("Name of the preset, used to make the path name"),
+ maxlen=64,
+ )
+ remove_active = bpy.props.BoolProperty(
+ default=False,
+ options={'HIDDEN'},
+ )
@staticmethod
def as_filename(name): # could reuse for other presets
@@ -55,7 +62,10 @@ class AddPresetBase():
filename = self.as_filename(name)
- target_path = bpy.utils.user_resource('SCRIPTS', os.path.join("presets", self.preset_subdir), create=True)
+ target_path = os.path.join("presets", self.preset_subdir)
+ target_path = bpy.utils.user_resource('SCRIPTS',
+ target_path,
+ create=True)
if not target_path:
self.report({'WARNING'}, "Failed to create presets path")
@@ -96,7 +106,9 @@ class AddPresetBase():
filepath = bpy.utils.preset_find(preset_active, self.preset_subdir)
if not filepath:
- filepath = bpy.utils.preset_find(preset_active, self.preset_subdir, display_name=True)
+ filepath = bpy.utils.preset_find(preset_active,
+ self.preset_subdir,
+ display_name=True)
if not filepath:
return {'CANCELLED'}
@@ -132,10 +144,17 @@ class AddPresetBase():
class ExecutePreset(bpy.types.Operator):
''' Executes a preset '''
bl_idname = "script.execute_preset"
- bl_label = "Execute a Python Preset"
-
- filepath = bpy.props.StringProperty(name="Path", description="Path of the Python file to execute", maxlen=512, default="")
- menu_idname = bpy.props.StringProperty(name="Menu ID Name", description="ID name of the menu this was called from", default="")
+ bl_label = _("Execute a Python Preset")
+
+ filepath = bpy.props.StringProperty(
+ name=_("Path"),
+ description=_("Path of the Python file to execute"),
+ maxlen=512,
+ )
+ menu_idname = bpy.props.StringProperty(
+ name=_("Menu ID Name"),
+ description=_("ID name of the menu this was called from"),
+ )
def execute(self, context):
from os.path import basename
@@ -153,7 +172,7 @@ class ExecutePreset(bpy.types.Operator):
class AddPresetRender(AddPresetBase, bpy.types.Operator):
'''Add a Render Preset'''
bl_idname = "render.preset_add"
- bl_label = "Add Render Preset"
+ bl_label = _("Add Render Preset")
preset_menu = "RENDER_MT_presets"
preset_defines = [
@@ -179,11 +198,14 @@ class AddPresetRender(AddPresetBase, bpy.types.Operator):
class AddPresetSSS(AddPresetBase, bpy.types.Operator):
'''Add a Subsurface Scattering Preset'''
bl_idname = "material.sss_preset_add"
- bl_label = "Add SSS Preset"
+ bl_label = _("Add SSS Preset")
preset_menu = "MATERIAL_MT_sss_presets"
preset_defines = [
- "material = (bpy.context.material.active_node_material if bpy.context.material.active_node_material else bpy.context.material)"
+ ("material = "
+ "bpy.context.material.active_node_material "
+ "if bpy.context.material.active_node_material "
+ "else bpy.context.material")
]
preset_values = [
@@ -204,7 +226,7 @@ class AddPresetSSS(AddPresetBase, bpy.types.Operator):
class AddPresetCloth(AddPresetBase, bpy.types.Operator):
'''Add a Cloth Preset'''
bl_idname = "cloth.preset_add"
- bl_label = "Add Cloth Preset"
+ bl_label = _("Add Cloth Preset")
preset_menu = "CLOTH_MT_presets"
preset_defines = [
@@ -226,7 +248,7 @@ class AddPresetCloth(AddPresetBase, bpy.types.Operator):
class AddPresetSunSky(AddPresetBase, bpy.types.Operator):
'''Add a Sky & Atmosphere Preset'''
bl_idname = "lamp.sunsky_preset_add"
- bl_label = "Add Sunsky Preset"
+ bl_label = _("Add Sunsky Preset")
preset_menu = "LAMP_MT_sunsky_presets"
preset_defines = [
@@ -282,7 +304,7 @@ class AddPresetInteraction(AddPresetBase, bpy.types.Operator):
class AddPresetKeyconfig(AddPresetBase, bpy.types.Operator):
'''Add a Keyconfig Preset'''
bl_idname = "wm.keyconfig_preset_add"
- bl_label = "Add Keyconfig Preset"
+ bl_label = _("Add Keyconfig Preset")
preset_menu = "USERPREF_MT_keyconfigs"
preset_subdir = "keyconfig"
__doc__ = _('Add a Keyconfig Preset')
@@ -310,7 +332,11 @@ class AddPresetOperator(AddPresetBase, bpy.types.Operator):
preset_menu = "WM_MT_operator_presets"
__doc__ = _("Add an Application Interaction Preset")
- operator = bpy.props.StringProperty(name="Operator", maxlen=64, options={'HIDDEN'})
+ operator = bpy.props.StringProperty(
+ name=_("Operator"),
+ maxlen=64,
+ options={'HIDDEN'},
+ )
# XXX, not ideal
preset_defines = [
@@ -326,12 +352,15 @@ class AddPresetOperator(AddPresetBase, bpy.types.Operator):
properties_blacklist = bpy.types.Operator.bl_rna.properties.keys()
prefix, suffix = self.operator.split("_OT_", 1)
- operator_rna = getattr(getattr(bpy.ops, prefix.lower()), suffix).get_rna().bl_rna
+ op = getattr(getattr(bpy.ops, prefix.lower()), suffix)
+ operator_rna = op.get_rna().bl_rna
+ del op
ret = []
for prop_id, prop in operator_rna.properties.items():
- if (not (prop.is_hidden or prop.is_skip_save)) and prop_id not in properties_blacklist:
- ret.append("op.%s" % prop_id)
+ if not (prop.is_hidden or prop.is_skip_save):
+ if prop_id not in properties_blacklist:
+ ret.append("op.%s" % prop_id)
return ret
@@ -343,7 +372,7 @@ class AddPresetOperator(AddPresetBase, bpy.types.Operator):
class WM_MT_operator_presets(bpy.types.Menu):
- bl_label = "Operator Presets"
+ bl_label = _("Operator Presets")
def draw(self, context):
self.operator = context.space_data.operator.bl_idname
diff --git a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
index 2406cc59952..ba0b1da45d1 100644
--- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
+++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
@@ -1,27 +1,23 @@
-# ***** BEGIN GPL LICENSE BLOCK *****
+# ##### BEGIN GPL LICENSE BLOCK #####
#
-# Script copyright (C) Campbell J Barton
+# 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 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.
#
-# 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.
#
-# 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 LICENCE BLOCK *****
+# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
-# History
-#
# Originally written by Matt Ebb
import bpy
@@ -47,8 +43,10 @@ def guess_player_path(preset):
player_path = "djv_view"
if sys.platform == "darwin":
- # TODO, crummy supporting only 1 version, could find the newest installed version
- test_path = '/Applications/djv-0.8.2.app/Contents/Resources/bin/djv_view'
+ # TODO, crummy supporting only 1 version,
+ # could find the newest installed version
+ test_path = ("/Applications/djv-0.8.2.app"
+ "/Contents/Resources/bin/djv_view")
if os.path.exists(test_path):
player_path = test_path
@@ -61,6 +59,9 @@ def guess_player_path(preset):
elif preset == 'MPLAYER':
player_path = "mplayer"
+ else:
+ player_path = ""
+
return player_path
@@ -84,10 +85,10 @@ class PlayRenderedAnim(bpy.types.Operator):
is_movie = rd.is_movie_format
# try and guess a command line if it doesn't exist
- if player_path == '':
+ if player_path == "":
player_path = guess_player_path(preset)
- if is_movie == False and preset in ('FRAMECYCLER', 'RV', 'MPLAYER'):
+ if is_movie == False and preset in {'FRAMECYCLER', 'RV', 'MPLAYER'}:
# replace the number with '#'
file_a = rd.frame_path(frame=0)
@@ -97,11 +98,11 @@ class PlayRenderedAnim(bpy.types.Operator):
while len(file_a) == len(file_b):
frame_tmp = (frame_tmp * 10) + 9
- print(frame_tmp)
file_b = rd.frame_path(frame=frame_tmp)
file_b = rd.frame_path(frame=int(frame_tmp / 10))
- file = "".join((c if file_b[i] == c else "#") for i, c in enumerate(file_a))
+ file = ("".join((c if file_b[i] == c else "#")
+ for i, c in enumerate(file_a)))
else:
# works for movies and images
file = rd.frame_path(frame=scene.frame_start)
@@ -111,10 +112,35 @@ class PlayRenderedAnim(bpy.types.Operator):
cmd = [player_path]
# extra options, fps controls etc.
if preset == 'BLENDER24':
+ # -----------------------------------------------------------------
+ # Check blender is not 2.5x until it supports playback again
+ try:
+ process = subprocess.Popen([player_path, '--version'],
+ stdout=subprocess.PIPE,
+ )
+ except:
+ # ignore and allow the main execution to catch the problem.
+ process = None
+
+ if process is not None:
+ process.wait()
+ out = process.stdout.read()
+ process.stdout.close()
+ out_split = out.strip().split()
+ if out_split[0] == b'Blender':
+ if not out_split[1].startswith(b'2.4'):
+ self.report({'ERROR'},
+ "Blender %s doesn't support playback: %r" %
+ (out_split[1].decode(), player_path))
+ return {'CANCELLED'}
+ del out, out_split
+ del process
+ # -----------------------------------------------------------------
+
opts = ["-a", "-f", str(rd.fps), str(rd.fps_base), file]
cmd.extend(opts)
elif preset == 'DJV':
- opts = [file, "-playback_speed", str(rd.fps)]
+ opts = [file, "-playback_speed", "%d" % int(rd.fps / rd.fps_base)]
cmd.extend(opts)
elif preset == 'FRAMECYCLER':
opts = [file, "%d-%d" % (scene.frame_start, scene.frame_end)]
@@ -127,18 +153,26 @@ class PlayRenderedAnim(bpy.types.Operator):
if is_movie:
opts.append(file)
else:
- opts.append("mf://%s" % file.replace("#", "?"))
- opts += ["-mf", "fps=%.4f" % (rd.fps / rd.fps_base)]
+ opts += [("mf://%s" % file.replace("#", "?")),
+ "-mf",
+ "fps=%.4f" % (rd.fps / rd.fps_base),
+ ]
+
opts += ["-loop", "0", "-really-quiet", "-fs"]
cmd.extend(opts)
else: # 'CUSTOM'
cmd.append(file)
# launch it
+ print("Executing command:\n %r" % " ".join(cmd))
+
try:
process = subprocess.Popen(cmd)
- except:
- pass
- #raise OSError("Couldn't find an external animation player.")
+ except Exception as e:
+ import traceback
+ self.report({'ERROR'},
+ "Couldn't run external animation player with command "
+ "%r\n%s" % (" ".join(cmd), str(e)))
+ return {'CANCELLED'}
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
index 7ea89cfa479..851f33bde11 100644
--- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py
+++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
@@ -243,7 +243,7 @@ def testNewVecLs2DRotIsBetter(vecs, mat=-1, bestAreaSoFar = -1):
# Do this allong the way
if mat != -1:
- v = vecs[i] = v*mat
+ v = vecs[i] = mat * v
x= v.x
y= v.y
if x<minx: minx= x
@@ -747,14 +747,8 @@ def packIslands(islandList):
def VectoQuat(vec):
- a3 = vec.normalized()
- up = Vector((0.0, 0.0, 1.0))
- if abs(a3.dot(up)) == 1.0:
- up = Vector((0.0, 1.0, 0.0))
-
- a1 = a3.cross(up).normalized()
- a2 = a3.cross(a1)
- return Matrix((a1, a2, a3)).to_quaternion()
+ vec = vec.normalized()
+ return vec.to_track_quat('Z', 'X' if abs(vec.x) > 0.5 else 'Y').inverted()
class thickface(object):
@@ -1070,7 +1064,7 @@ def main(context,
f_uv = f.uv
for j, v in enumerate(f.v):
# XXX - note, between mathutils in 2.4 and 2.5 the order changed.
- f_uv[j][:] = (v.co * MatQuat).xy
+ f_uv[j][:] = (MatQuat * v.co).xy
if USER_SHARE_SPACE:
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 00a2f546382..ae44860c3dd 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -773,7 +773,7 @@ class WM_OT_doc_edit(bpy.types.Operator):
def draw(self, context):
layout = self.layout
- layout.label(text=_("Descriptor ID: '%s'") % self.doc_id)
+ layout.label(text=_("Descriptor ID")+": '%s'" % self.doc_id)
layout.prop(self, "doc_new", text="")
def invoke(self, context, event):
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index ce6d0990f05..0a4d0b60514 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -394,6 +394,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.operator("object.multires_higher_levels_delete", text="Delete Higher")
col.operator("object.multires_reshape", text="Reshape")
col.operator("object.multires_base_apply", text="Apply Base")
+ col.prop(md, "use_subsurf_uv")
col.prop(md, "show_only_control_edges")
layout.separator()
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index 45c15bd1ce6..2a52ae23782 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -174,6 +174,7 @@ class MATERIAL_PT_pipeline(MaterialButtonsPanel, bpy.types.Panel):
row.prop(mat, "use_transparency")
sub = row.column()
sub.prop(mat, "offset_z")
+
sub.active = mat_type and mat.use_transparency and mat.transparency_method == 'Z_TRANSPARENCY'
row = layout.row()
@@ -199,6 +200,7 @@ class MATERIAL_PT_pipeline(MaterialButtonsPanel, bpy.types.Panel):
col.prop(mat, "shadow_cast_alpha", text="Casting Alpha")
col.prop(mat, "use_cast_buffer_shadows")
col.prop(mat, "use_cast_approximate")
+ col.prop(mat, "pass_index")
class MATERIAL_PT_diffuse(MaterialButtonsPanel, bpy.types.Panel):
@@ -729,7 +731,8 @@ class MATERIAL_PT_options(MaterialButtonsPanel, bpy.types.Panel):
col.prop(mat, "use_vertex_color_paint")
col.prop(mat, "use_vertex_color_light")
col.prop(mat, "use_object_color")
- col.prop(mat, "pass_index")
+ if simple_material(base_mat):
+ col.prop(mat, "pass_index")
class MATERIAL_PT_shadow(MaterialButtonsPanel, bpy.types.Panel):
diff --git a/release/scripts/startup/bl_ui/properties_world.py b/release/scripts/startup/bl_ui/properties_world.py
index 4f398c9fbd9..63f8e88147b 100644
--- a/release/scripts/startup/bl_ui/properties_world.py
+++ b/release/scripts/startup/bl_ui/properties_world.py
@@ -19,8 +19,7 @@
# <pep8 compliant>
import bpy
from rna_prop_ui import PropertyPanel
-
-# TODO, "color_range" not in the UI
+from blf import gettext as _
class WorldButtonsPanel():
@@ -64,7 +63,7 @@ class WORLD_PT_context_world(WorldButtonsPanel, bpy.types.Panel):
class WORLD_PT_preview(WorldButtonsPanel, bpy.types.Panel):
- bl_label = "Preview"
+ bl_label = _("Preview")
COMPAT_ENGINES = {'BLENDER_RENDER'}
@classmethod
@@ -77,7 +76,7 @@ class WORLD_PT_preview(WorldButtonsPanel, bpy.types.Panel):
class WORLD_PT_world(WorldButtonsPanel, bpy.types.Panel):
- bl_label = "World"
+ bl_label = _("World")
COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw(self, context):
@@ -95,10 +94,14 @@ class WORLD_PT_world(WorldButtonsPanel, bpy.types.Panel):
col.prop(world, "zenith_color")
col.active = world.use_sky_blend
row.column().prop(world, "ambient_color")
+
+ row = layout.row()
+ row.prop(world, "exposure")
+ row.prop(world, "color_range")
class WORLD_PT_ambient_occlusion(WorldButtonsPanel, bpy.types.Panel):
- bl_label = "Ambient Occlusion"
+ bl_label = _("Ambient Occlusion")
COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw_header(self, context):
@@ -112,12 +115,12 @@ class WORLD_PT_ambient_occlusion(WorldButtonsPanel, bpy.types.Panel):
layout.active = light.use_ambient_occlusion
split = layout.split()
- split.prop(light, "ao_factor", text="Factor")
+ split.prop(light, "ao_factor", text=_("Factor"))
split.prop(light, "ao_blend_type", text="")
class WORLD_PT_environment_lighting(WorldButtonsPanel, bpy.types.Panel):
- bl_label = "Environment Lighting"
+ bl_label = _("Environment Lighting")
COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw_header(self, context):
@@ -131,12 +134,12 @@ class WORLD_PT_environment_lighting(WorldButtonsPanel, bpy.types.Panel):
layout.active = light.use_environment_light
split = layout.split()
- split.prop(light, "environment_energy", text="Energy")
+ split.prop(light, "environment_energy", text=_("Energy"))
split.prop(light, "environment_color", text="")
class WORLD_PT_indirect_lighting(WorldButtonsPanel, bpy.types.Panel):
- bl_label = "Indirect Lighting"
+ bl_label = _("Indirect Lighting")
COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw_header(self, context):
@@ -150,15 +153,15 @@ class WORLD_PT_indirect_lighting(WorldButtonsPanel, bpy.types.Panel):
layout.active = light.use_indirect_light and light.gather_method == 'APPROXIMATE'
split = layout.split()
- split.prop(light, "indirect_factor", text="Factor")
- split.prop(light, "indirect_bounces", text="Bounces")
+ split.prop(light, "indirect_factor", text=_("Factor"))
+ split.prop(light, "indirect_bounces", text=_("Bounces"))
if light.gather_method == 'RAYTRACE':
- layout.label(text="Only works with Approximate gather method")
+ layout.label(text=_("Only works with Approximate gather method"))
class WORLD_PT_gather(WorldButtonsPanel, bpy.types.Panel):
- bl_label = "Gather"
+ bl_label = _("Gather")
COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw(self, context):
@@ -172,18 +175,18 @@ class WORLD_PT_gather(WorldButtonsPanel, bpy.types.Panel):
split = layout.split()
col = split.column()
- col.label(text="Attenuation:")
+ col.label(text=_("Attenuation:"))
if light.gather_method == 'RAYTRACE':
col.prop(light, "distance")
col.prop(light, "use_falloff")
sub = col.row()
sub.active = light.use_falloff
- sub.prop(light, "falloff_strength", text="Strength")
+ sub.prop(light, "falloff_strength", text=_("Strength"))
if light.gather_method == 'RAYTRACE':
col = split.column()
- col.label(text="Sampling:")
+ col.label(text=_("Sampling:"))
col.prop(light, "sample_method", text="")
sub = col.column()
@@ -198,15 +201,15 @@ class WORLD_PT_gather(WorldButtonsPanel, bpy.types.Panel):
if light.gather_method == 'APPROXIMATE':
col = split.column()
- col.label(text="Sampling:")
+ col.label(text=_("Sampling:"))
col.prop(light, "passes")
- col.prop(light, "error_threshold", text="Error")
+ col.prop(light, "error_threshold", text=_("Error"))
col.prop(light, "use_cache")
col.prop(light, "correction")
class WORLD_PT_mist(WorldButtonsPanel, bpy.types.Panel):
- bl_label = "Mist"
+ bl_label = _("Mist")
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -235,7 +238,7 @@ class WORLD_PT_mist(WorldButtonsPanel, bpy.types.Panel):
class WORLD_PT_stars(WorldButtonsPanel, bpy.types.Panel):
- bl_label = "Stars"
+ bl_label = _("Stars")
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -254,11 +257,11 @@ class WORLD_PT_stars(WorldButtonsPanel, bpy.types.Panel):
col = split.column()
col.prop(world.star_settings, "size")
- col.prop(world.star_settings, "color_random", text="Colors")
+ col.prop(world.star_settings, "color_random", text=_("Colors"))
col = split.column()
- col.prop(world.star_settings, "distance_min", text="Min. Dist")
- col.prop(world.star_settings, "average_separation", text="Separation")
+ col.prop(world.star_settings, "distance_min", text=_("Min. Dist"))
+ col.prop(world.star_settings, "average_separation", text=_("Separation"))
class WORLD_PT_custom_props(WorldButtonsPanel, PropertyPanel, bpy.types.Panel):
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 6e0eded1d4c..15ba638dffb 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -64,7 +64,7 @@ class IMAGE_MT_view(bpy.types.Menu):
ratios = [[1, 8], [1, 4], [1, 2], [1, 1], [2, 1], [4, 1], [8, 1]]
for a, b in ratios:
- text = _("Zoom %d:%d") % (a, b)
+ text = _("Zoom") + " %d:%d" % (a, b)
layout.operator("image.view_zoom_ratio", text=text).ratio = a / b
layout.separator()
@@ -199,6 +199,10 @@ class IMAGE_MT_uvs_transform(bpy.types.Menu):
layout.operator("transform.rotate")
layout.operator("transform.resize")
+ layout.separator()
+
+ layout.operator("transform.shear")
+
class IMAGE_MT_uvs_snap(bpy.types.Menu):
bl_label = _("Snap")
diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py
index 4254ec3c9ab..fadd3ec73be 100644
--- a/release/scripts/startup/bl_ui/space_info.py
+++ b/release/scripts/startup/bl_ui/space_info.py
@@ -61,8 +61,10 @@ class INFO_HT_header(bpy.types.Header):
layout.template_running_jobs()
layout.template_reports_banner()
-
- layout.label(text=scene.statistics())
+
+ row = layout.row(align=True)
+ row.operator("wm.splash", text="", icon='BLENDER', emboss=False)
+ row.label(text=scene.statistics())
# XXX: this should be right-aligned to the RHS of the region
layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER', text="")
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index e7276b82aba..1f9d45e9bc4 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -358,13 +358,13 @@ class SEQUENCER_PT_edit(SequencerButtonsPanel, bpy.types.Panel):
col = layout.column(align=True)
row = col.row()
- row.label(text=_("Final Length: %s") % bpy.utils.smpte_from_frame(strip.frame_final_duration))
+ row.label(text=_("Final Length")+": %s" % bpy.utils.smpte_from_frame(strip.frame_final_duration))
row = col.row()
row.active = (frame_current >= strip.frame_start and frame_current <= strip.frame_start + strip.frame_duration)
- row.label(text=_("Playhead: %d") % (frame_current - strip.frame_start))
+ row.label(text=_("Playhead")+": %d" % (frame_current - strip.frame_start))
- col.label(text=_("Frame Offset %d:%d") % (strip.frame_offset_start, strip.frame_offset_end))
- col.label(text=_("Frame Still %d:%d") % (strip.frame_still_start, strip.frame_still_end))
+ col.label(text=_("Frame Offset")+" %d:%d" % (strip.frame_offset_start, strip.frame_offset_end))
+ col.label(text=_("Frame Still")+" %d:%d" % (strip.frame_still_start, strip.frame_still_end))
elem = False
@@ -374,7 +374,7 @@ class SEQUENCER_PT_edit(SequencerButtonsPanel, bpy.types.Panel):
elem = strip.elements[0]
if elem and elem.orig_width > 0 and elem.orig_height > 0:
- col.label(text=_("Orig Dim: %dx%d") % (elem.orig_width, elem.orig_height))
+ col.label(text=_("Orig Dim")+": %dx%d" % (elem.orig_width, elem.orig_height))
class SEQUENCER_PT_effect(SequencerButtonsPanel, bpy.types.Panel):
@@ -668,7 +668,7 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, bpy.types.Panel):
if scene:
sta = scene.frame_start
end = scene.frame_end
- layout.label(text=_("Original frame range: %d-%d (%d)") % (sta, end, end - sta + 1))
+ layout.label(text=_("Original frame range")+": %d-%d (%d)" % (sta, end, end - sta + 1))
class SEQUENCER_PT_filter(SequencerButtonsPanel, bpy.types.Panel):
diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py
index 0c3da2f5e1b..93e513acf0a 100644
--- a/release/scripts/startup/bl_ui/space_text.py
+++ b/release/scripts/startup/bl_ui/space_text.py
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
from blf import gettext as _
@@ -34,19 +34,21 @@ class TEXT_HT_header(bpy.types.Header):
row.template_header()
if context.area.show_menus:
- sub = row.row(align=True)
- sub.menu("TEXT_MT_view")
- sub.menu("TEXT_MT_text")
+ row.menu("TEXT_MT_view")
+ row.menu("TEXT_MT_text")
+
if text:
- sub.menu("TEXT_MT_edit")
- sub.menu("TEXT_MT_format")
+ row.menu("TEXT_MT_edit")
+ row.menu("TEXT_MT_format")
+
+ row.menu("TEXT_MT_templates")
if text and text.is_modified:
- row = layout.row()
- row.alert = True
- row.operator("text.resolve_conflict", text="", icon='HELP')
+ sub = row.row()
+ sub.alert = True
+ sub.operator("text.resolve_conflict", text="", icon='HELP')
- layout.template_ID(st, "text", new="text.new", unlink="text.unlink")
+ row.template_ID(st, "text", new="text.new", unlink="text.unlink")
row = layout.row(align=True)
row.prop(st, "show_line_numbers", text="")
@@ -64,11 +66,13 @@ class TEXT_HT_header(bpy.types.Header):
row = layout.row()
if text.filepath:
if text.is_dirty:
- row.label(text="File: *%s (unsaved)" % text.filepath)
+ row.label(text=_("File")+": *%r " % text.filepath+_("(unsaved)"))
else:
- row.label(text="File: %s" % text.filepath)
+ row.label(text=_("File")+": %r" % text.filepath)
else:
- row.label(text="Text: External" if text.library else "Text: Internal")
+ row.label(text=_("Text: External")
+ if text.library
+ else _("Text: Internal"))
class TEXT_PT_properties(bpy.types.Panel):
@@ -151,8 +155,12 @@ class TEXT_MT_view(bpy.types.Menu):
layout.separator()
- layout.operator("text.move", text=_("Top of File")).type = 'FILE_TOP'
- layout.operator("text.move", text=_("Bottom of File")).type = 'FILE_BOTTOM'
+ layout.operator("text.move",
+ text=_("Top of File"),
+ ).type = 'FILE_TOP'
+ layout.operator("text.move",
+ text=_("Bottom of File"),
+ ).type = 'FILE_BOTTOM'
class TEXT_MT_text(bpy.types.Menu):
@@ -186,19 +194,15 @@ class TEXT_MT_text(bpy.types.Menu):
# XXX uiMenuItemO(head, 0, "text.refresh_pyconstraints");
#endif
- layout.separator()
-
- layout.menu("TEXT_MT_templates")
-
class TEXT_MT_templates(bpy.types.Menu):
- '''
- Creates the menu items by scanning scripts/templates
- '''
- bl_label = _("Script Templates")
+ bl_label = _("Templates")
def draw(self, context):
- self.path_menu(bpy.utils.script_paths("templates"), "text.open", {"internal": True})
+ self.path_menu(bpy.utils.script_paths("templates"),
+ "text.open",
+ {"internal": True},
+ )
class TEXT_MT_edit_select(bpy.types.Menu):
@@ -247,8 +251,12 @@ class TEXT_MT_edit_to3d(bpy.types.Menu):
def draw(self, context):
layout = self.layout
- layout.operator("text.to_3d_object", text=_("One Object")).split_lines = False
- layout.operator("text.to_3d_object", text=_("One Object Per Line")).split_lines = True
+ layout.operator("text.to_3d_object",
+ text=_("One Object"),
+ ).split_lines = False
+ layout.operator("text.to_3d_object",
+ text=_("One Object Per Line"),
+ ).split_lines = True
class TEXT_MT_edit(bpy.types.Menu):
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 900d38d1693..fb5f2de7115 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -355,7 +355,7 @@ class USERPREF_PT_edit(bpy.types.Panel):
col.prop(edit, "use_duplicate_lamp", text=_("Lamp"))
col.prop(edit, "use_duplicate_material", text=_("Material"))
col.prop(edit, "use_duplicate_texture", text=_("Texture"))
- #col.prop(edit, "use_duplicate_fcurve", text="F-Curve")
+ #col.prop(edit, "use_duplicate_fcurve", text=_("F-Curve"))
col.prop(edit, "use_duplicate_action", text=_("Action"))
col.prop(edit, "use_duplicate_particle", text=_("Particle"))
@@ -656,7 +656,7 @@ class USERPREF_PT_theme(bpy.types.Panel):
col = split.column()
for i, ui in enumerate(theme.bone_color_sets):
- col.label(text=_("Color Set %d:") % (i + 1)) # i starts from 0
+ col.label(text=_("Color Set")+" %d:" % (i + 1)) # i starts from 0
row = col.row()
@@ -889,6 +889,16 @@ class USERPREF_PT_addons(bpy.types.Panel):
return True
return False
+ @staticmethod
+ def draw_error(layout, message):
+ lines = message.split("\n")
+ box = layout.box()
+ rowsub = box.row()
+ rowsub.label(lines[0])
+ rowsub.label(icon='ERROR')
+ for l in lines[1:]:
+ box.label(l)
+
def draw(self, context):
layout = self.layout
@@ -909,6 +919,14 @@ class USERPREF_PT_addons(bpy.types.Panel):
col = split.column()
+ # set in addon_utils.modules(...)
+ if addon_utils.error_duplicates:
+ self.draw_error(col,
+ "Multiple addons using the same name found!\n"
+ "likely a problem with the script search path.\n"
+ "(see console for details)",
+ )
+
filter = context.window_manager.addon_filter
search = context.window_manager.addon_search.lower()
support = context.window_manager.addon_support
diff --git a/release/scripts/startup/bl_ui/space_userpref_keymap.py b/release/scripts/startup/bl_ui/space_userpref_keymap.py
index feb90cadd68..fde11a0ac29 100644
--- a/release/scripts/startup/bl_ui/space_userpref_keymap.py
+++ b/release/scripts/startup/bl_ui/space_userpref_keymap.py
@@ -202,7 +202,7 @@ class InputKeyMapPanel:
subcol = self.indented_layout(col, level + 1)
subrow = subcol.row()
subrow.prop(km, "show_expanded_items", text="", emboss=False)
- subrow.label(text=_("%s (Global)") % _(km.name) )
+ subrow.label(text="%s " % _(km.name) + _("(Global)") )
else:
km.show_expanded_items = True
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 9ead8bb98df..b4adc3bf028 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -55,21 +55,13 @@ class VIEW3D_HT_header(bpy.types.Header):
sub.menu("VIEW3D_MT_object")
row = layout.row()
- row.template_header_3D()
-
- # do in C for now since these buttons cant be both toggle AND exclusive.
- '''
- if obj and obj.mode == 'EDIT' and obj.type == 'MESH':
- row_sub = row.row(align=True)
- row_sub.prop(toolsettings, "mesh_select_mode", text="", index=0, icon='VERTEXSEL')
- row_sub.prop(toolsettings, "mesh_select_mode", text="", index=1, icon='EDGESEL')
- row_sub.prop(toolsettings, "mesh_select_mode", text="", index=2, icon='FACESEL')
- '''
+ # Contains buttons like Mode, Pivot, Manipulator, Layer, Mesh Select Mode...
+ row.template_header_3D()
if obj:
# Particle edit
if obj.mode == 'PARTICLE_EDIT':
- row.prop(toolsettings.particle_edit, "select_mode", text="", expand=True, toggle=True)
+ row.prop(toolsettings.particle_edit, "select_mode", text="", expand=True)
# Occlude geometry
if view.viewport_shade in {'SOLID', 'SHADED', 'TEXTURED'} and (obj.mode == 'PARTICLE_EDIT' or (obj.mode == 'EDIT' and obj.type == 'MESH')):
@@ -88,19 +80,22 @@ class VIEW3D_HT_header(bpy.types.Header):
row.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True)
# Snap
+ snap_element = toolsettings.snap_element
row = layout.row(align=True)
row.prop(toolsettings, "use_snap", text="")
row.prop(toolsettings, "snap_element", text="", icon_only=True)
- if toolsettings.snap_element != 'INCREMENT':
+ if snap_element != 'INCREMENT':
row.prop(toolsettings, "snap_target", text="")
- if obj and obj.mode == 'OBJECT':
- row.prop(toolsettings, "use_snap_align_rotation", text="")
- if toolsettings.snap_element == 'VOLUME':
+ if obj:
+ if obj.mode == 'OBJECT':
+ row.prop(toolsettings, "use_snap_align_rotation", text="")
+ elif obj.mode == 'EDIT':
+ row.prop(toolsettings, "use_snap_self", text="")
+
+ if snap_element == 'VOLUME':
row.prop(toolsettings, "use_snap_peel_object", text="")
- elif toolsettings.snap_element == 'FACE':
+ elif snap_element == 'FACE':
row.prop(toolsettings, "use_snap_project", text="")
- if toolsettings.use_snap_project and obj.mode == 'EDIT':
- row.prop(toolsettings, "use_snap_project_self", text="")
# OpenGL render
row = layout.row(align=True)
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index f2370ec39ac..d029de3786c 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -117,7 +117,8 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, bpy.types.Panel):
col.operator("transform.translate")
col.operator("transform.rotate")
col.operator("transform.resize", text="Scale")
- col.operator("transform.shrink_fatten", text="Along Normal")
+ col.operator("transform.shrink_fatten", text=_("Shrink/Fatten"))
+ col.operator("transform.push_pull", text=_("Push/Pull"))
col = layout.column(align=True)
col.label(text="Deform:")
diff --git a/release/scripts/templates/batch_export.py b/release/scripts/templates/batch_export.py
new file mode 100755
index 00000000000..aa0e601725b
--- /dev/null
+++ b/release/scripts/templates/batch_export.py
@@ -0,0 +1,33 @@
+# exports each selected object into its own file
+
+import bpy
+import os
+
+# export to blend file location
+basedir = os.path.dirname(bpy.data.filepath)
+
+if not basedir:
+ raise Exception("Blend file is not saved")
+
+selection = bpy.context.selected_objects
+
+bpy.ops.object.select_all(action='DESELECT')
+
+for obj in selection:
+
+ obj.select = True
+
+ name = bpy.path.clean_name(obj.name)
+ fn = os.path.join(basedir, name)
+
+ bpy.ops.export_scene.fbx(filepath=fn + ".fbx", use_selection=True)
+
+ ## Can be used for multiple formats
+ # bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True)
+
+ obj.select = False
+
+ print("written:", fn)
+
+for obj in selection:
+ obj.select = True
diff --git a/release/scripts/templates/ui_menu.py b/release/scripts/templates/ui_menu.py
new file mode 100755
index 00000000000..d3923b5b083
--- /dev/null
+++ b/release/scripts/templates/ui_menu.py
@@ -0,0 +1,49 @@
+import bpy
+
+
+class CustomMenu(bpy.types.Menu):
+ bl_label = "Custom Menu"
+ bl_idname = "OBJECT_MT_custom_menu"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("wm.open_mainfile")
+ layout.operator("wm.save_as_mainfile").copy = True
+
+ layout.operator("object.shade_smooth")
+
+ layout.label(text="Hello world!", icon='WORLD_DATA')
+
+ # use an operator enum property to populate a submenu
+ layout.operator_menu_enum("object.select_by_type",
+ property="type",
+ text="Select All by Type...",
+ )
+
+ # call another menu
+ layout.operator("wm.call_menu", text="Unwrap").name = "VIEW3D_MT_uv_map"
+
+
+def draw_item(self, context):
+ layout = self.layout
+ layout.menu(CustomMenu.bl_idname)
+
+
+def register():
+ bpy.utils.register_class(CustomMenu)
+
+ # lets add ourselves to the main header
+ bpy.types.INFO_HT_header.append(draw_item)
+
+
+def unregister():
+ bpy.utils.unregister_class(CustomMenu)
+
+ bpy.types.INFO_HT_header.remove(draw_item)
+
+if __name__ == "__main__":
+ register()
+
+ # The menu can also be called from scripts
+ bpy.ops.wm.call_menu(name=CustomMenu.bl_idname)
diff --git a/release/scripts/templates/ui_menu_simple.py b/release/scripts/templates/ui_menu_simple.py
new file mode 100755
index 00000000000..2129dfd81a4
--- /dev/null
+++ b/release/scripts/templates/ui_menu_simple.py
@@ -0,0 +1,26 @@
+import bpy
+
+
+class SimpleCustomMenu(bpy.types.Menu):
+ bl_label = "Simple Custom Menu"
+ bl_idname = "OBJECT_MT_simple_custom_menu"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("wm.open_mainfile")
+ layout.operator("wm.save_as_mainfile")
+
+
+def register():
+ bpy.utils.register_class(SimpleCustomMenu)
+
+
+def unregister():
+ bpy.utils.unregister_class(SimpleCustomMenu)
+
+if __name__ == "__main__":
+ register()
+
+ # The menu can also be called from scripts
+ bpy.ops.wm.call_menu(name=SimpleCustomMenu.bl_idname)
diff --git a/release/scripts/templates/panel_simple.py b/release/scripts/templates/ui_panel_simple.py
index e5bf70cb654..cde6126b626 100644..100755
--- a/release/scripts/templates/panel_simple.py
+++ b/release/scripts/templates/ui_panel_simple.py
@@ -1,8 +1,9 @@
import bpy
-class OBJECT_PT_hello(bpy.types.Panel):
+class HelloWorldPanel(bpy.types.Panel):
bl_label = "Hello World Panel"
+ bl_idname = "OBJECT_PT_hello"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
@@ -22,11 +23,11 @@ class OBJECT_PT_hello(bpy.types.Panel):
def register():
- bpy.utils.register_class(OBJECT_PT_hello)
+ bpy.utils.register_class(HelloWorldPanel)
def unregister():
- bpy.utils.unregister_class(OBJECT_PT_hello)
+ bpy.utils.unregister_class(HelloWorldPanel)
if __name__ == "__main__":