svn merge -r 30566:30717 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorJoerg Mueller <nexyon@gmail.com>
Sun, 25 Jul 2010 13:12:58 +0000 (13:12 +0000)
committerJoerg Mueller <nexyon@gmail.com>
Sun, 25 Jul 2010 13:12:58 +0000 (13:12 +0000)
132 files changed:
intern/guardedalloc/MEM_guardedalloc.h
intern/smoke/intern/FLUID_3D.h
release/scripts/io/export_fbx.py
release/scripts/io/import_scene_obj.py
release/scripts/io/netrender/__init__.py
release/scripts/op/object.py
release/scripts/ui/properties_data_armature_rigify.py
release/scripts/ui/space_image.py
release/scripts/ui/space_sequencer.py
release/scripts/ui/space_userpref.py
release/scripts/ui/space_view3d.py
release/scripts/ui/space_view3d_toolbar.py
source/blender/blenkernel/BKE_bmesh.h
source/blender/blenkernel/BKE_brush.h
source/blender/blenkernel/BKE_curve.h
source/blender/blenkernel/BKE_sequencer.h
source/blender/blenkernel/intern/anim.c
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/brush.c
source/blender/blenkernel/intern/cloth.c
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/key.c
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/pointcache.c
source/blender/blenkernel/intern/scene.c
source/blender/blenkernel/intern/seqcache.c [new file with mode: 0644]
source/blender/blenkernel/intern/seqeffects.c
source/blender/blenkernel/intern/sequencer.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenlib/intern/math_geom.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/editors/animation/keyingsets.c
source/blender/editors/armature/editarmature.c
source/blender/editors/curve/editcurve.c
source/blender/editors/curve/editfont.c
source/blender/editors/datafiles/startup.blend.c
source/blender/editors/include/ED_curve.h
source/blender/editors/include/ED_sculpt.h
source/blender/editors/interface/interface.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/resources.c
source/blender/editors/mesh/editmesh_add.c
source/blender/editors/mesh/editmesh_mods.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/metaball/mball_edit.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_select.c
source/blender/editors/object/object_transform.c
source/blender/editors/physics/particle_edit.c
source/blender/editors/render/render_shading.c
source/blender/editors/screen/area.c
source/blender/editors/screen/screen_intern.h
source/blender/editors/screen/screen_ops.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/paint_intern.h
source/blender/editors/sculpt_paint/paint_ops.c
source/blender/editors/sculpt_paint/paint_stroke.c
source/blender/editors/sculpt_paint/paint_undo.c
source/blender/editors/sculpt_paint/paint_utils.c
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/space_file/file_ops.c
source/blender/editors/space_image/image_draw.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_info/info_stats.c
source/blender/editors/space_info/space_info.c
source/blender/editors/space_node/node_select.c
source/blender/editors/space_script/script_edit.c
source/blender/editors/space_sequencer/sequencer_add.c
source/blender/editors/space_sequencer/sequencer_draw.c
source/blender/editors/space_sequencer/sequencer_select.c
source/blender/editors/space_sequencer/space_sequencer.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/view3d_buttons.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_edit.c
source/blender/editors/space_view3d/view3d_intern.h
source/blender/editors/space_view3d/view3d_ops.c
source/blender/editors/space_view3d/view3d_snap.c
source/blender/editors/space_view3d/view3d_view.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform_constraints.c
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c
source/blender/editors/transform/transform_input.c
source/blender/editors/transform/transform_manipulator.c
source/blender/editors/transform/transform_orientations.c
source/blender/editors/util/undo.c
source/blender/makesdna/DNA_curve_types.h
source/blender/makesdna/DNA_mesh_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesdna/intern/dna_genfile.c
source/blender/makesdna/intern/makesdna.c
source/blender/makesrna/SConscript
source/blender/makesrna/intern/CMakeLists.txt
source/blender/makesrna/intern/Makefile
source/blender/makesrna/intern/rna_brush.c
source/blender/makesrna/intern/rna_camera.c
source/blender/makesrna/intern/rna_curve.c
source/blender/makesrna/intern/rna_mesh.c
source/blender/makesrna/intern/rna_modifier.c
source/blender/makesrna/intern/rna_object_force.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_sequencer.c
source/blender/makesrna/intern/rna_userdef.c
source/blender/modifiers/intern/MOD_multires.c
source/blender/nodes/intern/CMP_util.c
source/blender/python/generic/mathutils.h
source/blender/python/generic/mathutils_quat.c
source/blender/python/intern/bpy_rna.c
source/blender/python/intern/bpy_rna.h
source/blender/render/intern/include/render_types.h
source/blender/render/intern/include/volume_precache.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/gammaCorrectionTables.c
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/shadeinput.c
source/blender/render/intern/source/volume_precache.c
source/blender/render/intern/source/volumetric.c
source/blender/windowmanager/intern/wm_draw.c
source/blender/windowmanager/intern/wm_files.c
source/blender/windowmanager/intern/wm_operators.c
source/blenderplayer/bad_level_call_stubs/stubs.c
source/gameengine/Converter/BL_ArmatureChannel.cpp
source/gameengine/Converter/BL_ArmatureObject.cpp
source/gameengine/Expressions/PyObjectPlus.cpp
source/gameengine/Ketsji/KX_Camera.h
source/gameengine/Ketsji/KX_Dome.cpp

