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:
authorJoshua Leung <aligorith@gmail.com>2015-12-14 18:03:25 +0300
committerJoshua Leung <aligorith@gmail.com>2015-12-14 18:03:59 +0300
commit1fbd74296df79fff2b4fd3234ea20b0ade51b0f9 (patch)
treeda6c648e96d9ac3b87051d69ef2565ad52e64465 /source/blender/editors/space_graph
parent236d094865325413895853609f6af85f01fef70f (diff)
Graph Editor: "Add at Cursor" options for Insert Key operator in Graph Editor
* Added the ability to add a keyframe at the current cursor location in the Graph Editor. This is useful for precisely defining the shape of driver F-Curves. * Fixed a bug where the wrong cursor-x time was being used in Drivers mode (i.e. it was still using time, and not just any time-value, but the NLA-mapped time!)
Diffstat (limited to 'source/blender/editors/space_graph')
-rw-r--r--source/blender/editors/space_graph/graph_edit.c128
1 files changed, 98 insertions, 30 deletions
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 5011b03955b..6042100a984 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -483,57 +483,125 @@ void GRAPH_OT_ghost_curves_clear(wmOperatorType *ot)
/* ******************** Insert Keyframes Operator ************************* */
-/* defines for insert keyframes tool */
+/* Mode defines for insert keyframes tool */
+typedef enum eGraphKeys_InsertKey_Types {
+ GRAPHKEYS_INSERTKEY_ALL = (1 << 0),
+ GRAPHKEYS_INSERTKEY_SEL = (1 << 1),
+ GRAPHKEYS_INSERTKEY_CURSOR = (1 << 2),
+ GRAPHKEYS_INSERTKEY_ACTIVE = (1 << 3),
+} eGraphKeys_InsertKey_Types;
+
+/* RNA mode types for insert keyframes tool */
static EnumPropertyItem prop_graphkeys_insertkey_types[] = {
- {1, "ALL", 0, "All Channels", ""},
- {2, "SEL", 0, "Only Selected Channels", ""},
+ {GRAPHKEYS_INSERTKEY_ALL, "ALL", 0, "All Channels",
+ "Insert a keyframe on all visible and editable F-Curves using each curve's current value"},
+ {GRAPHKEYS_INSERTKEY_SEL, "SEL", 0, "Only Selected Channels",
+ "Insert a keyframe on selected F-Curves using each curve's current value"},
+ {0, "", 0, "", ""},
+ {GRAPHKEYS_INSERTKEY_ACTIVE | GRAPHKEYS_INSERTKEY_CURSOR, "CURSOR_ACTIVE", 0,
+ "Active Channels At Cursor", "Insert a keyframe for the active F-Curve at the cursor point"},
+ {GRAPHKEYS_INSERTKEY_SEL | GRAPHKEYS_INSERTKEY_CURSOR, "CURSOR_SEL", 0,
+ "Selected Channels At Cursor", "Insert a keyframe for selected F-Curves at the cursor point"},
{0, NULL, 0, NULL, NULL}
};
/* this function is responsible for snapping keyframes to frame-times */
-static void insert_graph_keys(bAnimContext *ac, short mode)
+static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
+ size_t num_items;
ReportList *reports = ac->reports;
+ SpaceIpo *sipo = (SpaceIpo *)ac->sl;
Scene *scene = ac->scene;
short flag = 0;
/* filter data */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_CURVE_VISIBLE | ANIMFILTER_FOREDIT | ANIMFILTER_NODUPLIS);
- if (mode == 2) filter |= ANIMFILTER_SEL;
-
- ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ if (mode & GRAPHKEYS_INSERTKEY_SEL)
+ filter |= ANIMFILTER_SEL;
+ else if (mode & GRAPHKEYS_INSERTKEY_ACTIVE)
+ filter |= ANIMFILTER_ACTIVE;
+
+ num_items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ if (num_items == 0) {
+ if (mode & GRAPHKEYS_INSERTKEY_ACTIVE)
+ BKE_report(reports, RPT_ERROR, "No active F-Curve to add a keyframe to. Select an editable F-Curve first");
+ else if (mode & GRAPHKEYS_INSERTKEY_SEL)
+ BKE_report(reports, RPT_ERROR, "No selected F-Curves to add keyframes to");
+ else
+ BKE_report(reports, RPT_ERROR, "No channels to add keyframes to");
+
+ return;
+ }
/* init keyframing flag */
flag = ANIM_get_keyframing_flags(scene, 1);
/* insert keyframes */
- for (ale = anim_data.first; ale; ale = ale->next) {
- AnimData *adt = ANIM_nla_mapping_get(ac, ale);
- FCurve *fcu = (FCurve *)ale->key_data;
- float cfra;
-
- /* adjust current frame for NLA-mapping */
- if (adt)
- cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
- else
- cfra = (float)CFRA;
+ if (mode & GRAPHKEYS_INSERTKEY_CURSOR) {
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
- /* read value from property the F-Curve represents, or from the curve only?
- * - ale->id != NULL: Typically, this means that we have enough info to try resolving the path
- * - ale->owner != NULL: If this is set, then the path may not be resolvable from the ID alone,
- * so it's easier for now to just read the F-Curve directly.
- * (TODO: add the full-blown PointerRNA relative parsing case here...)
- */
- if (ale->id && !ale->owner)
- insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
- else
- insert_vert_fcurve(fcu, cfra, fcu->curval, 0);
-
- ale->update |= ANIM_UPDATE_DEFAULT;
+ short mapping_flag = ANIM_get_normalization_flags(ac);
+ float offset;
+ float unit_scale = ANIM_unit_mapping_get_factor(ac->scene, ale->id, ale->key_data, mapping_flag, &offset);
+
+ float x, y;
+
+
+ /* perform time remapping for x-coordinate (if necessary) */
+ if ((sipo) && (sipo->mode == SIPO_MODE_DRIVERS))
+ x = sipo->cursorTime;
+ else if (adt)
+ x = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ x = (float)CFRA;
+
+ /* normalise units of cursor's value */
+ if (sipo)
+ y = (sipo->cursorVal / unit_scale) - offset;
+ else
+ y = 0.0f;
+
+ /* insert keyframe directly into the F-Curve */
+ insert_vert_fcurve(fcu, x, y, 0);
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
+ }
+ else {
+ for (ale = anim_data.first; ale; ale = ale->next) {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+ FCurve *fcu = (FCurve *)ale->key_data;
+ float cfra;
+
+ /* adjust current frame for NLA-mapping */
+ if ((sipo) && (sipo->mode == SIPO_MODE_DRIVERS))
+ cfra = sipo->cursorTime;
+ else if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+ else
+ cfra = (float)CFRA;
+
+ /* read value from property the F-Curve represents, or from the curve only?
+ * - ale->id != NULL: Typically, this means that we have enough info to try resolving the path
+ * - ale->owner != NULL: If this is set, then the path may not be resolvable from the ID alone,
+ * so it's easier for now to just read the F-Curve directly.
+ * (TODO: add the full-blown PointerRNA relative parsing case here...)
+ * - fcu->driver != NULL: If this is set, then it's a driver. If we don't check for this, we'd end
+ * up adding the keyframes on a new F-Curve in the action data instead.
+ */
+ if (ale->id && !ale->owner && !fcu->driver)
+ insert_keyframe(reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)), fcu->rna_path, fcu->array_index, cfra, flag);
+ else
+ insert_vert_fcurve(fcu, cfra, fcu->curval, 0);
+
+ ale->update |= ANIM_UPDATE_DEFAULT;
+ }
}
ANIM_animdata_update(ac, &anim_data);
@@ -545,7 +613,7 @@ static void insert_graph_keys(bAnimContext *ac, short mode)
static int graphkeys_insertkey_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
- short mode;
+ eGraphKeys_InsertKey_Types mode;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)