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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release/scripts/startup')
-rw-r--r--release/scripts/startup/bl_operators/add_mesh_torus.py21
-rw-r--r--release/scripts/startup/bl_operators/image.py37
-rw-r--r--release/scripts/startup/bl_operators/mesh.py33
-rw-r--r--release/scripts/startup/bl_operators/nla.py123
-rw-r--r--release/scripts/startup/bl_operators/object.py232
-rw-r--r--release/scripts/startup/bl_operators/object_align.py218
-rw-r--r--release/scripts/startup/bl_operators/object_quick_effects.py313
-rw-r--r--release/scripts/startup/bl_operators/object_randomize_transform.py89
-rw-r--r--release/scripts/startup/bl_operators/presets.py55
-rw-r--r--release/scripts/startup/bl_operators/screen_play_rendered_anim.py96
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_follow_active.py5
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_lightmap.py13
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_smart_project.py60
-rw-r--r--release/scripts/startup/bl_operators/wm.py106
-rw-r--r--release/scripts/startup/bl_ui/__init__.py35
-rw-r--r--release/scripts/startup/bl_ui/properties_animviz.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_data_camera.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py21
-rw-r--r--release/scripts/startup/bl_ui/properties_data_empty.py9
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py21
-rw-r--r--release/scripts/startup/bl_ui/properties_data_metaball.py17
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py13
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_object_constraint.py21
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py11
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py386
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py12
-rw-r--r--release/scripts/startup/bl_ui/properties_world.py6
-rw-r--r--release/scripts/startup/bl_ui/space_image.py11
-rw-r--r--release/scripts/startup/bl_ui/space_info.py6
-rw-r--r--release/scripts/startup/bl_ui/space_node.py1
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py33
-rw-r--r--release/scripts/startup/bl_ui/space_text.py61
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py121
-rw-r--r--release/scripts/startup/bl_ui/space_userpref_keymap.py24
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py119
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py31
-rw-r--r--release/scripts/startup/keyingsets_builtins.py2
41 files changed, 1671 insertions, 704 deletions
diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py
index 460330a56a1..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",
@@ -132,7 +139,7 @@ class AddTorus(bpy.types.Operator):
mesh.faces.foreach_set("vertices_raw", faces)
mesh.update()
- import add_object_utils
- add_object_utils.object_data_add(context, mesh, operator=self)
+ from bpy_extras import object_utils
+ object_utils.object_data_add(context, mesh, operator=self)
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/image.py b/release/scripts/startup/bl_operators/image.py
index 462db3a2c5e..23bafe2eaae 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." % 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()
@@ -121,7 +133,6 @@ class ProjectEdit(bpy.types.Operator):
def execute(self, context):
import os
- import subprocess
EXT = "png" # could be made an option but for now ok
@@ -143,14 +154,14 @@ class ProjectEdit(bpy.types.Operator):
filepath = os.path.basename(bpy.data.filepath)
filepath = os.path.splitext(filepath)[0]
- # filepath = bpy.path.clean_name(filepath) # fixes <memory> rubbish, needs checking
+ # fixes <memory> rubbish, needs checking
+ # filepath = bpy.path.clean_name(filepath)
- 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
@@ -164,7 +175,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 44d81ba53df..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
@@ -36,6 +36,7 @@ class MeshSelectInteriorFaces(bpy.types.Operator):
return (ob and ob.type == 'MESH')
def execute(self, context):
+ from bpy_extras import mesh_utils
ob = context.active_object
context.tool_settings.mesh_select_mode = False, False, True
is_editmode = (ob.mode == 'EDIT')
@@ -47,7 +48,7 @@ class MeshSelectInteriorFaces(bpy.types.Operator):
face_list = mesh.faces[:]
face_edge_keys = [face.edge_keys for face in face_list]
- edge_face_count = mesh.edge_face_count_dict
+ edge_face_count = mesh_utils.edge_face_count_dict(mesh)
def test_interior(index):
for key in face_edge_keys[index]:
@@ -80,14 +81,12 @@ class MeshMirrorUV(bpy.types.Operator):
@classmethod
def poll(cls, context):
- ob = context.active_object
- return (ob and ob.type == 'MESH')
+ obj = context.active_object
+ return (obj and obj.type == 'MESH' and obj.data.uv_textures.active)
def execute(self, context):
DIR = (self.direction == 'NEGATIVE')
- from mathutils import Vector
-
ob = context.active_object
is_editmode = (ob.mode == 'EDIT')
if is_editmode:
@@ -112,21 +111,18 @@ 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)
if j is not None:
vmap[i] = j
- active_uv_layer = None
- for lay in mesh.uv_textures:
- if lay.active:
- active_uv_layer = lay.data
- break
-
+ 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[:]
@@ -151,7 +147,6 @@ class MeshMirrorUV(bpy.types.Operator):
if j is not None:
fmap[i] = j
- done = [False] * len(faces)
for i, j in fmap.items():
if not fuvsel[i] or not fuvsel[j]:
@@ -169,10 +164,10 @@ class MeshMirrorUV(bpy.types.Operator):
v1 = faces[j].vertices[:]
v2 = [vmap[k] for k in faces[i].vertices[:]]
- for k in range(len(uv1)):
- k_map = v1.index(v2[k])
- uv1[k].x = - (uv2[k_map].x - 0.5) + 0.5
- uv1[k].y = uv2[k_map].y
+ if len(v1) == len(v2):
+ for k in range(len(v1)):
+ k_map = v1.index(v2[k])
+ uv1[k].xy = - (uv2[k_map].x - 0.5) + 0.5, uv2[k_map].y
if is_editmode:
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
diff --git a/release/scripts/startup/bl_operators/nla.py b/release/scripts/startup/bl_operators/nla.py
index 923ca92a162..469e9015e62 100644
--- a/release/scripts/startup/bl_operators/nla.py
+++ b/release/scripts/startup/bl_operators/nla.py
@@ -16,17 +16,16 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
-def pose_info():
+def pose_frame_info(obj):
from mathutils import Matrix
info = {}
- obj = bpy.context.object
pose = obj.pose
pose_items = pose.bones.items()
@@ -51,7 +50,6 @@ def pose_info():
except:
binfo["matrix_pose_inv"] = Matrix()
- print(binfo["matrix_pose"])
info[name] = binfo
for name, pbone in pose_items:
@@ -67,45 +65,86 @@ def pose_info():
matrix = binfo_parent["matrix_pose_inv"] * matrix
rest_matrix = binfo_parent["matrix_local_inv"] * rest_matrix
- matrix = rest_matrix.inverted() * matrix
+ binfo["matrix_key"] = rest_matrix.inverted() * matrix
+
+ return info
- binfo["matrix_key"] = matrix.copy()
+def obj_frame_info(obj):
+ info = {}
+ # parent = obj.parent
+ info["matrix_key"] = obj.matrix_local.copy()
return info
-def bake(frame_start, frame_end, step=1, only_selected=False):
+def bake(frame_start,
+ frame_end, step=1,
+ only_selected=False,
+ do_pose=True,
+ do_object=True,
+ do_constraint_clear=False,
+ ):
+
scene = bpy.context.scene
obj = bpy.context.object
pose = obj.pose
+ frame_back = scene.frame_current
+
+ if pose is None:
+ do_pose = False
- info_ls = []
+ if do_pose is None and do_object is None:
+ return None
+
+ pose_info = []
+ obj_info = []
frame_range = range(frame_start, frame_end + 1, step)
- # could spped this up by applying steps here too...
+ # -------------------------------------------------------------------------
+ # Collect transformations
+
+ # could speed this up by applying steps here too...
for f in frame_range:
scene.frame_set(f)
- info = pose_info()
- info_ls.append(info)
+ if do_pose:
+ pose_info.append(pose_frame_info(obj))
+ if do_object:
+ obj_info.append(obj_frame_info(obj))
+
f += 1
+ # -------------------------------------------------------------------------
+ # Create action
+
+ # incase animation data hassnt been created
+ atd = obj.animation_data_create()
action = bpy.data.actions.new("Action")
+ atd.action = action
- bpy.context.object.animation_data.action = action
+ if do_pose:
+ pose_items = pose.bones.items()
+ else:
+ pose_items = [] # skip
- pose_items = pose.bones.items()
+ # -------------------------------------------------------------------------
+ # Apply transformations to action
- for name, pbone in pose_items:
+ # pose
+ for name, pbone in (pose_items if do_pose else ()):
if only_selected and not pbone.bone.select:
continue
+ if do_constraint_clear:
+ while pbone.constraints:
+ pbone.constraints.remove(pbone.constraints[0])
+
for f in frame_range:
- matrix = info_ls[int((f - frame_start) / step)][name]["matrix_key"]
+ matrix = pose_info[(f - frame_start) // step][name]["matrix_key"]
- #pbone.location = matrix.to_translation()
- #pbone.rotation_quaternion = matrix.to_quaternion()
+ # pbone.location = matrix.to_translation()
+ # pbone.rotation_quaternion = matrix.to_quaternion()
pbone.matrix_basis = matrix
pbone.keyframe_insert("location", -1, f, name)
@@ -121,10 +160,35 @@ def bake(frame_start, frame_end, step=1, only_selected=False):
pbone.keyframe_insert("scale", -1, f, name)
+ # object. TODO. multiple objects
+ if do_object:
+ if do_constraint_clear:
+ while obj.constraints:
+ obj.constraints.remove(obj.constraints[0])
+
+ for f in frame_range:
+ matrix = obj_info[(f - frame_start) // step]["matrix_key"]
+ obj.matrix_local = matrix
+
+ obj.keyframe_insert("location", -1, f)
+
+ rotation_mode = obj.rotation_mode
+
+ if rotation_mode == 'QUATERNION':
+ obj.keyframe_insert("rotation_quaternion", -1, f)
+ elif rotation_mode == 'AXIS_ANGLE':
+ obj.keyframe_insert("rotation_axis_angle", -1, f)
+ else: # euler, XYZ, ZXY etc
+ obj.keyframe_insert("rotation_euler", -1, f)
+
+ obj.keyframe_insert("scale", -1, f)
+
+ scene.frame_set(frame_back)
+
return action
-from bpy.props import IntProperty, BoolProperty
+from bpy.props import IntProperty, BoolProperty, EnumProperty
class BakeAction(bpy.types.Operator):
@@ -144,10 +208,31 @@ class BakeAction(bpy.types.Operator):
default=1, min=1, max=120)
only_selected = BoolProperty(name="Only Selected",
default=True)
+ clear_consraints = BoolProperty(name="Clear Constraints",
+ default=False)
+ bake_types = EnumProperty(
+ name="Bake Data",
+ options={'ENUM_FLAG'},
+ items=(('POSE', "Pose", ""),
+ ('OBJECT', "Object", ""),
+ ),
+ default={'POSE'},
+ )
def execute(self, context):
- action = bake(self.frame_start, self.frame_end, self.step, self.only_selected)
+ action = bake(self.frame_start,
+ self.frame_end,
+ self.step,
+ self.only_selected,
+ 'POSE' in self.bake_types,
+ 'OBJECT' in self.bake_types,
+ self.clear_consraints,
+ )
+
+ if action is None:
+ self.report({'INFO'}, "Nothing to bake")
+ return {'CANCELLED'}
# basic cleanup, could move elsewhere
for fcu in action.fcurves:
diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py
index 0342a14a1b2..627a1530fe1 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
@@ -28,9 +28,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):
@@ -39,22 +52,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'}
@@ -93,19 +121,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):
@@ -163,7 +197,12 @@ 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):
@@ -215,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)
@@ -224,23 +264,37 @@ 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):
@@ -272,13 +326,16 @@ class ShapeTransfer(bpy.types.Operator):
orig_shape_coords = me_cos(ob_act.active_shape_key.data)
orig_normals = me_nos(me.vertices)
- # orig_coords = me_cos(me.vertices) # the actual mverts location isnt as relyable as the base shape :S
+ # the actual mverts location isnt as relyable as the base shape :S
+ # orig_coords = me_cos(me.vertices)
orig_coords = me_cos(me.shape_keys.key_blocks[0].data)
for ob_other in objects:
me_other = ob_other.data
if len(me_other.vertices) != len(me.vertices):
- self.report({'WARNING'}, "Skipping '%s', vertex count differs" % ob_other.name)
+ self.report({'WARNING'},
+ ("Skipping '%s', "
+ "vertex count differs") % ob_other.name)
continue
target_normals = me_nos(me_other.vertices)
@@ -290,53 +347,90 @@ class ShapeTransfer(bpy.types.Operator):
ob_add_shape(ob_other, orig_key_name)
# editing the final coords, only list that stores wrapped coords
- target_shape_coords = [v.co for v in ob_other.active_shape_key.data]
+ target_shape_coords = [v.co for v in
+ ob_other.active_shape_key.data]
median_coords = [[] for i in range(len(me.vertices))]
# Method 1, edge
if mode == 'OFFSET':
for i, vert_cos in enumerate(median_coords):
- vert_cos.append(target_coords[i] + (orig_shape_coords[i] - orig_coords[i]))
+ vert_cos.append(target_coords[i] +
+ (orig_shape_coords[i] - orig_coords[i]))
elif mode == 'RELATIVE_FACE':
for face in me.faces:
i1, i2, i3, i4 = face.vertices_raw
if i4 != 0:
pt = barycentric_transform(orig_shape_coords[i1],
- orig_coords[i4], orig_coords[i1], orig_coords[i2],
- target_coords[i4], target_coords[i1], target_coords[i2])
+ orig_coords[i4],
+ orig_coords[i1],
+ orig_coords[i2],
+ target_coords[i4],
+ target_coords[i1],
+ target_coords[i2],
+ )
median_coords[i1].append(pt)
pt = barycentric_transform(orig_shape_coords[i2],
- orig_coords[i1], orig_coords[i2], orig_coords[i3],
- target_coords[i1], target_coords[i2], target_coords[i3])
+ orig_coords[i1],
+ orig_coords[i2],
+ orig_coords[i3],
+ target_coords[i1],
+ target_coords[i2],
+ target_coords[i3],
+ )
median_coords[i2].append(pt)
pt = barycentric_transform(orig_shape_coords[i3],
- orig_coords[i2], orig_coords[i3], orig_coords[i4],
- target_coords[i2], target_coords[i3], target_coords[i4])
+ orig_coords[i2],
+ orig_coords[i3],
+ orig_coords[i4],
+ target_coords[i2],
+ target_coords[i3],
+ target_coords[i4],
+ )
median_coords[i3].append(pt)
pt = barycentric_transform(orig_shape_coords[i4],
- orig_coords[i3], orig_coords[i4], orig_coords[i1],
- target_coords[i3], target_coords[i4], target_coords[i1])
+ orig_coords[i3],
+ orig_coords[i4],
+ orig_coords[i1],
+ target_coords[i3],
+ target_coords[i4],
+ target_coords[i1],
+ )
median_coords[i4].append(pt)
else:
pt = barycentric_transform(orig_shape_coords[i1],
- orig_coords[i3], orig_coords[i1], orig_coords[i2],
- target_coords[i3], target_coords[i1], target_coords[i2])
+ orig_coords[i3],
+ orig_coords[i1],
+ orig_coords[i2],
+ target_coords[i3],
+ target_coords[i1],
+ target_coords[i2],
+ )
median_coords[i1].append(pt)
pt = barycentric_transform(orig_shape_coords[i2],
- orig_coords[i1], orig_coords[i2], orig_coords[i3],
- target_coords[i1], target_coords[i2], target_coords[i3])
+ orig_coords[i1],
+ orig_coords[i2],
+ orig_coords[i3],
+ target_coords[i1],
+ target_coords[i2],
+ target_coords[i3],
+ )
median_coords[i2].append(pt)
pt = barycentric_transform(orig_shape_coords[i3],
- orig_coords[i2], orig_coords[i3], orig_coords[i1],
- target_coords[i2], target_coords[i3], target_coords[i1])
+ orig_coords[i2],
+ orig_coords[i3],
+ orig_coords[i1],
+ target_coords[i2],
+ target_coords[i3],
+ target_coords[i1],
+ )
median_coords[i3].append(pt)
elif mode == 'RELATIVE_EDGE':
@@ -374,7 +468,8 @@ class ShapeTransfer(bpy.types.Operator):
if use_clamp:
# clamp to the same movement as the original
# breaks copy between different scaled meshes.
- len_from = (orig_shape_coords[i] - orig_coords[i]).length
+ len_from = (orig_shape_coords[i] -
+ orig_coords[i]).length
ofs = co - target_coords[i]
ofs.length = len_from
co = target_coords[i] + ofs
@@ -395,7 +490,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]
@@ -429,11 +527,14 @@ class JoinUVs(bpy.types.Operator):
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
if not mesh.uv_textures:
- self.report({'WARNING'}, "Object: %s, Mesh: '%s' has no UVs\n" % (obj.name, mesh.name))
+ self.report({'WARNING'},
+ "Object: %s, Mesh: '%s' has no UVs"
+ % (obj.name, mesh.name))
else:
len_faces = len(mesh.faces)
- uv_array = array.array('f', [0.0] * 8) * len_faces # seems to be the fastest way to create an array
+ # seems to be the fastest way to create an array
+ uv_array = array.array('f', [0.0] * 8) * len_faces
mesh.uv_textures.active.data.foreach_get("uv_raw", uv_array)
objects = context.selected_editable_objects[:]
@@ -450,11 +551,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)
@@ -482,14 +590,18 @@ class MakeDupliFace(bpy.types.Operator):
SCALE_FAC = 0.01
offset = 0.5 * SCALE_FAC
- base_tri = Vector((-offset, -offset, 0.0)), Vector((offset, -offset, 0.0)), Vector((offset, offset, 0.0)), Vector((-offset, offset, 0.0))
+ base_tri = (Vector((-offset, -offset, 0.0)),
+ Vector((+offset, -offset, 0.0)),
+ Vector((+offset, +offset, 0.0)),
+ Vector((-offset, +offset, 0.0)),
+ )
def matrix_to_quat(matrix):
# scale = matrix.median_scale
trans = matrix.to_translation()
rot = matrix.to_3x3() # also contains scale
- return [(b * rot) + trans for b in base_tri]
+ return [(rot * b) + trans for b in base_tri]
scene = bpy.context.scene
linked = {}
for obj in bpy.context.selected_objects:
@@ -498,7 +610,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")
@@ -535,7 +650,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 644f30a4745..7fd769c40c9 100644
--- a/release/scripts/startup/bl_operators/object_align.py
+++ b/release/scripts/startup/bl_operators/object_align.py
@@ -16,106 +16,212 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
from mathutils import Vector
-def align_objects(align_x, align_y, align_z, align_mode, relative_to):
+def GlobalBB_LQ(bb_world):
+
+ # 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:
+ matrix_world = obj.matrix_world.copy()
+ bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box]
- loc_world = obj.location
- bb_world = [Vector(v[:]) * obj.matrix_world for v in obj.bound_box]
+ if bb_quality:
+ GBB = GlobalBB_HQ(obj)
+ else:
+ GBB = GlobalBB_LQ(bb_world)
- Left_Up_Front = bb_world[1]
- Right_Down_Back = bb_world[7]
+ 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
@@ -230,7 +336,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):
@@ -239,6 +345,13 @@ 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", ""),
@@ -271,7 +384,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 21640fa3ee6..ef10bfd737d 100644
--- a/release/scripts/startup/bl_operators/object_quick_effects.py
+++ b/release/scripts/startup/bl_operators/object_quick_effects.py
@@ -16,16 +16,38 @@
#
# ##### 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,
+ )
+
+
+def object_ensure_material(obj, mat_name):
+ """ Use an existing material or add a new one.
+ """
+ mat = mat_slot = None
+ for mat_slot in obj.material_slots:
+ mat = mat_slot.material
+ if mat:
+ break
+ if mat is None:
+ mat = bpy.data.materials.new(mat_name)
+ if mat_slot:
+ mat_slot.material = mat
+ else:
+ obj.data.materials.append(mat)
+ return mat
-class MakeFur(bpy.types.Operator):
- bl_idname = "object.make_fur"
- bl_label = "Make Fur"
+class QuickFur(bpy.types.Operator):
+ bl_idname = "object.quick_fur"
+ bl_label = "Quick Fur"
bl_options = {'REGISTER', 'UNDO'}
density = EnumProperty(items=(
@@ -44,7 +66,8 @@ class MakeFur(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.")
@@ -75,14 +98,164 @@ class MakeFur(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'}
+class QuickExplode(bpy.types.Operator):
+ bl_idname = "object.quick_explode"
+ bl_label = "Quick Explode"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ style = EnumProperty(items=(
+ ('EXPLODE', "Explode", ""),
+ ('BLEND', "Blend", "")),
+ name="Explode Style",
+ description="",
+ default='EXPLODE')
+
+ amount = IntProperty(name="Amount of pieces",
+ default=100, min=2, max=10000, soft_min=2, soft_max=10000)
+
+ frame_duration = IntProperty(name="Duration",
+ default=50, min=1, max=300000, soft_min=1, soft_max=10000)
+
+ frame_start = IntProperty(name="Start Frame",
+ default=1, min=1, max=300000, soft_min=1, soft_max=10000)
+
+ frame_end = IntProperty(name="End Frame",
+ default=10, min=1, max=300000, soft_min=1, soft_max=10000)
+
+ velocity = FloatProperty(name="Outwards Velocity",
+ default=1, min=0, max=300000, soft_min=0, soft_max=10)
+
+ fade = BoolProperty(name="Fade",
+ description="Fade the pieces over time.",
+ default=True)
+
+ def execute(self, context):
+ fake_context = bpy.context.copy()
+ obj_act = context.active_object
+
+ if obj_act is None or obj_act.type != 'MESH':
+ self.report({'ERROR'}, "Active object is not a mesh")
+ return {'CANCELLED'}
+
+ mesh_objects = [obj for obj in context.selected_objects
+ if obj.type == 'MESH' and obj != obj_act]
+ mesh_objects.insert(0, obj_act)
+
+ if self.style == 'BLEND' and len(mesh_objects) != 2:
+ self.report({'ERROR'}, "Select two mesh objects")
+ return {'CANCELLED'}
+ elif not mesh_objects:
+ self.report({'ERROR'}, "Select at least one mesh object")
+ return {'CANCELLED'}
+
+ for obj in mesh_objects:
+ if obj.particle_systems:
+ self.report({'ERROR'},
+ "Object %r already has a "
+ "particle system" % obj.name)
+
+ return {'CANCELLED'}
+
+ if self.fade:
+ tex = bpy.data.textures.new("Explode fade", 'BLEND')
+ tex.use_color_ramp = True
+
+ if self.style == 'BLEND':
+ tex.color_ramp.elements[0].position = 0.333
+ tex.color_ramp.elements[1].position = 0.666
+
+ tex.color_ramp.elements[0].color[3] = 1.0
+ tex.color_ramp.elements[1].color[3] = 0.0
+
+ if self.style == 'BLEND':
+ from_obj = mesh_objects[1]
+ to_obj = mesh_objects[0]
+
+ for obj in mesh_objects:
+ fake_context["object"] = obj
+ bpy.ops.object.particle_system_add(fake_context)
+
+ settings = obj.particle_systems[-1].settings
+ settings.count = self.amount
+ settings.frame_start = self.frame_start
+ settings.frame_end = self.frame_end - self.frame_duration
+ settings.lifetime = self.frame_duration
+ settings.normal_factor = self.velocity
+ settings.render_type = 'NONE'
+
+ explode = obj.modifiers.new(name='Explode', type='EXPLODE')
+ explode.use_edge_cut = True
+
+ if self.fade:
+ explode.show_dead = False
+ uv = obj.data.uv_textures.new("Explode fade")
+ explode.particle_uv = uv.name
+
+ mat = object_ensure_material(obj, "Explode Fade")
+
+ mat.use_transparency = True
+ mat.use_transparent_shadows = True
+ mat.alpha = 0.0
+ mat.specular_alpha = 0.0
+
+ tex_slot = mat.texture_slots.add()
+
+ tex_slot.texture = tex
+ tex_slot.texture_coords = 'UV'
+ tex_slot.uv_layer = uv.name
+
+ tex_slot.use_map_alpha = True
+
+ if self.style == 'BLEND':
+ if obj == to_obj:
+ tex_slot.alpha_factor = -1.0
+ elem = tex.color_ramp.elements[1]
+ elem.color = mat.diffuse_color
+ else:
+ elem = tex.color_ramp.elements[0]
+ elem.color = mat.diffuse_color
+ else:
+ tex_slot.use_map_color_diffuse = False
+
+ if self.style == 'BLEND':
+ settings.physics_type = 'KEYED'
+ settings.use_emit_random = False
+ settings.rotation_mode = 'NOR'
+
+ psys = obj.particle_systems[-1]
+
+ fake_context["particle_system"] = obj.particle_systems[-1]
+ bpy.ops.particle.new_target(fake_context)
+ bpy.ops.particle.new_target(fake_context)
+
+ if obj == from_obj:
+ psys.targets[1].object = to_obj
+ else:
+ psys.targets[0].object = from_obj
+ settings.normal_factor = -self.velocity
+ explode.show_unborn = False
+ explode.show_dead = True
+ else:
+ settings.factor_random = self.velocity
+ settings.angular_velocity_factor = self.velocity / 10.0
+
+ return {'FINISHED'}
+
+ def invoke(self, context, event):
+ self.frame_start = context.scene.frame_current
+ self.frame_end = self.frame_start + self.frame_duration
+ return self.execute(context)
+
+
def obj_bb_minmax(obj, min_co, max_co):
for i in range(0, 8):
- bb_vec = Vector((obj.bound_box[i][0], obj.bound_box[i][1], obj.bound_box[i][2])) * 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])
@@ -92,28 +265,33 @@ def obj_bb_minmax(obj, min_co, max_co):
max_co[2] = max(bb_vec[2], max_co[2])
-class MakeSmoke(bpy.types.Operator):
- bl_idname = "object.make_smoke"
- bl_label = "Make Smoke"
+class QuickSmoke(bpy.types.Operator):
+ bl_idname = "object.quick_smoke"
+ 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']
- min_co = Vector((100000, 100000, 100000))
- max_co = Vector((-100000, -100000, -100000))
+ 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
if not mesh_objects:
self.report({'ERROR'}, "Select at least one mesh object.")
@@ -171,21 +349,25 @@ class MakeSmoke(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
@@ -201,33 +383,43 @@ class MakeSmoke(bpy.types.Operator):
return {'FINISHED'}
-class MakeFluid(bpy.types.Operator):
- bl_idname = "object.make_fluid"
- bl_label = "Make Fluid"
+class QuickFluid(bpy.types.Operator):
+ bl_idname = "object.quick_fluid"
+ 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))
@@ -240,7 +432,8 @@ class MakeFluid(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
@@ -264,10 +457,14 @@ class MakeFluid(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 9dc5086086f..b94c4f06cd3 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
@@ -93,40 +93,69 @@ 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 493c51ad237..fbcc327c3bd 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
@@ -30,8 +30,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
@@ -54,7 +61,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")
@@ -95,7 +105,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'}
@@ -133,8 +145,15 @@ class ExecutePreset(bpy.types.Operator):
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="")
+ 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
@@ -182,7 +201,10 @@ class AddPresetSSS(AddPresetBase, bpy.types.Operator):
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 = [
@@ -306,7 +328,11 @@ class AddPresetOperator(AddPresetBase, bpy.types.Operator):
bl_label = "Operator Preset"
preset_menu = "WM_MT_operator_presets"
- 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 = [
@@ -315,19 +341,22 @@ class AddPresetOperator(AddPresetBase, bpy.types.Operator):
@property
def preset_subdir(self):
- return __class__.operator_path(self.operator)
+ return AddPresetOperator.operator_path(self.operator)
@property
def preset_values(self):
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) 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
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 64af25e7b0f..a38d817d738 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
@@ -46,8 +42,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
@@ -60,6 +58,9 @@ def guess_player_path(preset):
elif preset == 'MPLAYER':
player_path = "mplayer"
+ else:
+ player_path = ""
+
return player_path
@@ -78,14 +79,14 @@ class PlayRenderedAnim(bpy.types.Operator):
preset = prefs.filepaths.animation_player_preset
player_path = prefs.filepaths.animation_player
- file_path = bpy.path.abspath(rd.filepath)
+ # file_path = bpy.path.abspath(rd.filepath) # UNUSED
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)
@@ -95,11 +96,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)
@@ -109,10 +110,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)]
@@ -125,18 +151,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_follow_active.py b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
index ad5ec15ff80..43ca9af59ba 100644
--- a/release/scripts/startup/bl_operators/uvcalc_follow_active.py
+++ b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
@@ -25,6 +25,8 @@ import bpy
def extend(obj, operator, EXTEND_MODE):
+ from bpy_extras import mesh_utils
+
me = obj.data
me_verts = me.vertices
# script will fail without UVs
@@ -40,7 +42,6 @@ def extend(obj, operator, EXTEND_MODE):
edge_average_lengths = {}
OTHER_INDEX = 2, 3, 0, 1
- FAST_INDICIES = 0, 2, 1, 3 # order is faster
def extend_uvs(face_source, face_target, edge_key):
'''
@@ -170,7 +171,7 @@ def extend(obj, operator, EXTEND_MODE):
edge_faces[edkey] = [i]
if EXTEND_MODE == 'LENGTH':
- edge_loops = me.edge_loops_from_faces(face_sel, [ed.key for ed in me.edges if ed.use_seam])
+ edge_loops = mesh_utils.edge_loops_from_faces(me, face_sel, [ed.key for ed in me.edges if ed.use_seam])
me_verts = me.vertices
for loop in edge_loops:
looplen = [0.0]
diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
index 3893612437a..9ae0cd0ddf9 100644
--- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py
+++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
@@ -406,7 +406,7 @@ def lightmap_uvpack(meshes,
ok = False
# Tall boxes in groups of 2
- for d, boxes in odd_dict.items():
+ for d, boxes in list(odd_dict.items()):
if d[1] < max_int_dimension:
#\boxes.sort(key = lambda a: len(a.children))
while len(boxes) >= 2:
@@ -427,7 +427,7 @@ def lightmap_uvpack(meshes,
odd_dict.setdefault((w, h), []).append(pf_parent)
# Even boxes in groups of 4
- for d, boxes in even_dict.items():
+ for d, boxes in list(even_dict.items()):
if d < max_int_dimension:
boxes.sort(key=lambda a: len(a.children))
@@ -444,7 +444,7 @@ def lightmap_uvpack(meshes,
del even_dict
del odd_dict
- orig = len(pretty_faces)
+ # orig = len(pretty_faces)
pretty_faces = [pf for pf in pretty_faces if not pf.has_parent]
@@ -489,7 +489,10 @@ def lightmap_uvpack(meshes,
if PREF_APPLY_IMAGE:
if not PREF_PACK_IN_ONE:
- image = Image.New("lightmap", PREF_IMG_PX_SIZE, PREF_IMG_PX_SIZE, 24)
+ image = bpy.data.images.new(name="lightmap",
+ width=PREF_IMG_PX_SIZE,
+ height=PREF_IMG_PX_SIZE,
+ )
for f in face_sel:
# f.image = image
@@ -530,7 +533,7 @@ def unwrap(operator, context, **kwargs):
return {'FINISHED'}
-from bpy.props import BoolProperty, FloatProperty, IntProperty, EnumProperty
+from bpy.props import BoolProperty, FloatProperty, IntProperty
class LightMapPack(bpy.types.Operator):
diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
index 4f5b1d8b233..851f33bde11 100644
--- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py
+++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# TODO <pep8 compliant>
from mathutils import Matrix, Vector, geometry
import bpy
@@ -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
@@ -746,13 +746,9 @@ def packIslands(islandList):
uv.y= (uv.y+yoffset) * yfactor
-
def VectoQuat(vec):
vec = vec.normalized()
- if abs(vec.x) > 0.5:
- return vec.to_track_quat('Z', 'X')
- else:
- return vec.to_track_quat('Z', 'Y')
+ return vec.to_track_quat('Z', 'X' if abs(vec.x) > 0.5 else 'Y').inverted()
class thickface(object):
@@ -791,7 +787,11 @@ def main_consts():
global ob
ob = None
-def main(context, island_margin, projection_limit):
+def main(context,
+ island_margin,
+ projection_limit,
+ user_area_weight,
+ ):
global USER_FILL_HOLES
global USER_FILL_HOLES_QUALITY
global USER_STRETCH_ASPECT
@@ -812,21 +812,25 @@ def main(context, island_margin, projection_limit):
global RotMatStepRotation
main_consts()
-#XXX objects= bpy.data.scenes.active.objects
- objects = context.selected_editable_objects
-
+ # TODO, all selected meshes
+ '''
+ # objects = context.selected_editable_objects
+ objects = []
# we can will tag them later.
obList = [ob for ob in objects if ob.type == 'MESH']
# Face select object may not be selected.
-#XXX ob = objects.active
- ob= objects[0]
+ ob = context.active_object
if ob and (not ob.select) and ob.type == 'MESH':
# Add to the list
obList =[ob]
del objects
+ '''
+
+ # quick workaround
+ obList = [ob for ob in [context.active_object] if ob and ob.type == 'MESH']
if not obList:
raise('error, no selected mesh objects')
@@ -840,7 +844,6 @@ def main(context, island_margin, projection_limit):
USER_FILL_HOLES = (0)
USER_FILL_HOLES_QUALITY = (50) # Only for hole filling.
USER_VIEW_INIT = (0) # Only for hole filling.
- USER_AREA_WEIGHT = (1) # Only for hole filling.
# Reuse variable
if len(obList) == 1:
@@ -966,12 +969,15 @@ def main(context, island_margin, projection_limit):
# Add the average of all these faces normals as a projectionVec
averageVec = Vector((0.0, 0.0, 0.0))
- if USER_AREA_WEIGHT:
+ if user_area_weight == 0.0:
for fprop in newProjectMeshFaces:
- averageVec += (fprop.no * fprop.area)
+ averageVec += fprop.no
+ elif user_area_weight == 1.0:
+ for fprop in newProjectMeshFaces:
+ averageVec += fprop.no * fprop.area
else:
for fprop in newProjectMeshFaces:
- averageVec += fprop.no
+ averageVec += fprop.no * ((fprop.area * user_area_weight) + (1.0 - user_area_weight))
if averageVec.x != 0 or averageVec.y != 0 or averageVec.z != 0: # Avoid NAN
projectVecs.append(averageVec.normalized())
@@ -1058,7 +1064,7 @@ def main(context, island_margin, projection_limit):
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)[:2]
+ f_uv[j][:] = (MatQuat * v.co).xy
if USER_SHARE_SPACE:
@@ -1094,12 +1100,8 @@ def main(context, island_margin, projection_limit):
"""
pup_block = [\
'Projection',\
-* ('Angle Limit:', USER_PROJECTION_LIMIT, 1, 89, ''),\
('Selected Faces Only', USER_ONLY_SELECTED_FACES, 'Use only selected faces from all selected meshes.'),\
('Init from view', USER_VIEW_INIT, 'The first projection will be from the view vector.'),\
- ('Area Weight', USER_AREA_WEIGHT, 'Weight projections vector by face area.'),\
- '',\
- '',\
'',\
'UV Layout',\
('Share Tex Space', USER_SHARE_SPACE, 'Objects Share texture space, map all objects into 1 uvmap.'),\
@@ -1121,11 +1123,15 @@ class SmartProject(bpy.types.Operator):
bl_options = {'REGISTER', 'UNDO'}
angle_limit = FloatProperty(name="Angle Limit",
- description="lower for more projection groups, higher for less distortion.",
+ description="lower for more projection groups, higher for less distortion",
default=66.0, min=1.0, max=89.0)
island_margin = FloatProperty(name="Island Margin",
- description="Margin to reduce bleed from adjacent islands.",
+ description="Margin to reduce bleed from adjacent islands",
+ default=0.0, min=0.0, max=1.0)
+
+ user_area_weight = FloatProperty(name="Area Weight",
+ description="Weight projections vector by faces with larger areas",
default=0.0, min=0.0, max=1.0)
@classmethod
@@ -1133,7 +1139,11 @@ class SmartProject(bpy.types.Operator):
return context.active_object != None
def execute(self, context):
- main(context, self.island_margin, self.angle_limit)
+ main(context,
+ self.island_margin,
+ self.angle_limit,
+ self.user_area_weight,
+ )
return {'FINISHED'}
def invoke(self, context, event):
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index 53c8d562297..af33e45668c 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -19,7 +19,9 @@
# <pep8 compliant>
import bpy
-from bpy.props import StringProperty, BoolProperty, IntProperty, FloatProperty
+from bpy.props import StringProperty, BoolProperty, IntProperty, \
+ FloatProperty, EnumProperty
+
from rna_prop_ui import rna_idprop_ui_prop_get, rna_idprop_ui_prop_clear
@@ -106,7 +108,7 @@ class WM_OT_context_set_boolean(bpy.types.Operator):
'''Set a context value.'''
bl_idname = "wm.context_set_boolean"
bl_label = "Context Set Boolean"
- bl_options = {'UNDO'}
+ bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
value = BoolProperty(name="Value",
@@ -119,7 +121,7 @@ class WM_OT_context_set_int(bpy.types.Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_int"
bl_label = "Context Set"
- bl_options = {'UNDO'}
+ bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
value = IntProperty(name="Value", description="Assign value", default=0)
@@ -132,7 +134,7 @@ class WM_OT_context_scale_int(bpy.types.Operator):
'''Scale an int context value.'''
bl_idname = "wm.context_scale_int"
bl_label = "Context Set"
- bl_options = {'UNDO'}
+ bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
value = FloatProperty(name="Value", description="Assign value", default=1.0)
@@ -168,7 +170,7 @@ class WM_OT_context_set_float(bpy.types.Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_float"
bl_label = "Context Set Float"
- bl_options = {'UNDO'}
+ bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
value = FloatProperty(name="Value",
@@ -182,7 +184,7 @@ class WM_OT_context_set_string(bpy.types.Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_string"
bl_label = "Context Set String"
- bl_options = {'UNDO'}
+ bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
value = StringProperty(name="Value",
@@ -195,7 +197,7 @@ class WM_OT_context_set_enum(bpy.types.Operator):
'''Set a context value.'''
bl_idname = "wm.context_set_enum"
bl_label = "Context Set Enum"
- bl_options = {'UNDO'}
+ bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
value = StringProperty(name="Value",
@@ -209,7 +211,7 @@ class WM_OT_context_set_value(bpy.types.Operator):
'''Set a context value.'''
bl_idname = "wm.context_set_value"
bl_label = "Context Set Value"
- bl_options = {'UNDO'}
+ bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
value = StringProperty(name="Value",
@@ -227,7 +229,7 @@ class WM_OT_context_toggle(bpy.types.Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_toggle"
bl_label = "Context Toggle"
- bl_options = {'UNDO'}
+ bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
@@ -246,7 +248,7 @@ class WM_OT_context_toggle_enum(bpy.types.Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_toggle_enum"
bl_label = "Context Toggle Values"
- bl_options = {'UNDO'}
+ bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
value_1 = StringProperty(name="Value", \
@@ -273,7 +275,7 @@ class WM_OT_context_cycle_int(bpy.types.Operator):
'''vertex keys, groups' etc.'''
bl_idname = "wm.context_cycle_int"
bl_label = "Context Int Cycle"
- bl_options = {'UNDO'}
+ bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
reverse = rna_reverse_prop
@@ -307,7 +309,7 @@ class WM_OT_context_cycle_enum(bpy.types.Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_cycle_enum"
bl_label = "Context Enum Cycle"
- bl_options = {'UNDO'}
+ bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
reverse = rna_reverse_prop
@@ -360,7 +362,7 @@ class WM_OT_context_cycle_array(bpy.types.Operator):
Useful for cycling the active mesh edit mode.'''
bl_idname = "wm.context_cycle_array"
bl_label = "Context Array Cycle"
- bl_options = {'UNDO'}
+ bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
reverse = rna_reverse_prop
@@ -406,7 +408,7 @@ class WM_MT_context_menu_enum(bpy.types.Menu):
class WM_OT_context_menu_enum(bpy.types.Operator):
bl_idname = "wm.context_menu_enum"
bl_label = "Context Enum Menu"
- bl_options = {'UNDO'}
+ bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
def execute(self, context):
@@ -420,7 +422,7 @@ class WM_OT_context_set_id(bpy.types.Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_set_id"
bl_label = "Set Library ID"
- bl_options = {'UNDO'}
+ bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
value = StringProperty(name="Value",
@@ -457,14 +459,76 @@ doc_id = StringProperty(name="Doc ID",
doc_new = StringProperty(name="Edit Description",
description="", maxlen=1024, default="")
+data_path_iter = StringProperty(
+ description="The data path relative to the context, must point to an iterable.")
+
+data_path_item = StringProperty(
+ description="The data path from each iterable to the value (int or float)")
+
+
+class WM_OT_context_collection_boolean_set(bpy.types.Operator):
+ '''Set boolean values for a collection of items'''
+ bl_idname = "wm.context_collection_boolean_set"
+ bl_label = "Context Collection Boolean Set"
+ bl_options = {'UNDO', 'REGISTER', 'INTERNAL'}
+
+ data_path_iter = data_path_iter
+ data_path_item = data_path_item
+
+ type = EnumProperty(items=(
+ ('TOGGLE', "Toggle", ""),
+ ('ENABLE', "Enable", ""),
+ ('DISABLE', "Disable", ""),
+ ),
+ name="Type")
+
+ def execute(self, context):
+ data_path_iter = self.data_path_iter
+ data_path_item = self.data_path_item
+
+ items = list(getattr(context, data_path_iter))
+ items_ok = []
+ is_set = False
+ for item in items:
+ try:
+ value_orig = eval("item." + data_path_item)
+ except:
+ continue
+
+ if value_orig == True:
+ is_set = True
+ elif value_orig == False:
+ pass
+ else:
+ self.report({'WARNING'}, "Non boolean value found: %s[ ].%s" %
+ (data_path_iter, data_path_item))
+ return {'CANCELLED'}
+
+ items_ok.append(item)
+
+ if self.type == 'ENABLE':
+ is_set = True
+ elif self.type == 'DISABLE':
+ is_set = False
+ else:
+ is_set = not is_set
+
+ exec_str = "item.%s = %s" % (data_path_item, is_set)
+ for item in items_ok:
+ exec(exec_str)
+
+ return {'FINISHED'}
+
class WM_OT_context_modal_mouse(bpy.types.Operator):
'''Adjust arbitrary values with mouse input'''
bl_idname = "wm.context_modal_mouse"
bl_label = "Context Modal Mouse"
+ bl_options = {'GRAB_POINTER', 'BLOCKING', 'INTERNAL'}
+
+ data_path_iter = data_path_iter
+ data_path_item = data_path_item
- data_path_iter = StringProperty(description="The data path relative to the context, must point to an iterable.")
- data_path_item = StringProperty(description="The data path from each iterable to the value (int or float)")
input_scale = FloatProperty(default=0.01, description="Scale the mouse movement by this value before applying the delta")
invert = BoolProperty(default=False, description="Invert the mouse input")
initial_x = IntProperty(options={'HIDDEN'})
@@ -940,6 +1004,14 @@ class WM_OT_copy_prev_settings(bpy.types.Operator):
self.report({'ERROR'}, "Source path %r exists" % path_src)
else:
shutil.copytree(path_src, path_dst)
+
+ # in 2.57 and earlier windows installers, system scripts were copied
+ # into the configuration directory, don't want to copy those
+ system_script = os.path.join(path_dst, 'scripts/modules/bpy_types.py')
+ if os.path.isfile(system_script):
+ shutil.rmtree(os.path.join(path_dst, 'scripts'))
+ shutil.rmtree(os.path.join(path_dst, 'plugins'))
+
# dont loose users work if they open the splash later.
if bpy.data.is_saved is bpy.data.is_dirty is False:
bpy.ops.wm.read_homefile()
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index 5c565fbd300..bf63c6071b9 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -85,25 +85,26 @@ def register():
from bpy.props import StringProperty, EnumProperty
WindowManager = bpy.types.WindowManager
+ def addon_filter_items(self, context):
+ import addon_utils
+
+ items = [('All', "All", ""),
+ ('Enabled', "Enabled", ""),
+ ('Disabled', "Disabled", ""),
+ ]
+
+ items_unique = set()
+
+ for mod in addon_utils.modules(space_userpref.USERPREF_PT_addons._addons_fake_modules):
+ info = addon_utils.module_bl_info(mod)
+ items_unique.add(info["category"])
+
+ items.extend([(cat, cat, "") for cat in sorted(items_unique)])
+ return items
+
WindowManager.addon_search = StringProperty(name="Search", description="Search within the selected filter")
WindowManager.addon_filter = EnumProperty(
- items=[('All', "All", ""),
- ('Enabled', "Enabled", ""),
- ('Disabled', "Disabled", ""),
- ('3D View', "3D View", ""),
- ('Add Curve', "Add Curve", ""),
- ('Add Mesh', "Add Mesh", ""),
- ('Animation', "Animation", ""),
- ('Development', "Development", ""),
- ('Game Engine', "Game Engine", ""),
- ('Import-Export', "Import-Export", ""),
- ('Mesh', "Mesh", ""),
- ('Object', "Object", ""),
- ('Render', "Render", ""),
- ('Rigging', "Rigging", ""),
- ('Text Editor', "Text Editor", ""),
- ('System', "System", "")
- ],
+ items=addon_filter_items,
name="Category",
description="Filter add-ons by category",
)
diff --git a/release/scripts/startup/bl_ui/properties_animviz.py b/release/scripts/startup/bl_ui/properties_animviz.py
index eb1bbfd2fb1..3b33a7ccc61 100644
--- a/release/scripts/startup/bl_ui/properties_animviz.py
+++ b/release/scripts/startup/bl_ui/properties_animviz.py
@@ -94,4 +94,5 @@ class OnionSkinButtonsPanel():
col.prop(arm, "show_only_ghost_selected", text="Selected Only")
if __name__ == "__main__": # only for live edit.
+ import bpy
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index 9477dc866ab..f2a3bac2373 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -299,10 +299,7 @@ class DATA_PT_onion_skinning(OnionSkinButtonsPanel): # , bpy.types.Panel): # in
return (context.object) and (context.armature)
def draw(self, context):
- layout = self.layout
-
ob = context.object
-
self.draw_settings(context, ob.pose.animation_visualisation, bones=True)
diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py
index e5076fd20d5..80cd5227fca 100644
--- a/release/scripts/startup/bl_ui/properties_data_camera.py
+++ b/release/scripts/startup/bl_ui/properties_data_camera.py
@@ -127,6 +127,7 @@ class DATA_PT_camera_display(CameraButtonsPanel, bpy.types.Panel):
col.prop(cam, "show_mist", text="Mist")
col.prop(cam, "show_title_safe", text="Title Safe")
col.prop(cam, "show_name", text="Name")
+ col.prop_menu_enum(cam, "show_guide")
col = split.column()
col.prop(cam, "draw_size", text="Size")
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index 623daffac93..3c88127c724 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -113,9 +113,24 @@ class DATA_PT_shape_curve(CurveButtonsPanel, bpy.types.Panel):
sub.prop(curve, "use_fill_back")
col.prop(curve, "use_fill_deform", text="Fill Deformed")
- col.label(text="Textures:")
- col.prop(curve, "use_uv_as_generated")
- col.prop(curve, "use_auto_texspace")
+
+class DATA_PT_curve_texture_space(CurveButtonsPanel, bpy.types.Panel):
+ bl_label = "Texture Space"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ curve = context.curve
+
+ row = layout.row()
+ row.prop(curve, "use_auto_texspace")
+ row.prop(curve, "use_uv_as_generated")
+
+ row = layout.row()
+ row.column().prop(curve, "texspace_location", text="Location")
+ row.column().prop(curve, "texspace_size", text="Size")
class DATA_PT_geometry_curve(CurveButtonsPanel, bpy.types.Panel):
diff --git a/release/scripts/startup/bl_ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py
index e46cd1270ad..42b0af7eaf5 100644
--- a/release/scripts/startup/bl_ui/properties_data_empty.py
+++ b/release/scripts/startup/bl_ui/properties_data_empty.py
@@ -39,6 +39,15 @@ class DATA_PT_empty(DataButtonsPanel, bpy.types.Panel):
ob = context.object
layout.prop(ob, "empty_draw_type", text="Display")
+
+ if ob.empty_draw_type == 'IMAGE':
+ layout.template_ID(ob, "data", open="image.open", unlink="image.unlink")
+
+ layout.prop(ob, "color", text="Transparency", index=3, slider=True)
+ row = layout.row(align=True)
+ row.prop(ob, "empty_image_offset", text="Offset X", index=0)
+ row.prop(ob, "empty_image_offset", text="Offset Y", index=1)
+
layout.prop(ob, "empty_draw_size", text="Size")
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index b1d1789fadd..618a88f0879 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -46,6 +46,8 @@ class MESH_MT_shape_key_specials(bpy.types.Menu):
layout.operator("object.shape_key_transfer", icon='COPY_ID') # icon is not ideal
layout.operator("object.join_shapes", icon='COPY_ID') # icon is not ideal
layout.operator("object.shape_key_mirror", icon='ARROW_LEFTRIGHT')
+ op = layout.operator("object.shape_key_add", icon='ZOOMIN', text="New Shape From Mix")
+ op.from_mix = True
class MeshButtonsPanel():
@@ -97,8 +99,9 @@ class DATA_PT_normals(MeshButtonsPanel, bpy.types.Panel):
split.prop(mesh, "show_double_sided")
-class DATA_PT_settings(MeshButtonsPanel, bpy.types.Panel):
- bl_label = "Settings"
+class DATA_PT_texture_space(MeshButtonsPanel, bpy.types.Panel):
+ bl_label = "Texture Space"
+ bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
def draw(self, context):
@@ -107,7 +110,13 @@ class DATA_PT_settings(MeshButtonsPanel, bpy.types.Panel):
mesh = context.mesh
layout.prop(mesh, "texture_mesh")
+
+ layout.separator()
+
layout.prop(mesh, "use_auto_texspace")
+ row = layout.row()
+ row.column().prop(mesh, "texspace_location", text="Location")
+ row.column().prop(mesh, "texspace_size", text="Size")
class DATA_PT_vertex_groups(MeshButtonsPanel, bpy.types.Panel):
@@ -193,7 +202,8 @@ class DATA_PT_shape_keys(MeshButtonsPanel, bpy.types.Panel):
col = row.column()
sub = col.column(align=True)
- sub.operator("object.shape_key_add", icon='ZOOMIN', text="")
+ op = sub.operator("object.shape_key_add", icon='ZOOMIN', text="")
+ op.from_mix = False
sub.operator("object.shape_key_remove", icon='ZOOMOUT', text="")
sub.menu("MESH_MT_shape_key_specials", icon='DOWNARROW_HLT', text="")
@@ -280,9 +290,8 @@ class DATA_PT_texface(MeshButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
- ob = context.active_object
-
- return (context.mode == 'EDIT_MESH') and ob and ob.type == 'MESH'
+ obj = context.object
+ return (context.mode == 'EDIT_MESH') and obj and obj.type == 'MESH'
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/properties_data_metaball.py b/release/scripts/startup/bl_ui/properties_data_metaball.py
index 81ba15d6f40..6dda99bc37f 100644
--- a/release/scripts/startup/bl_ui/properties_data_metaball.py
+++ b/release/scripts/startup/bl_ui/properties_data_metaball.py
@@ -72,6 +72,23 @@ class DATA_PT_metaball(DataButtonsPanel, bpy.types.Panel):
layout.prop(mball, "update_method", expand=True)
+class DATA_PT_mball_texture_space(DataButtonsPanel, bpy.types.Panel):
+ bl_label = "Texture Space"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ mball = context.meta_ball
+
+ layout.prop(mball, "use_auto_texspace")
+
+ row = layout.row()
+ row.column().prop(mball, "texspace_location", text="Location")
+ row.column().prop(mball, "texspace_size", text="Size")
+
+
class DATA_PT_metaball_element(DataButtonsPanel, bpy.types.Panel):
bl_label = "Active Element"
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 27af84dbcfb..0a4d0b60514 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -219,7 +219,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.label(text="Texture Coordinates:")
col.prop(md, "texture_coords", text="")
if md.texture_coords == 'OBJECT':
- layout.prop(md, "texture_coordinate_object", text="Object")
+ layout.prop(md, "texture_coords_object", text="Object")
elif md.texture_coords == 'UV' and ob.type == 'MESH':
layout.prop_search(md, "uv_layer", ob.data, "uv_textures")
@@ -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()
@@ -483,11 +484,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.label(text="Mode:")
col.prop(md, "wrap_method", text="")
- split = layout.split(percentage=0.25)
-
- col = split.column()
-
if md.wrap_method == 'PROJECT':
+ split = layout.split(percentage=0.25)
+
+ col = split.column()
col.label(text="Axis:")
col.prop(md, "use_project_x")
col.prop(md, "use_project_y")
@@ -499,7 +499,6 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.prop(md, "use_positive_direction")
col = split.column()
-
col.label(text="Cull Faces:")
col.prop(md, "cull_face", expand=True)
@@ -673,7 +672,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.prop(md, "texture_coords", text="")
if md.texture_coords == 'OBJECT':
- layout.prop(md, "texture_coordinate_object", text="Object")
+ layout.prop(md, "texture_coords_object", text="Object")
elif md.texture_coords == 'UV' and ob.type == 'MESH':
layout.prop_search(md, "uv_layer", ob.data, "uv_textures")
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index 52d6b5f1376..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,6 +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")
+ if simple_material(base_mat):
+ col.prop(mat, "pass_index")
class MATERIAL_PT_shadow(MaterialButtonsPanel, bpy.types.Panel):
@@ -883,7 +887,7 @@ class MATERIAL_PT_volume_lighting(VolumeButtonsPanel, bpy.types.Panel):
sub = col.column()
sub.enabled = True
sub.active = False
- sub.prop(vol, "use_light_cache")
+ sub.label("Light Cache Enabled")
col.prop(vol, "cache_resolution")
sub = col.column(align=True)
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index ae66642e903..cdbcf2cf533 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -34,7 +34,6 @@ class OBJECT_PT_context_object(ObjectButtonsPanel, bpy.types.Panel):
def draw(self, context):
layout = self.layout
space = context.space_data
- ob = context.object
if space.use_pin_id:
layout.template_ID(space, "pin_id")
diff --git a/release/scripts/startup/bl_ui/properties_object_constraint.py b/release/scripts/startup/bl_ui/properties_object_constraint.py
index 59f9ca16d1a..5f79dd3127a 100644
--- a/release/scripts/startup/bl_ui/properties_object_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_object_constraint.py
@@ -651,6 +651,24 @@ class ConstraintButtonsPanel():
sub.prop(con, "from_min_z", text="Min")
sub.prop(con, "from_max_z", text="Max")
+ col = layout.column()
+ row = col.row()
+ row.label(text="Source to Destination Mapping:")
+
+ # note: chr(187) is the ASCII arrow ( >> ). Blender Text Editor can't
+ # open it. Thus we are using the hardcoded value instead.
+ row = col.row()
+ row.prop(con, "map_to_x_from", expand=False, text="")
+ row.label(text=" %s X" % chr(187))
+
+ row = col.row()
+ row.prop(con, "map_to_y_from", expand=False, text="")
+ row.label(text=" %s Y" % chr(187))
+
+ row = col.row()
+ row.prop(con, "map_to_z_from", expand=False, text="")
+ row.label(text=" %s Z" % chr(187))
+
split = layout.split()
col = split.column()
@@ -661,7 +679,6 @@ class ConstraintButtonsPanel():
col = split.column()
col.label(text="X:")
- col.row().prop(con, "map_to_x_from", expand=True)
sub = col.column(align=True)
sub.prop(con, "to_min_x", text="Min")
@@ -669,7 +686,6 @@ class ConstraintButtonsPanel():
col = split.column()
col.label(text="Y:")
- col.row().prop(con, "map_to_y_from", expand=True)
sub = col.column(align=True)
sub.prop(con, "to_min_y", text="Min")
@@ -677,7 +693,6 @@ class ConstraintButtonsPanel():
col = split.column()
col.label(text="Z:")
- col.row().prop(con, "map_to_z_from", expand=True)
sub = col.column(align=True)
sub.prop(con, "to_min_z", text="Min")
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index 5037308c6fd..4c92296dacd 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -168,10 +168,8 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, bpy.types.Panel):
if psys != None and psys.is_edited:
if psys.is_global_hair:
layout.operator("particle.connect_hair")
- layout.label(text="Hair is disconnected.")
else:
layout.operator("particle.disconnect_hair")
- layout.label(text="")
elif psys != None and part.type == 'REACTOR':
split.enabled = particle_panel_enabled(context, psys)
split.prop(psys, "reactor_target_object")
@@ -881,6 +879,15 @@ class PARTICLE_PT_render(ParticleButtonsPanel, bpy.types.Panel):
col = row.column()
col.prop(part, "billboard_offset")
+ row = layout.row()
+ col = row.column()
+ col.prop(part, "billboard_size", text="Scale")
+ if part.billboard_align == 'VEL':
+ col = row.column(align=True)
+ col.label("Velocity Scale:")
+ col.prop(part, "billboard_velocity_head", text="Head")
+ col.prop(part, "billboard_velocity_tail", text="Tail")
+
if psys:
col = layout.column()
col.prop_search(psys, "billboard_normal_uv", ob.data, "uv_textures")
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 5da89d0090a..c7e3a9e7220 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -257,6 +257,7 @@ class PHYSICS_PT_domain_boundary(PhysicButtonsPanel, bpy.types.Panel):
col.prop(fluid, "slip_type", text="")
if fluid.slip_type == 'PARTIALSLIP':
col.prop(fluid, "partial_slip_factor", slider=True, text="Amount")
+ col.prop(fluid, "surface_noobs")
col = split.column()
col.label(text="Surface:")
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index a3b10702fa7..6d36db29a6c 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -141,6 +141,7 @@ class RENDER_PT_layers(RenderButtonsPanel, bpy.types.Panel):
col.prop(rl, "use_pass_uv")
col.prop(rl, "use_pass_mist")
col.prop(rl, "use_pass_object_index")
+ col.prop(rl, "use_pass_material_index")
col.prop(rl, "use_pass_color")
col = split.column()
@@ -172,8 +173,130 @@ class RENDER_PT_layers(RenderButtonsPanel, bpy.types.Panel):
row.prop(rl, "exclude_refraction", text="")
+class RENDER_PT_dimensions(RenderButtonsPanel, bpy.types.Panel):
+ bl_label = "Dimensions"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ rd = scene.render
+
+ row = layout.row(align=True)
+ row.menu("RENDER_MT_presets", text=bpy.types.RENDER_MT_presets.bl_label)
+ row.operator("render.preset_add", text="", icon="ZOOMIN")
+ row.operator("render.preset_add", text="", icon="ZOOMOUT").remove_active = True
+
+ split = layout.split()
+
+ col = split.column()
+ sub = col.column(align=True)
+ sub.label(text="Resolution:")
+ sub.prop(rd, "resolution_x", text="X")
+ sub.prop(rd, "resolution_y", text="Y")
+ sub.prop(rd, "resolution_percentage", text="")
+
+ sub.label(text="Aspect Ratio:")
+ sub.prop(rd, "pixel_aspect_x", text="X")
+ sub.prop(rd, "pixel_aspect_y", text="Y")
+
+ row = col.row()
+ row.prop(rd, "use_border", text="Border")
+ sub = row.row()
+ sub.active = rd.use_border
+ sub.prop(rd, "use_crop_to_border", text="Crop")
+
+ col = split.column()
+ sub = col.column(align=True)
+ sub.label(text="Frame Range:")
+ sub.prop(scene, "frame_start", text="Start")
+ sub.prop(scene, "frame_end", text="End")
+ sub.prop(scene, "frame_step", text="Step")
+
+ sub.label(text="Frame Rate:")
+ if rd.fps_base == 1:
+ fps_rate = round(rd.fps / rd.fps_base)
+ else:
+ fps_rate = round(rd.fps / rd.fps_base, 2)
+
+ # TODO: Change the following to iterate over existing presets
+ custom_framerate = (fps_rate not in {23.98, 24, 25, 29.97, 30, 50, 59.94, 60})
+
+ if custom_framerate == True:
+ fps_label_text = "Custom (" + str(fps_rate) + " fps)"
+ else:
+ fps_label_text = str(fps_rate) + " fps"
+
+ sub.menu("RENDER_MT_framerate_presets", text=fps_label_text)
+
+ if custom_framerate or (bpy.types.RENDER_MT_framerate_presets.bl_label == "Custom"):
+ sub.prop(rd, "fps")
+ sub.prop(rd, "fps_base", text="/")
+ subrow = sub.row(align=True)
+ subrow.label(text="Time Remapping:")
+ subrow = sub.row(align=True)
+ subrow.prop(rd, "frame_map_old", text="Old")
+ subrow.prop(rd, "frame_map_new", text="New")
+
+
+class RENDER_PT_antialiasing(RenderButtonsPanel, bpy.types.Panel):
+ bl_label = "Anti-Aliasing"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw_header(self, context):
+ rd = context.scene.render
+
+ self.layout.prop(rd, "use_antialiasing", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render
+ layout.active = rd.use_antialiasing
+
+ split = layout.split()
+
+ col = split.column()
+ col.row().prop(rd, "antialiasing_samples", expand=True)
+ sub = col.row()
+ sub.enabled = not rd.use_border
+ sub.prop(rd, "use_full_sample")
+
+ col = split.column()
+ col.prop(rd, "pixel_filter_type", text="")
+ col.prop(rd, "filter_size", text="Size")
+
+
+class RENDER_PT_motion_blur(RenderButtonsPanel, bpy.types.Panel):
+ bl_label = "Sampled Motion Blur"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ @classmethod
+ def poll(cls, context):
+ rd = context.scene.render
+ return not rd.use_full_sample and (rd.engine in cls.COMPAT_ENGINES)
+
+ def draw_header(self, context):
+ rd = context.scene.render
+
+ self.layout.prop(rd, "use_motion_blur", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render
+ layout.active = rd.use_motion_blur
+
+ row = layout.row()
+ row.prop(rd, "motion_blur_samples")
+ row.prop(rd, "motion_blur_shutter")
+
+
class RENDER_PT_shading(RenderButtonsPanel, bpy.types.Panel):
bl_label = "Shading"
+ bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
def draw(self, context):
@@ -254,8 +377,7 @@ class RENDER_PT_post_processing(RenderButtonsPanel, bpy.types.Panel):
col.prop(rd, "use_compositing")
col.prop(rd, "use_sequencer")
- col = split.column()
- col.prop(rd, "dither_intensity", text="Dither", slider=True)
+ split.prop(rd, "dither_intensity", text="Dither", slider=True)
layout.separator()
@@ -276,6 +398,51 @@ class RENDER_PT_post_processing(RenderButtonsPanel, bpy.types.Panel):
sub.prop(rd, "edge_color", text="")
+class RENDER_PT_stamp(RenderButtonsPanel, bpy.types.Panel):
+ bl_label = "Stamp"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw_header(self, context):
+ rd = context.scene.render
+
+ self.layout.prop(rd, "use_stamp", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render
+
+ layout.active = rd.use_stamp
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(rd, "use_stamp_time", text="Time")
+ col.prop(rd, "use_stamp_date", text="Date")
+ col.prop(rd, "use_stamp_render_time", text="RenderTime")
+ col.prop(rd, "use_stamp_frame", text="Frame")
+ col.prop(rd, "use_stamp_scene", text="Scene")
+ col.prop(rd, "use_stamp_camera", text="Camera")
+ col.prop(rd, "use_stamp_lens", text="Lens")
+ col.prop(rd, "use_stamp_filename", text="Filename")
+ col.prop(rd, "use_stamp_marker", text="Marker")
+ col.prop(rd, "use_stamp_sequencer_strip", text="Seq. Strip")
+
+ col = split.column()
+ col.active = rd.use_stamp
+ col.prop(rd, "stamp_foreground", slider=True)
+ col.prop(rd, "stamp_background", slider=True)
+ col.separator()
+ col.prop(rd, "stamp_font_size", text="Font Size")
+
+ row = layout.split(percentage=0.2)
+ row.prop(rd, "use_stamp_note", text="Note")
+ sub = row.row()
+ sub.active = rd.use_stamp_note
+ sub.prop(rd, "stamp_note_text", text="")
+
+
class RENDER_PT_output(RenderButtonsPanel, bpy.types.Panel):
bl_label = "Output"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -433,172 +600,6 @@ class RENDER_PT_encoding(RenderButtonsPanel, bpy.types.Panel):
split.prop(rd, "ffmpeg_audio_volume", slider=True)
-class RENDER_PT_antialiasing(RenderButtonsPanel, bpy.types.Panel):
- bl_label = "Anti-Aliasing"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw_header(self, context):
- rd = context.scene.render
-
- self.layout.prop(rd, "use_antialiasing", text="")
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render
- layout.active = rd.use_antialiasing
-
- split = layout.split()
-
- col = split.column()
- col.row().prop(rd, "antialiasing_samples", expand=True)
- sub = col.row()
- sub.enabled = not rd.use_border
- sub.prop(rd, "use_full_sample")
-
- col = split.column()
- col.prop(rd, "pixel_filter_type", text="")
- col.prop(rd, "filter_size", text="Size")
-
-
-class RENDER_PT_motion_blur(RenderButtonsPanel, bpy.types.Panel):
- bl_label = "Sampled Motion Blur"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- @classmethod
- def poll(cls, context):
- rd = context.scene.render
- return not rd.use_full_sample and (rd.engine in cls.COMPAT_ENGINES)
-
- def draw_header(self, context):
- rd = context.scene.render
-
- self.layout.prop(rd, "use_motion_blur", text="")
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render
- layout.active = rd.use_motion_blur
-
- row = layout.row()
- row.prop(rd, "motion_blur_samples")
- row.prop(rd, "motion_blur_shutter")
-
-
-class RENDER_PT_dimensions(RenderButtonsPanel, bpy.types.Panel):
- bl_label = "Dimensions"
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render
-
- row = layout.row(align=True)
- row.menu("RENDER_MT_presets", text=bpy.types.RENDER_MT_presets.bl_label)
- row.operator("render.preset_add", text="", icon="ZOOMIN")
- row.operator("render.preset_add", text="", icon="ZOOMOUT").remove_active = True
-
- split = layout.split()
-
- col = split.column()
- sub = col.column(align=True)
- sub.label(text="Resolution:")
- sub.prop(rd, "resolution_x", text="X")
- sub.prop(rd, "resolution_y", text="Y")
- sub.prop(rd, "resolution_percentage", text="")
-
- sub.label(text="Aspect Ratio:")
- sub.prop(rd, "pixel_aspect_x", text="X")
- sub.prop(rd, "pixel_aspect_y", text="Y")
-
- row = col.row()
- row.prop(rd, "use_border", text="Border")
- sub = row.row()
- sub.active = rd.use_border
- sub.prop(rd, "use_crop_to_border", text="Crop")
-
- col = split.column()
- sub = col.column(align=True)
- sub.label(text="Frame Range:")
- sub.prop(scene, "frame_start", text="Start")
- sub.prop(scene, "frame_end", text="End")
- sub.prop(scene, "frame_step", text="Step")
-
- sub.label(text="Frame Rate:")
- if rd.fps_base == 1:
- fps_rate = round(rd.fps / rd.fps_base)
- else:
- fps_rate = round(rd.fps / rd.fps_base, 2)
-
- # TODO: Change the following to iterate over existing presets
- custom_framerate = (fps_rate not in {23.98, 24, 25, 29.97, 30, 50, 59.94, 60})
-
- if custom_framerate == True:
- fps_label_text = "Custom (" + str(fps_rate) + " fps)"
- else:
- fps_label_text = str(fps_rate) + " fps"
-
- sub.menu("RENDER_MT_framerate_presets", text=fps_label_text)
-
- if custom_framerate or (bpy.types.RENDER_MT_framerate_presets.bl_label == "Custom"):
- sub.prop(rd, "fps")
- sub.prop(rd, "fps_base", text="/")
- subrow = sub.row(align=True)
- subrow.label(text="Time Remapping:")
- subrow = sub.row(align=True)
- subrow.prop(rd, "frame_map_old", text="Old")
- subrow.prop(rd, "frame_map_new", text="New")
-
-
-class RENDER_PT_stamp(RenderButtonsPanel, bpy.types.Panel):
- bl_label = "Stamp"
- bl_options = {'DEFAULT_CLOSED'}
- COMPAT_ENGINES = {'BLENDER_RENDER'}
-
- def draw_header(self, context):
- rd = context.scene.render
-
- self.layout.prop(rd, "use_stamp", text="")
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.render
-
- layout.active = rd.use_stamp
-
- split = layout.split()
-
- col = split.column()
- col.prop(rd, "use_stamp_time", text="Time")
- col.prop(rd, "use_stamp_date", text="Date")
- col.prop(rd, "use_stamp_render_time", text="RenderTime")
- col.prop(rd, "use_stamp_frame", text="Frame")
- col.prop(rd, "use_stamp_scene", text="Scene")
- col.prop(rd, "use_stamp_camera", text="Camera")
- col.prop(rd, "use_stamp_lens", text="Lens")
- col.prop(rd, "use_stamp_filename", text="Filename")
- col.prop(rd, "use_stamp_marker", text="Marker")
- col.prop(rd, "use_stamp_sequencer_strip", text="Seq. Strip")
-
- col = split.column()
- col.active = rd.use_stamp
- col.prop(rd, "stamp_foreground", slider=True)
- col.prop(rd, "stamp_background", slider=True)
- col.separator()
- col.prop(rd, "stamp_font_size", text="Font Size")
-
- row = layout.split(percentage=0.2)
- row.prop(rd, "use_stamp_note", text="Note")
- sub = row.row()
- sub.active = rd.use_stamp_note
- sub.prop(rd, "stamp_note_text", text="")
-
-
class RENDER_PT_bake(RenderButtonsPanel, bpy.types.Panel):
bl_label = "Bake"
bl_options = {'DEFAULT_CLOSED'}
@@ -613,29 +614,42 @@ class RENDER_PT_bake(RenderButtonsPanel, bpy.types.Panel):
layout.prop(rd, "bake_type")
- if rd.bake_type == 'NORMALS':
- layout.prop(rd, "bake_normal_space")
- elif rd.bake_type in {'DISPLACEMENT', 'AO'}:
- layout.prop(rd, "use_bake_normalize")
+ multires_bake = False
+ if rd.bake_type in ['NORMALS', 'DISPLACEMENT']:
+ layout.prop(rd, 'use_bake_multires')
+ multires_bake = rd.use_bake_multires
- # col.prop(rd, "bake_aa_mode")
- # col.prop(rd, "use_bake_antialiasing")
+ if not multires_bake:
+ if rd.bake_type == 'NORMALS':
+ layout.prop(rd, "bake_normal_space")
+ elif rd.bake_type in {'DISPLACEMENT', 'AO'}:
+ layout.prop(rd, "use_bake_normalize")
- layout.separator()
+ # col.prop(rd, "bake_aa_mode")
+ # col.prop(rd, "use_bake_antialiasing")
- split = layout.split()
+ layout.separator()
- col = split.column()
- col.prop(rd, "use_bake_clear")
- col.prop(rd, "bake_margin")
- col.prop(rd, "bake_quad_split", text="Split")
+ split = layout.split()
+
+ col = split.column()
+ col.prop(rd, "use_bake_clear")
+ col.prop(rd, "bake_margin")
+ col.prop(rd, "bake_quad_split", text="Split")
+
+ col = split.column()
+ col.prop(rd, "use_bake_selected_to_active")
+ sub = col.column()
+ sub.active = rd.use_bake_selected_to_active
+ sub.prop(rd, "bake_distance")
+ sub.prop(rd, "bake_bias")
+ else:
+ if rd.bake_type == 'DISPLACEMENT':
+ layout.prop(rd, "use_bake_lores_mesh")
+
+ layout.prop(rd, "use_bake_clear")
+ layout.prop(rd, "bake_margin")
- col = split.column()
- col.prop(rd, "use_bake_selected_to_active")
- sub = col.column()
- sub.active = rd.use_bake_selected_to_active
- sub.prop(rd, "bake_distance")
- sub.prop(rd, "bake_bias")
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index 01890bc3c99..7ca8818cbd2 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -88,15 +88,15 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
- if not hasattr(context, "texture_slot"):
+ if not (hasattr(context, "texture_slot") or hasattr(context, "texture_node")):
return False
return ((context.material or context.world or context.lamp or context.brush or context.texture or context.particle_system or isinstance(context.space_data.pin_id, bpy.types.ParticleSettings))
and (engine in cls.COMPAT_ENGINES))
def draw(self, context):
layout = self.layout
- slot = context.texture_slot
- node = context.texture_node
+ slot = getattr(context, "texture_slot", None)
+ node = getattr(context, "texture_node", None)
space = context.space_data
tex = context.texture
idblock = context_tex_datablock(context)
@@ -208,7 +208,7 @@ class TextureSlotPanel(TextureButtonsPanel):
return False
engine = context.scene.render.engine
- return TextureButtonsPanel.poll(self, context) and (engine in cls.COMPAT_ENGINES)
+ return TextureButtonsPanel.poll(cls, context) and (engine in cls.COMPAT_ENGINES)
# Texture Type Panels #
@@ -393,7 +393,7 @@ class TEXTURE_PT_image_sampling(TextureTypePanel, bpy.types.Panel):
idblock = context_tex_datablock(context)
tex = context.texture
- slot = context.texture_slot
+ slot = getattr(context, "texture_slot", None)
split = layout.split()
@@ -408,7 +408,7 @@ class TEXTURE_PT_image_sampling(TextureTypePanel, bpy.types.Panel):
col = split.column()
#Only for Material based textures, not for Lamp/World...
- if isinstance(idblock, bpy.types.Material):
+ if slot and isinstance(idblock, bpy.types.Material):
col.prop(tex, "use_normal_map")
row = col.row()
row.active = tex.use_normal_map
diff --git a/release/scripts/startup/bl_ui/properties_world.py b/release/scripts/startup/bl_ui/properties_world.py
index 4f398c9fbd9..c577af01374 100644
--- a/release/scripts/startup/bl_ui/properties_world.py
+++ b/release/scripts/startup/bl_ui/properties_world.py
@@ -20,8 +20,6 @@
import bpy
from rna_prop_ui import PropertyPanel
-# TODO, "color_range" not in the UI
-
class WorldButtonsPanel():
bl_space_type = 'PROPERTIES'
@@ -96,6 +94,10 @@ class WORLD_PT_world(WorldButtonsPanel, bpy.types.Panel):
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"
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 77583b80824..fa5579ea2e0 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -198,6 +198,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"
@@ -434,9 +438,9 @@ class IMAGE_PT_game_properties(bpy.types.Panel):
@classmethod
def poll(cls, context):
- rd = context.scene.render
sima = context.space_data
- return (sima and sima.image) and (rd.engine == 'BLENDER_GAME')
+ # display even when not in game mode because these settings effect the 3d view
+ return (sima and sima.image) # and (rd.engine == 'BLENDER_GAME')
def draw(self, context):
layout = self.layout
@@ -615,10 +619,9 @@ class IMAGE_PT_view_properties(bpy.types.Panel):
split = layout.split()
col = split.column()
+ col.prop(uvedit, "show_faces")
col.prop(uvedit, "show_smooth_edges", text="Smooth")
col.prop(uvedit, "show_modified_edges", text="Modified")
- #col.prop(uvedit, "show_edges")
- #col.prop(uvedit, "show_faces")
col = split.column()
col.prop(uvedit, "show_stretch", text="Stretch")
diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py
index 1fb2e5b735e..f66cee7f431 100644
--- a/release/scripts/startup/bl_ui/space_info.py
+++ b/release/scripts/startup/bl_ui/space_info.py
@@ -61,7 +61,9 @@ class INFO_HT_header(bpy.types.Header):
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="")
@@ -350,7 +352,7 @@ class INFO_MT_help(bpy.types.Menu):
layout = self.layout
layout.operator("wm.url_open", text="Manual", icon='HELP').url = 'http://wiki.blender.org/index.php/Doc:Manual'
- layout.operator("wm.url_open", text="Release Log", icon='URL').url = 'http://www.blender.org/development/release-logs/blender-257/'
+ layout.operator("wm.url_open", text="Release Log", icon='URL').url = 'http://www.blender.org/development/release-logs/blender-258/'
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index fed1cc49c4c..2088d8798f2 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -138,6 +138,7 @@ class NODE_MT_node(bpy.types.Menu):
layout.operator("node.duplicate_move")
layout.operator("node.delete")
+ layout.operator("node.delete_reconnect")
layout.separator()
layout.operator("node.link_make")
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 2079aef6402..c477a2ff62b 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -42,7 +42,7 @@ class SEQUENCER_HT_header(bpy.types.Header):
sub = row.row(align=True)
sub.menu("SEQUENCER_MT_view")
- if (st.view_type == 'SEQUENCER') or (st.view_type == 'SEQUENCER_PREVIEW'):
+ if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
sub.menu("SEQUENCER_MT_select")
sub.menu("SEQUENCER_MT_marker")
sub.menu("SEQUENCER_MT_add")
@@ -50,17 +50,17 @@ class SEQUENCER_HT_header(bpy.types.Header):
layout.prop(st, "view_type", expand=True, text="")
- if (st.view_type == 'PREVIEW') or (st.view_type == 'SEQUENCER_PREVIEW'):
+ if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
layout.prop(st, "display_mode", expand=True, text="")
- if (st.view_type == 'SEQUENCER'):
+ if st.view_type == 'SEQUENCER':
row = layout.row(align=True)
row.operator("sequencer.copy", text="", icon='COPYDOWN')
row.operator("sequencer.paste", text="", icon='PASTEDOWN')
layout.separator()
layout.operator("sequencer.refresh_all")
- elif (st.view_type == 'SEQUENCER_PREVIEW'):
+ elif st.view_type == 'SEQUENCER_PREVIEW':
layout.separator()
layout.operator("sequencer.refresh_all")
layout.prop(st, "display_channel", text="Channel")
@@ -101,9 +101,9 @@ class SEQUENCER_MT_view(bpy.types.Menu):
layout.separator()
- if (st.view_type == 'SEQUENCER') or (st.view_type == 'SEQUENCER_PREVIEW'):
+ if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
layout.operator("sequencer.view_all", text='View all Sequences')
- if (st.view_type == 'PREVIEW') or (st.view_type == 'SEQUENCER_PREVIEW'):
+ if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
layout.operator_context = 'INVOKE_REGION_PREVIEW'
layout.operator("sequencer.view_all_preview", text='Fit preview in window')
layout.operator("sequencer.view_zoom_ratio", text='Show preview 1:1').ratio = 1.0
@@ -213,6 +213,7 @@ class SEQUENCER_MT_add_effect(bpy.types.Menu):
layout.operator("sequencer.effect_strip_add", text="Color").type = 'COLOR'
layout.operator("sequencer.effect_strip_add", text="Speed Control").type = 'SPEED'
layout.operator("sequencer.effect_strip_add", text="Multicam Selector").type = 'MULTICAM'
+ layout.operator("sequencer.effect_strip_add", text="Adjustment Layer").type = 'ADJUSTMENT'
class SEQUENCER_MT_strip(bpy.types.Menu):
@@ -299,7 +300,7 @@ class SequencerButtonsPanel():
@staticmethod
def has_sequencer(context):
- return (context.space_data.view_type == 'SEQUENCER') or (context.space_data.view_type == 'SEQUENCER_PREVIEW')
+ return (context.space_data.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'})
@classmethod
def poll(cls, context):
@@ -312,7 +313,7 @@ class SequencerButtonsPanel_Output():
@staticmethod
def has_preview(context):
- return (context.space_data.view_type == 'PREVIEW') or (context.space_data.view_type == 'SEQUENCER_PREVIEW')
+ return (context.space_data.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'})
@classmethod
def poll(cls, context):
@@ -391,7 +392,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, bpy.types.Panel):
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
'PLUGIN',
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'SPEED',
- 'MULTICAM'}
+ 'MULTICAM', 'ADJUSTMENT'}
def draw(self, context):
layout = self.layout
@@ -530,7 +531,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, bpy.types.Panel):
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
'PLUGIN',
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR',
- 'MULTICAM', 'SPEED'}
+ 'MULTICAM', 'SPEED', 'ADJUSTMENT'}
def draw(self, context):
layout = self.layout
@@ -656,11 +657,17 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, bpy.types.Panel):
layout.template_ID(strip, "scene")
+ scene = strip.scene
+ if scene:
+ layout.prop(scene.render, "use_sequencer")
+
layout.label(text="Camera Override")
layout.template_ID(strip, "scene_camera")
- sce = strip.scene
- layout.label(text="Original frame range: %d-%d (%d)" % (sce.frame_start, sce.frame_end, sce.frame_end - sce.frame_start + 1))
+ if scene:
+ sta = scene.frame_start
+ end = scene.frame_end
+ layout.label(text="Original frame range: %d-%d (%d)" % (sta, end, end - sta + 1))
class SEQUENCER_PT_filter(SequencerButtonsPanel, bpy.types.Panel):
@@ -680,7 +687,7 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, bpy.types.Panel):
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
'PLUGIN',
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR',
- 'MULTICAM', 'SPEED'}
+ 'MULTICAM', 'SPEED', 'ADJUSTMENT'}
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py
index 3d3fc8499af..b787fc5cf75 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
@@ -33,19 +33,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.color(redalert)
- 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="")
@@ -63,11 +65,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 (unsaved)" % text.filepath)
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):
@@ -129,6 +133,7 @@ class TEXT_PT_find(bpy.types.Panel):
layout.operator("text.mark_all")
# settings
+ layout.prop(st, "use_match_case")
row = layout.row()
row.prop(st, "use_find_wrap", text="Wrap")
row.prop(st, "use_find_all", text="All")
@@ -149,8 +154,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):
@@ -184,19 +193,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):
@@ -245,8 +250,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 bf396e98c79..576709c6072 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -94,7 +94,7 @@ class USERPREF_HT_header(bpy.types.Header):
layout.operator("wm.keyconfig_import")
elif userpref.active_section == 'ADDONS':
layout.operator("wm.addon_install")
- layout.menu("USERPREF_MT_addons_dev_guides", text=" Addons Developer Guides", icon='INFO')
+ layout.menu("USERPREF_MT_addons_dev_guides")
elif userpref.active_section == 'THEMES':
layout.operator("ui.reset_default_theme")
@@ -126,7 +126,7 @@ class USERPREF_MT_appconfigs(bpy.types.Menu):
preset_operator = "wm.appconfig_activate"
def draw(self, context):
- props = self.layout.operator("wm.appconfig_default", text="Blender (default)")
+ self.layout.operator("wm.appconfig_default", text="Blender (default)")
# now draw the presets
bpy.types.Menu.draw_preset(self, context)
@@ -199,6 +199,7 @@ class USERPREF_PT_interface(bpy.types.Panel):
col.prop(view, "use_zoom_to_mouse")
col.prop(view, "use_rotate_around_active")
col.prop(view, "use_global_pivot")
+ col.prop(view, "use_camera_lock_parent")
col.separator()
@@ -437,6 +438,8 @@ class USERPREF_PT_system(bpy.types.Panel):
col.label(text="OpenGL:")
col.prop(system, "gl_clip_alpha", slider=True)
col.prop(system, "use_mipmaps")
+ col.label(text="Anisotropic Filtering")
+ col.prop(system, "anisotropic_filter", text="")
col.prop(system, "use_vertex_buffer_objects")
#Anti-aliasing is disabled as it breaks broder/lasso select
#col.prop(system, "use_antialiasing")
@@ -752,7 +755,7 @@ class USERPREF_PT_file(bpy.types.Panel):
from bl_ui.space_userpref_keymap import InputKeyMapPanel
-class USERPREF_PT_input(InputKeyMapPanel):
+class USERPREF_PT_input(bpy.types.Panel, InputKeyMapPanel):
bl_space_type = 'USER_PREFERENCES'
bl_label = "Input"
@@ -846,17 +849,14 @@ class USERPREF_PT_input(InputKeyMapPanel):
class USERPREF_MT_addons_dev_guides(bpy.types.Menu):
- bl_label = "Addons develoment guides"
+ bl_label = "Development Guides"
# menu to open webpages with addons development guides
def draw(self, context):
layout = self.layout
- layout.operator('wm.url_open', text='API Concepts'
- ).url = 'http://wiki.blender.org/index.php/Dev:2.5/Py/API/Intro'
- layout.operator('wm.url_open', text='Addons guidelines',
- ).url = 'http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Guidelines/Addons'
- layout.operator('wm.url_open', text='How to share your addon',
- ).url = 'http://wiki.blender.org/index.php/Dev:Py/Sharing'
+ layout.operator('wm.url_open', text='API Concepts', icon='URL').url = 'http://wiki.blender.org/index.php/Dev:2.5/Py/API/Intro'
+ layout.operator('wm.url_open', text='Addon Guidelines', icon='URL').url = 'http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Guidelines/Addons'
+ layout.operator('wm.url_open', text='How to share your addon', icon='URL').url = 'http://wiki.blender.org/index.php/Dev:Py/Sharing'
class USERPREF_PT_addons(bpy.types.Panel):
@@ -876,6 +876,29 @@ class USERPREF_PT_addons(bpy.types.Panel):
def module_get(mod_name):
return USERPREF_PT_addons._addons_fake_modules[mod_name]
+ @staticmethod
+ def is_user_addon(mod, user_addon_paths):
+ if not user_addon_paths:
+ user_script_path = bpy.utils.user_script_path()
+ if user_script_path is not None:
+ user_addon_paths.append(os.path.join(user_script_path(), "addons"))
+ user_addon_paths.append(os.path.join(bpy.utils.resource_path('USER'), "scripts", "addons"))
+
+ for path in user_addon_paths:
+ if bpy.path.is_subdir(mod.__file__, path):
+ 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
@@ -888,6 +911,7 @@ class USERPREF_PT_addons(bpy.types.Panel):
split = layout.split(percentage=0.2)
col = split.column()
col.prop(context.window_manager, "addon_search", text="", icon='VIEWZOOM')
+ col.label(text="Categories")
col.prop(context.window_manager, "addon_filter", expand=True)
col.label(text="Supported Level")
@@ -895,10 +919,21 @@ 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
+ # initialized on demand
+ user_addon_paths = []
+
for mod, info in addons:
module_name = mod.__name__
@@ -968,18 +1003,21 @@ class USERPREF_PT_addons(bpy.types.Panel):
split = colsub.row().split(percentage=0.15)
split.label(text="Warning:")
split.label(text=' ' + info["warning"], icon='ERROR')
- if info["wiki_url"] or info["tracker_url"]:
+
+ user_addon = USERPREF_PT_addons.is_user_addon(mod, user_addon_paths)
+ tot_row = bool(info["wiki_url"]) + bool(info["tracker_url"]) + bool(user_addon)
+
+ if tot_row:
split = colsub.row().split(percentage=0.15)
split.label(text="Internet:")
if info["wiki_url"]:
split.operator("wm.url_open", text="Link to the Wiki", icon='HELP').url = info["wiki_url"]
if info["tracker_url"]:
split.operator("wm.url_open", text="Report a Bug", icon='URL').url = info["tracker_url"]
+ if user_addon:
+ split.operator("wm.addon_remove", text="Remove", icon='CANCEL').module = mod.__name__
- if info["wiki_url"] and info["tracker_url"]:
- split.separator()
- else:
- split.separator()
+ for i in range(4 - tot_row):
split.separator()
# Append missing scripts
@@ -1103,7 +1141,6 @@ class WM_OT_addon_install(bpy.types.Operator):
del pyfile_dir
# done checking for exceptional case
- addon_files_old = set(os.listdir(path_addons))
addons_old = {mod.__name__ for mod in addon_utils.modules(USERPREF_PT_addons._addons_fake_modules)}
#check to see if the file is in compressed format (.zip)
@@ -1116,7 +1153,7 @@ class WM_OT_addon_install(bpy.types.Operator):
if self.overwrite:
for f in file_to_extract.namelist():
- __class__._module_remove(path_addons, f)
+ WM_OT_addon_install._module_remove(path_addons, f)
else:
for f in file_to_extract.namelist():
path_dest = os.path.join(path_addons, os.path.basename(f))
@@ -1140,7 +1177,7 @@ class WM_OT_addon_install(bpy.types.Operator):
path_dest = os.path.join(path_addons, os.path.basename(pyfile))
if self.overwrite:
- __class__._module_remove(path_addons, os.path.basename(pyfile))
+ WM_OT_addon_install._module_remove(path_addons, os.path.basename(pyfile))
elif os.path.exists(path_dest):
self.report({'WARNING'}, "File already installed to %r\n" % path_dest)
return {'CANCELLED'}
@@ -1185,6 +1222,54 @@ class WM_OT_addon_install(bpy.types.Operator):
return {'RUNNING_MODAL'}
+class WM_OT_addon_remove(bpy.types.Operator):
+ "Disable an addon"
+ bl_idname = "wm.addon_remove"
+ bl_label = "Remove Add-On"
+
+ module = StringProperty(name="Module", description="Module name of the addon to remove")
+
+ @staticmethod
+ def path_from_addon(module):
+ for mod in addon_utils.modules(USERPREF_PT_addons._addons_fake_modules):
+ if mod.__name__ == module:
+ filepath = mod.__file__
+ if os.path.exists(filepath):
+ if os.path.splitext(os.path.basename(filepath))[0] == "__init__":
+ return os.path.dirname(filepath), True
+ else:
+ return filepath, False
+ return None, False
+
+ def execute(self, context):
+ path, isdir = WM_OT_addon_remove.path_from_addon(self.module)
+ if path is None:
+ self.report('WARNING', "Addon path %r could not be found" % path)
+ return {'CANCELLED'}
+
+ # incase its enabled
+ addon_utils.disable(self.module)
+
+ import shutil
+ if isdir:
+ shutil.rmtree(path)
+ else:
+ os.remove(path)
+
+ context.area.tag_redraw()
+ return {'FINISHED'}
+
+ # lame confirmation check
+ def draw(self, context):
+ self.layout.label(text="Remove Addon: %r?" % self.module)
+ path, isdir = WM_OT_addon_remove.path_from_addon(self.module)
+ self.layout.label(text="Path: %r" % path)
+
+ def invoke(self, context, event):
+ wm = context.window_manager
+ return wm.invoke_props_dialog(self, width=600)
+
+
class WM_OT_addon_expand(bpy.types.Operator):
"Display more information on this add-on"
bl_idname = "wm.addon_expand"
diff --git a/release/scripts/startup/bl_ui/space_userpref_keymap.py b/release/scripts/startup/bl_ui/space_userpref_keymap.py
index 378fe231091..85764c55304 100644
--- a/release/scripts/startup/bl_ui/space_userpref_keymap.py
+++ b/release/scripts/startup/bl_ui/space_userpref_keymap.py
@@ -138,7 +138,7 @@ class USERPREF_MT_keyconfigs(bpy.types.Menu):
bpy.types.Menu.draw_preset(self, context)
-class InputKeyMapPanel(bpy.types.Panel):
+class InputKeyMapPanel:
bl_space_type = 'USER_PREFERENCES'
bl_label = "Input"
bl_region_type = 'WINDOW'
@@ -189,9 +189,9 @@ class InputKeyMapPanel(bpy.types.Panel):
if km.is_modal:
row.label(text="", icon='LINKED')
if km.is_user_defined:
- op = row.operator("wm.keymap_restore", text="Restore")
+ row.operator("wm.keymap_restore", text="Restore")
else:
- op = row.operator("wm.keymap_edit", text="Edit")
+ row.operator("wm.keymap_edit", text="Edit")
if km.show_expanded_children:
if children:
@@ -213,7 +213,7 @@ class InputKeyMapPanel(bpy.types.Panel):
col = self.indented_layout(col, level + 1)
subcol = col.split(percentage=0.2).column()
subcol.enabled = km.is_user_defined
- op = subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
+ subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
col.separator()
@@ -234,7 +234,7 @@ class InputKeyMapPanel(bpy.types.Panel):
for pname, value in properties.bl_rna.properties.items():
if pname != "rna_type" and not properties.is_property_hidden(pname):
if isinstance(value, bpy.types.OperatorProperties):
- __class__.draw_kmi_properties(box, value, title=pname)
+ InputKeyMapPanel.draw_kmi_properties(box, value, title=pname)
else:
flow.prop(properties, pname)
@@ -325,7 +325,7 @@ class InputKeyMapPanel(bpy.types.Panel):
# Operator properties
props = kmi.properties
if props is not None:
- __class__.draw_kmi_properties(box, props)
+ InputKeyMapPanel.draw_kmi_properties(box, props)
# Modal key maps attached to this operator
if not km.is_modal:
@@ -351,9 +351,9 @@ class InputKeyMapPanel(bpy.types.Panel):
row.label()
if km.is_user_defined:
- op = row.operator("wm.keymap_restore", text="Restore")
+ row.operator("wm.keymap_restore", text="Restore")
else:
- op = row.operator("wm.keymap_edit", text="Edit")
+ row.operator("wm.keymap_edit", text="Edit")
for kmi in filtered_items:
self.draw_kmi(display_keymaps, kc, km, kmi, col, 1)
@@ -362,7 +362,7 @@ class InputKeyMapPanel(bpy.types.Panel):
col = self.indented_layout(layout, 1)
subcol = col.split(percentage=0.2).column()
subcol.enabled = km.is_user_defined
- op = subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
+ subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
def draw_hierarchy(self, display_keymaps, layout):
for entry in KM_HIERARCHY:
@@ -411,8 +411,8 @@ def export_properties(prefix, properties, lines=None):
if lines is None:
lines = []
- for pname in properties.keys():
- if not properties.is_property_hidden(pname):
+ for pname in properties.bl_rna.properties.keys():
+ if pname != "rna_type" and not properties.is_property_hidden(pname):
value = getattr(properties, pname)
if isinstance(value, bpy.types.OperatorProperties):
export_properties(prefix + "." + pname, value, lines)
@@ -723,9 +723,7 @@ class WM_OT_keyitem_add(bpy.types.Operator):
bl_label = "Add Key Map Item"
def execute(self, context):
- wm = context.window_manager
km = context.keymap
- kc = wm.keyconfigs.default
if km.is_modal:
km.keymap_items.new_modal("", 'A', 'PRESS') # kmi
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 7d31bc39b0a..083c330f61d 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -54,21 +54,13 @@ class VIEW3D_HT_header(bpy.types.Header):
sub.menu("VIEW3D_MT_object")
row = layout.row()
+ # Contains buttons like Mode, Pivot, Manipulator, Layer, Mesh Select Mode...
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')
- '''
-
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')):
@@ -87,16 +79,21 @@ 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="")
# OpenGL render
@@ -685,6 +682,7 @@ class VIEW3D_MT_object(bpy.types.Menu):
layout.operator("ed.undo")
layout.operator("ed.redo")
+ layout.operator("ed.undo_history")
layout.separator()
@@ -771,10 +769,16 @@ class VIEW3D_MT_object_specials(bpy.types.Menu):
if obj.type == 'CAMERA':
layout.operator_context = 'INVOKE_REGION_WIN'
- props = layout.operator("wm.context_modal_mouse", text="Camera Lens Angle")
- props.data_path_iter = "selected_editable_objects"
- props.data_path_item = "data.lens"
- props.input_scale = 0.1
+ if obj.data.type == 'PERSP':
+ props = layout.operator("wm.context_modal_mouse", text="Camera Lens Angle")
+ props.data_path_iter = "selected_editable_objects"
+ props.data_path_item = "data.lens"
+ props.input_scale = 0.1
+ else:
+ props = layout.operator("wm.context_modal_mouse", text="Camera Lens Scale")
+ props.data_path_iter = "selected_editable_objects"
+ props.data_path_item = "data.ortho_scale"
+ props.input_scale = 0.01
if not obj.data.dof_object:
#layout.label(text="Test Has DOF obj");
@@ -1049,6 +1053,7 @@ class VIEW3D_MT_paint_weight(bpy.types.Menu):
layout.operator("ed.undo")
layout.operator("ed.redo")
+ layout.operator("ed.undo_history")
layout.separator()
@@ -1096,17 +1101,18 @@ class VIEW3D_MT_sculpt(bpy.types.Menu):
layout.operator_menu_enum("brush.curve_preset", "shape")
layout.separator()
- sculpt_tool = brush.sculpt_tool
+ if brush is not None: # unlikely but can happen
+ sculpt_tool = brush.sculpt_tool
- if sculpt_tool != 'GRAB':
- layout.prop_menu_enum(brush, "stroke_method")
+ if sculpt_tool != 'GRAB':
+ layout.prop_menu_enum(brush, "stroke_method")
- if sculpt_tool in {'DRAW', 'PINCH', 'INFLATE', 'LAYER', 'CLAY'}:
- layout.prop_menu_enum(brush, "direction")
+ if sculpt_tool in {'DRAW', 'PINCH', 'INFLATE', 'LAYER', 'CLAY'}:
+ layout.prop_menu_enum(brush, "direction")
- if sculpt_tool == 'LAYER':
- layout.prop(brush, "use_persistent")
- layout.operator("sculpt.set_persistent_base")
+ if sculpt_tool == 'LAYER':
+ layout.prop(brush, "use_persistent")
+ layout.operator("sculpt.set_persistent_base")
layout.separator()
layout.prop(sculpt, "use_threaded", text="Threaded Sculpt")
@@ -1129,6 +1135,7 @@ class VIEW3D_MT_particle(bpy.types.Menu):
layout.operator("ed.undo")
layout.operator("ed.redo")
+ layout.operator("ed.undo_history")
layout.separator()
@@ -1182,6 +1189,7 @@ class VIEW3D_MT_pose(bpy.types.Menu):
layout.operator("ed.undo")
layout.operator("ed.redo")
+ layout.operator("ed.undo_history")
layout.separator()
@@ -1239,7 +1247,7 @@ class VIEW3D_MT_pose(bpy.types.Menu):
layout.separator()
layout.menu("VIEW3D_MT_pose_showhide")
- layout.operator_menu_enum("pose.flags_set", 'mode', text="Bone Settings")
+ layout.menu("VIEW3D_MT_bone_options_toggle", text="Bone Settings")
class VIEW3D_MT_pose_transform(bpy.types.Menu):
@@ -1360,6 +1368,49 @@ class VIEW3D_MT_pose_apply(bpy.types.Menu):
layout.operator("pose.visual_transform_apply")
+class BoneOptions:
+ def draw(self, context):
+ layout = self.layout
+
+ options = [
+ "show_wire",
+ "use_deform",
+ "use_envelope_multiply",
+ "use_inherit_rotation",
+ "use_inherit_scale",
+ ]
+
+ if context.mode == 'EDIT_ARMATURE':
+ bone_props = bpy.types.EditBone.bl_rna.properties
+ data_path_iter = "selected_bones"
+ opt_suffix = ""
+ options.append("lock")
+ else: # posemode
+ bone_props = bpy.types.Bone.bl_rna.properties
+ data_path_iter = "selected_pose_bones"
+ opt_suffix = "bone."
+
+ for opt in options:
+ props = layout.operator("wm.context_collection_boolean_set", text=bone_props[opt].name)
+ props.data_path_iter = data_path_iter
+ props.data_path_item = opt_suffix + opt
+ props.type = self.type
+
+
+class VIEW3D_MT_bone_options_toggle(bpy.types.Menu, BoneOptions):
+ bl_label = "Toggle Bone Options"
+ type = 'TOGGLE'
+
+
+class VIEW3D_MT_bone_options_enable(bpy.types.Menu, BoneOptions):
+ bl_label = "Enable Bone Options"
+ type = 'ENABLE'
+
+
+class VIEW3D_MT_bone_options_disable(bpy.types.Menu, BoneOptions):
+ bl_label = "Disable Bone Options"
+ type = 'DISABLE'
+
# ********** Edit Menus, suffix from ob.type **********
@@ -1373,6 +1424,7 @@ class VIEW3D_MT_edit_mesh(bpy.types.Menu):
layout.operator("ed.undo")
layout.operator("ed.redo")
+ layout.operator("ed.undo_history")
layout.separator()
@@ -1844,6 +1896,7 @@ class VIEW3D_MT_edit_meta(bpy.types.Menu):
layout.operator("ed.undo")
layout.operator("ed.redo")
+ layout.operator("ed.undo_history")
layout.separator()
@@ -1951,7 +2004,7 @@ class VIEW3D_MT_edit_armature(bpy.types.Menu):
layout.separator()
- layout.operator_menu_enum("armature.flags_set", "mode", text="Bone Settings")
+ layout.menu("VIEW3D_MT_bone_options_toggle", text="Bone Settings")
class VIEW3D_MT_armature_specials(bpy.types.Menu):
@@ -2024,6 +2077,9 @@ class VIEW3D_PT_view3d_properties(bpy.types.Panel):
elif not view.lock_object:
col.prop(view, "lock_cursor", text="Lock to Cursor")
+ col = layout.column()
+ col.prop(view, "lock_camera")
+
col = layout.column(align=True)
col.label(text="Clip:")
col.prop(view, "clip_start", text="Start")
@@ -2315,7 +2371,8 @@ class VIEW3D_PT_etch_a_ton(bpy.types.Panel):
col.prop(toolsettings, "use_etch_autoname")
col.prop(toolsettings, "etch_number")
col.prop(toolsettings, "etch_side")
- col.operator("sketch.convert", text="Convert")
+
+ col.operator("sketch.convert", text="Convert")
class VIEW3D_PT_context_properties(bpy.types.Panel):
@@ -2348,7 +2405,7 @@ class VIEW3D_PT_context_properties(bpy.types.Panel):
def draw(self, context):
import rna_prop_ui
- member = __class__._active_context_member(context)
+ member = VIEW3D_PT_context_properties._active_context_member(context)
if member:
# Draw with no edit button
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index a6db6fbdde8..91cfd22b3d6 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -58,8 +58,8 @@ def draw_gpencil_tools(context, layout):
row = col.row()
row.prop(context.tool_settings, "use_grease_pencil_sessions")
-# ********** default tools for objectmode ****************
+# ********** default tools for objectmode ****************
class VIEW3D_PT_tools_objectmode(View3DPanel, bpy.types.Panel):
bl_context = "objectmode"
@@ -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:")
@@ -466,7 +467,7 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
def draw(self, context):
layout = self.layout
- settings = __class__.paint_settings(context)
+ settings = self.paint_settings(context)
brush = settings.brush
if not context.particle_edit_object:
@@ -687,7 +688,7 @@ class VIEW3D_PT_tools_brush_texture(PaintPanel, bpy.types.Panel):
def draw(self, context):
layout = self.layout
- settings = __class__.paint_settings(context)
+ settings = self.paint_settings(context)
brush = settings.brush
tex_slot = brush.texture_slot
@@ -786,7 +787,7 @@ class VIEW3D_PT_tools_brush_tool(PaintPanel, bpy.types.Panel):
def draw(self, context):
layout = self.layout
- settings = __class__.paint_settings(context)
+ settings = self.paint_settings(context)
brush = settings.brush
col = layout.column(align=True)
@@ -821,7 +822,7 @@ class VIEW3D_PT_tools_brush_stroke(PaintPanel, bpy.types.Panel):
def draw(self, context):
layout = self.layout
- settings = __class__.paint_settings(context)
+ settings = self.paint_settings(context)
brush = settings.brush
image_paint = context.image_paint_object
@@ -944,7 +945,6 @@ class VIEW3D_PT_sculpt_options(PaintPanel, bpy.types.Panel):
tool_settings = context.tool_settings
sculpt = tool_settings.sculpt
- settings = __class__.paint_settings(context)
layout.label(text="Lock:")
row = layout.row(align=True)
@@ -974,7 +974,6 @@ class VIEW3D_PT_sculpt_symmetry(PaintPanel, bpy.types.Panel):
layout = self.layout
sculpt = context.tool_settings.sculpt
- settings = __class__.paint_settings(context)
split = layout.split()
@@ -997,14 +996,22 @@ class VIEW3D_PT_tools_brush_appearance(PaintPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
- return (context.sculpt_object and context.tool_settings.sculpt) or (context.vertex_paint_object and context.tool_settings.vertex_paint) or (context.weight_paint_object and context.tool_settings.weight_paint) or (context.image_paint_object and context.tool_settings.image_paint)
+ ts = context.tool_settings
+ return ((context.sculpt_object and ts.sculpt) or
+ (context.vertex_paint_object and ts.vertex_paint) or
+ (context.weight_paint_object and ts.weight_paint) or
+ (context.image_paint_object and ts.image_paint))
def draw(self, context):
layout = self.layout
- settings = __class__.paint_settings(context)
+ settings = self.paint_settings(context)
brush = settings.brush
+ if brush is None: # unlikely but can happen
+ layout.label(text="Brush Unset")
+ return
+
col = layout.column()
if context.sculpt_object and context.tool_settings.sculpt:
@@ -1245,7 +1252,7 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, bpy.types.Panel):
if pe.type == 'PARTICLES':
if ob.particle_systems:
if len(ob.particle_systems) > 1:
- layout.template_list(ob, "particle_systems", ob.particle_systems, "active_index", type='ICONS')
+ layout.template_list(ob, "particle_systems", ob.particle_systems, "active_index", rows=2, maxrows=3)
ptcache = ob.particle_systems.active.point_cache
else:
@@ -1254,7 +1261,7 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, bpy.types.Panel):
ptcache = md.point_cache
if ptcache and len(ptcache.point_caches) > 1:
- layout.template_list(ptcache, "point_caches", ptcache.point_caches, "active_index", type='ICONS')
+ layout.template_list(ptcache, "point_caches", ptcache.point_caches, "active_index", rows=2, maxrows=3)
if not pe.is_editable:
layout.label(text="Point cache must be baked")
diff --git a/release/scripts/startup/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py
index 8cb63ea48cf..dcc1afed74b 100644
--- a/release/scripts/startup/keyingsets_builtins.py
+++ b/release/scripts/startup/keyingsets_builtins.py
@@ -407,7 +407,7 @@ class BUILTIN_KSI_DeltaRotation(bpy.types.KeyingSetInfo):
# add the property name to the base path
# rotation mode affects the property used
if data.rotation_mode == 'QUATERNION':
- path = path_add_property(base_path, "delta_rotation_quaternion")
+ path = keyingsets_utils.path_add_property(base_path, "delta_rotation_quaternion")
elif data.rotation_mode == 'AXIS_ANGLE':
# XXX: for now, this is not available yet
#path = path_add_property(base_path, "delta_rotation_axis_angle")