Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00019 * All rights reserved. 00020 * 00021 * Contributor(s): Full recode, Ton Roosendaal, Crete 2005 00022 * Full recode, Joshua Leung, 2009 00023 * 00024 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00032 #include <string.h> 00033 #include <math.h> 00034 #include <stdlib.h> 00035 #include <stddef.h> 00036 00037 #include "MEM_guardedalloc.h" 00038 00039 #include "DNA_anim_types.h" 00040 #include "DNA_armature_types.h" 00041 #include "DNA_constraint_types.h" 00042 #include "DNA_scene_types.h" 00043 #include "DNA_object_types.h" 00044 00045 #include "BLI_blenlib.h" 00046 #include "BLI_bpath.h" 00047 #include "BLI_math.h" 00048 #include "BLI_utildefines.h" 00049 #include "BLI_ghash.h" 00050 00051 #include "BKE_animsys.h" 00052 #include "BKE_action.h" 00053 #include "BKE_anim.h" 00054 #include "BKE_constraint.h" 00055 #include "BKE_global.h" 00056 #include "BKE_fcurve.h" 00057 #include "BKE_library.h" 00058 #include "BKE_main.h" 00059 #include "BKE_object.h" 00060 00061 #include "BKE_idprop.h" 00062 00063 #include "BIK_api.h" 00064 00065 #include "RNA_access.h" 00066 00067 /* *********************** NOTE ON POSE AND ACTION ********************** 00068 00069 - Pose is the local (object level) component of armature. The current 00070 object pose is saved in files, and (will be) is presorted for dependency 00071 - Actions have fewer (or other) channels, and write data to a Pose 00072 - Currently ob->pose data is controlled in where_is_pose only. The (recalc) 00073 event system takes care of calling that 00074 - The NLA system (here too) uses Poses as interpolation format for Actions 00075 - Therefore we assume poses to be static, and duplicates of poses have channels in 00076 same order, for quick interpolation reasons 00077 00078 ****************************** (ton) ************************************ */ 00079 00080 /* ***************** Library data level operations on action ************** */ 00081 00082 bAction *add_empty_action(const char name[]) 00083 { 00084 bAction *act; 00085 00086 act= alloc_libblock(&G.main->action, ID_AC, name); 00087 00088 return act; 00089 } 00090 00091 /* .................................. */ 00092 00093 /* temp data for make_local_action */ 00094 typedef struct tMakeLocalActionContext { 00095 bAction *act; /* original action */ 00096 bAction *act_new; /* new action */ 00097 00098 int is_lib; /* some action users were libraries */ 00099 int is_local; /* some action users were not libraries */ 00100 } tMakeLocalActionContext; 00101 00102 /* helper function for make_local_action() - local/lib init step */ 00103 static void make_localact_init_cb(ID *id, AnimData *adt, void *mlac_ptr) 00104 { 00105 tMakeLocalActionContext *mlac = (tMakeLocalActionContext *)mlac_ptr; 00106 00107 if (adt->action == mlac->act) { 00108 if (id->lib) mlac->is_lib= TRUE; 00109 else mlac->is_local= TRUE; 00110 } 00111 } 00112 00113 /* helper function for make_local_action() - change references */ 00114 static void make_localact_apply_cb(ID *id, AnimData *adt, void *mlac_ptr) 00115 { 00116 tMakeLocalActionContext *mlac = (tMakeLocalActionContext *)mlac_ptr; 00117 00118 if (adt->action == mlac->act) { 00119 if (id->lib == NULL) { 00120 adt->action = mlac->act_new; 00121 00122 id_us_plus(&mlac->act_new->id); 00123 id_us_min(&mlac->act->id); 00124 } 00125 } 00126 } 00127 00128 // does copy_fcurve... 00129 void make_local_action(bAction *act) 00130 { 00131 tMakeLocalActionContext mlac = {act, NULL, FALSE, FALSE}; 00132 Main *bmain= G.main; 00133 00134 if (act->id.lib==NULL) 00135 return; 00136 00137 // XXX: double-check this; it used to be just single-user check, but that was when fake-users were still default 00138 if ((act->id.flag & LIB_FAKEUSER) && (act->id.us<=1)) { 00139 id_clear_lib_data(bmain, &act->id); 00140 return; 00141 } 00142 00143 BKE_animdata_main_cb(bmain, make_localact_init_cb, &mlac); 00144 00145 if (mlac.is_local && mlac.is_lib==FALSE) { 00146 id_clear_lib_data(bmain, &act->id); 00147 } 00148 else if (mlac.is_local && mlac.is_lib) { 00149 mlac.act_new= copy_action(act); 00150 mlac.act_new->id.us= 0; 00151 00152 BKE_id_lib_local_paths(bmain, act->id.lib, &mlac.act_new->id); 00153 00154 BKE_animdata_main_cb(bmain, make_localact_apply_cb, &mlac); 00155 } 00156 } 00157 00158 /* .................................. */ 00159 00160 void free_action (bAction *act) 00161 { 00162 /* sanity check */ 00163 if (act == NULL) 00164 return; 00165 00166 /* Free F-Curves */ 00167 free_fcurves(&act->curves); 00168 00169 /* Free groups */ 00170 if (act->groups.first) 00171 BLI_freelistN(&act->groups); 00172 00173 /* Free pose-references (aka local markers) */ 00174 if (act->markers.first) 00175 BLI_freelistN(&act->markers); 00176 } 00177 00178 /* .................................. */ 00179 00180 bAction *copy_action (bAction *src) 00181 { 00182 bAction *dst = NULL; 00183 bActionGroup *dgrp, *sgrp; 00184 FCurve *dfcu, *sfcu; 00185 00186 if (src == NULL) 00187 return NULL; 00188 dst= copy_libblock(&src->id); 00189 00190 /* duplicate the lists of groups and markers */ 00191 BLI_duplicatelist(&dst->groups, &src->groups); 00192 BLI_duplicatelist(&dst->markers, &src->markers); 00193 00194 /* copy F-Curves, fixing up the links as we go */ 00195 dst->curves.first= dst->curves.last= NULL; 00196 00197 for (sfcu= src->curves.first; sfcu; sfcu= sfcu->next) { 00198 /* duplicate F-Curve */ 00199 dfcu= copy_fcurve(sfcu); 00200 BLI_addtail(&dst->curves, dfcu); 00201 00202 /* fix group links (kindof bad list-in-list search, but this is the most reliable way) */ 00203 for (dgrp=dst->groups.first, sgrp=src->groups.first; dgrp && sgrp; dgrp=dgrp->next, sgrp=sgrp->next) { 00204 if (sfcu->grp == sgrp) { 00205 dfcu->grp= dgrp; 00206 00207 if (dgrp->channels.first == sfcu) 00208 dgrp->channels.first= dfcu; 00209 if (dgrp->channels.last == sfcu) 00210 dgrp->channels.last= dfcu; 00211 00212 break; 00213 } 00214 } 00215 } 00216 00217 return dst; 00218 } 00219 00220 /* *************** Action Groups *************** */ 00221 00222 /* Get the active action-group for an Action */ 00223 bActionGroup *get_active_actiongroup (bAction *act) 00224 { 00225 bActionGroup *agrp= NULL; 00226 00227 if (act && act->groups.first) { 00228 for (agrp= act->groups.first; agrp; agrp= agrp->next) { 00229 if (agrp->flag & AGRP_ACTIVE) 00230 break; 00231 } 00232 } 00233 00234 return agrp; 00235 } 00236 00237 /* Make the given Action-Group the active one */ 00238 void set_active_action_group (bAction *act, bActionGroup *agrp, short select) 00239 { 00240 bActionGroup *grp; 00241 00242 /* sanity checks */ 00243 if (act == NULL) 00244 return; 00245 00246 /* Deactive all others */ 00247 for (grp= act->groups.first; grp; grp= grp->next) { 00248 if ((grp==agrp) && (select)) 00249 grp->flag |= AGRP_ACTIVE; 00250 else 00251 grp->flag &= ~AGRP_ACTIVE; 00252 } 00253 } 00254 00255 /* Add a new action group with the given name to the action */ 00256 bActionGroup *action_groups_add_new (bAction *act, const char name[]) 00257 { 00258 bActionGroup *agrp; 00259 00260 /* sanity check: must have action and name */ 00261 if (ELEM(NULL, act, name)) 00262 return NULL; 00263 00264 /* allocate a new one */ 00265 agrp = MEM_callocN(sizeof(bActionGroup), "bActionGroup"); 00266 00267 /* make it selected, with default name */ 00268 agrp->flag = AGRP_SELECTED; 00269 BLI_strncpy(agrp->name, name[0] ? name : "Group", sizeof(agrp->name)); 00270 00271 /* add to action, and validate */ 00272 BLI_addtail(&act->groups, agrp); 00273 BLI_uniquename(&act->groups, agrp, "Group", '.', offsetof(bActionGroup, name), sizeof(agrp->name)); 00274 00275 /* return the new group */ 00276 return agrp; 00277 } 00278 00279 /* Add given channel into (active) group 00280 * - assumes that channel is not linked to anything anymore 00281 * - always adds at the end of the group 00282 */ 00283 void action_groups_add_channel (bAction *act, bActionGroup *agrp, FCurve *fcurve) 00284 { 00285 /* sanity checks */ 00286 if (ELEM3(NULL, act, agrp, fcurve)) 00287 return; 00288 00289 /* if no channels anywhere, just add to two lists at the same time */ 00290 if (act->curves.first == NULL) { 00291 fcurve->next = fcurve->prev = NULL; 00292 00293 agrp->channels.first = agrp->channels.last = fcurve; 00294 act->curves.first = act->curves.last = fcurve; 00295 } 00296 00297 /* if the group already has channels, the F-Curve can simply be added to the list 00298 * (i.e. as the last channel in the group) 00299 */ 00300 else if (agrp->channels.first) { 00301 /* if the group's last F-Curve is the action's last F-Curve too, 00302 * then set the F-Curve as the last for the action first so that 00303 * the lists will be in sync after linking 00304 */ 00305 if (agrp->channels.last == act->curves.last) 00306 act->curves.last= fcurve; 00307 00308 /* link in the given F-Curve after the last F-Curve in the group, 00309 * which means that it should be able to fit in with the rest of the 00310 * list seamlessly 00311 */ 00312 BLI_insertlinkafter(&agrp->channels, agrp->channels.last, fcurve); 00313 } 00314 00315 /* otherwise, need to find the nearest F-Curve in group before/after current to link with */ 00316 else { 00317 bActionGroup *grp; 00318 00319 /* firstly, link this F-Curve to the group */ 00320 agrp->channels.first = agrp->channels.last = fcurve; 00321 00322 /* step through the groups preceding this one, finding the F-Curve there to attach this one after */ 00323 for (grp= agrp->prev; grp; grp= grp->prev) { 00324 /* if this group has F-Curves, we want weave the given one in right after the last channel there, 00325 * but via the Action's list not this group's list 00326 * - this is so that the F-Curve is in the right place in the Action, 00327 * but won't be included in the previous group 00328 */ 00329 if (grp->channels.last) { 00330 /* once we've added, break here since we don't need to search any further... */ 00331 BLI_insertlinkafter(&act->curves, grp->channels.last, fcurve); 00332 break; 00333 } 00334 } 00335 00336 /* if grp is NULL, that means we fell through, and this F-Curve should be added as the new first 00337 * since group is (effectively) the first group. Thus, the existing first F-Curve becomes the 00338 * second in the chain, etc. etc. 00339 */ 00340 if (grp == NULL) 00341 BLI_insertlinkbefore(&act->curves, act->curves.first, fcurve); 00342 } 00343 00344 /* set the F-Curve's new group */ 00345 fcurve->grp= agrp; 00346 } 00347 00348 /* Remove the given channel from all groups */ 00349 void action_groups_remove_channel (bAction *act, FCurve *fcu) 00350 { 00351 /* sanity checks */ 00352 if (ELEM(NULL, act, fcu)) 00353 return; 00354 00355 /* check if any group used this directly */ 00356 if (fcu->grp) { 00357 bActionGroup *agrp= fcu->grp; 00358 00359 if (agrp->channels.first == agrp->channels.last) { 00360 if (agrp->channels.first == fcu) { 00361 agrp->channels.first= NULL; 00362 agrp->channels.last= NULL; 00363 } 00364 } 00365 else if (agrp->channels.first == fcu) { 00366 if ((fcu->next) && (fcu->next->grp==agrp)) 00367 agrp->channels.first= fcu->next; 00368 else 00369 agrp->channels.first= NULL; 00370 } 00371 else if (agrp->channels.last == fcu) { 00372 if ((fcu->prev) && (fcu->prev->grp==agrp)) 00373 agrp->channels.last= fcu->prev; 00374 else 00375 agrp->channels.last= NULL; 00376 } 00377 00378 fcu->grp= NULL; 00379 } 00380 00381 /* now just remove from list */ 00382 BLI_remlink(&act->curves, fcu); 00383 } 00384 00385 /* Find a group with the given name */ 00386 bActionGroup *action_groups_find_named (bAction *act, const char name[]) 00387 { 00388 /* sanity checks */ 00389 if (ELEM3(NULL, act, act->groups.first, name) || (name[0] == 0)) 00390 return NULL; 00391 00392 /* do string comparisons */ 00393 return BLI_findstring(&act->groups, name, offsetof(bActionGroup, name)); 00394 } 00395 00396 /* Clear all 'temp' flags on all groups */ 00397 void action_groups_clear_tempflags (bAction *act) 00398 { 00399 bActionGroup *agrp; 00400 00401 /* sanity checks */ 00402 if (ELEM(NULL, act, act->groups.first)) 00403 return; 00404 00405 /* flag clearing loop */ 00406 for (agrp = act->groups.first; agrp; agrp = agrp->next) 00407 agrp->flag &= ~AGRP_TEMP; 00408 } 00409 00410 /* *************** Pose channels *************** */ 00411 00412 /* usually used within a loop, so we got a N^2 slowdown */ 00413 bPoseChannel *get_pose_channel(const bPose *pose, const char *name) 00414 { 00415 if (ELEM(NULL, pose, name) || (name[0] == 0)) 00416 return NULL; 00417 00418 if(pose->chanhash) 00419 return BLI_ghash_lookup(pose->chanhash, (void *)name); 00420 00421 return BLI_findstring(&((bPose *)pose)->chanbase, name, offsetof(bPoseChannel, name)); 00422 } 00423 00424 /* Use with care, not on Armature poses but for temporal ones */ 00425 /* (currently used for action constraints and in rebuild_pose) */ 00426 bPoseChannel *verify_pose_channel(bPose *pose, const char *name) 00427 { 00428 bPoseChannel *chan; 00429 00430 if (pose == NULL) 00431 return NULL; 00432 00433 /* See if this channel exists */ 00434 chan= BLI_findstring(&pose->chanbase, name, offsetof(bPoseChannel, name)); 00435 if(chan) { 00436 return chan; 00437 } 00438 00439 /* If not, create it and add it */ 00440 chan = MEM_callocN(sizeof(bPoseChannel), "verifyPoseChannel"); 00441 00442 BLI_strncpy(chan->name, name, sizeof(chan->name)); 00443 /* init vars to prevent math errors */ 00444 unit_qt(chan->quat); 00445 unit_axis_angle(chan->rotAxis, &chan->rotAngle); 00446 chan->size[0] = chan->size[1] = chan->size[2] = 1.0f; 00447 00448 chan->limitmin[0]= chan->limitmin[1]= chan->limitmin[2]= -180.0f; 00449 chan->limitmax[0]= chan->limitmax[1]= chan->limitmax[2]= 180.0f; 00450 chan->stiffness[0]= chan->stiffness[1]= chan->stiffness[2]= 0.0f; 00451 chan->ikrotweight = chan->iklinweight = 0.0f; 00452 unit_m4(chan->constinv); 00453 00454 chan->protectflag = OB_LOCK_ROT4D; /* lock by components by default */ 00455 00456 BLI_addtail(&pose->chanbase, chan); 00457 free_pose_channels_hash(pose); 00458 00459 return chan; 00460 } 00461 00462 /* Find the active posechannel for an object (we can't just use pose, as layer info is in armature) */ 00463 bPoseChannel *get_active_posechannel (Object *ob) 00464 { 00465 bArmature *arm= (ob) ? ob->data : NULL; 00466 bPoseChannel *pchan; 00467 00468 if ELEM3(NULL, ob, ob->pose, arm) 00469 return NULL; 00470 00471 /* find active */ 00472 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { 00473 if ((pchan->bone) && (pchan->bone == arm->act_bone) && (pchan->bone->layer & arm->layer)) 00474 return pchan; 00475 } 00476 00477 return NULL; 00478 } 00479 00480 const char *get_ikparam_name(bPose *pose) 00481 { 00482 if (pose) { 00483 switch (pose->iksolver) { 00484 case IKSOLVER_LEGACY: 00485 return NULL; 00486 case IKSOLVER_ITASC: 00487 return "bItasc"; 00488 } 00489 } 00490 return NULL; 00491 } 00492 /* dst should be freed already, makes entire duplicate */ 00493 void copy_pose (bPose **dst, bPose *src, int copycon) 00494 { 00495 bPose *outPose; 00496 bPoseChannel *pchan; 00497 ListBase listb; 00498 00499 if (!src) { 00500 *dst=NULL; 00501 return; 00502 } 00503 00504 if (*dst==src) { 00505 printf("copy_pose source and target are the same\n"); 00506 *dst=NULL; 00507 return; 00508 } 00509 00510 outPose= MEM_callocN(sizeof(bPose), "pose"); 00511 00512 BLI_duplicatelist(&outPose->chanbase, &src->chanbase); 00513 00514 outPose->iksolver = src->iksolver; 00515 outPose->ikdata = NULL; 00516 outPose->ikparam = MEM_dupallocN(src->ikparam); 00517 00518 for (pchan=outPose->chanbase.first; pchan; pchan=pchan->next) { 00519 // TODO: rename this argument... 00520 if (copycon) { 00521 copy_constraints(&listb, &pchan->constraints, TRUE); // copy_constraints NULLs listb 00522 pchan->constraints= listb; 00523 pchan->mpath= NULL; /* motion paths should not get copied yet... */ 00524 } 00525 00526 if(pchan->prop) { 00527 pchan->prop= IDP_CopyProperty(pchan->prop); 00528 } 00529 } 00530 00531 /* for now, duplicate Bone Groups too when doing this */ 00532 if (copycon) 00533 BLI_duplicatelist(&outPose->agroups, &src->agroups); 00534 00535 *dst=outPose; 00536 } 00537 00538 void init_pose_itasc(bItasc *itasc) 00539 { 00540 if (itasc) { 00541 itasc->iksolver = IKSOLVER_ITASC; 00542 itasc->minstep = 0.01f; 00543 itasc->maxstep = 0.06f; 00544 itasc->numiter = 100; 00545 itasc->numstep = 4; 00546 itasc->precision = 0.005f; 00547 itasc->flag = ITASC_AUTO_STEP|ITASC_INITIAL_REITERATION; 00548 itasc->feedback = 20.f; 00549 itasc->maxvel = 50.f; 00550 itasc->solver = ITASC_SOLVER_SDLS; 00551 itasc->dampmax = 0.5; 00552 itasc->dampeps = 0.15; 00553 } 00554 } 00555 void init_pose_ikparam(bPose *pose) 00556 { 00557 bItasc *itasc; 00558 switch (pose->iksolver) { 00559 case IKSOLVER_ITASC: 00560 itasc = MEM_callocN(sizeof(bItasc), "itasc"); 00561 init_pose_itasc(itasc); 00562 pose->ikparam = itasc; 00563 break; 00564 case IKSOLVER_LEGACY: 00565 default: 00566 pose->ikparam = NULL; 00567 break; 00568 } 00569 } 00570 00571 void make_pose_channels_hash(bPose *pose) 00572 { 00573 if(!pose->chanhash) { 00574 bPoseChannel *pchan; 00575 00576 pose->chanhash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "make_pose_chan gh"); 00577 for(pchan=pose->chanbase.first; pchan; pchan=pchan->next) 00578 BLI_ghash_insert(pose->chanhash, pchan->name, pchan); 00579 } 00580 } 00581 00582 void free_pose_channels_hash(bPose *pose) 00583 { 00584 if(pose->chanhash) { 00585 BLI_ghash_free(pose->chanhash, NULL, NULL); 00586 pose->chanhash= NULL; 00587 } 00588 } 00589 00590 00591 void free_pose_channel(bPoseChannel *pchan) 00592 { 00593 00594 if (pchan->mpath) { 00595 animviz_free_motionpath(pchan->mpath); 00596 pchan->mpath= NULL; 00597 } 00598 00599 free_constraints(&pchan->constraints); 00600 00601 if (pchan->prop) { 00602 IDP_FreeProperty(pchan->prop); 00603 MEM_freeN(pchan->prop); 00604 } 00605 } 00606 00607 void free_pose_channels(bPose *pose) 00608 { 00609 bPoseChannel *pchan; 00610 00611 if (pose->chanbase.first) { 00612 for (pchan = pose->chanbase.first; pchan; pchan=pchan->next) 00613 free_pose_channel(pchan); 00614 00615 BLI_freelistN(&pose->chanbase); 00616 } 00617 00618 free_pose_channels_hash(pose); 00619 } 00620 00621 void free_pose(bPose *pose) 00622 { 00623 if (pose) { 00624 /* free pose-channels */ 00625 free_pose_channels(pose); 00626 00627 /* free pose-groups */ 00628 if (pose->agroups.first) 00629 BLI_freelistN(&pose->agroups); 00630 00631 /* free IK solver state */ 00632 BIK_clear_data(pose); 00633 00634 /* free IK solver param */ 00635 if (pose->ikparam) 00636 MEM_freeN(pose->ikparam); 00637 00638 /* free pose */ 00639 MEM_freeN(pose); 00640 } 00641 } 00642 00643 static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan) 00644 { 00645 bConstraint *pcon, *con; 00646 00647 copy_v3_v3(pchan->loc, chan->loc); 00648 copy_v3_v3(pchan->size, chan->size); 00649 copy_v3_v3(pchan->eul, chan->eul); 00650 copy_v3_v3(pchan->rotAxis, chan->rotAxis); 00651 pchan->rotAngle= chan->rotAngle; 00652 copy_qt_qt(pchan->quat, chan->quat); 00653 pchan->rotmode= chan->rotmode; 00654 copy_m4_m4(pchan->chan_mat, (float(*)[4])chan->chan_mat); 00655 copy_m4_m4(pchan->pose_mat, (float(*)[4])chan->pose_mat); 00656 pchan->flag= chan->flag; 00657 00658 con= chan->constraints.first; 00659 for(pcon= pchan->constraints.first; pcon && con; pcon= pcon->next, con= con->next) { 00660 pcon->enforce= con->enforce; 00661 pcon->headtail= con->headtail; 00662 } 00663 } 00664 00665 /* makes copies of internal data, unlike copy_pose_channel_data which only 00666 * copies the pose state. 00667 * hint: use when copying bones in editmode (on returned value from verify_pose_channel) */ 00668 void duplicate_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *pchan_from) 00669 { 00670 /* copy transform locks */ 00671 pchan->protectflag = pchan_from->protectflag; 00672 00673 /* copy rotation mode */ 00674 pchan->rotmode = pchan_from->rotmode; 00675 00676 /* copy bone group */ 00677 pchan->agrp_index= pchan_from->agrp_index; 00678 00679 /* ik (dof) settings */ 00680 pchan->ikflag = pchan_from->ikflag; 00681 copy_v3_v3(pchan->limitmin, pchan_from->limitmin); 00682 copy_v3_v3(pchan->limitmax, pchan_from->limitmax); 00683 copy_v3_v3(pchan->stiffness, pchan_from->stiffness); 00684 pchan->ikstretch= pchan_from->ikstretch; 00685 pchan->ikrotweight= pchan_from->ikrotweight; 00686 pchan->iklinweight= pchan_from->iklinweight; 00687 00688 /* constraints */ 00689 copy_constraints(&pchan->constraints, &pchan_from->constraints, TRUE); 00690 00691 /* id-properties */ 00692 if(pchan->prop) { 00693 /* unlikely but possible it exists */ 00694 IDP_FreeProperty(pchan->prop); 00695 MEM_freeN(pchan->prop); 00696 pchan->prop= NULL; 00697 } 00698 if(pchan_from->prop) { 00699 pchan->prop= IDP_CopyProperty(pchan_from->prop); 00700 } 00701 00702 /* custom shape */ 00703 pchan->custom= pchan_from->custom; 00704 } 00705 00706 00707 /* checks for IK constraint, Spline IK, and also for Follow-Path constraint. 00708 * can do more constraints flags later 00709 */ 00710 /* pose should be entirely OK */ 00711 void update_pose_constraint_flags(bPose *pose) 00712 { 00713 bPoseChannel *pchan, *parchan; 00714 bConstraint *con; 00715 00716 /* clear */ 00717 for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { 00718 pchan->constflag= 0; 00719 } 00720 pose->flag &= ~POSE_CONSTRAINTS_TIMEDEPEND; 00721 00722 /* detect */ 00723 for (pchan= pose->chanbase.first; pchan; pchan=pchan->next) { 00724 for (con= pchan->constraints.first; con; con= con->next) { 00725 if (con->type==CONSTRAINT_TYPE_KINEMATIC) { 00726 bKinematicConstraint *data = (bKinematicConstraint*)con->data; 00727 00728 pchan->constflag |= PCHAN_HAS_IK; 00729 00730 if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0)) 00731 pchan->constflag |= PCHAN_HAS_TARGET; 00732 00733 /* negative rootbone = recalc rootbone index. used in do_versions */ 00734 if(data->rootbone<0) { 00735 data->rootbone= 0; 00736 00737 if(data->flag & CONSTRAINT_IK_TIP) parchan= pchan; 00738 else parchan= pchan->parent; 00739 00740 while(parchan) { 00741 data->rootbone++; 00742 if((parchan->bone->flag & BONE_CONNECTED)==0) 00743 break; 00744 parchan= parchan->parent; 00745 } 00746 } 00747 } 00748 else if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) { 00749 bFollowPathConstraint *data= (bFollowPathConstraint *)con->data; 00750 00751 /* for drawing constraint colors when color set allows this */ 00752 pchan->constflag |= PCHAN_HAS_CONST; 00753 00754 /* if we have a valid target, make sure that this will get updated on frame-change 00755 * (needed for when there is no anim-data for this pose) 00756 */ 00757 if ((data->tar) && (data->tar->type==OB_CURVE)) 00758 pose->flag |= POSE_CONSTRAINTS_TIMEDEPEND; 00759 } 00760 else if (con->type == CONSTRAINT_TYPE_SPLINEIK) 00761 pchan->constflag |= PCHAN_HAS_SPLINEIK; 00762 else 00763 pchan->constflag |= PCHAN_HAS_CONST; 00764 } 00765 } 00766 } 00767 00768 /* Clears all BONE_UNKEYED flags for every pose channel in every pose 00769 * This should only be called on frame changing, when it is acceptable to 00770 * do this. Otherwise, these flags should not get cleared as poses may get lost. 00771 */ 00772 void framechange_poses_clear_unkeyed(void) 00773 { 00774 Object *ob; 00775 bPose *pose; 00776 bPoseChannel *pchan; 00777 00778 /* This needs to be done for each object that has a pose */ 00779 // TODO: proxies may/may not be correctly handled here... (this needs checking) 00780 for (ob= G.main->object.first; ob; ob= ob->id.next) { 00781 /* we only need to do this on objects with a pose */ 00782 if ( (pose= ob->pose) ) { 00783 for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { 00784 if (pchan->bone) 00785 pchan->bone->flag &= ~BONE_UNKEYED; 00786 } 00787 } 00788 } 00789 } 00790 00791 /* ************************** Bone Groups ************************** */ 00792 00793 /* Adds a new bone-group */ 00794 void pose_add_group (Object *ob) 00795 { 00796 bPose *pose= (ob) ? ob->pose : NULL; 00797 bActionGroup *grp; 00798 00799 if (ELEM(NULL, ob, ob->pose)) 00800 return; 00801 00802 grp= MEM_callocN(sizeof(bActionGroup), "PoseGroup"); 00803 BLI_strncpy(grp->name, "Group", sizeof(grp->name)); 00804 BLI_addtail(&pose->agroups, grp); 00805 BLI_uniquename(&pose->agroups, grp, "Group", '.', offsetof(bActionGroup, name), sizeof(grp->name)); 00806 00807 pose->active_group= BLI_countlist(&pose->agroups); 00808 } 00809 00810 /* Remove the active bone-group */ 00811 void pose_remove_group (Object *ob) 00812 { 00813 bPose *pose= (ob) ? ob->pose : NULL; 00814 bActionGroup *grp = NULL; 00815 bPoseChannel *pchan; 00816 00817 /* sanity checks */ 00818 if (ELEM(NULL, ob, pose)) 00819 return; 00820 if (pose->active_group <= 0) 00821 return; 00822 00823 /* get group to remove */ 00824 grp= BLI_findlink(&pose->agroups, pose->active_group-1); 00825 if (grp) { 00826 /* adjust group references (the trouble of using indices!): 00827 * - firstly, make sure nothing references it 00828 * - also, make sure that those after this item get corrected 00829 */ 00830 for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) { 00831 if (pchan->agrp_index == pose->active_group) 00832 pchan->agrp_index= 0; 00833 else if (pchan->agrp_index > pose->active_group) 00834 pchan->agrp_index--; 00835 } 00836 00837 /* now, remove it from the pose */ 00838 BLI_freelinkN(&pose->agroups, grp); 00839 pose->active_group--; 00840 if(pose->active_group < 0 || pose->agroups.first == NULL) { 00841 pose->active_group= 0; 00842 } 00843 } 00844 } 00845 00846 /* ************** F-Curve Utilities for Actions ****************** */ 00847 00848 /* Check if the given action has any keyframes */ 00849 short action_has_motion(const bAction *act) 00850 { 00851 FCurve *fcu; 00852 00853 /* return on the first F-Curve that has some keyframes/samples defined */ 00854 if (act) { 00855 for (fcu= act->curves.first; fcu; fcu= fcu->next) { 00856 if (fcu->totvert) 00857 return 1; 00858 } 00859 } 00860 00861 /* nothing found */ 00862 return 0; 00863 } 00864 00865 /* Calculate the extents of given action */ 00866 void calc_action_range(const bAction *act, float *start, float *end, short incl_modifiers) 00867 { 00868 FCurve *fcu; 00869 float min=999999999.0f, max=-999999999.0f; 00870 short foundvert=0, foundmod=0; 00871 00872 if (act) { 00873 for (fcu= act->curves.first; fcu; fcu= fcu->next) { 00874 /* if curve has keyframes, consider them first */ 00875 if (fcu->totvert) { 00876 float nmin, nmax; 00877 00878 /* get extents for this curve */ 00879 // TODO: allow enabling/disabling this? 00880 calc_fcurve_range(fcu, &nmin, &nmax, FALSE, TRUE); 00881 00882 /* compare to the running tally */ 00883 min= MIN2(min, nmin); 00884 max= MAX2(max, nmax); 00885 00886 foundvert= 1; 00887 } 00888 00889 /* if incl_modifiers is enabled, need to consider modifiers too 00890 * - only really care about the last modifier 00891 */ 00892 if ((incl_modifiers) && (fcu->modifiers.last)) { 00893 FModifier *fcm= fcu->modifiers.last; 00894 00895 /* only use the maximum sensible limits of the modifiers if they are more extreme */ 00896 switch (fcm->type) { 00897 case FMODIFIER_TYPE_LIMITS: /* Limits F-Modifier */ 00898 { 00899 FMod_Limits *fmd= (FMod_Limits *)fcm->data; 00900 00901 if (fmd->flag & FCM_LIMIT_XMIN) { 00902 min= MIN2(min, fmd->rect.xmin); 00903 } 00904 if (fmd->flag & FCM_LIMIT_XMAX) { 00905 max= MAX2(max, fmd->rect.xmax); 00906 } 00907 } 00908 break; 00909 00910 case FMODIFIER_TYPE_CYCLES: /* Cycles F-Modifier */ 00911 { 00912 FMod_Cycles *fmd= (FMod_Cycles *)fcm->data; 00913 00914 if (fmd->before_mode != FCM_EXTRAPOLATE_NONE) 00915 min= MINAFRAMEF; 00916 if (fmd->after_mode != FCM_EXTRAPOLATE_NONE) 00917 max= MAXFRAMEF; 00918 } 00919 break; 00920 00921 // TODO: function modifier may need some special limits 00922 00923 default: /* all other standard modifiers are on the infinite range... */ 00924 min= MINAFRAMEF; 00925 max= MAXFRAMEF; 00926 break; 00927 } 00928 00929 foundmod= 1; 00930 } 00931 } 00932 } 00933 00934 if (foundvert || foundmod) { 00935 if(min==max) max+= 1.0f; 00936 *start= min; 00937 *end= max; 00938 } 00939 else { 00940 *start= 0.0f; 00941 *end= 1.0f; 00942 } 00943 } 00944 00945 /* Return flags indicating which transforms the given object/posechannel has 00946 * - if 'curves' is provided, a list of links to these curves are also returned 00947 */ 00948 short action_get_item_transforms (bAction *act, Object *ob, bPoseChannel *pchan, ListBase *curves) 00949 { 00950 PointerRNA ptr; 00951 FCurve *fcu; 00952 char *basePath=NULL; 00953 short flags=0; 00954 00955 /* build PointerRNA from provided data to obtain the paths to use */ 00956 if (pchan) 00957 RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan, &ptr); 00958 else if (ob) 00959 RNA_id_pointer_create((ID *)ob, &ptr); 00960 else 00961 return 0; 00962 00963 /* get the basic path to the properties of interest */ 00964 basePath= RNA_path_from_ID_to_struct(&ptr); 00965 if (basePath == NULL) 00966 return 0; 00967 00968 /* search F-Curves for the given properties 00969 * - we cannot use the groups, since they may not be grouped in that way... 00970 */ 00971 for (fcu= act->curves.first; fcu; fcu= fcu->next) { 00972 char *bPtr=NULL, *pPtr=NULL; 00973 00974 /* if enough flags have been found, we can stop checking unless we're also getting the curves */ 00975 if ((flags == ACT_TRANS_ALL) && (curves == NULL)) 00976 break; 00977 00978 /* just in case... */ 00979 if (fcu->rna_path == NULL) 00980 continue; 00981 00982 /* step 1: check for matching base path */ 00983 bPtr= strstr(fcu->rna_path, basePath); 00984 00985 if (bPtr) { 00986 /* we must add len(basePath) bytes to the match so that we are at the end of the 00987 * base path so that we don't get false positives with these strings in the names 00988 */ 00989 bPtr += strlen(basePath); 00990 00991 /* step 2: check for some property with transforms 00992 * - to speed things up, only check for the ones not yet found 00993 * unless we're getting the curves too 00994 * - if we're getting the curves, the BLI_genericNodeN() creates a LinkData 00995 * node wrapping the F-Curve, which then gets added to the list 00996 * - once a match has been found, the curve cannot possibly be any other one 00997 */ 00998 if ((curves) || (flags & ACT_TRANS_LOC) == 0) { 00999 pPtr= strstr(bPtr, "location"); 01000 if (pPtr) { 01001 flags |= ACT_TRANS_LOC; 01002 01003 if (curves) 01004 BLI_addtail(curves, BLI_genericNodeN(fcu)); 01005 continue; 01006 } 01007 } 01008 01009 if ((curves) || (flags & ACT_TRANS_SCALE) == 0) { 01010 pPtr= strstr(bPtr, "scale"); 01011 if (pPtr) { 01012 flags |= ACT_TRANS_SCALE; 01013 01014 if (curves) 01015 BLI_addtail(curves, BLI_genericNodeN(fcu)); 01016 continue; 01017 } 01018 } 01019 01020 if ((curves) || (flags & ACT_TRANS_ROT) == 0) { 01021 pPtr= strstr(bPtr, "rotation"); 01022 if (pPtr) { 01023 flags |= ACT_TRANS_ROT; 01024 01025 if (curves) 01026 BLI_addtail(curves, BLI_genericNodeN(fcu)); 01027 continue; 01028 } 01029 } 01030 01031 if ((curves) || (flags & ACT_TRANS_PROP) == 0) { 01032 /* custom properties only */ 01033 pPtr= strstr(bPtr, "[\""); /* extra '"' comment here to keep my texteditor functionlist working :) */ 01034 if (pPtr) { 01035 flags |= ACT_TRANS_PROP; 01036 01037 if (curves) 01038 BLI_addtail(curves, BLI_genericNodeN(fcu)); 01039 continue; 01040 } 01041 } 01042 } 01043 } 01044 01045 /* free basePath */ 01046 MEM_freeN(basePath); 01047 01048 /* return flags found */ 01049 return flags; 01050 } 01051 01052 /* ************** Pose Management Tools ****************** */ 01053 01054 /* Copy the data from the action-pose (src) into the pose */ 01055 /* both args are assumed to be valid */ 01056 /* exported to game engine */ 01057 /* Note! this assumes both poses are aligned, this isnt always true when dealing with user poses */ 01058 void extract_pose_from_pose(bPose *pose, const bPose *src) 01059 { 01060 const bPoseChannel *schan; 01061 bPoseChannel *pchan= pose->chanbase.first; 01062 01063 if (pose==src) { 01064 printf("extract_pose_from_pose source and target are the same\n"); 01065 return; 01066 } 01067 01068 for (schan=src->chanbase.first; (schan && pchan); schan=schan->next, pchan= pchan->next) { 01069 copy_pose_channel_data(pchan, schan); 01070 } 01071 } 01072 01073 /* for do_all_pose_actions, clears the pose. Now also exported for proxy and tools */ 01074 void rest_pose(bPose *pose) 01075 { 01076 bPoseChannel *pchan; 01077 01078 if (!pose) 01079 return; 01080 01081 memset(pose->stride_offset, 0, sizeof(pose->stride_offset)); 01082 memset(pose->cyclic_offset, 0, sizeof(pose->cyclic_offset)); 01083 01084 for (pchan=pose->chanbase.first; pchan; pchan= pchan->next) { 01085 zero_v3(pchan->loc); 01086 zero_v3(pchan->eul); 01087 unit_qt(pchan->quat); 01088 unit_axis_angle(pchan->rotAxis, &pchan->rotAngle); 01089 pchan->size[0]= pchan->size[1]= pchan->size[2]= 1.0f; 01090 01091 pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE); 01092 } 01093 } 01094 01095 /* both poses should be in sync */ 01096 void copy_pose_result(bPose *to, bPose *from) 01097 { 01098 bPoseChannel *pchanto, *pchanfrom; 01099 01100 if(to==NULL || from==NULL) { 01101 printf("pose result copy error to:%p from:%p\n", (void *)to, (void *)from); // debug temp 01102 return; 01103 } 01104 01105 if (to==from) { 01106 printf("copy_pose_result source and target are the same\n"); 01107 return; 01108 } 01109 01110 01111 for(pchanfrom= from->chanbase.first; pchanfrom; pchanfrom= pchanfrom->next) { 01112 pchanto= get_pose_channel(to, pchanfrom->name); 01113 if(pchanto) { 01114 copy_m4_m4(pchanto->pose_mat, pchanfrom->pose_mat); 01115 copy_m4_m4(pchanto->chan_mat, pchanfrom->chan_mat); 01116 01117 /* used for local constraints */ 01118 copy_v3_v3(pchanto->loc, pchanfrom->loc); 01119 copy_qt_qt(pchanto->quat, pchanfrom->quat); 01120 copy_v3_v3(pchanto->eul, pchanfrom->eul); 01121 copy_v3_v3(pchanto->size, pchanfrom->size); 01122 01123 copy_v3_v3(pchanto->pose_head, pchanfrom->pose_head); 01124 copy_v3_v3(pchanto->pose_tail, pchanfrom->pose_tail); 01125 01126 pchanto->rotmode= pchanfrom->rotmode; 01127 pchanto->flag= pchanfrom->flag; 01128 pchanto->protectflag= pchanfrom->protectflag; 01129 } 01130 } 01131 } 01132 01133 /* For the calculation of the effects of an Action at the given frame on an object 01134 * This is currently only used for the Action Constraint 01135 */ 01136 void what_does_obaction (Object *ob, Object *workob, bPose *pose, bAction *act, char groupname[], float cframe) 01137 { 01138 bActionGroup *agrp= action_groups_find_named(act, groupname); 01139 01140 /* clear workob */ 01141 clear_workob(workob); 01142 01143 /* init workob */ 01144 copy_m4_m4(workob->obmat, ob->obmat); 01145 copy_m4_m4(workob->parentinv, ob->parentinv); 01146 copy_m4_m4(workob->constinv, ob->constinv); 01147 workob->parent= ob->parent; 01148 01149 workob->rotmode= ob->rotmode; 01150 01151 workob->trackflag= ob->trackflag; 01152 workob->upflag= ob->upflag; 01153 01154 workob->partype= ob->partype; 01155 workob->par1= ob->par1; 01156 workob->par2= ob->par2; 01157 workob->par3= ob->par3; 01158 01159 workob->constraints.first = ob->constraints.first; 01160 workob->constraints.last = ob->constraints.last; 01161 01162 workob->pose= pose; /* need to set pose too, since this is used for both types of Action Constraint */ 01163 01164 BLI_strncpy(workob->parsubstr, ob->parsubstr, sizeof(workob->parsubstr)); 01165 BLI_strncpy(workob->id.name, "OB<ConstrWorkOb>", sizeof(workob->id.name)); /* we don't use real object name, otherwise RNA screws with the real thing */ 01166 01167 /* if we're given a group to use, it's likely to be more efficient (though a bit more dangerous) */ 01168 if (agrp) { 01169 /* specifically evaluate this group only */ 01170 PointerRNA id_ptr; 01171 01172 /* get RNA-pointer for the workob's ID */ 01173 RNA_id_pointer_create(&workob->id, &id_ptr); 01174 01175 /* execute action for this group only */ 01176 animsys_evaluate_action_group(&id_ptr, act, agrp, NULL, cframe); 01177 } 01178 else { 01179 AnimData adt= {NULL}; 01180 01181 /* init animdata, and attach to workob */ 01182 workob->adt= &adt; 01183 01184 adt.recalc= ADT_RECALC_ANIM; 01185 adt.action= act; 01186 01187 /* execute effects of Action on to workob (or it's PoseChannels) */ 01188 BKE_animsys_evaluate_animdata(NULL, &workob->id, &adt, cframe, ADT_RECALC_ANIM); 01189 } 01190 } 01191 01192 /* ********** NLA with non-poses works with ipo channels ********** */ 01193 01194 #if 0 // XXX OLD ANIMATION SYSTEM (TO BE REMOVED) 01195 01196 /* ************************ Blending with NLA *************** */ 01197 01198 static void blend_pose_strides(bPose *dst, bPose *src, float srcweight, short mode) 01199 { 01200 float dstweight; 01201 01202 switch (mode){ 01203 case ACTSTRIPMODE_BLEND: 01204 dstweight = 1.0F - srcweight; 01205 break; 01206 case ACTSTRIPMODE_ADD: 01207 dstweight = 1.0F; 01208 break; 01209 default : 01210 dstweight = 1.0F; 01211 } 01212 01213 interp_v3_v3v3(dst->stride_offset, dst->stride_offset, src->stride_offset, srcweight); 01214 } 01215 01216 01217 /* 01218 01219 bone matching diagram, strips A and B 01220 01221 .------------------------. 01222 | A | 01223 '------------------------' 01224 . . b2 01225 . .-------------v----------. 01226 . | B . | 01227 . '------------------------' 01228 . . . 01229 . . . 01230 offset: . 0 . A-B . A-b2+B 01231 . . . 01232 01233 */ 01234 01235 01236 static void blend_pose_offset_bone(bActionStrip *strip, bPose *dst, bPose *src, float srcweight, short mode) 01237 { 01238 /* matching offset bones */ 01239 /* take dst offset, and put src on on that location */ 01240 01241 if(strip->offs_bone[0]==0) 01242 return; 01243 01244 /* are we also blending with matching bones? */ 01245 if(strip->prev && strip->start>=strip->prev->start) { 01246 bPoseChannel *dpchan= get_pose_channel(dst, strip->offs_bone); 01247 if(dpchan) { 01248 bPoseChannel *spchan= get_pose_channel(src, strip->offs_bone); 01249 if(spchan) { 01250 float vec[3]; 01251 01252 /* dst->ctime has the internal strip->prev action time */ 01253 /* map this time to nla time */ 01254 01255 float ctime= get_actionstrip_frame(strip, src->ctime, 1); 01256 01257 if( ctime > strip->prev->end) { 01258 bActionChannel *achan; 01259 01260 /* add src to dest, minus the position of src on strip->prev->end */ 01261 01262 ctime= get_actionstrip_frame(strip, strip->prev->end, 0); 01263 01264 achan= get_action_channel(strip->act, strip->offs_bone); 01265 if(achan && achan->ipo) { 01266 bPoseChannel pchan; 01267 /* Evaluates and sets the internal ipo value */ 01268 calc_ipo(achan->ipo, ctime); 01269 /* This call also sets the pchan flags */ 01270 execute_action_ipo(achan, &pchan); 01271 01272 /* store offset that moves src to location of pchan */ 01273 sub_v3_v3v3(vec, dpchan->loc, pchan.loc); 01274 01275 mul_mat3_m4_v3(dpchan->bone->arm_mat, vec); 01276 } 01277 } 01278 else { 01279 /* store offset that moves src to location of dst */ 01280 01281 sub_v3_v3v3(vec, dpchan->loc, spchan->loc); 01282 mul_mat3_m4_v3(dpchan->bone->arm_mat, vec); 01283 } 01284 01285 /* if blending, we only add with factor scrweight */ 01286 mul_v3_fl(vec, srcweight); 01287 01288 add_v3_v3(dst->cyclic_offset, vec); 01289 } 01290 } 01291 } 01292 01293 add_v3_v3(dst->cyclic_offset, src->cyclic_offset); 01294 } 01295 01296 /* added "sizecorr" here, to allow armatures to be scaled and still have striding. 01297 Only works for uniform scaling. In general I'd advise against scaling armatures ever though! (ton) 01298 */ 01299 static float stridechannel_frame(Object *ob, float sizecorr, bActionStrip *strip, Path *path, float pathdist, float *stride_offset) 01300 { 01301 bAction *act= strip->act; 01302 const char *name= strip->stridechannel; 01303 bActionChannel *achan= get_action_channel(act, name); 01304 int stride_axis= strip->stride_axis; 01305 01306 if(achan && achan->ipo) { 01307 IpoCurve *icu= NULL; 01308 float minx=0.0f, maxx=0.0f, miny=0.0f, maxy=0.0f; 01309 int foundvert= 0; 01310 01311 if(stride_axis==0) stride_axis= AC_LOC_X; 01312 else if(stride_axis==1) stride_axis= AC_LOC_Y; 01313 else stride_axis= AC_LOC_Z; 01314 01315 /* calculate the min/max */ 01316 for (icu=achan->ipo->curve.first; icu; icu=icu->next) { 01317 if(icu->adrcode==stride_axis) { 01318 if(icu->totvert>1) { 01319 foundvert= 1; 01320 minx= icu->bezt[0].vec[1][0]; 01321 maxx= icu->bezt[icu->totvert-1].vec[1][0]; 01322 01323 miny= icu->bezt[0].vec[1][1]; 01324 maxy= icu->bezt[icu->totvert-1].vec[1][1]; 01325 } 01326 break; 01327 } 01328 } 01329 01330 if(foundvert && miny!=maxy) { 01331 float stridelen= sizecorr*fabs(maxy-miny), striptime; 01332 float actiondist, pdist, pdistNewNormalized, offs; 01333 float vec1[4], vec2[4], dir[3]; 01334 01335 /* internal cycling, actoffs is in frames */ 01336 offs= stridelen*strip->actoffs/(maxx-minx); 01337 01338 /* amount path moves object */ 01339 pdist = (float)fmod (pathdist+offs, stridelen); 01340 striptime= pdist/stridelen; 01341 01342 /* amount stride bone moves */ 01343 actiondist= sizecorr*eval_icu(icu, minx + striptime*(maxx-minx)) - miny; 01344 01345 pdist = fabs(actiondist) - pdist; 01346 pdistNewNormalized = (pathdist+pdist)/path->totdist; 01347 01348 /* now we need to go pdist further (or less) on cu path */ 01349 where_on_path(ob, (pathdist)/path->totdist, vec1, dir); /* vec needs size 4 */ 01350 if (pdistNewNormalized <= 1) { 01351 // search for correction in positive path-direction 01352 where_on_path(ob, pdistNewNormalized, vec2, dir); /* vec needs size 4 */ 01353 sub_v3_v3v3(stride_offset, vec2, vec1); 01354 } 01355 else { 01356 // we reached the end of the path, search backwards instead 01357 where_on_path(ob, (pathdist-pdist)/path->totdist, vec2, dir); /* vec needs size 4 */ 01358 sub_v3_v3v3(stride_offset, vec1, vec2); 01359 } 01360 mul_mat3_m4_v3(ob->obmat, stride_offset); 01361 return striptime; 01362 } 01363 } 01364 return 0.0f; 01365 } 01366 01367 static void cyclic_offs_bone(Object *ob, bPose *pose, bActionStrip *strip, float time) 01368 { 01369 /* only called when strip has cyclic, so >= 1.0f works... */ 01370 if(time >= 1.0f) { 01371 bActionChannel *achan= get_action_channel(strip->act, strip->offs_bone); 01372 01373 if(achan && achan->ipo) { 01374 IpoCurve *icu= NULL; 01375 Bone *bone; 01376 float min[3]={0.0f, 0.0f, 0.0f}, max[3]={0.0f, 0.0f, 0.0f}; 01377 int index=0, foundvert= 0; 01378 01379 /* calculate the min/max */ 01380 for (icu=achan->ipo->curve.first; icu; icu=icu->next) { 01381 if(icu->totvert>1) { 01382 01383 if(icu->adrcode==AC_LOC_X) 01384 index= 0; 01385 else if(icu->adrcode==AC_LOC_Y) 01386 index= 1; 01387 else if(icu->adrcode==AC_LOC_Z) 01388 index= 2; 01389 else 01390 continue; 01391 01392 foundvert= 1; 01393 min[index]= icu->bezt[0].vec[1][1]; 01394 max[index]= icu->bezt[icu->totvert-1].vec[1][1]; 01395 } 01396 } 01397 if(foundvert) { 01398 /* bring it into armature space */ 01399 sub_v3_v3v3(min, max, min); 01400 bone= get_named_bone(ob->data, strip->offs_bone); /* weak */ 01401 if(bone) { 01402 mul_mat3_m4_v3(bone->arm_mat, min); 01403 01404 /* dominant motion, cyclic_offset was cleared in rest_pose */ 01405 if (strip->flag & (ACTSTRIP_CYCLIC_USEX | ACTSTRIP_CYCLIC_USEY | ACTSTRIP_CYCLIC_USEZ)) { 01406 if (strip->flag & ACTSTRIP_CYCLIC_USEX) pose->cyclic_offset[0]= time*min[0]; 01407 if (strip->flag & ACTSTRIP_CYCLIC_USEY) pose->cyclic_offset[1]= time*min[1]; 01408 if (strip->flag & ACTSTRIP_CYCLIC_USEZ) pose->cyclic_offset[2]= time*min[2]; 01409 } else { 01410 if( fabs(min[0]) >= fabs(min[1]) && fabs(min[0]) >= fabs(min[2])) 01411 pose->cyclic_offset[0]= time*min[0]; 01412 else if( fabs(min[1]) >= fabs(min[0]) && fabs(min[1]) >= fabs(min[2])) 01413 pose->cyclic_offset[1]= time*min[1]; 01414 else 01415 pose->cyclic_offset[2]= time*min[2]; 01416 } 01417 } 01418 } 01419 } 01420 } 01421 } 01422 01423 /* simple case for now; only the curve path with constraint value > 0.5 */ 01424 /* blending we might do later... */ 01425 static Object *get_parent_path(Object *ob) 01426 { 01427 bConstraint *con; 01428 01429 if(ob->parent && ob->parent->type==OB_CURVE) 01430 return ob->parent; 01431 01432 for (con = ob->constraints.first; con; con=con->next) { 01433 if(con->type==CONSTRAINT_TYPE_FOLLOWPATH) { 01434 if(con->enforce>0.5f) { 01435 bFollowPathConstraint *data= con->data; 01436 return data->tar; 01437 } 01438 } 01439 } 01440 return NULL; 01441 } 01442 01443 /* ************** do the action ************ */ 01444 01445 /* ----- nla, etc. --------- */ 01446 01447 static void do_nla(Scene *scene, Object *ob, int blocktype) 01448 { 01449 bPose *tpose= NULL; 01450 Key *key= NULL; 01451 ListBase tchanbase={NULL, NULL}, chanbase={NULL, NULL}; 01452 bActionStrip *strip, *striplast=NULL, *stripfirst=NULL; 01453 float striptime, frametime, length, actlength; 01454 float blendfac, stripframe; 01455 float scene_cfra= BKE_curframe(scene); 01456 int doit, dostride; 01457 01458 if(blocktype==ID_AR) { 01459 copy_pose(&tpose, ob->pose, 1); 01460 rest_pose(ob->pose); // potentially destroying current not-keyed pose 01461 } 01462 else { 01463 key= ob_get_key(ob); 01464 } 01465 01466 /* check on extend to left or right, when no strip is hit by 'cfra' */ 01467 for (strip=ob->nlastrips.first; strip; strip=strip->next) { 01468 /* escape loop on a hit */ 01469 if( scene_cfra >= strip->start && scene_cfra <= strip->end + 0.1f) /* note 0.1 comes back below */ 01470 break; 01471 if(scene_cfra < strip->start) { 01472 if(stripfirst==NULL) 01473 stripfirst= strip; 01474 else if(stripfirst->start > strip->start) 01475 stripfirst= strip; 01476 } 01477 else if(scene_cfra > strip->end) { 01478 if(striplast==NULL) 01479 striplast= strip; 01480 else if(striplast->end < strip->end) 01481 striplast= strip; 01482 } 01483 } 01484 if(strip==NULL) { /* extend */ 01485 if(striplast) 01486 scene_cfra= striplast->end; 01487 else if(stripfirst) 01488 scene_cfra= stripfirst->start; 01489 } 01490 01491 /* and now go over all strips */ 01492 for (strip=ob->nlastrips.first; strip; strip=strip->next){ 01493 doit=dostride= 0; 01494 01495 if (strip->act && !(strip->flag & ACTSTRIP_MUTE)) { /* so theres an action */ 01496 01497 /* Determine if the current frame is within the strip's range */ 01498 length = strip->end-strip->start; 01499 actlength = strip->actend-strip->actstart; 01500 striptime = (scene_cfra-(strip->start)) / length; 01501 stripframe = (scene_cfra-(strip->start)) ; 01502 01503 if (striptime>=0.0){ 01504 01505 if(blocktype==ID_AR) 01506 rest_pose(tpose); 01507 01508 /* To handle repeat, we add 0.1 frame extra to make sure the last frame is included */ 01509 if (striptime < 1.0f + 0.1f/length) { 01510 01511 /* Handle path */ 01512 if ((strip->flag & ACTSTRIP_USESTRIDE) && (blocktype==ID_AR) && (ob->ipoflag & OB_DISABLE_PATH)==0){ 01513 Object *parent= get_parent_path(ob); 01514 01515 if (parent) { 01516 Curve *cu = parent->data; 01517 float ctime, pdist; 01518 01519 if (cu->flag & CU_PATH){ 01520 /* Ensure we have a valid path */ 01521 if(cu->path==NULL || cu->path->data==NULL) makeDispListCurveTypes(scene, parent, 0); 01522 if(cu->path) { 01523 01524 /* Find the position on the path */ 01525 ctime= bsystem_time(scene, ob, scene_cfra, 0.0); 01526 01527 if(calc_ipo_spec(cu->ipo, CU_SPEED, &ctime)==0) { 01528 /* correct for actions not starting on zero */ 01529 ctime= (ctime - strip->actstart)/cu->pathlen; 01530 CLAMP(ctime, 0.0, 1.0); 01531 } 01532 pdist = ctime*cu->path->totdist; 01533 01534 if(tpose && strip->stridechannel[0]) { 01535 striptime= stridechannel_frame(parent, ob->size[0], strip, cu->path, pdist, tpose->stride_offset); 01536 } 01537 else { 01538 if (strip->stridelen) { 01539 striptime = pdist / strip->stridelen; 01540 striptime = (float)fmod (striptime+strip->actoffs, 1.0); 01541 } 01542 else 01543 striptime = 0; 01544 } 01545 01546 frametime = (striptime * actlength) + strip->actstart; 01547 frametime= bsystem_time(scene, ob, frametime, 0.0); 01548 01549 if(blocktype==ID_AR) { 01550 extract_pose_from_action (tpose, strip->act, frametime); 01551 } 01552 else if(blocktype==ID_OB) { 01553 extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime); 01554 if(key) 01555 extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime); 01556 } 01557 doit=dostride= 1; 01558 } 01559 } 01560 } 01561 } 01562 /* To handle repeat, we add 0.1 frame extra to make sure the last frame is included */ 01563 else { 01564 01565 /* Mod to repeat */ 01566 if(strip->repeat!=1.0f) { 01567 float cycle= striptime*strip->repeat; 01568 01569 striptime = (float)fmod (cycle, 1.0f + 0.1f/length); 01570 cycle-= striptime; 01571 01572 if(blocktype==ID_AR) 01573 cyclic_offs_bone(ob, tpose, strip, cycle); 01574 } 01575 01576 frametime = (striptime * actlength) + strip->actstart; 01577 frametime= nla_time(scene, frametime, (float)strip->repeat); 01578 01579 if(blocktype==ID_AR) { 01580 extract_pose_from_action (tpose, strip->act, frametime); 01581 } 01582 else if(blocktype==ID_OB) { 01583 extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime); 01584 if(key) 01585 extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime); 01586 } 01587 01588 doit=1; 01589 } 01590 } 01591 /* Handle extend */ 01592 else { 01593 if (strip->flag & ACTSTRIP_HOLDLASTFRAME){ 01594 /* we want the strip to hold on the exact fraction of the repeat value */ 01595 01596 frametime = actlength * (strip->repeat-(int)strip->repeat); 01597 if(frametime<=0.000001f) frametime= actlength; /* rounding errors... */ 01598 frametime= bsystem_time(scene, ob, frametime+strip->actstart, 0.0); 01599 01600 if(blocktype==ID_AR) 01601 extract_pose_from_action (tpose, strip->act, frametime); 01602 else if(blocktype==ID_OB) { 01603 extract_ipochannels_from_action(&tchanbase, &ob->id, strip->act, "Object", frametime); 01604 if(key) 01605 extract_ipochannels_from_action(&tchanbase, &key->id, strip->act, "Shape", frametime); 01606 } 01607 01608 /* handle cycle hold */ 01609 if(strip->repeat!=1.0f) { 01610 if(blocktype==ID_AR) 01611 cyclic_offs_bone(ob, tpose, strip, strip->repeat-1.0f); 01612 } 01613 01614 doit=1; 01615 } 01616 } 01617 01618 /* Handle blendin & blendout */ 01619 if (doit){ 01620 /* Handle blendin */ 01621 01622 if (strip->blendin>0.0 && stripframe<=strip->blendin && scene_cfra>=strip->start){ 01623 blendfac = stripframe/strip->blendin; 01624 } 01625 else if (strip->blendout>0.0 && stripframe>=(length-strip->blendout) && scene_cfra<=strip->end){ 01626 blendfac = (length-stripframe)/(strip->blendout); 01627 } 01628 else 01629 blendfac = 1; 01630 01631 if(blocktype==ID_AR) {/* Blend this pose with the accumulated pose */ 01632 /* offset bone, for matching cycles */ 01633 blend_pose_offset_bone (strip, ob->pose, tpose, blendfac, strip->mode); 01634 01635 blend_poses (ob->pose, tpose, blendfac, strip->mode); 01636 if(dostride) 01637 blend_pose_strides (ob->pose, tpose, blendfac, strip->mode); 01638 } 01639 else { 01640 blend_ipochannels(&chanbase, &tchanbase, blendfac, strip->mode); 01641 BLI_freelistN(&tchanbase); 01642 } 01643 } 01644 } 01645 } 01646 } 01647 01648 if(blocktype==ID_OB) { 01649 execute_ipochannels(&chanbase); 01650 } 01651 else if(blocktype==ID_AR) { 01652 /* apply stride offset to object */ 01653 add_v3_v3(ob->obmat[3], ob->pose->stride_offset); 01654 } 01655 01656 /* free */ 01657 if (tpose) 01658 free_pose(tpose); 01659 if(chanbase.first) 01660 BLI_freelistN(&chanbase); 01661 } 01662 01663 #endif // XXX OLD ANIMATION SYSTEM (TO BE REMOVED)