commit before doing some hefty shapekey change, will break compilation
authorJoseph Eagar <joeedh@gmail.com>
Sun, 1 Nov 2009 00:06:53 +0000 (00:06 +0000)
committerJoseph Eagar <joeedh@gmail.com>
Sun, 1 Nov 2009 00:06:53 +0000 (00:06 +0000)
226 files changed:
source/blender/blenkernel/BKE_animsys.h
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/BKE_curve.h
source/blender/blenkernel/BKE_global.h
source/blender/blenkernel/BKE_key.h
source/blender/blenkernel/BKE_material.h
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/BKE_modifier.h
source/blender/blenkernel/BKE_sequence.h
source/blender/blenkernel/intern/DerivedMesh.c
source/blender/blenkernel/intern/anim_sys.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/blender.c
source/blender/blenkernel/intern/curve.c
source/blender/blenkernel/intern/customdata.c
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/displist.c
source/blender/blenkernel/intern/key.c
source/blender/blenkernel/intern/lattice.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/modifier.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/object.c
source/blender/blenkernel/intern/paint.c
source/blender/blenkernel/intern/particle.c
source/blender/blenkernel/intern/particle_system.c
source/blender/blenkernel/intern/sequence.c
source/blender/blenkernel/intern/smoke.c
source/blender/blenkernel/intern/softbody.c
source/blender/blenlib/BLI_arithb.h
source/blender/blenlib/BLI_bfile.h
source/blender/blenlib/BLI_editVert.h
source/blender/blenlib/BLI_ghash.h
source/blender/blenlib/BLI_storage.h
source/blender/blenlib/BLI_util.h
source/blender/blenlib/BLI_winstuff.h
source/blender/blenlib/intern/BLI_bfile.c
source/blender/blenlib/intern/storage.c
source/blender/blenlib/intern/util.c
source/blender/blenlib/intern/winstuff.c
source/blender/blenloader/BLO_readfile.h
source/blender/blenloader/intern/readblenentry.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/readfile.h
source/blender/blenloader/intern/writefile.c
source/blender/bmesh/bmesh.h
source/blender/bmesh/intern/bmesh_opdefines.c
source/blender/bmesh/operators/mesh_conv.c
source/blender/editors/animation/anim_channels_defines.c
source/blender/editors/animation/anim_channels_edit.c
source/blender/editors/animation/anim_draw.c
source/blender/editors/animation/anim_filter.c
source/blender/editors/animation/anim_ops.c
source/blender/editors/animation/keyframes_edit.c
source/blender/editors/animation/keyframing.c
source/blender/editors/animation/keyingsets.c
source/blender/editors/armature/armature_ops.c
source/blender/editors/armature/editarmature.c
source/blender/editors/armature/poseobject.c
source/blender/editors/datafiles/B.blend.c
source/blender/editors/include/ED_anim_api.h
source/blender/editors/include/ED_keyframes_edit.h
source/blender/editors/include/ED_mesh.h
source/blender/editors/include/ED_object.h
source/blender/editors/include/ED_physics.h
source/blender/editors/include/ED_space_api.h
source/blender/editors/include/UI_icons.h
source/blender/editors/include/UI_interface.h
source/blender/editors/interface/Makefile
source/blender/editors/interface/SConscript
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_icons.c
source/blender/editors/interface/interface_layout.c
source/blender/editors/interface/interface_panel.c
source/blender/editors/interface/interface_regions.c
source/blender/editors/interface/interface_style.c
source/blender/editors/interface/interface_templates.c
source/blender/editors/mesh/bmeshutils.c
source/blender/editors/mesh/editface.c
source/blender/editors/mesh/editmesh.c
source/blender/editors/mesh/editmesh_add.c
source/blender/editors/mesh/editmesh_loop.c
source/blender/editors/mesh/editmesh_mods.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/mesh/loopcut.c
source/blender/editors/mesh/mesh_intern.h
source/blender/editors/mesh/mesh_ops.c
source/blender/editors/mesh/meshtools.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_edit.c
source/blender/editors/object/object_intern.h
source/blender/editors/object/object_modifier.c
source/blender/editors/object/object_ops.c
source/blender/editors/object/object_relations.c
source/blender/editors/object/object_select.c
source/blender/editors/object/object_shapekey.c
source/blender/editors/object/object_vgroup.c
source/blender/editors/physics/particle_edit.c
source/blender/editors/physics/particle_object.c
source/blender/editors/physics/physics_intern.h
source/blender/editors/physics/physics_ops.c
source/blender/editors/screen/screen_edit.c
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_utils.c
source/blender/editors/sculpt_paint/paint_vertex.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/space_action/action_draw.c
source/blender/editors/space_action/action_header.c
source/blender/editors/space_api/spacetypes.c
source/blender/editors/space_buttons/buttons_context.c
source/blender/editors/space_buttons/buttons_header.c
source/blender/editors/space_buttons/space_buttons.c
source/blender/editors/space_console/console_ops.c
source/blender/editors/space_file/file_draw.c
source/blender/editors/space_file/filesel.c
source/blender/editors/space_graph/graph_draw.c
source/blender/editors/space_graph/graph_edit.c
source/blender/editors/space_graph/graph_header.c
source/blender/editors/space_graph/graph_intern.h
source/blender/editors/space_graph/graph_ops.c
source/blender/editors/space_graph/space_graph.c
source/blender/editors/space_image/image_draw.c
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_image/space_image.c
source/blender/editors/space_nla/nla_header.c
source/blender/editors/space_nla/space_nla.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_node/node_edit.c
source/blender/editors/space_node/space_node.c
source/blender/editors/space_outliner/outliner.c
source/blender/editors/space_outliner/outliner_header.c [deleted file]
source/blender/editors/space_outliner/outliner_intern.h
source/blender/editors/space_outliner/outliner_ops.c
source/blender/editors/space_outliner/space_outliner.c
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/editors/space_sequencer/sequencer_ops.c
source/blender/editors/space_sequencer/sequencer_select.c
source/blender/editors/space_sequencer/space_sequencer.c
source/blender/editors/space_text/text_draw.c
source/blender/editors/space_text/text_ops.c
source/blender/editors/space_text/text_python.c
source/blender/editors/space_view3d/drawobject.c
source/blender/editors/space_view3d/drawvolume.c
source/blender/editors/space_view3d/space_view3d.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_header.c
source/blender/editors/space_view3d/view3d_select.c
source/blender/editors/space_view3d/view3d_view.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform.h
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_generics.c
source/blender/editors/transform/transform_ops.c
source/blender/editors/transform/transform_snap.c
source/blender/editors/uvedit/uvedit_unwrap_ops.c
source/blender/gpu/GPU_extensions.h
source/blender/gpu/intern/gpu_buffers.c
source/blender/gpu/intern/gpu_extensions.c
source/blender/gpu/intern/gpu_material.c
source/blender/gpu/intern/gpu_shader_material.glsl
source/blender/gpu/intern/gpu_shader_material.glsl.c
source/blender/makesdna/DNA_customdata_types.h
source/blender/makesdna/DNA_fileglobal_types.h
source/blender/makesdna/DNA_key_types.h
source/blender/makesdna/DNA_mesh_types.h
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesdna/DNA_object_types.h
source/blender/makesdna/DNA_scene_types.h
source/blender/makesdna/DNA_screen_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesdna/DNA_text_types.h
source/blender/makesdna/DNA_windowmanager_types.h
source/blender/makesrna/RNA_types.h
source/blender/makesrna/intern/makesrna.c
source/blender/makesrna/intern/rna_access.c
source/blender/makesrna/intern/rna_constraint.c
source/blender/makesrna/intern/rna_key.c
source/blender/makesrna/intern/rna_material.c
source/blender/makesrna/intern/rna_mesh.c
source/blender/makesrna/intern/rna_modifier.c
source/blender/makesrna/intern/rna_object.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_sculpt_paint.c
source/blender/makesrna/intern/rna_sequence.c
source/blender/makesrna/intern/rna_space.c
source/blender/makesrna/intern/rna_ui.c
source/blender/makesrna/intern/rna_ui_api.c
source/blender/makesrna/intern/rna_userdef.c
source/blender/makesrna/intern/rna_wm.c
source/blender/nodes/intern/CMP_nodes/CMP_defocus.c
source/blender/nodes/intern/CMP_nodes/CMP_image.c
source/blender/nodes/intern/CMP_util.c
source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c
source/blender/nodes/intern/TEX_nodes/TEX_output.c
source/blender/python/generic/matrix.c
source/blender/python/generic/vector.c
source/blender/python/intern/bpy_interface.c
source/blender/python/intern/bpy_rna.c
source/blender/render/SConscript
source/blender/render/intern/source/pipeline.c
source/blender/render/intern/source/rayshade.c
source/blender/render/intern/source/volume_precache.c
source/blender/render/intern/source/volumetric.c
source/blender/render/intern/source/zbuf.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/WM_types.h
source/blender/windowmanager/intern/wm.c
source/blender/windowmanager/intern/wm_cursors.c
source/blender/windowmanager/intern/wm_draw.c
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_files.c
source/blender/windowmanager/intern/wm_init_exit.c
source/blender/windowmanager/intern/wm_jobs.c
source/blender/windowmanager/intern/wm_keymap.c
source/blender/windowmanager/intern/wm_operators.c
source/blender/windowmanager/intern/wm_window.c
source/blender/windowmanager/wm.h
source/blender/windowmanager/wm_event_types.h
source/blender/windowmanager/wm_window.h

index cc5b4dfdcaf7ccfec48d2335430fb067e9216f4d..045095567bc91697715ff8d43d2ca20f08810509 100644 (file)
@@ -67,6 +67,7 @@ struct KeyingSet *BKE_keyingset_add(struct ListBase *list, const char name[], sh
 /* Add a destination to a KeyingSet */
 void BKE_keyingset_add_destination(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, short flag, short groupmode);
 
+/* Find the destination matching the criteria given */
 struct KS_Path *BKE_keyingset_find_destination(struct KeyingSet *ks, struct ID *id, const char group_name[], const char rna_path[], int array_index, int group_mode);
 
 /* Copy all KeyingSets in the given list */
@@ -78,6 +79,15 @@ void BKE_keyingset_free(struct KeyingSet *ks);
 /* Free all the KeyingSets in the given list */
 void BKE_keyingsets_free(struct ListBase *list);
 
+/* ************************************* */
+/* Path Fixing API */
+
+/* Fix all the paths for the given ID+AnimData */
+void BKE_animdata_fix_paths_rename(struct ID *owner_id, struct AnimData *adt, char *prefix, char *oldName, char *newName);
+
+/* Fix all the paths for the entire database... */
+void BKE_all_animdata_fix_paths_rename(char *prefix, char *oldName, char *newName);
+
 /* ************************************* */
 // TODO: overrides, remapping, and path-finding api's
 
index cbce20a4980842984fd9fabf0990ffcbb18787ab..e4a763a25d0949662592ac3c202c55f156dc22ab 100644 (file)
@@ -43,7 +43,7 @@ struct bContext;
 struct ReportList;
 
 #define BLENDER_VERSION                        250
-#define BLENDER_SUBVERSION             6
+#define BLENDER_SUBVERSION             7
 
 #define BLENDER_MINVERSION             250
 #define BLENDER_MINSUBVERSION  0
index 78a2f13a7cc7f86fdfc39f1731fb8f203e1427e7..2d1bec09dbfb37bc92b27ce55bde3124f0d4b557 100644 (file)
@@ -92,6 +92,9 @@ void switchdirectionNurb( struct Nurb *nu);
 float (*curve_getVertexCos(struct Curve *cu, struct ListBase *lb, int *numVerts_r))[3];
 void curve_applyVertexCos(struct Curve *cu, struct ListBase *lb, float (*vertexCos)[3]);
 
+float (*curve_getKeyVertexCos(struct Curve *cu, struct ListBase *lb, float *key))[3];
+void curve_applyKeyVertexTilts(struct Curve *cu, struct ListBase *lb, float *key);
+
 /* nurb checks if they can be drawn, also clamp order func */
 int check_valid_nurb_u( struct Nurb *nu);
 int check_valid_nurb_v( struct Nurb *nu);
index 5d0b89220d5123542257a7d5da420325980a85d8..2e9ac2f65f0adfbd1e89f55469169643eaaf2fb9 100644 (file)
@@ -110,7 +110,7 @@ typedef struct Global {
 #define G_BACKBUFSEL   (1 <<  4)
 #define G_PICKSEL              (1 <<  5)
 
-#define G_FACESELECT   (1 <<  8)
+/* #define G_FACESELECT        (1 <<  8) use (mesh->editflag & ME_EDIT_PAINT_MASK) */
 
 #define G_DEBUG                        (1 << 12)
 #define G_DOSCRIPTLINKS (1 << 13)
@@ -145,6 +145,7 @@ typedef struct Global {
 #define G_FILE_GLSL_NO_NODES    (1 << 20)                              /* deprecated */
 #define G_FILE_GLSL_NO_EXTRA_TEX (1 << 21)                             /* deprecated */
 #define G_FILE_IGNORE_DEPRECATION_WARNINGS     (1 << 22)       /* deprecated */
+#define G_FILE_RECOVER                  (1 << 23)
 
 /* G.windowstate */
 #define G_WINDOWSTATE_USERDEF          0
index 4bfa6a41099d5c1e51beeb4e9008c82bb3768bd1..b70801a9edd5c2a4aee4e8e399d9361b168c6c6b 100644 (file)
@@ -56,17 +56,15 @@ void key_curve_position_weights(float t, float *data, int type);
 void key_curve_tangent_weights(float t, float *data, int type);
 void key_curve_normal_weights(float t, float *data, int type);
 
-/* only exported to curve.c! */
-void cp_cu_key(struct Curve *cu, struct KeyBlock *kb, int start, int end);
-
-int do_ob_key(struct Scene *scene, struct Object *ob);
+float *do_ob_key(struct Scene *scene, struct Object *ob);
 
 struct Key *ob_get_key(struct Object *ob);
 struct KeyBlock *ob_get_keyblock(struct Object *ob);
 struct KeyBlock *key_get_keyblock(struct Key *key, int index);
 struct KeyBlock *key_get_named_keyblock(struct Key *key, const char name[]);
+char *key_get_curValue_rnaPath(struct Key *key, struct KeyBlock *kb);
 // needed for the GE
-void do_rel_key(int start, int end, int tot, char *basispoin, struct Key *key, int mode);
+void do_rel_key(int start, int end, int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb, int mode);
 
 #ifdef __cplusplus
 };
index 85316dddedf19e8316c108a5a57e76dcc2d8f755..3ea7cae2c862088e5cde0e06a0bf92faf87039f4 100644 (file)
@@ -47,6 +47,7 @@ void test_object_materials(struct ID *id);
 void init_material(struct Material *ma);
 struct Material *add_material(char *name);
 struct Material *copy_material(struct Material *ma);
+struct Material *give_node_material(struct Material *ma); /* returns node material or self */
 void make_local_material(struct Material *ma);
 
 void automatname(struct Material *);
index 249da2478b7fb2c7409f9c9c55aba6ef3a267d97..5a072da13f5905e9ad5887d9f288630ee977adbe 100644 (file)
@@ -55,7 +55,7 @@ extern "C" {
 
 struct EditMesh *BKE_mesh_get_editmesh(struct Mesh *me);
 void BKE_mesh_end_editmesh(struct Mesh *me, struct EditMesh *em);
-struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me);
+struct BMesh *BKE_mesh_to_bmesh(struct Mesh *me, struct Object *ob);
 
 /*
   this function recreates a tesselation.
@@ -111,7 +111,6 @@ void mesh_calc_normals(struct MVert *mverts, int numVerts, struct MFace *mfaces,
        /* Return a newly MEM_malloc'd array of all the mesh vertex locations
         * (_numVerts_r_ may be NULL) */
 float (*mesh_getVertexCos(struct Mesh *me, int *numVerts_r))[3];
-float (*mesh_getRefKeyCos(struct Mesh *me, int *numVerts_r))[3];
 
 /* map from uv vertex to face (for select linked, stitch, uv suburf) */
 
index 8a3c8c64575cc4892329f9cab3e28a21ca01e36b..89ac993d71a674bb27129f394e6f91fdde07068c 100644 (file)
@@ -294,7 +294,7 @@ void          modifiers_foreachIDLink(struct Object *ob,
 struct ModifierData  *modifiers_findByType(struct Object *ob, ModifierType type);
 void          modifiers_clearErrors(struct Object *ob);
 int           modifiers_getCageIndex(struct Object *ob,
-                                     int *lastPossibleCageIndex_r);
+                                     int *lastPossibleCageIndex_r, int virtual_);
 
 int           modifiers_isSoftbodyEnabled(struct Object *ob);
 int           modifiers_isClothEnabled(struct Object *ob);
index f72617c83128da36e1d9c56989f629357167d4b6..fb3c282b0900b6646f0a94b95c46162944632643 100644 (file)
@@ -135,6 +135,7 @@ struct SeqEffectHandle {
 /* ********************* prototypes *************** */
 
 /* sequence.c */
+void printf_strip(struct Sequence *seq);
 
 // extern
 void seq_free_sequence(struct Scene *scene, struct Sequence *seq);
@@ -181,6 +182,7 @@ int check_single_seq(struct Sequence *seq);
 void fix_single_seq(struct Sequence *seq);
 int seq_test_overlap(struct ListBase * seqbasep, struct Sequence *test);
 int shuffle_seq(struct ListBase * seqbasep, struct Sequence *test);
+int shuffle_seq_time(ListBase * seqbasep);
 void free_imbuf_seq(struct ListBase * seqbasep, int check_mem_usage);
 
 void seq_update_sound(struct Sequence *seq);
index 91279597768654846fe130d28f6187697cc40da3..ec927dd30de2f8aaf6d33d77f51271789b85e9e2 100644 (file)
@@ -1990,9 +1990,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
        *final_r = NULL;
 
        if(useDeform) {
-               if(useDeform > 0 && do_ob_key(scene, ob)) /* shape key makes deform verts */
-                       deformedVerts = mesh_getVertexCos(me, &numVerts);
-               else if(inputVertexCos)
+               if(inputVertexCos)
                        deformedVerts = inputVertexCos;
                
                /* Apply all leading deforming modifiers */
@@ -2035,7 +2033,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
                if(inputVertexCos)
                        deformedVerts = inputVertexCos;
                else
-                       deformedVerts = mesh_getRefKeyCos(me, &numVerts);
+                       deformedVerts = mesh_getVertexCos(me, &numVerts);
        }
 
 
@@ -2248,7 +2246,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
        float (*deformedVerts)[3] = NULL;
        CustomDataMask mask;
        DerivedMesh *dm, *orcodm = NULL;
-       int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL);
+       int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL, 1);
        LinkNode *datamasks, *curr;
        int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
 
@@ -2259,7 +2257,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D
        }
 
        dm = NULL;
-       md = ob->modifiers.first;
+       md = modifiers_getVirtualModifierList(ob);
        
        /* we always want to keep original indices */
        dataMask |= CD_MASK_ORIGINDEX;
@@ -2695,13 +2693,13 @@ int editbmesh_get_first_deform_matrices(Object *ob, BMEditMesh *em, float (**def
        ModifierData *md;
        DerivedMesh *dm;
        int i, a, numleft = 0, numVerts = 0;
-       int cageIndex = modifiers_getCageIndex(ob, NULL);
+       int cageIndex = modifiers_getCageIndex(ob, NULL, 1);
        float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
 
        modifiers_clearErrors(ob);
 
        dm = NULL;
-       md = ob->modifiers.first;
+       md = modifiers_getVirtualModifierList(ob);
 
        /* compute the deformation matrices and coordinates for the first
           modifiers with on cage editing that are enabled and support computing
index 47f5dd116d7b655d213e4cbfa8df9b9c8e5f594f..61e754ffbec6aac9654e162cd043dfa5ed2ec648 100644 (file)
@@ -238,24 +238,88 @@ void BKE_animdata_make_local(AnimData *adt)
 
 /* Path Validation -------------------------------------------- */
 
-#if 0
-/* Check if some given RNA Path needs fixing - free the given path and set a new one as appropriate */
-static char *rna_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, char *oldpath)
+/* Check if a given RNA Path is valid, by tracing it from the given ID, and seeing if we can resolve it */
+static short check_rna_path_is_valid (ID *owner_id, char *path)
 {
+       PointerRNA id_ptr, ptr;
+       PropertyRNA *prop=NULL;
        
+       /* make initial RNA pointer to start resolving from */
+       RNA_id_pointer_create(owner_id, &id_ptr);
        
-       return oldpath; // FIXME!!!
+       /* try to resolve */
+       return RNA_path_resolve(&id_ptr, path, &ptr, &prop); 
+}
+
+/* Check if some given RNA Path needs fixing - free the given path and set a new one as appropriate 
+ * NOTE: we assume that oldName and newName have [" "] padding around them
+ */
+static char *rna_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, char *oldpath)
+{
+       char *prefixPtr= strstr(oldpath, prefix);
+       char *oldNamePtr= strstr(oldpath, oldName);
+       int prefixLen= strlen(prefix);
+       int oldNameLen= strlen(oldName);
+       
+       /* only start fixing the path if the prefix and oldName feature in the path,
+        * and prefix occurs immediately before oldName
+        */
+       if ( (prefixPtr && oldNamePtr) && (prefixPtr+prefixLen == oldNamePtr) ) {
+               /* if we haven't aren't able to resolve the path now, try again after fixing it */
+               if (check_rna_path_is_valid(owner_id, oldpath) == 0) {          
+                       DynStr *ds= BLI_dynstr_new();
+                       char *postfixPtr= oldNamePtr+oldNameLen;
+                       char *newPath = NULL;
+                       char oldChar;
+                       
+                       /* add the part of the string that goes up to the start of the prefix */
+                       if (prefixPtr > oldpath) {
+                               oldChar= prefixPtr[0]; 
+                               prefixPtr[0]= 0;
+                               BLI_dynstr_append(ds, oldpath);
+                               prefixPtr[0]= oldChar;
+                       }
+                       
+                       /* add the prefix */
+                       BLI_dynstr_append(ds, prefix);
+                       
+                       /* add the new name (complete with brackets) */
+                       BLI_dynstr_append(ds, newName);
+                       
+                       /* add the postfix */
+                       BLI_dynstr_append(ds, postfixPtr);
+                       
+                       /* create new path, and cleanup old data */
+                       newPath= BLI_dynstr_get_cstring(ds);
+                       BLI_dynstr_free(ds);
+                       
+                       /* check if the new path will solve our problems */
+                       // TODO: will need to check whether this step really helps in practice
+                       if (check_rna_path_is_valid(owner_id, newPath)) {
+                               /* free the old path, and return the new one, since we've solved the issues */
+                               MEM_freeN(oldpath);
+                               return newPath;
+                       }
+                       else {
+                               /* still couldn't resolve the path... so, might as well just leave it alone */
+                               MEM_freeN(newPath);
+                       }
+               }
+       }
+       
+       /* the old path doesn't need to be changed */
+       return oldpath;
 }
 
 /* Check RNA-Paths for a list of F-Curves */
-static void fcurves_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, ListBase *curves)
+static void fcurves_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, ListBase *curves)
 {
        FCurve *fcu;
        
        /* we need to check every curve... */
        for (fcu= curves->first; fcu; fcu= fcu->next) {
                /* firstly, handle the F-Curve's own path */
-               fcu->rna_path= rna_path_rename_fix(owner_id, modPtr, newName, fcu->rna_path);
+               fcu->rna_path= rna_path_rename_fix(owner_id, prefix, oldName, newName, fcu->rna_path);
                
                /* driver? */
                if (fcu->driver) {
@@ -264,14 +328,14 @@ static void fcurves_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *new
                        
                        /* driver targets */
                        for (dtar= driver->targets.first; dtar; dtar=dtar->next) {
-                               dtat->rna_path= rna_path_rename_fix(dtar->id, modPtr, newName, dtar->rna_path);
+                               dtar->rna_path= rna_path_rename_fix(dtar->id, prefix, oldName, newName, dtar->rna_path);
                        }
                }
        }
 }
 
 /* Fix all RNA-Paths for Actions linked to NLA Strips */
