/* Get the min/max keyframes*/ static void get_keyframe_extents (bAnimContext *ac, float *min, float *max, const short onlySel) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; /* get data to filter, from Action or Dopesheet */ filter= (ANIMFILTER_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_CURVESONLY | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* set large values to try to override */ *min= 999999999.0f; *max= -999999999.0f; /* check if any channels to set range with */ if (anim_data.first) { /* go through channels, finding max extents */ for (ale= anim_data.first; ale; ale= ale->next) { AnimData *adt= ANIM_nla_mapping_get(ac, ale); FCurve *fcu= (FCurve *)ale->key_data; float tmin, tmax; /* get range and apply necessary scaling before processing */ calc_fcurve_range(fcu, &tmin, &tmax, onlySel); if (adt) { tmin= BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP); tmax= BKE_nla_tweakedit_remap(adt, tmax, NLATIME_CONVERT_MAP); } /* try to set cur using these values, if they're more extreme than previously set values */ *min= MIN2(*min, tmin); *max= MAX2(*max, tmax); } /* free memory */ BLI_freelistN(&anim_data); } else { /* set default range */ if (ac->scene) { *min= (float)ac->scene->r.sfra; *max= (float)ac->scene->r.efra; } else { *min= -5; *max= 100; } } }
/* Calculate the extents of given action */ void calc_action_range(const bAction *act, float *start, float *end, short incl_modifiers) { FCurve *fcu; float min = 999999999.0f, max = -999999999.0f; short foundvert = 0, foundmod = 0; if (act) { for (fcu = act->curves.first; fcu; fcu = fcu->next) { /* if curve has keyframes, consider them first */ if (fcu->totvert) { float nmin, nmax; /* get extents for this curve */ /* TODO: allow enabling/disabling this? */ calc_fcurve_range(fcu, &nmin, &nmax, false, true); /* compare to the running tally */ min = min_ff(min, nmin); max = max_ff(max, nmax); foundvert = 1; } /* if incl_modifiers is enabled, need to consider modifiers too * - only really care about the last modifier */ if ((incl_modifiers) && (fcu->modifiers.last)) { FModifier *fcm = fcu->modifiers.last; /* only use the maximum sensible limits of the modifiers if they are more extreme */ switch (fcm->type) { case FMODIFIER_TYPE_LIMITS: /* Limits F-Modifier */ { FMod_Limits *fmd = (FMod_Limits *)fcm->data; if (fmd->flag & FCM_LIMIT_XMIN) { min = min_ff(min, fmd->rect.xmin); } if (fmd->flag & FCM_LIMIT_XMAX) { max = max_ff(max, fmd->rect.xmax); } break; } case FMODIFIER_TYPE_CYCLES: /* Cycles F-Modifier */ { FMod_Cycles *fmd = (FMod_Cycles *)fcm->data; if (fmd->before_mode != FCM_EXTRAPOLATE_NONE) min = MINAFRAMEF; if (fmd->after_mode != FCM_EXTRAPOLATE_NONE) max = MAXFRAMEF; break; } /* TODO: function modifier may need some special limits */ default: /* all other standard modifiers are on the infinite range... */ min = MINAFRAMEF; max = MAXFRAMEF; break; } foundmod = 1; } } } if (foundvert || foundmod) { if (min == max) max += 1.0f; *start = min; *end = max; } else { *start = 0.0f; *end = 1.0f; } }
/* Get the min/max keyframes*/ static bool get_keyframe_extents(bAnimContext *ac, float *min, float *max, const short onlySel) { ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; bool found = false; /* get data to filter, from Action or Dopesheet */ /* XXX: what is sel doing here?! * Commented it, was breaking things (eg. the "auto preview range" tool). */ filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE /*| ANIMFILTER_SEL *//*| ANIMFILTER_CURVESONLY*/ | ANIMFILTER_NODUPLIS); ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* set large values to try to override */ *min = 999999999.0f; *max = -999999999.0f; /* check if any channels to set range with */ if (anim_data.first) { /* go through channels, finding max extents */ for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ANIM_nla_mapping_get(ac, ale); if (ale->datatype == ALE_GPFRAME) { bGPDlayer *gpl = ale->data; bGPDframe *gpf; /* find gp-frame which is less than or equal to cframe */ for (gpf = gpl->frames.first; gpf; gpf = gpf->next) { const float framenum = (float)gpf->framenum; *min = min_ff(*min, framenum); *max = max_ff(*max, framenum); found = true; } } else if (ale->datatype == ALE_MASKLAY) { MaskLayer *masklay = ale->data; MaskLayerShape *masklay_shape; /* find mask layer which is less than or equal to cframe */ for (masklay_shape = masklay->splines_shapes.first; masklay_shape; masklay_shape = masklay_shape->next) { const float framenum = (float)masklay_shape->frame; *min = min_ff(*min, framenum); *max = max_ff(*max, framenum); found = true; } } else { FCurve *fcu = (FCurve *)ale->key_data; float tmin, tmax; /* get range and apply necessary scaling before processing */ if (calc_fcurve_range(fcu, &tmin, &tmax, onlySel, TRUE)) { if (adt) { tmin = BKE_nla_tweakedit_remap(adt, tmin, NLATIME_CONVERT_MAP); tmax = BKE_nla_tweakedit_remap(adt, tmax, NLATIME_CONVERT_MAP); } /* try to set cur using these values, if they're more extreme than previously set values */ *min = min_ff(*min, tmin); *max = max_ff(*max, tmax); found = true; } } } /* free memory */ BLI_freelistN(&anim_data); } else { /* set default range */ if (ac->scene) { *min = (float)ac->scene->r.sfra; *max = (float)ac->scene->r.efra; } else { *min = -5; *max = 100; } } return found; }