Animato: Added 'experimental' grouping schemes for F-Curves
authorJoshua Leung <aligorith@gmail.com>
Mon, 9 Feb 2009 10:04:11 +0000 (10:04 +0000)
committerJoshua Leung <aligorith@gmail.com>
Mon, 9 Feb 2009 10:04:11 +0000 (10:04 +0000)
When inserting keyframes on previous un-animated Objects/bones, F-Curves will be added into Action Groups into either "Object Transform" or <PoseChannel Name>. Ob->Material settings are not grouped for now to illustrate what's possible.

Old files are currently not patched to use do this, as it's still not clear whether this will be ideal.

source/blender/blenkernel/BKE_action.h
source/blender/blenkernel/intern/action.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/animation/anim_channels.c
source/blender/editors/animation/keyframing.c
source/blender/editors/include/ED_keyframing.h
source/blender/editors/space_action/action_draw.c
source/blender/editors/space_action/space_action.c
source/blender/editors/space_graph/graph_draw.c
source/blender/editors/space_graph/graph_edit.c
source/blender/editors/space_graph/space_graph.c

index 9abacf862c5726a2ae99e1ba5b67d673cd2e1868..a5a978ae3fa8b87735dc820720cb0e1cc8fcb9cf 100644 (file)
 
 #include "DNA_listBase.h"
 
-/**
- * The following structures are defined in DNA_action_types.h, and DNA_anim_types.h
- */
-
+/* The following structures are defined in DNA_action_types.h, and DNA_anim_types.h */
 struct bAction;
+struct bActionGroup;
+struct FCurve;
 struct bPose;
 struct bPoseChannel;
 struct Object;
