89 if (fcu && fcu->
bezt) {
102 FCurve **fcurves =
static_cast<FCurve **
>(alloca(
sizeof(*fcurves) * fkc_len));
104 for (
int i = 0; i < fkc_len; i++) {
105 if (fcurves[i] && fcurves[i]->bezt) {
106 fkc[i].
fcurve = fcurves[i];
120 const float *keyed_frames,
121 int keyed_frames_len)
129 for (
int frame_index = 0; frame_index < keyed_frames_len; frame_index++) {
130 const float evaltime = keyed_frames[frame_index];
142 while (frame_index < keyed_frames_len) {
143 const float evaltime = keyed_frames[frame_index];
144 const float bezt_time = roundf(bezt->
vec[1][0]);
153 if (bezt == bezt_end) {
159 while (frame_index < keyed_frames_len) {
171 char path_xform[256];
174 const int path_xform_prefix_len =
SNPRINTF(path_xform,
"pose.bones[\"%s\"]", pchan_name_esc);
175 char *path_xform_suffix = path_xform + path_xform_prefix_len;
176 const int path_xform_suffix_maxncpy =
sizeof(path_xform) - path_xform_prefix_len;
194 FCurve_KeyCache loc[3], eul[3], quat[4], rotAxis[3], rotAngle, size[3], rotmode;
195 } fkc_pchan = {{{
nullptr}}};
197#define FCURVE_ASSIGN_VALUE(id, path_test_suffix, index) \
198 BLI_strncpy(path_xform_suffix, path_test_suffix, path_xform_suffix_maxncpy); \
199 action_flip_pchan_cache_fcurve_assign_value(&fkc_pchan.id, index, path_xform, fcache)
201#define FCURVE_ASSIGN_ARRAY(id, path_test_suffix) \
202 BLI_strncpy(path_xform_suffix, path_test_suffix, path_xform_suffix_maxncpy); \
203 action_flip_pchan_cache_fcurve_assign_array( \
204 fkc_pchan.id, ARRAY_SIZE(fkc_pchan.id), path_xform, fcache)
214#undef FCURVE_ASSIGN_VALUE
215#undef FCURVE_ASSIGN_ARRAY
218#define FCURVE_CHANNEL_LEN (sizeof(fkc_pchan) / sizeof(FCurve_KeyCache))
220 int fcurve_array_len = 0;
224 if (fkc->
fcurve !=
nullptr) {
225 fcurve_array[fcurve_array_len++] = fkc->
fcurve;
230 if (fcurve_array_len == 0) {
235 int keyed_frames_len;
237 fcurve_array, fcurve_array_len, &keyed_frames_len);
242 if (fkc->
fcurve ==
nullptr) {
249 float flip_mtx[4][4];
256 if (!
STREQ(pchan_name_flip, pchan->
name)) {
260 float arm_mat_inv[4][4];
265 for (
int frame_index = 0; frame_index < keyed_frames_len; frame_index++) {
269 bPoseChannel pchan_temp = blender::dna::shallow_copy(*pchan);
272#define READ_VALUE_FLT(id) \
273 if (fkc_pchan.id.fcurve_eval != nullptr) { \
274 pchan_temp.id = fkc_pchan.id.fcurve_eval[frame_index]; \
278#define READ_VALUE_INT(id) \
279 if (fkc_pchan.id.fcurve_eval != nullptr) { \
280 pchan_temp.id = floorf(fkc_pchan.id.fcurve_eval[frame_index] + 0.5f); \
284#define READ_ARRAY_FLT(id) \
285 for (int i = 0; i < ARRAY_SIZE(pchan_temp.id); i++) { \
286 READ_VALUE_FLT(id[i]); \
302 float chan_mat[4][4];
320 const float unit_x[3] = {1.0f, 0.0f, 0.0f};
321 const bool is_x_axis_orthogonal = (pchan_flip ==
nullptr) &&
323 if (is_x_axis_orthogonal) {
325 float extra_mat[4][4] = {
326 {-1.0f, 0.0f, 0.0f, 0.0f},
327 {0.0f, 1.0f, 0.0f, 0.0f},
328 {0.0f, 0.0f, -1.0f, 0.0f},
329 {0.0f, 0.0f, 0.0f, 1.0f},
337#define WRITE_VALUE_FLT(id) \
338 if (fkc_pchan.id.fcurve_eval != nullptr) { \
339 BezTriple *bezt = fkc_pchan.id.bezt_array[frame_index]; \
340 if (bezt != nullptr) { \
341 const float delta = pchan_temp.id - bezt->vec[1][1]; \
342 bezt->vec[0][1] += delta; \
343 bezt->vec[1][1] += delta; \
344 bezt->vec[2][1] += delta; \
349#define WRITE_ARRAY_FLT(id) \
350 for (int i = 0; i < ARRAY_SIZE(pchan_temp.id); i++) { \
351 WRITE_VALUE_FLT(id[i]); \
364#undef WRITE_ARRAY_FLT
365#undef WRITE_VALUE_FLT
369 for (
int i = 0; i < fcurve_array_len; i++) {
391 const char *path_pose_prefix =
"pose.bones[\"";
392 const int path_pose_prefix_len = strlen(path_pose_prefix);
396 agrp->flag &= ~AGRP_TEMP;
400 if (!
STRPREFIX(fcu->rna_path, path_pose_prefix)) {
404 const char *name_esc = fcu->rna_path + path_pose_prefix_len;
408 if (
UNLIKELY(name_esc_end ==
nullptr)) {
413 const size_t name_esc_len = size_t(name_esc_end - name_esc);
418 if (
UNLIKELY(name_len >=
sizeof(name))) {
425 if (!
STREQ(name_flip, name)) {
428 char *path_flip =
BLI_sprintfN(
"pose.bones[\"%s%s", name_flip_esc, name_esc_end);
430 fcu->rna_path = path_flip;
432 if (fcu->grp !=
nullptr) {
443 agrp->flag &= ~AGRP_TEMP;
446 if (!
STREQ(name_flip, agrp->name)) {
447 STRNCPY(agrp->name, name_flip);
Functions for backward compatibility with the legacy Action API.
Blender kernel action and pose functionality.
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
void BKE_pchan_apply_mat4(bPoseChannel *pchan, const float mat[4][4], bool use_compat)
void BKE_pchan_to_mat4(const bPoseChannel *pchan, float r_chanmat[4][4])
float * BKE_fcurves_calc_keyed_frames(FCurve **fcurve_array, int fcurve_array_len, int *r_frames_len)
void BKE_fcurve_pathcache_destroy(FCurvePathCache *fcache)
void BKE_fcurve_handles_recalc_ex(FCurve *fcu, eBezTriple_Flag handle_sel_flag)
float evaluate_fcurve_only_curve(const FCurve *fcu, float evaltime)
int BKE_fcurve_pathcache_find_array(FCurvePathCache *fcache, const char *rna_path, FCurve **fcurve_result, int fcurve_result_len)
FCurve * BKE_fcurve_pathcache_find(FCurvePathCache *fcache, const char rna_path[], int array_index)
FCurvePathCache * BKE_fcurve_pathcache_create(ListBase *list)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void unit_m4(float m[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
size_t size_t size_t const char * BLI_str_escape_find_quote(const char *str) ATTR_NONNULL(1)
#define STRNCPY(dst, src)
size_t size_t size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, size_t src_maxncpy) ATTR_NONNULL(1
#define SNPRINTF(dst, format,...)
size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
size_t BLI_string_flip_side_name(char *name_dst, const char *name_src, bool strip_number, size_t name_dst_maxncpy) ATTR_NONNULL(1
void DEG_id_tag_update(ID *id, unsigned int flags)
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define READ_VALUE_FLT(id)
static void action_flip_pchan_rna_paths(bAction *act)
static void action_flip_pchan_cache_fcurve_assign_value(FCurve_KeyCache *fkc, int index, const char *path, FCurvePathCache *fcache)
#define WRITE_ARRAY_FLT(id)
static void action_flip_pchan_cache_init(FCurve_KeyCache *fkc, const float *keyed_frames, int keyed_frames_len)
static void action_flip_pchan_cache_fcurve_assign_array(FCurve_KeyCache *fkc, int fkc_len, const char *path, FCurvePathCache *fcache)
#define READ_VALUE_INT(id)
#define FCURVE_ASSIGN_ARRAY(id, path_test_suffix)
#define FCURVE_CHANNEL_LEN
static void action_flip_pchan(Object *ob_arm, const bPoseChannel *pchan, FCurvePathCache *fcache)
#define WRITE_VALUE_FLT(id)
#define READ_ARRAY_FLT(id)
void BKE_action_flip_with_pose(bAction *act, Object *ob_arm)
#define FCURVE_ASSIGN_VALUE(id, path_test_suffix, index)
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
Vector< const FCurve * > fcurves_all(const bAction *action)
Vector< bActionGroup * > channel_groups_all(bAction *action)