Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/action.c')
-rw-r--r--source/blender/blenkernel/intern/action.c871
1 files changed, 489 insertions, 382 deletions
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index e0afdec5e23..d54bc749b71 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -35,16 +35,17 @@
#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 "DNA_scene_types.h"
+#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_anim.h"
#include "BKE_armature.h"
@@ -52,7 +53,7 @@
#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"
@@ -64,7 +65,10 @@
#include "BLI_blenlib.h"
#include "BLI_ghash.h"
-#include "nla.h"
+#include "RNA_access.h"
+#include "RNA_types.h"
+
+//XXX #include "nla.h"
/* *********************** NOTE ON POSE AND ACTION **********************
@@ -81,52 +85,34 @@
/* ***************** Library data level operations on action ************** */
-static void make_local_action_channels(bAction *act)
+bAction *add_empty_action(const char name[])
{
- 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);
- }
- }
- }
- }
-}
+ bAction *act;
+
+ act= alloc_libblock(&G.main->action, ID_AC, name);
+ act->id.flag |= LIB_FAKEUSER; // XXX this is nasty for new users... maybe we don't want this anymore
+ act->id.us++;
+
+ return act;
+}
+// does copy_fcurve...
void make_local_action(bAction *act)
{
- Object *ob;
+ // Object *ob;
bAction *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) {
@@ -135,17 +121,19 @@ void make_local_action(bAction *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) {
@@ -158,24 +146,20 @@ void make_local_action(bAction *act)
}
ob= ob->id.next;
}
+#endif // XXX old animation system
}
}
void free_action (bAction *act)
{
- bActionChannel *chan;
+ /* 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 */
+ free_fcurves(&act->curves);
- if (act->chanbase.first)
- BLI_freelistN(&act->chanbase);
-
/* Free groups */
if (act->groups.first)
BLI_freelistN(&act->groups);
@@ -188,42 +172,237 @@ void free_action (bAction *act)
bAction *copy_action (bAction *src)
{
bAction *dst = NULL;
- bActionChannel *dchan, *schan;
bActionGroup *dgrp, *sgrp;
+ FCurve *dfcu, *sfcu;
- if (!src) return NULL;
-
+ if (src == NULL)
+ return NULL;
dst= copy_libblock(src);
- duplicatelist(&(dst->chanbase), &(src->chanbase));
- duplicatelist(&(dst->groups), &(src->groups));
- duplicatelist(&(dst->markers), &(src->markers));
+ /* duplicate the lists of groups and markers */
+ BLI_duplicatelist(&dst->groups, &src->groups);
+ BLI_duplicatelist(&dst->markers, &src->markers);
+
+ /* copy F-Curves, fixing up the links as we go */
+ dst->curves.first= dst->curves.last= NULL;
- for (dchan=dst->chanbase.first, schan=src->chanbase.first; dchan; dchan=dchan->next, schan=schan->next) {
+ for (sfcu= src->curves.first; sfcu; sfcu= sfcu->next) {
+ /* duplicate F-Curve */
+ dfcu= copy_fcurve(sfcu);
+ BLI_addtail(&dst->curves, dfcu);
+
+ /* fix group links (kindof bad list-in-list search, but this is the most reliable way) */
for (dgrp=dst->groups.first, sgrp=src->groups.first; dgrp && sgrp; dgrp=dgrp->next, sgrp=sgrp->next) {
- if (dchan->grp == sgrp) {
- dchan->grp= dgrp;
+ if (sfcu->grp == sgrp) {
+ dfcu->grp= dgrp;
- if (dgrp->channels.first == schan)
- dgrp->channels.first= dchan;
- if (dgrp->channels.last == schan)
- dgrp->channels.last= dchan;
+ if (dgrp->channels.first == sfcu)
+ dgrp->channels.first= dfcu;
+ if (dgrp->channels.last == sfcu)
+ dgrp->channels.last= dfcu;
break;
}
}
-
- dchan->ipo = copy_ipo(dchan->ipo);
- copy_constraint_channels(&dchan->constraintChannels, &schan->constraintChannels);
}
- 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;
}
+/* Get the active action-group for an Action */
+bActionGroup *get_active_actiongroup (bAction *act)
+{
+ bActionGroup *agrp= NULL;
+
+ if (act && act->groups.first) {
+ for (agrp= act->groups.first; agrp; agrp= agrp->next) {
+ if (agrp->flag & AGRP_ACTIVE)
+ break;
+ }
+ }
+
+ return agrp;
+}
+
+/* Make the given Action-Group the active one */
+void set_active_action_group (bAction *act, bActionGroup *agrp, short select)
+{
+ bActionGroup *grp;
+
+ /* sanity checks */
+ if (act == NULL)
+ return;
+
+ /* Deactive all others */
+ for (grp= act->groups.first; grp; grp= grp->next) {
+ if ((grp==agrp) && (select))
+ grp->flag |= AGRP_ACTIVE;
+ else
+ grp->flag &= ~AGRP_ACTIVE;
+ }
+}
+
+/* Add given channel into (active) group
+ * - assumes that channel is not linked to anything anymore
+ * - always adds at the end of the group
+ */
+void action_groups_add_channel (bAction *act, bActionGroup *agrp, FCurve *fcurve)
+{
+ FCurve *fcu;
+ short done=0;
+
+ /* sanity checks */
+ if (ELEM3(NULL, act, agrp, fcurve))
+ return;
+
+ /* if no channels, just add to two lists at the same time */
+ if (act->curves.first == NULL) {
+ fcurve->next = fcurve->prev = NULL;
+
+ agrp->channels.first = agrp->channels.last = fcurve;
+ act->curves.first = act->curves.last = fcurve;
+
+ fcurve->grp= agrp;
+ return;
+ }
+
+ /* try to find a channel to slot this in before/after */
+ for (fcu= act->curves.first; fcu; fcu= fcu->next) {
+ /* if channel has no group, then we have ungrouped channels, which should always occur after groups */
+ if (fcu->grp == NULL) {
+ BLI_insertlinkbefore(&act->curves, fcu, fcurve);
+
+ if (agrp->channels.first == NULL)
+ agrp->channels.first= fcurve;
+ agrp->channels.last= fcurve;
+
+ done= 1;
+ break;
+ }
+
+ /* if channel has group after current, we can now insert (otherwise we have gone too far) */
+ else if (fcu->grp == agrp->next) {
+ BLI_insertlinkbefore(&act->curves, fcu, fcurve);
+
+ if (agrp->channels.first == NULL)
+ agrp->channels.first= fcurve;
+ agrp->channels.last= fcurve;
+
+ done= 1;
+ break;
+ }
+
+ /* if channel has group we're targeting, check whether it is the last one of these */
+ else if (fcu->grp == agrp) {
+ if ((fcu->next) && (fcu->next->grp != agrp)) {
+ BLI_insertlinkafter(&act->curves, fcu, fcurve);
+ agrp->channels.last= fcurve;
+ done= 1;
+ break;
+ }
+ else if (fcu->next == NULL) {
+ BLI_addtail(&act->curves, fcurve);
+ agrp->channels.last= fcurve;
+ done= 1;
+ break;
+ }
+ }
+
+ /* if channel has group before target, check whether the next one is something after target */
+ else if (fcu->grp == agrp->prev) {
+ if (fcu->next) {
+ if ((fcu->next->grp != fcu->grp) && (fcu->next->grp != agrp)) {
+ BLI_insertlinkafter(&act->curves, fcu, fcurve);
+
+ agrp->channels.first= fcurve;
+ agrp->channels.last= fcurve;
+
+ done= 1;
+ break;
+ }
+ }
+ else {
+ BLI_insertlinkafter(&act->curves, fcu, fcurve);
+
+ agrp->channels.first= fcurve;
+ agrp->channels.last= fcurve;
+
+ done= 1;
+ break;
+ }
+ }
+ }
+
+ /* only if added, set channel as belonging to this group */
+ if (done) {
+ //printf("FCurve added to group \n");
+ fcurve->grp= agrp;
+ }
+ else {
+ printf("Error: FCurve '%s' couldn't be added to Group '%s' \n", fcurve->rna_path, agrp->name);
+ BLI_addtail(&act->curves, fcurve);
+ }
+}
+
+/* Remove the given channel from all groups */
+void action_groups_remove_channel (bAction *act, FCurve *fcu)
+{
+ /* sanity checks */
+ if (ELEM(NULL, act, fcu))
+ return;
+
+ /* check if any group used this directly */
+ if (fcu->grp) {
+ bActionGroup *agrp= fcu->grp;
+
+ if (agrp->channels.first == agrp->channels.last) {
+ if (agrp->channels.first == fcu) {
+ agrp->channels.first= NULL;
+ agrp->channels.last= NULL;
+ }
+ }
+ else if (agrp->channels.first == fcu) {
+ if ((fcu->next) && (fcu->next->grp==agrp))
+ agrp->channels.first= fcu->next;
+ else
+ agrp->channels.first= NULL;
+ }
+ else if (agrp->channels.last == fcu) {
+ if ((fcu->prev) && (fcu->prev->grp==agrp))
+ agrp->channels.last= fcu->prev;
+ else
+ agrp->channels.last= NULL;
+ }
+
+ fcu->grp= NULL;
+ }
+
+ /* now just remove from list */
+ BLI_remlink(&act->curves, fcu);
+}
+
+/* Find a group with the given name */
+bActionGroup *action_groups_find_named (bAction *act, const char name[])
+{
+ bActionGroup *grp;
+
+ /* sanity checks */
+ if (ELEM3(NULL, act, act->groups.first, name) || (name[0] == 0))
+ return NULL;
+
+ /* do string comparisons */
+ for (grp= act->groups.first; grp; grp= grp->next) {
+ if (strcmp(grp->name, name) == 0)
+ return grp;
+ }
+
+ /* not found */
+ return NULL;
+}
/* ************************ Pose channels *************** */
@@ -232,12 +411,13 @@ bPoseChannel *get_pose_channel(const bPose *pose, const char *name)
{
bPoseChannel *chan;
- if(pose==NULL) return NULL;
+ if (pose==NULL) return NULL;
for (chan=pose->chanbase.first; chan; chan=chan->next) {
- if(chan->name[0] == name[0])
+ if (chan->name[0] == name[0]) {
if (!strcmp (chan->name, name))
return chan;
+ }
}
return NULL;
@@ -249,11 +429,10 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name)
{
bPoseChannel *chan;
- if (!pose) {
+ if (pose == NULL)
return NULL;
- }
- /* See if this channel exists */
+ /* See if this channel exists */
for (chan=pose->chanbase.first; chan; chan=chan->next) {
if (!strcmp (name, chan->name))
return chan;
@@ -262,10 +441,10 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name)
/* If not, create it and add it */
chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel");
- strncpy (chan->name, name, 31);
+ strncpy(chan->name, name, 31);
/* init vars to prevent math errors */
- chan->quat[0] = 1.0F;
- chan->size[0] = chan->size[1] = chan->size[2] = 1.0F;
+ chan->quat[0] = 1.0f;
+ chan->size[0] = chan->size[1] = chan->size[2] = 1.0f;
chan->limitmin[0]= chan->limitmin[1]= chan->limitmin[2]= -180.0f;
chan->limitmax[0]= chan->limitmax[1]= chan->limitmax[2]= 180.0f;
@@ -273,14 +452,32 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name)
Mat4One(chan->constinv);
- BLI_addtail (&pose->chanbase, chan);
+ BLI_addtail(&pose->chanbase, chan);
return chan;
}
+/* Find the active posechannel for an object (we can't just use pose, as layer info is in armature) */
+bPoseChannel *get_active_posechannel (Object *ob)
+{
+ bArmature *arm= (ob) ? ob->data : NULL;
+ bPoseChannel *pchan;
+
+ if ELEM3(NULL, ob, ob->pose, arm)
+ return NULL;
+
+ /* find active */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ((pchan->bone) && (pchan->bone->flag & BONE_ACTIVE) && (pchan->bone->layer & arm->layer))
+ return pchan;
+ }
+
+ return NULL;
+}
+
/* dst should be freed already, makes entire duplicate */
-void copy_pose(bPose **dst, bPose *src, int copycon)
+void copy_pose (bPose **dst, bPose *src, int copycon)
{
bPose *outPose;
bPoseChannel *pchan;
@@ -299,7 +496,7 @@ void copy_pose(bPose **dst, bPose *src, int copycon)
outPose= MEM_callocN(sizeof(bPose), "pose");
- duplicatelist(&outPose->chanbase, &src->chanbase);
+ BLI_duplicatelist(&outPose->chanbase, &src->chanbase);
if (copycon) {
for (pchan=outPose->chanbase.first; pchan; pchan=pchan->next) {
@@ -363,7 +560,7 @@ void game_copy_pose(bPose **dst, bPose *src)
out= MEM_dupallocN(src);
out->agroups.first= out->agroups.last= NULL;
- duplicatelist(&out->chanbase, &src->chanbase);
+ BLI_duplicatelist(&out->chanbase, &src->chanbase);
/* remap pointers */
ghash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp);
@@ -401,7 +598,9 @@ static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan
VECCOPY(pchan->loc, chan->loc);
VECCOPY(pchan->size, chan->size);
+ VECCOPY(pchan->eul, chan->eul);
QUATCOPY(pchan->quat, chan->quat);
+ pchan->rotmode= chan->rotmode;
Mat4CpyMat4(pchan->chan_mat, (float(*)[4])chan->chan_mat);
Mat4CpyMat4(pchan->pose_mat, (float(*)[4])chan->pose_mat);
pchan->flag= chan->flag;
@@ -497,53 +696,24 @@ void framechange_poses_clear_unkeyed(void)
/* ************************ 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;
}
@@ -556,7 +726,7 @@ static float get_actionstrip_frame(bActionStrip *strip, float cframe, int invert
repeat = (strip->flag & ACTSTRIP_USESTRIDE) ? (1.0f) : (strip->repeat);
if (strip->scale == 0.0f) strip->scale= 1.0f;
- scale = fabs(strip->scale); /* scale must be positive (for now) */
+ scale = (float)fabs(strip->scale); /* scale must be positive (for now) */
actlength = strip->actend-strip->actstart;
if (actlength == 0.0f) actlength = 1.0f;
@@ -590,6 +760,184 @@ float get_action_frame_inv(Object *ob, float cframe)
}
+
+
+/* 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;
+ short foundvert=0;
+
+ if (act) {
+ for (fcu= act->curves.first; fcu; fcu= fcu->next) {
+ if (fcu->totvert) {
+ float nmin, nmax;
+
+ /* get extents for this curve */
+ calc_fcurve_range(fcu, &nmin, &nmax);
+
+ /* compare to the running tally */
+ min= MIN2(min, nmin);
+ max= MAX2(max, nmax);
+
+ 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);
+ }
+}
+
+/* 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->eul, pchanfrom->eul);
+ VECCOPY(pchanto->size, pchanfrom->size);
+
+ VECCOPY(pchanto->pose_head, pchanfrom->pose_head);
+ VECCOPY(pchanto->pose_tail, pchanfrom->pose_tail);
+ pchanto->flag= pchanfrom->flag;
+ }
+ }
+}
+
+/* For the calculation of the effects of an Action at the given frame on an object
+ * This is currently only used for the Action Constraint
+ */
+void what_does_obaction (Scene *scene, Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], float cframe)
+{
+ bActionGroup *agrp= action_groups_find_named(act, groupname);
+
+ /* clear workob */
+ clear_workob(workob);
+
+ /* init workob */
+ Mat4CpyMat4(workob->obmat, ob->obmat);
+ Mat4CpyMat4(workob->parentinv, ob->parentinv);
+ Mat4CpyMat4(workob->constinv, ob->constinv);
+ workob->parent= ob->parent;
+ workob->track= ob->track;
+
+ workob->trackflag= ob->trackflag;
+ workob->upflag= ob->upflag;
+
+ workob->partype= ob->partype;
+ workob->par1= ob->par1;
+ workob->par2= ob->par2;
+ workob->par3= ob->par3;
+
+ workob->constraints.first = ob->constraints.first;
+ workob->constraints.last = ob->constraints.last;
+
+ workob->pose= pose; /* need to set pose too, since this is used for both types of Action Constraint */
+
+ strcpy(workob->parsubstr, ob->parsubstr);
+ strcpy(workob->id.name, "OB<ConstrWorkOb>"); /* we don't use real object name, otherwise RNA screws with the real thing */
+
+ /* if we're given a group to use, it's likely to be more efficient (though a bit more dangerous) */
+ if (agrp) {
+ /* specifically evaluate this group only */
+ PointerRNA id_ptr;
+
+ /* get RNA-pointer for the workob's ID */
+ RNA_id_pointer_create(&workob->id, &id_ptr);
+
+ /* execute action for this group only */
+ animsys_evaluate_action_group(&id_ptr, act, agrp, NULL, cframe);
+ }
+ else {
+ AnimData adt;
+
+ /* init animdata, and attach to workob */
+ memset(&adt, 0, sizeof(AnimData));
+ workob->adt= &adt;
+
+ adt.recalc= ADT_RECALC_ANIM;
+ adt.action= act;
+
+ /* execute effects of Action on to workob (or it's PoseChannels) */
+ BKE_animsys_evaluate_animdata(&workob->id, &adt, cframe, ADT_RECALC_ANIM);
+ }
+}
+
+/* ********** 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)
@@ -697,7 +1045,6 @@ void blend_poses(bPose *dst, bPose *src, float srcweight, short mode)
bPoseChannel *dchan;
const bPoseChannel *schan;
bConstraint *dcon, *scon;
- float dquat[4], squat[4];
float dstweight;
int i;
@@ -719,23 +1066,34 @@ void blend_poses(bPose *dst, bPose *src, float srcweight, short mode)
/* Do the transformation blend */
if (schan->flag & POSE_ROT) {
- QUATCOPY(dquat, dchan->quat);
- QUATCOPY(squat, schan->quat);
- if(mode==ACTSTRIPMODE_BLEND)
- QuatInterpol(dchan->quat, dquat, squat, srcweight);
- else {
- QuatMulFac(squat, srcweight);
- QuatMul(dchan->quat, dquat, squat);
+ /* quat interpolation done separate */
+ if (schan->rotmode == PCHAN_ROT_QUAT) {
+ float dquat[4], squat[4];
+
+ QUATCOPY(dquat, dchan->quat);
+ QUATCOPY(squat, schan->quat);
+ if (mode==ACTSTRIPMODE_BLEND)
+ QuatInterpol(dchan->quat, dquat, squat, srcweight);
+ else {
+ QuatMulFac(squat, srcweight);
+ QuatMul(dchan->quat, dquat, squat);
+ }
+
+ NormalQuat(dchan->quat);
}
-
- NormalQuat (dchan->quat);
}
- for (i=0; i<3; i++){
+ for (i=0; i<3; i++) {
+ /* blending for loc and scale are pretty self-explanatory... */
if (schan->flag & POSE_LOC)
dchan->loc[i] = (dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight);
if (schan->flag & POSE_SIZE)
dchan->size[i] = 1.0f + ((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight);
+
+ /* euler-rotation interpolation done here instead... */
+ // FIXME: are these results decent?
+ if ((schan->flag & POSE_ROT) && (schan->rotmode))
+ dchan->eul[i] = (dchan->eul[i]*dstweight) + (schan->eul[i]*srcweight);
}
dchan->flag |= schan->flag;
}
@@ -749,167 +1107,6 @@ void blend_poses(bPose *dst, bPose *src, float srcweight, short mode)
dst->ctime= src->ctime;
}
-
-void calc_action_range(const bAction *act, float *start, float *end, int incl_hidden)
-{
- const bActionChannel *chan;
- const bConstraintChannel *conchan;
- const IpoCurve *icu;
- float min=999999999.0f, max=-999999999.0;
- 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->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;
@@ -1028,7 +1225,7 @@ int execute_ipochannels(ListBase *lb)
/* this now only used for repeating cycles, to enable fields and blur. */
/* the whole time control in blender needs serious thinking... */
-static float nla_time(float cfra, float unit)
+static float nla_time(Scene *scene, float cfra, float unit)
{
extern float bluroffs; // bad construct, borrowed from object.c for now
extern float fieldoffs;
@@ -1037,7 +1234,7 @@ static float nla_time(float cfra, float unit)
cfra+= unit*(bluroffs+fieldoffs);
/* global time */
- cfra*= G.scene->r.framelen;
+ cfra*= scene->r.framelen;
return cfra;
}
@@ -1191,48 +1388,9 @@ static Object *get_parent_path(Object *ob)
/* ************** do the action ************ */
-/* For the calculation of the effects of an action at the given frame on an object
- * This is currently only used for the action constraint
- */
-void what_does_obaction (Object *ob, bAction *act, float cframe)
-{
- ListBase tchanbase= {NULL, NULL};
-
- clear_workob();
- Mat4CpyMat4(workob.obmat, ob->obmat);
- Mat4CpyMat4(workob.parentinv, ob->parentinv);
- Mat4CpyMat4(workob.constinv, ob->constinv);
- workob.parent= ob->parent;
- workob.track= ob->track;
-
- workob.trackflag= ob->trackflag;
- workob.upflag= ob->upflag;
-
- workob.partype= ob->partype;
- workob.par1= ob->par1;
- workob.par2= ob->par2;
- workob.par3= ob->par3;
-
- workob.constraints.first = ob->constraints.first;
- workob.constraints.last = ob->constraints.last;
-
- strcpy(workob.parsubstr, ob->parsubstr);
- strcpy(workob.id.name, ob->id.name);
-
- /* extract_ipochannels_from_action needs id's! */
- workob.action= act;
-
- extract_ipochannels_from_action(&tchanbase, &workob.id, act, "Object", bsystem_time(&workob, cframe, 0.0));
-
- if (tchanbase.first) {
- execute_ipochannels(&tchanbase);
- BLI_freelistN(&tchanbase);
- }
-}
-
/* ----- nla, etc. --------- */
-static void do_nla(Object *ob, int blocktype)
+static void do_nla(Scene *scene, Object *ob, int blocktype)
{
bPose *tpose= NULL;
Key *key= NULL;
@@ -1240,7 +1398,7 @@ static void do_nla(Object *ob, int blocktype)
bActionStrip *strip, *striplast=NULL, *stripfirst=NULL;
float striptime, frametime, length, actlength;
float blendfac, stripframe;
- float scene_cfra= frame_to_float(G.scene->r.cfra);
+ float scene_cfra= frame_to_float(scene, scene->r.cfra);
int doit, dostride;
if(blocktype==ID_AR) {
@@ -1306,11 +1464,11 @@ static void do_nla(Object *ob, int blocktype)
if (cu->flag & CU_PATH){
/* Ensure we have a valid path */
- if(cu->path==NULL || cu->path->data==NULL) makeDispListCurveTypes(parent, 0);
+ if(cu->path==NULL || cu->path->data==NULL) makeDispListCurveTypes(scene, parent, 0);
if(cu->path) {
/* Find the position on the path */
- ctime= bsystem_time(ob, scene_cfra, 0.0);
+ ctime= bsystem_time(scene, ob, scene_cfra, 0.0);
if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) {
/* correct for actions not starting on zero */
@@ -1332,7 +1490,7 @@ static void do_nla(Object *ob, int blocktype)
}
frametime = (striptime * actlength) + strip->actstart;
- frametime= bsystem_time(ob, frametime, 0.0);
+ frametime= bsystem_time(scene, ob, frametime, 0.0);
if(blocktype==ID_AR) {
extract_pose_from_action (tpose, strip->act, frametime);
@@ -1362,7 +1520,7 @@ static void do_nla(Object *ob, int blocktype)
}
frametime = (striptime * actlength) + strip->actstart;
- frametime= nla_time(frametime, (float)strip->repeat);
+ frametime= nla_time(scene, frametime, (float)strip->repeat);
if(blocktype==ID_AR) {
extract_pose_from_action (tpose, strip->act, frametime);
@@ -1383,7 +1541,7 @@ static void do_nla(Object *ob, int blocktype)
frametime = actlength * (strip->repeat-(int)strip->repeat);
if(frametime<=0.000001f) frametime= actlength; /* rounding errors... */
- frametime= bsystem_time(ob, frametime+strip->actstart, 0.0);
+ frametime= bsystem_time(scene, ob, frametime+strip->actstart, 0.0);
if(blocktype==ID_AR)
extract_pose_from_action (tpose, strip->act, frametime);
@@ -1448,55 +1606,4 @@ static void do_nla(Object *ob, int blocktype)
BLI_freelistN(&chanbase);
}
-void do_all_pose_actions(Object *ob)
-{
- /* only to have safe calls from editor */
- if(ob==NULL) 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) G.scene->r.cfra;
-
- cframe= get_action_frame(ob, cframe);
-
- extract_pose_from_action (ob->pose, ob->action, bsystem_time(ob, cframe, 0.0));
- }
- else if(ob->nlastrips.first) {
- do_nla(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(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) G.scene->r.cfra;
-
- cframe= get_action_frame(ob, cframe);
-
- extract_ipochannels_from_action(&tchanbase, &ob->id, ob->action, "Object", bsystem_time(ob, cframe, 0.0));
- if(key)
- extract_ipochannels_from_action(&tchanbase, &key->id, ob->action, "Shape", bsystem_time(ob, cframe, 0.0));
-
- if(tchanbase.first) {
- execute_ipochannels(&tchanbase);
- BLI_freelistN(&tchanbase);
- }
- }
- else if(ob->nlastrips.first) {
- do_nla(ob, ID_OB);
- }
-}
+#endif // XXX OLD ANIMATION SYSTEM (TO BE REMOVED)