2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2010-02-19 11:42:21 +00:00
|
|
|
* ***** 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2009, Blender Foundation, Joshua Leung
|
|
|
|
* This is a new part of Blender
|
|
|
|
*
|
|
|
|
* Contributor(s): Joshua Leung
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
2013-02-28 00:01:20 +00:00
|
|
|
/** \file blender/editors/armature/pose_utils.c
|
2011-02-27 20:29:51 +00:00
|
|
|
* \ingroup edarmature
|
|
|
|
*/
|
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "BLI_math.h"
|
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
|
|
|
|
#include "DNA_anim_types.h"
|
|
|
|
#include "DNA_armature_types.h"
|
|
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
|
|
|
|
#include "BKE_action.h"
|
|
|
|
#include "BKE_armature.h"
|
2011-03-13 12:22:57 +00:00
|
|
|
#include "BKE_idprop.h"
|
2018-10-19 19:08:12 -03:00
|
|
|
#include "BKE_layer.h"
|
2018-06-12 17:57:24 +02:00
|
|
|
#include "BKE_main.h"
|
2018-10-19 19:08:12 -03:00
|
|
|
#include "BKE_object.h"
|
2010-02-19 11:42:21 +00:00
|
|
|
|
|
|
|
#include "BKE_context.h"
|
|
|
|
|
2017-06-08 10:14:53 +02:00
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
#include "RNA_access.h"
|
|
|
|
|
|
|
|
#include "WM_api.h"
|
|
|
|
#include "WM_types.h"
|
|
|
|
|
|
|
|
#include "ED_armature.h"
|
|
|
|
#include "ED_keyframing.h"
|
|
|
|
|
|
|
|
#include "armature_intern.h"
|
|
|
|
|
|
|
|
/* *********************************************** */
|
|
|
|
/* Contents of this File:
|
|
|
|
*
|
|
|
|
* This file contains methods shared between Pose Slide and Pose Lib;
|
2018-06-01 18:19:39 +02:00
|
|
|
* primarily the functions in question concern Animato <-> Pose
|
2010-02-19 11:42:21 +00:00
|
|
|
* convenience functions, such as applying/getting pose values
|
|
|
|
* and/or inserting keyframes for these.
|
|
|
|
*/
|
2018-06-04 09:31:30 +02:00
|
|
|
/* *********************************************** */
|
2010-02-19 11:42:21 +00:00
|
|
|
/* FCurves <-> PoseChannels Links */
|
|
|
|
|
|
|
|
/* helper for poseAnim_mapping_get() -> get the relevant F-Curves per PoseChannel */
|
2012-05-08 20:18:33 +00:00
|
|
|
static void fcurves_to_pchan_links_get(ListBase *pfLinks, Object *ob, bAction *act, bPoseChannel *pchan)
|
2010-02-19 11:42:21 +00:00
|
|
|
{
|
|
|
|
ListBase curves = {NULL, NULL};
|
|
|
|
int transFlags = action_get_item_transforms(act, ob, pchan, &curves);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2016-05-18 03:19:06 +12:00
|
|
|
pchan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SIZE | POSE_BBONE_SHAPE);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* check if any transforms found... */
|
|
|
|
if (transFlags) {
|
|
|
|
/* make new linkage data */
|
2012-05-08 20:18:33 +00:00
|
|
|
tPChanFCurveLink *pfl = MEM_callocN(sizeof(tPChanFCurveLink), "tPChanFCurveLink");
|
2010-02-19 11:42:21 +00:00
|
|
|
PointerRNA ptr;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-10-19 19:08:12 -03:00
|
|
|
pfl->ob = ob;
|
2012-05-08 20:18:33 +00:00
|
|
|
pfl->fcurves = curves;
|
|
|
|
pfl->pchan = pchan;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* get the RNA path to this pchan - this needs to be freed! */
|
|
|
|
RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan, &ptr);
|
2012-05-08 20:18:33 +00:00
|
|
|
pfl->pchan_path = RNA_path_from_ID_to_struct(&ptr);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* add linkage data to operator data */
|
|
|
|
BLI_addtail(pfLinks, pfl);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* set pchan's transform flags */
|
|
|
|
if (transFlags & ACT_TRANS_LOC)
|
|
|
|
pchan->flag |= POSE_LOC;
|
|
|
|
if (transFlags & ACT_TRANS_ROT)
|
|
|
|
pchan->flag |= POSE_ROT;
|
|
|
|
if (transFlags & ACT_TRANS_SCALE)
|
|
|
|
pchan->flag |= POSE_SIZE;
|
2016-05-18 03:19:06 +12:00
|
|
|
if (transFlags & ACT_TRANS_BBONE)
|
|
|
|
pchan->flag |= POSE_BBONE_SHAPE;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* store current transforms */
|
2011-10-28 12:40:15 +00:00
|
|
|
copy_v3_v3(pfl->oldloc, pchan->loc);
|
|
|
|
copy_v3_v3(pfl->oldrot, pchan->eul);
|
|
|
|
copy_v3_v3(pfl->oldscale, pchan->size);
|
|
|
|
copy_qt_qt(pfl->oldquat, pchan->quat);
|
|
|
|
copy_v3_v3(pfl->oldaxis, pchan->rotAxis);
|
2011-03-13 12:22:57 +00:00
|
|
|
pfl->oldangle = pchan->rotAngle;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2016-05-18 03:19:06 +12:00
|
|
|
/* store current bbone values */
|
|
|
|
pfl->roll1 = pchan->roll1;
|
|
|
|
pfl->roll2 = pchan->roll2;
|
|
|
|
pfl->curveInX = pchan->curveInX;
|
|
|
|
pfl->curveInY = pchan->curveInY;
|
|
|
|
pfl->curveOutX = pchan->curveOutX;
|
|
|
|
pfl->curveOutY = pchan->curveOutY;
|
2017-11-01 13:38:51 +13:00
|
|
|
pfl->ease1 = pchan->ease1;
|
|
|
|
pfl->ease2 = pchan->ease2;
|
2016-05-18 03:19:06 +12:00
|
|
|
pfl->scaleIn = pchan->scaleIn;
|
|
|
|
pfl->scaleOut = pchan->scaleOut;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2011-03-13 12:22:57 +00:00
|
|
|
/* make copy of custom properties */
|
2011-07-09 14:33:28 +00:00
|
|
|
if (pchan->prop && (transFlags & ACT_TRANS_PROP))
|
2011-03-13 12:22:57 +00:00
|
|
|
pfl->oldprops = IDP_CopyProperty(pchan->prop);
|
2010-02-19 11:42:21 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
}
|
2010-02-19 11:42:21 +00:00
|
|
|
|
2018-10-19 19:08:12 -03:00
|
|
|
/**
|
|
|
|
* Returns a valid pose armature for this object, else returns NULL.
|
|
|
|
**/
|
|
|
|
Object *poseAnim_object_get(Object *ob_)
|
|
|
|
{
|
|
|
|
Object *ob = BKE_object_pose_armature_get(ob_);
|
|
|
|
if (!ELEM(NULL,
|
|
|
|
ob,
|
|
|
|
ob->data,
|
|
|
|
ob->adt,
|
|
|
|
ob->adt->action))
|
|
|
|
{
|
|
|
|
return ob;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-02-19 11:42:21 +00:00
|
|
|
|
|
|
|
/* get sets of F-Curves providing transforms for the bones in the Pose */
|
2018-10-19 19:08:12 -03:00
|
|
|
void poseAnim_mapping_get(bContext *C, ListBase *pfLinks)
|
2018-06-04 09:31:30 +02:00
|
|
|
{
|
|
|
|
/* for each Pose-Channel which gets affected, get the F-Curves for that channel
|
2010-02-19 11:42:21 +00:00
|
|
|
* and set the relevant transform flags...
|
|
|
|
*/
|
2018-10-19 19:08:12 -03:00
|
|
|
Object *prev_ob, *ob_pose_armature;
|
|
|
|
|
|
|
|
prev_ob = NULL;
|
|
|
|
ob_pose_armature = NULL;
|
|
|
|
CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, selected_pose_bones, Object *, ob)
|
2012-04-30 16:22:40 +00:00
|
|
|
{
|
2018-10-19 19:08:12 -03:00
|
|
|
if (ob != prev_ob) {
|
|
|
|
prev_ob = ob;
|
|
|
|
ob_pose_armature = poseAnim_object_get(ob);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ob_pose_armature == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
fcurves_to_pchan_links_get(pfLinks,
|
|
|
|
ob_pose_armature,
|
|
|
|
ob_pose_armature->adt->action,
|
|
|
|
pchan);
|
2010-02-19 11:42:21 +00:00
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2011-03-31 01:37:42 +00:00
|
|
|
/* if no PoseChannels were found, try a second pass, doing visible ones instead
|
|
|
|
* i.e. if nothing selected, do whole pose
|
|
|
|
*/
|
2014-02-08 06:07:10 +11:00
|
|
|
if (BLI_listbase_is_empty(pfLinks)) {
|
2018-10-19 19:08:12 -03:00
|
|
|
prev_ob = NULL;
|
|
|
|
ob_pose_armature = NULL;
|
|
|
|
CTX_DATA_BEGIN_WITH_ID(C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob)
|
2012-04-30 16:22:40 +00:00
|
|
|
{
|
2018-10-19 19:08:12 -03:00
|
|
|
if (ob != prev_ob) {
|
|
|
|
prev_ob = ob;
|
|
|
|
ob_pose_armature = poseAnim_object_get(ob);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ob_pose_armature == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
fcurves_to_pchan_links_get(pfLinks,
|
|
|
|
ob_pose_armature,
|
|
|
|
ob_pose_armature->adt->action,
|
|
|
|
pchan);
|
2011-03-31 01:37:42 +00:00
|
|
|
}
|
|
|
|
CTX_DATA_END;
|
|
|
|
}
|
2010-02-19 11:42:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* free F-Curve <-> PoseChannel links */
|
2012-04-29 17:11:40 +00:00
|
|
|
void poseAnim_mapping_free(ListBase *pfLinks)
|
2010-02-19 11:42:21 +00:00
|
|
|
{
|
2012-05-08 20:18:33 +00:00
|
|
|
tPChanFCurveLink *pfl, *pfln = NULL;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* free the temp pchan links and their data */
|
2012-05-08 20:18:33 +00:00
|
|
|
for (pfl = pfLinks->first; pfl; pfl = pfln) {
|
|
|
|
pfln = pfl->next;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2011-03-13 12:22:57 +00:00
|
|
|
/* free custom properties */
|
|
|
|
if (pfl->oldprops) {
|
|
|
|
IDP_FreeProperty(pfl->oldprops);
|
|
|
|
MEM_freeN(pfl->oldprops);
|
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* free list of F-Curve reference links */
|
|
|
|
BLI_freelistN(&pfl->fcurves);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* free pchan RNA Path */
|
|
|
|
MEM_freeN(pfl->pchan_path);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* free link itself */
|
|
|
|
BLI_freelinkN(pfLinks, pfl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------------- */
|
|
|
|
|
|
|
|
/* helper for apply() / reset() - refresh the data */
|
2012-04-29 17:11:40 +00:00
|
|
|
void poseAnim_mapping_refresh(bContext *C, Scene *scene, Object *ob)
|
2010-02-19 11:42:21 +00:00
|
|
|
{
|
2018-04-06 12:07:27 +02:00
|
|
|
Depsgraph *depsgraph = CTX_data_depsgraph(C);
|
2012-05-08 20:18:33 +00:00
|
|
|
bArmature *arm = (bArmature *)ob->data;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
|
|
|
/* old optimize trick... this enforces to bypass the depgraph
|
2010-02-19 11:42:21 +00:00
|
|
|
* - note: code copied from transform_generics.c -> recalcData()
|
|
|
|
*/
|
2012-07-07 22:51:57 +00:00
|
|
|
/* FIXME: shouldn't this use the builtin stuff? */
|
2012-05-08 20:18:33 +00:00
|
|
|
if ((arm->flag & ARM_DELAYDEFORM) == 0)
|
2017-06-08 10:14:53 +02:00
|
|
|
DEG_id_tag_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
|
2010-02-19 11:42:21 +00:00
|
|
|
else
|
2018-04-06 12:07:27 +02:00
|
|
|
BKE_pose_where_is(depsgraph, scene, ob);
|
2018-06-04 09:31:30 +02:00
|
|
|
|
WIP COW Fix: Insert keyframe operators/api now queries depsgraph for evaluated data
When using copy on write, insert keyframe operators were reading from old
bmain data instead of COW data. This meant that inserting keyframes would
often read old/stale data, resulting in invalid keyframes getting created
(e.g. from last transform operation, instead of actual current state).
This commit makes it so that keyframing operators will ask depsgraph for
the evaluated copy of the data, so that it can read values from that. It
introduces a new function - `DEG_get_evaluated_rna_pointer()`, which when
working correctly/fully, should work just like the other `DEG_get_evaluated_*()`
functions, except it lets you pass in an RNA Pointer.
However, currently, this is only done for Pose Bones (as a dirty hack, since this
is an important/pivotal requirement for production) and/or datablock
properties directly (since we can just use the DEG_get_evaluated_id() directly).
on the datablock.
Committing to a branch for now as this all needs more testing. More work to come
later at a more sane time of day!
2018-05-18 20:36:48 +02:00
|
|
|
DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE); /* otherwise animation doesn't get updated */
|
2012-05-08 20:18:33 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
|
2010-02-19 11:42:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* reset changes made to current pose */
|
2012-04-29 17:11:40 +00:00
|
|
|
void poseAnim_mapping_reset(ListBase *pfLinks)
|
2010-02-19 11:42:21 +00:00
|
|
|
{
|
|
|
|
tPChanFCurveLink *pfl;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* iterate over each pose-channel affected, restoring all channels to their original values */
|
2012-05-08 20:18:33 +00:00
|
|
|
for (pfl = pfLinks->first; pfl; pfl = pfl->next) {
|
|
|
|
bPoseChannel *pchan = pfl->pchan;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* just copy all the values over regardless of whether they changed or not */
|
2011-10-28 12:40:15 +00:00
|
|
|
copy_v3_v3(pchan->loc, pfl->oldloc);
|
|
|
|
copy_v3_v3(pchan->eul, pfl->oldrot);
|
|
|
|
copy_v3_v3(pchan->size, pfl->oldscale);
|
|
|
|
copy_qt_qt(pchan->quat, pfl->oldquat);
|
|
|
|
copy_v3_v3(pchan->rotAxis, pfl->oldaxis);
|
2011-03-13 12:22:57 +00:00
|
|
|
pchan->rotAngle = pfl->oldangle;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2016-05-18 03:19:06 +12:00
|
|
|
/* store current bbone values */
|
|
|
|
pchan->roll1 = pfl->roll1;
|
|
|
|
pchan->roll2 = pfl->roll2;
|
|
|
|
pchan->curveInX = pfl->curveInX;
|
|
|
|
pchan->curveInY = pfl->curveInY;
|
|
|
|
pchan->curveOutX = pfl->curveOutX;
|
|
|
|
pchan->curveOutY = pfl->curveOutY;
|
2017-11-01 13:38:51 +13:00
|
|
|
pchan->ease1 = pfl->ease1;
|
|
|
|
pchan->ease2 = pfl->ease2;
|
2016-05-18 03:19:06 +12:00
|
|
|
pchan->scaleIn = pfl->scaleIn;
|
|
|
|
pchan->scaleOut = pfl->scaleOut;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2011-03-13 12:22:57 +00:00
|
|
|
/* just overwrite values of properties from the stored copies (there should be some) */
|
|
|
|
if (pfl->oldprops)
|
|
|
|
IDP_SyncGroupValues(pfl->pchan->prop, pfl->oldprops);
|
2010-02-19 11:42:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* perform autokeyframing after changes were made + confirmed */
|
2018-10-19 19:08:12 -03:00
|
|
|
void poseAnim_mapping_autoKeyframe(bContext *C, Scene *scene, ListBase *pfLinks, float cframe)
|
2010-02-19 11:42:21 +00:00
|
|
|
{
|
2018-10-19 19:08:12 -03:00
|
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
|
|
bool skip = true;
|
|
|
|
|
|
|
|
FOREACH_OBJECT_IN_MODE_BEGIN(view_layer, OB_MODE_POSE, ob) {
|
|
|
|
ob->id.tag &= ~LIB_TAG_DOIT;
|
|
|
|
ob = poseAnim_object_get(ob);
|
|
|
|
|
|
|
|
/* Ensure validity of the settings from the context. */
|
|
|
|
if (ob == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (autokeyframe_cfra_can_key(scene, &ob->id)) {
|
|
|
|
ob->id.tag |= LIB_TAG_DOIT;
|
|
|
|
skip = false;
|
|
|
|
}
|
|
|
|
} FOREACH_OBJECT_IN_MODE_END;
|
|
|
|
|
|
|
|
if (skip) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* insert keyframes as necessary if autokeyframing */
|
2018-10-19 19:08:12 -03:00
|
|
|
KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_WHOLE_CHARACTER_ID);
|
|
|
|
ListBase dsources = {NULL, NULL};
|
|
|
|
tPChanFCurveLink *pfl;
|
|
|
|
|
|
|
|
/* iterate over each pose-channel affected, tagging bones to be keyed */
|
|
|
|
/* XXX: here we already have the information about what transforms exist, though
|
|
|
|
* it might be easier to just overwrite all using normal mechanisms
|
|
|
|
*/
|
|
|
|
for (pfl = pfLinks->first; pfl; pfl = pfl->next) {
|
|
|
|
bPoseChannel *pchan = pfl->pchan;
|
|
|
|
|
|
|
|
if ((pfl->ob->id.tag & LIB_TAG_DOIT) == 0) {
|
|
|
|
continue;
|
2010-02-19 11:42:21 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2018-10-19 19:08:12 -03:00
|
|
|
/* add datasource override for the PoseChannel, to be used later */
|
|
|
|
ANIM_relative_keyingset_add_source(&dsources, &pfl->ob->id, &RNA_PoseBone, pchan);
|
|
|
|
|
|
|
|
/* clear any unkeyed tags */
|
|
|
|
if (pchan->bone) {
|
|
|
|
pchan->bone->flag &= ~BONE_UNKEYED;
|
2011-07-12 03:02:53 +00:00
|
|
|
}
|
2010-02-19 11:42:21 +00:00
|
|
|
}
|
2018-10-19 19:08:12 -03:00
|
|
|
|
|
|
|
/* insert keyframes for all relevant bones in one go */
|
|
|
|
ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cframe);
|
|
|
|
BLI_freelistN(&dsources);
|
|
|
|
|
|
|
|
/* do the bone paths
|
|
|
|
* - only do this if keyframes should have been added
|
|
|
|
* - do not calculate unless there are paths already to update...
|
|
|
|
*/
|
|
|
|
FOREACH_OBJECT_IN_MODE_BEGIN(view_layer, OB_MODE_POSE, ob) {
|
|
|
|
if (ob->id.tag & LIB_TAG_DOIT) {
|
|
|
|
if (ob->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) {
|
|
|
|
//ED_pose_clear_paths(C, ob); // XXX for now, don't need to clear
|
|
|
|
ED_pose_recalculate_paths(C, scene, ob, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} FOREACH_OBJECT_IN_MODE_END;
|
2010-02-19 11:42:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------------- */
|
|
|
|
|
2018-06-04 09:31:30 +02:00
|
|
|
/* find the next F-Curve for a PoseChannel with matching path...
|
2010-02-19 11:42:21 +00:00
|
|
|
* - path is not just the pfl rna_path, since that path doesn't have property info yet
|
|
|
|
*/
|
2012-05-08 20:18:33 +00:00
|
|
|
LinkData *poseAnim_mapping_getNextFCurve(ListBase *fcuLinks, LinkData *prev, const char *path)
|
2010-02-19 11:42:21 +00:00
|
|
|
{
|
2012-05-08 20:18:33 +00:00
|
|
|
LinkData *first = (prev) ? prev->next : (fcuLinks) ? fcuLinks->first : NULL;
|
2010-02-19 11:42:21 +00:00
|
|
|
LinkData *ld;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* check each link to see if the linked F-Curve has a matching path */
|
2012-05-08 20:18:33 +00:00
|
|
|
for (ld = first; ld; ld = ld->next) {
|
|
|
|
FCurve *fcu = (FCurve *)ld->data;
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* check if paths match */
|
2015-01-26 16:03:11 +01:00
|
|
|
if (STREQ(path, fcu->rna_path))
|
2010-02-19 11:42:21 +00:00
|
|
|
return ld;
|
2012-10-21 05:46:41 +00:00
|
|
|
}
|
2018-06-04 09:31:30 +02:00
|
|
|
|
2010-02-19 11:42:21 +00:00
|
|
|
/* none found */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-06-04 09:31:30 +02:00
|
|
|
/* *********************************************** */
|