diff options
Diffstat (limited to 'source/blender/editors/transform/transform_convert_object.c')
-rw-r--r-- | source/blender/editors/transform/transform_convert_object.c | 225 |
1 files changed, 224 insertions, 1 deletions
diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index 1e33b9653f9..92ed477eb25 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -30,10 +30,12 @@ #include "BLI_listbase.h" #include "BLI_math.h" +#include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_object.h" +#include "BKE_pointcache.h" #include "BKE_report.h" #include "BKE_rigidbody.h" #include "BKE_scene.h" @@ -466,7 +468,7 @@ static int count_proportional_objects(TransInfo *t) return total; } -void clear_trans_object_base_flags(TransInfo *t) +static void clear_trans_object_base_flags(TransInfo *t) { ViewLayer *view_layer = t->view_layer; Base *base; @@ -768,6 +770,149 @@ void createTransTexspace(TransInfo *t) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Transform (Auto-Keyframing) + * \{ */ + +/** + * Auto-keyframing feature - for objects + * + * \param tmode: A transform mode. + * + * \note Context may not always be available, + * so must check before using it as it's a luxury for a few cases. + */ +static void autokeyframe_object( + bContext *C, Scene *scene, ViewLayer *view_layer, Object *ob, int tmode) +{ + Main *bmain = CTX_data_main(C); + ID *id = &ob->id; + FCurve *fcu; + + // TODO: this should probably be done per channel instead... + if (autokeyframe_cfra_can_key(scene, id)) { + ReportList *reports = CTX_wm_reports(C); + ToolSettings *ts = scene->toolsettings; + KeyingSet *active_ks = ANIM_scene_get_active_keyingset(scene); + ListBase dsources = {NULL, NULL}; + float cfra = (float)CFRA; // xxx this will do for now + eInsertKeyFlags flag = 0; + + /* Get flags used for inserting keyframes. */ + flag = ANIM_get_keyframing_flags(scene, true); + + /* add datasource override for the object */ + ANIM_relative_keyingset_add_source(&dsources, id, NULL, NULL); + + if (IS_AUTOKEY_FLAG(scene, ONLYKEYINGSET) && (active_ks)) { + /* Only insert into active keyingset + * NOTE: we assume here that the active Keying Set + * does not need to have its iterator overridden. + */ + ANIM_apply_keyingset(C, &dsources, NULL, active_ks, MODIFYKEY_MODE_INSERT, cfra); + } + else if (IS_AUTOKEY_FLAG(scene, INSERTAVAIL)) { + AnimData *adt = ob->adt; + + /* only key on available channels */ + if (adt && adt->action) { + ListBase nla_cache = {NULL, NULL}; + for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) { + insert_keyframe(bmain, + reports, + id, + adt->action, + (fcu->grp ? fcu->grp->name : NULL), + fcu->rna_path, + fcu->array_index, + cfra, + ts->keyframe_type, + &nla_cache, + flag); + } + + BKE_animsys_free_nla_keyframing_context_cache(&nla_cache); + } + } + else if (IS_AUTOKEY_FLAG(scene, INSERTNEEDED)) { + bool do_loc = false, do_rot = false, do_scale = false; + + /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */ + if (tmode == TFM_TRANSLATION) { + do_loc = true; + } + else if (ELEM(tmode, TFM_ROTATION, TFM_TRACKBALL)) { + if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) { + if (ob != OBACT(view_layer)) { + do_loc = true; + } + } + else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) { + do_loc = true; + } + + if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) { + do_rot = true; + } + } + else if (tmode == TFM_RESIZE) { + if (scene->toolsettings->transform_pivot_point == V3D_AROUND_ACTIVE) { + if (ob != OBACT(view_layer)) { + do_loc = true; + } + } + else if (scene->toolsettings->transform_pivot_point == V3D_AROUND_CURSOR) { + do_loc = true; + } + + if ((scene->toolsettings->transform_flag & SCE_XFORM_AXIS_ALIGN) == 0) { + do_scale = true; + } + } + + /* insert keyframes for the affected sets of channels using the builtin KeyingSets found */ + if (do_loc) { + KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOCATION_ID); + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + } + if (do_rot) { + KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_ROTATION_ID); + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + } + if (do_scale) { + KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_SCALING_ID); + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + } + } + /* insert keyframe in all (transform) channels */ + else { + KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, ANIM_KS_LOC_ROT_SCALE_ID); + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra); + } + + /* free temp info */ + BLI_freelistN(&dsources); + } +} + +/* Return if we need to update motion paths, only if they already exist, + * and we will insert a keyframe at the end of transform. */ +static bool motionpath_need_update_object(Scene *scene, Object *ob) +{ + /* XXX: there's potential here for problems with unkeyed rotations/scale, + * but for now (until proper data-locality for baking operations), + * this should be a better fix for T24451 and T37755 + */ + + if (autokeyframe_cfra_can_key(scene, &ob->id)) { + return (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS) != 0; + } + + return false; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Recalc Data object * * \{ */ @@ -829,3 +974,81 @@ void recalcData_objects(TransInfo *t) } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Special After Transform Object + * \{ */ + +void special_aftertrans_update__object(bContext *C, TransInfo *t) +{ + BLI_assert(t->flag & (T_OBJECT | T_TEXTURE)); + + Object *ob; + const bool canceled = (t->state == TRANS_CANCEL); + + TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); + bool motionpath_update = false; + + for (int i = 0; i < tc->data_len; i++) { + TransData *td = tc->data + i; + ListBase pidlist; + PTCacheID *pid; + ob = td->ob; + + if (td->flag & TD_SKIP) { + continue; + } + + /* flag object caches as outdated */ + BKE_ptcache_ids_from_object(&pidlist, ob, t->scene, MAX_DUPLI_RECUR); + for (pid = pidlist.first; pid; pid = pid->next) { + if (pid->type != PTCACHE_TYPE_PARTICLES) { + /* particles don't need reset on geometry change */ + pid->cache->flag |= PTCACHE_OUTDATED; + } + } + BLI_freelistN(&pidlist); + + /* pointcache refresh */ + if (BKE_ptcache_object_reset(t->scene, ob, PTCACHE_RESET_OUTDATED)) { + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + } + + /* Needed for proper updating of "quick cached" dynamics. */ + /* Creates troubles for moving animated objects without */ + /* autokey though, probably needed is an anim sys override? */ + /* Please remove if some other solution is found. -jahka */ + DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM); + + /* Set autokey if necessary */ + if (!canceled) { + autokeyframe_object(C, t->scene, t->view_layer, ob, t->mode); + } + + motionpath_update |= motionpath_need_update_object(t->scene, ob); + + /* restore rigid body transform */ + if (ob->rigidbody_object && canceled) { + float ctime = BKE_scene_frame_get(t->scene); + if (BKE_rigidbody_check_sim_running(t->scene->rigidbody_world, ctime)) { + BKE_rigidbody_aftertrans_update(ob, + td->ext->oloc, + td->ext->orot, + td->ext->oquat, + td->ext->orotAxis, + td->ext->orotAngle); + } + } + } + + if (motionpath_update) { + /* Update motion paths once for all transformed objects. */ + const eObjectPathCalcRange range = canceled ? OBJECT_PATH_CALC_RANGE_CURRENT_FRAME : + OBJECT_PATH_CALC_RANGE_CHANGED; + ED_objects_recalculate_paths(C, t->scene, range); + } + + clear_trans_object_base_flags(t); +} + +/** \} */ |