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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release')
-rw-r--r--release/VERSION1
-rw-r--r--release/datafiles/.Bfs2
-rw-r--r--release/datafiles/blenderbuttonsbin210319 -> 210335 bytes
-rw-r--r--release/datafiles/brushicons/add.pngbin10948 -> 8154 bytes
-rw-r--r--release/datafiles/brushicons/blob.pngbin10703 -> 8149 bytes
-rw-r--r--release/datafiles/brushicons/blur.pngbin9327 -> 7019 bytes
-rw-r--r--release/datafiles/brushicons/clay.pngbin11181 -> 8124 bytes
-rw-r--r--release/datafiles/brushicons/clone.pngbin10774 -> 8425 bytes
-rw-r--r--release/datafiles/brushicons/crease.pngbin8638 -> 6591 bytes
-rw-r--r--release/datafiles/brushicons/darken.pngbin9653 -> 7280 bytes
-rw-r--r--release/datafiles/brushicons/draw.pngbin11349 -> 8450 bytes
-rw-r--r--release/datafiles/brushicons/fill.pngbin16892 -> 12244 bytes
-rw-r--r--release/datafiles/brushicons/flatten.pngbin9114 -> 6971 bytes
-rw-r--r--release/datafiles/brushicons/grab.pngbin8045 -> 6015 bytes
-rw-r--r--release/datafiles/brushicons/inflate.pngbin8840 -> 6791 bytes
-rw-r--r--release/datafiles/brushicons/layer.pngbin11004 -> 8715 bytes
-rw-r--r--release/datafiles/brushicons/lighten.pngbin9437 -> 7025 bytes
-rw-r--r--release/datafiles/brushicons/mix.pngbin10448 -> 7841 bytes
-rw-r--r--release/datafiles/brushicons/multiply.pngbin10039 -> 7456 bytes
-rw-r--r--release/datafiles/brushicons/nudge.pngbin18012 -> 14292 bytes
-rw-r--r--release/datafiles/brushicons/pinch.pngbin9880 -> 7605 bytes
-rw-r--r--release/datafiles/brushicons/scrape.pngbin13055 -> 10025 bytes
-rw-r--r--release/datafiles/brushicons/smear.pngbin9358 -> 7037 bytes
-rw-r--r--release/datafiles/brushicons/smooth.pngbin16428 -> 13520 bytes
-rw-r--r--release/datafiles/brushicons/snake_hook.pngbin9710 -> 7421 bytes
-rw-r--r--release/datafiles/brushicons/soften.pngbin9219 -> 6892 bytes
-rw-r--r--release/datafiles/brushicons/subtract.pngbin10173 -> 7510 bytes
-rw-r--r--release/datafiles/brushicons/texdraw.pngbin9462 -> 6944 bytes
-rw-r--r--release/datafiles/brushicons/thumb.pngbin9098 -> 6754 bytes
-rw-r--r--release/datafiles/brushicons/twist.pngbin10889 -> 8373 bytes
-rw-r--r--release/datafiles/brushicons/vertexdraw.pngbin10253 -> 7697 bytes
-rw-r--r--release/datafiles/ctodata.py1
-rw-r--r--release/datafiles/splash.pngbin174800 -> 268962 bytes
-rw-r--r--release/environment-mswindows36
-rw-r--r--release/freedesktop/blender.desktop2
-rw-r--r--release/freedesktop/icons/16x16/apps/blender.pngbin0 -> 977 bytes
-rw-r--r--release/freedesktop/icons/16x16/blender.pngbin845 -> 0 bytes
-rw-r--r--release/freedesktop/icons/16x16/blender.svg250
-rw-r--r--release/freedesktop/icons/22x22/apps/blender.pngbin0 -> 1451 bytes
-rw-r--r--release/freedesktop/icons/22x22/blender.pngbin1236 -> 0 bytes
-rw-r--r--release/freedesktop/icons/22x22/blender.svg250
-rw-r--r--release/freedesktop/icons/24x24/apps/blender.pngbin0 -> 1681 bytes
-rw-r--r--release/freedesktop/icons/256x256/apps/blender.pngbin0 -> 32907 bytes
-rw-r--r--release/freedesktop/icons/32x32/apps/blender.pngbin0 -> 2126 bytes
-rw-r--r--release/freedesktop/icons/32x32/blender.pngbin1955 -> 0 bytes
-rw-r--r--release/freedesktop/icons/32x32/blender.svg250
-rw-r--r--release/freedesktop/icons/blender_icon_source.svg855
-rw-r--r--release/freedesktop/icons/scalable/apps/blender.svg (renamed from release/freedesktop/icons/scalable/blender.svg)0
-rw-r--r--release/plugins/sequence/blur.c2
-rw-r--r--release/plugins/sequence/color-correction-hsv.c2
-rw-r--r--release/plugins/sequence/color-correction-yuv.c2
-rw-r--r--release/plugins/sequence/dnr.c2
-rw-r--r--release/plugins/sequence/gamma.c2
-rw-r--r--release/plugins/sequence/scatter.c6
-rw-r--r--release/scripts/io/netrender/__init__.py69
-rw-r--r--release/scripts/io/netrender/balancing.py195
-rw-r--r--release/scripts/io/netrender/client.py372
-rw-r--r--release/scripts/io/netrender/master.py1079
-rw-r--r--release/scripts/io/netrender/master_html.py315
-rw-r--r--release/scripts/io/netrender/model.py360
-rw-r--r--release/scripts/io/netrender/netrender.css88
-rw-r--r--release/scripts/io/netrender/netrender.js146
-rw-r--r--release/scripts/io/netrender/operators.py564
-rw-r--r--release/scripts/io/netrender/repath.py150
-rw-r--r--release/scripts/io/netrender/slave.py349
-rw-r--r--release/scripts/io/netrender/thumbnail.py81
-rw-r--r--release/scripts/io/netrender/ui.py550
-rw-r--r--release/scripts/io/netrender/utils.py313
-rw-r--r--release/scripts/io/netrender/versioning.py72
-rw-r--r--release/scripts/modules/add_object_utils.py14
-rw-r--r--release/scripts/modules/addon_utils.py326
-rw-r--r--release/scripts/modules/animsys_refactor.py22
-rw-r--r--release/scripts/modules/bpy/__init__.py16
-rw-r--r--release/scripts/modules/bpy/path.py3
-rw-r--r--release/scripts/modules/bpy/utils.py299
-rw-r--r--release/scripts/modules/bpy_types.py79
-rw-r--r--release/scripts/modules/bpyml.py12
-rw-r--r--release/scripts/modules/bpyml_ui.py4
-rw-r--r--release/scripts/modules/console_python.py (renamed from release/scripts/op/console_python.py)52
-rw-r--r--release/scripts/modules/console_shell.py (renamed from release/scripts/op/console_shell.py)11
-rw-r--r--release/scripts/modules/image_utils.py2
-rw-r--r--release/scripts/modules/io_utils.py198
-rw-r--r--release/scripts/modules/keyingsets_utils.py24
-rw-r--r--release/scripts/modules/mesh_utils.py69
-rw-r--r--release/scripts/modules/rna_info.py31
-rw-r--r--release/scripts/modules/sys_info.py31
-rw-r--r--release/scripts/op/fcurve_euler_filter.py89
-rw-r--r--release/scripts/op/uv.py381
-rw-r--r--release/scripts/presets/interaction/blender.py5
-rw-r--r--release/scripts/presets/interaction/maya.py10
-rw-r--r--release/scripts/presets/keyconfig/maya.py442
-rw-r--r--release/scripts/startup/bl_operators/__init__.py58
-rw-r--r--release/scripts/startup/bl_operators/add_mesh_torus.py (renamed from release/scripts/op/add_mesh_torus.py)22
-rw-r--r--release/scripts/startup/bl_operators/animsys_update.py (renamed from release/scripts/op/animsys_update.py)21
-rw-r--r--release/scripts/startup/bl_operators/image.py (renamed from release/scripts/op/image.py)45
-rw-r--r--release/scripts/startup/bl_operators/mesh.py (renamed from release/scripts/op/mesh.py)25
-rw-r--r--release/scripts/startup/bl_operators/nla.py (renamed from release/scripts/op/nla.py)19
-rw-r--r--release/scripts/startup/bl_operators/object.py (renamed from release/scripts/op/object.py)25
-rw-r--r--release/scripts/startup/bl_operators/object_align.py (renamed from release/scripts/op/object_align.py)26
-rw-r--r--release/scripts/startup/bl_operators/object_quick_effects.py296
-rw-r--r--release/scripts/startup/bl_operators/object_randomize_transform.py (renamed from release/scripts/op/object_randomize_transform.py)22
-rw-r--r--release/scripts/startup/bl_operators/presets.py (renamed from release/scripts/op/presets.py)32
-rw-r--r--release/scripts/startup/bl_operators/screen_play_rendered_anim.py (renamed from release/scripts/op/screen_play_rendered_anim.py)25
-rw-r--r--release/scripts/startup/bl_operators/sequencer.py (renamed from release/scripts/op/sequencer.py)14
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_follow_active.py (renamed from release/scripts/op/uvcalc_follow_active.py)20
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_lightmap.py582
-rw-r--r--release/scripts/startup/bl_operators/uvcalc_smart_project.py (renamed from release/scripts/op/uvcalc_smart_project.py)119
-rw-r--r--release/scripts/startup/bl_operators/vertexpaint_dirt.py (renamed from release/scripts/op/vertexpaint_dirt.py)36
-rw-r--r--release/scripts/startup/bl_operators/wm.py (renamed from release/scripts/op/wm.py)228
-rw-r--r--release/scripts/startup/bl_ui/__init__.py121
-rw-r--r--release/scripts/startup/bl_ui/properties_animviz.py (renamed from release/scripts/ui/properties_animviz.py)21
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py (renamed from release/scripts/ui/properties_data_armature.py)118
-rw-r--r--release/scripts/startup/bl_ui/properties_data_bone.py (renamed from release/scripts/ui/properties_data_bone.py)13
-rw-r--r--release/scripts/startup/bl_ui/properties_data_camera.py (renamed from release/scripts/ui/properties_data_camera.py)23
-rw-r--r--release/scripts/startup/bl_ui/properties_data_curve.py (renamed from release/scripts/ui/properties_data_curve.py)25
-rw-r--r--release/scripts/startup/bl_ui/properties_data_empty.py (renamed from release/scripts/ui/properties_data_empty.py)11
-rw-r--r--release/scripts/startup/bl_ui/properties_data_lamp.py (renamed from release/scripts/ui/properties_data_lamp.py)41
-rw-r--r--release/scripts/startup/bl_ui/properties_data_lattice.py (renamed from release/scripts/ui/properties_data_lattice.py)38
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py (renamed from release/scripts/ui/properties_data_mesh.py)23
-rw-r--r--release/scripts/startup/bl_ui/properties_data_metaball.py (renamed from release/scripts/ui/properties_data_metaball.py)12
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py (renamed from release/scripts/ui/properties_data_modifier.py)158
-rw-r--r--release/scripts/startup/bl_ui/properties_game.py (renamed from release/scripts/ui/properties_game.py)53
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py (renamed from release/scripts/ui/properties_material.py)317
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py (renamed from release/scripts/ui/properties_object.py)42
-rw-r--r--release/scripts/startup/bl_ui/properties_object_constraint.py (renamed from release/scripts/ui/properties_object_constraint.py)151
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py (renamed from release/scripts/ui/properties_particle.py)567
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_cloth.py (renamed from release/scripts/ui/properties_physics_cloth.py)20
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py (renamed from release/scripts/ui/properties_physics_common.py)44
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_field.py (renamed from release/scripts/ui/properties_physics_field.py)20
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py (renamed from release/scripts/ui/properties_physics_fluid.py)18
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_smoke.py (renamed from release/scripts/ui/properties_physics_smoke.py)19
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_softbody.py (renamed from release/scripts/ui/properties_physics_softbody.py)16
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py (renamed from release/scripts/ui/properties_render.py)118
-rw-r--r--release/scripts/startup/bl_ui/properties_scene.py (renamed from release/scripts/ui/properties_scene.py)165
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py (renamed from release/scripts/ui/properties_texture.py)206
-rw-r--r--release/scripts/startup/bl_ui/properties_world.py (renamed from release/scripts/ui/properties_world.py)10
-rw-r--r--release/scripts/startup/bl_ui/space_console.py (renamed from release/scripts/ui/space_console.py)14
-rw-r--r--release/scripts/startup/bl_ui/space_dopesheet.py (renamed from release/scripts/ui/space_dopesheet.py)104
-rw-r--r--release/scripts/startup/bl_ui/space_filebrowser.py (renamed from release/scripts/ui/space_filebrowser.py)12
-rw-r--r--release/scripts/startup/bl_ui/space_graph.py (renamed from release/scripts/ui/space_graph.py)18
-rw-r--r--release/scripts/startup/bl_ui/space_image.py (renamed from release/scripts/ui/space_image.py)84
-rw-r--r--release/scripts/startup/bl_ui/space_info.py (renamed from release/scripts/ui/space_info.py)29
-rw-r--r--release/scripts/startup/bl_ui/space_logic.py (renamed from release/scripts/ui/space_logic.py)12
-rw-r--r--release/scripts/startup/bl_ui/space_nla.py (renamed from release/scripts/ui/space_nla.py)18
-rw-r--r--release/scripts/startup/bl_ui/space_node.py (renamed from release/scripts/ui/space_node.py)13
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py (renamed from release/scripts/ui/space_outliner.py)12
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py (renamed from release/scripts/ui/space_sequencer.py)57
-rw-r--r--release/scripts/startup/bl_ui/space_text.py (renamed from release/scripts/ui/space_text.py)16
-rw-r--r--release/scripts/startup/bl_ui/space_time.py (renamed from release/scripts/ui/space_time.py)11
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py (renamed from release/scripts/ui/space_userpref.py)266
-rw-r--r--release/scripts/startup/bl_ui/space_userpref_keymap.py (renamed from release/scripts/ui/space_userpref_keymap.py)69
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py (renamed from release/scripts/ui/space_view3d.py)129
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py (renamed from release/scripts/ui/space_view3d_toolbar.py)182
-rw-r--r--release/scripts/startup/keyingsets_builtins.py (renamed from release/scripts/keyingsets/keyingsets_builtins.py)186
-rw-r--r--release/scripts/templates/addon_add_object.py8
-rw-r--r--release/scripts/templates/background_job.py64
-rw-r--r--release/scripts/templates/builtin_keyingset.py3
-rw-r--r--release/scripts/templates/operator_export.py9
-rw-r--r--release/scripts/templates/operator_mesh_add.py2
-rw-r--r--release/scripts/templates/operator_modal.py2
-rw-r--r--release/scripts/templates/operator_modal_timer.py45
-rw-r--r--release/scripts/templates/panel_simple.py2
-rw-r--r--release/text/readme.html26
-rw-r--r--release/windows/contrib/vfapi/vfapi-plugin.c26
-rw-r--r--release/windows/installer/00.sconsblender.nsi512
165 files changed, 5467 insertions, 8935 deletions
diff --git a/release/VERSION b/release/VERSION
deleted file mode 100644
index 9a256b1d546..00000000000
--- a/release/VERSION
+++ /dev/null
@@ -1 +0,0 @@
-2.56a-beta
diff --git a/release/datafiles/.Bfs b/release/datafiles/.Bfs
deleted file mode 100644
index 80854424071..00000000000
--- a/release/datafiles/.Bfs
+++ /dev/null
@@ -1,2 +0,0 @@
-/
-/tmp/
diff --git a/release/datafiles/blenderbuttons b/release/datafiles/blenderbuttons
index 42e82430ca1..9872e53585e 100644
--- a/release/datafiles/blenderbuttons
+++ b/release/datafiles/blenderbuttons
Binary files differ
diff --git a/release/datafiles/brushicons/add.png b/release/datafiles/brushicons/add.png
index ad041bed130..1343f7542b8 100644
--- a/release/datafiles/brushicons/add.png
+++ b/release/datafiles/brushicons/add.png
Binary files differ
diff --git a/release/datafiles/brushicons/blob.png b/release/datafiles/brushicons/blob.png
index 1d63d1e873c..2deb42c9dad 100644
--- a/release/datafiles/brushicons/blob.png
+++ b/release/datafiles/brushicons/blob.png
Binary files differ
diff --git a/release/datafiles/brushicons/blur.png b/release/datafiles/brushicons/blur.png
index 6b8fc4b6053..93636abbe56 100644
--- a/release/datafiles/brushicons/blur.png
+++ b/release/datafiles/brushicons/blur.png
Binary files differ
diff --git a/release/datafiles/brushicons/clay.png b/release/datafiles/brushicons/clay.png
index dab73b7cbdd..27ea974a833 100644
--- a/release/datafiles/brushicons/clay.png
+++ b/release/datafiles/brushicons/clay.png
Binary files differ
diff --git a/release/datafiles/brushicons/clone.png b/release/datafiles/brushicons/clone.png
index 89677961d81..b10faadef85 100644
--- a/release/datafiles/brushicons/clone.png
+++ b/release/datafiles/brushicons/clone.png
Binary files differ
diff --git a/release/datafiles/brushicons/crease.png b/release/datafiles/brushicons/crease.png
index ac057e081c1..b2be546ac03 100644
--- a/release/datafiles/brushicons/crease.png
+++ b/release/datafiles/brushicons/crease.png
Binary files differ
diff --git a/release/datafiles/brushicons/darken.png b/release/datafiles/brushicons/darken.png
index ee312c7a04f..b129bd7bbea 100644
--- a/release/datafiles/brushicons/darken.png
+++ b/release/datafiles/brushicons/darken.png
Binary files differ
diff --git a/release/datafiles/brushicons/draw.png b/release/datafiles/brushicons/draw.png
index 2cbc8052312..6d0666a6586 100644
--- a/release/datafiles/brushicons/draw.png
+++ b/release/datafiles/brushicons/draw.png
Binary files differ
diff --git a/release/datafiles/brushicons/fill.png b/release/datafiles/brushicons/fill.png
index 654ec7b66fc..6152a91e9e0 100644
--- a/release/datafiles/brushicons/fill.png
+++ b/release/datafiles/brushicons/fill.png
Binary files differ
diff --git a/release/datafiles/brushicons/flatten.png b/release/datafiles/brushicons/flatten.png
index 401226be862..53e807cf811 100644
--- a/release/datafiles/brushicons/flatten.png
+++ b/release/datafiles/brushicons/flatten.png
Binary files differ
diff --git a/release/datafiles/brushicons/grab.png b/release/datafiles/brushicons/grab.png
index d3ebbef31ad..d564fb4222b 100644
--- a/release/datafiles/brushicons/grab.png
+++ b/release/datafiles/brushicons/grab.png
Binary files differ
diff --git a/release/datafiles/brushicons/inflate.png b/release/datafiles/brushicons/inflate.png
index f3ad313add8..5faba1f8de4 100644
--- a/release/datafiles/brushicons/inflate.png
+++ b/release/datafiles/brushicons/inflate.png
Binary files differ
diff --git a/release/datafiles/brushicons/layer.png b/release/datafiles/brushicons/layer.png
index df3b02fb766..0c8009b7403 100644
--- a/release/datafiles/brushicons/layer.png
+++ b/release/datafiles/brushicons/layer.png
Binary files differ
diff --git a/release/datafiles/brushicons/lighten.png b/release/datafiles/brushicons/lighten.png
index 6dacf6dcc75..9667c9973e4 100644
--- a/release/datafiles/brushicons/lighten.png
+++ b/release/datafiles/brushicons/lighten.png
Binary files differ
diff --git a/release/datafiles/brushicons/mix.png b/release/datafiles/brushicons/mix.png
index d871d241769..837ac02e513 100644
--- a/release/datafiles/brushicons/mix.png
+++ b/release/datafiles/brushicons/mix.png
Binary files differ
diff --git a/release/datafiles/brushicons/multiply.png b/release/datafiles/brushicons/multiply.png
index 2dd32463627..9ee4a1eebd0 100644
--- a/release/datafiles/brushicons/multiply.png
+++ b/release/datafiles/brushicons/multiply.png
Binary files differ
diff --git a/release/datafiles/brushicons/nudge.png b/release/datafiles/brushicons/nudge.png
index 84964e91f30..ced9f96602b 100644
--- a/release/datafiles/brushicons/nudge.png
+++ b/release/datafiles/brushicons/nudge.png
Binary files differ
diff --git a/release/datafiles/brushicons/pinch.png b/release/datafiles/brushicons/pinch.png
index b60bcd66a36..ce00ba0c040 100644
--- a/release/datafiles/brushicons/pinch.png
+++ b/release/datafiles/brushicons/pinch.png
Binary files differ
diff --git a/release/datafiles/brushicons/scrape.png b/release/datafiles/brushicons/scrape.png
index 9b7a57c1b9f..7a8838ba7e9 100644
--- a/release/datafiles/brushicons/scrape.png
+++ b/release/datafiles/brushicons/scrape.png
Binary files differ
diff --git a/release/datafiles/brushicons/smear.png b/release/datafiles/brushicons/smear.png
index 4cdc2205c46..5d42b3b24ee 100644
--- a/release/datafiles/brushicons/smear.png
+++ b/release/datafiles/brushicons/smear.png
Binary files differ
diff --git a/release/datafiles/brushicons/smooth.png b/release/datafiles/brushicons/smooth.png
index 052e2452d13..8d248a9691b 100644
--- a/release/datafiles/brushicons/smooth.png
+++ b/release/datafiles/brushicons/smooth.png
Binary files differ
diff --git a/release/datafiles/brushicons/snake_hook.png b/release/datafiles/brushicons/snake_hook.png
index f8351d909ee..961c54ec488 100644
--- a/release/datafiles/brushicons/snake_hook.png
+++ b/release/datafiles/brushicons/snake_hook.png
Binary files differ
diff --git a/release/datafiles/brushicons/soften.png b/release/datafiles/brushicons/soften.png
index 2b2e9116f30..07367a4c189 100644
--- a/release/datafiles/brushicons/soften.png
+++ b/release/datafiles/brushicons/soften.png
Binary files differ
diff --git a/release/datafiles/brushicons/subtract.png b/release/datafiles/brushicons/subtract.png
index c28975ecf20..cd2a64a819c 100644
--- a/release/datafiles/brushicons/subtract.png
+++ b/release/datafiles/brushicons/subtract.png
Binary files differ
diff --git a/release/datafiles/brushicons/texdraw.png b/release/datafiles/brushicons/texdraw.png
index 1241349a15e..94faa584c19 100644
--- a/release/datafiles/brushicons/texdraw.png
+++ b/release/datafiles/brushicons/texdraw.png
Binary files differ
diff --git a/release/datafiles/brushicons/thumb.png b/release/datafiles/brushicons/thumb.png
index 8c39075fc8a..821ee8eac88 100644
--- a/release/datafiles/brushicons/thumb.png
+++ b/release/datafiles/brushicons/thumb.png
Binary files differ
diff --git a/release/datafiles/brushicons/twist.png b/release/datafiles/brushicons/twist.png
index 53904427660..84024f07937 100644
--- a/release/datafiles/brushicons/twist.png
+++ b/release/datafiles/brushicons/twist.png
Binary files differ
diff --git a/release/datafiles/brushicons/vertexdraw.png b/release/datafiles/brushicons/vertexdraw.png
index 8bd2dc1be8a..88a9fbb2b60 100644
--- a/release/datafiles/brushicons/vertexdraw.png
+++ b/release/datafiles/brushicons/vertexdraw.png
Binary files differ
diff --git a/release/datafiles/ctodata.py b/release/datafiles/ctodata.py
index be33f724deb..2d2daabb661 100644
--- a/release/datafiles/ctodata.py
+++ b/release/datafiles/ctodata.py
@@ -28,7 +28,6 @@
# <pep8 compliant>
import sys
-import os
if len(sys.argv) < 2:
sys.stdout.write("Usage: ctodata <c_file>\n")
diff --git a/release/datafiles/splash.png b/release/datafiles/splash.png
index 9207b935271..cad2bc5f06c 100644
--- a/release/datafiles/splash.png
+++ b/release/datafiles/splash.png
Binary files differ
diff --git a/release/environment-mswindows b/release/environment-mswindows
index f8890f89af8..41308533e0b 100644
--- a/release/environment-mswindows
+++ b/release/environment-mswindows
@@ -1,18 +1,18 @@
-# This is a Blender Environment Variable config file.
-#
-# Comment lines start with "#", other lines will be split at the "="
-# and the part before will be used as env var name and the part after
-# as env var value. The value can make reference to previous or
-# prelaunch variables with "%%" and the content will be replaced.
-# Once set, values of variables will not be overwritten.
-#
-# BLENDER_SHARE should be COMMON_APPDATA\\Blender Foundation\\Blender for typical installs.
-# BLENDER_VERSION will be set by the program before processing this file.
-BLENDER_USER_BASE=%USERPROFILE%\\Blender Foundation\\Blender\\%BLENDER_VERSION%
-BLENDER_SYSTEM_BASE=%BLENDER_SHARE%\\%BLENDER_VERSION%
-BLENDER_USER_DATAFILES=%USERPROFILE%\\Blender Foundation\\%BLENDER_VERSION%\\datafiles
-BLENDER_SYSTEM_DATAFILES=%BLENDER_SHARE%\\%BLENDER_VERSION%\\datafiles
-BLENDER_USER_PY=%USERPROFILE%\\Blender Foundation\\%BLENDER_VERSION%\\py
-BLENDER_SYSTEM_PY=%BLENDER_SHARE%\\%BLENDER_VERSION%\\py
-BLENDER_USER_PLUGINS=%USERPROFILE%\\Blender Foundation\\%BLENDER_VERSION%\\plugins
-BLENDER_SYSTEM_PLUGINS=%BLENDER_SHARE%\\%BLENDER_VERSION%\\plugins
+# This is a Blender Environment Variable config file.
+#
+# Comment lines start with "#", other lines will be split at the "="
+# and the part before will be used as env var name and the part after
+# as env var value. The value can make reference to previous or
+# prelaunch variables with "%%" and the content will be replaced.
+# Once set, values of variables will not be overwritten.
+#
+# BLENDER_SHARE should be COMMON_APPDATA\\Blender Foundation\\Blender for typical installs.
+# BLENDER_VERSION will be set by the program before processing this file.
+BLENDER_USER_BASE=%USERPROFILE%\\Blender Foundation\\Blender\\%BLENDER_VERSION%
+BLENDER_SYSTEM_BASE=%BLENDER_SHARE%\\%BLENDER_VERSION%
+BLENDER_USER_DATAFILES=%USERPROFILE%\\Blender Foundation\\%BLENDER_VERSION%\\datafiles
+BLENDER_SYSTEM_DATAFILES=%BLENDER_SHARE%\\%BLENDER_VERSION%\\datafiles
+BLENDER_USER_PY=%USERPROFILE%\\Blender Foundation\\%BLENDER_VERSION%\\py
+BLENDER_SYSTEM_PY=%BLENDER_SHARE%\\%BLENDER_VERSION%\\py
+BLENDER_USER_PLUGINS=%USERPROFILE%\\Blender Foundation\\%BLENDER_VERSION%\\plugins
+BLENDER_SYSTEM_PLUGINS=%BLENDER_SHARE%\\%BLENDER_VERSION%\\plugins
diff --git a/release/freedesktop/blender.desktop b/release/freedesktop/blender.desktop
index ba503f2f62e..34b2b9bb0af 100644
--- a/release/freedesktop/blender.desktop
+++ b/release/freedesktop/blender.desktop
@@ -8,7 +8,7 @@ GenericName[ru]=Редактор 3D-моделей
Comment=3D modeling, animation, rendering and post-production
Comment[es]=modelado 3D, animación, renderizado y post-producción
Exec=blender
-Icon=blender.svg
+Icon=blender
Terminal=false
Type=Application
Categories=Graphics;3DGraphics;
diff --git a/release/freedesktop/icons/16x16/apps/blender.png b/release/freedesktop/icons/16x16/apps/blender.png
new file mode 100644
index 00000000000..a80352540fa
--- /dev/null
+++ b/release/freedesktop/icons/16x16/apps/blender.png
Binary files differ
diff --git a/release/freedesktop/icons/16x16/blender.png b/release/freedesktop/icons/16x16/blender.png
deleted file mode 100644
index 2ddf0deff21..00000000000
--- a/release/freedesktop/icons/16x16/blender.png
+++ /dev/null
Binary files differ
diff --git a/release/freedesktop/icons/16x16/blender.svg b/release/freedesktop/icons/16x16/blender.svg
deleted file mode 100644
index 7835b312a6c..00000000000
--- a/release/freedesktop/icons/16x16/blender.svg
+++ /dev/null
@@ -1,250 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16"
- height="16"
- id="svg7854"
- sodipodi:version="0.32"
- inkscape:version="0.48.0 r9654"
- version="1.0"
- sodipodi:docname="blender.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- sodipodi:modified="true"
- inkscape:export-filename="/home/user/my/blender/builds/blender/release/freedesktop/icons/16x16/blender.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
- <defs
- id="defs7856">
- <linearGradient
- inkscape:collect="always"
- id="linearGradient39171">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop39173" />
- <stop
- style="stop-color:white;stop-opacity:0;"
- offset="1"
- id="stop39175" />
- </linearGradient>
- <linearGradient
- id="linearGradient39155">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop39157" />
- <stop
- style="stop-color:#dadada;stop-opacity:1;"
- offset="1"
- id="stop39159" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient35500">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop35502" />
- <stop
- style="stop-color:white;stop-opacity:0;"
- offset="1"
- id="stop35504" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient35488">
- <stop
- style="stop-color:black;stop-opacity:1;"
- offset="0"
- id="stop35490" />
- <stop
- style="stop-color:black;stop-opacity:0;"
- offset="1"
- id="stop35492" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient3564">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop3566" />
- <stop
- style="stop-color:white;stop-opacity:0;"
- offset="1"
- id="stop3568" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3564"
- id="linearGradient34576"
- gradientUnits="userSpaceOnUse"
- x1="185.9903"
- y1="193.33229"
- x2="190.46461"
- y2="-458.05771"
- gradientTransform="matrix(0.06818845,0,0,0.06818845,22.51112,27.02885)" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient35488"
- id="radialGradient35494"
- cx="28.019106"
- cy="38.98439"
- fx="28.019106"
- fy="38.98439"
- r="15.467961"
- gradientTransform="matrix(1,0,0,0.342857,0,25.61831)"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient35500"
- id="linearGradient35506"
- x1="21.204315"
- y1="21.699249"
- x2="20.155914"
- y2="-26.908371"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient39155"
- id="linearGradient39161"
- x1="31.1875"
- y1="18.875"
- x2="29.875"
- y2="34.375"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient39171"
- id="radialGradient39177"
- cx="26.109201"
- cy="19.668886"
- fx="26.109201"
- fy="19.668886"
- r="20.278975"
- gradientTransform="matrix(1.647222,0,0,1.26792,-15.47413,-5.79794)"
- gradientUnits="userSpaceOnUse" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#e0e0e0"
- borderopacity="1"
- gridtolerance="10000"
- guidetolerance="10"
- objecttolerance="10"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="16.245778"
- inkscape:cx="10.326105"
- inkscape:cy="15.440713"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- width="48px"
- height="48px"
- inkscape:showpageshadow="false"
- inkscape:window-width="1392"
- inkscape:window-height="976"
- inkscape:window-x="0"
- inkscape:window-y="0"
- showgrid="false"
- inkscape:window-maximized="1" />
- <metadata
- id="metadata7859">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:creator>
- <cc:Agent>
- <dc:title>Jakub Steiner</dc:title>
- </cc:Agent>
- </dc:creator>
- <dc:source>http://jimmac.musichall.cz</dc:source>
- <cc:license
- rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
- <dc:title></dc:title>
- </cc:Work>
- <cc:License
- rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
- <cc:permits
- rdf:resource="http://web.resource.org/cc/Reproduction" />
- <cc:permits
- rdf:resource="http://web.resource.org/cc/Distribution" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/Notice" />
- <cc:permits
- rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/ShareAlike" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/SourceCode" />
- </cc:License>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-32)">
- <g
- id="blender"
- transform="matrix(0.32150786,0,0,0.32150786,0.0378132,31.723202)"
- inkscape:label="blender">
- <path
- transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)"
- d="m 43.487067,38.98439 c 0,2.928932 -6.925242,5.303301 -15.467961,5.303301 -8.542719,0 -15.467961,-2.374369 -15.467961,-5.303301 0,-2.928932 6.925242,-5.303301 15.467961,-5.303301 8.542719,0 15.467961,2.374369 15.467961,5.303301 z"
- sodipodi:ry="5.3033009"
- sodipodi:rx="15.467961"
- sodipodi:cy="38.98439"
- sodipodi:cx="28.019106"
- id="path35486"
- style="opacity:0.54857142;color:#000000;fill:url(#radialGradient35494);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- sodipodi:nodetypes="csssssssssscccsscccscccssccc"
- d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -2.434775,-0.6939758 -3.431728,0.00488 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 3.792068,3.0680399 5.702368,4.5676189 0,0 -17.551681,-0.01171 -17.551681,-0.01171 -1.994685,0 -3.1682604,0.947915 -3.4153942,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800212,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -15.901723,11.764162 -15.901723,11.764162 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.677593,-7.102098 8.677593,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 z"
- id="path2482"
- style="fill:#f57900;fill-rule:evenodd;stroke:#ce5c00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
- <path
- transform="matrix(0.821621,0,0,0.839506,5.875686,3.882724)"
- d="m 42.75,25.75 c 0,5.591883 -5.176708,10.125 -11.5625,10.125 -6.385792,0 -11.5625,-4.533117 -11.5625,-10.125 0,-5.591883 5.176708,-10.125 11.5625,-10.125 6.385792,0 11.5625,4.533117 11.5625,10.125 z"
- sodipodi:ry="10.125"
- sodipodi:rx="11.5625"
- sodipodi:cy="25.75"
- sodipodi:cx="31.1875"
- id="path39153"
- style="color:#000000;fill:url(#linearGradient39161);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- sodipodi:nodetypes="cssssscscczccsccssssccscccccscssc"
- id="path3562"
- d="m 25.796988,6.0267804 c -0.404852,5.53e-4 -0.818619,0.1256944 -1.095272,0.3196267 -7.14e-4,7.142e-4 -0.0014,0.00143 -0.0021,0.00213 -0.280209,0.1956525 -0.336859,0.3680061 -0.345206,0.4602725 -0.0083,0.092266 -0.01324,0.1672776 0.189655,0.3345475 0.01899,0.015735 0.03747,0.032076 0.0554,0.049009 0.124258,0.1010285 5.704394,4.6389489 5.704394,4.6389489 0.373658,0.304091 0.51584,0.810232 0.355197,1.264415 -0.160635,0.454191 -0.589422,0.382732 -1.071174,0.384283 -5.634142,0.05114 -17.60967,0.01918 -17.60967,0.01918 -0.952967,6.38e-4 -2.3472795,0.516793 -2.4135719,1.585761 -0.063562,1.024947 0.9093059,1.457499 1.5782589,1.457499 0,0 8.830403,-0.01705 8.830403,-0.01705 0.488364,-5.91e-4 0.922857,0.221532 1.080466,0.683755 0.15761,0.462231 0.0033,0.53156 -0.383664,0.829439 0,0 -15.9006939,12.205735 -15.9006939,12.205735 -0.00142,0.0014 -0.00284,0.0028 -0.00426,0.0043 -0.064038,0.04879 -0.084772,0.06226 -0.061795,0.04476 -0.5536756,0.424618 -0.8961097,0.98072 -1.0185711,1.476701 -0.1224537,0.495981 -0.04659,0.882548 0.1875202,1.182646 0.4788333,0.613413 1.7693735,0.732111 2.8980115,-0.178996 0,0 8.6727243,-7.09799 8.6727243,-7.09799 0.361955,-0.295752 0.867758,-0.340606 1.276111,-0.113169 0.408345,0.227437 0.636512,0.681082 0.575631,1.144518 0,0 -0.112502,0.980045 -0.10655,1.370159 0.192357,2.636407 1.448328,4.914995 3.115366,6.91474 2.877746,3.172809 6.84939,4.556285 11.042271,4.719919 4.20342,-0.04394 8.185784,-1.662428 11.042264,-4.758277 5.218918,-6.385867 3.941737,-13.3639 -1.747326,-17.993227 C 36.14442,13.301598 31.42752,9.8792062 26.81986,6.3400589 c -0.0043,-0.00352 -0.0086,-0.00707 -0.01279,-0.010651 -0.0072,-0.00489 -0.01427,-0.00987 -0.02131,-0.014921 -0.210578,-0.1612288 -0.584681,-0.288267 -0.988772,-0.2877065 z"
- style="opacity:0.4857143;fill:none;stroke:url(#linearGradient34576);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
- <path
- d="m 26.007076,24.754048 c 0.07447,-1.361157 0.739293,-2.562655 1.738705,-3.413271 0.983518,-0.836183 2.304215,-1.346747 3.746876,-1.346747 1.441743,0 2.762441,0.510564 3.745729,1.346747 1.000515,0.850616 1.664539,2.051213 1.739875,3.41237 0.07718,1.400852 -0.4828,2.701576 -1.46425,3.66495 -1.000516,0.981409 -2.427099,1.597503 -4.021354,1.597503 -1.595172,0 -3.021756,-0.616094 -4.022225,-1.597503 -0.982461,-0.963374 -1.540507,-2.264098 -1.463356,-3.664049 z"
- id="path2478"
- style="fill:#3465a4;fill-rule:evenodd;stroke:none"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc"
- id="path39166"
- d="m 25.8125,6.03125 c -0.404852,5.528e-4 -0.848347,0.1185677 -1.125,0.3125 -0.280209,0.1956523 -0.335403,0.3764836 -0.34375,0.46875 -0.0083,0.092267 -0.01539,0.1764801 0.1875,0.34375 0.01899,0.015735 0.04457,0.014317 0.0625,0.03125 0.124258,0.1010283 5.71875,4.65625 5.71875,4.65625 0.373658,0.304091 0.504393,0.795817 0.34375,1.25 -0.160635,0.454191 -0.580748,0.373449 -1.0625,0.375 -5.634142,0.05114 -17.625,0.03125 -17.625,0.03125 -0.952967,6.38e-4 -2.3399576,0.524782 -2.40625,1.59375 -0.063562,1.024947 0.924797,1.4375 1.59375,1.4375 0,-1e-6 8.8125,0 8.8125,0 0.488364,-5.92e-4 0.936141,0.225277 1.09375,0.6875 0.157609,0.462231 -0.01926,0.514621 -0.40625,0.8125 0,0 -15.875,12.21875 -15.875,12.21875 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.777612,0.754857 2.90625,-0.15625 1e-7,10e-7 8.65625,-7.09375 8.65625,-7.09375 0.361955,-0.295753 0.872897,-0.352437 1.28125,-0.125 0.408345,0.227436 0.623381,0.692814 0.5625,1.15625 0,-1e-6 -0.0997,0.953636 -0.09375,1.34375 0.09498,1.301756 0.451616,2.521825 0.989039,3.664234 C 20.799917,36.321089 27.770982,19.392853 44.1875,21.03125 43.339652,19.54368 42.151282,18.185293 40.65625,16.96875 36.159865,13.309932 31.42016,9.8828973 26.8125,6.34375 26.805335,6.3388584 26.788292,6.317553 26.78125,6.3125 26.570707,6.1513121 26.216591,6.0306895 25.8125,6.03125 z"
- style="opacity:0.51999996;fill:url(#radialGradient39177);fill-opacity:1;fill-rule:evenodd;stroke:none"
- inkscape:connector-curvature="0" />
- </g>
- </g>
-</svg>
diff --git a/release/freedesktop/icons/22x22/apps/blender.png b/release/freedesktop/icons/22x22/apps/blender.png
new file mode 100644
index 00000000000..cc79979d428
--- /dev/null
+++ b/release/freedesktop/icons/22x22/apps/blender.png
Binary files differ
diff --git a/release/freedesktop/icons/22x22/blender.png b/release/freedesktop/icons/22x22/blender.png
deleted file mode 100644
index fad6f88526f..00000000000
--- a/release/freedesktop/icons/22x22/blender.png
+++ /dev/null
Binary files differ
diff --git a/release/freedesktop/icons/22x22/blender.svg b/release/freedesktop/icons/22x22/blender.svg
deleted file mode 100644
index 0f71a2c4fce..00000000000
--- a/release/freedesktop/icons/22x22/blender.svg
+++ /dev/null
@@ -1,250 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="22"
- height="22"
- id="svg7854"
- sodipodi:version="0.32"
- inkscape:version="0.48.0 r9654"
- version="1.0"
- sodipodi:docname="blender.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- sodipodi:modified="true"
- inkscape:export-filename="/home/user/my/blender/builds/blender/release/freedesktop/icons/22x22/blender.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
- <defs
- id="defs7856">
- <linearGradient
- inkscape:collect="always"
- id="linearGradient39171">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop39173" />
- <stop
- style="stop-color:white;stop-opacity:0;"
- offset="1"
- id="stop39175" />
- </linearGradient>
- <linearGradient
- id="linearGradient39155">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop39157" />
- <stop
- style="stop-color:#dadada;stop-opacity:1;"
- offset="1"
- id="stop39159" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient35500">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop35502" />
- <stop
- style="stop-color:white;stop-opacity:0;"
- offset="1"
- id="stop35504" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient35488">
- <stop
- style="stop-color:black;stop-opacity:1;"
- offset="0"
- id="stop35490" />
- <stop
- style="stop-color:black;stop-opacity:0;"
- offset="1"
- id="stop35492" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient3564">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop3566" />
- <stop
- style="stop-color:white;stop-opacity:0;"
- offset="1"
- id="stop3568" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3564"
- id="linearGradient34576"
- gradientUnits="userSpaceOnUse"
- x1="185.9903"
- y1="193.33229"
- x2="190.46461"
- y2="-458.05771"
- gradientTransform="matrix(0.06818845,0,0,0.06818845,22.51112,27.02885)" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient35488"
- id="radialGradient35494"
- cx="28.019106"
- cy="38.98439"
- fx="28.019106"
- fy="38.98439"
- r="15.467961"
- gradientTransform="matrix(1,0,0,0.342857,0,25.61831)"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient35500"
- id="linearGradient35506"
- x1="21.204315"
- y1="21.699249"
- x2="20.155914"
- y2="-26.908371"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient39155"
- id="linearGradient39161"
- x1="31.1875"
- y1="18.875"
- x2="29.875"
- y2="34.375"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient39171"
- id="radialGradient39177"
- cx="26.109201"
- cy="19.668886"
- fx="26.109201"
- fy="19.668886"
- r="20.278975"
- gradientTransform="matrix(1.647222,0,0,1.26792,-15.47413,-5.79794)"
- gradientUnits="userSpaceOnUse" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#e0e0e0"
- borderopacity="1"
- gridtolerance="10000"
- guidetolerance="10"
- objecttolerance="10"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="16.245778"
- inkscape:cx="10.326105"
- inkscape:cy="15.440713"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- width="48px"
- height="48px"
- inkscape:showpageshadow="false"
- inkscape:window-width="1392"
- inkscape:window-height="976"
- inkscape:window-x="0"
- inkscape:window-y="0"
- showgrid="false"
- inkscape:window-maximized="1" />
- <metadata
- id="metadata7859">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:creator>
- <cc:Agent>
- <dc:title>Jakub Steiner</dc:title>
- </cc:Agent>
- </dc:creator>
- <dc:source>http://jimmac.musichall.cz</dc:source>
- <cc:license
- rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
- <dc:title></dc:title>
- </cc:Work>
- <cc:License
- rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
- <cc:permits
- rdf:resource="http://web.resource.org/cc/Reproduction" />
- <cc:permits
- rdf:resource="http://web.resource.org/cc/Distribution" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/Notice" />
- <cc:permits
- rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/ShareAlike" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/SourceCode" />
- </cc:License>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-26)">
- <g
- id="blender"
- transform="matrix(0.45418175,0,0,0.45418175,-0.2261234,25.847379)"
- inkscape:label="blender">
- <path
- transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)"
- d="m 43.487067,38.98439 c 0,2.928932 -6.925242,5.303301 -15.467961,5.303301 -8.542719,0 -15.467961,-2.374369 -15.467961,-5.303301 0,-2.928932 6.925242,-5.303301 15.467961,-5.303301 8.542719,0 15.467961,2.374369 15.467961,5.303301 z"
- sodipodi:ry="5.3033009"
- sodipodi:rx="15.467961"
- sodipodi:cy="38.98439"
- sodipodi:cx="28.019106"
- id="path35486"
- style="opacity:0.54857142;color:#000000;fill:url(#radialGradient35494);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- sodipodi:nodetypes="csssssssssscccsscccscccssccc"
- d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -2.434775,-0.6939758 -3.431728,0.00488 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 3.792068,3.0680399 5.702368,4.5676189 0,0 -17.551681,-0.01171 -17.551681,-0.01171 -1.994685,0 -3.1682604,0.947915 -3.4153942,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800212,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -15.901723,11.764162 -15.901723,11.764162 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.677593,-7.102098 8.677593,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 z"
- id="path2482"
- style="fill:#f57900;fill-rule:evenodd;stroke:#ce5c00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
- <path
- transform="matrix(0.821621,0,0,0.839506,5.875686,3.882724)"
- d="m 42.75,25.75 c 0,5.591883 -5.176708,10.125 -11.5625,10.125 -6.385792,0 -11.5625,-4.533117 -11.5625,-10.125 0,-5.591883 5.176708,-10.125 11.5625,-10.125 6.385792,0 11.5625,4.533117 11.5625,10.125 z"
- sodipodi:ry="10.125"
- sodipodi:rx="11.5625"
- sodipodi:cy="25.75"
- sodipodi:cx="31.1875"
- id="path39153"
- style="color:#000000;fill:url(#linearGradient39161);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- sodipodi:nodetypes="cssssscscczccsccssssccscccccscssc"
- id="path3562"
- d="m 25.796988,6.0267804 c -0.404852,5.53e-4 -0.818619,0.1256944 -1.095272,0.3196267 -7.14e-4,7.142e-4 -0.0014,0.00143 -0.0021,0.00213 -0.280209,0.1956525 -0.336859,0.3680061 -0.345206,0.4602725 -0.0083,0.092266 -0.01324,0.1672776 0.189655,0.3345475 0.01899,0.015735 0.03747,0.032076 0.0554,0.049009 0.124258,0.1010285 5.704394,4.6389489 5.704394,4.6389489 0.373658,0.304091 0.51584,0.810232 0.355197,1.264415 -0.160635,0.454191 -0.589422,0.382732 -1.071174,0.384283 -5.634142,0.05114 -17.60967,0.01918 -17.60967,0.01918 -0.952967,6.38e-4 -2.3472795,0.516793 -2.4135719,1.585761 -0.063562,1.024947 0.9093059,1.457499 1.5782589,1.457499 0,0 8.830403,-0.01705 8.830403,-0.01705 0.488364,-5.91e-4 0.922857,0.221532 1.080466,0.683755 0.15761,0.462231 0.0033,0.53156 -0.383664,0.829439 0,0 -15.9006939,12.205735 -15.9006939,12.205735 -0.00142,0.0014 -0.00284,0.0028 -0.00426,0.0043 -0.064038,0.04879 -0.084772,0.06226 -0.061795,0.04476 -0.5536756,0.424618 -0.8961097,0.98072 -1.0185711,1.476701 -0.1224537,0.495981 -0.04659,0.882548 0.1875202,1.182646 0.4788333,0.613413 1.7693735,0.732111 2.8980115,-0.178996 0,0 8.6727243,-7.09799 8.6727243,-7.09799 0.361955,-0.295752 0.867758,-0.340606 1.276111,-0.113169 0.408345,0.227437 0.636512,0.681082 0.575631,1.144518 0,0 -0.112502,0.980045 -0.10655,1.370159 0.192357,2.636407 1.448328,4.914995 3.115366,6.91474 2.877746,3.172809 6.84939,4.556285 11.042271,4.719919 4.20342,-0.04394 8.185784,-1.662428 11.042264,-4.758277 5.218918,-6.385867 3.941737,-13.3639 -1.747326,-17.993227 C 36.14442,13.301598 31.42752,9.8792062 26.81986,6.3400589 c -0.0043,-0.00352 -0.0086,-0.00707 -0.01279,-0.010651 -0.0072,-0.00489 -0.01427,-0.00987 -0.02131,-0.014921 -0.210578,-0.1612288 -0.584681,-0.288267 -0.988772,-0.2877065 z"
- style="opacity:0.4857143;fill:none;stroke:url(#linearGradient34576);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
- <path
- d="m 26.007076,24.754048 c 0.07447,-1.361157 0.739293,-2.562655 1.738705,-3.413271 0.983518,-0.836183 2.304215,-1.346747 3.746876,-1.346747 1.441743,0 2.762441,0.510564 3.745729,1.346747 1.000515,0.850616 1.664539,2.051213 1.739875,3.41237 0.07718,1.400852 -0.4828,2.701576 -1.46425,3.66495 -1.000516,0.981409 -2.427099,1.597503 -4.021354,1.597503 -1.595172,0 -3.021756,-0.616094 -4.022225,-1.597503 -0.982461,-0.963374 -1.540507,-2.264098 -1.463356,-3.664049 z"
- id="path2478"
- style="fill:#3465a4;fill-rule:evenodd;stroke:none"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc"
- id="path39166"
- d="m 25.8125,6.03125 c -0.404852,5.528e-4 -0.848347,0.1185677 -1.125,0.3125 -0.280209,0.1956523 -0.335403,0.3764836 -0.34375,0.46875 -0.0083,0.092267 -0.01539,0.1764801 0.1875,0.34375 0.01899,0.015735 0.04457,0.014317 0.0625,0.03125 0.124258,0.1010283 5.71875,4.65625 5.71875,4.65625 0.373658,0.304091 0.504393,0.795817 0.34375,1.25 -0.160635,0.454191 -0.580748,0.373449 -1.0625,0.375 -5.634142,0.05114 -17.625,0.03125 -17.625,0.03125 -0.952967,6.38e-4 -2.3399576,0.524782 -2.40625,1.59375 -0.063562,1.024947 0.924797,1.4375 1.59375,1.4375 0,-1e-6 8.8125,0 8.8125,0 0.488364,-5.92e-4 0.936141,0.225277 1.09375,0.6875 0.157609,0.462231 -0.01926,0.514621 -0.40625,0.8125 0,0 -15.875,12.21875 -15.875,12.21875 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.777612,0.754857 2.90625,-0.15625 1e-7,10e-7 8.65625,-7.09375 8.65625,-7.09375 0.361955,-0.295753 0.872897,-0.352437 1.28125,-0.125 0.408345,0.227436 0.623381,0.692814 0.5625,1.15625 0,-1e-6 -0.0997,0.953636 -0.09375,1.34375 0.09498,1.301756 0.451616,2.521825 0.989039,3.664234 C 20.799917,36.321089 27.770982,19.392853 44.1875,21.03125 43.339652,19.54368 42.151282,18.185293 40.65625,16.96875 36.159865,13.309932 31.42016,9.8828973 26.8125,6.34375 26.805335,6.3388584 26.788292,6.317553 26.78125,6.3125 26.570707,6.1513121 26.216591,6.0306895 25.8125,6.03125 z"
- style="opacity:0.51999996;fill:url(#radialGradient39177);fill-opacity:1;fill-rule:evenodd;stroke:none"
- inkscape:connector-curvature="0" />
- </g>
- </g>
-</svg>
diff --git a/release/freedesktop/icons/24x24/apps/blender.png b/release/freedesktop/icons/24x24/apps/blender.png
new file mode 100644
index 00000000000..86e8248e786
--- /dev/null
+++ b/release/freedesktop/icons/24x24/apps/blender.png
Binary files differ
diff --git a/release/freedesktop/icons/256x256/apps/blender.png b/release/freedesktop/icons/256x256/apps/blender.png
new file mode 100644
index 00000000000..117c25a5ab4
--- /dev/null
+++ b/release/freedesktop/icons/256x256/apps/blender.png
Binary files differ
diff --git a/release/freedesktop/icons/32x32/apps/blender.png b/release/freedesktop/icons/32x32/apps/blender.png
new file mode 100644
index 00000000000..8af71e4f382
--- /dev/null
+++ b/release/freedesktop/icons/32x32/apps/blender.png
Binary files differ
diff --git a/release/freedesktop/icons/32x32/blender.png b/release/freedesktop/icons/32x32/blender.png
deleted file mode 100644
index 6426ade96b6..00000000000
--- a/release/freedesktop/icons/32x32/blender.png
+++ /dev/null
Binary files differ
diff --git a/release/freedesktop/icons/32x32/blender.svg b/release/freedesktop/icons/32x32/blender.svg
deleted file mode 100644
index 030d551699b..00000000000
--- a/release/freedesktop/icons/32x32/blender.svg
+++ /dev/null
@@ -1,250 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
- xmlns:dc="http://purl.org/dc/elements/1.1/"
- xmlns:cc="http://creativecommons.org/ns#"
- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
- xmlns:svg="http://www.w3.org/2000/svg"
- xmlns="http://www.w3.org/2000/svg"
- xmlns:xlink="http://www.w3.org/1999/xlink"
- xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="32"
- height="32"
- id="svg7854"
- sodipodi:version="0.32"
- inkscape:version="0.48.0 r9654"
- version="1.0"
- sodipodi:docname="blender.svg"
- inkscape:output_extension="org.inkscape.output.svg.inkscape"
- sodipodi:modified="true"
- inkscape:export-filename="/home/user/my/blender/builds/blender/release/freedesktop/icons/32x32/blender.png"
- inkscape:export-xdpi="90"
- inkscape:export-ydpi="90">
- <defs
- id="defs7856">
- <linearGradient
- inkscape:collect="always"
- id="linearGradient39171">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop39173" />
- <stop
- style="stop-color:white;stop-opacity:0;"
- offset="1"
- id="stop39175" />
- </linearGradient>
- <linearGradient
- id="linearGradient39155">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop39157" />
- <stop
- style="stop-color:#dadada;stop-opacity:1;"
- offset="1"
- id="stop39159" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient35500">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop35502" />
- <stop
- style="stop-color:white;stop-opacity:0;"
- offset="1"
- id="stop35504" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient35488">
- <stop
- style="stop-color:black;stop-opacity:1;"
- offset="0"
- id="stop35490" />
- <stop
- style="stop-color:black;stop-opacity:0;"
- offset="1"
- id="stop35492" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- id="linearGradient3564">
- <stop
- style="stop-color:white;stop-opacity:1;"
- offset="0"
- id="stop3566" />
- <stop
- style="stop-color:white;stop-opacity:0;"
- offset="1"
- id="stop3568" />
- </linearGradient>
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient3564"
- id="linearGradient34576"
- gradientUnits="userSpaceOnUse"
- x1="185.9903"
- y1="193.33229"
- x2="190.46461"
- y2="-458.05771"
- gradientTransform="matrix(0.06818845,0,0,0.06818845,22.51112,27.02885)" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient35488"
- id="radialGradient35494"
- cx="28.019106"
- cy="38.98439"
- fx="28.019106"
- fy="38.98439"
- r="15.467961"
- gradientTransform="matrix(1,0,0,0.342857,0,25.61831)"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient35500"
- id="linearGradient35506"
- x1="21.204315"
- y1="21.699249"
- x2="20.155914"
- y2="-26.908371"
- gradientUnits="userSpaceOnUse" />
- <linearGradient
- inkscape:collect="always"
- xlink:href="#linearGradient39155"
- id="linearGradient39161"
- x1="31.1875"
- y1="18.875"
- x2="29.875"
- y2="34.375"
- gradientUnits="userSpaceOnUse" />
- <radialGradient
- inkscape:collect="always"
- xlink:href="#linearGradient39171"
- id="radialGradient39177"
- cx="26.109201"
- cy="19.668886"
- fx="26.109201"
- fy="19.668886"
- r="20.278975"
- gradientTransform="matrix(1.647222,0,0,1.26792,-15.47413,-5.79794)"
- gradientUnits="userSpaceOnUse" />
- </defs>
- <sodipodi:namedview
- id="base"
- pagecolor="#ffffff"
- bordercolor="#e0e0e0"
- borderopacity="1"
- gridtolerance="10000"
- guidetolerance="10"
- objecttolerance="10"
- inkscape:pageopacity="0.0"
- inkscape:pageshadow="2"
- inkscape:zoom="8.1228891"
- inkscape:cx="39.360762"
- inkscape:cy="28.503541"
- inkscape:document-units="px"
- inkscape:current-layer="layer1"
- width="48px"
- height="48px"
- inkscape:showpageshadow="false"
- inkscape:window-width="1392"
- inkscape:window-height="976"
- inkscape:window-x="0"
- inkscape:window-y="0"
- showgrid="false"
- inkscape:window-maximized="1" />
- <metadata
- id="metadata7859">
- <rdf:RDF>
- <cc:Work
- rdf:about="">
- <dc:format>image/svg+xml</dc:format>
- <dc:type
- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:creator>
- <cc:Agent>
- <dc:title>Jakub Steiner</dc:title>
- </cc:Agent>
- </dc:creator>
- <dc:source>http://jimmac.musichall.cz</dc:source>
- <cc:license
- rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
- <dc:title></dc:title>
- </cc:Work>
- <cc:License
- rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
- <cc:permits
- rdf:resource="http://web.resource.org/cc/Reproduction" />
- <cc:permits
- rdf:resource="http://web.resource.org/cc/Distribution" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/Notice" />
- <cc:permits
- rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/ShareAlike" />
- <cc:requires
- rdf:resource="http://web.resource.org/cc/SourceCode" />
- </cc:License>
- </rdf:RDF>
- </metadata>
- <g
- inkscape:label="Layer 1"
- inkscape:groupmode="layer"
- id="layer1"
- transform="translate(0,-16)">
- <g
- id="blender"
- transform="matrix(0.65782075,0,0,0.65782075,-0.38501735,15.782256)"
- inkscape:label="blender">
- <path
- transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)"
- d="m 43.487067,38.98439 c 0,2.928932 -6.925242,5.303301 -15.467961,5.303301 -8.542719,0 -15.467961,-2.374369 -15.467961,-5.303301 0,-2.928932 6.925242,-5.303301 15.467961,-5.303301 8.542719,0 15.467961,2.374369 15.467961,5.303301 z"
- sodipodi:ry="5.3033009"
- sodipodi:rx="15.467961"
- sodipodi:cy="38.98439"
- sodipodi:cx="28.019106"
- id="path35486"
- style="opacity:0.54857142;color:#000000;fill:url(#radialGradient35494);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- sodipodi:nodetypes="csssssssssscccsscccscccssccc"
- d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -2.434775,-0.6939758 -3.431728,0.00488 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 3.792068,3.0680399 5.702368,4.5676189 0,0 -17.551681,-0.01171 -17.551681,-0.01171 -1.994685,0 -3.1682604,0.947915 -3.4153942,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800212,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -15.901723,11.764162 -15.901723,11.764162 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.677593,-7.102098 8.677593,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 z"
- id="path2482"
- style="fill:#f57900;fill-rule:evenodd;stroke:#ce5c00;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
- <path
- transform="matrix(0.821621,0,0,0.839506,5.875686,3.882724)"
- d="m 42.75,25.75 c 0,5.591883 -5.176708,10.125 -11.5625,10.125 -6.385792,0 -11.5625,-4.533117 -11.5625,-10.125 0,-5.591883 5.176708,-10.125 11.5625,-10.125 6.385792,0 11.5625,4.533117 11.5625,10.125 z"
- sodipodi:ry="10.125"
- sodipodi:rx="11.5625"
- sodipodi:cy="25.75"
- sodipodi:cx="31.1875"
- id="path39153"
- style="color:#000000;fill:url(#linearGradient39161);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
- sodipodi:type="arc" />
- <path
- sodipodi:nodetypes="cssssscscczccsccssssccscccccscssc"
- id="path3562"
- d="m 25.796988,6.0267804 c -0.404852,5.53e-4 -0.818619,0.1256944 -1.095272,0.3196267 -7.14e-4,7.142e-4 -0.0014,0.00143 -0.0021,0.00213 -0.280209,0.1956525 -0.336859,0.3680061 -0.345206,0.4602725 -0.0083,0.092266 -0.01324,0.1672776 0.189655,0.3345475 0.01899,0.015735 0.03747,0.032076 0.0554,0.049009 0.124258,0.1010285 5.704394,4.6389489 5.704394,4.6389489 0.373658,0.304091 0.51584,0.810232 0.355197,1.264415 -0.160635,0.454191 -0.589422,0.382732 -1.071174,0.384283 -5.634142,0.05114 -17.60967,0.01918 -17.60967,0.01918 -0.952967,6.38e-4 -2.3472795,0.516793 -2.4135719,1.585761 -0.063562,1.024947 0.9093059,1.457499 1.5782589,1.457499 0,0 8.830403,-0.01705 8.830403,-0.01705 0.488364,-5.91e-4 0.922857,0.221532 1.080466,0.683755 0.15761,0.462231 0.0033,0.53156 -0.383664,0.829439 0,0 -15.9006939,12.205735 -15.9006939,12.205735 -0.00142,0.0014 -0.00284,0.0028 -0.00426,0.0043 -0.064038,0.04879 -0.084772,0.06226 -0.061795,0.04476 -0.5536756,0.424618 -0.8961097,0.98072 -1.0185711,1.476701 -0.1224537,0.495981 -0.04659,0.882548 0.1875202,1.182646 0.4788333,0.613413 1.7693735,0.732111 2.8980115,-0.178996 0,0 8.6727243,-7.09799 8.6727243,-7.09799 0.361955,-0.295752 0.867758,-0.340606 1.276111,-0.113169 0.408345,0.227437 0.636512,0.681082 0.575631,1.144518 0,0 -0.112502,0.980045 -0.10655,1.370159 0.192357,2.636407 1.448328,4.914995 3.115366,6.91474 2.877746,3.172809 6.84939,4.556285 11.042271,4.719919 4.20342,-0.04394 8.185784,-1.662428 11.042264,-4.758277 5.218918,-6.385867 3.941737,-13.3639 -1.747326,-17.993227 C 36.14442,13.301598 31.42752,9.8792062 26.81986,6.3400589 c -0.0043,-0.00352 -0.0086,-0.00707 -0.01279,-0.010651 -0.0072,-0.00489 -0.01427,-0.00987 -0.02131,-0.014921 -0.210578,-0.1612288 -0.584681,-0.288267 -0.988772,-0.2877065 z"
- style="opacity:0.4857143;fill:none;stroke:url(#linearGradient34576);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
- inkscape:connector-curvature="0" />
- <path
- d="m 26.007076,24.754048 c 0.07447,-1.361157 0.739293,-2.562655 1.738705,-3.413271 0.983518,-0.836183 2.304215,-1.346747 3.746876,-1.346747 1.441743,0 2.762441,0.510564 3.745729,1.346747 1.000515,0.850616 1.664539,2.051213 1.739875,3.41237 0.07718,1.400852 -0.4828,2.701576 -1.46425,3.66495 -1.000516,0.981409 -2.427099,1.597503 -4.021354,1.597503 -1.595172,0 -3.021756,-0.616094 -4.022225,-1.597503 -0.982461,-0.963374 -1.540507,-2.264098 -1.463356,-3.664049 z"
- id="path2478"
- style="fill:#3465a4;fill-rule:evenodd;stroke:none"
- inkscape:connector-curvature="0" />
- <path
- sodipodi:nodetypes="csssscsccsscsccssssscsscccsssc"
- id="path39166"
- d="m 25.8125,6.03125 c -0.404852,5.528e-4 -0.848347,0.1185677 -1.125,0.3125 -0.280209,0.1956523 -0.335403,0.3764836 -0.34375,0.46875 -0.0083,0.092267 -0.01539,0.1764801 0.1875,0.34375 0.01899,0.015735 0.04457,0.014317 0.0625,0.03125 0.124258,0.1010283 5.71875,4.65625 5.71875,4.65625 0.373658,0.304091 0.504393,0.795817 0.34375,1.25 -0.160635,0.454191 -0.580748,0.373449 -1.0625,0.375 -5.634142,0.05114 -17.625,0.03125 -17.625,0.03125 -0.952967,6.38e-4 -2.3399576,0.524782 -2.40625,1.59375 -0.063562,1.024947 0.924797,1.4375 1.59375,1.4375 0,-1e-6 8.8125,0 8.8125,0 0.488364,-5.92e-4 0.936141,0.225277 1.09375,0.6875 0.157609,0.462231 -0.01926,0.514621 -0.40625,0.8125 0,0 -15.875,12.21875 -15.875,12.21875 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.777612,0.754857 2.90625,-0.15625 1e-7,10e-7 8.65625,-7.09375 8.65625,-7.09375 0.361955,-0.295753 0.872897,-0.352437 1.28125,-0.125 0.408345,0.227436 0.623381,0.692814 0.5625,1.15625 0,-1e-6 -0.0997,0.953636 -0.09375,1.34375 0.09498,1.301756 0.451616,2.521825 0.989039,3.664234 C 20.799917,36.321089 27.770982,19.392853 44.1875,21.03125 43.339652,19.54368 42.151282,18.185293 40.65625,16.96875 36.159865,13.309932 31.42016,9.8828973 26.8125,6.34375 26.805335,6.3388584 26.788292,6.317553 26.78125,6.3125 26.570707,6.1513121 26.216591,6.0306895 25.8125,6.03125 z"
- style="opacity:0.51999996;fill:url(#radialGradient39177);fill-opacity:1;fill-rule:evenodd;stroke:none"
- inkscape:connector-curvature="0" />
- </g>
- </g>
-</svg>
diff --git a/release/freedesktop/icons/blender_icon_source.svg b/release/freedesktop/icons/blender_icon_source.svg
new file mode 100644
index 00000000000..362536d8fd8
--- /dev/null
+++ b/release/freedesktop/icons/blender_icon_source.svg
@@ -0,0 +1,855 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ inkscape:export-ydpi="90.000000"
+ inkscape:export-xdpi="90.000000"
+ inkscape:export-filename="/home/jimmac/Desktop/wi-fi.png"
+ width="400"
+ height="300"
+ id="svg11300"
+ sodipodi:version="0.32"
+ inkscape:version="0.48.1 r9760"
+ sodipodi:docname="blender.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ version="1.0"
+ style="enable-background:new">
+ <sodipodi:namedview
+ stroke="#ef2929"
+ fill="#f57900"
+ id="base"
+ pagecolor="#474747"
+ bordercolor="#666666"
+ borderopacity="0.25490196"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="102.02872"
+ inkscape:cy="157.85704"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:grid-bbox="true"
+ inkscape:document-units="px"
+ inkscape:showpageshadow="false"
+ inkscape:window-width="1278"
+ inkscape:window-height="973"
+ inkscape:window-x="1906"
+ inkscape:window-y="126"
+ width="400px"
+ height="300px"
+ inkscape:snap-nodes="false"
+ inkscape:snap-bbox="true"
+ inkscape:window-maximized="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid5883"
+ spacingx="1px"
+ spacingy="1px" />
+ </sodipodi:namedview>
+ <defs
+ id="defs3">
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient9792">
+ <stop
+ style="stop-color:#1064aa;stop-opacity:1"
+ offset="0"
+ id="stop9794" />
+ <stop
+ style="stop-color:#0d528b;stop-opacity:1"
+ offset="1"
+ id="stop9796" />
+ </linearGradient>
+ <inkscape:perspective
+ id="perspective105"
+ inkscape:persp3d-origin="300 : 400 : 1"
+ inkscape:vp_z="700 : 600 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="-50 : 600 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective5151"
+ inkscape:persp3d-origin="300 : 400 : 1"
+ inkscape:vp_z="700 : 600 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="-50 : 600 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ inkscape:persp3d-origin="300 : 400 : 1"
+ inkscape:vp_z="700 : 600 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="-50 : 600 : 1"
+ id="perspective103"
+ sodipodi:type="inkscape:persp3d" />
+ <linearGradient
+ id="linearGradient5457"
+ inkscape:collect="always">
+ <stop
+ id="stop5459"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop5461"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5447"
+ inkscape:collect="always">
+ <stop
+ id="stop5449"
+ offset="0"
+ style="stop-color:#ff830a;stop-opacity:1" />
+ <stop
+ id="stop5451"
+ offset="1"
+ style="stop-color:#d06700;stop-opacity:1" />
+ </linearGradient>
+ <inkscape:perspective
+ inkscape:persp3d-origin="300 : 400 : 1"
+ inkscape:vp_z="700 : 600 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="-50 : 600 : 1"
+ id="perspective91"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ inkscape:persp3d-origin="300 : 400 : 1"
+ inkscape:vp_z="700 : 600 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="-50 : 600 : 1"
+ id="perspective90"
+ sodipodi:type="inkscape:persp3d" />
+ <linearGradient
+ id="linearGradient6160"
+ inkscape:collect="always">
+ <stop
+ id="stop6162"
+ offset="0"
+ style="stop-color:#eeeeec;stop-opacity:1;" />
+ <stop
+ id="stop6164"
+ offset="1"
+ style="stop-color:#eeeeec;stop-opacity:0;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient6115"
+ inkscape:collect="always">
+ <stop
+ id="stop6117"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop6119"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:0;" />
+ </linearGradient>
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient39171"
+ id="radialGradient39177"
+ cx="26.109201"
+ cy="19.668886"
+ fx="26.109201"
+ fy="19.668886"
+ r="20.278975"
+ gradientTransform="matrix(1.647222,0,0,1.26792,-15.47413,-5.79794)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient39155"
+ id="linearGradient39161"
+ x1="31.1875"
+ y1="18.875"
+ x2="29.875"
+ y2="34.375"
+ gradientUnits="userSpaceOnUse" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient35488"
+ id="radialGradient35494"
+ cx="28.019106"
+ cy="38.98439"
+ fx="28.019106"
+ fy="38.98439"
+ r="15.467961"
+ gradientTransform="matrix(1,0,0,0.342857,0,25.61831)"
+ gradientUnits="userSpaceOnUse" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3564"
+ id="linearGradient34576"
+ gradientUnits="userSpaceOnUse"
+ x1="185.9903"
+ y1="193.33229"
+ x2="106.04736"
+ y2="-134.32658"
+ gradientTransform="matrix(6.818845e-2,0,0,6.818845e-2,22.51112,27.02885)" />
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient3564">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop3566" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop3568" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient35488">
+ <stop
+ style="stop-color:black;stop-opacity:1;"
+ offset="0"
+ id="stop35490" />
+ <stop
+ style="stop-color:black;stop-opacity:0;"
+ offset="1"
+ id="stop35492" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient39155">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop39157" />
+ <stop
+ style="stop-color:#dadada;stop-opacity:1;"
+ offset="1"
+ id="stop39159" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient39171">
+ <stop
+ style="stop-color:white;stop-opacity:1;"
+ offset="0"
+ id="stop39173" />
+ <stop
+ style="stop-color:white;stop-opacity:0;"
+ offset="1"
+ id="stop39175" />
+ </linearGradient>
+ <radialGradient
+ r="15.467961"
+ fy="40.303635"
+ fx="28.915268"
+ cy="40.303635"
+ cx="28.915268"
+ gradientTransform="matrix(1,0,0,0.342857,0,25.61831)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient5348"
+ xlink:href="#linearGradient35488"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="34.375"
+ x2="29.875"
+ y1="18.875"
+ x1="31.1875"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient5350"
+ xlink:href="#linearGradient39155"
+ inkscape:collect="always" />
+ <radialGradient
+ r="15.467961"
+ fy="38.98439"
+ fx="28.019106"
+ cy="38.98439"
+ cx="28.019106"
+ gradientTransform="matrix(1,0,0,0.342857,0,25.61831)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient5444"
+ xlink:href="#linearGradient35488"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="34.375"
+ x2="29.875"
+ y1="18.875"
+ x1="31.1875"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient5446"
+ xlink:href="#linearGradient39155"
+ inkscape:collect="always" />
+ <linearGradient
+ y2="-247.19307"
+ x2="-71.578575"
+ y1="43.460403"
+ x1="2.813544"
+ gradientTransform="matrix(6.818845e-2,0,0,6.818845e-2,22.51112,27.02885)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient5448"
+ xlink:href="#linearGradient3564"
+ inkscape:collect="always" />
+ <radialGradient
+ r="20.278975"
+ fy="19.668886"
+ fx="26.109201"
+ cy="19.668886"
+ cx="26.109201"
+ gradientTransform="matrix(1.647222,0,0,1.26792,-15.47413,-5.79794)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient5450"
+ xlink:href="#linearGradient39171"
+ inkscape:collect="always" />
+ <radialGradient
+ r="15.467961"
+ fy="38.98439"
+ fx="28.019106"
+ cy="38.98439"
+ cx="28.019106"
+ gradientTransform="matrix(1,0,0,0.342857,0,25.61831)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient5482"
+ xlink:href="#linearGradient35488"
+ inkscape:collect="always" />
+ <filter
+ height="1.60714"
+ y="-0.30357"
+ width="1.2081623"
+ x="-0.10408114"
+ id="filter6077"
+ inkscape:collect="always">
+ <feGaussianBlur
+ id="feGaussianBlur6079"
+ stdDeviation="1.3416025"
+ inkscape:collect="always" />
+ </filter>
+ <clipPath
+ id="clipPath6085"
+ clipPathUnits="userSpaceOnUse">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#954900;stroke-width:0.2076302;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path6087"
+ d="M 16.048489,28.093447 C 16.058272,28.670129 16.244963,29.791349 16.519605,30.670872 C 17.101171,32.525009 18.086445,34.24353 19.458731,35.757368 C 20.866219,37.310486 22.59725,38.560595 24.598046,39.447128 C 26.703403,40.378701 28.982841,40.854616 31.34818,40.850869 C 33.713519,40.845862 35.992781,40.362183 38.09714,39.423852 C 40.09716,38.528564 41.828183,37.275461 43.23468,35.718335 C 44.603887,34.198491 45.587256,32.477221 46.168769,30.622077 C 46.463031,29.683724 46.64569,28.732685 46.722007,27.776769 C 46.795321,26.837463 46.764043,25.893258 46.630178,24.952977 C 46.370197,23.117378 45.733884,21.39613 44.757526,19.825397 C 43.861985,18.383698 42.709718,17.120857 41.340258,16.058422 C 41.340258,16.058422 41.342254,16.05644 41.342254,16.05644 C 41.342254,16.05644 27.513796,5.4367205 27.513796,5.4367205 C 27.502032,5.4269448 27.491273,5.4171691 27.47851,5.4083763 C 26.569507,4.7124499 25.043735,4.7144005 24.046782,5.4132603 C 23.036112,6.1189624 22.954961,7.2225216 23.851255,7.9614749 C 25.75103,9.4612382 27.643323,11.029515 29.553623,12.529094 C 29.553623,12.529094 12.001942,12.517388 12.001942,12.517388 C 10.007257,12.517388 8.8336816,13.465303 8.5865478,14.851071 C 8.3684707,16.073907 9.3344691,17.5892 11.066569,17.5892 C 14.023142,17.593062 17.00868,17.582341 19.975784,17.576483 C 19.975784,17.576483 4.074061,29.340645 4.074061,29.340645 C 4.0535343,29.356288 4.0330076,29.369972 4.0124809,29.385615 C 2.5150612,30.534004 2.0292858,32.444937 2.9725001,33.654008 C 3.9323324,34.883598 5.9702654,34.884596 7.4872289,33.660013 C 7.4872289,33.660013 16.164822,26.557915 16.164822,26.557915 C 16.164822,26.557915 16.039712,27.517739 16.048489,28.093447 z"
+ sodipodi:nodetypes="csssssssssscccsscccscccssccc" />
+ </clipPath>
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.8055409,0,4.4643372)"
+ r="21.275852"
+ fy="44.23357"
+ fx="34.8689"
+ cy="44.23357"
+ cx="34.8689"
+ id="radialGradient6101"
+ xlink:href="#linearGradient3564"
+ inkscape:collect="always" />
+ <filter
+ id="filter6103"
+ inkscape:collect="always">
+ <feGaussianBlur
+ id="feGaussianBlur6105"
+ stdDeviation="0.19207211"
+ inkscape:collect="always" />
+ </filter>
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,0.8095091,0,4.3545041)"
+ r="21.804204"
+ fy="13.112802"
+ fx="22.436661"
+ cy="13.112802"
+ cx="22.436661"
+ id="radialGradient6121"
+ xlink:href="#linearGradient6115"
+ inkscape:collect="always" />
+ <filter
+ id="filter6127"
+ inkscape:collect="always">
+ <feGaussianBlur
+ id="feGaussianBlur6129"
+ stdDeviation="0.098637264"
+ inkscape:collect="always" />
+ </filter>
+ <filter
+ id="filter6156"
+ inkscape:collect="always">
+ <feGaussianBlur
+ id="feGaussianBlur6158"
+ stdDeviation="0.93085205"
+ inkscape:collect="always" />
+ </filter>
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.1062168,0,0,0.7160758,-16.531813,35.180186)"
+ r="113.01414"
+ fy="58.663204"
+ fx="155.64211"
+ cy="58.663204"
+ cx="155.64211"
+ id="radialGradient6166"
+ xlink:href="#linearGradient6160"
+ inkscape:collect="always" />
+ <radialGradient
+ r="20.278975"
+ fy="16.789225"
+ fx="26.441687"
+ cy="16.789225"
+ cx="26.441687"
+ gradientTransform="matrix(1.647222,0,0,1.26792,-15.47413,-5.79794)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient6168"
+ xlink:href="#linearGradient39171"
+ inkscape:collect="always" />
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.6103065,0,0,1.308109,-19.819726,-14.288347)"
+ r="22.135636"
+ fy="37.477009"
+ fx="32.475037"
+ cy="37.477009"
+ cx="32.475037"
+ id="radialGradient5453"
+ xlink:href="#linearGradient5447"
+ inkscape:collect="always" />
+ <radialGradient
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.0461723,0,0,2.2699636,-34.350196,-238.66924)"
+ r="7.4158326"
+ fy="188.28326"
+ fx="32.834167"
+ cy="188.28326"
+ cx="32.834167"
+ id="radialGradient5463"
+ xlink:href="#linearGradient5457"
+ inkscape:collect="always" />
+ <filter
+ height="1.348965"
+ y="-0.17448251"
+ width="1.3871316"
+ x="-0.19356578"
+ id="filter5489"
+ inkscape:collect="always">
+ <feGaussianBlur
+ id="feGaussianBlur5491"
+ stdDeviation="1.1962095"
+ inkscape:collect="always" />
+ </filter>
+ <filter
+ id="filter5467"
+ inkscape:collect="always">
+ <feGaussianBlur
+ id="feGaussianBlur5469"
+ stdDeviation="0.20058598"
+ inkscape:collect="always" />
+ </filter>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ id="perspective18062" />
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ id="perspective19694" />
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ id="perspective19708" />
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ id="perspective19722" />
+ <radialGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient9792"
+ id="radialGradient9798"
+ cx="31.857779"
+ cy="22.970091"
+ fx="31.857779"
+ fy="22.970091"
+ r="5.8577784"
+ gradientTransform="matrix(1.2493214,0,0,0.91226922,-7.942827,2.2083028)"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <metadata
+ id="metadata4">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Jakub Steiner</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ <dc:source>http://jimmac.musichall.cz</dc:source>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" />
+ <dc:title>Folder</dc:title>
+ <dc:subject>
+ <rdf:Bag>
+ <rdf:li>dir</rdf:li>
+ <rdf:li>folder</rdf:li>
+ </rdf:Bag>
+ </dc:subject>
+ <dc:date />
+ <dc:rights>
+ <cc:Agent>
+ <dc:title />
+ </cc:Agent>
+ </dc:rights>
+ <dc:publisher>
+ <cc:Agent>
+ <dc:title />
+ </cc:Agent>
+ </dc:publisher>
+ <dc:identifier />
+ <dc:relation />
+ <dc:language />
+ <dc:coverage />
+ <dc:description />
+ <dc:contributor>
+ <cc:Agent>
+ <dc:title />
+ </cc:Agent>
+ </dc:contributor>
+ </cc:Work>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/by-sa/3.0/">
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" />
+ <cc:requires
+ rdf:resource="http://creativecommons.org/ns#Notice" />
+ <cc:requires
+ rdf:resource="http://creativecommons.org/ns#Attribution" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://creativecommons.org/ns#ShareAlike" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="baseplate"
+ style="display:none">
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6282"
+ width="256"
+ height="256"
+ x="20"
+ y="20"
+ inkscape:label="256x256" />
+ <rect
+ inkscape:label="48x48"
+ y="39.99633"
+ x="296.0625"
+ height="48"
+ width="48"
+ id="rect6284"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6592"
+ width="32"
+ height="32"
+ x="303"
+ y="115.99633"
+ inkscape:label="32x32" />
+ <rect
+ inkscape:label="22x22"
+ y="167.05884"
+ x="303"
+ height="22"
+ width="22"
+ id="rect6749"
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect6833"
+ width="16"
+ height="16"
+ x="303"
+ y="209"
+ inkscape:label="16x16" />
+ <rect
+ style="fill:#eeeeec;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="rect5028"
+ width="24"
+ height="24"
+ x="301.95709"
+ y="165.95343"
+ inkscape:label="24x24" />
+ <text
+ inkscape:label="context"
+ sodipodi:linespacing="125%"
+ id="context"
+ y="-18.999996"
+ x="21"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Trebuchet MS;-inkscape-font-specification:Trebuchet MS"
+ xml:space="preserve"><tspan
+ y="-18.999996"
+ x="21"
+ id="tspan16843"
+ sodipodi:role="line">apps</tspan></text>
+ <text
+ inkscape:label="icon-name"
+ sodipodi:linespacing="125%"
+ id="icon-name"
+ y="-18.999996"
+ x="159"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Trebuchet MS;-inkscape-font-specification:Trebuchet MS"
+ xml:space="preserve"><tspan
+ y="-18.999996"
+ x="159"
+ id="tspan16847"
+ sodipodi:role="line">blender</tspan></text>
+ </g>
+ <g
+ id="layer1"
+ inkscape:label="artwork"
+ inkscape:groupmode="layer"
+ style="display:inline">
+ <g
+ transform="translate(294.96666,38.974759)"
+ inkscape:label="Layer 1"
+ id="g5323">
+ <g
+ id="g4390">
+ <path
+ transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)"
+ d="m 43.487067,38.98439 c 0,2.928932 -6.925242,5.303301 -15.467961,5.303301 -8.542719,0 -15.467961,-2.374369 -15.467961,-5.303301 0,-2.928932 6.925242,-5.303301 15.467961,-5.303301 8.542719,0 15.467961,2.374369 15.467961,5.303301 z"
+ sodipodi:ry="5.3033009"
+ sodipodi:rx="15.467961"
+ sodipodi:cy="38.98439"
+ sodipodi:cx="28.019106"
+ id="path35486"
+ style="opacity:0.54857142;fill:url(#radialGradient35494);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:nodetypes="csssssssssscccsscccscccssccc"
+ d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -2.434775,-0.6939758 -3.431728,0.00488 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 3.792068,3.0680401 5.702368,4.5676191 0,0 -17.551681,-0.01171 -17.551681,-0.01171 -1.994685,0 -3.1682604,0.947915 -3.4153942,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800212,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -15.901723,11.764162 -15.901723,11.764162 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.6775931,-7.102098 8.6775931,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 z"
+ id="path2482"
+ style="fill:#f57900;fill-rule:evenodd;stroke:#ce5c00;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none" />
+ <path
+ transform="matrix(0.821621,0,0,0.839506,5.875686,3.882724)"
+ d="m 42.75,25.75 c 0,5.591883 -5.176708,10.125 -11.5625,10.125 -6.385792,0 -11.5625,-4.533117 -11.5625,-10.125 0,-5.591883 5.176708,-10.125 11.5625,-10.125 6.385792,0 11.5625,4.533117 11.5625,10.125 z"
+ sodipodi:ry="10.125"
+ sodipodi:rx="11.5625"
+ sodipodi:cy="25.75"
+ sodipodi:cx="31.1875"
+ id="path39153"
+ style="fill:url(#linearGradient39161);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:nodetypes="cssssscscczccsccssssccscccccscssc"
+ id="path3562"
+ d="m 25.796988,6.0267804 c -0.404852,5.53e-4 -0.818619,0.1256944 -1.095272,0.3196267 -7.14e-4,7.142e-4 -0.0014,0.00143 -0.0021,0.00213 -0.280209,0.1956525 -0.336859,0.3680061 -0.345206,0.4602725 -0.0083,0.092266 -0.01324,0.1672776 0.189655,0.3345475 0.01899,0.015735 0.03747,0.032076 0.0554,0.049009 0.124258,0.1010285 5.704394,4.6389488 5.704394,4.6389488 0.373658,0.304091 0.51584,0.810232 0.355197,1.264415 -0.160635,0.454191 -0.589422,0.382732 -1.071174,0.384283 -5.634142,0.05114 -17.60967,0.01918 -17.60967,0.01918 -0.952967,6.38e-4 -2.3472795,0.516793 -2.4135719,1.585761 -0.063562,1.024947 0.9093059,1.457499 1.5782589,1.457499 0,0 8.830403,-0.01705 8.830403,-0.01705 0.488364,-5.91e-4 0.922857,0.221532 1.080466,0.683755 0.15761,0.462231 0.0033,0.53156 -0.383664,0.829439 0,0 -15.9006939,12.205735 -15.9006939,12.205735 -0.00142,0.0014 -0.00284,0.0028 -0.00426,0.0043 -0.064038,0.04879 -0.084772,0.06226 -0.061795,0.04476 -0.5536756,0.424618 -0.8961097,0.98072 -1.0185711,1.476701 -0.1224537,0.495981 -0.04659,0.882548 0.1875202,1.182646 0.4788333,0.613413 1.8577618,0.820499 2.9863998,-0.09061 0,0 8.6727241,-7.09799 8.6727241,-7.09799 0.361955,-0.295752 0.77937,-0.340606 1.187723,-0.113169 0.408345,0.227437 0.548124,0.592694 0.487243,1.05613 0,0 -0.112502,0.980045 -0.10655,1.370159 0.192357,2.636407 1.448328,5.003383 3.115366,7.003128 2.877746,3.172809 6.937778,4.644674 11.130659,4.808308 4.20342,-0.04394 8.318367,-1.795011 11.174847,-4.89086 5.218918,-6.385867 3.809154,-13.408094 -1.879909,-18.037421 -4.496387,-3.658818 -9.213287,-7.0812097 -13.820947,-10.620357 -0.0043,-0.00352 -0.0086,-0.00707 -0.01279,-0.010651 -0.0072,-0.00489 -0.01427,-0.00987 -0.02131,-0.014921 C 26.575182,6.1532581 26.201079,6.0262199 25.796988,6.0267804 z"
+ style="opacity:0.4857143;fill:none;stroke:url(#linearGradient34576);stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ d="m 25.653978,25.09146 c 0.07926,-1.448773 0.78688,-2.727609 1.850623,-3.632978 1.046825,-0.890007 2.452533,-1.433435 3.988056,-1.433435 1.534545,0 2.940254,0.543428 3.986835,1.433435 1.064917,0.905369 1.771683,2.183246 1.851868,3.632019 0.08215,1.491022 -0.513877,2.875471 -1.558501,3.900856 -1.064918,1.044581 -2.583328,1.700332 -4.280202,1.700332 -1.697851,0 -3.216262,-0.655751 -4.281129,-1.700332 -1.045701,-1.025385 -1.639667,-2.409834 -1.55755,-3.899897 z"
+ id="path2478"
+ style="fill:#0d528b;fill-rule:evenodd;stroke:none;opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ sodipodi:nodetypes="cccczscccssssscsscsss"
+ id="path39166"
+ d="m 24.59375,7.1875 c 0,0 5.71875,4.65625 5.71875,4.65625 0.495581,0.404913 0.140487,1.262555 -0.78125,1.25 -5.634142,0.05114 -17.375,-0.03125 -17.375,-0.03125 -0.83333,0 -2.34375,0.577974 -2.34375,1.6875 0,1.109526 0.674797,1.256826 1.34375,1.25092 10e-7,0 8.8125,0 8.8125,0 1.45524,0.03051 1.617186,1.227393 0.6875,2.03033 0,0 -15.875,12.21875 -15.875,12.21875 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.7334178,0.312915 2.8620558,-0.598192 10e-8,10e-7 8.5678612,-7.049556 8.5678612,-7.049556 0.825495,-0.683682 2.569434,-0.118316 2.418275,1.384804 -0.225591,2.243266 0.09704,3.321215 0.922097,5.052178 2.275388,4.773775 9.8328,-12.333881 26.249318,-10.695484 -0.847848,-1.48757 -2.036218,-3.155316 -3.53125,-4.371859 C 36.866972,13.000573 27.607995,6.1227791 27.607995,6.1227791 26.244584,5.10849 23.323901,5.9514388 24.59375,7.1875 z"
+ style="opacity:0.51999996;fill:url(#radialGradient39177);fill-opacity:1;fill-rule:evenodd;stroke:none" />
+ </g>
+ </g>
+ <g
+ id="g5332"
+ inkscape:label="Layer 1"
+ transform="matrix(5.4776822,0,0,5.4776822,10.728205,6.96691)">
+ <g
+ id="g5334">
+ <path
+ transform="matrix(0.6403051,0,0,0.6919793,12.73379,11.876691)"
+ d="m 43.487067,38.98439 c 0,2.928932 -6.925242,5.303301 -15.467961,5.303301 -8.542719,0 -15.467961,-2.374369 -15.467961,-5.303301 0,-2.928932 6.925242,-5.303301 15.467961,-5.303301 8.542719,0 15.467961,2.374369 15.467961,5.303301 z"
+ sodipodi:ry="5.3033009"
+ sodipodi:rx="15.467961"
+ sodipodi:cy="38.98439"
+ sodipodi:cx="28.019106"
+ id="path5480"
+ style="fill:url(#radialGradient5482);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ sodipodi:type="arc" />
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.7837838;fill:url(#radialGradient5348);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter6077);enable-background:accumulate"
+ id="path5336"
+ sodipodi:cx="28.019106"
+ sodipodi:cy="38.98439"
+ sodipodi:rx="15.467961"
+ sodipodi:ry="5.3033009"
+ d="m 43.487067,38.98439 c 0,2.928932 -6.925242,5.303301 -15.467961,5.303301 -8.542719,0 -15.467961,-2.374369 -15.467961,-5.303301 0,-2.928932 6.925242,-5.303301 15.467961,-5.303301 8.542719,0 15.467961,2.374369 15.467961,5.303301 z"
+ transform="matrix(1.274286,0,0,1.377124,-7.569123,-16.70193)" />
+ <path
+ style="fill:url(#radialGradient5453);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="path5338"
+ d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -2.434775,-0.6939758 -3.431728,0.00488 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 3.792068,3.0680401 5.702368,4.5676191 0,0 -17.551681,-0.01171 -17.551681,-0.01171 -1.994685,0 -3.1682604,0.947915 -3.4153942,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800212,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -15.901723,11.764162 -15.901723,11.764162 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.6775931,-7.102098 8.6775931,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 z"
+ sodipodi:nodetypes="csssssssssscccsscccscccssccc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient5350);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path5340"
+ sodipodi:cx="31.1875"
+ sodipodi:cy="25.75"
+ sodipodi:rx="11.5625"
+ sodipodi:ry="10.125"
+ d="m 42.75,25.75 c 0,5.591883 -5.176708,10.125 -11.5625,10.125 -6.385792,0 -11.5625,-4.533117 -11.5625,-10.125 0,-5.591883 5.176708,-10.125 11.5625,-10.125 6.385792,0 11.5625,4.533117 11.5625,10.125 z"
+ transform="matrix(0.821621,0,0,0.839506,5.875686,3.882724)" />
+ <path
+ style="opacity:0.4857143;fill:none;stroke:url(#radialGradient6101);stroke-width:0.36511794;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;filter:url(#filter6103)"
+ d="m 25.796988,6.0267804 c -0.404852,5.53e-4 -0.818619,0.1256944 -1.095272,0.3196267 -7.14e-4,7.142e-4 -0.0014,0.00143 -0.0021,0.00213 -0.280209,0.1956525 -0.336859,0.3680061 -0.345206,0.4602725 -0.0083,0.092266 -0.01324,0.1672776 0.189655,0.3345475 0.01899,0.015735 0.03747,0.032076 0.0554,0.049009 0.124258,0.1010285 5.704394,4.6389488 5.704394,4.6389488 0.373658,0.304091 0.51584,0.810232 0.355197,1.264415 -0.160635,0.454191 -0.589422,0.382732 -1.071174,0.384283 -5.634142,0.05114 -17.60967,0.01918 -17.60967,0.01918 -0.952967,6.38e-4 -2.3472795,0.516793 -2.4135719,1.585761 -0.063562,1.024947 0.9093059,1.457499 1.5782589,1.457499 0,0 8.830403,-0.01705 8.830403,-0.01705 0.488364,-5.91e-4 0.922857,0.221532 1.080466,0.683755 0.15761,0.462231 0.0033,0.53156 -0.383664,0.829439 0,0 -15.9006939,12.205735 -15.9006939,12.205735 -0.00142,0.0014 -0.00284,0.0028 -0.00426,0.0043 -0.064038,0.04879 -0.084772,0.06226 -0.061795,0.04476 -0.5536756,0.424618 -0.8961097,0.98072 -1.0185711,1.476701 -0.1224537,0.495981 -0.04659,0.882548 0.1875202,1.182646 0.4788333,0.613413 1.8577618,0.820499 2.9863998,-0.09061 0,0 8.6727241,-7.09799 8.6727241,-7.09799 0.361955,-0.295752 0.77937,-0.340606 1.187723,-0.113169 0.408345,0.227437 0.548124,0.592694 0.487243,1.05613 0,0 -0.112502,0.980045 -0.10655,1.370159 0.192357,2.636407 1.448328,5.003383 3.115366,7.003128 2.877746,3.172809 6.937778,4.644674 11.130659,4.808308 4.20342,-0.04394 8.318367,-1.795011 11.174847,-4.89086 5.218918,-6.385867 3.809154,-13.408094 -1.879909,-18.037421 -4.496387,-3.658818 -9.213287,-7.0812097 -13.820947,-10.620357 -0.0043,-0.00352 -0.0086,-0.00707 -0.01279,-0.010651 -0.0072,-0.00489 -0.01427,-0.00987 -0.02131,-0.014921 C 26.575182,6.1532581 26.201079,6.0262199 25.796988,6.0267804 z"
+ id="path5342"
+ sodipodi:nodetypes="cssssscscczccsccssssccscccccscssc" />
+ <path
+ style="fill:url(#radialGradient9798);fill-rule:evenodd;stroke:none;fill-opacity:1"
+ id="path5344"
+ d="m 25.824987,24.903921 c 0.07942,-1.451637 0.788437,-2.733003 1.854283,-3.640163 1.048896,-0.891767 2.457385,-1.436271 3.995946,-1.436271 1.537581,0 2.946071,0.544504 3.994721,1.436271 1.067023,0.90716 1.775187,2.187565 1.855531,3.639202 0.08231,1.493972 -0.514893,2.88116 -1.561584,3.908574 -1.067024,1.046647 -2.588437,1.703695 -4.288668,1.703695 -1.70121,0 -3.222624,-0.657048 -4.289597,-1.703695 -1.047769,-1.027414 -1.642911,-2.414602 -1.560632,-3.907613 z"
+ inkscape:connector-curvature="0" />
+ <path
+ style="opacity:0.51999996;fill:url(#radialGradient6168);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 24.59375,7.1875 c 0,0 5.71875,4.65625 5.71875,4.65625 0.495581,0.404913 0.140487,1.262555 -0.78125,1.25 -5.634142,0.05114 -17.375,-0.03125 -17.375,-0.03125 -0.83333,0 -2.34375,0.577974 -2.34375,1.6875 0,1.109526 0.674797,1.256826 1.34375,1.25092 10e-7,0 8.8125,0 8.8125,0 1.45524,0.03051 1.617186,1.227393 0.6875,2.03033 0,0 -15.875,12.21875 -15.875,12.21875 -0.00142,0.0014 -0.029829,-0.0014 -0.03125,0 -0.064037,0.04879 -0.054226,0.04875 -0.03125,0.03125 -0.5536758,0.424619 -0.9087886,1.004019 -1.03125,1.5 -0.1224536,0.495981 -0.04661,0.856152 0.1875,1.15625 0.4788333,0.613413 1.7334178,0.312915 2.8620558,-0.598192 10e-8,10e-7 8.5678612,-7.049556 8.5678612,-7.049556 0.825495,-0.683682 2.569434,-0.118316 2.418275,1.384804 -0.225591,2.243266 0.09704,3.321215 0.922097,5.052178 2.275388,4.773775 9.8328,-12.333881 26.249318,-10.695484 -0.847848,-1.48757 -2.036218,-3.155316 -3.53125,-4.371859 C 36.866972,13.000573 27.607995,6.1227791 27.607995,6.1227791 26.244584,5.10849 23.323901,5.9514388 24.59375,7.1875 z"
+ id="path5346"
+ sodipodi:nodetypes="cccczscccssssscsscsss" />
+ <path
+ clip-path="url(#clipPath6085)"
+ sodipodi:nodetypes="csssssssssscccsscccscccssccc"
+ d="m 16.048489,28.093447 c 0.0098,0.576682 0.196474,1.697902 0.471116,2.577425 0.581566,1.854137 1.56684,3.572658 2.939126,5.086496 1.407488,1.553118 3.138519,2.803227 5.139315,3.68976 2.105357,0.931573 4.384795,1.407488 6.750134,1.403741 2.365339,-0.005 4.644601,-0.488686 6.74896,-1.427017 2.00002,-0.895288 3.731043,-2.148391 5.13754,-3.705517 1.369207,-1.519844 2.352576,-3.241114 2.934089,-5.096258 0.294262,-0.938353 0.476921,-1.889392 0.553238,-2.845308 0.07331,-0.939306 0.04204,-1.883511 -0.09183,-2.823792 -0.259981,-1.835599 -0.896294,-3.556847 -1.872652,-5.12758 -0.895541,-1.441699 -2.047808,-2.70454 -3.417268,-3.766975 0,0 0.002,-0.002 0.002,-0.002 0,0 -13.828458,-10.6197195 -13.828458,-10.6197195 -0.01176,-0.00978 -0.02252,-0.019551 -0.03529,-0.028344 -0.909003,-0.6959264 -2.434775,-0.6939758 -3.431728,0.00488 -1.01067,0.7057021 -1.091821,1.8092613 -0.195527,2.5482146 1.899775,1.4997633 3.792068,3.0680401 5.702368,4.5676191 0,0 -17.551681,-0.01171 -17.551681,-0.01171 -1.994685,0 -3.1682604,0.947915 -3.4153942,2.333683 -0.2180771,1.222836 0.7479213,2.738129 2.4800212,2.738129 2.956573,0.0039 5.942111,-0.0069 8.909215,-0.01272 0,0 -15.901723,11.764162 -15.901723,11.764162 -0.020527,0.01564 -0.041053,0.02933 -0.06158,0.04497 -1.4974197,1.148389 -1.9831951,3.059322 -1.0399808,4.268393 0.9598323,1.22959 2.9977653,1.230588 4.5147288,0.006 0,0 8.6775931,-7.102098 8.6775931,-7.102098 0,0 -0.12511,0.959824 -0.116333,1.535532 z"
+ id="path6081"
+ style="opacity:0.69791667;fill:none;stroke:#954900;stroke-width:0.73023587;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;filter:url(#filter5467)" />
+ <path
+ transform="translate(-0.1038151,0.1038151)"
+ d="m 25.78125,5.3125 c -0.53584,7.387e-4 -1.084766,0.146423 -1.5,0.4375 -0.421409,0.2942497 -0.602942,0.6572658 -0.625,0.96875 -0.02206,0.3114842 0.107704,0.6085842 0.46875,0.90625 1.903914,1.5030311 3.813217,3.066663 5.71875,4.5625 a 0.43281463,0.43281463 0 0 1 -0.28125,0.78125 l -17.5625,0 c -0.930321,0 -1.612381,0.221355 -2.09375,0.5625 -0.4813693,0.341145 -0.7691312,0.781356 -0.875,1.375 -0.1688145,0.946603 0.5535284,2.25 2.03125,2.25 2.953338,0.0039 5.936874,-0.02539 8.90625,-0.03125 a 0.43281463,0.43281463 0 0 1 0.25,0.78125 L 4.3125,29.6875 c -0.034092,0.02598 -0.03665,0.01897 -0.0625,0.03125 -1.347439,1.033367 -1.7002474,2.678513 -0.9375,3.65625 0.7751666,0.993025 2.5374375,1.042487 3.90625,-0.0625 L 15.875,26.21875 a 0.43281463,0.43281463 0 0 1 0.71875,0.375 c 0,0 -0.101633,0.982953 -0.09375,1.5 0.0084,0.493889 0.177213,1.603948 0.4375,2.4375 0.562811,1.794343 1.51227,3.468677 2.84375,4.9375 1.36736,1.508838 3.052893,2.699756 5,3.5625 2.049801,0.906991 4.255957,1.378654 6.5625,1.375 2.309464,-0.0049 4.515994,-0.462465 6.5625,-1.375 1.947032,-0.871568 3.666193,-2.082502 5.03125,-3.59375 1.327624,-1.473686 2.24864,-3.138671 2.8125,-4.9375 0.285397,-0.910084 0.457704,-1.828798 0.53125,-2.75 0.07074,-0.906296 0.0357,-1.840704 -0.09375,-2.75 -0.251441,-1.7753 -0.866193,-3.446363 -1.8125,-4.96875 -0.86755,-1.396638 -1.949249,-2.591626 -3.28125,-3.625 L 27.25,5.78125 a 0.43281463,0.43281463 0 0 1 -0.03125,0 c -0.09093,-0.075558 -0.08886,-0.092466 0,-0.03125 -0.363805,-0.2785273 -0.903938,-0.4382356 -1.4375,-0.4375 z"
+ inkscape:href="#path5338"
+ id="path6113"
+ style="opacity:0.43678164;fill:none;stroke:url(#radialGradient6121);stroke-width:0.18255897;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;filter:url(#filter6127)"
+ xlink:href="#path5338"
+ inkscape:original="M 25.78125 4.875 C 25.161562 4.8758538 24.529727 5.0568221 24.03125 5.40625 C 23.02058 6.1119521 22.947456 7.2297967 23.84375 7.96875 C 25.743525 9.4685133 27.6522 11.031671 29.5625 12.53125 L 12 12.53125 C 10.005315 12.53125 8.8408838 13.457982 8.59375 14.84375 C 8.3756729 16.066586 9.3304001 17.59375 11.0625 17.59375 C 14.019073 17.59765 17.001646 17.56832 19.96875 17.5625 L 4.0625 29.34375 C 4.041973 29.35939 4.020527 29.35936 4 29.375 C 2.5025803 30.523389 2.0255357 32.447179 2.96875 33.65625 C 3.9285823 34.88584 5.9830365 34.880838 7.5 33.65625 L 16.15625 26.5625 C 16.15625 26.5625 16.053723 27.518042 16.0625 28.09375 C 16.0723 28.670432 16.256608 29.776727 16.53125 30.65625 C 17.112816 32.510387 18.096464 34.236162 19.46875 35.75 C 20.876238 37.303118 22.592954 38.550967 24.59375 39.4375 C 26.699107 40.369073 28.978411 40.847497 31.34375 40.84375 C 33.709089 40.83875 35.989391 40.375831 38.09375 39.4375 C 40.09377 38.542212 41.843503 37.275876 43.25 35.71875 C 44.619207 34.198906 45.574737 32.480144 46.15625 30.625 C 46.450512 29.686647 46.642433 28.737166 46.71875 27.78125 C 46.79206 26.841944 46.75887 25.877781 46.625 24.9375 C 46.365019 23.101901 45.726358 21.383233 44.75 19.8125 C 43.854459 18.370801 42.71321 17.124935 41.34375 16.0625 L 27.5 5.4375 C 27.48824 5.42772 27.48152 5.415043 27.46875 5.40625 C 27.014249 5.0582868 26.400938 4.8741462 25.78125 4.875 z "
+ inkscape:radius="-0.43277135"
+ sodipodi:type="inkscape:offset" />
+ <path
+ id="path6151"
+ transform="matrix(0.1857898,0,0,0.1857898,-2.4225986,-1.6310883)"
+ d="m 153.40625,38.03125 c -5.56523,0.01098 -10.69216,2.532873 -9.5,6.0625 1.49885,-4.120535 12.31419,-5.870121 18.0625,-1.59375 0,0 50.71398,37.676904 75.34375,57.71875 7.49621,6.09984 13.55477,14.25472 18.09375,21.84375 0.41707,0.0374 0.83082,0.0519 1.25,0.0937 C 252.012,114.00782 245.50181,104.88259 237.3125,98.21875 212.68273,78.176911 161.96875,40.5 161.96875,40.5 c -2.33385,-1.736235 -5.52342,-2.474747 -8.5625,-2.46875 z m 24.4375,37.34375 c -0.52291,1.766542 -2.397,3.352638 -5.34375,3.3125 -30.86204,0.280116 -95.1875,-0.15625 -95.1875,-0.15625 -4.564714,-10e-7 -12.84375,3.141119 -12.84375,9.21875 0,0.379852 0.03453,0.753994 0.0625,1.09375 0.781053,-5.477136 8.452586,-8.3125 12.78125,-8.3125 0,0 64.32546,0.436359 95.1875,0.15625 4.0631,0.05534 6.11164,-2.970588 5.34375,-5.3125 z m -50.90625,25.46875 c -0.30408,1.66026 -1.32885,3.40896 -3.0625,4.90625 0,0 -86.96875,66.90625 -86.96875,66.90625 -0.0078,0.008 -0.148468,-0.008 -0.15625,0 -0.350777,0.26728 -0.313357,0.28336 -0.1875,0.1875 -3.032861,2.32594 -4.954195,5.50192 -5.625,8.21875 -0.306372,1.24091 -0.375948,2.3112 -0.25,3.28125 0.05246,-0.4134 0.138206,-0.82845 0.25,-1.28125 0.670805,-2.71683 2.592139,-5.89281 5.625,-8.21875 -0.125857,0.0959 -0.163277,0.0798 0.1875,-0.1875 0.0078,-0.008 0.148469,0.008 0.15625,0 0,0 86.96875,-66.90625 86.96875,-66.90625 2.45227,-2.11794 3.50673,-4.74191 3.0625,-6.90625 z m -19.125,52.34375 c -0.30179,3.03149 -0.43687,5.65829 -0.375,8.0625 0.026,-1.8868 0.1482,-3.90098 0.375,-6.15625 0.067,-0.66645 0.0608,-1.30801 0,-1.90625 z"
+ style="fill:url(#radialGradient6166);fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter6156)" />
+ <path
+ sodipodi:nodetypes="ccc"
+ transform="matrix(0.182559,0,0,0.182559,-1.95853,-1.2718719)"
+ id="path5455"
+ d="m 29.75,176 c -2.614996,11.18132 0.641128,17.71466 14,16.25 -9.13081,-1.29592 -13.534207,-6.9556 -14,-16.25 z"
+ style="opacity:0.54819282;fill:url(#radialGradient5463);fill-opacity:1;fill-rule:evenodd;stroke:none;filter:url(#filter5489)" />
+ </g>
+ </g>
+ <g
+ transform="matrix(0.9907499,0,0,0.9907499,303.07254,116.07051)"
+ inkscape:label="Layer 1"
+ id="g5430">
+ <path
+ sodipodi:type="arc"
+ style="opacity:0.54857142;fill:url(#radialGradient5444);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path5432"
+ sodipodi:cx="28.019106"
+ sodipodi:cy="38.98439"
+ sodipodi:rx="15.467961"
+ sodipodi:ry="5.3033009"
+ d="m 43.487067,38.98439 c 0,2.928932 -6.925242,5.303301 -15.467961,5.303301 -8.542719,0 -15.467961,-2.374369 -15.467961,-5.303301 0,-2.928932 6.925242,-5.303301 15.467961,-5.303301 8.542719,0 15.467961,2.374369 15.467961,5.303301 z"
+ transform="matrix(0.855157,0,0,0.922661,-5.661873,-11.9649)" />
+ <path
+ style="fill:#f57900;fill-rule:evenodd;stroke:#ce5c00;stroke-width:1.00933623;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ id="path5434"
+ d="m 10.187586,18.047598 c 0.0066,0.386372 0.131851,1.137579 0.316159,1.726852 0.390282,1.242256 1.051486,2.393649 1.972408,3.407908 0.944546,1.040575 2.106217,1.878137 3.448923,2.472106 1.412877,0.624146 2.942576,0.943005 4.529923,0.940494 1.587347,-0.0034 3.116928,-0.327415 4.529134,-0.956089 1.342186,-0.599834 2.503852,-1.439402 3.447733,-2.482663 0.918857,-1.018282 1.578781,-2.171518 1.969027,-3.414447 0.197475,-0.628689 0.320055,-1.265877 0.37127,-1.906332 0.0492,-0.629327 0.02821,-1.261936 -0.06162,-1.891916 -0.174469,-1.229834 -0.60149,-2.383056 -1.256711,-3.435433 -0.600985,-0.965926 -1.374255,-1.812018 -2.293281,-2.5238405 0,0 0.0013,-0.00133 0.0013,-0.00133 0,0 -9.280088,-7.1151179 -9.280088,-7.1151179 -0.0079,-0.00655 -0.01511,-0.013099 -0.02368,-0.01899 -0.610019,-0.4662646 -1.633945,-0.6859286 -2.302986,-0.2176987 -0.678247,0.4728142 -0.732706,1.4331601 -0.131215,1.9282522 1.274912,1.0048282 2.456416,1.9671715 3.738393,2.9718762 0,0 -12.7509646,0.014254 -12.7509646,0.014254 -1.3386056,0 -1.914871,1.0224026 -1.9384708,1.9833918 -0.02305,0.9386102 0.7891825,2.0702192 1.9515704,2.0711752 0,0 3.965571,0.0175 5.956754,0.01358 -3.4235028,2.47543 -6.8475413,5.076299 -10.2708111,7.552044 -1.0048978,0.769411 -1.14339496,2.049719 -0.5104168,2.859786 0.6441302,0.823814 1.8242592,0.824483 2.8422726,0.004 0,0 5.8234133,-5.010677 5.8234133,-5.010677 0,0 -0.08396,0.643074 -0.07807,1.028793 z"
+ sodipodi:nodetypes="csssssssssscccssccczsccsccc" />
+ <path
+ sodipodi:type="arc"
+ style="fill:url(#linearGradient5446);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+ id="path5436"
+ sodipodi:cx="31.1875"
+ sodipodi:cy="25.75"
+ sodipodi:rx="11.5625"
+ sodipodi:ry="10.125"
+ d="m 42.75,25.75 c 0,5.591883 -5.176708,10.125 -11.5625,10.125 -6.385792,0 -11.5625,-4.533117 -11.5625,-10.125 0,-5.591883 5.176708,-10.125 11.5625,-10.125 6.385792,0 11.5625,4.533117 11.5625,10.125 z"
+ transform="matrix(0.551379,0,0,0.562462,3.360761,1.826627)" />
+ <path
+ style="opacity:0.4857143;fill:none;stroke:url(#linearGradient5448);stroke-width:1.00933504;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 16.183788,3.9296777 c 0,0 5.841301,4.5669819 5.841301,4.5669819 0,0 -15.0860461,0.044876 -15.0860461,0.044876 -0.6224845,-0.00994 -1.3825975,0.1034157 -1.4062455,0.9246436 -0.025438,0.8833949 0.7343979,0.9913899 1.2651077,0.9986569 0,0 8.5494479,0.05356 8.5494479,0.05356 0,0 -12.267489,8.74809 -12.267489,8.74809 -1.605644,1.202274 -1.1006151,2.791545 0.8108018,1.702087 0,0 7.4517972,-5.968473 7.4517972,-5.968473 -0.285869,2.351972 -0.387804,4.925306 1.645322,7.280497 1.825159,2.11428 4.424594,3.170021 7.161605,3.322252 2.746147,0.01701 5.453371,-0.928662 7.352804,-2.916071 3.478266,-4.106778 2.808095,-8.758593 -0.85778,-11.83863 -2.897349,-2.4343285 -6.060137,-4.77752 -9.089408,-7.0523203 -0.87112,-0.6541592 -1.8742,-0.359145 -1.371218,0.133852 z"
+ id="path5438"
+ sodipodi:nodetypes="ccczcccscsccsss" />
+ <path
+ style="fill:#0d528b;fill-rule:evenodd;stroke:none;opacity:1"
+ id="path5440"
+ d="m 16.870671,15.810225 c 0.04997,-0.911963 0.49613,-1.716956 1.166823,-2.286861 0.660025,-0.560235 1.546327,-0.902308 2.514478,-0.902308 0.967535,0 1.853838,0.342073 2.51371,0.902308 0.671432,0.569905 1.11705,1.374294 1.167606,2.286258 0.05179,0.938558 -0.323999,1.810031 -0.982639,2.455482 -0.671432,0.657536 -1.628794,1.070313 -2.698677,1.070313 -1.070498,0 -2.027861,-0.412777 -2.699262,-1.070313 -0.659317,-0.645451 -1.033814,-1.516924 -0.982039,-2.454879 z" />
+ <path
+ style="opacity:0.51999996;fill:url(#radialGradient5450);fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 15.941783,4.3847816 c 1.218441,0.9640174 3.50563,2.730562 4.713027,3.7120538 0,0 -11.580862,-0.019972 -14.4894503,-0.022335 -0.5984048,4e-4 -1.1019407,0.4637065 -1.1000164,1.3968904 0.00192,0.9331843 0.7369658,1.6018793 1.1570273,1.6018793 0,0 7.6693824,0.02524 7.6693824,0.02524 0,0 -10.8035198,7.912497 -10.8035198,7.912497 -1.9819419,1.644102 -0.070483,3.132672 1.7755004,1.771457 1e-7,0 5.9980934,-4.790917 5.9980934,-4.790917 0,0 -0.59069,2.16135 0.282449,4.098577 1.355348,3.0071 7.649453,-8.255022 17.958019,-7.22789 -0.532397,-0.932577 -1.389106,-1.894653 -2.327894,-2.65732 0,0 -5.954377,-4.5306028 -8.847705,-6.749341 -1.770054,-1.2855307 -3.104625,-0.097655 -1.984913,0.9292116 z"
+ id="path5442"
+ sodipodi:nodetypes="ccczcccccscscc" />
+ </g>
+ <image
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz AAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAMdEVY dFRpdGxlAEZvbGRlcuNZL58AAAAUdEVYdEF1dGhvcgBKYWt1YiBTdGVpbmVy5vv3LwAAACF0RVh0 U291cmNlAGh0dHA6Ly9qaW1tYWMubXVzaWNoYWxsLmN6aWbjXgAAAFJ0RVh0Q29weXJpZ2h0AEND IEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5z ZXMvYnktc2EvMy4wL16DWrwAAAKLSURBVDiNpZNdSFNxGMaf//9/Nne2+TF1psNczc0RrSxBI+8s axp+hBClgdpFsYu6iKiE7vtQr4TAa8WwujEFhykIZWBRMqELJ87cLkSbbH5tx23nnH9XCQtBquf2 efnB+7zPS9xuN/5HwmED3bavY+C8SqWiuyvg8v3p08MABLhUfO5ygUYnvO2x+Wr/GqDKKahbqxHb +Vo70xte95SlQ8jvDHotE9UKNQylmVp9CU/GQ1SOhW31typJhgFL3sEQYVrPw+UKbxqg2zorO+tb GQgDoRQgDIqcAtPqAHCAMPDkDpJ7ydSSdxCEkmtdqzXvmN1uBwA0F646N4IBx8+FOQqqjYr5RaLG VAzmaoFwth3UVgNqdoKEPjC9uTi5GVxsu5i7OrKfwV1/1c2UzDugKGqe41QOJQB1uDG+bETlnSE0 PhnD+KIG2voeiNKKaLZat7EXe7QPeHH8WwOS8YGyxk7CxCyKWBik4AT6R+cBAOuROPpH58HFfPBs K0yZMAFoEgCg1zxRrfKcEWdDO4tHwxLZjAoii2vAD7oLh6LJggAFhFAj7bNMXOdG00dn3Q3m975S V6aGE6nY5jakKBLBL/A0lQMAjuTq4Wkqh7QTBf0xCa4xAIBEfLczJWddq27x/RsFqvogKcUqjHnm CqvV5OIbC0DHFPRlF6DIMuLrS+DDLRC2lhEVSmPhgH+a+Dz5A5ATV0GFK4+DVTNPj86cJglpMqvU lWExxLJ5JJC+gUYPyXRGDs3NKvKeeowc9EzPLdPNXJb7kF2oK3HY8gwZnIGrSCkU62uR3a2gn3xf U9s6JzF2IAAAntk/W7G7ey+ZUtu0DEWcQ1E4onGZjL/8pNzfPumOpDXxX/ULcc4GQ2/jH+UAAAAA SUVORK5CYII= "
+ width="16"
+ height="16"
+ id="image19710"
+ x="303"
+ y="209" />
+ <image
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz AAAN1wAADdcBQiibeAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAAMdEVY dFRpdGxlAEZvbGRlcuNZL58AAAAUdEVYdEF1dGhvcgBKYWt1YiBTdGVpbmVy5vv3LwAAACF0RVh0 U291cmNlAGh0dHA6Ly9qaW1tYWMubXVzaWNoYWxsLmN6aWbjXgAAAFJ0RVh0Q29weXJpZ2h0AEND IEF0dHJpYnV0aW9uLVNoYXJlQWxpa2UgaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbGljZW5z ZXMvYnktc2EvMy4wL16DWrwAAASJSURBVDiNtZVbbFRFGMd/M+fsfbfb1m4vtiBgBekF05CoQDAQ jKuiAYwPBhT0AYJGTYAgEiW8iYAPhgeRBx8kkUuUqglKNsECcqsoEMOl9AaBtlt6YUu72+7u2XPO +NBDLSQgL37JZE6+zPy+/3wz33dENBrl/zD9YRZ9WdO0KpdMrldCTFRW7i93KLR5zeXaww/aIx5G 8c7ZV1Vo3gZ8Ph07nbKu7d7Q4coLr3wQXKusrPxP8HzzjJvBprl5Jfm40nEZnrUi3Hd8/0vzQ21/ N6Qq2++r+LNIbLPL7V6uB0KlUuogJCBASgTSD6CEwF9SRGHVbKVrUohIHc273h+yUqmNHyeiX90P 3Fvz6cEIKMctx63491P2nEMphW3llNQ9gvxptH7zoSVs8eKalrvTMnp5ij4hRJG6/J1ASITmBd0L mhehexyqB+RoQCmlwByGnkamvvu1dnHLkgNbiuKvbeyP/nZXjhcE2tODZ36s629rCSba2+y+pguM 9PbkCuat1iwjjQyVgQJROhNZ8QwyUoPwRlDJDui9SPHcJZ7+c0dfeN7XevrwSGXHWCrG2/YJp1Yp wa6qdXtQvRcQUoIriKxdhvTlk0hmyBomkXw/msphnd2F1XUcAmGaf/q5U7j9i9c3Tz+r3w9qxc8i 7TQKG1G9FMsV5Nj5Dq7dTJLK5EgMZVn9ynSKapdjt8dQgwnyIgUVyaH0NmDBGHhr+ckPlBA7qtbt QcVPI4UHzBGUvxTbV0xnzxCXb9zmzKUuWjsHyJk2AZfivUU1CG8FdDcQ9lqkBsW0scvbWhJ7Gsu1 reqjetTVQ2RzuqnEsPSQksovME0Tw8hRf+QKQyPG2Alt28IwDHQ9iHarDU/hFIAQgPyiJLZZeoIn qjfWe+2WeloP7rNav99h29mkjZWFgSsYI4OE3CY1k/LHoBVFfhbNqsAwDOhsBCEYVmGA5Khib3DT 9LV7Nav5B1oOHsiRTW0CirN9N1b4ysseofN37ENrMZ/7nDWLn+D1OeUYpmJyaRBdAy7uR+s8hQhE 6L+ZMIE4gAwURqTVe5HWX+qTIp1aOGM32wcyNHX9ccRURhqr6zq+K/sJxVZB7yVK811MLHIjUnG8 jVsJNqwdraNH6zAzIznbUkcBxLk36QUCWZPqWfvoATKA2LuQnTMmR96a8lS1z752DNRoVSpPGFu6 0TL9Yz752ByuXmo1MlmzUSHf+OT6zG4RjUaJxWIS0Jxa1gAvENyzkF+rJhRMmzpnvk73edTt66Bs p9QFIq8cUTaTtj9PmcPDRlfCDix7+dv46Wg0agunG3gBl/NKNKAQyAdmrKxl6ds18tm8SImr5PEn NV0TeMMFpAZuk4jfMIf7e4kPy7ZX9w68A3QA/YAhHJU+55mY4+BlQBioWlbjrZ43yVNXyGB5oZew FJBTIpcR/uTJbnloy4lkA9DpgPuA7B3FLsDjBBEO2O0E9AMTnFPdaXsWkHPmLJBygLeANGDh9Io7 MO0euO4EzAMKnFEEFAMlzlwIBB1xAqf/PNSvabzFYjFxry8ajap7ff8Agrza9zbhZ90AAAAASUVO RK5CYII= "
+ width="22"
+ height="22"
+ id="image19724"
+ x="303"
+ y="167" />
+ <g
+ id="g9782">
+ <path
+ inkscape:connector-curvature="0"
+ d="m 491.24978,63.587162 c 0.0868,-1.562276 0.85304,-2.940366 2.0071,-3.917191 l 0,0 c 1.13397,-0.959657 2.65807,-1.545263 4.32238,-1.545368 l 0,0 c 1.66352,1.05e-4 3.18763,0.585711 4.32164,1.545368 l 0,0 c 1.15441,0.976825 1.92058,2.354729 2.0083,3.916662 0.0883,1.607195 -0.5568,3.100488 -1.69002,4.206112 l 0,0 c -1.15468,1.126218 -2.79964,1.833283 -4.63965,1.833283 l 0,0 c -1.84055,0 -3.48657,-0.707065 -4.6413,-1.833283 l 0,0 c -1.13316,-1.1052 -1.77768,-2.598705 -1.68845,-4.205583"
+ style="fill:#0d528b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path9266" />
+ <path
+ inkscape:connector-curvature="0"
+ d="m 481.16722,66.750592 c 0.0104,0.610255 0.20736,1.79817 0.49919,2.729465 l 0,0 c 0.61545,1.964124 1.65874,3.783545 3.11239,5.387111 l 0,0 c 1.49072,1.645175 3.32369,2.969218 5.44354,3.907954 l 0,0 c 2.22956,0.986777 4.64394,1.49145 7.14888,1.48679 l 0,0 c 2.50548,-0.0047 4.91952,-0.5173 7.14831,-1.511426 l 0,0 c 2.11802,-0.947748 3.95115,-2.274901 5.44081,-3.925057 l 0,0 c 1.4507,-1.60945 2.49248,-3.431761 3.10865,-5.397552 l 0,0 c 0.31113,-0.993921 0.50512,-2.000669 0.58489,-3.012691 l 0,0 c 0.0777,-0.995696 0.0445,-1.994889 -0.0967,-2.99138 l 0,0 c -0.27562,-1.943638 -0.94876,-3.766981 -1.98312,-5.430282 -0.94903,-1.527057 -2.16917,-2.864253 -3.61988,-3.990365 l 0,0 0.002,-0.0019 0,0 -14.64557,-11.247437 0,0 c -0.0127,-0.01007 -0.0246,-0.0204 -0.0374,-0.03021 l 0,0 c -0.96328,-0.736748 -2.57907,-0.734363 -3.635,0.0053 l 0,0 c -1.06998,0.747614 -1.18998,1.982859 -0.24037,2.76466 l 0,0 -0.003,0.0024 0,0 6.10894,4.968542 -18.62178,0.01988 0,0 c -0.009,0 -0.0169,-2.54e-4 -0.0254,-2.54e-4 l 0,0 c -1.53866,7.81e-4 -3.01717,1.012631 -3.31158,2.287629 l 0,0 c -0.29846,1.300517 0.747,2.378713 2.34591,2.384837 l 0,0 -8.7e-4,0.0054 0,0 9.43718,-0.01812 -16.84256,12.927248 0,0 c -0.0213,0.01624 -0.0435,0.03159 -0.0647,0.04813 l 0,0 c -1.58657,1.216401 -2.10109,3.240153 -1.10147,4.520744 l 0,0 c 1.01669,1.302506 3.17515,1.303326 4.78149,0.0059 l 0,0 9.19101,-7.5214 c 0,0 -0.13322,1.015864 -0.12318,1.626223 z m 23.61918,3.398421 c -1.89407,1.931845 -4.54345,3.025253 -7.41438,3.02989 l 0,0 c -2.87226,0.0059 -5.52304,-1.079204 -7.41741,-3.005774 l 0,0 c -0.92589,-0.939669 -1.60603,-2.017734 -2.02563,-3.169949 l 0,0 c -0.41078,-1.130245 -0.5704,-2.328628 -0.46553,-3.539224 l 0,0 c 0.10249,-1.18492 0.4522,-2.312381 1.01629,-3.334659 l 0,0 c 0.5529,-1.003965 1.3139,-1.910907 2.25336,-2.678847 l 0,0 c 1.84095,-1.501268 4.18327,-2.31238 6.63653,-2.315588 l 0,0 c 2.45327,-0.0035 4.79576,0.801359 6.63656,2.296745 l 0,0 c 0.9387,0.76378 1.69904,1.667754 2.25239,2.669942 l 0,0 c 0.56369,1.020529 0.91378,2.146534 1.01687,3.331769 l 0,0 c 0.10468,1.209461 -0.0549,2.408769 -0.46563,3.539942 l 0,0 c -0.41926,1.152825 -1.09877,2.232769 -2.02342,3.175753"
+ style="fill:#f5792a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ id="path9268" />
+ </g>
+ <g
+ id="g9786"
+ transform="matrix(5.2091874,0,0,5.2091874,-2775.9222,-186.77589)">
+ <path
+ id="path9788"
+ style="fill:#0d528b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 491.24978,63.587162 c 0.0868,-1.562276 0.85304,-2.940366 2.0071,-3.917191 l 0,0 c 1.13397,-0.959657 2.65807,-1.545263 4.32238,-1.545368 l 0,0 c 1.66352,1.05e-4 3.18763,0.585711 4.32164,1.545368 l 0,0 c 1.15441,0.976825 1.92058,2.354729 2.0083,3.916662 0.0883,1.607195 -0.5568,3.100488 -1.69002,4.206112 l 0,0 c -1.15468,1.126218 -2.79964,1.833283 -4.63965,1.833283 l 0,0 c -1.84055,0 -3.48657,-0.707065 -4.6413,-1.833283 l 0,0 c -1.13316,-1.1052 -1.77768,-2.598705 -1.68845,-4.205583"
+ inkscape:connector-curvature="0" />
+ <path
+ id="path9790"
+ style="fill:#f5792a;fill-opacity:1;fill-rule:nonzero;stroke:none"
+ d="m 481.16722,66.750592 c 0.0104,0.610255 0.20736,1.79817 0.49919,2.729465 l 0,0 c 0.61545,1.964124 1.65874,3.783545 3.11239,5.387111 l 0,0 c 1.49072,1.645175 3.32369,2.969218 5.44354,3.907954 l 0,0 c 2.22956,0.986777 4.64394,1.49145 7.14888,1.48679 l 0,0 c 2.50548,-0.0047 4.91952,-0.5173 7.14831,-1.511426 l 0,0 c 2.11802,-0.947748 3.95115,-2.274901 5.44081,-3.925057 l 0,0 c 1.4507,-1.60945 2.49248,-3.431761 3.10865,-5.397552 l 0,0 c 0.31113,-0.993921 0.50512,-2.000669 0.58489,-3.012691 l 0,0 c 0.0777,-0.995696 0.0445,-1.994889 -0.0967,-2.99138 l 0,0 c -0.27562,-1.943638 -0.94876,-3.766981 -1.98312,-5.430282 -0.94903,-1.527057 -2.16917,-2.864253 -3.61988,-3.990365 l 0,0 0.002,-0.0019 0,0 -14.64557,-11.247437 0,0 c -0.0127,-0.01007 -0.0246,-0.0204 -0.0374,-0.03021 l 0,0 c -0.96328,-0.736748 -2.57907,-0.734363 -3.635,0.0053 l 0,0 c -1.06998,0.747614 -1.18998,1.982859 -0.24037,2.76466 l 0,0 -0.003,0.0024 0,0 6.10894,4.968542 -18.62178,0.01988 0,0 c -0.009,0 -0.0169,-2.54e-4 -0.0254,-2.54e-4 l 0,0 c -1.53866,7.81e-4 -3.01717,1.012631 -3.31158,2.287629 l 0,0 c -0.29846,1.300517 0.747,2.378713 2.34591,2.384837 l 0,0 -8.7e-4,0.0054 0,0 9.43718,-0.01812 -16.84256,12.927248 0,0 c -0.0213,0.01624 -0.0435,0.03159 -0.0647,0.04813 l 0,0 c -1.58657,1.216401 -2.10109,3.240153 -1.10147,4.520744 l 0,0 c 1.01669,1.302506 3.17515,1.303326 4.78149,0.0059 l 0,0 9.19101,-7.5214 c 0,0 -0.13322,1.015864 -0.12318,1.626223 z m 23.61918,3.398421 c -1.89407,1.931845 -4.54345,3.025253 -7.41438,3.02989 l 0,0 c -2.87226,0.0059 -5.52304,-1.079204 -7.41741,-3.005774 l 0,0 c -0.92589,-0.939669 -1.60603,-2.017734 -2.02563,-3.169949 l 0,0 c -0.41078,-1.130245 -0.5704,-2.328628 -0.46553,-3.539224 l 0,0 c 0.10249,-1.18492 0.4522,-2.312381 1.01629,-3.334659 l 0,0 c 0.5529,-1.003965 1.3139,-1.910907 2.25336,-2.678847 l 0,0 c 1.84095,-1.501268 4.18327,-2.31238 6.63653,-2.315588 l 0,0 c 2.45327,-0.0035 4.79576,0.801359 6.63656,2.296745 l 0,0 c 0.9387,0.76378 1.69904,1.667754 2.25239,2.669942 l 0,0 c 0.56369,1.020529 0.91378,2.146534 1.01687,3.331769 l 0,0 c 0.10468,1.209461 -0.0549,2.408769 -0.46563,3.539942 l 0,0 c -0.41926,1.152825 -1.09877,2.232769 -2.02342,3.175753"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+</svg>
diff --git a/release/freedesktop/icons/scalable/blender.svg b/release/freedesktop/icons/scalable/apps/blender.svg
index bc1a3a970f6..bc1a3a970f6 100644
--- a/release/freedesktop/icons/scalable/blender.svg
+++ b/release/freedesktop/icons/scalable/apps/blender.svg
diff --git a/release/plugins/sequence/blur.c b/release/plugins/sequence/blur.c
index c23a924ac65..cec3351e976 100644
--- a/release/plugins/sequence/blur.c
+++ b/release/plugins/sequence/blur.c
@@ -41,7 +41,7 @@ char name[24]= "Blur";
VarStruct varstr[]= {
LABEL, "Input: 1 strip", 0.0, 0.0, 0.0, "",
- NUMSLI|FLO, "Blur", 0.5, 0.0, 10.0, "Maximum filtersize",
+ NUMSLI|FLO, "Blur", 0.5, 0.0, 10.0, "Maximum filtersize",
NUMSLI|FLO, "Gamma", 1.0, 0.4, 2.0, "Gamma correction",
TOG|INT, "Animated", 0.0, 0.0, 1.0, "For (Ipo) animated blur",
NUM|INT, "debug", 0.0, 0.0, 2.0,
diff --git a/release/plugins/sequence/color-correction-hsv.c b/release/plugins/sequence/color-correction-hsv.c
index cff2f1aad82..1ee58e256d2 100644
--- a/release/plugins/sequence/color-correction-hsv.c
+++ b/release/plugins/sequence/color-correction-hsv.c
@@ -196,7 +196,7 @@ void plugin_seq_doit(Cast *cast, float facf0, float facf1, int width,
src1f= ibuf1->rect_float;
for (y = 0; y < 256; y++) {
- float v = 1.0 * y / 255;
+ float v = 1.0 * y / 255;
v += cast->setup_y;
v *= cast->gain_y;
v = pow(v, cast->gamma_y);
diff --git a/release/plugins/sequence/color-correction-yuv.c b/release/plugins/sequence/color-correction-yuv.c
index b80489f3b0b..1a78fc7d4b6 100644
--- a/release/plugins/sequence/color-correction-yuv.c
+++ b/release/plugins/sequence/color-correction-yuv.c
@@ -129,7 +129,7 @@ void plugin_seq_doit(Cast *cast, float facf0, float facf1, int width,
src1f= ibuf1->rect_float;
for (y = 0; y < 256; y++) {
- float v = 1.0 * y / 255;
+ float v = 1.0 * y / 255;
v += cast->setup_y;
v *= cast->gain_y;
v = pow(v, cast->gamma_y);
diff --git a/release/plugins/sequence/dnr.c b/release/plugins/sequence/dnr.c
index b6a99de0622..606ec19ef41 100644
--- a/release/plugins/sequence/dnr.c
+++ b/release/plugins/sequence/dnr.c
@@ -66,7 +66,7 @@ static void precalculate(unsigned char * table, int level)
}
*table++ = ap;
- }
+ }
}
}
diff --git a/release/plugins/sequence/gamma.c b/release/plugins/sequence/gamma.c
index e1380746cea..7ce86fff347 100644
--- a/release/plugins/sequence/gamma.c
+++ b/release/plugins/sequence/gamma.c
@@ -85,7 +85,7 @@ static void make_gamma_table(float setup, float gain, float gamma,
int y;
for (y = 0; y < 256; y++) {
- float v = 1.0 * y / 255;
+ float v = 1.0 * y / 255;
v += setup;
v *= gain;
v = pow(v, gamma);
diff --git a/release/plugins/sequence/scatter.c b/release/plugins/sequence/scatter.c
index ac4346c1a44..4741b33ce0e 100644
--- a/release/plugins/sequence/scatter.c
+++ b/release/plugins/sequence/scatter.c
@@ -193,9 +193,9 @@ static void fill_out(ImBuf *out, float r, float g, float b, float a)
} else {
for (x=0;x < tot;x++) {
rect[0] = (int)(r * 255);
- rect[1] = (int)(g * 255);
- rect[2] = (int)(b * 255);
- rect[3] = (int)(a * 255);
+ rect[1] = (int)(g * 255);
+ rect[2] = (int)(b * 255);
+ rect[3] = (int)(a * 255);
rect += 4;
}
}
diff --git a/release/scripts/io/netrender/__init__.py b/release/scripts/io/netrender/__init__.py
deleted file mode 100644
index 6c4ed4119fc..00000000000
--- a/release/scripts/io/netrender/__init__.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# ##### 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 #####
-
-# This directory is a Python package.
-
-# To support reload properly, try to access a package var, if it's there, reload everything
-if "init_data" in locals():
- import imp
- imp.reload(model)
- imp.reload(operators)
- imp.reload(client)
- imp.reload(slave)
- imp.reload(master)
- imp.reload(master_html)
- imp.reload(utils)
- imp.reload(balancing)
- imp.reload(ui)
- imp.reload(repath)
- imp.reload(versioning)
-else:
- from netrender import model
- from netrender import operators
- from netrender import client
- from netrender import slave
- from netrender import master
- from netrender import master_html
- from netrender import utils
- from netrender import balancing
- from netrender import ui
- from netrender import repath
- from netrender import versioning
-
-jobs = []
-slaves = []
-blacklist = []
-
-init_file = ""
-valid_address = False
-init_data = True
-
-
-def register():
- ui.addProperties()
-
- import bpy
- scene = bpy.context.scene
- if scene:
- netsettings = scene.network_render
- ui.init_data(netsettings)
-
-
-def unregister():
- import bpy
- del bpy.types.Scene.network_render
diff --git a/release/scripts/io/netrender/balancing.py b/release/scripts/io/netrender/balancing.py
deleted file mode 100644
index dde3ad53084..00000000000
--- a/release/scripts/io/netrender/balancing.py
+++ /dev/null
@@ -1,195 +0,0 @@
-# ##### 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 #####
-
-import time
-
-from netrender.utils import *
-import netrender.model
-
-class RatingRule:
- def __init__(self):
- self.enabled = True
-
- def id(self):
- return str(id(self))
-
- def rate(self, job):
- return 0
-
-class ExclusionRule:
- def __init__(self):
- self.enabled = True
-
- def id(self):
- return str(id(self))
-
- def test(self, job):
- return False
-
-class PriorityRule:
- def __init__(self):
- self.enabled = True
-
- def id(self):
- return str(id(self))
-
- def test(self, job):
- return False
-
-class Balancer:
- def __init__(self):
- self.rules = []
- self.priorities = []
- self.exceptions = []
-
- def ruleByID(self, rule_id):
- for rule in self.rules:
- if rule.id() == rule_id:
- return rule
- for rule in self.priorities:
- if rule.id() == rule_id:
- return rule
- for rule in self.exceptions:
- if rule.id() == rule_id:
- return rule
-
- return None
-
- def addRule(self, rule):
- self.rules.append(rule)
-
- def addPriority(self, priority):
- self.priorities.append(priority)
-
- def addException(self, exception):
- self.exceptions.append(exception)
-
- def applyRules(self, job):
- return sum((rule.rate(job) for rule in self.rules if rule.enabled))
-
- def applyPriorities(self, job):
- for priority in self.priorities:
- if priority.enabled and priority.test(job):
- return True # priorities are first
-
- return False
-
- def applyExceptions(self, job):
- for exception in self.exceptions:
- if exception.enabled and exception.test(job):
- return True # exceptions are last
-
- return False
-
- def sortKey(self, job):
- return (1 if self.applyExceptions(job) else 0, # exceptions after
- 0 if self.applyPriorities(job) else 1, # priorities first
- self.applyRules(job))
-
- def balance(self, jobs):
- if jobs:
- # use inline copy to make sure the list is still accessible while sorting
- jobs[:] = sorted(jobs, key=self.sortKey)
- return jobs[0]
- else:
- return None
-
-# ==========================
-
-class RatingUsage(RatingRule):
- def __str__(self):
- return "Usage per job"
-
- def rate(self, job):
- # less usage is better
- return job.usage / job.priority
-
-class RatingUsageByCategory(RatingRule):
- def __init__(self, get_jobs):
- super().__init__()
- self.getJobs = get_jobs
-
- def __str__(self):
- return "Usage per category"
-
- def rate(self, job):
- total_category_usage = sum([j.usage for j in self.getJobs() if j.category == job.category])
- maximum_priority = max([j.priority for j in self.getJobs() if j.category == job.category])
-
- # less usage is better
- return total_category_usage / maximum_priority
-
-class NewJobPriority(PriorityRule):
- def __init__(self, limit = 1):
- super().__init__()
- self.limit = limit
-
- def setLimit(self, value):
- self.limit = int(value)
-
- def str_limit(self):
- return "less than %i frame%s done" % (self.limit, "s" if self.limit > 1 else "")
-
- def __str__(self):
- return "Priority to new jobs"
-
- def test(self, job):
- return job.countFrames(status = DONE) < self.limit
-
-class MinimumTimeBetweenDispatchPriority(PriorityRule):
- def __init__(self, limit = 10):
- super().__init__()
- self.limit = limit
-
- def setLimit(self, value):
- self.limit = int(value)
-
- def str_limit(self):
- return "more than %i minute%s since last" % (self.limit, "s" if self.limit > 1 else "")
-
- def __str__(self):
- return "Priority to jobs that haven't been dispatched recently"
-
- def test(self, job):
- return job.countFrames(status = DISPATCHED) == 0 and (time.time() - job.last_dispatched) / 60 > self.limit
-
-class ExcludeQueuedEmptyJob(ExclusionRule):
- def __str__(self):
- return "Exclude non queued or empty jobs"
-
- def test(self, job):
- return job.status != JOB_QUEUED or job.countFrames(status = QUEUED) == 0
-
-class ExcludeSlavesLimit(ExclusionRule):
- def __init__(self, count_jobs, count_slaves, limit = 0.75):
- super().__init__()
- self.count_jobs = count_jobs
- self.count_slaves = count_slaves
- self.limit = limit
-
- def setLimit(self, value):
- self.limit = float(value)
-
- def str_limit(self):
- return "more than %.0f%% of all slaves" % (self.limit * 100)
-
- def __str__(self):
- return "Exclude jobs that would use too many slaves"
-
- def test(self, job):
- return not ( self.count_jobs() == 1 or self.count_slaves() <= 1 or float(job.countSlaves() + 1) / self.count_slaves() <= self.limit )
diff --git a/release/scripts/io/netrender/client.py b/release/scripts/io/netrender/client.py
deleted file mode 100644
index bc43b8cfbb7..00000000000
--- a/release/scripts/io/netrender/client.py
+++ /dev/null
@@ -1,372 +0,0 @@
-# ##### 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 #####
-
-import bpy
-import sys, os, re
-import http, http.client, http.server, urllib
-import subprocess, shutil, time, hashlib
-import json
-
-import netrender
-import netrender.model
-import netrender.slave as slave
-import netrender.master as master
-from netrender.utils import *
-
-def addFluidFiles(job, path):
- if os.path.exists(path):
- pattern = re.compile("fluidsurface_(final|preview)_([0-9]+)\.(bobj|bvel)\.gz")
-
- for fluid_file in sorted(os.listdir(path)):
- match = pattern.match(fluid_file)
-
- if match:
- # fluid frames starts at 0, which explains the +1
- # This is stupid
- current_frame = int(match.groups()[1]) + 1
- job.addFile(path + fluid_file, current_frame, current_frame)
-
-def addPointCache(job, ob, point_cache, default_path):
- if not point_cache.use_disk_cache:
- return
-
-
- name = point_cache.name
- if name == "":
- name = "".join(["%02X" % ord(c) for c in ob.name])
-
- cache_path = bpy.path.abspath(point_cache.filepath) if point_cache.use_external else default_path
-
- index = "%02i" % point_cache.index
-
- if os.path.exists(cache_path):
- pattern = re.compile(name + "_([0-9]+)_" + index + "\.bphys")
-
- cache_files = []
-
- for cache_file in sorted(os.listdir(cache_path)):
- match = pattern.match(cache_file)
-
- if match:
- cache_frame = int(match.groups()[0])
- cache_files.append((cache_frame, cache_file))
-
- cache_files.sort()
-
- if len(cache_files) == 1:
- cache_frame, cache_file = cache_files[0]
- job.addFile(cache_path + cache_file, cache_frame, cache_frame)
- else:
- for i in range(len(cache_files)):
- current_item = cache_files[i]
- next_item = cache_files[i+1] if i + 1 < len(cache_files) else None
- previous_item = cache_files[i - 1] if i > 0 else None
-
- current_frame, current_file = current_item
-
- if not next_item and not previous_item:
- job.addFile(cache_path + current_file, current_frame, current_frame)
- elif next_item and not previous_item:
- next_frame = next_item[0]
- job.addFile(cache_path + current_file, current_frame, next_frame - 1)
- elif not next_item and previous_item:
- previous_frame = previous_item[0]
- job.addFile(cache_path + current_file, previous_frame + 1, current_frame)
- else:
- next_frame = next_item[0]
- previous_frame = previous_item[0]
- job.addFile(cache_path + current_file, previous_frame + 1, next_frame - 1)
-
-def fillCommonJobSettings(job, job_name, netsettings):
- job.name = job_name
- job.category = netsettings.job_category
-
- for slave in netrender.blacklist:
- job.blacklist.append(slave.id)
-
- job.chunks = netsettings.chunks
- job.priority = netsettings.priority
-
- if netsettings.job_type == "JOB_BLENDER":
- job.type = netrender.model.JOB_BLENDER
- elif netsettings.job_type == "JOB_PROCESS":
- job.type = netrender.model.JOB_PROCESS
- elif netsettings.job_type == "JOB_VCS":
- job.type = netrender.model.JOB_VCS
-
-def clientSendJob(conn, scene, anim = False):
- netsettings = scene.network_render
- if netsettings.job_type == "JOB_BLENDER":
- return clientSendJobBlender(conn, scene, anim)
- elif netsettings.job_type == "JOB_VCS":
- return clientSendJobVCS(conn, scene, anim)
-
-def clientSendJobVCS(conn, scene, anim = False):
- netsettings = scene.network_render
- job = netrender.model.RenderJob()
-
- if anim:
- for f in range(scene.frame_start, scene.frame_end + 1):
- job.addFrame(f)
- else:
- job.addFrame(scene.frame_current)
-
- filename = bpy.data.filepath
-
- if not filename.startswith(netsettings.vcs_wpath):
- # this is an error, need better way to handle this
- return
-
- filename = filename[len(netsettings.vcs_wpath):]
-
- if filename[0] in (os.sep, os.altsep):
- filename = filename[1:]
-
- print("CREATING VCS JOB", filename)
-
- job.addFile(filename, signed=False)
-
- job_name = netsettings.job_name
- path, name = os.path.split(filename)
- if job_name == "[default]":
- job_name = name
-
-
- fillCommonJobSettings(job, job_name, netsettings)
-
- # VCS Specific code
- job.version_info = netrender.model.VersioningInfo()
- job.version_info.system = netsettings.vcs_system
- job.version_info.wpath = netsettings.vcs_wpath
- job.version_info.rpath = netsettings.vcs_rpath
- job.version_info.revision = netsettings.vcs_revision
-
- # try to send path first
- conn.request("POST", "/job", json.dumps(job.serialize()))
- response = conn.getresponse()
- response.read()
-
- job_id = response.getheader("job-id")
-
- # a VCS job is always good right now, need error handling
-
- return job_id
-
-def clientSendJobBlender(conn, scene, anim = False):
- netsettings = scene.network_render
- job = netrender.model.RenderJob()
-
- if anim:
- for f in range(scene.frame_start, scene.frame_end + 1):
- job.addFrame(f)
- else:
- job.addFrame(scene.frame_current)
-
- filename = bpy.data.filepath
- job.addFile(filename)
-
- job_name = netsettings.job_name
- path, name = os.path.split(filename)
- if job_name == "[default]":
- job_name = name
-
- ###########################
- # LIBRARIES
- ###########################
- for lib in bpy.data.libraries:
- file_path = bpy.path.abspath(lib.filepath)
- if os.path.exists(file_path):
- job.addFile(file_path)
-
- ###########################
- # IMAGES
- ###########################
- for image in bpy.data.images:
- if image.source == "FILE" and not image.packed_file:
- file_path = bpy.path.abspath(image.filepath)
- if os.path.exists(file_path):
- job.addFile(file_path)
-
- tex_path = os.path.splitext(file_path)[0] + ".tex"
- if os.path.exists(tex_path):
- job.addFile(tex_path)
-
- ###########################
- # FLUID + POINT CACHE
- ###########################
- root, ext = os.path.splitext(name)
- default_path = path + os.sep + "blendcache_" + root + os.sep # need an API call for that
-
- for object in bpy.data.objects:
- for modifier in object.modifiers:
- if modifier.type == 'FLUID_SIMULATION' and modifier.settings.type == "DOMAIN":
- addFluidFiles(job, bpy.path.abspath(modifier.settings.filepath))
- elif modifier.type == "CLOTH":
- addPointCache(job, object, modifier.point_cache, default_path)
- elif modifier.type == "SOFT_BODY":
- addPointCache(job, object, modifier.point_cache, default_path)
- elif modifier.type == "SMOKE" and modifier.smoke_type == "TYPE_DOMAIN":
- addPointCache(job, object, modifier.domain_settings.point_cache, default_path)
- elif modifier.type == "MULTIRES" and modifier.is_external:
- file_path = bpy.path.abspath(modifier.filepath)
- job.addFile(file_path)
-
- # particles modifier are stupid and don't contain data
- # we have to go through the object property
- for psys in object.particle_systems:
- addPointCache(job, object, psys.point_cache, default_path)
-
- #print(job.files)
-
- fillCommonJobSettings(job, job_name, netsettings)
-
- # try to send path first
- conn.request("POST", "/job", json.dumps(job.serialize()))
- response = conn.getresponse()
- response.read()
-
- job_id = response.getheader("job-id")
-
- # if not ACCEPTED (but not processed), send files
- if response.status == http.client.ACCEPTED:
- for rfile in job.files:
- f = open(rfile.filepath, "rb")
- conn.request("PUT", fileURL(job_id, rfile.index), f)
- f.close()
- response = conn.getresponse()
- response.read()
-
- # server will reply with ACCEPTED until all files are found
-
- return job_id
-
-def requestResult(conn, job_id, frame):
- conn.request("GET", renderURL(job_id, frame))
-
-class NetworkRenderEngine(bpy.types.RenderEngine):
- bl_idname = 'NET_RENDER'
- bl_label = "Network Render"
- bl_use_postprocess = False
- def render(self, scene):
- if scene.network_render.mode == "RENDER_CLIENT":
- self.render_client(scene)
- elif scene.network_render.mode == "RENDER_SLAVE":
- self.render_slave(scene)
- elif scene.network_render.mode == "RENDER_MASTER":
- self.render_master(scene)
- else:
- print("UNKNOWN OPERATION MODE")
-
- def render_master(self, scene):
- netsettings = scene.network_render
-
- address = "" if netsettings.server_address == "[default]" else netsettings.server_address
-
- master.runMaster((address, netsettings.server_port), netsettings.use_master_broadcast, netsettings.use_master_clear, bpy.path.abspath(netsettings.path), self.update_stats, self.test_break)
-
-
- def render_slave(self, scene):
- slave.render_slave(self, scene.network_render, scene.render.threads)
-
- def render_client(self, scene):
- netsettings = scene.network_render
- self.update_stats("", "Network render client initiation")
-
-
- conn = clientConnection(netsettings.server_address, netsettings.server_port)
-
- if conn:
- # Sending file
-
- self.update_stats("", "Network render exporting")
-
- new_job = False
-
- job_id = netsettings.job_id
-
- # reading back result
-
- self.update_stats("", "Network render waiting for results")
-
-
- requestResult(conn, job_id, scene.frame_current)
- response = conn.getresponse()
- buf = response.read()
-
- if response.status == http.client.NO_CONTENT:
- new_job = True
- netsettings.job_id = clientSendJob(conn, scene)
- job_id = netsettings.job_id
-
- requestResult(conn, job_id, scene.frame_current)
- response = conn.getresponse()
- buf = response.read()
-
- while response.status == http.client.ACCEPTED and not self.test_break():
- time.sleep(1)
- requestResult(conn, job_id, scene.frame_current)
- response = conn.getresponse()
- buf = response.read()
-
- # cancel new jobs (animate on network) on break
- if self.test_break() and new_job:
- conn.request("POST", cancelURL(job_id))
- response = conn.getresponse()
- response.read()
- print( response.status, response.reason )
- netsettings.job_id = 0
-
- if response.status != http.client.OK:
- conn.close()
- return
-
- r = scene.render
- x= int(r.resolution_x*r.resolution_percentage*0.01)
- y= int(r.resolution_y*r.resolution_percentage*0.01)
-
- result_path = os.path.join(bpy.path.abspath(netsettings.path), "output.exr")
-
- folder = os.path.split(result_path)[0]
-
- if not os.path.exists(folder):
- os.mkdir(folder)
-
- f = open(result_path, "wb")
-
- f.write(buf)
-
- f.close()
-
- result = self.begin_result(0, 0, x, y)
- result.load_from_file(result_path)
- self.end_result(result)
-
- conn.close()
-
-def compatible(module):
- module = __import__(module)
- for subclass in module.__dict__.values():
- try: subclass.COMPAT_ENGINES.add('NET_RENDER')
- except: pass
- del module
-
-compatible("properties_world")
-compatible("properties_material")
-compatible("properties_data_mesh")
-compatible("properties_data_camera")
-compatible("properties_texture")
diff --git a/release/scripts/io/netrender/master.py b/release/scripts/io/netrender/master.py
deleted file mode 100644
index 793e3bb51bf..00000000000
--- a/release/scripts/io/netrender/master.py
+++ /dev/null
@@ -1,1079 +0,0 @@
-# ##### 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 #####
-
-import sys, os
-import http, http.client, http.server, urllib, socket, socketserver, threading
-import subprocess, shutil, time, hashlib
-import pickle
-import select # for select.error
-import json
-
-from netrender.utils import *
-import netrender.model
-import netrender.balancing
-import netrender.master_html
-import netrender.thumbnail as thumbnail
-
-class MRenderFile(netrender.model.RenderFile):
- def __init__(self, filepath, index, start, end, signature):
- super().__init__(filepath, index, start, end, signature)
- self.found = False
-
- def test(self):
- self.found = os.path.exists(self.filepath)
- if self.found and self.signature != None:
- found_signature = hashFile(self.filepath)
- self.found = self.signature == found_signature
-
- return self.found
-
-
-class MRenderSlave(netrender.model.RenderSlave):
- def __init__(self, name, address, stats):
- super().__init__()
- self.id = hashlib.md5(bytes(repr(name) + repr(address), encoding='utf8')).hexdigest()
- self.name = name
- self.address = address
- self.stats = stats
- self.last_seen = time.time()
-
- self.job = None
- self.job_frames = []
-
- netrender.model.RenderSlave._slave_map[self.id] = self
-
- def seen(self):
- self.last_seen = time.time()
-
- def finishedFrame(self, frame_number):
- self.job_frames.remove(frame_number)
- if not self.job_frames:
- self.job = None
-
-class MRenderJob(netrender.model.RenderJob):
- def __init__(self, job_id, job_info):
- super().__init__(job_info)
- self.id = job_id
- self.last_dispatched = time.time()
-
- # force one chunk for process jobs
- if self.type == netrender.model.JOB_PROCESS:
- self.chunks = 1
-
- # Force WAITING status on creation
- self.status = JOB_WAITING
-
- # special server properties
- self.last_update = 0
- self.save_path = ""
- self.files = [MRenderFile(rfile.filepath, rfile.index, rfile.start, rfile.end, rfile.signature) for rfile in job_info.files]
-
- def initInfo(self):
- if not self.resolution:
- self.resolution = tuple(getFileInfo(self.files[0].filepath, ["bpy.context.scene.render.resolution_x", "bpy.context.scene.render.resolution_y", "bpy.context.scene.render.resolution_percentage"]))
-
- def save(self):
- if self.save_path:
- f = open(os.path.join(self.save_path, "job.txt"), "w")
- f.write(json.dumps(self.serialize()))
- f.close()
-
- def edit(self, info_map):
- if "status" in info_map:
- self.status = info_map["status"]
-
- if "priority" in info_map:
- self.priority = info_map["priority"]
-
- if "chunks" in info_map:
- self.chunks = info_map["chunks"]
-
- def testStart(self):
- # Don't test files for versionned jobs
- if not self.version_info:
- for f in self.files:
- if not f.test():
- return False
-
- self.start()
- self.initInfo()
- return True
-
- def testFinished(self):
- for f in self.frames:
- if f.status == QUEUED or f.status == DISPATCHED:
- break
- else:
- self.status = JOB_FINISHED
-
- def pause(self, status = None):
- if self.status not in {JOB_PAUSED, JOB_QUEUED}:
- return
-
- if status is None:
- self.status = JOB_PAUSED if self.status == JOB_QUEUED else JOB_QUEUED
- elif status:
- self.status = JOB_QUEUED
- else:
- self.status = JOB_PAUSED
-
- def start(self):
- self.status = JOB_QUEUED
-
- def addLog(self, frames):
- log_name = "_".join(("%06d" % f for f in frames)) + ".log"
- log_path = os.path.join(self.save_path, log_name)
-
- for number in frames:
- frame = self[number]
- if frame:
- frame.log_path = log_path
-
- def addFrame(self, frame_number, command):
- frame = MRenderFrame(frame_number, command)
- self.frames.append(frame)
- return frame
-
- def reset(self, all):
- for f in self.frames:
- f.reset(all)
-
- def getFrames(self):
- frames = []
- for f in self.frames:
- if f.status == QUEUED:
- self.last_dispatched = time.time()
- frames.append(f)
- if len(frames) >= self.chunks:
- break
-
- return frames
-
-class MRenderFrame(netrender.model.RenderFrame):
- def __init__(self, frame, command):
- super().__init__()
- self.number = frame
- self.slave = None
- self.time = 0
- self.status = QUEUED
- self.command = command
-
- self.log_path = None
-
- def reset(self, all):
- if all or self.status == ERROR:
- self.log_path = None
- self.slave = None
- self.time = 0
- self.status = QUEUED
-
-
-# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
-# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-file_pattern = re.compile("/file_([a-zA-Z0-9]+)_([0-9]+)")
-render_pattern = re.compile("/render_([a-zA-Z0-9]+)_([0-9]+).exr")
-thumb_pattern = re.compile("/thumb_([a-zA-Z0-9]+)_([0-9]+).jpg")
-log_pattern = re.compile("/log_([a-zA-Z0-9]+)_([0-9]+).log")
-reset_pattern = re.compile("/reset(all|)_([a-zA-Z0-9]+)_([0-9]+)")
-cancel_pattern = re.compile("/cancel_([a-zA-Z0-9]+)")
-pause_pattern = re.compile("/pause_([a-zA-Z0-9]+)")
-edit_pattern = re.compile("/edit_([a-zA-Z0-9]+)")
-
-class RenderHandler(http.server.BaseHTTPRequestHandler):
- def log_message(self, format, *args):
- # override because the original calls self.address_string(), which
- # is extremely slow due to some timeout..
- sys.stderr.write("[%s] %s\n" % (self.log_date_time_string(), format%args))
-
- def getInfoMap(self):
- length = int(self.headers['content-length'])
-
- if length > 0:
- msg = str(self.rfile.read(length), encoding='utf8')
- return json.loads(msg)
- else:
- return {}
-
- def send_head(self, code = http.client.OK, headers = {}, content = "application/octet-stream"):
- self.send_response(code)
- self.send_header("Content-type", content)
-
- for key, value in headers.items():
- self.send_header(key, value)
-
- self.end_headers()
-
- def do_HEAD(self):
-
- if self.path == "/status":
- job_id = self.headers.get('job-id', "")
- job_frame = int(self.headers.get('job-frame', -1))
-
- job = self.server.getJobID(job_id)
- if job:
- frame = job[job_frame]
-
-
- if frame:
- self.send_head(http.client.OK)
- else:
- # no such frame
- self.send_head(http.client.NO_CONTENT)
- else:
- # no such job id
- self.send_head(http.client.NO_CONTENT)
-
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
- def do_GET(self):
-
- if self.path == "/version":
- self.send_head()
- self.server.stats("", "Version check")
- self.wfile.write(VERSION)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path.startswith("/render"):
- match = render_pattern.match(self.path)
-
- if match:
- job_id = match.groups()[0]
- frame_number = int(match.groups()[1])
-
- job = self.server.getJobID(job_id)
-
- if job:
- frame = job[frame_number]
-
- if frame:
- if frame.status in (QUEUED, DISPATCHED):
- self.send_head(http.client.ACCEPTED)
- elif frame.status == DONE:
- self.server.stats("", "Sending result to client")
-
- filename = os.path.join(job.save_path, "%06d.exr" % frame_number)
-
- f = open(filename, 'rb')
- self.send_head(content = "image/x-exr")
- shutil.copyfileobj(f, self.wfile)
- f.close()
- elif frame.status == ERROR:
- self.send_head(http.client.PARTIAL_CONTENT)
- else:
- # no such frame
- self.send_head(http.client.NO_CONTENT)
- else:
- # no such job id
- self.send_head(http.client.NO_CONTENT)
- else:
- # invalid url
- self.send_head(http.client.NO_CONTENT)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path.startswith("/thumb"):
- match = thumb_pattern.match(self.path)
-
- if match:
- job_id = match.groups()[0]
- frame_number = int(match.groups()[1])
-
- job = self.server.getJobID(job_id)
-
- if job:
- frame = job[frame_number]
-
- if frame:
- if frame.status in (QUEUED, DISPATCHED):
- self.send_head(http.client.ACCEPTED)
- elif frame.status == DONE:
- filename = os.path.join(job.save_path, "%06d.exr" % frame_number)
-
- thumbname = thumbnail.generate(filename)
-
- if thumbname:
- f = open(thumbname, 'rb')
- self.send_head(content = "image/jpeg")
- shutil.copyfileobj(f, self.wfile)
- f.close()
- else: # thumbnail couldn't be generated
- self.send_head(http.client.PARTIAL_CONTENT)
- return
- elif frame.status == ERROR:
- self.send_head(http.client.PARTIAL_CONTENT)
- else:
- # no such frame
- self.send_head(http.client.NO_CONTENT)
- else:
- # no such job id
- self.send_head(http.client.NO_CONTENT)
- else:
- # invalid url
- self.send_head(http.client.NO_CONTENT)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path.startswith("/log"):
- match = log_pattern.match(self.path)
-
- if match:
- job_id = match.groups()[0]
- frame_number = int(match.groups()[1])
-
- job = self.server.getJobID(job_id)
-
- if job:
- frame = job[frame_number]
-
- if frame:
- if not frame.log_path or frame.status in (QUEUED, DISPATCHED):
- self.send_head(http.client.PROCESSING)
- else:
- self.server.stats("", "Sending log to client")
- f = open(frame.log_path, 'rb')
-
- self.send_head(content = "text/plain")
-
- shutil.copyfileobj(f, self.wfile)
-
- f.close()
- else:
- # no such frame
- self.send_head(http.client.NO_CONTENT)
- else:
- # no such job id
- self.send_head(http.client.NO_CONTENT)
- else:
- # invalid URL
- self.send_head(http.client.NO_CONTENT)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path == "/status":
- job_id = self.headers.get('job-id', "")
- job_frame = int(self.headers.get('job-frame', -1))
-
- if job_id:
-
- job = self.server.getJobID(job_id)
- if job:
- if job_frame != -1:
- frame = job[frame]
-
- if frame:
- message = frame.serialize()
- else:
- # no such frame
- self.send_heat(http.client.NO_CONTENT)
- return
- else:
- message = job.serialize()
- else:
- # no such job id
- self.send_head(http.client.NO_CONTENT)
- return
- else: # status of all jobs
- message = []
-
- for job in self.server:
- message.append(job.serialize())
-
-
- self.server.stats("", "Sending status")
- self.send_head()
- self.wfile.write(bytes(json.dumps(message), encoding='utf8'))
-
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path == "/job":
- self.server.balance()
-
- slave_id = self.headers['slave-id']
-
- slave = self.server.getSeenSlave(slave_id)
-
- if slave: # only if slave id is valid
- job, frames = self.server.newDispatch(slave_id)
-
- if job and frames:
- for f in frames:
- print("dispatch", f.number)
- f.status = DISPATCHED
- f.slave = slave
-
- slave.job = job
- slave.job_frames = [f.number for f in frames]
-
- self.send_head(headers={"job-id": job.id})
-
- message = job.serialize(frames)
-
- self.wfile.write(bytes(json.dumps(message), encoding='utf8'))
-
- self.server.stats("", "Sending job to slave")
- else:
- # no job available, return error code
- slave.job = None
- slave.job_frames = []
-
- self.send_head(http.client.ACCEPTED)
- else: # invalid slave id
- self.send_head(http.client.NO_CONTENT)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path.startswith("/file"):
- match = file_pattern.match(self.path)
-
- if match:
- slave_id = self.headers['slave-id']
- slave = self.server.getSeenSlave(slave_id)
-
- if not slave:
- # invalid slave id
- print("invalid slave id")
-
- job_id = match.groups()[0]
- file_index = int(match.groups()[1])
-
- job = self.server.getJobID(job_id)
-
- if job:
- render_file = job.files[file_index]
-
- if render_file:
- self.server.stats("", "Sending file to slave")
- f = open(render_file.filepath, 'rb')
-
- self.send_head()
- shutil.copyfileobj(f, self.wfile)
-
- f.close()
- else:
- # no such file
- self.send_head(http.client.NO_CONTENT)
- else:
- # no such job id
- self.send_head(http.client.NO_CONTENT)
- else: # invalid url
- self.send_head(http.client.NO_CONTENT)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path == "/slaves":
- message = []
-
- self.server.stats("", "Sending slaves status")
-
- for slave in self.server.slaves:
- message.append(slave.serialize())
-
- self.send_head()
-
- self.wfile.write(bytes(json.dumps(message), encoding='utf8'))
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- else:
- # hand over the rest to the html section
- netrender.master_html.get(self)
-
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- def do_POST(self):
-
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- if self.path == "/job":
-
- length = int(self.headers['content-length'])
-
- job_info = netrender.model.RenderJob.materialize(json.loads(str(self.rfile.read(length), encoding='utf8')))
-
- job_id = self.server.nextJobID()
-
- job = MRenderJob(job_id, job_info)
-
- for frame in job_info.frames:
- frame = job.addFrame(frame.number, frame.command)
-
- self.server.addJob(job)
-
- headers={"job-id": job_id}
-
- if job.testStart():
- self.server.stats("", "New job, started")
- self.send_head(headers=headers)
- else:
- self.server.stats("", "New job, missing files (%i total)" % len(job.files))
- self.send_head(http.client.ACCEPTED, headers=headers)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path.startswith("/edit"):
- match = edit_pattern.match(self.path)
-
- if match:
- job_id = match.groups()[0]
-
- job = self.server.getJobID(job_id)
-
- if job:
- info_map = self.getInfoMap()
-
- job.edit(info_map)
- self.send_head()
- else:
- # no such job id
- self.send_head(http.client.NO_CONTENT)
- else:
- # invalid url
- self.send_head(http.client.NO_CONTENT)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path == "/balance_limit":
- info_map = self.getInfoMap()
- for rule_id, limit in info_map.items():
- try:
- rule = self.server.balancer.ruleByID(rule_id)
- if rule:
- rule.setLimit(limit)
- except:
- pass # invalid type
-
- self.send_head()
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path == "/balance_enable":
- info_map = self.getInfoMap()
- for rule_id, enabled in info_map.items():
- rule = self.server.balancer.ruleByID(rule_id)
- if rule:
- rule.enabled = enabled
-
- self.send_head()
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path.startswith("/cancel"):
- match = cancel_pattern.match(self.path)
-
- if match:
- info_map = self.getInfoMap()
- clear = info_map.get("clear", False)
-
- job_id = match.groups()[0]
-
- job = self.server.getJobID(job_id)
-
- if job:
- self.server.stats("", "Cancelling job")
- self.server.removeJob(job, clear)
- self.send_head()
- else:
- # no such job id
- self.send_head(http.client.NO_CONTENT)
- else:
- # invalid url
- self.send_head(http.client.NO_CONTENT)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path.startswith("/pause"):
- match = pause_pattern.match(self.path)
-
- if match:
- info_map = self.getInfoMap()
- status = info_map.get("status", None)
-
- job_id = match.groups()[0]
-
- job = self.server.getJobID(job_id)
-
- if job:
- self.server.stats("", "Pausing job")
- job.pause(status)
- self.send_head()
- else:
- # no such job id
- self.send_head(http.client.NO_CONTENT)
- else:
- # invalid url
- self.send_head(http.client.NO_CONTENT)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path == "/clear":
- # cancel all jobs
- info_map = self.getInfoMap()
- clear = info_map.get("clear", False)
-
- self.server.stats("", "Clearing jobs")
- self.server.clear(clear)
-
- self.send_head()
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path.startswith("/reset"):
- match = reset_pattern.match(self.path)
-
- if match:
- all = match.groups()[0] == 'all'
- job_id = match.groups()[1]
- job_frame = int(match.groups()[2])
-
- job = self.server.getJobID(job_id)
-
- if job:
- if job_frame != 0:
-
- frame = job[job_frame]
- if frame:
- self.server.stats("", "Reset job frame")
- frame.reset(all)
- self.send_head()
- else:
- # no such frame
- self.send_head(http.client.NO_CONTENT)
-
- else:
- self.server.stats("", "Reset job")
- job.reset(all)
- self.send_head()
-
- else: # job not found
- self.send_head(http.client.NO_CONTENT)
- else: # invalid url
- self.send_head(http.client.NO_CONTENT)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path == "/slave":
- length = int(self.headers['content-length'])
- job_frame_string = self.headers['job-frame']
-
- self.server.stats("", "New slave connected")
-
- slave_info = netrender.model.RenderSlave.materialize(json.loads(str(self.rfile.read(length), encoding='utf8')), cache = False)
-
- slave_id = self.server.addSlave(slave_info.name, self.client_address, slave_info.stats)
-
- self.send_head(headers = {"slave-id": slave_id})
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path == "/log":
- length = int(self.headers['content-length'])
-
- log_info = netrender.model.LogFile.materialize(json.loads(str(self.rfile.read(length), encoding='utf8')))
-
- slave_id = log_info.slave_id
-
- slave = self.server.getSeenSlave(slave_id)
-
- if slave: # only if slave id is valid
- job = self.server.getJobID(log_info.job_id)
-
- if job:
- self.server.stats("", "Log announcement")
- job.addLog(log_info.frames)
- self.send_head(http.client.OK)
- else:
- # no such job id
- self.send_head(http.client.NO_CONTENT)
- else: # invalid slave id
- self.send_head(http.client.NO_CONTENT)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- def do_PUT(self):
-
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- if self.path.startswith("/file"):
- match = file_pattern.match(self.path)
-
- if match:
- self.server.stats("", "Receiving job")
-
- length = int(self.headers['content-length'])
- job_id = match.groups()[0]
- file_index = int(match.groups()[1])
-
- job = self.server.getJobID(job_id)
-
- if job:
-
- render_file = job.files[file_index]
-
- if render_file:
- main_file = job.files[0].filepath # filename of the first file
-
- main_path, main_name = os.path.split(main_file)
-
- if file_index > 0:
- file_path = prefixPath(job.save_path, render_file.filepath, main_path)
- else:
- file_path = os.path.join(job.save_path, main_name)
-
- buf = self.rfile.read(length)
-
- # add same temp file + renames as slave
-
- f = open(file_path, "wb")
- f.write(buf)
- f.close()
- del buf
-
- render_file.filepath = file_path # set the new path
-
- if job.testStart():
- self.server.stats("", "File upload, starting job")
- self.send_head(http.client.OK)
- else:
- self.server.stats("", "File upload, file missings")
- self.send_head(http.client.ACCEPTED)
- else: # invalid file
- print("file not found", job_id, file_index)
- self.send_head(http.client.NO_CONTENT)
- else: # job not found
- print("job not found", job_id, file_index)
- self.send_head(http.client.NO_CONTENT)
- else: # invalid url
- print("no match")
- self.send_head(http.client.NO_CONTENT)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path == "/render":
- self.server.stats("", "Receiving render result")
-
- # need some message content here or the slave doesn't like it
- self.wfile.write(bytes("foo", encoding='utf8'))
-
- slave_id = self.headers['slave-id']
-
- slave = self.server.getSeenSlave(slave_id)
-
- if slave: # only if slave id is valid
- job_id = self.headers['job-id']
-
- job = self.server.getJobID(job_id)
-
- if job:
- job_frame = int(self.headers['job-frame'])
- job_result = int(self.headers['job-result'])
- job_time = float(self.headers['job-time'])
-
- frame = job[job_frame]
-
- if frame:
- if job.hasRenderResult():
- if job_result == DONE:
- length = int(self.headers['content-length'])
- buf = self.rfile.read(length)
- f = open(os.path.join(job.save_path, "%06d.exr" % job_frame), 'wb')
- f.write(buf)
- f.close()
-
- del buf
- elif job_result == ERROR:
- # blacklist slave on this job on error
- # slaves might already be in blacklist if errors on the whole chunk
- if not slave.id in job.blacklist:
- job.blacklist.append(slave.id)
-
- slave.finishedFrame(job_frame)
-
- frame.status = job_result
- frame.time = job_time
-
- job.testFinished()
-
- self.send_head()
- else: # frame not found
- self.send_head(http.client.NO_CONTENT)
- else: # job not found
- self.send_head(http.client.NO_CONTENT)
- else: # invalid slave id
- self.send_head(http.client.NO_CONTENT)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path == "/thumb":
- self.server.stats("", "Receiving thumbnail result")
-
- # need some message content here or the slave doesn't like it
- self.wfile.write(bytes("foo", encoding='utf8'))
-
- slave_id = self.headers['slave-id']
-
- slave = self.server.getSeenSlave(slave_id)
-
- if slave: # only if slave id is valid
- job_id = self.headers['job-id']
-
- job = self.server.getJobID(job_id)
-
- if job:
- job_frame = int(self.headers['job-frame'])
-
- frame = job[job_frame]
-
- if frame:
- if job.hasRenderResult():
- length = int(self.headers['content-length'])
- buf = self.rfile.read(length)
- f = open(os.path.join(job.save_path, "%06d.jpg" % job_frame), 'wb')
- f.write(buf)
- f.close()
-
- del buf
-
- else: # frame not found
- self.send_head(http.client.NO_CONTENT)
- else: # job not found
- self.send_head(http.client.NO_CONTENT)
- else: # invalid slave id
- self.send_head(http.client.NO_CONTENT)
- # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
- elif self.path.startswith("/log"):
- self.server.stats("", "Receiving log file")
-
- match = log_pattern.match(self.path)
-
- if match:
- job_id = match.groups()[0]
-
- job = self.server.getJobID(job_id)
-
- if job:
- job_frame = int(match.groups()[1])
-
- frame = job[job_frame]
-
- if frame and frame.log_path:
- length = int(self.headers['content-length'])
- buf = self.rfile.read(length)
- f = open(frame.log_path, 'ab')
- f.write(buf)
- f.close()
-
- del buf
-
- self.server.getSeenSlave(self.headers['slave-id'])
-
- self.send_head()
- else: # frame not found
- self.send_head(http.client.NO_CONTENT)
- else: # job not found
- self.send_head(http.client.NO_CONTENT)
- else: # invalid url
- self.send_head(http.client.NO_CONTENT)
-
-class RenderMasterServer(socketserver.ThreadingMixIn, http.server.HTTPServer):
- def __init__(self, address, handler_class, path, subdir=True):
- super().__init__(address, handler_class)
- self.jobs = []
- self.jobs_map = {}
- self.slaves = []
- self.slaves_map = {}
- self.job_id = 0
-
- if subdir:
- self.path = os.path.join(path, "master_" + str(os.getpid()))
- else:
- self.path = path
-
- self.slave_timeout = 5 # 5 mins: need a parameter for that
-
- self.balancer = netrender.balancing.Balancer()
- self.balancer.addRule(netrender.balancing.RatingUsageByCategory(self.getJobs))
- self.balancer.addRule(netrender.balancing.RatingUsage())
- self.balancer.addException(netrender.balancing.ExcludeQueuedEmptyJob())
- self.balancer.addException(netrender.balancing.ExcludeSlavesLimit(self.countJobs, self.countSlaves, limit = 0.9))
- self.balancer.addPriority(netrender.balancing.NewJobPriority())
- self.balancer.addPriority(netrender.balancing.MinimumTimeBetweenDispatchPriority(limit = 2))
-
- if not os.path.exists(self.path):
- os.mkdir(self.path)
-
- def restore(self, jobs, slaves, balancer = None):
- self.jobs = jobs
- self.jobs_map = {}
-
- for job in self.jobs:
- self.jobs_map[job.id] = job
- self.job_id = max(self.job_id, int(job.id))
-
- self.slaves = slaves
- for slave in self.slaves:
- self.slaves_map[slave.id] = slave
-
- if balancer:
- self.balancer = balancer
-
-
- def nextJobID(self):
- self.job_id += 1
- return str(self.job_id)
-
- def addSlave(self, name, address, stats):
- slave = MRenderSlave(name, address, stats)
- self.slaves.append(slave)
- self.slaves_map[slave.id] = slave
-
- return slave.id
-
- def removeSlave(self, slave):
- self.slaves.remove(slave)
- self.slaves_map.pop(slave.id)
-
- def getSlave(self, slave_id):
- return self.slaves_map.get(slave_id)
-
- def getSeenSlave(self, slave_id):
- slave = self.getSlave(slave_id)
- if slave:
- slave.seen()
-
- return slave
-
- def timeoutSlaves(self):
- removed = []
-
- t = time.time()
-
- for slave in self.slaves:
- if (t - slave.last_seen) / 60 > self.slave_timeout:
- removed.append(slave)
-
- if slave.job:
- for f in slave.job_frames:
- slave.job[f].status = ERROR
-
- for slave in removed:
- self.removeSlave(slave)
-
- def updateUsage(self):
- blend = 0.5
- for job in self.jobs:
- job.usage *= (1 - blend)
-
- if self.slaves:
- slave_usage = blend / self.countSlaves()
-
- for slave in self.slaves:
- if slave.job:
- slave.job.usage += slave_usage
-
-
- def clear(self, clear_files = False):
- removed = self.jobs[:]
-
- for job in removed:
- self.removeJob(job, clear_files)
-
- def balance(self):
- self.balancer.balance(self.jobs)
-
- def getJobs(self):
- return self.jobs
-
- def countJobs(self, status = JOB_QUEUED):
- total = 0
- for j in self.jobs:
- if j.status == status:
- total += 1
-
- return total
-
- def countSlaves(self):
- return len(self.slaves)
-
- def removeJob(self, job, clear_files = False):
- self.jobs.remove(job)
- self.jobs_map.pop(job.id)
-
- if clear_files:
- shutil.rmtree(job.save_path)
-
- for slave in self.slaves:
- if slave.job == job:
- slave.job = None
- slave.job_frames = []
-
- def addJob(self, job):
- self.jobs.append(job)
- self.jobs_map[job.id] = job
-
- # create job directory
- job.save_path = os.path.join(self.path, "job_" + job.id)
- if not os.path.exists(job.save_path):
- os.mkdir(job.save_path)
-
- job.save()
-
- def getJobID(self, id):
- return self.jobs_map.get(id)
-
- def __iter__(self):
- for job in self.jobs:
- yield job
-
- def newDispatch(self, slave_id):
- if self.jobs:
- for job in self.jobs:
- if not self.balancer.applyExceptions(job) and slave_id not in job.blacklist:
- return job, job.getFrames()
-
- return None, None
-
-def clearMaster(path):
- shutil.rmtree(path)
-
-def createMaster(address, clear, path):
- filepath = os.path.join(path, "blender_master.data")
-
- if not clear and os.path.exists(filepath):
- print("loading saved master:", filepath)
- with open(filepath, 'rb') as f:
- path, jobs, slaves = pickle.load(f)
-
- httpd = RenderMasterServer(address, RenderHandler, path, subdir=False)
- httpd.restore(jobs, slaves)
-
- return httpd
-
- return RenderMasterServer(address, RenderHandler, path)
-
-def saveMaster(path, httpd):
- filepath = os.path.join(path, "blender_master.data")
-
- with open(filepath, 'wb') as f:
- pickle.dump((httpd.path, httpd.jobs, httpd.slaves), f, pickle.HIGHEST_PROTOCOL)
-
-def runMaster(address, broadcast, clear, path, update_stats, test_break):
- httpd = createMaster(address, clear, path)
- httpd.timeout = 1
- httpd.stats = update_stats
-
- if broadcast:
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
-
- start_time = time.time() - 2
-
- while not test_break():
- try:
- httpd.handle_request()
- except select.error:
- pass
-
- if time.time() - start_time >= 2: # need constant here
- httpd.timeoutSlaves()
-
- httpd.updateUsage()
-
- if broadcast:
- print("broadcasting address")
- s.sendto(bytes("%i" % address[1], encoding='utf8'), 0, ('<broadcast>', 8000))
- start_time = time.time()
-
- httpd.server_close()
- if clear:
- clearMaster(httpd.path)
- else:
- saveMaster(path, httpd)
-
diff --git a/release/scripts/io/netrender/master_html.py b/release/scripts/io/netrender/master_html.py
deleted file mode 100644
index 877273207a8..00000000000
--- a/release/scripts/io/netrender/master_html.py
+++ /dev/null
@@ -1,315 +0,0 @@
-# ##### 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 #####
-
-import os
-import re
-import shutil
-from netrender.utils import *
-import netrender.model
-
-src_folder = os.path.split(__file__)[0]
-
-def get(handler):
- def output(text):
- handler.wfile.write(bytes(text, encoding='utf8'))
-
- def head(title, refresh = False):
- output("<html><head>")
- if refresh:
- output("<meta http-equiv='refresh' content=5>")
- output("<script src='/html/netrender.js' type='text/javascript'></script>")
-# output("<script src='/html/json2.js' type='text/javascript'></script>")
- output("<title>")
- output(title)
- output("</title></head><body>")
- output("<link rel='stylesheet' href='/html/netrender.css' type='text/css'>")
-
-
- def link(text, url, script=""):
- return "<a href='%s' %s>%s</a>" % (url, script, text)
-
- def tag(name, text, attr=""):
- return "<%s %s>%s</%s>" % (name, attr, text, name)
-
- def startTable(border=1, class_style = None, caption = None):
- output("<table border='%i'" % border)
-
- if class_style:
- output(" class='%s'" % class_style)
-
- output(">")
-
- if caption:
- output("<caption>%s</caption>" % caption)
-
- def headerTable(*headers):
- output("<thead><tr>")
-
- for c in headers:
- output("<td>" + c + "</td>")
-
- output("</tr></thead>")
-
- def rowTable(*data, id = None, class_style = None, extra = None):
- output("<tr")
-
- if id:
- output(" id='%s'" % id)
-
- if class_style:
- output(" class='%s'" % class_style)
-
- if extra:
- output(" %s" % extra)
-
- output(">")
-
- for c in data:
- output("<td>" + str(c) + "</td>")
-
- output("</tr>")
-
- def endTable():
- output("</table>")
-
- def checkbox(title, value, script=""):
- return """<input type="checkbox" title="%s" %s %s>""" % (title, "checked" if value else "", ("onclick=\"%s\"" % script) if script else "")
-
- if handler.path == "/html/netrender.js":
- f = open(os.path.join(src_folder, "netrender.js"), 'rb')
-
- handler.send_head(content = "text/javascript")
- shutil.copyfileobj(f, handler.wfile)
-
- f.close()
- elif handler.path == "/html/netrender.css":
- f = open(os.path.join(src_folder, "netrender.css"), 'rb')
-
- handler.send_head(content = "text/css")
- shutil.copyfileobj(f, handler.wfile)
-
- f.close()
- elif handler.path == "/html" or handler.path == "/":
- handler.send_head(content = "text/html")
- head("NetRender", refresh = True)
-
- output("<h2>Jobs</h2>")
-
- startTable()
- headerTable(
- "&nbsp;",
- "id",
- "name",
- "category",
- "type",
- "chunks",
- "priority",
- "usage",
- "wait",
- "status",
- "length",
- "done",
- "dispatched",
- "error",
- "priority",
- "exception"
- )
-
- handler.server.balance()
-
- for job in handler.server.jobs:
- results = job.framesStatus()
- rowTable(
- """<button title="cancel job" onclick="cancel_job('%s');">X</button>""" % job.id +
- """<button title="pause job" onclick="request('/pause_%s', null);">P</button>""" % job.id +
- """<button title="reset all frames" onclick="request('/resetall_%s_0', null);">R</button>""" % job.id,
- job.id,
- link(job.name, "/html/job" + job.id),
- job.category if job.category else "<i>None</i>",
- netrender.model.JOB_TYPES[job.type],
- str(job.chunks) +
- """<button title="increase chunks size" onclick="request('/edit_%s', &quot;{'chunks': %i}&quot;);">+</button>""" % (job.id, job.chunks + 1) +
- """<button title="decrease chunks size" onclick="request('/edit_%s', &quot;{'chunks': %i}&quot;);" %s>-</button>""" % (job.id, job.chunks - 1, "disabled=True" if job.chunks == 1 else ""),
- str(job.priority) +
- """<button title="increase priority" onclick="request('/edit_%s', &quot;{'priority': %i}&quot;);">+</button>""" % (job.id, job.priority + 1) +
- """<button title="decrease priority" onclick="request('/edit_%s', &quot;{'priority': %i}&quot;);" %s>-</button>""" % (job.id, job.priority - 1, "disabled=True" if job.priority == 1 else ""),
- "%0.1f%%" % (job.usage * 100),
- "%is" % int(time.time() - job.last_dispatched),
- job.statusText(),
- len(job),
- results[DONE],
- results[DISPATCHED],
- str(results[ERROR]) +
- """<button title="reset error frames" onclick="request('/reset_%s_0', null);" %s>R</button>""" % (job.id, "disabled=True" if not results[ERROR] else ""),
- "yes" if handler.server.balancer.applyPriorities(job) else "no",
- "yes" if handler.server.balancer.applyExceptions(job) else "no"
- )
-
- endTable()
-
- output("<h2>Slaves</h2>")
-
- startTable()
- headerTable("name", "address", "last seen", "stats", "job")
-
- for slave in handler.server.slaves:
- rowTable(slave.name, slave.address[0], time.ctime(slave.last_seen), slave.stats, link(slave.job.name, "/html/job" + slave.job.id) if slave.job else "None")
-
- endTable()
-
- output("<h2>Configuration</h2>")
-
- output("""<button title="remove all jobs" onclick="clear_jobs();">CLEAR JOB LIST</button>""")
-
- startTable(caption = "Rules", class_style = "rules")
-
- headerTable("type", "enabled", "description", "limit")
-
- for rule in handler.server.balancer.rules:
- rowTable(
- "rating",
- checkbox("", rule.enabled, "balance_enable('%s', '%s')" % (rule.id(), str(not rule.enabled).lower())),
- rule,
- rule.str_limit() +
- """<button title="edit limit" onclick="balance_edit('%s', '%s');">edit</button>""" % (rule.id(), str(rule.limit)) if hasattr(rule, "limit") else "&nbsp;"
- )
-
- for rule in handler.server.balancer.priorities:
- rowTable(
- "priority",
- checkbox("", rule.enabled, "balance_enable('%s', '%s')" % (rule.id(), str(not rule.enabled).lower())),
- rule,
- rule.str_limit() +
- """<button title="edit limit" onclick="balance_edit('%s', '%s');">edit</button>""" % (rule.id(), str(rule.limit)) if hasattr(rule, "limit") else "&nbsp;"
- )
-
- for rule in handler.server.balancer.exceptions:
- rowTable(
- "exception",
- checkbox("", rule.enabled, "balance_enable('%s', '%s')" % (rule.id(), str(not rule.enabled).lower())),
- rule,
- rule.str_limit() +
- """<button title="edit limit" onclick="balance_edit('%s', '%s');">edit</button>""" % (rule.id(), str(rule.limit)) if hasattr(rule, "limit") else "&nbsp;"
- )
-
- endTable()
-
- output("</body></html>")
-
- elif handler.path.startswith("/html/job"):
- handler.send_head(content = "text/html")
- job_id = handler.path[9:]
-
- head("NetRender")
-
- job = handler.server.getJobID(job_id)
-
- if job:
- output("<h2>Render Information</h2>")
-
- job.initInfo()
-
- startTable()
-
- rowTable("resolution", "%ix%i at %i%%" % job.resolution)
-
- endTable()
-
-
- if job.type == netrender.model.JOB_BLENDER:
- output("<h2>Files</h2>")
-
- startTable()
- headerTable("path")
-
- tot_cache = 0
- tot_fluid = 0
-
- rowTable(job.files[0].filepath)
- rowTable("Other Files", class_style = "toggle", extra = "onclick='toggleDisplay(&quot;.other&quot;, &quot;none&quot;, &quot;table-row&quot;)'")
-
- for file in job.files:
- if file.filepath.endswith(".bphys"):
- tot_cache += 1
- elif file.filepath.endswith(".bobj.gz") or file.filepath.endswith(".bvel.gz"):
- tot_fluid += 1
- else:
- if file != job.files[0]:
- rowTable(file.filepath, class_style = "other")
-
- if tot_cache > 0:
- rowTable("%i physic cache files" % tot_cache, class_style = "toggle", extra = "onclick='toggleDisplay(&quot;.cache&quot;, &quot;none&quot;, &quot;table-row&quot;)'")
- for file in job.files:
- if file.filepath.endswith(".bphys"):
- rowTable(os.path.split(file.filepath)[1], class_style = "cache")
-
- if tot_fluid > 0:
- rowTable("%i fluid bake files" % tot_fluid, class_style = "toggle", extra = "onclick='toggleDisplay(&quot;.fluid&quot;, &quot;none&quot;, &quot;table-row&quot;)'")
- for file in job.files:
- if file.filepath.endswith(".bobj.gz") or file.filepath.endswith(".bvel.gz"):
- rowTable(os.path.split(file.filepath)[1], class_style = "fluid")
-
- endTable()
- elif job.type == netrender.model.JOB_VCS:
- output("<h2>Versioning</h2>")
-
- startTable()
-
- rowTable("System", job.version_info.system.name)
- rowTable("Remote Path", job.version_info.rpath)
- rowTable("Working Path", job.version_info.wpath)
- rowTable("Revision", job.version_info.revision)
- rowTable("Render File", job.files[0].filepath)
-
- endTable()
-
- if job.blacklist:
- output("<h2>Blacklist</h2>")
-
- startTable()
- headerTable("name", "address")
-
- for slave_id in job.blacklist:
- slave = handler.server.slaves_map[slave_id]
- rowTable(slave.name, slave.address[0])
-
- endTable()
-
- output("<h2>Frames</h2>")
-
- startTable()
- headerTable("no", "status", "render time", "slave", "log", "result", "")
-
- for frame in job.frames:
- rowTable(
- frame.number,
- frame.statusText(),
- "%.1fs" % frame.time,
- frame.slave.name if frame.slave else "&nbsp;",
- link("view log", logURL(job_id, frame.number)) if frame.log_path else "&nbsp;",
- link("view result", renderURL(job_id, frame.number)) + " [" +
- tag("span", "show", attr="class='thumb' onclick='showThumb(%s, %i)'" % (job.id, frame.number)) + "]" if frame.status == DONE else "&nbsp;",
- "<img name='thumb%i' title='hide thumbnails' src='' class='thumb' onclick='showThumb(%s, %i)'>" % (frame.number, job.id, frame.number)
- )
-
- endTable()
- else:
- output("no such job")
-
- output("</body></html>")
-
diff --git a/release/scripts/io/netrender/model.py b/release/scripts/io/netrender/model.py
deleted file mode 100644
index 5fc0bc2a0bb..00000000000
--- a/release/scripts/io/netrender/model.py
+++ /dev/null
@@ -1,360 +0,0 @@
-# ##### 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 #####
-
-import sys, os
-import http, http.client, http.server, urllib
-import subprocess, shutil, time, hashlib
-
-import netrender.versioning as versioning
-from netrender.utils import *
-
-class LogFile:
- def __init__(self, job_id = 0, slave_id = 0, frames = []):
- self.job_id = job_id
- self.slave_id = slave_id
- self.frames = frames
-
- def serialize(self):
- return {
- "job_id": self.job_id,
- "slave_id": self.slave_id,
- "frames": self.frames
- }
-
- @staticmethod
- def materialize(data):
- if not data:
- return None
-
- logfile = LogFile()
- logfile.job_id = data["job_id"]
- logfile.slave_id = data["slave_id"]
- logfile.frames = data["frames"]
-
- return logfile
-
-class RenderSlave:
- _slave_map = {}
-
- def __init__(self):
- self.id = ""
- self.name = ""
- self.address = ("",0)
- self.stats = ""
- self.total_done = 0
- self.total_error = 0
- self.last_seen = 0.0
-
- def serialize(self):
- return {
- "id": self.id,
- "name": self.name,
- "address": self.address,
- "stats": self.stats,
- "total_done": self.total_done,
- "total_error": self.total_error,
- "last_seen": self.last_seen
- }
-
- @staticmethod
- def materialize(data, cache = True):
- if not data:
- return None
-
- slave_id = data["id"]
-
- if cache and slave_id in RenderSlave._slave_map:
- return RenderSlave._slave_map[slave_id]
-
- slave = RenderSlave()
- slave.id = slave_id
- slave.name = data["name"]
- slave.address = data["address"]
- slave.stats = data["stats"]
- slave.total_done = data["total_done"]
- slave.total_error = data["total_error"]
- slave.last_seen = data["last_seen"]
-
- if cache:
- RenderSlave._slave_map[slave_id] = slave
-
- return slave
-
-JOB_BLENDER = 1
-JOB_PROCESS = 2
-JOB_VCS = 3
-
-JOB_TYPES = {
- JOB_BLENDER: "Blender",
- JOB_PROCESS: "Process",
- JOB_VCS: "Versioned",
- }
-
-class VersioningInfo:
- def __init__(self, info = None):
- self._system = None
- self.wpath = ""
- self.rpath = ""
- self.revision = ""
-
- @property
- def system(self):
- return self._system
-
- @system.setter
- def system(self, value):
- self._system = versioning.SYSTEMS[value]
-
- def update(self):
- self.system.update(self)
-
- def serialize(self):
- return {
- "wpath": self.wpath,
- "rpath": self.rpath,
- "revision": self.revision,
- "system": self.system.name
- }
-
- @staticmethod
- def generate(system, path):
- vs = VersioningInfo()
- vs.wpath = path
- vs.system = system
-
- vs.rpath = vs.system.path(path)
- vs.revision = vs.system.revision(path)
-
- return vs
-
-
- @staticmethod
- def materialize(data):
- if not data:
- return None
-
- vs = VersioningInfo()
- vs.wpath = data["wpath"]
- vs.rpath = data["rpath"]
- vs.revision = data["revision"]
- vs.system = data["system"]
-
- return vs
-
-
-class RenderFile:
- def __init__(self, filepath = "", index = 0, start = -1, end = -1, signature=0):
- self.filepath = filepath
- self.original_path = filepath
- self.signature = signature
- self.index = index
- self.start = start
- self.end = end
-
- def serialize(self):
- return {
- "filepath": self.filepath,
- "original_path": self.original_path,
- "index": self.index,
- "start": self.start,
- "end": self.end,
- "signature": self.signature
- }
-
- @staticmethod
- def materialize(data):
- if not data:
- return None
-
- rfile = RenderFile(data["filepath"], data["index"], data["start"], data["end"], data["signature"])
- rfile.original_path = data["original_path"]
-
- return rfile
-
-class RenderJob:
- def __init__(self, job_info = None):
- self.id = ""
- self.type = JOB_BLENDER
- self.name = ""
- self.category = "None"
- self.status = JOB_WAITING
- self.files = []
- self.chunks = 0
- self.priority = 0
- self.blacklist = []
-
- self.version_info = None
-
- self.resolution = None
-
- self.usage = 0.0
- self.last_dispatched = 0.0
- self.frames = []
-
- if job_info:
- self.type = job_info.type
- self.name = job_info.name
- self.category = job_info.category
- self.status = job_info.status
- self.files = job_info.files
- self.chunks = job_info.chunks
- self.priority = job_info.priority
- self.blacklist = job_info.blacklist
- self.version_info = job_info.version_info
-
- def hasRenderResult(self):
- return self.type in (JOB_BLENDER, JOB_VCS)
-
- def rendersWithBlender(self):
- return self.type in (JOB_BLENDER, JOB_VCS)
-
- def addFile(self, file_path, start=-1, end=-1, signed=True):
- if signed:
- signature = hashFile(file_path)
- else:
- signature = None
- self.files.append(RenderFile(file_path, len(self.files), start, end, signature))
-
- def addFrame(self, frame_number, command = ""):
- frame = RenderFrame(frame_number, command)
- self.frames.append(frame)
- return frame
-
- def __len__(self):
- return len(self.frames)
-
- def countFrames(self, status=QUEUED):
- total = 0
- for f in self.frames:
- if f.status == status:
- total += 1
-
- return total
-
- def countSlaves(self):
- return len(set((frame.slave for frame in self.frames if frame.status == DISPATCHED)))
-
- def statusText(self):
- return JOB_STATUS_TEXT[self.status]
-
- def framesStatus(self):
- results = {
- QUEUED: 0,
- DISPATCHED: 0,
- DONE: 0,
- ERROR: 0
- }
-
- for frame in self.frames:
- results[frame.status] += 1
-
- return results
-
- def __contains__(self, frame_number):
- for f in self.frames:
- if f.number == frame_number:
- return True
- else:
- return False
-
- def __getitem__(self, frame_number):
- for f in self.frames:
- if f.number == frame_number:
- return f
- else:
- return None
-
- def serialize(self, frames = None):
- min_frame = min((f.number for f in frames)) if frames else -1
- max_frame = max((f.number for f in frames)) if frames else -1
- return {
- "id": self.id,
- "type": self.type,
- "name": self.name,
- "category": self.category,
- "status": self.status,
- "files": [f.serialize() for f in self.files if f.start == -1 or not frames or (f.start <= max_frame and f.end >= min_frame)],
- "frames": [f.serialize() for f in self.frames if not frames or f in frames],
- "chunks": self.chunks,
- "priority": self.priority,
- "usage": self.usage,
- "blacklist": self.blacklist,
- "last_dispatched": self.last_dispatched,
- "version_info": self.version_info.serialize() if self.version_info else None,
- "resolution": self.resolution
- }
-
- @staticmethod
- def materialize(data):
- if not data:
- return None
-
- job = RenderJob()
- job.id = data["id"]
- job.type = data["type"]
- job.name = data["name"]
- job.category = data["category"]
- job.status = data["status"]
- job.files = [RenderFile.materialize(f) for f in data["files"]]
- job.frames = [RenderFrame.materialize(f) for f in data["frames"]]
- job.chunks = data["chunks"]
- job.priority = data["priority"]
- job.usage = data["usage"]
- job.blacklist = data["blacklist"]
- job.last_dispatched = data["last_dispatched"]
- job.resolution = data["resolution"]
-
- version_info = data.get("version_info", None)
- if version_info:
- job.version_info = VersioningInfo.materialize(version_info)
-
- return job
-
-class RenderFrame:
- def __init__(self, number = 0, command = ""):
- self.number = number
- self.time = 0
- self.status = QUEUED
- self.slave = None
- self.command = command
-
- def statusText(self):
- return FRAME_STATUS_TEXT[self.status]
-
- def serialize(self):
- return {
- "number": self.number,
- "time": self.time,
- "status": self.status,
- "slave": None if not self.slave else self.slave.serialize(),
- "command": self.command
- }
-
- @staticmethod
- def materialize(data):
- if not data:
- return None
-
- frame = RenderFrame()
- frame.number = data["number"]
- frame.time = data["time"]
- frame.status = data["status"]
- frame.slave = RenderSlave.materialize(data["slave"])
- frame.command = data["command"]
-
- return frame
diff --git a/release/scripts/io/netrender/netrender.css b/release/scripts/io/netrender/netrender.css
deleted file mode 100644
index 0c54690e002..00000000000
--- a/release/scripts/io/netrender/netrender.css
+++ /dev/null
@@ -1,88 +0,0 @@
-body {
- background-color:#eee;
- font-size:12px;
- font-family: "Lucida Sans","Lucida Sans Unicode","Lucida Grande",Lucida,sans-serif;
-
-}
-a {
- /*text-decoration:none;*/
- color:#666;
-}
-a:hover {
- color:#000;
-}
-h2 {
- background-color:#ddd;
- font-size:120%;
- padding:5px;
-}
-
-h2 {
- background-color:#ddd;
- font-size:110%;
- padding:5px;
-}
-
-table {
- text-align:center;
- border:0;
- background-color:#ddd;
- padding: 0px;
- margin: 0px;
-}
-thead{
- font-size:90%;
- color:#555;
- background-color:#ccc;
-}
-td {
- border:0;
- padding:2px;
- padding-left:10px;
- padding-right:10px;
- margin-left:20px;
- background-color:#ddd;
-}
-td:hover {
- background-color:#ccc;
-}
-tr {
- border:0;
-}
-button {
- color: #111;
- width: auto;
- height: auto;
-}
-
-.toggle {
- text-decoration: underline;
- cursor: pointer;
-}
-
-.cache {
- display: none;
-}
-
-.fluid {
- display: none;
-}
-
-.other {
- display: none;
-}
-
-.rules {
- width: 60em;
- text-align: left;
-}
-
-img.thumb {
- display: none;
- cursor: pointer;
-}
-
-span.thumb {
- text-decoration: underline;
- cursor: pointer;
-}
diff --git a/release/scripts/io/netrender/netrender.js b/release/scripts/io/netrender/netrender.js
deleted file mode 100644
index 1024a169571..00000000000
--- a/release/scripts/io/netrender/netrender.js
+++ /dev/null
@@ -1,146 +0,0 @@
-lastFrame = -1
-maxFrame = -1
-minFrame = -1
-
-function request(url, data)
-{
- xmlhttp = new XMLHttpRequest();
- xmlhttp.open("POST", url, false);
- xmlhttp.send(data);
- window.location.reload()
-}
-
-function edit(id, info)
-{
- request("/edit_" + id, info)
-}
-
-function clear_jobs()
-{
- var r=confirm("Also delete files on master?");
-
- if (r==true) {
- request('/clear', '{"clear":true}');
- } else {
- request('/clear', '{"clear":false}');
- }
-}
-
-function cancel_job(id)
-{
- var r=confirm("Also delete files on master?");
-
- if (r==true) {
- request('/cancel_' + id, '{"clear":true}');
- } else {
- request('/cancel_' + id, '{"clear":false}');
- }
-}
-
-function balance_edit(id, old_value)
-{
- var new_value = prompt("New limit", old_value);
- if (new_value != null && new_value != "") {
- request("/balance_limit", '{"' + id + '":"' + new_value + '"}');
- }
-}
-
-function balance_enable(id, value)
-{
- request("/balance_enable", '{"' + id + '":' + value + "}");
-}
-
-function showThumb(job, frame)
-{
- if (lastFrame != -1) {
- if (maxFrame != -1 && minFrame != -1) {
- if (frame >= minFrame && frame <= maxFrame) {
- for(i = minFrame; i <= maxFrame; i=i+1) {
- toggleThumb(job, i);
- }
- minFrame = -1;
- maxFrame = -1;
- lastFrame = -1;
- } else if (frame > maxFrame) {
- for(i = maxFrame+1; i <= frame; i=i+1) {
- toggleThumb(job, i);
- }
- maxFrame = frame;
- lastFrame = frame;
- } else {
- for(i = frame; i <= minFrame-1; i=i+1) {
- toggleThumb(job, i);
- }
- minFrame = frame;
- lastFrame = frame;
- }
- } else if (frame == lastFrame) {
- toggleThumb(job, frame);
- } else if (frame < lastFrame) {
- minFrame = frame;
- maxFrame = lastFrame;
-
- for(i = minFrame; i <= maxFrame-1; i=i+1) {
- toggleThumb(job, i);
- }
- lastFrame = frame;
- } else {
- minFrame = lastFrame;
- maxFrame = frame;
-
- for(i = minFrame+1; i <= maxFrame; i=i+1) {
- toggleThumb(job, i);
- }
- lastFrame = frame;
- }
- } else {
- toggleThumb(job, frame);
- }
-}
-
-function toggleThumb(job, frame)
-{
- img = document.images["thumb" + frame];
- url = "/thumb_" + job + "_" + frame + ".jpg"
-
- if (img.style.display == "block") {
- img.style.display = "none";
- img.src = "";
- lastFrame = -1;
- } else {
- img.src = url;
- img.style.display = "block";
- lastFrame = frame;
- }
-}
-
-function returnObjById( id )
-{
- if (document.getElementById)
- var returnVar = document.getElementById(id);
- else if (document.all)
- var returnVar = document.all[id];
- else if (document.layers)
- var returnVar = document.layers[id];
- return returnVar;
-}
-
-function toggleDisplay( className, value1, value2 )
-{
- style = getStyle(className)
-
- if (style.style["display"] == value1) {
- style.style["display"] = value2;
- } else {
- style.style["display"] = value1;
- }
-}
-
-function getStyle(className) {
- var classes = document.styleSheets[0].rules || document.styleSheets[0].cssRules
- for(var x=0;x<classes.length;x++) {
- if(classes[x].selectorText==className) {
- return classes[x];
- }
- }
-} \ No newline at end of file
diff --git a/release/scripts/io/netrender/operators.py b/release/scripts/io/netrender/operators.py
deleted file mode 100644
index f2c2fda7bde..00000000000
--- a/release/scripts/io/netrender/operators.py
+++ /dev/null
@@ -1,564 +0,0 @@
-# ##### 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 #####
-
-import bpy
-import sys, os
-import http, http.client, http.server, urllib, socket
-import webbrowser
-import json
-
-import netrender
-from netrender.utils import *
-import netrender.client as client
-import netrender.model
-import netrender.versioning as versioning
-
-class RENDER_OT_netslave_bake(bpy.types.Operator):
- '''NEED DESCRIPTION'''
- bl_idname = "render.netslavebake"
- bl_label = "Bake all in file"
-
- @classmethod
- def poll(cls, context):
- return True
-
- def execute(self, context):
- scene = context.scene
- netsettings = scene.network_render
-
- filename = bpy.data.filepath
- path, name = os.path.split(filename)
- root, ext = os.path.splitext(name)
- default_path = path + os.sep + "blendcache_" + root + os.sep # need an API call for that
- relative_path = os.sep + os.sep + "blendcache_" + root + os.sep
-
- # Force all point cache next to the blend file
- for object in bpy.data.objects:
- for modifier in object.modifiers:
- if modifier.type == 'FLUID_SIMULATION' and modifier.settings.type == "DOMAIN":
- modifier.settings.path = relative_path
- bpy.ops.fluid.bake({"active_object": object, "scene": scene})
- elif modifier.type == "CLOTH":
- modifier.point_cache.frame_step = 1
- modifier.point_cache.use_disk_cache = True
- modifier.point_cache.use_external = False
- elif modifier.type == "SOFT_BODY":
- modifier.point_cache.frame_step = 1
- modifier.point_cache.use_disk_cache = True
- modifier.point_cache.use_external = False
- elif modifier.type == "SMOKE" and modifier.smoke_type == "TYPE_DOMAIN":
- modifier.domain_settings.point_cache.use_step = 1
- modifier.domain_settings.point_cache.use_disk_cache = True
- modifier.domain_settings.point_cache.use_external = False
-
- # particles modifier are stupid and don't contain data
- # we have to go through the object property
- for psys in object.particle_systems:
- psys.point_cache.use_step = 1
- psys.point_cache.use_disk_cache = True
- psys.point_cache.use_external = False
- psys.point_cache.filepath = relative_path
-
- bpy.ops.ptcache.bake_all()
-
- #bpy.ops.wm.save_mainfile(filepath = path + os.sep + root + "_baked.blend")
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
-
-class RENDER_OT_netclientanim(bpy.types.Operator):
- '''Start rendering an animation on network'''
- bl_idname = "render.netclientanim"
- bl_label = "Animation on network"
-
- @classmethod
- def poll(cls, context):
- return True
-
- def execute(self, context):
- scene = context.scene
- netsettings = scene.network_render
-
- conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
-
- if conn:
- # Sending file
- scene.network_render.job_id = client.clientSendJob(conn, scene, True)
- conn.close()
-
- bpy.ops.render.render('INVOKE_AREA', animation=True)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
-
-class RENDER_OT_netclientrun(bpy.types.Operator):
- '''Start network rendering service'''
- bl_idname = "render.netclientstart"
- bl_label = "Start Service"
-
- @classmethod
- def poll(cls, context):
- return True
-
- def execute(self, context):
- bpy.ops.render.render('INVOKE_AREA', animation=True)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
-
-class RENDER_OT_netclientsend(bpy.types.Operator):
- '''Send Render Job to the Network'''
- bl_idname = "render.netclientsend"
- bl_label = "Send job"
-
- @classmethod
- def poll(cls, context):
- return True
-
- def execute(self, context):
- scene = context.scene
- netsettings = scene.network_render
-
- try:
- conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
-
- if conn:
- # Sending file
- scene.network_render.job_id = client.clientSendJob(conn, scene, True)
- conn.close()
- self.report('INFO', "Job sent to master")
- except Exception as err:
- self.report('ERROR', str(err))
-
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
-
-class RENDER_OT_netclientsendframe(bpy.types.Operator):
- '''Send Render Job with current frame to the Network'''
- bl_idname = "render.netclientsendframe"
- bl_label = "Send current frame job"
-
- @classmethod
- def poll(cls, context):
- return True
-
- def execute(self, context):
- scene = context.scene
- netsettings = scene.network_render
-
- try:
- conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
-
- if conn:
- # Sending file
- scene.network_render.job_id = client.clientSendJob(conn, scene, False)
- conn.close()
- self.report('INFO', "Job sent to master")
- except Exception as err:
- self.report('ERROR', str(err))
-
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
-
-class RENDER_OT_netclientstatus(bpy.types.Operator):
- '''Refresh the status of the current jobs'''
- bl_idname = "render.netclientstatus"
- bl_label = "Client Status"
-
- @classmethod
- def poll(cls, context):
- return True
-
- def execute(self, context):
- netsettings = context.scene.network_render
- conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
-
- if conn:
- conn.request("GET", "/status")
-
- response = conn.getresponse()
- content = response.read()
- print( response.status, response.reason )
-
- jobs = (netrender.model.RenderJob.materialize(j) for j in json.loads(str(content, encoding='utf8')))
-
- while(len(netsettings.jobs) > 0):
- netsettings.jobs.remove(0)
-
- netrender.jobs = []
-
- for j in jobs:
- netrender.jobs.append(j)
- netsettings.jobs.add()
- job = netsettings.jobs[-1]
-
- j.results = j.framesStatus() # cache frame status
-
- job.name = j.name
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
-
-class RENDER_OT_netclientblacklistslave(bpy.types.Operator):
- '''Operator documentation text, will be used for the operator tooltip and python docs.'''
- bl_idname = "render.netclientblacklistslave"
- bl_label = "Client Blacklist Slave"
-
- @classmethod
- def poll(cls, context):
- return True
-
- def execute(self, context):
- netsettings = context.scene.network_render
-
- if netsettings.active_slave_index >= 0:
-
- # deal with data
- slave = netrender.slaves.pop(netsettings.active_slave_index)
- netrender.blacklist.append(slave)
-
- # deal with rna
- netsettings.slaves_blacklist.add()
- netsettings.slaves_blacklist[-1].name = slave.name
-
- netsettings.slaves.remove(netsettings.active_slave_index)
- netsettings.active_slave_index = -1
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
-
-class RENDER_OT_netclientwhitelistslave(bpy.types.Operator):
- '''Operator documentation text, will be used for the operator tooltip and python docs.'''
- bl_idname = "render.netclientwhitelistslave"
- bl_label = "Client Whitelist Slave"
-
- @classmethod
- def poll(cls, context):
- return True
-
- def execute(self, context):
- netsettings = context.scene.network_render
-
- if netsettings.active_blacklisted_slave_index >= 0:
-
- # deal with data
- slave = netrender.blacklist.pop(netsettings.active_blacklisted_slave_index)
- netrender.slaves.append(slave)
-
- # deal with rna
- netsettings.slaves.add()
- netsettings.slaves[-1].name = slave.name
-
- netsettings.slaves_blacklist.remove(netsettings.active_blacklisted_slave_index)
- netsettings.active_blacklisted_slave_index = -1
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
-
-
-class RENDER_OT_netclientslaves(bpy.types.Operator):
- '''Refresh status about available Render slaves'''
- bl_idname = "render.netclientslaves"
- bl_label = "Client Slaves"
-
- @classmethod
- def poll(cls, context):
- return True
-
- def execute(self, context):
- netsettings = context.scene.network_render
- conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
-
- if conn:
- conn.request("GET", "/slaves")
-
- response = conn.getresponse()
- content = response.read()
- print( response.status, response.reason )
-
- slaves = (netrender.model.RenderSlave.materialize(s) for s in json.loads(str(content, encoding='utf8')))
-
- while(len(netsettings.slaves) > 0):
- netsettings.slaves.remove(0)
-
- netrender.slaves = []
-
- for s in slaves:
- for i in range(len(netrender.blacklist)):
- slave = netrender.blacklist[i]
- if slave.id == s.id:
- netrender.blacklist[i] = s
- netsettings.slaves_blacklist[i].name = s.name
- break
- else:
- netrender.slaves.append(s)
-
- netsettings.slaves.add()
- slave = netsettings.slaves[-1]
- slave.name = s.name
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
-
-class RENDER_OT_netclientcancel(bpy.types.Operator):
- '''Cancel the selected network rendering job.'''
- bl_idname = "render.netclientcancel"
- bl_label = "Client Cancel"
-
- @classmethod
- def poll(cls, context):
- netsettings = context.scene.network_render
- return netsettings.active_job_index >= 0 and len(netsettings.jobs) > 0
-
- def execute(self, context):
- netsettings = context.scene.network_render
- conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
-
- if conn:
- job = netrender.jobs[netsettings.active_job_index]
-
- conn.request("POST", cancelURL(job.id), json.dumps({'clear':False}))
-
- response = conn.getresponse()
- response.read()
- print( response.status, response.reason )
-
- netsettings.jobs.remove(netsettings.active_job_index)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
-
-class RENDER_OT_netclientcancelall(bpy.types.Operator):
- '''Cancel all running network rendering jobs.'''
- bl_idname = "render.netclientcancelall"
- bl_label = "Client Cancel All"
-
- @classmethod
- def poll(cls, context):
- return True
-
- def execute(self, context):
- netsettings = context.scene.network_render
- conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
-
- if conn:
- conn.request("POST", "/clear", json.dumps({'clear':False}))
-
- response = conn.getresponse()
- response.read()
- print( response.status, response.reason )
-
- while(len(netsettings.jobs) > 0):
- netsettings.jobs.remove(0)
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
-
-class netclientdownload(bpy.types.Operator):
- '''Download render results from the network'''
- bl_idname = "render.netclientdownload"
- bl_label = "Client Download"
-
- @classmethod
- def poll(cls, context):
- netsettings = context.scene.network_render
- return netsettings.active_job_index >= 0 and len(netsettings.jobs) > netsettings.active_job_index
-
- def execute(self, context):
- netsettings = context.scene.network_render
- rd = context.scene.render
-
- conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
-
- if conn:
- job_id = netrender.jobs[netsettings.active_job_index].id
-
- conn.request("GET", "/status", headers={"job-id":job_id})
-
- response = conn.getresponse()
-
- if response.status != http.client.OK:
- self.report('ERROR', "Job ID %i not defined on master" % job_id)
- return {'ERROR'}
-
- content = response.read()
-
- job = netrender.model.RenderJob.materialize(json.loads(str(content, encoding='utf8')))
-
- conn.close()
-
- finished_frames = []
-
- nb_error = 0
- nb_missing = 0
-
- for frame in job.frames:
- if frame.status == DONE:
- finished_frames.append(frame.number)
- elif frame.status == ERROR:
- nb_error += 1
- else:
- nb_missing += 1
-
- if not finished_frames:
- return
-
- frame_ranges = []
-
- first = None
- last = None
-
- for i in range(len(finished_frames)):
- current = finished_frames[i]
-
- if not first:
- first = current
- last = current
- elif last + 1 == current:
- last = current
-
- if last + 1 < current or i + 1 == len(finished_frames):
- if first < last:
- frame_ranges.append((first, last))
- else:
- frame_ranges.append((first,))
-
- first = current
- last = current
-
- getResults(netsettings.server_address, netsettings.server_port, job_id, job.resolution[0], job.resolution[1], job.resolution[2], frame_ranges)
-
- if nb_error and nb_missing:
- self.report('ERROR', "Results downloaded but skipped %i frames with errors and %i unfinished frames" % (nb_error, nb_missing))
- elif nb_error:
- self.report('ERROR', "Results downloaded but skipped %i frames with errors" % nb_error)
- elif nb_missing:
- self.report('WARNING', "Results downloaded but skipped %i unfinished frames" % nb_missing)
- else:
- self.report('INFO', "All results downloaded")
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
-
-class netclientscan(bpy.types.Operator):
- '''Listen on network for master server broadcasting its address and port.'''
- bl_idname = "render.netclientscan"
- bl_label = "Client Scan"
-
- @classmethod
- def poll(cls, context):
- return True
-
- def execute(self, context):
- address, port = clientScan(self.report)
-
- if address:
- scene = context.scene
- netsettings = scene.network_render
- netsettings.server_address = address
- netsettings.server_port = port
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
-
-class netclientvcsguess(bpy.types.Operator):
- '''Guess VCS setting for the current file'''
- bl_idname = "render.netclientvcsguess"
- bl_label = "VCS Guess"
-
- @classmethod
- def poll(cls, context):
- return True
-
- def execute(self, context):
- netsettings = context.scene.network_render
-
- system = versioning.SYSTEMS.get(netsettings.vcs_system, None)
-
- if system:
- wpath, name = os.path.split(os.path.abspath(bpy.data.filepath))
-
- rpath = system.path(wpath)
- revision = system.revision(wpath)
-
- netsettings.vcs_wpath = wpath
- netsettings.vcs_rpath = rpath
- netsettings.vcs_revision = revision
-
-
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
-
-
-class netclientweb(bpy.types.Operator):
- '''Open new window with information about running rendering jobs'''
- bl_idname = "render.netclientweb"
- bl_label = "Open Master Monitor"
-
- @classmethod
- def poll(cls, context):
- netsettings = context.scene.network_render
- return netsettings.server_address != "[default]"
-
- def execute(self, context):
- netsettings = context.scene.network_render
-
-
- # open connection to make sure server exists
- conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
-
- if conn:
- conn.close()
-
- webbrowser.open("http://%s:%i" % (netsettings.server_address, netsettings.server_port))
-
- return {'FINISHED'}
-
- def invoke(self, context, event):
- return self.execute(context)
diff --git a/release/scripts/io/netrender/repath.py b/release/scripts/io/netrender/repath.py
deleted file mode 100644
index 3ac9636b628..00000000000
--- a/release/scripts/io/netrender/repath.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# ##### 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 #####
-
-import sys, os
-import subprocess
-
-import bpy
-
-from netrender.utils import *
-import netrender.model
-
-BLENDER_PATH = sys.argv[0]
-
-def reset(job):
- main_file = job.files[0]
-
- job_full_path = main_file.filepath
-
- if os.path.exists(job_full_path + ".bak"):
- os.remove(job_full_path) # repathed file
- os.renames(job_full_path + ".bak", job_full_path)
-
-def update(job):
- paths = []
-
- main_file = job.files[0]
-
- job_full_path = main_file.filepath
-
-
- path, ext = os.path.splitext(job_full_path)
-
- new_path = path + ".remap" + ext
-
- # Disable for now. Partial repath should work anyway
- #all = main_file.filepath != main_file.original_path
- all = False
-
- for rfile in job.files[1:]:
- if all or rfile.original_path != rfile.filepath:
- paths.append(rfile.original_path)
- paths.append(rfile.filepath)
-
- # Only update if needed
- if paths:
- process = subprocess.Popen([BLENDER_PATH, "-b", "-noaudio", job_full_path, "-P", __file__, "--", new_path] + paths, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- process.wait()
-
- os.renames(job_full_path, job_full_path + ".bak")
- os.renames(new_path, job_full_path)
-
-def process(paths):
- def processPointCache(point_cache):
- point_cache.use_external = False
-
- def processFluid(fluid):
- new_path = path_map.get(fluid.filepath, None)
- if new_path:
- fluid.path = new_path
-
- path_map = {}
- for i in range(0, len(paths), 2):
- # special case for point cache
- if paths[i].endswith(".bphys"):
- pass # Don't need them in the map, they all use the default external path
- # NOTE: This is probably not correct all the time, need to be fixed.
- # special case for fluids
- elif paths[i].endswith(".bobj.gz"):
- path_map[os.path.split(paths[i])[0]] = os.path.split(paths[i+1])[0]
- else:
- path_map[os.path.split(paths[i])[1]] = paths[i+1]
-
- # TODO original paths aren't really the orignal path (they are the normalized path
- # so we repath using the filenames only.
-
- ###########################
- # LIBRARIES
- ###########################
- for lib in bpy.data.libraries:
- file_path = bpy.path.abspath(lib.filepath)
- new_path = path_map.get(os.path.split(file_path)[1], None)
- if new_path:
- lib.filepath = new_path
-
- ###########################
- # IMAGES
- ###########################
- for image in bpy.data.images:
- if image.source == "FILE" and not image.packed_file:
- file_path = bpy.path.abspath(image.filepath)
- new_path = path_map.get(os.path.split(file_path)[1], None)
- if new_path:
- image.filepath = new_path
-
-
- ###########################
- # FLUID + POINT CACHE
- ###########################
- for object in bpy.data.objects:
- for modifier in object.modifiers:
- if modifier.type == 'FLUID_SIMULATION' and modifier.settings.type == "DOMAIN":
- processFluid(settings)
- elif modifier.type == "CLOTH":
- processPointCache(modifier.point_cache)
- elif modifier.type == "SOFT_BODY":
- processPointCache(modifier.point_cache)
- elif modifier.type == "SMOKE" and modifier.smoke_type == "TYPE_DOMAIN":
- processPointCache(modifier.domain_settings.point_cache_low)
- if modifier.domain_settings.use_high_resolution:
- processPointCache(modifier.domain_settings.point_cache_high)
- elif modifier.type == "MULTIRES" and modifier.is_external:
- file_path = bpy.path.abspath(modifier.filepath)
- new_path = path_map.get(file_path, None)
- if new_path:
- modifier.filepath = new_path
-
- # particles modifier are stupid and don't contain data
- # we have to go through the object property
- for psys in object.particle_systems:
- processPointCache(psys.point_cache)
-
-
-if __name__ == "__main__":
- try:
- i = sys.argv.index("--")
- except:
- i = 0
-
- if i:
- new_path = sys.argv[i+1]
- args = sys.argv[i+2:]
-
- process(args)
-
- bpy.ops.wm.save_as_mainfile(filepath=new_path, check_existing=False)
diff --git a/release/scripts/io/netrender/slave.py b/release/scripts/io/netrender/slave.py
deleted file mode 100644
index b05de0afeb9..00000000000
--- a/release/scripts/io/netrender/slave.py
+++ /dev/null
@@ -1,349 +0,0 @@
-# ##### 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 #####
-
-import sys, os, platform, shutil
-import http, http.client, http.server, urllib
-import subprocess, time
-import json
-
-import bpy
-
-from netrender.utils import *
-import netrender.model
-import netrender.repath
-import netrender.thumbnail as thumbnail
-
-BLENDER_PATH = sys.argv[0]
-
-CANCEL_POLL_SPEED = 2
-MAX_TIMEOUT = 10
-INCREMENT_TIMEOUT = 1
-MAX_CONNECT_TRY = 10
-try:
- system = platform.system()
-except UnicodeDecodeError:
- import sys
- system = sys.platform
-
-if system in ('Windows', 'win32') and platform.version() >= '5': # Error mode is only available on Win2k or higher, that's version 5
- import ctypes
- def SetErrorMode():
- val = ctypes.windll.kernel32.SetErrorMode(0x0002)
- ctypes.windll.kernel32.SetErrorMode(val | 0x0002)
- return val
-
- def RestoreErrorMode(val):
- ctypes.windll.kernel32.SetErrorMode(val)
-else:
- def SetErrorMode():
- return 0
-
- def RestoreErrorMode(val):
- pass
-
-def clearSlave(path):
- shutil.rmtree(path)
-
-def slave_Info():
- sysname, nodename, release, version, machine, processor = platform.uname()
- slave = netrender.model.RenderSlave()
- slave.name = nodename
- slave.stats = sysname + " " + release + " " + machine + " " + processor
- return slave
-
-def testCancel(conn, job_id, frame_number):
- conn.request("HEAD", "/status", headers={"job-id":job_id, "job-frame": str(frame_number)})
-
- # canceled if job isn't found anymore
- if responseStatus(conn) == http.client.NO_CONTENT:
- return True
- else:
- return False
-
-def testFile(conn, job_id, slave_id, rfile, JOB_PREFIX, main_path = None):
- job_full_path = prefixPath(JOB_PREFIX, rfile.filepath, main_path)
-
- found = os.path.exists(job_full_path)
-
- if found and rfile.signature != None:
- found_signature = hashFile(job_full_path)
- found = found_signature == rfile.signature
-
- if not found:
- print("Found file %s at %s but signature mismatch!" % (rfile.filepath, job_full_path))
- job_full_path = prefixPath(JOB_PREFIX, rfile.filepath, main_path, force = True)
-
- if not found:
- # Force prefix path if not found
- job_full_path = prefixPath(JOB_PREFIX, rfile.filepath, main_path, force = True)
- temp_path = os.path.join(JOB_PREFIX, "slave.temp")
- conn.request("GET", fileURL(job_id, rfile.index), headers={"slave-id":slave_id})
- response = conn.getresponse()
-
- if response.status != http.client.OK:
- return None # file for job not returned by server, need to return an error code to server
-
- f = open(temp_path, "wb")
- buf = response.read(1024)
-
- while buf:
- f.write(buf)
- buf = response.read(1024)
-
- f.close()
-
- os.renames(temp_path, job_full_path)
-
- rfile.filepath = job_full_path
-
- return job_full_path
-
-def breakable_timeout(timeout):
- for i in range(timeout):
- time.sleep(1)
- if engine.test_break():
- break
-
-def render_slave(engine, netsettings, threads):
- timeout = 1
-
- bisleep = BreakableIncrementedSleep(INCREMENT_TIMEOUT, 1, MAX_TIMEOUT, engine.test_break)
-
- engine.update_stats("", "Network render node initiation")
-
- conn = clientConnection(netsettings.server_address, netsettings.server_port)
-
- if not conn:
- timeout = 1
- print("Connection failed, will try connecting again at most %i times" % MAX_CONNECT_TRY)
- bisleep.reset()
-
- for i in range(MAX_CONNECT_TRY):
- bisleep.sleep()
-
- conn = clientConnection(netsettings.server_address, netsettings.server_port)
-
- if conn or engine.test_break():
- break
-
- print("Retry %i failed, waiting %is before retrying" % (i + 1, bisleep.current))
-
- if conn:
- conn.request("POST", "/slave", json.dumps(slave_Info().serialize()))
- response = conn.getresponse()
- response.read()
-
- slave_id = response.getheader("slave-id")
-
- NODE_PREFIX = os.path.join(bpy.path.abspath(netsettings.path), "slave_" + slave_id)
- if not os.path.exists(NODE_PREFIX):
- os.mkdir(NODE_PREFIX)
-
- engine.update_stats("", "Network render connected to master, waiting for jobs")
-
- while not engine.test_break():
- conn.request("GET", "/job", headers={"slave-id":slave_id})
- response = conn.getresponse()
-
- if response.status == http.client.OK:
- bisleep.reset()
-
- job = netrender.model.RenderJob.materialize(json.loads(str(response.read(), encoding='utf8')))
- engine.update_stats("", "Network render processing job from master")
-
- JOB_PREFIX = os.path.join(NODE_PREFIX, "job_" + job.id)
- if not os.path.exists(JOB_PREFIX):
- os.mkdir(JOB_PREFIX)
-
- # set tempdir for fsaa temp files
- # have to set environ var because render is done in a subprocess and that's the easiest way to propagate the setting
- os.environ["TMP"] = JOB_PREFIX
-
-
- if job.type == netrender.model.JOB_BLENDER:
- job_path = job.files[0].filepath # path of main file
- main_path, main_file = os.path.split(job_path)
-
- job_full_path = testFile(conn, job.id, slave_id, job.files[0], JOB_PREFIX)
- print("Fullpath", job_full_path)
- print("File:", main_file, "and %i other files" % (len(job.files) - 1,))
-
- for rfile in job.files[1:]:
- testFile(conn, job.id, slave_id, rfile, JOB_PREFIX, main_path)
- print("\t", rfile.filepath)
-
- netrender.repath.update(job)
-
- engine.update_stats("", "Render File "+ main_file+ " for job "+ job.id)
- elif job.type == netrender.model.JOB_VCS:
- if not job.version_info:
- # Need to return an error to server, incorrect job type
- pass
-
- job_path = job.files[0].filepath # path of main file
- main_path, main_file = os.path.split(job_path)
-
- job.version_info.update()
-
- # For VCS jobs, file path is relative to the working copy path
- job_full_path = os.path.join(job.version_info.wpath, job_path)
-
- engine.update_stats("", "Render File "+ main_file+ " for job "+ job.id)
-
- # announce log to master
- logfile = netrender.model.LogFile(job.id, slave_id, [frame.number for frame in job.frames])
- conn.request("POST", "/log", bytes(json.dumps(logfile.serialize()), encoding='utf8'))
- response = conn.getresponse()
- response.read()
-
-
- first_frame = job.frames[0].number
-
- # start render
- start_t = time.time()
-
- if job.rendersWithBlender():
- frame_args = []
-
- for frame in job.frames:
- print("frame", frame.number)
- frame_args += ["-f", str(frame.number)]
-
- val = SetErrorMode()
- process = subprocess.Popen([BLENDER_PATH, "-b", "-noaudio", job_full_path, "-t", str(threads), "-o", os.path.join(JOB_PREFIX, "######"), "-E", "BLENDER_RENDER", "-F", "MULTILAYER"] + frame_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- RestoreErrorMode(val)
- elif job.type == netrender.model.JOB_PROCESS:
- command = job.frames[0].command
- val = SetErrorMode()
- process = subprocess.Popen(command.split(" "), stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- RestoreErrorMode(val)
-
- headers = {"slave-id":slave_id}
-
- cancelled = False
- stdout = bytes()
- run_t = time.time()
- while not cancelled and process.poll() is None:
- stdout += process.stdout.read(1024)
- current_t = time.time()
- cancelled = engine.test_break()
- if current_t - run_t > CANCEL_POLL_SPEED:
-
- # update logs if needed
- if stdout:
- # (only need to update on one frame, they are linked
- conn.request("PUT", logURL(job.id, first_frame), stdout, headers=headers)
- response = conn.getresponse()
- response.read()
-
- # Also output on console
- if netsettings.use_slave_output_log:
- print(str(stdout, encoding='utf8'), end="")
-
- stdout = bytes()
-
- run_t = current_t
- if testCancel(conn, job.id, first_frame):
- cancelled = True
-
- if job.type == netrender.model.JOB_BLENDER:
- netrender.repath.reset(job)
-
- # read leftovers if needed
- stdout += process.stdout.read()
-
- if cancelled:
- # kill process if needed
- if process.poll() is None:
- try:
- process.terminate()
- except OSError:
- pass
- continue # to next frame
-
- # flush the rest of the logs
- if stdout:
- # Also output on console
- if netsettings.use_slave_thumb:
- print(str(stdout, encoding='utf8'), end="")
-
- # (only need to update on one frame, they are linked
- conn.request("PUT", logURL(job.id, first_frame), stdout, headers=headers)
- if responseStatus(conn) == http.client.NO_CONTENT:
- continue
-
- total_t = time.time() - start_t
-
- avg_t = total_t / len(job.frames)
-
- status = process.returncode
-
- print("status", status)
-
- headers = {"job-id":job.id, "slave-id":slave_id, "job-time":str(avg_t)}
-
-
- if status == 0: # non zero status is error
- headers["job-result"] = str(DONE)
- for frame in job.frames:
- headers["job-frame"] = str(frame.number)
- if job.hasRenderResult():
- # send image back to server
-
- filename = os.path.join(JOB_PREFIX, "%06d.exr" % frame.number)
-
- # thumbnail first
- if netsettings.use_slave_thumb:
- thumbname = thumbnail.generate(filename)
-
- if thumbname:
- f = open(thumbname, 'rb')
- conn.request("PUT", "/thumb", f, headers=headers)
- f.close()
- responseStatus(conn)
-
- f = open(filename, 'rb')
- conn.request("PUT", "/render", f, headers=headers)
- f.close()
- if responseStatus(conn) == http.client.NO_CONTENT:
- continue
-
- elif job.type == netrender.model.JOB_PROCESS:
- conn.request("PUT", "/render", headers=headers)
- if responseStatus(conn) == http.client.NO_CONTENT:
- continue
- else:
- headers["job-result"] = str(ERROR)
- for frame in job.frames:
- headers["job-frame"] = str(frame.number)
- # send error result back to server
- conn.request("PUT", "/render", headers=headers)
- if responseStatus(conn) == http.client.NO_CONTENT:
- continue
-
- engine.update_stats("", "Network render connected to master, waiting for jobs")
- else:
- bisleep.sleep()
-
- conn.close()
-
- if netsettings.use_slave_clear:
- clearSlave(NODE_PREFIX)
-
-if __name__ == "__main__":
- pass
diff --git a/release/scripts/io/netrender/thumbnail.py b/release/scripts/io/netrender/thumbnail.py
deleted file mode 100644
index 2ead6e82745..00000000000
--- a/release/scripts/io/netrender/thumbnail.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# ##### 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 #####
-
-import sys, os
-import subprocess
-
-import bpy
-
-def generate(filename, external=True):
- if external:
- process = subprocess.Popen([sys.argv[0], "-b", "-noaudio", "-P", __file__, "--", filename], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- while process.poll() is None:
- process.stdout.read(1024) # empty buffer to be sure
- process.stdout.read()
-
- return _thumbname(filename)
- else:
- return _internal(filename)
-
-def _thumbname(filename):
- root = os.path.splitext(filename)[0]
- return root + ".jpg"
-
-def _internal(filename):
- imagename = os.path.split(filename)[1]
- thumbname = _thumbname(filename)
-
- if os.path.exists(thumbname):
- return thumbname
-
- if bpy:
- scene = bpy.data.scenes[0] # FIXME, this is dodgy!
- scene.render.file_format = "JPEG"
- scene.render.file_quality = 90
-
- # remove existing image, if there's a leftover (otherwise open changes the name)
- if imagename in bpy.data.images:
- img = bpy.data.images[imagename]
- bpy.data.images.remove(img)
-
- bpy.ops.image.open(filepath=filename)
- img = bpy.data.images[imagename]
-
- img.save_render(thumbname, scene=scene)
-
- img.user_clear()
- bpy.data.images.remove(img)
-
- try:
- process = subprocess.Popen(["convert", thumbname, "-resize", "300x300", thumbname])
- process.wait()
- return thumbname
- except Exception as exp:
- print("Error while generating thumbnail")
- print(exp)
-
- return None
-
-if __name__ == "__main__":
- import bpy
- try:
- start = sys.argv.index("--") + 1
- except ValueError:
- start = 0
- for filename in sys.argv[start:]:
- generate(filename, external=False)
diff --git a/release/scripts/io/netrender/ui.py b/release/scripts/io/netrender/ui.py
deleted file mode 100644
index 343c60e7865..00000000000
--- a/release/scripts/io/netrender/ui.py
+++ /dev/null
@@ -1,550 +0,0 @@
-# ##### 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 #####
-
-import bpy
-import sys, os
-import http, http.client, http.server, urllib
-import subprocess, shutil, time, hashlib
-
-import netrender
-import netrender.slave as slave
-import netrender.master as master
-
-from netrender.utils import *
-
-VERSION = b"0.3"
-
-PATH_PREFIX = "/tmp/"
-
-QUEUED = 0
-DISPATCHED = 1
-DONE = 2
-ERROR = 3
-
-LAST_ADDRESS_TEST = 0
-
-def base_poll(cls, context):
- rd = context.scene.render
- return (rd.use_game_engine==False) and (rd.engine in cls.COMPAT_ENGINES)
-
-
-def init_file():
- if netrender.init_file != bpy.data.filepath:
- netrender.init_file = bpy.data.filepath
- netrender.init_data = True
- netrender.valid_address = False
-
-def init_data(netsettings):
- init_file()
-
- if netrender.init_data:
- netrender.init_data = False
-
- netsettings.active_slave_index = 0
- while(len(netsettings.slaves) > 0):
- netsettings.slaves.remove(0)
-
- netsettings.active_blacklisted_slave_index = 0
- while(len(netsettings.slaves_blacklist) > 0):
- netsettings.slaves_blacklist.remove(0)
-
- netsettings.active_job_index = 0
- while(len(netsettings.jobs) > 0):
- netsettings.jobs.remove(0)
-
-def verify_address(netsettings):
- global LAST_ADDRESS_TEST
- init_file()
-
- if LAST_ADDRESS_TEST + 30 < time.time():
- LAST_ADDRESS_TEST = time.time()
-
- try:
- conn = clientConnection(netsettings.server_address, netsettings.server_port, scan = False, timeout = 1)
- except:
- conn = None
-
- if conn:
- netrender.valid_address = True
- conn.close()
- else:
- netrender.valid_address = False
-
- return netrender.valid_address
-
-class NeedValidAddress():
- @classmethod
- def poll(cls, context):
- return super().poll(context) and verify_address(context.scene.network_render)
-
-class NetRenderButtonsPanel():
- bl_space_type = "PROPERTIES"
- bl_region_type = "WINDOW"
- bl_context = "render"
- # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
-
- @classmethod
- def poll(cls, context):
- rd = context.scene.render
- return rd.engine == 'NET_RENDER' and rd.use_game_engine == False
-
-# Setting panel, use in the scene for now.
-class RENDER_PT_network_settings(NetRenderButtonsPanel, bpy.types.Panel):
- bl_label = "Network Settings"
- COMPAT_ENGINES = {'NET_RENDER'}
-
- @classmethod
- def poll(cls, context):
- return super().poll(context)
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- netsettings = scene.network_render
-
- verify_address(netsettings)
-
- layout.prop(netsettings, "mode", expand=True)
-
- if netsettings.mode in ("RENDER_MASTER", "RENDER_SLAVE"):
- layout.operator("render.netclientstart", icon='PLAY')
-
- layout.prop(netsettings, "path")
-
- split = layout.split(percentage=0.7)
-
- col = split.column()
- col.label(text="Server Address:")
- col.prop(netsettings, "server_address", text="")
-
- col = split.column()
- col.label(text="Port:")
- col.prop(netsettings, "server_port", text="")
-
- if netsettings.mode != "RENDER_MASTER":
- layout.operator("render.netclientscan", icon='FILE_REFRESH', text="")
-
- if not netrender.valid_address:
- layout.label(text="No master at specified address")
-
- layout.operator("render.netclientweb", icon='QUESTION')
-
-class RENDER_PT_network_slave_settings(NetRenderButtonsPanel, bpy.types.Panel):
- bl_label = "Slave Settings"
- COMPAT_ENGINES = {'NET_RENDER'}
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- return super().poll(context) and scene.network_render.mode == "RENDER_SLAVE"
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- rd = scene.render
- netsettings = scene.network_render
-
- layout.prop(netsettings, "use_slave_clear")
- layout.prop(netsettings, "use_slave_thumb")
- layout.prop(netsettings, "use_slave_output_log")
- layout.label(text="Threads:")
- layout.prop(rd, "threads_mode", expand=True)
- sub = layout.column()
- sub.enabled = rd.threads_mode == 'FIXED'
- sub.prop(rd, "threads")
-
-class RENDER_PT_network_master_settings(NetRenderButtonsPanel, bpy.types.Panel):
- bl_label = "Master Settings"
- COMPAT_ENGINES = {'NET_RENDER'}
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- return super().poll(context) and scene.network_render.mode == "RENDER_MASTER"
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- netsettings = scene.network_render
-
- layout.prop(netsettings, "use_master_broadcast")
- layout.prop(netsettings, "use_master_clear")
-
-class RENDER_PT_network_job(NetRenderButtonsPanel, bpy.types.Panel):
- bl_label = "Job Settings"
- COMPAT_ENGINES = {'NET_RENDER'}
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- return super().poll(context) and scene.network_render.mode == "RENDER_CLIENT"
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- netsettings = scene.network_render
-
- verify_address(netsettings)
-
- if netsettings.server_address != "[default]":
- layout.operator("render.netclientanim", icon='RENDER_ANIMATION')
- layout.operator("render.netclientsend", icon='FILE_BLEND')
- layout.operator("render.netclientsendframe", icon='RENDER_STILL')
- if netsettings.job_id:
- row = layout.row()
- row.operator("render.render", text="Get Image", icon='RENDER_STILL')
- row.operator("render.render", text="Get Animation", icon='RENDER_ANIMATION').animation = True
-
- split = layout.split(percentage=0.3)
-
- col = split.column()
- col.label(text="Type:")
- col.label(text="Name:")
- col.label(text="Category:")
-
- col = split.column()
- col.prop(netsettings, "job_type", text="")
- col.prop(netsettings, "job_name", text="")
- col.prop(netsettings, "job_category", text="")
-
- row = layout.row()
- row.prop(netsettings, "priority")
- row.prop(netsettings, "chunks")
-
-class RENDER_PT_network_job_vcs(NetRenderButtonsPanel, bpy.types.Panel):
- bl_label = "VCS Job Settings"
- COMPAT_ENGINES = {'NET_RENDER'}
-
- @classmethod
- def poll(cls, context):
- scene = context.scene
- return (super().poll(context)
- and scene.network_render.mode == "RENDER_CLIENT"
- and scene.network_render.job_type == "JOB_VCS")
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- netsettings = scene.network_render
-
- layout.operator("render.netclientvcsguess", icon='FILE_REFRESH', text="")
-
- layout.prop(netsettings, "vcs_system")
- layout.prop(netsettings, "vcs_revision")
- layout.prop(netsettings, "vcs_rpath")
- layout.prop(netsettings, "vcs_wpath")
-
-class RENDER_PT_network_slaves(NeedValidAddress, NetRenderButtonsPanel, bpy.types.Panel):
- bl_label = "Slaves Status"
- COMPAT_ENGINES = {'NET_RENDER'}
-
- @classmethod
- def poll(cls, context):
- netsettings = context.scene.network_render
- return super().poll(context) and netsettings.mode == "RENDER_CLIENT"
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- netsettings = scene.network_render
-
- row = layout.row()
- row.template_list(netsettings, "slaves", netsettings, "active_slave_index", rows=2)
-
- sub = row.column(align=True)
- sub.operator("render.netclientslaves", icon='FILE_REFRESH', text="")
- sub.operator("render.netclientblacklistslave", icon='ZOOMOUT', text="")
-
- if len(netrender.slaves) > netsettings.active_slave_index >= 0:
- layout.separator()
-
- slave = netrender.slaves[netsettings.active_slave_index]
-
- layout.label(text="Name: " + slave.name)
- layout.label(text="Address: " + slave.address[0])
- layout.label(text="Seen: " + time.ctime(slave.last_seen))
- layout.label(text="Stats: " + slave.stats)
-
-class RENDER_PT_network_slaves_blacklist(NeedValidAddress, NetRenderButtonsPanel, bpy.types.Panel):
- bl_label = "Slaves Blacklist"
- COMPAT_ENGINES = {'NET_RENDER'}
-
- @classmethod
- def poll(cls, context):
- netsettings = context.scene.network_render
- return super().poll(context) and netsettings.mode == "RENDER_CLIENT"
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- netsettings = scene.network_render
-
- row = layout.row()
- row.template_list(netsettings, "slaves_blacklist", netsettings, "active_blacklisted_slave_index", rows=2)
-
- sub = row.column(align=True)
- sub.operator("render.netclientwhitelistslave", icon='ZOOMOUT', text="")
-
- if len(netrender.blacklist) > netsettings.active_blacklisted_slave_index >= 0:
- layout.separator()
-
- slave = netrender.blacklist[netsettings.active_blacklisted_slave_index]
-
- layout.label(text="Name: " + slave.name)
- layout.label(text="Address: " + slave.address[0])
- layout.label(text="Seen: " + time.ctime(slave.last_seen))
- layout.label(text="Stats: " + slave.stats)
-
-class RENDER_PT_network_jobs(NeedValidAddress, NetRenderButtonsPanel, bpy.types.Panel):
- bl_label = "Jobs"
- COMPAT_ENGINES = {'NET_RENDER'}
-
- @classmethod
- def poll(cls, context):
- netsettings = context.scene.network_render
- return super().poll(context) and netsettings.mode == "RENDER_CLIENT"
-
- def draw(self, context):
- layout = self.layout
-
- scene = context.scene
- netsettings = scene.network_render
-
- row = layout.row()
- row.template_list(netsettings, "jobs", netsettings, "active_job_index", rows=2)
-
- sub = row.column(align=True)
- sub.operator("render.netclientstatus", icon='FILE_REFRESH', text="")
- sub.operator("render.netclientcancel", icon='ZOOMOUT', text="")
- sub.operator("render.netclientcancelall", icon='PANEL_CLOSE', text="")
- sub.operator("render.netclientdownload", icon='RENDER_ANIMATION', text="")
-
- if len(netrender.jobs) > netsettings.active_job_index >= 0:
- layout.separator()
-
- job = netrender.jobs[netsettings.active_job_index]
-
- layout.label(text="Name: %s" % job.name)
- layout.label(text="Length: %04i" % len(job))
- layout.label(text="Done: %04i" % job.results[DONE])
- layout.label(text="Error: %04i" % job.results[ERROR])
-
-import properties_render
-class RENDER_PT_network_output(NeedValidAddress, NetRenderButtonsPanel, bpy.types.Panel):
- bl_label = "Output"
- COMPAT_ENGINES = {'NET_RENDER'}
-
- @classmethod
- def poll(cls, context):
- netsettings = context.scene.network_render
- return super().poll(context) and netsettings.mode == "RENDER_CLIENT"
-
- draw = properties_render.RENDER_PT_output.draw
-
-
-def addProperties():
- class NetRenderSettings(bpy.types.IDPropertyGroup):
- pass
-
- class NetRenderSlave(bpy.types.IDPropertyGroup):
- pass
-
- class NetRenderJob(bpy.types.IDPropertyGroup):
- pass
-
- bpy.utils.register_class(NetRenderSettings)
- bpy.utils.register_class(NetRenderSlave)
- bpy.utils.register_class(NetRenderJob)
-
- from bpy.props import PointerProperty, StringProperty, BoolProperty, EnumProperty, IntProperty, CollectionProperty
- bpy.types.Scene.network_render = PointerProperty(type=NetRenderSettings, name="Network Render", description="Network Render Settings")
-
- NetRenderSettings.server_address = StringProperty(
- name="Server address",
- description="IP or name of the master render server",
- maxlen = 128,
- default = "[default]")
-
- NetRenderSettings.server_port = IntProperty(
- name="Server port",
- description="port of the master render server",
- default = 8000,
- min=1,
- max=65535)
-
- NetRenderSettings.use_master_broadcast = BoolProperty(
- name="Broadcast",
- description="broadcast master server address on local network",
- default = True)
-
- NetRenderSettings.use_slave_clear = BoolProperty(
- name="Clear on exit",
- description="delete downloaded files on exit",
- default = True)
-
- NetRenderSettings.use_slave_thumb = BoolProperty(
- name="Generate thumbnails",
- description="Generate thumbnails on slaves instead of master",
- default = False)
-
- NetRenderSettings.use_slave_output_log = BoolProperty(
- name="Output render log on console",
- description="Output render text log to console as well as sending it to the master",
- default = True)
-
- NetRenderSettings.use_master_clear = BoolProperty(
- name="Clear on exit",
- description="delete saved files on exit",
- default = False)
-
- default_path = os.environ.get("TEMP")
-
- if not default_path:
- if os.name == 'nt':
- default_path = "c:/tmp/"
- else:
- default_path = "/tmp/"
- elif not default_path.endswith(os.sep):
- default_path += os.sep
-
- NetRenderSettings.path = StringProperty(
- name="Path",
- description="Path for temporary files",
- maxlen = 128,
- default = default_path,
- subtype='FILE_PATH')
-
- NetRenderSettings.job_type = EnumProperty(
- items=(
- ("JOB_BLENDER", "Blender", "Standard Blender Job"),
- ("JOB_PROCESS", "Process", "Custom Process Job"),
- ("JOB_VCS", "VCS", "Version Control System Managed Job"),
- ),
- name="Job Type",
- description="Type of render job",
- default="JOB_BLENDER")
-
- NetRenderSettings.job_name = StringProperty(
- name="Job name",
- description="Name of the job",
- maxlen = 128,
- default = "[default]")
-
- NetRenderSettings.job_category = StringProperty(
- name="Job category",
- description="Category of the job",
- maxlen = 128,
- default = "")
-
- NetRenderSettings.chunks = IntProperty(
- name="Chunks",
- description="Number of frame to dispatch to each slave in one chunk",
- default = 5,
- min=1,
- max=65535)
-
- NetRenderSettings.priority = IntProperty(
- name="Priority",
- description="Priority of the job",
- default = 1,
- min=1,
- max=10)
-
- NetRenderSettings.vcs_wpath = StringProperty(
- name="Working Copy",
- description="Path of the local working copy",
- maxlen = 1024,
- default = "")
-
- NetRenderSettings.vcs_rpath = StringProperty(
- name="Remote Path",
- description="Path of the server copy (protocol specific)",
- maxlen = 1024,
- default = "")
-
- NetRenderSettings.vcs_revision = StringProperty(
- name="Revision",
- description="Revision for this job",
- maxlen = 256,
- default = "")
-
- NetRenderSettings.vcs_system = StringProperty(
- name="VCS",
- description="Version Control System",
- maxlen = 64,
- default = "Subversion")
-
- NetRenderSettings.job_id = StringProperty(
- name="Network job id",
- description="id of the last sent render job",
- maxlen = 64,
- default = "")
-
- NetRenderSettings.active_slave_index = IntProperty(
- name="Index of the active slave",
- description="",
- default = -1,
- min= -1,
- max=65535)
-
- NetRenderSettings.active_blacklisted_slave_index = IntProperty(
- name="Index of the active slave",
- description="",
- default = -1,
- min= -1,
- max=65535)
-
- NetRenderSettings.active_job_index = IntProperty(
- name="Index of the active job",
- description="",
- default = -1,
- min= -1,
- max=65535)
-
- NetRenderSettings.mode = EnumProperty(
- items=(
- ("RENDER_CLIENT", "Client", "Act as render client"),
- ("RENDER_MASTER", "Master", "Act as render master"),
- ("RENDER_SLAVE", "Slave", "Act as render slave"),
- ),
- name="Network mode",
- description="Mode of operation of this instance",
- default="RENDER_CLIENT")
-
- NetRenderSettings.slaves = CollectionProperty(type=NetRenderSlave, name="Slaves", description="")
- NetRenderSettings.slaves_blacklist = CollectionProperty(type=NetRenderSlave, name="Slaves Blacklist", description="")
- NetRenderSettings.jobs = CollectionProperty(type=NetRenderJob, name="Job List", description="")
-
- NetRenderSlave.name = StringProperty(
- name="Name of the slave",
- description="",
- maxlen = 64,
- default = "")
-
- NetRenderJob.name = StringProperty(
- name="Name of the job",
- description="",
- maxlen = 128,
- default = "")
diff --git a/release/scripts/io/netrender/utils.py b/release/scripts/io/netrender/utils.py
deleted file mode 100644
index ed9fb2de812..00000000000
--- a/release/scripts/io/netrender/utils.py
+++ /dev/null
@@ -1,313 +0,0 @@
-# ##### 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 #####
-
-import sys, os
-import re
-import http, http.client, http.server, urllib, socket
-import subprocess, shutil, time, hashlib, zlib
-
-import netrender.model
-
-try:
- import bpy
-except:
- bpy = None
-
-VERSION = bytes("1.3", encoding='utf8')
-
-# Jobs status
-JOB_WAITING = 0 # before all data has been entered
-JOB_PAUSED = 1 # paused by user
-JOB_FINISHED = 2 # finished rendering
-JOB_QUEUED = 3 # ready to be dispatched
-
-JOB_STATUS_TEXT = {
- JOB_WAITING: "Waiting",
- JOB_PAUSED: "Paused",
- JOB_FINISHED: "Finished",
- JOB_QUEUED: "Queued"
- }
-
-
-# Frames status
-QUEUED = 0
-DISPATCHED = 1
-DONE = 2
-ERROR = 3
-
-FRAME_STATUS_TEXT = {
- QUEUED: "Queued",
- DISPATCHED: "Dispatched",
- DONE: "Done",
- ERROR: "Error"
- }
-
-class DirectoryContext:
- def __init__(self, path):
- self.path = path
-
- def __enter__(self):
- self.curdir = os.path.abspath(os.curdir)
- os.chdir(self.path)
-
- def __exit__(self, exc_type, exc_value, traceback):
- os.chdir(self.curdir)
-
-class BreakableIncrementedSleep:
- def __init__(self, increment, default_timeout, max_timeout, break_fct):
- self.increment = increment
- self.default = default_timeout
- self.max = max_timeout
- self.current = self.default
- self.break_fct = break_fct
-
- def reset(self):
- self.current = self.default
-
- def increase(self):
- self.current = min(self.current + self.increment, self.max)
-
- def sleep(self):
- for i in range(self.current):
- time.sleep(1)
- if self.break_fct():
- break
-
- self.increase()
-
-def responseStatus(conn):
- response = conn.getresponse()
- response.read()
- return response.status
-
-def reporting(report, message, errorType = None):
- if errorType:
- t = 'ERROR'
- else:
- t = 'INFO'
-
- if report:
- report(t, message)
- return None
- elif errorType:
- raise errorType(message)
- else:
- return None
-
-def clientScan(report = None):
- try:
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
- s.settimeout(30)
-
- s.bind(('', 8000))
-
- buf, address = s.recvfrom(64)
-
- address = address[0]
- port = int(str(buf, encoding='utf8'))
-
- reporting(report, "Master server found")
-
- return (address, port)
- except socket.timeout:
- reporting(report, "No master server on network", IOError)
-
- return ("", 8000) # return default values
-
-def clientConnection(address, port, report = None, scan = True, timeout = 5):
- if address == "[default]":
-# calling operator from python is fucked, scene isn't in context
-# if bpy:
-# bpy.ops.render.netclientscan()
-# else:
- if not scan:
- return None
-
- address, port = clientScan()
- if address == "":
- return None
-
- try:
- conn = http.client.HTTPConnection(address, port, timeout = timeout)
-
- if conn:
- if clientVerifyVersion(conn):
- return conn
- else:
- conn.close()
- reporting(report, "Incorrect master version", ValueError)
- except BaseException as err:
- if report:
- report('ERROR', str(err))
- return None
- else:
- print(err)
- return None
-
-def clientVerifyVersion(conn):
- conn.request("GET", "/version")
- response = conn.getresponse()
-
- if response.status != http.client.OK:
- conn.close()
- return False
-
- server_version = response.read()
-
- if server_version != VERSION:
- print("Incorrect server version!")
- print("expected", str(VERSION, encoding='utf8'), "received", str(server_version, encoding='utf8'))
- return False
-
- return True
-
-def fileURL(job_id, file_index):
- return "/file_%s_%i" % (job_id, file_index)
-
-def logURL(job_id, frame_number):
- return "/log_%s_%i.log" % (job_id, frame_number)
-
-def renderURL(job_id, frame_number):
- return "/render_%s_%i.exr" % (job_id, frame_number)
-
-def cancelURL(job_id):
- return "/cancel_%s" % (job_id)
-
-def hashFile(path):
- f = open(path, "rb")
- value = hashData(f.read())
- f.close()
- return value
-
-def hashData(data):
- m = hashlib.md5()
- m.update(data)
- return m.hexdigest()
-
-
-def prefixPath(prefix_directory, file_path, prefix_path, force = False):
- if (os.path.isabs(file_path) or
- len(file_path) >= 3 and (file_path[1:3] == ":/" or file_path[1:3] == ":\\") or # Windows absolute path don't count as absolute on unix, have to handle them myself
- file_path[0] == "/" or file_path[0] == "\\"): # and vice versa
-
- # if an absolute path, make sure path exists, if it doesn't, use relative local path
- full_path = file_path
- if force or not os.path.exists(full_path):
- p, n = os.path.split(os.path.normpath(full_path))
-
- if prefix_path and p.startswith(prefix_path):
- if len(prefix_path) < len(p):
- directory = os.path.join(prefix_directory, p[len(prefix_path)+1:]) # +1 to remove separator
- if not os.path.exists(directory):
- os.mkdir(directory)
- else:
- directory = prefix_directory
- full_path = os.path.join(directory, n)
- else:
- full_path = os.path.join(prefix_directory, n)
- else:
- full_path = os.path.join(prefix_directory, file_path)
-
- return full_path
-
-def getResults(server_address, server_port, job_id, resolution_x, resolution_y, resolution_percentage, frame_ranges):
- if bpy.app.debug:
- print("=============================================")
- print("============= FETCHING RESULTS ==============")
-
- frame_arguments = []
- for r in frame_ranges:
- if len(r) == 2:
- frame_arguments.extend(["-s", str(r[0]), "-e", str(r[1]), "-a"])
- else:
- frame_arguments.extend(["-f", str(r[0])])
-
- filepath = os.path.join(bpy.app.tempdir, "netrender_temp.blend")
- bpy.ops.wm.save_as_mainfile(filepath=filepath, copy=True, check_existing=False)
-
- arguments = [sys.argv[0], "-b", "-noaudio", filepath, "-o", bpy.path.abspath(bpy.context.scene.render.filepath), "-P", __file__] + frame_arguments + ["--", "GetResults", server_address, str(server_port), job_id, str(resolution_x), str(resolution_y), str(resolution_percentage)]
- if bpy.app.debug:
- print("Starting subprocess:")
- print(" ".join(arguments))
-
- process = subprocess.Popen(arguments, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- while process.poll() is None:
- stdout = process.stdout.read(1024)
- if bpy.app.debug:
- print(str(stdout, encoding='utf-8'), end="")
-
-
- # read leftovers if needed
- stdout = process.stdout.read()
- if bpy.app.debug:
- print(str(stdout, encoding='utf-8'))
-
- os.remove(filepath)
-
- if bpy.app.debug:
- print("=============================================")
- return
-
-def _getResults(server_address, server_port, job_id, resolution_x, resolution_y, resolution_percentage):
- render = bpy.context.scene.render
-
- netsettings = bpy.context.scene.network_render
-
- netsettings.server_address = server_address
- netsettings.server_port = int(server_port)
- netsettings.job_id = job_id
-
- render.engine = 'NET_RENDER'
- render.resolution_x = int(resolution_x)
- render.resolution_y = int(resolution_y)
- render.resolution_percentage = int(resolution_percentage)
-
- render.use_full_sample = False
- render.use_compositing = False
- render.use_border = False
-
-
-def getFileInfo(filepath, infos):
- process = subprocess.Popen([sys.argv[0], "-b", "-noaudio", filepath, "-P", __file__, "--", "FileInfo"] + infos, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- stdout = bytes()
- while process.poll() is None:
- stdout += process.stdout.read(1024)
-
- # read leftovers if needed
- stdout += process.stdout.read()
-
- stdout = str(stdout, encoding="utf8")
-
- values = [eval(v[1:].strip()) for v in stdout.split("\n") if v.startswith("$")]
-
- return values
-
-
-if __name__ == "__main__":
- try:
- start = sys.argv.index("--") + 1
- except ValueError:
- start = 0
- action, *args = sys.argv[start:]
-
- if action == "FileInfo":
- for info in args:
- print("$", eval(info))
- elif action == "GetResults":
- _getResults(args[0], args[1], args[2], args[3], args[4], args[5])
diff --git a/release/scripts/io/netrender/versioning.py b/release/scripts/io/netrender/versioning.py
deleted file mode 100644
index d4f8522cce8..00000000000
--- a/release/scripts/io/netrender/versioning.py
+++ /dev/null
@@ -1,72 +0,0 @@
-import sys, os
-import re
-import subprocess
-
-from netrender.utils import *
-
-class AbstractVCS:
- name = "ABSTRACT VCS"
- def __init__(self):
- pass
-
- def update(self, info):
- """update(info)
- Update a working copy to the specified revision.
- If working copy doesn't exist, do a full get from server to create it.
- [info] model.VersioningInfo instance, specifies the working path, remote path and version number."""
- pass
-
- def revision(self, path):
- """revision(path)
- return the current revision of the specified working copy path"""
- pass
-
- def path(self, path):
- """path(path)
- return the remote path of the specified working copy path"""
- pass
-
-class Subversion(AbstractVCS):
- name = "Subversion"
- def __init__(self):
- super().__init__()
- self.version_exp = re.compile("([0-9]*)")
- self.path_exp = re.compile("URL: (.*)")
-
- def update(self, info):
- if not os.path.exists(info.wpath):
- base, folder = os.path.split(info.wpath)
-
- with DirectoryContext(base):
- subprocess.call(["svn", "co", "%s@%s" % (info.rpath, str(info.revision)), folder])
- else:
- with DirectoryContext(info.wpath):
- subprocess.call(["svn", "up", "--accept", "theirs-full", "-r", str(info.revision)])
-
- def revision(self, path):
- if not os.path.exists(path):
- return
-
- with DirectoryContext(path):
- stdout = subprocess.check_output(["svnversion"])
-
- match = self.version_exp.match(str(stdout, encoding="utf-8"))
-
- if match:
- return match.group(1)
-
- def path(self, path):
- if not os.path.exists(path):
- return
-
- with DirectoryContext(path):
- stdout = subprocess.check_output(["svn", "info"])
-
- match = self.path_exp.search(str(stdout, encoding="utf-8"))
-
- if match:
- return match.group(1)
-
-SYSTEMS = {
- Subversion.name: Subversion()
- }
diff --git a/release/scripts/modules/add_object_utils.py b/release/scripts/modules/add_object_utils.py
index 10707734bc4..1cf7fc2f4d5 100644
--- a/release/scripts/modules/add_object_utils.py
+++ b/release/scripts/modules/add_object_utils.py
@@ -83,6 +83,19 @@ def object_data_add(context, obdata, operator=None):
obj_act = scene.objects.active
+ # 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):
+ _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
+ # XXX
+
if obj_act and obj_act.mode == 'EDIT' and obj_act.type == obj_new.type:
bpy.ops.mesh.select_all(action='DESELECT')
bpy.ops.object.mode_set(mode='OBJECT')
@@ -92,6 +105,7 @@ def object_data_add(context, obdata, operator=None):
#scene.objects.active = obj_new
bpy.ops.object.join() # join into the active.
+ bpy.data.meshes.remove(obdata)
bpy.ops.object.mode_set(mode='EDIT')
else:
diff --git a/release/scripts/modules/addon_utils.py b/release/scripts/modules/addon_utils.py
new file mode 100644
index 00000000000..3877f711b7f
--- /dev/null
+++ b/release/scripts/modules/addon_utils.py
@@ -0,0 +1,326 @@
+# ##### 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>
+
+__all__ = (
+ "paths",
+ "modules",
+ "check",
+ "enable",
+ "disable",
+ "reset_all",
+ "module_bl_info",
+)
+
+import bpy as _bpy
+
+
+def paths():
+ # RELEASE SCRIPTS: official scripts distributed in Blender releases
+ paths = _bpy.utils.script_paths("addons")
+
+ # CONTRIB SCRIPTS: good for testing but not official scripts yet
+ # if folder addons_contrib/ exists, scripts in there will be loaded too
+ paths += _bpy.utils.script_paths("addons_contrib")
+
+ # EXTERN SCRIPTS: external projects scripts
+ # if folder addons_extern/ exists, scripts in there will be loaded too
+ paths += _bpy.utils.script_paths("addons_extern")
+
+ return paths
+
+
+def modules(module_cache):
+ import os
+ import sys
+ import time
+
+ path_list = paths()
+
+ # fake module importing
+ def fake_module(mod_name, mod_path, speedy=True):
+ if _bpy.app.debug:
+ print("fake_module", mod_path, mod_name)
+ import ast
+ ModuleType = type(ast)
+ file_mod = open(mod_path, "r", encoding='UTF-8')
+ if speedy:
+ lines = []
+ line_iter = iter(file_mod)
+ l = ""
+ while not l.startswith("bl_info"):
+ l = line_iter.readline()
+ if len(l) == 0:
+ break
+ while l.rstrip():
+ lines.append(l)
+ l = line_iter.readline()
+ data = "".join(lines)
+
+ else:
+ data = file_mod.read()
+
+ file_mod.close()
+
+ try:
+ ast_data = ast.parse(data, filename=mod_path)
+ except:
+ print("Syntax error 'ast.parse' can't read %r" % mod_path)
+ import traceback
+ traceback.print_exc()
+ ast_data = None
+
+ body_info = None
+
+ if ast_data:
+ for body in ast_data.body:
+ if body.__class__ == ast.Assign:
+ if len(body.targets) == 1:
+ if getattr(body.targets[0], "id", "") == "bl_info":
+ body_info = body
+ break
+
+ if body_info:
+ try:
+ mod = ModuleType(mod_name)
+ mod.bl_info = ast.literal_eval(body.value)
+ mod.__file__ = mod_path
+ mod.__time__ = os.path.getmtime(mod_path)
+ except:
+ print("AST error in module %s" % mod_name)
+ import traceback
+ traceback.print_exc()
+ raise
+
+ return mod
+ else:
+ return None
+
+ modules_stale = set(module_cache.keys())
+
+ for path in path_list:
+ for mod_name, mod_path in _bpy.path.module_names(path):
+ 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)
+ del module_cache[mod_name]
+ mod = None
+
+ if mod is None:
+ mod = fake_module(mod_name, mod_path)
+ if mod:
+ module_cache[mod_name] = mod
+
+ # just incase we get stale modules, not likely
+ for mod_stale in modules_stale:
+ del module_cache[mod_stale]
+ del modules_stale
+
+ mod_list = list(module_cache.values())
+ mod_list.sort(key=lambda mod: (mod.bl_info['category'], mod.bl_info['name']))
+ return mod_list
+
+
+def check(module_name):
+ """
+ Returns the loaded state of the addon.
+
+ :arg module_name: The name of the addon and module.
+ :type module_name: string
+ :return: (loaded_default, loaded_state)
+ :rtype: tuple of booleans
+ """
+ import sys
+ loaded_default = module_name in _bpy.context.user_preferences.addons
+
+ mod = sys.modules.get(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" %
+ (module_name, getattr(mod, "__file__", "<unknown>")))
+
+ loaded_state = False
+
+ return loaded_default, loaded_state
+
+
+def enable(module_name, default_set=True):
+ """
+ Enables an addon by name.
+
+ :arg module_name: The name of the addon and module.
+ :type module_name: string
+ :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():
+ import traceback
+ traceback.print_exc()
+
+ # reload if the mtime changes
+ mod = sys.modules.get(module_name)
+ if mod:
+ mod.__addon_enabled__ = False
+ mtime_orig = getattr(mod, "__time__", 0)
+ mtime_new = os.path.getmtime(mod.__file__)
+ if mtime_orig != mtime_new:
+ print("module changed on disk:", mod.__file__, "reloading...")
+
+ try:
+ imp.reload(mod)
+ except:
+ handle_error()
+ del sys.modules[module_name]
+ return None
+ mod.__addon_enabled__ = False
+
+ # Split registering up into 3 steps so we can undo if it fails par way through
+ # 1) try import
+ try:
+ mod = __import__(module_name)
+ mod.__time__ = os.path.getmtime(mod.__file__)
+ mod.__addon_enabled__ = False
+ except:
+ handle_error()
+ return None
+
+ # 2) try register collected modules
+ # removed, addons need to handle own registration now.
+
+ # 3) try run the modules register function
+ try:
+ mod.register()
+ except:
+ handle_error()
+ del sys.modules[module_name]
+ return None
+
+ # * OK loaded successfully! *
+ if default_set:
+ # just incase its enabled alredy
+ ext = _bpy.context.user_preferences.addons.get(module_name)
+ if not ext:
+ ext = _bpy.context.user_preferences.addons.new()
+ ext.module = module_name
+
+ mod.__addon_enabled__ = True
+
+ if _bpy.app.debug:
+ print("\taddon_utils.enable", mod.__name__)
+
+ return mod
+
+
+def disable(module_name, default_set=True):
+ """
+ Disables an addon by name.
+
+ :arg module_name: The name of the addon and module.
+ :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.
+ if mod:
+ mod.__addon_enabled__ = False
+
+ try:
+ mod.unregister()
+ except:
+ import traceback
+ traceback.print_exc()
+ else:
+ print("addon_utils.disable", module_name, "not loaded")
+
+ # could be in more then once, unlikely but better do this just incase.
+ addons = _bpy.context.user_preferences.addons
+
+ if default_set:
+ while module_name in addons:
+ addon = addons.get(module_name)
+ if addon:
+ addons.remove(addon)
+
+ if _bpy.app.debug:
+ print("\taddon_utils.disable", module_name)
+
+
+def reset_all(reload_scripts=False):
+ """
+ Sets the addon state based on the user preferences.
+ """
+ import sys
+ import imp
+
+ # RELEASE SCRIPTS: official scripts distributed in Blender releases
+ paths_list = paths()
+
+ for path in paths_list:
+ _bpy.utils._sys_path_ensure(path)
+ for mod_name, mod_path in _bpy.path.module_names(path):
+ is_enabled, is_loaded = check(mod_name)
+
+ # first check if reload is needed before changing state.
+ if reload_scripts:
+ mod = sys.modules.get(mod_name)
+ if mod:
+ imp.reload(mod)
+
+ if is_enabled == is_loaded:
+ pass
+ elif is_enabled:
+ enable(mod_name)
+ elif is_loaded:
+ print("\taddon_utils.reset_all unloading", mod_name)
+ 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}):
+ addon_info = getattr(mod, "bl_info", {})
+
+ # avoid re-initializing
+ if "_init" in addon_info:
+ return addon_info
+
+ if not addon_info:
+ mod.bl_info = addon_info
+
+ for key, value in info_basis.items():
+ addon_info.setdefault(key, value)
+
+ if not addon_info["name"]:
+ addon_info["name"] = mod.__name__
+
+ addon_info["_init"] = None
+ return addon_info
diff --git a/release/scripts/modules/animsys_refactor.py b/release/scripts/modules/animsys_refactor.py
index 464df870e87..5336a8b2b35 100644
--- a/release/scripts/modules/animsys_refactor.py
+++ b/release/scripts/modules/animsys_refactor.py
@@ -28,6 +28,12 @@ The main function to use is: update_data_paths(...)
IS_TESTING = False
+def drepr(string):
+ # is there a less crappy way to do this in python?, re.escape also escapes
+ # single quotes strings so cant use it.
+ return '"%s"' % repr(string)[1:-1].replace("\"", "\\\"").replace("\\'", "'")
+
+
class DataPathBuilder(object):
__slots__ = ("data_path", )
""" Dummy class used to parse fcurve and driver data paths.
@@ -40,7 +46,12 @@ class DataPathBuilder(object):
return DataPathBuilder(self.data_path + (str_value, ))
def __getitem__(self, key):
- str_value = '["%s"]' % key
+ if type(key) is int:
+ str_value = '[%d]' % key
+ elif type(key) is str:
+ str_value = '[%s]' % drepr(key)
+ else:
+ raise Exception("unsupported accessor %r of type %r (internal error)" % (key, type(key)))
return DataPathBuilder(self.data_path + (str_value, ))
def resolve(self, real_base, rna_update_from_map=None):
@@ -170,6 +181,15 @@ def update_data_paths(rna_update):
continue
for fcurve in anim_data.drivers:
+ data_path = fcurve.data_path
+ data_path_new = find_path_new(anim_data_base, data_path, rna_update_dict, rna_update_from_map)
+ # print(data_path_new)
+ if data_path_new != data_path:
+ if not IS_TESTING:
+ fcurve.data_path = data_path_new
+ fcurve.driver.is_valid = True # reset to allow this to work again
+ print("driver-fcurve (%s): %s -> %s" % (id_data.name, data_path, data_path_new))
+
for var in fcurve.driver.variables:
if var.type == 'SINGLE_PROP':
for tar in var.targets:
diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py
index 5c636d3a0df..1df8e9e5588 100644
--- a/release/scripts/modules/bpy/__init__.py
+++ b/release/scripts/modules/bpy/__init__.py
@@ -18,6 +18,10 @@
# <pep8 compliant>
+"""
+Give access to blender data and utility functions.
+"""
+
# internal blender C module
import _bpy
from _bpy import types, props, app
@@ -37,18 +41,6 @@ import sys as _sys
def _main():
- ## security issue, dont allow the $CWD in the path.
- ## note: this removes "" but not "." which are the same, security
- ## people need to explain how this is even a fix.
- # _sys.path[:] = filter(None, _sys.path)
-
- # because of how the console works. we need our own help() pager func.
- # replace the bold function because it adds crazy chars
- import pydoc
- pydoc.getpager = lambda: pydoc.plainpager
- pydoc.Helper.getline = lambda self, prompt: None
- pydoc.TextDoc.use_bold = lambda self, text: text
-
# Possibly temp. addons path
from os.path import join, dirname, normpath
_sys.path.append(normpath(join(dirname(__file__), "..", "..", "addons", "modules")))
diff --git a/release/scripts/modules/bpy/path.py b/release/scripts/modules/bpy/path.py
index 9a29b713882..f7e5b988cc8 100644
--- a/release/scripts/modules/bpy/path.py
+++ b/release/scripts/modules/bpy/path.py
@@ -144,6 +144,9 @@ def resolve_ncase(path):
dirpath = os.path.dirname(dirpath)
if not os.path.exists(dirpath):
+ if dirpath == path:
+ return path, False
+
dirpath, found = _ncase_path_found(dirpath)
if not found:
diff --git a/release/scripts/modules/bpy/utils.py b/release/scripts/modules/bpy/utils.py
index e3e93203235..a2d7b9e502f 100644
--- a/release/scripts/modules/bpy/utils.py
+++ b/release/scripts/modules/bpy/utils.py
@@ -23,10 +23,7 @@ This module contains utility functions specific to blender but
not assosiated with blenders internal data.
"""
-from _bpy import register_class
-from _bpy import unregister_class
-
-from _bpy import blend_paths
+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
@@ -34,24 +31,32 @@ import bpy as _bpy
import os as _os
import sys as _sys
+import addon_utils as _addon_utils
+
+_script_module_dirs = "startup", "modules"
+
def _test_import(module_name, loaded_modules):
- import traceback
- import time
+ use_time = _bpy.app.debug
+
if module_name in loaded_modules:
return None
if "." in module_name:
print("Ignoring '%s', can't import files containing multiple periods." % module_name)
return None
- t = time.time()
+ if use_time:
+ import time
+ t = time.time()
+
try:
mod = __import__(module_name)
except:
+ import traceback
traceback.print_exc()
return None
- if _bpy.app.debug:
+ if use_time:
print("time %s %.4f" % (module_name, time.time() - t))
loaded_modules.add(mod.__name__) # should match mod.__name__ too
@@ -74,9 +79,6 @@ def modules_from_path(path, loaded_modules):
:return: all loaded modules.
:rtype: list
"""
- import traceback
- import time
-
modules = []
for mod_name, mod_path in _bpy.path.module_names(path):
@@ -100,10 +102,11 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
:arg refresh_scripts: only load scripts which are not already loaded as modules.
:type refresh_scripts: bool
"""
- import traceback
- import time
+ use_time = _bpy.app.debug
- t_main = time.time()
+ if use_time:
+ import time
+ t_main = time.time()
loaded_modules = set()
@@ -117,7 +120,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
# 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]:
- addon_disable(module_name, default_set=False)
+ _addon_utils.disable(module_name, default_set=False)
def register_module_call(mod):
register = getattr(mod, "register", None)
@@ -125,6 +128,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
try:
register()
except:
+ import traceback
traceback.print_exc()
else:
print("\nWarning! '%s' has no register function, this is now a requirement for registerable scripts." % mod.__file__)
@@ -135,6 +139,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
try:
unregister()
except:
+ import traceback
traceback.print_exc()
def test_reload(mod):
@@ -148,6 +153,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
try:
return imp.reload(mod)
except:
+ import traceback
traceback.print_exc()
def test_register(mod):
@@ -178,10 +184,8 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
_global_loaded_modules[:] = []
- user_path = user_script_path()
-
for base_path in script_paths():
- for path_subdir in ("", "ui", "op", "io", "keyingsets", "modules"):
+ for path_subdir in _script_module_dirs:
path = _os.path.join(base_path, path_subdir)
if _os.path.isdir(path):
_sys_path_ensure(path)
@@ -190,14 +194,11 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
if path_subdir == "modules":
continue
- if user_path != base_path and path_subdir == "":
- continue # avoid loading 2.4x scripts
-
for mod in modules_from_path(path, loaded_modules):
test_register(mod)
- # deal with addons seperately
- addon_reset_all(reload_scripts)
+ # deal with addons separately
+ _addon_utils.reset_all(reload_scripts)
# run the active integration preset
filepath = preset_find(_bpy.context.user_preferences.inputs.active_keyconfig, "keyconfig")
@@ -208,7 +209,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
import gc
print("gc.collect() -> %d" % gc.collect())
- if _bpy.app.debug:
+ if use_time:
print("Python Script Load Time %.4f" % (time.time() - t_main))
@@ -227,27 +228,41 @@ def user_script_path():
return None
-def script_paths(subdir=None, user=True):
+def script_paths(subdir=None, user_pref=True, all=False):
"""
- Returns a list of valid script paths from the home directory and user preferences.
+ Returns a list of valid script paths.
- Accepts any number of string arguments which are joined to make a path.
+ :arg subdir: Optional subdir.
+ :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.
+ :type all: bool
+ :return: script paths.
+ :rtype: list
"""
scripts = list(_scripts)
# add user scripts dir
- if user:
+ if user_pref:
user_script_path = _bpy.context.user_preferences.filepaths.script_directory
else:
user_script_path = None
- for path in _bpy_script_paths() + (user_script_path, ):
+ if all:
+ # all possible paths
+ 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()
+
+ for path in base_paths + (user_script_path, ):
if path:
path = _os.path.normpath(path)
if path not in scripts and _os.path.isdir(path):
scripts.append(path)
- if not subdir:
+ if subdir is None:
return scripts
script_paths = []
@@ -259,6 +274,24 @@ def script_paths(subdir=None, user=True):
return script_paths
+def refresh_script_paths():
+ """
+ Run this after creating new script paths to update sys.path
+ """
+
+ for base_path in script_paths():
+ for path_subdir in _script_module_dirs:
+ path = _os.path.join(base_path, path_subdir)
+ if _os.path.isdir(path):
+ _sys_path_ensure(path)
+
+ for path in _addon_utils.paths():
+ _sys_path_ensure(path)
+ path = _os.path.join(path, "modules")
+ if _os.path.isdir(path):
+ _sys_path_ensure(path)
+
+
_presets = _os.path.join(_scripts[0], "presets") # FIXME - multiple paths
@@ -267,7 +300,7 @@ def preset_paths(subdir):
Returns a list of paths for a specific preset.
"""
dirs = []
- for path in script_paths("presets"):
+ for path in script_paths("presets", all=True):
directory = _os.path.join(path, subdir)
if _os.path.isdir(directory):
dirs.append(directory)
@@ -322,176 +355,6 @@ def smpte_from_frame(frame, fps=None, fps_base=None):
return smpte_from_seconds((frame * fps_base) / fps, fps)
-def addon_check(module_name):
- """
- Returns the loaded state of the addon.
-
- :arg module_name: The name of the addon and module.
- :type module_name: string
- :return: (loaded_default, loaded_state)
- :rtype: tuple of booleans
- """
- loaded_default = module_name in _bpy.context.user_preferences.addons
-
- mod = _sys.modules.get(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" %
- (module_name, getattr(mod, "__file__", "<unknown>")))
-
- loaded_state = False
-
- return loaded_default, loaded_state
-
-
-def addon_enable(module_name, default_set=True):
- """
- Enables an addon by name.
-
- :arg module_name: The name of the addon and module.
- :type module_name: string
- :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():
- import traceback
- traceback.print_exc()
-
- # reload if the mtime changes
- mod = sys.modules.get(module_name)
- if mod:
- mod.__addon_enabled__ = False
- mtime_orig = getattr(mod, "__time__", 0)
- mtime_new = os.path.getmtime(mod.__file__)
- if mtime_orig != mtime_new:
- print("module changed on disk:", mod.__file__, "reloading...")
-
- try:
- imp.reload(mod)
- except:
- handle_error()
- del sys.modules[module_name]
- return None
- mod.__addon_enabled__ = False
-
- # Split registering up into 3 steps so we can undo if it fails par way through
- # 1) try import
- try:
- mod = __import__(module_name)
- mod.__time__ = os.path.getmtime(mod.__file__)
- mod.__addon_enabled__ = False
- except:
- handle_error()
- return None
-
- # 2) try register collected modules
- # removed, addons need to handle own registration now.
-
- # 3) try run the modules register function
- try:
- mod.register()
- except:
- handle_error()
- del sys.modules[module_name]
- return None
-
- # * OK loaded successfully! *
- if default_set:
- # just incase its enabled alredy
- ext = _bpy.context.user_preferences.addons.get(module_name)
- if not ext:
- ext = _bpy.context.user_preferences.addons.new()
- ext.module = module_name
-
- mod.__addon_enabled__ = True
-
- if _bpy.app.debug:
- print("\tbpy.utils.addon_enable", mod.__name__)
-
- return mod
-
-
-def addon_disable(module_name, default_set=True):
- """
- Disables an addon by name.
-
- :arg module_name: The name of the addon and module.
- :type module_name: string
- """
- import traceback
- 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.
- if mod:
- mod.__addon_enabled__ = False
-
- try:
- mod.unregister()
- except:
- traceback.print_exc()
- else:
- print("addon_disable", module_name, "not loaded")
-
- # could be in more then once, unlikely but better do this just incase.
- addons = _bpy.context.user_preferences.addons
-
- if default_set:
- while module_name in addons:
- addon = addons.get(module_name)
- if addon:
- addons.remove(addon)
-
- if _bpy.app.debug:
- print("\tbpy.utils.addon_disable", module_name)
-
-
-def addon_reset_all(reload_scripts=False):
- """
- Sets the addon state based on the user preferences.
- """
- import imp
-
- # RELEASE SCRIPTS: official scripts distributed in Blender releases
- paths = script_paths("addons")
-
- # CONTRIB SCRIPTS: good for testing but not official scripts yet
- paths += script_paths("addons_contrib")
-
- # EXTERN SCRIPTS: external projects scripts
- paths += script_paths("addons_extern")
-
- for path in paths:
- _sys_path_ensure(path)
- for mod_name, mod_path in _bpy.path.module_names(path):
- is_enabled, is_loaded = addon_check(mod_name)
-
- # first check if reload is needed before changing state.
- if reload_scripts:
- mod = _sys.modules.get(mod_name)
- if mod:
- imp.reload(mod)
-
- if is_enabled == is_loaded:
- pass
- elif is_enabled:
- addon_enable(mod_name)
- elif is_loaded:
- print("\taddon_reset_all unloading", mod_name)
- addon_disable(mod_name)
-
-
def preset_find(name, preset_path, display_name=False):
if not name:
return None
@@ -518,12 +381,13 @@ def keyconfig_set(filepath):
print("loading preset:", filepath)
keyconfigs = _bpy.context.window_manager.keyconfigs
- kc_orig = keyconfigs.active
keyconfigs_old = keyconfigs[:]
try:
- exec(compile(open(filepath).read(), filepath, 'exec'), {"__file__": filepath})
+ file = open(filepath)
+ exec(compile(file.read(), filepath, 'exec'), {"__file__": filepath})
+ file.close()
except:
import traceback
traceback.print_exc()
@@ -583,48 +447,47 @@ def _bpy_module_classes(module, is_registered=False):
typemap_list = _bpy_types.TypeMap.get(module, ())
i = 0
while i < len(typemap_list):
- cls_weakref, path, line = typemap_list[i]
+ cls_weakref = typemap_list[i]
cls = cls_weakref()
if cls is None:
del typemap_list[i]
else:
- if is_registered == ("bl_rna" in cls.__dict__):
- yield (cls, path, line)
+ if is_registered == cls.is_registered:
+ yield cls
i += 1
def register_module(module, verbose=False):
- import traceback
if verbose:
print("bpy.utils.register_module(%r): ..." % module)
- for cls, path, line in _bpy_module_classes(module, is_registered=False):
+ cls = None
+ for cls in _bpy_module_classes(module, is_registered=False):
if verbose:
- print(" %s of %s:%s" % (cls, path, line))
+ print(" %r" % cls)
try:
register_class(cls)
except:
- print("bpy.utils.register_module(): failed to registering class '%s.%s'" % (cls.__module__, cls.__name__))
- print("\t", path, "line", line)
+ print("bpy.utils.register_module(): failed to registering class %r" % cls)
+ import traceback
traceback.print_exc()
if verbose:
print("done.\n")
- if "cls" not in locals():
+ if cls is None:
raise Exception("register_module(%r): defines no classes" % module)
def unregister_module(module, verbose=False):
- import traceback
if verbose:
print("bpy.utils.unregister_module(%r): ..." % module)
- for cls, path, line in _bpy_module_classes(module, is_registered=True):
+ for cls in _bpy_module_classes(module, is_registered=True):
if verbose:
- print(" %s of %s:%s" % (cls, path, line))
+ print(" %r" % cls)
try:
unregister_class(cls)
except:
- print("bpy.utils.unregister_module(): failed to unregistering class '%s.%s'" % (cls.__module__, cls.__name__))
- print("\t", path, "line", line)
+ print("bpy.utils.unregister_module(): failed to unregistering class %r" % cls)
+ import traceback
traceback.print_exc()
if verbose:
- print("done.\n") \ No newline at end of file
+ print("done.\n")
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 4eb712a65cc..c3352dd33ad 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -23,9 +23,11 @@ import _bpy
from mathutils import Vector
StructRNA = bpy_types.Struct.__bases__[0]
-StructMetaIDProp = _bpy.StructMetaIDProp
+StructMetaPropGroup = _bpy.StructMetaPropGroup
# StructRNA = bpy_types.Struct
+bpy_types.BlendDataLibraries.load = _bpy._library_load
+
class Context(StructRNA):
__slots__ = ()
@@ -188,7 +190,7 @@ class _GenericBone:
@length.setter
def length(self, value):
- self.tail = self.head + ((self.tail - self.head).normalize() * value)
+ self.tail = self.head + ((self.tail - self.head).normalized() * value)
@property
def vector(self):
@@ -258,15 +260,15 @@ class _GenericBone:
return bones
-class PoseBone(StructRNA, _GenericBone, metaclass=StructMetaIDProp):
+class PoseBone(StructRNA, _GenericBone, metaclass=StructMetaPropGroup):
__slots__ = ()
-class Bone(StructRNA, _GenericBone, metaclass=StructMetaIDProp):
+class Bone(StructRNA, _GenericBone, metaclass=StructMetaPropGroup):
__slots__ = ()
-class EditBone(StructRNA, _GenericBone, metaclass=StructMetaIDProp):
+class EditBone(StructRNA, _GenericBone, metaclass=StructMetaPropGroup):
__slots__ = ()
def align_orientation(self, other):
@@ -278,19 +280,29 @@ class EditBone(StructRNA, _GenericBone, metaclass=StructMetaIDProp):
self.tail = self.head + vec
self.roll = other.roll
- def transform(self, matrix):
+ def transform(self, matrix, scale=True, roll=True):
"""
Transform the the bones head, tail, roll and envalope (when the matrix has a scale component).
- Expects a 4x4 or 3x3 matrix.
+
+ :arg matrix: 3x3 or 4x4 transformation matrix.
+ :type matrix: :class:`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
- scalar = matrix.median_scale
- self.head_radius *= scalar
- self.tail_radius *= scalar
- self.align_roll(z_vec * matrix)
+
+ if scale:
+ scalar = matrix.median_scale
+ self.head_radius *= scalar
+ self.tail_radius *= scalar
+
+ if roll:
+ self.align_roll(z_vec * matrix)
def ord_ind(i1, i2):
@@ -557,37 +569,49 @@ TypeMap = {}
class RNAMeta(type):
def __new__(cls, name, bases, classdict, **args):
result = type.__new__(cls, name, bases, classdict)
- if bases and bases[0] != StructRNA:
- import traceback
- import weakref
+ if bases and bases[0] is not StructRNA:
+ from _weakref import ref as ref
module = result.__module__
# first part of packages only
if "." in module:
module = module[:module.index(".")]
- sf = traceback.extract_stack(limit=2)[0]
-
- TypeMap.setdefault(module, []).append((weakref.ref(result), sf[0], sf[1]))
+ TypeMap.setdefault(module, []).append(ref(result))
return result
+ @property
+ def is_registered(cls):
+ return "bl_rna" in cls.__dict__
+
+
+class OrderedDictMini(dict):
+ def __init__(self, *args):
+ self.order = []
+ dict.__init__(self, args)
+
+ def __setitem__(self, key, val):
+ dict.__setitem__(self, key, val)
+ if key not in self.order:
+ self.order.append(key)
-import collections
+ def __delitem__(self, key):
+ dict.__delitem__(self, key)
+ self.order.remove(key)
-class RNAMetaIDProp(RNAMeta, StructMetaIDProp):
+class RNAMetaPropGroup(RNAMeta, StructMetaPropGroup):
pass
class OrderedMeta(RNAMeta):
-
def __init__(cls, name, bases, attributes):
- super(OrderedMeta, cls).__init__(name, bases, attributes)
- cls.order = list(attributes.keys())
+ if attributes.__class__ is OrderedDictMini:
+ cls.order = attributes.order
def __prepare__(name, bases, **kwargs):
- return collections.OrderedDict()
+ return OrderedDictMini() # collections.OrderedDict()
# Only defined so operators members can be used by accessing self.order
@@ -634,7 +658,7 @@ class Macro(StructRNA, metaclass=OrderedMeta):
return ops.macro_define(self, opname)
-class IDPropertyGroup(StructRNA, metaclass=RNAMetaIDProp):
+class PropertyGroup(StructRNA, metaclass=RNAMetaPropGroup):
__slots__ = ()
@@ -656,6 +680,9 @@ class _GenericUI:
if draw_funcs is None:
def draw_ls(self, context):
+ # ensure menus always get default context
+ operator_context_default = self.layout.operator_context
+
for func in draw_ls._draw_funcs:
# so bad menu functions dont stop the entire menu from drawing.
try:
@@ -664,6 +691,8 @@ class _GenericUI:
import traceback
traceback.print_exc()
+ self.layout.operator_context = operator_context_default
+
draw_funcs = draw_ls._draw_funcs = [cls.draw]
cls.draw = draw_ls
@@ -671,7 +700,7 @@ class _GenericUI:
@classmethod
def append(cls, draw_func):
- """Prepend an draw function to this menu, takes the same arguments as the menus draw function."""
+ """Append a draw function to this menu, takes the same arguments as the menus draw function."""
draw_funcs = cls._dyn_ui_initialize()
draw_funcs.append(draw_func)
diff --git a/release/scripts/modules/bpyml.py b/release/scripts/modules/bpyml.py
index f1f72d50fd2..fdf5172a0b3 100644
--- a/release/scripts/modules/bpyml.py
+++ b/release/scripts/modules/bpyml.py
@@ -160,9 +160,9 @@ if __name__ == "__main__":
from bpyml_test import *
draw = [
- ui() [
- split() [
- column() [
+ ui()[
+ split()[
+ column()[
prop(data='context.scene.render', property='use_stamp_time', text='Time'),
prop(data='context.scene.render', property='use_stamp_date', text='Date'),
prop(data='context.scene.render', property='use_stamp_render_time', text='RenderTime'),
@@ -173,7 +173,7 @@ if __name__ == "__main__":
prop(data='context.scene.render', property='use_stamp_marker', text='Marker'),
prop(data='context.scene.render', property='use_stamp_sequencer_strip', text='Seq. Strip')
],
- column() [
+ column()[
active(expr='context.scene.render.use_stamp'),
prop(data='context.scene.render', property='stamp_foreground', slider=True),
prop(data='context.scene.render', property='stamp_background', slider=True),
@@ -181,9 +181,9 @@ if __name__ == "__main__":
prop(data='context.scene.render', property='stamp_font_size', text='Font Size')
]
],
- split(percentage=0.2) [
+ split(percentage=0.2)[
prop(data='context.scene.render', property='use_stamp_note', text='Note'),
- row() [
+ row()[
active(expr='context.scene.render.use_stamp_note'),
prop(data='context.scene.render', property='stamp_note_text', text='')
]
diff --git a/release/scripts/modules/bpyml_ui.py b/release/scripts/modules/bpyml_ui.py
index 2462dd60e3e..1e0522974d1 100644
--- a/release/scripts/modules/bpyml_ui.py
+++ b/release/scripts/modules/bpyml_ui.py
@@ -65,7 +65,7 @@ def _parse_rna_args(base, py_node):
def _call_recursive(context, base, py_node):
- prop = base.bl_rna.properties.get(py_node[TAG])
+ # prop = base.bl_rna.properties.get(py_node[TAG])
if py_node[TAG] in base.bl_rna.properties:
value = py_node[ARGS].get("expr")
if value:
@@ -73,7 +73,7 @@ def _call_recursive(context, base, py_node):
setattr(base, py_node[TAG], value)
else:
value = py_node[ARGS]['value'] # have to have this
- setattr(base, name, value)
+ setattr(base, py_node[TAG], value)
else:
args = _parse_rna_args(base, py_node)
func_new = getattr(base, py_node[TAG])
diff --git a/release/scripts/op/console_python.py b/release/scripts/modules/console_python.py
index 98d3f3f74a3..3048fa1d597 100644
--- a/release/scripts/op/console_python.py
+++ b/release/scripts/modules/console_python.py
@@ -33,6 +33,20 @@ def add_scrollback(text, text_type):
type=text_type)
+def replace_help(namespace):
+ def _help(*args):
+ # because of how the console works. we need our own help() pager func.
+ # replace the bold function because it adds crazy chars
+ import pydoc
+ pydoc.getpager = lambda: pydoc.plainpager
+ pydoc.Helper.getline = lambda self, prompt: None
+ pydoc.TextDoc.use_bold = lambda self, text: text
+
+ pydoc.help(*args)
+
+ namespace["help"] = _help
+
+
def get_console(console_id):
'''
helper function for console operators
@@ -83,11 +97,13 @@ def get_console(console_id):
namespace["bpy"] = bpy
namespace["C"] = bpy.context
- namespace.update(__import__("mathutils").__dict__) # from mathutils import *
- namespace.update(__import__("math").__dict__) # from math import *
+ replace_help(namespace)
console = InteractiveConsole(locals=namespace, filename="<blender_console>")
+ console.push("from mathutils import *")
+ console.push("from math import *")
+
if _BPY_MAIN_OWN:
console._bpy_main_mod = bpy_main_mod
@@ -224,12 +240,20 @@ def autocomplete(context):
# This function isnt aware of the text editor or being an operator
# just does the autocomp then copy its results back
- current_line.body, current_line.current_character, scrollback = \
- intellisense.expand(
- line=current_line.body,
+ result = intellisense.expand(
+ line=line,
cursor=current_line.current_character,
namespace=console.locals,
private=bpy.app.debug)
+
+ line_new = result[0]
+ current_line.body, current_line.current_character, scrollback = result
+ del result
+
+ # update sel. setting body should really do this!
+ ofs = len(line_new) - len(line)
+ sc.select_start += ofs
+ sc.select_end += ofs
except:
# unlikely, but this can happen with unicode errors for example.
# or if the api attribute access its self causes an error.
@@ -272,23 +296,11 @@ def banner(context):
add_scrollback("Execute: Enter", 'OUTPUT')
add_scrollback("Autocomplete: Ctrl+Space", 'OUTPUT')
add_scrollback("Ctrl +/- Wheel: Zoom", 'OUTPUT')
- add_scrollback("Builtin Modules: bpy, bpy.data, bpy.ops, bpy.props, bpy.types, bpy.context, bgl, blf, mathutils", 'OUTPUT')
+ add_scrollback("Builtin Modules: bpy, bpy.data, bpy.ops, bpy.props, bpy.types, bpy.context, bpy.utils, bgl, blf, mathutils", 'OUTPUT')
add_scrollback("Convenience Imports: from mathutils import *; from math import *", 'OUTPUT')
add_scrollback("", 'OUTPUT')
- add_scrollback(" WARNING!!! Blender 2.5 API is subject to change, see API reference for more info.", 'ERROR')
- add_scrollback("", 'OUTPUT')
+ # add_scrollback(" WARNING!!! Blender 2.5 API is subject to change, see API reference for more info.", 'ERROR')
+ # add_scrollback("", 'OUTPUT')
sc.prompt = PROMPT
return {'FINISHED'}
-
-
-def register():
- pass
-
-
-def unregister():
- pass
-
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/op/console_shell.py b/release/scripts/modules/console_shell.py
index 2c5b48acd34..7a6f45c426f 100644
--- a/release/scripts/op/console_shell.py
+++ b/release/scripts/modules/console_shell.py
@@ -76,14 +76,3 @@ def banner(context):
sc.prompt = os.getcwd() + PROMPT
return {'FINISHED'}
-
-
-def register():
- pass
-
-
-def unregister():
- pass
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/modules/image_utils.py b/release/scripts/modules/image_utils.py
index d74c89ac173..39e49ee1f96 100644
--- a/release/scripts/modules/image_utils.py
+++ b/release/scripts/modules/image_utils.py
@@ -23,5 +23,5 @@ def image_load(filepath, dirpath, place_holder=False, recursive=False, convert_c
import bpy
try:
return bpy.data.images.load(filepath)
- except SystemError:
+ except RuntimeError:
return bpy.data.images.new("Untitled", 128, 128)
diff --git a/release/scripts/modules/io_utils.py b/release/scripts/modules/io_utils.py
index 39b38669188..820d7cfa39d 100644
--- a/release/scripts/modules/io_utils.py
+++ b/release/scripts/modules/io_utils.py
@@ -19,13 +19,17 @@
# <pep8 compliant>
import bpy
-from bpy.props import *
+from bpy.props import StringProperty, BoolProperty, EnumProperty
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'})
+ # subclasses can override with decorator
+ # True == use ext, False == no ext, None == do nothing.
+ check_extension = True
+
def invoke(self, context, event):
import os
if not self.filepath:
@@ -41,12 +45,18 @@ class ExportHelper:
return {'RUNNING_MODAL'}
def check(self, context):
- filepath = bpy.path.ensure_ext(self.filepath, self.filename_ext)
+ check_extension = self.check_extension
+
+ if check_extension is None:
+ return False
+
+ filepath = bpy.path.ensure_ext(self.filepath, self.filename_ext if check_extension else "")
+
if filepath != self.filepath:
self.filepath = filepath
return True
- else:
- return False
+
+ return False
class ImportHelper:
@@ -57,6 +67,86 @@ class ImportHelper:
return {'RUNNING_MODAL'}
+# Axis conversion function, not pretty LUT
+# use lookup tabes to convert between any axis
+_axis_convert_matrix = (
+ ((-1.0, 0.0, 0.0), (0.0, -1.0, 0.0), (0.0, 0.0, 1.0)),
+ ((-1.0, 0.0, 0.0), (0.0, 0.0, -1.0), (0.0, -1.0, 0.0)),
+ ((-1.0, 0.0, 0.0), (0.0, 0.0, 1.0), (0.0, 1.0, 0.0)),
+ ((-1.0, 0.0, 0.0), (0.0, 1.0, 0.0), (0.0, 0.0, -1.0)),
+ ((0.0, -1.0, 0.0), (-1.0, 0.0, 0.0), (0.0, 0.0, -1.0)),
+ ((0.0, -1.0, 0.0), (0.0, 0.0, -1.0), (1.0, 0.0, 0.0)),
+ ((0.0, -1.0, 0.0), (0.0, 0.0, 1.0), (-1.0, 0.0, 0.0)),
+ ((0.0, -1.0, 0.0), (1.0, 0.0, 0.0), (0.0, 0.0, 1.0)),
+ ((0.0, 0.0, -1.0), (-1.0, 0.0, 0.0), (0.0, 1.0, 0.0)),
+ ((0.0, 0.0, -1.0), (0.0, -1.0, 0.0), (-1.0, 0.0, 0.0)),
+ ((0.0, 0.0, -1.0), (0.0, 1.0, 0.0), (1.0, 0.0, 0.0)),
+ ((0.0, 0.0, -1.0), (1.0, 0.0, 0.0), (0.0, -1.0, 0.0)),
+ ((0.0, 0.0, 1.0), (-1.0, 0.0, 0.0), (0.0, -1.0, 0.0)),
+ ((0.0, 0.0, 1.0), (0.0, -1.0, 0.0), (1.0, 0.0, 0.0)),
+ ((0.0, 0.0, 1.0), (0.0, 1.0, 0.0), (-1.0, 0.0, 0.0)),
+ ((0.0, 0.0, 1.0), (1.0, 0.0, 0.0), (0.0, 1.0, 0.0)),
+ ((0.0, 1.0, 0.0), (-1.0, 0.0, 0.0), (0.0, 0.0, 1.0)),
+ ((0.0, 1.0, 0.0), (0.0, 0.0, -1.0), (-1.0, 0.0, 0.0)),
+ ((0.0, 1.0, 0.0), (0.0, 0.0, 1.0), (1.0, 0.0, 0.0)),
+ ((0.0, 1.0, 0.0), (1.0, 0.0, 0.0), (0.0, 0.0, -1.0)),
+ ((1.0, 0.0, 0.0), (0.0, -1.0, 0.0), (0.0, 0.0, -1.0)),
+ ((1.0, 0.0, 0.0), (0.0, 0.0, -1.0), (0.0, 1.0, 0.0)),
+ ((1.0, 0.0, 0.0), (0.0, 0.0, 1.0), (0.0, -1.0, 0.0)),
+ )
+
+# store args as a single int
+# (X Y Z -X -Y -Z) --> (0, 1, 2, 3, 4, 5)
+# each value is ((src_forward, src_up), (dst_forward, dst_up))
+# where all 4 values are or'd into a single value...
+# (i1<<0 | i1<<3 | i1<<6 | i1<<9)
+_axis_convert_lut = (
+ {0x5c, 0x9a, 0x119, 0x15d, 0x20b, 0x2a2, 0x2c8, 0x365, 0x413, 0x46c, 0x4d0, 0x529, 0x644, 0x682, 0x701, 0x745, 0x823, 0x88a, 0x8e0, 0x94d, 0xa2b, 0xa54, 0xae8, 0xb11},
+ {0x9c, 0xac, 0x159, 0x169, 0x22b, 0x2e8, 0x40b, 0x465, 0x4c8, 0x522, 0x684, 0x694, 0x741, 0x751, 0x813, 0x8d0, 0xa23, 0xa4d, 0xae0, 0xb0a},
+ {0x99, 0xa9, 0x15c, 0x16c, 0x213, 0x2d0, 0x423, 0x44a, 0x4e0, 0x50d, 0x681, 0x691, 0x744, 0x754, 0x82b, 0x8e8, 0xa0b, 0xa62, 0xac8, 0xb25},
+ {0x59, 0x85, 0x11c, 0x142, 0x223, 0x28d, 0x2e0, 0x34a, 0x42b, 0x469, 0x4e8, 0x52c, 0x641, 0x69d, 0x704, 0x75a, 0x80b, 0x8a5, 0x8c8, 0x962, 0xa13, 0xa51, 0xad0, 0xb14},
+ {0xa5, 0x162, 0x21c, 0x285, 0x2d9, 0x342, 0x463, 0x46b, 0x520, 0x528, 0x68d, 0x74a, 0x804, 0x89d, 0x8c1, 0x95a, 0xa4b, 0xa53, 0xb08, 0xb10},
+ {0x4b, 0x53, 0x108, 0x110, 0x29c, 0x2ac, 0x359, 0x369, 0x41a, 0x422, 0x4dd, 0x4e5, 0x663, 0x66b, 0x720, 0x728, 0x884, 0x894, 0x941, 0x951, 0xa02, 0xa0a, 0xac5, 0xacd},
+ {0x63, 0x6b, 0x120, 0x128, 0x299, 0x2a9, 0x35c, 0x36c, 0x405, 0x40d, 0x4c2, 0x4ca, 0x64b, 0x653, 0x708, 0x710, 0x881, 0x891, 0x944, 0x954, 0xa1d, 0xa25, 0xada, 0xae2},
+ {0x8a, 0x14d, 0x219, 0x29a, 0x2dc, 0x35d, 0x44b, 0x453, 0x508, 0x510, 0x6a2, 0x765, 0x801, 0x882, 0x8c4, 0x945, 0xa63, 0xa6b, 0xb20, 0xb28},
+ {0x5a, 0x62, 0x8b, 0x11d, 0x125, 0x148, 0x22c, 0x28b, 0x293, 0x2e9, 0x348, 0x350, 0x41c, 0x42c, 0x45a, 0x4d9, 0x4e9, 0x51d, 0x642, 0x64a, 0x6a3, 0x705, 0x70d, 0x760, 0x814, 0x8a3, 0x8ab, 0x8d1, 0x960, 0x968, 0xa04, 0xa14, 0xa42, 0xac1, 0xad1, 0xb05},
+ {0x54, 0xab, 0x111, 0x168, 0x21d, 0x225, 0x2da, 0x2e2, 0x45c, 0x519, 0x66c, 0x693, 0x729, 0x750, 0x805, 0x80d, 0x8c2, 0x8ca, 0xa44, 0xb01},
+ {0x51, 0x93, 0x114, 0x150, 0x202, 0x20a, 0x2c5, 0x2cd, 0x459, 0x51c, 0x669, 0x6ab, 0x72c, 0x768, 0x81a, 0x822, 0x8dd, 0x8e5, 0xa41, 0xb04},
+ {0x45, 0x4d, 0xa3, 0x102, 0x10a, 0x160, 0x229, 0x2a3, 0x2ab, 0x2ec, 0x360, 0x368, 0x419, 0x429, 0x445, 0x4dc, 0x4ec, 0x502, 0x65d, 0x665, 0x68b, 0x71a, 0x722, 0x748, 0x811, 0x88b, 0x893, 0x8d4, 0x948, 0x950, 0xa01, 0xa11, 0xa5d, 0xac4, 0xad4, 0xb1a},
+ {0x5d, 0x65, 0xa0, 0x11a, 0x122, 0x163, 0x214, 0x2a0, 0x2a8, 0x2d1, 0x363, 0x36b, 0x404, 0x414, 0x45d, 0x4c1, 0x4d1, 0x51a, 0x645, 0x64d, 0x688, 0x702, 0x70a, 0x74b, 0x82c, 0x888, 0x890, 0x8e9, 0x94b, 0x953, 0xa1c, 0xa2c, 0xa45, 0xad9, 0xae9, 0xb02},
+ {0x6c, 0x90, 0x129, 0x153, 0x21a, 0x222, 0x2dd, 0x2e5, 0x444, 0x501, 0x654, 0x6a8, 0x711, 0x76b, 0x802, 0x80a, 0x8c5, 0x8cd, 0xa5c, 0xb19},
+ {0x69, 0xa8, 0x12c, 0x16b, 0x205, 0x20d, 0x2c2, 0x2ca, 0x441, 0x504, 0x651, 0x690, 0x714, 0x753, 0x81d, 0x825, 0x8da, 0x8e2, 0xa59, 0xb1c},
+ {0x42, 0x4a, 0x88, 0x105, 0x10d, 0x14b, 0x211, 0x288, 0x290, 0x2d4, 0x34b, 0x353, 0x401, 0x411, 0x442, 0x4c4, 0x4d4, 0x505, 0x65a, 0x662, 0x6a0, 0x71d, 0x725, 0x763, 0x829, 0x8a0, 0x8a8, 0x8ec, 0x963, 0x96b, 0xa19, 0xa29, 0xa5a, 0xadc, 0xaec, 0xb1d},
+ {0xa2, 0x165, 0x204, 0x282, 0x2c1, 0x345, 0x448, 0x450, 0x50b, 0x513, 0x68a, 0x74d, 0x81c, 0x89a, 0x8d9, 0x95d, 0xa60, 0xa68, 0xb23, 0xb2b},
+ {0x60, 0x68, 0x123, 0x12b, 0x284, 0x294, 0x341, 0x351, 0x41d, 0x425, 0x4da, 0x4e2, 0x648, 0x650, 0x70b, 0x713, 0x89c, 0x8ac, 0x959, 0x969, 0xa05, 0xa0d, 0xac2, 0xaca},
+ {0x48, 0x50, 0x10b, 0x113, 0x281, 0x291, 0x344, 0x354, 0x402, 0x40a, 0x4c5, 0x4cd, 0x660, 0x668, 0x723, 0x72b, 0x899, 0x8a9, 0x95c, 0x96c, 0xa1a, 0xa22, 0xadd, 0xae5},
+ {0x8d, 0x14a, 0x201, 0x29d, 0x2c4, 0x35a, 0x460, 0x468, 0x523, 0x52b, 0x6a5, 0x762, 0x819, 0x885, 0x8dc, 0x942, 0xa48, 0xa50, 0xb0b, 0xb13},
+ {0x44, 0x9d, 0x101, 0x15a, 0x220, 0x2a5, 0x2e3, 0x362, 0x428, 0x454, 0x4eb, 0x511, 0x65c, 0x685, 0x719, 0x742, 0x808, 0x88d, 0x8cb, 0x94a, 0xa10, 0xa6c, 0xad3, 0xb29},
+ {0x84, 0x94, 0x141, 0x151, 0x210, 0x2d3, 0x420, 0x462, 0x4e3, 0x525, 0x69c, 0x6ac, 0x759, 0x769, 0x828, 0x8eb, 0xa08, 0xa4a, 0xacb, 0xb0d},
+ {0x81, 0x91, 0x144, 0x154, 0x228, 0x2eb, 0x408, 0x44d, 0x4cb, 0x50a, 0x699, 0x6a9, 0x75c, 0x76c, 0x810, 0x8d3, 0xa20, 0xa65, 0xae3, 0xb22},
+ )
+
+_axis_convert_num = {'X': 0, 'Y': 1, 'Z': 2, '-X': 3, '-Y': 4, '-Z': 5}
+
+
+def axis_conversion(from_forward='Y', from_up='Z', to_forward='Y', to_up='Z'):
+ """
+ Each argument us an axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z']
+ where the first 2 are a source and the second 2 are the target.
+ """
+ from mathutils import Matrix
+ from functools import reduce
+
+ 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))))
+ for i, axis_lut in enumerate(_axis_convert_lut):
+ if value in axis_lut:
+ return Matrix(_axis_convert_matrix[i])
+ assert("internal error")
+
+
# limited replacement for BPyImage.comprehensiveImageLoad
def load_image(imagepath, dirname):
import os
@@ -81,14 +171,14 @@ def create_derived_objects(scene, ob):
return False, None
if ob.dupli_type != 'NONE':
- ob.create_dupli_list(scene)
+ ob.dupli_list_create(scene)
return True, [(dob.object, dob.matrix) for dob in ob.dupli_list]
else:
return False, [(ob, ob.matrix_world)]
def free_derived_objects(ob):
- ob.free_dupli_list()
+ ob.dupli_list_clear()
def unpack_list(list_of_tuples):
@@ -116,3 +206,99 @@ def unpack_face_list(list_of_tuples):
flat_ls[i:i + len(t)] = t
i += 4
return flat_ls
+
+
+path_reference_mode = EnumProperty(
+ name="Path Mode",
+ 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"),
+ ('STRIP', "Strip Path", "Filename only"),
+ ('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):
+ """
+ Return a filepath relative to a destination directory, for use with
+ exporters.
+
+ :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).
+ :type base_src: string
+ :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']
+ :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.
+ :type copy_set: set
+ :return: the new filepath.
+ :rtype: string
+ """
+ import os
+ is_relative = filepath.startswith("//")
+ filepath_abs = os.path.normpath(bpy.path.abspath(filepath, base_src))
+
+ 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'
+ elif mode == 'COPY':
+ if copy_subdir:
+ subdir_abs = os.path.join(os.path.normpath(base_dst), copy_subdir)
+ else:
+ subdir_abs = os.path.normpath(base_dst)
+
+ filepath_cpy = os.path.join(subdir_abs, os.path.basename(filepath))
+
+ copy_set.add((filepath_abs, filepath_cpy))
+
+ filepath_abs = filepath_cpy
+ mode = 'RELATIVE'
+ else:
+ Excaption("invalid mode given %r" % mode)
+
+ if mode == 'ABSOLUTE':
+ return filepath_abs
+ elif mode == 'RELATIVE':
+ return os.path.relpath(filepath_abs, base_dst)
+ elif mode == 'STRIP':
+ return os.path.basename(filepath_abs)
+
+
+def path_reference_copy(copy_set, report=print):
+ """
+ Execute copying files of path_reference
+
+ :arg copy_set: set of (from, to) pairs to copy.
+ :type copy_set: set
+ :arg report: function used for reporting warnings, takes a string argument.
+ :type report: function
+ """
+ if not copy_set:
+ return
+
+ import os
+ import shutil
+
+ for file_src, file_dst in copy_set:
+ if not os.path.exists(file_src):
+ report("missing %r, not copying" % file_src)
+ elif os.path.exists(file_dst) and os.path.samefile(file_src, file_dst):
+ pass
+ else:
+ dir_to = os.path.dirname(file_dst)
+
+ if not os.path.isdir(dir_to):
+ os.makedirs(dir_to)
+
+ shutil.copy(file_src, file_dst)
diff --git a/release/scripts/modules/keyingsets_utils.py b/release/scripts/modules/keyingsets_utils.py
index 00ad45cf9bb..dc61ce2a4af 100644
--- a/release/scripts/modules/keyingsets_utils.py
+++ b/release/scripts/modules/keyingsets_utils.py
@@ -43,7 +43,7 @@ import bpy
# Append the specified property name on the the existing path
def path_add_property(path, prop):
- if len(path):
+ if path:
return path + "." + prop
else:
return prop
@@ -52,16 +52,21 @@ def path_add_property(path, prop):
# Poll Callbacks
-# selected objects
+# selected objects (active object must be in object mode)
def RKS_POLL_selected_objects(ksi, context):
- return context.active_object or len(context.selected_objects)
+ ob = context.active_object
+ if ob:
+ return ob.mode == 'OBJECT'
+ else:
+ return bool(context.selected_objects)
# selected bones
def RKS_POLL_selected_bones(ksi, context):
# we must be in Pose Mode, and there must be some bones selected
- if (context.active_object) and (context.active_object.mode == 'POSE'):
- if context.active_pose_bone or len(context.selected_pose_bones):
+ ob = context.active_object
+ if ob and ob.mode == 'POSE':
+ if context.active_pose_bone or context.selected_pose_bones:
return True
# nothing selected
@@ -78,13 +83,20 @@ def RKS_POLL_selected_items(ksi, context):
# all selected objects or pose bones, depending on which we've got
def RKS_ITER_selected_item(ksi, context, ks):
- if (context.active_object) and (context.active_object.mode == 'POSE'):
+ ob = context.active_object
+ if ob and ob.mode == 'POSE':
for bone in context.selected_pose_bones:
ksi.generate(context, ks, bone)
else:
for ob in context.selected_objects:
ksi.generate(context, ks, ob)
+
+# all select objects only
+def RKS_ITER_selected_objects(ksi, context, ks):
+ for ob in context.selected_objects:
+ ksi.generate(context, ks, ob)
+
###########################
# Generate Callbacks
diff --git a/release/scripts/modules/mesh_utils.py b/release/scripts/modules/mesh_utils.py
new file mode 100644
index 00000000000..5bacff7b0cc
--- /dev/null
+++ b/release/scripts/modules/mesh_utils.py
@@ -0,0 +1,69 @@
+# ##### 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>
+
+
+def mesh_linked_faces(mesh):
+ '''
+ Splits the mesh into connected parts,
+ these parts are returned as lists of faces.
+ used for seperating cubes from other mesh elements in the 1 mesh
+ '''
+
+ # Build vert face connectivity
+ vert_faces = [[] for i in range(len(mesh.vertices))]
+ for f in mesh.faces:
+ for v in f.vertices:
+ vert_faces[v].append(f)
+
+ # sort faces into connectivity groups
+ face_groups = [[f] for f in mesh.faces]
+ face_mapping = list(range(len(mesh.faces))) # map old, new face location
+
+ # Now clump faces iterativly
+ ok = True
+ while ok:
+ ok = False
+
+ for i, f in enumerate(mesh.faces):
+ mapped_index = face_mapping[f.index]
+ mapped_group = face_groups[mapped_index]
+
+ for v in f.vertices:
+ for nxt_f in vert_faces[v]:
+ if nxt_f != f:
+ nxt_mapped_index = face_mapping[nxt_f.index]
+
+ # We are not a part of the same group
+ if mapped_index != nxt_mapped_index:
+ ok = True
+
+ # 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
+
+ # Move faces into this group
+ mapped_group.extend(face_groups[nxt_mapped_index])
+
+ # remove reference to the list
+ face_groups[nxt_mapped_index] = None
+
+ # return all face groups that are not null
+ # this is all the faces that are connected in their own lists.
+ return [fg for fg in face_groups if fg]
diff --git a/release/scripts/modules/rna_info.py b/release/scripts/modules/rna_info.py
index e0298d30aa2..93a344f4b09 100644
--- a/release/scripts/modules/rna_info.py
+++ b/release/scripts/modules/rna_info.py
@@ -152,6 +152,14 @@ class InfoStructRNA:
functions.append((identifier, attr))
return functions
+ def get_py_c_functions(self):
+ import types
+ functions = []
+ for identifier, attr in self._get_py_visible_attrs():
+ if type(attr) in (types.BuiltinMethodType, types.BuiltinFunctionType):
+ functions.append((identifier, attr))
+ return functions
+
def __str__(self):
txt = ""
@@ -199,10 +207,15 @@ class InfoPropertyRNA:
self.fixed_type = None
if self.type == "enum":
- self.enum_items[:] = rna_prop.items.keys()
+ self.enum_items[:] = rna_prop.enum_items.keys()
+ self.is_enum_flag = rna_prop.is_enum_flag
+ else:
+ self.is_enum_flag = False
if self.array_length:
self.default = tuple(getattr(rna_prop, "default_array", ()))
+ elif self.type == "enum" and self.is_enum_flag:
+ self.default = getattr(rna_prop, "default_flag", set())
else:
self.default = getattr(rna_prop, "default", None)
self.default_str = "" # fallback
@@ -214,7 +227,10 @@ class InfoPropertyRNA:
elif self.type == "string":
self.default_str = "\"%s\"" % self.default
elif self.type == "enum":
- self.default_str = "'%s'" % self.default
+ if self.is_enum_flag:
+ self.default_str = "%r" % self.default # repr or set()
+ else:
+ self.default_str = "'%s'" % self.default
elif self.array_length:
self.default_str = ''
# special case for floats
@@ -237,7 +253,7 @@ class InfoPropertyRNA:
return "%s=%s" % (self.identifier, default)
return self.identifier
- def get_type_description(self, as_ret=False, as_arg=False, class_fmt="%s"):
+ def get_type_description(self, as_ret=False, as_arg=False, class_fmt="%s", collection_id="Collection"):
type_str = ""
if self.fixed_type is None:
type_str += self.type
@@ -247,7 +263,10 @@ class InfoPropertyRNA:
if self.type in ("float", "int"):
type_str += " in [%s, %s]" % (range_str(self.min), range_str(self.max))
elif self.type == "enum":
- type_str += " in [%s]" % ", ".join(("'%s'" % s) for s in self.enum_items)
+ if self.is_enum_flag:
+ type_str += " set in {%s}" % ", ".join(("'%s'" % s) for s in self.enum_items)
+ else:
+ type_str += " in [%s]" % ", ".join(("'%s'" % s) for s in self.enum_items)
if not (as_arg or as_ret):
# write default property, ignore function args for this
@@ -258,9 +277,9 @@ class InfoPropertyRNA:
else:
if self.type == "collection":
if self.collection_type:
- collection_str = (class_fmt % self.collection_type.identifier) + " collection of "
+ collection_str = (class_fmt % self.collection_type.identifier) + (" %s of " % collection_id)
else:
- collection_str = "Collection of "
+ collection_str = "%s of " % collection_id
else:
collection_str = ""
diff --git a/release/scripts/modules/sys_info.py b/release/scripts/modules/sys_info.py
index 303277a5d75..1272d81872d 100644
--- a/release/scripts/modules/sys_info.py
+++ b/release/scripts/modules/sys_info.py
@@ -50,11 +50,9 @@ def textWrap(text, length=70):
def write_sysinfo(op):
output_filename = "system-info.txt"
- warnings = 0
- notices = 0
- if output_filename in bpy.data.texts.keys():
- output = bpy.data.texts[output_filename]
+ output = bpy.data.texts.get(output_filename)
+ if output:
output.clear()
else:
output = bpy.data.texts.new(name=output_filename)
@@ -96,16 +94,19 @@ def write_sysinfo(op):
output.write('autosave: {}\n'.format(bpy.utils.user_resource('AUTOSAVE')))
output.write('tempdir: {}\n'.format(bpy.app.tempdir))
- output.write('\nOpenGL\n')
- output.write(lilies)
- output.write('renderer:\t{}\n'.format(bgl.glGetString(bgl.GL_RENDERER)))
- output.write('vendor:\t\t{}\n'.format(bgl.glGetString(bgl.GL_VENDOR)))
- output.write('version:\t{}\n'.format(bgl.glGetString(bgl.GL_VERSION)))
- output.write('extensions:\n')
-
- glext = bgl.glGetString(bgl.GL_EXTENSIONS)
- glext = textWrap(glext, 70)
- for l in glext:
- output.write('\t\t{}\n'.format(l))
+ if bpy.app.background:
+ output.write('\nOpenGL: missing, background mode\n')
+ else:
+ output.write('\nOpenGL\n')
+ output.write(lilies)
+ output.write('renderer:\t{}\n'.format(bgl.glGetString(bgl.GL_RENDERER)))
+ output.write('vendor:\t\t{}\n'.format(bgl.glGetString(bgl.GL_VENDOR)))
+ output.write('version:\t{}\n'.format(bgl.glGetString(bgl.GL_VERSION)))
+ output.write('extensions:\n')
+
+ glext = bgl.glGetString(bgl.GL_EXTENSIONS)
+ glext = textWrap(glext, 70)
+ for l in glext:
+ output.write('\t\t{}\n'.format(l))
op.report({'INFO'}, "System information generated in 'system-info.txt'")
diff --git a/release/scripts/op/fcurve_euler_filter.py b/release/scripts/op/fcurve_euler_filter.py
deleted file mode 100644
index 6332bbe309c..00000000000
--- a/release/scripts/op/fcurve_euler_filter.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# ##### 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>
-
-from math import *
-import bpy
-from mathutils import *
-
-
-def main(context):
- def cleanupEulCurve(fcv):
- keys = []
-
- for k in fcv.keyframe_points:
- keys.append([k.handle_left.copy(), k.co.copy(), k.handle_right.copy()])
- print(keys)
-
- for i in range(len(keys)):
- cur = keys[i]
- prev = keys[i - 1] if i > 0 else None
- next = keys[i + 1] if i < len(keys) - 1 else None
-
- if prev is None:
- continue
-
- th = pi
- if abs(prev[1][1] - cur[1][1]) >= th: # more than 180 degree jump
- fac = pi * 2.0
- if prev[1][1] > cur[1][1]:
- while abs(cur[1][1] - prev[1][1]) >= th: # < prev[1][1]:
- cur[0][1] += fac
- cur[1][1] += fac
- cur[2][1] += fac
- elif prev[1][1] < cur[1][1]:
- while abs(cur[1][1] - prev[1][1]) >= th:
- cur[0][1] -= fac
- cur[1][1] -= fac
- cur[2][1] -= fac
-
- for i in range(len(keys)):
- for x in range(2):
- fcv.keyframe_points[i].handle_left[x] = keys[i][0][x]
- fcv.keyframe_points[i].co[x] = keys[i][1][x]
- fcv.keyframe_points[i].handle_right[x] = keys[i][2][x]
-
- flist = bpy.context.active_object.animation_data.action.fcurves
- for f in flist:
- if f.select and f.data_path.endswith("rotation_euler"):
- cleanupEulCurve(f)
-
-
-class DiscontFilterOp(bpy.types.Operator):
- """Fixes the most common causes of gimbal lock in the fcurves of the active bone"""
- bl_idname = "graph.euler_filter"
- bl_label = "Filter out discontinuities in the active fcurves"
-
- @classmethod
- def poll(cls, context):
- return context.active_object != None
-
- def execute(self, context):
- main(context)
- return {'FINISHED'}
-
-def register():
- bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/op/uv.py b/release/scripts/op/uv.py
deleted file mode 100644
index 83282924b5b..00000000000
--- a/release/scripts/op/uv.py
+++ /dev/null
@@ -1,381 +0,0 @@
-# ##### 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 bpy.props import *
-
-
-def write_svg(fw, mesh, image_width, image_height, face_iter):
- # for making an XML compatible string
- from xml.sax.saxutils import escape
- from os.path import basename
-
- fw('<?xml version="1.0" standalone="no"?>\n')
- fw('<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" \n')
- fw(' "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">\n')
- fw('<svg width="%dpx" height="%dpx" viewBox="0px 0px %dpx %dpx"\n' % (image_width, image_height, image_width, image_height))
- fw(' xmlns="http://www.w3.org/2000/svg" version="1.1">\n')
- desc = "%r, %s, (Blender %s)" % (basename(bpy.data.filepath), mesh.name, bpy.app.version_string)
- fw('<desc>%s</desc>\n' % escape(desc))
-
- # svg colors
- fill_settings = []
- fill_default = 'fill="grey"'
- for mat in mesh.materials if mesh.materials else [None]:
- if mat:
- fill_settings.append('fill="rgb(%d, %d, %d)"' % tuple(int(c * 255) for c in mat.diffuse_color))
- else:
- fill_settings.append(fill_default)
-
- faces = mesh.faces
- for i, uvs in face_iter:
- try: # rare cases material index is invalid.
- fill = fill_settings[faces[i].material_index]
- except IndexError:
- fill = fill_default
-
- fw('<polygon %s fill-opacity="0.5" stroke="black" stroke-width="1px" \n' % fill)
- fw(' points="')
-
- for j, uv in enumerate(uvs):
- x, y = uv[0], 1.0 - uv[1]
- fw('%.3f,%.3f ' % (x * image_width, y * image_height))
- fw('" />\n')
- fw('\n')
- fw('</svg>\n')
-
-
-def write_eps(fw, mesh, image_width, image_height, face_iter):
- fw('%!PS-Adobe-3.0 EPSF-3.0\n')
- fw("%%%%Creator: Blender %s\n" % bpy.app.version_string)
- fw('%%Pages: 1\n')
- fw('%%Orientation: Portrait\n')
- fw("%%%%BoundingBox: 0 0 %d %d\n" % (image_width, image_height))
- fw("%%%%HiResBoundingBox: 0.0 0.0 %.4f %.4f\n" % (image_width, image_height))
- fw('%%EndComments\n')
- fw('%%Page: 1 1\n')
- fw('0 0 translate\n')
- fw('1.0 1.0 scale\n')
- fw('0 0 0 setrgbcolor\n')
- fw('[] 0 setdash\n')
- fw('1 setlinewidth\n')
- fw('1 setlinejoin\n')
- fw('1 setlinecap\n')
- fw('/DRAW {')
- # can remove from here to next comment to disable filling, aparently alpha is not supported
- fw('gsave\n')
- fw('0.7 setgray\n')
- fw('fill\n')
- fw('grestore\n')
- fw('0 setgray\n')
- # remove to here
- fw('stroke\n')
- fw('} def\n')
- fw('newpath\n')
-
- firstline = True
- for i, uvs in face_iter:
- for j, uv in enumerate(uvs):
- x, y = uv[0], uv[1]
- if j == 0:
- if not firstline:
- fw('closepath\n')
- fw('DRAW\n')
- fw('newpath\n')
- firstline = False
- fw('%.5f %.5f moveto\n' % (x * image_width, y * image_height))
- else:
- fw('%.5f %.5f lineto\n' % (x * image_width, y * image_height))
-
- fw('closepath\n')
- fw('DRAW\n')
- fw('showpage\n')
- fw('%%EOF\n')
-
-
-def write_png(fw, mesh_source, image_width, image_height, face_iter):
- filepath = fw.__self__.name
- fw.__self__.close()
-
- material_solids = [bpy.data.materials.new("uv_temp_solid") for i in range(max(1, len(mesh_source.materials)))]
- material_wire = bpy.data.materials.new("uv_temp_wire")
-
- scene = bpy.data.scenes.new("uv_temp")
- mesh = bpy.data.meshes.new("uv_temp")
- for mat_solid in material_solids:
- mesh.materials.append(mat_solid)
-
- tot_verts = 0
- face_lens = []
- for f in mesh_source.faces:
- tot_verts += len(f.vertices)
-
- faces_source = mesh_source.faces
-
- # get unique UV's incase there are many overlapping which slow down filling.
- face_hash_3 = set()
- face_hash_4 = set()
- for i, uv in face_iter:
- material_index = faces_source[i].material_index
- if len(uv) == 3:
- face_hash_3.add((uv[0][0], uv[0][1], uv[1][0], uv[1][1], uv[2][0], uv[2][1], material_index))
- else:
- face_hash_4.add((uv[0][0], uv[0][1], uv[1][0], uv[1][1], uv[2][0], uv[2][1], uv[3][0], uv[3][1], material_index))
-
- # now set the faces coords and locations
- # build mesh data
- mesh_new_vertices = []
- mesh_new_materials = []
- mesh_new_face_vertices = []
-
- current_vert = 0
-
- for face_data in face_hash_3:
- mesh_new_vertices.extend([face_data[0], face_data[1], 0.0, face_data[2], face_data[3], 0.0, face_data[4], face_data[5], 0.0])
- mesh_new_face_vertices.extend([current_vert, current_vert + 1, current_vert + 2, 0])
- mesh_new_materials.append(face_data[6])
- current_vert += 3
- for face_data in face_hash_4:
- mesh_new_vertices.extend([face_data[0], face_data[1], 0.0, face_data[2], face_data[3], 0.0, face_data[4], face_data[5], 0.0, face_data[6], face_data[7], 0.0])
- mesh_new_face_vertices.extend([current_vert, current_vert + 1, current_vert + 2, current_vert + 3])
- mesh_new_materials.append(face_data[8])
- current_vert += 4
-
- mesh.vertices.add(len(mesh_new_vertices) // 3)
- mesh.faces.add(len(mesh_new_face_vertices) // 4)
-
- mesh.vertices.foreach_set("co", mesh_new_vertices)
- mesh.faces.foreach_set("vertices_raw", mesh_new_face_vertices)
- mesh.faces.foreach_set("material_index", mesh_new_materials)
-
- mesh.update(calc_edges=True)
-
- obj_solid = bpy.data.objects.new("uv_temp_solid", mesh)
- obj_wire = bpy.data.objects.new("uv_temp_wire", mesh)
- base_solid = scene.objects.link(obj_solid)
- base_wire = scene.objects.link(obj_wire)
- base_solid.layers[0] = True
- base_wire.layers[0] = True
-
- # place behind the wire
- obj_solid.location = 0, 0, -1
-
- obj_wire.material_slots[0].link = 'OBJECT'
- obj_wire.material_slots[0].material = material_wire
-
- # setup the camera
- cam = bpy.data.cameras.new("uv_temp")
- cam.type = 'ORTHO'
- cam.ortho_scale = 1.0
- obj_cam = bpy.data.objects.new("uv_temp_cam", cam)
- obj_cam.location = 0.5, 0.5, 1.0
- scene.objects.link(obj_cam)
- scene.camera = obj_cam
-
- # setup materials
- for i, mat_solid in enumerate(material_solids):
- if mesh_source.materials and mesh_source.materials[i]:
- mat_solid.diffuse_color = mesh_source.materials[i].diffuse_color
-
- mat_solid.use_shadeless = True
- mat_solid.use_transparency = True
- mat_solid.alpha = 0.25
-
- material_wire.type = 'WIRE'
- material_wire.use_shadeless = True
- material_wire.diffuse_color = 0, 0, 0
-
- # scene render settings
- scene.render.use_raytrace = False
- scene.render.alpha_mode = 'STRAIGHT'
- scene.render.color_mode = 'RGBA'
-
- scene.render.resolution_x = image_width
- scene.render.resolution_y = image_height
- scene.render.resolution_percentage = 100
-
- if image_width > image_height:
- scene.render.pixel_aspect_y = image_width / image_height
- elif image_width < image_height:
- scene.render.pixel_aspect_x = image_height / image_width
-
- scene.frame_start = 1
- scene.frame_end = 1
-
- scene.render.file_format = 'PNG'
- scene.render.filepath = filepath
-
- data_context = {"blend_data": bpy.context.blend_data, "scene": scene}
- bpy.ops.render.render(data_context, write_still=True)
-
- # cleanup
- bpy.data.scenes.remove(scene)
- bpy.data.objects.remove(obj_cam)
- bpy.data.objects.remove(obj_solid)
- bpy.data.objects.remove(obj_wire)
-
- bpy.data.cameras.remove(cam)
- bpy.data.meshes.remove(mesh)
-
- bpy.data.materials.remove(material_wire)
- for mat_solid in material_solids:
- bpy.data.materials.remove(mat_solid)
-
-
-class ExportUVLayout(bpy.types.Operator):
- """Export UV layout to file"""
-
- bl_idname = "uv.export_layout"
- bl_label = "Export UV Layout"
- bl_options = {'REGISTER', 'UNDO'}
-
- filepath = StringProperty(name="File Path", description="File path used for exporting the SVG 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'})
- export_all = BoolProperty(name="All UV's", description="Export all UVs in this mesh (not just the visible ones)", default=False)
- mode = EnumProperty(items=(
- ('SVG', "Scalable Vector Graphic (.svg)", "Export the UV layout to a vector SVG file"),
- ('EPS', "Encapsulate PostScript (.eps)", "Export the UV layout to a vector EPS file"),
- ('PNG', "PNG Image (.png)", "Export the UV layout a bitmap image")),
- name="Format",
- description="File format to export the UV layout to",
- default='PNG')
- size = IntVectorProperty(size=2, default=(1024, 1024), min=8, max=32768, description="Dimensions of the exported file")
-
- @classmethod
- def poll(cls, context):
- obj = context.active_object
- return (obj and obj.type == 'MESH' and obj.data.uv_textures)
-
- def _space_image(self, context):
- space_data = context.space_data
- if isinstance(space_data, bpy.types.SpaceImageEditor):
- return space_data
- else:
- return None
-
- def _image_size(self, context, default_width=1024, default_height=1024):
- # fallback if not in image context.
- image_width, image_height = default_width, default_height
-
- space_data = self._space_image(context)
- if space_data:
- image = space_data.image
- if image:
- width, height = tuple(context.space_data.image.size)
- # incase no data is found.
- if width and height:
- image_width, image_height = width, height
-
- return image_width, image_height
-
- def _face_uv_iter(self, context):
- obj = context.active_object
- mesh = obj.data
- uv_layer = mesh.uv_textures.active.data
- uv_layer_len = len(uv_layer)
-
- if not self.export_all:
-
- local_image = Ellipsis
-
- if context.tool_settings.show_uv_local_view:
- space_data = self._space_image(context)
- if space_data:
- local_image = space_data.image
-
- faces = mesh.faces
-
- for i in range(uv_layer_len):
- uv_elem = uv_layer[i]
- # context checks
- if faces[i].select and (local_image is Ellipsis or local_image == uv_elem.image):
- #~ uv = uv_elem.uv
- #~ if False not in uv_elem.select_uv[:len(uv)]:
- #~ yield (i, uv)
-
- # just write what we see.
- yield (i, uv_layer[i].uv)
- else:
- # all, simple
- for i in range(uv_layer_len):
- yield (i, uv_layer[i].uv)
-
- def execute(self, context):
-
- obj = context.active_object
- is_editmode = (obj.mode == 'EDIT')
- if is_editmode:
- bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
-
- mesh = obj.data
-
- mode = self.mode
-
- filepath = self.filepath
- filepath = bpy.path.ensure_ext(filepath, "." + mode.lower())
- file = open(filepath, "w")
- fw = file.write
-
- if mode == 'SVG':
- func = write_svg
- elif mode == 'EPS':
- func = write_eps
- elif mode == 'PNG':
- func = write_png
-
- func(fw, mesh, self.size[0], self.size[1], self._face_uv_iter(context))
-
- if is_editmode:
- bpy.ops.object.mode_set(mode='EDIT', toggle=False)
-
- return {'FINISHED'}
-
- def check(self, context):
- filepath = bpy.path.ensure_ext(self.filepath, "." + self.mode.lower())
- if filepath != self.filepath:
- self.filepath = filepath
- return True
- else:
- return False
-
- def invoke(self, context, event):
- import os
- self.size = self._image_size(context)
- self.filepath = os.path.splitext(bpy.data.filepath)[0]
- wm = context.window_manager
- wm.fileselect_add(self)
- return {'RUNNING_MODAL'}
-
-
-def menu_func(self, context):
- self.layout.operator(ExportUVLayout.bl_idname)
-
-
-def register():
- bpy.utils.register_module(__name__)
- bpy.types.IMAGE_MT_uvs.append(menu_func)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
- bpy.types.IMAGE_MT_uvs.remove(menu_func)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/presets/interaction/blender.py b/release/scripts/presets/interaction/blender.py
index 7ac9cd1eb0b..3b6ce13d7e0 100644
--- a/release/scripts/presets/interaction/blender.py
+++ b/release/scripts/presets/interaction/blender.py
@@ -1,9 +1,6 @@
# Configuration Blender
import bpy
-wm = bpy.context.window_manager
-wm.keyconfigs.active = wm.keyconfigs['Blender']
-
bpy.context.user_preferences.view.use_mouse_auto_depth = False
bpy.context.user_preferences.view.use_zoom_to_mouse = False
bpy.context.user_preferences.view.use_rotate_around_active = False
@@ -13,4 +10,4 @@ bpy.context.user_preferences.inputs.select_mouse = 'RIGHT'
bpy.context.user_preferences.inputs.view_zoom_method = 'DOLLY'
bpy.context.user_preferences.inputs.view_zoom_axis = 'VERTICAL'
bpy.context.user_preferences.inputs.view_rotate_method = 'TRACKBALL'
-bpy.context.user_preferences.inputs.invert_mouse_wheel_zoom = False
+bpy.context.user_preferences.inputs.invert_mouse_zoom = False
diff --git a/release/scripts/presets/interaction/maya.py b/release/scripts/presets/interaction/maya.py
new file mode 100644
index 00000000000..62084645081
--- /dev/null
+++ b/release/scripts/presets/interaction/maya.py
@@ -0,0 +1,10 @@
+# Configuration Blender
+import bpy
+
+bpy.context.user_preferences.edit.use_drag_immediately = True
+bpy.context.user_preferences.edit.use_insertkey_xyz_to_rgb = False
+bpy.context.user_preferences.inputs.select_mouse = 'LEFT'
+bpy.context.user_preferences.inputs.view_zoom_method = 'DOLLY'
+bpy.context.user_preferences.inputs.view_zoom_axis = 'HORIZONTAL'
+bpy.context.user_preferences.inputs.view_rotate_method = 'TURNTABLE'
+bpy.context.user_preferences.inputs.invert_mouse_zoom = True
diff --git a/release/scripts/presets/keyconfig/maya.py b/release/scripts/presets/keyconfig/maya.py
index 120597cdd2a..87f4791ec51 100644
--- a/release/scripts/presets/keyconfig/maya.py
+++ b/release/scripts/presets/keyconfig/maya.py
@@ -7,380 +7,372 @@ kc = wm.keyconfigs.new('maya')
# Map 3D View
km = kc.keymaps.new('3D View', space_type='VIEW_3D', region_type='WINDOW', modal=False)
-kmi = km.items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', any=True)
+kmi = km.keymap_items.new('view3d.manipulator', 'LEFTMOUSE', 'PRESS', any=True)
kmi.properties.release_confirm = True
-kmi = km.items.new('view3d.cursor3d', 'ACTIONMOUSE', 'PRESS')
-kmi = km.items.new('view3d.rotate', 'LEFTMOUSE', 'PRESS', alt=True)
-kmi = km.items.new('view3d.move', 'MIDDLEMOUSE', 'PRESS', alt=True)
-kmi = km.items.new('view3d.zoom', 'RIGHTMOUSE', 'PRESS', alt=True)
-kmi = km.items.new('view3d.view_selected', 'NUMPAD_PERIOD', 'PRESS')
-kmi = km.items.new('view3d.view_center_cursor', 'NUMPAD_PERIOD', 'PRESS', ctrl=True)
-kmi = km.items.new('view3d.fly', 'F', 'PRESS', shift=True)
-kmi = km.items.new('view3d.smoothview', 'TIMER1', 'ANY', any=True)
-kmi = km.items.new('view3d.rotate', 'TRACKPADPAN', 'ANY', alt=True)
-kmi = km.items.new('view3d.rotate', 'MOUSEROTATE', 'ANY')
-kmi = km.items.new('view3d.move', 'TRACKPADPAN', 'ANY')
-kmi = km.items.new('view3d.zoom', 'TRACKPADZOOM', 'ANY')
-kmi = km.items.new('view3d.zoom', 'NUMPAD_PLUS', 'PRESS')
+kmi = km.keymap_items.new('view3d.cursor3d', 'ACTIONMOUSE', 'PRESS')
+kmi = km.keymap_items.new('view3d.rotate', 'LEFTMOUSE', 'PRESS', alt=True)
+kmi = km.keymap_items.new('view3d.move', 'MIDDLEMOUSE', 'PRESS', alt=True)
+kmi = km.keymap_items.new('view3d.zoom', 'RIGHTMOUSE', 'PRESS', alt=True)
+kmi = km.keymap_items.new('view3d.view_selected', 'NUMPAD_PERIOD', 'PRESS')
+kmi = km.keymap_items.new('view3d.view_center_cursor', 'NUMPAD_PERIOD', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.fly', 'F', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.smoothview', 'TIMER1', 'ANY', any=True)
+kmi = km.keymap_items.new('view3d.rotate', 'TRACKPADPAN', 'ANY', alt=True)
+kmi = km.keymap_items.new('view3d.rotate', 'MOUSEROTATE', 'ANY')
+kmi = km.keymap_items.new('view3d.move', 'TRACKPADPAN', 'ANY')
+kmi = km.keymap_items.new('view3d.zoom', 'TRACKPADZOOM', 'ANY')
+kmi = km.keymap_items.new('view3d.zoom', 'NUMPAD_PLUS', 'PRESS')
kmi.properties.delta = 1
-kmi = km.items.new('view3d.zoom', 'NUMPAD_MINUS', 'PRESS')
+kmi = km.keymap_items.new('view3d.zoom', 'NUMPAD_MINUS', 'PRESS')
kmi.properties.delta = -1
-kmi = km.items.new('view3d.zoom', 'EQUAL', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.zoom', 'EQUAL', 'PRESS', ctrl=True)
kmi.properties.delta = 1
-kmi = km.items.new('view3d.zoom', 'MINUS', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.zoom', 'MINUS', 'PRESS', ctrl=True)
kmi.properties.delta = -1
-kmi = km.items.new('view3d.zoom', 'WHEELINMOUSE', 'PRESS')
+kmi = km.keymap_items.new('view3d.zoom', 'WHEELINMOUSE', 'PRESS')
kmi.properties.delta = 1
-kmi = km.items.new('view3d.zoom', 'WHEELOUTMOUSE', 'PRESS')
+kmi = km.keymap_items.new('view3d.zoom', 'WHEELOUTMOUSE', 'PRESS')
kmi.properties.delta = -1
-kmi = km.items.new('view3d.view_all', 'HOME', 'PRESS')
+kmi = km.keymap_items.new('view3d.view_all', 'HOME', 'PRESS')
kmi.properties.center = False
-kmi = km.items.new('view3d.view_all', 'C', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.view_all', 'C', 'PRESS', shift=True)
kmi.properties.center = True
-kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_0', 'PRESS')
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_0', 'PRESS')
kmi.properties.type = 'CAMERA'
-kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS')
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS')
kmi.properties.type = 'FRONT'
-kmi = km.items.new('view3d.view_orbit', 'NUMPAD_2', 'PRESS')
+kmi = km.keymap_items.new('view3d.view_orbit', 'NUMPAD_2', 'PRESS')
kmi.properties.type = 'ORBITDOWN'
-kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS')
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS')
kmi.properties.type = 'RIGHT'
-kmi = km.items.new('view3d.view_orbit', 'NUMPAD_4', 'PRESS')
+kmi = km.keymap_items.new('view3d.view_orbit', 'NUMPAD_4', 'PRESS')
kmi.properties.type = 'ORBITLEFT'
-kmi = km.items.new('view3d.view_persportho', 'NUMPAD_5', 'PRESS')
-kmi = km.items.new('view3d.view_orbit', 'NUMPAD_6', 'PRESS')
+kmi = km.keymap_items.new('view3d.view_persportho', 'NUMPAD_5', 'PRESS')
+kmi = km.keymap_items.new('view3d.view_orbit', 'NUMPAD_6', 'PRESS')
kmi.properties.type = 'ORBITRIGHT'
-kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_7', 'PRESS')
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_7', 'PRESS')
kmi.properties.type = 'TOP'
-kmi = km.items.new('view3d.view_orbit', 'NUMPAD_8', 'PRESS')
+kmi = km.keymap_items.new('view3d.view_orbit', 'NUMPAD_8', 'PRESS')
kmi.properties.type = 'ORBITUP'
-kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', ctrl=True)
kmi.properties.type = 'BACK'
-kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS', ctrl=True)
kmi.properties.type = 'LEFT'
-kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_7', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_7', 'PRESS', ctrl=True)
kmi.properties.type = 'BOTTOM'
-kmi = km.items.new('view3d.view_pan', 'NUMPAD_2', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.view_pan', 'NUMPAD_2', 'PRESS', ctrl=True)
kmi.properties.type = 'PANDOWN'
-kmi = km.items.new('view3d.view_pan', 'NUMPAD_4', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.view_pan', 'NUMPAD_4', 'PRESS', ctrl=True)
kmi.properties.type = 'PANLEFT'
-kmi = km.items.new('view3d.view_pan', 'NUMPAD_6', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.view_pan', 'NUMPAD_6', 'PRESS', ctrl=True)
kmi.properties.type = 'PANRIGHT'
-kmi = km.items.new('view3d.view_pan', 'NUMPAD_8', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.view_pan', 'NUMPAD_8', 'PRESS', ctrl=True)
kmi.properties.type = 'PANUP'
-kmi = km.items.new('view3d.view_pan', 'WHEELUPMOUSE', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.view_pan', 'WHEELUPMOUSE', 'PRESS', ctrl=True)
kmi.properties.type = 'PANRIGHT'
-kmi = km.items.new('view3d.view_pan', 'WHEELDOWNMOUSE', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.view_pan', 'WHEELDOWNMOUSE', 'PRESS', ctrl=True)
kmi.properties.type = 'PANLEFT'
-kmi = km.items.new('view3d.view_pan', 'WHEELUPMOUSE', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.view_pan', 'WHEELUPMOUSE', 'PRESS', shift=True)
kmi.properties.type = 'PANUP'
-kmi = km.items.new('view3d.view_pan', 'WHEELDOWNMOUSE', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.view_pan', 'WHEELDOWNMOUSE', 'PRESS', shift=True)
kmi.properties.type = 'PANDOWN'
-kmi = km.items.new('view3d.view_orbit', 'WHEELUPMOUSE', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('view3d.view_orbit', 'WHEELUPMOUSE', 'PRESS', ctrl=True, alt=True)
kmi.properties.type = 'ORBITLEFT'
-kmi = km.items.new('view3d.view_orbit', 'WHEELDOWNMOUSE', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('view3d.view_orbit', 'WHEELDOWNMOUSE', 'PRESS', ctrl=True, alt=True)
kmi.properties.type = 'ORBITRIGHT'
-kmi = km.items.new('view3d.view_orbit', 'WHEELUPMOUSE', 'PRESS', shift=True, alt=True)
+kmi = km.keymap_items.new('view3d.view_orbit', 'WHEELUPMOUSE', 'PRESS', shift=True, alt=True)
kmi.properties.type = 'ORBITUP'
-kmi = km.items.new('view3d.view_orbit', 'WHEELDOWNMOUSE', 'PRESS', shift=True, alt=True)
+kmi = km.keymap_items.new('view3d.view_orbit', 'WHEELDOWNMOUSE', 'PRESS', shift=True, alt=True)
kmi.properties.type = 'ORBITDOWN'
-kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', shift=True)
kmi.properties.align_active = True
kmi.properties.type = 'FRONT'
-kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS', shift=True)
kmi.properties.align_active = True
kmi.properties.type = 'RIGHT'
-kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_7', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_7', 'PRESS', shift=True)
kmi.properties.align_active = True
kmi.properties.type = 'TOP'
-kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_1', 'PRESS', shift=True, ctrl=True)
kmi.properties.align_active = True
kmi.properties.type = 'BACK'
-kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_3', 'PRESS', shift=True, ctrl=True)
kmi.properties.align_active = True
kmi.properties.type = 'LEFT'
-kmi = km.items.new('view3d.viewnumpad', 'NUMPAD_7', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('view3d.viewnumpad', 'NUMPAD_7', 'PRESS', shift=True, ctrl=True)
kmi.properties.align_active = True
kmi.properties.type = 'BOTTOM'
-kmi = km.items.new('view3d.localview', 'NUMPAD_SLASH', 'PRESS')
-kmi = km.items.new('view3d.layers', 'ACCENT_GRAVE', 'PRESS')
+kmi = km.keymap_items.new('view3d.localview', 'NUMPAD_SLASH', 'PRESS')
+kmi = km.keymap_items.new('view3d.layers', 'ACCENT_GRAVE', 'PRESS')
kmi.properties.nr = 0
-kmi = km.items.new('view3d.layers', 'ONE', 'PRESS', any=True)
+kmi = km.keymap_items.new('view3d.layers', 'ONE', 'PRESS', any=True)
kmi.properties.nr = 1
-kmi = km.items.new('view3d.layers', 'TWO', 'PRESS', any=True)
+kmi = km.keymap_items.new('view3d.layers', 'TWO', 'PRESS', any=True)
kmi.properties.nr = 2
-kmi = km.items.new('view3d.layers', 'THREE', 'PRESS', any=True)
+kmi = km.keymap_items.new('view3d.layers', 'THREE', 'PRESS', any=True)
kmi.properties.nr = 3
-kmi = km.items.new('view3d.layers', 'FOUR', 'PRESS', any=True)
+kmi = km.keymap_items.new('view3d.layers', 'FOUR', 'PRESS', any=True)
kmi.properties.nr = 4
-kmi = km.items.new('view3d.layers', 'FIVE', 'PRESS', any=True)
+kmi = km.keymap_items.new('view3d.layers', 'FIVE', 'PRESS', any=True)
kmi.properties.nr = 5
-kmi = km.items.new('view3d.layers', 'SIX', 'PRESS', any=True)
+kmi = km.keymap_items.new('view3d.layers', 'SIX', 'PRESS', any=True)
kmi.properties.nr = 6
-kmi = km.items.new('view3d.layers', 'SEVEN', 'PRESS', any=True)
+kmi = km.keymap_items.new('view3d.layers', 'SEVEN', 'PRESS', any=True)
kmi.properties.nr = 7
-kmi = km.items.new('view3d.layers', 'EIGHT', 'PRESS', any=True)
+kmi = km.keymap_items.new('view3d.layers', 'EIGHT', 'PRESS', any=True)
kmi.properties.nr = 8
-kmi = km.items.new('view3d.layers', 'NINE', 'PRESS', any=True)
+kmi = km.keymap_items.new('view3d.layers', 'NINE', 'PRESS', any=True)
kmi.properties.nr = 9
-kmi = km.items.new('view3d.layers', 'ZERO', 'PRESS', any=True)
+kmi = km.keymap_items.new('view3d.layers', 'ZERO', 'PRESS', any=True)
kmi.properties.nr = 10
-kmi = km.items.new('wm.context_toggle_enum', 'Z', 'PRESS')
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'Z', 'PRESS')
kmi.properties.data_path = 'space_data.viewport_shade'
kmi.properties.value_1 = 'SOLID'
kmi.properties.value_2 = 'WIREFRAME'
-kmi = km.items.new('wm.context_toggle_enum', 'Z', 'PRESS', alt=True)
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'Z', 'PRESS', alt=True)
kmi.properties.data_path = 'space_data.viewport_shade'
kmi.properties.value_1 = 'TEXTURED'
kmi.properties.value_2 = 'SOLID'
-kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS')
-kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS')
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True)
kmi.properties.extend = True
-kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', ctrl=True)
kmi.properties.center = True
-kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', alt=True)
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', alt=True)
kmi.properties.enumerate = True
-kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True)
kmi.properties.center = True
kmi.properties.extend = True
-kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True)
kmi.properties.center = True
kmi.properties.enumerate = True
-kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, alt=True)
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, alt=True)
kmi.properties.enumerate = True
kmi.properties.extend = True
-kmi = km.items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True)
+kmi = km.keymap_items.new('view3d.select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True)
kmi.properties.center = True
kmi.properties.enumerate = True
kmi.properties.extend = True
-kmi = km.items.new('view3d.select_border', 'EVT_TWEAK_S', 'ANY')
+kmi = km.keymap_items.new('view3d.select_border', 'EVT_TWEAK_S', 'ANY')
kmi.properties.extend = False
-kmi = km.items.new('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', ctrl=True)
-kmi = km.items.new('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', shift=True, ctrl=True)
+kmi = km.keymap_items.new('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', ctrl=True)
+kmi = km.keymap_items.new('view3d.select_lasso', 'EVT_TWEAK_A', 'ANY', shift=True, ctrl=True)
kmi.properties.deselect = True
-kmi = km.items.new('view3d.select_circle', 'C', 'PRESS')
-kmi = km.items.new('view3d.clip_border', 'B', 'PRESS', alt=True)
-kmi = km.items.new('view3d.zoom_border', 'B', 'PRESS', shift=True)
-kmi = km.items.new('view3d.render_border', 'B', 'PRESS', shift=True)
-kmi = km.items.new('view3d.camera_to_view', 'NUMPAD_0', 'PRESS', ctrl=True, alt=True)
-kmi = km.items.new('view3d.object_as_camera', 'NUMPAD_0', 'PRESS', ctrl=True)
-kmi = km.items.new('wm.call_menu', 'S', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.select_circle', 'C', 'PRESS')
+kmi = km.keymap_items.new('view3d.clip_border', 'B', 'PRESS', alt=True)
+kmi = km.keymap_items.new('view3d.zoom_border', 'B', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.render_border', 'B', 'PRESS', shift=True)
+kmi = km.keymap_items.new('view3d.camera_to_view', 'NUMPAD_0', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('view3d.object_as_camera', 'NUMPAD_0', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'S', 'PRESS', shift=True)
kmi.properties.name = 'VIEW3D_MT_snap'
-kmi = km.items.new('wm.context_set_enum', 'COMMA', 'PRESS')
+kmi = km.keymap_items.new('wm.context_set_enum', 'COMMA', 'PRESS')
kmi.properties.data_path = 'space_data.pivot_point'
kmi.properties.value = 'BOUNDING_BOX_CENTER'
-kmi = km.items.new('wm.context_set_enum', 'COMMA', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.context_set_enum', 'COMMA', 'PRESS', ctrl=True)
kmi.properties.data_path = 'space_data.pivot_point'
kmi.properties.value = 'MEDIAN_POINT'
-kmi = km.items.new('wm.context_toggle', 'COMMA', 'PRESS', alt=True)
+kmi = km.keymap_items.new('wm.context_toggle', 'COMMA', 'PRESS', alt=True)
kmi.properties.data_path = 'space_data.use_pivot_point'
-kmi = km.items.new('wm.context_toggle', 'Q', 'PRESS')
+kmi = km.keymap_items.new('wm.context_toggle', 'Q', 'PRESS')
kmi.properties.data_path = 'space_data.show_manipulator'
-kmi = km.items.new('wm.context_set_enum', 'PERIOD', 'PRESS')
+kmi = km.keymap_items.new('wm.context_set_enum', 'PERIOD', 'PRESS')
kmi.properties.data_path = 'space_data.pivot_point'
kmi.properties.value = 'CURSOR'
-kmi = km.items.new('wm.context_set_enum', 'PERIOD', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.context_set_enum', 'PERIOD', 'PRESS', ctrl=True)
kmi.properties.data_path = 'space_data.pivot_point'
kmi.properties.value = 'INDIVIDUAL_ORIGINS'
-kmi = km.items.new('wm.context_set_enum', 'PERIOD', 'PRESS', alt=True)
+kmi = km.keymap_items.new('wm.context_set_enum', 'PERIOD', 'PRESS', alt=True)
kmi.properties.data_path = 'space_data.pivot_point'
kmi.properties.value = 'ACTIVE_ELEMENT'
-kmi = km.items.new('transform.translate', 'G', 'PRESS', shift=True)
-kmi = km.items.new('transform.translate', 'EVT_TWEAK_S', 'ANY')
-kmi = km.items.new('transform.rotate', 'R', 'PRESS', shift=True)
-kmi = km.items.new('transform.resize', 'S', 'PRESS', shift=True)
-kmi = km.items.new('transform.warp', 'W', 'PRESS', shift=True)
-kmi = km.items.new('transform.tosphere', 'S', 'PRESS', shift=True, alt=True)
-kmi = km.items.new('transform.shear', 'S', 'PRESS', shift=True, ctrl=True, alt=True)
-kmi = km.items.new('transform.select_orientation', 'SPACE', 'PRESS', alt=True)
-kmi = km.items.new('transform.create_orientation', 'SPACE', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('transform.translate', 'G', 'PRESS', shift=True)
+kmi = km.keymap_items.new('transform.translate', 'EVT_TWEAK_S', 'ANY')
+kmi = km.keymap_items.new('transform.rotate', 'R', 'PRESS', shift=True)
+kmi = km.keymap_items.new('transform.resize', 'S', 'PRESS', shift=True)
+kmi = km.keymap_items.new('transform.warp', 'W', 'PRESS', shift=True)
+kmi = km.keymap_items.new('transform.tosphere', 'S', 'PRESS', shift=True, alt=True)
+kmi = km.keymap_items.new('transform.shear', 'S', 'PRESS', shift=True, ctrl=True, alt=True)
+kmi = km.keymap_items.new('transform.select_orientation', 'SPACE', 'PRESS', alt=True)
+kmi = km.keymap_items.new('transform.create_orientation', 'SPACE', 'PRESS', ctrl=True, alt=True)
kmi.properties.use = True
-kmi = km.items.new('transform.mirror', 'M', 'PRESS', ctrl=True)
-kmi = km.items.new('wm.context_toggle', 'TAB', 'PRESS', shift=True)
+kmi = km.keymap_items.new('transform.mirror', 'M', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.context_toggle', 'TAB', 'PRESS', shift=True)
kmi.properties.data_path = 'tool_settings.use_snap'
-kmi = km.items.new('transform.snap_type', 'TAB', 'PRESS', shift=True, ctrl=True)
-kmi = km.items.new('view3d.enable_manipulator', 'W', 'PRESS')
+kmi = km.keymap_items.new('transform.snap_type', 'TAB', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('view3d.enable_manipulator', 'W', 'PRESS')
kmi.properties.translate = True
-kmi = km.items.new('view3d.enable_manipulator', 'E', 'PRESS')
+kmi = km.keymap_items.new('view3d.enable_manipulator', 'E', 'PRESS')
kmi.properties.rotate = True
-kmi = km.items.new('view3d.enable_manipulator', 'R', 'PRESS')
+kmi = km.keymap_items.new('view3d.enable_manipulator', 'R', 'PRESS')
kmi.properties.scale = True
-kmi = km.items.new('view3d.select_border', 'EVT_TWEAK_S', 'ANY', shift=True)
+kmi = km.keymap_items.new('view3d.select_border', 'EVT_TWEAK_S', 'ANY', shift=True)
kmi.properties.extend = True
# Map Object Mode
km = kc.keymaps.new('Object Mode', space_type='EMPTY', region_type='WINDOW', modal=False)
-kmi = km.items.new('wm.context_cycle_enum', 'O', 'PRESS', shift=True)
+kmi = km.keymap_items.new('wm.context_cycle_enum', 'O', 'PRESS', shift=True)
kmi.properties.data_path = 'tool_settings.proportional_edit_falloff'
-kmi = km.items.new('wm.context_toggle_enum', 'O', 'PRESS')
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'O', 'PRESS')
kmi.properties.data_path = 'tool_settings.proportional_edit'
kmi.properties.value_1 = 'DISABLED'
kmi.properties.value_2 = 'ENABLED'
-kmi = km.items.new('view3d.game_start', 'P', 'PRESS')
-kmi = km.items.new('object.select_all', 'A', 'PRESS')
-kmi = km.items.new('object.select_inverse', 'I', 'PRESS', ctrl=True)
-kmi = km.items.new('object.select_linked', 'L', 'PRESS', shift=True)
-kmi = km.items.new('object.select_grouped', 'G', 'PRESS', shift=True)
-kmi = km.items.new('object.select_mirror', 'M', 'PRESS', shift=True, ctrl=True)
-kmi = km.items.new('object.select_hierarchy', 'LEFT_BRACKET', 'PRESS')
+kmi = km.keymap_items.new('view3d.game_start', 'P', 'PRESS')
+kmi = km.keymap_items.new('object.select_all', 'A', 'PRESS')
+kmi = km.keymap_items.new('object.select_inverse', 'I', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.select_linked', 'L', 'PRESS', shift=True)
+kmi = km.keymap_items.new('object.select_grouped', 'G', 'PRESS', shift=True)
+kmi = km.keymap_items.new('object.select_mirror', 'M', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('object.select_hierarchy', 'LEFT_BRACKET', 'PRESS')
kmi.properties.direction = 'PARENT'
-kmi = km.items.new('object.select_hierarchy', 'LEFT_BRACKET', 'PRESS', shift=True)
+kmi = km.keymap_items.new('object.select_hierarchy', 'LEFT_BRACKET', 'PRESS', shift=True)
kmi.properties.direction = 'PARENT'
kmi.properties.extend = True
-kmi = km.items.new('object.select_hierarchy', 'RIGHT_BRACKET', 'PRESS')
+kmi = km.keymap_items.new('object.select_hierarchy', 'RIGHT_BRACKET', 'PRESS')
kmi.properties.direction = 'CHILD'
-kmi = km.items.new('object.select_hierarchy', 'RIGHT_BRACKET', 'PRESS', shift=True)
+kmi = km.keymap_items.new('object.select_hierarchy', 'RIGHT_BRACKET', 'PRESS', shift=True)
kmi.properties.direction = 'CHILD'
kmi.properties.extend = True
-kmi = km.items.new('object.parent_set', 'P', 'PRESS', ctrl=True)
-kmi = km.items.new('object.parent_no_inverse_set', 'P', 'PRESS', shift=True, ctrl=True)
-kmi = km.items.new('object.parent_clear', 'P', 'PRESS', alt=True)
-kmi = km.items.new('object.track_set', 'T', 'PRESS', ctrl=True)
-kmi = km.items.new('object.track_clear', 'T', 'PRESS', alt=True)
-kmi = km.items.new('object.constraint_add_with_targets', 'C', 'PRESS', shift=True, ctrl=True)
-kmi = km.items.new('object.constraints_clear', 'C', 'PRESS', ctrl=True, alt=True)
-kmi = km.items.new('object.location_clear', 'G', 'PRESS', alt=True)
-kmi = km.items.new('object.rotation_clear', 'R', 'PRESS', alt=True)
-kmi = km.items.new('object.scale_clear', 'S', 'PRESS', alt=True)
-kmi = km.items.new('object.origin_clear', 'O', 'PRESS', alt=True)
-kmi = km.items.new('object.hide_view_clear', 'H', 'PRESS', alt=True)
-kmi = km.items.new('object.hide_view_set', 'H', 'PRESS')
-kmi = km.items.new('object.hide_view_set', 'H', 'PRESS', shift=True)
+kmi = km.keymap_items.new('object.parent_set', 'P', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.parent_no_inverse_set', 'P', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('object.parent_clear', 'P', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.track_set', 'T', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.track_clear', 'T', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.constraint_add_with_targets', 'C', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('object.constraints_clear', 'C', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('object.location_clear', 'G', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.rotation_clear', 'R', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.scale_clear', 'S', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.origin_clear', 'O', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.hide_view_clear', 'H', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS')
+kmi = km.keymap_items.new('object.hide_view_set', 'H', 'PRESS', shift=True)
kmi.properties.unselected = True
-kmi = km.items.new('object.move_to_layer', 'M', 'PRESS')
-kmi = km.items.new('object.delete', 'X', 'PRESS')
-kmi = km.items.new('object.delete', 'DEL', 'PRESS')
-kmi = km.items.new('wm.call_menu', 'A', 'PRESS', shift=True)
+kmi = km.keymap_items.new('object.move_to_layer', 'M', 'PRESS')
+kmi = km.keymap_items.new('object.delete', 'X', 'PRESS')
+kmi = km.keymap_items.new('object.delete', 'DEL', 'PRESS')
+kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True)
kmi.properties.name = 'INFO_MT_add'
-kmi = km.items.new('object.duplicates_make_real', 'A', 'PRESS', shift=True, ctrl=True)
-kmi = km.items.new('wm.call_menu', 'A', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.duplicates_make_real', 'A', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_object_apply'
-kmi = km.items.new('wm.call_menu', 'U', 'PRESS')
+kmi = km.keymap_items.new('wm.call_menu', 'U', 'PRESS')
kmi.properties.name = 'VIEW3D_MT_make_single_user'
-kmi = km.items.new('wm.call_menu', 'L', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'L', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_make_links'
-kmi = km.items.new('object.duplicate_move', 'D', 'PRESS', shift=True)
-kmi = km.items.new('object.duplicate_move_linked', 'D', 'PRESS', alt=True)
-kmi = km.items.new('object.join', 'J', 'PRESS', ctrl=True)
-kmi = km.items.new('object.convert', 'C', 'PRESS', alt=True)
-kmi = km.items.new('object.proxy_make', 'P', 'PRESS', ctrl=True, alt=True)
-kmi = km.items.new('object.make_local', 'L', 'PRESS')
-kmi = km.items.new('anim.keyframe_insert_menu', 'I', 'PRESS')
-kmi = km.items.new('anim.keyframe_delete_v3d', 'I', 'PRESS', alt=True)
-kmi = km.items.new('anim.keying_set_active_set', 'I', 'PRESS', shift=True, ctrl=True, alt=True)
-kmi = km.items.new('group.create', 'G', 'PRESS', ctrl=True)
-kmi = km.items.new('group.objects_remove', 'G', 'PRESS', ctrl=True, alt=True)
-kmi = km.items.new('group.objects_add_active', 'G', 'PRESS', shift=True, ctrl=True)
-kmi = km.items.new('group.objects_remove_active', 'G', 'PRESS', shift=True, alt=True)
-kmi = km.items.new('wm.call_menu', 'W', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.duplicate_move', 'D', 'PRESS', shift=True)
+kmi = km.keymap_items.new('object.duplicate_move_linked', 'D', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.join', 'J', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.convert', 'C', 'PRESS', alt=True)
+kmi = km.keymap_items.new('object.proxy_make', 'P', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('object.make_local', 'L', 'PRESS')
+kmi = km.keymap_items.new('anim.keyframe_insert_menu', 'I', 'PRESS')
+kmi = km.keymap_items.new('anim.keyframe_delete_v3d', 'I', 'PRESS', alt=True)
+kmi = km.keymap_items.new('anim.keying_set_active_set', 'I', 'PRESS', shift=True, ctrl=True, alt=True)
+kmi = km.keymap_items.new('group.create', 'G', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('group.objects_remove', 'G', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('group.objects_add_active', 'G', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('group.objects_remove_active', 'G', 'PRESS', shift=True, alt=True)
+kmi = km.keymap_items.new('wm.call_menu', 'W', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_object_specials'
-kmi = km.items.new('object.subdivision_set', 'ZERO', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.subdivision_set', 'ZERO', 'PRESS', ctrl=True)
kmi.properties.level = 0
-kmi = km.items.new('object.subdivision_set', 'ONE', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.subdivision_set', 'ONE', 'PRESS', ctrl=True)
kmi.properties.level = 1
-kmi = km.items.new('object.subdivision_set', 'TWO', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.subdivision_set', 'TWO', 'PRESS', ctrl=True)
kmi.properties.level = 2
-kmi = km.items.new('object.subdivision_set', 'THREE', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.subdivision_set', 'THREE', 'PRESS', ctrl=True)
kmi.properties.level = 3
-kmi = km.items.new('object.subdivision_set', 'FOUR', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.subdivision_set', 'FOUR', 'PRESS', ctrl=True)
kmi.properties.level = 4
-kmi = km.items.new('object.subdivision_set', 'FIVE', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.subdivision_set', 'FIVE', 'PRESS', ctrl=True)
kmi.properties.level = 5
-kmi = km.items.new('object.select_all', 'SELECTMOUSE', 'CLICK')
+kmi = km.keymap_items.new('object.select_all', 'SELECTMOUSE', 'CLICK')
kmi.properties.action = 'DESELECT'
# Map Mesh
km = kc.keymaps.new('Mesh', space_type='EMPTY', region_type='WINDOW', modal=False)
-kmi = km.items.new('mesh.loopcut_slide', 'R', 'PRESS', ctrl=True)
-kmi = km.items.new('mesh.loop_select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True)
-kmi = km.items.new('mesh.loop_select', 'SELECTMOUSE', 'PRESS', shift=True, alt=True)
+kmi = km.keymap_items.new('mesh.loopcut_slide', 'R', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.loop_select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('mesh.loop_select', 'SELECTMOUSE', 'PRESS', shift=True, alt=True)
kmi.properties.extend = True
-kmi = km.items.new('mesh.edgering_select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True)
-kmi = km.items.new('mesh.edgering_select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True)
+kmi = km.keymap_items.new('mesh.edgering_select', 'SELECTMOUSE', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('mesh.edgering_select', 'SELECTMOUSE', 'PRESS', shift=True, ctrl=True, alt=True)
kmi.properties.extend = True
-kmi = km.items.new('mesh.select_shortest_path', 'SELECTMOUSE', 'PRESS', ctrl=True)
-kmi = km.items.new('mesh.select_all', 'A', 'PRESS')
-kmi = km.items.new('mesh.select_more', 'NUMPAD_PLUS', 'PRESS', ctrl=True)
-kmi = km.items.new('mesh.select_less', 'NUMPAD_MINUS', 'PRESS', ctrl=True)
-kmi = km.items.new('mesh.select_inverse', 'I', 'PRESS', ctrl=True)
-kmi = km.items.new('mesh.select_non_manifold', 'M', 'PRESS', shift=True, ctrl=True, alt=True)
-kmi = km.items.new('mesh.select_linked', 'L', 'PRESS', ctrl=True)
-kmi = km.items.new('mesh.select_linked_pick', 'L', 'PRESS')
-kmi = km.items.new('mesh.select_linked_pick', 'L', 'PRESS', shift=True)
+kmi = km.keymap_items.new('mesh.select_shortest_path', 'SELECTMOUSE', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.select_all', 'A', 'PRESS')
+kmi = km.keymap_items.new('mesh.select_more', 'NUMPAD_PLUS', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.select_less', 'NUMPAD_MINUS', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.select_inverse', 'I', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.select_non_manifold', 'M', 'PRESS', shift=True, ctrl=True, alt=True)
+kmi = km.keymap_items.new('mesh.select_linked', 'L', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.select_linked_pick', 'L', 'PRESS')
+kmi = km.keymap_items.new('mesh.select_linked_pick', 'L', 'PRESS', shift=True)
kmi.properties.deselect = True
-kmi = km.items.new('mesh.faces_select_linked_flat', 'F', 'PRESS', shift=True, ctrl=True, alt=True)
+kmi = km.keymap_items.new('mesh.faces_select_linked_flat', 'F', 'PRESS', shift=True, ctrl=True, alt=True)
kmi.properties.sharpness = 135.0
-kmi = km.items.new('mesh.select_similar', 'G', 'PRESS', shift=True)
-kmi = km.items.new('wm.call_menu', 'TAB', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.select_similar', 'G', 'PRESS', shift=True)
+kmi = km.keymap_items.new('wm.call_menu', 'TAB', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_select_mode'
-kmi = km.items.new('mesh.hide', 'H', 'PRESS')
-kmi = km.items.new('mesh.hide', 'H', 'PRESS', shift=True)
+kmi = km.keymap_items.new('mesh.hide', 'H', 'PRESS')
+kmi = km.keymap_items.new('mesh.hide', 'H', 'PRESS', shift=True)
kmi.properties.unselected = True
-kmi = km.items.new('mesh.reveal', 'H', 'PRESS', alt=True)
-kmi = km.items.new('mesh.normals_make_consistent', 'N', 'PRESS', ctrl=True)
-kmi = km.items.new('mesh.normals_make_consistent', 'N', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('mesh.reveal', 'H', 'PRESS', alt=True)
+kmi = km.keymap_items.new('mesh.normals_make_consistent', 'N', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.normals_make_consistent', 'N', 'PRESS', shift=True, ctrl=True)
kmi.properties.inside = True
-kmi = km.items.new('view3d.edit_mesh_extrude_move_normal', 'E', 'PRESS', ctrl=True)
-kmi = km.items.new('view3d.edit_mesh_extrude_individual_move', 'E', 'PRESS', shift=True)
-kmi = km.items.new('wm.call_menu', 'E', 'PRESS', alt=True)
+kmi = km.keymap_items.new('view3d.edit_mesh_extrude_move_normal', 'E', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('view3d.edit_mesh_extrude_individual_move', 'E', 'PRESS', shift=True)
+kmi = km.keymap_items.new('wm.call_menu', 'E', 'PRESS', alt=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_extrude'
-kmi = km.items.new('mesh.spin', 'R', 'PRESS', alt=True)
-kmi = km.items.new('mesh.fill', 'F', 'PRESS', alt=True)
-kmi = km.items.new('mesh.beautify_fill', 'F', 'PRESS', shift=True, alt=True)
-kmi = km.items.new('mesh.quads_convert_to_tris', 'T', 'PRESS', ctrl=True)
-kmi = km.items.new('mesh.tris_convert_to_quads', 'J', 'PRESS', alt=True)
-kmi = km.items.new('mesh.edge_flip', 'F', 'PRESS', shift=True, ctrl=True)
-kmi = km.items.new('mesh.rip_move', 'V', 'PRESS')
-kmi = km.items.new('mesh.merge', 'M', 'PRESS', alt=True)
-kmi = km.items.new('transform.shrink_fatten', 'S', 'PRESS', ctrl=True, alt=True)
-kmi = km.items.new('mesh.edge_face_add', 'F', 'PRESS')
-kmi = km.items.new('mesh.duplicate_move', 'D', 'PRESS', shift=True)
-kmi = km.items.new('wm.call_menu', 'A', 'PRESS', shift=True)
+kmi = km.keymap_items.new('mesh.spin', 'R', 'PRESS', alt=True)
+kmi = km.keymap_items.new('mesh.fill', 'F', 'PRESS', alt=True)
+kmi = km.keymap_items.new('mesh.beautify_fill', 'F', 'PRESS', shift=True, alt=True)
+kmi = km.keymap_items.new('mesh.quads_convert_to_tris', 'T', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('mesh.tris_convert_to_quads', 'J', 'PRESS', alt=True)
+kmi = km.keymap_items.new('mesh.edge_flip', 'F', 'PRESS', shift=True, ctrl=True)
+kmi = km.keymap_items.new('mesh.rip_move', 'V', 'PRESS')
+kmi = km.keymap_items.new('mesh.merge', 'M', 'PRESS', alt=True)
+kmi = km.keymap_items.new('transform.shrink_fatten', 'S', 'PRESS', ctrl=True, alt=True)
+kmi = km.keymap_items.new('mesh.edge_face_add', 'F', 'PRESS')
+kmi = km.keymap_items.new('mesh.duplicate_move', 'D', 'PRESS', shift=True)
+kmi = km.keymap_items.new('wm.call_menu', 'A', 'PRESS', shift=True)
kmi.properties.name = 'INFO_MT_mesh_add'
-kmi = km.items.new('mesh.separate', 'P', 'PRESS')
-kmi = km.items.new('mesh.split', 'Y', 'PRESS')
-kmi = km.items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', ctrl=True)
-kmi = km.items.new('mesh.delete', 'X', 'PRESS')
-kmi = km.items.new('mesh.delete', 'DEL', 'PRESS')
-kmi = km.items.new('mesh.knife_cut', 'LEFTMOUSE', 'PRESS', key_modifier='K')
-kmi = km.items.new('mesh.knife_cut', 'LEFTMOUSE', 'PRESS', shift=True, key_modifier='K')
+kmi = km.keymap_items.new('mesh.separate', 'P', 'PRESS')
+kmi = km.keymap_items.new('mesh.split', 'Y', 'PRESS')
+kmi = km.keymap_items.new('mesh.dupli_extrude_cursor', 'ACTIONMOUSE', 'CLICK', ctrl=True)
+kmi = km.keymap_items.new('mesh.delete', 'X', 'PRESS')
+kmi = km.keymap_items.new('mesh.delete', 'DEL', 'PRESS')
+kmi = km.keymap_items.new('mesh.knife_cut', 'LEFTMOUSE', 'PRESS', key_modifier='K')
+kmi = km.keymap_items.new('mesh.knife_cut', 'LEFTMOUSE', 'PRESS', shift=True, key_modifier='K')
kmi.properties.type = 'MIDPOINTS'
-kmi = km.items.new('object.vertex_parent_set', 'P', 'PRESS', ctrl=True)
-kmi = km.items.new('wm.call_menu', 'W', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('object.vertex_parent_set', 'P', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'W', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_specials'
-kmi = km.items.new('wm.call_menu', 'F', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'F', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_faces'
-kmi = km.items.new('wm.call_menu', 'E', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'E', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_edges'
-kmi = km.items.new('wm.call_menu', 'V', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'V', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_edit_mesh_vertices'
-kmi = km.items.new('wm.call_menu', 'H', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'H', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_hook'
-kmi = km.items.new('wm.call_menu', 'U', 'PRESS')
+kmi = km.keymap_items.new('wm.call_menu', 'U', 'PRESS')
kmi.properties.name = 'VIEW3D_MT_uv_map'
-kmi = km.items.new('wm.call_menu', 'G', 'PRESS', ctrl=True)
+kmi = km.keymap_items.new('wm.call_menu', 'G', 'PRESS', ctrl=True)
kmi.properties.name = 'VIEW3D_MT_vertex_group'
-kmi = km.items.new('wm.context_cycle_enum', 'O', 'PRESS', shift=True)
+kmi = km.keymap_items.new('wm.context_cycle_enum', 'O', 'PRESS', shift=True)
kmi.properties.data_path = 'tool_settings.proportional_edit_falloff'
-kmi = km.items.new('wm.context_toggle_enum', 'O', 'PRESS')
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'O', 'PRESS')
kmi.properties.data_path = 'tool_settings.proportional_edit'
kmi.properties.value_1 = 'DISABLED'
kmi.properties.value_2 = 'ENABLED'
-kmi = km.items.new('wm.context_toggle_enum', 'O', 'PRESS', alt=True)
+kmi = km.keymap_items.new('wm.context_toggle_enum', 'O', 'PRESS', alt=True)
kmi.properties.data_path = 'tool_settings.proportional_edit'
kmi.properties.value_1 = 'DISABLED'
kmi.properties.value_2 = 'CONNECTED'
-kmi = km.items.new('mesh.select_all', 'SELECTMOUSE', 'CLICK')
+kmi = km.keymap_items.new('mesh.select_all', 'SELECTMOUSE', 'CLICK')
kmi.properties.action = 'DESELECT'
wm.keyconfigs.active = kc
-
-bpy.context.user_preferences.edit.use_drag_immediately = True
-bpy.context.user_preferences.edit.use_insertkey_xyz_to_rgb = False
-bpy.context.user_preferences.inputs.select_mouse = 'LEFT'
-bpy.context.user_preferences.inputs.view_zoom_method = 'DOLLY'
-bpy.context.user_preferences.inputs.view_zoom_axis = 'HORIZONTAL'
-bpy.context.user_preferences.inputs.view_rotate_method = 'TURNTABLE'
-bpy.context.user_preferences.inputs.invert_mouse_wheel_zoom = True
diff --git a/release/scripts/startup/bl_operators/__init__.py b/release/scripts/startup/bl_operators/__init__.py
new file mode 100644
index 00000000000..d5f7a63366a
--- /dev/null
+++ b/release/scripts/startup/bl_operators/__init__.py
@@ -0,0 +1,58 @@
+# ##### 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>
+
+if "bpy" in locals():
+ from imp import reload as _reload
+ for val in _modules_loaded.values():
+ _reload(val)
+_modules = (
+ "add_mesh_torus",
+ "animsys_update",
+ "image",
+ "mesh",
+ "nla",
+ "object_align",
+ "object",
+ "object_randomize_transform",
+ "object_quick_effects",
+ "presets",
+ "screen_play_rendered_anim",
+ "sequencer",
+ "uvcalc_follow_active",
+ "uvcalc_lightmap",
+ "uvcalc_smart_project",
+ "vertexpaint_dirt",
+ "wm",
+)
+__import__(name=__name__, fromlist=_modules)
+_namespace = globals()
+_modules_loaded = {name: _namespace[name] for name in _modules}
+del _namespace
+
+
+import bpy
+
+
+def register():
+ bpy.utils.register_module(__name__)
+
+
+def unregister():
+ bpy.utils.unregister_module(__name__)
diff --git a/release/scripts/op/add_mesh_torus.py b/release/scripts/startup/bl_operators/add_mesh_torus.py
index db4f90f05d1..460330a56a1 100644
--- a/release/scripts/op/add_mesh_torus.py
+++ b/release/scripts/startup/bl_operators/add_mesh_torus.py
@@ -19,10 +19,11 @@
# <pep8 compliant>
import bpy
import mathutils
-from math import cos, sin, pi
def add_torus(major_rad, minor_rad, major_seg, minor_seg):
+ from math import cos, sin, pi
+
Vector = mathutils.Vector
Quaternion = mathutils.Quaternion
@@ -71,7 +72,7 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
return verts, faces
-from bpy.props import *
+from bpy.props import FloatProperty, IntProperty, BoolProperty, FloatVectorProperty
class AddTorus(bpy.types.Operator):
@@ -135,20 +136,3 @@ class AddTorus(bpy.types.Operator):
add_object_utils.object_data_add(context, mesh, operator=self)
return {'FINISHED'}
-
-
-def menu_func(self, context):
- self.layout.operator(AddTorus.bl_idname, text="Torus", icon='MESH_TORUS')
-
-
-def register():
- bpy.utils.register_class(AddTorus)
- bpy.types.INFO_MT_mesh_add.append(menu_func)
-
-
-def unregister():
- bpy.utils.unregister_class(AddTorus)
- bpy.types.INFO_MT_mesh_add.remove(menu_func)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/op/animsys_update.py b/release/scripts/startup/bl_operators/animsys_update.py
index 9262ff40a37..63d438a5066 100644
--- a/release/scripts/op/animsys_update.py
+++ b/release/scripts/startup/bl_operators/animsys_update.py
@@ -237,14 +237,16 @@ data_path_update = [
("ImageTexture", "mirror_y", "use_mirror_y"),
("ImageTexture", "normal_map", "use_normal_map"),
("MarbleTexture", "noise_size", "noise_scale"),
- ("MarbleTexture", "noisebasis2", "noisebasis_2"),
+ ("MarbleTexture", "noisebasis2", "noise_basis_2"),
+ ("MarbleTexture", "noisebasis_2", "noise_basis_2"),
("MusgraveTexture", "highest_dimension", "dimension_max"),
("MusgraveTexture", "noise_size", "noise_scale"),
("StucciTexture", "noise_size", "noise_scale"),
("VoronoiTexture", "coloring", "color_mode"),
("VoronoiTexture", "noise_size", "noise_scale"),
("WoodTexture", "noise_size", "noise_scale"),
- ("WoodTexture", "noisebasis2", "noisebasis_2"),
+ ("WoodTexture", "noisebasis2", "noise_basis_2"),
+ ("WoodTexture", "noisebasis_2", "noise_basis_2"),
("World", "blend_sky", "use_sky_blend"),
("World", "paper_sky", "use_sky_paper"),
("World", "real_sky", "use_sky_real"),
@@ -679,6 +681,7 @@ data_path_update = [
("SpeedControlSequence", "global_speed", "multiply_speed"),
("SpeedControlSequence", "use_curve_velocity", "use_as_speed"),
("SpeedControlSequence", "use_curve_compress_y", "scale_to_length"),
+ ("Key", "keys", "key_blocks"),
]
@@ -686,7 +689,7 @@ import bpy
class UpdateAnimData(bpy.types.Operator):
- '''Update data paths from 2.53 to edited data paths of drivers and fcurves'''
+ """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"
@@ -694,15 +697,3 @@ class UpdateAnimData(bpy.types.Operator):
import animsys_refactor
animsys_refactor.update_data_paths(data_path_update)
return {'FINISHED'}
-
-
-if __name__ == "__main__":
- bpy.ops.anim.update_data_paths()
-
-
-def register():
- bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
diff --git a/release/scripts/op/image.py b/release/scripts/startup/bl_operators/image.py
index e1d471f8254..462db3a2c5e 100644
--- a/release/scripts/op/image.py
+++ b/release/scripts/startup/bl_operators/image.py
@@ -31,25 +31,20 @@ class EditExternally(bpy.types.Operator):
filepath = StringProperty(name="File Path", description="Path to an image file", maxlen=1024, default="")
def _editor_guess(self, context):
- import platform
- try:
- system = platform.system()
- except UnicodeDecodeError:
- import sys
- system = sys.platform
+ import sys
image_editor = context.user_preferences.filepaths.image_editor
# use image editor in the preferences when available.
if not image_editor:
- if system in ('Windows', 'win32'):
+ if sys.platform[:3] == "win":
image_editor = ["start"] # not tested!
- elif system == 'Darwin':
+ elif sys.platform == "darwin":
image_editor = ["open"]
else:
image_editor = ["gimp"]
else:
- if system == 'Darwin':
+ if sys.platform == "darwin":
# blender file selector treats .app as a folder
# and will include a trailing backslash, so we strip it.
image_editor.rstrip('\\')
@@ -65,12 +60,18 @@ class EditExternally(bpy.types.Operator):
filepath = bpy.path.abspath(self.filepath)
if not os.path.exists(filepath):
- self.report('ERROR', "Image path '%s' not found." % filepath)
+ self.report({'ERROR'}, "Image path %r not found." % filepath)
return {'CANCELLED'}
cmd = self._editor_guess(context) + [filepath]
- subprocess.Popen(cmd)
+ try:
+ subprocess.Popen(cmd)
+ except:
+ import traceback
+ traceback.print_exc()
+ self.report({'ERROR'}, "Image editor not found, please specify in User Preferences > File")
+ return {'CANCELLED'}
return {'FINISHED'}
@@ -78,6 +79,8 @@ class EditExternally(bpy.types.Operator):
try:
filepath = context.space_data.image.filepath
except:
+ import traceback
+ traceback.print_exc()
self.report({'ERROR'}, "Image not found on disk")
return {'CANCELLED'}
@@ -109,7 +112,7 @@ class SaveDirty(bpy.types.Operator):
class ProjectEdit(bpy.types.Operator):
- """Edit a snapshot if the viewport in an external image editor"""
+ """Edit a snapshot of the viewport in an external image editor"""
bl_idname = "image.project_edit"
bl_label = "Project Edit"
bl_options = {'REGISTER'}
@@ -168,7 +171,10 @@ class ProjectEdit(bpy.types.Operator):
image_new.file_format = 'PNG'
image_new.save()
- bpy.ops.image.external_edit(filepath=filepath_final)
+ try:
+ bpy.ops.image.external_edit(filepath=filepath_final)
+ except RuntimeError as re:
+ self.report({'ERROR'}, str(re))
return {'FINISHED'}
@@ -185,6 +191,8 @@ class ProjectApply(bpy.types.Operator):
try:
image = bpy.data.images[image_name]
except KeyError:
+ import traceback
+ traceback.print_exc()
self.report({'ERROR'}, "Could not find image '%s'" % image_name)
return {'CANCELLED'}
@@ -192,14 +200,3 @@ class ProjectApply(bpy.types.Operator):
bpy.ops.paint.project_image(image=image_name)
return {'FINISHED'}
-
-
-def register():
- bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/op/mesh.py b/release/scripts/startup/bl_operators/mesh.py
index 4906fd7fc6c..44d81ba53df 100644
--- a/release/scripts/op/mesh.py
+++ b/release/scripts/startup/bl_operators/mesh.py
@@ -20,6 +20,8 @@
import bpy
+from bpy.props import EnumProperty
+
class MeshSelectInteriorFaces(bpy.types.Operator):
'''Select faces where all edges have more then 2 face users.'''
@@ -66,17 +68,23 @@ class MeshSelectInteriorFaces(bpy.types.Operator):
class MeshMirrorUV(bpy.types.Operator):
'''Copy mirror UV coordinates on the X axis based on a mirrored mesh'''
- bl_idname = "mesh.faces_miror_uv"
+ 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="")
+
@classmethod
def poll(cls, context):
ob = context.active_object
return (ob and ob.type == 'MESH')
def execute(self, context):
- DIR = 1 # TODO, make an option
+ DIR = (self.direction == 'NEGATIVE')
from mathutils import Vector
@@ -129,7 +137,7 @@ class MeshMirrorUV(bpy.types.Operator):
# find mirror faces
mirror_fm = {}
for i, f in enumerate(faces):
- verts = f.vertices[:]
+ verts = list(f.vertices)
verts.sort()
verts = tuple(verts)
mirror_fm[verts] = i
@@ -170,14 +178,3 @@ class MeshMirrorUV(bpy.types.Operator):
bpy.ops.object.mode_set(mode='EDIT', toggle=False)
return {'FINISHED'}
-
-
-def register():
- bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/op/nla.py b/release/scripts/startup/bl_operators/nla.py
index 5711fdf12e5..923ca92a162 100644
--- a/release/scripts/op/nla.py
+++ b/release/scripts/startup/bl_operators/nla.py
@@ -98,7 +98,7 @@ def bake(frame_start, frame_end, step=1, only_selected=False):
pose_items = pose.bones.items()
for name, pbone in pose_items:
- if only_selected and not pbone.select:
+ if only_selected and not pbone.bone.select:
continue
for f in frame_range:
@@ -124,7 +124,7 @@ def bake(frame_start, frame_end, step=1, only_selected=False):
return action
-from bpy.props import *
+from bpy.props import IntProperty, BoolProperty
class BakeAction(bpy.types.Operator):
@@ -168,18 +168,3 @@ class BakeAction(bpy.types.Operator):
def invoke(self, context, event):
wm = context.window_manager
return wm.invoke_props_dialog(self)
-
-
-#def menu_func(self, context):
-# self.layout.operator(BakeAction.bl_idname, text="Bake Armature Action")
-
-
-def register():
- bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/op/object.py b/release/scripts/startup/bl_operators/object.py
index 92886689972..0342a14a1b2 100644
--- a/release/scripts/op/object.py
+++ b/release/scripts/startup/bl_operators/object.py
@@ -19,7 +19,7 @@
# <pep8 compliant>
import bpy
-from bpy.props import *
+from bpy.props import StringProperty, BoolProperty, EnumProperty, IntProperty
class SelectPattern(bpy.types.Operator):
@@ -177,6 +177,9 @@ class SubdivisionSet(bpy.types.Operator):
if relative and level == 0:
return {'CANCELLED'} # nothing to do
+ if not relative and level < 0:
+ self.level = level = 0
+
def set_object_subd(obj):
for mod in obj.modifiers:
if mod.type == 'MULTIRES':
@@ -250,11 +253,11 @@ class ShapeTransfer(bpy.types.Operator):
def ob_add_shape(ob, name):
me = ob.data
key = ob.shape_key_add(from_mix=False)
- if len(me.shape_keys.keys) == 1:
+ if len(me.shape_keys.key_blocks) == 1:
key.name = "Basis"
key = ob.shape_key_add(from_mix=False) # we need a rest
key.name = name
- ob.active_shape_key_index = len(me.shape_keys.keys) - 1
+ ob.active_shape_key_index = len(me.shape_keys.key_blocks) - 1
ob.show_only_shape_key = True
from mathutils.geometry import barycentric_transform
@@ -270,7 +273,7 @@ class ShapeTransfer(bpy.types.Operator):
orig_normals = me_nos(me.vertices)
# orig_coords = me_cos(me.vertices) # the actual mverts location isnt as relyable as the base shape :S
- orig_coords = me_cos(me.shape_keys.keys[0].data)
+ orig_coords = me_cos(me.shape_keys.key_blocks[0].data)
for ob_other in objects:
me_other = ob_other.data
@@ -280,7 +283,7 @@ class ShapeTransfer(bpy.types.Operator):
target_normals = me_nos(me_other.vertices)
if me_other.shape_keys:
- target_coords = me_cos(me_other.shape_keys.keys[0].data)
+ target_coords = me_cos(me_other.shape_keys.key_blocks[0].data)
else:
target_coords = me_cos(me_other.vertices)
@@ -476,7 +479,6 @@ class MakeDupliFace(bpy.types.Operator):
def _main(self, context):
from mathutils import Vector
- from math import sqrt
SCALE_FAC = 0.01
offset = 0.5 * SCALE_FAC
@@ -562,14 +564,3 @@ class ClearAllRestrictRender(bpy.types.Operator):
for obj in context.scene.objects:
obj.hide_render = False
return {'FINISHED'}
-
-
-def register():
- bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/op/object_align.py b/release/scripts/startup/bl_operators/object_align.py
index d98fe584c1a..644f30a4745 100644
--- a/release/scripts/op/object_align.py
+++ b/release/scripts/startup/bl_operators/object_align.py
@@ -230,7 +230,7 @@ def align_objects(align_x, align_y, align_z, align_mode, relative_to):
return True
-from bpy.props import *
+from bpy.props import EnumProperty
class AlignObjects(bpy.types.Operator):
@@ -239,7 +239,7 @@ class AlignObjects(bpy.types.Operator):
bl_label = "Align Objects"
bl_options = {'REGISTER', 'UNDO'}
- align_mode = bpy.props.EnumProperty(items=(
+ align_mode = EnumProperty(items=(
('OPT_1', "Negative Sides", ""),
('OPT_2', "Centers", ""),
('OPT_3', "Positive Sides", "")),
@@ -247,7 +247,7 @@ class AlignObjects(bpy.types.Operator):
description="",
default='OPT_2')
- relative_to = bpy.props.EnumProperty(items=(
+ relative_to = EnumProperty(items=(
('OPT_1', "Scene Origin", ""),
('OPT_2', "3D Cursor", ""),
('OPT_3', "Selection", ""),
@@ -278,23 +278,3 @@ class AlignObjects(bpy.types.Operator):
return {'CANCELLED'}
else:
return {'FINISHED'}
-
-
-def menu_func(self, context):
- if context.mode == 'OBJECT':
- self.layout.operator(AlignObjects.bl_idname,
- text="Align Objects")
-
-
-def register():
- bpy.utils.register_module(__name__)
- bpy.types.VIEW3D_MT_transform.append(menu_func)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
- bpy.types.VIEW3D_MT_transform.remove(menu_func)
-
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py
new file mode 100644
index 00000000000..21640fa3ee6
--- /dev/null
+++ b/release/scripts/startup/bl_operators/object_quick_effects.py
@@ -0,0 +1,296 @@
+# ##### 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>
+
+from mathutils import Vector
+import bpy
+from bpy.props import BoolProperty, EnumProperty, IntProperty, FloatProperty, FloatVectorProperty
+
+
+class MakeFur(bpy.types.Operator):
+ bl_idname = "object.make_fur"
+ bl_label = "Make Fur"
+ 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)
+
+ def execute(self, context):
+ fake_context = bpy.context.copy()
+ 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.")
+ return {'CANCELLED'}
+
+ mat = bpy.data.materials.new("Fur Material")
+ mat.strand.tip_size = 0.25
+ mat.strand.blend_distance = 0.5
+
+ for obj in mesh_objects:
+ fake_context["object"] = obj
+ bpy.ops.object.particle_system_add(fake_context)
+
+ psys = obj.particle_systems[-1]
+ psys.settings.type = 'HAIR'
+
+ if self.density == 'LIGHT':
+ psys.settings.count = 100
+ elif self.density == 'MEDIUM':
+ psys.settings.count = 1000
+ elif self.density == 'HEAVY':
+ psys.settings.count = 10000
+
+ psys.settings.child_nbr = self.view_percentage
+ psys.settings.hair_length = self.length
+ psys.settings.use_strand_primitive = True
+ psys.settings.use_hair_bspline = True
+ psys.settings.child_type = 'INTERPOLATED'
+
+ obj.data.materials.append(mat)
+ obj.particle_systems[-1].settings.material = len(obj.data.materials)
+
+ return {'FINISHED'}
+
+
+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
+
+ min_co[0] = min(bb_vec[0], min_co[0])
+ min_co[1] = min(bb_vec[1], min_co[1])
+ min_co[2] = min(bb_vec[2], min_co[2])
+ max_co[0] = max(bb_vec[0], max_co[0])
+ max_co[1] = max(bb_vec[1], max_co[1])
+ max_co[2] = max(bb_vec[2], max_co[2])
+
+
+class MakeSmoke(bpy.types.Operator):
+ bl_idname = "object.make_smoke"
+ bl_label = "Make 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)
+
+ 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))
+
+ if not mesh_objects:
+ self.report({'ERROR'}, "Select at least one mesh object.")
+ return {'CANCELLED'}
+
+ for obj in mesh_objects:
+ fake_context["object"] = obj
+ # make each selected object a smoke flow
+ bpy.ops.object.modifier_add(fake_context, type='SMOKE')
+ obj.modifiers[-1].smoke_type = 'FLOW'
+
+ psys = obj.particle_systems[-1]
+ if self.style == 'PUFF':
+ psys.settings.frame_end = psys.settings.frame_start
+ psys.settings.emit_from = 'VOLUME'
+ psys.settings.distribution = 'RAND'
+ elif self.style == 'FIRE':
+ psys.settings.effector_weights.gravity = -1
+ psys.settings.lifetime = 5
+ psys.settings.count = 100000
+
+ obj.modifiers[-2].flow_settings.initial_velocity = True
+ obj.modifiers[-2].flow_settings.temperature = 2
+
+ psys.settings.use_render_emitter = self.show_flows
+ if not self.show_flows:
+ obj.draw_type = 'WIRE'
+
+ # store bounding box min/max for the domain object
+ obj_bb_minmax(obj, min_co, max_co)
+
+ # add the smoke domain object
+ bpy.ops.mesh.primitive_cube_add()
+ obj = context.active_object
+ obj.name = "Smoke Domain"
+
+ # give the smoke some room above the flows
+ obj.location = 0.5 * (max_co + min_co) + Vector((0.0, 0.0, 1.0))
+ obj.scale = 0.5 * (max_co - min_co) + Vector((1.0, 1.0, 2.0))
+
+ # setup smoke domain
+ bpy.ops.object.modifier_add(type='SMOKE')
+ obj.modifiers[-1].smoke_type = 'DOMAIN'
+ if self.style == 'FIRE':
+ obj.modifiers[-1].domain_settings.use_dissolve_smoke = True
+ obj.modifiers[-1].domain_settings.dissolve_speed = 20
+ obj.modifiers[-1].domain_settings.use_high_resolution = True
+
+ # create a volume material with a voxel data texture for the domain
+ bpy.ops.object.material_slot_add()
+
+ mat = bpy.data.materials.new("Smoke Domain Material")
+ obj.material_slots[0].material = mat
+ mat.type = 'VOLUME'
+ 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
+
+ # 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
+
+ ramp = mat.texture_slots[1].texture.color_ramp
+
+ elem = ramp.elements.new(0.333)
+ elem.color[0] = elem.color[3] = 1
+ elem.color[1] = elem.color[2] = 0
+
+ elem = ramp.elements.new(0.666)
+ elem.color[0] = elem.color[1] = elem.color[3] = 1
+ elem.color[2] = 0
+
+ mat.texture_slots[1].use_map_emission = True
+ mat.texture_slots[1].blend_type = 'MULTIPLY'
+
+ return {'FINISHED'}
+
+
+class MakeFluid(bpy.types.Operator):
+ bl_idname = "object.make_fluid"
+ bl_label = "Make 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)
+
+ 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)]
+ min_co = Vector((100000, 100000, 100000))
+ max_co = Vector((-100000, -100000, -100000))
+
+ if not mesh_objects:
+ self.report({'ERROR'}, "Select at least one mesh object.")
+ return {'CANCELLED'}
+
+ for obj in mesh_objects:
+ fake_context["object"] = obj
+ # 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
+ for mod in obj.modifiers:
+ if mod.type == 'FLUID_SIMULATION':
+ break
+
+ if self.style == 'INFLOW':
+ mod.settings.type = 'INFLOW'
+ mod.settings.inflow_velocity = self.initial_velocity.copy()
+ else:
+ mod.settings.type = 'FLUID'
+ mod.settings.initial_velocity = self.initial_velocity.copy()
+
+ obj.hide_render = not self.show_flows
+ if not self.show_flows:
+ obj.draw_type = 'WIRE'
+
+ # store bounding box min/max for the domain object
+ obj_bb_minmax(obj, min_co, max_co)
+
+ # add the fluid domain object
+ bpy.ops.mesh.primitive_cube_add()
+ obj = context.active_object
+ obj.name = "Fluid Domain"
+
+ # 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])))
+
+ # setup smoke domain
+ bpy.ops.object.modifier_add(type='FLUID_SIMULATION')
+ obj.modifiers[-1].settings.type = 'DOMAIN'
+
+ # make the domain smooth so it renders nicely
+ bpy.ops.object.shade_smooth()
+
+ # create a ray-transparent material for the domain
+ bpy.ops.object.material_slot_add()
+
+ mat = bpy.data.materials.new("Fluid Domain Material")
+ obj.material_slots[0].material = mat
+
+ mat.specular_intensity = 1
+ mat.specular_hardness = 100
+ mat.use_transparency = True
+ mat.alpha = 0.0
+ mat.transparency_method = 'RAYTRACE'
+ mat.raytrace_transparency.ior = 1.33
+ mat.raytrace_transparency.depth = 4
+
+ if self.start_baking:
+ bpy.ops.fluid.bake()
+
+ return {'FINISHED'}
diff --git a/release/scripts/op/object_randomize_transform.py b/release/scripts/startup/bl_operators/object_randomize_transform.py
index ee7a5f98b91..9dc5086086f 100644
--- a/release/scripts/op/object_randomize_transform.py
+++ b/release/scripts/startup/bl_operators/object_randomize_transform.py
@@ -84,7 +84,7 @@ def randomize_selected(seed, delta, loc, rot, scale, scale_even):
uniform(0.0, 0.0), uniform(0.0, 0.0), uniform(0.0, 0.0)
-from bpy.props import *
+from bpy.props import IntProperty, BoolProperty, FloatVectorProperty
class RandomizeLocRotSize(bpy.types.Operator):
@@ -145,23 +145,3 @@ class RandomizeLocRotSize(bpy.types.Operator):
randomize_selected(seed, delta, loc, rot, scale, scale_even)
return {'FINISHED'}
-
-
-def menu_func(self, context):
- if context.mode == 'OBJECT':
- self.layout.operator(RandomizeLocRotSize.bl_idname,
- text="Randomize Transform")
-
-
-def register():
- bpy.utils.register_module(__name__)
- bpy.types.VIEW3D_MT_transform.append(menu_func)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
- bpy.types.VIEW3D_MT_transform.remove(menu_func)
-
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/op/presets.py b/release/scripts/startup/bl_operators/presets.py
index 65653aeee3e..493c51ad237 100644
--- a/release/scripts/op/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -19,7 +19,6 @@
# <pep8 compliant>
import bpy
-import os
class AddPresetBase():
@@ -49,11 +48,11 @@ class AddPresetBase():
preset_menu_class = getattr(bpy.types, self.preset_menu)
if not self.remove_active:
-
- if not self.name:
+ name = self.name.strip()
+ if not name:
return {'FINISHED'}
- filename = self.as_filename(self.name)
+ filename = self.as_filename(name)
target_path = bpy.utils.user_resource('SCRIPTS', os.path.join("presets", self.preset_subdir), create=True)
@@ -119,7 +118,7 @@ class AddPresetBase():
return {'FINISHED'}
def check(self, context):
- self.name = self.as_filename(self.name)
+ self.name = self.as_filename(self.name.strip())
def invoke(self, context, event):
if not self.remove_active:
@@ -243,10 +242,10 @@ class AddPresetSunSky(AddPresetBase, bpy.types.Operator):
"sky.sun_brightness",
"sky.sun_intensity",
"sky.sun_size",
- "sky.use_sky_blend",
- "sky.use_sky_blend_type",
- "sky.use_sky_color_space",
- "sky.use_sky_exposure",
+ "sky.sky_blend",
+ "sky.sky_blend_type",
+ "sky.sky_color_space",
+ "sky.sky_exposure",
]
preset_subdir = "sunsky"
@@ -265,7 +264,7 @@ class AddPresetInteraction(AddPresetBase, bpy.types.Operator):
preset_values = [
"user_preferences.edit.use_drag_immediately",
"user_preferences.edit.use_insertkey_xyz_to_rgb",
- "user_preferences.inputs.invert_mouse_wheel_zoom",
+ "user_preferences.inputs.invert_mouse_zoom",
"user_preferences.inputs.select_mouse",
"user_preferences.inputs.use_emulate_numpad",
"user_preferences.inputs.use_mouse_continuous",
@@ -328,7 +327,7 @@ class AddPresetOperator(AddPresetBase, bpy.types.Operator):
ret = []
for prop_id, prop in operator_rna.properties.items():
if (not prop.is_hidden) and prop_id not in properties_blacklist:
- ret.append("op.%s" % prop_id)
+ ret.append("op.%s" % prop_id)
return ret
@@ -351,14 +350,3 @@ class WM_MT_operator_presets(bpy.types.Menu):
return AddPresetOperator.operator_path(self.operator)
preset_operator = "script.execute_preset"
-
-
-def register():
- bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/op/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
index 579af9b34b3..64af25e7b0f 100644
--- a/release/scripts/op/screen_play_rendered_anim.py
+++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py
@@ -29,19 +29,14 @@ import os
def guess_player_path(preset):
- import platform
- try:
- system = platform.system()
- except UnicodeDecodeError:
- import sys
- system = sys.platform
+ import sys
if preset == 'BLENDER24':
player_path = "blender"
- if system == 'Darwin':
+ if sys.platform == "darwin":
test_path = "/Applications/blender 2.49.app/Contents/MacOS/blender"
- elif system in ('Windows', 'win32'):
+ elif sys.platform[:3] == "win":
test_path = "/Program Files/Blender Foundation/Blender/blender.exe"
if os.path.exists(test_path):
@@ -50,7 +45,8 @@ def guess_player_path(preset):
elif preset == 'DJV':
player_path = "djv_view"
- if system == 'Darwin':
+ 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'
if os.path.exists(test_path):
player_path = test_path
@@ -144,14 +140,3 @@ class PlayRenderedAnim(bpy.types.Operator):
#raise OSError("Couldn't find an external animation player.")
return {'FINISHED'}
-
-
-def register():
- bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/op/sequencer.py b/release/scripts/startup/bl_operators/sequencer.py
index de341bef269..16b72406c49 100644
--- a/release/scripts/op/sequencer.py
+++ b/release/scripts/startup/bl_operators/sequencer.py
@@ -20,7 +20,7 @@
import bpy
-from bpy.props import *
+from bpy.props import IntProperty
class SequencerCrossfadeSounds(bpy.types.Operator):
@@ -132,15 +132,3 @@ class SequencerDeinterlaceSelectedMovies(bpy.types.Operator):
s.use_deinterlace = True
return {'FINISHED'}
-
-
-def register():
- bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/op/uvcalc_follow_active.py b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
index 12895fae1c5..ad5ec15ff80 100644
--- a/release/scripts/op/uvcalc_follow_active.py
+++ b/release/scripts/startup/bl_operators/uvcalc_follow_active.py
@@ -245,20 +245,6 @@ class FollowActiveQuads(bpy.types.Operator):
main(context, self)
return {'FINISHED'}
-
-# Add to a menu
-menu_func = (lambda self, context: self.layout.operator(FollowActiveQuads.bl_idname))
-
-
-def register():
- bpy.utils.register_module(__name__)
- bpy.types.VIEW3D_MT_uv_map.append(menu_func)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
- bpy.types.VIEW3D_MT_uv_map.remove(menu_func)
-
-
-if __name__ == "__main__":
- register()
+ def invoke(self, context, event):
+ wm = context.window_manager
+ return wm.invoke_props_dialog(self)
diff --git a/release/scripts/startup/bl_operators/uvcalc_lightmap.py b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
new file mode 100644
index 00000000000..3893612437a
--- /dev/null
+++ b/release/scripts/startup/bl_operators/uvcalc_lightmap.py
@@ -0,0 +1,582 @@
+# ##### 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
+import mathutils
+
+
+class prettyface(object):
+ __slots__ = "uv", "width", "height", "children", "xoff", "yoff", "has_parent", "rot"
+
+ def __init__(self, data):
+ self.has_parent = False
+ self.rot = False # only used for triables
+ self.xoff = 0
+ self.yoff = 0
+
+ if type(data) == list: # list of data
+ self.uv = None
+
+ # join the data
+ if len(data) == 2:
+ # 2 vertical blocks
+ data[1].xoff = data[0].width
+ self.width = data[0].width * 2
+ self.height = data[0].height
+
+ elif len(data) == 4:
+ # 4 blocks all the same size
+ d = data[0].width # dimension x/y are the same
+
+ data[1].xoff += d
+ data[2].yoff += d
+
+ data[3].xoff += d
+ data[3].yoff += d
+
+ self.width = self.height = d * 2
+
+ #else:
+ # print(len(data), data)
+ # raise "Error"
+
+ for pf in data:
+ pf.has_parent = True
+
+ self.children = data
+
+ elif type(data) == tuple:
+ # 2 blender faces
+ # f, (len_min, len_mid, len_max)
+ self.uv = data
+
+ f1, lens1, lens1ord = data[0]
+ if data[1]:
+ f2, lens2, lens2ord = data[1]
+ self.width = (lens1[lens1ord[0]] + lens2[lens2ord[0]]) / 2.0
+ self.height = (lens1[lens1ord[1]] + lens2[lens2ord[1]]) / 2.0
+ else: # 1 tri :/
+ self.width = lens1[0]
+ self.height = lens1[1]
+
+ self.children = []
+
+ else: # blender face
+ # self.uv = data.uv
+ self.uv = data.id_data.uv_textures.active.data[data.index].uv # XXX25
+
+ # cos = [v.co for v in data]
+ cos = [data.id_data.vertices[v].co for v in data.vertices] # XXX25
+
+ self.width = ((cos[0] - cos[1]).length + (cos[2] - cos[3]).length) / 2.0
+ self.height = ((cos[1] - cos[2]).length + (cos[0] - cos[3]).length) / 2.0
+
+ self.children = []
+
+ def spin(self):
+ if self.uv and len(self.uv) == 4:
+ self.uv = self.uv[1], self.uv[2], self.uv[3], self.uv[0]
+
+ self.width, self.height = self.height, self.width
+ self.xoff, self.yoff = self.yoff, self.xoff # not needed?
+ self.rot = not self.rot # only for tri pairs.
+ # print("spinning")
+ for pf in self.children:
+ pf.spin()
+
+ def place(self, xoff, yoff, xfac, yfac, margin_w, margin_h):
+ from math import pi
+
+ xoff += self.xoff
+ yoff += self.yoff
+
+ for pf in self.children:
+ pf.place(xoff, yoff, xfac, yfac, margin_w, margin_h)
+
+ uv = self.uv
+ if not uv:
+ return
+
+ x1 = xoff
+ y1 = yoff
+ x2 = xoff + self.width
+ y2 = yoff + self.height
+
+ # Scale the values
+ x1 = x1 / xfac + margin_w
+ x2 = x2 / xfac - margin_w
+ y1 = y1 / yfac + margin_h
+ y2 = y2 / yfac - margin_h
+
+ # 2 Tri pairs
+ if len(uv) == 2:
+ # match the order of angle sizes of the 3d verts with the UV angles and rotate.
+ def get_tri_angles(v1, v2, v3):
+ a1 = (v2 - v1).angle(v3 - v1, pi)
+ a2 = (v1 - v2).angle(v3 - v2, pi)
+ a3 = pi - (a1 + a2) # a3= (v2 - v3).angle(v1 - v3)
+
+ return [(a1, 0), (a2, 1), (a3, 2)]
+
+ def set_uv(f, p1, p2, p3):
+
+ # cos =
+ #v1 = cos[0]-cos[1]
+ #v2 = cos[1]-cos[2]
+ #v3 = cos[2]-cos[0]
+
+ # angles_co = get_tri_angles(*[v.co for v in f])
+ angles_co = get_tri_angles(*[f.id_data.vertices[v].co for v in f.vertices]) # XXX25
+
+ angles_co.sort()
+ I = [i for a, i in angles_co]
+
+ # fuv = f.uv
+ fuv = f.id_data.uv_textures.active.data[f.index].uv # XXX25
+
+ if self.rot:
+ fuv[I[2]] = p1
+ fuv[I[1]] = p2
+ fuv[I[0]] = p3
+ else:
+ fuv[I[2]] = p1
+ fuv[I[0]] = p2
+ fuv[I[1]] = p3
+
+ f, lens, lensord = uv[0]
+
+ set_uv(f, (x1, y1), (x1, y2 - margin_h), (x2 - margin_w, y1))
+
+ if uv[1]:
+ f, lens, lensord = uv[1]
+ set_uv(f, (x2, y2), (x2, y1 + margin_h), (x1 + margin_w, y2))
+
+ else: # 1 QUAD
+ uv[1][0], uv[1][1] = x1, y1
+ uv[2][0], uv[2][1] = x1, y2
+ uv[3][0], uv[3][1] = x2, y2
+ uv[0][0], uv[0][1] = x2, y1
+
+ def __hash__(self):
+ # None unique hash
+ return self.width, self.height
+
+
+def lightmap_uvpack(meshes,
+ PREF_SEL_ONLY=True,
+ PREF_NEW_UVLAYER=False,
+ PREF_PACK_IN_ONE=False,
+ PREF_APPLY_IMAGE=False,
+ PREF_IMG_PX_SIZE=512,
+ PREF_BOX_DIV=8,
+ PREF_MARGIN_DIV=512
+ ):
+ '''
+ BOX_DIV if the maximum division of the UV map that
+ a box may be consolidated into.
+ Basicly, a lower value will be slower but waist less space
+ and a higher value will have more clumpy boxes but more waisted space
+ '''
+ import time
+ from math import sqrt
+
+ if not meshes:
+ return
+
+ t = time.time()
+
+ if PREF_PACK_IN_ONE:
+ if PREF_APPLY_IMAGE:
+ image = bpy.data.images.new(name="lightmap", width=PREF_IMG_PX_SIZE, height=PREF_IMG_PX_SIZE, alpha=False)
+ face_groups = [[]]
+ else:
+ face_groups = []
+
+ for me in meshes:
+ # Add face UV if it does not exist.
+ # All new faces are selected.
+ if not me.uv_textures:
+ me.uv_textures.new()
+
+ if PREF_SEL_ONLY:
+ faces = [f for f in me.faces if f.select]
+ else:
+ faces = me.faces[:]
+
+ if PREF_PACK_IN_ONE:
+ face_groups[0].extend(faces)
+ else:
+ face_groups.append(faces)
+
+ if PREF_NEW_UVLAYER:
+ me.uv_textures.new()
+
+ for face_sel in face_groups:
+ print("\nStarting unwrap")
+
+ if len(face_sel) < 4:
+ print("\tWarning, less then 4 faces, skipping")
+ continue
+
+ pretty_faces = [prettyface(f) for f in face_sel if len(f.vertices) == 4]
+
+ # Do we have any tri's
+ if len(pretty_faces) != len(face_sel):
+
+ # Now add tri's, not so simple because we need to pair them up.
+ def trylens(f):
+ # f must be a tri
+
+ # cos = [v.co for v in f]
+ cos = [f.id_data.vertices[v].co for v in f.vertices] # XXX25
+
+ lens = [(cos[0] - cos[1]).length, (cos[1] - cos[2]).length, (cos[2] - cos[0]).length]
+
+ lens_min = lens.index(min(lens))
+ lens_max = lens.index(max(lens))
+ for i in range(3):
+ if i != lens_min and i != lens_max:
+ lens_mid = i
+ break
+ lens_order = lens_min, lens_mid, lens_max
+
+ return f, lens, lens_order
+
+ tri_lengths = [trylens(f) for f in face_sel if len(f.vertices) == 3]
+ 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]])
+
+ while tri_lengths:
+ tri1 = tri_lengths.pop()
+
+ if not tri_lengths:
+ pretty_faces.append(prettyface((tri1, None)))
+ break
+
+ best_tri_index = -1
+ best_tri_diff = 100000000.0
+
+ for i, tri2 in enumerate(tri_lengths):
+ diff = trilensdiff(tri1, tri2)
+ if diff < best_tri_diff:
+ best_tri_index = i
+ best_tri_diff = diff
+
+ pretty_faces.append(prettyface((tri1, tri_lengths.pop(best_tri_index))))
+
+ # Get the min, max and total areas
+ max_area = 0.0
+ min_area = 100000000.0
+ tot_area = 0
+ for f in face_sel:
+ area = f.area
+ if area > max_area:
+ max_area = area
+ if area < min_area:
+ min_area = area
+ tot_area += area
+
+ max_len = sqrt(max_area)
+ min_len = sqrt(min_area)
+ side_len = sqrt(tot_area)
+
+ # Build widths
+
+ curr_len = max_len
+
+ print("\tGenerating lengths...", end="")
+
+ lengths = []
+ while curr_len > min_len:
+ lengths.append(curr_len)
+ curr_len = curr_len / 2.0
+
+ # Dont allow boxes smaller then the margin
+ # since we contract on the margin, boxes that are smaller will create errors
+ # print(curr_len, side_len/MARGIN_DIV)
+ if curr_len / 4.0 < side_len / PREF_MARGIN_DIV:
+ break
+
+ if not lengths:
+ lengths.append(curr_len)
+
+ # convert into ints
+ lengths_to_ints = {}
+
+ l_int = 1
+ for l in reversed(lengths):
+ lengths_to_ints[l] = l_int
+ l_int *= 2
+
+ lengths_to_ints = list(lengths_to_ints.items())
+ lengths_to_ints.sort()
+ print("done")
+
+ # apply quantized values.
+
+ for pf in pretty_faces:
+ w = pf.width
+ h = pf.height
+ bestw_diff = 1000000000.0
+ besth_diff = 1000000000.0
+ new_w = 0.0
+ new_h = 0.0
+ for l, i in lengths_to_ints:
+ d = abs(l - w)
+ if d < bestw_diff:
+ bestw_diff = d
+ new_w = i # assign the int version
+
+ d = abs(l - h)
+ if d < besth_diff:
+ besth_diff = d
+ new_h = i # ditto
+
+ pf.width = new_w
+ pf.height = new_h
+
+ if new_w > new_h:
+ pf.spin()
+
+ print("...done")
+
+ # Since the boxes are sized in powers of 2, we can neatly group them into bigger squares
+ # this is done hierarchily, so that we may avoid running the pack function
+ # on many thousands of boxes, (under 1k is best) because it would get slow.
+ # Using an off and even dict us usefull because they are packed differently
+ # where w/h are the same, their packed in groups of 4
+ # where they are different they are packed in pairs
+ #
+ # After this is done an external pack func is done that packs the whole group.
+
+ print("\tConsolidating Boxes...", end="")
+ even_dict = {} # w/h are the same, the key is an int (w)
+ odd_dict = {} # w/h are different, the key is the (w,h)
+
+ for pf in pretty_faces:
+ w, h = pf.width, pf.height
+ if w == h:
+ even_dict.setdefault(w, []).append(pf)
+ else:
+ odd_dict.setdefault((w, h), []).append(pf)
+
+ # Count the number of boxes consolidated, only used for stats.
+ c = 0
+
+ # This is tricky. the total area of all packed boxes, then squt that to get an estimated size
+ # this is used then converted into out INT space so we can compare it with
+ # the ints assigned to the boxes size
+ # and divided by BOX_DIV, basicly if BOX_DIV is 8
+ # ...then the maximum box consolidataion (recursive grouping) will have a max width & height
+ # ...1/8th of the UV size.
+ # ...limiting this is needed or you end up with bug unused texture spaces
+ # ...however if its too high, boxpacking is way too slow for high poly meshes.
+ float_to_int_factor = lengths_to_ints[0][0]
+ if float_to_int_factor > 0:
+ max_int_dimension = int(((side_len / float_to_int_factor)) / PREF_BOX_DIV)
+ ok = True
+ else:
+ max_int_dimension = 0.0 # wont be used
+ ok = False
+
+ # RECURSIVE prettyface grouping
+ while ok:
+ ok = False
+
+ # Tall boxes in groups of 2
+ for d, boxes in odd_dict.items():
+ if d[1] < max_int_dimension:
+ #\boxes.sort(key = lambda a: len(a.children))
+ while len(boxes) >= 2:
+ # print("foo", len(boxes))
+ ok = True
+ c += 1
+ pf_parent = prettyface([boxes.pop(), boxes.pop()])
+ pretty_faces.append(pf_parent)
+
+ w, h = pf_parent.width, pf_parent.height
+
+ if w > h:
+ raise "error"
+
+ if w == h:
+ even_dict.setdefault(w, []).append(pf_parent)
+ else:
+ odd_dict.setdefault((w, h), []).append(pf_parent)
+
+ # Even boxes in groups of 4
+ for d, boxes in even_dict.items():
+ if d < max_int_dimension:
+ boxes.sort(key=lambda a: len(a.children))
+
+ while len(boxes) >= 4:
+ # print("bar", len(boxes))
+ ok = True
+ c += 1
+
+ pf_parent = prettyface([boxes.pop(), boxes.pop(), boxes.pop(), boxes.pop()])
+ pretty_faces.append(pf_parent)
+ w = pf_parent.width # width and weight are the same
+ even_dict.setdefault(w, []).append(pf_parent)
+
+ del even_dict
+ del odd_dict
+
+ orig = len(pretty_faces)
+
+ pretty_faces = [pf for pf in pretty_faces if not pf.has_parent]
+
+ # spin every second prettyface
+ # if there all vertical you get less efficiently used texture space
+ i = len(pretty_faces)
+ d = 0
+ while i:
+ i -= 1
+ pf = pretty_faces[i]
+ if pf.width != pf.height:
+ d += 1
+ if d % 2: # only pack every second
+ pf.spin()
+ # pass
+
+ print("Consolidated", c, "boxes, done")
+ # print("done", orig, len(pretty_faces))
+
+ # boxes2Pack.append([islandIdx, w,h])
+ print("\tPacking Boxes", len(pretty_faces), end="...")
+ boxes2Pack = [[0.0, 0.0, pf.width, pf.height, i] for i, pf in enumerate(pretty_faces)]
+ packWidth, packHeight = mathutils.geometry.box_pack_2d(boxes2Pack)
+
+ # print(packWidth, packHeight)
+
+ packWidth = float(packWidth)
+ packHeight = float(packHeight)
+
+ margin_w = ((packWidth) / PREF_MARGIN_DIV) / packWidth
+ margin_h = ((packHeight) / PREF_MARGIN_DIV) / packHeight
+
+ # print(margin_w, margin_h)
+ print("done")
+
+ # Apply the boxes back to the UV coords.
+ print("\twriting back UVs", end="")
+ for i, box in enumerate(boxes2Pack):
+ pretty_faces[i].place(box[0], box[1], packWidth, packHeight, margin_w, margin_h)
+ # pf.place(box[1][1], box[1][2], packWidth, packHeight, margin_w, margin_h)
+ print("done")
+
+ if PREF_APPLY_IMAGE:
+ if not PREF_PACK_IN_ONE:
+ image = Image.New("lightmap", PREF_IMG_PX_SIZE, PREF_IMG_PX_SIZE, 24)
+
+ for f in face_sel:
+ # f.image = image
+ f.id_data.uv_textures.active.data[f.index].image = image # XXX25
+
+ for me in meshes:
+ me.update()
+
+ print("finished all %.2f " % (time.time() - t))
+
+ # Window.RedrawAll()
+
+
+def unwrap(operator, context, **kwargs):
+
+ is_editmode = (bpy.context.object.mode == 'EDIT')
+ if is_editmode:
+ bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+
+ PREF_ACT_ONLY = kwargs.pop("PREF_ACT_ONLY")
+
+ meshes = []
+ if PREF_ACT_ONLY:
+ obj = context.scene.objects.active
+ 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()
+
+ if not meshes:
+ operator.report({'ERROR'}, "No mesh object.")
+ return {'CANCELLED'}
+
+ lightmap_uvpack(meshes, **kwargs)
+
+ if is_editmode:
+ bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+
+ return {'FINISHED'}
+
+from bpy.props import BoolProperty, FloatProperty, IntProperty, EnumProperty
+
+
+class LightMapPack(bpy.types.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(
+ 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")
+
+ # 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")
+
+ def execute(self, context):
+ kwargs = self.as_keywords()
+ PREF_CONTEXT = kwargs.pop("PREF_CONTEXT")
+
+ if PREF_CONTEXT == 'SEL_FACES':
+ kwargs["PREF_ACT_ONLY"] = True
+ kwargs["PREF_SEL_ONLY"] = True
+ elif PREF_CONTEXT == 'ALL_FACES':
+ kwargs["PREF_ACT_ONLY"] = True
+ kwargs["PREF_SEL_ONLY"] = False
+ elif PREF_CONTEXT == 'ALL_OBJECTS':
+ kwargs["PREF_ACT_ONLY"] = False
+ kwargs["PREF_SEL_ONLY"] = False
+ else:
+ raise Exception("invalid context")
+
+ kwargs["PREF_MARGIN_DIV"] = int(1.0 / (kwargs["PREF_MARGIN_DIV"] / 100.0))
+
+ return unwrap(self, context, **kwargs)
+
+ def invoke(self, context, event):
+ wm = context.window_manager
+ return wm.invoke_props_dialog(self)
diff --git a/release/scripts/op/uvcalc_smart_project.py b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
index 8cdf593f98d..4f5b1d8b233 100644
--- a/release/scripts/op/uvcalc_smart_project.py
+++ b/release/scripts/startup/bl_operators/uvcalc_smart_project.py
@@ -1,31 +1,25 @@
-# --------------------------------------------------------------------------
-# Smart Projection UV Projection Unwrapper v1.2 by Campbell Barton (AKA Ideasman)
-# --------------------------------------------------------------------------
-# ***** BEGIN GPL LICENSE BLOCK *****
+# ##### 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 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>
from mathutils import Matrix, Vector, geometry
-import time
import bpy
-from math import cos, radians
DEG_TO_RAD = 0.017453292519943295 # pi/180.0
SMALL_NUM = 0.000000001
@@ -36,14 +30,10 @@ global USER_FILL_HOLES_QUALITY
USER_FILL_HOLES = None
USER_FILL_HOLES_QUALITY = None
-dict_matrix = {}
-
def pointInTri2D(v, v1, v2, v3):
- global dict_matrix
-
key = v1.x, v1.y, v2.x, v2.y, v3.x, v3.y
- # Commented because its slower to do teh bounds check, we should realy cache the bounds info for each face.
+ # Commented because its slower to do the bounds check, we should realy cache the bounds info for each face.
'''
# BOUNDS CHECK
xmin= 1000000
@@ -268,21 +258,6 @@ def testNewVecLs2DRotIsBetter(vecs, mat=-1, bestAreaSoFar = -1):
h = maxy-miny
return (w*h, w,h), vecs # Area, vecs
-# Takes a list of faces that make up a UV island and rotate
-# until they optimally fit inside a square.
-ROTMAT_2D_POS_90D = Matrix.Rotation( radians(90.0), 2)
-ROTMAT_2D_POS_45D = Matrix.Rotation( radians(45.0), 2)
-
-RotMatStepRotation = []
-rot_angle = 22.5 #45.0/2
-while rot_angle > 0.1:
- RotMatStepRotation.append([\
- Matrix.Rotation( radians(rot_angle), 2),\
- Matrix.Rotation( radians(-rot_angle), 2)])
-
- rot_angle = rot_angle/2.0
-
-
def optiRotateUvIsland(faces):
global currentArea
@@ -464,7 +439,7 @@ def mergeUvIslands(islandList):
# if targetIsland[3] > (sourceIsland[2]) and\ #
- # print USER_FREE_SPACE_TO_TEST_QUALITY, 'ass'
+ # print USER_FREE_SPACE_TO_TEST_QUALITY
if targetIsland[2] > (sourceIsland[1] * USER_FREE_SPACE_TO_TEST_QUALITY) and\
targetIsland[4] > sourceIsland[4] and\
targetIsland[5] > sourceIsland[5]:
@@ -734,7 +709,7 @@ def packIslands(islandList):
#print '\tPacking UV Islands...'
#XXX Window.DrawProgressBar(0.7, 'Packing %i UV Islands...' % len(packBoxes) )
- time1 = time.time()
+ # time1 = time.time()
packWidth, packHeight = geometry.box_pack_2d(packBoxes)
# print 'Box Packing Time:', time.time() - time1
@@ -793,6 +768,27 @@ class thickface(object):
self.area = face.area
self.edge_keys = face.edge_keys
+
+def main_consts():
+ from math import radians
+
+ global ROTMAT_2D_POS_90D
+ global ROTMAT_2D_POS_45D
+ global RotMatStepRotation
+
+ ROTMAT_2D_POS_90D = Matrix.Rotation( radians(90.0), 2)
+ ROTMAT_2D_POS_45D = Matrix.Rotation( radians(45.0), 2)
+
+ RotMatStepRotation = []
+ rot_angle = 22.5 #45.0/2
+ while rot_angle > 0.1:
+ RotMatStepRotation.append([\
+ Matrix.Rotation( radians(rot_angle), 2),\
+ Matrix.Rotation( radians(-rot_angle), 2)])
+
+ rot_angle = rot_angle/2.0
+
+
global ob
ob = None
def main(context, island_margin, projection_limit):
@@ -800,6 +796,21 @@ def main(context, island_margin, projection_limit):
global USER_FILL_HOLES_QUALITY
global USER_STRETCH_ASPECT
global USER_ISLAND_MARGIN
+
+ from math import cos
+ import time
+
+ global dict_matrix
+ dict_matrix = {}
+
+
+ # Constants:
+ # Takes a list of faces that make up a UV island and rotate
+ # until they optimally fit inside a square.
+ global ROTMAT_2D_POS_90D
+ global ROTMAT_2D_POS_45D
+ global RotMatStepRotation
+ main_consts()
#XXX objects= bpy.data.scenes.active.objects
objects = context.selected_editable_objects
@@ -868,7 +879,7 @@ def main(context, island_margin, projection_limit):
time1 = time.time()
- # Tag as False se we dont operate on teh same mesh twice.
+ # Tag as False se we dont operate on the same mesh twice.
#XXX bpy.data.meshes.tag = False
for me in bpy.data.meshes:
me.tag = False
@@ -1074,6 +1085,8 @@ def main(context, island_margin, projection_limit):
if is_editmode:
bpy.ops.object.mode_set(mode='EDIT')
+ dict_matrix.clear()
+
#XXX Window.DrawProgressBar(1.0, "")
#XXX Window.WaitCursor(0)
#XXX Window.RedrawAll()
@@ -1098,7 +1111,7 @@ def main(context, island_margin, projection_limit):
]
"""
-from bpy.props import *
+from bpy.props import FloatProperty
class SmartProject(bpy.types.Operator):
@@ -1123,20 +1136,6 @@ class SmartProject(bpy.types.Operator):
main(context, self.island_margin, self.angle_limit)
return {'FINISHED'}
-
-# Add to a menu
-menu_func = (lambda self, context: self.layout.operator(SmartProject.bl_idname,
- text="Smart Project"))
-
-
-def register():
- bpy.utils.register_module(__name__)
- bpy.types.VIEW3D_MT_uv_map.append(menu_func)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
- bpy.types.VIEW3D_MT_uv_map.remove(menu_func)
-
-if __name__ == "__main__":
- register()
+ def invoke(self, context, event):
+ wm = context.window_manager
+ return wm.invoke_props_dialog(self)
diff --git a/release/scripts/op/vertexpaint_dirt.py b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
index d5060e913ae..672db71e361 100644
--- a/release/scripts/op/vertexpaint_dirt.py
+++ b/release/scripts/startup/bl_operators/vertexpaint_dirt.py
@@ -30,16 +30,10 @@
# but results are far more accurate
#
-import bpy
-import math
-import time
-
-from mathutils import Vector
-from bpy.props import *
-
def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean, dirt_only):
-## Window.WaitCursor(1)
+ from mathutils import Vector
+ from math import acos
#BPyMesh.meshCalcNormals(me)
@@ -76,7 +70,7 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
vec /= tot_con
# angle is the acos of the dot product between vert and connected verts normals
- ang = math.acos(no.dot(vec))
+ ang = acos(no.dot(vec))
# enforce min/max
ang = max(clamp_dirt, ang)
@@ -146,11 +140,12 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
col[1] = tone * col[1]
col[2] = tone * col[2]
-## Window.WaitCursor(0)
+import bpy
+from bpy.props import FloatProperty, IntProperty, BoolProperty
-class VertexPaintDirt(bpy.types.Operator):
+class VertexPaintDirt(bpy.types.Operator):
bl_idname = "paint.vertex_color_dirt"
bl_label = "Dirty Vertex Colors"
bl_options = {'REGISTER', 'UNDO'}
@@ -162,29 +157,20 @@ class VertexPaintDirt(bpy.types.Operator):
dirt_only = BoolProperty(name="Dirt Only", description="Dont calculate cleans for convex areas", default=False)
def execute(self, context):
+ import time
+ from math import radians
obj = context.object
if not obj or obj.type != 'MESH':
- print('Error, no active mesh object, aborting')
- return('CANCELLED',)
+ self.report({'ERROR'}, "Error, no active mesh object, aborting")
+ return {'CANCELLED'}
mesh = obj.data
t = time.time()
- applyVertexDirt(mesh, self.blur_iterations, self.blur_strength, math.radians(self.dirt_angle), math.radians(self.clean_angle), self.dirt_only)
+ applyVertexDirt(mesh, self.blur_iterations, self.blur_strength, radians(self.dirt_angle), radians(self.clean_angle), self.dirt_only)
print('Dirt calculated in %.6f' % (time.time() - t))
return {'FINISHED'}
-
-
-def register():
- bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/op/wm.py b/release/scripts/startup/bl_operators/wm.py
index cbc9e3cd55f..53c8d562297 100644
--- a/release/scripts/op/wm.py
+++ b/release/scripts/startup/bl_operators/wm.py
@@ -19,8 +19,7 @@
# <pep8 compliant>
import bpy
-
-from bpy.props import *
+from bpy.props import StringProperty, BoolProperty, IntProperty, FloatProperty
from rna_prop_ui import rna_idprop_ui_prop_get, rna_idprop_ui_prop_clear
@@ -51,7 +50,7 @@ rna_relative_prop = BoolProperty(name="Relative",
def context_path_validate(context, data_path):
import sys
try:
- value = eval("context.%s" % data_path)
+ value = eval("context.%s" % data_path) if data_path else Ellipsis
except AttributeError:
if "'NoneType'" in str(sys.exc_info()[1]):
# One of the items in the rna path is None, just ignore this
@@ -75,20 +74,20 @@ def execute_context_assign(self, context):
return {'FINISHED'}
-class BRUSH_OT_set_active_number(bpy.types.Operator):
+class BRUSH_OT_active_index_set(bpy.types.Operator):
'''Set active sculpt/paint brush from it's number'''
- bl_idname = "brush.set_active_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)
- number = IntProperty(name="number",
+ 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_texture"}
+ "image_paint": "use_paint_image"}
def execute(self, context):
attr = self._attr_dict.get(self.mode)
@@ -96,7 +95,7 @@ class BRUSH_OT_set_active_number(bpy.types.Operator):
return {'CANCELLED'}
for i, brush in enumerate((cur for cur in bpy.data.brushes if getattr(cur, attr))):
- if i == self.number:
+ if i == self.index:
getattr(context.tool_settings, self.mode).brush = brush
return {'FINISHED'}
@@ -336,7 +335,7 @@ class WM_OT_context_cycle_enum(bpy.types.Operator):
if type(rna_prop) != bpy.types.EnumProperty:
raise Exception("expected an enum property")
- enums = rna_struct.properties[rna_prop_str].items.keys()
+ enums = rna_struct.properties[rna_prop_str].enum_items.keys()
orig_index = enums.index(orig_value)
# Have the info we need, advance to the next item
@@ -384,6 +383,39 @@ class WM_OT_context_cycle_array(bpy.types.Operator):
return {'FINISHED'}
+class WM_MT_context_menu_enum(bpy.types.Menu):
+ bl_label = ""
+ data_path = "" # BAD DESIGN, set from operator below.
+
+ def draw(self, context):
+ data_path = self.data_path
+ value = context_path_validate(bpy.context, data_path)
+ if value is Ellipsis:
+ return {'PASS_THROUGH'}
+ base_path, prop_string = data_path.rsplit(".", 1)
+ value_base = context_path_validate(context, base_path)
+
+ values = [(i.name, i.identifier) for i in value_base.bl_rna.properties[prop_string].enum_items]
+
+ for name, identifier in values:
+ prop = self.layout.operator("wm.context_set_enum", text=name)
+ prop.data_path = data_path
+ prop.value = identifier
+
+
+class WM_OT_context_menu_enum(bpy.types.Operator):
+ bl_idname = "wm.context_menu_enum"
+ bl_label = "Context Enum Menu"
+ bl_options = {'UNDO'}
+ data_path = rna_path_prop
+
+ def execute(self, context):
+ data_path = self.data_path
+ WM_MT_context_menu_enum.data_path = data_path
+ bpy.ops.wm.call_menu(name="WM_MT_context_menu_enum")
+ return {'PASS_THROUGH'}
+
+
class WM_OT_context_set_id(bpy.types.Operator):
'''Toggle a context value.'''
bl_idname = "wm.context_set_id"
@@ -520,6 +552,7 @@ class WM_OT_url_open(bpy.types.Operator):
def execute(self, context):
import webbrowser
+ _webbrowser_bug_fix()
webbrowser.open(self.url)
return {'FINISHED'}
@@ -543,7 +576,7 @@ class WM_OT_path_open(bpy.types.Operator):
self.report({'ERROR'}, "File '%s' not found" % filepath)
return {'CANCELLED'}
- if sys.platform == 'win32':
+ if sys.platform[:3] == "win":
subprocess.Popen(['start', filepath], shell=True)
elif sys.platform == 'darwin':
subprocess.Popen(['open', filepath])
@@ -563,7 +596,10 @@ class WM_OT_doc_view(bpy.types.Operator):
bl_label = "View Documentation"
doc_id = doc_id
- _prefix = "http://www.blender.org/documentation/blender_python_api_%s" % "_".join(str(v) for v in bpy.app.version)
+ 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)
+ else:
+ _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 = []
@@ -584,6 +620,15 @@ class WM_OT_doc_view(bpy.types.Operator):
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
+ rna_parent = getattr(bpy.types, class_name).bl_rna
+ rna_prop = rna_parent.properties[class_prop]
+ rna_parent = rna_parent.base
+ while rna_parent and rna_prop == rna_parent.properties.get(class_prop):
+ class_name = rna_parent.identifier
+ rna_parent = rna_parent.base
+
# 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' % \
@@ -593,6 +638,7 @@ class WM_OT_doc_view(bpy.types.Operator):
return {'PASS_THROUGH'}
import webbrowser
+ _webbrowser_bug_fix()
webbrowser.open(url)
return {'FINISHED'}
@@ -669,9 +715,6 @@ class WM_OT_doc_edit(bpy.types.Operator):
return wm.invoke_props_dialog(self, width=600)
-from bpy.props import *
-
-
rna_path = StringProperty(name="Property Edit",
description="Property data_path edit", maxlen=1024, default="", options={'HIDDEN'})
@@ -702,7 +745,12 @@ class WM_OT_properties_edit(bpy.types.Operator):
data_path = self.data_path
value = self.value
prop = self.property
- prop_old = self._last_prop[0]
+
+ prop_old = getattr(self, "_last_prop", [None])[0]
+
+ if prop_old is None:
+ self.report({'ERROR'}, "Direct execution not supported")
+ return {'CANCELLED'}
try:
value_eval = eval(value)
@@ -734,10 +782,21 @@ class WM_OT_properties_edit(bpy.types.Operator):
prop_ui['description'] = self.description
+ # otherwise existing buttons which reference freed
+ # memory may crash blender [#26510]
+ # context.area.tag_redraw()
+ for win in context.window_manager.windows:
+ for area in win.screen.areas:
+ area.tag_redraw()
+
return {'FINISHED'}
def invoke(self, context, event):
+ if not self.data_path:
+ self.report({'ERROR'}, "Data path not set")
+ return {'CANCELLED'}
+
self._last_prop = [self.property]
item = eval("context.%s" % self.data_path)
@@ -779,6 +838,18 @@ class WM_OT_properties_add(bpy.types.Operator):
return {'FINISHED'}
+class WM_OT_properties_context_change(bpy.types.Operator):
+ "Change the context tab in a Properties Window"
+ bl_idname = "wm.properties_context_change"
+ bl_label = ""
+
+ context = StringProperty(name="Context", maxlen=32)
+
+ def execute(self, context):
+ context.space_data.context = (self.context)
+ return {'FINISHED'}
+
+
class WM_OT_properties_remove(bpy.types.Operator):
'''Internal use (edit a property data_path)'''
bl_idname = "wm.properties_remove"
@@ -804,6 +875,41 @@ class WM_OT_keyconfig_activate(bpy.types.Operator):
return {'FINISHED'}
+class WM_OT_appconfig_default(bpy.types.Operator):
+ bl_idname = "wm.appconfig_default"
+ bl_label = "Default Application Configuration"
+
+ def execute(self, context):
+ import os
+
+ context.window_manager.keyconfigs.active = context.window_manager.keyconfigs.default
+
+ filepath = os.path.join(bpy.utils.preset_paths("interaction")[0], "blender.py")
+
+ if os.path.exists(filepath):
+ bpy.ops.script.execute_preset(filepath=filepath, menu_idname="USERPREF_MT_interaction_presets")
+
+ return {'FINISHED'}
+
+
+class WM_OT_appconfig_activate(bpy.types.Operator):
+ bl_idname = "wm.appconfig_activate"
+ bl_label = "Activate Application Configuration"
+
+ filepath = StringProperty(name="File Path", maxlen=1024)
+
+ def execute(self, context):
+ import os
+ bpy.utils.keyconfig_set(self.filepath)
+
+ filepath = self.filepath.replace("keyconfig", "interaction")
+
+ if os.path.exists(filepath):
+ bpy.ops.script.execute_preset(filepath=filepath, menu_idname="USERPREF_MT_interaction_presets")
+
+ return {'FINISHED'}
+
+
class WM_OT_sysinfo(bpy.types.Operator):
'''Generate System Info'''
bl_idname = "wm.sysinfo"
@@ -815,12 +921,92 @@ class WM_OT_sysinfo(bpy.types.Operator):
return {'FINISHED'}
-def register():
- bpy.utils.register_module(__name__)
+class WM_OT_copy_prev_settings(bpy.types.Operator):
+ '''Copy settings from previous version'''
+ bl_idname = "wm.copy_prev_settings"
+ bl_label = "Copy Previous Settings"
+
+ def execute(self, context):
+ import os
+ import shutil
+ ver = bpy.app.version
+ ver_old = ((ver[0] * 100) + ver[1]) - 1
+ path_src = bpy.utils.resource_path('USER', ver_old // 100, ver_old % 100)
+ path_dst = bpy.utils.resource_path('USER')
+
+ if os.path.isdir(path_dst):
+ self.report({'ERROR'}, "Target path %r exists" % path_dst)
+ elif not os.path.isdir(path_src):
+ self.report({'ERROR'}, "Source path %r exists" % path_src)
+ else:
+ shutil.copytree(path_src, path_dst)
+ # dont loose users work if they open the splash later.
+ if bpy.data.is_saved is bpy.data.is_dirty is False:
+ bpy.ops.wm.read_homefile()
+ else:
+ self.report({'INFO'}, "Reload Start-Up file to restore settings.")
+ 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]
-def unregister():
- bpy.utils.unregister_module(__name__)
+ cmdline = [self.name] + raise_opt + args
-if __name__ == "__main__":
- register()
+ 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
new file mode 100644
index 00000000000..5c565fbd300
--- /dev/null
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -0,0 +1,121 @@
+# ##### 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>
+
+# note, properties_animviz is a helper module only.
+
+if "bpy" in locals():
+ from imp import reload as _reload
+ for val in _modules_loaded.values():
+ _reload(val)
+_modules = (
+ "properties_animviz",
+ "properties_data_armature",
+ "properties_data_bone",
+ "properties_data_camera",
+ "properties_data_curve",
+ "properties_data_empty",
+ "properties_data_lamp",
+ "properties_data_lattice",
+ "properties_data_mesh",
+ "properties_data_metaball",
+ "properties_data_modifier",
+ "properties_game",
+ "properties_material",
+ "properties_object_constraint",
+ "properties_object",
+ "properties_particle",
+ "properties_physics_cloth",
+ "properties_physics_common",
+ "properties_physics_field",
+ "properties_physics_fluid",
+ "properties_physics_smoke",
+ "properties_physics_softbody",
+ "properties_render",
+ "properties_scene",
+ "properties_texture",
+ "properties_world",
+ "space_console",
+ "space_dopesheet",
+ "space_filebrowser",
+ "space_graph",
+ "space_image",
+ "space_info",
+ "space_logic",
+ "space_nla",
+ "space_node",
+ "space_outliner",
+ "space_sequencer",
+ "space_text",
+ "space_time",
+ "space_userpref_keymap",
+ "space_userpref",
+ "space_view3d",
+ "space_view3d_toolbar",
+)
+__import__(name=__name__, fromlist=_modules)
+_namespace = globals()
+_modules_loaded = {name: _namespace[name] for name in _modules}
+del _namespace
+
+
+import bpy
+
+
+def register():
+ bpy.utils.register_module(__name__)
+
+ # space_userprefs.py
+ from bpy.props import StringProperty, EnumProperty
+ WindowManager = bpy.types.WindowManager
+
+ WindowManager.addon_search = StringProperty(name="Search", description="Search within the selected filter")
+ WindowManager.addon_filter = EnumProperty(
+ items=[('All', "All", ""),
+ ('Enabled', "Enabled", ""),
+ ('Disabled', "Disabled", ""),
+ ('3D View', "3D View", ""),
+ ('Add Curve', "Add Curve", ""),
+ ('Add Mesh', "Add Mesh", ""),
+ ('Animation', "Animation", ""),
+ ('Development', "Development", ""),
+ ('Game Engine', "Game Engine", ""),
+ ('Import-Export', "Import-Export", ""),
+ ('Mesh', "Mesh", ""),
+ ('Object', "Object", ""),
+ ('Render', "Render", ""),
+ ('Rigging', "Rigging", ""),
+ ('Text Editor', "Text Editor", ""),
+ ('System', "System", "")
+ ],
+ name="Category",
+ description="Filter add-ons by category",
+ )
+
+ WindowManager.addon_support = EnumProperty(
+ items=[('OFFICIAL', "Official", ""),
+ ('COMMUNITY', 'Community', ""),
+ ],
+ name="Support",
+ description="Display support level", default={'OFFICIAL', 'COMMUNITY'}, options={'ENUM_FLAG'})
+ # done...
+
+
+def unregister():
+ bpy.utils.unregister_module(__name__)
diff --git a/release/scripts/ui/properties_animviz.py b/release/scripts/startup/bl_ui/properties_animviz.py
index 5f5684f5c89..eb1bbfd2fb1 100644
--- a/release/scripts/ui/properties_animviz.py
+++ b/release/scripts/startup/bl_ui/properties_animviz.py
@@ -17,11 +17,13 @@
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
-import bpy
-
# Generic Panels (Independent of DataType)
+# NOTE:
+# The specialised panel types are derived in their respective UI modules
+# dont register these classes since they are only helpers.
+
class MotionPathButtonsPanel():
bl_space_type = 'PROPERTIES'
@@ -91,16 +93,5 @@ class OnionSkinButtonsPanel():
col.label(text="Display:")
col.prop(arm, "show_only_ghost_selected", text="Selected Only")
-
-# NOTE:
-# The specialised panel types are derived in their respective UI modules
-# dont register these classes since they are only helpers.
-def register():
- pass # bpy.utils.register_module(__name__)
-
-
-def unregister():
- pass # bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
+if __name__ == "__main__": # only for live edit.
+ bpy.utils.register_module(__name__)
diff --git a/release/scripts/ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index 6550e1bb1ed..9477dc866ab 100644
--- a/release/scripts/ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -58,24 +58,17 @@ class DATA_PT_skeleton(ArmatureButtonsPanel, bpy.types.Panel):
layout.prop(arm, "pose_position", expand=True)
- split = layout.split()
-
- col = split.column()
+ col = layout.column()
col.label(text="Layers:")
col.prop(arm, "layers", text="")
col.label(text="Protected Layers:")
col.prop(arm, "layers_protected", text="")
- col.label(text="Deform:")
-
- split = layout.split()
-
- col = split.column()
- col.prop(arm, "use_deform_vertex_groups", text="Vertex Groups")
- col.prop(arm, "use_deform_envelopes", text="Envelopes")
-
- col = split.column()
- col.prop(arm, "use_deform_preserve_volume", text="Quaternion")
+ layout.label(text="Deform:")
+ flow = layout.column_flow()
+ flow.prop(arm, "use_deform_vertex_groups", text="Vertex Groups")
+ flow.prop(arm, "use_deform_envelopes", text="Envelopes")
+ flow.prop(arm, "use_deform_preserve_volume", text="Quaternion")
class DATA_PT_display(ArmatureButtonsPanel, bpy.types.Panel):
@@ -87,7 +80,7 @@ class DATA_PT_display(ArmatureButtonsPanel, bpy.types.Panel):
ob = context.object
arm = context.armature
- layout.row().prop(arm, "draw_type", expand=True)
+ layout.prop(arm, "draw_type", expand=True)
split = layout.split()
@@ -137,10 +130,10 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, bpy.types.Panel):
col.prop(group, "color_set")
if group.color_set:
col = split.column()
- subrow = col.row(align=True)
- subrow.prop(group.colors, "normal", text="")
- subrow.prop(group.colors, "select", text="")
- subrow.prop(group.colors, "active", text="")
+ sub = col.row(align=True)
+ sub.prop(group.colors, "normal", text="")
+ sub.prop(group.colors, "select", text="")
+ sub.prop(group.colors, "active", text="")
row = layout.row()
row.active = (ob.proxy is None)
@@ -154,6 +147,44 @@ 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):
+ bl_label = "Pose Library"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.object and context.object.type == 'ARMATURE' and context.object.pose)
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ poselib = ob.pose_library
+
+ layout.template_ID(ob, "pose_library", new="poselib.new", unlink="poselib.unlink")
+
+ if poselib:
+ row = layout.row()
+ row.template_list(poselib, "pose_markers", poselib.pose_markers, "active_index", rows=5)
+
+ col = row.column(align=True)
+ col.active = (poselib.library is None)
+
+ # invoke should still be used for 'add', as it is needed to allow
+ # add/replace options to be used properly
+ col.operator("poselib.pose_add", icon='ZOOMIN', text="")
+
+ col.operator_context = 'EXEC_DEFAULT' # exec not invoke, so that menu doesn't need showing
+
+ pose_marker_active = poselib.pose_markers.active
+
+ 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")
+
+
# TODO: this panel will soon be depreceated too
class DATA_PT_ghost(ArmatureButtonsPanel, bpy.types.Panel):
bl_label = "Ghost"
@@ -167,16 +198,15 @@ class DATA_PT_ghost(ArmatureButtonsPanel, bpy.types.Panel):
split = layout.split()
- col = split.column()
+ col = split.column(align=True)
- sub = col.column(align=True)
if arm.ghost_type == 'RANGE':
- sub.prop(arm, "ghost_frame_start", text="Start")
- sub.prop(arm, "ghost_frame_end", text="End")
- sub.prop(arm, "ghost_size", text="Step")
+ col.prop(arm, "ghost_frame_start", text="Start")
+ col.prop(arm, "ghost_frame_end", text="End")
+ col.prop(arm, "ghost_size", text="Step")
elif arm.ghost_type == 'CURRENT_FRAME':
- sub.prop(arm, "ghost_step", text="Range")
- sub.prop(arm, "ghost_size", text="Step")
+ col.prop(arm, "ghost_step", text="Range")
+ col.prop(arm, "ghost_size", text="Step")
col = split.column()
col.label(text="Display:")
@@ -196,11 +226,9 @@ class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, bpy.types.Panel):
layout = self.layout
ob = context.object
-
itasc = ob.pose.ik_param
- row = layout.row()
- row.prop(ob.pose, "ik_solver")
+ layout.prop(ob.pose, "ik_solver")
if itasc:
layout.prop(itasc, "mode", expand=True)
@@ -209,13 +237,10 @@ class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, bpy.types.Panel):
layout.label(text="Reiteration:")
layout.prop(itasc, "reiteration_method", expand=True)
- split = layout.split()
- split.active = not simulation or itasc.reiteration_method != 'NEVER'
- col = split.column()
- col.prop(itasc, "precision")
-
- col = split.column()
- col.prop(itasc, "iterations")
+ row = layout.row()
+ row.active = not simulation or itasc.reiteration_method != 'NEVER'
+ row.prop(itasc, "precision")
+ row.prop(itasc, "iterations")
if simulation:
layout.prop(itasc, "use_auto_step")
@@ -235,7 +260,10 @@ class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, bpy.types.Panel):
row.prop(itasc, "damping_max", text="Damp", slider=True)
row.prop(itasc, "damping_epsilon", text="Eps", slider=True)
-from properties_animviz import MotionPathButtonsPanel, OnionSkinButtonsPanel
+from bl_ui.properties_animviz import (
+ MotionPathButtonsPanel,
+ OnionSkinButtonsPanel,
+ )
class DATA_PT_motion_paths(MotionPathButtonsPanel, bpy.types.Panel):
@@ -257,12 +285,8 @@ class DATA_PT_motion_paths(MotionPathButtonsPanel, bpy.types.Panel):
layout.separator()
split = layout.split()
-
- col = split.column()
- col.operator("pose.paths_calculate", text="Calculate Paths")
-
- col = split.column()
- col.operator("pose.paths_clear", text="Clear Paths")
+ split.operator("pose.paths_calculate", text="Calculate Paths")
+ split.operator("pose.paths_clear", text="Clear Paths")
class DATA_PT_onion_skinning(OnionSkinButtonsPanel): # , bpy.types.Panel): # inherit from panel when ready
@@ -287,13 +311,5 @@ class DATA_PT_custom_props_arm(ArmatureButtonsPanel, PropertyPanel, bpy.types.Pa
_context_path = "object.data"
_property_type = bpy.types.Armature
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py
index feca4fc2502..9fc055e9343 100644
--- a/release/scripts/ui/properties_data_bone.py
+++ b/release/scripts/startup/bl_ui/properties_data_bone.py
@@ -17,6 +17,7 @@
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
+
import bpy
from rna_prop_ui import PropertyPanel
@@ -123,7 +124,7 @@ class BONE_PT_transform_locks(BoneButtonsPanel, bpy.types.Panel):
col.active = not (bone.parent and bone.use_connect)
col = row.column()
- if pchan.rotation_mode in ('QUATERNION', 'AXIS_ANGLE'):
+ if pchan.rotation_mode in {'QUATERNION', 'AXIS_ANGLE'}:
col.prop(pchan, "lock_rotations_4d", text="Lock Rotation")
if pchan.lock_rotations_4d:
col.prop(pchan, "lock_rotation_w", text="W")
@@ -368,13 +369,5 @@ class BONE_PT_custom_props(BoneButtonsPanel, PropertyPanel, bpy.types.Panel):
else:
return "active_bone"
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py
index 0f5d4a59bf5..e5076fd20d5 100644
--- a/release/scripts/ui/properties_data_camera.py
+++ b/release/scripts/startup/bl_ui/properties_data_camera.py
@@ -78,7 +78,14 @@ class DATA_PT_camera(CameraButtonsPanel, bpy.types.Panel):
elif cam.type == 'ORTHO':
col.prop(cam, "ortho_scale")
- layout.prop(cam, "use_panorama")
+ col = layout.column()
+ if cam.type == 'ORTHO':
+ if cam.use_panorama:
+ col.alert = True
+ else:
+ col.enabled = False
+
+ col.prop(cam, "use_panorama")
split = layout.split()
@@ -95,9 +102,7 @@ class DATA_PT_camera(CameraButtonsPanel, bpy.types.Panel):
layout.label(text="Depth of Field:")
split = layout.split()
-
- col = split.column()
- col.prop(cam, "dof_object", text="")
+ split.prop(cam, "dof_object", text="")
col = split.column()
@@ -137,13 +142,5 @@ class DATA_PT_custom_props_camera(CameraButtonsPanel, PropertyPanel, bpy.types.P
_context_path = "object.data"
_property_type = bpy.types.Camera
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index b26b7140fd2..623daffac93 100644
--- a/release/scripts/ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -28,7 +28,7 @@ class CurveButtonsPanel():
@classmethod
def poll(cls, context):
- return (context.object and context.object.type in ('CURVE', 'SURFACE', 'FONT') and context.curve)
+ return (context.object and context.object.type in {'CURVE', 'SURFACE', 'FONT'} and context.curve)
class CurveButtonsPanelCurve(CurveButtonsPanel):
@@ -106,12 +106,12 @@ class DATA_PT_shape_curve(CurveButtonsPanel, bpy.types.Panel):
sub.prop(curve, "render_resolution_v", text="Render V")
if (is_curve or is_text):
+ col.label(text="Fill:")
sub = col.column()
sub.active = (curve.bevel_object is None)
- sub.label(text="Fill:")
sub.prop(curve, "use_fill_front")
sub.prop(curve, "use_fill_back")
- sub.prop(curve, "use_fill_deform", text="Fill Deformed")
+ col.prop(curve, "use_fill_deform", text="Fill Deformed")
col.label(text="Textures:")
col.prop(curve, "use_uv_as_generated")
@@ -312,12 +312,9 @@ class DATA_PT_font(CurveButtonsPanel, bpy.types.Panel):
col.prop(char, "use_italic")
col.prop(char, "use_underline")
- split = layout.split()
- col = split.column()
- col.prop(text, "small_caps_scale", text="Small Caps")
-
- col = split.column()
- col.prop(char, "use_small_caps")
+ row = layout.row()
+ row.prop(text, "small_caps_scale", text="Small Caps")
+ row.prop(char, "use_small_caps")
class DATA_PT_paragraph(CurveButtonsPanel, bpy.types.Panel):
@@ -394,13 +391,5 @@ class DATA_PT_custom_props_curve(CurveButtonsPanel, PropertyPanel, bpy.types.Pan
_context_path = "object.data"
_property_type = bpy.types.Curve
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py
index bb0028efec5..e46cd1270ad 100644
--- a/release/scripts/ui/properties_data_empty.py
+++ b/release/scripts/startup/bl_ui/properties_data_empty.py
@@ -39,16 +39,7 @@ class DATA_PT_empty(DataButtonsPanel, bpy.types.Panel):
ob = context.object
layout.prop(ob, "empty_draw_type", text="Display")
-
layout.prop(ob, "empty_draw_size", text="Size")
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_data_lamp.py b/release/scripts/startup/bl_ui/properties_data_lamp.py
index 55781434763..36010c8b511 100644
--- a/release/scripts/ui/properties_data_lamp.py
+++ b/release/scripts/startup/bl_ui/properties_data_lamp.py
@@ -91,7 +91,7 @@ class DATA_PT_lamp(DataButtonsPanel, bpy.types.Panel):
sub.prop(lamp, "color", text="")
sub.prop(lamp, "energy")
- if lamp.type in ('POINT', 'SPOT'):
+ if lamp.type in {'POINT', 'SPOT'}:
sub.label(text="Falloff:")
sub.prop(lamp, "falloff_type", text="")
sub.prop(lamp, "distance")
@@ -195,7 +195,7 @@ class DATA_PT_shadow(DataButtonsPanel, bpy.types.Panel):
def poll(cls, context):
lamp = context.lamp
engine = context.scene.render.engine
- return (lamp and lamp.type in ('POINT', 'SUN', 'SPOT', 'AREA')) and (engine in cls.COMPAT_ENGINES)
+ return (lamp and lamp.type in {'POINT', 'SUN', 'SPOT', 'AREA'}) and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -234,7 +234,7 @@ class DATA_PT_shadow(DataButtonsPanel, bpy.types.Panel):
col = split.column()
col.label(text="Sampling:")
- if lamp.type in ('POINT', 'SUN', 'SPOT'):
+ if lamp.type in {'POINT', 'SUN', 'SPOT'}:
sub = col.row()
sub.prop(lamp, "shadow_ray_samples", text="Samples")
@@ -251,26 +251,21 @@ class DATA_PT_shadow(DataButtonsPanel, bpy.types.Panel):
col.row().prop(lamp, "shadow_ray_sample_method", expand=True)
- split = layout.split()
- col = split.column()
-
if lamp.shadow_ray_sample_method == 'ADAPTIVE_QMC':
- col.prop(lamp, "shadow_adaptive_threshold", text="Threshold")
- col = split.column()
+ layout.prop(lamp, "shadow_adaptive_threshold", text="Threshold")
if lamp.type == 'AREA' and lamp.shadow_ray_sample_method == 'CONSTANT_JITTERED':
- col = split.column()
- col = split.column()
- col.prop(lamp, "use_umbra")
- col.prop(lamp, "use_dither")
- col.prop(lamp, "use_jitter")
+ row = layout.row()
+ row.prop(lamp, "use_umbra")
+ row.prop(lamp, "use_dither")
+ row.prop(lamp, "use_jitter")
elif lamp.shadow_method == 'BUFFER_SHADOW':
col = layout.column()
col.label(text="Buffer Type:")
col.row().prop(lamp, "shadow_buffer_type", expand=True)
- if lamp.shadow_buffer_type in ('REGULAR', 'HALFWAY', 'DEEP'):
+ if lamp.shadow_buffer_type in {'REGULAR', 'HALFWAY', 'DEEP'}:
split = layout.split()
col = split.column()
@@ -318,13 +313,11 @@ class DATA_PT_area(DataButtonsPanel, bpy.types.Panel):
return (lamp and lamp.type == 'AREA') and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
- lamp = context.lamp
-
layout = self.layout
- split = layout.split()
- col = split.column()
+ lamp = context.lamp
+ col = layout.column()
col.row().prop(lamp, "shape", expand=True)
sub = col.row(align=True)
@@ -379,7 +372,7 @@ class DATA_PT_falloff_curve(DataButtonsPanel, bpy.types.Panel):
lamp = context.lamp
engine = context.scene.render.engine
- return (lamp and lamp.type in ('POINT', 'SPOT') and lamp.falloff_type == 'CUSTOM_CURVE') and (engine in cls.COMPAT_ENGINES)
+ return (lamp and lamp.type in {'POINT', 'SPOT'} and lamp.falloff_type == 'CUSTOM_CURVE') and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
lamp = context.lamp
@@ -392,13 +385,5 @@ class DATA_PT_custom_props_lamp(DataButtonsPanel, PropertyPanel, bpy.types.Panel
_context_path = "object.data"
_property_type = bpy.types.Lamp
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_data_lattice.py b/release/scripts/startup/bl_ui/properties_data_lattice.py
index 6bdb36d3520..cd719b6fe84 100644
--- a/release/scripts/ui/properties_data_lattice.py
+++ b/release/scripts/startup/bl_ui/properties_data_lattice.py
@@ -59,23 +59,17 @@ class DATA_PT_lattice(DataButtonsPanel, bpy.types.Panel):
lat = context.lattice
- split = layout.split()
- col = split.column()
- col.prop(lat, "points_u")
- col = split.column()
- col.prop(lat, "interpolation_type_u", text="")
-
- split = layout.split()
- col = split.column()
- col.prop(lat, "points_v")
- col = split.column()
- col.prop(lat, "interpolation_type_v", text="")
-
- split = layout.split()
- col = split.column()
- col.prop(lat, "points_w")
- col = split.column()
- col.prop(lat, "interpolation_type_w", text="")
+ row = layout.row()
+ row.prop(lat, "points_u")
+ row.prop(lat, "interpolation_type_u", text="")
+
+ row = layout.row()
+ row.prop(lat, "points_v")
+ row.prop(lat, "interpolation_type_v", text="")
+
+ row = layout.row()
+ row.prop(lat, "points_w")
+ row.prop(lat, "interpolation_type_w", text="")
row = layout.row()
row.prop(lat, "use_outside")
@@ -87,13 +81,5 @@ class DATA_PT_custom_props_lattice(DataButtonsPanel, PropertyPanel, bpy.types.Pa
_context_path = "object.data"
_property_type = bpy.types.Lattice
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index 342204d0e78..b1d1789fadd 100644
--- a/release/scripts/ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -94,9 +94,7 @@ class DATA_PT_normals(MeshButtonsPanel, bpy.types.Panel):
sub.active = mesh.use_auto_smooth
sub.prop(mesh, "auto_smooth_angle", text="Angle")
- col = split.column()
-
- col.prop(mesh, "show_double_sided")
+ split.prop(mesh, "show_double_sided")
class DATA_PT_settings(MeshButtonsPanel, bpy.types.Panel):
@@ -120,7 +118,7 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, bpy.types.Panel):
def poll(cls, context):
engine = context.scene.render.engine
obj = context.object
- return (obj and obj.type in ('MESH', 'LATTICE') and (engine in cls.COMPAT_ENGINES))
+ return (obj and obj.type in {'MESH', 'LATTICE'} and (engine in cls.COMPAT_ENGINES))
def draw(self, context):
layout = self.layout
@@ -169,7 +167,7 @@ class DATA_PT_shape_keys(MeshButtonsPanel, bpy.types.Panel):
def poll(cls, context):
engine = context.scene.render.engine
obj = context.object
- return (obj and obj.type in ('MESH', 'LATTICE', 'CURVE', 'SURFACE') and (engine in cls.COMPAT_ENGINES))
+ return (obj and obj.type in {'MESH', 'LATTICE', 'CURVE', 'SURFACE'} and (engine in cls.COMPAT_ENGINES))
def draw(self, context):
layout = self.layout
@@ -190,7 +188,7 @@ class DATA_PT_shape_keys(MeshButtonsPanel, bpy.types.Panel):
rows = 2
if kb:
rows = 5
- row.template_list(key, "keys", ob, "active_shape_key_index", rows=rows)
+ row.template_list(key, "key_blocks", ob, "active_shape_key_index", rows=rows)
col = row.column()
@@ -245,7 +243,7 @@ class DATA_PT_shape_keys(MeshButtonsPanel, bpy.types.Panel):
col.active = enable_edit_value
col.label(text="Blend:")
col.prop_search(kb, "vertex_group", ob, "vertex_groups", text="")
- col.prop_search(kb, "relative_key", key, "keys", text="")
+ col.prop_search(kb, "relative_key", key, "key_blocks", text="")
else:
row = layout.row()
@@ -283,7 +281,6 @@ class DATA_PT_texface(MeshButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
ob = context.active_object
- rd = context.scene.render
return (context.mode == 'EDIT_MESH') and ob and ob.type == 'MESH'
@@ -353,13 +350,5 @@ class DATA_PT_custom_props_mesh(MeshButtonsPanel, PropertyPanel, bpy.types.Panel
_context_path = "object.data"
_property_type = bpy.types.Mesh
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_data_metaball.py b/release/scripts/startup/bl_ui/properties_data_metaball.py
index cf7aa8c08fd..81ba15d6f40 100644
--- a/release/scripts/ui/properties_data_metaball.py
+++ b/release/scripts/startup/bl_ui/properties_data_metaball.py
@@ -96,7 +96,7 @@ class DATA_PT_metaball_element(DataButtonsPanel, bpy.types.Panel):
col = split.column(align=True)
- if metaelem.type in ('CUBE', 'ELLIPSOID'):
+ if metaelem.type in {'CUBE', 'ELLIPSOID'}:
col.label(text="Size:")
col.prop(metaelem, "size_x", text="X")
col.prop(metaelem, "size_y", text="Y")
@@ -117,13 +117,5 @@ class DATA_PT_custom_props_metaball(DataButtonsPanel, PropertyPanel, bpy.types.P
_context_path = "object.data"
_property_type = bpy.types.MetaBall
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index f17cd8a4b98..95db7d216fb 100644
--- a/release/scripts/ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -59,16 +59,15 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.prop(md, "use_vertex_groups", text="Vertex Groups")
col.prop(md, "use_bone_envelopes", text="Bone Envelopes")
- split = layout.split()
+ layout.separator()
- col = split.split()
- col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
- sub = col.column()
+ row = layout.row()
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ sub = row.row()
sub.active = bool(md.vertex_group)
sub.prop(md, "invert_vertex_group")
- col = layout.column()
- col.prop(md, "use_multi_modifier")
+ layout.prop(md, "use_multi_modifier")
def ARRAY(self, layout, ob, md):
layout.prop(md, "fit_type")
@@ -113,18 +112,14 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
layout.separator()
- col = layout.column()
- col.prop(md, "start_cap")
- col.prop(md, "end_cap")
+ layout.prop(md, "start_cap")
+ layout.prop(md, "end_cap")
def BEVEL(self, layout, ob, md):
split = layout.split()
- col = split.column()
- col.prop(md, "width")
-
- col = split.column()
- col.prop(md, "use_only_vertices")
+ split.prop(md, "width")
+ split.prop(md, "use_only_vertices")
layout.label(text="Limit Method:")
layout.row().prop(md, "limit_method", expand=True)
@@ -188,10 +183,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.prop(md, "use_transform")
def CLOTH(self, layout, ob, md):
- layout.label(text="See Cloth panel.")
+ layout.label(text="Settings can be found inside the Physics context")
def COLLISION(self, layout, ob, md):
- layout.label(text="See Collision panel.")
+ layout.label(text="Settings can be found inside the Physics context")
def CURVE(self, layout, ob, md):
split = layout.split()
@@ -214,7 +209,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col = split.column()
col.label(text="Texture:")
- col.prop(md, "texture", text="")
+ col.template_ID(md, "texture", new="texture.new")
col.label(text="Vertex Group:")
col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
@@ -230,13 +225,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
layout.separator()
- split = layout.split()
-
- col = split.column()
- col.prop(md, "mid_level")
-
- col = split.column()
- col.prop(md, "strength")
+ row = layout.row()
+ row.prop(md, "mid_level")
+ row.prop(md, "strength")
def EDGE_SPLIT(self, layout, ob, md):
split = layout.split()
@@ -247,8 +238,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
sub.active = md.use_edge_angle
sub.prop(md, "split_angle")
- col = split.column()
- col.prop(md, "use_edge_sharp", text="Sharp Edges")
+ split.prop(md, "use_edge_sharp", text="Sharp Edges")
def EXPLODE(self, layout, ob, md):
split = layout.split()
@@ -259,9 +249,11 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
sub = col.column()
sub.active = bool(md.vertex_group)
sub.prop(md, "protect")
+ col.label(text="Particle UV")
+ col.prop_search(md, "particle_uv", ob.data, "uv_textures", text="")
col = split.column()
- col.prop(md, "use_edge_split")
+ col.prop(md, "use_edge_cut")
col.prop(md, "show_unborn")
col.prop(md, "show_alive")
col.prop(md, "show_dead")
@@ -270,7 +262,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
layout.operator("object.explode_refresh", text="Refresh")
def FLUID_SIMULATION(self, layout, ob, md):
- layout.label(text="See Fluid panel.")
+ layout.label(text="Settings can be found inside the Physics context")
def HOOK(self, layout, ob, md):
split = layout.split()
@@ -334,6 +326,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
def MESH_DEFORM(self, layout, ob, md):
split = layout.split()
+
col = split.column()
sub = col.column()
sub.label(text="Object:")
@@ -354,13 +347,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
else:
layout.operator("object.meshdeform_bind", text="Bind")
- split = layout.split()
-
- col = split.column()
- col.prop(md, "precision")
-
- col = split.column()
- col.prop(md, "use_dynamic_bind")
+ row = layout.row()
+ row.prop(md, "precision")
+ row.prop(md, "use_dynamic_bind")
def MIRROR(self, layout, ob, md):
split = layout.split(percentage=0.25)
@@ -383,7 +372,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.prop(md, "use_mirror_v", text="V")
col = layout.column()
-
+
if md.use_mirror_merge == True:
col.prop(md, "merge_threshold")
col.label(text="Mirror Object:")
@@ -393,9 +382,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
split = layout.split()
if ob.mode == 'EDIT':
col = split.column()
- col.operator("object.assign_navpolygon", text="Assign poly idx")
- col = split.column()
- col.operator("object.assign_new_navpolygon", text="Assign new poly idx")
+ col.operator("object.assign_navpolygon", text="Assign poly idx")
+ col = split.column()
+ col.operator("object.assign_new_navpolygon", text="Assign new poly idx")
def MULTIRES(self, layout, ob, md):
layout.row().prop(md, "subdivision_type", expand=True)
@@ -460,7 +449,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.prop(md, "random_position", text="Random", slider=True)
def PARTICLE_SYSTEM(self, layout, ob, md):
- layout.label(text="See Particle panel.")
+ layout.label(text="Settings can be found inside the Particle context")
def SCREW(self, layout, ob, md):
split = layout.split()
@@ -520,8 +509,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col = split.column()
col.label(text="Cull Faces:")
- col.prop(md, "use_cull_front_faces", text="Front")
- col.prop(md, "use_cull_back_faces", text="Back")
+ col.prop(md, "cull_face", expand=True)
layout.label(text="Auxiliary Target:")
layout.prop(md, "auxiliary_target", text="")
@@ -553,12 +541,12 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.label(text="Deform:")
col.prop(md, "factor")
col.prop(md, "limits", slider=True)
- if md.deform_method in ('TAPER', 'STRETCH'):
+ if md.deform_method in {'TAPER', 'STRETCH'}:
col.prop(md, "lock_x")
col.prop(md, "lock_y")
def SMOKE(self, layout, ob, md):
- layout.label(text="See Smoke panel.")
+ layout.label(text="Settings can be found inside the Physics context")
def SMOOTH(self, layout, ob, md):
split = layout.split(percentage=0.25)
@@ -576,10 +564,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
def SOFT_BODY(self, layout, ob, md):
- layout.label(text="See Soft Body panel.")
+ layout.label(text="Settings can be found inside the Physics context")
def SOLIDIFY(self, layout, ob, md):
-
split = layout.split()
col = split.column()
@@ -590,21 +577,26 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.prop(md, "edge_crease_inner", text="Inner")
col.prop(md, "edge_crease_outer", text="Outer")
col.prop(md, "edge_crease_rim", text="Rim")
+ col.label(text="Material Index Offset:")
col = split.column()
col.prop(md, "offset")
- colsub = col.column()
- colsub.active = bool(md.vertex_group)
- colsub.prop(md, "invert_vertex_group", text="Invert")
+ sub = col.column()
+ sub.active = bool(md.vertex_group)
+ sub.prop(md, "invert_vertex_group", text="Invert")
col.prop(md, "use_even_offset")
col.prop(md, "use_quality_normals")
-
col.prop(md, "use_rim")
- colsub = col.column()
- colsub.active = md.use_rim
- colsub.prop(md, "use_rim_material")
+
+ sub = col.column()
+ sub.label()
+ row = sub.split(align=True, percentage=0.4)
+ row.prop(md, "material_offset", text="")
+ row = row.row()
+ row.active = md.use_rim
+ row.prop(md, "material_offset_rim", text="Rim")
def SUBSURF(self, layout, ob, md):
layout.row().prop(md, "subdivision_type", expand=True)
@@ -621,7 +613,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.prop(md, "show_only_control_edges")
def SURFACE(self, layout, ob, md):
- layout.label(text="See Fields panel.")
+ layout.label(text="Settings can be found inside the Physics context")
def UV_PROJECT(self, layout, ob, md):
if ob.type == 'MESH':
@@ -651,6 +643,48 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
sub.prop(md, "scale_x", text="Scale X")
sub.prop(md, "scale_y", text="Scale Y")
+ def WARP(self, layout, ob, md):
+ use_falloff = (md.falloff_type != 'NONE')
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="From:")
+ col.prop(md, "object_from", text="")
+
+ col.prop(md, "use_volume_preserve")
+
+ col = split.column()
+ col.label(text="To:")
+ col.prop(md, "object_to", text="")
+ col.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+
+ col = layout.column()
+
+ row = col.row(align=True)
+ row.prop(md, "strength")
+ if use_falloff:
+ row.prop(md, "falloff_radius")
+
+ col.prop(md, "falloff_type")
+ if use_falloff:
+ if md.falloff_type == 'CURVE':
+ col.template_curve_mapping(md, "falloff_curve")
+
+ # 2 new columns
+ split = layout.split()
+ col = split.column()
+ col.label(text="Texture:")
+ col.prop(md, "texture", text="")
+
+ col = split.column()
+ col.label(text="Texture Coordinates:")
+ col.prop(md, "texture_coords", text="")
+
+ if md.texture_coords == 'OBJECT':
+ layout.prop(md, "texture_coordinate_object", text="Object")
+ elif md.texture_coords == 'UV' and ob.type == 'MESH':
+ layout.prop_search(md, "uv_layer", ob.data, "uv_textures")
+
def WAVE(self, layout, ob, md):
split = layout.split()
@@ -688,7 +722,11 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
layout.prop(md, "start_position_object")
layout.prop_search(md, "vertex_group", ob, "vertex_groups")
- layout.prop(md, "texture")
+ split = layout.split(percentage=0.33)
+ col = split.column()
+ col.label(text="Texture")
+ col = split.column()
+ col.template_ID(md, "texture", new="texture.new")
layout.prop(md, "texture_coords")
if md.texture_coords == 'MAP_UV' and ob.type == 'MESH':
layout.prop_search(md, "uv_layer", ob.data, "uv_textures")
@@ -707,13 +745,5 @@ class DATA_PT_modifiers(ModifierButtonsPanel, bpy.types.Panel):
col.prop(md, "width", slider=True)
col.prop(md, "narrowness", slider=True)
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_game.py b/release/scripts/startup/bl_ui/properties_game.py
index 60934891b7f..6952f3c31db 100644
--- a/release/scripts/ui/properties_game.py
+++ b/release/scripts/startup/bl_ui/properties_game.py
@@ -47,7 +47,7 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, bpy.types.Panel):
layout.separator()
#if game.physics_type == 'DYNAMIC':
- if game.physics_type in ('DYNAMIC', 'RIGID_BODY'):
+ if game.physics_type in {'DYNAMIC', 'RIGID_BODY'}:
split = layout.split()
col = split.column()
@@ -56,7 +56,7 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, bpy.types.Panel):
col.prop(ob, "hide_render", text="Invisible") # out of place but useful
col = split.column()
- col.prop(game, "use_material_physics")
+ col.prop(game, "use_material_physics_fh")
col.prop(game, "use_rotate_from_normal")
col.prop(game, "use_sleep")
@@ -163,7 +163,7 @@ class PHYSICS_PT_game_physics(PhysicsButtonsPanel, bpy.types.Panel):
subsub.active = game.use_anisotropic_friction
subsub.prop(game, "friction_coefficients", text="", slider=True)
- elif game.physics_type in ('SENSOR', 'INVISIBLE', 'NO_COLLISION', 'OCCLUDE'):
+ elif game.physics_type in {'SENSOR', 'INVISIBLE', 'NO_COLLISION', 'OCCLUDE'}:
layout.prop(ob, "hide_render", text="Invisible")
@@ -175,7 +175,7 @@ class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, bpy.types.Panel):
def poll(cls, context):
game = context.object.game
rd = context.scene.render
- return (game.physics_type in ('DYNAMIC', 'RIGID_BODY', 'SENSOR', 'SOFT_BODY', 'STATIC')) and (rd.engine in cls.COMPAT_ENGINES)
+ return (game.physics_type in {'DYNAMIC', 'RIGID_BODY', 'SENSOR', 'SOFT_BODY', 'STATIC'}) and (rd.engine in cls.COMPAT_ENGINES)
def draw_header(self, context):
game = context.active_object.game
@@ -190,18 +190,14 @@ class PHYSICS_PT_game_collision_bounds(PhysicsButtonsPanel, bpy.types.Panel):
layout.active = game.use_collision_bounds
layout.prop(game, "collision_bounds_type", text="Bounds")
- split = layout.split()
-
- col = split.column()
- col.prop(game, "collision_margin", text="Margin", slider=True)
-
- col = split.column()
- col.prop(game, "use_collision_compound", text="Compound")
+ row = layout.row()
+ row.prop(game, "collision_margin", text="Margin", slider=True)
+ row.prop(game, "use_collision_compound", text="Compound")
class PHYSICS_PT_game_obstacles(PhysicsButtonsPanel, bpy.types.Panel):
bl_label = "Create obstacle"
COMPAT_ENGINES = {'BLENDER_GAME'}
-
+
@classmethod
def poll(self, context):
game = context.object.game
@@ -222,7 +218,7 @@ class PHYSICS_PT_game_obstacles(PhysicsButtonsPanel, bpy.types.Panel):
split = layout.split()
col = split.column()
- col.prop(game, "obstacle_radius", text="Radius")
+ col.prop(game, "obstacle_radius", text="Radius")
class RenderButtonsPanel():
bl_space_type = 'PROPERTIES'
@@ -352,6 +348,7 @@ class RENDER_PT_game_shading(RenderButtonsPanel, bpy.types.Panel):
col.prop(gs, "use_glsl_lights", text="Lights")
col.prop(gs, "use_glsl_shaders", text="Shaders")
col.prop(gs, "use_glsl_shadows", text="Shadows")
+ col.prop(gs, "use_glsl_color_management", text="Color Management")
col = split.column()
col.prop(gs, "use_glsl_ramps", text="Ramps")
@@ -385,7 +382,7 @@ class RENDER_PT_game_display(RenderButtonsPanel, bpy.types.Panel):
flow.prop(gs, "show_framerate_profile", text="Framerate and Profile")
flow.prop(gs, "show_physics_visualization", text="Physics Visualization")
flow.prop(gs, "use_deprecation_warnings")
- flow.prop(gs, "show_mouse")
+ flow.prop(gs, "show_mouse", text="Mouse Cursor")
class RENDER_PT_game_sound(RenderButtonsPanel, bpy.types.Panel):
@@ -447,13 +444,9 @@ class WORLD_PT_game_world(WorldButtonsPanel, bpy.types.Panel):
world = context.world
- split = layout.split()
-
- col = split.column()
- col.prop(world, "horizon_color")
-
- col = split.column()
- col.prop(world, "ambient_color")
+ row = layout.row()
+ row.column().prop(world, "horizon_color")
+ row.column().prop(world, "ambient_color")
class WORLD_PT_game_mist(WorldButtonsPanel, bpy.types.Panel):
@@ -476,13 +469,10 @@ class WORLD_PT_game_mist(WorldButtonsPanel, bpy.types.Panel):
world = context.world
layout.active = world.mist_settings.use_mist
- split = layout.split()
-
- col = split.column()
- col.prop(world.mist_settings, "start")
- col = split.column()
- col.prop(world.mist_settings, "depth")
+ row = layout.row()
+ row.prop(world.mist_settings, "start")
+ row.prop(world.mist_settings, "depth")
class WORLD_PT_game_physics(WorldButtonsPanel, bpy.types.Panel):
@@ -547,12 +537,5 @@ class WORLD_PT_game_physics_obstacles(WorldButtonsPanel, bpy.types.Panel):
layout.prop(gs, "level_height")
layout.prop(gs, "show_obstacle_simulation")
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index 82c3e840420..52d6b5f1376 100644
--- a/release/scripts/ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -34,6 +34,22 @@ def active_node_mat(mat):
return None
+def check_material(mat):
+ if mat is not None:
+ if mat.use_nodes:
+ if mat.active_node_material is not None:
+ return True
+ return False
+ return True
+ return False
+
+
+def simple_material(mat):
+ if (mat is not None) and (not mat.use_nodes):
+ return True
+ return False
+
+
class MATERIAL_MT_sss_presets(bpy.types.Menu):
bl_label = "SSS Presets"
preset_subdir = "sss"
@@ -119,6 +135,13 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, bpy.types.Panel):
if mat:
layout.prop(mat, "type", expand=True)
+ if mat.use_nodes:
+ row = layout.row()
+ row.label(text="", icon='NODETREE')
+ if mat.active_node_material:
+ row.prop(mat.active_node_material, "name", text="")
+ else:
+ row.label(text="No material node selected")
class MATERIAL_PT_preview(MaterialButtonsPanel, bpy.types.Panel):
@@ -129,15 +152,64 @@ class MATERIAL_PT_preview(MaterialButtonsPanel, bpy.types.Panel):
self.layout.template_preview(context.material)
+class MATERIAL_PT_pipeline(MaterialButtonsPanel, bpy.types.Panel):
+ bl_label = "Render Pipeline Options"
+ bl_options = {'DEFAULT_CLOSED'}
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
+
+ @classmethod
+ def poll(cls, context):
+ mat = context.material
+ engine = context.scene.render.engine
+ return mat and (not simple_material(mat)) and (mat.type in {'SURFACE', 'WIRE', 'VOLUME'}) and (engine in cls.COMPAT_ENGINES)
+
+ def draw(self, context):
+ layout = self. layout
+
+ mat = context.material
+ mat_type = mat.type in {'SURFACE', 'WIRE'}
+
+ row = layout.row()
+ row.active = mat_type
+ 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()
+ row.active = mat.use_transparency or not mat_type
+ row.prop(mat, "transparency_method", expand=True)
+
+ layout.separator()
+
+ split = layout.split()
+ col = split.column()
+
+ col.prop(mat, "use_raytrace")
+ col.prop(mat, "use_full_oversampling")
+ sub = col.column()
+ sub.active = mat_type
+ sub.prop(mat, "use_sky")
+ sub.prop(mat, "invert_z")
+
+ col = split.column()
+ col.active = mat_type
+
+ col.prop(mat, "use_cast_shadows_only", text="Cast Only")
+ col.prop(mat, "shadow_cast_alpha", text="Casting Alpha")
+ col.prop(mat, "use_cast_buffer_shadows")
+ col.prop(mat, "use_cast_approximate")
+
+
class MATERIAL_PT_diffuse(MaterialButtonsPanel, bpy.types.Panel):
bl_label = "Diffuse"
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
@classmethod
def poll(cls, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render.engine
- return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in cls.COMPAT_ENGINES)
+ return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -164,36 +236,24 @@ class MATERIAL_PT_diffuse(MaterialButtonsPanel, bpy.types.Panel):
elif mat.diffuse_shader == 'MINNAERT':
col.prop(mat, "darkness")
elif mat.diffuse_shader == 'TOON':
- split = col.split()
-
- col = split.column()
- col.prop(mat, "diffuse_toon_size", text="Size")
-
- col = split.column()
- col.prop(mat, "diffuse_toon_smooth", text="Smooth")
+ row = col.row()
+ row.prop(mat, "diffuse_toon_size", text="Size")
+ row.prop(mat, "diffuse_toon_smooth", text="Smooth")
elif mat.diffuse_shader == 'FRESNEL':
- split = col.split()
-
- col = split.column()
- col.prop(mat, "diffuse_fresnel", text="Fresnel")
-
- col = split.column()
- col.prop(mat, "diffuse_fresnel_factor", text="Factor")
+ row = col.row()
+ row.prop(mat, "diffuse_fresnel", text="Fresnel")
+ 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()
- split = layout.split()
-
- col = split.column()
- col.prop(mat, "diffuse_ramp_input", text="Input")
-
- col = split.column()
- col.prop(mat, "diffuse_ramp_blend", text="Blend")
row = layout.row()
- row.prop(mat, "diffuse_ramp_factor", text="Factor")
+ row.prop(mat, "diffuse_ramp_input", text="Input")
+ row.prop(mat, "diffuse_ramp_blend", text="Blend")
+
+ layout.prop(mat, "diffuse_ramp_factor", text="Factor")
class MATERIAL_PT_specular(MaterialButtonsPanel, bpy.types.Panel):
@@ -202,9 +262,9 @@ class MATERIAL_PT_specular(MaterialButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render.engine
- return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in cls.COMPAT_ENGINES)
+ return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -224,41 +284,29 @@ class MATERIAL_PT_specular(MaterialButtonsPanel, bpy.types.Panel):
col.prop(mat, "use_specular_ramp", text="Ramp")
col = layout.column()
- if mat.specular_shader in ('COOKTORR', 'PHONG'):
+ if mat.specular_shader in {'COOKTORR', 'PHONG'}:
col.prop(mat, "specular_hardness", text="Hardness")
elif mat.specular_shader == 'BLINN':
- split = layout.split()
-
- col = split.column()
- col.prop(mat, "specular_hardness", text="Hardness")
-
- col = split.column()
- col.prop(mat, "specular_ior", text="IOR")
+ row = col.row()
+ row.prop(mat, "specular_hardness", text="Hardness")
+ row.prop(mat, "specular_ior", text="IOR")
elif mat.specular_shader == 'WARDISO':
col.prop(mat, "specular_slope", text="Slope")
elif mat.specular_shader == 'TOON':
- split = layout.split()
-
- col = split.column()
- col.prop(mat, "specular_toon_size", text="Size")
-
- col = split.column()
- col.prop(mat, "specular_toon_smooth", text="Smooth")
+ row = col.row()
+ row.prop(mat, "specular_toon_size", text="Size")
+ row.prop(mat, "specular_toon_smooth", text="Smooth")
if mat.use_specular_ramp:
layout.separator()
layout.template_color_ramp(mat, "specular_ramp", expand=True)
layout.separator()
- split = layout.split()
-
- col = split.column()
- col.prop(mat, "specular_ramp_input", text="Input")
-
- col = split.column()
- col.prop(mat, "specular_ramp_blend", text="Blend")
row = layout.row()
- row.prop(mat, "specular_ramp_factor", text="Factor")
+ row.prop(mat, "specular_ramp_input", text="Input")
+ row.prop(mat, "specular_ramp_blend", text="Blend")
+
+ layout.prop(mat, "specular_ramp_factor", text="Factor")
class MATERIAL_PT_shading(MaterialButtonsPanel, bpy.types.Panel):
@@ -267,16 +315,16 @@ class MATERIAL_PT_shading(MaterialButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render.engine
- return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in cls.COMPAT_ENGINES)
+ return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
mat = active_node_mat(context.material)
- if mat.type in ('SURFACE', 'WIRE'):
+ if mat.type in {'SURFACE', 'WIRE'}:
split = layout.split()
col = split.column()
@@ -297,36 +345,40 @@ class MATERIAL_PT_shading(MaterialButtonsPanel, bpy.types.Panel):
class MATERIAL_PT_transp(MaterialButtonsPanel, bpy.types.Panel):
bl_label = "Transparency"
- bl_options = {'DEFAULT_CLOSED'}
+ # bl_options = {'DEFAULT_CLOSED'}
COMPAT_ENGINES = {'BLENDER_RENDER'}
@classmethod
def poll(cls, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render.engine
- return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in cls.COMPAT_ENGINES)
+ return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
def draw_header(self, context):
- mat = active_node_mat(context.material)
+ mat = context.material
- self.layout.prop(mat, "use_transparency", text="")
+ if simple_material(mat):
+ self.layout.prop(mat, "use_transparency", text="")
def draw(self, context):
layout = self.layout
+ base_mat = context.material
mat = active_node_mat(context.material)
rayt = mat.raytrace_transparency
- row = layout.row()
- row.active = mat.use_transparency and (not mat.use_shadeless)
- row.prop(mat, "transparency_method", expand=True)
+ if simple_material(base_mat):
+ row = layout.row()
+ row.active = mat.use_transparency
+ row.prop(mat, "transparency_method", expand=True)
split = layout.split()
+ split.active = base_mat.use_transparency
col = split.column()
col.prop(mat, "alpha")
row = col.row()
- row.active = mat.use_transparency and (not mat.use_shadeless)
+ row.active = (base_mat.transparency_method != 'MASK') and (not mat.use_shadeless)
row.prop(mat, "specular_alpha", text="Specular")
col = split.column()
@@ -336,10 +388,10 @@ class MATERIAL_PT_transp(MaterialButtonsPanel, bpy.types.Panel):
sub.active = rayt.fresnel > 0
sub.prop(rayt, "fresnel_factor", text="Blend")
- if mat.transparency_method == 'RAYTRACE':
+ if base_mat.transparency_method == 'RAYTRACE':
layout.separator()
split = layout.split()
- split.active = mat.use_transparency
+ split.active = base_mat.use_transparency
col = split.column()
col.prop(rayt, "ior")
@@ -364,9 +416,9 @@ class MATERIAL_PT_mirror(MaterialButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render.engine
- return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in cls.COMPAT_ENGINES)
+ return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
def draw_header(self, context):
raym = active_node_mat(context.material).raytrace_mirror
@@ -422,9 +474,9 @@ class MATERIAL_PT_sss(MaterialButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render.engine
- return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in cls.COMPAT_ENGINES)
+ return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
def draw_header(self, context):
mat = active_node_mat(context.material)
@@ -497,6 +549,7 @@ class MATERIAL_PT_halo(MaterialButtonsPanel, bpy.types.Panel):
col = split.column()
col.prop(mat, "alpha")
col.prop(mat, "diffuse_color", text="")
+ col.prop(halo, "seed")
col = split.column()
col.prop(halo, "size")
@@ -568,16 +621,20 @@ class MATERIAL_PT_physics(MaterialButtonsPanel, bpy.types.Panel):
phys = context.material.physics # dont use node material
split = layout.split()
+ row = split.row()
+ row.prop(phys, "friction")
+ row.prop(phys, "elasticity", slider=True)
- col = split.column()
- col.prop(phys, "distance")
- col.prop(phys, "friction")
- col.prop(phys, "use_normal_align")
+ row = layout.row()
+ row.label(text="Force Field:")
- col = split.column()
- col.prop(phys, "force", slider=True)
- col.prop(phys, "elasticity", slider=True)
- col.prop(phys, "damping", slider=True)
+ row = layout.row()
+ row.prop(phys, "fh_force")
+ row.prop(phys, "fh_damping", slider=True)
+
+ row = layout.row()
+ row.prop(phys, "fh_distance")
+ row.prop(phys, "use_fh_normal")
class MATERIAL_PT_strand(MaterialButtonsPanel, bpy.types.Panel):
@@ -589,7 +646,7 @@ class MATERIAL_PT_strand(MaterialButtonsPanel, bpy.types.Panel):
def poll(cls, context):
mat = context.material
engine = context.scene.render.engine
- return mat and (mat.type in ('SURFACE', 'WIRE', 'HALO')) and (engine in cls.COMPAT_ENGINES)
+ return mat and (mat.type in {'SURFACE', 'WIRE', 'HALO'}) and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
@@ -633,26 +690,29 @@ class MATERIAL_PT_options(MaterialButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render.engine
- return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in cls.COMPAT_ENGINES)
+ return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
- mat = active_node_mat(context.material)
+ base_mat = context.material
+ mat = active_node_mat(base_mat)
split = layout.split()
col = split.column()
- col.prop(mat, "use_raytrace")
- col.prop(mat, "use_full_oversampling")
- col.prop(mat, "use_sky")
+ if simple_material(base_mat):
+ col.prop(mat, "use_raytrace")
+ col.prop(mat, "use_full_oversampling")
+ col.prop(mat, "use_sky")
col.prop(mat, "use_mist")
- col.prop(mat, "invert_z")
- sub = col.row()
- sub.prop(mat, "offset_z")
- sub.active = mat.use_transparency and mat.transparency_method == 'Z_TRANSPARENCY'
+ if simple_material(base_mat):
+ col.prop(mat, "invert_z")
+ sub = col.row()
+ sub.prop(mat, "offset_z")
+ sub.active = mat.use_transparency and mat.transparency_method == 'Z_TRANSPARENCY'
sub = col.column(align=True)
sub.label(text="Light Group:")
sub.prop(mat, "light_group", text="")
@@ -678,26 +738,32 @@ class MATERIAL_PT_shadow(MaterialButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render.engine
- return mat and (mat.type in ('SURFACE', 'WIRE')) and (engine in cls.COMPAT_ENGINES)
+ return check_material(mat) and (mat.type in {'SURFACE', 'WIRE'}) and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
- mat = active_node_mat(context.material)
+ base_mat = context.material
+ mat = active_node_mat(base_mat)
split = layout.split()
col = split.column()
col.prop(mat, "use_shadows", text="Receive")
col.prop(mat, "use_transparent_shadows", text="Receive Transparent")
+ if simple_material(base_mat):
+ col.prop(mat, "use_cast_shadows_only", text="Cast Only")
+ col.prop(mat, "shadow_cast_alpha", text="Casting Alpha")
col.prop(mat, "use_only_shadow", text="Shadows Only")
- col.prop(mat, "use_cast_shadows_only", text="Cast Only")
- col.prop(mat, "shadow_cast_alpha", text="Casting Alpha")
+ sub = col.column()
+ sub.active = mat.use_only_shadow
+ sub.prop(mat, "shadow_only_type", text="")
col = split.column()
- col.prop(mat, "use_cast_buffer_shadows")
+ if simple_material(base_mat):
+ col.prop(mat, "use_cast_buffer_shadows")
sub = col.column()
sub.active = mat.use_cast_buffer_shadows
sub.prop(mat, "shadow_buffer_bias", text="Buffer Bias")
@@ -705,7 +771,8 @@ class MATERIAL_PT_shadow(MaterialButtonsPanel, bpy.types.Panel):
sub = col.column()
sub.active = (not mat.use_ray_shadow_bias)
sub.prop(mat, "shadow_ray_bias", text="Ray Bias")
- col.prop(mat, "use_cast_approximate")
+ if simple_material(base_mat):
+ col.prop(mat, "use_cast_approximate")
class MATERIAL_PT_transp_game(MaterialButtonsPanel, bpy.types.Panel):
@@ -715,29 +782,27 @@ class MATERIAL_PT_transp_game(MaterialButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
- mat = active_node_mat(context.material)
+ mat = context.material
engine = context.scene.render.engine
- return mat and (engine in cls.COMPAT_ENGINES)
+ return check_material(mat) and (engine in cls.COMPAT_ENGINES)
def draw_header(self, context):
- mat = active_node_mat(context.material)
+ mat = context.material
- self.layout.prop(mat, "use_transparency", text="")
+ if simple_material(mat):
+ self.layout.prop(mat, "use_transparency", text="")
def draw(self, context):
layout = self.layout
+ base_mat = context.material
+ mat = active_node_mat(base_mat)
- mat = active_node_mat(context.material)
- rayt = mat.raytrace_transparency
-
- row = layout.row()
- row.active = mat.use_transparency and (not mat.use_shadeless)
- row.prop(mat, "transparency_method", expand=True)
-
- split = layout.split()
+ if simple_material(base_mat):
+ row = layout.row()
+ row.active = mat.use_transparency
+ row.prop(mat, "transparency_method", expand=True)
- col = split.column()
- col.prop(mat, "alpha")
+ layout.prop(mat, "alpha")
class VolumeButtonsPanel():
@@ -762,12 +827,9 @@ class MATERIAL_PT_volume_density(VolumeButtonsPanel, bpy.types.Panel):
vol = context.material.volume # dont use node material
- split = layout.split()
- col = split.column()
- col.prop(vol, "density")
-
- col = split.column()
- col.prop(vol, "density_scale")
+ row = layout.row()
+ row.prop(vol, "density")
+ row.prop(vol, "density_scale")
class MATERIAL_PT_volume_shading(VolumeButtonsPanel, bpy.types.Panel):
@@ -817,7 +879,7 @@ class MATERIAL_PT_volume_lighting(VolumeButtonsPanel, bpy.types.Panel):
sub = col.column()
sub.active = vol.use_light_cache
sub.prop(vol, "cache_resolution")
- elif vol.light_method in ('MULTIPLE_SCATTERING', 'SHADED_PLUS_MULTIPLE_SCATTERING'):
+ elif vol.light_method in {'MULTIPLE_SCATTERING', 'SHADED_PLUS_MULTIPLE_SCATTERING'}:
sub = col.column()
sub.enabled = True
sub.active = False
@@ -834,6 +896,12 @@ class MATERIAL_PT_volume_transp(VolumeButtonsPanel, bpy.types.Panel):
bl_label = "Transparency"
COMPAT_ENGINES = {'BLENDER_RENDER'}
+ @classmethod
+ def poll(cls, context):
+ mat = context.material
+ engine = context.scene.render.engine
+ return mat and simple_material(mat) and (mat.type == 'VOLUME') and (engine in cls.COMPAT_ENGINES)
+
def draw(self, context):
layout = self.layout
@@ -869,6 +937,12 @@ class MATERIAL_PT_volume_options(VolumeButtonsPanel, bpy.types.Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
bl_options = {'DEFAULT_CLOSED'}
+ @classmethod
+ def poll(cls, context):
+ mat = context.material
+ engine = context.scene.render.engine
+ return check_material(mat) and (mat.type == 'VOLUME') and (engine in cls.COMPAT_ENGINES)
+
def draw(self, context):
layout = self.layout
@@ -877,8 +951,9 @@ class MATERIAL_PT_volume_options(VolumeButtonsPanel, bpy.types.Panel):
split = layout.split()
col = split.column()
- col.prop(mat, "use_raytrace")
- col.prop(mat, "use_full_oversampling")
+ if simple_material(context.material):
+ col.prop(mat, "use_raytrace")
+ col.prop(mat, "use_full_oversampling")
col.prop(mat, "use_mist")
col = split.column()
@@ -894,13 +969,5 @@ class MATERIAL_PT_custom_props(MaterialButtonsPanel, PropertyPanel, bpy.types.Pa
_context_path = "material"
_property_type = bpy.types.Material
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index 30380e2d338..ae66642e903 100644
--- a/release/scripts/ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -40,8 +40,7 @@ class OBJECT_PT_context_object(ObjectButtonsPanel, bpy.types.Panel):
layout.template_ID(space, "pin_id")
else:
row = layout.row()
- row.label(text="", icon='OBJECT_DATA')
- row.prop(ob, "name", text="")
+ row.template_ID(context.scene.objects, "active")
class OBJECT_PT_transform(ObjectButtonsPanel, bpy.types.Panel):
@@ -111,7 +110,7 @@ class OBJECT_PT_transform_locks(ObjectButtonsPanel, bpy.types.Panel):
col.prop(ob, "lock_location", text="Location")
col = row.column()
- if ob.rotation_mode in ('QUATERNION', 'AXIS_ANGLE'):
+ if ob.rotation_mode in {'QUATERNION', 'AXIS_ANGLE'}:
col.prop(ob, "lock_rotations_4d", text="Rotation")
if ob.lock_rotations_4d:
col.prop(ob, "lock_rotation_w", text="W")
@@ -249,13 +248,10 @@ class OBJECT_PT_duplication(ObjectButtonsPanel, bpy.types.Panel):
layout.prop(ob, "use_dupli_vertices_rotation", text="Rotation")
elif ob.dupli_type == 'FACES':
- split = layout.split()
-
- col = split.column()
- col.prop(ob, "use_dupli_faces_scale", text="Scale")
- col = split.column()
- col.prop(ob, "dupli_faces_scale", text="Inherit Scale")
+ row = layout.row()
+ row.prop(ob, "use_dupli_faces_scale", text="Scale")
+ row.prop(ob, "dupli_faces_scale", text="Inherit Scale")
elif ob.dupli_type == 'GROUP':
layout.prop(ob, "dupli_group", text="Group")
@@ -291,7 +287,11 @@ class OBJECT_PT_animation(ObjectButtonsPanel, bpy.types.Panel):
col.prop(ob, "track_axis", text="Axis")
col.prop(ob, "up_axis", text="Up Axis")
-from properties_animviz import MotionPathButtonsPanel, OnionSkinButtonsPanel
+
+from bl_ui.properties_animviz import (
+ MotionPathButtonsPanel,
+ OnionSkinButtonsPanel,
+ )
class OBJECT_PT_motion_paths(MotionPathButtonsPanel, bpy.types.Panel):
@@ -311,13 +311,9 @@ class OBJECT_PT_motion_paths(MotionPathButtonsPanel, bpy.types.Panel):
layout.separator()
- split = layout.split()
-
- col = split.column()
- col.operator("object.paths_calculate", text="Calculate Paths")
-
- col = split.column()
- col.operator("object.paths_clear", text="Clear Paths")
+ row = layout.row()
+ row.operator("object.paths_calculate", text="Calculate Paths")
+ row.operator("object.paths_clear", text="Clear Paths")
class OBJECT_PT_onion_skinning(OnionSkinButtonsPanel): # , bpy.types.Panel): # inherit from panel when ready
@@ -329,8 +325,6 @@ class OBJECT_PT_onion_skinning(OnionSkinButtonsPanel): # , bpy.types.Panel): #
return (context.object)
def draw(self, context):
- layout = self.layout
-
ob = context.object
self.draw_settings(context, ob.animation_visualisation)
@@ -341,13 +335,5 @@ class OBJECT_PT_custom_props(ObjectButtonsPanel, PropertyPanel, bpy.types.Panel)
_context_path = "object"
_property_type = bpy.types.Object
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_object_constraint.py b/release/scripts/startup/bl_ui/properties_object_constraint.py
index 4b9c2885277..59f9ca16d1a 100644
--- a/release/scripts/ui/properties_object_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_object_constraint.py
@@ -34,7 +34,7 @@ class ConstraintButtonsPanel():
# match enum type to our functions, avoids a lookup table.
getattr(self, con.type)(context, box, con)
- if con.type not in ('RIGID_BODY_JOINT', 'NULL'):
+ if con.type not in {'RIGID_BODY_JOINT', 'NULL'}:
box.prop(con, "influence")
def space_template(self, layout, con, target=True, owner=True):
@@ -65,7 +65,7 @@ class ConstraintButtonsPanel():
row = layout.row()
row.label(text="Head/Tail:")
row.prop(con, "head_tail", text="")
- elif con.target.type in ('MESH', 'LATTICE'):
+ elif con.target.type in {'MESH', 'LATTICE'}:
layout.prop_search(con, "subtarget", con.target, "vertex_groups", text="Vertex Group")
def ik_template(self, layout, con):
@@ -112,13 +112,9 @@ class ConstraintButtonsPanel():
col.prop(con, "use_scale_y", text="Y")
col.prop(con, "use_scale_z", text="Z")
- split = layout.split()
-
- col = split.column()
- col.operator("constraint.childof_set_inverse")
-
- col = split.column()
- col.operator("constraint.childof_clear_inverse")
+ row = layout.row()
+ row.operator("constraint.childof_set_inverse")
+ row.operator("constraint.childof_clear_inverse")
def TRACK_TO(self, context, layout, con):
self.target_template(layout, con)
@@ -127,13 +123,9 @@ class ConstraintButtonsPanel():
row.label(text="To:")
row.prop(con, "track_axis", expand=True)
- split = layout.split()
-
- col = split.column()
- col.prop(con, "up_axis", text="Up")
-
- col = split.column()
- col.prop(con, "use_target_z")
+ row = layout.row()
+ row.prop(con, "up_axis", text="Up")
+ row.prop(con, "use_target_z")
self.space_template(layout, con)
@@ -212,6 +204,7 @@ class ConstraintButtonsPanel():
self.ik_template(layout, con)
layout.prop(con, "limit_mode")
+
row = layout.row()
row.prop(con, "weight", text="Weight", slider=True)
row.prop(con, "distance", text="Distance", slider=True)
@@ -486,16 +479,11 @@ class ConstraintButtonsPanel():
def STRETCH_TO(self, context, layout, con):
self.target_template(layout, con)
- split = layout.split()
-
- col = split.column()
- col.prop(con, "rest_length", text="Rest Length")
-
- col = split.column()
- col.operator("constraint.stretchto_reset", text="Reset")
+ row = layout.row()
+ row.prop(con, "rest_length", text="Rest Length")
+ row.operator("constraint.stretchto_reset", text="Reset")
- col = layout.column()
- col.prop(con, "bulge", text="Volume Variation")
+ layout.prop(con, "bulge", text="Volume Variation")
row = layout.row()
row.label(text="Volume:")
@@ -507,13 +495,9 @@ class ConstraintButtonsPanel():
def FLOOR(self, context, layout, con):
self.target_template(layout, con)
- split = layout.split()
-
- col = split.column()
- col.prop(con, "use_sticky")
-
- col = split.column()
- col.prop(con, "use_rotation")
+ row = layout.row()
+ row.prop(con, "use_sticky")
+ row.prop(con, "use_rotation")
layout.prop(con, "offset")
@@ -529,13 +513,9 @@ class ConstraintButtonsPanel():
layout.prop(con, "pivot_type")
layout.prop(con, "child")
- split = layout.split()
-
- col = split.column()
- col.prop(con, "use_linked_collision", text="Linked Collision")
-
- col = split.column()
- col.prop(con, "show_pivot", text="Display Pivot")
+ row = layout.row()
+ row.prop(con, "use_linked_collision", text="Linked Collision")
+ row.prop(con, "show_pivot", text="Display Pivot")
split = layout.split()
@@ -555,15 +535,23 @@ class ConstraintButtonsPanel():
layout.label(text="Limits:")
split = layout.split()
- col = split.column(align=True)
- col.prop(con, "use_angular_limit_x", text="Angular X")
- col.prop(con, "use_angular_limit_y", text="Angular Y")
- col.prop(con, "use_angular_limit_z", text="Angular Z")
+ col = split.column()
+ col.prop(con, "use_angular_limit_x", text="Angle X")
+ sub = col.column()
+ sub.active = con.use_angular_limit_x
+ sub.prop(con, "limit_angle_max_x", text="")
col = split.column()
- col.prop(con, "limit_cone_min", text="")
+ col.prop(con, "use_angular_limit_y", text="Angle Y")
+ sub = col.column()
+ sub.active = con.use_angular_limit_y
+ sub.prop(con, "limit_angle_max_y", text="")
+
col = split.column()
- col.prop(con, "limit_cone_max", text="")
+ col.prop(con, "use_angular_limit_z", text="Angle Z")
+ sub = col.column()
+ sub.active = con.use_angular_limit_z
+ sub.prop(con, "limit_angle_max_z", text="")
elif con.pivot_type == 'GENERIC_6_DOF':
layout.label(text="Limits:")
@@ -571,16 +559,62 @@ class ConstraintButtonsPanel():
col = split.column(align=True)
col.prop(con, "use_limit_x", text="X")
+ sub = col.column()
+ sub.active = con.use_limit_x
+ sub.prop(con, "limit_min_x", text="Min")
+ sub.prop(con, "limit_max_x", text="Max")
+
+ col = split.column(align=True)
col.prop(con, "use_limit_y", text="Y")
+ sub = col.column()
+ sub.active = con.use_limit_y
+ sub.prop(con, "limit_min_y", text="Min")
+ sub.prop(con, "limit_max_y", text="Max")
+
+ col = split.column(align=True)
col.prop(con, "use_limit_z", text="Z")
- col.prop(con, "use_angular_limit_x", text="Angular X")
- col.prop(con, "use_angular_limit_y", text="Angular Y")
- col.prop(con, "use_angular_limit_z", text="Angular Z")
+ sub = col.column()
+ sub.active = con.use_limit_z
+ sub.prop(con, "limit_min_z", text="Min")
+ sub.prop(con, "limit_max_z", text="Max")
- col = split.column()
- col.prop(con, "limit_generic_min", text="")
- col = split.column()
- col.prop(con, "limit_generic_max", text="")
+ split = layout.split()
+
+ col = split.column(align=True)
+ col.prop(con, "use_angular_limit_x", text="Angle X")
+ sub = col.column()
+ sub.active = con.use_angular_limit_x
+ sub.prop(con, "limit_angle_min_x", text="Min")
+ sub.prop(con, "limit_angle_max_x", text="Max")
+
+ col = split.column(align=True)
+ col.prop(con, "use_angular_limit_y", text="Angle Y")
+ sub = col.column()
+ sub.active = con.use_angular_limit_y
+ sub.prop(con, "limit_angle_min_y", text="Min")
+ sub.prop(con, "limit_angle_max_y", text="Max")
+
+ col = split.column(align=True)
+ col.prop(con, "use_angular_limit_z", text="Angle Z")
+ sub = col.column()
+ sub.active = con.use_angular_limit_z
+ sub.prop(con, "limit_angle_min_z", text="Min")
+ sub.prop(con, "limit_angle_max_z", text="Max")
+
+ elif con.pivot_type == 'HINGE':
+ layout.label(text="Limits:")
+ split = layout.split()
+
+ row = split.row(align=True)
+ col = row.column()
+ col.prop(con, "use_angular_limit_x", text="Angle X")
+
+ col = row.column()
+ col.active = con.use_angular_limit_x
+ col.prop(con, "limit_angle_min_x", text="Min")
+ col = row.column()
+ col.active = con.use_angular_limit_x
+ col.prop(con, "limit_angle_max_x", text="Max")
def CLAMP_TO(self, context, layout, con):
self.target_template(layout, con)
@@ -589,8 +623,7 @@ class ConstraintButtonsPanel():
row.label(text="Main Axis:")
row.prop(con, "main_axis", expand=True)
- row = layout.row()
- row.prop(con, "use_cyclic")
+ layout.prop(con, "use_cyclic")
def TRANSFORM(self, context, layout, con):
self.target_template(layout, con)
@@ -747,13 +780,5 @@ class BONE_PT_constraints(ConstraintButtonsPanel, bpy.types.Panel):
for con in context.pose_bone.constraints:
self.draw_constraint(context, con)
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index 4bed2e81629..5037308c6fd 100644
--- a/release/scripts/ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -20,15 +20,19 @@
import bpy
from rna_prop_ui import PropertyPanel
-from properties_physics_common import point_cache_ui
-from properties_physics_common import effector_weights_ui
-from properties_physics_common import basic_force_field_settings_ui
-from properties_physics_common import basic_force_field_falloff_ui
+from bl_ui.properties_physics_common import (
+ point_cache_ui,
+ effector_weights_ui,
+ basic_force_field_settings_ui,
+ basic_force_field_falloff_ui,
+ )
def particle_panel_enabled(context, psys):
+ if psys is None:
+ return True
phystype = psys.settings.physics_type
- if psys.settings.type in ('EMITTER', 'REACTOR') and phystype in ('NO', 'KEYED'):
+ if psys.settings.type in {'EMITTER', 'REACTOR'} and phystype in {'NO', 'KEYED'}:
return True
else:
return (psys.point_cache.is_baked is False) and (not psys.is_edited) and (not context.particle_system_editable)
@@ -37,11 +41,25 @@ def particle_panel_enabled(context, psys):
def particle_panel_poll(cls, context):
psys = context.particle_system
engine = context.scene.render.engine
- if psys is None:
- return False
- if psys.settings is None:
+ settings = 0
+
+ if psys:
+ settings = psys.settings
+ elif isinstance(context.space_data.pin_id, bpy.types.ParticleSettings):
+ settings = context.space_data.pin_id
+
+ if not settings:
return False
- return psys.settings.is_fluid == False and (engine in cls.COMPAT_ENGINES)
+
+ return settings.is_fluid == False and (engine in cls.COMPAT_ENGINES)
+
+
+def particle_get_settings(context):
+ if context.particle_system:
+ return context.particle_system.settings
+ elif isinstance(context.space_data.pin_id, bpy.types.ParticleSettings):
+ return context.space_data.pin_id
+ return None
class ParticleButtonsPanel():
@@ -62,13 +80,14 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
engine = context.scene.render.engine
- return (context.particle_system or context.object) and (engine in cls.COMPAT_ENGINES)
+ return (context.particle_system or context.object or context.space_data.pin_id) and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
ob = context.object
psys = context.particle_system
+ part = 0
if ob:
row = layout.row()
@@ -79,7 +98,21 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, bpy.types.Panel):
col.operator("object.particle_system_add", icon='ZOOMIN', text="")
col.operator("object.particle_system_remove", icon='ZOOMOUT', text="")
- if psys and not psys.settings:
+ if psys is None:
+ part = particle_get_settings(context)
+
+ if part is None:
+ return
+
+ layout.template_ID(context.space_data, "pin_id")
+
+ if part.is_fluid:
+ layout.label(text="Settings used for fluid.")
+ return
+
+ layout.prop(part, "type", text="Type")
+
+ elif not psys.settings:
split = layout.split(percentage=0.32)
col = split.column()
@@ -89,7 +122,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, bpy.types.Panel):
col = split.column()
col.prop(psys, "name", text="")
col.template_ID(psys, "settings", new="particle.new")
- elif psys:
+ else:
part = psys.settings
split = layout.split(percentage=0.32)
@@ -110,39 +143,39 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, bpy.types.Panel):
#row.label(text="Viewport")
#row.label(text="Render")
- if part:
- if part.is_fluid:
- layout.label(text=str(part.count) + " fluid particles for this frame.")
- return
+ if part.is_fluid:
+ layout.label(text=str(part.count) + " fluid particles for this frame.")
+ return
- row = col.row()
- row.enabled = particle_panel_enabled(context, psys)
- row.prop(part, "type", text="")
- row.prop(psys, "seed")
+ row = col.row()
+ row.enabled = particle_panel_enabled(context, psys)
+ row.prop(part, "type", text="")
+ row.prop(psys, "seed")
- split = layout.split(percentage=0.65)
- if part.type == 'HAIR':
- if psys.is_edited:
- split.operator("particle.edited_clear", text="Free Edit")
- else:
- row = split.row()
- row.enabled = particle_panel_enabled(context, psys)
- row.prop(part, "regrow_hair")
- row.prop(part, "use_advanced_hair")
+ if part:
+ split = layout.split(percentage=0.65)
+ if part.type == 'HAIR':
+ if psys != None and psys.is_edited:
+ split.operator("particle.edited_clear", text="Free Edit")
+ else:
row = split.row()
row.enabled = particle_panel_enabled(context, psys)
- row.prop(part, "hair_step")
- if psys.is_edited:
- if psys.is_global_hair:
- layout.operator("particle.connect_hair")
- layout.label(text="Hair is disconnected.")
- else:
- layout.operator("particle.disconnect_hair")
- layout.label(text="")
- elif 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")
+ row.prop(part, "regrow_hair")
+ row.prop(part, "use_advanced_hair")
+ 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_global_hair:
+ layout.operator("particle.connect_hair")
+ layout.label(text="Hair is disconnected.")
+ else:
+ layout.operator("particle.disconnect_hair")
+ layout.label(text="")
+ elif psys != None and part.type == 'REACTOR':
+ split.enabled = particle_panel_enabled(context, psys)
+ split.prop(psys, "reactor_target_object")
+ split.prop(psys, "reactor_target_particle_system", text="Particle System")
class PARTICLE_PT_emission(ParticleButtonsPanel, bpy.types.Panel):
@@ -152,23 +185,23 @@ class PARTICLE_PT_emission(ParticleButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
psys = context.particle_system
- if psys is None:
- return False
- if psys.settings is None:
+ settings = particle_get_settings(context)
+
+ if settings is None:
return False
- if psys.settings.is_fluid:
+ if settings.is_fluid:
return False
if particle_panel_poll(PARTICLE_PT_emission, context):
- return not context.particle_system.point_cache.use_external
+ return psys is None or not context.particle_system.point_cache.use_external
return False
def draw(self, context):
layout = self.layout
psys = context.particle_system
- part = psys.settings
+ part = particle_get_settings(context)
- layout.enabled = particle_panel_enabled(context, psys) and not psys.has_multiple_caches
+ layout.enabled = particle_panel_enabled(context, psys) and (psys is None or not psys.has_multiple_caches)
row = layout.row()
row.active = part.distribution != 'GRID'
@@ -189,25 +222,23 @@ class PARTICLE_PT_emission(ParticleButtonsPanel, bpy.types.Panel):
col.prop(part, "lifetime")
col.prop(part, "lifetime_random", slider=True)
- layout.row().label(text="Emit From:")
-
- row = layout.row()
- row.prop(part, "emit_from", expand=True)
+ layout.label(text="Emit From:")
+ layout.prop(part, "emit_from", expand=True)
row = layout.row()
- if part.distribution == 'GRID':
+ if part.emit_from == 'VERT':
+ row.prop(part, "use_emit_random")
+ elif part.distribution == 'GRID':
row.prop(part, "invert_grid")
+ row.prop(part, "hexagonal_grid")
else:
row.prop(part, "use_emit_random")
row.prop(part, "use_even_distribution")
if part.emit_from == 'FACE' or part.emit_from == 'VOLUME':
- row = layout.row()
-
- row.prop(part, "distribution", expand=True)
+ layout.prop(part, "distribution", expand=True)
row = layout.row()
-
if part.distribution == 'JIT':
row.prop(part, "userjit", text="Particles/Face")
row.prop(part, "jitter_factor", text="Jittering Amount", slider=True)
@@ -247,7 +278,6 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, bpy.types.Panel):
if not psys.cloth:
return
- #part = psys.settings
cloth = psys.cloth.settings
layout.enabled = psys.use_hair_dynamics and psys.point_cache.is_baked == False
@@ -264,7 +294,6 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, bpy.types.Panel):
sub.prop(cloth, "collider_friction", slider=True)
col = split.column()
-
col.label(text="Damping:")
sub = col.column(align=True)
sub.prop(cloth, "spring_damping", text="Spring")
@@ -292,7 +321,7 @@ class PARTICLE_PT_cache(ParticleButtonsPanel, bpy.types.Panel):
phystype = psys.settings.physics_type
if phystype == 'NO' or phystype == 'KEYED':
return False
- return (psys.settings.type in ('EMITTER', 'REACTOR') or (psys.settings.type == 'HAIR' and (psys.use_hair_dynamics or psys.point_cache.is_baked))) and engine in cls.COMPAT_ENGINES
+ return (psys.settings.type in {'EMITTER', 'REACTOR'} or (psys.settings.type == 'HAIR' and (psys.use_hair_dynamics or psys.point_cache.is_baked))) and engine in cls.COMPAT_ENGINES
def draw(self, context):
psys = context.particle_system
@@ -308,9 +337,11 @@ class PARTICLE_PT_velocity(ParticleButtonsPanel, bpy.types.Panel):
def poll(cls, context):
if particle_panel_poll(PARTICLE_PT_velocity, context):
psys = context.particle_system
- if psys.settings.type == 'HAIR' and not psys.settings.use_advanced_hair:
+ settings = particle_get_settings(context)
+
+ if settings.type == 'HAIR' and not settings.use_advanced_hair:
return False
- return psys.settings.physics_type != 'BOIDS' and not psys.point_cache.use_external
+ return settings.physics_type != 'BOIDS' and (psys is None or not psys.point_cache.use_external)
else:
return False
@@ -318,32 +349,30 @@ class PARTICLE_PT_velocity(ParticleButtonsPanel, bpy.types.Panel):
layout = self.layout
psys = context.particle_system
- part = psys.settings
+ part = particle_get_settings(context)
layout.enabled = particle_panel_enabled(context, psys)
split = layout.split()
- sub = split.column()
- sub.label(text="Emitter Geometry:")
- sub.prop(part, "normal_factor")
- subsub = sub.column(align=True)
- subsub.prop(part, "tangent_factor")
- subsub.prop(part, "tangent_phase", slider=True)
+ col = split.column()
+ col.label(text="Emitter Geometry:")
+ col.prop(part, "normal_factor")
+ sub = col.column(align=True)
+ sub.prop(part, "tangent_factor")
+ sub.prop(part, "tangent_phase", slider=True)
- sub = split.column()
- sub.label(text="Emitter Object")
- sub.prop(part, "object_align_factor", text="")
+ col = split.column()
+ col.label(text="Emitter Object:")
+ col.prop(part, "object_align_factor", text="")
- layout.row().label(text="Other:")
- split = layout.split()
- sub = split.column()
+ layout.label(text="Other:")
+ row = layout.row()
if part.emit_from == 'PARTICLE':
- sub.prop(part, "particle_factor")
+ row.prop(part, "particle_factor")
else:
- sub.prop(part, "object_factor", slider=True)
- sub = split.column()
- sub.prop(part, "factor_random")
+ row.prop(part, "object_factor", slider=True)
+ row.prop(part, "factor_random")
#if part.type=='REACTOR':
# sub.prop(part, "reactor_factor")
@@ -358,9 +387,11 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, bpy.types.Panel):
def poll(cls, context):
if particle_panel_poll(PARTICLE_PT_rotation, context):
psys = context.particle_system
- if psys.settings.type == 'HAIR' and not psys.settings.use_advanced_hair:
+ settings = particle_get_settings(context)
+
+ if settings.type == 'HAIR' and not settings.use_advanced_hair:
return False
- return psys.settings.physics_type != 'BOIDS' and not psys.point_cache.use_external
+ return settings.physics_type != 'BOIDS' and (psys is None or not psys.point_cache.use_external)
else:
return False
@@ -368,31 +399,33 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, bpy.types.Panel):
layout = self.layout
psys = context.particle_system
- part = psys.settings
+ if psys:
+ part = psys.settings
+ else:
+ part = context.space_data.pin_id
layout.enabled = particle_panel_enabled(context, psys)
- split = layout.split()
- split.label(text="Initial Rotation:")
- split.prop(part, "use_dynamic_rotation")
- split = layout.split()
+ row = layout.row()
+ row.label(text="Initial Rotation:")
+ row.prop(part, "use_dynamic_rotation")
- sub = split.column(align=True)
- sub.prop(part, "rotation_mode", text="")
- sub.prop(part, "rotation_factor_random", slider=True, text="Random")
+ split = layout.split()
- sub = split.column(align=True)
- sub.prop(part, "phase_factor", slider=True)
- sub.prop(part, "phase_factor_random", text="Random", slider=True)
+ col = split.column(align=True)
+ col.prop(part, "rotation_mode", text="")
+ col.prop(part, "rotation_factor_random", slider=True, text="Random")
- layout.row().label(text="Angular Velocity:")
- layout.row().prop(part, "angular_velocity_mode", expand=True)
- split = layout.split()
+ col = split.column(align=True)
+ col.prop(part, "phase_factor", slider=True)
+ col.prop(part, "phase_factor_random", text="Random", slider=True)
- sub = split.column()
+ col = layout.column()
+ col.label(text="Angular Velocity:")
+ col.row().prop(part, "angular_velocity_mode", expand=True)
if part.angular_velocity_mode != 'NONE':
- sub.prop(part, "angular_velocity_factor", text="")
+ col.prop(part, "angular_velocity_factor", text="")
class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
@@ -403,9 +436,11 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
def poll(cls, context):
if particle_panel_poll(PARTICLE_PT_physics, context):
psys = context.particle_system
- if psys.settings.type == 'HAIR' and not psys.settings.use_advanced_hair:
+ settings = particle_get_settings(context)
+
+ if settings.type == 'HAIR' and not settings.use_advanced_hair:
return False
- return not psys.point_cache.use_external
+ return psys is None or not psys.point_cache.use_external
else:
return False
@@ -413,12 +448,11 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
layout = self.layout
psys = context.particle_system
- part = psys.settings
+ part = particle_get_settings(context)
layout.enabled = particle_panel_enabled(context, psys)
- row = layout.row()
- row.prop(part, "physics_type", expand=True)
+ layout.prop(part, "physics_type", expand=True)
row = layout.row()
col = row.column(align=True)
@@ -430,70 +464,76 @@ 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 == 'NEWTON':
+ if part.physics_type in ('NEWTON', 'FLUID'):
split = layout.split()
- sub = split.column()
- sub.label(text="Forces:")
- sub.prop(part, "brownian_factor")
- sub.prop(part, "drag_factor", slider=True)
- sub.prop(part, "damping", slider=True)
- sub = split.column()
- sub.label(text="Integration:")
- sub.prop(part, "integrator", text="")
- sub.prop(part, "time_tweak")
- sub.prop(part, "subframes")
- sub = layout.row()
- sub.prop(part, "use_size_deflect")
- sub.prop(part, "use_die_on_collision")
-
- elif part.physics_type == 'FLUID':
- fluid = part.fluid
- split = layout.split()
- sub = split.column()
+ col = split.column()
+ col.label(text="Forces:")
+ col.prop(part, "brownian_factor")
+ col.prop(part, "drag_factor", slider=True)
+ col.prop(part, "damping", slider=True)
- sub.label(text="Forces:")
- sub.prop(part, "brownian_factor")
- sub.prop(part, "drag_factor", slider=True)
- sub.prop(part, "damping", slider=True)
- sub = split.column()
- sub.label(text="Integration:")
- sub.prop(part, "integrator", text="")
- sub.prop(part, "time_tweak")
- sub.prop(part, "subframes")
- sub = layout.row()
- sub.prop(part, "use_size_deflect")
- sub.prop(part, "use_die_on_collision")
+ col = split.column()
+ col.label(text="Integration:")
+ col.prop(part, "integrator", text="")
+ col.prop(part, "timestep")
+ col.prop(part, "subframes")
- split = layout.split()
- sub = split.column()
- sub.label(text="Fluid Interaction:")
- sub.prop(fluid, "fluid_radius")
- sub.prop(fluid, "repulsion_force")
- subsub = sub.column(align=True)
- subsub.prop(fluid, "rest_density")
- subsub.prop(fluid, "density_force", text="Force")
+ row = layout.row()
+ row.prop(part, "use_size_deflect")
+ row.prop(part, "use_die_on_collision")
- sub.label(text="Viscosity:")
- subsub = sub.column(align=True)
- subsub.prop(fluid, "linear_viscosity", text="Linear")
- subsub.prop(fluid, "square_viscosity", text="Square")
+ if part.physics_type == 'FLUID':
+ fluid = part.fluid
- sub = split.column()
+ split = layout.split()
- sub.label(text="Springs:")
- sub.prop(fluid, "spring_force", text="Force")
- #Hidden to make ui a bit lighter, can be unhidden for a bit more control
- #sub.prop(fluid, "rest_length", slider=True)
- sub.prop(fluid, "use_viscoelastic_springs")
- subsub = sub.column(align=True)
- subsub.active = fluid.use_viscoelastic_springs
- subsub.prop(fluid, "yield_ratio", slider=True)
- subsub.prop(fluid, "plasticity", slider=True)
- subsub.prop(fluid, "use_initial_rest_length")
+ col = split.column()
+ col.label(text="Fluid properties:")
+ col.prop(fluid, "stiffness", text="Stiffness")
+ col.prop(fluid, "linear_viscosity", text="Viscosity")
+ col.prop(fluid, "buoyancy", text="Buoancy", slider=True)
- sub.label(text="Buoyancy:")
- sub.prop(fluid, "buoyancy", text="Strength", slider=True)
+ col = split.column()
+ col.label(text="Advanced:")
+
+ sub = col.row()
+ sub.prop(fluid, "repulsion", slider=fluid.factor_repulsion)
+ sub.prop(fluid, "factor_repulsion", text="")
+
+ sub = col.row()
+ sub.prop(fluid, "stiff_viscosity", slider=fluid.factor_stiff_viscosity)
+ sub.prop(fluid, "factor_stiff_viscosity", text="")
+
+ sub = col.row()
+ sub.prop(fluid, "fluid_radius", slider=fluid.factor_radius)
+ sub.prop(fluid, "factor_radius", text="")
+
+ sub = col.row()
+ sub.prop(fluid, "rest_density", slider=fluid.factor_density)
+ sub.prop(fluid, "factor_density", text="")
+
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="Springs:")
+ col.prop(fluid, "spring_force", text="Force")
+ col.prop(fluid, "use_viscoelastic_springs")
+ sub = col.column(align=True)
+ sub.active = fluid.use_viscoelastic_springs
+ sub.prop(fluid, "yield_ratio", slider=True)
+ sub.prop(fluid, "plasticity", slider=True)
+
+ col = split.column()
+ col.label(text="Advanced:")
+ sub = col.row()
+ sub.prop(fluid, "rest_length", slider=fluid.factor_rest_length)
+ sub.prop(fluid, "factor_rest_length", text="")
+ col.label(text="")
+ sub = col.column()
+ sub.active = fluid.use_viscoelastic_springs
+ sub.prop(fluid, "use_initial_rest_length")
+ sub.prop(fluid, "spring_frames", text="Frames")
elif part.physics_type == 'KEYED':
split = layout.split()
@@ -503,7 +543,8 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
col = row.column()
col.active = not psys.use_keyed_timing
col.prop(part, "keyed_loops", text="Loops")
- row.prop(psys, "use_keyed_timing", text="Use Timing")
+ if psys:
+ row.prop(psys, "use_keyed_timing", text="Use Timing")
layout.label(text="Keys:")
elif part.physics_type == 'BOIDS':
@@ -554,7 +595,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, bpy.types.Panel):
col.prop(boids, "pitch", slider=True)
col.prop(boids, "height", slider=True)
- if part.physics_type == 'KEYED' or part.physics_type == 'BOIDS' or part.physics_type == 'FLUID':
+ if psys and part.physics_type in {'KEYED', 'BOIDS', 'FLUID'}:
if part.physics_type == 'BOIDS':
layout.label(text="Relations:")
elif part.physics_type == 'FLUID':
@@ -609,19 +650,19 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
psys = context.particle_system
+ settings = particle_get_settings(context)
engine = context.scene.render.engine
- if psys is None:
- return False
- if psys.settings is None:
+
+ if settings is None:
return False
- if psys.point_cache.use_external:
+ if psys != None and psys.point_cache.use_external:
return False
- return psys.settings.physics_type == 'BOIDS' and engine in cls.COMPAT_ENGINES
+ return settings.physics_type == 'BOIDS' and engine in cls.COMPAT_ENGINES
def draw(self, context):
layout = self.layout
- boids = context.particle_system.settings.boids
+ boids = particle_get_settings(context).boids
layout.enabled = particle_panel_enabled(context, context.particle_system)
@@ -709,65 +750,65 @@ class PARTICLE_PT_render(ParticleButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
- psys = context.particle_system
+ settings = particle_get_settings(context)
engine = context.scene.render.engine
- if psys is None:
- return False
- if psys.settings is None:
+ if settings is None:
return False
+
return engine in cls.COMPAT_ENGINES
def draw(self, context):
layout = self.layout
psys = context.particle_system
- part = psys.settings
+ part = particle_get_settings(context)
row = layout.row()
row.prop(part, "material")
- row.prop(psys, "parent")
+ if psys:
+ row.prop(psys, "parent")
split = layout.split()
- sub = split.column()
- sub.prop(part, "use_render_emitter")
- sub.prop(part, "use_parent_particles")
- sub = split.column()
- sub.prop(part, "show_unborn")
- sub.prop(part, "use_dead")
+ col = split.column()
+ col.prop(part, "use_render_emitter")
+ col.prop(part, "use_parent_particles")
- row = layout.row()
- row.prop(part, "render_type", expand=True)
+ col = split.column()
+ col.prop(part, "show_unborn")
+ col.prop(part, "use_dead")
+
+ layout.prop(part, "render_type", expand=True)
split = layout.split()
- sub = split.column()
+ col = split.column()
if part.render_type == 'LINE':
- sub.prop(part, "line_length_tail")
- sub.prop(part, "line_length_head")
- sub = split.column()
- sub.prop(part, "use_velocity_length")
+ col.prop(part, "line_length_tail")
+ col.prop(part, "line_length_head")
+
+ split.prop(part, "use_velocity_length")
elif part.render_type == 'PATH':
- sub.prop(part, "use_strand_primitive")
- subsub = sub.column()
- subsub.active = (part.use_strand_primitive is False)
- subsub.prop(part, "use_render_adaptive")
- subsub = sub.column()
- subsub.active = part.use_render_adaptive or part.use_strand_primitive == True
- subsub.prop(part, "adaptive_angle")
- subsub = sub.column()
- subsub.active = (part.use_render_adaptive is True and part.use_strand_primitive is False)
- subsub.prop(part, "adaptive_pixel")
- sub.prop(part, "use_hair_bspline")
- sub.prop(part, "render_step", text="Steps")
+ col.prop(part, "use_strand_primitive")
+ sub = col.column()
+ sub.active = (part.use_strand_primitive is False)
+ sub.prop(part, "use_render_adaptive")
+ sub = col.column()
+ sub.active = part.use_render_adaptive or part.use_strand_primitive == True
+ sub.prop(part, "adaptive_angle")
+ sub = col.column()
+ sub.active = (part.use_render_adaptive is True and part.use_strand_primitive is False)
+ sub.prop(part, "adaptive_pixel")
+ col.prop(part, "use_hair_bspline")
+ col.prop(part, "render_step", text="Steps")
- sub = split.column()
- sub.label(text="Timing:")
- sub.prop(part, "use_absolute_path_time")
- sub.prop(part, "path_start", text="Start", slider=not part.use_absolute_path_time)
- sub.prop(part, "path_end", text="End", slider=not part.use_absolute_path_time)
- sub.prop(part, "length_random", text="Random", slider=True)
+ col = split.column()
+ col.label(text="Timing:")
+ col.prop(part, "use_absolute_path_time")
+ col.prop(part, "path_start", text="Start", slider=not part.use_absolute_path_time)
+ col.prop(part, "path_end", text="End", slider=not part.use_absolute_path_time)
+ col.prop(part, "length_random", text="Random", slider=True)
row = layout.row()
col = row.column()
@@ -786,22 +827,23 @@ class PARTICLE_PT_render(ParticleButtonsPanel, bpy.types.Panel):
sub.prop(part, "simplify_viewport")
elif part.render_type == 'OBJECT':
- sub.prop(part, "dupli_object")
- sub.prop(part, "use_global_dupli")
+ col.prop(part, "dupli_object")
+ col.prop(part, "use_global_dupli")
elif part.render_type == 'GROUP':
- sub.prop(part, "dupli_group")
+ col.prop(part, "dupli_group")
split = layout.split()
- sub = split.column()
- sub.prop(part, "use_whole_group")
- subsub = sub.column()
- subsub.active = (part.use_whole_group is False)
- subsub.prop(part, "use_group_count")
- sub = split.column()
- subsub = sub.column()
- subsub.active = (part.use_whole_group is False)
- subsub.prop(part, "use_global_dupli")
- subsub.prop(part, "use_group_pick_random")
+ col = split.column()
+ col.prop(part, "use_whole_group")
+ sub = col.column()
+ sub.active = (part.use_whole_group is False)
+ sub.prop(part, "use_group_count")
+
+ col = split.column()
+ sub = col.column()
+ sub.active = (part.use_whole_group is False)
+ sub.prop(part, "use_global_dupli")
+ sub.prop(part, "use_group_pick_random")
if part.use_group_count and not part.use_whole_group:
row = layout.row()
@@ -821,7 +863,9 @@ class PARTICLE_PT_render(ParticleButtonsPanel, bpy.types.Panel):
row.prop(weight, "count")
elif part.render_type == 'BILLBOARD':
- sub.label(text="Align:")
+ ob = context.object
+
+ col.label(text="Align:")
row = layout.row()
row.prop(part, "billboard_align", expand=True)
@@ -833,21 +877,25 @@ class PARTICLE_PT_render(ParticleButtonsPanel, bpy.types.Panel):
col = row.column(align=True)
col.label(text="Tilt:")
col.prop(part, "billboard_tilt", text="Angle", slider=True)
- col.prop(part, "billboard_tilt_random", slider=True)
+ col.prop(part, "billboard_tilt_random", text="Random", slider=True)
col = row.column()
col.prop(part, "billboard_offset")
- row = layout.row()
- row.prop(psys, "billboard_normal_uv")
- row = layout.row()
- row.prop(psys, "billboard_time_index_uv")
+ if psys:
+ col = layout.column()
+ col.prop_search(psys, "billboard_normal_uv", ob.data, "uv_textures")
+ col.prop_search(psys, "billboard_time_index_uv", ob.data, "uv_textures")
- row = layout.row()
- row.label(text="Split uv's:")
- row.prop(part, "billboard_uv_split", text="Number of splits")
- row = layout.row()
- row.prop(psys, "billboard_split_uv")
- row = layout.row()
+ split = layout.split(percentage=0.33)
+ split.label(text="Split uv's:")
+ split.prop(part, "billboard_uv_split", text="Number of splits")
+
+ if psys:
+ col = layout.column()
+ col.active = part.billboard_uv_split > 1
+ col.prop_search(psys, "billboard_split_uv", ob.data, "uv_textures")
+
+ row = col.row()
row.label(text="Animate:")
row.prop(part, "billboard_animation", text="")
row.label(text="Offset:")
@@ -866,6 +914,11 @@ 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:
+ 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):
bl_label = "Display"
@@ -874,11 +927,9 @@ class PARTICLE_PT_draw(ParticleButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
- psys = context.particle_system
+ settings = particle_get_settings(context)
engine = context.scene.render.engine
- if psys is None:
- return False
- if psys.settings is None:
+ if settings is None:
return False
return engine in cls.COMPAT_ENGINES
@@ -886,7 +937,7 @@ class PARTICLE_PT_draw(ParticleButtonsPanel, bpy.types.Panel):
layout = self.layout
psys = context.particle_system
- part = psys.settings
+ part = particle_get_settings(context)
row = layout.row()
row.prop(part, "draw_method", expand=True)
@@ -903,7 +954,7 @@ class PARTICLE_PT_draw(ParticleButtonsPanel, bpy.types.Panel):
else:
row.label(text="")
- if part.draw_percentage != 100:
+ if part.draw_percentage != 100 and psys is not None:
if part.type == 'HAIR':
if psys.use_hair_dynamics and psys.point_cache.is_baked == False:
layout.row().label(text="Display percentage makes dynamics inaccurate without baking!")
@@ -920,16 +971,15 @@ class PARTICLE_PT_draw(ParticleButtonsPanel, bpy.types.Panel):
if part.physics_type == 'BOIDS':
col.prop(part, "show_health")
- col = row.column()
- col.prop(part, "show_material_color", text="Use material color")
+ col = row.column(align=True)
+ col.label(text="Color:")
+ col.prop(part, "draw_color", text="")
+ sub = col.row()
+ sub.active = part.draw_color in ('VELOCITY', 'ACCELERATION')
+ sub.prop(part, "color_maximum", text="Max")
if (path):
col.prop(part, "draw_step")
- else:
- sub = col.column()
- sub.active = (part.show_material_color is False)
- #sub.label(text="color")
- #sub.label(text="Override material color")
class PARTICLE_PT_children(ParticleButtonsPanel, bpy.types.Panel):
@@ -945,7 +995,7 @@ class PARTICLE_PT_children(ParticleButtonsPanel, bpy.types.Panel):
layout = self.layout
psys = context.particle_system
- part = psys.settings
+ part = particle_get_settings(context)
layout.row().prop(part, "child_type", expand=True)
@@ -960,7 +1010,8 @@ class PARTICLE_PT_children(ParticleButtonsPanel, bpy.types.Panel):
if part.child_type == 'INTERPOLATED':
col = row.column()
- col.prop(psys, "child_seed", text="Seed")
+ if psys:
+ col.prop(psys, "child_seed", text="Seed")
col.prop(part, "virtual_parents", slider=True)
col.prop(part, "create_long_hair_children")
else:
@@ -985,7 +1036,8 @@ class PARTICLE_PT_children(ParticleButtonsPanel, bpy.types.Panel):
sub = col.column(align=True)
sub.prop(part, "child_radius", text="Radius")
sub.prop(part, "child_roundness", text="Roundness", slider=True)
- sub.prop(psys, "child_seed", text="Seed")
+ if psys:
+ sub.prop(psys, "child_seed", text="Seed")
elif part.virtual_parents > 0.0:
sub = col.column(align=True)
sub.label(text="Parting not")
@@ -1040,7 +1092,7 @@ class PARTICLE_PT_field_weights(ParticleButtonsPanel, bpy.types.Panel):
return particle_panel_poll(cls, context)
def draw(self, context):
- part = context.particle_system.settings
+ part = particle_get_settings(context)
effector_weights_ui(self, context, part.effector_weights)
if part.type == 'HAIR':
@@ -1059,14 +1111,18 @@ class PARTICLE_PT_force_fields(ParticleButtonsPanel, bpy.types.Panel):
def draw(self, context):
layout = self.layout
- part = context.particle_system.settings
+ part = particle_get_settings(context)
- layout.prop(part, "use_self_effect")
+ row = layout.row()
+ row.prop(part, "use_self_effect")
+ row.prop(part, "effector_amount", text="Amount")
split = layout.split(percentage=0.2)
split.label(text="Type 1:")
split.prop(part.force_field_1, "type", text="")
basic_force_field_settings_ui(self, context, part.force_field_1)
+ if part.force_field_1.type != 'NONE':
+ layout.label(text="Falloff:")
basic_force_field_falloff_ui(self, context, part.force_field_1)
if part.force_field_1.type != 'NONE':
@@ -1076,6 +1132,8 @@ class PARTICLE_PT_force_fields(ParticleButtonsPanel, bpy.types.Panel):
split.label(text="Type 2:")
split.prop(part.force_field_2, "type", text="")
basic_force_field_settings_ui(self, context, part.force_field_2)
+ if part.force_field_2.type != 'NONE':
+ layout.label(text="Falloff:")
basic_force_field_falloff_ui(self, context, part.force_field_2)
@@ -1086,6 +1144,8 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
+ if context.particle_system is None:
+ return False
return particle_panel_poll(cls, context)
def draw(self, context):
@@ -1093,9 +1153,6 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, bpy.types.Panel):
ob = context.object
psys = context.particle_system
- # part = psys.settings
-
- # layout.label(text="Nothing here yet.")
row = layout.row()
row.label(text="Vertex Group")
@@ -1156,13 +1213,5 @@ class PARTICLE_PT_custom_props(ParticleButtonsPanel, PropertyPanel, bpy.types.Pa
_context_path = "particle_system.settings"
_property_type = bpy.types.ParticleSettings
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py
index 0ac4429c71a..bce6ab993a7 100644
--- a/release/scripts/ui/properties_physics_cloth.py
+++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py
@@ -20,8 +20,10 @@
import bpy
-from properties_physics_common import point_cache_ui
-from properties_physics_common import effector_weights_ui
+from bl_ui.properties_physics_common import (
+ point_cache_ui,
+ effector_weights_ui,
+ )
def cloth_panel_enabled(md):
@@ -112,7 +114,7 @@ class PHYSICS_PT_cloth(PhysicButtonsPanel, bpy.types.Panel):
if key:
col.label(text="Rest Shape Key:")
- col.prop_search(cloth, "rest_shape_key", key, "keys", text="")
+ col.prop_search(cloth, "rest_shape_key", key, "key_blocks", text="")
class PHYSICS_PT_cloth_cache(PhysicButtonsPanel, bpy.types.Panel):
@@ -155,6 +157,8 @@ class PHYSICS_PT_cloth_collision(PhysicButtonsPanel, bpy.types.Panel):
col = split.column()
col.prop(cloth, "collision_quality", slider=True, text="Quality")
col.prop(cloth, "distance_min", slider=True, text="Distance")
+ col.prop(cloth, "repel_force", slider=True, text="Repel")
+ col.prop(cloth, "distance_repel", slider=True, text="Repel Distance")
col.prop(cloth, "friction")
col = split.column()
@@ -215,13 +219,5 @@ class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, bpy.types.Panel):
cloth = context.cloth.settings
effector_weights_ui(self, context, cloth.effector_weights)
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index 3d854533506..f7cf8da1840 100644
--- a/release/scripts/ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -89,7 +89,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
col.operator("ptcache.remove", icon='ZOOMOUT', text="")
row = layout.row()
- if cachetype in ('PSYS', 'HAIR', 'SMOKE'):
+ if cachetype in {'PSYS', 'HAIR', 'SMOKE'}:
row.prop(cache, "use_external")
if cache.use_external:
@@ -106,7 +106,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
layout.label(text=cache.info)
else:
if cachetype == 'SMOKE':
- if bpy.data.is_dirty:
+ if not bpy.data.is_saved:
layout.label(text="Cache is disabled until the file is saved")
layout.enabled = False
@@ -121,7 +121,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
row.enabled = enabled
row.prop(cache, "frame_start")
row.prop(cache, "frame_end")
- if cachetype not in ('SMOKE', 'CLOTH'):
+ if cachetype not in {'SMOKE', 'CLOTH'}:
row.prop(cache, "frame_step")
row.prop(cache, "use_quick_cache")
if cachetype != 'SMOKE':
@@ -129,7 +129,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
if cachetype != 'SMOKE':
split = layout.split()
- split.enabled = enabled and (not bpy.data.is_dirty)
+ split.enabled = enabled and bpy.data.is_saved
col = split.column()
col.prop(cache, "use_disk_cache")
@@ -139,7 +139,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
col.prop(cache, "use_library_path", "Use Lib Path")
row = layout.row()
- row.enabled = enabled and (not bpy.data.is_dirty)
+ row.enabled = enabled and bpy.data.is_saved
row.active = cache.use_disk_cache
row.label(text="Compression:")
row.prop(cache, "compression", expand=True)
@@ -232,8 +232,9 @@ def basic_force_field_settings_ui(self, context, field):
col.prop(field, "flow")
col = split.column()
- col.prop(field, "noise")
- col.prop(field, "seed")
+ sub = col.column(align=True)
+ sub.prop(field, "noise")
+ sub.prop(field, "seed")
if field.type == 'TURBULENCE':
col.prop(field, "use_global_coords", text="Global")
elif field.type == 'HARMONIC':
@@ -254,8 +255,6 @@ def basic_force_field_settings_ui(self, context, field):
def basic_force_field_falloff_ui(self, context, field):
layout = self.layout
- # XXX: This doesn't update for some reason.
- #split = layout.split()
split = layout.split(percentage=0.35)
if not field or field.type == 'NONE':
@@ -263,27 +262,24 @@ def basic_force_field_falloff_ui(self, context, field):
col = split.column()
col.prop(field, "z_direction", text="")
- col.prop(field, "use_min_distance", text="Use Minimum")
- col.prop(field, "use_max_distance", text="Use Maximum")
col = split.column()
col.prop(field, "falloff_power", text="Power")
- sub = col.column()
+ split = layout.split()
+ col = split.column()
+ row = col.row(align=True)
+ row.prop(field, "use_min_distance", text="")
+ sub = row.row()
sub.active = field.use_min_distance
- sub.prop(field, "distance_min", text="Distance")
+ sub.prop(field, "distance_min", text="Minimum")
- sub = col.column()
+ col = split.column()
+ row = col.row(align=True)
+ row.prop(field, "use_max_distance", text="")
+ sub = row.row()
sub.active = field.use_max_distance
- sub.prop(field, "distance_max", text="Distance")
-
+ sub.prop(field, "distance_max", text="Maximum")
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_physics_field.py b/release/scripts/startup/bl_ui/properties_physics_field.py
index 8a697806aa1..9f96f0a5b9f 100644
--- a/release/scripts/ui/properties_physics_field.py
+++ b/release/scripts/startup/bl_ui/properties_physics_field.py
@@ -20,8 +20,10 @@
import bpy
-from properties_physics_common import basic_force_field_settings_ui
-from properties_physics_common import basic_force_field_falloff_ui
+from bl_ui.properties_physics_common import (
+ basic_force_field_settings_ui,
+ basic_force_field_falloff_ui,
+ )
class PhysicButtonsPanel():
@@ -55,7 +57,7 @@ class PHYSICS_PT_field(PhysicButtonsPanel, bpy.types.Panel):
split.prop(field, "type", text="")
- if field.type not in ('NONE', 'GUIDE', 'TEXTURE'):
+ if field.type not in {'NONE', 'GUIDE', 'TEXTURE'}:
split = layout.split(percentage=0.2)
split.label(text="Shape:")
split.prop(field, "shape", text="")
@@ -112,7 +114,7 @@ class PHYSICS_PT_field(PhysicButtonsPanel, bpy.types.Panel):
else:
basic_force_field_settings_ui(self, context, field)
- if field.type not in ('NONE', 'GUIDE'):
+ if field.type not in {'NONE', 'GUIDE'}:
layout.label(text="Falloff:")
layout.prop(field, "falloff_type", expand=True)
@@ -215,13 +217,5 @@ class PHYSICS_PT_collision(PhysicButtonsPanel, bpy.types.Panel):
col.label(text="Force Fields:")
col.prop(settings, "absorption", text="Absorption")
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 6385a535a44..5da89d0090a 100644
--- a/release/scripts/ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -49,11 +49,11 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, bpy.types.Panel):
return
row.prop(fluid, "type")
- if fluid.type not in ('NONE', 'DOMAIN', 'PARTICLE', 'FLUID'):
+ if fluid.type not in {'NONE', 'DOMAIN', 'PARTICLE', 'FLUID'}:
row.prop(fluid, "use", text="")
layout = layout.column()
- if fluid.type not in ('NONE', 'DOMAIN', 'PARTICLE', 'FLUID'):
+ if fluid.type not in {'NONE', 'DOMAIN', 'PARTICLE', 'FLUID'}:
layout.active = fluid.use
if fluid.type == 'DOMAIN':
@@ -123,7 +123,9 @@ class PHYSICS_PT_fluid(PhysicButtonsPanel, bpy.types.Panel):
col.label(text="Volume Initialization:")
col.prop(fluid, "volume_initialization", text="")
col.prop(fluid, "use_animated_mesh")
- col.prop(fluid, "use_local_coords")
+ row = col.row()
+ row.active = not fluid.use_animated_mesh
+ row.prop(fluid, "use_local_coords")
col = split.column()
col.label(text="Inflow Velocity:")
@@ -280,13 +282,5 @@ class PHYSICS_PT_domain_particles(PhysicButtonsPanel, bpy.types.Panel):
col.prop(fluid, "tracer_particles")
col.prop(fluid, "generate_particles")
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_physics_smoke.py b/release/scripts/startup/bl_ui/properties_physics_smoke.py
index 56ddff292d9..61d8d2e3825 100644
--- a/release/scripts/ui/properties_physics_smoke.py
+++ b/release/scripts/startup/bl_ui/properties_physics_smoke.py
@@ -20,8 +20,10 @@
import bpy
-from properties_physics_common import point_cache_ui
-from properties_physics_common import effector_weights_ui
+from bl_ui.properties_physics_common import (
+ point_cache_ui,
+ effector_weights_ui,
+ )
class PhysicButtonsPanel():
@@ -100,9 +102,6 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, bpy.types.Panel):
sub.prop(flow, "density")
sub.prop(flow, "temperature")
- #elif md.smoke_type == 'COLLISION':
- # layout.separator()
-
class PHYSICS_PT_smoke_groups(PhysicButtonsPanel, bpy.types.Panel):
bl_label = "Smoke Groups"
@@ -203,13 +202,5 @@ class PHYSICS_PT_smoke_field_weights(PhysicButtonsPanel, bpy.types.Panel):
domain = context.smoke.domain_settings
effector_weights_ui(self, context, domain.effector_weights)
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_physics_softbody.py b/release/scripts/startup/bl_ui/properties_physics_softbody.py
index 7d3fa66ed02..61115a0590e 100644
--- a/release/scripts/ui/properties_physics_softbody.py
+++ b/release/scripts/startup/bl_ui/properties_physics_softbody.py
@@ -20,8 +20,10 @@
import bpy
-from properties_physics_common import point_cache_ui
-from properties_physics_common import effector_weights_ui
+from bl_ui.properties_physics_common import (
+ point_cache_ui,
+ effector_weights_ui,
+ )
def softbody_panel_enabled(md):
@@ -260,13 +262,5 @@ class PHYSICS_PT_softbody_field_weights(PhysicButtonsPanel, bpy.types.Panel):
effector_weights_ui(self, context, softbody.effector_weights)
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 5dfed9ccb20..a3b10702fa7 100644
--- a/release/scripts/ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -62,13 +62,9 @@ class RENDER_PT_render(RenderButtonsPanel, bpy.types.Panel):
rd = context.scene.render
- split = layout.split()
-
- col = split.column()
- col.operator("render.render", text="Image", icon='RENDER_STILL')
-
- col = split.column()
- col.operator("render.render", text="Animation", icon='RENDER_ANIMATION').animation = True
+ row = layout.row()
+ row.operator("render.render", text="Image", icon='RENDER_STILL')
+ row.operator("render.render", text="Animation", icon='RENDER_ANIMATION').animation = True
layout.prop(rd, "display_mode", text="Display")
@@ -293,6 +289,7 @@ class RENDER_PT_output(RenderButtonsPanel, bpy.types.Panel):
layout.prop(rd, "filepath", text="")
split = layout.split()
+
col = split.column()
col.prop(rd, "file_format", text="")
col.row().prop(rd, "color_mode", text="Color", expand=True)
@@ -302,36 +299,21 @@ class RENDER_PT_output(RenderButtonsPanel, bpy.types.Panel):
col.prop(rd, "use_overwrite")
col.prop(rd, "use_placeholder")
- if file_format in ('AVI_JPEG', 'JPEG'):
- split = layout.split()
- split.prop(rd, "file_quality", slider=True)
+ if file_format in {'AVI_JPEG', 'JPEG'}:
+ layout.prop(rd, "file_quality", slider=True)
if file_format == 'PNG':
- split = layout.split()
- split.prop(rd, "file_quality", slider=True, text="Compression")
-
- elif file_format == 'MULTILAYER':
- split = layout.split()
+ layout.prop(rd, "file_quality", slider=True, text="Compression")
- col = split.column()
- col.label(text="Codec:")
- col.prop(rd, "exr_codec", text="")
- col = split.column()
-
- elif file_format == 'OPEN_EXR':
- split = layout.split()
-
- col = split.column()
- col.label(text="Codec:")
- col.prop(rd, "exr_codec", text="")
+ if file_format in {'OPEN_EXR', 'MULTILAYER'}:
+ row = layout.row()
+ row.prop(rd, "exr_codec", text="Codec")
- subsplit = split.split()
- col = subsplit.column()
- col.prop(rd, "use_exr_half")
- col.prop(rd, "exr_zbuf")
-
- col = subsplit.column()
- col.prop(rd, "exr_preview")
+ if file_format == 'OPEN_EXR':
+ row = layout.row()
+ row.prop(rd, "use_exr_half")
+ row.prop(rd, "exr_zbuf")
+ row.prop(rd, "exr_preview")
elif file_format == 'JPEG2000':
split = layout.split()
@@ -343,7 +325,7 @@ class RENDER_PT_output(RenderButtonsPanel, bpy.types.Panel):
col.prop(rd, "jpeg2k_preset", text="")
col.prop(rd, "jpeg2k_ycc")
- elif file_format in ('CINEON', 'DPX'):
+ elif file_format in {'CINEON', 'DPX'}:
split = layout.split()
split.label("FIXME: hard coded Non-Linear, Gamma:1.0")
@@ -359,12 +341,10 @@ class RENDER_PT_output(RenderButtonsPanel, bpy.types.Panel):
'''
elif file_format == 'TIFF':
- split = layout.split()
- split.prop(rd, "use_tiff_16bit")
+ layout.prop(rd, "use_tiff_16bit")
elif file_format == 'QUICKTIME_CARBON':
- split = layout.split()
- split.operator("scene.render_data_set_quicktime_codec")
+ layout.operator("scene.render_data_set_quicktime_codec")
elif file_format == 'QUICKTIME_QTKIT':
split = layout.split()
@@ -376,12 +356,10 @@ class RENDER_PT_output(RenderButtonsPanel, bpy.types.Panel):
col.prop(rd, "quicktime_audiocodec_type", text="Audio Codec")
if rd.quicktime_audiocodec_type != 'No audio':
split = layout.split()
- col = split.column()
if rd.quicktime_audiocodec_type == 'LPCM':
- col.prop(rd, "quicktime_audio_bitdepth", text="")
+ split.prop(rd, "quicktime_audio_bitdepth", text="")
- col = split.column()
- col.prop(rd, "quicktime_audio_samplerate", text="")
+ split.prop(rd, "quicktime_audio_samplerate", text="")
split = layout.split()
col = split.column()
@@ -406,7 +384,7 @@ class RENDER_PT_encoding(RenderButtonsPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
rd = context.scene.render
- return rd.file_format in ('FFMPEG', 'XVID', 'H264', 'THEORA')
+ return rd.file_format in {'FFMPEG', 'XVID', 'H264', 'THEORA'}
def draw(self, context):
layout = self.layout
@@ -416,22 +394,15 @@ class RENDER_PT_encoding(RenderButtonsPanel, bpy.types.Panel):
layout.menu("RENDER_MT_ffmpeg_presets", text="Presets")
split = layout.split()
-
- col = split.column()
- col.prop(rd, "ffmpeg_format")
- if rd.ffmpeg_format in ('AVI', 'QUICKTIME', 'MKV', 'OGG'):
- col = split.column()
- col.prop(rd, "ffmpeg_codec")
+ split.prop(rd, "ffmpeg_format")
+ if rd.ffmpeg_format in {'AVI', 'QUICKTIME', 'MKV', 'OGG'}:
+ split.prop(rd, "ffmpeg_codec")
else:
split.label()
- split = layout.split()
-
- col = split.column()
- col.prop(rd, "ffmpeg_video_bitrate")
-
- col = split.column()
- col.prop(rd, "ffmpeg_gopsize")
+ row = layout.row()
+ row.prop(rd, "ffmpeg_video_bitrate")
+ row.prop(rd, "ffmpeg_gopsize")
split = layout.split()
@@ -442,28 +413,24 @@ class RENDER_PT_encoding(RenderButtonsPanel, bpy.types.Panel):
col.prop(rd, "ffmpeg_buffersize", text="Buffer")
col = split.column()
-
col.prop(rd, "ffmpeg_autosplit")
col.label(text="Mux:")
col.prop(rd, "ffmpeg_muxrate", text="Rate")
col.prop(rd, "ffmpeg_packetsize", text="Packet Size")
- # Audio:
- sub = layout.column()
-
- if rd.ffmpeg_format not in ('MP3', ):
- sub.prop(rd, "ffmpeg_audio_codec", text="Audio Codec")
+ layout.separator()
- sub.separator()
+ # Audio:
+ if rd.ffmpeg_format not in {'MP3'}:
+ layout.prop(rd, "ffmpeg_audio_codec", text="Audio Codec")
- split = sub.split()
+ split = layout.split()
col = split.column()
col.prop(rd, "ffmpeg_audio_bitrate")
col.prop(rd, "ffmpeg_audio_mixrate")
- col = split.column()
- col.prop(rd, "ffmpeg_audio_volume", slider=True)
+ split.prop(rd, "ffmpeg_audio_volume", slider=True)
class RENDER_PT_antialiasing(RenderButtonsPanel, bpy.types.Panel):
@@ -568,10 +535,7 @@ class RENDER_PT_dimensions(RenderButtonsPanel, bpy.types.Panel):
fps_rate = round(rd.fps / rd.fps_base, 2)
# TODO: Change the following to iterate over existing presets
- if (fps_rate in (23.98, 24, 25, 29.97, 30, 50, 59.94, 60)):
- custom_framerate = False
- else:
- custom_framerate = True
+ custom_framerate = (fps_rate not in {23.98, 24, 25, 29.97, 30, 50, 59.94, 60})
if custom_framerate == True:
fps_label_text = "Custom (" + str(fps_rate) + " fps)"
@@ -580,7 +544,7 @@ class RENDER_PT_dimensions(RenderButtonsPanel, bpy.types.Panel):
sub.menu("RENDER_MT_framerate_presets", text=fps_label_text)
- if (bpy.types.RENDER_MT_framerate_presets.bl_label == "Custom") or (custom_framerate == True):
+ if custom_framerate or (bpy.types.RENDER_MT_framerate_presets.bl_label == "Custom"):
sub.prop(rd, "fps")
sub.prop(rd, "fps_base", text="/")
subrow = sub.row(align=True)
@@ -651,7 +615,7 @@ class RENDER_PT_bake(RenderButtonsPanel, bpy.types.Panel):
if rd.bake_type == 'NORMALS':
layout.prop(rd, "bake_normal_space")
- elif rd.bake_type in ('DISPLACEMENT', 'AO'):
+ elif rd.bake_type in {'DISPLACEMENT', 'AO'}:
layout.prop(rd, "use_bake_normalize")
# col.prop(rd, "bake_aa_mode")
@@ -673,13 +637,5 @@ class RENDER_PT_bake(RenderButtonsPanel, bpy.types.Panel):
sub.prop(rd, "bake_distance")
sub.prop(rd, "bake_bias")
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index 51fe7c9e132..ce5ac0c62d3 100644
--- a/release/scripts/ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -55,14 +55,10 @@ class SCENE_PT_unit(SceneButtonsPanel, bpy.types.Panel):
col.row().prop(unit, "system", expand=True)
col.row().prop(unit, "system_rotation", expand=True)
- split = layout.split()
- split.active = (unit.system != 'NONE')
-
- col = split.column()
- col.prop(unit, "scale_length", text="Scale")
-
- col = split.column()
- col.prop(unit, "use_separate")
+ row = layout.row()
+ row.active = (unit.system != 'NONE')
+ row.prop(unit, "scale_length", text="Scale")
+ row.prop(unit, "use_separate")
class SCENE_PT_keying_sets(SceneButtonsPanel, bpy.types.Panel):
@@ -199,9 +195,6 @@ class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, bpy.types.Panel):
_context_path = "scene"
_property_type = bpy.types.Scene
-
-from bpy.props import *
-
# XXX, move operator to op/ dir
@@ -310,83 +303,75 @@ class ANIM_OT_keying_set_export(bpy.types.Operator):
return {'RUNNING_MODAL'}
class SCENE_PT_navmesh(SceneButtonsPanel, bpy.types.Panel):
- bl_label = "Navmesh"
- bl_default_closed = True
- COMPAT_ENGINES = {'BLENDER_GAME'}
-
- def draw(self, context):
- layout = self.layout
-
- rd = context.scene.game_settings.recast_data
-
- layout.operator("object.create_navmesh", text='Build navigation mesh')
-
- layout.label(text="Rasterization:")
- split = layout.split()
-
- col = split.column()
- col.prop(rd, "cell_size")
- col = split.column()
- col.prop(rd, "cell_height")
-
- layout.separator()
-
- layout.label(text="Agent:")
- split = layout.split()
-
- col = split.column()
- row = col.row()
- row.prop(rd, "agent_height")
- row = col.row()
- row.prop(rd, "agent_radius")
-
- col = split.column()
- row = col.row()
- row.prop(rd, "max_slope")
- row = col.row()
- row.prop(rd, "max_climb")
-
- layout.separator()
-
- layout.label(text="Region:")
- split = layout.split()
- col = split.column()
- col.prop(rd, "region_min_size")
-
- col = split.column()
- col.prop(rd, "region_merge_size")
-
- layout.separator()
-
- layout.label(text="Polygonization:")
- split = layout.split()
- col = split.column()
- row = col.row()
- row.prop(rd, "edge_max_len")
- row = col.row()
- row.prop(rd, "edge_max_error")
-
- col = split.column()
- row = col.row()
- row.prop(rd, "verts_per_poly")
-
- layout.separator()
-
- layout.label(text="Detail Mesh:")
- split = layout.split()
- col = split.column()
- col.prop(rd, "sample_dist")
-
- col = split.column()
- col.prop(rd, "sample_max_error")
-
-
-def register():
+ bl_label = "Navmesh"
+ bl_default_closed = True
+ COMPAT_ENGINES = {'BLENDER_GAME'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.game_settings.recast_data
+
+ layout.operator("object.create_navmesh", text='Build navigation mesh')
+
+ layout.label(text="Rasterization:")
+ split = layout.split()
+
+ col = split.column()
+ col.prop(rd, "cell_size")
+ col = split.column()
+ col.prop(rd, "cell_height")
+
+ layout.separator()
+
+ layout.label(text="Agent:")
+ split = layout.split()
+
+ col = split.column()
+ row = col.row()
+ row.prop(rd, "agent_height")
+ row = col.row()
+ row.prop(rd, "agent_radius")
+
+ col = split.column()
+ row = col.row()
+ row.prop(rd, "max_slope")
+ row = col.row()
+ row.prop(rd, "max_climb")
+
+ layout.separator()
+
+ layout.label(text="Region:")
+ split = layout.split()
+ col = split.column()
+ col.prop(rd, "region_min_size")
+
+ col = split.column()
+ col.prop(rd, "region_merge_size")
+
+ layout.separator()
+
+ layout.label(text="Polygonization:")
+ split = layout.split()
+ col = split.column()
+ row = col.row()
+ row.prop(rd, "edge_max_len")
+ row = col.row()
+ row.prop(rd, "edge_max_error")
+
+ col = split.column()
+ row = col.row()
+ row.prop(rd, "verts_per_poly")
+
+ layout.separator()
+
+ layout.label(text="Detail Mesh:")
+ split = layout.split()
+ col = split.column()
+ col.prop(rd, "sample_dist")
+
+ col = split.column()
+ col.prop(rd, "sample_max_error")
+
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index 05e130fac2d..01890bc3c99 100644
--- a/release/scripts/ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -43,7 +43,7 @@ class TEXTURE_MT_envmap_specials(bpy.types.Menu):
layout.operator("texture.envmap_clear", icon='FILE_REFRESH')
layout.operator("texture.envmap_clear_all", icon='FILE_REFRESH')
-from properties_material import active_node_mat
+from bl_ui.properties_material import active_node_mat
def context_tex_datablock(context):
@@ -60,6 +60,12 @@ def context_tex_datablock(context):
return idblock
idblock = context.brush
+ if idblock:
+ return idblock
+
+ if context.particle_system:
+ idblock = context.particle_system.settings
+
return idblock
@@ -84,7 +90,7 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, bpy.types.Panel):
engine = context.scene.render.engine
if not hasattr(context, "texture_slot"):
return False
- return ((context.material or context.world or context.lamp or context.brush or context.texture)
+ 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):
@@ -96,13 +102,14 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, bpy.types.Panel):
idblock = context_tex_datablock(context)
pin_id = space.pin_id
- if not isinstance(pin_id, bpy.types.Material):
+ if space.use_pin_id and not isinstance(pin_id, bpy.types.Texture):
+ idblock = pin_id
pin_id = None
if not space.use_pin_id:
layout.prop(space, "texture_context", expand=True)
- tex_collection = (not space.use_pin_id) and (node is None) and (not isinstance(idblock, bpy.types.Brush))
+ tex_collection = (pin_id is None) and (node is None) and (not isinstance(idblock, bpy.types.Brush))
if tex_collection:
row = layout.row()
@@ -237,8 +244,7 @@ class TEXTURE_PT_clouds(TextureTypePanel, bpy.types.Panel):
col.prop(tex, "noise_scale", text="Size")
col.prop(tex, "noise_depth", text="Depth")
- col = split.column()
- col.prop(tex, "nabla", text="Nabla")
+ split.prop(tex, "nabla", text="Nabla")
class TEXTURE_PT_wood(TextureTypePanel, bpy.types.Panel):
@@ -251,24 +257,23 @@ class TEXTURE_PT_wood(TextureTypePanel, bpy.types.Panel):
tex = context.texture
- layout.prop(tex, "noisebasis_2", expand=True)
+ layout.prop(tex, "noise_basis_2", expand=True)
layout.prop(tex, "wood_type", expand=True)
col = layout.column()
- col.active = tex.wood_type in ('RINGNOISE', 'BANDNOISE')
+ col.active = tex.wood_type in {'RINGNOISE', 'BANDNOISE'}
col.label(text="Noise:")
col.row().prop(tex, "noise_type", text="Type", expand=True)
layout.prop(tex, "noise_basis", text="Basis")
split = layout.split()
- split.active = tex.wood_type in ('RINGNOISE', 'BANDNOISE')
+ split.active = tex.wood_type in {'RINGNOISE', 'BANDNOISE'}
col = split.column()
col.prop(tex, "noise_scale", text="Size")
col.prop(tex, "turbulence")
- col = split.column()
- col.prop(tex, "nabla")
+ split.prop(tex, "nabla")
class TEXTURE_PT_marble(TextureTypePanel, bpy.types.Panel):
@@ -282,7 +287,7 @@ class TEXTURE_PT_marble(TextureTypePanel, bpy.types.Panel):
tex = context.texture
layout.prop(tex, "marble_type", expand=True)
- layout.prop(tex, "noisebasis_2", expand=True)
+ layout.prop(tex, "noise_basis_2", expand=True)
layout.label(text="Noise:")
layout.prop(tex, "noise_type", text="Type", expand=True)
layout.prop(tex, "noise_basis", text="Basis")
@@ -308,13 +313,9 @@ class TEXTURE_PT_magic(TextureTypePanel, bpy.types.Panel):
tex = context.texture
- split = layout.split()
-
- col = split.column()
- col.prop(tex, "noise_depth", text="Depth")
-
- col = split.column()
- col.prop(tex, "turbulence")
+ row = layout.row()
+ row.prop(tex, "noise_depth", text="Depth")
+ row.prop(tex, "turbulence")
class TEXTURE_PT_blend(TextureTypePanel, bpy.types.Panel):
@@ -331,7 +332,7 @@ class TEXTURE_PT_blend(TextureTypePanel, bpy.types.Panel):
sub = layout.row()
- sub.active = (tex.progression in ('LINEAR', 'QUADRATIC', 'EASING', 'RADIAL'))
+ sub.active = (tex.progression in {'LINEAR', 'QUADRATIC', 'EASING', 'RADIAL'})
sub.prop(tex, "use_flip_axis", expand=True)
@@ -350,13 +351,9 @@ class TEXTURE_PT_stucci(TextureTypePanel, bpy.types.Panel):
layout.prop(tex, "noise_type", text="Type", expand=True)
layout.prop(tex, "noise_basis", text="Basis")
- split = layout.split()
-
- col = split.column()
- col.prop(tex, "noise_scale", text="Size")
-
- col = split.column()
- col.prop(tex, "turbulence")
+ row = layout.row()
+ row.prop(tex, "noise_scale", text="Size")
+ row.prop(tex, "turbulence")
class TEXTURE_PT_image(TextureTypePanel, bpy.types.Panel):
@@ -375,7 +372,7 @@ class TEXTURE_PT_image(TextureTypePanel, bpy.types.Panel):
def texture_filter_common(tex, layout):
layout.label(text="Filter:")
layout.prop(tex, "filter_type", text="")
- if tex.use_mipmap and tex.filter_type in ('AREA', 'EWA', 'FELINE'):
+ if tex.use_mipmap and tex.filter_type in {'AREA', 'EWA', 'FELINE'}:
if tex.filter_type == 'FELINE':
layout.prop(tex, "filter_probes", text="Probes")
else:
@@ -555,24 +552,20 @@ class TEXTURE_PT_musgrave(TextureTypePanel, bpy.types.Panel):
musgrave_type = tex.musgrave_type
col = split.column()
- if musgrave_type in ('HETERO_TERRAIN', 'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'):
+ if musgrave_type in {'HETERO_TERRAIN', 'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'}:
col.prop(tex, "offset")
- if musgrave_type in ('MULTIFRACTAL', 'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'):
+ if musgrave_type in {'MULTIFRACTAL', 'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'}:
col.prop(tex, "noise_intensity", text="Intensity")
- if musgrave_type in ('RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'):
+ if musgrave_type in {'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'}:
col.prop(tex, "gain")
layout.label(text="Noise:")
layout.prop(tex, "noise_basis", text="Basis")
- split = layout.split()
-
- col = split.column()
- col.prop(tex, "noise_scale", text="Size")
-
- col = split.column()
- col.prop(tex, "nabla")
+ row = layout.row()
+ row.prop(tex, "noise_scale", text="Size")
+ row.prop(tex, "nabla")
class TEXTURE_PT_voronoi(TextureTypePanel, bpy.types.Panel):
@@ -606,14 +599,9 @@ class TEXTURE_PT_voronoi(TextureTypePanel, bpy.types.Panel):
sub.prop(tex, "weight_4", text="4", slider=True)
layout.label(text="Noise:")
-
- split = layout.split()
-
- col = split.column()
- col.prop(tex, "noise_scale", text="Size")
-
- col = split.column()
- col.prop(tex, "nabla")
+ row = layout.row()
+ row.prop(tex, "noise_scale", text="Size")
+ row.prop(tex, "nabla")
class TEXTURE_PT_distortednoise(TextureTypePanel, bpy.types.Panel):
@@ -635,8 +623,7 @@ class TEXTURE_PT_distortednoise(TextureTypePanel, bpy.types.Panel):
col.prop(tex, "distortion", text="Distortion")
col.prop(tex, "noise_scale", text="Size")
- col = split.column()
- col.prop(tex, "nabla")
+ split.prop(tex, "nabla")
class TEXTURE_PT_voxeldata(TextureButtonsPanel, bpy.types.Panel):
@@ -656,7 +643,7 @@ class TEXTURE_PT_voxeldata(TextureButtonsPanel, bpy.types.Panel):
vd = tex.voxel_data
layout.prop(vd, "file_format")
- if vd.file_format in ('BLENDER_VOXEL', 'RAW_8BIT'):
+ if vd.file_format in {'BLENDER_VOXEL', 'RAW_8BIT'}:
layout.prop(vd, "filepath")
if vd.file_format == 'RAW_8BIT':
layout.prop(vd, "resolution")
@@ -668,7 +655,7 @@ class TEXTURE_PT_voxeldata(TextureButtonsPanel, bpy.types.Panel):
layout.template_image(tex, "image", tex.image_user, compact=True)
#layout.prop(vd, "frame_duration")
- if vd.file_format in ('BLENDER_VOXEL', 'RAW_8BIT'):
+ if vd.file_format in {'BLENDER_VOXEL', 'RAW_8BIT'}:
layout.prop(vd, "use_still_frame")
row = layout.row()
row.active = vd.use_still_frame
@@ -719,12 +706,13 @@ class TEXTURE_PT_pointdensity(TextureButtonsPanel, bpy.types.Panel):
col.separator()
- col.label(text="Color Source:")
- col.prop(pd, "color_source", text="")
- if pd.color_source in ('PARTICLE_SPEED', 'PARTICLE_VELOCITY'):
- col.prop(pd, "speed_scale")
- if pd.color_source in ('PARTICLE_SPEED', 'PARTICLE_AGE'):
- layout.template_color_ramp(pd, "color_ramp", expand=True)
+ if pd.point_source == 'PARTICLE_SYSTEM':
+ col.label(text="Color Source:")
+ col.prop(pd, "color_source", text="")
+ if pd.color_source in {'PARTICLE_SPEED', 'PARTICLE_VELOCITY'}:
+ col.prop(pd, "speed_scale")
+ if pd.color_source in {'PARTICLE_SPEED', 'PARTICLE_AGE'}:
+ layout.template_color_ramp(pd, "color_ramp", expand=True)
col = split.column()
col.label()
@@ -733,6 +721,15 @@ class TEXTURE_PT_pointdensity(TextureButtonsPanel, bpy.types.Panel):
col.prop(pd, "falloff", text="")
if pd.falloff == 'SOFT':
col.prop(pd, "falloff_soft")
+ if pd.falloff == "PARTICLE_VELOCITY":
+ col.prop(pd, "falloff_speed_scale")
+
+ col.prop(pd, "use_falloff_curve")
+
+ if pd.use_falloff_curve:
+ col = layout.column()
+ col.label(text="Falloff Curve")
+ col.template_curve_mapping(pd, "falloff_curve", brush=False)
class TEXTURE_PT_pointdensity_turbulence(TextureButtonsPanel, bpy.types.Panel):
@@ -746,12 +743,9 @@ class TEXTURE_PT_pointdensity_turbulence(TextureButtonsPanel, bpy.types.Panel):
return tex and (tex.type == 'POINT_DENSITY' and (engine in cls.COMPAT_ENGINES))
def draw_header(self, context):
- layout = self.layout
+ pd = context.texture.point_density
- tex = context.texture
- pd = tex.point_density
-
- layout.prop(pd, "use_turbulence", text="")
+ self.layout.prop(pd, "use_turbulence", text="")
def draw(self, context):
layout = self.layout
@@ -834,7 +828,7 @@ class TEXTURE_PT_mapping(TextureSlotPanel, bpy.types.Panel):
layout.prop(tex, "map_mode", expand=True)
row = layout.row()
- row.active = tex.map_mode in ('FIXED', 'TILED')
+ row.active = tex.map_mode in {'FIXED', 'TILED'}
row.prop(tex, "angle")
else:
if isinstance(idblock, bpy.types.Material):
@@ -845,7 +839,7 @@ class TEXTURE_PT_mapping(TextureSlotPanel, bpy.types.Panel):
split = layout.split()
col = split.column()
- if tex.texture_coords in ('ORCO', 'UV'):
+ if tex.texture_coords in {'ORCO', 'UV'}:
col.prop(tex, "use_from_dupli")
elif tex.texture_coords == 'OBJECT':
col.prop(tex, "use_from_original")
@@ -858,14 +852,9 @@ class TEXTURE_PT_mapping(TextureSlotPanel, bpy.types.Panel):
row.prop(tex, "mapping_y", text="")
row.prop(tex, "mapping_z", text="")
- split = layout.split()
-
- col = split.column()
- col.prop(tex, "offset")
-
- col = split.column()
-
- col.prop(tex, "scale")
+ row = layout.row()
+ row.column().prop(tex, "offset")
+ row.column().prop(tex, "scale")
class TEXTURE_PT_influence(TextureSlotPanel, bpy.types.Panel):
@@ -902,7 +891,7 @@ class TEXTURE_PT_influence(TextureSlotPanel, bpy.types.Panel):
return sub # XXX, temp. use_map_normal needs to override.
if isinstance(idblock, bpy.types.Material):
- if idblock.type in ('SURFACE', 'WIRE'):
+ if idblock.type in {'SURFACE', 'WIRE'}:
split = layout.split()
col = split.column()
@@ -983,38 +972,65 @@ class TEXTURE_PT_influence(TextureSlotPanel, bpy.types.Panel):
col = split.column()
factor_but(col, "use_map_zenith_up", "zenith_up_factor", "Zenith Up")
factor_but(col, "use_map_zenith_down", "zenith_down_factor", "Zenith Down")
+ elif isinstance(idblock, bpy.types.ParticleSettings):
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="General:")
+ factor_but(col, "use_map_time", "time_factor", "Time")
+ factor_but(col, "use_map_life", "life_factor", "Lifetime")
+ factor_but(col, "use_map_density", "density_factor", "Density")
+ factor_but(col, "use_map_size", "size_factor", "Size")
+
+ col = split.column()
+ col.label(text="Physics:")
+ factor_but(col, "use_map_velocity", "velocity_factor", "Velocity")
+ factor_but(col, "use_map_damp", "damp_factor", "Damp")
+ factor_but(col, "use_map_gravity", "gravity_factor", "Gravity")
+ factor_but(col, "use_map_field", "field_factor", "Force Fields")
+
+ layout.label(text="Hair:")
+
+ split = layout.split()
+
+ col = split.column()
+ factor_but(col, "use_map_length", "length_factor", "Length")
+ factor_but(col, "use_map_clump", "clump_factor", "Clump")
+
+ col = split.column()
+ factor_but(col, "use_map_kink", "kink_factor", "Kink")
+ factor_but(col, "use_map_rough", "rough_factor", "Rough")
layout.separator()
- split = layout.split()
+ if not isinstance(idblock, bpy.types.ParticleSettings):
+ split = layout.split()
- col = split.column()
- col.prop(tex, "blend_type", text="Blend")
- col.prop(tex, "use_rgb_to_intensity")
- # color is used on grayscale textures even when use_rgb_to_intensity is disabled.
- col.prop(tex, "color", text="")
+ col = split.column()
+ col.prop(tex, "blend_type", text="Blend")
+ col.prop(tex, "use_rgb_to_intensity")
+ # color is used on grayscale textures even when use_rgb_to_intensity is disabled.
+ col.prop(tex, "color", text="")
- col = split.column()
- col.prop(tex, "invert", text="Negative")
- col.prop(tex, "use_stencil")
+ col = split.column()
+ col.prop(tex, "invert", text="Negative")
+ col.prop(tex, "use_stencil")
if isinstance(idblock, bpy.types.Material) or isinstance(idblock, bpy.types.World):
col.prop(tex, "default_value", text="DVar", slider=True)
if isinstance(idblock, bpy.types.Material):
- row = layout.row()
- row.label(text="Bump Mapping:")
+ layout.label(text="Bump Mapping:")
- row = layout.row()
# only show bump settings if activated but not for normalmap images
- row.active = tex.use_map_normal and not (tex.texture.type == 'IMAGE' and tex.texture.use_normal_map)
+ 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)
- col = row.column()
- col.prop(tex, "bump_method", text="Method")
+ row.prop(tex, "bump_method", text="Method")
- col = row.column()
- col.prop(tex, "bump_objectspace", text="Space")
- col.active = tex.bump_method in ('BUMP_DEFAULT', 'BUMP_BEST_QUALITY')
+ sub = row.row()
+ sub.active = tex.bump_method in {'BUMP_DEFAULT', 'BUMP_BEST_QUALITY'}
+ sub.prop(tex, "bump_objectspace", text="Space")
class TEXTURE_PT_custom_props(TextureButtonsPanel, PropertyPanel, bpy.types.Panel):
@@ -1022,13 +1038,5 @@ class TEXTURE_PT_custom_props(TextureButtonsPanel, PropertyPanel, bpy.types.Pane
_context_path = "texture"
_property_type = bpy.types.Texture
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/properties_world.py b/release/scripts/startup/bl_ui/properties_world.py
index fd11f299f34..4f398c9fbd9 100644
--- a/release/scripts/ui/properties_world.py
+++ b/release/scripts/startup/bl_ui/properties_world.py
@@ -266,13 +266,5 @@ class WORLD_PT_custom_props(WorldButtonsPanel, PropertyPanel, bpy.types.Panel):
_context_path = "world"
_property_type = bpy.types.World
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_console.py b/release/scripts/startup/bl_ui/space_console.py
index b3bd886d8c5..da6c102100b 100644
--- a/release/scripts/ui/space_console.py
+++ b/release/scripts/startup/bl_ui/space_console.py
@@ -18,15 +18,13 @@
# <pep8 compliant>
import bpy
-from bpy.props import *
+from bpy.props import StringProperty
class CONSOLE_HT_header(bpy.types.Header):
bl_space_type = 'CONSOLE'
def draw(self, context):
- sc = context.space_data
- # text = sc.text
layout = self.layout
row = layout.row(align=True)
@@ -161,13 +159,5 @@ class ConsoleLanguage(bpy.types.Operator):
return {'FINISHED'}
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index 9a1acfd76b8..930a2029d32 100644
--- a/release/scripts/ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -33,48 +33,52 @@ def dopesheet_filter(layout, context, genericFiltersOnly=False):
row.prop(dopesheet, "show_only_selected", text="")
row.prop(dopesheet, "show_hidden", text="")
- if genericFiltersOnly:
- return
-
- row = layout.row(align=True)
- row.prop(dopesheet, "show_transforms", 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="")
+ 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 bpy.data.groups:
row = layout.row(align=True)
- row.prop(dopesheet, "show_only_group_objects", text="")
- if dopesheet.show_only_group_objects:
- row.prop(dopesheet, "filter_group", text="")
+ 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 bpy.data.groups:
+ row = layout.row(align=True)
+ row.prop(dopesheet, "show_only_group_objects", text="")
+ if dopesheet.show_only_group_objects:
+ row.prop(dopesheet, "filter_group", text="")
+
+ if not is_nla:
+ row = layout.row(align=True)
+ row.prop(dopesheet, "show_only_matching_fcurves", text="")
+ if dopesheet.show_only_matching_fcurves:
+ row.prop(dopesheet, "filter_fcurve_name", text="")
#######################################
@@ -118,7 +122,7 @@ class DOPESHEET_HT_header(bpy.types.Header):
# filters which will work here and are useful (especially for character animation)
dopesheet_filter(layout, context, genericFiltersOnly=True)
- if st.mode in ('ACTION', 'SHAPEKEY'):
+ if st.mode in {'ACTION', 'SHAPEKEY'}:
layout.template_ID(st, "action", new="action.new")
# Grease Pencil mode doesn't need snapping, as it's frame-aligned only
@@ -159,6 +163,7 @@ class DOPESHEET_MT_view(bpy.types.Menu):
layout.separator()
layout.operator("action.frame_jump")
layout.operator("action.view_all")
+ layout.operator("action.view_selected")
layout.separator()
layout.operator("screen.area_dupli")
@@ -187,6 +192,10 @@ class DOPESHEET_MT_select(bpy.types.Menu):
layout.operator("action.select_column", text="Columns on Selected Markers").mode = 'MARKERS_COLUMN'
layout.operator("action.select_column", text="Between Selected Markers").mode = 'MARKERS_BETWEEN'
+ layout.separator()
+ layout.operator("action.select_leftright", text="Before Current Frame").mode = 'LEFT'
+ layout.operator("action.select_leftright", text="After Current Frame").mode = 'RIGHT'
+
# FIXME: grease pencil mode isn't supported for these yet, so skip for that mode only
if context.space_data.mode != 'GPENCIL':
layout.separator()
@@ -217,10 +226,13 @@ class DOPESHEET_MT_marker(bpy.types.Menu):
layout.operator("marker.rename", text="Rename Marker")
layout.operator("marker.move", text="Grab/Move Marker")
- if st.mode in ('ACTION', 'SHAPEKEY') and st.action:
+ if st.mode in {'ACTION', 'SHAPEKEY'} and st.action:
layout.separator()
layout.prop(st, "show_pose_markers")
+ if st.show_pose_markers is False:
+ layout.operator("action.markers_make_local")
+
#######################################
# Keyframe Editing
@@ -353,13 +365,5 @@ class DOPESHEET_MT_gpencil_frame(bpy.types.Menu):
#layout.operator("action.copy")
#layout.operator("action.paste")
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py
index 2d66bb38637..73fe1a97252 100644
--- a/release/scripts/ui/space_filebrowser.py
+++ b/release/scripts/startup/bl_ui/space_filebrowser.py
@@ -43,7 +43,7 @@ class FILEBROWSER_HT_header(bpy.types.Header):
row.separator()
row = layout.row(align=True)
- row.operator("file.directory_new", text="", icon='NEWFOLDER')
+ row.operator("file.directory_new", icon='NEWFOLDER')
params = st.params
@@ -73,13 +73,5 @@ class FILEBROWSER_HT_header(bpy.types.Header):
row.prop(params, "use_filter_sound", text="")
row.prop(params, "use_filter_text", text="")
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index 55c4d4cfd94..bfc1a0e3a23 100644
--- a/release/scripts/ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -25,7 +25,7 @@ class GRAPH_HT_header(bpy.types.Header):
bl_space_type = 'GRAPH_EDITOR'
def draw(self, context):
- from space_dopesheet import dopesheet_filter
+ from bl_ui.space_dopesheet import dopesheet_filter
layout = self.layout
@@ -100,6 +100,7 @@ class GRAPH_MT_view(bpy.types.Menu):
layout.separator()
layout.operator("graph.frame_jump")
layout.operator("graph.view_all")
+ layout.operator("graph.view_selected")
layout.separator()
layout.operator("screen.area_dupli")
@@ -130,6 +131,10 @@ class GRAPH_MT_select(bpy.types.Menu):
layout.operator("graph.select_column", text="Between Selected Markers").mode = 'MARKERS_BETWEEN'
layout.separator()
+ layout.operator("graph.select_leftright", text="Before Current Frame").mode = 'LEFT'
+ layout.operator("graph.select_leftright", text="After Current Frame").mode = 'RIGHT'
+
+ layout.separator()
layout.operator("graph.select_more")
layout.operator("graph.select_less")
@@ -205,6 +210,7 @@ class GRAPH_MT_key(bpy.types.Menu):
layout.separator()
layout.operator("graph.keyframe_insert")
layout.operator("graph.fmodifier_add")
+ layout.operator("graph.sound_bake")
layout.separator()
layout.operator("graph.duplicate")
@@ -240,13 +246,5 @@ class GRAPH_MT_key_transform(bpy.types.Menu):
layout.operator("transform.rotate", text="Rotate")
layout.operator("transform.resize", text="Scale")
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 433c12b0620..77583b80824 100644
--- a/release/scripts/ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -91,8 +91,8 @@ class IMAGE_MT_select(bpy.types.Menu):
layout.separator()
layout.operator("uv.select_all")
- layout.operator("uv.select_inverse")
- layout.operator("uv.unlink_selection")
+ layout.operator("uv.select_all", text="Inverse").action = 'INVERT'
+ layout.operator("uv.unlink_selected")
layout.separator()
@@ -128,6 +128,10 @@ class IMAGE_MT_image(bpy.types.Menu):
layout.operator("image.external_edit", "Edit Externally")
+ layout.separator()
+
+ layout.menu("IMAGE_MT_image_invert")
+
if not show_render:
layout.separator()
@@ -139,7 +143,7 @@ class IMAGE_MT_image(bpy.types.Menu):
# only for dirty && specific image types, perhaps
# this could be done in operator poll too
if ima.is_dirty:
- if ima.source in ('FILE', 'GENERATED') and ima.type != 'MULTILAYER':
+ if ima.source in {'FILE', 'GENERATED'} and ima.type != 'MULTILAYER':
layout.operator("image.pack", text="Pack As PNG").as_png = True
layout.separator()
@@ -147,6 +151,32 @@ class IMAGE_MT_image(bpy.types.Menu):
layout.prop(sima, "use_image_paint")
+class IMAGE_MT_image_invert(bpy.types.Menu):
+ bl_label = "Invert"
+
+ def draw(self, context):
+ layout = self.layout
+
+ op = layout.operator("image.invert", text="Invert Image Colors")
+ op.invert_r = True
+ op.invert_g = True
+ op.invert_b = True
+
+ layout.separator()
+
+ op = layout.operator("image.invert", text="Invert Red Channel")
+ op.invert_r = True
+
+ op = layout.operator("image.invert", text="Invert Green Channel")
+ op.invert_g = True
+
+ op = layout.operator("image.invert", text="Invert Blue Channel")
+ op.invert_b = True
+
+ op = layout.operator("image.invert", text="Invert Alpha Channel")
+ op.invert_a = True
+
+
class IMAGE_MT_uvs_showhide(bpy.types.Menu):
bl_label = "Show/Hide Faces"
@@ -176,14 +206,14 @@ class IMAGE_MT_uvs_snap(bpy.types.Menu):
layout = self.layout
layout.operator_context = 'EXEC_REGION_WIN'
- layout.operator("uv.snap_selection", text="Selected to Pixels").target = 'PIXELS'
- layout.operator("uv.snap_selection", text="Selected to Cursor").target = 'CURSOR'
- layout.operator("uv.snap_selection", text="Selected to Adjacent Unselected").target = 'ADJACENT_UNSELECTED'
+ layout.operator("uv.snap_selected", text="Selected to Pixels").target = 'PIXELS'
+ layout.operator("uv.snap_selected", text="Selected to Cursor").target = 'CURSOR'
+ layout.operator("uv.snap_selected", text="Selected to Adjacent Unselected").target = 'ADJACENT_UNSELECTED'
layout.separator()
layout.operator("uv.snap_cursor", text="Cursor to Pixels").target = 'PIXELS'
- layout.operator("uv.snap_cursor", text="Cursor to Selection").target = 'SELECTION'
+ layout.operator("uv.snap_cursor", text="Cursor to Selected").target = 'SELECTED'
class IMAGE_MT_uvs_mirror(bpy.types.Menu):
@@ -204,7 +234,7 @@ class IMAGE_MT_uvs_weldalign(bpy.types.Menu):
layout = self.layout
layout.operator("uv.weld") # W, 1
- layout.operator_enums("uv.align", "axis") # W, 2/3/4
+ layout.operator_enum("uv.align", "axis") # W, 2/3/4
class IMAGE_MT_uvs(bpy.types.Menu):
@@ -233,7 +263,7 @@ class IMAGE_MT_uvs(bpy.types.Menu):
layout.operator("uv.average_islands_scale")
layout.operator("uv.minimize_stretch")
layout.operator("uv.stitch")
- layout.operator("mesh.faces_miror_uv")
+ layout.operator("mesh.faces_mirror_uv")
layout.separator()
@@ -340,10 +370,7 @@ class IMAGE_HT_header(bpy.types.Header):
layout.prop(toolsettings, "use_uv_select_sync", text="")
if toolsettings.use_uv_select_sync:
- row = layout.row(align=True)
- row.prop(toolsettings, "mesh_select_mode", text="", index=0, icon='VERTEXSEL')
- row.prop(toolsettings, "mesh_select_mode", text="", index=1, icon='EDGESEL')
- row.prop(toolsettings, "mesh_select_mode", text="", index=2, icon='FACESEL')
+ layout.template_edit_mode_selection()
else:
layout.prop(toolsettings, "uv_select_mode", text="", expand=True)
layout.prop(uvedit, "sticky_select_mode", text="", icon_only=True)
@@ -357,8 +384,8 @@ class IMAGE_HT_header(bpy.types.Header):
row.prop(toolsettings, "use_snap", text="")
row.prop(toolsettings, "snap_element", text="", icon_only=True)
- # mesh = context.edit_object.data
- # row.prop_search(mesh.uv_textures, "active", mesh, "uv_textures")
+ mesh = context.edit_object.data
+ layout.prop_search(mesh.uv_textures, "active", mesh, "uv_textures", text="")
if ima:
# layers
@@ -374,7 +401,7 @@ class IMAGE_HT_header(bpy.types.Header):
row = layout.row(align=True)
if ima.type == 'COMPOSITE':
row.operator("image.record_composite", icon='REC')
- if ima.type == 'COMPOSITE' and ima.source in ('MOVIE', 'SEQUENCE'):
+ if ima.type == 'COMPOSITE' and ima.source in {'MOVIE', 'SEQUENCE'}:
row.operator("image.play_composite", icon='PLAY')
if show_uvedit or sima.use_image_paint:
@@ -395,7 +422,6 @@ class IMAGE_PT_image_properties(bpy.types.Panel):
layout = self.layout
sima = context.space_data
- # ima = sima.image
iuser = sima.image_user
layout.template_image(sima, "image", iuser)
@@ -578,7 +604,9 @@ class IMAGE_PT_view_properties(bpy.types.Panel):
if show_uvedit:
col = layout.column()
- col.prop(uvedit, "cursor_location")
+ col.label("Cursor Location")
+ row = col.row()
+ row.prop(uvedit, "cursor_location", text="")
col = layout.column()
col.label(text="UVs:")
@@ -638,7 +666,7 @@ class IMAGE_PT_paint(bpy.types.Panel):
col.prop(brush, "blend", text="Blend")
- if brush.imagepaint_tool == 'CLONE':
+ if brush.image_tool == 'CLONE':
col.separator()
col.prop(brush, "clone_image", text="Image")
col.prop(brush, "clone_alpha", text="Alpha")
@@ -654,11 +682,9 @@ class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, bpy.types.Panel):
toolsettings = context.tool_settings.image_paint
brush = toolsettings.brush
-# tex_slot = brush.texture_slot
-
col = layout.column()
-
col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
+ col.prop(brush, "use_fixed_texture")
class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, bpy.types.Panel):
@@ -672,13 +698,13 @@ class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, bpy.types.Panel):
col = layout.column(align=True)
- col.prop(brush, "imagepaint_tool", expand=False, text="")
+ col.prop(brush, "image_tool", expand=False, text="")
row = layout.row(align=True)
row.prop(brush, "use_paint_sculpt", text="", icon='SCULPTMODE_HLT')
row.prop(brush, "use_paint_vertex", text="", icon='VPAINT_HLT')
row.prop(brush, "use_paint_weight", text="", icon='WPAINT_HLT')
- row.prop(brush, "use_paint_texture", text="", icon='TPAINT_HLT')
+ row.prop(brush, "use_paint_image", text="", icon='TPAINT_HLT')
class IMAGE_PT_paint_stroke(BrushButtonsPanel, bpy.types.Panel):
@@ -725,13 +751,5 @@ class IMAGE_PT_paint_curve(BrushButtonsPanel, bpy.types.Panel):
row.operator("brush.curve_preset", icon="LINCURVE", text="").shape = 'LINE'
row.operator("brush.curve_preset", icon="NOCURVE", text="").shape = 'MAX'
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py
index 6c392cb9a3d..1fb2e5b735e 100644
--- a/release/scripts/ui/space_info.py
+++ b/release/scripts/startup/bl_ui/space_info.py
@@ -26,9 +26,7 @@ class INFO_HT_header(bpy.types.Header):
def draw(self, context):
layout = self.layout
- wm = context.window_manager
window = context.window
- sinfo = context.space_data
scene = context.scene
rd = scene.render
@@ -70,6 +68,7 @@ class INFO_HT_header(bpy.types.Header):
# XXX: BEFORE RELEASE, MOVE FILE MENU OUT OF INFO!!!
"""
+ sinfo = context.space_data
row = layout.row(align=True)
row.prop(sinfo, "show_report_debug", text="Debug")
row.prop(sinfo, "show_report_info", text="Info")
@@ -203,6 +202,7 @@ class INFO_MT_mesh_add(bpy.types.Menu):
layout.separator()
layout.operator("mesh.primitive_grid_add", icon='MESH_GRID', text="Grid")
layout.operator("mesh.primitive_monkey_add", icon='MESH_MONKEY', text="Monkey")
+ layout.operator("mesh.primitive_torus_add", text="Torus", icon='MESH_TORUS')
class INFO_MT_curve_add(bpy.types.Menu):
@@ -327,8 +327,6 @@ class INFO_MT_render(bpy.types.Menu):
def draw(self, context):
layout = self.layout
- # rd = context.scene.render
-
layout.operator("render.render", text="Render Image", icon='RENDER_STILL')
layout.operator("render.render", text="Render Animation", icon='RENDER_ANIMATION').animation = True
@@ -352,7 +350,7 @@ class INFO_MT_help(bpy.types.Menu):
layout = self.layout
layout.operator("wm.url_open", text="Manual", icon='HELP').url = 'http://wiki.blender.org/index.php/Doc:Manual'
- layout.operator("wm.url_open", text="Release Log", icon='URL').url = 'http://www.blender.org/development/release-logs/blender-256-beta/'
+ layout.operator("wm.url_open", text="Release Log", icon='URL').url = 'http://www.blender.org/development/release-logs/blender-257/'
layout.separator()
@@ -363,16 +361,17 @@ class INFO_MT_help(bpy.types.Menu):
layout.separator()
layout.operator("wm.url_open", text="Report a Bug", icon='URL').url = 'http://projects.blender.org/tracker/?atid=498&group_id=9&func=browse'
layout.separator()
- layout.operator("wm.url_open", text="Python API Reference", icon='URL').url = "http://www.blender.org/documentation/blender_python_api_%s/contents.html" % "_".join(str(v) for v in bpy.app.version)
+
+ layout.operator("wm.url_open", text="Python API Reference", icon='URL').url = bpy.types.WM_OT_doc_view._prefix
layout.operator("help.operator_cheat_sheet", icon='TEXT')
layout.operator("wm.sysinfo", icon='TEXT')
layout.separator()
- if sys.platform == "win32":
- layout.operator("wm.toggle_console", icon='CONSOLE')
+ if sys.platform[:3] == "win":
+ layout.operator("wm.console_toggle", icon='CONSOLE')
layout.separator()
- layout.operator("anim.update_data_paths", text="FCurve/Driver 2.54 fix", icon='HELP')
+ layout.operator("anim.update_data_paths", text="FCurve/Driver Version fix", icon='HELP')
layout.separator()
- layout.operator("wm.splash")
+ layout.operator("wm.splash", icon='BLENDER')
# Help operators
@@ -402,13 +401,5 @@ class HELP_OT_operator_cheat_sheet(bpy.types.Operator):
self.report({'INFO'}, "See OperatorList.txt textblock")
return {'FINISHED'}
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_logic.py b/release/scripts/startup/bl_ui/space_logic.py
index 54dde61e90a..7f7aba71a46 100644
--- a/release/scripts/ui/space_logic.py
+++ b/release/scripts/startup/bl_ui/space_logic.py
@@ -66,8 +66,6 @@ class LOGIC_HT_header(bpy.types.Header):
def draw(self, context):
layout = self.layout
- st = context.space_data
-
row = layout.row(align=True)
row.template_header()
@@ -88,13 +86,5 @@ class LOGIC_MT_view(bpy.types.Menu):
layout.operator("logic.properties", icon='MENU_PANEL')
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py
index 13afc97f913..717adb3baa8 100644
--- a/release/scripts/ui/space_nla.py
+++ b/release/scripts/startup/bl_ui/space_nla.py
@@ -25,7 +25,7 @@ class NLA_HT_header(bpy.types.Header):
bl_space_type = 'NLA_EDITOR'
def draw(self, context):
- from space_dopesheet import dopesheet_filter
+ from bl_ui.space_dopesheet import dopesheet_filter
layout = self.layout
@@ -93,6 +93,10 @@ class NLA_MT_select(bpy.types.Menu):
layout.operator("nla.select_border")
layout.operator("nla.select_border", text="Border Axis Range").axis_range = True
+ layout.separator()
+ layout.operator("nla.select_leftright", text="Before Current Frame").mode = 'LEFT'
+ layout.operator("nla.select_leftright", text="After Current Frame").mode = 'RIGHT'
+
class NLA_MT_marker(bpy.types.Menu):
bl_label = "Marker"
@@ -184,15 +188,7 @@ class NLA_MT_edit_transform(bpy.types.Menu):
layout.column()
layout.operator("transform.translate", text="Grab/Move")
layout.operator("transform.transform", text="Extend").mode = 'TIME_EXTEND'
- layout.operator("transform.resize", text="Scale")
-
+ layout.operator("transform.transform", text="Scale").mode = 'TIME_SCALE'
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index aaf14813ee5..fed1cc49c4c 100644
--- a/release/scripts/ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -156,9 +156,6 @@ class NODE_MT_node(bpy.types.Menu):
layout.operator("node.preview_toggle")
layout.operator("node.hide_socket_toggle")
- # XXX
- # layout.operator("node.rename")
-
layout.separator()
layout.operator("node.show_cyclic_dependencies")
@@ -195,13 +192,5 @@ class NODE_PT_properties(bpy.types.Panel):
col.prop(snode, "backdrop_y", text="Y")
col.operator("node.backimage_move", text="Move")
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 219dd1de117..1f196cbd191 100644
--- a/release/scripts/ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -72,7 +72,7 @@ class OUTLINER_MT_view(bpy.types.Menu):
space = context.space_data
col = layout.column()
- if space.display_mode not in ('DATABLOCKS', 'USER_PREFERENCES', 'KEYMAPS'):
+ if space.display_mode not in {'DATABLOCKS', 'USER_PREFERENCES', 'KEYMAPS'}:
col.prop(space, "show_restrict_columns")
col.separator()
col.operator("outliner.show_active")
@@ -116,13 +116,5 @@ class OUTLINER_MT_edit_datablocks(bpy.types.Menu):
col.operator("outliner.drivers_add_selected")
col.operator("outliner.drivers_delete_selected")
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 3ae1e35aaf8..2079aef6402 100644
--- a/release/scripts/ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -101,34 +101,6 @@ class SEQUENCER_MT_view(bpy.types.Menu):
layout.separator()
- """
- uiBlock *block= uiBeginBlock(C, ar, "seq_viewmenu", UI_EMBOSSP);
- short yco= 0, menuwidth=120;
-
- if (sseq->mainb == SEQ_DRAW_SEQUENCE) {
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
- "Play Back Animation "
- "in all Sequence Areas|Alt A", 0, yco-=20,
- menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
- }
- else {
- uiDefIconTextBut(block, BUTM, 1, ICON_MENU_PANEL,
- "Grease Pencil...", 0, yco-=20,
- menuwidth, 19, NULL, 0.0, 0.0, 1, 7, "");
- uiDefMenuSep(block);
-
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
- "Play Back Animation "
- "in this window|Alt A", 0, yco-=20,
- menuwidth, 19, NULL, 0.0, 0.0, 1, 1, "");
- }
- uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1,
- "Play Back Animation in all "
- "3D Views and Sequence Areas|Alt Shift A",
- 0, yco-=20,
- menuwidth, 19, NULL, 0.0, 0.0, 1, 2, "");
-
- """
if (st.view_type == 'SEQUENCER') or (st.view_type == 'SEQUENCER_PREVIEW'):
layout.operator("sequencer.view_all", text='View all Sequences')
if (st.view_type == 'PREVIEW') or (st.view_type == 'SEQUENCER_PREVIEW'):
@@ -353,7 +325,6 @@ class SEQUENCER_PT_edit(SequencerButtonsPanel, bpy.types.Panel):
def draw(self, context):
layout = self.layout
scene = context.scene
- render = context.scene.render
frame_current = scene.frame_current
strip = act_strip(context)
@@ -416,11 +387,11 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, bpy.types.Panel):
if not strip:
return False
- return strip.type in ('ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
+ return strip.type in {'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
'PLUGIN',
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'SPEED',
- 'MULTICAM')
+ 'MULTICAM'}
def draw(self, context):
layout = self.layout
@@ -446,7 +417,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, bpy.types.Panel):
col = layout.column()
col.prop(strip, "blur_width", slider=True)
- if strip.transition_type in ('SINGLE', 'DOUBLE'):
+ if strip.transition_type in {'SINGLE', 'DOUBLE'}:
col.prop(strip, "angle")
elif strip.type == 'GLOW':
@@ -492,7 +463,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, bpy.types.Panel):
col = layout.column(align=True)
if strip.type == 'SPEED':
col.prop(strip, "multiply_speed")
- elif strip.type in ('CROSS', 'GAMMA_CROSS', 'PLUGIN', 'WIPE'):
+ elif strip.type in {'CROSS', 'GAMMA_CROSS', 'PLUGIN', 'WIPE'}:
col.prop(strip, "use_default_fade", "Default fade")
if not strip.use_default_fade:
col.prop(strip, "effect_fader", text="Effect fader")
@@ -554,12 +525,12 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, bpy.types.Panel):
if not strip:
return False
- return strip.type in ('MOVIE', 'IMAGE', 'SCENE', 'META',
+ return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'META',
'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
'PLUGIN',
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR',
- 'MULTICAM', 'SPEED')
+ 'MULTICAM', 'SPEED'}
def draw(self, context):
layout = self.layout
@@ -704,12 +675,12 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, bpy.types.Panel):
if not strip:
return False
- return strip.type in ('MOVIE', 'IMAGE', 'SCENE', 'META',
+ return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'META',
'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
'PLUGIN',
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR',
- 'MULTICAM', 'SPEED')
+ 'MULTICAM', 'SPEED'}
def draw(self, context):
layout = self.layout
@@ -766,7 +737,7 @@ class SEQUENCER_PT_proxy(SequencerButtonsPanel, bpy.types.Panel):
if not strip:
return False
- return strip.type in ('MOVIE', 'IMAGE', 'SCENE', 'META', 'MULTICAM')
+ return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'META', 'MULTICAM'}
def draw_header(self, context):
strip = act_strip(context)
@@ -829,13 +800,5 @@ class SEQUENCER_PT_view(SequencerButtonsPanel_Output, bpy.types.Panel):
col.prop(st, "show_separate_color")
col.prop(st, "proxy_render_size")
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py
index df5967c9128..5b07e8dc37f 100644
--- a/release/scripts/ui/space_text.py
+++ b/release/scripts/startup/bl_ui/space_text.py
@@ -95,6 +95,11 @@ class TEXT_PT_properties(bpy.types.Panel):
if text:
flow.prop(text, "use_tabs_as_spaces")
+ flow.prop(st, "show_margin")
+ col = flow.column()
+ col.active = st.show_margin
+ col.prop(st, "margin_column")
+
class TEXT_PT_find(bpy.types.Panel):
bl_space_type = 'TEXT_EDITOR'
@@ -124,6 +129,7 @@ class TEXT_PT_find(bpy.types.Panel):
layout.operator("text.mark_all")
# settings
+ layout.prop(st, "use_match_case")
row = layout.row()
row.prop(st, "use_find_wrap", text="Wrap")
row.prop(st, "use_find_all", text="All")
@@ -293,13 +299,5 @@ class TEXT_MT_toolbox(bpy.types.Menu):
layout.operator("text.run_script")
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py
index 046274abc89..7e62465d1ee 100644
--- a/release/scripts/ui/space_time.py
+++ b/release/scripts/startup/bl_ui/space_time.py
@@ -141,7 +141,6 @@ class TIME_MT_frame(bpy.types.Menu):
def draw(self, context):
layout = self.layout
- # tools = context.tool_settings
layout.operator("marker.add", text="Add Marker")
layout.operator("marker.duplicate", text="Duplicate Marker")
@@ -198,13 +197,5 @@ class TIME_MT_autokey(bpy.types.Menu):
layout.prop_enum(tools, "auto_keying_mode", 'ADD_REPLACE_KEYS')
layout.prop_enum(tools, "auto_keying_mode", 'REPLACE_KEYS')
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 79bdff8ad93..bf396e98c79 100644
--- a/release/scripts/ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -19,7 +19,9 @@
# <pep8 compliant>
import bpy
import os
-import shutil
+import addon_utils
+
+from bpy.props import StringProperty, BoolProperty, EnumProperty
def ui_items_general(col, context):
@@ -118,6 +120,18 @@ class USERPREF_MT_interaction_presets(bpy.types.Menu):
draw = bpy.types.Menu.draw_preset
+class USERPREF_MT_appconfigs(bpy.types.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)")
+
+ # now draw the presets
+ bpy.types.Menu.draw_preset(self, context)
+
+
class USERPREF_MT_splash(bpy.types.Menu):
bl_label = "Splash"
@@ -132,7 +146,7 @@ class USERPREF_MT_splash(bpy.types.Menu):
# text = bpy.path.display_name(context.window_manager.keyconfigs.active.name)
# if not text:
# text = "Blender (default)"
- row.menu("USERPREF_MT_keyconfigs", text="Preset")
+ row.menu("USERPREF_MT_appconfigs", text="Preset")
class USERPREF_PT_interface(bpy.types.Panel):
@@ -635,7 +649,29 @@ class USERPREF_PT_theme(bpy.types.Panel):
layout.separator()
layout.separator()
+ elif theme.theme_area == 'BONE_COLOR_SETS':
+ col = split.column()
+
+ for i, ui in enumerate(theme.bone_color_sets):
+ col.label(text="Color Set %d:" % (i + 1)) # i starts from 0
+
+ row = col.row()
+
+ subsplit = row.split(percentage=0.95)
+
+ padding = subsplit.split(percentage=0.15)
+ colsub = padding.column()
+ colsub = padding.column()
+ colsub.row().prop(ui, "normal")
+ colsub.row().prop(ui, "select")
+ colsub.row().prop(ui, "active")
+
+ subsplit = row.split(percentage=0.85)
+ padding = subsplit.split(percentage=0.15)
+ colsub = padding.column()
+ colsub = padding.column()
+ colsub.row().prop(ui, "show_colored_constraints")
else:
self._theme_generic(split, getattr(theme, theme.theme_area.lower()))
@@ -713,7 +749,7 @@ class USERPREF_PT_file(bpy.types.Panel):
sub.active = paths.use_auto_save_temporary_files
sub.prop(paths, "auto_save_time", text="Timer (mins)")
-from space_userpref_keymap import InputKeyMapPanel
+from bl_ui.space_userpref_keymap import InputKeyMapPanel
class USERPREF_PT_input(InputKeyMapPanel):
@@ -764,9 +800,9 @@ class USERPREF_PT_input(InputKeyMapPanel):
sub.label(text="Zoom Style:")
sub.row().prop(inputs, "view_zoom_method", text="")
- if inputs.view_zoom_method == 'DOLLY':
+ if inputs.view_zoom_method in {'DOLLY', 'CONTINUE'}:
sub.row().prop(inputs, "view_zoom_axis", expand=True)
- sub.prop(inputs, "invert_mouse_wheel_zoom")
+ sub.prop(inputs, "invert_mouse_zoom")
#sub.prop(inputs, "use_mouse_mmb_paste")
@@ -795,7 +831,6 @@ class USERPREF_PT_input(InputKeyMapPanel):
#start = time.time()
userpref = context.user_preferences
- wm = context.window_manager
inputs = userpref.inputs
@@ -830,8 +865,6 @@ class USERPREF_PT_addons(bpy.types.Panel):
bl_region_type = 'WINDOW'
bl_options = {'HIDE_HEADER'}
- _addons_cats = None
- _addons_sups = None
_addons_fake_modules = {}
@classmethod
@@ -843,107 +876,6 @@ class USERPREF_PT_addons(bpy.types.Panel):
def module_get(mod_name):
return USERPREF_PT_addons._addons_fake_modules[mod_name]
- @staticmethod
- def _addon_list():
- import os
- import sys
- import time
-
- modules = []
- loaded_modules = set()
-
- # RELEASE SCRIPTS: official scripts distributed in Blender releases
- paths = bpy.utils.script_paths("addons")
-
- # CONTRIB SCRIPTS: good for testing but not official scripts yet
- # if folder addons_contrib/ exists, scripts in there will be loaded too
- paths += bpy.utils.script_paths("addons_contrib")
-
- # EXTERN SCRIPTS: external projects scripts
- # if folder addons_extern/ exists, scripts in there will be loaded too
- paths += bpy.utils.script_paths("addons_extern")
-
- if bpy.app.debug:
- t_main = time.time()
-
- # fake module importing
- def fake_module(mod_name, mod_path, speedy=True):
- if bpy.app.debug:
- print("fake_module", mod_name, mod_path)
- import ast
- ModuleType = type(ast)
- file_mod = open(mod_path, "r", encoding='UTF-8')
- if speedy:
- lines = []
- line_iter = iter(file_mod)
- l = ""
- while not l.startswith("bl_info"):
- l = line_iter.readline()
- if len(l) == 0:
- break
- while l.rstrip():
- lines.append(l)
- l = line_iter.readline()
- data = "".join(lines)
-
- else:
- data = file_mod.read()
-
- file_mod.close()
-
- try:
- ast_data = ast.parse(data, filename=mod_path)
- except:
- print("Syntax error 'ast.parse' can't read %r" % mod_path)
- import traceback
- traceback.print_exc()
- ast_data = None
-
- body_info = None
-
- if ast_data:
- for body in ast_data.body:
- if body.__class__ == ast.Assign:
- if len(body.targets) == 1:
- if getattr(body.targets[0], "id", "") == "bl_info":
- body_info = body
- break
-
- if body_info:
- mod = ModuleType(mod_name)
- mod.bl_info = ast.literal_eval(body.value)
- mod.__file__ = mod_path
- mod.__time__ = os.path.getmtime(mod_path)
- return mod
- else:
- return None
-
- modules_stale = set(USERPREF_PT_addons._addons_fake_modules.keys())
-
- for path in paths:
- for mod_name, mod_path in bpy.path.module_names(path):
- modules_stale -= {mod_name}
- mod = USERPREF_PT_addons._addons_fake_modules.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)
- del USERPREF_PT_addons._addons_fake_modules[mod_name]
- mod = None
-
- if mod is None:
- mod = fake_module(mod_name, mod_path)
- if mod:
- USERPREF_PT_addons._addons_fake_modules[mod_name] = mod
-
- # just incase we get stale modules, not likely
- for mod_stale in modules_stale:
- del USERPREF_PT_addons._addons_fake_modules[mod_stale]
- del modules_stale
-
- mod_list = list(USERPREF_PT_addons._addons_fake_modules.values())
- mod_list.sort(key=lambda mod: (mod.bl_info['category'], mod.bl_info['name']))
- return mod_list
-
def draw(self, context):
layout = self.layout
@@ -951,22 +883,7 @@ class USERPREF_PT_addons(bpy.types.Panel):
used_ext = {ext.module for ext in userpref.addons}
# collect the categories that can be filtered on
- addons = [(mod, addon_info_get(mod)) for mod in self._addon_list()]
-
- cats = {info["category"] for mod, info in addons}
- cats.discard("")
-
- if USERPREF_PT_addons._addons_cats != cats:
- bpy.types.WindowManager.addon_filter = bpy.props.EnumProperty(items=[(cat, cat, "") for cat in ["All", "Enabled", "Disabled"] + sorted(cats)], name="Category", description="Filter add-ons by category")
- bpy.types.WindowManager.addon_search = bpy.props.StringProperty(name="Search", description="Search within the selected filter")
- USERPREF_PT_addons._addons_cats = cats
-
- sups = {info["support"] for mod, info in addons}
- sups.discard("")
-
- if USERPREF_PT_addons._addons_sups != sups:
- bpy.types.WindowManager.addon_support = bpy.props.EnumProperty(items=[(sup, sup.title(), "") for sup in reversed(sorted(sups))], name="Support", description="Display support level", default={'OFFICIAL', 'COMMUNITY'}, options={'ENUM_FLAG'})
- USERPREF_PT_addons._addons_sups = sups
+ addons = [(mod, addon_utils.module_bl_info(mod)) for mod in addon_utils.modules(USERPREF_PT_addons._addons_fake_modules)]
split = layout.split(percentage=0.2)
col = split.column()
@@ -1070,7 +987,7 @@ class USERPREF_PT_addons(bpy.types.Panel):
module_names = {mod.__name__ for mod, info in addons}
missing_modules = {ext for ext in used_ext if ext not in module_names}
- if missing_modules and filter in ("All", "Enabled"):
+ if missing_modules and filter in {"All", "Enabled"}:
col.column().separator()
col.column().label(text="Missing script files")
@@ -1088,29 +1005,6 @@ class USERPREF_PT_addons(bpy.types.Panel):
row.operator("wm.addon_disable", icon='CHECKBOX_HLT', text="", emboss=False).module = module_name
-from bpy.props import *
-
-
-def addon_info_get(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
- if "_init" in addon_info:
- return addon_info
-
- if not addon_info:
- mod.bl_info = addon_info
-
- for key, value in info_basis.items():
- addon_info.setdefault(key, value)
-
- if not addon_info["name"]:
- addon_info["name"] = mod.__name__
-
- addon_info["_init"] = None
- return addon_info
-
-
class WM_OT_addon_enable(bpy.types.Operator):
"Enable an addon"
bl_idname = "wm.addon_enable"
@@ -1119,11 +1013,11 @@ class WM_OT_addon_enable(bpy.types.Operator):
module = StringProperty(name="Module", description="Module name of the addon to enable")
def execute(self, context):
- mod = bpy.utils.addon_enable(self.module)
+ mod = addon_utils.enable(self.module)
if mod:
# check if add-on is written for current blender version, or raise a warning
- info = addon_info_get(mod)
+ 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.")
@@ -1140,7 +1034,7 @@ class WM_OT_addon_disable(bpy.types.Operator):
module = StringProperty(name="Module", description="Module name of the addon to disable")
def execute(self, context):
- bpy.utils.addon_disable(self.module)
+ addon_utils.disable(self.module)
return {'FINISHED'}
@@ -1150,6 +1044,10 @@ class WM_OT_addon_install(bpy.types.Operator):
bl_label = "Install Add-On..."
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'})
@@ -1172,16 +1070,41 @@ class WM_OT_addon_install(bpy.types.Operator):
def execute(self, context):
import traceback
import zipfile
+ import shutil
+
pyfile = self.filepath
- # dont use bpy.utils.script_paths("addons") because we may not be able to write to it.
- path_addons = bpy.utils.user_resource('SCRIPTS', "addons", create=True)
+ if self.target == 'DEFAULT':
+ # dont use bpy.utils.script_paths("addons") because we may not be able to write to it.
+ path_addons = bpy.utils.user_resource('SCRIPTS', "addons", create=True)
+ else:
+ path_addons = bpy.context.user_preferences.filepaths.script_directory
+ if path_addons:
+ path_addons = os.path.join(path_addons, "addons")
if not path_addons:
- self.report({'WARNING'}, "Failed to get addons path\n")
+ self.report({'ERROR'}, "Failed to get addons path")
return {'CANCELLED'}
- contents = set(os.listdir(path_addons))
+ # create dir is if missing.
+ if not os.path.exists(path_addons):
+ os.makedirs(path_addons)
+
+ # Check if we are installing from a target path,
+ # doing so causes 2+ addons of same name or when the same from/to
+ # location is used, removal of the file!
+ addon_path = ""
+ pyfile_dir = os.path.dirname(pyfile)
+ for addon_path in addon_utils.paths():
+ if os.path.samefile(pyfile_dir, addon_path):
+ self.report({'ERROR'}, "Source file is in the addon search path: %r" % addon_path)
+ return {'CANCELLED'}
+ del addon_path
+ 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)
if zipfile.is_zipfile(pyfile):
@@ -1203,6 +1126,12 @@ class WM_OT_addon_install(bpy.types.Operator):
try: # extract the file to "addons"
file_to_extract.extractall(path_addons)
+
+ # zip files can create this dir with metadata, don't need it
+ macosx_dir = os.path.join(path_addons, '__MACOSX')
+ if os.path.isdir(macosx_dir):
+ shutil.rmtree(macosx_dir)
+
except:
traceback.print_exc()
return {'CANCELLED'}
@@ -1224,23 +1153,28 @@ class WM_OT_addon_install(bpy.types.Operator):
traceback.print_exc()
return {'CANCELLED'}
+ addons_new = {mod.__name__ for mod in addon_utils.modules(USERPREF_PT_addons._addons_fake_modules)} - addons_old
+ addons_new.discard("modules")
+
# disable any addons we may have enabled previously and removed.
# this is unlikely but do just incase. bug [#23978]
- addons_new = set(os.listdir(path_addons)) - contents
for new_addon in addons_new:
- bpy.utils.addon_disable(os.path.splitext(new_addon)[0])
+ addon_utils.disable(new_addon)
# possible the zip contains multiple addons, we could disallow this
# but for now just use the first
- for mod in USERPREF_PT_addons._addon_list():
+ for mod in addon_utils.modules(USERPREF_PT_addons._addons_fake_modules):
if mod.__name__ in addons_new:
- info = addon_info_get(mod)
+ info = addon_utils.module_bl_info(mod)
# show the newly installed addon.
context.window_manager.addon_filter = 'All'
context.window_manager.addon_search = info["name"]
break
+ # incase a new module path was created to install this addon.
+ bpy.utils.refresh_script_paths()
+
# TODO, should not be a warning.
# self.report({'WARNING'}, "File installed to '%s'\n" % path_dest)
return {'FINISHED'}
@@ -1270,17 +1204,9 @@ class WM_OT_addon_expand(bpy.types.Operator):
traceback.print_exc()
return {'CANCELLED'}
- info = addon_info_get(mod)
+ info = addon_utils.module_bl_info(mod)
info["show_expanded"] = not info["show_expanded"]
return {'FINISHED'}
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_userpref_keymap.py b/release/scripts/startup/bl_ui/space_userpref_keymap.py
index a78ef1be36f..378fe231091 100644
--- a/release/scripts/ui/space_userpref_keymap.py
+++ b/release/scripts/startup/bl_ui/space_userpref_keymap.py
@@ -206,7 +206,7 @@ class InputKeyMapPanel(bpy.types.Panel):
# Key Map items
if km.show_expanded_items:
- for kmi in km.items:
+ for kmi in km.keymap_items:
self.draw_kmi(display_keymaps, kc, km, kmi, col, level + 1)
# "Add New" at end of keymap item list
@@ -292,7 +292,7 @@ class InputKeyMapPanel(bpy.types.Panel):
box.enabled = km.is_user_defined
- if map_type not in ('TEXTINPUT', 'TIMER'):
+ if map_type not in {'TEXTINPUT', 'TIMER'}:
split = box.split(percentage=0.4)
sub = split.row()
@@ -339,7 +339,7 @@ class InputKeyMapPanel(bpy.types.Panel):
km = km.active()
layout.context_pointer_set("keymap", km)
- filtered_items = [kmi for kmi in km.items if filter_text in kmi.name.lower()]
+ filtered_items = [kmi for kmi in km.keymap_items if filter_text in kmi.name.lower()]
if len(filtered_items) != 0:
col = layout.column()
@@ -404,7 +404,7 @@ class InputKeyMapPanel(bpy.types.Panel):
self.draw_hierarchy(display_keymaps, col)
-from bpy.props import *
+from bpy.props import StringProperty, BoolProperty, IntProperty
def export_properties(prefix, properties, lines=None):
@@ -433,9 +433,9 @@ class WM_OT_keyconfig_test(bpy.types.Operator):
def kmistr(kmi):
if km.is_modal:
- s = ["kmi = km.items.new_modal(\'%s\', \'%s\', \'%s\'" % (kmi.propvalue, kmi.type, kmi.value)]
+ s = ["kmi = km.keymap_items.new_modal(\'%s\', \'%s\', \'%s\'" % (kmi.propvalue, kmi.type, kmi.value)]
else:
- s = ["kmi = km.items.new(\'%s\', \'%s\', \'%s\'" % (kmi.idname, kmi.type, kmi.value)]
+ s = ["kmi = km.keymap_items.new(\'%s\', \'%s\', \'%s\'" % (kmi.idname, kmi.type, kmi.value)]
if kmi.any:
s.append(", any=True")
@@ -468,7 +468,7 @@ class WM_OT_keyconfig_test(bpy.types.Operator):
km = km.active()
if src:
- for item in km.items:
+ for item in km.keymap_items:
if src.compare(item):
print("===========")
print(parent.name)
@@ -481,15 +481,15 @@ class WM_OT_keyconfig_test(bpy.types.Operator):
if self.testEntry(kc, child, src, parent):
result = True
else:
- for i in range(len(km.items)):
- src = km.items[i]
+ for i in range(len(km.keymap_items)):
+ src = km.keymap_items[i]
for child in children:
if self.testEntry(kc, child, src, km):
result = True
- for j in range(len(km.items) - i - 1):
- item = km.items[j + i + 1]
+ for j in range(len(km.keymap_items) - i - 1):
+ item = km.keymap_items[j + i + 1]
if src.compare(item):
print("===========")
print(km.name)
@@ -555,13 +555,7 @@ class WM_OT_keyconfig_import(bpy.types.Operator):
config_name = basename(self.filepath)
- path = bpy.utils.preset_paths("keyconfig")[0] # we need some way to tell the user and system preset path
- print(path)
-
- # create config folder if needed
- if not os.path.exists(path):
- os.mkdir(path)
-
+ path = bpy.utils.user_resource('SCRIPTS', os.path.join("presets", "keyconfig"), create=True)
path = os.path.join(path, config_name)
if self.keep_original:
@@ -633,11 +627,11 @@ class WM_OT_keyconfig_export(bpy.types.Operator):
f.write("# Map %s\n" % km.name)
f.write("km = kc.keymaps.new('%s', space_type='%s', region_type='%s', modal=%s)\n\n" % (km.name, km.space_type, km.region_type, km.is_modal))
- for kmi in km.items:
+ for kmi in km.keymap_items:
if km.is_modal:
- f.write("kmi = km.items.new_modal('%s', '%s', '%s'" % (kmi.propvalue, kmi.type, kmi.value))
+ f.write("kmi = km.keymap_items.new_modal('%s', '%s', '%s'" % (kmi.propvalue, kmi.type, kmi.value))
else:
- f.write("kmi = km.items.new('%s', '%s', '%s'" % (kmi.idname, kmi.type, kmi.value))
+ f.write("kmi = km.keymap_items.new('%s', '%s', '%s'" % (kmi.idname, kmi.type, kmi.value))
if kmi.any:
f.write(", any=True")
else:
@@ -676,7 +670,6 @@ class WM_OT_keymap_edit(bpy.types.Operator):
bl_label = "Edit Key Map"
def execute(self, context):
- wm = context.window_manager
km = context.keymap
km.copy_to_user()
return {'FINISHED'}
@@ -711,13 +704,12 @@ class WM_OT_keyitem_restore(bpy.types.Operator):
@classmethod
def poll(cls, context):
- km = context.keymap
- return km.is_user_defined
+ keymap = getattr(context, "keymap", None)
+ return keymap and keymap.is_user_defined
def execute(self, context):
- wm = context.window_manager
km = context.keymap
- kmi = km.items.from_id(self.item_id)
+ kmi = km.keymap_items.from_id(self.item_id)
if not kmi.is_user_defined:
km.restore_item_to_default(kmi)
@@ -736,9 +728,9 @@ class WM_OT_keyitem_add(bpy.types.Operator):
kc = wm.keyconfigs.default
if km.is_modal:
- km.items.new_modal("", 'A', 'PRESS') # kmi
+ km.keymap_items.new_modal("", 'A', 'PRESS') # kmi
else:
- km.items.new("none", 'A', 'PRESS') # kmi
+ km.keymap_items.new("none", 'A', 'PRESS') # kmi
# clear filter and expand keymap so we can see the newly added item
if context.space_data.filter_text != "":
@@ -758,13 +750,12 @@ class WM_OT_keyitem_remove(bpy.types.Operator):
@classmethod
def poll(cls, context):
- km = context.keymap
- return km.is_user_defined
+ return hasattr(context, "keymap") and context.keymap.is_user_defined
def execute(self, context):
km = context.keymap
- kmi = km.items.from_id(self.item_id)
- km.items.remove(kmi)
+ kmi = km.keymap_items.from_id(self.item_id)
+ km.keymap_items.remove(kmi)
return {'FINISHED'}
@@ -776,22 +767,14 @@ class WM_OT_keyconfig_remove(bpy.types.Operator):
@classmethod
def poll(cls, context):
wm = context.window_manager
- return wm.keyconfigs.active.is_user_defined
+ keyconf = wm.keyconfigs.active
+ return keyconf and keyconf.is_user_defined
def execute(self, context):
- import sys
wm = context.window_manager
keyconfig = wm.keyconfigs.active
wm.keyconfigs.remove(keyconfig)
return {'FINISHED'}
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 162322a8720..7d31bc39b0a 100644
--- a/release/scripts/ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -42,13 +42,13 @@ class VIEW3D_HT_header(bpy.types.Header):
sub.menu("VIEW3D_MT_view")
# Select Menu
- if mode_string not in ('EDIT_TEXT', 'SCULPT', 'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'):
+ if mode_string not in {'EDIT_TEXT', 'SCULPT', 'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
sub.menu("VIEW3D_MT_select_%s" % mode_string.lower())
if edit_object:
sub.menu("VIEW3D_MT_edit_%s" % edit_object.type.lower())
elif obj:
- if mode_string not in ('PAINT_TEXTURE'):
+ if mode_string not in {'PAINT_TEXTURE'}:
sub.menu("VIEW3D_MT_%s" % mode_string.lower())
else:
sub.menu("VIEW3D_MT_object")
@@ -71,11 +71,11 @@ class VIEW3D_HT_header(bpy.types.Header):
row.prop(toolsettings.particle_edit, "select_mode", text="", expand=True, toggle=True)
# Occlude geometry
- if view.viewport_shade in ('SOLID', 'SHADED', 'TEXTURED') and (obj.mode == 'PARTICLE_EDIT' or (obj.mode == 'EDIT' and obj.type == 'MESH')):
+ if view.viewport_shade in {'SOLID', 'SHADED', 'TEXTURED'} and (obj.mode == 'PARTICLE_EDIT' or (obj.mode == 'EDIT' and obj.type == 'MESH')):
row.prop(view, "use_occlude_geometry", text="")
# Proportional editing
- if obj.mode in ('EDIT', 'PARTICLE_EDIT'):
+ if obj.mode in {'EDIT', 'PARTICLE_EDIT'}:
row = layout.row(align=True)
row.prop(toolsettings, "proportional_edit", text="", icon_only=True)
if toolsettings.proportional_edit != 'DISABLED':
@@ -160,7 +160,7 @@ class VIEW3D_MT_transform(bpy.types.Menu):
layout.separator()
obj = context.object
- if obj.type == 'ARMATURE' and obj.mode in ('EDIT', 'POSE') and obj.data.draw_type in ('BBONE', 'ENVELOPE'):
+ if obj.type == 'ARMATURE' and obj.mode in {'EDIT', 'POSE'} and obj.data.draw_type in {'BBONE', 'ENVELOPE'}:
layout.operator("transform.transform", text="Scale Envelope/BBone").mode = 'BONE_SIZE'
if context.edit_object and context.edit_object.type == 'ARMATURE':
@@ -177,6 +177,11 @@ class VIEW3D_MT_transform(bpy.types.Menu):
layout.operator("object.origin_set", text="Origin to Geometry").type = 'ORIGIN_GEOMETRY'
layout.operator("object.origin_set", text="Origin to 3D Cursor").type = 'ORIGIN_CURSOR'
+ layout.separator()
+
+ layout.operator("object.randomize_transform")
+ layout.operator("object.align")
+
class VIEW3D_MT_mirror(bpy.types.Menu):
bl_label = "Mirror"
@@ -240,9 +245,21 @@ class VIEW3D_MT_uv_map(bpy.types.Menu):
layout = self.layout
layout.operator("uv.unwrap")
+
+ layout.operator_context = 'INVOKE_DEFAULT'
+ layout.operator("uv.smart_project")
+ layout.operator("uv.lightmap_pack")
+ layout.operator("uv.follow_active_quads")
+
+ layout.separator()
+
+ layout.operator_context = 'EXEC_DEFAULT'
layout.operator("uv.cube_project")
layout.operator("uv.cylinder_project")
layout.operator("uv.sphere_project")
+
+ layout.separator()
+
layout.operator("uv.project_from_view")
layout.operator("uv.project_from_view", text="Project from View (Bounds)").scale_to_bounds = True
@@ -250,6 +267,7 @@ class VIEW3D_MT_uv_map(bpy.types.Menu):
layout.operator("uv.reset")
+
# ********** View menus **********
@@ -317,16 +335,17 @@ class VIEW3D_MT_view_navigation(bpy.types.Menu):
def draw(self, context):
layout = self.layout
- layout.operator_enums("view3d.view_orbit", "type")
+ layout.operator_enum("view3d.view_orbit", "type")
layout.separator()
- layout.operator_enums("view3d.view_pan", "type")
+ layout.operator_enum("view3d.view_pan", "type")
layout.separator()
layout.operator("view3d.zoom", text="Zoom In").delta = 1
layout.operator("view3d.zoom", text="Zoom Out").delta = -1
+ layout.operator("view3d.zoom_camera_1_to_1", text="Zoom Camera 1:1")
layout.separator()
@@ -425,6 +444,7 @@ class VIEW3D_MT_select_pose(bpy.types.Menu):
layout.operator("pose.select_all", text="Select/Deselect All")
layout.operator("pose.select_inverse", text="Inverse")
+ layout.operator("pose.select_flip_active", text="Flip Active")
layout.operator("pose.select_constraint_target", text="Constraint Target")
layout.operator("pose.select_linked", text="Linked")
@@ -647,10 +667,11 @@ class VIEW3D_MT_select_face(bpy.types.Menu): # XXX no matching enum
bl_label = "Select"
def draw(self, context):
- layout = self.layout
+ # layout = self.layout
# TODO
# see view3d_select_faceselmenu
+ pass
# ********** Object menu **********
@@ -713,7 +734,6 @@ class VIEW3D_MT_object(bpy.types.Menu):
class VIEW3D_MT_object_animation(bpy.types.Menu):
- bl_context = "objectmode"
bl_label = "Animation"
def draw(self, context):
@@ -763,7 +783,7 @@ class VIEW3D_MT_object_specials(bpy.types.Menu):
props.data_path_item = "data.dof_distance"
props.input_scale = 0.02
- if obj.type in ('CURVE', 'FONT'):
+ if obj.type in {'CURVE', 'FONT'}:
layout.operator_context = 'INVOKE_REGION_WIN'
props = layout.operator("wm.context_modal_mouse", text="Extrude Size")
@@ -791,7 +811,7 @@ class VIEW3D_MT_object_specials(bpy.types.Menu):
props.data_path_iter = "selected_editable_objects"
props.data_path_item = "data.energy"
- if obj.data.type in ('SPOT', 'AREA', 'POINT'):
+ if obj.data.type in {'SPOT', 'AREA', 'POINT'}:
props = layout.operator("wm.context_modal_mouse", text="Falloff Distance")
props.data_path_iter = "selected_editable_objects"
props.data_path_item = "data.distance"
@@ -831,10 +851,15 @@ class VIEW3D_MT_object_apply(bpy.types.Menu):
def draw(self, context):
layout = self.layout
- layout.operator("object.location_apply", text="Location")
- layout.operator("object.rotation_apply", text="Rotation")
- layout.operator("object.scale_apply", text="Scale")
+ layout.operator("object.transform_apply", text="Location").location = True
+ layout.operator("object.transform_apply", text="Rotation").rotation = True
+ layout.operator("object.transform_apply", text="Scale").scale = True
+ props = layout.operator("object.transform_apply", text="Rotation & Scale")
+ props.scale = True
+ props.rotation = True
+
layout.separator()
+
layout.operator("object.visual_transform_apply", text="Visual Transform")
layout.operator("object.duplicates_make_real")
@@ -932,7 +957,7 @@ class VIEW3D_MT_make_links(bpy.types.Menu):
layout.operator_menu_enum("object.make_links_scene", "scene", text="Objects to Scene...")
layout.operator_menu_enum("marker.make_links_scene", "scene", text="Markers to Scene...")
- layout.operator_enums("object.make_links_data", "type") # inline
+ layout.operator_enum("object.make_links_data", "type") # inline
class VIEW3D_MT_object_game(bpy.types.Menu):
@@ -1038,6 +1063,10 @@ class VIEW3D_MT_paint_weight(bpy.types.Menu):
layout.operator("object.vertex_group_clean", text="Clean")
layout.operator("object.vertex_group_levels", text="Levels")
+ layout.separator()
+
+ layout.operator("paint.weight_set")
+
# ********** Sculpt menu **********
@@ -1070,12 +1099,9 @@ class VIEW3D_MT_sculpt(bpy.types.Menu):
sculpt_tool = brush.sculpt_tool
if sculpt_tool != 'GRAB':
- layout.prop(brush, "use_airbrush")
-
- if sculpt_tool != 'LAYER':
- layout.prop(brush, "use_anchor")
+ layout.prop_menu_enum(brush, "stroke_method")
- if sculpt_tool in ('DRAW', 'PINCH', 'INFLATE', 'LAYER', 'CLAY'):
+ if sculpt_tool in {'DRAW', 'PINCH', 'INFLATE', 'LAYER', 'CLAY'}:
layout.prop_menu_enum(brush, "direction")
if sculpt_tool == 'LAYER':
@@ -1154,31 +1180,26 @@ class VIEW3D_MT_pose(bpy.types.Menu):
def draw(self, context):
layout = self.layout
- arm = context.active_object.data
-
layout.operator("ed.undo")
layout.operator("ed.redo")
layout.separator()
layout.menu("VIEW3D_MT_transform")
- layout.menu("VIEW3D_MT_snap")
layout.menu("VIEW3D_MT_pose_transform")
+ layout.menu("VIEW3D_MT_pose_apply")
- layout.separator()
-
- layout.operator("anim.keyframe_insert_menu", text="Insert Keyframe...")
- layout.operator("anim.keyframe_delete_v3d", text="Delete Keyframe...")
- layout.operator("anim.keying_set_active_set", text="Change Keying Set...")
+ layout.menu("VIEW3D_MT_snap")
layout.separator()
- layout.operator("pose.relax")
+ layout.menu("VIEW3D_MT_object_animation")
layout.separator()
- layout.menu("VIEW3D_MT_pose_apply")
+ layout.menu("VIEW3D_MT_pose_slide")
+ layout.menu("VIEW3D_MT_pose_propagate")
layout.separator()
@@ -1188,7 +1209,7 @@ class VIEW3D_MT_pose(bpy.types.Menu):
layout.separator()
- layout.menu("VIEW3D_MT_pose_pose")
+ layout.menu("VIEW3D_MT_pose_library")
layout.menu("VIEW3D_MT_pose_motion")
layout.menu("VIEW3D_MT_pose_group")
@@ -1236,7 +1257,36 @@ class VIEW3D_MT_pose_transform(bpy.types.Menu):
layout.label(text="Origin")
-class VIEW3D_MT_pose_pose(bpy.types.Menu):
+class VIEW3D_MT_pose_slide(bpy.types.Menu):
+ bl_label = "In-Betweens"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("pose.push")
+ layout.operator("pose.relax")
+ layout.operator("pose.breakdown")
+
+
+class VIEW3D_MT_pose_propagate(bpy.types.Menu):
+ bl_label = "Propagate"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("pose.propagate")
+
+ layout.separator()
+
+ layout.operator("pose.propagate", text="To Next Keyframe").mode = 'NEXT_KEY'
+ layout.operator("pose.propagate", text="To Last Keyframe (Make Cyclic)").mode = 'LAST_KEY'
+
+ layout.separator()
+
+ layout.operator("pose.propagate", text="On Selected Markers").mode = 'SELECTED_MARKERS'
+
+
+class VIEW3D_MT_pose_library(bpy.types.Menu):
bl_label = "Pose Library"
def draw(self, context):
@@ -1450,7 +1500,7 @@ class VIEW3D_OT_edit_mesh_extrude_individual_move(bpy.types.Operator):
totface = mesh.total_face_sel
totedge = mesh.total_edge_sel
- totvert = mesh.total_vert_sel
+ # totvert = mesh.total_vert_sel
if select_mode[2] and totface == 1:
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN', TRANSFORM_OT_translate={"constraint_orientation": 'NORMAL', "constraint_axis": (False, False, True)})
@@ -1478,7 +1528,7 @@ class VIEW3D_OT_edit_mesh_extrude_move(bpy.types.Operator):
totface = mesh.total_face_sel
totedge = mesh.total_edge_sel
- totvert = mesh.total_vert_sel
+ # totvert = mesh.total_vert_sel
if totface >= 1:
bpy.ops.mesh.extrude_region_move('INVOKE_REGION_WIN', TRANSFORM_OT_translate={"constraint_orientation": 'NORMAL', "constraint_axis": (False, False, True)})
@@ -1510,6 +1560,8 @@ class VIEW3D_MT_edit_mesh_vertices(bpy.types.Menu):
layout.operator("mesh.vertices_smooth")
layout.operator("mesh.remove_doubles")
+ layout.operator("mesh.vertices_sort")
+ layout.operator("mesh.vertices_randomize")
layout.operator("mesh.select_vertex_path")
@@ -1938,8 +1990,7 @@ class VIEW3D_MT_edit_armature_roll(bpy.types.Menu):
def draw(self, context):
layout = self.layout
- layout.operator("armature.calculate_roll", text="Recalculate with Z-Axis Up").type = 'GLOBALUP'
- layout.operator("armature.calculate_roll", text="Recalculate with Z-Axis to Cursor").type = 'CURSOR'
+ layout.operator_menu_enum("armature.calculate_roll", "type")
layout.separator()
@@ -1962,7 +2013,6 @@ class VIEW3D_PT_view3d_properties(bpy.types.Panel):
layout = self.layout
view = context.space_data
- scene = context.scene
col = layout.column()
col.active = view.region_3d.view_perspective != 'CAMERA'
@@ -2004,7 +2054,7 @@ class VIEW3D_PT_view3d_name(bpy.types.Panel):
row.label(text="", icon='OBJECT_DATA')
row.prop(ob, "name", text="")
- if ob.type == 'ARMATURE' and ob.mode in ('EDIT', 'POSE'):
+ if ob.type == 'ARMATURE' and ob.mode in {'EDIT', 'POSE'}:
bone = context.active_bone
if bone:
row = layout.row()
@@ -2314,3 +2364,6 @@ def unregister():
if __name__ == "__main__":
register()
+
+if __name__ == "__main__": # only for live edit.
+ bpy.utils.register_module(__name__)
diff --git a/release/scripts/ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 163e02817a4..a6db6fbdde8 100644
--- a/release/scripts/ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -122,7 +122,6 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, bpy.types.Panel):
col = layout.column(align=True)
col.label(text="Deform:")
col.operator("transform.edge_slide")
- col.operator("mesh.rip_move")
col.operator("mesh.noise")
col.operator("mesh.vertices_smooth")
@@ -173,11 +172,18 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, bpy.types.Panel):
ob = context.active_object
if ob:
- mesh = context.active_object.data
+ mesh = ob.data
col = layout.column(align=True)
col.prop(mesh, "use_mirror_x")
- col.prop(mesh, "use_mirror_topology")
- col.prop(context.tool_settings, "edge_path_mode")
+ sub = col.column()
+ sub.active = ob.data.use_mirror_x
+ sub.prop(mesh, "use_mirror_topology")
+
+ ts = context.tool_settings
+
+ col.label("Edge Select Mode")
+ col.prop(ts, "edge_path_mode", text="")
+ col.prop(context.tool_settings, "edge_path_live_unwrap")
# ********** default tools for editmode_curve ****************
@@ -324,12 +330,9 @@ class VIEW3D_PT_tools_armatureedit_options(View3DPanel, bpy.types.Panel):
bl_label = "Armature Options"
def draw(self, context):
- layout = self.layout
-
arm = context.active_object.data
- col = layout.column(align=True)
- col.prop(arm, "use_mirror_x")
+ self.layout.prop(arm, "use_mirror_x")
# ********** default tools for editmode_mball ****************
@@ -424,12 +427,9 @@ class VIEW3D_PT_tools_posemode_options(View3DPanel, bpy.types.Panel):
bl_label = "Pose Options"
def draw(self, context):
- layout = self.layout
-
arm = context.active_object.data
- col = layout.column(align=True)
- col.prop(arm, "use_auto_ik")
+ self.layout.prop(arm, "use_auto_ik")
# ********** default tools for paint modes ****************
@@ -448,7 +448,7 @@ class PaintPanel():
return ts.vertex_paint
elif context.weight_paint_object:
return ts.weight_paint
- elif context.texture_paint_object:
+ elif context.image_paint_object:
return ts.image_paint
elif context.particle_edit_object:
return ts.particle_edit
@@ -515,16 +515,16 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
row.prop(brush, "unprojected_radius", text="Radius", slider=True)
else:
row.prop(brush, "use_locked_size", toggle=True, text="", icon='UNLOCKED')
- row.prop(brush, "size", text="Radius", slider=True)
+ row.prop(brush, "size", slider=True)
row.prop(brush, "use_pressure_size", toggle=True, text="")
- if brush.sculpt_tool not in ('SNAKE_HOOK', 'GRAB', 'ROTATE'):
+ if brush.sculpt_tool not in {'SNAKE_HOOK', 'GRAB', 'ROTATE'}:
col.separator()
row = col.row(align=True)
- if brush.use_space and brush.sculpt_tool not in ('SMOOTH'):
+ if brush.use_space and brush.sculpt_tool not in {'SMOOTH'}:
if brush.use_space_atten:
row.prop(brush, "use_space_atten", toggle=True, text="", icon='LOCKED')
else:
@@ -533,26 +533,26 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
row.prop(brush, "strength", text="Strength", slider=True)
row.prop(brush, "use_pressure_strength", text="")
- if brush.sculpt_tool not in ('SMOOTH'):
+ if brush.sculpt_tool not in {'SMOOTH'}:
col.separator()
row = col.row(align=True)
row.prop(brush, "auto_smooth_factor", slider=True)
row.prop(brush, "use_inverse_smooth_pressure", toggle=True, text="")
- if brush.sculpt_tool in ('GRAB', 'SNAKE_HOOK'):
+ if brush.sculpt_tool in {'GRAB', 'SNAKE_HOOK'}:
col.separator()
row = col.row(align=True)
row.prop(brush, "normal_weight", slider=True)
- if brush.sculpt_tool in ('CREASE', 'BLOB'):
+ if brush.sculpt_tool in {'CREASE', 'BLOB'}:
col.separator()
row = col.row(align=True)
row.prop(brush, "crease_pinch_factor", slider=True, text="Pinch")
- if brush.sculpt_tool not in ('PINCH', 'INFLATE', 'SMOOTH'):
+ if brush.sculpt_tool not in {'PINCH', 'INFLATE', 'SMOOTH'}:
row = col.row(align=True)
col.separator()
@@ -564,8 +564,8 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
row.prop(brush, "sculpt_plane", text="")
- #if brush.sculpt_tool in ('CLAY', 'CLAY_TUBES', 'FLATTEN', 'FILL', 'SCRAPE'):
- if brush.sculpt_tool in ('CLAY', 'FLATTEN', 'FILL', 'SCRAPE'):
+ #if brush.sculpt_tool in {'CLAY', 'CLAY_TUBES', 'FLATTEN', 'FILL', 'SCRAPE'}:
+ if brush.sculpt_tool in {'CLAY', 'FLATTEN', 'FILL', 'SCRAPE'}:
row = col.row(align=True)
row.prop(brush, "plane_offset", slider=True)
row.prop(brush, "use_offset_pressure", text="")
@@ -578,6 +578,10 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
row.active = brush.use_plane_trim
row.prop(brush, "plane_trim", slider=True, text="Distance")
+ if brush.sculpt_tool == 'LAYER':
+ row = col.row()
+ row.prop(brush, "height", slider=True, text="Height")
+
col.separator()
row = col.row()
@@ -586,7 +590,7 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
col.separator()
col.row().prop(brush, "direction", expand=True)
- if brush.sculpt_tool in ('DRAW', 'CREASE', 'BLOB', 'INFLATE', 'LAYER', 'CLAY'):
+ if brush.sculpt_tool in {'DRAW', 'CREASE', 'BLOB', 'INFLATE', 'LAYER', 'CLAY'}:
col.separator()
col.prop(brush, "use_accumulate")
@@ -608,13 +612,13 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
# Texture Paint Mode #
- elif context.texture_paint_object and brush:
+ elif context.image_paint_object and brush:
col = layout.column()
col.template_color_wheel(brush, "color", value_slider=True)
col.prop(brush, "color", text="")
row = col.row(align=True)
- row.prop(brush, "size", text="Radius", slider=True)
+ row.prop(brush, "size", slider=True)
row.prop(brush, "use_pressure_size", toggle=True, text="")
row = col.row(align=True)
@@ -628,7 +632,7 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
col.prop(brush, "blend", text="Blend")
col = layout.column()
- col.active = (brush.blend not in ('ERASE_ALPHA', 'ADD_ALPHA'))
+ col.active = (brush.blend not in {'ERASE_ALPHA', 'ADD_ALPHA'})
col.prop(brush, "use_alpha")
# Weight Paint Mode #
@@ -639,7 +643,7 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
col = layout.column()
row = col.row(align=True)
- row.prop(brush, "size", text="Radius", slider=True)
+ row.prop(brush, "size", slider=True)
row.prop(brush, "use_pressure_size", toggle=True, text="")
row = col.row(align=True)
@@ -657,7 +661,7 @@ class VIEW3D_PT_tools_brush(PaintPanel, bpy.types.Panel):
col.prop(brush, "color", text="")
row = col.row(align=True)
- row.prop(brush, "size", text="Radius", slider=True)
+ row.prop(brush, "size", slider=True)
row.prop(brush, "use_pressure_size", toggle=True, text="")
row = col.row(align=True)
@@ -678,7 +682,7 @@ class VIEW3D_PT_tools_brush_texture(PaintPanel, bpy.types.Panel):
def poll(cls, context):
settings = cls.paint_settings(context)
return (settings and settings.brush and (context.sculpt_object or
- context.texture_paint_object))
+ context.image_paint_object))
def draw(self, context):
layout = self.layout
@@ -690,6 +694,8 @@ class VIEW3D_PT_tools_brush_texture(PaintPanel, bpy.types.Panel):
col = layout.column()
col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
+ if brush.use_paint_image:
+ col.prop(brush, "use_fixed_texture")
if context.sculpt_object:
#XXX duplicated from properties_texture.py
@@ -703,32 +709,32 @@ class VIEW3D_PT_tools_brush_texture(PaintPanel, bpy.types.Panel):
col.separator()
col = layout.column()
- col.active = tex_slot.map_mode in ('FIXED', )
+ col.active = tex_slot.map_mode in {'FIXED'}
col.label(text="Angle:")
col = layout.column()
- if not brush.use_anchor and brush.sculpt_tool not in ('GRAB', 'SNAKE_HOOK', 'THUMB', 'ROTATE') and tex_slot.map_mode in ('FIXED'):
+ if not brush.use_anchor and brush.sculpt_tool not in {'GRAB', 'SNAKE_HOOK', 'THUMB', 'ROTATE'} and tex_slot.map_mode in {'FIXED'}:
col.prop(brush, "texture_angle_source_random", text="")
else:
col.prop(brush, "texture_angle_source_no_random", text="")
#row = col.row(align=True)
#row.label(text="Angle:")
- #row.active = tex_slot.map_mode in ('FIXED', 'TILED')
+ #row.active = tex_slot.map_mode in {'FIXED', 'TILED'}
#row = col.row(align=True)
#col = row.column()
- #col.active = tex_slot.map_mode in ('FIXED')
+ #col.active = tex_slot.map_mode in {'FIXED'}
#col.prop(brush, "use_rake", toggle=True, icon='PARTICLEMODE', text="")
col = layout.column()
col.prop(tex_slot, "angle", text="")
- col.active = tex_slot.map_mode in ('FIXED', 'TILED')
+ col.active = tex_slot.map_mode in {'FIXED', 'TILED'}
#col = layout.column()
#col.prop(brush, "use_random_rotation")
- #col.active = (not brush.use_rake) and (not brush.use_anchor) and brush.sculpt_tool not in ('GRAB', 'SNAKE_HOOK', 'THUMB', 'ROTATE') and tex_slot.map_mode in ('FIXED')
+ #col.active = (not brush.use_rake) and (not brush.use_anchor) and (brush.sculpt_tool not in {'GRAB', 'SNAKE_HOOK', 'THUMB', 'ROTATE'}) and tex_slot.map_mode in {'FIXED'}
split = layout.split()
@@ -748,7 +754,7 @@ class VIEW3D_PT_tools_brush_texture(PaintPanel, bpy.types.Panel):
row = col.row(align=True)
row.label(text="Overlay:")
- row.active = tex_slot.map_mode in ('FIXED', 'TILED')
+ row.active = tex_slot.map_mode in {'FIXED', 'TILED'}
row = col.row(align=True)
@@ -759,11 +765,11 @@ class VIEW3D_PT_tools_brush_texture(PaintPanel, bpy.types.Panel):
else:
col.prop(brush, "use_texture_overlay", toggle=True, text="", icon='MUTE_IPO_ON')
- col.active = tex_slot.map_mode in ('FIXED', 'TILED')
+ col.active = tex_slot.map_mode in {'FIXED', 'TILED'}
col = row.column()
col.prop(brush, "texture_overlay_alpha", text="Alpha")
- col.active = tex_slot.map_mode in ('FIXED', 'TILED') and brush.use_texture_overlay
+ col.active = tex_slot.map_mode in {'FIXED', 'TILED'} and brush.use_texture_overlay
class VIEW3D_PT_tools_brush_tool(PaintPanel, bpy.types.Panel):
@@ -774,7 +780,7 @@ class VIEW3D_PT_tools_brush_tool(PaintPanel, bpy.types.Panel):
def poll(cls, context):
settings = cls.paint_settings(context)
return (settings and settings.brush and
- (context.sculpt_object or context.texture_paint_object or
+ (context.sculpt_object or context.image_paint_object or
context.vertex_paint_object or context.weight_paint_object))
def draw(self, context):
@@ -782,24 +788,22 @@ class VIEW3D_PT_tools_brush_tool(PaintPanel, bpy.types.Panel):
settings = __class__.paint_settings(context)
brush = settings.brush
- texture_paint = context.texture_paint_object
- sculpt = context.sculpt_object
col = layout.column(align=True)
if context.sculpt_object:
col.prop(brush, "sculpt_tool", expand=False, text="")
col.operator("brush.reset")
- elif context.texture_paint_object:
- col.prop(brush, "imagepaint_tool", expand=False, text="")
+ elif context.image_paint_object:
+ col.prop(brush, "image_tool", expand=False, text="")
elif context.vertex_paint_object or context.weight_paint_object:
- col.prop(brush, "vertexpaint_tool", expand=False, text="")
+ col.prop(brush, "vertex_tool", expand=False, text="")
row = layout.row(align=True)
row.prop(brush, "use_paint_sculpt", text="", icon='SCULPTMODE_HLT')
row.prop(brush, "use_paint_vertex", text="", icon='VPAINT_HLT')
row.prop(brush, "use_paint_weight", text="", icon='WPAINT_HLT')
- row.prop(brush, "use_paint_texture", text="", icon='TPAINT_HLT')
+ row.prop(brush, "use_paint_image", text="", icon='TPAINT_HLT')
class VIEW3D_PT_tools_brush_stroke(PaintPanel, bpy.types.Panel):
@@ -812,14 +816,14 @@ class VIEW3D_PT_tools_brush_stroke(PaintPanel, bpy.types.Panel):
return (settings and settings.brush and (context.sculpt_object or
context.vertex_paint_object or
context.weight_paint_object or
- context.texture_paint_object))
+ context.image_paint_object))
def draw(self, context):
layout = self.layout
settings = __class__.paint_settings(context)
brush = settings.brush
- texture_paint = context.texture_paint_object
+ image_paint = context.image_paint_object
col = layout.column()
@@ -843,7 +847,7 @@ class VIEW3D_PT_tools_brush_stroke(PaintPanel, bpy.types.Panel):
row.active = brush.use_space
row.prop(brush, "spacing", text="Spacing")
- if brush.sculpt_tool not in ('GRAB', 'THUMB', 'SNAKE_HOOK', 'ROTATE') and (not brush.use_anchor) and (not brush.use_restore_mesh):
+ if (brush.sculpt_tool not in {'GRAB', 'THUMB', 'SNAKE_HOOK', 'ROTATE'}) and (not brush.use_anchor) and (not brush.use_restore_mesh):
col = layout.column()
col.separator()
@@ -870,7 +874,7 @@ class VIEW3D_PT_tools_brush_stroke(PaintPanel, bpy.types.Panel):
col.separator()
- if not texture_paint:
+ if not image_paint:
row = col.row()
row.prop(brush, "use_smooth_stroke")
@@ -882,7 +886,7 @@ class VIEW3D_PT_tools_brush_stroke(PaintPanel, bpy.types.Panel):
col.separator()
col = layout.column()
- col.active = (not brush.use_anchor) and (brush.sculpt_tool not in ('GRAB', 'THUMB', 'ROTATE', 'SNAKE_HOOK'))
+ col.active = (not brush.use_anchor) and (brush.sculpt_tool not in {'GRAB', 'THUMB', 'ROTATE', 'SNAKE_HOOK'})
row = col.row()
row.prop(brush, "use_space")
@@ -896,7 +900,7 @@ class VIEW3D_PT_tools_brush_stroke(PaintPanel, bpy.types.Panel):
#col.separator()
- #if texture_paint:
+ #if image_paint:
# row.prop(brush, "use_pressure_spacing", toggle=True, text="")
@@ -941,28 +945,22 @@ class VIEW3D_PT_sculpt_options(PaintPanel, bpy.types.Panel):
tool_settings = context.tool_settings
sculpt = tool_settings.sculpt
settings = __class__.paint_settings(context)
- brush = settings.brush
-
- split = layout.split()
-
- col = split.column()
-
- col.prop(sculpt, "use_threaded", text="Threaded Sculpt")
- col.prop(sculpt, "show_low_resolution")
- col.prop(sculpt, "show_brush")
- col.label(text="Unified Settings:")
- col.prop(tool_settings, "sculpt_paint_use_unified_size", text="Size")
- col.prop(tool_settings, "sculpt_paint_use_unified_strength", text="Strength")
-
- col = split.column()
-
- col.label(text="Lock:")
- row = col.row(align=True)
+ layout.label(text="Lock:")
+ row = layout.row(align=True)
row.prop(sculpt, "lock_x", text="X", toggle=True)
row.prop(sculpt, "lock_y", text="Y", toggle=True)
row.prop(sculpt, "lock_z", text="Z", toggle=True)
+ layout.prop(sculpt, "use_threaded", text="Threaded Sculpt")
+ layout.prop(sculpt, "show_low_resolution")
+ layout.prop(sculpt, "show_brush")
+ layout.prop(sculpt, "use_deform_only")
+
+ layout.label(text="Unified Settings:")
+ layout.prop(tool_settings, "sculpt_paint_use_unified_size", text="Size")
+ layout.prop(tool_settings, "sculpt_paint_use_unified_strength", text="Strength")
+
class VIEW3D_PT_sculpt_symmetry(PaintPanel, bpy.types.Panel):
bl_label = "Symmetry"
@@ -973,31 +971,24 @@ class VIEW3D_PT_sculpt_symmetry(PaintPanel, bpy.types.Panel):
return (context.sculpt_object and context.tool_settings.sculpt)
def draw(self, context):
-
layout = self.layout
sculpt = context.tool_settings.sculpt
settings = __class__.paint_settings(context)
- brush = settings.brush
split = layout.split()
col = split.column()
-
col.label(text="Mirror:")
col.prop(sculpt, "use_symmetry_x", text="X")
col.prop(sculpt, "use_symmetry_y", text="Y")
col.prop(sculpt, "use_symmetry_z", text="Z")
- col = split.column()
-
- col.prop(sculpt, "radial_symmetry", text="Radial")
-
- col = layout.column()
+ split.prop(sculpt, "radial_symmetry", text="Radial")
- col.separator()
+ layout.separator()
- col.prop(sculpt, "use_symmetry_feather", text="Feather")
+ layout.prop(sculpt, "use_symmetry_feather", text="Feather")
class VIEW3D_PT_tools_brush_appearance(PaintPanel, bpy.types.Panel):
@@ -1006,20 +997,19 @@ class VIEW3D_PT_tools_brush_appearance(PaintPanel, bpy.types.Panel):
@classmethod
def poll(cls, context):
- return (context.sculpt_object and context.tool_settings.sculpt) or (context.vertex_paint_object and context.tool_settings.vertex_paint) or (context.weight_paint_object and context.tool_settings.weight_paint) or (context.texture_paint_object and context.tool_settings.image_paint)
+ 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)
def draw(self, context):
layout = self.layout
- sculpt = context.tool_settings.sculpt
settings = __class__.paint_settings(context)
brush = settings.brush
col = layout.column()
if context.sculpt_object and context.tool_settings.sculpt:
- #if brush.sculpt_tool in ('DRAW', 'INFLATE', 'CLAY', 'PINCH', 'CREASE', 'BLOB', 'FLATTEN', 'FILL', 'SCRAPE', 'CLAY_TUBES'):
- if brush.sculpt_tool in ('DRAW', 'INFLATE', 'CLAY', 'PINCH', 'CREASE', 'BLOB', 'FLATTEN', 'FILL', 'SCRAPE'):
+ #if brush.sculpt_tool in {'DRAW', 'INFLATE', 'CLAY', 'PINCH', 'CREASE', 'BLOB', 'FLATTEN', 'FILL', 'SCRAPE', 'CLAY_TUBES'}:
+ if brush.sculpt_tool in {'DRAW', 'INFLATE', 'CLAY', 'PINCH', 'CREASE', 'BLOB', 'FLATTEN', 'FILL', 'SCRAPE'}:
col.prop(brush, "cursor_color_add", text="Add Color")
col.prop(brush, "cursor_color_subtract", text="Subtract Color")
else:
@@ -1124,13 +1114,13 @@ class VIEW3D_PT_tools_vertexpaint(View3DPanel, bpy.types.Panel):
class VIEW3D_PT_tools_projectpaint(View3DPanel, bpy.types.Panel):
- bl_context = "texturepaint"
+ bl_context = "imagepaint"
bl_label = "Project Paint"
@classmethod
def poll(cls, context):
brush = context.tool_settings.image_paint.brush
- return (brush and brush.imagepaint_tool != 'SOFTEN')
+ return (brush and brush.image_tool != 'SOFTEN')
def draw_header(self, context):
ipaint = context.tool_settings.image_paint
@@ -1140,6 +1130,8 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, bpy.types.Panel):
def draw(self, context):
layout = self.layout
+ ob = context.active_object
+ mesh = ob.data
ipaint = context.tool_settings.image_paint
settings = context.tool_settings.image_paint
use_projection = ipaint.use_projection
@@ -1167,16 +1159,16 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, bpy.types.Panel):
row2 = row.row(align=False)
row2.active = (use_projection and ipaint.use_stencil_layer)
- row2.menu("VIEW3D_MT_tools_projectpaint_stencil", text=context.active_object.data.uv_texture_stencil.name)
+ row2.menu("VIEW3D_MT_tools_projectpaint_stencil", text=mesh.uv_texture_stencil.name)
row2.prop(ipaint, "invert_stencil", text="", icon='IMAGE_ALPHA')
col = layout.column()
sub = col.column()
row = sub.row()
- row.active = (settings.brush.imagepaint_tool == 'CLONE')
+ row.active = (settings.brush.image_tool == 'CLONE')
row.prop(ipaint, "use_clone_layer", text="Layer")
- row.menu("VIEW3D_MT_tools_projectpaint_clone", text=context.active_object.data.uv_texture_clone.name)
+ row.menu("VIEW3D_MT_tools_projectpaint_clone", text=mesh.uv_texture_clone.name)
sub = col.column()
sub.prop(ipaint, "seam_bleed")
@@ -1200,14 +1192,14 @@ class VIEW3D_PT_imagepaint_options(PaintPanel):
@classmethod
def poll(cls, context):
- return (context.texture_paint_object and context.tool_settings.image_paint)
+ return (context.image_paint_object and context.tool_settings.image_paint)
def draw(self, context):
layout = self.layout
- col = layout.column()
-
tool_settings = context.tool_settings
+
+ col = layout.column()
col.label(text="Unified Settings:")
col.prop(tool_settings, "sculpt_paint_use_unified_size", text="Size")
col.prop(tool_settings, "sculpt_paint_use_unified_strength", text="Strength")
@@ -1300,13 +1292,5 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, bpy.types.Panel):
sub.active = pe.use_fade_time
sub.prop(pe, "fade_frames", slider=True)
-
-def register():
+if __name__ == "__main__": # only for live edit.
bpy.utils.register_module(__name__)
-
-
-def unregister():
- bpy.utils.unregister_module(__name__)
-
-if __name__ == "__main__":
- register()
diff --git a/release/scripts/keyingsets/keyingsets_builtins.py b/release/scripts/startup/keyingsets_builtins.py
index cff4aecac54..8cb63ea48cf 100644
--- a/release/scripts/keyingsets/keyingsets_builtins.py
+++ b/release/scripts/startup/keyingsets_builtins.py
@@ -23,10 +23,15 @@ Built-In Keying Sets
None of these Keying Sets should be removed, as these
are needed by various parts of Blender in order for them
to work correctly.
+
+Beware also about changing the order that these are defined
+here, since this can result in old files referring to the
+wrong Keying Set as the active one, potentially resulting
+in lost (i.e. unkeyed) animation.
"""
import bpy
-from keyingsets_utils import *
+import keyingsets_utils
###############################
# Built-In KeyingSets
@@ -37,13 +42,13 @@ class BUILTIN_KSI_Location(bpy.types.KeyingSetInfo):
bl_label = "Location"
# poll - use predefined callback for selected bones/objects
- poll = RKS_POLL_selected_items
+ poll = keyingsets_utils.RKS_POLL_selected_items
# iterator - use callback for selected bones/objects
- iterator = RKS_ITER_selected_item
+ iterator = keyingsets_utils.RKS_ITER_selected_item
# generator - use callback for location
- generate = RKS_GEN_location
+ generate = keyingsets_utils.RKS_GEN_location
# Rotation
@@ -51,13 +56,13 @@ class BUILTIN_KSI_Rotation(bpy.types.KeyingSetInfo):
bl_label = "Rotation"
# poll - use predefined callback for selected bones/objects
- poll = RKS_POLL_selected_items
+ poll = keyingsets_utils.RKS_POLL_selected_items
# iterator - use callback for selected bones/objects
- iterator = RKS_ITER_selected_item
+ iterator = keyingsets_utils.RKS_ITER_selected_item
# generator - use callback for location
- generate = RKS_GEN_rotation
+ generate = keyingsets_utils.RKS_GEN_rotation
# Scale
@@ -65,13 +70,13 @@ class BUILTIN_KSI_Scaling(bpy.types.KeyingSetInfo):
bl_label = "Scaling"
# poll - use predefined callback for selected bones/objects
- poll = RKS_POLL_selected_items
+ poll = keyingsets_utils.RKS_POLL_selected_items
# iterator - use callback for selected bones/objects
- iterator = RKS_ITER_selected_item
+ iterator = keyingsets_utils.RKS_ITER_selected_item
# generator - use callback for location
- generate = RKS_GEN_scaling
+ generate = keyingsets_utils.RKS_GEN_scaling
# ------------
@@ -81,17 +86,17 @@ class BUILTIN_KSI_LocRot(bpy.types.KeyingSetInfo):
bl_label = "LocRot"
# poll - use predefined callback for selected bones/objects
- poll = RKS_POLL_selected_items
+ poll = keyingsets_utils.RKS_POLL_selected_items
# iterator - use callback for selected bones/objects
- iterator = RKS_ITER_selected_item
+ iterator = keyingsets_utils.RKS_ITER_selected_item
# generator
def generate(self, context, ks, data):
# location
- RKS_GEN_location(self, context, ks, data)
+ keyingsets_utils.RKS_GEN_location(self, context, ks, data)
# rotation
- RKS_GEN_rotation(self, context, ks, data)
+ keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
# LocScale
@@ -99,17 +104,17 @@ class BUILTIN_KSI_LocScale(bpy.types.KeyingSetInfo):
bl_label = "LocScale"
# poll - use predefined callback for selected bones/objects
- poll = RKS_POLL_selected_items
+ poll = keyingsets_utils.RKS_POLL_selected_items
# iterator - use callback for selected bones/objects
- iterator = RKS_ITER_selected_item
+ iterator = keyingsets_utils.RKS_ITER_selected_item
# generator
def generate(self, context, ks, data):
# location
- RKS_GEN_location(self, context, ks, data)
+ keyingsets_utils.RKS_GEN_location(self, context, ks, data)
# scale
- RKS_GEN_scaling(self, context, ks, data)
+ keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
# LocRotScale
@@ -117,19 +122,19 @@ class BUILTIN_KSI_LocRotScale(bpy.types.KeyingSetInfo):
bl_label = "LocRotScale"
# poll - use predefined callback for selected bones/objects
- poll = RKS_POLL_selected_items
+ poll = keyingsets_utils.RKS_POLL_selected_items
# iterator - use callback for selected bones/objects
- iterator = RKS_ITER_selected_item
+ iterator = keyingsets_utils.RKS_ITER_selected_item
# generator
def generate(self, context, ks, data):
# location
- RKS_GEN_location(self, context, ks, data)
+ keyingsets_utils.RKS_GEN_location(self, context, ks, data)
# rotation
- RKS_GEN_rotation(self, context, ks, data)
+ keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
# scale
- RKS_GEN_scaling(self, context, ks, data)
+ keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
# RotScale
@@ -137,17 +142,17 @@ class BUILTIN_KSI_RotScale(bpy.types.KeyingSetInfo):
bl_label = "RotScale"
# poll - use predefined callback for selected bones/objects
- poll = RKS_POLL_selected_items
+ poll = keyingsets_utils.RKS_POLL_selected_items
# iterator - use callback for selected bones/objects
- iterator = RKS_ITER_selected_item
+ iterator = keyingsets_utils.RKS_ITER_selected_item
# generator
def generate(self, context, ks, data):
# rotation
- RKS_GEN_rotation(self, context, ks, data)
+ keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
# scaling
- RKS_GEN_scaling(self, context, ks, data)
+ keyingsets_utils.RKS_GEN_scaling(self, context, ks, data)
# ------------
@@ -159,13 +164,13 @@ class BUILTIN_KSI_VisualLoc(bpy.types.KeyingSetInfo):
bl_options = {'INSERTKEY_VISUAL'}
# poll - use predefined callback for selected bones/objects
- poll = RKS_POLL_selected_items
+ poll = keyingsets_utils.RKS_POLL_selected_items
# iterator - use callback for selected bones/objects
- iterator = RKS_ITER_selected_item
+ iterator = keyingsets_utils.RKS_ITER_selected_item
# generator - use callback for location
- generate = RKS_GEN_location
+ generate = keyingsets_utils.RKS_GEN_location
# Rotation
@@ -175,13 +180,13 @@ class BUILTIN_KSI_VisualRot(bpy.types.KeyingSetInfo):
bl_options = {'INSERTKEY_VISUAL'}
# poll - use predefined callback for selected bones/objects
- poll = RKS_POLL_selected_items
+ poll = keyingsets_utils.RKS_POLL_selected_items
# iterator - use callback for selected bones/objects
- iterator = RKS_ITER_selected_item
+ iterator = keyingsets_utils.RKS_ITER_selected_item
# generator - use callback for rotation
- generate = RKS_GEN_rotation
+ generate = keyingsets_utils.RKS_GEN_rotation
# VisualLocRot
@@ -191,17 +196,17 @@ class BUILTIN_KSI_VisualLocRot(bpy.types.KeyingSetInfo):
bl_options = {'INSERTKEY_VISUAL'}
# poll - use predefined callback for selected bones/objects
- poll = RKS_POLL_selected_items
+ poll = keyingsets_utils.RKS_POLL_selected_items
# iterator - use callback for selected bones/objects
- iterator = RKS_ITER_selected_item
+ iterator = keyingsets_utils.RKS_ITER_selected_item
# generator
def generate(self, context, ks, data):
# location
- RKS_GEN_location(self, context, ks, data)
+ keyingsets_utils.RKS_GEN_location(self, context, ks, data)
# rotation
- RKS_GEN_rotation(self, context, ks, data)
+ keyingsets_utils.RKS_GEN_rotation(self, context, ks, data)
# ------------
@@ -210,16 +215,20 @@ class BUILTIN_KSI_VisualLocRot(bpy.types.KeyingSetInfo):
class BUILTIN_KSI_Available(bpy.types.KeyingSetInfo):
bl_label = "Available"
- # poll - use predefined callback for selected objects
- # TODO: this should really check whether the selected object (or datablock)
- # has any animation data defined yet
- poll = RKS_POLL_selected_objects
+ # poll - selected objects or selected object with animation data
+ def poll(ksi, context):
+ ob = context.active_object
+ if ob:
+ # TODO: this fails if one animation-less object is active, but many others are selected
+ return ob.animation_data and ob.animation_data.action
+ else:
+ return bool(context.selected_objects)
# iterator - use callback for selected bones/objects
- iterator = RKS_ITER_selected_item
+ iterator = keyingsets_utils.RKS_ITER_selected_item
# generator - use callback for doing this
- generate = RKS_GEN_available
+ generate = keyingsets_utils.RKS_GEN_available
###############################
@@ -278,7 +287,7 @@ class BUILTIN_KSI_WholeCharacter(bpy.types.KeyingSetInfo):
path = id_path + prop
else:
# standard transforms/properties
- path = path_add_property(id_path, prop)
+ path = keyingsets_utils.path_add_property(id_path, prop)
# add Keying Set entry for this...
if use_groups:
@@ -352,6 +361,93 @@ class BUILTIN_KSI_WholeCharacter(bpy.types.KeyingSetInfo):
# for now, just add all of 'em
ksi.addProp(ks, bone, '["%s"]' % (prop))
+###############################
+
+
+# Delta Location
+class BUILTIN_KSI_DeltaLocation(bpy.types.KeyingSetInfo):
+ bl_label = "Delta Location"
+
+ # poll - selected objects only (and only if active object in object mode)
+ poll = keyingsets_utils.RKS_POLL_selected_objects
+
+ # iterator - selected objects only
+ iterator = keyingsets_utils.RKS_ITER_selected_objects
+
+ # generator - delta location channels only
+ def generate(ksi, context, ks, data):
+ # get id-block and path info
+ id_block, base_path, grouping = keyingsets_utils.get_transform_generators_base_info(data)
+
+ # add the property name to the base path
+ path = keyingsets_utils.path_add_property(base_path, "delta_location")
+
+ # add Keying Set entry for this...
+ if grouping:
+ ks.paths.add(id_block, path, group_method='NAMED', group_name=grouping)
+ else:
+ ks.paths.add(id_block, path)
+
+
+# Delta Rotation
+class BUILTIN_KSI_DeltaRotation(bpy.types.KeyingSetInfo):
+ bl_label = "Delta Rotation"
+
+ # poll - selected objects only (and only if active object in object mode)
+ poll = keyingsets_utils.RKS_POLL_selected_objects
+
+ # iterator - selected objects only
+ iterator = keyingsets_utils.RKS_ITER_selected_objects
+
+ # generator - delta location channels only
+ def generate(ksi, context, ks, data):
+ # get id-block and path info
+ id_block, base_path, grouping = keyingsets_utils.get_transform_generators_base_info(data)
+
+ # 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")
+ elif data.rotation_mode == 'AXIS_ANGLE':
+ # XXX: for now, this is not available yet
+ #path = path_add_property(base_path, "delta_rotation_axis_angle")
+ return
+ else:
+ path = keyingsets_utils.path_add_property(base_path, "delta_rotation_euler")
+
+ # add Keying Set entry for this...
+ if grouping:
+ ks.paths.add(id_block, path, group_method='NAMED', group_name=grouping)
+ else:
+ ks.paths.add(id_block, path)
+
+
+# Delta Scale
+class BUILTIN_KSI_DeltaScale(bpy.types.KeyingSetInfo):
+ bl_label = "Delta Scale"
+
+ # poll - selected objects only (and only if active object in object mode)
+ poll = keyingsets_utils.RKS_POLL_selected_objects
+
+ # iterator - selected objects only
+ iterator = keyingsets_utils.RKS_ITER_selected_objects
+
+ # generator - delta location channels only
+ def generate(ksi, context, ks, data):
+ # get id-block and path info
+ id_block, base_path, grouping = keyingsets_utils.get_transform_generators_base_info(data)
+
+ # add the property name to the base path
+ path = keyingsets_utils.path_add_property(base_path, "delta_scale")
+
+ # add Keying Set entry for this...
+ if grouping:
+ ks.paths.add(id_block, path, group_method='NAMED', group_name=grouping)
+ else:
+ ks.paths.add(id_block, path)
+
+###############################
+
def register():
bpy.utils.register_module(__name__)
@@ -363,5 +459,3 @@ def unregister():
if __name__ == "__main__":
register()
-
-###############################
diff --git a/release/scripts/templates/addon_add_object.py b/release/scripts/templates/addon_add_object.py
index f4f1185e282..67e033271f4 100644
--- a/release/scripts/templates/addon_add_object.py
+++ b/release/scripts/templates/addon_add_object.py
@@ -31,8 +31,10 @@ def add_object(self, context):
edges = []
faces = [[0, 1, 2, 3]]
- mesh_data = bpy.data.meshes.new(name='New Object Mesh')
- mesh_data.from_pydata(verts, edges, faces)
+ mesh = bpy.data.meshes.new(name='New Object Mesh')
+ 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)
@@ -55,7 +57,7 @@ class OBJECT_OT_add_object(bpy.types.Operator, AddObjectHelper):
return {'FINISHED'}
-#### REGISTER ####
+# Registration
def add_object_button(self, context):
self.layout.operator(
diff --git a/release/scripts/templates/background_job.py b/release/scripts/templates/background_job.py
index 0337f8f4922..11b51e5a9b5 100644
--- a/release/scripts/templates/background_job.py
+++ b/release/scripts/templates/background_job.py
@@ -1,12 +1,18 @@
-# This script is an example of how you can run blender from the command line (in background mode with no interface)
-# to automate tasks, in this example it creates a text object, camera and light, then renders and/or saves it.
-# This example also shows how you can parse command line options to python scripts.
+# This script is an example of how you can run blender from the command line
+# (in background mode with no interface) to automate tasks, in this example it
+# creates a text object, camera and light, then renders and/or saves it.
+# This example also shows how you can parse command line options to scripts.
#
# Example usage for this test.
-# blender --background --factory-startup --python $HOME/background_job.py -- --text="Hello World" --render="/tmp/hello" --save="/tmp/hello.blend"
+# blender --background --factory-startup --python $HOME/background_job.py -- \
+# --text="Hello World" \
+# --render="/tmp/hello" \
+# --save="/tmp/hello.blend"
#
# Notice:
-# '--factory-startup' is used to avoid the user default settings from interfearing with automated scene generation.
+# '--factory-startup' is used to avoid the user default settings from
+# interfearing with automated scene generation.
+#
# '--' causes blender to ignore all following arguments so python can use them.
#
# See blender --help for details.
@@ -14,7 +20,7 @@
import bpy
-def example_function(body_text, save_path, render_path):
+def example_function(text, save_path, render_path):
scene = bpy.context.scene
@@ -27,15 +33,15 @@ def example_function(body_text, save_path, render_path):
# Text Object
txt_ob = bpy.data.objects.new(name="MyText", object_data=txt_data)
- scene.objects.link(txt_ob) # add the data to the scene as an object
- txt_data.body = body_text # set the body text to the command line arg given
- txt_data.align = 'CENTER' # center text
+ scene.objects.link(txt_ob) # add the data to the scene as an object
+ txt_data.body = text # the body text to the command line arg given
+ txt_data.align = 'CENTER' # center text
# Camera
- cam_data = bpy.data.cameras.new("MyCam") # create new camera data
+ cam_data = bpy.data.cameras.new("MyCam")
cam_ob = bpy.data.objects.new(name="MyCam", object_data=cam_data)
- scene.objects.link(cam_ob) # add the camera data to the scene (creating a new object)
- scene.camera = cam_ob # set the active camera
+ scene.objects.link(cam_ob) # instance the camera object in the scene
+ scene.camera = cam_ob # set the active camera
cam_ob.location = 0.0, 0.0, 10.0
# Lamp
@@ -65,14 +71,12 @@ def example_function(body_text, save_path, render_path):
bpy.ops.render.render(write_still=True)
-import sys # to get command line args
-import optparse # to parse options for us and print a nice help message
-
-
def main():
+ import sys # to get command line args
+ import argparse # to parse options for us and print a nice help message
- # get the args passed to blender after "--", all of which are ignored by blender specifically
- # so python may receive its own arguments
+ # get the args passed to blender after "--", all of which are ignored by
+ # blender so scripts may receive their own arguments
argv = sys.argv
if "--" not in argv:
@@ -81,31 +85,35 @@ def main():
argv = argv[argv.index("--") + 1:] # get all args after "--"
# When --help or no args are given, print this help
- usage_text = "Run blender in background mode with this script:"
- usage_text += " blender --background --python " + __file__ + " -- [options]"
+ usage_text = \
+ "Run blender in background mode with this script:"
+ " blender --background --python " + __file__ + " -- [options]"
- parser = optparse.OptionParser(usage=usage_text)
+ parser = argparse.ArgumentParser(description=usage_text)
- # Example background utility, add some text and renders or saves it (with options)
+ # Example utility, add some text and renders or saves it (with options)
# Possible types are: string, int, long, choice, float and complex.
- parser.add_option("-t", "--text", dest="body_text", help="This text will be used to render an image", type="string")
+ parser.add_argument("-t", "--text", dest="text", type=str, required=True,
+ help="This text will be used to render an image")
- parser.add_option("-s", "--save", dest="save_path", help="Save the generated file to the specified path", metavar='FILE')
- parser.add_option("-r", "--render", dest="render_path", help="Render an image to the specified path", metavar='FILE')
+ parser.add_argument("-s", "--save", dest="save_path", metavar='FILE',
+ help="Save the generated file to the specified path")
+ parser.add_argument("-r", "--render", dest="render_path", metavar='FILE',
+ help="Render an image to the specified path")
- options, args = parser.parse_args(argv) # In this example we wont use the args
+ args = parser.parse_args(argv) # In this example we wont use the args
if not argv:
parser.print_help()
return
- if not options.body_text:
+ if not args.text:
print("Error: --text=\"some string\" argument not given, aborting.")
parser.print_help()
return
# Run the example function
- example_function(options.body_text, options.save_path, options.render_path)
+ example_function(args.text, args.save_path, args.render_path)
print("batch job finished, exiting")
diff --git a/release/scripts/templates/builtin_keyingset.py b/release/scripts/templates/builtin_keyingset.py
index 0b808e9cd26..19f92dc75e7 100644
--- a/release/scripts/templates/builtin_keyingset.py
+++ b/release/scripts/templates/builtin_keyingset.py
@@ -1,5 +1,4 @@
import bpy
-from keyingsets_utils import *
class BUILTIN_KSI_hello(bpy.types.KeyingSetInfo):
@@ -7,7 +6,7 @@ class BUILTIN_KSI_hello(bpy.types.KeyingSetInfo):
# poll - test for whether Keying Set can be used at all
def poll(ksi, context):
- return (context.active_object) or (context.selected_objects)
+ return context.active_object or context.selected_objects
# iterator - go over all relevant data, calling generate()
def iterator(ksi, context, ks):
diff --git a/release/scripts/templates/operator_export.py b/release/scripts/templates/operator_export.py
index 5390d32aeff..1b1c90c8a21 100644
--- a/release/scripts/templates/operator_export.py
+++ b/release/scripts/templates/operator_export.py
@@ -13,12 +13,11 @@ def write_some_data(context, filepath, use_some_setting):
# ExportHelper is a helper class, defines filename and
# invoke() function which calls the file selector.
from io_utils import ExportHelper
-
-from bpy.props import *
+from bpy.props import StringProperty, BoolProperty, EnumProperty
class ExportSomeData(bpy.types.Operator, ExportHelper):
- '''This appiers in the tooltip of the operator and in the generated docs.'''
+ '''This appears in the tooltip of the operator and in the generated docs.'''
bl_idname = "export.some_data" # this is important since its how bpy.ops.export.some_data is constructed
bl_label = "Export Some Data"
@@ -31,7 +30,9 @@ class ExportSomeData(bpy.types.Operator, ExportHelper):
# to the class instance from the operator settings before calling.
use_setting = BoolProperty(name="Example Boolean", description="Example Tooltip", default=True)
- type = bpy.props.EnumProperty(items=(('OPT_A', "First Option", "Description one"), ('OPT_B', "Second Option", "Description two.")),
+ 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')
diff --git a/release/scripts/templates/operator_mesh_add.py b/release/scripts/templates/operator_mesh_add.py
index 77d172b3068..65b08eebb4e 100644
--- a/release/scripts/templates/operator_mesh_add.py
+++ b/release/scripts/templates/operator_mesh_add.py
@@ -34,7 +34,7 @@ def add_box(width, height, depth):
return vertices, faces
-from bpy.props import *
+from bpy.props import FloatProperty, BoolProperty, FloatVectorProperty
class AddBox(bpy.types.Operator):
diff --git a/release/scripts/templates/operator_modal.py b/release/scripts/templates/operator_modal.py
index 6eb3843d6a6..78dbd4c6b43 100644
--- a/release/scripts/templates/operator_modal.py
+++ b/release/scripts/templates/operator_modal.py
@@ -1,5 +1,5 @@
import bpy
-from bpy.props import *
+from bpy.props import IntProperty, FloatProperty
class ModalOperator(bpy.types.Operator):
diff --git a/release/scripts/templates/operator_modal_timer.py b/release/scripts/templates/operator_modal_timer.py
new file mode 100644
index 00000000000..d2267191cf5
--- /dev/null
+++ b/release/scripts/templates/operator_modal_timer.py
@@ -0,0 +1,45 @@
+import bpy
+
+
+class ModalTimerOperator(bpy.types.Operator):
+ '''Operator which runs its self from a timer.'''
+ bl_idname = "wm.modal_timer_operator"
+ bl_label = "Modal Timer Operator"
+
+ _timer = None
+
+ def modal(self, context, event):
+ if event.type == 'ESC':
+ return self.cancel()
+
+ if event.type == 'TIMER':
+ # change theme color, silly!
+ color = context.user_preferences.themes[0].view_3d.back
+ color.s = 1.0
+ color.h += 0.01
+
+ return {'PASS_THROUGH'}
+
+ def execute(self, context):
+ context.window_manager.modal_handler_add(self)
+ self._timer = context.window_manager.event_timer_add(0.1, context.window)
+ return {'RUNNING_MODAL'}
+
+ def cancel(self, context):
+ context.window_manager.event_timer_remove(self._timer)
+ return {'CANCELLED'}
+
+
+def register():
+ bpy.utils.register_class(ModalTimerOperator)
+
+
+def unregister():
+ bpy.utils.unregister_class(ModalTimerOperator)
+
+
+if __name__ == "__main__":
+ register()
+
+ # test call
+ bpy.ops.wm.modal_timer_operator()
diff --git a/release/scripts/templates/panel_simple.py b/release/scripts/templates/panel_simple.py
index ddbd4eb7aa4..e5bf70cb654 100644
--- a/release/scripts/templates/panel_simple.py
+++ b/release/scripts/templates/panel_simple.py
@@ -26,7 +26,7 @@ def register():
def unregister():
- bpy.utils.unregister_class(OBJECT_PT_hello)
+ bpy.utils.unregister_class(OBJECT_PT_hello)
if __name__ == "__main__":
diff --git a/release/text/readme.html b/release/text/readme.html
index aa73a8cb512..1014d8ef80a 100644
--- a/release/text/readme.html
+++ b/release/text/readme.html
@@ -12,37 +12,35 @@
</style>
</head>
<body>
-<p class="title"><b>Blender 2.56 Beta</b></p>
+<p class="title"><b>Blender 2.57</b></p>
<p><br></p>
<p class="header"><b>About</b></p>
-<p class="body">Welcome to Blender, the free, open source 3D application for modeling, animation, rendering, compositing, video editing and game creation. Blender is available for Linux, Mac OS X, Windows, Solaris and Irix and has a large world-wide community.</p>
+<p class="body">Welcome to Blender, the free, open source 3D application for modeling, animation, rendering, compositing, video editing and game creation. Blender is available for Linux, Mac OS X, Windows, Solaris and FreeBSD and has a large world-wide community.</p>
<p class="body">Blender can be used freely for any purpose, including commercial use and distribution. It's free and open-source software, released under the GNU GPL licence. The entire source code is available on our website.</p>
<p class="body">For more information, visit <a href="http://www.blender.org">blender.org</a>.</p>
<p><br></p>
-<p class="header"><b>2.56 Beta</b></p>
-<p class="body">The Blender Foundation and online developer community is proud to present Blender 2.56 Beta. This release is the fourth official beta release of the Blender 2.5 series, and represents the culmination of many years of redesign and development work. <a href="http://www.blender.org/development/release-logs/blender-256-beta/">More information about this release</a>.</p>
+<p class="header"><b>2.57</b></p>
+<p class="body">The Blender Foundation and online developer community is proud to present Blender 2.57. This release is the first official stable release of the Blender 2.5 series, and represents the culmination of many years of redesign and development work. <a href="http://www.blender.org/development/release-logs/blender-256-beta/">More information about this release</a>.</p>
<p class="body">What to Expect:</p>
<p class="body"> • Big improvements - This is our most exciting version to date, already a significant improvement in many ways over 2.49</p>
<p class="body"> • Missing/Incomplete Features - Although most of it is there, not all functionality from pre-2.5 versions has been restored yet. Some functionality may be re-implemented a different way.</p>
-<p class="body"> • Bugs - We've fixed a lot lately, but there are still quite a few bugs. This is beta software, we're still working on it!</p>
<p class="body"> • Changes - If you're used to the old Blenders, Blender 2.5 may seem quite different at first, but it won't be long before it grows on you even more than before.</p>
<p><br></p>
<p class="header"><b>Bugs</b></p>
-<p class="body">Blender 2.56 Beta is unfinished software. If you encounter a bug, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender 2.56. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.</p>
+<p class="body">Although Blender 2.57 is considered a stable release, you may encounter a bug. If you do, please help us by posting it in the bug tracker or using Help → Report a Bug from inside Blender 2.57. If it wasn’t reported yet, please log in (or register) and fill in detailed information about the error. Please post detailed instructions on how to reproduce it or post a .blend file showcasing the bug.</p>
<p><br></p>
<p class="header"><b>Package Contents</b></p>
<p class="body">The downloaded Blender package includes:</p>
<p class="body"> • The Blender application for the chosen operating system.</p>
-<p class="body"> • Scripts for importing and exporters to other 3d formats.</p>
+<p class="body"> • Scripts for importing and exporting to other 3d formats.</p>
<p class="body"> • Readme and copyright files.</p>
<p><br></p>
<p class="header"><b>Installation</b></p>
-<p class="body"><b>Windows: </b>The download .zip contains a Blender folder. You may put this anywhere on your hard drive. To launch Blender, double-click on Blender.exe.<br>
-Install scripts by putting them in the .blender/scripts folder next to the executable.</p>
-<p class="body"><b>Linux, FreeBSD, Irix, Solaris: </b>Unpack the distribution, copy the .blender directory from it to your home directory. Then run the Blender executable.<br>
-Install scripts by putting them in the .blender/scripts inside your home folder.</p>
-<p class="body"><b>Mac OS X: </b>The downloaded package includes blender.app. Optionally copy this to your Applications folder, and add it to the dock by dragging it from there to the dock.<br>
-Install scripts by putting them in the .blender/scripts inside your home folder. If the folder does not exist, you can create it manually.</p>
+<p class="body"><b>Windows: </b>The download .zip contains a Blender folder. You may put this anywhere on your hard drive. To launch Blender, double-click on Blender.exe.</p>
+<p class="body"><b>Linux, FreeBSD, Solaris: </b>Unpack the archive, Then run the Blender executable.</p>
+<p class="body"><b>Mac OS X: </b>The downloaded package includes blender.app. Optionally copy this to your Applications folder, and add it to the dock by dragging it from there to the dock.</p>
+<p></p>
+<p class="body"><b>Installing Add-ons (all systems)</b> Add-ons can be installed from the user preferences addons section, download an addon as a .py or .zip file, then press the "Install Add-on" button and select the file to install it.</p>
<p><br></p>
<p class="header"><b>Getting Started</b></p>
<p class="body">When opening Blender, you’ll see large 3D view in the center, a Toolbar on the left, a Properties area on the right and a Timeline at the bottom.</p>
@@ -53,7 +51,7 @@ Install scripts by putting them in the .blender/scripts inside your home folder.
<p class="header"><b>Links</b></p>
<p class="body">Users:</p>
<p class="body"> General information <a href="http://www.blender.org">www.blender.org</a> <br>
- Full release log <a href="http://www.blender.org/development/release-logs/blender-254-beta/">www.blender.org/development/release-logs/blender-256-beta/</a><br>
+ Full release log <a href="http://www.blender.org/development/release-logs/blender-257/">www.blender.org/development/release-logs/blender-257/</a><br>
Tutorials <a href="http://www.blender.org/education-help/">www.blender.org/education-help/</a> <br>
Manual <a href="http://wiki.blender.org/index.php/Doc:Manual">wiki.blender.org/index.php/Doc:Manual</a><br>
User Forum <a href="http://www.blenderartists.org">www.blenderartists.org</a><br>
diff --git a/release/windows/contrib/vfapi/vfapi-plugin.c b/release/windows/contrib/vfapi/vfapi-plugin.c
index c54f8234d2d..81547b8bb1a 100644
--- a/release/windows/contrib/vfapi/vfapi-plugin.c
+++ b/release/windows/contrib/vfapi/vfapi-plugin.c
@@ -114,17 +114,17 @@ __declspec(dllexport) HRESULT vfGetPluginInfo(
static unsigned long getipaddress(const char * ipaddr)
{
- struct hostent *host;
- unsigned long ip;
+ struct hostent *host;
+ unsigned long ip;
- if (((ip = inet_addr(ipaddr)) == INADDR_NONE)
- && strcmp(ipaddr, "255.255.255.255") != 0) {
- if ((host = gethostbyname(ipaddr)) != NULL) {
- memcpy(&ip, host->h_addr, sizeof(ip));
- }
- }
+ if (((ip = inet_addr(ipaddr)) == INADDR_NONE)
+ && strcmp(ipaddr, "255.255.255.255") != 0) {
+ if ((host = gethostbyname(ipaddr)) != NULL) {
+ memcpy(&ip, host->h_addr, sizeof(ip));
+ }
+ }
- return (ip);
+ return (ip);
}
static void my_send(SOCKET sock, char * str)
@@ -363,12 +363,12 @@ HRESULT __stdcall VF_ReadDataFunc_Blen(
} while (strcmp(buf, "P6\n") != 0);
do {
- rval = my_gets(s_in, buf, 256);
- } while ( (buf[0] == '#' || buf[0] == '\n') && rval >= 0);
+ rval = my_gets(s_in, buf, 256);
+ } while ( (buf[0] == '#' || buf[0] == '\n') && rval >= 0);
- if (sscanf(buf, "%d %d\n", &width, &height) != 2) {
+ if (sscanf(buf, "%d %d\n", &width, &height) != 2) {
goto errout;
- }
+ }
if (width != c->width || height != c->height) {
goto errout;
diff --git a/release/windows/installer/00.sconsblender.nsi b/release/windows/installer/00.sconsblender.nsi
index e5ebf8b2f64..03f62f0df48 100644
--- a/release/windows/installer/00.sconsblender.nsi
+++ b/release/windows/installer/00.sconsblender.nsi
@@ -1,251 +1,261 @@
-;
-; $Id$
-;
-; Blender Self-Installer for Windows (NSIS - http://nsis.sourceforge.net)
-;
-; Requires the MoreInfo plugin - http://nsis.sourceforge.net/MoreInfo_plug-in
-;
-
-!include "MUI.nsh"
-!include "WinVer.nsh"
-!include "FileFunc.nsh"
-!include "WordFunc.nsh"
-!include "nsDialogs.nsh"
-!include "x64.nsh"
-
-RequestExecutionLevel user
-
-SetCompressor /SOLID lzma
-
-Name "Blender [VERSION]"
-
-!define MUI_ABORTWARNING
-
-!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of Blender. It is recommended that you close all other applications before starting Setup."
-!define MUI_WELCOMEFINISHPAGE_BITMAP "[RELDIR]\01.installer.bmp"
-!define MUI_HEADERIMAGE
-!define MUI_HEADERIMAGE_BITMAP "[RELDIR]\00.header.bmp"
-!define MUI_COMPONENTSPAGE_SMALLDESC
-!define MUI_FINISHPAGE_RUN "$INSTDIR\blender.exe"
-!define MUI_CHECKBITMAP "[RELDIR]\00.checked.bmp"
-!define MUI_UNWELCOMEFINISHPAGE_BITMAP "[RELDIR]\01.installer.bmp"
-
-!insertmacro MUI_PAGE_WELCOME
-!insertmacro MUI_PAGE_LICENSE "[DISTDIR]\Copyright.txt"
-!insertmacro MUI_PAGE_COMPONENTS
-
-!insertmacro MUI_PAGE_DIRECTORY
-Page custom DataLocation DataLocationOnLeave
-!insertmacro MUI_PAGE_INSTFILES
-!insertmacro MUI_PAGE_FINISH
-
-!insertmacro MUI_UNPAGE_WELCOME
-!insertmacro MUI_UNPAGE_CONFIRM
-!insertmacro MUI_UNPAGE_INSTFILES
-!insertmacro MUI_UNPAGE_FINISH
-
-!insertmacro Locate
-!insertmacro VersionCompare
-
-
-Icon "[RELDIR]\00.installer.ico"
-UninstallIcon "[RELDIR]\00.installer.ico"
-
-;--------------------------------
-;Languages
-
- !insertmacro MUI_LANGUAGE "English"
-
-;--------------------------------
-;Language Strings
-
- ;Description
- LangString DESC_SecCopyUI ${LANG_ENGLISH} "Copy all required files to the application folder."
- LangString DESC_Section2 ${LANG_ENGLISH} "Add shortcut items to the Start Menu. (Recommended)"
- LangString DESC_Section3 ${LANG_ENGLISH} "Add a shortcut to Blender on your desktop."
- LangString DESC_Section4 ${LANG_ENGLISH} "Blender can register itself with .blend files to allow double-clicking from Windows Explorer, etc."
- LangString TEXT_IO_TITLE ${LANG_ENGLISH} "Specify User Data Location"
-;--------------------------------
-;Data
-
-Caption "Blender [VERSION] Installer"
-OutFile "[DISTDIR]\..\blender-[VERSION]-windows[BITNESS].exe"
-;InstallDir "$PROGRAMFILES[BITNESS]\Blender Foundation\Blender"
-; Install to user profile dir. While it is non-standard, it allows
-; users to install without having to have the installer run in elevated mode.
-InstallDir "$PROFILE\Blender Foundation\Blender"
-
-BrandingText "Blender Foundation | http://www.blender.org"
-ComponentText "This will install Blender [VERSION] on your computer."
-
-DirText "Use the field below to specify the folder where you want Blender to be copied to. To specify a different folder, type a new name or use the Browse button to select an existing folder."
-
-SilentUnInstall normal
-
-Var BLENDERHOME
-Var SHORTVERSION ; This is blender_version_decimal() from path_util.c
-
-; custom controls
-Var HWND
-
-Var HWND_APPDATA
-Var HWND_INSTDIR
-Var HWND_HOMEDIR
-
-Function .onInit
- ClearErrors
- StrCpy $SHORTVERSION "[SHORTVERSION]"
-FunctionEnd
-
-Function DataLocation
- nsDialogs::Create /NOUNLOAD 1018
- Pop $HWND
-
- ${If} $HWND == error
- Abort
- ${EndIf}
-
- ${NSD_CreateLabel} 0 0 100% 12u "Please specify where you wish to install Blender's user data files."
- ${NSD_CreateRadioButton} 0 20 100% 12u "Use the Application Data directory"
- Pop $HWND_APPDATA
- ${NSD_CreateRadioButton} 0 50 100% 12u "Use the installation directory (ie. location chosen to install blender.exe)."
- Pop $HWND_INSTDIR
- ${NSD_CreateRadioButton} 0 80 100% 12u "I have defined a %HOME% variable, please install files here."
- Pop $HWND_HOMEDIR
-
- ${If} ${AtMostWinME}
- GetDlgItem $0 $HWND $HWND_APPDATA
- EnableWindow $0 0
- SendMessage $HWND_INSTDIR ${BM_SETCHECK} 1 0
- ${Else}
- SendMessage $HWND_APPDATA ${BM_SETCHECK} 1 0
- ${EndIf}
-
- nsDialogs::Show
-
-FunctionEnd
-
-Function DataLocationOnLeave
- ${NSD_GetState} $HWND_APPDATA $R0
- ${If} $R0 == "1"
- StrCpy $BLENDERHOME "$APPDATA\Blender Foundation\Blender"
- ${Else}
- ${NSD_GetState} $HWND_INSTDIR $R0
- ${If} $R0 == "1"
- StrCpy $BLENDERHOME $INSTDIR
- ${Else}
- ${NSD_GetState} $HWND_HOMEDIR $R0
- ${If} $R0 == "1"
- ReadEnvStr $BLENDERHOME "HOME"
- ${EndIf}
- ${EndIf}
- ${EndIf}
-FunctionEnd
-
-Section "Blender-[VERSION] (required)" SecCopyUI
- SectionIn RO
-
- ; Set output path to the installation directory.
- SetOutPath $INSTDIR
- ; the contents of Blender installation root dir
- [ROOTDIRCONTS]
-
- ; all datafiles (python, scripts, config)
- [DODATAFILES]
-
- SetOutPath $INSTDIR
- ${If} ${RunningX64}
- SetRegView 64
- ${EndIf}
- ; Write the installation path into the registry
- WriteRegStr HKLM "SOFTWARE\BlenderFoundation" "Install_Dir" "$INSTDIR"
- WriteRegStr HKLM "SOFTWARE\BlenderFoundation" "ConfigData_Dir" "$BLENDERHOME"
- WriteRegStr HKLM "SOFTWARE\BlenderFoundation" "ShortVersion" "[SHORTVERSION]"
- ; Write the uninstall keys for Windows
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Blender" "DisplayName" "Blender (remove only)"
- WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Blender" "UninstallString" '"$INSTDIR\uninstall.exe"'
- WriteUninstaller "uninstall.exe"
-
-SectionEnd
-
-Section "Add Start Menu shortcuts" Section2
- SetShellVarContext all
- CreateDirectory "$SMPROGRAMS\Blender Foundation\Blender\"
- CreateShortCut "$SMPROGRAMS\Blender Foundation\Blender\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
- CreateShortCut "$SMPROGRAMS\Blender Foundation\Blender\Blender.lnk" "$INSTDIR\Blender.exe" "" "$INSTDIR\blender.exe" 0
- CreateShortCut "$SMPROGRAMS\Blender Foundation\Blender\Readme.lnk" "$INSTDIR\readme.html" "" "" 0
- CreateShortCut "$SMPROGRAMS\Blender Foundation\Blender\Copyright.lnk" "$INSTDIR\Copyright.txt" "" "$INSTDIR\copyright.txt" 0
- CreateShortCut "$SMPROGRAMS\Blender Foundation\Blender\GPL-license.lnk" "$INSTDIR\GPL-license.txt" "" "$INSTDIR\GPL-license.txt" 0
-SectionEnd
-
-Section "Add Desktop Blender-[VERSION] shortcut" Section3
- CreateShortCut "$DESKTOP\Blender.lnk" "$INSTDIR\blender.exe" "" "$INSTDIR\blender.exe" 0
-SectionEnd
-
-Section "Open .blend files with Blender-[VERSION]" Section4
-
- ${If} ${RunningX64}
- SetRegView 64
- ${EndIf}
- WriteRegStr HKCR ".blend" "" "blendfile"
- WriteRegStr HKCR "blendfile" "" "Blender .blend File"
- WriteRegStr HKCR "blendfile\shell" "" "open"
- WriteRegStr HKCR "blendfile\DefaultIcon" "" $INSTDIR\blender.exe,1
- WriteRegStr HKCR "blendfile\shell\open\command" "" \
- '"$INSTDIR\blender.exe" "%1"'
-
-SectionEnd
-
-UninstallText "This will uninstall Blender [VERSION], and all installed files. Before continuing make sure you have created backup of all the files you may want to keep: startup.blend, bookmarks.txt, recent-files.txt. Hit next to continue."
-
-Section "Uninstall"
- ; remove registry keys
- ${If} ${RunningX64}
- SetRegView 64
- ${EndIf}
- ReadRegStr $BLENDERHOME HKLM "SOFTWARE\BlenderFoundation" "ConfigData_Dir"
- ReadRegStr $SHORTVERSION HKLM "SOFTWARE\BlenderFoundation" "ShortVersion"
- DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Blender"
- DeleteRegKey HKLM "SOFTWARE\BlenderFoundation"
- SetShellVarContext all
-
- ; remove files
- [DELROOTDIRCONTS]
-
- ; remove bundled python
- RmDir /r $INSTDIR\$SHORTVERSION\python
-
- Delete "$INSTDIR\uninstall.exe"
-
- MessageBox MB_YESNO "Recursively erase contents of $BLENDERHOME\$SHORTVERSION\scripts? NOTE: This includes all installed scripts and *any* file and directory you have manually created, installed later or copied. This also including .blend files." IDNO NextNoScriptRemove
- RMDir /r "$BLENDERHOME\$SHORTVERSION\scripts"
-NextNoScriptRemove:
- MessageBox MB_YESNO "Recursively erase contents from $BLENDERHOME\$SHORTVERSION\config? NOTE: This includes your startup.blend, bookmarks and any other file and directory you may have created in that directory" IDNO NextNoConfigRemove
- RMDir /r "$BLENDERHOME\$SHORTVERSION\config"
-NextNoConfigRemove:
- MessageBox MB_YESNO "Recursively erase contents from $BLENDERHOME\$SHORTVERSION\plugins? NOTE: This includes files and subdirectories in this directory" IDNO NextNoPluginRemove
- RMDir /r "$BLENDERHOME\$SHORTVERSION\plugins"
-NextNoPluginRemove:
- ; try to remove dirs, but leave them if they contain anything
- RMDir "$BLENDERHOME\$SHORTVERSION\plugins"
- RMDir "$BLENDERHOME\$SHORTVERSION\config"
- RMDir "$BLENDERHOME\$SHORTVERSION\scripts"
- RMDir "$BLENDERHOME\$SHORTVERSION"
- RMDir "$BLENDERHOME"
- ; remove shortcuts
- Delete "$SMPROGRAMS\Blender Foundation\Blender\*.*"
- Delete "$DESKTOP\Blender.lnk"
- ; remove all link related directories and files
- RMDir "$SMPROGRAMS\Blender Foundation\Blender"
- RMDir "$SMPROGRAMS\Blender Foundation"
- ; Clear out installation dir
- RMDir "$INSTDIR"
-SectionEnd
-
-!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
- !insertmacro MUI_DESCRIPTION_TEXT ${SecCopyUI} $(DESC_SecCopyUI)
- !insertmacro MUI_DESCRIPTION_TEXT ${Section2} $(DESC_Section2)
- !insertmacro MUI_DESCRIPTION_TEXT ${Section3} $(DESC_Section3)
- !insertmacro MUI_DESCRIPTION_TEXT ${Section4} $(DESC_Section4)
-!insertmacro MUI_FUNCTION_DESCRIPTION_END
-
+;
+; $Id$
+;
+; Blender Self-Installer for Windows (NSIS - http://nsis.sourceforge.net)
+;
+
+SetCompressor /SOLID lzma
+
+Name "Blender [VERSION]"
+
+RequestExecutionLevel admin
+
+!include "MUI.nsh"
+!include "WinVer.nsh"
+!include "FileFunc.nsh"
+!include "WordFunc.nsh"
+!include "nsDialogs.nsh"
+!include "x64.nsh"
+
+!define MUI_ABORTWARNING
+
+!define MUI_WELCOMEPAGE_TEXT "This wizard will guide you through the installation of Blender. It is recommended that you close all other applications before starting Setup."
+!define MUI_WELCOMEFINISHPAGE_BITMAP "[RELDIR]\01.installer.bmp"
+!define MUI_HEADERIMAGE
+!define MUI_HEADERIMAGE_BITMAP "[RELDIR]\00.header.bmp"
+!define MUI_COMPONENTSPAGE_SMALLDESC
+!define MUI_FINISHPAGE_RUN "$INSTDIR\blender.exe"
+!define MUI_CHECKBITMAP "[RELDIR]\00.checked.bmp"
+!define MUI_UNWELCOMEFINISHPAGE_BITMAP "[RELDIR]\01.installer.bmp"
+
+!insertmacro MUI_PAGE_WELCOME
+!insertmacro MUI_PAGE_LICENSE "[DISTDIR]\Copyright.txt"
+!insertmacro MUI_PAGE_COMPONENTS
+
+!insertmacro MUI_PAGE_DIRECTORY
+Page custom DataLocation DataLocationOnLeave
+!insertmacro MUI_PAGE_INSTFILES
+!insertmacro MUI_PAGE_FINISH
+
+!insertmacro MUI_UNPAGE_WELCOME
+!insertmacro MUI_UNPAGE_CONFIRM
+!insertmacro MUI_UNPAGE_INSTFILES
+!insertmacro MUI_UNPAGE_FINISH
+
+!insertmacro Locate
+!insertmacro VersionCompare
+
+
+Icon "[RELDIR]\00.installer.ico"
+UninstallIcon "[RELDIR]\00.installer.ico"
+
+;--------------------------------
+;Languages
+
+ !insertmacro MUI_LANGUAGE "English"
+
+;--------------------------------
+;Language Strings
+
+ ;Description
+ LangString DESC_InstallFiles ${LANG_ENGLISH} "Copy all required files to the application folder."
+ LangString DESC_StartMenu ${LANG_ENGLISH} "Add shortcut items to the Start Menu. (Recommended)"
+ LangString DESC_DesktopShortcut ${LANG_ENGLISH} "Add a shortcut to Blender on your desktop."
+ LangString DESC_BlendRegister ${LANG_ENGLISH} "Blender can register itself with .blend files to allow double-clicking from Windows Explorer, etc."
+ LangString TEXT_IO_TITLE ${LANG_ENGLISH} "Specify User Data Location"
+;--------------------------------
+;Data
+
+Caption "Blender [VERSION] Installer"
+OutFile "[DISTDIR]\..\blender-[VERSION]-windows[BITNESS].exe"
+InstallDir $INSTDIR ; $INSTDIR is set inside .onInit
+BrandingText "Blender Foundation | http://www.blender.org"
+ComponentText "This will install Blender [VERSION] on your computer."
+
+DirText "Use the field below to specify the folder where you want Blender to be copied to. To specify a different folder, type a new name or use the Browse button to select an existing folder."
+
+SilentUnInstall normal
+
+Var BLENDERHOME
+Var SHORTVERSION ; This is blender_version_decimal() from path_util.c
+
+; Custom controls
+Var HWND
+
+Var HWND_APPDATA
+Var HWND_INSTDIR
+Var HWND_HOMEDIR
+
+Function .onInit
+ ClearErrors
+ StrCpy $SHORTVERSION "[SHORTVERSION]"
+
+ ${If} ${RunningX64}
+ ${If} "[BITNESS]" == "32"
+ ${OrIf} "[BITNESS]" == "-mingw"
+ StrCpy $INSTDIR "$PROGRAMFILES32\Blender Foundation\Blender" ; Can't use InstallDir inside Section
+ ${ElseIf} "[BITNESS]" == "64"
+ StrCpy $INSTDIR "$PROGRAMFILES64\Blender Foundation\Blender"
+ ${EndIf}
+ ${Else}
+ StrCpy $INSTDIR "$PROGRAMFILES\Blender Foundation\Blender"
+ ${EndIf}
+FunctionEnd
+
+Function un.onInit
+FunctionEnd
+
+Function DataLocation
+ nsDialogs::Create /NOUNLOAD 1018
+ Pop $HWND
+
+ ${If} $HWND == error
+ Abort
+ ${EndIf}
+
+ ${NSD_CreateLabel} 0 0 100% 24u "Please specify where you wish to install Blender's user data files. Be aware that if you choose to use your Application Data directory, your preferences and scripts will only be accessible by the current user account."
+ ${NSD_CreateRadioButton} 0 50 100% 12u "Use Application Data directory (recommended)"
+ Pop $HWND_APPDATA
+ ${NSD_CreateRadioButton} 0 80 100% 12u "Use installation directory"
+ Pop $HWND_INSTDIR
+ ${NSD_CreateRadioButton} 0 110 100% 12u "I have defined a %HOME% variable, please install files there"
+ Pop $HWND_HOMEDIR
+
+ ${If} ${AtMostWinME}
+ GetDlgItem $0 $HWND $HWND_APPDATA
+ EnableWindow $0 0
+ SendMessage $HWND_INSTDIR ${BM_SETCHECK} 1 0
+ ${Else}
+ SendMessage $HWND_APPDATA ${BM_SETCHECK} 1 0
+ ${EndIf}
+
+ nsDialogs::Show
+
+FunctionEnd
+
+Function DataLocationOnLeave
+ ${NSD_GetState} $HWND_APPDATA $R0
+ ${If} $R0 == "1"
+ SetShellVarContext current
+ StrCpy $BLENDERHOME "$APPDATA\Blender Foundation\Blender"
+ SetShellVarContext all
+ ${Else}
+ ${NSD_GetState} $HWND_INSTDIR $R0
+ ${If} $R0 == "1"
+ StrCpy $BLENDERHOME $INSTDIR
+ ${Else}
+ ${NSD_GetState} $HWND_HOMEDIR $R0
+ ${If} $R0 == "1"
+ ReadEnvStr $BLENDERHOME "HOME"
+ ${EndIf}
+ ${EndIf}
+ ${EndIf}
+FunctionEnd
+
+Section "Blender [VERSION] (required)" InstallFiles
+ SectionIn RO
+
+ ; Set output path to the installation directory.
+ SetOutPath $INSTDIR
+ ; The contents of Blender installation root dir
+ [ROOTDIRCONTS]
+
+ ; All datafiles (python, scripts, config)
+ [DODATAFILES]
+
+ SetOutPath $INSTDIR
+ ${If} ${RunningX64}
+ SetRegView 64
+ ${EndIf}
+ ; Write the installation path into the registry
+ WriteRegStr HKLM "SOFTWARE\BlenderFoundation" "Install_Dir" "$INSTDIR"
+ WriteRegStr HKLM "SOFTWARE\BlenderFoundation" "ConfigData_Dir" "$BLENDERHOME"
+ WriteRegStr HKLM "SOFTWARE\BlenderFoundation" "ShortVersion" "[SHORTVERSION]"
+ ; Write the uninstall keys for Windows
+ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Blender" "DisplayName" "Blender"
+ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Blender" "Publisher" "Blender Foundation"
+ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Blender" "URLInfoAbout" "http://www.blender.org/"
+ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Blender" "DisplayVersion" "[VERSION]"
+ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Blender" "DisplayIcon" "$INSTDIR\blender.exe"
+ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Blender" "UninstallString" '"$INSTDIR\uninstall.exe"'
+ WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Blender" "NoModify" 1
+ WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Blender" "NoRepair " 1
+ WriteUninstaller "uninstall.exe"
+
+SectionEnd
+
+Section "Add Start Menu Shortcuts" StartMenu
+ SetShellVarContext all
+ CreateDirectory "$SMPROGRAMS\Blender Foundation\Blender\"
+ CreateShortCut "$SMPROGRAMS\Blender Foundation\Blender\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
+ CreateShortCut "$SMPROGRAMS\Blender Foundation\Blender\Blender.lnk" "$INSTDIR\Blender.exe" "" "$INSTDIR\blender.exe" 0
+ CreateShortCut "$SMPROGRAMS\Blender Foundation\Blender\Readme.lnk" "$INSTDIR\readme.html" "" "" 0
+ CreateShortCut "$SMPROGRAMS\Blender Foundation\Blender\Copyright.lnk" "$INSTDIR\Copyright.txt" "" "$INSTDIR\copyright.txt" 0
+ CreateShortCut "$SMPROGRAMS\Blender Foundation\Blender\GPL-license.lnk" "$INSTDIR\GPL-license.txt" "" "$INSTDIR\GPL-license.txt" 0
+ System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)' ; refresh icons
+SectionEnd
+
+Section "Add Desktop Shortcut" DesktopShortcut
+ CreateShortCut "$DESKTOP\Blender.lnk" "$INSTDIR\blender.exe" "" "$INSTDIR\blender.exe" 0
+ System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)' ; refresh icons
+SectionEnd
+
+Section "Open .blend files with Blender" BlendRegister
+ ExecWait '"$INSTDIR\blender.exe" -r'
+SectionEnd
+
+UninstallText "This will uninstall Blender [VERSION], and all installed files. Before continuing make sure you have created backup of all the files you may want to keep: startup.blend, bookmarks.txt, recent-files.txt. Hit 'Uninstall' to continue."
+
+Section "Uninstall"
+ ; Remove registry keys
+ ${If} ${RunningX64}
+ SetRegView 64
+ ${EndIf}
+
+ ReadRegStr $BLENDERHOME HKLM "SOFTWARE\BlenderFoundation" "ConfigData_Dir"
+ ReadRegStr $SHORTVERSION HKLM "SOFTWARE\BlenderFoundation" "ShortVersion"
+ DeleteRegKey HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Blender"
+ DeleteRegKey HKLM "SOFTWARE\BlenderFoundation"
+ DeleteRegKey HKCR ".blend"
+ DeleteRegKey HKCR "blendfile"
+ DeleteRegKey HKCR "CLSID\{D45F043D-F17F-4e8a-8435-70971D9FA46D}"
+ SetShellVarContext all
+
+ ; Remove files
+ [DELROOTDIRCONTS]
+
+ Delete "$INSTDIR\uninstall.exe"
+
+ MessageBox MB_YESNO "Recursively erase contents of $BLENDERHOME\$SHORTVERSION\scripts? NOTE: This includes all installed scripts and *any* file and directory you have manually created, installed later or copied. This also including .blend files." IDNO NextNoScriptRemove
+ RMDir /r "$BLENDERHOME\$SHORTVERSION\scripts"
+NextNoScriptRemove:
+ MessageBox MB_YESNO "Recursively erase contents from $BLENDERHOME\$SHORTVERSION\config? NOTE: This includes your startup.blend, bookmarks and any other file and directory you may have created in that directory" IDNO NextNoConfigRemove
+ RMDir /r "$BLENDERHOME\$SHORTVERSION\config"
+NextNoConfigRemove:
+ MessageBox MB_YESNO "Recursively erase contents from $BLENDERHOME\$SHORTVERSION\plugins? NOTE: This includes files and subdirectories in this directory" IDNO NextNoPluginRemove
+ RMDir /r "$BLENDERHOME\$SHORTVERSION\plugins"
+NextNoPluginRemove:
+ ; Try to remove dirs, but leave them if they contain anything
+ RMDir "$BLENDERHOME\$SHORTVERSION\plugins"
+ RMDir "$BLENDERHOME\$SHORTVERSION\config"
+ RMDir "$BLENDERHOME\$SHORTVERSION\scripts"
+ RMDir "$BLENDERHOME\$SHORTVERSION"
+ RMDir "$BLENDERHOME"
+ ; Remove shortcuts
+ Delete "$SMPROGRAMS\Blender Foundation\Blender\*.*"
+ Delete "$DESKTOP\Blender.lnk"
+ ; Remove all link related directories and files
+ RMDir /r "$SMPROGRAMS\Blender Foundation"
+ ; Clear out installation dir
+ RMDir /r "$INSTDIR"
+
+ System::Call 'shell32.dll::SHChangeNotify(i, i, i, i) v (0x08000000, 0, 0, 0)' ; Refresh icons
+SectionEnd
+
+!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+ !insertmacro MUI_DESCRIPTION_TEXT ${InstallFiles} $(DESC_InstallFiles)
+ !insertmacro MUI_DESCRIPTION_TEXT ${StartMenu} $(DESC_StartMenu)
+ !insertmacro MUI_DESCRIPTION_TEXT ${DesktopShortcut} $(DESC_DesktopShortcut)
+ !insertmacro MUI_DESCRIPTION_TEXT ${BlendRegister} $(DESC_BlendRegister)
+!insertmacro MUI_FUNCTION_DESCRIPTION_END
+