-static void nlastrips_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *newName, ListBase *strips)
+static void nlastrips_path_rename_fix (ID *owner_id, char *prefix, char *oldName, char *newName, ListBase *strips)
 {
        NlaStrip *strip;
        
@@ -279,42 +343,122 @@ static void nlastrips_path_rename_fix (ID *owner_id, PointerRNA *modPtr, char *n
        for (strip= strips->first; strip; strip= strip->next) {
                /* fix strip's action */
                if (strip->act)
-                       fcurves_path_rename_fix(owner_id, modPtr, newName, &strip->act->curves);
+                       fcurves_path_rename_fix(owner_id, prefix, oldName, newName, &strip->act->curves);
                /* ignore own F-Curves, since those are local...  */
                
                /* check sub-strips (if metas) */
-               nlastrips_path_rename_fix(owner_id, modPtr, newName, &strip->strips);
+               nlastrips_path_rename_fix(owner_id, prefix, oldName, newName, &strip->strips);
        }
 }
 
 /* Fix all RNA-Paths in the AnimData block used by the given ID block
- *     - the pointer of interest must not have had its new name assigned already, otherwise
- *       path matching for this will never work
+ * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
+ *             i.e. pose.pose_channels["Bone"]
  */
-void BKE_animdata_fix_paths_rename (ID *owner_id, PointerRNA *modPtr, char *newName)
+void BKE_animdata_fix_paths_rename (ID *owner_id, AnimData *adt, char *prefix, char *oldName, char *newName)
 {
-       AnimData *adt= BKE_animdata_from_id(owner_id);
        NlaTrack *nlt;
+       char *oldN, *newN;
        
        /* if no AnimData, no need to proceed */
-       if (ELEM4(NULL, owner_id, adt, modPtr, newName))
+       if (ELEM4(NULL, owner_id, adt, oldName, newName))
                return;
        
+       /* pad the names with [" "] so that only exact matches are made */
+       oldN= BLI_sprintfN("[\"%s\"]", oldName);
+       newN= BLI_sprintfN("[\"%s\"]", newName);
+       
        /* Active action and temp action */
        if (adt->action)
-               fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->action->curves);
+               fcurves_path_rename_fix(owner_id, prefix, oldN, newN, &adt->action->curves);
        if (adt->tmpact)
-               fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->tmpact->curves);
+               fcurves_path_rename_fix(owner_id, prefix, oldN, newN, &adt->tmpact->curves);
                
        /* Drivers - Drivers are really F-Curves */
-       fcurves_path_rename_fix(owner_id, modPtr, newName, &adt->drivers);
+       fcurves_path_rename_fix(owner_id, prefix, oldN, newN, &adt->drivers);
        
        /* NLA Data - Animation Data for Strips */
-       for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
+       for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next)
+               nlastrips_path_rename_fix(owner_id, prefix, oldN, newN, &nlt->strips);
+               
+       /* free the temp names */
+       MEM_freeN(oldN);
+       MEM_freeN(newN);
+}
+
+/* Fix all RNA-Paths throughout the database (directly access the Global.main version)
+ * NOTE: it is assumed that the structure we're replacing is <prefix><["><name><"]>
+ *             i.e. pose.pose_channels["Bone"]
+ */
+void BKE_all_animdata_fix_paths_rename (char *prefix, char *oldName, char *newName)
+{
+       Main *mainptr= G.main;
+       ID *id;
+       
+       /* macro for less typing 
+        *      - whether animdata exists is checked for by the main renaming callback, though taking 
+        *        this outside of the function may make things slightly faster?
+        */
+#define RENAMEFIX_ANIM_IDS(first) \
+       for (id= first; id; id= id->next) { \
+               AnimData *adt= BKE_animdata_from_id(id); \
+               BKE_animdata_fix_paths_rename(id, adt, prefix, oldName, newName);\
+       }
+       
+       /* nodes */
+       RENAMEFIX_ANIM_IDS(mainptr->nodetree.first);
+       
+       /* textures */
+       RENAMEFIX_ANIM_IDS(mainptr->tex.first);
+       
+       /* lamps */
+       RENAMEFIX_ANIM_IDS(mainptr->lamp.first);
+       
+       /* materials */
+       RENAMEFIX_ANIM_IDS(mainptr->mat.first);
+       
+       /* cameras */
+       RENAMEFIX_ANIM_IDS(mainptr->camera.first);
+       
+       /* shapekeys */
+       RENAMEFIX_ANIM_IDS(mainptr->key.first);
+       
+       /* metaballs */
+       RENAMEFIX_ANIM_IDS(mainptr->mball.first);
+       
+       /* curves */
+       RENAMEFIX_ANIM_IDS(mainptr->curve.first);
+       
+       /* armatures */
+       RENAMEFIX_ANIM_IDS(mainptr->armature.first);
+       
+       /* meshes */
+       // TODO...
+       
+       /* particles */
+       RENAMEFIX_ANIM_IDS(mainptr->particle.first);
+       
+       /* objects */
+       RENAMEFIX_ANIM_IDS(mainptr->object.first); 
+       
+       /* worlds */
+       RENAMEFIX_ANIM_IDS(mainptr->world.first);
+       
+       /* scenes */
+       for (id= mainptr->scene.first; id; id= id->next) {
+               AnimData *adt= BKE_animdata_from_id(id);
+               Scene *scene= (Scene *)id;
+               
+               /* do compositing nodes first (since these aren't included in main tree) */
+               if (scene->nodetree) {
+                       AnimData *adt2= BKE_animdata_from_id((ID *)scene->nodetree);
+                       BKE_animdata_fix_paths_rename((ID *)scene->nodetree, adt2, prefix, oldName, newName);
+               }
                
+               /* now fix scene animation data as per normal */
+               BKE_animdata_fix_paths_rename((ID *)id, adt, prefix, oldName, newName);
        }
 }
-#endif
 
 /* *********************************** */ 
 /* KeyingSet API */
index afc5a972a65bae05760dde4729c6b0407dae3241..fa0db751c00142ffd1c906646abe7ba9697380a6 100644 (file)
@@ -1287,7 +1287,7 @@ void armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float
  *     - the result should be that the rotations given in the provided pointers have had conversions 
  *       applied (as appropriate), such that the rotation of the element hasn't 'visually' changed 
  */
-void BKE_rotMode_change_values (float quat[4], float eul[3], float *axis, float angle[3], short oldMode, short newMode)
+void BKE_rotMode_change_values (float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode)
 {
        /* check if any change - if so, need to convert data */
        if (newMode > 0) { /* to euler */
index 9c1b93f2bf868e660b27e1cbdac91ae233ba521c..0abe5592da31355d91f95dbedb250d622fbe1abc 100644 (file)
@@ -226,8 +226,6 @@ static void clear_global(void)
 //     free_vertexpaint();
 
        G.main= NULL;
-       
-       G.f &= ~(G_FACESELECT);
 }
 
 /* make sure path names are correct for OS */
@@ -281,12 +279,15 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
        Object *ob;
        bScreen *curscreen= NULL;
        Scene *curscene= NULL;
+       int recover;
        char mode;
-       
+
        /* 'u' = undo save, 'n' = no UI load */
        if(bfd->main->screen.first==NULL) mode= 'u';
        else if(G.fileflags & G_FILE_NO_UI) mode= 'n';
        else mode= 0;
+
+       recover= (G.fileflags & G_FILE_RECOVER);
        
        clean_paths(bfd->main);
        
@@ -371,6 +372,16 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
        if(G.main->versionfile < 250)
                do_versions_ipos_to_animato(G.main); // XXX fixme... complicated versionpatching
        
+       /* in case of autosave or quit.blend, use original filename instead */
+       if(recover && bfd->filename[0])
+               filename= bfd->filename;
+       
+       /* these are the same at times, should never copy to the same location */
+       if(G.sce != filename)
+               BLI_strncpy(G.sce, filename, FILE_MAX);
+       
+       BLI_strncpy(G.main->name, filename, FILE_MAX); /* is guaranteed current file */
+
        /* baseflags, groups, make depsgraph, etc */
        set_scene_bg(CTX_data_scene(C));
 
@@ -383,11 +394,6 @@ static void setup_app_data(bContext *C, BlendFileData *bfd, char *filename)
        /* now tag update flags, to ensure deformers get calculated on redraw */
        DAG_scene_update_flags(CTX_data_scene(C), CTX_data_scene(C)->lay);
        
-       if (G.sce != filename) /* these are the same at times, should never copy to the same location */
-               strcpy(G.sce, filename);
-       
-       BLI_strncpy(G.main->name, filename, FILE_MAX); /* is guaranteed current file */
-       
        MEM_freeN(bfd);
 }
 
index 2ce877bd8472f8cd6812c401ef7edaf20e587ce6..f31f4cd975385dbef6fb2ef5242fa7d60c48896a 100644 (file)
@@ -1099,8 +1099,7 @@ float *make_orco_curve(Scene *scene, Object *ob)
        float *fp, *coord_array;
        int remakeDisp = 0;
 
-       if (!(cu->flag&CU_UV_ORCO) && cu->key && cu->key->refkey) {
-               cp_cu_key(cu, cu->key->refkey, 0, count_curveverts(&cu->nurb));
+       if (!(cu->flag&CU_UV_ORCO) && cu->key && cu->key->block.first) {
                makeDispListCurveTypes(scene, ob, 1);
                remakeDisp = 1;
        }
@@ -1922,7 +1921,7 @@ void makeBevelList(Object *ob)
        BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0;
        float min, inp, x1, x2, y1, y2;
        struct bevelsort *sortdata, *sd, *sd1;
-       int a, b, nr, poly, resolu, len=0;
+       int a, b, nr, poly, resolu = 0, len = 0;
        int do_tilt, do_radius;
        
        /* this function needs an object, because of tflag and upflag */
@@ -2905,6 +2904,64 @@ void curve_applyVertexCos(Curve *cu, ListBase *lb, float (*vertexCos)[3])
        }
 }
 
+float (*curve_getKeyVertexCos(Curve *cu, ListBase *lb, float *key))[3]
+{
+       int i, numVerts;
+       float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos)*numVerts, "cu_vcos");
+       Nurb *nu;
+
+       co = cos[0];
+       for (nu=lb->first; nu; nu=nu->next) {
+               if (nu->type == CU_BEZIER) {
+                       BezTriple *bezt = nu->bezt;
+
+                       for (i=0; i<nu->pntsu; i++,bezt++) {
+                               VECCOPY(co, key); co+=3; key+=3;
+                               VECCOPY(co, key); co+=3; key+=3;
+                               VECCOPY(co, key); co+=3; key+=3;
+                               key++; /* skip tilt */
+                       }
+               }
+               else {
+                       BPoint *bp = nu->bp;
+
+                       for(i=0; i<nu->pntsu*nu->pntsv; i++,bp++) {
+                               VECCOPY(co, key); co+=3; key+=3;
+                               key++; /* skip tilt */
+                       }
+               }
+       }
+
+       return cos;
+}
+
+void curve_applyKeyVertexTilts(Curve *cu, ListBase *lb, float *key)
+{
+       Nurb *nu;
+       int i;
+
+       for(nu=lb->first; nu; nu=nu->next) {
+               if(nu->type == CU_BEZIER) {
+                       BezTriple *bezt = nu->bezt;
+
+                       for(i=0; i<nu->pntsu; i++,bezt++) {
+                               key+=3*3;
+                               bezt->alfa= *key;
+                               key++;
+                       }
+               }
+               else {
+                       BPoint *bp = nu->bp;
+
+                       for(i=0; i<nu->pntsu*nu->pntsv; i++,bp++) {
+                               key+=3;
+                               bp->alfa= *key;
+                               key++;
+                       }
+               }
+       }
+}
+
 int check_valid_nurb_u( struct Nurb *nu )
 {
        if (nu==NULL)                                           return 0;
index 2d743a33106a98e4ce0002b9010be40c2719777d..da461f51afb85cce10ce570a79969d4f9355761b 100644 (file)
@@ -829,7 +829,27 @@ static void layerDefault_mcol(void *data, int count)
                mcol[i] = default_mcol;
 }
 
+static void layerInterp_shapekey(void **sources, float *weights,
+                             float *sub_weights, int count, void *dest)
+{
+       float *co = dest, *src;
+       float **in = sources;
+       int i, j, k;
 
+       if(count <= 0) return;
+
+       memset(co, 0, sizeof(float)*3);
+       
+       sub_weight = sub_weights;
+       for(i = 0; i < count; ++i) {
+               float weight = weights ? weights[i] : 1.0f;
+               
+               src = in[i];
+               co[0] += src[0] * weight;
+               co[1] += src[1] * weight;
+               co[2] += src[2] * weight;
+       }
+}
 
 const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
        {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL},
@@ -875,13 +895,16 @@ const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
         layerSwap_mcol, layerDefault_mcol},
        {sizeof(MCol)*4, "MCol", 4, "TextureCol", NULL, NULL, layerInterp_mcol,
         layerSwap_mcol, layerDefault_mcol},
+       {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
+       {sizeof(float), "", 3, "ShapeKey", layerInterp_shapekey},
 };
 
 const char *LAYERTYPENAMES[CD_NUMTYPES] = {
        "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", "CDMTFace",
        "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags","CDMFloatProperty",
        "CDMIntProperty","CDMStringProperty", "CDOrigSpace", "CDOrco", "CDMTexPoly", "CDMLoopUV",
-       "CDMloopCol", "CDTangent", "CDMDisps", "CDWeightMCol"};
+       "CDMloopCol", "CDTangent", "CDMDisps", "CDWeightMCol", "CDMPoly", 
+       "CDMLoop", "CDMLoopCol", "CDIDCol", "CDTextureCol", "CDShapeKeyIndex"};
 
 const CustomDataMask CD_MASK_BAREMESH =
        CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MLOOP | CD_MASK_MPOLY;
@@ -893,15 +916,17 @@ const CustomDataMask CD_MASK_MESH =
        CD_MASK_MTEXPOLY;
 const CustomDataMask CD_MASK_EDITMESH =
        CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MLOOPUV |
-       CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY |
-       CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS;
+       CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_SHAPE_KEYINDEX |
+       CD_MASK_MCOL|CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR |
+       CD_MASK_MDISPS | CD_MASK_SHAPEKEY;
 const CustomDataMask CD_MASK_DERIVEDMESH =
        CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE |
        CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
        CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_WEIGHT_MLOOPCOL |
        CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_TANGENT | CD_MASK_WEIGHT_MCOL;
 const CustomDataMask CD_MASK_BMESH = CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY |
-       CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR;
+       CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | 
+       CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX;
 const CustomDataMask CD_MASK_FACECORNERS =
        CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
        CD_MASK_MLOOPCOL;
index 26ea17a296ad6cbedba9649809a3da8d886a8e37..d60a26e8feb563d88a89b4f0887a97d486f8ecdb 100644 (file)
@@ -2235,7 +2235,18 @@ void DAG_id_flush_update(ID *id, short flag)
                                }
                        }
                }
-
+               
+               /* set flags based on ShapeKey */
+               if(idtype == ID_KE) {
+                       for(obt=bmain->object.first; obt; obt= obt->id.next) {
+                               Key *key= ob_get_key(obt);
+                               if(!(ob && obt == ob) && ((ID *)key == id)) {
+                                       obt->flag |= (OB_RECALC|OB_RECALC_DATA);
+                                       BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
+                               }
+                       }
+               }
+               
                /* set flags based on particle settings */
                if(idtype == ID_PA) {
                        ParticleSystem *psys;
index d8f466835b343ac30c81ae02ea1889c7561e2676..4ef868616857c2bc71f35d419a145a1c9a3a639d 100644 (file)
@@ -1245,6 +1245,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl
        int editmode = (!forRender && cu->editnurb);
        float (*originalVerts)[3] = NULL;
        float (*deformedVerts)[3] = NULL;
+       float *keyVerts= NULL;
        int required_mode;
 
        if(forRender) required_mode = eModifierMode_Render;
@@ -1254,9 +1255,17 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl
        
        if(editmode) required_mode |= eModifierMode_Editmode;
 
-       if(cu->editnurb==NULL && do_ob_key(scene, ob)) {
-               deformedVerts = curve_getVertexCos(ob->data, nurb, &numVerts);
-               originalVerts = MEM_dupallocN(deformedVerts);
+       if(cu->editnurb==NULL) {
+               keyVerts= do_ob_key(scene, ob);
+
+               if(keyVerts) {
+                       /* split coords from key data, the latter also includes
+                          tilts, which is passed through in the modifier stack.
+                          this is also the reason curves do not use a virtual
+                          shape key modifier yet. */
+                       deformedVerts= curve_getKeyVertexCos(cu, nurb, keyVerts);
+                       originalVerts= MEM_dupallocN(deformedVerts);
+               }
        }
        
        if (preTesselatePoint) {
@@ -1270,7 +1279,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl
                        if (mti->type!=eModifierTypeType_OnlyDeform) continue;
 
                        if (!deformedVerts) {
-                               deformedVerts = curve_getVertexCos(ob->data, nurb, &numVerts);
+                               deformedVerts = curve_getVertexCos(cu, nurb, &numVerts);
                                originalVerts = MEM_dupallocN(deformedVerts);
                        }
                        
@@ -1281,9 +1290,13 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, fl
                }
        }
 
-       if (deformedVerts) {
-               curve_applyVertexCos(ob->data, nurb, deformedVerts);
-       }
+       if (deformedVerts)
+               curve_applyVertexCos(cu, nurb, deformedVerts);
+       if (keyVerts) /* these are not passed through modifier stack */
+               curve_applyKeyVertexTilts(cu, nurb, keyVerts);
+       
+       if(keyVerts)
+               MEM_freeN(keyVerts);
 
        *originalVerts_r = originalVerts;
        *deformedVerts_r = deformedVerts;
index 2d3b84bbdb309cf4d67453bebbe4d5b34a4dc6e7..742214ab28e872b9428b1569781fcc17ce9da47a 100644 (file)
@@ -35,6 +35,9 @@
 
 #include "MEM_guardedalloc.h"
 
+#include "BLI_blenlib.h"
+#include "BLI_editVert.h"
+
 #include "DNA_anim_types.h"
 #include "DNA_curve_types.h"
 #include "DNA_key_types.h"
 #include "BKE_lattice.h"
 #include "BKE_library.h"
 #include "BKE_mesh.h"
+#include "BKE_tessmesh.h"
 #include "BKE_main.h"
 #include "BKE_object.h"
 #include "BKE_utildefines.h"
 
-#include "BLI_blenlib.h"
+#include "RNA_access.h"
 #include "BLI_cellalloc.h"
 
 
@@ -167,7 +171,7 @@ Key *copy_key(Key *key)
        while(kbn) {
                
                if(kbn->data) kbn->data= MEM_dupallocN(kbn->data);
-               if( kb==key->refkey ) keyn->refkey= kbn;
+               if(kb==key->refkey) keyn->refkey= kbn;
                
                kbn= kbn->next;
                kb= kb->next;
@@ -496,48 +500,80 @@ static void rel_flerp(int aantal, float *in, float *ref, float *out, float fac)
        }
 }
 
-static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *k, float *weights, int mode)
+static char *key_block_get_data(Key *key, KeyBlock *actkb, KeyBlock *kb, char **freedata)
+{
+       if(kb == actkb) {
+               /* this hack makes it possible to edit shape keys in
+                  edit mode with shape keys blending applied */
+               if(GS(key->from->name) == ID_ME) {
+                       Mesh *me;
+                       BMVert *eve;
+                       BMIter iter;
+                       float (*co)[3];
+                       int a;
+
+                       me= (Mesh*)key->from;
+
+                       if(me->edit_btmesh && me->edit_btmesh->bm->totvert == kb->totelem) {
+                               a= 0;
+                               co= MEM_callocN(sizeof(float)*3*me->edit_btmesh->bm->totvert, "key_block_get_data");
+
+                               BM_ITER(eve, &iter, me->edit_btmesh->bm, BM_VERTS_OF_MESH, NULL) {
+                                       VECCOPY(co[a], eve->co);
+                                       a++;
+                               }
+
+                               *freedata= (char*)co;
+                               return (char*)co;
+                       }
+               }
+       }
+
+       *freedata= NULL;
+       return kb->data;
+}
+
+static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock *kb, float *weights, int mode)
 {
        float ktot = 0.0, kd = 0.0;
        int elemsize, poinsize = 0, a, *ofsp, ofs[32], flagflo=0;
-       char *k1, *kref;
+       char *k1, *kref, *freek1, *freekref;
        char *cp, elemstr[8];
 
        if(key->from==NULL) return;
 
        if( GS(key->from->name)==ID_ME ) {
-               ofs[0]= sizeof(MVert);
+               ofs[0]= sizeof(float)*3;
                ofs[1]= 0;
                poinsize= ofs[0];
        }
        else if( GS(key->from->name)==ID_LT ) {
-               ofs[0]= sizeof(BPoint);
+               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(BPoint);
-               else ofs[0]= sizeof(BezTriple);
+               if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
+               else ofs[0]= sizeof(float)*10;
                
                ofs[1]= 0;
                poinsize= ofs[0];
        }
 
-
        if(end>tot) end= tot;
        
-       k1= k->data;
-       kref= key->refkey->data;
-       
-       if(tot != k->totelem) {
+       if(tot != kb->totelem) {
                ktot= 0.0;
                flagflo= 1;
-               if(k->totelem) {
-                       kd= k->totelem/(float)tot;
+               if(kb->totelem) {
+                       kd= kb->totelem/(float)tot;
                }
                else return;
        }
 
+       k1= key_block_get_data(key, actkb, kb, &freek1);
+       kref= key_block_get_data(key, actkb, key->refkey, &freekref);
+
        /* this exception is needed for slurphing */
        if(start!=0) {
                
@@ -574,33 +610,24 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                        
                        switch(cp[1]) {
                        case IPO_FLOAT:
-                               
                                if(weights) {
-                                       memcpy(poin, kref, sizeof(float)*cp[0]);
+                                       memcpy(poin, kref, sizeof(float)*3);
                                        if(*weights!=0.0f)
                                                rel_flerp(cp[0], (float *)poin, (float *)kref, (float *)k1, *weights);
                                        weights++;
                                }
                                else 
-                                       memcpy(poin, k1, sizeof(float)*cp[0]);
-
-                               poin+= ofsp[0];
-
+                                       memcpy(poin, k1, sizeof(float)*3);
                                break;
                        case IPO_BPOINT:
-                               memcpy(poin, k1, 3*sizeof(float));
-                               memcpy(poin+4*sizeof(float), k1+3*sizeof(float), sizeof(float));
-                               
-                               poin+= ofsp[0];                         
-
+                               memcpy(poin, k1, sizeof(float)*4);
                                break;
                        case IPO_BEZTRIPLE:
                                memcpy(poin, k1, sizeof(float)*10);
-                               poin+= ofsp[0]; 
-
                                break;
                        }
                        
+                       poin+= ofsp[0]; 
                        cp+= 2; ofsp++;
                }
                
@@ -620,71 +647,63 @@ static void cp_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                
                if(mode==KEY_BEZTRIPLE) a+=2;
        }
+
+       if(freek1) MEM_freeN(freek1);
+       if(freekref) MEM_freeN(freekref);
 }
 
-void cp_cu_key(Curve *cu, KeyBlock *kb, int start, int end)
+static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, int start, int end, char *out, int tot)
 {
        Nurb *nu;
-       int a, step = 0, tot, a1, a2;
        char *poin;
+       int a, step, a1, a2;
 
-       tot= count_curveverts(&cu->nurb);
-       nu= cu->nurb.first;
-       a= 0;
-       while(nu) {
+       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= (char *)nu->bp->vec;
-                       poin -= a*sizeof(BPoint);
-                       
+                       poin= out - a*sizeof(float)*4;
                        a1= MAX2(a, start);
                        a2= MIN2(a+step, end);
                        
-                       if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, NULL, KEY_BPOINT);
+                       if(a1<a2) cp_key(a1, a2, tot, poin, key, actkb, kb, NULL, KEY_BPOINT);
                }
                else if(nu->bezt) {
-                       
                        step= 3*nu->pntsu;
                        
-                       poin= (char *)nu->bezt->vec;
-                       poin -= a*sizeof(BezTriple);
-
+                       poin= out - a*sizeof(float)*10;
                        a1= MAX2(a, start);
                        a2= MIN2(a+step, end);
 
-                       if(a1<a2) cp_key(a1, a2, tot, poin, cu->key, kb, NULL, KEY_BEZTRIPLE);
-                       
+                       if(a1<a2) cp_key(a1, a2, tot, poin, key, actkb, kb, NULL, KEY_BEZTRIPLE);
                }
-               a+= step;
-               nu=nu->next;
+               else
+                       step= 0;
        }
 }
 
 
