[WIP]tweak-experiment-experimental #119805
|
@ -8408,26 +8408,38 @@ def km_3d_view_tool_sculpt_gpencil_select_lasso(params):
|
|||
# ------------------------------------------------------------------------------
|
||||
# Tool System (Sequencer, Generic)
|
||||
|
||||
def km_sequencer_editor_tool_generic_select(params, *, fallback):
|
||||
def km_sequencer_editor_tool_generic_select_timeline_rcs(params, fallback):
|
||||
return [
|
||||
("sequencer.select", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("handles_only", True), ("wait_to_deselect_others", True)]}),
|
||||
*_template_items_change_frame(params),
|
||||
# Frame change can be cancelled if click happens on strip handle. In such case move the handle.
|
||||
("transform.seq_slide", {"type": 'LEFTMOUSE', "value": 'PRESS'},
|
||||
{"properties": [("view2d_edge_pan", True)]}),
|
||||
]
|
||||
|
||||
|
||||
def km_sequencer_editor_tool_generic_select_timeline_lcs(params, fallback):
|
||||
return [
|
||||
*_template_items_tool_select(
|
||||
params, "sequencer.select", "sequencer.cursor_set", cursor_prioritize=True, fallback=fallback),
|
||||
]
|
||||
|
||||
|
||||
def km_sequencer_editor_tool_generic_select_timeline(params, *, fallback):
|
||||
return (
|
||||
_fallback_id("Sequencer Tool: Tweak", fallback),
|
||||
_fallback_id("Sequencer Timeline Tool: Tweak", fallback),
|
||||
{"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
*([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select(
|
||||
params, "sequencer.select", "sequencer.cursor_set", cursor_prioritize=True, fallback=fallback)),
|
||||
|
||||
*([] if params.use_fallback_tool_select_handled else
|
||||
_template_sequencer_preview_select(
|
||||
type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)),
|
||||
# Ignored for preview.
|
||||
*_template_items_change_frame(params),
|
||||
*(km_sequencer_editor_tool_generic_select_timeline_rcs(params, fallback) if (params.select_mouse == 'RIGHTMOUSE')
|
||||
else km_sequencer_editor_tool_generic_select_timeline_lcs(params, fallback)),
|
||||
]},
|
||||
)
|
||||
|
||||
|
||||
def km_sequencer_editor_tool_generic_select_box(params, *, fallback):
|
||||
def km_sequencer_editor_tool_generic_select_box_timeline(params, *, fallback):
|
||||
return (
|
||||
_fallback_id("Sequencer Tool: Select Box", fallback),
|
||||
_fallback_id("Sequencer Timeline Tool: Select Box", fallback),
|
||||
{"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
# Don't use `tool_maybe_tweak_event`, see comment for this slot.
|
||||
|
@ -8436,7 +8448,6 @@ def km_sequencer_editor_tool_generic_select_box(params, *, fallback):
|
|||
**(params.select_tweak_event if (fallback and params.use_fallback_tool_select_mouse) else
|
||||
params.tool_tweak_event),
|
||||
properties=[("tweak", params.select_mouse == 'LEFTMOUSE')])),
|
||||
|
||||
# RMB select can already set the frame, match the tweak tool.
|
||||
# Ignored for preview.
|
||||
*(_template_items_change_frame(params)
|
||||
|
@ -8445,6 +8456,36 @@ def km_sequencer_editor_tool_generic_select_box(params, *, fallback):
|
|||
)
|
||||
|
||||
|
||||
def km_sequencer_editor_tool_generic_select_preview(params, *, fallback):
|
||||
return (
|
||||
_fallback_id("Sequencer Preview Tool: Tweak", fallback),
|
||||
{"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
*([] if (fallback and (params.select_mouse == 'RIGHTMOUSE')) else _template_items_tool_select(
|
||||
params, "sequencer.select", "sequencer.cursor_set", cursor_prioritize=True, fallback=fallback)),
|
||||
|
||||
*([] if params.use_fallback_tool_select_handled else
|
||||
_template_sequencer_preview_select(
|
||||
type=params.select_mouse, value=params.select_mouse_value, legacy=params.legacy)),
|
||||
]},
|
||||
)
|
||||
|
||||
|
||||
def km_sequencer_editor_tool_generic_select_box_preview(params, *, fallback):
|
||||
return (
|
||||
_fallback_id("Sequencer Preview Tool: Select Box", fallback),
|
||||
{"space_type": 'SEQUENCE_EDITOR', "region_type": 'WINDOW'},
|
||||
{"items": [
|
||||
# Don't use `tool_maybe_tweak_event`, see comment for this slot.
|
||||
*([] if (fallback and not params.use_fallback_tool) else _template_items_tool_select_actions_simple(
|
||||
"sequencer.select_box",
|
||||
**(params.select_tweak_event if (fallback and params.use_fallback_tool_select_mouse) else
|
||||
params.tool_tweak_event),
|
||||
properties=[("tweak", params.select_mouse == 'LEFTMOUSE')])),
|
||||
]},
|
||||
)
|
||||
|
||||
|
||||
def km_sequencer_editor_tool_generic_cursor(params):
|
||||
return (
|
||||
"Sequencer Tool: Cursor",
|
||||
|
@ -8793,8 +8834,10 @@ def generate_keymaps(params=None):
|
|||
km_3d_view_tool_sculpt_gpencil_select_box(params),
|
||||
km_3d_view_tool_sculpt_gpencil_select_circle(params),
|
||||
km_3d_view_tool_sculpt_gpencil_select_lasso(params),
|
||||
*(km_sequencer_editor_tool_generic_select(params, fallback=fallback) for fallback in (False, True)),
|
||||
*(km_sequencer_editor_tool_generic_select_box(params, fallback=fallback) for fallback in (False, True)),
|
||||
*(km_sequencer_editor_tool_generic_select_timeline(params, fallback=fallback) for fallback in (False, True)),
|
||||
*(km_sequencer_editor_tool_generic_select_box_timeline(params, fallback=fallback) for fallback in (False, True)),
|
||||
*(km_sequencer_editor_tool_generic_select_preview(params, fallback=fallback) for fallback in (False, True)),
|
||||
*(km_sequencer_editor_tool_generic_select_box_preview(params, fallback=fallback) for fallback in (False, True)),
|
||||
km_sequencer_editor_tool_generic_cursor(params),
|
||||
km_sequencer_editor_tool_blade(params),
|
||||
km_sequencer_editor_tool_sample(params),
|
||||
|
|
|
@ -317,6 +317,7 @@ class SEQUENCER_PT_sequencer_overlay(Panel):
|
|||
|
||||
layout.prop(overlay_settings, "show_strip_offset", text="Offsets")
|
||||
layout.prop(overlay_settings, "show_fcurves", text="F-Curves")
|
||||
layout.prop(overlay_settings, "show_strip_handles", text="Handles")
|
||||
layout.prop(overlay_settings, "show_strip_retiming", text="Retiming")
|
||||
layout.prop(overlay_settings, "show_thumbnails", text="Thumbnails")
|
||||
layout.prop(overlay_settings, "show_grid", text="Grid")
|
||||
|
|
|
@ -2669,17 +2669,17 @@ class _defs_sequencer_generic:
|
|||
|
||||
class _defs_sequencer_select:
|
||||
@ToolDef.from_fn
|
||||
def select():
|
||||
def select_timeline():
|
||||
return dict(
|
||||
idname="builtin.select",
|
||||
label="Tweak",
|
||||
icon="ops.generic.select",
|
||||
widget=None,
|
||||
keymap="Sequencer Tool: Tweak",
|
||||
keymap="Sequencer Timeline Tool: Tweak",
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def box():
|
||||
def box_timeline():
|
||||
def draw_settings(_context, layout, tool):
|
||||
props = tool.operator_properties("sequencer.select_box")
|
||||
row = layout.row()
|
||||
|
@ -2690,7 +2690,33 @@ class _defs_sequencer_select:
|
|||
label="Select Box",
|
||||
icon="ops.generic.select_box",
|
||||
widget=None,
|
||||
keymap="Sequencer Tool: Select Box",
|
||||
keymap="Sequencer Timeline Tool: Select Box",
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def select_preview():
|
||||
return dict(
|
||||
idname="builtin.select",
|
||||
label="Tweak",
|
||||
icon="ops.generic.select",
|
||||
widget=None,
|
||||
keymap="Sequencer Preview Tool: Tweak",
|
||||
)
|
||||
|
||||
@ToolDef.from_fn
|
||||
def box_preview():
|
||||
def draw_settings(_context, layout, tool):
|
||||
props = tool.operator_properties("sequencer.select_box")
|
||||
row = layout.row()
|
||||
row.use_property_split = False
|
||||
row.prop(props, "mode", text="", expand=True, icon_only=True)
|
||||
return dict(
|
||||
idname="builtin.select_box",
|
||||
label="Select Box",
|
||||
icon="ops.generic.select_box",
|
||||
widget=None,
|
||||
keymap="Sequencer Preview Tool: Select Box",
|
||||
draw_settings=draw_settings,
|
||||
)
|
||||
|
||||
|
@ -3274,13 +3300,6 @@ class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel):
|
|||
yield from cls._tools.items()
|
||||
|
||||
# Private tool lists for convenient reuse in `_tools`.
|
||||
|
||||
_tools_select = (
|
||||
(
|
||||
_defs_sequencer_select.select,
|
||||
_defs_sequencer_select.box,
|
||||
),
|
||||
)
|
||||
_tools_annotate = (
|
||||
(
|
||||
_defs_annotate.scribble,
|
||||
|
@ -3297,7 +3316,10 @@ class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel):
|
|||
None: [
|
||||
],
|
||||
'PREVIEW': [
|
||||
*_tools_select,
|
||||
(
|
||||
_defs_sequencer_select.select_preview,
|
||||
_defs_sequencer_select.box_preview,
|
||||
),
|
||||
_defs_sequencer_generic.cursor,
|
||||
None,
|
||||
_defs_sequencer_generic.translate,
|
||||
|
@ -3309,12 +3331,13 @@ class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel):
|
|||
*_tools_annotate,
|
||||
],
|
||||
'SEQUENCER': [
|
||||
*_tools_select,
|
||||
(
|
||||
_defs_sequencer_select.select_timeline,
|
||||
_defs_sequencer_select.box_timeline,
|
||||
),
|
||||
_defs_sequencer_generic.blade,
|
||||
],
|
||||
'SEQUENCER_PREVIEW': [
|
||||
*_tools_select,
|
||||
None,
|
||||
*_tools_annotate,
|
||||
None,
|
||||
_defs_sequencer_generic.blade,
|
||||
|
|
|
@ -533,6 +533,17 @@ class USERPREF_PT_edit_node_editor(EditingPanel, CenterAlignMixIn, Panel):
|
|||
layout.prop(edit, "node_preview_resolution", text="Preview Resolution")
|
||||
|
||||
|
||||
class USERPREF_PT_edit_sequence_editor(EditingPanel, CenterAlignMixIn, Panel):
|
||||
bl_label = "Video Sequencer"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
||||
def draw_centered(self, context, layout):
|
||||
prefs = context.preferences
|
||||
edit = prefs.edit
|
||||
|
||||
layout.prop(edit, "use_sequencer_simplified_tweaking")
|
||||
|
||||
|
||||
class USERPREF_PT_edit_misc(EditingPanel, CenterAlignMixIn, Panel):
|
||||
bl_label = "Miscellaneous"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
|
@ -2777,6 +2788,7 @@ classes = (
|
|||
USERPREF_PT_edit_gpencil,
|
||||
USERPREF_PT_edit_text_editor,
|
||||
USERPREF_PT_edit_node_editor,
|
||||
USERPREF_PT_edit_sequence_editor,
|
||||
USERPREF_PT_edit_misc,
|
||||
|
||||
USERPREF_PT_animation_timeline,
|
||||
|
|
|
@ -29,7 +29,7 @@ extern "C" {
|
|||
|
||||
/* Blender file format version. */
|
||||
#define BLENDER_FILE_VERSION BLENDER_VERSION
|
||||
#define BLENDER_FILE_SUBVERSION 9
|
||||
#define BLENDER_FILE_SUBVERSION 10
|
||||
|
||||
/* Minimum Blender version that supports reading file written with the current
|
||||
* version. Older Blender versions will test this and cancel loading the file, showing a warning to
|
||||
|
|
|
@ -930,6 +930,10 @@ void blo_do_versions_userdef(UserDef *userdef)
|
|||
}
|
||||
}
|
||||
|
||||
if (!USER_VERSION_ATLEAST(402, 10)) {
|
||||
userdef->sequencer_editor_flag |= USER_SEQ_ED_SIMPLE_TWEAKING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always bump subversion in BKE_blender_version.h when adding versioning
|
||||
* code here, and wrap it inside a USER_VERSION_ATLEAST check.
|
||||
|
|
|
@ -222,6 +222,22 @@ static bool use_sequencer_snapping(bContext *C)
|
|||
(snap_flag & SEQ_SNAP_CURRENT_FRAME_TO_STRIPS);
|
||||
}
|
||||
|
||||
static bool sequencer_skip_for_handle_tweak(const bContext *C, const wmEvent *event)
|
||||
{
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
|
||||
float mouse_co[2];
|
||||
UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouse_co[0], &mouse_co[1]);
|
||||
Sequence *seq1, *seq2;
|
||||
int side;
|
||||
|
||||
ED_sequencer_handle_selection_refine(scene, v2d, mouse_co, &seq1, &seq2, &side);
|
||||
|
||||
return side != SEQ_SIDE_NONE;
|
||||
}
|
||||
|
||||
/* Modal Operator init */
|
||||
static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
|
@ -230,6 +246,9 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
|
|||
if (CTX_wm_space_seq(C) != nullptr && region->regiontype == RGN_TYPE_PREVIEW) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
if (sequencer_skip_for_handle_tweak(C, event)) {
|
||||
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
||||
/* Change to frame that mouse is over before adding modal handler,
|
||||
* as user could click on a single frame (jump to frame) as well as
|
||||
|
|
|
@ -8,10 +8,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_vector_set.hh"
|
||||
|
||||
struct Scene;
|
||||
struct Sequence;
|
||||
struct SpaceSeq;
|
||||
struct bContext;
|
||||
struct View2D;
|
||||
|
||||
void ED_sequencer_select_sequence_single(Scene *scene, Sequence *seq, bool deselect_all);
|
||||
/**
|
||||
|
@ -45,4 +48,28 @@ void ED_operatormacros_sequencer();
|
|||
Sequence *ED_sequencer_special_preview_get();
|
||||
void ED_sequencer_special_preview_set(bContext *C, const int mval[2]);
|
||||
void ED_sequencer_special_preview_clear();
|
||||
bool sequencer_retiming_mode_is_active(const bContext *C);
|
||||
bool sequencer_retiming_mode_is_active(const Scene *scene);
|
||||
/**
|
||||
* Returns true if strip can be selected, false otherwise.
|
||||
*
|
||||
* r_seq1 first strip to be selected. Never nullptr if function returns true
|
||||
* r_seq2 second strip to be selected.
|
||||
* r_side which handle is selected. This further clarifies result if seq2 is nullptr.
|
||||
*/
|
||||
bool ED_sequencer_handle_selection_refine(const struct Scene *scene,
|
||||
const View2D *v2d,
|
||||
float mouse_co[2],
|
||||
struct Sequence **r_seq1,
|
||||
struct Sequence **r_seq2,
|
||||
int *r_side);
|
||||
|
||||
/**
|
||||
* Returns collection with selected strips presented to user. If operation is done in preview,
|
||||
* collection is limited to selected presented strips, that can produce image output at current
|
||||
* frame.
|
||||
*
|
||||
* \param C: context
|
||||
* \return collection of strips (`Sequence`)
|
||||
*/
|
||||
blender::VectorSet<Sequence *> ED_sequencer_selected_strips_from_context(bContext *C);
|
||||
bool ED_sequencer_can_select_handle(const Scene *scene, const Sequence *seq, const View2D *v2d);
|
||||
|
|
|
@ -1682,7 +1682,7 @@ static int sequencer_delete_exec(bContext *C, wmOperator *op)
|
|||
|
||||
SEQ_prefetch_stop(scene);
|
||||
|
||||
for (Sequence *seq : selected_strips_from_context(C)) {
|
||||
for (Sequence *seq : ED_sequencer_selected_strips_from_context(C)) {
|
||||
SEQ_edit_flag_for_removal(scene, seqbasep, seq);
|
||||
if (delete_data) {
|
||||
sequencer_delete_strip_data(C, seq);
|
||||
|
@ -1712,7 +1712,7 @@ static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *e
|
|||
}
|
||||
}
|
||||
|
||||
if (sequencer_retiming_mode_is_active(C)) {
|
||||
if (sequencer_retiming_mode_is_active(scene)) {
|
||||
RNA_boolean_set(op->ptr, "use_retiming_mode", true);
|
||||
}
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ void channel_draw_context_init(const bContext *C,
|
|||
|
||||
/* `sequencer_edit.cc` */
|
||||
|
||||
void seq_rectf(const Scene *scene, Sequence *seq, rctf *rectf);
|
||||
void seq_rectf(const Scene *scene, const Sequence *seq, rctf *rectf);
|
||||
Sequence *find_neighboring_sequence(Scene *scene, Sequence *test, int lr, int sel);
|
||||
void recurs_sel_seq(Sequence *seq_meta);
|
||||
int seq_effect_find_selected(Scene *scene,
|
||||
|
@ -178,16 +178,6 @@ bool sequencer_view_strips_poll(bContext *C);
|
|||
*/
|
||||
blender::VectorSet<Sequence *> all_strips_from_context(bContext *C);
|
||||
|
||||
/**
|
||||
* Returns collection with selected strips presented to user. If operation is done in preview,
|
||||
* collection is limited to selected presented strips, that can produce image output at current
|
||||
* frame.
|
||||
*
|
||||
* \param C: context
|
||||
* \return collection of strips (`Sequence`)
|
||||
*/
|
||||
blender::VectorSet<Sequence *> selected_strips_from_context(bContext *C);
|
||||
|
||||
/* Externals. */
|
||||
|
||||
extern EnumPropertyItem sequencer_prop_effect_types[];
|
||||
|
@ -335,12 +325,16 @@ int sequencer_retiming_box_select_exec(bContext *C, wmOperator *op);
|
|||
|
||||
/* `sequencer_retiming_draw.cc` */
|
||||
void sequencer_draw_retiming(const bContext *C, SeqQuadsBatch *quads);
|
||||
blender::Vector<Sequence *> sequencer_visible_strips_get(const bContext *C);
|
||||
SeqRetimingKey *try_to_realize_virtual_key(const bContext *C, Sequence *seq, const int mval[2]);
|
||||
SeqRetimingKey *retiming_mousover_key_get(const bContext *C, const int mval[2], Sequence **r_seq);
|
||||
int left_fake_key_frame_get(const bContext *C, const Sequence *seq);
|
||||
int right_fake_key_frame_get(const bContext *C, const Sequence *seq);
|
||||
bool retiming_keys_are_visible(const bContext *C);
|
||||
bool retiming_keys_are_visible(const SpaceSeq *sseq);
|
||||
rctf retiming_keys_box_get(const Scene *scene, const View2D *v2d, const Sequence *seq);
|
||||
|
||||
/* `sequencer_timeline_draw.cc` */
|
||||
blender::Vector<Sequence *> sequencer_visible_strips_get(const bContext *C);
|
||||
blender::Vector<Sequence *> sequencer_visible_strips_get(const Scene *scene, const View2D *v2d);
|
||||
|
||||
/* `sequencer_clipboard.cc` */
|
||||
int sequencer_clipboard_copy_exec(bContext *C, wmOperator *op);
|
||||
|
|
|
@ -39,9 +39,8 @@
|
|||
|
||||
using blender::MutableSpan;
|
||||
|
||||
bool sequencer_retiming_mode_is_active(const bContext *C)
|
||||
bool sequencer_retiming_mode_is_active(const Scene *scene)
|
||||
{
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene);
|
||||
if (ed == nullptr) {
|
||||
return false;
|
||||
|
@ -90,7 +89,7 @@ static int sequencer_retiming_data_show_exec(bContext *C, wmOperator * /* op */)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (sequencer_retiming_mode_is_active(C)) {
|
||||
if (sequencer_retiming_mode_is_active(scene)) {
|
||||
sequencer_retiming_data_hide_all(ed->seqbasep);
|
||||
}
|
||||
else if (SEQ_retiming_data_is_editable(seq_act)) {
|
||||
|
@ -259,7 +258,7 @@ static int sequencer_retiming_key_add_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
|
||||
int ret_val;
|
||||
blender::VectorSet<Sequence *> strips = selected_strips_from_context(C);
|
||||
blender::VectorSet<Sequence *> strips = ED_sequencer_selected_strips_from_context(C);
|
||||
if (!strips.is_empty()) {
|
||||
ret_val = retiming_key_add_from_selection(C, op, strips, timeline_frame);
|
||||
}
|
||||
|
@ -345,7 +344,7 @@ static bool freeze_frame_add_from_strip_selection(bContext *C,
|
|||
const int duration)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
blender::VectorSet<Sequence *> strips = selected_strips_from_context(C);
|
||||
blender::VectorSet<Sequence *> strips = ED_sequencer_selected_strips_from_context(C);
|
||||
const int timeline_frame = BKE_scene_frame_get(scene);
|
||||
bool success = false;
|
||||
|
||||
|
@ -382,7 +381,7 @@ static int sequencer_retiming_freeze_frame_add_exec(bContext *C, wmOperator *op)
|
|||
duration = RNA_int_get(op->ptr, "duration");
|
||||
}
|
||||
|
||||
if (sequencer_retiming_mode_is_active(C)) {
|
||||
if (sequencer_retiming_mode_is_active(scene)) {
|
||||
success = freeze_frame_add_from_retiming_selection(C, op, duration);
|
||||
}
|
||||
else {
|
||||
|
@ -485,7 +484,7 @@ static int sequencer_retiming_transition_add_exec(bContext *C, wmOperator *op)
|
|||
duration = RNA_int_get(op->ptr, "duration");
|
||||
}
|
||||
|
||||
if (sequencer_retiming_mode_is_active(C)) {
|
||||
if (sequencer_retiming_mode_is_active(scene)) {
|
||||
success = transition_add_from_retiming_selection(C, op, duration);
|
||||
}
|
||||
else {
|
||||
|
@ -541,9 +540,11 @@ static SeqRetimingKey *ensure_left_and_right_keys(const bContext *C, Sequence *s
|
|||
/* Return speed of existing segment or strip. Assume 1 element is selected. */
|
||||
static float strip_speed_get(bContext *C, const wmOperator * /* op */)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
|
||||
/* Strip mode. */
|
||||
if (!sequencer_retiming_mode_is_active(C)) {
|
||||
blender::VectorSet<Sequence *> strips = selected_strips_from_context(C);
|
||||
if (!sequencer_retiming_mode_is_active(scene)) {
|
||||
blender::VectorSet<Sequence *> strips = ED_sequencer_selected_strips_from_context(C);
|
||||
if (strips.size() == 1) {
|
||||
Sequence *seq = strips[0];
|
||||
SeqRetimingKey *key = ensure_left_and_right_keys(C, seq);
|
||||
|
@ -551,7 +552,6 @@ static float strip_speed_get(bContext *C, const wmOperator * /* op */)
|
|||
}
|
||||
}
|
||||
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
blender::Map selection = SEQ_retiming_selection_get(SEQ_editing_get(scene));
|
||||
/* Retiming mode. */
|
||||
if (selection.size() == 1) {
|
||||
|
@ -566,7 +566,7 @@ static float strip_speed_get(bContext *C, const wmOperator * /* op */)
|
|||
static int strip_speed_set_exec(bContext *C, const wmOperator *op)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
blender::VectorSet<Sequence *> strips = selected_strips_from_context(C);
|
||||
blender::VectorSet<Sequence *> strips = ED_sequencer_selected_strips_from_context(C);
|
||||
|
||||
for (Sequence *seq : strips) {
|
||||
SeqRetimingKey *key = ensure_left_and_right_keys(C, seq);
|
||||
|
@ -613,7 +613,7 @@ static int sequencer_retiming_segment_speed_set_exec(bContext *C, wmOperator *op
|
|||
const Scene *scene = CTX_data_scene(C);
|
||||
|
||||
/* Strip mode. */
|
||||
if (!sequencer_retiming_mode_is_active(C)) {
|
||||
if (!sequencer_retiming_mode_is_active(scene)) {
|
||||
return strip_speed_set_exec(C, op);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,9 +42,8 @@
|
|||
#define KEY_SIZE (10 * U.pixelsize)
|
||||
#define KEY_CENTER (UI_view2d_view_to_region_y(v2d, strip_y_rescale(seq, 0.0f)) + 4 + KEY_SIZE / 2)
|
||||
|
||||
bool retiming_keys_are_visible(const bContext *C)
|
||||
bool retiming_keys_are_visible(const SpaceSeq *sseq)
|
||||
{
|
||||
const SpaceSeq *sseq = CTX_wm_space_seq(C);
|
||||
return (sseq->timeline_overlay.flag & SEQ_TIMELINE_SHOW_STRIP_RETIMING) != 0;
|
||||
}
|
||||
|
||||
|
@ -76,67 +75,34 @@ static float pixels_to_view_height(const bContext *C, const float height)
|
|||
return height / scale_y;
|
||||
}
|
||||
|
||||
static float strip_start_screenspace_get(const bContext *C, const Sequence *seq)
|
||||
static float strip_start_screenspace_get(const Scene *scene,
|
||||
const View2D *v2d,
|
||||
const Sequence *seq)
|
||||
{
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
return UI_view2d_view_to_region_x(v2d, SEQ_time_left_handle_frame_get(scene, seq));
|
||||
}
|
||||
|
||||
static float strip_end_screenspace_get(const bContext *C, const Sequence *seq)
|
||||
static float strip_end_screenspace_get(const Scene *scene, const View2D *v2d, const Sequence *seq)
|
||||
{
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
return UI_view2d_view_to_region_x(v2d, SEQ_time_right_handle_frame_get(scene, seq));
|
||||
}
|
||||
|
||||
static rctf strip_box_get(const bContext *C, const Sequence *seq)
|
||||
static rctf strip_box_get(const Scene *scene, const View2D *v2d, const Sequence *seq)
|
||||
{
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
rctf rect;
|
||||
rect.xmin = strip_start_screenspace_get(C, seq);
|
||||
rect.xmax = strip_end_screenspace_get(C, seq);
|
||||
rect.xmin = strip_start_screenspace_get(scene, v2d, seq);
|
||||
rect.xmax = strip_end_screenspace_get(scene, v2d, seq);
|
||||
rect.ymin = UI_view2d_view_to_region_y(v2d, strip_y_rescale(seq, 0));
|
||||
rect.ymax = UI_view2d_view_to_region_y(v2d, strip_y_rescale(seq, 1));
|
||||
return rect;
|
||||
}
|
||||
|
||||
blender::Vector<Sequence *> sequencer_visible_strips_get(const bContext *C)
|
||||
{
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
const Editing *ed = SEQ_editing_get(CTX_data_scene(C));
|
||||
blender::Vector<Sequence *> strips;
|
||||
|
||||
LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
|
||||
if (min_ii(SEQ_time_left_handle_frame_get(scene, seq), SEQ_time_start_frame_get(seq)) >
|
||||
v2d->cur.xmax)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (max_ii(SEQ_time_right_handle_frame_get(scene, seq),
|
||||
SEQ_time_content_end_frame_get(scene, seq)) < v2d->cur.xmin)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (seq->machine + 1.0f < v2d->cur.ymin) {
|
||||
continue;
|
||||
}
|
||||
if (seq->machine > v2d->cur.ymax) {
|
||||
continue;
|
||||
}
|
||||
strips.append(seq);
|
||||
}
|
||||
return strips;
|
||||
}
|
||||
|
||||
/** Size in pixels. */
|
||||
#define RETIME_KEY_MOUSEOVER_THRESHOLD (16.0f * UI_SCALE_FAC)
|
||||
|
||||
static rctf keys_box_get(const bContext *C, const Sequence *seq)
|
||||
rctf retiming_keys_box_get(const Scene *scene, const View2D *v2d, const Sequence *seq)
|
||||
{
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
rctf rect = strip_box_get(C, seq);
|
||||
rctf rect = strip_box_get(scene, v2d, seq);
|
||||
rect.ymax = KEY_CENTER + KEY_SIZE / 2;
|
||||
rect.ymin = KEY_CENTER - KEY_SIZE / 2;
|
||||
return rect;
|
||||
|
@ -163,7 +129,7 @@ static bool retiming_fake_key_is_clicked(const bContext *C,
|
|||
{
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
|
||||
rctf box = keys_box_get(C, seq);
|
||||
rctf box = retiming_keys_box_get(CTX_data_scene(C), v2d, seq);
|
||||
if (!BLI_rctf_isect_pt(&box, mval[0], mval[1])) {
|
||||
return false;
|
||||
}
|
||||
|
@ -231,8 +197,10 @@ static SeqRetimingKey *mouse_over_key_get_from_strip(const bContext *C,
|
|||
|
||||
SeqRetimingKey *retiming_mousover_key_get(const bContext *C, const int mval[2], Sequence **r_seq)
|
||||
{
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
for (Sequence *seq : sequencer_visible_strips_get(C)) {
|
||||
rctf box = keys_box_get(C, seq);
|
||||
rctf box = retiming_keys_box_get(scene, v2d, seq);
|
||||
if (!BLI_rctf_isect_pt(&box, mval[0], mval[1])) {
|
||||
continue;
|
||||
}
|
||||
|
@ -267,7 +235,7 @@ static void retime_key_draw(const bContext *C,
|
|||
const float key_x = key_x_get(scene, seq, key);
|
||||
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
const rctf strip_box = strip_box_get(C, seq);
|
||||
const rctf strip_box = strip_box_get(scene, v2d, seq);
|
||||
if (!BLI_rctf_isect_x(&strip_box, UI_view2d_view_to_region_x(v2d, key_x))) {
|
||||
return; /* Key out of the strip bounds. */
|
||||
}
|
||||
|
@ -405,7 +373,7 @@ static void retime_keys_draw(const bContext *C, SeqQuadsBatch *quads)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!retiming_keys_are_visible(C)) {
|
||||
if (!retiming_keys_are_visible(CTX_wm_space_seq(C))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -573,7 +541,7 @@ static void retime_speed_draw(const bContext *C)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!retiming_keys_are_visible(C)) {
|
||||
if (!retiming_keys_are_visible(CTX_wm_space_seq(C))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "RNA_define.hh"
|
||||
|
||||
#include "SEQ_channels.hh"
|
||||
#include "SEQ_effects.hh"
|
||||
#include "SEQ_iterator.hh"
|
||||
#include "SEQ_relations.hh"
|
||||
#include "SEQ_retiming.hh"
|
||||
|
@ -68,9 +69,9 @@ blender::VectorSet<Sequence *> all_strips_from_context(bContext *C)
|
|||
return SEQ_query_all_strips(seqbase);
|
||||
}
|
||||
|
||||
blender::VectorSet<Sequence *> selected_strips_from_context(bContext *C)
|
||||
blender::VectorSet<Sequence *> ED_sequencer_selected_strips_from_context(bContext *C)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene);
|
||||
ListBase *seqbase = SEQ_active_seqbase_get(ed);
|
||||
ListBase *channels = SEQ_channels_displayed_get(ed);
|
||||
|
@ -247,7 +248,7 @@ void ED_sequencer_select_sequence_single(Scene *scene, Sequence *seq, bool desel
|
|||
recurs_sel_seq(seq);
|
||||
}
|
||||
|
||||
void seq_rectf(const Scene *scene, Sequence *seq, rctf *rect)
|
||||
void seq_rectf(const Scene *scene, const Sequence *seq, rctf *rect)
|
||||
{
|
||||
rect->xmin = SEQ_time_left_handle_frame_get(scene, seq);
|
||||
rect->xmax = SEQ_time_right_handle_frame_get(scene, seq);
|
||||
|
@ -327,7 +328,7 @@ Sequence *find_nearest_seq(const Scene *scene, const View2D *v2d, const int mval
|
|||
if (SEQ_transform_sequence_can_be_translated(seq)) {
|
||||
|
||||
/* Clamp handles to defined size in pixel space. */
|
||||
handsize = 2.0f * sequence_handle_size_get_clamped(scene, seq, pixelx);
|
||||
handsize = 4.0f * sequence_handle_size_get_clamped(scene, seq, pixelx);
|
||||
displen = float(abs(SEQ_time_left_handle_frame_get(scene, seq) -
|
||||
SEQ_time_right_handle_frame_get(scene, seq)));
|
||||
|
||||
|
@ -447,7 +448,7 @@ static int sequencer_de_select_all_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (sequencer_retiming_mode_is_active(C) && retiming_keys_are_visible(C)) {
|
||||
if (sequencer_retiming_mode_is_active(scene) && retiming_keys_are_visible(CTX_wm_space_seq(C))) {
|
||||
return sequencer_retiming_select_all_exec(C, op);
|
||||
}
|
||||
|
||||
|
@ -822,13 +823,26 @@ static Sequence *seq_select_seq_from_preview(
|
|||
return seq_select;
|
||||
}
|
||||
|
||||
static bool element_already_selected(const Sequence *seq, const int handle_clicked)
|
||||
static bool element_already_selected(const Sequence *seq1,
|
||||
const Sequence *seq2,
|
||||
int handle_clicked)
|
||||
{
|
||||
const bool handle_already_selected = ((handle_clicked == SEQ_SIDE_LEFT) &&
|
||||
(seq->flag & SEQ_LEFTSEL)) ||
|
||||
((handle_clicked == SEQ_SIDE_RIGHT) &&
|
||||
(seq->flag & SEQ_RIGHTSEL));
|
||||
return ((seq->flag & SELECT) && handle_clicked == SEQ_SIDE_NONE) || handle_already_selected;
|
||||
if (seq1 == nullptr) {
|
||||
return false;
|
||||
}
|
||||
const bool seq1_already_selected = ((seq1->flag & SELECT) != 0);
|
||||
if (seq2 == nullptr) {
|
||||
const bool handle_already_selected = (seq1->flag & handle_clicked) != 0 ||
|
||||
handle_clicked == SEQ_SIDE_NONE;
|
||||
return seq1_already_selected && handle_already_selected;
|
||||
}
|
||||
const bool seq2_already_selected = ((seq2->flag & SELECT) != 0);
|
||||
const int seq1_handle = seq1->flag & (SEQ_RIGHTSEL | SEQ_LEFTSEL);
|
||||
const int seq2_handle = seq2->flag & (SEQ_RIGHTSEL | SEQ_LEFTSEL);
|
||||
/* Handles must be selected in XOR fashion, with `seq1` matching `handle_clicked`. */
|
||||
const bool both_handles_selected = seq1_handle == handle_clicked && seq2_handle != 0 &&
|
||||
seq1_handle != seq2_handle;
|
||||
return seq1_already_selected && seq2_already_selected && both_handles_selected;
|
||||
}
|
||||
|
||||
static void sequencer_select_strip_impl(const Editing *ed,
|
||||
|
@ -885,15 +899,194 @@ static void sequencer_select_strip_impl(const Editing *ed,
|
|||
}
|
||||
}
|
||||
|
||||
/* Similar to `sequence_handle_size_get_clamped()` but allows for larger clickable area. */
|
||||
static float clickable_handle_size_get(const Scene *scene, const Sequence *seq, const View2D *v2d)
|
||||
{
|
||||
const float pixelx = 1 / UI_view2d_scale_get_x(v2d);
|
||||
const float strip_len = SEQ_time_strip_length_get(scene, seq);
|
||||
return min_ff(15.0f * pixelx * U.pixelsize, strip_len / 4);
|
||||
}
|
||||
|
||||
bool ED_sequencer_can_select_handle(const Scene *scene, const Sequence *seq, const View2D *v2d)
|
||||
{
|
||||
int min_len = 25 * U.pixelsize;
|
||||
if ((U.sequencer_editor_flag & USER_SEQ_ED_SIMPLE_TWEAKING) == 0) {
|
||||
min_len = 15 * U.pixelsize;
|
||||
}
|
||||
|
||||
const float pixelx = 1 / UI_view2d_scale_get_x(v2d);
|
||||
const int strip_len = SEQ_time_right_handle_frame_get(scene, seq) -
|
||||
SEQ_time_left_handle_frame_get(scene, seq);
|
||||
if (strip_len / pixelx < min_len) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void strip_clickable_areas_get(const Scene *scene,
|
||||
const Sequence *seq,
|
||||
const View2D *v2d,
|
||||
rctf *r_body,
|
||||
rctf *r_left_handle,
|
||||
rctf *r_right_handle)
|
||||
{
|
||||
seq_rectf(scene, seq, r_body);
|
||||
memcpy(r_left_handle, r_body, sizeof(*r_left_handle));
|
||||
memcpy(r_right_handle, r_body, sizeof(*r_right_handle));
|
||||
|
||||
const float handsize = clickable_handle_size_get(scene, seq, v2d);
|
||||
BLI_rctf_pad(r_left_handle, handsize / 3, 0.0f);
|
||||
BLI_rctf_pad(r_right_handle, handsize / 3, 0.0f);
|
||||
r_left_handle->xmax = r_body->xmin + handsize;
|
||||
r_right_handle->xmin = r_body->xmax - handsize;
|
||||
BLI_rctf_pad(r_body, -handsize, 0.0f);
|
||||
}
|
||||
|
||||
static rctf strip_clickable_area_get(const Scene *scene, const View2D *v2d, const Sequence *seq)
|
||||
{
|
||||
rctf body, left, right;
|
||||
strip_clickable_areas_get(scene, seq, v2d, &body, &left, &right);
|
||||
BLI_rctf_union(&body, &left);
|
||||
BLI_rctf_union(&body, &right);
|
||||
return body;
|
||||
}
|
||||
|
||||
static float strip_to_frame_distance(const Scene *scene,
|
||||
const View2D *v2d,
|
||||
const Sequence *seq,
|
||||
float timeline_frame)
|
||||
{
|
||||
rctf body, left, right;
|
||||
strip_clickable_areas_get(scene, seq, v2d, &body, &left, &right);
|
||||
return BLI_rctf_length_x(&body, timeline_frame);
|
||||
}
|
||||
|
||||
/* Get strips that can be selected by click. */
|
||||
static blender::Vector<Sequence *> mouseover_strips_sorted_get(const Scene *scene,
|
||||
const View2D *v2d,
|
||||
float mouse_co[2])
|
||||
{
|
||||
blender::Vector<Sequence *> strips = sequencer_visible_strips_get(scene, v2d);
|
||||
const Editing *ed = SEQ_editing_get(scene);
|
||||
|
||||
strips.remove_if([&](Sequence *seq) {
|
||||
rctf body = strip_clickable_area_get(scene, v2d, seq);
|
||||
if (!BLI_rctf_isect_pt_v(&body, mouse_co)) {
|
||||
return true;
|
||||
}
|
||||
if (SEQ_transform_is_locked(ed->displayed_channels, seq)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
/* It may be better to sort strips, as there can be very small strip in set, that may not be
|
||||
* removed by previous conditions. `std::sort` has issues with this container though. */
|
||||
if (strips.size() > 1 && strip_to_frame_distance(scene, v2d, strips[0], mouse_co[0]) <
|
||||
strip_to_frame_distance(scene, v2d, strips[1], mouse_co[0]))
|
||||
{
|
||||
SWAP(Sequence *, strips[0], strips[1]);
|
||||
}
|
||||
|
||||
BLI_assert(strips.size() <= 2);
|
||||
return strips;
|
||||
}
|
||||
|
||||
static bool strips_are_adjacent(const Scene *scene, const Sequence *seq1, const Sequence *seq2)
|
||||
{
|
||||
const int s1_left = SEQ_time_left_handle_frame_get(scene, seq1);
|
||||
const int s1_right = SEQ_time_right_handle_frame_get(scene, seq1);
|
||||
const int s2_left = SEQ_time_left_handle_frame_get(scene, seq2);
|
||||
const int s2_right = SEQ_time_right_handle_frame_get(scene, seq2);
|
||||
|
||||
return s1_right == s2_left || s1_left == s2_right;
|
||||
}
|
||||
|
||||
static int handle_selection_refine(const Scene *scene,
|
||||
const Sequence *seq,
|
||||
const View2D *v2d,
|
||||
float mouse_co[2])
|
||||
{
|
||||
rctf body, left, right;
|
||||
strip_clickable_areas_get(scene, seq, v2d, &body, &left, &right);
|
||||
|
||||
if (!ED_sequencer_can_select_handle(scene, seq, v2d)) {
|
||||
return SEQ_SIDE_NONE;
|
||||
}
|
||||
|
||||
if (BLI_rctf_isect_pt_v(&left, mouse_co)) {
|
||||
return SEQ_SIDE_LEFT;
|
||||
}
|
||||
if (BLI_rctf_isect_pt_v(&right, mouse_co)) {
|
||||
return SEQ_SIDE_RIGHT;
|
||||
}
|
||||
|
||||
return SEQ_SIDE_NONE;
|
||||
}
|
||||
|
||||
static bool both_handles_are_selected(const Scene *scene,
|
||||
const Sequence *seq1,
|
||||
const Sequence *seq2,
|
||||
int seq1_side,
|
||||
const View2D *v2d,
|
||||
float mouse_co[2])
|
||||
{
|
||||
if ((U.sequencer_editor_flag & USER_SEQ_ED_SIMPLE_TWEAKING) == 0) {
|
||||
return false;
|
||||
}
|
||||
if (seq1_side == SEQ_SIDE_NONE) {
|
||||
return false;
|
||||
}
|
||||
if (!strips_are_adjacent(scene, seq1, seq2)) {
|
||||
return false;
|
||||
}
|
||||
const int seq2_side = handle_selection_refine(scene, seq2, v2d, mouse_co);
|
||||
if (seq1_side == SEQ_SIDE_RIGHT && seq2_side != SEQ_SIDE_LEFT) {
|
||||
return false;
|
||||
}
|
||||
else if (seq1_side == SEQ_SIDE_LEFT && seq2_side != SEQ_SIDE_RIGHT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ED_sequencer_handle_selection_refine(const Scene *scene,
|
||||
const View2D *v2d,
|
||||
float mouse_co[2],
|
||||
Sequence **r_seq1,
|
||||
Sequence **r_seq2,
|
||||
int *r_side)
|
||||
{
|
||||
blender::Vector<Sequence *> strips = mouseover_strips_sorted_get(scene, v2d, mouse_co);
|
||||
*r_seq1 = *r_seq2 = nullptr;
|
||||
|
||||
if (strips.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*r_seq1 = strips[0];
|
||||
*r_side = handle_selection_refine(scene, *r_seq1, v2d, mouse_co);
|
||||
|
||||
if (strips.size() == 2 &&
|
||||
both_handles_are_selected(scene, *r_seq1, strips[1], *r_side, v2d, mouse_co))
|
||||
{
|
||||
*r_seq2 = strips[1];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool use_retiming_mode(const bContext *C, const Sequence *seq_key_test)
|
||||
{
|
||||
return seq_key_test && SEQ_retiming_data_is_editable(seq_key_test) &&
|
||||
!sequencer_retiming_mode_is_active(C) && retiming_keys_are_visible(C);
|
||||
!sequencer_retiming_mode_is_active(CTX_data_scene(C)) &&
|
||||
retiming_keys_are_visible(CTX_wm_space_seq(C));
|
||||
}
|
||||
|
||||
int sequencer_select_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
View2D *v2d = UI_view2d_fromcontext(C);
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
Editing *ed = SEQ_editing_get(scene);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
|
@ -912,7 +1105,7 @@ int sequencer_select_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
}
|
||||
|
||||
if (sequencer_retiming_mode_is_active(C) && retiming_keys_are_visible(C)) {
|
||||
if (sequencer_retiming_mode_is_active(scene) && retiming_keys_are_visible(CTX_wm_space_seq(C))) {
|
||||
return sequencer_retiming_key_select_exec(C, op);
|
||||
}
|
||||
|
||||
|
@ -925,21 +1118,30 @@ int sequencer_select_exec(bContext *C, wmOperator *op)
|
|||
int mval[2];
|
||||
mval[0] = RNA_int_get(op->ptr, "mouse_x");
|
||||
mval[1] = RNA_int_get(op->ptr, "mouse_y");
|
||||
float mouse_co[2];
|
||||
UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouse_co[0], &mouse_co[1]);
|
||||
|
||||
int handle_clicked = SEQ_SIDE_NONE;
|
||||
Sequence *seq = nullptr;
|
||||
Sequence *seq2 = nullptr;
|
||||
if (region->regiontype == RGN_TYPE_PREVIEW) {
|
||||
seq = seq_select_seq_from_preview(C, mval, toggle, extend, center);
|
||||
}
|
||||
else {
|
||||
seq = find_nearest_seq(scene, v2d, mval, &handle_clicked);
|
||||
ED_sequencer_handle_selection_refine(scene, v2d, mouse_co, &seq, &seq2, &handle_clicked);
|
||||
}
|
||||
|
||||
if (RNA_boolean_get(op->ptr, "handles_only") && handle_clicked == SEQ_SIDE_NONE) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
/* NOTE: `side_of_frame` and `linked_time` functionality is designed to be shared on one
|
||||
* keymap, therefore both properties can be true at the same time. */
|
||||
Sequence *seq_key_test = nullptr;
|
||||
SeqRetimingKey *key = retiming_mousover_key_get(C, mval, &seq_key_test);
|
||||
|
||||
/* NOTE: `side_of_frame` and `linked_time` functionality is designed to be shared on one keymap,
|
||||
* therefore both properties can be true at the same time. */
|
||||
/* NOTE: `side_of_frame` and `linked_time` functionality is designed to be shared on one
|
||||
* keymap, therefore both properties can be true at the same time. */
|
||||
if (seq && RNA_boolean_get(op->ptr, "linked_time")) {
|
||||
if (use_retiming_mode(C, seq_key_test)) {
|
||||
return sequencer_retiming_select_linked_time(C, op);
|
||||
|
@ -981,7 +1183,9 @@ int sequencer_select_exec(bContext *C, wmOperator *op)
|
|||
|
||||
/* Clicking on already selected element falls on modal operation.
|
||||
* All strips are deselected on mouse button release unless extend mode is used. */
|
||||
if (seq && element_already_selected(seq, handle_clicked) && wait_to_deselect_others && !toggle) {
|
||||
if (element_already_selected(seq, seq2, handle_clicked) && wait_to_deselect_others && !toggle &&
|
||||
!RNA_boolean_get(op->ptr, "handles_only"))
|
||||
{
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
}
|
||||
|
||||
|
@ -1020,6 +1224,11 @@ int sequencer_select_exec(bContext *C, wmOperator *op)
|
|||
|
||||
/* Do actual selection. */
|
||||
sequencer_select_strip_impl(ed, seq, handle_clicked, extend, deselect, toggle);
|
||||
if (seq2 != nullptr) {
|
||||
/* Invert handle selection for second strip */
|
||||
int seq2_handle_clicked = (handle_clicked == SEQ_LEFTSEL) ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
|
||||
sequencer_select_strip_impl(ed, seq2, seq2_handle_clicked, extend, deselect, toggle);
|
||||
}
|
||||
|
||||
sequencer_select_do_updates(C, scene);
|
||||
sequencer_select_set_active(scene, seq);
|
||||
|
@ -1086,6 +1295,11 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
|
|||
"Side of Frame",
|
||||
"Select all strips on same side of the current frame as the mouse cursor");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
/* Used for handle tweaking. */
|
||||
prop = RNA_def_boolean(ot->srna, "handles_only", false, "Handles Only", "Select handles only");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
RNA_def_property_flag(prop, PROP_HIDDEN);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
@ -1665,7 +1879,7 @@ static int sequencer_box_select_exec(bContext *C, wmOperator *op)
|
|||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (sequencer_retiming_mode_is_active(C) && retiming_keys_are_visible(C)) {
|
||||
if (sequencer_retiming_mode_is_active(scene) && retiming_keys_are_visible(CTX_wm_space_seq(C))) {
|
||||
return sequencer_retiming_box_select_exec(C, op);
|
||||
}
|
||||
|
||||
|
@ -1700,7 +1914,7 @@ static int sequencer_box_select_exec(bContext *C, wmOperator *op)
|
|||
if (handles) {
|
||||
/* Get the handles draw size. */
|
||||
float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
|
||||
float handsize = sequence_handle_size_get_clamped(scene, seq, pixelx);
|
||||
float handsize = sequence_handle_size_get_clamped(scene, seq, pixelx) * 4;
|
||||
|
||||
/* Right handle. */
|
||||
if (rectf.xmax > (SEQ_time_right_handle_frame_get(scene, seq) - handsize)) {
|
||||
|
@ -1755,20 +1969,24 @@ static int sequencer_box_select_exec(bContext *C, wmOperator *op)
|
|||
static int sequencer_box_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
View2D *v2d = &CTX_wm_region(C)->v2d;
|
||||
const View2D *v2d = UI_view2d_fromcontext(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
|
||||
if (region->regiontype == RGN_TYPE_PREVIEW && !sequencer_view_preview_only_poll(C)) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
const bool tweak = RNA_boolean_get(op->ptr, "tweak");
|
||||
|
||||
if (tweak) {
|
||||
int hand_dummy;
|
||||
if (RNA_boolean_get(op->ptr, "tweak")) {
|
||||
int mval[2];
|
||||
float mouse_co[2];
|
||||
WM_event_drag_start_mval(event, region, mval);
|
||||
Sequence *seq = find_nearest_seq(scene, v2d, mval, &hand_dummy);
|
||||
UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouse_co[0], &mouse_co[1]);
|
||||
|
||||
int handle_clicked = SEQ_SIDE_NONE;
|
||||
Sequence *seq = nullptr;
|
||||
Sequence *seq2 = nullptr;
|
||||
ED_sequencer_handle_selection_refine(scene, v2d, mouse_co, &seq, &seq2, &handle_clicked);
|
||||
|
||||
if (seq != nullptr) {
|
||||
return OPERATOR_CANCELLED | OPERATOR_PASS_THROUGH;
|
||||
}
|
||||
|
|
|
@ -62,9 +62,6 @@
|
|||
#include "sequencer_intern.hh"
|
||||
#include "sequencer_quads_batch.hh"
|
||||
|
||||
#define SEQ_LEFTHANDLE 1
|
||||
#define SEQ_RIGHTHANDLE 2
|
||||
#define SEQ_HANDLE_SIZE 8.0f
|
||||
#define MUTE_ALPHA 120
|
||||
|
||||
struct StripDrawContext {
|
||||
|
@ -99,6 +96,38 @@ struct TimelineDrawContext {
|
|||
SeqQuadsBatch *quads;
|
||||
};
|
||||
|
||||
blender::Vector<Sequence *> sequencer_visible_strips_get(const bContext *C)
|
||||
{
|
||||
return sequencer_visible_strips_get(CTX_data_scene(C), UI_view2d_fromcontext(C));
|
||||
}
|
||||
|
||||
blender::Vector<Sequence *> sequencer_visible_strips_get(const Scene *scene, const View2D *v2d)
|
||||
{
|
||||
const Editing *ed = SEQ_editing_get(scene);
|
||||
blender::Vector<Sequence *> strips;
|
||||
|
||||
LISTBASE_FOREACH (Sequence *, seq, ed->seqbasep) {
|
||||
if (min_ii(SEQ_time_left_handle_frame_get(scene, seq), SEQ_time_start_frame_get(seq)) >
|
||||
v2d->cur.xmax)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (max_ii(SEQ_time_right_handle_frame_get(scene, seq),
|
||||
SEQ_time_content_end_frame_get(scene, seq)) < v2d->cur.xmin)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (seq->machine + 1.0f < v2d->cur.ymin) {
|
||||
continue;
|
||||
}
|
||||
if (seq->machine > v2d->cur.ymax) {
|
||||
continue;
|
||||
}
|
||||
strips.append(seq);
|
||||
}
|
||||
return strips;
|
||||
}
|
||||
|
||||
static TimelineDrawContext timeline_draw_context_get(const bContext *C)
|
||||
{
|
||||
TimelineDrawContext ctx;
|
||||
|
@ -649,9 +678,53 @@ static void drawmeta_contents(TimelineDrawContext *timeline_ctx, const StripDraw
|
|||
}
|
||||
}
|
||||
|
||||
static void draw_handle_transform_text(const TimelineDrawContext *timeline_ctx,
|
||||
const StripDrawContext *strip_ctx,
|
||||
const short direction)
|
||||
{
|
||||
/* Draw numbers for start and end of the strip next to its handles. */
|
||||
if (strip_ctx->strip_is_too_small || (strip_ctx->seq->flag & SELECT) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((strip_ctx->seq->flag & direction) == 0 && (G.moving & G_TRANSFORM_SEQ) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
char numstr[64];
|
||||
BLF_set_default();
|
||||
|
||||
/* Calculate if strip is wide enough for showing the labels. */
|
||||
size_t numstr_len = SNPRINTF_RLEN(
|
||||
numstr, "%d%d", int(strip_ctx->left_handle), int(strip_ctx->right_handle));
|
||||
const float tot_width = BLF_width(BLF_default(), numstr, numstr_len);
|
||||
|
||||
if (strip_ctx->strip_length / timeline_ctx->pixelx < 20 + tot_width) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uchar col[4] = {255, 255, 255, 255};
|
||||
const float text_margin = 1.2f * strip_ctx->handle_width;
|
||||
const float text_y = strip_ctx->bottom + 0.09f;
|
||||
float text_x = strip_ctx->left_handle;
|
||||
|
||||
if (direction == SEQ_LEFTSEL) {
|
||||
numstr_len = SNPRINTF_RLEN(numstr, "%d", int(strip_ctx->left_handle));
|
||||
text_x += text_margin;
|
||||
}
|
||||
else {
|
||||
numstr_len = SNPRINTF_RLEN(numstr, "%d", int(strip_ctx->right_handle - 1));
|
||||
text_x = strip_ctx->right_handle -
|
||||
(text_margin + timeline_ctx->pixelx * BLF_width(BLF_default(), numstr, numstr_len));
|
||||
}
|
||||
UI_view2d_text_cache_add(timeline_ctx->v2d, text_x, text_y, numstr, numstr_len, col);
|
||||
}
|
||||
|
||||
float sequence_handle_size_get_clamped(const Scene *scene, Sequence *seq, const float pixelx)
|
||||
{
|
||||
const float maxhandle = (pixelx * SEQ_HANDLE_SIZE) * U.pixelsize;
|
||||
const bool use_thin_handle = (U.sequencer_editor_flag & USER_SEQ_ED_SIMPLE_TWEAKING) != 0;
|
||||
const float handle_size = use_thin_handle ? 5.0f : 8.0f;
|
||||
const float maxhandle = (pixelx * handle_size) * U.pixelsize;
|
||||
|
||||
/* Ensure that handle is not wider, than quarter of strip. */
|
||||
return min_ff(maxhandle,
|
||||
|
@ -660,87 +733,52 @@ float sequence_handle_size_get_clamped(const Scene *scene, Sequence *seq, const
|
|||
4.0f));
|
||||
}
|
||||
|
||||
/* Draw a handle, on left or right side of strip. */
|
||||
static void draw_seq_handle(TimelineDrawContext *timeline_ctx,
|
||||
static void draw_seq_handle(const TimelineDrawContext *timeline_ctx,
|
||||
const StripDrawContext *strip_ctx,
|
||||
const short direction)
|
||||
{
|
||||
Sequence *seq = strip_ctx->seq;
|
||||
const bool show_handles = (timeline_ctx->sseq->timeline_overlay.flag &
|
||||
SEQ_TIMELINE_SHOW_HANDLES) != 0;
|
||||
const bool strip_selected = (seq->flag & SELECT) != 0;
|
||||
const bool handle_selected = (seq->flag & direction) != 0;
|
||||
|
||||
if ((!strip_selected || !handle_selected) && !show_handles) {
|
||||
return;
|
||||
}
|
||||
if (SEQ_transform_is_locked(timeline_ctx->channels, seq)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint whichsel = 0;
|
||||
uchar col[4];
|
||||
|
||||
/* Set up co-ordinates and dimensions for either left or right handle. */
|
||||
rctf handle = {0, 0, strip_ctx->bottom, strip_ctx->top};
|
||||
if (direction == SEQ_LEFTHANDLE) {
|
||||
handle.xmin = strip_ctx->left_handle;
|
||||
handle.xmax = strip_ctx->left_handle + strip_ctx->handle_width;
|
||||
whichsel = SEQ_LEFTSEL;
|
||||
if ((seq->type & SEQ_TYPE_EFFECT) && SEQ_effect_get_num_inputs(seq->type) > 0) {
|
||||
return;
|
||||
}
|
||||
else if (direction == SEQ_RIGHTHANDLE) {
|
||||
handle.xmin = strip_ctx->right_handle - strip_ctx->handle_width;
|
||||
handle.xmax = strip_ctx->right_handle;
|
||||
whichsel = SEQ_RIGHTSEL;
|
||||
}
|
||||
|
||||
if (!(seq->type & SEQ_TYPE_EFFECT) || SEQ_effect_get_num_inputs(seq->type) == 0) {
|
||||
|
||||
if (seq->flag & whichsel) {
|
||||
if (strip_ctx->is_active_strip) {
|
||||
UI_GetThemeColor3ubv(TH_SEQ_ACTIVE, col);
|
||||
}
|
||||
else {
|
||||
UI_GetThemeColor3ubv(TH_SEQ_SELECTED, col);
|
||||
/* Make handles slightly brighter than the outlines. */
|
||||
UI_GetColorPtrShade3ubv(col, col, 50);
|
||||
}
|
||||
col[3] = 255;
|
||||
}
|
||||
else {
|
||||
col[0] = col[1] = col[2] = 0;
|
||||
col[3] = 50;
|
||||
}
|
||||
|
||||
timeline_ctx->quads->add_quad(handle.xmin, handle.ymin, handle.xmax, handle.ymax, col);
|
||||
}
|
||||
|
||||
/* Draw numbers for start and end of the strip next to its handles. */
|
||||
if (!strip_ctx->can_draw_strip_content ||
|
||||
!(((seq->flag & SELECT) && (G.moving & G_TRANSFORM_SEQ)) || (seq->flag & whichsel)))
|
||||
{
|
||||
if (!ED_sequencer_can_select_handle(timeline_ctx->scene, seq, timeline_ctx->v2d)) {
|
||||
return;
|
||||
}
|
||||
|
||||
char numstr[64];
|
||||
size_t numstr_len;
|
||||
const int fontid = BLF_default();
|
||||
BLF_set_default();
|
||||
|
||||
/* Calculate if strip is wide enough for showing the labels. */
|
||||
numstr_len = SNPRINTF_RLEN(
|
||||
numstr, "%d%d", int(strip_ctx->left_handle), int(strip_ctx->right_handle));
|
||||
float tot_width = BLF_width(fontid, numstr, numstr_len);
|
||||
|
||||
if (strip_ctx->strip_length / timeline_ctx->pixelx > 20 + tot_width) {
|
||||
col[0] = col[1] = col[2] = col[3] = 255;
|
||||
float text_margin = 1.2f * strip_ctx->handle_width;
|
||||
|
||||
float text_x = strip_ctx->left_handle;
|
||||
const float text_y = strip_ctx->bottom + 0.09f;
|
||||
if (direction == SEQ_LEFTHANDLE) {
|
||||
numstr_len = SNPRINTF_RLEN(numstr, "%d", int(strip_ctx->left_handle));
|
||||
text_x += text_margin;
|
||||
}
|
||||
else {
|
||||
numstr_len = SNPRINTF_RLEN(numstr, "%d", int(strip_ctx->right_handle - 1));
|
||||
text_x = strip_ctx->right_handle -
|
||||
(text_margin + timeline_ctx->pixelx * BLF_width(fontid, numstr, numstr_len));
|
||||
}
|
||||
UI_view2d_text_cache_add(timeline_ctx->v2d, text_x, text_y, numstr, numstr_len, col);
|
||||
uchar col[4];
|
||||
if (strip_selected && handle_selected && seq == SEQ_select_active_get(timeline_ctx->scene)) {
|
||||
UI_GetThemeColor4ubv(TH_SEQ_ACTIVE, col);
|
||||
}
|
||||
else if (strip_selected && handle_selected) {
|
||||
UI_GetThemeColor4ubv(TH_SEQ_SELECTED, col);
|
||||
}
|
||||
else {
|
||||
col[0] = col[1] = col[2] = 0;
|
||||
col[3] = 50;
|
||||
}
|
||||
|
||||
rctf handle = {0, 0, strip_ctx->bottom, strip_ctx->top};
|
||||
if (direction == SEQ_LEFTSEL) {
|
||||
handle.xmin = strip_ctx->left_handle;
|
||||
handle.xmax = strip_ctx->left_handle + strip_ctx->handle_width;
|
||||
}
|
||||
else if (direction == SEQ_RIGHTSEL) {
|
||||
handle.xmin = strip_ctx->right_handle - strip_ctx->handle_width;
|
||||
handle.xmax = strip_ctx->right_handle;
|
||||
}
|
||||
|
||||
timeline_ctx->quads->add_quad(handle.xmin, handle.ymin, handle.xmax, handle.ymax, col);
|
||||
}
|
||||
|
||||
static void draw_seq_outline(TimelineDrawContext *timeline_ctx, const StripDrawContext *strip_ctx)
|
||||
|
@ -1463,8 +1501,10 @@ static void draw_seq_strips(TimelineDrawContext *timeline_ctx,
|
|||
draw_effect_inputs_highlight(timeline_ctx, &strip_ctx);
|
||||
draw_multicam_highlight(timeline_ctx, &strip_ctx);
|
||||
draw_seq_solo_highlight(timeline_ctx, &strip_ctx);
|
||||
draw_seq_handle(timeline_ctx, &strip_ctx, SEQ_LEFTHANDLE);
|
||||
draw_seq_handle(timeline_ctx, &strip_ctx, SEQ_RIGHTHANDLE);
|
||||
draw_seq_handle(timeline_ctx, &strip_ctx, SEQ_LEFTSEL);
|
||||
draw_seq_handle(timeline_ctx, &strip_ctx, SEQ_RIGHTSEL);
|
||||
draw_handle_transform_text(timeline_ctx, &strip_ctx, SEQ_LEFTSEL);
|
||||
draw_handle_transform_text(timeline_ctx, &strip_ctx, SEQ_RIGHTSEL);
|
||||
draw_seq_outline(timeline_ctx, &strip_ctx);
|
||||
}
|
||||
timeline_ctx->quads->draw();
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
/* For menu, popup, icons, etc. */
|
||||
#include "ED_anim_api.hh"
|
||||
#include "ED_screen.hh"
|
||||
#include "ED_sequencer.hh"
|
||||
#include "ED_time_scrub_ui.hh"
|
||||
#include "ED_util_imbuf.hh"
|
||||
|
||||
|
@ -338,7 +339,7 @@ static int sequencer_view_selected_exec(bContext *C, wmOperator *op)
|
|||
{
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ARegion *region = CTX_wm_region(C);
|
||||
blender::VectorSet strips = selected_strips_from_context(C);
|
||||
blender::VectorSet strips = ED_sequencer_selected_strips_from_context(C);
|
||||
View2D *v2d = UI_view2d_fromcontext(C);
|
||||
rctf cur_new = v2d->cur;
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "ED_markers.hh"
|
||||
#include "ED_screen.hh"
|
||||
#include "ED_sequencer.hh"
|
||||
#include "ED_space_api.hh"
|
||||
#include "ED_time_scrub_ui.hh"
|
||||
#include "ED_transform.hh"
|
||||
|
@ -39,6 +40,7 @@
|
|||
#include "WM_api.hh"
|
||||
#include "WM_message.hh"
|
||||
|
||||
#include "SEQ_retiming.hh"
|
||||
#include "SEQ_sequencer.hh"
|
||||
#include "SEQ_time.hh"
|
||||
#include "SEQ_transform.hh"
|
||||
|
@ -646,6 +648,93 @@ static void sequencer_main_region_message_subscribe(const wmRegionMessageSubscri
|
|||
}
|
||||
}
|
||||
|
||||
static bool mouseover_retiming_key(const Scene *scene,
|
||||
const Sequence *seq,
|
||||
const View2D *v2d,
|
||||
const ScrArea *area,
|
||||
float mouse_co_region[2])
|
||||
{
|
||||
const SpaceSeq *sseq = static_cast<SpaceSeq *>(area->spacedata.first);
|
||||
|
||||
if (!SEQ_retiming_data_is_editable(seq) || !retiming_keys_are_visible(sseq)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rctf retiming_keys_box = retiming_keys_box_get(scene, v2d, seq);
|
||||
return BLI_rctf_isect_pt_v(&retiming_keys_box, mouse_co_region);
|
||||
}
|
||||
|
||||
static void sequencer_main_cursor(wmWindow *win, ScrArea *area, ARegion *region)
|
||||
{
|
||||
int wmcursor = WM_CURSOR_DEFAULT;
|
||||
|
||||
const bToolRef *tref = area->runtime.tool;
|
||||
if (!STREQ(tref->idname, "builtin.select")) {
|
||||
WM_cursor_set(win, wmcursor);
|
||||
return;
|
||||
}
|
||||
|
||||
rcti scrub_rect = region->winrct;
|
||||
scrub_rect.ymin = scrub_rect.ymax - UI_TIME_SCRUB_MARGIN_Y;
|
||||
if (BLI_rcti_isect_pt_v(&scrub_rect, win->eventstate->xy)) {
|
||||
WM_cursor_set(win, wmcursor);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((U.sequencer_editor_flag & USER_SEQ_ED_SIMPLE_TWEAKING) == 0) {
|
||||
WM_cursor_set(win, wmcursor);
|
||||
return;
|
||||
}
|
||||
|
||||
float mouse_co_region[2] = {float(win->eventstate->xy[0] - region->winrct.xmin),
|
||||
float(win->eventstate->xy[1] - region->winrct.ymin)};
|
||||
float mouse_co_view[2];
|
||||
UI_view2d_region_to_view(
|
||||
®ion->v2d, mouse_co_region[0], mouse_co_region[1], &mouse_co_view[0], &mouse_co_view[1]);
|
||||
|
||||
const Scene *scene = win->scene;
|
||||
const Editing *ed = SEQ_editing_get(scene);
|
||||
|
||||
if (ed == NULL) {
|
||||
WM_cursor_set(win, wmcursor);
|
||||
return;
|
||||
}
|
||||
|
||||
int side;
|
||||
Sequence *seq1, *seq2;
|
||||
ED_sequencer_handle_selection_refine(scene, ®ion->v2d, mouse_co_view, &seq1, &seq2, &side);
|
||||
|
||||
if (seq1 == nullptr) {
|
||||
WM_cursor_set(win, wmcursor);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mouseover_retiming_key(scene, seq1, ®ion->v2d, area, mouse_co_region)) {
|
||||
WM_cursor_set(win, wmcursor);
|
||||
return;
|
||||
}
|
||||
|
||||
const View2D *v2d = ®ion->v2d;
|
||||
const float scale_y = UI_view2d_scale_get_y(v2d);
|
||||
|
||||
if (!ED_sequencer_can_select_handle(scene, seq1, v2d) || scale_y < 16 * U.pixelsize) {
|
||||
WM_cursor_set(win, wmcursor);
|
||||
return;
|
||||
}
|
||||
|
||||
if (seq1 != nullptr && seq2 != nullptr) {
|
||||
wmcursor = WM_CURSOR_BOTH_HANDLES;
|
||||
}
|
||||
else if (side == SEQ_SIDE_LEFT) {
|
||||
wmcursor = WM_CURSOR_LEFT_HANDLE;
|
||||
}
|
||||
else if (side == SEQ_SIDE_RIGHT) {
|
||||
wmcursor = WM_CURSOR_RIGHT_HANDLE;
|
||||
}
|
||||
|
||||
WM_cursor_set(win, wmcursor);
|
||||
}
|
||||
|
||||
/* *********************** header region ************************ */
|
||||
/* Add handlers, stuff you only do once or on area/region changes. */
|
||||
static void sequencer_header_region_init(wmWindowManager * /*wm*/, ARegion *region)
|
||||
|
@ -1015,6 +1104,9 @@ void ED_spacetype_sequencer()
|
|||
art->message_subscribe = sequencer_main_region_message_subscribe;
|
||||
art->keymapflag = ED_KEYMAP_TOOL | ED_KEYMAP_GIZMO | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES |
|
||||
ED_KEYMAP_ANIMATION;
|
||||
art->cursor = sequencer_main_cursor;
|
||||
art->event_cursor = true;
|
||||
art->clip_gizmo_events_by_ui = true;
|
||||
BLI_addhead(&st->regiontypes, art);
|
||||
|
||||
/* Preview. */
|
||||
|
|
|
@ -150,6 +150,9 @@ enum eTFlag {
|
|||
|
||||
/** Special flag for when the transform code is called after keys have been duplicated. */
|
||||
T_DUPLICATED_KEYFRAMES = 1 << 26,
|
||||
|
||||
/** Handle tweaking with #USER_SEQ_ED_SIMPLE_TWEAKING. */
|
||||
T_HANDLE_TWEAK = 1 << 27
|
||||
};
|
||||
ENUM_OPERATORS(eTFlag, T_DUPLICATED_KEYFRAMES);
|
||||
|
||||
|
|
|
@ -934,7 +934,7 @@ static TransConvertTypeInfo *convert_type_get(const TransInfo *t, Object **r_obj
|
|||
if (t->options & CTX_SEQUENCER_IMAGE) {
|
||||
return &TransConvertType_SequencerImage;
|
||||
}
|
||||
if (sequencer_retiming_mode_is_active(t->context)) {
|
||||
if (sequencer_retiming_mode_is_active(t->scene)) {
|
||||
return &TransConvertType_SequencerRetiming;
|
||||
}
|
||||
return &TransConvertType_Sequencer;
|
||||
|
|
|
@ -696,6 +696,14 @@ static void special_aftertrans_update__sequencer(bContext * /*C*/, TransInfo *t)
|
|||
&t->scene->markers, t->scene, TFM_TIME_EXTEND, t->values_final[0], t->frame_side);
|
||||
}
|
||||
}
|
||||
|
||||
if ((t->flag & T_HANDLE_TWEAK) != 0) {
|
||||
TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t);
|
||||
blender::VectorSet<Sequence *> strips = seq_transform_collection_from_transdata(tc);
|
||||
for (Sequence *seq : strips) {
|
||||
seq->flag &= ~(SEQ_LEFTSEL | SEQ_RIGHTSEL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void transform_convert_sequencer_channel_clamp(TransInfo *t, float r_val[2])
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include <cstdlib>
|
||||
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_sequence_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "BKE_context.hh"
|
||||
|
||||
|
@ -22,6 +24,11 @@
|
|||
#include "transform.hh"
|
||||
#include "transform_mode.hh"
|
||||
|
||||
#include "ED_sequencer.hh"
|
||||
|
||||
#include "SEQ_sequencer.hh"
|
||||
#include "SEQ_time.hh"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
using namespace blender;
|
||||
|
@ -288,6 +295,62 @@ static void calcSpringFactor(MouseInput *mi)
|
|||
}
|
||||
}
|
||||
|
||||
static int transform_seq_slide_strip_cursor_get(const Sequence *seq)
|
||||
{
|
||||
if ((seq->flag & SEQ_LEFTSEL) != 0) {
|
||||
return WM_CURSOR_LEFT_HANDLE;
|
||||
}
|
||||
if ((seq->flag & SEQ_RIGHTSEL) != 0) {
|
||||
return WM_CURSOR_RIGHT_HANDLE;
|
||||
}
|
||||
return WM_CURSOR_NSEW_SCROLL;
|
||||
}
|
||||
|
||||
static int transform_seq_slide_cursor_get(TransInfo *t)
|
||||
{
|
||||
if ((U.sequencer_editor_flag & USER_SEQ_ED_SIMPLE_TWEAKING) == 0) {
|
||||
return WM_CURSOR_NSEW_SCROLL;
|
||||
}
|
||||
|
||||
const Scene *scene = t->scene;
|
||||
blender::VectorSet<Sequence *> strips = ED_sequencer_selected_strips_from_context(t->context);
|
||||
|
||||
if (strips.size() == 1) {
|
||||
t->flag |= T_HANDLE_TWEAK;
|
||||
return transform_seq_slide_strip_cursor_get(strips[0]);
|
||||
}
|
||||
if (strips.size() == 2) {
|
||||
Sequence *seq1 = strips[0];
|
||||
Sequence *seq2 = strips[1];
|
||||
|
||||
if (SEQ_time_left_handle_frame_get(scene, seq1) > SEQ_time_left_handle_frame_get(scene, seq2))
|
||||
{
|
||||
SWAP(Sequence *, seq1, seq2);
|
||||
}
|
||||
|
||||
if (seq1->machine != seq2->machine) {
|
||||
return WM_CURSOR_NSEW_SCROLL;
|
||||
}
|
||||
|
||||
const Scene *scene = t->scene;
|
||||
if (SEQ_time_right_handle_frame_get(scene, seq1) !=
|
||||
SEQ_time_left_handle_frame_get(scene, seq2))
|
||||
{
|
||||
return WM_CURSOR_NSEW_SCROLL;
|
||||
}
|
||||
|
||||
const int cursor1 = transform_seq_slide_strip_cursor_get(seq1);
|
||||
const int cursor2 = transform_seq_slide_strip_cursor_get(seq2);
|
||||
|
||||
if (cursor1 == WM_CURSOR_RIGHT_HANDLE && cursor2 == WM_CURSOR_LEFT_HANDLE) {
|
||||
t->flag |= T_HANDLE_TWEAK;
|
||||
return WM_CURSOR_BOTH_HANDLES;
|
||||
}
|
||||
}
|
||||
|
||||
return WM_CURSOR_NSEW_SCROLL;
|
||||
}
|
||||
|
||||
void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
|
||||
{
|
||||
/* In case we allocate a new value. */
|
||||
|
@ -383,6 +446,11 @@ void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode)
|
|||
t->flag |= T_MODAL_CURSOR_SET;
|
||||
WM_cursor_modal_set(win, WM_CURSOR_NSEW_SCROLL);
|
||||
}
|
||||
/* On ly use special cursor, when tweaking strips with mouse. */
|
||||
if (t->mode == TFM_SEQ_SLIDE && (t->launch_event == 1 || t->launch_event == 3)) {
|
||||
WM_cursor_modal_set(win, transform_seq_slide_cursor_get(t));
|
||||
}
|
||||
|
||||
break;
|
||||
case HLP_SPRING:
|
||||
case HLP_ANGLE:
|
||||
|
|
|
@ -1168,7 +1168,7 @@ void transform_mode_init(TransInfo *t, wmOperator *op, const int mode)
|
|||
t->mode = eTfmMode(mode);
|
||||
t->mode_info = mode_info_get(t, mode);
|
||||
|
||||
if (t->spacetype == SPACE_SEQ && sequencer_retiming_mode_is_active(t->context)) {
|
||||
if (t->spacetype == SPACE_SEQ && sequencer_retiming_mode_is_active(t->scene)) {
|
||||
t->mode_info = &TransMode_translate;
|
||||
}
|
||||
|
||||
|
|
|
@ -634,6 +634,7 @@ typedef enum eSpaceSeq_SequencerTimelineOverlay_Flag {
|
|||
SEQ_TIMELINE_SHOW_STRIP_COLOR_TAG = (1 << 3),
|
||||
SEQ_TIMELINE_SHOW_STRIP_RETIMING = (1 << 4),
|
||||
SEQ_TIMELINE_SHOW_FCURVES = (1 << 5),
|
||||
SEQ_TIMELINE_SHOW_HANDLES = (1 << 6),
|
||||
/** Draw all wave-forms. */
|
||||
SEQ_TIMELINE_ALL_WAVEFORMS = (1 << 7),
|
||||
/** Draw no wave-forms. */
|
||||
|
|
|
@ -1025,7 +1025,7 @@ typedef struct UserDef {
|
|||
/** Pie menu distance from center before a direction is set. */
|
||||
short pie_menu_threshold;
|
||||
|
||||
short _pad6[2];
|
||||
int sequencer_editor_flag; /* eUserpref_SeqEditorFlags */
|
||||
|
||||
char factor_display_type;
|
||||
|
||||
|
@ -1511,6 +1511,10 @@ typedef enum eUserpref_SeqProxySetup {
|
|||
USER_SEQ_PROXY_SETUP_AUTOMATIC = 1,
|
||||
} eUserpref_SeqProxySetup;
|
||||
|
||||
typedef enum eUserpref_SeqEditorFlags {
|
||||
USER_SEQ_ED_SIMPLE_TWEAKING = (1 << 0),
|
||||
} eUserpref_SeqEditorFlags;
|
||||
|
||||
/* Locale Ids. Auto will try to get local from OS. Our default is English though. */
|
||||
/** #UserDef.language */
|
||||
enum {
|
||||
|
|
|
@ -5877,6 +5877,11 @@ static void rna_def_space_sequencer_timeline_overlay(BlenderRNA *brna)
|
|||
RNA_def_property_boolean_sdna(prop, nullptr, "flag", SEQ_TIMELINE_SHOW_STRIP_RETIMING);
|
||||
RNA_def_property_ui_text(prop, "Show Retiming Keys", "Display retiming keys on top of strips");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "show_strip_handles", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "flag", SEQ_TIMELINE_SHOW_HANDLES);
|
||||
RNA_def_property_ui_text(prop, "Show Strip Handles", "Display strip handles when unselected");
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, nullptr);
|
||||
}
|
||||
|
||||
static void rna_def_space_sequencer(BlenderRNA *brna)
|
||||
|
|
|
@ -5572,6 +5572,13 @@ static void rna_def_userdef_edit(BlenderRNA *brna)
|
|||
RNA_def_property_array(prop, 3);
|
||||
RNA_def_property_ui_text(prop, "Sculpt/Paint Overlay Color", "Color of texture overlay");
|
||||
|
||||
/* VSE */
|
||||
prop = RNA_def_property(srna, "use_sequencer_simplified_tweaking", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "sequencer_editor_flag", USER_SEQ_ED_SIMPLE_TWEAKING);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Tweak Handles", "Allows dragging handles without selecting them first");
|
||||
|
||||
/* duplication linking */
|
||||
prop = RNA_def_property(srna, "use_duplicate_mesh", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "dupflag", USER_DUP_MESH);
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
struct Scene;
|
||||
struct Sequence;
|
||||
|
||||
Sequence *SEQ_select_active_get(Scene *scene);
|
||||
Sequence *SEQ_select_active_get(const Scene *scene);
|
||||
bool SEQ_select_active_get_pair(Scene *scene, Sequence **r_seq_act, Sequence **r_seq_other);
|
||||
void SEQ_select_active_set(Scene *scene, Sequence *seq);
|
||||
|
|
|
@ -25,8 +25,8 @@ struct SequencerToolSettings;
|
|||
enum {
|
||||
SEQ_SIDE_MOUSE = -1,
|
||||
SEQ_SIDE_NONE = 0,
|
||||
SEQ_SIDE_LEFT,
|
||||
SEQ_SIDE_RIGHT,
|
||||
SEQ_SIDE_LEFT = (1 << 1), /* Same as SEQ_LEFTSEL. */
|
||||
SEQ_SIDE_RIGHT = (1 << 2), /*Same as SEQ_RIGHTSEL. */
|
||||
SEQ_SIDE_BOTH,
|
||||
SEQ_SIDE_NO_CHANGE,
|
||||
};
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "SEQ_select.hh"
|
||||
#include "SEQ_sequencer.hh"
|
||||
|
||||
Sequence *SEQ_select_active_get(Scene *scene)
|
||||
Sequence *SEQ_select_active_get(const Scene *scene)
|
||||
{
|
||||
const Editing *ed = SEQ_editing_get(scene);
|
||||
|
||||
|
|
|
@ -1181,5 +1181,83 @@ void wm_init_cursor_data()
|
|||
BlenderCursor[WM_CURSOR_PICK_AREA] = &PickAreaCursor;
|
||||
END_CURSOR_BLOCK;
|
||||
|
||||
/********************** Right handle cursor ***********************/
|
||||
BEGIN_CURSOR_BLOCK;
|
||||
|
||||
static char right_handle_bitmap[] = {
|
||||
0x00, 0x00, 0xfc, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0,
|
||||
0x11, 0xc0, 0x31, 0xc0, 0x71, 0xc0, 0x71, 0xc0, 0x31, 0xc0, 0x11,
|
||||
0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xfc, 0x01, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static char right_handle_mask[] = {
|
||||
0xfc, 0x03, 0xfc, 0x03, 0xfc, 0x03, 0xe0, 0x0b, 0xe0, 0x1b, 0xe0,
|
||||
0x3b, 0xe0, 0x7b, 0xe0, 0xfb, 0xe0, 0xfb, 0xe0, 0x7b, 0xe0, 0x3b,
|
||||
0xe0, 0x1b, 0xe0, 0x0b, 0xfc, 0x03, 0xfc, 0x03, 0xfc, 0x03,
|
||||
};
|
||||
|
||||
static BCursor RightHandleCursor = {
|
||||
right_handle_bitmap,
|
||||
right_handle_mask,
|
||||
7,
|
||||
7,
|
||||
false,
|
||||
};
|
||||
|
||||
BlenderCursor[WM_CURSOR_RIGHT_HANDLE] = &RightHandleCursor;
|
||||
END_CURSOR_BLOCK;
|
||||
|
||||
/********************** Left handle cursor ***********************/
|
||||
BEGIN_CURSOR_BLOCK;
|
||||
|
||||
static char left_handle_bitmap[] = {
|
||||
0x00, 0x00, 0x80, 0x3f, 0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x88,
|
||||
0x03, 0x8c, 0x03, 0x8e, 0x03, 0x8e, 0x03, 0x8c, 0x03, 0x88, 0x03,
|
||||
0x80, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x3f, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static char left_handle_mask[] = {
|
||||
0xc0, 0x3f, 0xc0, 0x3f, 0xc0, 0x3f, 0xc0, 0x07, 0xd8, 0x07, 0xdc,
|
||||
0x07, 0xde, 0x07, 0xdf, 0x07, 0xdf, 0x07, 0xde, 0x07, 0xdc, 0x07,
|
||||
0xd8, 0x07, 0xc0, 0x07, 0xc0, 0x3f, 0xc0, 0x3f, 0xc0, 0x3f,
|
||||
};
|
||||
|
||||
static BCursor LeftHandleCursor = {
|
||||
left_handle_bitmap,
|
||||
left_handle_mask,
|
||||
7,
|
||||
7,
|
||||
false,
|
||||
};
|
||||
|
||||
BlenderCursor[WM_CURSOR_LEFT_HANDLE] = &LeftHandleCursor;
|
||||
END_CURSOR_BLOCK;
|
||||
|
||||
/********************** both handles cursor ***********************/
|
||||
BEGIN_CURSOR_BLOCK;
|
||||
|
||||
static char both_handles_bitmap[] = {
|
||||
0x00, 0x00, 0x3f, 0xfc, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38,
|
||||
0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c,
|
||||
0x38, 0x1c, 0x38, 0x1c, 0x38, 0x1c, 0x3f, 0xfc, 0x00, 0x00,
|
||||
};
|
||||
|
||||
static char both_handles_mask[] = {
|
||||
0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7c, 0x3e, 0x7c, 0x3e, 0x7c,
|
||||
0x3e, 0x7c, 0x3e, 0x7c, 0x3e, 0x7c, 0x3e, 0x7c, 0x3e, 0x7c, 0x3e,
|
||||
0x7c, 0x3e, 0x7c, 0x3e, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe,
|
||||
};
|
||||
|
||||
static BCursor BothHandlesCursor = {
|
||||
both_handles_bitmap,
|
||||
both_handles_mask,
|
||||
7,
|
||||
7,
|
||||
false,
|
||||
};
|
||||
|
||||
BlenderCursor[WM_CURSOR_BOTH_HANDLES] = &BothHandlesCursor;
|
||||
END_CURSOR_BLOCK;
|
||||
|
||||
/********************** Put the cursors in the array ***********************/
|
||||
}
|
||||
|
|
|
@ -57,6 +57,10 @@ enum WMCursorType {
|
|||
|
||||
WM_CURSOR_PICK_AREA,
|
||||
|
||||
WM_CURSOR_LEFT_HANDLE,
|
||||
WM_CURSOR_RIGHT_HANDLE,
|
||||
WM_CURSOR_BOTH_HANDLES,
|
||||
|
||||
/* --- ALWAYS LAST ----- */
|
||||
WM_CURSOR_NUM,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue