Page MenuHome

0001-VSE-implement-sequence-translation-in-sequencer-prev.patch

File Metadata

Author
Jehan Pagès (jehan)
Created
Apr 29 2014, 6:46 AM

0001-VSE-implement-sequence-translation-in-sequencer-prev.patch

From 8f9d8e6b63af8b5d673ea6a4ac96bed93eac4b89 Mon Sep 17 00:00:00 2001
From: Jehan <jehan@girinstud.io>
Date: Tue, 29 Apr 2014 16:25:07 +1200
Subject: [PATCH] VSE: implement sequence translation in sequencer preview by
drag'n drop.
The feature follows blender convention:
- it takes into account both mouse select button (left/right) and the
"Release confirms" custom user settings.
- Drag'n drop can be initiated by usual 'g' shortcut too.
- Clicking 'x' or 'y' during transformation adds constraints along
respectively the X or Y axis, and 'c' clears any constraint.
The dnd applies to all selected sequences on current frame.
---
.../editors/space_sequencer/sequencer_intern.h | 1 +
.../editors/space_sequencer/sequencer_ops.c | 5 +
.../editors/space_sequencer/sequencer_view.c | 239 +++++++++++++++++++++
3 files changed, 245 insertions(+)
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 60fc300..f889a72 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -190,6 +190,7 @@ void SEQUENCER_OT_strip_modifier_move(struct wmOperatorType *ot);
/* sequencer_view.c */
void SEQUENCER_OT_sample(struct wmOperatorType *ot);
+void SEQUENCER_OT_transform_preview(struct wmOperatorType *ot);
#endif /* __SEQUENCER_INTERN_H__ */
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
index f022e78..2263b67 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -127,6 +127,7 @@ void sequencer_operatortypes(void)
/* sequencer_view.h */
WM_operatortype_append(SEQUENCER_OT_sample);
+ WM_operatortype_append(SEQUENCER_OT_transform_preview);
}
@@ -356,6 +357,10 @@ void sequencer_keymap(wmKeyConfig *keyconf)
/* sample */
WM_keymap_add_item(keymap, "SEQUENCER_OT_sample", ACTIONMOUSE, KM_PRESS, 0, 0);
+
+ /* Transformation */
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_transform_preview", SELECTMOUSE, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "SEQUENCER_OT_transform_preview", GKEY, KM_PRESS, 0, 0);
}
void ED_operatormacros_sequencer(void)
diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c
index 7fdbc9c..a082eaf 100644
--- a/source/blender/editors/space_sequencer/sequencer_view.c
+++ b/source/blender/editors/space_sequencer/sequencer_view.c
@@ -35,6 +35,7 @@
#include "BLI_utildefines.h"
#include "DNA_scene_types.h"
+#include "DNA_userdef_types.h"
#include "BKE_context.h"
#include "BKE_main.h"
@@ -238,3 +239,241 @@ void SEQUENCER_OT_sample(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_BLOCKING;
}
+
+/******************** sequence visual transformation operator ********************/
+
+typedef enum SequenceTransformConstraint {
+ TRANSFORM_NO_CONSTRAINT,
+ TRANSFORM_X_CONSTRAINT,
+ TRANSFORM_Y_CONSTRAINT
+} SequenceTransformConstraint;
+
+typedef struct SequenceTransformInfo {
+ int original_event_x;
+ int original_event_y;
+ int previous_event_x;
+ int previous_event_y;
+ int transformed_x;
+ int transformed_y;
+
+ bool invoked_by_mouse;
+ SequenceTransformConstraint constraint;
+} SequenceTransformInfo;
+
+/* Force a refresh of sequencer display. */
+static void sequencer_refresh_all(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+}
+
+/* Cancel the on-going transformation. */
+static void sequencer_transform_preview_cancel(struct bContext *C,
+ struct wmOperator *op)
+{
+ SequenceTransformInfo *info = op->customdata;
+ Scene *scene = CTX_data_scene(C);
+ Sequence *seq;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (!(seq->flag & SELECT) || !(seq->flag & SEQ_USE_TRANSFORM)
+ || scene->r.cfra < BKE_sequence_tx_get_final_left(seq, 0)
+ || scene->r.cfra >= BKE_sequence_tx_get_final_right(seq, 0))
+ continue;
+ seq->strip->transform->xofs -= (seq->flag & SEQ_FLIPX? -1 : 1) * info->transformed_x;
+ seq->strip->transform->yofs -= (seq->flag & SEQ_FLIPY? -1 : 1) * info->transformed_y;
+ BKE_sequencer_cache_cleanup_sequence(seq);
+ }
+ sequencer_refresh_all(C);
+ MEM_freeN(op->customdata);
+}
+
+/* Actually compute the new transformed offset. */
+static void sequencer_transform_preview_apply(struct bContext *C,
+ struct wmOperator *op,
+ const struct wmEvent *event)
+{
+ Scene *scene = CTX_data_scene(C);
+ ARegion *ar = CTX_wm_region(C);
+ float fx, fy;
+ float scale;
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ Strip *strip;
+ StripTransform *transform;
+ SequenceTransformInfo *info = op->customdata;
+ int transform_x, transform_y;
+
+ scale = (float) scene->r.size / 100.0f;
+ scale = scale == 0? 0.01f : scale;
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx, &fy);
+ if (info->constraint == TRANSFORM_Y_CONSTRAINT)
+ transform_x = - info->transformed_x;
+ else
+ transform_x = (int) ((fx - (float) info->previous_event_x) / scale);
+ if (info->constraint == TRANSFORM_X_CONSTRAINT)
+ transform_y = - info->transformed_y;
+ else
+ transform_y = (int) ((fy - (float) info->previous_event_y) / scale);
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (!(seq->flag & SELECT) || !(seq->flag & SEQ_USE_TRANSFORM)
+ || scene->r.cfra < BKE_sequence_tx_get_final_left(seq, 0)
+ || scene->r.cfra >= BKE_sequence_tx_get_final_right(seq, 0))
+ continue;
+ if (seq->strip == NULL) {
+ seq->strip = MEM_callocN(sizeof(struct Strip), "Strip");
+ }
+ strip = seq->strip;
+ if (strip->transform == NULL) {
+ strip->transform = MEM_callocN(sizeof(struct StripTransform), "StripTransform");
+ }
+ transform = strip->transform;
+
+ transform->xofs += (seq->flag & SEQ_FLIPX? -1 : 1) * transform_x;
+ transform->yofs += (seq->flag & SEQ_FLIPY? -1 : 1) * transform_y;
+ BKE_sequencer_cache_cleanup_sequence(seq);
+ }
+
+ info->transformed_x += transform_x;
+ info->transformed_y += transform_y;
+ if (info->constraint == TRANSFORM_Y_CONSTRAINT)
+ info->previous_event_x = info->original_event_x;
+ else
+ info->previous_event_x = (int) fx;
+ if (info->constraint == TRANSFORM_X_CONSTRAINT)
+ info->previous_event_y = info->original_event_y;
+ else
+ info->previous_event_y = (int) fy;
+
+ sequencer_refresh_all(C);
+}
+
+static int sequencer_transform_preview_invoke(struct bContext *C,
+ struct wmOperator *op,
+ const struct wmEvent *event)
+{
+ Scene *scene = CTX_data_scene(C);
+ Sequence *seq = BKE_sequencer_active_get(scene);
+ ARegion *ar = CTX_wm_region(C);
+ float fx, fy;
+ SequenceTransformInfo *info;
+
+ if (! (seq && seq->flag & SEQ_USE_TRANSFORM && seq->strip && seq->strip->transform))
+ return OPERATOR_CANCELLED;
+
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx, &fy);
+
+ info = MEM_callocN(sizeof(SequenceTransformInfo), "SequenceTransformInfo");
+ info->original_event_x = fx;
+ info->original_event_y = fy;
+ info->previous_event_x = fx;
+ info->previous_event_y = fy;
+ info->transformed_x = 0;
+ info->transformed_y = 0;
+ info->constraint = TRANSFORM_NO_CONSTRAINT;
+ op->customdata = info;
+
+ switch (event->type) {
+ case RIGHTMOUSE:
+ case LEFTMOUSE:
+ info->invoked_by_mouse = true;
+ break;
+ default:
+ info->invoked_by_mouse = false;
+ }
+
+ sequencer_transform_preview_apply(C, op, event);
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int sequencer_transform_preview_modal(struct bContext *C,
+ struct wmOperator *op,
+ const struct wmEvent *event)
+{
+ SequenceTransformInfo *info = op->customdata;
+
+ switch (event->type) {
+ case CKEY:
+ // Clear any constraint.
+ info->constraint = TRANSFORM_NO_CONSTRAINT;
+ sequencer_transform_preview_apply(C, op, event);
+ break;
+ case XKEY:
+ // Constraint along the X axis.
+ info->constraint = TRANSFORM_X_CONSTRAINT;
+ sequencer_transform_preview_apply(C, op, event);
+ break;
+ case YKEY:
+ // Constraint along the Y axis.
+ info->constraint = TRANSFORM_Y_CONSTRAINT;
+ sequencer_transform_preview_apply(C, op, event);
+ break;
+ case RIGHTMOUSE:
+ if (!info->invoked_by_mouse)
+ {
+ sequencer_transform_preview_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ }
+ case LEFTMOUSE:
+ if (!info->invoked_by_mouse ||
+ (event->type == LEFTMOUSE && U.flag & USER_LMOUSESELECT) ||
+ (event->type == RIGHTMOUSE && !(U.flag & USER_LMOUSESELECT)))
+ {
+ if (info->invoked_by_mouse && event->val == KM_RELEASE && !(U.flag & USER_RELEASECONFIRM))
+ {
+ sequencer_transform_preview_apply(C, op, event);
+ break;
+ }
+
+ sequencer_transform_preview_apply(C, op, event);
+ MEM_freeN(op->customdata);
+ return OPERATOR_FINISHED;
+ }
+ case ESCKEY:
+ sequencer_transform_preview_cancel(C, op);
+ return OPERATOR_CANCELLED;
+ case MOUSEMOVE:
+ sequencer_transform_preview_apply(C, op, event);
+ break;
+ }
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int sequencer_transform_preview_poll(struct bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT && seq->flag & SEQ_USE_TRANSFORM
+ && scene->r.cfra >= BKE_sequence_tx_get_final_left(seq, 0)
+ && scene->r.cfra < BKE_sequence_tx_get_final_right(seq, 0))
+ return true;
+ }
+
+ return false;
+}
+
+void SEQUENCER_OT_transform_preview(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Translate Selected Sequences";
+ ot->idname = "SEQUENCER_OT_transform_preview";
+ ot->description = "Use mouse to move selected translatable sequences in current frame";
+
+ /* api callbacks */
+ ot->invoke = sequencer_transform_preview_invoke;
+ ot->modal = sequencer_transform_preview_modal;
+ ot->cancel = sequencer_transform_preview_cancel;
+ ot->poll = sequencer_transform_preview_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+}
--
1.8.1.2

Event Timeline