-void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode)
+void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, KeyBlock *actkb, int mode)
 {
        KeyBlock *kb;
        int *ofsp, ofs[3], elemsize, b;
        char *cp, *poin, *reffrom, *from, elemstr[8];
+       char *freefrom, *freereffrom;
        
        if(key->from==NULL) return;
        
-       if (G.f & G_DEBUG) printf("do_rel_key() \n");
-       
        if( GS(key->from->name)==ID_ME ) {
-               ofs[0]= sizeof(MVert);
+               ofs[0]= sizeof(float)*3;
                ofs[1]= 0;
        }
        else if( GS(key->from->name)==ID_LT ) {
-               ofs[0]= sizeof(BPoint);
+               ofs[0]= sizeof(float)*3;
                ofs[1]= 0;
        }
        else if( GS(key->from->name)==ID_CU ) {
-               if(mode==KEY_BPOINT) ofs[0]= sizeof(BPoint);
-               else ofs[0]= sizeof(BezTriple);
+               if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
+               else ofs[0]= sizeof(float)*10;
                
                ofs[1]= 0;
        }
@@ -701,7 +720,7 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode
        if(mode==KEY_BEZTRIPLE) elemsize*= 3;
 
        /* step 1 init */
-       cp_key(start, end, tot, basispoin, key, key->refkey, NULL, mode);
+       cp_key(start, end, tot, basispoin, key, actkb, key->refkey, NULL, mode);
        
        /* step 2: do it */
        
@@ -709,21 +728,18 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode
                if(kb!=key->refkey) {
                        float icuval= kb->curval;
                        
-                       if (G.f & G_DEBUG) printf("\tdo rel key %s : %s = %f \n", key->id.name+2, kb->name, icuval);
-                       
                        /* only with value, and no difference allowed */
                        if(!(kb->flag & KEYBLOCK_MUTE) && icuval!=0.0f && kb->totelem==tot) {
                                KeyBlock *refb;
                                float weight, *weights= kb->weights;
-                               
-                               if (G.f & G_DEBUG) printf("\t\tnot skipped \n");
-                               
-                               poin= basispoin;
-                               from= kb->data;
+
                                /* reference now can be any block */
                                refb= BLI_findlink(&key->block, kb->relative);
                                if(refb==NULL) continue;
-                               reffrom= refb->data;
+                               
+                               poin= basispoin;
+                               from= key_block_get_data(key, actkb, kb, &freefrom);
+                               reffrom= key_block_get_data(key, actkb, refb, &freereffrom);
                                
                                poin+= start*ofs[0];
                                reffrom+= key->elemsize*start;  // key elemsize yes!
@@ -745,17 +761,13 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode
                                                
                                                switch(cp[1]) {
                                                case IPO_FLOAT:
-                                                       rel_flerp(cp[0], (float *)poin, (float *)reffrom, (float *)from, weight);
-                                                       
+                                                       rel_flerp(3, (float *)poin, (float *)reffrom, (float *)from, weight);
                                                        break;
                                                case IPO_BPOINT:
-                                                       rel_flerp(3, (float *)poin, (float *)reffrom, (float *)from, icuval);
-                                                       rel_flerp(1, (float *)(poin+16), (float *)(reffrom+16), (float *)(from+16), icuval);
-                       
+                                                       rel_flerp(4, (float *)poin, (float *)reffrom, (float *)from, weight);
                                                        break;
                                                case IPO_BEZTRIPLE:
-                                                       rel_flerp(9, (float *)poin, (float *)reffrom, (float *)from, icuval);
-                       
+                                                       rel_flerp(10, (float *)poin, (float *)reffrom, (float *)from, weight);
                                                        break;
                                                }
                                                
@@ -771,38 +783,39 @@ void do_rel_key(int start, int end, int tot, char *basispoin, Key *key, int mode
                                        if(mode==KEY_BEZTRIPLE) b+= 2;
                                        if(weights) weights++;
                                }
+
+                               if(freefrom) MEM_freeN(freefrom);
+                               if(freereffrom) MEM_freeN(freereffrom);
                        }
                }
        }
 }
 
 
-static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock **k, float *t, int mode)
+static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, int mode)
 {
        float k1tot = 0.0, k2tot = 0.0, k3tot = 0.0, k4tot = 0.0;
        float k1d = 0.0, k2d = 0.0, k3d = 0.0, k4d = 0.0;
        int a, ofs[32], *ofsp;
        int flagdo= 15, flagflo=0, elemsize, poinsize=0;
-       char *k1, *k2, *k3, *k4;
+       char *k1, *k2, *k3, *k4, *freek1, *freek2, *freek3, *freek4;
        char *cp, elemstr[8];;
 
        if(key->from==0) return;
 
-       if (G.f & G_DEBUG) printf("do_key() \n");
-       
        if( GS(key->from->name)==ID_ME ) {
-               ofs[0]= sizeof(MVert);
+               ofs[0]= sizeof(float)*3;
                ofs[1]= 0;
                poinsize= ofs[0];
        }
        else if( GS(key->from->name)==ID_LT ) {
-               ofs[0]= sizeof(BPoint);
+               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(BPoint);
-               else ofs[0]= sizeof(BezTriple);
+               if(mode==KEY_BPOINT) ofs[0]= sizeof(float)*4;
+               else ofs[0]= sizeof(float)*10;
                
                ofs[1]= 0;
                poinsize= ofs[0];
@@ -810,10 +823,10 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
        
        if(end>tot) end= tot;
 
-       k1= k[0]->data;
-       k2= k[1]->data;
-       k3= k[2]->data;
-       k4= k[3]->data;
+       k1= key_block_get_data(key, actkb, k[0], &freek1);
+       k2= key_block_get_data(key, actkb, k[1], &freek2);
+       k3= key_block_get_data(key, actkb, k[2], &freek3);
+       k4= key_block_get_data(key, actkb, k[3], &freek4);
 
        /*  test for more or less points (per key!) */
        if(tot != k[0]->totelem) {
@@ -921,26 +934,17 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                        
                        switch(cp[1]) {
                        case IPO_FLOAT:
-                               flerp(cp[0], (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
-                               poin+= ofsp[0];                         
-
+                               flerp(3, (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
                                break;
                        case IPO_BPOINT:
-                               flerp(3, (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
-                               flerp(1, (float *)(poin+16), (float *)(k1+12), (float *)(k2+12), (float *)(k3+12), (float *)(k4+12), t);
-                               
-                               poin+= ofsp[0];                         
-
+                               flerp(4, (float *)poin, (float *)k1, (float *)k2, (float *)k3, (float *)k4, t);
                                break;
                        case IPO_BEZTRIPLE:
-                               flerp(9, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t);
-                               flerp(1, (float *)(poin+36), (float *)(k1+36), (float *)(k2+36), (float *)(k3+36), (float *)(k4+36), t);
-                               poin+= ofsp[0];                         
-
+                               flerp(10, (void *)poin, (void *)k1, (void *)k2, (void *)k3, (void *)k4, t);
                                break;
                        }
                        
-
+                       poin+= ofsp[0];                         
                        cp+= 2;
                        ofsp++;
                }
@@ -988,6 +992,11 @@ static void do_key(int start, int end, int tot, char *poin, Key *key, KeyBlock *
                
                if(mode==KEY_BEZTRIPLE) a+= 2;
        }
+
+       if(freek1) MEM_freeN(freek1);
+       if(freek2) MEM_freeN(freek2);
+       if(freek3) MEM_freeN(freek3);
+       if(freek4) MEM_freeN(freek4);
 }
 
 static float *get_weights_array(Object *ob, char *vgroup)
@@ -1037,41 +1046,30 @@ static float *get_weights_array(Object *ob, char *vgroup)
        return NULL;
 }
 
-static int do_mesh_key(Scene *scene, Object *ob, Mesh *me)
+static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
 {
-       KeyBlock *k[4];
-       float cfra, ctime, t[4], delta, loc[3], size[3];
+       KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
+       float cfra, ctime, t[4], delta;
        int a, flag = 0, step;
        
-       if(me->totvert==0) return 0;
-       if(me->key==NULL) return 0;
-       if(me->key->block.first==NULL) return 0;
-       
-       /* prevent python from screwing this up? anyhoo, the from pointer could be dropped */
-       me->key->from= (ID *)me;
-       
-       if (G.f & G_DEBUG) printf("do mesh key ob:%s me:%s ke:%s \n", ob->id.name+2, me->id.name+2, me->key->id.name+2);
-       
-       if(me->key->slurph && me->key->type!=KEY_RELATIVE ) {
-               if (G.f & G_DEBUG) printf("\tslurph key\n");
-               
-               delta= me->key->slurph;
-               delta/= me->totvert;
+       if(key->slurph && key->type!=KEY_RELATIVE ) {
+               delta= key->slurph;
+               delta/= tot;
                
                step= 1;
-               if(me->totvert>100 && slurph_opt) {
-                       step= me->totvert/50;
+               if(tot>100 && slurph_opt) {
+                       step= tot/50;
                        delta*= step;
                        /* in do_key and cp_key the case a>tot is handled */
                }
                
                cfra= (float)scene->r.cfra;
                
-               for(a=0; a<me->totvert; a+=step, cfra+= delta) {
+               for(a=0; a<tot; a+=step, cfra+= delta) {
                        
                        ctime= bsystem_time(scene, 0, cfra, 0.0); // xxx  ugly cruft!
 #if 0 // XXX old animation system
-                       if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) {
+                       if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
                                ctime /= 100.0;
                                CLAMP(ctime, 0.0, 1.0);
                        }
@@ -1080,42 +1078,33 @@ static int do_mesh_key(Scene *scene, Object *ob, Mesh *me)
                        ctime /= 100.0f;
                        CLAMP(ctime, 0.0f, 1.0f); // XXX for compat, we use this, but this clamping was confusing
                
-                       flag= setkeys(ctime, &me->key->block, k, t, 0);
-                       if(flag==0) {
-                               
-                               do_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k, t, 0);
-                       }
-                       else {
-                               cp_key(a, a+step, me->totvert, (char *)me->mvert->co, me->key, k[2], NULL, 0);
-                       }
+                       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);
                }
-               
-               if(flag && k[2]==me->key->refkey) tex_space_mesh(me);
-               else boundbox_mesh(me, loc, size);
        }
        else {
-               if(me->key->type==KEY_RELATIVE) {
+               if(key->type==KEY_RELATIVE) {
                        KeyBlock *kb;
                        
-                       if (G.f & G_DEBUG) printf("\tdo relative \n");
-                       
-                       for(kb= me->key->block.first; kb; kb= kb->next)
+                       for(kb= key->block.first; kb; kb= kb->next)
                                kb->weights= get_weights_array(ob, kb->vgroup);
 
-                       do_rel_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, 0);
+                       do_rel_key(0, tot, tot, (char *)out, key, actkb, 0);
                        
-                       for(kb= me->key->block.first; kb; kb= kb->next) {
+                       for(kb= key->block.first; kb; kb= kb->next) {
                                if(kb->weights) MEM_freeN(kb->weights);
                                kb->weights= NULL;
                        }
                }
                else {
-                       if (G.f & G_DEBUG) printf("\tdo absolute \n");
-                       
                        ctime= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0f); // xxx old cruft
                        
 #if 0 // XXX old animation system
-                       if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) {
+                       if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
                                ctime /= 100.0;
                                CLAMP(ctime, 0.0, 1.0);
                        }
@@ -1124,106 +1113,69 @@ static int do_mesh_key(Scene *scene, Object *ob, Mesh *me)
                        ctime /= 100.0f;
                        CLAMP(ctime, 0.0f, 1.0f); // XXX for compat, we use this, but this clamping was confusing
                        
-                       flag= setkeys(ctime, &me->key->block, k, t, 0);
-                       if(flag==0) {
-                               do_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k, t, 0);
-                       }
-                       else {
-                               cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, me->key, k[2], NULL, 0);
-                       }
-                       
-                       if(flag && k[2]==me->key->refkey) tex_space_mesh(me);
-                       else boundbox_mesh(me, loc, size);
+                       flag= setkeys(ctime, &key->block, k, t, 0);
+
+                       if(flag==0)
+                               do_key(0, tot, tot, (char *)out, key, actkb, k, t, 0);
+                       else
+                               cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, 0);
                }
        }
-       return 1;
 }
 
-static void do_cu_key(Curve *cu, KeyBlock **k, float *t)
+static void do_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock **k, float *t, char *out, int tot)
 {
        Nurb *nu;
-       int a, step = 0, tot;
        char *poin;
+       int a, step;
        
-       tot= count_curveverts(&cu->nurb);
-       nu= cu->nurb.first;
-       a= 0;
-       
-       while(nu) {
+       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= (char *)nu->bp->vec;
-                       poin -= a*sizeof(BPoint);
-                       
-                       do_key(a, a+step, tot, poin, cu->key, k, t, KEY_BPOINT);
+                       poin= out - a*sizeof(float)*4;
+                       do_key(a, a+step, tot, poin, key, actkb, k, t, KEY_BPOINT);
                }
                else if(nu->bezt) {
-                       
                        step= 3*nu->pntsu;
-                       
-                       poin= (char *)nu->bezt->vec;
-                       poin -= a*sizeof(BezTriple);
-
-                       do_key(a, a+step, tot, poin, cu->key, k, t, KEY_BEZTRIPLE);
-                       
+                       poin= out - a*sizeof(float)*10;
+                       do_key(a, a+step, tot, poin, key, actkb, k, t, KEY_BEZTRIPLE);
                }
-               a+= step;
-               nu=nu->next;
+               else
+                       step= 0;
        }
 }
 
-static void do_rel_cu_key(Curve *cu, float ctime)
+static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, float ctime, char *out, int tot)
 {
        Nurb *nu;
-       int a, step = 0, tot;
        char *poin;
+       int a, step;
        
-       tot= count_curveverts(&cu->nurb);
-       nu= cu->nurb.first;
-       a= 0;
-       while(nu) {
+       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= (char *)nu->bp->vec;
-                       poin -= a*sizeof(BPoint);
-                       
-                       do_rel_key(a, a+step, tot, poin, cu->key, KEY_BPOINT);
+                       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= (char *)nu->bezt->vec;
-                       poin -= a*sizeof(BezTriple);
-
-                       do_rel_key(a, a+step, tot, poin, cu->key, KEY_BEZTRIPLE);
+                       poin= out - a*sizeof(float)*10;
+                       do_rel_key(a, a+step, tot, poin, key, actkb, KEY_BEZTRIPLE);
                }
-               a+= step;
-               
-               nu=nu->next;
+               else
+                       step= 0;
        }
 }
 
-static int do_curve_key(Scene *scene, Curve *cu)
+static void do_curve_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
 {
-       KeyBlock *k[4];
+       Curve *cu= ob->data;
+       KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
        float cfra, ctime, t[4], delta;
-       int a, flag = 0, step = 0, tot;
-       
-       tot= count_curveverts(&cu->nurb);
+       int a, flag = 0, step = 0;
        
-       if(tot==0) return 0;
-       if(cu->key==NULL) return 0;
-       if(cu->key->block.first==NULL) return 0;
-       
-       if(cu->key->slurph) {
-               delta= cu->key->slurph;
+       if(key->slurph) {
+               delta= key->slurph;
                delta/= tot;
                
                step= 1;
@@ -1238,66 +1190,52 @@ static int do_curve_key(Scene *scene, Curve *cu)
                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(cu->key->ipo, KEY_SPEED, &ctime)==0) {
+                       if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
                                ctime /= 100.0;
                                CLAMP(ctime, 0.0, 1.0);
                        }
 #endif // XXX old animation system
                
-                       flag= setkeys(ctime, &cu->key->block, k, t, 0);
-                       if(flag==0) {
-                               
-                               /* do_key(a, a+step, tot, (char *)cu->mvert->co, cu->key, k, t, 0); */
-                       }
-                       else {
-                               /* cp_key(a, a+step, tot, (char *)cu->mvert->co, cu->key, k[2],0); */
-                       }
-               }
+                       flag= setkeys(ctime, &key->block, k, t, 0);
 
-               if(flag && k[2]==cu->key->refkey) tex_space_curve(cu);
-               
-               
+                       if(flag==0)
+                               ; /* do_key(a, a+step, tot, (char *)out, key, k, t, 0); */
+                       else
+                               ; /* cp_key(a, a+step, tot, (char *)out, key, k[2],0); */
+               }
        }
        else {
                
                ctime= bsystem_time(scene, NULL, (float)scene->r.cfra, 0.0);
                
-               if(cu->key->type==KEY_RELATIVE) {
-                       do_rel_cu_key(cu, ctime);
+               if(key->type==KEY_RELATIVE) {
+                       do_rel_cu_key(cu, cu->key, actkb, ctime, out, tot);
                }
                else {
 #if 0 // XXX old animation system
-                       if(calc_ipo_spec(cu->key->ipo, KEY_SPEED, &ctime)==0) {
+                       if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
                                ctime /= 100.0;
                                CLAMP(ctime, 0.0, 1.0);
                        }
 #endif // XXX old animation system
                        
-                       flag= setkeys(ctime, &cu->key->block, k, t, 0);
+                       flag= setkeys(ctime, &key->block, k, t, 0);
                        
-                       if(flag==0) do_cu_key(cu, k, t);
-                       else cp_cu_key(cu, k[2], 0, tot);
-                                       
-                       if(flag && k[2]==cu->key->refkey) tex_space_curve(cu);
+                       if(flag==0) do_cu_key(cu, key, actkb, k, t, out, tot);
+                       else cp_cu_key(cu, key, actkb, k[2], 0, tot, out, tot);
                }
        }
-       
-       return 1;
 }
 
-static int do_latt_key(Scene *scene, Object *ob, Lattice *lt)
+static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, int tot)
 {
-       KeyBlock *k[4];
+       Lattice *lt= ob->data;
+       KeyBlock *k[4], *actkb= ob_get_keyblock(ob);
        float delta, cfra, ctime, t[4];
-       int a, tot, flag;
+       int a, flag;
        
-       if(lt->key==NULL) return 0;
-       if(lt->key->block.first==NULL) return 0;
-
-       tot= lt->pntsu*lt->pntsv*lt->pntsw;
-
-       if(lt->key->slurph) {
-               delta= lt->key->slurph;
+       if(key->slurph) {
+               delta= key->slurph;
                delta/= (float)tot;
                
                cfra= (float)scene->r.cfra;
@@ -1306,74 +1244,110 @@ static int do_latt_key(Scene *scene, Object *ob, Lattice *lt)
                        
                        ctime= bsystem_time(scene, 0, cfra, 0.0); // XXX old cruft
 #if 0 // XXX old animation system
-                       if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) {
+                       if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
                                ctime /= 100.0;
                                CLAMP(ctime, 0.0, 1.0);
                        }
 #endif // XXX old animation system
                
-                       flag= setkeys(ctime, &lt->key->block, k, t, 0);
-                       if(flag==0) {
-                               
-                               do_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k, t, 0);
-                       }
-                       else {
-                               cp_key(a, a+1, tot, (char *)lt->def->vec, lt->key, k[2], NULL, 0);
-                       }
+                       flag= setkeys(ctime, &key->block, k, t, 0);
+
+                       if(flag==0)
+                               do_key(a, a+1, tot, (char *)out, key, actkb, k, t, 0);
+                       else
+                               cp_key(a, a+1, tot, (char *)out, key, actkb, k[2], NULL, 0);
                }               
        }
        else {
-               ctime= bsystem_time(scene, NULL, (float)scene->r.cfra, 0.0);
-       
-               if(lt->key->type==KEY_RELATIVE) {
+               if(key->type==KEY_RELATIVE) {
                        KeyBlock *kb;
                        
-                       for(kb= lt->key->block.first; kb; kb= kb->next)
+                       for(kb= key->block.first; kb; kb= kb->next)
                                kb->weights= get_weights_array(ob, kb->vgroup);
                        
-                       do_rel_key(0, tot, tot, (char *)lt->def->vec, lt->key, 0);
+                       do_rel_key(0, tot, tot, (char *)out, key, actkb, 0);
                        
-                       for(kb= lt->key->block.first; kb; kb= kb->next) {
+                       for(kb= key->block.first; kb; kb= kb->next) {
                                if(kb->weights) MEM_freeN(kb->weights);
                                kb->weights= NULL;
                        }
                }
                else {
+                       ctime= bsystem_time(scene, NULL, (float)scene->r.cfra, 0.0);
+
 #if 0 // XXX old animation system
-                       if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) {
+                       if(calc_ipo_spec(key->ipo, KEY_SPEED, &ctime)==0) {
                                ctime /= 100.0;
                                CLAMP(ctime, 0.0, 1.0);
                        }
 #endif // XXX old animation system
                        
-                       flag= setkeys(ctime, &lt->key->block, k, t, 0);
-                       if(flag==0) {
-                               do_key(0, tot, tot, (char *)lt->def->vec, lt->key, k, t, 0);
-                       }
-                       else {
-                               cp_key(0, tot, tot, (char *)lt->def->vec, lt->key, k[2], NULL, 0);
-                       }
+                       flag= setkeys(ctime, &key->block, k, t, 0);
+
+                       if(flag==0)
+                               do_key(0, tot, tot, (char *)out, key, actkb, k, t, 0);
+                       else
+                               cp_key(0, tot, tot, (char *)out, key, actkb, k[2], NULL, 0);
                }
        }
        
        if(lt->flag & LT_OUTSIDE) outside_lattice(lt);
-       
-       return 1;
 }
 
-/* returns 1 when key applied */
-int do_ob_key(Scene *scene, Object *ob)
+/* returns key coordinates (+ tilt) when key applied, NULL otherwise */
+float *do_ob_key(Scene *scene, Object *ob)
 {
        Key *key= ob_get_key(ob);
+       KeyBlock *actkb= ob_get_keyblock(ob);
+       char *out;
+       int tot= 0, size= 0;
+       
+       if(key==NULL || key->block.first==NULL)
+               return NULL;
+
+       /* compute size of output array */
+       if(ob->type == OB_MESH) {
+               Mesh *me= ob->data;
+
+               tot= me->totvert;
+               size= tot*3*sizeof(float);
+       }
+       else if(ob->type == OB_LATTICE) {
+               Lattice *lt= ob->data;
+
+               tot= lt->pntsu*lt->pntsv*lt->pntsw;
+               size= tot*3*sizeof(float);
+       }
+       else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
+               Curve *cu= ob->data;
+               Nurb *nu;
+
+               for(nu=cu->nurb.first; nu; nu=nu->next) {
+                       if(nu->bezt) {
+                               tot += 3*nu->pntsu;
+                               size += nu->pntsu*10*sizeof(float);
+                       }
+                       else if(nu->bp) {
+                               tot += nu->pntsu*nu->pntsv;
+                               size += nu->pntsu*nu->pntsv*10*sizeof(float);
+                       }
+               }
+       }
+
+       /* if nothing to interpolate, cancel */
+       if(tot == 0 || size == 0)
+               return NULL;
        
-       if(key==NULL)
-               return 0;
+       /* allocate array */
+       out= MEM_callocN(size, "do_ob_key out");
+
+       /* prevent python from screwing this up? anyhoo, the from pointer could be dropped */
+       key->from= (ID *)ob->data;
                
        if(ob->shapeflag & OB_SHAPE_LOCK) {
+               /* shape locked, copy the locked shape instead of blending */
                KeyBlock *kb= BLI_findlink(&key->block, ob->shapenr-1);
                
-               if (G.f & G_DEBUG) printf("ob %s, key %s locked \n", ob->id.name+2, key->id.name+2);
-               
                if(kb && (kb->flag & KEYBLOCK_MUTE))
                        kb= key->refkey;
 
@@ -1382,46 +1356,29 @@ int do_ob_key(Scene *scene, Object *ob)
                        ob->shapenr= 1;
                }
                
-               if(ob->type==OB_MESH) {
-                       Mesh *me= ob->data;
+               if(ELEM(ob->type, OB_MESH, OB_LATTICE)) {
                        float *weights= get_weights_array(ob, kb->vgroup);
 
-                       cp_key(0, me->totvert, me->totvert, (char *)me->mvert->co, key, kb, weights, 0);
-                       
-                       if(weights) MEM_freeN(weights);
-               }
-               else if(ob->type==OB_LATTICE) {
-                       Lattice *lt= ob->data;
-                       float *weights= get_weights_array(ob, kb->vgroup);
-                       int tot= lt->pntsu*lt->pntsv*lt->pntsw;
-                       
-                       cp_key(0, tot, tot, (char *)lt->def->vec, key, kb, weights, 0);
-                       
+                       cp_key(0, tot, tot, (char*)out, key, actkb, kb, weights, 0);
+
                        if(weights) MEM_freeN(weights);
                }
-               else if ELEM(ob->type, OB_CURVE, OB_SURF) {
-                       Curve *cu= ob->data;
-                       int tot= count_curveverts(&cu->nurb);
-                       
-                       cp_cu_key(cu, kb, 0, tot);
-               }
-               return 1;
+               else if(ELEM(ob->type, OB_CURVE, OB_SURF))
+                       cp_cu_key(ob->data, key, actkb, kb, 0, tot, out, tot);
        }
        else {
                /* do shapekey local drivers */
                float ctime= (float)scene->r.cfra; // XXX this needs to be checked
                
-               if (G.f & G_DEBUG) 
-                       printf("ob %s - do shapekey (%s) drivers \n", ob->id.name+2, key->id.name+2);
                BKE_animsys_evaluate_animdata(&key->id, key->adt, ctime, ADT_RECALC_DRIVERS);
                
-               if(ob->type==OB_MESH) return do_mesh_key(scene, ob, ob->data);
-               else if(ob->type==OB_CURVE) return do_curve_key(scene, ob->data);
-               else if(ob->type==OB_SURF) return do_curve_key(scene, ob->data);
-               else if(ob->type==OB_LATTICE) return do_latt_key(scene, ob, ob->data);
+               if(ob->type==OB_MESH) do_mesh_key(scene, ob, key, out, tot);
+               else if(ob->type==OB_LATTICE) do_latt_key(scene, ob, key, out, tot);
+               else if(ob->type==OB_CURVE) do_curve_key(scene, ob, key, out, tot);
+               else if(ob->type==OB_SURF) do_curve_key(scene, ob, key, out, tot);
        }
        
-       return 0;
+       return (float*)out;
 }
 
 Key *ob_get_key(Object *ob)
@@ -1490,3 +1447,24 @@ KeyBlock *key_get_named_keyblock(Key *key, const char name[])
        
        return NULL;
 }
+
+/* Get RNA-Path for 'value' setting of the given ShapeKey 
+ * NOTE: the user needs to free the returned string once they're finishe with it
+ */
+char *key_get_curValue_rnaPath(Key *key, KeyBlock *kb)
+{
+       PointerRNA ptr;
+       PropertyRNA *prop;
+       
+       /* sanity checks */
+       if ELEM(NULL, key, kb)
+               return NULL;
+       
+       /* create the RNA pointer */
+       RNA_pointer_create(&key->id, &RNA_ShapeKey, kb, &ptr);
+       /* get pointer to the property too */
+       prop= RNA_struct_find_property(&ptr, "value");
+       
+       /* return the path */
+       return RNA_path_from_ID_to_property(&ptr, prop);
+}
index 0faff6d33543bc2139271dcd12cc9fc42a14102d..4ebd36f36c727bae2b167fe42da77afff98d0a97 100644 (file)
@@ -996,10 +996,6 @@ void lattice_calc_modifiers(Scene *scene, Object *ob)
 
        freedisplist(&ob->disp);
 
-       if (!editmode) {
-               do_ob_key(scene, ob);
-       }
-
        for (; md; md=md->next) {
                ModifierTypeInfo *mti = modifierType_getInfo(md->type);
 
index c1093c119dc1e72e2bb6605cb3f7a53043522d5c..c2260e1e76144242272a09127dc4ebedf1a045e4 100644 (file)
@@ -485,6 +485,18 @@ ID *material_from(Object *ob, int act)
        else return ob->data;
 }
 
+Material *give_node_material(Material *ma)
+{
+       if(ma && ma->use_nodes && ma->nodetree) {
+               bNode *node= nodeGetActiveID(ma->nodetree, ID_MA);
+
+               if(node)
+                       return (Material *)node->id;
+       }
+
+       return NULL;
+}
+
 /* GS reads the memory pointed at in a specific ordering. There are,
  * however two definitions for it. I have jotted them down here, both,
  * but I think the first one is actually used. The thing is that
@@ -982,7 +994,7 @@ int object_remove_material_slot(Object *ob)
 /* if g==NULL, it only does r channel */
 void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
 {
-       float tmp, facm= 1.0-fac;
+       float tmp, facm= 1.0f-fac;
        
        switch (type) {
                case MA_RAMP_BLEND:
@@ -1007,26 +1019,26 @@ void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
                        }
                                break;
                case MA_RAMP_SCREEN:
-                       *r = 1.0 - (facm + fac*(1.0 - col[0])) * (1.0 - *r);
+                       *r = 1.0f - (facm + fac*(1.0f - col[0])) * (1.0f - *r);
                        if(g) {
-                               *g = 1.0 - (facm + fac*(1.0 - col[1])) * (1.0 - *g);
-                               *b = 1.0 - (facm + fac*(1.0 - col[2])) * (1.0 - *b);
+                               *g = 1.0f - (facm + fac*(1.0f - col[1])) * (1.0f - *g);
+                               *b = 1.0f - (facm + fac*(1.0f - col[2])) * (1.0f - *b);
                        }
                                break;
                case MA_RAMP_OVERLAY:
                        if(*r < 0.5f)
                                *r *= (facm + 2.0f*fac*col[0]);
                        else
-                               *r = 1.0 - (facm + 2.0f*fac*(1.0 - col[0])) * (1.0 - *r);
+                               *r = 1.0f - (facm + 2.0f*fac*(1.0f - col[0])) * (1.0f - *r);
                        if(g) {
                                if(*g < 0.5f)
                                        *g *= (facm + 2.0f*fac*col[1]);
                                else
-                                       *g = 1.0 - (facm + 2.0f*fac*(1.0 - col[1])) * (1.0 - *g);
+                                       *g = 1.0f - (facm + 2.0f*fac*(1.0f - col[1])) * (1.0f - *g);
                                if(*b < 0.5f)
                                        *b *= (facm + 2.0f*fac*col[2]);
                                else
-                                       *b = 1.0 - (facm + 2.0f*fac*(1.0 - col[2])) * (1.0 - *b);
+                                       *b = 1.0f - (facm + 2.0f*fac*(1.0f - col[2])) * (1.0f - *b);
                        }
                                break;
                case MA_RAMP_SUB:
@@ -1037,12 +1049,12 @@ void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
                        }
                                break;
                case MA_RAMP_DIV:
-                       if(col[0]!=0.0)
+                       if(col[0]!=0.0f)
                                *r = facm*(*r) + fac*(*r)/col[0];
                        if(g) {
-                               if(col[1]!=0.0)
+                               if(col[1]!=0.0f)
                                        *g = facm*(*g) + fac*(*g)/col[1];
-                               if(col[2]!=0.0)
+                               if(col[2]!=0.0f)
                                        *b = facm*(*b) + fac*(*b)/col[2];
                        }
                                break;
@@ -1076,31 +1088,31 @@ void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
                case MA_RAMP_DODGE:                     
                        
                                
-                       if(*r !=0.0){
-                               tmp = 1.0 - fac*col[0];
-                               if(tmp <= 0.0)
-                                       *r = 1.0;
-                               else if ((tmp = (*r) / tmp)> 1.0)
-                                       *r = 1.0;
+                       if(*r !=0.0f){
+                               tmp = 1.0f - fac*col[0];
+                               if(tmp <= 0.0f)
+                                       *r = 1.0f;
+                               else if ((tmp = (*r) / tmp)> 1.0f)
+                                       *r = 1.0f;
                                else 
                                        *r = tmp;
                        }
                        if(g) {
-                               if(*g !=0.0){
-                                       tmp = 1.0 - fac*col[1];
-                                       if(tmp <= 0.0 )
-                                               *g = 1.0;
-                                       else if ((tmp = (*g) / tmp) > 1.0 )
-                                               *g = 1.0;
+                               if(*g !=0.0f){
+                                       tmp = 1.0f - fac*col[1];
+                                       if(tmp <= 0.0f )
+                                               *g = 1.0f;
+                                       else if ((tmp = (*g) / tmp) > 1.0f )
+                                               *g = 1.0f;
                                        else
                                                *g = tmp;
                                }
-                               if(*b !=0.0){
-                                       tmp = 1.0 - fac*col[2];
-                                       if(tmp <= 0.0)
-                                               *b = 1.0;
-                                       else if ((tmp = (*b) / tmp) > 1.0 )
-                                               *b = 1.0;
+                               if(*b !=0.0f){
+                                       tmp = 1.0f - fac*col[2];
+                                       if(tmp <= 0.0f)
+                                               *b = 1.0f;
+                                       else if ((tmp = (*b) / tmp) > 1.0f )
+                                               *b = 1.0f;
                                        else
                                                *b = tmp;
                                }
@@ -1111,33 +1123,33 @@ void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
                        
                        tmp = facm + fac*col[0];
                        
-                       if(tmp <= 0.0)
-                               *r = 0.0;
-                       else if (( tmp = (1.0 - (1.0 - (*r)) / tmp )) < 0.0)
-                               *r = 0.0;
-                       else if (tmp > 1.0)
-                               *r=1.0;
+                       if(tmp <= 0.0f)
+                               *r = 0.0f;
+                       else if (( tmp = (1.0f - (1.0f - (*r)) / tmp )) < 0.0f)
+                               *r = 0.0f;
+                       else if (tmp > 1.0f)
+                               *r=1.0f;
                        else 
                                *r = tmp; 
 
                        if(g) {
                                tmp = facm + fac*col[1];
-                               if(tmp <= 0.0)
-                                       *g = 0.0;
-                               else if (( tmp = (1.0 - (1.0 - (*g)) / tmp )) < 0.0 )
-                                       *g = 0.0;
-                               else if(tmp >1.0)
-                                       *g=1.0;
+                               if(tmp <= 0.0f)
+                                       *g = 0.0f;
+                               else if (( tmp = (1.0f - (1.0f - (*g)) / tmp )) < 0.0f )
+                                       *g = 0.0f;
+                               else if(tmp >1.0f)
+                                       *g=1.0f;
                                else
                                        *g = tmp;
                                        
                                tmp = facm + fac*col[2];
-                               if(tmp <= 0.0)
-                                       *b = 0.0;
-                               else if (( tmp = (1.0 - (1.0 - (*b)) / tmp )) < 0.0  )
-                                       *b = 0.0;
-                               else if(tmp >1.0)
-                                       *b= 1.0;
+                               if(tmp <= 0.0f)
+                                       *b = 0.0f;
+                               else if (( tmp = (1.0f - (1.0f - (*b)) / tmp )) < 0.0f  )
+                                       *b = 0.0f;
+                               else if(tmp >1.0f)
+                                       *b= 1.0f;
                                else
                                        *b = tmp;
                        }
@@ -1197,29 +1209,29 @@ void ramp_blend(int type, float *r, float *g, float *b, float fac, float *col)
                 float scr, scg, scb; 
                  
                 /* first calculate non-fac based Screen mix */ 
-                scr = 1.0 - ((1.0 - col[0])) * (1.0 - *r); 
-                scg = 1.0 - ((1.0 - col[1])) * (1.0 - *g); 
-                scb = 1.0 - ((1.0 - col[2])) * (1.0 - *b); 
+                scr = 1.0f - (1.0f - col[0]) * (1.0f - *r); 
+                scg = 1.0f - (1.0f - col[1]) * (1.0f - *g); 
+                scb = 1.0f - (1.0f - col[2]) * (1.0f - *b); 
                  
-                *r = facm*(*r) + fac*(((1.0 - *r) * col[0] * (*r)) + (*r * scr)); 
-                *g = facm*(*g) + fac*(((1.0 - *g) * col[1] * (*g)) + (*g * scg)); 
-                *b = facm*(*b) + fac*(((1.0 - *b) * col[2] * (*b)) + (*b * scb)); 
+                *r = facm*(*r) + fac*(((1.0f - *r) * col[0] * (*r)) + (*r * scr)); 
+                *g = facm*(*g) + fac*(((1.0f - *g) * col[1] * (*g)) + (*g * scg)); 
+                *b = facm*(*b) + fac*(((1.0f - *b) * col[2] * (*b)) + (*b * scb)); 
             } 
                 break; 
         case MA_RAMP_LINEAR: 
-            if (col[0] > 0.5)  
-                *r = *r + fac*(2*(col[0]-0.5)); 
+            if (col[0] > 0.5f)  
+                *r = *r + fac*(2.0f*(col[0]-0.5f)); 
             else  
-                *r = *r + fac*(2*(col[0]) - 1); 
+                *r = *r + fac*(2.0f*(col[0]) - 1.0f); 
             if (g){ 
-                if (col[1] > 0.5)  
-                    *g = *g + fac*(2*(col[1]-0.5)); 
+                if (col[1] > 0.5f)  
+                    *g = *g + fac*(2.0f*(col[1]-0.5f)); 
                 else  
-                    *g = *g + fac*(2*(col[1]) -1); 
-                if (col[2] > 0.5)  
-                    *b = *b + fac*(2*(col[2]-0.5)); 
+                    *g = *g + fac*(2.0f*(col[1]) -1.0f); 
+                if (col[2] > 0.5f)  
+                    *b = *b + fac*(2.0f*(col[2]-0.5f)); 
                 else  
-                    *b = *b + fac*(2*(col[2]) - 1); 
+                    *b = *b + fac*(2.0f*(col[2]) - 1.0f); 
             } 
                 break; 
        }       
index 2725d1dc894c438b7cb389faa8fe905d17437301..f6d1b332e141fb5ad3df3dd6e24fe8e886ee812a 100644 (file)
@@ -345,14 +345,14 @@ Mesh *copy_mesh(Mesh *me)
        return men;
 }
 
-BMesh *BKE_mesh_to_bmesh(Mesh *me)
+BMesh *BKE_mesh_to_bmesh(Mesh *me, Object *ob)
 {
        BMesh *bm;
        int allocsize[4] = {512,512,2048,512};
 
        bm = BM_Make_Mesh(allocsize);
 
-       BMO_CallOpf(bm, "mesh_to_bmesh mesh=%p", me);
+       BMO_CallOpf(bm, "mesh_to_bmesh mesh=%p object=%p", me, ob);
 
        return bm;
 }
@@ -496,35 +496,12 @@ void boundbox_mesh(Mesh *me, float *loc, float *size)
 
 void tex_space_mesh(Mesh *me)
 {
-       KeyBlock *kb;
-       float *fp, loc[3], size[3], min[3], max[3];
+       float loc[3], size[3];
        int a;
 
        boundbox_mesh(me, loc, size);
 
        if(me->texflag & AUTOSPACE) {
-               if(me->key) {
-                       kb= me->key->refkey;
-                       if (kb) {
-                               
-                               INIT_MINMAX(min, max);
-                               
-                               fp= kb->data;
-                               for(a=0; a<kb->totelem; a++, fp+=3) {   
-                                       DO_MINMAX(fp, min, max);
-                               }
-                               if(kb->totelem) {
-                                       loc[0]= (min[0]+max[0])/2.0f; loc[1]= (min[1]+max[1])/2.0f; loc[2]= (min[2]+max[2])/2.0f;
-                                       size[0]= (max[0]-min[0])/2.0f; size[1]= (max[1]-min[1])/2.0f; size[2]= (max[2]-min[2])/2.0f;
-                               }
-                               else {
-                                       loc[0]= loc[1]= loc[2]= 0.0;
-                                       size[0]= size[1]= size[2]= 0.0;
-                               }
-                               
-                       }
-               }
-
                for (a=0; a<3; a++) {
                        if(size[a]==0.0) size[a]= 1.0;
                        else if(size[a]>0.0 && size[a]<0.00001) size[a]= 0.00001;
@@ -564,26 +541,20 @@ void mesh_get_texspace(Mesh *me, float *loc_r, float *rot_r, float *size_r)
 float *get_mesh_orco_verts(Object *ob)
 {
        Mesh *me = ob->data;
+       MVert *mvert = NULL;
+       Mesh *tme = me->texcomesh?me->texcomesh:me;
        int a, totvert;
        float (*vcos)[3] = NULL;
 
        /* Get appropriate vertex coordinates */
-       if(me->key && me->texcomesh==0 && me->key->refkey) {
-               vcos= mesh_getRefKeyCos(me, &totvert);
-       }
-       else {
-               MVert *mvert = NULL;            
-               Mesh *tme = me->texcomesh?me->texcomesh:me;
+       vcos = MEM_callocN(sizeof(*vcos)*me->totvert, "orco mesh");
+       mvert = tme->mvert;
+       totvert = MIN2(tme->totvert, me->totvert);
 
-               vcos = MEM_callocN(sizeof(*vcos)*me->totvert, "orco mesh");
-               mvert = tme->mvert;
-               totvert = MIN2(tme->totvert, me->totvert);
-
-               for(a=0; a<totvert; a++, mvert++) {
-                       vcos[a][0]= mvert->co[0];
-                       vcos[a][1]= mvert->co[1];
-                       vcos[a][2]= mvert->co[2];
-               }
+       for(a=0; a<totvert; a++, mvert++) {
+               vcos[a][0]= mvert->co[0];
+               vcos[a][1]= mvert->co[1];
+               vcos[a][2]= mvert->co[2];
        }
 
        return (float*)vcos;
@@ -1354,29 +1325,6 @@ float (*mesh_getVertexCos(Mesh *me, int *numVerts_r))[3]
        return cos;
 }
 
-float (*mesh_getRefKeyCos(Mesh *me, int *numVerts_r))[3]
-{
-       KeyBlock *kb;
-       float (*cos)[3] = NULL;
-       int totvert;
-       
-       if(me->key && me->key->refkey) {
-               if(numVerts_r) *numVerts_r= me->totvert;
-               
-               kb= me->key->refkey;
-               
-               /* prevent accessing invalid memory */
-               if (me->totvert > kb->totelem)          cos= MEM_callocN(sizeof(*cos)*me->totvert, "vertexcos1");
-               else                                                            cos= MEM_mallocN(sizeof(*cos)*me->totvert, "vertexcos1");
-               
-               totvert= MIN2(kb->totelem, me->totvert);
-
-               memcpy(cos, kb->data, sizeof(*cos)*totvert);
-       }
-
-       return cos;
-}
-
 UvVertMap *make_uv_vert_map(struct MFace *mface, struct MTFace *tface, unsigned int totface, unsigned int totvert, int selected, float *limit)
 {
        UvVertMap *vmap;
index a70d1a02bb463b9df139589d9385e9077d5e82c3..2ceebd3c0a52e2e0a900b2720ea6a137e55bf674 100644 (file)
@@ -64,6 +64,7 @@
 #include "DNA_curve_types.h"
 #include "DNA_effect_types.h"
 #include "DNA_group_types.h"
+#include "DNA_key_types.h"
 #include "DNA_material_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
@@ -96,6 +97,7 @@
 #include "BKE_fluidsim.h"
 #include "BKE_global.h"
 #include "BKE_multires.h"
+#include "BKE_key.h"
 #include "BKE_lattice.h"
 #include "BKE_library.h"
 #include "BKE_material.h"
@@ -1196,9 +1198,9 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd,
 
        /* need to avoid infinite recursion here */
        if(amd->start_cap && amd->start_cap != ob)
-               start_cap = mesh_get_derived_final(scene, amd->start_cap, CD_MASK_MESH);
+               start_cap = amd->start_cap->derivedFinal;
        if(amd->end_cap && amd->end_cap != ob)
-               end_cap = mesh_get_derived_final(scene, amd->end_cap, CD_MASK_MESH);
+               end_cap = amd->end_cap->derivedFinal;
 
        Mat4One(offset);
 
@@ -5549,7 +5551,7 @@ static DerivedMesh *booleanModifier_applyModifier(
 {
        // XXX doesn't handle derived data
        BooleanModifierData *bmd = (BooleanModifierData*) md;
-       DerivedMesh *dm = mesh_get_derived_final(md->scene, bmd->object, CD_MASK_BAREMESH);
+       DerivedMesh *dm = bmd->object->derivedFinal;
 
        /* we do a quick sanity check */
        if(dm && (derivedData->getNumTessFaces(derivedData) > 3)
@@ -7536,6 +7538,52 @@ static void simpledeformModifier_deformVertsEM(ModifierData *md, Object *ob, BME
                dm->release(dm);
 }
 
+/* Shape Key */
+
+static void shapekeyModifier_deformVerts(
+                                        ModifierData *md, Object *ob, DerivedMesh *derivedData,
+      float (*vertexCos)[3], int numVerts, int useRenderParams, int isFinalCalc)
+{
+       KeyBlock *kb= ob_get_keyblock(ob);
+       float (*deformedVerts)[3];
+
+       if(kb && kb->totelem == numVerts) {
+               deformedVerts= (float(*)[3])do_ob_key(md->scene, ob);
+               if(deformedVerts) {
+                       memcpy(vertexCos, deformedVerts, sizeof(float)*3*numVerts);
+                       MEM_freeN(deformedVerts);
+               }
+       }
+}
+
+static void shapekeyModifier_deformVertsEM(
+                                          ModifierData *md, Object *ob, EditMesh *editData,
+       DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+       Key *key= ob_get_key(ob);
+
+       if(key && key->type == KEY_RELATIVE)
+               shapekeyModifier_deformVerts(md, ob, derivedData, vertexCos, numVerts, 0, 0);
+}
+
+static void shapekeyModifier_deformMatricesEM(
+                                             ModifierData *md, Object *ob, EditMesh *editData,
+          DerivedMesh *derivedData, float (*vertexCos)[3],
+                                            float (*defMats)[3][3], int numVerts)
+{
+       Key *key= ob_get_key(ob);
+       KeyBlock *kb= ob_get_keyblock(ob);
+       float scale[3][3];
+       int a;
+
+       if(kb && kb->totelem==numVerts && kb!=key->refkey) {
+               Mat3Scale(scale, kb->curval);
+
+               for(a=0; a<numVerts; a++)
+                       Mat3CpyMat3(defMats[a], scale);
+       }
+}
+
 /***/
 
 static ModifierTypeInfo typeArr[NUM_MODIFIER_TYPES];
@@ -7940,6 +7988,14 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
                mti->copyData = multiresModifier_copyData;
                mti->applyModifier = multiresModifier_applyModifier;
 
+               mti = INIT_TYPE(ShapeKey);
+               mti->type = eModifierTypeType_OnlyDeform;
+               mti->flags = eModifierTypeFlag_AcceptsCVs
+                               | eModifierTypeFlag_SupportsEditmode;
+               mti->deformVerts = shapekeyModifier_deformVerts;
+               mti->deformVertsEM = shapekeyModifier_deformVertsEM;
+               mti->deformMatricesEM = shapekeyModifier_deformMatricesEM;
+
                typeArrInit = 0;
 #undef INIT_TYPE
        }
@@ -8104,9 +8160,9 @@ void modifier_setError(ModifierData *md, char *format, ...)
  * also used in transform_conversion.c, to detect CrazySpace [tm] (2nd arg
  * then is NULL)
  */
-int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r)
+int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r, int virtual_)
 {
-       ModifierData *md = ob->modifiers.first;
+       ModifierData *md = (virtual_)? modifiers_getVirtualModifierList(ob): ob->modifiers.first;
        int i, cageIndex = -1;
 
        /* Find the last modifier acting on the cage. */
@@ -8215,11 +8271,11 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob)
        static ArmatureModifierData amd;
        static CurveModifierData cmd;
        static LatticeModifierData lmd;
+       static ShapeKeyModifierData smd;
        static int init = 1;
+       ModifierData *md;
 
        if (init) {
-               ModifierData *md;
-
                md = modifier_new(eModifierType_Armature);
                amd = *((ArmatureModifierData*) md);
                modifier_free(md);
@@ -8232,32 +8288,50 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob)
                lmd = *((LatticeModifierData*) md);
                modifier_free(md);
 
+               md = modifier_new(eModifierType_ShapeKey);
+               smd = *((ShapeKeyModifierData*) md);
+               modifier_free(md);
+
                amd.modifier.mode |= eModifierMode_Virtual;
                cmd.modifier.mode |= eModifierMode_Virtual;
                lmd.modifier.mode |= eModifierMode_Virtual;
+               smd.modifier.mode |= eModifierMode_Virtual;
 
                init = 0;
        }
 
-       if (ob->parent) {
+       md = ob->modifiers.first;
+
+       if(ob->parent) {
                if(ob->parent->type==OB_ARMATURE && ob->partype==PARSKEL) {
                        amd.object = ob->parent;
-                       amd.modifier.next = ob->modifiers.first;
+                       amd.modifier.next = md;
                        amd.deformflag= ((bArmature *)(ob->parent->data))->deformflag;
-                       return &amd.modifier;
+                       md = &amd.modifier;
                } else if(ob->parent->type==OB_CURVE && ob->partype==PARSKEL) {
                        cmd.object = ob->parent;
                        cmd.defaxis = ob->trackflag + 1;
-                       cmd.modifier.next = ob->modifiers.first;
-                       return &cmd.modifier;
+                       cmd.modifier.next = md;
+                       md = &cmd.modifier;
                } else if(ob->parent->type==OB_LATTICE && ob->partype==PARSKEL) {
                        lmd.object = ob->parent;
-                       lmd.modifier.next = ob->modifiers.first;
-                       return &lmd.modifier;
+                       lmd.modifier.next = md;
+                       md = &lmd.modifier;
                }
        }
 
-       return ob->modifiers.first;
+       /* shape key modifier, not yet for curves */
+       if(ELEM(ob->type, OB_MESH, OB_LATTICE) && ob_get_key(ob)) {
+               if(ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE))
+                       smd.modifier.mode |= eModifierMode_Editmode|eModifierMode_OnCage;
+               else
+                       smd.modifier.mode &= ~eModifierMode_Editmode|eModifierMode_OnCage;
+
+               smd.modifier.next = md;
+               md = &smd.modifier;
+       }
+
+       return md;
 }
 /* Takes an object and returns its first selected armature, else just its
  * armature
@@ -8334,6 +8408,8 @@ int modifier_isDeformer(ModifierData *md)
                return 1;
        if (md->type==eModifierType_Lattice)
                return 1;
+       if (md->type==eModifierType_ShapeKey)
+               return 1;
        
        return 0;
 }
index 1a89de7e8d6bb515476820557241d190594e2f73..2776444c8a0351e2b6002e30cdffd494b2185a2f 100644 (file)
@@ -1198,6 +1198,8 @@ static void node_init_preview(bNode *node, int xsize, int ysize)
                node->preview->xsize= xsize;
                node->preview->ysize= ysize;
        }
+       else
+               memset(node->preview->rect, 0, 4*xsize + xsize*ysize*sizeof(float)*4);
 }
 
 void ntreeInitPreview(bNodeTree *ntree, int xsize, int ysize)
index cb9748ddb85c543f990b9179748097d03283c3ba..964d8d9449f40fd63ac06856ee08204220d79465 100644 (file)
@@ -1134,6 +1134,8 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys)
        psysn->pathcache= NULL;
        psysn->childcache= NULL;
        psysn->edit= NULL;
+       psysn->frand= NULL;
+       psysn->pdd= NULL;
        
        psysn->pathcachebufs.first = psysn->pathcachebufs.last = NULL;
        psysn->childcachebufs.first = psysn->childcachebufs.last = NULL;
index f17d2fbdcac408e8fe964f1b9f60549f55c94e24..3dfe3966e2fe1ef2ac0c3f3068e3888cebd5f3da 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "DNA_brush_types.h"
 #include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
 #include "DNA_scene_types.h"
 
 #include "BKE_brush.h"
@@ -160,8 +161,7 @@ void paint_brush_slot_remove(Paint *p)
 
 int paint_facesel_test(Object *ob)
 {
-       return (G.f&G_FACESELECT) && (ob && (ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT)));
-
+       return (ob && ob->data && (((Mesh *)ob->data)->editflag & ME_EDIT_PAINT_MASK) && (ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT)));
 }
 
 void paint_init(Paint *p, const char col[3])
index 555f66c86c88d6a4d6eb5a6559fd264700640e39..7e9cf19670ebc40ebb58feb998c185b45e8cac49 100644 (file)
@@ -2278,15 +2278,20 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c
        ParticleSettings *part = psys->part;
        ParticleEditSettings *pset = &scene->toolsettings->particle;
        int totparent=0, between=0;
-       int steps = (int)pow(2.0,(double)part->draw_step);
+       int steps = (int)pow(2.0, (double)part->draw_step);
        int totchild = psys->totchild;
        int i, seed, totthread= threads[0].tot;
 
        /*---start figuring out what is actually wanted---*/
-       if(psys_in_edit_mode(scene, psys))
+       if(psys_in_edit_mode(scene, psys)) {
+               ParticleEditSettings *pset = &scene->toolsettings->particle;
+
                if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_DRAW_PART)==0)
                        totchild=0;
 
+               steps = (int)pow(2.0, (double)pset->draw_step);
+       }
+
        if(totchild && part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES){
                totparent=(int)(totchild*part->parents*0.3);
                
@@ -2361,7 +2366,7 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle
        ParticleSystem *psys = ctx->sim.psys;
        ParticleSettings *part = psys->part;
        ParticleCacheKey **cache= psys->childcache;
-       ParticleCacheKey **pcache= psys->pathcache;
+       ParticleCacheKey **pcache= psys_in_edit_mode(ctx->sim.scene, psys) ? psys->edit->pathcache : psys->pathcache;
        ParticleCacheKey *state, *par = NULL, *key[4];
        ParticleData *pa=NULL;
        ParticleTexture ptex;
@@ -2373,6 +2378,9 @@ static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle
        int k, cpa_num;
        short cpa_from;
 
+       if(!pcache)
+               return;
+
        if(part->flag & PART_BRANCHING) {
                branch_begin=rng_getFloat(thread->rng_path);
                branch_end=branch_begin+(1.0f-branch_begin)*rng_getFloat(thread->rng_path);
@@ -2955,7 +2963,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
        
        float birthtime = 0.0, dietime = 0.0;
        float t, time = 0.0, keytime = 0.0, frs_sec;
-       float hairmat[4][4];
+       float hairmat[4][4], rotmat[3][3], prev_tangent[3];
        int k,i;
        int steps = (int)pow(2.0, (double)pset->draw_step);
        int totpart = edit->totpoint;
@@ -2999,8 +3007,12 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
                /*--get the first data points--*/
                init_particle_interpolation(ob, psys, pa, &pind);
 
-               if(psys)
+               if(psys) {
                        psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
+                       VECCOPY(rotmat[0], hairmat[2]);
+                       VECCOPY(rotmat[1], hairmat[1]);
+                       VECCOPY(rotmat[2], hairmat[0]);
+               }
 
                birthtime = pind.birthtime;
                dietime = pind.dietime;
@@ -3021,9 +3033,55 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
                        do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result);
 
                         /* non-hair points are allready in global space */
-                       if(psys && !(psys->flag & PSYS_GLOBAL_HAIR))
+                       if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
                                Mat4MulVecfl(hairmat, result.co);
 
+                               /* create rotations for proper creation of children */
+                               if(k) {
+                                       float cosangle, angle, tangent[3], normal[3], q[4];
+
+                                       if(k == 1) {
+                                               /* calculate initial tangent for incremental rotations */
+                                               VECSUB(tangent, ca->co, (ca - 1)->co);
+                                               VECCOPY(prev_tangent, tangent);
+                                               Normalize(prev_tangent);
+
+                                               /* First rotation is based on emitting face orientation.                */
+                                               /* This is way better than having flipping rotations resulting  */
+                                               /* from using a global axis as a rotation pole (vec_to_quat()). */
+                                               /* It's not an ideal solution though since it disregards the    */
+                                               /* initial tangent, but taking that in to account will allow    */
+                                               /* the possibility of flipping again. -jahka                                    */
+                                               Mat3ToQuat_is_ok(rotmat, (ca-1)->rot);
+                                       }
+                                       else {
+                                               VECSUB(tangent, ca->co, (ca - 1)->co);
+                                               Normalize(tangent);
+
+                                               cosangle= Inpf(tangent, prev_tangent);
+
+                                               /* note we do the comparison on cosangle instead of
+                                               * angle, since floating point accuracy makes it give
+                                               * different results across platforms */
+                                               if(cosangle > 0.999999f) {
+                                                       QUATCOPY((ca - 1)->rot, (ca - 2)->rot);
+                                               }
+                                               else {
+                                                       angle= saacos(cosangle);
+                                                       Crossf(normal, prev_tangent, tangent);
+                                                       VecRotToQuat(normal, angle, q);
+                                                       QuatMul((ca - 1)->rot, q, (ca - 2)->rot);
+                                               }
+
+                                               VECCOPY(prev_tangent, tangent);
+                                       }
+
+                                       if(k == steps)
+                                               QUATCOPY(ca->rot, (ca - 1)->rot);
+                               }
+
+                       }
+
                        VECCOPY(ca->co, result.co);
 
                        ca->vel[0] = ca->vel[1] = 0.0f;
@@ -3054,6 +3112,11 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
        }
 
        edit->totcached = totpart;
+
+       if(psys && psys->part->type == PART_HAIR) {
+               ParticleSimulationData sim = {scene, ob, psys, psys_get_modifier(ob, psys), NULL};
+               psys_cache_child_paths(&sim, cfra, 1);
+       }
 }
 /************************************************/
 /*                     Particle Key handling                           */
@@ -3766,6 +3829,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
                pind.keyed = keyed;
                pind.cache = cached ? psys->pointcache : NULL;
                pind.epoint = NULL;
+               pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
                pind.dm = psys->hair_out_dm;
                init_particle_interpolation(sim->ob, psys, pa, &pind);
                do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, state);
index 00b1672dea61ff94a646d72725870163c2eb2bda..446bd263f5df8dde329f3ea6384fdcd9479b3db6 100644 (file)
@@ -3504,8 +3504,6 @@ static void psys_changed_physics(ParticleSimulationData *sim)
        if(part->phystype == PART_PHYS_BOIDS && part->boids == NULL) {
                BoidState *state;
 
-               psys_check_boid_data(sim->psys);
-
                part->boids = MEM_callocN(sizeof(BoidSettings), "Boid Settings");
                boid_default_settings(part->boids);
 
@@ -3518,6 +3516,8 @@ static void psys_changed_physics(ParticleSimulationData *sim)
                state->flag |= BOIDSTATE_CURRENT;
                BLI_addtail(&part->boids->states, state);
        }
+
+       psys_check_boid_data(sim->psys);
 }
 static void particles_fluid_step(ParticleSimulationData *sim, int cfra)
 {      
index b80df60e726464f6c47f12097498fef37005198b..48eb58687dac5bea9c27dd2af8f9b87bb8f70f51 100644 (file)
@@ -69,6 +69,13 @@ static int blender_test_break() {return 0;}
 /* **** XXX ******** */
 
 
+void printf_strip(Sequence *seq)
+{
+       fprintf(stderr, "name: '%s', len:%d, start:%d, (startofs:%d, endofs:%d), (startstill:%d, endstill:%d), machine:%d, (startdisp:%d, enddisp:%d)\n",
+                       seq->name, seq->len, seq->start, seq->startofs, seq->endofs, seq->startstill, seq->endstill, seq->machine, seq->startdisp, seq->enddisp);
+       fprintf(stderr, "\tseq_tx_set_final_left: %d %d\n\n", seq_tx_get_final_left(seq, 0), seq_tx_get_final_right(seq, 0));
+}
+
 /* **********************************************************************
    alloc / free functions
    ********************************************************************** */
@@ -3238,7 +3245,7 @@ void seq_tx_set_final_left(Sequence *seq, int val)
 {
        if (val < (seq)->start) {
                seq->startstill = abs(val - (seq)->start);
-                               (seq)->startofs = 0;
+               seq->startofs = 0;
        } else {
                seq->startofs = abs(val - (seq)->start);
                seq->startstill = 0;
@@ -3249,7 +3256,7 @@ void seq_tx_set_final_right(Sequence *seq, int val)
 {
        if (val > (seq)->start + (seq)->len) {
                seq->endstill = abs(val - (seq->start + (seq)->len));
-               (seq)->endofs = 0;
+               seq->endofs = 0;
        } else {
                seq->endofs = abs(val - ((seq)->start + (seq)->len));
                seq->endstill = 0;
@@ -3334,18 +3341,25 @@ int seq_tx_test(Sequence * seq)
        return (seq->type < SEQ_EFFECT) || (get_sequence_effect_num_inputs(seq->type) == 0);
 }
 
+static int seq_overlap(Sequence *seq1, Sequence *seq2)
+{
+       if(seq1 != seq2)
+               if(seq1->machine==seq2->machine)
+                       if(((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp))==0)
+                               return 1;
+
+       return 0;
+}
+
 int seq_test_overlap(ListBase * seqbasep, Sequence *test)
 {
        Sequence *seq;
 
        seq= seqbasep->first;
        while(seq) {
-               if(seq!=test) {
-                       if(test->machine==seq->machine) {
-                               if( (test->enddisp <= seq->startdisp) || (test->startdisp >= seq->enddisp) );
-                               else return 1;
-                       }
-               }
+               if(seq_overlap(test, seq))
+                       return 1;
+
                seq= seq->next;
        }
        return 0;
@@ -3403,6 +3417,76 @@ int shuffle_seq(ListBase * seqbasep, Sequence *test)
        }
 }
 
+static int shuffle_seq_time_offset_test(ListBase * seqbasep, char dir)
+{
+       int offset= 0;
+       Sequence *seq, *seq_other;
+
+       for(seq= seqbasep->first; seq; seq= seq->next) {
+               if(seq->tmp) {
+                       for(seq_other= seqbasep->first; seq_other; seq_other= seq_other->next) {
+                               if(seq_overlap(seq, seq_other)) {
+                                       if(dir=='L') {
+                                               offset= MIN2(offset, seq_other->startdisp - seq->enddisp);
+                                       }
+                                       else {
+                                               offset= MAX2(offset, seq_other->enddisp - seq->startdisp);
+                                       }
+                               }
+                       }
+               }
+       }
+       return offset;
+}
+
+static int shuffle_seq_time_offset(ListBase * seqbasep, char dir)
+{
+       int ofs= 0;
+       int tot_ofs= 0;
+       Sequence *seq;
+       while( (ofs= shuffle_seq_time_offset_test(seqbasep, dir)) ) {
+               for(seq= seqbasep->first; seq; seq= seq->next) {
+                       if(seq->tmp) {
+                               /* seq_test_overlap only tests display values */
+                               seq->startdisp +=       ofs;
+                               seq->enddisp +=         ofs;
+                       }
+               }
+
+               tot_ofs+= ofs;
+       }
+
+       for(seq= seqbasep->first; seq; seq= seq->next) {
+               if(seq->tmp)
+                       calc_sequence_disp(seq); /* corrects dummy startdisp/enddisp values */
+       }
+
+       return tot_ofs;
+}
+
+int shuffle_seq_time(ListBase * seqbasep)
+{
+       /* note: seq->tmp is used to tag strips to move */
+
+       Sequence *seq;
+
+       int offset_l = shuffle_seq_time_offset(seqbasep, 'L');
+       int offset_r = shuffle_seq_time_offset(seqbasep, 'R');
+       int offset = (-offset_l < offset_r) ?  offset_l:offset_r;
+
+       if(offset) {
+               for(seq= seqbasep->first; seq; seq= seq->next) {
+                       if(seq->tmp) {
+                               seq_translate(seq, offset);
+                               seq->flag &= ~SEQ_OVERLAP;
+                       }
+               }
+       }
+
+       return offset? 0:1;
+}
+
+
 void seq_update_sound(struct Sequence *seq)
 {
        if(seq->type == SEQ_SOUND)
index a52a98a19699feed64a69644b8b3e6e79f001a0f..194200e0effb524882a8a57857d8c09c323fdc08 100644 (file)
@@ -1027,7 +1027,7 @@ static void smoke_calc_domain(Scene *scene, Object *ob, SmokeModifierData *smd)
                        {
                                SmokeModifierData *smd2 = (SmokeModifierData *)md;
 
-                               if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll)
+                               if((smd2->type & MOD_SMOKE_TYPE_COLL) && smd2->coll && smd2->coll->points)
                                {
                                        // we got nice collision object
                                        SmokeCollSettings *scs = smd2->coll;
index dfefc79af9d588a0514cdc80bddef078a8637358..be68ebbdaedfb281ab5d8c111ff3a82225774839 100644 (file)
@@ -1706,7 +1706,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3],
        GHash *hash;
        GHashIterator *ihash;
        float nv1[3], nv2[3], nv3[3], nv4[3], edge1[3], edge2[3],d_nvect[3], dv1[3],ve[3],avel[3]={0.0,0.0,0.0},
-    vv1[3], vv2[3], vv3[3], vv4[3], coledge[3], mindistedge = 1000.0f, 
+    vv1[3], vv2[3], vv3[3], vv4[3], coledge[3]={0.0f, 0.0f, 0.0f}, mindistedge = 1000.0f, 
        outerforceaccu[3],innerforceaccu[3],
                facedist,n_mag,force_mag_norm,minx,miny,minz,maxx,maxy,maxz,
                innerfacethickness = -0.5f, outerfacethickness = 0.2f,
index f4d91891dd1fb28bd23a09db2b3d8db30ccf6e53..46d31ed47aaee66824009d04cfb46831603b18e4 100644 (file)
@@ -454,6 +454,7 @@ void i_window(
 #define BLI_CS_CIE             2
 
 #define RAD2DEG(_rad) ((_rad)*(180.0/M_PI))
+#define DEG2RAD(_deg) ((_deg)*(M_PI/180.0))
 
 void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b);
 void hex_to_rgb(char *hexcol, float *r, float *g, float *b);
index 92543558a19e559672412775af0f228516a3c853..15374b4d44563e4eac26d0c00ebf1c070d1cb2ec 100644 (file)
@@ -38,9 +38,9 @@
 #define BFILE_NORMAL (0)
 /* No supervision, just translate // if needed, RISKY */
 #define BFILE_RAW    (1<<0)
-/* Path is relative to config dirs */
+/* Path is based in env vars specified by "envvars" */
 #define BFILE_CONFIG (1<<1)
-/* Path is for current session temp file */
+/* Path is for current session temp files */
 #define BFILE_TEMP   (1<<2)
 
 /* Config handling, special cases: */
 /* Compression to apply on close: */
 #define BFILE_GZIP (1<<5)
 
+/**
+ For the envvars param.
+ */
+typedef enum BEnvVarFamilies {
+       BENV_NONE,
+       BENV_BASE,
+       BENV_DATAFILES,
+       BENV_PYTHON,
+       BENV_PLUGINS
+} BEnvVarFam;
+
 /**
  File descriptor for Blender abstracted file access.
  */
@@ -58,22 +69,23 @@ typedef struct {
        int fd;
 
        /* Anything below should not be touched directly */
-       int uflags;  /* Special options requested by upper level, copy of bflags */
-       char *fpath; /* Final/requested path name */
-       char *tpath; /* Temp path name if applicable */
-       int type;    /* Own flags, common classification of open and fopen */
-       int error;   /* An op caused an error, unsafe to replace older files */
+       int uflags;       /* Special options requested by upper level, copy of bflags */
+       BEnvVarFam evars; /* What kind of file, describe the env vars to use */
+       char *fpath;      /* Final/requested path name */
+       char *tpath;      /* Temp path name if applicable */
+       int classf;       /* Own flags, common classification of open and fopen */
+       int error;        /* An op caused an error, unsafe to replace older files */
 } BFILE;
 
 /**
  Open a BFILE* with fopen()-like syntax.
  */
-BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags);
+BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags, BEnvVarFam envvars);
 
 /**
  Open a BFILE* with open()-like syntax.
  */
-BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags);
+BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags, BEnvVarFam envvars);
 
 /**
  Get the FILE* associated with the BFILE*.
index 60b7f74954d6f088ae5b9cfd14b8db69821e5c40..22a9b5edcaf275e790cca6c11db7b947668ddc06 100644 (file)
@@ -176,6 +176,8 @@ typedef struct EditMesh
        short mat_nr;
        /* stats */
        int totvert, totedge, totface, totvertsel, totedgesel, totfacesel;
+       /* shape key being edited */
+       int shapenr;
        
        struct DerivedMesh *derivedCage, *derivedFinal;
        /* the custom data layer mask that was last used to calculate
index 3ee767ec15656f8ab512930311910957f808269c..16b966e3c7b6830f2db1e732dce4e8ec75008333 100644 (file)
@@ -178,7 +178,7 @@ extern unsigned int hashsizes[];
 /*---------inlined functions---------*/
 BM_INLINE void BLI_ghash_insert(GHash *gh, void *key, void *val) {
        unsigned int hash= gh->hashfp(key)%gh->nbuckets;
-       Entry *e= BLI_mempool_alloc(gh->entrypool);
+       Entry *e= (Entry*) BLI_mempool_alloc(gh->entrypool);
 
        e->key= key;
        e->val= val;
index fa44bb36e150358431071bd306dca09696235e77..96e88ec8e89ff2584cb414d052cfc106cb5a7ba8 100644 (file)
@@ -66,6 +66,9 @@ int    BLI_exist(char *name);
         * @param name The name of the file to read.
         * @retval A list of strings representing the file lines.
         */
+
+int BLI_is_dir(char *file);
+
 struct LinkNode *BLI_read_file_as_lines(char *name);
 
        /**
index 1ce7a8cdb772c0818bad7fce6f4aefb3093a6008..7642b71eea08a242448cf5c42193c3aac082a038 100644 (file)
@@ -51,6 +51,7 @@ char *BLI_gethome_folder(char *folder_name, int flag);
 #define BLI_GETHOME_ALL                        (BLI_GETHOME_SYSTEM|BLI_GETHOME_LOCAL|BLI_GETHOME_USER)
 
 void BLI_setenv(const char *env, const char *val);
+void BLI_setenv_if_new(const char *env, const char* val);
 
 void BLI_make_file_string(const char *relabase, char *string,  const char *dir, const char *file);
 void BLI_make_exist(char *dir);
index 757b3605203bcec541db967075d52d2b4cc0d16a..77d41e2b96af48e1cc5d4479faaf430ffeaf9572 100644 (file)
@@ -129,6 +129,7 @@ struct dirent *readdir(DIR *dp);
 int closedir (DIR *dp);
 void get_default_root(char *root);
 int check_file_chars(char *filename);
+char *dirname(char *path);
 
 #ifdef WIN32
 int BLI_getInstallationDir(char *str);
index a7ce1df5712f99bcd34f4738932a9096f8d8322b..042cf4beffceb5db74bd8cd9a55a0486405c764f 100644 (file)
  */
 
 #include <string.h>
-
+#include <stdlib.h>
 #ifndef WIN32
-  #include <unistd.h>
+ #include <unistd.h>
+ #include <sys/param.h>
+// #include <libgen.h>
 #else
 #include <io.h>
 #include "BLI_winstuff.h"
+ #include <io.h>
+ #include "BLI_winstuff.h"
 #endif
-
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 
 #include "MEM_guardedalloc.h"
-
+#include "BKE_utildefines.h"
+#include "BKE_blender.h"
+#include "BLI_util.h"
+#include "BLI_fileops.h"
+#include "BLI_storage.h"
 #include "BLI_bfile.h"
 
-// This would provide config paths and their oldest viable version
-// so if there is an uncompatible change, user's old versions are not loaded
-//#include "bfile_tables.h"
-
-/* Internal bfile type flags */
-#define BTF_OPEN     (0)
-#define BTF_FOPEN    (1<<0)
-#define BTF_READ     (1<<1)
-#define BTF_WRITE    (1<<2)
-#define BTF_AT_END   (1<<3)
-#define BTF_DISCARD  (1<<4)
-
-
-void fill_paths(BFILE *bfile, const char *path) {
-       char* source_path = NULL;
-       int bflags = bfile->uflags;
-
-       if(bflags & BFILE_NORMAL || bflags & BFILE_RAW) {
-//             bfile->fpath is path with // replaced
-       }
-       if(bflags & BFILE_TEMP) {
-//             bfile->fpath is tempdir+path
-       }
-       if(bflags & BFILE_CONFIG) {
-//             bfile->fpath is userdir+version+path
-//             source_path is first hit in (if using fallback to older versions)
-//                 userdir+curversion+path (... userdir+limitversion+path) sysdir+path
-//             (limitversion is based in path, using some kind of regex or "tables")
-       }
-
-       if(bfile->type & BTF_WRITE && !(bflags & BFILE_RAW)) {
-               /* Generate temp path */
-               // bfile->tpath is fpath+randstring
-               if(!(bfile->type & BTF_DISCARD)) {
-                       /* Copy data to tpath */
-                       if(source_path) {
-                               // copy it from older version or sys version
-                       }
-               }
-       } else {
-               bfile->tpath = bfile->fpath;
-       }
-}
-
-BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags) {
+/* Internal bfile classification flags */
+#define BCF_OPEN     (0)
+#define BCF_FOPEN    (1<<0)
+#define BCF_READ     (1<<1)
+#define BCF_WRITE    (1<<2)
+#define BCF_AT_END   (1<<3)
+#define BCF_DISCARD  (1<<4)
+
+/* Declaration of internal functions */
+void chomp(char* line);
+void expand_envvars(char* src, char* dst);
+void fill_paths(BFILE *bfile, const char *path);
+char* find_in_pathlist(char* filename, char* pathlist);
+void init_vars_from_file(const char* path);
+void setup_temp();
+
+/*** Exported functions ***/
+
+BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags,
+                       BEnvVarFam envvars)
+{
        BFILE *bfile;
 
        bfile = MEM_mallocN(sizeof(BFILE), "bfile-fopen");
-       bfile->type = BTF_FOPEN;
+       bfile->classf = BCF_FOPEN;
        bfile->uflags = bflags;
 
        /* From fopen() doc, we can guess some logic:
-       r  BTF_READ
-       r+ BTF_READ | BTF_WRITE
-       w  BTF_DISCARD | BTF_WRITE
-       w+ BTF_DISCARD | BTF_WRITE | BTF_READ
-       a  BTF_AT_END | BTF_WRITE
-       a+ BTF_AT_END | BTF_WRITE | BTF_READ
+       r  BCF_READ
+       r+ BCF_READ | BCF_WRITE
+       w  BCF_DISCARD | BCF_WRITE
+       w+ BCF_DISCARD | BCF_WRITE | BCF_READ
+       a  BCF_AT_END | BCF_WRITE
+       a+ BCF_AT_END | BCF_WRITE | BCF_READ
        */
        if(strchr(mode, 'r'))
-               bfile->type |= BTF_READ;
+               bfile->classf |= BCF_READ;
        if(strchr(mode, 'w'))
-               bfile->type |= (BTF_DISCARD | BTF_WRITE);
+               bfile->classf |= (BCF_DISCARD | BCF_WRITE);
        if(strchr(mode, 'a'))
-               bfile->type |= (BTF_AT_END | BTF_WRITE);
+               bfile->classf |= (BCF_AT_END | BCF_WRITE);
        if(strchr(mode, '+'))
-               bfile->type |= (BTF_READ | BTF_WRITE);
+               bfile->classf |= (BCF_READ | BCF_WRITE);
 
        fill_paths(bfile, path);
 
@@ -118,24 +99,26 @@ BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags) {
 }
 
 
-BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags) {
+BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags,
+                      BEnvVarFam envvars)
+{
        BFILE *bfile;
 
        bfile = MEM_mallocN(sizeof(BFILE), "bfile-open");
-       bfile->type = BTF_OPEN;
+       bfile->classf = BCF_OPEN;
        bfile->uflags = bflags;
 
        /* Easy mapping for open() */
        if(flags & O_RDONLY)
-               bfile->type |= BTF_READ;
+               bfile->classf |= BCF_READ;
        if(flags & O_WRONLY)
-               bfile->type |= BTF_WRITE;
+               bfile->classf |= BCF_WRITE;
        if(flags & O_RDWR)
-               bfile->type |= (BTF_READ | BTF_WRITE);
+               bfile->classf |= (BCF_READ | BCF_WRITE);
        if(flags & O_APPEND)
-               bfile->type |= BTF_AT_END;
+               bfile->classf |= BCF_AT_END;
        if(flags & O_TRUNC)
-               bfile->type |= BTF_DISCARD;
+               bfile->classf |= BCF_DISCARD;
 
        fill_paths(bfile, pathname);
 
@@ -180,7 +163,9 @@ ssize_t BLI_bfile_read(BFILE *f, void *buf, size_t count) {
 }
 
 
-size_t BLI_bfile_fwrite(const void *ptr, size_t size, size_t nmemb, BFILE *f) {
+size_t BLI_bfile_fwrite(const void *ptr, size_t size, size_t nmemb,
+                        BFILE *f)
+{
        size_t ret;
 
        ret = fwrite(ptr, size, nmemb, f->stream);
@@ -205,7 +190,7 @@ size_t BLI_bfile_fread(void *ptr, size_t size, size_t nmemb, BFILE *f) {
 
 
 void BLI_bfile_close(BFILE *bfile) {
-       if((bfile->type | BTF_WRITE) &&
+       if((bfile->classf | BCF_WRITE) &&
           !(bfile->uflags | BFILE_RAW)) {
                /* Make sure data is on disk */
                /* Move to final name if no errors */
@@ -234,3 +219,301 @@ void BLI_bfile_set_error(BFILE *bfile, int error) {
                bfile->error = error;
        }
 }
+
+
+#if defined(WIN32)
+ #define LAST_SESSION_FILE "%HOME%\\Blender\\last-session FIXME FIXME FIXME"
+ #define ENVIRONMENT_FILE "FIXME"
+ #define SHARED_DIRECTORY "FIXME TOO"
+#elif defined(OSX)
+ #define LAST_SESSION_FILE "${HOME}/Library/Application Support/Blender/last-session"
+ #define ENVIRONMENT_FILE "${HOME}/Library/Application Support/Blender/${BLENDER_VERSION}/environment"
+ #define SHARED_DIRECTORY "/Library/Application Support/Blender"
+#else
+ #define LAST_SESSION_FILE "${HOME}/.blender/last-session"
+ #define ENVIRONMENT_FILE "${HOME}/.blender/${BLENDER_VERSION}/environment"
+ #define SHARED_DIRECTORY "/usr/share/blender"
+#endif
+void BLI_bfile_init_vars() {
+       char file[MAXPATHLEN];
+       char temp[MAXPATHLEN];
+       extern char bprogname[];
+       FILE* fp;
+
+       /* This one is unconditional */
+       sprintf(temp, "%d", BLENDER_VERSION);
+       BLI_setenv("BLENDER_VERSION", temp);
+
+       /* Is this unpack&run? */
+       sprintf(temp, "%s/%d/environment", dirname(bprogname), BLENDER_VERSION);
+       if(BLI_exist(temp)) {
+               BLI_setenv_if_new("BLENDER_SHARE", dirname(bprogname));
+       } else {
+               BLI_setenv_if_new("BLENDER_SHARE", SHARED_DIRECTORY);
+       }
+
+       expand_envvars(LAST_SESSION_FILE, file);
+       fp = fopen(file, "r");
+       /* 1st line, read previous version */
+       if (fp && (fscanf(fp, "%3c\n", temp) == 1)) {
+               temp[3] = '\0';
+               BLI_setenv("BLENDER_VERSION_PREV", temp);
+               /* 2nd line, read previous session path if needed */
+               if(!getenv("BLENDER_TEMP")) {
+                       if ((fgets(temp, MAXPATHLEN, fp) != NULL)) {
+                               /* Clean any \n */
+                               chomp(temp);
+                               /* Check the dir is still there or generate new one */
+                               if(!BLI_exist(temp)) {
+                                       setup_temp();
+                               }
+                       } else {
+                               /* We have to generate it for sure */
+                               setup_temp();
+                       }
+               }
+       } else {
+               /* Probably new user, or only <=249 before */
+               BLI_setenv("BLENDER_VERSION_PREV", "0");
+               setup_temp();
+       }
+
+       if(fp) {
+               fclose(fp);
+       }
+
+       /* Load vars from user and system files */
+       expand_envvars(ENVIRONMENT_FILE, file);
+       init_vars_from_file(file);
+       sprintf(temp, "/%d/environment", BLENDER_VERSION);
+       BLI_make_file_string("/", file, getenv("BLENDER_SHARE"), temp);
+       init_vars_from_file(file);
+}
+
+
+/*** Internal functions ***/
+
+/**
+ Eliminate trailing EOL by writing a \0 over it.
+ Name taken from Perl.
+ */
+void chomp(char* line) {
+       int len = strlen(line);
+#ifndef WIN32
+       if (line[len - 1] == '\n') {
+               line[len - 1] = '\0';
+       }
+#else
+       if ((line[len - 2] == '\r' ) && ((line[len - 1] == '\n'))) {
+               line[len - 2] = '\0';
+       }
+#endif /* WIN32 */
+}
+
+
+/**
+ Parse a file with lines like FOO=bar (comment lines have # as first
+ character) assigning to envvar FOO the value bar if FOO does not
+ exist yet.
+ Any white space before FOO, around the = or trailing will be used,
+ so beware.
+ */
+#define MAX_LINE 4096
+#define ENV_VAR 256
+#define VAR_LEN 8192
+void init_vars_from_file(const char* path) {
+       char line[MAX_LINE];
+       char name[ENV_VAR];
+       FILE *fp;
+       char* separator;
+       char expanded[VAR_LEN];
+
+       fp = fopen(path, "r");
+       if (!fp) return;
+
+       while (fgets(line, MAX_LINE, fp) != NULL) {
+               /* Ignore comment lines */
+               if (line[0] == '#')
+                       continue;
+
+               /* Split into envvar name and contents */
+               separator = strchr(line, '=');
+               if(separator && ((separator - line) < ENV_VAR)) {
+                       /* First remove EOL */
+                       chomp(line);
+                       strncpy(name, line, separator - line);
+                       name[separator - line] = '\0';
+                       expand_envvars(separator + 1, expanded);
+                       BLI_setenv_if_new(name, expanded);
+               }
+       }
+       fclose(fp);
+}
+
+
+/**
+ Look for ${} (or %%) env vars in src and expand if the var
+ exists (even if empty value). If not exist, the name is left as is.
+ The process is done all over src, and nested ${${}} is not supported.
+ src must be \0 terminated, and dst must be big enough.
+*/
+#ifndef WIN32
+ #define ENVVAR_PREFFIX "${"
+ #define ENVVAR_P_SIZE 2
+ #define ENVVAR_SUFFIX "}"
+ #define ENVVAR_S_SIZE 1
+#else
+ #define ENVVAR_PREFFIX "%"
+ #define ENVVAR_P_SIZE 1
+ #define ENVVAR_SUFFIX "%"
+ #define ENVVAR_S_SIZE 1
+#endif /* WIN32 */
+void expand_envvars(char* src, char* dst) {
+       char* hit1;
+       char* hit2;
+       char name[ENV_VAR];
+       char* value;
+       int prevlen;
+       int done = 0;
+       char* source = src;
+
+       dst[0] = '\0';
+       while (!done) {
+               hit1 = strstr(source, ENVVAR_PREFFIX);
+               if (hit1) {
+                       hit2 = strstr(hit1 + ENVVAR_P_SIZE, ENVVAR_SUFFIX);
+                       if (hit2) {
+                               /* "Copy" the leading part, if any */
+                               if (hit1 != source) {
+                                       prevlen = strlen(dst);
+                                       strncat(dst, source, hit1 - source);
+                                       dst[prevlen + (hit1 - source)] = '\0';
+                               }
+                               /* Figure the name of the env var we just found  */
+                               strncpy(name, hit1 + ENVVAR_P_SIZE,
+                                       hit2 - (hit1 + ENVVAR_P_SIZE));
+                               name[hit2 - (hit1 + ENVVAR_P_SIZE)] = '\0';
+                               /* See if we can get something with that name */
+                               value = getenv(name);
+                               if (value) {
+                                       /* Push the var value */
+                                       strcat(dst, value);
+                               } else {
+                                       /* Leave the var name, so it is clear that it failed */
+                                       strcat(dst, ENVVAR_PREFFIX);
+                                       strcat(dst, name);
+                                       strcat(dst, ENVVAR_SUFFIX);
+                               }
+                               /* Continue after closing mark, like a new string */
+                               source = hit2 + ENVVAR_S_SIZE;
+                       } else {
+                               /* Non terminated var so "copy as is" and finish */
+                               strcat(dst, source);
+                               done = 1;
+                       }
+               } else {
+                       /* "Copy" whatever is left */
+                       strcat(dst, source);
+                       done = 1;
+               }
+       }
+}
+
+
+/**
+ Return a full path if the filename exists when combined
+ with any item from pathlist. Or NULL otherwise.
+ */
+#ifdef WIN32
+ #define SEPARATOR ';'
+#else
+ #define SEPARATOR ':'
+#endif
+char* find_in_pathlist(char* filename, char* pathlist) {
+       char first[FILE_MAX + 10];
+       char* rest = NULL;
+
+       /* Separate first path from rest, use typical separator for current OS */
+       rest = strchr(pathlist, SEPARATOR);
+       if (rest) {
+               strncpy(first, pathlist, rest - pathlist);
+               first[rest - pathlist] = '\0';
+               /* Skip the separator so it becomes a valid new pathlist */
+               rest++;
+       } else {
+               strcpy(first, pathlist);
+       }
+
+       /* Check if combination exists */
+       BLI_add_slash(first);
+       strcat(first, filename);
+       if(BLI_exist(first)) {
+               return strdup(first);
+       }
+
+       /* First path failed, try with rest of paths if possible */
+       if(rest) {
+               return find_in_pathlist(filename, rest);
+       } else {
+               return NULL;
+       }
+}
+
+
+/**
+ Setup fpath and tpath based in the needs of the bfile.
+ */
+void fill_paths(BFILE *bfile, const char *path) {
+       char* source_path = NULL;
+       char* temp_path = NULL;
+       int bflags = bfile->uflags;
+
+       if(bflags & BFILE_NORMAL || bflags & BFILE_RAW) {
+//             bfile->fpath is path with // replaced
+       }
+       if(bflags & BFILE_TEMP) {
+               temp_path = MEM_mallocN(MAXPATHLEN, "bfile-fpath-1");
+               snprintf(temp_path, MAXPATHLEN, "%s/%s", getenv("BLENDER_TEMP"), path);
+               bfile->fpath = temp_path;
+       }
+       if(bflags & BFILE_CONFIG) {
+//             bfile->fpath is userdir+version+path
+//             source_path is first hit in (if using fallback to older versions)
+//                 userdir+curversion+path (... userdir+limitversion+path) sysdir+path
+//             (limitversion is based in path, using some kind of regex or "tables")
+       }
+
+       if(bfile->classf & BCF_WRITE && !(bflags & BFILE_RAW)) {
+               /* Generate temp path */
+               temp_path = MEM_mallocN(MAXPATHLEN, "bfile-fpath-2");
+               snprintf(temp_path, MAXPATHLEN, "%s.XXXXXX", path);
+               bfile->tpath = mkdtemp(temp_path);
+               if(!(bfile->classf & BCF_DISCARD)) {
+                       /* Copy data to tpath */
+                       if(source_path) {
+                               // copy it from older version or sys version
+                       }
+               }
+       } else {
+               bfile->tpath = bfile->fpath;
+       }
+}
+
+
+/**
+ Create a temp directory in safe and multiuser way.
+ */
+void setup_temp() {
+       char template[MAXPATHLEN];
+       char* tempdir;
+
+       if(getenv("TMPDIR")) {
+               sprintf(template, "%s/blender-XXXXXX", getenv("TMPDIR"));
+       } else {
+               sprintf(template, "/tmp/blender-XXXXXX");
+// MacOSX NSTemporaryDirectory and WIN32 ???
+       }
+       tempdir = mkdtemp(template);
+       BLI_setenv("BLENDER_TEMP", tempdir);
+}
+
index cdc5cec705fb714ce879a906c0a8b394a3065b08..dbf1f5100a60024f17bf0ebc2d128bcd81359599 100644 (file)
@@ -468,6 +468,11 @@ int BLI_exist(char *name)
        return(st.st_mode);
 }
 
+/* would be better in fileops.c except that it needs stat.h so add here */
+int BLI_is_dir(char *file) {
+       return S_ISDIR(BLI_exist(file));
+}
+
 LinkNode *BLI_read_file_as_lines(char *name)
 {
        FILE *fp= fopen(name, "r");
index 387d1881d3cf9eeaaf1e612952d8310d51a5743e..e2acbf21624427c607d71aa4b42dcf8c12b102d9 100644 (file)
@@ -992,6 +992,18 @@ void BLI_setenv(const char *env, const char*val)
 #endif
 }
 
+
+/**
+ Only set an env var if already not there.
+ Like Unix setenv(env, val, 0);
+ */
+void BLI_setenv_if_new(const char *env, const char* val)
+{
+       if(getenv(env) == NULL)
+               BLI_setenv(env, val);
+}
+
+
 void BLI_clean(char *path)
 {
        if(path==0) return;
@@ -1374,10 +1386,10 @@ void BLI_where_am_i(char *fullname, const char *name)
        char *path = NULL, *temp;
        
 #ifdef _WIN32
-       char *seperator = ";";
+       char *separator = ";";
        char slash = '\\';
 #else
-       char *seperator = ":";
+       char *separator = ":";
        char slash = '/';
 #endif
 
@@ -1415,7 +1427,7 @@ void BLI_where_am_i(char *fullname, const char *name)
                        path = getenv("PATH");
                        if (path) {
                                do {
-                                       temp = strstr(path, seperator);
+                                       temp = strstr(path, separator);
                                        if (temp) {
                                                strncpy(filename, path, temp - path);
                                                filename[temp - path] = 0;
index 2f96f7b6af1173bf9ed1de26e8bff7099132f2e7..16295fc2680ef43a4cacc17527fc91e4d714aef8 100644 (file)
@@ -217,6 +217,32 @@ int check_file_chars(char *filename)
        return 1;
 }
 
+/* Copied from http://sourceware.org/ml/newlib/2005/msg00248.html */
+/* Copyright 2005 Shaun Jackman
+ * Permission to use, copy, modify, and distribute this software
+ * is freely granted, provided that this notice is preserved.
+ */
+#include <string.h>
+char* dirname(char *path)
+{
+       char *p;
+       if( path == NULL || *path == '\0' )
+               return ".";
+       p = path + strlen(path) - 1;
+       while( *p == '/' ) {
+               if( p == path )
+                       return path;
+               *p-- = '\0';
+       }
+       while( p >= path && *p != '/' )
+               p--;
+       return
+               p < path ? "." :
+               p == path ? "/" :
+               (*p = '\0', path);
+}
+/* End of copied part */
+
 #else
 
 /* intentionally empty for UNIX */
index 52295dc3092368f146b514bf0f1da6de6fa72dae..408d07b965c45dcaa2ee8528e4406f038c633699 100644 (file)
@@ -62,6 +62,7 @@ typedef struct BlendFileData {
        int fileflags;
        int displaymode;
        int globalf;
+       char filename[240];     /* 240 = FILE_MAX */
        
        struct bScreen* curscreen;
        struct Scene*   curscene;
index 3d21bb54e2b8e1d5fae392d9b4898f9f836e12cd..7608f988f4fbf7653079458d89cd20ba26efc79a 100644 (file)
@@ -364,7 +364,7 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
        fd = blo_openblendermemfile(memfile, reports);
        if (fd) {
                fd->reports= reports;
-               strcpy(fd->filename, filename);
+               strcpy(fd->relabase, filename);
                
                /* clear ob->proxy_from pointers in old main */
                blo_clear_proxy_pointers_from_lib(fd, oldmain);
index 8efdbdd1905287ce9fa96e121fb4bff57fbf8fa9..fa1a7da669a2796d021a883e917792bd0a676c30 100644 (file)
@@ -978,7 +978,7 @@ FileData *blo_openblenderfile(char *name, ReportList *reports)
                fd->read = fd_read_gzip_from_file;
 
                /* needed for library_append and read_libraries */
-               BLI_strncpy(fd->filename, name, sizeof(fd->filename));
+               BLI_strncpy(fd->relabase, name, sizeof(fd->relabase));
 
                return blo_decode_and_check(fd, reports);
        }
@@ -4287,7 +4287,7 @@ static void composite_patch(bNodeTree *ntree, Scene *scene)
        bNode *node;
        
        for(node= ntree->nodes.first; node; node= node->next)
-               if(node->id==NULL && ELEM(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE))
+               if(node->id==NULL && ELEM3(node->type, CMP_NODE_R_LAYERS, CMP_NODE_COMPOSITE, CMP_NODE_DEFOCUS))
                        node->id= &scene->id;
 }
 
@@ -4400,8 +4400,10 @@ static void link_recurs_seq(FileData *fd, ListBase *lb)
 static void direct_link_paint(FileData *fd, Paint **paint)
 {
        (*paint)= newdataadr(fd, (*paint));
-       if(*paint)
+       if(*paint) {
+               (*paint)->paint_cursor= NULL;
                (*paint)->brushes= newdataadr(fd, (*paint)->brushes);
+       }
 }
 
 static void direct_link_scene(FileData *fd, Scene *sce)
@@ -4600,7 +4602,6 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
                win->curswin= NULL;
                win->tweak= NULL;
 
-               win->timers.first= win->timers.last= NULL;
                win->queue.first= win->queue.last= NULL;
                win->handlers.first= win->handlers.last= NULL;
                win->modalhandlers.first= win->modalhandlers.last= NULL;
@@ -4612,6 +4613,7 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
                win->drawfail= 0;
        }
        
+       wm->timers.first= wm->timers.last= NULL;
        wm->operators.first= wm->operators.last= NULL;
        wm->paintcursors.first= wm->paintcursors.last= NULL;
        wm->queue.first= wm->queue.last= NULL;
@@ -5302,7 +5304,7 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main)
        }
        /* make sure we have full path in lib->filename */
        BLI_strncpy(lib->filename, lib->name, sizeof(lib->name));
-       cleanup_path(fd->filename, lib->filename);
+       cleanup_path(fd->relabase, lib->filename);
        
 //     printf("direct_link_library: name %s\n", lib->name);
 //     printf("direct_link_library: filename %s\n", lib->filename);
@@ -5636,6 +5638,9 @@ static BHead *read_global(BlendFileData *bfd, FileData *fd, BHead *bhead)
        bfd->fileflags= fg->fileflags;
        bfd->displaymode= fg->displaymode;
        bfd->globalf= fg->globalf;
+       BLI_strncpy(bfd->filename, fg->filename, sizeof(bfd->filename));
+       if(G.fileflags & G_FILE_RECOVER)
+               BLI_strncpy(fd->relabase, fg->filename, sizeof(fd->relabase));
        
        bfd->curscreen= fg->curscreen;
        bfd->curscene= fg->curscene;
@@ -6451,7 +6456,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
        /* WATCH IT!!!: pointers from libdata have not been converted */
 
        if(G.f & G_DEBUG)
-               printf("read file %s\n  Version %d sub %d\n", fd->filename, main->versionfile, main->subversionfile);
+               printf("read file %s\n  Version %d sub %d\n", fd->relabase, main->versionfile, main->subversionfile);
        
        if(main->versionfile == 100) {
                /* tex->extend and tex->imageflag have changed: */
@@ -6598,7 +6603,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
        if(main->versionfile <= 140) {
-               /* r-g-b-fac in texure */
+               /* r-g-b-fac in texture */
                Tex *tex = main->tex.first;
                while (tex) {
                        if ((tex->rfac == 0.0) &&
@@ -10087,7 +10092,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
 
-       /* put 2.50 compatibility code here until next subversion bump */
        if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 6)) {
                Object *ob;
                Lamp *la;
@@ -10113,6 +10117,71 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                        la->compressthresh= 0.05f;
        }
 
+       if (main->versionfile < 250 || (main->versionfile == 250 && main->subversionfile < 7)) {
+               Mesh *me;
+               Nurb *nu;
+               Lattice *lt;
+               Curve *cu;
+               Key *key;
+               float *data;
+               int a, tot;
+
+               /* shape keys are no longer applied to the mesh itself, but rather
+                  to the derivedmesh/displist, so here we ensure that the basis
+                  shape key is always set in the mesh coordinates. */
+
+               for(me= main->mesh.first; me; me= me->id.next) {
+                       if((key = newlibadr(fd, lib, me->key)) && key->refkey) {
+                               data= key->refkey->data;
+                               tot= MIN2(me->totvert, key->refkey->totelem);
+
+                               for(a=0; a<tot; a++, data+=3)
+                                       VECCOPY(me->mvert[a].co, data)
+                       }
+               }
+
+               for(lt= main->latt.first; lt; lt= lt->id.next) {
+                       if((key = newlibadr(fd, lib, lt->key)) && key->refkey) {
+                               data= key->refkey->data;
+                               tot= MIN2(lt->pntsu*lt->pntsv*lt->pntsw, key->refkey->totelem);
+
+                               for(a=0; a<tot; a++, data+=3)
+                                       VECCOPY(lt->def[a].vec, data)
+                       }
+               }
+
+               for(cu= main->curve.first; cu; cu= cu->id.next) {
+                       if((key = newlibadr(fd, lib, cu->key)) && key->refkey) {
+                               data= key->refkey->data;
+
+                               for(nu=cu->nurb.first; nu; nu=nu->next) {
+                                       if(nu->bezt) {
+                                               BezTriple *bezt = nu->bezt;
+
+                                               for(a=0; a<nu->pntsu; a++, bezt++) {
+                                                       VECCOPY(bezt->vec[0], data); data+=3;
+                                                       VECCOPY(bezt->vec[1], data); data+=3;
+                                                       VECCOPY(bezt->vec[2], data); data+=3;
+                                                       bezt->alfa= *data; data++;
+                                               }
+                                       }
+                                       else if(nu->bp) {
+                                               BPoint *bp = nu->bp;
+
+                                               for(a=0; a<nu->pntsu*nu->pntsv; a++, bp++) {
+                                                       VECCOPY(bp->vec, data); data+=3;
+                                                       bp->alfa= *data; data++;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /* put 2.50 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 src/usiblender.c! */
 
@@ -10225,14 +10294,25 @@ BlendFileData *blo_read_file_internal(FileData *fd, char *file)
                        break;
 
                case ID_LI:
-                       bhead = read_libblock(fd, bfd->main, bhead, LIB_LOCAL, NULL);
+                       /* skip library datablocks in undo, this works together with
+                          BLO_read_from_memfile, where the old main->library is restored
+                          overwriting  the libraries from the memory file. previously
+                          it did not save ID_LI/ID_ID blocks in this case, but they are
+                          needed to make quit.blend recover them correctly. */
+                       if(fd->memfile)
+                               bhead= blo_nextbhead(fd, bhead);
+                       else
+                               bhead= read_libblock(fd, bfd->main, bhead, LIB_LOCAL, NULL);
                        break;
                case ID_ID:
+                       /* same as above */
+                       if(fd->memfile)
+                               bhead= blo_nextbhead(fd, bhead);
+                       else
                                /* always adds to the most recently loaded
                                 * ID_LI block, see direct_link_library.
-                                * this is part of the file format definition.
-                                */
-                       bhead = read_libblock(fd, fd->mainlist.last, bhead, LIB_READ+LIB_EXTERN, NULL);
+                                * this is part of the file format definition. */
+                               bhead = read_libblock(fd, fd->mainlist.last, bhead, LIB_READ+LIB_EXTERN, NULL);
                        break;
                        
                        /* in 2.50+ files, the file identifier for screens is patched, forward compatibility */
@@ -10254,7 +10334,7 @@ BlendFileData *blo_read_file_internal(FileData *fd, char *file)
 
        lib_link_all(fd, bfd->main);
        lib_verify_nodetree(bfd->main, 1);
-       fix_relpaths_library(fd->filename, bfd->main); /* make all relative paths, relative to the open blend file */
+       fix_relpaths_library(fd->relabase, bfd->main); /* make all relative paths, relative to the open blend file */
        
        link_global(fd, bfd);   /* as last */
        
@@ -10302,6 +10382,10 @@ static void sort_bhead_old_map(FileData *fd)
 
 static BHead *find_previous_lib(FileData *fd, BHead *bhead)
 {
+       /* skip library datablocks in undo, see comment in read_libblock */
+       if(fd->memfile)
+               return NULL;
+
        for (; bhead; bhead= blo_prevbhead(fd, bhead))
                if (bhead->code==ID_LI)
                        break;
@@ -10373,7 +10457,7 @@ static void expand_doit(FileData *fd, Main *mainvar, void *old)
 
                        if(bheadlib) {
                                Library *lib= read_struct(fd, bheadlib, "Library");
-                               Main *ptr= blo_find_main(fd, &fd->mainlist, lib->name, fd->filename);
+                               Main *ptr= blo_find_main(fd, &fd->mainlist, lib->name, fd->relabase);
 
                                id= is_yet_read(fd, ptr, bhead);
 
@@ -11631,7 +11715,7 @@ BlendFileData *blo_read_blendafterruntime(int file, char *name, int actualsize,
        fd->read = fd_read_from_file;
 
        /* needed for library_append and read_libraries */
-       BLI_strncpy(fd->filename, name, sizeof(fd->filename));
+       BLI_strncpy(fd->relabase, name, sizeof(fd->relabase));
 
        fd = blo_decode_and_check(fd, reports);
        if (!fd)
index 2a0b6c327d37fc32320a6ab224e65264939aeac3..41bc8f80fec1aae17152c9fd31615778127401ee 100644 (file)
@@ -56,7 +56,7 @@ typedef struct FileData {
        gzFile gzfiledes;
 
        // now only in use for library appending
-       char filename[FILE_MAXDIR+FILE_MAXFILE];
+       char relabase[FILE_MAXDIR+FILE_MAXFILE];
        
        // variables needed for reading from stream
        char headerdone;
index 72e1b5b1b787b8a3edb2ec20775bedb7a6eeda22..14b99dd7ae5c944eb3f401a4ca9bbeae53e084d3 100644 (file)
@@ -2310,7 +2310,7 @@ static void write_scripts(WriteData *wd, ListBase *idbase)
 /* context is usually defined by WM, two cases where no WM is available:
  * - for forward compatibility, curscreen has to be saved
  * - for undofile, curscene needs to be saved */
-static void write_global(WriteData *wd, Main *mainvar)
+static void write_global(WriteData *wd, int fileflags, Main *mainvar)
 {
        FileGlobal fg;
        bScreen *screen;
@@ -2323,8 +2323,9 @@ static void write_global(WriteData *wd, Main *mainvar)
        fg.curscene= screen->scene;
        fg.displaymode= G.displaymode;
        fg.winpos= G.winpos;
-       fg.fileflags= (G.fileflags & ~G_FILE_NO_UI);    // prevent to save this, is not good convention, and feature with concerns...
+       fg.fileflags= (fileflags & ~G_FILE_NO_UI);      // prevent to save this, is not good convention, and feature with concerns...
        fg.globalf= G.f;
+       BLI_strncpy(fg.filename, mainvar->name, sizeof(fg.filename));
 
        sprintf(subvstr, "%4d", BLENDER_SUBVERSION);
        memcpy(fg.subvstr, subvstr, 4);
@@ -2353,7 +2354,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
        mywrite(wd, buf, 12);
 
        write_renderinfo(wd, mainvar);
-       write_global(wd, mainvar);
+       write_global(wd, write_flags, mainvar);
 
        /* no UI save in undo */
        if(current==NULL) {
@@ -2384,8 +2385,7 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
        write_brushes  (wd, &mainvar->brush);
        write_scripts  (wd, &mainvar->script);
        write_gpencils (wd, &mainvar->gpencil);
-       if(current==NULL)       
-               write_libraries(wd,  mainvar->next); /* no library save in undo */
+       write_libraries(wd,  mainvar->next);
 
        if (write_user_block) {
                write_userdef(wd);
index fac86f79e23a3ac38d1bb1b1f4b3ffb1394e9e5f..55001812ccf8dd295e40cccfc0e283ea48e8dfbb 100644 (file)
@@ -177,6 +177,9 @@ typedef struct BMesh {
 
        /*active face pointer*/
        struct BMFace *act_face;
+
+       /*active shape key number, should really be in BMEditMesh, not here*/
+       int shapenr;
 } BMesh;
 
 typedef struct BMVert {        
index f61cf451944dad438965f715ced172fc6cbc069f..eb8d48896c7e39a0de65ef0c8048791745452bce 100644 (file)
@@ -468,11 +468,12 @@ BMOpDefine def_object_load_bmesh = {
 /*
   BMesh to Mesh
 
-  Converts a bmesh to a Mesh
+  Converts a bmesh to a Mesh.  This is reserved for exiting editmode.
 */
 BMOpDefine def_bmesh_to_mesh = {
        "bmesh_to_mesh",
-       {{BMOP_OPSLOT_PNT, "meshptr"}, //pointer to a mesh structure to fill in
+       {{BMOP_OPSLOT_PNT, "mesh"}, //pointer to a mesh structure to fill in
+        {BMOP_OPSLOT_PNT, "object"}, //pointer to an object structure
         {BMOP_OPSLOT_INT, "notesselation"}, //don't calculate mfaces
         {0, /*null-terminating sentinel*/}},
        bmesh_to_mesh_exec,
@@ -482,11 +483,13 @@ BMOpDefine def_bmesh_to_mesh = {
 /*
   Mesh to BMesh
 
-  Load the contents of a mesh into the bmesh.
+  Load the contents of a mesh into the bmesh.  this bmop is private, it's
+  reserved exclusively for entering editmode.
 */
 BMOpDefine def_mesh_to_bmesh = {
        "mesh_to_bmesh",
        {{BMOP_OPSLOT_PNT, "mesh"}, //pointer to a Mesh structure
+        {BMOP_OPSLOT_PNT, "object"}, //pointer to an Object structure
         {0, /*null-terminating sentinel*/}},
        mesh_to_bmesh_exec,
        0
index 15bc1f25bbad126093b6f6b2e714e4b1afdb5c11..d9c8bd63c5cbbb7f65ae1b95a0b065b4a22fdde3 100644 (file)
@@ -6,6 +6,8 @@
 #include "DNA_customdata_types.h"
 #include "DNA_mesh_types.h"
 #include "DNA_meshdata_types.h"
+#include "DNA_modifier_types.h"
+#include "DNA_key_types.h"
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
 
@@ -15,6 +17,8 @@
 #include "BKE_global.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_cdderivedmesh.h"
+#include "BKE_key.h"
+#include "BKE_main.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_edgehash.h"
 #include "mesh_intern.h"
 #include "bmesh.h"
 
+/*
+  HACK: we're using the old keyindex shape key hack for now, where each
+  vertex is assigned an index on entering editmode, which is used to retrieve
+  the original shapekey coordinates on exiting editmode.
+
+  this should be replaced by proper use of customdata layers, but I'm not
+  sure if that's such a good idea before merging with trunk or not.
+*/
+
 /*
  * MESH CONV.C
  *
 */
 
 void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
+       Object *ob = BMO_Get_Pnt(op, "object");
        Mesh *me = BMO_Get_Pnt(op, "mesh");
        MVert *mvert;
        MEdge *medge;
        MLoop *ml;
        MPoly *mpoly;
+       KeyBlock *actkey;
        BMVert *v, **vt=NULL;
        BMEdge *e, **fedges=NULL, **et = NULL;
-       BLI_array_declare(fedges);
        BMFace *f;
+       BLI_array_declare(fedges);
+       float (*keyco)[3]= NULL;
+       int *keyi;
        int i, j, li, allocsize[4] = {512, 512, 2048, 512};
 
        if (!me || !me->totvert) return; /*sanity check*/
        
        mvert = me->mvert;
-
        vt = MEM_mallocN(sizeof(void**)*me->totvert, "mesh to bmesh vtable");
 
        CustomData_copy(&me->vdata, &bm->vdata, CD_MASK_BMESH, CD_CALLOC, 0);
@@ -59,13 +75,23 @@ void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
        CustomData_copy(&me->ldata, &bm->ldata, CD_MASK_BMESH, CD_CALLOC, 0);
        CustomData_copy(&me->pdata, &bm->pdata, CD_MASK_BMESH, CD_CALLOC, 0);
 
+       CustomData_add_layer(&bm->vdata, CD_SHAPE_KEYINDEX, CD_ASSIGN, NULL, 0);
+
        CustomData_bmesh_init_pool(&bm->vdata, allocsize[0]);
        CustomData_bmesh_init_pool(&bm->edata, allocsize[1]);
        CustomData_bmesh_init_pool(&bm->ldata, allocsize[2]);
        CustomData_bmesh_init_pool(&bm->pdata, allocsize[3]);
-
+       actkey = ob_get_keyblock(ob);
+       if(actkey && actkey->totelem == me->totvert) {
+               keyco= actkey->data;
+               bm->shapenr= ob->shapenr;
+       } else if (actkey) {
+               printf("shapekey<->mesh mismatch!\n");
+       }
+       
        for (i=0; i<me->totvert; i++, mvert++) {
-               v = BM_Make_Vert(bm, mvert->co, NULL);
+               v = BM_Make_Vert(bm, keyco ? keyco[i] : mvert->co, NULL);
                VECCOPY(v->no, mvert->no);
 
                vt[i] = v;
@@ -80,6 +106,10 @@ void mesh_to_bmesh_exec(BMesh *bm, BMOperator *op) {
 
                /*Copy Custom Data*/
                CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data);
+
+               /*set shape key original index*/
+               keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX);
+               *keyi = i;
        }
 
        if (!me->totedge) {
@@ -223,24 +253,25 @@ void object_load_bmesh_exec(BMesh *bm, BMOperator *op) {
        Scene *scene = BMO_Get_Pnt(op, "scene");
        Mesh *me = ob->data;
 
-       BMO_CallOpf(bm, "bmesh_to_mesh meshptr=%p", me);
+       BMO_CallOpf(bm, "bmesh_to_mesh mesh=%p object=%p", me, ob);
 
        /*BMESH_TODO eventually we'll have to handle shapekeys here*/
 }
 
 void bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) {
-       Mesh *me = BMO_Get_Pnt(op, "meshptr");
+       Mesh *me = BMO_Get_Pnt(op, "mesh");
+       Object *ob = BMO_Get_Pnt(op, "object");
        MLoop *mloop;
        MPoly *mpoly;
        MVert *mvert, *oldverts;
        MEdge *medge;
        MFace *mface;
-       BMVert *v;
+       BMVert *v, *eve;
        BMEdge *e;
        BMLoop *l;
        BMFace *f;
        BMIter iter, liter;
-       int i, j, ototvert, totloop, totface, numTex, numCol;
+       int i, j, *keyi, ototvert, totloop, totface, numTex, numCol;
        int dotess = !BMO_Get_Int(op, "notesselation");
 
        numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY);
@@ -459,5 +490,129 @@ void bmesh_to_mesh_exec(BMesh *bm, BMOperator *op) {
                mpoly++;
        }
 
+       /* patch hook indices and vertex parents */
+       {
+               Object *ob;
+               ModifierData *md;
+               BMVert **vertMap = NULL;
+               int i,j;
+
+               for (ob=G.main->object.first; ob; ob=ob->id.next) {
+                       if (ob->parent==ob && ELEM(ob->partype, PARVERT1,PARVERT3)) {
+                               
+                               /* duplicate code from below, make it function later...? */
+                               if (!vertMap) {
+                                       vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
+                                       
+                                       BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+                                               keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
+                                               if (*keyi != ORIGINDEX_NONE)
+                                                       vertMap[*keyi] = eve;
+                                       }
+                               }
+                               if(ob->par1 < ototvert) {
+                                       eve = vertMap[ob->par1];
+                                       if(eve) ob->par1= BMINDEX_GET(eve);
+                               }
+                               if(ob->par2 < ototvert) {
+                                       eve = vertMap[ob->par2];
+                                       if(eve) ob->par2= BMINDEX_GET(eve);
+                               }
+                               if(ob->par3 < ototvert) {
+                                       eve = vertMap[ob->par3];
+                                       if(eve) ob->par3= BMINDEX_GET(eve);
+                               }
+                               
+                       }
+                       if (ob->data==me) {
+                               for (md=ob->modifiers.first; md; md=md->next) {
+                                       if (md->type==eModifierType_Hook) {
+                                               HookModifierData *hmd = (HookModifierData*) md;
+
+                                               if (!vertMap) {
+                                                       vertMap = MEM_callocN(sizeof(*vertMap)*ototvert, "vertMap");
+                                                       
+                                                       BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
+                                                               keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
+                                                               if (*keyi != ORIGINDEX_NONE)
+                                                                       vertMap[*keyi] = eve;
+                                                       }
+                                               }
+                                               
+                                               for (i=j=0; i<hmd->totindex; i++) {
+                                                       if(hmd->indexar[i] < ototvert) {
+                                                               eve = vertMap[hmd->indexar[i]];
+                                                               
+                                                               if (eve) {
+                                                                       hmd->indexar[j++] = BMINDEX_GET(eve);
+                                                               }
+                                                       }
+                                                       else j++;
+                                               }
+
+                                               hmd->totindex = j;
+                                       }
+                               }
+                       }
+               }
+
+               if (vertMap) MEM_freeN(vertMap);
+       }
+
        mesh_update_customdata_pointers(me);
+
+       /* are there keys? */
+       if(me->key) {
+               float *fp, *newkey, *oldkey;
+               KeyBlock *currkey;
+               KeyBlock *actkey= BLI_findlink(&me->key->block, bm->shapenr-1);
+
+               /* Lets reorder the key data so that things line up roughly
+                * with the way things were before editmode */
+               currkey = me->key->block.first;
+               while(currkey) {
+                       fp= newkey= MEM_callocN(me->key->elemsize*bm->totvert,  "currkey->data");
+                       oldkey = currkey->data;
+
+                       eve= BMIter_New(&iter, bm, BM_VERTS_OF_MESH, NULL);
+
+                       i = 0;
+                       mvert = me->mvert;
+                       while(eve) {
+                               keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
+                               if (*keyi >= 0 && *keyi < currkey->totelem) { // valid old vertex
+                                       if(currkey == actkey) {
+                                               if(actkey == me->key->refkey) {
+                                                       VECCOPY(fp, mvert->co);
+                                               }
+                                               else {
+                                                       VECCOPY(fp, mvert->co);
+                                                       if(oldverts) {
+                                                               VECCOPY(mvert->co, oldverts[*keyi].co);
+                                                       }
+                                               }
+                                       }
+                                       else {
+                                               if(oldkey) {
+                                                       VECCOPY(fp, oldkey + 3 * *keyi);
+                                               }
+                                       }
+                               }
+                               else {
+                                       VECCOPY(fp, mvert->co);
+                               }
+                               fp+= 3;
+                               ++i;
+                               ++mvert;
+                               eve= BMIter_Step(&iter);
+                       }
+                       currkey->totelem= bm->totvert;
+                       if(currkey->data) MEM_freeN(currkey->data);
+                       currkey->data = newkey;
+                       
+                       currkey= currkey->next;
+               }
+       }
+
+       if(oldverts) MEM_freeN(oldverts);
 }
\ No newline at end of file
index 7c9814eda7b346216ad8afda6691b77e2740de72..efbdd505bcbaf60db71a7f9df36f957700c85ca5 100644 (file)
@@ -1386,7 +1386,7 @@ static int acf_dsskey_setting_flag(int setting, short *neg)
        
        switch (setting) {
                case ACHANNEL_SETTING_EXPAND: /* expanded */
-                       return KEYBLOCK_DS_EXPAND;
+                       return KEY_DS_EXPAND;
                        
                case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */
                        return ADT_NLA_EVAL_OFF;
@@ -1737,28 +1737,91 @@ static bAnimChannelType ACF_DSARM=
 
 
 /* ShapeKey Entry  ------------------------------------------- */
-// XXX ... this is currently obsolete...
 
-#if 0
-static void dummy_olddraw_shapekeys ()
+/* name for ShapeKey */
+static void acf_shapekey_name(bAnimListElem *ale, char *name)
 {
-       case ANIMTYPE_SHAPEKEY: /* shapekey channel */
-       {
-               KeyBlock *kb = (KeyBlock *)ale->data;
+       KeyBlock *kb= (KeyBlock *)ale->data;
+       
+       /* just copy the name... */
+       if (kb && name) {
+               /* if the KeyBlock had a name, use it, otherwise use the index */
+               if (kb->name[0])
+                       strcpy(name, kb->name);
+               else
+                       sprintf(name, "Key %d", ale->index);
+       }
+}
+
+/* check if some setting exists for this channel */
+static short acf_shapekey_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting)
+{
+       switch (setting) {
+               case ACHANNEL_SETTING_SELECT: /* selected */
+               case ACHANNEL_SETTING_MUTE: /* muted */
+               case ACHANNEL_SETTING_PROTECT: /* protected */
+                       return 1;
+                       
+               /* nothing else is supported */
+               default:
+                       return 0;
+       }
+}
+
+/* get the appropriate flag(s) for the setting when it is valid  */
+static int acf_shapekey_setting_flag(int setting, short *neg)
+{
+       /* clear extra return data first */
+       *neg= 0;
+       
+       switch (setting) {
+               case ACHANNEL_SETTING_MUTE: /* mute */
+                       return KEYBLOCK_MUTE;
                
-               indent = 0;
-               special = -1;
+               case ACHANNEL_SETTING_SELECT: /* selected */
+                       return KEYBLOCK_SEL;
                
-               offset= (ale->id) ? 21 : 0;
+               case ACHANNEL_SETTING_PROTECT: /* locked */
+                       return KEYBLOCK_LOCKED;
                
-               if (kb->name[0] == '\0')
-                       sprintf(name, "Key %d", ale->index);
-               else
-                       strcpy(name, kb->name);
+               default: /* unsupported */
+                       return 0;
        }
-               break;
 }
-#endif
+
+/* get pointer to the setting */
+static void *acf_shapekey_setting_ptr(bAnimListElem *ale, int setting, short *type)
+{
+       KeyBlock *kb= (KeyBlock *)ale->data;
+       
+       /* clear extra return data first */
+       *type= 0;
+       
+       switch (setting) {
+               case ACHANNEL_SETTING_SELECT: /* selected */
+               case ACHANNEL_SETTING_MUTE: /* muted */
+               case ACHANNEL_SETTING_PROTECT: /* protected */
+                       GET_ACF_FLAG_PTR(kb->flag)
+               
+               default: /* unsupported */
+                       return NULL;
+       }
+}
+
+/* shapekey expander type define */
+static bAnimChannelType ACF_SHAPEKEY= 
+{
+       acf_generic_channel_backdrop,   /* backdrop */
+       acf_generic_indention_0,                /* indent level */
+       acf_generic_basic_offset,               /* offset */
+       
+       acf_shapekey_name,                              /* name */
+       NULL,                                                   /* icon */
+       
+       acf_shapekey_setting_valid,             /* has setting */
+       acf_shapekey_setting_flag,              /* flag for setting */
+       acf_shapekey_setting_ptr                /* pointer for setting */
+};
 
 /* Grease Pencil entries  ------------------------------------------- */
 // XXX ... this is currently not restored yet
@@ -1923,7 +1986,7 @@ void ANIM_init_channel_typeinfo_data (void)
                animchannelTypeInfo[type++]= &ACF_DSMBALL;              /* MetaBall Channel */
                animchannelTypeInfo[type++]= &ACF_DSARM;                /* Armature Channel */
                
-               animchannelTypeInfo[type++]= NULL;                              /* ShapeKey */ // XXX this is no longer used for now...
+               animchannelTypeInfo[type++]= &ACF_SHAPEKEY;             /* ShapeKey */
                
                        // XXX not restored yet
                animchannelTypeInfo[type++]= NULL;                              /* Grease Pencil Datablock */ 
@@ -2084,7 +2147,7 @@ void ANIM_channel_setting_set (bAnimContext *ac, bAnimListElem *ale, int setting
 // XXX hardcoded size of icons
 #define ICON_WIDTH             17
 // XXX hardcoded width of sliders
-#define SLIDER_WIDTH   70
+#define SLIDER_WIDTH   80
 
 /* Draw the given channel */
 // TODO: make this use UI controls for the buttons
@@ -2195,6 +2258,134 @@ static void achannel_setting_widget_cb(bContext *C, void *poin, void *poin2)
        WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
 }
 
+/* callback for visiblility-toggle widget settings - perform value flushing (Graph Editor only) */
+static void achannel_setting_visible_widget_cb(bContext *C, void *ale_npoin, void *dummy_poin)
+{
+       bAnimListElem *ale_setting= (bAnimListElem *)ale_npoin;
+       int prevLevel=0, matchLevel=0;
+       short vizOn = 0;
+       
+       bAnimContext ac;
+       ListBase anim_data = {NULL, NULL};
+       bAnimListElem *ale, *match=NULL;
+       int filter;
+       
+       /* send notifiers before doing anything else... */
+       WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
+       
+       /* verify animation context */
+       if (ANIM_animdata_get_context(C, &ac) == 0)
+               return;
+       
+       /* verify that we have a channel to operate on, and that it has all we need */
+       if (ale_setting) {
+               /* check if the setting is on... */
+               vizOn= ANIM_channel_setting_get(&ac, ale_setting, ACHANNEL_SETTING_VISIBLE);
+               
+               /* vizOn == -1 means setting not found... */
+               if (vizOn == -1)
+                       return;
+       }
+       else
+               return;
+       
+       /* get all channels that can possibly be chosen 
+        *      - therefore, the filter is simply ANIMFILTER_CHANNELS, since if we took VISIBLE too,
+        *        then the channels under closed expanders get ignored...
+        */
+       filter= ANIMFILTER_CHANNELS;
+       ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
+       
+       /* find the channel that got changed */
+       for (ale= anim_data.first; ale; ale= ale->next) {
+               /* compare data, and type as main way of identifying the channel */
+               if ((ale->data == ale_setting->data) && (ale->type == ale_setting->type)) {
+                       /* we also have to check the ID, this is assigned to, since a block may have multiple users */
+                       // TODO: is the owner-data more revealing?
+                       if (ale->id == ale_setting->id) {
+                               match= ale;
+                               break;
+                       }
+               }
+       }
+       if (match == NULL) {
+               printf("ERROR: no channel matching the one changed was found \n");
+               BLI_freelistN(&anim_data);
+               return;
+       }
+       else {
+               bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale_setting);
+               
+               /* get the level of the channel that was affected
+                *       - we define the level as simply being the offset for the start of the channel
+                */
+               matchLevel= (acf->get_offset)? acf->get_offset(&ac, ale_setting) : 0;
+       }
+       
+       /* flush up? 
+        *      - only flush up if the current state is now enabled 
+        *        (otherwise, it's too much work to force the parents to be inactive too)
+        */
+       if (vizOn) {
+               /* go backwards in the list, until the highest-ranking element (by indention has been covered) */
+               for (ale= match->prev; ale; ale= ale->prev) {
+                       bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
+                       int level;
+                       
+                       /* get the level of the current channel traversed 
+                        *       - we define the level as simply being the offset for the start of the channel
+                        */
+                       level= (acf->get_offset)? acf->get_offset(&ac, ale) : 0;
+                       
+                       /* if the level is 'less than' (i.e. more important) the previous channel, 
+                        * flush the new status...
+                        */
+                       if (level < matchLevel)
+                               ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, vizOn);
+                       /* however, if the level is 'greater than' (i.e. less important than the previous channel,
+                        * stop searching, since we've already reached the bottom of another hierarchy
+                        */
+                       else if (level > matchLevel)
+                               break;
+                       
+                       /* store this level as the 'old' level now */
+                       prevLevel= level;
+               }
+       }
+       
+       /* flush down (always) */
+       {
+               /* go forwards in the list, until the lowest-ranking element (by indention has been covered) */
+               for (ale= match->next; ale; ale= ale->next) {
+                       bAnimChannelType *acf= ANIM_channel_get_typeinfo(ale);
+                       int level;
+                       
+                       /* get the level of the current channel traversed 
+                        *       - we define the level as simply being the offset for the start of the channel
+                        */
+                       level= (acf->get_offset)? acf->get_offset(&ac, ale) : 0;
+                       
+                       /* if the level is 'greater than' (i.e. less important) the channel that was changed, 
+                        * flush the new status...
+                        */
+                       if (level > matchLevel)
+                               ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, vizOn);
+                       /* however, if the level is 'less than or equal to' the channel that was changed,
+                        * (i.e. the current channel is as important if not more important than the changed channel)
+                        * then we should stop, since we've found the last one of the children we should flush
+                        */
+                       else
+                               break;
+                       
+                       /* store this level as the 'old' level now */
+                       prevLevel= level;
+               }
+       }
+       
+       /* free temp data */
+       BLI_freelistN(&anim_data);
+}
+
 /* callback for widget sliders - insert keyframes */
 static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poin)
 {
@@ -2237,7 +2428,57 @@ static void achannel_setting_slider_cb(bContext *C, void *id_poin, void *fcu_poi
        }
 }
 
-
+/* callback for shapekey widget sliders - insert keyframes */
+static void achannel_setting_slider_shapekey_cb(bContext *C, void *key_poin, void *kb_poin)
+{
+       Key *key= (Key *)key_poin;
+       KeyBlock *kb= (KeyBlock *)kb_poin;
+       char *rna_path= key_get_curValue_rnaPath(key, kb);
+       
+       Scene *scene= CTX_data_scene(C);
+       PointerRNA id_ptr, ptr;
+       PropertyRNA *prop;
+       short flag=0, done=0;
+       float cfra;
+       
+       /* get current frame */
+       // NOTE: this will do for now...
+       cfra= (float)CFRA;
+       
+       /* get flags for keyframing */
+       if (IS_AUTOKEY_FLAG(INSERTNEEDED))
+               flag |= INSERTKEY_NEEDED;
+       if (IS_AUTOKEY_FLAG(AUTOMATKEY))
+               flag |= INSERTKEY_MATRIX;
+       if (IS_AUTOKEY_MODE(scene, EDITKEYS))
+               flag |= INSERTKEY_REPLACE;
+       
+       
+       /* get RNA pointer, and resolve the path */
+       RNA_id_pointer_create((ID *)key, &id_ptr);
+       
+       /* try to resolve the path stored in the F-Curve */
+       if (RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop)) {
+               /* find or create new F-Curve */
+               // XXX is the group name for this ok?
+               bAction *act= verify_adt_action((ID *)key, 1);
+               FCurve *fcu= verify_fcurve(act, NULL, rna_path, 0, 1);
+               
+               /* set the special 'replace' flag if on a keyframe */
+               if (fcurve_frame_has_keyframe(fcu, cfra, 0))
+                       flag |= INSERTKEY_REPLACE;
+               
+               /* insert a keyframe for this F-Curve */
+               done= insert_keyframe_direct(ptr, prop, fcu, cfra, flag);
+               
+               if (done)
+                       WM_event_add_notifier(C, NC_ANIMATION|ND_ANIMCHAN_EDIT, NULL);
+       }
+       
+       /* free the path */
+       if (rna_path)
+               MEM_freeN(rna_path);
+}
 
 /* Draw a widget for some setting */
 static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChannelType *acf, uiBlock *block, int xpos, int ypos, int setting)
@@ -2260,9 +2501,9 @@ static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChan
                        icon= ICON_CHECKBOX_DEHLT;
                        
                        if (ale->type == ANIMTYPE_FCURVE)
-                               tooltip= "F-Curve is visible in Graph Editor for editing.";
+                               tooltip= "Channel is visible in Graph Editor for editing.";
                        else
-                               tooltip= "F-Curve(s) are visible in Graph Editor for editing.";
+                               tooltip= "Channel(s) are visible in Graph Editor for editing.";
                        break;
                        
                case ACHANNEL_SETTING_EXPAND: /* expanded triangle */
@@ -2327,10 +2568,14 @@ static void draw_setting_widget (bAnimContext *ac, bAnimListElem *ale, bAnimChan
                                break;
                }
                
-               /* set call to send relevant notifiers */
-               // NOTE: for now, we only need to send 'edited' 
-               if (but)
-                       uiButSetFunc(but, achannel_setting_widget_cb, NULL, NULL);
+               /* set call to send relevant notifiers and/or perform type-specific updates */
+               if (but) {
+                       /* 'visibility' toggles for Graph Editor need special flushing */
+                       if (setting == ACHANNEL_SETTING_VISIBLE) 
+                               uiButSetNFunc(but, achannel_setting_visible_widget_cb, MEM_dupallocN(ale), 0);
+                       else
+                               uiButSetFunc(but, achannel_setting_widget_cb, NULL, NULL);
+               }
        }
 }
 
@@ -2445,7 +2690,7 @@ void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *b
                 *        and wouldn't be able to auto-keyframe...
                 *      - slider should start before the toggles (if they're visible) to keep a clean line down the side
                 */
-               if ((draw_sliders) && (ale->type == ANIMTYPE_FCURVE)) {
+               if ((draw_sliders) && ELEM(ale->type, ANIMTYPE_FCURVE, ANIMTYPE_SHAPEKEY)) {
                        /* adjust offset */
                        offset += SLIDER_WIDTH;
                        
@@ -2453,20 +2698,49 @@ void ANIM_channel_draw_widgets (bAnimContext *ac, bAnimListElem *ale, uiBlock *b
                        uiBlockSetEmboss(block, UI_EMBOSS);
                        
                        if (ale->id) { /* Slider using RNA Access -------------------- */
-                               FCurve *fcu= (FCurve *)ale->data;
                                PointerRNA id_ptr, ptr;
                                PropertyRNA *prop;
+                               char *rna_path = NULL;
+                               int array_index = 0;
+                               short free_path = 0;
                                
-                               /* get RNA pointer, and resolve the path */
-                               RNA_id_pointer_create(ale->id, &id_ptr);
+                               /* get destination info */
+                               if (ale->type == ANIMTYPE_FCURVE) {
+                                       FCurve *fcu= (FCurve *)ale->data;
+                                       
+                                       rna_path= fcu->rna_path;
+                                       array_index= fcu->array_index;
+                               }
+                               else if (ale->type == ANIMTYPE_SHAPEKEY) {
+                                       KeyBlock *kb= (KeyBlock *)ale->data;
+                                       Key *key= (Key *)ale->id;
+                                       
+                                       rna_path= key_get_curValue_rnaPath(key, kb);
+                                       free_path= 1;
+                               }
                                
-                               /* try to resolve the path */
-                               if (RNA_path_resolve(&id_ptr, fcu->rna_path, &ptr, &prop)) {
-                                       uiBut *but;
+                               /* only if RNA-Path found */
+                               if (rna_path) {
+                                       /* get RNA pointer, and resolve the path */
+                                       RNA_id_pointer_create(ale->id, &id_ptr);
+                                       
+                                       /* try to resolve the path */
+                                       if (RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop)) {
+                                               uiBut *but;
+                                               
+                                               /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */
+                                               but= uiDefAutoButR(block, &ptr, prop, array_index, "", 0, (int)v2d->cur.xmax-offset, ymid, SLIDER_WIDTH, (int)ymaxc-yminc);
+                                               
+                                               /* assign keyframing function according to slider type */
+                                               if (ale->type == ANIMTYPE_SHAPEKEY)
+                                                       uiButSetFunc(but, achannel_setting_slider_shapekey_cb, ale->id, ale->data);
+                                               else
+                                                       uiButSetFunc(but, achannel_setting_slider_cb, ale->id, ale->data);
+                                       }
                                        
-                                       /* create the slider button, and assign relevant callback to ensure keyframes are inserted... */
-                                       but= uiDefAutoButR(block, &ptr, prop, fcu->array_index, "", 0, (int)v2d->cur.xmax-offset, ymid, SLIDER_WIDTH, (int)ymaxc-yminc);
-                                       uiButSetFunc(but, achannel_setting_slider_cb, ale->id, fcu);
+                                       /* free the path if necessary */
+                                       if (free_path)
+                                               MEM_freeN(rna_path);
                                }
                        }
                        else { /* Special Slider for stuff without RNA Access ---------- */
index 7ee591f8cab07114114b5a55befb090bc39b24d4..01945a9733ef7b0d8f1fc3c9248bbdc7675eec1d 100644 (file)
@@ -238,6 +238,10 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
                                        if (ale->flag & FCURVE_SELECTED)
                                                sel= ACHANNEL_SETFLAG_CLEAR;
                                        break;
+                               case ANIMTYPE_SHAPEKEY:
+                                       if (ale->flag & KEYBLOCK_SEL)
+                                               sel= ACHANNEL_SETFLAG_CLEAR;
+                                       break;
                                case ANIMTYPE_NLATRACK:
                                        if (ale->flag & NLATRACK_SELECTED)
                                                sel= ACHANNEL_SETFLAG_CLEAR;
@@ -307,6 +311,13 @@ void ANIM_deselect_anim_channels (void *data, short datatype, short test, short
                                fcu->flag &= ~FCURVE_ACTIVE;
                        }
                                break;
+                       case ANIMTYPE_SHAPEKEY:
+                       {
+                               KeyBlock *kb= (KeyBlock *)ale->data;
+                               
+                               ACHANNEL_SET_FLAG(kb, sel, KEYBLOCK_SEL);
+                       }
+                               break;
                        case ANIMTYPE_NLATRACK:
                        {
                                NlaTrack *nlt= (NlaTrack *)ale->data;
@@ -904,28 +915,14 @@ static int animchannels_visibility_toggle_exec(bContext *C, wmOperator *op)
                if (vis == ACHANNEL_SETFLAG_CLEAR) 
                        break;
                
-               if ((ale->type == ANIMTYPE_FCURVE) && (ale->flag & FCURVE_VISIBLE))
-                       vis= ACHANNEL_SETFLAG_CLEAR;
-               else if ((ale->type == ANIMTYPE_GROUP) && !(ale->flag & AGRP_NOTVISIBLE))
+               /* set the setting in the appropriate way (if available) */
+               if (ANIM_channel_setting_get(&ac, ale, ACHANNEL_SETTING_VISIBLE))
                        vis= ACHANNEL_SETFLAG_CLEAR;
        }
                
        /* Now set the flags */
        for (ale= anim_data.first; ale; ale= ale->next) {
-               switch (ale->type) {
-                       case ANIMTYPE_FCURVE: /* F-Curve */
-                       {
-                               FCurve *fcu= (FCurve *)ale->data;
-                               ACHANNEL_SET_FLAG(fcu, vis, FCURVE_VISIBLE);
-                       }
-                               break;
-                       case ANIMTYPE_GROUP: /* Group */
-                       {
-                               bActionGroup *agrp= (bActionGroup *)ale->data;
-                               ACHANNEL_SET_FLAG_NEG(agrp, vis, AGRP_NOTVISIBLE);
-                       }
-                               break;
-               }
+               ANIM_channel_setting_set(&ac, ale, ACHANNEL_SETTING_VISIBLE, vis);
        }
        
        /* cleanup */
@@ -1361,7 +1358,7 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh
        /* get the channel that was clicked on */
                /* filter channels */
        filter= (ANIMFILTER_VISIBLE | ANIMFILTER_CHANNELS);
-       filter= ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+       ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
        
                /* get channel from index */
        ale= BLI_findlink(&anim_data, channel_index);
@@ -1531,6 +1528,24 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh
                        if (fcu->flag & FCURVE_SELECTED)
                                ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, fcu, ANIMTYPE_FCURVE);
                                
+                       notifierFlags |= ND_ANIMCHAN_SELECT;
+               }
+                       break;
+               case ANIMTYPE_SHAPEKEY: 
+               {
+                       KeyBlock *kb= (KeyBlock *)ale->data;
+                       
+                       /* select/deselect */
+                       if (selectmode == SELECT_INVERT) {
+                               /* inverse selection status of this ShapeKey only */
+                               kb->flag ^= KEYBLOCK_SEL;
+                       }
+                       else {
+                               /* select ShapeKey by itself */
+                               ANIM_deselect_anim_channels(ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
+                               kb->flag |= KEYBLOCK_SEL;
+                       }
+                               
                        notifierFlags |= ND_ANIMCHAN_SELECT;
                }
                        break;
@@ -1571,9 +1586,6 @@ static int mouse_anim_channels (bAnimContext *ac, float x, int channel_index, sh
 #endif // XXX future of this is unclear
                }
                        break;
-               case ANIMTYPE_SHAPEKEY:
-                       /* TODO: shapekey channels cannot be selected atm... */
-                       break;
                default:
                        printf("Error: Invalid channel type in mouse_anim_channels() \n");
        }
index 2dc4aa09407d357760932daf7608dc004dab7c88..aa581a7d15afeb5c0e802e4e68559c53a711418f 100644 (file)
@@ -156,7 +156,7 @@ static void draw_cfra_number (Scene *scene, View2D *v2d, float cfra, short time)
        glScalef(xscale, 1.0, 1.0);
 }
 
-/* General call for drawing current frame indicator in a */
+/* General call for drawing current frame indicator in animation editor */
 void ANIM_draw_cfra (const bContext *C, View2D *v2d, short flag)
 {
        Scene *scene= CTX_data_scene(C);
index ea097420d1ac78101e518ab5875513d2e27d5d6b..8c4f10fb2224e57e918555973a69dd09111322ac 100644 (file)
@@ -78,6 +78,7 @@
 
 #include "BKE_animsys.h"
 #include "BKE_action.h"
+#include "BKE_fcurve.h"
 #include "BKE_context.h"
 #include "BKE_global.h"
 #include "BKE_key.h"
@@ -207,8 +208,10 @@ static short actedit_get_context (bAnimContext *ac, SpaceAction *saction)
 static short graphedit_get_context (bAnimContext *ac, SpaceIpo *sipo)
 {
        /* init dopesheet data if non-existant (i.e. for old files) */
-       if (sipo->ads == NULL)
+       if (sipo->ads == NULL) {
                sipo->ads= MEM_callocN(sizeof(bDopeSheet), "GraphEdit DopeSheet");
+               sipo->ads->source= (ID *)ac->scene;
+       }
        
        /* set settings for Graph Editor - "Selected = Editable" */
        if (sipo->flag & SIPO_SELCUVERTSONLY)
@@ -370,9 +373,18 @@ short ANIM_animdata_get_context (const bContext *C, bAnimContext *ac)
  *
  *     - id: ID block which should have an AnimData pointer following it immediately, to use
  *     - adtOk: line or block of code to execute for AnimData-blocks case (usually ANIMDATA_ADD_ANIMDATA)
- *     - nlaOk: line or block of code to execute for NLA case
+ *     - nlaOk: line or block of code to execute for NLA tracks+strips case
  *     - driversOk: line or block of code to execute for Drivers case
  *     - keysOk: line or block of code for Keyframes case
+ *
+ * The checks for the various cases are as follows:
+ *     0) top level: checks for animdata and also that all the F-Curves for the block will be visible
+ *     1) animdata check: for filtering animdata blocks only
+ *     2A) nla tracks: include animdata block's data as there are NLA tracks+strips there
+ *     2B) actions to convert to nla: include animdata block's data as there is an action that can be 
+ *             converted to a new NLA strip, and the filtering options allow this
+ *     3) drivers: include drivers from animdata block (for Drivers mode in Graph Editor)
+ *     4) normal keyframes: only when there is an active action
  */
 #define ANIMDATA_FILTER_CASES(id, adtOk, nlaOk, driversOk, keysOk) \
        {\
@@ -647,6 +659,36 @@ bAnimListElem *make_new_animlistelem (void *data, short datatype, void *owner, s
                                ale->datatype= ALE_FCURVE;
                        }
                                break;
+                               
+                       case ANIMTYPE_SHAPEKEY:
+                       {
+                               KeyBlock *kb= (KeyBlock *)data;
+                               Key *key= (Key *)ale->id;
+                               
+                               ale->flag= kb->flag;
+                               
+                               /* whether we have keyframes depends on whether there is a Key block to find it from */
+                               if (key) {
+                                       /* index of shapekey is defined by place in key's list */
+                                       ale->index= BLI_findindex(&key->block, kb);
+                                       
+                                       /* the corresponding keyframes are from the animdata */
+                                       if (ale->adt && ale->adt->action) {
+                                               bAction *act= ale->adt->action;
+                                               char *rna_path = key_get_curValue_rnaPath(key, kb);
+                                               
+                                               /* try to find the F-Curve which corresponds to this exactly,
+                                                * then free the MEM_alloc'd string
+                                                */
+                                               if (rna_path) {
+                                                       ale->key_data= (void *)list_find_fcurve(&act->curves, rna_path, 0);
+                                                       MEM_freeN(rna_path);
+                                               }
+                                       }
+                                       ale->datatype= (ale->key_data)? ALE_FCURVE : ALE_NONE;
+                               }
+                       }       
+                               break;
                        
                        case ANIMTYPE_GPLAYER:
                        {
@@ -892,7 +934,55 @@ static int animdata_filter_nla (ListBase *anim_data, bDopeSheet *ads, AnimData *
        /* return the number of items added to the list */
        return items;
 }
+
+/* Include ShapeKey Data for ShapeKey Editor */
+static int animdata_filter_shapekey (ListBase *anim_data, Key *key, int filter_mode)
+{
+       bAnimListElem *ale;
+       int items = 0;
+       
+       /* check if channels or only F-Curves */
+       if ((filter_mode & ANIMFILTER_CURVESONLY) == 0) {
+               KeyBlock *kb;
+               
+               /* loop through the channels adding ShapeKeys as appropriate */
+               for (kb= key->block.first; kb; kb= kb->next) {
+                       /* skip the first one, since that's the non-animateable basis */
+                       // XXX maybe in future this may become handy?
+                       if (kb == key->block.first) continue;
+                       
+                       /* only work with this channel and its subchannels if it is editable */
+                       if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_SHAPEKEY(kb)) {
+                               /* only include this track if selected in a way consistent with the filtering requirements */
+                               if ( ANIMCHANNEL_SELOK(SEL_SHAPEKEY(kb)) ) {
+                                       // TODO: consider 'active' too?
+                                       
+                                       /* owner-id here must be key so that the F-Curve can be resolved... */
+                                       ale= make_new_animlistelem(kb, ANIMTYPE_SHAPEKEY, NULL, ANIMTYPE_NONE, (ID *)key);
+                                       
+                                       if (ale) {
+                                               BLI_addtail(anim_data, ale);
+                                               items++;
+                                       }
+                               }
+                       }
+               }
+       }
+       else {
+               /* just use the action associated with the shapekey */
+               // FIXME: is owner-id and having no owner/dopesheet really fine?
+               if (key->adt) {
+                       if (filter_mode & ANIMFILTER_ANIMDATA)
+                               ANIMDATA_ADD_ANIMDATA(key)
+                       else if (key->adt->action)
+                               items= animdata_filter_action(anim_data, NULL, key->adt->action, filter_mode, NULL, ANIMTYPE_NONE, (ID *)key);
+               }
+       }
+       
+       /* return the number of items added to the list */
+       return items;
+}
+
 #if 0
 // FIXME: switch this to use the bDopeSheet...
 static int animdata_filter_gpencil (ListBase *anim_data, bScreen *sc, int filter_mode)
@@ -1023,7 +1113,7 @@ static int animdata_filter_dopesheet_mats (ListBase *anim_data, bDopeSheet *ads,
                        }
                        
                        /* add material's animation data */
-                       if (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+                       if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_CURVESONLY)) {
                                ANIMDATA_FILTER_CASES(ma, 
                                        { /* AnimData blocks - do nothing... */ },
                                        items += animdata_filter_nla(anim_data, ads, ma->adt, filter_mode, ma, ANIMTYPE_DSMAT, (ID *)ma);, 
@@ -1083,7 +1173,7 @@ static int animdata_filter_dopesheet_particles (ListBase *anim_data, bDopeSheet
                                }
                        }
                        
-                       if (FILTER_PART_OBJD(psys->part) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+                       if (!(filter_mode & ANIMFILTER_VISIBLE) || FILTER_PART_OBJD(psys->part) || (filter_mode & ANIMFILTER_CURVESONLY)) {
                                ANIMDATA_FILTER_CASES(psys->part,
                                        { /* AnimData blocks - do nothing... */ },
                                        items += animdata_filter_nla(anim_data, ads, psys->part->adt, filter_mode, psys->part, ANIMTYPE_DSPART, (ID *)psys->part);, 
@@ -1164,7 +1254,7 @@ static int animdata_filter_dopesheet_obdata (ListBase *anim_data, bDopeSheet *ad
        }
        
        /* add object-data animation channels? */
-       if ((expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
+       if (!(filter_mode & ANIMFILTER_VISIBLE) || (expanded) || (filter_mode & ANIMFILTER_CURVESONLY)) {
                /* filtering for channels - nla, drivers, keyframes */
                ANIMDATA_FILTER_CASES(iat, 
                        { /* AnimData blocks - do nothing... */ },
@@ -1202,7 +1292,8 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
        }
        
        /* if collapsed, don't go any further (unless adding keyframes only) */
-       if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
+       if ( ((filter_mode & ANIMFILTER_VISIBLE) && EXPANDED_OBJC(ob) == 0) &&
+                !(filter_mode & (ANIMFILTER_CURVESONLY|ANIMFILTER_NLATRACKS)) )
                return items;
        
        /* Action, Drivers, or NLA */
@@ -1225,7 +1316,7 @@ static int animdata_filter_dopesheet_ob (ListBase *anim_data, bDopeSheet *ads, B
                                }
                                
                                /* add F-Curve channels (drivers are F-Curves) */
-                               if (EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
+                               if (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_DRVD(adt) || !(filter_mode & ANIMFILTER_CHANNELS)) {
                                        // need to make the ownertype normal object here... (maybe type should be a separate one for clarity?)
                                        items += animdata_filter_fcurves(anim_data, ads, adt->drivers.first, NULL, ob, ANIMTYPE_OBJECT, filter_mode, (ID *)ob);
                                }