@@ -52,28 +51,40 @@ struct ID;
 extern "C" {
 #endif
 
+/* Action API ----------------- */
+
+/* Allocate a new bAction with the given name */
 struct bAction *add_empty_action(const char name[]);
-       
-       /**
- * Allocate a new bAction on the heap and copy 
- * the contents of src into it. If src is NULL NULL is returned.
- */
 
+/* Allocate a copy of the given Action and all its data */     
 struct bAction *copy_action(struct bAction *src);
 
-/**
- * Deallocate the action's channels including constraint channels.
- * does not free the action structure.
- */
+/* Deallocate all of the Action's data, but not the Action itself */
 void free_action(struct bAction *act);
 
 // XXX is this needed?
 void make_local_action(struct bAction *act);
-       
-/**
- * Some kind of bounding box operation on the action.
- */
+               
+/* Some kind of bounding box operation on the action */
+// XXX depreceated..
 void calc_action_range(const struct bAction *act, float *start, float *end, int incl_hidden);
+
+/* Action Groups API ----------------- */
+
+/* Make the given Action Group the active one */
+void set_active_action_group(struct bAction *act, struct bActionGroup *agrp, short select);
+
+/* Add given channel into (active) group  */
+void action_groups_add_channel(struct bAction *act, struct bActionGroup *agrp, struct FCurve *fcurve);
+
+/* Remove the given channel from all groups */
+void action_groups_remove_channel(struct bAction *act, struct FCurve *fcu);
+
+/* Find a group with the given name */
+struct bActionGroup *action_groups_find_named(struct bAction *act, const char name[]);
+
+
+/* Pose API ----------------- */       
        
 /**
  * Removes and deallocates all channels from a pose.
index 72fd0259b89380e3f0cf4b3472357044ed918832..4e66d5f0ab89bf93ee4e6eedfd18ec0b1eefb451 100644 (file)
@@ -188,6 +188,192 @@ bAction *copy_action (bAction *src)
 }
 
 
+/* Get the active action-group for an Action */
+bActionGroup *get_active_actiongroup (bAction *act)
+{
+       bActionGroup *agrp= NULL;
+       
+       if (act && act->groups.first) { 
+               for (agrp= act->groups.first; agrp; agrp= agrp->next) {
+                       if (agrp->flag & AGRP_ACTIVE)
+                               break;
+               }
+       }
+       
+       return agrp;
+}
+
+/* Make the given Action-Group the active one */
+void set_active_action_group (bAction *act, bActionGroup *agrp, short select)
+{
+       bActionGroup *grp;
+       
+       /* sanity checks */
+       if (act == NULL)
+               return;
+       
+       /* Deactive all others */
+       for (grp= act->groups.first; grp; grp= grp->next) {
+               if ((grp==agrp) && (select))
+                       grp->flag |= AGRP_ACTIVE;
+               else    
+                       grp->flag &= ~AGRP_ACTIVE;
+       }
+}
+
+/* Add given channel into (active) group 
+ *     - assumes that channel is not linked to anything anymore
+ *     - always adds at the end of the group 
+ */
+void action_groups_add_channel (bAction *act, bActionGroup *agrp, FCurve *fcurve)
+{
+       FCurve *fcu;
+       short done=0;
+       
+       /* sanity checks */
+       if (ELEM3(NULL, act, agrp, fcurve))
+               return;
+       
+       /* if no channels, just add to two lists at the same time */
+       if (act->curves.first == NULL) {
+               fcurve->next = fcurve->prev = NULL;
+               
+               agrp->channels.first = agrp->channels.last = fcurve;
+               act->curves.first = act->curves.last = fcurve;
+               
+               fcurve->grp= agrp;
+               return;
+       }
+       
+       /* try to find a channel to slot this in before/after */
+       for (fcu= act->curves.first; fcu; fcu= fcu->next) {
+               /* if channel has no group, then we have ungrouped channels, which should always occur after groups */
+               if (fcu->grp == NULL) {
+                       BLI_insertlinkbefore(&act->curves, fcu, fcurve);
+                       
+                       if (agrp->channels.first == NULL)
+                               agrp->channels.first= fcurve;
+                       agrp->channels.last= fcurve;
+                       
+                       done= 1;
+                       break;
+               }
+               
+               /* if channel has group after current, we can now insert (otherwise we have gone too far) */
+               else if (fcu->grp == agrp->next) {
+                       BLI_insertlinkbefore(&act->curves, fcu, fcurve);
+                       
+                       if (agrp->channels.first == NULL)
+                               agrp->channels.first= fcurve;
+                       agrp->channels.last= fcurve;
+                       
+                       done= 1;
+                       break;
+               }
+               
+               /* if channel has group we're targeting, check whether it is the last one of these */
+               else if (fcu->grp == agrp) {
+                       if ((fcu->next) && (fcu->next->grp != agrp)) {
+                               BLI_insertlinkafter(&act->curves, fcu, fcurve);
+                               agrp->channels.last= fcurve;
+                               done= 1;
+                               break;
+                       }
+                       else if (fcu->next == NULL) {
+                               BLI_addtail(&act->curves, fcurve);
+                               agrp->channels.last= fcurve;
+                               done= 1;
+                               break;
+                       }
+               }
+               
+               /* if channel has group before target, check whether the next one is something after target */
+               else if (fcu->grp == agrp->prev) {
+                       if (fcu->next) {
+                               if ((fcu->next->grp != fcu->grp) && (fcu->next->grp != agrp)) {
+                                       BLI_insertlinkafter(&act->curves, fcu, fcurve);
+                                       
+                                       agrp->channels.first= fcurve;
+                                       agrp->channels.last= fcurve;
+                                       
+                                       done= 1;
+                                       break;
+                               }
+                       }
+                       else {
+                               BLI_insertlinkafter(&act->curves, fcu, fcurve);
+                               
+                               agrp->channels.first= fcurve;
+                               agrp->channels.last= fcurve;
+                               
+                               done= 1;
+                               break;
+                       }
+               }
+       }
+       
+       /* only if added, set channel as belonging to this group */
+       if (done)
+               fcurve->grp= agrp;
+       else 
+               printf("Error: FCurve '%s' couldn't be added to Group '%s' \n", fcurve->rna_path, agrp->name);
+}      
+
+/* Remove the given channel from all groups */
+void action_groups_remove_channel (bAction *act, FCurve *fcu)
+{
+       /* sanity checks */
+       if (ELEM(NULL, act, fcu))       
+               return;
+       
+       /* check if any group used this directly */
+       if (fcu->grp) {
+               bActionGroup *agrp= fcu->grp;
+               
+               if (agrp->channels.first == agrp->channels.last) {
+                       if (agrp->channels.first == fcu) {
+                               agrp->channels.first= NULL;
+                               agrp->channels.last= NULL;
+                       }
+               }
+               else if (agrp->channels.first == fcu) {
+                       if ((fcu->next) && (fcu->next->grp==agrp))
+                               agrp->channels.first= fcu->next;
+                       else
+                               agrp->channels.first= NULL;
+               }
+               else if (agrp->channels.last == fcu) {
+                       if ((fcu->prev) && (fcu->prev->grp==agrp))
+                               agrp->channels.last= fcu->prev;
+                       else
+                               agrp->channels.last= NULL;
+               }
+               
+               fcu->grp= NULL;
+       }
+       
+       /* now just remove from list */
+       BLI_remlink(&act->curves, fcu);
+}
+
+/* Find a group with the given name */
+bActionGroup *action_groups_find_named (bAction *act, const char name[])
+{
+       bActionGroup *grp;
+       
+       /* sanity checks */
+       if (ELEM3(NULL, act, act->groups.first, name) || (name[0] == 0))
+               return NULL;
+               
+       /* do string comparisons */
+       for (grp= act->groups.first; grp; grp= grp->next) {
+               if (strcmp(grp->name, name) == 0)
+                       return grp;
+       }
+       
+       /* not found */
+       return NULL;
+}
 
 /* ************************ Pose channels *************** */
 
index d22fc83f1e45bcdb79ca022b9ea3ab578ae5a79c..2a0f98cfe8d9dbe0ef8ef06d72f6cc4013499304 100644 (file)
@@ -5525,7 +5525,7 @@ static void area_add_window_regions(ScrArea *sa, SpaceLink *sl, ListBase *lb)
                                /* we totally reinit the view for the Action Editor, as some old instances had some weird cruft set */
                                ar->v2d.tot.xmin= -20.0f;
                                ar->v2d.tot.ymin= (float)(-sa->winy);
-                               ar->v2d.tot.xmax= (float)(sa->winx);
+                               ar->v2d.tot.xmax= (float)((sa->winx > 120)? (sa->winx) : 120);
                                ar->v2d.tot.ymax= 0.0f;
                                
                                ar->v2d.cur= ar->v2d.tot;
index a74476587800caa20a24a5e6eefe908a8073de44..a697580d674914acf1369f1e7883495039aafed8 100644 (file)
@@ -1075,7 +1075,7 @@ static void mouse_anim_channels (bAnimContext *ac, float x, int channel_index, s
                case ANIMTYPE_GROUP: 
                {
                        bActionGroup *agrp= (bActionGroup *)ale->data;
-                       short offset= (ac->datatype == ANIMCONT_DOPESHEET)? 21 : 0;
+                       short offset= (ac->datatype == ANIMCONT_DOPESHEET)? 18 : 0;
                        
                        if ((x < (offset+17)) && (agrp->channels.first)) {
                                /* toggle expand */
index 3b865f4dac109e61f8654233c344e47f3e522f56..110fd84a630e8015b742cf9085e7284ea8a5690d 100644 (file)
@@ -3,6 +3,7 @@
  */
  
 #include <stdio.h>
+#include <stddef.h>
 #include <string.h>
 #include <math.h>
 #include <float.h>
@@ -95,13 +96,13 @@ typedef struct bKeyingContext {
 /* Animation Data Validation */
 
 /* Get (or add relevant data to be able to do so) F-Curve from the Active Action, 
- * for the given Animation Data block 
+ * for the given Animation Data block. This assumes that all the destinations are valid.
  */
-// TODO: should we check if path is valid? For now, assume that it's already set OK by caller...
-FCurve *verify_fcurve (ID *id, const char rna_path[], const int array_index, short add)
+FCurve *verify_fcurve (ID *id, const char group[], const char rna_path[], const int array_index, short add)
 {
        AnimData *adt;
        bAction *act;
+       bActionGroup *grp;
        FCurve *fcu;
        
        /* sanity checks */
@@ -133,7 +134,7 @@ FCurve *verify_fcurve (ID *id, const char rna_path[], const int array_index, sho
                fcu= NULL;
        
        if ((fcu == NULL) && (add)) {
-               /* use default settings */
+               /* use default settings to make a F-Curve */
                fcu= MEM_callocN(sizeof(FCurve), "FCurve");
                
                fcu->flag |= (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES);
@@ -144,8 +145,33 @@ FCurve *verify_fcurve (ID *id, const char rna_path[], const int array_index, sho
                fcu->rna_path= BLI_strdupn(rna_path, strlen(rna_path));
                fcu->array_index= array_index;
                
-               /* add curve */
-               BLI_addtail(&act->curves, fcu); // XXX it might be better to add this in order, for easier UI coding...
+               
+               /* if a group name has been provided, try to add or find a group, then add F-Curve to it */
+               if (group) {
+                       /* try to find group */
+                       grp= action_groups_find_named(act, group);
+                       
+                       /* no matching groups, so add one */
+                       if (grp == NULL) {
+                               /* Add a new group, and make it active */
+                               grp= MEM_callocN(sizeof(bActionGroup), "bActionGroup");
+                               
+                               grp->flag |= (AGRP_ACTIVE|AGRP_SELECTED|AGRP_EXPANDED);
+                               BLI_snprintf(grp->name, 64, group);
+                               
+                               BLI_addtail(&act->groups, grp);
+                               BLI_uniquename(&act->groups, grp, "Group", offsetof(bActionGroup, name), 64);
+                               
+                               set_active_action_group(act, grp, 1);
+                       }
+                       
+                       /* add F-Curve to group */
+                       action_groups_add_channel(act, grp, fcu);
+               }
+               else {
+                       /* just add F-Curve to end of Action's list */
+                       BLI_addtail(&act->curves, fcu);
+               }
        }
        
        /* return the F-Curve */
@@ -711,7 +737,7 @@ static float visualkey_get_value (PointerRNA *ptr, PropertyRNA *prop, int array_
  *     the keyframe insertion. These include the 'visual' keyframing modes, quick refresh,
  *     and extra keyframe filtering.
  */
-short insertkey (ID *id, const char rna_path[], int array_index, float cfra, short flag)
+short insertkey (ID *id, const char group[], const char rna_path[], int array_index, float cfra, short flag)
 {      
        PointerRNA id_ptr, ptr;
        PropertyRNA *prop;
@@ -725,7 +751,7 @@ short insertkey (ID *id, const char rna_path[], int array_index, float cfra, sho
        }
        
        /* get F-Curve */
-       fcu= verify_fcurve(id, rna_path, array_index, 1);
+       fcu= verify_fcurve(id, group, rna_path, array_index, 1);
        
        /* only continue if we have an F-Curve to add keyframe to */
        if (fcu) {
@@ -809,7 +835,7 @@ short insertkey (ID *id, const char rna_path[], int array_index, float cfra, sho
  *     The flag argument is used for special settings that alter the behaviour of
  *     the keyframe deletion. These include the quick refresh options.
  */
-short deletekey (ID *id, const char rna_path[], int array_index, float cfra, short flag)
+short deletekey (ID *id, const char group[], const char rna_path[], int array_index, float cfra, short flag)
 {
        AnimData *adt;
        FCurve *fcu;
@@ -819,7 +845,7 @@ short deletekey (ID *id, const char rna_path[], int array_index, float cfra, sho
         *              so 'add' var must be 0
         */
        // XXX we don't check the validity of the path here yet, but it should be ok...
-       fcu= verify_fcurve(id, rna_path, array_index, 0);
+       fcu= verify_fcurve(id, group, rna_path, array_index, 0);
        adt= BKE_animdata_from_id(id);
        
        /* only continue if we have an ipo-curve to remove keyframes from */
@@ -2049,24 +2075,25 @@ static int insert_key_exec (bContext *C, wmOperator *op)
                        switch (mode) {
                        case 3: /* color of active material (only for geometry...) */
                                // NOTE: this is just a demo... but ideally we'd go through materials instead of active one only so reference stays same
-                               success+= insertkey(id, "active_material.diffuse_color", 0, cfra, 0);
-                               success+= insertkey(id, "active_material.diffuse_color", 1, cfra, 0);
-                               success+= insertkey(id, "active_material.diffuse_color", 2, cfra, 0);
+                               // XXX no group for now
+                               success+= insertkey(id, NULL, "active_material.diffuse_color", 0, cfra, 0);
+                               success+= insertkey(id, NULL, "active_material.diffuse_color", 1, cfra, 0);
+                               success+= insertkey(id, NULL, "active_material.diffuse_color", 2, cfra, 0);
                                break;
                        case 2: /* object scale */
-                               success+= insertkey(id, "scale", 0, cfra, 0);
-                               success+= insertkey(id, "scale", 1, cfra, 0);
-                               success+= insertkey(id, "scale", 2, cfra, 0);
+                               success+= insertkey(id, "Object Transforms", "scale", 0, cfra, 0);
+                               success+= insertkey(id, "Object Transforms", "scale", 1, cfra, 0);
+                               success+= insertkey(id, "Object Transforms", "scale", 2, cfra, 0);
                                break;
                        case 1: /* object rotation */
-                               success+= insertkey(id, "rotation", 0, cfra, 0);
-                               success+= insertkey(id, "rotation", 1, cfra, 0);
-                               success+= insertkey(id, "rotation", 2, cfra, 0);
+                               success+= insertkey(id, "Object Transforms", "rotation", 0, cfra, 0);
+                               success+= insertkey(id, "Object Transforms", "rotation", 1, cfra, 0);
+                               success+= insertkey(id, "Object Transforms", "rotation", 2, cfra, 0);
                                break;
                        default: /* object location */
-                               success+= insertkey(id, "location", 0, cfra, 0);
-                               success+= insertkey(id, "location", 1, cfra, 0);
-                               success+= insertkey(id, "location", 2, cfra, 0);
+                               success+= insertkey(id, "Object Transforms", "location", 0, cfra, 0);
+                               success+= insertkey(id, "Object Transforms", "location", 1, cfra, 0);
+                               success+= insertkey(id, "Object Transforms", "location", 2, cfra, 0);
                                break;
                        }
                        
@@ -2084,22 +2111,30 @@ static int insert_key_exec (bContext *C, wmOperator *op)
                                        switch (mode) {
                                        case 6: /* pchan scale */
                                                sprintf(buf, "pose.pose_channels[\"%s\"].scale", pchan->name);
-                                               success+= insertkey(id, buf, 0, cfra, 0);
-                                               success+= insertkey(id, buf, 1, cfra, 0);
-                                               success+= insertkey(id, buf, 2, cfra, 0);
+                                               success+= insertkey(id, pchan->name, buf, 0, cfra, 0);
+                                               success+= insertkey(id, pchan->name, buf, 1, cfra, 0);
+                                               success+= insertkey(id, pchan->name, buf, 2, cfra, 0);
                                                break;
                                        case 5: /* pchan rotation */
-                                               sprintf(buf, "pose.pose_channels[\"%s\"].rotation", pchan->name);
-                                               success+= insertkey(id, buf, 0, cfra, 0);
-                                               success+= insertkey(id, buf, 1, cfra, 0);
-                                               success+= insertkey(id, buf, 2, cfra, 0);
-                                               success+= insertkey(id, buf, 3, cfra, 0);
+                                               if (pchan->rotmode == PCHAN_ROT_QUAT) {
+                                                       sprintf(buf, "pose.pose_channels[\"%s\"].rotation", pchan->name);
+                                                       success+= insertkey(id, pchan->name, buf, 0, cfra, 0);
+                                                       success+= insertkey(id, pchan->name, buf, 1, cfra, 0);
+                                                       success+= insertkey(id, pchan->name, buf, 2, cfra, 0);
+                                                       success+= insertkey(id, pchan->name, buf, 3, cfra, 0);
+                                               }
+                                               else {
+                                                       sprintf(buf, "pose.pose_channels[\"%s\"].euler_rotation", pchan->name);
+                                                       success+= insertkey(id, pchan->name, buf, 0, cfra, 0);
+                                                       success+= insertkey(id, pchan->name, buf, 1, cfra, 0);
+                                                       success+= insertkey(id, pchan->name, buf, 2, cfra, 0);
+                                               }
                                                break;
                                        default: /* pchan location */
                                                sprintf(buf, "pose.pose_channels[\"%s\"].location", pchan->name);
-                                               success+= insertkey(id, buf, 0, cfra, 0);
-                                               success+= insertkey(id, buf, 1, cfra, 0);
-                                               success+= insertkey(id, buf, 2, cfra, 0);
+                                               success+= insertkey(id, pchan->name, buf, 0, cfra, 0);
+                                               success+= insertkey(id, pchan->name, buf, 1, cfra, 0);
+                                               success+= insertkey(id, pchan->name, buf, 2, cfra, 0);
                                                break;
                                        }
                                }
@@ -2172,7 +2207,7 @@ static int delete_key_exec (bContext *C, wmOperator *op)
                        
                        for (fcu= act->curves.first; fcu; fcu= fcn) {
                                fcn= fcu->next;
-                               success+= deletekey(id, fcu->rna_path, fcu->array_index, cfra, 0);
+                               success+= deletekey(id, NULL, fcu->rna_path, fcu->array_index, cfra, 0);
                        }
                }
                
index e7bdbb86ffa5e5140367e0c34dd66c589f6cc960..91dbbec873f7d1e8e2e35fefd6138593087bba1d 100644 (file)
@@ -73,12 +73,12 @@ enum {
  *     Use this to create any necessary animation data, and then insert a keyframe
  *     using the current value being keyframed, in the relevant place. Returns success.
  */
-short insertkey(struct ID *id, const char rna_path[], int array_index, float cfra, short flag);
+short insertkey(struct ID *id, const char group[], const char rna_path[], int array_index, float cfra, short flag);
 
 /* Main Keyframing API call: 
  *     Use this to delete keyframe on current frame for relevant channel. Will perform checks just in case.
  */
-short deletekey(struct ID *id, const char rna_path[], int array_index, float cfra, short flag);
+short deletekey(struct ID *id, const char group[], const char rna_path[], int array_index, float cfra, short flag);
 
 
 /* Main Keyframe Management operators: 
index 3152abcae9415e62866616cc4a79d516856c1edc..2908d3b8e3349266d1675ff47e29d2488f4d8c02 100644 (file)
@@ -594,7 +594,7 @@ void draw_channel_names(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
                                        indent= 0;
                                        special= -1;
                                        
-                                       offset= (ale->id) ? 21 : 0;
+                                       offset= (ale->id) ? 18 : 0;
                                        
                                        /* only show expand if there are any channels */
                                        if (agrp->channels.first) {
@@ -619,8 +619,8 @@ void draw_channel_names(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
                                        
                                        indent = 0;
                                        
-                                       //group= (ale->grp) ? 1 : 0;
-                                       //grp= ale->grp;
+                                       group= (fcu->grp) ? 1 : 0;
+                                       grp= fcu->grp;
                                        
                                        switch (ale->ownertype) {
                                                case ANIMTYPE_NONE:     /* no owner */
@@ -650,9 +650,7 @@ void draw_channel_names(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
                                        
                                        sel = SEL_FCU(fcu);
                                        
-                                       // for now, we just print the full path... this needs more work!
                                        getname_anim_fcurve(name, ale->id, fcu);
-                                       //sprintf(name, "%s[%d]", fcu->rna_path, fcu->array_index);
                                }
                                        break;
                                
index fea9214d08133dde159ea6ba88deea47172279ef..b4e43c29c3da816c09af2a98adffd9e632c1ac3e 100644 (file)
@@ -299,6 +299,7 @@ static void action_channel_area_listener(ARegion *ar, wmNotifier *wmn)
                        switch(wmn->data) {
                                case ND_BONE_ACTIVE:
                                case ND_BONE_SELECT:
+                               case ND_KEYS:
                                        ED_region_tag_redraw(ar);
                                        break;
                        }
index 6ccfae88b085e0ca0f500e49f873023a70481085..a6424c8f5b6012a4033fff3029b173d5c520992d 100644 (file)
@@ -875,7 +875,7 @@ void graph_draw_channel_names(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
                                        indent= 0;
                                        special= -1;
                                        
-                                       offset= (ale->id) ? 21 : 0;
+                                       offset= (ale->id) ? 18 : 0;
                                        
                                        /* only show expand if there are any channels */
                                        if (agrp->channels.first) {
@@ -900,8 +900,8 @@ void graph_draw_channel_names(bAnimContext *ac, SpaceIpo *sipo, ARegion *ar)
                                        
                                        indent = 0;
                                        
-                                       //group= (ale->grp) ? 1 : 0;
-                                       //grp= ale->grp;
+                                       group= (fcu->grp) ? 1 : 0;
+                                       grp= fcu->grp;
                                        
                                        // XXX include some UI element to allow toggling of visibility
                                        
index a7b9e8aa883d22a420c78bc3b2c08004cf62a9ee..08f724bb9a4796527aa212dd67407d3acba63ff7 100644 (file)
@@ -122,7 +122,6 @@ static void get_keyframe_extents (bAnimContext *ac, float *xmin, float *xmax, fl
                        
                        /* get range and apply necessary scaling before */
                        calc_fcurve_range(fcu, &tmin, &tmax);
-                       tmin= tmax= 0.0f; // xxx
                        
                        if (nob) {
                                tmin= get_action_frame_inv(nob, tmin);
index 3644406c12f10779663f7afad32162b2e6ce7234..29c92ee4496e16d511eb438a572e8d186b8e48db 100644 (file)
@@ -100,7 +100,7 @@ static SpaceLink *graph_new(const bContext *C)
        ar->regiontype= RGN_TYPE_WINDOW;
        
        ar->v2d.tot.xmin= 0.0f;
-       ar->v2d.tot.ymin= -10.0f;
+       ar->v2d.tot.ymin= (float)scene->r.sfra - 10.0f;
        ar->v2d.tot.xmax= (float)scene->r.efra;
        ar->v2d.tot.ymax= 10.0f;