synched with trunk at revision 34793
authorNick Samarin <nicks1987@bigmir.net>
Wed, 16 Feb 2011 16:56:11 +0000 (16:56 +0000)
committerNick Samarin <nicks1987@bigmir.net>
Wed, 16 Feb 2011 16:56:11 +0000 (16:56 +0000)
198 files changed:
release/Makefile [deleted file]
release/VERSION
release/bin/blender-thumbnailer.py
release/datafiles/blenderbuttons
release/datafiles/ctodata.py [new file with mode: 0644]
release/datafiles/datatoc.py
release/datafiles/prvicons
release/datafiles/splash.png
release/freedesktop/icons/16x16/blender.png
release/freedesktop/icons/16x16/blender.svg [new file with mode: 0644]
release/freedesktop/icons/16x16/blender.xcf.bz2 [deleted file]
release/freedesktop/icons/22x22/blender.png
release/freedesktop/icons/22x22/blender.svg [new file with mode: 0644]
release/freedesktop/icons/22x22/blender.xcf.bz2 [deleted file]
release/freedesktop/icons/32x32/blender.png
release/freedesktop/icons/32x32/blender.svg
release/getversion.py [deleted file]
release/plugins/sequence/color-correction-hsv.c
release/plugins/sequence/color-correction-yuv.c
release/scripts/io/netrender/__init__.py
release/scripts/io/netrender/balancing.py
release/scripts/io/netrender/client.py
release/scripts/io/netrender/master.py
release/scripts/io/netrender/master_html.py
release/scripts/io/netrender/model.py
release/scripts/io/netrender/netrender.js
release/scripts/io/netrender/operators.py
release/scripts/io/netrender/slave.py
release/scripts/io/netrender/thumbnail.py [new file with mode: 0644]
release/scripts/io/netrender/ui.py
release/scripts/io/netrender/utils.py
release/scripts/io/netrender/versioning.py [new file with mode: 0644]
release/scripts/keyingsets/keyingsets_builtins.py
release/scripts/modules/add_object_utils.py
release/scripts/modules/animsys_refactor.py
release/scripts/modules/bpy/__init__.py
release/scripts/modules/bpy/ops.py
release/scripts/modules/bpy/path.py
release/scripts/modules/bpy/utils.py
release/scripts/modules/bpy_types.py
release/scripts/modules/console/__init__.py
release/scripts/modules/console/complete_calltip.py
release/scripts/modules/console/complete_import.py
release/scripts/modules/console/complete_namespace.py
release/scripts/modules/console/intellisense.py
release/scripts/modules/image_utils.py [new file with mode: 0644]
release/scripts/modules/io_utils.py
release/scripts/modules/keyingsets_utils.py [moved from release/scripts/keyingsets/keyingsets_utils.py with 63% similarity]
release/scripts/modules/rigify/__init__.py [deleted file]
release/scripts/modules/rigify/arm_biped.py [deleted file]
release/scripts/modules/rigify/copy.py [deleted file]
release/scripts/modules/rigify/delta.py [deleted file]
release/scripts/modules/rigify/eye_balls.py [deleted file]
release/scripts/modules/rigify/eye_lid.py [deleted file]
release/scripts/modules/rigify/finger_curl.py [deleted file]
release/scripts/modules/rigify/leg_biped.py [deleted file]
release/scripts/modules/rigify/leg_quadruped.py [deleted file]
release/scripts/modules/rigify/mouth.py [deleted file]
release/scripts/modules/rigify/neck.py [deleted file]
release/scripts/modules/rigify/neck_flex.py [deleted file]
release/scripts/modules/rigify/palm_curl.py [deleted file]
release/scripts/modules/rigify/shape_key_control.py [deleted file]
release/scripts/modules/rigify/shape_key_distance.py [deleted file]
release/scripts/modules/rigify/shape_key_rotdiff.py [deleted file]
release/scripts/modules/rigify/spine_pivot_flex.py [deleted file]
release/scripts/modules/rigify/stretch.py [deleted file]
release/scripts/modules/rigify/stretch_twist.py [deleted file]
release/scripts/modules/rigify/tail_control.py [deleted file]
release/scripts/modules/rigify/tongue.py [deleted file]
release/scripts/modules/rigify/track_dual.py [deleted file]
release/scripts/modules/rigify/track_reverse.py [deleted file]
release/scripts/modules/rigify_utils.py [deleted file]
release/scripts/modules/rna_info.py
release/scripts/modules/rna_prop_ui.py
release/scripts/modules/sys_info.py [new file with mode: 0644]
release/scripts/op/add_armature_human.py [deleted file]
release/scripts/op/add_mesh_torus.py
release/scripts/op/animsys_update.py
release/scripts/op/console_python.py
release/scripts/op/fcurve_euler_filter.py
release/scripts/op/image.py
release/scripts/op/io_anim_bvh/__init__.py [deleted file]
release/scripts/op/io_anim_bvh/import_bvh.py [deleted file]
release/scripts/op/io_mesh_ply/__init__.py [deleted file]
release/scripts/op/io_mesh_ply/export_ply.py [deleted file]
release/scripts/op/io_scene_3ds/__init__.py [deleted file]
release/scripts/op/io_scene_3ds/export_3ds.py [deleted file]
release/scripts/op/io_scene_3ds/import_3ds.py [deleted file]
release/scripts/op/io_scene_fbx/__init__.py [deleted file]
release/scripts/op/io_scene_fbx/export_fbx.py [deleted file]
release/scripts/op/io_scene_obj/__init__.py [deleted file]
release/scripts/op/io_scene_obj/export_obj.py [deleted file]
release/scripts/op/io_scene_obj/import_obj.py [deleted file]
release/scripts/op/io_scene_x3d/__init__.py [deleted file]
release/scripts/op/io_scene_x3d/export_x3d.py [deleted file]
release/scripts/op/io_shape_mdd/__init__.py [deleted file]
release/scripts/op/io_shape_mdd/export_mdd.py [deleted file]
release/scripts/op/io_shape_mdd/import_mdd.py [deleted file]
release/scripts/op/mesh.py
release/scripts/op/nla.py
release/scripts/op/object.py
release/scripts/op/object_align.py
release/scripts/op/object_randomize_transform.py
release/scripts/op/presets.py
release/scripts/op/screen_play_rendered_anim.py
release/scripts/op/sequencer.py
release/scripts/op/uv.py
release/scripts/op/uvcalc_follow_active.py
release/scripts/op/uvcalc_smart_project.py
release/scripts/op/vertexpaint_dirt.py
release/scripts/op/wm.py
release/scripts/presets/ffmpeg/DV.py
release/scripts/presets/ffmpeg/DVD.py
release/scripts/presets/ffmpeg/SVCD.py
release/scripts/presets/ffmpeg/VCD.py
release/scripts/presets/ffmpeg/h264.py
release/scripts/presets/ffmpeg/theora.py
release/scripts/presets/ffmpeg/xvid.py
release/scripts/presets/keyconfig/maya.py [moved from release/scripts/presets/interaction/maya.py with 99% similarity]
release/scripts/presets/render/HDV_1080p.py
release/scripts/presets/render/HDV_NTSC_1080p.py [new file with mode: 0644]
release/scripts/presets/render/HDV_PAL_1080p.py [new file with mode: 0644]
release/scripts/presets/sss/apple.py
release/scripts/presets/sss/chicken.py
release/scripts/presets/sss/cream.py
release/scripts/presets/sss/ketchup.py
release/scripts/presets/sss/marble.py
release/scripts/presets/sss/potato.py
release/scripts/presets/sss/skim_milk.py
release/scripts/presets/sss/skin1.py
release/scripts/presets/sss/skin2.py
release/scripts/presets/sss/whole_milk.py
release/scripts/templates/addon_add_object.py [new file with mode: 0644]
release/scripts/templates/background_job.py [new file with mode: 0644]
release/scripts/templates/builtin_keyingset.py [new file with mode: 0644]
release/scripts/templates/gamelogic.py
release/scripts/templates/gamelogic_basic.py
release/scripts/templates/gamelogic_module.py
release/scripts/templates/operator.py [deleted file]
release/scripts/templates/operator_export.py [new file with mode: 0644]
release/scripts/templates/operator_mesh_add.py [new file with mode: 0644]
release/scripts/templates/operator_modal.py
release/scripts/templates/operator_modal_draw.py
release/scripts/templates/operator_modal_view3d.py
release/scripts/templates/operator_simple.py
release/scripts/templates/operator_uv.py
release/scripts/templates/panel_simple.py
release/scripts/ui/properties_animviz.py
release/scripts/ui/properties_data_armature.py
release/scripts/ui/properties_data_armature_rigify.py [deleted file]
release/scripts/ui/properties_data_bone.py
release/scripts/ui/properties_data_camera.py
release/scripts/ui/properties_data_curve.py
release/scripts/ui/properties_data_empty.py
release/scripts/ui/properties_data_lamp.py
release/scripts/ui/properties_data_lattice.py
release/scripts/ui/properties_data_mesh.py
release/scripts/ui/properties_data_metaball.py
release/scripts/ui/properties_data_modifier.py
release/scripts/ui/properties_game.py
release/scripts/ui/properties_material.py
release/scripts/ui/properties_object.py
release/scripts/ui/properties_object_constraint.py
release/scripts/ui/properties_particle.py
release/scripts/ui/properties_physics_cloth.py
release/scripts/ui/properties_physics_common.py
release/scripts/ui/properties_physics_field.py
release/scripts/ui/properties_physics_fluid.py
release/scripts/ui/properties_physics_smoke.py
release/scripts/ui/properties_physics_softbody.py
release/scripts/ui/properties_render.py
release/scripts/ui/properties_scene.py
release/scripts/ui/properties_texture.py
release/scripts/ui/properties_world.py
release/scripts/ui/space_console.py
release/scripts/ui/space_dopesheet.py
release/scripts/ui/space_filebrowser.py
release/scripts/ui/space_graph.py
release/scripts/ui/space_image.py
release/scripts/ui/space_info.py
release/scripts/ui/space_logic.py
release/scripts/ui/space_nla.py
release/scripts/ui/space_node.py
release/scripts/ui/space_outliner.py
release/scripts/ui/space_sequencer.py
release/scripts/ui/space_text.py
release/scripts/ui/space_time.py
release/scripts/ui/space_userpref.py
release/scripts/ui/space_userpref_keymap.py
release/scripts/ui/space_view3d.py
release/scripts/ui/space_view3d_toolbar.py
release/test/pep8.py [deleted file]
release/test/rna_array.py [deleted file]
release/test/rna_info_dump.py [deleted file]
release/text/readme.html
release/windows/extra/Help.url [deleted file]
release/windows/installer/00.sconsblender.nsi
release/windows/specific.sh [deleted file]

diff --git a/release/Makefile b/release/Makefile
deleted file mode 100644 (file)
index bef76b3..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-# -*- mode: gnumakefile; tab-width: 8; indent-tabs-mode: t; -*-
-# vim: tabstop=8
-# $Id$
-#
-# ***** 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.
-#
-# The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
-# All rights reserved.
-#
-# The Original Code is: all of this file.
-#
-# Contributor(s): none yet.
-#
-# ***** END GPL LICENSE BLOCK *****
-
-include nan_definitions.mk
-
-export VERSION := $(shell ./getversion.py)
-
-BLENDNAME=blender-$(VERSION)-$(CONFIG_GUESS)-py$(NAN_PYTHON_VERSION)$(TYPE)
-export DISTDIR=$(NAN_OBJDIR)/$(BLENDNAME)
-export CONFDIR=$(DISTDIR)/.blender
-
-ifeq ($(OS),$(findstring $(OS), "freebsd irix linux openbsd solaris"))
-   TAR="tar"
-   TARFLAGS="cf"
-   EXT0=""
-   EXT1=".tar"
-   COMPRESS="bzip2"
-   COMPRESSFLAGS="-f"
-   EXT2=".bz2"
-   ifeq ($(OS), solaris)
-     ifeq ($(CPU), i386)
-       NOPLUGINS?=true
-     endif
-   endif
-   # don"t build plugins on irix if using gcc
-   ifeq ($(OS), irix)
-     ifeq ($(IRIX_USE_GCC), true)
-       NOPLUGINS?=true
-     endif
-   endif
-endif
-
-ifeq ($(OS),windows)
-   TAR="zip"
-   TARFLAGS="-r9"
-   EXT0=".exe"
-   EXT1=".zip"
-   NOPLUGINS?=true
-   NOSTRIP?=true
-endif
-
-ifeq ($(OS),darwin)
-   TAR="tar"
-   TARFLAGS="cf"
-   EXT0=".app"
-   EXT1=".tar"
-   COMPRESS="bzip2"
-   COMPRESSFLAGS="-f"
-   EXT2=".bz2"
-endif
-
-release: all
-
-all:
-       @$(MAKE) pkg TYPE=""
-ifeq ($(WITH_BF_STATICOPENGL), true)
-       @$(MAKE) pkg TYPE="-static" 
-endif
-
-# OS independent targets below:
-
-dist: all
-
-package: version makedirs
-
-install: package
-       @#echo "****> Install text"
-       @cp text/readme.html $(DISTDIR)
-       @cp text/*.txt $(DISTDIR)
-    ifeq ($(FREEDESKTOP), true)
-       @#echo "****> Install freedesktop icons"
-       @mkdir $(DISTDIR)/icons
-       @mkdir $(DISTDIR)/icons/16x16
-       @cp freedesktop/icons/16x16/blender.png $(DISTDIR)/icons/16x16
-       @mkdir $(DISTDIR)/icons/22x22
-       @cp freedesktop/icons/22x22/blender.png $(DISTDIR)/icons/22x22
-       @mkdir $(DISTDIR)/icons/32x32
-       @cp freedesktop/icons/32x32/blender.png $(DISTDIR)/icons/32x32
-       @mkdir $(DISTDIR)/icons/scalable
-       @cp freedesktop/icons/scalable/blender.svg $(DISTDIR)/icons/scalable
-    endif
-       @echo "----> Make Config dir .blender"
-       @mkdir -p $(CONFDIR)
-       @# possible overruling .txt text documents
-       @[ ! -d $(CONFIG_GUESS)/text ] || \
-           cp -f $(CONFIG_GUESS)/text/*.txt $(DISTDIR)
-#on OS X the contents of the .blender dir is already inside the bundle
-    ifneq ($(OS), darwin)
-       @[ ! -d $(OCGDIR)/bin/.blender ] || \
-               cp -r $(OCGDIR)/bin/.blender $(DISTDIR)
-       @cp $(NANBLENDERHOME)/release/bin/.blender/.Blanguages $(CONFDIR)
-       @cp $(NANBLENDERHOME)/release/bin/.blender/.bfont.ttf $(CONFDIR)
-    endif
-       @echo "----> Copy blender$(EXT0) executable"
-    ifeq ($(TYPE),-static)
-       @cp $(OCGDIR)/bin/blenderstatic$(EXT0) $(DISTDIR)/blender$(EXT0)
-    else
-    ifeq ($(OS),darwin)
-       @cp -r $(OCGDIR)/bin/blender$(EXT0) $(DISTDIR)/Blender$(EXT0)
-    else
-       @cp $(OCGDIR)/bin/blender$(EXT0) $(DISTDIR)/blender$(EXT0)
-    endif
-       @if [ -f $(OCGDIR)/bin/blenderplayer$(EXTO) ]; then \
-               cp $(OCGDIR)/bin/blenderplayer$(EXTO) \
-                       $(DISTDIR)/blenderplayer$(EXTO) ; \
-       fi
-    endif
-
-ifneq ($(NOPLUGINS),true)
-       @echo "----> Copy and compile plugins"
-       @cp -r plugins $(DISTDIR)/plugins
-       @mkdir -p $(DISTDIR)/plugins/include
-       @cp ../source/blender/blenpluginapi/*.h $(DISTDIR)/plugins/include/
-       @chmod 755 $(DISTDIR)/plugins/bmake
-       @$(MAKE) -C $(DISTDIR)/plugins all  > /dev/null || exit 1;
-       @rm -f $(DISTDIR)/plugins/*/*.o
-
-#on OS X the plugins move to the installation directory
-    ifneq ($(OS),darwin)
-       @mkdir -p $(CONFDIR)/plugins/sequence
-       @mkdir -p $(CONFDIR)/plugins/texture
-       @mv $(DISTDIR)/plugins/sequence/*.so $(CONFDIR)/plugins/sequence
-       @mv $(DISTDIR)/plugins/texture/*.so $(CONFDIR)/plugins/texture
-    endif
-endif
-
-       @echo "----> Copy python infrastructure"
-       @[ ! -d scripts ] || cp -r scripts $(CONFDIR)/scripts
-       
-    ifeq ($(OS),darwin)
-       @echo "----> Copy python modules"
-       @mkdir $(CONFDIR)/python/
-       @unzip -q $(LCGDIR)/release/python.zip -d $(CONFDIR)/python/    
-    endif
-
-    ifeq ($(OS),darwin)
-       @echo "----> Move .blender to .app/Contents/MacOS/"
-       @rm -fr $(DISTDIR)/blender$(EXT0)/Contents/MacOS/.blender
-       @mv $(DISTDIR)/.blender $(DISTDIR)/blender$(EXT0)/Contents/MacOS/
-    endif
-
-    ifneq ($(NOSTRIP),true)
-       @echo "----> Strip blender executable"
-      ifeq ($(OS),darwin)
-       @strip -x $(DISTDIR)/blender$(EXT0)/Contents/MacOS/blender
-      else
-       @strip -x $(DISTDIR)/blender$(EXT0)
-       @if [ -f $(DISTDIR)/blenderplayer$(EXTO) ]; then \
-           strip -x $(DISTDIR)/blenderplayer$(EXT0) ; \
-       fi
-      endif
-    endif
-       @[ ! -x $(CONFIG_GUESS)/specific.sh ] || (\
-           echo "**--> Execute specific.sh in $(CONFIG_GUESS)/" && \
-           cd $(CONFIG_GUESS) && ./specific.sh )
-       @echo "----> Cleaning .svn metadata directories"
-       @find $(DISTDIR) -type d -name ".svn" | xargs rm -fr
-
-pkg: install
-       @echo "----> Create distribution file $(BLENDNAME)$(EXT1)"
-       @#enable the next sleep if you get 'tar file changed while reading'
-       @#sleep 10
-       rm -f  $(NAN_OBJDIR)/$(VERSION)/$(BLENDNAME)$(EXT1)*
-       @cd $(NAN_OBJDIR) && $(TAR) $(TARFLAGS) $(VERSION)/$(BLENDNAME)$(EXT1) $(BLENDNAME)
-    ifdef COMPRESS
-       @echo "----> Compressing distribution to $(BLENDNAME)$(EXT1)$(EXT2)"
-       @$(COMPRESS) $(COMPRESSFLAGS) $(NAN_OBJDIR)/$(VERSION)/$(BLENDNAME)$(EXT1)
-    endif
-       @#echo "****> Clean up temporary distribution directory"
-       @#rm -fr $(DISTDIR)
-       @echo "****> $(NAN_OBJDIR)/$(VERSION)/$(BLENDNAME)$(EXT1)$(EXT2) is ready"
-
-version: FORCE
-       @echo "*---> Create $(BLENDNAME) package"
-
-makedirs: FORCE
-       @echo "****> Create package directory $(VERSION) if necessary"
-       @[ -d $(NAN_OBJDIR)/$(VERSION) ] || mkdir $(NAN_OBJDIR)/$(VERSION)
-       @echo "****> Remove and recreate temporary distribution directory"
-       @rm -fr $(DISTDIR)
-       @mkdir $(DISTDIR)
-
-FORCE:
index 6020b0f868b8f674b6d128ca9416a85eca1cf782..9a256b1d546a53ff2f78e4ff74f05dced2a5bd69 100644 (file)
@@ -1 +1 @@
-2.54-beta
+2.56a-beta
index be8705601106c04e936fd45fd1fa7b4e6ed8e02d..8b93eebdeece7c9e673756a1f2ee900028a418d6 100755 (executable)
 #
 # ##### END GPL LICENSE BLOCK #####
 
+# <pep8 compliant>
+
 """
 Thumbnailer runs with python 2.6 and 3.x.
 To run automatically with nautilus:
    gconftool --type boolean --set /desktop/gnome/thumbnailers/application@x-blender/enable true
-   gconftool --type string --set /desktop/gnome/thumbnailers/application@x-blender/command "blender-thumbnailer.py %i %o"
+   gconftool --type string --set /desktop/gnome/thumbnailers/application@x-blender/command "blender-thumbnailer.py %u %o"
 """
 
 import struct
 
+
+def open_wrapper_get():
+    """ wrap OS spesific read functionality here, fallback to 'open()'
+    """
+
+    def open_gio(path, mode):
+        g_file = gio.File(path).read()
+        g_file.orig_seek = g_file.seek
+
+        def new_seek(offset, whence=0):
+            return g_file.orig_seek(offset, [1, 0, 2][whence])
+
+        g_file.seek = new_seek
+        return g_file
+
+    try:
+        import gio
+        return open_gio
+    except ImportError:
+        return open
+
+
 def blend_extract_thumb(path):
     import os
+    open_wrapper = open_wrapper_get()
 
     # def MAKE_ID(tag): ord(tag[0])<<24 | ord(tag[1])<<16 | ord(tag[2])<<8 | ord(tag[3])
-    REND = 1145980242 # MAKE_ID(b'REND')
-    TEST = 1414743380 # MAKE_ID(b'TEST')
+    REND = 1145980242  # MAKE_ID(b'REND')
+    TEST = 1414743380  # MAKE_ID(b'TEST')
 
-    blendfile = open(path, 'rb')
+    blendfile = open_wrapper(path, 'rb')
 
     head = blendfile.read(12)
 
-    if head[0:2] == b'\x1f\x8b': # gzip magic
+    if head[0:2] == b'\x1f\x8b':  # gzip magic
         import gzip
         blendfile.close()
-        blendfile = gzip.open(path, 'rb')
+        blendfile = gzip.GzipFile('', 'rb', 0, open_wrapper(path, 'rb'))
         head = blendfile.read(12)
 
     if not head.startswith(b'BLENDER'):
         blendfile.close()
         return None, 0, 0
 
-    is_64_bit = (head[7] == b'-')
+    is_64_bit = (head[7] == b'-'[0])
 
     # true for PPC, false for X86
-    is_big_endian = (head[8] == b'V')
+    is_big_endian = (head[8] == b'V'[0])
 
     # blender pre 2.5 had no thumbs
     if head[9:11] <= b'24':
@@ -66,23 +91,22 @@ def blend_extract_thumb(path):
         if len(bhead) < sizeof_bhead:
             return None, 0, 0
 
-        code, length = struct.unpack(int_endian_pair, bhead[0:8]) # 8 == sizeof(int) * 2
+        code, length = struct.unpack(int_endian_pair, bhead[0:8])  # 8 == sizeof(int) * 2
 
         if code == REND:
             blendfile.seek(length, os.SEEK_CUR)
         else:
             break
-            
-    
+
     if code != TEST:
         return None, 0, 0
 
     try:
-        x, y = struct.unpack(int_endian_pair, blendfile.read(8)) # 8 == sizeof(int) * 2
+        x, y = struct.unpack(int_endian_pair, blendfile.read(8))  # 8 == sizeof(int) * 2
     except struct.error:
         return None, 0, 0
 
-    length -= 8 # sizeof(int) * 2
+    length -= 8  # sizeof(int) * 2
 
     if length != x * y * 4:
         return None, 0, 0
@@ -116,13 +140,13 @@ def write_png(buf, width, height):
 if __name__ == '__main__':
     import sys
 
-    if len(sys.argv) < 2:
+    if len(sys.argv) < 3:
         print("Expected 2 arguments <input.blend> <output.png>")
     else:
         file_in = sys.argv[-2]
 
         buf, width, height = blend_extract_thumb(file_in)
-        
+
         if buf:
             file_out = sys.argv[-1]
 
index b9fa75cc2540dda65beeb0290ebaee2d29568014..42e82430ca1517cd6af81ed136b1d0fbf2c9648a 100644 (file)
Binary files a/release/datafiles/blenderbuttons and b/release/datafiles/blenderbuttons differ
diff --git a/release/datafiles/ctodata.py b/release/datafiles/ctodata.py
new file mode 100644 (file)
index 0000000..be33f72
--- /dev/null
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# ***** 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.
+#
+# The Original Code is Copyright (C) 2009 Blender Foundation.
+# All rights reserved.
+#
+# Contributor(s): Campbell Barton
+#
+# ***** END GPL LICENCE BLOCK *****
+
+
+# <pep8 compliant>
+
+import sys
+import os
+
+if len(sys.argv) < 2:
+    sys.stdout.write("Usage: ctodata <c_file>\n")
+    sys.exit(1)
+
+filename = sys.argv[1]
+
+try:
+    fpin = open(filename, "r")
+except:
+    sys.stdout.write("Unable to open input %s\n" % sys.argv[1])
+    sys.exit(1)
+
+data = fpin.read().rsplit("{")[-1].split("}")[0]
+data = data.replace(",", " ")
+data = data.split()
+data = bytes([int(v) for v in data])
+
+dname = filename + ".ctodata"
+
+try:
+    fpout = open(dname, "wb")
+except:
+    sys.stdout.write("Unable to open output %s\n" % dname)
+    sys.exit(1)
+
+fpout.write(data)
index 7ad9644022299a3d1325dc06dac31927b7cb209f..564070dcf9f908889483154c42f0b1a480f02548 100755 (executable)
@@ -45,8 +45,8 @@ fpin.seek(0, os.SEEK_END)
 size = fpin.tell()
 fpin.seek(0)
 
-if filename[0] == ".":
-    filename = filename[1:]
+if filename[0:2] == "." + os.sep:
+    filename = filename[2:]
 
 cname = filename + ".c"
 sys.stdout.write("Making C file <%s>\n" % cname)
index 2f7151722097f0ed9874505d84f284064a8fe1ed..364d9678f0bcb7427e1a163c4ba6047873eee610 100644 (file)
Binary files a/release/datafiles/prvicons and b/release/datafiles/prvicons differ
index 36ebb154ca933fd071a80f547ba78e61a03aca02..9207b935271e4896e5fd57e380f41a78a1e2b36f 100644 (file)
Binary files a/release/datafiles/splash.png and b/release/datafiles/splash.png differ
index 238d67321a77f54a43a8f11671cd89720040c6e3..2ddf0deff2175ef16d9256d102a4e1b60882f371 100644 (file)
Binary files a/release/freedesktop/icons/16x16/blender.png and b/release/freedesktop/icons/16x16/blender.png differ
diff --git a/release/freedesktop/icons/16x16/blender.svg b/release/freedesktop/icons/16x16/blender.svg
new file mode 100644 (file)
index 0000000..7835b31
--- /dev/null
@@ -0,0 +1,250 @@
+<?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/16x16/blender.xcf.bz2 b/release/freedesktop/icons/16x16/blender.xcf.bz2
deleted file mode 100644 (file)
index 67cb725..0000000
Binary files a/release/freedesktop/icons/16x16/blender.xcf.bz2 and /dev/null differ
index 3178ddd58ee21b7dfe8e432d178d64f9210159c8..fad6f88526f8b353361bf80cb5b461babd8c2fd6 100644 (file)
Binary files a/release/freedesktop/icons/22x22/blender.png and b/release/freedesktop/icons/22x22/blender.png differ
diff --git a/release/freedesktop/icons/22x22/blender.svg b/release/freedesktop/icons/22x22/blender.svg
new file mode 100644 (file)
index 0000000..0f71a2c
--- /dev/null
@@ -0,0 +1,250 @@
+<?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/22x22/blender.xcf.bz2 b/release/freedesktop/icons/22x22/blender.xcf.bz2
deleted file mode 100644 (file)
index fb43962..0000000
Binary files a/release/freedesktop/icons/22x22/blender.xcf.bz2 and /dev/null differ
index 4c9acf10d639a5a7110d8a40478a6176a031c186..6426ade96b6787beecdc5e4d10f88f501cad1e10 100644 (file)
Binary files a/release/freedesktop/icons/32x32/blender.png and b/release/freedesktop/icons/32x32/blender.png differ
index 241111c5c640aff9e85571ac41cde8652b9d123e..030d551699be8ce623c81f902f64559c4e12a529 100644 (file)
@@ -1,8 +1,9 @@
 <?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://web.resource.org/cc/"
+   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"
    height="32"
    id="svg7854"
    sodipodi:version="0.32"
-   inkscape:version="0.44+devel"
+   inkscape:version="0.48.0 r9654"
    version="1.0"
-   sodipodi:docbase="/home/jimmac/gfx/ximian/art/icons/application-icons/blender/32x32"
    sodipodi:docname="blender.svg"
    inkscape:output_extension="org.inkscape.output.svg.inkscape"
-   inkscape:export-filename="/home/jimmac/gfx/ximian/art/icons/application-icons/blender/32x32/blender.png"
+   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"
-   sodipodi:modified="true">
+   inkscape:export-ydpi="90">
   <defs
      id="defs7856">
     <linearGradient
        xlink:href="#linearGradient3564"
        id="linearGradient34576"
        gradientUnits="userSpaceOnUse"
-       x1="213.58719"
-       y1="195.85153"
-       x2="183.16304"
-       y2="-404.09323"
-       gradientTransform="matrix(4.454064e-2,7.407134e-4,-7.396764e-4,4.445763e-2,14.51614,17.23777)" />
+       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"
        x1="21.204315"
        y1="21.699249"
        x2="20.155914"
-       y2="-26.279823"
+       y2="-26.908371"
        gradientUnits="userSpaceOnUse" />
     <linearGradient
        inkscape:collect="always"
        fx="26.109201"
        fy="19.668886"
        r="20.278975"
-       gradientTransform="matrix(1.034353,0,0,0.794876,-9.267532,-3.559595)"
+       gradientTransform="matrix(1.647222,0,0,1.26792,-15.47413,-5.79794)"
        gradientUnits="userSpaceOnUse" />
   </defs>
   <sodipodi:namedview
      objecttolerance="10"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="1"
-     inkscape:cx="43.462736"
-     inkscape:cy="4.2521067"
+     inkscape:zoom="8.1228891"
+     inkscape:cx="39.360762"
+     inkscape:cy="28.503541"
      inkscape:document-units="px"
      inkscape:current-layer="layer1"
-     width="32px"
-     height="32px"
+     width="48px"
+     height="48px"
      inkscape:showpageshadow="false"
-     inkscape:window-width="1046"
-     inkscape:window-height="975"
-     inkscape:window-x="66"
-     inkscape:window-y="135"
-     showgrid="true" />
+     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>
         <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/">
   <g
      inkscape:label="Layer 1"
      inkscape:groupmode="layer"
-     id="layer1">
-    <path
-       sodipodi:type="arc"
-       style="opacity:0.54857142;color:black;fill:url(#radialGradient35494);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
-       id="path35486"
-       sodipodi:cx="28.019106"
-       sodipodi:cy="38.98439"
-       sodipodi:rx="15.467961"
-       sodipodi:ry="5.3033009"
-       d="M 43.487067 38.98439 A 15.467961 5.3033009 0 1 1  12.551145,38.98439 A 15.467961 5.3033009 0 1 1  43.487067 38.98439 z"
-       transform="matrix(0.855157,0,0,0.922661,-5.661873,-11.9649)" />
-    <path
-       style="fill:#f57900;fill-rule:evenodd;stroke:#ce5c00;stroke-width:0.99999976;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
-       id="path2482"
-       d="M 10.187586,18.047598 C 10.194151,18.43397 10.319437,19.185177 10.503745,19.77445 C 10.894027,21.016706 11.555231,22.168099 12.476153,23.182358 C 13.420699,24.222933 14.58237,25.060495 15.925076,25.654464 C 17.337953,26.27861 18.867652,26.597469 20.454999,26.594958 C 22.042346,26.591604 23.571927,26.267543 24.984133,25.638869 C 26.326319,25.039035 27.487985,24.199467 28.431866,23.156206 C 29.350723,22.137924 30.010647,20.984688 30.400893,19.741759 C 30.598368,19.11307 30.720948,18.475882 30.772163,17.835427 C 30.821363,17.2061 30.800373,16.573491 30.710538,15.943511 C 30.536069,14.713677 30.109048,13.560455 29.453827,12.508078 C 28.852842,11.542152 28.079572,10.69606 27.160546,9.9842375 C 27.160546,9.9842375 27.161885,9.9829095 27.161885,9.9829095 C 27.161885,9.9829095 17.881797,2.8677916 17.881797,2.8677916 C 17.873902,2.861242 17.866682,2.8546924 17.858117,2.8488013 C 17.248098,2.3825367 16.224172,2.1628727 15.555131,2.6311026 C 14.876884,3.1039168 14.822425,4.0642627 15.423916,4.5593548 C 16.698828,5.564183 17.880332,6.5265263 19.162309,7.531231 C 19.162309,7.531231 6.4113444,7.545485 6.4113444,7.545485 C 5.0727388,7.545485 4.4964734,8.5678876 4.4728736,9.5288768 C 4.4498234,10.467487 5.2620561,11.472929 6.424444,11.473885 C 6.424444,11.473885 10.390015,11.491386 12.381198,11.487462 C 8.9576952,13.962892 5.5336567,16.437594 2.1103869,18.913339 C 1.1054891,19.68275 0.96699194,20.963058 1.5999701,21.773125 C 2.2441003,22.596939 3.4242293,22.597608 4.4422427,21.777148 C 4.4422427,21.777148 10.265656,17.018805 10.265656,17.018805 C 10.265656,17.018805 10.181697,17.661879 10.187586,18.047598 z "
-       sodipodi:nodetypes="csssssssssscccssccczsccsccc" />
-    <path
-       sodipodi:type="arc"
-       style="opacity:1;color:black;fill:url(#linearGradient39161);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
-       id="path39153"
-       sodipodi:cx="31.1875"
-       sodipodi:cy="25.75"
-       sodipodi:rx="11.5625"
-       sodipodi:ry="10.125"
-       d="M 42.75 25.75 A 11.5625 10.125 0 1 1  19.625,25.75 A 11.5625 10.125 0 1 1  42.75 25.75 z"
-       transform="matrix(0.551379,0,0,0.562462,3.360761,1.826627)" />
-    <path
-       style="opacity:0.4857143;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient34576);stroke-width:0.99999857;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 16.183788,3.9296777 C 16.183788,3.9296777 22.025089,8.4966596 22.025089,8.4966596 C 22.025089,8.4966596 6.9390429,8.5415355 6.9390429,8.5415355 C 6.3165584,8.5315997 5.5564454,8.6449512 5.5327974,9.4661791 C 5.5073593,10.349574 6.2671953,10.457569 6.7979051,10.464836 C 6.7979051,10.464836 15.347353,10.518394 15.347353,10.518394 C 15.347353,10.518394 3.079864,19.266484 3.079864,19.266484 C 1.47422,20.468758 1.9792489,22.058029 3.8906658,20.968571 C 3.8906658,20.968571 11.342463,15.000098 11.342463,15.000098 C 11.056594,17.35207 10.954659,19.925404 12.987785,22.280595 C 14.812944,24.394875 17.412379,25.450616 20.14939,25.602847 C 22.895537,25.619861 25.602761,24.674185 27.502194,22.686776 C 30.98046,18.579998 30.310289,13.928183 26.644414,10.848146 C 23.747065,8.4138175 20.584277,6.070626 17.555006,3.7958257 C 16.683886,3.1416665 15.680806,3.4366807 16.183788,3.9296777 z "
-       id="path3562"
-       sodipodi:nodetypes="ccczcccscsccsss" />
-    <path
-       style="fill:#3465a4;fill-rule:evenodd;stroke:none;stroke-width:1.0074476;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
-       id="path2478"
-       d="M 16.870671,15.810225 C 16.920643,14.898262 17.366801,14.093269 18.037494,13.523364 C 18.697519,12.963129 19.583821,12.621056 20.551972,12.621056 C 21.519507,12.621056 22.40581,12.963129 23.065682,13.523364 C 23.737114,14.093269 24.182732,14.897658 24.233288,15.809622 C 24.285081,16.74818 23.909289,17.619653 23.250649,18.265104 C 22.579217,18.92264 21.621855,19.335417 20.551972,19.335417 C 19.481474,19.335417 18.524111,18.92264 17.85271,18.265104 C 17.193393,17.619653 16.818896,16.74818 16.870671,15.810225 z " />
-    <path
-       style="opacity:0.51999996;fill:url(#radialGradient39177);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
-       d="M 15.941783,4.3847816 C 17.160224,5.348799 19.447413,7.1153436 20.65481,8.0968354 C 20.65481,8.0968354 9.073948,8.076863 6.1653597,8.0745003 C 5.5669549,8.0749003 5.063419,8.5382068 5.0653433,9.4713907 C 5.0672676,10.404575 5.8023091,10.947103 6.2223706,10.947103 C 6.2223706,10.947103 13.891753,10.97234 13.891753,10.97234 C 13.891753,10.97234 3.0882332,18.695586 3.0882332,18.695586 C 1.1062913,20.339688 3.0177499,22.143676 4.8637336,20.782461 C 4.8637337,20.782461 10.861827,15.991544 10.861827,15.991544 C 10.861827,15.991544 10.271137,18.152894 11.144276,20.090121 C 12.499624,23.097221 18.793729,11.835099 29.102295,12.862231 C 28.569898,11.929654 27.713189,10.967578 26.774401,10.204911 C 26.774401,10.204911 20.820024,5.6743082 17.926696,3.45557 C 16.156642,2.1700393 14.822071,3.3579146 15.941783,4.3847816 z "
-       id="path39166"
-       sodipodi:nodetypes="ccczcccccscscc" />
+     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/getversion.py b/release/getversion.py
deleted file mode 100755 (executable)
index 4c47722..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env python
-# -*- mode: python; tab-width: 4; indent-tabs-mode: t; -*-
-# vim: tabstop=4
-# $Id$
-# ***** 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.
-#
-# The Original Code is Copyright (C) 2008 by the Blender Foundation
-# All rights reserved.
-#
-# The Original Code is: see repository.
-#
-# Contributor(s): see repository.
-
-# <pep8-80 compliant>
-
-import sys
-import os
-import re
-
-nanblenderhome = os.getenv("NANBLENDERHOME")
-
-if nanblenderhome is None:
-    nanblenderhome = os.path.dirname(os.path.abspath(sys.argv[0])) + "/.."
-
-config = nanblenderhome + "/source/blender/blenkernel/BKE_blender.h"
-
-infile = open(config)
-
-major = None
-minor = None
-
-for line in infile.readlines():
-    m = re.search("#define BLENDER_VERSION\s+(\d+)", line)
-    if m:
-        major = m.group(1)
-    m = re.search("#define BLENDER_SUBVERSION\s+(\d+)", line)
-    if m:
-        minor = m.group(1)
-    if minor and major:
-        major = float(major) / 100.0
-        break
-
-infile.close()
-
-# Major was changed to float, but minor is still a string
-if minor and major:
-    if minor == "0":
-        print "%.2f" % major
-    else:
-        print "%.2f.%s" % (major, minor)
-else:
-    print "unknownversion"
index 120ca76bbe721d95175e2cec9ef42c8adc90bd61..cff2f1aad82cb0cf05c78461d086a4a673abc3f8 100644 (file)
@@ -187,12 +187,13 @@ void plugin_seq_doit(Cast *cast, float facf0, float facf1, int width,
        double gamma_table[256];
        double uv_table[256];
        float *destf = out->rect_float;
-       float *src1f = ibuf1->rect_float;
+       float *src1f;
        
        if (!ibuf1) return;
 
        dest= (char *) out->rect;
        src1= (char *) ibuf1->rect;
+       src1f= ibuf1->rect_float;
 
        for (y = 0; y < 256; y++) {
                float v = 1.0 * y / 255;
index 721cadb07ce0a139d077035fe1e937138e2e3c56..b80489f3b0bbf5f95bcb142e46d73a51b5300a46 100644 (file)
@@ -120,12 +120,13 @@ void plugin_seq_doit(Cast *cast, float facf0, float facf1, int width,
        float gamma_table[256];
        float uv_table[256];
        float *destf = out->rect_float;
-       float *src1f = ibuf1->rect_float;
+       float *src1f;
        
        if (!ibuf1) return;
 
        dest= (char *) out->rect;
        src1= (char *) ibuf1->rect;
+       src1f= ibuf1->rect_float;
 
        for (y = 0; y < 256; y++) {
                float v = 1.0 * y / 255;
index b8c1fddc6919b51f5c27c9abd9e81f717505145d..6c4ed4119fce1134363ca28c2b22d13e9dd43a68 100644 (file)
 
 # To support reload properly, try to access a package var, if it's there, reload everything
 if "init_data" in locals():
-    reload(model)
-    reload(operators)
-    reload(client)
-    reload(slave)
-    reload(master)
-    reload(master_html)
-    reload(utils)
-    reload(balancing)
-    reload(ui)
-    reload(repath)
+    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
@@ -41,18 +43,25 @@ else:
     from netrender import balancing
     from netrender import ui
     from netrender import repath
+    from netrender import versioning
 
 jobs = []
 slaves = []
 blacklist = []
 
 init_file = ""
-init_address = True
+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():
index 95f345249f2a8c2c5db2fc75f19eb6a75aabfda4..dde3ad53084137019d95f802d106d76560ef3ac6 100644 (file)
@@ -25,6 +25,9 @@ class RatingRule:
     def __init__(self):
         self.enabled = True
 
+    def id(self):
+        return str(id(self))
+
     def rate(self, job):
         return 0
 
@@ -32,6 +35,9 @@ class ExclusionRule:
     def __init__(self):
         self.enabled = True
 
+    def id(self):
+        return str(id(self))
+
     def test(self, job):
         return False
 
@@ -39,6 +45,9 @@ class PriorityRule:
     def __init__(self):
         self.enabled = True
 
+    def id(self):
+        return str(id(self))
+
     def test(self, job):
         return False
 
@@ -50,13 +59,13 @@ class Balancer:
 
     def ruleByID(self, rule_id):
         for rule in self.rules:
-            if id(rule) == rule_id:
+            if rule.id() == rule_id:
                 return rule
         for rule in self.priorities:
-            if id(rule) == rule_id:
+            if rule.id() == rule_id:
                 return rule
         for rule in self.exceptions:
-            if id(rule) == rule_id:
+            if rule.id() == rule_id:
                 return rule
 
         return None
index c17944725b0c3c49b6aab5d8e5aae2a9afac788b..bc43b8cfbb77fc4c0320b470dbb9322fe6528442 100644 (file)
@@ -92,7 +92,82 @@ def addPointCache(job, ob, point_cache, default_path):
                     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()
 
@@ -140,15 +215,13 @@ def clientSendJob(conn, scene, anim = False):
     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.path))
+                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_low, default_path)
-                if modifier.domain_settings.use_high_resolution:
-                    addPointCache(job, object, modifier.domain_settings.point_cache_high, default_path)
+                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)
@@ -160,14 +233,7 @@ def clientSendJob(conn, scene, anim = False):
 
     #print(job.files)
 
-    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
+    fillCommonJobSettings(job, job_name, netsettings)
 
     # try to send path first
     conn.request("POST", "/job", json.dumps(job.serialize()))
@@ -195,7 +261,7 @@ def requestResult(conn, job_id, frame):
 class NetworkRenderEngine(bpy.types.RenderEngine):
     bl_idname = 'NET_RENDER'
     bl_label = "Network Render"
-    bl_postprocess = False
+    bl_use_postprocess = False
     def render(self, scene):
         if scene.network_render.mode == "RENDER_CLIENT":
             self.render_client(scene)
@@ -211,7 +277,7 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
 
         address = "" if netsettings.server_address == "[default]" else netsettings.server_address
 
-        master.runMaster((address, netsettings.server_port), netsettings.use_master_broadcast, netsettings.use_master_clear, netsettings.path, self.update_stats, self.test_break)
+        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):
@@ -236,10 +302,11 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
             # reading back result
 
             self.update_stats("", "Network render waiting for results")
-
+            
+             
             requestResult(conn, job_id, scene.frame_current)
             response = conn.getresponse()
-            response.read()
+            buf = response.read()
 
             if response.status == http.client.NO_CONTENT:
                 new_job = True
@@ -248,13 +315,13 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
 
                 requestResult(conn, job_id, scene.frame_current)
                 response = conn.getresponse()
-                response.read()
-
+                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()
-                response.read()
+                buf = response.read()
 
             # cancel new jobs (animate on network) on break
             if self.test_break() and new_job:
@@ -271,18 +338,22 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
             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(os.path.join(netsettings.path, "output.exr"), "wb")
-            buf = response.read(1024)
+            f = open(result_path, "wb")
 
-            while buf:
-                f.write(buf)
-                buf = response.read(1024)
+            f.write(buf)
 
             f.close()
 
             result = self.begin_result(0, 0, x, y)
-            result.load_from_file(os.path.join(netsettings.path, "output.exr"))
+            result.load_from_file(result_path)
             self.end_result(result)
 
             conn.close()
@@ -294,7 +365,6 @@ def compatible(module):
         except:        pass
     del module
 
-#compatible("properties_render")
 compatible("properties_world")
 compatible("properties_material")
 compatible("properties_data_mesh")
index 11409bf372e4a7cea2623572a0f452b05546a120..793e3bb51bf1fd706c080a2cc0b04cf380a04bab 100644 (file)
@@ -27,6 +27,7 @@ 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):
@@ -35,7 +36,7 @@ class MRenderFile(netrender.model.RenderFile):
 
     def test(self):
         self.found = os.path.exists(self.filepath)
-        if self.found:
+        if self.found and self.signature != None:
             found_signature = hashFile(self.filepath)
             self.found = self.signature == found_signature
             
@@ -82,8 +83,6 @@ class MRenderJob(netrender.model.RenderJob):
         self.save_path = ""
         self.files = [MRenderFile(rfile.filepath, rfile.index, rfile.start, rfile.end, rfile.signature) for rfile in job_info.files]
 
-        self.resolution = None
-
     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"]))
@@ -105,9 +104,11 @@ class MRenderJob(netrender.model.RenderJob):
             self.chunks = info_map["chunks"]
 
     def testStart(self):
-        for f in self.files:
-            if not f.test():
-                return False
+        # 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()
@@ -201,6 +202,15 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
         # 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)
@@ -297,7 +307,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
                         elif frame.status == DONE:
                             filename = os.path.join(job.save_path, "%06d.exr" % frame_number)
 
-                            thumbname = thumbnail(filename)
+                            thumbname = thumbnail.generate(filename)
 
                             if thumbname:
                                 f = open(thumbname, 'rb')
@@ -516,8 +526,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
                 job = self.server.getJobID(job_id)
 
                 if job:
-                    length = int(self.headers['content-length'])
-                    info_map = eval(str(self.rfile.read(length), encoding='utf8'))
+                    info_map = self.getInfoMap()
 
                     job.edit(info_map)
                     self.send_head()
@@ -529,8 +538,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
                 self.send_head(http.client.NO_CONTENT)
         # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
         elif self.path == "/balance_limit":
-            length = int(self.headers['content-length'])
-            info_map = eval(str(self.rfile.read(length), encoding='utf8'))
+            info_map = self.getInfoMap()
             for rule_id, limit in info_map.items():
                 try:
                     rule = self.server.balancer.ruleByID(rule_id)
@@ -542,8 +550,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
             self.send_head()
         # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
         elif self.path == "/balance_enable":
-            length = int(self.headers['content-length'])
-            info_map = eval(str(self.rfile.read(length), encoding='utf8'))
+            info_map = self.getInfoMap()
             for rule_id, enabled in info_map.items():
                 rule = self.server.balancer.ruleByID(rule_id)
                 if rule:
@@ -555,13 +562,8 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
             match = cancel_pattern.match(self.path)
 
             if match:
-                length = int(self.headers['content-length'])
-
-                if length > 0:
-                    info_map = eval(str(self.rfile.read(length), encoding='utf8'))
-                    clear = info_map.get("clear", False)
-                else:
-                    clear = False
+                info_map = self.getInfoMap()
+                clear = info_map.get("clear", False)
 
                 job_id = match.groups()[0]
 
@@ -582,13 +584,8 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
             match = pause_pattern.match(self.path)
 
             if match:
-                length = int(self.headers['content-length'])
-
-                if length > 0:
-                    info_map = eval(str(self.rfile.read(length), encoding='utf8'))
-                    status = info_map.get("status", None)
-                else:
-                    status = None
+                info_map = self.getInfoMap()
+                status = info_map.get("status", None)
 
                 job_id = match.groups()[0]
 
@@ -607,13 +604,8 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
         # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
         elif self.path == "/clear":
             # cancel all jobs
-            length = int(self.headers['content-length'])
-
-            if length > 0:
-                info_map = eval(str(self.rfile.read(length), encoding='utf8'))
-                clear = info_map.get("clear", False)
-            else:
-                clear = False
+            info_map = self.getInfoMap()
+            clear = info_map.get("clear", False)
 
             self.server.stats("", "Clearing jobs")
             self.server.clear(clear)
@@ -769,7 +761,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
                     frame = job[job_frame]
 
                     if frame:
-                        if job.type == netrender.model.JOB_BLENDER:
+                        if job.hasRenderResult():
                             if job_result == DONE:
                                 length = int(self.headers['content-length'])
                                 buf = self.rfile.read(length)
@@ -820,7 +812,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
                     frame = job[job_frame]
 
                     if frame:
-                        if job.type == netrender.model.JOB_BLENDER:
+                        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')
index 74155f6bd66cf898ec9a430f6a1ab52049401078..877273207a84a28e896ccbd38d37c74fb06e5556 100644 (file)
@@ -20,6 +20,7 @@ import os
 import re
 import shutil
 from netrender.utils import *
+import netrender.model
 
 src_folder = os.path.split(__file__)[0]
 
@@ -115,6 +116,7 @@ def get(handler):
                         "id",
                         "name",
                         "category",
+                        "type",
                         "chunks",
                         "priority",
                         "usage",
@@ -139,6 +141,7 @@ def get(handler):
                         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 ""),
@@ -180,28 +183,28 @@ def get(handler):
         for rule in handler.server.balancer.rules:
             rowTable(
                         "rating",
-                        checkbox("", rule.enabled, "balance_enable('%i', '%s')" % (id(rule), str(not rule.enabled))),
+                        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('%i', '%s');">edit</button>""" % (id(rule), str(rule.limit)) if hasattr(rule, "limit") else "&nbsp;"
+                        """<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('%i', '%s')" % (id(rule), str(not rule.enabled))),
+                        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('%i', '%s');">edit</button>""" % (id(rule), str(rule.limit)) if hasattr(rule, "limit") else "&nbsp;"
+                        """<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('%i', '%s')" % (id(rule), str(not rule.enabled))),
+                        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('%i', '%s');">edit</button>""" % (id(rule), str(rule.limit)) if hasattr(rule, "limit") else "&nbsp;"
+                        """<button title="edit limit" onclick="balance_edit('%s', '%s');">edit</button>""" % (rule.id(), str(rule.limit)) if hasattr(rule, "limit") else "&nbsp;"
                     )
 
         endTable()
@@ -228,39 +231,52 @@ def get(handler):
             endTable()
 
 
-            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;)'")
+            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"):
-                        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()
+                        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>")
index e7656f498b4a450800d5bf35e9cd580b98ab9150..5fc0bc2a0bb9ea286cf05935567699471c6d6f06 100644 (file)
@@ -20,6 +20,7 @@ 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:
@@ -96,11 +97,65 @@ class RenderSlave:
 
 JOB_BLENDER = 1
 JOB_PROCESS = 2
+JOB_VCS     = 3
 
 JOB_TYPES = {
-                            JOB_BLENDER: "Blender",
-                            JOB_PROCESS: "Process"
-                        }
+                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):
@@ -142,6 +197,10 @@ class RenderJob:
         self.chunks = 0
         self.priority = 0
         self.blacklist = []
+        
+        self.version_info = None
+        
+        self.resolution = None
 
         self.usage = 0.0
         self.last_dispatched = 0.0
@@ -156,9 +215,19 @@ class RenderJob:
             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 addFile(self, file_path, start=-1, end=-1):
-        signature = hashFile(file_path)
+    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 = ""):
@@ -225,7 +294,9 @@ class RenderJob:
                             "priority": self.priority,
                             "usage": self.usage,
                             "blacklist": self.blacklist,
-                            "last_dispatched": self.last_dispatched
+                            "last_dispatched": self.last_dispatched,
+                            "version_info": self.version_info.serialize() if self.version_info else None,
+                            "resolution": self.resolution
                         }
 
     @staticmethod
@@ -246,6 +317,11 @@ class RenderJob:
         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
 
index 041a39a3ebc0c59a115e0d35b20dc01b4cc90430..1024a169571804033657953fad194bfe2d7301fb 100644 (file)
@@ -20,9 +20,9 @@ function clear_jobs()
        var r=confirm("Also delete files on master?");
        
        if (r==true) {
-               request('/clear', "{'clear':True}");
+               request('/clear', '{"clear":true}');
        } else {
-               request('/clear', "{'clear':False}");
+               request('/clear', '{"clear":false}');
        }
 }
 
@@ -31,9 +31,9 @@ function cancel_job(id)
        var r=confirm("Also delete files on master?");
        
        if (r==true) {
-               request('/cancel_' + id, "{'clear':True}");
+               request('/cancel_' + id, '{"clear":true}');
        } else {
-               request('/cancel_' + id, "{'clear':False}");
+               request('/cancel_' + id, '{"clear":false}');
        }
 }
 
@@ -41,13 +41,13 @@ 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 + "'}");
+               request("/balance_limit", '{"' + id + '":"' + new_value + '"}');
        }
 }
 
 function balance_enable(id, value)
 {
-       request("/balance_enable", "{" + id + ":" + value + "}");
+       request("/balance_enable", '{"' + id + '":' + value + "}");
 }
 
 function showThumb(job, frame)
index 2b40cd7712503d87162f2be134b43eaea5839ae9..f2c2fda7bdee4a6a9e66d475fa308b07f1e102c5 100644 (file)
@@ -26,6 +26,7 @@ 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'''
@@ -61,12 +62,9 @@ class RENDER_OT_netslave_bake(bpy.types.Operator):
                     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_low.use_step = 1
-                    modifier.domain_settings.point_cache_low.use_disk_cache = True
-                    modifier.domain_settings.point_cache_low.use_external = False
-                    modifier.domain_settings.point_cache_high.use_step = 1
-                    modifier.domain_settings.point_cache_high.use_disk_cache = True
-                    modifier.domain_settings.point_cache_high.use_external = False
+                    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
@@ -354,7 +352,7 @@ class RENDER_OT_netclientcancel(bpy.types.Operator):
         if conn:
             job = netrender.jobs[netsettings.active_job_index]
 
-            conn.request("POST", cancelURL(job.id))
+            conn.request("POST", cancelURL(job.id), json.dumps({'clear':False}))
 
             response = conn.getresponse()
             response.read()
@@ -381,7 +379,7 @@ class RENDER_OT_netclientcancelall(bpy.types.Operator):
         conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
 
         if conn:
-            conn.request("POST", "/clear")
+            conn.request("POST", "/clear", json.dumps({'clear':False}))
 
             response = conn.getresponse()
             response.read()
@@ -403,7 +401,7 @@ class netclientdownload(bpy.types.Operator):
     @classmethod
     def poll(cls, context):
         netsettings = context.scene.network_render
-        return netsettings.active_job_index >= 0 and len(netsettings.jobs) > 0
+        return netsettings.active_job_index >= 0 and len(netsettings.jobs) > netsettings.active_job_index
 
     def execute(self, context):
         netsettings = context.scene.network_render
@@ -412,29 +410,71 @@ class netclientdownload(bpy.types.Operator):
         conn = clientConnection(netsettings.server_address, netsettings.server_port, self.report)
 
         if conn:
-            job = netrender.jobs[netsettings.active_job_index]
-
+            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:
-                client.requestResult(conn, job.id, frame.number)
-                response = conn.getresponse()
-                response.read()
-
-                if response.status != http.client.OK:
-                    print("missing", frame.number)
-                    continue
-
-                print("got back", frame.number)
-
-                f = open(os.path.join(netsettings.path, "%06d.exr" % frame.number), "wb")
-                buf = response.read(1024)
-
-                while buf:
-                    f.write(buf)
-                    buf = response.read(1024)
-
-                f.close()
-
-            conn.close()
+                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'}
 
@@ -464,6 +504,38 @@ class netclientscan(bpy.types.Operator):
     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"
index f017fefa4e3070123021051b649ac63b7ca659d1..b05de0afeb96d75bf913f4be5b5bafb093e7f5ca 100644 (file)
@@ -21,17 +21,26 @@ 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
-
-if platform.system() == 'Windows' and platform.version() >= '5': # Error mode is only available on Win2k or higher, that's version 5
+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)
@@ -71,7 +80,7 @@ def testFile(conn, job_id, slave_id, rfile, JOB_PREFIX, main_path = None):
     
     found = os.path.exists(job_full_path)
     
-    if found:
+    if found and rfile.signature != None:
         found_signature = hashFile(job_full_path)
         found = found_signature == rfile.signature
         
@@ -104,13 +113,36 @@ def testFile(conn, job_id, slave_id, rfile, JOB_PREFIX, main_path = None):
 
     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()
@@ -118,7 +150,7 @@ def render_slave(engine, netsettings, threads):
 
         slave_id = response.getheader("slave-id")
 
-        NODE_PREFIX = os.path.join(netsettings.path, "slave_" + 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)
 
@@ -129,7 +161,7 @@ def render_slave(engine, netsettings, threads):
             response = conn.getresponse()
 
             if response.status == http.client.OK:
-                timeout = 1 # reset timeout on new job
+                bisleep.reset()
 
                 job = netrender.model.RenderJob.materialize(json.loads(str(response.read(), encoding='utf8')))
                 engine.update_stats("", "Network render processing job from master")
@@ -138,6 +170,10 @@ def render_slave(engine, netsettings, threads):
                 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
@@ -153,6 +189,20 @@ def render_slave(engine, netsettings, threads):
                         
                     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
@@ -167,7 +217,7 @@ def render_slave(engine, netsettings, threads):
                 # start render
                 start_t = time.time()
 
-                if job.type == netrender.model.JOB_BLENDER:
+                if job.rendersWithBlender():
                     frame_args = []
 
                     for frame in job.frames:
@@ -252,20 +302,20 @@ def render_slave(engine, netsettings, threads):
                     headers["job-result"] = str(DONE)
                     for frame in job.frames:
                         headers["job-frame"] = str(frame.number)
-                        if job.type == netrender.model.JOB_BLENDER:
+                        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(filename)
-
-                                f = open(thumbname, 'rb')
-                                conn.request("PUT", "/thumb", f, headers=headers)
-                                f.close()
-                                responseStatus(conn)
+                                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)
@@ -288,13 +338,7 @@ def render_slave(engine, netsettings, threads):
 
                 engine.update_stats("", "Network render connected to master, waiting for jobs")
             else:
-                if timeout < MAX_TIMEOUT:
-                    timeout += INCREMENT_TIMEOUT
-
-                for i in range(timeout):
-                    time.sleep(1)
-                    if engine.test_break():
-                        break
+                bisleep.sleep()
 
         conn.close()
 
diff --git a/release/scripts/io/netrender/thumbnail.py b/release/scripts/io/netrender/thumbnail.py
new file mode 100644 (file)
index 0000000..2ead6e8
--- /dev/null
@@ -0,0 +1,81 @@
+# ##### 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)
index c065b95b92894a5f2b39204fe3f9f820f156e466..343c60e78654d9aa30b9277d0f5ba24811b5dc77 100644 (file)
@@ -36,6 +36,8 @@ 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)
@@ -45,7 +47,7 @@ def init_file():
     if netrender.init_file != bpy.data.filepath:
         netrender.init_file = bpy.data.filepath
         netrender.init_data = True
-        netrender.init_address = True
+        netrender.valid_address = False
 
 def init_data(netsettings):
     init_file()
@@ -66,22 +68,31 @@ def init_data(netsettings):
             netsettings.jobs.remove(0)
 
 def verify_address(netsettings):
+    global LAST_ADDRESS_TEST
     init_file()
 
-    if netrender.init_address:
-        netrender.init_address = False
+    if LAST_ADDRESS_TEST + 30 < time.time():
+        LAST_ADDRESS_TEST = time.time()
 
         try:
-            conn = clientConnection(netsettings.server_address, netsettings.server_port, scan = False)
+            conn = clientConnection(netsettings.server_address, netsettings.server_port, scan = False, timeout = 1)
         except:
             conn = None
 
         if conn:
+            netrender.valid_address = True
             conn.close()
         else:
-            netsettings.server_address = "[default]"
+            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 RenderButtonsPanel():
+class NetRenderButtonsPanel():
     bl_space_type = "PROPERTIES"
     bl_region_type = "WINDOW"
     bl_context = "render"
@@ -90,16 +101,16 @@ class RenderButtonsPanel():
     @classmethod
     def poll(cls, context):
         rd = context.scene.render
-        return (rd.use_game_engine==False) and (rd.engine in cls.COMPAT_ENGINES)
+        return rd.engine == 'NET_RENDER' and rd.use_game_engine == False 
 
 # Setting panel, use in the scene for now.
-class RENDER_PT_network_settings(bpy.types.Panel, RenderButtonsPanel):
+class RENDER_PT_network_settings(NetRenderButtonsPanel, bpy.types.Panel):
     bl_label = "Network Settings"
     COMPAT_ENGINES = {'NET_RENDER'}
 
     @classmethod
     def poll(cls, context):
-        return super(RENDER_PT_network_settings, cls).poll(context)
+        return super().poll(context)
 
     def draw(self, context):
         layout = self.layout
@@ -128,17 +139,20 @@ class RENDER_PT_network_settings(bpy.types.Panel, RenderButtonsPanel):
 
         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(bpy.types.Panel, RenderButtonsPanel):
+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(RENDER_PT_network_slave_settings, cls).poll(context) and scene.network_render.mode == "RENDER_SLAVE"
+        return super().poll(context) and scene.network_render.mode == "RENDER_SLAVE"
 
     def draw(self, context):
         layout = self.layout
@@ -156,14 +170,14 @@ class RENDER_PT_network_slave_settings(bpy.types.Panel, RenderButtonsPanel):
         sub.enabled = rd.threads_mode == 'FIXED'
         sub.prop(rd, "threads")
 
-class RENDER_PT_network_master_settings(bpy.types.Panel, RenderButtonsPanel):
+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(RENDER_PT_network_master_settings, cls).poll(context) and scene.network_render.mode == "RENDER_MASTER"
+        return super().poll(context) and scene.network_render.mode == "RENDER_MASTER"
 
     def draw(self, context):
         layout = self.layout
@@ -174,14 +188,14 @@ class RENDER_PT_network_master_settings(bpy.types.Panel, RenderButtonsPanel):
         layout.prop(netsettings, "use_master_broadcast")
         layout.prop(netsettings, "use_master_clear")
 
-class RENDER_PT_network_job(bpy.types.Panel, RenderButtonsPanel):
+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(RENDER_PT_network_job, cls).poll(context) and scene.network_render.mode == "RENDER_CLIENT"
+        return super().poll(context) and scene.network_render.mode == "RENDER_CLIENT"
 
     def draw(self, context):
         layout = self.layout
@@ -203,10 +217,12 @@ class RENDER_PT_network_job(bpy.types.Panel, RenderButtonsPanel):
         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="")
 
@@ -214,18 +230,38 @@ class RENDER_PT_network_job(bpy.types.Panel, RenderButtonsPanel):
         row.prop(netsettings, "priority")
         row.prop(netsettings, "chunks")
 
-class RENDER_PT_network_slaves(bpy.types.Panel, RenderButtonsPanel):
-    bl_label = "Slaves Status"
+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
-        if netsettings.mode != "RENDER_CLIENT":
-            return False
-        verify_address(netsettings)
-        return super(RENDER_PT_network_slaves, cls).poll(context) and netsettings.server_address != "[default]"
+
+        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
@@ -240,9 +276,7 @@ class RENDER_PT_network_slaves(bpy.types.Panel, RenderButtonsPanel):
         sub.operator("render.netclientslaves", icon='FILE_REFRESH', text="")
         sub.operator("render.netclientblacklistslave", icon='ZOOMOUT', text="")
 
-        init_data(netsettings)
-
-        if netsettings.active_slave_index >= 0 and len(netsettings.slaves) > 0:
+        if len(netrender.slaves) > netsettings.active_slave_index >= 0:
             layout.separator()
 
             slave = netrender.slaves[netsettings.active_slave_index]
@@ -252,18 +286,14 @@ class RENDER_PT_network_slaves(bpy.types.Panel, RenderButtonsPanel):
             layout.label(text="Seen: " + time.ctime(slave.last_seen))
             layout.label(text="Stats: " + slave.stats)
 
-class RENDER_PT_network_slaves_blacklist(bpy.types.Panel, RenderButtonsPanel):
+class RENDER_PT_network_slaves_blacklist(NeedValidAddress, NetRenderButtonsPanel, bpy.types.Panel):
     bl_label = "Slaves Blacklist"
     COMPAT_ENGINES = {'NET_RENDER'}
 
     @classmethod
     def poll(cls, context):
-        scene = context.scene
-        netsettings = scene.network_render
-        if netsettings.mode != "RENDER_CLIENT":
-            return False
-        verify_address(netsettings)
-        return super(RENDER_PT_network_slaves_blacklist, cls).poll(context) and netsettings.server_address != "[default]"
+        netsettings = context.scene.network_render
+        return super().poll(context) and netsettings.mode == "RENDER_CLIENT"
 
     def draw(self, context):
         layout = self.layout
@@ -277,9 +307,7 @@ class RENDER_PT_network_slaves_blacklist(bpy.types.Panel, RenderButtonsPanel):
         sub = row.column(align=True)
         sub.operator("render.netclientwhitelistslave", icon='ZOOMOUT', text="")
 
-        init_data(netsettings)
-
-        if netsettings.active_blacklisted_slave_index >= 0 and len(netsettings.slaves_blacklist) > 0:
+        if len(netrender.blacklist) > netsettings.active_blacklisted_slave_index >= 0:
             layout.separator()
 
             slave = netrender.blacklist[netsettings.active_blacklisted_slave_index]
@@ -289,18 +317,14 @@ class RENDER_PT_network_slaves_blacklist(bpy.types.Panel, RenderButtonsPanel):
             layout.label(text="Seen: " + time.ctime(slave.last_seen))
             layout.label(text="Stats: " + slave.stats)
 
-class RENDER_PT_network_jobs(bpy.types.Panel, RenderButtonsPanel):
+class RENDER_PT_network_jobs(NeedValidAddress, NetRenderButtonsPanel, bpy.types.Panel):
     bl_label = "Jobs"
     COMPAT_ENGINES = {'NET_RENDER'}
 
     @classmethod
     def poll(cls, context):
-        scene = context.scene
-        netsettings = scene.network_render
-        if netsettings.mode != "RENDER_CLIENT":
-            return False
-        verify_address(netsettings)
-        return super(RENDER_PT_network_jobs, cls).poll(context) and netsettings.server_address != "[default]"
+        netsettings = context.scene.network_render
+        return super().poll(context) and netsettings.mode == "RENDER_CLIENT"
 
     def draw(self, context):
         layout = self.layout
@@ -317,9 +341,7 @@ class RENDER_PT_network_jobs(bpy.types.Panel, RenderButtonsPanel):
         sub.operator("render.netclientcancelall", icon='PANEL_CLOSE', text="")
         sub.operator("render.netclientdownload", icon='RENDER_ANIMATION', text="")
 
-        init_data(netsettings)
-
-        if netsettings.active_job_index >= 0 and len(netsettings.jobs) > 0:
+        if len(netrender.jobs) > netsettings.active_job_index >= 0:
             layout.separator()
 
             job = netrender.jobs[netsettings.active_job_index]
@@ -329,16 +351,33 @@ class RENDER_PT_network_jobs(bpy.types.Panel, RenderButtonsPanel):
             layout.label(text="Done: %04i" % job.results[DONE])
             layout.label(text="Error: %04i" % job.results[ERROR])
 
-class NetRenderSettings(bpy.types.IDPropertyGroup):
-    pass
+import properties_render
+class RENDER_PT_network_output(NeedValidAddress, NetRenderButtonsPanel, bpy.types.Panel):
+    bl_label = "Output"
+    COMPAT_ENGINES = {'NET_RENDER'}
 
-class NetRenderSlave(bpy.types.IDPropertyGroup):
-    pass
+    @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
 
-class NetRenderJob(bpy.types.IDPropertyGroup):
-    pass
 
 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")
     
@@ -397,6 +436,16 @@ def addProperties():
                     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",
@@ -423,6 +472,30 @@ def addProperties():
                     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",
index e2a5051cf642cc4440950c2c940dc9d145d4cf67..ed9fb2de81280c7aaf79d63c1579a57a3b521d7f 100644 (file)
@@ -28,7 +28,7 @@ try:
 except:
   bpy = None
 
-VERSION = bytes("0.9", encoding='utf8')
+VERSION = bytes("1.3", encoding='utf8')
 
 # Jobs status
 JOB_WAITING = 0 # before all data has been entered
@@ -57,6 +57,39 @@ FRAME_STATUS_TEXT = {
         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()
@@ -97,7 +130,7 @@ def clientScan(report = None):
 
         return ("", 8000) # return default values
 
-def clientConnection(address, port, report = None, scan = True):
+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:
@@ -111,7 +144,7 @@ def clientConnection(address, port, report = None, scan = True):
             return None
 
     try:
-        conn = http.client.HTTPConnection(address, port, timeout = 5)
+        conn = http.client.HTTPConnection(address, port, timeout = timeout)
 
         if conn:
             if clientVerifyVersion(conn):
@@ -119,12 +152,13 @@ def clientConnection(address, port, report = None, scan = True):
             else:
                 conn.close()
                 reporting(report, "Incorrect master version", ValueError)
-    except Exception as err:
+    except BaseException as err:
         if report:
             report('ERROR', str(err))
             return None
         else:
-            raise
+            print(err)
+            return None
 
 def clientVerifyVersion(conn):
     conn.request("GET", "/version")
@@ -168,7 +202,10 @@ def hashData(data):
     
 
 def prefixPath(prefix_directory, file_path, prefix_path, force = False):
-    if os.path.isabs(file_path):
+    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):
@@ -185,12 +222,69 @@ def prefixPath(prefix_directory, file_path, prefix_path, force = False):
             else:
                 full_path = os.path.join(prefix_directory, n)
     else:
-        full_path = (prefix_directory, file_path)
+        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__, "--"] + infos, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    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)
@@ -203,33 +297,17 @@ def getFileInfo(filepath, infos):
     values = [eval(v[1:].strip()) for v in stdout.split("\n") if v.startswith("$")]
 
     return values
-
-def thumbnail(filename):
-    root = os.path.splitext(filename)[0]
-    imagename = os.path.split(filename)[1]
-    thumbname = root + ".jpg"
-
-    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
-        bpy.ops.image.open(filepath=filename)
-        img = bpy.data.images[imagename]
-        img.save_render(thumbname, scene=scene)
-
-        try:
-            process = subprocess.Popen(["convert", thumbname, "-resize", "300x300", thumbname])
-            process.wait()
-            return thumbname
-        except:
-            pass
-
-    return None
+  
 
 if __name__ == "__main__":
-    import bpy
-    for info in sys.argv[7:]:
-        print("$", eval(info))
+    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
new file mode 100644 (file)
index 0000000..d4f8522
--- /dev/null
@@ -0,0 +1,72 @@
+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()
+           }
index 73b750572992b2c9a0d7c86fa35172823b811715..cff4aecac54c5cc049e92b16247eeb3dc91bfcd7 100644 (file)
@@ -1,7 +1,29 @@
-# 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.
+# ##### 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>
+
+"""
+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.
+"""
 
 import bpy
 from keyingsets_utils import *
@@ -9,6 +31,7 @@ from keyingsets_utils import *
 ###############################
 # Built-In KeyingSets
 
+
 # Location
 class BUILTIN_KSI_Location(bpy.types.KeyingSetInfo):
     bl_label = "Location"
@@ -19,9 +42,10 @@ class BUILTIN_KSI_Location(bpy.types.KeyingSetInfo):
     # iterator - use callback for selected bones/objects
     iterator = RKS_ITER_selected_item
 
-    # generator - use callback for location 
+    # generator - use callback for location
     generate = RKS_GEN_location
 
+
 # Rotation
 class BUILTIN_KSI_Rotation(bpy.types.KeyingSetInfo):
     bl_label = "Rotation"
@@ -32,9 +56,10 @@ class BUILTIN_KSI_Rotation(bpy.types.KeyingSetInfo):
     # iterator - use callback for selected bones/objects
     iterator = RKS_ITER_selected_item
 
-    # generator - use callback for location 
+    # generator - use callback for location
     generate = RKS_GEN_rotation
 
+
 # Scale
 class BUILTIN_KSI_Scaling(bpy.types.KeyingSetInfo):
     bl_label = "Scaling"
@@ -45,11 +70,12 @@ class BUILTIN_KSI_Scaling(bpy.types.KeyingSetInfo):
     # iterator - use callback for selected bones/objects
     iterator = RKS_ITER_selected_item
 
-    # generator - use callback for location 
+    # generator - use callback for location
     generate = RKS_GEN_scaling
 
 # ------------
 
+
 # LocRot
 class BUILTIN_KSI_LocRot(bpy.types.KeyingSetInfo):
     bl_label = "LocRot"
@@ -60,13 +86,14 @@ class BUILTIN_KSI_LocRot(bpy.types.KeyingSetInfo):
     # iterator - use callback for selected bones/objects
     iterator = RKS_ITER_selected_item
 
-    # generator - use callback for location 
+    # generator
     def generate(self, context, ks, data):
         # location
         RKS_GEN_location(self, context, ks, data)
         # rotation
         RKS_GEN_rotation(self, context, ks, data)
 
+
 # LocScale
 class BUILTIN_KSI_LocScale(bpy.types.KeyingSetInfo):
     bl_label = "LocScale"
@@ -77,13 +104,14 @@ class BUILTIN_KSI_LocScale(bpy.types.KeyingSetInfo):
     # iterator - use callback for selected bones/objects
     iterator = RKS_ITER_selected_item
 
-    # generator - use callback for location 
+    # generator
     def generate(self, context, ks, data):
         # location
         RKS_GEN_location(self, context, ks, data)
         # scale
         RKS_GEN_scaling(self, context, ks, data)
 
+
 # LocRotScale
 class BUILTIN_KSI_LocRotScale(bpy.types.KeyingSetInfo):
     bl_label = "LocRotScale"
@@ -94,7 +122,7 @@ class BUILTIN_KSI_LocRotScale(bpy.types.KeyingSetInfo):
     # iterator - use callback for selected bones/objects
     iterator = RKS_ITER_selected_item
 
-    # generator - use callback for location 
+    # generator
     def generate(self, context, ks, data):
         # location
         RKS_GEN_location(self, context, ks, data)
@@ -103,6 +131,7 @@ class BUILTIN_KSI_LocRotScale(bpy.types.KeyingSetInfo):
         # scale
         RKS_GEN_scaling(self, context, ks, data)
 
+
 # RotScale
 class BUILTIN_KSI_RotScale(bpy.types.KeyingSetInfo):
     bl_label = "RotScale"
@@ -113,20 +142,21 @@ class BUILTIN_KSI_RotScale(bpy.types.KeyingSetInfo):
     # iterator - use callback for selected bones/objects
     iterator = RKS_ITER_selected_item
 
-    # generator - use callback for location 
+    # generator
     def generate(self, context, ks, data):
         # rotation
         RKS_GEN_rotation(self, context, ks, data)
         # scaling
         RKS_GEN_scaling(self, context, ks, data)
-        
+
 # ------------
 
+
 # Location
 class BUILTIN_KSI_VisualLoc(bpy.types.KeyingSetInfo):
     bl_label = "Visual Location"
 
-    insertkey_visual = True
+    bl_options = {'INSERTKEY_VISUAL'}
 
     # poll - use predefined callback for selected bones/objects
     poll = RKS_POLL_selected_items
@@ -134,9 +164,10 @@ class BUILTIN_KSI_VisualLoc(bpy.types.KeyingSetInfo):
     # iterator - use callback for selected bones/objects
     iterator = RKS_ITER_selected_item
 
-    # generator - use callback for location 
+    # generator - use callback for location
     generate = RKS_GEN_location
 
+
 # Rotation
 class BUILTIN_KSI_VisualRot(bpy.types.KeyingSetInfo):
     bl_label = "Visual Rotation"
@@ -149,9 +180,10 @@ class BUILTIN_KSI_VisualRot(bpy.types.KeyingSetInfo):
     # iterator - use callback for selected bones/objects
     iterator = RKS_ITER_selected_item
 
-    # generator - use callback for location 
+    # generator - use callback for rotation
     generate = RKS_GEN_rotation
 
+
 # VisualLocRot
 class BUILTIN_KSI_VisualLocRot(bpy.types.KeyingSetInfo):
     bl_label = "Visual LocRot"
@@ -164,7 +196,7 @@ class BUILTIN_KSI_VisualLocRot(bpy.types.KeyingSetInfo):
     # iterator - use callback for selected bones/objects
     iterator = RKS_ITER_selected_item
 
-    # generator - use callback for location 
+    # generator
     def generate(self, context, ks, data):
         # location
         RKS_GEN_location(self, context, ks, data)
@@ -173,53 +205,163 @@ class BUILTIN_KSI_VisualLocRot(bpy.types.KeyingSetInfo):
 
 # ------------
 
+
 # Available
 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) 
+    # TODO: this should really check whether the selected object (or datablock)
     #         has any animation data defined yet
     poll = RKS_POLL_selected_objects
 
     # iterator - use callback for selected bones/objects
     iterator = RKS_ITER_selected_item
 
-    # generator - use callback for location 
+    # generator - use callback for doing this
     generate = RKS_GEN_available
 
-############################### 
-
-classes = [
-    BUILTIN_KSI_Location,
-    BUILTIN_KSI_Rotation,
-    BUILTIN_KSI_Scaling,
-
-    BUILTIN_KSI_LocRot,
-    BUILTIN_KSI_LocScale,
-    BUILTIN_KSI_LocRotScale,
-    BUILTIN_KSI_RotScale,
+###############################
 
-    BUILTIN_KSI_VisualLoc,
-    BUILTIN_KSI_VisualRot,
-    BUILTIN_KSI_VisualLocRot,
 
-    BUILTIN_KSI_Available,
-]
+# All properties that are likely to get animated in a character rig
+class BUILTIN_KSI_WholeCharacter(bpy.types.KeyingSetInfo):
+    bl_label = "Whole Character"
+
+    # these prefixes should be avoided, as they are not really bones
+    # that animators should be touching (or need to touch)
+    badBonePrefixes = (
+        'DEF',
+        'GEO',
+        'MCH',
+        'ORG',
+        'COR',
+        'VIS',
+        # ... more can be added here as you need in your own rigs ...
+    )
+
+    # poll - pose-mode on active object only
+    def poll(ksi, context):
+        return ((context.active_object) and (context.active_object.pose) and
+                (context.active_object.mode == 'POSE'))
+
+    # iterator - all bones regardless of selection
+    def iterator(ksi, context, ks):
+        for bone in context.active_object.pose.bones:
+            if not bone.name.startswith(BUILTIN_KSI_WholeCharacter.badBonePrefixes):
+                ksi.generate(context, ks, bone)
+
+    # generator - all unlocked bone transforms + custom properties
+    def generate(ksi, context, ks, bone):
+        # loc, rot, scale - only include unlocked ones
+        ksi.doLoc(ks, bone)
+
+        if bone.rotation_mode in ('QUATERNION', 'AXIS_ANGLE'):
+            ksi.doRot4d(ks, bone)
+        else:
+            ksi.doRot3d(ks, bone)
+        ksi.doScale(ks, bone)
+
+        # custom props?
+        ksi.doCustomProps(ks, bone)
+
+    # ----------------
+
+    # helper to add some bone's property to the Keying Set
+    def addProp(ksi, ks, bone, prop, index=-1, use_groups=True):
+        # add the property name to the base path
+        id_path = bone.path_from_id()
+        id_block = bone.id_data
+
+        if prop.startswith('['):
+            # custom properties
+            path = id_path + prop
+        else:
+            # standard transforms/properties
+            path = path_add_property(id_path, prop)
+
+        # add Keying Set entry for this...
+        if use_groups:
+            ks.paths.add(id_block, path, index, group_method='NAMED', group_name=bone.name)
+        else:
+            ks.paths.add(id_block, path, index)
+
+    # ----------------
+
+    # location properties
+    def doLoc(ksi, ks, bone):
+        if bone.lock_location == (False, False, False):
+            ksi.addProp(ks, bone, "location")
+        else:
+            for i in range(3):
+                if not bone.lock_location[i]:
+                    ksi.addProp(ks, bone, "location", i)
+
+    # rotation properties
+    def doRot4d(ksi, ks, bone):
+        # rotation mode affects the property used
+        if bone.rotation_mode == 'QUATERNION':
+            prop = "rotation_quaternion"
+        elif bone.rotation_mode == 'AXIS_ANGLE':
+            prop = "rotation_axis_angle"
+
+        # add rotation properties if they will
+        if bone.lock_rotations_4d:
+            # can check individually
+            if (bone.lock_rotation == (False, False, False)) and (bone.lock_rotation_w == False):
+                ksi.addProp(ks, bone, prop)
+            else:
+                if bone.lock_rotation_w == False:
+                    ksi.addProp(ks, bone, prop, 0)  # w = 0
+
+                for i in range(3):
+                    if not bone.lock_rotation[i]:
+                        ksi.addProp(ks, bone, prop, i + 1)  # i + 1, since here x,y,z = 1,2,3, and w=0
+        elif True not in bone.lock_rotation:
+            # if axis-angle rotations get locked as eulers, then it's too messy to allow anything
+            # other than all open unless we keyframe the whole lot
+            ksi.addProp(ks, bone, prop)
+
+    def doRot3d(ksi, ks, bone):
+        if bone.lock_rotation == (False, False, False):
+            ksi.addProp(ks, bone, "rotation_euler")
+        else:
+            for i in range(3):
+                if not bone.lock_rotation[i]:
+                    ksi.addProp(ks, bone, "rotation_euler", i)
+
+    # scale properties
+    def doScale(ksi, ks, bone):
+        if bone.lock_scale == (0, 0, 0):
+            ksi.addProp(ks, bone, "scale")
+        else:
+            for i in range(3):
+                if not bone.lock_scale[i]:
+                    ksi.addProp(ks, bone, "scale", i)
+
+    # ----------------
+
+    # custom properties
+    def doCustomProps(ksi, ks, bone):
+        # go over all custom properties for bone
+        for prop, val in bone.items():
+            # ignore special "_RNA_UI" used for UI editing
+            if prop == "_RNA_UI":
+                continue
+
+            # for now, just add all of 'em
+            ksi.addProp(ks, bone, '["%s"]' % (prop))
 
 
 def register():
-    register = bpy.types.register
-    for cls in classes:
-        register(cls)
+    bpy.utils.register_module(__name__)
 
 
 def unregister():
-    unregister = bpy.types.unregister
-    for cls in classes:
-        unregister(cls)
+    bpy.utils.unregister_module(__name__)
+
 
 if __name__ == "__main__":
     register()
 
-############################### 
+###############################
index 44efc8f2ada582c7a277f700c8122a60187a60c1..10707734bc40cd497b3586b1dfaa1aaf4c62aa37 100644 (file)
@@ -23,28 +23,47 @@ import mathutils
 
 
 def add_object_align_init(context, operator):
+    space_data = context.space_data
+    if space_data.type != 'VIEW_3D':
+        space_data = None
 
-    if operator and operator.properties.is_property_set("location") and operator.properties.is_property_set("rotation"):
+    # location
+    if operator and operator.properties.is_property_set("location"):
         location = mathutils.Matrix.Translation(mathutils.Vector(operator.properties.location))
-        rotation = mathutils.Euler(operator.properties.rotation).to_matrix().resize4x4()
     else:
-        # TODO, local view cursor!
-        location = mathutils.Matrix.Translation(context.scene.cursor_location)
+        if space_data:  # local view cursor is detected below
+            location = mathutils.Matrix.Translation(space_data.cursor_location)
+        else:
+            location = mathutils.Matrix.Translation(context.scene.cursor_location)
 
-        if context.user_preferences.edit.object_align == 'VIEW' and context.space_data.type == 'VIEW_3D':
-            rotation = context.space_data.region_3d.view_matrix.rotation_part().invert().resize4x4()
+        if operator:
+            operator.properties.location = location.to_translation()
+
+    # rotation
+    view_align = (context.user_preferences.edit.object_align == 'VIEW')
+    view_align_force = False
+    if operator:
+        if operator.properties.is_property_set("view_align"):
+            view_align = view_align_force = operator.view_align
+        else:
+            operator.properties.view_align = view_align
+
+    if operator and operator.properties.is_property_set("rotation") and not view_align_force:
+        rotation = mathutils.Euler(operator.properties.rotation).to_matrix().to_4x4()
+    else:
+        if view_align and space_data:
+            rotation = space_data.region_3d.view_matrix.to_3x3().inverted().to_4x4()
         else:
             rotation = mathutils.Matrix()
 
         # set the operator properties
         if operator:
-            operator.properties.location = location.translation_part()
             operator.properties.rotation = rotation.to_euler()
 
     return location * rotation
 
 
-def add_object_data(context, obdata, operator=None):
+def object_data_add(context, obdata, operator=None):
 
     scene = context.scene
 
@@ -65,6 +84,7 @@ def add_object_data(context, obdata, operator=None):
     obj_act = scene.objects.active
 
     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')
 
         obj_act.select = True
index 8cc91873b0ed5a7828c2d0b0dc8a332cbf82e4ac..464df870e87d6b4219a5adc75e6a31acbbeed6ae 100644 (file)
 This module has utility functions for renaming
 rna values in fcurves and drivers.
 
-The main function to use is: update_data_paths(...) 
+The main function to use is: update_data_paths(...)
 """
 
 IS_TESTING = False
 
+
 class DataPathBuilder(object):
     __slots__ = ("data_path", )
     """ Dummy class used to parse fcurve and driver data paths.
@@ -37,7 +38,7 @@ class DataPathBuilder(object):
     def __getattr__(self, attr):
         str_value = ".%s" % attr
         return DataPathBuilder(self.data_path + (str_value, ))
-        
+
     def __getitem__(self, key):
         str_value = '["%s"]' % key
         return DataPathBuilder(self.data_path + (str_value, ))
@@ -51,7 +52,7 @@ class DataPathBuilder(object):
             if base is not Ellipsis:
                 try:
                     # this only works when running with an old blender
-                    # where the old path will resolve 
+                    # where the old path will resolve
                     base = eval("base" + item)
                 except:
                     base_new = Ellipsis
@@ -61,7 +62,7 @@ class DataPathBuilder(object):
                             try:
                                 print("base." + item_new)
                                 base_new = eval("base." + item_new)
-                                break # found, dont keep looking
+                                break  # found, dont keep looking
                             except:
                                 pass
 
@@ -77,7 +78,7 @@ import bpy
 
 def id_iter():
     type_iter = type(bpy.data.objects)
-    
+
     for attr in dir(bpy.data):
         data_iter = getattr(bpy.data, attr, None)
         if type(data_iter) == type_iter:
@@ -111,16 +112,17 @@ def classes_recursive(base_type, clss=None):
 
 
 def find_path_new(id_data, data_path, rna_update_dict, rna_update_from_map):
+    # note!, id_data can be ID type or a node tree
     # ignore ID props for now
     if data_path.startswith("["):
         return data_path
-    
+
     # recursive path fixing, likely will be one in most cases.
     data_path_builder = eval("DataPathBuilder(tuple())." + data_path)
     data_resolve = data_path_builder.resolve(id_data, rna_update_from_map)
 
     path_new = [pair[0] for pair in data_resolve]
-    
+
     # print(data_resolve)
     data_base = id_data
 
@@ -137,55 +139,60 @@ def find_path_new(id_data, data_path, rna_update_dict, rna_update_from_map):
 
         # set this as the base for further properties
         data_base = data
-    
-    data_path_new = "".join(path_new)[1:] # skip the first "."
+
+    data_path_new = "".join(path_new)[1:]  # skip the first "."
     return data_path_new
 
 
 def update_data_paths(rna_update):
     ''' rna_update triple [(class_name, from, to), ...]
     '''
-    
+
     # make a faster lookup dict
     rna_update_dict = {}
     for ren_class, ren_from, ren_to in rna_update:
         rna_update_dict.setdefault(ren_class, {})[ren_from] = ren_to
-        
+
     rna_update_from_map = {}
     for ren_class, ren_from, ren_to in rna_update:
         rna_update_from_map.setdefault(ren_from, []).append(ren_to)
 
     for id_data in id_iter():
-        anim_data = getattr(id_data, "animation_data", None)
-        if anim_data is None:
-            continue
-        
-        for fcurve in anim_data.drivers:
-            for var in fcurve.driver.variables:
-                if var.type == 'SINGLE_PROP':
-                    for tar in var.targets:
-                        id_data_other = tar.id
-                        data_path = tar.data_path
-                        
-                        if id_data_other and data_path:
-                            data_path_new = find_path_new(id_data_other, data_path, rna_update_dict, rna_update_from_map)
-                            # print(data_path_new)
-                            if data_path_new != data_path:
-                                if not IS_TESTING:
-                                    tar.data_path = data_path_new
-                                print("driver (%s): %s -> %s" % (id_data_other.name, data_path, data_path_new))
-                
-            
-        
-        for action in anim_data_actions(anim_data):
-            for fcu in action.fcurves:
-                data_path = fcu.data_path
-                data_path_new = find_path_new(id_data, data_path, rna_update_dict, rna_update_from_map)
-                # print(data_path_new)
-                if data_path_new != data_path:
-                    if not IS_TESTING:
-                        fcu.data_path = data_path_new
-                    print("fcurve (%s): %s -> %s" % (id_data.name, data_path, data_path_new))
+
+        # check node-trees too
+        anim_data_ls = [(id_data, getattr(id_data, "animation_data", None))]
+        node_tree = getattr(id_data, "node_tree", None)
+        if node_tree:
+            anim_data_ls.append((node_tree, node_tree.animation_data))
+
+        for anim_data_base, anim_data in anim_data_ls:
+            if anim_data is None:
+                continue
+
+            for fcurve in anim_data.drivers:
+                for var in fcurve.driver.variables:
+                    if var.type == 'SINGLE_PROP':
+                        for tar in var.targets:
+                            id_data_other = tar.id
+                            data_path = tar.data_path
+
+                            if id_data_other and data_path:
+                                data_path_new = find_path_new(id_data_other, data_path, rna_update_dict, rna_update_from_map)
+                                # print(data_path_new)
+                                if data_path_new != data_path:
+                                    if not IS_TESTING:
+                                        tar.data_path = data_path_new
+                                    print("driver (%s): %s -> %s" % (id_data_other.name, data_path, data_path_new))
+
+            for action in anim_data_actions(anim_data):
+                for fcu in action.fcurves:
+                    data_path = fcu.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:
+                            fcu.data_path = data_path_new
+                        print("fcurve (%s): %s -> %s" % (id_data.name, data_path, data_path_new))
 
 
 if __name__ == "__main__":
index cba85d935ae620ea00a96c8c20f89bedc577da9f..5c636d3a0dfd90498b3819479abd6db1e5270f85 100644 (file)
@@ -26,9 +26,8 @@ data = _bpy.data
 context = _bpy.context
 
 # python modules
-from bpy import utils, path
-
-from bpy import ops as _ops_module
+from . import utils, path
+from . import ops as _ops_module
 
 # fake operator module
 ops = _ops_module.ops_fake_module
@@ -50,6 +49,10 @@ def _main():
     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")))
+
     # if "-d" in sys.argv: # Enable this to measure startup speed
     if 0:
         import cProfile
index 7a824ce2e6830ab682c1bfa35367d2857107e91c..f54b0a1fefc9fc376146e04f5038cee2e3a075b6 100644 (file)
@@ -115,14 +115,44 @@ class bpy_ops_submodule_op(object):
     def _get_doc(self):
         return op_as_string(self.idname())
 
+    @staticmethod
+    def _parse_args(args):
+        C_dict = None
+        C_exec = 'EXEC_DEFAULT'
+
+        if len(args) == 0:
+            pass
+        elif len(args) == 1:
+            if type(args[0]) != str:
+                C_dict = args[0]
+            else:
+                C_exec = args[0]
+        elif len(args) == 2:
+            C_exec, C_dict = args
+        else:
+            raise ValueError("1 or 2 args execution context is supported")
+
+        return C_dict, C_exec
+
+    @staticmethod
+    def _scene_update(context):
+        scene = context.scene
+        if scene:  # None in backgroud mode
+            scene.update()
+        else:
+            import bpy
+            for scene in bpy.data.scenes:
+                scene.update()
+
     __doc__ = property(_get_doc)
 
     def __init__(self, module, func):
         self.module = module
         self.func = func
 
-    def poll(self, context=None):
-        return op_poll(self.idname_py(), context)
+    def poll(self, *args):
+        C_dict, C_exec = __class__._parse_args(args)
+        return op_poll(self.idname_py(), C_dict, C_exec)
 
     def idname(self):
         # submod.foo -> SUBMOD_OT_foo
@@ -133,42 +163,23 @@ class bpy_ops_submodule_op(object):
         return self.module + "." + self.func
 
     def __call__(self, *args, **kw):
+        import bpy
+        context = bpy.context
 
         # Get the operator from blender
-        if len(args) > 2:
-            raise ValueError("1 or 2 args execution context is supported")
+        wm = context.window_manager
 
-        C_dict = None
+        # run to account for any rna values the user changes.
+        __class__._scene_update(context)
 
         if args:
-
-            C_exec = 'EXEC_DEFAULT'
-
-            if len(args) == 2:
-                C_exec = args[0]
-                C_dict = args[1]
-            else:
-                if type(args[0]) != str:
-                    C_dict = args[0]
-                else:
-                    C_exec = args[0]
-
-            if len(args) == 2:
-                C_dict = args[1]
-
+            C_dict, C_exec = __class__._parse_args(args)
             ret = op_call(self.idname_py(), C_dict, kw, C_exec)
-
         else:
-            ret = op_call(self.idname_py(), C_dict, kw)
+            ret = op_call(self.idname_py(), None, kw)
 
-        if 'FINISHED' in ret:
-            import bpy
-            scene = bpy.context.scene
-            if scene:  # None in backgroud mode
-                scene.update()
-            else:
-                for scene in bpy.data.scenes:
-                    scene.update()
+        if 'FINISHED' in ret and context.window_manager == wm:
+            __class__._scene_update(context)
 
         return ret
 
@@ -182,8 +193,16 @@ class bpy_ops_submodule_op(object):
         import bpy
         idname = self.idname()
         as_string = op_as_string(idname)
-        descr = getattr(bpy.types, idname).bl_rna.description
-        return as_string + "\n" + descr
+        op_class = getattr(bpy.types, idname)
+        descr = op_class.bl_rna.description
+        # XXX, workaround for not registering
+        # every __doc__ to save time on load.
+        if not descr:
+            descr = op_class.__doc__
+            if not descr:
+                descr = ""
+
+        return "# %s\n%s" % (descr, as_string)
 
     def __str__(self):  # used for print(...)
         return "<function bpy.ops.%s.%s at 0x%x'>" % \
index 92d2533c2c1fab4dac09a512d521f97a413f62a0..9a29b713882b5985152712756dc9f9fa3c88779c 100644 (file)
@@ -27,12 +27,15 @@ import bpy as _bpy
 import os as _os
 
 
-def abspath(path):
+def abspath(path, start=None):
     """
     Returns the absolute path relative to the current blend file using the "//" prefix.
+
+    :arg start: Relative to this path, when not set the current filename is used.
+    :type start: string
     """
     if path.startswith("//"):
-        return _os.path.join(_os.path.dirname(_bpy.data.filepath), path[2:])
+        return _os.path.join(_os.path.dirname(_bpy.data.filepath if start is None else start), path[2:])
 
     return path
 
@@ -52,6 +55,17 @@ def relpath(path, start=None):
     return path
 
 
+def is_subdir(path, directory):
+    """
+    Returns true if *path* in a subdirectory of *directory*.
+    Both paths must be absolute.
+    """
+    from os.path import normpath, normcase
+    path = normpath(normcase(path))
+    directory = normpath(normcase(directory))
+    return path.startswith(directory)
+
+
 def clean_name(name, replace="_"):
     """
     Returns a name with characters replaced that may cause problems under various circumstances, such as writing to a file.
@@ -99,6 +113,13 @@ def display_name(name):
         return name_base
 
 
+def display_name_from_filepath(name):
+    """
+    Returns the path stripped of directort and extension, ensured to be utf8 compatible.
+    """
+    return _os.path.splitext(_os.path.basename(name))[0].encode("utf8", "replace").decode("utf8")
+
+
 def resolve_ncase(path):
     """
     Resolve a case insensitive path on a case sensitive system,
@@ -108,7 +129,7 @@ def resolve_ncase(path):
     import os
 
     def _ncase_path_found(path):
-        if path == "" or os.path.exists(path):
+        if not path or os.path.exists(path):
             return path, True
 
         filename = os.path.basename(path)  # filename may be a directory or a file
@@ -192,7 +213,9 @@ def module_names(path, recursive=False):
     modules = []
 
     for filename in sorted(_os.listdir(path)):
-        if filename.endswith(".py") and filename != "__init__.py":
+        if filename == "modules":
+            pass  # XXX, hard coded exception.
+        elif filename.endswith(".py") and filename != "__init__.py":
             fullpath = join(path, filename)
             modules.append((filename[0:-3], fullpath))
         elif ("." not in filename):
index 1792425268b45aa2899f4dfd4e383d3a5b53478c..e3e93203235251922e8346116c7a24aa7701a04d 100644 (file)
@@ -23,12 +23,16 @@ This module contains utility functions specific to blender but
 not assosiated with blenders internal data.
 """
 
-import bpy as _bpy
-import os as _os
-import sys as _sys
+from _bpy import register_class
+from _bpy import unregister_class
 
 from _bpy import blend_paths
 from _bpy import script_paths as _bpy_script_paths
+from _bpy import user_resource as _user_resource
+
+import bpy as _bpy
+import os as _os
+import sys as _sys
 
 
 def _test_import(module_name, loaded_modules):
@@ -99,9 +103,6 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
     import traceback
     import time
 
-    # must be set back to True on exits
-    _bpy_types._register_immediate = False
-
     t_main = time.time()
 
     loaded_modules = set()
@@ -111,7 +112,6 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
 
     if reload_scripts:
         _bpy_types.TypeMap.clear()
-        _bpy_types.PropertiesMap.clear()
 
         # just unload, dont change user defaults, this means we can sync to reload.
         # note that they will only actually reload of the modification time changes.
@@ -120,7 +120,6 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
             addon_disable(module_name, default_set=False)
 
     def register_module_call(mod):
-        _bpy_types._register_module(mod.__name__)
         register = getattr(mod, "register", None)
         if register:
             try:
@@ -131,7 +130,6 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
             print("\nWarning! '%s' has no register function, this is now a requirement for registerable scripts." % mod.__file__)
 
     def unregister_module_call(mod):
-        _bpy_types._unregister_module(mod.__name__)
         unregister = getattr(mod, "unregister", None)
         if unregister:
             try:
@@ -140,6 +138,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
                 traceback.print_exc()
 
     def test_reload(mod):
+        import imp
         # reloading this causes internal errors
         # because the classes from this module are stored internally
         # possibly to refresh internal references too but for now, best not to.
@@ -147,7 +146,7 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
             return mod
 
         try:
-            return reload(mod)
+            return imp.reload(mod)
         except:
             traceback.print_exc()
 
@@ -197,18 +196,14 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
                 for mod in modules_from_path(path, loaded_modules):
                     test_register(mod)
 
-    _bpy_types._register_immediate = True
-
     # deal with addons seperately
-    addon_reset_all()
-
+    addon_reset_all(reload_scripts)
 
     # run the active integration preset
     filepath = preset_find(_bpy.context.user_preferences.inputs.active_keyconfig, "keyconfig")
     if filepath:
         keyconfig_set(filepath)
 
-
     if reload_scripts:
         import gc
         print("gc.collect() -> %d" % gc.collect())
@@ -339,7 +334,14 @@ def addon_check(module_name):
     loaded_default = module_name in _bpy.context.user_preferences.addons
 
     mod = _sys.modules.get(module_name)
-    loaded_state = mod and getattr(mod, "__addon_enabled__")
+    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
 
@@ -358,15 +360,11 @@ def addon_enable(module_name, default_set=True):
     import os
     import sys
     import bpy_types as _bpy_types
-
-
-    _bpy_types._register_immediate = False
+    import imp
 
     def handle_error():
         import traceback
         traceback.print_exc()
-        _bpy_types._register_immediate = True
-
 
     # reload if the mtime changes
     mod = sys.modules.get(module_name)
@@ -378,7 +376,7 @@ def addon_enable(module_name, default_set=True):
             print("module changed on disk:", mod.__file__, "reloading...")
 
             try:
-                reload(mod)
+                imp.reload(mod)
             except:
                 handle_error()
                 del sys.modules[module_name]
@@ -396,19 +394,13 @@ def addon_enable(module_name, default_set=True):
         return None
 
     # 2) try register collected modules
-    try:
-        _bpy_types._register_module(module_name)
-    except:
-        handle_error()
-        del sys.modules[module_name]
-        return None
+    # removed, addons need to handle own registration now.
 
     # 3) try run the modules register function
     try:
         mod.register()
     except:
         handle_error()
-        _bpy_types._unregister_module(module_name)
         del sys.modules[module_name]
         return None
 
@@ -419,12 +411,11 @@ def addon_enable(module_name, default_set=True):
         if not ext:
             ext = _bpy.context.user_preferences.addons.new()
             ext.module = module_name
-    
-    _bpy_types._register_immediate = True
 
     mod.__addon_enabled__ = True
 
-    print("\tbpy.utils.addon_enable", mod.__name__)
+    if _bpy.app.debug:
+        print("\tbpy.utils.addon_enable", mod.__name__)
 
     return mod
 
@@ -447,7 +438,6 @@ def addon_disable(module_name, default_set=True):
         mod.__addon_enabled__ = False
 
         try:
-            _bpy_types._unregister_module(module_name, free=False)  # dont free because we may want to enable again.
             mod.unregister()
         except:
             traceback.print_exc()
@@ -462,21 +452,37 @@ def addon_disable(module_name, default_set=True):
             addon = addons.get(module_name)
             if addon:
                 addons.remove(addon)
-    
-    print("\tbpy.utils.addon_disable", module_name)
+
+    if _bpy.app.debug:
+        print("\tbpy.utils.addon_disable", module_name)
 
 
-def addon_reset_all():
+def addon_reset_all(reload_scripts=False):
     """
     Sets the addon state based on the user preferences.
     """
+    import imp
 
-    paths = script_paths("addons") + script_paths("addons_contrib")
+    # 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:
@@ -485,12 +491,13 @@ def addon_reset_all():
                 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
-    
+
     for directory in preset_paths(preset_path):
-        
+
         if display_name:
             filename = ""
             for fn in _os.listdir(directory):
@@ -533,8 +540,91 @@ def keyconfig_set(filepath):
             keyconfigs.remove(kc_dupe)
         else:
             break
-    
+
     kc_new.name = name
     keyconfigs.active = kc_new
 
 
+def user_resource(type, path="", create=False):
+    """
+    Return a user resource path (normally from the users home directory).
+
+    :arg type: Resource type in ['DATAFILES', 'CONFIG', 'SCRIPTS', 'AUTOSAVE'].
+    :type type: string
+    :arg subdir: Optional subdirectory.
+    :type subdir: string
+    :arg create: Treat the path as a directory and create it if its not existing.
+    :type create: boolean
+    :return: a path.
+    :rtype: string
+    """
+
+    target_path = _user_resource(type, path)
+
+    if create:
+        # should always be true.
+        if target_path:
+            # create path if not existing.
+            if not _os.path.exists(target_path):
+                try:
+                    _os.makedirs(target_path)
+                except:
+                    import traceback
+                    traceback.print_exc()
+                    target_path = ""
+            elif not _os.path.isdir(target_path):
+                print("Path %r found but isn't a directory!" % target_path)
+                target_path = ""
+
+    return target_path
+
+
+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 = cls_weakref()
+
+        if cls is None:
+            del typemap_list[i]
+        else:
+            if is_registered == ("bl_rna" in cls.__dict__):
+                yield (cls, path, line)
+            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):
+        if verbose:
+            print("    %s of %s:%s" % (cls, path, line))
+        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)
+            traceback.print_exc()
+    if verbose:
+        print("done.\n")
+    if "cls" not in locals():
+        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):
+        if verbose:
+            print("    %s of %s:%s" % (cls, path, line))
+        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)
+            traceback.print_exc()
+    if verbose:
+        print("done.\n")
\ No newline at end of file
index 261165d883010acaaf6786d54b3dc2c35739db2e..4eb712a65ccc59d467a463f5fb941542ed8bd9d0 100644 (file)
@@ -142,19 +142,19 @@ class _GenericBone:
     def x_axis(self):
         """ Vector pointing down the x-axis of the bone.
         """
-        return self.matrix.rotation_part() * Vector((1.0, 0.0, 0.0))
+        return Vector((1.0, 0.0, 0.0)) * self.matrix.to_3x3()
 
     @property
     def y_axis(self):
         """ Vector pointing down the x-axis of the bone.
         """
-        return self.matrix.rotation_part() * Vector((0.0, 1.0, 0.0))
+        return Vector((0.0, 1.0, 0.0)) * self.matrix.to_3x3()
 
     @property
     def z_axis(self):
         """ Vector pointing down the x-axis of the bone.
         """
-        return self.matrix.rotation_part() * Vector((0.0, 0.0, 1.0))
+        return Vector((0.0, 0.0, 1.0)) * self.matrix.to_3x3()
 
     @property
     def basename(self):
@@ -258,15 +258,15 @@ class _GenericBone:
         return bones
 
 
-class PoseBone(StructRNA, _GenericBone):
+class PoseBone(StructRNA, _GenericBone, metaclass=StructMetaIDProp):
     __slots__ = ()
 
 
-class Bone(StructRNA, _GenericBone):
+class Bone(StructRNA, _GenericBone, metaclass=StructMetaIDProp):
     __slots__ = ()
 
 
-class EditBone(StructRNA, _GenericBone):
+class EditBone(StructRNA, _GenericBone, metaclass=StructMetaIDProp):
     __slots__ = ()
 
     def align_orientation(self, other):
@@ -284,13 +284,13 @@ class EditBone(StructRNA, _GenericBone):
         Expects a 4x4 or 3x3 matrix.
         """
         from mathutils import Vector
-        z_vec = self.matrix.rotation_part() * Vector((0.0, 0.0, 1.0))
-        self.tail = matrix * self.tail
-        self.head = matrix * self.head
+        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(matrix * z_vec)
+        self.align_roll(z_vec * matrix)
 
 
 def ord_ind(i1, i2):
@@ -302,18 +302,25 @@ def ord_ind(i1, i2):
 class Mesh(bpy_types.ID):
     __slots__ = ()
 
-    def from_pydata(self, verts, edges, faces):
+    def from_pydata(self, vertices, edges, faces):
         """
         Make a mesh from a list of verts/edges/faces
         Until we have a nicer way to make geometry, use this.
+
+        :arg vertices: float triplets each representing (X, Y, Z) eg: [(0.0, 1.0, 0.5), ...].
+        :type vertices: iterable object
+        :arg edges: int pairs, each pair contains two indices to the *vertices* argument. eg: [(1, 2), ...]
+        :type edges: iterable object
+        :arg faces: iterator of faces, each faces contains three or four indices to the *vertices* argument. eg: [(5, 6, 8, 9), (1, 2, 3), ...]
+        :type faces: iterable object
         """
-        self.vertices.add(len(verts))
+        self.vertices.add(len(vertices))
         self.edges.add(len(edges))
         self.faces.add(len(faces))
 
-        verts_flat = [f for v in verts for f in v]
-        self.vertices.foreach_set("co", verts_flat)
-        del verts_flat
+        vertices_flat = [f for v in vertices for f in v]
+        self.vertices.foreach_set("co", vertices_flat)
+        del vertices_flat
 
         edges_flat = [i for e in edges for i in e]
         self.edges.foreach_set("vertices", edges_flat)
@@ -326,7 +333,7 @@ class Mesh(bpy_types.ID):
                 else:
                     return f[0], f[1], f[2], 0
             elif f[2] == 0 or f[3] == 0:
-                return f[3], f[0], f[1], f[2]
+                return f[2], f[3], f[0], f[1]
             return f
 
         faces_flat = [v for f in faces for v in treat_face(f)]
@@ -543,85 +550,34 @@ class Text(bpy_types.ID):
         import bpy
         return tuple(obj for obj in bpy.data.objects if self in [cont.text for cont in obj.game.controllers if cont.type == 'PYTHON'])
 
-import collections
-
+# values are module: [(cls, path, line), ...]
 TypeMap = {}
-# Properties (IDPropertyGroup) are different from types because they need to be registered
-# before adding sub properties to them, so they are registered on definition
-# and unregistered on unload
-PropertiesMap = {}
-
-# Using our own loading function we set this to false
-# so when running a script directly in the text editor
-# registers moduals instantly.
-_register_immediate = True
-
-
-def _unregister_module(module, free=True):
-    for t in TypeMap.get(module, ()):
-        try:
-            bpy_types.unregister(t)
-        except:
-            import traceback
-            print("bpy.utils._unregister_module(): Module '%s' failed to unregister class '%s.%s'" % (module, t.__module__, t.__name__))
-            traceback.print_exc()
-
-    if free == True and module in TypeMap:
-        del TypeMap[module]
-
-    for t in PropertiesMap.get(module, ()):
-        try:
-            bpy_types.unregister(t)
-        except:
-            import traceback
-            print("bpy.utils._unload_module(): Module '%s' failed to unregister class '%s.%s'" % (module, t.__module__, t.__name__))
-            traceback.print_exc()
-
-    if free == True and module in PropertiesMap:
-        del PropertiesMap[module]
-
-
-def _register_module(module):
-    for t in TypeMap.get(module, ()):
-        try:
-            bpy_types.register(t)
-        except:
-            import traceback
-            import sys
-            print("bpy.utils._register_module(): '%s' failed to register class '%s.%s'" % (sys.modules[module].__file__, t.__module__, t.__name__))
-            traceback.print_exc()
 
 
 class RNAMeta(type):
-    @classmethod
-    def _register_immediate(cls):
-        return _register_immediate
-
     def __new__(cls, name, bases, classdict, **args):
         result = type.__new__(cls, name, bases, classdict)
         if bases and bases[0] != StructRNA:
+            import traceback
+            import weakref
             module = result.__module__
 
-            ClassMap = TypeMap
-
-            # Register right away if needed
-            if cls._register_immediate():
-                bpy_types.register(result)
-                ClassMap = PropertiesMap
-
             # first part of packages only
             if "." in module:
                 module = module[:module.index(".")]
 
-            ClassMap.setdefault(module, []).append(result)
+            sf = traceback.extract_stack(limit=2)[0]
+
+            TypeMap.setdefault(module, []).append((weakref.ref(result), sf[0], sf[1]))
 
         return result
 
 
-class RNAMetaRegister(RNAMeta, StructMetaIDProp):
-    @classmethod
-    def _register_immediate(cls):
-        return True
+import collections
+
+
+class RNAMetaIDProp(RNAMeta, StructMetaIDProp):
+    pass
 
 
 class OrderedMeta(RNAMeta):
@@ -638,7 +594,7 @@ class OrderedMeta(RNAMeta):
 # with doc generation 'self.properties.bl_rna.properties' can fail
 class Operator(StructRNA, metaclass=OrderedMeta):
     __slots__ = ()
-    
+
     def __getattribute__(self, attr):
         properties = StructRNA.path_resolve(self, "properties")
         bl_rna = getattr(properties, "bl_rna", None)
@@ -650,16 +606,22 @@ class Operator(StructRNA, metaclass=OrderedMeta):
         properties = StructRNA.path_resolve(self, "properties")
         bl_rna = getattr(properties, "bl_rna", None)
         if bl_rna and attr in bl_rna.properties:
-            setattr(properties, attr, value)
+            return setattr(properties, attr, value)
         return super().__setattr__(attr, value)
 
     def __delattr__(self, attr):
         properties = StructRNA.path_resolve(self, "properties")
         bl_rna = getattr(properties, "bl_rna", None)
         if bl_rna and attr in bl_rna.properties:
-            delattr(properties, attr)
+            return delattr(properties, attr)
         return super().__delattr__(attr)
 
+    def as_keywords(self, ignore=()):
+        """ Return a copy of the properties as a dictionary.
+        """
+        ignore = ignore + ("rna_type",)
+        return {attr: getattr(self, attr) for attr in self.properties.rna_type.properties.keys() if attr not in ignore}
+
 
 class Macro(StructRNA, metaclass=OrderedMeta):
     # bpy_types is imported before ops is defined
@@ -672,7 +634,7 @@ class Macro(StructRNA, metaclass=OrderedMeta):
         return ops.macro_define(self, opname)
 
 
-class IDPropertyGroup(StructRNA, metaclass=RNAMetaRegister):
+class IDPropertyGroup(StructRNA, metaclass=RNAMetaIDProp):
         __slots__ = ()
 
 
@@ -680,6 +642,10 @@ class RenderEngine(StructRNA, metaclass=RNAMeta):
     __slots__ = ()
 
 
+class KeyingSetInfo(StructRNA, metaclass=RNAMeta):
+    __slots__ = ()
+
+
 class _GenericUI:
     __slots__ = ()
 
@@ -691,7 +657,12 @@ class _GenericUI:
 
             def draw_ls(self, context):
                 for func in draw_ls._draw_funcs:
-                    func(self, context)
+                    # so bad menu functions dont stop the entire menu from drawing.
+                    try:
+                        func(self, context)
+                    except:
+                        import traceback
+                        traceback.print_exc()
 
             draw_funcs = draw_ls._draw_funcs = [cls.draw]
             cls.draw = draw_ls
@@ -739,7 +710,7 @@ class Menu(StructRNA, _GenericUI, metaclass=RNAMeta):
         import bpy.utils
 
         layout = self.layout
-        
+
         if not searchpaths:
             layout.label("* Missing Paths *")
 
index efd2ed85accc40b173eb6bf437849eada1ad1139..97cb14822c4e5f55cefafb26e31c372962ce87af 100644 (file)
@@ -1,17 +1,22 @@
 # Copyright (c) 2009 www.stani.be (GPL license)
 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
+# ##### BEGIN GPL LICENSE BLOCK #####
 #
-# 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 Lesser General Public License for more details.
+#  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.
 #
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#  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>
 
index 87fac9f4c0759bc37881a73ac40b23ae058b0620..29187297707eafb96d7ee5f3c6ec7efc9f043a04 100644 (file)
@@ -1,17 +1,22 @@
 # Copyright (c) 2009 www.stani.be (GPL license)
 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
+# ##### BEGIN GPL LICENSE BLOCK #####
 #
-# 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 Lesser General Public License for more details.
+#  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.
 #
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#  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-80 compliant>
 
@@ -168,7 +173,10 @@ def complete(line, cursor, namespace):
     'abs(number) -> number\\nReturn the absolute value of the argument.'
     """
     matches = []
+    word = ''
+    scrollback = ''
     match = RE_DEF_COMPLETE.search(line[:cursor])
+
     if match:
         word = match.group(1)
         func_word = match.group(2)
@@ -176,7 +184,7 @@ def complete(line, cursor, namespace):
             func = eval(func_word, namespace)
         except Exception:
             func = None
-            scrollback = ''
+
         if func:
             doc = get_doc(func)
             argspec = get_argspec(func, doc=doc)
@@ -186,7 +194,5 @@ def complete(line, cursor, namespace):
             elif doc:
                 scrollback += '\n' + doc
             scrollback = reduce_newlines(scrollback)
-    else:
-        word = ''
-        scrollback = ''
+
     return matches, word, scrollback
index 4b50cf6deb822f3761b8d04dd5d8567c740d0d11..63f15d9cf77b21ae55f61020c1c30be0fb4f0903 100644 (file)
@@ -1,17 +1,22 @@
 # Copyright (c) 2009 Fernando Perez, www.stani.be (GPL license)
 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
+# ##### BEGIN GPL LICENSE BLOCK #####
 #
-# 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 Lesser General Public License for more details.
+#  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.
 #
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#  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 #####
 
 # Original copyright (see docstring):
 #*****************************************************************************
index 7a9fd331e4912861356d81bb03863ad097e7ae7c..a31280ebff042c8085e5bb01fbaf69985fa1a112 100644 (file)
@@ -1,17 +1,22 @@
 # Copyright (c) 2009 www.stani.be (GPL license)
 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
+# ##### BEGIN GPL LICENSE BLOCK #####
 #
-# 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 Lesser General Public License for more details.
+#  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.
 #
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#  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-80 compliant>
 
index 0f9acf9b6a94629c228c55393b4ed49e14a2e25f..9352d7c14e1943c315747cdb1c339e860a8b7c15 100644 (file)
@@ -1,17 +1,22 @@
 # Copyright (c) 2009 www.stani.be (GPL license)
 
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
+# ##### BEGIN GPL LICENSE BLOCK #####
 #
-# 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 Lesser General Public License for more details.
+#  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.
 #
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#  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-80 compliant>
 
@@ -75,10 +80,10 @@ def complete(line, cursor, namespace, private=True):
         # unquoted word -> module or attribute completion
         word = re_unquoted_word.group(1)
         if RE_MODULE.match(line):
-            import complete_import
+            from . import complete_import
             matches = complete_import.complete(line)
         else:
-            import complete_namespace
+            from . import complete_namespace
             matches = complete_namespace.complete(word, namespace, private)
     else:
         # for now we don't have completers for strings
@@ -112,7 +117,7 @@ def expand(line, cursor, namespace, private=True):
     'abs(number) -> number\\nReturn the absolute value of the argument.'
     """
     if line[:cursor].strip().endswith('('):
-        import complete_calltip
+        from . import complete_calltip
         matches, word, scrollback = complete_calltip.complete(line,
             cursor, namespace)
         no_calltip = False
diff --git a/release/scripts/modules/image_utils.py b/release/scripts/modules/image_utils.py
new file mode 100644 (file)
index 0000000..d74c89a
--- /dev/null
@@ -0,0 +1,27 @@
+# ##### 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 image_load(filepath, dirpath, place_holder=False, recursive=False, convert_callback=None):
+    import bpy
+    try:
+        return bpy.data.images.load(filepath)
+    except SystemError:
+        return bpy.data.images.new("Untitled", 128, 128)
index eb9b2eaa90b34be4fe6133abd368e86082e3f05b..39b386691887fb267c292f6aed0de42a367ee8fb 100644 (file)
@@ -37,7 +37,7 @@ class ExportHelper:
 
             self.filepath = blend_filepath + self.filename_ext
 
-        context.window_manager.add_fileselect(self)
+        context.window_manager.fileselect_add(self)
         return {'RUNNING_MODAL'}
 
     def check(self, context):
@@ -53,7 +53,7 @@ class ImportHelper:
     filepath = StringProperty(name="File Path", description="Filepath used for importing the file", maxlen=1024, default="", subtype='FILE_PATH')
 
     def invoke(self, context, event):
-        context.window_manager.add_fileselect(self)
+        context.window_manager.fileselect_add(self)
         return {'RUNNING_MODAL'}
 
 
similarity index 63%
rename from release/scripts/keyingsets/keyingsets_utils.py
rename to release/scripts/modules/keyingsets_utils.py
index 901aa71529640b238557eb540ea475e10159e547..00ad45cf9bbbabfd1b766b04d186d4a4e4a64f01 100644 (file)
@@ -1,45 +1,81 @@
-# This file defines a set of methods that are useful for various 
+# ##### 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>
+
+# This file defines a set of methods that are useful for various
 # Relative Keying Set (RKS) related operations, such as: callbacks
-# for polling, iterator callbacks, and also generate callbacks. 
-# All of these can be used in conjunction with the others. 
+# for polling, iterator callbacks, and also generate callbacks.
+# All of these can be used in conjunction with the others.
+
+__all__ = [
+    "path_add_property",
+    "RKS_POLL_selected_objects",
+    "RKS_POLL_selected_bones",
+    "RKS_POLL_selected_items",
+    "RKS_ITER_selected_item",
+    "RKS_GEN_available",
+    "RKS_GEN_location",
+    "RKS_GEN_rotation",
+    "RKS_GEN_scaling",
+]
 
 import bpy
 
 ###########################
 # General Utilities
 
+
 # Append the specified property name on the the existing path
 def path_add_property(path, prop):
     if len(path):
-        return path + "." + prop;
+        return path + "." + prop
     else:
-        return prop;
+        return prop
 
 ###########################
 # Poll Callbacks
 
+
 # selected objects
 def RKS_POLL_selected_objects(ksi, context):
-    return context.active_object or len(context.selected_objects);
-    
+    return context.active_object or len(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 
+    # 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):
-            return True;
-    
-    # nothing selected 
-    return False;
+            return True
+
+    # nothing selected
+    return False
 
 
 # selected bones or objects
 def RKS_POLL_selected_items(ksi, context):
-    return RKS_POLL_selected_bones(ksi, context) or RKS_POLL_selected_objects(ksi, context);
+    return RKS_POLL_selected_bones(ksi, context) or RKS_POLL_selected_objects(ksi, context)
 
 ###########################
 # Iterator Callbacks
 
+
 # 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'):
@@ -52,34 +88,49 @@ def RKS_ITER_selected_item(ksi, context, ks):
 ###########################
 # Generate Callbacks
 
+
 # 'Available' F-Curves
 def RKS_GEN_available(ksi, context, ks, data):
-    # try to get the animation data associated with the closest 
+    # try to get the animation data associated with the closest
     # ID-block to the data (neither of which may exist/be easy to find)
     id_block = data.id_data
     adt = getattr(id_block, "animation_data", None)
 
     # there must also be an active action...
     if adt is None or adt.action is None:
-        return;
-        
-    # for each F-Curve, include an path to key it
+        return
+
+    # if we haven't got an ID-block as 'data', try to restrict
+    # paths added to only those which branch off from here
+    # i.e. for bones
+    if id_block != data:
+        basePath = data.path_from_id()
+    else:
+        basePath = None  # this is not needed...
+
+    # for each F-Curve, include a path to key it
     # NOTE: we don't need to set the group settings here
     for fcu in adt.action.fcurves:
-        ks.paths.add(id_block, fcu.data_path, index=fcu.array_index)
-    
+        if basePath:
+            if basePath in fcu.data_path:
+                ks.paths.add(id_block, fcu.data_path, index=fcu.array_index)
+        else:
+            ks.paths.add(id_block, fcu.data_path, index=fcu.array_index)
+
 # ------
 
+
 # get ID block and based ID path for transform generators
+# private function
 def get_transform_generators_base_info(data):
-    # ID-block for the data 
+    # ID-block for the data
     id_block = data.id_data
-    
+
     # get base path and grouping method/name
     if isinstance(data, bpy.types.ID):
         # no path in this case
         path = ""
-        
+
         # data on ID-blocks directly should get grouped by the KeyingSet
         grouping = None
     else:
@@ -89,29 +140,31 @@ def get_transform_generators_base_info(data):
         # try to use the name of the data element to group the F-Curve
         # else fallback on the KeyingSet name
         grouping = getattr(data, "name", None)
-        
+
     # return the ID-block and the path
     return id_block, path, grouping
 
-# Location 
+
+# Location
 def RKS_GEN_location(ksi, context, ks, data):
     # get id-block and path info
     id_block, base_path, grouping = get_transform_generators_base_info(data)
-    
+
     # add the property name to the base path
     path = path_add_property(base_path, "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)
 
-# Rotation 
+
+# Rotation
 def RKS_GEN_rotation(ksi, context, ks, data):
     # get id-block and path info
-    id_block, base_path, grouping= get_transform_generators_base_info(data)
-    
+    id_block, base_path, grouping = 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':
@@ -120,40 +173,24 @@ def RKS_GEN_rotation(ksi, context, ks, data):
         path = path_add_property(base_path, "rotation_axis_angle")
     else:
         path = path_add_property(base_path, "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)
 
-# Scaling 
+
+# Scaling
 def RKS_GEN_scaling(ksi, context, ks, data):
     # get id-block and path info
-    id_block, base_path, grouping= get_transform_generators_base_info(data)
-    
+    id_block, base_path, grouping = get_transform_generators_base_info(data)
+
     # add the property name to the base path
     path = path_add_property(base_path, "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)
-
-###########################
-# Un-needed stuff which is here to just shut up the warnings...
-
-classes = []
-
-def register():
-    pass
-
-
-def unregister():
-    pass
-
-if __name__ == "__main__":
-    register()
-
-###########################
diff --git a/release/scripts/modules/rigify/__init__.py b/release/scripts/modules/rigify/__init__.py
deleted file mode 100644 (file)
index 98d9bb2..0000000
+++ /dev/null
@@ -1,560 +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 mathutils import Vector
-
-# TODO, have these in a more general module
-from rna_prop_ui import rna_idprop_ui_prop_get
-SPECIAL_TYPES = "root",
-LAYER_TYPES = "main", "extra", "ik", "fk"
-
-ORG_LAYERS = [n == 31 for n in range(0, 32)]
-MCH_LAYERS = [n == 30 for n in range(0, 32)]
-DEF_LAYERS = [n == 29 for n in range(0, 32)]
-ROOT_LAYERS = [n == 28 for n in range(0, 32)]
-
-ORG_PREFIX = "ORG-"
-MCH_PREFIX = "MCH-"
-DEF_PREFIX = "DEF-"
-
-WGT_PREFIX = "WGT-"
-
-
-class RigifyError(Exception):
-    """Exception raised for errors in the metarig.
-    """
-
-    def __init__(self, message):
-        self.message = message
-
-    def __str__(self):
-        return repr(self.message)
-
-
-def submodule_func_from_type(bone_type):
-    type_pair = bone_type.split(".")
-
-    # 'leg.ik' will look for an ik function in the leg module
-    # 'leg' will look up leg.main
-    if len(type_pair) == 1:
-        type_pair = type_pair[0], "main"
-
-    type_name, func_name = type_pair
-
-    # from rigify import leg
-    try:
-        submod = __import__(name="%s.%s" % (__package__, type_name), fromlist=[type_name])
-    except ImportError:
-        raise RigifyError("python module for type '%s' not found" % type_name)
-
-    reload(submod)
-    return type_name, submod, getattr(submod, func_name)
-
-
-def get_submodule_types():
-    import os
-    submodules = []
-    files = os.listdir(os.path.dirname(__file__))
-    for f in files:
-        if not f.startswith("_") and f.endswith(".py"):
-            submodules.append(f[:-3])
-
-    return sorted(submodules)
-
-
-def get_bone_type_options(pbone, type_name):
-    options = {}
-    bone_name = pbone.name
-    for key, value in pbone.items():
-        key_pair = key.rsplit(".")
-        # get all bone properties
-        """"
-        if key_pair[0] == type_name:
-            if len(key_pair) != 2:
-                raise RigifyError("option error for bone '%s', property name was not a pair '%s'" % (bone_name, key_pair))
-            options[key_pair[1]] = value
-        """
-        options[key] = value
-
-    return options
-
-
-def get_layer_dict(options):
-    '''
-    Extracts layer info from a bone options dict
-    defaulting to the layer index if not set.
-    '''
-    layer_default = [False] * 32
-    result = {}
-    for i, layer_type in enumerate(LAYER_TYPES):
-        # no matter if its not defined
-        layer_index = options.get("layer_" + layer_type, i + 2)
-        layer = layer_default[:]
-        layer[layer_index-1] = True
-        result[layer_type] = layer
-    return result
-
-
-def validate_rig(context, obj):
-    '''
-    Makes no changes
-    only runs the metarig definitions and reports errors
-    '''
-    type_found = False
-
-    for pbone in obj.pose.bones:
-        bone_name = pbone.name
-        bone_type = pbone.get("type", "")
-
-        if bone_type:
-            bone_type_list = [bt for bt in bone_type.replace(",", " ").split()]
-        else:
-            bone_type_list = []
-
-        for bone_type in bone_type_list:
-            if bone_type.split(".")[0] in SPECIAL_TYPES:
-                continue
-
-            type_name, submod, type_func = submodule_func_from_type(bone_type)
-            reload(submod)
-            submod.metarig_definition(obj, bone_name)
-            type_found = True
-
-            get_bone_type_options(pbone, bone_type)
-
-        # missing, - check for duplicate root bone.
-
-    if not type_found:
-        raise RigifyError("This rig has no 'type' properties defined on any pose bones, nothing to do")
-
-
-def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
-    '''
-    Main function for generating
-    '''
-    from collections import OrderedDict
-    import rigify_utils
-    reload(rigify_utils)
-
-    print("Begin...")
-
-    # Not needed but catches any errors before duplicating
-    validate_rig(context, obj_orig)
-
-    use_global_undo = context.user_preferences.edit.use_global_undo
-    context.user_preferences.edit.use_global_undo = False
-    mode_orig = context.mode
-    rest_backup = obj_orig.data.pose_position
-    obj_orig.data.pose_position = 'REST'
-
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-    scene = context.scene
-
-    # Check if the generated rig already exists, so we can
-    # regenerate in the same object.  If not, create a new
-    # object to generate the rig in.
-    print("Fetch rig.")
-    try:
-        name = obj_orig["rig_object_name"]
-    except KeyError:
-        name = "rig"
-
-    try:
-        obj = scene.objects[name]
-    except KeyError:
-        obj = bpy.data.objects.new(name, bpy.data.armatures.new(name))
-        scene.objects.link(obj)
-
-    obj.data.pose_position = 'POSE'
-
-    # Get rid of anim data in case the rig already existed
-    print("Clear rig animation data.")
-    obj.animation_data_clear()
-
-    # Select generated rig object
-    obj_orig.select = False
-    obj.select = True
-    scene.objects.active = obj
-
-    # Remove all bones from the generated rig armature.
-    bpy.ops.object.mode_set(mode='EDIT')
-    for bone in obj.data.edit_bones:
-        obj.data.edit_bones.remove(bone)
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-    # Create temporary duplicates for merging
-    temp_rig_1 = obj_orig.copy()
-    temp_rig_1.data = obj_orig.data.copy()
-    scene.objects.link(temp_rig_1)
-
-    temp_rig_2 = obj_orig.copy()
-    temp_rig_2.data = obj.data
-    scene.objects.link(temp_rig_2)
-
-    # Select the temp rigs for merging
-    for objt in scene.objects:
-        objt.select = False # deselect all objects
-    temp_rig_1.select = True
-    temp_rig_2.select = True
-    scene.objects.active = temp_rig_2
-
-    # Merge the temporary rigs
-    bpy.ops.object.join(context)
-
-    # Delete the second temp rig
-    bpy.ops.object.delete()
-
-    # Select the generated rig
-    for objt in scene.objects:
-        objt.select = False # deselect all objects
-    obj.select = True
-    scene.objects.active = obj
-
-    # Copy over the pose_bone properties
-    for bone in obj_orig.pose.bones:
-        bone_gen = obj.pose.bones[bone.name]
-
-        # Rotation mode and transform locks
-        bone_gen.rotation_mode = bone.rotation_mode
-        bone_gen.lock_rotation = tuple(bone.lock_rotation)
-        bone_gen.lock_rotation_w = bone.lock_rotation_w
-        bone_gen.lock_rotations_4d = bone.lock_rotations_4d
-        bone_gen.lock_location = tuple(bone.lock_location)
-        bone_gen.lock_scale = tuple(bone.lock_scale)
-
-        # Custom properties
-        for prop in bone.keys():
-            bone_gen[prop] = bone[prop]
-
-    # Copy over bone properties
-    for bone in obj_orig.data.bones:
-        bone_gen = obj.data.bones[bone.name]
-
-        # B-bone stuff
-        bone_gen.bbone_segments = bone.bbone_segments
-        bone_gen.bbone_in = bone.bbone_in
-        bone_gen.bbone_out = bone.bbone_out
-
-
-    # Create proxy deformation rig
-    # TODO: remove this
-    if META_DEF:
-        obj_def = obj_orig.copy()
-        obj_def.data = obj_orig.data.copy()
-        scene.objects.link(obj_def)
-
-    scene.update()
-    print("On to the real work.")
-
-    arm = obj.data
-
-    # prepend the ORG prefix to the bones, and create the base_names mapping
-    base_names = {}
-    bpy.ops.object.mode_set(mode='EDIT')
-    for bone in arm.edit_bones:
-        bone_name = bone.name
-        bone.name = ORG_PREFIX + bone_name
-        base_names[bone.name] = bone_name
-
-    # create root_bone
-    bpy.ops.object.mode_set(mode='EDIT')
-    edit_bone = obj.data.edit_bones.new("root")
-    root_bone = edit_bone.name
-    edit_bone.head = (0.0, 0.0, 0.0)
-    edit_bone.tail = (0.0, 1.0, 0.0)
-    edit_bone.roll = 0.0
-    edit_bone.layers = ROOT_LAYERS
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-    # key: bone name
-    # value: {type:definition, ...}
-    #    where type is the submodule name - leg, arm etc
-    #    and definition is a list of bone names
-    bone_definitions = {}
-
-    # key: bone name
-    # value: [functions, ...]
-    #    each function is from the module. eg leg.ik, arm.main
-    bone_typeinfos = {}
-
-    # key: bone name
-    # value: [new_bone_name, ...]
-    #   where each bone with a 'type' stores a list of bones that it created
-    #   ...needed so we can override the root parent
-    bone_genesis = {}
-
-
-    # inspect all bones and assign their definitions before modifying
-    for pbone in obj.pose.bones:
-        bone_name = pbone.name
-        bone_type = pbone.get("type", "")
-        if bone_type:
-            bone_type_list = [bt for bt in bone_type.replace(",", " ").split()]
-
-            # not essential but means running autorig again wont do anything
-            del pbone["type"]
-        else:
-            bone_type_list = []
-
-        for bone_type in bone_type_list:
-            type_name, submod, type_func = submodule_func_from_type(bone_type)
-            reload(submod)
-
-            bone_def_dict = bone_definitions.setdefault(bone_name, {})
-
-            # Only calculate bone definitions once
-            if type_name not in bone_def_dict:
-                bone_def_dict[type_name] = submod.metarig_definition(obj, bone_name)
-
-            bone_typeinfo = bone_typeinfos.setdefault(bone_name, [])
-            bone_typeinfo.append((type_name, type_func))
-
-
-    # sort bones, not needed but gives more pradictable execution which may be useful in rare cases
-    bones_sorted = obj.pose.bones.values()
-    bones_sorted.sort(key=lambda pbone: pbone.name) # first sort by names
-    bones_sorted.sort(key=lambda pbone: len(pbone.parent_recursive)) # parents before children
-
-    # now we have all the info about bones we can start operating on them
-    # for pbone in obj.pose.bones:
-    for pbone in bones_sorted:
-        bone_name = pbone.name
-        print(bone_name)
-        if bone_name not in bone_typeinfos:
-            continue
-
-        bone_def_dict = bone_definitions[bone_name]
-
-        # Only blend results from the same submodule, eg.
-        #    leg.ik and arm.fk could not be blended.
-        results = OrderedDict()
-
-        bone_names_pre = {bone.name for bone in arm.bones}
-
-        for type_name, type_func in bone_typeinfos[bone_name]:
-            print("    " + type_name)
-            # this bones definition of the current typeinfo
-            definition = bone_def_dict[type_name]
-            options = get_bone_type_options(pbone, type_name)
-
-            bpy.ops.object.mode_set(mode='EDIT')
-            ret = type_func(obj, definition, base_names, options)
-            bpy.ops.object.mode_set(mode='OBJECT')
-
-            if ret:
-                result_submod = results.setdefault(type_name, [])
-
-                if result_submod and len(result_submod[-1]) != len(ret):
-                    raise RigifyError("bone lists not compatible: %s, %s" % (result_submod[-1], ret))
-
-                result_submod.append(ret)
-
-        for result_submod in results.values():
-            # blend 2 chains
-            definition = bone_def_dict[type_name]
-
-            if len(result_submod) == 2:
-                blend_bone_list(obj, definition, result_submod[0], result_submod[1], target_bone=bone_name)
-
-
-        bone_names_post = {bone.name for bone in arm.bones}
-
-        # Store which bones were created from this one
-        bone_genesis[bone_name] = list(bone_names_post - bone_names_pre)
-
-    # need a reverse lookup on bone_genesis so as to know immediately
-    # where a bone comes from
-    bone_genesis_reverse = {}
-    '''
-    for bone_name, bone_children in bone_genesis.items():
-        for bone_child_name in bone_children:
-            bone_genesis_reverse[bone_child_name] = bone_name
-    '''
-
-
-    if root_bone:
-        # assign all new parentless bones to this
-
-        bpy.ops.object.mode_set(mode='EDIT')
-        root_ebone = arm.edit_bones[root_bone]
-        for ebone in arm.edit_bones:
-            bone_name = ebone.name
-            if ebone.parent is None:
-                ebone.parent = root_ebone
-            '''
-            if ebone.parent is None and bone_name not in base_names:
-                # check for override
-                bone_creator = bone_genesis_reverse[bone_name]
-                pbone_creator = obj.pose.bones[bone_creator]
-                root_bone_override = pbone_creator.get("root", "")
-
-                if root_bone_override:
-                    root_ebone_tmp = arm.edit_bones[root_bone_override]
-                else:
-                    root_ebone_tmp = root_ebone
-
-                ebone.use_connect = False
-                ebone.parent = root_ebone_tmp
-            '''
-
-        bpy.ops.object.mode_set(mode='OBJECT')
-
-
-    if META_DEF:
-        # for pbone in obj_def.pose.bones:
-        for bone_name, bone_name_new in base_names.items():
-            #pbone_from = bone_name
-            pbone = obj_def.pose.bones[bone_name_new]
-
-            con = pbone.constraints.new('COPY_ROTATION')
-            con.target = obj
-            con.subtarget = bone_name
-
-            if not pbone.bone.use_connect:
-                con = pbone.constraints.new('COPY_LOCATION')
-                con.target = obj
-                con.subtarget = bone_name
-
-        # would be 'REST' from when copied
-        obj_def.data.pose_position = 'POSE'
-
-    # todo - make a more generic system?
-    layer_tot = [False] * 32
-    layer_last = layer_tot[:]
-    layer_last[31] = True
-    layer_second_last = layer_tot[:]
-    layer_second_last[30] = True
-
-    for bone_name, bone in arm.bones.items():
-        bone.use_deform = False  # Non DEF bones shouldn't deform
-        if bone_name.startswith(ORG_PREFIX):
-            bone.layers = ORG_LAYERS
-        elif bone_name.startswith(MCH_PREFIX): # XXX fixme
-            bone.layers = MCH_LAYERS
-        elif bone_name.startswith(DEF_PREFIX): # XXX fixme
-            bone.layers = DEF_LAYERS
-            bone.use_deform = True
-        else:
-            # Assign bone appearance if there is a widget for it
-            obj.pose.bones[bone_name].custom_shape = context.scene.objects.get(WGT_PREFIX + bone_name)
-
-        layer_tot[:] = [max(lay) for lay in zip(layer_tot, bone.layers)]
-
-    # Only for demo'ing
-    layer_show = [a and not (b or c or d) for a, b, c, d in zip(layer_tot, ORG_LAYERS, MCH_LAYERS, DEF_LAYERS)]
-    arm.layers = layer_show
-
-
-    # obj.hide = True
-    obj.data.show_axes = False
-
-    bpy.ops.object.mode_set(mode=mode_orig)
-    obj_orig.data.pose_position = rest_backup
-    obj.data.pose_position = 'POSE'
-    obj_orig.data.pose_position = 'POSE'
-    context.user_preferences.edit.use_global_undo = use_global_undo
-
-    print("Done.\n")
-
-    return obj
-
-
-def generate_test(context, metarig_type="", GENERATE_FINAL=True):
-    import os
-    new_objects = []
-
-    scene = context.scene
-
-    def create_empty_armature(name):
-        armature = bpy.data.armatures.new(name)
-        obj_new = bpy.data.objects.new(name, armature)
-        scene.objects.link(obj_new)
-        scene.objects.active = obj_new
-        for obj in scene.objects:
-            obj.select = False
-        obj_new.select = True
-
-    for module_name in get_submodule_types():
-        if (metarig_type and module_name != metarig_type):
-            continue
-
-        # XXX workaround!, problem with updating the pose matrix.
-        if module_name == "delta":
-            continue
-
-        type_name, submodule, func = submodule_func_from_type(module_name)
-
-        metarig_template = getattr(submodule, "metarig_template", None)
-
-        if metarig_template:
-            create_empty_armature("meta_" + module_name) # sets active
-            metarig_template()
-            obj = context.active_object
-            obj.location = scene.cursor_location
-
-            if GENERATE_FINAL:
-                obj_new = generate_rig(context, obj)
-                new_objects.append((obj, obj_new))
-            else:
-                new_objects.append((obj, None))
-        else:
-            print("note: rig type '%s' has no metarig_template(), can't test this" % module_name)
-
-    return new_objects
-
-
-def generate_test_all(context, GRAPH=False):
-    import rigify
-    import rigify_utils
-    import graphviz_export
-    import os
-    reload(rigify)
-    reload(rigify_utils)
-    reload(graphviz_export)
-
-    new_objects = rigify.generate_test(context)
-
-    if GRAPH:
-        base_name = os.path.splitext(bpy.data.filepath)[0]
-        for obj, obj_new in new_objects:
-            for obj in (obj, obj_new):
-                fn = base_name + "-" + bpy.path.clean_name(obj.name)
-
-                path_dot = fn + ".dot"
-                path_png = fn + ".png"
-                saved = graphviz_export.graph_armature(obj, path_dot, CONSTRAINTS=True, DRIVERS=True)
-
-                #if saved:
-                #    os.system("dot -Tpng %s > %s; eog %s" % (path_dot, path_png, path_png))
-
-    i = 0
-    for obj, obj_new in new_objects:
-        obj.data.draw_type = 'STICK'
-        obj.location[1] += i
-        obj_new.location[1] += i
-        obj_new.select = False
-        obj.select = True
-        i += 4
-
-
-if __name__ == "__main__":
-    generate_rig(bpy.context, bpy.context.active_object)
diff --git a/release/scripts/modules/rigify/arm_biped.py b/release/scripts/modules/rigify/arm_biped.py
deleted file mode 100644 (file)
index ac878c3..0000000
+++ /dev/null
@@ -1,396 +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 math import radians, pi
-from rigify import RigifyError, ORG_PREFIX
-from rigify_utils import bone_class_instance, copy_bone_simple, add_pole_target_bone, add_stretch_to, blend_bone_list, get_side_name, get_base_name
-from rna_prop_ui import rna_idprop_ui_prop_get
-from mathutils import Vector
-
-METARIG_NAMES = "shoulder", "arm", "forearm", "hand"
-
-
-def metarig_template():
-    # generated by rigify.write_meta_rig
-    bpy.ops.object.mode_set(mode='EDIT')
-    obj = bpy.context.active_object
-    arm = obj.data
-    bone = arm.edit_bones.new('shoulder')
-    bone.head[:] = 0.0000, -0.0425, 0.0000
-    bone.tail[:] = 0.0942, -0.0075, 0.0333
-    bone.roll = -0.2227
-    bone.use_connect = False
-    bone = arm.edit_bones.new('upper_arm')
-    bone.head[:] = 0.1066, -0.0076, -0.0010
-    bone.tail[:] = 0.2855, 0.0206, -0.0104
-    bone.roll = 1.6152
-    bone.use_connect = False
-    bone.parent = arm.edit_bones['shoulder']
-    bone = arm.edit_bones.new('forearm')
-    bone.head[:] = 0.2855, 0.0206, -0.0104
-    bone.tail[:] = 0.4550, -0.0076, -0.0023
-    bone.roll = 1.5153
-    bone.use_connect = True
-    bone.parent = arm.edit_bones['upper_arm']
-    bone = arm.edit_bones.new('hand')
-    bone.head[:] = 0.4550, -0.0076, -0.0023
-    bone.tail[:] = 0.5423, -0.0146, -0.0131
-    bone.roll = -3.0083
-    bone.use_connect = True
-    bone.parent = arm.edit_bones['forearm']
-
-    bpy.ops.object.mode_set(mode='OBJECT')
-    pbone = obj.pose.bones['upper_arm']
-    pbone['type'] = 'arm_biped'
-
-
-def metarig_definition(obj, orig_bone_name):
-    mt = bone_class_instance(obj, METARIG_NAMES) # meta
-    mt.arm = orig_bone_name
-    mt.update()
-
-    mt.shoulder_p = mt.arm_p.parent
-
-    if not mt.shoulder_p:
-        raise RigifyError("could not find '%s' parent, skipping:" % orig_bone_name)
-
-    mt.shoulder = mt.shoulder_p.name
-
-    # We could have some bones attached, find the bone that has this as its 2nd parent
-    hands = []
-    for pbone in obj.pose.bones:
-        index = pbone.parent_index(mt.arm_p)
-        if index == 2 and pbone.bone.use_connect and pbone.bone.parent.use_connect:
-            hands.append(pbone)
-
-    if len(hands) != 1:
-        raise RigifyError("Found %s possible hands attached to this arm, expected 1 from bone: %s" % ([pbone.name for pbone in hands], orig_bone_name))
-
-    # first add the 2 new bones
-    mt.hand_p = hands[0]
-    mt.hand = mt.hand_p.name
-
-    mt.forearm_p = mt.hand_p.parent
-    mt.forearm = mt.forearm_p.name
-
-    return mt.names()
-
-
-def ik(obj, definitions, base_names, options):
-
-    arm = obj.data
-
-    mt = bone_class_instance(obj, METARIG_NAMES)
-    mt.shoulder, mt.arm, mt.forearm, mt.hand = definitions
-    mt.update()
-
-    ik = bone_class_instance(obj, ["pole", "pole_vis", "hand_vis"])
-    ik_chain = mt.copy(to_fmt="MCH-%s_ik", base_names=base_names, exclude_attrs=["shoulder"])
-
-    # IK needs no parent_index
-    ik_chain.hand_e.use_connect = False
-    ik_chain.hand_e.parent = None
-    ik_chain.hand_e.use_local_location = False
-    ik_chain.rename("hand", get_base_name(base_names[mt.hand]) + "_ik" + get_side_name(mt.hand))
-
-    ik_chain.arm_e.use_connect = False
-    ik_chain.arm_e.parent = mt.shoulder_e
-
-    # Add the bone used for the arms poll target
-    #ik.pole = add_pole_target_bone(obj, mt.forearm, get_base_name(base_names[mt.forearm]) + "_target" + get_side_name(mt.forearm), mode='ZAVERAGE')
-    ik.pole = add_pole_target_bone(obj, mt.forearm, "elbow_target" + get_side_name(mt.forearm), mode='ZAVERAGE')
-
-    ik.update()
-    ik.pole_e.use_local_location = False
-
-    # option: elbow_parent
-    elbow_parent_name = options.get("elbow_parent", "")
-
-    if elbow_parent_name:
-        try:
-            elbow_parent_e = arm.edit_bones[ORG_PREFIX + elbow_parent_name]
-        except:
-            # TODO, old/new parent mapping
-            raise RigifyError("parent bone from property 'arm_biped_generic.elbow_parent' not found '%s'" % elbow_parent_name)
-        ik.pole_e.parent = elbow_parent_e
-
-    # update bones after this!
-    ik.hand_vis = add_stretch_to(obj, mt.hand, ik_chain.hand, "VIS-%s_ik" % base_names[mt.hand])
-    ik.pole_vis = add_stretch_to(obj, mt.forearm, ik.pole, "VIS-%s_ik" % base_names[mt.forearm])
-
-    ik.update()
-    ik.hand_vis_e.hide_select = True
-    ik.pole_vis_e.hide_select = True
-
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-    mt.update()
-    ik.update()
-    ik_chain.update()
-
-    # Set IK dof
-    ik_chain.forearm_p.lock_ik_x = False
-    ik_chain.forearm_p.lock_ik_y = True
-    ik_chain.forearm_p.lock_ik_z = True
-
-    con = ik_chain.forearm_p.constraints.new('IK')
-    con.target = obj
-    con.subtarget = ik_chain.hand
-    con.pole_target = obj
-    con.pole_subtarget = ik.pole
-
-    con.use_tail = True
-    con.use_stretch = True
-    con.use_target = True
-    con.use_rotation = False
-    con.chain_count = 2
-    con.pole_angle = -pi/2
-
-    # last step setup layers
-    if "ik_layer" in options:
-        layer = [n==options["ik_layer"] for n in range(0,32)]
-    else:
-        layer = list(mt.arm_b.layers)
-    ik_chain.hand_b.layers = layer
-    ik.hand_vis_b.layers   = layer
-    ik.pole_b.layers       = layer
-    ik.pole_vis_b.layers   = layer
-
-    bpy.ops.object.mode_set(mode='EDIT')
-    # don't blend the shoulder
-    return [None] + ik_chain.names()
-
-
-def fk(obj, definitions, base_names, options):
-
-    arm = obj.data
-
-    mt = bone_class_instance(obj, METARIG_NAMES)
-    mt.shoulder, mt.arm, mt.forearm, mt.hand = definitions
-    mt.update()
-
-    ex = bone_class_instance(obj, ["socket", "hand_delta"])
-    fk_chain = mt.copy(base_names=base_names)
-
-    # shoulder is used as a hinge
-    fk_chain.rename("shoulder", "MCH-%s_hinge" % base_names[mt.arm])
-    fk_chain.shoulder_e.translate(Vector((0.0, fk_chain.shoulder_e.length / 2, 0.0)))
-
-    # upper arm constrains to this.
-    ex.socket_e = copy_bone_simple(arm, mt.arm, "MCH-%s_socket" % base_names[mt.arm])
-    ex.socket = ex.socket_e.name
-    ex.socket_e.use_connect = False
-    ex.socket_e.parent = mt.shoulder_e
-    ex.socket_e.length *= 0.5
-
-    # insert the 'MCH-delta_hand', between the forearm and the hand
-    # copies forarm rotation
-    ex.hand_delta_e = copy_bone_simple(arm, fk_chain.hand, "MCH-delta_%s" % base_names[mt.hand], parent=True)
-    ex.hand_delta = ex.hand_delta_e.name
-    ex.hand_delta_e.length *= 0.5
-    ex.hand_delta_e.use_connect = False
-    if "hand_roll" in options:
-        ex.hand_delta_e.roll += radians(options["hand_roll"])
-
-    fk_chain.hand_e.use_connect = False
-    fk_chain.hand_e.parent = ex.hand_delta_e
-
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-    mt.update()
-    ex.update()
-    fk_chain.update()
-
-    # Set rotation modes and axis locks
-    fk_chain.forearm_p.rotation_mode = 'XYZ'
-    fk_chain.forearm_p.lock_rotation = (False, True, True)
-    fk_chain.hand_p.rotation_mode = 'ZXY'
-    fk_chain.arm_p.lock_location = True, True, True
-
-    con = fk_chain.arm_p.constraints.new('COPY_LOCATION')
-    con.target = obj
-    con.subtarget = ex.socket
-
-    fk_chain.hand_p.lock_location = True, True, True
-    con = ex.hand_delta_p.constraints.new('COPY_ROTATION')
-    con.target = obj
-    con.subtarget = fk_chain.forearm
-
-    def hinge_setup():
-        # Hinge constraint & driver
-        con = fk_chain.shoulder_p.constraints.new('COPY_ROTATION')
-        con.name = "hinge"
-        con.target = obj
-        con.subtarget = mt.shoulder
-        driver_fcurve = con.driver_add("influence")
-        driver = driver_fcurve.driver
-
-
-        controller_path = fk_chain.arm_p.path_from_id()
-        # add custom prop
-        fk_chain.arm_p["hinge"] = 0.0
-        prop = rna_idprop_ui_prop_get(fk_chain.arm_p, "hinge", create=True)
-        prop["soft_min"] = 0.0
-        prop["soft_max"] = 1.0
-
-
-        # *****
-        driver = driver_fcurve.driver
-        driver.type = 'AVERAGE'
-
-        var = driver.variables.new()
-        var.name = "hinge"
-        var.targets[0].id_type = 'OBJECT'
-        var.targets[0].id = obj
-        var.targets[0].data_path = controller_path + '["hinge"]'
-
-        mod = driver_fcurve.modifiers[0]
-        mod.poly_order = 1
-        mod.coefficients[0] = 1.0
-        mod.coefficients[1] = -1.0
-
-    hinge_setup()
-
-    # last step setup layers
-    if "fk_layer" in options:
-        layer = [n==options["fk_layer"] for n in range(0,32)]
-    else:
-        layer = list(mt.arm_b.layers)
-    fk_chain.arm_b.layers     = layer
-    fk_chain.forearm_b.layers = layer
-    fk_chain.hand_b.layers    = layer
-
-    # Forearm was getting wrong roll somehow.  Hack to fix that.
-    bpy.ops.object.mode_set(mode='EDIT')
-    fk_chain.update()
-    mt.update()
-    fk_chain.forearm_e.roll = mt.forearm_e.roll
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-    bpy.ops.object.mode_set(mode='EDIT')
-    return None, fk_chain.arm, fk_chain.forearm, fk_chain.hand
-
-
-def deform(obj, definitions, base_names, options):
-    bpy.ops.object.mode_set(mode='EDIT')
-
-    # Create upper arm bones: two bones, each half of the upper arm.
-    uarm1 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.01" % base_names[definitions[1]], parent=True)
-    uarm2 = copy_bone_simple(obj.data, definitions[1], "DEF-%s.02" % base_names[definitions[1]], parent=True)
-    uarm1.use_connect = False
-    uarm2.use_connect = False
-    uarm2.parent = uarm1
-    center = uarm1.center
-    uarm1.tail = center
-    uarm2.head = center
-
-    # Create forearm bones: two bones, each half of the forearm.
-    farm1 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.01" % base_names[definitions[2]], parent=True)
-    farm2 = copy_bone_simple(obj.data, definitions[2], "DEF-%s.02" % base_names[definitions[2]], parent=True)
-    farm1.use_connect = False
-    farm2.use_connect = False
-    farm2.parent = farm1
-    center = farm1.center
-    farm1.tail = center
-    farm2.head = center
-
-    # Create twist bone
-    twist = copy_bone_simple(obj.data, definitions[2], "MCH-arm_twist")
-    twist.use_connect = False
-    twist.parent = obj.data.edit_bones[definitions[3]]
-    twist.length /= 2
-
-    # Create hand bone
-    hand = copy_bone_simple(obj.data, definitions[3], "DEF-%s" % base_names[definitions[3]], parent=True)
-
-    # Store names before leaving edit mode
-    uarm1_name = uarm1.name
-    uarm2_name = uarm2.name
-    farm1_name = farm1.name
-    farm2_name = farm2.name
-    twist_name = twist.name
-    hand_name = hand.name
-
-    # Leave edit mode
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-    # Get the pose bones
-    uarm1 = obj.pose.bones[uarm1_name]
-    uarm2 = obj.pose.bones[uarm2_name]
-    farm1 = obj.pose.bones[farm1_name]
-    farm2 = obj.pose.bones[farm2_name]
-    twist = obj.pose.bones[twist_name]
-    hand = obj.pose.bones[hand_name]
-
-    # Upper arm constraints
-    con = uarm1.constraints.new('DAMPED_TRACK')
-    con.name = "trackto"
-    con.target = obj
-    con.subtarget = definitions[2]
-
-    con = uarm1.constraints.new('COPY_SCALE')
-    con.name = "trackto"
-    con.target = obj
-    con.subtarget = definitions[1]
-
-    con = uarm2.constraints.new('COPY_ROTATION')
-    con.name = "copy_rot"
-    con.target = obj
-    con.subtarget = definitions[1]
-
-    # Forearm constraints
-    con = farm1.constraints.new('COPY_ROTATION')
-    con.name = "copy_rot"
-    con.target = obj
-    con.subtarget = definitions[2]
-
-    con = farm1.constraints.new('COPY_SCALE')
-    con.name = "copy_rot"
-    con.target = obj
-    con.subtarget = definitions[2]
-
-    con = farm2.constraints.new('COPY_ROTATION')
-    con.name = "copy_rot"
-    con.target = obj
-    con.subtarget = twist.name
-
-    con = farm2.constraints.new('DAMPED_TRACK')
-    con.name = "trackto"
-    con.target = obj
-    con.subtarget = definitions[3]
-
-    # Hand constraint
-    con = hand.constraints.new('COPY_ROTATION')
-    con.name = "copy_rot"
-    con.target = obj
-    con.subtarget = definitions[3]
-
-    bpy.ops.object.mode_set(mode='EDIT')
-    return (uarm1_name, uarm2_name, farm1_name, farm2_name, hand_name)
-
-
-def main(obj, bone_definition, base_names, options):
-    bones_fk = fk(obj, bone_definition, base_names, options)
-    bones_ik = ik(obj, bone_definition, base_names, options)
-    bones_deform = deform(obj, bone_definition, base_names, options)
-
-    bpy.ops.object.mode_set(mode='OBJECT')
-    blend_bone_list(obj, bone_definition, bones_fk, bones_ik, target_bone=bones_ik[3], target_prop="ik", blend_default=0.0)
diff --git a/release/scripts/modules/rigify/copy.py b/release/scripts/modules/rigify/copy.py
deleted file mode 100644 (file)
index c051e5b..0000000
+++ /dev/null
@@ -1,112 +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 rigify_utils import bone_class_instance, copy_bone_simple
-
-METARIG_NAMES = ("cpy",)
-
-
-def metarig_template():
-    # generated by rigify.write_meta_rig
-    bpy.ops.object.mode_set(mode='EDIT')
-    obj = bpy.context.active_object
-    arm = obj.data
-    bone = arm.edit_bones.new('Bone')
-    bone.head[:] = 0.0000, 0.0000, 0.0000
-    bone.tail[:] = 0.0000, 0.0000, 1.0000
-    bone.roll = 0.0000
-    bone.use_connect = False
-
-    bpy.ops.object.mode_set(mode='OBJECT')
-    pbone = obj.pose.bones['Bone']
-    pbone['type'] = 'copy'
-
-
-def metarig_definition(obj, orig_bone_name):
-    return (orig_bone_name,)
-
-
-def deform(obj, definitions, base_names, options):
-    bpy.ops.object.mode_set(mode='EDIT')
-
-    # Create deform bone.
-    bone = copy_bone_simple(obj.data, definitions[0], "DEF-%s" % base_names[definitions[0]], parent=True)
-
-    # Store name before leaving edit mode
-    bone_name = bone.name
-
-    # Leave edit mode
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-    # Get the pose bone
-    bone = obj.pose.bones[bone_name]
-
-    # Constrain to the original bone
-    con = bone.constraints.new('COPY_TRANSFORMS')
-    con.name = "copy_loc"
-    con.target = obj
-    con.subtarget = definitions[0]
-
-    return (bone_name,)
-
-
-def control(obj, definitions, base_names, options):
-    bpy.ops.object.mode_set(mode='EDIT')
-
-    arm = obj.data
-    mt = bone_class_instance(obj, METARIG_NAMES)
-    mt.cpy = definitions[0]
-    mt.update()
-    cp = bone_class_instance(obj, ["cpy"])
-    cp.cpy_e = copy_bone_simple(arm, mt.cpy, base_names[mt.cpy], parent=True)
-    cp.cpy = cp.cpy_e.name
-
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-    cp.update()
-    mt.update()
-
-    con = mt.cpy_p.constraints.new('COPY_TRANSFORMS')
-    con.target = obj
-    con.subtarget = cp.cpy
-
-
-    # Rotation mode and axis locks
-    cp.cpy_p.rotation_mode = mt.cpy_p.rotation_mode
-    cp.cpy_p.lock_location = tuple(mt.cpy_p.lock_location)
-    cp.cpy_p.lock_rotations_4d = mt.cpy_p.lock_rotations_4d
-    cp.cpy_p.lock_rotation = tuple(mt.cpy_p.lock_rotation)
-    cp.cpy_p.lock_rotation_w = mt.cpy_p.lock_rotation_w
-    cp.cpy_p.lock_scale = tuple(mt.cpy_p.lock_scale)
-
-    # Layers
-    cp.cpy_b.layers = list(mt.cpy_b.layers)
-
-    return (mt.cpy,)
-
-
-def main(obj, bone_definition, base_names, options):
-    # Create control bone
-    cpy = control(obj, bone_definition, base_names, options)[0]
-    # Create deform bone
-    deform(obj, bone_definition, base_names, options)
-
-    return (cpy,)
diff --git a/release/scripts/modules/rigify/delta.py b/release/scripts/modules/rigify/delta.py
deleted file mode 100644 (file)
index d0b4fbc..0000000
+++ /dev/null
@@ -1,162 +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 rigify import RigifyError
-
-# not used, defined for completeness
-METARIG_NAMES = tuple()
-
-
-def metarig_template():
-    # generated by rigify.write_meta_rig
-    bpy.ops.object.mode_set(mode='EDIT')
-    obj = bpy.context.active_object
-    arm = obj.data
-    bone = arm.edit_bones.new('bonesker')
-    bone.head[:] = 0.0000, 0.0000, 0.0000
-    bone.tail[:] = -0.0000, 0.7382, 0.1895
-    bone.roll = -0.0000
-    bone.use_connect = False
-    bone = arm.edit_bones.new('delta')
-    bone.head[:] = -0.0497, 0.8414, 0.3530
-    bone.tail[:] = -0.2511, 1.1588, 0.9653
-    bone.roll = 2.6044
-    bone.use_connect = False
-    bone.parent = arm.edit_bones['bonesker']
-    bone = arm.edit_bones.new('boney')
-    bone.head[:] = 0.7940, 2.5592, 0.4134
-    bone.tail[:] = 0.7940, 3.3975, 0.4890
-    bone.roll = 3.1416
-    bone.use_connect = False
-    bone.parent = arm.edit_bones['delta']
-
-    bpy.ops.object.mode_set(mode='OBJECT')
-    pbone = obj.pose.bones['delta']
-    pbone['type'] = 'delta'
-
-
-def metarig_definition(obj, orig_bone_name):
-    '''
-    The bone given is the head, its parent is the body,
-    # its only child the first of a chain with matching basenames.
-    eg.
-        body -> head -> neck_01 -> neck_02 -> neck_03.... etc
-    '''
-    arm = obj.data
-    delta = arm.bones[orig_bone_name]
-    children = delta.children
-
-    if len(children) != 1:
-        raise RigifyError("only 1 child supported for delta on bone '%s'" % delta.name)
-
-    if delta.use_connect:
-        raise RigifyError("bone cannot be connected to its parent '%s'" % delta.name)
-
-    bone_definition = [delta.name, children[0].name]
-
-    return bone_definition
-
-
-def main(obj, bone_definition, base_names, options):
-    '''
-    Use this bone to define a delta thats applied to its child in pose mode.
-    '''
-    mode_orig = obj.mode
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-    delta_name, child_name = bone_definition
-
-    delta_pbone = obj.pose.bones[delta_name]
-
-    arm = obj.data
-    child_pbone = obj.pose.bones[child_name]
-
-    delta_phead = delta_pbone.head.copy()
-    delta_ptail = delta_pbone.tail.copy()
-    delta_pmatrix = delta_pbone.matrix.copy()
-
-    child_phead = child_pbone.head.copy()
-    child_ptail = child_pbone.tail.copy()
-    child_pmatrix = child_pbone.matrix.copy()
-
-
-    children = delta_pbone.children
-
-    bpy.ops.object.mode_set(mode='EDIT')
-
-    delta_ebone = arm.edit_bones[delta_name]
-    child_ebone = arm.edit_bones[child_name]
-
-    delta_head = delta_ebone.head.copy()
-    delta_tail = delta_ebone.tail.copy()
-
-    child_head = child_ebone.head.copy()
-    child_tail = child_ebone.tail.copy()
-
-    #arm.edit_bones.remove(delta_ebone)
-    #del delta_ebone # cant use this
-    del child_pbone
-
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-
-    # Move the child bone to the deltas location
-    obj.animation_data_create()
-    delta_pbone = obj.pose.bones[delta_name]
-    # child_pbone = obj.pose.bones[child_name]
-
-    # ------------------- drivers
-
-    delta_pbone.rotation_mode = 'XYZ'
-
-    rot = delta_pmatrix.invert().rotation_part() * child_pmatrix.rotation_part()
-    rot = rot.invert().to_euler()
-
-    fcurve_drivers = delta_pbone.driver_add("rotation_euler", -1)
-    for i, fcurve_driver in enumerate(fcurve_drivers):
-        driver = fcurve_driver.driver
-        driver.type = 'AVERAGE'
-        #mod = fcurve_driver.modifiers.new('GENERATOR')
-        mod = fcurve_driver.modifiers[0]
-        mod.poly_order = 1
-        mod.coefficients[0] = rot[i]
-        mod.coefficients[1] = 0.0
-
-    # tricky, find the transform to drive the bone to this location.
-    delta_head_offset = child_pmatrix.rotation_part() * (delta_phead - child_phead)
-
-    fcurve_drivers = delta_pbone.driver_add("location", -1)
-    for i, fcurve_driver in enumerate(fcurve_drivers):
-        driver = fcurve_driver.driver
-        driver.type = 'AVERAGE'
-        #mod = fcurve_driver.modifiers.new('GENERATOR')
-        mod = fcurve_driver.modifiers[0]
-        mod.poly_order = 1
-        mod.coefficients[0] = delta_head_offset[i]
-        mod.coefficients[1] = 0.0
-
-
-    bpy.ops.object.mode_set(mode='EDIT')
-
-    bpy.ops.object.mode_set(mode=mode_orig)
-
-    # no blendeing
-    return None
diff --git a/release/scripts/modules/rigify/eye_balls.py b/release/scripts/modules/rigify/eye_balls.py
deleted file mode 100644 (file)
index 127ee87..0000000
+++ /dev/null
@@ -1,405 +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 rna_prop_ui import rna_idprop_ui_prop_get
-from mathutils import Vector
-from rigify import RigifyError
-from rigify_utils import copy_bone_simple
-
-#METARIG_NAMES = ("cpy",)
-RIG_TYPE = "eye_balls"
-
-def addget_shape_key(obj, name="Key"):
-    """ Fetches a shape key, or creates it if it doesn't exist
-    """
-    # Create a shapekey set if it doesn't already exist
-    if obj.data.shape_keys is None:
-        shape = obj.add_shape_key(name="Basis", from_mix=False)
-        obj.active_shape_key_index = 0
-
-    # Get the shapekey, or create it if it doesn't already exist
-    if name in obj.data.shape_keys.keys:
-        shape_key = obj.data.shape_keys.keys[name]
-    else:
-        shape_key = obj.add_shape_key(name=name, from_mix=False)
-
-    return shape_key
-
-
-def addget_shape_key_driver(obj, name="Key"):
-    """ Fetches the driver for the shape key, or creates it if it doesn't
-        already exist.
-    """
-    driver_path = 'keys["' + name + '"].value'
-    fcurve = None
-    driver = None
-    new = False
-    if obj.data.shape_keys.animation_data is not None:
-        for driver_s in obj.data.shape_keys.animation_data.drivers:
-            if driver_s.data_path == driver_path:
-                fcurve = driver_s
-    if fcurve is None:
-        fcurve = obj.data.shape_keys.keys[name].driver_add("value")
-        fcurve.driver.type = 'AVERAGE'
-        new = True
-
-    return fcurve, new
-   
-    
-def create_shape_and_driver(obj, bone, meshes, shape_name, var_name, var_path, expression):
-    """ Creates/gets a shape key and sets up a driver for it.
-
-        obj = armature object
-        bone = driving bone name
-        meshes = list of meshes to create the shapekey/driver on
-        shape_name = name of the shape key
-        var_name = name of the driving variable
-        var_path = path to the property on the bone to drive with
-        expression = python expression for the driver
-    """
-    pb = obj.pose.bones
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-    for mesh_name in meshes:
-        mesh_obj = bpy.data.objects[mesh_name]
-
-        # Add/get the shape key
-        shape = addget_shape_key(mesh_obj, name=shape_name)
-
-        # Add/get the shape key driver
-        fcurve, a = addget_shape_key_driver(mesh_obj, name=shape_name)
-
-        # Set up the driver
-        driver = fcurve.driver
-        driver.type = 'SCRIPTED'
-        driver.expression = expression
-
-        # Get the variable, or create it if it doesn't already exist
-        if var_name in driver.variables:
-            var = driver.variables[var_name]
-        else:
-            var = driver.variables.new()
-            var.name = var_name
-
-        # Set up the variable
-        var.type = "SINGLE_PROP"
-        var.targets[0].id_type = 'OBJECT'
-        var.targets[0].id = obj
-        var.targets[0].data_path = 'pose.bones["' + bone + '"]' + var_path
-
-
-def mark_actions():
-    for action in bpy.data.actions:
-        action.tag = True
-
-def get_unmarked_action():
-    for action in bpy.data.actions:
-        if action.tag != True:
-            return action
-    return None
-
-def add_action(name=None):
-    mark_actions()
-    bpy.ops.action.new()
-    action = get_unmarked_action()
-    if name is not None:
-        action.name = name
-    return action
-
-
-def metarig_template():
-    # generated by rigify.write_meta_rig
-    bpy.ops.object.mode_set(mode='EDIT')
-    obj = bpy.context.active_object
-    arm = obj.data
-    bone = arm.edit_bones.new('Bone')
-    bone.head[:] = 0.0000, 0.0000, 0.0000
-    bone.tail[:] = 0.0000, 0.0000, 1.0000
-    bone.roll = 0.0000
-    bone.use_connect = False
-
-    bpy.ops.object.mode_set(mode='OBJECT')
-    pbone = obj.pose.bones['Bone']
-    pbone['type'] = 'copy'
-
-
-def metarig_definition(obj, orig_bone_name):
-    bone = obj.data.bones[orig_bone_name]
-    chain = []
-
-    try:
-        chain += [bone.parent.name, bone.name]
-    except AttributeError:
-        raise RigifyError("'%s' rig type requires a parent (bone: %s)" % (RIG_TYPE, orig_bone_name))
-
-    return chain
-
-
-def deform(obj, definitions, base_names, options):
-    bpy.ops.object.mode_set(mode='EDIT')
-
-    eb = obj.data.edit_bones
-    pb = obj.pose.bones
-
-    # Get list of eyes
-    if "eyes" in options:
-        eye_base_names = options["eyes"].replace(" ", "").split(",")
-    else:
-        eye_base_names = []
-
-    # Get their ORG- names
-    eyes = []
-    for name in eye_base_names:
-        eyes += ["ORG-"+name]
-
-    # Duplicate the eyes to make deformation bones
-    def_eyes = [] # def/org pairs
-    for eye in eyes:
-        def_eyes += [(copy_bone_simple(obj.data, eye, "DEF-"+base_names[eye], parent=True).name, eye)]
-
-
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-    # Constraints
-    for eye in def_eyes:
-        con = pb[eye[0]].constraints.new('COPY_TRANSFORMS')
-        con.target = obj
-        con.subtarget = eye[1]
-
-    return (None,)
-
-
-
-
-def control(obj, definitions, base_names, options):
-    bpy.ops.object.mode_set(mode='EDIT')
-
-    eb = obj.data.edit_bones
-    bb = obj.data.bones
-    pb = obj.pose.bones
-
-    head = definitions[0]
-    eye_target = definitions[1]
-
-    # Get list of pupil mesh objects
-    if "mesh" in options:
-        pupil_meshes = options["mesh"].replace(" ", "").split(",")
-    else:
-        pupil_meshes = []
-
-    # Get list of eyes
-    if "eyes" in options:
-        eye_base_names = options["eyes"].replace(" ", "").split(",")
-    else:
-        eye_base_names = []
-
-    # Get their ORG- names
-    eyes = []
-    for name in eye_base_names:
-        eyes += ["ORG-"+name]
-
-    # Get the average position of the eyes
-    center = Vector((0, 0, 0))
-    for eye in eyes:
-        center += eb[eye].head
-    if len(eyes) != 0:
-        center /= len(eyes)
-
-    # Get the average length of the eyes
-    length = 0.0
-    for eye in eyes:
-        length += eb[eye].length
-    if len(eyes) == 0:
-        length = 1.0
-    else:
-        length /= len(eyes)
-
-
-    # Make the mind's eye
-    minds_eye = copy_bone_simple(obj.data, eye_target, "MCH-"+base_names[eye_target]+".mind", parent=True).name
-    eb[minds_eye].head = center
-    eb[minds_eye].tail = eb[eye_target].head
-    eb[minds_eye].roll = 0.0
-    eb[minds_eye].length = length
-
-    # Create org/copy/control eye sets
-    eye_sets = []
-    for eye in eyes:
-        copy = copy_bone_simple(obj.data, minds_eye, "MCH-"+base_names[eye]+".cpy", parent=True).name
-        eb[copy].translate(eb[eye].head - eb[copy].head)
-        eb[copy].parent = eb[eye].parent
-
-        control = copy_bone_simple(obj.data, eye, base_names[eye], parent=True).name
-        eb[control].parent = eb[copy]
-
-        eye_sets += [(eye, copy, control)]
-
-    # Bones for parent/free switch for eye target
-    target_ctrl = copy_bone_simple(obj.data, eye_target, base_names[eye_target], parent=True).name
-    parent = copy_bone_simple(obj.data, head, "MCH-eye_target_parent", parent=False).name
-
-    eb[target_ctrl].parent = eb[parent]
-
-
-
-
-    bpy.ops.object.mode_set(mode='OBJECT')
-
-    # Axis locks
-    pb[target_ctrl].lock_scale = False, True, True
-
-    # Add eye_spread action if it doesn't already exist
-    action_name = "eye_spread"
-    if action_name in bpy.data.actions:
-        spread_action = bpy.data.actions[action_name]
-    else:
-        spread_action = add_action(name=action_name)
-
-    # Add free property
-    prop_name = "free"
-    prop = rna_idprop_ui_prop_get(pb[target_ctrl], prop_name, create=True)
-    pb[target_ctrl][prop_name] = 0.0
-    prop["soft_min"] = 0.0
-    prop["soft_max"] = 1.0
-    prop["min"] = 0.0
-    prop["max"] = 1.0
-
-    free_driver_path = pb[target_ctrl].path_from_id() + '["free"]'
-
-    # Constraints
-    # Mind's eye tracks eye target control
-    con = pb[minds_eye].constraints.new('DAMPED_TRACK')
-    con.target = obj
-    con.subtarget = target_ctrl
-
-    # Parent copies transforms of head
-    con = pb[parent].constraints.new('COPY_TRANSFORMS')
-    con.target = obj
-    con.subtarget = head
-
-    fcurve = con.driver_add("influence")
-    driver = fcurve.driver
-    driver.type = 'AVERAGE'
-    mod = fcurve.modifiers[0]
-    mod.coefficients[0] = 1.0
-    mod.coefficients[1] = -1.0
-
-    var = driver.variables.new()
-    var.name = "free"
-    var.targets[0].id_type = 'OBJECT'
-    var.targets[0].id = obj
-    var.targets[0].data_path = free_driver_path
-
-    # Eye set's constraints
-    for eye in eye_sets:
-        # Org copies transforms of control
-        con = pb[eye[0]].constraints.new('COPY_TRANSFORMS')
-        con.target = obj
-        con.subtarget = eye[2]
-
-        # Copy copies rotation of mind's eye
-        con = pb[eye[1]].constraints.new('COPY_ROTATION')
-        con.target = obj
-        con.subtarget = minds_eye
-
-        # Control gets action constraint for eye spread
-        con = pb[eye[2]].constraints.new('ACTION')
-        con.target = obj
-        con.subtarget = target_ctrl
-        con.action = spread_action
-        con.transform_channel = 'SCALE_X'
-        con.frame_start = -20
-        con.frame_end = 20
-        con.min = 0.0
-        con.max = 2.0
-        con.target_space = 'LOCAL'
-    
-    
-    # Get/create the shape keys and drivers for pupil dilation
-    shape_names = ["PUPILS-dilate_wide", "PUPILS-dilate_narrow"]
-    slider_name = "pupil_dilate"
-    
-    # Set up the custom property on the bone
-    prop = rna_idprop_ui_prop_get(pb[target_ctrl], slider_name, create=True)
-    pb[target_ctrl][slider_name] = 0.0
-    prop["min"] = 0.0
-    prop["max"] = 1.0
-    prop["soft_min"] = 0.0
-    prop["soft_max"] = 1.0
-    if len(shape_names) > 1:
-        prop["min"] = -1.0
-        prop["soft_min"] = -1.0
-
-    # Add the shape drivers
-    # Positive
-    if shape_names[0] != "":
-        # Set up the variables for creating the shape key driver
-        shape_name = shape_names[0]
-        var_name = slider_name.replace(".", "_").replace("-", "_")
-        var_path = '["' + slider_name + '"]'
-        if slider_name + "_fac" in options:
-            fac = options[slider_name + "_fac"]
-        else:
-            fac = 1.0
-        expression = var_name + " * " + str(fac)
-        # Create the shape key driver
-        create_shape_and_driver(obj, target_ctrl, pupil_meshes, shape_name, var_name, var_path, expression)
-    # Negative
-    if shape_names[0] != "" and len(shape_names) > 1:
-        # Set up the variables for creating the shape key driver
-        shape_name = shape_names[1]
-        var_name = slider_name.replace(".", "_").replace("-", "_")
-        var_path = '["' + slider_name + '"]'
-        if slider_name + "_fac" in options:
-            fac = options[slider_name + "_fac"]
-        else:
-            fac = 1.0
-        expression = var_name + " * " + str(fac) + " * -1"
-        # Create the shape key driver
-        create_shape_and_driver(obj, target_ctrl, pupil_meshes, shape_name, var_name, var_path, expression)
-
-
-
-    # Set layers
-    #layer = list(bb[definitions[2]].layers)
-    #bb[lid1].layers = layer
-    #bb[lid2].layers = layer
-    #bb[lid3].layers = layer
-    #bb[lid4].layers = layer
-    #bb[lid5].layers = layer
-    #bb[lid6].layers = layer
-    #bb[lid7].layers = layer
-    #bb[lid8].layers = layer
-
-
-    return (None,)
-
-
-
-
-def main(obj, bone_definition, base_names, options):
-    # Create control rig
-    control(obj, bone_definition, base_names, options)
-    # Create deform rig
-    deform(obj, bone_definition, base_names, options)
-
-    return (None,)
-
diff --git a/release/scripts/modules/rigify/eye_lid.py b/release/scripts/modules/rigify/eye_lid.py
deleted file mode 100644 (file)
index 3f336e2..0000000
+++ /dev/null
@@ -1,687 +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 rna_prop_ui import rna_idprop_ui_prop_get
-from math import acos
-from mathutils import Vector
-from rigify import RigifyError
-from rigify_utils import copy_bone_simple
-
-#METARIG_NAMES = ("cpy",)
-RIG_TYPE = "eye_lid"
-
-def mark_actions():
-    for action in bpy.data.actions:
-        action.tag = True
-
-def get_unmarked_action():
-    for action in bpy.data.actions:
-        if action.tag != True:
-            return action
-    return None
-
-def add_action(name=None):
-    mark_actions()
-    bpy.ops.action.new()
-