index c51e96f04b51e29c2fd4189e6c3b7dace542b1a8..6b78b0b6bdc987ad8ea798f6fe8018bedd6a00c7 100644 (file)
@@ -63,7 +63,7 @@
 extern "C" {
 #endif
 
-       /** Returns the lenght of the allocated memory segment pointed at
+       /** Returns the length of the allocated memory segment pointed at
         * by vmemh. If the pointer was not previously allocated by this
         * module, the result is undefined.*/
        size_t MEM_allocN_len(void *vmemh);
index ab121ef506eff24a1f5f328b99aae9a31b462051..6ca50b2c03207c710065af3305911aabb2ae210c 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <cstdlib>
 #include <cmath>
+#include <cstring>
 #include <iostream>
 #include "OBSTACLE.h"
 // #include "WTURBULENCE.h"
index 6469a59c8ffb5a383992c5a0e78904630e958246..b68d6fafafa4ac54e5d582423064dcd289bb5efc 100644 (file)
@@ -947,10 +947,7 @@ def write(filename, batch_objects = None, \
         render = scene.render
         width  = render.resolution_x
         height = render.resolution_y
-#              render = scene.render
-#              width   = render.sizeX
-#              height  = render.sizeY
-        aspect = float(width)/height
+        aspect = width / height
 
         data = my_cam.blenObject.data
 
@@ -962,11 +959,9 @@ def write(filename, batch_objects = None, \
         file.write('\n\t\t\tProperty: "FieldOfView", "FieldOfView", "A+",%.6f' % math.degrees(data.angle))
         file.write('\n\t\t\tProperty: "FieldOfViewX", "FieldOfView", "A+",1')
         file.write('\n\t\t\tProperty: "FieldOfViewY", "FieldOfView", "A+",1')
-        file.write('\n\t\t\tProperty: "FocalLength", "Real", "A+",14.0323972702026')
+        file.write('\n\t\t\tProperty: "FocalLength", "Real", "A+",14.0323972702026')
         file.write('\n\t\t\tProperty: "OpticalCenterX", "Real", "A+",%.6f' % data.shift_x) # not sure if this is in the correct units?
-#              file.write('\n\t\t\tProperty: "OpticalCenterX", "Real", "A+",%.6f' % data.shiftX) # not sure if this is in the correct units?
         file.write('\n\t\t\tProperty: "OpticalCenterY", "Real", "A+",%.6f' % data.shift_y) # ditto
-#              file.write('\n\t\t\tProperty: "OpticalCenterY", "Real", "A+",%.6f' % data.shiftY) # ditto
         file.write('\n\t\t\tProperty: "BackgroundColor", "Color", "A+",0,0,0')
         file.write('\n\t\t\tProperty: "TurnTable", "Real", "A+",0')
         file.write('\n\t\t\tProperty: "DisplayTurnTableIcon", "bool", "",1')
@@ -975,7 +970,7 @@ def write(filename, batch_objects = None, \
         file.write('\n\t\t\tProperty: "UseRealTimeMotionBlur", "bool", "",1')
         file.write('\n\t\t\tProperty: "ResolutionMode", "enum", "",0')
         file.write('\n\t\t\tProperty: "ApertureMode", "enum", "",2')
-        file.write('\n\t\t\tProperty: "GateFit", "enum", "",0')
+        file.write('\n\t\t\tProperty: "GateFit", "enum", "",2')
         file.write('\n\t\t\tProperty: "CameraFormat", "enum", "",0')
         file.write('\n\t\t\tProperty: "AspectW", "double", "",%i' % width)
         file.write('\n\t\t\tProperty: "AspectH", "double", "",%i' % height)
@@ -2782,7 +2777,7 @@ Takes:  {''')
 
                 # Set the action active
                 for my_bone in ob_arms:
-                    if blenAction in my_bone.blenActionList:
+                    if ob.animation_data and blenAction in my_bone.blenActionList:
                         ob.animation_data.action = blenAction
                         # print '\t\tSetting Action!', blenAction
                 # scene.update(1)
index 9bbb9124b605c524705eb5d8369b373787b6489d..5b29a5ded909ab21e6e34f94a8b174bd965fbef0 100644 (file)
@@ -420,8 +420,7 @@ def create_materials(filepath, material_libs, unique_materials, unique_material_
     # Add an MTL with the same name as the obj if no MTLs are spesified.
     temp_mtl = os.path.splitext((os.path.basename(filepath)))[0] + '.mtl'
 
-    if os.path.exists(DIR + temp_mtl) and temp_mtl not in material_libs:
-#      if sys.exists(DIR + temp_mtl) and temp_mtl not in material_libs:
+    if os.path.exists(os.path.join(DIR, temp_mtl)) and temp_mtl not in material_libs:
         material_libs.append( temp_mtl )
     del temp_mtl
 
@@ -435,11 +434,9 @@ def create_materials(filepath, material_libs, unique_materials, unique_material_
     unique_material_images[None]= None, False
 
     for libname in material_libs:
-        mtlpath= DIR + libname
+        mtlpath= os.path.join(DIR, libname)
         if not os.path.exists(mtlpath):
-#              if not sys.exists(mtlpath):
-            #print '\tError Missing MTL: "%s"' % mtlpath
-            pass
+            print ("\tError Missing MTL: '%s'" % mtlpath)
         else:
             #print '\t\tloading mtl: "%s"' % mtlpath
             context_material= None
index f5f104d6d9229d2eb6eb6dc7a4231be6d46b2693..43f3094e628e227b25d1ddcdb76fc90348969e42 100644 (file)
@@ -42,6 +42,9 @@ def register():
 
 def unregister():
     import bpy
+
+    bpy.types.Scene.RemoveProperty("network_render")
+
     bpy.types.unregister(ui.NetRenderJob)
     bpy.types.unregister(ui.NetRenderSettings)
     bpy.types.unregister(ui.NetRenderSlave)
index 2df1250251e36d0988d242226ef320fb4d014e63..0b052195541919bdb003f6737245434ee2a87b7f 100644 (file)
@@ -113,44 +113,46 @@ class SelectHierarchy(bpy.types.Operator):
         return context.object
 
     def execute(self, context):
-        objs = context.selected_objects
+        select_new = []
+        act_new = None
+        
+        
+        selected_objects = context.selected_objects
         obj_act = context.object
 
-        if context.object not in objs:
-            objs.append(context.object)
-
-        if not self.properties.extend:
-            # for obj in objs:
-            #     obj.select = False
-            bpy.ops.object.select_all(action='DESELECT')
+        if context.object not in selected_objects:
+            selected_objects.append(context.object)
 
         if self.properties.direction == 'PARENT':
-            parents = []
-            for obj in objs:
+            for obj in selected_objects:
                 parent = obj.parent
 
                 if parent:
-                    parents.append(parent)
-
                     if obj_act == obj:
-                        context.scene.objects.active = parent
+                        act_new = parent
 
-                    parent.select = True
-                
-            if parents:
-                return {'CANCELLED'}
+                    select_new.append(parent)
 
         else:
-            children = []
-            for obj in objs:
-                children += list(obj.children)
-                for obj_iter in children:
-                    obj_iter.select = True
+            for obj in selected_objects:
+                select_new.extend(obj.children)
 
-            children.sort(key=lambda obj_iter: obj_iter.name)
-            context.scene.objects.active = children[0]
+            if select_new:
+                select_new.sort(key=lambda obj_iter: obj_iter.name)
+                act_new = select_new[0]
 
-        return {'FINISHED'}
+        # dont edit any object settings above this
+        if select_new:
+            if not self.properties.extend:
+                bpy.ops.object.select_all(action='DESELECT')
+
+            for obj in select_new:
+                obj.select = True
+
+            context.scene.objects.active = act_new
+            return {'FINISHED'}
+            
+        return {'CANCELLED'}
 
 
 class SubdivisionSet(bpy.types.Operator):
index 43021858f9fbb2124126caab03e1d50969e7321c..193ff390b1e29a33fccf12866a7a595734eb85b4 100644 (file)
@@ -360,6 +360,7 @@ def register():
 
 
 def unregister():
+    bpy.types.Scene.RemoveProperty("pose_templates")
     unregister = bpy.types.unregister
     for cls in classes:
         unregister(cls)
index e9c963db7b362307ffa304adc1f49cc0b1936899..907725a4ef7b9043748d0bcbd9d05ad120316b50 100644 (file)
@@ -562,22 +562,10 @@ class IMAGE_PT_paint(bpy.types.Panel):
 
         toolsettings = context.tool_settings.image_paint
         brush = toolsettings.brush
-        wide_ui = context.region.width > narrowui
 
         col = layout.split().column()
         row = col.row()
-        row.template_list(toolsettings, "brushes", toolsettings, "active_brush_index", rows=2)
-
-        col.template_ID(toolsettings, "brush", new="brush.add")
-
-        if wide_ui:
-            sub = layout.row(align=True)
-        else:
-            sub = layout.column(align=True)
-        sub.prop_enum(brush, "imagepaint_tool", 'DRAW')
-        sub.prop_enum(brush, "imagepaint_tool", 'SOFTEN')
-        sub.prop_enum(brush, "imagepaint_tool", 'CLONE')
-        sub.prop_enum(brush, "imagepaint_tool", 'SMEAR')
+        col.template_ID_preview(toolsettings, "brush", new="brush.add", filter="is_imapaint_brush", rows=3, cols=8)
 
         if brush:
             col = layout.column()
@@ -604,6 +592,30 @@ class IMAGE_PT_paint(bpy.types.Panel):
                 col.prop(brush, "clone_alpha", text="Alpha")
 
 
+class IMAGE_PT_tools_brush_texture(bpy.types.Panel):
+    bl_space_type = 'IMAGE_EDITOR'
+    bl_region_type = 'UI'
+    bl_label = "Texture"
+    bl_default_closed = True
+
+    def poll(self, context):
+        sima = context.space_data
+        toolsettings = context.tool_settings.image_paint
+        return sima.show_paint and toolsettings.brush
+
+    def draw(self, context):
+        layout = self.layout
+
+        toolsettings = context.tool_settings.image_paint
+        brush = toolsettings.brush
+
+#        tex_slot = brush.texture_slot
+
+        col = layout.column()
+
+        col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
+
+
 class IMAGE_PT_paint_stroke(bpy.types.Panel):
     bl_space_type = 'IMAGE_EDITOR'
     bl_region_type = 'UI'
@@ -653,8 +665,15 @@ class IMAGE_PT_paint_curve(bpy.types.Panel):
         brush = toolsettings.brush
 
         layout.template_curve_mapping(brush, "curve")
-        layout.operator_menu_enum("brush.curve_preset", "shape")
 
+        row = layout.row(align=True)
+        row.operator("brush.curve_preset", icon="SMOOTHCURVE", text="").shape = 'SMOOTH'
+        row.operator("brush.curve_preset", icon="SPHERECURVE", text="").shape = 'ROUND'
+        row.operator("brush.curve_preset", icon="ROOTCURVE", text="").shape = 'ROOT'
+        row.operator("brush.curve_preset", icon="SHARPCURVE", text="").shape = 'SHARP'
+        row.operator("brush.curve_preset", icon="LINCURVE", text="").shape = 'LINE'
+        row.operator("brush.curve_preset", icon="NOCURVE", text="").shape = 'MAX'
+        row.operator("brush.curve_preset", icon="RNDCURVE", text="").shape = 'MID9'
 
 classes = [
     IMAGE_MT_view,
@@ -669,6 +688,7 @@ classes = [
     IMAGE_HT_header,
     IMAGE_PT_image_properties,
     IMAGE_PT_paint,
+    IMAGE_PT_tools_brush_texture,
     IMAGE_PT_paint_stroke,
     IMAGE_PT_paint_curve,
     IMAGE_PT_game_properties,
index b9b9003506b21cc254d5fc36c00842e9c5c42d71..ba17b13775a3fec190de99d0da3d0df35a47d096 100644 (file)
@@ -486,6 +486,20 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel):
                 col.prop(strip, "use_effect_default_fade", "Default fade")
                 if not strip.use_effect_default_fade:
                     col.prop(strip, "effect_fader", text="Effect fader")
+        
+        layout.prop(strip, "use_translation", text="Image Offset:")
+        if strip.use_translation:
+            col = layout.column(align=True)
+            col.prop(strip.transform, "offset_x", text="X")
+            col.prop(strip.transform, "offset_y", text="Y")
+
+        layout.prop(strip, "use_crop", text="Image Crop:")
+        if strip.use_crop:
+            col = layout.column(align=True)
+            col.prop(strip.crop, "top")
+            col.prop(strip.crop, "left")
+            col.prop(strip.crop, "bottom")
+            col.prop(strip.crop, "right")
 
     def draw_panel_transform(self, strip):
         layout = self.layout
index 2429f6e472c60f8e8da3399c7956b5eda1a50c61..b3629b03c2278180e9f7171f8fdabef5b5721cb0 100644 (file)
@@ -170,7 +170,7 @@ class USERPREF_PT_interface(bpy.types.Panel):
 
         col.prop(view, "show_mini_axis", text="Display Mini Axis")
         sub = col.column()
-        sub.enabled = view.show_mini_axis
+        sub.active = view.show_mini_axis
         sub.prop(view, "mini_axis_size", text="Size")
         sub.prop(view, "mini_axis_brightness", text="Brightness")
 
@@ -216,7 +216,7 @@ class USERPREF_PT_interface(bpy.types.Panel):
         #col.prop(view, "open_right_mouse_delay", text="Hold RMB")
         col.prop(view, "use_manipulator")
         sub = col.column()
-        sub.enabled = view.use_manipulator
+        sub.active = view.use_manipulator
         sub.prop(view, "manipulator_size", text="Size")
         sub.prop(view, "manipulator_handle_size", text="Handle Size")
         sub.prop(view, "manipulator_hotspot", text="Hotspot")
@@ -720,7 +720,7 @@ class USERPREF_PT_file(bpy.types.Panel):
         col.prop(paths, "save_preview_images")
         col.prop(paths, "auto_save_temporary_files")
         sub = col.column()
-        sub.enabled = paths.auto_save_temporary_files
+        sub.active = paths.auto_save_temporary_files
         sub.prop(paths, "auto_save_time", text="Timer (mins)")
 
 from space_userpref_keymap import InputKeyMapPanel
@@ -748,7 +748,7 @@ class USERPREF_PT_input(InputKeyMapPanel):
 
         sub.label(text="Mouse:")
         sub1 = sub.column()
-        sub1.enabled = (inputs.select_mouse == 'RIGHT')
+        sub1.active = (inputs.select_mouse == 'RIGHT')
         sub1.prop(inputs, "emulate_3_button_mouse")
         sub.prop(inputs, "continuous_mouse")
 
index c5d74d397e8161a01c17cc5d473b16404f2f85b3..12b3c508ac20b391e58768fda9732c941c92aa0e 100644 (file)
@@ -2079,7 +2079,7 @@ class VIEW3D_PT_view3d_meshdisplay(bpy.types.Panel):
 
         col.separator()
         col.label(text="Numerics:")
-        col.prop(mesh, "draw_edge_lenght")
+        col.prop(mesh, "draw_edge_length")
         col.prop(mesh, "draw_edge_angle")
         col.prop(mesh, "draw_face_area")
 
index dabd26f6aad3260726c5ba7d09e259dd34b8999e..9d3c26891af38c5cae64605409a8030ccf0cdbd5 100644 (file)
@@ -555,7 +555,6 @@ class VIEW3D_PT_tools_brush(PaintPanel):
         # Sculpt Mode #
 
         elif context.sculpt_object and brush:
-            edit = context.user_preferences.edit
 
             col = layout.column()
 
@@ -564,21 +563,12 @@ class VIEW3D_PT_tools_brush(PaintPanel):
 
             row = col.row(align=True)
 
-            if edit.sculpt_paint_use_unified_size:
-                if edit.sculpt_paint_unified_lock_brush_size:
-                    row.prop(edit, "sculpt_paint_unified_lock_brush_size", toggle=True, text="", icon='LOCKED')
-                    row.prop(edit, "sculpt_paint_unified_unprojected_radius", text="Radius", slider=True)
-                else:
-                    row.prop(edit, "sculpt_paint_unified_lock_brush_size", toggle=True, text="", icon='UNLOCKED')
-                    row.prop(edit, "sculpt_paint_unified_size", text="Radius", slider=True)
-
+            if brush.use_locked_size:
+                row.prop(brush, "use_locked_size", toggle=True, text="", icon='LOCKED')
+                row.prop(brush, "unprojected_radius", text="Radius", slider=True)
             else:
-                if brush.lock_brush_size:
-                    row.prop(brush, "lock_brush_size", toggle=True, text="", icon='LOCKED')
-                    row.prop(brush, "unprojected_radius", text="Radius", slider=True)
-                else:
-                    row.prop(brush, "lock_brush_size", toggle=True, text="", icon='UNLOCKED')
-                    row.prop(brush, "size", text="Radius", slider=True)
+                row.prop(brush, "use_locked_size", toggle=True, text="", icon='UNLOCKED')
+                row.prop(brush, "size", text="Radius", slider=True)
 
             row.prop(brush, "use_size_pressure", toggle=True, text="")
 
@@ -594,11 +584,7 @@ class VIEW3D_PT_tools_brush(PaintPanel):
                     else:
                         row.prop(brush, "use_space_atten", toggle=True, text="", icon='UNLOCKED')
 
-                if edit.sculpt_paint_use_unified_strength:
-                    row.prop(edit, "sculpt_paint_unified_strength", text="Unified Strength", slider=True)
-                else:
-                    row.prop(brush, "strength", text="Strength", slider=True)
-
+                row.prop(brush, "strength", text="Strength", slider=True)
                 row.prop(brush, "use_strength_pressure", text="")
 
 
@@ -710,11 +696,11 @@ class VIEW3D_PT_tools_brush(PaintPanel):
             col.prop(brush, "color", text="")
 
             row = col.row(align=True)
-            row.prop(brush, "size", slider=True)
+            row.prop(brush, "size", text="Radius", slider=True)
             row.prop(brush, "use_size_pressure", toggle=True, text="")
 
             row = col.row(align=True)
-            row.prop(brush, "strength", slider=True)
+            row.prop(brush, "strength", text="Strength", slider=True)
             row.prop(brush, "use_strength_pressure", toggle=True, text="")
 
             row = col.row(align=True)
@@ -735,12 +721,13 @@ class VIEW3D_PT_tools_brush(PaintPanel):
             layout.prop(context.tool_settings, "auto_normalize", text="Auto Normalize")
 
             col = layout.column()
+
             row = col.row(align=True)
-            row.prop(brush, "size", slider=True)
+            row.prop(brush, "size", text="Radius", slider=True)
             row.prop(brush, "use_size_pressure", toggle=True, text="")
 
             row = col.row(align=True)
-            row.prop(brush, "strength", slider=True)
+            row.prop(brush, "strength", text="Strength", slider=True)
             row.prop(brush, "use_strength_pressure", toggle=True, text="")
 
             row = col.row(align=True)
@@ -755,11 +742,11 @@ class VIEW3D_PT_tools_brush(PaintPanel):
             col.prop(brush, "color", text="")
 
             row = col.row(align=True)
-            row.prop(brush, "size", slider=True)
+            row.prop(brush, "size", text="Radius", slider=True)
             row.prop(brush, "use_size_pressure", toggle=True, text="")
 
             row = col.row(align=True)
-            row.prop(brush, "strength", slider=True)
+            row.prop(brush, "strength", text="Strength", slider=True)
             row.prop(brush, "use_strength_pressure", toggle=True, text="")
 
             # XXX - TODO
@@ -1032,7 +1019,8 @@ class VIEW3D_PT_sculpt_options(PaintPanel):
 
         wide_ui = context.region.width > narrowui
 
-        sculpt = context.tool_settings.sculpt
+        tool_settings = context.tool_settings
+        sculpt = tool_settings.sculpt
         settings = self.paint_settings(context)
         brush = settings.brush
 
@@ -1040,10 +1028,9 @@ class VIEW3D_PT_sculpt_options(PaintPanel):
 
         col = split.column()
 
-        edit = context.user_preferences.edit
         col.label(text="Unified Settings:")
-        col.prop(edit, "sculpt_paint_use_unified_size", text="Size")
-        col.prop(edit, "sculpt_paint_use_unified_strength", text="Strength")
+        col.prop(tool_settings, "sculpt_paint_use_unified_size", text="Size")
+        col.prop(tool_settings, "sculpt_paint_use_unified_strength", text="Strength")
 
         if wide_ui:
             col = split.column()
@@ -1111,12 +1098,14 @@ class VIEW3D_PT_tools_brush_appearance(PaintPanel):
         col = layout.column();
 
         if context.sculpt_object and context.tool_settings.sculpt:
-            #if brush.sculpt_tool in ('DRAW', 'INFLATE', 'CLAY', 'CLAY_TUBES', 'PINCH', 'CREASE', 'BLOB', 'FLATTEN', 'FILL', 'SCRAPE'):
+            #if brush.sculpt_tool in ('DRAW', 'INFLATE', 'CLAY', 'PINCH', 'CREASE', 'BLOB', 'FLATTEN', 'FILL', 'SCRAPE', 'CLAY_TUBES'):
             if brush.sculpt_tool in ('DRAW', 'INFLATE', 'CLAY', 'PINCH', 'CREASE', 'BLOB', 'FLATTEN', 'FILL', 'SCRAPE'):
                 col.prop(brush, "add_col", text="Add Color")
                 col.prop(brush, "sub_col", text="Subtract Color")
             else:
                 col.prop(brush, "add_col", text="Color")
+        else:
+            col.prop(brush, "add_col", text="Color")
 
         col.separator()
 
@@ -1154,7 +1143,8 @@ class VIEW3D_PT_tools_weightpaint_options(View3DPanel):
     def draw(self, context):
         layout = self.layout
 
-        wpaint = context.tool_settings.weight_paint
+        tool_settings = context.tool_settings
+        wpaint = tool_settings.weight_paint
 
         col = layout.column()
         col.prop(wpaint, "all_faces")
@@ -1167,6 +1157,10 @@ class VIEW3D_PT_tools_weightpaint_options(View3DPanel):
             col.prop(mesh, "use_mirror_x")
             col.prop(mesh, "use_mirror_topology")
 
+        col.label(text="Unified Settings:")
+        col.prop(tool_settings, "sculpt_paint_use_unified_size", text="Size")
+        col.prop(tool_settings, "sculpt_paint_use_unified_strength", text="Strength")
+
 # Commented out because the Apply button isn't an operator yet, making these settings useless
 #              col.label(text="Gamma:")
 #              col.prop(wpaint, "gamma", text="")
@@ -1186,7 +1180,8 @@ class VIEW3D_PT_tools_vertexpaint(View3DPanel):
     def draw(self, context):
         layout = self.layout
 
-        vpaint = context.tool_settings.vertex_paint
+        tool_settings = context.tool_settings
+        vpaint = tool_settings.vertex_paint
 
         col = layout.column()
         #col.prop(vpaint, "mode", text="")
@@ -1194,6 +1189,10 @@ class VIEW3D_PT_tools_vertexpaint(View3DPanel):
         col.prop(vpaint, "normals")
         col.prop(vpaint, "spray")
 
+        col.label(text="Unified Settings:")
+        col.prop(tool_settings, "sculpt_paint_use_unified_size", text="Size")
+        col.prop(tool_settings, "sculpt_paint_use_unified_strength", text="Strength")
+
 # Commented out because the Apply button isn't an operator yet, making these settings useless
 #              col.label(text="Gamma:")
 #              col.prop(vpaint, "gamma", text="")
@@ -1272,6 +1271,23 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel):
         sub.operator("image.save_dirty", text="Save All Edited")
 
 
+class VIEW3D_PT_imagepaint_options(PaintPanel):
+    bl_label = "Options"
+    bl_default_closed = True
+
+    def poll(self, context):
+        return (context.texture_paint_object and context.tool_settings.image_paint)
+
+    def draw(self, context):
+        layout = self.layout
+
+        col = layout.column()
+
+        tool_settings = context.tool_settings
+        col.label(text="Unified Settings:")
+        col.prop(tool_settings, "sculpt_paint_use_unified_size", text="Size")
+        col.prop(tool_settings, "sculpt_paint_use_unified_strength", text="Strength")
+        
 class VIEW3D_MT_tools_projectpaint_clone(bpy.types.Menu):
     bl_label = "Clone Layer"
 
@@ -1339,7 +1355,7 @@ class VIEW3D_PT_tools_particlemode(View3DPanel):
         col = layout.column(align=True)
         col.active = pe.editable
         col.label(text="Keep:")
-        col.prop(pe, "keep_lengths", text="Lenghts")
+        col.prop(pe, "keep_lengths", text="Lengths")
         col.prop(pe, "keep_root", text="Root")
         if not pe.hair:
             col.label(text="Correct:")
@@ -1385,6 +1401,7 @@ classes = [
     VIEW3D_PT_sculpt_options,
     VIEW3D_PT_tools_vertexpaint,
     VIEW3D_PT_tools_weightpaint_options,
+    VIEW3D_PT_imagepaint_options,
 
     VIEW3D_PT_tools_projectpaint,
     VIEW3D_MT_tools_projectpaint_clone,
index aff102f2e09294323b1b28410dbe13278c771648..18db68a93af9c79853a18f3c664b875cf85d6837 100644 (file)
@@ -58,7 +58,7 @@ struct BME_Loop;
        -Remove the eflags completely, they are mostly not used
        -Remove the selection/vis/bevel weight flag/values ect and move them to custom data
        -Remove EID member and move to custom data
-       -Add a radial cycle length, disk cycle length and loop cycle lenght attributes to custom data and have eulers maintain/use them if present.
+       -Add a radial cycle length, disk cycle length and loop cycle length attributes to custom data and have eulers maintain/use them if present.
        -Move data such as vertex coordinates/normals to custom data and leave pointers in structures to active layer data.
        -Remove BME_CycleNode structure?
 */
index 75fdb719a621574b67cc3ab6b691444a176f78ac..3ad902c41feea6e998f18f41401e36a21c7997a7 100644 (file)
@@ -88,14 +88,24 @@ void brush_radial_control_invoke(struct wmOperator *op, struct Brush *br, float
 int brush_radial_control_exec(struct wmOperator *op, struct Brush *br, float size_weight);
 
 /* unified strength and size */
-int sculpt_get_brush_size(struct Brush *brush);
-void sculpt_set_brush_size(struct Brush *brush, int size);
-int sculpt_get_lock_brush_size(struct Brush *brush);
-float sculpt_get_brush_unprojected_radius(struct Brush *brush);
-void sculpt_set_brush_unprojected_radius(struct Brush *brush, float unprojected_radius);
-float sculpt_get_brush_alpha(struct Brush *brush);
-void sculpt_set_brush_alpha(struct Brush *brush, float alpha);
 
+int  brush_size(struct Brush *brush);
+void brush_set_size(struct Brush *brush, int value);
+
+int  brush_use_locked_size(struct Brush *brush);
+void brush_set_use_locked_size(struct Brush *brush, int value);
+
+int  brush_use_alpha_pressure(struct Brush *brush);
+void brush_set_use_alpha_pressure(struct Brush *brush, int value);
+
+int  brush_use_size_pressure(struct Brush *brush);
+void brush_set_use_size_pressure(struct Brush *brush, int value);
+
+float brush_unprojected_radius(struct Brush *brush);
+void  brush_set_unprojected_radius(struct Brush *brush, float value);
+
+float brush_alpha(struct Brush *brush);
+void  brush_set_alpha(struct Brush *brush, float value);
 
 #endif
 
index ca45c2f318ce7b7d2a7032f18fbb69bb9b0ffe71..e83ea4b809c15230ccbf5179979f5bacf052b25b 100644 (file)
@@ -105,5 +105,7 @@ int check_valid_nurb_v( struct Nurb *nu);
 int clamp_nurb_order_u( struct Nurb *nu);
 int clamp_nurb_order_v( struct Nurb *nu);
 
+ListBase *BKE_curve_nurbs(struct Curve *cu);
+
 #endif
 
index c5417e04780266ddef806107d45146d895375138..81ae83cafb670e060359978496e4fffdf3fdce41 100644 (file)
@@ -164,6 +164,28 @@ struct StripElem *give_stripelem(struct Sequence *seq, int cfra);
 // intern?
 void update_changed_seq_and_deps(struct Scene *scene, struct Sequence *changed_seq, int len_change, int ibuf_change);
 
+/* seqcache.c */
+
+typedef enum {
+       SEQ_STRIPELEM_IBUF,
+       SEQ_STRIPELEM_IBUF_COMP,
+       SEQ_STRIPELEM_IBUF_STARTSTILL,
+       SEQ_STRIPELEM_IBUF_ENDSTILL
+} seq_stripelem_ibuf_t;
+
+void seq_stripelem_cache_init();
+void seq_stripelem_cache_destruct();
+
+void seq_stripelem_cache_cleanup();
+
+struct ImBuf * seq_stripelem_cache_get(
+       struct Sequence * seq, int rectx, int recty, 
+       float cfra, seq_stripelem_ibuf_t type);
+void seq_stripelem_cache_put(
+       struct Sequence * seq, int rectx, int recty, 
+       float cfra, seq_stripelem_ibuf_t type, struct ImBuf * nval);
+
+
 /* seqeffects.c */
 // intern?
 struct SeqEffectHandle get_sequence_blend(struct Sequence *seq);
index 157c0743c500851f8215f4f21d405b6d86dd1b1a..412084f7cd125e8785a592ee5a3f986b3de2df53 100644 (file)
@@ -66,6 +66,8 @@
 #include "BKE_utildefines.h"
 #include "BKE_depsgraph.h"
 
+#include "ED_curve.h" /* for ED_curve_nurbs */
+
 // XXX bad level call...
 
 /* --------------------- */
@@ -458,17 +460,17 @@ void calc_curvepath(Object *ob)
        float *fp, *dist, *maxdist, xyz[3];
        float fac, d=0, fac1, fac2;
        int a, tot, cycl=0;
+       ListBase *nurbs;
        
        /* in a path vertices are with equal differences: path->len = number of verts */
        /* NOW WITH BEVELCURVE!!! */
        
        if(ob==NULL || ob->type != OB_CURVE) return;
        cu= ob->data;
-       if(cu->editnurb) 
-               nu= cu->editnurb->first;
-       else 
-               nu= cu->nurb.first;
-       
+
+       nurbs= BKE_curve_nurbs(cu);
+       nu= nurbs->first;
+
        if(cu->path) free_path(cu->path);
        cu->path= NULL;
        
index 101c7a3bbbdb7408a8b8417faca5d9536c5bceb7..9a624017a164826cd1f43ebf42129287885a463e 100644 (file)
@@ -102,6 +102,7 @@ void free_blender(void)
        BKE_spacetypes_free();          /* after free main, it uses space callbacks */
        
        IMB_exit();
+       seq_stripelem_cache_destruct();
        
        free_nodesystem();      
 }
index 8e3cc0751b5126f0c10b0b6d00aa49b429b6e360..23a221cadf489cbdb3fcab65266dca8888ee31b8 100644 (file)
@@ -38,6 +38,7 @@
 #include "DNA_windowmanager_types.h"
 
 #include "WM_types.h"
+#include "WM_api.h"
 
 #include "RNA_access.h"
 
@@ -357,9 +358,10 @@ void brush_sample_tex(Brush *brush, float *xy, float *rgba)
        if (mtex && mtex->tex) {
                float co[3], tin, tr, tg, tb, ta;
                int hasrgb;
-               
-               co[0]= xy[0]/(brush->size >> 1);
-               co[1]= xy[1]/(brush->size >> 1);
+               const int radius= brush_size(brush);
+
+               co[0]= xy[0]/radius;
+               co[1]= xy[1]/radius;
                co[2]= 0.0f;
 
                hasrgb= externtex(mtex, co, &tin, &tr, &tg, &tb, &ta);
@@ -382,23 +384,24 @@ void brush_sample_tex(Brush *brush, float *xy, float *rgba)
 }
 
 
-void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **outbuf)
+void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf)
 {
        ImBuf *ibuf;
        float xy[2], dist, rgba[4], *dstf;
        int x, y, rowbytes, xoff, yoff, imbflag;
-       int maxsize = brush->size >> 1;
+       const int radius= brush_size(brush);
        char *dst, crgb[3];
+       const float alpha= brush_alpha(brush);
 
        imbflag= (flt)? IB_rectfloat: IB_rect;
-       xoff = -size/2.0f + 0.5f;
-       yoff = -size/2.0f + 0.5f;
-       rowbytes= size*4;
+       xoff = -bufsize/2.0f + 0.5f;
+       yoff = -bufsize/2.0f + 0.5f;
+       rowbytes= bufsize*4;
 
        if (*outbuf)
                ibuf= *outbuf;
        else
-               ibuf= IMB_allocImBuf(size, size, 32, imbflag, 0);
+               ibuf= IMB_allocImBuf(bufsize, bufsize, 32, imbflag, 0);
 
        if (flt) {
                for (y=0; y < ibuf->y; y++) {
@@ -412,7 +415,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o
                                        dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]);
 
                                        VECCOPY(dstf, brush->rgb);
-                                       dstf[3]= brush->alpha*brush_curve_strength_clamp(brush, dist, maxsize);
+                                       dstf[3]= alpha*brush_curve_strength_clamp(brush, dist, radius);
                                }
                                else if (texfall == 1) {
                                        brush_sample_tex(brush, xy, dstf);
@@ -425,7 +428,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o
                                        dstf[0] = rgba[0]*brush->rgb[0];
                                        dstf[1] = rgba[1]*brush->rgb[1];
                                        dstf[2] = rgba[2]*brush->rgb[2];
-                                       dstf[3] = rgba[3]*brush->alpha*brush_curve_strength_clamp(brush, dist, maxsize);
+                                       dstf[3] = rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius);
                                }
                        }
                }
@@ -448,7 +451,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o
                                        dst[0]= crgb[0];
                                        dst[1]= crgb[1];
                                        dst[2]= crgb[2];
-                                       dst[3]= FTOCHAR(brush->alpha*brush_curve_strength(brush, dist, maxsize));
+                                       dst[3]= FTOCHAR(alpha*brush_curve_strength(brush, dist, radius));
                                }
                                else if (texfall == 1) {
                                        brush_sample_tex(brush, xy, rgba);
@@ -464,7 +467,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o
                                        dst[0] = FTOCHAR(rgba[0]*brush->rgb[0]);
                                        dst[1] = FTOCHAR(rgba[1]*brush->rgb[1]);
                                        dst[2] = FTOCHAR(rgba[2]*brush->rgb[2]);
-                                       dst[3] = FTOCHAR(rgba[3]*brush->alpha*brush_curve_strength_clamp(brush, dist, maxsize));
+                                       dst[3] = FTOCHAR(rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius));
                                }
                        }
                }
@@ -478,7 +481,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int size, ImBuf **o
 typedef struct BrushPainterCache {
        short enabled;
 
-       int size;                       /* size override, if 0 uses brush->size */
+       int size;                       /* size override, if 0 uses 2*brush_size(brush) */
        short flt;                      /* need float imbuf? */
        short texonly;          /* no alpha, color or fallof, only texture in imbuf */
 
@@ -523,8 +526,8 @@ BrushPainter *brush_painter_new(Brush *brush)
        painter->firsttouch= 1;
        painter->cache.lastsize= -1; /* force ibuf create in refresh */
 
-       painter->startsize = brush->size;
-       painter->startalpha = brush->alpha;
+       painter->startsize = brush_size(brush);
+       painter->startalpha = brush_alpha(brush);
        painter->startjitter = brush->jitter;
        painter->startspacing = brush->spacing;
 
@@ -557,8 +560,8 @@ void brush_painter_free(BrushPainter *painter)
 {
        Brush *brush = painter->brush;
 
-       brush->size = painter->startsize;
-       brush->alpha = painter->startalpha;
+       brush_set_size(brush, painter->startsize);
+       brush_set_alpha(brush, painter->startalpha);
        brush->jitter = painter->startjitter;
        brush->spacing = painter->startspacing;
 
@@ -575,9 +578,10 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, i
        float *bf, *mf, *tf, *otf=NULL, xoff, yoff, xy[2], rgba[4];
        char *b, *m, *t, *ot= NULL;
        int dotexold, origx= x, origy= y;
+       const int radius= brush_size(brush);
 
-       xoff = -brush->size/2.0f + 0.5f;
-       yoff = -brush->size/2.0f + 0.5f;
+       xoff = -radius + 0.5f;
+       yoff = -radius + 0.5f;
        xoff += (int)pos[0] - (int)painter->startpaintpos[0];
        yoff += (int)pos[1] - (int)painter->startpaintpos[1];
 
@@ -659,14 +663,15 @@ static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float
        BrushPainterCache *cache= &painter->cache;
        ImBuf *oldtexibuf, *ibuf;
        int imbflag, destx, desty, srcx, srcy, w, h, x1, y1, x2, y2;
+       const int diameter= 2*brush_size(brush);
 
        imbflag= (cache->flt)? IB_rectfloat: IB_rect;
        if (!cache->ibuf)
-               cache->ibuf= IMB_allocImBuf(brush->size, brush->size, 32, imbflag, 0);
+               cache->ibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag, 0);
        ibuf= cache->ibuf;
 
        oldtexibuf= cache->texibuf;
-       cache->texibuf= IMB_allocImBuf(brush->size, brush->size, 32, imbflag, 0);
+       cache->texibuf= IMB_allocImBuf(diameter, diameter, 32, imbflag, 0);
 
        if (oldtexibuf) {
                srcx= srcy= 0;
@@ -713,9 +718,13 @@ static void brush_painter_refresh_cache(BrushPainter *painter, float *pos)
        MTex *mtex= &brush->mtex;
        int size;
        short flt;
+       const int diameter= 2*brush_size(brush);
+       const float alpha= brush_alpha(brush);
 
-       if ((brush->size != cache->lastsize) || (brush->alpha != cache->lastalpha)
-               || (brush->jitter != cache->lastjitter)) {
+       if (diameter != cache->lastsize ||
+               alpha != cache->lastalpha ||
+               brush->jitter != cache->lastjitter)
+       {
                if (cache->ibuf) {
                        IMB_freeImBuf(cache->ibuf);
                        cache->ibuf= NULL;
@@ -726,7 +735,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, float *pos)
                }
 
                flt= cache->flt;
-               size= (cache->size)? cache->size: brush->size;
+               size= (cache->size)? cache->size: diameter;
 
                if (!(mtex && mtex->tex) || (mtex->tex->type==0)) {
                        brush_imbuf_new(brush, flt, 0, size, &cache->ibuf);
@@ -738,8 +747,8 @@ static void brush_painter_refresh_cache(BrushPainter *painter, float *pos)
                else
                        brush_imbuf_new(brush, flt, 2, size, &cache->ibuf);
 
-               cache->lastsize= brush->size;
-               cache->lastalpha= brush->alpha;
+               cache->lastsize= diameter;
+               cache->lastalpha= alpha;
                cache->lastjitter= brush->jitter;
        }
        else if ((brush->flag & BRUSH_FIXED_TEX) && mtex && mtex->tex) {
@@ -758,10 +767,10 @@ void brush_painter_break_stroke(BrushPainter *painter)
 
 static void brush_apply_pressure(BrushPainter *painter, Brush *brush, float pressure)
 {
-       if (brush->flag & BRUSH_ALPHA_PRESSURE
-               brush->alpha = MAX2(0.0, painter->startalpha*pressure);
-       if (brush->flag & BRUSH_SIZE_PRESSURE)
-               brush->size = MAX2(1.0, painter->startsize*pressure);
+       if (brush_use_alpha_pressure(brush)
+               brush_set_alpha(brush, MAX2(0.0, painter->startalpha*pressure));
+       if (brush_use_size_pressure(brush))
+               brush_set_size(brush, MAX2(1.0, painter->startsize*pressure));
        if (brush->flag & BRUSH_JITTER_PRESSURE)
                brush->jitter = MAX2(0.0, painter->startjitter*pressure);
        if (brush->flag & BRUSH_SPACING_PRESSURE)
@@ -772,6 +781,8 @@ void brush_jitter_pos(Brush *brush, float *pos, float *jitterpos)
 {
        if(brush->jitter){
                float rand_pos[2];
+               const int radius= brush_size(brush);
+               const int diameter= 2*radius;
 
                // find random position within a circle of diameter 1
                do {
@@ -779,8 +790,8 @@ void brush_jitter_pos(Brush *brush, float *pos, float *jitterpos)
                        rand_pos[1] = BLI_frand()-0.5f;
                } while (len_v2(rand_pos) > 0.5f);
 
-               jitterpos[0] = pos[0] + 2*rand_pos[0]*brush->size*brush->jitter;
-               jitterpos[1] = pos[1] + 2*rand_pos[1]*brush->size*brush->jitter;
+               jitterpos[0] = pos[0] + 2*rand_pos[0]*diameter*brush->jitter;
+               jitterpos[1] = pos[1] + 2*rand_pos[1]*diameter*brush->jitter;
        }
        else {
                VECCOPY2D(jitterpos, pos);
@@ -819,7 +830,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
                double starttime, curtime= time;
 
                /* compute brush spacing adapted to brush size */
-               spacing= brush->rate; //brush->size*brush->spacing*0.01f;
+               spacing= brush->rate; //radius*brush->spacing*0.01f;
 
                /* setup starting time, direction vector and accumulated time */
                starttime= painter->accumtime;
@@ -850,11 +861,13 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
        else {
                float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2];
                float t, len, press;
+               const int radius= brush_size(brush);
+               const int diameter= 2*radius;
 
-               /* compute brush spacing adapted to brush size, spacing may depend
+               /* compute brush spacing adapted to brush radius, spacing may depend
                   on pressure, so update it */
                brush_apply_pressure(painter, brush, painter->lastpressure);
-               spacing= MAX2(1.0f, brush->size)*brush->spacing*0.01f;
+               spacing= MAX2(1.0f, radius)*brush->spacing*0.01f;
 
                /* setup starting distance, direction vector and accumulated distance */
                startdistance= painter->accumdistance;
@@ -871,7 +884,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
                        t = step/len;
                        press= (1.0f-t)*painter->lastpressure + t*pressure;
                        brush_apply_pressure(painter, brush, press);
-                       spacing= MAX2(1.0f, brush->size)*brush->spacing*0.01f;
+                       spacing= MAX2(1.0f, radius)*brush->spacing*0.01f;
 
                        brush_jitter_pos(brush, paintpos, finalpos);
 
@@ -921,8 +934,8 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl
        painter->lastmousepos[1]= pos[1];
        painter->lastpressure= pressure;
 
-       brush->alpha = painter->startalpha;
-       brush->size = painter->startsize;
+       brush_set_alpha(brush, painter->startalpha);
+       brush_set_size(brush, painter->startsize);
        brush->jitter = painter->startjitter;
        brush->spacing = painter->startspacing;
 
@@ -1041,9 +1054,9 @@ void brush_radial_control_invoke(wmOperator *op, Brush *br, float size_weight)
        float original_value= 0;
 
        if(mode == WM_RADIALCONTROL_SIZE)
-               original_value = sculpt_get_brush_size(br) * size_weight;
+               original_value = brush_size(br) * size_weight;
        else if(mode == WM_RADIALCONTROL_STRENGTH)
-               original_value = sculpt_get_brush_alpha(br);
+               original_value = brush_alpha(br);
        else if(mode == WM_RADIALCONTROL_ANGLE) {
                MTex *mtex = brush_active_texture(br);
                if(mtex)
@@ -1061,15 +1074,15 @@ int brush_radial_control_exec(wmOperator *op, Brush *br, float size_weight)
        const float conv = 0.017453293;
 
        if(mode == WM_RADIALCONTROL_SIZE)
-               if (sculpt_get_lock_brush_size(br)) {
+               if (brush_use_locked_size(br)) {
                        float initial_value = RNA_float_get(op->ptr, "initial_value");
-                       const float unprojected_radius = sculpt_get_brush_unprojected_radius(br);
-                       sculpt_set_brush_unprojected_radius(br, unprojected_radius * new_value/initial_value * size_weight);
+                       const float unprojected_radius = brush_unprojected_radius(br);
+                       brush_set_unprojected_radius(br, unprojected_radius * new_value/initial_value * size_weight);
                }
                else
-                       sculpt_set_brush_size(br, new_value * size_weight);
+                       brush_set_size(br, new_value * size_weight);
        else if(mode == WM_RADIALCONTROL_STRENGTH)
-               sculpt_set_brush_alpha(br, new_value);
+               brush_set_alpha(br, new_value);
        else if(mode == WM_RADIALCONTROL_ANGLE) {
                MTex *mtex = brush_active_texture(br);
                if(mtex)
@@ -1078,3 +1091,248 @@ int brush_radial_control_exec(wmOperator *op, Brush *br, float size_weight)
 
        return OPERATOR_FINISHED;
 }
+
+/* Unified Size and Strength */
+
+static void set_unified_settings(Brush *brush, short flag, int value)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       if (value)
+                               sce->toolsettings->sculpt_paint_settings |= flag;
+                       else
+                               sce->toolsettings->sculpt_paint_settings &= ~flag;
+               }
+       }
+}
+
+static short unified_settings(Brush *brush)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       return sce->toolsettings->sculpt_paint_settings;
+               }
+       }
+
+       return 0;
+}
+
+static void set_unified_size(Brush *brush, int value)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       sce->toolsettings->sculpt_paint_unified_size= value;
+               }
+       }
+}
+
+static int unified_size(Brush *brush)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       return sce->toolsettings->sculpt_paint_unified_size;
+               }
+       }
+
+       return 35; // XXX magic number
+}
+
+static void set_unified_alpha(Brush *brush, float value)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       sce->toolsettings->sculpt_paint_unified_alpha= value;
+               }
+       }
+}
+
+static float unified_alpha(Brush *brush)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       return sce->toolsettings->sculpt_paint_unified_alpha;
+               }
+       }
+
+       return 0.5f; // XXX magic number
+}
+
+static void set_unified_unprojected_radius(Brush *brush, float value)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       sce->toolsettings->sculpt_paint_unified_unprojected_radius= value;
+               }
+       }
+}
+
+static float unified_unprojected_radius(Brush *brush)
+{
+       Scene *sce;
+       for (sce= G.main->scene.first; sce; sce= sce->id.next) {
+               if (sce->toolsettings && 
+                       ELEM4(brush,
+                           paint_brush(&(sce->toolsettings->imapaint.paint)),
+                           paint_brush(&(sce->toolsettings->vpaint->paint)),
+                           paint_brush(&(sce->toolsettings->wpaint->paint)),
+                           paint_brush(&(sce->toolsettings->sculpt->paint))))
+               {
+                       return sce->toolsettings->sculpt_paint_unified_unprojected_radius;
+               }
+       }
+
+       return 0.125f; // XXX magic number
+}
+void brush_set_size(Brush *brush, int size)
+{
+       if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE)
+               set_unified_size(brush, size);
+       else
+               brush->size= size;
+
+       WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
+}
+
+int brush_size(Brush *brush)
+{
+       return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? unified_size(brush) : brush->size;
+}
+
+void brush_set_use_locked_size(Brush *brush, int value)
+{
+       if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) {
+               set_unified_settings(brush, SCULPT_PAINT_UNIFIED_LOCK_BRUSH_SIZE, value);
+       }
+       else {
+               if (value)
+                       brush->flag |= BRUSH_LOCK_SIZE;
+               else
+                       brush->flag &= ~BRUSH_LOCK_SIZE;
+       }
+
+       WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
+}
+
+int brush_use_locked_size(Brush *brush)
+{
+       return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? (unified_settings(brush) & SCULPT_PAINT_UNIFIED_LOCK_BRUSH_SIZE) : (brush->flag & BRUSH_LOCK_SIZE);
+}
+
+void brush_set_use_size_pressure(Brush *brush, int value)
+{
+       if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) {
+               set_unified_settings(brush, SCULPT_PAINT_UNIFIED_SIZE_PRESSURE, value);
+       }
+       else {
+               if (value)
+                       brush->flag |= BRUSH_SIZE_PRESSURE;
+               else
+                       brush->flag &= ~BRUSH_SIZE_PRESSURE;
+       }
+
+       WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
+}
+
+int brush_use_size_pressure(Brush *brush)
+{
+       return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? (unified_settings(brush) & SCULPT_PAINT_UNIFIED_SIZE_PRESSURE) : (brush->flag & BRUSH_SIZE_PRESSURE);
+}
+
+void brush_set_use_alpha_pressure(Brush *brush, int value)
+{
+       if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_ALPHA) {
+               set_unified_settings(brush, SCULPT_PAINT_UNIFIED_ALPHA_PRESSURE, value);
+       }
+       else {
+               if (value)
+                       brush->flag |= BRUSH_ALPHA_PRESSURE;
+               else
+                       brush->flag &= ~BRUSH_ALPHA_PRESSURE;
+       }
+
+       WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
+}
+
+int brush_use_alpha_pressure(Brush *brush)
+{
+       return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_ALPHA) ? (unified_settings(brush) & SCULPT_PAINT_UNIFIED_ALPHA_PRESSURE) : (brush->flag & BRUSH_ALPHA_PRESSURE);
+}
+
+void brush_set_unprojected_radius(Brush *brush, float unprojected_radius)
+{
+       if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE)
+               set_unified_unprojected_radius(brush, unprojected_radius);
+       else
+               brush->unprojected_radius= unprojected_radius;
+
+       WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
+}
+
+float brush_unprojected_radius(Brush *brush)
+{
+       return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_SIZE) ? unified_unprojected_radius(brush) : brush->unprojected_radius;
+}
+
+void brush_set_alpha(Brush *brush, float alpha)
+{
+       if (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_ALPHA) 
+               set_unified_alpha(brush, alpha);
+       else
+               brush->alpha= alpha;
+
+       WM_main_add_notifier(NC_BRUSH|NA_EDITED, brush);
+}
+
+float brush_alpha(Brush *brush)
+{
+       return (unified_settings(brush) & SCULPT_PAINT_USE_UNIFIED_ALPHA) ? unified_alpha(brush) : brush->alpha;
+}
index ce5bca1da5684d2c9ef33dee1ff4053d4f9239d8..b9b1c16c0c4b2e94836e1a25ce950af492e43fb3 100644 (file)
@@ -144,6 +144,9 @@ void cloth_init ( ClothModifierData *clmd )
 
        if(!clmd->sim_parms->effector_weights)
                clmd->sim_parms->effector_weights = BKE_add_effector_weights(NULL);
+
+       if(clmd->point_cache)
+               clmd->point_cache->step = 1;
 }
 
 static BVHTree *bvhselftree_build_from_cloth (ClothModifierData *clmd, float epsilon)
index d355a520a8ca7094b3097212b83071538b4c6dcb..4142ad7128fe03abaa7e17c3272ad37d73e62920 100644 (file)
@@ -58,6 +58,8 @@
 #include "BKE_object.h"  
 #include "BKE_utildefines.h"  // VECCOPY
 
+#include "ED_curve.h"
+
 /* globals */
 
 /* local */
@@ -104,13 +106,8 @@ void free_curve(Curve *cu)
        BLI_freelistN(&cu->bev);
        freedisplist(&cu->disp);
        BKE_free_editfont(cu);
-       
-       if(cu->editnurb) {
-               freeNurblist(cu->editnurb);
-               MEM_freeN(cu->editnurb);
-               cu->editnurb= NULL;
-       }
 
+       free_curve_editNurb(cu);
        unlink_curve(cu);
        BKE_free_animdata((ID *)cu);
        
@@ -2008,8 +2005,10 @@ void makeBevelList(Object *ob)
        /* STEP 1: MAKE POLYS  */
 
        BLI_freelistN(&(cu->bev));
-       if(cu->editnurb && ob->type!=OB_FONT) nu= cu->editnurb->first;
-       else nu= cu->nurb.first;
+       if(cu->editnurb && ob->type!=OB_FONT) {
+               ListBase *nurbs= ED_curve_editnurbs(cu);
+               nu= nurbs->first;
+       } else nu= cu->nurb.first;
        
        while(nu) {
                
@@ -2999,7 +2998,7 @@ float (*curve_getKeyVertexCos(Curve *cu, ListBase *lb, float *key))[3]
                                VECCOPY(co, key); co+=3; key+=3;
                                VECCOPY(co, key); co+=3; key+=3;
                                VECCOPY(co, key); co+=3; key+=3;
-                               key++; /* skip tilt */
+                               key+=3; /* skip tilt */
                        }
                }
                else {
@@ -3099,5 +3098,12 @@ int clamp_nurb_order_v( struct Nurb *nu)
        return change;
 }
 
+/* Get edit nurbs or normal nurbs list */
+ListBase *BKE_curve_nurbs(Curve *cu)
+{
+       if (cu->editnurb) {
+               return ED_curve_editnurbs(cu);
+       }
 
-
+       return &cu->nurb;
+}
index bb020c936a651c4970c7f2c738b4e460b5879f62..ca659faa9727201239964b13a13053942d646d1e 100644 (file)
@@ -63,6 +63,7 @@
 
 #include "BLO_sys_types.h" // for intptr_t support
 
+#include "ED_curve.h" /* for BKE_curve_nurbs */
 
 static void boundbox_displist(Object *ob);
 
@@ -1221,7 +1222,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl
        ModifierData *md = modifiers_getVirtualModifierList(ob);
        ModifierData *preTesselatePoint;
        Curve *cu= ob->data;
-       ListBase *nurb= cu->editnurb?cu->editnurb:&cu->nurb;
+       ListBase *nurb= BKE_curve_nurbs(cu);
        int numVerts = 0;
        int editmode = (!forRender && cu->editnurb);
        float (*originalVerts)[3] = NULL;
@@ -1324,8 +1325,9 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba
        ModifierData *md = modifiers_getVirtualModifierList(ob);
        ModifierData *preTesselatePoint;
        Curve *cu= ob->data;
-       ListBase *nurb= cu->editnurb?cu->editnurb:&cu->nurb;
-       int required_mode, totvert = 0;
+       ListBase *nurb= BKE_curve_nurbs(cu);
+       DispList *dl;
+       int required_mode = 0, totvert = 0;
        int editmode = (!forRender && cu->editnurb);
        DerivedMesh *dm= NULL, *ndm;
        float (*vertCos)[3] = NULL;
@@ -1590,9 +1592,9 @@ void makeDispListSurf(Scene *scene, Object *ob, ListBase *dispbase,
        int numVerts;
        float (*originalVerts)[3];
        float (*deformedVerts)[3];
-               
+
        if(!forRender && cu->editnurb)
-               nubase= cu->editnurb;
+               nubase= ED_curve_editnurbs(cu);
        else
                nubase= &cu->nurb;
 
@@ -1689,10 +1691,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
                        cu->taperobj = NULL;
                }
 
-               if(cu->editnurb)
-                       nubase= cu->editnurb;
-               else
-                       nubase= &cu->nurb;
+               nubase= BKE_curve_nurbs(cu);
 
                BLI_freelistN(&(cu->bev));
 
index b8219c4aa357c83bb7f3943cc62c81050b44ddf2..354b3b0e7d80d30611572ae4d94048b55c6265d9 100644 (file)
@@ -542,11 +542,15 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                poinsize= ofs[0];
        }
        else if( GS(key->from->name)==ID_CU ) {
-               if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
-               else ofs[0]= sizeof(float)*10;
-               
+               if(mode==KEY_BPOINT) {
+                       ofs[0]= sizeof(float)*4;
+                       poinsize= ofs[0];
+               }else {
+                       ofs[0]= sizeof(float)*12;
+                       poinsize= ofs[0]/3;
+               }
+
                ofs[1]= 0;
-               poinsize= ofs[0];
        }
 
        if(end>tot) end= tot;
@@ -612,7 +616,7 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                                memcpy(poin, k1, sizeof(float)*4);
                                break;
                        case IPO_BEZTRIPLE:
-                               memcpy(poin, k1, sizeof(float)*10);
+                               memcpy(poin, k1, sizeof(float)*12);
                                break;
                        }
                        
@@ -644,28 +648,25 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
 static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, int start, int end, char *out, int tot)
 {
        Nurb *nu;
-       char *poin;
        int a, step, a1, a2;
 
        for(a=0, nu=cu->nurb.first; nu; nu=nu->next, a+=step) {
                if(nu->bp) {
                        step= nu->pntsu*nu->pntsv;
-                       
-                       /* exception because keys prefer to work with complete blocks */
-                       poin= out - a*sizeof(float)*4;
+
                        a1= MAX2(a, start);
                        a2= MIN2(a+step, end);
-                       
-                       if(a1<a2) cp_key(a1, a2, tot, poin, key, actkb, kb, NULL, KEY_BPOINT);
+
+                       if(a1<a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_BPOINT);
                }
                else if(nu->bezt) {
                        step= 3*nu->pntsu;
-                       
-                       poin= out - a*sizeof(float)*10;
+
+                       /* exception because keys prefer to work with complete blocks */
                        a1= MAX2(a, start);
                        a2= MIN2(a+step, end);
 
-                       if(a1<a2) cp_key(a1, a2, tot, poin, key, actkb, kb, NULL, KEY_BEZTRIPLE);
+                       if(a1<a2) cp_key(a1, a2, tot, out, key, actkb, kb, NULL, KEY_BEZTRIPLE);
                }
                else
                        step= 0;
@@ -679,26 +680,34 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock
        int *ofsp, ofs[3], elemsize, b;
        char *cp, *poin, *reffrom, *from, elemstr[8];
        char *freefrom, *freereffrom;
-       
+       int poinsize= 0;
+
        if(key->from==NULL) return;
-       
+
        if( GS(key->from->name)==ID_ME ) {
                ofs[0]= sizeof(float)*3;
                ofs[1]= 0;
+               poinsize= ofs[0];
        }
        else if( GS(key->from->name)==ID_LT ) {
                ofs[0]= sizeof(float)*3;
                ofs[1]= 0;
+               poinsize= ofs[0];
        }
        else if( GS(key->from->name)==ID_CU ) {
-               if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
-               else ofs[0]= sizeof(float)*10;
-               
+               if(mode==KEY_BPOINT) {
+                       ofs[0]= sizeof(float)*4;
+                       poinsize= ofs[0];
+               } else {
+                       ofs[0]= sizeof(float)*12;
+                       poinsize= ofs[0] / 3;
+               }
+
                ofs[1]= 0;
        }
-       
+
        if(end>tot) end= tot;
-       
+
        /* in case of beztriple */
        elemstr[0]= 1;                          /* nr of ipofloats */
        elemstr[1]= IPO_BEZTRIPLE;
@@ -730,7 +739,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock
                                from= key_block_get_data(key, actkb, kb, &freefrom);
                                reffrom= key_block_get_data(key, actkb, refb, &freereffrom);
                                
-                               poin+= start*ofs[0];
+                               poin+= start*poinsize;
                                reffrom+= key->elemsize*start;  // key elemsize yes!
                                from+= key->elemsize*start;
                                
@@ -756,7 +765,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock
                                                        rel_flerp(4, (float *)poin, (float *)reffrom, (float *)from, weight);
                                                        break;
                                                case IPO_BEZTRIPLE:
-                                                       rel_flerp(10, (float *)poin, (float *)reffrom, (float *)from, weight);
+                                                       rel_flerp(12, (float *)poin, (float *)reffrom, (float *)from, weight);
                                                        break;
                                                }
                                                
@@ -803,11 +812,15 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                poinsize= ofs[0];
        }
        else if( GS(key->from->name)==ID_CU ) {
-               if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
-               else ofs[0]= sizeof(float)*10;
-               
+               if(mode==KEY_BPOINT) {
+                       ofs[0]= sizeof(float)*4;
+                       poinsize= ofs[0];
+               } else {
+                       ofs[0]= sizeof(float)*12;
+                       poinsize= ofs[0] / 3;
+               }
+
                ofs[1]= 0;
-               poinsize= ofs[0];
        }
        
        if(end>tot) end= tot;
@@ -929,7 +942,7 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                                flerp(4, (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
                                break;
                        case IPO_BEZTRIPLE:
-                               flerp(10, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t);
+                               flerp(12, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t);
                                break;
                        }
                        
@@ -1137,19 +1150,16 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
 static void do_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, char *out, int tot)
 {
        Nurb *nu;
-       char *poin;
        int a, step;
        
        for(a=0, nu=cu->nurb.first; nu; nu=nu->next, a+=step) {
                if(nu->bp) {
                        step= nu->pntsu*nu->pntsv;
-                       poin= out - a*sizeof(float)*4;
-                       do_key(a, a+step, tot, poin, key, actkb, k, t, KEY_BPOINT);
+                       do_key(a, a+step, tot, out, key, actkb, k, t, KEY_BPOINT);
                }
                else if(nu->bezt) {
                        step= 3*nu->pntsu;
-                       poin= out - a*sizeof(float)*10;
-                       do_key(a, a+step, tot, poin, key, actkb, k, t, KEY_BEZTRIPLE);
+                       do_key(a, a+step, tot, out, key, actkb, k, t, KEY_BEZTRIPLE);
                }
                else
                        step= 0;
@@ -1159,19 +1169,16 @@ static void do_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float
 static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, float ctime, char *out, int tot)
 {
        Nurb *nu;
-       char *poin;
        int a, step;
        
        for(a=0, nu=cu->nurb.first; nu; nu=nu->next, a+=step) {
                if(nu->bp) {
                        step= nu->pntsu*nu->pntsv;
-                       poin= out - a*sizeof(float)*3;
                        do_rel_key(a, a+step, tot, out, key, actkb, KEY_BPOINT);
                }
                else if(nu->bezt) {
                        step= 3*nu->pntsu;
-                       poin= out - a*sizeof(float)*10;
-                       do_rel_key(a, a+step, tot, poin, key, actkb, KEY_BEZTRIPLE);
+                       do_rel_key(a, a+step, tot, out, key, actkb, KEY_BEZTRIPLE);
                }
                else
                        step= 0;
@@ -1184,35 +1191,61 @@ static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
        KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
        float cfra, ctime, t[4], delta;
        int a, flag = 0, step = 0;
-       
-       if(key->slurph) {
-               delta= key->slurph;
-               delta/= tot;
-               
+
+       if(key->slurph  && key->type!=KEY_RELATIVE) {
+               Nurb *nu;
+               int mode, i= 0, remain= 0, estep, count;
+
+               delta= (float)key->slurph / tot;
+
                step= 1;
                if(tot>100 && slurph_opt) {
                        step= tot/50;
                        delta*= step;
                        /* in do_key and cp_key the case a>tot has been handled */
                }
-               
+
                cfra= (float)scene->r.cfra;
-               
-               for(a=0; a<tot; a+=step, cfra+= delta) {
-                       ctime= bsystem_time(scene, 0, cfra, 0.0f); // XXX old cruft
-#if 0 // XXX old animation system
-                       if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
-                               ctime /= 100.0;
-                               CLAMP(ctime, 0.0, 1.0);
+
+               for(nu=cu->nurb.first; nu; nu=nu->next) {
+                       if(nu->bp) {
+                               mode= KEY_BPOINT;
+                               estep= nu->pntsu*nu->pntsv;
+                       }
+                       else if(nu->bezt) {
+                               mode= KEY_BEZTRIPLE;
+                               estep= 3*nu->pntsu;
                        }
-#endif // XXX old animation system
-               
-                       flag= setkeys(ctime, &key->block, k, t, 0);
-                       
-                       if(flag==0)
-                               do_key(a, a+step, tot, (char *)out, key, actkb, k, t, 0);
                        else
-                               cp_key(a, a+step, tot, (char *)out, key, actkb, k[2], NULL, 0);
+                               step= 0;
+
+                       a= 0;
+                       while (a < estep) {
+                               if (remain <= 0) {
+                                       cfra+= delta;
+                                       ctime= bsystem_time(scene, 0, cfra, 0.0f); // XXX old cruft
+
+                                       ctime /= 100.0f;
+                                       CLAMP(ctime, 0.0f, 1.0f); // XXX for compat, we use this, but this clamping was confusing
+                                       flag= setkeys(ctime, &key->block, k, t, 0);
+
+                                       remain= step;
+                               }
+
+                               count= MIN2(remain, estep);
+                               if (mode == KEY_BEZTRIPLE) {
+                                       count += 3 - count % 3;
+                               }
+
+                               if(flag==0)
+                                       do_key(i, i+count, tot, (char *)out, key, actkb, k, t, mode);
+                               else
+                                       cp_key(i, i+count, tot, (char *)out, key, actkb, k[2], NULL, mode);
+
+                               a += count;
+                               i += count;
+                               remain -= count;
+                       }
                }
        }
        else {
@@ -1336,11 +1369,11 @@ float *do_ob_key(Scene *scene, Object *ob)
                for(nu=cu->nurb.first; nu; nu=nu->next) {
                        if(nu->bezt) {
                                tot += 3*nu->pntsu;
-                               size += nu->pntsu*10*sizeof(float);
+                               size += nu->pntsu*12*sizeof(float);
                        }
                        else if(nu->bp) {
                                tot += nu->pntsu*nu->pntsv;
-                               size += nu->pntsu*nu->pntsv*10*sizeof(float);
+                               size += nu->pntsu*nu->pntsv*12*sizeof(float);
                        }
                }
        }
index 8b035ff1bba831a267f107cdb21f2e5a658a64d1..acfaef9eb88a41d0b3215431c19dc670ee806568 100644 (file)
@@ -1015,7 +1015,9 @@ int splitIDname(char *name, char *left, int *nr)
                
                left[a]= 0;
        }
-       strcpy(left, name);     
+
+       for(a= 0; name[a]; a++)
+               left[a]= name[a];
 
        return a;
 }
@@ -1105,20 +1107,17 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name)
                if(nr>999 && strlen(left)>16) left[16]= 0;
                else if(strlen(left)>17) left[17]= 0;
 
-               if(left_len) {
-                       for(idtest= lb->first; idtest; idtest= idtest->next) {
-                               if(             (id != idtest) &&
-                                               (idtest->lib == NULL) &&
-                                               (*name == *(idtest->name+2)) &&
-                                               (strncmp(name, idtest->name+2, left_len)==0) &&
-                                               (splitIDname(idtest->name+2, leftest, &nrtest) == left_len)
-
-                               ) {
-                                       if(nrtest < sizeof(in_use))
-                                               in_use[nrtest]= 1;      /* mark as used */
-                                       if(nr <= nrtest)
-                                               nr= nrtest+1;           /* track largest unused */
-                               }
+               for(idtest= lb->first; idtest; idtest= idtest->next) {
+                       if(             (id != idtest) &&
+                                       (idtest->lib == NULL) &&
+                                       (*name == *(idtest->name+2)) &&
+                                       (strncmp(name, idtest->name+2, left_len)==0) &&
+                                       (splitIDname(idtest->name+2, leftest, &nrtest) == left_len)
+                       ) {
+                               if(nrtest < sizeof(in_use))
+                                       in_use[nrtest]= 1;      /* mark as used */
+                               if(nr <= nrtest)
+                                       nr= nrtest+1;           /* track largest unused */
                        }
                }
 
@@ -1135,7 +1134,7 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name)
                 * rather than just chopping and adding numbers, 
                 * shave off the end chars until we have a unique name.
                 * Check the null terminators match as well so we dont get Cube.000 -> Cube.00 */
-               if (nr==0 && name[left_len] == left[left_len]) {
+               if (nr==0 && name[left_len]== left[left_len]) {
                        int len = strlen(name)-1;
                        idtest= is_dupid(lb, id, name);
                        
index 75b5e6d9331951bbf7fb63fc37b732ec7d5ba127..efff3d138e65eebe03b4589b6b8f84c9c6cb99a3 100644 (file)
@@ -1885,13 +1885,12 @@ static void give_parvert(Object *par, int nr, float *vec)
                BPoint *bp;
                BezTriple *bezt;
                int found= 0;
-               
+               ListBase *nurbs;
+
                cu= par->data;
-               if(cu->editnurb)
-                       nu= cu->editnurb->first;
-               else
-                       nu= cu->nurb.first;
-               
+               nurbs= BKE_curve_nurbs(cu);
+               nu= nurbs->first;
+
                count= 0;
                while(nu && !found) {
                        if(nu->type == CU_BEZIER) {
@@ -2946,7 +2945,7 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, char *name, int from_
        Curve *cu= ob->data;
        Key *key= cu->key;
        KeyBlock *kb;
-       ListBase *lb= (cu->editnurb)? cu->editnurb: &cu->nurb;
+       ListBase *lb= BKE_curve_nurbs(cu);
        int newkey= 0;
 
        if(key==NULL) {
index 5295a496d2bc51a9d4947aad81057a49505663b7..ced5d116ad003ec0cfb1fde371aaa90e765cf92b 100644 (file)
@@ -1041,11 +1041,13 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
                if((lb_dupli_ob=object_duplilist(scene, ob))) {
                        DupliObject *dob;
                        for(dob= lb_dupli_ob->first; dob; dob= dob->next) {
-                               ListBase lb_dupli_pid;
-                               BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis);
-                               addlisttolist(lb, &lb_dupli_pid);
-                               if(lb_dupli_pid.first)
-                                       printf("Adding Dupli\n");
+                               if(dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */
+                                       ListBase lb_dupli_pid;
+                                       BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis);
+                                       addlisttolist(lb, &lb_dupli_pid);
+                                       if(lb_dupli_pid.first)
+                                               printf("Adding Dupli\n");
+                               }
                        }
 
                        free_object_duplilist(lb_dupli_ob);     /* does restore */
index fe52375617b34f556831dbc2c68ddbbb201cfcaa..9d736bd92eb305233b5dfa3d0aab34f8af106341 100644 (file)
@@ -512,6 +512,10 @@ void set_scene_bg(Scene *scene)
        /* check for cyclic sets, for reading old files but also for definite security (py?) */
        scene_check_setscene(scene);
        
+       /* can happen when switching modes in other scenes */
+       if(scene->obedit && !(scene->obedit->mode & OB_MODE_EDIT))
+               scene->obedit= NULL;
+
        /* deselect objects (for dataselect) */
        for(ob= G.main->object.first; ob; ob= ob->id.next)
                ob->flag &= ~(SELECT|OB_FROMGROUP);
diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c
new file mode 100644 (file)
index 0000000..4d58ec8
--- /dev/null
@@ -0,0 +1,267 @@
+/**
+* $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Peter Schlaile <peter [at] schlaile [dot] de> 2010
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+#include "MEM_CacheLimiterC-Api.h"
+
+#include "DNA_sequence_types.h"
+#include "BKE_sequencer.h"
+#include "BLI_ghash.h"
+#include "BLI_mempool.h"
+#include <pthread.h>
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+typedef struct seqCacheKey 
+{
+       struct Sequence * seq;
+       int rectx;
+       int recty;
+       float cfra;
+       seq_stripelem_ibuf_t type;
+} seqCacheKey;
+
+typedef struct seqCacheEntry
+{
+       ImBuf * ibuf;
+       MEM_CacheLimiterHandleC * c_handle;
+} seqCacheEntry;
+
+static GHash * hash = 0;
+static MEM_CacheLimiterC * limitor = 0;
+static struct BLI_mempool * entrypool = 0;
+static struct BLI_mempool * keypool = 0;
+static int ibufs_in  = 0;
+static int ibufs_rem = 0;
+
+static unsigned int HashHash(void *key_)
+{
+       seqCacheKey * key = (seqCacheKey*) key_;
+       unsigned int rval = key->rectx + key->recty;
+
+       rval ^= *(unsigned int*) &key->cfra;
+       rval += key->type;
+       rval ^= ((unsigned int) key->seq) << 6;
+
+       return rval;
+}
+
+static int HashCmp(void *a_, void *b_)
+{
+       seqCacheKey * a = (seqCacheKey*) a_;
+       seqCacheKey * b = (seqCacheKey*) b_;
+
+       if (a->seq < b->seq) {
+               return -1;              
+       }
+       if (a->seq > b->seq) {
+               return 1;
+       }
+
+       if (a->cfra < b->cfra) {
+               return -1;
+       }
+       if (a->cfra > b->cfra) {
+               return 1;
+       }
+
+       if (a->type < b->type) {
+               return -1;
+       }
+       if (a->type > b->type) {
+               return 1;
+       }
+
+       if (a->rectx < b->rectx) {
+               return -1;
+       }
+       if (a->rectx > b->rectx) {
+               return 1;
+       }
+
+       if (a->recty < b->recty) {
+               return -1;
+       }
+       if (a->recty > b->recty) {
+               return 1;
+       }
+
+       return 0;
+}
+
+static void HashKeyFree(void *key)
+{
+       BLI_mempool_free(keypool, key);
+}
+
+static void HashValFree(void *val)
+{
+       seqCacheEntry* e = (seqCacheEntry*) val;
+
+       if (e->ibuf) {
+               /* fprintf(stderr, "Removing: %p, cnt: %d\n", e->ibuf, 
+                  e->ibuf->refcounter); */
+               IMB_freeImBuf(e->ibuf);
+               MEM_CacheLimiter_unmanage(e->c_handle);
+               ibufs_rem++;
+       }
+
+       e->ibuf = 0;
+       e->c_handle = 0;
+
+       BLI_mempool_free(entrypool, e);
+}
+
+static void IMB_seq_cache_destructor(void * p)
+{
+       seqCacheEntry* e = (seqCacheEntry*) p;
+       
+       if (e && e->ibuf) {
+               /* fprintf(stderr, "Removing: %p, cnt: %d\n", e->ibuf,
+                  e->ibuf->refcounter); */
+               IMB_freeImBuf(e->ibuf);
+               ibufs_rem++;
+
+               e->ibuf = 0;
+               e->c_handle = 0;
+       }
+}
+
+void seq_stripelem_cache_init()
+{
+       hash = BLI_ghash_new(HashHash, HashCmp, "seq stripelem cache hash");
+       limitor = new_MEM_CacheLimiter( IMB_seq_cache_destructor );
+
+       entrypool = BLI_mempool_create(sizeof(seqCacheEntry), 64, 64, 0);
+       keypool = BLI_mempool_create(sizeof(seqCacheKey), 64, 64, 0);
+}
+
+void seq_stripelem_cache_destruct()
+{
+       if (!entrypool) {
+               return;
+       }
+       BLI_ghash_free(hash, HashKeyFree, HashValFree);
+       delete_MEM_CacheLimiter(limitor);
+       BLI_mempool_destroy(entrypool);
+       BLI_mempool_destroy(keypool);
+}
+
+void seq_stripelem_cache_cleanup()
+{
+       if (!entrypool) {
+               seq_stripelem_cache_init();
+       }
+
+       /* fprintf(stderr, "Stats before cleanup: in: %d rem: %d\n",
+          ibufs_in, ibufs_rem); */
+
+       BLI_ghash_free(hash, HashKeyFree, HashValFree);
+       hash = BLI_ghash_new(HashHash, HashCmp, "seq stripelem cache hash");
+
+       /* fprintf(stderr, "Stats after cleanup: in: %d rem: %d\n",
+          ibufs_in, ibufs_rem); */
+
+}
+
+struct ImBuf * seq_stripelem_cache_get(
+       struct Sequence * seq, int rectx, int recty, 
+       float cfra, seq_stripelem_ibuf_t type)
+{
+       seqCacheKey key;
+       seqCacheEntry * e;
+
+       if (!seq) {
+               return 0;
+       }
+
+       if (!entrypool) {
+               seq_stripelem_cache_init();
+       }
+
+       key.seq = seq;
+       key.rectx = rectx;
+       key.recty = recty;
+       key.cfra = cfra - seq->start;
+       key.type = type;
+       
+       e = (seqCacheEntry*) BLI_ghash_lookup(hash, &key);
+
+       if (e && e->ibuf) {
+               IMB_refImBuf(e->ibuf);
+
+               MEM_CacheLimiter_touch(e->c_handle);
+               return e->ibuf;
+       }
+       return 0;
+}
+
+void seq_stripelem_cache_put(
+       struct Sequence * seq, int rectx, int recty, 
+       float cfra, seq_stripelem_ibuf_t type, struct ImBuf * i)
+{
+       seqCacheKey * key;
+       seqCacheEntry * e;
+
+       if (!i) {
+               return;
+       }
+
+       ibufs_in++;
+
+       if (!entrypool) {
+               seq_stripelem_cache_init();
+       }
+
+       key = (seqCacheKey*) BLI_mempool_alloc(keypool);
+
+       key->seq = seq;
+       key->rectx = rectx;
+       key->recty = recty;
+       key->cfra = cfra - seq->start;
+       key->type = type;
+
+       /* we want our own version */
+       IMB_refImBuf(i);
+
+       e = (seqCacheEntry*) BLI_mempool_alloc(entrypool);
+
+       e->ibuf = i;
+       e->c_handle = 0;
+
+       BLI_ghash_remove(hash, key, HashKeyFree, HashValFree);
+       BLI_ghash_insert(hash, key, e);
+
+       e->c_handle = MEM_CacheLimiter_insert(limitor, e);
+
+       MEM_CacheLimiter_ref(e->c_handle);
+       MEM_CacheLimiter_enforce_limits(limitor);
+       MEM_CacheLimiter_unref(e->c_handle);
+}
index 73c19772c695bddbcaf6a2242e4b83a739ef9c64..151fc1c407c8b234f7597211e8600cae56135ac0 100644 (file)
@@ -827,7 +827,7 @@ static void makeGammaTables(float gamma)
 
        /* The end of the table should match 1.0 carefully. In order to avoid    */
        /* rounding errors, we just set this explicitly. The last segment may    */
-       /* have a different lenght than the other segments, but our              */
+       /* have a different length than the other segments, but our              */
        /* interpolation is insensitive to that.                                 */
        color_domain_table[RE_GAMMA_TABLE_SIZE]   = 1.0;
        gamma_range_table[RE_GAMMA_TABLE_SIZE]     = 1.0;
@@ -2786,6 +2786,7 @@ static void do_multicam(Scene *scene, Sequence *seq, int cfra,
                IMB_float_from_rect_simple(i);
                memcpy(out->rect_float, i->rect_float, out->x * out->y *4*sizeof(float));
        }
+       IMB_freeImBuf(i);
 }
 
 /* **********************************************************************
index 94aa2c62f1abfc0410c41f9614d6e765b8b291da..bbc50490ab70cbf043dbc5c2f3e55ee2afad4202 100644 (file)
@@ -55,6 +55,7 @@
 #include "BLI_listbase.h"
 #include "BLI_path_util.h"
 #include "BLI_string.h"
+#include "BLI_threads.h"
 #include <pthread.h>
 
 #include "IMB_imbuf.h"
@@ -115,53 +116,11 @@ int seq_recursive_apply(Sequence *seq, int (*apply_func)(Sequence *, void *), vo
    alloc / free functions
    ********************************************************************** */
 
-static void free_tstripdata(int len, TStripElem *se)
-{
-       TStripElem *seo;
-       int a;
-
-       seo= se;
-       if (!se)
-               return;
-
-       for(a=0; a<len; a++, se++) {
-               if(se->ibuf) {
-                       IMB_freeImBuf(se->ibuf);
-                       se->ibuf = 0;
-               }
-               if(se->ibuf_comp) {
-                       IMB_freeImBuf(se->ibuf_comp);
-                       se->ibuf_comp = 0;
-               }
-       }
-
-       MEM_freeN(seo);
-}
 
 
 void new_tstripdata(Sequence *seq)
 {
        if(seq->strip) {
-               free_tstripdata(seq->strip->len, seq->strip->tstripdata);
-               free_tstripdata(seq->strip->endstill, 
-                               seq->strip->tstripdata_endstill);
-               free_tstripdata(seq->strip->startstill, 
-                               seq->strip->tstripdata_startstill);
-
-               seq->strip->tstripdata= 0;
-               seq->strip->tstripdata_endstill= 0;
-               seq->strip->tstripdata_startstill= 0;
-
-               if(seq->strip->ibuf_startstill) {
-                       IMB_freeImBuf(seq->strip->ibuf_startstill);
-                       seq->strip->ibuf_startstill = 0;
-               }
-
-               if(seq->strip->ibuf_endstill) {
-                       IMB_freeImBuf(seq->strip->ibuf_endstill);
-                       seq->strip->ibuf_endstill = 0;
-               }
-
                seq->strip->len= seq->len;
        }
 }
@@ -207,20 +166,6 @@ void seq_free_strip(Strip *strip)
                MEM_freeN(strip->color_balance);
        }
 
-       free_tstripdata(strip->len, strip->tstripdata);
-       free_tstripdata(strip->endstill, strip->tstripdata_endstill);
-       free_tstripdata(strip->startstill, strip->tstripdata_startstill);
-
-       if(strip->ibuf_startstill) {
-               IMB_freeImBuf(strip->ibuf_startstill);
-               strip->ibuf_startstill = 0;
-       }
-
-       if(strip->ibuf_endstill) {
-               IMB_freeImBuf(strip->ibuf_endstill);
-               strip->ibuf_endstill = 0;
-       }
-
        MEM_freeN(strip);
 }
 
@@ -949,137 +894,9 @@ static void multibuf(ImBuf *ibuf, float fmul)
        }
 }
 
-static void do_effect(Scene *scene, int cfra, Sequence *seq, TStripElem * se,
-                     int render_size)
-{
-       TStripElem *se1, *se2, *se3;
-       float fac, facf;
-       int x, y;
-       int early_out;
-       struct SeqEffectHandle sh = get_sequence_effect(seq);
-       FCurve *fcu= NULL;
-
-       if (!sh.execute) { /* effect not supported in this version... */
-               make_black_ibuf(se->ibuf);
-               return;
-       }
-
-       if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) {
-               sh.get_default_fac(seq, cfra, &fac, &facf);
-               if( scene->r.mode & R_FIELDS ); else facf= fac;
-       } else {
-               fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, 
-                                         "effect_fader", 0);
-               if (fcu) {
-                       fac = facf = evaluate_fcurve(fcu, cfra);
-                       if( scene->r.mode & R_FIELDS ) {
-                               facf = evaluate_fcurve(fcu, cfra + 0.5);
-                       }
-               } else {
-                       fac = facf = seq->effect_fader;
-               }
-       }
-
-       early_out = sh.early_out(seq, fac, facf);
-
-       if (early_out == -1) { /* no input needed */
-               sh.execute(scene, seq, cfra, fac, facf, 
-                          se->ibuf->x, se->ibuf->y, render_size,
-                          0, 0, 0, se->ibuf);
-               return;
-       }
-
-       switch (early_out) {
-       case 0:
-               if (se->se1==0 || se->se2==0 || se->se3==0) {
-                       make_black_ibuf(se->ibuf);
-                       return;
-               }
-
-               se1= se->se1;
-               se2= se->se2;
-               se3= se->se3;
-
-               if (   (se1==0 || se2==0 || se3==0)
-                       || (se1->ibuf==0 || se2->ibuf==0 || se3->ibuf==0)) {
-                       make_black_ibuf(se->ibuf);
-                       return;
-               }
-
-               break;
-       case 1:
-               if (se->se1 == 0) {
-                       make_black_ibuf(se->ibuf);
-                       return;
-               }
-
-               se1= se->se1;
-
-               if (se1 == 0 || se1->ibuf == 0) {
-                       make_black_ibuf(se->ibuf);
-                       return;
-               }
-
-               if (se->ibuf != se1->ibuf) {
-                       IMB_freeImBuf(se->ibuf);
-                       se->ibuf = se1->ibuf;
-                       IMB_refImBuf(se->ibuf);
-               }
-               return;
-       case 2:
-               if (se->se2 == 0) {
-                       make_black_ibuf(se->ibuf);
-                       return;
-               }
-
-               se2= se->se2;
-
-               if (se2 == 0 || se2->ibuf == 0) {
-                       make_black_ibuf(se->ibuf);
-                       return;
-               }
-               if (se->ibuf != se2->ibuf) {
-                       IMB_freeImBuf(se->ibuf);
-                       se->ibuf = se2->ibuf;
-                       IMB_refImBuf(se->ibuf);
-               }
-               return;
-       default:
-               make_black_ibuf(se->ibuf);
-               return;
-       }
-
-       x= se2->ibuf->x;
-       y= se2->ibuf->y;
-
-       if (!se1->ibuf->rect_float && se->ibuf->rect_float) {
-               IMB_float_from_rect_simple(se1->ibuf);
-       }
-       if (!se2->ibuf->rect_float && se->ibuf->rect_float) {
-               IMB_float_from_rect_simple(se2->ibuf);
-       }
-       if (!se3->ibuf->rect_float && se->ibuf->rect_float) {
-               IMB_float_from_rect_simple(se3->ibuf);
-       }
-       
-       if (!se1->ibuf->rect && !se->ibuf->rect_float) {
-               IMB_rect_from_float(se1->ibuf);
-       }
-       if (!se2->ibuf->rect && !se->ibuf->rect_float) {
-               IMB_rect_from_float(se2->ibuf);
-       }
-       if (!se3->ibuf->rect && !se->ibuf->rect_float) {
-               IMB_rect_from_float(se3->ibuf);
-       }
-
-       sh.execute(scene, seq, cfra, fac, facf, x, y, render_size,
-                  se1->ibuf, se2->ibuf, se3->ibuf,
-                  se->ibuf);
-}
-
-static int give_stripelem_index(Sequence *seq, int cfra)
+static float give_stripelem_index(Sequence *seq, float cfra)
 {
-       int nr;
+       float nr;
 
        if(seq->startdisp >cfra || seq->enddisp <= cfra) return -1;
        if(seq->len == 0) return -1;
@@ -1095,93 +912,12 @@ static int give_stripelem_index(Sequence *seq, int cfra)
        }
        if (seq->strobe < 1.0) seq->strobe = 1.0;
        if (seq->strobe > 1.0) {
-               nr -= (int)fmod((double)nr, (double)seq->strobe);
+               nr -= fmod((double)nr, (double)seq->strobe);
        }
 
        return nr;
 }
 
-static TStripElem* alloc_tstripdata(int len, const char * name)
-{
-       int i;
-       TStripElem *se = MEM_callocN(len * sizeof(TStripElem), name);
-       for (i = 0; i < len; i++) {
-               se[i].ok = STRIPELEM_OK;
-       }
-       return se;
-}
-
-static TStripElem *give_tstripelem(Sequence *seq, int cfra)
-{
-       TStripElem *se;
-       int nr;
-
-       se = seq->strip->tstripdata;
-       if (se == 0 && seq->len > 0) {
-               se = seq->strip->tstripdata = alloc_tstripdata(seq->len,
-                                                                  "tstripelems");
-       }
-       nr = give_stripelem_index(seq, cfra);
-
-       if (nr == -1) return 0;
-       if (se == 0) return 0;
-
-       se += nr; 
-
-       /* if there are IPOs with blend modes active, one has to watch out
-          for startstill + endstill area: we can't use the same tstripelem
-          here for all ibufs, since then, blending with IPOs won't work!
-          
-          Rather common case, if you use a single image and try to fade
-          it in and out... or want to use your strip as a watermark in
-          alpha over mode...
-       */
-       if (seq->blend_mode != SEQ_BLEND_REPLACE ||
-               (/*seq->ipo && seq->ipo->curve.first &&*/ 
-                  (!(seq->type & SEQ_EFFECT) || !seq->seq1))) {
-               Strip * s = seq->strip;
-               if (cfra < seq->start) {
-                       se = s->tstripdata_startstill;
-                       if (seq->startstill != s->startstill) {
-                               free_tstripdata(s->startstill, 
-                                               s->tstripdata_startstill);
-                               se = 0;
-                       }
-
-                       if (se == 0) {
-                               s->startstill = seq->startstill;
-                               se = seq->strip->tstripdata_startstill
-                                       = alloc_tstripdata(
-                                               s->startstill,
-                                               "tstripelems_startstill");
-                       }
-                       se += seq->start - cfra - 1;
-
-               } else if (cfra > seq->start + seq->len-1) {
-                       se = s->tstripdata_endstill;
-                       if (seq->endstill != s->endstill) {
-                               free_tstripdata(s->endstill, 
-                                               s->tstripdata_endstill);
-                               se = 0;
-                       }
-
-                       if (se == 0) {
-                               s->endstill = seq->endstill;
-                               se = seq->strip->tstripdata_endstill
-                                       = alloc_tstripdata(
-                                               s->endstill,
-                                               "tstripelems_endstill");
-                       }
-                       se += cfra - (seq->start + seq->len-1) - 1;
-               }
-       }
-
-       
-       se->nr= nr;
-
-       return se;
-}
-
 StripElem *give_stripelem(Sequence *seq, int cfra)
 {
        StripElem *se= seq->strip->stripdata;
@@ -1190,7 +926,7 @@ StripElem *give_stripelem(Sequence *seq, int cfra)
                /* use the first */
        }
        else {
-               int nr = give_stripelem_index(seq, cfra);
+               int nr = (int) give_stripelem_index(seq, cfra);
 
                if (nr == -1) return 0;
                if (se == 0) return 0;
@@ -1321,17 +1057,15 @@ static int seq_proxy_get_fname(Scene *scene, Sequence * seq, int cfra, char * na
                         dir, render_size, se->name);
                frameno = 1;
        } else if (seq->type == SEQ_MOVIE) {
-               TStripElem * tse = give_tstripelem(seq, cfra);
-
-               frameno = tse->nr + seq->anim_startofs;
+               frameno = (int) give_stripelem_index(seq, cfra) 
+                       + seq->anim_startofs;
 
                snprintf(name, PROXY_MAXFILE, "%s/%s/%d/####", dir,
                         seq->strip->stripdata->name,
                         render_size);
        } else {
-               TStripElem * tse = give_tstripelem(seq, cfra);
-
-               frameno = tse->nr + seq->anim_startofs;
+               frameno = (int) give_stripelem_index(seq, cfra) 
+                       + seq->anim_startofs;
 
                snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####", dir,
                         render_size);
@@ -1360,10 +1094,11 @@ static struct ImBuf * seq_proxy_fetch(Scene *scene, Sequence * seq, int cfra, in
        }
 
        if (seq->flag & SEQ_USE_PROXY_CUSTOM_FILE) {
-               TStripElem * tse = give_tstripelem(seq, cfra);
-               int frameno = tse->nr + seq->anim_startofs;
+               int frameno = (int) give_stripelem_index(seq, cfra) 
+                       + seq->anim_startofs;
                if (!seq->strip->proxy->anim) {
-                       if (!seq_proxy_get_fname(scene, seq, cfra, name, render_size)) {
+                       if (!seq_proxy_get_fname(
+                                   scene, seq, cfra, name, render_size)) {
                                return 0;
                        }
  
@@ -1606,12 +1341,12 @@ static void make_cb_table_float(float lift, float gain, float gamma,
        }
 }
 
-static void color_balance_byte_byte(Sequence * seq, TStripElem* se, float mul)
+static void color_balance_byte_byte(Sequence * seq, ImBuf* ibuf, float mul)
 {
        unsigned char cb_tab[3][256];
        int c;
-       unsigned char * p = (unsigned char*) se->ibuf->rect;
-       unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y;
+       unsigned char * p = (unsigned char*) ibuf->rect;
+       unsigned char * e = p + ibuf->x * 4 * ibuf->y;
 
        StripColorBalance cb = calc_cb(seq->strip->color_balance);
 
@@ -1629,24 +1364,24 @@ static void color_balance_byte_byte(Sequence * seq, TStripElem* se, float mul)
        }
 }
 
-static void color_balance_byte_float(Sequence * seq, TStripElem* se, float mul)
+static void color_balance_byte_float(Sequence * seq, ImBuf* ibuf, float mul)
 {
        float cb_tab[4][256];
        int c,i;
-       unsigned char * p = (unsigned char*) se->ibuf->rect;
-       unsigned char * e = p + se->ibuf->x * 4 * se->ibuf->y;
+       unsigned char * p = (unsigned char*) ibuf->rect;
+       unsigned char * e = p + ibuf->x * 4 * ibuf->y;
        float * o;
        StripColorBalance cb;
 
-       imb_addrectfloatImBuf(se->ibuf);
+       imb_addrectfloatImBuf(ibuf);
 
-       o = se->ibuf->rect_float;
+       o = ibuf->rect_float;
 
        cb = calc_cb(seq->strip->color_balance);
 
        for (c = 0; c < 3; c++) {
                make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c],
-                                       cb_tab[c], mul);
+                                   cb_tab[c], mul);
        }
 
        for (i = 0; i < 256; i++) {
@@ -1663,10 +1398,10 @@ static void color_balance_byte_float(Sequence * seq, TStripElem* se, float mul)
        }
 }
 
-static void color_balance_float_float(Sequence * seq, TStripElem* se, float mul)
+static void color_balance_float_float(Sequence * seq, ImBuf* ibuf, float mul)
 {
-       float * p = se->ibuf->rect_float;
-       float * e = se->ibuf->rect_float + se->ibuf->x * 4* se->ibuf->y;
+       float * p = ibuf->rect_float;
+       float * e = ibuf->rect_float + ibuf->x * 4* ibuf->y;
        StripColorBalance cb = calc_cb(seq->strip->color_balance);
 
        while (p < e) {
@@ -1678,14 +1413,14 @@ static void color_balance_float_float(Sequence * seq, TStripElem* se, float mul)
        }
 }
 
-static void color_balance(Sequence * seq, TStripElem* se, float mul)
+static void color_balance(Sequence * seq, ImBuf* ibuf, float mul)
 {
-       if (se->ibuf->rect_float) {
-               color_balance_float_float(seq, se, mul);
+       if (ibuf->rect_float) {
+               color_balance_float_float(seq, ibuf, mul);
        } else if(seq->flag & SEQ_MAKE_FLOAT) {
-               color_balance_byte_float(seq, se, mul);
+               color_balance_byte_float(seq, ibuf, mul);
        } else {
-               color_balance_byte_byte(seq, se, mul);
+               color_balance_byte_byte(seq, ibuf, mul);
        }
 }
 
@@ -1708,18 +1443,18 @@ static void color_balance(Sequence * seq, TStripElem* se, float mul)
 
 */
 
-static int input_have_to_preprocess(Scene *scene, Sequence * seq, TStripElem* se, int cfra, int seqrectx, int seqrecty)
+static int input_have_to_preprocess(
+       Scene *scene, Sequence * seq, float cfra, int seqrectx, int seqrecty)
 {
        float mul;
 
        if ((seq->flag & SEQ_FILTERY) || 
-               (seq->flag & SEQ_USE_CROP) ||
-               (seq->flag & SEQ_USE_TRANSFORM) ||
-               (seq->flag & SEQ_FLIPX) ||
-               (seq->flag & SEQ_FLIPY) ||
-               (seq->flag & SEQ_USE_COLOR_BALANCE) ||
-               (seq->flag & SEQ_MAKE_PREMUL) ||
-               (se->ibuf->x != seqrectx || se->ibuf->y != seqrecty)) {
+           (seq->flag & SEQ_USE_CROP) ||
+           (seq->flag & SEQ_USE_TRANSFORM) ||
+           (seq->flag & SEQ_FLIPX) ||
+           (seq->flag & SEQ_FLIPY) ||
+           (seq->flag & SEQ_USE_COLOR_BALANCE) ||
+           (seq->flag & SEQ_MAKE_PREMUL)) {
                return TRUE;
        }
 
@@ -1733,19 +1468,25 @@ static int input_have_to_preprocess(Scene *scene, Sequence * seq, TStripElem* se
        if (mul != 1.0) {
                return TRUE;
        }
+
+       if (seq->sat != 1.0) {
+               return TRUE;
+       }
                
        return FALSE;
 }
 
-static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cfra, int seqrectx, int seqrecty)
+static ImBuf * input_preprocess(
+       Scene *scene, Sequence *seq, float cfra, int seqrectx, int seqrecty,
+       ImBuf * ibuf)
 {
        float mul;
 
-       seq->strip->orx= se->ibuf->x;
-       seq->strip->ory= se->ibuf->y;
+       seq->strip->orx= ibuf->x;
+       seq->strip->ory= ibuf->y;
 
        if((seq->flag & SEQ_FILTERY) && seq->type != SEQ_MOVIE) {
-               IMB_filtery(se->ibuf);
+               IMB_filtery(ibuf);
        }
 
        if(seq->flag & SEQ_USE_CROP || seq->flag & SEQ_USE_TRANSFORM) {
@@ -1763,8 +1504,8 @@ static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cf
                        t = *seq->strip->transform;
                }
 
-               sx = se->ibuf->x - c.left - c.right;
-               sy = se->ibuf->y - c.top - c.bottom;
+               sx = ibuf->x - c.left - c.right;
+               sy = ibuf->y - c.top - c.bottom;
                dx = sx;
                dy = sy;
 
@@ -1773,49 +1514,49 @@ static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cf
                        dy = scene->r.ysch;
                }
 
-               if (c.top + c.bottom >= se->ibuf->y ||
-                       c.left + c.right >= se->ibuf->x ||
+               if (c.top + c.bottom >= ibuf->y ||
+                       c.left + c.right >= ibuf->x ||
                        t.xofs >= dx || t.yofs >= dy) {
-                       make_black_ibuf(se->ibuf);
+                       make_black_ibuf(ibuf);
                } else {
                        ImBuf * i;
 
-                       if (se->ibuf->rect_float) {
+                       if (ibuf->rect_float) {
                                i = IMB_allocImBuf(dx, dy,32, IB_rectfloat, 0);
                        } else {
                                i = IMB_allocImBuf(dx, dy,32, IB_rect, 0);
                        }
 
-                       IMB_rectcpy(i, se->ibuf, 
-                                       t.xofs, t.yofs, 
-                                       c.left, c.bottom, 
-                                       sx, sy);
-
-                       IMB_freeImBuf(se->ibuf);
+                       IMB_rectcpy(i, ibuf, 
+                                   t.xofs, t.yofs, 
+                                   c.left, c.bottom, 
+                                   sx, sy);
+                       
+                       IMB_freeImBuf(ibuf);
 
-                       se->ibuf = i;
+                       ibuf = i;
                }
        } 
 
        if(seq->flag & SEQ_FLIPX) {
-               IMB_flipx(se->ibuf);
+               IMB_flipx(ibuf);
        }
        
        if(seq->flag & SEQ_FLIPY) {
-               IMB_flipy(se->ibuf);
+               IMB_flipy(ibuf);
        }
 
        if(seq->sat != 1.0f) {
                /* inline for now, could become an imbuf function */
                int i;
-               char *rct= (char *)se->ibuf->rect;
-               float *rctf= se->ibuf->rect_float;
+               char *rct= (char *)ibuf->rect;
+               float *rctf= ibuf->rect_float;
                const float sat= seq->sat;
                float hsv[3];
 
                if(rct) {
                        float rgb[3];
-                       for (i = se->ibuf->x * se->ibuf->y; i > 0; i--, rct+=4) {
+                       for (i = ibuf->x * ibuf->y; i > 0; i--, rct+=4) {
                                rgb_byte_to_float(rct, rgb);
                                rgb_to_hsv(rgb[0], rgb[1], rgb[2], hsv, hsv+1, hsv+2);
                                hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rgb, rgb+1, rgb+2);
@@ -1824,7 +1565,7 @@ static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cf
                }
 
                if(rctf) {
-                       for (i = se->ibuf->x * se->ibuf->y; i > 0; i--, rctf+=4) {
+                       for (i = ibuf->x * ibuf->y; i > 0; i--, rctf+=4) {
                                rgb_to_hsv(rctf[0], rctf[1], rctf[2], hsv, hsv+1, hsv+2);
                                hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rctf, rctf+1, rctf+2);
                        }
@@ -1838,725 +1579,548 @@ static void input_preprocess(Scene *scene, Sequence *seq, TStripElem *se, int cf
        }
 
        if(seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) {
-               color_balance(seq, se, mul);
+               color_balance(seq, ibuf, mul);
                mul = 1.0;
        }
 
        if(seq->flag & SEQ_MAKE_FLOAT) {
-               if (!se->ibuf->rect_float)
-                       IMB_float_from_rect_simple(se->ibuf);
+               if (!ibuf->rect_float)
+                       IMB_float_from_rect_simple(ibuf);
 
-               if (se->ibuf->rect) {
-                       imb_freerectImBuf(se->ibuf);
+               if (ibuf->rect) {
+                       imb_freerectImBuf(ibuf);
                }
        }
 
        if(mul != 1.0) {
-               multibuf(se->ibuf, mul);
+               multibuf(ibuf, mul);
        }
 
        if(seq->flag & SEQ_MAKE_PREMUL) {
-               if(se->ibuf->depth == 32 && se->ibuf->zbuf == 0) {
-                       IMB_premultiply_alpha(se->ibuf);
+               if(ibuf->depth == 32 && ibuf->zbuf == 0) {
+                       IMB_premultiply_alpha(ibuf);
                }
        }
 
 
-       if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty ) {
+       if(ibuf->x != seqrectx || ibuf->y != seqrecty ) {
                if(scene->r.mode & R_OSA) {
-                       IMB_scaleImBuf(se->ibuf, 
-                                          (short)seqrectx, (short)seqrecty);
+                       IMB_scaleImBuf(ibuf, 
+                                      (short)seqrectx, (short)seqrecty);
                } else {
-                       IMB_scalefastImBuf(se->ibuf, 
+                       IMB_scalefastImBuf(ibuf, 
                                           (short)seqrectx, (short)seqrecty);
                }
        }
+       return ibuf;
 }
 
-/* test if image too small or discarded from cache: reload */
-
-static void test_and_auto_discard_ibuf(TStripElem * se, 
-                                      int seqrectx, int seqrecty)
+static ImBuf * copy_from_ibuf_still(Sequence * seq, float nr,
+                                   int seqrectx, int seqrecty)
 {
-       if (se->ibuf) {
-               if(se->ibuf->x != seqrectx || se->ibuf->y != seqrecty 
-                  || !(se->ibuf->rect || se->ibuf->rect_float)) {
-                       IMB_freeImBuf(se->ibuf);
+       ImBuf * rval = 0;
+       ImBuf * ibuf = 0;
 
-                       se->ibuf= 0;
-                       se->ok= STRIPELEM_OK;
-               }
+       if (nr == 0) {
+               ibuf = seq_stripelem_cache_get(
+                       seq, seqrectx, seqrecty, seq->start, 
+                       SEQ_STRIPELEM_IBUF_STARTSTILL);
+       }
+       if (nr == seq->len - 1) {
+               ibuf = seq_stripelem_cache_get(
+                       seq, seqrectx, seqrecty, seq->start, 
+                       SEQ_STRIPELEM_IBUF_ENDSTILL);
        }
-       if (se->ibuf_comp) {
-               if(se->ibuf_comp->x != seqrectx || se->ibuf_comp->y != seqrecty 
-                  || !(se->ibuf_comp->rect || se->ibuf_comp->rect_float)) {
-                       IMB_freeImBuf(se->ibuf_comp);
 
-                       se->ibuf_comp = 0;
-               }
+       if (ibuf) {
+               rval = IMB_dupImBuf(ibuf);
+               IMB_freeImBuf(ibuf);
        }
+
+       return rval;
 }
 
-static void test_and_auto_discard_ibuf_stills(Strip * strip)
+static void copy_to_ibuf_still(Sequence * seq, float nr,
+                              ImBuf * ibuf)
 {
-       if (strip->ibuf_startstill) {
-               if (!strip->ibuf_startstill->rect &&
-                       !strip->ibuf_startstill->rect_float) {
-                       IMB_freeImBuf(strip->ibuf_startstill);
-                       strip->ibuf_startstill = 0;
-               }
+       if (nr == 0) {
+               seq_stripelem_cache_put(
+                       seq, 0, 0, seq->start, 
+                       SEQ_STRIPELEM_IBUF_STARTSTILL, ibuf);
        }
-       if (strip->ibuf_endstill) {
-               if (!strip->ibuf_endstill->rect &&
-                       !strip->ibuf_endstill->rect_float) {
-                       IMB_freeImBuf(strip->ibuf_endstill);
-                       strip->ibuf_endstill = 0;
-               }
+       if (nr == seq->len - 1) {
+               seq_stripelem_cache_put(
+                       seq, 0, 0, seq->start, 
+                       SEQ_STRIPELEM_IBUF_ENDSTILL, ibuf);
        }
 }
 
-static void copy_from_ibuf_still(Sequence * seq, TStripElem * se)
-{
-       if (!se->ibuf) {
-               if (se->nr == 0 && seq->strip->ibuf_startstill) {
-                       IMB_cache_limiter_touch(seq->strip->ibuf_startstill);
+/* **********************************************************************
+   strip rendering functions
+   ********************************************************************** */
 
-                       se->ibuf = IMB_dupImBuf(seq->strip->ibuf_startstill);
-               }
-               if (se->nr == seq->len - 1 
-                       && (seq->len != 1)
-                       && seq->strip->ibuf_endstill) {
-                       IMB_cache_limiter_touch(seq->strip->ibuf_endstill);
+static ImBuf* seq_render_strip_stack(
+       Scene *scene,
+       ListBase *seqbasep, float cfra, int chanshown, int render_size,
+       int seqrectx, int seqrecty);
+
+static ImBuf * seq_render_strip(Scene *scene, Sequence * seq, float cfra,
+                               int render_size, 
+                               int seqrectx, int seqrecty);
 
-                       se->ibuf = IMB_dupImBuf(seq->strip->ibuf_endstill);
-               }
-       }
-}
 
-static void copy_to_ibuf_still(Sequence * seq, TStripElem * se)
+static ImBuf* seq_render_effect_strip_impl(
+       Scene *scene, float cfra, Sequence *seq, int render_size,
+       int seqrectx, int seqrecty)
 {
-       if (se->ibuf) {
-               if (se->nr == 0) {
-                       seq->strip->ibuf_startstill = IMB_dupImBuf(se->ibuf);
+       float fac, facf;
+       int early_out;
+       int i;
+       int must_preprocess = FALSE;
 
-                       IMB_cache_limiter_insert(seq->strip->ibuf_startstill);
-                       IMB_cache_limiter_touch(seq->strip->ibuf_startstill);
-               }
-               if (se->nr == seq->len - 1 && seq->len != 1) {
-                       seq->strip->ibuf_endstill = IMB_dupImBuf(se->ibuf);
+       struct SeqEffectHandle sh = get_sequence_effect(seq);
+       FCurve *fcu= NULL;
+       ImBuf * ibuf[3];
+       ImBuf * out = 0;
+
+       ibuf[0] = ibuf[1] = ibuf[2] = 0;
+
+       if (!sh.execute) { /* effect not supported in this version... */
+               goto finish;
+       }
 
-                       IMB_cache_limiter_insert(seq->strip->ibuf_endstill);
-                       IMB_cache_limiter_touch(seq->strip->ibuf_endstill);
+       if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) {
+               sh.get_default_fac(seq, cfra, &fac, &facf);
+               if( scene->r.mode & R_FIELDS ); else facf= fac;
+       } else {
+               fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, 
+                                         "effect_fader", 0);
+               if (fcu) {
+                       fac = facf = evaluate_fcurve(fcu, cfra);
+                       if( scene->r.mode & R_FIELDS ) {
+                               facf = evaluate_fcurve(fcu, cfra + 0.5);
+                       }
+               } else {
+                       fac = facf = seq->effect_fader;
                }
        }
-}
 
-static void free_metastrip_imbufs(ListBase *seqbasep, int cfra, int chanshown)
-{
-       Sequence* seq_arr[MAXSEQ+1];
-       int i;
-       TStripElem* se = 0;
+       early_out = sh.early_out(seq, fac, facf);
 
-       evaluate_seq_frame_gen(seq_arr, seqbasep, cfra);
+       if (early_out == -1) { /* no input needed */
+               /* hmmm, global float option ? */
+               out = IMB_allocImBuf(
+                       (short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
 
-       for (i = 0; i < MAXSEQ; i++) {
-               if (!video_seq_is_rendered(seq_arr[i])) {
-                       continue;
-               }
-               se = give_tstripelem(seq_arr[i], cfra);
-               if (se) {
-                       if (se->ibuf) {
-                               IMB_freeImBuf(se->ibuf);
+               sh.execute(scene, seq, cfra, fac, facf, 
+                          out->x, out->y, render_size,
+                          0, 0, 0, out);
+               goto finish;
+       }
 
-                               se->ibuf= 0;
-                               se->ok= STRIPELEM_OK;
-                       }
 
-                       if (se->ibuf_comp) {
-                               IMB_freeImBuf(se->ibuf_comp);
+       must_preprocess = input_have_to_preprocess(
+               scene, seq, cfra, seqrectx, seqrecty);
 
-                               se->ibuf_comp = 0;
-                       }
+       switch (early_out) {
+       case 0:
+               break;
+       case 1:
+               if (seq->seq1) {
+                       ibuf[0] = seq_render_strip(scene, seq->seq1, cfra,
+                                                  render_size, 
+                                                  seqrectx, seqrecty);
                }
-       }
-       
-}
-
-static void check_limiter_refcount(const char * func, TStripElem *se)
-{
-       if (se && se->ibuf) {
-               int refcount = IMB_cache_limiter_get_refcount(se->ibuf);
-               if (refcount != 1) {
-                       /* can happen on complex pipelines */
-                       if (refcount > 1 && (G.f & G_DEBUG) == 0) {
-                               return;
+               if (ibuf[0]) {
+                       if (must_preprocess) {
+                               out = IMB_dupImBuf(ibuf[0]);
+                       } else {
+                               out = ibuf[0];
+                               IMB_refImBuf(out);
                        }
-                       fprintf(stderr, 
-                               "sequencer: (ibuf) %s: "
-                               "suspicious memcache "
-                               "limiter refcount: %d\n", func, refcount);
                }
-       }
-}
-static void check_limiter_refcount_comp(const char * func, TStripElem *se)
-{
-       if (se && se->ibuf_comp) {
-               int refcount = IMB_cache_limiter_get_refcount(se->ibuf_comp);
-               if (refcount != 1) {
-                       /* can happen on complex pipelines */
-                       if (refcount > 1 && (G.f & G_DEBUG) == 0) {
-                               return;
+               goto finish;
+       case 2:
+               if (seq->seq2) {
+                       ibuf[1] = seq_render_strip(scene, seq->seq2, cfra,
+                                                  render_size, 
+                                                  seqrectx, seqrecty);
+               }
+               if (ibuf[1]) {
+                       if (must_preprocess) {
+                               out = IMB_dupImBuf(ibuf[1]);
+                       } else {
+                               out = ibuf[1];
+                               IMB_refImBuf(out);
                        }
-                       fprintf(stderr, 
-                               "sequencer: (ibuf comp) %s: "
-                               "suspicious memcache "
-                               "limiter refcount: %d\n", func, refcount);
                }
+               goto finish;
+       default:
+               goto finish;
        }
-}
 
-static TStripElem* do_build_seq_array_recursively(
-       Scene *scene,
-       ListBase *seqbasep, int cfra, int chanshown, int render_size,
-       int seqrectx, int seqrecty);
+       if (seq->seq1) {
+               ibuf[0] = seq_render_strip(scene, seq->seq1, cfra,
+                                          render_size, 
+                                          seqrectx, seqrecty);
+       } 
 
-static void do_build_seq_ibuf(Scene *scene, Sequence * seq, TStripElem *se, int cfra,
-                                 int build_proxy_run, int render_size, int seqrectx, int seqrecty)
-{
-       char name[FILE_MAXDIR+FILE_MAXFILE];
-       int use_limiter = TRUE;
+       if (seq->seq2) {
+               ibuf[1] = seq_render_strip(scene, seq->seq2, cfra,
+                                          render_size, 
+                                          seqrectx, seqrecty);
+       }
 
-       test_and_auto_discard_ibuf(se, seqrectx, seqrecty);
-       test_and_auto_discard_ibuf_stills(seq->strip);
+       if (seq->seq3) {
+               ibuf[2] = seq_render_strip(scene, seq->seq3, cfra,
+                                          render_size, 
+                                          seqrectx, seqrecty);
+       }
 
-       if(seq->type == SEQ_META) {
-               TStripElem * meta_se = 0;
-               int use_preprocess = FALSE;
-               use_limiter = FALSE;
-
-               if (!build_proxy_run && se->ibuf == 0) {
-                       se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-                       if (se->ibuf) {
-                               use_limiter = TRUE;
-                               use_preprocess = TRUE;
+       if (!ibuf[0] || !ibuf[1]) {
+               goto finish;
+       }
+
+       /* if any inputs are rectfloat, output is float too */
+       if((ibuf[0] && ibuf[0]->rect_float) || 
+          (ibuf[1] && ibuf[1]->rect_float) || 
+          (ibuf[2] && ibuf[2]->rect_float)) {
+               out = IMB_allocImBuf(
+                       (short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
+       } else {
+               out = IMB_allocImBuf(
+                       (short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+       }
+
+       for (i = 0; i < 3; i++) {
+               ImBuf * b = ibuf[i];
+               if (b) {
+                       if (!b->rect_float && out->rect_float) {
+                               IMB_float_from_rect_simple(b);
+                       }
+                       if (!b->rect && !out->rect_float) {
+                               IMB_rect_from_float(b);
                        }
                }
+       }
 
-               if(!se->ibuf && seq->seqbase.first) {
-                       meta_se = do_build_seq_array_recursively(scene,
-                               &seq->seqbase, seq->start + se->nr, 0,
-                               render_size, seqrectx, seqrecty);
+       sh.execute(scene, seq, cfra, fac, facf, out->x, out->y, render_size,
+                  ibuf[0], ibuf[1], ibuf[2], out);
 
-                       check_limiter_refcount("do_build_seq_ibuf: for META", meta_se);
-               }
+finish:
+       for (i = 0; i < 3; i++) {
+               IMB_freeImBuf(ibuf[i]);
+       }
 
-               se->ok = STRIPELEM_OK;
-
-               if(!se->ibuf && meta_se) {
-                       se->ibuf = meta_se->ibuf_comp;
-                       if(se->ibuf &&
-                          (!input_have_to_preprocess(scene, seq, se, cfra,
-                                                     seqrectx, seqrecty) ||
-                               build_proxy_run)) {
-                               IMB_refImBuf(se->ibuf);
-                               if (build_proxy_run) {
-                                       IMB_cache_limiter_unref(se->ibuf);
-                               }
-                       } else if (se->ibuf) {
-                               struct ImBuf * i = IMB_dupImBuf(se->ibuf);
+       if (!out) {
+               out = IMB_allocImBuf(
+                       (short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+       }
 
-                               IMB_cache_limiter_unref(se->ibuf);
+       return out;
+}
 
-                               se->ibuf = i;
 
-                               use_limiter = TRUE;
-                               use_preprocess = TRUE;
-                       }
-               } else if (se->ibuf) {
-                       use_limiter = TRUE;
-               }
-               if (meta_se) {
-                       free_metastrip_imbufs(
-                               &seq->seqbase, seq->start + se->nr, 0);
-               }
+static ImBuf * seq_render_scene_strip_impl(
+       Scene * scene, Sequence * seq, float nr, int seqrectx, int seqrecty)
+{
+       ImBuf * ibuf = 0;
+       float frame= seq->sfra + nr + seq->anim_startofs;
+       float oldcfra = seq->scene->r.cfra;
+       Object *oldcamera= seq->scene->camera;
+       ListBase oldmarkers;
+       
+       /* Hack! This function can be called from do_render_seq(), in that case
+          the seq->scene can already have a Render initialized with same name,
+          so we have to use a default name. (compositor uses scene name to
+          find render).
+          However, when called from within the UI (image preview in sequencer)
+          we do want to use scene Render, that way the render result is defined
+          for display in render/imagewindow
+          
+          Hmm, don't see, why we can't do that all the time,
+          and since G.rendering is uhm, gone... (Peter)
+       */
 
-               if (use_preprocess) {
-                       input_preprocess(scene, seq, se, cfra, seqrectx,
-                                        seqrecty);
-               }
-       } else if(seq->type & SEQ_EFFECT) {
-               int use_preprocess = FALSE;
-               /* should the effect be recalculated? */
-               
-               if (!build_proxy_run && se->ibuf == 0) {
-                       se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-                       if (se->ibuf) {
-                               use_preprocess = TRUE;
-                       }
-               }
+       int rendering = G.rendering;
+       int doseq;
+       int doseq_gl= G.rendering ? /*(scene->r.seq_flag & R_SEQ_GL_REND)*/ 0 : (scene->r.seq_flag & R_SEQ_GL_PREV);
+       int have_seq= FALSE;
+       Scene *sce= seq->scene;// *oldsce= scene;
+       int sce_valid= FALSE;
 
-               if(se->ibuf == 0) {
-                       /* if any inputs are rectfloat, output is float too */
-                       if((se->se1 && se->se1->ibuf && se->se1->ibuf->rect_float) ||
-                          (se->se2 && se->se2->ibuf && se->se2->ibuf->rect_float) ||
-                          (se->se3 && se->se3->ibuf && se->se3->ibuf->rect_float))
-                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
-                       else
-                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
-                       
-                       do_effect(scene, cfra, seq, se, render_size);
-                       if (input_have_to_preprocess(scene, seq, se, cfra,
-                                                    seqrectx, seqrecty) &&
-                               !build_proxy_run) {
-                               if ((se->se1 && (se->ibuf == se->se1->ibuf)) ||
-                                       (se->se2 && (se->ibuf == se->se2->ibuf))) {
-                                       struct ImBuf * i
-                                               = IMB_dupImBuf(se->ibuf);
-
-                                       IMB_freeImBuf(se->ibuf);
-
-                                       se->ibuf = i;
-                               }
-                               use_preprocess = TRUE;
-                       }
-               }
-               if (use_preprocess) {
-                       input_preprocess(scene, seq, se, cfra, seqrectx,
-                                        seqrecty);
-               }
-       } else if(seq->type == SEQ_IMAGE) {
-               if(se->ok == STRIPELEM_OK && se->ibuf == 0) {
-                       StripElem * s_elem = give_stripelem(seq, cfra);
-                       BLI_join_dirfile(name, seq->strip->dir, s_elem->name);
-                       BLI_path_abs(name, G.sce);
-                       if (!build_proxy_run) {
-                               se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-                       }
-                       copy_from_ibuf_still(seq, se);
+       have_seq= (sce->r.scemode & R_DOSEQ) 
+               && sce->ed && sce->ed->seqbase.first;
 
-                       if (se->ibuf==NULL && (se->ibuf= IMB_loadiffname(name, IB_rect))) {
-                               /* we don't need both (speed reasons)! */
-                               if (se->ibuf->rect_float && se->ibuf->rect)
-                                       imb_freerectImBuf(se->ibuf);
+       if(sce) {
+               sce_valid= (sce->camera || have_seq);
+       }
 
-                               /* all sequencer color is done in SRGB space, linear gives odd crossfades */
-                               if(se->ibuf->profile == IB_PROFILE_LINEAR_RGB)
-                                       IMB_convert_profile(se->ibuf, IB_PROFILE_NONE);
+       if (!sce_valid) {
+               return 0;
+       }
 
-                               copy_to_ibuf_still(seq, se);
-                       }
-                       
-                       if(se->ibuf == 0) {
-                               se->ok = STRIPELEM_FAILED;
-                       } else if (!build_proxy_run) {
-                               input_preprocess(scene, seq, se, cfra,
-                                                seqrectx, seqrecty);
-                       }
-               }
-       } else if(seq->type == SEQ_MOVIE) {
-               if(se->ok == STRIPELEM_OK && se->ibuf==0) {
-                       if(!build_proxy_run) {
-                               se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-                       }
-                       copy_from_ibuf_still(seq, se);
-
-                       if (se->ibuf == 0) {
-                               if(seq->anim==0) {
-                                       BLI_join_dirfile(name, seq->strip->dir, seq->strip->stripdata->name);
-                                       BLI_path_abs(name, G.sce);
-                                       
-                                       seq->anim = openanim(
-                                               name, IB_rect | 
-                                               ((seq->flag & SEQ_FILTERY) 
-                                                ? IB_animdeinterlace : 0));
-                               }
-                               if(seq->anim) {
-                                       IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
-                                       se->ibuf = IMB_anim_absolute(seq->anim, se->nr + seq->anim_startofs);
-                                       /* we don't need both (speed reasons)! */
-                                       if (se->ibuf 
-                                               && se->ibuf->rect_float 
-                                               && se->ibuf->rect) {
-                                               imb_freerectImBuf(se->ibuf);
-                                       }
-
-                               }
-                               copy_to_ibuf_still(seq, se);
+       
+       /* prevent eternal loop */
+       doseq= scene->r.scemode & R_DOSEQ;
+       scene->r.scemode &= ~R_DOSEQ;
+       
+       seq->scene->r.cfra= frame;
+       if(seq->scene_camera)   
+               seq->scene->camera= seq->scene_camera;
+       else    
+               scene_camera_switch_update(seq->scene);
+       
+#ifdef DURIAN_CAMERA_SWITCH
+       /* stooping to new low's in hackyness :( */
+       oldmarkers= seq->scene->markers;
+       seq->scene->markers.first= seq->scene->markers.last= NULL;
+#endif
+       
+       if(sequencer_view3d_cb && BLI_thread_is_main() && doseq_gl && (seq->scene == scene || have_seq==0) && seq->scene->camera) {
+               /* opengl offscreen render */
+               scene_update_for_newframe(seq->scene, seq->scene->lay);
+               ibuf= sequencer_view3d_cb(seq->scene, seqrectx, seqrecty, 
+                                         scene->r.seq_prev_type);
+       }
+       else {
+               Render *re;
+               RenderResult rres;
+               
+               if(rendering)
+                       re= RE_NewRender(" do_build_seq_ibuf");
+               else
+                       re= RE_NewRender(sce->id.name);
+               
+               RE_BlenderFrame(re, sce, NULL, sce->lay, frame);
+               
+               RE_AcquireResultImage(re, &rres);
+               
+               if(rres.rectf) {
+                       ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0);
+                       memcpy(ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty);
+                       if(rres.rectz) {
+                               addzbuffloatImBuf(ibuf);
+                               memcpy(ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty);
                        }
                        
-                       if(se->ibuf == 0) {
-                               se->ok = STRIPELEM_FAILED;
-                       } else if (!build_proxy_run) {
-                               input_preprocess(scene, seq, se, cfra,
-                                                seqrectx, seqrecty);
-                       }
-               }
-       } else if(seq->type == SEQ_SCENE) {     // scene can be NULL after deletions
-               Scene *sce= seq->scene;// *oldsce= scene;
-               int have_seq= FALSE;
-               int sce_valid= FALSE;
-
-               if(sce) {
-                       have_seq= (sce->r.scemode & R_DOSEQ) && sce->ed && sce->ed->seqbase.first;
-                       sce_valid= (sce->camera || have_seq);
-               }
-
-               if (se->ibuf == NULL && sce_valid && !build_proxy_run) {
-                       se->ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
-                       if (se->ibuf) {
-                               input_preprocess(scene, seq, se, cfra,
-                                                seqrectx, seqrecty);
-                       }
-               }
-
-               if (se->ibuf == NULL && sce_valid) {
-                       copy_from_ibuf_still(seq, se);
-                       if (se->ibuf) {
-                               input_preprocess(scene, seq, se, cfra,
-                                                seqrectx, seqrecty);
-                       }
+                       /* {
+                          ImBuf *imb= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0);
+                          IMB_saveiff(imb, "/tmp/foo.image", IB_rect | IB_metadata);
+                          IMB_freeImBuf(imb);
+                          } */
+                       
+               } else if (rres.rect32) {
+                       ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0);
+                       memcpy(ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty);
                }
                
-               if (!sce_valid) {
-                       se->ok = STRIPELEM_FAILED;
-               }
-               else if (se->ibuf==NULL && sce_valid) {
-                       int frame= seq->sfra + se->nr + seq->anim_startofs;
-                       int oldcfra = seq->scene->r.cfra;
-                       Object *oldcamera= seq->scene->camera;
-                       ListBase oldmarkers;
-
-                       /* Hack! This function can be called from do_render_seq(), in that case
-                          the seq->scene can already have a Render initialized with same name,
-                          so we have to use a default name. (compositor uses scene name to
-                          find render).
-                          However, when called from within the UI (image preview in sequencer)
-                          we do want to use scene Render, that way the render result is defined
-                          for display in render/imagewindow
-
-                          Hmm, don't see, why we can't do that all the time,
-                          and since G.rendering is uhm, gone... (Peter)
-                       */
-
-                       int rendering = G.rendering;
-                       int doseq;
-                       int doseq_gl= G.rendering ? /*(scene->r.seq_flag & R_SEQ_GL_REND)*/ 0 : (scene->r.seq_flag & R_SEQ_GL_PREV);
-
-                       /* prevent eternal loop */
-                       doseq= scene->r.scemode & R_DOSEQ;
-                       scene->r.scemode &= ~R_DOSEQ;
-
-                       seq->scene->r.cfra= frame;
-                       if(seq->scene_camera)   seq->scene->camera= seq->scene_camera;
-                       else                                    scene_camera_switch_update(seq->scene);
-
+               RE_ReleaseResultImage(re);
+               
+               // BIF_end_render_callbacks();
+       }
+       
+       /* restore */
+       scene->r.scemode |= doseq;
+       
+       seq->scene->r.cfra = oldcfra;
+       seq->scene->camera= oldcamera;
+       
 #ifdef DURIAN_CAMERA_SWITCH
-                       /* stooping to new low's in hackyness :( */
-                       oldmarkers= seq->scene->markers;
-                       seq->scene->markers.first= seq->scene->markers.last= NULL;
+       /* stooping to new low's in hackyness :( */
+       seq->scene->markers= oldmarkers;
 #endif
 
-                       if(sequencer_view3d_cb && doseq_gl && (seq->scene == scene || have_seq==0) && seq->scene->camera) {
-                               /* opengl offscreen render */
-                               scene_update_for_newframe(seq->scene, seq->scene->lay);
-                               se->ibuf= sequencer_view3d_cb(seq->scene, seqrectx, seqrecty, scene->r.seq_prev_type);
-                       }
-                       else {
-                               Render *re;
-                               RenderResult rres;
+       return ibuf;
+}
 
-                               if(rendering)
-                                       re= RE_NewRender(" do_build_seq_ibuf");
-                               else
-                                       re= RE_NewRender(sce->id.name);
+static ImBuf * seq_render_strip(Scene *scene, Sequence * seq, float cfra,
+                               int render_size, 
+                               int seqrectx, int seqrecty)
+{
+       char name[FILE_MAXDIR+FILE_MAXFILE];
+       int use_preprocess = input_have_to_preprocess(
+               scene, seq, cfra, seqrectx, seqrecty);
+       ImBuf * ibuf = seq_stripelem_cache_get(
+               seq, seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF);
+       float nr = give_stripelem_index(seq, cfra);
 
-                               RE_BlenderFrame(re, sce, NULL, sce->lay, frame);
+       /* currently, we cache preprocessed images */
+       if (ibuf) {
+               use_preprocess = FALSE;
+       }
 
-                               RE_AcquireResultImage(re, &rres);
+       if(seq->type == SEQ_META) {
+               ImBuf * meta_ibuf = 0;
 
-                               if(rres.rectf) {
-                                       se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0);
-                                       memcpy(se->ibuf->rect_float, rres.rectf, 4*sizeof(float)*rres.rectx*rres.recty);
-                                       if(rres.rectz) {
-                                               addzbuffloatImBuf(se->ibuf);
-                                               memcpy(se->ibuf->zbuf_float, rres.rectz, sizeof(float)*rres.rectx*rres.recty);
-                                       }
+               if (ibuf == 0) {
+                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
+               }
 
-                                       /* {
-                                               ImBuf *imb= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rectfloat, 0);
-                                               IMB_saveiff(imb, "/tmp/foo.image", IB_rect | IB_metadata);
-                                               IMB_freeImBuf(imb);
-                                       } */
+               if(!ibuf && seq->seqbase.first) {
+                       meta_ibuf = seq_render_strip_stack(
+                               scene,
+                               &seq->seqbase, seq->start + nr, 0,
+                               render_size, seqrectx, seqrecty);
+               }
 
-                               } else if (rres.rect32) {
-                                       se->ibuf= IMB_allocImBuf(rres.rectx, rres.recty, 32, IB_rect, 0);
-                                       memcpy(se->ibuf->rect, rres.rect32, 4*rres.rectx*rres.recty);
-                               }
+               if(!ibuf && meta_ibuf) {
+                       ibuf = meta_ibuf;
+                       if(ibuf && use_preprocess) {
+                               struct ImBuf * i = IMB_dupImBuf(ibuf);
 
-                               RE_ReleaseResultImage(re);
+                               IMB_freeImBuf(ibuf);
 
-                               // BIF_end_render_callbacks();
+                               ibuf = i;
                        }
-                       
-                       /* restore */
-                       scene->r.scemode |= doseq;
+               }
+       } else if(seq->type == SEQ_SPEED) {
+               ImBuf * child_ibuf = 0;
 
-                       seq->scene->r.cfra = oldcfra;
-                       seq->scene->camera= oldcamera;
+               if (ibuf == 0) {
+                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
+               }
 
-#ifdef DURIAN_CAMERA_SWITCH
-                       /* stooping to new low's in hackyness :( */
-                       seq->scene->markers= oldmarkers;
-#endif
+               if (ibuf == 0) {
+                       float f_cfra;
+                       SpeedControlVars * s 
+                               = (SpeedControlVars *)seq->effectdata;
 
-                       copy_to_ibuf_still(seq, se);
+                       sequence_effect_speed_rebuild_map(scene, seq, 0);
 
-                       if (!build_proxy_run) {
-                               if(se->ibuf == NULL) {
-                                       se->ok = STRIPELEM_FAILED;
-                               } else {
-                                       input_preprocess(scene, seq, se, cfra,
-                                                        seqrectx, seqrecty);
-                               }
-                       }
+                       /* weeek! */
+                       f_cfra = seq->start + s->frameMap[(int) nr];
 
+                       child_ibuf = seq_render_strip(scene, seq->seq1, f_cfra,
+                                                     render_size, 
+                                                     seqrectx, seqrecty);
                }
-       }
-       if (!build_proxy_run) {
-               if (se->ibuf && use_limiter) {
-                       IMB_cache_limiter_insert(se->ibuf);
-                       IMB_cache_limiter_ref(se->ibuf);
-                       IMB_cache_limiter_touch(se->ibuf);
-               }
-       }
-}
 
-static TStripElem* do_build_seq_recursively(Scene *scene, Sequence *seq, int cfra, int render_size, int seqrectx, int seqrecty);
+               if (!ibuf && child_ibuf) {
+                       ibuf = child_ibuf;
+                       if(ibuf && use_preprocess) {
+                               struct ImBuf * i = IMB_dupImBuf(ibuf);
 
-static void do_effect_seq_recursively(Scene *scene, Sequence *seq, TStripElem *se, int cfra, int render_size, int seqrectx, int seqrecty)
-{
-       float fac, facf;
-       struct SeqEffectHandle sh = get_sequence_effect(seq);
-       int early_out;
-       FCurve *fcu= NULL;
-
-       se->se1 = 0;
-       se->se2 = 0;
-       se->se3 = 0;
+                               IMB_freeImBuf(ibuf);
 
-       if ((seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) != 0) {
-               sh.get_default_fac(seq, cfra, &fac, &facf);
-               if( scene->r.mode & R_FIELDS ); else facf= fac;
-       } else {
-               fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, 
-                                         "effect_fader", 0);
-               if (fcu) {
-                       fac = facf = evaluate_fcurve(fcu, cfra);
-                       if( scene->r.mode & R_FIELDS ) {
-                               facf = evaluate_fcurve(fcu, cfra + 0.5);
+                               ibuf = i;
                        }
-               } else {
-                       fac = facf = seq->effect_fader;
                }
-       }
-
-       early_out = sh.early_out(seq, fac, facf);
-       switch (early_out) {
-       case -1:
-               /* no input needed */
-               break;
-       case 0:
-               se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra, render_size, seqrectx, seqrecty);
-               se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra, render_size, seqrectx, seqrecty);
-               if (seq->seq3) {
-                       se->se3 = do_build_seq_recursively(scene, seq->seq3, cfra, render_size, seqrectx, seqrecty);
+       } else if(seq->type & SEQ_EFFECT) {
+               /* should the effect be recalculated? */
+               
+               if (ibuf == 0) {
+                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
                }
-               break;
-       case 1:
-               se->se1 = do_build_seq_recursively(scene, seq->seq1, cfra, render_size, seqrectx, seqrecty);
-               break;
-       case 2:
-               se->se2 = do_build_seq_recursively(scene, seq->seq2, cfra, render_size, seqrectx, seqrecty);
-               break;
-       }
-
-
-       do_build_seq_ibuf(scene, seq, se, cfra, FALSE, render_size, seqrectx, seqrecty);
 
-       /* children are not needed anymore ... */
-
-       if (se->se1 && se->se1->ibuf) {
-               IMB_cache_limiter_unref(se->se1->ibuf);
-       }
-       if (se->se2 && se->se2->ibuf) {
-               IMB_cache_limiter_unref(se->se2->ibuf);
-       }
-       if (se->se3 && se->se3->ibuf) {
-               IMB_cache_limiter_unref(se->se3->ibuf);
-       }
-       check_limiter_refcount("do_effect_seq_recursively", se);
-}
-
-static TStripElem* do_build_seq_recursively_impl(Scene *scene, Sequence * seq, int cfra, int render_size, int seqrectx, int seqrecty)
-{
-       TStripElem *se;
-
-       se = give_tstripelem(seq, cfra);
-
-       if(se) {
-               if (seq->type & SEQ_EFFECT) {
-                       do_effect_seq_recursively(scene, seq, se, cfra, render_size, seqrectx, seqrecty);
-               } else {
-                       do_build_seq_ibuf(scene, seq, se, cfra, FALSE, render_size, seqrectx, seqrecty);
+               if(ibuf == 0) {         
+                       ibuf = seq_render_effect_strip_impl(
+                               scene, cfra, seq, render_size, 
+                               seqrectx, seqrecty);
                }
-       }
-       return se;
-}
-
-/* FIXME:
-   
-If cfra was float throughout blender (especially in the render
-pipeline) one could even _render_ with subframe precision
-instead of faking using the blend code below...
-
-*/
-
-static TStripElem* do_handle_speed_effect(Scene *scene, Sequence * seq, int cfra, int render_size, int seqrectx, int seqrecty)
-{
-       SpeedControlVars * s = (SpeedControlVars *)seq->effectdata;
-       int nr = cfra - seq->start;
-       float f_cfra;
-       int cfra_left;
-       int cfra_right;
-       TStripElem * se = 0;
-       TStripElem * se1 = 0;
-       TStripElem * se2 = 0;
-       
-       sequence_effect_speed_rebuild_map(scene, seq, 0);
-       
-       f_cfra = seq->start + s->frameMap[nr];
-       
-       cfra_left = (int) floor(f_cfra);
-       cfra_right = (int) ceil(f_cfra);
+       } else if(seq->type == SEQ_IMAGE) {
+               StripElem * s_elem = give_stripelem(seq, cfra);
 
-       se = give_tstripelem(seq, cfra);
+               if(ibuf == 0) {
+                       BLI_join_dirfile(name, seq->strip->dir, s_elem->name);
+                       BLI_path_abs(name, G.sce);
 
-       if (!se) {
-               return se;
-       }
+                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
+               }
 
-       if (cfra_left == cfra_right || 
-               (s->flags & SEQ_SPEED_BLEND) == 0) {
-               test_and_auto_discard_ibuf(se, seqrectx, seqrecty);
+               if (ibuf == 0) {
+                       ibuf = copy_from_ibuf_still(seq,nr,seqrectx,seqrecty);
+               }
 
-               if (se->ibuf == NULL) {
-                       se1 = do_build_seq_recursively(scene, seq->seq1, cfra_left, render_size, seqrectx, seqrecty);
+               if (ibuf == 0 && (ibuf=IMB_loadiffname(name, IB_rect))) {
+                       /* we don't need both (speed reasons)! */
+                       if (ibuf->rect_float && ibuf->rect)
+                               imb_freerectImBuf(ibuf);
 
-                       if((se1 && se1->ibuf && se1->ibuf->rect_float))
-                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
-                       else
-                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
+                       /* all sequencer color is done in SRGB space, linear gives odd crossfades */
+                       if(ibuf->profile == IB_PROFILE_LINEAR_RGB)
+                               IMB_convert_profile(ibuf, IB_PROFILE_NONE);
 
-                       if (se1 == 0 || se1->ibuf == 0) {
-                               make_black_ibuf(se->ibuf);
-                       } else {
-                               if (se->ibuf != se1->ibuf) {
-                                       if (se->ibuf) {
-                                               IMB_freeImBuf(se->ibuf);
-                                       }
+                       copy_to_ibuf_still(seq, nr, ibuf);
+               }
+       } else if(seq->type == SEQ_MOVIE) {
+               if(ibuf == 0) {
+                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
+                       
+               }
+               
+               if (ibuf == 0) {
+                       ibuf = copy_from_ibuf_still(seq, nr,seqrectx,seqrecty);
+               }
 
-                                       se->ibuf = se1->ibuf;
-                                       IMB_refImBuf(se->ibuf);
+               if (ibuf == 0) {
+                       if(seq->anim==0) {
+                               BLI_join_dirfile(name, 
+                                                seq->strip->dir, 
+                                                seq->strip->stripdata->name);
+                               BLI_path_abs(name, G.sce);
+                                       
+                               seq->anim = openanim(
+                                       name, IB_rect | 
+                                       ((seq->flag & SEQ_FILTERY) 
+                                        ? IB_animdeinterlace : 0));
+                       }
+                       if(seq->anim) {
+                               IMB_anim_set_preseek(seq->anim, 
+                                                    seq->anim_preseek);
+                               ibuf = IMB_anim_absolute(seq->anim, 
+                                                        nr 
+                                                        + seq->anim_startofs);
+                               /* we don't need both (speed reasons)! */
+                               if (ibuf && ibuf->rect_float 
+                                   && ibuf->rect) {
+                                       imb_freerectImBuf(ibuf);
                                }
-                       }
-               }
-       } else {
-               struct SeqEffectHandle sh;
 
-               if(se->ibuf) {
-                       if(se->ibuf->x < seqrectx || se->ibuf->y < seqrecty 
-                          || !(se->ibuf->rect || se->ibuf->rect_float)) {
-                               IMB_freeImBuf(se->ibuf);
-                               se->ibuf= 0;
                        }
+                       copy_to_ibuf_still(seq, nr, ibuf);
                }
-
-               if (se->ibuf == NULL) {
-                       se1 = do_build_seq_recursively(scene, seq->seq1, cfra_left, render_size, seqrectx, seqrecty);
-                       se2 = do_build_seq_recursively(scene, seq->seq1, cfra_right, render_size, seqrectx, seqrecty);
-
-                       if((se1 && se1->ibuf && se1->ibuf->rect_float))
-                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rectfloat, 0);
-                       else
-                               se->ibuf= IMB_allocImBuf((short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
                        
-                       if (!se1 || !se2) {
-                               make_black_ibuf(se->ibuf);
-                       } else {
-                               sh = get_sequence_effect(seq);
-
-                               sh.execute(scene, seq, cfra, 
-                                          f_cfra - (float) cfra_left, 
-                                          f_cfra - (float) cfra_left, 
-                                          se->ibuf->x, se->ibuf->y, 
-                                          render_size,
-                                          se1->ibuf, se2->ibuf, 0, se->ibuf);
-                       }
+       } else if(seq->type == SEQ_SCENE) {     // scene can be NULL after deletions
+               if (ibuf == 0) {
+                       ibuf = seq_proxy_fetch(scene, seq, cfra, render_size);
                }
+               if (ibuf == 0) {
+                       ibuf = copy_from_ibuf_still(seq, nr,seqrectx,seqrecty);
+               }
+               
+               if (ibuf == 0) {
+                       ibuf = seq_render_scene_strip_impl(scene, seq, nr,
+                                                          seqrectx, seqrecty);
 
+                       copy_to_ibuf_still(seq, nr, ibuf);
+               }
        }
 
-       /* caller expects this to be referenced, so do it! */
-       if (se->ibuf) {
-               IMB_cache_limiter_insert(se->ibuf);
-               IMB_cache_limiter_ref(se->ibuf);
-               IMB_cache_limiter_touch(se->ibuf);
+       if (!ibuf) {
+               ibuf = IMB_allocImBuf(
+                       (short)seqrectx, (short)seqrecty, 32, IB_rect, 0);
        }
 
-       /* children are no longer needed */
-       if (se1 && se1->ibuf)
-               IMB_cache_limiter_unref(se1->ibuf);
-       if (se2 && se2->ibuf)
-               IMB_cache_limiter_unref(se2->ibuf);
-
-       check_limiter_refcount("do_handle_speed_effect", se);
-
-       return se;
-}
-
-/* 
- * build all ibufs recursively
- * 
- * if successfull, the returned TStripElem contains the (referenced!) imbuf
- * that means: you _must_ call 
- *
- * IMB_cache_limiter_unref(rval);
- * 
- * if rval != 0
- * 
- */
-
-static TStripElem* do_build_seq_recursively(Scene *scene, Sequence * seq, int cfra, int render_size, int seqrectx, int seqrecty)
-{
-       TStripElem *se;
+       if (ibuf->x != seqrectx || ibuf->y != seqrecty) {
+               use_preprocess = TRUE;
+       }
 
-       /* BAD HACK! Seperate handling for speed effects needed, since
-          a) you can't just fetch a different cfra within an effect strip
-          b) we have to blend two frames, and CFRA is not float...
-       */
-       if (seq->type == SEQ_SPEED) {
-               se = do_handle_speed_effect(scene, seq, cfra, render_size, seqrectx, seqrecty);
-       } else {
-               se = do_build_seq_recursively_impl(scene, seq, cfra, render_size, seqrectx, seqrecty);
+       if (use_preprocess) {
+               ibuf = input_preprocess(scene, seq, cfra, seqrectx,
+                                       seqrecty, ibuf);
        }
 
-       check_limiter_refcount("do_build_seq_recursively", se);
+       seq_stripelem_cache_put(
+               seq, seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF, ibuf);
 
-       return se;
+       return ibuf;
 }
 
+/* **********************************************************************
+   strip stack rendering functions
+   ********************************************************************** */
+
 static int seq_must_swap_input_in_blend_mode(Sequence * seq)
 {
        int swap_input = FALSE;
@@ -2593,28 +2157,22 @@ static int seq_get_early_out_for_blend_mode(Sequence * seq)
        return early_out;
 }
 
-static TStripElem* do_build_seq_array_recursively(
-       Scene *scene, ListBase *seqbasep, int cfra, int chanshown, 
+static ImBuf* seq_render_strip_stack(
+       Scene *scene, ListBase *seqbasep, float cfra, int chanshown, 
        int render_size, int seqrectx, int seqrecty)
 {
        Sequence* seq_arr[MAXSEQ+1];
        int count;
        int i;
-       TStripElem* se = 0;
+       ImBuf* out = 0;
 
        count = get_shown_sequences(seqbasep, cfra, chanshown, 
-                                       (Sequence **)&seq_arr);
+                                   (Sequence **)&seq_arr);
 
        if (!count) {
                return 0;
        }
 
-       se = give_tstripelem(seq_arr[count - 1], cfra);
-
-       if (!se) {
-               return 0;
-       }
-
 #if 0 /* commentind since this breaks keyframing, since it resets the value on draw */
        if(scene->r.cfra != cfra) {
                // XXX for prefetch and overlay offset!..., very bad!!!
@@ -2623,25 +2181,24 @@ static TStripElem* do_build_seq_array_recursively(
        }
 #endif
 
-       test_and_auto_discard_ibuf(se, seqrectx, seqrecty);
+       out = seq_stripelem_cache_get(
+               seq_arr[count - 1], 
+               seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF_COMP);
 
-       if (se->ibuf_comp != 0) {
-               IMB_cache_limiter_insert(se->ibuf_comp);
-               IMB_cache_limiter_ref(se->ibuf_comp);
-               IMB_cache_limiter_touch(se->ibuf_comp);
-               return se;
+       if (out) {
+               return out;
        }
-
        
        if(count == 1) {
-               se = do_build_seq_recursively(scene, seq_arr[0],
-                                             cfra, render_size,
-                                             seqrectx, seqrecty);
-               if (se->ibuf) {
-                       se->ibuf_comp = se->ibuf;
-                       IMB_refImBuf(se->ibuf_comp);
-               }
-               return se;
+               out = seq_render_strip(scene, seq_arr[0],
+                                       cfra, render_size,
+                                       seqrectx, seqrecty);
+               seq_stripelem_cache_put(
+                       seq_arr[0], 
+                       seqrectx, seqrecty, cfra, 
+                       SEQ_STRIPELEM_IBUF_COMP, out);
+
+               return out;
        }
 
 
@@ -2649,29 +2206,17 @@ static TStripElem* do_build_seq_array_recursively(
                int early_out;
                Sequence * seq = seq_arr[i];
 
-               se = give_tstripelem(seq, cfra);
-
-               test_and_auto_discard_ibuf(se, seqrectx, seqrecty);
+               out = seq_stripelem_cache_get(
+                       seq, 
+                       seqrectx, seqrecty, cfra, SEQ_STRIPELEM_IBUF_COMP);
 
-               if (se->ibuf_comp != 0) {
+               if (out) {
                        break;
                }
                if (seq->blend_mode == SEQ_BLEND_REPLACE) {
-                       do_build_seq_recursively(
-                               scene, seq, cfra, render_size,
-                               seqrectx, seqrecty);
-
-                       if (se->ibuf) {
-                               se->ibuf_comp = se->ibuf;
-                               IMB_refImBuf(se->ibuf);
-                       } else {
-                               se->ibuf_comp = IMB_allocImBuf(
-                                       (short)seqrectx, (short)seqrecty, 
-                                       32, IB_rect, 0);
-                               IMB_cache_limiter_insert(se->ibuf_comp);
-                               IMB_cache_limiter_ref(se->ibuf_comp);
-                               IMB_cache_limiter_touch(se->ibuf_comp);
-                       }
+                       out = seq_render_strip(scene, seq, cfra,
+                                              render_size,
+                                              seqrectx, seqrecty);
                        break;
                }
 
@@ -2680,154 +2225,111 @@ static TStripElem* do_build_seq_array_recursively(
                switch (early_out) {
                case -1:
                case 2:
-                       do_build_seq_recursively(
-                               scene, seq, cfra, render_size,
-                               seqrectx, seqrecty);
-
-                       if (se->ibuf) {
-                               se->ibuf_comp = se->ibuf;
-                               IMB_refImBuf(se->ibuf_comp);
-                       } else {
-                               se->ibuf_comp = IMB_allocImBuf(
-                                       (short)seqrectx, (short)seqrecty, 
-                                       32, IB_rect, 0);
-                               IMB_cache_limiter_insert(se->ibuf_comp);
-                               IMB_cache_limiter_ref(se->ibuf_comp);
-                               IMB_cache_limiter_touch(se->ibuf_comp);
-                       }
+                       out = seq_render_strip(scene, seq, cfra,
+                                              render_size,
+                                              seqrectx, seqrecty);
                        break;
                case 1:
                        if (i == 0) {
-                               se->ibuf_comp = IMB_allocImBuf(
+                               out = IMB_allocImBuf(
                                        (short)seqrectx, (short)seqrecty, 
                                        32, IB_rect, 0);
-                               IMB_cache_limiter_insert(se->ibuf_comp);
-                               IMB_cache_limiter_ref(se->ibuf_comp);
-                               IMB_cache_limiter_touch(se->ibuf_comp);
                        }
                        break;
                case 0:
-                       do_build_seq_recursively(
-                               scene, seq, cfra, render_size,
-                               seqrectx, seqrecty);
-
-                       if (!se->ibuf) {
-                               se->ibuf = IMB_allocImBuf(
-                                       (short)seqrectx, (short)seqrecty, 
-                                       32, IB_rect, 0);
-                               IMB_cache_limiter_insert(se->ibuf);
-                               IMB_cache_limiter_ref(se->ibuf);
-                               IMB_cache_limiter_touch(se->ibuf);
-                       }
                        if (i == 0) {
-                               se->ibuf_comp = se->ibuf;
-                               IMB_refImBuf(se->ibuf_comp);
+                               out = seq_render_strip(scene, seq, cfra,
+                                                      render_size,
+                                                      seqrectx, seqrecty);
                        }
+
                        break;
                }
-       
-               if (se->ibuf_comp) {
+               if (out) {
                        break;
                }
        }
 
+       seq_stripelem_cache_put(
+               seq_arr[i], seqrectx, seqrecty, cfra, 
+               SEQ_STRIPELEM_IBUF_COMP, out);
+
+
        i++;
 
        for (; i < count; i++) {
                Sequence * seq = seq_arr[i];
-               struct SeqEffectHandle sh = get_sequence_blend(seq);
-               TStripElem* se1 = give_tstripelem(seq_arr[i-1], cfra);
-               TStripElem* se2 = give_tstripelem(seq_arr[i], cfra);
 
-               float facf = seq->blend_opacity / 100.0;
-               int swap_input = seq_must_swap_input_in_blend_mode(seq);
-               int early_out = seq_get_early_out_for_blend_mode(seq);
+               if (seq_get_early_out_for_blend_mode(seq) == 0) {
+                       struct SeqEffectHandle sh = get_sequence_blend(seq);
+                       ImBuf * ibuf1 = out;
+                       ImBuf * ibuf2 = seq_render_strip(scene, seq, cfra,
+                                                        render_size,
+                                                        seqrectx, seqrecty);
 
-               switch (early_out) {
-               case 0: {
-                       int x= se2->ibuf->x;
-                       int y= se2->ibuf->y;
+                       float facf = seq->blend_opacity / 100.0;
+                       int swap_input 
+                               = seq_must_swap_input_in_blend_mode(seq);
 
-                       if(se1->ibuf_comp == NULL)
-                               continue;
+                       int x= out->x;
+                       int y= out->y;
 
-                       if (se1->ibuf_comp->rect_float ||
-                               se2->ibuf->rect_float) {
-                               se2->ibuf_comp = IMB_allocImBuf(
+                       if (ibuf1->rect_float || ibuf2->rect_float) {
+                               out = IMB_allocImBuf(
                                        (short)seqrectx, (short)seqrecty, 
                                        32, IB_rectfloat, 0);
                        } else {
-                               se2->ibuf_comp = IMB_allocImBuf(
+                               out = IMB_allocImBuf(
                                        (short)seqrectx, (short)seqrecty, 
                                        32, IB_rect, 0);
                        }
 
-
-                       if (!se1->ibuf_comp->rect_float && 
-                               se2->ibuf_comp->rect_float) {
-                               IMB_float_from_rect_simple(se1->ibuf_comp);
+                       if (!ibuf1->rect_float && out->rect_float) {
+                               IMB_float_from_rect_simple(ibuf1);
                        }
-                       if (!se2->ibuf->rect_float && 
-                               se2->ibuf_comp->rect_float) {
-                               IMB_float_from_rect_simple(se2->ibuf);
+                       if (!ibuf2->rect_float && out->rect_float) {
+                               IMB_float_from_rect_simple(ibuf2);
                        }
 
-                       if (!se1->ibuf_comp->rect && 
-                               !se2->ibuf_comp->rect_float) {
-                               IMB_rect_from_float(se1->ibuf_comp);
+                       if (!ibuf1->rect && !out->rect_float) {
+                               IMB_rect_from_float(ibuf1);
                        }
-                       if (!se2->ibuf->rect && 
-                               !se2->ibuf_comp->rect_float) {
-                               IMB_rect_from_float(se2->ibuf);
+                       if (!ibuf2->rect && !out->rect_float) {
+                               IMB_rect_from_float(ibuf2);
                        }
                        
                        if (swap_input) {
                                sh.execute(scene, seq, cfra, 
                                           facf, facf, x, y, render_size,
-                                          se2->ibuf, se1->ibuf_comp, 0,
-                                          se2->ibuf_comp);
+                                          ibuf2, ibuf1, 0, out);
                        } else {
                                sh.execute(scene, seq, cfra, 
                                           facf, facf, x, y, render_size,
-                                          se1->ibuf_comp, se2->ibuf, 0,
-                                          se2->ibuf_comp);
+                                          ibuf1, ibuf2, 0, out);
                        }
-                       
-                       IMB_cache_limiter_insert(se2->ibuf_comp);
-                       IMB_cache_limiter_ref(se2->ibuf_comp);
-                       IMB_cache_limiter_touch(se2->ibuf_comp);
-
-                       IMB_cache_limiter_unref(se1->ibuf_comp);
-                       IMB_cache_limiter_unref(se2->ibuf);
-
-                       break;
+               
+                       IMB_freeImBuf(ibuf1);
+                       IMB_freeImBuf(ibuf2);
                }
-               case 1: {
-                       se2->ibuf_comp = se1->ibuf_comp;
-                       if(se2->ibuf_comp)
-                               IMB_refImBuf(se2->ibuf_comp);
 
-                       break;
-               }
-               }
-               se = se2;
+               seq_stripelem_cache_put(
+                       seq_arr[i], seqrectx, seqrecty, cfra, 
+                       SEQ_STRIPELEM_IBUF_COMP, out);
        }
 
-       return se;
+       return out;
 }
 
 /*
  * returned ImBuf is refed!
- * you have to unref after usage!
+ * you have to free after usage!
  */
 
-static ImBuf *give_ibuf_seq_impl(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
+ImBuf *give_ibuf_seq(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
 {
        Editing *ed= seq_give_editing(scene, FALSE);
        int count;
        ListBase *seqbasep;
-       TStripElem *se;
-
        
        if(ed==NULL) return NULL;
 
@@ -2839,64 +2341,19 @@ static ImBuf *give_ibuf_seq_impl(Scene *scene, int rectx, int recty, int cfra, i
                seqbasep= ed->seqbasep;
        }
 
-       se = do_build_seq_array_recursively(scene, seqbasep, cfra, chanshown, render_size, rectx, recty);
-
-       if(!se) { 
-               return 0;
-       }
-
-       check_limiter_refcount_comp("give_ibuf_seq_impl", se);
-
-       return se->ibuf_comp;
+       return seq_render_strip_stack(
+               scene, seqbasep, cfra, chanshown, render_size, rectx, recty);
 }
 
 ImBuf *give_ibuf_seqbase(struct Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size, ListBase *seqbasep)
 {
-       TStripElem *se;
-
-       se = do_build_seq_array_recursively(scene, seqbasep, cfra, chanshown, render_size, rectx, recty);
-
-       if(!se) { 
-               return 0;
-       }
-
-       check_limiter_refcount_comp("give_ibuf_seqbase", se);
-
-       if (se->ibuf_comp) {
-               IMB_cache_limiter_unref(se->ibuf_comp);
-       }
-
-       return se->ibuf_comp;
+       return seq_render_strip_stack(scene, seqbasep, cfra, chanshown, render_size, rectx, recty);
 }
 
 
 ImBuf *give_ibuf_seq_direct(Scene *scene, int rectx, int recty, int cfra, int render_size, Sequence *seq)
 {
-       TStripElem* se;
-
-       se = do_build_seq_recursively(scene, seq, cfra, render_size, rectx, recty);
-
-       if(!se) { 
-               return 0;
-       }
-
-       check_limiter_refcount("give_ibuf_seq_direct", se);
-
-       if (se->ibuf) {
-               IMB_cache_limiter_unref(se->ibuf);
-       }
-
-       return se->ibuf;
-}
-
-ImBuf *give_ibuf_seq(Scene *scene, int rectx, int recty, int cfra, int chanshown, int render_size)
-{
-       ImBuf* i = give_ibuf_seq_impl(scene, rectx, recty, cfra, chanshown, render_size);
-
-       if (i) {
-               IMB_cache_limiter_unref(i);
-       }
-       return i;
+       return seq_render_strip(scene, seq, cfra, render_size, rectx, recty);
 }
 
 #if 0
@@ -3245,20 +2702,6 @@ ImBuf *give_ibuf_seq_threaded(Scene *scene, int rectx, int recty, int cfra, int
 
 /* Functions to free imbuf and anim data on changes */
 
-static void free_imbuf_strip_elem(TStripElem *se)
-{
-       if(se->ibuf) {
-               IMB_freeImBuf(se->ibuf);
-       }
-       if(se->ibuf_comp) {
-               IMB_freeImBuf(se->ibuf_comp);
-       }
-       se->ibuf_comp = 0;
-       se->ibuf= 0;
-       se->ok= STRIPELEM_OK;
-       se->se1= se->se2= se->se3= 0;
-}
-
 static void free_anim_seq(Sequence *seq)
 {
        if(seq->anim) {
@@ -3271,8 +2714,6 @@ void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage,
                    int keep_file_handles)
 {
        Sequence *seq;
-       TStripElem *se;
-       int a;
 
        if (check_mem_usage) {
                /* Let the cache limitor take care of this (schlaile) */
@@ -3298,31 +2739,10 @@ void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage,
                }
        }
 
+       seq_stripelem_cache_cleanup();
        
        for(seq= seqbase->first; seq; seq= seq->next) {
                if(seq->strip) {
-                       for(a = 0, se = seq->strip->tstripdata; 
-                               a < seq->strip->len && se; a++, se++) {
-                               free_imbuf_strip_elem(se);
-                       }
-                       for(a = 0, se = seq->strip->tstripdata_startstill; 
-                               a < seq->strip->startstill && se; a++, se++) {
-                               free_imbuf_strip_elem(se);
-                       }
-                       for(a = 0, se = seq->strip->tstripdata_endstill; 
-                               a < seq->strip->endstill && se; a++, se++) {
-                               free_imbuf_strip_elem(se);
-                       }
-                       if(seq->strip->ibuf_startstill) {
-                               IMB_freeImBuf(seq->strip->ibuf_startstill);
-                               seq->strip->ibuf_startstill = 0;
-                       }
-
-                       if(seq->strip->ibuf_endstill) {
-                               IMB_freeImBuf(seq->strip->ibuf_endstill);
-                               seq->strip->ibuf_endstill = 0;
-                       }
-
                        if(seq->type==SEQ_MOVIE && !keep_file_handles)
                                free_anim_seq(seq);
                        if(seq->type==SEQ_SPEED) {
@@ -3344,8 +2764,7 @@ void free_imbuf_seq(Scene *scene, ListBase * seqbase, int check_mem_usage,
 static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *changed_seq, int len_change, int ibuf_change)
 {
        Sequence *subseq;
-       int a, free_imbuf = 0;
-       TStripElem *se;
+       int free_imbuf = 0;
        
        /* recurs downwards to see if this seq depends on the changed seq */
        
@@ -3371,12 +2790,6 @@ static int update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *chan
        
        if(free_imbuf) {
                if(ibuf_change) {
-                       se= seq->strip->tstripdata;
-                       if (se) {
-                               for(a=0; a<seq->len; a++, se++)
-                                       free_imbuf_strip_elem(se);
-                       }
-                       
                        if(seq->type == SEQ_MOVIE)
                                free_anim_seq(seq);
                        if(seq->type == SEQ_SPEED) {
@@ -3402,39 +2815,6 @@ void update_changed_seq_and_deps(Scene *scene, Sequence *changed_seq, int len_ch
                update_changed_seq_recurs(scene, seq, changed_seq, len_change, ibuf_change);
 }
 
-#if 0 // XXX from 2.4x, needs updating
-void free_imbuf_seq()
-{
-       Scene * sce = G.main->scene.first;
-       while(sce) {
-               free_imbuf_seq_editing(sce->ed);
-               sce= sce->id.next;
-       }
-}
-#endif 
-
-#if 0 // XXX old animation system
-static void free_imbuf_seq_with_ipo(Scene *scene, struct Ipo *ipo)
-{
-       /* force update of all sequences with this ipo, on ipo changes */
-       Editing *ed= seq_give_editing(scene, FALSE);
-       Sequence *seq;
-
-       if(ed==NULL) return;
-
-       SEQ_BEGIN(ed, seq) {
-               if(seq->ipo == ipo) {
-                       update_changed_seq_and_deps(scene, seq, 0, 1);
-                       if(seq->type == SEQ_SPEED) {
-                               sequence_effect_speed_rebuild_map(seq, 1);
-                       }
-                       free_proxy_seq(seq);
-               }
-       }
-       SEQ_END
-}
-#endif
-
 /* seq funcs's for transforming internally
  notice the difference between start/end and left/right.
 
index c82595ee2b25bb796cd10ffaa27b5c95e79df526..4d1994e760b7b1a1ed7a4a2f002a2beea35d5aec 100644 (file)
@@ -3226,7 +3226,7 @@ static void get_scalar_from_vertexgroup(Object *ob, int vertID, short groupindex
 }
 
 /* Resetting a Mesh SB object's springs */
-/* Spring lenght are caculted from'raw' mesh vertices that are NOT altered by modifier stack. */
+/* Spring length are caculted from'raw' mesh vertices that are NOT altered by modifier stack. */
 static void springs_from_mesh(Object *ob)
 {
        SoftBody *sb;
@@ -3362,7 +3362,7 @@ static void mesh_to_softbody(Scene *scene, Object *ob)
                                add_2nd_order_springs(ob,sb->secondspring); /* exploits the the first run of build_bps_springlist(ob);*/
                                build_bps_springlist(ob); /* yes we need to do it again*/
                        }
-                       springs_from_mesh(ob); /* write the 'rest'-lenght of the springs */
+                       springs_from_mesh(ob); /* write the 'rest'-length of the springs */
                           if (ob->softflag & OB_SB_SELF) {calculate_collision_balls(ob);}
 
                }
index 4d1911e8be8c80c73e811af075e3c3d98da1e1dc..fd0829ebe3b4440882992e9dd2bd2f6f3a2037af 100644 (file)
@@ -1225,7 +1225,7 @@ static int point_in_slice_as(float p[3],float origin[3],float normal[3])
        return 1;
 }
 
-/*mama (knowing the squared lenght of the normal)*/
+/*mama (knowing the squared length of the normal)*/
 static int point_in_slice_m(float p[3],float origin[3],float normal[3],float lns)
 {
        float h,rp[3];
index de2a3cd47cc5a8d40315f38f7575a584757a5236..3514eb91dd5c4d7da0ac04fe6fe3364c80367918 100644 (file)
@@ -10853,12 +10853,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        }
        
 
-       /* put 2.50 compatibility code here until next subversion bump */
+       if (main->versionfile < 253)
        {
                Object *ob;
                Scene *scene;
                bScreen *sc;
                Tex *tex;
+               Brush *brush;
 
                for (sc= main->screen.first; sc; sc= sc->id.next) {
                        ScrArea *sa;
@@ -10974,12 +10975,9 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                SEQ_END
                        }
                }
-       }
 
-       {
                /* GSOC 2010 Sculpt - New settings for Brush */
 
-               Brush *brush;
                for (brush= main->brush.first; brush; brush= brush->id.next) {
                        /* Sanity Check */
 
@@ -11052,6 +11050,25 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
 
+       /* GSOC Sculpt 2010 - Sanity check on Sculpt/Paint settings */
+       if (main->versionfile < 253) {
+               Scene *sce;
+               for (sce= main->scene.first; sce; sce= sce->id.next) {
+                       if (sce->toolsettings->sculpt_paint_unified_alpha == 0)
+                               sce->toolsettings->sculpt_paint_unified_alpha = 0.5f;
+
+                       if (sce->toolsettings->sculpt_paint_unified_unprojected_radius == 0) 
+                               sce->toolsettings->sculpt_paint_unified_unprojected_radius = 0.125f;
+
+                       if (sce->toolsettings->sculpt_paint_unified_size == 0)
+                               sce->toolsettings->sculpt_paint_unified_size = 35;
+               }
+       }
+
+       /* put compatibility code here until next subversion bump */
+       {
+       }
+
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
        /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */
 
index 902f572b2f3cd6ebaa2453d111526c8a0f9f02a0..bee1b0a5388fee21f2dede2f7fbee5c1ff0cb419 100644 (file)
@@ -1423,7 +1423,7 @@ static void write_curves(WriteData *wd, ListBase *idbase)
                        
                        if(cu->vfont) {
                                writedata(wd, DATA, amount_of_chars(cu->str)+1, cu->str);
-                               writestruct(wd, DATA, "CharInfo", cu->len, cu->strinfo);
+                               writestruct(wd, DATA, "CharInfo", cu->len+1, cu->strinfo);
                                writestruct(wd, DATA, "TextBox", cu->totbox, cu->tb);                           
                        }
                        else {
index 1c06266a148685e27cce88132462bc906edff53d..301111d22fd913191c1103c0035d36fb6a3ac8df 100644 (file)
@@ -43,6 +43,7 @@
 #include "DNA_constraint_types.h"
 #include "DNA_scene_types.h"
 
+#include "BKE_main.h"
 #include "BKE_animsys.h"
 #include "BKE_action.h"
 #include "BKE_context.h"
@@ -589,7 +590,7 @@ void ANIM_keyingset_info_register (const bContext *C, KeyingSetInfo *ksi)
 /* Remove the given KeyingSetInfo from the list of type infos, and also remove the builtin set if appropriate */
 void ANIM_keyingset_info_unregister (const bContext *C, KeyingSetInfo *ksi)
 {
-       Scene *scene = CTX_data_scene(C);
+       Main *bmain= CTX_data_main(C);
        KeyingSet *ks, *ksn;
        
        /* find relevant builtin KeyingSets which use this, and remove them */
@@ -600,8 +601,14 @@ void ANIM_keyingset_info_unregister (const bContext *C, KeyingSetInfo *ksi)
                
                /* remove if matching typeinfo name */
                if (strcmp(ks->typeinfo, ksi->idname) == 0) {
+                       Scene *scene;
                        BKE_keyingset_free(ks);
-                       BLI_freelinkN(&scene->keyingsets, ks);
+                       BLI_remlink(&builtin_keyingsets, ks);
+
+                       for(scene= bmain->scene.first; scene; scene= scene->id.next)
+                               BLI_remlink_safe(&scene->keyingsets, ks);
+
+                       MEM_freeN(ks);
                }
        }
        
index 0cf6ce3656e7a25b0cd75ed39bbacd9ca1c34fcd..f8e793bd1781f99a354c2e27db6babdc15c41fb6 100644 (file)
@@ -4095,7 +4095,7 @@ void ARMATURE_OT_select_all(wmOperatorType *ot)
 {
        
        /* identifiers */
-       ot->name= "deselect all editbone";
+       ot->name= "Select or Deselect All";
        ot->idname= "ARMATURE_OT_select_all";
        
        /* api callbacks */
@@ -5213,7 +5213,7 @@ void POSE_OT_select_all(wmOperatorType *ot)
 {
        
        /* identifiers */
-       ot->name= "deselect all bones";
+       ot->name= "Select or Deselect All";
        ot->idname= "POSE_OT_select_all";
        
        /* api callbacks */
index 659ee7b9cea4fb47b283f12d664007527706f3c3..8d8dac33f9f1c66eeee66bb8fe1f2e3a83d488fc 100644 (file)
@@ -42,6 +42,7 @@
 #include "BLI_math.h"
 #include "BLI_dynstr.h"
 #include "BLI_rand.h"
+#include "BLI_ghash.h"
 
 #include "DNA_key_types.h"
 #include "DNA_object_types.h"
@@ -69,6 +70,7 @@
 #include "ED_types.h"
 #include "ED_util.h"
 #include "ED_view3d.h"
+#include "ED_curve.h"
 
 #include "UI_interface.h"
 
 typedef struct {
        ListBase nubase;
        void *lastsel;
+       GHash *undoIndex;
 } UndoCurve;
 
+/* Definitions needed for shape keys */
+typedef struct {
+       void *origNode;
+       int index;
+} NodeKeyIndex;
+
 void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatus);
 static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short selstatus);
 
@@ -96,7 +105,7 @@ ListBase *curve_get_editcurve(Object *ob)
 {
        if(ob && ELEM(ob->type, OB_CURVE, OB_SURF)) {
                Curve *cu= ob->data;
-               return cu->editnurb;
+               return &cu->editnurb->nurbs;
        }
        return NULL;
 }
@@ -108,15 +117,18 @@ void set_actNurb(Object *obedit, Nurb *nu)
        
        if(nu==NULL)
                cu->actnu = -1;
-       else
-               cu->actnu = BLI_findindex(cu->editnurb, nu);
+       else {
+               ListBase *nurbs= ED_curve_editnurbs(cu);
+               cu->actnu = BLI_findindex(nurbs, nu);
+       }
 }
 
 Nurb *get_actNurb(Object *obedit)
 {
        Curve *cu= obedit->data;
-       
-       return BLI_findlink(cu->editnurb, cu->actnu);
+       ListBase *nurbs= ED_curve_editnurbs(cu);
+
+       return BLI_findlink(nurbs, cu->actnu);
 }
 
 /* ******************* SELECTION FUNCTIONS ********************* */
@@ -258,6 +270,688 @@ void printknots(Object *obedit)
        }
 }
 
+/* ********************* Shape keys *************** */
+
+static NodeKeyIndex *init_nodeKeyIndex(void *node, int index)
+{
+       NodeKeyIndex *nodeIndex = MEM_callocN(sizeof(NodeKeyIndex), "init_nodeKeyIndex");
+
+       nodeIndex->origNode= node;
+       nodeIndex->index= index;
+
+       return nodeIndex;
+}
+
+static void free_nodeKeyIndex(NodeKeyIndex *pointIndex)
+{
+       MEM_freeN(pointIndex);
+}
+
+static void init_editNurb_keyIndex(EditNurb *editnurb, ListBase *origBase)
+{
+       Nurb *nu= editnurb->nurbs.first;
+       Nurb *orignu= origBase->first;
+       GHash *gh;
+       BezTriple *bezt, *origbezt;
+       BPoint *bp, *origbp;
+       int a, keyindex= 0;
+
+       gh= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "editNurb keyIndex");
+
+       while (orignu) {
+               if (orignu->bezt) {
+                       a= orignu->pntsu;
+                       bezt= nu->bezt;
+                       origbezt= orignu->bezt;
+                       while (a--) {
+                               BLI_ghash_insert(gh, bezt, init_nodeKeyIndex(origbezt, keyindex));
+                               keyindex+= 12;
+                               bezt++;
+                               origbezt++;
+                       }
+               } else {
+                       a= orignu->pntsu * orignu->pntsv;
+                       bp= nu->bp;
+                       origbp= orignu->bp;
+                       while (a--) {
+                               BLI_ghash_insert(gh, bp, init_nodeKeyIndex(origbp, keyindex));
+                               keyindex+= 4;
+                               bp++;
+                               origbp++;
+                       }
+               }
+
+               nu= nu->next;
+               orignu= orignu->next;
+       }
+
+       editnurb->keyindex= gh;
+}
+
+static void free_editNurb_keyIndex(EditNurb *editnurb)
+{
+       if (!editnurb->keyindex) {
+               return;
+       }
+       BLI_ghash_free(editnurb->keyindex, NULL, (GHashValFreeFP)free_nodeKeyIndex);
+}
+
+static NodeKeyIndex *getNodeKeyIndex(EditNurb *editnurb, void *node)
+{
+       return BLI_ghash_lookup(editnurb->keyindex, node);
+}
+
+static BezTriple *getKeyIndexOrig_bezt(EditNurb *editnurb, void *node)
+{
+       NodeKeyIndex *index= getNodeKeyIndex(editnurb, node);
+
+       if (!index) {
+               return NULL;
+       }
+
+       return (BezTriple*)index->origNode;
+}
+
+static BPoint *getKeyIndexOrig_bp(EditNurb *editnurb, void *node)
+{
+       NodeKeyIndex *index= getNodeKeyIndex(editnurb, node);
+
+       if (!index) {
+               return NULL;
+       }
+
+       return (BPoint*)index->origNode;
+}
+
+static int getKeyIndexOrig_index(EditNurb *editnurb, void *node)
+{
+       NodeKeyIndex *index= getNodeKeyIndex(editnurb, node);
+
+       if (!index) {
+               return -1;
+       }
+
+       return index->index;
+}
+
+static void keyIndex_delNode(EditNurb *editnurb, void *node)
+{
+       if (!editnurb->keyindex) {
+               return;
+       }
+
+       BLI_ghash_remove(editnurb->keyindex, node, NULL, (GHashValFreeFP)free_nodeKeyIndex);
+}
+
+static void keyIndex_delBezt(EditNurb *editnurb, BezTriple *bezt)
+{
+       keyIndex_delNode(editnurb, bezt);
+}
+
+static void keyIndex_delBP(EditNurb *editnurb, BPoint *bp)
+{
+       keyIndex_delNode(editnurb, bp);
+}
+
+static void keyIndex_delNurb(EditNurb *editnurb, Nurb *nu)
+{
+       int a;
+
+       if (nu->bezt) {
+               BezTriple *bezt= nu->bezt;
+               a= nu->pntsu;
+
+               while (a--) {
+                       BLI_ghash_remove(editnurb->keyindex, bezt, NULL, (GHashValFreeFP)free_nodeKeyIndex);
+                       ++bezt;
+               }
+       } else {
+               BPoint *bp= nu->bp;
+               a= nu->pntsu * nu->pntsv;
+
+               while (a--) {
+                       BLI_ghash_remove(editnurb->keyindex, bp, NULL, (GHashValFreeFP)free_nodeKeyIndex);
+                       ++bp;
+               }
+       }
+}
+
+static void keyIndex_delNurbList(EditNurb *editnurb, ListBase *nubase)
+{
+       Nurb *nu= nubase->first;
+
+       while (nu) {
+               keyIndex_delNurb(editnurb, nu);
+
+               nu= nu->next;
+       }
+}
+
+static void keyIndex_updateNode(EditNurb *editnurb, char *node,
+       char *newnode, int count, int size, int search)
+{
+       int i;
+       NodeKeyIndex *index;
+
+       if (editnurb->keyindex == NULL) {
+               /* No shape keys - updating not needed */
+               return;
+       }
+
+       for (i = 0; i < count; i++) {
+               for (;;) {
+                       index= getNodeKeyIndex(editnurb, node);
+                       if (!search || index) {
+                               break;
+                       }
+                       node += size;
+               }
+
+               BLI_ghash_remove(editnurb->keyindex, node, NULL, NULL);
+
+               if (index) {
+                       BLI_ghash_insert(editnurb->keyindex, newnode, index);
+               }
+
+               newnode += size;
+               node += size;
+       }
+}
+
+static void keyIndex_updateBezt(EditNurb *editnurb, BezTriple *bezt,
+       BezTriple *newbezt, int count, int search)
+{
+       keyIndex_updateNode(editnurb, (char*)bezt, (char*)newbezt, count, sizeof(BezTriple), search);
+}
+
+static void keyIndex_updateBP(EditNurb *editnurb, BPoint *bp,
+       BPoint *newbp, int count, int search)
+{
+       keyIndex_updateNode(editnurb, (char*)bp, (char*)newbp, count, sizeof(BPoint), search);
+}
+
+static void keyIndex_updateNurb(EditNurb *editnurb, Nurb *nu, Nurb *newnu)
+{
+       if (nu->bezt) {
+               keyIndex_updateBezt(editnurb, nu->bezt, newnu->bezt, newnu->pntsu, 0);
+       } else {
+               keyIndex_updateBP(editnurb, nu->bp, newnu->bp, newnu->pntsu * newnu->pntsv, 0);
+       }
+}
+
+static void keyIndex_swap(EditNurb *editnurb, void *a, void *b)
+{
+       NodeKeyIndex *index1= getNodeKeyIndex(editnurb, a);
+       NodeKeyIndex *index2= getNodeKeyIndex(editnurb, b);
+
+       BLI_ghash_remove(editnurb->keyindex, a, NULL, NULL);
+       BLI_ghash_remove(editnurb->keyindex, b, NULL, NULL);
+
+       BLI_ghash_insert(editnurb->keyindex, a, index2);
+       BLI_ghash_insert(editnurb->keyindex, b, index1);
+}
+
+static void keyIndex_switchDirection(EditNurb *editnurb, Nurb *nu)
+{
+       int a;
+
+       if (nu->bezt) {
+               BezTriple *bezt1, *bezt2;
+
+               a= nu->pntsu;
+
+               bezt1= nu->bezt;
+               bezt2= bezt1+(a-1);
+
+               if (a & 1) ++a;
+
+               a/=2;
+
+               while (a--) {
+                       if (bezt1 != bezt2) {
+                               keyIndex_swap(editnurb, bezt1, bezt2);
+                       }
+
+                       bezt1++;
+                       bezt2--;
+               }
+       } else {
+               BPoint *bp1, *bp2;
+
+               if (nu->pntsv == 1) {
+                       a= nu->pntsu;
+                       bp1= nu->bp;
+                       bp2= bp1+(a-1);
+                       a/= 2;
+                       while(bp1!=bp2 && a>0) {
+                               if (bp1 != bp2) {
+                                       keyIndex_swap(editnurb, bp1, bp2);
+                               }
+
+                               a--;
+                               bp1++;
+                               bp2--;
+                       }
+               } else {
+                       int b;
+
+                       for(b=0; b<nu->pntsv; b++) {
+
+                               bp1= nu->bp+b*nu->pntsu;
+                               a= nu->pntsu;
+                               bp2= bp1+(a-1);
+                               a/= 2;
+
+                               while(bp1!=bp2 && a>0) {
+                                       if (bp1 != bp2) {
+                                               keyIndex_swap(editnurb, bp1, bp2);
+                                       }
+
+                                       a--;
+                                       bp1++;
+                                       bp2--;
+                               }
+                       }
+
+               }
+       }
+}
+
+static void switch_keys_direction(Curve *cu, Nurb *actnu)
+{
+       KeyBlock *currkey;
+       ListBase *nubase= &cu->editnurb->nurbs;
+       Nurb *nu;
+       float *fp;
+       int a;
+
+       currkey = cu->key->block.first;
+       while(currkey) {
+               fp= currkey->data;
+
+               nu= nubase->first;
+               while (nu) {
+                       if (nu->bezt) {
+                               a= nu->pntsu;
+                               if (nu == actnu) {
+                                       while (a--) {
+                                               swap_v3_v3(fp, fp + 6);
+                                               *(fp+9) = -*(fp+9);
+                                               fp += 12;
+                                       }
+                               } else fp += a * 12;
+                       } else {
+                               a= nu->pntsu * nu->pntsv;
+                               if (nu == actnu) {
+                                       while (a--) {
+                                               *(fp+3) = -*(fp+3);
+                                               fp += 4;
+                                       }
+                               } else fp += a * 4;
+                       }
+
+                       nu= nu->next;
+               }
+
+               currkey= currkey->next;
+       }
+}
+
+static void keyData_switchDirectionNurb(Curve *cu, Nurb *nu)
+{
+       EditNurb *editnurb= cu->editnurb;
+
+       if (!editnurb->keyindex) {
+               /* no shape keys - nothing to do */
+               return;
+       }
+
+       keyIndex_switchDirection(editnurb, nu);
+       switch_keys_direction(cu, nu);
+}
+
+static GHash *dupli_keyIndexHash(GHash *keyindex)
+{
+       GHash *gh;
+       GHashIterator *hashIter;
+
+       gh= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "dupli_keyIndex gh");
+
+       for(hashIter = BLI_ghashIterator_new(keyindex);
+                                  !BLI_ghashIterator_isDone(hashIter);
+                                  BLI_ghashIterator_step(hashIter)) {
+               void *node = BLI_ghashIterator_getKey(hashIter);
+               NodeKeyIndex *index = BLI_ghashIterator_getValue(hashIter);
+               NodeKeyIndex *newIndex = MEM_callocN(sizeof(NodeKeyIndex), "dupli_keyIndexHash index");
+
+               memcpy(newIndex, index, sizeof(NodeKeyIndex));
+
+               BLI_ghash_insert(gh, node, newIndex);
+       }
+
+       BLI_ghashIterator_free(hashIter);
+
+       return gh;
+}
+
+static void key_to_bezt(float *key, BezTriple *basebezt, BezTriple *bezt)
+{
+       memcpy(bezt, basebezt, sizeof(BezTriple));
+       memcpy(bezt->vec, key, sizeof(float) * 9);
+       bezt->alfa= key[9];
+}
+
+static void bezt_to_key(BezTriple *bezt, float *key)
+{
+        memcpy(key, bezt->vec, sizeof(float) * 9);
+        key[9] = bezt->alfa;
+}
+
+static void calc_keyHandles(ListBase *nurb, float *key)
+{
+       Nurb *nu;
+       int a;
+       float *fp= key;
+       BezTriple *bezt;
+
+       nu= nurb->first;
+       while (nu) {
+               if (nu->bezt) {
+                       BezTriple *prevp, *nextp;
+                       BezTriple cur, prev, next;
+                       float *startfp, *prevfp, *nextfp;
+
+                       bezt= nu->bezt;
+                       a= nu->pntsu;
+                       startfp= fp;
+
+                       if(nu->flagu & CU_NURB_CYCLIC) {
+                               prevp= bezt+(a-1);
+                               prevfp= fp+(12 * (a-1));
+                       } else {
+                               prevp= NULL;
+                               prevfp= NULL;
+                       }
+
+                       nextp= bezt + 1;
+                       nextfp= fp + 12;
+
+                       while (a--) {
+                               key_to_bezt(fp, bezt, &cur);
+
+                               if (nextp) key_to_bezt(nextfp, nextp, &next);
+                               if (prevp) key_to_bezt(prevfp, prevp, &prev);
+
+                               calchandleNurb(&cur, prevp ? &prev : NULL, nextp ? &next : NULL, 0);
+                               bezt_to_key(&cur, fp);
+
+                               prevp= bezt;
+                               prevfp= fp;
+                               if(a==1) {
+                                       if(nu->flagu & CU_NURB_CYCLIC) {
+                                               nextp= nu->bezt;
+                                               nextfp= startfp;
+                                       } else {
+                                               nextp= NULL;
+                                               nextfp= NULL;
+                                       }
+                               }
+                               else {
+                                       ++nextp;
+                                       nextfp += 12;;
+                               }
+
+                               ++bezt;
+                               fp += 12;
+                       }
+               } else {
+                       a= nu->pntsu * nu->pntsv;
+                       fp += a * 4;
+               }
+
+               nu= nu->next;
+       }
+}
+
+static void calc_shapeKeys(Object *obedit)
+{
+       Curve *cu= (Curve*)obedit->data;
+
+       /* are there keys? */
+       if(cu->key) {
+               int a, i, j;
+               EditNurb *editnurb= cu->editnurb;
+               KeyBlock *currkey;
+               KeyBlock *actkey= ob_get_keyblock(obedit);
+               BezTriple *bezt, *oldbezt;
+               BPoint *bp, *oldbp;
+               Nurb *nu;
+               int totvert= count_curveverts(&editnurb->nurbs);
+
+               float (*ofs)[3] = NULL;
+               float *oldkey, *newkey, *fp, *ofp;
+
+               /* editing the base key should update others */
+               if(cu->key->type==KEY_RELATIVE) {
+                       int act_is_basis = 0;
+                       /* find if this key is a basis for any others */
+                       for(currkey = cu->key->block.first; currkey; currkey= currkey->next) {
+                               if(obedit->shapenr-1 == currkey->relative) {
+                                       act_is_basis = 1;
+                                       break;
+                               }
+                       }
+
+                       if(act_is_basis) { /* active key is a base */
+                               int j;
+                               int totvec= 0;
+
+                               /* Calculate needed memory to store offset */
+                               nu= editnurb->nurbs.first;
+                               while(nu) {
+                                       if (nu->bezt) {
+                                               /* Three vects to store handles and one for alfa */
+                                               totvec+= nu->pntsu * 4;
+                                       } else {
+                                               totvec+= 2 * nu->pntsu * nu->pntsv;
+                                       }
+
+                                       nu= nu->next;
+                               }
+
+                               ofs= MEM_callocN(sizeof(float) * 3 * totvec,  "currkey->data");
+                               nu= editnurb->nurbs.first;
+                               i= 0;
+                               while(nu) {
+                                       if(nu->bezt) {
+                                               bezt= nu->bezt;
+                                               a= nu->pntsu;
+                                               while(a--) {
+                                                       oldbezt= getKeyIndexOrig_bezt(editnurb, bezt);
+
+                                                       if (oldbezt) {
+                                                               for (j= 0; j < 3; ++j) {
+                                                                       VECSUB(ofs[i], bezt->vec[j], oldbezt->vec[j]);
+                                                                       i++;
+                                                                       fp+= 3;
+                                                               }
+                                                               ofs[i++][0]= bezt->alfa - oldbezt->alfa;
+                                                       } else {
+                                                               i += 4;
+                                                       }
+                                                       bezt++;
+                                               }
+                                       }
+                                       else {
+                                               bp= nu->bp;
+                                               a= nu->pntsu*nu->pntsv;
+                                               while(a--) {
+                                                       oldbp= getKeyIndexOrig_bp(editnurb, bp);
+                                                       if (oldbp) {
+                                                               VECSUB(ofs[i], bp->vec, oldbp->vec);
+                                                               ofs[i+1][0]= bp->alfa - oldbp->alfa;
+                                                       }
+                                                       i += 2;
+                                                       ++bp;
+                                                       fp += 4;
+                                               }
+                                       }
+
+                                       nu= nu->next;
+                               }
+                       }
+               }
+
+               currkey = cu->key->block.first;
+               while(currkey) {
+                       int apply_offset = (ofs && (currkey != actkey) && (obedit->shapenr-1 == currkey->relative));
+
+                       fp= newkey= MEM_callocN(cu->key->elemsize * totvert,  "currkey->data");
+                       ofp= oldkey = currkey->data;
+
+                       nu= editnurb->nurbs.first;
+                       i = 0;
+                       while(nu) {
+                               if(currkey == actkey) {
+                                       int restore= actkey != cu->key->refkey;
+
+                                       if(nu->bezt) {
+                                               bezt= nu->bezt;
+                                               a= nu->pntsu;
+                                               while(a--) {
+                                                       oldbezt= getKeyIndexOrig_bezt(editnurb, bezt);
+
+                                                       for (j= 0; j < 3; ++j, ++i) {
+                                                               VECCOPY(fp, bezt->vec[j]);
+
+                                                               if (restore && oldbezt) {
+                                                                       VECCOPY(bezt->vec[j], oldbezt->vec[j]);
+                                                               }
+
+                                                               fp+= 3;
+                                                       }
+                                                       fp[0]= bezt->alfa;
+
+                                                       if(restore && oldbezt) {
+                                                               bezt->alfa= oldbezt->alfa;
+                                                       }
+
+                                                       fp+= 3; ++i;/* alphas */
+                                                       ++bezt;
+                                               }
+                                       }
+                                       else {
+                                               bp= nu->bp;
+                                               a= nu->pntsu*nu->pntsv;
+                                               while(a--) {
+                                                       oldbp= getKeyIndexOrig_bp(editnurb, bp);
+
+                                                       VECCOPY(fp, bp->vec);
+
+                                                       fp[3]= bp->alfa;
+
+                                                       if(restore && oldbp) {
+                                                               VECCOPY(bp->vec, oldbp->vec);
+                                                               bp->alfa= oldbp->alfa;
+                                                       }
+
+                                                       fp+= 4;
+                                                       ++bp;
+                                                       i+=2;
+                                               }
+                                       }
+                               }
+                               else {
+                                       int index;
+                                       float *curofp;
+
+                                       if(oldkey) {
+                                               if(nu->bezt) {
+                                                       bezt= nu->bezt;
+                                                       a= nu->pntsu;
+
+                                                       while(a--) {
+                                                               index= getKeyIndexOrig_index(editnurb, bezt);
+                                                               if (index >= 0) {
+                                                                       curofp= ofp + index;
+
+                                                                       for (j= 0; j < 3; ++j, ++i) {
+                                                                               VECCOPY(fp, curofp);
+
+                                                                               if(apply_offset) {
+                                                                                       VECADD(fp, fp, ofs[i]);
+                                                                               }
+
+                                                                               fp+= 3; curofp+= 3;
+                                                                       }
+                                                                       fp[0]= ofp[0];
+
+                                                                       if(apply_offset) {
+                                                                               /* apply alfa offsets */
+                                                                               VECADD(fp, fp, ofs[i]);
+                                                                               ++i;
+                                                                       }
+
+                                                                       fp+= 3; curofp+= 3;     /* alphas */
+                                                               } else {
+                                                                       for (j= 0; j < 3; ++j, ++i) {
+                                                                               VECCOPY(fp, bezt->vec[j]);
+                                                                               fp+= 3;
+                                                                       }
+                                                                       fp[0]= bezt->alfa;
+
+                                                                       fp+= 3; /* alphas */
+                                                               }
+                                                               ++bezt;
+                                                       }
+                                               }
+                                               else {
+                                                       bp= nu->bp;
+                                                       a= nu->pntsu*nu->pntsv;
+                                                       while(a--) {
+                                                               index= getKeyIndexOrig_index(editnurb, bp);
+
+                                                               if (index >= 0) {
+                                                                       curofp= ofp + index;
+                                                                       VECCOPY(fp, curofp);
+                                                                       fp[3]= curofp[4];
+
+                                                                       if(apply_offset) {
+                                                                               VECADD(fp, fp, ofs[i]);
+                                                                               fp[3]+=ofs[i+1][0];
+                                                                       }
+                                                               } else {
+                                                                       VECCOPY(fp, bp->vec);
+                                                                       fp[3]= bp->alfa;
+                                                               }
+
+                                                               fp+= 4;
+                                                               ++bp;
+                                                               i+=2;
+                                                       }
+                                               }
+                                       }
+                               }
+
+                               nu= nu->next;
+                       }
+
+                       if (apply_offset) {
+                               /* handles could become malicious after offsets applying */
+                               calc_keyHandles(&editnurb->nurbs, newkey);
+                       }
+
+                       currkey->totelem= totvert;
+                       if(currkey->data) MEM_freeN(currkey->data);
+                       currkey->data = newkey;
+
+                       currkey= currkey->next;
+               }
+
+               if(ofs) MEM_freeN(ofs);
+       }
+}
+
 /* ********************* LOAD and MAKE *************** */
 
 /* load editNurb in object */
@@ -272,48 +966,32 @@ void load_editNurb(Object *obedit)
        if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
                Curve *cu= obedit->data;
                Nurb *nu, *newnu;
-               KeyBlock *actkey;
-               int totvert= count_curveverts(editnurb);
+               ListBase newnurb= {NULL, NULL}, oldnurb= cu->nurb;
 
-               /* are there keys? */
-               actkey = ob_get_keyblock(obedit);
-               if(actkey) {
-                       /* active key: the vertices */
-                       
-                       if(totvert) {
-                               if(actkey->data) MEM_freeN(actkey->data);
-                       
-                               actkey->data= MEM_callocN(cu->key->elemsize*totvert, "actkey->data");
-                               actkey->totelem= totvert;
-               
-                               curve_to_key(cu, actkey, editnurb);
-                       }
-               }
-               
-               if(cu->key && actkey!=cu->key->refkey) {
-                       ;
-               }
-               else {
-                       freeNurblist(&(cu->nurb));
-                       
-                       for(nu= editnurb->first; nu; nu= nu->next) {
-                               newnu= duplicateNurb(nu);
-                               BLI_addtail(&(cu->nurb), newnu);
-                               
-                               if(nu->type == CU_NURBS) {
-                                       clamp_nurb_order_u(nu);
-                               }
+               for(nu= editnurb->first; nu; nu= nu->next) {
+                       newnu= duplicateNurb(nu);
+                       BLI_addtail(&newnurb, newnu);
+
+                       if(nu->type == CU_NURBS) {
+                               clamp_nurb_order_u(nu);
                        }
                }
+
+               cu->nurb= newnurb;
+
+               calc_shapeKeys(obedit);
+
+               freeNurblist(&oldnurb);
        }
-       
+
        set_actNurb(obedit, NULL);
 }
 
 /* make copy in cu->editnurb */
 void make_editNurb(Object *obedit)
 {
-       ListBase *editnurb= curve_get_editcurve(obedit);
+       Curve *cu= (Curve*)obedit->data;
+       EditNurb *editnurb= cu->editnurb;
        Nurb *nu, *newnu, *nu_act= NULL;
        KeyBlock *actkey;
 
@@ -322,20 +1000,29 @@ void make_editNurb(Object *obedit)
        set_actNurb(obedit, NULL);
 
        if (ELEM(obedit->type, OB_CURVE, OB_SURF)) {
-               Curve *cu= obedit->data;
-               
-               if(editnurb)
-                       freeNurblist(editnurb);
-               else
-                       editnurb= cu->editnurb= MEM_callocN(sizeof(ListBase), "editnurb");
-               
+               actkey = ob_get_keyblock(obedit);
+               if(actkey) {
+                       // XXX strcpy(G.editModeTitleExtra, "(Key) ");
+                       undo_editmode_clear();
+                       key_to_curve(actkey, cu, &cu->nurb);
+               }
+
+               if(editnurb) {
+                       freeNurblist(&editnurb->nurbs);
+                       free_editNurb_keyIndex(editnurb);
+                       editnurb->keyindex= NULL;
+               } else {
+                       editnurb= MEM_callocN(sizeof(EditNurb), "editnurb");
+                       cu->editnurb= editnurb;
+               }
+
                nu= cu->nurb.first;
                cu->lastsel= NULL;   /* for select row */
-               
+
                while(nu) {
                        newnu= duplicateNurb(nu);
                        test2DNurb(newnu);      // after join, or any other creation of curve
-                       BLI_addtail(editnurb, newnu);
+                       BLI_addtail(&editnurb->nurbs, newnu);
 
                        if (nu_act == NULL && isNurbsel(nu)) {
                                nu_act= newnu;
@@ -344,26 +1031,30 @@ void make_editNurb(Object *obedit)
 
                        nu= nu->next;
                }
-               
-               actkey = ob_get_keyblock(obedit);
+
                if(actkey) {
-                       // XXX strcpy(G.editModeTitleExtra, "(Key) ");
-                       key_to_curve(actkey, cu, editnurb);
+                       init_editNurb_keyIndex(editnurb, &cu->nurb);
                }
        }
 }
 
-void free_editNurb(Object *obedit)
+void free_curve_editNurb (Curve *cu)
 {
-       Curve *cu= obedit->data;
-
        if(cu->editnurb) {
-               freeNurblist(cu->editnurb);
+               freeNurblist(&cu->editnurb->nurbs);
+               free_editNurb_keyIndex(cu->editnurb);
                MEM_freeN(cu->editnurb);
                cu->editnurb= NULL;
        }
 }
 
+void free_editNurb(Object *obedit)
+{
+       Curve *cu= obedit->data;
+
+       free_curve_editNurb(cu);
+}
+
 void CU_deselect_all(Object *obedit)
 {
        ListBase *editnurb= curve_get_editcurve(obedit);
@@ -433,7 +1124,7 @@ static int separate_exec(bContext *C, wmOperator *op)
        Object *oldob, *newob;
        Base *oldbase, *newbase;
        Curve *oldcu, *newcu;
-       ListBase *oldedit, *newedit;
+       EditNurb *oldedit, *newedit;
 
        oldbase= CTX_data_active_base(C);
        oldob= oldbase->object;
@@ -459,15 +1150,16 @@ static int separate_exec(bContext *C, wmOperator *op)
        /* 2. put new object in editmode and clear it */
        make_editNurb(newob);
        newedit= newcu->editnurb;
-       freeNurblist(newedit);
+       freeNurblist(&newedit->nurbs);
+       free_editNurb_keyIndex(newedit);
 
        /* 3. move over parts from old object */
-       for(nu= oldedit->first; nu; nu=nu1) {
+       for(nu= oldedit->nurbs.first; nu; nu=nu1) {
                nu1= nu->next;
 
                if(isNurbsel(nu)) {
-                       BLI_remlink(oldedit, nu);
-                       BLI_addtail(newedit, nu);
+                       BLI_remlink(&oldedit->nurbs, nu);
+                       BLI_addtail(&newedit->nurbs, nu);
                }
        }
 
@@ -679,6 +1371,7 @@ static int deleteflagNurb(bContext *C, wmOperator *op, int flag)
                }
                if(a==0) {
                        BLI_remlink(editnurb, nu);
+                       keyIndex_delNurb(cu->editnurb, nu);
                        freeNurb(nu); nu=NULL;
                }
                else {
@@ -707,10 +1400,13 @@ static int deleteflagNurb(bContext *C, wmOperator *op, int flag)
                                        if((bp->f1 & flag)==0) {
                                                memcpy(bpn, bp, nu->pntsu*sizeof(BPoint));
                                                bpn+= nu->pntsu;
+                                       } else {
+                                               keyIndex_delBP(cu->editnurb, bp);
                                        }
                                        bp+= nu->pntsu;
                                }
                                nu->pntsv= newv;
+                               keyIndex_updateBP(cu->editnurb, nu->bp, newbp, newv * nu->pntsu, 1);
                                MEM_freeN(nu->bp);
                                nu->bp= newbp;
                                clamp_nurb_order_v(nu);
@@ -744,9 +1440,12 @@ static int deleteflagNurb(bContext *C, wmOperator *op, int flag)
                                                        if((bp->f1 & flag)==0) {
                                                                *bpn= *bp;
                                                                bpn++;
+                                                       } else {
+                                                               keyIndex_delBP(cu->editnurb, bp);
                                                        }
                                                }
                                        }
+                                       keyIndex_updateBP(cu->editnurb, nu->bp, newbp, newu * nu->pntsv, 1);
                                        MEM_freeN(nu->bp);
                                        nu->bp= newbp;
                                        if(newu==1 && nu->pntsv>1) {    /* make a U spline */
@@ -772,13 +1471,13 @@ static int deleteflagNurb(bContext *C, wmOperator *op, int flag)
 }
 
 /* only for OB_SURF */
-static short extrudeflagNurb(ListBase *editnurb, int flag)
+static short extrudeflagNurb(EditNurb *editnurb, int flag)
 {
        Nurb *nu;
        BPoint *bp, *bpn, *newbp;
        int ok= 0, a, u, v, len;
 
-       nu= editnurb->first;
+       nu= editnurb->nurbs.first;
        while(nu) {
 
                if(nu->pntsv==1) {
@@ -794,9 +1493,9 @@ static short extrudeflagNurb(ListBase *editnurb, int flag)
                                ok= 1;
                                newbp =
                                        (BPoint*)MEM_mallocN(2 * nu->pntsu * sizeof(BPoint), "extrudeNurb1");
-                               memcpy(newbp, nu->bp, nu->pntsu*sizeof(BPoint) );
+                               ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu);
                                bp= newbp+ nu->pntsu;
-                               memcpy(bp, nu->bp, nu->pntsu*sizeof(BPoint) );
+                               ED_curve_bpcpy(editnurb, bp, nu->bp, nu->pntsu);
                                MEM_freeN(nu->bp);
                                nu->bp= newbp;
                                a= nu->pntsu;
@@ -813,7 +1512,7 @@ static short extrudeflagNurb(ListBase *editnurb, int flag)
                        }
                }
                else {
-                       /* which row or collumn is selected */
+                       /* which row or column is selected */
 
                        if( isNurbselUV(nu, &u, &v, flag) ) {
 
@@ -832,14 +1531,14 @@ static short extrudeflagNurb(ListBase *editnurb, int flag)
                                                                                  * sizeof(BPoint), "extrudeNurb1");
                                        if(u==0) {
                                                len= nu->pntsv*nu->pntsu;
-                                               memcpy(newbp+nu->pntsu, nu->bp, len*sizeof(BPoint) );
-                                               memcpy(newbp, nu->bp, nu->pntsu*sizeof(BPoint) );
+                                               ED_curve_bpcpy(editnurb, newbp+nu->pntsu, nu->bp, len);
+                                               ED_curve_bpcpy(editnurb, newbp, nu->bp, nu->pntsu);
                                                bp= newbp;
                                        }
                                        else {
                                                len= nu->pntsv*nu->pntsu;
-                                               memcpy(newbp, nu->bp, len*sizeof(BPoint) );
-                                               memcpy(newbp+len, nu->bp+len-nu->pntsu, nu->pntsu*sizeof(BPoint) );
+                                               ED_curve_bpcpy(editnurb, newbp, nu->bp, len);
+                                               ED_curve_bpcpy(editnurb, newbp+len, nu->bp+len-nu->pntsu, nu->pntsu);
                                                bp= newbp+len;
                                        }
 
@@ -866,7 +1565,7 @@ static short extrudeflagNurb(ListBase *editnurb, int flag)
                                                        bpn->f1 |= flag;
                                                        bpn++;
                                                }
-                                               memcpy(bpn, bp, nu->pntsu*sizeof(BPoint));
+                                               ED_curve_bpcpy(editnurb, bpn, bp, nu->pntsu);
                                                bp+= nu->pntsu;
                                                bpn+= nu->pntsu;
                                                if(v== nu->pntsu-1) {
@@ -1068,13 +1767,16 @@ static void adduplicateflagNurb(Object *obedit, short flag)
 static int switch_direction_exec(bContext *C, wmOperator *op)
 {
        Object *obedit= CTX_data_edit_object(C);
-       ListBase *editnurb= curve_get_editcurve(obedit);
+       Curve *cu= (Curve*)obedit->data;
+       EditNurb *editnurb= cu->editnurb;
        Nurb *nu;
-       
-       for(nu= editnurb->first; nu; nu= nu->next)
-               if(isNurbsel(nu))
+
+       for(nu= editnurb->nurbs.first; nu; nu= nu->next)
+               if(isNurbsel(nu)) {
                        switchdirectionNurb(nu);
-       
+                       keyData_switchDirectionNurb(cu, nu);
+               }
+
        DAG_id_flush_update(obedit->data, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_GEOM|ND_DATA, obedit->data);
 
@@ -3004,7 +3706,7 @@ static int make_segment_exec(bContext *C, wmOperator *op)
        /* joins 2 curves */
        Object *obedit= CTX_data_edit_object(C);
        Curve *cu= obedit->data;
-       ListBase *editnurb= curve_get_editcurve(obedit);
+       ListBase *nubase= curve_get_editcurve(obedit);
        Nurb *nu, *nu1=0, *nu2=0;
        BezTriple *bezt;
        BPoint *bp;
@@ -3012,7 +3714,7 @@ static int make_segment_exec(bContext *C, wmOperator *op)
        int a;
 
        /* first decide if this is a surface merge! */
-       if(obedit->type==OB_SURF) nu= editnurb->first;
+       if(obedit->type==OB_SURF) nu= nubase->first;
        else nu= NULL;
        
        while(nu) {
@@ -3035,7 +3737,7 @@ static int make_segment_exec(bContext *C, wmOperator *op)
                return merge_nurb(C, op);
        
        /* find both nurbs and points, nu1 will be put behind nu2 */
-       for(nu= editnurb->first; nu; nu=