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:
authorNathan Letwory <nathan@letworyinteractive.com>2011-07-21 13:40:59 +0400
committerNathan Letwory <nathan@letworyinteractive.com>2011-07-21 13:40:59 +0400
commiteea7c358c7d606f9a4df8f11d42ac5b0df28a6d4 (patch)
tree32c72886e2007dad65c71b89c90dee891c08e5c3 /release
parentc89379e7e15aeb50a7d7106218821a17e5a7dac9 (diff)
parent314fdb941e28d5f1fbe2acace6133d6216f4e36c (diff)
svn merge -r37276:38555 https://svn.blender.org/svnroot/bf-blender/trunk/blender .
Diffstat (limited to 'release')
-rw-r--r--release/datafiles/splash.pngbin268962 -> 201866 bytes
-rw-r--r--release/scripts/modules/addon_utils.py18
-rw-r--r--release/scripts/modules/bpy/__init__.py29
-rw-r--r--release/scripts/modules/bpy/ops.py20
-rw-r--r--release/scripts/modules/bpy/path.py13
-rw-r--r--release/scripts/modules/bpy/utils.py9
-rw-r--r--release/scripts/modules/bpy_extras/image_utils.py7
-rw-r--r--release/scripts/modules/bpy_extras/io_utils.py43
-rw-r--r--release/scripts/modules/bpy_extras/mesh_utils.py85
-rw-r--r--release/scripts/modules/bpy_extras/view3d_utils.py6
-rw-r--r--release/scripts/modules/bpy_types.py6
-rw-r--r--release/scripts/modules/bpyml_ui.py1
-rw-r--r--release/scripts/modules/console/complete_namespace.py7
-rw-r--r--release/scripts/modules/console/intellisense.py23
-rw-r--r--release/scripts/modules/console_python.py2
-rw-r--r--release/scripts/modules/rna_prop_ui.py18
-rw-r--r--release/scripts/startup/bl_operators/image.py5
-rw-r--r--release/scripts/startup/bl_operators/mesh.py22
-rw-r--r--release/scripts/startup/bl_operators/nla.py123
-rw-r--r--release/scripts/startup/bl_operators/object_align.py203
-rw-r--r--release/scripts/startup/bl_operators/object_quick_effects.py189
-rw-r--r--release/scripts/startup/bl_operators/presets.py4
-rw-r--r--release/scripts/startup/bl_operators/screen_play_rendered_anim.py2
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_follow_active.py1
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_lightmap.py13
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_smart_project.py58
-rw-r--r--release/scripts/startup/bl_operators/wm.py71
-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_curve.py23
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_data_metaball.py19
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py8
-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.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py9
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py12
-rw-r--r--release/scripts/startup/bl_ui/space_image.py4
-rw-r--r--release/scripts/startup/bl_ui/space_info.py2
-rw-r--r--release/scripts/startup/bl_ui/space_node.py3
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py26
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py118
-rw-r--r--release/scripts/startup/bl_ui/space_userpref_keymap.py18
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py82
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py23
-rw-r--r--release/scripts/startup/keyingsets_builtins.py2
-rw-r--r--release/scripts/templates/batch_export.py33
-rw-r--r--release/text/GPL-license.txt2
-rw-r--r--release/text/readme.html10
52 files changed, 1097 insertions, 301 deletions
diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png
index cad2bc5f06c..d6ccdb5b733 100644
--- a/release/datafiles/splash.png
+++ b/release/datafiles/splash.png
Binary files differ
diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py
index 3877f711b7f..cf74282d064 100644
--- a/release/scripts/modules/addon_utils.py
+++ b/release/scripts/modules/addon_utils.py
@@ -31,6 +31,8 @@ __all__ = (
import bpy as _bpy
+error_duplicates = False
+
def paths():
# RELEASE SCRIPTS: official scripts distributed in Blender releases
paths = _bpy.utils.script_paths("addons")
@@ -47,9 +49,10 @@ def paths():
def modules(module_cache):
+ global error_duplicates
import os
- import sys
- import time
+
+ error_duplicates = False
path_list = paths()
@@ -119,7 +122,12 @@ def modules(module_cache):
modules_stale -= {mod_name}
mod = module_cache.get(mod_name)
if mod:
- if mod.__time__ != os.path.getmtime(mod_path):
+ if mod.__file__ != mod_path:
+ print("multiple addons with the same name:\n %r\n %r" %
+ (mod.__file__, mod_path))
+ error_duplicates = True
+
+ elif mod.__time__ != os.path.getmtime(mod_path):
print("reloading addon:", mod_name, mod.__time__, os.path.getmtime(mod_path), mod_path)
del module_cache[mod_name]
mod = None
@@ -173,11 +181,9 @@ def enable(module_name, default_set=True):
:return: the loaded module or None on failier.
:rtype: module
"""
- # note, this still gets added to _bpy_types.TypeMap
import os
import sys
- import bpy_types as _bpy_types
import imp
def handle_error():
@@ -246,8 +252,6 @@ def disable(module_name, default_set=True):
:type module_name: string
"""
import sys
- import bpy_types as _bpy_types
-
mod = sys.modules.get(module_name)
# possible this addon is from a previous session and didnt load a module this time.
diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py
index 1df8e9e5588..9c48dc89f83 100644
--- a/release/scripts/modules/bpy/__init__.py
+++ b/release/scripts/modules/bpy/__init__.py
@@ -22,24 +22,29 @@
Give access to blender data and utility functions.
"""
-# internal blender C module
-import _bpy
-from _bpy import types, props, app
+__all__ = (
+ "app",
+ "context",
+ "data",
+ "ops",
+ "path",
+ "props",
+ "types",
+ "utils",
+)
+
-data = _bpy.data
-context = _bpy.context
+# internal blender C module
+from _bpy import types, props, app, data, context
# python modules
-from . import utils, path
-from . import ops as _ops_module
+from . import utils, path, ops
# fake operator module
-ops = _ops_module.ops_fake_module
-
-import sys as _sys
-
+ops = ops.ops_fake_module
def _main():
+ import sys as _sys
# Possibly temp. addons path
from os.path import join, dirname, normpath
@@ -59,3 +64,5 @@ def _main():
_main()
+
+del _main
diff --git a/release/scripts/modules/bpy/ops.py b/release/scripts/modules/bpy/ops.py
index f54b0a1fefc..64c5a1a5f5f 100644
--- a/release/scripts/modules/bpy/ops.py
+++ b/release/scripts/modules/bpy/ops.py
@@ -29,7 +29,7 @@ op_as_string = ops_module.as_string
op_get_rna = ops_module.get_rna
-class bpy_ops(object):
+class BPyOps(object):
'''
Fake module like class.
@@ -42,7 +42,7 @@ class bpy_ops(object):
'''
if module.startswith('__'):
raise AttributeError(module)
- return bpy_ops_submodule(module)
+ return BPyOpsSubMod(module)
def __dir__(self):
@@ -67,7 +67,7 @@ class bpy_ops(object):
return "<module like class 'bpy.ops'>"
-class bpy_ops_submodule(object):
+class BPyOpsSubMod(object):
'''
Utility class to fake submodules.
@@ -84,7 +84,7 @@ class bpy_ops_submodule(object):
'''
if func.startswith('__'):
raise AttributeError(func)
- return bpy_ops_submodule_op(self.module, func)
+ return BPyOpsSubModOp(self.module, func)
def __dir__(self):
@@ -103,7 +103,7 @@ class bpy_ops_submodule(object):
return "<module like class 'bpy.ops.%s'>" % self.module
-class bpy_ops_submodule_op(object):
+class BPyOpsSubModOp(object):
'''
Utility class to fake submodule operators.
@@ -151,7 +151,7 @@ class bpy_ops_submodule_op(object):
self.func = func
def poll(self, *args):
- C_dict, C_exec = __class__._parse_args(args)
+ C_dict, C_exec = BPyOpsSubModOp._parse_args(args)
return op_poll(self.idname_py(), C_dict, C_exec)
def idname(self):
@@ -170,16 +170,16 @@ class bpy_ops_submodule_op(object):
wm = context.window_manager
# run to account for any rna values the user changes.
- __class__._scene_update(context)
+ BPyOpsSubModOp._scene_update(context)
if args:
- C_dict, C_exec = __class__._parse_args(args)
+ C_dict, C_exec = BPyOpsSubModOp._parse_args(args)
ret = op_call(self.idname_py(), C_dict, kw, C_exec)
else:
ret = op_call(self.idname_py(), None, kw)
if 'FINISHED' in ret and context.window_manager == wm:
- __class__._scene_update(context)
+ BPyOpsSubModOp._scene_update(context)
return ret
@@ -208,4 +208,4 @@ class bpy_ops_submodule_op(object):
return "<function bpy.ops.%s.%s at 0x%x'>" % \
(self.module, self.func, id(self))
-ops_fake_module = bpy_ops()
+ops_fake_module = BPyOps()
diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py
index 5e95428f641..f6254efac2e 100644
--- a/release/scripts/modules/bpy/path.py
+++ b/release/scripts/modules/bpy/path.py
@@ -35,7 +35,7 @@ def abspath(path, start=None):
:type start: string
"""
if path.startswith("//"):
- return _os.path.join(_os.path.dirname(_bpy.data.filepath if start is None else start), path[2:])
+ return _os.path.join(_os.path.dirname(_bpy.data.filepath) if start is None else start, path[2:])
return path
@@ -117,7 +117,7 @@ def display_name_from_filepath(name):
"""
Returns the path stripped of directort and extension, ensured to be utf8 compatible.
"""
- return _os.path.splitext(_os.path.basename(name))[0].encode("utf8", "replace").decode("utf8")
+ return _os.path.splitext(basename(name))[0].encode("utf8", "replace").decode("utf8")
def resolve_ncase(path):
@@ -231,3 +231,12 @@ def module_names(path, recursive=False):
modules.append(("%s.%s" % (filename, mod_name), mod_path))
return modules
+
+
+def basename(path):
+ """
+ Equivalent to os.path.basename, but skips a "//" suffix.
+
+ Use for Windows compatibility.
+ """
+ return _os.path.basename(path[2:] if path.startswith("//") else path)
diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py
index 7c0d3d24cba..57d3e6dd703 100644
--- a/release/scripts/modules/bpy/utils.py
+++ b/release/scripts/modules/bpy/utils.py
@@ -298,11 +298,18 @@ _presets = _os.path.join(_scripts[0], "presets") # FIXME - multiple paths
def preset_paths(subdir):
"""
Returns a list of paths for a specific preset.
+
+ :arg subdir: preset subdirectory (must not be an absolute path).
+ :type subdir: string
+ :return: script paths.
+ :rtype: list
"""
dirs = []
for path in script_paths("presets", all=True):
directory = _os.path.join(path, subdir)
- if _os.path.isdir(directory):
+ if not directory.startswith(path):
+ raise Exception("invalid subdir given %r" % subdir)
+ elif _os.path.isdir(directory):
dirs.append(directory)
return dirs
diff --git a/release/scripts/modules/bpy_extras/image_utils.py b/release/scripts/modules/bpy_extras/image_utils.py
index f45f9c6f225..e56c1c651c4 100644
--- a/release/scripts/modules/bpy_extras/image_utils.py
+++ b/release/scripts/modules/bpy_extras/image_utils.py
@@ -22,6 +22,7 @@ __all__ = (
"load_image",
)
+
# limited replacement for BPyImage.comprehensiveImageLoad
def load_image(imagepath,
dirname="",
@@ -85,7 +86,9 @@ def load_image(imagepath,
variants = [imagepath]
if dirname:
- variants += [os.path.join(dirname, imagepath), os.path.join(dirname, os.path.basename(imagepath))]
+ variants += [os.path.join(dirname, imagepath),
+ os.path.join(dirname, bpy.path.basename(imagepath)),
+ ]
for filepath_test in variants:
if ncase_cmp:
@@ -98,7 +101,7 @@ def load_image(imagepath,
return _image_load(nfilepath)
if place_holder:
- image = bpy.data.images.new(os.path.basename(filepath), 128, 128)
+ image = bpy.data.images.new(bpy.path.basename(imagepath), 128, 128)
# allow the path to be resolved later
image.filepath = imagepath
return image
diff --git a/release/scripts/modules/bpy_extras/io_utils.py b/release/scripts/modules/bpy_extras/io_utils.py
index 12c2d809132..9545e20b025 100644
--- a/release/scripts/modules/bpy_extras/io_utils.py
+++ b/release/scripts/modules/bpy_extras/io_utils.py
@@ -22,6 +22,7 @@ __all__ = (
"ExportHelper",
"ImportHelper",
"axis_conversion",
+ "axis_conversion_ensure",
"create_derived_objects",
"free_derived_objects",
"unpack_list",
@@ -154,12 +155,50 @@ def axis_conversion(from_forward='Y', from_up='Z', to_forward='Y', to_up='Z'):
if from_forward == to_forward and from_up == to_up:
return Matrix().to_3x3()
+ if from_forward[-1] == from_up[-1] or to_forward[-1] == to_up[-1]:
+ raise Exception("invalid axis arguments passed, "
+ "can't use up/forward on the same axis.")
+
value = reduce(int.__or__, (_axis_convert_num[a] << (i * 3) for i, a in enumerate((from_forward, from_up, to_forward, to_up))))
for i, axis_lut in enumerate(_axis_convert_lut):
if value in axis_lut:
return Matrix(_axis_convert_matrix[i])
- assert("internal error")
+ assert(0)
+
+
+def axis_conversion_ensure(operator, forward_attr, up_attr):
+ """
+ Function to ensure an operator has valid axis conversion settings, intended
+ to be used from :class:`Operator.check`.
+
+ :arg operator: the operator to access axis attributes from.
+ :type operator: :class:`Operator`
+ :arg forward_attr:
+ :type forward_attr: string
+ :arg up_attr: the directory the *filepath* will be referenced from (normally the export path).
+ :type up_attr: string
+ :return: True if the value was modified.
+ :rtype: boolean
+ """
+ def validate(axis_forward, axis_up):
+ if axis_forward[-1] == axis_up[-1]:
+ axis_up = axis_up[0:-1] + 'XYZ'[('XYZ'.index(axis_up[-1]) + 1) % 3]
+
+ return axis_forward, axis_up
+
+ change = False
+
+ axis = getattr(operator, forward_attr), getattr(operator, up_attr)
+ axis_new = validate(*axis)
+
+ if axis != axis_new:
+ setattr(operator, forward_attr, axis_new[0])
+ setattr(operator, up_attr, axis_new[1])
+
+ return True
+ else:
+ return False
# return a tuple (free, object list), free is True if memory should be freed later with free_derived_objects()
@@ -262,7 +301,7 @@ def path_reference(filepath, base_src, base_dst, mode='AUTO', copy_subdir="", co
filepath_abs = filepath_cpy
mode = 'RELATIVE'
else:
- Excaption("invalid mode given %r" % mode)
+ raise Exception("invalid mode given %r" % mode)
if mode == 'ABSOLUTE':
return filepath_abs
diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py
index b6d8a1fcf16..c42d3d0236a 100644
--- a/release/scripts/modules/bpy_extras/mesh_utils.py
+++ b/release/scripts/modules/bpy_extras/mesh_utils.py
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
__all__ = (
"mesh_linked_faces",
@@ -25,8 +25,10 @@ __all__ = (
"edge_loops_from_faces",
"edge_loops_from_edges",
"ngon_tesselate",
+ "face_random_points",
)
+
def mesh_linked_faces(mesh):
"""
Splits the mesh into connected faces, use this for seperating cubes from
@@ -66,7 +68,8 @@ def mesh_linked_faces(mesh):
if mapped_index != nxt_mapped_index:
ok = True
- # Assign mapping to this group so they all map to this group
+ # Assign mapping to this group so they
+ # all map to this group
for grp_f in face_groups[nxt_mapped_index]:
face_mapping[grp_f.index] = mapped_index
@@ -104,9 +107,9 @@ def edge_face_count(mesh):
:return: list face users for each item in mesh.edges.
:rtype: list
"""
- edge_face_count_dict = edge_face_count_dict(mesh)
+ edge_face_count = edge_face_count_dict(mesh)
get = dict.get
- return [get(edge_face_count_dict, ed.key, 0) for ed in mesh.edges]
+ return [get(edge_face_count, ed.key, 0) for ed in mesh.edges]
def edge_loops_from_faces(mesh, faces=None, seams=()):
@@ -211,8 +214,6 @@ def edge_loops_from_edges(mesh, edges=None):
if not hasattr(edges, "pop"):
edges = edges[:]
- edge_dict = {ed.key: ed for ed in mesh.edges if ed.select}
-
while edges:
current_edge = edges.pop()
vert_end, vert_start = current_edge.vertices[:]
@@ -267,6 +268,7 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
fix_loops: If this is enabled polylines that use loops to make multiple polylines are delt with correctly.
'''
+ from mathutils.geometry import tesselate_polygon
from mathutils import Vector
vector_to_tuple = Vector.to_tuple
@@ -285,7 +287,7 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
else:
return v1[1], v2[1]
- if not PREF_FIX_LOOPS:
+ if not fix_loops:
'''
Normal single concave loop filling
'''
@@ -298,7 +300,7 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
if verts[i][1] == verts[i - 1][0]:
verts.pop(i - 1)
- fill = fill_polygon([verts])
+ fill = tesselate_polygon([verts])
else:
'''
@@ -433,3 +435,70 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
fill[i] = tuple([ii for ii in reversed(fi)])
return fill
+
+
+def face_random_points(num_points, faces):
+ """
+ Generates a list of random points over mesh faces.
+
+ :arg num_points: the number of random points to generate on each face.
+ :type int:
+ :arg faces: list of the faces to generate points on.
+ :type faces: :class:`MeshFaces`, sequence
+ :return: list of random points over all faces.
+ :rtype: list
+ """
+
+ from random import random
+ from mathutils.geometry import area_tri
+
+ # Split all quads into 2 tris, tris remain unchanged
+ tri_faces = []
+ for f in faces:
+ tris = []
+ verts = f.id_data.vertices
+ fv = f.vertices[:]
+ tris.append((verts[fv[0]].co,
+ verts[fv[1]].co,
+ verts[fv[2]].co,
+ ))
+ if len(fv) == 4:
+ tris.append((verts[fv[0]].co,
+ verts[fv[3]].co,
+ verts[fv[2]].co,
+ ))
+ tri_faces.append(tris)
+
+ # For each face, generate the required number of random points
+ sampled_points = [None] * (num_points * len(faces))
+ for i, tf in enumerate(tri_faces):
+ for k in range(num_points):
+ # If this is a quad, we need to weight its 2 tris by their area
+ if len(tf) != 1:
+ area1 = area_tri(*tf[0])
+ area2 = area_tri(*tf[1])
+ area_tot = area1 + area2
+
+ area1 = area1 / area_tot
+ area2 = area2 / area_tot
+
+ vecs = tf[0 if (random() < area1) else 1]
+ else:
+ vecs = tf[0]
+
+ u1 = random()
+ u2 = random()
+ u_tot = u1 + u2
+
+ if u_tot > 1:
+ u1 = 1.0 - u1
+ u2 = 1.0 - u2
+
+ side1 = vecs[1] - vecs[0]
+ side2 = vecs[2] - vecs[0]
+
+ p = vecs[0] + u1 * side1 + u2 * side2
+
+ sampled_points[num_points * i + k] = p
+
+ return sampled_points
diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py
index 45f537ebd2f..c0c0f9186bd 100644
--- a/release/scripts/modules/bpy_extras/view3d_utils.py
+++ b/release/scripts/modules/bpy_extras/view3d_utils.py
@@ -22,9 +22,9 @@ __all__ = (
"region_2d_to_vector_3d",
"region_2d_to_location_3d",
"location_3d_to_region_2d",
- "location_3d_to_region_2d",
)
+
def region_2d_to_vector_3d(region, rv3d, coord):
"""
Return a direction vector from the viewport at the spesific 2d region
@@ -48,7 +48,7 @@ def region_2d_to_vector_3d(region, rv3d, coord):
out = Vector(((2.0 * coord[0] / region.width) - 1.0,
(2.0 * coord[1] / region.height) - 1.0,
-0.5
- ))
+ ))
w = (out[0] * persinv[0][3]) + \
(out[1] * persinv[1][3]) + \
@@ -114,6 +114,8 @@ def location_3d_to_region_2d(region, rv3d, coord):
:return: 2d location
:rtype: :class:`Vector`
"""
+ from mathutils import Vector
+
prj = Vector((coord[0], coord[1], coord[2], 1.0)) * rv3d.perspective_matrix
if prj.w > 0.0:
width_half = region.width / 2.0
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 3c1b454e72e..f2cd46b20ae 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -20,7 +20,6 @@
from _bpy import types as bpy_types
import _bpy
-from mathutils import Vector
StructRNA = bpy_types.Struct.__bases__[0]
StructMetaPropGroup = _bpy.StructMetaPropGroup
@@ -144,18 +143,21 @@ class _GenericBone:
def x_axis(self):
""" Vector pointing down the x-axis of the bone.
"""
+ from mathutils import Vector
return Vector((1.0, 0.0, 0.0)) * self.matrix.to_3x3()
@property
def y_axis(self):
""" Vector pointing down the x-axis of the bone.
"""
+ from mathutils import Vector
return Vector((0.0, 1.0, 0.0)) * self.matrix.to_3x3()
@property
def z_axis(self):
""" Vector pointing down the x-axis of the bone.
"""
+ from mathutils import Vector
return Vector((0.0, 0.0, 1.0)) * self.matrix.to_3x3()
@property
@@ -239,7 +241,7 @@ class _GenericBone:
chain.append(child)
else:
if len(children_basename):
- print("multiple basenames found, this is probably not what you want!", bone.name, children_basename)
+ print("multiple basenames found, this is probably not what you want!", self.name, children_basename)
break
diff --git a/release/scripts/modules/bpyml_ui.py b/release/scripts/modules/bpyml_ui.py
index 1e0522974d1..5df04b8bf34 100644
--- a/release/scripts/modules/bpyml_ui.py
+++ b/release/scripts/modules/bpyml_ui.py
@@ -22,7 +22,6 @@
import bpy as _bpy
import bpyml
from bpyml import TAG, ARGS, CHILDREN
-from types import ModuleType
_uilayout_rna = _bpy.types.UILayout.bl_rna
diff --git a/release/scripts/modules/console/complete_namespace.py b/release/scripts/modules/console/complete_namespace.py
index a31280ebff0..d787fed0967 100644
--- a/release/scripts/modules/console/complete_namespace.py
+++ b/release/scripts/modules/console/complete_namespace.py
@@ -37,6 +37,11 @@ def is_dict(obj):
return hasattr(obj, 'keys') and hasattr(getattr(obj, 'keys'), '__call__')
+def is_struct_seq(obj):
+ """Returns whether obj is a structured sequence subclass: sys.float_info"""
+ return isinstance(obj, tuple) and hasattr(obj, 'n_fields')
+
+
def complete_names(word, namespace):
"""Complete variable names or attributes
@@ -174,7 +179,7 @@ def complete(word, namespace, private=True):
if type(obj) in (bool, float, int, str):
return []
# an extra char '[', '(' or '.' will be added
- if hasattr(obj, '__getitem__'):
+ if hasattr(obj, '__getitem__') and not is_struct_seq(obj):
# list or dictionary
matches = complete_indices(word, namespace, obj)
elif hasattr(obj, '__call__'):
diff --git a/release/scripts/modules/console/intellisense.py b/release/scripts/modules/console/intellisense.py
index 9352d7c14e1..a177b305fda 100644
--- a/release/scripts/modules/console/intellisense.py
+++ b/release/scripts/modules/console/intellisense.py
@@ -53,7 +53,7 @@ RE_UNQUOTED_WORD = re.compile(
re.UNICODE)
-def complete(line, cursor, namespace, private=True):
+def complete(line, cursor, namespace, private):
"""Returns a list of possible completions:
* name completion
@@ -82,6 +82,9 @@ def complete(line, cursor, namespace, private=True):
if RE_MODULE.match(line):
from . import complete_import
matches = complete_import.complete(line)
+ if not private:
+ matches[:] = [m for m in matches if m[:1] != "_"]
+ matches.sort()
else:
from . import complete_namespace
matches = complete_namespace.complete(word, namespace, private)
@@ -120,15 +123,29 @@ def expand(line, cursor, namespace, private=True):
from . import complete_calltip
matches, word, scrollback = complete_calltip.complete(line,
cursor, namespace)
+ prefix = os.path.commonprefix(matches)[len(word):]
no_calltip = False
else:
matches, word = complete(line, cursor, namespace, private)
+ prefix = os.path.commonprefix(matches)[len(word):]
if len(matches) == 1:
scrollback = ''
else:
- scrollback = ' '.join([m.split('.')[-1] for m in matches])
+ # causes blender bug [#27495] since string keys may contain '.'
+ # scrollback = ' '.join([m.split('.')[-1] for m in matches])
+
+ # add white space to align with the cursor
+ white_space = " " + (" " * (cursor + len(prefix)))
+ word_prefix = word + prefix
+ scrollback = '\n'.join(
+ [white_space + m[len(word_prefix):]
+ if (word_prefix and m.startswith(word_prefix))
+ else
+ white_space + m.split('.')[-1]
+ for m in matches])
+
no_calltip = True
- prefix = os.path.commonprefix(matches)[len(word):]
+
if prefix:
line = line[:cursor] + prefix + line[cursor:]
cursor += len(prefix)
diff --git a/release/scripts/modules/console_python.py b/release/scripts/modules/console_python.py
index 3048fa1d597..455eabe377b 100644
--- a/release/scripts/modules/console_python.py
+++ b/release/scripts/modules/console_python.py
@@ -80,7 +80,7 @@ def get_console(console_id):
if console_data:
console, stdout, stderr = console_data
- # XXX, bug in python 3.1.2 ? (worked in 3.1.1)
+ # XXX, bug in python 3.1.2, 3.2 ? (worked in 3.1.1)
# seems there is no way to clear StringIO objects for writing, have to make new ones each time.
import io
stdout = io.StringIO()
diff --git a/release/scripts/modules/rna_prop_ui.py b/release/scripts/modules/rna_prop_ui.py
index 9311987e2e7..388ae2b0e13 100644
--- a/release/scripts/modules/rna_prop_ui.py
+++ b/release/scripts/modules/rna_prop_ui.py
@@ -111,12 +111,16 @@ def draw(layout, context, context_member, property_type, use_edit=True):
continue
row = layout.row()
- convert_to_pyobject = getattr(val, "convert_to_pyobject", None)
-
- val_orig = val
- if convert_to_pyobject:
- val_draw = val = val.convert_to_pyobject()
- val_draw = str(val_draw)
+ to_dict = getattr(val, "to_dict", None)
+ to_list = getattr(val, "to_list", None)
+
+ # val_orig = val # UNUSED
+ if to_dict:
+ val = to_dict()
+ val_draw = str(val)
+ elif to_list:
+ val = to_list()
+ val_draw = str(val)
else:
val_draw = val
@@ -131,7 +135,7 @@ def draw(layout, context, context_member, property_type, use_edit=True):
row.label(text=key)
# explicit exception for arrays
- if convert_to_pyobject and not hasattr(val_orig, "len"):
+ if to_dict or to_list:
row.label(text=val_draw)
else:
if key in rna_properties:
diff --git a/release/scripts/startup/bl_operators/image.py b/release/scripts/startup/bl_operators/image.py
index 462db3a2c5e..4bb53f776ba 100644
--- a/release/scripts/startup/bl_operators/image.py
+++ b/release/scripts/startup/bl_operators/image.py
@@ -60,7 +60,7 @@ class EditExternally(bpy.types.Operator):
filepath = 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]
@@ -121,7 +121,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
@@ -164,7 +163,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 89802d7ba5c..03b0e469310 100644
--- a/release/scripts/startup/bl_operators/mesh.py
+++ b/release/scripts/startup/bl_operators/mesh.py
@@ -81,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:
@@ -120,12 +118,7 @@ class MeshMirrorUV(bpy.types.Operator):
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]
@@ -152,7 +145,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]:
@@ -170,10 +162,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_align.py b/release/scripts/startup/bl_operators/object_align.py
index 644f30a4745..d215f3476cf 100644
--- a/release/scripts/startup/bl_operators/object_align.py
+++ b/release/scripts/startup/bl_operators/object_align.py
@@ -21,13 +21,102 @@
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 = verts[-1].co * matrix_world
+
+ 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 = verts[i].co * matrix_world
+
+ # 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
@@ -42,80 +131,89 @@ def align_objects(align_x, align_y, align_z, align_mode, relative_to):
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:
-
- 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_Front_Up = GBB[0]
+ Right_Back_Down = GBB[1]
- Left_Up_Front = bb_world[1]
- Right_Down_Back = bb_world[7]
-
- 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 +328,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 +337,11 @@ class AlignObjects(bpy.types.Operator):
bl_label = "Align Objects"
bl_options = {'REGISTER', 'UNDO'}
+ bb_quality = BoolProperty(
+ name="High Quality",
+ description="Enables high quality calculation of the bounding box for perfect results on complex shape meshes with rotation/scale (Slow)",
+ default=False)
+
align_mode = EnumProperty(items=(
('OPT_1', "Negative Sides", ""),
('OPT_2', "Centers", ""),
@@ -271,10 +374,10 @@ 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")
return {'CANCELLED'}
else:
- return {'FINISHED'}
+ return {'FINISHED'} \ No newline at end of file
diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py
index 21640fa3ee6..074f204d50e 100644
--- a/release/scripts/startup/bl_operators/object_quick_effects.py
+++ b/release/scripts/startup/bl_operators/object_quick_effects.py
@@ -23,9 +23,26 @@ import bpy
from bpy.props import BoolProperty, EnumProperty, IntProperty, FloatProperty, FloatVectorProperty
-class MakeFur(bpy.types.Operator):
- bl_idname = "object.make_fur"
- bl_label = "Make Fur"
+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 QuickFur(bpy.types.Operator):
+ bl_idname = "object.quick_fur"
+ bl_label = "Quick Fur"
bl_options = {'REGISTER', 'UNDO'}
density = EnumProperty(items=(
@@ -80,9 +97,157 @@ class MakeFur(bpy.types.Operator):
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
+ bpy.ops.mesh.uv_texture_add(fake_context)
+ uv = obj.data.uv_textures[-1]
+ uv.name = "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 = Vector(obj.bound_box[i]) * obj.matrix_world
min_co[0] = min(bb_vec[0], min_co[0])
min_co[1] = min(bb_vec[1], min_co[1])
@@ -92,9 +257,9 @@ 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=(
@@ -112,8 +277,8 @@ class MakeSmoke(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']
- min_co = Vector((100000, 100000, 100000))
- max_co = Vector((-100000, -100000, -100000))
+ 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.")
@@ -201,9 +366,9 @@ 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=(
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index 493c51ad237..f3c799c9ac2 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -315,7 +315,7 @@ 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):
@@ -326,7 +326,7 @@ class AddPresetOperator(AddPresetBase, bpy.types.Operator):
ret = []
for prop_id, prop in operator_rna.properties.items():
- if (not prop.is_hidden) and prop_id not in properties_blacklist:
+ if (not (prop.is_hidden or prop.is_skip_save)) and 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..910ccf96c0e 100644
--- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
+++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
@@ -78,7 +78,7 @@ 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
diff --git a/release/scripts/startup/bl_operators/uvcalc_follow_active.py b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
index edd09d9c66b..43ca9af59ba 100644
--- a/release/scripts/startup/bl_operators/uvcalc_follow_active.py
+++ b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
@@ -42,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):
'''
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..9c3be84b807 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
@@ -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][:] = (v.co * MatQuat).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 fcc30ecbb4b..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
@@ -457,15 +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 = {'INTERNAL'}
+ 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'})
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_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index 11a129377e8..3c88127c724 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -113,13 +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")
- row.column().prop(curve, "texspace_size")
+ 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_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index e2c88413177..618a88f0879 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -118,6 +118,7 @@ class DATA_PT_texture_space(MeshButtonsPanel, bpy.types.Panel):
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):
bl_label = "Vertex Groups"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -289,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 c568d10b3b0..6dda99bc37f 100644
--- a/release/scripts/startup/bl_ui/properties_data_metaball.py
+++ b/release/scripts/startup/bl_ui/properties_data_metaball.py
@@ -70,10 +70,23 @@ class DATA_PT_metaball(DataButtonsPanel, bpy.types.Panel):
layout.label(text="Update:")
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")
- row.column().prop(mball, "texspace_size")
+ 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):
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 75069993521..ce6d0990f05 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -483,11 +483,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 +498,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)
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 03823ad7345..5f79dd3127a 100644
--- a/release/scripts/startup/bl_ui/properties_object_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_object_constraint.py
@@ -655,8 +655,8 @@ class ConstraintButtonsPanel():
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.
+ # 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))
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index 63333083cb2..4c92296dacd 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -879,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 4e1c1b34363..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()
@@ -376,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()
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/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 9f69ca17076..722b46aba11 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -434,7 +434,6 @@ class IMAGE_PT_game_properties(bpy.types.Panel):
@classmethod
def poll(cls, context):
- rd = context.scene.render
sima = context.space_data
# display even when not in game mode because these settings effect the 3d view
return (sima and sima.image) # and (rd.engine == 'BLENDER_GAME')
@@ -616,10 +615,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..2b12e75564c 100644
--- a/release/scripts/startup/bl_ui/space_info.py
+++ b/release/scripts/startup/bl_ui/space_info.py
@@ -350,7 +350,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..831fd359782 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -135,9 +135,10 @@ class NODE_MT_node(bpy.types.Menu):
layout.operator("transform.resize")
layout.separator()
-
+
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 858c619d3c1..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
@@ -300,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):
@@ -313,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):
@@ -657,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):
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index f018785a925..139b3205835 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)
@@ -438,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")
@@ -847,17 +849,14 @@ class USERPREF_PT_input(bpy.types.Panel, 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):
@@ -877,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
@@ -897,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__
@@ -970,20 +1003,24 @@ 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
# First collect scripts that are used but have no script file.
module_names = {mod.__name__ for mod, info in addons}
@@ -1105,7 +1142,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)
@@ -1118,7 +1154,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))
@@ -1142,7 +1178,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'}
@@ -1187,6 +1223,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 e99cefb91b8..85764c55304 100644
--- a/release/scripts/startup/bl_ui/space_userpref_keymap.py
+++ b/release/scripts/startup/bl_ui/space_userpref_keymap.py
@@ -189,9 +189,9 @@ class InputKeyMapPanel:
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:
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:
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:
# 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:
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:
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:
@@ -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 a8a15b674b0..e1d31b53359 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -98,6 +98,8 @@ class VIEW3D_HT_header(bpy.types.Header):
row.prop(toolsettings, "use_snap_peel_object", text="")
elif toolsettings.snap_element == 'FACE':
row.prop(toolsettings, "use_snap_project", text="")
+ if toolsettings.use_snap_project and obj.mode == 'EDIT':
+ row.prop(toolsettings, "use_snap_project_self", text="")
# OpenGL render
row = layout.row(align=True)
@@ -791,10 +793,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");
@@ -1117,17 +1125,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")
@@ -1262,7 +1271,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):
@@ -1383,6 +1392,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 **********
@@ -1976,7 +2028,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):
@@ -2377,7 +2429,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 503a1d806ac..e1efeed87ea 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -60,7 +60,6 @@ def draw_gpencil_tools(context, layout):
# ********** default tools for objectmode ****************
-
class VIEW3D_PT_tools_objectmode(View3DPanel, bpy.types.Panel):
bl_context = "objectmode"
bl_label = "Object Tools"
@@ -466,7 +465,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 +686,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 +785,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 +820,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 +943,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 +972,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 +994,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:
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")
diff --git a/release/scripts/templates/batch_export.py b/release/scripts/templates/batch_export.py
new file mode 100644
index 00000000000..aa0e601725b
--- /dev/null
+++ b/release/scripts/templates/batch_export.py
@@ -0,0 +1,33 @@
+# exports each selected object into its own file
+
+import bpy
+import os
+
+# export to blend file location
+basedir = os.path.dirname(bpy.data.filepath)
+
+if not basedir:
+ raise Exception("Blend file is not saved")
+
+selection = bpy.context.selected_objects
+
+bpy.ops.object.select_all(action='DESELECT')
+
+for obj in selection:
+
+ obj.select = True
+
+ name = bpy.path.clean_name(obj.name)
+ fn = os.path.join(basedir, name)
+
+ bpy.ops.export_scene.fbx(filepath=fn + ".fbx", use_selection=True)
+
+ ## Can be used for multiple formats
+ # bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True)
+
+ obj.select = False
+
+ print("written:", fn)
+
+for obj in selection:
+ obj.select = True
diff --git a/release/text/GPL-license.txt b/release/text/GPL-license.txt
index 8860b2a8afa..e8c0353e734 100644
--- a/release/text/GPL-license.txt
+++ b/release/text/GPL-license.txt
@@ -2,7 +2,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
diff --git a/release/text/readme.html b/release/text/readme.html
index 1014d8ef80a..2b5a4071a7f 100644
--- a/release/text/readme.html
+++ b/release/text/readme.html
@@ -12,22 +12,22 @@
</style>
</head>
<body>
-<p class="title"><b>Blender 2.57</b></p>
+<p class="title"><b>Blender 2.58</b></p>
<p><br></p>
<p class="header"><b>About</b></p>
<p class="body">Welcome to Blender, the free, open source 3D application for modeling, animation, rendering, compositing, video editing and game creation. Blender is available for Linux, Mac OS X, Windows, Solaris and FreeBSD and has a large world-wide community.</p>
<p class="body">Blender can be used freely for any purpose, including commercial use and distribution. It's free and open-source software, released under the GNU GPL licence. The entire source code is available on our website.</p>
<p class="body">For more information, visit <a href="http://www.blender.org">blender.org</a>.</p>
<p><br></p>
-<p class="header"><b>2.57</b></p>
-<p class="body">The Blender Foundation and online developer community is proud to present Blender 2.57. This release is the first official stable release of the Blender 2.5 series, and represents the culmination of many years of redesign and development work. <a href="http://www.blender.org/development/release-logs/blender-256-beta/">More information about this release</a>.</p>
+<p class="header"><b>2.58</b></p>
+<p class="body">The Blender Foundation and online developer community is proud to present Blender 2.58. This release is the second official stable release of the Blender 2.5 series, and represents the culmination of many years of redesign and development work. <a href="http://www.blender.org/development/release-logs/blender-258/">More information about this release</a>.</p>
<p class="body">What to Expect:</p>
<p class="body"> • Big improvements - This is our most exciting version to date, already a significant improvement in many ways over 2.49</p>
<p class="body"> • Missing/Incomplete Features - Although most of it is there, not all functionality from pre-2.5 versions has been restored yet. Some functionality may be re-implemented a different way.</p>
<p class="body"> • Changes - If you're used to the old Blenders, Blender 2.5 may seem quite different at first, but it won't be long before it grows on you even more than before.</p>
<p><br></p>
<p class="header"><b>Bugs</b></p>
-<p class="body">Although Blender 2.57 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender 2.57. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.</p>
+<p class="body">Although Blender 2.58 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender 2.58. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.</p>
<p><br></p>
<p class="header"><b>Package Contents</b></p>
<p class="body">The downloaded Blender package includes:</p>
@@ -51,7 +51,7 @@
<p class="header"><b>Links</b></p>
<p class="body">Users:</p>
<p class="body"> General information <a href="http://www.blender.org">www.blender.org</a> <br>
- Full release log <a href="http://www.blender.org/development/release-logs/blender-257/">www.blender.org/development/release-logs/blender-257/</a><br>
+ Full release log <a href="http://www.blender.org/development/release-logs/blender-258/">www.blender.org/development/release-logs/blender-258/</a><br>
Tutorials <a href="http://www.blender.org/education-help/">www.blender.org/education-help/</a> <br>
Manual <a href="http://wiki.blender.org/index.php/Doc:Manual">wiki.blender.org/index.php/Doc:Manual</a><br>
User Forum <a href="http://www.blenderartists.org">www.blenderartists.org</a><br>