Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/animation/keyframing.c')
-rw-r--r--source/blender/editors/animation/keyframing.c305
1 files changed, 212 insertions, 93 deletions
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 8d079641e9f..5b742ddf272 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -14,6 +14,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_dynstr.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -1109,9 +1110,62 @@ static float *visualkey_get_values(
/* ------------------------- Insert Key API ------------------------- */
+/* Check indices that were intended to be remapped and report any failed remaps. */
+static void get_keyframe_values_create_reports(ReportList *reports,
+ PointerRNA ptr,
+ PropertyRNA *prop,
+ const int index,
+ const int count,
+ const bool force_all,
+ const BLI_bitmap *successful_remaps)
+{
+
+ DynStr *ds_failed_indices = BLI_dynstr_new();
+
+ int total_failed = 0;
+ for (int i = 0; i < count; i++) {
+ const bool cur_index_evaluated = ELEM(index, i, -1) || force_all;
+ if (!cur_index_evaluated) {
+ /* values[i] was never intended to be remapped. */
+ continue;
+ }
+
+ if (BLI_BITMAP_TEST_BOOL(successful_remaps, i)) {
+ /* values[i] succesfully remapped. */
+ continue;
+ }
+
+ total_failed++;
+ /* Report that values[i] were intended to be remapped but failed remapping process. */
+ BLI_dynstr_appendf(ds_failed_indices, "%d, ", i);
+ }
+
+ if (total_failed == 0) {
+ BLI_dynstr_free(ds_failed_indices);
+ return;
+ }
+
+ char *str_failed_indices = BLI_dynstr_get_cstring(ds_failed_indices);
+ BLI_dynstr_free(ds_failed_indices);
+
+ BKE_reportf(reports,
+ RPT_WARNING,
+ "Could not insert %i keyframe(s) due to zero NLA influence, base value, or value "
+ "remapping failed: %s.%s for indices [%s]",
+ total_failed,
+ ptr.owner_id->name,
+ RNA_property_ui_name(prop),
+ str_failed_indices);
+
+ MEM_freeN(str_failed_indices);
+}
+
/**
* Retrieve current property values to keyframe,
* possibly applying NLA correction when necessary.
+ *
+ * \param r_successful_remaps: Enables bits for indices which are both intended to be remapped and
+ * were successfully remapped. Bitmap allocated so it must be freed afterward.
*/
static float *get_keyframe_values(ReportList *reports,
PointerRNA ptr,
@@ -1121,8 +1175,10 @@ static float *get_keyframe_values(ReportList *reports,
eInsertKeyFlags flag,
float *buffer,
int buffer_size,
+ const struct AnimationEvalContext *anim_eval_context,
int *r_count,
- bool *r_force_all)
+ bool *r_force_all,
+ BLI_bitmap **r_successful_remaps)
{
float *values;
@@ -1138,17 +1194,25 @@ static float *get_keyframe_values(ReportList *reports,
values = setting_get_rna_values(&ptr, prop, buffer, buffer_size, r_count);
}
- /* adjust the value for NLA factors */
- if (!BKE_animsys_nla_remap_keyframe_values(
- nla_context, &ptr, prop, values, *r_count, index, r_force_all)) {
- BKE_report(
- reports, RPT_ERROR, "Could not insert keyframe due to zero NLA influence or base value");
+ *r_successful_remaps = BLI_BITMAP_NEW(*r_count, __func__);
- if (values != buffer) {
- MEM_freeN(values);
- }
- return NULL;
- }
+ /* adjust the value for NLA factors */
+ BKE_animsys_nla_remap_keyframe_values(nla_context,
+ &ptr,
+ prop,
+ values,
+ *r_count,
+ index,
+ anim_eval_context,
+ r_force_all,
+ *r_successful_remaps);
+ get_keyframe_values_create_reports(reports,
+ ptr,
+ prop,
+ index,
+ *r_count,
+ r_force_all ? *r_force_all : false,
+ *r_successful_remaps);
return values;
}
@@ -1284,6 +1348,7 @@ bool insert_keyframe_direct(ReportList *reports,
int value_count;
int index = fcu->array_index;
+ BLI_bitmap *successful_remaps = NULL;
float *values = get_keyframe_values(reports,
ptr,
prop,
@@ -1292,13 +1357,10 @@ bool insert_keyframe_direct(ReportList *reports,
flag,
value_buffer,
RNA_MAX_ARRAY_LENGTH,
+ anim_eval_context,
&value_count,
- NULL);
-
- if (values == NULL) {
- /* This happens if NLA rejects this insertion. */
- return false;
- }
+ NULL,
+ &successful_remaps);
if (index >= 0 && index < value_count) {
curval = values[index];
@@ -1308,6 +1370,14 @@ bool insert_keyframe_direct(ReportList *reports,
MEM_freeN(values);
}
+ const bool curval_valid = BLI_BITMAP_TEST_BOOL(successful_remaps, index);
+ MEM_freeN(successful_remaps);
+
+ /* This happens if NLA rejects this insertion. */
+ if (!curval_valid) {
+ return false;
+ }
+
return insert_keyframe_value(reports, &ptr, prop, fcu, anim_eval_context, curval, keytype, flag);
}
@@ -1461,6 +1531,7 @@ int insert_keyframe(Main *bmain,
int value_count;
bool force_all;
+ BLI_bitmap *successful_remaps = NULL;
float *values = get_keyframe_values(reports,
ptr,
prop,
@@ -1469,77 +1540,72 @@ int insert_keyframe(Main *bmain,
flag,
value_buffer,
RNA_MAX_ARRAY_LENGTH,
+ anim_eval_context,
&value_count,
- &force_all);
+ &force_all,
+ &successful_remaps);
- if (values != NULL) {
- /* Key the entire array. */
- if (array_index == -1 || force_all) {
- /* In force mode, if any of the curves succeeds, drop the replace mode and restart. */
- if (force_all && (flag & (INSERTKEY_REPLACE | INSERTKEY_AVAILABLE)) != 0) {
- int exclude = -1;
+ /* Key the entire array. */
+ if (array_index == -1 || force_all) {
+ /* In force mode, if any of the curves succeeds, drop the replace mode and restart. */
+ if (force_all && (flag & (INSERTKEY_REPLACE | INSERTKEY_AVAILABLE)) != 0) {
+ int exclude = -1;
- for (array_index = 0; array_index < value_count; array_index++) {
- if (insert_keyframe_fcurve_value(bmain,
- reports,
- &ptr,
- prop,
- act,
- group,
- rna_path,
- array_index,
- &remapped_context,
- values[array_index],
- keytype,
- flag)) {
- ret++;
- exclude = array_index;
- break;
- }
+ for (array_index = 0; array_index < value_count; array_index++) {
+ if (!BLI_BITMAP_TEST_BOOL(successful_remaps, array_index)) {
+ continue;
}
- if (exclude != -1) {
- flag &= ~(INSERTKEY_REPLACE | INSERTKEY_AVAILABLE);
-
- for (array_index = 0; array_index < value_count; array_index++) {
- if (array_index != exclude) {
- ret += insert_keyframe_fcurve_value(bmain,
- reports,
- &ptr,
- prop,
- act,
- group,
- rna_path,
- array_index,
- &remapped_context,
- values[array_index],
- keytype,
- flag);
- }
- }
+ if (insert_keyframe_fcurve_value(bmain,
+ reports,
+ &ptr,
+ prop,
+ act,
+ group,
+ rna_path,
+ array_index,
+ &remapped_context,
+ values[array_index],
+ keytype,
+ flag)) {
+ ret++;
+ exclude = array_index;
+ break;
}
}
- /* Simply insert all channels. */
- else {
+
+ if (exclude != -1) {
+ flag &= ~(INSERTKEY_REPLACE | INSERTKEY_AVAILABLE);
+
for (array_index = 0; array_index < value_count; array_index++) {
- ret += insert_keyframe_fcurve_value(bmain,
- reports,
- &ptr,
- prop,
- act,
- group,
- rna_path,
- array_index,
- &remapped_context,
- values[array_index],
- keytype,
- flag);
+ if (!BLI_BITMAP_TEST_BOOL(successful_remaps, array_index)) {
+ continue;
+ }
+
+ if (array_index != exclude) {
+ ret += insert_keyframe_fcurve_value(bmain,
+ reports,
+ &ptr,
+ prop,
+ act,
+ group,
+ rna_path,
+ array_index,
+ &remapped_context,
+ values[array_index],
+ keytype,
+ flag);
+ }
}
}
}
- /* Key a single index. */
+ /* Simply insert all channels. */
else {
- if (array_index >= 0 && array_index < value_count) {
+ for (array_index = 0; array_index < value_count; array_index++) {
+ if (!BLI_BITMAP_TEST_BOOL(successful_remaps, array_index)) {
+ continue;
+ }
+
ret += insert_keyframe_fcurve_value(bmain,
reports,
&ptr,
@@ -1554,12 +1620,31 @@ int insert_keyframe(Main *bmain,
flag);
}
}
-
- if (values != value_buffer) {
- MEM_freeN(values);
+ }
+ /* Key a single index. */
+ else {
+ if (array_index >= 0 && array_index < value_count &&
+ BLI_BITMAP_TEST_BOOL(successful_remaps, array_index)) {
+ ret += insert_keyframe_fcurve_value(bmain,
+ reports,
+ &ptr,
+ prop,
+ act,
+ group,
+ rna_path,
+ array_index,
+ &remapped_context,
+ values[array_index],
+ keytype,
+ flag);
}
}
+ if (values != value_buffer) {
+ MEM_freeN(values);
+ }
+
+ MEM_freeN(successful_remaps);
BKE_animsys_free_nla_keyframing_context_cache(&tmp_nla_cache);
if (ret) {
@@ -1979,23 +2064,57 @@ static int insert_key_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UN
{
Scene *scene = CTX_data_scene(C);
- /* if prompting or no active Keying Set, show the menu */
- if ((scene->active_keyingset == 0) || RNA_boolean_get(op->ptr, "always_prompt")) {
- uiPopupMenu *pup;
- uiLayout *layout;
-
- /* call the menu, which will call this operator again, hence the canceled */
- pup = UI_popup_menu_begin(C, WM_operatortype_name(op->type, op->ptr), ICON_NONE);
- layout = UI_popup_menu_layout(pup);
- uiItemsEnumO(layout, "ANIM_OT_keyframe_insert_menu", "type");
- UI_popup_menu_end(C, pup);
+ /* When there is an active keying set and no request to prompt, keyframe immediately. */
+ if ((scene->active_keyingset != 0) && !RNA_boolean_get(op->ptr, "always_prompt")) {
+ /* Just call the exec() on the active keying-set. */
+ RNA_enum_set(op->ptr, "type", 0);
+ return op->type->exec(C, op);
+ }
+
+ /* Show a menu listing all keying-sets, the enum is expanded here to make use of the
+ * operator that accesses the keying-set by name. This is important for the ability
+ * to assign shortcuts to arbitrarily named keying sets. See T89560.
+ * These menu items perform the key-frame insertion (not this operator)
+ * hence the #OPERATOR_INTERFACE return. */
+ uiPopupMenu *pup = UI_popup_menu_begin(C, WM_operatortype_name(op->type, op->ptr), ICON_NONE);
+ uiLayout *layout = UI_popup_menu_layout(pup);
+
+ /* Even though `ANIM_OT_keyframe_insert_menu` can show a menu in one line,
+ * prefer `ANIM_OT_keyframe_insert_by_name` so users can bind keys to specific
+ * keying sets by name in the key-map instead of the index which isn't stable. */
+ PropertyRNA *prop = RNA_struct_find_property(op->ptr, "type");
+ const EnumPropertyItem *item_array = NULL;
+ int totitem;
+ bool free;
+
+ RNA_property_enum_items_gettexted(C, op->ptr, prop, &item_array, &totitem, &free);
+
+ for (int i = 0; i < totitem; i++) {
+ const EnumPropertyItem *item = &item_array[i];
+ if (item->identifier[0] != '\0') {
+ uiItemStringO(layout,
+ item->name,
+ item->icon,
+ "ANIM_OT_keyframe_insert_by_name",
+ "type",
+ item->identifier);
+ }
+ else {
+ /* This enum shouldn't contain headings, assert there are none.
+ * NOTE: If in the future the enum includes them, additional layout code can be
+ * added to show them - although that doesn't seem likely. */
+ BLI_assert(item->name == NULL);
+ uiItemS(layout);
+ }
+ }
- return OPERATOR_INTERFACE;
+ if (free) {
+ MEM_freeN((void *)item_array);
}
- /* just call the exec() on the active keyingset */
- RNA_enum_set(op->ptr, "type", 0);
- return op->type->exec(C, op);
+ UI_popup_menu_end(C, pup);
+
+ return OPERATOR_INTERFACE;
}
void ANIM_OT_keyframe_insert_menu(wmOperatorType *ot)