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/space_action')
-rw-r--r--source/blender/editors/space_action/action_buttons.c3
-rw-r--r--source/blender/editors/space_action/action_data.c8
-rw-r--r--source/blender/editors/space_action/action_draw.c268
-rw-r--r--source/blender/editors/space_action/action_edit.c42
-rw-r--r--source/blender/editors/space_action/action_intern.h9
-rw-r--r--source/blender/editors/space_action/action_ops.c166
-rw-r--r--source/blender/editors/space_action/action_select.c171
-rw-r--r--source/blender/editors/space_action/space_action.c309
8 files changed, 630 insertions, 346 deletions
diff --git a/source/blender/editors/space_action/action_buttons.c b/source/blender/editors/space_action/action_buttons.c
index b16d0543d0e..55ad773f4df 100644
--- a/source/blender/editors/space_action/action_buttons.c
+++ b/source/blender/editors/space_action/action_buttons.c
@@ -48,7 +48,6 @@
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_screen.h"
#include "BKE_unit.h"
@@ -118,7 +117,7 @@ static int action_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void ACTION_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
+ ot->name = "Toggle Sidebar";
ot->idname = "ACTION_OT_properties";
ot->description = "Toggle the properties region visibility";
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index 8d4596a79a7..a3773110d0f 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -53,12 +53,12 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
+#include "BKE_context.h"
#include "BKE_fcurve.h"
-#include "BKE_library.h"
#include "BKE_key.h"
+#include "BKE_library.h"
#include "BKE_nla.h"
#include "BKE_scene.h"
-#include "BKE_context.h"
#include "BKE_report.h"
#include "UI_view2d.h"
@@ -566,11 +566,11 @@ void ED_animedit_unlink_action(bContext *C, ID *id, AnimData *adt, bAction *act,
if (strip->act == act) {
/* Remove this strip, and the track too if it doesn't have anything else */
- BKE_nlastrip_free(&nlt->strips, strip);
+ BKE_nlastrip_free(&nlt->strips, strip, true);
if (nlt->strips.first == NULL) {
BLI_assert(nstrip == NULL);
- BKE_nlatrack_free(&adt->nla_tracks, nlt);
+ BKE_nlatrack_free(&adt->nla_tracks, nlt, true);
}
}
}
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 33822e633be..77def4af6d0 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -43,16 +43,24 @@
/* Types --------------------------------------------------------------- */
#include "DNA_anim_types.h"
+#include "DNA_cachefile_types.h"
+#include "DNA_object_types.h"
#include "DNA_screen_types.h"
+#include "DNA_scene_types.h"
#include "BKE_action.h"
#include "BKE_context.h"
+#include "BKE_pointcache.h"
/* Everything from source (BIF, BDR, BSE) ------------------------------ */
#include "BIF_gl.h"
+#include "GPU_immediate.h"
+#include "GPU_matrix.h"
+#include "GPU_state.h"
+
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -156,32 +164,29 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
- int filter;
View2D *v2d = &ar->v2d;
bDopeSheet *ads = &saction->ads;
AnimData *adt = NULL;
float act_start, act_end, y;
- size_t items;
- int height;
- unsigned char col1[3], col2[3];
- unsigned char col1a[3], col2a[3];
- unsigned char col1b[3], col2b[3];
+ unsigned char col1[4], col2[4];
+ unsigned char col1a[4], col2a[4];
+ unsigned char col1b[4], col2b[4];
const bool show_group_colors = !(saction->flag & SACTION_NODRAWGCOLORS);
/* get theme colors */
- UI_GetThemeColor3ubv(TH_BACK, col2);
- UI_GetThemeColor3ubv(TH_HILITE, col1);
+ UI_GetThemeColor4ubv(TH_SHADE2, col2);
+ UI_GetThemeColor4ubv(TH_HILITE, col1);
- UI_GetThemeColor3ubv(TH_GROUP, col2a);
- UI_GetThemeColor3ubv(TH_GROUP_ACTIVE, col1a);
+ UI_GetThemeColor4ubv(TH_GROUP, col2a);
+ UI_GetThemeColor4ubv(TH_GROUP_ACTIVE, col1a);
- UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELOB, col1b);
- UI_GetThemeColor3ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
+ UI_GetThemeColor4ubv(TH_DOPESHEET_CHANNELOB, col1b);
+ UI_GetThemeColor4ubv(TH_DOPESHEET_CHANNELSUBOB, col2b);
/* set view-mapping rect (only used for x-axis), for NLA-scaling mapping with less calculation */
@@ -194,10 +199,10 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
}
/* build list of channels to draw */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
- items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
+ int filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
+ size_t items = ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype);
- height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac)));
+ int height = ((items * ACHANNEL_STEP(ac)) + (ACHANNEL_HEIGHT(ac)));
/* don't use totrect set, as the width stays the same
* (NOTE: this is ok here, the configuration is pretty straightforward)
*/
@@ -205,7 +210,13 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
/* first backdrop strips */
y = (float)(-ACHANNEL_HEIGHT(ac));
- glEnable(GL_BLEND);
+
+ GPUVertFormat *format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ GPU_blend(true);
for (ale = anim_data.first; ale; ale = ale->next) {
const float yminc = (float)(y - ACHANNEL_HEIGHT_HALF(ac));
@@ -229,22 +240,20 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
case ANIMTYPE_SUMMARY:
{
/* reddish color from NLA */
- UI_ThemeColor4(TH_ANIM_ACTIVE);
+ immUniformThemeColor(TH_ANIM_ACTIVE);
break;
}
case ANIMTYPE_SCENE:
case ANIMTYPE_OBJECT:
{
- if (sel) glColor4ub(col1b[0], col1b[1], col1b[2], 0x45);
- else glColor4ub(col1b[0], col1b[1], col1b[2], 0x22);
+ immUniformColor3ubvAlpha(col1b, sel ? col1[3] : col1b[3]);
break;
}
case ANIMTYPE_FILLACTD:
case ANIMTYPE_DSSKEY:
case ANIMTYPE_DSWOR:
{
- if (sel) glColor4ub(col2b[0], col2b[1], col2b[2], 0x45);
- else glColor4ub(col2b[0], col2b[1], col2b[2], 0x22);
+ immUniformColor3ubvAlpha(col2b, sel ? col1[3] : col2b[3]);
break;
}
case ANIMTYPE_GROUP:
@@ -252,17 +261,14 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
bActionGroup *agrp = ale->data;
if (show_group_colors && agrp->customCol) {
if (sel) {
- unsigned char *cp = (unsigned char *)agrp->cs.select;
- glColor4ub(cp[0], cp[1], cp[2], 0x45);
+ immUniformColor3ubvAlpha((unsigned char *)agrp->cs.select, col1a[3]);
}
else {
- unsigned char *cp = (unsigned char *)agrp->cs.solid;
- glColor4ub(cp[0], cp[1], cp[2], 0x1D);
+ immUniformColor3ubvAlpha((unsigned char *)agrp->cs.solid, col2a[3]);
}
}
else {
- if (sel) glColor4ub(col1a[0], col1a[1], col1a[2], 0x22);
- else glColor4ub(col2a[0], col2a[1], col2a[2], 0x22);
+ immUniformColor4ubv(sel ? col1a : col2a);
}
break;
}
@@ -270,53 +276,45 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
{
FCurve *fcu = ale->data;
if (show_group_colors && fcu->grp && fcu->grp->customCol) {
- unsigned char *cp = (unsigned char *)fcu->grp->cs.active;
-
- if (sel) glColor4ub(cp[0], cp[1], cp[2], 0x65);
- else glColor4ub(cp[0], cp[1], cp[2], 0x0B);
+ immUniformColor3ubvAlpha((unsigned char *)fcu->grp->cs.active, sel ? col1[3] : col2[3]);
}
else {
- if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
- else glColor4ub(col2[0], col2[1], col2[2], 0x22);
+ immUniformColor4ubv(sel ? col1 : col2);
}
break;
}
default:
{
- if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
- else glColor4ub(col2[0], col2[1], col2[2], 0x22);
- break;
+ immUniformColor4ubv(sel ? col1 : col2);
}
}
/* draw region twice: firstly backdrop, then the current range */
- glRectf(v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
if (ac->datatype == ANIMCONT_ACTION)
- glRectf(act_start, (float)y - ACHANNEL_HEIGHT_HALF(ac), act_end, (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immRectf(pos, act_start, (float)y - ACHANNEL_HEIGHT_HALF(ac), act_end, (float)y + ACHANNEL_HEIGHT_HALF(ac));
}
else if (ac->datatype == ANIMCONT_GPENCIL) {
/* frames less than one get less saturated background */
- if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
- else glColor4ub(col2[0], col2[1], col2[2], 0x22);
- glRectf(0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ unsigned char *color = sel ? col1 : col2;
+ immUniformColor4ubv(color);
+ immRectf(pos, 0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac));
/* frames one and higher get a saturated background */
- if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
- else glColor4ub(col2[0], col2[1], col2[2], 0x44);
- glRectf(v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immUniformColor3ubvAlpha(color, MIN2(255, color[3] * 2));
+ immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
}
else if (ac->datatype == ANIMCONT_MASK) {
/* TODO --- this is a copy of gpencil */
/* frames less than one get less saturated background */
- if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x22);
- else glColor4ub(col2[0], col2[1], col2[2], 0x22);
- glRectf(0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ unsigned char *color = sel ? col1 : col2;
+ immUniformColor4ubv(color);
+ immRectf(pos, 0.0f, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmin, (float)y + ACHANNEL_HEIGHT_HALF(ac));
/* frames one and higher get a saturated background */
- if (sel) glColor4ub(col1[0], col1[1], col1[2], 0x44);
- else glColor4ub(col2[0], col2[1], col2[2], 0x44);
- glRectf(v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
+ immUniformColor3ubvAlpha(color, MIN2(255, color[3] * 2));
+ immRectf(pos, v2d->cur.xmin, (float)y - ACHANNEL_HEIGHT_HALF(ac), v2d->cur.xmax + EXTRA_SCROLL_PAD, (float)y + ACHANNEL_HEIGHT_HALF(ac));
}
}
}
@@ -324,7 +322,18 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
/* Increment the step */
y -= ACHANNEL_STEP(ac);
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
+
+ /* black line marking 'current frame' for Time-Slide transform mode */
+ if (saction->flag & SACTION_MOVING) {
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+
+ immBegin(GPU_PRIM_LINES, 2);
+ immVertex2f(pos, saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD);
+ immVertex2f(pos, saction->timeslide, v2d->cur.ymax);
+ immEnd();
+ }
+ immUnbindProgram();
/* Draw keyframes
* 1) Only channels that are visible in the Action Editor get drawn/evaluated.
@@ -348,28 +357,28 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
/* draw 'keyframes' for each specific datatype */
switch (ale->datatype) {
case ALE_ALL:
- draw_summary_channel(v2d, ale->data, y, ac->yscale_fac);
+ draw_summary_channel(v2d, ale->data, y, ac->yscale_fac, saction->flag);
break;
case ALE_SCE:
- draw_scene_channel(v2d, ads, ale->key_data, y, ac->yscale_fac);
+ draw_scene_channel(v2d, ads, ale->key_data, y, ac->yscale_fac, saction->flag);
break;
case ALE_OB:
- draw_object_channel(v2d, ads, ale->key_data, y, ac->yscale_fac);
+ draw_object_channel(v2d, ads, ale->key_data, y, ac->yscale_fac, saction->flag);
break;
case ALE_ACT:
- draw_action_channel(v2d, adt, ale->key_data, y, ac->yscale_fac);
+ draw_action_channel(v2d, adt, ale->key_data, y, ac->yscale_fac, saction->flag);
break;
case ALE_GROUP:
- draw_agroup_channel(v2d, adt, ale->data, y, ac->yscale_fac);
+ draw_agroup_channel(v2d, adt, ale->data, y, ac->yscale_fac, saction->flag);
break;
case ALE_FCURVE:
- draw_fcurve_channel(v2d, adt, ale->key_data, y, ac->yscale_fac);
+ draw_fcurve_channel(v2d, adt, ale->key_data, y, ac->yscale_fac, saction->flag);
break;
case ALE_GPFRAME:
- draw_gpl_channel(v2d, ads, ale->data, y, ac->yscale_fac);
+ draw_gpl_channel(v2d, ads, ale->data, y, ac->yscale_fac, saction->flag);
break;
case ALE_MASKLAY:
- draw_masklay_channel(v2d, ads, ale->data, y, ac->yscale_fac);
+ draw_masklay_channel(v2d, ads, ale->data, y, ac->yscale_fac, saction->flag);
break;
}
}
@@ -378,16 +387,141 @@ void draw_channel_strips(bAnimContext *ac, SpaceAction *saction, ARegion *ar)
y -= ACHANNEL_STEP(ac);
}
- /* free tempolary channels used for drawing */
+ /* free temporary channels used for drawing */
ANIM_animdata_freelist(&anim_data);
+}
- /* black line marking 'current frame' for Time-Slide transform mode */
- if (saction->flag & SACTION_MOVING) {
- glColor3f(0.0f, 0.0f, 0.0f);
+/* ************************************************************************* */
+/* Timeline - Caches */
+
+void timeline_draw_cache(SpaceAction *saction, Object *ob, Scene *scene)
+{
+ PTCacheID *pid;
+ ListBase pidlist;
+ const float cache_draw_height = (4.0f * UI_DPI_FAC * U.pixelsize);
+ float yoffs = 0.f;
+
+ if (!(saction->cache_display & TIME_CACHE_DISPLAY) || (!ob))
+ return;
+
+ BKE_ptcache_ids_from_object(&pidlist, ob, scene, 0);
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
+ /* iterate over pointcaches on the active object, and draw each one's range */
+ for (pid = pidlist.first; pid; pid = pid->next) {
+ float col[4];
+
+ switch (pid->type) {
+ case PTCACHE_TYPE_SOFTBODY:
+ if (!(saction->cache_display & TIME_CACHE_SOFTBODY)) continue;
+ break;
+ case PTCACHE_TYPE_PARTICLES:
+ if (!(saction->cache_display & TIME_CACHE_PARTICLES)) continue;
+ break;
+ case PTCACHE_TYPE_CLOTH:
+ if (!(saction->cache_display & TIME_CACHE_CLOTH)) continue;
+ break;
+ case PTCACHE_TYPE_SMOKE_DOMAIN:
+ case PTCACHE_TYPE_SMOKE_HIGHRES:
+ if (!(saction->cache_display & TIME_CACHE_SMOKE)) continue;
+ break;
+ case PTCACHE_TYPE_DYNAMICPAINT:
+ if (!(saction->cache_display & TIME_CACHE_DYNAMICPAINT)) continue;
+ break;
+ case PTCACHE_TYPE_RIGIDBODY:
+ if (!(saction->cache_display & TIME_CACHE_RIGIDBODY)) continue;
+ break;
+ }
+
+ if (pid->cache->cached_frames == NULL)
+ continue;
+
+ GPU_matrix_push();
+ GPU_matrix_translate_2f(0.0, (float)V2D_SCROLL_HEIGHT_TEXT + yoffs);
+ GPU_matrix_scale_2f(1.0, cache_draw_height);
+
+ switch (pid->type) {
+ case PTCACHE_TYPE_SOFTBODY:
+ col[0] = 1.0; col[1] = 0.4; col[2] = 0.02;
+ col[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_PARTICLES:
+ col[0] = 1.0; col[1] = 0.1; col[2] = 0.02;
+ col[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_CLOTH:
+ col[0] = 0.1; col[1] = 0.1; col[2] = 0.75;
+ col[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_SMOKE_DOMAIN:
+ case PTCACHE_TYPE_SMOKE_HIGHRES:
+ col[0] = 0.2; col[1] = 0.2; col[2] = 0.2;
+ col[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_DYNAMICPAINT:
+ col[0] = 1.0; col[1] = 0.1; col[2] = 0.75;
+ col[3] = 0.1;
+ break;
+ case PTCACHE_TYPE_RIGIDBODY:
+ col[0] = 1.0; col[1] = 0.6; col[2] = 0.0;
+ col[3] = 0.1;
+ break;
+ default:
+ col[0] = 1.0; col[1] = 0.0; col[2] = 1.0;
+ col[3] = 0.1;
+ BLI_assert(0);
+ break;
+ }
+
+ const int sta = pid->cache->startframe, end = pid->cache->endframe;
+ const int len = (end - sta + 1) * 6;
+
+ GPU_blend(true);
+
+ immUniformColor4fv(col);
+ immRectf(pos, (float)sta, 0.0, (float)end, 1.0);
+
+ col[3] = 0.4f;
+ if (pid->cache->flag & PTCACHE_BAKED) {
+ col[0] -= 0.4f; col[1] -= 0.4f; col[2] -= 0.4f;
+ }
+ else if (pid->cache->flag & PTCACHE_OUTDATED) {
+ col[0] += 0.4f; col[1] += 0.4f; col[2] += 0.4f;
+ }
+
+ immUniformColor4fv(col);
+
+ if (len > 0) {
+ immBeginAtMost(GPU_PRIM_TRIS, len);
+
+ /* draw a quad for each cached frame */
+ for (int i = sta; i <= end; i++) {
+ if (pid->cache->cached_frames[i - sta]) {
+ immVertex2f(pos, (float)i - 0.5f, 0.0f);
+ immVertex2f(pos, (float)i - 0.5f, 1.0f);
+ immVertex2f(pos, (float)i + 0.5f, 1.0f);
- glBegin(GL_LINES);
- glVertex2f(saction->timeslide, v2d->cur.ymin - EXTRA_SCROLL_PAD);
- glVertex2f(saction->timeslide, v2d->cur.ymax);
- glEnd();
+ immVertex2f(pos, (float)i - 0.5f, 0.0f);
+ immVertex2f(pos, (float)i + 0.5f, 1.0f);
+ immVertex2f(pos, (float)i + 0.5f, 0.0f);
+ }
+ }
+
+ immEnd();
+ }
+
+ GPU_blend(false);
+
+ GPU_matrix_pop();
+
+ yoffs += cache_draw_height;
}
+
+ immUnbindProgram();
+
+ BLI_freelistN(&pidlist);
}
+
+/* ************************************************************************* */
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index 289cf730228..c2376b506d4 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -54,14 +54,12 @@
#include "RNA_enum_types.h"
#include "BKE_action.h"
+#include "BKE_context.h"
#include "BKE_fcurve.h"
#include "BKE_gpencil.h"
#include "BKE_global.h"
#include "BKE_key.h"
-#include "BKE_library.h"
-#include "BKE_main.h"
#include "BKE_nla.h"
-#include "BKE_context.h"
#include "BKE_report.h"
#include "UI_view2d.h"
@@ -385,12 +383,22 @@ static int actkeys_viewall(bContext *C, const bool only_sel)
if (only_sel && (found == false))
return OPERATOR_CANCELLED;
- v2d->cur.xmin = min;
- v2d->cur.xmax = max;
+ if (fabsf(max - min) < 1.0f) {
+ /* Exception - center the single keyfrme */
+ float xwidth = BLI_rctf_size_x(&v2d->cur);
+
+ v2d->cur.xmin = min - xwidth / 2.0f;
+ v2d->cur.xmax = max + xwidth / 2.0f;
+ }
+ else {
+ /* Normal case - stretch the two keyframes out to fill the space, with extra spacing */
+ v2d->cur.xmin = min;
+ v2d->cur.xmax = max;
- extra = 0.1f * BLI_rctf_size_x(&v2d->cur);
- v2d->cur.xmin -= extra;
- v2d->cur.xmax += extra;
+ extra = 0.125f * BLI_rctf_size_x(&v2d->cur);
+ v2d->cur.xmin -= extra;
+ v2d->cur.xmax += extra;
+ }
/* set vertical range */
if (only_sel == false) {
@@ -674,6 +682,7 @@ static void insert_action_keys(bAnimContext *ac, short mode)
bAnimListElem *ale;
int filter;
+ struct Depsgraph *depsgraph = ac->depsgraph;
ReportList *reports = ac->reports;
Scene *scene = ac->scene;
ToolSettings *ts = scene->toolsettings;
@@ -691,15 +700,8 @@ static void insert_action_keys(bAnimContext *ac, short mode)
/* 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-scaling */
- if (adt)
- cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
- else
- cfra = (float)CFRA;
+ float 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
@@ -708,10 +710,16 @@ static void insert_action_keys(bAnimContext *ac, short mode)
* (TODO: add the full-blown PointerRNA relative parsing case here...)
*/
if (ale->id && !ale->owner) {
- insert_keyframe(ac->bmain, reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)),
+ insert_keyframe(ac->bmain, depsgraph, reports, ale->id, NULL, ((fcu->grp) ? (fcu->grp->name) : (NULL)),
fcu->rna_path, fcu->array_index, cfra, ts->keyframe_type, flag);
}
else {
+ AnimData *adt = ANIM_nla_mapping_get(ac, ale);
+
+ /* adjust current frame for NLA-scaling */
+ if (adt)
+ cfra = BKE_nla_tweakedit_remap(adt, (float)CFRA, NLATIME_CONVERT_UNMAP);
+
const float curval = evaluate_fcurve(fcu, cfra);
insert_vert_fcurve(fcu, cfra, curval, ts->keyframe_type, 0);
}
diff --git a/source/blender/editors/space_action/action_intern.h b/source/blender/editors/space_action/action_intern.h
index 37bef41e4d5..986afe96e11 100644
--- a/source/blender/editors/space_action/action_intern.h
+++ b/source/blender/editors/space_action/action_intern.h
@@ -33,10 +33,13 @@
struct bContext;
struct bAnimContext;
+struct Scene;
+struct Object;
struct SpaceAction;
struct ScrArea;
struct ARegion;
struct ARegionType;
+struct View2D;
struct wmOperatorType;
/* internal exports only */
@@ -54,11 +57,13 @@ void ACTION_OT_properties(struct wmOperatorType *ot);
void draw_channel_names(struct bContext *C, struct bAnimContext *ac, struct ARegion *ar);
void draw_channel_strips(struct bAnimContext *ac, struct SpaceAction *saction, struct ARegion *ar);
+void timeline_draw_cache(struct SpaceAction *saction, struct Object *ob, struct Scene *scene);
+
/* ***************************************** */
/* action_select.c */
-void ACTION_OT_select_all_toggle(struct wmOperatorType *ot);
-void ACTION_OT_select_border(struct wmOperatorType *ot);
+void ACTION_OT_select_all(struct wmOperatorType *ot);
+void ACTION_OT_select_box(struct wmOperatorType *ot);
void ACTION_OT_select_lasso(struct wmOperatorType *ot);
void ACTION_OT_select_circle(struct wmOperatorType *ot);
void ACTION_OT_select_column(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_action/action_ops.c b/source/blender/editors/space_action/action_ops.c
index ea7591c36c0..bbcba93370d 100644
--- a/source/blender/editors/space_action/action_ops.c
+++ b/source/blender/editors/space_action/action_ops.c
@@ -40,6 +40,7 @@
#include "ED_markers.h"
#include "ED_transform.h"
#include "ED_object.h"
+#include "ED_select_utils.h"
#include "action_intern.h"
@@ -58,8 +59,8 @@ void action_operatortypes(void)
/* keyframes */
/* selection */
WM_operatortype_append(ACTION_OT_clickselect);
- WM_operatortype_append(ACTION_OT_select_all_toggle);
- WM_operatortype_append(ACTION_OT_select_border);
+ WM_operatortype_append(ACTION_OT_select_all);
+ WM_operatortype_append(ACTION_OT_select_box);
WM_operatortype_append(ACTION_OT_select_lasso);
WM_operatortype_append(ACTION_OT_select_circle);
WM_operatortype_append(ACTION_OT_select_column);
@@ -118,168 +119,12 @@ void ED_operatormacros_action(void)
/* ************************** registration - keymaps **********************************/
-static void action_keymap_keyframes(wmKeyConfig *keyconf, wmKeyMap *keymap)
-{
- wmKeyMapItem *kmi;
-
- /* action_select.c - selection tools */
- /* click-select: keyframe (replace) */
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_clickselect", SELECTMOUSE, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "extend", false);
- RNA_boolean_set(kmi->ptr, "column", false);
- RNA_boolean_set(kmi->ptr, "channel", false);
- /* click-select: all on same frame (replace) */
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT, 0);
- RNA_boolean_set(kmi->ptr, "extend", false);
- RNA_boolean_set(kmi->ptr, "column", true);
- RNA_boolean_set(kmi->ptr, "channel", false);
- /* click-select: keyframe (add) */
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "extend", true);
- RNA_boolean_set(kmi->ptr, "column", false);
- RNA_boolean_set(kmi->ptr, "channel", false);
- /* click-select: all on same frame (add) */
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_ALT | KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "extend", true);
- RNA_boolean_set(kmi->ptr, "column", true);
- RNA_boolean_set(kmi->ptr, "channel", false);
- /* click-select: all on same channel (replace) */
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_ALT, 0);
- RNA_boolean_set(kmi->ptr, "extend", false);
- RNA_boolean_set(kmi->ptr, "column", false);
- RNA_boolean_set(kmi->ptr, "channel", true);
- /* click-select: all on same channel (add) */
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_clickselect", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_ALT | KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "extend", true);
- RNA_boolean_set(kmi->ptr, "column", false);
- RNA_boolean_set(kmi->ptr, "channel", true);
-
- /* click-select: left/right */
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
- RNA_boolean_set(kmi->ptr, "extend", false);
- RNA_enum_set(kmi->ptr, "mode", ACTKEYS_LRSEL_TEST);
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "extend", true);
- RNA_enum_set(kmi->ptr, "mode", ACTKEYS_LRSEL_TEST);
-
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_leftright", LEFTBRACKETKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "extend", false);
- RNA_enum_set(kmi->ptr, "mode", ACTKEYS_LRSEL_LEFT);
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_leftright", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "extend", false);
- RNA_enum_set(kmi->ptr, "mode", ACTKEYS_LRSEL_RIGHT);
-
- /* deselect all */
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "invert", false);
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0);
- RNA_boolean_set(kmi->ptr, "invert", true);
-
- /* borderselect */
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_border", BKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "axis_range", false);
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0);
- RNA_boolean_set(kmi->ptr, "axis_range", true);
-
- /* region select */
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL, 0);
- RNA_boolean_set(kmi->ptr, "deselect", false);
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_select_lasso", EVT_TWEAK_A, KM_ANY, KM_CTRL | KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "deselect", true);
-
- WM_keymap_add_item(keymap, "ACTION_OT_select_circle", CKEY, KM_PRESS, 0, 0);
-
- /* column select */
- RNA_enum_set(WM_keymap_add_item(keymap, "ACTION_OT_select_column", KKEY, KM_PRESS, 0, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_KEYS);
- RNA_enum_set(WM_keymap_add_item(keymap, "ACTION_OT_select_column", KKEY, KM_PRESS, KM_CTRL, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_CFRA);
- RNA_enum_set(WM_keymap_add_item(keymap, "ACTION_OT_select_column", KKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_COLUMN);
- RNA_enum_set(WM_keymap_add_item(keymap, "ACTION_OT_select_column", KKEY, KM_PRESS, KM_ALT, 0)->ptr, "mode", ACTKEYS_COLUMNSEL_MARKERS_BETWEEN);
-
- /* select more/less */
- WM_keymap_add_item(keymap, "ACTION_OT_select_more", PADPLUSKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_select_less", PADMINUS, KM_PRESS, KM_CTRL, 0);
-
- /* select linked */
- WM_keymap_add_item(keymap, "ACTION_OT_select_linked", LKEY, KM_PRESS, 0, 0);
-
-
- /* action_edit.c */
- /* jump to selected keyframes */
- WM_keymap_add_item(keymap, "ACTION_OT_frame_jump", GKEY, KM_PRESS, KM_CTRL, 0);
-
- /* menu + single-step transform */
- WM_keymap_add_item(keymap, "ACTION_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_mirror", MKEY, KM_PRESS, KM_SHIFT, 0);
-
- /* menu + set setting */
- WM_keymap_add_item(keymap, "ACTION_OT_handle_type", VKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_interpolation_type", TKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_extrapolation_type", EKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_keyframe_type", RKEY, KM_PRESS, 0, 0);
-
- /* destructive */
- WM_keymap_add_item(keymap, "ACTION_OT_sample", OKEY, KM_PRESS, KM_SHIFT, 0);
-
- WM_keymap_add_menu(keymap, "DOPESHEET_MT_delete", XKEY, KM_PRESS, 0, 0);
- WM_keymap_add_menu(keymap, "DOPESHEET_MT_delete", DELKEY, KM_PRESS, 0, 0);
-
- WM_keymap_add_item(keymap, "ACTION_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_keyframe_insert", IKEY, KM_PRESS, 0, 0);
-
- /* copy/paste */
- WM_keymap_add_item(keymap, "ACTION_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_paste", VKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "flipped", true);
-#ifdef __APPLE__
- WM_keymap_add_item(keymap, "ACTION_OT_copy", CKEY, KM_PRESS, KM_OSKEY, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_paste", VKEY, KM_PRESS, KM_OSKEY, 0);
- kmi = WM_keymap_add_item(keymap, "ACTION_OT_paste", VKEY, KM_PRESS, KM_OSKEY | KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "flipped", true);
-#endif
-
- /* auto-set range */
- WM_keymap_add_item(keymap, "ACTION_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
-#ifdef WITH_INPUT_NDOF
- WM_keymap_add_item(keymap, "ACTION_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
-#endif
- WM_keymap_add_item(keymap, "ACTION_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "ACTION_OT_view_frame", PAD0, KM_PRESS, 0, 0);
-
-
- /* animation module */
- /* channels list
- * NOTE: these operators were originally for the channels list, but are added here too for convenience...
- */
- WM_keymap_add_item(keymap, "ANIM_OT_channels_editable_toggle", TABKEY, KM_PRESS, 0, 0);
-
- /* find (i.e. a shortcut for setting the name filter) */
- WM_keymap_add_item(keymap, "ANIM_OT_channels_find", FKEY, KM_PRESS, KM_CTRL, 0);
-
- /* transform system */
- transform_keymap_for_space(keyconf, keymap, SPACE_ACTION);
-
- kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", OKEY, KM_PRESS, 0, 0);
- RNA_string_set(kmi->ptr, "data_path", "tool_settings.use_proportional_action");
- ED_keymap_proportional_cycle(keyconf, keymap);
-
- /* special markers hotkeys for anim editors: see note in definition of this function */
- ED_marker_keymap_animedit_conflictfree(keymap);
-}
-
/* --------------- */
void action_keymap(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap;
-
/* keymap for all regions */
- keymap = WM_keymap_ensure(keyconf, "Dopesheet Generic", SPACE_ACTION, 0);
-
- /* region management... */
- WM_keymap_add_item(keymap, "ACTION_OT_properties", NKEY, KM_PRESS, 0, 0);
-
+ WM_keymap_ensure(keyconf, "Dopesheet Generic", SPACE_ACTION, 0);
/* channels */
/* Channels are not directly handled by the Action Editor module, but are inherited from the Animation module.
@@ -288,6 +133,5 @@ void action_keymap(wmKeyConfig *keyconf)
*/
/* keyframes */
- keymap = WM_keymap_ensure(keyconf, "Dopesheet", SPACE_ACTION, 0);
- action_keymap_keyframes(keyconf, keymap);
+ WM_keymap_ensure(keyconf, "Dopesheet", SPACE_ACTION, 0);
}
diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c
index 581725b7030..0c96560f6d5 100644
--- a/source/blender/editors/space_action/action_select.c
+++ b/source/blender/editors/space_action/action_select.c
@@ -51,6 +51,7 @@
#include "BKE_fcurve.h"
#include "BKE_nla.h"
#include "BKE_context.h"
+#include "BKE_gpencil.h"
#include "UI_view2d.h"
@@ -61,6 +62,7 @@
#include "ED_keyframes_edit.h"
#include "ED_markers.h"
#include "ED_screen.h"
+#include "ED_select_utils.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -134,15 +136,20 @@ static void deselect_action_keys(bAnimContext *ac, short test, short sel)
/* Now set the flags */
for (ale = anim_data.first; ale; ale = ale->next) {
- if (ale->type == ANIMTYPE_GPLAYER)
+ if (ale->type == ANIMTYPE_GPLAYER) {
ED_gplayer_frame_select_set(ale->data, sel);
- else if (ale->type == ANIMTYPE_MASKLAYER)
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_masklayer_frame_select_set(ale->data, sel);
- else
+ }
+ else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, NULL, sel_cb, NULL);
+ }
}
/* Cleanup */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -157,10 +164,24 @@ static int actkeys_deselectall_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
/* 'standard' behavior - check if selected, then apply relevant selection */
- if (RNA_boolean_get(op->ptr, "invert"))
- deselect_action_keys(&ac, 0, SELECT_INVERT);
- else
- deselect_action_keys(&ac, 1, SELECT_ADD);
+ const int action = RNA_enum_get(op->ptr, "action");
+ switch (action) {
+ case SEL_TOGGLE:
+ deselect_action_keys(&ac, 1, SELECT_ADD);
+ break;
+ case SEL_SELECT:
+ deselect_action_keys(&ac, 0, SELECT_ADD);
+ break;
+ case SEL_DESELECT:
+ deselect_action_keys(&ac, 0, SELECT_SUBTRACT);
+ break;
+ case SEL_INVERT:
+ deselect_action_keys(&ac, 0, SELECT_INVERT);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
/* set notifier that keyframe selection have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@@ -168,11 +189,11 @@ static int actkeys_deselectall_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void ACTION_OT_select_all_toggle(wmOperatorType *ot)
+void ACTION_OT_select_all(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Select All";
- ot->idname = "ACTION_OT_select_all_toggle";
+ ot->idname = "ACTION_OT_select_all";
ot->description = "Toggle selection of all keyframes";
/* api callbacks */
@@ -182,12 +203,11 @@ void ACTION_OT_select_all_toggle(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* props */
- ot->prop = RNA_def_boolean(ot->srna, "invert", 0, "Invert", "");
- RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE);
+ /* properties */
+ WM_operator_properties_select_all(ot);
}
-/* ******************** Border Select Operator **************************** */
+/* ******************** Box Select Operator **************************** */
/* This operator currently works in one of three ways:
* -> BKEY - 1) all keyframes within region are selected (ACTKEYS_BORDERSEL_ALLKEYS)
* -> ALT-BKEY - depending on which axis of the region was larger...
@@ -195,15 +215,15 @@ void ACTION_OT_select_all_toggle(wmOperatorType *ot)
* -> 3) y-axis, so select all frames within channels that region included (ACTKEYS_BORDERSEL_CHANNELS)
*/
-/* defines for borderselect mode */
+/* defines for box_select mode */
enum {
ACTKEYS_BORDERSEL_ALLKEYS = 0,
ACTKEYS_BORDERSEL_FRAMERANGE,
ACTKEYS_BORDERSEL_CHANNELS,
-} /*eActKeys_BorderSelect_Mode*/;
+} /*eActKeys_BoxSelect_Mode*/;
-static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, short selectmode)
+static void box_select_action(bAnimContext *ac, const rcti rect, short mode, short selectmode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
@@ -234,7 +254,7 @@ static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, s
/* init editing data */
memset(&ked, 0, sizeof(KeyframeEditData));
- /* loop over data, doing border select */
+ /* loop over data, doing box select */
for (ale = anim_data.first; ale; ale = ale->next) {
AnimData *adt = ANIM_nla_mapping_get(ac, ale);
@@ -268,25 +288,29 @@ static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, s
bGPdata *gpd = ale->data;
bGPDlayer *gpl;
for (gpl = gpd->layers.first; gpl; gpl = gpl->next) {
- ED_gplayer_frames_select_border(gpl, rectf.xmin, rectf.xmax, selectmode);
+ ED_gplayer_frames_select_box(gpl, rectf.xmin, rectf.xmax, selectmode);
}
+ ale->update |= ANIM_UPDATE_DEPS;
break;
}
#endif
case ANIMTYPE_GPLAYER:
- ED_gplayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode);
+ {
+ ED_gplayer_frames_select_box(ale->data, rectf.xmin, rectf.xmax, selectmode);
+ ale->update |= ANIM_UPDATE_DEPS;
break;
+ }
case ANIMTYPE_MASKDATABLOCK:
{
Mask *mask = ale->data;
MaskLayer *masklay;
for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) {
- ED_masklayer_frames_select_border(masklay, rectf.xmin, rectf.xmax, selectmode);
+ ED_masklayer_frames_select_box(masklay, rectf.xmin, rectf.xmax, selectmode);
}
break;
}
case ANIMTYPE_MASKLAYER:
- ED_masklayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode);
+ ED_masklayer_frames_select_box(ale->data, rectf.xmin, rectf.xmax, selectmode);
break;
default:
ANIM_animchannel_keyframes_loop(&ked, ac->ads, ale, ok_cb, select_cb, NULL);
@@ -299,12 +323,13 @@ static void borderselect_action(bAnimContext *ac, const rcti rect, short mode, s
}
/* cleanup */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
/* ------------------- */
-static int actkeys_borderselect_exec(bContext *C, wmOperator *op)
+static int actkeys_box_select_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
rcti rect;
@@ -331,7 +356,7 @@ static int actkeys_borderselect_exec(bContext *C, wmOperator *op)
selectmode = SELECT_SUBTRACT;
}
- /* selection 'mode' depends on whether borderselect region only matters on one axis */
+ /* selection 'mode' depends on whether box_select region only matters on one axis */
if (RNA_boolean_get(op->ptr, "axis_range")) {
/* mode depends on which axis of the range is larger to determine which axis to use
* - checking this in region-space is fine, as it's fundamentally still going to be a different rect size
@@ -346,8 +371,8 @@ static int actkeys_borderselect_exec(bContext *C, wmOperator *op)
else
mode = ACTKEYS_BORDERSEL_ALLKEYS;
- /* apply borderselect action */
- borderselect_action(&ac, rect, mode, selectmode);
+ /* apply box_select action */
+ box_select_action(&ac, rect, mode, selectmode);
/* set notifier that keyframe selection have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL);
@@ -355,18 +380,18 @@ static int actkeys_borderselect_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void ACTION_OT_select_border(wmOperatorType *ot)
+void ACTION_OT_select_box(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Border Select";
- ot->idname = "ACTION_OT_select_border";
+ ot->name = "Box Select";
+ ot->idname = "ACTION_OT_select_box";
ot->description = "Select all keyframes within the specified region";
/* api callbacks */
- ot->invoke = WM_gesture_border_invoke;
- ot->exec = actkeys_borderselect_exec;
- ot->modal = WM_gesture_border_modal;
- ot->cancel = WM_gesture_border_cancel;
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = actkeys_box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
ot->poll = ED_operator_action_active;
@@ -374,7 +399,7 @@ void ACTION_OT_select_border(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* rna */
- WM_operator_properties_gesture_border_select(ot);
+ WM_operator_properties_gesture_box_select(ot);
ot->prop = RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
}
@@ -480,6 +505,7 @@ static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view,
case ANIMTYPE_GPLAYER:
{
ED_gplayer_frames_select_region(&ked, ale->data, mode, selectmode);
+ ale->update |= ANIM_UPDATE_DEPS;
break;
}
case ANIMTYPE_MASKDATABLOCK:
@@ -507,6 +533,7 @@ static void region_select_action_keys(bAnimContext *ac, const rctf *rectf_view,
}
/* cleanup */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -546,7 +573,7 @@ static int actkeys_lassoselect_exec(bContext *C, wmOperator *op)
BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot);
BLI_rctf_rcti_copy(&rect_fl, &rect);
- /* apply borderselect action */
+ /* apply box_select action */
region_select_action_keys(&ac, &rect_fl, BEZT_OK_CHANNEL_LASSO, selectmode, &data_lasso);
MEM_freeN((void *)data_lasso.mcords);
@@ -693,10 +720,11 @@ static void markers_selectkeys_between(bAnimContext *ac)
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
}
else if (ale->type == ANIMTYPE_GPLAYER) {
- ED_gplayer_frames_select_border(ale->data, min, max, SELECT_ADD);
+ ED_gplayer_frames_select_box(ale->data, min, max, SELECT_ADD);
+ ale->update |= ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
- ED_masklayer_frames_select_border(ale->data, min, max, SELECT_ADD);
+ ED_masklayer_frames_select_box(ale->data, min, max, SELECT_ADD);
}
else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
@@ -704,6 +732,7 @@ static void markers_selectkeys_between(bAnimContext *ac)
}
/* Cleanup */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -783,17 +812,23 @@ static void columnselect_action_keys(bAnimContext *ac, short mode)
ked.f1 = ce->cfra;
/* select elements with frame number matching cfraelem */
- if (ale->type == ANIMTYPE_GPLAYER)
+ if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frame(ale->data, ce->cfra, SELECT_ADD);
- else if (ale->type == ANIMTYPE_MASKLAYER)
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frame(ale->data, ce->cfra, SELECT_ADD);
- else
+ }
+ else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ }
}
}
/* free elements */
BLI_freelistN(&ked.list);
+
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -1068,12 +1103,16 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
ANIM_nla_mapping_apply_fcurve(adt, ale->key_data, 1, 1);
}
- else if (ale->type == ANIMTYPE_GPLAYER)
- ED_gplayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode);
- else if (ale->type == ANIMTYPE_MASKLAYER)
- ED_masklayer_frames_select_border(ale->data, ked.f1, ked.f2, select_mode);
- else
+ else if (ale->type == ANIMTYPE_GPLAYER) {
+ ED_gplayer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode);
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
+ ED_masklayer_frames_select_box(ale->data, ked.f1, ked.f2, select_mode);
+ }
+ else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ }
}
/* Sync marker support */
@@ -1098,6 +1137,7 @@ static void actkeys_select_leftright(bAnimContext *ac, short leftright, short se
}
/* Cleanup */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -1214,6 +1254,7 @@ static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short s
/* select the nominated keyframe on the given frame */
if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frame(ale->data, selx, select_mode);
+ ale->update |= ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frame(ale->data, selx, select_mode);
@@ -1231,12 +1272,14 @@ static void actkeys_mselect_single(bAnimContext *ac, bAnimListElem *ale, short s
for (ale = anim_data.first; ale; ale = ale->next) {
if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frame(ale->data, selx, select_mode);
+ ale->update |= ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frame(ale->data, selx, select_mode);
}
}
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
else {
@@ -1281,16 +1324,22 @@ static void actkeys_mselect_column(bAnimContext *ac, short select_mode, float se
ked.f1 = selx;
/* select elements with frame number matching cfra */
- if (ale->type == ANIMTYPE_GPLAYER)
+ if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frame(ale->key_data, selx, select_mode);
- else if (ale->type == ANIMTYPE_MASKLAYER)
+ ale->update |= ANIM_UPDATE_DEPS;
+ }
+ else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frame(ale->key_data, selx, select_mode);
- else
+ }
+ else {
ANIM_fcurve_keyframes_loop(&ked, ale->key_data, ok_cb, select_cb, NULL);
+ }
}
/* free elements */
BLI_freelistN(&ked.list);
+
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -1305,6 +1354,7 @@ static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, s
/* select all keyframes in this channel */
if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frames(ale->data, select_mode);
+ ale->update = ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frames(ale->data, select_mode);
@@ -1322,12 +1372,14 @@ static void actkeys_mselect_channel_only(bAnimContext *ac, bAnimListElem *ale, s
for (ale = anim_data.first; ale; ale = ale->next) {
if (ale->type == ANIMTYPE_GPLAYER) {
ED_gpencil_select_frames(ale->data, select_mode);
+ ale->update |= ANIM_UPDATE_DEPS;
}
else if (ale->type == ANIMTYPE_MASKLAYER) {
ED_mask_select_frames(ale->data, select_mode);
}
}
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
else {
@@ -1356,7 +1408,7 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
rctf rectf;
/* get dopesheet info */
- if (ac->datatype == ANIMCONT_DOPESHEET)
+ if (ELEM(ac->datatype, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE))
ads = ac->data;
/* use View2D to determine the index of the channel (i.e a row in the list) where keyframe was */
@@ -1397,37 +1449,37 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
case ALE_SCE:
{
Scene *scene = (Scene *)ale->key_data;
- scene_to_keylist(ads, scene, &anim_keys, NULL);
+ scene_to_keylist(ads, scene, &anim_keys, 0);
break;
}
case ALE_OB:
{
Object *ob = (Object *)ale->key_data;
- ob_to_keylist(ads, ob, &anim_keys, NULL);
+ ob_to_keylist(ads, ob, &anim_keys, 0);
break;
}
case ALE_ACT:
{
bAction *act = (bAction *)ale->key_data;
- action_to_keylist(adt, act, &anim_keys, NULL);
+ action_to_keylist(adt, act, &anim_keys, 0);
break;
}
case ALE_FCURVE:
{
FCurve *fcu = (FCurve *)ale->key_data;
- fcurve_to_keylist(adt, fcu, &anim_keys, NULL);
+ fcurve_to_keylist(adt, fcu, &anim_keys, 0);
break;
}
}
}
else if (ale->type == ANIMTYPE_SUMMARY) {
/* dopesheet summary covers everything */
- summary_to_keylist(ac, &anim_keys, NULL);
+ summary_to_keylist(ac, &anim_keys, 0);
}
else if (ale->type == ANIMTYPE_GROUP) {
// TODO: why don't we just give groups key_data too?
bActionGroup *agrp = (bActionGroup *)ale->data;
- agroup_to_keylist(adt, agrp, &anim_keys, NULL);
+ agroup_to_keylist(adt, agrp, &anim_keys, 0);
}
else if (ale->type == ANIMTYPE_GPLAYER) {
// TODO: why don't we just give gplayers key_data too?
@@ -1460,6 +1512,7 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
/* remove active channel from list of channels for separate treatment (since it's needed later on) */
BLI_remlink(&anim_data, ale);
+ ale->next = ale->prev = NULL;
/* cleanup temporary lists */
BLI_dlrbTree_free(&anim_keys);
@@ -1477,7 +1530,7 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
deselect_action_keys(ac, 0, SELECT_SUBTRACT);
/* highlight channel clicked on */
- if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET)) {
+ if (ELEM(ac->datatype, ANIMCONT_ACTION, ANIMCONT_DOPESHEET, ANIMCONT_TIMELINE)) {
/* deselect all other channels first */
ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR);
@@ -1544,6 +1597,12 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_
}
}
+ /* flush tagged updates
+ * NOTE: We temporarily add this channel back to the list so that this can happen
+ */
+ anim_data.first = anim_data.last = ale;
+ ANIM_animdata_update(ac, &anim_data);
+
/* free this channel */
MEM_freeN(ale);
}
@@ -1590,7 +1649,7 @@ void ACTION_OT_clickselect(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "Mouse Select Keys";
+ ot->name = "Select Keyframes";
ot->idname = "ACTION_OT_clickselect";
ot->description = "Select keyframes by clicking on them";
diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c
index a2fe129c819..15587a5f39d 100644
--- a/source/blender/editors/space_action/space_action.c
+++ b/source/blender/editors/space_action/space_action.c
@@ -33,7 +33,8 @@
#include <stdio.h>
#include "DNA_action_types.h"
-#include "DNA_group_types.h"
+#include "DNA_collection_types.h"
+#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
@@ -45,10 +46,15 @@
#include "BKE_context.h"
#include "BKE_screen.h"
-#include "BIF_gl.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
+
+#include "BIF_gl.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -59,6 +65,7 @@
#include "ED_markers.h"
#include "action_intern.h" /* own include */
+#include "GPU_framebuffer.h"
/* ******************** manage regions ********************* */
@@ -88,10 +95,8 @@ ARegion *action_has_buttons_region(ScrArea *sa)
/* ******************** default callbacks for action space ***************** */
-static SpaceLink *action_new(const bContext *C)
+static SpaceLink *action_new(const ScrArea *sa, const Scene *scene)
{
- Scene *scene = CTX_data_scene(C);
- ScrArea *sa = CTX_wm_area(C);
SpaceAction *saction;
ARegion *ar;
@@ -100,15 +105,22 @@ static SpaceLink *action_new(const bContext *C)
saction->autosnap = SACTSNAP_FRAME;
saction->mode = SACTCONT_DOPESHEET;
+ saction->mode_prev = SACTCONT_DOPESHEET;
saction->ads.filterflag |= ADS_FILTER_SUMMARY;
+ /* enable all cache display */
+ saction->cache_display |= TIME_CACHE_DISPLAY;
+ saction->cache_display |= (TIME_CACHE_SOFTBODY | TIME_CACHE_PARTICLES);
+ saction->cache_display |= (TIME_CACHE_CLOTH | TIME_CACHE_SMOKE | TIME_CACHE_DYNAMICPAINT);
+ saction->cache_display |= TIME_CACHE_RIGIDBODY;
+
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for action");
BLI_addtail(&saction->regionbase, ar);
ar->regiontype = RGN_TYPE_HEADER;
- ar->alignment = RGN_ALIGN_BOTTOM;
+ ar->alignment = RGN_ALIGN_TOP;
/* channel list region */
ar = MEM_callocN(sizeof(ARegion), "channel region for action");
@@ -170,6 +182,7 @@ static void action_free(SpaceLink *UNUSED(sl))
static void action_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
{
SpaceAction *saction = sa->spacedata.first;
+
saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
}
@@ -202,15 +215,19 @@ static void action_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceAction *saction = CTX_wm_space_action(C);
+ Scene *scene = CTX_data_scene(C);
+ Object *obact = CTX_data_active_object(C);
bAnimContext ac;
View2D *v2d = &ar->v2d;
View2DGrid *grid;
View2DScrollers *scrollers;
- short unit = 0, flag = 0;
+ short marker_flag = 0;
+ short cfra_flag = 0;
+ short unit = 0;
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
+ GPU_clear(GPU_COLOR_BIT);
UI_view2d_view_ortho(v2d);
@@ -222,21 +239,28 @@ static void action_main_region_draw(const bContext *C, ARegion *ar)
ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
+ /* start and end frame */
+ ANIM_draw_framerange(scene, v2d);
+
/* data */
if (ANIM_animdata_get_context(C, &ac)) {
draw_channel_strips(&ac, saction, ar);
}
/* current frame */
- if (saction->flag & SACTION_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS;
- if ((saction->flag & SACTION_NODRAWCFRANUM) == 0) flag |= DRAWCFRA_SHOW_NUMBOX;
- ANIM_draw_cfra(C, v2d, flag);
+ if (saction->flag & SACTION_DRAWTIME) cfra_flag |= DRAWCFRA_UNIT_SECONDS;
+ ANIM_draw_cfra(C, v2d, cfra_flag);
/* markers */
UI_view2d_view_orthoSpecial(ar, v2d, 1);
- flag = ((ac.markers && (ac.markers != &ac.scene->markers)) ? DRAW_MARKERS_LOCAL : 0) | DRAW_MARKERS_MARGIN;
- ED_markers_draw(C, flag);
+ marker_flag = ((ac.markers && (ac.markers != &ac.scene->markers)) ? DRAW_MARKERS_LOCAL : 0) | DRAW_MARKERS_MARGIN;
+ ED_markers_draw(C, marker_flag);
+
+ /* caches */
+ if (saction->mode == SACTCONT_TIMELINE) {
+ timeline_draw_cache(saction, obact, scene);
+ }
/* preview range */
UI_view2d_view_ortho(v2d);
@@ -250,9 +274,15 @@ static void action_main_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
/* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, unit, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
UI_view2d_scrollers_draw(C, v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
+
+ /* draw current frame number-indicator on top of scrollers */
+ if ((saction->flag & SACTION_NODRAWCFRANUM) == 0) {
+ UI_view2d_view_orthoSpecial(ar, v2d, 1);
+ ANIM_draw_cfra_number(C, v2d, cfra_flag);
+ }
}
/* add handlers, stuff you only do once or on area/region changes */
@@ -281,7 +311,7 @@ static void action_channel_region_draw(const bContext *C, ARegion *ar)
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
+ GPU_clear(GPU_COLOR_BIT);
UI_view2d_view_ortho(v2d);
@@ -308,7 +338,9 @@ static void action_header_region_draw(const bContext *C, ARegion *ar)
ED_region_header(C, ar);
}
-static void action_channel_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void action_channel_region_listener(
+ wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -351,7 +383,55 @@ static void action_channel_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(
}
}
-static void action_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void saction_channel_region_message_subscribe(
+ const struct bContext *UNUSED(C),
+ struct WorkSpace *UNUSED(workspace), struct Scene *UNUSED(scene),
+ struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, sa->spacedata.first, &ptr);
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ /* All dopesheet filter settings, etc. affect the drawing of this editor,
+ * also same applies for all animation-related datatypes that may appear here,
+ * so just whitelist the entire structs for updates
+ */
+ {
+ wmMsgParams_RNA msg_key_params = {{{0}}};
+ StructRNA *type_array[] = {
+ &RNA_DopeSheet, /* dopesheet filters */
+
+ &RNA_ActionGroup, /* channel groups */
+
+ &RNA_FCurve, /* F-Curve */
+ &RNA_Keyframe,
+ &RNA_FCurveSample,
+
+ &RNA_GreasePencil, /* Grease Pencil */
+ &RNA_GPencilLayer,
+ &RNA_GPencilFrame,
+ };
+
+ for (int i = 0; i < ARRAY_SIZE(type_array); i++) {
+ msg_key_params.ptr.type = type_array[i];
+ WM_msg_subscribe_rna_params(
+ mbus,
+ &msg_key_params,
+ &msg_sub_value_region_tag_redraw,
+ __func__);
+ }
+ }
+}
+
+static void action_main_region_listener(
+ wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -363,6 +443,7 @@ static void action_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
case ND_RENDER_OPTIONS:
case ND_OB_ACTIVE:
case ND_FRAME:
+ case ND_FRAME_RANGE:
case ND_MARKERS:
ED_region_tag_redraw(ar);
break;
@@ -391,7 +472,11 @@ static void action_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
if (wmn->action == NA_RENAME)
ED_region_tag_redraw(ar);
break;
-
+ case NC_SCREEN:
+ if (ELEM(wmn->data, ND_LAYER)) {
+ ED_region_tag_redraw(ar);
+ }
+ break;
default:
if (wmn->data == ND_KEYS)
ED_region_tag_redraw(ar);
@@ -399,8 +484,52 @@ static void action_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
}
}
+static void saction_main_region_message_subscribe(
+ const struct bContext *C,
+ struct WorkSpace *workspace, struct Scene *scene,
+ struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceDopeSheetEditor, sa->spacedata.first, &ptr);
+
+ wmMsgSubscribeValue msg_sub_value_region_tag_redraw = {
+ .owner = ar,
+ .user_data = ar,
+ .notify = ED_region_do_msg_notify_tag_redraw,
+ };
+
+ /* Timeline depends on scene properties. */
+ {
+ bool use_preview = (scene->r.flag & SCER_PRV_RANGE);
+ extern PropertyRNA rna_Scene_frame_start;
+ extern PropertyRNA rna_Scene_frame_end;
+ extern PropertyRNA rna_Scene_frame_preview_start;
+ extern PropertyRNA rna_Scene_frame_preview_end;
+ extern PropertyRNA rna_Scene_use_preview_range;
+ extern PropertyRNA rna_Scene_frame_current;
+ const PropertyRNA *props[] = {
+ use_preview ? &rna_Scene_frame_preview_start : &rna_Scene_frame_start,
+ use_preview ? &rna_Scene_frame_preview_end : &rna_Scene_frame_end,
+ &rna_Scene_use_preview_range,
+ &rna_Scene_frame_current,
+ };
+
+ PointerRNA idptr;
+ RNA_id_pointer_create(&scene->id, &idptr);
+
+ for (int i = 0; i < ARRAY_SIZE(props); i++) {
+ WM_msg_subscribe_rna(mbus, &idptr, props[i], &msg_sub_value_region_tag_redraw, __func__);
+ }
+ }
+
+ /* Now run the general "channels region" one - since channels and main should be in sync */
+ saction_channel_region_message_subscribe(C, workspace, scene, screen, sa, ar, mbus);
+}
+
/* editor level listener */
-static void action_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
+static void action_listener(
+ wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene))
{
SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
@@ -440,16 +569,43 @@ static void action_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
}
break;
case NC_SCENE:
- switch (wmn->data) {
- case ND_OB_ACTIVE: /* selection changed, so force refresh to flush (needs flag set to do syncing) */
- case ND_OB_SELECT:
- saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
- ED_area_tag_refresh(sa);
- break;
+ if (saction->mode == SACTCONT_TIMELINE) {
+ switch (wmn->data) {
+ case ND_RENDER_RESULT:
+ ED_area_tag_redraw(sa);
+ break;
+ case ND_OB_ACTIVE:
+ case ND_FRAME:
+ ED_area_tag_refresh(sa);
+ break;
+ case ND_FRAME_RANGE:
+ {
+ ARegion *ar;
+ Scene *scene = wmn->reference;
+
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ ar->v2d.tot.xmin = (float)(SFRA - 4);
+ ar->v2d.tot.xmax = (float)(EFRA + 4);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ else {
+ switch (wmn->data) {
+ case ND_OB_ACTIVE: /* selection changed, so force refresh to flush (needs flag set to do syncing) */
+ case ND_OB_SELECT:
+ saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
+ ED_area_tag_refresh(sa);
+ break;
- default: /* just redrawing the view will do */
- ED_area_tag_redraw(sa);
- break;
+ default: /* just redrawing the view will do */
+ ED_area_tag_redraw(sa);
+ break;
+ }
}
break;
case NC_OBJECT:
@@ -462,6 +618,15 @@ static void action_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
case ND_TRANSFORM:
/* moving object shouldn't need to redraw action */
break;
+ case ND_POINTCACHE:
+ case ND_MODIFIER:
+ case ND_PARTICLE:
+ /* only needed in timeline mode */
+ if (saction->mode == SACTCONT_TIMELINE) {
+ ED_area_tag_refresh(sa);
+ ED_area_tag_redraw(sa);
+ }
+ break;
default: /* just redrawing the view will do */
ED_area_tag_redraw(sa);
break;
@@ -492,6 +657,9 @@ static void action_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
case ND_SPACE_DOPESHEET:
ED_area_tag_redraw(sa);
break;
+ case ND_SPACE_TIME:
+ ED_area_tag_redraw(sa);
+ break;
case ND_SPACE_CHANGED:
saction->flag |= SACTION_TEMP_NEEDCHANSYNC;
ED_area_tag_refresh(sa);
@@ -504,20 +672,49 @@ static void action_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
ED_area_tag_refresh(sa);
}
break;
+ case NC_WM:
+ switch (wmn->data) {
+ case ND_FILEREAD:
+ ED_area_tag_refresh(sa);
+ break;
+ }
+ break;
}
}
-static void action_header_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void action_header_region_listener(
+ wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
- // SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
+ SpaceAction *saction = (SpaceAction *)sa->spacedata.first;
/* context changes */
switch (wmn->category) {
- case NC_SCENE:
- switch (wmn->data) {
- case ND_OB_ACTIVE:
+ case NC_SCREEN:
+ if (saction->mode == SACTCONT_TIMELINE) {
+ if (wmn->data == ND_ANIMPLAY)
ED_region_tag_redraw(ar);
- break;
+ }
+ break;
+ case NC_SCENE:
+ if (saction->mode == SACTCONT_TIMELINE) {
+ switch (wmn->data) {
+ case ND_RENDER_RESULT:
+ case ND_OB_SELECT:
+ case ND_FRAME:
+ case ND_FRAME_RANGE:
+ case ND_KEYINGSET:
+ case ND_RENDER_OPTIONS:
+ ED_region_tag_redraw(ar);
+ break;
+ }
+ }
+ else {
+ switch (wmn->data) {
+ case ND_OB_ACTIVE:
+ ED_region_tag_redraw(ar);
+ break;
+ }
}
break;
case NC_ID:
@@ -556,10 +753,12 @@ static void action_buttons_area_init(wmWindowManager *wm, ARegion *ar)
static void action_buttons_area_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
-static void action_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void action_region_listener(
+ wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -629,7 +828,7 @@ static void action_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, I
}
if ((ID *)sact->ads.filter_grp == old_id) {
- sact->ads.filter_grp = (Group *)new_id;
+ sact->ads.filter_grp = (Collection *)new_id;
}
if ((ID *)sact->ads.source == old_id) {
sact->ads.source = new_id;
@@ -637,6 +836,37 @@ static void action_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, I
}
+/**
+ * \note Used for splitting out a subset of modes is more involved,
+ * The previous non-timeline mode is stored so switching back to the
+ * dope-sheet doesn't always reset the sub-mode.
+ */
+static int action_space_subtype_get(ScrArea *sa)
+{
+ SpaceAction *sact = sa->spacedata.first;
+ return sact->mode == SACTCONT_TIMELINE ? SACTCONT_TIMELINE : SACTCONT_DOPESHEET;
+}
+
+static void action_space_subtype_set(ScrArea *sa, int value)
+{
+ SpaceAction *sact = sa->spacedata.first;
+ if (value == SACTCONT_TIMELINE) {
+ if (sact->mode != SACTCONT_TIMELINE) {
+ sact->mode_prev = sact->mode;
+ }
+ sact->mode = value;
+ }
+ else {
+ sact->mode = sact->mode_prev;
+ }
+}
+
+static void action_space_subtype_item_extend(
+ bContext *UNUSED(C), EnumPropertyItem **item, int *totitem)
+{
+ RNA_enum_items_add(item, totitem, rna_enum_space_action_mode_items);
+}
+
/* only called once, from space/spacetypes.c */
void ED_spacetype_action(void)
{
@@ -655,6 +885,9 @@ void ED_spacetype_action(void)
st->listener = action_listener;
st->refresh = action_refresh;
st->id_remap = action_id_remap;
+ st->space_subtype_item_extend = action_space_subtype_item_extend;
+ st->space_subtype_get = action_space_subtype_get;
+ st->space_subtype_set = action_space_subtype_set;
/* regions: main window */
art = MEM_callocN(sizeof(ARegionType), "spacetype action region");
@@ -662,6 +895,7 @@ void ED_spacetype_action(void)
art->init = action_main_region_init;
art->draw = action_main_region_draw;
art->listener = action_main_region_listener;
+ art->message_subscribe = saction_main_region_message_subscribe;
art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
@@ -687,6 +921,7 @@ void ED_spacetype_action(void)
art->init = action_channel_region_init;
art->draw = action_channel_region_draw;
art->listener = action_channel_region_listener;
+ art->message_subscribe = saction_channel_region_message_subscribe;
BLI_addhead(&st->regiontypes, art);