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

poseUtils.c « armature « editors « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: b8b9c354d9adcd2713a16e964f27015eabb4c656 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
/**
 * $Id$
 *
 * ***** 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 *****
 */

#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <math.h>
#include <float.h>

#include "MEM_guardedalloc.h"

#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_dynstr.h"
#include "BLI_dlrbTree.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"
#include "BKE_depsgraph.h"

#include "BKE_context.h"

#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;
 * primarily the functions in question concern Animato <-> Pose 
 * convenience functions, such as applying/getting pose values
 * and/or inserting keyframes for these.
 */
/* *********************************************** */ 
/* FCurves <-> PoseChannels Links */

/* helper for poseAnim_mapping_get() -> get the relevant F-Curves per PoseChannel */
static void fcurves_to_pchan_links_get (ListBase *pfLinks, Object *ob, bAction *act, bPoseChannel *pchan)
{
	ListBase curves = {NULL, NULL};
	int transFlags = action_get_item_transforms(act, ob, pchan, &curves);
	
	pchan->flag &= ~(POSE_LOC|POSE_ROT|POSE_SIZE);
	
	/* check if any transforms found... */
	if (transFlags) {
		/* make new linkage data */
		tPChanFCurveLink *pfl= MEM_callocN(sizeof(tPChanFCurveLink), "tPChanFCurveLink");
		PointerRNA ptr;
		
		pfl->fcurves= curves;
		pfl->pchan= pchan;
		
		/* get the RNA path to this pchan - this needs to be freed! */
		RNA_pointer_create((ID *)ob, &RNA_PoseBone, pchan, &ptr);
		pfl->pchan_path= RNA_path_from_ID_to_struct(&ptr);
		
		/* add linkage data to operator data */
		BLI_addtail(pfLinks, pfl);
		
		/* 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;
			
		/* store current transforms */
		// TODO: store axis-angle too?
		VECCOPY(pfl->oldloc, pchan->loc);
		VECCOPY(pfl->oldrot, pchan->eul);
		VECCOPY(pfl->oldscale, pchan->size);
		QUATCOPY(pfl->oldquat, pchan->quat);
	}
} 


/* get sets of F-Curves providing transforms for the bones in the Pose  */
// TODO: separate the inner workings out to another helper func, since we need option of whether to take selected or visible bones...
void poseAnim_mapping_get (bContext *C, ListBase *pfLinks, Object *ob, bAction *act)
{	
	/* for each Pose-Channel which gets affected, get the F-Curves for that channel 
	 * and set the relevant transform flags...
	 */
	CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 
	{
		fcurves_to_pchan_links_get(pfLinks, ob, act, pchan);
	}
	CTX_DATA_END;
}

/* free F-Curve <-> PoseChannel links  */
void poseAnim_mapping_free (ListBase *pfLinks)
{
	tPChanFCurveLink *pfl, *pfln=NULL;
		
	/* free the temp pchan links and their data */
	for (pfl= pfLinks->first; pfl; pfl= pfln) {
		pfln= pfl->next;
		
		/* free list of F-Curve reference links */
		BLI_freelistN(&pfl->fcurves);
		
		/* free pchan RNA Path */
		MEM_freeN(pfl->pchan_path);
		
		/* free link itself */
		BLI_freelinkN(pfLinks, pfl);
	}
}

/* ------------------------- */

/* helper for apply() / reset() - refresh the data */
void poseAnim_mapping_refresh (bContext *C, Scene *scene, Object *ob)
{
	bArmature *arm= (bArmature *)ob->data;
	
	/* old optimize trick... this enforces to bypass the depgraph 
	 *	- note: code copied from transform_generics.c -> recalcData()
	 */
	// FIXME: shouldn't this use the builtin stuff?
	if ((arm->flag & ARM_DELAYDEFORM)==0)
		DAG_id_flush_update(&ob->id, OB_RECALC_DATA);  /* sets recalc flags */
	else
		where_is_pose(scene, ob);
	
	/* note, notifier might evolve */
	WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
}

/* reset changes made to current pose */
void poseAnim_mapping_reset (ListBase *pfLinks)
{
	tPChanFCurveLink *pfl;
	
	/* iterate over each pose-channel affected, restoring all channels to their original values */
	for (pfl= pfLinks->first; pfl; pfl= pfl->next) {
		bPoseChannel *pchan= pfl->pchan;
		
		/* just copy all the values over regardless of whether they changed or not */
		// TODO; include axis-angle here too?
		VECCOPY(pchan->loc, pfl->oldloc);
		VECCOPY(pchan->eul, pfl->oldrot);
		VECCOPY(pchan->size, pfl->oldscale);
		QUATCOPY(pchan->quat, pfl->oldquat);
	}
}

/* perform autokeyframing after changes were made + confirmed */
void poseAnim_mapping_autoKeyframe (bContext *C, Scene *scene, Object *ob, ListBase *pfLinks, float cframe)
{
	static short keyingsets_need_init = 1;
	static KeyingSet *ks_loc = NULL;
	static KeyingSet *ks_rot = NULL;
	static KeyingSet *ks_scale = NULL;
	
	/* get keyingsets the first time this is run? 
	 * NOTE: it should be safe to store these static, since they're currently builtin ones
	 * but maybe later this may change, in which case this code needs to be revised!
	 */
	if (keyingsets_need_init) {
		ks_loc= ANIM_builtin_keyingset_get_named(NULL, "Location");
		ks_rot= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
		ks_scale= ANIM_builtin_keyingset_get_named(NULL, "Scaling");
		
		keyingsets_need_init = 0;
	}
	
	/* insert keyframes as necessary if autokeyframing */
	if (autokeyframe_cfra_can_key(scene, &ob->id)) {
		tPChanFCurveLink *pfl;
		
		/* iterate over each pose-channel affected, applying the changes */
		for (pfl= pfLinks->first; pfl; pfl= pfl->next) {
			ListBase dsources = {NULL, NULL};
			bPoseChannel *pchan= pfl->pchan;
			
			/* add datasource override for the PoseChannel so KeyingSet will do right thing */
			ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan); 
			
			/* insert keyframes 
			 * 	- these keyingsets here use dsources, since we need to specify exactly which keyframes get affected
			 */
			if (pchan->flag & POSE_LOC)
				ANIM_apply_keyingset(C, &dsources, NULL, ks_loc, MODIFYKEY_MODE_INSERT, cframe);
			if (pchan->flag & POSE_ROT)
				ANIM_apply_keyingset(C, &dsources, NULL, ks_rot, MODIFYKEY_MODE_INSERT, cframe);
			if (pchan->flag & POSE_SIZE)
				ANIM_apply_keyingset(C, &dsources, NULL, ks_scale, MODIFYKEY_MODE_INSERT, cframe);
				
			/* free the temp info */
			BLI_freelistN(&dsources);
		}
	}
}

/* ------------------------- */

/* find the next F-Curve for a PoseChannel with matching path... 
 *	- path is not just the pfl rna_path, since that path doesn't have property info yet
 */
LinkData *poseAnim_mapping_getNextFCurve (ListBase *fcuLinks, LinkData *prev, char *path)
{
	LinkData *first= (prev)? prev->next : (fcuLinks)? fcuLinks->first : NULL;
	LinkData *ld;
	
	/* check each link to see if the linked F-Curve has a matching path */
	for (ld= first; ld; ld= ld->next) {
		FCurve *fcu= (FCurve *)ld->data;
		
		/* check if paths match */
		if (strcmp(path, fcu->rna_path) == 0)
			return ld;
	}	
	
	/* none found */
	return NULL;
}

/* *********************************************** */