forked from blender/blender
WIP: just adding in the Phab DIFF to local repo to easily see what's left to refactor #2
@ -179,7 +179,7 @@ void BKE_nlastrips_clear_metastrip(ListBase *strips, struct NlaStrip *strip);
|
||||
* Add the given NLA-Strip to the given Meta-Strip, assuming that the
|
||||
* strip isn't attached to any list of strips
|
||||
*/
|
||||
bool BKE_nlameta_add_strip(struct NlaStrip *mstrip, struct NlaStrip *strip);
|
||||
bool BKE_nlameta_try_add_strip(struct NlaStrip *mstrip, struct NlaStrip *strip);
|
||||
/**
|
||||
* Adjust the settings of NLA-Strips contained within a Meta-Strip (recursively),
|
||||
* until the Meta-Strips children all fit within the Meta-Strip's new dimensions
|
||||
|
437
source/blender/blenkernel/BKE_nla.h.orig
Normal file
437
source/blender/blenkernel/BKE_nla.h.orig
Normal file
@ -0,0 +1,437 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2009 Blender Foundation, Joshua Leung. All rights reserved. */
|
||||
|
||||
#pragma once
|
||||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
*/
|
||||
|
||||
/** Temp constant defined for these functions only. */
|
||||
#define NLASTRIP_MIN_LEN_THRESH 0.1f
|
||||
|
||||
#include "DNA_listBase.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct AnimData;
|
||||
struct LibraryForeachIDData;
|
||||
struct Main;
|
||||
struct NlaStrip;
|
||||
struct NlaTrack;
|
||||
struct Scene;
|
||||
struct Speaker;
|
||||
struct bAction;
|
||||
|
||||
struct BlendDataReader;
|
||||
struct BlendExpander;
|
||||
struct BlendLibReader;
|
||||
struct BlendWriter;
|
||||
struct PointerRNA;
|
||||
struct PropertyRNA;
|
||||
|
||||
/* ----------------------------- */
|
||||
/* Data Management */
|
||||
|
||||
/**
|
||||
* Frees the given NLA strip, and calls #BKE_nlastrip_remove_and_free to
|
||||
* remove and free all children strips.
|
||||
*/
|
||||
void BKE_nlastrip_free(struct NlaStrip *strip, bool do_id_user);
|
||||
/**
|
||||
* Remove the given NLA track from the set of NLA tracks, free the track's data,
|
||||
* and the track itself.
|
||||
*/
|
||||
void BKE_nlatrack_free(ListBase *tracks, struct NlaTrack *nlt, bool do_id_user);
|
||||
/**
|
||||
* Free the elements of type NLA Tracks provided in the given list, but do not free
|
||||
* the list itself since that is not free-standing
|
||||
*/
|
||||
void BKE_nla_tracks_free(ListBase *tracks, bool do_id_user);
|
||||
|
||||
/**
|
||||
* Copy NLA strip
|
||||
*
|
||||
* \param use_same_action: When true, the existing action is used (instead of being duplicated)
|
||||
* \param flag: Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_...
|
||||
* flags in BKE_lib_id.h
|
||||
*/
|
||||
struct NlaStrip *BKE_nlastrip_copy(struct Main *bmain,
|
||||
struct NlaStrip *strip,
|
||||
bool use_same_action,
|
||||
int flag);
|
||||
/**
|
||||
* Copy a single NLA Track.
|
||||
* \param flag: Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_...
|
||||
* flags in BKE_lib_id.h
|
||||
*/
|
||||
struct NlaTrack *BKE_nlatrack_copy(struct Main *bmain,
|
||||
struct NlaTrack *nlt,
|
||||
bool use_same_actions,
|
||||
int flag);
|
||||
/**
|
||||
* Copy all NLA data.
|
||||
* \param flag: Control ID pointers management, see LIB_ID_CREATE_.../LIB_ID_COPY_...
|
||||
* flags in BKE_lib_id.h
|
||||
*/
|
||||
void BKE_nla_tracks_copy(struct Main *bmain, ListBase *dst, const ListBase *src, int flag);
|
||||
|
||||
/**
|
||||
* Copy NLA tracks from #adt_source to #adt_dest, and update the active track/strip pointers to
|
||||
* point at those copies.
|
||||
*/
|
||||
void BKE_nla_tracks_copy_from_adt(struct Main *bmain,
|
||||
struct AnimData *adt_dest,
|
||||
const struct AnimData *adt_source,
|
||||
int flag);
|
||||
|
||||
/**
|
||||
* Add a NLA Track to the given AnimData.
|
||||
* \param prev: NLA-Track to add the new one after.
|
||||
*/
|
||||
struct NlaTrack *BKE_nlatrack_add(struct AnimData *adt,
|
||||
struct NlaTrack *prev,
|
||||
bool is_liboverride);
|
||||
|
||||
/**
|
||||
* Create a NLA Strip referencing the given Action.
|
||||
*/
|
||||
struct NlaStrip *BKE_nlastrip_new(struct bAction *act);
|
||||
|
||||
/*
|
||||
* Removes the given NLA strip from the list of strips provided.
|
||||
*/
|
||||
void BKE_nlastrip_remove(ListBase *strips, struct NlaStrip *strip);
|
||||
|
||||
/*
|
||||
* Removes the given NLA strip from the list of strips provided, and frees it's memory.
|
||||
*/
|
||||
void BKE_nlastrip_remove_and_free(ListBase *strips, struct NlaStrip *strip, const bool do_id_user);
|
||||
|
||||
/**
|
||||
* Add new NLA-strip to the top of the NLA stack - i.e.
|
||||
* into the last track if space, or a new one otherwise.
|
||||
*/
|
||||
struct NlaStrip *BKE_nlastack_add_strip(struct AnimData *adt,
|
||||
struct bAction *act,
|
||||
bool is_liboverride);
|
||||
/**
|
||||
* Add a NLA Strip referencing the given speaker's sound.
|
||||
*/
|
||||
struct NlaStrip *BKE_nla_add_soundstrip(struct Main *bmain,
|
||||
struct Scene *scene,
|
||||
struct Speaker *speaker);
|
||||
|
||||
/**
|
||||
* Callback used by lib_query to walk over all ID usages
|
||||
* (mimics `foreach_id` callback of #IDTypeInfo structure).
|
||||
*/
|
||||
void BKE_nla_strip_foreach_id(struct NlaStrip *strip, struct LibraryForeachIDData *data);
|
||||
|
||||
/* ----------------------------- */
|
||||
/* API */
|
||||
|
||||
/**
|
||||
* Check if there is any space in the given list to add the given strip.
|
||||
*/
|
||||
bool BKE_nlastrips_has_space(ListBase *strips, float start, float end);
|
||||
/**
|
||||
* Rearrange the strips in the track so that they are always in order
|
||||
* (usually only needed after a strip has been moved)
|
||||
*/
|
||||
void BKE_nlastrips_sort_strips(ListBase *strips);
|
||||
|
||||
/**
|
||||
* Add the given NLA-Strip to the given list of strips, assuming that it
|
||||
* isn't currently a member of another list, NULL, or conflicting with existing
|
||||
* strips position.
|
||||
*/
|
||||
void BKE_nlastrips_add_strip_unsafe(ListBase *strips, struct NlaStrip *strip);
|
||||
|
||||
/**
|
||||
* NULL checks incoming strip and verifies no overlap / invalid
|
||||
* configuration against other strips in NLA Track before calling
|
||||
* #BKE_nlastrips_add_strip_unsafe.
|
||||
*/
|
||||
bool BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip);
|
||||
|
||||
/**
|
||||
* Convert 'islands' (i.e. continuous string of) selected strips to be
|
||||
* contained within 'Meta-Strips' which act as strips which contain strips.
|
||||
*
|
||||
* \param is_temp: are the meta-strips to be created 'temporary' ones used for transforms?
|
||||
*/
|
||||
void BKE_nlastrips_make_metas(ListBase *strips, bool is_temp);
|
||||
/**
|
||||
* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips.
|
||||
*
|
||||
* \param only_sel: only consider selected meta-strips, otherwise all meta-strips are removed
|
||||
* \param only_temp: only remove the 'temporary' meta-strips used for transforms
|
||||
*/
|
||||
void BKE_nlastrips_clear_metas(ListBase *strips, bool only_sel, bool only_temp);
|
||||
/**
|
||||
* Split a meta-strip into a set of normal strips.
|
||||
*/
|
||||
void BKE_nlastrips_clear_metastrip(ListBase *strips, struct NlaStrip *strip);
|
||||
/**
|
||||
* Add the given NLA-Strip to the given Meta-Strip, assuming that the
|
||||
* strip isn't attached to any list of strips
|
||||
*/
|
||||
bool BKE_nlameta_add_strip(struct NlaStrip *mstrip, struct NlaStrip *strip);
|
||||
/**
|
||||
* Adjust the settings of NLA-Strips contained within a Meta-Strip (recursively),
|
||||
* until the Meta-Strips children all fit within the Meta-Strip's new dimensions
|
||||
*/
|
||||
void BKE_nlameta_flush_transforms(struct NlaStrip *mstrip);
|
||||
|
||||
/* ............ */
|
||||
|
||||
/**
|
||||
* Find the active NLA-track for the given stack.
|
||||
*/
|
||||
struct NlaTrack *BKE_nlatrack_find_active(ListBase *tracks);
|
||||
/**
|
||||
* Make the given NLA-track the active one for the given stack. If no track is provided,
|
||||
* this function can be used to simply deactivate all the NLA tracks in the given stack too.
|
||||
*/
|
||||
void BKE_nlatrack_set_active(ListBase *tracks, struct NlaTrack *nlt);
|
||||
|
||||
/**
|
||||
* Get the NLA Track that the active action/action strip comes from,
|
||||
* since this info is not stored in AnimData. It also isn't as simple
|
||||
* as just using the active track, since multiple tracks may have been
|
||||
* entered at the same time.
|
||||
*/
|
||||
struct NlaTrack *BKE_nlatrack_find_tweaked(struct AnimData *adt);
|
||||
|
||||
/**
|
||||
* Toggle the 'solo' setting for the given NLA-track, making sure that it is the only one
|
||||
* that has this status in its AnimData block.
|
||||
*/
|
||||
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);
|
||||
/**
|
||||
* Rearrange the strips in the track so that they are always in order
|
||||
* (usually only needed after a strip has been moved).
|
||||
*/
|
||||
void BKE_nlatrack_sort_strips(struct NlaTrack *nlt);
|
||||
|
||||
/**
|
||||
* Add the given NLA-Strip to the given NLA-Track.
|
||||
* Calls #BKE_nlastrips_add_strip to check if strip can be added.
|
||||
*/
|
||||
bool BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip, bool is_liboverride);
|
||||
|
||||
/**
|
||||
* Remove the NLA-Strip from the given NLA-Track.
|
||||
*/
|
||||
void BKE_nlatrack_remove_strip(struct NlaTrack *track, struct NlaStrip *strip);
|
||||
|
||||
/**
|
||||
* Get the extents of the given NLA-Track including gaps between strips,
|
||||
* returning whether this succeeded or not
|
||||
*/
|
||||
bool BKE_nlatrack_get_bounds(struct NlaTrack *nlt, float bounds[2]);
|
||||
/**
|
||||
* Check whether given NLA track is not local (i.e. from linked data) when the object is a library
|
||||
* override.
|
||||
*
|
||||
* \param nlt: May be NULL, in which case we consider it as a non-local track case.
|
||||
*/
|
||||
bool BKE_nlatrack_is_nonlocal_in_liboverride(const struct ID *id, const struct NlaTrack *nlt);
|
||||
|
||||
/* ............ */
|
||||
|
||||
/**
|
||||
* Compute the left-hand-side 'frame limit' of that strip, in its NLA track.
|
||||
*
|
||||
* \details This is either :
|
||||
* - the end frame of the previous strip, if the strip's track contains another strip on it left
|
||||
* - the macro MINFRAMEF, if no strips are to the left of this strip in its track
|
||||
*
|
||||
* \param strip: The strip to compute the left-hand-side 'frame limit' of.
|
||||
* \return The beginning frame of the previous strip, or MINFRAMEF if no strips are next in that
|
||||
* track.
|
||||
*/
|
||||
float BKE_nlastrip_compute_frame_from_previous_strip(struct NlaStrip *strip);
|
||||
/**
|
||||
* Compute the right-hand-side 'frame limit' of that strip, in its NLA track.
|
||||
*
|
||||
* \details This is either :
|
||||
*
|
||||
* - the begin frame of the next strip, if the strip's track contains another strip on it right
|
||||
* - the macro MAXFRAMEF, if no strips are to the right of this strip in its track
|
||||
*
|
||||
* \param strip: The strip to compute the right-hand-side 'frame limit' of.
|
||||
* \return The beginning frame of the next strip, or MAXFRAMEF if no strips are next in that track.
|
||||
*/
|
||||
float BKE_nlastrip_compute_frame_to_next_strip(struct NlaStrip *strip);
|
||||
|
||||
/**
|
||||
* Returns the next strip in this strip's NLA track, or a null pointer.
|
||||
*
|
||||
* \param strip: The strip to find the next trip from.
|
||||
* \param check_transitions: Whether or not to skip transitions.
|
||||
* \return The next strip in the track, or NULL if none are present.
|
||||
*/
|
||||
struct NlaStrip *BKE_nlastrip_next_in_track(struct NlaStrip *strip, bool skip_transitions);
|
||||
|
||||
/**
|
||||
* Returns the previous strip in this strip's NLA track, or a null pointer.
|
||||
*
|
||||
* \param strip: The strip to find the previous trip from.
|
||||
* \param check_transitions: Whether or not to skip transitions.
|
||||
* \return The previous strip in the track, or NULL if none are present.
|
||||
*/
|
||||
struct NlaStrip *BKE_nlastrip_prev_in_track(struct NlaStrip *strip, bool skip_transitions);
|
||||
|
||||
/* ............ */
|
||||
|
||||
/**
|
||||
* Find the active NLA-strip within the given track.
|
||||
*/
|
||||
struct NlaStrip *BKE_nlastrip_find_active(struct NlaTrack *nlt);
|
||||
/**
|
||||
* Make the given NLA-Strip the active one within the given block.
|
||||
*/
|
||||
void BKE_nlastrip_set_active(struct AnimData *adt, struct NlaStrip *strip);
|
||||
|
||||
/**
|
||||
* Does the given NLA-strip fall within the given bounds (times)?.
|
||||
*/
|
||||
bool BKE_nlastrip_within_bounds(struct NlaStrip *strip, float min, float max);
|
||||
/**
|
||||
* Return the distance from the given frame to the NLA strip, measured in frames.
|
||||
* If the given frame intersects the NLA strip, the distance is zero.
|
||||
*/
|
||||
float BKE_nlastrip_distance_to_frame(const struct NlaStrip *strip, float timeline_frame);
|
||||
/**
|
||||
* Recalculate the start and end frames for the current strip, after changing
|
||||
* the extents of the action or the mapping (repeats or scale factor) info.
|
||||
*/
|
||||
void BKE_nlastrip_recalculate_bounds(struct NlaStrip *strip);
|
||||
/**
|
||||
* Recalculate the start and end frames for the strip to match the bounds of its action such that
|
||||
* the overall NLA animation result is unchanged.
|
||||
*/
|
||||
void BKE_nlastrip_recalculate_bounds_sync_action(struct NlaStrip *strip);
|
||||
|
||||
/**
|
||||
* Recalculate the blend-in and blend-out values after a strip transform update.
|
||||
*/
|
||||
void BKE_nlastrip_recalculate_blend(struct NlaStrip *strip);
|
||||
|
||||
/**
|
||||
* Find (and set) a unique name for a strip from the whole AnimData block
|
||||
* Uses a similar method to the BLI method, but is implemented differently
|
||||
* as we need to ensure that the name is unique over several lists of tracks,
|
||||
* not just a single track.
|
||||
*/
|
||||
void BKE_nlastrip_validate_name(struct AnimData *adt, struct NlaStrip *strip);
|
||||
|
||||
/* ............ */
|
||||
|
||||
/**
|
||||
* Check if the given NLA-Track has any strips with own F-Curves.
|
||||
*/
|
||||
bool BKE_nlatrack_has_animated_strips(struct NlaTrack *nlt);
|
||||
/**
|
||||
* Check if given NLA-Tracks have any strips with own F-Curves.
|
||||
*/
|
||||
bool BKE_nlatracks_have_animated_strips(ListBase *tracks);
|
||||
/**
|
||||
* Validate the NLA-Strips 'control' F-Curves based on the flags set.
|
||||
*/
|
||||
void BKE_nlastrip_validate_fcurves(struct NlaStrip *strip);
|
||||
|
||||
/**
|
||||
* Check if the given RNA pointer + property combo should be handled by
|
||||
* NLA strip curves or not.
|
||||
*/
|
||||
bool BKE_nlastrip_has_curves_for_property(const struct PointerRNA *ptr,
|
||||
const struct PropertyRNA *prop);
|
||||
|
||||
/**
|
||||
* Ensure that auto-blending and other settings are set correctly.
|
||||
*/
|
||||
void BKE_nla_validate_state(struct AnimData *adt);
|
||||
|
||||
/* ............ */
|
||||
|
||||
/**
|
||||
* Check if an action is "stashed" in the NLA already
|
||||
*
|
||||
* The criteria for this are:
|
||||
* 1) The action in question lives in a "stash" track.
|
||||
* 2) We only check first-level strips. That is, we will not check inside meta strips.
|
||||
*/
|
||||
bool BKE_nla_action_is_stashed(struct AnimData *adt, struct bAction *act);
|
||||
/**
|
||||
* "Stash" an action (i.e. store it as a track/layer in the NLA, but non-contributing)
|
||||
* to retain it in the file for future uses.
|
||||
*/
|
||||
bool BKE_nla_action_stash(struct AnimData *adt, bool is_liboverride);
|
||||
|
||||
/* ............ */
|
||||
|
||||
/**
|
||||
* For the given AnimData block, add the active action to the NLA
|
||||
* stack (i.e. 'push-down' action). The UI should only allow this
|
||||
* for normal editing only (i.e. not in edit-mode for some strip's action),
|
||||
* so no checks for this are performed.
|
||||
*
|
||||
* TODO: maybe we should have checks for this too.
|
||||
*/
|
||||
void BKE_nla_action_pushdown(struct AnimData *adt, bool is_liboverride);
|
||||
|
||||
/**
|
||||
* Find the active strip + track combination, and set them up as the tweaking track,
|
||||
* and return if successful or not.
|
||||
*/
|
||||
bool BKE_nla_tweakmode_enter(struct AnimData *adt);
|
||||
/**
|
||||
* Exit tweak-mode for this AnimData block.
|
||||
*/
|
||||
void BKE_nla_tweakmode_exit(struct AnimData *adt);
|
||||
|
||||
/* ----------------------------- */
|
||||
/* Time Mapping */
|
||||
|
||||
/* time mapping conversion modes */
|
||||
enum eNlaTime_ConvertModes {
|
||||
/* convert from global time to strip time - for evaluation */
|
||||
NLATIME_CONVERT_EVAL = 0,
|
||||
/* convert from global time to strip time - for editing corrections */
|
||||
/* XXX: old 0 invert. */
|
||||
NLATIME_CONVERT_UNMAP,
|
||||
/* convert from strip time to global time */
|
||||
/* XXX: old 1 invert. */
|
||||
NLATIME_CONVERT_MAP,
|
||||
};
|
||||
|
||||
/**
|
||||
* Non clipped mapping for strip-time <-> global time:
|
||||
* `mode = eNlaTime_ConvertModes -> NLATIME_CONVERT_*`
|
||||
*
|
||||
* Public API method - perform this mapping using the given AnimData block
|
||||
* and perform any necessary sanity checks on the value
|
||||
*/
|
||||
float BKE_nla_tweakedit_remap(struct AnimData *adt, float cframe, short mode);
|
||||
|
||||
/* ----------------------------- */
|
||||
/* .blend file API */
|
||||
|
||||
void BKE_nla_blend_write(struct BlendWriter *writer, struct ListBase *tracks);
|
||||
void BKE_nla_blend_read_data(struct BlendDataReader *reader, struct ListBase *tracks);
|
||||
void BKE_nla_blend_read_lib(struct BlendLibReader *reader, struct ID *id, struct ListBase *tracks);
|
||||
void BKE_nla_blend_read_expand(struct BlendExpander *expander, struct ListBase *tracks);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
145
source/blender/blenkernel/BKE_nla.h.rej
Normal file
145
source/blender/blenkernel/BKE_nla.h.rej
Normal file
@ -0,0 +1,145 @@
|
||||
***************
|
||||
*** 30,44 ****
|
||||
/* ----------------------------- */
|
||||
/* Data Management */
|
||||
|
||||
- /**
|
||||
- * Remove the given NLA strip from the NLA track it occupies, free the strip's data,
|
||||
- * and the strip itself.
|
||||
- */
|
||||
void BKE_nlastrip_free(ListBase *strips, struct NlaStrip *strip, bool do_id_user);
|
||||
- /**
|
||||
- * Remove the given NLA track from the set of NLA tracks, free the track's data,
|
||||
- * and the track itself.
|
||||
- */
|
||||
void BKE_nlatrack_free(ListBase *tracks, struct NlaTrack *nlt, bool do_id_user);
|
||||
/**
|
||||
* Free the elements of type NLA Tracks provided in the given list, but do not free
|
||||
--- 30,38 ----
|
||||
/* ----------------------------- */
|
||||
/* Data Management */
|
||||
|
||||
+ /* Free the strip's data and the strip itself. */
|
||||
void BKE_nlastrip_free(ListBase *strips, struct NlaStrip *strip, bool do_id_user);
|
||||
+ /* Free the track's data and the track itself. */
|
||||
void BKE_nlatrack_free(ListBase *tracks, struct NlaTrack *nlt, bool do_id_user);
|
||||
/**
|
||||
* Free the elements of type NLA Tracks provided in the given list, but do not free
|
||||
***************
|
||||
*** 82,98 ****
|
||||
const struct AnimData *adt_source,
|
||||
int flag);
|
||||
|
||||
/**
|
||||
* Add a NLA Track to the given AnimData.
|
||||
* \param prev: NLA-Track to add the new one after.
|
||||
*/
|
||||
- struct NlaTrack *BKE_nlatrack_add(struct AnimData *adt,
|
||||
- struct NlaTrack *prev,
|
||||
- bool is_liboverride);
|
||||
/**
|
||||
* Create a NLA Strip referencing the given Action.
|
||||
*/
|
||||
struct NlaStrip *BKE_nlastrip_new(struct bAction *act);
|
||||
/**
|
||||
* Add new NLA-strip to the top of the NLA stack - i.e.
|
||||
* into the last track if space, or a new one otherwise.
|
||||
--- 76,121 ----
|
||||
const struct AnimData *adt_source,
|
||||
int flag);
|
||||
|
||||
+
|
||||
+ struct NlaTrack *BKE_nlatrack_new();
|
||||
+ void BKE_nlatrack_remove(ListBase *tracks, struct NlaTrack *nlt);
|
||||
+ void BKE_nlatrack_remove_and_free(ListBase *tracks, struct NlaTrack *nlt, bool do_id_user);
|
||||
+
|
||||
+ void BKE_nlatrack_insert_after(ListBase *nla_tracks,
|
||||
+ struct NlaTrack *prev,
|
||||
+ struct NlaTrack *new_track,
|
||||
+ bool is_liboverride);
|
||||
+
|
||||
+ void BKE_nlatrack_insert_before(ListBase *nla_tracks,
|
||||
+ struct NlaTrack *next,
|
||||
+ struct NlaTrack *new_track,
|
||||
+ bool is_liboverride);
|
||||
/**
|
||||
* Add a NLA Track to the given AnimData.
|
||||
* \param prev: NLA-Track to add the new one after.
|
||||
*/
|
||||
+ struct NlaTrack *BKE_nlatrack_new_after_and_set_active(ListBase *nla_tracks,
|
||||
+ struct NlaTrack *prev,
|
||||
+ bool is_liboverride);
|
||||
+
|
||||
+ struct NlaTrack *BKE_nlatrack_new_before_and_set_active(ListBase *nla_tracks,
|
||||
+ struct NlaTrack *next,
|
||||
+ bool is_liboverride);
|
||||
+
|
||||
+ struct NlaTrack *BKE_nlatrack_new_tail_and_set_active(ListBase *nla_tracks,
|
||||
+ const bool is_liboverride);
|
||||
+ struct NlaTrack *BKE_nlatrack_new_head_and_set_active(ListBase *nla_tracks,
|
||||
+ bool is_liboverride);
|
||||
+
|
||||
/**
|
||||
* Create a NLA Strip referencing the given Action.
|
||||
*/
|
||||
struct NlaStrip *BKE_nlastrip_new(struct bAction *act);
|
||||
+
|
||||
+ void BKE_nlatrack_remove_strip(struct NlaTrack *track, struct NlaStrip *strip);
|
||||
+ void BKE_nlastrip_remove(ListBase *strips, struct NlaStrip *strip);
|
||||
+ void BKE_nlastrip_remove_and_free(ListBase *strips, struct NlaStrip *strip, const bool do_id_user);
|
||||
+
|
||||
/**
|
||||
* Add new NLA-strip to the top of the NLA stack - i.e.
|
||||
* into the last track if space, or a new one otherwise.
|
||||
***************
|
||||
*** 126,136 ****
|
||||
*/
|
||||
void BKE_nlastrips_sort_strips(ListBase *strips);
|
||||
|
||||
/**
|
||||
* Add the given NLA-Strip to the given list of strips, assuming that it
|
||||
* isn't currently a member of another list
|
||||
*/
|
||||
- bool BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip);
|
||||
|
||||
/**
|
||||
* Convert 'islands' (i.e. continuous string of) selected strips to be
|
||||
--- 149,161 ----
|
||||
*/
|
||||
void BKE_nlastrips_sort_strips(ListBase *strips);
|
||||
|
||||
+ bool BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip);
|
||||
/**
|
||||
* Add the given NLA-Strip to the given list of strips, assuming that it
|
||||
* isn't currently a member of another list
|
||||
*/
|
||||
+ void BKE_nlastrips_add_strip(ListBase *strips, struct NlaStrip *strip);
|
||||
+ bool BKE_nlastrips_try_add_strip(ListBase *strips, struct NlaStrip *strip);
|
||||
|
||||
/**
|
||||
* Convert 'islands' (i.e. continuous string of) selected strips to be
|
||||
***************
|
||||
*** 222,232 ****
|
||||
*/
|
||||
void BKE_nlatrack_sort_strips(struct NlaTrack *nlt);
|
||||
|
||||
- /**
|
||||
- * Add the given NLA-Strip to the given NLA-Track, assuming that it
|
||||
- * isn't currently attached to another one.
|
||||
*/
|
||||
- bool BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip, bool is_liboverride);
|
||||
|
||||
/**
|
||||
* Get the extents of the given NLA-Track including gaps between strips,
|
||||
--- 247,257 ----
|
||||
*/
|
||||
void BKE_nlatrack_sort_strips(struct NlaTrack *nlt);
|
||||
|
||||
+ void BKE_nlatrack_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip);
|
||||
+ /** Compared to non-try version, this function does checks (NULL, track flags, whether track has
|
||||
+ * space for strip, etc).
|
||||
*/
|
||||
+ bool BKE_nlatrack_try_add_strip(struct NlaTrack *nlt, struct NlaStrip *strip, bool is_liboverride);
|
||||
|
||||
/**
|
||||
* Get the extents of the given NLA-Track including gaps between strips,
|
@ -2001,12 +2001,12 @@ static void nlastrips_to_animdata(ID *id, ListBase *strips)
|
||||
|
||||
/* Try to add this strip to the current NLA-Track
|
||||
* (i.e. the 'last' one on the stack at the moment). */
|
||||
if (BKE_nlatrack_add_strip(nlt, strip, false) == 0) {
|
||||
if (!BKE_nlatrack_try_add_strip(nlt, strip, false)) {
|
||||
/* trying to add to the current failed (no space),
|
||||
* so add a new track to the stack, and add to that...
|
||||
*/
|
||||
nlt = BKE_nlatrack_add(adt, NULL, false);
|
||||
BKE_nlatrack_add_strip(nlt, strip, false);
|
||||
nlt = BKE_nlatrack_new_tail_and_set_active(&adt->nla_tracks, false);
|
||||
BKE_nlatrack_add_strip(nlt, strip);
|
||||
}
|
||||
|
||||
/* ensure that strip has a name */
|
||||
|
@ -61,7 +61,7 @@ static void nla_tweakmode_find_active(const ListBase /* NlaTrack */ *nla_tracks,
|
||||
|
||||
/* Freeing ------------------------------------------- */
|
||||
|
||||
void BKE_nlastrip_free(NlaStrip *strip, const bool do_id_user)
|
||||
void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip, bool do_id_user)
|
||||
{
|
||||
NlaStrip *cs, *csn;
|
||||
|
||||
@ -73,7 +73,7 @@ void BKE_nlastrip_free(NlaStrip *strip, const bool do_id_user)
|
||||
/* free child-strips */
|
||||
for (cs = strip->strips.first; cs; cs = csn) {
|
||||
csn = cs->next;
|
||||
BKE_nlastrip_remove_and_free(&strip->strips, cs, do_id_user);
|
||||
BKE_nlastrip_free(&strip->strips, cs, do_id_user);
|
||||
}
|
||||
|
||||
/* remove reference to action */
|
||||
@ -866,7 +866,7 @@ void BKE_nlastrips_clear_metastrip(ListBase *strips, NlaStrip *strip)
|
||||
}
|
||||
|
||||
/* free the meta-strip now */
|
||||
BKE_nlastrip_remove_and_free(strips, strip, true);
|
||||
BKE_nlastrip_free(strips, strip, true);
|
||||
}
|
||||
|
||||
void BKE_nlastrips_clear_metas(ListBase *strips, bool only_sel, bool only_temp)
|
||||
|
2339
source/blender/blenkernel/intern/nla.c.orig
Normal file
2339
source/blender/blenkernel/intern/nla.c.orig
Normal file
File diff suppressed because it is too large
Load Diff
478
source/blender/blenkernel/intern/nla.c.rej
Normal file
478
source/blender/blenkernel/intern/nla.c.rej
Normal file
@ -0,0 +1,478 @@
|
||||
***************
|
||||
*** 91,106 ****
|
||||
/* free own F-Modifiers */
|
||||
free_fmodifiers(&strip->modifiers);
|
||||
|
||||
- MEM_freeN(strip);
|
||||
- }
|
||||
-
|
||||
- void BKE_nlatrack_remove_strip(NlaTrack *track, NlaStrip *strip)
|
||||
- {
|
||||
- BLI_assert(track);
|
||||
- BKE_nlastrip_remove(&track->strips, strip);
|
||||
}
|
||||
|
||||
- void BKE_nlatrack_free(NlaTrack *nlt, const bool do_id_user)
|
||||
{
|
||||
NlaStrip *strip, *stripn;
|
||||
|
||||
--- 91,106 ----
|
||||
/* free own F-Modifiers */
|
||||
free_fmodifiers(&strip->modifiers);
|
||||
|
||||
+ /* free the strip itself */
|
||||
+ if (strips) {
|
||||
+ BLI_freelinkN(strips, strip);
|
||||
+ }
|
||||
+ else {
|
||||
+ MEM_freeN(strip);
|
||||
+ }
|
||||
}
|
||||
|
||||
+ void BKE_nlatrack_free(ListBase *tracks, NlaTrack *nlt, bool do_id_user)
|
||||
{
|
||||
NlaStrip *strip, *stripn;
|
||||
|
||||
***************
|
||||
*** 112,152 ****
|
||||
/* free strips */
|
||||
for (strip = nlt->strips.first; strip; strip = stripn) {
|
||||
stripn = strip->next;
|
||||
- BKE_nlastrip_remove_and_free(&nlt->strips, strip, do_id_user);
|
||||
}
|
||||
|
||||
/* free NLA track itself now */
|
||||
- MEM_freeN(nlt);
|
||||
- }
|
||||
-
|
||||
- void BKE_nlastrip_remove(ListBase *strips, NlaStrip *strip)
|
||||
- {
|
||||
- BLI_assert(strips);
|
||||
- BLI_remlink(strips, strip);
|
||||
- }
|
||||
-
|
||||
- void BKE_nlastrip_remove_and_free(ListBase *strips, NlaStrip *strip, const bool do_id_user)
|
||||
- {
|
||||
- BKE_nlastrip_remove(strips, strip);
|
||||
- BKE_nlastrip_free(strip, do_id_user);
|
||||
- }
|
||||
-
|
||||
- void BKE_nlatrack_remove(ListBase *tracks, NlaTrack *nlt)
|
||||
- {
|
||||
- BLI_assert(tracks);
|
||||
- BLI_remlink(tracks, nlt);
|
||||
- }
|
||||
-
|
||||
- /* Remove the given NLA track from the set of NLA tracks, free the track's data,
|
||||
- * and the track itself.
|
||||
- */
|
||||
- void BKE_nlatrack_remove_and_free(ListBase *tracks, NlaTrack *nlt, const bool do_id_user)
|
||||
- {
|
||||
- BKE_nlatrack_remove(tracks, nlt);
|
||||
- BKE_nlatrack_free(nlt, do_id_user);
|
||||
}
|
||||
|
||||
- void BKE_nla_tracks_free(ListBase *tracks, const bool do_id_user)
|
||||
{
|
||||
NlaTrack *nlt, *nltn;
|
||||
|
||||
--- 112,130 ----
|
||||
/* free strips */
|
||||
for (strip = nlt->strips.first; strip; strip = stripn) {
|
||||
stripn = strip->next;
|
||||
+ BKE_nlastrip_free(&nlt->strips, strip, do_id_user);
|
||||
}
|
||||
|
||||
/* free NLA track itself now */
|
||||
+ if (tracks) {
|
||||
+ BLI_freelinkN(tracks, nlt);
|
||||
+ }
|
||||
+ else {
|
||||
+ MEM_freeN(nlt);
|
||||
+ }
|
||||
}
|
||||
|
||||
+ void BKE_nla_tracks_free(ListBase *tracks, bool do_id_user)
|
||||
{
|
||||
NlaTrack *nlt, *nltn;
|
||||
|
||||
***************
|
||||
*** 158,164 ****
|
||||
/* free tracks one by one */
|
||||
for (nlt = tracks->first; nlt; nlt = nltn) {
|
||||
nltn = nlt->next;
|
||||
- BKE_nlatrack_remove_and_free(tracks, nlt, do_id_user);
|
||||
}
|
||||
|
||||
/* clear the list's pointers to be safe */
|
||||
--- 136,142 ----
|
||||
/* free tracks one by one */
|
||||
for (nlt = tracks->first; nlt; nlt = nltn) {
|
||||
nltn = nlt->next;
|
||||
+ BKE_nlatrack_free(tracks, nlt, do_id_user);
|
||||
}
|
||||
|
||||
/* clear the list's pointers to be safe */
|
||||
***************
|
||||
*** 324,355 ****
|
||||
|
||||
/* Adding ------------------------------------------- */
|
||||
|
||||
- NlaTrack *BKE_nlatrack_new()
|
||||
{
|
||||
/* allocate new track */
|
||||
- NlaTrack *nlt = MEM_callocN(sizeof(NlaTrack), "NlaTrack");
|
||||
|
||||
/* set settings requiring the track to not be part of the stack yet */
|
||||
nlt->flag = NLATRACK_SELECTED | NLATRACK_OVERRIDELIBRARY_LOCAL;
|
||||
-
|
||||
- return nlt;
|
||||
- }
|
||||
-
|
||||
- void BKE_nlatrack_insert_after(ListBase *nla_tracks,
|
||||
- NlaTrack *prev,
|
||||
- NlaTrack *new_track,
|
||||
- const bool is_liboverride)
|
||||
- {
|
||||
- BLI_assert(!ELEM(NULL, nla_tracks, new_track));
|
||||
-
|
||||
- /** If NULL, then caller intends to insert a new head. But, tracks are not allowed to be placed
|
||||
- * before library overrides. So it must inserted after the last override. */
|
||||
- if (prev == NULL) {
|
||||
- NlaTrack *first_track = (NlaTrack *)nla_tracks->first;
|
||||
- if (first_track != NULL && (first_track->flag & NLATRACK_OVERRIDELIBRARY_LOCAL) == 0) {
|
||||
- prev = first_track;
|
||||
- }
|
||||
- }
|
||||
|
||||
/* In liboverride case, we only add local tracks after all those coming from the linked data,
|
||||
* so we need to find the first local track. */
|
||||
--- 302,322 ----
|
||||
|
||||
/* Adding ------------------------------------------- */
|
||||
|
||||
+ NlaTrack *BKE_nlatrack_add(AnimData *adt, NlaTrack *prev, const bool is_liboverride)
|
||||
{
|
||||
+ NlaTrack *nlt;
|
||||
+
|
||||
+ /* sanity checks */
|
||||
+ if (adt == NULL) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
/* allocate new track */
|
||||
+ nlt = MEM_callocN(sizeof(NlaTrack), "NlaTrack");
|
||||
|
||||
/* set settings requiring the track to not be part of the stack yet */
|
||||
nlt->flag = NLATRACK_SELECTED | NLATRACK_OVERRIDELIBRARY_LOCAL;
|
||||
+ nlt->index = BLI_listbase_count(&adt->nla_tracks);
|
||||
|
||||
/* In liboverride case, we only add local tracks after all those coming from the linked data,
|
||||
* so we need to find the first local track. */
|
||||
***************
|
||||
*** 361,441 ****
|
||||
prev = first_local != NULL ? first_local->prev : NULL;
|
||||
}
|
||||
/* Add track to stack, and make it the active one. */
|
||||
- BLI_insertlinkafter(nla_tracks, prev, new_track);
|
||||
- new_track->index = BLI_findindex(nla_tracks, new_track);
|
||||
|
||||
/* must have unique name, but we need to seed this */
|
||||
- strcpy(new_track->name, "NlaTrack");
|
||||
- BLI_uniquename(nla_tracks,
|
||||
- new_track,
|
||||
- DATA_("NlaTrack"),
|
||||
- '.',
|
||||
- offsetof(NlaTrack, name),
|
||||
- sizeof(new_track->name));
|
||||
- }
|
||||
-
|
||||
- void BKE_nlatrack_insert_before(ListBase *nla_tracks,
|
||||
- NlaTrack *next,
|
||||
- NlaTrack *new_track,
|
||||
- const bool is_liboverride)
|
||||
- {
|
||||
- if (is_liboverride) {
|
||||
-
|
||||
- /** Currently, all library override tracks are assumed to be grouped together at the start of
|
||||
- * the list. So we can only add the new track after the last library track. */
|
||||
- if (next != NULL && (next->flag & NLATRACK_OVERRIDELIBRARY_LOCAL) == 0) {
|
||||
- BKE_nlatrack_insert_after(nla_tracks, next, new_track, is_liboverride);
|
||||
- return;
|
||||
- }
|
||||
- }
|
||||
|
||||
- BLI_insertlinkbefore(nla_tracks, next, new_track);
|
||||
- new_track->index = BLI_findindex(nla_tracks, new_track);
|
||||
-
|
||||
- /* Must have unique name, but we need to seed this. */
|
||||
- strcpy(new_track->name, "NlaTrack");
|
||||
- BLI_uniquename(nla_tracks,
|
||||
- new_track,
|
||||
- DATA_("NlaTrack"),
|
||||
- '.',
|
||||
- offsetof(NlaTrack, name),
|
||||
- sizeof(new_track->name));
|
||||
- }
|
||||
-
|
||||
- NlaTrack *BKE_nlatrack_new_after_and_set_active(ListBase *nla_tracks,
|
||||
- NlaTrack *prev,
|
||||
- const bool is_liboverride)
|
||||
- {
|
||||
- NlaTrack *new_track = BKE_nlatrack_new();
|
||||
-
|
||||
- BKE_nlatrack_insert_after(nla_tracks, prev, new_track, is_liboverride);
|
||||
- BKE_nlatrack_set_active(nla_tracks, new_track);
|
||||
-
|
||||
- return new_track;
|
||||
- }
|
||||
-
|
||||
- NlaTrack *BKE_nlatrack_new_before_and_set_active(ListBase *nla_tracks,
|
||||
- NlaTrack *next,
|
||||
- const bool is_liboverride)
|
||||
- {
|
||||
- NlaTrack *new_track = BKE_nlatrack_new();
|
||||
-
|
||||
- BKE_nlatrack_insert_before(nla_tracks, next, new_track, is_liboverride);
|
||||
- BKE_nlatrack_set_active(nla_tracks, new_track);
|
||||
-
|
||||
- return new_track;
|
||||
- }
|
||||
-
|
||||
- NlaTrack *BKE_nlatrack_new_tail_and_set_active(ListBase *nla_tracks, const bool is_liboverride)
|
||||
- {
|
||||
- return BKE_nlatrack_new_after_and_set_active(
|
||||
- nla_tracks, (NlaTrack *)nla_tracks->last, is_liboverride);
|
||||
- }
|
||||
-
|
||||
- NlaTrack *BKE_nlatrack_new_head_and_set_active(ListBase *nla_tracks, const bool is_liboverride)
|
||||
- {
|
||||
- return BKE_nlatrack_new_before_and_set_active(
|
||||
- nla_tracks, (NlaTrack *)nla_tracks->first, is_liboverride);
|
||||
}
|
||||
|
||||
NlaStrip *BKE_nlastrip_new(bAction *act)
|
||||
--- 328,348 ----
|
||||
prev = first_local != NULL ? first_local->prev : NULL;
|
||||
}
|
||||
/* Add track to stack, and make it the active one. */
|
||||
+ if (prev != NULL) {
|
||||
+ BLI_insertlinkafter(&adt->nla_tracks, prev, nlt);
|
||||
+ }
|
||||
+ else {
|
||||
+ BLI_addtail(&adt->nla_tracks, nlt);
|
||||
+ }
|
||||
+ BKE_nlatrack_set_active(&adt->nla_tracks, nlt);
|
||||
|
||||
/* must have unique name, but we need to seed this */
|
||||
+ strcpy(nlt->name, "NlaTrack");
|
||||
+ BLI_uniquename(
|
||||
+ &adt->nla_tracks, nlt, DATA_("NlaTrack"), '.', offsetof(NlaTrack, name), sizeof(nlt->name));
|
||||
|
||||
+ /* return the new track */
|
||||
+ return nlt;
|
||||
}
|
||||
|
||||
NlaStrip *BKE_nlastrip_new(bAction *act)
|
||||
***************
|
||||
*** 504,515 ****
|
||||
}
|
||||
|
||||
/* firstly try adding strip to last track, but if that fails, add to a new track */
|
||||
- if (!BKE_nlatrack_try_add_strip(adt->nla_tracks.last, strip, is_liboverride)) {
|
||||
/* trying to add to the last track failed (no track or no space),
|
||||
* so add a new track to the stack, and add to that...
|
||||
*/
|
||||
- nlt = BKE_nlatrack_new_tail_and_set_active(&adt->nla_tracks, is_liboverride);
|
||||
- BKE_nlatrack_add_strip(nlt, strip);
|
||||
}
|
||||
|
||||
/* automatically name it too */
|
||||
--- 411,422 ----
|
||||
}
|
||||
|
||||
/* firstly try adding strip to last track, but if that fails, add to a new track */
|
||||
+ if (BKE_nlatrack_add_strip(adt->nla_tracks.last, strip, is_liboverride) == 0) {
|
||||
/* trying to add to the last track failed (no track or no space),
|
||||
* so add a new track to the stack, and add to that...
|
||||
*/
|
||||
+ nlt = BKE_nlatrack_add(adt, NULL, is_liboverride);
|
||||
+ BKE_nlatrack_add_strip(nlt, strip, is_liboverride);
|
||||
}
|
||||
|
||||
/* automatically name it too */
|
||||
***************
|
||||
*** 809,821 ****
|
||||
strips->last = tmp.last;
|
||||
}
|
||||
|
||||
- void BKE_nlastrips_add_strip(ListBase *strips, NlaStrip *strip)
|
||||
{
|
||||
NlaStrip *ns;
|
||||
bool not_added = true;
|
||||
|
||||
/* sanity checks */
|
||||
- BLI_assert(!ELEM(NULL, strips, strip));
|
||||
|
||||
/* find the right place to add the strip to the nominated track */
|
||||
for (ns = strips->first; ns; ns = ns->next) {
|
||||
--- 716,735 ----
|
||||
strips->last = tmp.last;
|
||||
}
|
||||
|
||||
+ bool BKE_nlastrips_add_strip(ListBase *strips, NlaStrip *strip)
|
||||
{
|
||||
NlaStrip *ns;
|
||||
bool not_added = true;
|
||||
|
||||
/* sanity checks */
|
||||
+ if (ELEM(NULL, strips, strip)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /* check if any space to add */
|
||||
+ if (BKE_nlastrips_has_space(strips, strip->start, strip->end) == 0) {
|
||||
+ return false;
|
||||
+ }
|
||||
|
||||
/* find the right place to add the strip to the nominated track */
|
||||
for (ns = strips->first; ns; ns = ns->next) {
|
||||
***************
|
||||
*** 830,849 ****
|
||||
/* just add to the end of the list of the strips then... */
|
||||
BLI_addtail(strips, strip);
|
||||
}
|
||||
- }
|
||||
-
|
||||
- /** This version does additional checks (NULL check and space check). */
|
||||
- bool BKE_nlastrips_try_add_strip(ListBase *strips, NlaStrip *strip)
|
||||
- {
|
||||
- if (ELEM(NULL, strips, strip)) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- if (!BKE_nlastrips_has_space(strips, strip->start, strip->end)) {
|
||||
- return false;
|
||||
- }
|
||||
|
||||
- BKE_nlastrips_add_strip(strips, strip);
|
||||
return true;
|
||||
}
|
||||
|
||||
--- 744,751 ----
|
||||
/* just add to the end of the list of the strips then... */
|
||||
BLI_addtail(strips, strip);
|
||||
}
|
||||
|
||||
+ /* added... */
|
||||
return true;
|
||||
}
|
||||
|
||||
***************
|
||||
*** 894,900 ****
|
||||
}
|
||||
}
|
||||
|
||||
- bool BKE_nlameta_try_add_strip(NlaStrip *mstrip, NlaStrip *strip)
|
||||
{
|
||||
/* sanity checks */
|
||||
if (ELEM(NULL, mstrip, strip)) {
|
||||
--- 796,802 ----
|
||||
}
|
||||
}
|
||||
|
||||
+ bool BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip)
|
||||
{
|
||||
/* sanity checks */
|
||||
if (ELEM(NULL, mstrip, strip)) {
|
||||
***************
|
||||
*** 939,945 ****
|
||||
}
|
||||
|
||||
/* just try to add to the meta-strip (no dimension changes needed) */
|
||||
- return BKE_nlastrips_try_add_strip(&mstrip->strips, strip);
|
||||
}
|
||||
|
||||
void BKE_nlameta_flush_transforms(NlaStrip *mstrip)
|
||||
--- 841,847 ----
|
||||
}
|
||||
|
||||
/* just try to add to the meta-strip (no dimension changes needed) */
|
||||
+ return BKE_nlastrips_add_strip(&mstrip->strips, strip);
|
||||
}
|
||||
|
||||
void BKE_nlameta_flush_transforms(NlaStrip *mstrip)
|
||||
***************
|
||||
*** 1160,1166 ****
|
||||
BKE_nlastrips_sort_strips(&nlt->strips);
|
||||
}
|
||||
|
||||
- bool BKE_nlatrack_try_add_strip(NlaTrack *nlt, NlaStrip *strip, const bool is_liboverride)
|
||||
{
|
||||
/* sanity checks */
|
||||
if (ELEM(NULL, nlt, strip)) {
|
||||
--- 1062,1068 ----
|
||||
BKE_nlastrips_sort_strips(&nlt->strips);
|
||||
}
|
||||
|
||||
+ bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip, const bool is_liboverride)
|
||||
{
|
||||
/* sanity checks */
|
||||
if (ELEM(NULL, nlt, strip)) {
|
||||
***************
|
||||
*** 1174,1186 ****
|
||||
}
|
||||
|
||||
/* try to add the strip to the track using a more generic function */
|
||||
- return BKE_nlastrips_try_add_strip(&nlt->strips, strip);
|
||||
- }
|
||||
-
|
||||
- void BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip)
|
||||
- {
|
||||
- BLI_assert(!ELEM(NULL, nlt, strip));
|
||||
- BKE_nlastrips_add_strip(&nlt->strips, strip);
|
||||
}
|
||||
|
||||
bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2])
|
||||
--- 1076,1082 ----
|
||||
}
|
||||
|
||||
/* try to add the strip to the track using a more generic function */
|
||||
+ return BKE_nlastrips_add_strip(&nlt->strips, strip);
|
||||
}
|
||||
|
||||
bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2])
|
||||
***************
|
||||
*** 1884,1890 ****
|
||||
}
|
||||
}
|
||||
|
||||
- nlt = BKE_nlatrack_new_after_and_set_active(&adt->nla_tracks, prev_track, is_liboverride);
|
||||
BLI_assert(nlt != NULL);
|
||||
|
||||
/* We need to ensure that if there wasn't any previous instance,
|
||||
--- 1780,1786 ----
|
||||
}
|
||||
}
|
||||
|
||||
+ nlt = BKE_nlatrack_add(adt, prev_track, is_liboverride);
|
||||
BLI_assert(nlt != NULL);
|
||||
|
||||
/* We need to ensure that if there wasn't any previous instance,
|
||||
***************
|
||||
*** 1904,1910 ****
|
||||
strip = BKE_nlastrip_new(adt->action);
|
||||
BLI_assert(strip != NULL);
|
||||
|
||||
- BKE_nlatrack_add_strip(nlt, strip);
|
||||
BKE_nlastrip_validate_name(adt, strip);
|
||||
|
||||
/* mark the stash track and strip so that they doesn't disturb the stack animation,
|
||||
--- 1800,1806 ----
|
||||
strip = BKE_nlastrip_new(adt->action);
|
||||
BLI_assert(strip != NULL);
|
||||
|
||||
+ BKE_nlatrack_add_strip(nlt, strip, is_liboverride);
|
||||
BKE_nlastrip_validate_name(adt, strip);
|
||||
|
||||
/* mark the stash track and strip so that they doesn't disturb the stack animation,
|
988
source/blender/editors/space_action/action_data.c.orig
Normal file
988
source/blender/editors/space_action/action_data.c.orig
Normal file
@ -0,0 +1,988 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2015 Blender Foundation. */
|
||||
|
||||
/** \file
|
||||
* \ingroup spaction
|
||||
*/
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_gpencil_types.h"
|
||||
#include "DNA_key_types.h"
|
||||
#include "DNA_mask_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_enum_types.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "BKE_action.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_fcurve.h"
|
||||
#include "BKE_key.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_scene.h"
|
||||
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
#include "ED_gpencil.h"
|
||||
#include "ED_keyframes_edit.h"
|
||||
#include "ED_keyframing.h"
|
||||
#include "ED_markers.h"
|
||||
#include "ED_mask.h"
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
||||
#include "action_intern.h"
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* ACTION CREATION */
|
||||
|
||||
AnimData *ED_actedit_animdata_from_context(const bContext *C, ID **r_adt_id_owner)
|
||||
{
|
||||
SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
AnimData *adt = NULL;
|
||||
|
||||
/* Get AnimData block to use */
|
||||
if (saction->mode == SACTCONT_ACTION) {
|
||||
/* Currently, "Action Editor" means object-level only... */
|
||||
if (ob) {
|
||||
adt = ob->adt;
|
||||
if (r_adt_id_owner) {
|
||||
*r_adt_id_owner = &ob->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (saction->mode == SACTCONT_SHAPEKEY) {
|
||||
Key *key = BKE_key_from_object(ob);
|
||||
if (key) {
|
||||
adt = key->adt;
|
||||
if (r_adt_id_owner) {
|
||||
*r_adt_id_owner = &key->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return adt;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
/* Create new action */
|
||||
static bAction *action_create_new(bContext *C, bAction *oldact)
|
||||
{
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
bAction *action;
|
||||
|
||||
/* create action - the way to do this depends on whether we've got an
|
||||
* existing one there already, in which case we make a copy of it
|
||||
* (which is useful for "versioning" actions within the same file)
|
||||
*/
|
||||
if (oldact && GS(oldact->id.name) == ID_AC) {
|
||||
/* make a copy of the existing action */
|
||||
action = (bAction *)BKE_id_copy(CTX_data_main(C), &oldact->id);
|
||||
}
|
||||
else {
|
||||
/* just make a new (empty) action */
|
||||
action = BKE_action_add(CTX_data_main(C), "Action");
|
||||
}
|
||||
|
||||
/* when creating new ID blocks, there is already 1 user (as for all new datablocks),
|
||||
* but the RNA pointer code will assign all the proper users instead, so we compensate
|
||||
* for that here
|
||||
*/
|
||||
BLI_assert(action->id.us == 1);
|
||||
id_us_min(&action->id);
|
||||
|
||||
/* set ID-Root type */
|
||||
if (area->spacetype == SPACE_ACTION) {
|
||||
SpaceAction *saction = (SpaceAction *)area->spacedata.first;
|
||||
|
||||
if (saction->mode == SACTCONT_SHAPEKEY) {
|
||||
action->idroot = ID_KE;
|
||||
}
|
||||
else {
|
||||
action->idroot = ID_OB;
|
||||
}
|
||||
}
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
/* Change the active action used by the action editor */
|
||||
static void actedit_change_action(bContext *C, bAction *act)
|
||||
{
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
|
||||
|
||||
PointerRNA ptr, idptr;
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* create RNA pointers and get the property */
|
||||
RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, saction, &ptr);
|
||||
prop = RNA_struct_find_property(&ptr, "action");
|
||||
|
||||
/* NOTE: act may be NULL here, so better to just use a cast here */
|
||||
RNA_id_pointer_create((ID *)act, &idptr);
|
||||
|
||||
/* set the new pointer, and force a refresh */
|
||||
RNA_property_pointer_set(&ptr, prop, idptr, NULL);
|
||||
RNA_property_update(C, &ptr, prop);
|
||||
}
|
||||
|
||||
/* ******************** New Action Operator *********************** */
|
||||
|
||||
/* Criteria:
|
||||
* 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions...
|
||||
* OR
|
||||
* The NLA Editor is active (i.e. Animation Data panel -> new action)
|
||||
* 2) The associated AnimData block must not be in tweak-mode.
|
||||
*/
|
||||
static bool action_new_poll(bContext *C)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
/* Check tweak-mode is off (as you don't want to be tampering with the action in that case) */
|
||||
/* NOTE: unlike for pushdown,
|
||||
* this operator needs to be run when creating an action from nothing... */
|
||||
if (ED_operator_action_active(C)) {
|
||||
SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
|
||||
Object *ob = CTX_data_active_object(C);
|
||||
|
||||
/* For now, actions are only for the active object, and on object and shape-key levels... */
|
||||
if (saction->mode == SACTCONT_ACTION) {
|
||||
/* XXX: This assumes that actions are assigned to the active object in this mode */
|
||||
if (ob) {
|
||||
if ((ob->adt == NULL) || (ob->adt->flag & ADT_NLA_EDIT_ON) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (saction->mode == SACTCONT_SHAPEKEY) {
|
||||
Key *key = BKE_key_from_object(ob);
|
||||
if (key) {
|
||||
if ((key->adt == NULL) || (key->adt->flag & ADT_NLA_EDIT_ON) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ED_operator_nla_active(C)) {
|
||||
if (!(scene->flag & SCE_NLA_EDIT_ON)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* something failed... */
|
||||
return false;
|
||||
}
|
||||
|
||||
static int action_new_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
PointerRNA ptr, idptr;
|
||||
PropertyRNA *prop;
|
||||
|
||||
bAction *oldact = NULL;
|
||||
AnimData *adt = NULL;
|
||||
ID *adt_id_owner = NULL;
|
||||
/* hook into UI */
|
||||
UI_context_active_but_prop_get_templateID(C, &ptr, &prop);
|
||||
|
||||
if (prop) {
|
||||
/* The operator was called from a button. */
|
||||
PointerRNA oldptr;
|
||||
|
||||
oldptr = RNA_property_pointer_get(&ptr, prop);
|
||||
oldact = (bAction *)oldptr.owner_id;
|
||||
|
||||
/* stash the old action to prevent it from being lost */
|
||||
if (ptr.type == &RNA_AnimData) {
|
||||
adt = ptr.data;
|
||||
adt_id_owner = ptr.owner_id;
|
||||
}
|
||||
else if (ptr.type == &RNA_SpaceDopeSheetEditor) {
|
||||
adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
|
||||
}
|
||||
}
|
||||
else {
|
||||
adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
|
||||
oldact = adt->action;
|
||||
}
|
||||
{
|
||||
bAction *action = NULL;
|
||||
|
||||
/* Perform stashing operation - But only if there is an action */
|
||||
if (adt && oldact) {
|
||||
BLI_assert(adt_id_owner != NULL);
|
||||
/* stash the action */
|
||||
if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(adt_id_owner))) {
|
||||
/* The stash operation will remove the user already
|
||||
* (and unlink the action from the AnimData action slot).
|
||||
* Hence, we must unset the ref to the action in the
|
||||
* action editor too (if this is where we're being called from)
|
||||
* first before setting the new action once it is created,
|
||||
* or else the user gets decremented twice!
|
||||
*/
|
||||
if (ptr.type == &RNA_SpaceDopeSheetEditor) {
|
||||
SpaceAction *saction = ptr.data;
|
||||
saction->action = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#if 0
|
||||
printf("WARNING: Failed to stash %s. It may already exist in the NLA stack though\n",
|
||||
oldact->id.name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* create action */
|
||||
action = action_create_new(C, oldact);
|
||||
|
||||
if (prop) {
|
||||
/* set this new action
|
||||
* NOTE: we can't use actedit_change_action, as this function is also called from the NLA
|
||||
*/
|
||||
RNA_id_pointer_create(&action->id, &idptr);
|
||||
RNA_property_pointer_set(&ptr, prop, idptr, NULL);
|
||||
RNA_property_update(C, &ptr, prop);
|
||||
}
|
||||
}
|
||||
|
||||
/* set notifier that keyframes have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_ADDED, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACTION_OT_new(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "New Action";
|
||||
ot->idname = "ACTION_OT_new";
|
||||
ot->description = "Create new action";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = action_new_exec;
|
||||
ot->poll = action_new_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ******************* Action Push-Down Operator ******************** */
|
||||
|
||||
/* Criteria:
|
||||
* 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
|
||||
* 2) There must be an action active
|
||||
* 3) The associated AnimData block must not be in tweak-mode
|
||||
*/
|
||||
static bool action_pushdown_poll(bContext *C)
|
||||
{
|
||||
if (ED_operator_action_active(C)) {
|
||||
SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
|
||||
AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
|
||||
|
||||
/* Check for AnimData, Actions, and that tweak-mode is off. */
|
||||
if (adt && saction->action) {
|
||||
/* NOTE: We check this for the AnimData block in question and not the global flag,
|
||||
* as the global flag may be left dirty by some of the browsing ops here.
|
||||
*/
|
||||
if (!(adt->flag & ADT_NLA_EDIT_ON)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* something failed... */
|
||||
return false;
|
||||
}
|
||||
|
||||
static int action_pushdown_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
|
||||
ID *adt_id_owner = NULL;
|
||||
AnimData *adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
|
||||
|
||||
/* Do the deed... */
|
||||
if (adt) {
|
||||
/* Perform the push-down operation
|
||||
* - This will deal with all the AnimData-side user-counts. */
|
||||
if (action_has_motion(adt->action) == 0) {
|
||||
/* action may not be suitable... */
|
||||
BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* action can be safely added */
|
||||
BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(adt_id_owner));
|
||||
|
||||
struct Main *bmain = CTX_data_main(C);
|
||||
DEG_id_tag_update_ex(bmain, adt_id_owner, ID_RECALC_ANIMATION);
|
||||
|
||||
/* The action needs updating too, as FCurve modifiers are to be reevaluated. They won't extend
|
||||
* beyond the NLA strip after pushing down to the NLA. */
|
||||
DEG_id_tag_update_ex(bmain, &adt->action->id, ID_RECALC_ANIMATION);
|
||||
|
||||
/* Stop displaying this action in this editor
|
||||
* NOTE: The editor itself doesn't set a user...
|
||||
*/
|
||||
saction->action = NULL;
|
||||
}
|
||||
|
||||
/* Send notifiers that stuff has changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACTION_OT_push_down(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Push Down Action";
|
||||
ot->idname = "ACTION_OT_push_down";
|
||||
ot->description = "Push action down on to the NLA stack as a new strip";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = action_pushdown_exec;
|
||||
ot->poll = action_pushdown_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ******************* Action Stash Operator ******************** */
|
||||
|
||||
static int action_stash_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
|
||||
ID *adt_id_owner = NULL;
|
||||
AnimData *adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
|
||||
|
||||
/* Perform stashing operation */
|
||||
if (adt) {
|
||||
/* don't do anything if this action is empty... */
|
||||
if (action_has_motion(adt->action) == 0) {
|
||||
/* action may not be suitable... */
|
||||
BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* stash the action */
|
||||
if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(adt_id_owner))) {
|
||||
/* The stash operation will remove the user already,
|
||||
* so the flushing step later shouldn't double up
|
||||
* the user-count fixes. Hence, we must unset this ref
|
||||
* first before setting the new action.
|
||||
*/
|
||||
saction->action = NULL;
|
||||
}
|
||||
else {
|
||||
/* action has already been added - simply warn about this, and clear */
|
||||
BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
|
||||
}
|
||||
|
||||
/* clear action refs from editor, and then also the backing data (not necessary) */
|
||||
actedit_change_action(C, NULL);
|
||||
}
|
||||
|
||||
/* Send notifiers that stuff has changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACTION_OT_stash(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Stash Action";
|
||||
ot->idname = "ACTION_OT_stash";
|
||||
ot->description = "Store this action in the NLA stack as a non-contributing strip for later use";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = action_stash_exec;
|
||||
ot->poll = action_pushdown_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
ot->prop = RNA_def_boolean(ot->srna,
|
||||
"create_new",
|
||||
true,
|
||||
"Create New Action",
|
||||
"Create a new action once the existing one has been safely stored");
|
||||
}
|
||||
|
||||
/* ----------------- */
|
||||
|
||||
/* Criteria:
|
||||
* 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions
|
||||
* 2) The associated AnimData block must not be in tweak-mode
|
||||
*/
|
||||
static bool action_stash_create_poll(bContext *C)
|
||||
{
|
||||
if (ED_operator_action_active(C)) {
|
||||
AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
|
||||
|
||||
/* Check tweak-mode is off (as you don't want to be tampering with the action in that case) */
|
||||
/* NOTE: unlike for pushdown,
|
||||
* this operator needs to be run when creating an action from nothing... */
|
||||
if (adt) {
|
||||
if (!(adt->flag & ADT_NLA_EDIT_ON)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* There may not be any action/animdata yet, so, just fallback to the global setting
|
||||
* (which may not be totally valid yet if the action editor was used and things are
|
||||
* now in an inconsistent state)
|
||||
*/
|
||||
SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
if (!(scene->flag & SCE_NLA_EDIT_ON)) {
|
||||
/* For now, actions are only for the active object, and on object and shape-key levels...
|
||||
*/
|
||||
return ELEM(saction->mode, SACTCONT_ACTION, SACTCONT_SHAPEKEY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* something failed... */
|
||||
return false;
|
||||
}
|
||||
|
||||
static int action_stash_create_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
|
||||
ID *adt_id_owner = NULL;
|
||||
AnimData *adt = ED_actedit_animdata_from_context(C, &adt_id_owner);
|
||||
|
||||
/* Check for no action... */
|
||||
if (saction->action == NULL) {
|
||||
/* just create a new action */
|
||||
bAction *action = action_create_new(C, NULL);
|
||||
actedit_change_action(C, action);
|
||||
}
|
||||
else if (adt) {
|
||||
/* Perform stashing operation */
|
||||
if (action_has_motion(adt->action) == 0) {
|
||||
/* don't do anything if this action is empty... */
|
||||
BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* stash the action */
|
||||
if (BKE_nla_action_stash(adt, ID_IS_OVERRIDE_LIBRARY(adt_id_owner))) {
|
||||
bAction *new_action = NULL;
|
||||
|
||||
/* Create new action not based on the old one
|
||||
* (since the "new" operator already does that). */
|
||||
new_action = action_create_new(C, NULL);
|
||||
|
||||
/* The stash operation will remove the user already,
|
||||
* so the flushing step later shouldn't double up
|
||||
* the user-count fixes. Hence, we must unset this ref
|
||||
* first before setting the new action.
|
||||
*/
|
||||
saction->action = NULL;
|
||||
actedit_change_action(C, new_action);
|
||||
}
|
||||
else {
|
||||
/* action has already been added - simply warn about this, and clear */
|
||||
BKE_report(op->reports, RPT_ERROR, "Action has already been stashed");
|
||||
actedit_change_action(C, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send notifiers that stuff has changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACTION_OT_stash_and_create(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Stash Action";
|
||||
ot->idname = "ACTION_OT_stash_and_create";
|
||||
ot->description =
|
||||
"Store this action in the NLA stack as a non-contributing strip for later use, and create a "
|
||||
"new action";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = action_stash_create_exec;
|
||||
ot->poll = action_stash_create_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* ACTION UNLINK */
|
||||
|
||||
/* ******************* Action Unlink Operator ******************** */
|
||||
/* We use a custom unlink operator here, as there are some technicalities which need special care:
|
||||
* 1) When in Tweak Mode, it shouldn't be possible to unlink the active action,
|
||||
* or else, everything turns to custard.
|
||||
* 2) If the Action doesn't have any other users, the user should at least get
|
||||
* a warning that it is going to get lost.
|
||||
* 3) We need a convenient way to exit Tweak Mode from the Action Editor
|
||||
*/
|
||||
|
||||
void ED_animedit_unlink_action(
|
||||
bContext *C, ID *id, AnimData *adt, bAction *act, ReportList *reports, bool force_delete)
|
||||
{
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
|
||||
/* If the old action only has a single user (that it's about to lose),
|
||||
* warn user about it
|
||||
*
|
||||
* TODO: Maybe we should just save it for them? But then, there's the problem of
|
||||
* trying to get rid of stuff that's actually unwanted!
|
||||
*/
|
||||
if (act->id.us == 1) {
|
||||
BKE_reportf(reports,
|
||||
RPT_WARNING,
|
||||
"Action '%s' will not be saved, create Fake User or Stash in NLA Stack to retain",
|
||||
act->id.name + 2);
|
||||
}
|
||||
|
||||
/* Clear Fake User and remove action stashing strip (if present) */
|
||||
if (force_delete) {
|
||||
/* Remove stashed strip binding this action to this datablock */
|
||||
/* XXX: we cannot unlink it from *OTHER* datablocks that may also be stashing it,
|
||||
* but GE users only seem to use/care about single-object binding for now so this
|
||||
* should be fine
|
||||
*/
|
||||
if (adt) {
|
||||
NlaTrack *nlt, *nlt_next;
|
||||
NlaStrip *strip, *nstrip;
|
||||
|
||||
for (nlt = adt->nla_tracks.first; nlt; nlt = nlt_next) {
|
||||
nlt_next = nlt->next;
|
||||
|
||||
if (strstr(nlt->name, DATA_("[Action Stash]"))) {
|
||||
for (strip = nlt->strips.first; strip; strip = nstrip) {
|
||||
nstrip = strip->next;
|
||||
|
||||
if (strip->act == act) {
|
||||
/* Remove this strip, and the track too if it doesn't have anything else */
|
||||
BKE_nlastrip_remove_and_free(&nlt->strips, strip, true);
|
||||
|
||||
if (nlt->strips.first == NULL) {
|
||||
BLI_assert(nstrip == NULL);
|
||||
BKE_nlatrack_free(&adt->nla_tracks, nlt, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear Fake User */
|
||||
id_fake_user_clear(&act->id);
|
||||
}
|
||||
|
||||
/* If in Tweak Mode, don't unlink. Instead, this becomes a shortcut to exit Tweak Mode. */
|
||||
if ((adt) && (adt->flag & ADT_NLA_EDIT_ON)) {
|
||||
BKE_nla_tweakmode_exit(adt);
|
||||
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
if (scene != NULL) {
|
||||
scene->flag &= ~SCE_NLA_EDIT_ON;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Unlink normally - Setting it to NULL should be enough to get the old one unlinked */
|
||||
if (area->spacetype == SPACE_ACTION) {
|
||||
/* clear action editor -> action */
|
||||
actedit_change_action(C, NULL);
|
||||
}
|
||||
else {
|
||||
/* clear AnimData -> action */
|
||||
PointerRNA ptr;
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* create AnimData RNA pointers */
|
||||
RNA_pointer_create(id, &RNA_AnimData, adt, &ptr);
|
||||
prop = RNA_struct_find_property(&ptr, "action");
|
||||
|
||||
/* clear... */
|
||||
RNA_property_pointer_set(&ptr, prop, PointerRNA_NULL, NULL);
|
||||
RNA_property_update(C, &ptr, prop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------- */
|
||||
|
||||
static bool action_unlink_poll(bContext *C)
|
||||
{
|
||||
if (ED_operator_action_active(C)) {
|
||||
SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
|
||||
AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
|
||||
|
||||
/* Only when there's an active action, in the right modes... */
|
||||
if (saction->action && adt) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* something failed... */
|
||||
return false;
|
||||
}
|
||||
|
||||
static int action_unlink_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
|
||||
bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
|
||||
|
||||
if (adt && adt->action) {
|
||||
ED_animedit_unlink_action(C, NULL, adt, adt->action, op->reports, force_delete);
|
||||
}
|
||||
|
||||
/* Unlink is also abused to exit NLA tweak mode. */
|
||||
WM_main_add_notifier(NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
/* NOTE: this is hardcoded to match the behavior for the unlink button
|
||||
* (in interface_templates.c). */
|
||||
RNA_boolean_set(op->ptr, "force_delete", event->modifier & KM_SHIFT);
|
||||
return action_unlink_exec(C, op);
|
||||
}
|
||||
|
||||
void ACTION_OT_unlink(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* identifiers */
|
||||
ot->name = "Unlink Action";
|
||||
ot->idname = "ACTION_OT_unlink";
|
||||
ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
|
||||
|
||||
/* callbacks */
|
||||
ot->invoke = action_unlink_invoke;
|
||||
ot->exec = action_unlink_exec;
|
||||
ot->poll = action_unlink_poll;
|
||||
|
||||
/* properties */
|
||||
prop = RNA_def_boolean(ot->srna,
|
||||
"force_delete",
|
||||
false,
|
||||
"Force Delete",
|
||||
"Clear Fake User and remove "
|
||||
"copy stashed in this data-block's NLA stack");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* ACTION BROWSING */
|
||||
|
||||
/* Try to find NLA Strip to use for action layer up/down tool */
|
||||
static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime)
|
||||
{
|
||||
NlaStrip *strip;
|
||||
|
||||
for (strip = strips->first; strip; strip = strip->next) {
|
||||
/* Can we use this? */
|
||||
if (IN_RANGE_INCL(ctime, strip->start, strip->end)) {
|
||||
/* in range - use this one */
|
||||
return strip;
|
||||
}
|
||||
if ((ctime < strip->start) && (strip->prev == NULL)) {
|
||||
/* before first - use this one */
|
||||
return strip;
|
||||
}
|
||||
if ((ctime > strip->end) && (strip->next == NULL)) {
|
||||
/* after last - use this one */
|
||||
return strip;
|
||||
}
|
||||
}
|
||||
|
||||
/* nothing suitable found... */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Switch NLA Strips/Actions. */
|
||||
static void action_layer_switch_strip(
|
||||
AnimData *adt, NlaTrack *old_track, NlaStrip *old_strip, NlaTrack *nlt, NlaStrip *strip)
|
||||
{
|
||||
/* Exit tweak-mode on old strip
|
||||
* NOTE: We need to manually clear this stuff ourselves, as tweak-mode exit doesn't do it
|
||||
*/
|
||||
BKE_nla_tweakmode_exit(adt);
|
||||
|
||||
if (old_strip) {
|
||||
old_strip->flag &= ~(NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
|
||||
}
|
||||
if (old_track) {
|
||||
old_track->flag &= ~(NLATRACK_ACTIVE | NLATRACK_SELECTED);
|
||||
}
|
||||
|
||||
/* Make this one the active one instead */
|
||||
strip->flag |= (NLASTRIP_FLAG_ACTIVE | NLASTRIP_FLAG_SELECT);
|
||||
nlt->flag |= NLATRACK_ACTIVE;
|
||||
|
||||
/* Copy over "solo" flag - This is useful for stashed actions... */
|
||||
if (old_track) {
|
||||
if (old_track->flag & NLATRACK_SOLO) {
|
||||
old_track->flag &= ~NLATRACK_SOLO;
|
||||
nlt->flag |= NLATRACK_SOLO;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* NLA muting <==> Solo Tracks */
|
||||
if (adt->flag & ADT_NLA_EVAL_OFF) {
|
||||
/* disable NLA muting */
|
||||
adt->flag &= ~ADT_NLA_EVAL_OFF;
|
||||
|
||||
/* mark this track as being solo */
|
||||
adt->flag |= ADT_NLA_SOLO_TRACK;
|
||||
nlt->flag |= NLATRACK_SOLO;
|
||||
|
||||
/* TODO: Needs rest-pose flushing (when we get reference track) */
|
||||
}
|
||||
}
|
||||
|
||||
/* Enter tweak-mode again - hopefully we're now "it" */
|
||||
BKE_nla_tweakmode_enter(adt);
|
||||
BLI_assert(adt->actstrip == strip);
|
||||
}
|
||||
|
||||
/* ********************** One Layer Up Operator ************************** */
|
||||
|
||||
static bool action_layer_next_poll(bContext *C)
|
||||
{
|
||||
/* Action Editor's action editing modes only */
|
||||
if (ED_operator_action_active(C)) {
|
||||
AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
|
||||
if (adt) {
|
||||
/* only allow if we're in tweak-mode, and there's something above us... */
|
||||
if (adt->flag & ADT_NLA_EDIT_ON) {
|
||||
/* We need to check if there are any tracks above the active one
|
||||
* since the track the action comes from is not stored in AnimData
|
||||
*/
|
||||
if (adt->nla_tracks.last) {
|
||||
NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.last;
|
||||
|
||||
if (nlt->flag & NLATRACK_DISABLED) {
|
||||
/* A disabled track will either be the track itself,
|
||||
* or one of the ones above it.
|
||||
*
|
||||
* If this is the top-most one, there is the possibility
|
||||
* that there is no active action. For now, we let this
|
||||
* case return true too, so that there is a natural way
|
||||
* to "move to an empty layer", even though this means
|
||||
* that we won't actually have an action.
|
||||
*/
|
||||
// return (adt->tmpact != NULL);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* something failed... */
|
||||
return false;
|
||||
}
|
||||
|
||||
static int action_layer_next_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
|
||||
NlaTrack *act_track;
|
||||
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
float ctime = BKE_scene_ctime_get(scene);
|
||||
|
||||
/* Get active track */
|
||||
act_track = BKE_nlatrack_find_tweaked(adt);
|
||||
|
||||
if (act_track == NULL) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Could not find current NLA Track");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* Find next action, and hook it up */
|
||||
if (act_track->next) {
|
||||
NlaTrack *nlt;
|
||||
|
||||
/* Find next action to use */
|
||||
for (nlt = act_track->next; nlt; nlt = nlt->next) {
|
||||
NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
|
||||
|
||||
if (strip) {
|
||||
action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* No more actions (strips) - Go back to editing the original active action
|
||||
* NOTE: This will mean exiting tweak-mode...
|
||||
*/
|
||||
BKE_nla_tweakmode_exit(adt);
|
||||
|
||||
/* Deal with solo flags...
|
||||
* Assume: Solo Track == NLA Muting
|
||||
*/
|
||||
if (adt->flag & ADT_NLA_SOLO_TRACK) {
|
||||
/* turn off solo flags on tracks */
|
||||
act_track->flag &= ~NLATRACK_SOLO;
|
||||
adt->flag &= ~ADT_NLA_SOLO_TRACK;
|
||||
|
||||
/* turn on NLA muting (to keep same effect) */
|
||||
adt->flag |= ADT_NLA_EVAL_OFF;
|
||||
|
||||
/* TODO: Needs rest-pose flushing (when we get reference track) */
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the action that this editor now uses
|
||||
* NOTE: The calls above have already handled the user-count/anim-data side of things. */
|
||||
actedit_change_action(C, adt->action);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACTION_OT_layer_next(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Next Layer";
|
||||
ot->idname = "ACTION_OT_layer_next";
|
||||
ot->description =
|
||||
"Switch to editing action in animation layer above the current action in the NLA Stack";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = action_layer_next_exec;
|
||||
ot->poll = action_layer_next_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ********************* One Layer Down Operator ************************* */
|
||||
|
||||
static bool action_layer_prev_poll(bContext *C)
|
||||
{
|
||||
/* Action Editor's action editing modes only */
|
||||
if (ED_operator_action_active(C)) {
|
||||
AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
|
||||
if (adt) {
|
||||
if (adt->flag & ADT_NLA_EDIT_ON) {
|
||||
/* Tweak Mode: We need to check if there are any tracks below the active one
|
||||
* that we can move to */
|
||||
if (adt->nla_tracks.first) {
|
||||
NlaTrack *nlt = (NlaTrack *)adt->nla_tracks.first;
|
||||
|
||||
/* Since the first disabled track is the track being tweaked/edited,
|
||||
* we can simplify things by only checking the first track:
|
||||
* - If it is disabled, this is the track being tweaked,
|
||||
* so there can't be anything below it
|
||||
* - Otherwise, there is at least 1 track below the tweaking
|
||||
* track that we can descend to
|
||||
*/
|
||||
if ((nlt->flag & NLATRACK_DISABLED) == 0) {
|
||||
/* not disabled = there are actions below the one being tweaked */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Normal Mode: If there are any tracks, we can try moving to those */
|
||||
return (adt->nla_tracks.first != NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* something failed... */
|
||||
return false;
|
||||
}
|
||||
|
||||
static int action_layer_prev_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
AnimData *adt = ED_actedit_animdata_from_context(C, NULL);
|
||||
NlaTrack *act_track;
|
||||
NlaTrack *nlt;
|
||||
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
float ctime = BKE_scene_ctime_get(scene);
|
||||
|
||||
/* Sanity Check */
|
||||
if (adt == NULL) {
|
||||
BKE_report(
|
||||
op->reports, RPT_ERROR, "Internal Error: Could not find Animation Data/NLA Stack to use");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* Get active track */
|
||||
act_track = BKE_nlatrack_find_tweaked(adt);
|
||||
|
||||
/* If there is no active track, that means we are using the active action... */
|
||||
if (act_track) {
|
||||
/* Active Track - Start from the one below it */
|
||||
nlt = act_track->prev;
|
||||
}
|
||||
else {
|
||||
/* Active Action - Use the top-most track */
|
||||
nlt = adt->nla_tracks.last;
|
||||
}
|
||||
|
||||
/* Find previous action and hook it up */
|
||||
for (; nlt; nlt = nlt->prev) {
|
||||
NlaStrip *strip = action_layer_get_nlastrip(&nlt->strips, ctime);
|
||||
|
||||
if (strip) {
|
||||
action_layer_switch_strip(adt, act_track, adt->actstrip, nlt, strip);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the action that this editor now uses
|
||||
* NOTE: The calls above have already handled the user-count/animdata side of things. */
|
||||
actedit_change_action(C, adt->action);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void ACTION_OT_layer_prev(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Previous Layer";
|
||||
ot->idname = "ACTION_OT_layer_prev";
|
||||
ot->description =
|
||||
"Switch to editing action in animation layer below the current action in the NLA Stack";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = action_layer_prev_exec;
|
||||
ot->poll = action_layer_prev_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
25
source/blender/editors/space_action/action_data.c.rej
Normal file
25
source/blender/editors/space_action/action_data.c.rej
Normal file
@ -0,0 +1,25 @@
|
||||
***************
|
||||
*** 576,586 ****
|
||||
|
||||
if (strip->act == act) {
|
||||
/* Remove this strip, and the track too if it doesn't have anything else */
|
||||
- BKE_nlastrip_free(&nlt->strips, strip, true);
|
||||
|
||||
if (nlt->strips.first == NULL) {
|
||||
BLI_assert(nstrip == NULL);
|
||||
- BKE_nlatrack_free(&adt->nla_tracks, nlt, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
--- 576,586 ----
|
||||
|
||||
if (strip->act == act) {
|
||||
/* Remove this strip, and the track too if it doesn't have anything else */
|
||||
+ BKE_nlastrip_remove_and_free(&nlt->strips, strip, true);
|
||||
|
||||
if (nlt->strips.first == NULL) {
|
||||
BLI_assert(nstrip == NULL);
|
||||
+ BKE_nlatrack_remove_and_free(&adt->nla_tracks, nlt, true);
|
||||
}
|
||||
}
|
||||
}
|
@ -581,14 +581,14 @@ bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel)
|
||||
*/
|
||||
if (above_sel) {
|
||||
/* just add a new one above this one */
|
||||
BKE_nlatrack_add(adt, nlt, is_liboverride);
|
||||
BKE_nlatrack_new_after_and_set_active(&adt->nla_tracks, nlt, is_liboverride);
|
||||
ale->update = ANIM_UPDATE_DEPS;
|
||||
added = true;
|
||||
}
|
||||
else if ((lastAdt == NULL) || (adt != lastAdt)) {
|
||||
/* add one track to the top of the owning AnimData's stack,
|
||||
* then don't add anymore to this stack */
|
||||
BKE_nlatrack_add(adt, NULL, is_liboverride);
|
||||
BKE_nlatrack_new_tail_and_set_active(&adt->nla_tracks, is_liboverride);
|
||||
lastAdt = adt;
|
||||
ale->update = ANIM_UPDATE_DEPS;
|
||||
added = true;
|
||||
@ -625,7 +625,7 @@ bool nlaedit_add_tracks_empty(bAnimContext *ac)
|
||||
/* ensure it is empty */
|
||||
if (BLI_listbase_is_empty(&adt->nla_tracks)) {
|
||||
/* add new track to this AnimData block then */
|
||||
BKE_nlatrack_add(adt, NULL, ID_IS_OVERRIDE_LIBRARY(ale->id));
|
||||
BKE_nlatrack_new_tail_and_set_active(&adt->nla_tracks, ID_IS_OVERRIDE_LIBRARY(ale->id));
|
||||
ale->update = ANIM_UPDATE_DEPS;
|
||||
added = true;
|
||||
}
|
||||
@ -736,7 +736,7 @@ static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
}
|
||||
|
||||
/* call delete on this track - deletes all strips too */
|
||||
BKE_nlatrack_free(&adt->nla_tracks, nlt, true);
|
||||
BKE_nlatrack_remove_and_free(&adt->nla_tracks, nlt, true);
|
||||
ale->update = ANIM_UPDATE_DEPS;
|
||||
}
|
||||
}
|
||||
|
828
source/blender/editors/space_nla/nla_channels.c.orig
Normal file
828
source/blender/editors/space_nla/nla_channels.c.orig
Normal file
@ -0,0 +1,828 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2009 Blender Foundation, Joshua Leung. All rights reserved. */
|
||||
|
||||
/** \file
|
||||
* \ingroup spnla
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_layer.h"
|
||||
#include "BKE_nla.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_scene.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
#include "ED_keyframes_edit.h"
|
||||
#include "ED_object.h"
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_define.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_build.h"
|
||||
|
||||
#include "UI_view2d.h"
|
||||
|
||||
#include "nla_intern.h" /* own include */
|
||||
|
||||
/* *********************************************** */
|
||||
/* Operators for NLA channels-list which need to be different
|
||||
* from the standard Animation Editor ones */
|
||||
|
||||
/* ******************** Mouse-Click Operator *********************** */
|
||||
/* Depending on the channel that was clicked on, the mouse click will activate whichever
|
||||
* part of the channel is relevant.
|
||||
*
|
||||
* NOTE: eventually,
|
||||
* this should probably be phased out when many of these things are replaced with buttons
|
||||
* --> Most channels are now selection only.
|
||||
*/
|
||||
|
||||
static int mouse_nla_channels(bContext *C, bAnimContext *ac, int channel_index, short selectmode)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
int notifierFlags = 0;
|
||||
|
||||
/* get the channel that was clicked on */
|
||||
/* filter channels */
|
||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS |
|
||||
ANIMFILTER_FCURVESONLY);
|
||||
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
/* get channel from index */
|
||||
ale = BLI_findlink(&anim_data, channel_index);
|
||||
if (ale == NULL) {
|
||||
/* channel not found */
|
||||
if (G.debug & G_DEBUG) {
|
||||
printf("Error: animation channel (index = %d) not found in mouse_anim_channels()\n",
|
||||
channel_index);
|
||||
}
|
||||
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* action to take depends on what channel we've got */
|
||||
/* WARNING: must keep this in sync with the equivalent function in anim_channels_edit.c */
|
||||
switch (ale->type) {
|
||||
case ANIMTYPE_SCENE: {
|
||||
Scene *sce = (Scene *)ale->data;
|
||||
AnimData *adt = sce->adt;
|
||||
|
||||
/* set selection status */
|
||||
if (selectmode == SELECT_INVERT) {
|
||||
/* swap select */
|
||||
sce->flag ^= SCE_DS_SELECTED;
|
||||
if (adt) {
|
||||
adt->flag ^= ADT_UI_SELECTED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
sce->flag |= SCE_DS_SELECTED;
|
||||
if (adt) {
|
||||
adt->flag |= ADT_UI_SELECTED;
|
||||
}
|
||||
}
|
||||
|
||||
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_OBJECT: {
|
||||
ViewLayer *view_layer = ac->view_layer;
|
||||
Base *base = (Base *)ale->data;
|
||||
Object *ob = base->object;
|
||||
AnimData *adt = ob->adt;
|
||||
|
||||
if (nlaedit_is_tweakmode_on(ac) == 0 && (base->flag & BASE_SELECTABLE)) {
|
||||
/* set selection status */
|
||||
if (selectmode == SELECT_INVERT) {
|
||||
/* swap select */
|
||||
ED_object_base_select(base, BA_INVERT);
|
||||
|
||||
if (adt) {
|
||||
adt->flag ^= ADT_UI_SELECTED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* deselect all */
|
||||
/* TODO: should this deselect all other types of channels too? */
|
||||
BKE_view_layer_synced_ensure(ac->scene, view_layer);
|
||||
LISTBASE_FOREACH (Base *, b, BKE_view_layer_object_bases_get(view_layer)) {
|
||||
ED_object_base_select(b, BA_DESELECT);
|
||||
if (b->object->adt) {
|
||||
b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
/* select object now */
|
||||
ED_object_base_select(base, BA_SELECT);
|
||||
if (adt) {
|
||||
adt->flag |= ADT_UI_SELECTED;
|
||||
}
|
||||
}
|
||||
|
||||
/* change active object - regardless of whether it is now selected [#37883] */
|
||||
ED_object_base_activate_with_mode_exit_if_needed(C, base); /* adds notifier */
|
||||
|
||||
if ((adt) && (adt->flag & ADT_UI_SELECTED)) {
|
||||
adt->flag |= ADT_UI_ACTIVE;
|
||||
}
|
||||
|
||||
/* notifiers - channel was selected */
|
||||
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_FILLACTD: /* Action Expander */
|
||||
case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */
|
||||
case ANIMTYPE_DSLAM:
|
||||
case ANIMTYPE_DSCAM:
|
||||
case ANIMTYPE_DSCACHEFILE:
|
||||
case ANIMTYPE_DSCUR:
|
||||
case ANIMTYPE_DSSKEY:
|
||||
case ANIMTYPE_DSWOR:
|
||||
case ANIMTYPE_DSNTREE:
|
||||
case ANIMTYPE_DSPART:
|
||||
case ANIMTYPE_DSMBALL:
|
||||
case ANIMTYPE_DSARM:
|
||||
case ANIMTYPE_DSMESH:
|
||||
case ANIMTYPE_DSTEX:
|
||||
case ANIMTYPE_DSLAT:
|
||||
case ANIMTYPE_DSLINESTYLE:
|
||||
case ANIMTYPE_DSSPK:
|
||||
case ANIMTYPE_DSGPENCIL:
|
||||
case ANIMTYPE_PALETTE:
|
||||
case ANIMTYPE_DSHAIR:
|
||||
case ANIMTYPE_DSPOINTCLOUD:
|
||||
case ANIMTYPE_DSVOLUME:
|
||||
case ANIMTYPE_DSSIMULATION: {
|
||||
/* sanity checking... */
|
||||
if (ale->adt) {
|
||||
/* select/deselect */
|
||||
if (selectmode == SELECT_INVERT) {
|
||||
/* inverse selection status of this AnimData block only */
|
||||
ale->adt->flag ^= ADT_UI_SELECTED;
|
||||
}
|
||||
else {
|
||||
/* select AnimData block by itself */
|
||||
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_CLEAR);
|
||||
ale->adt->flag |= ADT_UI_SELECTED;
|
||||
}
|
||||
|
||||
/* set active? */
|
||||
if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) {
|
||||
ale->adt->flag |= ADT_UI_ACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_NLATRACK: {
|
||||
NlaTrack *nlt = (NlaTrack *)ale->data;
|
||||
|
||||
if (nlaedit_is_tweakmode_on(ac) == 0) {
|
||||
/* set selection */
|
||||
if (selectmode == SELECT_INVERT) {
|
||||
/* inverse selection status of this F-Curve only */
|
||||
nlt->flag ^= NLATRACK_SELECTED;
|
||||
}
|
||||
else {
|
||||
/* select F-Curve by itself */
|
||||
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_CLEAR);
|
||||
nlt->flag |= NLATRACK_SELECTED;
|
||||
}
|
||||
|
||||
/* if NLA-Track is selected now,
|
||||
* make NLA-Track the 'active' one in the visible list */
|
||||
if (nlt->flag & NLATRACK_SELECTED) {
|
||||
ANIM_set_active_channel(ac, ac->data, ac->datatype, filter, nlt, ANIMTYPE_NLATRACK);
|
||||
}
|
||||
|
||||
/* notifier flags - channel was selected */
|
||||
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ANIMTYPE_NLAACTION: {
|
||||
AnimData *adt = BKE_animdata_from_id(ale->id);
|
||||
|
||||
/* NOTE: rest of NLA-Action name doubles for operating on the AnimData block
|
||||
* - this is useful when there's no clear divider, and makes more sense in
|
||||
* the case of users trying to use this to change actions
|
||||
* - in tweak-mode, clicking here gets us out of tweak-mode, as changing selection
|
||||
* while in tweak-mode is really evil!
|
||||
* - we disable "solo" flags too, to make it easier to work with stashed actions
|
||||
* with less trouble
|
||||
*/
|
||||
if (nlaedit_is_tweakmode_on(ac)) {
|
||||
/* Exit tweak-mode immediately. */
|
||||
nlaedit_disable_tweakmode(ac, true);
|
||||
|
||||
/* changes to NLA-Action occurred */
|
||||
notifierFlags |= ND_NLA_ACTCHANGE;
|
||||
ale->update |= ANIM_UPDATE_DEPS;
|
||||
}
|
||||
else {
|
||||
/* select/deselect */
|
||||
if (selectmode == SELECT_INVERT) {
|
||||
/* inverse selection status of this AnimData block only */
|
||||
adt->flag ^= ADT_UI_SELECTED;
|
||||
}
|
||||
else {
|
||||
/* select AnimData block by itself */
|
||||
ANIM_anim_channels_select_set(ac, ACHANNEL_SETFLAG_CLEAR);
|
||||
adt->flag |= ADT_UI_SELECTED;
|
||||
}
|
||||
|
||||
/* set active? */
|
||||
if (adt->flag & ADT_UI_SELECTED) {
|
||||
adt->flag |= ADT_UI_ACTIVE;
|
||||
}
|
||||
|
||||
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (G.debug & G_DEBUG) {
|
||||
printf("Error: Invalid channel type in mouse_nla_channels()\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* free channels */
|
||||
ANIM_animdata_update(ac, &anim_data);
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
|
||||
/* return the notifier-flags set */
|
||||
return notifierFlags;
|
||||
}
|
||||
|
||||
/* ------------------- */
|
||||
|
||||
/* handle clicking */
|
||||
static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
bAnimContext ac;
|
||||
SpaceNla *snla;
|
||||
ARegion *region;
|
||||
View2D *v2d;
|
||||
int channel_index;
|
||||
int notifierFlags = 0;
|
||||
short selectmode;
|
||||
float x, y;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* get useful pointers from animation context data */
|
||||
snla = (SpaceNla *)ac.sl;
|
||||
region = ac.region;
|
||||
v2d = ®ion->v2d;
|
||||
|
||||
/* select mode is either replace (deselect all, then add) or add/extend */
|
||||
if (RNA_boolean_get(op->ptr, "extend")) {
|
||||
selectmode = SELECT_INVERT;
|
||||
}
|
||||
else {
|
||||
selectmode = SELECT_REPLACE;
|
||||
}
|
||||
|
||||
/* Figure out which channel user clicked in. */
|
||||
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
|
||||
UI_view2d_listview_view_to_cell(NLACHANNEL_NAMEWIDTH,
|
||||
NLACHANNEL_STEP(snla),
|
||||
0,
|
||||
NLACHANNEL_FIRST_TOP(&ac),
|
||||
x,
|
||||
y,
|
||||
NULL,
|
||||
&channel_index);
|
||||
|
||||
/* handle mouse-click in the relevant channel then */
|
||||
notifierFlags = mouse_nla_channels(C, &ac, channel_index, selectmode);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | notifierFlags, NULL);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_channels_click(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* identifiers */
|
||||
ot->name = "Mouse Click on NLA Channels";
|
||||
ot->idname = "NLA_OT_channels_click";
|
||||
ot->description = "Handle clicks to select NLA channels";
|
||||
|
||||
/* api callbacks */
|
||||
ot->invoke = nlachannels_mouseclick_invoke;
|
||||
ot->poll = ED_operator_nla_active;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_UNDO;
|
||||
|
||||
/* props */
|
||||
prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); /* SHIFTKEY */
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
||||
/* Special Operators */
|
||||
|
||||
/* ******************** Action Push Down ******************************** */
|
||||
|
||||
static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
ID *id = NULL;
|
||||
AnimData *adt = NULL;
|
||||
int channel_index = RNA_int_get(op->ptr, "channel_index");
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* get anim-channel to use (or more specifically, the animdata block behind it) */
|
||||
if (channel_index == -1) {
|
||||
PointerRNA adt_ptr = {NULL};
|
||||
|
||||
/* active animdata block */
|
||||
if (nla_panel_context(C, &adt_ptr, NULL, NULL) == 0 || (adt_ptr.data == NULL)) {
|
||||
BKE_report(op->reports,
|
||||
RPT_ERROR,
|
||||
"No active AnimData block to use "
|
||||
"(select a data-block expander first or set the appropriate flags on an AnimData "
|
||||
"block)");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
id = adt_ptr.owner_id;
|
||||
adt = adt_ptr.data;
|
||||
}
|
||||
else {
|
||||
/* indexed channel */
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
/* filter channels */
|
||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS |
|
||||
ANIMFILTER_FCURVESONLY);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* get channel from index */
|
||||
ale = BLI_findlink(&anim_data, channel_index);
|
||||
if (ale == NULL) {
|
||||
BKE_reportf(op->reports, RPT_ERROR, "No animation channel found at index %d", channel_index);
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
if (ale->type != ANIMTYPE_NLAACTION) {
|
||||
BKE_reportf(op->reports,
|
||||
RPT_ERROR,
|
||||
"Animation channel at index %d is not a NLA 'Active Action' channel",
|
||||
channel_index);
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* grab AnimData from the channel */
|
||||
adt = ale->adt;
|
||||
id = ale->id;
|
||||
|
||||
/* we don't need anything here anymore, so free it all */
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
}
|
||||
|
||||
/* double-check that we are free to push down here... */
|
||||
if (adt == NULL) {
|
||||
BKE_report(op->reports, RPT_WARNING, "Internal Error - AnimData block is not valid");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
if (nlaedit_is_tweakmode_on(&ac)) {
|
||||
BKE_report(op->reports,
|
||||
RPT_WARNING,
|
||||
"Cannot push down actions while tweaking a strip's action, exit tweak mode first");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
if (adt->action == NULL) {
|
||||
BKE_report(op->reports, RPT_WARNING, "No active action to push down");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* 'push-down' action - only usable when not in Tweak-mode. */
|
||||
BKE_nla_action_pushdown(adt, ID_IS_OVERRIDE_LIBRARY(id));
|
||||
|
||||
struct Main *bmain = CTX_data_main(C);
|
||||
DEG_id_tag_update_ex(bmain, id, ID_RECALC_ANIMATION);
|
||||
|
||||
/* The action needs updating too, as FCurve modifiers are to be reevaluated. They won't extend
|
||||
* beyond the NLA strip after pushing down to the NLA. */
|
||||
DEG_id_tag_update_ex(bmain, &adt->action->id, ID_RECALC_ANIMATION);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA_ACTCHANGE, NULL);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_action_pushdown(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Push Down Action";
|
||||
ot->idname = "NLA_OT_action_pushdown";
|
||||
ot->description = "Push action down onto the top of the NLA stack as a new strip";
|
||||
|
||||
/* callbacks */
|
||||
ot->exec = nlachannels_pushdown_exec;
|
||||
ot->poll = nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
ot->prop = RNA_def_int(ot->srna,
|
||||
"channel_index",
|
||||
-1,
|
||||
-1,
|
||||
INT_MAX,
|
||||
"Channel Index",
|
||||
"Index of NLA action channel to perform pushdown operation on",
|
||||
0,
|
||||
INT_MAX);
|
||||
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE | PROP_HIDDEN);
|
||||
}
|
||||
|
||||
/* ******************** Action Unlink ******************************** */
|
||||
|
||||
static bool nla_action_unlink_poll(bContext *C)
|
||||
{
|
||||
if (ED_operator_nla_active(C)) {
|
||||
PointerRNA adt_ptr;
|
||||
return (nla_panel_context(C, &adt_ptr, NULL, NULL) && (adt_ptr.data != NULL));
|
||||
}
|
||||
|
||||
/* something failed... */
|
||||
return false;
|
||||
}
|
||||
|
||||
static int nla_action_unlink_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
PointerRNA adt_ptr;
|
||||
AnimData *adt;
|
||||
|
||||
/* check context and also validity of pointer */
|
||||
if (!nla_panel_context(C, &adt_ptr, NULL, NULL)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* get animdata */
|
||||
adt = adt_ptr.data;
|
||||
if (adt == NULL) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* do unlinking */
|
||||
if (adt->action) {
|
||||
bool force_delete = RNA_boolean_get(op->ptr, "force_delete");
|
||||
ED_animedit_unlink_action(C, adt_ptr.owner_id, adt, adt->action, op->reports, force_delete);
|
||||
}
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int nla_action_unlink_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
/* NOTE: this is hardcoded to match the behavior for the unlink button
|
||||
* (in interface_templates.c) */
|
||||
RNA_boolean_set(op->ptr, "force_delete", event->modifier & KM_SHIFT);
|
||||
return nla_action_unlink_exec(C, op);
|
||||
}
|
||||
|
||||
void NLA_OT_action_unlink(wmOperatorType *ot)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
/* identifiers */
|
||||
ot->name = "Unlink Action";
|
||||
ot->idname = "NLA_OT_action_unlink";
|
||||
ot->description = "Unlink this action from the active action slot (and/or exit Tweak Mode)";
|
||||
|
||||
/* callbacks */
|
||||
ot->invoke = nla_action_unlink_invoke;
|
||||
ot->exec = nla_action_unlink_exec;
|
||||
ot->poll = nla_action_unlink_poll;
|
||||
|
||||
/* properties */
|
||||
prop = RNA_def_boolean(ot->srna,
|
||||
"force_delete",
|
||||
false,
|
||||
"Force Delete",
|
||||
"Clear Fake User and remove copy stashed in this data-block's NLA stack");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
}
|
||||
|
||||
/* ******************** Add Tracks Operator ***************************** */
|
||||
/* Add NLA Tracks to the same AnimData block as a selected track, or above the selected tracks */
|
||||
|
||||
bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
AnimData *lastAdt = NULL;
|
||||
bool added = false;
|
||||
|
||||
/* get a list of the (selected) NLA Tracks being shown in the NLA */
|
||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL |
|
||||
ANIMFILTER_NODUPLIS | ANIMFILTER_FCURVESONLY);
|
||||
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
/* add tracks... */
|
||||
for (ale = anim_data.first; ale; ale = ale->next) {
|
||||
if (ale->type == ANIMTYPE_NLATRACK) {
|
||||
NlaTrack *nlt = (NlaTrack *)ale->data;
|
||||
AnimData *adt = ale->adt;
|
||||
|
||||
const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
|
||||
|
||||
/* check if just adding a new track above this one,
|
||||
* or whether we're adding a new one to the top of the stack that this one belongs to
|
||||
*/
|
||||
if (above_sel) {
|
||||
/* just add a new one above this one */
|
||||
BKE_nlatrack_add(adt, nlt, is_liboverride);
|
||||
ale->update = ANIM_UPDATE_DEPS;
|
||||
added = true;
|
||||
}
|
||||
else if ((lastAdt == NULL) || (adt != lastAdt)) {
|
||||
/* add one track to the top of the owning AnimData's stack,
|
||||
* then don't add anymore to this stack */
|
||||
BKE_nlatrack_add(adt, NULL, is_liboverride);
|
||||
lastAdt = adt;
|
||||
ale->update = ANIM_UPDATE_DEPS;
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
ANIM_animdata_update(ac, &anim_data);
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
bool nlaedit_add_tracks_empty(bAnimContext *ac)
|
||||
{
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
bool added = false;
|
||||
|
||||
/* get a list of the selected AnimData blocks in the NLA */
|
||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA |
|
||||
ANIMFILTER_SEL | ANIMFILTER_NODUPLIS | ANIMFILTER_FCURVESONLY);
|
||||
ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
|
||||
|
||||
/* check if selected AnimData blocks are empty, and add tracks if so... */
|
||||
for (ale = anim_data.first; ale; ale = ale->next) {
|
||||
AnimData *adt = ale->adt;
|
||||
|
||||
/* sanity check */
|
||||
BLI_assert(adt->flag & ADT_UI_SELECTED);
|
||||
|
||||
/* ensure it is empty */
|
||||
if (BLI_listbase_is_empty(&adt->nla_tracks)) {
|
||||
/* add new track to this AnimData block then */
|
||||
BKE_nlatrack_add(adt, NULL, ID_IS_OVERRIDE_LIBRARY(ale->id));
|
||||
ale->update = ANIM_UPDATE_DEPS;
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
ANIM_animdata_update(ac, &anim_data);
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
/* ----- */
|
||||
|
||||
static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
bAnimContext ac;
|
||||
bool above_sel = RNA_boolean_get(op->ptr, "above_selected");
|
||||
bool op_done = false;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* perform adding in two passes - existing first so that we don't double up for empty */
|
||||
op_done |= nlaedit_add_tracks_existing(&ac, above_sel);
|
||||
op_done |= nlaedit_add_tracks_empty(&ac);
|
||||
|
||||
/* done? */
|
||||
if (op_done) {
|
||||
DEG_relations_tag_update(CTX_data_main(C));
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
/* failed to add any tracks */
|
||||
BKE_report(
|
||||
op->reports, RPT_WARNING, "Select an existing NLA Track or an empty action line first");
|
||||
|
||||
/* not done */
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void NLA_OT_tracks_add(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Add Tracks";
|
||||
ot->idname = "NLA_OT_tracks_add";
|
||||
ot->description = "Add NLA-Tracks above/after the selected tracks";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = nlaedit_add_tracks_exec;
|
||||
ot->poll = nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
RNA_def_boolean(ot->srna,
|
||||
"above_selected",
|
||||
0,
|
||||
"Above Selected",
|
||||
"Add a new NLA Track above every existing selected one");
|
||||
}
|
||||
|
||||
/* ******************** Delete Tracks Operator ***************************** */
|
||||
/* Delete selected NLA Tracks */
|
||||
|
||||
static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* get a list of the AnimData blocks being shown in the NLA */
|
||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL |
|
||||
ANIMFILTER_NODUPLIS | ANIMFILTER_FCURVESONLY);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* delete tracks */
|
||||
for (ale = anim_data.first; ale; ale = ale->next) {
|
||||
if (ale->type == ANIMTYPE_NLATRACK) {
|
||||
NlaTrack *nlt = (NlaTrack *)ale->data;
|
||||
AnimData *adt = ale->adt;
|
||||
|
||||
if (BKE_nlatrack_is_nonlocal_in_liboverride(ale->id, nlt)) {
|
||||
/* No deletion of non-local tracks of override data. */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if track is currently 'solo', then AnimData should have its
|
||||
* 'has solo' flag disabled
|
||||
*/
|
||||
if (nlt->flag & NLATRACK_SOLO) {
|
||||
adt->flag &= ~ADT_NLA_SOLO_TRACK;
|
||||
}
|
||||
|
||||
/* call delete on this track - deletes all strips too */
|
||||
BKE_nlatrack_free(&adt->nla_tracks, nlt, true);
|
||||
ale->update = ANIM_UPDATE_DEPS;
|
||||
}
|
||||
}
|
||||
|
||||
/* free temp data */
|
||||
ANIM_animdata_update(&ac, &anim_data);
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
|
||||
DEG_relations_tag_update(ac.bmain);
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_tracks_delete(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Delete Tracks";
|
||||
ot->idname = "NLA_OT_tracks_delete";
|
||||
ot->description = "Delete selected NLA-Tracks and the strips they contain";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = nlaedit_delete_tracks_exec;
|
||||
ot->poll = nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
||||
/* AnimData Related Operators */
|
||||
|
||||
/* ******************** Include Objects Operator ***************************** */
|
||||
/* Include selected objects in NLA Editor, by giving them AnimData blocks
|
||||
* NOTE: This doesn't help for non-object AnimData, where we do not have any effective
|
||||
* selection mechanism in place. Unfortunately, this means that non-object AnimData
|
||||
* once again becomes a second-class citizen here. However, at least for the most
|
||||
* common use case, we now have a nice shortcut again.
|
||||
*/
|
||||
|
||||
static int nlaedit_objects_add_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
bAnimContext ac;
|
||||
SpaceNla *snla;
|
||||
|
||||
/* get editor data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* ensure that filters are set so that the effect will be immediately visible */
|
||||
snla = (SpaceNla *)ac.sl;
|
||||
if (snla && snla->ads) {
|
||||
snla->ads->filterflag &= ~ADS_FILTER_NLA_NOACT;
|
||||
}
|
||||
|
||||
/* operate on selected objects... */
|
||||
CTX_DATA_BEGIN (C, Object *, ob, selected_objects) {
|
||||
/* ensure that object has AnimData... that's all */
|
||||
BKE_animdata_ensure_id(&ob->id);
|
||||
}
|
||||
CTX_DATA_END;
|
||||
|
||||
/* set notifier that things have changed */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
|
||||
|
||||
/* done */
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void NLA_OT_selected_objects_add(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Include Selected Objects";
|
||||
ot->idname = "NLA_OT_selected_objects_add";
|
||||
ot->description = "Make selected objects appear in NLA Editor by adding Animation Data";
|
||||
|
||||
/* api callbacks */
|
||||
ot->exec = nlaedit_objects_add_exec;
|
||||
ot->poll = nlaop_poll_tweakmode_off;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/* *********************************************** */
|
@ -713,12 +713,12 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
|
||||
strip->start = cfra;
|
||||
|
||||
/* firstly try adding strip to our current track, but if that fails, add to a new track */
|
||||
if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) {
|
||||
if (!BKE_nlatrack_try_add_strip(nlt, strip, is_liboverride)) {
|
||||
/* trying to add to the current failed (no space),
|
||||
* so add a new track to the stack, and add to that...
|
||||
*/
|
||||
nlt = BKE_nlatrack_add(adt, NULL, is_liboverride);
|
||||
BKE_nlatrack_add_strip(nlt, strip, is_liboverride);
|
||||
nlt = BKE_nlatrack_new_tail_and_set_active(&adt->nla_tracks, is_liboverride);
|
||||
BKE_nlatrack_add_strip(nlt, strip);
|
||||
}
|
||||
|
||||
/* auto-name it */
|
||||
@ -951,12 +951,12 @@ static int nlaedit_add_sound_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
strip->end += cfra;
|
||||
|
||||
/* firstly try adding strip to our current track, but if that fails, add to a new track */
|
||||
if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) {
|
||||
if (!BKE_nlatrack_try_add_strip(nlt, strip, is_liboverride)) {
|
||||
/* trying to add to the current failed (no space),
|
||||
* so add a new track to the stack, and add to that...
|
||||
*/
|
||||
nlt = BKE_nlatrack_add(adt, NULL, is_liboverride);
|
||||
BKE_nlatrack_add_strip(nlt, strip, is_liboverride);
|
||||
nlt = BKE_nlatrack_new_tail_and_set_active(&adt->nla_tracks, is_liboverride);
|
||||
BKE_nlatrack_add_strip(nlt, strip);
|
||||
}
|
||||
|
||||
/* auto-name it */
|
||||
@ -1190,13 +1190,9 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
|
||||
|
||||
/* in case there's no space in the track above,
|
||||
* or we haven't got a reference to it yet, try adding */
|
||||
if (BKE_nlatrack_add_strip(nlt->next, nstrip, is_liboverride) == 0) {
|
||||
/* need to add a new track above the one above the current one
|
||||
* - if the current one is the last one, nlt->next will be NULL, which defaults to adding
|
||||
* at the top of the stack anyway...
|
||||
*/
|
||||
track = BKE_nlatrack_add(adt, nlt->next, is_liboverride);
|
||||
BKE_nlatrack_add_strip(track, nstrip, is_liboverride);
|
||||
if (!BKE_nlatrack_try_add_strip(nlt->next, nstrip, is_liboverride)) {
|
||||
track = BKE_nlatrack_new_after_and_set_active(&adt->nla_tracks, nlt, is_liboverride);
|
||||
BKE_nlatrack_add_strip(track, nstrip);
|
||||
}
|
||||
|
||||
/* deselect the original and the active flag */
|
||||
@ -1731,8 +1727,8 @@ static int nlaedit_swap_exec(bContext *C, wmOperator *op)
|
||||
}
|
||||
|
||||
/* add strips back to track now */
|
||||
BKE_nlatrack_add_strip(nlt, area, is_liboverride);
|
||||
BKE_nlatrack_add_strip(nlt, sb, is_liboverride);
|
||||
BKE_nlatrack_try_add_strip(nlt, area, is_liboverride);
|
||||
BKE_nlatrack_try_add_strip(nlt, sb, is_liboverride);
|
||||
}
|
||||
|
||||
/* Clear (temp) meta-strips. */
|
||||
@ -1802,8 +1798,6 @@ static int nlaedit_move_up_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
NlaTrack *nltn = nlt->next;
|
||||
NlaStrip *strip, *stripn;
|
||||
|
||||
const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
|
||||
|
||||
/* if this track has no tracks after it, skip for now... */
|
||||
if (nltn == NULL) {
|
||||
continue;
|
||||
@ -1894,8 +1888,6 @@ static int nlaedit_move_down_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
NlaTrack *nltp = nlt->prev;
|
||||
NlaStrip *strip, *stripn;
|
||||
|
||||
const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(ale->id);
|
||||
|
||||
/* if this track has no tracks before it, skip for now... */
|
||||
if (nltp == NULL) {
|
||||
continue;
|
||||
@ -2457,10 +2449,10 @@ static int nlaedit_snap_exec(bContext *C, wmOperator *op)
|
||||
BLI_remlink(&tmp_strips, strip);
|
||||
|
||||
/* in case there's no space in the current track, try adding */
|
||||
if (BKE_nlatrack_add_strip(nlt, strip, is_liboverride) == 0) {
|
||||
if (!BKE_nlatrack_try_add_strip(nlt, strip, is_liboverride)) {
|
||||
/* need to add a new track above the current one */
|
||||
track = BKE_nlatrack_add(adt, nlt, is_liboverride);
|
||||
BKE_nlatrack_add_strip(track, strip, is_liboverride);
|
||||
track = BKE_nlatrack_new_after_and_set_active(&adt->nla_tracks, nlt, is_liboverride);
|
||||
BKE_nlatrack_add_strip(track, strip);
|
||||
|
||||
/* clear temp meta-strips on this new track,
|
||||
* as we may not be able to get back to it */
|
||||
|
2850
source/blender/editors/space_nla/nla_edit.c.orig
Normal file
2850
source/blender/editors/space_nla/nla_edit.c.orig
Normal file
File diff suppressed because it is too large
Load Diff
71
source/blender/editors/space_nla/nla_edit.c.rej
Normal file
71
source/blender/editors/space_nla/nla_edit.c.rej
Normal file
@ -0,0 +1,71 @@
|
||||
***************
|
||||
*** 1310,1324 ****
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* if a strip either side of this was a transition, delete those too */
|
||||
if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) {
|
||||
- BKE_nlastrip_free(&nlt->strips, strip->prev, true);
|
||||
}
|
||||
if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) {
|
||||
nstrip = nstrip->next;
|
||||
- BKE_nlastrip_free(&nlt->strips, strip->next, true);
|
||||
}
|
||||
|
||||
/* finally, delete this strip */
|
||||
- BKE_nlastrip_free(&nlt->strips, strip, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
--- 1306,1320 ----
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* if a strip either side of this was a transition, delete those too */
|
||||
if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) {
|
||||
+ BKE_nlastrip_remove_and_free(&nlt->strips, strip->prev, true);
|
||||
}
|
||||
if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) {
|
||||
nstrip = nstrip->next;
|
||||
+ BKE_nlastrip_remove_and_free(&nlt->strips, strip->next, true);
|
||||
}
|
||||
|
||||
/* finally, delete this strip */
|
||||
+ BKE_nlastrip_remove_and_free(&nlt->strips, strip, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
***************
|
||||
*** 1824,1831 ****
|
||||
if (BKE_nlatrack_has_space(nltn, strip->start, strip->end)) {
|
||||
/* remove from its current track, and add to the one above
|
||||
* (it 'should' work, so no need to worry) */
|
||||
- BLI_remlink(&nlt->strips, strip);
|
||||
- BKE_nlatrack_add_strip(nltn, strip, is_liboverride);
|
||||
}
|
||||
}
|
||||
}
|
||||
--- 1818,1825 ----
|
||||
if (BKE_nlatrack_has_space(nltn, strip->start, strip->end)) {
|
||||
/* remove from its current track, and add to the one above
|
||||
* (it 'should' work, so no need to worry) */
|
||||
+ BKE_nlatrack_remove_strip(nlt, strip);
|
||||
+ BKE_nlatrack_add_strip(nltn, strip);
|
||||
}
|
||||
}
|
||||
}
|
||||
***************
|
||||
*** 1916,1923 ****
|
||||
if (BKE_nlatrack_has_space(nltp, strip->start, strip->end)) {
|
||||
/* remove from its current track, and add to the one above
|
||||
* (it 'should' work, so no need to worry) */
|
||||
- BLI_remlink(&nlt->strips, strip);
|
||||
- BKE_nlatrack_add_strip(nltp, strip, is_liboverride);
|
||||
}
|
||||
}
|
||||
}
|
||||
--- 1908,1915 ----
|
||||
if (BKE_nlatrack_has_space(nltp, strip->start, strip->end)) {
|
||||
/* remove from its current track, and add to the one above
|
||||
* (it 'should' work, so no need to worry) */
|
||||
+ BKE_nlatrack_remove_strip(nlt, strip);
|
||||
+ BKE_nlatrack_add_strip(nltp, strip);
|
||||
}
|
||||
}
|
||||
}
|
@ -434,7 +434,6 @@ static void recalcData_nla(TransInfo *t)
|
||||
* as only one may have been altered by transform if only 1 handle moved.
|
||||
*/
|
||||
/* In LibOverride case, we cannot move strips across tracks that come from the linked data. */
|
||||
const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(tdn->id);
|
||||
if (BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, tdn->nlt)) {
|
||||
continue;
|
||||
}
|
||||
@ -489,7 +488,7 @@ static void recalcData_nla(TransInfo *t)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
549
source/blender/editors/transform/transform_convert_nla.c.orig
Normal file
549
source/blender/editors/transform/transform_convert_nla.c.orig
Normal file
@ -0,0 +1,549 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
* Copyright 2001-2002 NaN Holding BV. All rights reserved. */
|
||||
|
||||
/** \file
|
||||
* \ingroup edtransform
|
||||
*/
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_nla.h"
|
||||
|
||||
#include "ED_anim_api.h"
|
||||
#include "ED_markers.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "transform.h"
|
||||
#include "transform_convert.h"
|
||||
#include "transform_mode.h"
|
||||
#include "transform_snap.h"
|
||||
|
||||
/** Used for NLA transform (stored in #TransData.extra pointer). */
|
||||
typedef struct TransDataNla {
|
||||
/** ID-block NLA-data is attached to. */
|
||||
ID *id;
|
||||
|
||||
/** Original NLA-Track that the strip belongs to. */
|
||||
struct NlaTrack *oldTrack;
|
||||
/** Current NLA-Track that the strip belongs to. */
|
||||
struct NlaTrack *nlt;
|
||||
|
||||
/** NLA-strip this data represents. */
|
||||
struct NlaStrip *strip;
|
||||
|
||||
/* dummy values for transform to write in - must have 3 elements... */
|
||||
/** start handle. */
|
||||
float h1[3];
|
||||
/** end handle. */
|
||||
float h2[3];
|
||||
|
||||
/** index of track that strip is currently in. */
|
||||
int trackIndex;
|
||||
/** handle-index: 0 for dummy entry, -1 for start, 1 for end, 2 for both ends. */
|
||||
int handle;
|
||||
} TransDataNla;
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Transform application to NLA strips
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* \brief Applies a translation to the given #NlaStrip.
|
||||
* \param strip_rna_ptr: The RNA pointer of the NLA strip to modify.
|
||||
* \param transdata: The transformation info structure.
|
||||
*/
|
||||
static void applyTransformNLA_translation(PointerRNA *strip_rna_ptr, const TransDataNla *transdata)
|
||||
{
|
||||
/* NOTE: we write these twice to avoid truncation errors which can arise when
|
||||
* moving the strips a large distance using numeric input #33852.
|
||||
*/
|
||||
RNA_float_set(strip_rna_ptr, "frame_start", transdata->h1[0]);
|
||||
RNA_float_set(strip_rna_ptr, "frame_end", transdata->h2[0]);
|
||||
|
||||
RNA_float_set(strip_rna_ptr, "frame_start", transdata->h1[0]);
|
||||
RNA_float_set(strip_rna_ptr, "frame_end", transdata->h2[0]);
|
||||
}
|
||||
|
||||
static void applyTransformNLA_timeScale(PointerRNA *strip_rna_ptr, const float value)
|
||||
{
|
||||
RNA_float_set(strip_rna_ptr, "scale", value);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name NLA Transform Creation
|
||||
* \{ */
|
||||
|
||||
static void createTransNlaData(bContext *C, TransInfo *t)
|
||||
{
|
||||
Scene *scene = t->scene;
|
||||
SpaceNla *snla = NULL;
|
||||
TransData *td = NULL;
|
||||
TransDataNla *tdn = NULL;
|
||||
|
||||
bAnimContext ac;
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
int filter;
|
||||
|
||||
int count = 0;
|
||||
|
||||
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
|
||||
|
||||
/* determine what type of data we are operating on */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0) {
|
||||
return;
|
||||
}
|
||||
snla = (SpaceNla *)ac.sl;
|
||||
|
||||
/* filter data */
|
||||
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_FOREDIT |
|
||||
ANIMFILTER_FCURVESONLY);
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
/* which side of the current frame should be allowed */
|
||||
if (t->mode == TFM_TIME_EXTEND) {
|
||||
t->frame_side = transform_convert_frame_side_dir_get(t, (float)scene->r.cfra);
|
||||
}
|
||||
else {
|
||||
/* normal transform - both sides of current frame are considered */
|
||||
t->frame_side = 'B';
|
||||
}
|
||||
|
||||
/* loop 1: count how many strips are selected (consider each strip as 2 points) */
|
||||
for (ale = anim_data.first; ale; ale = ale->next) {
|
||||
NlaTrack *nlt = (NlaTrack *)ale->data;
|
||||
NlaStrip *strip;
|
||||
|
||||
/* make some meta-strips for chains of selected strips */
|
||||
BKE_nlastrips_make_metas(&nlt->strips, 1);
|
||||
|
||||
/* only consider selected strips */
|
||||
for (strip = nlt->strips.first; strip; strip = strip->next) {
|
||||
/* TODO: we can make strips have handles later on. */
|
||||
/* transition strips can't get directly transformed */
|
||||
if (strip->type != NLASTRIP_TYPE_TRANSITION) {
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
if (FrameOnMouseSide(t->frame_side, strip->start, (float)scene->r.cfra)) {
|
||||
count++;
|
||||
}
|
||||
if (FrameOnMouseSide(t->frame_side, strip->end, (float)scene->r.cfra)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* stop if trying to build list if nothing selected */
|
||||
if (count == 0) {
|
||||
/* clear temp metas that may have been created but aren't needed now
|
||||
* because they fell on the wrong side of scene->r.cfra
|
||||
*/
|
||||
for (ale = anim_data.first; ale; ale = ale->next) {
|
||||
NlaTrack *nlt = (NlaTrack *)ale->data;
|
||||
BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
|
||||
}
|
||||
|
||||
/* cleanup temp list */
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
return;
|
||||
}
|
||||
|
||||
/* allocate memory for data */
|
||||
tc->data_len = count;
|
||||
|
||||
tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransData(NLA Editor)");
|
||||
td = tc->data;
|
||||
tc->custom.type.data = tdn = MEM_callocN(tc->data_len * sizeof(TransDataNla),
|
||||
"TransDataNla (NLA Editor)");
|
||||
tc->custom.type.use_free = true;
|
||||
|
||||
/* loop 2: build transdata array */
|
||||
for (ale = anim_data.first; ale; ale = ale->next) {
|
||||
/* only if a real NLA-track */
|
||||
if (ale->type == ANIMTYPE_NLATRACK) {
|
||||
AnimData *adt = ale->adt;
|
||||
NlaTrack *nlt = (NlaTrack *)ale->data;
|
||||
NlaStrip *strip;
|
||||
|
||||
/* only consider selected strips */
|
||||
for (strip = nlt->strips.first; strip; strip = strip->next) {
|
||||
/* TODO: we can make strips have handles later on. */
|
||||
/* transition strips can't get directly transformed */
|
||||
if (strip->type != NLASTRIP_TYPE_TRANSITION) {
|
||||
if (strip->flag & NLASTRIP_FLAG_SELECT) {
|
||||
/* our transform data is constructed as follows:
|
||||
* - only the handles on the right side of the current-frame get included
|
||||
* - td structs are transform-elements operated on by the transform system
|
||||
* and represent a single handle. The storage/pointer used (val or loc) depends on
|
||||
* whether we're scaling or transforming. Ultimately though, the handles
|
||||
* the td writes to will simply be a dummy in tdn
|
||||
* - for each strip being transformed, a single tdn struct is used, so in some
|
||||
* cases, there will need to be 1 of these tdn elements in the array skipped...
|
||||
*/
|
||||
float center[3], yval;
|
||||
|
||||
/* firstly, init tdn settings */
|
||||
tdn->id = ale->id;
|
||||
tdn->oldTrack = tdn->nlt = nlt;
|
||||
tdn->strip = strip;
|
||||
tdn->trackIndex = BLI_findindex(&adt->nla_tracks, nlt);
|
||||
|
||||
yval = (float)(tdn->trackIndex * NLACHANNEL_STEP(snla));
|
||||
|
||||
tdn->h1[0] = strip->start;
|
||||
tdn->h1[1] = yval;
|
||||
tdn->h2[0] = strip->end;
|
||||
tdn->h2[1] = yval;
|
||||
tdn->h1[2] = tdn->h2[2] = strip->scale;
|
||||
|
||||
center[0] = (float)scene->r.cfra;
|
||||
center[1] = yval;
|
||||
center[2] = 0.0f;
|
||||
|
||||
/* set td's based on which handles are applicable */
|
||||
if (FrameOnMouseSide(t->frame_side, strip->start, (float)scene->r.cfra)) {
|
||||
/* just set tdn to assume that it only has one handle for now */
|
||||
tdn->handle = -1;
|
||||
|
||||
/* Now, link the transform data up to this data. */
|
||||
td->loc = tdn->h1;
|
||||
copy_v3_v3(td->iloc, tdn->h1);
|
||||
|
||||
if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
|
||||
/* Store all the other gunk that is required by transform. */
|
||||
copy_v3_v3(td->center, center);
|
||||
td->axismtx[2][2] = 1.0f;
|
||||
td->flag |= TD_SELECTED;
|
||||
unit_m3(td->mtx);
|
||||
unit_m3(td->smtx);
|
||||
}
|
||||
|
||||
td->extra = tdn;
|
||||
td++;
|
||||
}
|
||||
if (FrameOnMouseSide(t->frame_side, strip->end, (float)scene->r.cfra)) {
|
||||
/* if tdn is already holding the start handle,
|
||||
* then we're doing both, otherwise, only end */
|
||||
tdn->handle = (tdn->handle) ? 2 : 1;
|
||||
|
||||
/* Now, link the transform data up to this data. */
|
||||
td->loc = tdn->h2;
|
||||
copy_v3_v3(td->iloc, tdn->h2);
|
||||
|
||||
if (ELEM(t->mode, TFM_TRANSLATION, TFM_TIME_EXTEND)) {
|
||||
/* Store all the other gunk that is required by transform. */
|
||||
copy_v3_v3(td->center, center);
|
||||
td->axismtx[2][2] = 1.0f;
|
||||
td->flag |= TD_SELECTED;
|
||||
unit_m3(td->mtx);
|
||||
unit_m3(td->smtx);
|
||||
}
|
||||
|
||||
td->extra = tdn;
|
||||
td++;
|
||||
}
|
||||
|
||||
/* If both handles were used, skip the next tdn (i.e. leave it blank)
|
||||
* since the counting code is dumb.
|
||||
* Otherwise, just advance to the next one.
|
||||
*/
|
||||
if (tdn->handle == 2) {
|
||||
tdn += 2;
|
||||
}
|
||||
else {
|
||||
tdn++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* cleanup temp list */
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
}
|
||||
|
||||
static void recalcData_nla(TransInfo *t)
|
||||
{
|
||||
SpaceNla *snla = (SpaceNla *)t->area->spacedata.first;
|
||||
|
||||
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
|
||||
|
||||
/* handle auto-snapping
|
||||
* NOTE: only do this when transform is still running, or we can't restore
|
||||
*/
|
||||
if (t->state != TRANS_CANCEL) {
|
||||
const short autosnap = getAnimEdit_SnapMode(t);
|
||||
if (autosnap != SACTSNAP_OFF) {
|
||||
TransData *td = tc->data;
|
||||
for (int i = 0; i < tc->data_len; i++, td++) {
|
||||
transform_snap_anim_flush_data(t, td, autosnap, td->loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* For each strip we've got, perform some additional validation of the values
|
||||
* that got set before using RNA to set the value (which does some special
|
||||
* operations when setting these values to make sure that everything works ok).
|
||||
*/
|
||||
TransDataNla *tdn = tc->custom.type.data;
|
||||
for (int i = 0; i < tc->data_len; i++, tdn++) {
|
||||
NlaStrip *strip = tdn->strip;
|
||||
PointerRNA strip_ptr;
|
||||
int delta_y1, delta_y2;
|
||||
|
||||
/* if this tdn has no handles, that means it is just a dummy that should be skipped */
|
||||
if (tdn->handle == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* set refresh tags for objects using this animation,
|
||||
* BUT only if realtime updates are enabled
|
||||
*/
|
||||
if ((snla->flag & SNLA_NOREALTIMEUPDATES) == 0) {
|
||||
ANIM_id_update(CTX_data_main(t->context), tdn->id);
|
||||
}
|
||||
|
||||
/* if canceling transform, just write the values without validating, then move on */
|
||||
if (t->state == TRANS_CANCEL) {
|
||||
/* clear the values by directly overwriting the originals, but also need to restore
|
||||
* endpoints of neighboring transition-strips
|
||||
*/
|
||||
|
||||
/* start */
|
||||
strip->start = tdn->h1[0];
|
||||
|
||||
if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION)) {
|
||||
strip->prev->end = tdn->h1[0];
|
||||
}
|
||||
|
||||
/* end */
|
||||
strip->end = tdn->h2[0];
|
||||
|
||||
if ((strip->next) && (strip->next->type == NLASTRIP_TYPE_TRANSITION)) {
|
||||
strip->next->start = tdn->h2[0];
|
||||
}
|
||||
|
||||
strip->scale = tdn->h1[2];
|
||||
|
||||
/* flush transforms to child strips (since this should be a meta) */
|
||||
BKE_nlameta_flush_transforms(strip);
|
||||
|
||||
/* restore to original track (if needed) */
|
||||
if (tdn->oldTrack != tdn->nlt) {
|
||||
/* Just append to end of list for now,
|
||||
* since strips get sorted in special_aftertrans_update(). */
|
||||
BLI_remlink(&tdn->nlt->strips, strip);
|
||||
BLI_addtail(&tdn->oldTrack->strips, strip);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* firstly, check if the proposed transform locations would overlap with any neighboring strips
|
||||
* (barring transitions) which are absolute barriers since they are not being moved
|
||||
*
|
||||
* this is done as a iterative procedure (done 5 times max for now)
|
||||
*/
|
||||
NlaStrip *prev = BKE_nlastrip_prev_in_track(strip, true);
|
||||
NlaStrip *next = BKE_nlastrip_next_in_track(strip, true);
|
||||
|
||||
for (short iter = 0; iter < 5; iter++) {
|
||||
const bool pExceeded = (prev != NULL) && (tdn->h1[0] < prev->end);
|
||||
const bool nExceeded = (next != NULL) && (tdn->h2[0] > next->start);
|
||||
|
||||
if ((pExceeded && nExceeded) || (iter == 4)) {
|
||||
/* both endpoints exceeded (or iteration ping-pong'd meaning that we need a
|
||||
* compromise)
|
||||
* - Simply crop strip to fit within the bounds of the strips bounding it
|
||||
* - If there were no neighbors, clear the transforms
|
||||
* (make it default to the strip's current values).
|
||||
*/
|
||||
if (prev && next) {
|
||||
tdn->h1[0] = prev->end;
|
||||
tdn->h2[0] = next->start;
|
||||
}
|
||||
else {
|
||||
tdn->h1[0] = strip->start;
|
||||
tdn->h2[0] = strip->end;
|
||||
}
|
||||
}
|
||||
else if (nExceeded) {
|
||||
/* move backwards */
|
||||
float offset = tdn->h2[0] - next->start;
|
||||
|
||||
tdn->h1[0] -= offset;
|
||||
tdn->h2[0] -= offset;
|
||||
}
|
||||
else if (pExceeded) {
|
||||
/* more forwards */
|
||||
float offset = prev->end - tdn->h1[0];
|
||||
|
||||
tdn->h1[0] += offset;
|
||||
tdn->h2[0] += offset;
|
||||
}
|
||||
else { /* all is fine and well */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Use RNA to write the values to ensure that constraints on these are obeyed
|
||||
* (e.g. for transition strips, the values are taken from the neighbors)
|
||||
*/
|
||||
RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr);
|
||||
|
||||
switch (t->mode) {
|
||||
case TFM_TIME_EXTEND:
|
||||
case TFM_TIME_SCALE: {
|
||||
/* The final scale is the product of the original strip scale (from before the transform
|
||||
* operation started) and the current scale value of this transform operation. */
|
||||
const float originalStripScale = tdn->h1[2];
|
||||
const float newStripScale = originalStripScale * t->values_final[0];
|
||||
applyTransformNLA_timeScale(&strip_ptr, newStripScale);
|
||||
applyTransformNLA_translation(&strip_ptr, tdn);
|
||||
break;
|
||||
}
|
||||
case TFM_TRANSLATION:
|
||||
applyTransformNLA_translation(&strip_ptr, tdn);
|
||||
break;
|
||||
default:
|
||||
printf("recalcData_nla: unsupported NLA transformation mode %d\n", t->mode);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* flush transforms to child strips (since this should be a meta) */
|
||||
BKE_nlameta_flush_transforms(strip);
|
||||
|
||||
/* Now, check if we need to try and move track:
|
||||
* - we need to calculate both,
|
||||
* as only one may have been altered by transform if only 1 handle moved.
|
||||
*/
|
||||
/* In LibOverride case, we cannot move strips across tracks that come from the linked data. */
|
||||
const bool is_liboverride = ID_IS_OVERRIDE_LIBRARY(tdn->id);
|
||||
if (BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, tdn->nlt)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
delta_y1 = ((int)tdn->h1[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
|
||||
delta_y2 = ((int)tdn->h2[1] / NLACHANNEL_STEP(snla) - tdn->trackIndex);
|
||||
|
||||
if (delta_y1 || delta_y2) {
|
||||
NlaTrack *track;
|
||||
int delta = (delta_y2) ? delta_y2 : delta_y1;
|
||||
int n;
|
||||
|
||||
/* Move in the requested direction,
|
||||
* checking at each layer if there's space for strip to pass through,
|
||||
* stopping on the last track available or that we're able to fit in.
|
||||
*/
|
||||
if (delta > 0) {
|
||||
for (track = tdn->nlt->next, n = 0; (track) && (n < delta); track = track->next, n++) {
|
||||
/* check if space in this track for the strip */
|
||||
if (BKE_nlatrack_has_space(track, strip->start, strip->end) &&
|
||||
!BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, track)) {
|
||||
/* move strip to this track */
|
||||
BKE_nlatrack_remove_strip(tdn->nlt, strip);
|
||||
BKE_nlatrack_add_strip(track, strip, is_liboverride);
|
||||
|
||||
tdn->nlt = track;
|
||||
tdn->trackIndex++;
|
||||
}
|
||||
else { /* can't move any further */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* make delta 'positive' before using it, since we now know to go backwards */
|
||||
delta = -delta;
|
||||
|
||||
for (track = tdn->nlt->prev, n = 0; (track) && (n < delta); track = track->prev, n++) {
|
||||
/* check if space in this track for the strip */
|
||||
if (BKE_nlatrack_has_space(track, strip->start, strip->end) &&
|
||||
!BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, track)) {
|
||||
/* move strip to this track */
|
||||
BKE_nlatrack_remove_strip(tdn->nlt, strip);
|
||||
BKE_nlatrack_add_strip(track, strip, is_liboverride);
|
||||
|
||||
tdn->nlt = track;
|
||||
tdn->trackIndex--;
|
||||
}
|
||||
else { /* can't move any further */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Special After Transform NLA
|
||||
* \{ */
|
||||
|
||||
static void special_aftertrans_update__nla(bContext *C, TransInfo *UNUSED(t))
|
||||
{
|
||||
bAnimContext ac;
|
||||
|
||||
/* initialize relevant anim-context 'context' data */
|
||||
if (ANIM_animdata_get_context(C, &ac) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ac.datatype) {
|
||||
ListBase anim_data = {NULL, NULL};
|
||||
bAnimListElem *ale;
|
||||
short filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_FCURVESONLY);
|
||||
|
||||
/* get channels to work on */
|
||||
ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
|
||||
|
||||
for (ale = anim_data.first; ale; ale = ale->next) {
|
||||
NlaTrack *nlt = (NlaTrack *)ale->data;
|
||||
|
||||
/* make sure strips are in order again */
|
||||
BKE_nlatrack_sort_strips(nlt);
|
||||
|
||||
/* remove the temp metas */
|
||||
BKE_nlastrips_clear_metas(&nlt->strips, 0, 1);
|
||||
}
|
||||
|
||||
/* General refresh for the outliner because the following might have happened:
|
||||
* - strips moved between tracks
|
||||
* - strips swapped order
|
||||
* - duplicate-move moves to different track. */
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL);
|
||||
|
||||
/* free temp memory */
|
||||
ANIM_animdata_freelist(&anim_data);
|
||||
|
||||
/* Perform after-transform validation. */
|
||||
ED_nla_postop_refresh(&ac);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
TransConvertTypeInfo TransConvertType_NLA = {
|
||||
/*flags*/ (T_POINTS | T_2D_EDIT),
|
||||
/*createTransData*/ createTransNlaData,
|
||||
/*recalcData*/ recalcData_nla,
|
||||
/*special_aftertrans_update*/ special_aftertrans_update__nla,
|
||||
};
|
38
source/blender/editors/transform/transform_convert_nla.c.rej
Normal file
38
source/blender/editors/transform/transform_convert_nla.c.rej
Normal file
@ -0,0 +1,38 @@
|
||||
***************
|
||||
*** 457,464 ****
|
||||
if (BKE_nlatrack_has_space(track, strip->start, strip->end) &&
|
||||
!BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, track)) {
|
||||
/* move strip to this track */
|
||||
- BLI_remlink(&tdn->nlt->strips, strip);
|
||||
- BKE_nlatrack_add_strip(track, strip, is_liboverride);
|
||||
|
||||
tdn->nlt = track;
|
||||
tdn->trackIndex++;
|
||||
--- 456,463 ----
|
||||
if (BKE_nlatrack_has_space(track, strip->start, strip->end) &&
|
||||
!BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, track)) {
|
||||
/* move strip to this track */
|
||||
+ BKE_nlatrack_remove_strip(tdn->nlt, strip);
|
||||
+ BKE_nlatrack_add_strip(track, strip);
|
||||
|
||||
tdn->nlt = track;
|
||||
tdn->trackIndex++;
|
||||
***************
|
||||
*** 477,484 ****
|
||||
if (BKE_nlatrack_has_space(track, strip->start, strip->end) &&
|
||||
!BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, track)) {
|
||||
/* move strip to this track */
|
||||
- BLI_remlink(&tdn->nlt->strips, strip);
|
||||
- BKE_nlatrack_add_strip(track, strip, is_liboverride);
|
||||
|
||||
tdn->nlt = track;
|
||||
tdn->trackIndex--;
|
||||
--- 476,483 ----
|
||||
if (BKE_nlatrack_has_space(track, strip->start, strip->end) &&
|
||||
!BKE_nlatrack_is_nonlocal_in_liboverride(tdn->id, track)) {
|
||||
/* move strip to this track */
|
||||
+ BKE_nlatrack_remove_strip(tdn->nlt, strip);
|
||||
+ BKE_nlatrack_add_strip(track, strip);
|
||||
|
||||
tdn->nlt = track;
|
||||
tdn->trackIndex--;
|
@ -573,7 +573,14 @@ static void rna_KeyingSet_paths_clear(KeyingSet *keyingset, ReportList *reports)
|
||||
/* needs wrapper function to push notifier */
|
||||
static NlaTrack *rna_NlaTrack_new(ID *id, AnimData *adt, Main *bmain, bContext *C, NlaTrack *track)
|
||||
{
|
||||
NlaTrack *new_track = BKE_nlatrack_add(adt, track, ID_IS_OVERRIDE_LIBRARY(id));
|
||||
NlaTrack *new_track;
|
||||
if (track != NULL) {
|
||||
new_track = BKE_nlatrack_new_after_and_set_active(
|
||||
&adt->nla_tracks, track, ID_IS_OVERRIDE_LIBRARY(id));
|
||||
}
|
||||
else {
|
||||
new_track = BKE_nlatrack_new_tail_and_set_active(&adt->nla_tracks, ID_IS_OVERRIDE_LIBRARY(id));
|
||||
}
|
||||
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_ADDED, NULL);
|
||||
|
||||
@ -593,7 +600,7 @@ static void rna_NlaTrack_remove(
|
||||
return;
|
||||
}
|
||||
|
||||
BKE_nlatrack_free(&adt->nla_tracks, track, true);
|
||||
BKE_nlatrack_remove_and_free(&adt->nla_tracks, track, true);
|
||||
RNA_POINTER_INVALIDATE(track_ptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL);
|
||||
|
1071
source/blender/makesrna/intern/rna_nla.c.orig
Normal file
1071
source/blender/makesrna/intern/rna_nla.c.orig
Normal file
File diff suppressed because it is too large
Load Diff
44
source/blender/makesrna/intern/rna_nla.c.rej
Normal file
44
source/blender/makesrna/intern/rna_nla.c.rej
Normal file
@ -0,0 +1,44 @@
|
||||
***************
|
||||
*** 390,401 ****
|
||||
strip->end += (start - strip->start);
|
||||
strip->start = start;
|
||||
|
||||
- if (BKE_nlastrips_add_strip(&track->strips, strip) == 0) {
|
||||
BKE_report(
|
||||
reports,
|
||||
RPT_ERROR,
|
||||
"Unable to add strip (the track does not have any space to accommodate this new strip)");
|
||||
- BKE_nlastrip_free(NULL, strip, true);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
--- 390,401 ----
|
||||
strip->end += (start - strip->start);
|
||||
strip->start = start;
|
||||
|
||||
+ if (!BKE_nlastrips_try_add_strip(&track->strips, strip)) {
|
||||
BKE_report(
|
||||
reports,
|
||||
RPT_ERROR,
|
||||
"Unable to add strip (the track does not have any space to accommodate this new strip)");
|
||||
+ BKE_nlastrip_free(strip, true);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
***************
|
||||
*** 446,452 ****
|
||||
return;
|
||||
}
|
||||
|
||||
- BKE_nlastrip_free(&track->strips, strip, true);
|
||||
RNA_POINTER_INVALIDATE(strip_ptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL);
|
||||
--- 446,452 ----
|
||||
return;
|
||||
}
|
||||
|
||||
+ BKE_nlastrip_remove_and_free(&track->strips, strip, true);
|
||||
RNA_POINTER_INVALIDATE(strip_ptr);
|
||||
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_REMOVED, NULL);
|
@ -1 +1 @@
|
||||
Subproject commit e133fc08cd3254bb3d3bd1345028c8486700bca4
|
||||
Subproject commit d50df97812e481c36ccae965e8fa3101ab8ab320
|
Loading…
Reference in New Issue
Block a user