1 # SPDX-FileCopyrightText: 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors
3 # SPDX-License-Identifier: GPL-3.0-or-later
5 from operator
import attrgetter
9 from .utils
.doc
import doc_brief
, doc_description
, doc_idname
, doc_name
10 from .utils
.functions
import find_strips_in_range
, move_selection
, trim_strips
13 class POWER_SEQUENCER_OT_channel_offset(bpy
.types
.Operator
):
15 Move selected strip to the nearest open channel above/down
19 "name": doc_name(__qualname__
),
21 "description": doc_description(__doc__
),
24 {"type": "UP_ARROW", "value": "PRESS", "alt": True},
25 {"direction": "up", "trim_target_channel": False},
26 "Move to Open Channel Above",
29 {"type": "UP_ARROW", "value": "PRESS", "ctrl": True, "alt": True},
30 {"direction": "up", "trim_target_channel": True},
31 "Move to Channel Above and Trim",
34 {"type": "DOWN_ARROW", "value": "PRESS", "alt": True},
35 {"direction": "down", "trim_target_channel": False},
36 "Move to Open Channel Below",
39 {"type": "DOWN_ARROW", "value": "PRESS", "ctrl": True, "alt": True},
40 {"direction": "down", "trim_target_channel": True},
41 "Move to Channel Below and Trim",
44 "keymap": "Sequencer",
46 bl_idname
= doc_idname(__qualname__
)
47 bl_label
= doc
["name"]
48 bl_description
= doc_brief(doc
["description"])
49 bl_options
= {"REGISTER", "UNDO"}
51 direction
: bpy
.props
.EnumProperty(
53 ("up", "up", "Move the selection 1 channel up"),
54 ("down", "down", "Move the selection 1 channel down"),
57 description
="Move the sequences up or down",
60 trim_target_channel
: bpy
.props
.BoolProperty(
62 description
="Trim strips to make space in the target channel",
65 keep_selection_offset
: bpy
.props
.BoolProperty(
66 name
="Keep selection offset",
67 description
="The selected strips preserve their relative positions",
72 def poll(cls
, context
):
73 return context
.selected_sequences
75 def execute(self
, context
):
80 if self
.direction
== "up":
82 limit_channel
= max_channel
83 comparison_function
= min
85 if self
.direction
== "down":
87 limit_channel
= min_channel
88 comparison_function
= max
90 selection
= [s
for s
in context
.selected_sequences
if not s
.lock
]
95 sequences
= sorted(selection
, key
=attrgetter("channel", "frame_final_start"))
96 if self
.direction
== "up":
97 sequences
= [s
for s
in reversed(sequences
)]
100 if not self
.keep_selection_offset
or (
101 head
.channel
!= limit_channel
and self
.keep_selection_offset
104 if self
.trim_target_channel
:
105 channel_trim
= s
.channel
+ channel_offset
106 strips_in_trim_channel
= [
108 for sequence
in context
.sequences
109 if (sequence
.channel
== channel_trim
)
111 if strips_in_trim_channel
:
112 to_delete
, to_trim
= find_strips_in_range(
113 s
.frame_final_start
, s
.frame_final_end
, strips_in_trim_channel
116 context
, s
.frame_final_start
, s
.frame_final_end
, to_trim
, to_delete
119 s
.channel
= comparison_function(limit_channel
, s
.channel
+ channel_offset
)
120 if s
.channel
== limit_channel
:
121 move_selection(context
, [s
], 0, 0)
123 if self
.keep_selection_offset
and not self
.trim_target_channel
:
124 start_frame
= head
.frame_final_start
126 while not head
.channel
== limit_channel
:
127 move_selection(context
, sequences
, -x_difference
, channel_offset
)
128 x_difference
= head
.frame_final_start
- start_frame
129 if x_difference
== 0: