Sculpt: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r24257...
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 4 Nov 2009 21:21:30 +0000 (21:21 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Wed, 4 Nov 2009 21:21:30 +0000 (21:21 +0000)
119 files changed:
CMakeLists.txt
SConstruct
config/win64-vc-config.py
intern/ghost/intern/GHOST_SystemCocoa.mm
intern/ghost/intern/GHOST_WindowCocoa.mm
intern/moto/include/MT_assert.h
release/scripts/io/export_3ds.py
release/scripts/io/export_fbx.py
release/scripts/io/export_mdd.py
release/scripts/io/export_obj.py
release/scripts/io/export_ply.py
release/scripts/io/export_x3d.py
release/scripts/io/import_anim_bvh.py [new file with mode: 0644]
release/scripts/io/import_scene_3ds.py [moved from release/scripts/io/import_3ds.py with 99% similarity]
release/scripts/io/import_scene_obj.py [moved from release/scripts/io/import_obj.py with 99% similarity]
release/scripts/io/netrender/client.py
release/scripts/modules/bpy_ops.py
release/scripts/modules/bpy_utils.py [moved from release/scripts/modules/bpy_sys.py with 92% similarity]
release/scripts/op/add_mesh_torus.py [moved from release/scripts/io/add_mesh_torus.py with 95% similarity]
release/scripts/op/mesh_skin.py [moved from release/scripts/io/mesh_skin.py with 100% similarity]
release/scripts/op/uvcalc_smart_project.py [new file with mode: 0644]
release/scripts/op/vertexpaint_dirt.py [moved from release/scripts/io/vertexpaint_dirt.py with 53% similarity]
release/scripts/op/wm.py [new file with mode: 0644]
release/scripts/templates/operator.py
release/scripts/ui/properties_data_armature.py
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_data_text.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_buttons.py
release/scripts/ui/space_console.py
release/scripts/ui/space_filebrowser.py
release/scripts/ui/space_image.py
release/scripts/ui/space_info.py
release/scripts/ui/space_logic.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_view3d.py
release/scripts/ui/space_view3d_toolbar.py
source/blender/blenkernel/BKE_deform.h
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/deform.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenkernel/intern/texture.c
source/blender/blenloader/intern/readfile.c
source/blender/collada/DocumentExporter.cpp
source/blender/collada/DocumentImporter.cpp
source/blender/editors/animation/drivers.c
source/blender/editors/animation/keyframing.c
source/blender/editors/include/ED_mesh.h
source/blender/editors/mesh/mesh_data.c
source/blender/editors/mesh/mesh_ops.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_ops.c
source/blender/editors/object/object_relations.c
source/blender/editors/object/object_shapekey.c
source/blender/editors/screen/area.c
source/blender/editors/screen/screen_edit.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform_constraints.c
source/blender/editors/transform/transform_manipulator.c
source/blender/editors/uvedit/uvedit_intern.h
source/blender/editors/uvedit/uvedit_ops.c
source/blender/editors/uvedit/uvedit_unwrap_ops.c
source/blender/makesdna/DNA_particle_types.h
source/blender/makesdna/DNA_texture_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/RNA_define.h
source/blender/makesrna/RNA_enum_types.h
source/blender/makesrna/intern/makesrna.c
source/blender/makesrna/intern/rna_ID.c
source/blender/makesrna/intern/rna_access.c
source/blender/makesrna/intern/rna_boid.c
source/blender/makesrna/intern/rna_cloth.c
source/blender/makesrna/intern/rna_define.c
source/blender/makesrna/intern/rna_fluidsim.c
source/blender/makesrna/intern/rna_internal_types.h
source/blender/makesrna/intern/rna_mesh.c
source/blender/makesrna/intern/rna_object.c
source/blender/makesrna/intern/rna_object_force.c
source/blender/makesrna/intern/rna_particle.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_smoke.c
source/blender/makesrna/intern/rna_texture.c
source/blender/python/epy_doc_gen.py
source/blender/python/intern/bpy_interface.c
source/blender/python/intern/bpy_rna.c
source/blender/render/intern/source/pointdensity.c
source/blender/windowmanager/intern/wm_operators.c

index 74c527841f542a10e8c403c588f89902651acb7b..4e02ea20fb0cadbf001f3d7f642271ac9476d393 100644 (file)
@@ -518,9 +518,9 @@ IF(APPLE)
        ENDIF (WITH_COCOA)
 
        IF(WITH_OPENMP)
-               SET(LLIBS "${LLIBS} -lgomp ")
-               SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp ")
-               SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp ")
+               SET(LLIBS "${LLIBS} -lgomp")
+               SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp")
+               SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")
        ENDIF(WITH_OPENMP)
 
        IF (WITH_OPENCOLLADA)
@@ -555,6 +555,16 @@ IF(APPLE)
        SET(TIFF_INC ${TIFF}/include)
 
        SET(EXETYPE MACOSX_BUNDLE)
+
+
+       IF(CMAKE_OSX_ARCHITECTURES MATCHES "i386")
+               SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -ftree-vectorize -msse -msse2 -fvariable-expansion-in-unroller")
+               SET(CMAKE_C_FLAGS_RELEASE "-O3 -ftree-vectorize -msse -msse2 -fvariable-expansion-in-unroller")
+       ELSEIF(CMAKE_OSX_ARCHITECTURES MATCHES "x86_64")
+               SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -ftree-vectorize -msse -msse2 -msse3 -mssse3 -fvariable-expansion-in-unroller")
+               SET(CMAKE_C_FLAGS_RELEASE "-O3 -ftree-vectorize -msse -msse2 -msse3 -mssse3 -fvariable-expansion-in-unroller")
+       ENDIF(CMAKE_OSX_ARCHITECTURES MATCHES "i386")
+
 ENDIF(APPLE)
 
 IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
index cb90c2eaf663094681d006430103327c4335b6e7..e6dd85e8cff6c1702df38b0ee25b3915a18bbe09 100644 (file)
@@ -124,7 +124,10 @@ if toolset:
                #if env:
                #       btools.SetupSpawn(env)
 else:
-       env = BlenderEnvironment(ENV = os.environ)
+       if bitness==64 and platform=='win32':
+               env = BlenderEnvironment(ENV = os.environ, MSVS_ARCH='amd64')
+       else:
+               env = BlenderEnvironment(ENV = os.environ)
 
 if not env:
        print "Could not create a build environment"
index 429f8b0b6d6aae4dd5ebdbe7fcfe767436c6e0e0..53df6d96bf8e5fae77145ccba5b95e41614e01c5 100644 (file)
@@ -158,7 +158,7 @@ BF_COLLADA_LIB = 'bf_collada'
 
 BF_OPENCOLLADA = LIBDIR + '/opencollada'
 BF_OPENCOLLADA_INC = '${BF_OPENCOLLADA}/include'
-BF_OPENCOLLADA_LIB = 'opencollada'
+BF_OPENCOLLADA_LIB = 'OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver xml2 pcre'
 BF_OPENCOLLADA_LIBPATH = '${BF_OPENCOLLADA}/lib'
 
 WITH_BF_STATICOPENGL = False
index 5dbf79a0293797d1b26b64404ddf19cce003343a..73be363dff189756411e54f2dfcf81cbb2cb504e 100644 (file)
@@ -786,7 +786,7 @@ bool GHOST_SystemCocoa::processEvents(bool waitForEvent)
                                case NSFlagsChanged:
                                        handleKeyEvent(event);
                                        
-                                       /* Support system-wide keyboard shortcuts, like Exposé, ...) =>included in always NSApp sendEvent */
+                                       /* Support system-wide keyboard shortcuts, like Exposâ\88\9a©, ...) =>included in always NSApp sendEvent */
                                        /*              if (([event modifierFlags] & NSCommandKeyMask) || [event type] == NSFlagsChanged) {
                                         [NSApp sendEvent:event];
                                         }*/
@@ -891,8 +891,8 @@ GHOST_TUns8 GHOST_SystemCocoa::handleQuitRequest()
        //Check open windows if some changes are not saved
        if (m_windowManager->getAnyModifiedState())
        {
-               int shouldQuit = NSRunAlertPanel(@"Exit Blender", @"Some changes have not been saved. Do you really want to quit ?",
-                                                                                @"Cancel", @"Quit anyway", nil);
+               int shouldQuit = NSRunAlertPanel(@"Exit Blender", @"Some changes have not been saved.\nDo you really want to quit ?",
+                                                                                @"Cancel", @"Quit Anyway", nil);
                if (shouldQuit == NSAlertAlternateReturn)
                {
                        pushEvent( new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL) );
index 7716175b9f631a3c3b04563c3e27ff323a187a20..f0bc8dd4d0f8de6b41ba2808520313eff7ff92b2 100644 (file)
@@ -68,7 +68,7 @@ extern "C" {
 - (void)windowWillClose:(NSNotification *)notification;
 - (void)windowDidBecomeKey:(NSNotification *)notification;
 - (void)windowDidResignKey:(NSNotification *)notification;
-- (void)windowDidUpdate:(NSNotification *)notification;
+- (void)windowDidExpose:(NSNotification *)notification;
 - (void)windowDidResize:(NSNotification *)notification;
 @end
 
@@ -91,13 +91,10 @@ extern "C" {
 
 - (void)windowDidResignKey:(NSNotification *)notification
 {
-       //The window is no more key when its own view becomes fullscreen
-       //but ghost doesn't know the view/window difference, so hide this fact
-       if (associatedWindow->getState() != GHOST_kWindowStateFullScreen)
-               systemCocoa->handleWindowEvent(GHOST_kEventWindowDeactivate, associatedWindow);
+       systemCocoa->handleWindowEvent(GHOST_kEventWindowDeactivate, associatedWindow);
 }
 
-- (void)windowDidUpdate:(NSNotification *)notification
+- (void)windowDidExpose:(NSNotification *)notification
 {
        systemCocoa->handleWindowEvent(GHOST_kEventWindowUpdate, associatedWindow);
 }
@@ -622,6 +619,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setState(GHOST_TWindowState state)
                                //Make window normal and resize it
                                [m_window setStyleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask)];
                                [m_window setFrame:[[m_window screen] visibleFrame] display:YES];
+                               //TODO for 10.6 only : window title is forgotten after the style change
                                [m_window makeFirstResponder:m_openGLView];
 #else
                                //With 10.5, we need to create a new window to change its style to borderless
index 22f6b6a555c3e44596e6625ae18c07b81d348f0e..b8f18fc52ff290b6efc5b7d3a80e0b0261856805 100644 (file)
@@ -76,7 +76,7 @@ abort();
 #endif /* breakpoint */
 
 
-#if defined(WIN32) && !defined(__GNUC__)
+#if defined(_WIN32) && !defined(__GNUC__)
 #define MT_assert(predicate) assert(predicate)
 #else
 
index 3e5d64a3e35e666daa273f8e2278d427b72724c9..a96abb502154e80afd0680d11d529450b9eaea90 100644 (file)
@@ -1109,7 +1109,7 @@ def save_3ds(filename, context):
 #         Blender.Draw.PupMenu("Error%t|This script requires a full python installation")
 # # save_3ds('/test_b.3ds')
 from bpy.props import *
-class EXPORT_OT_autodesk_3ds(bpy.types.Operator):
+class Export3DS(bpy.types.Operator):
        '''Export to 3DS file format (.3ds).'''
        bl_idname = "export.autodesk_3ds"
        bl_label = 'Export 3DS'
@@ -1135,9 +1135,13 @@ class EXPORT_OT_autodesk_3ds(bpy.types.Operator):
                print("Poll")
                return context.active_object != None
 
-bpy.ops.add(EXPORT_OT_autodesk_3ds)
+bpy.ops.add(Export3DS)
 
 # Add to a menu
 import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("export.autodesk_3ds", text="Autodesk 3DS...")
+
+def menu_func(self, context):
+    default_path = bpy.data.filename.replace(".blend", ".3ds")
+    self.layout.item_stringO(Export3DS.bl_idname, "path", default_path, text="Autodesk 3DS...")
+
 menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
index b303e536b99dc22f34e248e2c46cbe2c94f38348..ec2d2791b5233dd35afadc97fa4d2163aed4705c 100644 (file)
@@ -237,14 +237,14 @@ def sane_groupname(data): return sane_name(data, sane_name_mapping_group)
 #      FORCE_CWD - dont use the basepath, just add a ./ to the filename.
 #              use when we know the file will be in the basepath.
 #      '''
-#      fname = bpy.sys.expandpath(fname_orig)
+#      fname = bpy.utils.expandpath(fname_orig)
 # #    fname = Blender.sys.expandpath(fname_orig)
 #      fname_strip = os.path.basename(fname)
 # #    fname_strip = strip_path(fname)
 #      if FORCE_CWD:
 #              fname_rel = '.' + os.sep + fname_strip
 #      else:
-#              fname_rel = bpy.sys.relpath(fname, basepath)
+#              fname_rel = bpy.utils.relpath(fname, basepath)
 # #            fname_rel = Blender.sys.relpath(fname, basepath)
 #      if fname_rel.startswith('//'): fname_rel = '.' + os.sep + fname_rel[2:]
 #      return fname, fname_strip, fname_rel
@@ -349,7 +349,7 @@ def write(filename, batch_objects = None, \
                fbxpath = filename
                
                # get the path component of filename
-               tmp_exists = bpy.sys.exists(fbxpath)
+               tmp_exists = bpy.utils.exists(fbxpath)
 #              tmp_exists = Blender.sys.exists(fbxpath)
                
                if tmp_exists != 2: # a file, we want a path
@@ -363,7 +363,7 @@ def write(filename, batch_objects = None, \
 #                              Draw.PupMenu('Error%t|Directory does not exist!')
                                return
 
-                       tmp_exists = bpy.sys.exists(fbxpath)
+                       tmp_exists = bpy.utils.exists(fbxpath)
 #                      tmp_exists = Blender.sys.exists(fbxpath)
                
                if tmp_exists != 2:
@@ -398,7 +398,7 @@ def write(filename, batch_objects = None, \
                                # path may alredy exist
                                # TODO - might exist but be a file. unlikely but should probably account for it.
 
-                               if bpy.sys.exists(new_fbxpath) == 0:
+                               if bpy.utils.exists(new_fbxpath) == 0:
 #                              if Blender.sys.exists(new_fbxpath) == 0:
                                        os.mkdir(new_fbxpath)
                                
@@ -3351,7 +3351,7 @@ def write_ui():
        
        # GLOBALS.clear()
 from bpy.props import *
-class EXPORT_OT_fbx(bpy.types.Operator):
+class ExportFBX(bpy.types.Operator):
        '''Selection to an ASCII Autodesk FBX'''
        bl_idname = "export.fbx"
        bl_label = "Export FBX"
@@ -3433,7 +3433,7 @@ class EXPORT_OT_fbx(bpy.types.Operator):
                return ('RUNNING_MODAL',)
 
 
-bpy.ops.add(EXPORT_OT_fbx)
+bpy.ops.add(ExportFBX)
 
 # if __name__ == "__main__":
 #      bpy.ops.EXPORT_OT_ply(filename="/tmp/test.ply")
@@ -3456,7 +3456,7 @@ bpy.ops.add(EXPORT_OT_fbx)
 # - bpy.data.remove_scene: line 366
 # - bpy.sys.time move to bpy.sys.util?
 # - new scene creation, activation: lines 327-342, 368
-# - uses bpy.sys.expandpath, *.relpath - replace at least relpath
+# - uses bpy.utils.expandpath, *.relpath - replace at least relpath
 
 # SMALL or COSMETICAL
 # - find a way to get blender version, and put it in bpy.util?, old was Blender.Get('version')
@@ -3464,6 +3464,10 @@ bpy.ops.add(EXPORT_OT_fbx)
 
 # Add to a menu
 import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("export.fbx", text="Autodesk FBX...")
+
+def menu_func(self, context):
+    default_path = bpy.data.filename.replace(".blend", ".fbx")
+    self.layout.item_stringO(ExportFBX.bl_idname, "path", default_path, text="Autodesk FBX...")
+
 menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
 
index 677361f33927ff56b7ddb3db9fbfcb33e3e82dbc..2b3e1681449fc043fdc9705ca6020f17bfdc8663 100644 (file)
@@ -54,148 +54,148 @@ import os
 #from Blender import *
 #import BPyMessages
 try:
-       from struct import pack
+    from struct import pack
 except:
-       pack = None
+    pack = None
 
 def zero_file(filepath):
-       '''
-       If a file fails, this replaces it with 1 char, better not remove it?
-       '''
-       file = open(filepath, 'w')
-       file.write('\n') # apparently macosx needs some data in a blank file?
-       file.close()
+    '''
+    If a file fails, this replaces it with 1 char, better not remove it?
+    '''
+    file = open(filepath, 'w')
+    file.write('\n') # apparently macosx needs some data in a blank file?
+    file.close()
 
 def check_vertcount(mesh,vertcount):
-       '''
-       check and make sure the vertcount is consistent throughout the frame range
-       '''
-       if len(mesh.verts) != vertcount:
-               raise Exception('Error, number of verts has changed during animation, cannot export')
-               f.close()
-               zero_file(filepath)
-               return
-       
-       
+    '''
+    check and make sure the vertcount is consistent throughout the frame range
+    '''
+    if len(mesh.verts) != vertcount:
+        raise Exception('Error, number of verts has changed during animation, cannot export')
+        f.close()
+        zero_file(filepath)
+        return
+    
+    
 def write(filename, sce, ob, PREF_STARTFRAME, PREF_ENDFRAME, PREF_FPS):
-       if not pack:
-               raise Exception('Error, this script requires the "pack" module')
-       
-       if ob.type != 'MESH':
-               raise Exception('Error, active object is not a mesh')
-       """
-       Window.EditMode(0)
-       Blender.Window.WaitCursor(1)
-
-       mesh_orig = Mesh.New()
-       mesh_orig.getFromObject(ob.name)
-       """
-       orig_frame = sce.current_frame
-       sce.set_frame(PREF_STARTFRAME)
-       me = ob.create_mesh(True, 'PREVIEW')
-
-       #Flip y and z
-       mat_flip= Mathutils.Matrix(\
-       [1.0, 0.0, 0.0, 0.0],\
-       [0.0, 0.0, 1.0, 0.0],\
-       [0.0, 1.0, 0.0, 0.0],\
-       [0.0, 0.0, 0.0, 1.0],\
-       )
-
-       numverts = len(me.verts)
-
-       numframes = PREF_ENDFRAME-PREF_STARTFRAME+1
-       PREF_FPS= float(PREF_FPS)
-       f = open(filename, 'wb') #no Errors yet:Safe to create file
-       
-       # Write the header
-       f.write(pack(">2i", numframes, numverts))
-       
-       # Write the frame times (should we use the time IPO??)
-       f.write( pack(">%df" % (numframes), *[frame/PREF_FPS for frame in range(numframes)]) ) # seconds
-       
-       #rest frame needed to keep frames in sync
-       """
-       Blender.Set('curframe', PREF_STARTFRAME)
-       me_tmp.getFromObject(ob.name)
-       """
-
-       check_vertcount(me,numverts)
-       me.transform(mat_flip * ob.matrix)
-       f.write(pack(">%df" % (numverts*3), *[axis for v in me.verts for axis in v.co]))
-               
-       for frame in range(PREF_STARTFRAME,PREF_ENDFRAME+1):#in order to start at desired frame
-               """
-               Blender.Set('curframe', frame)
-               me_tmp.getFromObject(ob.name)
-               """
-
-               sce.set_frame(frame)
-               me = ob.create_mesh(True, 'PREVIEW')
-               check_vertcount(me,numverts)
-               me.transform(mat_flip * ob.matrix)
-               
-               # Write the vertex data
-               f.write(pack(">%df" % (numverts*3), *[axis for v in me.verts for axis in v.co]))
-       
-       """
-       me_tmp.verts= None
-       """
-       f.close()
-       
-       print ('MDD Exported: %s frames:%d\n'% (filename, numframes-1))
-       """
-       Blender.Window.WaitCursor(0)
-       Blender.Set('curframe', orig_frame)
-       """
-       sce.set_frame(orig_frame)
+    """
+    Blender.Window.WaitCursor(1)
+
+    mesh_orig = Mesh.New()
+    mesh_orig.getFromObject(ob.name)
+    """
+
+    bpy.ops.object.mode_set(mode='OBJECT')
+
+    orig_frame = sce.current_frame
+    sce.set_frame(PREF_STARTFRAME)
+    me = ob.create_mesh(True, 'PREVIEW')
+
+    #Flip y and z
+    mat_flip= Mathutils.Matrix(\
+    [1.0, 0.0, 0.0, 0.0],\
+    [0.0, 0.0, 1.0, 0.0],\
+    [0.0, 1.0, 0.0, 0.0],\
+    [0.0, 0.0, 0.0, 1.0],\
+    )
+
+    numverts = len(me.verts)
+
+    numframes = PREF_ENDFRAME-PREF_STARTFRAME+1
+    PREF_FPS= float(PREF_FPS)
+    f = open(filename, 'wb') #no Errors yet:Safe to create file
+    
+    # Write the header
+    f.write(pack(">2i", numframes, numverts))
+    
+    # Write the frame times (should we use the time IPO??)
+    f.write( pack(">%df" % (numframes), *[frame/PREF_FPS for frame in range(numframes)]) ) # seconds
+    
+    #rest frame needed to keep frames in sync
+    """
+    Blender.Set('curframe', PREF_STARTFRAME)
+    me_tmp.getFromObject(ob.name)
+    """
+
+    check_vertcount(me,numverts)
+    me.transform(mat_flip * ob.matrix)
+    f.write(pack(">%df" % (numverts*3), *[axis for v in me.verts for axis in v.co]))
+        
+    for frame in range(PREF_STARTFRAME,PREF_ENDFRAME+1):#in order to start at desired frame
+        """
+        Blender.Set('curframe', frame)
+        me_tmp.getFromObject(ob.name)
+        """
+
+        sce.set_frame(frame)
+        me = ob.create_mesh(True, 'PREVIEW')
+        check_vertcount(me,numverts)
+        me.transform(mat_flip * ob.matrix)
+        
+        # Write the vertex data
+        f.write(pack(">%df" % (numverts*3), *[axis for v in me.verts for axis in v.co]))
+    
+    """
+    me_tmp.verts= None
+    """
+    f.close()
+    
+    print ('MDD Exported: %s frames:%d\n'% (filename, numframes-1))
+    """
+    Blender.Window.WaitCursor(0)
+    Blender.Set('curframe', orig_frame)
+    """
+    sce.set_frame(orig_frame)
 
 from bpy.props import *
 
-class EXPORT_OT_mdd(bpy.types.Operator):
-       '''Animated mesh to MDD vertex keyframe file.'''
-       bl_idname = "export.mdd"
-       bl_label = "Export MDD"
-
-       # get first scene to get min and max properties for frames, fps
-
-       sce = bpy.data.scenes[bpy.data.scenes.keys()[0]]
-       minframe = sce.rna_type.properties["current_frame"].soft_min
-       maxframe = sce.rna_type.properties["current_frame"].soft_max
-       minfps = sce.render_data.rna_type.properties["fps"].soft_min
-       maxfps = sce.render_data.rna_type.properties["fps"].soft_max
-
-       # List of operator properties, the attributes will be assigned
-       # to the class instance from the operator settings before calling.
-       path = StringProperty(name="File Path", description="File path used for exporting the MDD file", maxlen= 1024, default= "tmp.mdd")
-       fps = IntProperty(name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default= 25)
-       start_frame = IntProperty(name="Start Frame", description="Start frame for baking", min=minframe,max=maxframe,default=1)
-       end_frame = IntProperty(name="End Frame", description="End frame for baking", min=minframe, max=maxframe, default= 250)
-
-       def poll(self, context):
-               return context.active_object != None
-
-       def execute(self, context):
-               if not self.path:
-                       raise Exception("filename not set")
-               write(self.path, context.scene, context.active_object,
-                       self.start_frame, self.end_frame, self.fps )
-               return ('FINISHED',)
-       
-       def invoke(self, context, event):       
-               wm = context.manager
-               wm.add_fileselect(self)
-               return ('RUNNING_MODAL',)
-
-bpy.ops.add(EXPORT_OT_mdd)
+class ExportMDD(bpy.types.Operator):
+    '''Animated mesh to MDD vertex keyframe file.'''
+    bl_idname = "export.mdd"
+    bl_label = "Export MDD"
+
+    # get first scene to get min and max properties for frames, fps
+
+    sce = bpy.data.scenes[bpy.data.scenes.keys()[0]]
+    minframe = sce.rna_type.properties["current_frame"].soft_min
+    maxframe = sce.rna_type.properties["current_frame"].soft_max
+    minfps = sce.render_data.rna_type.properties["fps"].soft_min
+    maxfps = sce.render_data.rna_type.properties["fps"].soft_max
+
+    # List of operator properties, the attributes will be assigned
+    # to the class instance from the operator settings before calling.
+    path = StringProperty(name="File Path", description="File path used for exporting the MDD file", maxlen= 1024, default= "tmp.mdd")
+    fps = IntProperty(name="Frames Per Second", description="Number of frames/second", min=minfps, max=maxfps, default= 25)
+    start_frame = IntProperty(name="Start Frame", description="Start frame for baking", min=minframe,max=maxframe,default=1)
+    end_frame = IntProperty(name="End Frame", description="End frame for baking", min=minframe, max=maxframe, default= 250)
+
+    def poll(self, context):
+        ob = context.active_object
+        return (ob and ob.type=='MESH')
+
+    def execute(self, context):
+        if not self.path:
+            raise Exception("filename not set")
+        write(self.path, context.scene, context.active_object,
+            self.start_frame, self.end_frame, self.fps )
+        return ('FINISHED',)
+    
+    def invoke(self, context, event):
+        wm = context.manager
+        wm.add_fileselect(self)
+        return ('RUNNING_MODAL',)
+
+bpy.ops.add(ExportMDD)
 
 # Add to a menu
 import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("export.mdd", text="Vertex Keyframe Animation (.mdd)...")
+
+def menu_func(self, context):
+    default_path = bpy.data.filename.replace(".blend", ".mdd")
+    self.layout.item_stringO(ExportMDD.bl_idname, "path", default_path, text="Vertex Keyframe Animation (.mdd)...")
+
 menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
 
 if __name__=='__main__':
-       #if not pack:
-#              Draw.PupMenu('Error%t|This script requires a full python install')
-       #Blender.Window.FileSelector(mdd_export_ui, 'EXPORT MDD', sys.makename(ext='.mdd'))
-       bpy.ops.EXPORT_OT_mdd(path="/tmp/test.mdd")
+    #Blender.Window.FileSelector(mdd_export_ui, 'EXPORT MDD', sys.makename(ext='.mdd'))
+    bpy.ops.EXPORT_OT_mdd(path="/tmp/test.mdd")
index 72f1835fea8abd8f0b7d690a86e16ee7b420c352..2c77cbd702afe17dad133b89a68ceb7a30b1198e 100644 (file)
@@ -223,11 +223,11 @@ def copy_images(dest_dir):
        copyCount = 0
        
 #      for bImage in uniqueImages.values():
-#              image_path = bpy.sys.expandpath(bImage.filename)
+#              image_path = bpy.utils.expandpath(bImage.filename)
 #              if bpy.sys.exists(image_path):
 #                      # Make a name for the target path.
 #                      dest_image_path = dest_dir + image_path.split('\\')[-1].split('/')[-1]
-#                      if not bpy.sys.exists(dest_image_path): # Image isnt alredy there
+#                      if not bpy.utils.exists(dest_image_path): # Image isnt alredy there
 #                              print('\tCopying "%s" > "%s"' % (image_path, dest_image_path))
 #                              copy_file(image_path, dest_image_path)
 #                              copyCount+=1
@@ -932,7 +932,7 @@ Currently the exporter lacks these features:
 
 from bpy.props import *
 
-class EXPORT_OT_obj(bpy.types.Operator):
+class ExportOBJ(bpy.types.Operator):
        '''Save a Wavefront OBJ File'''
        
        bl_idname = "export.obj"
@@ -1002,10 +1002,14 @@ class EXPORT_OT_obj(bpy.types.Operator):
                print("Poll")
                return context.active_object != None
 
-bpy.ops.add(EXPORT_OT_obj)
+bpy.ops.add(ExportOBJ)
 
 import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("export.obj", text="Wavefront (.obj)...")
+
+def menu_func(self, context):
+    default_path = bpy.data.filename.replace(".blend", ".obj")
+    self.layout.item_stringO(ExportOBJ.bl_idname, "path", default_path, text="Wavefront (.obj)...")
+
 menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
 
 if __name__ == "__main__":
index 7235d51450e28792623966fe1b6c947f962ce083..99fa3233278105c10e2cdf14b78f267b94bbbb94 100644 (file)
@@ -252,7 +252,7 @@ def write(filename, scene, ob, \
 from bpy.props import *
 
 
-class EXPORT_OT_ply(bpy.types.Operator):
+class ExportPLY(bpy.types.Operator):
        '''Export a single object as a stanford PLY with normals, colours and texture coordinates.'''
        bl_idname = "export.ply"
        bl_label = "Export PLY"
@@ -292,10 +292,14 @@ class EXPORT_OT_ply(bpy.types.Operator):
                return ('RUNNING_MODAL',)
 
 
-bpy.ops.add(EXPORT_OT_ply)
+bpy.ops.add(ExportPLY)
 
 import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("export.ply", text="Stanford (.ply)...")
+
+def menu_func(self, context):
+    default_path = bpy.data.filename.replace(".blend", ".ply")
+    self.layout.item_stringO(ExportPLY.bl_idname, "path", default_path, text="Stanford (.ply)...")
+
 menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
 
 if __name__ == "__main__":
index 6de6725267650ccaf2f40756a3f977dedfc3ffa0..c8c5f71f6fff3513de437a76cf3c5af061b510a5 100644 (file)
@@ -1215,7 +1215,7 @@ def x3d_export_ui(filename):
 
 from bpy.props import *
 
-class EXPORT_OT_x3d(bpy.types.Operator):
+class ExportX3D(bpy.types.Operator):
        '''Export selection to Extensible 3D file (.x3d)'''
        bl_idname = "export.x3d"
        bl_label = 'Export X3D'
@@ -1238,10 +1238,14 @@ class EXPORT_OT_x3d(bpy.types.Operator):
                wm.add_fileselect(self)
                return ('RUNNING_MODAL',)
 
-bpy.ops.add(EXPORT_OT_x3d)
+bpy.ops.add(ExportX3D)
 
 import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("export.x3d", text="X3D Extensible 3D (.x3d)...")
+
+def menu_func(self, context):
+    default_path = bpy.data.filename.replace(".blend", ".x3d")
+    self.layout.item_stringO(ExportX3D.bl_idname, "path", default_path, text="X3D Extensible 3D (.x3d)...")
+
 menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_export, menu_func)
 
 # NOTES
diff --git a/release/scripts/io/import_anim_bvh.py b/release/scripts/io/import_anim_bvh.py
new file mode 100644 (file)
index 0000000..dff9a3a
--- /dev/null
@@ -0,0 +1,881 @@
+import math
+
+# import Blender
+import bpy
+# import BPyMessages
+import Mathutils
+Vector= Mathutils.Vector
+Euler= Mathutils.Euler
+Matrix= Mathutils.Matrix
+RotationMatrix= Mathutils.RotationMatrix
+TranslationMatrix= Mathutils.TranslationMatrix
+
+# NASTY GLOBAL
+ROT_STYLE = 'QUAT'
+
+DEG2RAD = 0.017453292519943295
+
+class bvh_node_class(object):
+       __slots__=(\
+       'name',# bvh joint name
+       'parent',# bvh_node_class type or None for no parent
+       'children',# a list of children of this type.
+       'rest_head_world',# worldspace rest location for the head of this node
+       'rest_head_local',# localspace rest location for the head of this node
+       'rest_tail_world',# # worldspace rest location for the tail of this node
+       'rest_tail_local',# # worldspace rest location for the tail of this node
+       'channels',# list of 6 ints, -1 for an unused channel, otherwise an index for the BVH motion data lines, lock triple then rot triple
+       'rot_order',# a triple of indicies as to the order rotation is applied. [0,1,2] is x/y/z - [None, None, None] if no rotation.
+       'anim_data',# a list one tuple's one for each frame. (locx, locy, locz, rotx, roty, rotz)
+       'has_loc',# Conveinience function, bool, same as (channels[0]!=-1 or channels[1]!=-1 channels[2]!=-1)
+       'has_rot',# Conveinience function, bool, same as (channels[3]!=-1 or channels[4]!=-1 channels[5]!=-1)
+       'temp')# use this for whatever you want
+       
+       def __init__(self, name, rest_head_world, rest_head_local, parent, channels, rot_order):
+               self.name= name
+               self.rest_head_world= rest_head_world
+               self.rest_head_local= rest_head_local
+               self.rest_tail_world= None
+               self.rest_tail_local= None
+               self.parent= parent
+               self.channels= channels
+               self.rot_order= rot_order
+               
+               # convenience functions
+               self.has_loc= channels[0] != -1 or channels[1] != -1 or channels[2] != -1
+               self.has_rot= channels[3] != -1 or channels[4] != -1 or channels[5] != -1
+               
+               
+               self.children= []
+               
+               # list of 6 length tuples: (lx,ly,lz, rx,ry,rz)
+               # even if the channels arnt used they will just be zero
+               # 
+               self.anim_data= [(0,0,0,0,0,0)] 
+               
+       
+       def __repr__(self):
+               return 'BVH name:"%s", rest_loc:(%.3f,%.3f,%.3f), rest_tail:(%.3f,%.3f,%.3f)' %\
+               (self.name,\
+               self.rest_head_world.x, self.rest_head_world.y, self.rest_head_world.z,\
+               self.rest_head_world.x, self.rest_head_world.y, self.rest_head_world.z)
+       
+
+
+# Change the order rotation is applied.
+MATRIX_IDENTITY_3x3 = Matrix([1,0,0],[0,1,0],[0,0,1])
+MATRIX_IDENTITY_4x4 = Matrix([1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1])
+
+def eulerRotate(x,y,z, rot_order): 
+       
+       # Clamp all values between 0 and 360, values outside this raise an error.
+       mats=[RotationMatrix(math.radians(x%360),3,'x'), RotationMatrix(math.radians(y%360),3,'y'), RotationMatrix(math.radians(z%360),3,'z')]
+       # print rot_order
+       # Standard BVH multiplication order, apply the rotation in the order Z,X,Y
+       
+       #XXX, order changes???
+       #eul = (mats[rot_order[2]]*(mats[rot_order[1]]* (mats[rot_order[0]]* MATRIX_IDENTITY_3x3))).toEuler()   
+       eul = (MATRIX_IDENTITY_3x3*mats[rot_order[0]]*(mats[rot_order[1]]* (mats[rot_order[2]]))).toEuler()     
+       
+       eul = math.degrees(eul.x), math.degrees(eul.y), math.degrees(eul.z) 
+       
+       return eul
+
+def read_bvh(context, file_path, GLOBAL_SCALE=1.0):
+       # File loading stuff
+       # Open the file for importing
+       file = open(file_path, 'rU')    
+       
+       # Seperate into a list of lists, each line a list of words.
+       file_lines = file.readlines()
+       # Non standard carrage returns?
+       if len(file_lines) == 1:
+               file_lines = file_lines[0].split('\r')
+       
+       # Split by whitespace.
+       file_lines =[ll for ll in [ l.split() for l in file_lines] if ll]
+       
+       
+       # Create Hirachy as empties
+       
+       if file_lines[0][0].lower() == 'hierarchy':
+               #print 'Importing the BVH Hierarchy for:', file_path
+               pass
+       else:
+               raise 'ERROR: This is not a BVH file'
+       
+       bvh_nodes= {None:None}
+       bvh_nodes_serial = [None]
+       
+       channelIndex = -1
+       
+
+       lineIdx = 0 # An index for the file.
+       while lineIdx < len(file_lines) -1:
+               #...
+               if file_lines[lineIdx][0].lower() == 'root' or file_lines[lineIdx][0].lower() == 'joint':
+                       
+                       # Join spaces into 1 word with underscores joining it.
+                       if len(file_lines[lineIdx]) > 2:
+                               file_lines[lineIdx][1] = '_'.join(file_lines[lineIdx][1:])
+                               file_lines[lineIdx] = file_lines[lineIdx][:2]
+                       
+                       # MAY NEED TO SUPPORT MULTIPLE ROOT's HERE!!!, Still unsure weather multiple roots are possible.??
+                       
+                       # Make sure the names are unique- Object names will match joint names exactly and both will be unique.
+                       name = file_lines[lineIdx][1]
+                       
+                       #print '%snode: %s, parent: %s' % (len(bvh_nodes_serial) * '  ', name,  bvh_nodes_serial[-1])
+                       
+                       lineIdx += 2 # Incriment to the next line (Offset)
+                       rest_head_local = Vector( GLOBAL_SCALE*float(file_lines[lineIdx][1]), GLOBAL_SCALE*float(file_lines[lineIdx][2]), GLOBAL_SCALE*float(file_lines[lineIdx][3]) )
+                       lineIdx += 1 # Incriment to the next line (Channels)
+                       
+                       # newChannel[Xposition, Yposition, Zposition, Xrotation, Yrotation, Zrotation]
+                       # newChannel references indecies to the motiondata,
+                       # if not assigned then -1 refers to the last value that will be added on loading at a value of zero, this is appended 
+                       # We'll add a zero value onto the end of the MotionDATA so this is always refers to a value.
+                       my_channel = [-1, -1, -1, -1, -1, -1] 
+                       my_rot_order= [None, None, None]
+                       rot_count= 0
+                       for channel in file_lines[lineIdx][2:]:
+                               channel= channel.lower()
+                               channelIndex += 1 # So the index points to the right channel
+                               if   channel == 'xposition':    my_channel[0] = channelIndex
+                               elif channel == 'yposition':    my_channel[1] = channelIndex
+                               elif channel == 'zposition':    my_channel[2] = channelIndex
+                               
+                               elif channel == 'xrotation':
+                                       my_channel[3] = channelIndex
+                                       my_rot_order[rot_count]= 0
+                                       rot_count+=1
+                               elif channel == 'yrotation':
+                                       my_channel[4] = channelIndex
+                                       my_rot_order[rot_count]= 1
+                                       rot_count+=1
+                               elif channel == 'zrotation':
+                                       my_channel[5] = channelIndex
+                                       my_rot_order[rot_count]= 2
+                                       rot_count+=1
+                       
+                       channels = file_lines[lineIdx][2:]
+                       
+                       my_parent= bvh_nodes_serial[-1] # account for none
+                       
+                       
+                       # Apply the parents offset accumletivly
+                       if my_parent==None:
+                               rest_head_world= Vector(rest_head_local)
+                       else:
+                               rest_head_world= my_parent.rest_head_world + rest_head_local
+                       
+                       bvh_node= bvh_nodes[name]= bvh_node_class(name, rest_head_world, rest_head_local, my_parent, my_channel, my_rot_order)
+                       
+                       # If we have another child then we can call ourselves a parent, else 
+                       bvh_nodes_serial.append(bvh_node)
+
+               # Account for an end node
+               if file_lines[lineIdx][0].lower() == 'end' and file_lines[lineIdx][1].lower() == 'site': # There is somtimes a name after 'End Site' but we will ignore it.
+                       lineIdx += 2 # Incriment to the next line (Offset)
+                       rest_tail = Vector( GLOBAL_SCALE*float(file_lines[lineIdx][1]), GLOBAL_SCALE*float(file_lines[lineIdx][2]), GLOBAL_SCALE*float(file_lines[lineIdx][3]) )
+                       
+                       bvh_nodes_serial[-1].rest_tail_world= bvh_nodes_serial[-1].rest_head_world + rest_tail
+                       bvh_nodes_serial[-1].rest_tail_local= rest_tail
+                       
+                       
+                       # Just so we can remove the Parents in a uniform way- End end never has kids
+                       # so this is a placeholder
+                       bvh_nodes_serial.append(None)
+               
+               if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0] == '}': # == ['}']
+                       bvh_nodes_serial.pop() # Remove the last item
+               
+               if len(file_lines[lineIdx]) == 1 and file_lines[lineIdx][0].lower() == 'motion':
+                       #print '\nImporting motion data'
+                       lineIdx += 3 # Set the cursor to the first frame
+                       break
+                       
+               lineIdx += 1
+       
+       
+       # Remove the None value used for easy parent reference
+       del bvh_nodes[None]
+       # Dont use anymore
+       del bvh_nodes_serial
+       
+       bvh_nodes_list= bvh_nodes.values()
+       
+       while lineIdx < len(file_lines):
+               line= file_lines[lineIdx]
+               for bvh_node in bvh_nodes_list:
+                       #for bvh_node in bvh_nodes_serial:
+                       lx= ly= lz= rx= ry= rz= 0.0
+                       channels= bvh_node.channels
+                       anim_data= bvh_node.anim_data
+                       if channels[0] != -1:
+                               lx= GLOBAL_SCALE * float(  line[channels[0]] )
+                               
+                       if channels[1] != -1:
+                               ly= GLOBAL_SCALE * float(  line[channels[1]] )
+                       
+                       if channels[2] != -1:
+                               lz= GLOBAL_SCALE * float(  line[channels[2]] )
+                       
+                       if channels[3] != -1 or channels[4] != -1 or channels[5] != -1:
+                               rx, ry, rz = float( line[channels[3]] ), float( line[channels[4]] ), float( line[channels[5]] )
+                               
+                               if ROT_STYLE != 'NATIVE':
+                                       rx, ry, rz = eulerRotate(rx, ry, rz, bvh_node.rot_order)
+                               
+                               #x,y,z = x/10.0, y/10.0, z/10.0 # For IPO's 36 is 360d
+                               
+                               # Make interpolation not cross between 180d, thjis fixes sub frame interpolation and time scaling.
+                               # Will go from (355d to 365d) rather then to (355d to 5d) - inbetween these 2 there will now be a correct interpolation.
+                               
+                               while anim_data[-1][3] - rx >  180: rx+=360
+                               while anim_data[-1][3] - rx < -180: rx-=360
+                               
+                               while anim_data[-1][4] - ry >  180: ry+=360
+                               while anim_data[-1][4] - ry < -180: ry-=360
+                               
+                               while anim_data[-1][5] - rz >  180: rz+=360
+                               while anim_data[-1][5] - rz < -180: rz-=360
+                               
+                       # Done importing motion data #
+                       anim_data.append( (lx, ly, lz, rx, ry, rz) )
+               lineIdx += 1
+       
+       # Assign children
+       for bvh_node in bvh_nodes.values():             
+               bvh_node_parent= bvh_node.parent
+               if bvh_node_parent:
+                       bvh_node_parent.children.append(bvh_node)
+       
+       # Now set the tip of each bvh_node
+       for bvh_node in bvh_nodes.values():
+               
+               if not bvh_node.rest_tail_world:
+                       if len(bvh_node.children)==0:
+                               # could just fail here, but rare BVH files have childless nodes
+                               bvh_node.rest_tail_world = Vector(bvh_node.rest_head_world)
+                               bvh_node.rest_tail_local = Vector(bvh_node.rest_head_local)
+                       elif len(bvh_node.children)==1:
+                               bvh_node.rest_tail_world= Vector(bvh_node.children[0].rest_head_world)
+                               bvh_node.rest_tail_local= Vector(bvh_node.children[0].rest_head_local)
+                       else:
+                               # allow this, see above
+                               #if not bvh_node.children:
+                               #       raise 'error, bvh node has no end and no children. bad file'
+                                       
+                               # Removed temp for now
+                               rest_tail_world= Vector(0,0,0)
+                               rest_tail_local= Vector(0,0,0)
+                               for bvh_node_child in bvh_node.children:
+                                       rest_tail_world += bvh_node_child.rest_head_world
+                                       rest_tail_local += bvh_node_child.rest_head_local
+                               
+                               bvh_node.rest_tail_world= rest_tail_world * (1.0/len(bvh_node.children))
+                               bvh_node.rest_tail_local= rest_tail_local * (1.0/len(bvh_node.children))
+
+               # Make sure tail isnt the same location as the head.
+               if (bvh_node.rest_tail_local-bvh_node.rest_head_local).length <= 0.001*GLOBAL_SCALE:
+                       
+                       bvh_node.rest_tail_local.y= bvh_node.rest_tail_local.y + GLOBAL_SCALE/10
+                       bvh_node.rest_tail_world.y= bvh_node.rest_tail_world.y + GLOBAL_SCALE/10
+                       
+               
+               
+       return bvh_nodes
+
+
+
+def bvh_node_dict2objects(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOOP= False):
+       
+       if IMPORT_START_FRAME<1:
+               IMPORT_START_FRAME= 1
+               
+       scn= context.scene
+       scn.objects.selected = []
+       
+       objects= []
+       
+       def add_ob(name):
+               ob = scn.objects.new('Empty')
+               objects.append(ob)
+               return ob
+       
+       # Add objects
+       for name, bvh_node in bvh_nodes.items():
+               bvh_node.temp= add_ob(name)
+       
+       # Parent the objects
+       for bvh_node in bvh_nodes.values():
+               bvh_node.temp.makeParent([ bvh_node_child.temp for bvh_node_child in bvh_node.children ], 1, 0) # ojbs, noninverse, 1 = not fast.
+       
+       # Offset
+       for bvh_node in bvh_nodes.values():
+               # Make relative to parents offset
+               bvh_node.temp.loc= bvh_node.rest_head_local
+       
+       # Add tail objects
+       for name, bvh_node in bvh_nodes.items():
+               if not bvh_node.children:
+                       ob_end= add_ob(name + '_end')
+                       bvh_node.temp.makeParent([ob_end], 1, 0) # ojbs, noninverse, 1 = not fast.
+                       ob_end.loc= bvh_node.rest_tail_local
+       
+       
+       # Animate the data, the last used bvh_node will do since they all have the same number of frames
+       for current_frame in range(len(bvh_node.anim_data)):
+               Blender.Set('curframe', current_frame+IMPORT_START_FRAME)
+               
+               for bvh_node in bvh_nodes.values():
+                       lx,ly,lz,rx,ry,rz= bvh_node.anim_data[current_frame]
+                       
+                       rest_head_local= bvh_node.rest_head_local
+                       bvh_node.temp.loc= rest_head_local.x+lx, rest_head_local.y+ly, rest_head_local.z+lz
+                       
+                       bvh_node.temp.rot= rx*DEG2RAD,ry*DEG2RAD,rz*DEG2RAD
+                       
+                       bvh_node.temp.insertIpoKey(Blender.Object.IpoKeyTypes.LOCROT)
+       
+       scn.update(1)
+       return objects
+
+
+
+def bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME= 1, IMPORT_LOOP= False):
+       
+       if IMPORT_START_FRAME<1:
+               IMPORT_START_FRAME= 1
+               
+       
+       # Add the new armature, 
+       scn = context.scene
+#XXX   scn.objects.selected = []
+       for ob in scn.objects:
+               ob.selected = False
+       
+       
+#XXX   arm_data= bpy.data.armatures.new()
+#XXX   arm_ob = scn.objects.new(arm_data)
+       bpy.ops.object.armature_add()
+       arm_ob= scn.objects[-1]
+       arm_data= arm_ob.data
+
+       
+       
+       
+#XXX   scn.objects.context = [arm_ob]
+#XXX   scn.objects.active = arm_ob
+       arm_ob.selected= True
+       scn.objects.active= arm_ob
+       print(scn.objects.active)
+       
+       
+       # Put us into editmode
+#XXX   arm_data.makeEditable()
+       
+       bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+       bpy.ops.object.mode_set(mode='EDIT', toggle=False)
+
+       
+       
+       # Get the average bone length for zero length bones, we may not use this.
+       average_bone_length= 0.0
+       nonzero_count= 0
+       for bvh_node in bvh_nodes.values():
+               l= (bvh_node.rest_head_local-bvh_node.rest_tail_local).length
+               if l:
+                       average_bone_length+= l
+                       nonzero_count+=1
+       
+       # Very rare cases all bones couldbe zero length???
+       if not average_bone_length:
+               average_bone_length = 0.1
+       else:
+               # Normal operation
+               average_bone_length = average_bone_length/nonzero_count
+       
+       
+#XXX - sloppy operator code
+       
+       bpy.ops.armature.delete()
+       bpy.ops.armature.select_all_toggle()
+       bpy.ops.armature.delete()
+
+       ZERO_AREA_BONES= []
+       for name, bvh_node in bvh_nodes.items():
+               # New editbone
+               bpy.ops.armature.bone_primitive_add(name="Bone")
+               
+#XXX           bone= bvh_node.temp= Blender.Armature.Editbone()
+               bone= bvh_node.temp= arm_data.edit_bones[-1]
+
+               bone.name= name
+#              arm_data.bones[name]= bone
+               
+               bone.head= bvh_node.rest_head_world
+               bone.tail= bvh_node.rest_tail_world
+               
+               # ZERO AREA BONES.
+               if (bone.head-bone.tail).length < 0.001:
+                       if bvh_node.parent:
+                               ofs= bvh_node.parent.rest_head_local- bvh_node.parent.rest_tail_local
+                               if ofs.length: # is our parent zero length also?? unlikely
+                                       bone.tail= bone.tail+ofs
+                               else:
+                                       bone.tail.y= bone.tail.y+average_bone_length
+                       else:
+                               bone.tail.y= bone.tail.y+average_bone_length
+                       
+                       ZERO_AREA_BONES.append(bone.name)
+       
+       
+       for bvh_node in bvh_nodes.values():
+               if bvh_node.parent:
+                       # bvh_node.temp is the Editbone
+                       
+                       # Set the bone parent
+                       bvh_node.temp.parent= bvh_node.parent.temp
+                       
+                       # Set the connection state
+                       if not bvh_node.has_loc and\
+                       bvh_node.parent and\
+                       bvh_node.parent.temp.name not in ZERO_AREA_BONES and\
+                       bvh_node.parent.rest_tail_local == bvh_node.rest_head_local:
+                               bvh_node.temp.connected= True
+       
+       # Replace the editbone with the editbone name,
+       # to avoid memory errors accessing the editbone outside editmode
+       for bvh_node in bvh_nodes.values():
+               bvh_node.temp= bvh_node.temp.name
+       
+#XXX   arm_data.update()
+       
+       # Now Apply the animation to the armature
+       
+       # Get armature animation data
+       bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
+       bpy.ops.object.mode_set(mode='POSE', toggle=False)
+       
+       pose= arm_ob.pose
+       pose_bones= pose.pose_channels
+       
+       
+       if ROT_STYLE=='NATIVE':
+               eul_order_lookup = {\
+                       (0,1,2):'XYZ',
+                       (0,2,1):'XZY',
+                       (1,0,2):'YXZ',
+                       (1,2,0):'YZX',
+                       (2,0,1):'ZXY',
+                       (2,1,0):'ZYZ'
+               }
+               
+               for bvh_node in bvh_nodes.values():
+                       bone_name= bvh_node.temp # may not be the same name as the bvh_node, could have been shortened.
+                       pose_bone= pose_bones[bone_name]
+                       pose_bone.rotation_mode  = eul_order_lookup[tuple(bvh_node.rot_order)]
+               
+       elif ROT_STYLE=='XYZ':
+               for pose_bone in pose_bones:
+                       pose_bone.rotation_mode  = 'XYZ'
+       else:
+               # Quats default
+               pass 
+       
+       
+       bpy.ops.pose.select_all_toggle() # set
+       bpy.ops.anim.insert_keyframe_menu(type=-4) # XXX -     -4 ???
+       
+
+       
+       
+       
+       #for p in pose_bones:
+       #       print(p)
+       
+       
+#XXX   action = Blender.Armature.NLA.NewAction("Action") 
+#XXX   action.setActive(arm_ob)
+       
+       #bpy.ops.act.new()
+       #action = bpy.data.actions[-1]
+       
+       # arm_ob.animation_data.action = action
+       action = arm_ob.animation_data.action
+       
+       
+       
+       
+       #xformConstants= [ Blender.Object.Pose.LOC, Blender.Object.Pose.ROT ]
+       
+       # Replace the bvh_node.temp (currently an editbone)
+       # With a tuple  (pose_bone, armature_bone, bone_rest_matrix, bone_rest_matrix_inv)
+       for bvh_node in bvh_nodes.values():
+               bone_name= bvh_node.temp # may not be the same name as the bvh_node, could have been shortened.
+               pose_bone= pose_bones[bone_name]
+               rest_bone= arm_data.bones[bone_name]
+#XXX           bone_rest_matrix = rest_bone.matrix['ARMATURESPACE'].rotationPart()
+               bone_rest_matrix = rest_bone.matrix.rotationPart()
+               
+               
+               bone_rest_matrix_inv= Matrix(bone_rest_matrix)
+               bone_rest_matrix_inv.invert()
+               
+               bone_rest_matrix_inv.resize4x4()
+               bone_rest_matrix.resize4x4()
+               bvh_node.temp= (pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv)
+               
+       
+       # Make a dict for fast access without rebuilding a list all the time.
+       '''
+       xformConstants_dict={
+       (True,True):    [Blender.Object.Pose.LOC, Blender.Object.Pose.ROT],\
+       (False,True):   [Blender.Object.Pose.ROT],\
+       (True,False):   [Blender.Object.Pose.LOC],\
+       (False,False):  [],\
+       }
+       '''
+       
+       # KEYFRAME METHOD, SLOW, USE IPOS DIRECT
+       
+       # Animate the data, the last used bvh_node will do since they all have the same number of frames
+       for current_frame in range(len(bvh_node.anim_data)-1): # skip the first frame (rest frame)
+               # print current_frame
+               
+               #if current_frame==150: # debugging
+               #       break
+               
+               # Dont neet to set the current frame
+               for bvh_node in bvh_nodes.values():
+                       pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
+                       lx,ly,lz,rx,ry,rz= bvh_node.anim_data[current_frame+1]
+                       
+                       if bvh_node.has_rot:
+                               
+                               if ROT_STYLE=='QUAT':
+                                       # Set the rotation, not so simple
+                                       bone_rotation_matrix= Euler(math.radians(rx), math.radians(ry), math.radians(rz)).toMatrix()
+                                       
+                                       bone_rotation_matrix.resize4x4()
+                                       #XXX ORDER CHANGE???
+                                       #pose_bone.rotation_quaternion= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat() # ORIGINAL
+                                       # pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix).toQuat()
+                                       # pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix).toQuat() # BAD
+                                       # pose_bone.rotation_quaternion= bone_rotation_matrix.toQuat() # NOT GOOD
+                                       # pose_bone.rotation_quaternion= bone_rotation_matrix.toQuat() # NOT GOOD
+                                       
+                                       #pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix_inv * bone_rest_matrix).toQuat()
+                                       #pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rest_matrix * bone_rotation_matrix).toQuat()
+                                       #pose_bone.rotation_quaternion= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat()
+                                       
+                                       #pose_bone.rotation_quaternion= ( bone_rest_matrix* bone_rest_matrix_inv * bone_rotation_matrix).toQuat()
+                                       #pose_bone.rotation_quaternion= (bone_rotation_matrix * bone_rest_matrix  * bone_rest_matrix_inv).toQuat()
+                                       #pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix  * bone_rest_matrix ).toQuat()
+                                       
+                                       pose_bone.rotation_quaternion= (bone_rest_matrix_inv * bone_rotation_matrix * bone_rest_matrix).toQuat()
+                                       
+                               else:
+                                       bone_rotation_matrix= Euler(math.radians(rx), math.radians(ry), math.radians(rz)).toMatrix()
+                                       bone_rotation_matrix.resize4x4()
+                                       
+                                       eul= (bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toEuler()
+                                       
+                                       #pose_bone.rotation_euler = math.radians(rx), math.radians(ry), math.radians(rz)
+                                       pose_bone.rotation_euler = eul
+                               
+                               print("ROTATION" + str(Euler(math.radians(rx), math.radians(ry), math.radians(rz))))
+                       
+                       if bvh_node.has_loc:
+                               # Set the Location, simple too
+                               
+                               #XXX ORDER CHANGE
+                               # pose_bone.location= (TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local ) * bone_rest_matrix_inv).translationPart() # WHY * 10? - just how pose works
+                               # pose_bone.location= (bone_rest_matrix_inv * TranslationMatrix(Vector(lx, ly, lz) - bvh_node.rest_head_local )).translationPart()
+                               # pose_bone.location= lx, ly, lz
+                               pose_bone.location= Vector(lx, ly, lz) - bvh_node.rest_head_local
+                               
+
+#XXX           # TODO- add in 2.5
+                       if 0:
+                               # Get the transform 
+                               xformConstants= xformConstants_dict[bvh_node.has_loc, bvh_node.has_rot]
+                               
+                               if xformConstants:
+                                       # Insert the keyframe from the loc/quat
+                                       pose_bone.insertKey(arm_ob, current_frame+IMPORT_START_FRAME, xformConstants, True )
+                       else:
+                               
+                               if bvh_node.has_loc:
+                                       pose_bone.keyframe_insert("location")
+                               if bvh_node.has_rot:
+                                       if ROT_STYLE=='QUAT':
+                                               pose_bone.keyframe_insert("rotation_quaternion")
+                                       else:
+                                               pose_bone.keyframe_insert("rotation_euler")
+                               
+                               
+                       
+               # bpy.ops.anim.insert_keyframe_menu(type=-4) # XXX -     -4 ???
+               bpy.ops.screen.frame_offset(delta=1)
+               
+               # First time, set the IPO's to linear
+#XXX   #TODO
+               if 0:
+                       if current_frame==0:
+                               for ipo in action.getAllChannelIpos().values():
+                                       if ipo:
+                                               for cur in ipo:
+                                                       cur.interpolation = Blender.IpoCurve.InterpTypes.LINEAR
+                                                       if IMPORT_LOOP:
+                                                               cur.extend = Blender.IpoCurve.ExtendTypes.CYCLIC
+                                                       
+                                               
+               else:
+                       for cu in action.fcurves:
+                               for bez in cu.keyframe_points:
+                                       bez.interpolation = 'CONSTANT'
+               
+       # END KEYFRAME METHOD
+       
+       
+       """
+       # IPO KEYFRAME SETTING
+       # Add in the IPOs by adding keyframes, AFAIK theres no way to add IPOs to an action so I do this :/
+       for bvh_node in bvh_nodes.values():
+               pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
+               
+               # Get the transform 
+               xformConstants= xformConstants_dict[bvh_node.has_loc, bvh_node.has_rot]
+               if xformConstants:
+                       pose_bone.loc[:]= 0,0,0
+                       pose_bone.quat[:]= 0,0,1,0
+                       # Insert the keyframe from the loc/quat
+                       pose_bone.insertKey(arm_ob, IMPORT_START_FRAME, xformConstants)
+
+       
+       action_ipos= action.getAllChannelIpos()
+       
+       
+       for bvh_node in bvh_nodes.values():
+               has_loc= bvh_node.has_loc
+               has_rot= bvh_node.has_rot
+               
+               if not has_rot and not has_loc:
+                       # No animation data
+                       continue
+               
+               ipo= action_ipos[bvh_node.temp[0].name] # posebones name as key
+               
+               if has_loc:
+                       curve_xloc= ipo[Blender.Ipo.PO_LOCX]
+                       curve_yloc= ipo[Blender.Ipo.PO_LOCY]
+                       curve_zloc= ipo[Blender.Ipo.PO_LOCZ]
+                       
+                       curve_xloc.interpolation= \
+                       curve_yloc.interpolation= \
+                       curve_zloc.interpolation= \
+                       Blender.IpoCurve.InterpTypes.LINEAR
+                       
+               
+               if has_rot:
+                       curve_wquat= ipo[Blender.Ipo.PO_QUATW]
+                       curve_xquat= ipo[Blender.Ipo.PO_QUATX]
+                       curve_yquat= ipo[Blender.Ipo.PO_QUATY]
+                       curve_zquat= ipo[Blender.Ipo.PO_QUATZ]
+                       
+                       curve_wquat.interpolation= \
+                       curve_xquat.interpolation= \
+                       curve_yquat.interpolation= \
+                       curve_zquat.interpolation= \
+                       Blender.IpoCurve.InterpTypes.LINEAR
+               
+               # Get the bone 
+               pose_bone, bone, bone_rest_matrix, bone_rest_matrix_inv= bvh_node.temp
+               
+               
+               def pose_rot(anim_data):
+                       bone_rotation_matrix= Euler(anim_data[3], anim_data[4], anim_data[5]).toMatrix()
+                       bone_rotation_matrix.resize4x4()
+                       return tuple((bone_rest_matrix * bone_rotation_matrix * bone_rest_matrix_inv).toQuat()) # qw,qx,qy,qz
+               
+               def pose_loc(anim_data):
+                       return tuple((TranslationMatrix(Vector(anim_data[0], anim_data[1], anim_data[2])) * bone_rest_matrix_inv).translationPart())
+               
+               
+               last_frame= len(bvh_node.anim_data)+IMPORT_START_FRAME-1
+               
+               if has_loc:
+                       pose_locations= [pose_loc(anim_key) for anim_key in bvh_node.anim_data]
+                       
+                       # Add the start at the end, we know the start is just 0,0,0 anyway
+                       curve_xloc.append((last_frame, pose_locations[-1][0]))
+                       curve_yloc.append((last_frame, pose_locations[-1][1]))
+                       curve_zloc.append((last_frame, pose_locations[-1][2]))
+                       
+                       if len(pose_locations) > 1:
+                               ox,oy,oz= pose_locations[0]
+                               x,y,z= pose_locations[1]
+                               
+                               for i in range(1, len(pose_locations)-1): # from second frame to second last frame
+                                       
+                                       nx,ny,nz= pose_locations[i+1]
+                                       xset= yset= zset= True # we set all these by default
+                                       if abs((ox+nx)/2 - x) < 0.00001:        xset= False
+                                       if abs((oy+ny)/2 - y) < 0.00001:        yset= False
+                                       if abs((oz+nz)/2 - z) < 0.00001:        zset= False
+                                       
+                                       if xset: curve_xloc.append((i+IMPORT_START_FRAME, x))
+                                       if yset: curve_yloc.append((i+IMPORT_START_FRAME, y))
+                                       if zset: curve_zloc.append((i+IMPORT_START_FRAME, z))
+                                       
+                                       # Set the old and use the new
+                                       ox,oy,oz=       x,y,z
+                                       x,y,z=          nx,ny,nz
+               
+               
+               if has_rot:
+                       pose_rotations= [pose_rot(anim_key) for anim_key in bvh_node.anim_data]
+                       
+                       # Add the start at the end, we know the start is just 0,0,0 anyway
+                       curve_wquat.append((last_frame, pose_rotations[-1][0]))
+                       curve_xquat.append((last_frame, pose_rotations[-1][1]))
+                       curve_yquat.append((last_frame, pose_rotations[-1][2]))
+                       curve_zquat.append((last_frame, pose_rotations[-1][3]))
+                       
+                       
+                       if len(pose_rotations) > 1:
+                               ow,ox,oy,oz= pose_rotations[0]
+                               w,x,y,z= pose_rotations[1]
+                               
+                               for i in range(1, len(pose_rotations)-1): # from second frame to second last frame
+                                       
+                                       nw, nx,ny,nz= pose_rotations[i+1]
+                                       wset= xset= yset= zset= True # we set all these by default
+                                       if abs((ow+nw)/2 - w) < 0.00001:        wset= False
+                                       if abs((ox+nx)/2 - x) < 0.00001:        xset= False
+                                       if abs((oy+ny)/2 - y) < 0.00001:        yset= False
+                                       if abs((oz+nz)/2 - z) < 0.00001:        zset= False
+                                       
+                                       if wset: curve_wquat.append((i+IMPORT_START_FRAME, w))
+                                       if xset: curve_xquat.append((i+IMPORT_START_FRAME, x))
+                                       if yset: curve_yquat.append((i+IMPORT_START_FRAME, y))
+                                       if zset: curve_zquat.append((i+IMPORT_START_FRAME, z))
+                                       
+                                       # Set the old and use the new
+                                       ow,ox,oy,oz=    w,x,y,z
+                                       w,x,y,z=                nw,nx,ny,nz
+
+       # IPO KEYFRAME SETTING
+       """
+       
+# XXX NOT NEEDED NOW?
+       # pose.update()
+       return arm_ob
+
+
+#=============#
+# TESTING     #
+#=============#
+
+#('/metavr/mocap/bvh/boxer.bvh')
+#('/d/staggered_walk.bvh')
+#('/metavr/mocap/bvh/dg-306-g.bvh') # Incompleate EOF
+#('/metavr/mocap/bvh/wa8lk.bvh') # duplicate joint names, \r line endings.
+#('/metavr/mocap/bvh/walk4.bvh') # 0 channels
+
+'''
+import os
+DIR = '/metavr/mocap/bvh/'
+for f in ('/d/staggered_walk.bvh',):
+       #for f in os.listdir(DIR)[5:6]:
+       #for f in os.listdir(DIR):
+       if f.endswith('.bvh'):
+               s = Blender.Scene.New(f)
+               s.makeCurrent()
+               #file= DIR + f
+               file= f
+               print f
+               bvh_nodes= read_bvh(file, 1.0)
+               bvh_node_dict2armature(bvh_nodes, 1)
+'''
+
+def load_bvh_ui(context, file, PREF_UI= False):
+       
+#XXX   if BPyMessages.Error_NoFile(file):
+#XXX           return
+       
+#XXX   Draw= Blender.Draw
+       
+       IMPORT_SCALE = 0.1
+       IMPORT_START_FRAME = 1
+       IMPORT_AS_ARMATURE = 1
+       IMPORT_AS_EMPTIES = 0
+       IMPORT_LOOP = 0
+       
+       # Get USER Options
+       if PREF_UI:
+               pup_block = [\
+               ('As Armature', IMPORT_AS_ARMATURE, 'Imports the BVH as an armature'),\
+               ('As Empties', IMPORT_AS_EMPTIES, 'Imports the BVH as empties'),\
+               ('Scale: ', IMPORT_SCALE, 0.001, 100.0, 'Scale the BVH, Use 0.01 when 1.0 is 1 metre'),\
+               ('Start Frame: ', IMPORT_START_FRAME, 1, 30000, 'Frame to start BVH motion'),\
+               ('Loop Animation', IMPORT_LOOP, 'Enable cyclic IPOs'),\
+               ]
+               
+#XXX           if not Draw.PupBlock('BVH Import...', pup_block):
+#XXX                   return
+       
+       # print('Attempting import BVH', file)
+       
+       if not IMPORT_AS_ARMATURE and not IMPORT_AS_EMPTIES:
+               raise('No import option selected')
+
+#XXX   Blender.Window.WaitCursor(1)
+       # Get the BVH data and act on it.
+       import time
+       t1= time.time()
+       print('\tparsing bvh...', end= "")
+       bvh_nodes= read_bvh(context, file, IMPORT_SCALE)
+       print('%.4f' % (time.time()-t1))
+       t1= time.time()
+       print('\timporting to blender...', end="")
+       if IMPORT_AS_ARMATURE:  bvh_node_dict2armature(context, bvh_nodes, IMPORT_START_FRAME, IMPORT_LOOP)
+       if IMPORT_AS_EMPTIES:   bvh_node_dict2objects(context, bvh_nodes,  IMPORT_START_FRAME, IMPORT_LOOP)
+       
+       print('Done in %.4f\n' % (time.time()-t1))
+#XXX   Blender.Window.WaitCursor(0)
+
+def main():
+       Blender.Window.FileSelector(load_bvh_ui, 'Import BVH', '*.bvh')
+
+from bpy.props import *
+
+class BvhImporter(bpy.types.Operator):
+       '''Load a Wavefront OBJ File.'''
+       bl_idname = "import_anim.bvh"
+       bl_label = "Import BVH"
+       
+       path = StringProperty(name="File Path", description="File path used for importing the OBJ file", maxlen= 1024, default= "")
+       
+       def execute(self, context):
+               # print("Selected: " + context.active_object.name)
+
+               read_bvh(context, self.path)
+
+               return ('FINISHED',)
+       
+       def invoke(self, context, event):       
+               wm = context.manager
+               wm.add_fileselect(self)
+               return ('RUNNING_MODAL',)
+
+
+bpy.ops.add(BvhImporter)
+
+
+import dynamic_menu
+menu_func = lambda self, context: self.layout.itemO(BvhImporter.bl_idname, text="Motion Capture (.bvh)...")
+menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func)
similarity index 99%
rename from release/scripts/io/import_3ds.py
rename to release/scripts/io/import_scene_3ds.py
index 62612cc79d4ea03e174b63a4b084beaa7138be13..cd351ccb99e20bf863e5e933a4fbd7965ddd3656 100644 (file)
@@ -139,7 +139,7 @@ import os
 import time
 import struct
 
-from import_obj import unpack_face_list, load_image
+from import_scene_obj import unpack_face_list, load_image
 
 import bpy
 import Mathutils
@@ -1143,7 +1143,7 @@ from bpy.props import *
 
 class IMPORT_OT_autodesk_3ds(bpy.types.Operator):
        '''Import from 3DS file format (.3ds)'''
-       bl_idname = "import.autodesk_3ds"
+       bl_idname = "import_scene.autodesk_3ds"
        bl_label = 'Import 3DS'
        
        # List of operator properties, the attributes will be assigned
@@ -1167,7 +1167,7 @@ class IMPORT_OT_autodesk_3ds(bpy.types.Operator):
 bpy.ops.add(IMPORT_OT_autodesk_3ds)
 
 import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("import.autodesk_3ds", text="3D Studio (.3ds)...")
+menu_func = lambda self, context: self.layout.itemO(IMPORT_OT_autodesk_3ds.bl_idname, text="3D Studio (.3ds)...")
 menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func)
 
 # NOTES:
similarity index 99%
rename from release/scripts/io/import_obj.py
rename to release/scripts/io/import_scene_obj.py
index e5e0dc35995db7e529de402fbaf2b4ff520de830..d1b29a3024da96f7e61d48cfeae118f05f1e109f 100644 (file)
@@ -1574,7 +1574,7 @@ from bpy.props import *
 
 class IMPORT_OT_obj(bpy.types.Operator):
        '''Load a Wavefront OBJ File.'''
-       bl_idname = "import.obj"
+       bl_idname = "import_scene.obj"
        bl_label = "Import OBJ"
        
        # List of operator properties, the attributes will be assigned
@@ -1626,7 +1626,7 @@ bpy.ops.add(IMPORT_OT_obj)
 
 
 import dynamic_menu
-menu_func = lambda self, context: self.layout.itemO("import.obj", text="Wavefront (.obj)...")
+menu_func = lambda self, context: self.layout.itemO(IMPORT_OT_obj.bl_idname, text="Wavefront (.obj)...")
 menu_item = dynamic_menu.add(bpy.types.INFO_MT_file_import, menu_func)
 
 
index 8694d7782aece3d1332269f15f8aaed1847a86b8..52643af7d73b96d7702c91e45fb7b1e7b1a7a9cf 100644 (file)
@@ -46,7 +46,7 @@ def addPointCache(job, ob, point_cache, default_path):
        if name == "":
                name = "".join(["%02X" % ord(c) for c in ob.name])
        
-       cache_path = bpy.sys.expandpath(point_cache.filepath) if point_cache.external else default_path
+       cache_path = bpy.utils.expandpath(point_cache.filepath) if point_cache.external else default_path
        
        index = "%02i" % point_cache.index
        
@@ -111,14 +111,14 @@ def clientSendJob(conn, scene, anim = False):
        # LIBRARIES
        ###########################
        for lib in bpy.data.libraries:
-               job.addFile(bpy.sys.expandpath(lib_path))
+               job.addFile(bpy.utils.expandpath(lib_path))
                
        ###########################
        # IMAGES
        ###########################
        for image in bpy.data.images:
                if image.source == "FILE" and not image.packed_file:
-                       job.addFile(bpy.sys.expandpath(image.filename))
+                       job.addFile(bpy.utils.expandpath(image.filename))
        
        ###########################
        # FLUID + POINT CACHE
@@ -129,7 +129,7 @@ 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.sys.expandpath(modifier.settings.path))
+                               addFluidFiles(job, bpy.utils.expandpath(modifier.settings.path))
                        elif modifier.type == "CLOTH":
                                addPointCache(job, object, modifier.point_cache, default_path)
                        elif modifier.type == "SOFT_BODY":
@@ -253,3 +253,15 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
                        
                        conn.close()
 
+def compatible(module):
+       exec("import " + module)
+       module = eval(module)
+       for member in dir(module):
+               subclass = getattr(module, member)
+               try:            subclass.COMPAT_ENGINES.add('NET_RENDER')
+               except: pass
+       del module
+
+compatible("properties_render")
+compatible("properties_world")
+compatible("properties_material")
index c30869669cc20b1ebb22e4f9c5ccbbda51ba2c25..55df062ac83be1df9c075c109ed6507755bdecc5 100644 (file)
@@ -186,365 +186,3 @@ class bpy_ops_submodule_op(object):
 
 import bpy
 bpy.ops = bpy_ops()
-
-# TODO, C macro's cant define settings :|
-
-from bpy.props import *
-
-
-class MESH_OT_delete_edgeloop(bpy.types.Operator):
-    '''Export a single object as a stanford PLY with normals,
-    colours and texture coordinates.'''
-    bl_idname = "mesh.delete_edgeloop"
-    bl_label = "Delete Edge Loop"
-
-    def execute(self, context):
-        bpy.ops.tfm.edge_slide(value=1.0)
-        bpy.ops.mesh.select_more()
-        bpy.ops.mesh.remove_doubles()
-        return ('FINISHED',)
-
-rna_path_prop = StringProperty(name="Context Attributes",
-        description="rna context string", maxlen=1024, default="")
-
-rna_reverse_prop = BoolProperty(name="Reverse",
-        description="Cycle backwards", default=False)
-
-
-class NullPathMember:
-    pass
-
-
-def context_path_validate(context, path):
-    import sys
-    try:
-        value = eval("context.%s" % path)
-    except AttributeError:
-        if "'NoneType'" in str(sys.exc_info()[1]):
-            # One of the items in the rna path is None, just ignore this
-            value = NullPathMember
-        else:
-            # We have a real error in the rna path, dont ignore that
-            raise
-
-    return value
-
-
-def execute_context_assign(self, context):
-    if context_path_validate(context, self.path) == NullPathMember:
-        return ('PASS_THROUGH',)
-
-    exec("context.%s=self.value" % self.path)
-    return ('FINISHED',)
-
-
-class WM_OT_context_set_boolean(bpy.types.Operator):
-    '''Set a context value.'''
-    bl_idname = "wm.context_set_boolean"
-    bl_label = "Context Set"
-
-    path = rna_path_prop
-    value = BoolProperty(name="Value",
-            description="Assignment value", default=True)
-
-    execute = execute_context_assign
-
-
-class WM_OT_context_set_int(bpy.types.Operator): # same as enum
-    '''Set a context value.'''
-    bl_idname = "wm.context_set_int"
-    bl_label = "Context Set"
-
-    path = rna_path_prop
-    value = IntProperty(name="Value", description="Assign value", default=0)
-
-    execute = execute_context_assign
-
-
-class WM_OT_context_set_float(bpy.types.Operator): # same as enum
-    '''Set a context value.'''
-    bl_idname = "wm.context_set_int"
-    bl_label = "Context Set"
-
-    path = rna_path_prop
-    value = FloatProperty(name="Value",
-            description="Assignment value", default=0.0)
-
-    execute = execute_context_assign
-
-
-class WM_OT_context_set_string(bpy.types.Operator): # same as enum
-    '''Set a context value.'''
-    bl_idname = "wm.context_set_string"
-    bl_label = "Context Set"
-
-    path = rna_path_prop
-    value = StringProperty(name="Value",
-            description="Assign value", maxlen=1024, default="")
-
-    execute = execute_context_assign
-
-
-class WM_OT_context_set_enum(bpy.types.Operator):
-    '''Set a context value.'''
-    bl_idname = "wm.context_set_enum"
-    bl_label = "Context Set"
-
-    path = rna_path_prop
-    value = StringProperty(name="Value",
-            description="Assignment value (as a string)",
-            maxlen=1024, default="")
-
-    execute = execute_context_assign
-
-
-class WM_OT_context_toggle(bpy.types.Operator):
-    '''Toggle a context value.'''
-    bl_idname = "wm.context_toggle"
-    bl_label = "Context Toggle"
-    path = rna_path_prop
-
-    def execute(self, context):
-
-        if context_path_validate(context, self.path) == NullPathMember:
-            return ('PASS_THROUGH',)
-
-        exec("context.%s=not (context.%s)" % (self.path, self.path))
-        return ('FINISHED',)
-
-
-class WM_OT_context_toggle_enum(bpy.types.Operator):
-    '''Toggle a context value.'''
-    bl_idname = "wm.context_toggle_enum"
-    bl_label = "Context Toggle Values"
-
-    path = rna_path_prop
-    value_1 = StringProperty(name="Value", \
-                description="Toggle enum", maxlen=1024, default="")
-
-    value_2 = StringProperty(name="Value", \
-                description="Toggle enum", maxlen=1024, default="")
-
-    def execute(self, context):
-
-        if context_path_validate(context, self.path) == NullPathMember:
-            return ('PASS_THROUGH',)
-
-        exec("context.%s = ['%s', '%s'][context.%s!='%s']" % \
-            (self.path, self.value_1, self.value_2, self.path, self.value_2))
-
-        return ('FINISHED',)
-
-
-class WM_OT_context_cycle_int(bpy.types.Operator):
-    '''Set a context value. Useful for cycling active material,
-    vertex keys, groups' etc.'''
-    bl_idname = "wm.context_cycle_int"
-    bl_label = "Context Int Cycle"
-    path = rna_path_prop
-    reverse = rna_reverse_prop
-
-    def execute(self, context):
-
-        value = context_path_validate(context, self.path)
-        if value == NullPathMember:
-            return ('PASS_THROUGH',)
-
-        self.value = value
-        if self.reverse:
-            self.value -= 1
-        else:
-            self.value += 1
-        execute_context_assign(self, context)
-
-        if self.value != eval("context.%s" % self.path):
-            # relies on rna clamping int's out of the range
-            if self.reverse:
-                self.value = (1 << 32)
-            else:
-                self.value = - (1 << 32)
-            execute_context_assign(self, context)
-
-        return ('FINISHED',)
-
-
-class WM_OT_context_cycle_enum(bpy.types.Operator):
-    '''Toggle a context value.'''
-    bl_idname = "wm.context_cycle_enum"
-    bl_label = "Context Enum Cycle"
-
-    path = rna_path_prop
-    reverse = rna_reverse_prop
-
-    def execute(self, context):
-
-        value = context_path_validate(context, self.path)
-        if value == NullPathMember:
-            return ('PASS_THROUGH',)
-
-        orig_value = value
-
-        # Have to get rna enum values
-        rna_struct_str, rna_prop_str = self.path.rsplit('.', 1)
-        i = rna_prop_str.find('[')
-
-        # just incse we get "context.foo.bar[0]"
-        if i != -1:
-            rna_prop_str = rna_prop_str[0:i]
-
-        rna_struct = eval("context.%s.rna_type" % rna_struct_str)
-
-        rna_prop = rna_struct.properties[rna_prop_str]
-
-        if type(rna_prop) != bpy.types.EnumProperty:
-            raise Exception("expected an enum property")
-
-        enums = rna_struct.properties[rna_prop_str].items.keys()
-        orig_index = enums.index(orig_value)
-
-        # Have the info we need, advance to the next item
-        if self.reverse:
-            if orig_index == 0:
-                advance_enum = enums[-1]
-            else:
-                advance_enum = enums[orig_index-1]
-        else:
-            if orig_index == len(enums) - 1:
-                advance_enum = enums[0]
-            else:
-                advance_enum = enums[orig_index + 1]
-
-        # set the new value
-        exec("context.%s=advance_enum" % self.path)
-        return ('FINISHED',)
-
-doc_id = StringProperty(name="Doc ID",
-        description="ID for the documentation", maxlen=1024, default="")
-
-doc_new = StringProperty(name="Doc New",
-        description="", maxlen=1024, default="")
-
-
-class WM_OT_doc_view(bpy.types.Operator):
-    '''Load online reference docs'''
-    bl_idname = "wm.doc_view"
-    bl_label = "View Documentation"
-
-    doc_id = doc_id
-    _prefix = 'http://www.blender.org/documentation/250PythonDoc'
-
-    def _nested_class_string(self, class_string):
-        ls = []
-        class_obj = getattr(bpy.types, class_string, None).bl_rna
-        while class_obj:
-            ls.insert(0, class_obj)
-            class_obj = class_obj.nested
-        return '.'.join([class_obj.identifier for class_obj in ls])
-
-    def execute(self, context):
-        id_split = self.doc_id.split('.')
-        if len(id_split) == 1: # rna, class
-            url = '%s/bpy.types.%s-class.html' % (self._prefix, id_split[0])
-        elif len(id_split) == 2: # rna, class.prop
-            class_name, class_prop = id_split
-
-            # It so happens that epydoc nests these
-            class_name_full = self._nested_class_string(class_name)
-
-            if hasattr(bpy.types, class_name.upper() + '_OT_' + class_prop):
-                url = '%s/bpy.ops.%s-module.html#%s' % \
-                        (self._prefix, class_name_full, class_prop)
-            else:
-                url = '%s/bpy.types.%s-class.html#%s' % \
-                        (self._prefix, class_name_full, class_prop)
-
-        else:
-            return ('PASS_THROUGH',)
-
-        import webbrowser
-        webbrowser.open(url)
-
-        return ('FINISHED',)
-
-
-class WM_OT_doc_edit(bpy.types.Operator):
-    '''Load online reference docs'''
-    bl_idname = "wm.doc_edit"
-    bl_label = "Edit Documentation"
-
-    doc_id = doc_id
-    doc_new = doc_new
-
-    _url = "http://www.mindrones.com/blender/svn/xmlrpc.php"
-
-    def _send_xmlrpc(self, data_dict):
-        print("sending data:", data_dict)
-
-        import xmlrpc.client
-        user = 'blenderuser'
-        pwd = 'blender>user'
-
-        docblog = xmlrpc.client.ServerProxy(self._url)
-        docblog.metaWeblog.newPost(1, user, pwd, data_dict, 1)
-
-    def execute(self, context):
-
-        class_name, class_prop = self.doc_id.split('.')
-
-        if not self.doc_new:
-            return 'OPERATOR_CANCELLED'
-
-        # check if this is an operator
-        op_name = class_name.upper() + '_OT_' + class_prop
-        op_class = getattr(bpy.types, op_name, None)
-
-        # Upload this to the web server
-        upload = {}
-
-        if op_class:
-            rna = op_class.bl_rna
-            doc_orig = rna.description
-            if doc_orig == self.doc_new:
-                return 'OPERATOR_CANCELLED'
-
-            print("op - old:'%s' -> new:'%s'" % (doc_orig, self.doc_new))
-            upload["title"] = 'OPERATOR %s:%s' % (self.doc_id, doc_orig)
-            upload["description"] = self.doc_new
-
-            self._send_xmlrpc(upload)
-
-        else:
-            rna = getattr(bpy.types, class_name).bl_rna
-            doc_orig = rna.properties[class_prop].description
-            if doc_orig == self.doc_new:
-                return 'OPERATOR_CANCELLED'
-
-            print("rna - old:'%s' -> new:'%s'" % (doc_orig, self.doc_new))
-            upload["title"] = 'RNA %s:%s' % s(self.doc_id, doc_orig)
-
-        upload["description"] = self.doc_new
-
-        self._send_xmlrpc(upload)
-
-        return ('FINISHED',)
-
-    def invoke(self, context, event):
-        wm = context.manager
-        wm.invoke_props_popup(self, event)
-        return ('RUNNING_MODAL',)
-
-
-bpy.ops.add(MESH_OT_delete_edgeloop)
-
-bpy.ops.add(WM_OT_context_set_boolean)
-bpy.ops.add(WM_OT_context_set_int)
-bpy.ops.add(WM_OT_context_set_float)
-bpy.ops.add(WM_OT_context_set_string)
-bpy.ops.add(WM_OT_context_set_enum)
-bpy.ops.add(WM_OT_context_toggle)
-bpy.ops.add(WM_OT_context_toggle_enum)
-bpy.ops.add(WM_OT_context_cycle_enum)
-bpy.ops.add(WM_OT_context_cycle_int)
-
-bpy.ops.add(WM_OT_doc_view)
-bpy.ops.add(WM_OT_doc_edit)
similarity index 92%
rename from release/scripts/modules/bpy_sys.py
rename to release/scripts/modules/bpy_utils.py
index 86f9c9d63a204a8230ddb3e7c221d214a2384491..dde01152daed20e890aba9f164b73f243130239d 100644 (file)
@@ -26,5 +26,5 @@ def expandpath(path):
     return path
 
 import types
-bpy.sys = types.ModuleType("bpy.sys")
-bpy.sys.expandpath = expandpath
+bpy.utils = types.ModuleType("bpy.utils")
+bpy.utils.expandpath = expandpath
similarity index 95%
rename from release/scripts/io/add_mesh_torus.py
rename to release/scripts/op/add_mesh_torus.py
index 8a6a3a58ed60ca86f9b1209e96c45b3857786681..ddc4f0b977002a2f33aa714a860f2a697a6cfa74 100644 (file)
@@ -74,7 +74,7 @@ def add_torus(major_rad, minor_rad, major_seg, minor_seg):
 from bpy.props import *
 
 
-class AddTorusPrimitive(bpy.types.Operator):
+class AddTorus(bpy.types.Operator):
     '''Add a torus mesh.'''
     bl_idname = "mesh.primitive_torus_add"
     bl_label = "Add Torus"
@@ -117,7 +117,7 @@ class AddTorusPrimitive(bpy.types.Operator):
         ob_new = bpy.data.add_object('MESH', "Torus")
         ob_new.data = mesh
         scene.add_object(ob_new)
-        scene.active_object = ob_new
+        scene.objects.active = ob_new
         ob_new.selected = True
 
         ob_new.location = tuple(context.scene.cursor_location)
@@ -125,12 +125,12 @@ class AddTorusPrimitive(bpy.types.Operator):
         return ('FINISHED',)
 
 # Register the operator
-bpy.ops.add(AddTorusPrimitive)
+bpy.ops.add(AddTorus)
 
 # Add to a menu
 import dynamic_menu
 
-menu_func = (lambda self, context: self.layout.itemO("mesh.primitive_torus_add",
+menu_func = (lambda self, context: self.layout.itemO(AddTorus.bl_idname,
                                         text="Torus", icon='ICON_MESH_DONUT'))
 
 menu_item = dynamic_menu.add(bpy.types.INFO_MT_mesh_add, menu_func)
diff --git a/release/scripts/op/uvcalc_smart_project.py b/release/scripts/op/uvcalc_smart_project.py
new file mode 100644 (file)
index 0000000..328470a
--- /dev/null
@@ -0,0 +1,1163 @@
+# -------------------------------------------------------------------------- 
+# Smart Projection UV Projection Unwrapper v1.2 by Campbell Barton (AKA Ideasman) 
+# -------------------------------------------------------------------------- 
+# ***** 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
+# 
+# ***** END GPL LICENCE BLOCK ***** 
+# -------------------------------------------------------------------------- 
+
+
+#from Blender import Object, Draw, Window, sys, Mesh, Geometry
+from Mathutils import Matrix, Vector, RotationMatrix
+import time
+import Geometry
+import bpy
+from math import cos, degrees, radians
+
+DEG_TO_RAD = 0.017453292519943295 # pi/180.0
+SMALL_NUM = 0.000000001
+BIG_NUM = 1e15
+
+global USER_FILL_HOLES
+global USER_FILL_HOLES_QUALITY
+USER_FILL_HOLES = None
+USER_FILL_HOLES_QUALITY = None
+
+dict_matrix = {}
+
+def pointInTri2D(v, v1, v2, v3):
+       global dict_matrix
+       
+       key = v1.x, v1.y, v2.x, v2.y, v3.x, v3.y
+       
+       # Commented because its slower to do teh bounds check, we should realy cache the bounds info for each face.
+       '''
+       # BOUNDS CHECK
+       xmin= 1000000
+       ymin= 1000000
+       
+       xmax= -1000000
+       ymax= -1000000
+       
+       for i in (0,2,4):
+               x= key[i]
+               y= key[i+1]
+               
+               if xmax<x:      xmax= x
+               if ymax<y:      ymax= y
+               if xmin>x:      xmin= x
+               if ymin>y:      ymin= y 
+       
+       x= v.x
+       y= v.y
+       
+       if x<xmin or x>xmax or y < ymin or y > ymax:
+               return False
+       # Done with bounds check
+       '''
+       try:
+               mtx = dict_matrix[key]
+               if not mtx:
+                       return False
+       except:
+               side1 = v2 - v1
+               side2 = v3 - v1
+               
+               nor = side1.cross(side2)
+               
+               l1 = [side1[0], side1[1], side1[2]]
+               l2 = [side2[0], side2[1], side2[2]]
+               l3 = [nor[0], nor[1], nor[2]]
+               
+               mtx = Matrix(l1, l2, l3)
+               
+               # Zero area 2d tri, even tho we throw away zerop area faces
+               # the projection UV can result in a zero area UV.
+               if not mtx.determinant():
+                       dict_matrix[key] = None
+                       return False
+               
+               mtx.invert()
+               
+               dict_matrix[key] = mtx
+       
+       uvw = (v - v1) * mtx
+       return 0 <= uvw[0] and 0 <= uvw[1] and uvw[0] + uvw[1] <= 1
+
+       
+def boundsIsland(faces):
+       minx = maxx = faces[0].uv[0][0] # Set initial bounds.
+       miny = maxy = faces[0].uv[0][1]
+       # print len(faces), minx, maxx, miny , maxy
+       for f in faces:
+               for uv in f.uv:
+                       x= uv.x
+                       y= uv.y
+                       if x<minx: minx= x
+                       if y<miny: miny= y
+                       if x>maxx: maxx= x
+                       if y>maxy: maxy= y
+       
+       return minx, miny, maxx, maxy
+
+"""
+def boundsEdgeLoop(edges):
+       minx = maxx = edges[0][0] # Set initial bounds.
+       miny = maxy = edges[0][1]
+       # print len(faces), minx, maxx, miny , maxy
+       for ed in edges:
+               for pt in ed:
+                       print 'ass'
+                       x= pt[0]
+                       y= pt[1]
+                       if x<minx: x= minx
+                       if y<miny: y= miny
+                       if x>maxx: x= maxx
+                       if y>maxy: y= maxy
+       
+       return minx, miny, maxx, maxy
+"""
+
+# Turns the islands into a list of unpordered edges (Non internal)
+# Onlt for UV's
+# only returns outline edges for intersection tests. and unique points.
+
+def island2Edge(island):
+       
+       # Vert index edges
+       edges = {}
+       
+       unique_points= {}
+       
+       for f in island:
+               f_uvkey= map(tuple, f.uv)
+               
+               
+               for vIdx, edkey in enumerate(f.edge_keys):
+                       unique_points[f_uvkey[vIdx]] = f.uv[vIdx]
+                       
+                       if f.v[vIdx].index > f.v[vIdx-1].index:
+                               i1= vIdx-1;     i2= vIdx
+                       else:           
+                               i1= vIdx;       i2= vIdx-1
+                       
+                       try:    edges[ f_uvkey[i1], f_uvkey[i2] ] *= 0 # sets eny edge with more then 1 user to 0 are not returned.
+                       except: edges[ f_uvkey[i1], f_uvkey[i2] ] = (f.uv[i1] - f.uv[i2]).length, 
+       
+       # If 2 are the same then they will be together, but full [a,b] order is not correct.
+       
+       # Sort by length
+       
+               
+       length_sorted_edges = [(Vector(key[0]), Vector(key[1]), value) for key, value in edges.items() if value != 0]
+       
+       try:    length_sorted_edges.sort(key = lambda A: -A[2]) # largest first
+       except: length_sorted_edges.sort(lambda A, B: cmp(B[2], A[2]))
+       
+       # Its okay to leave the length in there.
+       #for e in length_sorted_edges:
+       #       e.pop(2)
+       
+       # return edges and unique points
+       return length_sorted_edges, [v.__copy__().resize3D() for v in unique_points.values()]
+       
+# ========================= NOT WORKING????
+# Find if a points inside an edge loop, un-orderd.
+# pt is and x/y
+# edges are a non ordered loop of edges.
+# #offsets are the edge x and y offset.
+"""
+def pointInEdges(pt, edges):
+       #
+       x1 = pt[0] 
+       y1 = pt[1]
+       
+       # Point to the left of this line.
+       x2 = -100000
+       y2 = -10000
+       intersectCount = 0
+       for ed in edges:
+               xi, yi = lineIntersection2D(x1,y1, x2,y2, ed[0][0], ed[0][1], ed[1][0], ed[1][1])
+               if xi != None: # Is there an intersection.
+                       intersectCount+=1
+       
+       return intersectCount % 2
+"""
+
+def pointInIsland(pt, island):
+       vec1 = Vector(); vec2 = Vector(); vec3 = Vector()       
+       for f in island:
+               vec1.x, vec1.y = f.uv[0]
+               vec2.x, vec2.y = f.uv[1]
+               vec3.x, vec3.y = f.uv[2]
+
+               if pointInTri2D(pt, vec1, vec2, vec3):
+                       return True
+               
+               if len(f.v) == 4:
+                       vec1.x, vec1.y = f.uv[0]
+                       vec2.x, vec2.y = f.uv[2]
+                       vec3.x, vec3.y = f.uv[3]                        
+                       if pointInTri2D(pt, vec1, vec2, vec3):
+                               return True
+       return False
+
+
+# box is (left,bottom, right, top)
+def islandIntersectUvIsland(source, target, SourceOffset):
+       # Is 1 point in the box, inside the vertLoops
+       edgeLoopsSource = source[6] # Pretend this is offset
+       edgeLoopsTarget = target[6]
+       
+       # Edge intersect test   
+       for ed in edgeLoopsSource:
+               for seg in edgeLoopsTarget:
+                       i = Geometry.LineIntersect2D(\
+                       seg[0], seg[1], SourceOffset+ed[0], SourceOffset+ed[1])
+                       if i:
+                               return 1 # LINE INTERSECTION
+       
+       # 1 test for source being totally inside target
+       SourceOffset.resize3D()
+       for pv in source[7]:
+               if pointInIsland(pv+SourceOffset, target[0]):
+                       return 2 # SOURCE INSIDE TARGET
+       
+       # 2 test for a part of the target being totaly inside the source.
+       for pv in target[7]:
+               if pointInIsland(pv-SourceOffset, source[0]):
+                       return 3 # PART OF TARGET INSIDE SOURCE.
+
+       return 0 # NO INTERSECTION
+
+
+
+
+# Returns the X/y Bounds of a list of vectors.
+def testNewVecLs2DRotIsBetter(vecs, mat=-1, bestAreaSoFar = -1):
+       
+       # UV's will never extend this far.
+       minx = miny = BIG_NUM
+       maxx = maxy = -BIG_NUM
+       
+       for i, v in enumerate(vecs):
+               
+               # Do this allong the way
+               if mat != -1:
+                       v = vecs[i] = v*mat
+                       x= v.x
+                       y= v.y
+                       if x<minx: minx= x
+                       if y<miny: miny= y
+                       if x>maxx: maxx= x
+                       if y>maxy: maxy= y
+               
+               # Spesific to this algo, bail out if we get bigger then the current area
+               if bestAreaSoFar != -1 and (maxx-minx) * (maxy-miny) > bestAreaSoFar:
+                       return (BIG_NUM, None), None
+       w = maxx-minx
+       h = maxy-miny
+       return (w*h, w,h), vecs # Area, vecs
+       
+# Takes a list of faces that make up a UV island and rotate
+# until they optimally fit inside a square.
+ROTMAT_2D_POS_90D = RotationMatrix( radians(90.0), 2)
+ROTMAT_2D_POS_45D = RotationMatrix( radians(45.0), 2)
+
+RotMatStepRotation = []
+rot_angle = 22.5 #45.0/2
+while rot_angle > 0.1:
+       RotMatStepRotation.append([\
+        RotationMatrix( radians(rot_angle), 2),\
+        RotationMatrix( radians(-rot_angle), 2)])
+       
+       rot_angle = rot_angle/2.0
+       
+
+def optiRotateUvIsland(faces):
+       global currentArea
+       
+       # Bestfit Rotation
+       def best2dRotation(uvVecs, MAT1, MAT2):
+               global currentArea
+               
+               newAreaPos, newfaceProjectionGroupListPos =\
+               testNewVecLs2DRotIsBetter(uvVecs[:], MAT1, currentArea[0])
+               
+               
+               # Why do I use newpos here? May as well give the best area to date for an early bailout
+               # some slight speed increase in this.
+               # If the new rotation is smaller then the existing, we can 
+               # avoid copying a list and overwrite the old, crappy one.
+               
+               if newAreaPos[0] < currentArea[0]:
+                       newAreaNeg, newfaceProjectionGroupListNeg =\
+                       testNewVecLs2DRotIsBetter(uvVecs, MAT2, newAreaPos[0])  # Reuse the old bigger list.
+               else:
+                       newAreaNeg, newfaceProjectionGroupListNeg =\
+                       testNewVecLs2DRotIsBetter(uvVecs[:], MAT2, currentArea[0])  # Cant reuse, make a copy.
+               
+               
+               # Now from the 3 options we need to discover which to use
+               # we have cerrentArea/newAreaPos/newAreaNeg
+               bestArea = min(currentArea[0], newAreaPos[0], newAreaNeg[0])
+               
+               if currentArea[0] == bestArea:
+                       return uvVecs
+               elif newAreaPos[0] == bestArea:
+                       uvVecs = newfaceProjectionGroupListPos
+                       currentArea = newAreaPos                
+               elif newAreaNeg[0] == bestArea:
+                       uvVecs = newfaceProjectionGroupListNeg
+                       currentArea = newAreaNeg
+               
+               return uvVecs
+               
+       
+       # Serialized UV coords to Vectors
+       uvVecs = [uv for f in faces  for uv in f.uv]
+       
+       # Theres a small enough number of these to hard code it
+       # rather then a loop.
+       
+       # Will not modify anything
+       currentArea, dummy =\
+       testNewVecLs2DRotIsBetter(uvVecs)
+       
+       
+       # Try a 45d rotation
+       newAreaPos, newfaceProjectionGroupListPos = testNewVecLs2DRotIsBetter(uvVecs[:], ROTMAT_2D_POS_45D, currentArea[0])
+       
+       if newAreaPos[0] < currentArea[0]:
+               uvVecs = newfaceProjectionGroupListPos
+               currentArea = newAreaPos
+       # 45d done
+       
+       # Testcase different rotations and find the onfe that best fits in a square
+       for ROTMAT in RotMatStepRotation:
+               uvVecs = best2dRotation(uvVecs, ROTMAT[0], ROTMAT[1])
+       
+       # Only if you want it, make faces verticle!
+       if currentArea[1] > currentArea[2]:
+               # Rotate 90d
+               # Work directly on the list, no need to return a value.
+               testNewVecLs2DRotIsBetter(uvVecs, ROTMAT_2D_POS_90D)
+       
+       
+       # Now write the vectors back to the face UV's
+       i = 0 # count the serialized uv/vectors
+       for f in faces:
+               #f.uv = [uv for uv in uvVecs[i:len(f)+i] ]
+               for j, k in enumerate(range(i, len(f.v)+i)):
+                       f.uv[j][:] = uvVecs[k]
+               i += len(f.v)
+
+
+# Takes an island list and tries to find concave, hollow areas to pack smaller islands into.
+def mergeUvIslands(islandList):
+       global USER_FILL_HOLES
+       global USER_FILL_HOLES_QUALITY
+       
+       
+       # Pack islands to bottom LHS
+       # Sync with island
+       
+       #islandTotFaceArea = [] # A list of floats, each island area
+       #islandArea = [] # a list of tuples ( area, w,h)
+       
+       
+       decoratedIslandList = []
+       
+       islandIdx = len(islandList)
+       while islandIdx:
+               islandIdx-=1
+               minx, miny, maxx, maxy = boundsIsland(islandList[islandIdx])
+               w, h = maxx-minx, maxy-miny
+               
+               totFaceArea = 0
+               offset= Vector(minx, miny)
+               for f in islandList[islandIdx]:
+                       for uv in f.uv:
+                               uv -= offset
+                       
+                       totFaceArea += f.area
+               
+               islandBoundsArea = w*h
+               efficiency = abs(islandBoundsArea - totFaceArea)
+               
+               # UV Edge list used for intersections as well as unique points.
+               edges, uniqueEdgePoints = island2Edge(islandList[islandIdx])
+               
+               decoratedIslandList.append([islandList[islandIdx], totFaceArea, efficiency, islandBoundsArea, w,h, edges, uniqueEdgePoints]) 
+               
+       
+       # Sort by island bounding box area, smallest face area first.
+       # no.. chance that to most simple edge loop first.
+       decoratedIslandListAreaSort =decoratedIslandList[:]
+       
+       decoratedIslandListAreaSort.sort(key = lambda A: A[3])
+       
+       # sort by efficiency, Least Efficient first.
+       decoratedIslandListEfficSort = decoratedIslandList[:]
+       # decoratedIslandListEfficSort.sort(lambda A, B: cmp(B[2], A[2]))
+
+       decoratedIslandListEfficSort.sort(key = lambda A: -A[2])
+
+       # ================================================== THESE CAN BE TWEAKED.
+       # This is a quality value for the number of tests.
+       # from 1 to 4, generic quality value is from 1 to 100
+       USER_STEP_QUALITY =   ((USER_FILL_HOLES_QUALITY - 1) / 25.0) + 1
+       
+       # If 100 will test as long as there is enough free space.
+       # this is rarely enough, and testing takes a while, so lower quality speeds this up.
+       
+       # 1 means they have the same quality 
+       USER_FREE_SPACE_TO_TEST_QUALITY = 1 + (((100 - USER_FILL_HOLES_QUALITY)/100.0) *5)
+       
+       #print 'USER_STEP_QUALITY', USER_STEP_QUALITY
+       #print 'USER_FREE_SPACE_TO_TEST_QUALITY', USER_FREE_SPACE_TO_TEST_QUALITY
+       
+       removedCount = 0
+       
+       areaIslandIdx = 0
+       ctrl = Window.Qual.CTRL
+       BREAK= False
+       while areaIslandIdx < len(decoratedIslandListAreaSort) and not BREAK:
+               sourceIsland = decoratedIslandListAreaSort[areaIslandIdx]
+               # Alredy packed?
+               if not sourceIsland[0]:
+                       areaIslandIdx+=1
+               else:
+                       efficIslandIdx = 0
+                       while efficIslandIdx < len(decoratedIslandListEfficSort) and not BREAK:
+                               
+                               if Window.GetKeyQualifiers() & ctrl:
+                                       BREAK= True
+                                       break
+                               
+                               # Now we have 2 islands, is the efficience of the islands lowers theres an
+                               # increasing likely hood that we can fit merge into the bigger UV island.
+                               # this ensures a tight fit.
+                               
+                               # Just use figures we have about user/unused area to see if they might fit.
+                               
+                               targetIsland = decoratedIslandListEfficSort[efficIslandIdx]
+                               
+                               
+                               if sourceIsland[0] == targetIsland[0] or\
+                               not targetIsland[0] or\
+                               not sourceIsland[0]:
+                                       pass
+                               else:
+                                       
+                                       # ([island, totFaceArea, efficiency, islandArea, w,h])
+                                       # Waisted space on target is greater then UV bounding island area.
+                                       
+                                       
+                                       # if targetIsland[3] > (sourceIsland[2]) and\ #
+                                       # print USER_FREE_SPACE_TO_TEST_QUALITY, 'ass'
+                                       if targetIsland[2] > (sourceIsland[1] * USER_FREE_SPACE_TO_TEST_QUALITY) and\
+                                       targetIsland[4] > sourceIsland[4] and\
+                                       targetIsland[5] > sourceIsland[5]:
+                                               
+                                               # DEBUG # print '%.10f  %.10f' % (targetIsland[3], sourceIsland[1])
+                                               
+                                               # These enough spare space lets move the box until it fits
+                                               
+                                               # How many times does the source fit into the target x/y
+                                               blockTestXUnit = targetIsland[4]/sourceIsland[4]
+                                               blockTestYUnit = targetIsland[5]/sourceIsland[5]
+                                               
+                                               boxLeft = 0
+                                               
+                                               
+                                               # Distllllance we can move between whilst staying inside the targets bounds.
+                                               testWidth = targetIsland[4] - sourceIsland[4]
+                                               testHeight = targetIsland[5] - sourceIsland[5]
+                                               
+                                               # Increment we move each test. x/y
+                                               xIncrement = (testWidth / (blockTestXUnit * ((USER_STEP_QUALITY/50)+0.1)))
+                                               yIncrement = (testHeight / (blockTestYUnit * ((USER_STEP_QUALITY/50)+0.1)))
+
+                                               # Make sure were not moving less then a 3rg of our width/height
+                                               if xIncrement<sourceIsland[4]/3:
+                                                       xIncrement= sourceIsland[4]
+                                               if yIncrement<sourceIsland[5]/3:
+                                                       yIncrement= sourceIsland[5]
+                                               
+                                               
+                                               boxLeft = 0 # Start 1 back so we can jump into the loop.
+                                               boxBottom= 0 #-yIncrement
+                                               
+                                               ##testcount= 0
+                                               
+                                               while boxBottom <= testHeight:
+                                                       # Should we use this? - not needed for now.
+                                                       #if Window.GetKeyQualifiers() & ctrl:
+                                                       #       BREAK= True
+                                                       #       break
+                                                       
+                                                       ##testcount+=1
+                                                       #print 'Testing intersect'
+                                                       Intersect = islandIntersectUvIsland(sourceIsland, targetIsland, Vector(boxLeft, boxBottom))
+                                                       #print 'Done', Intersect
+                                                       if Intersect == 1:  # Line intersect, dont bother with this any more
+                                                               pass
+                                                       
+                                                       if Intersect == 2:  # Source inside target
+                                                               '''
+                                                               We have an intersection, if we are inside the target 
+                                                               then move us 1 whole width accross,
+                                                               Its possible this is a bad idea since 2 skinny Angular faces
+                                                               could join without 1 whole move, but its a lot more optimal to speed this up
+                                                               since we have alredy tested for it.
+                                                               
+                                                               It gives about 10% speedup with minimal errors.
+                                                               '''
+                                                               #print 'ass'
+                                                               # Move the test allong its width + SMALL_NUM
+                                                               #boxLeft += sourceIsland[4] + SMALL_NUM
+                                                               boxLeft += sourceIsland[4]
+                                                       elif Intersect == 0: # No intersection?? Place it.
+                                                               # Progress
+                                                               removedCount +=1
+#XXX                                                           Window.DrawProgressBar(0.0, 'Merged: %i islands, Ctrl to finish early.' % removedCount)
+                                                               
+                                                               # Move faces into new island and offset
+                                                               targetIsland[0].extend(sourceIsland[0])
+                                                               offset= Vector(boxLeft, boxBottom)
+                                                               
+                                                               for f in sourceIsland[0]:
+                                                                       for uv in f.uv:
+                                                                               uv+= offset
+                                                               
+                                                               sourceIsland[0][:] = [] # Empty
+                                                               
+
+                                                               # Move edge loop into new and offset.
+                                                               # targetIsland[6].extend(sourceIsland[6])
+                                                               #while sourceIsland[6]:
+                                                               targetIsland[6].extend( [ (\
+                                                                        (e[0]+offset, e[1]+offset, e[2])\
+                                                               ) for e in sourceIsland[6] ] )
+                                                               
+                                                               sourceIsland[6][:] = [] # Empty
+                                                               
+                                                               # Sort by edge length, reverse so biggest are first.
+                                                               
+                                                               try:     targetIsland[6].sort(key = lambda A: A[2])
+                                                               except: targetIsland[6].sort(lambda B,A: cmp(A[2], B[2] ))
+                                                               
+                                                               
+                                                               targetIsland[7].extend(sourceIsland[7])
+                                                               offset= Vector(boxLeft, boxBottom, 0)
+                                                               for p in sourceIsland[7]:
+                                                                       p+= offset
+                                                               
+                                                               sourceIsland[7][:] = []
+                                                               
+                                                               
+                                                               # Decrement the efficiency
+                                                               targetIsland[1]+=sourceIsland[1] # Increment totFaceArea
+                                                               targetIsland[2]-=sourceIsland[1] # Decrement efficiency
+                                                               # IF we ever used these again, should set to 0, eg
+                                                               sourceIsland[2] = 0 # No area if anyone wants to know
+                                                               
+                                                               break
+                                                       
+                                                       
+                                                       # INCREMENR NEXT LOCATION
+                                                       if boxLeft > testWidth:
+                                                               boxBottom += yIncrement
+                                                               boxLeft = 0.0
+                                                       else:
+                                                               boxLeft += xIncrement
+                                               ##print testcount
+                               
+                               efficIslandIdx+=1
+               areaIslandIdx+=1
+       
+       # Remove empty islands
+       i = len(islandList)
+       while i:
+               i-=1
+               if not islandList[i]:
+                       del islandList[i] # Can increment islands removed here.
+
+# Takes groups of faces. assumes face groups are UV groups.
+def getUvIslands(faceGroups, me):
+       
+       # Get seams so we dont cross over seams
+       edge_seams = {} # shoudl be a set
+       for ed in me.edges:
+               if ed.seam:
+                       edge_seams[ed.key] = None # dummy var- use sets!                        
+       # Done finding seams
+       
+       
+       islandList = []
+       
+#XXX   Window.DrawProgressBar(0.0, 'Splitting %d projection groups into UV islands:' % len(faceGroups))
+       #print '\tSplitting %d projection groups into UV islands:' % len(faceGroups),
+       # Find grouped faces
+       
+       faceGroupIdx = len(faceGroups)
+       
+       while faceGroupIdx:
+               faceGroupIdx-=1
+               faces = faceGroups[faceGroupIdx]
+               
+               if not faces:
+                       continue
+               
+               # Build edge dict
+               edge_users = {}
+               
+               for i, f in enumerate(faces):
+                       for ed_key in f.edge_keys:
+                               if ed_key in edge_seams: # DELIMIT SEAMS! ;)
+                                       edge_users[ed_key] = [] # so as not to raise an error
+                               else:
+                                       try:            edge_users[ed_key].append(i)
+                                       except:         edge_users[ed_key] = [i]
+               
+               # Modes
+               # 0 - face not yet touched.
+               # 1 - added to island list, and need to search
+               # 2 - touched and searched - dont touch again.
+               face_modes = [0] * len(faces) # initialize zero - untested.
+               
+               face_modes[0] = 1 # start the search with face 1
+               
+               newIsland = []
+               
+               newIsland.append(faces[0])
+               
+               
+               ok = True
+               while ok:
+                       
+                       ok = True
+                       while ok:
+                               ok= False
+                               for i in range(len(faces)):
+                                       if face_modes[i] == 1: # search
+                                               for ed_key in faces[i].edge_keys:
+                                                       for ii in edge_users[ed_key]:
+                                                               if i != ii and face_modes[ii] == 0:
+                                                                       face_modes[ii] = ok = 1 # mark as searched
+                                                                       newIsland.append(faces[ii])
+                                                               
+                                               # mark as searched, dont look again.
+                                               face_modes[i] = 2
+                       
+                       islandList.append(newIsland)
+                       
+                       ok = False
+                       for i in range(len(faces)):
+                               if face_modes[i] == 0:
+                                       newIsland = []
+                                       newIsland.append(faces[i])
+                                       
+                                       face_modes[i] = ok = 1
+                                       break
+                       # if not ok will stop looping
+       
+#XXX   Window.DrawProgressBar(0.1, 'Optimizing Rotation for %i UV Islands' % len(islandList))
+       
+       for island in islandList:
+               optiRotateUvIsland(island)
+       
+       return islandList
+       
+
+def packIslands(islandList):
+       if USER_FILL_HOLES:
+#XXX           Window.DrawProgressBar(0.1, 'Merging Islands (Ctrl: skip merge)...')
+               mergeUvIslands(islandList) # Modify in place
+               
+       
+       # Now we have UV islands, we need to pack them.
+       
+       # Make a synchronised list with the islands
+       # so we can box pak the islands.
+       packBoxes = []
+       
+       # Keep a list of X/Y offset so we can save time by writing the 
+       # uv's and packed data in one pass.
+       islandOffsetList = [] 
+       
+       islandIdx = 0
+       
+       while islandIdx < len(islandList):
+               minx, miny, maxx, maxy = boundsIsland(islandList[islandIdx])
+               
+               w, h = maxx-minx, maxy-miny
+               
+               if USER_ISLAND_MARGIN:
+                       minx -= USER_ISLAND_MARGIN# *w
+                       miny -= USER_ISLAND_MARGIN# *h
+                       maxx += USER_ISLAND_MARGIN# *w
+                       maxy += USER_ISLAND_MARGIN# *h
+               
+                       # recalc width and height
+                       w, h = maxx-minx, maxy-miny
+               
+               if w < 0.00001 or h < 0.00001:
+                       del islandList[islandIdx]
+                       islandIdx -=1
+                       continue
+               
+               '''Save the offset to be applied later,
+               we could apply to the UVs now and allign them to the bottom left hand area
+               of the UV coords like the box packer imagines they are
+               but, its quicker just to remember their offset and
+               apply the packing and offset in 1 pass '''
+               islandOffsetList.append((minx, miny))
+               
+               # Add to boxList. use the island idx for the BOX id.
+               packBoxes.append([0, 0, w, h])
+               islandIdx+=1
+       
+       # Now we have a list of boxes to pack that syncs
+       # with the islands.
+       
+       #print '\tPacking UV Islands...'
+#XXX   Window.DrawProgressBar(0.7, 'Packing %i UV Islands...' % len(packBoxes) )
+       
+       time1 = time.time()
+       packWidth, packHeight = Geometry.BoxPack2D(packBoxes)
+       
+       # print 'Box Packing Time:', time.time() - time1
+       
+       #if len(pa      ckedLs) != len(islandList):
+       #       raise "Error packed boxes differes from original length"
+       
+       #print '\tWriting Packed Data to faces'
+#XXX   Window.DrawProgressBar(0.8, 'Writing Packed Data to faces')
+       
+       # Sort by ID, so there in sync again
+       islandIdx = len(islandList)
+       # Having these here avoids devide by 0
+       if islandIdx:
+               
+               if USER_STRETCH_ASPECT:
+                       # Maximize to uv area?? Will write a normalize function.
+                       xfactor = 1.0 / packWidth
+                       yfactor = 1.0 / packHeight      
+               else:
+                       # Keep proportions.
+                       xfactor = yfactor = 1.0 / max(packWidth, packHeight)
+       
+       while islandIdx:
+               islandIdx -=1
+               # Write the packed values to the UV's
+               
+               xoffset = packBoxes[islandIdx][0] - islandOffsetList[islandIdx][0]
+               yoffset = packBoxes[islandIdx][1] - islandOffsetList[islandIdx][1]
+               
+               for f in islandList[islandIdx]: # Offsetting the UV's so they fit in there packed box
+                       for uv in f.uv:
+                               uv.x= (uv.x+xoffset) * xfactor
+                               uv.y= (uv.y+yoffset) * yfactor
+                       
+                       
+
+def VectoMat(vec):
+       a3 = vec.__copy__().normalize()
+       
+       up = Vector(0,0,1)
+       if abs(a3.dot(up)) == 1.0:
+               up = Vector(0,1,0)
+       
+       a1 = a3.cross(up).normalize()
+       a2 = a3.cross(a1)
+       return Matrix([a1[0], a1[1], a1[2]], [a2[0], a2[1], a2[2]], [a3[0], a3[1], a3[2]])
+
+
+# Utility funcs for 2.5, make into a module??
+def ord_ind(i1,i2):
+       if i1<i2: return i1,i2
+       return i2,i1
+       
+def edge_key(ed):
+       v1,v2 = tuple(ed.verts)
+       return ord_ind(v1, v2)
+
+def face_edge_keys(f):
+       verts  = tuple(f.verts)
+       if len(verts)==3:
+               return ord_ind(verts[0], verts[1]),  ord_ind(verts[1], verts[2]),  ord_ind(verts[2], verts[0])
+       
+       return ord_ind(verts[0], verts[1]),  ord_ind(verts[1], verts[2]),  ord_ind(verts[2], verts[3]),  ord_ind(verts[3], verts[0])
+
+
+class thickface(object):
+       __slost__= 'v', 'uv', 'no', 'area', 'edge_keys'
+       def __init__(self, face, uvface, mesh_verts):
+               self.v = [mesh_verts[i] for i in face.verts]
+               if len(self.v)==4:
+                       self.uv = uvface.uv1, uvface.uv2, uvface.uv3, uvface.uv4
+               else:
+                       self.uv = uvface.uv1, uvface.uv2, uvface.uv3
+                       
+               self.no = face.normal
+               self.area = face.area
+               self.edge_keys = face_edge_keys(face)
+
+global ob
+ob = None
+def main(context, island_margin, projection_limit):
+       global USER_FILL_HOLES
+       global USER_FILL_HOLES_QUALITY
+       global USER_STRETCH_ASPECT
+       global USER_ISLAND_MARGIN
+       
+#XXX objects= bpy.data.scenes.active.objects
+       objects = context.selected_editable_objects
+       
+       
+       # we can will tag them later.
+       obList =  [ob for ob in objects if ob.type == 'MESH']
+       
+       # Face select object may not be selected.
+#XXX   ob = objects.active
+       ob= objects[0]
+
+       if ob and ob.selected == 0 and ob.type == 'MESH':
+               # Add to the list
+               obList =[ob]
+       del objects
+       
+       if not obList:
+               raise('error, no selected mesh objects')
+       
+       # Create the variables.
+       USER_PROJECTION_LIMIT = projection_limit
+       USER_ONLY_SELECTED_FACES = (1)
+       USER_SHARE_SPACE = (1) # Only for hole filling.
+       USER_STRETCH_ASPECT = (1) # Only for hole filling.
+       USER_ISLAND_MARGIN = island_margin # Only for hole filling.
+       USER_FILL_HOLES = (0)
+       USER_FILL_HOLES_QUALITY = (50) # Only for hole filling.
+       USER_VIEW_INIT = (0) # Only for hole filling.
+       USER_AREA_WEIGHT = (1) # Only for hole filling.
+       
+       # Reuse variable
+       if len(obList) == 1:
+               ob = "Unwrap %i Selected Mesh"
+       else:
+               ob = "Unwrap %i Selected Meshes"
+       
+       # HACK, loop until mouse is lifted.
+       '''
+       while Window.GetMouseButtons() != 0:
+               time.sleep(10)
+       '''
+       
+#XXX   if not Draw.PupBlock(ob % len(obList), pup_block):
+#XXX           return
+#XXX   del ob
+       
+       # Convert from being button types
+       
+       USER_PROJECTION_LIMIT_CONVERTED = cos(USER_PROJECTION_LIMIT * DEG_TO_RAD)
+       USER_PROJECTION_LIMIT_HALF_CONVERTED = cos((USER_PROJECTION_LIMIT/2) * DEG_TO_RAD)
+       
+       
+       # Toggle Edit mode
+       is_editmode = (context.active_object.mode == 'EDIT')
+       if is_editmode:
+               bpy.ops.object.mode_set(mode='OBJECT')
+       # Assume face select mode! an annoying hack to toggle face select mode because Mesh dosent like faceSelectMode.
+       
+       if USER_SHARE_SPACE:
+               # Sort by data name so we get consistant results
+               obList.sort(key = lambda ob: ob.data.name)
+               collected_islandList= []
+       
+#XXX   Window.WaitCursor(1)
+       
+       time1 = time.time()
+       
+       # Tag as False se we dont operate on teh same mesh twice.
+#XXX   bpy.data.meshes.tag = False 
+       for me in bpy.data.meshes:
+               me.tag = False
+
+       
+       for ob in obList:
+               me = ob.data
+               
+               if me.tag or me.library:
+                       continue
+               
+               # Tag as used
+               me.tag = True
+               
+               if len(me.uv_textures)==0: # Mesh has no UV Coords, dont bother.
+                       me.add_uv_texture()
+               
+               uv_layer = me.active_uv_texture.data
+               me_verts = list(me.verts)
+               
+               if USER_ONLY_SELECTED_FACES:
+                       meshFaces = [thickface(f, uv_layer[i], me_verts) for i, f in enumerate(me.faces) if f.selected]
+               #else:
+               #       meshFaces = map(thickface, me.faces)
+               
+               if not meshFaces:
+                       continue
+               
+#XXX           Window.DrawProgressBar(0.1, 'SmartProj UV Unwrapper, mapping "%s", %i faces.' % (me.name, len(meshFaces)))
+               
+               # =======
+               # Generate a projection list from face normals, this is ment to be smart :)
+               
+               # make a list of face props that are in sync with meshFaces             
+               # Make a Face List that is sorted by area.
+               # meshFaces = []
+               
+               # meshFaces.sort( lambda a, b: cmp(b.area , a.area) ) # Biggest first.
+               meshFaces.sort( key = lambda a: -a.area ) 
+                       
+               # remove all zero area faces
+               while meshFaces and meshFaces[-1].area <= SMALL_NUM:
+                       # Set their UV's to 0,0
+                       for uv in meshFaces[-1].uv:
+                               uv.zero()
+                       meshFaces.pop()
+               
+               # Smallest first is slightly more efficient, but if the user cancels early then its better we work on the larger data.
+               
+               # Generate Projection Vecs
+               # 0d is   1.0
+               # 180 IS -0.59846
+               
+               
+               # Initialize projectVecs
+               if USER_VIEW_INIT:
+                       # Generate Projection
+                       projectVecs = [Vector(Window.GetViewVector()) * ob.matrixWorld.copy().invert().rotationPart()] # We add to this allong the way
+               else:
+                       projectVecs = []
+               
+               newProjectVec = meshFaces[0].no
+               newProjectMeshFaces = []        # Popping stuffs it up.
+               
+               
+               # Predent that the most unique angke is ages away to start the loop off
+               mostUniqueAngle = -1.0
+               
+               # This is popped
+               tempMeshFaces = meshFaces[:]
+               
+               
+               
+               # This while only gathers projection vecs, faces are assigned later on.
+               while 1:
+                       # If theres none there then start with the largest face
+                       
+                       # add all the faces that are close.
+                       for fIdx in range(len(tempMeshFaces)-1, -1, -1):
+                               # Use half the angle limit so we dont overweight faces towards this
+                               # normal and hog all the faces.
+                               if newProjectVec.dot(tempMeshFaces[fIdx].no) > USER_PROJECTION_LIMIT_HALF_CONVERTED:
+                                       newProjectMeshFaces.append(tempMeshFaces.pop(fIdx))
+                       
+                       # Add the average of all these faces normals as a projectionVec
+                       averageVec = Vector(0,0,0)
+                       if USER_AREA_WEIGHT:
+                               for fprop in newProjectMeshFaces:
+                                       averageVec += (fprop.no * fprop.area)
+                       else:
+                               for fprop in newProjectMeshFaces:
+                                       averageVec += fprop.no
+                                       
+                       if averageVec.x != 0 or averageVec.y != 0 or averageVec.z != 0: # Avoid NAN
+                               projectVecs.append(averageVec.normalize())
+                       
+                       
+                       # Get the next vec!
+                       # Pick the face thats most different to all existing angles :)
+                       mostUniqueAngle = 1.0 # 1.0 is 0d. no difference.
+                       mostUniqueIndex = 0 # dummy
+                       
+                       for fIdx in range(len(tempMeshFaces)-1, -1, -1):
+                               angleDifference = -1.0 # 180d difference.
+                               
+                               # Get the closest vec angle we are to.
+                               for p in projectVecs:
+                                       temp_angle_diff= p.dot(tempMeshFaces[fIdx].no)
+                                       
+                                       if angleDifference < temp_angle_diff:
+                                               angleDifference= temp_angle_diff
+                               
+                               if angleDifference < mostUniqueAngle:
+                                       # We have a new most different angle
+                                       mostUniqueIndex = fIdx
+                                       mostUniqueAngle = angleDifference
+                       
+                       if mostUniqueAngle < USER_PROJECTION_LIMIT_CONVERTED:
+                               #print 'adding', mostUniqueAngle, USER_PROJECTION_LIMIT, len(newProjectMeshFaces)
+                               # Now weight the vector to all its faces, will give a more direct projection
+                               # if the face its self was not representive of the normal from surrounding faces.
+                               
+                               newProjectVec = tempMeshFaces[mostUniqueIndex].no
+                               newProjectMeshFaces = [tempMeshFaces.pop(mostUniqueIndex)]
+                               
+                       
+                       else:
+                               if len(projectVecs) >= 1: # Must have at least 2 projections
+                                       break
+               
+               
+               # If there are only zero area faces then its possible
+               # there are no projectionVecs
+               if not len(projectVecs):
+                       Draw.PupMenu('error, no projection vecs where generated, 0 area faces can cause this.')
+                       return
+               
+               faceProjectionGroupList =[[] for i in range(len(projectVecs)) ]
+               
+               # MAP and Arrange # We know there are 3 or 4 faces here 
+               
+               for fIdx in range(len(meshFaces)-1, -1, -1):
+                       fvec = meshFaces[fIdx].no
+                       i = len(projectVecs)
+                       
+                       # Initialize first
+                       bestAng = fvec.dot(projectVecs[0])
+                       bestAngIdx = 0
+                       
+                       # Cycle through the remaining, first alredy done
+                       while i-1:
+                               i-=1
+                               
+                               newAng = fvec.dot(projectVecs[i])
+                               if newAng > bestAng: # Reverse logic for dotvecs
+                                       bestAng = newAng
+                                       bestAngIdx = i
+                       
+                       # Store the area for later use.
+                       faceProjectionGroupList[bestAngIdx].append(meshFaces[fIdx])
+               
+               # Cull faceProjectionGroupList,
+               
+               
+               # Now faceProjectionGroupList is full of faces that face match the project Vecs list
+               for i in range(len(projectVecs)):
+                       # Account for projectVecs having no faces.
+                       if not faceProjectionGroupList[i]:
+                               continue
+                       
+                       # Make a projection matrix from a unit length vector.
+                       MatProj = VectoMat(projectVecs[i])
+                       
+                       # Get the faces UV's from the projected vertex.
+                       for f in faceProjectionGroupList[i]:
+                               f_uv = f.uv
+                               for j, v in enumerate(f.v):
+                                       # XXX - note, between Mathutils in 2.4 and 2.5 the order changed.
+                                       f_uv[j][:] = (v.co * MatProj)[:2]
+               
+               
+               if USER_SHARE_SPACE:
+                       # Should we collect and pack later?
+                       islandList = getUvIslands(faceProjectionGroupList, me)
+                       collected_islandList.extend(islandList)
+                       
+               else:
+                       # Should we pack the islands for this 1 object?
+                       islandList = getUvIslands(faceProjectionGroupList, me)
+                       packIslands(islandList)
+               
+               
+               # update the mesh here if we need to.
+       
+       # We want to pack all in 1 go, so pack now
+       if USER_SHARE_SPACE:
+#XXX           Window.DrawProgressBar(0.9, "Box Packing for all objects...")
+               packIslands(collected_islandList)
+       
+       print("Smart Projection time: %.2f" % (time.time() - time1))
+       # Window.DrawProgressBar(0.9, "Smart Projections done, time: %.2f sec." % (time.time() - time1))
+       
+       if is_editmode:
+               bpy.ops.object.mode_set(mode='EDIT')
+       
+#XXX   Window.DrawProgressBar(1.0, "")
+#XXX   Window.WaitCursor(0)
+#XXX   Window.RedrawAll()
+
+"""
+       pup_block = [\
+       'Projection',\
+*      ('Angle Limit:', USER_PROJECTION_LIMIT, 1, 89, ''),\
+       ('Selected Faces Only', USER_ONLY_SELECTED_FACES, 'Use only selected faces from all selected meshes.'),\
+       ('Init from view', USER_VIEW_INIT, 'The first projection will be from the view vector.'),\
+       ('Area Weight', USER_AREA_WEIGHT, 'Weight projections vector by face area.'),\
+       '',\
+       '',\
+       '',\
+       'UV Layout',\
+       ('Share Tex Space', USER_SHARE_SPACE, 'Objects Share texture space, map all objects into 1 uvmap.'),\
+       ('Stretch to bounds', USER_STRETCH_ASPECT, 'Stretch the final output to texture bounds.'),\
+*      ('Island Margin:', USER_ISLAND_MARGIN, 0.0, 0.5, ''),\
+       'Fill in empty areas',\
+       ('Fill Holes', USER_FILL_HOLES, 'Fill in empty areas reduced texture waistage (slow).'),\
+       ('Fill Quality:', USER_FILL_HOLES_QUALITY, 1, 100, 'Depends on fill holes, how tightly to fill UV holes, (higher is slower)'),\
+       ]
+"""
+
+from bpy.props import *
+class SmartProject(bpy.types.Operator):
+       '''This script projection unwraps the selected faces of a mesh. it operates on all selected mesh objects, and can be used unwrap selected faces, or all faces.'''
+       bl_idname = "uv.smart_project"
+       bl_label = "Smart UV Project"
+
+       bl_register = True
+       bl_undo = True
+
+       angle_limit = FloatProperty(name="Angle Limit",
+                       description="lower for more projection groups, higher for less distortion.",
+                       default=66.0, min=1.0, max=89.0)
+
+       island_margin = FloatProperty(name="Island Margin",
+                       description="Margin to reduce bleed from adjacent islands.",
+                       default=0.0, min=0.0, max=1.0)
+
+       def poll(self, context):
+               return context.active_object != None
+
+       def execute(self, context):
+               main(context, self.island_margin, self.angle_limit)
+               return ('FINISHED',)
+
+bpy.ops.add(SmartProject)
+
+# Add to a menu
+import dynamic_menu
+
+menu_func = (lambda self, context: self.layout.itemO(SmartProject.bl_idname,
+                                                                               text="Smart Project"))
+
+menu_item = dynamic_menu.add(bpy.types.VIEW3D_MT_uv_map, menu_func)
+
+if __name__ == '__main__':
+       bpy.ops.uv.smart_project()
+
similarity index 53%
rename from release/scripts/io/vertexpaint_dirt.py
rename to release/scripts/op/vertexpaint_dirt.py
index 9f55d3bb04231f8c7141a49074123e454675c1c2..7d32c153d0461c55e2d83408ee856d2fe95734d5 100644 (file)
@@ -1,7 +1,3 @@
-# bl_author = ["Campbell Barton aka ideasman42", "Keith Boshoff aka Wahooney"]
-# bl_url = ["www.blender.org", "blenderartists.org", "www.python.org"]
-# bl_version = "0.2"
-
 # ***** BEGIN GPL LICENSE BLOCK *****
 #
 # Script copyright (C) Campbell J Barton
@@ -25,6 +21,8 @@
 
 # History
 #
+# Originally written by Campbell Barton aka ideasman42
+#
 # 2009-11-01: * 2.5 port by Keith "Wahooney" Boshoff
 #              * Replaced old method with my own, speed is similar (about 0.001 sec on Suzanne)
 #               but results are far more accurate
@@ -38,19 +36,20 @@ import time
 from Mathutils import Vector
 from bpy.props import *
 
-def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean, dirt_only, sel_only):
+def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean, dirt_only):
 ##    Window.WaitCursor(1)
 
     #BPyMesh.meshCalcNormals(me)
 
-    vert_tone= [0.0] * len(me.verts)
-    vert_tone_count= [0] * len(me.verts)
+    vert_tone = [0.0] * len(me.verts)
+
+    min_tone =180.0
+    max_tone =0.0
 
     # create lookup table for each vertex's connected vertices (via edges)
-    con = [[] for i in range(len(me.verts))]
+    con = []
 
-    min_tone=180.0
-    max_tone=0.0
+    con = [[] for i in range(len(me.verts))]
 
     # add connected verts
     for e in me.edges:
@@ -73,64 +72,56 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
         ang = math.acos(no.dot(vec))
 
         # enforce min/max
+        ang = max(clamp_dirt, ang)
 
-        vert_tone[v.index] = max(clamp_clean, min(clamp_dirt, ang))
-
-    # average vert_tone_list into vert_tonef
-#    for i, tones in enumerate(vert_tone):
-#        if vert_tone_count[i]:
-#            vert_tone[i] = vert_tone[i] / vert_tone_count[i]
-
-    # Below we use edges to blur along so the edges need counting, not the faces
-    vert_tone_count=    [0] *    len(me.verts)
-    for ed in me.edges:
-        vert_tone_count[ed.verts[0]] += 1
-        vert_tone_count[ed.verts[1]] += 1
-
+        if not dirt_only:
+            ang = min(clamp_clean, ang)
 
-    # Blur tone
-    blur        = blur_strength
-    blur_inv    = 1.0 - blur_strength
+        vert_tone[v.index] = ang
 
+    # blur tones
     for i in range(blur_iterations):
-
         # backup the original tones
-        orig_vert_tone= list(vert_tone)
-
-        for ed in me.edges:
+        orig_vert_tone = list(vert_tone)
 
-            i1 = ed.verts[0]
-            i2 = ed.verts[1]
+        # use connected verts look up for blurring
+        for j, c in enumerate(con):
+            for v in c:
+                vert_tone[j] += blur_strength * orig_vert_tone[v]
 
-            val1 = (orig_vert_tone[i2]*blur) +  (orig_vert_tone[i1]*blur_inv)
-            val2 = (orig_vert_tone[i1]*blur) +  (orig_vert_tone[i2]*blur_inv)
+            vert_tone[j] /= len(c) * blur_strength + 1
 
-            # Apply the ton divided by the number of faces connected
-            vert_tone[i1] += val1 / max(vert_tone_count[i1], 1)
-            vert_tone[i2] += val2 / max(vert_tone_count[i2], 1)
+    min_tone = min(vert_tone)
+    max_tone = max(vert_tone)
 
+    # debug information
+    # print(min_tone * 2 * math.pi)
+    # print(max_tone * 2 * math.pi)
+    # print(clamp_clean)
+    # print(clamp_dirt)
 
-    min_tone= min(vert_tone)
-    max_tone= max(vert_tone)
+    tone_range = max_tone-min_tone
 
-    print(min_tone)
-    print(max_tone)
-    print(clamp_clean)
-    print(clamp_dirt)
-
-    tone_range= max_tone-min_tone
-    if max_tone==min_tone:
+    if not tone_range:
         return
 
-    for lay in me.vertex_colors:
-        if lay.active:
-            active_col_layer = lay.data
+    active_col_layer = None
+
+    if len(me.vertex_colors):
+        for lay in me.vertex_colors:
+            if lay.active:
+                active_col_layer = lay.data
+    else:
+        bpy.ops.mesh.vertex_color_add()
+        me.vertex_colors[0].active = True
+        active_col_layer = me.vertex_colors[0].data
 
     if not active_col_layer:
-        return('CANCELLED', )
+        return("CANCELLED", )
 
     for i, f in enumerate(me.faces):
-        if not sel_only or f.sel:
+        if not me.use_paint_mask or f.selected:
+
             f_col = active_col_layer[i]
 
             f_col = [f_col.color1, f_col.color2, f_col.color3, f_col.color4]
@@ -140,49 +131,47 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean,
                 tone = vert_tone[me.verts[v].index]
                 tone = (tone-min_tone)/tone_range
 
+                if dirt_only:
+                    tone = min(tone, 0.5)
+                    tone *= 2
+
                 col[0] = tone*col[0]
                 col[1] = tone*col[1]
                 col[2] = tone*col[2]
 
 ##    Window.WaitCursor(0)
 
-
 class VertexPaintDirt(bpy.types.Operator):
-    '''This script uses the concavity of vertices to shade the mesh, and optionaly blur the shading to remove artifacts from spesific edges.'''
 
     bl_idname = "mesh.vertex_paint_dirt"
     bl_label = "Dirty Vertex Colors"
     bl_register = True
     bl_undo = True
 
-    blur_strength = FloatProperty(name="Blur Strength", description="Blur strength per iteration", default=1.0, min=0.01, max=1.0)
-    blur_iterations = IntProperty(name="Blur Iterations", description="Number times to blur the colors. (higher blurs more)", default=1, min=0, max=40)
-    clean_angle = FloatProperty(name="Highlight Angle", description="Less then 90 limits the angle used in the tonal range", default=0.0, min=0.0, max=180.0)
-    dirt_angle = FloatProperty(name="Dirt Angle", description="Less then 90 limits the angle used in the tonal range", default=180.0, min=0.0, max=180.0)
-    dirt_only = BoolProperty(name="Dirt Only", description="Dont calculate cleans for convex areas", default=False)
-    sel_faces_only = BoolProperty(name="Selected Faces Only", description="Only apply to UV/Face selected faces (mix vpain/uvface select)", default=False)
+    blur_strength = FloatProperty(name = "Blur Strength", description = "Blur strength per iteration", default = 1.0, min = 0.01, max = 1.0)
+    blur_iterations = IntProperty(name = "Blur Iterations", description = "Number times to blur the colors. (higher blurs more)", default = 1, min = 0, max = 40)
+    clean_angle = FloatProperty(name = "Highlight Angle", description = "Less then 90 limits the angle used in the tonal range", default = 180.0, min = 0.0, max = 180.0)
+    dirt_angle = FloatProperty(name = "Dirt Angle", description = "Less then 90 limits the angle used in the tonal range", default = 0.0, min = 0.0, max = 180.0)
+    dirt_only = BoolProperty(name= "Dirt Only", description = "Dont calculate cleans for convex areas", default = False)
 
     def execute(self, context):
-        sce= context.scene
-        ob= context.object
+        sce = context.scene
+        ob = context.object
 
         if not ob or ob.type != 'MESH':
             print('Error, no active mesh object, aborting.')
-            print(ob)
-            print(ob.type)
             return('CANCELLED',)
 
         me = ob.data
 
         t = time.time()
 
-        applyVertexDirt(me, self.blur_iterations, self.blur_strength, math.radians(self.dirt_angle), math.radians(self.clean_angle), self.dirt_only, self.sel_faces_only)
+        applyVertexDirt(me, self.blur_iterations, self.blur_strength, math.radians(self.dirt_angle), math.radians(self.clean_angle), self.dirt_only)
 
-        print('done in %.6f' % (time.time()-t))
+        print('Dirt calculated in %.6f' % (time.time()-t))
 
         return('FINISHED',)
 
-
 bpy.ops.add(VertexPaintDirt)
 
 if __name__ == "__main__":
diff --git a/release/scripts/op/wm.py b/release/scripts/op/wm.py
new file mode 100644 (file)
index 0000000..a9d62f9
--- /dev/null
@@ -0,0 +1,379 @@
+# ##### 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8-80 compliant>
+
+import bpy
+
+from bpy.props import *
+
+class MESH_OT_delete_edgeloop(bpy.types.Operator):
+    '''Export a single object as a stanford PLY with normals,
+    colours and texture coordinates.'''
+    bl_idname = "mesh.delete_edgeloop"
+    bl_label = "Delete Edge Loop"
+
+    def execute(self, context):
+        bpy.ops.tfm.edge_slide(value=1.0)
+        bpy.ops.mesh.select_more()
+        bpy.ops.mesh.remove_doubles()
+        return ('FINISHED',)
+
+rna_path_prop = StringProperty(name="Context Attributes",
+        description="rna context string", maxlen=1024, default="")
+
+rna_reverse_prop = BoolProperty(name="Reverse",
+        description="Cycle backwards", default=False)
+
+class NullPathMember:
+    pass
+
+
+def context_path_validate(context, path):
+    import sys
+    try:
+        value = eval("context.%s" % path)
+    except AttributeError:
+        if "'NoneType'" in str(sys.exc_info()[1]):
+            # One of the items in the rna path is None, just ignore this
+            value = NullPathMember
+        else:
+            # We have a real error in the rna path, dont ignore that
+            raise
+
+    return value
+
+
+def execute_context_assign(self, context):
+    if context_path_validate(context, self.path) == NullPathMember:
+        return ('PASS_THROUGH',)
+
+    exec("context.%s=self.value" % self.path)
+    return ('FINISHED',)
+
+
+class WM_OT_context_set_boolean(bpy.types.Operator):
+    '''Set a context value.'''
+    bl_idname = "wm.context_set_boolean"
+    bl_label = "Context Set"
+
+    path = rna_path_prop
+    value = BoolProperty(name="Value",
+            description="Assignment value", default=True)
+
+    execute = execute_context_assign
+
+
+class WM_OT_context_set_int(bpy.types.Operator): # same as enum
+    '''Set a context value.'''
+    bl_idname = "wm.context_set_int"
+    bl_label = "Context Set"
+
+    path = rna_path_prop
+    value = IntProperty(name="Value", description="Assign value", default=0)
+
+    execute = execute_context_assign
+
+
+class WM_OT_context_set_float(bpy.types.Operator): # same as enum
+    '''Set a context value.'''
+    bl_idname = "wm.context_set_int"
+    bl_label = "Context Set"
+
+    path = rna_path_prop
+    value = FloatProperty(name="Value",
+            description="Assignment value", default=0.0)
+
+    execute = execute_context_assign
+
+
+class WM_OT_context_set_string(bpy.types.Operator): # same as enum
+    '''Set a context value.'''
+    bl_idname = "wm.context_set_string"
+    bl_label = "Context Set"
+
+    path = rna_path_prop
+    value = StringProperty(name="Value",
+            description="Assign value", maxlen=1024, default="")
+
+    execute = execute_context_assign
+
+
+class WM_OT_context_set_enum(bpy.types.Operator):
+    '''Set a context value.'''
+    bl_idname = "wm.context_set_enum"
+    bl_label = "Context Set"
+
+    path = rna_path_prop
+    value = StringProperty(name="Value",
+            description="Assignment value (as a string)",
+            maxlen=1024, default="")
+
+    execute = execute_context_assign
+
+
+class WM_OT_context_toggle(bpy.types.Operator):
+    '''Toggle a context value.'''
+    bl_idname = "wm.context_toggle"
+    bl_label = "Context Toggle"
+    path = rna_path_prop
+
+    def execute(self, context):
+
+        if context_path_validate(context, self.path) == NullPathMember:
+            return ('PASS_THROUGH',)
+
+        exec("context.%s=not (context.%s)" % (self.path, self.path))
+        return ('FINISHED',)
+
+
+class WM_OT_context_toggle_enum(bpy.types.Operator):
+    '''Toggle a context value.'''
+    bl_idname = "wm.context_toggle_enum"
+    bl_label = "Context Toggle Values"
+
+    path = rna_path_prop
+    value_1 = StringProperty(name="Value", \
+                description="Toggle enum", maxlen=1024, default="")
+
+    value_2 = StringProperty(name="Value", \
+                description="Toggle enum", maxlen=1024, default="")
+
+    def execute(self, context):
+
+        if context_path_validate(context, self.path) == NullPathMember:
+            return ('PASS_THROUGH',)
+
+        exec("context.%s = ['%s', '%s'][context.%s!='%s']" % \
+            (self.path, self.value_1, self.value_2, self.path, self.value_2))
+
+        return ('FINISHED',)
+
+
+class WM_OT_context_cycle_int(bpy.types.Operator):
+    '''Set a context value. Useful for cycling active material,
+    vertex keys, groups' etc.'''
+    bl_idname = "wm.context_cycle_int"
+    bl_label = "Context Int Cycle"
+    path = rna_path_prop
+    reverse = rna_reverse_prop
+
+    def execute(self, context):
+
+        value = context_path_validate(context, self.path)
+        if value == NullPathMember:
+            return ('PASS_THROUGH',)
+
+        self.value = value
+        if self.reverse:
+            self.value -= 1
+        else:
+            self.value += 1
+        execute_context_assign(self, context)
+
+        if self.value != eval("context.%s" % self.path):
+            # relies on rna clamping int's out of the range
+            if self.reverse:
+                self.value = (1 << 32)
+            else:
+                self.value = - (1 << 32)
+            execute_context_assign(self, context)
+
+        return ('FINISHED',)
+
+
+class WM_OT_context_cycle_enum(bpy.types.Operator):
+    '''Toggle a context value.'''
+    bl_idname = "wm.context_cycle_enum"
+    bl_label = "Context Enum Cycle"
+
+    path = rna_path_prop
+    reverse = rna_reverse_prop
+
+    def execute(self, context):
+
+        value = context_path_validate(context, self.path)
+        if value == NullPathMember:
+            return ('PASS_THROUGH',)
+
+        orig_value = value
+
+        # Have to get rna enum values
+        rna_struct_str, rna_prop_str = self.path.rsplit('.', 1)
+        i = rna_prop_str.find('[')
+
+        # just incse we get "context.foo.bar[0]"
+        if i != -1:
+            rna_prop_str = rna_prop_str[0:i]
+
+        rna_struct = eval("context.%s.rna_type" % rna_struct_str)
+
+        rna_prop = rna_struct.properties[rna_prop_str]
+
+        if type(rna_prop) != bpy.types.EnumProperty:
+            raise Exception("expected an enum property")
+
+        enums = rna_struct.properties[rna_prop_str].items.keys()
+        orig_index = enums.index(orig_value)
+
+        # Have the info we need, advance to the next item
+        if self.reverse:
+            if orig_index == 0:
+                advance_enum = enums[-1]
+            else:
+                advance_enum = enums[orig_index-1]
+        else:
+            if orig_index == len(enums) - 1:
+                advance_enum = enums[0]
+            else:
+                advance_enum = enums[orig_index + 1]
+
+        # set the new value
+        exec("context.%s=advance_enum" % self.path)
+        return ('FINISHED',)
+
+doc_id = StringProperty(name="Doc ID",
+        description="ID for the documentation", maxlen=1024, default="")
+
+doc_new = StringProperty(name="Doc New",
+        description="", maxlen=1024, default="")
+
+
+class WM_OT_doc_view(bpy.types.Operator):
+    '''Load online reference docs'''
+    bl_idname = "wm.doc_view"
+    bl_label = "View Documentation"
+
+    doc_id = doc_id
+    _prefix = 'http://www.blender.org/documentation/250PythonDoc'
+
+    def _nested_class_string(self, class_string):
+        ls = []
+        class_obj = getattr(bpy.types, class_string, None).bl_rna
+        while class_obj:
+            ls.insert(0, class_obj)
+            class_obj = class_obj.nested
+        return '.'.join([class_obj.identifier for class_obj in ls])
+
+    def execute(self, context):
+        id_split = self.doc_id.split('.')
+        if len(id_split) == 1: # rna, class
+            url = '%s/bpy.types.%s-class.html' % (self._prefix, id_split[0])
+        elif len(id_split) == 2: # rna, class.prop
+            class_name, class_prop = id_split
+
+            # It so happens that epydoc nests these
+            class_name_full = self._nested_class_string(class_name)
+
+            if hasattr(bpy.types, class_name.upper() + '_OT_' + class_prop):
+                url = '%s/bpy.ops.%s-module.html#%s' % \
+                        (self._prefix, class_name_full, class_prop)
+            else:
+                url = '%s/bpy.types.%s-class.html#%s' % \
+                        (self._prefix, class_name_full, class_prop)
+
+        else:
+            return ('PASS_THROUGH',)
+
+        import webbrowser
+        webbrowser.open(url)
+
+        return ('FINISHED',)
+
+
+class WM_OT_doc_edit(bpy.types.Operator):
+    '''Load online reference docs'''
+    bl_idname = "wm.doc_edit"
+    bl_label = "Edit Documentation"
+
+    doc_id = doc_id
+    doc_new = doc_new
+
+    _url = "http://www.mindrones.com/blender/svn/xmlrpc.php"
+
+    def _send_xmlrpc(self, data_dict):
+        print("sending data:", data_dict)
+
+        import xmlrpc.client
+        user = 'blenderuser'
+        pwd = 'blender>user'
+
+        docblog = xmlrpc.client.ServerProxy(self._url)
+        docblog.metaWeblog.newPost(1, user, pwd, data_dict, 1)
+
+    def execute(self, context):
+
+        class_name, class_prop = self.doc_id.split('.')
+
+        if not self.doc_new:
+            return 'OPERATOR_CANCELLED'
+
+        # check if this is an operator
+        op_name = class_name.upper() + '_OT_' + class_prop
+        op_class = getattr(bpy.types, op_name, None)
+
+        # Upload this to the web server
+        upload = {}
+
+        if op_class:
+            rna = op_class.bl_rna
+            doc_orig = rna.description
+            if doc_orig == self.doc_new:
+                return 'OPERATOR_CANCELLED'
+
+            print("op - old:'%s' -> new:'%s'" % (doc_orig, self.doc_new))
+            upload["title"] = 'OPERATOR %s:%s' % (self.doc_id, doc_orig)
+            upload["description"] = self.doc_new
+
+            self._send_xmlrpc(upload)
+
+        else:
+            rna = getattr(bpy.types, class_name).bl_rna
+            doc_orig = rna.properties[class_prop].description
+            if doc_orig == self.doc_new:
+                return 'OPERATOR_CANCELLED'
+
+            print("rna - old:'%s' -> new:'%s'" % (doc_orig, self.doc_new))
+            upload["title"] = 'RNA %s:%s' % s(self.doc_id, doc_orig)
+
+        upload["description"] = self.doc_new
+
+        self._send_xmlrpc(upload)
+
+        return ('FINISHED',)
+
+    def invoke(self, context, event):
+        wm = context.manager
+        wm.invoke_props_popup(self, event)
+        return ('RUNNING_MODAL',)
+
+
+bpy.ops.add(MESH_OT_delete_edgeloop)
+
+bpy.ops.add(WM_OT_context_set_boolean)
+bpy.ops.add(WM_OT_context_set_int)
+bpy.ops.add(WM_OT_context_set_float)
+bpy.ops.add(WM_OT_context_set_string)
+bpy.ops.add(WM_OT_context_set_enum)
+bpy.ops.add(WM_OT_context_toggle)
+bpy.ops.add(WM_OT_context_toggle_enum)
+bpy.ops.add(WM_OT_context_cycle_enum)
+bpy.ops.add(WM_OT_context_cycle_int)
+
+bpy.ops.add(WM_OT_doc_view)
+bpy.ops.add(WM_OT_doc_edit)
index 88e6a3270962fa691ea73abbfc0c5c9fc59324f5..7eb21ad4f8b2e2d5357b8fbd907eca9c34cf97e6 100644 (file)
@@ -19,6 +19,7 @@
 import bpy
 
 def write_some_data(context, path, use_some_setting):
+    print("running write_some_data...")
     pass
 
 from bpy.props import *
@@ -33,16 +34,18 @@ class ExportSomeData(bpy.types.Operator):
 
     # TODO, add better example props
     path = StringProperty(name="File Path", description="File path used for exporting the PLY file", maxlen= 1024, default= "")
-    use_some_setting = BoolProperty(name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default= True)
+    use_setting = BoolProperty(name="Example Boolean", description="Example Tooltip", default= True)
 
     def poll(self, context):
         return context.active_object != None
 
     def execute(self, context):
-        if not self.is_property_set("path"):
-            raise Exception("filename not set")
 
-        write(self.path, context, use_setting, SOME_SETTING = self.use_some_setting)
+        # # Bug, currently isnt working
+        #if not self.is_property_set("path"):
+        #    raise Exception("filename not set")
+
+        write_some_data(self.path, context, self.use_setting)
 
         return ('FINISHED',)
 
@@ -53,11 +56,11 @@ class ExportSomeData(bpy.types.Operator):
             # File selector
             wm.add_fileselect(self) # will run self.execute()
             return ('RUNNING_MODAL',)
-        else if 0:
+        elif 0:
             # Redo popup
             wm.invoke_props_popup(self, event) #
             return ('RUNNING_MODAL',)
-        else if 0:
+        elif 0:
             return self.execute(context)
 
 
index 0f597c5891a5c8e99e1bed4edf15e8ea5edae1c7..f45f7ab6f609d0fb4229c2872b76a2fbeca4a088 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index b45ad1f83177faf634cf473c58acf6fd39a71155..d1dd11638995fa4f8ec13c024d85ff0e1f40e87b 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index c860998d779e8664041a185490873570af51dfa3..eefd243218678f2d8766170c0c8f0e8d20d438d9 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 5fa2f05839ad36dcc674fc375a0e3fec7a92d8b4..e2987e0a05c47bac99c1b774fdff7c3aefd00047 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index aa90c1e7068f46b9d8dcb9ecc14bf1874e6be693..3f6c7523b3e4f80054c4b6e557cb90e1ff40e360 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 12c4c8e6fb4add8cf3deceebada5fd295e1ff46d..c7ad5b1c8953acf36fdb6534c321eab0bb41294b 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index b9fba1f6808afebce5566b0fe964b8523a2fb58f..3a18a09670af20505e5aff4f35fd56443275d225 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 788345340d6ce636a64cbea0f29f929187466c02..20360fa5ee363e3351247083b0da7075160144ae 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 39bcc7bc8e394bf8640c14e6feae2c9437bb3c25..45330acd8e4de94ce9345c8d806742fd2113a2dd 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 23ab422b7b0eaad72b028a483d231f2286c055e8..410fbadec095bf93466319cd3ad0f53a2c1abada 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index d48f4046ba3efdc774487f4877a9c42fd374069e..b622264569fae8b7124191de5a989e0783678723 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index a348c6f2f524150be620034a121ca8b2eaa60f28..b445585507da0fabd9efe09089294ff8e61e7551 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 8c62f75eed2c7a576baf92c861ba211595afd21a..67d9cea09345ebf3acf8074b332209a80ef7bec8 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index aaf8fa9614c0d361053d757e308129f9e44a0d58..fe1458a080a8b6d22970c72e3dc8f267c3d85dae 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 36e6e20aaf04bfba3cad78320b40ad744c4e4af0..3dd7a931316d8851bb5aa6b71fa3f64e09151a03 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -88,7 +88,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
         col = split.column()
         col.itemR(con, "chain_length")
         col.itemR(con, "targetless")
-
+    
     def CHILD_OF(self, context, layout, con):
         self.target_template(layout, con)
 
@@ -129,7 +129,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
         row.itemR(con, "target_z")
 
         self.space_template(layout, con)
-
+    
     def IK(self, context, layout, con):
         if context.object.pose.ik_solver == "ITASC":
             layout.itemR(con, "ik_type")
@@ -168,7 +168,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
             sub = col.column()
             sub.active = con.rotation
             sub.itemR(con, "orient_weight", text="Rotation", slider=True)
-
+    
     def IK_COPY_POSE(self, context, layout, con):
         self.target_template(layout, con)
         self.ik_template(layout, con)
@@ -212,7 +212,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
         row = layout.row()
         row.itemR(con, "weight", text="Weight", slider=True)
         row.itemR(con, "distance", text="Distance", slider=True)
-
+    
     def FOLLOW_PATH(self, context, layout, con):
         self.target_template(layout, con)
 
@@ -310,7 +310,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
         row = layout.row()
         row.itemL(text="Convert:")
         row.itemR(con, "owner_space", text="")
-
+    
     def LIMIT_SCALE(self, context, layout, con):
         split = layout.split()
 
@@ -351,7 +351,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
         row = layout.row()
         row.itemL(text="Convert:")
         row.itemR(con, "owner_space", text="")
-
+    
     def COPY_ROTATION(self, context, layout, con):
         self.target_template(layout, con)
 
@@ -378,7 +378,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
         layout.itemR(con, "offset")
 
         self.space_template(layout, con)
-
+    
     def COPY_LOCATION(self, context, layout, con):
         self.target_template(layout, con)
 
@@ -438,7 +438,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
 
         row = layout.row()
         row.itemL(text="Convert:")
-        row.itemR(con, "owner_space", text="")
+        row.itemR(con, "target_space", text="")
 
     def LOCKED_TRACK(self, context, layout, con):
         self.target_template(layout, con)
@@ -597,13 +597,13 @@ class ConstraintButtonsPanel(bpy.types.Panel):
 
     def SPLINE_IK(self, context, layout, con):
         self.target_template(layout, con)
-        
+
         col = layout.column()
         col.itemL(text="Spline Fitting:")
         col.itemR(con, "chain_length")
         col.itemR(con, "even_divisions")
         #col.itemR(con, "affect_root") # XXX: this is not that useful yet
-        
+
         col = layout.column()
         col.itemL(text="Chain Scaling:")
         col.itemR(con, "keep_max_length")
index 8a1f0cc2b5f9cb01169d462cf71685b5d18515c6..e9cc541c807730ca593968e8e26d94b215ce5378 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -930,63 +930,64 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel):
     def draw(self, context):
         layout = self.layout
 
+        ob = context.object
         psys = context.particle_system
         part = psys.settings
 
-        layout.itemL(text="Nothing here yet.")
+        layout.itemL(text="Nothing here yet.")
 
-        #row = layout.row()
-        #row.itemL(text="Vertex Group")
-        #row.itemL(text="Negate")
+        row = layout.row()
+        row.itemL(text="Vertex Group")
+        row.itemL(text="Negate")
 
 
-        #row = layout.row()
-        #row.itemR(psys, "vertex_group_density")
-        #row.itemR(psys, "vertex_group_density_negate", text="")
+        row = layout.row()
+        row.item_pointerR(psys, "vertex_group_density", ob, "vertex_groups", text="Density")
+        row.itemR(psys, "vertex_group_density_negate", text="")
 
-        #row = layout.row()
-        #row.itemR(psys, "vertex_group_velocity")
-        #row.itemR(psys, "vertex_group_velocity_negate", text="")
+        row = layout.row()
+        row.item_pointerR(psys, "vertex_group_velocity", ob, "vertex_groups", text="Velocity")
+        row.itemR(psys, "vertex_group_velocity_negate", text="")
 
-        #row = layout.row()
-        #row.itemR(psys, "vertex_group_length")
-        #row.itemR(psys, "vertex_group_length_negate", text="")
+        row = layout.row()
+        row.item_pointerR(psys, "vertex_group_length", ob, "vertex_groups", text="Length")
+        row.itemR(psys, "vertex_group_length_negate", text="")
 
-        #row = layout.row()
-        #row.itemR(psys, "vertex_group_clump")
-        #row.itemR(psys, "vertex_group_clump_negate", text="")
+        row = layout.row()
+        row.item_pointerR(psys, "vertex_group_clump", ob, "vertex_groups", text="Clump")
+        row.itemR(psys, "vertex_group_clump_negate", text="")
 
-        #row = layout.row()
-        #row.itemR(psys, "vertex_group_kink")
-        #row.itemR(psys, "vertex_group_kink_negate", text="")
+        row = layout.row()
+        row.item_pointerR(psys, "vertex_group_kink", ob, "vertex_groups", text="Kink")
+        row.itemR(psys, "vertex_group_kink_negate", text="")
 
-        #row = layout.row()
-        #row.itemR(psys, "vertex_group_roughness1")
-        #row.itemR(psys, "vertex_group_roughness1_negate", text="")
+        row = layout.row()
+        row.item_pointerR(psys, "vertex_group_roughness1", ob, "vertex_groups", text="Roughness 1")
+        row.itemR(psys, "vertex_group_roughness1_negate", text="")
 
-        #row = layout.row()
-        #row.itemR(psys, "vertex_group_roughness2")
-        #row.itemR(psys, "vertex_group_roughness2_negate", text="")
+        row = layout.row()
+        row.item_pointerR(psys, "vertex_group_roughness2", ob, "vertex_groups", text="Roughness 2")
+        row.itemR(psys, "vertex_group_roughness2_negate", text="")
 
-        #row = layout.row()
-        #row.itemR(psys, "vertex_group_roughness_end")
-        #row.itemR(psys, "vertex_group_roughness_end_negate", text="")
+        row = layout.row()
+        row.item_pointerR(psys, "vertex_group_roughness_end", ob, "vertex_groups", text="Roughness End")
+        row.itemR(psys, "vertex_group_roughness_end_negate", text="")
 
-        #row = layout.row()
-        #row.itemR(psys, "vertex_group_size")
-        #row.itemR(psys, "vertex_group_size_negate", text="")
+        row = layout.row()
+        row.item_pointerR(psys, "vertex_group_size", ob, "vertex_groups", text="Size")
+        row.itemR(psys, "vertex_group_size_negate", text="")
 
-        #row = layout.row()
-        #row.itemR(psys, "vertex_group_tangent")
-        #row.itemR(psys, "vertex_group_tangent_negate", text="")
+        row = layout.row()
+        row.item_pointerR(psys, "vertex_group_tangent", ob, "vertex_groups", text="Tangent")
+        row.itemR(psys, "vertex_group_tangent_negate", text="")
 
-        #row = layout.row()
-        #row.itemR(psys, "vertex_group_rotation")
-        #row.itemR(psys, "vertex_group_rotation_negate", text="")
+        row = layout.row()
+        row.item_pointerR(psys, "vertex_group_rotation", ob, "vertex_groups", text="Rotation")
+        row.itemR(psys, "vertex_group_rotation_negate", text="")
 
-        #row = layout.row()
-        #row.itemR(psys, "vertex_group_field")
-        #row.itemR(psys, "vertex_group_field_negate", text="")
+        row = layout.row()
+        row.item_pointerR(psys, "vertex_group_field", ob, "vertex_groups", text="Field")
+        row.itemR(psys, "vertex_group_field_negate", text="")
 
 bpy.types.register(PARTICLE_PT_particles)
 bpy.types.register(PARTICLE_PT_hair_dynamics)
index 19b1c7a3c616bfbb8f28ea6b43be7beb74bd1fb0..255b7038b99ab3a4829b734bb4264393ff12ed32 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 73531f4cd28884d9f29425915633a0b6ab4b6bb2..187db9940f98b679868bb2bb11a60d24fbffc183 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 7499b03e7314f4670f6e61abf89579d965aef6ab..b61f2172d94b1a6daa2fce5cc9c80692af228c3c 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 46b1a5364d0981d9382a8126773f19fa88d4505c..47a5546c20521a6fbfb139b0a9ec8f2e721c7b83 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index c5d0409af6e6df8a23b293747c72b5cd4b1c8f99..3b9b6fdf2b1e65de44cb33f4a8768df0af2cb63e 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index ec290b38e4ab1429c99539abf6fc95c0a73f358c..27c8e357608c10bbbcf09f6081f49fd0714437a4 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 0524b00f011923d0f9951306f99e6e329d8f413c..6aafc8085023bde16f3767acbc698c601b1a6766 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 2061b6580f3edfbbcad8677cc88e41ca8dd6bfda..9ab431a2d6df7494615a377233deb37b3c7679d0 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 6490c03986d71bb91a6c2095853cb1dbc0350713..69540f7dea72e8c81e1e626a9922087547d259a1 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 39ca477b2d8abe740d3f986b5aea376a7ee64837..d00592470f05c54bfa3d7bfb169b6384ccc336d7 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index adb127d5ff6c59a047bdaa5aab1a977d08d6044a..d1b7f99cf5ddb4835d1a68ab2fa7109a6b7885c6 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 88b806ecf232bb64a7bd14eb6d54977b72aade67..c3b97fbaf0a30ee2efbeb814fdd5138e38d01e6c 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -157,6 +157,10 @@ class CONSOLE_OT_exec(bpy.types.Operator):
 
         console, stdout, stderr = get_console(hash(context.region))
 
+        # Hack, useful but must add some other way to access
+        #if "C" not in console.locals:
+        console.locals["C"] = context
+
         # redirect output
         sys.stdout = stdout
         sys.stderr = stderr
@@ -222,7 +226,7 @@ class CONSOLE_OT_autocomplete(bpy.types.Operator):
         sc = context.space_data
 
         console = get_console(hash(context.region))[0]
-
+        
         current_line = sc.history[-1]
         line = current_line.line
 
index 1a89639c4c2c3ce2c178576e35965c2b3bbbb844..2269cdd9a97054679d0d8ffe92fbc25780e734d2 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index c56bfb00af6d0005a34da25e7ba1a194f55e693c..f6b5b75da732d8e9422b8914b776271b47b20890 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 9328aad964cdb69983ef72795f27518384981ca0..cb1112c9dac912948875e79d93db1347f4fdce02 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -187,7 +187,9 @@ class INFO_MT_add(bpy.types.Menu):
         layout.itemO("object.text_add", text="Text", icon='ICON_OUTLINER_OB_FONT')
 
         layout.itemS()
-
+        
+        layout.operator_context = "INVOKE_SCREEN"
+        
         layout.itemO("object.armature_add", text="Armature", icon='ICON_OUTLINER_OB_ARMATURE')
         layout.item_enumO("object.add", "type", 'LATTICE', icon='ICON_OUTLINER_OB_LATTICE')
         layout.item_enumO("object.add", "type", 'EMPTY', icon='ICON_OUTLINER_OB_EMPTY')
@@ -195,6 +197,9 @@ class INFO_MT_add(bpy.types.Menu):
         layout.itemS()
 
         layout.item_enumO("object.add", "type", 'CAMERA', icon='ICON_OUTLINER_OB_CAMERA')
+        
+        layout.operator_context = "EXEC_SCREEN"
+        
         layout.item_menu_enumO("object.lamp_add", "type", 'LAMP', text="Lamp", icon='ICON_OUTLINER_OB_LAMP')
 
         layout.itemS()
index cec739773b3134c62bf346cd2a20ceb05323247e..42daa4ace0736a72db642d98ecf6c72ab38fe4bd 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index daf2d32a0bb0d8d9efdc144bbded9c5968ef9d03..9880a320e25c1bc3b19c2e047c2d3ab6bd240f9f 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 89c38b16965908aec36892d10284b41d4a7052bf..4d517cd90467112bedb3116c750b30ea8c09aa33 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index ff24bef9ee7e6657f898b1a65383c74c422788f5..ec90d15968dcf7f7782b871bf5e6bb1abe424e03 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index bd1514dbf77c3e672edc01368d33df1bde2c2c38..0d33f181a069942b078b9f18ab2c6c557d51e5bc 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 164a69f28262fe72460683f59eaae2b675a80cf5..42734589d48c7818a70098bbed7d073d41d20b1b 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
index 0235876a064277d59e9d19475659bd13b8dacc8d..935e3b4087489a19f6e9a0d3f51a30533e514625 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -355,60 +355,60 @@ class USERPREF_PT_theme(bpy.types.Panel):
 
     def draw(self, context):
         layout = self.layout
-        
+
         theme = context.user_preferences.themes[0]
-        
-        
+
+
         split = layout.split(percentage=0.33)
         split.itemR(theme, "active_theme", text="")
-        
+
         layout.itemS()
-        
+
         split = layout.split()
-        
+
         if theme.active_theme == 'VIEW_3D':
             v3d = theme.view_3d
-            
-            col = split.column()  
+
+            col = split.column()
             col.itemR(v3d, "back")
             col.itemR(v3d, "title")
             col.itemR(v3d, "text")
             col.itemR(v3d, "text_hi")
             col.itemR(v3d, "header")
             col.itemR(v3d, "header_text")
-            
-            col = split.column()  
-            col.itemR(v3d, "header_text_hi")    
+
+            col = split.column()
+            col.itemR(v3d, "header_text_hi")
             col.itemR(v3d, "grid")
             col.itemR(v3d, "panel", slider=True)
             col.itemR(v3d, "wire")
             col.itemR(v3d, "lamp", slider=True)
-            
-            col = split.column()  
+
+            col = split.column()
             col.itemR(v3d, "current_frame")
-            col.itemR(v3d, "editmesh_active", slider=True)  
+            col.itemR(v3d, "editmesh_active", slider=True)
             col.itemR(v3d, "object_selected")
             col.itemR(v3d, "object_active")
             col.itemR(v3d, "object_grouped")
             col.itemR(v3d, "object_grouped_active")
-            
-            col = split.column()  
+
+            col = split.column()
             col.itemR(v3d, "transform")
             col.itemR(v3d, "vertex")
             col.itemR(v3d, "face", slider=True)
             col.itemR(v3d, "normal")
             col.itemR(v3d, "bone_solid")
-            col.itemR(v3d, "bone_pose") 
+            col.itemR(v3d, "bone_pose")
 
 #           col.itemR(v3d, "edge") Doesn't seem to work
         elif theme.active_theme == 'USER_INTERFACE':
-            
+
             ui = theme.user_interface.wcol_regular
-            
+
             layout.itemL(text="Regular:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -424,12 +424,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
             layout.itemS()
-            
+
             ui = theme.user_interface.wcol_tool
             layout.itemL(text="Tool:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -444,12 +444,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.active = ui.shaded
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
-            
+
             ui = theme.user_interface.wcol_radio
             layout.itemL(text="Radio Buttons:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -464,12 +464,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.active = ui.shaded
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
-            
+
             ui = theme.user_interface.wcol_text
             layout.itemL(text="Text:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -484,12 +484,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.active = ui.shaded
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
-            
+
             ui = theme.user_interface.wcol_option
             layout.itemL(text="Option:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -504,12 +504,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.active = ui.shaded
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
-            
+
             ui = theme.user_interface.wcol_toggle
             layout.itemL(text="Toggle:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -524,12 +524,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.active = ui.shaded
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
-            
+
             ui = theme.user_interface.wcol_num
             layout.itemL(text="Number Field:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -544,12 +544,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.active = ui.shaded
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
-            
+
             ui = theme.user_interface.wcol_numslider
             layout.itemL(text="Value Slider:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -564,12 +564,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.active = ui.shaded
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
-            
+
             ui = theme.user_interface.wcol_box
             layout.itemL(text="Box:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -584,12 +584,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.active = ui.shaded
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
-            
+
             ui = theme.user_interface.wcol_menu
             layout.itemL(text="Menu:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -604,12 +604,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.active = ui.shaded
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
-            
+
             ui = theme.user_interface.wcol_pulldown
             layout.itemL(text="Pulldown:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -624,12 +624,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.active = ui.shaded
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
-            
+
             ui = theme.user_interface.wcol_menu_back
             layout.itemL(text="Menu Back:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -644,12 +644,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.active = ui.shaded
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
-            
+
             ui = theme.user_interface.wcol_menu_item
             layout.itemL(text="Menu Item:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -664,12 +664,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.active = ui.shaded
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
-            
+
             ui = theme.user_interface.wcol_scroll
             layout.itemL(text="Scroll Bar:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -684,12 +684,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.active = ui.shaded
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
-            
+
             ui = theme.user_interface.wcol_list_item
             layout.itemL(text="List Item:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "outline")
             sub1.itemR(ui, "item", slider=True)
             sub1 = sub.column()
@@ -704,12 +704,12 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub2.active = ui.shaded
             sub2.itemR(ui, "shadetop")
             sub2.itemR(ui, "shadedown")
-            
+
             ui = theme.user_interface.wcol_state
             layout.itemL(text="State:")
-            
+
             sub = layout.row()
-            sub1 = sub.column()  
+            sub1 = sub.column()
             sub1.itemR(ui, "inner_anim")
             sub1.itemR(ui, "inner_anim_sel")
             sub1 = sub.column()
@@ -720,340 +720,340 @@ class USERPREF_PT_theme(bpy.types.Panel):
             sub1.itemR(ui, "inner_key_sel")
             sub1 = sub.column()
             sub1.itemR(ui, "blend")
-            
+
             ui = theme.user_interface
             layout.itemS()
-            
-            sub = layout.row() 
+
+            sub = layout.row()
             sub.itemR(ui, "icon_file")
-            
+
             layout.itemS()
             layout.itemS()
-            
+
 
         elif theme.active_theme == 'GRAPH_EDITOR':
             graph = theme.graph_editor
-            
+
             col = split.column()
             col.itemR(graph, "back")
             col.itemR(graph, "title")
             col.itemR(graph, "text")
             col.itemR(graph, "text_hi")
             col.itemR(graph, "header")
-            
+
             col = split.column()
             col.itemR(graph, "header_text")
-            col.itemR(graph, "header_text_hi")   
+            col.itemR(graph, "header_text_hi")
             col.itemR(graph, "grid")
             col.itemR(graph, "panel")
             col.itemR(graph, "window_sliders")
-            
+
             col = split.column()
             col.itemR(graph, "channels_region")
             col.itemR(graph, "vertex")
             col.itemR(graph, "current_frame")
             col.itemR(graph, "handle_vertex")
             col.itemR(graph, "handle_vertex_select")
-            
+
             col = split.column()
             col.itemR(graph, "handle_vertex_size")
             col.itemR(graph, "channel_group")
             col.itemR(graph, "active_channels_group")
             col.itemR(graph, "dopesheet_channel")
             col.itemR(graph, "dopesheet_subchannel")
-            
-            
+
+
         elif theme.active_theme == 'FILE_BROWSER':
             file = theme.file_browser
-           
+
             col = split.column()
             col.itemR(file, "back")
             col.itemR(file, "title")
             col.itemR(file, "text")
             col.itemR(file, "text_hi")
-            
+
             col = split.column()
             col.itemR(file, "header")
             col.itemR(file, "header_text")
             col.itemR(file, "header_text_hi")
-            
+
             col = split.column()
             col.itemR(file, "selected_file")
             col.itemR(file, "tiles")
             col.itemR(file, "scrollbar")
-            
+
             col = split.column()
             col.itemR(file, "scroll_handle")
             col.itemR(file, "active_file")
             col.itemR(file, "active_file_text")
-            
+
         elif theme.active_theme == 'NLA_EDITOR':
             nla = theme.nla_editor
-            
+
             col = split.column()
             col.itemR(nla, "back")
             col.itemR(nla, "title")
             col.itemR(nla, "text")
             col.itemR(nla, "text_hi")
-            
+
             col = split.column()
             col.itemR(nla, "header")
             col.itemR(nla, "header_text")
             col.itemR(nla, "header_text_hi")
             col.itemR(nla, "grid")
-            
+
             col = split.column()
             col.itemR(nla, "view_sliders")
             col.itemR(nla, "bars")
             col.itemR(nla, "bars_selected")
-            
+
             col = split.column()
             col.itemR(nla, "strips")
             col.itemR(nla, "strips_selected")
             col.itemR(nla, "current_frame")
-            
+
         elif theme.active_theme == 'DOPESHEET_EDITOR':
             dope = theme.dopesheet_editor
-            
+
             col = split.column()
             col.itemR(dope, "back")
             col.itemR(dope, "title")
             col.itemR(dope, "text")
             col.itemR(dope, "text_hi")
             col.itemR(dope, "header")
-            
+
             col = split.column()
             col.itemR(dope, "header_text")
             col.itemR(dope, "header_text_hi")
             col.itemR(dope, "grid")
             col.itemR(dope, "value_sliders")
             col.itemR(dope, "view_sliders")
-            
+
             col = split.column()
             col.itemR(dope, "channels")
             col.itemR(dope, "channels_selected")
             col.itemR(dope, "channel_group")
             col.itemR(dope, "active_channels_group")
             col.itemR(dope, "long_key")
-            
+
             col = split.column()
             col.itemR(dope, "long_key_selected")
             col.itemR(dope, "current_frame")
             col.itemR(dope, "dopesheet_channel")
             col.itemR(dope, "dopesheet_subchannel")
-            
+
         elif theme.active_theme == 'IMAGE_EDITOR':
             image = theme.image_editor
 
             col = split.column()
             col.itemR(image, "back")
             col.itemR(image, "title")
-            
+
             col = split.column()
             col.itemR(image, "text")
             col.itemR(image, "text_hi")
-            
+
             col = split.column()
             col.itemR(image, "header")
             col.itemR(image, "header_text")
-            
+
             col = split.column()
             col.itemR(image, "header_text_hi")
             col.itemR(image, "editmesh_active", slider=True)
-            
+
         elif theme.active_theme == 'SEQUENCE_EDITOR':
             seq = theme.sequence_editor
-           
+
             col = split.column()
             col.itemR(seq, "back")
             col.itemR(seq, "title")
             col.itemR(seq, "text")
             col.itemR(seq, "text_hi")
             col.itemR(seq, "header")
-            
+
             col = split.column()
             col.itemR(seq, "header_text")
             col.itemR(seq, "header_text_hi")
             col.itemR(seq, "grid")
             col.itemR(seq, "window_sliders")
             col.itemR(seq, "movie_strip")
-            
+
             col = split.column()
             col.itemR(seq, "image_strip")
             col.itemR(seq, "scene_strip")
             col.itemR(seq, "audio_strip")
             col.itemR(seq, "effect_strip")
             col.itemR(seq, "plugin_strip")
-            
+
             col = split.column()
             col.itemR(seq, "transition_strip")
             col.itemR(seq, "meta_strip")
             col.itemR(seq, "current_frame")
             col.itemR(seq, "keyframe")
             col.itemR(seq, "draw_action")
-            
+
         elif theme.active_theme == 'PROPERTIES':
             prop = theme.properties
-           
+
             col = split.column()
             col.itemR(prop, "back")
             col.itemR(prop, "title")
-            
+
             col = split.column()
             col.itemR(prop, "text")
             col.itemR(prop, "text_hi")
-           
+
             col = split.column()
             col.itemR(prop, "header")
             col.itemR(prop, "header_text")
-           
+
             col = split.column()
             col.itemR(prop, "header_text_hi")
             col.itemR(prop, "panel")
-            
+
         elif theme.active_theme == 'TEXT_EDITOR':
             text = theme.text_editor
-           
+
             col = split.column()
             col.itemR(text, "back")
             col.itemR(text, "title")
             col.itemR(text, "text")
             col.itemR(text, "text_hi")
-            
+
             col = split.column()
             col.itemR(text, "header")
             col.itemR(text, "header_text")
             col.itemR(text, "header_text_hi")
             col.itemR(text, "line_numbers_background")
-            
+
             col = split.column()
             col.itemR(text, "scroll_bar")
             col.itemR(text, "selected_text")
             col.itemR(text, "cursor")
             col.itemR(text, "syntax_builtin")
-            
+
             col = split.column()
             col.itemR(text, "syntax_special")
             col.itemR(text, "syntax_comment")
             col.itemR(text, "syntax_string")
             col.itemR(text, "syntax_numbers")
-            
+
         elif theme.active_theme == 'TIMELINE':
             time = theme.timeline
-            
+
             col = split.column()
             col.itemR(time, "back")
             col.itemR(time, "title")
             col.itemR(time, "text")
-            
+
             col = split.column()
             col.itemR(time, "text_hi")
             col.itemR(time, "header")
-            
+
             col = split.column()
             col.itemR(time, "header_text")
             col.itemR(time, "header_text_hi")
-            
+
             col = split.column()
             col.itemR(time, "grid")
             col.itemR(time, "current_frame")
-            
+
         elif theme.active_theme == 'NODE_EDITOR':
             node = theme.node_editor
-            
+
             col = split.column()
             col.itemR(node, "back")
             col.itemR(node, "title")
             col.itemR(node, "text")
             col.itemR(node, "text_hi")
-            
+
             col = split.column()
             col.itemR(node, "header")
             col.itemR(node, "header_text")
             col.itemR(node, "header_text_hi")
             col.itemR(node, "wires")
-            
+
             col = split.column()
             col.itemR(node, "wire_select")
             col.itemR(node, "selected_text")
             col.itemR(node, "node_backdrop")
             col.itemR(node, "in_out_node")
-            
+
             col = split.column()
             col.itemR(node, "converter_node")
             col.itemR(node, "operator_node")
             col.itemR(node, "group_node")
-            
+
         elif theme.active_theme == 'LOGIC_EDITOR':
             logic = theme.logic_editor
-           
+
             col = split.column()
             col.itemR(logic, "back")
             col.itemR(logic, "title")
-            
+
             col = split.column()
             col.itemR(logic, "text")
             col.itemR(logic, "text_hi")
-            
+
             col = split.column()
             col.itemR(logic, "header")
             col.itemR(logic, "header_text")
-            
+
             col = split.column()
             col.itemR(logic, "header_text_hi")
             col.itemR(logic, "panel")
 
         elif theme.active_theme == 'OUTLINER':
             out = theme.outliner
-            
+
             col = split.column()
             col.itemR(out, "back")
             col.itemR(out, "title")
-            
+
             col = split.column()
             col.itemR(out, "text")
             col.itemR(out, "text_hi")
-            
+
             col = split.column()
             col.itemR(out, "header")
             col.itemR(out, "header_text")
-            
+
             col = split.column()
             col.itemR(out, "header_text_hi")
-            
+
         elif theme.active_theme == 'INFO':
             info = theme.info
-            
+
             col = split.column()
             col.itemR(info, "back")
             col.itemR(info, "title")
-            
+
             col = split.column()
             col.itemR(info, "text")
             col.itemR(info, "text_hi")
-            
+
             col = split.column()
             col.itemR(info, "header")
             col.itemR(info, "header_text")
-            
+
             col = split.column()
             col.itemR(info, "header_text_hi")
-           
+
         elif theme.active_theme == 'USER_PREFERENCES':
             prefs = theme.user_preferences
-            
+
             col = split.column()
             col.itemR(prefs, "back")
             col.itemR(prefs, "title")
-            
+
             col = split.column()
             col.itemR(prefs, "text")
             col.itemR(prefs, "text_hi")
-            
+
             col = split.column()
             col.itemR(prefs, "header")
             col.itemR(prefs, "header_text")
-            
+
             col = split.column()
             col.itemR(prefs, "header_text_hi")
 
@@ -1231,9 +1231,9 @@ class USERPREF_PT_input(bpy.types.Panel):
             itemrow = row.row()
             itemrow.enabled = km.user_defined
             if kmi.active:
-               itemrow.itemR(kmi, "active", text="", icon="ICON_CHECKBOX_HLT")
+                itemrow.itemR(kmi, "active", text="", icon="ICON_CHECKBOX_HLT")
             else:
-                   itemrow.itemR(kmi, "active", text="", icon="ICON_CHECKBOX_DEHLT")
+                itemrow.itemR(kmi, "active", text="", icon="ICON_CHECKBOX_DEHLT")
 
             itemcol = itemrow.column()
             itemcol.active = kmi.active
index 2670f6643d3bdab55b95bd382895a8cffded8bb2..5d64f9e4779e8610fa940b47465109ac0756a98e 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -90,6 +90,22 @@ class VIEW3D_MT_snap(bpy.types.Menu):
         layout.itemO("view3d.snap_cursor_to_grid", text="Cursor to Grid")
         layout.itemO("view3d.snap_cursor_to_active", text="Cursor to Active")
 
+class VIEW3D_MT_uv_map(dynamic_menu.DynMenu):
+    bl_label = "UV Mapping"
+
+    def draw(self, context):
+        layout = self.layout
+
+        layout.itemO("uv.unwrap")
+        layout.itemO("uv.cube_project")
+        layout.itemO("uv.cylinder_project")
+        layout.itemO("uv.sphere_project")
+        layout.itemO("uv.project_from_view")
+
+        layout.itemS()
+
+        layout.itemO("uv.reset")
+
 # ********** View menus **********
 
 
@@ -209,9 +225,9 @@ class VIEW3D_MT_select_object(bpy.types.Menu):
         layout.itemO("object.select_mirror", text="Mirror")
         layout.itemO("object.select_by_layer", text="Select All by Layer")
         layout.item_menu_enumO("object.select_by_type", "type", "", text="Select All by Type...")
-        
+
         layout.itemS()
-        
+
         layout.item_menu_enumO("object.select_grouped", "type", text="Grouped")
         layout.item_menu_enumO("object.select_linked", "type", text="Linked")
         layout.itemO("object.select_pattern", text="Select Pattern...")
@@ -407,7 +423,7 @@ class VIEW3D_MT_select_edit_armature(bpy.types.Menu):
         layout = self.layout
 
         layout.itemO("view3d.select_border")
-        
+
 
         layout.itemS()
 
@@ -463,8 +479,10 @@ class VIEW3D_MT_object(bpy.types.Menu):
         layout.item_booleanO("object.duplicate", "linked", True, text="Duplicate Linked")
         layout.itemO("object.delete", text="Delete...")
         layout.itemO("object.proxy_make", text="Make Proxy...")
+        layout.itemM("VIEW3D_MT_make_links", text="Make Links...")
         layout.item_menu_enumO("object.make_local", "type", text="Make Local...")
         layout.itemM("VIEW3D_MT_make_single_user")
+        layout.itemM("VIEW3D_MT_make_links")
 
         layout.itemS()
 
@@ -588,6 +606,18 @@ class VIEW3D_MT_make_single_user(bpy.types.Menu):
         props = layout.itemO("object.make_single_user", properties=True, text="Animation")
         props.animation = True
 
+
+class VIEW3D_MT_make_links(bpy.types.Menu):
+    bl_label = "Make Links"
+
+    def draw(self, context):
+        layout = self.layout
+        
+        layout.item_menu_enumO("object.make_links_scene", "type", text="Objects to Scene...")
+
+        layout.items_enumO("object.make_links_data", property="type") # inline
+
+
 # ********** Vertex paint menu **********
 
 
@@ -832,7 +862,7 @@ class VIEW3D_MT_edit_mesh(bpy.types.Menu):
 
         layout.itemS()
 
-        layout.itemO("uv.mapping_menu", text="UV Unwrap...")
+        layout.itemM("VIEW3D_MT_uv_map", text="UV Unwrap...")
 
         layout.itemS()
 
@@ -1359,8 +1389,8 @@ class VIEW3D_PT_3dview_meshdisplay(bpy.types.Panel):
     bl_label = "Mesh Display"
 
     def poll(self, context):
-        editmesh = context.mode == 'EDIT_MESH'
-        return (editmesh)
+        # The active object check is needed because of localmode
+        return (context.active_object and (context.mode == 'EDIT_MESH'))
 
     def draw(self, context):
         layout = self.layout
@@ -1585,6 +1615,7 @@ bpy.types.register(VIEW3D_MT_object_group)
 bpy.types.register(VIEW3D_MT_object_constraints)
 bpy.types.register(VIEW3D_MT_object_showhide)
 bpy.types.register(VIEW3D_MT_make_single_user)
+bpy.types.register(VIEW3D_MT_make_links)
 
 
 bpy.types.register(VIEW3D_MT_sculpt) # Sculpt Menu
@@ -1604,6 +1635,7 @@ bpy.types.register(VIEW3D_MT_pose_constraints)
 bpy.types.register(VIEW3D_MT_pose_showhide)
 
 bpy.types.register(VIEW3D_MT_snap) # Edit Menus
+bpy.types.register(VIEW3D_MT_uv_map) # Edit Menus
 
 bpy.types.register(VIEW3D_MT_edit_mesh)
 bpy.types.register(VIEW3D_MT_edit_mesh_specials) # Only as a menu for keybindings
index 5b773aac13357345b08a3e2f0ddf64ed01fbac58..0ad694efde11e5704620354361e42fae40a2dbed 100644 (file)
@@ -4,12 +4,12 @@
 #  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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
@@ -109,7 +109,8 @@ class VIEW3D_PT_tools_meshedit(View3DPanel):
 
         col = layout.column(align=True)
         col.itemL(text="UV Mapping:")
-        col.itemO("uv.mapping_menu", text="Unwrap")
+        col.item_stringO("wm.call_menu", "name", "VIEW3D_MT_uv_map", text="Unwrap")
+        
         col.itemO("mesh.uvs_rotate")
         col.itemO("mesh.uvs_mirror")
 
@@ -133,10 +134,12 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel):
     def draw(self, context):
         layout = self.layout
 
-        mesh = context.active_object.data
+        ob = context.active_object
 
-        col = layout.column(align=True)
-        col.itemR(mesh, "use_mirror_x")
+        if ob:
+            mesh = context.active_object.data
+            col = layout.column(align=True)
+            col.itemR(mesh, "use_mirror_x")
 
 # ********** default tools for editmode_curve ****************
 
@@ -521,7 +524,7 @@ class VIEW3D_PT_tools_brush(PaintPanel):
                     col.row().itemR(brush, "direction", expand=True)
 
                 if brush.sculpt_tool == 'LAYER':
-                    col.itemR(brush, "persistent")
+                    col.itemR(brush, "use_persistent")
                     col.itemO("sculpt.set_persistent_base")
 
         # Texture Paint Mode #
index e982806a6cc60958e27cec47581d8e9522cc149d..8a34b286881cd2f49a4f5b9590620e193d0309c7 100644 (file)
@@ -44,7 +44,7 @@ void copy_defgroups (struct ListBase *lb1, struct ListBase *lb2);
 struct bDeformGroup *copy_defgroup (struct bDeformGroup *ingroup);
 struct bDeformGroup *get_named_vertexgroup (Object *ob, char *name);
 int get_defgroup_num (struct Object *ob, struct bDeformGroup *dg);
-int get_named_vertexgroup_num (Object *ob, char *name);
+int get_named_vertexgroup_num (Object *ob, const char *name);
 void unique_vertexgroup_name (struct bDeformGroup *dg, struct Object *ob);
 
 float deformvert_get_weight(const struct MDeformVert *dvert, int group_num);
index 62c4143632c09768d3923182c2bf731b3ec1260a..3a8a3d4efc958524ba956c2d8dec052be08110ad 100644 (file)
@@ -1689,7 +1689,9 @@ static void splineik_init_tree_from_pchan(Object *ob, bPoseChannel *pchan_tip)
                /* setup new empty array for the points list */
                if (ikData->points) 
                        MEM_freeN(ikData->points);
-               ikData->numpoints= (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT)? ikData->chainlen : ikData->chainlen+1;
+               // NOTE: just do chainlen+1 always for now, since we may get crashes otherwise
+               //ikData->numpoints= (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT)? ikData->chainlen : ikData->chainlen+1;
+               ikData->numpoints= ikData->chainlen+1; 
                ikData->points= MEM_callocN(sizeof(float)*ikData->numpoints, "Spline IK Binding");
                
                /* perform binding of the joints to parametric positions along the curve based 
@@ -1804,106 +1806,109 @@ static void splineik_init_tree(Scene *scene, Object *ob, float ctime)
 static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan, int index, float ctime)
 {
        bSplineIKConstraint *ikData= tree->ikData;
-       float dirX[3]={1,0,0}, dirZ[3]={0,0,1};
-       float axis1[3], axis2[3], tmpVec[3];
+       float poseHead[3], poseTail[3], poseMat[4][4]; 
        float splineVec[3], scaleFac;
        float rad, radius=1.0f;
        float vec[4], dir[3];
        
-       /* step 1: get xyz positions for the endpoints of the bone
-        *      assume that they can be calculated on the path so that these calls will never fail
-        */
-               /* tail */
+       /* firstly, calculate the bone matrix the standard way, since this is needed for roll control */
+       where_is_pose_bone(scene, ob, pchan, ctime);
+       
+       VECCOPY(poseHead, pchan->pose_head);
+       VECCOPY(poseTail, pchan->pose_tail);
+       
+       /* step 1a: get xyz positions for the tail endpoint of the bone */
        if ( where_on_path(ikData->tar, tree->points[index], vec, dir, NULL, &rad) ) {
                /* convert the position to pose-space, then store it */
                Mat4MulVecfl(ob->imat, vec);
-               VECCOPY(pchan->pose_tail, vec);
+               VECCOPY(poseTail, vec);
                
                /* set the new radius */
                radius= rad;
        }
-               /* head 
-                *      - check that this isn't the last bone that is subject to restrictions 
-                *        i.e. if no-root option is enabled, the root should be calculated in the standard way
-                */
-       if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT)==0 || (index+1 < ikData->chainlen)) 
-       {
-               /* the head location of this bone is driven by the spline */
-               if ( where_on_path(ikData->tar, tree->points[index+1], vec, dir, NULL, &rad) ) {
-                       /* store the position, and convert it to pose space */
-                       Mat4MulVecfl(ob->imat, vec);
-                       VECCOPY(pchan->pose_head, vec);
-                       
-                       /* set the new radius (it should be the average value) */
-                       radius = (radius+rad) / 2;
-               }
-       }
-       else { 
-               // FIXME: this option isn't really useful yet...
-               //      maybe we are more interested in the head deltas that arise from this instead?
-               /* use the standard calculations for this */
-               where_is_pose_bone(scene, ob, pchan, ctime);
+       
+       /* step 1b: get xyz positions for the head endpoint of the bone */
+               /* firstly, calculate the position that the path suggests */
+       if ( where_on_path(ikData->tar, tree->points[index+1], vec, dir, NULL, &rad) ) {
+               /* store the position, and convert it to pose space */
+               Mat4MulVecfl(ob->imat, vec);
+               VECCOPY(poseHead, vec);
                
-               /* hack: assume for now that the pose_tail vector is still valid from the previous step, 
-                * and set that again now so that the chain doesn't get broken
-                */
-               VECCOPY(pchan->pose_tail, vec); 
+               /* set the new radius (it should be the average value) */
+               radius = (radius+rad) / 2;
+       }
+       if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) && (pchan == tree->root)) 
+       {
+               // this is the root bone, and it can be controlled however we like...
+               // TODO: how do we calculate the offset of the root, if we don't even know the binding?
+               VECCOPY(poseHead, pchan->pose_head);
        }
        
-       
-       /* step 2a: determine the implied transform from these endpoints 
+       /* step 2: determine the implied transform from these endpoints 
         *      - splineVec: the vector direction that the spline applies on the bone
         *      - scaleFac: the factor that the bone length is scaled by to get the desired amount
         */
-       VecSubf(splineVec, pchan->pose_tail, pchan->pose_head);
-       scaleFac= VecLength(splineVec) / pchan->bone->length; // TODO: this will need to be modified by blending factor
-       
-       /* step 2b: the spline vector now becomes the y-axis of the bone
-        *      - we need to normalise the splineVec first, so that it's just a unit direction vector
-        */
-       Mat4One(pchan->pose_mat);
+       VecSubf(splineVec, poseTail, poseHead);
+       scaleFac= VecLength(splineVec) / pchan->bone->length;
        
-       Normalize(splineVec);
-       VECCOPY(pchan->pose_mat[1], splineVec);
-       
-       
-       /* step 3a: determine two vectors which will both be at right angles to the bone vector 
-        *      based on the "Gram Schmidt process" for finding a set of Orthonormal Vectors, described at 
-        *              http://ltcconline.net/greenl/courses/203/Vectors/orthonormalBases.htm
-        *      and normalise them to make sure they will behave nicely (as unit vectors)
+       /* step 3: compute the shortest rotation needed to map from the bone rotation to the current axis 
+        *      - this uses the same method as is used for the Damped Track Constraint (see the code there for details)
         */
-               /* x-axis = dirX - projection(dirX onto splineVec) */
-       Projf(axis1, dirX, splineVec); /* project dirX onto splineVec */
-       VecSubf(pchan->pose_mat[0], dirX, axis1);
-       
-       Normalize(pchan->pose_mat[0]);
-       
-               /* z-axis = dirZ - projection(dirZ onto splineVec) - projection(dirZ onto dirX) */
-       Projf(axis1, dirZ, splineVec);                                  /* project dirZ onto Y-Axis */
-       Projf(axis2, dirZ, pchan->pose_mat[0]);                 /* project dirZ onto X-Axis */
-       
-       VecSubf(tmpVec, dirZ, axis1);                                   /* dirZ - proj(dirZ->YAxis) */
-       VecSubf(pchan->pose_mat[2], tmpVec, axis2);     /* (dirZ - proj(dirZ->YAxis)) - proj(dirZ->XAxis) */
-       
-       Normalize(pchan->pose_mat[2]);
-       
-       /* step 3b: rotate these axes for roll control and also to minimise flipping rotations */
-       // NOTE: for controlling flipping rotations, we could look to the curve for guidance...
-               // TODO: code me!
-       
+       {
+               float dmat[3][3], rmat[3][3], tmat[3][3];
+               float raxis[3], rangle;
+               
+               /* compute the raw rotation matrix from the bone's current matrix by extracting only the
+                * orientation-relevant axes, and normalising them
+                */
+               VECCOPY(rmat[0], pchan->pose_mat[0]);
+               VECCOPY(rmat[1], pchan->pose_mat[1]);
+               VECCOPY(rmat[2], pchan->pose_mat[2]);
+               Mat3Ortho(rmat);
+               
+               /* also, normalise the orientation imposed by the bone, now that we've extracted the scale factor */
+               Normalize(splineVec);
+               
+               /* calculate smallest axis-angle rotation necessary for getting from the
+                * current orientation of the bone, to the spline-imposed direction
+                */
+               Crossf(raxis, rmat[1], splineVec);
+               
+               rangle= Inpf(rmat[1], splineVec);
+               rangle= acos( MAX2(-1.0f, MIN2(1.0f, rangle)) );
+               
+               /* construct rotation matrix from the axis-angle rotation found above 
+                *      - this call takes care to make sure that the axis provided is a unit vector first
+                */
+               AxisAngleToMat3(raxis, rangle, dmat);
+               
+               /* combine these rotations so that the y-axis of the bone is now aligned as the spline dictates,
+                * while still maintaining roll control from the existing bone animation
+                */
+               Mat3MulMat3(tmat, dmat, rmat); // m1, m3, m2
+               Mat3Ortho(tmat); /* attempt to reduce shearing, though I doubt this'll really help too much now... */
+               Mat4CpyMat3(poseMat, tmat);
+       }
        
        /* step 4: set the scaling factors for the axes */
+       {
                /* only multiply the y-axis by the scaling factor to get nice volume-preservation */
-       VecMulf(pchan->pose_mat[1], scaleFac);
-               
+               VecMulf(poseMat[1], scaleFac);
+                       
                /* set the scaling factors of the x and z axes from the average radius of the curve? */
-       if (ikData->flag & CONSTRAINT_SPLINEIK_RAD2FAT) {
-               VecMulf(pchan->pose_mat[0], radius);
-               VecMulf(pchan->pose_mat[2], radius);
+               if (ikData->flag & CONSTRAINT_SPLINEIK_RAD2FAT) {
+                       VecMulf(poseMat[0], radius);
+                       VecMulf(poseMat[2], radius);
+               }
        }
        
        /* step 5: set the location of the bone in the matrix */
-       VECCOPY(pchan->pose_mat[3], pchan->pose_head);
+       VECCOPY(poseMat[3], pchan->pose_head);
+       
+       /* finally, store the new transform */
+       Mat4CpyMat4(pchan->pose_mat, poseMat);
+       VECCOPY(pchan->pose_head, poseHead);
+       VECCOPY(pchan->pose_tail, poseTail);
        
        /* done! */
        pchan->flag |= POSE_DONE;
index a387d1bca9df7cd0ee71cd1fbfe3b8b9dc2ff8e5..8391ebdebb7a7fc6519d0215ec6e04ba7378f0ff 100644 (file)
@@ -537,7 +537,7 @@ static int read_undosave(bContext *C, UndoElem *uel)
        int success=0, fileflags;
        
        /* This is needed so undoing/redoing doesnt crash with threaded previews going */
-       WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C));
+       WM_jobs_stop_all(CTX_wm_manager(C));
        
        strcpy(scestr, G.sce);  /* temporal store */
        fileflags= G.fileflags;
index f31f4cd975385dbef6fb2ef5242fa7d60c48896a..5580070b922759e81301f4d30601637eedd2f301 100644 (file)
@@ -2906,7 +2906,7 @@ void curve_applyVertexCos(Curve *cu, ListBase *lb, float (*vertexCos)[3])
 
 float (*curve_getKeyVertexCos(Curve *cu, ListBase *lb, float *key))[3]
 {
-       int i, numVerts;
+       int i, numVerts = count_curveverts(lb);
        float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "cu_vcos");
        Nurb *nu;
 
index 477368652735e598ae62104b3b1300e97c67cf43..b7949a6e06f83605d5b63cdccc51cdd35553833b 100644 (file)
@@ -110,7 +110,7 @@ bDeformGroup *get_named_vertexgroup (Object *ob, char *name)
        return NULL;
 }
 
-int get_named_vertexgroup_num (Object *ob, char *name)
+int get_named_vertexgroup_num (Object *ob, const char *name)
 {
        /* Return the location of the named deform group within the list of
         * deform groups. This function is a combination of get_defgroup_num and
index 639797564cc2805cc8eedc8fa939cb4908157adc..1193e8247bed014484ce2b1d657e8924517472b1 100644 (file)
@@ -3577,10 +3577,11 @@ static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
 {
        int i;
        int texmapping = dmd->texmapping;
+       float mapob_imat[4][4];
 
        if(texmapping == MOD_DISP_MAP_OBJECT) {
                if(dmd->map_object)
-                       Mat4Invert(dmd->map_object->imat, dmd->map_object->obmat);
+                       Mat4Invert(mapob_imat, dmd->map_object->obmat);
                else /* if there is no map object, default to local */
                        texmapping = MOD_DISP_MAP_LOCAL;
        }
@@ -3651,7 +3652,7 @@ static void get_texture_coords(DisplaceModifierData *dmd, Object *ob,
                        case MOD_DISP_MAP_OBJECT:
                                VECCOPY(*texco, *co);
                                Mat4MulVecfl(ob->obmat, *texco);
-                               Mat4MulVecfl(dmd->map_object->imat, *texco);
+                               Mat4MulVecfl(mapob_imat, *texco);
                                break;
                }
        }
index a17b4b0be68118e8e5d1923e9a8baa0363ad3510..6e986325f551b70efce0858375e5b7ff3b400236 100644 (file)
@@ -92,12 +92,13 @@ static int (*SB_localInterruptCallBack)(void) = NULL;
 
 /* ********** soft body engine ******* */
 
+typedef        enum {SB_EDGE=1,SB_BEND=2,SB_STIFFQUAD=3} type_spring;
 
 typedef struct BodySpring {
        int v1, v2;
-       float len, strength, cf,load;
+       float len,cf,load;
        float ext_force[3]; /* edges colliding and sailing */
-       short order;
+       type_spring springtype;
        short flag;
 } BodySpring;
 
@@ -613,13 +614,11 @@ static void add_mesh_quad_diag_springs(Object *ob)
                                        if(mface->v4) {
                                                bs->v1= mface->v1;
                                                bs->v2= mface->v3;
-                                               bs->strength= s_shear;
-                                               bs->order   =2;
+                                               bs->springtype   =SB_STIFFQUAD;
                                                bs++;
                                                bs->v1= mface->v2;
                                                bs->v2= mface->v4;
-                                               bs->strength= s_shear;
-                                               bs->order   =2;
+                                               bs->springtype   =SB_STIFFQUAD;
                                                bs++;
                                                
                                        }
@@ -670,8 +669,7 @@ static void add_2nd_order_roller(Object *ob,float stiffness,int *counter, int ad
                                                if (addsprings){
                                                        bs3->v1= v0;
                                                        bs3->v2= bs2->v1;
-                                                       bs3->strength= stiffness;
-                                                       bs3->order=2;
+                                                   bs3->springtype   =SB_BEND;
                                                        bs3++;
                                                }
                                        }
@@ -680,8 +678,7 @@ static void add_2nd_order_roller(Object *ob,float stiffness,int *counter, int ad