Finally, here is the basic (functional) prototype of the new animation system which will allow for the infamous "everything is animatable", and which also addresses several of the more serious shortcomings of the old system. Unfortunately, this will break old animation files (especially right now, as I haven't written the version patching code yet), however, this is for the future.
Highlights of the new system:
* Scrapped IPO-Curves/IPO/(Action+Constraint-Channels)/Action system, and replaced it with F-Curve/Action.
- F-Curves (animators from other packages will feel at home with this name) replace IPO-Curves.
- The 'new' Actions, act as the containers for F-Curves, so that they can be reused. They are therefore more akin to the old 'IPO' blocks, except they do not have the blocktype restriction, so you can store materials/texture/geometry F-Curves in the same Action as Object transforms, etc.
* F-Curves use RNA-paths for Data Access, hence allowing "every" (where sensible/editable that is) user-accessible setting from RNA to be animated.
* Drivers are no longer mixed with Animation Data, so rigs will not be that easily broken and several dependency problems can be eliminated. (NOTE: drivers haven't been hooked up yet, but the code is in place)
* F-Curve modifier system allows useful 'large-scale' manipulation of F-Curve values, including (I've only included implemented ones here): envelope deform (similar to lattices to allow broad-scale reshaping of curves), curve generator (polynomial or py-expression), cycles (replacing the old cyclic extrapolation modes, giving more control over this). (NOTE: currently this cannot be tested, as there's not access to them, but the code is all in place)
* NLA system with 'tracks' (i.e. layers), and multiple strips per track. (NOTE: NLA system is not yet functional, as it's only partially coded still)
There are more nice things that I will be preparing some nice docs for soon, but for now, check for more details:
http://lists.blender.org/pipermail/bf-taskforce25/2009-January/000260.html
So, what currently works:
* I've implemented two basic operators for the 3D-view only to Insert and Delete Keyframes. These are tempolary ones only that will be replaced in due course with 'proper' code.
* Object Loc/Rot/Scale can be keyframed. Also, the colour of the 'active' material (Note: this should really be for nth material instead, but that doesn't work yet in RNA) can also be keyframed into the same datablock.
* Standard animation refresh (i.e. animation resulting from NLA and Action evaluation) is now done completely separate from drivers before anything else is done after a frame change. Drivers are handled after this in a separate pass, as dictated by depsgraph flags, etc.
Notes:
* Drivers haven't been hooked up yet
* Only objects and data directly linked to objects can be animated.
* Depsgraph will need further tweaks. Currently, I've only made sure that it will update some things in the most basic cases (i.e. frame change).
* Animation Editors are currently broken (in terms of editing stuff). This will be my next target (priority to get Dopesheet working first, then F-Curve editor - i.e. old IPO Editor)
* I've had to put in large chunks of XXX sandboxing for old animation system code all around the place. This will be cleaned up in due course, as some places need special review.
In particular, the particles and sequencer code have far too many manual calls to calculate + flush animation info, which is really bad (this is a 'please explain yourselves' call to Physics coders!).
* All rights reserved.
*
* Contributor(s): Full recode, Ton Roosendaal, Crete 2005
+ * Full recode, Joshua Leung, 2009
*
* ***** END GPL LICENSE BLOCK *****
*/
#include "DNA_listBase.h"
/**
- * The following structures are defined in DNA_action_types.h
+ * The following structures are defined in DNA_action_types.h, and DNA_anim_types.h
*/
-struct bAction;
-struct bActionChannel;
+struct nAction;
struct bPose;
struct bPoseChannel;
struct Object;
extern "C" {
#endif
-struct bAction *add_empty_action(const char name[]);
+struct nAction *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.
+ */
+
+struct nAction *copy_action(struct nAction *src);
+
+/**
+ * Deallocate the action's channels including constraint channels.
+ * does not free the action structure.
+ */
+void free_action(struct nAction *act);
+
+// XXX is this needed?
+void make_local_action(struct nAction *act);
/**
* Removes and deallocates all channels from a pose.
void copy_pose(struct bPose **dst, struct bPose *src,
int copyconstraints);
-/**
- * Deallocate the action's channels including constraint channels.
- * does not free the action structure.
- */
-void free_action(struct bAction * id);
-
-void make_local_action(struct bAction *act);
-
-/* only for armatures, doing pose actions only too */
-void do_all_pose_actions(struct Scene *scene, struct Object *);
-/* only for objects, doing only 1 channel */
-void do_all_object_actions(struct Scene *scene, struct Object *);
/**
/* clears BONE_UNKEYED flags for frame changing */
void framechange_poses_clear_unkeyed(void);
-/**
- * Allocate a new bAction on the heap and copy
- * the contents of src into it. If src is NULL NULL is returned.
- */
-
-struct bAction *copy_action(struct bAction *src);
-
/**
* Some kind of bounding box operation on the action.
*/
*/
void what_does_obaction(struct Scene *scene, struct Object *ob, struct Object *workob, struct bAction *act, float cframe);
-/**
- * Iterate through the action channels of the action
- * and return the channel with the given name.
- * Returns NULL if no channel.
- */
-struct bActionChannel *get_action_channel(struct bAction *act, const char *name);
-/**
- * Iterate through the action channels of the action
- * and return the channel with the given name.
- * Returns and adds new channel if no channel.
- */
-struct bActionChannel *verify_action_channel(struct bAction *act, const char *name);
-
- /* baking */
-struct bAction *bake_obIPO_to_action(struct Object *ob);
-
/* exported for game engine */
void blend_poses(struct bPose *dst, struct bPose *src, float srcweight, short mode);
void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
float get_action_frame(struct Object *ob, float cframe);
/* map strip time to global time (frame nr) */
float get_action_frame_inv(struct Object *ob, float cframe);
-/* builds a list of NlaIpoChannel with ipo values to write in datablock */
-void extract_ipochannels_from_action(ListBase *lb, struct ID *id, struct bAction *act, const char *name, float ctime);
-/* write values returned by extract_ipochannels_from_action, returns the number of value written */
-int execute_ipochannels(ListBase *lb);
+
/* functions used by the game engine */
void game_copy_pose(struct bPose **dst, struct bPose *src);
--- /dev/null
+/* Testing code for new animation system in 2.5
+ * Copyright 2009, Joshua Leung
+ */
+
+#ifndef BKE_ANIM_SYS_H
+#define BKE_ANIM_SYS_H
+
+struct ID;
+struct ListBase;
+struct Main;
+struct AnimData;
+
+/* ************************************* */
+/* AnimData API */
+
+/* Get AnimData from the given ID-block. */
+struct AnimData *BKE_animdata_from_id(struct ID *id);
+
+/* ************************************* */
+// TODO: overrides, remapping, and path-finding api's
+
+/* ************************************* */
+/* Evaluation API */
+
+/* Evaluation loop for evaluating animation data */
+void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, float ctime, short recalc);
+
+/* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only */
+void BKE_animsys_evaluate_all_animation(struct Main *main, float ctime);
+
+
+/* ************************************* */
+
+#endif /* BKE_ANIM_SYS_H*/
struct ListBase;
struct Object;
struct Scene;
-struct bConstraintChannel;
struct bPoseChannel;
/* ---------------------------------------------------------------------------- */
void extract_proxylocal_constraints(struct ListBase *dst, struct ListBase *src);
short proxylocked_constraints_owner(struct Object *ob, struct bPoseChannel *pchan);
-/* Constraint Channel function prototypes */
-struct bConstraintChannel *get_constraint_channel(struct ListBase *list, const char *name);
-struct bConstraintChannel *verify_constraint_channel(struct ListBase *list, const char *name);
-void do_constraint_channels(struct ListBase *conbase, struct ListBase *chanbase, float ctime, short onlydrivers);
-void copy_constraint_channels(struct ListBase *dst, struct ListBase *src);
-void clone_constraint_channels(struct ListBase *dst, struct ListBase *src);
-void free_constraint_channels(struct ListBase *chanbase);
-
-
/* Constraint Evaluation function prototypes */
struct bConstraintOb *constraints_make_evalob(struct Scene *scene, struct Object *ob, void *subdata, short datatype);
void constraints_clear_evalob(struct bConstraintOb *cob);
--- /dev/null
+/* Testing code for new animation system in 2.5
+ * Copyright 2009, Joshua Leung
+ */
+
+#ifndef BKE_FCURVE_H
+#define BKE_FCURVE_H
+
+//struct ListBase;
+struct FCurve;
+struct FModifier;
+struct ChannelDriver;
+struct BezTriple;
+
+/* ************** Keyframe Tools ***************** */
+
+// XXX this stuff is defined in BKE_ipo.h too, so maybe skip for now?
+typedef struct CfraElem {
+ struct CfraElem *next, *prev;
+ float cfra;
+ int sel;
+} CfraElem;
+
+void bezt_add_to_cfra_elem(ListBase *lb, struct BezTriple *bezt);
+
+/* ************** F-Curve Drivers ***************** */
+
+void fcurve_free_driver(struct FCurve *fcu);
+
+/* ************** F-Curve Modifiers *************** */
+
+/* F-Curve Modifier Type-Info (fmi):
+ * This struct provides function pointers for runtime, so that functions can be
+ * written more generally (with fewer/no special exceptions for various modifiers).
+ *
+ * Callers of these functions must check that they actually point to something useful,
+ * as some constraints don't define some of these.
+ *
+ * Warning: it is not too advisable to reorder order of members of this struct,
+ * as you'll have to edit quite a few ($FMODIFIER_NUM_TYPES) of these
+ * structs.
+ */
+typedef struct FModifierTypeInfo {
+ /* admin/ident */
+ short type; /* FMODIFIER_TYPE_### */
+ short size; /* size in bytes of the struct */
+ char name[32]; /* name of modifier in interface */
+ char structName[32]; /* name of struct for SDNA */
+
+ /* data management function pointers - special handling */
+ /* free any data that is allocated separately (optional) */
+ void (*free_data)(struct FModifier *fcm);
+ /* copy any special data that is allocated separately (optional) */
+ void (*copy_data)(struct FModifier *fcm, struct FModifier *src);
+ /* set settings for data that will be used for FCuModifier.data (memory already allocated using MEM_callocN) */
+ void (*new_data)(void *mdata);
+
+ /* evaluation */
+ /* evaluate the modifier for the given time and 'accumulated' value */
+ void (*evaluate_modifier)(struct FCurve *fcu, struct FModifier *fcm, float *cvalue, float evaltime);
+} FModifierTypeInfo;
+
+/* Function Prototypes for FModifierTypeInfo's */
+FModifierTypeInfo *fmodifier_get_typeinfo(struct FModifier *fcm);
+FModifierTypeInfo *get_fmodifier_typeinfo(int type);
+
+/* ---------------------- */
+
+// TODO... general API here..
+struct FModifier *fcurve_add_modifier(struct FCurve *fcu, int type);
+void fcurve_copy_modifiers(ListBase *dst, ListBase *src);
+void fcurve_remove_modifier(struct FCurve *fcu, struct FModifier *fcm);
+void fcurve_free_modifiers(struct FCurve *fcu);
+void fcurve_bake_modifiers(struct FCurve *fcu, int start, int end);
+
+/* ************** F-Curves API ******************** */
+
+/* -------- Data Managemnt -------- */
+
+void free_fcurve(struct FCurve *fcu);
+struct FCurve *copy_fcurve(struct FCurve *fcu);
+
+/* find matching F-Curve in the given list of F-Curves */
+struct FCurve *list_find_fcurve(ListBase *list, const char rna_path[], const int array_index);
+
+/* -------- Curve Sanity -------- */
+
+void calchandles_fcurve(struct FCurve *fcu);
+void testhandles_fcurve(struct FCurve *fcu);
+void sort_time_fcurve(struct FCurve *fcu);
+short test_time_fcurve(struct FCurve *fcu);
+
+/* -------- Evaluation -------- */
+
+/* evaluate fcurve */
+float evaluate_fcurve(struct FCurve *fcu, float evaltime);
+/* evaluate fcurve and store value */
+void calculate_fcurve(struct FCurve *fcu, float ctime);
+
+
+#endif /* BKE_FCURVE_H*/
extern "C" {
#endif
+#if 0 // XXX old animation system
+
typedef struct CfraElem {
struct CfraElem *next, *prev;
float cfra;
short IPO_GetChannels(struct Ipo *ipo, short *channels);
float IPO_GetFloatValue(struct Ipo *ipo, short c, float ctime);
+#endif // XXX old animation system
+
#ifdef __cplusplus
};
#endif
#include "MEM_guardedalloc.h"
+#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curve_types.h"
-#include "DNA_ipo_types.h"
#include "DNA_key_types.h"
#include "DNA_nla_types.h"
#include "DNA_object_types.h"
#include "BKE_constraint.h"
#include "BKE_displist.h"
#include "BKE_global.h"
-#include "BKE_ipo.h"
+#include "BKE_fcurve.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
/* ***************** Library data level operations on action ************** */
-bAction *add_empty_action(const char name[])
+nAction *add_empty_action(const char name[])
{
- bAction *act;
+ nAction *act;
act= alloc_libblock(&G.main->action, ID_AC, name);
- act->id.flag |= LIB_FAKEUSER;
+ act->id.flag |= LIB_FAKEUSER; // XXX this is nasty for new users... maybe we don't want this anymore
act->id.us++;
return act;
}
-static void make_local_action_channels(bAction *act)
-{
- bActionChannel *chan;
- bConstraintChannel *conchan;
-
- for (chan=act->chanbase.first; chan; chan=chan->next) {
- if(chan->ipo) {
- if(chan->ipo->id.us==1) {
- chan->ipo->id.lib= NULL;
- chan->ipo->id.flag= LIB_LOCAL;
- new_id(0, (ID *)chan->ipo, 0);
- }
- else {
- chan->ipo= copy_ipo(chan->ipo);
- }
- }
- for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) {
- if(conchan->ipo) {
- if(conchan->ipo->id.us==1) {
- conchan->ipo->id.lib= NULL;
- conchan->ipo->id.flag= LIB_LOCAL;
- new_id(0, (ID *)conchan->ipo, 0);
- }
- else {
- conchan->ipo= copy_ipo(conchan->ipo);
- }
- }
- }
- }
-}
-
-void make_local_action(bAction *act)
+// does copy_fcurve...
+void make_local_action(nAction *act)
{
Object *ob;
- bAction *actn;
+ nAction *actn;
int local=0, lib=0;
- if(act->id.lib==0) return;
- if(act->id.us==1) {
+ if (act->id.lib==0) return;
+ if (act->id.us==1) {
act->id.lib= 0;
act->id.flag= LIB_LOCAL;
- make_local_action_channels(act);
+ //make_local_action_channels(act);
new_id(0, (ID *)act, 0);
return;
}
+#if 0 // XXX old animation system
ob= G.main->object.first;
while(ob) {
if(ob->action==act) {
}
ob= ob->id.next;
}
+#endif
if(local && lib==0) {
act->id.lib= 0;
act->id.flag= LIB_LOCAL;
- make_local_action_channels(act);
+ //make_local_action_channels(act);
new_id(0, (ID *)act, 0);
}
else if(local && lib) {
actn= copy_action(act);
actn->id.us= 0;
+#if 0 // XXX old animation system
ob= G.main->object.first;
while(ob) {
if(ob->action==act) {
}
ob= ob->id.next;
}
+#endif // XXX old animation system
}
}
-void free_action (bAction *act)
+void free_action (nAction *act)
{
- bActionChannel *chan;
+ FCurve *fcu, *fcn;
+
+ /* sanity check */
+ if (act == NULL)
+ return;
- /* Free channels */
- for (chan=act->chanbase.first; chan; chan=chan->next) {
- if (chan->ipo)
- chan->ipo->id.us--;
- free_constraint_channels(&chan->constraintChannels);
+ /* Free F-Curves */
+ for (fcu= act->curves.first; fcu; fcu= fcn) {
+ fcn= fcu->next;
+ free_fcurve(fcu);
}
- if (act->chanbase.first)
- BLI_freelistN(&act->chanbase);
-
/* Free groups */
if (act->groups.first)
BLI_freelistN(&act->groups);
BLI_freelistN(&act->markers);
}
-bAction *copy_action (bAction *src)
+nAction *copy_action (nAction *src)
{
- bAction *dst = NULL;
- bActionChannel *dchan, *schan;
+ nAction *dst = NULL;
+ //bActionChannel *dchan, *schan;
bActionGroup *dgrp, *sgrp;
if (!src) return NULL;
BLI_duplicatelist(&(dst->groups), &(src->groups));
BLI_duplicatelist(&(dst->markers), &(src->markers));
+#if 0 // XXX old animation system
for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next) {
for (dgrp=dst->groups.first, sgrp=src->groups.first; dgrp && sgrp; dgrp=dgrp->next, sgrp=sgrp->next) {
if (dchan->grp == sgrp) {
dchan->ipo = copy_ipo(dchan->ipo);
copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels);
}
+#endif // XXX old animation system
- dst->id.flag |= LIB_FAKEUSER;
+ dst->id.flag |= LIB_FAKEUSER; // XXX this is nasty for new users... maybe we don't want this anymore
dst->id.us++;
return dst;
Mat4One(chan->constinv);
- BLI_addtail (&pose->chanbase, chan);
+ BLI_addtail(&pose->chanbase, chan);
return chan;
}
/* ************************ END Pose channels *************** */
-/* ************************ Action channels *************** */
-
-
-bActionChannel *get_action_channel(bAction *act, const char *name)
-{
- bActionChannel *chan;
-
- if (!act || !name)
- return NULL;
-
- for (chan = act->chanbase.first; chan; chan=chan->next) {
- if (!strcmp (chan->name, name))
- return chan;
- }
-
- return NULL;
-}
-
-/* returns existing channel, or adds new one. In latter case it doesnt activate it, context is required for that */
-bActionChannel *verify_action_channel(bAction *act, const char *name)
-{
- bActionChannel *chan;
-
- chan= get_action_channel(act, name);
- if (chan == NULL) {
- chan = MEM_callocN (sizeof(bActionChannel), "actionChannel");
- strncpy(chan->name, name, 31);
- BLI_addtail(&act->chanbase, chan);
- }
- return chan;
-}
-
/* ************** time ****************** */
static bActionStrip *get_active_strip(Object *ob)
{
+#if 0 // XXX old animation system
bActionStrip *strip;
if(ob->action==NULL)
return NULL;
-
+
for (strip=ob->nlastrips.first; strip; strip=strip->next)
if(strip->flag & ACTSTRIP_ACTIVE)
break;
if(strip && strip->act==ob->action)
return strip;
+#endif // XXX old animation system
+
return NULL;
}
}
+
+
+/* Calculate the extents of given action */
+void calc_action_range(const bAction *act, float *start, float *end, int incl_hidden)
+{
+ FCurve *fcu;
+ float min=999999999.0f, max=-999999999.0f;
+ int foundvert=0;
+
+ if (act) {
+#if 0 // XXX old animation system
+ for (chan=act->chanbase.first; chan; chan=chan->next) {
+ if ((incl_hidden) || (chan->flag & ACHAN_HIDDEN)==0) {
+ if (chan->ipo) {
+ for (icu=chan->ipo->curve.first; icu; icu=icu->next) {
+ if (icu->totvert) {
+ min= MIN2(min, icu->bezt[0].vec[1][0]);
+ max= MAX2(max, icu->bezt[icu->totvert-1].vec[1][0]);
+ foundvert=1;
+ }
+ }
+ }
+ for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) {
+ if (conchan->ipo) {
+ for (icu=conchan->ipo->curve.first; icu; icu=icu->next) {
+ if (icu->totvert) {
+ min= MIN2(min, icu->bezt[0].vec[1][0]);
+ max= MAX2(max, icu->bezt[icu->totvert-1].vec[1][0]);
+ foundvert=1;
+ }
+ }
+ }
+ }
+ }
+ }
+#endif // XXX old animation system
+ }
+ if (foundvert) {
+ if(min==max) max+= 1.0f;
+ *start= min;
+ *end= max;
+ }
+ else {
+ *start= 0.0f;
+ *end= 1.0f;
+ }
+}
+
+/* Copy the data from the action-pose (src) into the pose */
+/* both args are assumed to be valid */
+/* exported to game engine */
+void extract_pose_from_pose(bPose *pose, const bPose *src)
+{
+ const bPoseChannel *schan;
+ bPoseChannel *pchan= pose->chanbase.first;
+
+ if (pose==src) {
+ printf("extract_pose_from_pose source and target are the same\n");
+ return;
+ }
+
+ for (schan=src->chanbase.first; schan; schan=schan->next, pchan= pchan->next) {
+ copy_pose_channel_data(pchan, schan);
+ }
+}
+
+/* Pose should exist, can have any number of channels too (used for constraint) */
+void extract_pose_from_action(bPose *pose, bAction *act, float ctime)
+{
+#if 0 // XXX old animation system
+ bActionChannel *achan;
+ bPoseChannel *pchan;
+ Ipo *ipo;
+
+ if (!act)
+ return;
+ if (!pose)
+ return;
+
+ /* Copy the data from the action into the pose */
+ for (pchan= pose->chanbase.first; pchan; pchan=pchan->next) {
+ /* skip this pose channel if it has been tagged as having unkeyed poses */
+ if ((pchan->bone) && (pchan->bone->flag & BONE_UNKEYED))
+ continue;
+
+ /* get action channel and clear pchan-transform flags */
+ achan= get_action_channel(act, pchan->name);
+ pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE);
+
+ if (achan) {
+ ipo = achan->ipo;
+ if (ipo) {
+ /* Evaluates and sets the internal ipo value */
+ calc_ipo(ipo, ctime);
+ /* This call also sets the pchan flags */
+ execute_action_ipo(achan, pchan);
+ }
+ /* 0 = do all ipos, not only drivers */
+ do_constraint_channels(&pchan->constraints, &achan->constraintChannels, ctime, 0);
+ }
+ }
+#endif // XXX old animation system
+
+ pose->ctime= ctime; /* used for cyclic offset matching */
+}
+
+/* for do_all_pose_actions, clears the pose. Now also exported for proxy and tools */
+void rest_pose(bPose *pose)
+{
+ bPoseChannel *pchan;
+ int i;
+
+ if (!pose)
+ return;
+
+ memset(pose->stride_offset, 0, sizeof(pose->stride_offset));
+ memset(pose->cyclic_offset, 0, sizeof(pose->cyclic_offset));
+
+ for (pchan=pose->chanbase.first; pchan; pchan= pchan->next){
+ for (i=0; i<3; i++) {
+ pchan->loc[i]= 0.0f;
+ pchan->quat[i+1]= 0.0f;
+ pchan->eul[i]= 0.0f;
+ pchan->size[i]= 1.0f;
+ }
+ pchan->quat[0]= 1.0f;
+
+ pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE);
+ }
+}
+
+/* both poses should be in sync */
+void copy_pose_result(bPose *to, bPose *from)
+{
+ bPoseChannel *pchanto, *pchanfrom;
+
+ if(to==NULL || from==NULL) {
+ printf("pose result copy error\n"); // debug temp
+ return;
+ }
+
+ if (to==from) {
+ printf("copy_pose_result source and target are the same\n");
+ return;
+ }
+
+
+ for(pchanfrom= from->chanbase.first; pchanfrom; pchanfrom= pchanfrom->next) {
+ pchanto= get_pose_channel(to, pchanfrom->name);
+ if(pchanto) {
+ Mat4CpyMat4(pchanto->pose_mat, pchanfrom->pose_mat);
+ Mat4CpyMat4(pchanto->chan_mat, pchanfrom->chan_mat);
+ /* used for local constraints */
+ VECCOPY(pchanto->loc, pchanfrom->loc);
+ QUATCOPY(pchanto->quat, pchanfrom->quat);
+ VECCOPY(pchanto->size, pchanfrom->size);
+
+ VECCOPY(pchanto->pose_head, pchanfrom->pose_head);
+ VECCOPY(pchanto->pose_tail, pchanfrom->pose_tail);
+ pchanto->flag= pchanfrom->flag;
+ }
+ }
+}
+
+/* ********** NLA with non-poses works with ipo channels ********** */
+
+#if 0 // XXX OLD ANIMATION SYSTEM (TO BE REMOVED)
+
/* ************************ Blending with NLA *************** */
static void blend_pose_strides(bPose *dst, bPose *src, float srcweight, short mode)
dst->ctime= src->ctime;
}
-/* Calculate the extents of given action */
-void calc_action_range(const bAction *act, float *start, float *end, int incl_hidden)
-{
- bActionChannel *chan;
- bConstraintChannel *conchan;
- IpoCurve *icu;
- float min=999999999.0f, max=-999999999.0f;
- int foundvert=0;
-
- if (act) {
- for (chan=act->chanbase.first; chan; chan=chan->next) {
- if ((incl_hidden) || (chan->flag & ACHAN_HIDDEN)==0) {
- if (chan->ipo) {
- for (icu=chan->ipo->curve.first; icu; icu=icu->next) {
- if (icu->totvert) {
- min= MIN2(min, icu->bezt[0].vec[1][0]);
- max= MAX2(max, icu->bezt[icu->totvert-1].vec[1][0]);
- foundvert=1;
- }
- }
- }
- for (conchan=chan->constraintChannels.first; conchan; conchan=conchan->next) {
- if (conchan->ipo) {
- for (icu=conchan->ipo->curve.first; icu; icu=icu->next) {
- if (icu->totvert) {
- min= MIN2(min, icu->bezt[0].vec[1][0]);
- max= MAX2(max, icu->bezt[icu->totvert-1].vec[1][0]);
- foundvert=1;
- }
- }
- }
- }
- }
- }
- }
- if (foundvert) {
- if(min==max) max+= 1.0f;
- *start= min;
- *end= max;
- }
- else {
- *start= 0.0f;
- *end= 1.0f;
- }
-}
-
-/* Copy the data from the action-pose (src) into the pose */
-/* both args are assumed to be valid */
-/* exported to game engine */
-void extract_pose_from_pose(bPose *pose, const bPose *src)
-{
- const bPoseChannel *schan;
- bPoseChannel *pchan= pose->chanbase.first;
-
- if (pose==src) {
- printf("extract_pose_from_pose source and target are the same\n");
- return;
- }
-
- for (schan=src->chanbase.first; schan; schan=schan->next, pchan= pchan->next) {
- copy_pose_channel_data(pchan, schan);
- }
-}
-
-/* Pose should exist, can have any number of channels too (used for constraint) */
-void extract_pose_from_action(bPose *pose, bAction *act, float ctime)
-{
- bActionChannel *achan;
- bPoseChannel *pchan;
- Ipo *ipo;
-
- if (!act)
- return;
- if (!pose)
- return;
-
- /* Copy the data from the action into the pose */
- for (pchan= pose->chanbase.first; pchan; pchan=pchan->next) {
- /* skip this pose channel if it has been tagged as having unkeyed poses */
- if ((pchan->bone) && (pchan->bone->flag & BONE_UNKEYED))
- continue;
-
- /* get action channel and clear pchan-transform flags */
- achan= get_action_channel(act, pchan->name);
- pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE);
-
- if (achan) {
- ipo = achan->ipo;
- if (ipo) {
- /* Evaluates and sets the internal ipo value */
- calc_ipo(ipo, ctime);
- /* This call also sets the pchan flags */
- execute_action_ipo(achan, pchan);
- }
- /* 0 = do all ipos, not only drivers */
- do_constraint_channels(&pchan->constraints, &achan->constraintChannels, ctime, 0);
- }
- }
-
- pose->ctime= ctime; /* used for cyclic offset matching */
-}
-
-/* for do_all_pose_actions, clears the pose. Now also exported for proxy and tools */
-void rest_pose(bPose *pose)
-{
- bPoseChannel *pchan;
- int i;
-
- if (!pose)
- return;
-
- memset(pose->stride_offset, 0, sizeof(pose->stride_offset));
- memset(pose->cyclic_offset, 0, sizeof(pose->cyclic_offset));
-
- for (pchan=pose->chanbase.first; pchan; pchan= pchan->next){
- for (i=0; i<3; i++) {
- pchan->loc[i]= 0.0f;
- pchan->quat[i+1]= 0.0f;
- pchan->eul[i]= 0.0f;
- pchan->size[i]= 1.0f;
- }
- pchan->quat[0]= 1.0f;
-
- pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE);
- }
-}
-
-/* both poses should be in sync */
-void copy_pose_result(bPose *to, bPose *from)
-{
- bPoseChannel *pchanto, *pchanfrom;
-
- if(to==NULL || from==NULL) {
- printf("pose result copy error\n"); // debug temp
- return;
- }
-
- if (to==from) {
- printf("copy_pose_result source and target are the same\n");
- return;
- }
-
-
- for(pchanfrom= from->chanbase.first; pchanfrom; pchanfrom= pchanfrom->next) {
- pchanto= get_pose_channel(to, pchanfrom->name);
- if(pchanto) {
- Mat4CpyMat4(pchanto->pose_mat, pchanfrom->pose_mat);
- Mat4CpyMat4(pchanto->chan_mat, pchanfrom->chan_mat);
- /* used for local constraints */
- VECCOPY(pchanto->loc, pchanfrom->loc);
- QUATCOPY(pchanto->quat, pchanfrom->quat);
- VECCOPY(pchanto->size, pchanfrom->size);
-
- VECCOPY(pchanto->pose_head, pchanfrom->pose_head);
- VECCOPY(pchanto->pose_tail, pchanfrom->pose_tail);
- pchanto->flag= pchanfrom->flag;
- }
- }
-}
-
-/* ********** NLA with non-poses works with ipo channels ********** */
-
typedef struct NlaIpoChannel {
struct NlaIpoChannel *next, *prev;
float val;
BLI_freelistN(&chanbase);
}
-void do_all_pose_actions(Scene *scene, Object *ob)
-{
- /* only to have safe calls from editor */
- if(ELEM(NULL, scene, ob)) return;
- if((ob->type!=OB_ARMATURE) || (ob->pose==NULL)) return;
-
- if(ob->pose->flag & POSE_LOCKED) { /* no actions to execute while transform */
- if(ob->pose->flag & POSE_DO_UNLOCK)
- ob->pose->flag &= ~(POSE_LOCKED|POSE_DO_UNLOCK);
- }
- else if( (ob->action) && ((ob->nlaflag & OB_NLA_OVERRIDE)==0 || (ob->nlastrips.first==NULL)) ) {
- float cframe= (float) scene->r.cfra;
-
- cframe= get_action_frame(ob, cframe);
-
- extract_pose_from_action(ob->pose, ob->action, bsystem_time(scene, ob, cframe, 0.0));
- }
- else if(ob->nlastrips.first) {
- do_nla(scene, ob, ID_AR);
- }
-
- /* clear POSE_DO_UNLOCK flags that might have slipped through (just in case) */
- ob->pose->flag &= ~POSE_DO_UNLOCK;
-}
-
-/* called from where_is_object */
-void do_all_object_actions(Scene *scene, Object *ob)
-{
- if(ob==NULL) return;
- if(ob->dup_group) return; /* prevent conflicts, might add smarter check later */
-
- /* Do local action */
- if(ob->action && ((ob->nlaflag & OB_NLA_OVERRIDE)==0 || ob->nlastrips.first==NULL) ) {
- ListBase tchanbase= {NULL, NULL};
- Key *key= ob_get_key(ob);
- float cframe= (float) scene->r.cfra;
-
- cframe= get_action_frame(ob, cframe);
-
- extract_ipochannels_from_action(&tchanbase, &ob->id, ob->action, "Object", bsystem_time(scene, ob, cframe, 0.0));
- if(key)
- extract_ipochannels_from_action(&tchanbase, &key->id, ob->action, "Shape", bsystem_time(scene, ob, cframe, 0.0));
-
- if(tchanbase.first) {
- execute_ipochannels(&tchanbase);
- BLI_freelistN(&tchanbase);
- }
- }
- else if(ob->nlastrips.first) {
- do_nla(scene, ob, ID_OB);
- }
-}
+#endif // XXX OLD ANIMATION SYSTEM (TO BE REMOVED)
else ok= 0;
}
if(ok) {
+#if 0 // XXX old animation system
do_ob_ipo(scene, ob);
+#endif // XXX old animation system
where_is_object_time(scene, ob, (float)scene->r.cfra);
dob= new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, OB_DUPLIFRAMES, animated);
Mat4CpyMat4(dob->omat, copyob.obmat);
--- /dev/null
+/* Testing code for new animation system in 2.5
+ * Copyright 2009, Joshua Leung
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+#include "BLI_dynstr.h"
+
+#include "BKE_animsys.h"
+#include "BKE_fcurve.h"
+#include "BKE_main.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+
+#include "DNA_anim_types.h"
+
+/* ***************************************** */
+/* AnimData API */
+
+/* Get AnimData from the given ID-block. In order for this to work, we assume that
+ * the AnimData block is stored immediately after the given ID-block in the struct,
+ * as per IdAdtTemplate.
+ */
+AnimData *BKE_animdata_from_id (ID *id)
+{
+ /* sanity check */
+ if (id == NULL)
+ return NULL;
+
+ /* only some ID-blocks have this info for now, so we cast the
+ * types that do to be of type IdAdtTemplate, and extract the
+ * animdata that way
+ */
+ // TODO: finish adding this for the other blocktypes
+ switch (GS(id->name)) {
+ case ID_OB:
+ case ID_KE:
+ case ID_MA: case ID_TE:
+ case ID_LA: case ID_CA: case ID_WO:
+ case ID_SCE:
+ {
+ IdAdtTemplate *iat= (IdAdtTemplate *)id;
+ return &(iat->adt);
+ }
+ break;
+ }
+
+ /* no AnimData (ID-block does not contain this data) */
+ return NULL;
+}
+
+/* Obtain an RNA-Path from the given ID-block to the property of interest
+ * - id: ID block that will be used as the 'root' of the path
+ * - ptr: pointer to struct where setting is stored
+ * - prop: property to get path for
+ */
+// TODO: should this be part of RNA Access API instead? or through editors only?
+char *BKE_animsys_get_rnapath (ID *id, PointerRNA *ptr, PropertyRNA *prop)
+{
+ // FIXME: this could be quite messy to do right :/
+ return NULL;
+}
+
+/* ***************************************** */
+/* Evaluation Data-Setting Backend */
+
+/* Retrieve string to act as RNA-path, adjusted using mapping-table if provided
+ * It returns whether the string needs to be freed (i.e. if it was a temp remapped one)
+ * // FIXME: maybe it would be faster if we didn't have to alloc/free strings like this all the time, but for now it's safer
+ *
+ * - remap: remapping table to use
+ * - path: original path string (as stored in F-Curve data)
+ * - dst: destination string to write data to
+ */
+short animsys_remap_path (AnimMapper *remap, char *path, char **dst)
+{
+ /* is there a valid remapping table to use? */
+ if (remap) {
+ /* find a matching entry... to use to remap */
+ // ...TODO...
+ }
+
+ /* nothing suitable found, so just set dst to look at path (i.e. no alloc/free needed) */
+ *dst= path;
+ return 0;
+}
+
+
+/* Write the given value to a setting using RNA */
+static void animsys_write_rna_setting (PointerRNA *ptr, char *path, int array_index, float value)
+{
+ PropertyRNA *prop;
+ PointerRNA new_ptr;
+
+ /* get property to write to */
+ if (RNA_path_resolve(ptr, path, &new_ptr, &prop))
+ {
+ /* set value - only for animatable numerical values */
+ // FIXME: probably 'editable' might not be enough in future...
+ if (RNA_property_editable(&new_ptr, prop))
+ {
+ switch (RNA_property_type(&new_ptr, prop))
+ {
+ case PROP_BOOLEAN:
+ if (RNA_property_array_length(&new_ptr, prop))
+ RNA_property_boolean_set_array(&new_ptr, prop, array_index, (int)value);
+ else
+ RNA_property_boolean_set(&new_ptr, prop, (int)value);
+ break;
+ case PROP_INT:
+ if (RNA_property_array_length(&new_ptr, prop))
+ RNA_property_int_set_array(&new_ptr, prop, array_index, (int)value);
+ else
+ RNA_property_int_set(&new_ptr, prop, (int)value);
+ break;
+ case PROP_FLOAT:
+ if (RNA_property_array_length(&new_ptr, prop))
+ RNA_property_float_set_array(&new_ptr, prop, array_index, value);
+ else
+ RNA_property_float_set(&new_ptr, prop, value);
+ break;
+ case PROP_ENUM:
+ RNA_property_enum_set(&new_ptr, prop, (int)value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+/* Simple replacement based data-setting of the FCurve using RNA */
+static void animsys_execute_fcurve (PointerRNA *ptr, AnimMapper *remap, FCurve *fcu)
+{
+ char *path = NULL;
+ short free_path=0;
+
+ /* get path, remapped as appropriate to work in its new environment */
+ free_path= animsys_remap_path(remap, fcu->rna_path, &path);
+
+ /* write value to setting */
+ animsys_write_rna_setting(ptr, path, fcu->array_index, fcu->curval);
+
+ /* free temp path-info */
+ if (free_path)
+ MEM_freeN(path);
+}
+
+/* Evaluate all the F-Curves in the given list
+ * This performs a set of standard checks. If extra checks are required, separate code should be used
+ */
+static void animsys_evaluate_fcurves (PointerRNA *ptr, ListBase *list, AnimMapper *remap, float ctime)
+{
+ FCurve *fcu;
+
+ /* calculate then execute each curve */
+ for (fcu= list->first; fcu; fcu= fcu->next)
+ {
+ /* check if this curve should be skipped */
+ if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0)
+ {
+ calculate_fcurve(fcu, ctime);
+ animsys_execute_fcurve(ptr, remap, fcu);
+ }
+ }
+}
+
+/* ***************************************** */
+/* Driver Evaluation */
+
+/* Evaluate Drivers */
+static void animsys_evaluate_drivers (PointerRNA *ptr, AnimData *adt, float ctime)
+{
+ FCurve *fcu;
+
+ /* drivers are stored as F-Curves, but we cannot use the standard code, as we need to check if
+ * the depsgraph requested that this driver be evaluated...
+ */
+ for (fcu= adt->drivers.first; fcu; fcu= fcu->next)
+ {
+ ChannelDriver *driver= fcu->driver;
+
+ /* check if this driver's curve should be skipped */
+ // FIXME: maybe we shouldn't check for muted, though that would make things more confusing, as there's already too many ways to disable?
+ if ((fcu->flag & (FCURVE_MUTED|FCURVE_DISABLED)) == 0)
+ {
+ /* check if driver itself is tagged for recalculation */
+ if ((driver) && (driver->flag & DRIVER_FLAG_RECALC)) {
+ /* evaluate this using values set already in other places */
+ // NOTE: for 'layering' option later on, we should check if we should remove old value before adding new to only be done when drivers only changed
+ calculate_fcurve(fcu, ctime);
+ animsys_execute_fcurve(ptr, NULL, fcu);
+
+ /* clear recalc flag */
+ driver->flag &= ~DRIVER_FLAG_RECALC;
+ }
+ }
+ }
+}
+
+/* ***************************************** */
+/* Actions Evaluation */
+
+/* Evaluate Action (F-Curve Bag) */
+static void animsys_evaluate_action (PointerRNA *ptr, nAction *act, AnimMapper *remap, float ctime)
+{
+ /* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */
+ if (act == NULL) return;
+ if ((remap) && (remap->target != act)) remap= NULL;
+
+ /* calculate then execute each curve */
+ animsys_evaluate_fcurves(ptr, &act->curves, remap, ctime);
+}
+
+/* ***************************************** */
+/* NLA System - Evaluation */
+
+/* used for list of strips to accumulate at current time */
+typedef struct NlaEvalStrip {
+ struct NlaEvalStrip *next, *prev;
+
+ NlaTrack *track; /* track that this strip belongs to */
+ NlaStrip *strip; /* strip that's being used */
+ NlaStrip *sblend; /* strip that's being blended towards (if applicable) */
+
+ short track_index; /* the index of the track within the list */
+ short strip_mode; /* which end of the strip are we looking at */
+} NlaEvalStrip;
+
+/* bNlaEvalStrip->strip_mode */
+enum {
+ NES_TIME_BEFORE = -1,
+ NES_TIME_WITHIN,
+ NES_TIME_AFTER,
+ NES_TIME_AFTER_BLEND
+} eNlaEvalStrip_StripMode;
+
+
+/* temp channel for accumulating data from NLA (avoids needing to clear all values first) */
+// TODO: maybe this will be used as the 'cache' stuff needed for editable values too?
+typedef struct NlaEvalChannel {
+ struct NlaEvalChannel *next, *prev;
+
+ char *path; /* ready-to-use path (i.e. remapped already) */
+ int array_index; /* if applicable... */
+
+ float value; /* value of this channel */
+} NlaEvalChannel;
+
+
+/* ---------------------- */
+
+/* evaluate the F-Curves controlling settings for the NLA-strips (currently, not relinkable) */
+static void nlastrip_evaluate_fcurves (NlaStrip *strip, float ctime)
+{
+ //PointerRNA actstrip_ptr;
+ //FCurve *fcu;
+
+ /* create RNA-pointer needed to set values */
+ //RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &actstrip_ptr);
+
+ /* execute these settings as per normal */
+ //animsys_evaluate_fcurves(&actstrip_ptr, &strip->fcurves, NULL, ctime);
+}
+
+
+/* gets the strip active at the current time for a track */
+static void nlatrack_ctime_get_strip (ListBase *list, NlaTrack *nlt, short index, float ctime)
+{
+ NlaStrip *strip, *astrip=NULL, *bstrip=NULL;
+ NlaEvalStrip *nes;
+ short side= 0;
+
+ /* skip if track is muted */
+ if (nlt->flag & NLATRACK_MUTED)
+ return;
+
+ /* loop over strips, checking if they fall within the range */
+ for (strip= nlt->strips.first; strip; strip= strip->next) {
+ /* only consider if:
+ * - current time occurs within strip's extents
+ * - current time occurs before strip (if it is the first)
+ * - current time occurs after strip (if hold is on)
+ * - current time occurs between strips (1st of those isn't holding) - blend!
+ */
+ if (IN_RANGE(ctime, strip->start, strip->end)) {
+ astrip= strip;
+ side= NES_TIME_WITHIN;
+ break;
+ }
+ else if (ctime < strip->start) {
+ if (strip == nlt->strips.first) {
+ astrip= strip;
+ side= NES_TIME_BEFORE;
+ break;
+ }
+ else {
+ astrip= strip->prev;
+
+ if (astrip->flag & NLASTRIP_HOLDLASTFRAME) {
+ side= NES_TIME_AFTER;
+ break;
+ }
+ else {
+ bstrip= strip;
+ side= NES_TIME_AFTER_BLEND;
+ break;
+ }
+ }
+ }
+ }
+
+ /* check if strip has been found (and whether it has data worth considering) */
+ if (ELEM(NULL, astrip, astrip->act))
+ return;
+ if (astrip->flag & NLASTRIP_MUTE)
+ return;
+
+ /* check if blending between strips */
+ if (side == NES_TIME_AFTER_BLEND) {
+ /* blending between strips... so calculate influence+act_time of both */
+ nlastrip_evaluate_fcurves(astrip, ctime);
+ nlastrip_evaluate_fcurves(bstrip, ctime);
+
+ if ((astrip->influence <= 0.0f) && (bstrip->influence <= 0.0f))
+ return;
+ }
+ else {
+ /* calculate/set the influence+act_time of this strip - don't consider if 0 influence */
+ nlastrip_evaluate_fcurves(astrip, ctime);
+
+ if (astrip->influence <= 0.0f)
+ return;
+ }
+
+
+ /* allocate new eval-strip for this strip + add to stack */
+ nes= MEM_callocN(sizeof(NlaEvalStrip), "bNlaEvalStrip");
+
+ nes->track= nlt;
+ nes->strip= astrip;
+ nes->sblend= bstrip;
+ nes->track_index= index;
+ nes->strip_mode= side;
+
+ BLI_addtail(list, nes);
+}
+
+/* ---------------------- */
+
+/* evaluates the given evaluation strip */
+// FIXME: will we need the evaluation cache table set up to blend stuff in?
+// TODO: only evaluate here, but flush in one go using the accumulated channels at end...
+static void nlastrip_ctime_evaluate (ListBase *channels, NlaEvalStrip *nes, float ctime)
+{
+ // 1. (in old code) was to extract 'IPO-channels' from actions
+ // 2. blend between the 'accumulated' data, and the new data
+}
+
+/* write the accumulated settings to */
+static void nladata_flush_channels (PointerRNA *ptr, ListBase *channels)
+{
+
+}
+
+/* ---------------------- */
+
+/* NLA Evaluation function (mostly for use through do_animdata)
+ * - All channels that will be affected are not cleared anymore. Instead, we just evaluate into
+ * some temp channels, where values can be accumulated in one go.
+ */
+static void animsys_evaluate_nla (PointerRNA *ptr, AnimData *adt, float ctime)
+{
+ NlaTrack *nlt;
+ short track_index=0;
+
+ ListBase estrips= {NULL, NULL};
+ ListBase echannels= {NULL, NULL};
+ NlaEvalStrip *nes;
+
+ /* 1. get the stack of strips to evaluate at current time (influence calculated here) */
+ for (nlt=adt->nla_tracks.first; nlt; nlt=nlt->next, track_index++)
+ nlatrack_ctime_get_strip(&estrips, nlt, track_index, ctime);
+
+ /* only continue if there are strips to evaluate */
+ if (estrips.first == NULL)
+ return;
+
+
+ /* 2. for each strip, evaluate then accumulate on top of existing channels, but don't set values yet */
+ for (nes= estrips.first; nes; nes= nes->next)
+ nlastrip_ctime_evaluate(&echannels, nes, ctime);
+
+ /* 3. flush effects of accumulating channels in NLA to the actual data they affect */
+ nladata_flush_channels(ptr, &echannels);
+
+ /* 4. free temporary evaluation data */
+ BLI_freelistN(&estrips);
+ BLI_freelistN(&echannels);
+}
+
+/* ***************************************** */
+/* Overrides System - Public API */
+
+/* Clear all overides */
+
+/* Add or get existing Override for given setting */
+AnimOverride *BKE_animsys_validate_override (PointerRNA *ptr, char *path, int array_index)
+{
+ // FIXME: need to define how to get overrides
+ return NULL;
+}
+
+/* -------------------- */
+
+/* Evaluate Overrides */
+static void animsys_evaluate_overrides (PointerRNA *ptr, AnimData *adt, float ctime)
+{
+ AnimOverride *aor;
+
+ /* for each override, simply execute... */
+ for (aor= adt->overrides.first; aor; aor= aor->next)
+ animsys_write_rna_setting(ptr, aor->rna_path, aor->array_index, aor->value);
+}
+
+/* ***************************************** */
+/* Evaluation System - Public API */
+
+/* Overview of how this system works:
+ * 1) Depsgraph sorts data as necessary, so that data is in an order that means
+ * that all dependences are resolved before dependants.
+ * 2) All normal animation is evaluated, so that drivers have some basis values to
+ * work with
+ * a. NLA stacks are done first, as the Active Actions act as 'tweaking' tracks
+ * which modify the effects of the NLA-stacks
+ * b. Active Action is evaluated as per normal, on top of the results of the NLA tracks
+ *
+ * --------------< often in a separate phase... >------------------
+ *
+ * 3) Drivers/expressions are evaluated on top of this, in an order where dependences are
+ * resolved nicely.
+ * Note: it may be necessary to have some tools to handle the cases where some higher-level
+ * drivers are added and cause some problematic dependencies that didn't exist in the local levels...
+ *
+ * --------------< always executed >------------------
+ *
+ * Maintainance of editability of settings (XXX):
+ * In order to ensure that settings that are animated can still be manipulated in the UI without requiring
+ * that keyframes are added to prevent these values from being overwritten, we use 'overrides'.
+ *
+ * Unresolved things:
+ * - Handling of multi-user settings (i.e. time-offset, group-instancing) -> big cache grids or nodal system? but stored where?
+ * - Multiple-block dependencies (i.e. drivers for settings are in both local and higher levels) -> split into separate lists?
+ */
+
+/* Evaluation loop for evaluation animation data
+ *
+ * This assumes that the animation-data provided belongs to the ID block in question,
+ * and that the flags for which parts of the anim-data settings need to be recalculated
+ * have been set already by the depsgraph. Now, we use the recalc
+ */
+void BKE_animsys_evaluate_animdata (ID *id, AnimData *adt, float ctime, short recalc)
+{
+ PointerRNA id_ptr;
+
+ /* sanity checks */
+ if ELEM(NULL, id, adt)
+ return;
+
+ /* get pointer to ID-block for RNA to use */
+ RNA_id_pointer_create(id, &id_ptr);
+
+ /* recalculate keyframe data:
+ * - NLA before Active Action, as Active Action behaves as 'tweaking track'
+ * that overrides 'rough' work in NLA
+ */
+ if ((recalc & ADT_RECALC_ANIM) /*|| (adt->recalc & ADT_RECALC_ANIM)*/) // XXX for now,don't check yet, as depsgraph doesn't know this yet
+ {
+ /* evaluate NLA data */
+ if ((adt->nla_tracks.first) && !(adt->flag & ADT_NLA_EVAL_OFF))
+ {
+ animsys_evaluate_nla(&id_ptr, adt, ctime);
+ }
+
+ /* evaluate Action data */
+ // FIXME: what if the solo track was not tweaking one, then nla-solo should be checked too?
+ if (adt->action)
+ animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime);
+ }
+
+ /* recalculate drivers
+ * - Drivers need to be evaluated afterwards, as they can either override
+ * or be layered on top of existing animation data.
+ * - Drivers should be in the appropriate order to be evaluated without problems...
+ */
+ if ((recalc & ADT_RECALC_DRIVERS) && (adt->recalc & ADT_RECALC_DRIVERS))
+ {
+ animsys_evaluate_drivers(&id_ptr, adt, ctime);
+ }
+
+ /* always execute 'overrides'
+ * - Overrides allow editing, by overwriting the value(s) set from animation-data, with the
+ * value last set by the user (and not keyframed yet).
+ * - Overrides are cleared upon frame change and/or keyframing
+ * - It is best that we execute this everytime, so that no errors are likely to occur.
+ */
+ animsys_evaluate_overrides(&id_ptr, adt, ctime);
+
+ /* clear recalc flag now */
+ adt->recalc= 0;
+}
+
+/* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only
+ *
+ * This will evaluate only the animation info available in the animation data-blocks
+ * encountered. In order to enforce the system by which some settings controlled by a
+ * 'local' (i.e. belonging in the nearest ID-block that setting is related to, not a
+ * standard 'root') block are overridden by a larger 'user'
+ */
+// TODO: we currently go over entire 'main' database...
+void BKE_animsys_evaluate_all_animation (Main *main, float ctime)
+{
+ ID *id;
+
+ //printf("Evaluate all animation - %f \n", ctime);
+
+ /* cameras */
+
+ /* textures */
+
+ /* lamps */
+
+ /* materials */
+
+ /* objects */
+ for (id= main->object.first; id; id= id->next) {
+ IdAdtTemplate *iat= (IdAdtTemplate *)id;
+ BKE_animsys_evaluate_animdata(id, &iat->adt, ctime, ADT_RECALC_ANIM);
+ }
+}
+
+/* ***************************************** */
if (pchan->constraints.first) {
bConstraintOb *cob;
- /* local constraints */
- do_constraint_channels(&pchan->constraints, NULL, ctime, 0);
-
/* make a copy of location of PoseChannel for later */
VECCOPY(vec, pchan->pose_mat[3]);
#endif
-/* ******************* Constraint Channels ********************** */
-/* Constraint Channels exist in one of two places:
- * - Under Action Channels in an Action (act->chanbase->achan->constraintChannels)
- * - Under Object without Object-level Action yet (ob->constraintChannels)
- *
- * The main purpose that Constraint Channels serve is to act as a link
- * between an IPO-block (which provides values to interpolate between for some settings)
- */
-
-/* ------------ Data Management ----------- */
-
-/* Free constraint channels, and reduce the number of users of the related ipo-blocks */
-void free_constraint_channels (ListBase *chanbase)
-{
- bConstraintChannel *chan;
-
- for (chan=chanbase->first; chan; chan=chan->next) {
- if (chan->ipo) {
- chan->ipo->id.us--;
- }
- }
-
- BLI_freelistN(chanbase);
-}
-
-/* Make a copy of the constraint channels from dst to src, and also give the
- * new constraint channels their own copy of the original's IPO.
- */
-void copy_constraint_channels (ListBase *dst, ListBase *src)
-{
- bConstraintChannel *dchan, *schan;
-
- dst->first = dst->last = NULL;
- BLI_duplicatelist(dst, src);
-
- for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next) {
- dchan->ipo = copy_ipo(schan->ipo);
- }
-}
-
-/* Make a copy of the constraint channels from dst to src, but make the
- * new constraint channels use the same IPO-data as their twin.
- */
-void clone_constraint_channels (ListBase *dst, ListBase *src)
-{
- bConstraintChannel *dchan, *schan;
-
- dst->first = dst->last = NULL;
- BLI_duplicatelist(dst, src);
-
- for (dchan=dst->first, schan=src->first; dchan; dchan=dchan->next, schan=schan->next) {
- id_us_plus((ID *)dchan->ipo);
- }
-}
-
-/* ------------- Constraint Channel Tools ------------ */
-
-/* Find the constraint channel with a given name */
-bConstraintChannel *get_constraint_channel (ListBase *list, const char name[])
-{
- bConstraintChannel *chan;
-
- if (list) {
- for (chan = list->first; chan; chan=chan->next) {
- if (!strcmp(name, chan->name)) {
- return chan;
- }
- }
- }
-
- return NULL;
-}
-
-/* Find or create a new constraint channel */
-bConstraintChannel *verify_constraint_channel (ListBase *list, const char name[])
-{
- bConstraintChannel *chan;
-
- chan= get_constraint_channel(list, name);
-
- if (chan == NULL) {
- chan= MEM_callocN(sizeof(bConstraintChannel), "new constraint channel");
- BLI_addtail(list, chan);
- strcpy(chan->name, name);
- }
-
- return chan;
-}
-
-/* --------- Constraint Channel Evaluation/Execution --------- */
-
-/* IPO-system call: calculate IPO-block for constraint channels, and flush that
- * info onto the corresponding constraint.
- */
-void do_constraint_channels (ListBase *conbase, ListBase *chanbase, float ctime, short onlydrivers)
-{
- bConstraint *con;
-
- /* for each Constraint, calculate its Influence from the corresponding ConstraintChannel */
- for (con=conbase->first; con; con=con->next) {
- Ipo *ipo= NULL;
-
- if (con->flag & CONSTRAINT_OWN_IPO)
- ipo= con->ipo;
- else {
- bConstraintChannel *chan = get_constraint_channel(chanbase, con->name);
- if (chan) ipo= chan->ipo;
- }
-
- if (ipo) {
- IpoCurve *icu;
-
- calc_ipo(ipo, ctime);
-
- for (icu=ipo->curve.first; icu; icu=icu->next) {
- if (!onlydrivers || icu->driver) {
- switch (icu->adrcode) {
- case CO_ENFORCE:
- {
- /* Influence is clamped to 0.0f -> 1.0f range */
- con->enforce = CLAMPIS(icu->curval, 0.0f, 1.0f);
- }
- break;
- case CO_HEADTAIL:
- {
- /* we need to check types of constraints that can get this here, as user
- * may have created an IPO-curve for this from IPO-editor but for a constraint
- * that cannot support this
- */
- switch (con->type) {
- /* supported constraints go here... */
- case CONSTRAINT_TYPE_LOCLIKE:
- case CONSTRAINT_TYPE_TRACKTO:
- case CONSTRAINT_TYPE_MINMAX:
- case CONSTRAINT_TYPE_STRETCHTO:
- case CONSTRAINT_TYPE_DISTLIMIT:
- con->headtail = icu->curval;
- break;
-
- default:
- /* not supported */
- break;
- }
- }
- break;
- }
- }
- }
- }
- }
-}
/* ************************ Constraints - General Utilities *************************** */
/* These functions here don't act on any specific constraints, and are therefore should/will
if (cu->path && cu->path->data) {
curvetime= bsystem_time(cob->scene, ct->tar, (float)ctime, 0.0) - data->offset;
+#if 0 // XXX old animation system
if (calc_ipo_spec(cu->ipo, CU_SPEED, &curvetime)==0) {
curvetime /= cu->pathlen;
CLAMP(curvetime, 0.0, 1.0);
}
+#endif // XXX old animation system
if ( where_on_path(ct->tar, curvetime, vec, dir) ) {
if (data->followflag) {
else if (cob->type == CONSTRAINT_OBTYPE_OBJECT) {
Object workob;
/* evaluate using workob */
- what_does_obaction(cob->scene, cob->ob, &workob, data->act, t);
+ //what_does_obaction(cob->scene, cob->ob, &workob, data->act, t); // FIXME: missing func...
object_to_mat4(&workob, ct->matrix);
}
else {
if (con->enforce == 0.0f) continue;
/* influence of constraint
- * - value should have been set from IPO's/Constraint Channels already
+ * - value should have been set from animation data already
*/
enf = con->enforce;
/* for dereferencing pointers */
#include "DNA_ID.h"
#include "DNA_key_types.h"
-#include "DNA_ipo_types.h"
#include "DNA_scene_types.h"
#include "DNA_vfont_types.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
#include "BKE_global.h"
-#include "BKE_ipo.h"
#include "BKE_key.h"
#include "BKE_library.h"
#include "BKE_main.h"
cu->vfont= 0;
if(cu->key) cu->key->id.us--;
cu->key= 0;
+#if 0 // XXX old animation system
if(cu->ipo) cu->ipo->id.us--;
cu->ipo= 0;
+#endif // XXX old animation system
}
cun->bev.first= cun->bev.last= 0;
cun->path= 0;
+#if 0 // XXX old animation system
/* single user ipo too */
if(cun->ipo) cun->ipo= copy_ipo(cun->ipo);
+#endif // XXX old animation system
id_us_plus((ID *)cun->vfont);
id_us_plus((ID *)cun->vfontb);
* 1: nothing, 1:auto, 2:vector, 3:aligned
*/
-/* mode: is not zero when IpoCurve, is 2 when forced horizontal for autohandles */
+/* mode: is not zero when FCurve, is 2 when forced horizontal for autohandles */
void calchandleNurb(BezTriple *bezt, BezTriple *prev, BezTriple *next, int mode)
{
float *p1,*p2,*p3, pt[3];
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
+#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_curve_types.h"
static int exists_channel(Object *ob, char *name)
{
+#if 0 // XXX old animation system
bActionStrip *strip;
if(ob->action)
for (strip=ob->nlastrips.first; strip; strip=strip->next)
if(get_action_channel(strip->act, name))
return 1;
+#endif // XXX old animation system
+
return 0;
}
-static void dag_object_time_update_flags(Object *ob)
+
+static short animdata_use_time(AnimData *adt)
{
+ NlaTrack *nlt;
- if(ob->ipo) ob->recalc |= OB_RECALC_OB;
- else if(ob->constraints.first) {
+ /* check action - only if assigned, and it has anim curves */
+ if (adt->action && adt->action->curves.first)
+ return 1;
+
+ /* check NLA tracks + strips */
+ for (nlt= adt->nla_tracks.first; nlt; nlt= nlt->next) {
+ if (nlt->strips.first)
+ return 1;
+ }
+
+ return 0;
+}
+
+static void dag_object_time_update_flags(Object *ob)
+{
+ if(ob->constraints.first) {
bConstraint *con;
for (con = ob->constraints.first; con; con=con->next) {
bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
if(ob->parent->type==OB_CURVE || ob->parent->type==OB_ARMATURE) ob->recalc |= OB_RECALC_OB;
}
+#if 0 // XXX old animation system
if(ob->action || ob->nlastrips.first) {
/* since actions now are mixed, we set the recalcs on the safe side */
ob->recalc |= OB_RECALC_OB;
}
}
}
+#endif // XXX old animation system
+ if(animdata_use_time(&ob->adt)) ob->recalc |= OB_RECALC;
if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA;
if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA;
--- /dev/null
+/* Testing code for new animation system in 2.5
+ * Copyright 2009, Joshua Leung
+ */
+
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_anim_types.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
+
+#include "BKE_fcurve.h"
+#include "BKE_curve.h"
+#include "BKE_idprop.h"
+#include "BKE_utildefines.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+
+#ifndef DISABLE_PYTHON
+#include "BPY_extern.h" /* for BPY_pydriver_eval() */
+#endif
+
+#define SMALL -1.0e-10
+#define SELECT 1
+
+/* ************************** Data-Level Functions ************************* */
+
+/* ---------------------- Freeing --------------------------- */
+
+/* Frees the F-Curve itself too */
+void free_fcurve (FCurve *fcu)
+{
+ if (fcu == NULL)
+ return;
+
+ /* free curve data */
+ if (fcu) {
+ if (fcu->bezt) MEM_freeN(fcu->bezt);
+ if (fcu->fpt) MEM_freeN(fcu->fpt);
+ }
+
+ /* free RNA-path, as this were allocated when getting the path string */
+ if (fcu->rna_path)
+ MEM_freeN(fcu->rna_path);
+
+ /* free extra data - i.e. modifiers, and driver */
+ fcurve_free_driver(fcu);
+ fcurve_free_modifiers(fcu);
+
+ /* free f-cruve itself */
+ MEM_freeN(fcu);
+}
+
+/* ---------------------- Copy --------------------------- */
+
+/* duplicate an F-Curve */
+FCurve *copy_fcurve (FCurve *fcu)
+{
+ FCurve *fcu_d;
+
+ /* sanity check */
+ if (fcu == NULL)
+ return NULL;
+
+ /* make a copy */
+ fcu_d= MEM_dupallocN(fcu);
+
+ /* copy curve data */
+ fcu_d->bezt= MEM_dupallocN(fcu_d->bezt);
+ fcu_d->fpt= MEM_dupallocN(fcu_d->fpt);
+
+ /* copy rna-path */
+ fcu_d->rna_path= MEM_dupallocN(fcu_d->rna_path);
+
+ /* copy driver */
+ //fcurve_copy_driver();
+
+ /* copy modifiers */
+ fcurve_copy_modifiers(&fcu_d->modifiers, &fcu->modifiers);
+
+ /* return new data */
+ return fcu_d;
+}
+
+/* ---------------------- Relink --------------------------- */
+
+#if 0
+/* uses id->newid to match pointers with other copied data
+ * - called after single-user or other such
+ */
+ if (icu->driver)
+ ID_NEW(icu->driver->ob);
+#endif
+
+/* --------------------- Finding -------------------------- */
+
+/* Find the F-Curve affecting the given RNA-access path + index, in the list of F-Curves provided */
+FCurve *list_find_fcurve (ListBase *list, const char rna_path[], const int array_index)
+{
+ FCurve *fcu;
+
+ /* sanity checks */
+ if ( ELEM(NULL, list, rna_path) || (array_index < 0) )
+ return NULL;
+
+ /* check paths of curves, then array indices... */
+ for (fcu= list->first; fcu; fcu= fcu->next) {
+ /* simple string-compare (this assumes that they have the same root...) */
+ if (strcmp(fcu->rna_path, rna_path) == 0) {
+ /* now check indicies */
+ if (fcu->array_index == array_index)
+ return fcu;
+ }
+ }
+
+ /* return */
+ return NULL;
+}
+
+/* ***************************** Keyframe Column Tools ********************************* */
+
+/* add a BezTriple to a column */
+void bezt_add_to_cfra_elem (ListBase *lb, BezTriple *bezt)
+{
+ CfraElem *ce, *cen;
+
+ for (ce= lb->first; ce; ce= ce->next) {
+ /* double key? */
+ if (ce->cfra == bezt->vec[1][0]) {
+ if (bezt->f2 & SELECT) ce->sel= bezt->f2;
+ return;
+ }
+ /* should key be inserted before this column? */
+ else if (ce->cfra > bezt->vec[1][0]) break;
+ }
+
+ /* create a new column */
+ cen= MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem");
+ if (ce) BLI_insertlinkbefore(lb, ce, cen);
+ else BLI_addtail(lb, cen);
+
+ cen->cfra= bezt->vec[1][0];
+ cen->sel= bezt->f2;
+}
+
+/* ***************************** F-Curve Sanity ********************************* */
+/* The functions here are used in various parts of Blender, usually after some editing
+ * of keyframe data has occurred. They ensure that keyframe data is properly ordered and
+ * that the handles are correctly
+ */
+
+/* This function recalculates the handles of an F-Curve
+ * If the BezTriples have been rearranged, sort them first before using this.
+ */
+void calchandles_fcurve (FCurve *fcu)
+{
+ BezTriple *bezt, *prev, *next;
+ int a= fcu->totvert;
+
+ /* Error checking:
+ * - need at least two points
+ * - need bezier keys
+ * - only bezier-interpolation has handles (for now)
+ */
+ if (ELEM(NULL, fcu, fcu->bezt) || (a < 2) /*|| ELEM(fcu->ipo, BEZT_IPO_CONST, BEZT_IPO_LIN)*/)
+ return;
+
+ /* get initial pointers */
+ bezt= fcu->bezt;
+ prev= NULL;
+ next= (bezt + 1);
+
+ /* loop over all beztriples, adjusting handles */
+ while (a--) {
+ /* clamp timing of handles to be on either side of beztriple */
+ if (bezt->vec[0][0] > bezt->vec[1][0]) bezt->vec[0][0]= bezt->vec[1][0];
+ if (bezt->vec[2][0] < bezt->vec[1][0]) bezt->vec[2][0]= bezt->vec[1][0];
+
+ /* calculate auto-handles */
+ if (fcu->flag & FCURVE_AUTO_HANDLES)
+ calchandleNurb(bezt, prev, next, 2); /* 2==special autohandle && keep extrema horizontal */
+ else
+ calchandleNurb(bezt, prev, next, 1); /* 1==special autohandle */
+
+ /* for automatic ease in and out */
+ if ((bezt->h1==HD_AUTO) && (bezt->h2==HD_AUTO)) {
+ /* only do this on first or last beztriple */
+ if ((a == 0) || (a == fcu->totvert-1)) {
+ /* set both handles to have same horizontal value as keyframe */
+ if (fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT) {
+ bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
+ }
+ }
+ }
+
+ /* advance pointers for next iteration */
+ prev= bezt;
+ if (a == 1) next= NULL;
+ else next++;
+ bezt++;
+ }
+}
+
+/* Use when F-Curve with handles has changed
+ * It treats all BezTriples with the following rules:
+ * - PHASE 1: do types have to be altered?
+ * -> Auto handles: become aligned when selection status is NOT(000 || 111)
+ * -> Vector handles: become 'nothing' when (one half selected AND other not)
+ * - PHASE 2: recalculate handles
+*/
+void testhandles_fcurve (FCurve *fcu)
+{
+ BezTriple *bezt;
+ int a;
+
+ /* only beztriples have handles (bpoints don't though) */
+ if ELEM(NULL, fcu, fcu->bezt)
+ return;
+
+ /* loop over beztriples */
+ for (a=0, bezt=fcu->bezt; a < fcu->totvert; a++, bezt++) {
+ short flag= 0;
+
+ /* flag is initialised as selection status
+ * of beztriple control-points (labelled 0,1,2)
+ */
+ if (bezt->f1 & SELECT) flag |= (1<<0); // == 1
+ if (bezt->f2 & SELECT) flag |= (1<<1); // == 2
+ if (bezt->f3 & SELECT) flag |= (1<<2); // == 4
+
+ /* one or two handles selected only */
+ if (ELEM(flag, 0, 7)==0) {
+ /* auto handles become aligned */
+ if (bezt->h1==HD_AUTO)
+ bezt->h1= HD_ALIGN;
+ if (bezt->h2==HD_AUTO)
+ bezt->h2= HD_ALIGN;
+
+ /* vector handles become 'free' when only one half selected */
+ if (bezt->h1==HD_VECT) {
+ /* only left half (1 or 2 or 1+2) */
+ if (flag < 4)
+ bezt->h1= 0;
+ }
+ if (bezt->h2==HD_VECT) {
+ /* only right half (4 or 2+4) */
+ if (flag > 3)
+ bezt->h2= 0;
+ }
+ }
+ }
+
+ /* recalculate handles */
+ calchandles_fcurve(fcu);
+}
+
+/* This function sorts BezTriples so that they are arranged in chronological order,
+ * as tools working on F-Curves expect that the BezTriples are in order.
+ */
+void sort_time_fcurve (FCurve *fcu)
+{
+ short ok= 1;
+
+ /* keep adjusting order of beztriples until nothing moves (bubble-sort) */
+ while (ok) {
+ ok= 0;
+
+ /* currently, will only be needed when there are beztriples */
+ if (fcu->bezt) {
+ BezTriple *bezt;
+ int a;
+
+ /* loop over ALL points to adjust position in array and recalculate handles */
+ for (a=0, bezt=fcu->bezt; a < fcu->totvert; a++, bezt++) {
+ /* check if thee's a next beztriple which we could try to swap with current */
+ if (a < (fcu->totvert-1)) {
+ /* swap if one is after the other (and indicate that order has changed) */
+ if (bezt->vec[1][0] > (bezt+1)->vec[1][0]) {
+ SWAP(BezTriple, *bezt, *(bezt+1));
+ ok= 1;
+ }
+
+ /* if either one of both of the points exceeds crosses over the keyframe time... */
+ if ( (bezt->vec[0][0] > bezt->vec[1][0]) && (bezt->vec[2][0] < bezt->vec[1][0]) ) {
+ /* swap handles if they have switched sides for some reason */
+ SWAP(float, bezt->vec[0][0], bezt->vec[2][0]);
+ SWAP(float, bezt->vec[0][1], bezt->vec[2][1]);
+ }
+ else {
+ /* clamp handles */
+ if (bezt->vec[0][0] > bezt->vec[1][0])
+ bezt->vec[0][0]= bezt->vec[1][0];
+ if (bezt->vec[2][0] < bezt->vec[1][0])
+ bezt->vec[2][0]= bezt->vec[1][0];
+ }
+ }
+ }
+ }
+ }
+}
+
+/* This function tests if any BezTriples are out of order, thus requiring a sort */
+short test_time_fcurve (FCurve *fcu)
+{
+ int a;
+
+ /* sanity checks */
+ if (fcu == NULL)
+ return 0;
+
+ /* currently, only need to test beztriples */
+ if (fcu->bezt) {
+ BezTriple *bezt;
+
+ /* loop through all BezTriples, stopping when one exceeds the one after it */
+ for (a=0, bezt= fcu->bezt; a < (fcu->totvert - 1); a++, bezt++) {
+ if (bezt->vec[1][0] > (bezt+1)->vec[1][0])
+ return 1;
+ }
+ }
+ else if (fcu->fpt) {
+ FPoint *fpt;
+
+ /* loop through all FPoints, stopping when one exceeds the one after it */
+ for (a=0, fpt= fcu->fpt; a < (fcu->totvert - 1); a++, fpt++) {
+ if (fpt->vec[0] > (fpt+1)->vec[0])
+ return 1;
+ }
+ }
+
+ /* none need any swapping */
+ return 0;
+}
+
+/* ***************************** Drivers ********************************* */
+
+/* Driver API --------------------------------- */
+
+/* This frees the driver itself */
+void fcurve_free_driver(FCurve *fcu)
+{
+ ChannelDriver *driver;
+
+ /* sanity checks */
+ if ELEM(NULL, fcu, fcu->driver)
+ return;
+ driver= fcu->driver;
+
+ /* free RNA-paths, as these were allocated when getting the path string */
+ if (driver->rna_path) MEM_freeN(driver->rna_path);
+ if (driver->rna_path2) MEM_freeN(driver->rna_path2);
+
+ /* free driver itself, then set F-Curve's point to this to NULL (as the curve may still be used) */
+ MEM_freeN(driver);
+ fcu->driver= NULL;
+}
+
+/* Driver Evaluation -------------------------- */
+
+/* Helper function to obtain a value using RNA from the specified source (for evaluating drivers)
+ * - target: used to specify which of the two driver-targets to use
+ */
+static float driver_get_driver_value (ChannelDriver *driver, short target)
+{
+ PointerRNA id_ptr, ptr;
+ PropertyRNA *prop;
+ char *path;
+ int index;
+ float value= 0.0f;
+
+ /* get RNA-pointer for the ID-block given in driver */
+ if (target == 2) {
+ /* second target */
+ RNA_id_pointer_create(driver->id2, &id_ptr);
+ path= driver->rna_path2;
+ index= driver->array_index2;
+ }
+ else {
+ /* first/main target */
+ RNA_id_pointer_create(driver->id, &id_ptr);
+ path= driver->rna_path;
+ index= driver->array_index;
+ }
+
+ /* get property to read from, and get value as appropriate */
+ if (RNA_path_resolve(&id_ptr, path, &ptr, &prop)) {
+ switch (RNA_property_type(&ptr, prop)) {
+ case PROP_BOOLEAN:
+ if (RNA_property_array_length(&ptr, prop))
+ value= (float)RNA_property_boolean_get_array(&ptr, prop, index);
+ else
+ value= (float)RNA_property_boolean_get(&ptr, prop);
+ break;
+ case PROP_INT:
+ if (RNA_property_array_length(&ptr, prop))
+ value= (float)RNA_property_int_get_array(&ptr, prop, index);
+ else
+ value= (float)RNA_property_int_get(&ptr, prop);
+ break;
+ case PROP_FLOAT:
+ if (RNA_property_array_length(&ptr, prop))
+ value= RNA_property_float_get_array(&ptr, prop, index);
+ else
+ value= RNA_property_float_get(&ptr, prop);
+ break;
+ case PROP_ENUM:
+ value= (float)RNA_property_enum_get(&ptr, prop);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return value;
+}
+
+/* Evaluate an Channel-Driver to get a 'time' value to use instead of "evaltime"
+ * - "evaltime" is the frame at which F-Curve is being evaluated
+ * - has to return a float value
+ */
+static float evaluate_driver (ChannelDriver *driver, float evaltime)
+{
+ /* check if driver can be evaluated */
+ if (driver->flag & DRIVER_FLAG_DISABLED)
+ return 0.0f;
+
+ switch (driver->type) {
+ case DRIVER_TYPE_CHANNEL: /* channel/setting drivers channel/setting */
+ return driver_get_driver_value(driver, 0);
+
+#ifndef DISABLE_PYTHON
+ case DRIVER_TYPE_PYTHON: /* expression */
+ {
+ /* check for empty or invalid expression */
+ if ( (driver->expression[0] == '\0') ||
+ (driver->flag & DRIVER_FLAG_INVALID) )
+ {
+ return 0.0f;
+ }
+
+ /* this evaluates the expression using Python,and returns its result:
+ * - on errors it reports, then returns 0.0f
+ */
+ //return BPY_pydriver_eval(driver); // XXX old func
+ return 1.0f;
+ }
+#endif /* DISABLE_PYTHON*/
+
+ case DRIVER_TYPE_ROTDIFF: /* difference of rotations of 2 bones (should be in same armature) */
+ {
+ /*
+ float q1[4], q2[4], quat[4], angle;
+
+ Mat4ToQuat(pchan->pose_mat, q1);
+ Mat4ToQuat(pchan2->pose_mat, q2);
+
+ QuatInv(q1);
+ QuatMul(quat, q1, q2);
+ angle = 2.0f * (saacos(quat[0]));
+ angle= ABS(angle);
+
+ return (angle > M_PI) ? (float)((2.0f * M_PI) - angle) : (float)(angle);
+ */
+ }
+ break;
+
+ default:
+ {
+ /* special 'hack' - just use stored value
+ * This is currently used as the mechanism which allows animated settings to be able
+ * to be changed via the UI.
+ */
+ return driver->curval;
+ }
+ }
+
+ /* return 0.0f, as couldn't find relevant data to use */
+ return 0.0f;
+}
+
+/* ***************************** Curve Calculations ********************************* */
+
+/* The total length of the handles is not allowed to be more
+ * than the horizontal distance between (v1-v4).
+ * This is to prevent curve loops.
+*/
+void correct_bezpart (float *v1, float *v2, float *v3, float *v4)
+{
+ float h1[2], h2[2], len1, len2, len, fac;
+
+ /* calculate handle deltas */
+ h1[0]= v1[0] - v2[0];
+ h1[1]= v1[1] - v2[1];
+
+ h2[0]= v4[0] - v3[0];
+ h2[1]= v4[1] - v3[1];
+
+ /* calculate distances:
+ * - len = span of time between keyframes
+ * - len1 = length of handle of start key
+ * - len2 = length of handle of end key
+ */
+ len= v4[0]- v1[0];
+ len1= (float)fabs(h1[0]);
+ len2= (float)fabs(h2[0]);
+
+ /* if the handles have no length, no need to do any corrections */
+ if ((len1+len2) == 0.0f)
+ return;
+
+ /* the two handles cross over each other, so force them
+ * apart using the proportion they overlap
+ */
+ if ((len1+len2) > len) {
+ fac= len / (len1+len2);
+
+ v2[0]= (v1[0] - fac*h1[0]);
+ v2[1]= (v1[1] - fac*h1[1]);
+
+ v3[0]= (v4[0] - fac*h2[0]);
+ v3[1]= (v4[1] - fac*h2[1]);
+ }
+}
+
+/* find root ('zero') */
+int findzero (float x, float q0, float q1, float q2, float q3, float *o)
+{
+ double c0, c1, c2, c3, a, b, c, p, q, d, t, phi;
+ int nr= 0;
+
+ c0= q0 - x;
+ c1= 3.0 * (q1 - q0);
+ c2= 3.0 * (q0 - 2.0*q1 + q2);
+ c3= q3 - q0 + 3.0 * (q1 - q2);
+
+ if (c3 != 0.0) {
+ a= c2/c3;
+ b= c1/c3;
+ c= c0/c3;
+ a= a/3;
+
+ p= b/3 - a*a;
+ q= (2*a*a*a - a*b + c) / 2;
+ d= q*q + p*p*p;
+
+ if (d > 0.0) {
+ t= sqrt(d);
+ o[0]= (float)(Sqrt3d(-q+t) + Sqrt3d(-q-t) - a);
+
+ if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1;
+ else return 0;
+ }
+ else if (d == 0.0) {
+ t= Sqrt3d(-q);
+ o[0]= (float)(2*t - a);
+
+ if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++;
+ o[nr]= (float)(-t-a);
+
+ if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1;
+ else return nr;
+ }
+ else {
+ phi= acos(-q / sqrt(-(p*p*p)));
+ t= sqrt(-p);
+ p= cos(phi/3);
+ q= sqrt(3 - 3*p*p);
+ o[0]= (float)(2*t*p - a);
+
+ if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++;
+ o[nr]= (float)(-t * (p + q) - a);
+
+ if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) nr++;
+ o[nr]= (float)(-t * (p - q) - a);
+
+ if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1;
+ else return nr;
+ }
+ }
+ else {
+ a=c2;
+ b=c1;
+ c=c0;
+
+ if (a != 0.0) {
+ // discriminant
+ p= b*b - 4*a*c;
+
+ if (p > 0) {
+ p= sqrt(p);
+ o[0]= (float)((-b-p) / (2 * a));
+
+ if ((o[0] >= SMALL) && (o[0] <= 1.000001)) nr++;
+ o[nr]= (float)((-b+p)/(2*a));
+
+ if ((o[nr] >= SMALL) && (o[nr] <= 1.000001)) return nr+1;
+ else return nr;
+ }
+ else if (p == 0) {
+ o[0]= (float)(-b / (2 * a));
+ if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1;
+ else return 0;
+ }
+ }
+ else if (b != 0.0) {
+ o[0]= (float)(-c/b);
+
+ if ((o[0] >= SMALL) && (o[0] <= 1.000001)) return 1;
+ else return 0;
+ }
+ else if (c == 0.0) {
+ o[0]= 0.0;
+ return 1;
+ }
+
+ return 0;
+ }
+}
+
+void berekeny (float f1, float f2, float f3, float f4, float *o, int b)
+{
+ float t, c0, c1, c2, c3;
+ int a;
+
+ c0= f1;
+ c1= 3.0f * (f2 - f1);
+ c2= 3.0f * (f1 - 2.0f*f2 + f3);
+ c3= f4 - f1 + 3.0f * (f2 - f3);
+
+ for (a=0; a < b; a++) {
+ t= o[a];
+ o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3;
+ }
+}
+
+void berekenx (float *f, float *o, int b)
+{
+ float t, c0, c1, c2, c3;
+ int a;
+
+ c0= f[0];
+ c1= 3.0f * (f[3] - f[0]);
+ c2= 3.0f * (f[0] - 2.0f*f[3] + f[6]);
+ c3= f[9] - f[0] + 3.0f * (f[3] - f[6]);
+
+ for (a=0; a < b; a++) {
+ t= o[a];
+ o[a]= c0 + t*c1 + t*t*c2 + t*t*t*c3;
+ }
+}
+
+
+/* -------------------------- */
+
+/* Calculate F-Curve value for 'evaltime' using BezTriple keyframes */
+static float fcurve_eval_keyframes (FCurve *fcu, BezTriple *bezts, float evaltime)
+{
+ BezTriple *bezt, *prevbezt, *lastbezt;
+ float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac;
+ int a, b;
+ float cvalue = 0.0f;
+
+ /* get pointers */
+ a= fcu->totvert-1;
+ prevbezt= bezts;
+ bezt= prevbezt+1;
+ lastbezt= prevbezt + a;
+
+ /* evaluation time at or past endpoints? */
+ if (prevbezt->vec[1][0] >= evaltime) {
+ /* before or on first keyframe */
+ if ((fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (prevbezt->ipo != BEZT_IPO_CONST)) {
+ /* linear or bezier interpolation */
+ if (prevbezt->ipo==BEZT_IPO_LIN) {
+ /* Use the next center point instead of our own handle for
+ * linear interpolated extrapolate
+ */
+ if (fcu->totvert == 1)
+ cvalue= prevbezt->vec[1][1];
+ else {
+ bezt = prevbezt+1;
+ dx= prevbezt->vec[1][0] - evaltime;
+ fac= bezt->vec[1][0] - prevbezt->vec[1][0];
+
+ /* prevent division by zero */
+ if (fac) {
+ fac= (bezt->vec[1][1] - prevbezt->vec[1][1]) / fac;
+ cvalue= prevbezt->vec[1][1] - (fac * dx);
+ }
+ else
+ cvalue= prevbezt->vec[1][1];
+ }
+ }
+ else {
+ /* Use the first handle (earlier) of first BezTriple to calculate the
+ * gradient and thus the value of the curve at evaltime
+ */
+ dx= prevbezt->vec[1][0] - evaltime;
+ fac= prevbezt->vec[1][0] - prevbezt->vec[0][0];
+
+ /* prevent division by zero */
+ if (fac) {
+ fac= (prevbezt->vec[1][1] - prevbezt->vec[0][1]) / fac;
+ cvalue= prevbezt->vec[1][1] - (fac * dx);
+ }
+ else
+ cvalue= prevbezt->vec[1][1];
+ }
+ }
+ else {
+ /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation,
+ * so just extend first keyframe's value
+ */
+ cvalue= prevbezt->vec[1][1];
+ }
+ }
+ else if (lastbezt->vec[1][0] <= evaltime) {
+ /* after or on last keyframe */
+ if ((fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (lastbezt->ipo != BEZT_IPO_CONST)) {
+ /* linear or bezier interpolation */
+ if (lastbezt->ipo==BEZT_IPO_LIN) {
+ /* Use the next center point instead of our own handle for
+ * linear interpolated extrapolate
+ */
+ if (fcu->totvert == 1)
+ cvalue= lastbezt->vec[1][1];
+ else {
+ prevbezt = lastbezt - 1;
+ dx= evaltime - lastbezt->vec[1][0];
+ fac= lastbezt->vec[1][0] - prevbezt->vec[1][0];
+
+ /* prevent division by zero */
+ if (fac) {
+ fac= (lastbezt->vec[1][1] - prevbezt->vec[1][1]) / fac;
+ cvalue= lastbezt->vec[1][1] + (fac * dx);
+ }
+ else
+ cvalue= lastbezt->vec[1][1];
+ }
+ }
+ else {
+ /* Use the gradient of the second handle (later) of last BezTriple to calculate the
+ * gradient and thus the value of the curve at evaltime
+ */
+ dx= evaltime - lastbezt->vec[1][0];
+ fac= lastbezt->vec[2][0] - lastbezt->vec[1][0];
+
+ /* prevent division by zero */
+ if (fac) {
+ fac= (lastbezt->vec[2][1] - lastbezt->vec[1][1]) / fac;
+ cvalue= lastbezt->vec[1][1] + (fac * dx);
+ }
+ else
+ cvalue= lastbezt->vec[1][1];
+ }
+ }
+ else {
+ /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation,
+ * so just extend last keyframe's value
+ */
+ cvalue= lastbezt->vec[1][1];
+ }
+ }
+ else {
+ /* evaltime occurs somewhere in the middle of the curve */
+ for (a=0; prevbezt && bezt && (a < fcu->totvert-1); a++, prevbezt=bezt, bezt++) {
+ /* evaltime occurs within the interval defined by these two keyframes */
+ if ((prevbezt->vec[1][0] <= evaltime) && (bezt->vec[1][0] >= evaltime)) {
+ /* value depends on interpolation mode */
+ if (prevbezt->ipo == BEZT_IPO_CONST) {
+ /* constant (evaltime not relevant, so no interpolation needed) */
+ cvalue= prevbezt->vec[1][1];
+ }
+ else if (prevbezt->ipo == BEZT_IPO_LIN) {
+ /* linear - interpolate between values of the two keyframes */
+ fac= bezt->vec[1][0] - prevbezt->vec[1][0];
+
+ /* prevent division by zero */
+ if (fac) {
+ fac= (evaltime - prevbezt->vec[1][0]) / fac;
+ cvalue= prevbezt->vec[1][1] + (fac * (bezt->vec[1][1] - prevbezt->vec[1][1]));
+ }
+ else
+ cvalue= prevbezt->vec[1][1];
+ }
+ else {
+ /* bezier interpolation */
+ /* v1,v2 are the first keyframe and its 2nd handle */
+ v1[0]= prevbezt->vec[1][0];
+ v1[1]= prevbezt->vec[1][1];
+ v2[0]= prevbezt->vec[2][0];
+ v2[1]= prevbezt->vec[2][1];
+ /* v3,v4 are the last keyframe's 1st handle + the last keyframe */
+ v3[0]= bezt->vec[0][0];
+ v3[1]= bezt->vec[0][1];
+ v4[0]= bezt->vec[1][0];
+ v4[1]= bezt->vec[1][1];
+
+ /* adjust handles so that they don't overlap (forming a loop) */
+ correct_bezpart(v1, v2, v3, v4);
+
+ /* try to get a value for this position - if failure, try another set of points */
+ b= findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl);
+ if (b) {
+ berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1);
+ cvalue= opl[0];
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /* return value */
+ return cvalue;
+}
+
+/* Calculate F-Curve value for 'evaltime' using FPoint samples */
+static float fcurve_eval_samples (FCurve *fcu, FPoint *fpts, float evaltime)
+{
+ FPoint *prevfpt, *lastfpt, *fpt;
+ float cvalue= 0.0f;
+
+ /* get pointers */
+ prevfpt= fpts;
+ lastfpt= prevfpt + fcu->totvert-1;
+
+ /* evaluation time at or past endpoints? */
+ if (prevfpt->vec[0] >= evaltime) {
+ /* before or on first sample, so just extend value */
+ cvalue= prevfpt->vec[1];
+ }
+ else if (lastfpt->vec[0] <= evaltime) {
+ /* after or on last sample, so just extend value */
+ cvalue= lastfpt->vec[1];
+ }
+ else {
+ /* find the one on the right frame (assume that these are spaced on 1-frame intervals) */
+ fpt= prevfpt + (int)(evaltime - prevfpt->vec[0]);
+ cvalue= fpt->vec[1];
+ }
+
+ /* return value */
+ return cvalue;
+}
+
+/* ******************************** F-Curve Modifiers ********************************* */
+
+/* Template --------------------------- */
+
+/* Each modifier defines a set of functions, which will be called at the appropriate
+ * times. In addition to this, each modifier should have a type-info struct, where
+ * its functions are attached for use.
+ */
+
+/* Template for type-info data:
+ * - make a copy of this when creating new modifiers, and just change the functions
+ * pointed to as necessary
+ * - although the naming of functions doesn't matter, it would help for code
+ * readability, to follow the same naming convention as is presented here
+ * - any functions that a constraint doesn't need to define, don't define
+ * for such cases, just use NULL
+ * - these should be defined after all the functions have been defined, so that
+ * forward-definitions/prototypes don't need to be used!
+ * - keep this copy #if-def'd so that future constraints can get based off this
+ */
+#if 0
+static FModifierTypeInfo FMI_MODNAME = {
+ FMODIFIER_TYPE_MODNAME, /* type */
+ sizeof(FMod_ModName), /* size */
+ "Modifier Name", /* name */
+ "FMod_ModName", /* struct name */
+ fcm_modname_free, /* free data */
+ fcm_modname_relink, /* relink data */
+ fcm_modname_copy, /* copy data */
+ fcm_modname_new_data, /* new data */
+ fcm_modname_evaluate /* evaluate */
+};
+#endif
+
+/* Generator F-Curve Modifier --------------------------- */
+
+static void fcm_generator_free (FModifier *fcm)
+{
+ FMod_Generator *data= (FMod_Generator *)fcm->data;
+
+ /* free polynomial coefficients array */
+ if (data->poly_coefficients)
+ MEM_freeN(data->poly_coefficients);
+}
+
+static void fcm_generator_copy (FModifier *fcm, FModifier *src)
+{
+ FMod_Generator *gen= (FMod_Generator *)fcm->data;
+ FMod_Generator *ogen= (FMod_Generator *)src->data;
+
+ /* copy polynomial coefficients array? */
+ if (ogen->poly_coefficients)
+ gen->poly_coefficients= MEM_dupallocN(ogen->poly_coefficients);
+}
+
+static void fcm_generator_new_data (void *mdata)
+{
+ FMod_Generator *data= (FMod_Generator *)mdata;
+ float *cp;
+
+ /* set default generator to be linear 0-1 (gradient = 1, y-offset = 0) */
+ data->poly_order= 1;
+ cp= data->poly_coefficients= MEM_callocN(sizeof(float)*2, "FMod_Generator_Coefs");
+ cp[0] = 0; // y-offset
+ cp[1] = 1; // gradient
+}
+
+
+static void fcm_generator_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+{
+ FMod_Generator *data= (FMod_Generator *)fcm->data;
+
+ /* behaviour depends on mode (NOTE: we don't need to do anything...) */
+ switch (data->mode) {
+ case FCM_GENERATOR_POLYNOMIAL: /* polynomial expression */
+ {
+ /* we overwrite cvalue with the sum of the polynomial */
+ float value= 0.0f, *cp = NULL;
+ unsigned int i;
+
+ /* for each coefficient, add to value, which we'll write to *cvalue in one go */
+ // TODO: could this be more efficient (i.e. without need to recalc pow() everytime)
+ cp= data->poly_coefficients;
+ for (i=0; (i <= data->poly_order) && (cp); i++, cp++)
+ value += (*cp) * pow(evaltime, i);
+
+ /* only if something changed */
+ if (data->poly_order)
+ *cvalue= value;
+ }
+ break;
+
+#ifndef DISABLE_PYTHON
+ case FCM_GENERATOR_EXPRESSION: /* py-expression */
+ // TODO...
+ break;
+#endif /* DISABLE_PYTHON */
+ }
+}
+
+static FModifierTypeInfo FMI_GENERATOR = {
+ FMODIFIER_TYPE_GENERATOR, /* type */
+ sizeof(FMod_Generator), /* size */
+ "Generator", /* name */
+ "FMod_Generator", /* struct name */
+ fcm_generator_free, /* free data */
+ fcm_generator_copy, /* copy data */
+ fcm_generator_new_data, /* new data */
+ fcm_generator_evaluate /* evaluate */
+};
+
+/* Envelope F-Curve Modifier --------------------------- */
+
+static void fcm_envelope_free (FModifier *fcm)
+{
+ FMod_Envelope *data= (FMod_Envelope *)fcm->data;
+
+ /* free envelope data array */
+ if (data->data)
+ MEM_freeN(data->data);
+}
+
+static void fcm_envelope_copy (FModifier *fcm, FModifier *src)
+{
+ FMod_Envelope *gen= (FMod_Envelope *)fcm->data;
+ FMod_Envelope *ogen= (FMod_Envelope *)src->data;
+
+ /* copy envelope data array */
+ if (ogen->data)
+ gen->data= MEM_dupallocN(ogen->data);
+}
+
+static void fcm_envelope_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+{
+ FMod_Envelope *env= (FMod_Envelope *)fcm->data;
+ FCM_EnvelopeData *fed, *prevfed, *lastfed;
+ float min=0.0f, max=0.0f, fac=0.0f;
+ int a;
+
+ /* get pointers */
+ if (env->data == NULL) return;
+ prevfed= env->data;
+ fed= prevfed + 1;
+ lastfed= prevfed + env->totvert-1;
+
+ /* get min/max values for envelope at evaluation time (relative to mid-value) */
+ if (prevfed->time >= evaltime) {
+ /* before or on first sample, so just extend value */
+ min= prevfed->min;
+ max= prevfed->max;
+ }
+ else if (lastfed->time <= evaltime) {
+ /* after or on last sample, so just extend value */
+ min= lastfed->min;
+ max= lastfed->max;
+ }
+ else {
+ /* evaltime occurs somewhere between segments */
+ for (a=0; prevfed && fed && (a < env->totvert-1); a++, prevfed=fed, fed++) {
+ /* evaltime occurs within the interval defined by these two envelope points */
+ if ((prevfed->time <= evaltime) && (fed->time >= evaltime)) {
+ float afac, bfac, diff;
+
+ diff= fed->time - prevfed->time;
+ afac= (evaltime - prevfed->time) / diff;
+ bfac= (fed->time - evaltime)/(diff);
+
+ min= afac*prevfed->min + bfac*fed->min;
+ max= afac*prevfed->max + bfac*fed->max;
+
+ break;
+ }
+ }
+ }
+
+ /* adjust *cvalue
+ * NOTE: env->min/max are relative to env->midval, and can be either +ve OR -ve, so we add...
+ */
+ fac= (*cvalue - min) / (max - min);
+ *cvalue= (env->midval + env->min) + (fac * (env->max - env->min));
+}
+
+static FModifierTypeInfo FMI_ENVELOPE = {
+ FMODIFIER_TYPE_ENVELOPE, /* type */
+ sizeof(FMod_Envelope), /* size */
+ "Envelope", /* name */
+ "FMod_Envelope", /* struct name */
+ fcm_envelope_free, /* free data */
+ fcm_envelope_copy, /* copy data */
+ NULL, /* new data */
+ fcm_envelope_evaluate /* evaluate */
+};
+
+/* Cycles F-Curve Modifier --------------------------- */
+
+/* This modifier changes evaltime to something that exists within the curve's frame-range,
+ * then re-evaluates modifier stack up to this point using the new time. This re-entrant behaviour
+ * is very likely to be more time-consuming than the original approach... (which was tighly integrated into
+ * the calculation code...).
+ *
+ * NOTE: this needs to be at the start of the stack to be of use, as it needs to know the extents of the keyframes/sample-data
+ * Possible TODO - store length of cycle information that can be initialised from the extents of the keyframes/sample-data, and adjusted
+ * as appropriate
+ */
+
+static void fcm_cycles_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+{
+ FMod_Cycles *data= (FMod_Cycles *)fcm->data;
+ ListBase mods = {NULL, NULL};
+ float prevkey[2], lastkey[2], cycyofs=0.0f;
+ float new_value;
+ short side=0, mode=0;
+ int cycles=0;
+
+ /* check if modifier is first in stack, otherwise disable ourself... */
+ // FIXME...
+ if (fcm->prev) {
+ fcm->flag |= FMODIFIER_FLAG_DISABLED;
+ return;
+ }
+
+ /* calculate new evaltime due to cyclic interpolation */
+ if (fcu && fcu->bezt) {
+ BezTriple *prevbezt= fcu->bezt;
+ BezTriple *lastbezt= prevbezt + fcu->totvert-1;
+
+ prevkey[0]= prevbezt->vec[1][0];
+ prevkey[1]= prevbezt->vec[1][1];
+
+ lastkey[0]= lastbezt->vec[1][0];
+ lastkey[1]= lastbezt->vec[1][1];
+ }
+ else if (fcu && fcu->fpt) {
+ FPoint *prevfpt= fcu->fpt;
+ FPoint *lastfpt= prevfpt + fcu->totvert-1;
+
+ prevkey[0]= prevfpt->vec[0];
+ prevkey[1]= prevfpt->vec[1];
+
+ lastkey[0]= lastfpt->vec[0];
+ lastkey[1]= lastfpt->vec[1];
+ }
+ else
+ return;
+
+ /* check if modifier will do anything
+ * 1) if in data range, definitely don't do anything
+ * 2) if before first frame or after last frame, make sure some cycling is in use
+ */
+ if (evaltime < prevkey[0]) {
+ if (data->before_mode) {
+ side= -1;
+ mode= data->before_mode;
+ cycles= data->before_cycles;
+ }
+ }
+ else if (evaltime > lastkey[0]) {
+ if (data->after_mode) {
+ side= 1;
+ mode= data->after_mode;
+ cycles= data->after_cycles;
+ }
+ }
+ if ELEM3(0, side, mode, cycles)
+ return;
+
+ /* extrapolation mode is 'cyclic' - find relative place within a cycle */
+ // FIXME: adding the more fine-grained control of extrpolation mode
+ {
+ float cycdx=0, cycdy=0, ofs=0;
+
+ /* ofs is start frame of cycle */
+ ofs= prevkey[0];
+
+ /* calculate period and amplitude (total height) of a cycle */
+ cycdx= lastkey[0] - prevkey[0];
+ cycdy= lastkey[1] - prevkey[1];
+
+ /* check if cycle is infinitely small, to be point of being impossible to use */
+ if (cycdx == 0)
+ return;
+ /* check that cyclic is still enabled for the specified time */
+ if ( ((float)side * (evaltime - ofs) / cycdx) > cycles )
+ return;
+
+
+ /* check if 'cyclic extrapolation', and thus calculate y-offset for this cycle */
+ if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
+ cycyofs = (float)floor((evaltime - ofs) / cycdx);
+ cycyofs *= cycdy;
+ }
+
+ /* calculate where in the cycle we are (overwrite evaltime to reflect this) */
+ evaltime= (float)(fmod(evaltime-ofs, cycdx) + ofs);
+ if (evaltime < ofs) evaltime += cycdx;
+ }
+
+
+ /* store modifiers after (and including ourself) before recalculating curve with new evaltime */
+ mods= fcu->modifiers;
+ fcu->modifiers.first= fcu->modifiers.last= NULL;
+
+ /* re-enter the evaluation loop (but without the burden of evaluating any modifiers, so 'should' be relatively quick) */
+ new_value= evaluate_fcurve(fcu, evaltime);
+
+ /* restore modifiers, and set new value (don't assume everything is still ok after being re-entrant) */
+ fcu->modifiers= mods;
+ *cvalue= new_value + cycyofs;
+}
+
+static FModifierTypeInfo FMI_CYCLES = {
+ FMODIFIER_TYPE_CYCLES, /* type */
+ sizeof(FMod_Cycles), /* size */
+ "Cycles", /* name */
+ "FMod_Cycles", /* struct name */
+ NULL, /* free data */
+ NULL, /* copy data */
+ NULL, /* new data */
+ fcm_cycles_evaluate /* evaluate */
+};
+
+/* Noise F-Curve Modifier --------------------------- */
+
+#if 0 // XXX not yet implemented
+static FModifierTypeInfo FMI_NOISE = {
+ FMODIFIER_TYPE_NOISE, /* type */
+ sizeof(FMod_Noise), /* size */
+ "Noise", /* name */
+ "FMod_Noise", /* struct name */
+ NULL, /* free data */
+ NULL, /* copy data */
+ fcm_noise_new_data, /* new data */
+ fcm_noise_evaluate /* evaluate */
+};
+#endif // XXX not yet implemented
+
+/* Filter F-Curve Modifier --------------------------- */
+
+#if 0 // XXX not yet implemented
+static FModifierTypeInfo FMI_FILTER = {
+ FMODIFIER_TYPE_FILTER, /* type */
+ sizeof(FMod_Filter), /* size */
+ "Filter", /* name */
+ "FMod_Filter", /* struct name */
+ NULL, /* free data */
+ NULL, /* copy data */
+ NULL, /* new data */
+ fcm_filter_evaluate /* evaluate */
+};
+#endif // XXX not yet implemented
+
+
+/* Python F-Curve Modifier --------------------------- */
+
+static void fcm_python_free (FModifier *fcm)
+{
+ FMod_Python *data= (FMod_Python *)fcm->data;
+
+ /* id-properties */
+ IDP_FreeProperty(data->prop);
+ MEM_freeN(data->prop);
+}
+
+static void fcm_python_new_data (void *mdata)
+{
+ FMod_Python *data= (FMod_Python *)mdata;
+
+ /* everything should be set correctly by calloc, except for the prop->type constant.*/
+ data->prop = MEM_callocN(sizeof(IDProperty), "PyFModifierProps");
+ data->prop->type = IDP_GROUP;
+}
+
+static void fcm_python_copy (FModifier *fcm, FModifier *src)
+{
+ FMod_Python *pymod = (FMod_Python *)fcm->data;
+ FMod_Python *opymod = (FMod_Python *)src->data;
+
+ pymod->prop = IDP_CopyProperty(opymod->prop);
+}
+
+static void fcm_python_evaluate (FCurve *fcu, FModifier *fcm, float *cvalue, float evaltime)
+{
+#ifndef DISABLE_PYTHON
+ //FMod_Python *data= (FMod_Python *)fcm->data;
+
+ /* FIXME... need to implement this modifier...
+ * It will need it execute a script using the custom properties
+ */
+#endif /* DISABLE_PYTHON */
+}
+
+static FModifierTypeInfo FMI_PYTHON = {
+ FMODIFIER_TYPE_PYTHON, /* type */
+ sizeof(FMod_Python), /* size */
+ "Python", /* name */
+ "FMod_Python", /* struct name */
+ fcm_python_free, /* free data */
+ fcm_python_copy, /* copy data */
+ fcm_python_new_data, /* new data */
+ fcm_python_evaluate /* evaluate */
+};
+
+
+/* F-Curve Modifier API --------------------------- */
+/* All of the F-Curve Modifier api functions use FModifierTypeInfo structs to carry out
+ * and operations that involve F-Curve modifier specifc code.
+ */
+
+/* These globals only ever get directly accessed in this file */
+static FModifierTypeInfo *fmodifiersTypeInfo[FMODIFIER_NUM_TYPES];
+static short FMI_INIT= 1; /* when non-zero, the list needs to be updated */
+
+/* This function only gets called when FMI_INIT is non-zero */
+static void fmods_init_typeinfo () {
+ fmodifiersTypeInfo[0]= NULL; /* 'Null' F-Curve Modifier */
+ fmodifiersTypeInfo[1]= &FMI_GENERATOR; /* Generator F-Curve Modifier */
+ fmodifiersTypeInfo[2]= &FMI_ENVELOPE; /* Envelope F-Curve Modifier */
+ fmodifiersTypeInfo[3]= &FMI_CYCLES; /* Cycles F-Curve Modifier */
+ fmodifiersTypeInfo[4]= NULL/*&FMI_NOISE*/; /* Apply-Noise F-Curve Modifier */ // XXX unimplemented
+ fmodifiersTypeInfo[5]= NULL/*&FMI_FILTER*/; /* Filter F-Curve Modifier */ // XXX unimplemented
+ fmodifiersTypeInfo[6]= &FMI_PYTHON; /* Custom Python F-Curve Modifier */
+}
+
+/* This function should be used for getting the appropriate type-info when only
+ * a F-Curve modifier type is known
+ */
+FModifierTypeInfo *get_fmodifier_typeinfo (int type)
+{
+ /* initialise the type-info list? */
+ if (FMI_INIT) {
+ fmods_init_typeinfo();
+ FMI_INIT = 0;
+ }
+
+ /* only return for valid types */
+ if ( (type >= FMODIFIER_TYPE_NULL) &&
+ (type <= FMODIFIER_NUM_TYPES ) )
+ {
+ /* there shouldn't be any segfaults here... */
+ return fmodifiersTypeInfo[type];
+ }
+ else {
+ printf("No valid F-Curve Modifier type-info data available. Type = %i \n", type);
+ }
+
+ return NULL;
+}
+
+/* This function should always be used to get the appropriate type-info, as it
+ * has checks which prevent segfaults in some weird cases.
+ */
+FModifierTypeInfo *fmodifier_get_typeinfo (FModifier *fcm)
+{
+ /* only return typeinfo for valid modifiers */
+ if (fcm)
+ return get_fmodifier_typeinfo(fcm->type);
+ else
+ return NULL;
+}
+
+/* API --------------------------- */
+
+/* Add a new F-Curve Modifier to the given F-Curve of a certain type */
+FModifier *fcurve_add_modifier (FCurve *fcu, int type)
+{
+ FModifierTypeInfo *fmi= get_fmodifier_typeinfo(type);
+ FModifier *fcm;
+
+ /* sanity checks */
+ if ELEM(NULL, fcu, fmi)
+ return NULL;
+
+ /* special checks for whether modifier can be added */
+ if ((fcu->modifiers.first) && (type == FMODIFIER_TYPE_CYCLES)) {
+ /* cycles modifier must be first in stack, so for now, don't add if it can't be */
+ // TODO: perhaps there is some better way, but for now,
+ printf("Error: Cannot add 'Cycles' modifier to F-Curve, as 'Cycles' modifier can only be first in stack. \n");
+ return NULL;
+ }
+
+ /* add modifier data */
+ fcm= MEM_callocN(sizeof(FModifier), "F-Curve Modifier");
+ BLI_addtail(&fcu->modifiers, fcm);
+
+ /* init custom settings if necessary */
+ if (fmi->new_data)
+ fmi->new_data(fcm->data);
+
+ /* return modifier for further editing */
+ return fcm;
+}
+
+/* Duplicate all of the F-Curve Modifiers in the Modifier stacks */
+void fcurve_copy_modifiers (ListBase *dst, ListBase *src)
+{
+ FModifier *fcm, *srcfcm;
+
+ if ELEM(NULL, dst, src)
+ return;
+
+ dst->first= dst->last= NULL;
+ BLI_duplicatelist(dst, src);
+
+ for (fcm=dst->first, srcfcm=src->first; fcm && srcfcm; srcfcm=srcfcm->next, fcm=fcm->next) {
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+
+ /* make a new copy of the F-Modifier's data */
+ fcm->data = MEM_dupallocN(fcm->data);
+
+ /* only do specific constraints if required */
+ if (fmi && fmi->copy_data)
+ fmi->copy_data(fcm, srcfcm);
+ }
+}
+
+/* Remove and free the given F-Curve Modifier from the given F-Curve's stack */
+void fcurve_remove_modifier (FCurve *fcu, FModifier *fcm)
+{
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+
+ /* sanity checks */
+ if ELEM3(NULL, fcu, fcm, fmi)
+ return;
+
+ /* free modifier's special data */
+ if (fmi->free_data)
+ fmi->free_data(fcm);
+
+ /* remove modifier from stack */
+ BLI_freelinkN(&fcu->modifiers, fcm);
+}
+
+/* Remove all of a given F-Curve's modifiers */
+void fcurve_free_modifiers (FCurve *fcu)
+{
+ FModifier *fcm, *fmn;
+
+ /* sanity check */
+ if (fcu == NULL)
+ return;
+
+ /* free each modifier in order */
+ for (fcm= fcu->modifiers.first; fcm; fcm= fmn) {
+ fmn= fcm->next;
+ fcurve_remove_modifier(fcu, fcm);
+ }
+}
+
+/* Bake modifiers for given F-Curve to curve sample data, in the frame range defined
+ * by start and end (inclusive).
+ */
+void fcurve_bake_modifiers (FCurve *fcu, int start, int end)
+{
+ FPoint *fpt, *new_fpt;
+ int cfra;
+
+ /* sanity checks */
+ // TODO: make these tests report errors using reports not printf's
+ if ELEM(NULL, fcu, fcu->modifiers.first) {
+ printf("Error: No F-Curve with F-Curve Modifiers to Bake\n");
+ return;
+ }
+ if (start >= end) {
+ printf("Error: Frame range for F-Curve Modifier Baking inappropriate \n");
+ return;
+ }
+
+ /* set up sample data */
+ fpt= new_fpt= MEM_callocN(sizeof(FPoint)*(end-start+1), "FPoint FModifier Samples");
+
+ /* sample the curve at 1-frame intervals from start to end frames
+ * - assume that any ChannelDriver possibly present did not interfere in any way
+ */
+ for (cfra= start; cfra <= end; cfra++, fpt++) {
+ fpt->vec[0]= (float)cfra;
+ fpt->vec[1]= evaluate_fcurve(fcu, (float)cfra);
+ }
+
+ /* free any existing sample/keyframe data on curve, and all modifiers */
+ if (fcu->bezt) MEM_freeN(fcu->bezt);
+ if (fcu->fpt) MEM_freeN(fcu->fpt);
+ fcurve_free_modifiers(fcu);
+
+ /* store the samples */
+ fcu->fpt= new_fpt;
+ fcu->totvert= end - start + 1;
+}
+
+/* ***************************** F-Curve - Evaluation ********************************* */
+
+/* Evaluate and return the value of the given F-Curve at the specified frame ("evaltime")
+ * Note: this is also used for drivers
+ */
+// TODO: set up the modifier system...
+float evaluate_fcurve (FCurve *fcu, float evaltime)
+{
+ FModifier *fcm;
+ float cvalue = 0.0f;
+
+ /* if there is a driver (only if this F-Curve is acting as 'driver'), evaluate it to find value to use as "evaltime"
+ * - this value will also be returned as the value of the 'curve', if there are no keyframes
+ */
+ if (fcu->driver) {
+ /* evaltime now serves as input for the curve */
+ evaltime= cvalue= evaluate_driver(fcu->driver, evaltime);
+ }
+
+ /* evaluate curve-data */
+ if (fcu->bezt)
+ cvalue= fcurve_eval_keyframes(fcu, fcu->bezt, evaltime);
+ else if (fcu->fpt)
+ cvalue= fcurve_eval_samples(fcu, fcu->fpt, evaltime);
+
+ /* evaluate modifiers */
+ for (fcm= fcu->modifiers.first; fcm; fcm= fcm->next) {
+ FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm);
+
+ /* only evaluate if there's a callback for this */
+ if (fmi && fmi->evaluate_modifier) {
+ if ((fcm->flag & FMODIFIER_FLAG_DISABLED) == 0)
+ fmi->evaluate_modifier(fcu, fcm, &cvalue, evaltime);
+ }
+ }
+
+ /* return evaluated value */
+ return cvalue;
+}
+
+/* Calculate the value of the given F-Curve at the given frame, and set its curval */
+// TODO: will this be necessary?
+void calculate_fcurve (FCurve *fcu, float ctime)
+{
+ /* calculate and set curval (evaluates driver too) */
+ fcu->curval= evaluate_fcurve(fcu, ctime);
+}
+
* ***** END GPL LICENSE BLOCK *****
*/
+#if 0 // XXX old animation system
+
#include <math.h>
#include <stdio.h>
#include <string.h>
* It is primarily used for patching old files, but is also used in the interface
* to make sure that all segments of the curve use the same interpolation.
*/
+// XXX move to readfile.c for patching old files only..
void set_interpolation_ipocurve (IpoCurve *icu, short ipo)
{
BezTriple *bezt;
/* return the value of this channel */
return ctime;
}
+
+#endif // XXX old animation system
#include "MEM_guardedalloc.h"
#include "DNA_curve_types.h"
-#include "DNA_ipo_types.h"
#include "DNA_key_types.h"
#include "DNA_lattice_types.h"
#include "DNA_mesh_types.h"
#include "BKE_blender.h"
#include "BKE_curve.h"
#include "BKE_global.h"
-#include "BKE_ipo.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
#define KEY_BPOINT 1
#define KEY_BEZTRIPLE 2
+ // old defines from DNA_ipo_types.h for data-type
+#define IPO_FLOAT 4
+#define IPO_BEZTRIPLE 100
+#define IPO_BPOINT 101
+
int slurph_opt= 1;
{
KeyBlock *kb;
+#if 0 // XXX old animation system
if(key->ipo) key->ipo->id.us--;
-
+#endif // XXX old animation system
while( (kb= key->block.first) ) {
key->type= KEY_NORMAL;
key->from= id;
+ // XXX the code here uses some defines which will soon be depreceated...
if( GS(id->name)==ID_ME) {
el= key->elemstr;
keyn= copy_libblock(key);
+#if 0 // XXX old animation system
keyn->ipo= copy_ipo(key->ipo);
-
+#endif // XXX old animation system
+
BLI_duplicatelist(&keyn->block, &key->block);
kb= key->block.first;
key->id.lib= 0;
new_id(0, (ID *)key, 0);
+
+#if 0 // XXX old animation system
make_local_ipo(key->ipo);
+#endif // XXX old animation system
}
-/*
- * Sort shape keys and Ipo curves after a change. This assumes that at most
+/* Sort shape keys and Ipo curves after a change. This assumes that at most
* one key was moved, which is a valid assumption for the places it's
* currently being called.
*/
void sort_keys(Key *key)
{
KeyBlock *kb;
- short i, adrcode;
- IpoCurve *icu = NULL;
+ //short i, adrcode;
+ //IpoCurve *icu = NULL;
KeyBlock *kb2;
/* locate the key which is out of position */
- for( kb= key->block.first; kb; kb= kb->next )
- if( kb->next && kb->pos > kb->next->pos )
+ for (kb= key->block.first; kb; kb= kb->next)
+ if ((kb->next) && (kb->pos > kb->next->pos))
break;
/* if we find a key, move it */
- if( kb ) {
+ if (kb) {
kb = kb->next; /* next key is the out-of-order one */
BLI_remlink(&key->block, kb);
-
+
/* find the right location and insert before */
- for( kb2=key->block.first; kb2; kb2= kb2->next ) {
- if( kb2->pos > kb->pos ) {
+ for (kb2=key->block.first; kb2; kb2= kb2->next) {
+ if (kb2->pos > kb->pos) {
BLI_insertlink(&key->block, kb2->prev, kb);
break;
}
}
-
+
/* if more than one Ipo curve, see if this key had a curve */
-
+#if 0 // XXX old animation system
if(key->ipo && key->ipo->curve.first != key->ipo->curve.last ) {
for(icu= key->ipo->curve.first; icu; icu= icu->next) {
/* if we find the curve, remove it and reinsert in the
}
}
}
-
+
/* kb points at the moved key, icu at the moved ipo (if it exists).
* go back now and renumber adrcodes */
/* first new code */
adrcode = kb2->adrcode;
- for( i = kb->adrcode - adrcode; i >= 0; --i, ++adrcode ) {
+ for (i = kb->adrcode - adrcode; i >= 0; i--, adrcode++) {
/* if the next ipo curve matches the current key, renumber it */
if(icu && icu->adrcode == kb->adrcode ) {
icu->adrcode = adrcode;
kb->adrcode = adrcode;
kb = kb->next;
}
+#endif // XXX old animation system
}
/* new rule; first key is refkey, this to match drawing channels... */
for(a=0; a<me->totvert; a+=step, cfra+= delta) {
- ctime= bsystem_time(scene, 0, cfra, 0.0);
+ 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) {
ctime /= 100.0;
CLAMP(ctime, 0.0, 1.0);
}
+#endif // XXX old animation system
flag= setkeys(ctime, &me->key->block, k, t, 0);
if(flag==0) {
}
}
else {
- ctime= bsystem_time(scene, ob, scene->r.cfra, 0.0);
-
+ ctime= bsystem_time(scene, ob, scene->r.cfra, 0.0); // xxx old cruft
+
+#if 0 // XXX old animation system
if(calc_ipo_spec(me->key->ipo, KEY_SPEED, &ctime)==0) {
ctime /= 100.0;
CLAMP(ctime, 0.0, 1.0);
}
-
+#endif // XXX old animation system
+
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);
cfra= scene->r.cfra;
for(a=0; a<tot; a+=step, cfra+= delta) {
-
- ctime= bsystem_time(scene, 0, cfra, 0.0);
+ ctime= bsystem_time(scene, 0, cfra, 0.0); // XXX old cruft
+#if 0 // XXX old animation system
if(calc_ipo_spec(cu->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_rel_cu_key(cu, ctime);
}
else {
+#if 0 // XXX old animation system
if(calc_ipo_spec(cu->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);
for(a=0; a<tot; a++, cfra+= delta) {
- ctime= bsystem_time(scene, 0, cfra, 0.0);
+ 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) {
ctime /= 100.0;
CLAMP(ctime, 0.0, 1.0);
}
+#endif // XXX old animation system
flag= setkeys(ctime, <->key->block, k, t, 0);
if(flag==0) {
}
}
else {
+#if 0 // XXX old animation system
if(calc_ipo_spec(lt->key->ipo, KEY_SPEED, &ctime)==0) {
ctime /= 100.0;
CLAMP(ctime, 0.0, 1.0);
}
+#endif // XXX old animation system
flag= setkeys(ctime, <->key->block, k, t, 0);
if(flag==0) {
return 1;
}
else {
+#if 0 // XXX old animation system
+ // NOTE: this stuff was NEVER reliable at all...
if(ob->ipoflag & OB_ACTION_KEY)
do_all_object_actions(scene, ob);
else {
calc_ipo(key->ipo, bsystem_time(scene, ob, scene->r.cfra, 0.0));
execute_ipo((ID *)key, key->ipo);
}
+#endif // XXX old animation system
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);
#include "BLI_arithb.h"
#include "DNA_armature_types.h"
-#include "DNA_ipo_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "BKE_deform.h"
#include "BKE_displist.h"
#include "BKE_global.h"
-#include "BKE_ipo.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
ltn= copy_libblock(lt);
ltn->def= MEM_dupallocN(lt->def);
+#if 0 // XXX old animation system
id_us_plus((ID *)ltn->ipo);
+#endif // XXX old animation system
ltn->key= copy_key(ltn->key);
if(ltn->key) ltn->key->from= (ID *)ltn;
fac= (cd->dloc[index])/(cu->path->totdist) + (co[index]-cd->dmin[index])/(cu->path->totdist);
}
+#if 0 // XXX old animation system
/* we want the ipo to work on the default 100 frame range, because there's no
actual time involved in path position */
+ // huh? by WHY!!!!???? - Aligorith
if(cu->ipo) {
fac*= 100.0f;
if(calc_ipo_spec(cu->ipo, CU_SPEED, &fac)==0)
fac/= 100.0;
}
+#endif // XXX old animation system
if( where_on_path_deform(par, fac, loc, dir)) { /* returns OK */
float q[4], mat[3][3], quat[4];
id = MEM_callocN(sizeof(bArmature), "armature");
break;
case ID_AC:
- id = MEM_callocN(sizeof(bAction), "action");
+ id = MEM_callocN(sizeof(nAction), "action"); // XXX animation system
break;
case ID_NT:
id = MEM_callocN(sizeof(bNodeTree), "nodetree");
free_camera((Camera*) id);
break;
case ID_IP:
- free_ipo((Ipo *)id);
+ /*free_ipo((Ipo *)id);*/
break;
case ID_KE:
free_key((Key *)id);
free_armature((bArmature *)id);
break;
case ID_AC:
- free_action((bAction *)id);
+ free_action((nAction *)id); // XXX animation system...
break;
case ID_NT:
ntreeFreeTree((bNodeTree *)id);
man= copy_libblock(ma);
+#if 0 // XXX old animation system
id_us_plus((ID *)man->ipo);
+#endif // XXX old animation system
id_us_plus((ID *)man->group);
#include "MEM_guardedalloc.h"
+#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_camera_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curve_types.h"
#include "DNA_group_types.h"
-#include "DNA_ipo_types.h"
#include "DNA_lamp_types.h"
#include "DNA_lattice_types.h"
#include "DNA_material_types.h"
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
-#include "BKE_armature.h"
-#include "BKE_action.h"
-#include "BKE_bullet.h"
-#include "BKE_colortools.h"
-#include "BKE_deform.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_nla.h"
-
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
#include "BLI_editVert.h"
#include "BKE_main.h"
#include "BKE_global.h"
+#include "BKE_armature.h"
+#include "BKE_action.h"
+#include "BKE_bullet.h"
+#include "BKE_colortools.h"
+#include "BKE_deform.h"
+#include "BKE_DerivedMesh.h"
+#include "BKE_nla.h"
+#include "BKE_animsys.h"
#include "BKE_anim.h"
#include "BKE_blender.h"
#include "BKE_constraint.h"
#include "BKE_displist.h"
#include "BKE_group.h"
#include "BKE_icons.h"
-#include "BKE_ipo.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
ob->bb= 0;
if(ob->path) free_path(ob->path);
ob->path= 0;
+#if 0 // XXX old animation system
if(ob->ipo) ob->ipo->id.us--;
if(ob->action) ob->action->id.us--;
+#endif // XXX old animation system
if(ob->poselib) ob->poselib->id.us--;
if(ob->dup_group) ob->dup_group->id.us--;
if(ob->defbase.first)
free_actuators(&ob->actuators);
free_constraints(&ob->constraints);
- free_constraint_channels(&ob->constraintChannels);
+#if 0 // XXX old animation system
free_nlastrips(&ob->nlastrips);
+#endif
#ifndef DISABLE_PYTHON
BPY_free_scriptlink(&ob->scriptlink);
Scene *sce;
Curve *cu;
Tex *tex;
- Ipo *ipo;
Group *group;
Camera *camera;
bConstraint *con;
- bActionStrip *strip;
+ //bActionStrip *strip; // XXX animsys
ModifierData *md;
int a;
}
/* strips */
+#if 0 // XXX old animation system
for(strip= obt->nlastrips.first; strip; strip= strip->next) {
if(strip->object==ob)
strip->object= NULL;
amod->ob= NULL;
}
}
+#endif // XXX old animation system
/* particle systems */
if(obt->particlesystem.first) {
}
sce= sce->id.next;
}
+
+#if 0 // XXX old animation system
/* ipos */
ipo= G.main->ipo.first;
while(ipo) {
}
ipo= ipo->id.next;
}
+#endif // XXX old animation system
/* screens */
sc= G.main->screen.first;
}
}
else if(sl->spacetype==SPACE_IPO) {
+ // XXX animsys this is likely to change...
SpaceIpo *sipo= (SpaceIpo *)sl;
if(sipo->from == (ID *)ob) sipo->from= NULL;
}
Camera *camn;
camn= copy_libblock(cam);
+
+#if 0 // XXX old animation system
id_us_plus((ID *)camn->ipo);
+#endif // XXX old animation system
+
#ifndef DISABLE_PYTHON
BPY_copy_scriptlink(&camn->scriptlink);
#endif
lan->curfalloff = curvemapping_copy(la->curfalloff);
+#if 0 // XXX old animation system
id_us_plus((ID *)lan->ipo);
+#endif // XXX old animation system
if (la->preview) lan->preview = BKE_previewimg_copy(la->preview);
#ifndef DISABLE_PYTHON
if(mtex && mtex->tex) mtex->tex->id.us--;
if(mtex) MEM_freeN(mtex);
}
+
+#if 0 // XXX old animation system
la->ipo= 0;
+#endif // XXX old animation system
curvemapping_free(la->curfalloff);
ob->trackflag= OB_POSY;
ob->upflag= OB_POSZ;
}
+
+#if 0 // XXX old animation system
ob->ipoflag = OB_OFFS_OB+OB_OFFS_PARENT;
ob->ipowin= ID_OB; /* the ipowin shown */
+#endif // XXX old animation system
+
ob->dupon= 1; ob->dupoff= 0;
ob->dupsta= 1; ob->dupend= 100;
ob->dupfacesca = 1.0;
ListBase targets = {NULL, NULL};
bConstraintTarget *ct;
+#if 0 // XXX old animation system
/* note that we can't change lib linked ipo blocks. for making
* proxies this still works correct however because the object
* is changed to object->proxy_from when evaluating the driver. */
icu->driver->ob= obn;
}
}
+#endif // XXX old animation system
if (cti && cti->get_constraint_targets) {
cti->get_constraint_targets(con, &targets);
armature_rebuild_pose(obn, obn->data);
}
copy_defgroups(&obn->defbase, &ob->defbase);
+#if 0 // XXX old animation system
copy_nlastrips(&obn->nlastrips, &ob->nlastrips);
- copy_constraints (&obn->constraints, &ob->constraints);
-
- clone_constraint_channels (&obn->constraintChannels, &ob->constraintChannels);
+#endif // XXX old animation system
+ copy_constraints(&obn->constraints, &ob->constraints);
/* increase user numbers */
id_us_plus((ID *)obn->data);
+#if 0 // XXX old animation system
id_us_plus((ID *)obn->ipo);
id_us_plus((ID *)obn->action);
+#endif // XXX old animation system
id_us_plus((ID *)obn->dup_group);
for(a=0; a<obn->totcol; a++) id_us_plus((ID *)obn->mat[a]);
void expand_local_object(Object *ob)
{
- bActionStrip *strip;
+ //bActionStrip *strip;
ParticleSystem *psys;
int a;
-
+
+#if 0 // XXX old animation system
id_lib_extern((ID *)ob->action);
id_lib_extern((ID *)ob->ipo);
+#endif // XXX old animation system
id_lib_extern((ID *)ob->data);
id_lib_extern((ID *)ob->dup_group);
for(a=0; a<ob->totcol; a++) {
id_lib_extern((ID *)ob->mat[a]);
}
+#if 0 // XXX old animation system
for (strip=ob->nlastrips.first; strip; strip=strip->next) {
id_lib_extern((ID *)strip->act);
}
+#endif // XXX old animation system
for(psys=ob->particlesystem.first; psys; psys=psys->next)
id_lib_extern((ID *)psys->part);
}
ob->parent= target->parent; /* libdata */
Mat4CpyMat4(ob->parentinv, target->parentinv);
+#if 0 // XXX old animation system
ob->ipo= target->ipo; /* libdata */
+#endif // XXX old animation system
/* skip constraints, constraintchannels, nla? */
no_speed_curve= val;
}
+// XXX THIS CRUFT NEEDS SERIOUS RECODING ASAP!
/* ob can be NULL */
float bsystem_time(struct Scene *scene, Object *ob, float cfra, float ofs)
{
/* global time */
cfra*= scene->r.framelen;
+#if 0 // XXX old animation system
if (ob) {
if (no_speed_curve==0 && ob->ipo)
cfra= calc_ipo_time(ob->ipo, cfra);
if ((ob->ipoflag & OB_OFFS_PARENT) && (ob->partype & PARSLOW)==0)
cfra-= give_timeoffset(ob);
}
+#endif // XXX old animation system
cfra-= ofs;
else if(enable_cu_speed) {
ctime= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0);
+#if 0 // XXX old animation system
if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) {
ctime /= cu->pathlen;
CLAMP(ctime, 0.0, 1.0);
}
+#endif // XXX old animation system
}
else {
ctime= scene->r.cfra - give_timeoffset(ob);
}
}
+// XXX what the hell is this?
static int no_parent_ipo=0;
void set_no_parent_ipo(int val)
{
void where_is_object_time(Scene *scene, Object *ob, float ctime)
{
float *fp1, *fp2, slowmat[4][4] = MAT4_UNITY;
- float stime, fac1, fac2, vec[3];
+ float stime=ctime, fac1, fac2, vec[3];
int a;
int pop;
if(ob==NULL) return;
+#if 0 // XXX old animation system
/* this is needed to be able to grab objects with ipos, otherwise it always freezes them */
stime= bsystem_time(scene, ob, ctime, 0.0);
if(stime != ob->ctime) {
/* do constraint ipos ..., note it needs stime (1 = only drivers ipos) */
do_constraint_channels(&ob->constraints, &ob->constraintChannels, stime, 1);
}
+#endif // XXX old animation system
+
+ /* execute drivers only, as animation has already been done */
+ BKE_animsys_evaluate_animdata(&ob->id, &ob->adt, ctime, ADT_RECALC_DRIVERS);
if(ob->parent) {
Object *par= ob->parent;
+ // XXX depreceated - animsys
if(ob->ipoflag & OB_OFFS_PARENT) ctime-= give_timeoffset(ob);
/* hurms, code below conflicts with depgraph... (ton) */
for a lamp that is the child of another object */
{
Object *par;
- Ipo *ipo;
+ //Ipo *ipo;
float *fp1, *fp2;
float slowmat[4][4];
float fac1, fac2;
/* NO TIMEOFFS */
/* no ipo! (because of dloc and realtime-ipos) */
- ipo= ob->ipo;
- ob->ipo= NULL;
+ // XXX old animation system
+ //ipo= ob->ipo;
+ //ob->ipo= NULL;
if(ob->parent) {
par= ob->parent;
}
/* WATCH IT!!! */
- ob->ipo= ipo;
+ // XXX old animation system
+ //ob->ipo= ipo;
}
/* for calculation of the inverse parent transform, only used for editor */
lattice_calc_modifiers(scene, ob);
}
else if(ob->type==OB_CAMERA) {
- Camera *cam = (Camera *)ob->data;
- calc_ipo(cam->ipo, frame_to_float(scene, scene->r.cfra));
- execute_ipo(&cam->id, cam->ipo);
+ //Camera *cam = (Camera *)ob->data;
+
+ // xxx old animation code here
+ //calc_ipo(cam->ipo, frame_to_float(scene, scene->r.cfra));
+ //execute_ipo(&cam->id, cam->ipo);
+
+ // in new system, this has already been done! - aligorith
}
else if(ob->type==OB_LAMP) {
- Lamp *la = (Lamp *)ob->data;
- calc_ipo(la->ipo, frame_to_float(scene, scene->r.cfra));
- execute_ipo(&la->id, la->ipo);
+ //Lamp *la = (Lamp *)ob->data;
+
+ // xxx old animation code here
+ //calc_ipo(la->ipo, frame_to_float(scene, scene->r.cfra));
+ //execute_ipo(&la->id, la->ipo);
+
+ // in new system, this has already been done! - aligorith
}
else if(ob->type==OB_ARMATURE) {
/* this happens for reading old files and to match library armatures with poses */
// printf("pose proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name);
}
else {
- do_all_pose_actions(scene, ob);
+ //do_all_pose_actions(scene, ob); // xxx old animation system
where_is_pose(scene, ob);
}
}
#include "DNA_object_types.h"
#include "DNA_curve_types.h"
#include "DNA_key_types.h"
-#include "DNA_ipo_types.h"
+#include "DNA_ipo_types.h" // XXX old animation system stuff to remove!
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "BKE_displist.h"
#include "BKE_particle.h"
#include "BKE_DerivedMesh.h"
-#include "BKE_ipo.h"
#include "BKE_object.h"
#include "BKE_softbody.h"
#include "BKE_material.h"
}
/* set correct ipo timing */
+#if 0 // XXX old animation system
if(part->flag&PART_ABS_TIME && part->ipo){
calc_ipo(part->ipo, cfra);
execute_ipo((ID *)part, part->ipo);
}
+#endif // XXX old animation system
return 1;
}
keys->steps = ctx->steps;
/* correct child ipo timing */
+#if 0 // XXX old animation system
if((part->flag&PART_ABS_TIME)==0 && part->ipo){
float dsta=part->end-part->sta;
calc_ipo(part->ipo, 100.0f*(ctx->cfra-(part->sta+dsta*cpa->rand[1]))/(part->lifetime*(1.0f - part->randlife*cpa->rand[0])));
execute_ipo((ID *)part, part->ipo);
}
+#endif // XXX old animation system
/* get different child parameters from textures & vgroups */
ptex.length=part->length*(1.0f - part->randlength*cpa->rand[0]);
part->boidfac[i]=0.5;
}
+#if 0 // XXX old animation system
part->ipo = NULL;
+#endif // XXX old animation system
part->simplify_refsize= 1920;
part->simplify_rate= 1.0f;
size=ptex.size;
}
+#if 0 // XXX old animation system
if(icu_size){
calc_icu(icu_size,pa->time);
size*=icu_size->curval;
}
+#endif // XXX old animation system
if(vg_size)
size*=psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_size);
if(part->childtype==PART_CHILD_FACES){
size=part->size;
+#if 0 // XXX old animation system
if((part->flag&PART_ABS_TIME)==0 && part->ipo){
IpoCurve *icu;
size = icu->curval;
}
}
+#endif // XXX old animation system
}
else
size=psys->particles[cpa->parent].size;
}
/* correct child ipo timing */
+#if 0 // XXX old animation system
if((part->flag&PART_ABS_TIME)==0 && part->ipo){
calc_ipo(part->ipo, 100.0f*t);
execute_ipo((ID *)part, part->ipo);
}
-
+#endif // XXX old animation system
+
/* get different child parameters from textures & vgroups */
ptex.clump=1.0;
ptex.kink=1.0;
#include "DNA_object_force.h"
#include "DNA_object_types.h"
#include "DNA_material_types.h"
-#include "DNA_ipo_types.h"
#include "DNA_curve_types.h"
#include "DNA_group_types.h"
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
+#include "DNA_ipo_types.h" // XXX old animation system stuff... to be removed!
#include "BLI_rand.h"
#include "BLI_jitter.h"
#include "BKE_DerivedMesh.h"
#include "BKE_object.h"
#include "BKE_material.h"
-#include "BKE_ipo.h"
#include "BKE_softbody.h"
#include "BKE_depsgraph.h"
#include "BKE_lattice.h"
ParticleSettings *part;
ParticleTexture ptex;
Material *ma=0;
- IpoCurve *icu=0;
+ //IpoCurve *icu=0; // XXX old animation system
int totpart;
float rand,length;
pa->lifetime=100.0f;
}
else{
+#if 0 // XXX old animation system
icu=find_ipocurve(psys->part->ipo,PART_EMIT_LIFE);
if(icu){
calc_icu(icu,100*ptex.time);
pa->lifetime*=icu->curval;
}
+#endif // XXX old animation system
/* need to get every rand even if we don't use them so that randoms don't affect eachother */
rand= BLI_frand();
}
static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd)
{
- IpoCurve *icu=0;
+ //IpoCurve *icu=0; // XXX old animation system
ParticleData *pa;
int p, totpart=psys->totpart;
initialize_particle(pa,p,ob,psys,psmd);
if(psys->part->type != PART_FLUID) {
+#if 0 // XXX old animation system
icu=find_ipocurve(psys->part->ipo,PART_EMIT_FREQ);
if(icu){
float time=psys->part->sta, end=psys->part->end;
p=0;
pa=psys->particles;
+
calc_icu(icu,time);
v1=icu->curval;
if(v1<0.0f) v1=0.0f;
pa->flag |= PARS_UNEXIST;
}
}
+#endif // XXX old animation system
}
}
/* sets particle to the emitter surface with initial velocity & rotation */
ParticleSettings *part;
ParticleTexture ptex;
ParticleKey state;
- IpoCurve *icu=0;
+ //IpoCurve *icu=0; // XXX old animation system
float fac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4];
float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0};
float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0};
if(part->partfac!=0.0)
VECADDFAC(vel,vel,p_vel,part->partfac);
+#if 0 // XXX old animation system
icu=find_ipocurve(psys->part->ipo,PART_EMIT_VEL);
if(icu){
calc_icu(icu,100*((pa->time-part->sta)/(part->end-part->sta)));
ptex.ivel*=icu->curval;
}
+#endif // XXX old animation system
VecMulf(vel,ptex.ivel);
Normalize(pa->state.ave);
VecMulf(pa->state.ave,part->avefac);
+#if 0 // XXX old animation system
icu=find_ipocurve(psys->part->ipo,PART_EMIT_AVE);
if(icu){
calc_icu(icu,100*((pa->time-part->sta)/(part->end-part->sta)));
VecMulf(pa->state.ave,icu->curval);
}
+#endif // XXX old animation system
}
pa->dietime = pa->time + pa->lifetime;
ParticleSettings *part=psys->part;
KDTree *tree=0;
BoidVecFunc bvf;
- IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE);
+ IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system
Material *ma=give_current_material(ob,part->omat);
float timestep;
int p, totpart;
/* current time */
- float ctime, ipotime;
+ float ctime, ipotime; // XXX old animation system
/* frame & time changes */
float dfra, dtime, pa_dtime, pa_dfra=0.0;
float birthtime, dietime;
timestep=psys_get_timestep(part);
dtime= dfra*timestep;
ctime= cfra*timestep;
- ipotime= cfra;
+ ipotime= cfra; // XXX old animation system
+#if 0 // XXX old animation system
if(part->flag&PART_ABS_TIME && part->ipo){
calc_ipo(part->ipo, cfra);
execute_ipo((ID *)part, part->ipo);
}
+#endif // XXX old animation system
if(dfra<0.0){
float *vg_size=0;
if(pa->flag & PARS_UNEXIST) continue;
/* set correct ipo timing */
+#if 0 // XXX old animation system
if((part->flag&PART_ABS_TIME)==0 && part->ipo){
ipotime=100.0f*(cfra-pa->time)/pa->lifetime;
calc_ipo(part->ipo, ipotime);
execute_ipo((ID *)part, part->ipo);
}
+#endif // XXX old animation system
pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size);
reset_particle(scene, pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot);
copy_particle_key(&pa->prev_state,&pa->state,1);
/* set correct ipo timing */
+#if 0 // XXX old animation system
if((part->flag&PART_ABS_TIME)==0 && part->ipo){
ipotime=100.0f*(cfra-pa->time)/pa->lifetime;
calc_ipo(part->ipo, ipotime);
execute_ipo((ID *)part, part->ipo);
}
+#endif // XXX old animation system
pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size);
/* reactions can change birth time so they need to be checked first */
ParticleSettings *part=psys->part;
ParticleData *pa;
ParticleKey state;
- IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE);
+ IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system
Material *ma=give_current_material(ob,part->omat);
int p;
float ipotime=cfra, disp, birthtime, dietime, *vg_size= NULL;
disp= (float)get_current_display_percentage(psys)/50.0f-1.0f;
for(p=0, pa=psys->particles; p<psys->totpart; p++,pa++){
+#if 0 // XXX old animation system
if((part->flag&PART_ABS_TIME)==0 && part->ipo){
ipotime=100.0f*(cfra-pa->time)/pa->lifetime;
calc_ipo(part->ipo, ipotime);
execute_ipo((ID *)part, part->ipo);
}
+#endif // XXX old animation system
pa->size= psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size);
psys->lattice= psys_get_lattice(scene, ob, psys);
BKE_ptcache_id_time(&pid, scene, 0.0f, &startframe, &endframe, NULL);
/* update ipo's */
+#if 0 // XXX old animation system
if((part->flag & PART_ABS_TIME) && part->ipo) {
calc_ipo(part->ipo, cfra);
execute_ipo((ID *)part, part->ipo);
}
+#endif // XXX old animation system
/* hair if it's already done is handled separate */
if(part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DONE)) {
*startframe= cache->startframe;
*endframe= cache->endframe;
- if ((ob->ipoflag & OB_OFFS_PARENT) && (ob->partype & PARSLOW)==0) {
+ // XXX ipoflag is depreceated - old animation system stuff
+ if (/*(ob->ipoflag & OB_OFFS_PARENT) &&*/ (ob->partype & PARSLOW)==0) {
offset= give_timeoffset(ob);
*startframe += (int)(offset+0.5f);
#endif
#include "MEM_guardedalloc.h"
+#include "DNA_anim_types.h"
#include "DNA_armature_types.h"
#include "DNA_color_types.h"
#include "DNA_constraint_types.h"
#include "BKE_action.h"
#include "BKE_anim.h"
+#include "BKE_animsys.h"
#include "BKE_armature.h"
#include "BKE_colortools.h"
#include "BKE_colortools.h"
object_handle_update(sce, ob); // bke_object.h
/* only update layer when an ipo */
- if(ob->ipo && has_ipo_code(ob->ipo, OB_LAY) ) {
- base->lay= ob->lay;
- }
+ // XXX old animation system
+ //if(ob->ipo && has_ipo_code(ob->ipo, OB_LAY) ) {
+ // base->lay= ob->lay;
+ //}
}
}
+/* This (evil) function is needed to cope with two legacy Blender rendering features
+ * mblur (motion blur that renders 'subframes' and blurs them together), and fields
+ * rendering. Thus, the use of ugly globals from object.c
+ */
+// BAD... EVIL... JUJU...!!!!
+// XXX moved here temporarily
+float frame_to_float (Scene *scene, int cfra) /* see also bsystem_time in object.c */
+{
+ extern float bluroffs; /* bad stuff borrowed from object.c */
+ extern float fieldoffs;
+ float ctime;
+
+ ctime= (float)cfra;
+ ctime+= bluroffs+fieldoffs;
+ ctime*= scene->r.framelen;
+
+ return ctime;
+}
+
/* applies changes right away, does all sets too */
void scene_update_for_newframe(Scene *sce, unsigned int lay)
{
Scene *scene= sce;
+ float ctime = frame_to_float(sce, sce->r.cfra);
/* clears all BONE_UNKEYED flags for every pose's pchans */
- framechange_poses_clear_unkeyed();
+ // xxx old animation system
+ //framechange_poses_clear_unkeyed();
+
+ /* clear animation overrides */
+ // XXX TODO...
+
+ /* All 'standard' (i.e. without any dependencies) animation is handled here,
+ * with an 'local' to 'macro' order of evaluation. This should ensure that
+ * settings stored nestled within a hierarchy (i.e. settings in a Texture block
+ * can be overridden by settings from Scene, which owns the Texture through a hierarchy
+ * such as Scene->World->MTex/Texture) can still get correctly overridden.
+ */
+ BKE_animsys_evaluate_all_animation(G.main, ctime);
+
- /* object ipos are calculated in where_is_object */
- do_all_data_ipos(sce);
#ifndef DISABLE_PYTHON
if (G.f & G_DOSCRIPTLINKS) BPY_do_all_scripts(SCRIPT_FRAMECHANGED, 0);
#endif
#include "BLI_arithb.h"
#include "BKE_global.h"
-#include "BKE_ipo.h"
#include "BKE_plugin_types.h"
#include "BKE_sequence.h"
#include "BKE_texture.h"
void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force)
{
float facf0 = seq->facf0;
- float ctime, div;
+ //float ctime, div;
int cfra;
float fallback_fac;
SpeedControlVars * v = (SpeedControlVars *)seq->effectdata;
/* if there is no IPO, try to make retiming easy by stretching the
strip */
-
- if (!seq->ipo && seq->seq1 && seq->seq1->enddisp != seq->seq1->start
+ // XXX old animation system - seq
+ if (/*!seq->ipo &&*/ seq->seq1 && seq->seq1->enddisp != seq->seq1->start
&& seq->seq1->len != 0) {
fallback_fac = (float) seq->seq1->len /
(float) (seq->seq1->enddisp - seq->seq1->start);
v->lastValidFrame = 0;
for (cfra = 1; cfra < v->length; cfra++) {
+#if 0 // XXX old animation system
if(seq->ipo) {
if((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
ctime = frame_to_float(scene, seq->startdisp + cfra);
calc_ipo(seq->ipo, ctime/div);
execute_ipo((ID *)seq, seq->ipo);
- } else {
+ } else
+#endif // XXX old animation system
+ {
seq->facf0 = fallback_fac;
}
seq->facf0 *= v->globalSpeed;
} else {
v->lastValidFrame = 0;
for (cfra = 0; cfra < v->length; cfra++) {
+#if 0 // XXX old animation system
if(seq->ipo) {
if((seq->flag & SEQ_IPO_FRAME_LOCKED) != 0) {
ctime = frame_to_float(scene, seq->startdisp + cfra);
calc_ipo(seq->ipo, ctime/div);
execute_ipo((ID *)seq, seq->ipo);
}
+#endif // XXX old animation system
if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) {
seq->facf0 *= v->length;
}
- if (!seq->ipo) {
+ if (/*!seq->ipo*/ 1) { // XXX old animation system - seq
seq->facf0 = (float) cfra * fallback_fac;
}
seq->facf0 *= v->globalSpeed;
#include "MEM_guardedalloc.h"
-#include "DNA_ipo_types.h"
#include "DNA_listBase.h"
#include "DNA_sequence_types.h"
#include "DNA_scene_types.h"
#include "BKE_global.h"
#include "BKE_image.h"
-#include "BKE_ipo.h"
#include "BKE_main.h"
#include "BKE_sequence.h"
#include "BKE_utildefines.h"
return;
}
+#if 0 // XXX old animation system
if(seq->ipo && seq->ipo->curve.first) {
do_seq_ipo(scene, seq, cfra);
fac= seq->facf0;
facf= seq->facf1;
- } else {
+ } else
+#endif // XXX old animation system
+ {
sh.get_default_fac(seq, cfra, &fac, &facf);
}
alpha over mode...
*/
if (seq->blend_mode != SEQ_BLEND_REPLACE ||
- (seq->ipo && seq->ipo->curve.first && (
- !(seq->type & SEQ_EFFECT) || !seq->seq1))) {
+ (/*seq->ipo && seq->ipo->curve.first &&*/
+ (!(seq->type & SEQ_EFFECT) || !seq->seq1))) {
Strip * s = seq->strip;
if (cfra < seq->start) {
se = s->tstripdata_startstill;
mul = seq->mul;
if(seq->blend_mode == SEQ_BLEND_REPLACE) {
+#if 0 // XXX old animation system
if (seq->ipo && seq->ipo->curve.first) {
do_seq_ipo(scene, seq, cfra);
mul *= seq->facf0;
}
+#endif // XXX old animation system
mul *= seq->blend_opacity / 100.0;
}
mul = seq->mul;
if(seq->blend_mode == SEQ_BLEND_REPLACE) {
+#if 0 // XXX old animation system
if (seq->ipo && seq->ipo->curve.first) {
do_seq_ipo(scene, seq, cfra);
mul *= seq->facf0;
}
+#endif // XXX old animation system
mul *= seq->blend_opacity / 100.0;
}
se->se2 = 0;
se->se3 = 0;
+#if 0 // XXX old animation system
if(seq->ipo && seq->ipo->curve.first) {
do_seq_ipo(scene, seq, cfra);
fac= seq->facf0;
facf= seq->facf1;
- } else {
+ } else
+#endif // XXX old animation system
+ {
sh.get_default_fac(seq, cfra, &fac, &facf);
}
seq->facf0 = seq->facf1 = 1.0;
+#if 0 // XXX old animation system
if(seq->ipo && seq->ipo->curve.first) {
do_seq_ipo(scene, seq, cfra);
}
+#endif
if( scene->r.mode & R_FIELDS ); else seq->facf0 = seq->facf1;
#include "BKE_texture.h"
#include "BKE_key.h"
#include "BKE_icons.h"
-#include "BKE_ipo.h"
#include "BKE_brush.h"
#include "BKE_node.h"
if(texn->type==TEX_IMAGE) id_us_plus((ID *)texn->ima);
else texn->ima= 0;
+#if 0 // XXX old animation system
id_us_plus((ID *)texn->ipo);
+#endif // XXX old animation system
if(texn->plugin) {
texn->plugin= MEM_dupallocN(texn->plugin);
if(texture->plugin) {
// assume all plugins depend on time
return 1;
- } else if( texture->ima &&
+ }
+ else if( texture->ima &&
ELEM(texture->ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
return 1;
- } else if(texture->ipo) {
+ }
+#if 0 // XXX old animation system
+ else if(texture->ipo) {
// assume any ipo means the texture is animated
return 1;
}
+#endif // XXX old animation system
return 0;
}
}
BKE_previewimg_free(&wrld->preview);
+#if 0 // XXX old animation system
wrld->ipo= 0;
+#endif // XXX old animation system
+
BKE_icon_delete((struct ID*)wrld);
wrld->id.icon_id = 0;
}
#ifndef DISABLE_PYTHON
BPY_copy_scriptlink(&wrld->scriptlink);
#endif
+
+#if 0 // XXX old animation system
id_us_plus((ID *)wrldn->ipo);
+#endif // XXX old animation system
return wrldn;
}
IpoCurve *icu;
/* fix IPO-curves to work with new interpolation options */
- for (ipo=main->ipo.first; ipo; ipo= ipo->id.next) {
- for (icu= ipo->curve.first; icu; icu= icu->next)
- set_interpolation_ipocurve(icu, icu->ipo);
- }
+ //for (ipo=main->ipo.first; ipo; ipo= ipo->id.next) {
+ // for (icu= ipo->curve.first; icu; icu= icu->next)
+ // set_interpolation_ipocurve(icu, icu->ipo); // function removed (XXX add it here)
+ //}
/* adjust default settings for Animation Editors */
for (sc= main->screen.first; sc; sc= sc->id.next) {
/* only work with this channel and its subchannels if it is editable */
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_ICU(icu)) {
/* only include this curve if selected or we are including all IPO-curves */
- if (!(filter_mode & ANIMFILTER_SEL) || (filter_mode & ANIMFILTER_ONLYICU) || (SEL_ICU(icu))) {
+ if (!(filter_mode & ANIMFILTER_SEL) || (filter_mode & ANIMFILTER_ONLYFCU) || (SEL_ICU(icu))) {
/* owner/ownertype will be either object or action-channel, depending if it was dopesheet or part of an action */
ale= make_new_animlistelem(icu, ANIMTYPE_ICU, owner, ownertype);
/* check if this achan should only be included if it is selected */
if (!(filter_mode & ANIMFILTER_SEL) || SEL_ACHAN(achan)) {
/* are we only interested in the ipo-curves? */
- if ((filter_mode & ANIMFILTER_ONLYICU)==0) {
+ if ((filter_mode & ANIMFILTER_ONLYFCU)==0) {
ale= make_new_animlistelem(achan, ANIMTYPE_ACHAN, achan, ANIMTYPE_ACHAN);
if (ale) {
}
/* check if expanded - if not, continue on to next animion channel */
- if (EXPANDED_ACHAN(achan) == 0 && (filter_mode & ANIMFILTER_ONLYICU)==0) {
+ if (EXPANDED_ACHAN(achan) == 0 && (filter_mode & ANIMFILTER_ONLYFCU)==0) {
/* only exit if we don't need to include constraint channels for group-channel keyframes */
if ( !(filter_mode & ANIMFILTER_IPOKEYS) || (achan->grp == NULL) || (EXPANDED_AGRP(achan->grp)==0) )
return items;
/* ipo channels */
if ((achan->ipo) && (filter_mode & ANIMFILTER_IPOKEYS)==0) {
/* include ipo-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && (filter_mode & ANIMFILTER_ONLYICU)==0) {
+ if ((filter_mode & ANIMFILTER_CHANNELS) && (filter_mode & ANIMFILTER_ONLYFCU)==0) {
ale= make_new_animlistelem(achan, ANIMTYPE_FILLIPO, achan, ANIMTYPE_ACHAN);
if (ale) {
}
/* add ipo-curve channels? */
- if (FILTER_IPO_ACHAN(achan) || (filter_mode & ANIMFILTER_ONLYICU)) {
+ if (FILTER_IPO_ACHAN(achan) || (filter_mode & ANIMFILTER_ONLYFCU)) {
/* loop through ipo-curve channels, adding them */
items += animdata_filter_ipocurves(anim_data, achan->ipo, filter_mode, achan, ANIMTYPE_ACHAN, (owned)?(owner):(NULL));
}
/* constraint channels */
if (achan->constraintChannels.first) {
/* include constraint-expand widget? */
- if ( (filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_ONLYICU)
+ if ( (filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_ONLYFCU)
&& !(filter_mode & ANIMFILTER_IPOKEYS) )
{
ale= make_new_animlistelem(achan, ANIMTYPE_FILLCON, achan, ANIMTYPE_ACHAN);
}
/* add constraint channels? */
- if (FILTER_CON_ACHAN(achan) || (filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYICU)) {
+ if (FILTER_CON_ACHAN(achan) || (filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYFCU)) {
/* loop through constraint channels, checking and adding them */
for (conchan=achan->constraintChannels.first; conchan; conchan=conchan->next) {
/* only work with this channel and its subchannels if it is editable */
/* loop over groups */
for (agrp= act->groups.first; agrp; agrp= agrp->next) {
/* add this group as a channel first */
- if (!(filter_mode & ANIMFILTER_ONLYICU) && !(filter_mode & ANIMFILTER_IPOKEYS)) {
+ if (!(filter_mode & ANIMFILTER_ONLYFCU) && !(filter_mode & ANIMFILTER_IPOKEYS)) {
/* check if filtering by selection */
if ( !(filter_mode & ANIMFILTER_SEL) || SEL_AGRP(agrp) ) {
ale= make_new_animlistelem(agrp, ANIMTYPE_GROUP, NULL, ANIMTYPE_NONE);
* - we're interested in keyframes, but not if they appear in selected channels
*/
if ( (!(filter_mode & ANIMFILTER_VISIBLE) || EXPANDED_AGRP(agrp)) ||
- ( ((filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYICU)) &&
+ ( ((filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYFCU)) &&
(!(filter_mode & ANIMFILTER_SEL) || (SEL_AGRP(agrp))) ) )
{
if (!(filter_mode & ANIMFILTER_FOREDIT) || EDITABLE_AGRP(agrp)) {
int items = 0;
/* check if filtering types are appropriate */
- if ( !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU|ANIMFILTER_ACTGROUPED)) )
+ if ( !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYFCU|ANIMFILTER_ACTGROUPED)) )
{
/* special hack for fullscreen area (which must be this one then):
* - we use the curarea->full as screen to get spaces from, since the
int items = 0;
/* include materials-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU))) {
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYFCU))) {
ale= make_new_animlistelem(ob, ANIMTYPE_FILLMATD, base, ANIMTYPE_OBJECT);
if (ale) {
BLI_addtail(anim_data, ale);
}
/* add materials? */
- if (FILTER_MAT_OBJC(ob) || (filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYICU)) {
+ if (FILTER_MAT_OBJC(ob) || (filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYFCU)) {
short a;
/* for each material, either add channels separately, or as ipo-block */
}
/* add material's ipo-curve channels? */
- if ( (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_ONLYICU)) &&
+ if ( (FILTER_MAT_OBJD(ma) || (filter_mode & ANIMFILTER_ONLYFCU)) &&
!(filter_mode & ANIMFILTER_IPOKEYS) )
{
items += animdata_filter_ipocurves(anim_data, ma->ipo, filter_mode, base, ANIMTYPE_OBJECT, (ID *)ma);
}
/* add camera ipo-curve channels? */
- if ( (FILTER_CAM_OBJD(ca) || (filter_mode & ANIMFILTER_ONLYICU)) &&
+ if ( (FILTER_CAM_OBJD(ca) || (filter_mode & ANIMFILTER_ONLYFCU)) &&
!(filter_mode & ANIMFILTER_IPOKEYS) )
{
items += animdata_filter_ipocurves(anim_data, ca->ipo, filter_mode, base, ANIMTYPE_OBJECT, (ID *)ca);
}
/* add lamp ipo-curve channels? */
- if ( (FILTER_LAM_OBJD(la) || (filter_mode & ANIMFILTER_ONLYICU)) &&
+ if ( (FILTER_LAM_OBJD(la) || (filter_mode & ANIMFILTER_ONLYFCU)) &&
!(filter_mode & ANIMFILTER_IPOKEYS) )
{
items += animdata_filter_ipocurves(anim_data, la->ipo, filter_mode, base, ANIMTYPE_OBJECT, (ID *)la);
}
/* add curve ipo-curve channels? */
- if ( (FILTER_CUR_OBJD(cu) || (filter_mode & ANIMFILTER_ONLYICU)) &&
+ if ( (FILTER_CUR_OBJD(cu) || (filter_mode & ANIMFILTER_ONLYFCU)) &&
!(filter_mode & ANIMFILTER_IPOKEYS) )
{
items += animdata_filter_ipocurves(anim_data, cu->ipo, filter_mode, base, ANIMTYPE_OBJECT, (ID *)cu);
int items = 0;
/* add this object as a channel first */
- if (!(filter_mode & ANIMFILTER_ONLYICU) && !(filter_mode & ANIMFILTER_IPOKEYS)) {
+ if (!(filter_mode & ANIMFILTER_ONLYFCU) && !(filter_mode & ANIMFILTER_IPOKEYS)) {
/* check if filtering by selection */
if ( !(filter_mode & ANIMFILTER_SEL) || ((base->flag & SELECT) || (base == sce->basact)) ) {
ale= make_new_animlistelem(base, ANIMTYPE_OBJECT, NULL, ANIMTYPE_NONE);
}
/* if collapsed, don't go any further (unless adding keyframes only) */
- if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU)) )
+ if ( (EXPANDED_OBJC(ob) == 0) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYFCU)) )
return items;
/* IPO? */
}
/* add ipo-curve channels? */
- if ( (FILTER_IPO_OBJC(ob) || (filter_mode & ANIMFILTER_ONLYICU)) &&
+ if ( (FILTER_IPO_OBJC(ob) || (filter_mode & ANIMFILTER_ONLYFCU)) &&
!(filter_mode & ANIMFILTER_IPOKEYS) )
{
items += animdata_filter_ipocurves(anim_data, ob->ipo, filter_mode, base, ANIMTYPE_OBJECT, NULL); // err... why not set ob?
/* Action? */
if ((ob->action) && !(ads->filterflag & ADS_FILTER_NOACTS)) {
/* include animion-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU))) {
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYFCU))) {
ale= make_new_animlistelem(ob->action, ANIMTYPE_FILLACTD, base, ANIMTYPE_OBJECT);
if (ale) {
ale->id= (ID *)ob; // err.... is this a good idea?
/* ShapeKeys? */
if ((key) && !(ads->filterflag & ADS_FILTER_NOSHAPEKEYS)) {
/* include shapekey-expand widget? */
- if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYICU))) {
+ if ((filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & (ANIMFILTER_IPOKEYS|ANIMFILTER_ONLYFCU))) {
ale= make_new_animlistelem(key, ANIMTYPE_DSSKEY, base, ANIMTYPE_OBJECT);
if (ale) {
BLI_addtail(anim_data, ale);
}
/* add channels */
- if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYICU)) {
+ if (FILTER_SKE_OBJD(key) || (filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYFCU)) {
items += animdata_filter_shapekey(anim_data, key, filter_mode, ob, ANIMTYPE_OBJECT);
}
}
bConstraintChannel *conchan;
/* include constraint-expand widget? */
- if ( (filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_ONLYICU)
+ if ( (filter_mode & ANIMFILTER_CHANNELS) && !(filter_mode & ANIMFILTER_ONLYFCU)
&& !(filter_mode & ANIMFILTER_IPOKEYS) )
{
ale= make_new_animlistelem(ob, ANIMTYPE_FILLCOND, base, ANIMTYPE_OBJECT);
}
/* add constraint channels? */
- if (FILTER_CON_OBJC(ob) || (filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYICU)) {
+ if (FILTER_CON_OBJC(ob) || (filter_mode & ANIMFILTER_IPOKEYS) || (filter_mode & ANIMFILTER_ONLYFCU)) {
/* loop through constraint channels, checking and adding them */
for (conchan=ob->constraintChannels.first; conchan; conchan=conchan->next) {
/* only work with this channel and its subchannels if it is editable */
#include "WM_types.h"
#include "ED_anim_api.h"
+#include "ED_keyframing.h" // XXX remove?
#include "ED_markers.h"
#include "ED_screen.h"
WM_operatortype_append(ANIM_OT_previewrange_define);
WM_operatortype_append(ANIM_OT_previewrange_clear);
+
+ // XXX this is used all over... maybe for screen instead?
+ WM_operatortype_append(ANIM_OT_insert_keyframe);
+ WM_operatortype_append(ANIM_OT_delete_keyframe);
}
void ED_keymap_anim(wmWindowManager *wm)
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
+#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_constraint_types.h"
#include "DNA_curve_types.h"
-#include "DNA_ipo_types.h"
+#include "DNA_ipo_types.h" // XXX to be phased out
#include "DNA_key_types.h"
#include "DNA_object_types.h"
#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "BKE_action.h"
-#include "BKE_ipo.h"
+#include "BKE_fcurve.h"
#include "BKE_key.h"
#include "BKE_utildefines.h"
int filter;
/* filter animation data */
- filter= ANIMFILTER_ONLYICU;
+ filter= ANIMFILTER_ONLYFCU;
ANIM_animdata_filter(&anim_data, filter, ac->data, ac->datatype);
/* loop over ipo-curves that are likely to have been edited, and check them */
for (ale= anim_data.first; ale; ale= ale->next) {
- IpoCurve *icu= ale->key_data;
+ FCurve *fcu= ale->key_data;
/* make sure keyframes in IPO-curve are all in order, and handles are in valid positions */
- sort_time_ipocurve(icu);
- testhandles_ipocurve(icu);
+ sort_time_fcurve(fcu);
+ testhandles_fcurve(fcu);
}
/* free temp data */
}
}
-/* --------- */
-
-/* This function is called to calculate the average location of the
- * selected keyframes, and place the current frame at that location.
- *
- * It must be called like so:
- * snap_cfra_ipo_keys(scene, NULL, -1); // initialise the static vars first
- * for (ipo...) snap_cfra_ipo_keys(scene, ipo, 0); // sum up keyframe times
- * snap_cfra_ipo_keys(scene, NULL, 1); // set current frame after taking average
- */
-// XXX this thing needs to be refactored!
-void snap_cfra_ipo_keys(BeztEditData *bed, Ipo *ipo, short mode)
-{
- static int cfra;
- static int tot;
-
- Scene *scene= bed->scene;
- IpoCurve *icu;
- BezTriple *bezt;
- int a;
-
-
- if (mode == -1) {
- /* initialise a new snap-operation */
- cfra= 0;
- tot= 0;
- }
- else if (mode == 1) {
- /* set current frame - using average frame */
- if (tot != 0)
- CFRA = cfra / tot;
- }
- else {
- /* loop through keys in ipo, summing the frame
- * numbers of those that are selected
- */
- if (ipo == NULL)
- return;
-
- for (icu= ipo->curve.first; icu; icu= icu->next) {
- for (a=0, bezt=icu->bezt; a < icu->totvert; a++, bezt++) {
- if (BEZSELECTED(bezt)) {
- cfra += (int)floor(bezt->vec[1][0] + 0.5f);
- tot++;
- }
- }
- }
- }
-}
-
/* ******************************************* */
/* Settings */
icu->ipo= IPO_MIXED;
/* recalculate handles, as some changes may have occurred */
- calchandles_ipocurve(icu);
+ //calchandles_ipocurve(icu); // XXX
}
static short set_bezt_constant(BeztEditData *bed, BezTriple *bezt)
#include "BLI_blenlib.h"
#include "BLI_arithb.h"
+#include "DNA_anim_types.h"
#include "DNA_action_types.h"
#include "DNA_curve_types.h"
-#include "DNA_ipo_types.h"
+#include "DNA_ipo_types.h" // XXX to be removed
#include "DNA_key_types.h"
#include "DNA_object_types.h"
#include "DNA_space_types.h"
#include "DNA_scene_types.h"
#include "BKE_action.h"
-#include "BKE_ipo.h"
+#include "BKE_fcurve.h"
#include "BKE_key.h"
#include "BKE_utildefines.h"
* Not recommended to be used many times successively. For that
* there is delete_ipo_keys().
*/
-void delete_icu_key(IpoCurve *icu, int index, short do_recalc)
+void delete_fcurve_key(FCurve *fcu, int index, short do_recalc)
{
/* firstly check that index is valid */
if (index < 0)
index *= -1;
- if (icu == NULL)
+ if (fcu == NULL)
return;
- if (index >= icu->totvert)
+ if (index >= fcu->totvert)
return;
/* Delete this key */
- memmove(&icu->bezt[index], &icu->bezt[index+1], sizeof(BezTriple)*(icu->totvert-index-1));
- icu->totvert--;
+ memmove(&fcu->bezt[index], &fcu->bezt[index+1], sizeof(BezTriple)*(fcu->totvert-index-1));
+ fcu->totvert--;
/* recalc handles - only if it won't cause problems */
if (do_recalc)
- calchandles_ipocurve(icu);
+ calchandles_fcurve(fcu);
}
+#if 0 // XXX obsolete
/* Delete selected keyframes in given IPO block */
void delete_ipo_keys(Ipo *ipo)
{
}
}
}
+#endif // XXX obsolete
/* ---------------- */
/* **************************************************** */
/* Various Tools */
+// XXX - stub... until keyframing code is fixed...
+static void insert_vert_fcu(FCurve *fcu, float x, float y, short flag)
+{
+}
+
/* Basic IPO-Curve 'cleanup' function that removes 'double points' and unnecessary keyframes on linear-segments only */
-void clean_ipo_curve(IpoCurve *icu, float thresh)
+void clean_fcurve(FCurve *fcu, float thresh)
{
BezTriple *old_bezts, *bezt, *beztn;
BezTriple *lastb;
int totCount, i;
/* check if any points */
- if ((icu == NULL) || (icu->totvert <= 1))
+ if ((fcu == NULL) || (fcu->totvert <= 1))
return;
/* make a copy of the old BezTriples, and clear IPO curve */
- old_bezts = icu->bezt;
- totCount = icu->totvert;
- icu->bezt = NULL;
- icu->totvert = 0;
+ old_bezts = fcu->bezt;
+ totCount = fcu->totvert;
+ fcu->bezt = NULL;
+ fcu->totvert = 0;
/* now insert first keyframe, as it should be ok */
bezt = old_bezts;
- insert_vert_icu(icu, bezt->vec[1][0], bezt->vec[1][1], 0);
+ insert_vert_fcu(fcu, bezt->vec[1][0], bezt->vec[1][1], 0);
/* Loop through BezTriples, comparing them. Skip any that do
* not fit the criteria for "ok" points.
beztn = NULL;
next[0] = next[1] = 0.0f;
}
- lastb= (icu->bezt + (icu->totvert - 1));
+ lastb= (fcu->bezt + (fcu->totvert - 1));
bezt= (old_bezts + i);
/* get references for quicker access */
if (cur[1] > next[1]) {
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe */
- insert_vert_icu(icu, cur[0], cur[1], 0);
+ insert_vert_fcu(fcu, cur[0], cur[1], 0);
}
}
}
/* only add if values are a considerable distance apart */
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe */
- insert_vert_icu(icu, cur[0], cur[1], 0);
+ insert_vert_fcu(fcu, cur[0], cur[1], 0);
}
}
}
/* does current have same value as previous and next? */
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe*/
- insert_vert_icu(icu, cur[0], cur[1], 0);
+ insert_vert_fcu(fcu, cur[0], cur[1], 0);
}
else if (IS_EQT(cur[1], next[1], thresh) == 0) {
/* add new keyframe */
- insert_vert_icu(icu, cur[0], cur[1], 0);
+ insert_vert_fcu(fcu, cur[0], cur[1], 0);
}
}
else {
/* add if value doesn't equal that of previous */
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe */
- insert_vert_icu(icu, cur[0], cur[1], 0);
+ insert_vert_fcu(fcu, cur[0], cur[1], 0);
}
}
}
} tSmooth_Bezt;
/* Use a weighted moving-means method to reduce intensity of fluctuations */
-//mode= pupmenu("Smooth IPO%t|Tweak Points%x1|Flatten Handles%x2");
-void smooth_ipo_curve(IpoCurve *icu, short mode)
+//mode= pupmenu("Smooth F-Curve%t|Tweak Points%x1|Flatten Handles%x2");
+void smooth_fcurve(FCurve *fcu, short mode)
{
BezTriple *bezt;
int i, x, totSel = 0;
/* first loop through - count how many verts are selected, and fix up handles
* this is done for both modes
*/
- bezt= icu->bezt;
- for (i=0; i < icu->totvert; i++, bezt++) {
+ bezt= fcu->bezt;
+ for (i=0; i < fcu->totvert; i++, bezt++) {
if (BEZSELECTED(bezt)) {
/* line point's handles up with point's vertical position */
bezt->vec[0][1]= bezt->vec[2][1]= bezt->vec[1][1];
tsb= tarray= MEM_callocN(totSel*sizeof(tSmooth_Bezt), "tSmooth_Bezt Array");
/* populate tarray with data of selected points */
- bezt= icu->bezt;
- for (i=0, x=0; (i < icu->totvert) && (x < totSel); i++, bezt++) {
+ bezt= fcu->bezt;
+ for (i=0, x=0; (i < fcu->totvert) && (x < totSel); i++, bezt++) {
if (BEZSELECTED(bezt)) {
/* tsb simply needs pointer to vec, and index */
tsb->h1 = &bezt->vec[0][1];
}
/* recalculate handles */
- calchandles_ipocurve(icu);
+ calchandles_fcurve(fcu);
}
/* **************************************************** */
-/**
- * $Id: keyframing.c 17745 2008-12-08 09:16:09Z aligorith $
- *
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * The Original Code is Copyright (C) 2008, Blender Foundation
- * This is a new part of Blender (with some old code)
- *
- * Contributor(s): Joshua Leung
- *
- * ***** END GPL LICENSE BLOCK *****
+/* Testing code for 2.5 animation system
+ * Copyright 2009, Joshua Leung
*/
-
-
-
+
#include <stdio.h>
#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
#include <math.h>
#include <float.h>
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
#include "MEM_guardedalloc.h"
-#include "BLI_arithb.h"
#include "BLI_blenlib.h"
+#include "BLI_arithb.h"
#include "BLI_dynstr.h"
-#include "DNA_listBase.h"
-#include "DNA_ID.h"
+#include "DNA_anim_types.h"
#include "DNA_action_types.h"
-#include "DNA_armature_types.h"
-#include "DNA_camera_types.h"
#include "DNA_constraint_types.h"
-#include "DNA_curve_types.h"
-#include "DNA_ipo_types.h"
#include "DNA_key_types.h"
-#include "DNA_lamp_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_fluidsim.h"
-#include "DNA_particle_types.h"
#include "DNA_material_types.h"
-#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
-#include "DNA_sequence_types.h"
-#include "DNA_space_types.h"
-#include "DNA_texture_types.h"
#include "DNA_userdef_types.h"
-#include "DNA_vec_types.h"
-#include "DNA_view3d_types.h"
-#include "DNA_world_types.h"
#include "DNA_windowmanager_types.h"
-#include "BKE_context.h"
-#include "BKE_utildefines.h"
-#include "BKE_blender.h"
+#include "BKE_animsys.h"
#include "BKE_action.h"
-#include "BKE_armature.h"
-#include "BKE_constraint.h"
-#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
-#include "BKE_ipo.h"
+#include "BKE_fcurve.h"
+#include "BKE_utildefines.h"
+#include "BKE_context.h"
#include "BKE_key.h"
-#include "BKE_object.h"
-#include "BKE_particle.h"
#include "BKE_material.h"
-#include "BKE_modifier.h"
#include "ED_anim_api.h"
#include "ED_keyframing.h"
#include "ED_keyframes_edit.h"
+#include "ED_screen.h"
+#include "ED_util.h"
#include "WM_api.h"
#include "WM_types.h"
-#if 0 // XXX resolve these old dependencies!
- #include "BIF_butspace.h"
- #include "BIF_editaction.h"
- #include "BIF_editkey.h"
- #include "BIF_interface.h"
- #include "BIF_mywindow.h"
- #include "BIF_poseobject.h"
- #include "BIF_screen.h"
- #include "BIF_space.h"
- #include "BIF_toolbox.h"
- #include "BIF_toets.h"
-
- #include "BSE_editipo.h"
- #include "BSE_node.h"
- #include "BSE_time.h"
- #include "BSE_view.h"
-
- #include "blendef.h"
-
- #include "PIL_time.h" /* sleep */
- #include "mydevice.h"
-#endif // XXX resolve these old dependencies!
-
-/* ****************************************** */
-
-/* note for Joshua: add_ipo() wants scene pointer to init the view2d 'cur' for
- the ipo data, which restores views. Needs to be resolved nicer? */
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_types.h"
/* ************************************************** */
/* LOCAL TYPES AND DEFINES */
/* general data/destination-source settings */
ID *id; /* id-block this comes from */
- char *actname; /* name of action channel */
- char *constname; /* name of constraint channel */
+ char *rna_path; /* base path to use */ // xxx.... maybe we don't need this?
- /* general destination source settings */
- Ipo *ipo; /* ipo-block that id-block has (optional) */
- bAction *act; /* action-block that id-block has (optional) */
-
- /* pose-level settings */
- bPoseChannel *pchan; /* pose channel */
-
- /* buttons-window settings */
- int map; /* offset to apply to certain adrcodes */
+ /* specific cases */
+ bPoseChannel *pchan; /* only needed when doing recalcs... */
} bCommonKeySrc;
/* -------------- Keying Sets ------------------- */
-/* storage for iterator for looping over keyingset channels */
-typedef struct bKS_AdrcodeGetter {
- struct bKeyingSet *ks; /* keyingset this applies to */
- struct bCommonKeySrc *cks; /* data to insert/delete keyframes... */
-
- short index; /* index of current channel to resume from */
- short tot; /* index after which we start returning from some special collection */
-} bKS_AdrcodeGetter;
-
-/* flags to look out for in keyingset channels... */
-#define KAG_CHAN_EXTEND (-1)
-
+#if 0 // XXX I'm not sure how these will work for now...
/* keying set - a set of channels that will be keyframed together */
// TODO: move this to a header to allow custom sets someday?
short (*include_cb)(struct bKeyingSet *, const char *);
char name[48]; /* name of keyingset */
- int blocktype; /* blocktype that all channels belong to */ // in future, this may be eliminated
+ int blocktype; /* nearest ID-blocktype to where data can be found */
short flag; /* flags to use when setting keyframes */
short chan_num; /* number of channels to insert keyframe in */
- short adrcodes[32]; /* adrcodes for channels to insert keys for (ideally would be variable-len, but limit of 32 will suffice) */
+ char (*paths)[256]; /* adrcodes for channels to insert keys for (ideally would be variable-len, but limit of 32 will suffice) */
} bKeyingSet;
/* keying set context - an array of keying sets and the number of them */
int tot; /* number of keyingsets in */
} bKeyingContext;
+#endif
-/* ************************************************** */
-/* IPO DATA VERIFICATION */
-// XXX these will need to be modified for use with RNA-IPO...
-
-/* depending type, it returns ipo, if needed it creates one */
-/* returns either action ipo or "real" ipo */
-/* arguments define full context;
- - *from has to be set always, to Object in case of Actions
- - blocktype defines available channels of Ipo struct (blocktype ID_OB can be in action too)
- - if actname, use this to locate actionchannel, and optional constname
- - if bonename, the constname is the ipo to the constraint
-*/
-
-/* note: check header_ipo.c, spaceipo_assign_ipo() too */
-Ipo *verify_ipo(ID *from, short blocktype, char actname[], char constname[], char bonename[], short add)
-{
- /* lib-linked data is not appropriate here */
- if ((from==NULL) || (from->lib))
- return NULL;
-
- /* first check action ipos */
- if (actname && actname[0]) {
- Object *ob= (Object *)from;
- bActionChannel *achan;
-
- if (GS(from->name)!=ID_OB) {
- printf("called ipo system for action with wrong base pointer\n");
- return NULL;
- }
-
- if ((ob->action==NULL) && (add))
- ob->action= add_empty_action("Action");
-
- if (add)
- achan= verify_action_channel(ob->action, actname);
- else
- achan= get_action_channel(ob->action, actname);
-
- if (achan) {
- /* automatically assign achan to act-group based on pchan's grouping */
- //if ((blocktype == ID_PO) && (add))
- // verify_pchan2achan_grouping(ob->action, ob->pose, actname);
-
- /* constraint exception */
- if (blocktype==ID_CO) {
- bConstraintChannel *conchan;
-
- if (add)
- conchan= verify_constraint_channel(&achan->constraintChannels, constname);
- else
- conchan= get_constraint_channel(&achan->constraintChannels, constname);
-
- if (conchan) {
- if ((conchan->ipo==NULL) && (add))
- conchan->ipo= add_ipo(NULL, "CoIpo", ID_CO);
- return conchan->ipo;
- }
- }
- else {
- if ((achan->ipo==NULL) && (add))
- achan->ipo= add_ipo(NULL, "ActIpo", blocktype);
- return achan->ipo;
- }
- }
- }
- else {
- switch (GS(from->name)) {
- case ID_OB:
- {
- Object *ob= (Object *)from;
-
- /* constraint exception */
- if (blocktype==ID_CO) {
- /* check the local constraint ipo */
- if (bonename && bonename[0] && ob->pose) {
- bPoseChannel *pchan= get_pose_channel(ob->pose, bonename);
- bConstraint *con;
-
- for (con= pchan->constraints.first; con; con= con->next) {
- if (strcmp(con->name, constname)==0)
- break;
- }
-
- if (con) {
- if ((con->ipo==NULL) && (add))
- con->ipo= add_ipo(NULL, "CoIpo", ID_CO);
- return con->ipo;
- }
- }
- else { /* the actionchannel */
- bConstraintChannel *conchan;
-
- if (add)
- conchan= verify_constraint_channel(&ob->constraintChannels, constname);
- else
- conchan= get_constraint_channel(&ob->constraintChannels, constname);
-
- if (conchan) {
- if ((conchan->ipo==NULL) && (add))
- conchan->ipo= add_ipo(NULL, "CoIpo", ID_CO);
- return conchan->ipo;
- }
- }
- }
- else if (blocktype==ID_OB) {
- if ((ob->ipo==NULL) && (add))
- ob->ipo= add_ipo(NULL, "ObIpo", ID_OB);
- return ob->ipo;
- }
- else if (blocktype==ID_KE) {
- Key *key= ob_get_key((Object *)from);
-
- if (key) {
- if ((key->ipo==NULL) && (add))
- key->ipo= add_ipo(NULL, "KeyIpo", ID_KE);
- return key->ipo;
- }
- return NULL;
- }
- else if (blocktype== ID_FLUIDSIM) {
- Object *ob= (Object *)from;
-
- FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim);
- if(fluidmd) {
- FluidsimSettings *fss= fluidmd->fss;
-
- if ((fss->ipo==NULL) && (add))
- fss->ipo= add_ipo(NULL, "FluidsimIpo", ID_FLUIDSIM);
- return fss->ipo;
- }
- }
- else if(blocktype== ID_PA) {
- Object *ob= (Object *)from;
- ParticleSystem *psys= psys_get_current(ob);
-
- if (psys) {
- if ((psys->part->ipo==NULL) && (add))
- psys->part->ipo= add_ipo(NULL, "ParticleIpo", ID_PA);
- return psys->part->ipo;
- }
- return NULL;
- }
- }
- break;
- case ID_MA:
- {
- Material *ma= (Material *)from;
-
- if ((ma->ipo==NULL) && (add))
- ma->ipo= add_ipo(NULL, "MatIpo", ID_MA);
- return ma->ipo;
- }
- break;
- case ID_TE:
- {
- Tex *tex= (Tex *)from;
-
- if ((tex->ipo==NULL) && (add))
- tex->ipo= add_ipo(NULL, "TexIpo", ID_TE);
- return tex->ipo;
- }
- break;
- case ID_SEQ:
- {
- Sequence *seq= (Sequence *)from; /* note, sequence is mimicing Id */
-
- if ((seq->ipo==NULL) && (add))
- seq->ipo= add_ipo(NULL, "SeqIpo", ID_SEQ);
- //update_seq_ipo_rect(seq); // XXX
- return seq->ipo;
- }
- break;
- case ID_CU:
- {
- Curve *cu= (Curve *)from;
-
- if ((cu->ipo==NULL) && (add))
- cu->ipo= add_ipo(NULL, "CuIpo", ID_CU);
- return cu->ipo;
- }
- break;
- case ID_WO:
- {
- World *wo= (World *)from;
-
- if ((wo->ipo==NULL) && (add))
- wo->ipo= add_ipo(NULL, "WoIpo", ID_WO);
- return wo->ipo;
- }
- break;
- case ID_LA:
- {
- Lamp *la= (Lamp *)from;
-
- if ((la->ipo==NULL) && (add))
- la->ipo= add_ipo(NULL, "LaIpo", ID_LA);
- return la->ipo;
- }
- break;
- case ID_CA:
- {
- Camera *ca= (Camera *)from;
-
- if ((ca->ipo==NULL) && (add))
- ca->ipo= add_ipo(NULL, "CaIpo", ID_CA);
- return ca->ipo;
- }
- break;
- case ID_SO:
- {
-#if 0 // depreceated
- bSound *snd= (bSound *)from;
-
- if ((snd->ipo==NULL) && (add))
- snd->ipo= add_ipo(NULL, "SndIpo", ID_SO);
- return snd->ipo;
-#endif // depreceated
- }
- break;
- }
- }
-
- return NULL;
-}
+/* ******************************************* */
+/* Animation Data Validation */
-/* Returns and creates
- * Make sure functions check for NULL or they will crash!
+/* Get (or add relevant data to be able to do so) F-Curve from the Active Action,
+ * for the given Animation Data block
*/
-IpoCurve *verify_ipocurve(ID *from, short blocktype, char actname[], char constname[], char bonename[], int adrcode, short add)
+// TODO: should we check if path is valid? For now, assume that it's already set OK by caller...
+FCurve *verify_fcurve (AnimData *adt, const char rna_path[], const int array_index, short add)
{
- Ipo *ipo;
- IpoCurve *icu= NULL;
+ nAction *act;
+ FCurve *fcu;
- /* return 0 if lib */
- /* creates ipo too (if add) */
- ipo= verify_ipo(from, blocktype, actname, constname, bonename, add);
+ /* sanity checks */
+ if ELEM(NULL, adt, rna_path)
+ return NULL;
+
+ /* init action if none available yet */
+ // TODO: need some wizardry to handle NLA stuff correct
+ if ((adt->action == NULL) && (add))
+ adt->action= add_empty_action("Action");
+ act= adt->action;
+
+ /* try to find f-curve matching for this setting
+ * - add if not found and allowed to add one
+ * TODO: add auto-grouping support? how this works will need to be resolved
+ */
+ if (act)
+ fcu= list_find_fcurve(&act->curves, rna_path, array_index);
+ else
+ fcu= NULL;
- if ((ipo) && (ipo->id.lib==NULL) && (from->lib==NULL)) {
- /* try to find matching curve */
- icu= find_ipocurve(ipo, adrcode);
+ if ((fcu == NULL) && (add)) {
+ /* use default settings */
+ fcu= MEM_callocN(sizeof(FCurve), "FCurve");
- /* make a new one if none found (and can add) */
- if ((icu==NULL) && (add)) {
- icu= MEM_callocN(sizeof(IpoCurve), "ipocurve");
-
- /* set default settings */
- icu->flag |= (IPO_VISIBLE|IPO_AUTO_HORIZ);
- if (ipo->curve.first==NULL)
- icu->flag |= IPO_ACTIVE; /* first one added active */
-
- icu->blocktype= blocktype;
- icu->adrcode= adrcode;
+ fcu->flag |= (FCURVE_VISIBLE|FCURVE_AUTO_HANDLES);
+ if (act->curves.first==NULL)
+ fcu->flag |= FCURVE_ACTIVE; /* first one added active */
- set_icu_vars(icu);
-
- /* default curve interpolation - from userpref */
- icu->ipo= U.ipo_new;
-
- /* add curve to IPO-block */
- BLI_addtail(&ipo->curve, icu);
-
- /* special type-dependent stuff */
- switch (GS(from->name)) {
- case ID_SEQ: {
- //Sequence *seq= (Sequence *)from;
-
- //update_seq_icu_rects(seq); // XXX
- break;
- }
- }
- }
+ /* store path - make copy, and store that */
+ 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...
}
- /* return ipo-curve */
- return icu;
+ /* return the F-Curve */
+ return fcu;
}
/* ************************************************** */
return start;
}
-/* This function adds a given BezTriple to an IPO-Curve. It will allocate
+/* This function adds a given BezTriple to an F-Curve. It will allocate
* memory for the array if needed, and will insert the BezTriple into a
* suitable place in chronological order.
*
- * NOTE: any recalculate of the IPO-Curve that needs to be done will need to
+ * NOTE: any recalculate of the F-Curve that needs to be done will need to
* be done by the caller.
*/
-int insert_bezt_icu (IpoCurve *icu, BezTriple *bezt)
+int insert_bezt_fcurve (FCurve *fcu, BezTriple *bezt)
{
BezTriple *newb;
int i= 0;
- if (icu->bezt) {
+ if (fcu->bezt) {
short replace = -1;
- i = binarysearch_bezt_index(icu->bezt, bezt->vec[1][0], icu->totvert, &replace);
+ i = binarysearch_bezt_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace);
if (replace) {
/* sanity check: 'i' may in rare cases exceed arraylen */
// FIXME: do not overwrite handletype if just replacing...?
- if ((i >= 0) && (i < icu->totvert))
- *(icu->bezt + i) = *bezt;
+ if ((i >= 0) && (i < fcu->totvert))
+ *(fcu->bezt + i) = *bezt;
}
else {
/* add new */
- newb= MEM_callocN((icu->totvert+1)*sizeof(BezTriple), "beztriple");
+ newb= MEM_callocN((fcu->totvert+1)*sizeof(BezTriple), "beztriple");
/* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */
if (i > 0)
- memcpy(newb, icu->bezt, i*sizeof(BezTriple));
+ memcpy(newb, fcu->bezt, i*sizeof(BezTriple));
/* add beztriple to paste at index i */
*(newb + i)= *bezt;
/* add the beztriples that occur after the beztriple to be pasted (originally in icu) */
- if (i < icu->totvert)
- memcpy(newb+i+1, icu->bezt+i, (icu->totvert-i)*sizeof(BezTriple));
+ if (i < fcu->totvert)
+ memcpy(newb+i+1, fcu->bezt+i, (fcu->totvert-i)*sizeof(BezTriple));
/* replace (+ free) old with new */
- MEM_freeN(icu->bezt);
- icu->bezt= newb;
+ MEM_freeN(fcu->bezt);
+ fcu->bezt= newb;
- icu->totvert++;
+ fcu->totvert++;
}
}
else {
- icu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple");
- *(icu->bezt)= *bezt;
- icu->totvert= 1;
+ // TODO: need to check for old sample-data now...
+ fcu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple");
+ *(fcu->bezt)= *bezt;
+ fcu->totvert= 1;
}
*
* 'fast' - is only for the python API where importing BVH's would take an extreamly long time.
*/
-void insert_vert_icu (IpoCurve *icu, float x, float y, short fast)
+void insert_vert_fcurve (FCurve *fcu, float x, float y, short fast)
{
BezTriple beztr;
- int a, h1, h2;
+ int a;
/* set all three points, for nicer start position */
memset(&beztr, 0, sizeof(BezTriple));
beztr.vec[1][1]= y;
beztr.vec[2][0]= x;
beztr.vec[2][1]= y;
- beztr.hide= IPO_BEZ;
+ beztr.ipo= U.ipo_new; /* use default interpolation mode here... */
beztr.f1= beztr.f2= beztr.f3= SELECT;
- beztr.h1= beztr.h2= HD_AUTO;
+ beztr.h1= beztr.h2= HD_AUTO; // XXX what about when we replace an old one?
/* add temp beztriple to keyframes */
- a= insert_bezt_icu(icu, &beztr);
+ a= insert_bezt_fcurve(fcu, &beztr);
/* what if 'a' is a negative index?
* for now, just exit to prevent any segfaults
* - this is a hack to make importers faster
* - we may calculate twice (see editipo_changed(), due to autohandle needing two calculations)
*/
- if (!fast) calchandles_ipocurve(icu);
+ if (!fast) calchandles_fcurve(fcu);
/* set handletype and interpolation */
- if (icu->totvert > 2) {
- BezTriple *bezt= (icu->bezt + a);
+ if (fcu->totvert > 2) {
+ BezTriple *bezt= (fcu->bezt + a);
+ short h1, h2;
/* set handles (autohandles by default) */
h1= h2= HD_AUTO;
if (a > 0) h1= (bezt-1)->h2;
- if (a < icu->totvert-1) h2= (bezt+1)->h1;
+ if (a < fcu->totvert-1) h2= (bezt+1)->h1;
bezt->h1= h1;
bezt->h2= h2;
- /* set interpolation (if curve is using IPO_MIXED, then take from previous) */
- if (icu->ipo == IPO_MIXED) {
- if (a > 0) bezt->ipo= (bezt-1)->ipo;
- else if (a < icu->totvert-1) bezt->ipo= (bezt+1)->ipo;
- }
- else
- bezt->ipo= icu->ipo;
+ /* set interpolation from previous (if available) */
+ if (a > 0) bezt->ipo= (bezt-1)->ipo;
+ else if (a < fcu->totvert-1) bezt->ipo= (bezt+1)->ipo;
/* don't recalculate handles if fast is set
* - this is a hack to make importers faster
* - we may calculate twice (see editipo_changed(), due to autohandle needing two calculations)
*/
- if (!fast) calchandles_ipocurve(icu);
- }
- else {
- BezTriple *bezt= (icu->bezt + a);
-
- /* set interpolation directly from ipo-curve */
- bezt->ipo= icu->ipo;
- }
-}
-
-
-/* ------------------- Get Data ------------------------ */
-
-/* Get pointer to use to get values from */
-// FIXME: this should not be possible with Data-API
-static void *get_context_ipo_poin (ID *id, int blocktype, char *actname, char *constname, IpoCurve *icu, int *vartype)
-{
- switch (blocktype) {
- case ID_PO: /* posechannel */
- if (GS(id->name)==ID_OB) {
- Object *ob= (Object *)id;
- bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
-
- if (pchan) {
- if (ELEM3(icu->adrcode, AC_EUL_X, AC_EUL_Y, AC_EUL_Z))
- *vartype= IPO_FLOAT_DEGR;
- else
- *vartype= IPO_FLOAT;
- return get_pchan_ipo_poin(pchan, icu->adrcode);
- }
- }
- break;
-
- case ID_CO: /* constraint */
- if ((GS(id->name)==ID_OB) && (constname && constname[0])) {
- Object *ob= (Object *)id;
- bConstraint *con;
-
- /* assume that we only want the influence (as only used for Constraint Channels) */
- if ((ob->ipoflag & OB_ACTION_OB) && !strcmp(actname, "Object")) {
- for (con= ob->constraints.first; con; con= con->next) {
- if (strcmp(constname, con->name)==0) {
- *vartype= IPO_FLOAT;
- return &con->enforce;
- }
- }
- }
- else if (ob->pose) {
- bPoseChannel *pchan= get_pose_channel(ob->pose, actname);
-
- if (pchan) {
- for (con= pchan->constraints.first; con; con= con->next) {
- if (strcmp(constname, con->name)==0) {
- *vartype= IPO_FLOAT;
- return &con->enforce;
- }
- }
- }
-