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_nla')
-rw-r--r--source/blender/editors/space_nla/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_nla/nla_buttons.c7
-rw-r--r--source/blender/editors/space_nla/nla_channels.c51
-rw-r--r--source/blender/editors/space_nla/nla_draw.c416
-rw-r--r--source/blender/editors/space_nla/nla_edit.c115
-rw-r--r--source/blender/editors/space_nla/nla_intern.h4
-rw-r--r--source/blender/editors/space_nla/nla_ops.c175
-rw-r--r--source/blender/editors/space_nla/nla_select.c84
-rw-r--r--source/blender/editors/space_nla/space_nla.c142
9 files changed, 525 insertions, 470 deletions
diff --git a/source/blender/editors/space_nla/CMakeLists.txt b/source/blender/editors/space_nla/CMakeLists.txt
index c8c64a79945..a6b80a9a587 100644
--- a/source/blender/editors/space_nla/CMakeLists.txt
+++ b/source/blender/editors/space_nla/CMakeLists.txt
@@ -23,6 +23,7 @@ set(INC
../../blenkernel
../../blenlib
../../blentranslation
+ ../../depsgraph
../../gpu
../../makesdna
../../makesrna
diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c
index 63eb0e361bf..d5d50c86851 100644
--- a/source/blender/editors/space_nla/nla_buttons.c
+++ b/source/blender/editors/space_nla/nla_buttons.c
@@ -145,6 +145,7 @@ bool nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA *nlt_p
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
case ANIMTYPE_DSGPENCIL:
+ case ANIMTYPE_PALETTE:
{
/* for these channels, we only do AnimData */
if (ale->adt && adt_ptr) {
@@ -276,7 +277,7 @@ static void nla_panel_animdata(const bContext *C, Panel *pa)
uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT);
uiItemL(row, id->name + 2, RNA_struct_ui_icon(id_ptr.type)); /* id-block (src) */
- uiItemL(row, "", VICO_SMALL_TRI_RIGHT_VEC); /* expander */
+ uiItemL(row, "", ICON_SMALL_TRI_RIGHT_VEC); /* expander */
uiItemL(row, IFACE_("Animation Data"), ICON_ANIM_DATA); /* animdata */
uiItemS(layout);
@@ -287,7 +288,7 @@ static void nla_panel_animdata(const bContext *C, Panel *pa)
row = uiLayoutRow(layout, true);
uiTemplateID(
row, (bContext *)C, &adt_ptr, "action",
- "ACTION_OT_new", NULL, "NLA_OT_action_unlink", UI_TEMPLATE_ID_FILTER_ALL);
+ "ACTION_OT_new", NULL, "NLA_OT_action_unlink", UI_TEMPLATE_ID_FILTER_ALL, false);
/* extrapolation */
row = uiLayoutRow(layout, true);
@@ -574,7 +575,7 @@ static int nla_properties_toggle_exec(bContext *C, wmOperator *UNUSED(op))
void NLA_OT_properties(wmOperatorType *ot)
{
- ot->name = "Properties";
+ ot->name = "Toggle Sidebar";
ot->idname = "NLA_OT_properties";
ot->description = "Toggle the properties region visibility";
diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c
index 103b0664a23..9f634851c81 100644
--- a/source/blender/editors/space_nla/nla_channels.c
+++ b/source/blender/editors/space_nla/nla_channels.c
@@ -45,6 +45,7 @@
#include "BKE_nla.h"
#include "BKE_context.h"
#include "BKE_global.h"
+#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_report.h"
@@ -59,6 +60,9 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "UI_view2d.h"
#include "nla_intern.h" // own include
@@ -123,40 +127,37 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
}
case ANIMTYPE_OBJECT:
{
- bDopeSheet *ads = (bDopeSheet *)ac->data;
- Scene *sce = (Scene *)ads->source;
+ ViewLayer *view_layer = ac->view_layer;
Base *base = (Base *)ale->data;
Object *ob = base->object;
AnimData *adt = ob->adt;
- if (nlaedit_is_tweakmode_on(ac) == 0 && (ob->restrictflag & OB_RESTRICT_SELECT) == 0) {
+ if (nlaedit_is_tweakmode_on(ac) == 0 && (base->flag & BASE_SELECTABLE)) {
/* set selection status */
if (selectmode == SELECT_INVERT) {
/* swap select */
- base->flag ^= SELECT;
- ob->flag = base->flag;
+ ED_object_base_select(base, BA_INVERT);
+ BKE_scene_object_base_flag_sync_from_base(base);
if (adt) adt->flag ^= ADT_UI_SELECTED;
}
else {
- Base *b;
-
/* deselect all */
/* TODO: should this deselect all other types of channels too? */
- for (b = sce->base.first; b; b = b->next) {
- b->flag &= ~SELECT;
- b->object->flag = b->flag;
+ for (Base *b = view_layer->object_bases.first; b; b = b->next) {
+ ED_object_base_select(b, BA_DESELECT);
+ BKE_scene_object_base_flag_sync_from_base(b);
if (b->object->adt) b->object->adt->flag &= ~(ADT_UI_SELECTED | ADT_UI_ACTIVE);
}
/* select object now */
- base->flag |= SELECT;
- ob->flag |= SELECT;
+ ED_object_base_select(base, BA_SELECT);
+ BKE_scene_object_base_flag_sync_from_base(base);
if (adt) adt->flag |= ADT_UI_SELECTED;
}
/* change active object - regardless of whether it is now selected [T37883] */
- ED_base_object_activate(C, base); /* adds notifier */
+ ED_object_base_activate(C, base); /* adds notifier */
if ((adt) && (adt->flag & ADT_UI_SELECTED))
adt->flag |= ADT_UI_ACTIVE;
@@ -184,6 +185,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
case ANIMTYPE_DSLINESTYLE:
case ANIMTYPE_DSSPK:
case ANIMTYPE_DSGPENCIL:
+ case ANIMTYPE_PALETTE:
{
/* sanity checking... */
if (ale->adt) {
@@ -236,6 +238,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
/* notifier flags - channel was edited */
notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+ ale->update |= ANIM_UPDATE_DEPS;
}
else if (x <= ((NLACHANNEL_BUTTON_WIDTH * 2) + offset)) {
/* toggle 'solo' */
@@ -243,6 +246,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
/* notifier flags - channel was edited */
notifierFlags |= (ND_ANIMCHAN | NA_EDITED);
+ ale->update |= ANIM_UPDATE_DEPS;
}
else if (nlaedit_is_tweakmode_on(ac) == 0) {
/* set selection */
@@ -285,6 +289,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
/* changes to NLA-Action occurred */
notifierFlags |= ND_NLA_ACTCHANGE;
+ ale->update |= ANIM_UPDATE_DEPS;
}
/* OR rest of name... */
else {
@@ -302,6 +307,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
/* changes to NLA-Action occurred */
notifierFlags |= ND_NLA_ACTCHANGE;
+ ale->update |= ANIM_UPDATE_DEPS;
}
else {
/* select/deselect */
@@ -331,6 +337,7 @@ static int mouse_nla_channels(bContext *C, bAnimContext *ac, float x, int channe
}
/* free channels */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* return the notifier-flags set */
@@ -412,6 +419,7 @@ void NLA_OT_channels_click(wmOperatorType *ot)
static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
+ ID *id = NULL;
AnimData *adt = NULL;
int channel_index = RNA_int_get(op->ptr, "channel_index");
@@ -430,6 +438,7 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
else {
+ id = adt_ptr.id.data;
adt = adt_ptr.data;
}
}
@@ -458,6 +467,7 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
/* grab AnimData from the channel */
adt = ale->adt;
+ id = ale->id;
/* we don't need anything here anymore, so free it all */
ANIM_animdata_freelist(&anim_data);
@@ -480,6 +490,8 @@ static int nlachannels_pushdown_exec(bContext *C, wmOperator *op)
else {
/* 'push-down' action - only usable when not in TweakMode */
BKE_nla_action_pushdown(adt);
+
+ DEG_id_tag_update_ex(CTX_data_main(C), id, DEG_TAG_TIME | DEG_TAG_COPY_ON_WRITE);
}
/* set notifier that things have changed */
@@ -598,18 +610,21 @@ bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel)
if (above_sel) {
/* just add a new one above this one */
BKE_nlatrack_add(adt, nlt);
+ ale->update = ANIM_UPDATE_DEPS;
added = true;
}
else if ((lastAdt == NULL) || (adt != lastAdt)) {
/* add one track to the top of the owning AnimData's stack, then don't add anymore to this stack */
BKE_nlatrack_add(adt, NULL);
lastAdt = adt;
+ ale->update = ANIM_UPDATE_DEPS;
added = true;
}
}
}
/* free temp data */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
return added;
@@ -638,11 +653,13 @@ bool nlaedit_add_tracks_empty(bAnimContext *ac)
if (BLI_listbase_is_empty(&adt->nla_tracks)) {
/* add new track to this AnimData block then */
BKE_nlatrack_add(adt, NULL);
+ ale->update = ANIM_UPDATE_DEPS;
added = true;
}
}
/* cleanup */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
return added;
@@ -666,6 +683,8 @@ static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op)
/* done? */
if (op_done) {
+ DEG_relations_tag_update(CTX_data_main(C));
+
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
@@ -732,13 +751,17 @@ static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op))
adt->flag &= ~ADT_NLA_SOLO_TRACK;
/* call delete on this track - deletes all strips too */
- BKE_nlatrack_free(&adt->nla_tracks, nlt);
+ BKE_nlatrack_free(&adt->nla_tracks, nlt, true);
+ ale->update = ANIM_UPDATE_DEPS;
}
}
/* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
+ DEG_relations_tag_update(ac.bmain);
+
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c
index ea35c583913..2cba6cf2fb2 100644
--- a/source/blender/editors/space_nla/nla_draw.c
+++ b/source/blender/editors/space_nla/nla_draw.c
@@ -53,9 +53,13 @@
#include "ED_anim_api.h"
#include "ED_keyframes_draw.h"
-#include "BIF_gl.h"
#include "BIF_glutil.h"
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_draw.h"
+#include "GPU_state.h"
+
#include "WM_types.h"
#include "UI_interface.h"
@@ -97,17 +101,12 @@ void nla_action_get_color(AnimData *adt, bAction *act, float color[4])
}
/* draw the keyframes in the specified Action */
-static void nla_action_draw_keyframes(AnimData *adt, bAction *act, View2D *v2d, float y, float ymin, float ymax)
+static void nla_action_draw_keyframes(View2D *v2d, AnimData *adt, bAction *act, float y, float ymin, float ymax)
{
- DLRBT_Tree keys;
- ActKeyColumn *ak;
- float xscale, f1, f2;
- float color[4];
-
/* get a list of the keyframes with NLA-scaling applied */
+ DLRBT_Tree keys;
BLI_dlrbTree_init(&keys);
- action_to_keylist(adt, act, &keys, NULL);
- BLI_dlrbTree_linkedlist_sync(&keys);
+ action_to_keylist(adt, act, &keys, 0);
if (ELEM(NULL, act, keys.first))
return;
@@ -116,30 +115,55 @@ static void nla_action_draw_keyframes(AnimData *adt, bAction *act, View2D *v2d,
* - get and reset the background color, this time without the alpha to stand out better
* (amplified alpha is used instead)
*/
+ float color[4];
nla_action_get_color(adt, act, color);
color[3] *= 2.5f;
- glColor4fv(color);
- /* - draw a rect from the first to the last frame (no extra overlaps for now)
- * that is slightly stumpier than the track background (hardcoded 2-units here)
- */
- f1 = ((ActKeyColumn *)keys.first)->cfra;
- f2 = ((ActKeyColumn *)keys.last)->cfra;
-
- glRectf(f1, ymin + 2, f2, ymax - 2);
-
+ GPUVertFormat *format = immVertexFormat();
+ uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- /* get View2D scaling factor */
- UI_view2d_scale_get(v2d, &xscale, NULL);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
- /* for now, color is hardcoded to be black */
- glColor3f(0.0f, 0.0f, 0.0f);
+ immUniformColor4fv(color);
- /* just draw each keyframe as a simple dot (regardless of the selection status)
- * - size is 3.0f which is smaller than the editable keyframes, so that there is a distinction
+ /* - draw a rect from the first to the last frame (no extra overlaps for now)
+ * that is slightly stumpier than the track background (hardcoded 2-units here)
*/
- for (ak = keys.first; ak; ak = ak->next)
- draw_keyframe_shape(ak->cfra, y, xscale, 3.0f, 0, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f);
+ float f1 = ((ActKeyColumn *)keys.first)->cfra;
+ float f2 = ((ActKeyColumn *)keys.last)->cfra;
+
+ immRectf(pos_id, f1, ymin + 2, f2, ymax - 2);
+ immUnbindProgram();
+
+ /* count keys before drawing */
+ /* Note: It's safe to cast DLRBT_Tree, as it's designed to degrade down to a ListBase */
+ uint key_len = BLI_listbase_count((ListBase *)&keys);
+
+ if (key_len > 0) {
+ format = immVertexFormat();
+ pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+ uint color_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint outline_color_id = GPU_vertformat_attr_add(format, "outlineColor", GPU_COMP_U8, 4, GPU_FETCH_INT_TO_FLOAT_UNIT);
+ uint flags_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT);
+ immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND);
+ GPU_enable_program_point_size();
+ immUniform2f("ViewportSize", BLI_rcti_size_x(&v2d->mask) + 1, BLI_rcti_size_y(&v2d->mask) + 1);
+ immBegin(GPU_PRIM_POINTS, key_len);
+
+ /* - disregard the selection status of keyframes so they draw a certain way
+ * - size is 6.0f which is smaller than the editable keyframes, so that there is a distinction
+ */
+ for (ActKeyColumn *ak = keys.first; ak; ak = ak->next) {
+ draw_keyframe_shape(ak->cfra, y, 6.0f, false, ak->key_type, KEYFRAME_SHAPE_FRAME, 1.0f,
+ pos_id, size_id, color_id, outline_color_id,
+ flags_id, KEYFRAME_HANDLE_NONE, KEYFRAME_EXTREME_NONE);
+ }
+
+ immEnd();
+ GPU_disable_program_point_size();
+ immUnbindProgram();
+ }
/* free icons */
BLI_dlrbTree_free(&keys);
@@ -148,57 +172,70 @@ static void nla_action_draw_keyframes(AnimData *adt, bAction *act, View2D *v2d,
/* Strip Markers ------------------------ */
/* Markers inside an action strip */
-static void nla_actionclip_draw_markers(NlaStrip *strip, float yminc, float ymaxc)
+static void nla_actionclip_draw_markers(NlaStrip *strip, float yminc, float ymaxc, int shade, const bool dashed)
{
- bAction *act = strip->act;
- TimeMarker *marker;
+ const bAction *act = strip->act;
- if (ELEM(NULL, strip->act, strip->act->markers.first))
+ if (ELEM(NULL, act, act->markers.first))
return;
- for (marker = act->markers.first; marker; marker = marker->next) {
+ const uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ if (dashed) {
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("colors_len", 0); /* "simple" mode */
+ immUniform1f("dash_width", 6.0f);
+ immUniform1f("dash_factor", 0.5f);
+ }
+ else {
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ }
+ immUniformThemeColorShade(TH_STRIP_SELECT, shade);
+
+ immBeginAtMost(GPU_PRIM_LINES, BLI_listbase_count(&act->markers) * 2);
+ for (TimeMarker *marker = act->markers.first; marker; marker = marker->next) {
if ((marker->frame > strip->actstart) && (marker->frame < strip->actend)) {
float frame = nlastrip_get_frame(strip, marker->frame, NLATIME_CONVERT_MAP);
/* just a simple line for now */
- // XXX: draw a triangle instead...
- fdrawline(frame, yminc + 1, frame, ymaxc - 1);
+ /* XXX: draw a triangle instead... */
+ immVertex2f(shdr_pos, frame, yminc + 1);
+ immVertex2f(shdr_pos, frame, ymaxc - 1);
}
}
+ immEnd();
+
+ immUnbindProgram();
}
/* Markers inside a NLA-Strip */
static void nla_strip_draw_markers(NlaStrip *strip, float yminc, float ymaxc)
{
- glLineWidth(2.0);
+ GPU_line_width(2.0f);
if (strip->type == NLASTRIP_TYPE_CLIP) {
/* try not to be too conspicuous, while being visible enough when transforming */
- if (strip->flag & NLASTRIP_FLAG_SELECT)
- UI_ThemeColorShade(TH_STRIP_SELECT, -60);
- else
- UI_ThemeColorShade(TH_STRIP_SELECT, -40);
-
- setlinestyle(3);
+ int shade = (strip->flag & NLASTRIP_FLAG_SELECT) ? -60 : -40;
/* just draw the markers in this clip */
- nla_actionclip_draw_markers(strip, yminc, ymaxc);
-
- setlinestyle(0);
+ nla_actionclip_draw_markers(strip, yminc, ymaxc, shade, true);
}
else if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
/* just a solid color, so that it is very easy to spot */
- UI_ThemeColorShade(TH_STRIP_SELECT, 20);
-
+ int shade = 20;
/* draw the markers in the first level of strips only (if they are actions) */
for (NlaStrip *nls = strip->strips.first; nls; nls = nls->next) {
if (nls->type == NLASTRIP_TYPE_CLIP) {
- nla_actionclip_draw_markers(nls, yminc, ymaxc);
+ nla_actionclip_draw_markers(nls, yminc, ymaxc, shade, false);
}
}
}
- glLineWidth(1.0);
+ GPU_line_width(1.0f);
}
/* Strips (Proper) ---------------------- */
@@ -266,18 +303,15 @@ static void nla_strip_get_color_inside(AnimData *adt, NlaStrip *strip, float col
}
/* helper call for drawing influence/time control curves for a given NLA-strip */
-static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc)
+static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc, unsigned int pos)
{
const float yheight = ymaxc - yminc;
- /* drawing color is simply a light-gray */
- // TODO: is this color suitable?
- // XXX nasty hacked color for now... which looks quite bad too...
- glColor3f(0.7f, 0.7f, 0.7f);
+ immUniformColor3f(0.7f, 0.7f, 0.7f);
/* draw with AA'd line */
- glEnable(GL_LINE_SMOOTH);
- glEnable(GL_BLEND);
+ GPU_line_smooth(true);
+ GPU_blend(true);
/* influence -------------------------- */
if (strip->flag & NLASTRIP_FLAG_USR_INFLUENCE) {
@@ -286,67 +320,101 @@ static void nla_draw_strip_curves(NlaStrip *strip, float yminc, float ymaxc)
/* plot the curve (over the strip's main region) */
if (fcu) {
- glBegin(GL_LINE_STRIP);
+ immBegin(GPU_PRIM_LINE_STRIP, abs((int)(strip->end - strip->start) + 1));
/* sample at 1 frame intervals, and draw
* - min y-val is yminc, max is y-maxc, so clamp in those regions
*/
for (cfra = strip->start; cfra <= strip->end; cfra += 1.0f) {
- float y = evaluate_fcurve(fcu, cfra);
+ float y = evaluate_fcurve(fcu, cfra); /* assume this to be in 0-1 range */
CLAMP(y, 0.0f, 1.0f);
- glVertex2f(cfra, ((y * yheight) + yminc));
+ immVertex2f(pos, cfra, ((y * yheight) + yminc));
}
- glEnd(); // GL_LINE_STRIP
+ immEnd();
}
}
else {
/* use blend in/out values only if both aren't zero */
if ((IS_EQF(strip->blendin, 0.0f) && IS_EQF(strip->blendout, 0.0f)) == 0) {
- glBegin(GL_LINE_STRIP);
+ immBeginAtMost(GPU_PRIM_LINE_STRIP, 4);
+
/* start of strip - if no blendin, start straight at 1, otherwise from 0 to 1 over blendin frames */
if (IS_EQF(strip->blendin, 0.0f) == 0) {
- glVertex2f(strip->start, yminc);
- glVertex2f(strip->start + strip->blendin, ymaxc);
+ immVertex2f(pos, strip->start, yminc);
+ immVertex2f(pos, strip->start + strip->blendin, ymaxc);
}
else
- glVertex2f(strip->start, ymaxc);
+ immVertex2f(pos, strip->start, ymaxc);
/* end of strip */
if (IS_EQF(strip->blendout, 0.0f) == 0) {
- glVertex2f(strip->end - strip->blendout, ymaxc);
- glVertex2f(strip->end, yminc);
+ immVertex2f(pos, strip->end - strip->blendout, ymaxc);
+ immVertex2f(pos, strip->end, yminc);
}
else
- glVertex2f(strip->end, ymaxc);
- glEnd(); // GL_LINE_STRIP
+ immVertex2f(pos, strip->end, ymaxc);
+
+ immEnd();
}
}
- /* time -------------------------- */
- // XXX do we want to draw this curve? in a different color too?
-
/* turn off AA'd lines */
- glDisable(GL_LINE_SMOOTH);
- glDisable(GL_BLEND);
+ GPU_line_smooth(false);
+ GPU_blend(false);
+}
+
+/* helper call to setup dashed-lines for strip outlines */
+static uint nla_draw_use_dashed_outlines(float color[4], bool muted)
+{
+ /* Note that we use dashed shader here, and make it draw solid lines if not muted... */
+ uint shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_LINE_DASHED_UNIFORM_COLOR);
+
+ float viewport_size[4];
+ GPU_viewport_size_get_f(viewport_size);
+ immUniform2f("viewport_size", viewport_size[2] / UI_DPI_FAC, viewport_size[3] / UI_DPI_FAC);
+
+ immUniform1i("colors_len", 0); /* Simple dashes. */
+ immUniformColor3fv(color);
+
+ /* line style: dotted for muted */
+ if (muted) {
+ /* dotted - and slightly thicker for readability of the dashes */
+ immUniform1f("dash_width", 5.0f);
+ immUniform1f("dash_factor", 0.4f);
+ GPU_line_width(1.5f);
+ }
+ else {
+ /* solid line */
+ immUniform1f("dash_factor", 2.0f);
+ GPU_line_width(1.0f);
+ }
+
+ return shdr_pos;
}
/* main call for drawing a single NLA-strip */
static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStrip *strip, View2D *v2d, float yminc, float ymaxc)
{
const bool non_solo = ((adt && (adt->flag & ADT_NLA_SOLO_TRACK)) && (nlt->flag & NLATRACK_SOLO) == 0);
- float color[3];
+ const bool muted = ((nlt->flag & NLATRACK_MUTED) || (strip->flag & NLASTRIP_FLAG_MUTED));
+ float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
+ uint shdr_pos;
/* get color of strip */
nla_strip_get_color_inside(adt, strip, color);
+ shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+
/* draw extrapolation info first (as backdrop)
* - but this should only be drawn if track has some contribution
*/
if ((strip->extendmode != NLASTRIP_EXTEND_NOTHING) && (non_solo == 0)) {
/* enable transparency... */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
switch (strip->extendmode) {
/* since this does both sides, only do the 'before' side, and leave the rest to the next case */
@@ -356,15 +424,10 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
*/
if (strip->prev == NULL) {
/* set the drawing color to the color of the strip, but with very faint alpha */
- glColor4f(color[0], color[1], color[2], 0.15f);
+ immUniformColor3fvAlpha(color, 0.15f);
/* draw the rect to the edge of the screen */
- glBegin(GL_QUADS);
- glVertex2f(v2d->cur.xmin, yminc);
- glVertex2f(v2d->cur.xmin, ymaxc);
- glVertex2f(strip->start, ymaxc);
- glVertex2f(strip->start, yminc);
- glEnd();
+ immRectf(shdr_pos, v2d->cur.xmin, yminc, strip->start, ymaxc);
}
ATTR_FALLTHROUGH;
@@ -373,45 +436,38 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
/* only need to try and draw if the next strip doesn't occur immediately after */
if ((strip->next == NULL) || (IS_EQF(strip->next->start, strip->end) == 0)) {
/* set the drawing color to the color of the strip, but this time less faint */
- glColor4f(color[0], color[1], color[2], 0.3f);
+ immUniformColor3fvAlpha(color, 0.3f);
/* draw the rect to the next strip or the edge of the screen */
- glBegin(GL_QUADS);
- glVertex2f(strip->end, yminc);
- glVertex2f(strip->end, ymaxc);
-
- if (strip->next) {
- glVertex2f(strip->next->start, ymaxc);
- glVertex2f(strip->next->start, yminc);
- }
- else {
- glVertex2f(v2d->cur.xmax, ymaxc);
- glVertex2f(v2d->cur.xmax, yminc);
- }
- glEnd();
+ float x2 = strip->next ? strip->next->start : v2d->cur.xmax;
+ immRectf(shdr_pos, strip->end, yminc, x2, ymaxc);
}
break;
}
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
/* draw 'inside' of strip itself */
if (non_solo == 0) {
+ immUnbindProgram();
+
/* strip is in normal track */
- glColor3fv(color);
UI_draw_roundbox_corner_set(UI_CNR_ALL); /* all corners rounded */
+ UI_draw_roundbox_shade_x(true, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1, color);
- UI_draw_roundbox_shade_x(GL_POLYGON, strip->start, yminc, strip->end, ymaxc, 0.0, 0.5, 0.1);
+ /* restore current vertex format & program (roundbox trashes it) */
+ shdr_pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
}
else {
/* strip is in disabled track - make less visible */
- glColor4f(color[0], color[1], color[2], 0.1f);
+ immUniformColor3fvAlpha(color, 0.1f);
- glEnable(GL_BLEND);
- glRectf(strip->start, yminc, strip->end, ymaxc);
- glDisable(GL_BLEND);
+ GPU_blend(true);
+ immRectf(shdr_pos, strip->start, yminc, strip->end, ymaxc);
+ GPU_blend(false);
}
@@ -419,8 +475,9 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
* - only if user hasn't hidden them...
*/
if ((snla->flag & SNLA_NOSTRIPCURVES) == 0)
- nla_draw_strip_curves(strip, yminc, ymaxc);
+ nla_draw_strip_curves(strip, yminc, ymaxc, shdr_pos);
+ immUnbindProgram();
/* draw markings indicating locations of local markers (useful for lining up different actions) */
if ((snla->flag & SNLA_NOLOCALMARKERS) == 0)
@@ -431,59 +488,79 @@ static void nla_draw_strip(SpaceNla *snla, AnimData *adt, NlaTrack *nlt, NlaStri
*/
if (strip->flag & NLASTRIP_FLAG_ACTIVE) {
/* strip should appear 'sunken', so draw a light border around it */
- glColor3f(0.9f, 1.0f, 0.9f); // FIXME: hardcoded temp-hack colors
+ color[0] = 0.9f; /* FIXME: hardcoded temp-hack colors */
+ color[1] = 1.0f;
+ color[2] = 0.9f;
}
else {
/* strip should appear to stand out, so draw a dark border around it */
- glColor3f(0.0f, 0.0f, 0.0f);
+ color[0] = color[1] = color[2] = 0.0f; /* FIXME: or 1.0f ?? */
}
- /* - line style: dotted for muted */
- if ((nlt->flag & NLATRACK_MUTED) || (strip->flag & NLASTRIP_FLAG_MUTED))
- setlinestyle(4);
+ /* draw outline
+ * - dashed-line shader is loaded after this block
+ */
+ if (muted) {
+ /* muted - draw dotted, squarish outline (for simplicity) */
+ shdr_pos = nla_draw_use_dashed_outlines(color, muted);
+ imm_draw_box_wire_2d(shdr_pos, strip->start, yminc, strip->end, ymaxc);
+ }
+ else {
+ /* non-muted - draw solid, rounded outline */
+ UI_draw_roundbox_shade_x(false, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1, color);
- /* draw outline */
- UI_draw_roundbox_shade_x(GL_LINE_LOOP, strip->start, yminc, strip->end, ymaxc, 0.0, 0.0, 0.1);
+ /* restore current vertex format & program (roundbox trashes it) */
+ shdr_pos = nla_draw_use_dashed_outlines(color, muted);
+ }
/* if action-clip strip, draw lines delimiting repeats too (in the same color as outline) */
- if ((strip->type == NLASTRIP_TYPE_CLIP) && IS_EQF(strip->repeat, 1.0f) == 0) {
+ if ((strip->type == NLASTRIP_TYPE_CLIP) && strip->repeat > 1.0f) {
float repeatLen = (strip->actend - strip->actstart) * strip->scale;
- int i;
/* only draw lines for whole-numbered repeats, starting from the first full-repeat
* up to the last full repeat (but not if it lies on the end of the strip)
*/
- for (i = 1; i < strip->repeat; i++) {
+ immBeginAtMost(GPU_PRIM_LINES, 2 * floorf(strip->repeat));
+ for (int i = 1; i < strip->repeat; i++) {
float repeatPos = strip->start + (repeatLen * i);
/* don't draw if line would end up on or after the end of the strip */
- if (repeatPos < strip->end)
- fdrawline(repeatPos, yminc + 4, repeatPos, ymaxc - 4);
+ if (repeatPos < strip->end) {
+ immVertex2f(shdr_pos, repeatPos, yminc + 4);
+ immVertex2f(shdr_pos, repeatPos, ymaxc - 4);
+ }
}
+ immEnd();
}
/* or if meta-strip, draw lines delimiting extents of sub-strips (in same color as outline, if more than 1 exists) */
else if ((strip->type == NLASTRIP_TYPE_META) && (strip->strips.first != strip->strips.last)) {
- NlaStrip *cs;
- float y = (ymaxc - yminc) / 2.0f + yminc;
+ const float y = (ymaxc - yminc) * 0.5f + yminc;
+
+ immBeginAtMost(GPU_PRIM_LINES, 4 * BLI_listbase_count(&strip->strips)); /* up to 2 lines per strip */
/* only draw first-level of child-strips, but don't draw any lines on the endpoints */
- for (cs = strip->strips.first; cs; cs = cs->next) {
+ for (NlaStrip *cs = strip->strips.first; cs; cs = cs->next) {
/* draw start-line if not same as end of previous (and only if not the first strip)
* - on upper half of strip
*/
- if ((cs->prev) && IS_EQF(cs->prev->end, cs->start) == 0)
- fdrawline(cs->start, y, cs->start, ymaxc);
+ if ((cs->prev) && IS_EQF(cs->prev->end, cs->start) == 0) {
+ immVertex2f(shdr_pos, cs->start, y);
+ immVertex2f(shdr_pos, cs->start, ymaxc);
+ }
/* draw end-line if not the last strip
* - on lower half of strip
*/
- if (cs->next)
- fdrawline(cs->end, yminc, cs->end, y);
+ if (cs->next) {
+ immVertex2f(shdr_pos, cs->end, yminc);
+ immVertex2f(shdr_pos, cs->end, y);
+ }
}
+
+ immEnd();
}
- /* reset linestyle */
- setlinestyle(0);
+ immUnbindProgram();
}
/* add the relevant text to the cache of text-strings to draw in pixelspace */
@@ -495,7 +572,6 @@ static void nla_draw_strip_text(
char str[256];
size_t str_len;
char col[4];
- rctf rect;
/* just print the name and the range */
if (strip->flag & NLASTRIP_FLAG_TEMP_META) {
@@ -522,11 +598,13 @@ static void nla_draw_strip_text(
/* set bounding-box for text
* - padding of 2 'units' on either side
*/
- // TODO: make this centered?
- rect.xmin = xminc;
- rect.ymin = yminc;
- rect.xmax = xmaxc;
- rect.ymax = ymaxc;
+ /* TODO: make this centered? */
+ rctf rect = {
+ .xmin = xminc,
+ .ymin = yminc,
+ .xmax = xmaxc,
+ .ymax = ymaxc
+ };
/* add this string to the cache of texts to draw */
UI_view2d_text_cache_add_rectf(v2d, &rect, str, str_len, col);
@@ -542,7 +620,6 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V
char numstr[32];
size_t numstr_len;
-
/* Always draw times above the strip, whereas sequencer drew below + above.
* However, we should be fine having everything on top, since these tend to be
* quite spaced out.
@@ -562,20 +639,14 @@ static void nla_draw_strip_frames_text(NlaTrack *UNUSED(nlt), NlaStrip *strip, V
void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
{
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-
View2D *v2d = &ar->v2d;
- float y = 0.0f;
- size_t items;
- int height;
const float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
const float text_margin_x = (8 * UI_DPI_FAC) * pixelx;
/* 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);
+ ListBase anim_data = {NULL, NULL};
+ 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);
/* Update max-extent of channels here (taking into account scrollers):
* - this is done to allow the channel list to be scrollable, but must be done here
@@ -583,16 +654,17 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
* - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
* start of list offset, and the second is as a correction for the scrollers.
*/
- height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
+ int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
+
/* don't use totrect set, as the width stays the same
* (NOTE: this is ok here, the configuration is pretty straightforward)
*/
v2d->tot.ymin = (float)(-height);
/* loop through channels, and set up drawing depending on their type */
- y = (float)(-NLACHANNEL_HEIGHT(snla));
+ float y = (float)(-NLACHANNEL_HEIGHT(snla));
- for (ale = anim_data.first; ale; ale = ale->next) {
+ for (bAnimListElem *ale = anim_data.first; ale; ale = ale->next) {
const float yminc = (float)(y - NLACHANNEL_HEIGHT_HALF(snla));
const float ymaxc = (float)(y + NLACHANNEL_HEIGHT_HALF(snla));
@@ -635,40 +707,55 @@ void draw_nla_main_data(bAnimContext *ac, SpaceNla *snla, ARegion *ar)
case ANIMTYPE_NLAACTION:
{
AnimData *adt = ale->adt;
- float color[4];
+
+ uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
/* just draw a semi-shaded rect spanning the width of the viewable area if there's data,
* and a second darker rect within which we draw keyframe indicator dots if there's data
*/
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
/* get colors for drawing */
+ float color[4];
nla_action_get_color(adt, ale->data, color);
- glColor4fv(color);
+ immUniformColor4fv(color);
/* draw slightly shifted up for greater separation from standard channels,
* but also slightly shorter for some more contrast when viewing the strips
*/
- glRectf(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
-
- /* draw keyframes in the action */
- nla_action_draw_keyframes(adt, ale->data, v2d, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP);
+ immRectf(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
/* draw 'embossed' lines above and below the strip for effect */
/* white base-lines */
- glLineWidth(2.0f);
- glColor4f(1.0f, 1.0f, 1.0f, 0.3);
- fdrawline(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
- fdrawline(v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
+ GPU_line_width(2.0f);
+ immUniformColor4f(1.0f, 1.0f, 1.0f, 0.3f);
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
+ immEnd();
/* black top-lines */
- glLineWidth(1.0f);
- glColor3f(0.0f, 0.0f, 0.0f);
- fdrawline(v2d->cur.xmin, yminc + NLACHANNEL_SKIP, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
- fdrawline(v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
+ GPU_line_width(1.0f);
+ immUniformColor3f(0.0f, 0.0f, 0.0f);
+ immBegin(GPU_PRIM_LINES, 4);
+ immVertex2f(pos, v2d->cur.xmin, yminc + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, yminc + NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmin, ymaxc - NLACHANNEL_SKIP);
+ immVertex2f(pos, v2d->cur.xmax, ymaxc - NLACHANNEL_SKIP);
+ immEnd();
+
+ /* TODO: these lines but better --^ */
+
+ immUnbindProgram();
+
+ /* draw keyframes in the action */
+ nla_action_draw_keyframes(v2d, adt, ale->data, y, yminc + NLACHANNEL_SKIP, ymaxc - NLACHANNEL_SKIP);
- glDisable(GL_BLEND);
+ GPU_blend(false);
break;
}
}
@@ -695,7 +782,6 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
View2D *v2d = &ar->v2d;
float y = 0.0f;
size_t items;
- int height;
/* build list of channels to draw */
filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_LIST_CHANNELS);
@@ -707,7 +793,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
* - offset of NLACHANNEL_HEIGHT*2 is added to the height of the channels, as first is for
* start of list offset, and the second is as a correction for the scrollers.
*/
- height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
+ int height = ((items * NLACHANNEL_STEP(snla)) + (NLACHANNEL_HEIGHT(snla) * 2));
/* don't use totrect set, as the width stays the same
* (NOTE: this is ok here, the configuration is pretty straightforward)
*/
@@ -745,8 +831,8 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
y = (float)(-NLACHANNEL_HEIGHT(snla));
/* set blending again, as may not be set in previous step */
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glEnable(GL_BLEND);
+ GPU_blend_set_func_separate(GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA);
+ GPU_blend(true);
/* loop through channels, and set up drawing depending on their type */
for (ale = anim_data.first; ale; ale = ale->next) {
@@ -769,7 +855,7 @@ void draw_nla_channel_list(const bContext *C, bAnimContext *ac, ARegion *ar)
UI_block_end(C, block);
UI_block_draw(C, block);
- glDisable(GL_BLEND);
+ GPU_blend(false);
}
/* free temporary channels */
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index 5cf3ace747b..3cab4cfefca 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -46,11 +46,11 @@
#include "BLT_translation.h"
#include "BKE_action.h"
-#include "BKE_fcurve.h"
-#include "BKE_nla.h"
#include "BKE_context.h"
+#include "BKE_fcurve.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_nla.h"
#include "BKE_report.h"
#include "BKE_screen.h"
@@ -67,6 +67,8 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "DEG_depsgraph_build.h"
+
#include "UI_interface.h"
#include "UI_resources.h"
#include "UI_view2d.h"
@@ -90,9 +92,12 @@ void ED_nla_postop_refresh(bAnimContext *ac)
for (ale = anim_data.first; ale; ale = ale->next) {
/* performing auto-blending, extend-mode validation, etc. */
BKE_nla_validate_state(ale->data);
+
+ ale->update |= ANIM_UPDATE_DEPS;
}
/* free temp memory */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
}
@@ -144,9 +149,12 @@ static int nlaedit_enable_tweakmode_exec(bContext *C, wmOperator *op)
BKE_nlatrack_solo_toggle(adt, nlt);
}
}
+
+ ale->update |= ANIM_UPDATE_DEPS;
}
/* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* if we managed to enter tweakmode on at least one AnimData block,
@@ -223,9 +231,12 @@ bool nlaedit_disable_tweakmode(bAnimContext *ac, bool do_solo)
/* to be sure that we're doing everything right, just exit tweakmode... */
BKE_nla_tweakmode_exit(adt);
+
+ ale->update |= ANIM_UPDATE_DEPS;
}
/* free temp data */
+ ANIM_animdata_update(ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* if we managed to enter tweakmode on at least one AnimData block,
@@ -669,6 +680,8 @@ static int nlaedit_add_actionclip_exec(bContext *C, wmOperator *op)
/* refresh auto strip properties */
ED_nla_postop_refresh(&ac);
+ DEG_relations_tag_update(ac.bmain);
+
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
@@ -939,9 +952,12 @@ static int nlaedit_add_meta_exec(bContext *C, wmOperator *UNUSED(op))
if (strip->flag & NLASTRIP_FLAG_SELECT)
BKE_nlastrip_validate_name(adt, strip);
}
+
+ ale->update |= ANIM_UPDATE_DEPS;
}
/* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* set notifier that things have changed */
@@ -991,9 +1007,12 @@ static int nlaedit_remove_meta_exec(bContext *C, wmOperator *UNUSED(op))
/* clear all selected meta-strips, regardless of whether they are temporary or not */
BKE_nlastrips_clear_metas(&nlt->strips, 1, 0);
+
+ ale->update |= ANIM_UPDATE_DEPS;
}
/* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* set notifier that things have changed */
@@ -1057,7 +1076,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
/* if selected, split the strip at its midpoint */
if (strip->flag & NLASTRIP_FLAG_SELECT) {
/* make a copy (assume that this is possible) */
- nstrip = BKE_nlastrip_copy(ac.bmain, strip, linked);
+ nstrip = BKE_nlastrip_copy(ac.bmain, strip, linked, 0);
/* in case there's no space in the track above, or we haven't got a reference to it yet, try adding */
if (BKE_nlatrack_add_strip(nlt->next, nstrip) == 0) {
@@ -1087,6 +1106,10 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *op)
/* refresh auto strip properties */
ED_nla_postop_refresh(&ac);
+ if (!linked) {
+ DEG_relations_tag_update(ac.bmain);
+ }
+
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
@@ -1160,14 +1183,14 @@ static int nlaedit_delete_exec(bContext *C, wmOperator *UNUSED(op))
if (strip->flag & NLASTRIP_FLAG_SELECT) {
/* if a strip either side of this was a transition, delete those too */
if ((strip->prev) && (strip->prev->type == NLASTRIP_TYPE_TRANSITION))
- BKE_nlastrip_free(&nlt->strips, strip->prev);
+ BKE_nlastrip_free(&nlt->strips, strip->prev, true);
if ((nstrip) && (nstrip->type == NLASTRIP_TYPE_TRANSITION)) {
nstrip = nstrip->next;
- BKE_nlastrip_free(&nlt->strips, strip->next);
+ BKE_nlastrip_free(&nlt->strips, strip->next, true);
}
/* finally, delete this strip */
- BKE_nlastrip_free(&nlt->strips, strip);
+ BKE_nlastrip_free(&nlt->strips, strip, true);
}
}
}
@@ -1178,6 +1201,8 @@ static int nlaedit_delete_exec(bContext *C, wmOperator *UNUSED(op))
/* refresh auto strip properties */
ED_nla_postop_refresh(&ac);
+ DEG_relations_tag_update(ac.bmain);
+
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
@@ -1242,7 +1267,7 @@ static void nlaedit_split_strip_actclip(Main *bmain, AnimData *adt, NlaTrack *nl
/* make a copy (assume that this is possible) and append
* it immediately after the current strip
*/
- nstrip = BKE_nlastrip_copy(bmain, strip, true);
+ nstrip = BKE_nlastrip_copy(bmain, strip, true, 0);
BLI_insertlinkafter(&nlt->strips, strip, nstrip);
/* set the endpoint of the first strip and the start of the new strip
@@ -1345,60 +1370,6 @@ void NLA_OT_split(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ******************** Bake Strips Operator ***************************** */
-/* Bakes the NLA Strips for the active AnimData blocks */
-
-static int nlaedit_bake_exec(bContext *C, wmOperator *UNUSED(op))
-{
- bAnimContext ac;
-
- ListBase anim_data = {NULL, NULL};
- bAnimListElem *ale;
- int filter;
-// int flag = 0;
-
- /* get editor data */
- if (ANIM_animdata_get_context(C, &ac) == 0)
- return OPERATOR_CANCELLED;
-
- /* get a list of the editable tracks being shown in the NLA */
- filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_FOREDIT);
- ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype);
-
- /* for each AnimData block, bake strips to animdata... */
- for (ale = anim_data.first; ale; ale = ale->next) {
- //BKE_nla_bake(ac.scene, ale->id, ale->data, flag);
- }
-
- /* free temp data */
- ANIM_animdata_freelist(&anim_data);
-
- /* refresh auto strip properties */
- ED_nla_postop_refresh(&ac);
-
- /* set notifier that things have changed */
- WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
-
- /* done */
- return OPERATOR_FINISHED;
-}
-
-/* why isn't this used? */
-static void UNUSED_FUNCTION(NLA_OT_bake)(wmOperatorType *ot)
-{
- /* identifiers */
- ot->name = "Bake Strips";
- ot->idname = "NLA_OT_bake";
- ot->description = "Bake all strips of selected AnimData blocks";
-
- /* api callbacks */
- ot->exec = nlaedit_bake_exec;
- ot->poll = nlaop_poll_tweakmode_off;
-
- /* flags */
- ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
-}
-
/* *********************************************** */
/* NLA Editing Operations (Modifying) */
@@ -1819,11 +1790,14 @@ static int nlaedit_sync_actlen_exec(bContext *C, wmOperator *op)
/* adjust the strip extents in response to this */
BKE_nlastrip_recalculate_bounds(strip);
+
+ ale->update |= ANIM_UPDATE_DEPS;
}
}
}
/* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
/* set notifier that things have changed */
@@ -1862,6 +1836,7 @@ static int nlaedit_make_single_user_exec(bContext *C, wmOperator *UNUSED(op))
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
+ bool copied = false;
/* get editor data */
if (ANIM_animdata_get_context(C, &ac) == 0)
@@ -1895,14 +1870,22 @@ static int nlaedit_make_single_user_exec(bContext *C, wmOperator *UNUSED(op))
/* switch to the new copy */
strip->act = new_action;
+
+ ale->update |= ANIM_UPDATE_DEPS;
+ copied = true;
}
}
}
}
/* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
+ if (copied) {
+ DEG_relations_tag_update(ac.bmain);
+ }
+
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
@@ -1952,6 +1935,7 @@ static int nlaedit_apply_scale_exec(bContext *C, wmOperator *UNUSED(op))
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
int filter;
+ bool copied = false;
KeyframeEditData ked = {{NULL}};
@@ -1981,6 +1965,8 @@ static int nlaedit_apply_scale_exec(bContext *C, wmOperator *UNUSED(op))
/* set this as the new referenced action, decrementing the users of the old one */
id_us_min(&strip->act->id);
strip->act = act;
+
+ copied = true;
}
/* setup iterator, and iterate over all the keyframes in the action, applying this scaling */
@@ -1993,13 +1979,20 @@ static int nlaedit_apply_scale_exec(bContext *C, wmOperator *UNUSED(op))
*/
strip->scale = 1.0f;
calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
+
+ ale->update |= ANIM_UPDATE_DEPS;
}
}
}
/* free temp data */
+ ANIM_animdata_update(&ac, &anim_data);
ANIM_animdata_freelist(&anim_data);
+ if (copied) {
+ DEG_relations_tag_update(ac.bmain);
+ }
+
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL);
diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h
index a00e71a192d..59844f31447 100644
--- a/source/blender/editors/space_nla/nla_intern.h
+++ b/source/blender/editors/space_nla/nla_intern.h
@@ -65,8 +65,8 @@ enum eNlaEdit_LeftRightSelect_Mode {
/* --- */
-void NLA_OT_select_all_toggle(wmOperatorType *ot);
-void NLA_OT_select_border(wmOperatorType *ot);
+void NLA_OT_select_all(wmOperatorType *ot);
+void NLA_OT_select_box(wmOperatorType *ot);
void NLA_OT_select_leftright(wmOperatorType *ot);
void NLA_OT_click_select(wmOperatorType *ot);
diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c
index bfc6138fb03..0122306f709 100644
--- a/source/blender/editors/space_nla/nla_ops.c
+++ b/source/blender/editors/space_nla/nla_ops.c
@@ -39,6 +39,7 @@
#include "ED_anim_api.h"
#include "ED_markers.h"
#include "ED_screen.h"
+#include "ED_select_utils.h"
#include "ED_transform.h"
#include "WM_api.h"
@@ -123,8 +124,8 @@ void nla_operatortypes(void)
/* select */
WM_operatortype_append(NLA_OT_click_select);
- WM_operatortype_append(NLA_OT_select_border);
- WM_operatortype_append(NLA_OT_select_all_toggle);
+ WM_operatortype_append(NLA_OT_select_box);
+ WM_operatortype_append(NLA_OT_select_all);
WM_operatortype_append(NLA_OT_select_leftright);
/* view */
@@ -171,172 +172,10 @@ void nla_operatortypes(void)
/* ************************** registration - keymaps **********************************/
-static void nla_keymap_channels(wmKeyMap *keymap)
-{
- wmKeyMapItem *kmi;
-
- /* keymappings here are NLA-specific (different to standard channels keymap) */
-
- /* selection --------------------------------------------------------------------- */
- /* click-select */
- // XXX for now, only leftmouse....
- kmi = WM_keymap_add_item(keymap, "NLA_OT_channels_click", LEFTMOUSE, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "extend", false);
- kmi = WM_keymap_add_item(keymap, "NLA_OT_channels_click", LEFTMOUSE, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "extend", true);
-
- /* channel operations ------------------------------------------------------------ */
- /* add tracks */
- kmi = WM_keymap_add_item(keymap, "NLA_OT_tracks_add", AKEY, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "above_selected", false);
- kmi = WM_keymap_add_item(keymap, "NLA_OT_tracks_add", AKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "above_selected", true);
-
- /* delete tracks */
- WM_keymap_add_item(keymap, "NLA_OT_tracks_delete", XKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "NLA_OT_tracks_delete", DELKEY, KM_PRESS, 0, 0);
-}
-
-static void nla_keymap_main(wmKeyConfig *keyconf, wmKeyMap *keymap)
-{
- wmKeyMapItem *kmi;
-
- /* selection ------------------------------------------------ */
- /* click select */
- kmi = WM_keymap_add_item(keymap, "NLA_OT_click_select", SELECTMOUSE, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "extend", false);
- kmi = WM_keymap_add_item(keymap, "NLA_OT_click_select", SELECTMOUSE, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "extend", true);
-
- /* select left/right */
- kmi = WM_keymap_add_item(keymap, "NLA_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL, 0);
- RNA_boolean_set(kmi->ptr, "extend", false);
- RNA_enum_set(kmi->ptr, "mode", NLAEDIT_LRSEL_TEST);
- kmi = WM_keymap_add_item(keymap, "NLA_OT_select_leftright", SELECTMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "extend", true);
- RNA_enum_set(kmi->ptr, "mode", NLAEDIT_LRSEL_TEST);
-
- kmi = WM_keymap_add_item(keymap, "NLA_OT_select_leftright", LEFTBRACKETKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "extend", false);
- RNA_enum_set(kmi->ptr, "mode", NLAEDIT_LRSEL_LEFT);
- kmi = WM_keymap_add_item(keymap, "NLA_OT_select_leftright", RIGHTBRACKETKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "extend", false);
- RNA_enum_set(kmi->ptr, "mode", NLAEDIT_LRSEL_RIGHT);
-
-
- /* deselect all */
- /* TODO: uniformize with other select_all ops? */
- kmi = WM_keymap_add_item(keymap, "NLA_OT_select_all_toggle", AKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "invert", false);
- kmi = WM_keymap_add_item(keymap, "NLA_OT_select_all_toggle", IKEY, KM_PRESS, KM_CTRL, 0);
- RNA_boolean_set(kmi->ptr, "invert", true);
-
- /* borderselect */
- kmi = WM_keymap_add_item(keymap, "NLA_OT_select_border", BKEY, KM_PRESS, 0, 0);
- RNA_boolean_set(kmi->ptr, "axis_range", false);
- kmi = WM_keymap_add_item(keymap, "NLA_OT_select_border", BKEY, KM_PRESS, KM_ALT, 0);
- RNA_boolean_set(kmi->ptr, "axis_range", true);
-
- /* view ---------------------------------------------------- */
- /* auto-set range */
- WM_keymap_add_item(keymap, "NLA_OT_previewrange_set", PKEY, KM_PRESS, KM_CTRL | KM_ALT, 0);
-
- WM_keymap_add_item(keymap, "NLA_OT_view_all", HOMEKEY, KM_PRESS, 0, 0);
-#ifdef WITH_INPUT_NDOF
- WM_keymap_add_item(keymap, "NLA_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0);
-#endif
- WM_keymap_add_item(keymap, "NLA_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "NLA_OT_view_frame", PAD0, KM_PRESS, 0, 0);
-
- /* editing ------------------------------------------------ */
-
- /* add strips */
- WM_keymap_add_item(keymap, "NLA_OT_actionclip_add", AKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "NLA_OT_transition_add", TKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "NLA_OT_soundclip_add", KKEY, KM_PRESS, KM_SHIFT, 0);
-
- /* meta-strips */
- WM_keymap_add_item(keymap, "NLA_OT_meta_add", GKEY, KM_PRESS, KM_SHIFT, 0);
- WM_keymap_add_item(keymap, "NLA_OT_meta_remove", GKEY, KM_PRESS, KM_ALT, 0);
-
- /* duplicate */
- kmi = WM_keymap_add_item(keymap, "NLA_OT_duplicate", DKEY, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "linked", false);
-
- kmi = WM_keymap_add_item(keymap, "NLA_OT_duplicate", DKEY, KM_PRESS, KM_ALT, 0);
- RNA_boolean_set(kmi->ptr, "linked", true);
-
- /* single user */
- WM_keymap_add_item(keymap, "NLA_OT_make_single_user", UKEY, KM_PRESS, 0, 0);
-
- /* delete */
- WM_keymap_add_item(keymap, "NLA_OT_delete", XKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "NLA_OT_delete", DELKEY, KM_PRESS, 0, 0);
-
- /* split */
- WM_keymap_add_item(keymap, "NLA_OT_split", YKEY, KM_PRESS, 0, 0);
-
- /* toggles */
- WM_keymap_add_item(keymap, "NLA_OT_mute_toggle", HKEY, KM_PRESS, 0, 0);
-
- /* swap */
- WM_keymap_add_item(keymap, "NLA_OT_swap", FKEY, KM_PRESS, KM_ALT, 0);
-
- /* move up */
- WM_keymap_add_item(keymap, "NLA_OT_move_up", PAGEUPKEY, KM_PRESS, 0, 0);
- /* move down */
- WM_keymap_add_item(keymap, "NLA_OT_move_down", PAGEDOWNKEY, KM_PRESS, 0, 0);
-
- /* apply scale */
- WM_keymap_add_item(keymap, "NLA_OT_apply_scale", AKEY, KM_PRESS, KM_CTRL, 0);
- /* clear scale */
- WM_keymap_add_item(keymap, "NLA_OT_clear_scale", SKEY, KM_PRESS, KM_ALT, 0);
-
- /* snap */
- WM_keymap_add_item(keymap, "NLA_OT_snap", SKEY, KM_PRESS, KM_SHIFT, 0);
-
- /* add f-modifier */
- WM_keymap_add_item(keymap, "NLA_OT_fmodifier_add", MKEY, KM_PRESS, KM_CTRL | KM_SHIFT, 0);
-
- /* transform system */
- transform_keymap_for_space(keyconf, keymap, SPACE_NLA);
-
- /* special markers hotkeys for anim editors: see note in definition of this function */
- ED_marker_keymap_animedit_conflictfree(keymap);
-}
-
-/* --------------- */
-
void nla_keymap(wmKeyConfig *keyconf)
{
- wmKeyMap *keymap;
- wmKeyMapItem *kmi;
-
/* keymap for all regions ------------------------------------------- */
- keymap = WM_keymap_ensure(keyconf, "NLA Generic", SPACE_NLA, 0);
-
- /* region management */
- WM_keymap_add_item(keymap, "NLA_OT_properties", NKEY, KM_PRESS, 0, 0);
-
- /* tweakmode
- * - enter and exit are separate operators with the same hotkey...
- * This works as they use different poll()'s
- */
- WM_keymap_add_item(keymap, "NLA_OT_tweakmode_enter", TABKEY, KM_PRESS, 0, 0);
- WM_keymap_add_item(keymap, "NLA_OT_tweakmode_exit", TABKEY, KM_PRESS, 0, 0);
-
- /* tweakmode for stashed actions
- * - similar to normal tweakmode, except we mark the tracks as being "solo"
- * too so that the action can be edited in isolation
- */
- kmi = WM_keymap_add_item(keymap, "NLA_OT_tweakmode_enter", TABKEY, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "isolate_action", true);
-
- kmi = WM_keymap_add_item(keymap, "NLA_OT_tweakmode_exit", TABKEY, KM_PRESS, KM_SHIFT, 0);
- RNA_boolean_set(kmi->ptr, "isolate_action", true);
-
- /* 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);
+ WM_keymap_ensure(keyconf, "NLA Generic", SPACE_NLA, 0);
/* channels ---------------------------------------------------------- */
/* Channels are not directly handled by the NLA Editor module, but are inherited from the Animation module.
@@ -346,10 +185,8 @@ void nla_keymap(wmKeyConfig *keyconf)
* However, those operations which involve clicking on channels and/or
* the placement of them in the view are implemented here instead
*/
- keymap = WM_keymap_ensure(keyconf, "NLA Channels", SPACE_NLA, 0);
- nla_keymap_channels(keymap);
+ WM_keymap_ensure(keyconf, "NLA Channels", SPACE_NLA, 0);
/* data ------------------------------------------------------------- */
- keymap = WM_keymap_ensure(keyconf, "NLA Editor", SPACE_NLA, 0);
- nla_keymap_main(keyconf, keymap);
+ WM_keymap_ensure(keyconf, "NLA Editor", SPACE_NLA, 0);
}
diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c
index c1d62a9768d..db7f5d707d2 100644
--- a/source/blender/editors/space_nla/nla_select.c
+++ b/source/blender/editors/space_nla/nla_select.c
@@ -46,6 +46,7 @@
#include "ED_anim_api.h"
#include "ED_keyframes_edit.h"
#include "ED_screen.h"
+#include "ED_select_utils.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -167,10 +168,24 @@ static int nlaedit_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_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_INVERT);
- else
- deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_ADD);
+ const int action = RNA_enum_get(op->ptr, "action");
+ switch (action) {
+ case SEL_TOGGLE:
+ deselect_nla_strips(&ac, DESELECT_STRIPS_TEST, SELECT_ADD);
+ break;
+ case SEL_SELECT:
+ deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_ADD);
+ break;
+ case SEL_DESELECT:
+ deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_SUBTRACT);
+ break;
+ case SEL_INVERT:
+ deselect_nla_strips(&ac, DESELECT_STRIPS_NOTEST, SELECT_INVERT);
+ break;
+ default:
+ BLI_assert(0);
+ break;
+ }
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL);
@@ -178,11 +193,11 @@ static int nlaedit_deselectall_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void NLA_OT_select_all_toggle(wmOperatorType *ot)
+void NLA_OT_select_all(wmOperatorType *ot)
{
/* identifiers */
ot->name = "(De)select All";
- ot->idname = "NLA_OT_select_all_toggle";
+ ot->idname = "NLA_OT_select_all";
ot->description = "Select or deselect all NLA-Strips";
/* api callbacks */
@@ -192,12 +207,11 @@ void NLA_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 strips within region are selected (NLAEDIT_BORDERSEL_ALLSTRIPS)
* -> ALT-BKEY - depending on which axis of the region was larger...
@@ -205,15 +219,15 @@ void NLA_OT_select_all_toggle(wmOperatorType *ot)
* -> 3) y-axis, so select all frames within channels that region included (NLAEDIT_BORDERSEL_CHANNELS)
*/
-/* defines for borderselect mode */
+/* defines for box_select mode */
enum {
- NLA_BORDERSEL_ALLSTRIPS = 0,
- NLA_BORDERSEL_FRAMERANGE,
- NLA_BORDERSEL_CHANNELS,
-} /* eNLAEDIT_BorderSelect_Mode */;
+ NLA_BOXSEL_ALLSTRIPS = 0,
+ NLA_BOXSEL_FRAMERANGE,
+ NLA_BOXSEL_CHANNELS,
+} /* eNLAEDIT_BoxSelect_Mode */;
-static void borderselect_nla_strips(bAnimContext *ac, rcti rect, short mode, short selectmode)
+static void box_select_nla_strips(bAnimContext *ac, rcti rect, short mode, short selectmode)
{
ListBase anim_data = {NULL, NULL};
bAnimListElem *ale;
@@ -235,12 +249,12 @@ static void borderselect_nla_strips(bAnimContext *ac, rcti rect, short mode, sho
/* convert selection modes to selection modes */
selectmode = selmodes_to_flagmodes(selectmode);
- /* loop over data, doing border select */
+ /* loop over data, doing box select */
for (ale = anim_data.first; ale; ale = ale->next) {
ymin = ymax - NLACHANNEL_STEP(snla);
/* perform vertical suitability check (if applicable) */
- if ((mode == NLA_BORDERSEL_FRAMERANGE) ||
+ if ((mode == NLA_BOXSEL_FRAMERANGE) ||
!((ymax < rectf.ymin) || (ymin > rectf.ymax)))
{
/* loop over data selecting (only if NLA-Track) */
@@ -250,7 +264,7 @@ static void borderselect_nla_strips(bAnimContext *ac, rcti rect, short mode, sho
/* only select strips if they fall within the required ranges (if applicable) */
for (strip = nlt->strips.first; strip; strip = strip->next) {
- if ((mode == NLA_BORDERSEL_CHANNELS) ||
+ if ((mode == NLA_BOXSEL_CHANNELS) ||
BKE_nlastrip_within_bounds(strip, rectf.xmin, rectf.xmax))
{
/* set selection */
@@ -273,7 +287,7 @@ static void borderselect_nla_strips(bAnimContext *ac, rcti rect, short mode, sho
/* ------------------- */
-static int nlaedit_borderselect_exec(bContext *C, wmOperator *op)
+static int nlaedit_box_select_exec(bContext *C, wmOperator *op)
{
bAnimContext ac;
rcti rect;
@@ -300,7 +314,7 @@ static int nlaedit_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
@@ -308,15 +322,15 @@ static int nlaedit_borderselect_exec(bContext *C, wmOperator *op)
* used for tweaking timing when "blocking", while channels is not that useful...
*/
if (BLI_rcti_size_x(&rect) >= BLI_rcti_size_y(&rect))
- mode = NLA_BORDERSEL_FRAMERANGE;
+ mode = NLA_BOXSEL_FRAMERANGE;
else
- mode = NLA_BORDERSEL_CHANNELS;
+ mode = NLA_BOXSEL_CHANNELS;
}
else
- mode = NLA_BORDERSEL_ALLSTRIPS;
+ mode = NLA_BOXSEL_ALLSTRIPS;
- /* apply borderselect action */
- borderselect_nla_strips(&ac, rect, mode, selectmode);
+ /* apply box_select action */
+ box_select_nla_strips(&ac, rect, mode, selectmode);
/* set notifier that things have changed */
WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_SELECTED, NULL);
@@ -324,18 +338,18 @@ static int nlaedit_borderselect_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-void NLA_OT_select_border(wmOperatorType *ot)
+void NLA_OT_select_box(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "Border Select";
- ot->idname = "NLA_OT_select_border";
+ ot->name = "Box Select";
+ ot->idname = "NLA_OT_select_box";
ot->description = "Use box selection to grab NLA-Strips";
/* api callbacks */
- ot->invoke = WM_gesture_border_invoke;
- ot->exec = nlaedit_borderselect_exec;
- ot->modal = WM_gesture_border_modal;
- ot->cancel = WM_gesture_border_cancel;
+ ot->invoke = WM_gesture_box_invoke;
+ ot->exec = nlaedit_box_select_exec;
+ ot->modal = WM_gesture_box_modal;
+ ot->cancel = WM_gesture_box_cancel;
ot->poll = nlaop_poll_tweakmode_off;
@@ -343,7 +357,7 @@ void NLA_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);
RNA_def_boolean(ot->srna, "axis_range", 0, "Axis Range", "");
}
@@ -653,7 +667,7 @@ void NLA_OT_click_select(wmOperatorType *ot)
PropertyRNA *prop;
/* identifiers */
- ot->name = "Mouse Select";
+ ot->name = "Select";
ot->idname = "NLA_OT_click_select";
ot->description = "Handle clicks to select NLA Strips";
diff --git a/source/blender/editors/space_nla/space_nla.c b/source/blender/editors/space_nla/space_nla.c
index 1f9ff9aaabd..d72014901a6 100644
--- a/source/blender/editors/space_nla/space_nla.c
+++ b/source/blender/editors/space_nla/space_nla.c
@@ -33,7 +33,7 @@
#include <stdio.h>
#include "DNA_anim_types.h"
-#include "DNA_group_types.h"
+#include "DNA_collection_types.h"
#include "DNA_scene_types.h"
#include "MEM_guardedalloc.h"
@@ -55,11 +55,15 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "WM_message.h"
+
+#include "RNA_access.h"
#include "UI_resources.h"
#include "UI_view2d.h"
#include "nla_intern.h" /* own include */
+#include "GPU_framebuffer.h"
/* ******************** manage regions ********************* */
@@ -91,10 +95,8 @@ ARegion *nla_has_buttons_region(ScrArea *sa)
/* ******************** default callbacks for nla space ***************** */
-static SpaceLink *nla_new(const bContext *C)
+static SpaceLink *nla_new(const ScrArea *sa, const Scene *scene)
{
- Scene *scene = CTX_data_scene(C);
- ScrArea *sa = CTX_wm_area(C);
ARegion *ar;
SpaceNla *snla;
@@ -113,7 +115,7 @@ static SpaceLink *nla_new(const bContext *C)
BLI_addtail(&snla->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 list for nla");
@@ -177,14 +179,14 @@ static void nla_free(SpaceLink *sl)
/* spacetype; init callback */
-static void nla_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa)
+static void nla_init(struct wmWindowManager *wm, ScrArea *sa)
{
SpaceNla *snla = (SpaceNla *)sa->spacedata.first;
/* init dopesheet data if non-existent (i.e. for old files) */
if (snla->ads == NULL) {
snla->ads = MEM_callocN(sizeof(bDopeSheet), "NlaEdit DopeSheet");
- snla->ads->source = (ID *)G.main->scene.first; // XXX this is bad, but we need this to be set correct
+ snla->ads->source = (ID *)WM_window_get_active_scene(wm->winactive);
}
ED_area_tag_refresh(sa);
@@ -231,7 +233,7 @@ static void nla_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);
@@ -244,7 +246,7 @@ static void nla_channel_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_restore(C);
/* scrollers */
- scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
+ scrollers = UI_view2d_scrollers_calc(C, v2d, NULL, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
UI_view2d_scrollers_draw(C, v2d, scrollers);
UI_view2d_scrollers_free(scrollers);
}
@@ -268,15 +270,16 @@ static void nla_main_region_draw(const bContext *C, ARegion *ar)
{
/* draw entirely, view changes should be handled here */
SpaceNla *snla = CTX_wm_space_nla(C);
+ Scene *scene = CTX_data_scene(C);
bAnimContext ac;
View2D *v2d = &ar->v2d;
View2DGrid *grid;
View2DScrollers *scrollers;
- short unit = 0, flag = 0;
+ short unit = 0, cfra_flag = 0;
/* clear and setup matrix */
UI_ThemeClearColor(TH_BACK);
- glClear(GL_COLOR_BUFFER_BIT);
+ GPU_clear(GPU_COLOR_BIT);
UI_view2d_view_ortho(v2d);
@@ -288,6 +291,9 @@ static void nla_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)) {
/* strips and backdrops */
@@ -300,9 +306,8 @@ static void nla_main_region_draw(const bContext *C, ARegion *ar)
UI_view2d_view_ortho(v2d);
/* current frame */
- if (snla->flag & SNLA_DRAWTIME) flag |= DRAWCFRA_UNIT_SECONDS;
- if ((snla->flag & SNLA_NODRAWCFRANUM) == 0) flag |= DRAWCFRA_SHOW_NUMBOX;
- ANIM_draw_cfra(C, v2d, flag);
+ if (snla->flag & SNLA_DRAWTIME) cfra_flag |= DRAWCFRA_UNIT_SECONDS;
+ ANIM_draw_cfra(C, v2d, cfra_flag);
/* markers */
UI_view2d_view_orthoSpecial(ar, v2d, 1);
@@ -320,9 +325,15 @@ static void nla_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 ((snla->flag & SNLA_NODRAWCFRANUM) == 0) {
+ UI_view2d_view_orthoSpecial(ar, v2d, 1);
+ ANIM_draw_cfra_number(C, v2d, cfra_flag);
+ }
}
@@ -350,10 +361,12 @@ static void nla_buttons_region_init(wmWindowManager *wm, ARegion *ar)
static void nla_buttons_region_draw(const bContext *C, ARegion *ar)
{
- ED_region_panels(C, ar, NULL, -1, true);
+ ED_region_panels(C, ar);
}
-static void nla_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void nla_region_listener(
+ wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -386,7 +399,9 @@ static void nla_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegio
}
-static void nla_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void nla_main_region_listener(
+ wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -398,6 +413,7 @@ static void nla_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), A
case ND_RENDER_OPTIONS:
case ND_OB_ACTIVE:
case ND_FRAME:
+ case ND_FRAME_RANGE:
case ND_MARKERS:
ED_region_tag_redraw(ar);
break;
@@ -424,6 +440,11 @@ static void nla_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), A
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);
@@ -431,7 +452,49 @@ static void nla_main_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), A
}
}
-static void nla_channel_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa), ARegion *ar, wmNotifier *wmn)
+static void nla_main_region_message_subscribe(
+ const struct bContext *UNUSED(C),
+ struct WorkSpace *UNUSED(workspace), struct Scene *scene,
+ struct bScreen *screen, struct ScrArea *sa, struct ARegion *ar,
+ struct wmMsgBus *mbus)
+{
+ PointerRNA ptr;
+ RNA_pointer_create(&screen->id, &RNA_SpaceNLA, 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__);
+ }
+ }
+}
+
+static void nla_channel_region_listener(
+ wmWindow *UNUSED(win), ScrArea *UNUSED(sa), ARegion *ar,
+ wmNotifier *wmn, const Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -465,8 +528,43 @@ static void nla_channel_region_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa)
}
}
+static void nla_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_SpaceNLA, 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,
+ * so just whitelist the entire struct for updates
+ */
+ {
+ wmMsgParams_RNA msg_key_params = {{{0}}};
+ StructRNA *type_array[] = {
+ &RNA_DopeSheet,
+ };
+
+ 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__);
+ }
+ }
+}
+
/* editor level listener */
-static void nla_listener(bScreen *UNUSED(sc), ScrArea *sa, wmNotifier *wmn)
+static void nla_listener(wmWindow *UNUSED(win), ScrArea *sa, wmNotifier *wmn, Scene *UNUSED(scene))
{
/* context changes */
switch (wmn->category) {
@@ -508,7 +606,7 @@ static void nla_id_remap(ScrArea *UNUSED(sa), SpaceLink *slink, ID *old_id, ID *
if (snla->ads) {
if ((ID *)snla->ads->filter_grp == old_id) {
- snla->ads->filter_grp = (Group *)new_id;
+ snla->ads->filter_grp = (Collection *)new_id;
}
if ((ID *)snla->ads->source == old_id) {
snla->ads->source = new_id;
@@ -540,6 +638,7 @@ void ED_spacetype_nla(void)
art->init = nla_main_region_init;
art->draw = nla_main_region_draw;
art->listener = nla_main_region_listener;
+ art->message_subscribe = nla_main_region_message_subscribe;
art->keymapflag = ED_KEYMAP_VIEW2D | ED_KEYMAP_MARKERS | ED_KEYMAP_ANIMATION | ED_KEYMAP_FRAMES;
BLI_addhead(&st->regiontypes, art);
@@ -564,6 +663,7 @@ void ED_spacetype_nla(void)
art->init = nla_channel_region_init;
art->draw = nla_channel_region_draw;
art->listener = nla_channel_region_listener;
+ art->message_subscribe = nla_channel_region_message_subscribe;
BLI_addhead(&st->regiontypes, art);