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:
authorBastien Montagne <montagne29@wanadoo.fr>2016-07-12 01:01:38 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2016-07-12 01:07:44 +0300
commitcfbd605567f48229a923df382baf6db98fbafc61 (patch)
treed4218c49672047d6c3b37517034660b3b5dcd966 /source/blender/editors/animation
parent71a57a37b2eebbed53b5335019287b4df9c30519 (diff)
parent7212ebd09f9720883581221be923ae5e97ff5d76 (diff)
Merge branch 'master' into blender2.8
Conflicts: intern/cycles/blender/addon/ui.py source/blender/blenkernel/BKE_particle.h source/blender/blenkernel/intern/dynamicpaint.c source/blender/blenkernel/intern/library.c source/blender/blenkernel/intern/object.c source/blender/blenkernel/intern/particle.c source/blender/blenkernel/intern/particle_distribute.c source/blender/blenkernel/intern/texture.c source/blender/editors/object/object_add.c source/blender/editors/object/object_relations.c source/blender/editors/physics/particle_edit.c source/blender/editors/physics/particle_object.c source/blender/editors/transform/transform_snap_object.c
Diffstat (limited to 'source/blender/editors/animation')
-rw-r--r--source/blender/editors/animation/anim_channels_edit.c12
-rw-r--r--source/blender/editors/animation/anim_filter.c198
-rw-r--r--source/blender/editors/animation/keyframes_draw.c171
-rw-r--r--source/blender/editors/animation/keyframes_edit.c10
4 files changed, 290 insertions, 101 deletions
diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c
index b690695ae69..edc258003fb 100644
--- a/source/blender/editors/animation/anim_channels_edit.c
+++ b/source/blender/editors/animation/anim_channels_edit.c
@@ -2352,7 +2352,7 @@ static void borderselect_anim_channels(bAnimContext *ac, rcti *rect, short selec
}
else {
ymin = 0.0f;
- ymax = (float)(-ACHANNEL_HEIGHT);
+ ymax = (float)(-ACHANNEL_HEIGHT(ac));
}
/* convert border-region to view coordinates */
@@ -2368,7 +2368,7 @@ static void borderselect_anim_channels(bAnimContext *ac, rcti *rect, short selec
if (ac->datatype == ANIMCONT_NLA)
ymin = ymax - NLACHANNEL_STEP(snla);
else
- ymin = ymax - ACHANNEL_STEP;
+ ymin = ymax - ACHANNEL_STEP(ac);
/* if channel is within border-select region, alter it */
if (!((ymax < rectf.ymin) || (ymin > rectf.ymax))) {
@@ -2569,7 +2569,7 @@ static int animchannels_channel_get(bAnimContext *ac, const int mval[2])
UI_view2d_listview_view_to_cell(v2d, NLACHANNEL_NAMEWIDTH, NLACHANNEL_STEP(snla), 0, (float)NLACHANNEL_HEIGHT_HALF(snla), x, y, NULL, &channel_index);
}
else {
- UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
+ UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP(ac), 0, (float)ACHANNEL_HEIGHT_HALF(ac), x, y, NULL, &channel_index);
}
return channel_index;
@@ -2701,6 +2701,10 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index,
if ((adt) && (adt->flag & ADT_UI_SELECTED))
adt->flag |= ADT_UI_ACTIVE;
+ /* ensure we exit editmode on whatever object was active before to avoid getting stuck there - T48747 */
+ if (ob != sce->obedit)
+ ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO);
+
notifierFlags |= (ND_ANIMCHAN | NA_SELECTED);
break;
}
@@ -2983,7 +2987,7 @@ static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmE
* ACHANNEL_HEIGHT_HALF.
*/
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y);
- UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP, 0, (float)ACHANNEL_HEIGHT_HALF, x, y, NULL, &channel_index);
+ UI_view2d_listview_view_to_cell(v2d, ACHANNEL_NAMEWIDTH, ACHANNEL_STEP(&ac), 0, (float)ACHANNEL_HEIGHT_HALF(&ac), x, y, NULL, &channel_index);
/* handle mouse-click in the relevant channel then */
notifierFlags = mouse_anim_channels(C, &ac, channel_index, selectmode);
diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c
index 554abc6e552..26f2a3ebf9c 100644
--- a/source/blender/editors/animation/anim_filter.c
+++ b/source/blender/editors/animation/anim_filter.c
@@ -70,6 +70,7 @@
#include "DNA_world_types.h"
#include "DNA_gpencil_types.h"
#include "DNA_object_types.h"
+#include "DNA_userdef_types.h"
#include "MEM_guardedalloc.h"
@@ -96,9 +97,30 @@
#include "ED_anim_api.h"
#include "ED_markers.h"
+#include "UI_resources.h" /* for TH_KEYFRAME_SCALE lookup */
+
/* ************************************************************ */
/* Blender Context <-> Animation Context mapping */
+/* ----------- Private Stuff - General -------------------- */
+
+/* Get vertical scaling factor (i.e. typically used for keyframe size) */
+static void animedit_get_yscale_factor(bAnimContext *ac)
+{
+ bTheme *btheme = UI_GetTheme();
+
+ /* grab scale factor directly from action editor setting
+ * NOTE: This theme setting doesn't have an ID, as it cannot be accessed normally
+ * since it is a float, and the theem settings methods can only handle chars.
+ */
+ ac->yscale_fac = btheme->tact.keyframe_scale_fac;
+
+ /* clamp to avoid problems with uninitialised values... */
+ if (ac->yscale_fac < 0.1f)
+ ac->yscale_fac = 1.0f;
+ //printf("yscale_fac = %f\n", ac->yscale_fac);
+}
+
/* ----------- Private Stuff - Action Editor ------------- */
/* Get shapekey data being edited (for Action Editor -> ShapeKey mode) */
@@ -351,6 +373,9 @@ bool ANIM_animdata_get_context(const bContext *C, bAnimContext *ac)
ac->spacetype = (sa) ? sa->spacetype : 0;
ac->regiontype = (ar) ? ar->regiontype : 0;
+ /* initialise default y-scale factor */
+ animedit_get_yscale_factor(ac);
+
/* get data context info */
// XXX: if the below fails, try to grab this info from context instead... (to allow for scripting)
return ANIM_animdata_context_getdata(ac);
@@ -1241,7 +1266,7 @@ static size_t animfilter_action(bAnimContext *ac, ListBase *anim_data, bDopeShee
/* don't include anything from this action if it is linked in from another file,
* and we're getting stuff for editing...
*/
- if ((filter_mode & ANIMFILTER_FOREDIT) && (act->id.lib))
+ if ((filter_mode & ANIMFILTER_FOREDIT) && ID_IS_LINKED_DATABLOCK(act))
return 0;
/* do groups */
@@ -2633,11 +2658,97 @@ static size_t animdata_filter_dopesheet_scene(bAnimContext *ac, ListBase *anim_d
return items;
}
+
+/* Helper for animdata_filter_dopesheet() - For checking if an object should be included or not */
+static bool animdata_filter_base_is_ok(bDopeSheet *ads, Scene *scene, Base *base, int filter_mode)
+{
+ Object *ob = base->object;
+
+ if (base->object == NULL)
+ return false;
+
+ /* firstly, check if object can be included, by the following factors:
+ * - if only visible, must check for layer and also viewport visibility
+ * --> while tools may demand only visible, user setting takes priority
+ * as user option controls whether sets of channels get included while
+ * tool-flag takes into account collapsed/open channels too
+ * - if only selected, must check if object is selected
+ * - there must be animation data to edit (this is done recursively as we
+ * try to add the channels)
+ */
+ if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
+ /* layer visibility - we check both object and base, since these may not be in sync yet */
+ if ((scene->lay & (ob->lay | base->lay)) == 0)
+ return false;
+
+ /* outliner restrict-flag */
+ if (ob->restrictflag & OB_RESTRICT_VIEW)
+ return false;
+ }
+
+ /* if only F-Curves with visible flags set can be shown, check that
+ * datablock hasn't been set to invisible
+ */
+ if (filter_mode & ANIMFILTER_CURVE_VISIBLE) {
+ if ((ob->adt) && (ob->adt->flag & ADT_CURVES_NOT_VISIBLE))
+ return false;
+ }
+
+ /* check selection and object type filters */
+ if ((ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/)) {
+ /* only selected should be shown */
+ return false;
+ }
+
+ /* check if object belongs to the filtering group if option to filter
+ * objects by the grouped status is on
+ * - used to ease the process of doing multiple-character choreographies
+ */
+ if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) {
+ if (BKE_group_object_exists(ads->filter_grp, ob) == 0)
+ return false;
+ }
+
+ /* no reason to exclude this object... */
+ return true;
+}
+
+/* Helper for animdata_filter_ds_sorted_bases() - Comparison callback for two Base pointers... */
+static int ds_base_sorting_cmp(const void *base1_ptr, const void *base2_ptr)
+{
+ const Base *b1 = *((const Base **)base1_ptr);
+ const Base *b2 = *((const Base **)base2_ptr);
+
+ return strcmp(b1->object->id.name + 2, b2->object->id.name + 2);
+}
+
+/* Get a sorted list of all the bases - for inclusion in dopesheet (when drawing channels) */
+static Base **animdata_filter_ds_sorted_bases(bDopeSheet *ads, Scene *scene, int filter_mode, size_t *r_usable_bases)
+{
+ /* Create an array with space for all the bases, but only containing the usable ones */
+ size_t tot_bases = BLI_listbase_count(&scene->base);
+ size_t num_bases = 0;
+
+ Base **sorted_bases = MEM_mallocN(sizeof(Base *) * tot_bases, "Dopesheet Usable Sorted Bases");
+ for (Base *base = scene->base.first; base; base = base->next) {
+ if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) {
+ sorted_bases[num_bases++] = base;
+ }
+ }
+
+ /* Sort this list of pointers (based on the names) */
+ qsort(sorted_bases, num_bases, sizeof(Base *), ds_base_sorting_cmp);
+
+ /* Return list of sorted bases */
+ *r_usable_bases = num_bases;
+ return sorted_bases;
+}
+
+
// TODO: implement pinning... (if and when pinning is done, what we need to do is to provide freeing mechanisms - to protect against data that was deleted)
static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, int filter_mode)
{
- Scene *sce = (Scene *)ads->source;
- Base *base;
+ Scene *scene = (Scene *)ads->source;
size_t items = 0;
/* check that we do indeed have a scene */
@@ -2657,56 +2768,45 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b
}
/* scene-linked animation - e.g. world, compositing nodes, scene anim (including sequencer currently) */
- items += animdata_filter_dopesheet_scene(ac, anim_data, ads, sce, filter_mode);
-
- /* loop over all bases (i.e.objects) in the scene */
- for (base = sce->base.first; base; base = base->next) {
- /* check if there's an object (all the relevant checks are done in the ob-function) */
- if (base->object) {
- Object *ob = base->object;
-
- /* firstly, check if object can be included, by the following factors:
- * - if only visible, must check for layer and also viewport visibility
- * --> while tools may demand only visible, user setting takes priority
- * as user option controls whether sets of channels get included while
- * tool-flag takes into account collapsed/open channels too
- * - if only selected, must check if object is selected
- * - there must be animation data to edit (this is done recursively as we
- * try to add the channels)
- */
- if ((filter_mode & ANIMFILTER_DATA_VISIBLE) && !(ads->filterflag & ADS_FILTER_INCL_HIDDEN)) {
- /* layer visibility - we check both object and base, since these may not be in sync yet */
- if ((sce->lay & (ob->lay | base->lay)) == 0) continue;
-
- /* outliner restrict-flag */
- if (ob->restrictflag & OB_RESTRICT_VIEW) continue;
- }
-
- /* if only F-Curves with visible flags set can be shown, check that
- * datablock hasn't been set to invisible
- */
- if (filter_mode & ANIMFILTER_CURVE_VISIBLE) {
- if ((ob->adt) && (ob->adt->flag & ADT_CURVES_NOT_VISIBLE))
- continue;
+ items += animdata_filter_dopesheet_scene(ac, anim_data, ads, scene, filter_mode);
+
+ /* If filtering for channel drawing, we want the objects in alphabetical order,
+ * to make it easier to predict where items are in the hierarchy
+ * - This order only really matters if we need to show all channels in the list (e.g. for drawing)
+ * (XXX: What about lingering "active" flags? The order may now become unpredictable)
+ * - Don't do this if this behaviour has been turned off (i.e. due to it being too slow)
+ * - Don't do this if there's just a single object
+ */
+ if ((filter_mode & ANIMFILTER_LIST_CHANNELS) && !(ads->flag & ADS_FLAG_NO_DB_SORT) &&
+ (scene->base.first != scene->base.last))
+ {
+ /* Filter list of bases (i.e. objects), sort them, then add their contents normally... */
+ // TODO: Cache the old sorted order - if the set of bases hasn't changed, don't re-sort...
+ Base **sorted_bases;
+ size_t num_bases;
+
+ sorted_bases = animdata_filter_ds_sorted_bases(ads, scene, filter_mode, &num_bases);
+ if (sorted_bases) {
+ /* Add the necessary channels for these bases... */
+ for (size_t i = 0; i < num_bases; i++) {
+ items += animdata_filter_dopesheet_ob(ac, anim_data, ads, sorted_bases[i], filter_mode);
}
- /* check selection and object type filters */
- if ( (ads->filterflag & ADS_FILTER_ONLYSEL) && !((base->flag & SELECT) /*|| (base == sce->basact)*/) ) {
- /* only selected should be shown */
- continue;
- }
+ // TODO: store something to validate whether any changes are needed?
- /* check if object belongs to the filtering group if option to filter
- * objects by the grouped status is on
- * - used to ease the process of doing multiple-character choreographies
- */
- if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) {
- if (BKE_group_object_exists(ads->filter_grp, ob) == 0)
- continue;
+ /* free temporary data */
+ MEM_freeN(sorted_bases);
+ }
+ }
+ else {
+ /* Filter and add contents of each base (i.e. object) without them sorting first
+ * NOTE: This saves performance in cases where order doesn't matter
+ */
+ for (Base *base = scene->base.first; base; base = base->next) {
+ if (animdata_filter_base_is_ok(ads, scene, base, filter_mode)) {
+ /* since we're still here, this object should be usable */
+ items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode);
}
-
- /* since we're still here, this object should be usable */
- items += animdata_filter_dopesheet_ob(ac, anim_data, ads, base, filter_mode);
}
}
diff --git a/source/blender/editors/animation/keyframes_draw.c b/source/blender/editors/animation/keyframes_draw.c
index 6f1883cff55..6e776953356 100644
--- a/source/blender/editors/animation/keyframes_draw.c
+++ b/source/blender/editors/animation/keyframes_draw.c
@@ -40,6 +40,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_dlrbTree.h"
+#include "BLI_math.h"
#include "BLI_utildefines.h"
#include "DNA_anim_types.h"
@@ -282,6 +283,9 @@ static ActKeyBlock *bezts_to_new_actkeyblock(BezTriple *prev, BezTriple *beztn)
ab->sel = (BEZT_ISSEL_ANY(prev) || BEZT_ISSEL_ANY(beztn)) ? SELECT : 0;
ab->modified = 1;
+ if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD)
+ ab->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD;
+
return ab;
}
@@ -305,16 +309,28 @@ static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, BezTriple *first_bezt
}
- /* check if block needed - same value(s)?
- * -> firstly, handles must have same central value as each other
- * -> secondly, handles which control that section of the curve must be constant
- */
+ /* check if block needed */
if (prev == NULL) return;
- if (IS_EQF(beztn->vec[1][1], prev->vec[1][1]) == 0) return;
-
- if (IS_EQF(beztn->vec[1][1], beztn->vec[0][1]) == 0) return;
- if (IS_EQF(prev->vec[1][1], prev->vec[2][1]) == 0) return;
+ if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD) {
+ /* Animator tagged a "moving hold"
+ * - Previous key must also be tagged as a moving hold, otherwise
+ * we're just dealing with the first of a pair, and we don't
+ * want to be creating any phantom holds...
+ */
+ if (BEZKEYTYPE(prev) != BEZT_KEYTYPE_MOVEHOLD)
+ return;
+ }
+ else {
+ /* Check for same values...
+ * - Handles must have same central value as each other
+ * - Handles which control that section of the curve must be constant
+ */
+ if (IS_EQF(beztn->vec[1][1], prev->vec[1][1]) == 0) return;
+
+ if (IS_EQF(beztn->vec[1][1], beztn->vec[0][1]) == 0) return;
+ if (IS_EQF(prev->vec[1][1], prev->vec[2][1]) == 0) return;
+ }
/* if there are no blocks already, just add as root */
if (blocks->root == NULL) {
@@ -340,7 +356,13 @@ static void add_bezt_to_keyblocks_list(DLRBT_Tree *blocks, BezTriple *first_bezt
*/
if (IS_EQT(ab->start, prev->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
/* set selection status and 'touched' status */
- if (BEZT_ISSEL_ANY(beztn)) ab->sel = SELECT;
+ if (BEZT_ISSEL_ANY(beztn))
+ ab->sel = SELECT;
+
+ /* XXX: only when the first one was a moving hold? */
+ if (BEZKEYTYPE(beztn) == BEZT_KEYTYPE_MOVEHOLD)
+ ab->flag |= ACTKEYBLOCK_FLAG_MOVING_HOLD;
+
ab->modified++;
/* done... no need to insert */
@@ -485,7 +507,27 @@ void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel,
/* tweak size of keyframe shape according to type of keyframe
* - 'proper' keyframes have key_type = 0, so get drawn at full size
*/
- hsize -= 0.5f * key_type;
+ switch (key_type) {
+ case BEZT_KEYTYPE_KEYFRAME: /* must be full size */
+ break;
+
+ case BEZT_KEYTYPE_BREAKDOWN: /* slightly smaller than normal keyframe */
+ hsize *= 0.85f;
+ break;
+
+ case BEZT_KEYTYPE_MOVEHOLD: /* slightly smaller than normal keyframes (but by less than for breakdowns) */
+ //hsize *= 0.72f;
+ hsize *= 0.95f;
+ break;
+
+ case BEZT_KEYTYPE_EXTREME: /* slightly larger */
+ hsize *= 1.2f;
+ break;
+
+ default:
+ hsize -= 0.5f * key_type;
+ break;
+ }
/* adjust view transform before starting */
glTranslatef(x, y, 0.0f);
@@ -518,6 +560,15 @@ void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel,
else UI_GetThemeColor4fv(TH_KEYTYPE_JITTER, inner_col);
break;
}
+ case BEZT_KEYTYPE_MOVEHOLD: /* similar to traditional keyframes, but different... */
+ {
+ /* XXX: Should these get their own theme options instead? */
+ if (sel) UI_GetThemeColorShade4fv(TH_STRIP_SELECT, 35, inner_col);
+ else UI_GetThemeColorShade4fv(TH_STRIP, 50, inner_col);
+
+ inner_col[3] = 1.0f; /* full opacity, to avoid problems with visual glitches */
+ break;
+ }
case BEZT_KEYTYPE_KEYFRAME: /* traditional yellowish frames (default theme) */
default:
{
@@ -557,13 +608,16 @@ void draw_keyframe_shape(float x, float y, float xscale, float hsize, short sel,
glTranslatef(-x, -y, 0.0f);
}
-static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos, short channelLocked)
+static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, float ypos, float yscale_fac, bool channelLocked)
{
ActKeyColumn *ak;
ActKeyBlock *ab;
float alpha;
float xscale;
- float iconsize = U.widget_unit / 4.0f;
+
+ const float iconsize = (U.widget_unit / 4.0f) * yscale_fac;
+ const float mhsize = iconsize * 0.7f;
+
glEnable(GL_BLEND);
/* get View2D scaling factor */
@@ -576,6 +630,7 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
/* draw keyblocks */
if (blocks) {
float sel_color[4], unsel_color[4];
+ float sel_mhcol[4], unsel_mhcol[4];
/* cache colours first */
UI_GetThemeColor4fv(TH_STRIP_SELECT, sel_color);
@@ -584,16 +639,32 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
sel_color[3] *= alpha;
unsel_color[3] *= alpha;
+ copy_v4_v4(sel_mhcol, sel_color);
+ sel_mhcol[3] *= 0.8f;
+ copy_v4_v4(unsel_mhcol, unsel_color);
+ unsel_mhcol[3] *= 0.8f;
+
/* NOTE: the tradeoff for changing colors between each draw is dwarfed by the cost of checking validity */
for (ab = blocks->first; ab; ab = ab->next) {
if (actkeyblock_is_valid(ab, keys)) {
- /* draw block */
- if (ab->sel)
- glColor4fv(sel_color);
- else
- glColor4fv(unsel_color);
-
- glRectf(ab->start, ypos - iconsize, ab->end, ypos + iconsize);
+ if (ab->flag & ACTKEYBLOCK_FLAG_MOVING_HOLD) {
+ /* draw "moving hold" long-keyframe block - slightly smaller */
+ if (ab->sel)
+ glColor4fv(sel_mhcol);
+ else
+ glColor4fv(unsel_mhcol);
+
+ glRectf(ab->start, ypos - mhsize, ab->end, ypos + mhsize);
+ }
+ else {
+ /* draw standard long-keyframe block */
+ if (ab->sel)
+ glColor4fv(sel_color);
+ else
+ glColor4fv(unsel_color);
+
+ glRectf(ab->start, ypos - iconsize, ab->end, ypos + iconsize);
+ }
}
}
}
@@ -619,7 +690,7 @@ static void draw_keylist(View2D *v2d, DLRBT_Tree *keys, DLRBT_Tree *blocks, floa
/* *************************** Channel Drawing Funcs *************************** */
-void draw_summary_channel(View2D *v2d, bAnimContext *ac, float ypos)
+void draw_summary_channel(View2D *v2d, bAnimContext *ac, float ypos, float yscale_fac)
{
DLRBT_Tree keys, blocks;
@@ -631,13 +702,13 @@ void draw_summary_channel(View2D *v2d, bAnimContext *ac, float ypos)
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
- draw_keylist(v2d, &keys, &blocks, ypos, 0);
+ draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
}
-void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos)
+void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos, float yscale_fac)
{
DLRBT_Tree keys, blocks;
@@ -649,13 +720,13 @@ void draw_scene_channel(View2D *v2d, bDopeSheet *ads, Scene *sce, float ypos)
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
- draw_keylist(v2d, &keys, &blocks, ypos, 0);
+ draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
}
-void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos)
+void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos, float yscale_fac)
{
DLRBT_Tree keys, blocks;
@@ -667,19 +738,19 @@ void draw_object_channel(View2D *v2d, bDopeSheet *ads, Object *ob, float ypos)
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
- draw_keylist(v2d, &keys, &blocks, ypos, 0);
+ draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, false);
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
}
-void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos)
+void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos, float yscale_fac)
{
DLRBT_Tree keys, blocks;
- short locked = (fcu->flag & FCURVE_PROTECTED) ||
- ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
- ((adt && adt->action) && (adt->action->id.lib));
+ bool locked = (fcu->flag & FCURVE_PROTECTED) ||
+ ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED)) ||
+ ((adt && adt->action) && ID_IS_LINKED_DATABLOCK(adt->action));
BLI_dlrbTree_init(&keys);
BLI_dlrbTree_init(&blocks);
@@ -689,18 +760,18 @@ void draw_fcurve_channel(View2D *v2d, AnimData *adt, FCurve *fcu, float ypos)
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
- draw_keylist(v2d, &keys, &blocks, ypos, locked);
+ draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
}
-void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos)
+void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float ypos, float yscale_fac)
{
DLRBT_Tree keys, blocks;
- short locked = (agrp->flag & AGRP_PROTECTED) ||
- ((adt && adt->action) && (adt->action->id.lib));
+ bool locked = (agrp->flag & AGRP_PROTECTED) ||
+ ((adt && adt->action) && ID_IS_LINKED_DATABLOCK(adt->action));
BLI_dlrbTree_init(&keys);
BLI_dlrbTree_init(&blocks);
@@ -710,17 +781,17 @@ void draw_agroup_channel(View2D *v2d, AnimData *adt, bActionGroup *agrp, float y
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
- draw_keylist(v2d, &keys, &blocks, ypos, locked);
+ draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
}
-void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos)
+void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos, float yscale_fac)
{
DLRBT_Tree keys, blocks;
- short locked = (act && act->id.lib != NULL);
+ bool locked = (act && ID_IS_LINKED_DATABLOCK(act));
BLI_dlrbTree_init(&keys);
BLI_dlrbTree_init(&blocks);
@@ -730,13 +801,13 @@ void draw_action_channel(View2D *v2d, AnimData *adt, bAction *act, float ypos)
BLI_dlrbTree_linkedlist_sync(&keys);
BLI_dlrbTree_linkedlist_sync(&blocks);
- draw_keylist(v2d, &keys, &blocks, ypos, locked);
+ draw_keylist(v2d, &keys, &blocks, ypos, yscale_fac, locked);
BLI_dlrbTree_free(&keys);
BLI_dlrbTree_free(&blocks);
}
-void draw_gpencil_channel(View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos)
+void draw_gpencil_channel(View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos, float yscale_fac)
{
DLRBT_Tree keys;
@@ -746,38 +817,42 @@ void draw_gpencil_channel(View2D *v2d, bDopeSheet *ads, bGPdata *gpd, float ypos
BLI_dlrbTree_linkedlist_sync(&keys);
- draw_keylist(v2d, &keys, NULL, ypos, 0);
+ draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, false);
BLI_dlrbTree_free(&keys);
}
-void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos)
+void draw_gpl_channel(View2D *v2d, bDopeSheet *ads, bGPDlayer *gpl, float ypos, float yscale_fac)
{
DLRBT_Tree keys;
+ bool locked = (gpl->flag & GP_LAYER_LOCKED) != 0;
+
BLI_dlrbTree_init(&keys);
gpl_to_keylist(ads, gpl, &keys);
BLI_dlrbTree_linkedlist_sync(&keys);
- draw_keylist(v2d, &keys, NULL, ypos, (gpl->flag & GP_LAYER_LOCKED));
+ draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, locked);
BLI_dlrbTree_free(&keys);
}
-void draw_masklay_channel(View2D *v2d, bDopeSheet *ads, MaskLayer *masklay, float ypos)
+void draw_masklay_channel(View2D *v2d, bDopeSheet *ads, MaskLayer *masklay, float ypos, float yscale_fac)
{
DLRBT_Tree keys;
-
+
+ bool locked = (masklay->flag & MASK_LAYERFLAG_LOCKED) != 0;
+
BLI_dlrbTree_init(&keys);
-
+
mask_to_keylist(ads, masklay, &keys);
-
+
BLI_dlrbTree_linkedlist_sync(&keys);
-
- draw_keylist(v2d, &keys, NULL, ypos, (masklay->flag & MASK_LAYERFLAG_LOCKED));
-
+
+ draw_keylist(v2d, &keys, NULL, ypos, yscale_fac, locked);
+
BLI_dlrbTree_free(&keys);
}
diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c
index 7b35a154fc8..4571df0f077 100644
--- a/source/blender/editors/animation/keyframes_edit.c
+++ b/source/blender/editors/animation/keyframes_edit.c
@@ -1208,6 +1208,13 @@ static short set_keytype_jitter(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
return 0;
}
+static short set_keytype_moving_hold(KeyframeEditData *UNUSED(ked), BezTriple *bezt)
+{
+ if (bezt->f2 & SELECT)
+ BEZKEYTYPE(bezt) = BEZT_KEYTYPE_MOVEHOLD;
+ return 0;
+}
+
/* Set the interpolation type of the selected BezTriples in each F-Curve to the specified one */
KeyframeEditFunc ANIM_editkeyframes_keytype(short code)
{
@@ -1221,6 +1228,9 @@ KeyframeEditFunc ANIM_editkeyframes_keytype(short code)
case BEZT_KEYTYPE_JITTER: /* jitter keyframe */
return set_keytype_jitter;
+ case BEZT_KEYTYPE_MOVEHOLD: /* moving hold */
+ return set_keytype_moving_hold;
+
case BEZT_KEYTYPE_KEYFRAME: /* proper keyframe */
default:
return set_keytype_keyframe;