diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 70097cf4137..e9cc54e5ced 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -37,7 +37,7 @@ extern "C" { * * See https://wiki.blender.org/wiki/Process/Compatibility_Handling for details. */ #define BLENDER_FILE_MIN_VERSION 306 -#define BLENDER_FILE_MIN_SUBVERSION 12 +#define BLENDER_FILE_MIN_SUBVERSION 13 /** User readable version string. */ const char *BKE_blender_version_string(void); diff --git a/source/blender/blenkernel/BKE_nla.h b/source/blender/blenkernel/BKE_nla.h index fd3b83e91ed..8d796f29edb 100644 --- a/source/blender/blenkernel/BKE_nla.h +++ b/source/blender/blenkernel/BKE_nla.h @@ -272,6 +272,12 @@ void BKE_nlatrack_solo_toggle(struct AnimData *adt, struct NlaTrack *nlt); * Check if there is any space in the given track to add a strip of the given length. */ bool BKE_nlatrack_has_space(struct NlaTrack *nlt, float start, float end); + +/** + * Check to see if there are any NLA strips in the NLA tracks. + */ +bool BKE_nlatrack_has_strips(ListBase *tracks); + /** * Rearrange the strips in the track so that they are always in order * (usually only needed after a strip has been moved). diff --git a/source/blender/blenkernel/intern/anim_sys.cc b/source/blender/blenkernel/intern/anim_sys.cc index 270ca1f7df1..700476646c8 100644 --- a/source/blender/blenkernel/intern/anim_sys.cc +++ b/source/blender/blenkernel/intern/anim_sys.cc @@ -963,8 +963,23 @@ NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list, /* loop over strips, checking if they fall within the range */ LISTBASE_FOREACH (NlaStrip *, strip, strips) { /* Check if current time occurs within this strip. */ - if (IN_RANGE_INCL(ctime, strip->start, strip->end) || - (strip->flag & NLASTRIP_FLAG_NO_TIME_MAP)) { + + /* This block leads to the Action Track and non-time-remapped tweak strip evaluation to respect + * the extrapolation modes. If in_range, these two tracks will always output NES_TIME_WITHIN so + * fcurve extrapolation isn't clamped to the keyframe bounds. */ + bool in_range = IN_RANGE_INCL(ctime, strip->start, strip->end); + if (strip->flag & NLASTRIP_FLAG_NO_TIME_MAP) { + switch (strip->extendmode) { + case NLASTRIP_EXTEND_HOLD: + in_range = true; + break; + case NLASTRIP_EXTEND_HOLD_FORWARD: + in_range = ctime >= strip->start; + break; + } + } + + if (in_range) { /* this strip is active, so try to use it */ estrip = strip; side = NES_TIME_WITHIN; @@ -3217,16 +3232,10 @@ static void animsys_create_action_track_strip(const AnimData *adt, r_action_strip->extendmode = adt->act_extendmode; r_action_strip->influence = adt->act_influence; - /* NOTE: must set this, or else the default setting overrides, - * and this setting doesn't work. */ - r_action_strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE; - - /* Unless `extendmode` is Nothing (might be useful for flattening NLA evaluation), disable range. - * Extend-mode Nothing and Hold will behave as normal. Hold Forward will behave just like Hold. + /* Must set NLASTRIP_FLAG_USR_INFLUENCE, or else the default setting overrides, and influence + * doesn't work. */ - if (r_action_strip->extendmode != NLASTRIP_EXTEND_NOTHING) { - r_action_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP; - } + r_action_strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE; const bool tweaking = (adt->flag & ADT_NLA_EDIT_ON) != 0; const bool soloing = (adt->flag & ADT_NLA_SOLO_TRACK) != 0; diff --git a/source/blender/blenkernel/intern/nla.cc b/source/blender/blenkernel/intern/nla.cc index 1f473b8d3c6..a9656f07431 100644 --- a/source/blender/blenkernel/intern/nla.cc +++ b/source/blender/blenkernel/intern/nla.cc @@ -1221,6 +1221,24 @@ bool BKE_nlatrack_has_space(NlaTrack *nlt, float start, float end) return BKE_nlastrips_has_space(&nlt->strips, start, end); } +bool BKE_nlatrack_has_strips(ListBase *tracks) +{ + /* sanity checks */ + if (BLI_listbase_is_empty(tracks)) { + return false; + } + + /* Check each track for NLA strips. */ + LISTBASE_FOREACH (NlaTrack *, track, tracks) { + if (BLI_listbase_count(&track->strips) > 0) { + return true; + } + } + + /* none found */ + return false; +} + void BKE_nlatrack_sort_strips(NlaTrack *nlt) { /* sanity checks */ diff --git a/source/blender/blenloader/intern/versioning_300.cc b/source/blender/blenloader/intern/versioning_300.cc index 5b723cf6d96..39a5d8a657e 100644 --- a/source/blender/blenloader/intern/versioning_300.cc +++ b/source/blender/blenloader/intern/versioning_300.cc @@ -69,6 +69,7 @@ #include "BKE_main_namemap.h" #include "BKE_mesh.hh" #include "BKE_modifier.h" +#include "BKE_nla.h" #include "BKE_node.hh" #include "BKE_screen.h" #include "BKE_workspace.h" @@ -1052,6 +1053,28 @@ static void version_geometry_nodes_extrude_smooth_propagation(bNodeTree &ntree) } } +/* Change the action strip (if a NLA strip is preset) to HOLD instead of HOLD FORWARD to maintain + * backwards compatibility.*/ +static void version_nla_action_strip_hold(Main *bmain) +{ + ID *id; + FOREACH_MAIN_ID_BEGIN (bmain, id) { + AnimData *adt = BKE_animdata_from_id(id); + /* We only want to preserve existing behavior if there's an action and 1 or more NLA strips. */ + if (adt == nullptr || adt->action == nullptr || + adt->act_extendmode != NLASTRIP_EXTEND_HOLD_FORWARD) + { + continue; + } + + if (BKE_nlatrack_has_strips(&adt->nla_tracks)) { + adt->act_extendmode = NLASTRIP_EXTEND_HOLD; + } + + FOREACH_MAIN_ID_END; + } +} + void do_versions_after_linking_300(FileData * /*fd*/, Main *bmain) { if (MAIN_VERSION_FILE_ATLEAST(bmain, 300, 0) && !MAIN_VERSION_FILE_ATLEAST(bmain, 300, 1)) { @@ -1148,7 +1171,8 @@ void do_versions_after_linking_300(FileData * /*fd*/, Main *bmain) SOCK_OBJECT, SOCK_COLLECTION, SOCK_TEXTURE, - SOCK_MATERIAL)) { + SOCK_MATERIAL)) + { link->tosock = link->tosock->next; } } @@ -1341,6 +1365,10 @@ void do_versions_after_linking_300(FileData * /*fd*/, Main *bmain) } } + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 306, 13)) { + version_nla_action_strip_hold(bmain); + } + /** * Versioning code until next subversion bump goes here. * @@ -2691,7 +2719,8 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) if (!MAIN_VERSION_FILE_ATLEAST(bmain, 300, 17)) { if (!DNA_struct_elem_find( - fd->filesdna, "View3DOverlay", "float", "normals_constant_screen_size")) { + fd->filesdna, "View3DOverlay", "float", "normals_constant_screen_size")) + { LISTBASE_FOREACH (bScreen *, screen, &bmain->screens) { LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { @@ -2757,7 +2786,8 @@ void blo_do_versions_300(FileData *fd, Library * /*lib*/, Main *bmain) if (!MAIN_VERSION_FILE_ATLEAST(bmain, 300, 18)) { if (!DNA_struct_elem_find( - fd->filesdna, "WorkSpace", "AssetLibraryReference", "asset_library_ref")) { + fd->filesdna, "WorkSpace", "AssetLibraryReference", "asset_library_ref")) + { LISTBASE_FOREACH (WorkSpace *, workspace, &bmain->workspaces) { BKE_asset_library_reference_init_default(&workspace->asset_library_ref); }