Anim: rebuild depsgraph relations when creating a new F-Curve
When a new F-Curve is created on a layered Action, tag the dependency graph for rebuilding its relationships. This is necessary as the F-Curve may be animating a depsgraph component that was previously not animated, and thus that relation needs to be constructed. This was already in place for legacy Actions, and simply overlooked for the new layered ones. Pull Request: https://projects.blender.org/blender/blender/pulls/125236
This commit is contained in:
@@ -675,7 +675,8 @@ class KeyframeStrip : public ::KeyframeActionStrip {
|
||||
/** Return the channelbag's index, or -1 if there is none for this slot handle. */
|
||||
int64_t find_channelbag_index(const ChannelBag &channelbag) const;
|
||||
|
||||
SingleKeyingResult keyframe_insert(const Slot &slot,
|
||||
SingleKeyingResult keyframe_insert(Main *bmain,
|
||||
const Slot &slot,
|
||||
FCurveDescriptor fcurve_descriptor,
|
||||
float2 time_value,
|
||||
const KeyframeSettings &settings,
|
||||
@@ -713,15 +714,27 @@ class ChannelBag : public ::ActionChannelBag {
|
||||
/**
|
||||
* Find an FCurve matching the fcurve descriptor, or create one if it doesn't
|
||||
* exist.
|
||||
*
|
||||
* \param bmain Used to tag the dependency graph(s) for relationship
|
||||
* rebuilding. This is necessary when adding a new F-Curve, as a
|
||||
* previously-unanimated depsgraph component may become animated now. Can be
|
||||
* nullptr, in which case the tagging is skipped and is left as the
|
||||
* responsibility of the caller.
|
||||
*/
|
||||
FCurve &fcurve_ensure(FCurveDescriptor fcurve_descriptor);
|
||||
FCurve &fcurve_ensure(Main *bmain, FCurveDescriptor fcurve_descriptor);
|
||||
|
||||
/**
|
||||
* Create an F-Curve, but only if it doesn't exist yet in this ChannelBag.
|
||||
*
|
||||
* \return the F-Curve it it was created, or nullptr if it already existed.
|
||||
*
|
||||
* \param bmain Used to tag the dependency graph(s) for relationship
|
||||
* rebuilding. This is necessary when adding a new F-Curve, as a
|
||||
* previously-unanimated depsgraph component may become animated now. Can be
|
||||
* nullptr, in which case the tagging is skipped and is left as the
|
||||
* responsibility of the caller.
|
||||
*/
|
||||
FCurve *fcurve_create_unique(FCurveDescriptor fcurve_descriptor);
|
||||
FCurve *fcurve_create_unique(Main *bmain, FCurveDescriptor fcurve_descriptor);
|
||||
|
||||
/**
|
||||
* Remove an F-Curve from the ChannelBag.
|
||||
@@ -742,9 +755,16 @@ class ChannelBag : public ::ActionChannelBag {
|
||||
/**
|
||||
* Create an F-Curve.
|
||||
*
|
||||
* Assumes that there is no such F-Curve yet on this ChannelBag.
|
||||
* Assumes that there is no such F-Curve yet on this ChannelBag. If it is
|
||||
* uncertain whether this is the case, use `fcurve_create_unique()` instead.
|
||||
*
|
||||
* \param bmain Used to tag the dependency graph(s) for relationship
|
||||
* rebuilding. This is necessary when adding a new F-Curve, as a
|
||||
* previously-unanimated depsgraph component may become animated now. Can be
|
||||
* nullptr, in which case the tagging is skipped and is left as the
|
||||
* responsibility of the caller.
|
||||
*/
|
||||
FCurve &fcurve_create(FCurveDescriptor fcurve_descriptor);
|
||||
FCurve &fcurve_create(Main *bmain, FCurveDescriptor fcurve_descriptor);
|
||||
};
|
||||
static_assert(sizeof(ChannelBag) == sizeof(::ActionChannelBag),
|
||||
"DNA struct and its C++ wrapper must have the same size");
|
||||
@@ -848,6 +868,10 @@ Vector<FCurve *> fcurves_all(Action &action);
|
||||
* nullptr for layered actions. See the comments in the implementation for more
|
||||
* details.
|
||||
*
|
||||
* \note This function also ensures that dependency graph relationships are
|
||||
* rebuilt. This is necessary when adding a new F-Curve, as a
|
||||
* previously-unanimated depsgraph component may become animated now.
|
||||
*
|
||||
* \param ptr: RNA pointer for the struct the fcurve is being looked up/created
|
||||
* for. For legacy actions this is optional and may be null.
|
||||
*
|
||||
|
||||
@@ -1124,23 +1124,23 @@ FCurve *ChannelBag::fcurve_find(const FCurveDescriptor fcurve_descriptor)
|
||||
return animrig::fcurve_find(fcurves, fcurve_descriptor);
|
||||
}
|
||||
|
||||
FCurve &ChannelBag::fcurve_ensure(const FCurveDescriptor fcurve_descriptor)
|
||||
FCurve &ChannelBag::fcurve_ensure(Main *bmain, const FCurveDescriptor fcurve_descriptor)
|
||||
{
|
||||
if (FCurve *existing_fcurve = this->fcurve_find(fcurve_descriptor)) {
|
||||
return *existing_fcurve;
|
||||
}
|
||||
return this->fcurve_create(fcurve_descriptor);
|
||||
return this->fcurve_create(bmain, fcurve_descriptor);
|
||||
}
|
||||
|
||||
FCurve *ChannelBag::fcurve_create_unique(FCurveDescriptor fcurve_descriptor)
|
||||
FCurve *ChannelBag::fcurve_create_unique(Main *bmain, FCurveDescriptor fcurve_descriptor)
|
||||
{
|
||||
if (this->fcurve_find(fcurve_descriptor)) {
|
||||
return nullptr;
|
||||
}
|
||||
return &this->fcurve_create(fcurve_descriptor);
|
||||
return &this->fcurve_create(bmain, fcurve_descriptor);
|
||||
}
|
||||
|
||||
FCurve &ChannelBag::fcurve_create(FCurveDescriptor fcurve_descriptor)
|
||||
FCurve &ChannelBag::fcurve_create(Main *bmain, FCurveDescriptor fcurve_descriptor)
|
||||
{
|
||||
FCurve *new_fcurve = create_fcurve_for_channel(fcurve_descriptor);
|
||||
|
||||
@@ -1149,6 +1149,11 @@ FCurve &ChannelBag::fcurve_create(FCurveDescriptor fcurve_descriptor)
|
||||
}
|
||||
|
||||
grow_array_and_append(&this->fcurve_array, &this->fcurve_array_num, new_fcurve);
|
||||
|
||||
if (bmain) {
|
||||
DEG_relations_tag_update(bmain);
|
||||
}
|
||||
|
||||
return *new_fcurve;
|
||||
}
|
||||
|
||||
@@ -1167,6 +1172,10 @@ bool ChannelBag::fcurve_remove(FCurve &fcurve_to_remove)
|
||||
dna::array::remove_index(
|
||||
&this->fcurve_array, &this->fcurve_array_num, nullptr, fcurve_index, fcurve_ptr_destructor);
|
||||
|
||||
/* As an optimisation, this function could call `DEG_relations_tag_update(bmain)` to prune any
|
||||
* relationships that are now no longer necessary. This is not needed for correctness of the
|
||||
* depsgraph evaluation results though. */
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1175,7 +1184,8 @@ void ChannelBag::fcurves_clear()
|
||||
dna::array::clear(&this->fcurve_array, &this->fcurve_array_num, nullptr, fcurve_ptr_destructor);
|
||||
}
|
||||
|
||||
SingleKeyingResult KeyframeStrip::keyframe_insert(const Slot &slot,
|
||||
SingleKeyingResult KeyframeStrip::keyframe_insert(Main *bmain,
|
||||
const Slot &slot,
|
||||
const FCurveDescriptor fcurve_descriptor,
|
||||
const float2 time_value,
|
||||
const KeyframeSettings &settings,
|
||||
@@ -1185,7 +1195,7 @@ SingleKeyingResult KeyframeStrip::keyframe_insert(const Slot &slot,
|
||||
* allow. */
|
||||
FCurve *fcurve = nullptr;
|
||||
if (key_insertion_may_create_fcurve(insert_key_flags)) {
|
||||
fcurve = &this->channelbag_for_slot_ensure(slot).fcurve_ensure(fcurve_descriptor);
|
||||
fcurve = &this->channelbag_for_slot_ensure(slot).fcurve_ensure(bmain, fcurve_descriptor);
|
||||
}
|
||||
else {
|
||||
ChannelBag *channels = this->channelbag_for_slot(slot);
|
||||
@@ -1438,7 +1448,7 @@ FCurve *action_fcurve_ensure(Main *bmain,
|
||||
assert_baklava_phase_1_invariants(action);
|
||||
KeyframeStrip &strip = action.layer(0)->strip(0)->as<KeyframeStrip>();
|
||||
|
||||
return &strip.channelbag_for_slot_ensure(slot).fcurve_ensure(fcurve_descriptor);
|
||||
return &strip.channelbag_for_slot_ensure(slot).fcurve_ensure(bmain, fcurve_descriptor);
|
||||
}
|
||||
|
||||
/* Try to find f-curve matching for this setting.
|
||||
|
||||
@@ -144,9 +144,9 @@ TEST_F(ActionLayersTest, add_strip)
|
||||
/* Add some keys to check that also the strip data is freed correctly. */
|
||||
const KeyframeSettings settings = get_keyframe_settings(false);
|
||||
Slot &slot = action->slot_add();
|
||||
strip.as<KeyframeStrip>().keyframe_insert(slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
strip.as<KeyframeStrip>().keyframe_insert(bmain, slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
another_strip.as<KeyframeStrip>().keyframe_insert(
|
||||
slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
bmain, slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
}
|
||||
|
||||
TEST_F(ActionLayersTest, remove_strip)
|
||||
@@ -159,9 +159,12 @@ TEST_F(ActionLayersTest, remove_strip)
|
||||
/* Add some keys to check that also the strip data is freed correctly. */
|
||||
const KeyframeSettings settings = get_keyframe_settings(false);
|
||||
Slot &slot = action->slot_add();
|
||||
strip0.as<KeyframeStrip>().keyframe_insert(slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
strip1.as<KeyframeStrip>().keyframe_insert(slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
strip2.as<KeyframeStrip>().keyframe_insert(slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
strip0.as<KeyframeStrip>().keyframe_insert(
|
||||
bmain, slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
strip1.as<KeyframeStrip>().keyframe_insert(
|
||||
bmain, slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
strip2.as<KeyframeStrip>().keyframe_insert(
|
||||
bmain, slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
|
||||
EXPECT_TRUE(layer.strip_remove(strip1));
|
||||
EXPECT_EQ(2, layer.strips().size());
|
||||
@@ -555,7 +558,7 @@ TEST_F(ActionLayersTest, KeyframeStrip__keyframe_insert)
|
||||
|
||||
const KeyframeSettings settings = get_keyframe_settings(false);
|
||||
SingleKeyingResult result_loc_a = key_strip.keyframe_insert(
|
||||
slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
bmain, slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
ASSERT_EQ(SingleKeyingResult::SUCCESS, result_loc_a)
|
||||
<< "Expected keyframe insertion to be successful";
|
||||
|
||||
@@ -566,7 +569,7 @@ TEST_F(ActionLayersTest, KeyframeStrip__keyframe_insert)
|
||||
|
||||
/* Insert a second key, should insert into the same FCurve as before. */
|
||||
SingleKeyingResult result_loc_b = key_strip.keyframe_insert(
|
||||
slot, {"location", 0}, {5.0f, 47.1f}, settings);
|
||||
bmain, slot, {"location", 0}, {5.0f, 47.1f}, settings);
|
||||
EXPECT_EQ(SingleKeyingResult::SUCCESS, result_loc_b);
|
||||
ASSERT_EQ(1, channels->fcurves().size()) << "Expect insertion with the same (slot/rna "
|
||||
"path/array index) tuple to go into the same FCurve";
|
||||
@@ -579,7 +582,7 @@ TEST_F(ActionLayersTest, KeyframeStrip__keyframe_insert)
|
||||
|
||||
/* Insert another key for another property, should create another FCurve. */
|
||||
SingleKeyingResult result_rot = key_strip.keyframe_insert(
|
||||
slot, {"rotation_quaternion", 0}, {1.0f, 0.25f}, settings);
|
||||
bmain, slot, {"rotation_quaternion", 0}, {1.0f, 0.25f}, settings);
|
||||
EXPECT_EQ(SingleKeyingResult::SUCCESS, result_rot);
|
||||
ASSERT_EQ(2, channels->fcurves().size()) << "Expected a second FCurve to be created.";
|
||||
EXPECT_EQ(2, channels->fcurves()[0]->totvert);
|
||||
|
||||
@@ -149,10 +149,10 @@ TEST_F(AnimationEvaluationTest, evaluate_layer__keyframes)
|
||||
KeyframeStrip &key_strip = strip.as<KeyframeStrip>();
|
||||
|
||||
/* Set some keys. */
|
||||
key_strip.keyframe_insert(*slot, {"location", 0}, {1.0f, 47.1f}, settings);
|
||||
key_strip.keyframe_insert(*slot, {"location", 0}, {5.0f, 47.5f}, settings);
|
||||
key_strip.keyframe_insert(*slot, {"rotation_euler", 1}, {1.0f, 0.0f}, settings);
|
||||
key_strip.keyframe_insert(*slot, {"rotation_euler", 1}, {5.0f, 3.14f}, settings);
|
||||
key_strip.keyframe_insert(bmain, *slot, {"location", 0}, {1.0f, 47.1f}, settings);
|
||||
key_strip.keyframe_insert(bmain, *slot, {"location", 0}, {5.0f, 47.5f}, settings);
|
||||
key_strip.keyframe_insert(bmain, *slot, {"rotation_euler", 1}, {1.0f, 0.0f}, settings);
|
||||
key_strip.keyframe_insert(bmain, *slot, {"rotation_euler", 1}, {5.0f, 3.14f}, settings);
|
||||
|
||||
/* Set the animated properties to some values. These should not be overwritten
|
||||
* by the evaluation itself. */
|
||||
@@ -189,9 +189,9 @@ TEST_F(AnimationEvaluationTest, strip_boundaries__single_strip)
|
||||
|
||||
/* Set some keys. */
|
||||
KeyframeStrip &key_strip = strip.as<KeyframeStrip>();
|
||||
key_strip.keyframe_insert(*slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
key_strip.keyframe_insert(*slot, {"location", 0}, {5.0f, 327.0f}, settings);
|
||||
key_strip.keyframe_insert(*slot, {"location", 0}, {10.0f, 48.0f}, settings);
|
||||
key_strip.keyframe_insert(bmain, *slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
key_strip.keyframe_insert(bmain, *slot, {"location", 0}, {5.0f, 327.0f}, settings);
|
||||
key_strip.keyframe_insert(bmain, *slot, {"location", 0}, {10.0f, 48.0f}, settings);
|
||||
|
||||
/* Evaluate the layer to see how it handles the boundaries + something in between. */
|
||||
EXPECT_TRUE(test_evaluate_layer("location", 0, {1.0f, 47.0f}));
|
||||
@@ -213,15 +213,15 @@ TEST_F(AnimationEvaluationTest, strip_boundaries__nonoverlapping)
|
||||
/* Set some keys. */
|
||||
{
|
||||
KeyframeStrip &key_strip1 = strip1.as<KeyframeStrip>();
|
||||
key_strip1.keyframe_insert(*slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
key_strip1.keyframe_insert(*slot, {"location", 0}, {5.0f, 327.0f}, settings);
|
||||
key_strip1.keyframe_insert(*slot, {"location", 0}, {10.0f, 48.0f}, settings);
|
||||
key_strip1.keyframe_insert(bmain, *slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
key_strip1.keyframe_insert(bmain, *slot, {"location", 0}, {5.0f, 327.0f}, settings);
|
||||
key_strip1.keyframe_insert(bmain, *slot, {"location", 0}, {10.0f, 48.0f}, settings);
|
||||
}
|
||||
{
|
||||
KeyframeStrip &key_strip2 = strip2.as<KeyframeStrip>();
|
||||
key_strip2.keyframe_insert(*slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
key_strip2.keyframe_insert(*slot, {"location", 0}, {5.0f, 327.0f}, settings);
|
||||
key_strip2.keyframe_insert(*slot, {"location", 0}, {10.0f, 48.0f}, settings);
|
||||
key_strip2.keyframe_insert(bmain, *slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
key_strip2.keyframe_insert(bmain, *slot, {"location", 0}, {5.0f, 327.0f}, settings);
|
||||
key_strip2.keyframe_insert(bmain, *slot, {"location", 0}, {10.0f, 48.0f}, settings);
|
||||
}
|
||||
|
||||
/* Check Strip 1. */
|
||||
@@ -253,15 +253,15 @@ TEST_F(AnimationEvaluationTest, strip_boundaries__overlapping_edge)
|
||||
/* Set some keys. */
|
||||
{
|
||||
KeyframeStrip &key_strip1 = strip1.as<KeyframeStrip>();
|
||||
key_strip1.keyframe_insert(*slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
key_strip1.keyframe_insert(*slot, {"location", 0}, {5.0f, 327.0f}, settings);
|
||||
key_strip1.keyframe_insert(*slot, {"location", 0}, {10.0f, 48.0f}, settings);
|
||||
key_strip1.keyframe_insert(bmain, *slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
key_strip1.keyframe_insert(bmain, *slot, {"location", 0}, {5.0f, 327.0f}, settings);
|
||||
key_strip1.keyframe_insert(bmain, *slot, {"location", 0}, {10.0f, 48.0f}, settings);
|
||||
}
|
||||
{
|
||||
KeyframeStrip &key_strip2 = strip2.as<KeyframeStrip>();
|
||||
key_strip2.keyframe_insert(*slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
key_strip2.keyframe_insert(*slot, {"location", 0}, {5.0f, 327.0f}, settings);
|
||||
key_strip2.keyframe_insert(*slot, {"location", 0}, {10.0f, 48.0f}, settings);
|
||||
key_strip2.keyframe_insert(bmain, *slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
key_strip2.keyframe_insert(bmain, *slot, {"location", 0}, {5.0f, 327.0f}, settings);
|
||||
key_strip2.keyframe_insert(bmain, *slot, {"location", 0}, {10.0f, 48.0f}, settings);
|
||||
}
|
||||
|
||||
/* Check Strip 1. */
|
||||
|
||||
@@ -877,7 +877,8 @@ struct KeyInsertData {
|
||||
int array_index;
|
||||
};
|
||||
|
||||
static SingleKeyingResult insert_key_layer(Layer &layer,
|
||||
static SingleKeyingResult insert_key_layer(Main *bmain,
|
||||
Layer &layer,
|
||||
const Slot &slot,
|
||||
const std::string &rna_path,
|
||||
const std::optional<PropertySubType> prop_subtype,
|
||||
@@ -889,14 +890,16 @@ static SingleKeyingResult insert_key_layer(Layer &layer,
|
||||
BLI_assert(layer.strips().size() == 1);
|
||||
|
||||
Strip *strip = layer.strip(0);
|
||||
return strip->as<KeyframeStrip>().keyframe_insert(slot,
|
||||
return strip->as<KeyframeStrip>().keyframe_insert(bmain,
|
||||
slot,
|
||||
{rna_path, key_data.array_index, prop_subtype},
|
||||
key_data.position,
|
||||
key_settings,
|
||||
insert_key_flags);
|
||||
}
|
||||
|
||||
static CombinedKeyingResult insert_key_layered_action(Action &action,
|
||||
static CombinedKeyingResult insert_key_layered_action(Main *bmain,
|
||||
Action &action,
|
||||
PointerRNA *rna_pointer,
|
||||
const blender::Span<RNAPath> rna_paths,
|
||||
const float scene_frame,
|
||||
@@ -955,7 +958,8 @@ static CombinedKeyingResult insert_key_layered_action(Action &action,
|
||||
}
|
||||
|
||||
const KeyInsertData key_data = {{scene_frame, rna_values[property_index]}, property_index};
|
||||
const SingleKeyingResult result = insert_key_layer(*layer,
|
||||
const SingleKeyingResult result = insert_key_layer(bmain,
|
||||
*layer,
|
||||
slot,
|
||||
*rna_path_id_to_prop,
|
||||
prop_subtype,
|
||||
@@ -1002,7 +1006,8 @@ CombinedKeyingResult insert_keyframes(Main *bmain,
|
||||
KeyframeSettings key_settings = get_keyframe_settings(
|
||||
(insert_key_flags & INSERTKEY_NO_USERPREF) == 0);
|
||||
key_settings.keyframe_type = key_type;
|
||||
return insert_key_layered_action(action,
|
||||
return insert_key_layered_action(bmain,
|
||||
action,
|
||||
struct_pointer,
|
||||
rna_paths,
|
||||
scene_frame.value_or(anim_eval_context.eval_time),
|
||||
|
||||
@@ -77,13 +77,15 @@ TEST_F(ActionFilterTest, slots_expanded_or_not)
|
||||
/* Create multiple FCurves for multiple Slots. */
|
||||
const KeyframeSettings settings = get_keyframe_settings(false);
|
||||
ASSERT_EQ(SingleKeyingResult::SUCCESS,
|
||||
key_strip.keyframe_insert(bind_cube, {"location", 0}, {1.0f, 0.25f}, settings));
|
||||
key_strip.keyframe_insert(bmain, bind_cube, {"location", 0}, {1.0f, 0.25f}, settings));
|
||||
ASSERT_EQ(SingleKeyingResult::SUCCESS,
|
||||
key_strip.keyframe_insert(bind_cube, {"location", 1}, {1.0f, 0.25f}, settings));
|
||||
ASSERT_EQ(SingleKeyingResult::SUCCESS,
|
||||
key_strip.keyframe_insert(bind_suzanne, {"location", 0}, {1.0f, 0.25f}, settings));
|
||||
ASSERT_EQ(SingleKeyingResult::SUCCESS,
|
||||
key_strip.keyframe_insert(bind_suzanne, {"location", 1}, {1.0f, 0.25f}, settings));
|
||||
key_strip.keyframe_insert(bmain, bind_cube, {"location", 1}, {1.0f, 0.25f}, settings));
|
||||
ASSERT_EQ(
|
||||
SingleKeyingResult::SUCCESS,
|
||||
key_strip.keyframe_insert(bmain, bind_suzanne, {"location", 0}, {1.0f, 0.25f}, settings));
|
||||
ASSERT_EQ(
|
||||
SingleKeyingResult::SUCCESS,
|
||||
key_strip.keyframe_insert(bmain, bind_suzanne, {"location", 1}, {1.0f, 0.25f}, settings));
|
||||
|
||||
ChannelBag *cube_channel_bag = key_strip.channelbag_for_slot(bind_cube);
|
||||
ASSERT_NE(nullptr, cube_channel_bag);
|
||||
@@ -232,9 +234,9 @@ TEST_F(ActionFilterTest, layered_action_active_fcurves)
|
||||
/* Create multiple FCurves. */
|
||||
const KeyframeSettings settings = get_keyframe_settings(false);
|
||||
ASSERT_EQ(SingleKeyingResult::SUCCESS,
|
||||
key_strip.keyframe_insert(bind_cube, {"location", 0}, {1.0f, 0.25f}, settings));
|
||||
key_strip.keyframe_insert(bmain, bind_cube, {"location", 0}, {1.0f, 0.25f}, settings));
|
||||
ASSERT_EQ(SingleKeyingResult::SUCCESS,
|
||||
key_strip.keyframe_insert(bind_cube, {"location", 1}, {1.0f, 0.25f}, settings));
|
||||
key_strip.keyframe_insert(bmain, bind_cube, {"location", 1}, {1.0f, 0.25f}, settings));
|
||||
|
||||
/* Set one F-Curve as the active one, and the other as inactive. The latter is necessary because
|
||||
* by default the first curve is automatically marked active, but that's too trivial a test case
|
||||
|
||||
@@ -740,6 +740,7 @@ static int slot_unassign_object_exec(bContext *C, wmOperator * /*op*/)
|
||||
Object *object = CTX_data_active_object(C);
|
||||
animrig::unassign_slot(object->id);
|
||||
|
||||
DEG_relations_tag_update(CTX_data_main(C));
|
||||
WM_event_add_notifier(C, NC_ANIMATION | ND_ANIMCHAN, nullptr);
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
@@ -513,7 +513,7 @@ static bool rna_KeyframeActionStrip_key_insert(ID *id,
|
||||
const animrig::KeyframeSettings settings = animrig::get_keyframe_settings(true);
|
||||
|
||||
const animrig::SingleKeyingResult result = key_strip.keyframe_insert(
|
||||
slot, {rna_path, array_index}, {time, value}, settings, INSERTKEY_NOFLAGS);
|
||||
bmain, slot, {rna_path, array_index}, {time, value}, settings, INSERTKEY_NOFLAGS);
|
||||
|
||||
const bool ok = result == animrig::SingleKeyingResult::SUCCESS;
|
||||
if (ok) {
|
||||
@@ -565,6 +565,7 @@ static int rna_iterator_ChannelBag_fcurves_length(PointerRNA *ptr)
|
||||
}
|
||||
|
||||
static FCurve *rna_ChannelBag_fcurve_new(ActionChannelBag *dna_channelbag,
|
||||
Main *bmain,
|
||||
ReportList *reports,
|
||||
const char *data_path,
|
||||
const int index)
|
||||
@@ -576,7 +577,7 @@ static FCurve *rna_ChannelBag_fcurve_new(ActionChannelBag *dna_channelbag,
|
||||
}
|
||||
|
||||
animrig::ChannelBag &self = dna_channelbag->wrap();
|
||||
FCurve *fcurve = self.fcurve_create_unique({data_path, index});
|
||||
FCurve *fcurve = self.fcurve_create_unique(bmain, {data_path, index});
|
||||
if (!fcurve) {
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
@@ -1758,7 +1759,7 @@ static void rna_def_channelbag_fcurves(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
|
||||
func = RNA_def_function(srna, "new", "rna_ChannelBag_fcurve_new");
|
||||
RNA_def_function_ui_description(func, "Add an F-Curve to the channelbag");
|
||||
RNA_def_function_flag(func, FUNC_USE_REPORTS);
|
||||
RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS);
|
||||
parm = RNA_def_string(func, "data_path", nullptr, 0, "Data Path", "F-Curve data path to use");
|
||||
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
|
||||
RNA_def_int(func, "index", 0, 0, INT_MAX, "Index", "Array index", 0, INT_MAX);
|
||||
|
||||
@@ -1714,6 +1714,7 @@ static void rna_def_animdata(BlenderRNA *brna)
|
||||
"Action Slot",
|
||||
"The slot identifies which sub-set of the Action is considered to be for this "
|
||||
"data-block, and its name is used to find the right slot when assigning an Action");
|
||||
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN, "rna_AnimData_dependency_update");
|
||||
|
||||
# endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user