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:
authorBenoit Bolsee <benoit.bolsee@online.be>2011-09-07 19:34:04 +0400
committerBenoit Bolsee <benoit.bolsee@online.be>2011-09-07 19:34:04 +0400
commitdbd6658d737b1592a633ddf6397be14e50e434d9 (patch)
tree57081721d70622a3c3141909b258f9bce8a5b1e3 /release/scripts
parentb5bd86e5907c3fa98546dabeda9703dfb15862f4 (diff)
parent884fc84793be1c5fdd6643ad267331381f8e1c6b (diff)
svn merge -r 37306:39975 https://svn.blender.org/svnroot/bf-blender/trunk/blender
Diffstat (limited to 'release/scripts')
-rw-r--r--release/scripts/modules/addon_utils.py89
-rw-r--r--release/scripts/modules/bpy/__init__.py41
-rw-r--r--release/scripts/modules/bpy/ops.py20
-rw-r--r--release/scripts/modules/bpy/path.py97
-rw-r--r--release/scripts/modules/bpy/utils.py90
-rw-r--r--release/scripts/modules/bpy_extras/__init__.py4
-rw-r--r--release/scripts/modules/bpy_extras/image_utils.py28
-rw-r--r--release/scripts/modules/bpy_extras/io_utils.py258
-rw-r--r--release/scripts/modules/bpy_extras/mesh_utils.py131
-rw-r--r--release/scripts/modules/bpy_extras/object_utils.py53
-rw-r--r--release/scripts/modules/bpy_extras/view3d_utils.py52
-rw-r--r--release/scripts/modules/bpy_types.py34
-rw-r--r--release/scripts/modules/bpyml.py2
-rw-r--r--release/scripts/modules/bpyml_ui.py7
-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.py4
-rw-r--r--release/scripts/modules/keyingsets_utils.py9
-rw-r--r--release/scripts/modules/rna_info.py8
-rw-r--r--release/scripts/modules/rna_prop_ui.py18
-rw-r--r--release/scripts/presets/ffmpeg/DV.py1
-rw-r--r--release/scripts/presets/ffmpeg/DVD.py1
-rw-r--r--release/scripts/presets/ffmpeg/SVCD.py1
-rw-r--r--release/scripts/presets/ffmpeg/VCD.py1
-rw-r--r--release/scripts/presets/ffmpeg/xvid.py3
-rw-r--r--release/scripts/startup/bl_operators/add_mesh_torus.py86
-rw-r--r--release/scripts/startup/bl_operators/animsys_update.py3
-rw-r--r--release/scripts/startup/bl_operators/image.py52
-rw-r--r--release/scripts/startup/bl_operators/mesh.py45
-rw-r--r--release/scripts/startup/bl_operators/nla.py191
-rw-r--r--release/scripts/startup/bl_operators/object.py305
-rw-r--r--release/scripts/startup/bl_operators/object_align.py272
-rw-r--r--release/scripts/startup/bl_operators/object_quick_effects.py365
-rw-r--r--release/scripts/startup/bl_operators/object_randomize_transform.py105
-rw-r--r--release/scripts/startup/bl_operators/presets.py78
-rw-r--r--release/scripts/startup/bl_operators/screen_play_rendered_anim.py99
-rw-r--r--release/scripts/startup/bl_operators/sequencer.py15
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_follow_active.py4
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_lightmap.py81
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_smart_project.py117
-rw-r--r--release/scripts/startup/bl_operators/vertexpaint_dirt.py37
-rw-r--r--release/scripts/startup/bl_operators/wm.py570
-rw-r--r--release/scripts/startup/bl_ui/__init__.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_animviz.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py62
-rw-r--r--release/scripts/startup/bl_ui/properties_data_bone.py17
-rw-r--r--release/scripts/startup/bl_ui/properties_data_camera.py11
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py44
-rw-r--r--release/scripts/startup/bl_ui/properties_data_empty.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_data_lamp.py23
-rw-r--r--release/scripts/startup/bl_ui/properties_data_lattice.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py29
-rw-r--r--release/scripts/startup/bl_ui/properties_data_metaball.py28
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py14
-rw-r--r--release/scripts/startup/bl_ui/properties_data_speaker.py125
-rw-r--r--release/scripts/startup/bl_ui/properties_game.py45
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py71
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py26
-rw-r--r--release/scripts/startup/bl_ui/properties_object_constraint.py18
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py52
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_cloth.py15
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_field.py5
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py10
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_smoke.py11
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_softbody.py15
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py51
-rw-r--r--release/scripts/startup/bl_ui/properties_scene.py45
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py75
-rw-r--r--release/scripts/startup/bl_ui/properties_world.py27
-rw-r--r--release/scripts/startup/bl_ui/space_console.py34
-rw-r--r--release/scripts/startup/bl_ui/space_dopesheet.py121
-rw-r--r--release/scripts/startup/bl_ui/space_filebrowser.py3
-rw-r--r--release/scripts/startup/bl_ui/space_graph.py38
-rw-r--r--release/scripts/startup/bl_ui/space_image.py122
-rw-r--r--release/scripts/startup/bl_ui/space_info.py48
-rw-r--r--release/scripts/startup/bl_ui/space_logic.py21
-rw-r--r--release/scripts/startup/bl_ui/space_nla.py39
-rw-r--r--release/scripts/startup/bl_ui/space_node.py42
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py38
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py132
-rw-r--r--release/scripts/startup/bl_ui/space_text.py93
-rw-r--r--release/scripts/startup/bl_ui/space_time.py20
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py254
-rw-r--r--release/scripts/startup/bl_ui/space_userpref_keymap.py189
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py300
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py97
-rw-r--r--release/scripts/startup/keyingsets_builtins.py35
-rw-r--r--release/scripts/templates/addon_add_object.py12
-rw-r--r--release/scripts/templates/batch_export.py33
-rw-r--r--release/scripts/templates/operator_export.py28
-rw-r--r--release/scripts/templates/operator_mesh_add.py41
-rw-r--r--release/scripts/templates/operator_modal.py4
-rw-r--r--release/scripts/templates/operator_modal_draw.py2
-rw-r--r--release/scripts/templates/operator_modal_timer.py2
-rw-r--r--release/scripts/templates/operator_modal_view3d.py7
-rw-r--r--release/scripts/templates/operator_simple.py2
-rw-r--r--release/scripts/templates/ui_menu.py49
-rw-r--r--release/scripts/templates/ui_menu_simple.py26
-rw-r--r--release/scripts/templates/ui_panel_simple.py (renamed from release/scripts/templates/panel_simple.py)7
100 files changed, 4104 insertions, 1985 deletions
diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py
index 3877f711b7f..0c5ef69e805 100644
--- a/release/scripts/modules/addon_utils.py
+++ b/release/scripts/modules/addon_utils.py
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
__all__ = (
"paths",
@@ -26,11 +26,15 @@ __all__ = (
"disable",
"reset_all",
"module_bl_info",
-)
+ )
import bpy as _bpy
+error_duplicates = False
+error_encoding = False
+
+
def paths():
# RELEASE SCRIPTS: official scripts distributed in Blender releases
paths = _bpy.utils.script_paths("addons")
@@ -47,14 +51,19 @@ def paths():
def modules(module_cache):
+ global error_duplicates
+ global error_encoding
import os
- import sys
- import time
+
+ error_duplicates = False
+ error_encoding = False
path_list = paths()
# fake module importing
def fake_module(mod_name, mod_path, speedy=True):
+ global error_encoding
+
if _bpy.app.debug:
print("fake_module", mod_path, mod_name)
import ast
@@ -65,12 +74,28 @@ def modules(module_cache):
line_iter = iter(file_mod)
l = ""
while not l.startswith("bl_info"):
- l = line_iter.readline()
+ try:
+ l = line_iter.readline()
+ except UnicodeDecodeError as e:
+ if not error_encoding:
+ error_encoding = True
+ print("Error reading file as UTF-8:", mod_path, e)
+ file_mod.close()
+ return None
+
if len(l) == 0:
break
while l.rstrip():
lines.append(l)
- l = line_iter.readline()
+ try:
+ l = line_iter.readline()
+ except UnicodeDecodeError as e:
+ if not error_encoding:
+ error_encoding = True
+ print("Error reading file as UTF-8:", mod_path, e)
+ file_mod.close()
+ return None
+
data = "".join(lines)
else:
@@ -119,8 +144,18 @@ def modules(module_cache):
modules_stale -= {mod_name}
mod = module_cache.get(mod_name)
if mod:
- if mod.__time__ != os.path.getmtime(mod_path):
- print("reloading addon:", mod_name, mod.__time__, os.path.getmtime(mod_path), 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
@@ -135,7 +170,9 @@ def modules(module_cache):
del modules_stale
mod_list = list(module_cache.values())
- mod_list.sort(key=lambda mod: (mod.bl_info['category'], mod.bl_info['name']))
+ mod_list.sort(key=lambda mod: (mod.bl_info['category'],
+ mod.bl_info['name'],
+ ))
return mod_list
@@ -155,8 +192,9 @@ def check(module_name):
loaded_state = mod and getattr(mod, "__addon_enabled__", Ellipsis)
if loaded_state is Ellipsis:
- print("Warning: addon-module %r found module but without"
- " __addon_enabled__ field, possible name collision from file: %r" %
+ print("Warning: addon-module %r found module "
+ "but without __addon_enabled__ field, "
+ "possible name collision from file: %r" %
(module_name, getattr(mod, "__file__", "<unknown>")))
loaded_state = False
@@ -173,11 +211,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():
@@ -201,7 +237,8 @@ def enable(module_name, default_set=True):
return None
mod.__addon_enabled__ = False
- # Split registering up into 3 steps so we can undo if it fails par way through
+ # Split registering up into 3 steps so we can undo
+ # if it fails par way through.
# 1) try import
try:
mod = __import__(module_name)
@@ -246,12 +283,11 @@ 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.
- # so even if the module is not found, still disable the addon in the user prefs.
+ # possible this addon is from a previous session and didnt load a
+ # module this time. So even if the module is not found, still disable
+ # the addon in the user prefs.
if mod:
mod.__addon_enabled__ = False
@@ -306,7 +342,22 @@ def reset_all(reload_scripts=False):
disable(mod_name)
-def module_bl_info(mod, info_basis={"name": "", "author": "", "version": (), "blender": (), "api": 0, "location": "", "description": "", "wiki_url": "", "tracker_url": "", "support": 'COMMUNITY', "category": "", "warning": "", "show_expanded": False}):
+def module_bl_info(mod, info_basis={"name": "",
+ "author": "",
+ "version": (),
+ "blender": (),
+ "api": 0,
+ "location": "",
+ "description": "",
+ "wiki_url": "",
+ "tracker_url": "",
+ "support": 'COMMUNITY',
+ "category": "",
+ "warning": "",
+ "show_expanded": False,
+ }
+ ):
+
addon_info = getattr(mod, "bl_info", {})
# avoid re-initializing
diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py
index 1df8e9e5588..5c371fd750a 100644
--- a/release/scripts/modules/bpy/__init__.py
+++ b/release/scripts/modules/bpy/__init__.py
@@ -16,34 +16,45 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
"""
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
+ops = ops.ops_fake_module
-import sys as _sys
-
-def _main():
+def main():
+ import sys
# Possibly temp. addons path
from os.path import join, dirname, normpath
- _sys.path.append(normpath(join(dirname(__file__), "..", "..", "addons", "modules")))
+ sys.path.append(normpath(join(dirname(__file__),
+ "..", "..", "addons", "modules")))
+
+ # fake module to allow:
+ # from bpy.types import Panel
+ sys.modules["bpy.types"] = types
# if "-d" in sys.argv: # Enable this to measure startup speed
if 0:
@@ -58,4 +69,6 @@ def _main():
utils.load_scripts()
-_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..284fef97795 100644
--- a/release/scripts/modules/bpy/path.py
+++ b/release/scripts/modules/bpy/path.py
@@ -16,26 +16,44 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
"""
This module has a similar scope to os.path, containing utility
functions for dealing with paths in Blender.
"""
+__all__ = (
+ "abspath",
+ "basename",
+ "clean_name",
+ "display_name",
+ "display_name_from_filepath",
+ "ensure_ext",
+ "is_subdir",
+ "module_names",
+ "relpath",
+ "resolve_ncase",
+ )
+
import bpy as _bpy
import os as _os
def abspath(path, start=None):
"""
- Returns the absolute path relative to the current blend file using the "//" prefix.
+ Returns the absolute path relative to the current blend file
+ using the "//" prefix.
- :arg start: Relative to this path, when not set the current filename is used.
+ :arg start: Relative to this path,
+ when not set the current filename is used.
: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
@@ -44,7 +62,8 @@ def relpath(path, start=None):
"""
Returns the path relative to the current blend file using the "//" prefix.
- :arg start: Relative to this path, when not set the current filename is used.
+ :arg start: Relative to this path,
+ when not set the current filename is used.
:type start: string
"""
if not path.startswith("//"):
@@ -68,27 +87,28 @@ def is_subdir(path, directory):
def clean_name(name, replace="_"):
"""
- Returns a name with characters replaced that may cause problems under various circumstances, such as writing to a file.
+ Returns a name with characters replaced that
+ may cause problems under various circumstances,
+ such as writing to a file.
All characters besides A-Z/a-z, 0-9 are replaced with "_"
or the replace argument if defined.
"""
- unclean_chars = \
- "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\
- \x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\
- \x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\
- \x2e\x2f\x3a\x3b\x3c\x3d\x3e\x3f\x40\x5b\x5c\x5d\x5e\x60\x7b\
- \x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\
- \x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\
- \x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\
- \xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\
- \xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\
- \xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\
- \xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\
- \xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\
- \xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe"
-
- for ch in unclean_chars:
+ bad_chars = ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
+ "\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d"
+ "\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c"
+ "\x2e\x2f\x3a\x3b\x3c\x3d\x3e\x3f\x40\x5b\x5c\x5d\x5e\x60\x7b"
+ "\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a"
+ "\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99"
+ "\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8"
+ "\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+ "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6"
+ "\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5"
+ "\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4"
+ "\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3"
+ "\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe")
+
+ for ch in bad_chars:
name = name.replace(ch, replace)
return name
@@ -96,8 +116,9 @@ def clean_name(name, replace="_"):
def display_name(name):
"""
Creates a display string from name to be used menus and the user interface.
- Capitalize the first letter in all lowercase names, mixed case names are kept as is.
- Intended for use with filenames and module names.
+ Capitalize the first letter in all lowercase names,
+ mixed case names are kept as is. Intended for use with
+ filenames and module names.
"""
name_base = _os.path.splitext(name)[0]
@@ -115,9 +136,11 @@ def display_name(name):
def display_name_from_filepath(name):
"""
- Returns the path stripped of directort and extension, ensured to be utf8 compatible.
+ Returns the path stripped of directory and extension,
+ ensured to be utf8 compatible.
"""
- return _os.path.splitext(_os.path.basename(name))[0].encode("utf8", "replace").decode("utf8")
+ name = _os.path.splitext(basename(name))[0]
+ return name.encode("utf8", "replace").decode("utf8")
def resolve_ncase(path):
@@ -132,7 +155,8 @@ def resolve_ncase(path):
if not path or os.path.exists(path):
return path, True
- filename = os.path.basename(path) # filename may be a directory or a file
+ # filename may be a directory or a file
+ filename = os.path.basename(path)
dirpath = os.path.dirname(path)
suffix = path[:0] # "" but ensure byte/str match
@@ -180,7 +204,7 @@ def resolve_ncase(path):
def ensure_ext(filepath, ext, case_sensitive=False):
"""
- Return the path with the extension added its its not alredy set.
+ Return the path with the extension added if it is not already set.
:arg ext: The extension to check for.
:type ext: string
@@ -190,7 +214,9 @@ def ensure_ext(filepath, ext, case_sensitive=False):
import os
fn_base, fn_ext = os.path.splitext(filepath)
if fn_base and fn_ext:
- if (case_sensitive and ext == fn_ext) or (ext.lower() == fn_ext.lower()):
+ if ((case_sensitive and ext == fn_ext) or
+ (ext.lower() == fn_ext.lower())):
+
return filepath
else:
return fn_base + ext
@@ -228,6 +254,17 @@ def module_names(path, recursive=False):
modules.append((filename, fullpath))
if recursive:
for mod_name, mod_path in module_names(directory, True):
- modules.append(("%s.%s" % (filename, mod_name), mod_path))
+ modules.append(("%s.%s" % (filename, mod_name),
+ mod_path,
+ ))
return modules
+
+
+def basename(path):
+ """
+ Equivalent to os.path.basename, but skips a "//" suffix.
+
+ Use for Windows compatibility.
+ """
+ return _os.path.basename(path[2:] if path[:2] in {"//", b"//"} else path)
diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py
index 7c0d3d24cba..a6304378cc4 100644
--- a/release/scripts/modules/bpy/utils.py
+++ b/release/scripts/modules/bpy/utils.py
@@ -16,13 +16,33 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
"""
This module contains utility functions specific to blender but
not assosiated with blenders internal data.
"""
+__all__ = (
+ "blend_paths",
+ "keyconfig_set",
+ "load_scripts",
+ "modules_from_path",
+ "preset_find",
+ "preset_paths",
+ "refresh_script_paths",
+ "register_class",
+ "register_module",
+ "resource_path",
+ "script_paths",
+ "smpte_from_frame",
+ "smpte_from_seconds",
+ "unregister_class",
+ "unregister_module",
+ "user_resource",
+ "user_script_path",
+ )
+
from _bpy import register_class, unregister_class, blend_paths, resource_path
from _bpy import script_paths as _bpy_script_paths
from _bpy import user_resource as _user_resource
@@ -42,7 +62,8 @@ def _test_import(module_name, loaded_modules):
if module_name in loaded_modules:
return None
if "." in module_name:
- print("Ignoring '%s', can't import files containing multiple periods." % module_name)
+ print("Ignoring '%s', can't import files containing "
+ "multiple periods." % module_name)
return None
if use_time:
@@ -74,7 +95,8 @@ def modules_from_path(path, loaded_modules):
:arg path: this path is scanned for scripts and packages.
:type path: string
- :arg loaded_modules: already loaded module names, files matching these names will be ignored.
+ :arg loaded_modules: already loaded module names, files matching these
+ names will be ignored.
:type loaded_modules: set
:return: all loaded modules.
:rtype: list
@@ -97,13 +119,17 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
"""
Load scripts and run each modules register function.
- :arg reload_scripts: Causes all scripts to have their unregister method called before loading.
+ :arg reload_scripts: Causes all scripts to have their unregister method
+ called before loading.
:type reload_scripts: bool
- :arg refresh_scripts: only load scripts which are not already loaded as modules.
+ :arg refresh_scripts: only load scripts which are not already loaded
+ as modules.
:type refresh_scripts: bool
"""
use_time = _bpy.app.debug
+ prefs = _bpy.context.user_preferences
+
if use_time:
import time
t_main = time.time()
@@ -116,10 +142,11 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
if reload_scripts:
_bpy_types.TypeMap.clear()
- # just unload, dont change user defaults, this means we can sync to reload.
- # note that they will only actually reload of the modification time changes.
- # this `wont` work for packages so... its not perfect.
- for module_name in [ext.module for ext in _bpy.context.user_preferences.addons]:
+ # just unload, dont change user defaults, this means we can sync
+ # to reload. note that they will only actually reload of the
+ # modification time changes. This `wont` work for packages so...
+ # its not perfect.
+ for module_name in [ext.module for ext in prefs.addons]:
_addon_utils.disable(module_name, default_set=False)
def register_module_call(mod):
@@ -131,7 +158,9 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
import traceback
traceback.print_exc()
else:
- print("\nWarning! '%s' has no register function, this is now a requirement for registerable scripts." % mod.__file__)
+ print("\nWarning! '%s' has no register function, "
+ "this is now a requirement for registerable scripts." %
+ mod.__file__)
def unregister_module_call(mod):
unregister = getattr(mod, "unregister", None)
@@ -172,7 +201,8 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
if reload_scripts:
# module names -> modules
- _global_loaded_modules[:] = [_sys.modules[mod_name] for mod_name in _global_loaded_modules]
+ _global_loaded_modules[:] = [_sys.modules[mod_name]
+ for mod_name in _global_loaded_modules]
# loop over and unload all scripts
_global_loaded_modules.reverse()
@@ -201,7 +231,8 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
_addon_utils.reset_all(reload_scripts)
# run the active integration preset
- filepath = preset_find(_bpy.context.user_preferences.inputs.active_keyconfig, "keyconfig")
+ filepath = preset_find(prefs.inputs.active_keyconfig, "keyconfig")
+
if filepath:
keyconfig_set(filepath)
@@ -214,12 +245,16 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
# base scripts
-_scripts = _os.path.join(_os.path.dirname(__file__), _os.path.pardir, _os.path.pardir)
+_scripts = _os.path.join(_os.path.dirname(__file__),
+ _os.path.pardir,
+ _os.path.pardir,
+ )
_scripts = (_os.path.normpath(_scripts), )
def user_script_path():
- path = _bpy.context.user_preferences.filepaths.script_directory
+ prefs = _bpy.context.user_preferences
+ path = prefs.filepaths.script_directory
if path:
path = _os.path.normpath(path)
@@ -236,22 +271,25 @@ def script_paths(subdir=None, user_pref=True, all=False):
:type subdir: string
:arg user_pref: Include the user preference script path.
:type user_pref: bool
- :arg all: Include local, user and system paths rather just the paths blender uses.
+ :arg all: Include local, user and system paths rather just the paths
+ blender uses.
:type all: bool
:return: script paths.
:rtype: list
"""
scripts = list(_scripts)
+ prefs = _bpy.context.user_preferences
# add user scripts dir
if user_pref:
- user_script_path = _bpy.context.user_preferences.filepaths.script_directory
+ user_script_path = prefs.filepaths.script_directory
else:
user_script_path = None
if all:
# all possible paths
- base_paths = tuple(_os.path.join(resource_path(res), "scripts") for res in ('LOCAL', 'USER', 'SYSTEM'))
+ base_paths = tuple(_os.path.join(resource_path(res), "scripts")
+ for res in ('LOCAL', 'USER', 'SYSTEM'))
else:
# only paths blender uses
base_paths = _bpy_script_paths()
@@ -298,11 +336,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
@@ -419,7 +464,8 @@ def user_resource(type, path="", create=False):
:type type: string
:arg subdir: Optional subdirectory.
:type subdir: string
- :arg create: Treat the path as a directory and create it if its not existing.
+ :arg create: Treat the path as a directory and create
+ it if its not existing.
:type create: boolean
:return: a path.
:rtype: string
@@ -470,7 +516,8 @@ def register_module(module, verbose=False):
try:
register_class(cls)
except:
- print("bpy.utils.register_module(): failed to registering class %r" % cls)
+ print("bpy.utils.register_module(): "
+ "failed to registering class %r" % cls)
import traceback
traceback.print_exc()
if verbose:
@@ -488,7 +535,8 @@ def unregister_module(module, verbose=False):
try:
unregister_class(cls)
except:
- print("bpy.utils.unregister_module(): failed to unregistering class %r" % cls)
+ print("bpy.utils.unregister_module(): "
+ "failed to unregistering class %r" % cls)
import traceback
traceback.print_exc()
if verbose:
diff --git a/release/scripts/modules/bpy_extras/__init__.py b/release/scripts/modules/bpy_extras/__init__.py
index 06d41fa670e..d853d5fda10 100644
--- a/release/scripts/modules/bpy_extras/__init__.py
+++ b/release/scripts/modules/bpy_extras/__init__.py
@@ -16,7 +16,7 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
"""
Utility modules assosiated with the bpy module.
@@ -28,4 +28,4 @@ __all__ = (
"image_utils",
"mesh_utils",
"view3d_utils",
-)
+ )
diff --git a/release/scripts/modules/bpy_extras/image_utils.py b/release/scripts/modules/bpy_extras/image_utils.py
index f45f9c6f225..02959fae534 100644
--- a/release/scripts/modules/bpy_extras/image_utils.py
+++ b/release/scripts/modules/bpy_extras/image_utils.py
@@ -16,11 +16,12 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
__all__ = (
"load_image",
-)
+ )
+
# limited replacement for BPyImage.comprehensiveImageLoad
def load_image(imagepath,
@@ -32,8 +33,8 @@ def load_image(imagepath,
verbose=False,
):
"""
- Return an image from the file path with options to search multiple paths and
- return a placeholder if its not found.
+ Return an image from the file path with options to search multiple paths
+ and return a placeholder if its not found.
:arg filepath: The image filename
If a path precedes it, this will be searched as well.
@@ -50,13 +51,14 @@ def load_image(imagepath,
:type recursive: bool
:arg ncase_cmp: on non windows systems, find the correct case for the file.
:type ncase_cmp: bool
- :arg convert_callback: a function that takes an existing path and returns a new one.
- Use this when loading image formats blender may not support, the CONVERT_CALLBACK
- can take the path for a GIF (for example), convert it to a PNG and return the PNG's path.
+ :arg convert_callback: a function that takes an existing path and returns
+ a new one. Use this when loading image formats blender may not support,
+ the CONVERT_CALLBACK can take the path for a GIF (for example),
+ convert it to a PNG and return the PNG's path.
For formats blender can read, simply return the path that is given.
:type convert_callback: function
:return: an image or None
- :rtype: :class:`Image`
+ :rtype: :class:`bpy.types.Image`
"""
import os
import bpy
@@ -85,11 +87,15 @@ 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:
- ncase_variants = filepath_test, bpy.path.resolve_ncase(filepath_test)
+ ncase_variants = (filepath_test,
+ bpy.path.resolve_ncase(filepath_test),
+ )
else:
ncase_variants = (filepath_test, )
@@ -98,7 +104,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..3f6a3682e7c 100644
--- a/release/scripts/modules/bpy_extras/io_utils.py
+++ b/release/scripts/modules/bpy_extras/io_utils.py
@@ -16,12 +16,13 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
__all__ = (
"ExportHelper",
"ImportHelper",
"axis_conversion",
+ "axis_conversion_ensure",
"create_derived_objects",
"free_derived_objects",
"unpack_list",
@@ -30,15 +31,34 @@ __all__ = (
"path_reference_copy",
"path_reference_mode",
"unique_name"
-)
+ )
import bpy
from bpy.props import StringProperty, BoolProperty, EnumProperty
+def _check_axis_conversion(op):
+ if hasattr(op, "axis_forward") and hasattr(op, "axis_up"):
+ return axis_conversion_ensure(op,
+ "axis_forward",
+ "axis_up",
+ )
+ return False
+
+
class ExportHelper:
- filepath = StringProperty(name="File Path", description="Filepath used for exporting the file", maxlen=1024, default="", subtype='FILE_PATH')
- check_existing = BoolProperty(name="Check Existing", description="Check and warn on overwriting existing files", default=True, options={'HIDDEN'})
+ filepath = StringProperty(
+ name="File Path",
+ description="Filepath used for exporting the file",
+ maxlen=1024,
+ subtype='FILE_PATH',
+ )
+ check_existing = BoolProperty(
+ name="Check Existing",
+ description="Check and warn on overwriting existing files",
+ default=True,
+ options={'HIDDEN'},
+ )
# subclasses can override with decorator
# True == use ext, False == no ext, None == do nothing.
@@ -59,27 +79,39 @@ class ExportHelper:
return {'RUNNING_MODAL'}
def check(self, context):
- check_extension = self.check_extension
+ change_ext = False
+ change_axis = _check_axis_conversion(self)
- if check_extension is None:
- return False
+ check_extension = self.check_extension
- filepath = bpy.path.ensure_ext(self.filepath, self.filename_ext if check_extension else "")
+ if check_extension is not None:
+ filepath = bpy.path.ensure_ext(self.filepath,
+ self.filename_ext
+ if check_extension
+ else "")
- if filepath != self.filepath:
- self.filepath = filepath
- return True
+ if filepath != self.filepath:
+ self.filepath = filepath
+ change_ext = True
- return False
+ return (change_ext or change_axis)
class ImportHelper:
- filepath = StringProperty(name="File Path", description="Filepath used for importing the file", maxlen=1024, default="", subtype='FILE_PATH')
+ filepath = StringProperty(
+ name="File Path",
+ description="Filepath used for importing the file",
+ maxlen=1024,
+ subtype='FILE_PATH',
+ )
def invoke(self, context, event):
context.window_manager.fileselect_add(self)
return {'RUNNING_MODAL'}
+ def check(self, context):
+ return _check_axis_conversion(self)
+
# Axis conversion function, not pretty LUT
# use lookup tabes to convert between any axis
@@ -115,29 +147,75 @@ _axis_convert_matrix = (
# where all 4 values are or'd into a single value...
# (i1<<0 | i1<<3 | i1<<6 | i1<<9)
_axis_convert_lut = (
- {0x8C8, 0x4D0, 0x2E0, 0xAE8, 0x701, 0x511, 0x119, 0xB29, 0x682, 0x88A, 0x09A, 0x2A2, 0x80B, 0x413, 0x223, 0xA2B, 0x644, 0x454, 0x05C, 0xA6C, 0x745, 0x94D, 0x15D, 0x365},
- {0xAC8, 0x8D0, 0x4E0, 0x2E8, 0x741, 0x951, 0x159, 0x369, 0x702, 0xB0A, 0x11A, 0x522, 0xA0B, 0x813, 0x423, 0x22B, 0x684, 0x894, 0x09C, 0x2AC, 0x645, 0xA4D, 0x05D, 0x465},
- {0x4C8, 0x2D0, 0xAE0, 0x8E8, 0x681, 0x291, 0x099, 0x8A9, 0x642, 0x44A, 0x05A, 0xA62, 0x40B, 0x213, 0xA23, 0x82B, 0x744, 0x354, 0x15C, 0x96C, 0x705, 0x50D, 0x11D, 0xB25},
- {0x2C8, 0xAD0, 0x8E0, 0x4E8, 0x641, 0xA51, 0x059, 0x469, 0x742, 0x34A, 0x15A, 0x962, 0x20B, 0xA13, 0x823, 0x42B, 0x704, 0xB14, 0x11C, 0x52C, 0x685, 0x28D, 0x09D, 0x8A5},
- {0x708, 0xB10, 0x120, 0x528, 0x8C1, 0xAD1, 0x2D9, 0x4E9, 0x942, 0x74A, 0x35A, 0x162, 0x64B, 0xA53, 0x063, 0x46B, 0x804, 0xA14, 0x21C, 0x42C, 0x885, 0x68D, 0x29D, 0x0A5},
- {0xB08, 0x110, 0x520, 0x728, 0x941, 0x151, 0x359, 0x769, 0x802, 0xA0A, 0x21A, 0x422, 0xA4B, 0x053, 0x463, 0x66B, 0x884, 0x094, 0x29C, 0x6AC, 0x8C5, 0xACD, 0x2DD, 0x4E5},
- {0x508, 0x710, 0xB20, 0x128, 0x881, 0x691, 0x299, 0x0A9, 0x8C2, 0x4CA, 0x2DA, 0xAE2, 0x44B, 0x653, 0xA63, 0x06B, 0x944, 0x754, 0x35C, 0x16C, 0x805, 0x40D, 0x21D, 0xA25},
- {0x108, 0x510, 0x720, 0xB28, 0x801, 0x411, 0x219, 0xA29, 0x882, 0x08A, 0x29A, 0x6A2, 0x04B, 0x453, 0x663, 0xA6B, 0x8C4, 0x4D4, 0x2DC, 0xAEC, 0x945, 0x14D, 0x35D, 0x765},
- {0x748, 0x350, 0x160, 0x968, 0xAC1, 0x2D1, 0x4D9, 0x8E9, 0xA42, 0x64A, 0x45A, 0x062, 0x68B, 0x293, 0x0A3, 0x8AB, 0xA04, 0x214, 0x41C, 0x82C, 0xB05, 0x70D, 0x51D, 0x125},
- {0x948, 0x750, 0x360, 0x168, 0xB01, 0x711, 0x519, 0x129, 0xAC2, 0x8CA, 0x4DA, 0x2E2, 0x88B, 0x693, 0x2A3, 0x0AB, 0xA44, 0x654, 0x45C, 0x06C, 0xA05, 0x80D, 0x41D, 0x225},
- {0x348, 0x150, 0x960, 0x768, 0xA41, 0x051, 0x459, 0x669, 0xA02, 0x20A, 0x41A, 0x822, 0x28B, 0x093, 0x8A3, 0x6AB, 0xB04, 0x114, 0x51C, 0x72C, 0xAC5, 0x2CD, 0x4DD, 0x8E5},
- {0x148, 0x950, 0x760, 0x368, 0xA01, 0x811, 0x419, 0x229, 0xB02, 0x10A, 0x51A, 0x722, 0x08B, 0x893, 0x6A3, 0x2AB, 0xAC4, 0x8D4, 0x4DC, 0x2EC, 0xA45, 0x04D, 0x45D, 0x665},
- {0x688, 0x890, 0x0A0, 0x2A8, 0x4C1, 0x8D1, 0xAD9, 0x2E9, 0x502, 0x70A, 0xB1A, 0x122, 0x74B, 0x953, 0x163, 0x36B, 0x404, 0x814, 0xA1C, 0x22C, 0x445, 0x64D, 0xA5D, 0x065},
- {0x888, 0x090, 0x2A0, 0x6A8, 0x501, 0x111, 0xB19, 0x729, 0x402, 0x80A, 0xA1A, 0x222, 0x94B, 0x153, 0x363, 0x76B, 0x444, 0x054, 0xA5C, 0x66C, 0x4C5, 0x8CD, 0xADD, 0x2E5},
- {0x288, 0x690, 0x8A0, 0x0A8, 0x441, 0x651, 0xA59, 0x069, 0x4C2, 0x2CA, 0xADA, 0x8E2, 0x34B, 0x753, 0x963, 0x16B, 0x504, 0x714, 0xB1C, 0x12C, 0x405, 0x20D, 0xA1D, 0x825},
- {0x088, 0x290, 0x6A0, 0x8A8, 0x401, 0x211, 0xA19, 0x829, 0x442, 0x04A, 0xA5A, 0x662, 0x14B, 0x353, 0x763, 0x96B, 0x4C4, 0x2D4, 0xADC, 0x8EC, 0x505, 0x10D, 0xB1D, 0x725},
- {0x648, 0x450, 0x060, 0xA68, 0x2C1, 0x4D1, 0x8D9, 0xAE9, 0x282, 0x68A, 0x89A, 0x0A2, 0x70B, 0x513, 0x123, 0xB2B, 0x204, 0x414, 0x81C, 0xA2C, 0x345, 0x74D, 0x95D, 0x165},
- {0xA48, 0x650, 0x460, 0x068, 0x341, 0x751, 0x959, 0x169, 0x2C2, 0xACA, 0x8DA, 0x4E2, 0xB0B, 0x713, 0x523, 0x12B, 0x284, 0x694, 0x89C, 0x0AC, 0x205, 0xA0D, 0x81D, 0x425},
- {0x448, 0x050, 0xA60, 0x668, 0x281, 0x091, 0x899, 0x6A9, 0x202, 0x40A, 0x81A, 0xA22, 0x50B, 0x113, 0xB23, 0x72B, 0x344, 0x154, 0x95C, 0x76C, 0x2C5, 0x4CD, 0x8DD, 0xAE5},
- {0x048, 0xA50, 0x660, 0x468, 0x201, 0xA11, 0x819, 0x429, 0x342, 0x14A, 0x95A, 0x762, 0x10B, 0xB13, 0x723, 0x52B, 0x2C4, 0xAD4, 0x8DC, 0x4EC, 0x285, 0x08D, 0x89D, 0x6A5},
- {0x808, 0xA10, 0x220, 0x428, 0x101, 0xB11, 0x719, 0x529, 0x142, 0x94A, 0x75A, 0x362, 0x8CB, 0xAD3, 0x2E3, 0x4EB, 0x044, 0xA54, 0x65C, 0x46C, 0x085, 0x88D, 0x69D, 0x2A5},
- {0xA08, 0x210, 0x420, 0x828, 0x141, 0x351, 0x759, 0x969, 0x042, 0xA4A, 0x65A, 0x462, 0xACB, 0x2D3, 0x4E3, 0x8EB, 0x084, 0x294, 0x69C, 0x8AC, 0x105, 0xB0D, 0x71D, 0x525},
- {0x408, 0x810, 0xA20, 0x228, 0x081, 0x891, 0x699, 0x2A9, 0x102, 0x50A, 0x71A, 0xB22, 0x4CB, 0x8D3, 0xAE3, 0x2EB, 0x144, 0x954, 0x75C, 0x36C, 0x045, 0x44D, 0x65D, 0xA65},
+ {0x8C8, 0x4D0, 0x2E0, 0xAE8, 0x701, 0x511, 0x119, 0xB29, 0x682, 0x88A,
+ 0x09A, 0x2A2, 0x80B, 0x413, 0x223, 0xA2B, 0x644, 0x454, 0x05C, 0xA6C,
+ 0x745, 0x94D, 0x15D, 0x365},
+ {0xAC8, 0x8D0, 0x4E0, 0x2E8, 0x741, 0x951, 0x159, 0x369, 0x702, 0xB0A,
+ 0x11A, 0x522, 0xA0B, 0x813, 0x423, 0x22B, 0x684, 0x894, 0x09C, 0x2AC,
+ 0x645, 0xA4D, 0x05D, 0x465},
+ {0x4C8, 0x2D0, 0xAE0, 0x8E8, 0x681, 0x291, 0x099, 0x8A9, 0x642, 0x44A,
+ 0x05A, 0xA62, 0x40B, 0x213, 0xA23, 0x82B, 0x744, 0x354, 0x15C, 0x96C,
+ 0x705, 0x50D, 0x11D, 0xB25},
+ {0x2C8, 0xAD0, 0x8E0, 0x4E8, 0x641, 0xA51, 0x059, 0x469, 0x742, 0x34A,
+ 0x15A, 0x962, 0x20B, 0xA13, 0x823, 0x42B, 0x704, 0xB14, 0x11C, 0x52C,
+ 0x685, 0x28D, 0x09D, 0x8A5},
+ {0x708, 0xB10, 0x120, 0x528, 0x8C1, 0xAD1, 0x2D9, 0x4E9, 0x942, 0x74A,
+ 0x35A, 0x162, 0x64B, 0xA53, 0x063, 0x46B, 0x804, 0xA14, 0x21C, 0x42C,
+ 0x885, 0x68D, 0x29D, 0x0A5},
+ {0xB08, 0x110, 0x520, 0x728, 0x941, 0x151, 0x359, 0x769, 0x802, 0xA0A,
+ 0x21A, 0x422, 0xA4B, 0x053, 0x463, 0x66B, 0x884, 0x094, 0x29C, 0x6AC,
+ 0x8C5, 0xACD, 0x2DD, 0x4E5},
+ {0x508, 0x710, 0xB20, 0x128, 0x881, 0x691, 0x299, 0x0A9, 0x8C2, 0x4CA,
+ 0x2DA, 0xAE2, 0x44B, 0x653, 0xA63, 0x06B, 0x944, 0x754, 0x35C, 0x16C,
+ 0x805, 0x40D, 0x21D, 0xA25},
+ {0x108, 0x510, 0x720, 0xB28, 0x801, 0x411, 0x219, 0xA29, 0x882, 0x08A,
+ 0x29A, 0x6A2, 0x04B, 0x453, 0x663, 0xA6B, 0x8C4, 0x4D4, 0x2DC, 0xAEC,
+ 0x945, 0x14D, 0x35D, 0x765},
+ {0x748, 0x350, 0x160, 0x968, 0xAC1, 0x2D1, 0x4D9, 0x8E9, 0xA42, 0x64A,
+ 0x45A, 0x062, 0x68B, 0x293, 0x0A3, 0x8AB, 0xA04, 0x214, 0x41C, 0x82C,
+ 0xB05, 0x70D, 0x51D, 0x125},
+ {0x948, 0x750, 0x360, 0x168, 0xB01, 0x711, 0x519, 0x129, 0xAC2, 0x8CA,
+ 0x4DA, 0x2E2, 0x88B, 0x693, 0x2A3, 0x0AB, 0xA44, 0x654, 0x45C, 0x06C,
+ 0xA05, 0x80D, 0x41D, 0x225},
+ {0x348, 0x150, 0x960, 0x768, 0xA41, 0x051, 0x459, 0x669, 0xA02, 0x20A,
+ 0x41A, 0x822, 0x28B, 0x093, 0x8A3, 0x6AB, 0xB04, 0x114, 0x51C, 0x72C,
+ 0xAC5, 0x2CD, 0x4DD, 0x8E5},
+ {0x148, 0x950, 0x760, 0x368, 0xA01, 0x811, 0x419, 0x229, 0xB02, 0x10A,
+ 0x51A, 0x722, 0x08B, 0x893, 0x6A3, 0x2AB, 0xAC4, 0x8D4, 0x4DC, 0x2EC,
+ 0xA45, 0x04D, 0x45D, 0x665},
+ {0x688, 0x890, 0x0A0, 0x2A8, 0x4C1, 0x8D1, 0xAD9, 0x2E9, 0x502, 0x70A,
+ 0xB1A, 0x122, 0x74B, 0x953, 0x163, 0x36B, 0x404, 0x814, 0xA1C, 0x22C,
+ 0x445, 0x64D, 0xA5D, 0x065},
+ {0x888, 0x090, 0x2A0, 0x6A8, 0x501, 0x111, 0xB19, 0x729, 0x402, 0x80A,
+ 0xA1A, 0x222, 0x94B, 0x153, 0x363, 0x76B, 0x444, 0x054, 0xA5C, 0x66C,
+ 0x4C5, 0x8CD, 0xADD, 0x2E5},
+ {0x288, 0x690, 0x8A0, 0x0A8, 0x441, 0x651, 0xA59, 0x069, 0x4C2, 0x2CA,
+ 0xADA, 0x8E2, 0x34B, 0x753, 0x963, 0x16B, 0x504, 0x714, 0xB1C, 0x12C,
+ 0x405, 0x20D, 0xA1D, 0x825},
+ {0x088, 0x290, 0x6A0, 0x8A8, 0x401, 0x211, 0xA19, 0x829, 0x442, 0x04A,
+ 0xA5A, 0x662, 0x14B, 0x353, 0x763, 0x96B, 0x4C4, 0x2D4, 0xADC, 0x8EC,
+ 0x505, 0x10D, 0xB1D, 0x725},
+ {0x648, 0x450, 0x060, 0xA68, 0x2C1, 0x4D1, 0x8D9, 0xAE9, 0x282, 0x68A,
+ 0x89A, 0x0A2, 0x70B, 0x513, 0x123, 0xB2B, 0x204, 0x414, 0x81C, 0xA2C,
+ 0x345, 0x74D, 0x95D, 0x165},
+ {0xA48, 0x650, 0x460, 0x068, 0x341, 0x751, 0x959, 0x169, 0x2C2, 0xACA,
+ 0x8DA, 0x4E2, 0xB0B, 0x713, 0x523, 0x12B, 0x284, 0x694, 0x89C, 0x0AC,
+ 0x205, 0xA0D, 0x81D, 0x425},
+ {0x448, 0x050, 0xA60, 0x668, 0x281, 0x091, 0x899, 0x6A9, 0x202, 0x40A,
+ 0x81A, 0xA22, 0x50B, 0x113, 0xB23, 0x72B, 0x344, 0x154, 0x95C, 0x76C,
+ 0x2C5, 0x4CD, 0x8DD, 0xAE5},
+ {0x048, 0xA50, 0x660, 0x468, 0x201, 0xA11, 0x819, 0x429, 0x342, 0x14A,
+ 0x95A, 0x762, 0x10B, 0xB13, 0x723, 0x52B, 0x2C4, 0xAD4, 0x8DC, 0x4EC,
+ 0x285, 0x08D, 0x89D, 0x6A5},
+ {0x808, 0xA10, 0x220, 0x428, 0x101, 0xB11, 0x719, 0x529, 0x142, 0x94A,
+ 0x75A, 0x362, 0x8CB, 0xAD3, 0x2E3, 0x4EB, 0x044, 0xA54, 0x65C, 0x46C,
+ 0x085, 0x88D, 0x69D, 0x2A5},
+ {0xA08, 0x210, 0x420, 0x828, 0x141, 0x351, 0x759, 0x969, 0x042, 0xA4A,
+ 0x65A, 0x462, 0xACB, 0x2D3, 0x4E3, 0x8EB, 0x084, 0x294, 0x69C, 0x8AC,
+ 0x105, 0xB0D, 0x71D, 0x525},
+ {0x408, 0x810, 0xA20, 0x228, 0x081, 0x891, 0x699, 0x2A9, 0x102, 0x50A,
+ 0x71A, 0xB22, 0x4CB, 0x8D3, 0xAE3, 0x2EB, 0x144, 0x954, 0x75C, 0x36C,
+ 0x045, 0x44D, 0x65D, 0xA65},
)
_axis_convert_num = {'X': 0, 'Y': 1, 'Z': 2, '-X': 3, '-Y': 4, '-Z': 5}
@@ -154,17 +232,61 @@ 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()
- value = reduce(int.__or__, (_axis_convert_num[a] << (i * 3) for i, a in enumerate((from_forward, from_up, to_forward, to_up))))
+ 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:`bpy.types.Operator.check`.
+
+ :arg operator: the operator to access axis attributes from.
+ :type operator: :class:`bpy.types.Operator`
+ :arg forward_attr: attribute storing the forward axis
+ :type forward_attr: string
+ :arg up_attr: attribute storing the up axis
+ :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()
+# return a tuple (free, object list), free is True if memory should be freed
+# later with free_derived_objects()
def create_derived_objects(scene, ob):
- if ob.parent and ob.parent.dupli_type != 'NONE':
+ if ob.parent and ob.parent.dupli_type in {'VERTS', 'FACES'}:
return False, None
if ob.dupli_type != 'NONE':
@@ -210,31 +332,45 @@ path_reference_mode = EnumProperty(
description="Method used to reference paths",
items=(('AUTO', "Auto", "Use Relative paths with subdirectories only"),
('ABSOLUTE', "Absolute", "Always write absolute paths"),
- ('RELATIVE', "Relative", "Always write relative patsh (where possible)"),
- ('MATCH', "Match", "Match Absolute/Relative setting with input path"),
+ ('RELATIVE', "Relative", "Always write relative patsh "
+ "(where possible)"),
+ ('MATCH', "Match", "Match Absolute/Relative "
+ "setting with input path"),
('STRIP', "Strip Path", "Filename only"),
- ('COPY', "Copy", "copy the file to the destination path (or subdirectory)"),
+ ('COPY', "Copy", "copy the file to the destination path "
+ "(or subdirectory)"),
),
default='AUTO'
)
-def path_reference(filepath, base_src, base_dst, mode='AUTO', copy_subdir="", copy_set=None):
+def path_reference(filepath,
+ base_src,
+ base_dst,
+ mode='AUTO',
+ copy_subdir="",
+ copy_set=None,
+ ):
"""
Return a filepath relative to a destination directory, for use with
exporters.
- :arg filepath: the file path to return, supporting blenders relative '//' prefix.
+ :arg filepath: the file path to return,
+ supporting blenders relative '//' prefix.
:type filepath: string
- :arg base_src: the directory the *filepath* is relative too (normally the blend file).
+ :arg base_src: the directory the *filepath* is relative too
+ (normally the blend file).
:type base_src: string
- :arg base_dst: the directory the *filepath* will be referenced from (normally the export path).
+ :arg base_dst: the directory the *filepath* will be referenced from
+ (normally the export path).
:type base_dst: string
- :arg mode: the method used get the path in ['AUTO', 'ABSOLUTE', 'RELATIVE', 'MATCH', 'STRIP', 'COPY']
+ :arg mode: the method used get the path in
+ ['AUTO', 'ABSOLUTE', 'RELATIVE', 'MATCH', 'STRIP', 'COPY']
:type mode: string
:arg copy_subdir: the subdirectory of *base_dst* to use when mode='COPY'.
:type copy_subdir: string
- :arg copy_set: collect from/to pairs when mode='COPY', pass to *path_reference_copy* when exportign is done.
+ :arg copy_set: collect from/to pairs when mode='COPY',
+ pass to *path_reference_copy* when exportign is done.
:type copy_set: set
:return: the new filepath.
:rtype: string
@@ -243,12 +379,14 @@ def path_reference(filepath, base_src, base_dst, mode='AUTO', copy_subdir="", co
is_relative = filepath.startswith("//")
filepath_abs = os.path.normpath(bpy.path.abspath(filepath, base_src))
- if mode in ('ABSOLUTE', 'RELATIVE', 'STRIP'):
+ if mode in {'ABSOLUTE', 'RELATIVE', 'STRIP'}:
pass
elif mode == 'MATCH':
mode = 'RELATIVE' if is_relative else 'ABSOLUTE'
elif mode == 'AUTO':
- mode = 'RELATIVE' if bpy.path.is_subdir(filepath, base_dst) else 'ABSOLUTE'
+ mode = ('RELATIVE'
+ if bpy.path.is_subdir(filepath, base_dst)
+ else 'ABSOLUTE')
elif mode == 'COPY':
if copy_subdir:
subdir_abs = os.path.join(os.path.normpath(base_dst), copy_subdir)
@@ -262,7 +400,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
@@ -301,7 +439,7 @@ def path_reference_copy(copy_set, report=print):
shutil.copy(file_src, file_dst)
-def unique_name(key, name, name_dict, name_max=-1, clean_func=None):
+def unique_name(key, name, name_dict, name_max=-1, clean_func=None, sep="."):
"""
Helper function for storing unique names which may have special characters
stripped and restricted to a maximum length.
@@ -318,22 +456,30 @@ def unique_name(key, name, name_dict, name_max=-1, clean_func=None):
:type name_dict: dict
:arg clean_func: Function to call on *name* before creating a unique value.
:type clean_func: function
+ :arg sep: Separator to use when between the name and a number when a
+ duplicate name is found.
+ :type sep: string
"""
name_new = name_dict.get(key)
if name_new is None:
count = 1
name_dict_values = name_dict.values()
- name_new = name_new_orig = name if clean_func is None else clean_func(name)
+ name_new = name_new_orig = (name if clean_func is None
+ else clean_func(name))
if name_max == -1:
while name_new in name_dict_values:
- name_new = "%s.%03d" % (name_new_orig, count)
+ name_new = "%s%s%03d" % (name_new_orig, sep, count)
count += 1
else:
name_new = name_new[:name_max]
while name_new in name_dict_values:
count_str = "%03d" % count
- name_new = "%.*s.%s" % (name_max - (len(count_str) + 1), name_new_orig, count_str)
+ name_new = "%.*s%s%s" % (name_max - (len(count_str) + 1),
+ name_new_orig,
+ sep,
+ count_str,
+ )
count += 1
name_dict[key] = name_new
diff --git a/release/scripts/modules/bpy_extras/mesh_utils.py b/release/scripts/modules/bpy_extras/mesh_utils.py
index b6d8a1fcf16..7bc6dae3cc6 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,7 +25,9 @@ __all__ = (
"edge_loops_from_faces",
"edge_loops_from_edges",
"ngon_tesselate",
-)
+ "face_random_points",
+ )
+
def mesh_linked_faces(mesh):
"""
@@ -33,7 +35,7 @@ def mesh_linked_faces(mesh):
other mesh elements within 1 mesh datablock.
:arg mesh: the mesh used to group with.
- :type mesh: :class:`Mesh`
+ :type mesh: :class:`bpy.types.Mesh`
:return: lists of lists containing faces.
:rtype: list
"""
@@ -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=()):
@@ -122,9 +125,9 @@ def edge_loops_from_faces(mesh, faces=None, seams=()):
[[(0, 1), (4, 8), (3, 8)], ...]
:arg mesh: the mesh used to get edge loops from.
- :type mesh: :class:`Mesh`
+ :type mesh: :class:`bpy.types.Mesh`
:arg faces: optional face list to only use some of the meshes faces.
- :type faces: :class:`MeshFaces`, sequence or or NoneType
+ :type faces: :class:`bpy.types.MeshFaces`, sequence or or NoneType
:return: return a list of edge vertex index lists.
:rtype: list
"""
@@ -167,8 +170,8 @@ def edge_loops_from_faces(mesh, faces=None, seams=()):
# from knowing the last 2, look for th next.
ed_adj = edges[context_loop[-1]]
if len(ed_adj) != 2:
-
- if other_dir and flipped == False: # the original edge had 2 other edges
+ # the original edge had 2 other edges
+ if other_dir and flipped == False:
flipped = True # only flip the list once
context_loop.reverse()
ed_adj[:] = []
@@ -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[:]
@@ -258,15 +259,18 @@ def edge_loops_from_edges(mesh, edges=None):
def ngon_tesselate(from_data, indices, fix_loops=True):
'''
- Takes a polyline of indices (fgon)
- and returns a list of face indicie lists.
- Designed to be used for importers that need indices for an fgon to create from existing verts.
+ Takes a polyline of indices (fgon) and returns a list of face
+ indicie lists. Designed to be used for importers that need indices for an
+ fgon to create from existing verts.
from_data: either a mesh, or a list/tuple of vectors.
- indices: a list of indices to use this list is the ordered closed polyline to fill, and can be a subset of the data given.
- fix_loops: If this is enabled polylines that use loops to make multiple polylines are delt with correctly.
+ indices: a list of indices to use this list is the ordered closed polyline
+ to fill, and can be a subset of the data given.
+ 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
@@ -274,7 +278,8 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
return []
def mlen(co):
- return abs(co[0]) + abs(co[1]) + abs(co[2]) # manhatten length of a vector, faster then length
+ # manhatten length of a vector, faster then length
+ return abs(co[0]) + abs(co[1]) + abs(co[2])
def vert_treplet(v, i):
return v, vector_to_tuple(v, 6), i, mlen(v)
@@ -285,31 +290,34 @@ 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
'''
- if type(from_data) in (tuple, list):
+ if type(from_data) in {tuple, list}:
verts = [Vector(from_data[i]) for ii, i in enumerate(indices)]
else:
verts = [from_data.vertices[i].co for ii, i in enumerate(indices)]
- for i in range(len(verts) - 1, 0, -1): # same as reversed(xrange(1, len(verts))):
+ # same as reversed(range(1, len(verts))):
+ for i in range(len(verts) - 1, 0, -1):
if verts[i][1] == verts[i - 1][0]:
verts.pop(i - 1)
- fill = fill_polygon([verts])
+ fill = tesselate_polygon([verts])
else:
'''
- Seperate this loop into multiple loops be finding edges that are used twice
- This is used by lightwave LWO files a lot
+ Seperate this loop into multiple loops be finding edges that are
+ used twice. This is used by lightwave LWO files a lot
'''
- if type(from_data) in (tuple, list):
- verts = [vert_treplet(Vector(from_data[i]), ii) for ii, i in enumerate(indices)]
+ if type(from_data) in {tuple, list}:
+ verts = [vert_treplet(Vector(from_data[i]), ii)
+ for ii, i in enumerate(indices)]
else:
- verts = [vert_treplet(from_data.vertices[i].co, ii) for ii, i in enumerate(indices)]
+ verts = [vert_treplet(from_data.vertices[i].co, ii)
+ for ii, i in enumerate(indices)]
edges = [(i, i - 1) for i in range(len(verts))]
if edges:
@@ -418,7 +426,7 @@ def ngon_tesselate(from_data, indices, fix_loops=True):
# See if its flipped the wrong way.
flip = None
for fi in fill:
- if flip != None:
+ if flip is not None:
break
for i, vi in enumerate(fi):
if vi == 0 and fi[i - 1] == 1:
@@ -433,3 +441,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:`bpy.types.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/object_utils.py b/release/scripts/modules/bpy_extras/object_utils.py
index 51a8d4b5e23..3081e6f172e 100644
--- a/release/scripts/modules/bpy_extras/object_utils.py
+++ b/release/scripts/modules/bpy_extras/object_utils.py
@@ -16,12 +16,12 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
__all__ = (
"add_object_align_init",
"object_data_add",
-)
+ )
import bpy
@@ -33,48 +33,55 @@ def add_object_align_init(context, operator):
Return a matrix using the operator settings and view context.
:arg context: The context to use.
- :type context: :class:`Context`
+ :type context: :class:`bpy.types.Context`
:arg operator: The operator, checked for location and rotation properties.
- :type operator: :class:`Operator`
+ :type operator: :class:`bpy.types.Operator`
:return: the matrix from the context and settings.
- :rtype: :class:`Matrix`
+ :rtype: :class:`mathutils.Matrix`
"""
+
+ from mathutils import Matrix, Vector, Euler
+ properties = operator.properties if operator is not None else None
+
space_data = context.space_data
if space_data.type != 'VIEW_3D':
space_data = None
# location
- if operator and operator.properties.is_property_set("location"):
- location = mathutils.Matrix.Translation(mathutils.Vector(operator.properties.location))
+ if operator and properties.is_property_set("location"):
+ location = Matrix.Translation(Vector(properties.location))
else:
if space_data: # local view cursor is detected below
- location = mathutils.Matrix.Translation(space_data.cursor_location)
+ location = Matrix.Translation(space_data.cursor_location)
else:
- location = mathutils.Matrix.Translation(context.scene.cursor_location)
+ location = Matrix.Translation(context.scene.cursor_location)
if operator:
- operator.properties.location = location.to_translation()
+ properties.location = location.to_translation()
# rotation
view_align = (context.user_preferences.edit.object_align == 'VIEW')
view_align_force = False
if operator:
- if operator.properties.is_property_set("view_align"):
+ if properties.is_property_set("view_align"):
view_align = view_align_force = operator.view_align
else:
- operator.properties.view_align = view_align
+ properties.view_align = view_align
- if operator and operator.properties.is_property_set("rotation") and not view_align_force:
- rotation = mathutils.Euler(operator.properties.rotation).to_matrix().to_4x4()
+ if operator and (properties.is_property_set("rotation") and
+ not view_align_force):
+
+ rotation = Euler(properties.rotation).to_matrix().to_4x4()
else:
if view_align and space_data:
- rotation = space_data.region_3d.view_matrix.to_3x3().inverted().to_4x4()
+ rotation = space_data.region_3d.view_matrix.to_3x3().inverted()
+ rotation.resize_4x4()
else:
rotation = mathutils.Matrix()
# set the operator properties
if operator:
- operator.properties.rotation = rotation.to_euler()
+ properties.rotation = rotation.to_euler()
return location * rotation
@@ -85,13 +92,13 @@ def object_data_add(context, obdata, operator=None):
location, rotation and layer.
:arg context: The context to use.
- :type context: :class:`Context`
+ :type context: :class:`bpy.types.Context`
:arg obdata: the data used for the new object.
:type obdata: valid object data type or None.
:arg operator: The operator, checked for location and rotation properties.
- :type operator: :class:`Operator`
+ :type operator: :class:`bpy.types.Operator`
:return: the newly created object in the scene.
- :rtype: :class:`ObjectBase`
+ :rtype: :class:`bpy.types.ObjectBase`
"""
scene = context.scene
@@ -114,14 +121,18 @@ def object_data_add(context, obdata, operator=None):
# XXX
# caused because entering editmodedoes not add a empty undo slot!
if context.user_preferences.edit.use_enter_edit_mode:
- if not (obj_act and obj_act.mode == 'EDIT' and obj_act.type == obj_new.type):
+ if not (obj_act and
+ obj_act.mode == 'EDIT' and
+ obj_act.type == obj_new.type):
+
_obdata = bpy.data.meshes.new(obdata.name)
obj_act = bpy.data.objects.new(_obdata.name, _obdata)
obj_act.matrix_world = obj_new.matrix_world
scene.objects.link(obj_act)
scene.objects.active = obj_act
bpy.ops.object.mode_set(mode='EDIT')
- bpy.ops.ed.undo_push(message="Enter Editmode") # need empty undo step
+ # need empty undo step
+ bpy.ops.ed.undo_push(message="Enter Editmode")
# XXX
if obj_act and obj_act.mode == 'EDIT' and obj_act.type == obj_new.type:
diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py
index 45f537ebd2f..c18a74bbb09 100644
--- a/release/scripts/modules/bpy_extras/view3d_utils.py
+++ b/release/scripts/modules/bpy_extras/view3d_utils.py
@@ -16,14 +16,14 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
__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):
"""
@@ -31,14 +31,14 @@ def region_2d_to_vector_3d(region, rv3d, coord):
coordinate.
:arg region: region of the 3D viewport, typically bpy.context.region.
- :type region: :class:`Region`
+ :type region: :class:`bpy.types.Region`
:arg rv3d: 3D region data, typically bpy.context.space_data.region_3d.
- :type rv3d: :class:`RegionView3D`
+ :type rv3d: :class:`bpy.types.RegionView3D`
:arg coord: 2d coordinates relative to the region:
(event.mouse_region_x, event.mouse_region_y) for example.
:type coord: 2d vector
:return: normalized 3d vector.
- :rtype: :class:`Vector`
+ :rtype: :class:`mathutils.Vector`
"""
from mathutils import Vector
@@ -48,13 +48,13 @@ 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]) + \
- (out[2] * persinv[2][3]) + persinv[3][3]
+ w = ((out[0] * persinv[0][3]) +
+ (out[1] * persinv[1][3]) +
+ (out[2] * persinv[2][3]) + persinv[3][3])
- return ((out * persinv) / w) - rv3d.view_matrix.inverted()[3].xyz
+ return ((persinv * out) / w) - rv3d.view_matrix.inverted()[3].xyz
else:
return rv3d.view_matrix.inverted()[2].xyz.normalized()
@@ -65,9 +65,9 @@ def region_2d_to_location_3d(region, rv3d, coord, depth_location):
*depth_location*.
:arg region: region of the 3D viewport, typically bpy.context.region.
- :type region: :class:`Region`
+ :type region: :class:`bpy.types.Region`
:arg rv3d: 3D region data, typically bpy.context.space_data.region_3d.
- :type rv3d: :class:`RegionView3D`
+ :type rv3d: :class:`bpy.types.RegionView3D`
:arg coord: 2d coordinates relative to the region;
(event.mouse_region_x, event.mouse_region_y) for example.
:type coord: 2d vector
@@ -75,7 +75,7 @@ def region_2d_to_location_3d(region, rv3d, coord, depth_location):
there is no defined depth with a 2d region input.
:type depth_location: 3d vector
:return: normalized 3d vector.
- :rtype: :class:`Vector`
+ :rtype: :class:`mathutils.Vector`
"""
from mathutils import Vector
from mathutils.geometry import intersect_point_line
@@ -90,15 +90,23 @@ def region_2d_to_location_3d(region, rv3d, coord, depth_location):
origin_start = rv3d.view_matrix.inverted()[3].to_3d()
origin_end = origin_start + coord_vec
view_vec = rv3d.view_matrix.inverted()[2]
- return intersect_line_plane(origin_start, origin_end, depth_location, view_vec, 1)
+ return intersect_line_plane(origin_start,
+ origin_end,
+ depth_location,
+ view_vec, 1,
+ )
else:
dx = (2.0 * coord[0] / region.width) - 1.0
dy = (2.0 * coord[1] / region.height) - 1.0
persinv = persmat.inverted()
viewinv = rv3d.view_matrix.inverted()
- origin_start = (persinv[0].xyz * dx) + (persinv[1].xyz * dy) + viewinv[3].xyz
+ origin_start = ((persinv[0].xyz * dx) +
+ (persinv[1].xyz * dy) + viewinv[3].xyz)
origin_end = origin_start + coord_vec
- return intersect_point_line(depth_location, origin_start, origin_end)[0]
+ return intersect_point_line(depth_location,
+ origin_start,
+ origin_end,
+ )[0]
def location_3d_to_region_2d(region, rv3d, coord):
@@ -106,15 +114,17 @@ def location_3d_to_region_2d(region, rv3d, coord):
Return the *region* relative 2d location of a 3d position.
:arg region: region of the 3D viewport, typically bpy.context.region.
- :type region: :class:`Region`
+ :type region: :class:`bpy.types.Region`
:arg rv3d: 3D region data, typically bpy.context.space_data.region_3d.
- :type rv3d: :class:`RegionView3D`
+ :type rv3d: :class:`bpy.types.RegionView3D`
:arg coord: 3d worldspace location.
:type coord: 3d vector
:return: 2d location
- :rtype: :class:`Vector`
+ :rtype: :class:`mathutils.Vector`
"""
- prj = Vector((coord[0], coord[1], coord[2], 1.0)) * rv3d.perspective_matrix
+ from mathutils import Vector
+
+ prj = rv3d.perspective_matrix * Vector((coord[0], coord[1], coord[2], 1.0))
if prj.w > 0.0:
width_half = region.width / 2.0
height_half = region.height / 2.0
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 3c1b454e72e..101416f4943 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
@@ -58,7 +57,7 @@ class Library(bpy_types.ID):
"curves", "grease_pencil", "groups", "images", \
"lamps", "lattices", "materials", "metaballs", \
"meshes", "node_groups", "objects", "scenes", \
- "sounds", "textures", "texts", "fonts", "worlds"
+ "sounds", "speakers", "textures", "texts", "fonts", "worlds"
return tuple(id_block for attr in attr_links for id_block in getattr(bpy.data, attr) if id_block.library == self)
@@ -144,19 +143,22 @@ class _GenericBone:
def x_axis(self):
""" Vector pointing down the x-axis of the bone.
"""
- return Vector((1.0, 0.0, 0.0)) * self.matrix.to_3x3()
+ from mathutils import Vector
+ return self.matrix.to_3x3() * Vector((1.0, 0.0, 0.0))
@property
def y_axis(self):
""" Vector pointing down the x-axis of the bone.
"""
- return Vector((0.0, 1.0, 0.0)) * self.matrix.to_3x3()
+ from mathutils import Vector
+ return self.matrix.to_3x3() * Vector((0.0, 1.0, 0.0))
@property
def z_axis(self):
""" Vector pointing down the x-axis of the bone.
"""
- return Vector((0.0, 0.0, 1.0)) * self.matrix.to_3x3()
+ from mathutils import Vector
+ return self.matrix.to_3x3() * Vector((0.0, 0.0, 1.0))
@property
def basename(self):
@@ -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
@@ -285,16 +287,16 @@ class EditBone(StructRNA, _GenericBone, metaclass=StructMetaPropGroup):
Transform the the bones head, tail, roll and envalope (when the matrix has a scale component).
:arg matrix: 3x3 or 4x4 transformation matrix.
- :type matrix: :class:`Matrix`
+ :type matrix: :class:`mathutils.Matrix`
:arg scale: Scale the bone envalope by the matrix.
:type scale: bool
:arg roll: Correct the roll to point in the same relative direction to the head and tail.
:type roll: bool
"""
from mathutils import Vector
- z_vec = Vector((0.0, 0.0, 1.0)) * self.matrix.to_3x3()
- self.tail = self.tail * matrix
- self.head = self.head * matrix
+ z_vec = self.matrix.to_3x3() * Vector((0.0, 0.0, 1.0))
+ self.tail = matrix * self.tail
+ self.head = matrix * self.head
if scale:
scalar = matrix.median_scale
@@ -302,7 +304,7 @@ class EditBone(StructRNA, _GenericBone, metaclass=StructMetaPropGroup):
self.tail_radius *= scalar
if roll:
- self.align_roll(z_vec * matrix)
+ self.align_roll(matrix * z_vec)
def ord_ind(i1, i2):
@@ -409,6 +411,16 @@ class Text(bpy_types.ID):
TypeMap = {}
+class Sound(bpy_types.ID):
+ __slots__ = ()
+
+ @property
+ def factory(self):
+ """The aud.Factory object of the sound."""
+ import aud
+ return aud._sound_from_pointer(self.as_pointer())
+
+
class RNAMeta(type):
def __new__(cls, name, bases, classdict, **args):
result = type.__new__(cls, name, bases, classdict)
diff --git a/release/scripts/modules/bpyml.py b/release/scripts/modules/bpyml.py
index fdf5172a0b3..42d2bf94fba 100644
--- a/release/scripts/modules/bpyml.py
+++ b/release/scripts/modules/bpyml.py
@@ -120,7 +120,7 @@ def fromxml(data):
py_item = (xml_node.tagName, _fromxml_kwargs(xml_node), [])
#_fromxml_iter(py_item, xml_node.childNodes)
for xml_node_child in xml_node.childNodes:
- if xml_node_child.nodeType not in (xml_node_child.TEXT_NODE, xml_node_child.COMMENT_NODE):
+ if xml_node_child.nodeType not in {xml_node_child.TEXT_NODE, xml_node_child.COMMENT_NODE}:
py_item[CHILDREN].append(_fromxml(xml_node_child))
return py_item
diff --git a/release/scripts/modules/bpyml_ui.py b/release/scripts/modules/bpyml_ui.py
index 1e0522974d1..f4b6de23dbb 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
@@ -41,13 +40,13 @@ def _parse_rna(prop, value):
elif prop.type == 'INT':
value = int(value)
elif prop.type == 'BOOLEAN':
- if value in (True, False):
+ if value in {True, False}:
pass
else:
- if value not in ("True", "False"):
+ if value not in {"True", "False"}:
raise Exception("invalid bool value: %s" % value)
value = bool(value == "True")
- elif prop.type in ('STRING', 'ENUM'):
+ elif prop.type in {'STRING', 'ENUM'}:
pass
elif prop.type == 'POINTER':
value = eval("_bpy." + value)
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..425ea210104 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()
@@ -179,7 +179,7 @@ def execute(context):
# special exception. its possible the command loaded a new user interface
if hash(sc) != hash(context.space_data):
- return
+ return {'FINISHED'}
bpy.ops.console.scrollback_append(text=sc.prompt + line, type='INPUT')
diff --git a/release/scripts/modules/keyingsets_utils.py b/release/scripts/modules/keyingsets_utils.py
index dc61ce2a4af..03400edc904 100644
--- a/release/scripts/modules/keyingsets_utils.py
+++ b/release/scripts/modules/keyingsets_utils.py
@@ -16,14 +16,14 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
# This file defines a set of methods that are useful for various
# Relative Keying Set (RKS) related operations, such as: callbacks
# for polling, iterator callbacks, and also generate callbacks.
# All of these can be used in conjunction with the others.
-__all__ = [
+__all__ = (
"path_add_property",
"RKS_POLL_selected_objects",
"RKS_POLL_selected_bones",
@@ -33,7 +33,7 @@ __all__ = [
"RKS_GEN_location",
"RKS_GEN_rotation",
"RKS_GEN_scaling",
-]
+ )
import bpy
@@ -75,7 +75,8 @@ def RKS_POLL_selected_bones(ksi, context):
# selected bones or objects
def RKS_POLL_selected_items(ksi, context):
- return RKS_POLL_selected_bones(ksi, context) or RKS_POLL_selected_objects(ksi, context)
+ return (RKS_POLL_selected_bones(ksi, context) or
+ RKS_POLL_selected_objects(ksi, context))
###########################
# Iterator Callbacks
diff --git a/release/scripts/modules/rna_info.py b/release/scripts/modules/rna_info.py
index 93a344f4b09..943f86adecb 100644
--- a/release/scripts/modules/rna_info.py
+++ b/release/scripts/modules/rna_info.py
@@ -148,7 +148,7 @@ class InfoStructRNA:
import types
functions = []
for identifier, attr in self._get_py_visible_attrs():
- if type(attr) in (types.FunctionType, types.MethodType):
+ if type(attr) in {types.FunctionType, types.MethodType}:
functions.append((identifier, attr))
return functions
@@ -156,7 +156,7 @@ class InfoStructRNA:
import types
functions = []
for identifier, attr in self._get_py_visible_attrs():
- if type(attr) in (types.BuiltinMethodType, types.BuiltinFunctionType):
+ if type(attr) in {types.BuiltinMethodType, types.BuiltinFunctionType}:
functions.append((identifier, attr))
return functions
@@ -260,7 +260,7 @@ class InfoPropertyRNA:
if self.array_length:
type_str += " array of %d items" % (self.array_length)
- if self.type in ("float", "int"):
+ if self.type in {"float", "int"}:
type_str += " in [%s, %s]" % (range_str(self.min), range_str(self.max))
elif self.type == "enum":
if self.is_enum_flag:
@@ -595,7 +595,7 @@ def BuildRNAInfo():
for prop in rna_info.properties:
# ERROR CHECK
default = prop.default
- if type(default) in (float, int):
+ if type(default) in {float, int}:
if default < prop.min or default > prop.max:
print("\t %s.%s, %s not in [%s - %s]" % (rna_info.identifier, prop.identifier, default, prop.min, prop.max))
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/presets/ffmpeg/DV.py b/release/scripts/presets/ffmpeg/DV.py
index 46d2a0a4a2f..926fb241747 100644
--- a/release/scripts/presets/ffmpeg/DV.py
+++ b/release/scripts/presets/ffmpeg/DV.py
@@ -11,3 +11,4 @@ else:
bpy.context.scene.render.ffmpeg_audio_mixrate = 48000
bpy.context.scene.render.ffmpeg_audio_codec = "PCM"
+bpy.context.scene.render.ffmpeg_audio_channels = 2
diff --git a/release/scripts/presets/ffmpeg/DVD.py b/release/scripts/presets/ffmpeg/DVD.py
index e18ec9f817b..196b5d68406 100644
--- a/release/scripts/presets/ffmpeg/DVD.py
+++ b/release/scripts/presets/ffmpeg/DVD.py
@@ -21,3 +21,4 @@ bpy.context.scene.render.ffmpeg_muxrate = 10080000
bpy.context.scene.render.ffmpeg_audio_codec = "AC3"
bpy.context.scene.render.ffmpeg_audio_bitrate = 448
bpy.context.scene.render.ffmpeg_audio_mixrate = 48000
+bpy.context.scene.render.ffmpeg_audio_channels = 6
diff --git a/release/scripts/presets/ffmpeg/SVCD.py b/release/scripts/presets/ffmpeg/SVCD.py
index c71a3851af0..e4459ab5c5c 100644
--- a/release/scripts/presets/ffmpeg/SVCD.py
+++ b/release/scripts/presets/ffmpeg/SVCD.py
@@ -21,3 +21,4 @@ bpy.context.scene.render.ffmpeg_muxrate = 0
bpy.context.scene.render.ffmpeg_audio_bitrate = 224
bpy.context.scene.render.ffmpeg_audio_mixrate = 44100
bpy.context.scene.render.ffmpeg_audio_codec = "MP2"
+bpy.context.scene.render.ffmpeg_audio_channels = 2
diff --git a/release/scripts/presets/ffmpeg/VCD.py b/release/scripts/presets/ffmpeg/VCD.py
index faf27efe9e6..c2b73e682a2 100644
--- a/release/scripts/presets/ffmpeg/VCD.py
+++ b/release/scripts/presets/ffmpeg/VCD.py
@@ -21,3 +21,4 @@ bpy.context.scene.render.ffmpeg_muxrate = 2352 * 75 * 8
bpy.context.scene.render.ffmpeg_audio_bitrate = 224
bpy.context.scene.render.ffmpeg_audio_mixrate = 44100
bpy.context.scene.render.ffmpeg_audio_codec = "MP2"
+bpy.context.scene.render.ffmpeg_audio_channels = 2
diff --git a/release/scripts/presets/ffmpeg/xvid.py b/release/scripts/presets/ffmpeg/xvid.py
index fa64562e566..c006ba267cc 100644
--- a/release/scripts/presets/ffmpeg/xvid.py
+++ b/release/scripts/presets/ffmpeg/xvid.py
@@ -1,8 +1,7 @@
import bpy
is_ntsc = (bpy.context.scene.render.fps != 25)
-bpy.context.scene.render.ffmpeg_format = "AVI"
-bpy.context.scene.render.ffmpeg_codec = "XVID"
+bpy.context.scene.render.ffmpeg_format = "XVID"
if is_ntsc:
bpy.context.scene.render.ffmpeg_gopsize = 18
diff --git a/release/scripts/startup/bl_operators/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py
index 6ab803cc469..056b3478c2b 100644
--- a/release/scripts/startup/bl_operators/add_mesh_torus.py
+++ b/release/scripts/startup/bl_operators/add_mesh_torus.py
@@ -16,8 +16,9 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
+from bpy.types import Operator
import mathutils
@@ -40,8 +41,10 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
for minor_index in range(minor_seg):
angle = 2 * pi * minor_index / minor_seg
- vec = Vector((major_rad + (cos(angle) * minor_rad), 0.0,
- (sin(angle) * minor_rad))) * quat
+ vec = quat * Vector((major_rad + (cos(angle) * minor_rad),
+ 0.0,
+ (sin(angle) * minor_rad),
+ ))
verts.extend(vec[:])
@@ -72,44 +75,75 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
return verts, faces
-from bpy.props import FloatProperty, IntProperty, BoolProperty, FloatVectorProperty
+from bpy.props import (FloatProperty,
+ IntProperty,
+ BoolProperty,
+ FloatVectorProperty,
+ )
-class AddTorus(bpy.types.Operator):
+class AddTorus(Operator):
'''Add a torus mesh'''
bl_idname = "mesh.primitive_torus_add"
bl_label = "Add Torus"
bl_options = {'REGISTER', 'UNDO'}
- major_radius = FloatProperty(name="Major Radius",
- description="Radius from the origin to the center of the cross sections",
- default=1.0, min=0.01, max=100.0)
- minor_radius = FloatProperty(name="Minor Radius",
+ major_radius = FloatProperty(
+ name="Major Radius",
+ description=("Radius from the origin to the "
+ "center of the cross sections"),
+ min=0.01, max=100.0,
+ default=1.0,
+ )
+ minor_radius = FloatProperty(
+ name="Minor Radius",
description="Radius of the torus' cross section",
- default=0.25, min=0.01, max=100.0)
- major_segments = IntProperty(name="Major Segments",
+ min=0.01, max=100.0,
+ default=0.25,
+ )
+ major_segments = IntProperty(
+ name="Major Segments",
description="Number of segments for the main ring of the torus",
- default=48, min=3, max=256)
- minor_segments = IntProperty(name="Minor Segments",
+ min=3, max=256,
+ default=48,
+ )
+ minor_segments = IntProperty(
+ name="Minor Segments",
description="Number of segments for the minor ring of the torus",
- default=12, min=3, max=256)
- use_abso = BoolProperty(name="Use Int+Ext Controls",
+ min=3, max=256,
+ default=12,
+ )
+ use_abso = BoolProperty(
+ name="Use Int+Ext Controls",
description="Use the Int / Ext controls for torus dimensions",
- default=False)
- abso_major_rad = FloatProperty(name="Exterior Radius",
+ default=False,
+ )
+ abso_major_rad = FloatProperty(
+ name="Exterior Radius",
description="Total Exterior Radius of the torus",
- default=1.0, min=0.01, max=100.0)
- abso_minor_rad = FloatProperty(name="Inside Radius",
+ min=0.01, max=100.0,
+ default=1.0,
+ )
+ abso_minor_rad = FloatProperty(
+ name="Inside Radius",
description="Total Interior Radius of the torus",
- default=0.5, min=0.01, max=100.0)
+ min=0.01, max=100.0,
+ default=0.5,
+ )
# generic transform props
- view_align = BoolProperty(name="Align to View",
- default=False)
- location = FloatVectorProperty(name="Location",
- subtype='TRANSLATION')
- rotation = FloatVectorProperty(name="Rotation",
- subtype='EULER')
+ view_align = BoolProperty(
+ name="Align to View",
+ default=False,
+ )
+ location = FloatVectorProperty(
+ name="Location",
+ subtype='TRANSLATION',
+ )
+ rotation = FloatVectorProperty(
+ name="Rotation",
+ subtype='EULER',
+ )
def execute(self, context):
diff --git a/release/scripts/startup/bl_operators/animsys_update.py b/release/scripts/startup/bl_operators/animsys_update.py
index 63d438a5066..3710c57ac16 100644
--- a/release/scripts/startup/bl_operators/animsys_update.py
+++ b/release/scripts/startup/bl_operators/animsys_update.py
@@ -686,9 +686,10 @@ data_path_update = [
import bpy
+from bpy.types import Operator
-class UpdateAnimData(bpy.types.Operator):
+class UpdateAnimData(Operator):
"""Update data paths from 2.56 and previous versions, modifying data paths of drivers and fcurves"""
bl_idname = "anim.update_data_paths"
bl_label = "Update Animation Data"
diff --git a/release/scripts/startup/bl_operators/image.py b/release/scripts/startup/bl_operators/image.py
index 462db3a2c5e..9226cbed51b 100644
--- a/release/scripts/startup/bl_operators/image.py
+++ b/release/scripts/startup/bl_operators/image.py
@@ -16,19 +16,24 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
+from bpy.types import Operator
from bpy.props import StringProperty
-class EditExternally(bpy.types.Operator):
+class EditExternally(Operator):
'''Edit image in an external application'''
bl_idname = "image.external_edit"
bl_label = "Image Edit Externally"
bl_options = {'REGISTER'}
- filepath = StringProperty(name="File Path", description="Path to an image file", maxlen=1024, default="")
+ filepath = StringProperty(
+ name="File Path",
+ description="Path to an image file",
+ maxlen=1024,
+ )
def _editor_guess(self, context):
import sys
@@ -57,10 +62,19 @@ class EditExternally(bpy.types.Operator):
def execute(self, context):
import os
import subprocess
- filepath = bpy.path.abspath(self.filepath)
+
+ filepath = self.filepath
+
+ if not filepath:
+ self.report({'ERROR'}, "Image path not set")
+ return {'CANCELLED'}
+
+ filepath = os.path.normpath(bpy.path.abspath(filepath))
if not os.path.exists(filepath):
- self.report({'ERROR'}, "Image path %r not found." % filepath)
+ self.report({'ERROR'},
+ "Image path %r not found, image may be packed or "
+ "unsaved." % filepath)
return {'CANCELLED'}
cmd = self._editor_guess(context) + [filepath]
@@ -70,7 +84,10 @@ class EditExternally(bpy.types.Operator):
except:
import traceback
traceback.print_exc()
- self.report({'ERROR'}, "Image editor not found, please specify in User Preferences > File")
+ self.report({'ERROR'},
+ "Image editor not found, "
+ "please specify in User Preferences > File")
+
return {'CANCELLED'}
return {'FINISHED'}
@@ -90,7 +107,7 @@ class EditExternally(bpy.types.Operator):
return {'FINISHED'}
-class SaveDirty(bpy.types.Operator):
+class SaveDirty(Operator):
"""Save all modified textures"""
bl_idname = "image.save_dirty"
bl_label = "Save Dirty"
@@ -104,14 +121,16 @@ class SaveDirty(bpy.types.Operator):
if "\\" not in filepath and "/" not in filepath:
self.report({'WARNING'}, "Invalid path: " + filepath)
elif filepath in unique_paths:
- self.report({'WARNING'}, "Path used by more then one image: " + filepath)
+ self.report({'WARNING'},
+ "Path used by more then one image: %r" %
+ filepath)
else:
unique_paths.add(filepath)
image.save()
return {'FINISHED'}
-class ProjectEdit(bpy.types.Operator):
+class ProjectEdit(Operator):
"""Edit a snapshot of the viewport in an external image editor"""
bl_idname = "image.project_edit"
bl_label = "Project Edit"
@@ -121,7 +140,6 @@ class ProjectEdit(bpy.types.Operator):
def execute(self, context):
import os
- import subprocess
EXT = "png" # could be made an option but for now ok
@@ -143,14 +161,14 @@ class ProjectEdit(bpy.types.Operator):
filepath = os.path.basename(bpy.data.filepath)
filepath = os.path.splitext(filepath)[0]
- # filepath = bpy.path.clean_name(filepath) # fixes <memory> rubbish, needs checking
+ # fixes <memory> rubbish, needs checking
+ # filepath = bpy.path.clean_name(filepath)
- if filepath.startswith(".") or filepath == "":
- # TODO, have a way to check if the file is saved, assume startup.blend
+ if bpy.data.is_saved:
+ filepath = "//" + filepath
+ else:
tmpdir = context.user_preferences.filepaths.temporary_directory
filepath = os.path.join(tmpdir, "project_edit")
- else:
- filepath = "//" + filepath
obj = context.object
@@ -164,7 +182,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
@@ -179,7 +197,7 @@ class ProjectEdit(bpy.types.Operator):
return {'FINISHED'}
-class ProjectApply(bpy.types.Operator):
+class ProjectApply(Operator):
"""Project edited image back onto the object"""
bl_idname = "image.project_apply"
bl_label = "Project Apply"
diff --git a/release/scripts/startup/bl_operators/mesh.py b/release/scripts/startup/bl_operators/mesh.py
index 89802d7ba5c..5f6583754e9 100644
--- a/release/scripts/startup/bl_operators/mesh.py
+++ b/release/scripts/startup/bl_operators/mesh.py
@@ -16,14 +16,15 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
+from bpy.types import Operator
from bpy.props import EnumProperty
-class MeshSelectInteriorFaces(bpy.types.Operator):
+class MeshSelectInteriorFaces(Operator):
'''Select faces where all edges have more then 2 face users.'''
bl_idname = "mesh.faces_select_interior"
@@ -67,28 +68,26 @@ class MeshSelectInteriorFaces(bpy.types.Operator):
return {'FINISHED'}
-class MeshMirrorUV(bpy.types.Operator):
+class MeshMirrorUV(Operator):
'''Copy mirror UV coordinates on the X axis based on a mirrored mesh'''
bl_idname = "mesh.faces_mirror_uv"
bl_label = "Copy Mirrored UV coords"
bl_options = {'REGISTER', 'UNDO'}
- direction = EnumProperty(items=(
- ('POSITIVE', "Positive", ""),
- ('NEGATIVE', "Negative", "")),
- name="Axis Direction",
- description="")
+ direction = EnumProperty(
+ name="Axis Direction",
+ items=(('POSITIVE', "Positive", ""),
+ ('NEGATIVE', "Negative", "")),
+ )
@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:
@@ -113,21 +112,18 @@ class MeshMirrorUV(bpy.types.Operator):
#for i, v in enumerate(mesh.vertices):
vmap = {}
- for mirror_a, mirror_b in (mirror_gt, mirror_lt), (mirror_lt, mirror_gt):
+ for mirror_a, mirror_b in ((mirror_gt, mirror_lt),
+ (mirror_lt, mirror_gt)):
for co, i in mirror_a.items():
nco = (-co[0], co[1], co[2])
j = mirror_b.get(nco)
if j is not None:
vmap[i] = j
- active_uv_layer = None
- for lay in mesh.uv_textures:
- if lay.active:
- active_uv_layer = lay.data
- break
-
+ active_uv_layer = mesh.uv_textures.active.data
fuvs = [(uv.uv1, uv.uv2, uv.uv3, uv.uv4) for uv in active_uv_layer]
- fuvs_cpy = [(uv[0].copy(), uv[1].copy(), uv[2].copy(), uv[3].copy()) for uv in fuvs]
+ fuvs_cpy = [(uv[0].copy(), uv[1].copy(), uv[2].copy(), uv[3].copy())
+ for uv in fuvs]
# as a list
faces = mesh.faces[:]
@@ -152,7 +148,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 +165,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..c764f7d62f1 100644
--- a/release/scripts/startup/bl_operators/nla.py
+++ b/release/scripts/startup/bl_operators/nla.py
@@ -16,17 +16,17 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
+from bpy.types import Operator
-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 +51,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 +66,87 @@ 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,
+ action=None):
+
scene = bpy.context.scene
obj = bpy.context.object
pose = obj.pose
+ frame_back = scene.frame_current
- info_ls = []
+ if pose is None:
+ do_pose = False
+
+ 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
- action = bpy.data.actions.new("Action")
+ # -------------------------------------------------------------------------
+ # Create action
- bpy.context.object.animation_data.action = action
+ # incase animation data hassnt been created
+ atd = obj.animation_data_create()
+ if action is None:
+ action = bpy.data.actions.new("Action")
+ atd.action = action
- pose_items = pose.bones.items()
+ if do_pose:
+ pose_items = pose.bones.items()
+ else:
+ pose_items = [] # skip
- for name, pbone in pose_items:
+ # -------------------------------------------------------------------------
+ # Apply transformations to action
+
+ # 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,33 +162,92 @@ 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):
+class BakeAction(Operator):
'''Bake animation to an Action'''
bl_idname = "nla.bake"
bl_label = "Bake Action"
bl_options = {'REGISTER', 'UNDO'}
- frame_start = IntProperty(name="Start Frame",
+ frame_start = IntProperty(
+ name="Start Frame",
description="Start frame for baking",
- default=1, min=1, max=300000)
- frame_end = IntProperty(name="End Frame",
+ min=0, max=300000,
+ default=1,
+ )
+ frame_end = IntProperty(
+ name="End Frame",
description="End frame for baking",
- default=250, min=1, max=300000)
- step = IntProperty(name="Frame Step",
+ min=1, max=300000,
+ default=250,
+ )
+ step = IntProperty(
+ name="Frame Step",
description="Frame Step",
- default=1, min=1, max=120)
- only_selected = BoolProperty(name="Only Selected",
- default=True)
+ min=1, max=120,
+ default=1,
+ )
+ 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:
@@ -168,3 +268,36 @@ class BakeAction(bpy.types.Operator):
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
+
+
+class ClearUselessActions(Operator):
+ '''Mark actions with no F-Curves for deletion after save+reload of file preserving "action libraries"'''
+ bl_idname = "anim.clear_useless_actions"
+ bl_label = "Clear Useless Actions"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ only_unused = BoolProperty(name="Only Unused",
+ description="Only unused (Fake User only) actions get considered",
+ default=True)
+
+ @classmethod
+ def poll(cls, context):
+ return len(bpy.data.actions) != 0
+
+ def execute(self, context):
+ removed = 0
+
+ for action in bpy.data.actions:
+ # if only user is "fake" user...
+ if ((self.only_unused is False) or
+ (action.use_fake_user and action.users == 1)):
+
+ # if it has F-Curves, then it's a "action library" (i.e. walk, wave, jump, etc.)
+ # and should be left alone as that's what fake users are for!
+ if not action.fcurves:
+ # mark action for deletion
+ action.user_clear()
+ removed += 1
+
+ self.report({'INFO'}, "Removed %d empty and/or fake-user only Actions" % (removed))
+ return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py
index 0342a14a1b2..6c9f27afaa5 100644
--- a/release/scripts/startup/bl_operators/object.py
+++ b/release/scripts/startup/bl_operators/object.py
@@ -16,21 +16,35 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
+from bpy.types import Operator
from bpy.props import StringProperty, BoolProperty, EnumProperty, IntProperty
-class SelectPattern(bpy.types.Operator):
+class SelectPattern(Operator):
'''Select object matching a naming pattern'''
bl_idname = "object.select_pattern"
bl_label = "Select Pattern"
bl_options = {'REGISTER', 'UNDO'}
- pattern = StringProperty(name="Pattern", description="Name filter using '*' and '?' wildcard chars", maxlen=32, default="*")
- case_sensitive = BoolProperty(name="Case Sensitive", description="Do a case sensitive compare", default=False)
- extend = BoolProperty(name="Extend", description="Extend the existing selection", default=True)
+ pattern = StringProperty(
+ name="Pattern",
+ description="Name filter using '*' and '?' wildcard chars",
+ maxlen=32,
+ default="*",
+ )
+ case_sensitive = BoolProperty(
+ name="Case Sensitive",
+ description="Do a case sensitive compare",
+ default=False,
+ )
+ extend = BoolProperty(
+ name="Extend",
+ description="Extend the existing selection",
+ default=True,
+ )
def execute(self, context):
@@ -39,22 +53,37 @@ class SelectPattern(bpy.types.Operator):
if self.case_sensitive:
pattern_match = fnmatch.fnmatchcase
else:
- pattern_match = lambda a, b: fnmatch.fnmatchcase(a.upper(), b.upper())
-
+ pattern_match = (lambda a, b:
+ fnmatch.fnmatchcase(a.upper(), b.upper()))
+ is_ebone = False
obj = context.object
if obj and obj.mode == 'POSE':
items = obj.data.bones
+ if not self.extend:
+ bpy.ops.pose.select_all(action='DESELECT')
elif obj and obj.type == 'ARMATURE' and obj.mode == 'EDIT':
items = obj.data.edit_bones
+ if not self.extend:
+ bpy.ops.armature.select_all(action='DESELECT')
+ is_ebone = True
else:
items = context.visible_objects
+ if not self.extend:
+ bpy.ops.object.select_all(action='DESELECT')
# Can be pose bones or objects
for item in items:
if pattern_match(item.name, self.pattern):
item.select = True
- elif not self.extend:
- item.select = False
+
+ # hrmf, perhaps there should be a utility function for this.
+ if is_ebone:
+ item.select_head = True
+ item.select_tail = True
+ if item.use_connect:
+ item_parent = item.parent
+ if item_parent is not None:
+ item_parent.select_tail = True
return {'FINISHED'}
@@ -71,7 +100,7 @@ class SelectPattern(bpy.types.Operator):
row.prop(self, "extend")
-class SelectCamera(bpy.types.Operator):
+class SelectCamera(Operator):
'''Select object matching a naming pattern'''
bl_idname = "object.select_camera"
bl_label = "Select Camera"
@@ -92,20 +121,26 @@ class SelectCamera(bpy.types.Operator):
return {'FINISHED'}
-class SelectHierarchy(bpy.types.Operator):
- '''Select object relative to the active objects position in the hierarchy'''
+class SelectHierarchy(Operator):
+ '''Select object relative to the active objects position''' \
+ '''in the hierarchy'''
bl_idname = "object.select_hierarchy"
bl_label = "Select Hierarchy"
bl_options = {'REGISTER', 'UNDO'}
- direction = EnumProperty(items=(
- ('PARENT', "Parent", ""),
- ('CHILD', "Child", "")),
- name="Direction",
- description="Direction to select in the hierarchy",
- default='PARENT')
+ direction = EnumProperty(
+ items=(('PARENT', "Parent", ""),
+ ('CHILD', "Child", ""),
+ ),
+ name="Direction",
+ description="Direction to select in the hierarchy",
+ default='PARENT')
- extend = BoolProperty(name="Extend", description="Extend the existing selection", default=False)
+ extend = BoolProperty(
+ name="Extend",
+ description="Extend the existing selection",
+ default=False,
+ )
@classmethod
def poll(cls, context):
@@ -153,17 +188,26 @@ class SelectHierarchy(bpy.types.Operator):
return {'CANCELLED'}
-class SubdivisionSet(bpy.types.Operator):
+class SubdivisionSet(Operator):
'''Sets a Subdivision Surface Level (1-5)'''
bl_idname = "object.subdivision_set"
bl_label = "Subdivision Set"
bl_options = {'REGISTER', 'UNDO'}
- level = IntProperty(name="Level",
- default=1, min=-100, max=100, soft_min=-6, soft_max=6)
+ level = IntProperty(
+ name="Level",
+ min=-100, max=100,
+ soft_min=-6, soft_max=6,
+ default=1,
+ )
- relative = BoolProperty(name="Relative", description="Apply the subsurf level as an offset relative to the current level", default=False)
+ relative = BoolProperty(
+ name="Relative",
+ description=("Apply the subsurf level as an offset "
+ "relative to the current level"),
+ default=False,
+ )
@classmethod
def poll(cls, context):
@@ -215,7 +259,8 @@ class SubdivisionSet(bpy.types.Operator):
mod = obj.modifiers.new("Subsurf", 'SUBSURF')
mod.levels = level
except:
- self.report({'WARNING'}, "Modifiers cannot be added to object: " + obj.name)
+ self.report({'WARNING'},
+ "Modifiers cannot be added to object: " + obj.name)
for obj in context.selected_editable_objects:
set_object_subd(obj)
@@ -223,24 +268,38 @@ class SubdivisionSet(bpy.types.Operator):
return {'FINISHED'}
-class ShapeTransfer(bpy.types.Operator):
- '''Copy another selected objects active shape to this one by applying the relative offsets'''
+class ShapeTransfer(Operator):
+ '''Copy another selected objects active shape to this one by ''' \
+ '''applying the relative offsets'''
bl_idname = "object.shape_key_transfer"
bl_label = "Transfer Shape Key"
bl_options = {'REGISTER', 'UNDO'}
- mode = EnumProperty(items=(
- ('OFFSET', "Offset", "Apply the relative positional offset"),
- ('RELATIVE_FACE', "Relative Face", "Calculate the geometricly relative position (using faces)."),
- ('RELATIVE_EDGE', "Relative Edge", "Calculate the geometricly relative position (using edges).")),
- name="Transformation Mode",
- description="Method to apply relative shape positions to the new shape",
- default='OFFSET')
-
- use_clamp = BoolProperty(name="Clamp Offset",
- description="Clamp the transformation to the distance each vertex moves in the original shape.",
- default=False)
+ mode = EnumProperty(
+ items=(('OFFSET',
+ "Offset",
+ "Apply the relative positional offset",
+ ),
+ ('RELATIVE_FACE',
+ "Relative Face",
+ "Calculate relative position (using faces).",
+ ),
+ ('RELATIVE_EDGE',
+ "Relative Edge",
+ "Calculate relative position (using edges).",
+ ),
+ ),
+ name="Transformation Mode",
+ description="Relative shape positions to the new shape method",
+ default='OFFSET',
+ )
+ use_clamp = BoolProperty(
+ name="Clamp Offset",
+ description=("Clamp the transformation to the distance each "
+ "vertex moves in the original shape."),
+ default=False,
+ )
def _main(self, ob_act, objects, mode='OFFSET', use_clamp=False):
@@ -272,13 +331,16 @@ class ShapeTransfer(bpy.types.Operator):
orig_shape_coords = me_cos(ob_act.active_shape_key.data)
orig_normals = me_nos(me.vertices)
- # orig_coords = me_cos(me.vertices) # the actual mverts location isnt as relyable as the base shape :S
+ # the actual mverts location isnt as relyable as the base shape :S
+ # orig_coords = me_cos(me.vertices)
orig_coords = me_cos(me.shape_keys.key_blocks[0].data)
for ob_other in objects:
me_other = ob_other.data
if len(me_other.vertices) != len(me.vertices):
- self.report({'WARNING'}, "Skipping '%s', vertex count differs" % ob_other.name)
+ self.report({'WARNING'},
+ ("Skipping '%s', "
+ "vertex count differs") % ob_other.name)
continue
target_normals = me_nos(me_other.vertices)
@@ -290,53 +352,90 @@ class ShapeTransfer(bpy.types.Operator):
ob_add_shape(ob_other, orig_key_name)
# editing the final coords, only list that stores wrapped coords
- target_shape_coords = [v.co for v in ob_other.active_shape_key.data]
+ target_shape_coords = [v.co for v in
+ ob_other.active_shape_key.data]
median_coords = [[] for i in range(len(me.vertices))]
# Method 1, edge
if mode == 'OFFSET':
for i, vert_cos in enumerate(median_coords):
- vert_cos.append(target_coords[i] + (orig_shape_coords[i] - orig_coords[i]))
+ vert_cos.append(target_coords[i] +
+ (orig_shape_coords[i] - orig_coords[i]))
elif mode == 'RELATIVE_FACE':
for face in me.faces:
i1, i2, i3, i4 = face.vertices_raw
if i4 != 0:
pt = barycentric_transform(orig_shape_coords[i1],
- orig_coords[i4], orig_coords[i1], orig_coords[i2],
- target_coords[i4], target_coords[i1], target_coords[i2])
+ orig_coords[i4],
+ orig_coords[i1],
+ orig_coords[i2],
+ target_coords[i4],
+ target_coords[i1],
+ target_coords[i2],
+ )
median_coords[i1].append(pt)
pt = barycentric_transform(orig_shape_coords[i2],
- orig_coords[i1], orig_coords[i2], orig_coords[i3],
- target_coords[i1], target_coords[i2], target_coords[i3])
+ orig_coords[i1],
+ orig_coords[i2],
+ orig_coords[i3],
+ target_coords[i1],
+ target_coords[i2],
+ target_coords[i3],
+ )
median_coords[i2].append(pt)
pt = barycentric_transform(orig_shape_coords[i3],
- orig_coords[i2], orig_coords[i3], orig_coords[i4],
- target_coords[i2], target_coords[i3], target_coords[i4])
+ orig_coords[i2],
+ orig_coords[i3],
+ orig_coords[i4],
+ target_coords[i2],
+ target_coords[i3],
+ target_coords[i4],
+ )
median_coords[i3].append(pt)
pt = barycentric_transform(orig_shape_coords[i4],
- orig_coords[i3], orig_coords[i4], orig_coords[i1],
- target_coords[i3], target_coords[i4], target_coords[i1])
+ orig_coords[i3],
+ orig_coords[i4],
+ orig_coords[i1],
+ target_coords[i3],
+ target_coords[i4],
+ target_coords[i1],
+ )
median_coords[i4].append(pt)
else:
pt = barycentric_transform(orig_shape_coords[i1],
- orig_coords[i3], orig_coords[i1], orig_coords[i2],
- target_coords[i3], target_coords[i1], target_coords[i2])
+ orig_coords[i3],
+ orig_coords[i1],
+ orig_coords[i2],
+ target_coords[i3],
+ target_coords[i1],
+ target_coords[i2],
+ )
median_coords[i1].append(pt)
pt = barycentric_transform(orig_shape_coords[i2],
- orig_coords[i1], orig_coords[i2], orig_coords[i3],
- target_coords[i1], target_coords[i2], target_coords[i3])
+ orig_coords[i1],
+ orig_coords[i2],
+ orig_coords[i3],
+ target_coords[i1],
+ target_coords[i2],
+ target_coords[i3],
+ )
median_coords[i2].append(pt)
pt = barycentric_transform(orig_shape_coords[i3],
- orig_coords[i2], orig_coords[i3], orig_coords[i1],
- target_coords[i2], target_coords[i3], target_coords[i1])
+ orig_coords[i2],
+ orig_coords[i3],
+ orig_coords[i1],
+ target_coords[i2],
+ target_coords[i3],
+ target_coords[i1],
+ )
median_coords[i3].append(pt)
elif mode == 'RELATIVE_EDGE':
@@ -374,7 +473,8 @@ class ShapeTransfer(bpy.types.Operator):
if use_clamp:
# clamp to the same movement as the original
# breaks copy between different scaled meshes.
- len_from = (orig_shape_coords[i] - orig_coords[i]).length
+ len_from = (orig_shape_coords[i] -
+ orig_coords[i]).length
ofs = co - target_coords[i]
ofs.length = len_from
co = target_coords[i] + ofs
@@ -395,7 +495,10 @@ class ShapeTransfer(bpy.types.Operator):
if 1: # swap from/to, means we cant copy to many at once.
if len(objects) != 1:
- self.report({'ERROR'}, "Expected one other selected mesh object to copy from")
+ self.report({'ERROR'},
+ ("Expected one other selected "
+ "mesh object to copy from"))
+
return {'CANCELLED'}
ob_act, objects = objects[0], [ob_act]
@@ -409,7 +512,7 @@ class ShapeTransfer(bpy.types.Operator):
return self._main(ob_act, objects, self.mode, self.use_clamp)
-class JoinUVs(bpy.types.Operator):
+class JoinUVs(Operator):
'''Copy UV Layout to objects with matching geometry'''
bl_idname = "object.join_uvs"
bl_label = "Join as UVs"
@@ -429,11 +532,14 @@ class JoinUVs(bpy.types.Operator):
bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
if not mesh.uv_textures:
- self.report({'WARNING'}, "Object: %s, Mesh: '%s' has no UVs\n" % (obj.name, mesh.name))
+ self.report({'WARNING'},
+ "Object: %s, Mesh: '%s' has no UVs"
+ % (obj.name, mesh.name))
else:
len_faces = len(mesh.faces)
- uv_array = array.array('f', [0.0] * 8) * len_faces # seems to be the fastest way to create an array
+ # seems to be the fastest way to create an array
+ uv_array = array.array('f', [0.0] * 8) * len_faces
mesh.uv_textures.active.data.foreach_get("uv_raw", uv_array)
objects = context.selected_editable_objects[:]
@@ -450,11 +556,18 @@ class JoinUVs(bpy.types.Operator):
mesh_other.tag = True
if len(mesh_other.faces) != len_faces:
- self.report({'WARNING'}, "Object: %s, Mesh: '%s' has %d faces, expected %d\n" % (obj_other.name, mesh_other.name, len(mesh_other.faces), len_faces))
+ self.report({'WARNING'}, "Object: %s, Mesh: "
+ "'%s' has %d faces, expected %d\n"
+ % (obj_other.name,
+ mesh_other.name,
+ len(mesh_other.faces),
+ len_faces),
+ )
else:
uv_other = mesh_other.uv_textures.active
if not uv_other:
- uv_other = mesh_other.uv_textures.new() # should return the texture it adds
+ # should return the texture it adds
+ uv_other = mesh_other.uv_textures.new()
# finally do the copy
uv_other.data.foreach_set("uv_raw", uv_array)
@@ -467,7 +580,7 @@ class JoinUVs(bpy.types.Operator):
return {'FINISHED'}
-class MakeDupliFace(bpy.types.Operator):
+class MakeDupliFace(Operator):
'''Make linked objects into dupli-faces'''
bl_idname = "object.make_dupli_face"
bl_label = "Make Dupli-Face"
@@ -482,14 +595,18 @@ class MakeDupliFace(bpy.types.Operator):
SCALE_FAC = 0.01
offset = 0.5 * SCALE_FAC
- base_tri = Vector((-offset, -offset, 0.0)), Vector((offset, -offset, 0.0)), Vector((offset, offset, 0.0)), Vector((-offset, offset, 0.0))
+ base_tri = (Vector((-offset, -offset, 0.0)),
+ Vector((+offset, -offset, 0.0)),
+ Vector((+offset, +offset, 0.0)),
+ Vector((-offset, +offset, 0.0)),
+ )
def matrix_to_quat(matrix):
# scale = matrix.median_scale
trans = matrix.to_translation()
rot = matrix.to_3x3() # also contains scale
- return [(b * rot) + trans for b in base_tri]
+ return [(rot * b) + trans for b in base_tri]
scene = bpy.context.scene
linked = {}
for obj in bpy.context.selected_objects:
@@ -498,7 +615,10 @@ class MakeDupliFace(bpy.types.Operator):
linked.setdefault(data, []).append(obj)
for data, objects in linked.items():
- face_verts = [axis for obj in objects for v in matrix_to_quat(obj.matrix_world) for axis in v]
+ face_verts = [axis for obj in objects
+ for v in matrix_to_quat(obj.matrix_world)
+ for axis in v]
+
faces = list(range(len(face_verts) // 3))
mesh = bpy.data.meshes.new(data.name + "_dupli")
@@ -534,8 +654,9 @@ class MakeDupliFace(bpy.types.Operator):
return {'FINISHED'}
-class IsolateTypeRender(bpy.types.Operator):
- '''Hide unselected render objects of same type as active by setting the hide render flag'''
+class IsolateTypeRender(Operator):
+ '''Hide unselected render objects of same type as active ''' \
+ '''by setting the hide render flag'''
bl_idname = "object.isolate_type_render"
bl_label = "Restrict Render Unselected"
bl_options = {'REGISTER', 'UNDO'}
@@ -554,7 +675,7 @@ class IsolateTypeRender(bpy.types.Operator):
return {'FINISHED'}
-class ClearAllRestrictRender(bpy.types.Operator):
+class ClearAllRestrictRender(Operator):
'''Reveal all render objects by setting the hide render flag'''
bl_idname = "object.hide_render_clear_all"
bl_label = "Clear All Restrict Render"
@@ -564,3 +685,49 @@ class ClearAllRestrictRender(bpy.types.Operator):
for obj in context.scene.objects:
obj.hide_render = False
return {'FINISHED'}
+
+
+class TransformsToDeltasAnim(Operator):
+ '''Convert object animation for normal transforms to delta transforms'''
+ bl_idname = "object.anim_transforms_to_deltas"
+ bl_label = "Animated Transforms to Deltas"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ @classmethod
+ def poll(cls, context):
+ obs = context.selected_editable_objects
+ return (obs is not None)
+
+ def execute(self, context):
+ for obj in context.selected_editable_objects:
+ # get animation data
+ adt = obj.animation_data
+ if (adt is None) or (adt.action is None):
+ self.report({'WARNING'},
+ "No animation data to convert on object: %r" %
+ obj.name)
+ continue
+
+ # if F-Curve uses standard transform path
+ # just append "delta_" to this path
+ for fcu in adt.action.fcurves:
+ if fcu.data_path == "location":
+ fcu.data_path = "delta_location"
+ obj.location.zero()
+ elif fcu.data_path == "rotation_euler":
+ fcu.data_path = "delta_rotation_euler"
+ obj.rotation_euler.zero()
+ elif fcu.data_path == "rotation_quaternion":
+ fcu.data_path = "delta_rotation_quaternion"
+ obj.rotation_quaternion.identity()
+ # XXX: currently not implemented
+ # elif fcu.data_path == "rotation_axis_angle":
+ # fcu.data_path = "delta_rotation_axis_angle"
+ elif fcu.data_path == "scale":
+ fcu.data_path = "delta_scale"
+ obj.scale = 1.0, 1.0, 1.0
+
+ # hack: force animsys flush by changing frame, so that deltas get run
+ context.scene.frame_set(context.scene.frame_current)
+
+ return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/object_align.py b/release/scripts/startup/bl_operators/object_align.py
index 644f30a4745..50e9bfb5b98 100644
--- a/release/scripts/startup/bl_operators/object_align.py
+++ b/release/scripts/startup/bl_operators/object_align.py
@@ -16,106 +16,213 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
+from bpy.types import Operator
from mathutils import Vector
-def align_objects(align_x, align_y, align_z, align_mode, relative_to):
+def GlobalBB_LQ(bb_world):
+
+ # Initialize the variables with the 8th vertex
+ left, right, front, back, down, up = (bb_world[7][0],
+ bb_world[7][0],
+ bb_world[7][1],
+ bb_world[7][1],
+ bb_world[7][2],
+ bb_world[7][2],
+ )
+
+ # Test against the other 7 verts
+ for i in range(7):
+
+ # X Range
+ val = bb_world[i][0]
+ if val < left:
+ left = val
+
+ if val > right:
+ right = val
+
+ # Y Range
+ val = bb_world[i][1]
+ if val < front:
+ front = val
+
+ if val > back:
+ back = val
+
+ # Z Range
+ val = bb_world[i][2]
+ if val < down:
+ down = val
+
+ if val > up:
+ up = val
+
+ return (Vector((left, front, up)), Vector((right, back, down)))
+
+
+def GlobalBB_HQ(obj):
+
+ matrix_world = obj.matrix_world.copy()
+
+ # Initialize the variables with the last vertex
+
+ verts = obj.data.vertices
+
+ val = matrix_world * verts[-1].co
+
+ left, right, front, back, down, up = (val[0],
+ val[0],
+ val[1],
+ val[1],
+ val[2],
+ val[2],
+ )
+
+ # Test against all other verts
+ for i in range(len(verts) - 1):
+
+ vco = matrix_world * verts[i].co
+
+ # X Range
+ val = vco[0]
+ if val < left:
+ left = val
+
+ if val > right:
+ right = val
+
+ # Y Range
+ val = vco[1]
+ if val < front:
+ front = val
+
+ if val > back:
+ back = val
+
+ # Z Range
+ val = vco[2]
+ if val < down:
+ down = val
+
+ if val > up:
+ up = val
+
+ return Vector((left, front, up)), Vector((right, back, down))
+
+
+def align_objects(align_x,
+ align_y,
+ align_z,
+ align_mode,
+ relative_to,
+ bb_quality):
cursor = bpy.context.scene.cursor_location
- Left_Up_Front_SEL = [0.0, 0.0, 0.0]
- Right_Down_Back_SEL = [0.0, 0.0, 0.0]
+ Left_Front_Up_SEL = [0.0, 0.0, 0.0]
+ Right_Back_Down_SEL = [0.0, 0.0, 0.0]
flag_first = True
objs = []
for obj in bpy.context.selected_objects:
- matrix_world = obj.matrix_world
- bb_world = [Vector(v[:]) * matrix_world for v in obj.bound_box]
+ matrix_world = obj.matrix_world.copy()
+ bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box]
objs.append((obj, bb_world))
if not objs:
return False
for obj, bb_world in objs:
- Left_Up_Front = bb_world[1]
- Right_Down_Back = bb_world[7]
+
+ if bb_quality:
+ GBB = GlobalBB_HQ(obj)
+ else:
+ GBB = GlobalBB_LQ(bb_world)
+
+ Left_Front_Up = GBB[0]
+ Right_Back_Down = GBB[1]
# Active Center
if obj == bpy.context.active_object:
- center_active_x = (Left_Up_Front[0] + Right_Down_Back[0]) / 2.0
- center_active_y = (Left_Up_Front[1] + Right_Down_Back[1]) / 2.0
- center_active_z = (Left_Up_Front[2] + Right_Down_Back[2]) / 2.0
+ center_active_x = (Left_Front_Up[0] + Right_Back_Down[0]) / 2.0
+ center_active_y = (Left_Front_Up[1] + Right_Back_Down[1]) / 2.0
+ center_active_z = (Left_Front_Up[2] + Right_Back_Down[2]) / 2.0
- size_active_x = (Right_Down_Back[0] - Left_Up_Front[0]) / 2.0
- size_active_y = (Right_Down_Back[1] - Left_Up_Front[1]) / 2.0
- size_active_z = (Left_Up_Front[2] - Right_Down_Back[2]) / 2.0
+ size_active_x = (Right_Back_Down[0] - Left_Front_Up[0]) / 2.0
+ size_active_y = (Right_Back_Down[1] - Left_Front_Up[1]) / 2.0
+ size_active_z = (Left_Front_Up[2] - Right_Back_Down[2]) / 2.0
# Selection Center
if flag_first:
flag_first = False
- Left_Up_Front_SEL[0] = Left_Up_Front[0]
- Left_Up_Front_SEL[1] = Left_Up_Front[1]
- Left_Up_Front_SEL[2] = Left_Up_Front[2]
+ Left_Front_Up_SEL[0] = Left_Front_Up[0]
+ Left_Front_Up_SEL[1] = Left_Front_Up[1]
+ Left_Front_Up_SEL[2] = Left_Front_Up[2]
- Right_Down_Back_SEL[0] = Right_Down_Back[0]
- Right_Down_Back_SEL[1] = Right_Down_Back[1]
- Right_Down_Back_SEL[2] = Right_Down_Back[2]
+ Right_Back_Down_SEL[0] = Right_Back_Down[0]
+ Right_Back_Down_SEL[1] = Right_Back_Down[1]
+ Right_Back_Down_SEL[2] = Right_Back_Down[2]
else:
# X axis
- if Left_Up_Front[0] < Left_Up_Front_SEL[0]:
- Left_Up_Front_SEL[0] = Left_Up_Front[0]
+ if Left_Front_Up[0] < Left_Front_Up_SEL[0]:
+ Left_Front_Up_SEL[0] = Left_Front_Up[0]
# Y axis
- if Left_Up_Front[1] < Left_Up_Front_SEL[1]:
- Left_Up_Front_SEL[1] = Left_Up_Front[1]
+ if Left_Front_Up[1] < Left_Front_Up_SEL[1]:
+ Left_Front_Up_SEL[1] = Left_Front_Up[1]
# Z axis
- if Left_Up_Front[2] > Left_Up_Front_SEL[2]:
- Left_Up_Front_SEL[2] = Left_Up_Front[2]
+ if Left_Front_Up[2] > Left_Front_Up_SEL[2]:
+ Left_Front_Up_SEL[2] = Left_Front_Up[2]
# X axis
- if Right_Down_Back[0] > Right_Down_Back_SEL[0]:
- Right_Down_Back_SEL[0] = Right_Down_Back[0]
+ if Right_Back_Down[0] > Right_Back_Down_SEL[0]:
+ Right_Back_Down_SEL[0] = Right_Back_Down[0]
# Y axis
- if Right_Down_Back[1] > Right_Down_Back_SEL[1]:
- Right_Down_Back_SEL[1] = Right_Down_Back[1]
+ if Right_Back_Down[1] > Right_Back_Down_SEL[1]:
+ Right_Back_Down_SEL[1] = Right_Back_Down[1]
# Z axis
- if Right_Down_Back[2] < Right_Down_Back_SEL[2]:
- Right_Down_Back_SEL[2] = Right_Down_Back[2]
+ if Right_Back_Down[2] < Right_Back_Down_SEL[2]:
+ Right_Back_Down_SEL[2] = Right_Back_Down[2]
- center_sel_x = (Left_Up_Front_SEL[0] + Right_Down_Back_SEL[0]) / 2.0
- center_sel_y = (Left_Up_Front_SEL[1] + Right_Down_Back_SEL[1]) / 2.0
- center_sel_z = (Left_Up_Front_SEL[2] + Right_Down_Back_SEL[2]) / 2.0
+ center_sel_x = (Left_Front_Up_SEL[0] + Right_Back_Down_SEL[0]) / 2.0
+ center_sel_y = (Left_Front_Up_SEL[1] + Right_Back_Down_SEL[1]) / 2.0
+ center_sel_z = (Left_Front_Up_SEL[2] + Right_Back_Down_SEL[2]) / 2.0
# Main Loop
for obj, bb_world in objs:
+ matrix_world = obj.matrix_world.copy()
+ bb_world = [matrix_world * Vector(v[:]) for v in obj.bound_box]
- loc_world = obj.location
- bb_world = [Vector(v[:]) * obj.matrix_world for v in obj.bound_box]
+ if bb_quality:
+ GBB = GlobalBB_HQ(obj)
+ else:
+ GBB = GlobalBB_LQ(bb_world)
- Left_Up_Front = bb_world[1]
- Right_Down_Back = bb_world[7]
+ Left_Front_Up = GBB[0]
+ Right_Back_Down = GBB[1]
- center_x = (Left_Up_Front[0] + Right_Down_Back[0]) / 2.0
- center_y = (Left_Up_Front[1] + Right_Down_Back[1]) / 2.0
- center_z = (Left_Up_Front[2] + Right_Down_Back[2]) / 2.0
+ center_x = (Left_Front_Up[0] + Right_Back_Down[0]) / 2.0
+ center_y = (Left_Front_Up[1] + Right_Back_Down[1]) / 2.0
+ center_z = (Left_Front_Up[2] + Right_Back_Down[2]) / 2.0
- positive_x = Right_Down_Back[0]
- positive_y = Right_Down_Back[1]
- positive_z = Left_Up_Front[2]
+ positive_x = Right_Back_Down[0]
+ positive_y = Right_Back_Down[1]
+ positive_z = Left_Front_Up[2]
- negative_x = Left_Up_Front[0]
- negative_y = Left_Up_Front[1]
- negative_z = Right_Down_Back[2]
+ negative_x = Left_Front_Up[0]
+ negative_y = Left_Front_Up[1]
+ negative_z = Right_Back_Down[2]
obj_loc = obj.location
@@ -230,40 +337,48 @@ 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):
+class AlignObjects(Operator):
'''Align Objects'''
bl_idname = "object.align"
bl_label = "Align Objects"
bl_options = {'REGISTER', 'UNDO'}
- align_mode = EnumProperty(items=(
- ('OPT_1', "Negative Sides", ""),
- ('OPT_2', "Centers", ""),
- ('OPT_3', "Positive Sides", "")),
- name="Align Mode:",
- description="",
- default='OPT_2')
-
- relative_to = EnumProperty(items=(
- ('OPT_1', "Scene Origin", ""),
- ('OPT_2', "3D Cursor", ""),
- ('OPT_3', "Selection", ""),
- ('OPT_4', "Active", "")),
- name="Relative To:",
- description="",
- default='OPT_4')
-
- align_axis = EnumProperty(items=(
- ('X', "X", ""),
- ('Y', "Y", ""),
- ('Z', "Z", ""),
- ),
- name="Align",
- description="Align to axis",
- options={'ENUM_FLAG'})
+ bb_quality = BoolProperty(
+ name="High Quality",
+ description=("Enables high quality calculation of the "
+ "bounding box for perfect results on complex "
+ "shape meshes with rotation/scale (Slow)"),
+ default=True,
+ )
+ align_mode = EnumProperty(
+ name="Align Mode:",
+ items=(('OPT_1', "Negative Sides", ""),
+ ('OPT_2', "Centers", ""),
+ ('OPT_3', "Positive Sides", ""),
+ ),
+ default='OPT_2',
+ )
+ relative_to = EnumProperty(
+ name="Relative To:",
+ items=(('OPT_1', "Scene Origin", ""),
+ ('OPT_2', "3D Cursor", ""),
+ ('OPT_3', "Selection", ""),
+ ('OPT_4', "Active", ""),
+ ),
+ default='OPT_4',
+ )
+ align_axis = EnumProperty(
+ name="Align",
+ description="Align to axis",
+ items=(('X', "X", ""),
+ ('Y', "Y", ""),
+ ('Z', "Z", ""),
+ ),
+ options={'ENUM_FLAG'},
+ )
@classmethod
def poll(cls, context):
@@ -271,7 +386,12 @@ class AlignObjects(bpy.types.Operator):
def execute(self, context):
align_axis = self.align_axis
- ret = align_objects('X' in align_axis, 'Y' in align_axis, 'Z' in align_axis, self.align_mode, self.relative_to)
+ ret = align_objects('X' in align_axis,
+ 'Y' in align_axis,
+ 'Z' in align_axis,
+ self.align_mode,
+ self.relative_to,
+ self.bb_quality)
if not ret:
self.report({'WARNING'}, "No objects with bound-box selected")
diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py
index 21640fa3ee6..48b547980d4 100644
--- a/release/scripts/startup/bl_operators/object_quick_effects.py
+++ b/release/scripts/startup/bl_operators/object_quick_effects.py
@@ -16,35 +16,65 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
from mathutils import Vector
import bpy
-from bpy.props import BoolProperty, EnumProperty, IntProperty, FloatProperty, FloatVectorProperty
+from bpy.types import Operator
+from bpy.props import (BoolProperty,
+ EnumProperty,
+ IntProperty,
+ FloatProperty,
+ FloatVectorProperty,
+ )
+
+
+def object_ensure_material(obj, mat_name):
+ """ Use an existing material or add a new one.
+ """
+ mat = mat_slot = None
+ for mat_slot in obj.material_slots:
+ mat = mat_slot.material
+ if mat:
+ break
+ if mat is None:
+ mat = bpy.data.materials.new(mat_name)
+ if mat_slot:
+ mat_slot.material = mat
+ else:
+ obj.data.materials.append(mat)
+ return mat
-class MakeFur(bpy.types.Operator):
- bl_idname = "object.make_fur"
- bl_label = "Make Fur"
+class QuickFur(Operator):
+ bl_idname = "object.quick_fur"
+ bl_label = "Quick Fur"
bl_options = {'REGISTER', 'UNDO'}
- density = EnumProperty(items=(
- ('LIGHT', "Light", ""),
- ('MEDIUM', "Medium", ""),
- ('HEAVY', "Heavy", "")),
- name="Fur Density",
- description="",
- default='MEDIUM')
-
- view_percentage = IntProperty(name="View %",
- default=10, min=1, max=100, soft_min=1, soft_max=100)
-
- length = FloatProperty(name="Length",
- default=0.1, min=0.001, max=100, soft_min=0.01, soft_max=10)
+ density = EnumProperty(
+ name="Fur Density",
+ items=(('LIGHT', "Light", ""),
+ ('MEDIUM', "Medium", ""),
+ ('HEAVY', "Heavy", "")),
+ default='MEDIUM',
+ )
+ view_percentage = IntProperty(
+ name="View %",
+ min=1, max=100,
+ soft_min=1, soft_max=100,
+ default=10,
+ )
+ length = FloatProperty(
+ name="Length",
+ min=0.001, max=100,
+ soft_min=0.01, soft_max=10,
+ default=0.1,
+ )
def execute(self, context):
fake_context = bpy.context.copy()
- mesh_objects = [obj for obj in context.selected_objects if obj.type == 'MESH']
+ mesh_objects = [obj for obj in context.selected_objects
+ if obj.type == 'MESH']
if not mesh_objects:
self.report({'ERROR'}, "Select at least one mesh object.")
@@ -75,14 +105,183 @@ class MakeFur(bpy.types.Operator):
psys.settings.child_type = 'INTERPOLATED'
obj.data.materials.append(mat)
- obj.particle_systems[-1].settings.material = len(obj.data.materials)
+ obj.particle_systems[-1].settings.material = \
+ len(obj.data.materials)
+
+ return {'FINISHED'}
+
+
+class QuickExplode(Operator):
+ bl_idname = "object.quick_explode"
+ bl_label = "Quick Explode"
+ bl_options = {'REGISTER', 'UNDO'}
+
+ style = EnumProperty(
+ name="Explode Style",
+ items=(('EXPLODE', "Explode", ""),
+ ('BLEND', "Blend", "")),
+ default='EXPLODE',
+ )
+ amount = IntProperty(
+ name="Amount of pieces",
+ min=2, max=10000,
+ soft_min=2, soft_max=10000,
+ default=100,
+ )
+ frame_duration = IntProperty(
+ name="Duration",
+ min=1, max=300000,
+ soft_min=1, soft_max=10000,
+ default=50,
+ )
+
+ frame_start = IntProperty(
+ name="Start Frame",
+ min=1, max=300000,
+ soft_min=1, soft_max=10000,
+ default=1,
+ )
+ frame_end = IntProperty(
+ name="End Frame",
+ min=1, max=300000,
+ soft_min=1, soft_max=10000,
+ default=10,
+ )
+
+ velocity = FloatProperty(
+ name="Outwards Velocity",
+ min=0, max=300000,
+ soft_min=0, soft_max=10,
+ default=1,
+ )
+
+ fade = BoolProperty(
+ name="Fade",
+ description="Fade the pieces over time.",
+ default=True,
+ )
+
+ def execute(self, context):
+ fake_context = bpy.context.copy()
+ obj_act = context.active_object
+
+ if obj_act is None or obj_act.type != 'MESH':
+ self.report({'ERROR'}, "Active object is not a mesh")
+ return {'CANCELLED'}
+
+ mesh_objects = [obj for obj in context.selected_objects
+ if obj.type == 'MESH' and obj != obj_act]
+ mesh_objects.insert(0, obj_act)
+
+ if self.style == 'BLEND' and len(mesh_objects) != 2:
+ self.report({'ERROR'}, "Select two mesh objects")
+ return {'CANCELLED'}
+ elif not mesh_objects:
+ self.report({'ERROR'}, "Select at least one mesh object")
+ return {'CANCELLED'}
+
+ for obj in mesh_objects:
+ if obj.particle_systems:
+ self.report({'ERROR'},
+ "Object %r already has a "
+ "particle system" % obj.name)
+
+ return {'CANCELLED'}
+
+ if self.fade:
+ tex = bpy.data.textures.new("Explode fade", 'BLEND')
+ tex.use_color_ramp = True
+
+ if self.style == 'BLEND':
+ tex.color_ramp.elements[0].position = 0.333
+ tex.color_ramp.elements[1].position = 0.666
+
+ tex.color_ramp.elements[0].color[3] = 1.0
+ tex.color_ramp.elements[1].color[3] = 0.0
+
+ if self.style == 'BLEND':
+ from_obj = mesh_objects[1]
+ to_obj = mesh_objects[0]
+
+ for obj in mesh_objects:
+ fake_context["object"] = obj
+ bpy.ops.object.particle_system_add(fake_context)
+
+ settings = obj.particle_systems[-1].settings
+ settings.count = self.amount
+ settings.frame_start = self.frame_start
+ settings.frame_end = self.frame_end - self.frame_duration
+ settings.lifetime = self.frame_duration
+ settings.normal_factor = self.velocity
+ settings.render_type = 'NONE'
+
+ explode = obj.modifiers.new(name='Explode', type='EXPLODE')
+ explode.use_edge_cut = True
+
+ if self.fade:
+ explode.show_dead = False
+ uv = obj.data.uv_textures.new("Explode fade")
+ explode.particle_uv = uv.name
+
+ mat = object_ensure_material(obj, "Explode Fade")
+
+ mat.use_transparency = True
+ mat.use_transparent_shadows = True
+ mat.alpha = 0.0
+ mat.specular_alpha = 0.0
+
+ tex_slot = mat.texture_slots.add()
+
+ tex_slot.texture = tex
+ tex_slot.texture_coords = 'UV'
+ tex_slot.uv_layer = uv.name
+
+ tex_slot.use_map_alpha = True
+
+ if self.style == 'BLEND':
+ if obj == to_obj:
+ tex_slot.alpha_factor = -1.0
+ elem = tex.color_ramp.elements[1]
+ elem.color = mat.diffuse_color
+ else:
+ elem = tex.color_ramp.elements[0]
+ elem.color = mat.diffuse_color
+ else:
+ tex_slot.use_map_color_diffuse = False
+
+ if self.style == 'BLEND':
+ settings.physics_type = 'KEYED'
+ settings.use_emit_random = False
+ settings.rotation_mode = 'NOR'
+
+ psys = obj.particle_systems[-1]
+
+ fake_context["particle_system"] = obj.particle_systems[-1]
+ bpy.ops.particle.new_target(fake_context)
+ bpy.ops.particle.new_target(fake_context)
+
+ if obj == from_obj:
+ psys.targets[1].object = to_obj
+ else:
+ psys.targets[0].object = from_obj
+ settings.normal_factor = -self.velocity
+ explode.show_unborn = False
+ explode.show_dead = True
+ else:
+ settings.factor_random = self.velocity
+ settings.angular_velocity_factor = self.velocity / 10.0
return {'FINISHED'}
+ def invoke(self, context, event):
+ self.frame_start = context.scene.frame_current
+ self.frame_end = self.frame_start + self.frame_duration
+ return self.execute(context)
+
def obj_bb_minmax(obj, min_co, max_co):
for i in range(0, 8):
- bb_vec = Vector((obj.bound_box[i][0], obj.bound_box[i][1], obj.bound_box[i][2])) * obj.matrix_world
+ bb_vec = obj.matrix_world * Vector(obj.bound_box[i])
min_co[0] = min(bb_vec[0], min_co[0])
min_co[1] = min(bb_vec[1], min_co[1])
@@ -92,28 +291,32 @@ 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(Operator):
+ bl_idname = "object.quick_smoke"
+ bl_label = "Quick Smoke"
bl_options = {'REGISTER', 'UNDO'}
- style = EnumProperty(items=(
- ('STREAM', "Stream", ""),
- ('PUFF', "Puff", ""),
- ('FIRE', "Fire", "")),
- name="Smoke Style",
- description="",
- default='STREAM')
-
- show_flows = BoolProperty(name="Render Smoke Objects",
- description="Keep the smoke objects visible during rendering.",
- default=False)
+ style = EnumProperty(
+ name="Smoke Style",
+ items=(('STREAM', "Stream", ""),
+ ('PUFF', "Puff", ""),
+ ('FIRE', "Fire", ""),
+ ),
+ default='STREAM',
+ )
+
+ show_flows = BoolProperty(
+ name="Render Smoke Objects",
+ description="Keep the smoke objects visible during rendering.",
+ default=False,
+ )
def execute(self, context):
fake_context = bpy.context.copy()
- mesh_objects = [obj for obj in context.selected_objects if obj.type == 'MESH']
- min_co = Vector((100000, 100000, 100000))
- max_co = Vector((-100000, -100000, -100000))
+ mesh_objects = [obj for obj in context.selected_objects
+ if obj.type == 'MESH']
+ min_co = Vector((100000.0, 100000.0, 100000.0))
+ max_co = -min_co
if not mesh_objects:
self.report({'ERROR'}, "Select at least one mesh object.")
@@ -171,21 +374,25 @@ class MakeSmoke(bpy.types.Operator):
mat.volume.density = 0
mat.volume.density_scale = 5
- mat.texture_slots.add()
- mat.texture_slots[0].texture = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA')
- mat.texture_slots[0].texture.voxel_data.domain_object = obj
- mat.texture_slots[0].use_map_color_emission = False
- mat.texture_slots[0].use_map_density = True
+ tex = bpy.data.textures.new("Smoke Density", 'VOXEL_DATA')
+ tex.voxel_data.domain_object = obj
+
+ tex_slot = mat.texture_slots.add()
+ tex_slot.texture = tex
+ tex_slot.use_map_color_emission = False
+ tex_slot.use_map_density = True
# for fire add a second texture for emission and emission color
if self.style == 'FIRE':
mat.volume.emission = 5
- mat.texture_slots.add()
- mat.texture_slots[1].texture = bpy.data.textures.new("Smoke Heat", 'VOXEL_DATA')
- mat.texture_slots[1].texture.voxel_data.domain_object = obj
- mat.texture_slots[1].texture.use_color_ramp = True
+ tex = bpy.data.textures.new("Smoke Heat", 'VOXEL_DATA')
+ tex.voxel_data.domain_object = obj
+ tex.use_color_ramp = True
+
+ tex_slot = mat.texture_slots.add()
+ tex_slot.texture = tex
- ramp = mat.texture_slots[1].texture.color_ramp
+ ramp = tex.color_ramp
elem = ramp.elements.new(0.333)
elem.color[0] = elem.color[3] = 1
@@ -201,33 +408,40 @@ class MakeSmoke(bpy.types.Operator):
return {'FINISHED'}
-class MakeFluid(bpy.types.Operator):
- bl_idname = "object.make_fluid"
- bl_label = "Make Fluid"
+class QuickFluid(Operator):
+ bl_idname = "object.quick_fluid"
+ bl_label = "Quick Fluid"
bl_options = {'REGISTER', 'UNDO'}
- style = EnumProperty(items=(
- ('INFLOW', "Inflow", ""),
- ('BASIC', "Basic", "")),
- name="Fluid Style",
- description="",
- default='BASIC')
-
- initial_velocity = FloatVectorProperty(name="Initial Velocity",
- description="Initial velocity of the fluid",
- default=(0.0, 0.0, 0.0), min=-100.0, max=100.0, subtype='VELOCITY')
-
- show_flows = BoolProperty(name="Render Fluid Objects",
- description="Keep the fluid objects visible during rendering.",
- default=False)
-
- start_baking = BoolProperty(name="Start Fluid Bake",
- description="Start baking the fluid immediately after creating the domain object.",
- default=False)
+ style = EnumProperty(
+ name="Fluid Style",
+ items=(('INFLOW', "Inflow", ""),
+ ('BASIC', "Basic", "")),
+ default='BASIC',
+ )
+ initial_velocity = FloatVectorProperty(
+ name="Initial Velocity",
+ description="Initial velocity of the fluid",
+ min=-100.0, max=100.0,
+ default=(0.0, 0.0, 0.0),
+ subtype='VELOCITY',
+ )
+ show_flows = BoolProperty(
+ name="Render Fluid Objects",
+ description="Keep the fluid objects visible during rendering.",
+ default=False,
+ )
+ start_baking = BoolProperty(
+ name="Start Fluid Bake",
+ description=("Start baking the fluid immediately "
+ "after creating the domain object"),
+ default=False,
+ )
def execute(self, context):
fake_context = bpy.context.copy()
- mesh_objects = [obj for obj in context.selected_objects if (obj.type == 'MESH' and not 0 in obj.dimensions)]
+ mesh_objects = [obj for obj in context.selected_objects
+ if (obj.type == 'MESH' and not 0.0 in obj.dimensions)]
min_co = Vector((100000, 100000, 100000))
max_co = Vector((-100000, -100000, -100000))
@@ -240,7 +454,8 @@ class MakeFluid(bpy.types.Operator):
# make each selected object a fluid
bpy.ops.object.modifier_add(fake_context, type='FLUID_SIMULATION')
- # fluid has to be before constructive modifiers, so it might not be the last modifier
+ # fluid has to be before constructive modifiers,
+ # so it might not be the last modifier
for mod in obj.modifiers:
if mod.type == 'FLUID_SIMULATION':
break
@@ -264,10 +479,14 @@ class MakeFluid(bpy.types.Operator):
obj = context.active_object
obj.name = "Fluid Domain"
- # give the fluid some room below the flows and scale with initial velocity
+ # give the fluid some room below the flows
+ # and scale with initial velocity
v = 0.5 * self.initial_velocity
obj.location = 0.5 * (max_co + min_co) + Vector((0.0, 0.0, -1.0)) + v
- obj.scale = 0.5 * (max_co - min_co) + Vector((1.0, 1.0, 2.0)) + Vector((abs(v[0]), abs(v[1]), abs(v[2])))
+ obj.scale = (0.5 * (max_co - min_co) +
+ Vector((1.0, 1.0, 2.0)) +
+ Vector((abs(v[0]), abs(v[1]), abs(v[2])))
+ )
# setup smoke domain
bpy.ops.object.modifier_add(type='FLUID_SIMULATION')
diff --git a/release/scripts/startup/bl_operators/object_randomize_transform.py b/release/scripts/startup/bl_operators/object_randomize_transform.py
index 9dc5086086f..7aea18487f3 100644
--- a/release/scripts/startup/bl_operators/object_randomize_transform.py
+++ b/release/scripts/startup/bl_operators/object_randomize_transform.py
@@ -16,9 +16,10 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
+from bpy.types import Operator
def randomize_selected(seed, delta, loc, rot, scale, scale_even):
@@ -87,46 +88,78 @@ def randomize_selected(seed, delta, loc, rot, scale, scale_even):
from bpy.props import IntProperty, BoolProperty, FloatVectorProperty
-class RandomizeLocRotSize(bpy.types.Operator):
+class RandomizeLocRotSize(Operator):
'''Randomize objects loc/rot/scale'''
bl_idname = "object.randomize_transform"
bl_label = "Randomize Transform"
bl_options = {'REGISTER', 'UNDO'}
- random_seed = IntProperty(name="Random Seed",
- description="Seed value for the random generator",
- default=0, min=0, max=1000)
-
- use_delta = BoolProperty(name="Transform Delta",
- description="Randomize delta transform values instead of regular transform", default=False)
-
- use_loc = BoolProperty(name="Randomize Location",
- description="Randomize the location values", default=True)
-
- loc = FloatVectorProperty(name="Location",
- description="Maximun distance the objects can spread over each axis",
- default=(0.0, 0.0, 0.0), min=-100.0, max=100.0, subtype='TRANSLATION')
-
- use_rot = BoolProperty(name="Randomize Rotation",
- description="Randomize the rotation values", default=True)
-
- rot = FloatVectorProperty(name="Rotation",
- description="Maximun rotation over each axis",
- default=(0.0, 0.0, 0.0), min=-180.0, max=180.0, subtype='TRANSLATION')
-
- use_scale = BoolProperty(name="Randomize Scale",
- description="Randomize the scale values", default=True)
-
- scale_even = BoolProperty(name="Scale Even",
- description="Use the same scale value for all axis", default=False)
-
- '''scale_min = FloatProperty(name="Minimun Scale Factor",
- description="Lowest scale percentage possible",
- default=0.15, min=-1.0, max=1.0, precision=3)'''
-
- scale = FloatVectorProperty(name="Scale",
- description="Maximum scale randomization over each axis",
- default=(0.0, 0.0, 0.0), min=-100.0, max=100.0, subtype='TRANSLATION')
+ random_seed = IntProperty(
+ name="Random Seed",
+ description="Seed value for the random generator",
+ min=0,
+ max=1000,
+ default=0,
+ )
+ use_delta = BoolProperty(
+ name="Transform Delta",
+ description=("Randomize delta transform values "
+ "instead of regular transform"),
+ default=False,
+ )
+ use_loc = BoolProperty(
+ name="Randomize Location",
+ description="Randomize the location values",
+ default=True,
+ )
+ loc = FloatVectorProperty(
+ name="Location",
+ description=("Maximun distance the objects "
+ "can spread over each axis"),
+ min=-100.0,
+ max=100.0,
+ default=(0.0, 0.0, 0.0),
+ subtype='TRANSLATION',
+ )
+ use_rot = BoolProperty(
+ name="Randomize Rotation",
+ description="Randomize the rotation values",
+ default=True,
+ )
+ rot = FloatVectorProperty(
+ name="Rotation",
+ description="Maximun rotation over each axis",
+ min=-180.0,
+ max=180.0,
+ default=(0.0, 0.0, 0.0),
+ subtype='TRANSLATION',
+ )
+ use_scale = BoolProperty(
+ name="Randomize Scale",
+ description="Randomize the scale values",
+ default=True,
+ )
+ scale_even = BoolProperty(
+ name="Scale Even",
+ description="Use the same scale value for all axis",
+ default=False,
+ )
+
+ '''scale_min = FloatProperty(
+ name="Minimun Scale Factor",
+ description="Lowest scale percentage possible",
+ min=-1.0, max=1.0, precision=3,
+ default=0.15,
+ )'''
+
+ scale = FloatVectorProperty(
+ name="Scale",
+ description="Maximum scale randomization over each axis",
+ min=-100.0,
+ max=100.0,
+ default=(0.0, 0.0, 0.0),
+ subtype='TRANSLATION',
+ )
def execute(self, context):
from math import radians
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index 2175d7528a4..2fd0c4a9e12 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -16,9 +16,10 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
+from bpy.types import Menu, Operator
class AddPresetBase():
@@ -30,8 +31,15 @@ class AddPresetBase():
# bl_label = "Add a Python Preset"
bl_options = {'REGISTER'} # only because invoke_props_popup requires.
- name = bpy.props.StringProperty(name="Name", description="Name of the preset, used to make the path name", maxlen=64, default="")
- remove_active = bpy.props.BoolProperty(default=False, options={'HIDDEN'})
+ name = bpy.props.StringProperty(
+ name="Name",
+ description="Name of the preset, used to make the path name",
+ maxlen=64,
+ )
+ remove_active = bpy.props.BoolProperty(
+ default=False,
+ options={'HIDDEN'},
+ )
@staticmethod
def as_filename(name): # could reuse for other presets
@@ -54,7 +62,10 @@ class AddPresetBase():
filename = self.as_filename(name)
- target_path = bpy.utils.user_resource('SCRIPTS', os.path.join("presets", self.preset_subdir), create=True)
+ target_path = os.path.join("presets", self.preset_subdir)
+ target_path = bpy.utils.user_resource('SCRIPTS',
+ target_path,
+ create=True)
if not target_path:
self.report({'WARNING'}, "Failed to create presets path")
@@ -95,7 +106,9 @@ class AddPresetBase():
filepath = bpy.utils.preset_find(preset_active, self.preset_subdir)
if not filepath:
- filepath = bpy.utils.preset_find(preset_active, self.preset_subdir, display_name=True)
+ filepath = bpy.utils.preset_find(preset_active,
+ self.preset_subdir,
+ display_name=True)
if not filepath:
return {'CANCELLED'}
@@ -128,13 +141,20 @@ class AddPresetBase():
return self.execute(context)
-class ExecutePreset(bpy.types.Operator):
+class ExecutePreset(Operator):
''' Executes a preset '''
bl_idname = "script.execute_preset"
bl_label = "Execute a Python Preset"
- filepath = bpy.props.StringProperty(name="Path", description="Path of the Python file to execute", maxlen=512, default="")
- menu_idname = bpy.props.StringProperty(name="Menu ID Name", description="ID name of the menu this was called from", default="")
+ filepath = bpy.props.StringProperty(
+ name="Path",
+ description="Path of the Python file to execute",
+ maxlen=512,
+ )
+ menu_idname = bpy.props.StringProperty(
+ name="Menu ID Name",
+ description="ID name of the menu this was called from",
+ )
def execute(self, context):
from os.path import basename
@@ -149,7 +169,7 @@ class ExecutePreset(bpy.types.Operator):
return {'FINISHED'}
-class AddPresetRender(AddPresetBase, bpy.types.Operator):
+class AddPresetRender(AddPresetBase, Operator):
'''Add a Render Preset'''
bl_idname = "render.preset_add"
bl_label = "Add Render Preset"
@@ -175,14 +195,17 @@ class AddPresetRender(AddPresetBase, bpy.types.Operator):
preset_subdir = "render"
-class AddPresetSSS(AddPresetBase, bpy.types.Operator):
+class AddPresetSSS(AddPresetBase, Operator):
'''Add a Subsurface Scattering Preset'''
bl_idname = "material.sss_preset_add"
bl_label = "Add SSS Preset"
preset_menu = "MATERIAL_MT_sss_presets"
preset_defines = [
- "material = (bpy.context.material.active_node_material if bpy.context.material.active_node_material else bpy.context.material)"
+ ("material = "
+ "bpy.context.material.active_node_material "
+ "if bpy.context.material.active_node_material "
+ "else bpy.context.material")
]
preset_values = [
@@ -200,7 +223,7 @@ class AddPresetSSS(AddPresetBase, bpy.types.Operator):
preset_subdir = "sss"
-class AddPresetCloth(AddPresetBase, bpy.types.Operator):
+class AddPresetCloth(AddPresetBase, Operator):
'''Add a Cloth Preset'''
bl_idname = "cloth.preset_add"
bl_label = "Add Cloth Preset"
@@ -222,7 +245,7 @@ class AddPresetCloth(AddPresetBase, bpy.types.Operator):
preset_subdir = "cloth"
-class AddPresetSunSky(AddPresetBase, bpy.types.Operator):
+class AddPresetSunSky(AddPresetBase, Operator):
'''Add a Sky & Atmosphere Preset'''
bl_idname = "lamp.sunsky_preset_add"
bl_label = "Add Sunsky Preset"
@@ -251,7 +274,7 @@ class AddPresetSunSky(AddPresetBase, bpy.types.Operator):
preset_subdir = "sunsky"
-class AddPresetInteraction(AddPresetBase, bpy.types.Operator):
+class AddPresetInteraction(AddPresetBase, Operator):
'''Add an Application Interaction Preset'''
bl_idname = "wm.interaction_preset_add"
bl_label = "Add Interaction Preset"
@@ -277,7 +300,7 @@ class AddPresetInteraction(AddPresetBase, bpy.types.Operator):
preset_subdir = "interaction"
-class AddPresetKeyconfig(AddPresetBase, bpy.types.Operator):
+class AddPresetKeyconfig(AddPresetBase, Operator):
'''Add a Keyconfig Preset'''
bl_idname = "wm.keyconfig_preset_add"
bl_label = "Add Keyconfig Preset"
@@ -300,13 +323,17 @@ class AddPresetKeyconfig(AddPresetBase, bpy.types.Operator):
keyconfigs.remove(keyconfigs.active)
-class AddPresetOperator(AddPresetBase, bpy.types.Operator):
+class AddPresetOperator(AddPresetBase, Operator):
'''Add an Application Interaction Preset'''
bl_idname = "wm.operator_preset_add"
bl_label = "Operator Preset"
preset_menu = "WM_MT_operator_presets"
- operator = bpy.props.StringProperty(name="Operator", maxlen=64, options={'HIDDEN'})
+ operator = bpy.props.StringProperty(
+ name="Operator",
+ maxlen=64,
+ options={'HIDDEN'},
+ )
# XXX, not ideal
preset_defines = [
@@ -315,19 +342,22 @@ class AddPresetOperator(AddPresetBase, bpy.types.Operator):
@property
def preset_subdir(self):
- return __class__.operator_path(self.operator)
+ return AddPresetOperator.operator_path(self.operator)
@property
def preset_values(self):
- properties_blacklist = bpy.types.Operator.bl_rna.properties.keys()
+ properties_blacklist = Operator.bl_rna.properties.keys()
prefix, suffix = self.operator.split("_OT_", 1)
- operator_rna = getattr(getattr(bpy.ops, prefix.lower()), suffix).get_rna().bl_rna
+ op = getattr(getattr(bpy.ops, prefix.lower()), suffix)
+ operator_rna = op.get_rna().bl_rna
+ del op
ret = []
for prop_id, prop in operator_rna.properties.items():
- if (not (prop.is_hidden or prop.is_skip_save)) and prop_id not in properties_blacklist:
- ret.append("op.%s" % prop_id)
+ if not (prop.is_hidden or prop.is_skip_save):
+ if prop_id not in properties_blacklist:
+ ret.append("op.%s" % prop_id)
return ret
@@ -338,12 +368,12 @@ class AddPresetOperator(AddPresetBase, bpy.types.Operator):
return os.path.join("operator", "%s.%s" % (prefix.lower(), suffix))
-class WM_MT_operator_presets(bpy.types.Menu):
+class WM_MT_operator_presets(Menu):
bl_label = "Operator Presets"
def draw(self, context):
self.operator = context.space_data.operator.bl_idname
- bpy.types.Menu.draw_preset(self, context)
+ Menu.draw_preset(self, context)
@property
def preset_subdir(self):
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..c2a09d6a4ae 100644
--- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
+++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
@@ -1,30 +1,27 @@
-# ***** BEGIN GPL LICENSE BLOCK *****
+# ##### BEGIN GPL LICENSE BLOCK #####
#
-# Script copyright (C) Campbell J Barton
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-#
-# ***** END GPL LICENCE BLOCK *****
+# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
-# History
-#
# Originally written by Matt Ebb
import bpy
+from bpy.types import Operator
import os
@@ -46,8 +43,10 @@ def guess_player_path(preset):
player_path = "djv_view"
if sys.platform == "darwin":
- # TODO, crummy supporting only 1 version, could find the newest installed version
- test_path = '/Applications/djv-0.8.2.app/Contents/Resources/bin/djv_view'
+ # TODO, crummy supporting only 1 version,
+ # could find the newest installed version
+ test_path = ("/Applications/djv-0.8.2.app"
+ "/Contents/Resources/bin/djv_view")
if os.path.exists(test_path):
player_path = test_path
@@ -60,10 +59,13 @@ def guess_player_path(preset):
elif preset == 'MPLAYER':
player_path = "mplayer"
+ else:
+ player_path = ""
+
return player_path
-class PlayRenderedAnim(bpy.types.Operator):
+class PlayRenderedAnim(Operator):
'''Plays back rendered frames/movies using an external player.'''
bl_idname = "render.play_rendered_anim"
bl_label = "Play Rendered Animation"
@@ -78,14 +80,14 @@ class PlayRenderedAnim(bpy.types.Operator):
preset = prefs.filepaths.animation_player_preset
player_path = prefs.filepaths.animation_player
- file_path = bpy.path.abspath(rd.filepath)
+ # file_path = bpy.path.abspath(rd.filepath) # UNUSED
is_movie = rd.is_movie_format
# try and guess a command line if it doesn't exist
- if player_path == '':
+ if player_path == "":
player_path = guess_player_path(preset)
- if is_movie == False and preset in ('FRAMECYCLER', 'RV', 'MPLAYER'):
+ if is_movie == False and preset in {'FRAMECYCLER', 'RV', 'MPLAYER'}:
# replace the number with '#'
file_a = rd.frame_path(frame=0)
@@ -95,11 +97,11 @@ class PlayRenderedAnim(bpy.types.Operator):
while len(file_a) == len(file_b):
frame_tmp = (frame_tmp * 10) + 9
- print(frame_tmp)
file_b = rd.frame_path(frame=frame_tmp)
file_b = rd.frame_path(frame=int(frame_tmp / 10))
- file = "".join((c if file_b[i] == c else "#") for i, c in enumerate(file_a))
+ file = ("".join((c if file_b[i] == c else "#")
+ for i, c in enumerate(file_a)))
else:
# works for movies and images
file = rd.frame_path(frame=scene.frame_start)
@@ -109,10 +111,35 @@ class PlayRenderedAnim(bpy.types.Operator):
cmd = [player_path]
# extra options, fps controls etc.
if preset == 'BLENDER24':
+ # -----------------------------------------------------------------
+ # Check blender is not 2.5x until it supports playback again
+ try:
+ process = subprocess.Popen([player_path, '--version'],
+ stdout=subprocess.PIPE,
+ )
+ except:
+ # ignore and allow the main execution to catch the problem.
+ process = None
+
+ if process is not None:
+ process.wait()
+ out = process.stdout.read()
+ process.stdout.close()
+ out_split = out.strip().split()
+ if out_split[0] == b'Blender':
+ if not out_split[1].startswith(b'2.4'):
+ self.report({'ERROR'},
+ "Blender %s doesn't support playback: %r" %
+ (out_split[1].decode(), player_path))
+ return {'CANCELLED'}
+ del out, out_split
+ del process
+ # -----------------------------------------------------------------
+
opts = ["-a", "-f", str(rd.fps), str(rd.fps_base), file]
cmd.extend(opts)
elif preset == 'DJV':
- opts = [file, "-playback_speed", str(rd.fps)]
+ opts = [file, "-playback_speed", "%d" % int(rd.fps / rd.fps_base)]
cmd.extend(opts)
elif preset == 'FRAMECYCLER':
opts = [file, "%d-%d" % (scene.frame_start, scene.frame_end)]
@@ -125,18 +152,26 @@ class PlayRenderedAnim(bpy.types.Operator):
if is_movie:
opts.append(file)
else:
- opts.append("mf://%s" % file.replace("#", "?"))
- opts += ["-mf", "fps=%.4f" % (rd.fps / rd.fps_base)]
+ opts += [("mf://%s" % file.replace("#", "?")),
+ "-mf",
+ "fps=%.4f" % (rd.fps / rd.fps_base),
+ ]
+
opts += ["-loop", "0", "-really-quiet", "-fs"]
cmd.extend(opts)
else: # 'CUSTOM'
cmd.append(file)
# launch it
+ print("Executing command:\n %r" % " ".join(cmd))
+
try:
process = subprocess.Popen(cmd)
- except:
- pass
- #raise OSError("Couldn't find an external animation player.")
+ except Exception as e:
+ import traceback
+ self.report({'ERROR'},
+ "Couldn't run external animation player with command "
+ "%r\n%s" % (" ".join(cmd), str(e)))
+ return {'CANCELLED'}
return {'FINISHED'}
diff --git a/release/scripts/startup/bl_operators/sequencer.py b/release/scripts/startup/bl_operators/sequencer.py
index 16b72406c49..856e182279a 100644
--- a/release/scripts/startup/bl_operators/sequencer.py
+++ b/release/scripts/startup/bl_operators/sequencer.py
@@ -19,11 +19,12 @@
# <pep8 compliant>
import bpy
+from bpy.types import Operator
from bpy.props import IntProperty
-class SequencerCrossfadeSounds(bpy.types.Operator):
+class SequencerCrossfadeSounds(Operator):
'''Do crossfading volume animation of two selected sound strips.'''
bl_idname = "sequencer.crossfade_sounds"
@@ -74,15 +75,19 @@ class SequencerCrossfadeSounds(bpy.types.Operator):
return {'CANCELLED'}
-class SequencerCutMulticam(bpy.types.Operator):
+class SequencerCutMulticam(Operator):
'''Cut multicam strip and select camera.'''
bl_idname = "sequencer.cut_multicam"
bl_label = "Cut multicam"
bl_options = {'REGISTER', 'UNDO'}
- camera = IntProperty(name="Camera",
- default=1, min=1, max=32, soft_min=1, soft_max=32)
+ camera = IntProperty(
+ name="Camera",
+ min=1, max=32,
+ soft_min=1, soft_max=32,
+ default=1,
+ )
@classmethod
def poll(cls, context):
@@ -112,7 +117,7 @@ class SequencerCutMulticam(bpy.types.Operator):
return {'FINISHED'}
-class SequencerDeinterlaceSelectedMovies(bpy.types.Operator):
+class SequencerDeinterlaceSelectedMovies(Operator):
'''Deinterlace all selected movie sources.'''
bl_idname = "sequencer.deinterlace_selected_movies"
diff --git a/release/scripts/startup/bl_operators/uvcalc_follow_active.py b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
index edd09d9c66b..6c258d094e8 100644
--- a/release/scripts/startup/bl_operators/uvcalc_follow_active.py
+++ b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
@@ -22,6 +22,7 @@
# http://mediawiki.blender.org/index.php/Scripts/Manual/UV_Calculate/Follow_active_quads
import bpy
+from bpy.types import Operator
def extend(obj, operator, EXTEND_MODE):
@@ -42,7 +43,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):
'''
@@ -227,7 +227,7 @@ def main(context, operator):
extend(obj, operator, operator.properties.mode)
-class FollowActiveQuads(bpy.types.Operator):
+class FollowActiveQuads(Operator):
'''Follow UVs from active quads along continuous face loops'''
bl_idname = "uv.follow_active_quads"
bl_label = "Follow Active Quads"
diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
index 3893612437a..060fe400045 100644
--- a/release/scripts/startup/bl_operators/uvcalc_lightmap.py
+++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
@@ -19,11 +19,20 @@
# <pep8 compliant>
import bpy
+from bpy.types import Operator
import mathutils
class prettyface(object):
- __slots__ = "uv", "width", "height", "children", "xoff", "yoff", "has_parent", "rot"
+ __slots__ = ("uv",
+ "width",
+ "height",
+ "children",
+ "xoff",
+ "yoff",
+ "has_parent",
+ "rot",
+ )
def __init__(self, data):
self.has_parent = False
@@ -263,10 +272,9 @@ def lightmap_uvpack(meshes,
del trylens
def trilensdiff(t1, t2):
- return\
- abs(t1[1][t1[2][0]] - t2[1][t2[2][0]]) + \
- abs(t1[1][t1[2][1]] - t2[1][t2[2][1]]) + \
- abs(t1[1][t1[2][2]] - t2[1][t2[2][2]])
+ return (abs(t1[1][t1[2][0]] - t2[1][t2[2][0]]) +
+ abs(t1[1][t1[2][1]] - t2[1][t2[2][1]]) +
+ abs(t1[1][t1[2][2]] - t2[1][t2[2][2]]))
while tri_lengths:
tri1 = tri_lengths.pop()
@@ -406,7 +414,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 +435,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 +452,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 +497,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
@@ -517,7 +528,7 @@ def unwrap(operator, context, **kwargs):
if obj and obj.type == 'MESH':
meshes = [obj.data]
else:
- meshes = {me.name: me for obj in context.selected_objects if obj.type == 'MESH' for me in (obj.data,) if not me.library if len(me.faces)}.values()
+ meshes = list({me for obj in context.selected_objects if obj.type == 'MESH' for me in (obj.data,) if me.faces and me.library is None})
if not meshes:
operator.report({'ERROR'}, "No mesh object.")
@@ -530,32 +541,60 @@ 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):
+class LightMapPack(Operator):
'''Follow UVs from active quads along continuous face loops'''
bl_idname = "uv.lightmap_pack"
bl_label = "Lightmap Pack"
bl_options = {'REGISTER', 'UNDO'}
PREF_CONTEXT = bpy.props.EnumProperty(
+ name="Selection",
items=(("SEL_FACES", "Selected Faces", "Space all UVs evently"),
("ALL_FACES", "All Faces", "Average space UVs edge length of each loop"),
("ALL_OBJECTS", "Selected Mesh Object", "Average space UVs edge length of each loop")
),
- name="Selection",
- description="")
+ )
# Image & UVs...
- PREF_PACK_IN_ONE = BoolProperty(name="Share Tex Space", default=True, description="Objects Share texture space, map all objects into 1 uvmap")
- PREF_NEW_UVLAYER = BoolProperty(name="New UV Layer", default=False, description="Create a new UV layer for every mesh packed")
- PREF_APPLY_IMAGE = BoolProperty(name="New Image", default=False, description="Assign new images for every mesh (only one if shared tex space enabled)")
- PREF_IMG_PX_SIZE = IntProperty(name="Image Size", min=64, max=5000, default=512, description="Width and Height for the new image")
-
+ PREF_PACK_IN_ONE = BoolProperty(
+ name="Share Tex Space",
+ description=("Objects Share texture space, map all objects "
+ "into 1 uvmap"),
+ default=True,
+ )
+ PREF_NEW_UVLAYER = BoolProperty(
+ name="New UV Layer",
+ description="Create a new UV layer for every mesh packed",
+ default=False,
+ )
+ PREF_APPLY_IMAGE = BoolProperty(
+ name="New Image",
+ description=("Assign new images for every mesh (only one if "
+ "shared tex space enabled)"),
+ default=False,
+ )
+ PREF_IMG_PX_SIZE = IntProperty(
+ name="Image Size",
+ description="Width and Height for the new image",
+ min=64, max=5000,
+ default=512,
+ )
# UV Packing...
- PREF_BOX_DIV = IntProperty(name="Pack Quality", min=1, max=48, default=12, description="Pre Packing before the complex boxpack")
- PREF_MARGIN_DIV = FloatProperty(name="Margin", min=0.001, max=1.0, default=0.1, description="Size of the margin as a division of the UV")
+ PREF_BOX_DIV = IntProperty(
+ name="Pack Quality",
+ description="Pre Packing before the complex boxpack",
+ min=1, max=48,
+ default=12,
+ )
+ PREF_MARGIN_DIV = FloatProperty(
+ name="Margin",
+ description="Size of the margin as a division of the UV",
+ min=0.001, max=1.0,
+ default=0.1,
+ )
def execute(self, context):
kwargs = self.as_keywords()
diff --git a/release/scripts/startup/bl_operators/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
index 4f5b1d8b233..23838588f43 100644
--- a/release/scripts/startup/bl_operators/uvcalc_smart_project.py
+++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
@@ -16,10 +16,11 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# TODO <pep8 compliant>
from mathutils import Matrix, Vector, geometry
import bpy
+from bpy.types import Operator
DEG_TO_RAD = 0.017453292519943295 # pi/180.0
SMALL_NUM = 0.000000001
@@ -177,7 +178,7 @@ def pointInEdges(pt, edges):
intersectCount = 0
for ed in edges:
xi, yi = lineIntersection2D(x1,y1, x2,y2, ed[0][0], ed[0][1], ed[1][0], ed[1][1])
- if xi != None: # Is there an intersection.
+ if xi is not None: # Is there an intersection.
intersectCount+=1
return intersectCount % 2
@@ -243,7 +244,7 @@ def testNewVecLs2DRotIsBetter(vecs, mat=-1, bestAreaSoFar = -1):
# Do this allong the way
if mat != -1:
- v = vecs[i] = v*mat
+ v = vecs[i] = mat * v
x= v.x
y= v.y
if x<minx: minx= x
@@ -746,13 +747,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 +788,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,35 +813,25 @@ def main(context, island_margin, projection_limit):
global RotMatStepRotation
main_consts()
-#XXX objects= bpy.data.scenes.active.objects
- objects = context.selected_editable_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]
-
- if ob and (not ob.select) and ob.type == 'MESH':
- # Add to the list
- obList =[ob]
- del objects
-
- if not obList:
- raise('error, no selected mesh objects')
-
# Create the variables.
USER_PROJECTION_LIMIT = projection_limit
- USER_ONLY_SELECTED_FACES = (1)
- USER_SHARE_SPACE = (1) # Only for hole filling.
- USER_STRETCH_ASPECT = (1) # Only for hole filling.
+ USER_ONLY_SELECTED_FACES = True
+ USER_SHARE_SPACE = 1 # Only for hole filling.
+ USER_STRETCH_ASPECT = 1 # Only for hole filling.
USER_ISLAND_MARGIN = island_margin # Only for hole filling.
- 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.
+ USER_FILL_HOLES = 0
+ USER_FILL_HOLES_QUALITY = 50 # Only for hole filling.
+ USER_VIEW_INIT = 0 # Only for hole filling.
+
+ is_editmode = (context.active_object.mode == 'EDIT')
+ if is_editmode:
+ obList = [ob for ob in [context.active_object] if ob and ob.type == 'MESH']
+ else:
+ obList = [ob for ob in context.selected_editable_objects if ob and ob.type == 'MESH']
+ USER_ONLY_SELECTED_FACES = False
+
+ if not obList:
+ raise('error, no selected mesh objects')
# Reuse variable
if len(obList) == 1:
@@ -902,8 +893,8 @@ def main(context, island_margin, projection_limit):
if USER_ONLY_SELECTED_FACES:
meshFaces = [thickface(f, uv_layer[i], me_verts) for i, f in enumerate(me.faces) if f.select]
- #else:
- # meshFaces = map(thickface, me.faces)
+ else:
+ meshFaces = [thickface(f, uv_layer[i], me_verts) for i, f in enumerate(me.faces)]
if not meshFaces:
continue
@@ -918,7 +909,7 @@ def main(context, island_margin, projection_limit):
# meshFaces = []
# meshFaces.sort( lambda a, b: cmp(b.area , a.area) ) # Biggest first.
- meshFaces.sort( key = lambda a: -a.area )
+ meshFaces.sort(key=lambda a: -a.area)
# remove all zero area faces
while meshFaces and meshFaces[-1].area <= SMALL_NUM:
@@ -966,12 +957,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 +1052,7 @@ def main(context, island_margin, projection_limit):
f_uv = f.uv
for j, v in enumerate(f.v):
# XXX - note, between mathutils in 2.4 and 2.5 the order changed.
- f_uv[j][:] = (v.co * MatQuat)[:2]
+ f_uv[j][:] = (MatQuat * v.co).xy
if USER_SHARE_SPACE:
@@ -1094,12 +1088,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.'),\
@@ -1114,26 +1104,41 @@ def main(context, island_margin, projection_limit):
from bpy.props import FloatProperty
-class SmartProject(bpy.types.Operator):
+class SmartProject(Operator):
'''This script projection unwraps the selected faces of a mesh. it operates on all selected mesh objects, and can be used unwrap selected faces, or all faces.'''
bl_idname = "uv.smart_project"
bl_label = "Smart UV Project"
bl_options = {'REGISTER', 'UNDO'}
- angle_limit = FloatProperty(name="Angle Limit",
- 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.",
- default=0.0, min=0.0, max=1.0)
+ angle_limit = FloatProperty(
+ name="Angle Limit",
+ description="lower for more projection groups, higher for less distortion",
+ min=1.0, max=89.0,
+ default=66.0,
+ )
+ island_margin = FloatProperty(
+ name="Island Margin",
+ description="Margin to reduce bleed from adjacent islands",
+ min=0.0, max=1.0,
+ default=0.0,
+ )
+ user_area_weight = FloatProperty(
+ name="Area Weight",
+ description="Weight projections vector by faces with larger areas",
+ min=0.0, max=1.0,
+ default=0.0,
+ )
@classmethod
def poll(cls, context):
- return context.active_object != None
+ return context.active_object is not 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/vertexpaint_dirt.py b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
index 672db71e361..4c78adb7161 100644
--- a/release/scripts/startup/bl_operators/vertexpaint_dirt.py
+++ b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
@@ -142,19 +142,44 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
import bpy
+from bpy.types import Operator
from bpy.props import FloatProperty, IntProperty, BoolProperty
-class VertexPaintDirt(bpy.types.Operator):
+class VertexPaintDirt(Operator):
bl_idname = "paint.vertex_color_dirt"
bl_label = "Dirty Vertex Colors"
bl_options = {'REGISTER', 'UNDO'}
- blur_strength = FloatProperty(name="Blur Strength", description="Blur strength per iteration", default=1.0, min=0.01, max=1.0)
- blur_iterations = IntProperty(name="Blur Iterations", description="Number times to blur the colors. (higher blurs more)", default=1, min=0, max=40)
- clean_angle = FloatProperty(name="Highlight Angle", description="Less then 90 limits the angle used in the tonal range", default=180.0, min=0.0, max=180.0)
- dirt_angle = FloatProperty(name="Dirt Angle", description="Less then 90 limits the angle used in the tonal range", default=0.0, min=0.0, max=180.0)
- dirt_only = BoolProperty(name="Dirt Only", description="Dont calculate cleans for convex areas", default=False)
+ blur_strength = FloatProperty(
+ name="Blur Strength",
+ description="Blur strength per iteration",
+ min=0.01, max=1.0,
+ default=1.0,
+ )
+ blur_iterations = IntProperty(
+ name="Blur Iterations",
+ description="Number times to blur the colors. (higher blurs more)",
+ min=0, max=40,
+ default=1,
+ )
+ clean_angle = FloatProperty(
+ name="Highlight Angle",
+ description="Less then 90 limits the angle used in the tonal range",
+ min=0.0, max=180.0,
+ default=180.0,
+ )
+ dirt_angle = FloatProperty(
+ name="Dirt Angle",
+ description="Less then 90 limits the angle used in the tonal range",
+ min=0.0, max=180.0,
+ default=0.0,
+ )
+ dirt_only = BoolProperty(
+ name="Dirt Only",
+ description="Dont calculate cleans for convex areas",
+ default=False,
+ )
def execute(self, context):
import time
diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py
index fcc30ecbb4b..aa09a088c4f 100644
--- a/release/scripts/startup/bl_operators/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -19,11 +19,18 @@
# <pep8 compliant>
import bpy
-from bpy.props import StringProperty, BoolProperty, IntProperty, FloatProperty
+from bpy.types import Menu, Operator
+from bpy.props import (StringProperty,
+ BoolProperty,
+ IntProperty,
+ FloatProperty,
+ EnumProperty,
+ )
+
from rna_prop_ui import rna_idprop_ui_prop_get, rna_idprop_ui_prop_clear
-class MESH_OT_delete_edgeloop(bpy.types.Operator):
+class MESH_OT_delete_edgeloop(Operator):
'''Delete an edge loop by merging the faces on each side to a single face loop'''
bl_idname = "mesh.delete_edgeloop"
bl_label = "Delete Edge Loop"
@@ -36,23 +43,30 @@ class MESH_OT_delete_edgeloop(bpy.types.Operator):
return {'CANCELLED'}
-rna_path_prop = StringProperty(name="Context Attributes",
- description="rna context string", maxlen=1024, default="")
+rna_path_prop = StringProperty(
+ name="Context Attributes",
+ description="rna context string",
+ maxlen=1024,
+ )
-rna_reverse_prop = BoolProperty(name="Reverse",
- description="Cycle backwards", default=False)
+rna_reverse_prop = BoolProperty(
+ name="Reverse",
+ description="Cycle backwards",
+ default=False,
+ )
-rna_relative_prop = BoolProperty(name="Relative",
+rna_relative_prop = BoolProperty(
+ name="Relative",
description="Apply relative to the current value (delta)",
- default=False)
+ default=False,
+ )
def context_path_validate(context, data_path):
- import sys
try:
value = eval("context.%s" % data_path) if data_path else Ellipsis
- except AttributeError:
- if "'NoneType'" in str(sys.exc_info()[1]):
+ except AttributeError as e:
+ if str(e).startswith("'NoneType'"):
# One of the items in the rna path is None, just ignore this
value = Ellipsis
else:
@@ -62,32 +76,87 @@ def context_path_validate(context, data_path):
return value
+def operator_value_is_undo(value):
+ if value in {None, Ellipsis}:
+ return False
+
+ # typical properties or objects
+ id_data = getattr(value, "id_data", Ellipsis)
+
+ if id_data is None:
+ return False
+ elif id_data is Ellipsis:
+ # handle mathutils types
+ id_data = getattr(getattr(value, "owner", None), "id_data", None)
+
+ if id_data is None:
+ return False
+
+ # return True if its a non window ID type
+ return (isinstance(id_data, bpy.types.ID) and
+ (not isinstance(id_data, (bpy.types.WindowManager,
+ bpy.types.Screen,
+ bpy.types.Scene,
+ bpy.types.Brush,
+ ))))
+
+
+def operator_path_is_undo(context, data_path):
+ # note that if we have data paths that use strings this could fail
+ # luckily we dont do this!
+ #
+ # When we cant find the data owner assume no undo is needed.
+ data_path_head, data_path_sep, data_path_tail = data_path.rpartition(".")
+
+ if not data_path_head:
+ return False
+
+ value = context_path_validate(context, data_path_head)
+
+ return operator_value_is_undo(value)
+
+
+def operator_path_undo_return(context, data_path):
+ return {'FINISHED'} if operator_path_is_undo(context, data_path) else {'CANCELLED'}
+
+
+def operator_value_undo_return(value):
+ return {'FINISHED'} if operator_value_is_undo(value) else {'CANCELLED'}
+
+
def execute_context_assign(self, context):
- if context_path_validate(context, self.data_path) is Ellipsis:
+ data_path = self.data_path
+ if context_path_validate(context, data_path) is Ellipsis:
return {'PASS_THROUGH'}
if getattr(self, "relative", False):
- exec("context.%s+=self.value" % self.data_path)
+ exec("context.%s += self.value" % data_path)
else:
- exec("context.%s=self.value" % self.data_path)
+ exec("context.%s = self.value" % data_path)
- return {'FINISHED'}
+ return operator_path_undo_return(context, data_path)
-class BRUSH_OT_active_index_set(bpy.types.Operator):
+class BRUSH_OT_active_index_set(Operator):
'''Set active sculpt/paint brush from it's number'''
bl_idname = "brush.active_index_set"
bl_label = "Set Brush Number"
- mode = StringProperty(name="mode",
- description="Paint mode to set brush for", maxlen=1024)
- index = IntProperty(name="number",
- description="Brush number")
+ mode = StringProperty(
+ name="mode",
+ description="Paint mode to set brush for",
+ maxlen=1024,
+ )
+ index = IntProperty(
+ name="number",
+ description="Brush number",
+ )
_attr_dict = {"sculpt": "use_paint_sculpt",
"vertex_paint": "use_paint_vertex",
"weight_paint": "use_paint_weight",
- "image_paint": "use_paint_image"}
+ "image_paint": "use_paint_image",
+ }
def execute(self, context):
attr = self._attr_dict.get(self.mode)
@@ -102,50 +171,63 @@ class BRUSH_OT_active_index_set(bpy.types.Operator):
return {'CANCELLED'}
-class WM_OT_context_set_boolean(bpy.types.Operator):
+class WM_OT_context_set_boolean(Operator):
'''Set a context value.'''
bl_idname = "wm.context_set_boolean"
bl_label = "Context Set Boolean"
bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
- value = BoolProperty(name="Value",
- description="Assignment value", default=True)
+ value = BoolProperty(
+ name="Value",
+ description="Assignment value",
+ default=True,
+ )
execute = execute_context_assign
-class WM_OT_context_set_int(bpy.types.Operator): # same as enum
+class WM_OT_context_set_int(Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_int"
bl_label = "Context Set"
bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
- value = IntProperty(name="Value", description="Assign value", default=0)
+ value = IntProperty(
+ name="Value",
+ description="Assign value",
+ default=0,
+ )
relative = rna_relative_prop
execute = execute_context_assign
-class WM_OT_context_scale_int(bpy.types.Operator):
+class WM_OT_context_scale_int(Operator):
'''Scale an int context value.'''
bl_idname = "wm.context_scale_int"
bl_label = "Context Set"
bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
- value = FloatProperty(name="Value", description="Assign value", default=1.0)
- always_step = BoolProperty(name="Always Step",
- description="Always adjust the value by a minimum of 1 when 'value' is not 1.0.",
- default=True)
+ value = FloatProperty(
+ name="Value",
+ description="Assign value",
+ default=1.0,
+ )
+ always_step = BoolProperty(
+ name="Always Step",
+ description="Always adjust the value by a minimum of 1 when 'value' is not 1.0.",
+ default=True,
+ )
def execute(self, context):
- if context_path_validate(context, self.data_path) is Ellipsis:
+ data_path = self.data_path
+ if context_path_validate(context, data_path) is Ellipsis:
return {'PASS_THROUGH'}
value = self.value
- data_path = self.data_path
if value == 1.0: # nothing to do
return {'CANCELLED'}
@@ -157,73 +239,85 @@ class WM_OT_context_scale_int(bpy.types.Operator):
else:
add = "-1"
func = "min"
- exec("context.%s = %s(round(context.%s * value), context.%s + %s)" % (data_path, func, data_path, data_path, add))
+ exec("context.%s = %s(round(context.%s * value), context.%s + %s)" %
+ (data_path, func, data_path, data_path, add))
else:
- exec("context.%s *= value" % self.data_path)
+ exec("context.%s *= value" % data_path)
- return {'FINISHED'}
+ return operator_path_undo_return(context, data_path)
-class WM_OT_context_set_float(bpy.types.Operator): # same as enum
+class WM_OT_context_set_float(Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_float"
bl_label = "Context Set Float"
bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
- value = FloatProperty(name="Value",
- description="Assignment value", default=0.0)
+ value = FloatProperty(
+ name="Value",
+ description="Assignment value",
+ default=0.0,
+ )
relative = rna_relative_prop
execute = execute_context_assign
-class WM_OT_context_set_string(bpy.types.Operator): # same as enum
+class WM_OT_context_set_string(Operator): # same as enum
'''Set a context value.'''
bl_idname = "wm.context_set_string"
bl_label = "Context Set String"
bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
- value = StringProperty(name="Value",
- description="Assign value", maxlen=1024, default="")
+ value = StringProperty(
+ name="Value",
+ description="Assign value",
+ maxlen=1024,
+ )
execute = execute_context_assign
-class WM_OT_context_set_enum(bpy.types.Operator):
+class WM_OT_context_set_enum(Operator):
'''Set a context value.'''
bl_idname = "wm.context_set_enum"
bl_label = "Context Set Enum"
bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
- value = StringProperty(name="Value",
+ value = StringProperty(
+ name="Value",
description="Assignment value (as a string)",
- maxlen=1024, default="")
+ maxlen=1024,
+ )
execute = execute_context_assign
-class WM_OT_context_set_value(bpy.types.Operator):
+class WM_OT_context_set_value(Operator):
'''Set a context value.'''
bl_idname = "wm.context_set_value"
bl_label = "Context Set Value"
bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
- value = StringProperty(name="Value",
+ value = StringProperty(
+ name="Value",
description="Assignment value (as a string)",
- maxlen=1024, default="")
+ maxlen=1024,
+ )
def execute(self, context):
- if context_path_validate(context, self.data_path) is Ellipsis:
+ data_path = self.data_path
+ if context_path_validate(context, data_path) is Ellipsis:
return {'PASS_THROUGH'}
- exec("context.%s=%s" % (self.data_path, self.value))
- return {'FINISHED'}
+ exec("context.%s = %s" % (data_path, self.value))
+ return operator_path_undo_return(context, data_path)
-class WM_OT_context_toggle(bpy.types.Operator):
+class WM_OT_context_toggle(Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_toggle"
bl_label = "Context Toggle"
@@ -232,43 +326,50 @@ class WM_OT_context_toggle(bpy.types.Operator):
data_path = rna_path_prop
def execute(self, context):
+ data_path = self.data_path
- if context_path_validate(context, self.data_path) is Ellipsis:
+ if context_path_validate(context, data_path) is Ellipsis:
return {'PASS_THROUGH'}
- exec("context.%s=not (context.%s)" %
- (self.data_path, self.data_path))
+ exec("context.%s = not (context.%s)" % (data_path, data_path))
- return {'FINISHED'}
+ return operator_path_undo_return(context, data_path)
-class WM_OT_context_toggle_enum(bpy.types.Operator):
+class WM_OT_context_toggle_enum(Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_toggle_enum"
bl_label = "Context Toggle Values"
bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
- value_1 = StringProperty(name="Value", \
- description="Toggle enum", maxlen=1024, default="")
-
- value_2 = StringProperty(name="Value", \
- description="Toggle enum", maxlen=1024, default="")
+ value_1 = StringProperty(
+ name="Value",
+ description="Toggle enum",
+ maxlen=1024,
+ )
+ value_2 = StringProperty(
+ name="Value",
+ description="Toggle enum",
+ maxlen=1024,
+ )
def execute(self, context):
+ data_path = self.data_path
- if context_path_validate(context, self.data_path) is Ellipsis:
+ if context_path_validate(context, data_path) is Ellipsis:
return {'PASS_THROUGH'}
- exec("context.%s = ['%s', '%s'][context.%s!='%s']" % \
- (self.data_path, self.value_1,\
- self.value_2, self.data_path,
- self.value_2))
+ exec("context.%s = ('%s', '%s')[context.%s != '%s']" %
+ (data_path, self.value_1,
+ self.value_2, data_path,
+ self.value_2,
+ ))
- return {'FINISHED'}
+ return operator_path_undo_return(context, data_path)
-class WM_OT_context_cycle_int(bpy.types.Operator):
+class WM_OT_context_cycle_int(Operator):
'''Set a context value. Useful for cycling active material, '''
'''vertex keys, groups' etc.'''
bl_idname = "wm.context_cycle_int"
@@ -289,7 +390,7 @@ class WM_OT_context_cycle_int(bpy.types.Operator):
else:
value += 1
- exec("context.%s=value" % data_path)
+ exec("context.%s = value" % data_path)
if value != eval("context.%s" % data_path):
# relies on rna clamping int's out of the range
@@ -298,12 +399,12 @@ class WM_OT_context_cycle_int(bpy.types.Operator):
else:
value = -1 << 31
- exec("context.%s=value" % data_path)
+ exec("context.%s = value" % data_path)
- return {'FINISHED'}
+ return operator_path_undo_return(context, data_path)
-class WM_OT_context_cycle_enum(bpy.types.Operator):
+class WM_OT_context_cycle_enum(Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_cycle_enum"
bl_label = "Context Enum Cycle"
@@ -313,15 +414,15 @@ class WM_OT_context_cycle_enum(bpy.types.Operator):
reverse = rna_reverse_prop
def execute(self, context):
-
- value = context_path_validate(context, self.data_path)
+ data_path = self.data_path
+ value = context_path_validate(context, data_path)
if value is Ellipsis:
return {'PASS_THROUGH'}
orig_value = value
# Have to get rna enum values
- rna_struct_str, rna_prop_str = self.data_path.rsplit('.', 1)
+ rna_struct_str, rna_prop_str = data_path.rsplit('.', 1)
i = rna_prop_str.find('[')
# just incse we get "context.foo.bar[0]"
@@ -351,11 +452,11 @@ class WM_OT_context_cycle_enum(bpy.types.Operator):
advance_enum = enums[orig_index + 1]
# set the new value
- exec("context.%s=advance_enum" % self.data_path)
- return {'FINISHED'}
+ exec("context.%s = advance_enum" % data_path)
+ return operator_path_undo_return(context, data_path)
-class WM_OT_context_cycle_array(bpy.types.Operator):
+class WM_OT_context_cycle_array(Operator):
'''Set a context array value.
Useful for cycling the active mesh edit mode.'''
bl_idname = "wm.context_cycle_array"
@@ -378,12 +479,12 @@ class WM_OT_context_cycle_array(bpy.types.Operator):
array.append(array.pop(0))
return array
- exec("context.%s=cycle(context.%s[:])" % (data_path, data_path))
+ exec("context.%s = cycle(context.%s[:])" % (data_path, data_path))
- return {'FINISHED'}
+ return operator_path_undo_return(context, data_path)
-class WM_MT_context_menu_enum(bpy.types.Menu):
+class WM_MT_context_menu_enum(Menu):
bl_label = ""
data_path = "" # BAD DESIGN, set from operator below.
@@ -403,7 +504,7 @@ class WM_MT_context_menu_enum(bpy.types.Menu):
prop.value = identifier
-class WM_OT_context_menu_enum(bpy.types.Operator):
+class WM_OT_context_menu_enum(Operator):
bl_idname = "wm.context_menu_enum"
bl_label = "Context Enum Menu"
bl_options = {'UNDO', 'INTERNAL'}
@@ -416,15 +517,18 @@ class WM_OT_context_menu_enum(bpy.types.Operator):
return {'PASS_THROUGH'}
-class WM_OT_context_set_id(bpy.types.Operator):
+class WM_OT_context_set_id(Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_set_id"
bl_label = "Set Library ID"
bl_options = {'UNDO', 'INTERNAL'}
data_path = rna_path_prop
- value = StringProperty(name="Value",
- description="Assign value", maxlen=1024, default="")
+ value = StringProperty(
+ name="Value",
+ description="Assign value",
+ maxlen=1024,
+ )
def execute(self, context):
value = self.value
@@ -446,28 +550,105 @@ class WM_OT_context_set_id(bpy.types.Operator):
if id_iter:
value_id = getattr(bpy.data, id_iter).get(value)
- exec("context.%s=value_id" % data_path)
+ exec("context.%s = value_id" % data_path)
- return {'FINISHED'}
+ return operator_path_undo_return(context, data_path)
+
+
+doc_id = StringProperty(
+ name="Doc ID",
+ maxlen=1024,
+ options={'HIDDEN'},
+ )
+
+doc_new = StringProperty(
+ name="Edit Description",
+ maxlen=1024,
+ )
+
+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(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
-doc_id = StringProperty(name="Doc ID",
- description="", maxlen=1024, default="", options={'HIDDEN'})
+ type = EnumProperty(
+ name="Type",
+ items=(('TOGGLE', "Toggle", ""),
+ ('ENABLE', "Enable", ""),
+ ('DISABLE', "Disable", ""),
+ ),
+ )
-doc_new = StringProperty(name="Edit Description",
- description="", maxlen=1024, default="")
+ 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)
+
+ # avoid undo push when nothing to do
+ if not items_ok:
+ return {'CANCELLED'}
+
+ 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 operator_value_undo_return(item)
-class WM_OT_context_modal_mouse(bpy.types.Operator):
+class WM_OT_context_modal_mouse(Operator):
'''Adjust arbitrary values with mouse input'''
bl_idname = "wm.context_modal_mouse"
bl_label = "Context Modal Mouse"
- bl_options = {'INTERNAL'}
-
- 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")
+ bl_options = {'GRAB_POINTER', 'BLOCKING', 'UNDO', 'INTERNAL'}
+
+ data_path_iter = data_path_iter
+ data_path_item = data_path_item
+
+ input_scale = FloatProperty(
+ description="Scale the mouse movement by this value before applying the delta",
+ default=0.01,
+ )
+ invert = BoolProperty(
+ description="Invert the mouse input",
+ default=False,
+ )
initial_x = IntProperty(options={'HIDDEN'})
def _values_store(self, context):
@@ -520,12 +701,13 @@ class WM_OT_context_modal_mouse(bpy.types.Operator):
self._values_delta(delta)
elif 'LEFTMOUSE' == event_type:
+ item = next(iter(self._values.keys()))
self._values_clear()
- return {'FINISHED'}
+ return operator_value_undo_return(item)
- elif event_type in ('RIGHTMOUSE', 'ESC'):
+ elif event_type in {'RIGHTMOUSE', 'ESC'}:
self._values_restore()
- return {'FINISHED'}
+ return {'CANCELLED'}
return {'RUNNING_MODAL'}
@@ -544,26 +726,32 @@ class WM_OT_context_modal_mouse(bpy.types.Operator):
return {'RUNNING_MODAL'}
-class WM_OT_url_open(bpy.types.Operator):
+class WM_OT_url_open(Operator):
"Open a website in the Webbrowser"
bl_idname = "wm.url_open"
bl_label = ""
- url = StringProperty(name="URL", description="URL to open")
+ url = StringProperty(
+ name="URL",
+ description="URL to open",
+ )
def execute(self, context):
import webbrowser
- _webbrowser_bug_fix()
webbrowser.open(self.url)
return {'FINISHED'}
-class WM_OT_path_open(bpy.types.Operator):
+class WM_OT_path_open(Operator):
"Open a path in a file browser"
bl_idname = "wm.path_open"
bl_label = ""
- filepath = StringProperty(name="File Path", maxlen=1024, subtype='FILE_PATH')
+ filepath = StringProperty(
+ name="File Path",
+ maxlen=1024,
+ subtype='FILE_PATH',
+ )
def execute(self, context):
import sys
@@ -591,16 +779,18 @@ class WM_OT_path_open(bpy.types.Operator):
return {'FINISHED'}
-class WM_OT_doc_view(bpy.types.Operator):
+class WM_OT_doc_view(Operator):
'''Load online reference docs'''
bl_idname = "wm.doc_view"
bl_label = "View Documentation"
doc_id = doc_id
if bpy.app.version_cycle == "release":
- _prefix = "http://www.blender.org/documentation/blender_python_api_%s%s_release" % ("_".join(str(v) for v in bpy.app.version[:2]), bpy.app.version_char)
+ _prefix = ("http://www.blender.org/documentation/blender_python_api_%s%s_release" %
+ ("_".join(str(v) for v in bpy.app.version[:2]), bpy.app.version_char))
else:
- _prefix = "http://www.blender.org/documentation/blender_python_api_%s" % "_".join(str(v) for v in bpy.app.version)
+ _prefix = ("http://www.blender.org/documentation/blender_python_api_%s" %
+ "_".join(str(v) for v in bpy.app.version))
def _nested_class_string(self, class_string):
ls = []
@@ -618,8 +808,8 @@ class WM_OT_doc_view(bpy.types.Operator):
class_name, class_prop = id_split
if hasattr(bpy.types, class_name.upper() + '_OT_' + class_prop):
- url = '%s/bpy.ops.%s.html#bpy.ops.%s.%s' % \
- (self._prefix, class_name, class_name, class_prop)
+ url = ("%s/bpy.ops.%s.html#bpy.ops.%s.%s" %
+ (self._prefix, class_name, class_name, class_prop))
else:
# detect if this is a inherited member and use that name instead
@@ -632,20 +822,19 @@ class WM_OT_doc_view(bpy.types.Operator):
# It so happens that epydoc nests these, not sphinx
# class_name_full = self._nested_class_string(class_name)
- url = '%s/bpy.types.%s.html#bpy.types.%s.%s' % \
- (self._prefix, class_name, class_name, class_prop)
+ url = ("%s/bpy.types.%s.html#bpy.types.%s.%s" %
+ (self._prefix, class_name, class_name, class_prop))
else:
return {'PASS_THROUGH'}
import webbrowser
- _webbrowser_bug_fix()
webbrowser.open(url)
return {'FINISHED'}
-class WM_OT_doc_edit(bpy.types.Operator):
+class WM_OT_doc_edit(Operator):
'''Load online reference docs'''
bl_idname = "wm.doc_edit"
bl_label = "Edit Documentation"
@@ -716,20 +905,39 @@ class WM_OT_doc_edit(bpy.types.Operator):
return wm.invoke_props_dialog(self, width=600)
-rna_path = StringProperty(name="Property Edit",
- description="Property data_path edit", maxlen=1024, default="", options={'HIDDEN'})
+rna_path = StringProperty(
+ name="Property Edit",
+ description="Property data_path edit",
+ maxlen=1024,
+ options={'HIDDEN'},
+ )
+
+rna_value = StringProperty(
+ name="Property Value",
+ description="Property value edit",
+ maxlen=1024,
+ )
-rna_value = StringProperty(name="Property Value",
- description="Property value edit", maxlen=1024, default="")
+rna_property = StringProperty(
+ name="Property Name",
+ description="Property name edit",
+ maxlen=1024,
+ )
-rna_property = StringProperty(name="Property Name",
- description="Property name edit", maxlen=1024, default="")
+rna_min = FloatProperty(
+ name="Min",
+ default=0.0,
+ precision=3,
+ )
-rna_min = FloatProperty(name="Min", default=0.0, precision=3)
-rna_max = FloatProperty(name="Max", default=1.0, precision=3)
+rna_max = FloatProperty(
+ name="Max",
+ default=1.0,
+ precision=3,
+ )
-class WM_OT_properties_edit(bpy.types.Operator):
+class WM_OT_properties_edit(Operator):
'''Internal use (edit a property data_path)'''
bl_idname = "wm.properties_edit"
bl_label = "Edit Property"
@@ -740,7 +948,9 @@ class WM_OT_properties_edit(bpy.types.Operator):
value = rna_value
min = rna_min
max = rna_max
- description = StringProperty(name="Tip", default="")
+ description = StringProperty(
+ name="Tip",
+ )
def execute(self, context):
data_path = self.data_path
@@ -776,7 +986,7 @@ class WM_OT_properties_edit(bpy.types.Operator):
prop_ui = rna_idprop_ui_prop_get(item, prop)
- if prop_type in (float, int):
+ if prop_type in {float, int}:
prop_ui['soft_min'] = prop_ui['min'] = prop_type(self.min)
prop_ui['soft_max'] = prop_ui['max'] = prop_type(self.max)
@@ -793,14 +1003,15 @@ class WM_OT_properties_edit(bpy.types.Operator):
return {'FINISHED'}
def invoke(self, context, event):
+ data_path = self.data_path
- if not self.data_path:
+ if not data_path:
self.report({'ERROR'}, "Data path not set")
return {'CANCELLED'}
self._last_prop = [self.property]
- item = eval("context.%s" % self.data_path)
+ item = eval("context.%s" % data_path)
# setup defaults
prop_ui = rna_idprop_ui_prop_get(item, self.property, False) # dont create
@@ -813,7 +1024,7 @@ class WM_OT_properties_edit(bpy.types.Operator):
return wm.invoke_props_dialog(self)
-class WM_OT_properties_add(bpy.types.Operator):
+class WM_OT_properties_add(Operator):
'''Internal use (edit a property data_path)'''
bl_idname = "wm.properties_add"
bl_label = "Add Property"
@@ -821,7 +1032,8 @@ class WM_OT_properties_add(bpy.types.Operator):
data_path = rna_path
def execute(self, context):
- item = eval("context.%s" % self.data_path)
+ data_path = self.data_path
+ item = eval("context.%s" % data_path)
def unique_name(names):
prop = 'prop'
@@ -839,19 +1051,22 @@ class WM_OT_properties_add(bpy.types.Operator):
return {'FINISHED'}
-class WM_OT_properties_context_change(bpy.types.Operator):
+class WM_OT_properties_context_change(Operator):
"Change the context tab in a Properties Window"
bl_idname = "wm.properties_context_change"
bl_label = ""
- context = StringProperty(name="Context", maxlen=32)
+ context = StringProperty(
+ name="Context",
+ maxlen=32,
+ )
def execute(self, context):
- context.space_data.context = (self.context)
+ context.space_data.context = self.context
return {'FINISHED'}
-class WM_OT_properties_remove(bpy.types.Operator):
+class WM_OT_properties_remove(Operator):
'''Internal use (edit a property data_path)'''
bl_idname = "wm.properties_remove"
bl_label = "Remove Property"
@@ -860,23 +1075,27 @@ class WM_OT_properties_remove(bpy.types.Operator):
property = rna_property
def execute(self, context):
- item = eval("context.%s" % self.data_path)
+ data_path = self.data_path
+ item = eval("context.%s" % data_path)
del item[self.property]
return {'FINISHED'}
-class WM_OT_keyconfig_activate(bpy.types.Operator):
+class WM_OT_keyconfig_activate(Operator):
bl_idname = "wm.keyconfig_activate"
bl_label = "Activate Keyconfig"
- filepath = StringProperty(name="File Path", maxlen=1024)
+ filepath = StringProperty(
+ name="File Path",
+ maxlen=1024,
+ )
def execute(self, context):
bpy.utils.keyconfig_set(self.filepath)
return {'FINISHED'}
-class WM_OT_appconfig_default(bpy.types.Operator):
+class WM_OT_appconfig_default(Operator):
bl_idname = "wm.appconfig_default"
bl_label = "Default Application Configuration"
@@ -893,11 +1112,14 @@ class WM_OT_appconfig_default(bpy.types.Operator):
return {'FINISHED'}
-class WM_OT_appconfig_activate(bpy.types.Operator):
+class WM_OT_appconfig_activate(Operator):
bl_idname = "wm.appconfig_activate"
bl_label = "Activate Application Configuration"
- filepath = StringProperty(name="File Path", maxlen=1024)
+ filepath = StringProperty(
+ name="File Path",
+ maxlen=1024,
+ )
def execute(self, context):
import os
@@ -911,7 +1133,7 @@ class WM_OT_appconfig_activate(bpy.types.Operator):
return {'FINISHED'}
-class WM_OT_sysinfo(bpy.types.Operator):
+class WM_OT_sysinfo(Operator):
'''Generate System Info'''
bl_idname = "wm.sysinfo"
bl_label = "System Info"
@@ -922,7 +1144,7 @@ class WM_OT_sysinfo(bpy.types.Operator):
return {'FINISHED'}
-class WM_OT_copy_prev_settings(bpy.types.Operator):
+class WM_OT_copy_prev_settings(Operator):
'''Copy settings from previous version'''
bl_idname = "wm.copy_prev_settings"
bl_label = "Copy Previous Settings"
@@ -957,65 +1179,3 @@ class WM_OT_copy_prev_settings(bpy.types.Operator):
return {'FINISHED'}
return {'CANCELLED'}
-
-
-def _webbrowser_bug_fix():
- # test for X11
- import os
-
- if os.environ.get("DISPLAY"):
-
- # BSD licenced code copied from python, temp fix for bug
- # http://bugs.python.org/issue11432, XXX == added code
- def _invoke(self, args, remote, autoraise):
- # XXX, added imports
- import io
- import subprocess
- import time
-
- raise_opt = []
- if remote and self.raise_opts:
- # use autoraise argument only for remote invocation
- autoraise = int(autoraise)
- opt = self.raise_opts[autoraise]
- if opt:
- raise_opt = [opt]
-
- cmdline = [self.name] + raise_opt + args
-
- if remote or self.background:
- inout = io.open(os.devnull, "r+")
- else:
- # for TTY browsers, we need stdin/out
- inout = None
- # if possible, put browser in separate process group, so
- # keyboard interrupts don't affect browser as well as Python
- setsid = getattr(os, 'setsid', None)
- if not setsid:
- setsid = getattr(os, 'setpgrp', None)
-
- p = subprocess.Popen(cmdline, close_fds=True, # XXX, stdin=inout,
- stdout=(self.redirect_stdout and inout or None),
- stderr=inout, preexec_fn=setsid)
- if remote:
- # wait five secons. If the subprocess is not finished, the
- # remote invocation has (hopefully) started a new instance.
- time.sleep(1)
- rc = p.poll()
- if rc is None:
- time.sleep(4)
- rc = p.poll()
- if rc is None:
- return True
- # if remote call failed, open() will try direct invocation
- return not rc
- elif self.background:
- if p.poll() is None:
- return True
- else:
- return False
- else:
- return not p.wait()
-
- import webbrowser
- webbrowser.UnixBrowser._invoke = _invoke
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index bf63c6071b9..778571632b2 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -36,6 +36,7 @@ _modules = (
"properties_data_mesh",
"properties_data_metaball",
"properties_data_modifier",
+ "properties_data_speaker",
"properties_game",
"properties_material",
"properties_object_constraint",
@@ -102,7 +103,10 @@ def register():
items.extend([(cat, cat, "") for cat in sorted(items_unique)])
return items
- WindowManager.addon_search = StringProperty(name="Search", description="Search within the selected filter")
+ WindowManager.addon_search = StringProperty(
+ name="Search",
+ description="Search within the selected filter",
+ )
WindowManager.addon_filter = EnumProperty(
items=addon_filter_items,
name="Category",
diff --git a/release/scripts/startup/bl_ui/properties_animviz.py b/release/scripts/startup/bl_ui/properties_animviz.py
index eb1bbfd2fb1..3b33a7ccc61 100644
--- a/release/scripts/startup/bl_ui/properties_animviz.py
+++ b/release/scripts/startup/bl_ui/properties_animviz.py
@@ -94,4 +94,5 @@ class OnionSkinButtonsPanel():
col.prop(arm, "show_only_ghost_selected", text="Selected Only")
if __name__ == "__main__": # only for live edit.
+ import bpy
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index 9477dc866ab..463ba84470f 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel, Menu
from rna_prop_ui import PropertyPanel
@@ -31,7 +32,7 @@ class ArmatureButtonsPanel():
return context.armature
-class DATA_PT_context_arm(ArmatureButtonsPanel, bpy.types.Panel):
+class DATA_PT_context_arm(ArmatureButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
@@ -48,7 +49,7 @@ class DATA_PT_context_arm(ArmatureButtonsPanel, bpy.types.Panel):
layout.template_ID(space, "pin_id")
-class DATA_PT_skeleton(ArmatureButtonsPanel, bpy.types.Panel):
+class DATA_PT_skeleton(ArmatureButtonsPanel, Panel):
bl_label = "Skeleton"
def draw(self, context):
@@ -70,8 +71,10 @@ class DATA_PT_skeleton(ArmatureButtonsPanel, bpy.types.Panel):
flow.prop(arm, "use_deform_envelopes", text="Envelopes")
flow.prop(arm, "use_deform_preserve_volume", text="Quaternion")
+ if context.scene.render.engine == "BLENDER_GAME":
+ layout.row().prop(arm, "vert_deformer", expand=True)
-class DATA_PT_display(ArmatureButtonsPanel, bpy.types.Panel):
+class DATA_PT_display(ArmatureButtonsPanel, Panel):
bl_label = "Display"
def draw(self, context):
@@ -96,7 +99,16 @@ class DATA_PT_display(ArmatureButtonsPanel, bpy.types.Panel):
col.prop(arm, "use_deform_delay", text="Delay Refresh")
-class DATA_PT_bone_groups(ArmatureButtonsPanel, bpy.types.Panel):
+class DATA_PT_bone_group_specials(Menu):
+ bl_label = "Bone Group Specials"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("pose.group_sort", icon='SORTALPHA')
+
+
+class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
bl_label = "Bone Groups"
@classmethod
@@ -108,16 +120,25 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, bpy.types.Panel):
ob = context.object
pose = ob.pose
+ group = pose.bone_groups.active
row = layout.row()
- row.template_list(pose, "bone_groups", pose.bone_groups, "active_index", rows=2)
+
+ rows = 2
+ if group:
+ rows = 5
+ row.template_list(pose, "bone_groups", pose.bone_groups, "active_index", rows=rows)
col = row.column(align=True)
col.active = (ob.proxy is None)
col.operator("pose.group_add", icon='ZOOMIN', text="")
col.operator("pose.group_remove", icon='ZOOMOUT', text="")
+ col.menu("DATA_PT_bone_group_specials", icon='DOWNARROW_HLT', text="")
+ if group:
+ col.separator()
+ col.operator("pose.group_move", icon='TRIA_UP', text="").direction = 'UP'
+ col.operator("pose.group_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
- group = pose.bone_groups.active
if group:
col = layout.column()
col.active = (ob.proxy is None)
@@ -147,7 +168,7 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, bpy.types.Panel):
sub.operator("pose.group_deselect", text="Deselect")
-class DATA_PT_pose_library(ArmatureButtonsPanel, bpy.types.Panel):
+class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
bl_label = "Pose Library"
bl_options = {'DEFAULT_CLOSED'}
@@ -164,9 +185,13 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, bpy.types.Panel):
layout.template_ID(ob, "pose_library", new="poselib.new", unlink="poselib.unlink")
if poselib:
+
+ # list of poses in pose library
row = layout.row()
row.template_list(poselib, "pose_markers", poselib.pose_markers, "active_index", rows=5)
-
+
+ # column of operators for active pose
+ # - goes beside list
col = row.column(align=True)
col.active = (poselib.library is None)
@@ -181,12 +206,16 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, bpy.types.Panel):
if pose_marker_active is not None:
col.operator("poselib.pose_remove", icon='ZOOMOUT', text="").pose = pose_marker_active.name
col.operator("poselib.apply_pose", icon='ZOOM_SELECTED', text="").pose_index = poselib.pose_markers.active_index
-
- layout.operator("poselib.action_sanitise")
+
+ col.operator("poselib.action_sanitise", icon='HELP', text="") # XXX: put in menu?
+
+ # properties for active marker
+ if pose_marker_active is not None:
+ layout.prop(pose_marker_active, "name")
# TODO: this panel will soon be depreceated too
-class DATA_PT_ghost(ArmatureButtonsPanel, bpy.types.Panel):
+class DATA_PT_ghost(ArmatureButtonsPanel, Panel):
bl_label = "Ghost"
def draw(self, context):
@@ -213,7 +242,7 @@ class DATA_PT_ghost(ArmatureButtonsPanel, bpy.types.Panel):
col.prop(arm, "show_only_ghost_selected", text="Selected Only")
-class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, bpy.types.Panel):
+class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, Panel):
bl_label = "iTaSC parameters"
bl_options = {'DEFAULT_CLOSED'}
@@ -266,7 +295,7 @@ from bl_ui.properties_animviz import (
)
-class DATA_PT_motion_paths(MotionPathButtonsPanel, bpy.types.Panel):
+class DATA_PT_motion_paths(MotionPathButtonsPanel, Panel):
#bl_label = "Bones Motion Paths"
bl_context = "data"
@@ -289,7 +318,7 @@ class DATA_PT_motion_paths(MotionPathButtonsPanel, bpy.types.Panel):
split.operator("pose.paths_clear", text="Clear Paths")
-class DATA_PT_onion_skinning(OnionSkinButtonsPanel): # , bpy.types.Panel): # inherit from panel when ready
+class DATA_PT_onion_skinning(OnionSkinButtonsPanel): # , Panel): # inherit from panel when ready
#bl_label = "Bones Onion Skinning"
bl_context = "data"
@@ -299,14 +328,11 @@ 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)
-class DATA_PT_custom_props_arm(ArmatureButtonsPanel, PropertyPanel, bpy.types.Panel):
+class DATA_PT_custom_props_arm(ArmatureButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "object.data"
_property_type = bpy.types.Armature
diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py
index 9fc055e9343..b3eaf88d5bf 100644
--- a/release/scripts/startup/bl_ui/properties_data_bone.py
+++ b/release/scripts/startup/bl_ui/properties_data_bone.py
@@ -19,6 +19,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
from rna_prop_ui import PropertyPanel
@@ -32,7 +33,7 @@ class BoneButtonsPanel():
return (context.bone or context.edit_bone)
-class BONE_PT_context_bone(BoneButtonsPanel, bpy.types.Panel):
+class BONE_PT_context_bone(BoneButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
@@ -48,7 +49,7 @@ class BONE_PT_context_bone(BoneButtonsPanel, bpy.types.Panel):
row.prop(bone, "name", text="")
-class BONE_PT_transform(BoneButtonsPanel, bpy.types.Panel):
+class BONE_PT_transform(BoneButtonsPanel, Panel):
bl_label = "Transform"
@classmethod
@@ -102,7 +103,7 @@ class BONE_PT_transform(BoneButtonsPanel, bpy.types.Panel):
sub.prop(bone, "lock")
-class BONE_PT_transform_locks(BoneButtonsPanel, bpy.types.Panel):
+class BONE_PT_transform_locks(BoneButtonsPanel, Panel):
bl_label = "Transform Locks"
bl_options = {'DEFAULT_CLOSED'}
@@ -135,7 +136,7 @@ class BONE_PT_transform_locks(BoneButtonsPanel, bpy.types.Panel):
row.column().prop(pchan, "lock_scale")
-class BONE_PT_relations(BoneButtonsPanel, bpy.types.Panel):
+class BONE_PT_relations(BoneButtonsPanel, Panel):
bl_label = "Relations"
def draw(self, context):
@@ -180,7 +181,7 @@ class BONE_PT_relations(BoneButtonsPanel, bpy.types.Panel):
sub.prop(bone, "use_local_location", text="Local Location")
-class BONE_PT_display(BoneButtonsPanel, bpy.types.Panel):
+class BONE_PT_display(BoneButtonsPanel, Panel):
bl_label = "Display"
@classmethod
@@ -217,7 +218,7 @@ class BONE_PT_display(BoneButtonsPanel, bpy.types.Panel):
col.prop_search(pchan, "custom_shape_transform", ob.pose, "bones", text="At")
-class BONE_PT_inverse_kinematics(BoneButtonsPanel, bpy.types.Panel):
+class BONE_PT_inverse_kinematics(BoneButtonsPanel, Panel):
bl_label = "Inverse Kinematics"
bl_options = {'DEFAULT_CLOSED'}
@@ -308,7 +309,7 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, bpy.types.Panel):
#row.prop(pchan, "ik_linear_weight", text="Weight", slider=True)
-class BONE_PT_deform(BoneButtonsPanel, bpy.types.Panel):
+class BONE_PT_deform(BoneButtonsPanel, Panel):
bl_label = "Deform"
bl_options = {'DEFAULT_CLOSED'}
@@ -357,7 +358,7 @@ class BONE_PT_deform(BoneButtonsPanel, bpy.types.Panel):
col.prop(bone, "use_cyclic_offset")
-class BONE_PT_custom_props(BoneButtonsPanel, PropertyPanel, bpy.types.Panel):
+class BONE_PT_custom_props(BoneButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_property_type = bpy.types.Bone, bpy.types.EditBone, bpy.types.PoseBone
diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py
index 80cd5227fca..5255af40951 100644
--- a/release/scripts/startup/bl_ui/properties_data_camera.py
+++ b/release/scripts/startup/bl_ui/properties_data_camera.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
from rna_prop_ui import PropertyPanel
@@ -32,7 +33,7 @@ class CameraButtonsPanel():
return context.camera and (engine in cls.COMPAT_ENGINES)
-class DATA_PT_context_camera(CameraButtonsPanel, bpy.types.Panel):
+class DATA_PT_context_camera(CameraButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -53,7 +54,7 @@ class DATA_PT_context_camera(CameraButtonsPanel, bpy.types.Panel):
split.separator()
-class DATA_PT_camera(CameraButtonsPanel, bpy.types.Panel):
+class DATA_PT_camera(CameraButtonsPanel, Panel):
bl_label = "Lens"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -106,12 +107,12 @@ class DATA_PT_camera(CameraButtonsPanel, bpy.types.Panel):
col = split.column()
- if cam.dof_object != None:
+ if cam.dof_object is not None:
col.enabled = False
col.prop(cam, "dof_distance", text="Distance")
-class DATA_PT_camera_display(CameraButtonsPanel, bpy.types.Panel):
+class DATA_PT_camera_display(CameraButtonsPanel, Panel):
bl_label = "Display"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -138,7 +139,7 @@ class DATA_PT_camera_display(CameraButtonsPanel, bpy.types.Panel):
sub.prop(cam, "passepartout_alpha", text="Alpha", slider=True)
-class DATA_PT_custom_props_camera(CameraButtonsPanel, PropertyPanel, bpy.types.Panel):
+class DATA_PT_custom_props_camera(CameraButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "object.data"
_property_type = bpy.types.Camera
diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index 11a129377e8..6448b9a5229 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
from rna_prop_ui import PropertyPanel
@@ -48,7 +49,7 @@ class CurveButtonsPanelActive(CurveButtonsPanel):
return (curve and type(curve) is not bpy.types.TextCurve and curve.splines.active)
-class DATA_PT_context_curve(CurveButtonsPanel, bpy.types.Panel):
+class DATA_PT_context_curve(CurveButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
@@ -65,7 +66,7 @@ class DATA_PT_context_curve(CurveButtonsPanel, bpy.types.Panel):
layout.template_ID(space, "pin_id") # XXX: broken
-class DATA_PT_shape_curve(CurveButtonsPanel, bpy.types.Panel):
+class DATA_PT_shape_curve(CurveButtonsPanel, Panel):
bl_label = "Shape"
def draw(self, context):
@@ -108,21 +109,32 @@ class DATA_PT_shape_curve(CurveButtonsPanel, bpy.types.Panel):
if (is_curve or is_text):
col.label(text="Fill:")
sub = col.column()
- sub.active = (curve.bevel_object is None)
+ sub.active = (curve.dimensions == '2D' or (curve.bevel_object is None and curve.dimensions == '3D'))
sub.prop(curve, "use_fill_front")
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, 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):
+class DATA_PT_geometry_curve(CurveButtonsPanel, Panel):
bl_label = "Geometry"
@classmethod
@@ -155,7 +167,7 @@ class DATA_PT_geometry_curve(CurveButtonsPanel, bpy.types.Panel):
col.prop(curve, "bevel_object", text="")
-class DATA_PT_pathanim(CurveButtonsPanelCurve, bpy.types.Panel):
+class DATA_PT_pathanim(CurveButtonsPanelCurve, Panel):
bl_label = "Path Animation"
def draw_header(self, context):
@@ -186,7 +198,7 @@ class DATA_PT_pathanim(CurveButtonsPanelCurve, bpy.types.Panel):
col.prop(curve, "use_time_offset", text="Offset Children")
-class DATA_PT_active_spline(CurveButtonsPanelActive, bpy.types.Panel):
+class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
bl_label = "Active Spline"
def draw(self, context):
@@ -257,7 +269,7 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, bpy.types.Panel):
layout.prop(act_spline, "use_smooth")
-class DATA_PT_font(CurveButtonsPanel, bpy.types.Panel):
+class DATA_PT_font(CurveButtonsPanel, Panel):
bl_label = "Font"
@classmethod
@@ -321,7 +333,7 @@ class DATA_PT_font(CurveButtonsPanel, bpy.types.Panel):
row.prop(char, "use_small_caps")
-class DATA_PT_paragraph(CurveButtonsPanel, bpy.types.Panel):
+class DATA_PT_paragraph(CurveButtonsPanel, Panel):
bl_label = "Paragraph"
@classmethod
@@ -350,7 +362,7 @@ class DATA_PT_paragraph(CurveButtonsPanel, bpy.types.Panel):
col.prop(text, "offset_y", text="Y")
-class DATA_PT_textboxes(CurveButtonsPanel, bpy.types.Panel):
+class DATA_PT_text_boxes(CurveButtonsPanel, Panel):
bl_label = "Text Boxes"
@classmethod
@@ -390,7 +402,7 @@ class DATA_PT_textboxes(CurveButtonsPanel, bpy.types.Panel):
row.operator("font.textbox_remove", text='', icon='X', emboss=False).index = i
-class DATA_PT_custom_props_curve(CurveButtonsPanel, PropertyPanel, bpy.types.Panel):
+class DATA_PT_custom_props_curve(CurveButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "object.data"
_property_type = bpy.types.Curve
diff --git a/release/scripts/startup/bl_ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py
index 5a0d327f90d..c781873e16c 100644
--- a/release/scripts/startup/bl_ui/properties_data_empty.py
+++ b/release/scripts/startup/bl_ui/properties_data_empty.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
class DataButtonsPanel():
@@ -30,7 +31,7 @@ class DataButtonsPanel():
return (context.object and context.object.type == 'EMPTY')
-class DATA_PT_empty(DataButtonsPanel, bpy.types.Panel):
+class DATA_PT_empty(DataButtonsPanel, Panel):
bl_label = "Empty"
def draw(self, context):
@@ -41,11 +42,9 @@ class DATA_PT_empty(DataButtonsPanel, bpy.types.Panel):
layout.prop(ob, "empty_draw_type", text="Display")
if ob.empty_draw_type == 'IMAGE':
- # layout.template_image(ob, "data", None)
layout.template_ID(ob, "data", open="image.open", unlink="image.unlink")
- row = layout.row(align=True)
- row.prop(ob, "color", text="Transparency", index=3, slider=True)
+ layout.prop(ob, "color", text="Transparency", index=3, slider=True)
row = layout.row(align=True)
row.prop(ob, "empty_image_offset", text="Offset X", index=0)
row.prop(ob, "empty_image_offset", text="Offset Y", index=1)
diff --git a/release/scripts/startup/bl_ui/properties_data_lamp.py b/release/scripts/startup/bl_ui/properties_data_lamp.py
index 36010c8b511..4ff180f74fb 100644
--- a/release/scripts/startup/bl_ui/properties_data_lamp.py
+++ b/release/scripts/startup/bl_ui/properties_data_lamp.py
@@ -18,15 +18,16 @@
# <pep8 compliant>
import bpy
+from bpy.types import Menu, Panel
from rna_prop_ui import PropertyPanel
-class LAMP_MT_sunsky_presets(bpy.types.Menu):
+class LAMP_MT_sunsky_presets(Menu):
bl_label = "Sun & Sky Presets"
preset_subdir = "sunsky"
preset_operator = "script.execute_preset"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
- draw = bpy.types.Menu.draw_preset
+ draw = Menu.draw_preset
class DataButtonsPanel():
@@ -40,7 +41,7 @@ class DataButtonsPanel():
return context.lamp and (engine in cls.COMPAT_ENGINES)
-class DATA_PT_context_lamp(DataButtonsPanel, bpy.types.Panel):
+class DATA_PT_context_lamp(DataButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -65,7 +66,7 @@ class DATA_PT_context_lamp(DataButtonsPanel, bpy.types.Panel):
split.label(text=str(texture_count), icon='TEXTURE')
-class DATA_PT_preview(DataButtonsPanel, bpy.types.Panel):
+class DATA_PT_preview(DataButtonsPanel, Panel):
bl_label = "Preview"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -73,7 +74,7 @@ class DATA_PT_preview(DataButtonsPanel, bpy.types.Panel):
self.layout.template_preview(context.lamp)
-class DATA_PT_lamp(DataButtonsPanel, bpy.types.Panel):
+class DATA_PT_lamp(DataButtonsPanel, Panel):
bl_label = "Lamp"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -115,7 +116,7 @@ class DATA_PT_lamp(DataButtonsPanel, bpy.types.Panel):
col.prop(lamp, "use_diffuse")
-class DATA_PT_sunsky(DataButtonsPanel, bpy.types.Panel):
+class DATA_PT_sunsky(DataButtonsPanel, Panel):
bl_label = "Sky & Atmosphere"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -187,7 +188,7 @@ class DATA_PT_sunsky(DataButtonsPanel, bpy.types.Panel):
sub.prop(lamp, "atmosphere_extinction", slider=True, text="Extinction")
-class DATA_PT_shadow(DataButtonsPanel, bpy.types.Panel):
+class DATA_PT_shadow(DataButtonsPanel, Panel):
bl_label = "Shadow"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -302,7 +303,7 @@ class DATA_PT_shadow(DataButtonsPanel, bpy.types.Panel):
sub.prop(lamp, "shadow_buffer_clip_end", text=" Clip End")
-class DATA_PT_area(DataButtonsPanel, bpy.types.Panel):
+class DATA_PT_area(DataButtonsPanel, Panel):
bl_label = "Area Shape"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -328,7 +329,7 @@ class DATA_PT_area(DataButtonsPanel, bpy.types.Panel):
sub.prop(lamp, "size_y", text="Size Y")
-class DATA_PT_spot(DataButtonsPanel, bpy.types.Panel):
+class DATA_PT_spot(DataButtonsPanel, Panel):
bl_label = "Spot Shape"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -362,7 +363,7 @@ class DATA_PT_spot(DataButtonsPanel, bpy.types.Panel):
sub.prop(lamp, "halo_step", text="Step")
-class DATA_PT_falloff_curve(DataButtonsPanel, bpy.types.Panel):
+class DATA_PT_falloff_curve(DataButtonsPanel, Panel):
bl_label = "Falloff Curve"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -380,7 +381,7 @@ class DATA_PT_falloff_curve(DataButtonsPanel, bpy.types.Panel):
self.layout.template_curve_mapping(lamp, "falloff_curve")
-class DATA_PT_custom_props_lamp(DataButtonsPanel, PropertyPanel, bpy.types.Panel):
+class DATA_PT_custom_props_lamp(DataButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "object.data"
_property_type = bpy.types.Lamp
diff --git a/release/scripts/startup/bl_ui/properties_data_lattice.py b/release/scripts/startup/bl_ui/properties_data_lattice.py
index cd719b6fe84..14d6ea66894 100644
--- a/release/scripts/startup/bl_ui/properties_data_lattice.py
+++ b/release/scripts/startup/bl_ui/properties_data_lattice.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
from rna_prop_ui import PropertyPanel
@@ -31,7 +32,7 @@ class DataButtonsPanel():
return context.lattice
-class DATA_PT_context_lattice(DataButtonsPanel, bpy.types.Panel):
+class DATA_PT_context_lattice(DataButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
@@ -51,7 +52,7 @@ class DATA_PT_context_lattice(DataButtonsPanel, bpy.types.Panel):
split.separator()
-class DATA_PT_lattice(DataButtonsPanel, bpy.types.Panel):
+class DATA_PT_lattice(DataButtonsPanel, Panel):
bl_label = "Lattice"
def draw(self, context):
@@ -76,7 +77,7 @@ class DATA_PT_lattice(DataButtonsPanel, bpy.types.Panel):
row.prop_search(lat, "vertex_group", context.object, "vertex_groups", text="")
-class DATA_PT_custom_props_lattice(DataButtonsPanel, PropertyPanel, bpy.types.Panel):
+class DATA_PT_custom_props_lattice(DataButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "object.data"
_property_type = bpy.types.Lattice
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index e2c88413177..75df7dad5f2 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -18,10 +18,11 @@
# <pep8 compliant>
import bpy
+from bpy.types import Menu, Panel
from rna_prop_ui import PropertyPanel
-class MESH_MT_vertex_group_specials(bpy.types.Menu):
+class MESH_MT_vertex_group_specials(Menu):
bl_label = "Vertex Group Specials"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -36,7 +37,7 @@ class MESH_MT_vertex_group_specials(bpy.types.Menu):
layout.operator("object.vertex_group_remove", icon='X', text="Delete All").all = True
-class MESH_MT_shape_key_specials(bpy.types.Menu):
+class MESH_MT_shape_key_specials(Menu):
bl_label = "Shape Key Specials"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -61,7 +62,7 @@ class MeshButtonsPanel():
return context.mesh and (engine in cls.COMPAT_ENGINES)
-class DATA_PT_context_mesh(MeshButtonsPanel, bpy.types.Panel):
+class DATA_PT_context_mesh(MeshButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -79,7 +80,7 @@ class DATA_PT_context_mesh(MeshButtonsPanel, bpy.types.Panel):
layout.template_ID(space, "pin_id")
-class DATA_PT_normals(MeshButtonsPanel, bpy.types.Panel):
+class DATA_PT_normals(MeshButtonsPanel, Panel):
bl_label = "Normals"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -99,7 +100,7 @@ class DATA_PT_normals(MeshButtonsPanel, bpy.types.Panel):
split.prop(mesh, "show_double_sided")
-class DATA_PT_texture_space(MeshButtonsPanel, bpy.types.Panel):
+class DATA_PT_texture_space(MeshButtonsPanel, Panel):
bl_label = "Texture Space"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -118,7 +119,8 @@ 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):
+
+class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
bl_label = "Vertex Groups"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -167,7 +169,7 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, bpy.types.Panel):
layout.prop(context.tool_settings, "vertex_group_weight", text="Weight")
-class DATA_PT_shape_keys(MeshButtonsPanel, bpy.types.Panel):
+class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
bl_label = "Shape Keys"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -260,7 +262,7 @@ class DATA_PT_shape_keys(MeshButtonsPanel, bpy.types.Panel):
row.prop(key, "slurph")
-class DATA_PT_uv_texture(MeshButtonsPanel, bpy.types.Panel):
+class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
bl_label = "UV Texture"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -283,15 +285,14 @@ class DATA_PT_uv_texture(MeshButtonsPanel, bpy.types.Panel):
layout.prop(lay, "name")
-class DATA_PT_texface(MeshButtonsPanel, bpy.types.Panel):
+class DATA_PT_texface(MeshButtonsPanel, Panel):
bl_label = "Texture Face"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@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
@@ -331,7 +332,7 @@ class DATA_PT_texface(MeshButtonsPanel, bpy.types.Panel):
col.label(text="No UV Texture")
-class DATA_PT_vertex_colors(MeshButtonsPanel, bpy.types.Panel):
+class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
bl_label = "Vertex Colors"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -354,7 +355,7 @@ class DATA_PT_vertex_colors(MeshButtonsPanel, bpy.types.Panel):
layout.prop(lay, "name")
-class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, bpy.types.Panel):
+class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "object.data"
_property_type = bpy.types.Mesh
diff --git a/release/scripts/startup/bl_ui/properties_data_metaball.py b/release/scripts/startup/bl_ui/properties_data_metaball.py
index c568d10b3b0..cd894e60dbb 100644
--- a/release/scripts/startup/bl_ui/properties_data_metaball.py
+++ b/release/scripts/startup/bl_ui/properties_data_metaball.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
from rna_prop_ui import PropertyPanel
@@ -31,7 +32,7 @@ class DataButtonsPanel():
return context.meta_ball
-class DATA_PT_context_metaball(DataButtonsPanel, bpy.types.Panel):
+class DATA_PT_context_metaball(DataButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
@@ -48,7 +49,7 @@ class DATA_PT_context_metaball(DataButtonsPanel, bpy.types.Panel):
layout.template_ID(space, "pin_id")
-class DATA_PT_metaball(DataButtonsPanel, bpy.types.Panel):
+class DATA_PT_metaball(DataButtonsPanel, Panel):
bl_label = "Metaball"
def draw(self, context):
@@ -70,13 +71,26 @@ 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, 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):
+class DATA_PT_metaball_element(DataButtonsPanel, Panel):
bl_label = "Active Element"
@classmethod
@@ -116,7 +130,7 @@ class DATA_PT_metaball_element(DataButtonsPanel, bpy.types.Panel):
col.prop(metaelem, "size_y", text="Y")
-class DATA_PT_custom_props_metaball(DataButtonsPanel, PropertyPanel, bpy.types.Panel):
+class DATA_PT_custom_props_metaball(DataButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "object.data"
_property_type = bpy.types.MetaBall
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 6fd5890590d..dc6b5401168 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
class ModifierButtonsPanel():
@@ -26,7 +27,7 @@ class ModifierButtonsPanel():
bl_context = "modifier"
-class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
+class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
bl_label = "Modifiers"
def draw(self, context):
@@ -402,6 +403,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.operator("object.multires_higher_levels_delete", text="Delete Higher")
col.operator("object.multires_reshape", text="Reshape")
col.operator("object.multires_base_apply", text="Apply Base")
+ col.prop(md, "use_subsurf_uv")
col.prop(md, "show_only_control_edges")
layout.separator()
@@ -491,11 +493,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")
@@ -507,7 +508,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)
@@ -585,13 +585,13 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
sub = col.column()
sub.active = bool(md.vertex_group)
sub.prop(md, "invert_vertex_group", text="Invert")
+ sub.prop(md, "thickness_vertex_group", text="Factor")
col.prop(md, "use_even_offset")
col.prop(md, "use_quality_normals")
col.prop(md, "use_rim")
sub = col.column()
- sub.label()
row = sub.split(align=True, percentage=0.4)
row.prop(md, "material_offset", text="")
row = row.row()
diff --git a/release/scripts/startup/bl_ui/properties_data_speaker.py b/release/scripts/startup/bl_ui/properties_data_speaker.py
new file mode 100644
index 00000000000..657c0fe652a
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_data_speaker.py
@@ -0,0 +1,125 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+import bpy
+from rna_prop_ui import PropertyPanel
+
+
+class DataButtonsPanel():
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+
+ @classmethod
+ def poll(cls, context):
+ engine = context.scene.render.engine
+ return context.speaker and (engine in cls.COMPAT_ENGINES)
+
+
+class DATA_PT_context_speaker(DataButtonsPanel, bpy.types.Panel):
+ bl_label = ""
+ bl_options = {'HIDE_HEADER'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ speaker = context.speaker
+ space = context.space_data
+
+ split = layout.split(percentage=0.65)
+
+ if ob:
+ split.template_ID(ob, "data")
+ elif speaker:
+ split.template_ID(space, "pin_id")
+
+
+class DATA_PT_speaker(DataButtonsPanel, bpy.types.Panel):
+ bl_label = "Sound"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ speaker = context.speaker
+
+ split = layout.split(percentage=0.75)
+
+ split.template_ID(speaker, "sound", open="sound.open_mono")
+ split.prop(speaker, "muted")
+
+ row = layout.row()
+ row.prop(speaker, "volume")
+ row.prop(speaker, "pitch")
+
+
+class DATA_PT_distance(DataButtonsPanel, bpy.types.Panel):
+ bl_label = "Distance"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ speaker = context.speaker
+
+ split = layout.split()
+
+ col = split.column()
+ col.label("Volume:")
+ col.prop(speaker, "volume_min", text="Minimum")
+ col.prop(speaker, "volume_max", text="Maximum")
+ col.prop(speaker, "attenuation")
+
+ col = split.column()
+ col.label("Distance:")
+ col.prop(speaker, "distance_max", text="Maximum")
+ col.prop(speaker, "distance_reference", text="Reference")
+
+
+class DATA_PT_cone(DataButtonsPanel, bpy.types.Panel):
+ bl_label = "Cone"
+ COMPAT_ENGINES = {'BLENDER_RENDER'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ speaker = context.speaker
+
+ split = layout.split()
+ col = split.column()
+
+ col.label("Angle:")
+ col.prop(speaker, "cone_angle_outer", text="Outer")
+ col.prop(speaker, "cone_angle_inner", text="Inner")
+
+ col = split.column()
+
+ col.label("Volume:")
+ col.prop(speaker, "cone_volume_outer", text="Outer")
+
+
+class DATA_PT_custom_props_speaker(DataButtonsPanel, PropertyPanel, bpy.types.Panel):
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+ _context_path = "object.data"
+ _property_type = bpy.types.Speaker
+
+if __name__ == "__main__": # only for live edit.
+ bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py
index 6952f3c31db..16c7adbe5ff 100644
--- a/release/scripts/startup/bl_ui/properties_game.py
+++ b/release/scripts/startup/bl_ui/properties_game.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
class PhysicsButtonsPanel():
@@ -26,7 +27,7 @@ class PhysicsButtonsPanel():
bl_context = "physics"
-class PHYSICS_PT_game_physics(PhysicsButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_game_physics(PhysicsButtonsPanel, Panel):
bl_label = "Physics"
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -167,7 +168,7 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, bpy.types.Panel):
layout.prop(ob, "hide_render", text="Invisible")
-class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, Panel):
bl_label = "Collision Bounds"
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -231,7 +232,7 @@ class RenderButtonsPanel():
return (rd.engine in cls.COMPAT_ENGINES)
-class RENDER_PT_game(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_game(RenderButtonsPanel, Panel):
bl_label = "Game"
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -243,7 +244,7 @@ class RENDER_PT_game(RenderButtonsPanel, bpy.types.Panel):
row.label()
-class RENDER_PT_game_player(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_game_player(RenderButtonsPanel, Panel):
bl_label = "Standalone Player"
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -276,7 +277,7 @@ class RENDER_PT_game_player(RenderButtonsPanel, bpy.types.Panel):
col.prop(gs, "frame_color", text="")
-class RENDER_PT_game_stereo(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_game_stereo(RenderButtonsPanel, Panel):
bl_label = "Stereo"
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -330,7 +331,7 @@ class RENDER_PT_game_stereo(RenderButtonsPanel, bpy.types.Panel):
layout.prop(gs, "dome_text")
-class RENDER_PT_game_shading(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_game_shading(RenderButtonsPanel, Panel):
bl_label = "Shading"
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -356,7 +357,7 @@ class RENDER_PT_game_shading(RenderButtonsPanel, bpy.types.Panel):
col.prop(gs, "use_glsl_extra_textures", text="Extra Textures")
-class RENDER_PT_game_performance(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_game_performance(RenderButtonsPanel, Panel):
bl_label = "Performance"
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -364,12 +365,15 @@ class RENDER_PT_game_performance(RenderButtonsPanel, bpy.types.Panel):
layout = self.layout
gs = context.scene.game_settings
- row = layout.row()
+ col = layout.column()
+ row = col.row()
row.prop(gs, "use_frame_rate")
row.prop(gs, "use_display_lists")
+
+ col.prop(gs, "restrict_animation_updates")
-class RENDER_PT_game_display(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_game_display(RenderButtonsPanel, Panel):
bl_label = "Display"
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -385,28 +389,13 @@ class RENDER_PT_game_display(RenderButtonsPanel, bpy.types.Panel):
flow.prop(gs, "show_mouse", text="Mouse Cursor")
-class RENDER_PT_game_sound(RenderButtonsPanel, bpy.types.Panel):
- bl_label = "Sound"
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
-
- layout.prop(scene, "audio_distance_model")
-
- layout.prop(scene, "audio_doppler_speed", text="Speed")
- layout.prop(scene, "audio_doppler_factor")
-
-
class WorldButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_context = "world"
-class WORLD_PT_game_context_world(WorldButtonsPanel, bpy.types.Panel):
+class WORLD_PT_game_context_world(WorldButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -430,7 +419,7 @@ class WORLD_PT_game_context_world(WorldButtonsPanel, bpy.types.Panel):
split.template_ID(space, "pin_id")
-class WORLD_PT_game_world(WorldButtonsPanel, bpy.types.Panel):
+class WORLD_PT_game_world(WorldButtonsPanel, Panel):
bl_label = "World"
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -449,7 +438,7 @@ class WORLD_PT_game_world(WorldButtonsPanel, bpy.types.Panel):
row.column().prop(world, "ambient_color")
-class WORLD_PT_game_mist(WorldButtonsPanel, bpy.types.Panel):
+class WORLD_PT_game_mist(WorldButtonsPanel, Panel):
bl_label = "Mist"
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -475,7 +464,7 @@ class WORLD_PT_game_mist(WorldButtonsPanel, bpy.types.Panel):
row.prop(world.mist_settings, "depth")
-class WORLD_PT_game_physics(WorldButtonsPanel, bpy.types.Panel):
+class WORLD_PT_game_physics(WorldButtonsPanel, Panel):
bl_label = "Physics"
COMPAT_ENGINES = {'BLENDER_GAME'}
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index 52d6b5f1376..13ce92f084c 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Menu, Panel
from rna_prop_ui import PropertyPanel
@@ -50,14 +51,14 @@ def simple_material(mat):
return False
-class MATERIAL_MT_sss_presets(bpy.types.Menu):
+class MATERIAL_MT_sss_presets(Menu):
bl_label = "SSS Presets"
preset_subdir = "sss"
preset_operator = "script.execute_preset"
- draw = bpy.types.Menu.draw_preset
+ draw = Menu.draw_preset
-class MATERIAL_MT_specials(bpy.types.Menu):
+class MATERIAL_MT_specials(Menu):
bl_label = "Material Specials"
def draw(self, context):
@@ -79,7 +80,7 @@ class MaterialButtonsPanel():
return context.material and (context.scene.render.engine in cls.COMPAT_ENGINES)
-class MATERIAL_PT_context_material(MaterialButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -144,7 +145,7 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, bpy.types.Panel):
row.label(text="No material node selected")
-class MATERIAL_PT_preview(MaterialButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_preview(MaterialButtonsPanel, Panel):
bl_label = "Preview"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -152,7 +153,7 @@ class MATERIAL_PT_preview(MaterialButtonsPanel, bpy.types.Panel):
self.layout.template_preview(context.material)
-class MATERIAL_PT_pipeline(MaterialButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_pipeline(MaterialButtonsPanel, Panel):
bl_label = "Render Pipeline Options"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -174,6 +175,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,9 +201,10 @@ 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):
+class MATERIAL_PT_diffuse(MaterialButtonsPanel, Panel):
bl_label = "Diffuse"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -245,18 +248,20 @@ class MATERIAL_PT_diffuse(MaterialButtonsPanel, bpy.types.Panel):
row.prop(mat, "diffuse_fresnel_factor", text="Factor")
if mat.use_diffuse_ramp:
- layout.separator()
- layout.template_color_ramp(mat, "diffuse_ramp", expand=True)
- layout.separator()
+ col = layout.column()
+ col.active = (not mat.use_shadeless)
+ col.separator()
+ col.template_color_ramp(mat, "diffuse_ramp", expand=True)
+ col.separator()
- row = layout.row()
+ row = col.row()
row.prop(mat, "diffuse_ramp_input", text="Input")
row.prop(mat, "diffuse_ramp_blend", text="Blend")
- layout.prop(mat, "diffuse_ramp_factor", text="Factor")
+ col.prop(mat, "diffuse_ramp_factor", text="Factor")
-class MATERIAL_PT_specular(MaterialButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_specular(MaterialButtonsPanel, Panel):
bl_label = "Specular"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -309,7 +314,7 @@ class MATERIAL_PT_specular(MaterialButtonsPanel, bpy.types.Panel):
layout.prop(mat, "specular_ramp_factor", text="Factor")
-class MATERIAL_PT_shading(MaterialButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_shading(MaterialButtonsPanel, Panel):
bl_label = "Shading"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -343,7 +348,7 @@ class MATERIAL_PT_shading(MaterialButtonsPanel, bpy.types.Panel):
sub.prop(mat, "use_cubic")
-class MATERIAL_PT_transp(MaterialButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_transp(MaterialButtonsPanel, Panel):
bl_label = "Transparency"
# bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -409,7 +414,7 @@ class MATERIAL_PT_transp(MaterialButtonsPanel, bpy.types.Panel):
sub.prop(rayt, "gloss_samples", text="Samples")
-class MATERIAL_PT_mirror(MaterialButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_mirror(MaterialButtonsPanel, Panel):
bl_label = "Mirror"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -467,7 +472,7 @@ class MATERIAL_PT_mirror(MaterialButtonsPanel, bpy.types.Panel):
sub.prop(raym, "gloss_anisotropic", text="Anisotropic")
-class MATERIAL_PT_sss(MaterialButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_sss(MaterialButtonsPanel, Panel):
bl_label = "Subsurface Scattering"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -519,7 +524,7 @@ class MATERIAL_PT_sss(MaterialButtonsPanel, bpy.types.Panel):
col.prop(sss, "error_threshold", text="Error")
-class MATERIAL_PT_halo(MaterialButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_halo(MaterialButtonsPanel, Panel):
bl_label = "Halo"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -572,7 +577,7 @@ class MATERIAL_PT_halo(MaterialButtonsPanel, bpy.types.Panel):
number_but(col, "use_star", "star_tip_count", "Star tips", "")
-class MATERIAL_PT_flare(MaterialButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_flare(MaterialButtonsPanel, Panel):
bl_label = "Flare"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -607,7 +612,7 @@ class MATERIAL_PT_flare(MaterialButtonsPanel, bpy.types.Panel):
col.prop(halo, "flare_subflare_size", text="Subsize")
-class MATERIAL_PT_physics(MaterialButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_physics(MaterialButtonsPanel, Panel):
bl_label = "Physics"
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -637,7 +642,7 @@ class MATERIAL_PT_physics(MaterialButtonsPanel, bpy.types.Panel):
row.prop(phys, "use_fh_normal")
-class MATERIAL_PT_strand(MaterialButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_strand(MaterialButtonsPanel, Panel):
bl_label = "Strand"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -684,7 +689,7 @@ class MATERIAL_PT_strand(MaterialButtonsPanel, bpy.types.Panel):
sub.prop(tan, "blend_distance", text="Distance")
-class MATERIAL_PT_options(MaterialButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_options(MaterialButtonsPanel, Panel):
bl_label = "Options"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -729,9 +734,11 @@ 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):
+class MATERIAL_PT_shadow(MaterialButtonsPanel, Panel):
bl_label = "Shadow"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -775,7 +782,7 @@ class MATERIAL_PT_shadow(MaterialButtonsPanel, bpy.types.Panel):
col.prop(mat, "use_cast_approximate")
-class MATERIAL_PT_transp_game(MaterialButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_transp_game(MaterialButtonsPanel, Panel):
bl_label = "Transparency"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_GAME'}
@@ -818,7 +825,7 @@ class VolumeButtonsPanel():
return mat and (mat.type == 'VOLUME') and (engine in cls.COMPAT_ENGINES)
-class MATERIAL_PT_volume_density(VolumeButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_volume_density(VolumeButtonsPanel, Panel):
bl_label = "Density"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -832,7 +839,7 @@ class MATERIAL_PT_volume_density(VolumeButtonsPanel, bpy.types.Panel):
row.prop(vol, "density_scale")
-class MATERIAL_PT_volume_shading(VolumeButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_volume_shading(VolumeButtonsPanel, Panel):
bl_label = "Shading"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -857,7 +864,7 @@ class MATERIAL_PT_volume_shading(VolumeButtonsPanel, bpy.types.Panel):
sub.prop(vol, "reflection_color", text="")
-class MATERIAL_PT_volume_lighting(VolumeButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_volume_lighting(VolumeButtonsPanel, Panel):
bl_label = "Lighting"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -883,7 +890,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)
@@ -892,7 +899,7 @@ class MATERIAL_PT_volume_lighting(VolumeButtonsPanel, bpy.types.Panel):
sub.prop(vol, "ms_intensity")
-class MATERIAL_PT_volume_transp(VolumeButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_volume_transp(VolumeButtonsPanel, Panel):
bl_label = "Transparency"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -910,7 +917,7 @@ class MATERIAL_PT_volume_transp(VolumeButtonsPanel, bpy.types.Panel):
layout.prop(mat, "transparency_method", expand=True)
-class MATERIAL_PT_volume_integration(VolumeButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_volume_integration(VolumeButtonsPanel, Panel):
bl_label = "Integration"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -932,7 +939,7 @@ class MATERIAL_PT_volume_integration(VolumeButtonsPanel, bpy.types.Panel):
col.prop(vol, "depth_threshold")
-class MATERIAL_PT_volume_options(VolumeButtonsPanel, bpy.types.Panel):
+class MATERIAL_PT_volume_options(VolumeButtonsPanel, Panel):
bl_label = "Options"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
bl_options = {'DEFAULT_CLOSED'}
@@ -964,7 +971,7 @@ class MATERIAL_PT_volume_options(VolumeButtonsPanel, bpy.types.Panel):
row.prop(mat, "use_light_group_exclusive", text="Exclusive")
-class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, bpy.types.Panel):
+class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "material"
_property_type = bpy.types.Material
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index ae66642e903..0779debb102 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
from rna_prop_ui import PropertyPanel
@@ -27,14 +28,13 @@ class ObjectButtonsPanel():
bl_context = "object"
-class OBJECT_PT_context_object(ObjectButtonsPanel, bpy.types.Panel):
+class OBJECT_PT_context_object(ObjectButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
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")
@@ -43,7 +43,7 @@ class OBJECT_PT_context_object(ObjectButtonsPanel, bpy.types.Panel):
row.template_ID(context.scene.objects, "active")
-class OBJECT_PT_transform(ObjectButtonsPanel, bpy.types.Panel):
+class OBJECT_PT_transform(ObjectButtonsPanel, Panel):
bl_label = "Transform"
def draw(self, context):
@@ -69,7 +69,7 @@ class OBJECT_PT_transform(ObjectButtonsPanel, bpy.types.Panel):
layout.prop(ob, "rotation_mode")
-class OBJECT_PT_delta_transform(ObjectButtonsPanel, bpy.types.Panel):
+class OBJECT_PT_delta_transform(ObjectButtonsPanel, Panel):
bl_label = "Delta Transform"
bl_options = {'DEFAULT_CLOSED'}
@@ -95,7 +95,7 @@ class OBJECT_PT_delta_transform(ObjectButtonsPanel, bpy.types.Panel):
row.column().prop(ob, "delta_scale")
-class OBJECT_PT_transform_locks(ObjectButtonsPanel, bpy.types.Panel):
+class OBJECT_PT_transform_locks(ObjectButtonsPanel, Panel):
bl_label = "Transform Locks"
bl_options = {'DEFAULT_CLOSED'}
@@ -121,7 +121,7 @@ class OBJECT_PT_transform_locks(ObjectButtonsPanel, bpy.types.Panel):
row.column().prop(ob, "lock_scale", text="Scale")
-class OBJECT_PT_relations(ObjectButtonsPanel, bpy.types.Panel):
+class OBJECT_PT_relations(ObjectButtonsPanel, Panel):
bl_label = "Relations"
def draw(self, context):
@@ -148,7 +148,7 @@ class OBJECT_PT_relations(ObjectButtonsPanel, bpy.types.Panel):
sub.active = (parent is not None)
-class OBJECT_PT_groups(ObjectButtonsPanel, bpy.types.Panel):
+class OBJECT_PT_groups(ObjectButtonsPanel, Panel):
bl_label = "Groups"
def draw(self, context):
@@ -187,7 +187,7 @@ class OBJECT_PT_groups(ObjectButtonsPanel, bpy.types.Panel):
index += 1
-class OBJECT_PT_display(ObjectButtonsPanel, bpy.types.Panel):
+class OBJECT_PT_display(ObjectButtonsPanel, Panel):
bl_label = "Display"
def draw(self, context):
@@ -221,7 +221,7 @@ class OBJECT_PT_display(ObjectButtonsPanel, bpy.types.Panel):
col.prop(ob, "show_transparent", text="Transparency")
-class OBJECT_PT_duplication(ObjectButtonsPanel, bpy.types.Panel):
+class OBJECT_PT_duplication(ObjectButtonsPanel, Panel):
bl_label = "Duplication"
def draw(self, context):
@@ -259,7 +259,7 @@ class OBJECT_PT_duplication(ObjectButtonsPanel, bpy.types.Panel):
# XXX: the following options are all quite buggy, ancient hacks that should be dropped
-class OBJECT_PT_animation(ObjectButtonsPanel, bpy.types.Panel):
+class OBJECT_PT_animation(ObjectButtonsPanel, Panel):
bl_label = "Animation Hacks"
bl_options = {'DEFAULT_CLOSED'}
@@ -294,7 +294,7 @@ from bl_ui.properties_animviz import (
)
-class OBJECT_PT_motion_paths(MotionPathButtonsPanel, bpy.types.Panel):
+class OBJECT_PT_motion_paths(MotionPathButtonsPanel, Panel):
#bl_label = "Object Motion Paths"
bl_context = "object"
@@ -316,7 +316,7 @@ class OBJECT_PT_motion_paths(MotionPathButtonsPanel, bpy.types.Panel):
row.operator("object.paths_clear", text="Clear Paths")
-class OBJECT_PT_onion_skinning(OnionSkinButtonsPanel): # , bpy.types.Panel): # inherit from panel when ready
+class OBJECT_PT_onion_skinning(OnionSkinButtonsPanel): # , Panel): # inherit from panel when ready
#bl_label = "Object Onion Skinning"
bl_context = "object"
@@ -330,7 +330,7 @@ class OBJECT_PT_onion_skinning(OnionSkinButtonsPanel): # , bpy.types.Panel): #
self.draw_settings(context, ob.animation_visualisation)
-class OBJECT_PT_custom_props(ObjectButtonsPanel, PropertyPanel, bpy.types.Panel):
+class OBJECT_PT_custom_props(ObjectButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "object"
_property_type = bpy.types.Object
diff --git a/release/scripts/startup/bl_ui/properties_object_constraint.py b/release/scripts/startup/bl_ui/properties_object_constraint.py
index 03823ad7345..05fac2026a0 100644
--- a/release/scripts/startup/bl_ui/properties_object_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_object_constraint.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
class ConstraintButtonsPanel():
@@ -234,7 +235,6 @@ class ConstraintButtonsPanel():
row.label()
def LIMIT_ROTATION(self, context, layout, con):
-
split = layout.split()
col = split.column(align=True)
@@ -258,9 +258,7 @@ class ConstraintButtonsPanel():
sub.prop(con, "min_z", text="Min")
sub.prop(con, "max_z", text="Max")
- row = layout.row()
- row.prop(con, "use_transform_limit")
- row.label()
+ layout.prop(con, "use_transform_limit")
row = layout.row()
row.label(text="Convert:")
@@ -476,6 +474,10 @@ class ConstraintButtonsPanel():
row.label(text="Clamp Region:")
row.prop(con, "limit_mode", text="")
+ row = layout.row()
+ row.prop(con, "use_transform_limit")
+ row.label()
+
def STRETCH_TO(self, context, layout, con):
self.target_template(layout, con)
@@ -655,8 +657,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))
@@ -755,7 +757,7 @@ class ConstraintButtonsPanel():
layout.label("Blender 2.5 has no py-constraints")
-class OBJECT_PT_constraints(ConstraintButtonsPanel, bpy.types.Panel):
+class OBJECT_PT_constraints(ConstraintButtonsPanel, Panel):
bl_label = "Object Constraints"
bl_context = "constraint"
@@ -779,7 +781,7 @@ class OBJECT_PT_constraints(ConstraintButtonsPanel, bpy.types.Panel):
self.draw_constraint(context, con)
-class BONE_PT_constraints(ConstraintButtonsPanel, bpy.types.Panel):
+class BONE_PT_constraints(ConstraintButtonsPanel, Panel):
bl_label = "Bone Constraints"
bl_context = "bone_constraint"
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index 63333083cb2..6f58f060504 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
from rna_prop_ui import PropertyPanel
from bl_ui.properties_physics_common import (
@@ -72,7 +73,7 @@ class ParticleButtonsPanel():
return particle_panel_poll(cls, context)
-class PARTICLE_PT_context_particles(ParticleButtonsPanel, bpy.types.Panel):
+class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -155,7 +156,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, bpy.types.Panel):
if part:
split = layout.split(percentage=0.65)
if part.type == 'HAIR':
- if psys != None and psys.is_edited:
+ if psys is not None and psys.is_edited:
split.operator("particle.edited_clear", text="Free Edit")
else:
row = split.row()
@@ -165,18 +166,18 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, bpy.types.Panel):
row = split.row()
row.enabled = particle_panel_enabled(context, psys)
row.prop(part, "hair_step")
- if psys != None and psys.is_edited:
+ if psys is not None and psys.is_edited:
if psys.is_global_hair:
layout.operator("particle.connect_hair")
else:
layout.operator("particle.disconnect_hair")
- elif psys != None and part.type == 'REACTOR':
+ elif psys is not None and part.type == 'REACTOR':
split.enabled = particle_panel_enabled(context, psys)
split.prop(psys, "reactor_target_object")
split.prop(psys, "reactor_target_particle_system", text="Particle System")
-class PARTICLE_PT_emission(ParticleButtonsPanel, bpy.types.Panel):
+class PARTICLE_PT_emission(ParticleButtonsPanel, Panel):
bl_label = "Emission"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -245,7 +246,7 @@ class PARTICLE_PT_emission(ParticleButtonsPanel, bpy.types.Panel):
row.prop(part, "grid_random", text="Random", slider=True)
-class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, bpy.types.Panel):
+class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel):
bl_label = "Hair dynamics"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -301,7 +302,7 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, bpy.types.Panel):
col.prop(cloth, "quality", text="Steps", slider=True)
-class PARTICLE_PT_cache(ParticleButtonsPanel, bpy.types.Panel):
+class PARTICLE_PT_cache(ParticleButtonsPanel, Panel):
bl_label = "Cache"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -327,7 +328,7 @@ class PARTICLE_PT_cache(ParticleButtonsPanel, bpy.types.Panel):
point_cache_ui(self, context, psys.point_cache, True, 'HAIR' if (psys.settings.type == 'HAIR') else 'PSYS')
-class PARTICLE_PT_velocity(ParticleButtonsPanel, bpy.types.Panel):
+class PARTICLE_PT_velocity(ParticleButtonsPanel, Panel):
bl_label = "Velocity"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -377,7 +378,7 @@ class PARTICLE_PT_velocity(ParticleButtonsPanel, bpy.types.Panel):
# sub.prop(part, "reaction_shape", slider=True)
-class PARTICLE_PT_rotation(ParticleButtonsPanel, bpy.types.Panel):
+class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel):
bl_label = "Rotation"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -426,7 +427,7 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, bpy.types.Panel):
col.prop(part, "angular_velocity_factor", text="")
-class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
+class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
bl_label = "Physics"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -462,7 +463,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
col.prop(part, "mass")
col.prop(part, "use_multiply_size_mass", text="Multiply mass with size")
- if part.physics_type in ('NEWTON', 'FLUID'):
+ if part.physics_type in {'NEWTON', 'FLUID'}:
split = layout.split()
col = split.column()
@@ -641,7 +642,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
sub.prop(key, "system", text="System")
-class PARTICLE_PT_boidbrain(ParticleButtonsPanel, bpy.types.Panel):
+class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
bl_label = "Boid Brain"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -653,7 +654,7 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, bpy.types.Panel):
if settings is None:
return False
- if psys != None and psys.point_cache.use_external:
+ if psys is not None and psys.point_cache.use_external:
return False
return settings.physics_type == 'BOIDS' and engine in cls.COMPAT_ENGINES
@@ -742,7 +743,7 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, bpy.types.Panel):
row.prop(rule, "flee_distance")
-class PARTICLE_PT_render(ParticleButtonsPanel, bpy.types.Panel):
+class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
bl_label = "Render"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -879,6 +880,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")
@@ -912,13 +922,13 @@ class PARTICLE_PT_render(ParticleButtonsPanel, bpy.types.Panel):
col = row.column()
col.label(text="")
- if part.render_type in ('OBJECT', 'GROUP') and not part.use_advanced_hair:
+ if part.render_type in {'OBJECT', 'GROUP'} and not part.use_advanced_hair:
row = layout.row(align=True)
row.prop(part, "particle_size")
row.prop(part, "size_random", slider=True)
-class PARTICLE_PT_draw(ParticleButtonsPanel, bpy.types.Panel):
+class PARTICLE_PT_draw(ParticleButtonsPanel, Panel):
bl_label = "Display"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -980,7 +990,7 @@ class PARTICLE_PT_draw(ParticleButtonsPanel, bpy.types.Panel):
col.prop(part, "draw_step")
-class PARTICLE_PT_children(ParticleButtonsPanel, bpy.types.Panel):
+class PARTICLE_PT_children(ParticleButtonsPanel, Panel):
bl_label = "Children"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -1080,7 +1090,7 @@ class PARTICLE_PT_children(ParticleButtonsPanel, bpy.types.Panel):
sub.prop(part, "kink_shape", slider=True)
-class PARTICLE_PT_field_weights(ParticleButtonsPanel, bpy.types.Panel):
+class PARTICLE_PT_field_weights(ParticleButtonsPanel, Panel):
bl_label = "Field Weights"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -1101,7 +1111,7 @@ class PARTICLE_PT_field_weights(ParticleButtonsPanel, bpy.types.Panel):
row.prop(part, "effect_hair", slider=True)
-class PARTICLE_PT_force_fields(ParticleButtonsPanel, bpy.types.Panel):
+class PARTICLE_PT_force_fields(ParticleButtonsPanel, Panel):
bl_label = "Force Field Settings"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -1135,7 +1145,7 @@ class PARTICLE_PT_force_fields(ParticleButtonsPanel, bpy.types.Panel):
basic_force_field_falloff_ui(self, context, part.force_field_2)
-class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, bpy.types.Panel):
+class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, Panel):
bl_label = "Vertexgroups"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -1206,7 +1216,7 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, bpy.types.Panel):
# row.prop(psys, "invert_vertex_group_field", text="")
-class PARTICLE_PT_custom_props(ParticleButtonsPanel, PropertyPanel, bpy.types.Panel):
+class PARTICLE_PT_custom_props(ParticleButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER'}
_context_path = "particle_system.settings"
_property_type = bpy.types.ParticleSettings
diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py
index bce6ab993a7..d5427d8bae8 100644
--- a/release/scripts/startup/bl_ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Menu, Panel
from bl_ui.properties_physics_common import (
@@ -30,14 +31,14 @@ def cloth_panel_enabled(md):
return md.point_cache.is_baked is False
-class CLOTH_MT_presets(bpy.types.Menu):
+class CLOTH_MT_presets(Menu):
'''
Creates the menu items by scanning scripts/templates
'''
bl_label = "Cloth Presets"
preset_subdir = "cloth"
preset_operator = "script.execute_preset"
- draw = bpy.types.Menu.draw_preset
+ draw = Menu.draw_preset
class PhysicButtonsPanel():
@@ -52,7 +53,7 @@ class PhysicButtonsPanel():
return (ob and ob.type == 'MESH') and (not rd.use_game_engine) and (context.cloth)
-class PHYSICS_PT_cloth(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_cloth(PhysicButtonsPanel, Panel):
bl_label = "Cloth"
def draw(self, context):
@@ -117,7 +118,7 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, bpy.types.Panel):
col.prop_search(cloth, "rest_shape_key", key, "key_blocks", text="")
-class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, Panel):
bl_label = "Cloth Cache"
bl_options = {'DEFAULT_CLOSED'}
@@ -130,7 +131,7 @@ class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, bpy.types.Panel):
point_cache_ui(self, context, md.point_cache, cloth_panel_enabled(md), 'CLOTH')
-class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, Panel):
bl_label = "Cloth Collision"
bl_options = {'DEFAULT_CLOSED'}
@@ -171,7 +172,7 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, bpy.types.Panel):
layout.prop(cloth, "group")
-class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, Panel):
bl_label = "Cloth Stiffness Scaling"
bl_options = {'DEFAULT_CLOSED'}
@@ -207,7 +208,7 @@ class PHYSICS_PT_cloth_stiffness(PhysicButtonsPanel, bpy.types.Panel):
col.prop(cloth, "bending_stiffness_max", text="Max")
-class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, Panel):
bl_label = "Cloth Field Weights"
bl_options = {'DEFAULT_CLOSED'}
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index f7cf8da1840..204e25d9f01 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -19,6 +19,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
class PhysicButtonsPanel():
@@ -44,7 +45,7 @@ def physics_add(self, layout, md, name, type, typeicon, toggles):
sub.operator("object.modifier_add", text=name, icon=typeicon).type = type
-class PHYSICS_PT_add(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_add(PhysicButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
diff --git a/release/scripts/startup/bl_ui/properties_physics_field.py b/release/scripts/startup/bl_ui/properties_physics_field.py
index 9f96f0a5b9f..e1dc4d04378 100644
--- a/release/scripts/startup/bl_ui/properties_physics_field.py
+++ b/release/scripts/startup/bl_ui/properties_physics_field.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
from bl_ui.properties_physics_common import (
@@ -37,7 +38,7 @@ class PhysicButtonsPanel():
return (context.object) and (not rd.use_game_engine)
-class PHYSICS_PT_field(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_field(PhysicButtonsPanel, Panel):
bl_label = "Force Fields"
@classmethod
@@ -164,7 +165,7 @@ class PHYSICS_PT_field(PhysicButtonsPanel, bpy.types.Panel):
sub.prop(field, "radial_max", text="Distance")
-class PHYSICS_PT_collision(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_collision(PhysicButtonsPanel, Panel):
bl_label = "Collision"
#bl_options = {'DEFAULT_CLOSED'}
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 5da89d0090a..46893af3582 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
class PhysicButtonsPanel():
@@ -32,7 +33,7 @@ class PhysicButtonsPanel():
return (ob and ob.type == 'MESH') and (not rd.use_game_engine) and (context.fluid)
-class PHYSICS_PT_fluid(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel):
bl_label = "Fluid"
def draw(self, context):
@@ -186,7 +187,7 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, bpy.types.Panel):
sub.prop(fluid, "velocity_radius", text="Radius")
-class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, Panel):
bl_label = "Domain World"
bl_options = {'DEFAULT_CLOSED'}
@@ -236,7 +237,7 @@ class PHYSICS_PT_domain_gravity(PhysicButtonsPanel, bpy.types.Panel):
col.prop(fluid, "compressibility", slider=True)
-class PHYSICS_PT_domain_boundary(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_domain_boundary(PhysicButtonsPanel, Panel):
bl_label = "Domain Boundary"
bl_options = {'DEFAULT_CLOSED'}
@@ -257,6 +258,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:")
@@ -264,7 +266,7 @@ class PHYSICS_PT_domain_boundary(PhysicButtonsPanel, bpy.types.Panel):
col.prop(fluid, "surface_subdivisions", text="Subdivisions")
-class PHYSICS_PT_domain_particles(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_domain_particles(PhysicButtonsPanel, Panel):
bl_label = "Domain Particles"
bl_options = {'DEFAULT_CLOSED'}
diff --git a/release/scripts/startup/bl_ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py
index 61d8d2e3825..771a778380d 100644
--- a/release/scripts/startup/bl_ui/properties_physics_smoke.py
+++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
from bl_ui.properties_physics_common import (
@@ -38,7 +39,7 @@ class PhysicButtonsPanel():
return (ob and ob.type == 'MESH') and (not rd.use_game_engine) and (context.smoke)
-class PHYSICS_PT_smoke(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel):
bl_label = "Smoke"
def draw(self, context):
@@ -103,7 +104,7 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, bpy.types.Panel):
sub.prop(flow, "temperature")
-class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, Panel):
bl_label = "Smoke Groups"
bl_options = {'DEFAULT_CLOSED'}
@@ -131,7 +132,7 @@ class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, bpy.types.Panel):
col.prop(group, "collision_group", text="")
-class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, Panel):
bl_label = "Smoke High Resolution"
bl_options = {'DEFAULT_CLOSED'}
@@ -168,7 +169,7 @@ class PHYSICS_PT_smoke_highres(PhysicButtonsPanel, bpy.types.Panel):
layout.prop(md, "show_high_resolution")
-class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, Panel):
bl_label = "Smoke Cache"
bl_options = {'DEFAULT_CLOSED'}
@@ -189,7 +190,7 @@ class PHYSICS_PT_smoke_cache(PhysicButtonsPanel, bpy.types.Panel):
point_cache_ui(self, context, cache, (cache.is_baked is False), 'SMOKE')
-class PHYSICS_PT_smoke_field_weights(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_smoke_field_weights(PhysicButtonsPanel, Panel):
bl_label = "Smoke Field Weights"
bl_options = {'DEFAULT_CLOSED'}
diff --git a/release/scripts/startup/bl_ui/properties_physics_softbody.py b/release/scripts/startup/bl_ui/properties_physics_softbody.py
index 61115a0590e..0b55ccf9516 100644
--- a/release/scripts/startup/bl_ui/properties_physics_softbody.py
+++ b/release/scripts/startup/bl_ui/properties_physics_softbody.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
from bl_ui.properties_physics_common import (
@@ -44,7 +45,7 @@ class PhysicButtonsPanel():
return (ob and (ob.type == 'MESH' or ob.type == 'LATTICE'or ob.type == 'CURVE')) and (not rd.use_game_engine) and (context.soft_body)
-class PHYSICS_PT_softbody(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_softbody(PhysicButtonsPanel, Panel):
bl_label = "Soft Body"
def draw(self, context):
@@ -71,7 +72,7 @@ class PHYSICS_PT_softbody(PhysicButtonsPanel, bpy.types.Panel):
col.prop(softbody, "speed")
-class PHYSICS_PT_softbody_cache(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_softbody_cache(PhysicButtonsPanel, Panel):
bl_label = "Soft Body Cache"
bl_options = {'DEFAULT_CLOSED'}
@@ -84,7 +85,7 @@ class PHYSICS_PT_softbody_cache(PhysicButtonsPanel, bpy.types.Panel):
point_cache_ui(self, context, md.point_cache, softbody_panel_enabled(md), 'SOFTBODY')
-class PHYSICS_PT_softbody_goal(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_softbody_goal(PhysicButtonsPanel, Panel):
bl_label = "Soft Body Goal"
bl_options = {'DEFAULT_CLOSED'}
@@ -127,7 +128,7 @@ class PHYSICS_PT_softbody_goal(PhysicButtonsPanel, bpy.types.Panel):
layout.prop_search(softbody, "vertex_group_goal", ob, "vertex_groups", text="Vertex Group")
-class PHYSICS_PT_softbody_edge(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_softbody_edge(PhysicButtonsPanel, Panel):
bl_label = "Soft Body Edges"
bl_options = {'DEFAULT_CLOSED'}
@@ -180,7 +181,7 @@ class PHYSICS_PT_softbody_edge(PhysicButtonsPanel, bpy.types.Panel):
col.prop(softbody, "use_face_collision", text="Face")
-class PHYSICS_PT_softbody_collision(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_softbody_collision(PhysicButtonsPanel, Panel):
bl_label = "Soft Body Self Collision"
bl_options = {'DEFAULT_CLOSED'}
@@ -212,7 +213,7 @@ class PHYSICS_PT_softbody_collision(PhysicButtonsPanel, bpy.types.Panel):
col.prop(softbody, "ball_damp", text="Dampening")
-class PHYSICS_PT_softbody_solver(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_softbody_solver(PhysicButtonsPanel, Panel):
bl_label = "Soft Body Solver"
bl_options = {'DEFAULT_CLOSED'}
@@ -248,7 +249,7 @@ class PHYSICS_PT_softbody_solver(PhysicButtonsPanel, bpy.types.Panel):
layout.prop(softbody, "use_estimate_matrix")
-class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel, bpy.types.Panel):
+class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel, Panel):
bl_label = "Soft Body Field Weights"
bl_options = {'DEFAULT_CLOSED'}
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 4e1c1b34363..395cfc6934e 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -18,27 +18,28 @@
# <pep8 compliant>
import bpy
+from bpy.types import Menu, Panel
-class RENDER_MT_presets(bpy.types.Menu):
+class RENDER_MT_presets(Menu):
bl_label = "Render Presets"
preset_subdir = "render"
preset_operator = "script.execute_preset"
- draw = bpy.types.Menu.draw_preset
+ draw = Menu.draw_preset
-class RENDER_MT_ffmpeg_presets(bpy.types.Menu):
+class RENDER_MT_ffmpeg_presets(Menu):
bl_label = "FFMPEG Presets"
preset_subdir = "ffmpeg"
preset_operator = "script.python_file_run"
- draw = bpy.types.Menu.draw_preset
+ draw = Menu.draw_preset
-class RENDER_MT_framerate_presets(bpy.types.Menu):
+class RENDER_MT_framerate_presets(Menu):
bl_label = "Frame Rate Presets"
preset_subdir = "framerate"
preset_operator = "script.execute_preset"
- draw = bpy.types.Menu.draw_preset
+ draw = Menu.draw_preset
class RenderButtonsPanel():
@@ -53,7 +54,7 @@ class RenderButtonsPanel():
return (context.scene and rd.use_game_engine is False) and (rd.engine in cls.COMPAT_ENGINES)
-class RENDER_PT_render(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_render(RenderButtonsPanel, Panel):
bl_label = "Render"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -69,7 +70,7 @@ class RENDER_PT_render(RenderButtonsPanel, bpy.types.Panel):
layout.prop(rd, "display_mode", text="Display")
-class RENDER_PT_layers(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_layers(RenderButtonsPanel, Panel):
bl_label = "Layers"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -141,6 +142,7 @@ class RENDER_PT_layers(RenderButtonsPanel, bpy.types.Panel):
col.prop(rl, "use_pass_uv")
col.prop(rl, "use_pass_mist")
col.prop(rl, "use_pass_object_index")
+ col.prop(rl, "use_pass_material_index")
col.prop(rl, "use_pass_color")
col = split.column()
@@ -172,7 +174,7 @@ class RENDER_PT_layers(RenderButtonsPanel, bpy.types.Panel):
row.prop(rl, "exclude_refraction", text="")
-class RENDER_PT_dimensions(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_dimensions(RenderButtonsPanel, Panel):
bl_label = "Dimensions"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -239,7 +241,7 @@ class RENDER_PT_dimensions(RenderButtonsPanel, bpy.types.Panel):
subrow.prop(rd, "frame_map_new", text="New")
-class RENDER_PT_antialiasing(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_antialiasing(RenderButtonsPanel, Panel):
bl_label = "Anti-Aliasing"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -267,7 +269,7 @@ class RENDER_PT_antialiasing(RenderButtonsPanel, bpy.types.Panel):
col.prop(rd, "filter_size", text="Size")
-class RENDER_PT_motion_blur(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_motion_blur(RenderButtonsPanel, Panel):
bl_label = "Sampled Motion Blur"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -293,7 +295,7 @@ class RENDER_PT_motion_blur(RenderButtonsPanel, bpy.types.Panel):
row.prop(rd, "motion_blur_shutter")
-class RENDER_PT_shading(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_shading(RenderButtonsPanel, Panel):
bl_label = "Shading"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -317,7 +319,7 @@ class RENDER_PT_shading(RenderButtonsPanel, bpy.types.Panel):
col.prop(rd, "alpha_mode", text="Alpha")
-class RENDER_PT_performance(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_performance(RenderButtonsPanel, Panel):
bl_label = "Performance"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -360,7 +362,7 @@ class RENDER_PT_performance(RenderButtonsPanel, bpy.types.Panel):
sub.prop(rd, "use_local_coords", text="Local Coordinates")
-class RENDER_PT_post_processing(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_post_processing(RenderButtonsPanel, Panel):
bl_label = "Post Processing"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -376,8 +378,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()
@@ -398,7 +399,7 @@ class RENDER_PT_post_processing(RenderButtonsPanel, bpy.types.Panel):
sub.prop(rd, "edge_color", text="")
-class RENDER_PT_stamp(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_stamp(RenderButtonsPanel, Panel):
bl_label = "Stamp"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -443,7 +444,7 @@ class RENDER_PT_stamp(RenderButtonsPanel, bpy.types.Panel):
sub.prop(rd, "stamp_note_text", text="")
-class RENDER_PT_output(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_output(RenderButtonsPanel, Panel):
bl_label = "Output"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -543,7 +544,7 @@ class RENDER_PT_output(RenderButtonsPanel, bpy.types.Panel):
col.prop(rd, "quicktime_audio_resampling_hq")
-class RENDER_PT_encoding(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_encoding(RenderButtonsPanel, Panel):
bl_label = "Encoding"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -591,16 +592,12 @@ class RENDER_PT_encoding(RenderButtonsPanel, bpy.types.Panel):
if rd.ffmpeg_format not in {'MP3'}:
layout.prop(rd, "ffmpeg_audio_codec", text="Audio Codec")
- split = layout.split()
-
- col = split.column()
- col.prop(rd, "ffmpeg_audio_bitrate")
- col.prop(rd, "ffmpeg_audio_mixrate")
-
- split.prop(rd, "ffmpeg_audio_volume", slider=True)
+ row = layout.row()
+ row.prop(rd, "ffmpeg_audio_bitrate")
+ row.prop(rd, "ffmpeg_audio_volume", slider=True)
-class RENDER_PT_bake(RenderButtonsPanel, bpy.types.Panel):
+class RENDER_PT_bake(RenderButtonsPanel, Panel):
bl_label = "Bake"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index ce5ac0c62d3..001897c222f 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Operator, Panel
from rna_prop_ui import PropertyPanel
@@ -31,7 +32,7 @@ class SceneButtonsPanel():
return context.scene
-class SCENE_PT_scene(SceneButtonsPanel, bpy.types.Panel):
+class SCENE_PT_scene(SceneButtonsPanel, Panel):
bl_label = "Scene"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -43,7 +44,35 @@ class SCENE_PT_scene(SceneButtonsPanel, bpy.types.Panel):
layout.prop(scene, "background_set", text="Background")
-class SCENE_PT_unit(SceneButtonsPanel, bpy.types.Panel):
+class SCENE_PT_audio(SceneButtonsPanel, Panel):
+ bl_label = "Audio"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+
+ def draw(self, context):
+ layout = self.layout
+ scene = context.scene
+ rd = context.scene.render
+
+ layout.prop(scene, "audio_volume")
+ layout.operator("sound.bake_animation")
+
+ split = layout.split()
+
+ col = split.column()
+ col.label("Listener:")
+ col.prop(scene, "audio_distance_model", text="")
+ col.prop(scene, "audio_doppler_speed", text="Speed")
+ col.prop(scene, "audio_doppler_factor", text="Doppler")
+
+ col = split.column()
+ col.label("Format:")
+ col.prop(rd, "ffmpeg_audio_channels", text="")
+ col.prop(rd, "ffmpeg_audio_mixrate", text="Rate")
+
+ layout.operator("sound.mixdown")
+
+
+class SCENE_PT_unit(SceneButtonsPanel, Panel):
bl_label = "Units"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -61,7 +90,7 @@ class SCENE_PT_unit(SceneButtonsPanel, bpy.types.Panel):
row.prop(unit, "use_separate")
-class SCENE_PT_keying_sets(SceneButtonsPanel, bpy.types.Panel):
+class SCENE_PT_keying_sets(SceneButtonsPanel, Panel):
bl_label = "Keying Sets"
def draw(self, context):
@@ -94,7 +123,7 @@ class SCENE_PT_keying_sets(SceneButtonsPanel, bpy.types.Panel):
col.prop(ks, "bl_options")
-class SCENE_PT_keying_set_paths(SceneButtonsPanel, bpy.types.Panel):
+class SCENE_PT_keying_set_paths(SceneButtonsPanel, Panel):
bl_label = "Active Keying Set"
@classmethod
@@ -144,7 +173,7 @@ class SCENE_PT_keying_set_paths(SceneButtonsPanel, bpy.types.Panel):
col.prop(ksp, "bl_options")
-class SCENE_PT_physics(SceneButtonsPanel, bpy.types.Panel):
+class SCENE_PT_physics(SceneButtonsPanel, Panel):
bl_label = "Gravity"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -161,7 +190,7 @@ class SCENE_PT_physics(SceneButtonsPanel, bpy.types.Panel):
layout.prop(scene, "gravity", text="")
-class SCENE_PT_simplify(SceneButtonsPanel, bpy.types.Panel):
+class SCENE_PT_simplify(SceneButtonsPanel, Panel):
bl_label = "Simplify"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -190,7 +219,7 @@ class SCENE_PT_simplify(SceneButtonsPanel, bpy.types.Panel):
col.prop(rd, "simplify_ao_sss", text="AO and SSS")
-class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, bpy.types.Panel):
+class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "scene"
_property_type = bpy.types.Scene
@@ -198,7 +227,7 @@ class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, bpy.types.Panel):
# XXX, move operator to op/ dir
-class ANIM_OT_keying_set_export(bpy.types.Operator):
+class ANIM_OT_keying_set_export(Operator):
"Export Keying Set to a python script."
bl_idname = "anim.keying_set_export"
bl_label = "Export Keying Set..."
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index 01890bc3c99..34f5a948ee7 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -18,10 +18,11 @@
# <pep8 compliant>
import bpy
+from bpy.types import Menu, Panel
from rna_prop_ui import PropertyPanel
-class TEXTURE_MT_specials(bpy.types.Menu):
+class TEXTURE_MT_specials(Menu):
bl_label = "Texture Specials"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -32,7 +33,7 @@ class TEXTURE_MT_specials(bpy.types.Menu):
layout.operator("texture.slot_paste", icon='PASTEDOWN')
-class TEXTURE_MT_envmap_specials(bpy.types.Menu):
+class TEXTURE_MT_envmap_specials(Menu):
bl_label = "Environment Map Specials"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -80,7 +81,7 @@ class TextureButtonsPanel():
return tex and (tex.type != 'NONE' or tex.use_nodes) and (context.scene.render.engine in cls.COMPAT_ENGINES)
-class TEXTURE_PT_context_texture(TextureButtonsPanel, bpy.types.Panel):
+class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -88,15 +89,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)
@@ -150,7 +151,7 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, bpy.types.Panel):
split.prop(tex, "type", text="")
-class TEXTURE_PT_preview(TextureButtonsPanel, bpy.types.Panel):
+class TEXTURE_PT_preview(TextureButtonsPanel, Panel):
bl_label = "Preview"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -167,7 +168,7 @@ class TEXTURE_PT_preview(TextureButtonsPanel, bpy.types.Panel):
layout.template_preview(tex, slot=slot)
-class TEXTURE_PT_colors(TextureButtonsPanel, bpy.types.Panel):
+class TEXTURE_PT_colors(TextureButtonsPanel, Panel):
bl_label = "Colors"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -208,7 +209,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 #
@@ -223,7 +224,7 @@ class TextureTypePanel(TextureButtonsPanel):
return tex and ((tex.type == cls.tex_type and not tex.use_nodes) and (engine in cls.COMPAT_ENGINES))
-class TEXTURE_PT_clouds(TextureTypePanel, bpy.types.Panel):
+class TEXTURE_PT_clouds(TextureTypePanel, Panel):
bl_label = "Clouds"
tex_type = 'CLOUDS'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -247,7 +248,7 @@ class TEXTURE_PT_clouds(TextureTypePanel, bpy.types.Panel):
split.prop(tex, "nabla", text="Nabla")
-class TEXTURE_PT_wood(TextureTypePanel, bpy.types.Panel):
+class TEXTURE_PT_wood(TextureTypePanel, Panel):
bl_label = "Wood"
tex_type = 'WOOD'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -276,7 +277,7 @@ class TEXTURE_PT_wood(TextureTypePanel, bpy.types.Panel):
split.prop(tex, "nabla")
-class TEXTURE_PT_marble(TextureTypePanel, bpy.types.Panel):
+class TEXTURE_PT_marble(TextureTypePanel, Panel):
bl_label = "Marble"
tex_type = 'MARBLE'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -303,7 +304,7 @@ class TEXTURE_PT_marble(TextureTypePanel, bpy.types.Panel):
col.prop(tex, "nabla")
-class TEXTURE_PT_magic(TextureTypePanel, bpy.types.Panel):
+class TEXTURE_PT_magic(TextureTypePanel, Panel):
bl_label = "Magic"
tex_type = 'MAGIC'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -318,7 +319,7 @@ class TEXTURE_PT_magic(TextureTypePanel, bpy.types.Panel):
row.prop(tex, "turbulence")
-class TEXTURE_PT_blend(TextureTypePanel, bpy.types.Panel):
+class TEXTURE_PT_blend(TextureTypePanel, Panel):
bl_label = "Blend"
tex_type = 'BLEND'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -336,7 +337,7 @@ class TEXTURE_PT_blend(TextureTypePanel, bpy.types.Panel):
sub.prop(tex, "use_flip_axis", expand=True)
-class TEXTURE_PT_stucci(TextureTypePanel, bpy.types.Panel):
+class TEXTURE_PT_stucci(TextureTypePanel, Panel):
bl_label = "Stucci"
tex_type = 'STUCCI'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -356,7 +357,7 @@ class TEXTURE_PT_stucci(TextureTypePanel, bpy.types.Panel):
row.prop(tex, "turbulence")
-class TEXTURE_PT_image(TextureTypePanel, bpy.types.Panel):
+class TEXTURE_PT_image(TextureTypePanel, Panel):
bl_label = "Image"
tex_type = 'IMAGE'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -382,7 +383,7 @@ def texture_filter_common(tex, layout):
layout.prop(tex, "use_filter_size_min")
-class TEXTURE_PT_image_sampling(TextureTypePanel, bpy.types.Panel):
+class TEXTURE_PT_image_sampling(TextureTypePanel, Panel):
bl_label = "Image Sampling"
bl_options = {'DEFAULT_CLOSED'}
tex_type = 'IMAGE'
@@ -393,7 +394,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,12 +409,16 @@ 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
row.prop(slot, "normal_map_space", text="")
+ row = col.row()
+ row.active = not tex.use_normal_map
+ row.prop(tex, "use_derivative_map")
+
col.prop(tex, "use_mipmap")
row = col.row()
row.active = tex.use_mipmap
@@ -423,7 +428,7 @@ class TEXTURE_PT_image_sampling(TextureTypePanel, bpy.types.Panel):
texture_filter_common(tex, col)
-class TEXTURE_PT_image_mapping(TextureTypePanel, bpy.types.Panel):
+class TEXTURE_PT_image_mapping(TextureTypePanel, Panel):
bl_label = "Image Mapping"
bl_options = {'DEFAULT_CLOSED'}
tex_type = 'IMAGE'
@@ -479,7 +484,7 @@ class TEXTURE_PT_image_mapping(TextureTypePanel, bpy.types.Panel):
col.prop(tex, "crop_max_y", text="Y")
-class TEXTURE_PT_envmap(TextureTypePanel, bpy.types.Panel):
+class TEXTURE_PT_envmap(TextureTypePanel, Panel):
bl_label = "Environment Map"
tex_type = 'ENVIRONMENT_MAP'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -517,7 +522,7 @@ class TEXTURE_PT_envmap(TextureTypePanel, bpy.types.Panel):
col.prop(env, "clip_end", text="End")
-class TEXTURE_PT_envmap_sampling(TextureTypePanel, bpy.types.Panel):
+class TEXTURE_PT_envmap_sampling(TextureTypePanel, Panel):
bl_label = "Environment Map Sampling"
bl_options = {'DEFAULT_CLOSED'}
tex_type = 'ENVIRONMENT_MAP'
@@ -531,7 +536,7 @@ class TEXTURE_PT_envmap_sampling(TextureTypePanel, bpy.types.Panel):
texture_filter_common(tex, layout)
-class TEXTURE_PT_musgrave(TextureTypePanel, bpy.types.Panel):
+class TEXTURE_PT_musgrave(TextureTypePanel, Panel):
bl_label = "Musgrave"
tex_type = 'MUSGRAVE'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -568,7 +573,7 @@ class TEXTURE_PT_musgrave(TextureTypePanel, bpy.types.Panel):
row.prop(tex, "nabla")
-class TEXTURE_PT_voronoi(TextureTypePanel, bpy.types.Panel):
+class TEXTURE_PT_voronoi(TextureTypePanel, Panel):
bl_label = "Voronoi"
tex_type = 'VORONOI'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -604,7 +609,7 @@ class TEXTURE_PT_voronoi(TextureTypePanel, bpy.types.Panel):
row.prop(tex, "nabla")
-class TEXTURE_PT_distortednoise(TextureTypePanel, bpy.types.Panel):
+class TEXTURE_PT_distortednoise(TextureTypePanel, Panel):
bl_label = "Distorted Noise"
tex_type = 'DISTORTED_NOISE'
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -626,7 +631,7 @@ class TEXTURE_PT_distortednoise(TextureTypePanel, bpy.types.Panel):
split.prop(tex, "nabla")
-class TEXTURE_PT_voxeldata(TextureButtonsPanel, bpy.types.Panel):
+class TEXTURE_PT_voxeldata(TextureButtonsPanel, Panel):
bl_label = "Voxel Data"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -666,7 +671,7 @@ class TEXTURE_PT_voxeldata(TextureButtonsPanel, bpy.types.Panel):
layout.prop(vd, "intensity")
-class TEXTURE_PT_pointdensity(TextureButtonsPanel, bpy.types.Panel):
+class TEXTURE_PT_pointdensity(TextureButtonsPanel, Panel):
bl_label = "Point Density"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -732,7 +737,7 @@ class TEXTURE_PT_pointdensity(TextureButtonsPanel, bpy.types.Panel):
col.template_curve_mapping(pd, "falloff_curve", brush=False)
-class TEXTURE_PT_pointdensity_turbulence(TextureButtonsPanel, bpy.types.Panel):
+class TEXTURE_PT_pointdensity_turbulence(TextureButtonsPanel, Panel):
bl_label = "Turbulence"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -769,7 +774,7 @@ class TEXTURE_PT_pointdensity_turbulence(TextureButtonsPanel, bpy.types.Panel):
col.prop(pd, "turbulence_strength")
-class TEXTURE_PT_mapping(TextureSlotPanel, bpy.types.Panel):
+class TEXTURE_PT_mapping(TextureSlotPanel, Panel):
bl_label = "Mapping"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -857,7 +862,7 @@ class TEXTURE_PT_mapping(TextureSlotPanel, bpy.types.Panel):
row.column().prop(tex, "scale")
-class TEXTURE_PT_influence(TextureSlotPanel, bpy.types.Panel):
+class TEXTURE_PT_influence(TextureSlotPanel, Panel):
bl_label = "Influence"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@@ -1024,16 +1029,18 @@ class TEXTURE_PT_influence(TextureSlotPanel, bpy.types.Panel):
# only show bump settings if activated but not for normalmap images
row = layout.row()
- row.active = (tex.use_map_normal or tex.use_map_warp) and not (tex.texture.type == 'IMAGE' and tex.texture.use_normal_map)
- row.prop(tex, "bump_method", text="Method")
+ sub = row.row()
+ sub.active = (tex.use_map_normal or tex.use_map_warp) and not (tex.texture.type == 'IMAGE' and (tex.texture.use_normal_map or tex.texture.use_derivative_map))
+ sub.prop(tex, "bump_method", text="Method")
+ # the space setting is supported for: derivmaps + bumpmaps (DEFAULT,BEST_QUALITY), not for normalmaps
sub = row.row()
- sub.active = tex.bump_method in {'BUMP_DEFAULT', 'BUMP_BEST_QUALITY'}
+ sub.active = (tex.use_map_normal or tex.use_map_warp) and not (tex.texture.type == 'IMAGE' and tex.texture.use_normal_map) and ((tex.bump_method in {'BUMP_DEFAULT', 'BUMP_BEST_QUALITY'}) or (tex.texture.type == 'IMAGE' and tex.texture.use_derivative_map))
sub.prop(tex, "bump_objectspace", text="Space")
-class TEXTURE_PT_custom_props(TextureButtonsPanel, PropertyPanel, bpy.types.Panel):
+class TEXTURE_PT_custom_props(TextureButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "texture"
_property_type = bpy.types.Texture
diff --git a/release/scripts/startup/bl_ui/properties_world.py b/release/scripts/startup/bl_ui/properties_world.py
index 4f398c9fbd9..71ee03296a0 100644
--- a/release/scripts/startup/bl_ui/properties_world.py
+++ b/release/scripts/startup/bl_ui/properties_world.py
@@ -18,10 +18,9 @@
# <pep8 compliant>
import bpy
+from bpy.types import Panel
from rna_prop_ui import PropertyPanel
-# TODO, "color_range" not in the UI
-
class WorldButtonsPanel():
bl_space_type = 'PROPERTIES'
@@ -34,7 +33,7 @@ class WorldButtonsPanel():
return (context.world and context.scene.render.engine in cls.COMPAT_ENGINES)
-class WORLD_PT_context_world(WorldButtonsPanel, bpy.types.Panel):
+class WORLD_PT_context_world(WorldButtonsPanel, Panel):
bl_label = ""
bl_options = {'HIDE_HEADER'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -63,7 +62,7 @@ class WORLD_PT_context_world(WorldButtonsPanel, bpy.types.Panel):
split.label(text=str(texture_count), icon='TEXTURE')
-class WORLD_PT_preview(WorldButtonsPanel, bpy.types.Panel):
+class WORLD_PT_preview(WorldButtonsPanel, Panel):
bl_label = "Preview"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -76,7 +75,7 @@ class WORLD_PT_preview(WorldButtonsPanel, bpy.types.Panel):
self.layout.template_preview(context.world)
-class WORLD_PT_world(WorldButtonsPanel, bpy.types.Panel):
+class WORLD_PT_world(WorldButtonsPanel, Panel):
bl_label = "World"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -96,8 +95,12 @@ class WORLD_PT_world(WorldButtonsPanel, bpy.types.Panel):
col.active = world.use_sky_blend
row.column().prop(world, "ambient_color")
+ row = layout.row()
+ row.prop(world, "exposure")
+ row.prop(world, "color_range")
+
-class WORLD_PT_ambient_occlusion(WorldButtonsPanel, bpy.types.Panel):
+class WORLD_PT_ambient_occlusion(WorldButtonsPanel, Panel):
bl_label = "Ambient Occlusion"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -116,7 +119,7 @@ class WORLD_PT_ambient_occlusion(WorldButtonsPanel, bpy.types.Panel):
split.prop(light, "ao_blend_type", text="")
-class WORLD_PT_environment_lighting(WorldButtonsPanel, bpy.types.Panel):
+class WORLD_PT_environment_lighting(WorldButtonsPanel, Panel):
bl_label = "Environment Lighting"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -135,7 +138,7 @@ class WORLD_PT_environment_lighting(WorldButtonsPanel, bpy.types.Panel):
split.prop(light, "environment_color", text="")
-class WORLD_PT_indirect_lighting(WorldButtonsPanel, bpy.types.Panel):
+class WORLD_PT_indirect_lighting(WorldButtonsPanel, Panel):
bl_label = "Indirect Lighting"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -157,7 +160,7 @@ class WORLD_PT_indirect_lighting(WorldButtonsPanel, bpy.types.Panel):
layout.label(text="Only works with Approximate gather method")
-class WORLD_PT_gather(WorldButtonsPanel, bpy.types.Panel):
+class WORLD_PT_gather(WorldButtonsPanel, Panel):
bl_label = "Gather"
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -205,7 +208,7 @@ class WORLD_PT_gather(WorldButtonsPanel, bpy.types.Panel):
col.prop(light, "correction")
-class WORLD_PT_mist(WorldButtonsPanel, bpy.types.Panel):
+class WORLD_PT_mist(WorldButtonsPanel, Panel):
bl_label = "Mist"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -234,7 +237,7 @@ class WORLD_PT_mist(WorldButtonsPanel, bpy.types.Panel):
layout.prop(world.mist_settings, "falloff")
-class WORLD_PT_stars(WorldButtonsPanel, bpy.types.Panel):
+class WORLD_PT_stars(WorldButtonsPanel, Panel):
bl_label = "Stars"
bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@@ -261,7 +264,7 @@ class WORLD_PT_stars(WorldButtonsPanel, bpy.types.Panel):
col.prop(world.star_settings, "average_separation", text="Separation")
-class WORLD_PT_custom_props(WorldButtonsPanel, PropertyPanel, bpy.types.Panel):
+class WORLD_PT_custom_props(WorldButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
_context_path = "world"
_property_type = bpy.types.World
diff --git a/release/scripts/startup/bl_ui/space_console.py b/release/scripts/startup/bl_ui/space_console.py
index da6c102100b..cbbefa01a3c 100644
--- a/release/scripts/startup/bl_ui/space_console.py
+++ b/release/scripts/startup/bl_ui/space_console.py
@@ -18,32 +18,30 @@
# <pep8 compliant>
import bpy
+from bpy.types import Header, Menu, Operator
from bpy.props import StringProperty
-class CONSOLE_HT_header(bpy.types.Header):
+class CONSOLE_HT_header(Header):
bl_space_type = 'CONSOLE'
def draw(self, context):
- layout = self.layout
+ layout = self.layout.row(align=True)
- row = layout.row(align=True)
- row.template_header()
+ layout.template_header()
if context.area.show_menus:
- sub = row.row(align=True)
- sub.menu("CONSOLE_MT_console")
+ layout.menu("CONSOLE_MT_console")
- row = layout.row(align=True)
- row.operator("console.autocomplete", text="Autocomplete")
+ layout.operator("console.autocomplete", text="Autocomplete")
-class CONSOLE_MT_console(bpy.types.Menu):
+class CONSOLE_MT_console(Menu):
bl_label = "Console"
def draw(self, context):
layout = self.layout
- layout.column()
+
layout.operator("console.clear")
layout.operator("console.copy")
layout.operator("console.paste")
@@ -55,7 +53,7 @@ class CONSOLE_MT_console(bpy.types.Menu):
layout.operator("screen.screen_full_area")
-class CONSOLE_MT_language(bpy.types.Menu):
+class CONSOLE_MT_language(Menu):
bl_label = "Languages..."
def draw(self, context):
@@ -82,7 +80,7 @@ def add_scrollback(text, text_type):
type=text_type)
-class ConsoleExec(bpy.types.Operator):
+class ConsoleExec(Operator):
'''Execute the current console line as a python expression'''
bl_idname = "console.execute"
bl_label = "Console Execute"
@@ -100,7 +98,7 @@ class ConsoleExec(bpy.types.Operator):
return {'FINISHED'}
-class ConsoleAutocomplete(bpy.types.Operator):
+class ConsoleAutocomplete(Operator):
'''Evaluate the namespace up until the cursor and give a list of options or complete the name if there is only one'''
bl_idname = "console.autocomplete"
bl_label = "Console Autocomplete"
@@ -117,7 +115,7 @@ class ConsoleAutocomplete(bpy.types.Operator):
return {'FINISHED'}
-class ConsoleBanner(bpy.types.Operator):
+class ConsoleBanner(Operator):
'''Print a message whem the terminal initializes'''
bl_idname = "console.banner"
bl_label = "Console Banner"
@@ -139,11 +137,15 @@ class ConsoleBanner(bpy.types.Operator):
return {'FINISHED'}
-class ConsoleLanguage(bpy.types.Operator):
+class ConsoleLanguage(Operator):
'''Set the current language for this console'''
bl_idname = "console.language"
bl_label = "Console Language"
- language = StringProperty(name="Language", maxlen=32, default="")
+
+ language = StringProperty(
+ name="Language",
+ maxlen=32,
+ )
def execute(self, context):
sc = context.space_data
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index 930a2029d32..90dcc99e6d7 100644
--- a/release/scripts/startup/bl_ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -19,6 +19,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Header, Menu
#######################################
@@ -33,41 +34,10 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False):
row.prop(dopesheet, "show_only_selected", text="")
row.prop(dopesheet, "show_hidden", text="")
- if not genericFiltersOnly:
- row = layout.row(align=True)
- row.prop(dopesheet, "show_transforms", text="")
-
- if is_nla:
- row.prop(dopesheet, "show_missing_nla", text="")
-
- row = layout.row(align=True)
- row.prop(dopesheet, "show_scenes", text="")
- row.prop(dopesheet, "show_worlds", text="")
- row.prop(dopesheet, "show_nodes", text="")
-
- if bpy.data.meshes:
- row.prop(dopesheet, "show_meshes", text="")
- if bpy.data.shape_keys:
- row.prop(dopesheet, "show_shapekeys", text="")
- if bpy.data.materials:
- row.prop(dopesheet, "show_materials", text="")
- if bpy.data.lamps:
- row.prop(dopesheet, "show_lamps", text="")
- if bpy.data.textures:
- row.prop(dopesheet, "show_textures", text="")
- if bpy.data.cameras:
- row.prop(dopesheet, "show_cameras", text="")
- if bpy.data.curves:
- row.prop(dopesheet, "show_curves", text="")
- if bpy.data.metaballs:
- row.prop(dopesheet, "show_metaballs", text="")
- if bpy.data.lattices:
- row.prop(dopesheet, "show_lattices", text="")
- if bpy.data.armatures:
- row.prop(dopesheet, "show_armatures", text="")
- if bpy.data.particles:
- row.prop(dopesheet, "show_particles", text="")
+ if is_nla:
+ row.prop(dopesheet, "show_missing_nla", text="")
+ if not genericFiltersOnly:
if bpy.data.groups:
row = layout.row(align=True)
row.prop(dopesheet, "show_only_group_objects", text="")
@@ -80,11 +50,47 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False):
if dopesheet.show_only_matching_fcurves:
row.prop(dopesheet, "filter_fcurve_name", text="")
+ if not genericFiltersOnly:
+ row = layout.row(align=True)
+ row.prop(dopesheet, "show_datablock_filters", text="Filters")
+
+ if dopesheet.show_datablock_filters:
+ row.prop(dopesheet, "show_scenes", text="")
+ row.prop(dopesheet, "show_worlds", text="")
+ row.prop(dopesheet, "show_nodes", text="")
+
+ row.prop(dopesheet, "show_transforms", text="")
+
+ if bpy.data.meshes:
+ row.prop(dopesheet, "show_meshes", text="")
+ if bpy.data.shape_keys:
+ row.prop(dopesheet, "show_shapekeys", text="")
+ if bpy.data.materials:
+ row.prop(dopesheet, "show_materials", text="")
+ if bpy.data.lamps:
+ row.prop(dopesheet, "show_lamps", text="")
+ if bpy.data.textures:
+ row.prop(dopesheet, "show_textures", text="")
+ if bpy.data.cameras:
+ row.prop(dopesheet, "show_cameras", text="")
+ if bpy.data.curves:
+ row.prop(dopesheet, "show_curves", text="")
+ if bpy.data.metaballs:
+ row.prop(dopesheet, "show_metaballs", text="")
+ if bpy.data.lattices:
+ row.prop(dopesheet, "show_lattices", text="")
+ if bpy.data.armatures:
+ row.prop(dopesheet, "show_armatures", text="")
+ if bpy.data.particles:
+ row.prop(dopesheet, "show_particles", text="")
+ if bpy.data.speakers:
+ row.prop(dopesheet, "show_speakers", text="")
+
#######################################
# DopeSheet Editor - General/Standard UI
-class DOPESHEET_HT_header(bpy.types.Header):
+class DOPESHEET_HT_header(Header):
bl_space_type = 'DOPESHEET_EDITOR'
def draw(self, context):
@@ -96,21 +102,19 @@ class DOPESHEET_HT_header(bpy.types.Header):
row.template_header()
if context.area.show_menus:
- sub = row.row(align=True)
+ row.menu("DOPESHEET_MT_view")
+ row.menu("DOPESHEET_MT_select")
+ row.menu("DOPESHEET_MT_marker")
- sub.menu("DOPESHEET_MT_view")
- sub.menu("DOPESHEET_MT_select")
- sub.menu("DOPESHEET_MT_marker")
-
- if st.mode == 'DOPESHEET' or (st.mode == 'ACTION' and st.action != None):
- sub.menu("DOPESHEET_MT_channel")
+ if st.mode == 'DOPESHEET' or (st.mode == 'ACTION' and st.action is not None):
+ row.menu("DOPESHEET_MT_channel")
elif st.mode == 'GPENCIL':
- sub.menu("DOPESHEET_MT_gpencil_channel")
+ row.menu("DOPESHEET_MT_gpencil_channel")
if st.mode != 'GPENCIL':
- sub.menu("DOPESHEET_MT_key")
+ row.menu("DOPESHEET_MT_key")
else:
- sub.menu("DOPESHEET_MT_gpencil_frame")
+ row.menu("DOPESHEET_MT_gpencil_frame")
layout.prop(st, "mode", text="")
layout.prop(st.dopesheet, "show_summary", text="Summary")
@@ -134,7 +138,7 @@ class DOPESHEET_HT_header(bpy.types.Header):
row.operator("action.paste", text="", icon='PASTEDOWN')
-class DOPESHEET_MT_view(bpy.types.Menu):
+class DOPESHEET_MT_view(Menu):
bl_label = "View"
def draw(self, context):
@@ -142,8 +146,6 @@ class DOPESHEET_MT_view(bpy.types.Menu):
st = context.space_data
- layout.column()
-
layout.prop(st, "use_realtime_update")
layout.prop(st, "show_frame_indicator")
layout.prop(st, "show_sliders")
@@ -170,13 +172,12 @@ class DOPESHEET_MT_view(bpy.types.Menu):
layout.operator("screen.screen_full_area")
-class DOPESHEET_MT_select(bpy.types.Menu):
+class DOPESHEET_MT_select(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
- layout.column()
# This is a bit misleading as the operator's default text is "Select All" while it actually *toggles* All/None
layout.operator("action.select_all_toggle")
layout.operator("action.select_all_toggle", text="Invert Selection").invert = True
@@ -206,7 +207,7 @@ class DOPESHEET_MT_select(bpy.types.Menu):
layout.operator("action.select_linked")
-class DOPESHEET_MT_marker(bpy.types.Menu):
+class DOPESHEET_MT_marker(Menu):
bl_label = "Marker"
def draw(self, context):
@@ -216,7 +217,6 @@ class DOPESHEET_MT_marker(bpy.types.Menu):
#layout.operator_context = 'EXEC_REGION_WIN'
- layout.column()
layout.operator("marker.add", "Add Marker")
layout.operator("marker.duplicate", text="Duplicate Marker")
layout.operator("marker.delete", text="Delete Marker")
@@ -237,7 +237,7 @@ class DOPESHEET_MT_marker(bpy.types.Menu):
#######################################
# Keyframe Editing
-class DOPESHEET_MT_channel(bpy.types.Menu):
+class DOPESHEET_MT_channel(Menu):
bl_label = "Channel"
def draw(self, context):
@@ -245,7 +245,6 @@ class DOPESHEET_MT_channel(bpy.types.Menu):
layout.operator_context = 'INVOKE_REGION_CHANNELS'
- layout.column()
layout.operator("anim.channels_delete")
layout.separator()
@@ -268,13 +267,12 @@ class DOPESHEET_MT_channel(bpy.types.Menu):
layout.operator("anim.channels_fcurves_enable")
-class DOPESHEET_MT_key(bpy.types.Menu):
+class DOPESHEET_MT_key(Menu):
bl_label = "Key"
def draw(self, context):
layout = self.layout
- layout.column()
layout.menu("DOPESHEET_MT_key_transform", text="Transform")
layout.operator_menu_enum("action.snap", "type", text="Snap")
@@ -284,7 +282,7 @@ class DOPESHEET_MT_key(bpy.types.Menu):
layout.operator("action.keyframe_insert")
layout.separator()
- layout.operator("action.duplicate")
+ layout.operator("action.duplicate_move")
layout.operator("action.delete")
layout.separator()
@@ -301,13 +299,12 @@ class DOPESHEET_MT_key(bpy.types.Menu):
layout.operator("action.paste")
-class DOPESHEET_MT_key_transform(bpy.types.Menu):
+class DOPESHEET_MT_key_transform(Menu):
bl_label = "Transform"
def draw(self, context):
layout = self.layout
- layout.column()
layout.operator("transform.transform", text="Grab/Move").mode = 'TIME_TRANSLATE'
layout.operator("transform.transform", text="Extend").mode = 'TIME_EXTEND'
layout.operator("transform.transform", text="Slide").mode = 'TIME_SLIDE'
@@ -317,7 +314,7 @@ class DOPESHEET_MT_key_transform(bpy.types.Menu):
#######################################
# Grease Pencil Editing
-class DOPESHEET_MT_gpencil_channel(bpy.types.Menu):
+class DOPESHEET_MT_gpencil_channel(Menu):
bl_label = "Channel"
def draw(self, context):
@@ -325,7 +322,6 @@ class DOPESHEET_MT_gpencil_channel(bpy.types.Menu):
layout.operator_context = 'INVOKE_REGION_CHANNELS'
- layout.column()
layout.operator("anim.channels_delete")
layout.separator()
@@ -345,13 +341,12 @@ class DOPESHEET_MT_gpencil_channel(bpy.types.Menu):
#layout.operator_menu_enum("anim.channels_move", "direction", text="Move...")
-class DOPESHEET_MT_gpencil_frame(bpy.types.Menu):
+class DOPESHEET_MT_gpencil_frame(Menu):
bl_label = "Frame"
def draw(self, context):
layout = self.layout
- layout.column()
layout.menu("DOPESHEET_MT_key_transform", text="Transform")
#layout.operator_menu_enum("action.snap", "type", text="Snap")
diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py
index 73fe1a97252..cf0d10c5844 100644
--- a/release/scripts/startup/bl_ui/space_filebrowser.py
+++ b/release/scripts/startup/bl_ui/space_filebrowser.py
@@ -18,9 +18,10 @@
# <pep8 compliant>
import bpy
+from bpy.types import Header
-class FILEBROWSER_HT_header(bpy.types.Header):
+class FILEBROWSER_HT_header(Header):
bl_space_type = 'FILE_BROWSER'
def draw(self, context):
diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index bfc1a0e3a23..d4b8c415a7f 100644
--- a/release/scripts/startup/bl_ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -19,9 +19,10 @@
# <pep8 compliant>
import bpy
+from bpy.types import Header, Menu
-class GRAPH_HT_header(bpy.types.Header):
+class GRAPH_HT_header(Header):
bl_space_type = 'GRAPH_EDITOR'
def draw(self, context):
@@ -35,13 +36,11 @@ class GRAPH_HT_header(bpy.types.Header):
row.template_header()
if context.area.show_menus:
- sub = row.row(align=True)
-
- sub.menu("GRAPH_MT_view")
- sub.menu("GRAPH_MT_select")
- sub.menu("GRAPH_MT_marker")
- sub.menu("GRAPH_MT_channel")
- sub.menu("GRAPH_MT_key")
+ row.menu("GRAPH_MT_view")
+ row.menu("GRAPH_MT_select")
+ row.menu("GRAPH_MT_marker")
+ row.menu("GRAPH_MT_channel")
+ row.menu("GRAPH_MT_key")
layout.prop(st, "mode", text="")
@@ -61,7 +60,7 @@ class GRAPH_HT_header(bpy.types.Header):
row.operator("graph.ghost_curves_create", text="", icon='GHOST_ENABLED')
-class GRAPH_MT_view(bpy.types.Menu):
+class GRAPH_MT_view(Menu):
bl_label = "View"
def draw(self, context):
@@ -69,8 +68,6 @@ class GRAPH_MT_view(bpy.types.Menu):
st = context.space_data
- layout.column()
-
layout.operator("graph.properties", icon='MENU_PANEL')
layout.separator()
@@ -81,7 +78,7 @@ class GRAPH_MT_view(bpy.types.Menu):
layout.prop(st, "use_auto_merge_keyframes")
layout.separator()
- layout.prop(st, "use_fancy_drawing")
+ layout.prop(st, "use_beauty_drawing")
layout.separator()
if st.show_handles:
@@ -107,13 +104,12 @@ class GRAPH_MT_view(bpy.types.Menu):
layout.operator("screen.screen_full_area")
-class GRAPH_MT_select(bpy.types.Menu):
+class GRAPH_MT_select(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
- layout.column()
# This is a bit misleading as the operator's default text is "Select All" while it actually *toggles* All/None
layout.operator("graph.select_all_toggle")
layout.operator("graph.select_all_toggle", text="Invert Selection").invert = True
@@ -142,7 +138,7 @@ class GRAPH_MT_select(bpy.types.Menu):
layout.operator("graph.select_linked")
-class GRAPH_MT_marker(bpy.types.Menu):
+class GRAPH_MT_marker(Menu):
bl_label = "Marker"
def draw(self, context):
@@ -150,7 +146,6 @@ class GRAPH_MT_marker(bpy.types.Menu):
#layout.operator_context = 'EXEC_REGION_WIN'
- layout.column()
layout.operator("marker.add", "Add Marker")
layout.operator("marker.duplicate", text="Duplicate Marker")
layout.operator("marker.delete", text="Delete Marker")
@@ -163,7 +158,7 @@ class GRAPH_MT_marker(bpy.types.Menu):
# TODO: pose markers for action edit mode only?
-class GRAPH_MT_channel(bpy.types.Menu):
+class GRAPH_MT_channel(Menu):
bl_label = "Channel"
def draw(self, context):
@@ -171,7 +166,6 @@ class GRAPH_MT_channel(bpy.types.Menu):
layout.operator_context = 'INVOKE_REGION_CHANNELS'
- layout.column()
layout.operator("anim.channels_delete")
layout.separator()
@@ -195,13 +189,12 @@ class GRAPH_MT_channel(bpy.types.Menu):
layout.operator("anim.channels_fcurves_enable")
-class GRAPH_MT_key(bpy.types.Menu):
+class GRAPH_MT_key(Menu):
bl_label = "Key"
def draw(self, context):
layout = self.layout
- layout.column()
layout.menu("GRAPH_MT_key_transform", text="Transform")
layout.operator_menu_enum("graph.snap", "type", text="Snap")
@@ -213,7 +206,7 @@ class GRAPH_MT_key(bpy.types.Menu):
layout.operator("graph.sound_bake")
layout.separator()
- layout.operator("graph.duplicate")
+ layout.operator("graph.duplicate_move")
layout.operator("graph.delete")
layout.separator()
@@ -234,13 +227,12 @@ class GRAPH_MT_key(bpy.types.Menu):
layout.operator("graph.euler_filter", text="Discontinuity (Euler) Filter")
-class GRAPH_MT_key_transform(bpy.types.Menu):
+class GRAPH_MT_key_transform(Menu):
bl_label = "Transform"
def draw(self, context):
layout = self.layout
- layout.column()
layout.operator("transform.translate", text="Grab/Move")
layout.operator("transform.transform", text="Extend").mode = 'TIME_EXTEND'
layout.operator("transform.rotate", text="Rotate")
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 9f69ca17076..97b5d8457e0 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Header, Menu, Panel
class BrushButtonsPanel():
@@ -31,7 +32,7 @@ class BrushButtonsPanel():
return sima.show_paint and toolsettings.brush
-class IMAGE_MT_view(bpy.types.Menu):
+class IMAGE_MT_view(Menu):
bl_label = "View"
def draw(self, context):
@@ -79,7 +80,7 @@ class IMAGE_MT_view(bpy.types.Menu):
layout.operator("screen.screen_full_area")
-class IMAGE_MT_select(bpy.types.Menu):
+class IMAGE_MT_select(Menu):
bl_label = "Select"
def draw(self, context):
@@ -100,7 +101,7 @@ class IMAGE_MT_select(bpy.types.Menu):
layout.operator("uv.select_linked")
-class IMAGE_MT_image(bpy.types.Menu):
+class IMAGE_MT_image(Menu):
bl_label = "Image"
def draw(self, context):
@@ -151,7 +152,7 @@ class IMAGE_MT_image(bpy.types.Menu):
layout.prop(sima, "use_image_paint")
-class IMAGE_MT_image_invert(bpy.types.Menu):
+class IMAGE_MT_image_invert(Menu):
bl_label = "Invert"
def draw(self, context):
@@ -177,7 +178,7 @@ class IMAGE_MT_image_invert(bpy.types.Menu):
op.invert_a = True
-class IMAGE_MT_uvs_showhide(bpy.types.Menu):
+class IMAGE_MT_uvs_showhide(Menu):
bl_label = "Show/Hide Faces"
def draw(self, context):
@@ -188,7 +189,7 @@ class IMAGE_MT_uvs_showhide(bpy.types.Menu):
layout.operator("uv.hide", text="Hide Unselected").unselected = True
-class IMAGE_MT_uvs_transform(bpy.types.Menu):
+class IMAGE_MT_uvs_transform(Menu):
bl_label = "Transform"
def draw(self, context):
@@ -198,8 +199,12 @@ class IMAGE_MT_uvs_transform(bpy.types.Menu):
layout.operator("transform.rotate")
layout.operator("transform.resize")
+ layout.separator()
+
+ layout.operator("transform.shear")
+
-class IMAGE_MT_uvs_snap(bpy.types.Menu):
+class IMAGE_MT_uvs_snap(Menu):
bl_label = "Snap"
def draw(self, context):
@@ -216,7 +221,7 @@ class IMAGE_MT_uvs_snap(bpy.types.Menu):
layout.operator("uv.snap_cursor", text="Cursor to Selected").target = 'SELECTED'
-class IMAGE_MT_uvs_mirror(bpy.types.Menu):
+class IMAGE_MT_uvs_mirror(Menu):
bl_label = "Mirror"
def draw(self, context):
@@ -227,7 +232,7 @@ class IMAGE_MT_uvs_mirror(bpy.types.Menu):
layout.operator("transform.mirror", text="Y Axis").constraint_axis[1] = True
-class IMAGE_MT_uvs_weldalign(bpy.types.Menu):
+class IMAGE_MT_uvs_weldalign(Menu):
bl_label = "Weld/Align"
def draw(self, context):
@@ -237,7 +242,7 @@ class IMAGE_MT_uvs_weldalign(bpy.types.Menu):
layout.operator_enum("uv.align", "axis") # W, 2/3/4
-class IMAGE_MT_uvs(bpy.types.Menu):
+class IMAGE_MT_uvs(Menu):
bl_label = "UVs"
def draw(self, context):
@@ -282,7 +287,7 @@ class IMAGE_MT_uvs(bpy.types.Menu):
layout.menu("IMAGE_MT_uvs_showhide")
-class IMAGE_MT_uvs_select_mode(bpy.types.Menu):
+class IMAGE_MT_uvs_select_mode(Menu):
bl_label = "UV Select Mode"
def draw(self, context):
@@ -324,7 +329,7 @@ class IMAGE_MT_uvs_select_mode(bpy.types.Menu):
prop.data_path = "tool_settings.uv_select_mode"
-class IMAGE_HT_header(bpy.types.Header):
+class IMAGE_HT_header(Header):
bl_space_type = 'IMAGE_EDITOR'
def draw(self, context):
@@ -382,7 +387,7 @@ class IMAGE_HT_header(bpy.types.Header):
row = layout.row(align=True)
row.prop(toolsettings, "use_snap", text="")
- row.prop(toolsettings, "snap_element", text="", icon_only=True)
+ row.prop(toolsettings, "snap_target", text="")
mesh = context.edit_object.data
layout.prop_search(mesh.uv_textures, "active", mesh, "uv_textures", text="")
@@ -408,7 +413,7 @@ class IMAGE_HT_header(bpy.types.Header):
layout.prop(sima, "use_realtime_update", text="", icon_only=True, icon='LOCKED')
-class IMAGE_PT_image_properties(bpy.types.Panel):
+class IMAGE_PT_image_properties(Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'UI'
bl_label = "Image"
@@ -427,14 +432,13 @@ class IMAGE_PT_image_properties(bpy.types.Panel):
layout.template_image(sima, "image", iuser)
-class IMAGE_PT_game_properties(bpy.types.Panel):
+class IMAGE_PT_game_properties(Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'UI'
bl_label = "Game Properties"
@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')
@@ -449,14 +453,12 @@ class IMAGE_PT_game_properties(bpy.types.Panel):
col = split.column()
+ col.prop(ima, "use_animation")
sub = col.column(align=True)
- sub.prop(ima, "use_animation")
-
- subsub = sub.column()
- subsub.active = ima.use_animation
- subsub.prop(ima, "frame_start", text="Start")
- subsub.prop(ima, "frame_end", text="End")
- subsub.prop(ima, "fps", text="Speed")
+ sub.active = ima.use_animation
+ sub.prop(ima, "frame_start", text="Start")
+ sub.prop(ima, "frame_end", text="End")
+ sub.prop(ima, "fps", text="Speed")
col.prop(ima, "use_tiles")
sub = col.column(align=True)
@@ -472,7 +474,7 @@ class IMAGE_PT_game_properties(bpy.types.Panel):
col.prop(ima, "mapping", expand=True)
-class IMAGE_PT_view_histogram(bpy.types.Panel):
+class IMAGE_PT_view_histogram(Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'PREVIEW'
bl_label = "Histogram"
@@ -491,7 +493,7 @@ class IMAGE_PT_view_histogram(bpy.types.Panel):
layout.prop(sima.scopes.histogram, "mode", icon_only=True)
-class IMAGE_PT_view_waveform(bpy.types.Panel):
+class IMAGE_PT_view_waveform(Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'PREVIEW'
bl_label = "Waveform"
@@ -505,13 +507,14 @@ class IMAGE_PT_view_waveform(bpy.types.Panel):
layout = self.layout
sima = context.space_data
+
layout.template_waveform(sima, "scopes")
- sub = layout.row().split(percentage=0.75)
- sub.prop(sima.scopes, "waveform_alpha")
- sub.prop(sima.scopes, "waveform_mode", text="", icon_only=True)
+ row = layout.split(percentage=0.75)
+ row.prop(sima.scopes, "waveform_alpha")
+ row.prop(sima.scopes, "waveform_mode", text="", icon_only=True)
-class IMAGE_PT_view_vectorscope(bpy.types.Panel):
+class IMAGE_PT_view_vectorscope(Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'PREVIEW'
bl_label = "Vectorscope"
@@ -529,7 +532,7 @@ class IMAGE_PT_view_vectorscope(bpy.types.Panel):
layout.prop(sima.scopes, "vectorscope_alpha")
-class IMAGE_PT_sample_line(bpy.types.Panel):
+class IMAGE_PT_sample_line(Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'PREVIEW'
bl_label = "Sample Line"
@@ -541,13 +544,15 @@ class IMAGE_PT_sample_line(bpy.types.Panel):
def draw(self, context):
layout = self.layout
- layout.operator("image.sample_line")
+
sima = context.space_data
+
+ layout.operator("image.sample_line")
layout.template_histogram(sima, "sample_histogram")
layout.prop(sima.sample_histogram, "mode")
-class IMAGE_PT_scope_sample(bpy.types.Panel):
+class IMAGE_PT_scope_sample(Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'PREVIEW'
bl_label = "Scope Samples"
@@ -559,16 +564,17 @@ class IMAGE_PT_scope_sample(bpy.types.Panel):
def draw(self, context):
layout = self.layout
+
sima = context.space_data
- split = layout.split()
- row = split.row()
+
+ row = layout.row()
row.prop(sima.scopes, "use_full_resolution")
- row = split.row()
- row.active = not sima.scopes.use_full_resolution
- row.prop(sima.scopes, "accuracy")
+ sub = row.row()
+ sub.active = not sima.scopes.use_full_resolution
+ sub.prop(sima.scopes, "accuracy")
-class IMAGE_PT_view_properties(bpy.types.Panel):
+class IMAGE_PT_view_properties(Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'UI'
bl_label = "Display"
@@ -605,21 +611,20 @@ class IMAGE_PT_view_properties(bpy.types.Panel):
if show_uvedit:
col = layout.column()
- col.label("Cursor Location")
- row = col.row()
- row.prop(uvedit, "cursor_location", text="")
+ col.label("Cursor Location:")
+ col.row().prop(uvedit, "cursor_location", text="")
+
+ col.separator()
- col = layout.column()
col.label(text="UVs:")
- row = col.row()
- row.prop(uvedit, "edge_draw_type", expand=True)
+ col.row().prop(uvedit, "edge_draw_type", expand=True)
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")
@@ -628,7 +633,7 @@ class IMAGE_PT_view_properties(bpy.types.Panel):
sub.row().prop(uvedit, "draw_stretch_type", expand=True)
-class IMAGE_PT_paint(bpy.types.Panel):
+class IMAGE_PT_paint(Panel):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'UI'
bl_label = "Paint"
@@ -644,9 +649,8 @@ class IMAGE_PT_paint(bpy.types.Panel):
toolsettings = context.tool_settings.image_paint
brush = toolsettings.brush
- col = layout.split().column()
- row = col.row()
- col.template_ID_preview(toolsettings, "brush", new="brush.add", rows=3, cols=8)
+ col = layout.column()
+ col.template_ID_preview(toolsettings, "brush", new="brush.add", rows=2, cols=6)
if brush:
col = layout.column()
@@ -673,7 +677,7 @@ class IMAGE_PT_paint(bpy.types.Panel):
col.prop(brush, "clone_alpha", text="Alpha")
-class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, bpy.types.Panel):
+class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, Panel):
bl_label = "Texture"
bl_options = {'DEFAULT_CLOSED'}
@@ -688,7 +692,7 @@ class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, bpy.types.Panel):
col.prop(brush, "use_fixed_texture")
-class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, bpy.types.Panel):
+class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, Panel):
bl_label = "Tool"
bl_options = {'DEFAULT_CLOSED'}
@@ -697,9 +701,7 @@ class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, bpy.types.Panel):
settings = context.tool_settings.image_paint
brush = settings.brush
- col = layout.column(align=True)
-
- col.prop(brush, "image_tool", expand=False, text="")
+ layout.prop(brush, "image_tool", text="")
row = layout.row(align=True)
row.prop(brush, "use_paint_sculpt", text="", icon='SCULPTMODE_HLT')
@@ -708,7 +710,7 @@ class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, bpy.types.Panel):
row.prop(brush, "use_paint_image", text="", icon='TPAINT_HLT')
-class IMAGE_PT_paint_stroke(BrushButtonsPanel, bpy.types.Panel):
+class IMAGE_PT_paint_stroke(BrushButtonsPanel, Panel):
bl_label = "Paint Stroke"
bl_options = {'DEFAULT_CLOSED'}
@@ -719,9 +721,9 @@ class IMAGE_PT_paint_stroke(BrushButtonsPanel, bpy.types.Panel):
brush = toolsettings.brush
layout.prop(brush, "use_airbrush")
- col = layout.column()
- col.active = brush.use_airbrush
- col.prop(brush, "rate", slider=True)
+ row = layout.row()
+ row.active = brush.use_airbrush
+ row.prop(brush, "rate", slider=True)
layout.prop(brush, "use_space")
row = layout.row(align=True)
@@ -732,7 +734,7 @@ class IMAGE_PT_paint_stroke(BrushButtonsPanel, bpy.types.Panel):
layout.prop(brush, "use_wrap")
-class IMAGE_PT_paint_curve(BrushButtonsPanel, bpy.types.Panel):
+class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel):
bl_label = "Paint Curve"
bl_options = {'DEFAULT_CLOSED'}
diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py
index 1fb2e5b735e..7f5a5f231cf 100644
--- a/release/scripts/startup/bl_ui/space_info.py
+++ b/release/scripts/startup/bl_ui/space_info.py
@@ -18,9 +18,10 @@
# <pep8 compliant>
import bpy
+from bpy.types import Header, Menu, Operator
-class INFO_HT_header(bpy.types.Header):
+class INFO_HT_header(Header):
bl_space_type = 'INFO'
def draw(self, context):
@@ -61,7 +62,9 @@ class INFO_HT_header(bpy.types.Header):
layout.template_reports_banner()
- layout.label(text=scene.statistics())
+ row = layout.row(align=True)
+ row.operator("wm.splash", text="", icon='BLENDER', emboss=False)
+ row.label(text=scene.statistics())
# XXX: this should be right-aligned to the RHS of the region
layout.operator("wm.window_fullscreen_toggle", icon='FULLSCREEN_ENTER', text="")
@@ -84,19 +87,19 @@ class INFO_HT_header(bpy.types.Header):
"""
-class INFO_MT_report(bpy.types.Menu):
+class INFO_MT_report(Menu):
bl_label = "Report"
def draw(self, context):
layout = self.layout
- layout.column()
+
layout.operator("console.select_all_toggle")
layout.operator("console.select_border")
layout.operator("console.report_delete")
layout.operator("console.report_copy")
-class INFO_MT_file(bpy.types.Menu):
+class INFO_MT_file(Menu):
bl_label = "File"
def draw(self, context):
@@ -150,7 +153,7 @@ class INFO_MT_file(bpy.types.Menu):
layout.operator("wm.quit_blender", text="Quit", icon='QUIT')
-class INFO_MT_file_import(bpy.types.Menu):
+class INFO_MT_file_import(Menu):
bl_idname = "INFO_MT_file_import"
bl_label = "Import"
@@ -159,7 +162,7 @@ class INFO_MT_file_import(bpy.types.Menu):
self.layout.operator("wm.collada_import", text="COLLADA (.dae)")
-class INFO_MT_file_export(bpy.types.Menu):
+class INFO_MT_file_export(Menu):
bl_idname = "INFO_MT_file_export"
bl_label = "Export"
@@ -168,7 +171,7 @@ class INFO_MT_file_export(bpy.types.Menu):
self.layout.operator("wm.collada_export", text="COLLADA (.dae)")
-class INFO_MT_file_external_data(bpy.types.Menu):
+class INFO_MT_file_external_data(Menu):
bl_label = "External Data"
def draw(self, context):
@@ -185,12 +188,13 @@ class INFO_MT_file_external_data(bpy.types.Menu):
layout.operator("file.find_missing_files")
-class INFO_MT_mesh_add(bpy.types.Menu):
+class INFO_MT_mesh_add(Menu):
bl_idname = "INFO_MT_mesh_add"
bl_label = "Mesh"
def draw(self, context):
layout = self.layout
+
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("mesh.primitive_plane_add", icon='MESH_PLANE', text="Plane")
layout.operator("mesh.primitive_cube_add", icon='MESH_CUBE', text="Cube")
@@ -205,12 +209,13 @@ class INFO_MT_mesh_add(bpy.types.Menu):
layout.operator("mesh.primitive_torus_add", text="Torus", icon='MESH_TORUS')
-class INFO_MT_curve_add(bpy.types.Menu):
+class INFO_MT_curve_add(Menu):
bl_idname = "INFO_MT_curve_add"
bl_label = "Curve"
def draw(self, context):
layout = self.layout
+
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("curve.primitive_bezier_curve_add", icon='CURVE_BEZCURVE', text="Bezier")
layout.operator("curve.primitive_bezier_circle_add", icon='CURVE_BEZCIRCLE', text="Circle")
@@ -219,7 +224,7 @@ class INFO_MT_curve_add(bpy.types.Menu):
layout.operator("curve.primitive_nurbs_path_add", icon='CURVE_PATH', text="Path")
-class INFO_MT_edit_curve_add(bpy.types.Menu):
+class INFO_MT_edit_curve_add(Menu):
bl_idname = "INFO_MT_edit_curve_add"
bl_label = "Add"
@@ -235,12 +240,13 @@ class INFO_MT_edit_curve_add(bpy.types.Menu):
INFO_MT_curve_add.draw(self, context)
-class INFO_MT_surface_add(bpy.types.Menu):
+class INFO_MT_surface_add(Menu):
bl_idname = "INFO_MT_surface_add"
bl_label = "Surface"
def draw(self, context):
layout = self.layout
+
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("surface.primitive_nurbs_surface_curve_add", icon='SURFACE_NCURVE', text="NURBS Curve")
layout.operator("surface.primitive_nurbs_surface_circle_add", icon='SURFACE_NCIRCLE', text="NURBS Circle")
@@ -250,17 +256,18 @@ class INFO_MT_surface_add(bpy.types.Menu):
layout.operator("surface.primitive_nurbs_surface_torus_add", icon='SURFACE_NTORUS', text="NURBS Torus")
-class INFO_MT_armature_add(bpy.types.Menu):
+class INFO_MT_armature_add(Menu):
bl_idname = "INFO_MT_armature_add"
bl_label = "Armature"
def draw(self, context):
layout = self.layout
+
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("object.armature_add", text="Single Bone", icon='BONE_DATA')
-class INFO_MT_add(bpy.types.Menu):
+class INFO_MT_add(Menu):
bl_label = "Add"
def draw(self, context):
@@ -285,6 +292,9 @@ class INFO_MT_add(bpy.types.Menu):
layout.operator("object.add", text="Empty", icon='OUTLINER_OB_EMPTY').type = 'EMPTY'
layout.separator()
+ layout.operator("object.speaker_add", text="Speaker", icon='OUTLINER_OB_SPEAKER')
+ layout.separator()
+
layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA')
layout.operator_context = 'EXEC_SCREEN'
layout.operator_menu_enum("object.lamp_add", "type", text="Lamp", icon='OUTLINER_OB_LAMP')
@@ -300,7 +310,7 @@ class INFO_MT_add(bpy.types.Menu):
layout.operator_menu_enum("object.group_instance_add", "group", text="Group Instance", icon='OUTLINER_OB_EMPTY')
-class INFO_MT_game(bpy.types.Menu):
+class INFO_MT_game(Menu):
bl_label = "Game"
def draw(self, context):
@@ -321,7 +331,7 @@ class INFO_MT_game(bpy.types.Menu):
layout.prop(gs, "use_auto_start")
-class INFO_MT_render(bpy.types.Menu):
+class INFO_MT_render(Menu):
bl_label = "Render"
def draw(self, context):
@@ -341,7 +351,7 @@ class INFO_MT_render(bpy.types.Menu):
layout.operator("render.play_rendered_anim")
-class INFO_MT_help(bpy.types.Menu):
+class INFO_MT_help(Menu):
bl_label = "Help"
def draw(self, context):
@@ -350,7 +360,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-259/'
layout.separator()
@@ -377,7 +387,7 @@ class INFO_MT_help(bpy.types.Menu):
# Help operators
-class HELP_OT_operator_cheat_sheet(bpy.types.Operator):
+class HELP_OT_operator_cheat_sheet(Operator):
bl_idname = "help.operator_cheat_sheet"
bl_label = "Operator Cheat Sheet"
diff --git a/release/scripts/startup/bl_ui/space_logic.py b/release/scripts/startup/bl_ui/space_logic.py
index 7f7aba71a46..869a91124d3 100644
--- a/release/scripts/startup/bl_ui/space_logic.py
+++ b/release/scripts/startup/bl_ui/space_logic.py
@@ -18,9 +18,10 @@
# <pep8 compliant>
import bpy
+from bpy.types import Header, Menu, Panel
-class LOGIC_PT_properties(bpy.types.Panel):
+class LOGIC_PT_properties(Panel):
bl_space_type = 'LOGIC_EDITOR'
bl_region_type = 'UI'
bl_label = "Properties"
@@ -49,7 +50,7 @@ class LOGIC_PT_properties(bpy.types.Panel):
row.operator("object.game_property_remove", text="", icon='X', emboss=False).index = i
-class LOGIC_MT_logicbricks_add(bpy.types.Menu):
+class LOGIC_MT_logicbricks_add(Menu):
bl_label = "Add"
def draw(self, context):
@@ -60,30 +61,24 @@ class LOGIC_MT_logicbricks_add(bpy.types.Menu):
layout.operator_menu_enum("logic.actuator_add", "type", text="Actuator")
-class LOGIC_HT_header(bpy.types.Header):
+class LOGIC_HT_header(Header):
bl_space_type = 'LOGIC_EDITOR'
def draw(self, context):
- layout = self.layout
+ layout = self.layout.row(align=True)
- row = layout.row(align=True)
- row.template_header()
+ layout.template_header()
if context.area.show_menus:
- sub = row.row(align=True)
- sub.menu("LOGIC_MT_view")
- #sub.menu("LOGIC_MT_select")
- #sub.menu("LOGIC_MT_add")
+ layout.menu("LOGIC_MT_view")
-class LOGIC_MT_view(bpy.types.Menu):
+class LOGIC_MT_view(Menu):
bl_label = "View"
def draw(self, context):
layout = self.layout
- layout.column()
-
layout.operator("logic.properties", icon='MENU_PANEL')
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py
index 717adb3baa8..ffead81c507 100644
--- a/release/scripts/startup/bl_ui/space_nla.py
+++ b/release/scripts/startup/bl_ui/space_nla.py
@@ -19,9 +19,10 @@
# <pep8 compliant>
import bpy
+from bpy.types import Header, Menu
-class NLA_HT_header(bpy.types.Header):
+class NLA_HT_header(Header):
bl_space_type = 'NLA_EDITOR'
def draw(self, context):
@@ -35,20 +36,18 @@ class NLA_HT_header(bpy.types.Header):
row.template_header()
if context.area.show_menus:
- sub = row.row(align=True)
-
- sub.menu("NLA_MT_view")
- sub.menu("NLA_MT_select")
- sub.menu("NLA_MT_marker")
- sub.menu("NLA_MT_edit")
- sub.menu("NLA_MT_add")
+ row.menu("NLA_MT_view")
+ row.menu("NLA_MT_select")
+ row.menu("NLA_MT_marker")
+ row.menu("NLA_MT_edit")
+ row.menu("NLA_MT_add")
dopesheet_filter(layout, context)
layout.prop(st, "auto_snap", text="")
-class NLA_MT_view(bpy.types.Menu):
+class NLA_MT_view(Menu):
bl_label = "View"
def draw(self, context):
@@ -56,8 +55,6 @@ class NLA_MT_view(bpy.types.Menu):
st = context.space_data
- layout.column()
-
layout.operator("nla.properties", icon='MENU_PANEL')
layout.separator()
@@ -74,17 +71,20 @@ class NLA_MT_view(bpy.types.Menu):
layout.operator("anim.previewrange_clear")
layout.separator()
+ layout.operator("nla.view_all")
+ layout.operator("nla.view_selected")
+
+ layout.separator()
layout.operator("screen.area_dupli")
layout.operator("screen.screen_full_area")
-class NLA_MT_select(bpy.types.Menu):
+class NLA_MT_select(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
- layout.column()
# This is a bit misleading as the operator's default text is "Select All" while it actually *toggles* All/None
layout.operator("nla.select_all_toggle")
layout.operator("nla.select_all_toggle", text="Invert Selection").invert = True
@@ -98,7 +98,7 @@ class NLA_MT_select(bpy.types.Menu):
layout.operator("nla.select_leftright", text="After Current Frame").mode = 'RIGHT'
-class NLA_MT_marker(bpy.types.Menu):
+class NLA_MT_marker(Menu):
bl_label = "Marker"
def draw(self, context):
@@ -106,7 +106,6 @@ class NLA_MT_marker(bpy.types.Menu):
#layout.operator_context = 'EXEC_REGION_WIN'
- layout.column()
layout.operator("marker.add", "Add Marker")
layout.operator("marker.duplicate", text="Duplicate Marker")
layout.operator("marker.delete", text="Delete Marker")
@@ -117,7 +116,7 @@ class NLA_MT_marker(bpy.types.Menu):
layout.operator("marker.move", text="Grab/Move Marker")
-class NLA_MT_edit(bpy.types.Menu):
+class NLA_MT_edit(Menu):
bl_label = "Edit"
def draw(self, context):
@@ -125,7 +124,6 @@ class NLA_MT_edit(bpy.types.Menu):
scene = context.scene
- layout.column()
layout.menu("NLA_MT_edit_transform", text="Transform")
layout.operator_menu_enum("nla.snap", "type", text="Snap")
@@ -160,15 +158,15 @@ class NLA_MT_edit(bpy.types.Menu):
layout.operator("nla.tweakmode_enter", text="Start Tweaking Strip Actions")
-class NLA_MT_add(bpy.types.Menu):
+class NLA_MT_add(Menu):
bl_label = "Add"
def draw(self, context):
layout = self.layout
- layout.column()
layout.operator("nla.actionclip_add")
layout.operator("nla.transition_add")
+ layout.operator("nla.soundclip_add")
layout.separator()
layout.operator("nla.meta_add")
@@ -179,13 +177,12 @@ class NLA_MT_add(bpy.types.Menu):
layout.operator("nla.tracks_add", text="Add Tracks Above Selected").above_selected = True
-class NLA_MT_edit_transform(bpy.types.Menu):
+class NLA_MT_edit_transform(Menu):
bl_label = "Transform"
def draw(self, context):
layout = self.layout
- layout.column()
layout.operator("transform.translate", text="Grab/Move")
layout.operator("transform.transform", text="Extend").mode = 'TIME_EXTEND'
layout.operator("transform.transform", text="Scale").mode = 'TIME_SCALE'
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index fed1cc49c4c..708017ba749 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -18,42 +18,39 @@
# <pep8 compliant>
import bpy
+from bpy.types import Header, Menu, Panel
-class NODE_HT_header(bpy.types.Header):
+class NODE_HT_header(Header):
bl_space_type = 'NODE_EDITOR'
def draw(self, context):
layout = self.layout
snode = context.space_data
+ snode_id = snode.id
+ id_from = snode.id_from
row = layout.row(align=True)
row.template_header()
if context.area.show_menus:
- sub = row.row(align=True)
- sub.menu("NODE_MT_view")
- sub.menu("NODE_MT_select")
- sub.menu("NODE_MT_add")
- sub.menu("NODE_MT_node")
+ row.menu("NODE_MT_view")
+ row.menu("NODE_MT_select")
+ row.menu("NODE_MT_add")
+ row.menu("NODE_MT_node")
- row = layout.row()
- row.prop(snode, "tree_type", text="", expand=True)
+ layout.prop(snode, "tree_type", text="", expand=True)
if snode.tree_type == 'MATERIAL':
- ob = snode.id_from
- snode_id = snode.id
- if ob:
- layout.template_ID(ob, "active_material", new="material.new")
+ if id_from:
+ layout.template_ID(id_from, "active_material", new="material.new")
if snode_id:
layout.prop(snode_id, "use_nodes")
elif snode.tree_type == 'TEXTURE':
- row.prop(snode, "texture_type", text="", expand=True)
+ layout.prop(snode, "texture_type", text="", expand=True)
- snode_id = snode.id
- id_from = snode.id_from
if id_from:
if snode.texture_type == 'BRUSH':
layout.template_ID(id_from, "texture", new="texture.new")
@@ -63,10 +60,8 @@ class NODE_HT_header(bpy.types.Header):
layout.prop(snode_id, "use_nodes")
elif snode.tree_type == 'COMPOSITING':
- scene = snode.id
-
- layout.prop(scene, "use_nodes")
- layout.prop(scene.render, "use_free_unused_nodes", text="Free Unused")
+ layout.prop(snode_id, "use_nodes")
+ layout.prop(snode_id.render, "use_free_unused_nodes", text="Free Unused")
layout.prop(snode, "show_backdrop")
if snode.show_backdrop:
row = layout.row(align=True)
@@ -78,7 +73,7 @@ class NODE_HT_header(bpy.types.Header):
layout.template_running_jobs()
-class NODE_MT_view(bpy.types.Menu):
+class NODE_MT_view(Menu):
bl_label = "View"
def draw(self, context):
@@ -107,7 +102,7 @@ class NODE_MT_view(bpy.types.Menu):
layout.operator("screen.screen_full_area")
-class NODE_MT_select(bpy.types.Menu):
+class NODE_MT_select(Menu):
bl_label = "Select"
def draw(self, context):
@@ -124,7 +119,7 @@ class NODE_MT_select(bpy.types.Menu):
layout.operator("node.select_same_type_prev")
-class NODE_MT_node(bpy.types.Menu):
+class NODE_MT_node(Menu):
bl_label = "Node"
def draw(self, context):
@@ -138,6 +133,7 @@ class NODE_MT_node(bpy.types.Menu):
layout.operator("node.duplicate_move")
layout.operator("node.delete")
+ layout.operator("node.delete_reconnect")
layout.separator()
layout.operator("node.link_make")
@@ -164,7 +160,7 @@ class NODE_MT_node(bpy.types.Menu):
# Node Backdrop options
-class NODE_PT_properties(bpy.types.Panel):
+class NODE_PT_properties(Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
bl_label = "Backdrop"
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 1f196cbd191..b1e6eaf3245 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -18,9 +18,10 @@
# <pep8 compliant>
import bpy
+from bpy.types import Header, Menu
-class OUTLINER_HT_header(bpy.types.Header):
+class OUTLINER_HT_header(Header):
bl_space_type = 'OUTLINER'
def draw(self, context):
@@ -63,7 +64,7 @@ class OUTLINER_HT_header(bpy.types.Header):
row.label(text="No Keying Set active")
-class OUTLINER_MT_view(bpy.types.Menu):
+class OUTLINER_MT_view(Menu):
bl_label = "View"
def draw(self, context):
@@ -71,14 +72,13 @@ class OUTLINER_MT_view(bpy.types.Menu):
space = context.space_data
- col = layout.column()
if space.display_mode not in {'DATABLOCKS', 'USER_PREFERENCES', 'KEYMAPS'}:
- col.prop(space, "show_restrict_columns")
- col.separator()
- col.operator("outliner.show_active")
+ layout.prop(space, "show_restrict_columns")
+ layout.separator()
+ layout.operator("outliner.show_active")
- col.operator("outliner.show_one_level")
- col.operator("outliner.show_hierarchy")
+ layout.operator("outliner.show_one_level")
+ layout.operator("outliner.show_hierarchy")
layout.separator()
@@ -86,7 +86,7 @@ class OUTLINER_MT_view(bpy.types.Menu):
layout.operator("screen.screen_full_area")
-class OUTLINER_MT_search(bpy.types.Menu):
+class OUTLINER_MT_search(Menu):
bl_label = "Search"
def draw(self, context):
@@ -94,27 +94,23 @@ class OUTLINER_MT_search(bpy.types.Menu):
space = context.space_data
- col = layout.column()
+ layout.prop(space, "use_filter_case_sensitive")
+ layout.prop(space, "use_filter_complete")
- col.prop(space, "use_filter_case_sensitive")
- col.prop(space, "use_filter_complete")
-
-class OUTLINER_MT_edit_datablocks(bpy.types.Menu):
+class OUTLINER_MT_edit_datablocks(Menu):
bl_label = "Edit"
def draw(self, context):
layout = self.layout
- col = layout.column()
-
- col.operator("outliner.keyingset_add_selected")
- col.operator("outliner.keyingset_remove_selected")
+ layout.operator("outliner.keyingset_add_selected")
+ layout.operator("outliner.keyingset_remove_selected")
- col.separator()
+ layout.separator()
- col.operator("outliner.drivers_add_selected")
- col.operator("outliner.drivers_delete_selected")
+ layout.operator("outliner.drivers_add_selected")
+ layout.operator("outliner.drivers_delete_selected")
if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 858c619d3c1..36f606da635 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Header, Menu, Panel
def act_strip(context):
@@ -27,7 +28,7 @@ def act_strip(context):
return None
-class SEQUENCER_HT_header(bpy.types.Header):
+class SEQUENCER_HT_header(Header):
bl_space_type = 'SEQUENCE_EDITOR'
def draw(self, context):
@@ -39,28 +40,28 @@ class SEQUENCER_HT_header(bpy.types.Header):
row.template_header()
if context.area.show_menus:
- sub = row.row(align=True)
- sub.menu("SEQUENCER_MT_view")
+ row.menu("SEQUENCER_MT_view")
- if (st.view_type == 'SEQUENCER') or (st.view_type == 'SEQUENCER_PREVIEW'):
- sub.menu("SEQUENCER_MT_select")
- sub.menu("SEQUENCER_MT_marker")
- sub.menu("SEQUENCER_MT_add")
- sub.menu("SEQUENCER_MT_strip")
+ if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
+ row.menu("SEQUENCER_MT_select")
+ row.menu("SEQUENCER_MT_marker")
+ row.menu("SEQUENCER_MT_add")
+ row.menu("SEQUENCER_MT_strip")
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'):
+ layout.template_running_jobs()
+ elif st.view_type == 'SEQUENCER_PREVIEW':
layout.separator()
layout.operator("sequencer.refresh_all")
layout.prop(st, "display_channel", text="Channel")
@@ -76,7 +77,7 @@ class SEQUENCER_HT_header(bpy.types.Header):
row.prop(ed, "overlay_lock", text="", icon='LOCKED')
-class SEQUENCER_MT_view_toggle(bpy.types.Menu):
+class SEQUENCER_MT_view_toggle(Menu):
bl_label = "View Type"
def draw(self, context):
@@ -87,7 +88,7 @@ class SEQUENCER_MT_view_toggle(bpy.types.Menu):
layout.operator("sequencer.view_toggle").type = 'SEQUENCER_PREVIEW'
-class SEQUENCER_MT_view(bpy.types.Menu):
+class SEQUENCER_MT_view(Menu):
bl_label = "View"
def draw(self, context):
@@ -95,15 +96,13 @@ class SEQUENCER_MT_view(bpy.types.Menu):
st = context.space_data
- layout.column()
-
layout.operator("sequencer.properties", icon='MENU_PANEL')
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
@@ -114,7 +113,11 @@ class SEQUENCER_MT_view(bpy.types.Menu):
layout.operator("sequencer.view_selected")
- layout.prop(st, "show_frames")
+ if st.show_frames:
+ layout.operator("anim.time_toggle", text="Show Seconds")
+ else:
+ layout.operator("anim.time_toggle", text="Show Frames")
+
layout.prop(st, "show_frame_indicator")
if st.display_mode == 'IMAGE':
layout.prop(st, "show_safe_margin")
@@ -129,13 +132,12 @@ class SEQUENCER_MT_view(bpy.types.Menu):
layout.operator("screen.screen_full_area")
-class SEQUENCER_MT_select(bpy.types.Menu):
+class SEQUENCER_MT_select(Menu):
bl_label = "Select"
def draw(self, context):
layout = self.layout
- layout.column()
layout.operator("sequencer.select_active_side", text="Strips to the Left").side = 'LEFT'
layout.operator("sequencer.select_active_side", text="Strips to the Right").side = 'RIGHT'
layout.separator()
@@ -148,7 +150,7 @@ class SEQUENCER_MT_select(bpy.types.Menu):
layout.operator("sequencer.select_inverse")
-class SEQUENCER_MT_marker(bpy.types.Menu):
+class SEQUENCER_MT_marker(Menu):
bl_label = "Marker"
def draw(self, context):
@@ -156,7 +158,6 @@ class SEQUENCER_MT_marker(bpy.types.Menu):
#layout.operator_context = 'EXEC_REGION_WIN'
- layout.column()
layout.operator("marker.add", "Add Marker")
layout.operator("marker.duplicate", text="Duplicate Marker")
layout.operator("marker.delete", text="Delete Marker")
@@ -169,14 +170,26 @@ class SEQUENCER_MT_marker(bpy.types.Menu):
#layout.operator("sequencer.sound_strip_add", text="Transform Markers") # toggle, will be rna - (sseq->flag & SEQ_MARKER_TRANS)
-class SEQUENCER_MT_add(bpy.types.Menu):
+class SEQUENCER_MT_change(Menu):
+ bl_label = "Change"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator_context = 'INVOKE_REGION_WIN'
+
+ layout.operator_menu_enum("sequencer.change_effect_input", "swap")
+ layout.operator_menu_enum("sequencer.change_effect_type", "type")
+ layout.operator("sequencer.change_path", text="Path/Files")
+
+
+class SEQUENCER_MT_add(Menu):
bl_label = "Add"
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
- layout.column()
if len(bpy.data.scenes) > 10:
layout.operator_context = 'INVOKE_DEFAULT'
layout.operator("sequencer.scene_strip_add", text="Scene...")
@@ -190,14 +203,13 @@ class SEQUENCER_MT_add(bpy.types.Menu):
layout.menu("SEQUENCER_MT_add_effect")
-class SEQUENCER_MT_add_effect(bpy.types.Menu):
+class SEQUENCER_MT_add_effect(Menu):
bl_label = "Effect Strip..."
def draw(self, context):
layout = self.layout
layout.operator_context = 'INVOKE_REGION_WIN'
- layout.column()
layout.operator("sequencer.effect_strip_add", text="Add").type = 'ADD'
layout.operator("sequencer.effect_strip_add", text="Subtract").type = 'SUBTRACT'
layout.operator("sequencer.effect_strip_add", text="Alpha Over").type = 'ALPHA_OVER'
@@ -216,7 +228,7 @@ class SEQUENCER_MT_add_effect(bpy.types.Menu):
layout.operator("sequencer.effect_strip_add", text="Adjustment Layer").type = 'ADJUSTMENT'
-class SEQUENCER_MT_strip(bpy.types.Menu):
+class SEQUENCER_MT_strip(Menu):
bl_label = "Strip"
def draw(self, context):
@@ -224,7 +236,6 @@ class SEQUENCER_MT_strip(bpy.types.Menu):
layout.operator_context = 'INVOKE_REGION_WIN'
- layout.column()
layout.operator("transform.transform", text="Grab/Move").mode = 'TRANSLATION'
layout.operator("transform.transform", text="Grab/Extend from frame").mode = 'TIME_EXTEND'
# uiItemO(layout, NULL, 0, "sequencer.strip_snap"); // TODO - add this operator
@@ -233,7 +244,9 @@ class SEQUENCER_MT_strip(bpy.types.Menu):
layout.operator("sequencer.cut", text="Cut (hard) at frame").type = 'HARD'
layout.operator("sequencer.cut", text="Cut (soft) at frame").type = 'SOFT'
layout.operator("sequencer.images_separate")
+ layout.operator("sequencer.offset_clear")
layout.operator("sequencer.deinterlace_selected_movies")
+ layout.operator("sequencer.rebuild_proxy")
layout.separator()
layout.operator("sequencer.duplicate")
@@ -292,6 +305,7 @@ class SEQUENCER_MT_strip(bpy.types.Menu):
layout.separator()
layout.operator("sequencer.swap_data")
+ layout.menu("SEQUENCER_MT_change")
class SequencerButtonsPanel():
@@ -300,7 +314,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,14 +327,14 @@ 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):
return cls.has_preview(context)
-class SEQUENCER_PT_edit(SequencerButtonsPanel, bpy.types.Panel):
+class SEQUENCER_PT_edit(SequencerButtonsPanel, Panel):
bl_label = "Edit Strip"
def draw(self, context):
@@ -374,9 +388,11 @@ class SEQUENCER_PT_edit(SequencerButtonsPanel, bpy.types.Panel):
if elem and elem.orig_width > 0 and elem.orig_height > 0:
col.label(text="Orig Dim: %dx%d" % (elem.orig_width, elem.orig_height))
+ else:
+ col.label(text="Orig Dim: None")
-class SEQUENCER_PT_effect(SequencerButtonsPanel, bpy.types.Panel):
+class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
bl_label = "Effect Strip"
@classmethod
@@ -514,7 +530,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, bpy.types.Panel):
col.prop(strip, "rotation_start", text="Rotation")
-class SEQUENCER_PT_input(SequencerButtonsPanel, bpy.types.Panel):
+class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
bl_label = "Strip Input"
@classmethod
@@ -558,6 +574,9 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, bpy.types.Panel):
col = split.column()
col.prop(elem, "filename", text="") # strip.elements[0] could be a fallback
+ # also accessible from the menu
+ layout.operator("sequencer.change_path")
+
elif seq_type == 'MOVIE':
split = layout.split(percentage=0.2)
col = split.column()
@@ -565,6 +584,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, bpy.types.Panel):
col = split.column()
col.prop(strip, "filepath", text="")
col.prop(strip, "mpeg_preseek", text="MPEG Preseek")
+ col.prop(strip, "streamindex", text="Stream Index")
# TODO, sound???
# end drawing filename
@@ -595,7 +615,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, bpy.types.Panel):
col.prop(strip, "frame_offset_end", text="End")
-class SEQUENCER_PT_sound(SequencerButtonsPanel, bpy.types.Panel):
+class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
bl_label = "Sound"
@classmethod
@@ -627,8 +647,10 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, bpy.types.Panel):
row.prop(strip.sound, "use_memory_cache")
+ layout.prop(strip, "waveform")
layout.prop(strip, "volume")
- layout.prop(strip, "attenuation")
+ layout.prop(strip, "pitch")
+ layout.prop(strip, "pan")
col = layout.column(align=True)
col.label(text="Trim Duration:")
@@ -636,7 +658,7 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, bpy.types.Panel):
col.prop(strip, "animation_offset_end", text="End")
-class SEQUENCER_PT_scene(SequencerButtonsPanel, bpy.types.Panel):
+class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel):
bl_label = "Scene"
@classmethod
@@ -657,14 +679,20 @@ 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):
+class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel):
bl_label = "Filter"
@classmethod
@@ -726,8 +754,8 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, bpy.types.Panel):
col.prop(strip.color_balance, "invert_gain", text="Inverse")
-class SEQUENCER_PT_proxy(SequencerButtonsPanel, bpy.types.Panel):
- bl_label = "Proxy"
+class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel):
+ bl_label = "Proxy / Timecode"
@classmethod
def poll(cls, context):
@@ -753,14 +781,30 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, bpy.types.Panel):
flow = layout.column_flow()
flow.prop(strip, "use_proxy_custom_directory")
flow.prop(strip, "use_proxy_custom_file")
- if strip.proxy: # TODO - need to add this somehow
+ if strip.proxy:
if strip.use_proxy_custom_directory and not strip.use_proxy_custom_file:
flow.prop(strip.proxy, "directory")
if strip.use_proxy_custom_file:
flow.prop(strip.proxy, "filepath")
+ row = layout.row()
+ row.prop(strip.proxy, "build_25")
+ row.prop(strip.proxy, "build_50")
+ row.prop(strip.proxy, "build_75")
+ row.prop(strip.proxy, "build_100")
+
+ col = layout.column()
+ col.label(text="Build JPEG quality")
+ col.prop(strip.proxy, "quality")
+
+ if strip.type == "MOVIE":
+ col = layout.column()
+ col.label(text="Use timecode index:")
+
+ col.prop(strip.proxy, "timecode")
+
-class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, bpy.types.Panel):
+class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel):
bl_label = "Scene Preview/Render"
bl_space_type = 'SEQUENCE_EDITOR'
bl_region_type = 'UI'
@@ -785,7 +829,7 @@ class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, bpy.types.Panel):
'''
-class SEQUENCER_PT_view(SequencerButtonsPanel_Output, bpy.types.Panel):
+class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel):
bl_label = "View Settings"
def draw(self, context):
diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py
index 0fc8d937f66..12e07c19ca1 100644
--- a/release/scripts/startup/bl_ui/space_text.py
+++ b/release/scripts/startup/bl_ui/space_text.py
@@ -16,11 +16,12 @@
#
# ##### END GPL LICENSE BLOCK #####
-# <pep8 compliant>
+# <pep8-80 compliant>
import bpy
+from bpy.types import Header, Menu, Panel
-class TEXT_HT_header(bpy.types.Header):
+class TEXT_HT_header(Header):
bl_space_type = 'TEXT_EDITOR'
def draw(self, context):
@@ -33,19 +34,21 @@ class TEXT_HT_header(bpy.types.Header):
row.template_header()
if context.area.show_menus:
- sub = row.row(align=True)
- sub.menu("TEXT_MT_view")
- sub.menu("TEXT_MT_text")
+ row.menu("TEXT_MT_view")
+ row.menu("TEXT_MT_text")
+
if text:
- sub.menu("TEXT_MT_edit")
- sub.menu("TEXT_MT_format")
+ row.menu("TEXT_MT_edit")
+ row.menu("TEXT_MT_format")
+
+ row.menu("TEXT_MT_templates")
if text and text.is_modified:
- row = layout.row()
- row.alert = True
- row.operator("text.resolve_conflict", text="", icon='HELP')
+ sub = row.row()
+ sub.alert = True
+ sub.operator("text.resolve_conflict", text="", icon='HELP')
- layout.template_ID(st, "text", new="text.new", unlink="text.unlink")
+ row.template_ID(st, "text", new="text.new", unlink="text.unlink")
row = layout.row(align=True)
row.prop(st, "show_line_numbers", text="")
@@ -63,14 +66,16 @@ class TEXT_HT_header(bpy.types.Header):
row = layout.row()
if text.filepath:
if text.is_dirty:
- row.label(text="File: *%s (unsaved)" % text.filepath)
+ row.label(text="File: *%r (unsaved)" % text.filepath)
else:
- row.label(text="File: %s" % text.filepath)
+ row.label(text="File: %r" % text.filepath)
else:
- row.label(text="Text: External" if text.library else "Text: Internal")
+ row.label(text="Text: External"
+ if text.library
+ else "Text: Internal")
-class TEXT_PT_properties(bpy.types.Panel):
+class TEXT_PT_properties(Panel):
bl_space_type = 'TEXT_EDITOR'
bl_region_type = 'UI'
bl_label = "Properties"
@@ -101,7 +106,7 @@ class TEXT_PT_properties(bpy.types.Panel):
col.prop(st, "margin_column")
-class TEXT_PT_find(bpy.types.Panel):
+class TEXT_PT_find(Panel):
bl_space_type = 'TEXT_EDITOR'
bl_region_type = 'UI'
bl_label = "Find"
@@ -135,7 +140,7 @@ class TEXT_PT_find(bpy.types.Panel):
row.prop(st, "use_find_all", text="All")
-class TEXT_MT_view(bpy.types.Menu):
+class TEXT_MT_view(Menu):
bl_label = "View"
def draw(self, context):
@@ -150,11 +155,15 @@ class TEXT_MT_view(bpy.types.Menu):
layout.separator()
- layout.operator("text.move", text="Top of File").type = 'FILE_TOP'
- layout.operator("text.move", text="Bottom of File").type = 'FILE_BOTTOM'
+ layout.operator("text.move",
+ text="Top of File",
+ ).type = 'FILE_TOP'
+ layout.operator("text.move",
+ text="Bottom of File",
+ ).type = 'FILE_BOTTOM'
-class TEXT_MT_text(bpy.types.Menu):
+class TEXT_MT_text(Menu):
bl_label = "Text"
def draw(self, context):
@@ -163,8 +172,9 @@ class TEXT_MT_text(bpy.types.Menu):
st = context.space_data
text = st.text
- layout.column()
+ layout.operator_context = 'EXEC_AREA'
layout.operator("text.new")
+ layout.operator_context = 'INVOKE_AREA'
layout.operator("text.open")
if text:
@@ -180,27 +190,18 @@ class TEXT_MT_text(bpy.types.Menu):
layout.column()
layout.operator("text.run_script")
- #ifdef WITH_PYTHON
- # XXX if(BPY_is_pyconstraint(text))
- # XXX uiMenuItemO(head, 0, "text.refresh_pyconstraints");
- #endif
-
- layout.separator()
-
- layout.menu("TEXT_MT_templates")
-
-class TEXT_MT_templates(bpy.types.Menu):
- '''
- Creates the menu items by scanning scripts/templates
- '''
- bl_label = "Script Templates"
+class TEXT_MT_templates(Menu):
+ bl_label = "Templates"
def draw(self, context):
- self.path_menu(bpy.utils.script_paths("templates"), "text.open", {"internal": True})
+ self.path_menu(bpy.utils.script_paths("templates"),
+ "text.open",
+ {"internal": True},
+ )
-class TEXT_MT_edit_select(bpy.types.Menu):
+class TEXT_MT_edit_select(Menu):
bl_label = "Select"
def draw(self, context):
@@ -210,7 +211,7 @@ class TEXT_MT_edit_select(bpy.types.Menu):
layout.operator("text.select_line")
-class TEXT_MT_edit_markers(bpy.types.Menu):
+class TEXT_MT_edit_markers(Menu):
bl_label = "Markers"
def draw(self, context):
@@ -221,7 +222,7 @@ class TEXT_MT_edit_markers(bpy.types.Menu):
layout.operator("text.previous_marker")
-class TEXT_MT_format(bpy.types.Menu):
+class TEXT_MT_format(Menu):
bl_label = "Format"
def draw(self, context):
@@ -240,17 +241,21 @@ class TEXT_MT_format(bpy.types.Menu):
layout.operator_menu_enum("text.convert_whitespace", "type")
-class TEXT_MT_edit_to3d(bpy.types.Menu):
+class TEXT_MT_edit_to3d(Menu):
bl_label = "Text To 3D Object"
def draw(self, context):
layout = self.layout
- layout.operator("text.to_3d_object", text="One Object").split_lines = False
- layout.operator("text.to_3d_object", text="One Object Per Line").split_lines = True
+ layout.operator("text.to_3d_object",
+ text="One Object",
+ ).split_lines = False
+ layout.operator("text.to_3d_object",
+ text="One Object Per Line",
+ ).split_lines = True
-class TEXT_MT_edit(bpy.types.Menu):
+class TEXT_MT_edit(Menu):
bl_label = "Edit"
@classmethod
@@ -284,7 +289,7 @@ class TEXT_MT_edit(bpy.types.Menu):
layout.menu("TEXT_MT_edit_to3d")
-class TEXT_MT_toolbox(bpy.types.Menu):
+class TEXT_MT_toolbox(Menu):
bl_label = ""
def draw(self, context):
diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py
index 7e62465d1ee..db009fe43c2 100644
--- a/release/scripts/startup/bl_ui/space_time.py
+++ b/release/scripts/startup/bl_ui/space_time.py
@@ -18,9 +18,10 @@
# <pep8 compliant>
import bpy
+from bpy.types import Header, Menu
-class TIME_HT_header(bpy.types.Header):
+class TIME_HT_header(Header):
bl_space_type = 'TIMELINE'
def draw(self, context):
@@ -34,10 +35,9 @@ class TIME_HT_header(bpy.types.Header):
row.template_header()
if context.area.show_menus:
- sub = row.row(align=True)
- sub.menu("TIME_MT_view")
- sub.menu("TIME_MT_frame")
- sub.menu("TIME_MT_playback")
+ row.menu("TIME_MT_view")
+ row.menu("TIME_MT_frame")
+ row.menu("TIME_MT_playback")
layout.prop(scene, "use_preview_range", text="", toggle=True)
@@ -91,7 +91,7 @@ class TIME_HT_header(bpy.types.Header):
row.operator("anim.keyframe_delete", text="", icon='KEY_DEHLT')
-class TIME_MT_view(bpy.types.Menu):
+class TIME_MT_view(Menu):
bl_label = "View"
def draw(self, context):
@@ -116,7 +116,7 @@ class TIME_MT_view(bpy.types.Menu):
layout.operator("marker.camera_bind")
-class TIME_MT_cache(bpy.types.Menu):
+class TIME_MT_cache(Menu):
bl_label = "Cache"
def draw(self, context):
@@ -136,7 +136,7 @@ class TIME_MT_cache(bpy.types.Menu):
col.prop(st, "cache_smoke")
-class TIME_MT_frame(bpy.types.Menu):
+class TIME_MT_frame(Menu):
bl_label = "Frame"
def draw(self, context):
@@ -162,7 +162,7 @@ class TIME_MT_frame(bpy.types.Menu):
sub.menu("TIME_MT_autokey")
-class TIME_MT_playback(bpy.types.Menu):
+class TIME_MT_playback(Menu):
bl_label = "Playback"
def draw(self, context):
@@ -187,7 +187,7 @@ class TIME_MT_playback(bpy.types.Menu):
layout.prop(scene, "use_audio_scrub")
-class TIME_MT_autokey(bpy.types.Menu):
+class TIME_MT_autokey(Menu):
bl_label = "Auto-Keyframing Mode"
def draw(self, context):
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index f018785a925..13edc3471d2 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Header, Menu, Operator, Panel
import os
import addon_utils
@@ -75,7 +76,7 @@ def opengl_lamp_buttons(column, lamp):
col.prop(lamp, "direction", text="")
-class USERPREF_HT_header(bpy.types.Header):
+class USERPREF_HT_header(Header):
bl_space_type = 'USER_PREFERENCES'
def draw(self, context):
@@ -94,12 +95,12 @@ 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")
-class USERPREF_PT_tabs(bpy.types.Panel):
+class USERPREF_PT_tabs(Panel):
bl_label = ""
bl_space_type = 'USER_PREFERENCES'
bl_region_type = 'WINDOW'
@@ -113,26 +114,26 @@ class USERPREF_PT_tabs(bpy.types.Panel):
layout.prop(userpref, "active_section", expand=True)
-class USERPREF_MT_interaction_presets(bpy.types.Menu):
+class USERPREF_MT_interaction_presets(Menu):
bl_label = "Presets"
preset_subdir = "interaction"
preset_operator = "script.execute_preset"
- draw = bpy.types.Menu.draw_preset
+ draw = Menu.draw_preset
-class USERPREF_MT_appconfigs(bpy.types.Menu):
+class USERPREF_MT_appconfigs(Menu):
bl_label = "AppPresets"
preset_subdir = "keyconfig"
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)
+ Menu.draw_preset(self, context)
-class USERPREF_MT_splash(bpy.types.Menu):
+class USERPREF_MT_splash(Menu):
bl_label = "Splash"
def draw(self, context):
@@ -149,7 +150,7 @@ class USERPREF_MT_splash(bpy.types.Menu):
row.menu("USERPREF_MT_appconfigs", text="Preset")
-class USERPREF_PT_interface(bpy.types.Panel):
+class USERPREF_PT_interface(Panel):
bl_space_type = 'USER_PREFERENCES'
bl_label = "Interface"
bl_region_type = 'WINDOW'
@@ -246,7 +247,7 @@ class USERPREF_PT_interface(bpy.types.Panel):
col.prop(view, "show_splash")
-class USERPREF_PT_edit(bpy.types.Panel):
+class USERPREF_PT_edit(Panel):
bl_space_type = 'USER_PREFERENCES'
bl_label = "Edit"
bl_region_type = 'WINDOW'
@@ -359,7 +360,7 @@ class USERPREF_PT_edit(bpy.types.Panel):
col.prop(edit, "use_duplicate_particle", text="Particle")
-class USERPREF_PT_system(bpy.types.Panel):
+class USERPREF_PT_system(Panel):
bl_space_type = 'USER_PREFERENCES'
bl_label = "System"
bl_region_type = 'WINDOW'
@@ -438,6 +439,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")
@@ -494,7 +497,7 @@ class USERPREF_PT_system(bpy.types.Panel):
sub.template_color_ramp(system, "weight_color_range", expand=True)
-class USERPREF_PT_theme(bpy.types.Panel):
+class USERPREF_PT_theme(Panel):
bl_space_type = 'USER_PREFERENCES'
bl_label = "Themes"
bl_region_type = 'WINDOW'
@@ -677,7 +680,7 @@ class USERPREF_PT_theme(bpy.types.Panel):
self._theme_generic(split, getattr(theme, theme.theme_area.lower()))
-class USERPREF_PT_file(bpy.types.Panel):
+class USERPREF_PT_file(Panel):
bl_space_type = 'USER_PREFERENCES'
bl_label = "Files"
bl_region_type = 'WINDOW'
@@ -753,7 +756,32 @@ class USERPREF_PT_file(bpy.types.Panel):
from bl_ui.space_userpref_keymap import InputKeyMapPanel
-class USERPREF_PT_input(bpy.types.Panel, InputKeyMapPanel):
+class USERPREF_MT_ndof_settings(Menu):
+ # accessed from the window keybindings in C (only)
+ bl_label = "3D Mouse Settings"
+
+ def draw(self, context):
+ layout = self.layout
+ input_prefs = context.user_preferences.inputs
+
+ layout.separator()
+ layout.prop(input_prefs, "ndof_sensitivity")
+
+ if context.space_data.type == 'VIEW_3D':
+ layout.separator()
+ layout.prop(input_prefs, "ndof_show_guide")
+
+ layout.separator()
+ layout.label(text="orbit options")
+ layout.prop(input_prefs, "ndof_orbit_invert_axes")
+
+ layout.separator()
+ layout.label(text="fly options")
+ layout.prop(input_prefs, "ndof_fly_helicopter", icon='NDOF_FLY')
+ layout.prop(input_prefs, "ndof_lock_horizon", icon='NDOF_DOM')
+
+
+class USERPREF_PT_input(Panel, InputKeyMapPanel):
bl_space_type = 'USER_PREFERENCES'
bl_label = "Input"
@@ -815,12 +843,9 @@ class USERPREF_PT_input(bpy.types.Panel, InputKeyMapPanel):
#sub.prop(view, "wheel_scroll_lines", text="Scroll Lines")
col.separator()
- ''' not implemented yet
sub = col.column()
sub.label(text="NDOF Device:")
- sub.prop(inputs, "ndof_pan_speed", text="Pan Speed")
- sub.prop(inputs, "ndof_rotate_speed", text="Orbit Speed")
- '''
+ sub.prop(inputs, "ndof_sensitivity", text="NDOF Sensitivity")
row.separator()
@@ -846,21 +871,18 @@ class USERPREF_PT_input(bpy.types.Panel, InputKeyMapPanel):
#print("runtime", time.time() - start)
-class USERPREF_MT_addons_dev_guides(bpy.types.Menu):
- bl_label = "Addons develoment guides"
+class USERPREF_MT_addons_dev_guides(Menu):
+ 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):
+class USERPREF_PT_addons(Panel):
bl_space_type = 'USER_PREFERENCES'
bl_label = "Addons"
bl_region_type = 'WINDOW'
@@ -877,6 +899,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 +942,27 @@ 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)",
+ )
+
+ if addon_utils.error_encoding:
+ self.draw_error(col,
+ "One or more addons do not have UTF-8 encoding\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,18 +1032,21 @@ class USERPREF_PT_addons(bpy.types.Panel):
split = colsub.row().split(percentage=0.15)
split.label(text="Warning:")
split.label(text=' ' + info["warning"], icon='ERROR')
- if info["wiki_url"] or info["tracker_url"]:
+
+ user_addon = USERPREF_PT_addons.is_user_addon(mod, user_addon_paths)
+ tot_row = bool(info["wiki_url"]) + bool(info["tracker_url"]) + bool(user_addon)
+
+ if tot_row:
split = colsub.row().split(percentage=0.15)
split.label(text="Internet:")
if info["wiki_url"]:
split.operator("wm.url_open", text="Link to the Wiki", icon='HELP').url = info["wiki_url"]
if info["tracker_url"]:
split.operator("wm.url_open", text="Report a Bug", icon='URL').url = info["tracker_url"]
+ if user_addon:
+ split.operator("wm.addon_remove", text="Remove", icon='CANCEL').module = mod.__name__
- if info["wiki_url"] and info["tracker_url"]:
- split.separator()
- else:
- split.separator()
+ for i in range(4 - tot_row):
split.separator()
# Append missing scripts
@@ -1007,54 +1072,84 @@ class USERPREF_PT_addons(bpy.types.Panel):
row.operator("wm.addon_disable", icon='CHECKBOX_HLT', text="", emboss=False).module = module_name
-class WM_OT_addon_enable(bpy.types.Operator):
+class WM_OT_addon_enable(Operator):
"Enable an addon"
bl_idname = "wm.addon_enable"
bl_label = "Enable Add-On"
- module = StringProperty(name="Module", description="Module name of the addon to enable")
+ module = StringProperty(
+ name="Module",
+ description="Module name of the addon to enable",
+ )
def execute(self, context):
mod = addon_utils.enable(self.module)
if mod:
- # check if add-on is written for current blender version, or raise a warning
info = addon_utils.module_bl_info(mod)
- if info.get("blender", (0, 0, 0)) > bpy.app.version:
- self.report("WARNING','This script was written for a newer version of Blender and might not function (correctly).\nThe script is enabled though.")
+ info_ver = info.get("blender", (0, 0, 0))
+
+ if info_ver > bpy.app.version:
+ self.report({'WARNING'}, ("This script was written Blender "
+ "version %d.%d.%d and might not "
+ "function (correctly).\n"
+ "The script is enabled though.") %
+ info_ver)
return {'FINISHED'}
else:
return {'CANCELLED'}
-class WM_OT_addon_disable(bpy.types.Operator):
+class WM_OT_addon_disable(Operator):
"Disable an addon"
bl_idname = "wm.addon_disable"
bl_label = "Disable Add-On"
- module = StringProperty(name="Module", description="Module name of the addon to disable")
+ module = StringProperty(
+ name="Module",
+ description="Module name of the addon to disable",
+ )
def execute(self, context):
addon_utils.disable(self.module)
return {'FINISHED'}
-class WM_OT_addon_install(bpy.types.Operator):
+class WM_OT_addon_install(Operator):
"Install an addon"
bl_idname = "wm.addon_install"
bl_label = "Install Add-On..."
- overwrite = BoolProperty(name="Overwrite", description="Remove existing addons with the same ID", default=True)
+ overwrite = BoolProperty(
+ name="Overwrite",
+ description="Remove existing addons with the same ID",
+ default=True,
+ )
target = EnumProperty(
name="Target Path",
items=(('DEFAULT', "Default", ""),
- ('PREFS', "User Prefs", "")))
-
- filepath = StringProperty(name="File Path", description="File path to write file to")
- filter_folder = BoolProperty(name="Filter folders", description="", default=True, options={'HIDDEN'})
- filter_python = BoolProperty(name="Filter python", description="", default=True, options={'HIDDEN'})
- filter_glob = StringProperty(default="*.py;*.zip", options={'HIDDEN'})
+ ('PREFS', "User Prefs", "")),
+ )
+
+ filepath = StringProperty(
+ name="File Path",
+ description="File path to write file to",
+ )
+ filter_folder = BoolProperty(
+ name="Filter folders",
+ default=True,
+ options={'HIDDEN'},
+ )
+ filter_python = BoolProperty(
+ name="Filter python",
+ default=True,
+ options={'HIDDEN'},
+ )
+ filter_glob = StringProperty(
+ default="*.py;*.zip",
+ options={'HIDDEN'},
+ )
@staticmethod
def _module_remove(path_addons, module):
@@ -1105,7 +1200,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 +1212,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 +1236,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,12 +1281,66 @@ class WM_OT_addon_install(bpy.types.Operator):
return {'RUNNING_MODAL'}
-class WM_OT_addon_expand(bpy.types.Operator):
+class WM_OT_addon_remove(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(Operator):
"Display more information on this add-on"
bl_idname = "wm.addon_expand"
bl_label = ""
- module = StringProperty(name="Module", description="Module name of the addon to expand")
+ module = StringProperty(
+ name="Module",
+ description="Module name of the addon to expand",
+ )
def execute(self, context):
module_name = self.module
diff --git a/release/scripts/startup/bl_ui/space_userpref_keymap.py b/release/scripts/startup/bl_ui/space_userpref_keymap.py
index e99cefb91b8..9ed1591cbf3 100644
--- a/release/scripts/startup/bl_ui/space_userpref_keymap.py
+++ b/release/scripts/startup/bl_ui/space_userpref_keymap.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Menu, Operator, OperatorProperties
import os
@@ -124,7 +125,7 @@ def _merge_keymaps(kc1, kc2):
return merged_keymaps
-class USERPREF_MT_keyconfigs(bpy.types.Menu):
+class USERPREF_MT_keyconfigs(Menu):
bl_label = "KeyPresets"
preset_subdir = "keyconfig"
preset_operator = "wm.keyconfig_activate"
@@ -135,7 +136,7 @@ class USERPREF_MT_keyconfigs(bpy.types.Menu):
props.value = "context.window_manager.keyconfigs.default"
# now draw the presets
- bpy.types.Menu.draw_preset(self, context)
+ Menu.draw_preset(self, context)
class InputKeyMapPanel:
@@ -188,10 +189,10 @@ class InputKeyMapPanel:
if km.is_modal:
row.label(text="", icon='LINKED')
- if km.is_user_defined:
- op = row.operator("wm.keymap_restore", text="Restore")
+ if km.is_user_modified:
+ row.operator("wm.keymap_restore", text="Restore")
else:
- op = row.operator("wm.keymap_edit", text="Edit")
+ row.label()
if km.show_expanded_children:
if children:
@@ -212,8 +213,7 @@ class InputKeyMapPanel:
# "Add New" at end of keymap item list
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()
@@ -233,8 +233,8 @@ class InputKeyMapPanel:
flow = box.column_flow(columns=2)
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)
+ if isinstance(value, OperatorProperties):
+ InputKeyMapPanel.draw_kmi_properties(box, value, title=pname)
else:
flow.prop(properties, pname)
@@ -243,7 +243,7 @@ class InputKeyMapPanel:
col = self.indented_layout(layout, level)
- if km.is_user_defined:
+ if kmi.show_expanded:
col = col.column(align=True)
box = col.box()
else:
@@ -256,7 +256,6 @@ class InputKeyMapPanel:
row.prop(kmi, "show_expanded", text="", emboss=False)
row = split.row()
- row.enabled = km.is_user_defined
row.prop(kmi, "active", text="", emboss=False)
if km.is_modal:
@@ -265,12 +264,13 @@ class InputKeyMapPanel:
row.label(text=kmi.name)
row = split.row()
- row.enabled = km.is_user_defined
row.prop(kmi, "map_type", text="")
if map_type == 'KEYBOARD':
row.prop(kmi, "type", text="", full_event=True)
elif map_type == 'MOUSE':
row.prop(kmi, "type", text="", full_event=True)
+ elif map_type == 'NDOF':
+ row.prop(kmi, "type", text="", full_event=True)
elif map_type == 'TWEAK':
subrow = row.row()
subrow.prop(kmi, "type", text="")
@@ -280,18 +280,17 @@ class InputKeyMapPanel:
else:
row.label()
- if not kmi.is_user_defined:
+ if (not kmi.is_user_defined) and kmi.is_user_modified:
op = row.operator("wm.keyitem_restore", text="", icon='BACK')
op.item_id = kmi.id
- op = row.operator("wm.keyitem_remove", text="", icon='X')
- op.item_id = kmi.id
+ else:
+ op = row.operator("wm.keyitem_remove", text="", icon='X')
+ op.item_id = kmi.id
# Expanded, additional event settings
if kmi.show_expanded:
box = col.box()
- box.enabled = km.is_user_defined
-
if map_type not in {'TEXTINPUT', 'TIMER'}:
split = box.split(percentage=0.4)
sub = split.row()
@@ -306,7 +305,7 @@ class InputKeyMapPanel:
sub = split.column()
subrow = sub.row(align=True)
- if map_type == 'KEYBOARD':
+ if map_type in {'KEYBOARD', 'NDOF'}:
subrow.prop(kmi, "type", text="", event=True)
subrow.prop(kmi, "value", text="")
elif map_type == 'MOUSE':
@@ -325,7 +324,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:
@@ -350,10 +349,10 @@ class InputKeyMapPanel:
row.label()
row.label()
- if km.is_user_defined:
- op = row.operator("wm.keymap_restore", text="Restore")
+ if km.is_user_modified:
+ row.operator("wm.keymap_restore", text="Restore")
else:
- op = row.operator("wm.keymap_edit", text="Edit")
+ row.label()
for kmi in filtered_items:
self.draw_kmi(display_keymaps, kc, km, kmi, col, 1)
@@ -361,8 +360,7 @@ class InputKeyMapPanel:
# "Add New" at end of keymap item list
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:
@@ -370,8 +368,7 @@ class InputKeyMapPanel:
def draw_keymaps(self, context, layout):
wm = context.window_manager
- kc = wm.keyconfigs.active
- defkc = wm.keyconfigs.default
+ kc = wm.keyconfigs.user
col = layout.column()
sub = col.column()
@@ -396,7 +393,7 @@ class InputKeyMapPanel:
col.separator()
- display_keymaps = _merge_keymaps(kc, defkc)
+ display_keymaps = _merge_keymaps(kc, kc)
if context.space_data.filter_text != "":
filter_text = context.space_data.filter_text.lower()
self.draw_filtered(display_keymaps, filter_text, col)
@@ -414,7 +411,7 @@ def export_properties(prefix, properties, lines=None):
for pname in properties.bl_rna.properties.keys():
if pname != "rna_type" and not properties.is_property_hidden(pname):
value = getattr(properties, pname)
- if isinstance(value, bpy.types.OperatorProperties):
+ if isinstance(value, OperatorProperties):
export_properties(prefix + "." + pname, value, lines)
elif properties.is_property_set(pname):
value = _string_value(value)
@@ -423,7 +420,7 @@ def export_properties(prefix, properties, lines=None):
return lines
-class WM_OT_keyconfig_test(bpy.types.Operator):
+class WM_OT_keyconfig_test(Operator):
"Test keyconfig for conflicts"
bl_idname = "wm.keyconfig_test"
bl_label = "Test Key Configuration for Conflicts"
@@ -531,37 +528,58 @@ def _string_value(value):
return result
-class WM_OT_keyconfig_import(bpy.types.Operator):
+class WM_OT_keyconfig_import(Operator):
"Import key configuration from a python script"
bl_idname = "wm.keyconfig_import"
bl_label = "Import Key Configuration..."
- filepath = StringProperty(name="File Path", description="Filepath to write file to", default="keymap.py")
- filter_folder = BoolProperty(name="Filter folders", description="", default=True, options={'HIDDEN'})
- filter_text = BoolProperty(name="Filter text", description="", default=True, options={'HIDDEN'})
- filter_python = BoolProperty(name="Filter python", description="", default=True, options={'HIDDEN'})
-
- keep_original = BoolProperty(name="Keep original", description="Keep original file after copying to configuration folder", default=True)
+ filepath = StringProperty(
+ name="File Path",
+ description="Filepath to write file to",
+ default="keymap.py",
+ )
+ filter_folder = BoolProperty(
+ name="Filter folders",
+ default=True,
+ options={'HIDDEN'},
+ )
+ filter_text = BoolProperty(
+ name="Filter text",
+ default=True,
+ options={'HIDDEN'},
+ )
+ filter_python = BoolProperty(
+ name="Filter python",
+ default=True,
+ options={'HIDDEN'},
+ )
+ keep_original = BoolProperty(
+ name="Keep original",
+ description="Keep original file after copying to configuration folder",
+ default=True,
+ )
def execute(self, context):
from os.path import basename
import shutil
- if not self.filepath:
- raise Exception("Filepath not set")
- f = open(self.filepath, "r")
- if not f:
- raise Exception("Could not open file")
+ if not self.filepath:
+ self.report({'ERROR'}, "Filepath not set")
+ return {'CANCELLED'}
config_name = basename(self.filepath)
path = bpy.utils.user_resource('SCRIPTS', os.path.join("presets", "keyconfig"), create=True)
path = os.path.join(path, config_name)
- if self.keep_original:
- shutil.copy(self.filepath, path)
- else:
- shutil.move(self.filepath, path)
+ try:
+ if self.keep_original:
+ shutil.copy(self.filepath, path)
+ else:
+ shutil.move(self.filepath, path)
+ except Exception as e:
+ self.report({'ERROR'}, "Installing keymap failed: %s" % e)
+ return {'CANCELLED'}
# sneaky way to check we're actually running the code.
bpy.utils.keyconfig_set(path)
@@ -576,20 +594,39 @@ class WM_OT_keyconfig_import(bpy.types.Operator):
# This operator is also used by interaction presets saving - AddPresetBase
-class WM_OT_keyconfig_export(bpy.types.Operator):
+class WM_OT_keyconfig_export(Operator):
"Export key configuration to a python script"
bl_idname = "wm.keyconfig_export"
bl_label = "Export Key Configuration..."
- filepath = StringProperty(name="File Path", description="Filepath to write file to", default="keymap.py")
- filter_folder = BoolProperty(name="Filter folders", description="", default=True, options={'HIDDEN'})
- filter_text = BoolProperty(name="Filter text", description="", default=True, options={'HIDDEN'})
- filter_python = BoolProperty(name="Filter python", description="", default=True, options={'HIDDEN'})
+ filepath = StringProperty(
+ name="File Path",
+ description="Filepath to write file to",
+ default="keymap.py",
+ )
+ filter_folder = BoolProperty(
+ name="Filter folders",
+ default=True,
+ options={'HIDDEN'},
+ )
+ filter_text = BoolProperty(
+ name="Filter text",
+ default=True,
+ options={'HIDDEN'},
+ )
+ filter_python = BoolProperty(
+ name="Filter python",
+ default=True,
+ options={'HIDDEN'},
+ )
def execute(self, context):
if not self.filepath:
raise Exception("Filepath not set")
+ if not self.filepath.endswith('.py'):
+ self.filepath += '.py'
+
f = open(self.filepath, "w")
if not f:
raise Exception("Could not open file")
@@ -604,7 +641,7 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
# Generate a list of keymaps to export:
#
- # First add all user_defined keymaps (found in inputs.edited_keymaps list),
+ # First add all user_modified keymaps (found in keyconfigs.user.keymaps list),
# then add all remaining keymaps from the currently active custom keyconfig.
#
# This will create a final list of keymaps that can be used as a 'diff' against
@@ -614,7 +651,9 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
class FakeKeyConfig():
keymaps = []
edited_kc = FakeKeyConfig()
- edited_kc.keymaps.extend(context.user_preferences.inputs.edited_keymaps)
+ for km in wm.keyconfigs.user.keymaps:
+ if km.is_user_modified:
+ edited_kc.keymaps.append(km)
# merge edited keymaps with non-default keyconfig, if it exists
if kc != wm.keyconfigs.default:
export_keymaps = _merge_keymaps(edited_kc, kc)
@@ -664,29 +703,21 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
return {'RUNNING_MODAL'}
-class WM_OT_keymap_edit(bpy.types.Operator):
- "Edit stored key map"
- bl_idname = "wm.keymap_edit"
- bl_label = "Edit Key Map"
-
- def execute(self, context):
- km = context.keymap
- km.copy_to_user()
- return {'FINISHED'}
-
-
-class WM_OT_keymap_restore(bpy.types.Operator):
+class WM_OT_keymap_restore(Operator):
"Restore key map(s)"
bl_idname = "wm.keymap_restore"
bl_label = "Restore Key Map(s)"
- all = BoolProperty(name="All Keymaps", description="Restore all keymaps to default")
+ all = BoolProperty(
+ name="All Keymaps",
+ description="Restore all keymaps to default",
+ )
def execute(self, context):
wm = context.window_manager
if self.all:
- for km in wm.keyconfigs.default.keymaps:
+ for km in wm.keyconfigs.user.keymaps:
km.restore_to_default()
else:
km = context.keymap
@@ -695,37 +726,38 @@ class WM_OT_keymap_restore(bpy.types.Operator):
return {'FINISHED'}
-class WM_OT_keyitem_restore(bpy.types.Operator):
+class WM_OT_keyitem_restore(Operator):
"Restore key map item"
bl_idname = "wm.keyitem_restore"
bl_label = "Restore Key Map Item"
- item_id = IntProperty(name="Item Identifier", description="Identifier of the item to remove")
+ item_id = IntProperty(
+ name="Item Identifier",
+ description="Identifier of the item to remove",
+ )
@classmethod
def poll(cls, context):
keymap = getattr(context, "keymap", None)
- return keymap and keymap.is_user_defined
+ return keymap
def execute(self, context):
km = context.keymap
kmi = km.keymap_items.from_id(self.item_id)
- if not kmi.is_user_defined:
+ if (not kmi.is_user_defined) and kmi.is_user_modified:
km.restore_item_to_default(kmi)
return {'FINISHED'}
-class WM_OT_keyitem_add(bpy.types.Operator):
+class WM_OT_keyitem_add(Operator):
"Add key map item"
bl_idname = "wm.keyitem_add"
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
@@ -741,16 +773,19 @@ class WM_OT_keyitem_add(bpy.types.Operator):
return {'FINISHED'}
-class WM_OT_keyitem_remove(bpy.types.Operator):
+class WM_OT_keyitem_remove(Operator):
"Remove key map item"
bl_idname = "wm.keyitem_remove"
bl_label = "Remove Key Map Item"
- item_id = IntProperty(name="Item Identifier", description="Identifier of the item to remove")
+ item_id = IntProperty(
+ name="Item Identifier",
+ description="Identifier of the item to remove",
+ )
@classmethod
def poll(cls, context):
- return hasattr(context, "keymap") and context.keymap.is_user_defined
+ return hasattr(context, "keymap")
def execute(self, context):
km = context.keymap
@@ -759,7 +794,7 @@ class WM_OT_keyitem_remove(bpy.types.Operator):
return {'FINISHED'}
-class WM_OT_keyconfig_remove(bpy.types.Operator):
+class WM_OT_keyconfig_remove(Operator):
"Remove key config"
bl_idname = "wm.keyconfig_remove"
bl_label = "Remove Key Config"
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 02004283264..9f96df1eb66 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -18,9 +18,10 @@
# <pep8 compliant>
import bpy
+from bpy.types import Header, Menu, Operator, Panel
-class VIEW3D_HT_header(bpy.types.Header):
+class VIEW3D_HT_header(Header):
bl_space_type = 'VIEW_3D'
def draw(self, context):
@@ -54,21 +55,13 @@ class VIEW3D_HT_header(bpy.types.Header):
sub.menu("VIEW3D_MT_object")
row = layout.row()
+ # Contains buttons like Mode, Pivot, Manipulator, Layer, Mesh Select Mode...
row.template_header_3D()
- # do in C for now since these buttons cant be both toggle AND exclusive.
- '''
- if obj and obj.mode == 'EDIT' and obj.type == 'MESH':
- row_sub = row.row(align=True)
- row_sub.prop(toolsettings, "mesh_select_mode", text="", index=0, icon='VERTEXSEL')
- row_sub.prop(toolsettings, "mesh_select_mode", text="", index=1, icon='EDGESEL')
- row_sub.prop(toolsettings, "mesh_select_mode", text="", index=2, icon='FACESEL')
- '''
-
if obj:
# Particle edit
if obj.mode == 'PARTICLE_EDIT':
- row.prop(toolsettings.particle_edit, "select_mode", text="", expand=True, toggle=True)
+ row.prop(toolsettings.particle_edit, "select_mode", text="", expand=True)
# Occlude geometry
if view.viewport_shade in {'SOLID', 'SHADED', 'TEXTURED'} and (obj.mode == 'PARTICLE_EDIT' or (obj.mode == 'EDIT' and obj.type == 'MESH')):
@@ -87,16 +80,21 @@ class VIEW3D_HT_header(bpy.types.Header):
row.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True)
# Snap
+ snap_element = toolsettings.snap_element
row = layout.row(align=True)
row.prop(toolsettings, "use_snap", text="")
row.prop(toolsettings, "snap_element", text="", icon_only=True)
- if toolsettings.snap_element != 'INCREMENT':
+ if snap_element != 'INCREMENT':
row.prop(toolsettings, "snap_target", text="")
- if obj and obj.mode == 'OBJECT':
- row.prop(toolsettings, "use_snap_align_rotation", text="")
- if toolsettings.snap_element == 'VOLUME':
+ if obj:
+ if obj.mode == 'OBJECT':
+ row.prop(toolsettings, "use_snap_align_rotation", text="")
+ elif obj.mode == 'EDIT':
+ row.prop(toolsettings, "use_snap_self", text="")
+
+ if snap_element == 'VOLUME':
row.prop(toolsettings, "use_snap_peel_object", text="")
- elif toolsettings.snap_element == 'FACE':
+ elif snap_element == 'FACE':
row.prop(toolsettings, "use_snap_project", text="")
# OpenGL render
@@ -131,7 +129,7 @@ class ShowHideMenu():
layout.operator("%s.hide" % self._operator_name, text="Hide Unselected").unselected = True
-class VIEW3D_MT_transform(bpy.types.Menu):
+class VIEW3D_MT_transform(Menu):
bl_label = "Transform"
# TODO: get rid of the custom text strings?
@@ -182,8 +180,12 @@ class VIEW3D_MT_transform(bpy.types.Menu):
layout.operator("object.randomize_transform")
layout.operator("object.align")
+ layout.separator()
+
+ layout.operator("object.anim_transforms_to_deltas")
-class VIEW3D_MT_mirror(bpy.types.Menu):
+
+class VIEW3D_MT_mirror(Menu):
bl_label = "Mirror"
def draw(self, context):
@@ -221,7 +223,7 @@ class VIEW3D_MT_mirror(bpy.types.Menu):
layout.operator("object.vertex_group_mirror")
-class VIEW3D_MT_snap(bpy.types.Menu):
+class VIEW3D_MT_snap(Menu):
bl_label = "Snap"
def draw(self, context):
@@ -238,7 +240,7 @@ class VIEW3D_MT_snap(bpy.types.Menu):
layout.operator("view3d.snap_cursor_to_active", text="Cursor to Active")
-class VIEW3D_MT_uv_map(bpy.types.Menu):
+class VIEW3D_MT_uv_map(Menu):
bl_label = "UV Mapping"
def draw(self, context):
@@ -271,7 +273,7 @@ class VIEW3D_MT_uv_map(bpy.types.Menu):
# ********** View menus **********
-class VIEW3D_MT_view(bpy.types.Menu):
+class VIEW3D_MT_view(Menu):
bl_label = "View"
def draw(self, context):
@@ -329,7 +331,7 @@ class VIEW3D_MT_view(bpy.types.Menu):
layout.operator("screen.screen_full_area")
-class VIEW3D_MT_view_navigation(bpy.types.Menu):
+class VIEW3D_MT_view_navigation(Menu):
bl_label = "Navigation"
def draw(self, context):
@@ -352,7 +354,7 @@ class VIEW3D_MT_view_navigation(bpy.types.Menu):
layout.operator("view3d.fly")
-class VIEW3D_MT_view_align(bpy.types.Menu):
+class VIEW3D_MT_view_align(Menu):
bl_label = "Align View"
def draw(self, context):
@@ -368,7 +370,7 @@ class VIEW3D_MT_view_align(bpy.types.Menu):
layout.operator("view3d.view_center_cursor")
-class VIEW3D_MT_view_align_selected(bpy.types.Menu):
+class VIEW3D_MT_view_align_selected(Menu):
bl_label = "Align View to Selected"
def draw(self, context):
@@ -394,7 +396,7 @@ class VIEW3D_MT_view_align_selected(bpy.types.Menu):
props.type = 'LEFT'
-class VIEW3D_MT_view_cameras(bpy.types.Menu):
+class VIEW3D_MT_view_cameras(Menu):
bl_label = "Cameras"
def draw(self, context):
@@ -406,7 +408,7 @@ class VIEW3D_MT_view_cameras(bpy.types.Menu):
# ********** Select menus, suffix from context.mode **********
-class VIEW3D_MT_select_object(bpy.types.Menu):
+class VIEW3D_MT_select_object(Menu):
bl_label = "Select"
def draw(self, context):
@@ -432,7 +434,7 @@ class VIEW3D_MT_select_object(bpy.types.Menu):
layout.operator("object.select_pattern", text="Select Pattern...")
-class VIEW3D_MT_select_pose(bpy.types.Menu):
+class VIEW3D_MT_select_pose(Menu):
bl_label = "Select"
def draw(self, context):
@@ -469,7 +471,7 @@ class VIEW3D_MT_select_pose(bpy.types.Menu):
layout.operator("object.select_pattern", text="Select Pattern...")
-class VIEW3D_MT_select_particle(bpy.types.Menu):
+class VIEW3D_MT_select_particle(Menu):
bl_label = "Select"
def draw(self, context):
@@ -494,7 +496,7 @@ class VIEW3D_MT_select_particle(bpy.types.Menu):
layout.operator("particle.select_tips", text="Tips")
-class VIEW3D_MT_select_edit_mesh(bpy.types.Menu):
+class VIEW3D_MT_select_edit_mesh(Menu):
bl_label = "Select"
def draw(self, context):
@@ -546,7 +548,7 @@ class VIEW3D_MT_select_edit_mesh(bpy.types.Menu):
layout.operator("mesh.region_to_loop")
-class VIEW3D_MT_select_edit_curve(bpy.types.Menu):
+class VIEW3D_MT_select_edit_curve(Menu):
bl_label = "Select"
def draw(self, context):
@@ -575,7 +577,7 @@ class VIEW3D_MT_select_edit_curve(bpy.types.Menu):
layout.operator("curve.select_less")
-class VIEW3D_MT_select_edit_surface(bpy.types.Menu):
+class VIEW3D_MT_select_edit_surface(Menu):
bl_label = "Select"
def draw(self, context):
@@ -601,7 +603,7 @@ class VIEW3D_MT_select_edit_surface(bpy.types.Menu):
layout.operator("curve.select_less")
-class VIEW3D_MT_select_edit_metaball(bpy.types.Menu):
+class VIEW3D_MT_select_edit_metaball(Menu):
bl_label = "Select"
def draw(self, context):
@@ -619,7 +621,7 @@ class VIEW3D_MT_select_edit_metaball(bpy.types.Menu):
layout.operator("mball.select_random_metaelems")
-class VIEW3D_MT_select_edit_lattice(bpy.types.Menu):
+class VIEW3D_MT_select_edit_lattice(Menu):
bl_label = "Select"
def draw(self, context):
@@ -632,7 +634,7 @@ class VIEW3D_MT_select_edit_lattice(bpy.types.Menu):
layout.operator("lattice.select_all", text="Select/Deselect All")
-class VIEW3D_MT_select_edit_armature(bpy.types.Menu):
+class VIEW3D_MT_select_edit_armature(Menu):
bl_label = "Select"
def draw(self, context):
@@ -663,7 +665,7 @@ class VIEW3D_MT_select_edit_armature(bpy.types.Menu):
layout.operator("object.select_pattern", text="Select Pattern...")
-class VIEW3D_MT_select_face(bpy.types.Menu): # XXX no matching enum
+class VIEW3D_MT_select_face(Menu): # XXX no matching enum
bl_label = "Select"
def draw(self, context):
@@ -676,7 +678,7 @@ class VIEW3D_MT_select_face(bpy.types.Menu): # XXX no matching enum
# ********** Object menu **********
-class VIEW3D_MT_object(bpy.types.Menu):
+class VIEW3D_MT_object(Menu):
bl_context = "objectmode"
bl_label = "Object"
@@ -734,7 +736,7 @@ class VIEW3D_MT_object(bpy.types.Menu):
layout.operator_menu_enum("object.convert", "target")
-class VIEW3D_MT_object_animation(bpy.types.Menu):
+class VIEW3D_MT_object_animation(Menu):
bl_label = "Animation"
def draw(self, context):
@@ -745,7 +747,7 @@ class VIEW3D_MT_object_animation(bpy.types.Menu):
layout.operator("anim.keying_set_active_set", text="Change Keying Set...")
-class VIEW3D_MT_object_clear(bpy.types.Menu):
+class VIEW3D_MT_object_clear(Menu):
bl_label = "Clear"
def draw(self, context):
@@ -757,7 +759,7 @@ class VIEW3D_MT_object_clear(bpy.types.Menu):
layout.operator("object.origin_clear", text="Origin")
-class VIEW3D_MT_object_specials(bpy.types.Menu):
+class VIEW3D_MT_object_specials(Menu):
bl_label = "Specials"
@classmethod
@@ -772,10 +774,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");
@@ -846,7 +854,7 @@ class VIEW3D_MT_object_specials(bpy.types.Menu):
props = layout.operator("object.hide_render_clear_all")
-class VIEW3D_MT_object_apply(bpy.types.Menu):
+class VIEW3D_MT_object_apply(Menu):
bl_label = "Apply"
def draw(self, context):
@@ -865,7 +873,7 @@ class VIEW3D_MT_object_apply(bpy.types.Menu):
layout.operator("object.duplicates_make_real")
-class VIEW3D_MT_object_parent(bpy.types.Menu):
+class VIEW3D_MT_object_parent(Menu):
bl_label = "Parent"
def draw(self, context):
@@ -875,7 +883,7 @@ class VIEW3D_MT_object_parent(bpy.types.Menu):
layout.operator("object.parent_clear", text="Clear")
-class VIEW3D_MT_object_track(bpy.types.Menu):
+class VIEW3D_MT_object_track(Menu):
bl_label = "Track"
def draw(self, context):
@@ -885,7 +893,7 @@ class VIEW3D_MT_object_track(bpy.types.Menu):
layout.operator("object.track_clear", text="Clear")
-class VIEW3D_MT_object_group(bpy.types.Menu):
+class VIEW3D_MT_object_group(Menu):
bl_label = "Group"
def draw(self, context):
@@ -900,7 +908,7 @@ class VIEW3D_MT_object_group(bpy.types.Menu):
layout.operator("group.objects_remove_active")
-class VIEW3D_MT_object_constraints(bpy.types.Menu):
+class VIEW3D_MT_object_constraints(Menu):
bl_label = "Constraints"
def draw(self, context):
@@ -911,7 +919,7 @@ class VIEW3D_MT_object_constraints(bpy.types.Menu):
layout.operator("object.constraints_clear")
-class VIEW3D_MT_object_showhide(bpy.types.Menu):
+class VIEW3D_MT_object_showhide(Menu):
bl_label = "Show/Hide"
def draw(self, context):
@@ -922,7 +930,7 @@ class VIEW3D_MT_object_showhide(bpy.types.Menu):
layout.operator("object.hide_view_set", text="Hide Unselected").unselected = True
-class VIEW3D_MT_make_single_user(bpy.types.Menu):
+class VIEW3D_MT_make_single_user(Menu):
bl_label = "Make Single User"
def draw(self, context):
@@ -944,7 +952,7 @@ class VIEW3D_MT_make_single_user(bpy.types.Menu):
props.animation = True
-class VIEW3D_MT_make_links(bpy.types.Menu):
+class VIEW3D_MT_make_links(Menu):
bl_label = "Make Links"
def draw(self, context):
@@ -961,7 +969,7 @@ class VIEW3D_MT_make_links(bpy.types.Menu):
layout.operator_enum("object.make_links_data", "type") # inline
-class VIEW3D_MT_object_game(bpy.types.Menu):
+class VIEW3D_MT_object_game(Menu):
bl_label = "Game"
def draw(self, context):
@@ -983,7 +991,7 @@ class VIEW3D_MT_object_game(bpy.types.Menu):
# ********** Vertex paint menu **********
-class VIEW3D_MT_paint_vertex(bpy.types.Menu):
+class VIEW3D_MT_paint_vertex(Menu):
bl_label = "Paint"
def draw(self, context):
@@ -998,7 +1006,7 @@ class VIEW3D_MT_paint_vertex(bpy.types.Menu):
layout.operator("paint.vertex_color_dirt")
-class VIEW3D_MT_hook(bpy.types.Menu):
+class VIEW3D_MT_hook(Menu):
bl_label = "Hooks"
def draw(self, context):
@@ -1017,7 +1025,7 @@ class VIEW3D_MT_hook(bpy.types.Menu):
layout.operator_menu_enum("object.hook_recenter", "modifier")
-class VIEW3D_MT_vertex_group(bpy.types.Menu):
+class VIEW3D_MT_vertex_group(Menu):
bl_label = "Vertex Groups"
def draw(self, context):
@@ -1042,7 +1050,7 @@ class VIEW3D_MT_vertex_group(bpy.types.Menu):
# ********** Weight paint menu **********
-class VIEW3D_MT_paint_weight(bpy.types.Menu):
+class VIEW3D_MT_paint_weight(Menu):
bl_label = "Weights"
def draw(self, context):
@@ -1072,7 +1080,7 @@ class VIEW3D_MT_paint_weight(bpy.types.Menu):
# ********** Sculpt menu **********
-class VIEW3D_MT_sculpt(bpy.types.Menu):
+class VIEW3D_MT_sculpt(Menu):
bl_label = "Sculpt"
def draw(self, context):
@@ -1098,17 +1106,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")
@@ -1121,7 +1130,7 @@ class VIEW3D_MT_sculpt(bpy.types.Menu):
# ********** Particle menu **********
-class VIEW3D_MT_particle(bpy.types.Menu):
+class VIEW3D_MT_particle(Menu):
bl_label = "Particle"
def draw(self, context):
@@ -1153,7 +1162,7 @@ class VIEW3D_MT_particle(bpy.types.Menu):
layout.menu("VIEW3D_MT_particle_showhide")
-class VIEW3D_MT_particle_specials(bpy.types.Menu):
+class VIEW3D_MT_particle_specials(Menu):
bl_label = "Specials"
def draw(self, context):
@@ -1171,13 +1180,13 @@ class VIEW3D_MT_particle_specials(bpy.types.Menu):
layout.operator("particle.remove_doubles")
-class VIEW3D_MT_particle_showhide(ShowHideMenu, bpy.types.Menu):
+class VIEW3D_MT_particle_showhide(ShowHideMenu, Menu):
_operator_name = "particle"
# ********** Pose Menu **********
-class VIEW3D_MT_pose(bpy.types.Menu):
+class VIEW3D_MT_pose(Menu):
bl_label = "Pose"
def draw(self, context):
@@ -1243,10 +1252,10 @@ 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):
+class VIEW3D_MT_pose_transform(Menu):
bl_label = "Clear Transform"
def draw(self, context):
@@ -1254,14 +1263,18 @@ class VIEW3D_MT_pose_transform(bpy.types.Menu):
layout.operator("pose.transforms_clear", text="All")
+ layout.separator()
+
layout.operator("pose.loc_clear", text="Location")
layout.operator("pose.rot_clear", text="Rotation")
layout.operator("pose.scale_clear", text="Scale")
- layout.label(text="Origin")
+ layout.separator()
+
+ layout.operator("pose.user_transforms_clear", text="Reset unkeyed")
-class VIEW3D_MT_pose_slide(bpy.types.Menu):
+class VIEW3D_MT_pose_slide(Menu):
bl_label = "In-Betweens"
def draw(self, context):
@@ -1272,7 +1285,7 @@ class VIEW3D_MT_pose_slide(bpy.types.Menu):
layout.operator("pose.breakdown")
-class VIEW3D_MT_pose_propagate(bpy.types.Menu):
+class VIEW3D_MT_pose_propagate(Menu):
bl_label = "Propagate"
def draw(self, context):
@@ -1290,7 +1303,7 @@ class VIEW3D_MT_pose_propagate(bpy.types.Menu):
layout.operator("pose.propagate", text="On Selected Markers").mode = 'SELECTED_MARKERS'
-class VIEW3D_MT_pose_library(bpy.types.Menu):
+class VIEW3D_MT_pose_library(Menu):
bl_label = "Pose Library"
def draw(self, context):
@@ -1305,7 +1318,7 @@ class VIEW3D_MT_pose_library(bpy.types.Menu):
layout.operator("poselib.pose_remove", text="Remove Pose...")
-class VIEW3D_MT_pose_motion(bpy.types.Menu):
+class VIEW3D_MT_pose_motion(Menu):
bl_label = "Motion Paths"
def draw(self, context):
@@ -1315,7 +1328,7 @@ class VIEW3D_MT_pose_motion(bpy.types.Menu):
layout.operator("pose.paths_clear", text="Clear")
-class VIEW3D_MT_pose_group(bpy.types.Menu):
+class VIEW3D_MT_pose_group(Menu):
bl_label = "Bone Groups"
def draw(self, context):
@@ -1329,7 +1342,7 @@ class VIEW3D_MT_pose_group(bpy.types.Menu):
layout.operator("pose.group_unassign")
-class VIEW3D_MT_pose_ik(bpy.types.Menu):
+class VIEW3D_MT_pose_ik(Menu):
bl_label = "Inverse Kinematics"
def draw(self, context):
@@ -1339,7 +1352,7 @@ class VIEW3D_MT_pose_ik(bpy.types.Menu):
layout.operator("pose.ik_clear")
-class VIEW3D_MT_pose_constraints(bpy.types.Menu):
+class VIEW3D_MT_pose_constraints(Menu):
bl_label = "Constraints"
def draw(self, context):
@@ -1350,11 +1363,11 @@ class VIEW3D_MT_pose_constraints(bpy.types.Menu):
layout.operator("pose.constraints_clear")
-class VIEW3D_MT_pose_showhide(ShowHideMenu, bpy.types.Menu):
+class VIEW3D_MT_pose_showhide(ShowHideMenu, Menu):
_operator_name = "pose"
-class VIEW3D_MT_pose_apply(bpy.types.Menu):
+class VIEW3D_MT_pose_apply(Menu):
bl_label = "Apply"
def draw(self, context):
@@ -1364,10 +1377,53 @@ 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(Menu, BoneOptions):
+ bl_label = "Toggle Bone Options"
+ type = 'TOGGLE'
+
+
+class VIEW3D_MT_bone_options_enable(Menu, BoneOptions):
+ bl_label = "Enable Bone Options"
+ type = 'ENABLE'
+
+
+class VIEW3D_MT_bone_options_disable(Menu, BoneOptions):
+ bl_label = "Disable Bone Options"
+ type = 'DISABLE'
+
# ********** Edit Menus, suffix from ob.type **********
-class VIEW3D_MT_edit_mesh(bpy.types.Menu):
+class VIEW3D_MT_edit_mesh(Menu):
bl_label = "Mesh"
def draw(self, context):
@@ -1414,7 +1470,7 @@ class VIEW3D_MT_edit_mesh(bpy.types.Menu):
layout.menu("VIEW3D_MT_edit_mesh_showhide")
-class VIEW3D_MT_edit_mesh_specials(bpy.types.Menu):
+class VIEW3D_MT_edit_mesh_specials(Menu):
bl_label = "Specials"
def draw(self, context):
@@ -1439,7 +1495,7 @@ class VIEW3D_MT_edit_mesh_specials(bpy.types.Menu):
layout.operator("mesh.select_vertex_path")
-class VIEW3D_MT_edit_mesh_select_mode(bpy.types.Menu):
+class VIEW3D_MT_edit_mesh_select_mode(Menu):
bl_label = "Mesh Select Mode"
def draw(self, context):
@@ -1460,7 +1516,7 @@ class VIEW3D_MT_edit_mesh_select_mode(bpy.types.Menu):
prop.data_path = "tool_settings.mesh_select_mode"
-class VIEW3D_MT_edit_mesh_extrude(bpy.types.Menu):
+class VIEW3D_MT_edit_mesh_extrude(Menu):
bl_label = "Extrude"
_extrude_funcs = { \
@@ -1494,7 +1550,7 @@ class VIEW3D_MT_edit_mesh_extrude(bpy.types.Menu):
self._extrude_funcs[menu_id](layout)
-class VIEW3D_OT_edit_mesh_extrude_individual_move(bpy.types.Operator):
+class VIEW3D_OT_edit_mesh_extrude_individual_move(Operator):
"Extrude individual elements and move"
bl_label = "Extrude Individual and Move"
bl_idname = "view3d.edit_mesh_extrude_individual_move"
@@ -1523,7 +1579,7 @@ class VIEW3D_OT_edit_mesh_extrude_individual_move(bpy.types.Operator):
return self.execute(context)
-class VIEW3D_OT_edit_mesh_extrude_move(bpy.types.Operator):
+class VIEW3D_OT_edit_mesh_extrude_move(Operator):
"Extrude and move along normals"
bl_label = "Extrude and Move on Normals"
bl_idname = "view3d.edit_mesh_extrude_move_normal"
@@ -1549,7 +1605,7 @@ class VIEW3D_OT_edit_mesh_extrude_move(bpy.types.Operator):
return self.execute(context)
-class VIEW3D_MT_edit_mesh_vertices(bpy.types.Menu):
+class VIEW3D_MT_edit_mesh_vertices(Menu):
bl_label = "Vertices"
def draw(self, context):
@@ -1581,7 +1637,7 @@ class VIEW3D_MT_edit_mesh_vertices(bpy.types.Menu):
layout.menu("VIEW3D_MT_hook")
-class VIEW3D_MT_edit_mesh_edges(bpy.types.Menu):
+class VIEW3D_MT_edit_mesh_edges(Menu):
bl_label = "Edges"
def draw(self, context):
@@ -1621,7 +1677,7 @@ class VIEW3D_MT_edit_mesh_edges(bpy.types.Menu):
layout.operator("mesh.region_to_loop")
-class VIEW3D_MT_edit_mesh_faces(bpy.types.Menu):
+class VIEW3D_MT_edit_mesh_faces(Menu):
bl_label = "Faces"
bl_idname = "VIEW3D_MT_edit_mesh_faces"
@@ -1669,7 +1725,7 @@ class VIEW3D_MT_edit_mesh_faces(bpy.types.Menu):
layout.operator_menu_enum("mesh.colors_mirror", "axis")
-class VIEW3D_MT_edit_mesh_normals(bpy.types.Menu):
+class VIEW3D_MT_edit_mesh_normals(Menu):
bl_label = "Normals"
def draw(self, context):
@@ -1683,7 +1739,7 @@ class VIEW3D_MT_edit_mesh_normals(bpy.types.Menu):
layout.operator("mesh.flip_normals")
-class VIEW3D_MT_edit_mesh_showhide(ShowHideMenu, bpy.types.Menu):
+class VIEW3D_MT_edit_mesh_showhide(ShowHideMenu, Menu):
_operator_name = "mesh"
# Edit Curve
@@ -1723,13 +1779,13 @@ def draw_curve(self, context):
layout.menu("VIEW3D_MT_edit_curve_showhide")
-class VIEW3D_MT_edit_curve(bpy.types.Menu):
+class VIEW3D_MT_edit_curve(Menu):
bl_label = "Curve"
draw = draw_curve
-class VIEW3D_MT_edit_curve_ctrlpoints(bpy.types.Menu):
+class VIEW3D_MT_edit_curve_ctrlpoints(Menu):
bl_label = "Control Points"
def draw(self, context):
@@ -1751,7 +1807,7 @@ class VIEW3D_MT_edit_curve_ctrlpoints(bpy.types.Menu):
layout.menu("VIEW3D_MT_hook")
-class VIEW3D_MT_edit_curve_segments(bpy.types.Menu):
+class VIEW3D_MT_edit_curve_segments(Menu):
bl_label = "Segments"
def draw(self, context):
@@ -1761,7 +1817,7 @@ class VIEW3D_MT_edit_curve_segments(bpy.types.Menu):
layout.operator("curve.switch_direction")
-class VIEW3D_MT_edit_curve_specials(bpy.types.Menu):
+class VIEW3D_MT_edit_curve_specials(Menu):
bl_label = "Specials"
def draw(self, context):
@@ -1775,17 +1831,17 @@ class VIEW3D_MT_edit_curve_specials(bpy.types.Menu):
layout.operator("curve.smooth_radius")
-class VIEW3D_MT_edit_curve_showhide(ShowHideMenu, bpy.types.Menu):
+class VIEW3D_MT_edit_curve_showhide(ShowHideMenu, Menu):
_operator_name = "curve"
-class VIEW3D_MT_edit_surface(bpy.types.Menu):
+class VIEW3D_MT_edit_surface(Menu):
bl_label = "Surface"
draw = draw_curve
-class VIEW3D_MT_edit_font(bpy.types.Menu):
+class VIEW3D_MT_edit_font(Menu):
bl_label = "Text"
def draw(self, context):
@@ -1805,7 +1861,7 @@ class VIEW3D_MT_edit_font(bpy.types.Menu):
layout.operator("font.style_toggle", text="Toggle Small Caps").style = 'SMALL_CAPS'
-class VIEW3D_MT_edit_text_chars(bpy.types.Menu):
+class VIEW3D_MT_edit_text_chars(Menu):
bl_label = "Special Characters"
def draw(self, context):
@@ -1839,7 +1895,7 @@ class VIEW3D_MT_edit_text_chars(bpy.types.Menu):
layout.operator("font.text_insert", text="Spanish Exclamation Mark|Alt !").text = b'\xC2\xA1'.decode()
-class VIEW3D_MT_edit_meta(bpy.types.Menu):
+class VIEW3D_MT_edit_meta(Menu):
bl_label = "Metaball"
def draw(self, context):
@@ -1872,7 +1928,7 @@ class VIEW3D_MT_edit_meta(bpy.types.Menu):
layout.menu("VIEW3D_MT_edit_meta_showhide")
-class VIEW3D_MT_edit_meta_showhide(bpy.types.Menu):
+class VIEW3D_MT_edit_meta_showhide(Menu):
bl_label = "Show/Hide"
def draw(self, context):
@@ -1883,7 +1939,7 @@ class VIEW3D_MT_edit_meta_showhide(bpy.types.Menu):
layout.operator("mball.hide_metaelems", text="Hide Unselected").unselected = True
-class VIEW3D_MT_edit_lattice(bpy.types.Menu):
+class VIEW3D_MT_edit_lattice(Menu):
bl_label = "Lattice"
def draw(self, context):
@@ -1905,7 +1961,7 @@ class VIEW3D_MT_edit_lattice(bpy.types.Menu):
layout.prop_menu_enum(settings, "proportional_edit_falloff")
-class VIEW3D_MT_edit_armature(bpy.types.Menu):
+class VIEW3D_MT_edit_armature(Menu):
bl_label = "Armature"
def draw(self, context):
@@ -1957,10 +2013,10 @@ 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):
+class VIEW3D_MT_armature_specials(Menu):
bl_label = "Specials"
def draw(self, context):
@@ -1980,7 +2036,7 @@ class VIEW3D_MT_armature_specials(bpy.types.Menu):
layout.operator("armature.flip_names", text="Flip Names")
-class VIEW3D_MT_edit_armature_parent(bpy.types.Menu):
+class VIEW3D_MT_edit_armature_parent(Menu):
bl_label = "Parent"
def draw(self, context):
@@ -1990,7 +2046,7 @@ class VIEW3D_MT_edit_armature_parent(bpy.types.Menu):
layout.operator("armature.parent_clear", text="Clear")
-class VIEW3D_MT_edit_armature_roll(bpy.types.Menu):
+class VIEW3D_MT_edit_armature_roll(Menu):
bl_label = "Bone Roll"
def draw(self, context):
@@ -2005,7 +2061,7 @@ class VIEW3D_MT_edit_armature_roll(bpy.types.Menu):
# ********** Panel **********
-class VIEW3D_PT_view3d_properties(bpy.types.Panel):
+class VIEW3D_PT_view3d_properties(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "View"
@@ -2025,9 +2081,11 @@ class VIEW3D_PT_view3d_properties(bpy.types.Panel):
col.prop(view, "lens")
col.label(text="Lock to Object:")
col.prop(view, "lock_object", text="")
- if view.lock_object and view.lock_object.type == 'ARMATURE':
- col.prop_search(view, "lock_bone", view.lock_object.data, "bones", text="")
- elif not view.lock_object:
+ lock_object = view.lock_object
+ if lock_object:
+ if lock_object.type == 'ARMATURE':
+ col.prop_search(view, "lock_bone", lock_object.data, "edit_bones" if lock_object.mode == 'EDIT' else "bones", text="")
+ else:
col.prop(view, "lock_cursor", text="Lock to Cursor")
col = layout.column()
@@ -2046,7 +2104,7 @@ class VIEW3D_PT_view3d_properties(bpy.types.Panel):
layout.column().prop(view, "cursor_location")
-class VIEW3D_PT_view3d_name(bpy.types.Panel):
+class VIEW3D_PT_view3d_name(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "Item"
@@ -2071,7 +2129,7 @@ class VIEW3D_PT_view3d_name(bpy.types.Panel):
row.prop(bone, "name", text="")
-class VIEW3D_PT_view3d_display(bpy.types.Panel):
+class VIEW3D_PT_view3d_display(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "Display"
@@ -2143,7 +2201,7 @@ class VIEW3D_PT_view3d_display(bpy.types.Panel):
row.prop(region, "use_box_clip")
-class VIEW3D_PT_view3d_meshdisplay(bpy.types.Panel):
+class VIEW3D_PT_view3d_meshdisplay(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "Mesh Display"
@@ -2180,7 +2238,7 @@ class VIEW3D_PT_view3d_meshdisplay(bpy.types.Panel):
col.prop(mesh, "show_extra_face_area")
-class VIEW3D_PT_view3d_curvedisplay(bpy.types.Panel):
+class VIEW3D_PT_view3d_curvedisplay(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "Curve Display"
@@ -2202,7 +2260,7 @@ class VIEW3D_PT_view3d_curvedisplay(bpy.types.Panel):
col.prop(context.scene.tool_settings, "normal_size", text="Normal Size")
-class VIEW3D_PT_background_image(bpy.types.Panel):
+class VIEW3D_PT_background_image(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "Background Images"
@@ -2255,7 +2313,7 @@ class VIEW3D_PT_background_image(bpy.types.Panel):
row.prop(bg, "offset_y", text="Y")
-class VIEW3D_PT_transform_orientations(bpy.types.Panel):
+class VIEW3D_PT_transform_orientations(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "Transform Orientations"
@@ -2283,7 +2341,7 @@ class VIEW3D_PT_transform_orientations(bpy.types.Panel):
col.operator("transform.delete_orientation", text="Delete")
-class VIEW3D_PT_etch_a_ton(bpy.types.Panel):
+class VIEW3D_PT_etch_a_ton(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "Skeleton Sketching"
@@ -2328,7 +2386,7 @@ class VIEW3D_PT_etch_a_ton(bpy.types.Panel):
col.operator("sketch.convert", text="Convert")
-class VIEW3D_PT_context_properties(bpy.types.Panel):
+class VIEW3D_PT_context_properties(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
bl_label = "Properties"
@@ -2358,7 +2416,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..aa26cb43eed 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -18,6 +18,7 @@
# <pep8 compliant>
import bpy
+from bpy.types import Menu, Panel
class View3DPanel():
@@ -53,15 +54,18 @@ def draw_gpencil_tools(context, layout):
row = col.row()
row.operator("gpencil.draw", text="Draw").mode = 'DRAW'
row.operator("gpencil.draw", text="Line").mode = 'DRAW_STRAIGHT'
+
+ row = col.row()
+ row.operator("gpencil.draw", text="Poly").mode = 'DRAW_POLY'
row.operator("gpencil.draw", text="Erase").mode = 'ERASER'
row = col.row()
row.prop(context.tool_settings, "use_grease_pencil_sessions")
-# ********** default tools for objectmode ****************
+# ********** default tools for objectmode ****************
-class VIEW3D_PT_tools_objectmode(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_objectmode(View3DPanel, Panel):
bl_context = "objectmode"
bl_label = "Object Tools"
@@ -88,8 +92,9 @@ class VIEW3D_PT_tools_objectmode(View3DPanel, bpy.types.Panel):
col = layout.column(align=True)
col.label(text="Shading:")
- col.operator("object.shade_smooth", text="Smooth")
- col.operator("object.shade_flat", text="Flat")
+ row = col.row(align=True)
+ row.operator("object.shade_smooth", text="Smooth")
+ row.operator("object.shade_flat", text="Flat")
draw_keyframing_tools(context, layout)
@@ -105,7 +110,7 @@ class VIEW3D_PT_tools_objectmode(View3DPanel, bpy.types.Panel):
# ********** default tools for editmode_mesh ****************
-class VIEW3D_PT_tools_meshedit(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_meshedit(View3DPanel, Panel):
bl_context = "mesh_edit"
bl_label = "Mesh Tools"
@@ -117,7 +122,8 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, bpy.types.Panel):
col.operator("transform.translate")
col.operator("transform.rotate")
col.operator("transform.resize", text="Scale")
- col.operator("transform.shrink_fatten", text="Along Normal")
+ col.operator("transform.shrink_fatten", text="Shrink/Fatten")
+ col.operator("transform.push_pull", text="Push/Pull")
col = layout.column(align=True)
col.label(text="Deform:")
@@ -154,15 +160,16 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, bpy.types.Panel):
col = layout.column(align=True)
col.label(text="Shading:")
- col.operator("mesh.faces_shade_smooth", text="Smooth")
- col.operator("mesh.faces_shade_flat", text="Flat")
+ row = col.row(align=True)
+ row.operator("mesh.faces_shade_smooth", text="Smooth")
+ row.operator("mesh.faces_shade_flat", text="Flat")
draw_repeat_tools(context, layout)
draw_gpencil_tools(context, layout)
-class VIEW3D_PT_tools_meshedit_options(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel):
bl_context = "mesh_edit"
bl_label = "Mesh Options"
@@ -188,7 +195,7 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, bpy.types.Panel):
# ********** default tools for editmode_curve ****************
-class VIEW3D_PT_tools_curveedit(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_curveedit(View3DPanel, Panel):
bl_context = "curve_edit"
bl_label = "Curve Tools"
@@ -234,7 +241,7 @@ class VIEW3D_PT_tools_curveedit(View3DPanel, bpy.types.Panel):
# ********** default tools for editmode_surface ****************
-class VIEW3D_PT_tools_surfaceedit(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_surfaceedit(View3DPanel, Panel):
bl_context = "surface_edit"
bl_label = "Surface Tools"
@@ -266,7 +273,7 @@ class VIEW3D_PT_tools_surfaceedit(View3DPanel, bpy.types.Panel):
# ********** default tools for editmode_text ****************
-class VIEW3D_PT_tools_textedit(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_textedit(View3DPanel, Panel):
bl_context = "text_edit"
bl_label = "Text Tools"
@@ -296,7 +303,7 @@ class VIEW3D_PT_tools_textedit(View3DPanel, bpy.types.Panel):
# ********** default tools for editmode_armature ****************
-class VIEW3D_PT_tools_armatureedit(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_armatureedit(View3DPanel, Panel):
bl_context = "armature_edit"
bl_label = "Armature Tools"
@@ -325,7 +332,7 @@ class VIEW3D_PT_tools_armatureedit(View3DPanel, bpy.types.Panel):
draw_gpencil_tools(context, layout)
-class VIEW3D_PT_tools_armatureedit_options(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_armatureedit_options(View3DPanel, Panel):
bl_context = "armature_edit"
bl_label = "Armature Options"
@@ -337,7 +344,7 @@ class VIEW3D_PT_tools_armatureedit_options(View3DPanel, bpy.types.Panel):
# ********** default tools for editmode_mball ****************
-class VIEW3D_PT_tools_mballedit(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_mballedit(View3DPanel, Panel):
bl_context = "mball_edit"
bl_label = "Meta Tools"
@@ -357,7 +364,7 @@ class VIEW3D_PT_tools_mballedit(View3DPanel, bpy.types.Panel):
# ********** default tools for editmode_lattice ****************
-class VIEW3D_PT_tools_latticeedit(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_latticeedit(View3DPanel, Panel):
bl_context = "lattice_edit"
bl_label = "Lattice Tools"
@@ -381,7 +388,7 @@ class VIEW3D_PT_tools_latticeedit(View3DPanel, bpy.types.Panel):
# ********** default tools for posemode ****************
-class VIEW3D_PT_tools_posemode(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_posemode(View3DPanel, Panel):
bl_context = "posemode"
bl_label = "Pose Tools"
@@ -422,7 +429,7 @@ class VIEW3D_PT_tools_posemode(View3DPanel, bpy.types.Panel):
draw_gpencil_tools(context, layout)
-class VIEW3D_PT_tools_posemode_options(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_posemode_options(View3DPanel, Panel):
bl_context = "posemode"
bl_label = "Pose Options"
@@ -456,7 +463,7 @@ class PaintPanel():
return None
-class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_brush(PaintPanel, Panel):
bl_label = "Brush"
@classmethod
@@ -466,7 +473,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:
@@ -674,7 +681,7 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
#row.prop(brush, "use_pressure_jitter", toggle=True, text="")
-class VIEW3D_PT_tools_brush_texture(PaintPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_brush_texture(PaintPanel, Panel):
bl_label = "Texture"
bl_options = {'DEFAULT_CLOSED'}
@@ -687,7 +694,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
@@ -772,7 +779,7 @@ class VIEW3D_PT_tools_brush_texture(PaintPanel, bpy.types.Panel):
col.active = tex_slot.map_mode in {'FIXED', 'TILED'} and brush.use_texture_overlay
-class VIEW3D_PT_tools_brush_tool(PaintPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_brush_tool(PaintPanel, Panel):
bl_label = "Tool"
bl_options = {'DEFAULT_CLOSED'}
@@ -786,7 +793,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)
@@ -806,7 +813,7 @@ class VIEW3D_PT_tools_brush_tool(PaintPanel, bpy.types.Panel):
row.prop(brush, "use_paint_image", text="", icon='TPAINT_HLT')
-class VIEW3D_PT_tools_brush_stroke(PaintPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_brush_stroke(PaintPanel, Panel):
bl_label = "Stroke"
bl_options = {'DEFAULT_CLOSED'}
@@ -821,7 +828,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
@@ -904,7 +911,7 @@ class VIEW3D_PT_tools_brush_stroke(PaintPanel, bpy.types.Panel):
# row.prop(brush, "use_pressure_spacing", toggle=True, text="")
-class VIEW3D_PT_tools_brush_curve(PaintPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_brush_curve(PaintPanel, Panel):
bl_label = "Curve"
bl_options = {'DEFAULT_CLOSED'}
@@ -931,7 +938,7 @@ class VIEW3D_PT_tools_brush_curve(PaintPanel, bpy.types.Panel):
row.operator("brush.curve_preset", icon="NOCURVE", text="").shape = 'MAX'
-class VIEW3D_PT_sculpt_options(PaintPanel, bpy.types.Panel):
+class VIEW3D_PT_sculpt_options(PaintPanel, Panel):
bl_label = "Options"
bl_options = {'DEFAULT_CLOSED'}
@@ -944,7 +951,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)
@@ -962,7 +968,7 @@ class VIEW3D_PT_sculpt_options(PaintPanel, bpy.types.Panel):
layout.prop(tool_settings, "sculpt_paint_use_unified_strength", text="Strength")
-class VIEW3D_PT_sculpt_symmetry(PaintPanel, bpy.types.Panel):
+class VIEW3D_PT_sculpt_symmetry(PaintPanel, Panel):
bl_label = "Symmetry"
bl_options = {'DEFAULT_CLOSED'}
@@ -974,7 +980,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()
@@ -991,20 +996,28 @@ class VIEW3D_PT_sculpt_symmetry(PaintPanel, bpy.types.Panel):
layout.prop(sculpt, "use_symmetry_feather", text="Feather")
-class VIEW3D_PT_tools_brush_appearance(PaintPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_brush_appearance(PaintPanel, Panel):
bl_label = "Appearance"
bl_options = {'DEFAULT_CLOSED'}
@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:
@@ -1029,7 +1042,7 @@ class VIEW3D_PT_tools_brush_appearance(PaintPanel, bpy.types.Panel):
# ********** default tools for weightpaint ****************
-class VIEW3D_PT_tools_weightpaint(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel):
bl_context = "weightpaint"
bl_label = "Weight Tools"
@@ -1039,7 +1052,7 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, bpy.types.Panel):
ob = context.active_object
col = layout.column()
- col.active = ob.vertex_groups.active != None
+ col.active = ob.vertex_groups.active is not None
col.operator("object.vertex_group_normalize_all", text="Normalize All")
col.operator("object.vertex_group_normalize", text="Normalize")
col.operator("object.vertex_group_invert", text="Invert")
@@ -1047,7 +1060,7 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, bpy.types.Panel):
col.operator("object.vertex_group_levels", text="Levels")
-class VIEW3D_PT_tools_weightpaint_options(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_weightpaint_options(View3DPanel, Panel):
bl_context = "weightpaint"
bl_label = "Options"
@@ -1084,7 +1097,7 @@ class VIEW3D_PT_tools_weightpaint_options(View3DPanel, bpy.types.Panel):
# ********** default tools for vertexpaint ****************
-class VIEW3D_PT_tools_vertexpaint(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_vertexpaint(View3DPanel, Panel):
bl_context = "vertexpaint"
bl_label = "Options"
@@ -1113,7 +1126,7 @@ class VIEW3D_PT_tools_vertexpaint(View3DPanel, bpy.types.Panel):
# ********** default tools for texturepaint ****************
-class VIEW3D_PT_tools_projectpaint(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
bl_context = "imagepaint"
bl_label = "Project Paint"
@@ -1205,7 +1218,7 @@ class VIEW3D_PT_imagepaint_options(PaintPanel):
col.prop(tool_settings, "sculpt_paint_use_unified_strength", text="Strength")
-class VIEW3D_MT_tools_projectpaint_clone(bpy.types.Menu):
+class VIEW3D_MT_tools_projectpaint_clone(Menu):
bl_label = "Clone Layer"
def draw(self, context):
@@ -1216,7 +1229,7 @@ class VIEW3D_MT_tools_projectpaint_clone(bpy.types.Menu):
prop.value = i
-class VIEW3D_MT_tools_projectpaint_stencil(bpy.types.Menu):
+class VIEW3D_MT_tools_projectpaint_stencil(Menu):
bl_label = "Mask Layer"
def draw(self, context):
@@ -1227,7 +1240,7 @@ class VIEW3D_MT_tools_projectpaint_stencil(bpy.types.Menu):
prop.value = i
-class VIEW3D_PT_tools_particlemode(View3DPanel, bpy.types.Panel):
+class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
'''default tools for particle mode'''
bl_context = "particlemode"
bl_label = "Options"
diff --git a/release/scripts/startup/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py
index 8cb63ea48cf..6b12c95e072 100644
--- a/release/scripts/startup/keyingsets_builtins.py
+++ b/release/scripts/startup/keyingsets_builtins.py
@@ -32,13 +32,14 @@ in lost (i.e. unkeyed) animation.
import bpy
import keyingsets_utils
+from bpy.types import KeyingSetInfo
###############################
# Built-In KeyingSets
# Location
-class BUILTIN_KSI_Location(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_Location(KeyingSetInfo):
bl_label = "Location"
# poll - use predefined callback for selected bones/objects
@@ -52,7 +53,7 @@ class BUILTIN_KSI_Location(bpy.types.KeyingSetInfo):
# Rotation
-class BUILTIN_KSI_Rotation(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_Rotation(KeyingSetInfo):
bl_label = "Rotation"
# poll - use predefined callback for selected bones/objects
@@ -66,7 +67,7 @@ class BUILTIN_KSI_Rotation(bpy.types.KeyingSetInfo):
# Scale
-class BUILTIN_KSI_Scaling(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_Scaling(KeyingSetInfo):
bl_label = "Scaling"
# poll - use predefined callback for selected bones/objects
@@ -82,7 +83,7 @@ class BUILTIN_KSI_Scaling(bpy.types.KeyingSetInfo):
# LocRot
-class BUILTIN_KSI_LocRot(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_LocRot(KeyingSetInfo):
bl_label = "LocRot"
# poll - use predefined callback for selected bones/objects
@@ -100,7 +101,7 @@ class BUILTIN_KSI_LocRot(bpy.types.KeyingSetInfo):
# LocScale
-class BUILTIN_KSI_LocScale(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_LocScale(KeyingSetInfo):
bl_label = "LocScale"
# poll - use predefined callback for selected bones/objects
@@ -118,7 +119,7 @@ class BUILTIN_KSI_LocScale(bpy.types.KeyingSetInfo):
# LocRotScale
-class BUILTIN_KSI_LocRotScale(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_LocRotScale(KeyingSetInfo):
bl_label = "LocRotScale"
# poll - use predefined callback for selected bones/objects
@@ -138,7 +139,7 @@ class BUILTIN_KSI_LocRotScale(bpy.types.KeyingSetInfo):
# RotScale
-class BUILTIN_KSI_RotScale(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_RotScale(KeyingSetInfo):
bl_label = "RotScale"
# poll - use predefined callback for selected bones/objects
@@ -158,7 +159,7 @@ class BUILTIN_KSI_RotScale(bpy.types.KeyingSetInfo):
# Location
-class BUILTIN_KSI_VisualLoc(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_VisualLoc(KeyingSetInfo):
bl_label = "Visual Location"
bl_options = {'INSERTKEY_VISUAL'}
@@ -174,7 +175,7 @@ class BUILTIN_KSI_VisualLoc(bpy.types.KeyingSetInfo):
# Rotation
-class BUILTIN_KSI_VisualRot(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_VisualRot(KeyingSetInfo):
bl_label = "Visual Rotation"
bl_options = {'INSERTKEY_VISUAL'}
@@ -190,7 +191,7 @@ class BUILTIN_KSI_VisualRot(bpy.types.KeyingSetInfo):
# VisualLocRot
-class BUILTIN_KSI_VisualLocRot(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_VisualLocRot(KeyingSetInfo):
bl_label = "Visual LocRot"
bl_options = {'INSERTKEY_VISUAL'}
@@ -212,7 +213,7 @@ class BUILTIN_KSI_VisualLocRot(bpy.types.KeyingSetInfo):
# Available
-class BUILTIN_KSI_Available(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_Available(KeyingSetInfo):
bl_label = "Available"
# poll - selected objects or selected object with animation data
@@ -234,7 +235,7 @@ class BUILTIN_KSI_Available(bpy.types.KeyingSetInfo):
# All properties that are likely to get animated in a character rig
-class BUILTIN_KSI_WholeCharacter(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_WholeCharacter(KeyingSetInfo):
bl_label = "Whole Character"
# these prefixes should be avoided, as they are not really bones
@@ -265,7 +266,7 @@ class BUILTIN_KSI_WholeCharacter(bpy.types.KeyingSetInfo):
# loc, rot, scale - only include unlocked ones
ksi.doLoc(ks, bone)
- if bone.rotation_mode in ('QUATERNION', 'AXIS_ANGLE'):
+ if bone.rotation_mode in {'QUATERNION', 'AXIS_ANGLE'}:
ksi.doRot4d(ks, bone)
else:
ksi.doRot3d(ks, bone)
@@ -365,7 +366,7 @@ class BUILTIN_KSI_WholeCharacter(bpy.types.KeyingSetInfo):
# Delta Location
-class BUILTIN_KSI_DeltaLocation(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_DeltaLocation(KeyingSetInfo):
bl_label = "Delta Location"
# poll - selected objects only (and only if active object in object mode)
@@ -390,7 +391,7 @@ class BUILTIN_KSI_DeltaLocation(bpy.types.KeyingSetInfo):
# Delta Rotation
-class BUILTIN_KSI_DeltaRotation(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_DeltaRotation(KeyingSetInfo):
bl_label = "Delta Rotation"
# poll - selected objects only (and only if active object in object mode)
@@ -407,7 +408,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")
@@ -423,7 +424,7 @@ class BUILTIN_KSI_DeltaRotation(bpy.types.KeyingSetInfo):
# Delta Scale
-class BUILTIN_KSI_DeltaScale(bpy.types.KeyingSetInfo):
+class BUILTIN_KSI_DeltaScale(KeyingSetInfo):
bl_label = "Delta Scale"
# poll - selected objects only (and only if active object in object mode)
diff --git a/release/scripts/templates/addon_add_object.py b/release/scripts/templates/addon_add_object.py
index 67e033271f4..833ac600995 100644
--- a/release/scripts/templates/addon_add_object.py
+++ b/release/scripts/templates/addon_add_object.py
@@ -35,7 +35,7 @@ def add_object(self, context):
mesh.from_pydata(verts, edges, faces)
# useful for development when the mesh may be invalid.
# mesh.validate(verbose=True)
- add_object_data(context, mesh_data, operator=self)
+ add_object_data(context, mesh, operator=self)
class OBJECT_OT_add_object(bpy.types.Operator, AddObjectHelper):
@@ -45,10 +45,12 @@ class OBJECT_OT_add_object(bpy.types.Operator, AddObjectHelper):
bl_description = "Create a new Mesh Object"
bl_options = {'REGISTER', 'UNDO'}
- scale = FloatVectorProperty(name='scale',
- default=(1.0, 1.0, 1.0),
- subtype='TRANSLATION',
- description='scaling')
+ scale = FloatVectorProperty(
+ name='scale',
+ default=(1.0, 1.0, 1.0),
+ subtype='TRANSLATION',
+ description='scaling',
+ )
def execute(self, context):
diff --git a/release/scripts/templates/batch_export.py b/release/scripts/templates/batch_export.py
new file mode 100644
index 00000000000..45d26f4b525
--- /dev/null
+++ b/release/scripts/templates/batch_export.py
@@ -0,0 +1,33 @@
+# exports each selected object into its own file
+
+import bpy
+import os
+
+# export to blend file location
+basedir = os.path.dirname(bpy.data.filepath)
+
+if not basedir:
+ raise Exception("Blend file is not saved")
+
+selection = bpy.context.selected_objects
+
+bpy.ops.object.select_all(action='DESELECT')
+
+for obj in selection:
+
+ obj.select = True
+
+ name = bpy.path.clean_name(obj.name)
+ fn = os.path.join(basedir, name)
+
+ bpy.ops.export_scene.fbx(filepath=fn + ".fbx", use_selection=True)
+
+ ## Can be used for multiple formats
+ # bpy.ops.export_scene.x3d(filepath=fn + ".x3d", use_selection=True)
+
+ obj.select = False
+
+ print("written:", fn)
+
+for obj in selection:
+ obj.select = True
diff --git a/release/scripts/templates/operator_export.py b/release/scripts/templates/operator_export.py
index 4cf943a53b7..b1d53e6ee0c 100644
--- a/release/scripts/templates/operator_export.py
+++ b/release/scripts/templates/operator_export.py
@@ -24,22 +24,30 @@ class ExportSomeData(bpy.types.Operator, ExportHelper):
# ExportHelper mixin class uses this
filename_ext = ".txt"
- filter_glob = StringProperty(default="*.txt", options={'HIDDEN'})
+ filter_glob = StringProperty(
+ default="*.txt",
+ options={'HIDDEN'},
+ )
# List of operator properties, the attributes will be assigned
# to the class instance from the operator settings before calling.
- use_setting = BoolProperty(name="Example Boolean", description="Example Tooltip", default=True)
-
- type = EnumProperty(items=(('OPT_A', "First Option", "Description one"),
- ('OPT_B', "Second Option", "Description two."),
- ),
- name="Example Enum",
- description="Choose between two items",
- default='OPT_A')
+ use_setting = BoolProperty(
+ name="Example Boolean",
+ description="Example Tooltip",
+ default=True,
+ )
+
+ type = EnumProperty(
+ name="Example Enum",
+ description="Choose between two items",
+ items=(('OPT_A', "First Option", "Description one"),
+ ('OPT_B', "Second Option", "Description two.")),
+ default='OPT_A',
+ )
@classmethod
def poll(cls, context):
- return context.active_object != None
+ return context.active_object is not None
def execute(self, context):
return write_some_data(context, self.filepath, self.use_setting)
diff --git a/release/scripts/templates/operator_mesh_add.py b/release/scripts/templates/operator_mesh_add.py
index 10d23a6712d..d89b7e82f77 100644
--- a/release/scripts/templates/operator_mesh_add.py
+++ b/release/scripts/templates/operator_mesh_add.py
@@ -43,25 +43,38 @@ class AddBox(bpy.types.Operator):
bl_label = "Add Box"
bl_options = {'REGISTER', 'UNDO'}
- width = FloatProperty(name="Width",
+ width = FloatProperty(
+ name="Width",
description="Box Width",
- default=1.0, min=0.01, max=100.0)
-
- height = FloatProperty(name="Height",
+ min=0.01, max=100.0,
+ default=1.0,
+ )
+ height = FloatProperty(
+ name="Height",
description="Box Height",
- default=1.0, min=0.01, max=100.0)
-
- depth = FloatProperty(name="Depth",
+ min=0.01, max=100.0,
+ default=1.0,
+ )
+ depth = FloatProperty(
+ name="Depth",
description="Box Depth",
- default=1.0, min=0.01, max=100.0)
+ min=0.01, max=100.0,
+ default=1.0,
+ )
# generic transform props
- view_align = BoolProperty(name="Align to View",
- default=False)
- location = FloatVectorProperty(name="Location",
- subtype='TRANSLATION')
- rotation = FloatVectorProperty(name="Rotation",
- subtype='EULER')
+ view_align = BoolProperty(
+ name="Align to View",
+ default=False,
+ )
+ location = FloatVectorProperty(
+ name="Location",
+ subtype='TRANSLATION',
+ )
+ rotation = FloatVectorProperty(
+ name="Rotation",
+ subtype='EULER',
+ )
def execute(self, context):
diff --git a/release/scripts/templates/operator_modal.py b/release/scripts/templates/operator_modal.py
index 78dbd4c6b43..a428b097f82 100644
--- a/release/scripts/templates/operator_modal.py
+++ b/release/scripts/templates/operator_modal.py
@@ -18,7 +18,7 @@ class ModalOperator(bpy.types.Operator):
elif event.type == 'LEFTMOUSE':
return {'FINISHED'}
- elif event.type in ('RIGHTMOUSE', 'ESC'):
+ elif event.type in {'RIGHTMOUSE', 'ESC'}:
context.object.location.x = self.first_value
return {'CANCELLED'}
@@ -47,4 +47,4 @@ if __name__ == "__main__":
register()
# test call
- bpy.ops.object.modal_operator()
+ bpy.ops.object.modal_operator('INVOKE_DEFAULT')
diff --git a/release/scripts/templates/operator_modal_draw.py b/release/scripts/templates/operator_modal_draw.py
index e7a1f6e4ffe..b3d525a59bf 100644
--- a/release/scripts/templates/operator_modal_draw.py
+++ b/release/scripts/templates/operator_modal_draw.py
@@ -45,7 +45,7 @@ class ModalDrawOperator(bpy.types.Operator):
context.region.callback_remove(self._handle)
return {'FINISHED'}
- elif event.type in ('RIGHTMOUSE', 'ESC'):
+ elif event.type in {'RIGHTMOUSE', 'ESC'}:
context.region.callback_remove(self._handle)
return {'CANCELLED'}
diff --git a/release/scripts/templates/operator_modal_timer.py b/release/scripts/templates/operator_modal_timer.py
index d2267191cf5..ec47390da81 100644
--- a/release/scripts/templates/operator_modal_timer.py
+++ b/release/scripts/templates/operator_modal_timer.py
@@ -10,7 +10,7 @@ class ModalTimerOperator(bpy.types.Operator):
def modal(self, context, event):
if event.type == 'ESC':
- return self.cancel()
+ return self.cancel(context)
if event.type == 'TIMER':
# change theme color, silly!
diff --git a/release/scripts/templates/operator_modal_view3d.py b/release/scripts/templates/operator_modal_view3d.py
index c494f121017..263bf72f129 100644
--- a/release/scripts/templates/operator_modal_view3d.py
+++ b/release/scripts/templates/operator_modal_view3d.py
@@ -8,7 +8,10 @@ class ViewOperator(bpy.types.Operator):
bl_idname = "view3d.modal_operator"
bl_label = "Simple View Operator"
- offset = FloatVectorProperty(name="Offset", size=3)
+ offset = FloatVectorProperty(
+ name="Offset",
+ size=3,
+ )
def execute(self, context):
v3d = context.space_data
@@ -29,7 +32,7 @@ class ViewOperator(bpy.types.Operator):
context.area.header_text_set()
return {'FINISHED'}
- elif event.type in ('RIGHTMOUSE', 'ESC'):
+ elif event.type in {'RIGHTMOUSE', 'ESC'}:
rv3d.view_location = self._initial_location
context.area.header_text_set()
return {'CANCELLED'}
diff --git a/release/scripts/templates/operator_simple.py b/release/scripts/templates/operator_simple.py
index 8348c7a95b1..05d9afc0ad1 100644
--- a/release/scripts/templates/operator_simple.py
+++ b/release/scripts/templates/operator_simple.py
@@ -13,7 +13,7 @@ class SimpleOperator(bpy.types.Operator):
@classmethod
def poll(cls, context):
- return context.active_object != None
+ return context.active_object is not None
def execute(self, context):
main(context)
diff --git a/release/scripts/templates/ui_menu.py b/release/scripts/templates/ui_menu.py
new file mode 100644
index 00000000000..d3c94b86809
--- /dev/null
+++ b/release/scripts/templates/ui_menu.py
@@ -0,0 +1,49 @@
+import bpy
+
+
+class CustomMenu(bpy.types.Menu):
+ bl_label = "Custom Menu"
+ bl_idname = "OBJECT_MT_custom_menu"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("wm.open_mainfile")
+ layout.operator("wm.save_as_mainfile").copy = True
+
+ layout.operator("object.shade_smooth")
+
+ layout.label(text="Hello world!", icon='WORLD_DATA')
+
+ # use an operator enum property to populate a submenu
+ layout.operator_menu_enum("object.select_by_type",
+ property="type",
+ text="Select All by Type...",
+ )
+
+ # call another menu
+ layout.operator("wm.call_menu", text="Unwrap").name = "VIEW3D_MT_uv_map"
+
+
+def draw_item(self, context):
+ layout = self.layout
+ layout.menu(CustomMenu.bl_idname)
+
+
+def register():
+ bpy.utils.register_class(CustomMenu)
+
+ # lets add ourselves to the main header
+ bpy.types.INFO_HT_header.append(draw_item)
+
+
+def unregister():
+ bpy.utils.unregister_class(CustomMenu)
+
+ bpy.types.INFO_HT_header.remove(draw_item)
+
+if __name__ == "__main__":
+ register()
+
+ # The menu can also be called from scripts
+ bpy.ops.wm.call_menu(name=CustomMenu.bl_idname)
diff --git a/release/scripts/templates/ui_menu_simple.py b/release/scripts/templates/ui_menu_simple.py
new file mode 100644
index 00000000000..2129dfd81a4
--- /dev/null
+++ b/release/scripts/templates/ui_menu_simple.py
@@ -0,0 +1,26 @@
+import bpy
+
+
+class SimpleCustomMenu(bpy.types.Menu):
+ bl_label = "Simple Custom Menu"
+ bl_idname = "OBJECT_MT_simple_custom_menu"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("wm.open_mainfile")
+ layout.operator("wm.save_as_mainfile")
+
+
+def register():
+ bpy.utils.register_class(SimpleCustomMenu)
+
+
+def unregister():
+ bpy.utils.unregister_class(SimpleCustomMenu)
+
+if __name__ == "__main__":
+ register()
+
+ # The menu can also be called from scripts
+ bpy.ops.wm.call_menu(name=SimpleCustomMenu.bl_idname)
diff --git a/release/scripts/templates/panel_simple.py b/release/scripts/templates/ui_panel_simple.py
index e5bf70cb654..cde6126b626 100644
--- a/release/scripts/templates/panel_simple.py
+++ b/release/scripts/templates/ui_panel_simple.py
@@ -1,8 +1,9 @@
import bpy
-class OBJECT_PT_hello(bpy.types.Panel):
+class HelloWorldPanel(bpy.types.Panel):
bl_label = "Hello World Panel"
+ bl_idname = "OBJECT_PT_hello"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "object"
@@ -22,11 +23,11 @@ class OBJECT_PT_hello(bpy.types.Panel):
def register():
- bpy.utils.register_class(OBJECT_PT_hello)
+ bpy.utils.register_class(HelloWorldPanel)
def unregister():
- bpy.utils.unregister_class(OBJECT_PT_hello)
+ bpy.utils.unregister_class(HelloWorldPanel)
if __name__ == "__main__":