| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||
| # Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors | ||
| import bpy | ||
| from math import floor | ||
|
|
||
| from .utils.functions import find_strips_mouse | ||
| from .utils.functions import trim_strips | ||
| from .utils.functions import get_frame_range | ||
| from .utils.doc import doc_name, doc_idname, doc_brief, doc_description | ||
|
|
||
|
|
||
| class POWER_SEQUENCER_OT_mouse_trim_instantly(bpy.types.Operator): | ||
| """ | ||
| *brief* Trim strip from a start to an end frame instantly | ||
| Trims a frame range or a selection from a start to an end frame. | ||
| If there's no precise time range, auto trims based on the closest cut | ||
| Args: | ||
| - frame_start and frame_end (int) define the frame range to trim | ||
| """ | ||
|
|
||
| doc = { | ||
| "name": doc_name(__qualname__), | ||
| "demo": "", | ||
| "description": doc_description(__doc__), | ||
| "shortcuts": [ | ||
| ( | ||
| {"type": "RIGHTMOUSE", "value": "PRESS", "ctrl": True, "alt": True}, | ||
| {"select_mode": "CONTEXT"}, | ||
| "Trim strip, keep gap", | ||
| ), | ||
| ( | ||
| {"type": "RIGHTMOUSE", "value": "PRESS", "ctrl": True, "alt": True, "shift": True}, | ||
| {"select_mode": "CURSOR"}, | ||
| "Trim strip, remove gap", | ||
| ), | ||
| ], | ||
| "keymap": "Sequencer", | ||
| } | ||
| bl_idname = doc_idname(__qualname__) | ||
| bl_label = doc["name"] | ||
| bl_description = doc_brief(doc["description"]) | ||
| bl_options = {"REGISTER", "UNDO"} | ||
|
|
||
| select_mode: bpy.props.EnumProperty( | ||
| items=[ | ||
| ("CONTEXT", "Smart", "Uses the selection if possible, else uses the other modes"), | ||
| ("CURSOR", "Time cursor", "Select all of the strips the time cursor overlaps"), | ||
| ], | ||
| name="Selection mode", | ||
| description="Auto-select the strip you click on or that the time cursor overlaps", | ||
| default="CONTEXT", | ||
| ) | ||
| select_linked: bpy.props.BoolProperty( | ||
| name="Use linked time", | ||
| description="If auto-select, cut linked strips if checked", | ||
| default=False, | ||
| ) | ||
| gap_remove: bpy.props.BoolProperty( | ||
| name="Remove gaps", | ||
| description="When trimming the sequences, remove gaps automatically", | ||
| default=True, | ||
| ) | ||
|
|
||
| @classmethod | ||
| def poll(cls, context): | ||
| return context.sequences | ||
|
|
||
| def invoke(self, context, event): | ||
| to_trim = [] | ||
| frame, channel = -1, -1 | ||
| x, y = context.region.view2d.region_to_view(x=event.mouse_region_x, y=event.mouse_region_y) | ||
| frame, channel = round(x), floor(y) | ||
|
|
||
| mouse_clicked_strip = find_strips_mouse(context, frame, channel, self.select_linked) | ||
| to_trim += mouse_clicked_strip | ||
| if self.select_mode == "CURSOR" or (self.select_mode == "CONTEXT" and to_trim == []): | ||
| to_trim += [ | ||
| s | ||
| for s in context.sequences | ||
| if s.frame_final_start <= frame <= s.frame_final_end and not s.lock | ||
| ] | ||
| if not to_trim: | ||
| return {"FINISHED"} | ||
|
|
||
| frame_cut_closest = min(get_frame_range(to_trim), key=lambda f: abs(frame - f)) | ||
| frame_start = min(frame, frame_cut_closest) | ||
| frame_end = max(frame, frame_cut_closest) | ||
|
|
||
| trim_strips(context, frame_start, frame_end, to_trim=to_trim) | ||
|
|
||
| context.scene.frame_current = frame | ||
|
|
||
| if self.gap_remove and self.select_mode == "CURSOR": | ||
| bpy.ops.power_sequencer.gap_remove(frame=frame_start, move_time_cursor=True) | ||
|
|
||
| return {"FINISHED"} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,31 +1,33 @@ | ||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||
| # Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors | ||
| if __name__ == "__main__": | ||
| import bpy | ||
|
|
||
| render = bpy.context.scene.render | ||
| render.resolution_x = 1280 | ||
| render.resolution_y = 720 | ||
| render.resolution_percentage = 100 | ||
| render.pixel_aspect_x = 1 | ||
| render.pixel_aspect_y = 1 | ||
|
|
||
| # FFMPEG | ||
| render.image_settings.file_format = "FFMPEG" | ||
| render.ffmpeg.format = "MPEG4" | ||
| render.ffmpeg.codec = "H264" | ||
|
|
||
| render.ffmpeg.constant_rate_factor = "HIGH" | ||
| render.ffmpeg.ffmpeg_preset = "BEST" | ||
|
|
||
| is_ntsc = render.fps != 25 | ||
| if is_ntsc: | ||
| render.ffmpeg.gopsize = 18 | ||
| else: | ||
| render.ffmpeg.gopsize = 15 | ||
| render.ffmpeg.use_max_b_frames = False | ||
|
|
||
| render.ffmpeg.video_bitrate = 4000 | ||
| render.ffmpeg.maxrate = 4000 | ||
| render.ffmpeg.minrate = 0 | ||
| render.ffmpeg.buffersize = 224 * 8 | ||
| render.ffmpeg.packetsize = 2048 | ||
| render.ffmpeg.muxrate = 10080000 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,31 +1,34 @@ | ||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||
| # Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors | ||
| if __name__ == "__main__": | ||
| import bpy | ||
|
|
||
| render = bpy.context.scene.render | ||
| render.resolution_x = 1920 | ||
| render.resolution_y = 1080 | ||
| render.resolution_percentage = 100 | ||
| render.pixel_aspect_x = 1 | ||
| render.pixel_aspect_y = 1 | ||
|
|
||
| render.image_settings.file_format = "FFMPEG" | ||
| render.ffmpeg.format = "MPEG4" | ||
| render.ffmpeg.codec = "H264" | ||
|
|
||
| render.ffmpeg.constant_rate_factor = "PERC_LOSSLESS" | ||
| render.ffmpeg.ffmpeg_preset = "BEST" | ||
|
|
||
| scene = bpy.context.scene | ||
| fps = scene.render.fps / scene.render.fps_base | ||
| render.ffmpeg.gopsize = round(fps / 2.0) | ||
| render.ffmpeg.use_max_b_frames = True | ||
| render.ffmpeg.max_b_frames = 2 | ||
|
|
||
| render.ffmpeg.video_bitrate = 9000 | ||
| render.ffmpeg.maxrate = 9000 | ||
| render.ffmpeg.minrate = 0 | ||
| render.ffmpeg.buffersize = 224 * 8 | ||
| render.ffmpeg.packetsize = 2048 | ||
| render.ffmpeg.muxrate = 10080000 | ||
|
|
||
| render.ffmpeg.audio_codec = "AAC" | ||
| render.ffmpeg.audio_bitrate = 384 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||
| # Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors | ||
| import bpy | ||
|
|
||
| from .utils.doc import doc_name, doc_idname, doc_brief, doc_description | ||
|
|
||
|
|
||
| class POWER_SEQUENCER_OT_select_all_left_or_right(bpy.types.Operator): | ||
| """ | ||
| *Brief* Selects all strips left or right of the time cursor | ||
| """ | ||
|
|
||
| doc = { | ||
| "name": doc_name(__qualname__), | ||
| "demo": "", | ||
| "description": doc_description(__doc__), | ||
| "shortcuts": [ | ||
| ( | ||
| {"type": "Q", "value": "PRESS", "shift": True}, | ||
| {"side": "LEFT"}, | ||
| "Select all strips to the LEFT of the time cursor", | ||
| ), | ||
| ( | ||
| {"type": "E", "value": "PRESS", "shift": True}, | ||
| {"side": "RIGHT"}, | ||
| "Select all strips to the right of the time cursor", | ||
| ), | ||
| ], | ||
| "keymap": "Sequencer", | ||
| } | ||
| bl_idname = doc_idname(__qualname__) | ||
| bl_label = doc["name"] | ||
| bl_description = doc_brief(doc["description"]) | ||
| bl_options = {"REGISTER", "UNDO"} | ||
|
|
||
| side: bpy.props.EnumProperty( | ||
| name="Side", | ||
| description=("Side to select"), | ||
| items=[ | ||
| ("LEFT", "Left", "Move strips back in time, to the left"), | ||
| ("RIGHT", "Right", "Move strips forward in time, to the right"), | ||
| ], | ||
| default="LEFT", | ||
| ) | ||
|
|
||
| @classmethod | ||
| def poll(cls, context): | ||
| return context.sequences | ||
|
|
||
| def execute(self, context): | ||
| if self.side == "LEFT": | ||
| for s in context.sequences: | ||
| s.select = s.frame_final_end < context.scene.frame_current | ||
| else: | ||
| for s in context.sequences: | ||
| s.select = s.frame_final_start > context.scene.frame_current | ||
| return {"FINISHED"} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,42 +1,44 @@ | ||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||
| # Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors | ||
| import bpy | ||
|
|
||
| from .utils.functions import find_strips_mouse | ||
| from .utils.functions import get_mouse_frame_and_channel | ||
| from .utils.doc import doc_name, doc_idname, doc_brief, doc_description | ||
|
|
||
|
|
||
| class POWER_SEQUENCER_OT_select_closest_to_mouse(bpy.types.Operator): | ||
| """ | ||
| Select the closest strip under the mouse cursor | ||
| """ | ||
|
|
||
| doc = { | ||
| "name": doc_name(__qualname__), | ||
| "demo": "", | ||
| "description": doc_description(__doc__), | ||
| "shortcuts": [], | ||
| "keymap": "Sequencer", | ||
| } | ||
| bl_idname = doc_idname(__qualname__) | ||
| bl_label = doc["name"] | ||
| bl_description = doc_brief(doc["description"]) | ||
| bl_options = {"REGISTER", "UNDO"} | ||
|
|
||
| frame: bpy.props.IntProperty(name="Frame") | ||
| channel: bpy.props.IntProperty(name="Channel") | ||
|
|
||
| @classmethod | ||
| def poll(cls, context): | ||
| return context.sequences | ||
|
|
||
| def invoke(self, context, event): | ||
| self.frame, self.channel = get_mouse_frame_and_channel(context, event) | ||
| return self.execute(context) | ||
|
|
||
| def execute(self, context): | ||
| try: | ||
| strip = find_strips_mouse(context, self.frame, self.channel)[0] | ||
| strip.select = True | ||
| except Exception: | ||
| return {"CANCELLED"} | ||
| return {"FINISHED"} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||
| # Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors | ||
| import bpy | ||
|
|
||
| from .utils.functions import get_sequences_under_cursor | ||
| from .utils.doc import doc_name, doc_idname, doc_brief, doc_description | ||
|
|
||
|
|
||
| class POWER_SEQUENCER_OT_snap(bpy.types.Operator): | ||
| """ | ||
| *Brief* Snaps selected strips to the time cursor ignoring locked sequences. | ||
| Automatically selects sequences if there is no active selection | ||
| """ | ||
|
|
||
| doc = { | ||
| "name": doc_name(__qualname__), | ||
| "demo": "", | ||
| "description": doc_description(__doc__), | ||
| "shortcuts": [ | ||
| ( | ||
| {"type": "S", "value": "PRESS", "shift": True}, | ||
| {}, | ||
| "Snap sequences to cursor", | ||
| ) | ||
| ], | ||
| "keymap": "Sequencer", | ||
| } | ||
| bl_idname = doc_idname(__qualname__) | ||
| bl_label = doc["name"] | ||
| bl_description = doc_brief(doc["description"]) | ||
| bl_options = {"REGISTER", "UNDO"} | ||
|
|
||
| @classmethod | ||
| def poll(cls, context): | ||
| return context.sequences | ||
|
|
||
| def execute(self, context): | ||
| sequences = ( | ||
| context.selected_sequences | ||
| if len(context.selected_sequences) > 0 | ||
| else get_sequences_under_cursor(context) | ||
| ) | ||
| frame = context.scene.frame_current | ||
| for s in sequences: | ||
| s.select = True | ||
| bpy.ops.sequencer.snap(frame=frame) | ||
| return {"FINISHED"} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||
| # Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors | ||
| import bpy | ||
| from .utils.functions import get_sequences_under_cursor, move_selection | ||
| from .utils.doc import doc_name, doc_idname, doc_brief, doc_description | ||
|
|
||
|
|
||
| class POWER_SEQUENCER_OT_snap_selection(bpy.types.Operator): | ||
| """ | ||
| *Brief* Snap the entire selection to the time cursor. | ||
| Automatically selects sequences if there is no active selection. | ||
| To snap each strip individually, see Snap | ||
| """ | ||
|
|
||
| doc = { | ||
| "name": doc_name(__qualname__), | ||
| "demo": "", | ||
| "description": doc_description(__doc__), | ||
| "shortcuts": [ | ||
| ( | ||
| {"type": "S", "value": "PRESS", "alt": True}, | ||
| {}, | ||
| "Snap selection to cursor", | ||
| ) | ||
| ], | ||
| "keymap": "Sequencer", | ||
| } | ||
| bl_idname = doc_idname(__qualname__) | ||
| bl_label = doc["name"] | ||
| bl_description = doc_brief(doc["description"]) | ||
| bl_options = {"REGISTER", "UNDO"} | ||
|
|
||
| @classmethod | ||
| def poll(cls, context): | ||
| return context.sequences | ||
|
|
||
| def execute(self, context): | ||
| sequences = ( | ||
| context.selected_sequences | ||
| if context.selected_sequences | ||
| else get_sequences_under_cursor(context) | ||
| ) | ||
| frame_first = min(sequences, key=lambda s: s.frame_final_start).frame_final_start | ||
| time_offset = context.scene.frame_current - frame_first | ||
| move_selection(context, sequences, time_offset) | ||
| return {"FINISHED"} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||
| # Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors | ||
| import bpy | ||
|
|
||
| from .utils.functions import convert_duration_to_frames | ||
| from .utils.global_settings import SequenceTypes | ||
| from .utils.doc import doc_name, doc_idname, doc_brief, doc_description | ||
|
|
||
|
|
||
| class POWER_SEQUENCER_OT_space_sequences(bpy.types.Operator): | ||
| """ | ||
| *brief* Offsets all strips to the right of the time cursor by a given duration, ignoring locked sequences | ||
| """ | ||
|
|
||
| doc = { | ||
| "name": doc_name(__qualname__), | ||
| "demo": "", | ||
| "description": doc_description(__doc__), | ||
| "shortcuts": [({"type": "EQUAL", "value": "PRESS"}, {}, "")], | ||
| "keymap": "Sequencer", | ||
| } | ||
| bl_idname = doc_idname(__qualname__) | ||
| bl_label = doc["name"] | ||
| bl_description = doc_brief(doc["description"]) | ||
| bl_options = {"REGISTER", "UNDO"} | ||
|
|
||
| gap_to_insert: bpy.props.FloatProperty( | ||
| name="Duration", description="The time offset to apply to the strips", default=1.0 | ||
| ) | ||
|
|
||
| @classmethod | ||
| def poll(cls, context): | ||
| return context.sequences | ||
|
|
||
| def invoke(self, context, event): | ||
| sequences = [ | ||
| s | ||
| for s in context.sequences | ||
| if s.type in SequenceTypes.CUTABLE | ||
| and s.frame_final_start >= context.scene.frame_current | ||
| and not s.lock | ||
| ] | ||
|
|
||
| gap_frames = convert_duration_to_frames(context, self.gap_to_insert) | ||
| sorted_sequences = sorted(sequences, key=lambda s: s.frame_final_start, reverse=True) | ||
| for s in sorted_sequences: | ||
| s.frame_start += gap_frames | ||
|
|
||
| markers = context.scene.timeline_markers | ||
| for m in [m for m in markers if m.frame >= context.scene.frame_current]: | ||
| m.frame += gap_frames | ||
| return {"FINISHED"} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||
| # Copyright (C) 2016-2020 by Nathan Lovato, Daniel Oakey, Razvan Radulescu, and contributors |