diff options
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_anim.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_object.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/anim.c | 186 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 7 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 4 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 19 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.h | 7 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 191 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_action_types.h | 3 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 4 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene.c | 6 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 1 |
12 files changed, 404 insertions, 28 deletions
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index bfba221e488..90af9a15a97 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -32,6 +32,7 @@ * \author nzc * \since March 2001 */ +struct bContext; struct EvaluationContext; struct Path; struct Object; @@ -63,6 +64,7 @@ struct bMotionPath *animviz_verify_motionpaths(struct ReportList *reports, struc void animviz_get_object_motionpaths(struct Object *ob, ListBase *targets); void animviz_calc_motionpaths(struct Scene *scene, ListBase *targets); +void animviz_queue_object(const struct bContext *C, struct Object *ob); /* ---------------------------------------------------- */ /* Curve Paths */ diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 8d1fe7640ee..d134701fc80 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -210,7 +210,7 @@ void BKE_object_handle_update(struct EvaluationContext *eval_ctx, struct Scene * void BKE_object_handle_update_ex(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct RigidBodyWorld *rbw, - const bool do_proxy_update); + const bool do_proxy_update, float ctime); void BKE_object_sculpt_modifiers_changed(struct Object *ob); int BKE_object_obdata_texspace_get(struct Object *ob, short **r_texflag, float **r_loc, float **r_size, float **r_rot); diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index b878dbe1f39..cdf05f89b8d 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -35,6 +35,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" +#include "BLI_threads.h" #include "BLF_translation.h" @@ -42,18 +43,24 @@ #include "DNA_armature_types.h" #include "DNA_key_types.h" #include "DNA_scene_types.h" +#include "DNA_screen_types.h" #include "BKE_curve.h" +#include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_key.h" #include "BKE_main.h" +#include "BKE_library.h" #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_scene.h" #include "BKE_anim.h" #include "BKE_report.h" +#include "WM_types.h" +#include "WM_api.h" + // XXX bad level call... /* --------------------- */ @@ -84,6 +91,12 @@ void animviz_settings_init(bAnimVizSettings *avs) avs->path_sf = 1; /* xxx - take from scene instead? */ avs->path_ef = 250; /* xxx - take from scene instead? */ + avs->inv_start = avs->path_sf; + avs->inv_end = avs->path_ef; + + /* max value shows invalid data */ + avs->calc_end = avs->calc_start = INT32_MAX; + avs->path_viewflag = (MOTIONPATH_VIEW_KFRAS | MOTIONPATH_VIEW_KFNOS); avs->path_step = 1; @@ -182,6 +195,11 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports, Scene *scene, Objec else { /* clear the existing path (as the range has changed), and reallocate below */ animviz_free_motionpath_cache(mpath); + avs->inv_start = avs->path_sf; + avs->inv_end = avs->path_ef; + + /* max value shows invalid data */ + avs->calc_end = avs->calc_start = INT32_MAX; } } } @@ -221,6 +239,7 @@ typedef struct MPathTarget { bMotionPath *mpath; /* motion path in question */ Object *ob; /* source object */ + Base *base_copy; /* copy object, to be used for position calculations */ bPoseChannel *pchan; /* source posechannel (if applicable) */ } MPathTarget; @@ -288,11 +307,19 @@ static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets) baseNext = base->next; if ((base->object == mpt->ob) && !(mpt->ob->flag & BA_TEMP_TAG)) { +// Object *ob = BKE_object_copy(mpt->ob); +// Base *basen = MEM_mallocN(sizeof(Base), "duplibase"); +// *basen = *base; +// basen->object = ob; +// mpt->base_copy = basen; +// ob->flag |= BA_TEMP_TAG; + BLI_remlink(&scene->base, base); BLI_addhead(&scene->base, base); - + //BLI_addhead(&scene->base, basen); + mpt->ob->flag |= BA_TEMP_TAG; - + /* we really don't need to continue anymore once this happens, but this line might really 'break' */ break; } @@ -304,7 +331,7 @@ static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets) } /* update scene for current frame */ -static void motionpaths_calc_update_scene(Scene *scene) +static void motionpaths_calc_update_scene(Scene *scene, float cframe) { #if 1 // 'production' optimizations always on /* rigid body simulation needs complete update to work correctly for now */ @@ -325,6 +352,9 @@ static void motionpaths_calc_update_scene(Scene *scene) for (base = scene->base.first; base; base = base->next) { if (base->object->flag & BA_TEMP_TAG) last = base; + else + /* no need to stay here, we got the last already */ + break; } /* perform updates for tagged objects */ @@ -332,7 +362,8 @@ static void motionpaths_calc_update_scene(Scene *scene) * is animated but not attached to/updatable from objects */ for (base = scene->base.first; base; base = base->next) { /* update this object */ - BKE_object_handle_update(G.main->eval_ctx, scene, base->object); + BKE_object_handle_update_ex(G.main->eval_ctx, scene, base->object, NULL, true, cframe); + /* if this is the last one we need to update, let's stop to save some time */ if (base == last) @@ -352,7 +383,7 @@ static void motionpaths_calc_update_scene(Scene *scene) /* ........ */ /* perform baking for the targets on the current frame */ -static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets) +static void motionpaths_calc_bake_targets(ListBase *targets, int cframe) { MPathTarget *mpt; @@ -364,11 +395,11 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets) /* current frame must be within the range the cache works for * - is inclusive of the first frame, but not the last otherwise we get buffer overruns */ - if ((CFRA < mpath->start_frame) || (CFRA >= mpath->end_frame)) + if ((cframe < mpath->start_frame) || (cframe >= mpath->end_frame)) continue; /* get the relevant cache vert to write to */ - mpv = mpath->points + (CFRA - mpath->start_frame); + mpv = mpath->points + (cframe - mpath->start_frame); /* pose-channel or object path baking? */ if (mpt->pchan) { @@ -386,6 +417,7 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets) else { /* worldspace object location */ copy_v3_v3(mpv->co, mpt->ob->obmat[3]); + //copy_v3_v3(mpv->co, mpt->base_copy->object->obmat[3]); } } } @@ -425,17 +457,16 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets) motionpaths_calc_optimise_depsgraph(scene, targets); /* calculate path over requested range */ - for (CFRA = sfra; CFRA <= efra; CFRA++) { + for (cfra = sfra; cfra <= efra; cfra++) { /* update relevant data for new frame */ - motionpaths_calc_update_scene(scene); + motionpaths_calc_update_scene(scene, cfra); /* perform baking for targets */ - motionpaths_calc_bake_targets(scene, targets); + motionpaths_calc_bake_targets(targets, cfra); } /* reset original environment */ - CFRA = cfra; - motionpaths_calc_update_scene(scene); + motionpaths_calc_update_scene(scene, CFRA); /* clear recalc flags from targets */ for (mpt = targets->first; mpt; mpt = mpt->next) { @@ -449,9 +480,140 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets) /* clear the flag requesting recalculation of targets */ avs->recalc &= ~ANIMVIZ_RECALC_PATHS; + + /* + if (mpt->base_copy) { + DAG_id_type_tag(G.main, ID_OB); + DAG_relations_tag_update(G.main); + BKE_scene_base_unlink(scene, mpt->base_copy); + BKE_libblock_free_us(G.main, mpt->base_copy->object); + if (scene->basact == mpt->base_copy) scene->basact = NULL; + MEM_freeN(mpt->base_copy); + } + */ } } +typedef struct MotionPathJob { + ListBase motionpaths; + ThreadMutex *mutex; + Scene *scene; + int total; /* total keyframes needed for processing */ + int processed; /* number of processed keyframes */ +} MotionPathJob; + +typedef struct MotionPathJobElement { + struct MotionPathJobElement *next, *prev; +} MotionPathJobElement; + +static void free_motionpath_job(void *data) +{ + MotionPathJob *mpj = (MotionPathJob *)data; + + BLI_mutex_free(mpj->mutex); + BLI_freelistN(&mpj->motionpaths); + MEM_freeN(mpj); +} + +/* only this runs inside thread */ +static void motionpath_startjob(void *data, short *stop, short *do_update, float *progress) +{ + MotionPathJob *mpj = data; + MotionPathJobElement *mpe; + + BLI_mutex_lock(mpj->mutex); + mpe = mpj->motionpaths.first; + BLI_mutex_unlock(mpj->mutex); + + while (mpe) { + MotionPathJobElement *mpe_next; + + if (*stop || G.is_break) { + BLI_mutex_lock(mpj->mutex); + mpe = mpe->next; + BLI_mutex_unlock(mpj->mutex); + while (mpe) { + /* + sound = previewjb->sound; + + BLI_spin_lock(sound->spinlock); + sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING; + BLI_spin_unlock(sound->spinlock); + + BLI_mutex_lock(pj->mutex); + previewjb = previewjb->next; + BLI_mutex_unlock(pj->mutex); + */ + } + + BLI_mutex_lock(mpj->mutex); + BLI_freelistN(&mpj->motionpaths); + mpj->total = 0; + mpj->processed = 0; + BLI_mutex_unlock(mpj->mutex); + break; + } + + BLI_mutex_lock(mpj->mutex); + mpe_next = mpe->next; + BLI_freelinkN(&mpj->motionpaths, mpe); + mpe = mpe_next; + mpj->processed++; + *progress = (mpj->total > 0) ? (float)mpj->processed / (float)mpj->total : 1.0f; + *do_update = true; + BLI_mutex_unlock(mpj->mutex); + } +} + +static void motionpath_endjob(void *data) +{ + MotionPathJob *mpj = data; + + WM_main_add_notifier(NC_SCENE | ND_ANIMPLAY, mpj->scene); +} + + +/* add an object ot the thread calculating motionpaths */ +void animviz_queue_object(const bContext *C, struct Object *ob) +{ + /* first, get the preview job, if it exists */ + wmJob *wm_job; + MotionPathJob *mpj; + ScrArea *sa = CTX_wm_area(C); + MotionPathJobElement *mpe = MEM_callocN(sizeof(MotionPathJobElement), "motionpath_element"); + wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Motion Paths", + WM_JOB_PROGRESS, WM_JOB_TYPE_MOTIONPATHS); + + mpj = WM_jobs_customdata_get(wm_job); + + if (!mpj) { + mpj = MEM_callocN(sizeof(MotionPathJob), "motion path job"); + + mpj->mutex = BLI_mutex_alloc(); + mpj->scene = CTX_data_scene(C); + + WM_jobs_customdata_set(wm_job, mpj, free_motionpath_job); + WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER); + WM_jobs_callbacks(wm_job, motionpath_startjob, NULL, NULL, motionpath_endjob); + } + + /* attempt to lock mutex of job here */ + + //mpe-> = ; + + BLI_mutex_lock(mpj->mutex); + BLI_addtail(&mpj->motionpaths, mpe); + mpj->total++; + BLI_mutex_unlock(mpj->mutex); + + if (!WM_jobs_is_running(wm_job)) { + G.is_break = false; + WM_jobs_start(CTX_wm_manager(C), wm_job); + } +} + + + /* ******************************************************************** */ /* Curve Paths - for curve deforms and/or curve following */ diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 365a5d838eb..04bdfe3b58e 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -3071,7 +3071,8 @@ bool BKE_object_parent_loop_check(const Object *par, const Object *ob) void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, Scene *scene, Object *ob, RigidBodyWorld *rbw, - const bool do_proxy_update) + const bool do_proxy_update, + float ctime) { if (ob->recalc & OB_RECALC_ALL) { /* speed optimization for animation lookups */ @@ -3117,7 +3118,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, copy_m4_m4(ob->obmat, ob->proxy_from->obmat); } else - BKE_object_where_is_calc_ex(scene, rbw, ob, NULL); + BKE_object_where_is_calc_time_ex(scene, ob, ctime, rbw, NULL); } if (ob->recalc & OB_RECALC_DATA) { @@ -3149,7 +3150,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, */ void BKE_object_handle_update(EvaluationContext *eval_ctx, Scene *scene, Object *ob) { - BKE_object_handle_update_ex(eval_ctx, scene, ob, NULL, true); + BKE_object_handle_update_ex(eval_ctx, scene, ob, NULL, true, BKE_scene_frame_get(scene)); } void BKE_object_sculpt_modifiers_changed(Object *ob) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index bd923d296f1..b6fede75d96 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1378,7 +1378,7 @@ static void scene_update_all_bases(EvaluationContext *eval_ctx, Scene *scene, Sc for (base = scene->base.first; base; base = base->next) { Object *object = base->object; - BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world, true); + BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world, true, BKE_scene_frame_get(scene_parent)); if (object->dup_group && (object->transflag & OB_DUPLIGROUP)) BKE_group_handle_recalc_and_update(eval_ctx, scene_parent, object, object->dup_group); @@ -1429,7 +1429,7 @@ static void scene_update_object_func(TaskPool *pool, void *taskdata, int threadi * separately from main thread because of we've got no idea about * dependencies inside the group. */ - BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world, false); + BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world, false, BKE_scene_frame_get(scene_parent)); /* Calculate statistics. */ if (add_to_stats) { diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 34314e7ff3d..38fb35bbb1a 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -66,6 +66,7 @@ #include "BIF_gl.h" #include "BIF_glutil.h" +#include "ED_armature.h" #include "ED_image.h" #include "ED_keyframing.h" #include "ED_screen.h" @@ -2391,6 +2392,24 @@ void transformApply(bContext *C, TransInfo *t) viewRedrawForce(C, t); } + if (t->scene->toolsettings->realtime_motion_path) { + if ((t->flag & T_POSE) && (t->poseobj) && (t->mode != TFM_DUMMY)) { + if ((t->poseobj->pose->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) { + //ED_pose_clear_paths(C, ob); // XXX for now, don't need to clear + bool targetless_ik = (t->flag & T_AUTOIK) != 0; // XXX this currently doesn't work, since flags aren't set yet! + + autokeyframe_pose_cb_func(C, t->scene, (View3D *)t->view, t->poseobj, t->mode, targetless_ik); + } + } + else { + int i; + for (i = 0; i < t->total; i++) { + TransData *td = t->data + i; + autokeyframe_ob_cb_func(C, t->scene, (View3D *)t->view, td->ob, t->mode); + } + } + } + /* If auto confirm is on, break after one pass */ if (t->options & CTX_AUTOCONFIRM) { t->state = TRANS_CONFIRM; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 2672df24d2e..33b4e2b5448 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -592,8 +592,13 @@ bool transdata_check_local_islands(TransInfo *t, short around); int count_set_pose_transflags(int *out_mode, short around, struct Object *ob); /* auto-keying stuff used by special_aftertrans_update */ +void autokeyframe_ob_tag_existing(struct Scene *scene, struct Object *ob); +void autokeyframe_ob_revert(struct bContext *C, struct Scene *scene, struct Object *ob); void autokeyframe_ob_cb_func(struct bContext *C, struct Scene *scene, struct View3D *v3d, struct Object *ob, int tmode); -void autokeyframe_pose_cb_func(struct bContext *C, struct Scene *scene, struct View3D *v3d, struct Object *ob, int tmode, short targetless_ik); + +void autokeyframe_pose_tag_existing(struct Scene *scene, struct Object *ob); +void autokeyframe_pose_revert(struct bContext *C, struct Scene *scene, struct Object *ob, bool targetless_ik); +void autokeyframe_pose_cb_func(struct bContext *C, struct Scene *scene, struct View3D *v3d, struct Object *ob, int tmode, bool targetless_ik); /*********************** Constraints *****************************/ diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 307fa86a56b..aa0d86e5b3f 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -1066,6 +1066,9 @@ static void createTransPose(TransInfo *t, Object *ob) /* initialize initial auto=ik chainlen's? */ if (ik_on) transform_autoik_update(t, 0); + + if (t->scene->toolsettings->realtime_motion_path) + autokeyframe_pose_tag_existing(t->scene, ob); } void restoreBones(TransInfo *t) @@ -5505,6 +5508,10 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) unit_m3(td->smtx); unit_m3(td->mtx); } + + if (t->scene->toolsettings->realtime_motion_path) { + autokeyframe_ob_tag_existing(scene, ob); + } } @@ -5685,6 +5692,69 @@ static void clear_trans_object_base_flags(TransInfo *t) /* auto-keyframing feature - for objects * tmode: should be a transform mode */ + +/* auto keyframing: we need to tag the existing fcurves before attempting to insert keyframes + * to avoid deleting them by mistake. Algorithm here is that if keyframe existed before, + * we insert old value on cancel, else we completely delete it */ +void autokeyframe_ob_tag_existing(Scene *scene, Object *ob) { + ID *id = &ob->id; + AnimData *adt = ob->adt; + bAction *act = (adt) ? adt->action : NULL; + FCurve *fcu; + float cfra = (float)CFRA; + + if (act) { + if (autokeyframe_cfra_can_key(scene, id)) { + for (fcu = act->curves.first; fcu; fcu = fcu->next) { + bool replace; + binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &replace); + + fcu->flag &= ~FCURVE_TAGGED; + if (replace) { + fcu->flag |= FCURVE_TAGGED; + } + } + } + } +} + +void autokeyframe_ob_revert(bContext *C, Scene *scene, Object *ob) { + ID *id = &ob->id; + AnimData *adt = ob->adt; + bAction *act = (adt) ? adt->action : NULL; + FCurve *fcu, *fcu_next; + ReportList *reports = CTX_wm_reports(C); + float cfra = (float)CFRA; + short flag = 0; + + /* flag is initialized from UserPref keyframing settings + * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get + * visual keyframes even if flag not set, as it's not that useful otherwise + * (for quick animation recording) + */ + flag = ANIM_get_keyframing_flags(scene, 1); + + if (autokeyframe_cfra_can_key(scene, id)) { + if (act) { + for (fcu = act->curves.first; fcu; fcu = fcu_next) { + fcu_next = fcu->next; + + if (fcu->flag & FCURVE_TAGGED) { + fcu->flag &= ~FCURVE_TAGGED; + insert_keyframe(reports, id, act, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag); + } + else + delete_keyframe(reports, id, act, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag); + } + } + + if (C && (ob->avs.path_bakeflag & MOTIONPATH_BAKE_HAS_PATHS)) { + //ED_objects_clear_paths(C); // XXX for now, don't need to clear + ED_objects_recalculate_paths(C, scene); + } + } +} + // NOTE: context may not always be available, so must check before using it as it's a luxury for a few cases void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, int tmode) { @@ -5717,7 +5787,7 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, /* only key on available channels */ if (adt && adt->action) { for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) { - fcu->flag &= ~FCURVE_SELECTED; + fcu->flag &= ~FCURVE_SELECTED; insert_keyframe(reports, id, adt->action, (fcu->grp ? fcu->grp->name : NULL), fcu->rna_path, fcu->array_index, cfra, flag); @@ -5795,12 +5865,112 @@ void autokeyframe_ob_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, } } +/* auto keyframing: we need to tag the existing fcurves before attempting to insert keyframes + * to avoid deleting them by mistake. Algorithm here is that if keyframe existed before, + * we insert old value on cancel, else we completely delete it */ +void autokeyframe_pose_tag_existing(Scene *scene, Object *ob) { + ID *id = &ob->id; + AnimData *adt = ob->adt; + bAction *act = (adt) ? adt->action : NULL; + bPose *pose = ob->pose; + bPoseChannel *pchan; + FCurve *fcu; + float cfra = (float)CFRA; + + if (act) { + if (autokeyframe_cfra_can_key(scene, id)) { + for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + if (pchan->bone->flag & BONE_TRANSFORM) { + for (fcu = act->curves.first; fcu; fcu = fcu->next) { + /* only insert keyframes for this F-Curve if it affects the current bone */ + if (strstr(fcu->rna_path, "bones")) { + char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones["); + + /* only if bone name matches too... + * NOTE: this will do constraints too, but those are ok to do here too? + */ + if (pchanName && STREQ(pchanName, pchan->name)) { + bool replace; + binarysearch_bezt_index(fcu->bezt, cfra, fcu->totvert, &replace); + + fcu->flag &= ~FCURVE_TAGGED; + if (replace) { + fcu->flag |= FCURVE_TAGGED; + } + } + if (pchanName) MEM_freeN(pchanName); + } + } + } + } + } + } +} + + +void autokeyframe_pose_revert(bContext *C, Scene *scene, Object *ob, bool targetless_ik) { + ID *id = &ob->id; + AnimData *adt = ob->adt; + bAction *act = (adt) ? adt->action : NULL; + bPose *pose = ob->pose; + bPoseChannel *pchan; + FCurve *fcu, *fcu_next; + ReportList *reports = CTX_wm_reports(C); + float cfra = (float)CFRA; + short flag = 0; + + /* flag is initialized from UserPref keyframing settings + * - special exception for targetless IK - INSERTKEY_MATRIX keyframes should get + * visual keyframes even if flag not set, as it's not that useful otherwise + * (for quick animation recording) + */ + flag = ANIM_get_keyframing_flags(scene, 1); + + if (targetless_ik) + flag |= INSERTKEY_MATRIX; + + if (autokeyframe_cfra_can_key(scene, id)) { + for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + if (pchan->bone->flag & BONE_TRANSFORM) { + if (act) { + for (fcu = act->curves.first; fcu; fcu = fcu_next) { + fcu_next = fcu->next; + + /* only insert keyframes for this F-Curve if it affects the current bone */ + if (strstr(fcu->rna_path, "bones")) { + char *pchanName = BLI_str_quoted_substrN(fcu->rna_path, "bones["); + + /* only if bone name matches too... + * NOTE: this will do constraints too, but those are ok to do here too? + */ + if (pchanName && STREQ(pchanName, pchan->name)) { + if (fcu->flag & FCURVE_TAGGED) { + fcu->flag &= ~FCURVE_TAGGED; + insert_keyframe(reports, id, act, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag); + } + else + delete_keyframe(reports, id, act, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag); + } + if (pchanName) MEM_freeN(pchanName); + } + } + } + } + } + + if (C && (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(scene, ob); + } + } +} + /* auto-keyframing feature - for poses/pose-channels * tmode: should be a transform mode * targetless_ik: has targetless ik been done on any channels? */ // NOTE: context may not always be available, so must check before using it as it's a luxury for a few cases -void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, int tmode, short targetless_ik) +void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *ob, int tmode, bool targetless_ik) { ID *id = &ob->id; AnimData *adt = ob->adt; @@ -5852,9 +6022,9 @@ void autokeyframe_pose_cb_func(bContext *C, Scene *scene, View3D *v3d, Object *o /* only if bone name matches too... * NOTE: this will do constraints too, but those are ok to do here too? */ - if (pchanName && STREQ(pchanName, pchan->name)) + if (pchanName && STREQ(pchanName, pchan->name)) { insert_keyframe(reports, id, act, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag); - + } if (pchanName) MEM_freeN(pchanName); } } @@ -6432,8 +6602,12 @@ void special_aftertrans_update(bContext *C, TransInfo *t) pose_grab_with_ik_clear(ob); /* automatic inserting of keys and unkeyed tagging - only if transform wasn't canceled (or TFM_DUMMY) */ - if (!canceled && (t->mode != TFM_DUMMY)) { - autokeyframe_pose_cb_func(C, t->scene, (View3D *)t->view, ob, t->mode, targetless_ik); + if (t->mode != TFM_DUMMY) { + if (t->scene->toolsettings->realtime_motion_path && canceled) + autokeyframe_pose_revert(C, t->scene, ob, targetless_ik); + else { + autokeyframe_pose_cb_func(C, t->scene, (View3D *)t->view, ob, t->mode, targetless_ik); + } DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } else if (arm->flag & ARM_DELAYDEFORM) { @@ -6498,9 +6672,10 @@ void special_aftertrans_update(bContext *C, TransInfo *t) DAG_id_tag_update(&ob->id, OB_RECALC_OB); /* Set autokey if necessary */ - if (!canceled) { + if (t->scene->toolsettings->realtime_motion_path && canceled) + autokeyframe_ob_revert(C, t->scene, ob); + else autokeyframe_ob_cb_func(C, t->scene, (View3D *)t->view, ob, t->mode); - } /* restore rigid body transform */ if (ob->rigidbody_object && canceled) { diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index b8688e5e12a..5e076136f9b 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -113,6 +113,9 @@ typedef struct bAnimVizSettings { int path_sf, path_ef; /* start and end frames of path-calculation range */ int path_bc, path_ac; /* number of frames before/after current frame to show */ + + int calc_start, calc_end; /* frames around which we have calculated motionpaths already */ + int inv_start, inv_end; /* start of invalid frames in the motionpath */ } bAnimVizSettings; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 94b609e9b9f..1872ced9b24 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1262,7 +1262,9 @@ typedef struct ToolSettings { /* Multires */ char multires_subdiv_type; - char pad3[1]; + + /* Motion Paths update in real time */ + char realtime_motion_path; /* Skeleton generation */ short skgen_resolution; diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 4a05a56b37a..810d83a8ddf 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2152,6 +2152,12 @@ static void rna_def_tool_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Relaxation Method", "Algorithm used for UV relaxation"); /* Transform */ + prop = RNA_def_property(srna, "realtime_motion_path", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "realtime_motion_path", 1); + RNA_def_property_ui_text(prop, "Real-Time Motion Path", + "Update motion paths in real time while tranfrorming"); + RNA_def_property_update(prop, NC_SCENE | ND_TOOLSETTINGS, NULL); /* header redraw */ + prop = RNA_def_property(srna, "proportional_edit", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "proportional"); RNA_def_property_enum_items(prop, proportional_editing_items); diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index eea28ca3146..c08a17396aa 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -427,6 +427,7 @@ enum { WM_JOB_TYPE_CLIP_PREFETCH, WM_JOB_TYPE_SEQ_BUILD_PROXY, WM_JOB_TYPE_SEQ_BUILD_PREVIEW, + WM_JOB_TYPE_MOTIONPATHS, /* add as needed, screencast, seq proxy build * if having hard coded values is a problem */ }; |