diff options
author | meta-androcto <meta.androcto1@gmail.com> | 2019-05-24 11:30:36 +0300 |
---|---|---|
committer | meta-androcto <meta.androcto1@gmail.com> | 2019-05-24 11:30:36 +0300 |
commit | dccb34a6395db94999c8416552a8b3e479697b31 (patch) | |
tree | 1df9cd37dc41945fe00e4d1f9fb5e29aba633f62 | |
parent | 774a8331c371ad798c59b569d30be5c6e3ab169d (diff) |
sequencer_kinoraw_tools: move to contrib: T63750
-rw-r--r-- | sequencer_kinoraw_tools/__init__.py | 399 | ||||
-rw-r--r-- | sequencer_kinoraw_tools/audio_tools.py | 358 | ||||
-rw-r--r-- | sequencer_kinoraw_tools/datamosh.py | 189 | ||||
-rw-r--r-- | sequencer_kinoraw_tools/eco.py | 127 | ||||
-rw-r--r-- | sequencer_kinoraw_tools/exiftool.py | 330 | ||||
-rw-r--r-- | sequencer_kinoraw_tools/functions.py | 455 | ||||
-rw-r--r-- | sequencer_kinoraw_tools/jumptocut.py | 656 | ||||
-rw-r--r-- | sequencer_kinoraw_tools/operators_extra_actions.py | 1302 | ||||
-rw-r--r-- | sequencer_kinoraw_tools/proxy_tools.py | 344 | ||||
-rw-r--r-- | sequencer_kinoraw_tools/random_editor.py | 138 | ||||
-rw-r--r-- | sequencer_kinoraw_tools/recursive_loader.py | 266 | ||||
-rw-r--r-- | sequencer_kinoraw_tools/ui.py | 765 |
12 files changed, 0 insertions, 5329 deletions
diff --git a/sequencer_kinoraw_tools/__init__.py b/sequencer_kinoraw_tools/__init__.py deleted file mode 100644 index c4af8988..00000000 --- a/sequencer_kinoraw_tools/__init__.py +++ /dev/null @@ -1,399 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -bl_info = { - "name": "Kinoraw Tools", - "author": "Carlos Padial, Turi Scandurra", - "version": (0, 5, 2), - "blender": (2, 74, 0), - "location": "Sequencer", - "description": "Compilation of tools to improve video editing with Blender's VSE", - "wiki_url": "https://github.com/kinoraw/kinoraw_tools/blob/master/README.md", - "tracker_url": "https://github.com/kinoraw/kinoraw_tools", - "support": "COMMUNITY", - "category": "Sequencer" - } - - -if "bpy" in locals(): - import importlib - importlib.reload(jumptocut) - importlib.reload(operators_extra_actions) - importlib.reload(audio_tools) - importlib.reload(proxy_tools) - importlib.reload(recursive_loader) - importlib.reload(eco) - importlib.reload(random_editor) - importlib.reload(ui) - importlib.reload(datamosh) -else: - from . import jumptocut - from . import operators_extra_actions - from . import audio_tools - from . import proxy_tools - from . import recursive_loader - from . import eco - from . import random_editor - from . import ui - from . import datamosh - -import bpy -from bpy.types import ( - AddonPreferences, - ) -from bpy.props import ( - IntProperty, - StringProperty, - BoolProperty, - EnumProperty, - ) - - -class KinorawToolsAddon(AddonPreferences): - # this must match the addon name, use '__package__' - # when defining this in a submodule of a python package. - bl_idname = __package__ - bl_option = {'REGISTER'} - - # extra_actions - kr_show_tools: BoolProperty( - name="Show tools", - description="Show extra tools in the panel", - default=False - ) - kr_mini_ui: BoolProperty( - name="Mini UI", - description="Enable mini UI", - default=True - ) - kr_show_info: BoolProperty( - name="Show info", - description="Show basic info from selected strip", - default=False - ) - kr_show_trim: BoolProperty( - name="Show trim", - default=False - ) - kr_show_modifiers: BoolProperty( - name="Show modifiers", - description="Show modifiers from selected strip", - default=False - ) - kr_extra_info: BoolProperty( - name="Show extra info", - description="Show extra info and settings from selected strip", - default=False - ) - # exif - use_exif_panel: BoolProperty( - name="Exif info Panel | depends on external programs, see Documentation", - default=False - ) - # glitch - use_glitch_panel: BoolProperty( - name="Glitch panel | depends on external programs, see Documentation", - default=False - ) - all_keyframes: BoolProperty( - name="Remove all keyframes", - default=True - ) - load_glitch: BoolProperty( - name="Load glitch after conversion > UNSTABLE!!!", - default=True - ) - # jump to cut - use_jumptocut: BoolProperty( - name="Jump to Cut Panel", - default=True - ) - use_io_tools: BoolProperty( - name="Enable in and out tools in Jump to Cut Panel", - default=False - ) - # Proxy Tools - use_proxy_tools: BoolProperty( - name="Proxy tools Panel | depends on external programs, see Documentation", - default=False - ) - proxy_dir: StringProperty( - name="Proxy Custom Directory", - default="//proxies/" - ) - proxy_scripts_path: StringProperty( - name="Directory to store proxy scripts", - default="//proxy_scripts/" - ) - proxy_scripts: BoolProperty( - name="Generate ffmpeg scripts", - default=False - ) - ffmpeg_command: StringProperty( - name="Command to generate proxy", - default='''ffmpeg -i {} -vcodec mjpeg -q:v 10 -s {}x{} -an -y {}''' - ) - use_internal_proxy = BoolProperty( - name="Use internal Blender's proxy system", - default=True - ) - use_bi_custom_directory = BoolProperty( - name="Proxy Custom Directory", - default=True - ) - quality = IntProperty( - name="Quality", - default=90, - min=0, max=32767 - ) - tc_list = [ - ("NONE", "No TC in use", ""), ("RECORD_RUN", "Record Run", ""), - ("FREE_RUN", "Free Run", ""), ("FREE_RUN_REC_DATE", "Free Run (rec date)", ""), - ("RECORD_RUN_NO_GAPS", "Record Run No Gaps", "") - ] - timecode = EnumProperty( - name="Settings Type", - items=tc_list, - default="NONE", - description="Timecode" - ) - # Audio Tools - use_audio_tools = BoolProperty( - name="Audio tools Panel | depends on external programs, see Documentation", - default=False - ) - audio_dir = StringProperty( - name="Path to store extracted audio", - default="//audio/" - ) - audio_scripts_path = StringProperty( - name="Path to store audio scripts", - default="//audio_scripts/" - ) - audio_scripts = BoolProperty( - name="Generate ffmpeg scripts", - default=False - ) - # Audio Tools - external links - audio_use_external_links = BoolProperty( - name="Use external audio linked to movie strips", - default=False - ) - audio_external_filename = StringProperty( - name="File to store info about linked audio", - default="//external_audio_sync_info.txt" - ) - # audio tools vu-meter - meterbridge = [ - ("VU", "Classic moving needle VU meter", ""), ("PPM", "PPM meter", ""), - ("DPM", "Digital peak meter", ""), ("JF", "'Jellyfish' phase meter", ""), - ("SCO", "Oscilloscope meter", "") - ] - metertype = EnumProperty( - name="Meter type", - items=meterbridge, - default="DPM", - description="Meterbridge meter type" - ) - # eco - use_eco_tools = BoolProperty( - name="Eco tools Panel", - default=True - ) - eco_value = IntProperty( - name="Number of echoes", - default=5, - min=1, max=25 - ) - eco_offset = IntProperty( - name="Echo Offset", - default=1, - min=-25000, max=25000 - ) - eco_use_add_blend_mode = BoolProperty( - name='use_add_blend_mode', - default=False - ) - # random editor - use_random_editor = BoolProperty( - name="Random editor Panel | Experimental", - default=False - ) - random_frames = IntProperty( - name="Frames", - default=1, - min=1, max=1000 - ) - random_selected_scene = StringProperty( - name="Selected Scene", - default="" - ) - random_use_marker_subsets = BoolProperty( - name="Use_Marker subsets", - default=True - ) - random_number_of_subsets = IntProperty( - name="Number of subsets", - default=3, - min=1, max=5 - ) - show_shortcuts = BoolProperty( - name="Hot Keys", - default=False, - description="List of the shortcuts used for the included various tools", - ) - show_experimental = BoolProperty( - name="Tools with External Dependencies / Experimental", - default=False, - description="List of various tools that need an External Library " - "or are Experimental\nPlease read the Documentation " - "before enabling them", - ) - - def draw(self, context): - layout = self.layout - icon_1 = "TRIA_RIGHT" if not self.show_shortcuts else "TRIA_DOWN" - icon_2 = "TRIA_RIGHT" if not self.show_experimental else "TRIA_DOWN" - - box = layout.box() - box.prop(self, "use_jumptocut") - box = layout.box() - box.prop(self, "use_eco_tools") - - box_exp = layout.box() - box_exp.prop(self, "show_experimental", emboss=False, icon=icon_2) - - if self.show_experimental: - box = box_exp.box() - box.prop(self, "use_audio_tools") - box = box_exp.box() - box.prop(self, "use_proxy_tools") - box = box_exp.box() - box.prop(self, "use_exif_panel") - box = box_exp.box() - box.prop(self, "use_glitch_panel") - box = box_exp.box() - box.prop(self, "use_random_editor") - - box = layout.box() - box.prop(self, "show_shortcuts", emboss=False, icon=icon_1) - - if self.show_shortcuts: - box.label(text="Skip One Second Forward: Ctrl + Shift + Right Arrow", icon="LAYER_USED") - box.label(text="Skip One Second Backwards: Ctrl + Shift + Left Arrow", icon="LAYER_USED") - box.label(text="Jump to Previous Strip: Q", icon="LAYER_USED") - box.label(text="Jump to Next Strip: W", icon="LAYER_USED") - box.label(text="Source IN: Ctrl + Shift + I", icon="LAYER_USED") - box.label(text="Source OUT: Ctrl + Shift + O", icon="LAYER_USED") - box.label(text="Jump to Previous Marker: Shift + Q", icon="LAYER_USED") - box.label(text="Jump to Next Marker: Shift + W", icon="LAYER_USED") - - -# Registration -def register(): - bpy.utils.register_class(KinorawToolsAddon) - - bpy.utils.register_module(__name__) - - # Append menu entries - bpy.types.SEQUENCER_MT_add.prepend(ui.sequencer_add_menu_func) - bpy.types.SEQUENCER_MT_select.prepend(ui.sequencer_select_menu_func) - bpy.types.SEQUENCER_MT_strip.prepend(ui.sequencer_strip_menu_func) - bpy.types.SEQUENCER_HT_header.append(ui.sequencer_header_func) - bpy.types.CLIP_HT_header.append(ui.clip_header_func) - bpy.types.CLIP_MT_clip.prepend(ui.clip_clip_menu_func) - bpy.types.TIME_MT_frame.prepend(ui.time_frame_menu_func) - bpy.types.TIME_HT_header.append(ui.time_header_func) - - # Add keyboard shortcut configuration - kc = bpy.context.window_manager.keyconfigs.addon - km = kc.keymaps.new(name='Frames') - - # jump 1 second - kmi = km.keymap_items.new('screenextra.frame_skip', - 'RIGHT_ARROW', 'PRESS', ctrl=True, shift=True) - kmi.properties.back = False - kmi = km.keymap_items.new('screenextra.frame_skip', - 'LEFT_ARROW', 'PRESS', ctrl=True, shift=True) - kmi.properties.back = True - - # jump to cut - kmi = km.keymap_items.new("sequencer.strip_jump", - 'Q', 'PRESS', ctrl=False, shift=False) - kmi.properties.next = False - kmi.properties.center = False - kmi = km.keymap_items.new("sequencer.strip_jump", - 'W', 'PRESS', ctrl=False, shift=False) - kmi.properties.next = True - kmi.properties.center = False - - # in and out - kmi = km.keymap_items.new("sequencerextra.sourcein", - 'I', 'PRESS', ctrl=True, shift=True) - kmi = km.keymap_items.new("sequencerextra.sourceout", - 'O', 'PRESS', ctrl=True, shift=True) - - # markers - kc = bpy.context.window_manager.keyconfigs.active - km = kc.keymaps.new(name='Screen') - kmi = km.keymap_items.new("screen.marker_jump", - 'Q', 'PRESS', ctrl=False, shift=True) - kmi.properties.next = False - kmi = km.keymap_items.new("screen.marker_jump", - 'W', 'PRESS', ctrl=False, shift=True) - kmi.properties.next = True - - -def unregister(): - bpy.utils.unregister_module(__name__) - - try: - bpy.utils.unregister_class(KinorawToolsAddon) - except RuntimeError: - pass - - # Remove menu entries - bpy.types.SEQUENCER_MT_add.remove(ui.sequencer_add_menu_func) - bpy.types.SEQUENCER_MT_select.remove(ui.sequencer_select_menu_func) - bpy.types.SEQUENCER_MT_strip.remove(ui.sequencer_strip_menu_func) - bpy.types.SEQUENCER_HT_header.remove(ui.sequencer_header_func) - bpy.types.CLIP_HT_header.remove(ui.clip_header_func) - bpy.types.CLIP_MT_clip.remove(ui.clip_clip_menu_func) - bpy.types.TIME_MT_frame.remove(ui.time_frame_menu_func) - bpy.types.TIME_HT_header.remove(ui.time_header_func) - - # Remove keyboard shortcut configuration - kc = bpy.context.window_manager.keyconfigs.addon - km = kc.keymaps['Frames'] - km.keymap_items.remove(km.keymap_items['screenextra.frame_skip']) - km.keymap_items.remove(km.keymap_items['screenextra.frame_skip']) - - km.keymap_items.remove(km.keymap_items['sequencer.strip_jump']) - km.keymap_items.remove(km.keymap_items['sequencer.strip_jump']) - - km.keymap_items.remove(km.keymap_items['sequencerextra.sourcein']) - km.keymap_items.remove(km.keymap_items['sequencerextra.sourceout']) - - kc = bpy.context.window_manager.keyconfigs.active - km = kc.keymaps['Screen'] - km.keymap_items.remove(km.keymap_items['screen.marker_jump']) - km.keymap_items.remove(km.keymap_items['screen.marker_jump']) - - -if __name__ == '__main__': - register() diff --git a/sequencer_kinoraw_tools/audio_tools.py b/sequencer_kinoraw_tools/audio_tools.py deleted file mode 100644 index 82a9a834..00000000 --- a/sequencer_kinoraw_tools/audio_tools.py +++ /dev/null @@ -1,358 +0,0 @@ -# gpl: authors Carlos Padial, Turi Scandurra - -import bpy -import os -from bpy.types import ( - Operator, - Panel, - ) -import subprocess -from . import functions - - -proxy_qualities = [ - ("1", "25%", ""), ("2", "50%", ""), - ("3", "75%", ""), ("4", "100%", "")] - -# -# ls *.sh | parallel -j 8 sh {} -# - - -# functions -def createsyncfile(filename): - if not os.path.isfile(bpy.path.abspath(filename)): - f = open(bpy.path.abspath(filename), "w") - data = [] - - try: - f.writelines(data) # Write a sequence of strings to a file - finally: - f.close() - - -def readsyncfile(filename): - try: - file = open(bpy.path.abspath(filename)) - data = file.readlines() - file.close() - - return data - - except IOError: - pass - - -def writesyncfile(filename, data): - try: - f = open(bpy.path.abspath(filename), "w") - try: - for line in data: - f.writelines(line) # Write a sequence of strings to a file - finally: - f.close() - - except IOError: - pass - - -# classes - -class ExtractWavOperator(Operator): - bl_idname = "sequencer.extract_wav_operator" - bl_label = "Extract Wav from movie strip Operator" - bl_description = "Use ffmpeg to extract audio from video and import it synced" - - @staticmethod - def has_sequencer(context): - return (context.space_data.view_type in - {'SEQUENCER', 'SEQUENCER_PREVIEW'}) - - @classmethod - def poll(self, context): - strip = functions.act_strip(context) - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return strip.type in ('MOVIE') - else: - return False - - def execute(self, context): - - preferences = context.preferences - audio_dir = preferences.addons[__package__].preferences.audio_dir - - functions.create_folder(bpy.path.abspath(audio_dir)) - - for strip in context.selected_editable_sequences: - - # get filename - if strip.type == "MOVIE": - filename = bpy.path.abspath(strip.filepath) - newfilename = bpy.path.abspath(strip.filepath).rpartition( - "/")[2] - fileoutput = os.path.join( - bpy.path.abspath(audio_dir), - newfilename) + ".wav" - - # check for wav existing file - if not os.path.isfile(fileoutput): - # if not, extract the file - extract_audio = "ffmpeg -i '{}' -acodec pcm_s16le -ac 2 {}".\ - format(filename, fileoutput) - print(extract_audio) - os.system(extract_audio) - else: - print("The audio File exists") - - if strip.type == "MOVIE": - # import the file and trim in the same way the original - bpy.ops.sequencer.sound_strip_add( - filepath=fileoutput, - frame_start=strip.frame_start, - channel=strip.channel + 1, - replace_sel=True, overlap=False, - cache=False - ) - - # Update view_layer - context.view_layer.update() - - newstrip = context.scene.sequence_editor.active_strip - - # deselect all other strips - for i in context.selected_editable_sequences: - if i.name != newstrip.name: - i.select = False - - # Update view_layer - context.view_layer.update() - - # Match the original clip's length - newstrip.frame_start = strip.frame_start - strip.animation_offset_start - - functions.triminout(newstrip, - strip.frame_start + strip.frame_offset_start, - strip.frame_start + strip.frame_offset_start + - strip.frame_final_duration) - - return {'FINISHED'} - - -class ExternalAudioSetSyncOperator(Operator): - bl_idname = "sequencer.external_audio_set_sync" - bl_label = "set sync info" - bl_description = ("Get sync info from selected audio and video strip " - "and store it into a text file") - - @staticmethod - def has_sequencer(context): - return (context.space_data.view_type in - {'SEQUENCER', 'SEQUENCER_PREVIEW'}) - - @classmethod - def poll(cls, context): - if cls.has_sequencer(context): - if len(context.selected_editable_sequences) == 2: - types = [] - for i in context.selected_editable_sequences: - types.append(i.type) - if 'MOVIE' and 'SOUND' in types: - return True - else: - return False - - def execute(self, context): - - preferences = context.preferences - filename = preferences.addons[__package__].preferences.audio_external_filename - - for strip in context.selected_editable_sequences: - if strip.type == "MOVIE": - moviestrip = strip - elif strip.type == "SOUND": - soundstrip = strip - - offset = str(moviestrip.frame_start - soundstrip.frame_start) - - data1 = readsyncfile(filename) - data2 = [] - newline = moviestrip.filepath + " " + soundstrip.filepath + " " + offset + "\n" - - if data1 is not None: - repeated = False - for line in data1: - if line.split()[0] == moviestrip.filepath and line.split()[1] == soundstrip.filepath: - data2.append(newline) - repeated = True - else: - data2.append(line) - if not repeated: - data2.append(newline) - else: - data2.append(newline) - - createsyncfile(filename) - writesyncfile(filename, data2) - - return {'FINISHED'} - - -class ExternalAudioReloadOperator(Operator): - bl_idname = "sequencer.external_audio_reload" - bl_label = "Reload External audio" - bl_description = ("Reload external audio synced to selected movie strip " - "according to info from a text file") - - @staticmethod - def has_sequencer(context): - return (context.space_data.view_type in - {'SEQUENCER', 'SEQUENCER_PREVIEW'}) - - @classmethod - def poll(cls, context): - if cls.has_sequencer(context): - if len(context.selected_editable_sequences) == 1: - if context.selected_editable_sequences[0].type == 'MOVIE': - return True - else: - return False - - def execute(self, context): - preferences = context.preferences - filename = preferences.addons[__package__].preferences.audio_external_filename - - data = readsyncfile(filename) - - for strip in context.selected_editable_sequences: - sounds = [] - - for line in data: - if line.split()[0] == strip.filepath: - moviefile = bpy.path.abspath(line.split()[0]) - soundfile = bpy.path.abspath(line.split()[1]) - offset = int(line.split()[2]) - sounds.append((soundfile, offset)) - - for soundfile, offset in sounds: - print(soundfile, offset) - print(strip.filepath) - # find start frame for sound strip (using offset from file) - sound_frame_start = strip.frame_start - strip.animation_offset_start - offset - - # import the file and trim in the same way the original - bpy.ops.sequencer.sound_strip_add( - filepath=soundfile, - frame_start=sound_frame_start, - channel=strip.channel + 1, - replace_sel=True, overlap=False, - cache=False - ) - - # Update view_layer - context.view_layer.update() - - newstrip = context.scene.sequence_editor.active_strip - - # deselect all other strips - for i in context.selected_editable_sequences: - if i.name != newstrip.name: - i.select = False - - # Update view_layer - context.view_layer.update() - - # trim sound strip like original one - functions.triminout(newstrip, - strip.frame_start + strip.frame_offset_start, - strip.frame_start + strip.frame_offset_start + - strip.frame_final_duration - ) - - return {'FINISHED'} - - -class AudioToolPanel(Panel): - bl_label = "Audio Tools" - bl_idname = "OBJECT_PT_AudioTool" - bl_space_type = 'SEQUENCE_EDITOR' - bl_region_type = 'UI' - - @classmethod - def poll(self, context): - if context.space_data.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}: - scn = context.scene - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - if prefs.use_audio_tools: - return True - else: - return False - - def draw_header(self, context): - layout = self.layout - layout.label(text="", icon="PLAY_AUDIO") - - def draw(self, context): - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - - strip = functions.act_strip(context) - - if strip.type == "MOVIE": - layout = self.layout - layout.prop(prefs, "audio_dir", text="Path for Audio files") - - layout.operator("sequencer.extract_wav_operator", text="Extract Wav") - - layout = self.layout - layout.prop(prefs, "audio_scripts") - - if prefs.audio_scripts: - layout = self.layout - layout.prop(prefs, "audio_scripts_path", text="Path for scripts") - - layout = self.layout - layout.prop(prefs, "audio_use_external_links", text="External Audio sync") - - if prefs.audio_use_external_links: - layout = self.layout - layout.prop(prefs, "audio_external_filename", text="Sync data") - - row = layout.row(align=True) - row.operator("sequencer.external_audio_set_sync", text="Set sync") - row.operator("sequencer.external_audio_reload", text="Reload Audio") - - layout = self.layout - - row = layout.row() - row.prop(prefs, "metertype", text="") - row.operator("sequencer.openmeterbridge", - text="Launch Audio Meter", icon="SOUND") - - -class OpenMeterbridgeOperator(Operator): - bl_idname = "sequencer.openmeterbridge" - bl_label = "External VU meter" - bl_description = "Open external VU meter to work with Jack" - - @staticmethod - def has_sequencer(context): - return (context.space_data.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}) - - @classmethod - def poll(cls, context): - if cls.has_sequencer(context): - if len(context.selected_editable_sequences) == 1: - return True - - def execute(self, context): - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - - command = "meterbridge -t {} 'PulseAudio JACK Sink:front-left' " \ - "'PulseAudio JACK Sink:front-right' &".format(prefs.metertype.lower()) - p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) - - return {'FINISHED'} diff --git a/sequencer_kinoraw_tools/datamosh.py b/sequencer_kinoraw_tools/datamosh.py deleted file mode 100644 index f64adbed..00000000 --- a/sequencer_kinoraw_tools/datamosh.py +++ /dev/null @@ -1,189 +0,0 @@ -# gpl: authors Carlos Padial, Turi Scandurra - -import bpy -import os -from bpy.props import IntProperty -from bpy.types import ( - Operator, - Panel, - ) -from . import functions - - -proxy_qualities = [ - ("1", "25%", ""), ("2", "50%", ""), - ("3", "75%", ""), ("4", "100%", ""), - ("5", "none", "") - ] - - -# functions -def createdatamosh(context, strip): - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - - fileinput = bpy.path.abspath(strip.filepath) - fileoutput = fileinput.rpartition(".")[0] + "_datamosh.avi" - - if prefs.all_keyframes: - command = "datamosh '{}' -a -o '{}'".format(fileinput, fileoutput) - else: - command = "datamosh '{}' -o '{}'".format(fileinput, fileoutput) - print(command) - os.system(command) - return fileoutput - - -def createavi(context, strip): - fileinput = bpy.path.abspath(strip.filepath) - fileoutput = fileinput.rpartition(".")[0] + "_.avi" - - command = "ffmpeg -i '{}' -vcodec copy '{}'".format(fileinput, fileoutput) - - print(command) - os.system(command) - - return fileoutput - - -def createavimjpeg(context, strip): - fileinput = bpy.path.abspath(strip.filepath) - fileoutput = fileinput.rpartition(".")[0] + "_mjpeg.avi" - - command = "ffmpeg -i '{}' -vcodec mjpeg -q:v 1 '{}'".format(fileinput, fileoutput) - - print(command) - os.system(command) - - return fileoutput - - -# classes -class CreateAvi(Operator): - bl_idname = "sequencer.createavi" - bl_label = "Create avi file" - bl_description = "Create an avi output file" - bl_options = {'REGISTER', 'UNDO'} - - size: IntProperty( - name="proxysize", - default=1 - ) - - @classmethod - def poll(self, context): - strip = functions.act_strip(context) - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return strip.type in ('MOVIE') - else: - return False - - def execute(self, context): - strips = functions.get_selected_strips(context) - - for strip in strips: - # deselect all other strips - for i in strips: - i.select = False - # select current strip - strip.select = True - if strip.type == "MOVIE": - if self.size == 1: - fileoutput = createavi(context, strip) - elif self.size == 2: - fileoutput = createavimjpeg(context, strip) - strip.filepath = fileoutput - - # select all strips again - for strip in strips: - try: - strip.select = True - except ReferenceError: - pass - - bpy.ops.sequencer.reload() - - return {'FINISHED'} - - -class CreateDatamosh(Operator): - bl_idname = "sequencer.createdatamosh" - bl_label = "Create Datamosh" - bl_description = "Create Datamosh" - - @classmethod - def poll(self, context): - strip = functions.act_strip(context) - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return strip.type in ('MOVIE') - else: - return False - - def execute(self, context): - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - strips = functions.get_selected_strips(context) - - for strip in strips: - # deselect all other strips - for i in strips: - i.select = False - # select current strip - strip.select = True - if strip.type == "MOVIE": - fileoutput = createdatamosh(context, strip) - if prefs.load_glitch: - strip.filepath = fileoutput - - # select all strips again - for strip in strips: - try: - strip.select = True - except ReferenceError: - pass - - bpy.ops.sequencer.reload() - - return {'FINISHED'} - - -class CreateGlitchToolPanel(Panel): - bl_label = "Glitch Tools" - bl_idname = "OBJECT_PT_GlitchTool" - bl_space_type = 'SEQUENCE_EDITOR' - bl_region_type = 'UI' - - @classmethod - def poll(self, context): - if context.space_data.view_type in {'SEQUENCER', - 'SEQUENCER_PREVIEW'}: - strip = functions.act_strip(context) - scn = context.scene - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - if prefs.use_glitch_panel: - return strip.type in ('MOVIE') - else: - return False - - def draw_header(self, context): - layout = self.layout - layout.label(text="", icon="GAME") - - def draw(self, context): - - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - - layout = self.layout - - layout.operator("sequencer.createavi", text="Create avi (same codec)") - layout.operator("sequencer.createavi", text="Create avi (mjpeg)").size = 2 - - layout.prop(prefs, "all_keyframes") - layout.prop(prefs, "load_glitch") - - layout.operator("sequencer.createdatamosh") diff --git a/sequencer_kinoraw_tools/eco.py b/sequencer_kinoraw_tools/eco.py deleted file mode 100644 index 55810b55..00000000 --- a/sequencer_kinoraw_tools/eco.py +++ /dev/null @@ -1,127 +0,0 @@ -# File sequencer_slide_strip.py - -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - - -import bpy -from bpy.types import ( - Operator, - Panel, - ) -from . import functions - - -class EcoPanel(Panel): - bl_label = "Eco Tool" - bl_idname = "OBJECT_PT_EcoTool" - bl_space_type = "SEQUENCE_EDITOR" - bl_region_type = "UI" - - @staticmethod - def has_sequencer(context): - return (context.space_data.view_type in - {'SEQUENCER', 'SEQUENCER_PREVIEW'}) - - @classmethod - def poll(self, context): - if context.space_data.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}: - strip = functions.act_strip(context) - scn = context.scene - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - if prefs.use_eco_tools: - return strip.type in ('META') - else: - return False - - def draw_header(self, context): - layout = self.layout - layout.label(text="", icon="FORCE_HARMONIC") - - def draw(self, context): - strip = functions.act_strip(context) - seq_type = strip.type - - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - - if seq_type in ('MOVIE', 'IMAGE', 'META', 'MOVIECLIP', 'SCENE'): - layout = self.layout - col = layout.column() - - col.prop(prefs, "eco_value", text="Ecos") - col.prop(prefs, "eco_offset", text="Offset") - col.prop(prefs, "eco_use_add_blend_mode", text="Use add blend mode") - col.operator("sequencer.eco") - - -class OBJECT_OT_EcoOperator(Operator): - bl_idname = "sequencer.eco" - bl_label = "Eco operator" - bl_description = "Generate an echo effect by duplicating the selected strip" - bl_options = {'REGISTER', 'UNDO'} - - @staticmethod - def has_sequencer(context): - return (context.space_data.view_type in - {'SEQUENCER', 'SEQUENCER_PREVIEW'}) - - @classmethod - def poll(self, context): - strip = functions.act_strip(context) - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return strip.type in ('META') - else: - return False - - def execute(self, context): - active_strip = functions.act_strip(context) - - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - - eco = prefs.eco_value - offset = prefs.eco_offset - - active_strip.blend_type = 'REPLACE' - active_strip.blend_alpha = 1 - for i in range(eco): - bpy.ops.sequencer.duplicate(mode='TRANSLATION') - bpy.ops.transform.seq_slide( - value=(offset, 1), snap=False, snap_target='CLOSEST', - snap_point=(0, 0, 0), snap_align=False, - snap_normal=(0, 0, 0), release_confirm=False - ) - - active_strip = functions.act_strip(context) - - if prefs.eco_use_add_blend_mode: - active_strip.blend_type = 'ADD' - active_strip.blend_alpha = 1 - 1 / eco - else: - active_strip.blend_type = 'ALPHA_OVER' - active_strip.blend_alpha = 1 / eco - - bpy.ops.sequencer.select_all(action='TOGGLE') - bpy.ops.sequencer.select_all(action='TOGGLE') - bpy.ops.sequencer.meta_make() - - return {'FINISHED'} diff --git a/sequencer_kinoraw_tools/exiftool.py b/sequencer_kinoraw_tools/exiftool.py deleted file mode 100644 index e51b825c..00000000 --- a/sequencer_kinoraw_tools/exiftool.py +++ /dev/null @@ -1,330 +0,0 @@ -# -*- coding: utf-8 -*- -# PyExifTool <http://github.com/smarnach/pyexiftool> -# Copyright 2012 Sven Marnach - -# This file is part of PyExifTool. -# -# PyExifTool is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# PyExifTool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with PyExifTool. If not, see <http://www.gnu.org/licenses/>. - -""" -PyExifTool is a Python library to communicate with an instance of Phil -Harvey's excellent ExifTool_ command-line application. The library -provides the class :py:class:`ExifTool` that runs the command-line -tool in batch mode and features methods to send commands to that -program, including methods to extract meta-information from one or -more image files. Since ``exiftool`` is run in batch mode, only a -single instance needs to be launched and can be reused for many -queries. This is much more efficient than launching a separate -process for every single query. - -.. _ExifTool: http://www.sno.phy.queensu.ca/~phil/exiftool/ - -The source code can be checked out from the github repository with - -:: - - git clone git://github.com/smarnach/pyexiftool.git - -Alternatively, you can download a tarball_. There haven't been any -releases yet. - -.. _tarball: https://github.com/smarnach/pyexiftool/tarball/master - -PyExifTool is licenced under GNU GPL version 3 or later. - -Example usage:: - - import exiftool - - files = ["a.jpg", "b.png", "c.tif"] - with exiftool.ExifTool() as et: - metadata = et.get_metadata_batch(files) - for d in metadata: - print("{:20.20} {:20.20}".format(d["SourceFile"], - d["EXIF:DateTimeOriginal"])) -""" - -from __future__ import unicode_literals - -import sys -import subprocess -import os -import json -import warnings -import codecs - -try: # Py3k compatibility - basestring -except NameError: - basestring = (bytes, str) - -executable = "exiftool" -"""The name of the executable to run. - -If the executable is not located in one of the paths listed in the -``PATH`` environment variable, the full path should be given here. -""" - -# Sentinel indicating the end of the output of a sequence of commands. -# The standard value should be fine. -sentinel = b"{ready}" - -# The block size when reading from exiftool. The standard value -# should be fine, though other values might give better performance in -# some cases. -block_size = 4096 - -# This code has been adapted from Lib/os.py in the Python source tree -# (sha1 265e36e277f3) - - -def _fscodec(): - encoding = sys.getfilesystemencoding() - errors = "strict" - if encoding != "mbcs": - try: - codecs.lookup_error("surrogateescape") - except LookupError: - pass - else: - errors = "surrogateescape" - - def fsencode(filename): - """ - Encode filename to the filesystem encoding with 'surrogateescape' error - handler, return bytes unchanged. On Windows, use 'strict' error handler - if the file system encoding is 'mbcs' (which is the default encoding). - """ - if isinstance(filename, bytes): - return filename - else: - return filename.encode(encoding, errors) - - return fsencode - -fsencode = _fscodec() -del _fscodec - - -class ExifTool(object): - """Run the `exiftool` command-line tool and communicate to it. - - You can pass the file name of the ``exiftool`` executable as an - argument to the constructor. The default value ``exiftool`` will - only work if the executable is in your ``PATH``. - - Most methods of this class are only available after calling - :py:meth:`start()`, which will actually launch the subprocess. To - avoid leaving the subprocess running, make sure to call - :py:meth:`terminate()` method when finished using the instance. - This method will also be implicitly called when the instance is - garbage collected, but there are circumstance when this won't ever - happen, so you should not rely on the implicit process - termination. Subprocesses won't be automatically terminated if - the parent process exits, so a leaked subprocess will stay around - until manually killed. - - A convenient way to make sure that the subprocess is terminated is - to use the :py:class:`ExifTool` instance as a context manager:: - - with ExifTool() as et: - ... - - .. warning:: Note that there is no error handling. Nonsensical - options will be silently ignored by exiftool, so there's not - much that can be done in that regard. You should avoid passing - non-existent files to any of the methods, since this will lead - to undefined behaviour. - - .. py:attribute:: running - - A Boolean value indicating whether this instance is currently - associated with a running subprocess. - """ - - def __init__(self, executable_=None): - if executable_ is None: - self.executable = executable - else: - self.executable = executable_ - self.running = False - - def start(self): - """Start an ``exiftool`` process in batch mode for this instance. - - This method will issue a ``UserWarning`` if the subprocess is - already running. The process is started with the ``-G`` and - ``-n`` as common arguments, which are automatically included - in every command you run with :py:meth:`execute()`. - """ - if self.running: - warnings.warn("ExifTool already running; doing nothing.") - return - with open(os.devnull, "w") as devnull: - self._process = subprocess.Popen( - [self.executable, "-stay_open", "True", "-@", "-", - "-common_args", "-G", "-u", "-a", "-n"], - stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=devnull) - self.running = True - - def terminate(self): - """Terminate the ``exiftool`` process of this instance. - - If the subprocess isn't running, this method will do nothing. - """ - if not self.running: - return - self._process.stdin.write(b"-stay_open\nFalse\n") - self._process.stdin.flush() - self._process.communicate() - del self._process - self.running = False - - def __enter__(self): - self.start() - return self - - def __exit__(self, exc_type, exc_val, exc_tb): - self.terminate() - - def __del__(self): - self.terminate() - - def execute(self, *params): - """Execute the given batch of parameters with ``exiftool``. - - This method accepts any number of parameters and sends them to - the attached ``exiftool`` process. The process must be - running, otherwise ``ValueError`` is raised. The final - ``-execute`` necessary to actually run the batch is appended - automatically; see the documentation of :py:meth:`start()` for - the common options. The ``exiftool`` output is read up to the - end-of-output sentinel and returned as a raw ``bytes`` object, - excluding the sentinel. - - The parameters must also be raw ``bytes``, in whatever - encoding exiftool accepts. For filenames, this should be the - system's filesystem encoding. - - .. note:: This is considered a low-level method, and should - rarely be needed by application developers. - """ - if not self.running: - raise ValueError("ExifTool instance not running.") - self._process.stdin.write(b"\n".join(params + (b"-execute\n",))) - self._process.stdin.flush() - output = b"" - fd = self._process.stdout.fileno() - while not output[-32:].strip().endswith(sentinel): - output += os.read(fd, block_size) - return output.strip()[:-len(sentinel)] - - def execute_json(self, *params): - """Execute the given batch of parameters and parse the JSON output. - - This method is similar to :py:meth:`execute()`. It - automatically adds the parameter ``-j`` to request JSON output - from ``exiftool`` and parses the output. The return value is - a list of dictionaries, mapping tag names to the corresponding - values. All keys are Unicode strings with the tag names - including the ExifTool group name in the format <group>:<tag>. - The values can have multiple types. All strings occurring as - values will be Unicode strings. Each dictionary contains the - name of the file it corresponds to in the key ``"SourceFile"``. - - The parameters to this function must be either raw strings - (type ``str`` in Python 2.x, type ``bytes`` in Python 3.x) or - Unicode strings (type ``unicode`` in Python 2.x, type ``str`` - in Python 3.x). Unicode strings will be encoded using - system's filesystem encoding. This behaviour means you can - pass in filenames according to the convention of the - respective Python version – as raw strings in Python 2.x and - as Unicode strings in Python 3.x. - """ - params = map(fsencode, params) - return json.loads(self.execute(b"-j", *params).decode("utf-8")) - - def get_metadata_batch(self, filenames): - """Return all meta-data for the given files. - - The return value will have the format described in the - documentation of :py:meth:`execute_json()`. - """ - return self.execute_json(*filenames) - - def get_metadata(self, filename): - """Return meta-data for a single file. - - The returned dictionary has the format described in the - documentation of :py:meth:`execute_json()`. - """ - return self.execute_json(filename)[0] - - def get_tags_batch(self, tags, filenames): - """Return only specified tags for the given files. - - The first argument is an iterable of tags. The tag names may - include group names, as usual in the format <group>:<tag>. - - The second argument is an iterable of file names. - - The format of the return value is the same as for - :py:meth:`execute_json()`. - """ - # Explicitly ruling out strings here because passing in a - # string would lead to strange and hard-to-find errors - if isinstance(tags, basestring): - raise TypeError("The argument 'tags' must be " - "an iterable of strings") - if isinstance(filenames, basestring): - raise TypeError("The argument 'filenames' must be " - "an iterable of strings") - params = ["-" + t for t in tags] - params.extend(filenames) - return self.execute_json(*params) - - def get_tags(self, tags, filename): - """Return only specified tags for a single file. - - The returned dictionary has the format described in the - documentation of :py:meth:`execute_json()`. - """ - return self.get_tags_batch(tags, [filename])[0] - - def get_tag_batch(self, tag, filenames): - """Extract a single tag from the given files. - - The first argument is a single tag name, as usual in the - format <group>:<tag>. - - The second argument is an iterable of file names. - - The return value is a list of tag values or ``None`` for - non-existent tags, in the same order as ``filenames``. - """ - data = self.get_tags_batch([tag], filenames) - result = [] - for d in data: - d.pop("SourceFile") - result.append(next(iter(d.values()), None)) - return result - - def get_tag(self, tag, filename): - """Extract a single tag from a single file. - - The return value is the value of the specified tag, or - ``None`` if this tag was not found in the file. - """ - return self.get_tag_batch(tag, [filename])[0] diff --git a/sequencer_kinoraw_tools/functions.py b/sequencer_kinoraw_tools/functions.py deleted file mode 100644 index b51f495c..00000000 --- a/sequencer_kinoraw_tools/functions.py +++ /dev/null @@ -1,455 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -import bpy -import os.path -import operator -import subprocess -import random -from bpy.props import ( - IntProperty, - FloatProperty, - EnumProperty, - BoolProperty, - ) - -imb_ext_image = [ - # IMG - ".png", ".tga", ".bmp", ".jpg", ".jpeg", ".sgi", ".rgb", - ".rgba", ".tif", ".tiff", ".tx", ".jp2", ".hdr", ".dds", - ".dpx", ".cin", ".exr", ".rw2", - # IMG QT - ".gif", ".psd", ".pct", ".pict", ".pntg", ".qtif" - ] -imb_ext_audio = [ - ".wav", ".ogg", ".oga", ".mp3", ".mp2", ".ac3", ".aac", - ".flac", ".wma", ".eac3", ".aif", ".aiff", ".m4a" - ] -imb_ext_movie = [ - ".avi", ".flc", ".mov", ".movie", ".mp4", ".m4v", ".m2v", - ".m2t", ".m2ts", ".mts", ".mv", ".avs", ".wmv", ".ogv", ".ogg", - ".dv", ".mpeg", ".mpg", ".mpg2", ".vob", ".mkv", ".flv", - ".divx", ".xvid", ".mxf" - ] -movieextdict = [ - ("1", ".avi", ""), - ("2", ".flc", ""), ("3", ".mov", ""), - ("4", ".movie", ""), ("5", ".mp4", ""), - ("6", ".m4v", ""), ("7", ".m2v", ""), - ("8", ".m2t", ""), ("9", ".m2ts", ""), - ("10", ".mts", ""), ("11", ".mv", ""), - ("12", ".avs", ""), ("13", ".wmv", ""), - ("14", ".ogv", ""), ("15", ".dv", ""), - ("16", ".mpeg", ""), ("17", ".mpg", ""), - ("18", ".mpg2", ""), ("19", ".vob", ""), - ("20", ".mkv", ""), ("21", ".flv", ""), - ("22", ".divx", ""), ("23", ".xvid", ""), - ("24", ".mxf", "") - ] - - -# Functions -def error_handlers(self, op_name, errors, reports="ERROR"): - if self and reports: - self.report({'INFO'}, - reports + ": some operations could not be performed " - "(See Console for more info)") - - print("\n[Kinoraw Tools]\nOperator: {}\nWarning: {}\n".format(op_name, errors)) - - -def initSceneProperties(context): - # initSceneProperties is ONLY for variables that should - # be keeped with the blend file. Any other addon preferences - # should go to the addon preferences operator in __init__ - try: - if context.scene.kr_scn_init is True: - return False - except AttributeError: - pass - - scn = context.scene - - # jump to cut - bpy.types.Scene.kr_auto_markers = BoolProperty( - name="kr_auto_markers", - description="Activate Auto markers", - default=False - ) - scn.kr_auto_markers = False - - bpy.types.Scene.kr_in_marker = IntProperty( - name="In", - description="In frame position", - min=-30000, max=30000, - default=1 - ) - scn.kr_in_marker = 1 - - bpy.types.Scene.kr_out_marker = IntProperty( - name="Out", - description="Out frame position", - min=scn.kr_in_marker, max=30000, - default=75 - ) - scn.kr_out_marker = 75 - - # sequencer extra actions - bpy.types.Scene.kr_default_fade_duration = IntProperty( - name="Duration", - description="Number of frames to fade", - min=1, max=250, - default=scn.render.fps - ) - scn.kr_default_fade_duration = scn.render.fps - - bpy.types.Scene.kr_default_fade_amount = FloatProperty( - name="Amount", - description="Maximum value of fade", - min=0.0, - max=100.0, - default=1.0 - ) - scn.kr_default_fade_amount = 1.0 - - # recursive loader - bpy.types.Scene.kr_recursive = BoolProperty( - name="Recursive", - description="Load in recursive folders", - default=False - ) - scn.kr_recursive = False - - bpy.types.Scene.kr_recursive_select_by_extension = BoolProperty( - name="Recursive ext", - description="Load only clips with selected extension", - default=False - ) - scn.kr_recursive_select_by_extension = False - - bpy.types.Scene.kr_default_ext = EnumProperty( - items=movieextdict, - name="ext enum", - default="3" - ) - scn.kr_default_ext = "3" - - bpy.types.Scene.kr_scn_init = BoolProperty( - name="Init", - default=False - ) - scn.kr_scn_init = True - - return True - - -def get_selected_strips(context): - "return a list of selected strips" - strips = [] - for i in context.scene.sequence_editor.sequences_all: - if i.select is True: - strips.append(i) - return strips - - -def create_folder(path): - if not os.path.isdir(bpy.path.abspath(path)): - folder = bpy.path.abspath(path) - command = "mkdir " + folder - subprocess.call(command, shell=True) - - -def add_marker(context, text, frame): - scn = context.scene - markers = scn.timeline_markers - mark = markers.new(name=text) - mark.frame = frame - - -def act_strip(context): - try: - return context.scene.sequence_editor.active_strip - except AttributeError: - return None - - -def detect_strip_type(filepath): - extension = os.path.splitext(filepath)[1] - extension = extension.lower() - if extension in imb_ext_image: - type = 'IMAGE' - elif extension in imb_ext_movie: - type = 'MOVIE' - elif extension in imb_ext_audio: - type = 'SOUND' - else: - type = None - - return type - - -# recursive load functions -def getpathfrombrowser(context): - ''' - returns path from filebrowser - ''' - for a in context.window.screen.areas: - if a.type == 'FILE_BROWSER': - params = a.spaces[0].params - break - try: - params - except UnboundLocalError: - return {'CANCELLED'} - - path = params.directory - return path - - -def getfilepathfrombrowser(context): - """ - returns path and file from filebrowser - """ - for a in context.window.screen.areas: - if a.type == 'FILE_BROWSER': - params = a.spaces[0].params - break - try: - params - except UnboundLocalError: - return {'CANCELLED'} - - if params.filename == '': - return {'CANCELLED'} - - path = params.directory - filename = params.filename - return path, filename - - -def setpathinbrowser(context, path, file): - ''' - set path and file in the filebrowser - ''' - for a in context.window.screen.areas: - if a.type == 'FILE_BROWSER': - params = a.spaces[0].params - break - try: - params - except UnboundLocalError: - - return {'CANCELLED'} - - params.directory = path - params.filename = file - return path, params - - -def sortlist(filelist): - ''' - given a list of tuplas (path, filename) returns a list sorted by filename - ''' - filelist_sorted = sorted(filelist, key=operator.itemgetter(1)) - return filelist_sorted - - -def onefolder(context, recursive_select_by_extension, ext): - ''' - returns a list of MOVIE type files from folder selected in file browser - ''' - filelist = [] - path, filename = getfilepathfrombrowser(context) - - for i in movieextdict: - if i[0] == ext: - extension = i[1].rpartition(".")[2] - break - - if detect_strip_type(path + filename) == 'MOVIE': - if recursive_select_by_extension is True: - # filtering by extension... - for file in os.listdir(path): - if file.rpartition(".")[2].lower() == extension: - filelist.append((path, file)) - else: - # looking for all known extensions - for file in os.listdir(path): - for i in movieextdict: - if file.rpartition(".")[2].lower() == i[1].rpartition(".")[2]: - filelist.append((path, file)) - return (filelist) - - -def recursive(context, recursive_select_by_extension, ext): - ''' - returns a list of MOVIE type files recursively from file browser - ''' - filelist = [] - path = getpathfrombrowser(context) - - for i in movieextdict: - if i[0] == ext: - extension = i[1].rpartition(".")[2] - break - - for root, dirs, files in os.walk(path): - for file in files: - if recursive_select_by_extension is True: - # filtering by extension... - if file.rpartition(".")[2].lower() == extension: - filelist.append((root, file)) - else: - # looking for all known extensions - for i in movieextdict: - if file.rpartition(".")[2].lower() == i[1].rpartition(".")[2]: - filelist.append((root, file)) - return filelist - - -# jump to cut functions -def triminout(strip, sin, sout): - - """trim the strip to in and out, and returns - true if the strip is outside given in and out""" - - start = strip.frame_start + strip.frame_offset_start - strip.frame_still_start - end = start + strip.frame_final_duration - - remove = False - if end < sin: - remove = True - if start > sout: - remove = True - - if end > sin: - if start < sin: - strip.select_right_handle = False - strip.select_left_handle = True - bpy.ops.sequencer.snap(frame=sin) - strip.select_left_handle = False - if start < sout: - if end > sout: - strip.select_left_handle = False - strip.select_right_handle = True - bpy.ops.sequencer.snap(frame=sout) - strip.select_right_handle = False - - return remove - - -# random editor functions - -def randompartition(lst, n, rand): - division = len(lst) / float(n) - lista = [] - for i in range(n): - lista.append(division) - - var = 0 - for i in range(n - 1): - lista[i] += random.randint(-int(rand * division), int(rand * division)) - var += lista[i] - - if lista[n - 1] != len(lst) - var: - lista[n - 1] = len(lst) - var - - random.shuffle(lista) - division = len(lst) / float(n) - count = 0 - newlist = [] - for i in range(n): - # print(lst[count : int(lista[i]-1)+count]) - newlist.append([lst[count: int(lista[i] - 1) + count]]) - count += int(lista[i]) - - return newlist - - -def randomframe(strip): - # random frame between a and b - a = strip.frame_start - b = strip.frame_final_duration - rand = a + int(random.random() * b) - - return rand - - -# ??? -def get_matching_markers(scene, name=None): - ''' - return a list of markers with same name - from the scene, or all markers if name is None - ''' - selected_markers = [] - markers = scene.timeline_markers - for mark in markers: - # print(mark.name, name) - if mark.name == name or name is None: - selected_markers.append(mark.frame) - - return selected_markers - - -def generate_subsets_list(number_of_subsets): - # generate marker subsets list - subset_list = [] - subset_names = ['A', 'B', 'C', 'D', 'E', 'F'] - - for subset in range(number_of_subsets): - subset_list.append(subset_names[subset]) - return subset_list - - -def get_marker_dict(scene, number_of_subsets): - """ - return a dict where: - keys = subset names - values = list of markers - """ - - subset_list = generate_subsets_list(number_of_subsets) - # generate dict with a list for each subset - marker_dict = {} - - for subset in subset_list: - lists = get_matching_markers(scene, subset) - marker_dict[subset] = lists - return marker_dict - - -def get_cut_dict(scene, number_of_subsets): - """ - return a dict where: - keys = markers in the scene + start and end - values = duration in frames from key marker to next marker - """ - # generate cut_list - - lists = get_matching_markers(scene) - lists.append(scene.frame_start) - lists.append(scene.frame_end) - lists.sort() - cut_dict = {} - - for i, j in enumerate(lists): - try: - cut_dict[j] = lists[i + 1] - j - except IndexError: - continue - return cut_dict diff --git a/sequencer_kinoraw_tools/jumptocut.py b/sequencer_kinoraw_tools/jumptocut.py deleted file mode 100644 index 45a02cf4..00000000 --- a/sequencer_kinoraw_tools/jumptocut.py +++ /dev/null @@ -1,656 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - - -import bpy -from . import functions -from bpy.types import ( - Operator, - ) -from bpy.props import ( - IntProperty, - ) -from bpy.app.handlers import persistent - - -class OBJECT_OT_Setinout(Operator): - bl_label = "Set IN and OUT to selected" - bl_idname = "sequencerextra.setinout" - bl_description = "Set IN and OUT markers to the selected strips limits" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor: - return scn.sequence_editor.active_strip - else: - return False - - def execute(self, context): - functions.initSceneProperties(context) - - scn = context.scene - markers = scn.timeline_markers - seq = scn.sequence_editor - - meta_level = len(seq.meta_stack) - if meta_level > 0: - seq = seq.meta_stack[meta_level - 1] - - # search for timeline limits - tl_start = 300000 - tl_end = -300000 - for i in context.selected_editable_sequences: - if i.select is True: - start = i.frame_start + i.frame_offset_start - i.frame_still_start - end = start + i.frame_final_duration - if start < tl_start: - tl_start = start - if end > tl_end: - tl_end = end - # print(tl_start,tl_end) - - if scn.kr_auto_markers: - scn.kr_in_marker = tl_start - scn.kr_out_marker = tl_end - else: - scn.kr_in_marker = tl_start - scn.kr_out_marker = tl_end - - if "IN" in markers: - mark = markers["IN"] - mark.frame = scn.kr_in_marker - else: - mark = markers.new(name="IN") - mark.frame = scn.kr_in_marker - - if "OUT" in markers: - mark = markers["OUT"] - mark.frame = scn.kr_out_marker - else: - mark = markers.new(name="OUT") - mark.frame = scn.kr_in_marker - - return {'FINISHED'} - - -class OBJECT_OT_Triminout(Operator): - bl_label = "Trim to in & out" - bl_idname = "sequencerextra.triminout" - bl_description = "Trim the selected strip to IN and OUT markers (if exists)" - - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor: - if scn.sequence_editor.active_strip: - markers = scn.timeline_markers - if "IN" and "OUT" in markers: - return True - else: - return False - - def execute(self, context): - - scene = context.scene - seq = scene.sequence_editor - - meta_level = len(seq.meta_stack) - if meta_level > 0: - seq = seq.meta_stack[meta_level - 1] - - markers = scene.timeline_markers - sin = markers["IN"].frame - sout = markers["OUT"].frame - strips = context.selected_editable_sequences - - # (triminout function only works fine - # with one strip selected at a time) - for strip in strips: - # deselect all other strips - for i in strips: - i.select = False - # select current strip - strip.select = True - remove = functions.triminout(strip, sin, sout) - if remove is True: - bpy.ops.sequencer.delete() - - # select all strips again - for strip in strips: - try: - strip.select = True - except ReferenceError: - pass - - bpy.ops.sequencer.reload() - - return {'FINISHED'} - - -# SOURCE IN OUT -class OBJECT_OT_Sourcein(Operator): # Operator source in - bl_label = "Source IN" - bl_idname = "sequencerextra.sourcein" - bl_description = "Add or move a marker named IN" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(self, context): - scn = context.scene - if scn: - return scn.sequence_editor - else: - return False - - def execute(self, context): - functions.initSceneProperties(context) - scn = context.scene - markers = scn.timeline_markers - - if scn.kr_auto_markers: - scn.kr_in_marker = scn.frame_current - - else: - scn.kr_in_marker = scn.frame_current - if "IN" in markers: - mark = markers["IN"] - mark.frame = scn.kr_in_marker - else: - mark = markers.new(name="IN") - mark.frame = scn.kr_in_marker - - # limit OUT marker position with IN marker - if scn.kr_in_marker > scn.kr_out_marker: - scn.kr_out_marker = scn.kr_in_marker - - if "OUT" in markers: - mark = markers["OUT"] - mark.frame = scn.kr_out_marker - - for m in markers: - m.select = False - if m.name in {"IN", "OUT"}: - m.select = True - bpy.ops.sequencer.reload() - - return {'FINISHED'} - - -class OBJECT_OT_Sourceout(Operator): # Operator source out - bl_label = "Source OUT" - bl_idname = "sequencerextra.sourceout" - bl_description = "Add or move a marker named OUT" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(self, context): - scn = context.scene - if scn: - return scn.sequence_editor - else: - return False - - def execute(self, context): - scn = context.scene - functions.initSceneProperties(context) - markers = scn.timeline_markers - - if scn.kr_auto_markers: - scn.kr_out_marker = scn.frame_current - - else: - scn.kr_out_marker = scn.frame_current - - # limit OUT marker position with IN marker - if scn.kr_out_marker < scn.kr_in_marker: - scn.kr_out_marker = scn.kr_in_marker - - if "OUT" in markers: - mark = markers["OUT"] - mark.frame = scn.kr_out_marker - else: - mark = markers.new(name="OUT") - mark.frame = scn.kr_out_marker - - for m in markers: - m.select = False - if m.name in {"IN", "OUT"}: - m.select = True - bpy.ops.sequencer.reload() - return {'FINISHED'} - - -class OBJECT_OT_Setstartend(Operator): # Operator set start & end - bl_label = "Set Start and End" - bl_idname = "sequencerextra.setstartend" - bl_description = "Set Start and End to IN and OUT marker values" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(self, context): - scn = context.scene - markers = scn.timeline_markers - if "IN" and "OUT" in markers: - return True - else: - return False - - def execute(self, context): - functions.initSceneProperties(context) - scn = context.scene - markers = scn.timeline_markers - sin = markers["IN"] - sout = markers["OUT"] - scn.frame_start = sin.frame - scn.frame_end = sout.frame - 1 - bpy.ops.sequencer.reload() - - return {'FINISHED'} - - -# Copy paste - -class OBJECT_OT_Metacopy(Operator): # Operator copy source in/out - bl_label = "Trim and Meta-Copy" - bl_idname = "sequencerextra.metacopy" - bl_description = ("Make meta from selected strips, trim it to in / out\n" - "(if available) and copy it to clipboard") - - bl_options = {'REGISTER', 'UNDO'} - - def execute(self, context): - try: - # redo - scene = bpy.context.scene - seq = scene.sequence_editor - markers = scene.timeline_markers - strip1 = seq.active_strip - - if strip1 is None: - self.report({'ERROR'}, "No strip selected") - return {"CANCELLED"} - - if "IN" and "OUT" in markers: - sin = markers["IN"].frame - sout = markers["OUT"].frame - bpy.ops.sequencer.meta_make() - strip2 = seq.active_strip - functions.triminout(strip2, sin, sout) - bpy.ops.sequencer.copy() - bpy.ops.sequencer.meta_separate() - self.report({'INFO'}, "META2 has been trimmed and copied") - else: - bpy.ops.sequencer.meta_make() - bpy.ops.sequencer.copy() - bpy.ops.sequencer.meta_separate() - self.report({'WARNING'}, "No In and Out!! META has been copied") - - except Exception as e: - functions.error_handlers(self, - "sequencerextra.metacopy", e, "Trim and Meta-Copy") - - return {"CANCELLED"} - - return {'FINISHED'} - - -class OBJECT_OT_Metapaste(Operator): # Operator paste source in/out - bl_label = "Paste in current Frame" - bl_idname = "sequencerextra.metapaste" - bl_description = "Paste source from clipboard to current frame" - bl_options = {'REGISTER', 'UNDO'} - - def execute(self, context): - # redo - scene = bpy.context.scene - bpy.ops.sequencer.paste() - bpy.ops.sequencer.snap(frame=scene.frame_current) - strips = context.selected_editable_sequences - context.scene.sequence_editor.active_strip = strips[0] - context.view_layer.update() - - return {'FINISHED'} - - -# Operator paste source in/out -class OBJECT_OT_Unmetatrim(Operator): - bl_label = "Paste in current Frame" - bl_idname = "sequencerextra.meta_separate_trim" - bl_description = "Unmeta and trim the content to meta duration" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor: - if scn.sequence_editor.active_strip: - return scn.sequence_editor.active_strip.type == "META" - else: - return False - - def execute(self, context): - scn = context.scene - seq = scn.sequence_editor - markers = scn.timeline_markers - - # setting in and out around meta - # while keeping data to restore in and out positions - strip = seq.active_strip - sin = strip.frame_start + strip.frame_offset_start - sout = sin + strip.frame_final_duration - - borrarin = False - borrarout = False - original_in = 0 - original_out = 0 - - if "IN" in markers: - original_in = markers["IN"].frame - markers["IN"].frame = sin - else: - mark = markers.new(name="IN") - mark.frame = sin - borrarin = True - - if "OUT" in markers: - original_out = markers["OUT"].frame - markers["OUT"].frame = sout - else: - mark = markers.new(name="OUT") - mark.frame = sout - borrarout = True - - # here starts the operator... - - # get all META from selected strips - metastrips = [] - for i in context.selected_editable_sequences: - if i.type == "META": - metastrips.append(i) - - for meta in metastrips: - bpy.ops.sequencer.reload() - - # deselect all strips - for i in context.selected_editable_sequences: - i.select = False - - # make active current meta - meta.select = True - seq.active_strip = meta - bpy.ops.sequencer.reload() - - # set in and out to meta - sin = meta.frame_start + meta.frame_offset_start - sout = sin + meta.frame_final_duration - # print("meta: ", sin, sout) - - # grab meta content - newstrips = [] - for i in meta.sequences: - newstrips.append(i) - - # store meta channel - basechan = meta.channel - # look for upper and lower channels used by strips inside the meta - lowerchan = 32 - upperchan = 0 - for i in newstrips: - if i.channel < lowerchan: - lowerchan = i.channel - if i.channel > upperchan: - upperchan = i.channel - - # calculate channel increment needed - deltachan = basechan - lowerchan - # reorder strips inside the meta - # before separate we need to store channel data - delta = upperchan - lowerchan + 1 - for i in newstrips: - i.channel = i.channel + delta - chandict = {} - for i in newstrips: - i.channel = i.channel + deltachan - delta - chandict[i.name] = i.channel - - """ - for i in chandict: - print(i, chandict[i]) - """ - # go inside meta to trim strips - bpy.ops.sequencer.meta_toggle() - - # update seq definition according to meta - meta_level = len(seq.meta_stack) - if meta_level > 0: - seq = seq.meta_stack[meta_level - 1] - - # create a list to store clips outside selection - # that will be removed - rmlist = [] - - # deselect all separated strips - for j in newstrips: - j.select = False - # print("newstrips: ",j.name, j.type) - - # trim each strip separately - # first check special strips: - # (those who can move when any other does) - for i in newstrips: - if i.type in {"CROSS", "SPEED", "WIPE"}: - i.select = True - remove = functions.triminout(i, sin, sout) - if remove is True: - # print("checked: ",i.name, i.type) - rmlist.append(i) - i.select = False - - # now for the rest of strips - for i in newstrips: - i.select = True - remove = functions.triminout(i, sin, sout) - if remove is True: - # print("checked: ",i.name, i.type) - rmlist.append(i) - i.select = False - - # back outside the meta and separate it - bpy.ops.sequencer.meta_toggle() - bpy.ops.sequencer.meta_separate() - - # reset seq definition - seq = scn.sequence_editor - - # remove strips from outside the meta duration - for i in rmlist: - # print("removing: ",i.name, i.type) - for j in scn.sequence_editor.sequences_all: - j.select = False - - i.select = True - scn.sequence_editor.active_strip = i - bpy.ops.sequencer.delete() - - # select all strips and set one of the strips as active - for i in newstrips: - if i not in rmlist: - i.select = True - scn.sequence_editor.active_strip = i - - bpy.ops.sequencer.reload() - - # restore original IN and OUT values - if borrarin: - markers.remove(markers['IN']) - else: - markers["IN"].frame = original_in - if borrarout: - markers.remove(markers['OUT']) - else: - markers["OUT"].frame = original_out - scn.update() - - return {'FINISHED'} - - -class OBJECT_OT_Extrasnap(Operator): # Operator paste source in/out - bl_label = "Extra Snap" - bl_idname = "sequencerextra.extrasnap" - bl_description = "Snap the right, center or left of the strip to current frame" - bl_options = {'REGISTER', 'UNDO'} - - # align: 0 = left snap, 1 = center snap, 2= right snap - align: IntProperty( - name="Align", - min=0, max=2, - default=1 - ) - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor: - return scn.sequence_editor.active_strip - else: - return False - - def execute(self, context): - scene = bpy.context.scene - bpy.ops.sequencer.snap(frame=scene.frame_current) - - if self.align != 0: - strips = context.selected_editable_sequences - for strip in strips: - if self.align == 1: # center snap - strip.frame_start -= strip.frame_final_duration / 2 - else: # right snap - strip.frame_start -= strip.frame_final_duration - - return {'FINISHED'} - - -class OBJECT_OT_Extrahandles(Operator): # Operator paste source in/out - bl_label = "Extra Handles" - bl_idname = "sequencerextra.extrahandles" - bl_description = "Snap the right, center or left of the strip to current frame" - bl_options = {'REGISTER', 'UNDO'} - - # side: 0 = left , 1 = both, 2= right - side: IntProperty( - name="Side", - min=0, max=2, - default=1 - ) - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor: - return scn.sequence_editor.active_strip - else: - return False - - def execute(self, context): - strips = context.selected_editable_sequences - - resetLeft = False - resetRight = False - changelistLeft = [] - changelistRight = [] - - for strip in strips: - if self.side == 0 or self.side == 1: - if strip.select_left_handle: - resetLeft = True - changelistLeft.append(strip) - if self.side == 1 or self.side == 2: - if strip.select_right_handle: - resetRight = True - changelistRight.append(strip) - - if len(changelistLeft) == len(strips): - resetLeft = False - - if len(changelistRight) == len(strips): - resetRight = False - - if ((len(changelistRight) != len(strips)) or - (len(changelistRight) != len(strips))) and \ - self.side == 1: - resetLeft = True - resetRight = True - - for strip in strips: - if resetLeft: - strip.select_left_handle = False - - if self.side == 0 or self.side == 1: - if strip.select_left_handle: - strip.select_left_handle = False - else: - strip.select_left_handle = True - - if resetRight: - strip.select_right_handle = False - - if self.side == 1 or self.side == 2: - if strip.select_right_handle: - strip.select_right_handle = False - else: - strip.select_right_handle = True - - return {'FINISHED'} - - -@persistent -def marker_handler(scn): - context = bpy.context - functions.initSceneProperties(context) - - if scn.kr_auto_markers: - markers = scn.timeline_markers - - if "IN" in markers: - mark = markers["IN"] - mark.frame = scn.kr_in_marker - else: - mark = markers.new(name="IN") - mark.frame = scn.kr_in_marker - - if "OUT" in markers: - mark = markers["OUT"] - mark.frame = scn.kr_out_marker - else: - mark = markers.new(name="OUT") - mark.frame = scn.kr_out_marker - - # limit OUT marker position with IN marker - if scn.kr_in_marker > scn.kr_out_marker: - scn.kr_out_marker = scn.kr_in_marker - - return {'FINISHED'} - else: - return {'CANCELLED'} - - -bpy.app.handlers.scene_update_post.append(marker_handler) diff --git a/sequencer_kinoraw_tools/operators_extra_actions.py b/sequencer_kinoraw_tools/operators_extra_actions.py deleted file mode 100644 index 8a060acb..00000000 --- a/sequencer_kinoraw_tools/operators_extra_actions.py +++ /dev/null @@ -1,1302 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -import bpy -import os -from bpy.types import Operator -from bpy.props import ( - IntProperty, - FloatProperty, - EnumProperty, - BoolProperty, - ) -from . import functions - - -# Skip one second -class Sequencer_Extra_FrameSkip(Operator): - bl_label = "Skip One Second" - bl_idname = "screenextra.frame_skip" - bl_description = "Skip through the Timeline by one-second increments" - bl_options = {'REGISTER', 'UNDO'} - - back: BoolProperty( - name="Back", - default=False - ) - - def execute(self, context): - one_second = bpy.context.scene.render.fps - if self.back is True: - one_second *= -1 - bpy.ops.screen.frame_offset(delta=one_second) - - return {'FINISHED'} - - -# Trim timeline -class Sequencer_Extra_TrimTimeline(Operator): - bl_label = "Trim to Timeline Content" - bl_idname = "timeextra.trimtimeline" - bl_description = "Automatically set start and end frames" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor: - return scn.sequence_editor.sequences - else: - return False - - def execute(self, context): - scn = context.scene - seq = scn.sequence_editor - meta_level = len(seq.meta_stack) - if meta_level > 0: - seq = seq.meta_stack[meta_level - 1] - - frame_start = 300000 - frame_end = -300000 - for i in seq.sequences: - try: - if i.frame_final_start < frame_start: - frame_start = i.frame_final_start - if i.frame_final_end > frame_end: - frame_end = i.frame_final_end - 1 - except AttributeError: - pass - - if frame_start != 300000: - scn.frame_start = frame_start - if frame_end != -300000: - scn.frame_end = frame_end - - bpy.ops.sequencer.view_all() - - return {'FINISHED'} - - -# Trim timeline to selection -class Sequencer_Extra_TrimTimelineToSelection(Operator): - bl_label = "Trim to Selection" - bl_idname = "timeextra.trimtimelinetoselection" - bl_description = "Set start and end frames to selection" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor: - return scn.sequence_editor.sequences - else: - return False - - def execute(self, context): - scn = context.scene - seq = scn.sequence_editor - meta_level = len(seq.meta_stack) - if meta_level > 0: - seq = seq.meta_stack[meta_level - 1] - - frame_start = 300000 - frame_end = -300000 - for i in seq.sequences: - try: - if i.frame_final_start < frame_start and i.select is True: - frame_start = i.frame_final_start - if i.frame_final_end > frame_end and i.select is True: - frame_end = i.frame_final_end - 1 - except AttributeError: - pass - - if frame_start != 300000: - scn.frame_start = frame_start - if frame_end != -300000: - scn.frame_end = frame_end - - bpy.ops.sequencer.view_selected() - return {'FINISHED'} - - -# Open image with editor and create movie clip strip -""" - When a movie or image strip is selected, this operator creates a movieclip - or find the correspondent movieclip that already exists for this footage, - and add a VSE clip strip with same cuts the original strip has. - It can convert movie strips and image sequences, both with hard cuts or - soft cuts. -""" - - -class Sequencer_Extra_CreateMovieclip(Operator): - bl_label = "Create a Movieclip from selected strip" - bl_idname = "sequencerextra.createmovieclip" - bl_description = "Create a Movieclip strip from a MOVIE or IMAGE strip" - - @classmethod - def poll(self, context): - strip = functions.act_strip(context) - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return strip.type in ('MOVIE', 'IMAGE') - else: - return False - - def execute(self, context): - strip = functions.act_strip(context) - scn = context.scene - - if strip.type == 'MOVIE': - path = strip.filepath - data_exists = False - - for i in bpy.data.movieclips: - if i.filepath == path: - data_exists = True - data = i - newstrip = None - if data_exists is False: - try: - data = bpy.data.movieclips.load(filepath=path) - newstrip = bpy.ops.sequencer.movieclip_strip_add( - replace_sel=True, overlap=False, - clip=data.name - ) - newstrip = functions.act_strip(context) - newstrip.frame_start = strip.frame_start\ - - strip.animation_offset_start - tin = strip.frame_offset_start + strip.frame_start - tout = tin + strip.frame_final_duration - # print(newstrip.frame_start, strip.frame_start, tin, tout) - functions.triminout(newstrip, tin, tout) - except: - self.report({'ERROR_INVALID_INPUT'}, 'Error loading file') - return {'CANCELLED'} - - else: - try: - newstrip = bpy.ops.sequencer.movieclip_strip_add( - replace_sel=True, overlap=False, - clip=data.name - ) - newstrip = functions.act_strip(context) - newstrip.frame_start = strip.frame_start\ - - strip.animation_offset_start - # i need to declare the strip this way in order - # to get triminout() working - clip = bpy.context.scene.sequence_editor.sequences[ - newstrip.name - ] - # i cannot change these movie clip attributes via scripts - # but it works in the python console... - # clip.animation_offset_start = strip.animation.offset_start - # clip.animation_offset_end = strip.animation.offset_end - # clip.frame_final_duration = strip.frame_final_duration - tin = strip.frame_offset_start + strip.frame_start - tout = tin + strip.frame_final_duration - # print(newstrip.frame_start, strip.frame_start, tin, tout) - functions.triminout(clip, tin, tout) - except: - self.report({'ERROR_INVALID_INPUT'}, 'Error loading file') - return {'CANCELLED'} - - elif strip.type == 'IMAGE': - # print("image") - base_dir = bpy.path.abspath(strip.directory) - scn.frame_current = strip.frame_start - strip.animation_offset_start - - # searching for the first frame of the sequencer. This is mandatory - # for hard cutted sequence strips to be correctly converted, - # avoiding to create a new movie clip if not needed - filename = sorted(os.listdir(base_dir))[0] - path = os.path.join(base_dir, filename) - # print(path) - data_exists = False - for i in bpy.data.movieclips: - # print(i.filepath, path) - if i.filepath == path: - data_exists = True - data = i - # print(data_exists) - if data_exists is False: - try: - data = bpy.data.movieclips.load(filepath=path) - newstrip = bpy.ops.sequencer.movieclip_strip_add( - replace_sel=True, overlap=False, - clip=data.name - ) - newstrip = functions.act_strip(context) - newstrip.frame_start = strip.frame_start\ - - strip.animation_offset_start - clip = bpy.context.scene.sequence_editor.sequences[ - newstrip.name - ] - tin = strip.frame_offset_start + strip.frame_start - tout = tin + strip.frame_final_duration - # print(newstrip.frame_start, strip.frame_start, tin, tout) - functions.triminout(clip, tin, tout) - except: - self.report({'ERROR_INVALID_INPUT'}, 'Error loading file') - return {'CANCELLED'} - else: - try: - newstrip = bpy.ops.sequencer.movieclip_strip_add( - replace_sel=True, overlap=False, - clip=data.name - ) - newstrip = functions.act_strip(context) - newstrip.frame_start = strip.frame_start\ - - strip.animation_offset_start - # need to declare the strip this way in order - # to get triminout() working - clip = bpy.context.scene.sequence_editor.sequences[ - newstrip.name - ] - # cannot change this attributes via scripts... - # but it works in the python console... - # clip.animation_offset_start = strip.animation.offset_start - # clip.animation_offset_end = strip.animation.offset_end - # clip.frame_final_duration = strip.frame_final_duration - tin = strip.frame_offset_start + strip.frame_start - tout = tin + strip.frame_final_duration - # print(newstrip.frame_start, strip.frame_start, tin, tout) - functions.triminout(clip, tin, tout) - except: - self.report({'ERROR_INVALID_INPUT'}, 'Error loading file') - return {'CANCELLED'} - - # show the new clip in a movie clip editor, if available. - if strip.type == 'MOVIE' or 'IMAGE': - for a in context.window.screen.areas: - if a.type == 'CLIP_EDITOR': - a.spaces[0].clip = data - - return {'FINISHED'} - - -# Open image with editor -class Sequencer_Extra_Edit(Operator): - bl_label = "Open with Editor" - bl_idname = "sequencerextra.edit" - bl_description = "Open with Movie Clip or Image Editor" - - @classmethod - def poll(self, context): - strip = functions.act_strip(context) - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return strip.type in ('MOVIE', 'IMAGE') - else: - return False - - def execute(self, context): - strip = functions.act_strip(context) - scn = context.scene - data_exists = False - - if strip.type == 'MOVIE': - path = strip.filepath - - for i in bpy.data.movieclips: - if i.filepath == path: - data_exists = True - data = i - - if data_exists is False: - try: - data = bpy.data.movieclips.load(filepath=path) - except: - self.report({'ERROR_INVALID_INPUT'}, "Error loading file") - return {'CANCELLED'} - - elif strip.type == 'IMAGE': - base_dir = bpy.path.abspath(strip.directory) - strip_elem = strip.strip_elem_from_frame(scn.frame_current) - elem_name = strip_elem.filename - path = base_dir + elem_name - - for i in bpy.data.images: - if i.filepath == path: - data_exists = True - data = i - - if data_exists is False: - try: - data = bpy.data.images.load(filepath=path) - except: - self.report({'ERROR_INVALID_INPUT'}, 'Error loading file') - return {'CANCELLED'} - - if strip.type == 'MOVIE': - for a in context.window.screen.areas: - if a.type == 'CLIP_EDITOR': - a.spaces[0].clip = data - elif strip.type == 'IMAGE': - for a in context.window.screen.areas: - if a.type == 'IMAGE_EDITOR': - a.spaces[0].image = data - - return {'FINISHED'} - - -# Open image with external editor -class Sequencer_Extra_EditExternally(Operator): - bl_label = "Open with External Editor" - bl_idname = "sequencerextra.editexternally" - bl_description = "Open with the default external image editor" - - @classmethod - def poll(self, context): - strip = functions.act_strip(context) - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return strip.type == 'IMAGE' - else: - return False - - def execute(self, context): - strip = functions.act_strip(context) - scn = context.scene - base_dir = bpy.path.abspath(strip.directory) - strip_elem = strip.strip_elem_from_frame(scn.frame_current) - path = base_dir + strip_elem.filename - - try: - bpy.ops.image.external_edit(filepath=path) - except: - self.report({'ERROR_INVALID_INPUT'}, - "Please specify an Image Editor in Preferences > File") - return {'CANCELLED'} - - return {'FINISHED'} - - -# File name to strip name -class Sequencer_Extra_FileNameToStripName(Operator): - bl_label = "File Name to Selected Strips Name" - bl_idname = "sequencerextra.striprename" - bl_description = "Set strip name to input file name" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor: - return scn.sequence_editor.sequences - else: - return False - - def execute(self, context): - scn = context.scene - seq = scn.sequence_editor - meta_level = len(seq.meta_stack) - if meta_level > 0: - seq = seq.meta_stack[meta_level - 1] - selection = False - for i in seq.sequences: - if i.select is True: - if i.type == 'IMAGE' and not i.mute: - selection = True - i.name = i.elements[0].filename - if (i.type == 'SOUND' or i.type == 'MOVIE') and not i.mute: - selection = True - i.name = bpy.path.display_name_from_filepath(i.filepath) - if selection is False: - self.report({'ERROR_INVALID_INPUT'}, - "No image or movie strip selected") - return {'CANCELLED'} - return {'FINISHED'} - - -# Navigate up -class Sequencer_Extra_NavigateUp(Operator): - bl_label = "Navigate Up" - bl_idname = "sequencerextra.navigateup" - bl_description = "Move to Parent Timeline" - - @classmethod - def poll(self, context): - try: - if context.scene.sequence_editor.meta_stack: - return True - return False - except: - return False - - def execute(self, context): - if (functions.act_strip(context)): - strip = functions.act_strip(context) - seq_type = strip.type - if seq_type == 'META': - context.scene.sequence_editor.active_strip = None - - bpy.ops.sequencer.meta_toggle() - return {'FINISHED'} - - -# Ripple delete -class Sequencer_Extra_RippleDelete(Operator): - bl_label = "Ripple Delete" - bl_idname = "sequencerextra.rippledelete" - bl_description = "Delete a strip and shift back following ones" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return True - else: - return False - - def execute(self, context): - scn = context.scene - seq = scn.sequence_editor - meta_level = len(seq.meta_stack) - if meta_level > 0: - seq = seq.meta_stack[meta_level - 1] - # strip = functions.act_strip(context) - for strip in context.selected_editable_sequences: - cut_frame = strip.frame_final_start - next_edit = 300000 - bpy.ops.sequencer.select_all(action='DESELECT') - strip.select = True - bpy.ops.sequencer.delete() - striplist = [] - for i in seq.sequences: - try: - if (i.frame_final_start > cut_frame and - not i.mute): - if i.frame_final_start < next_edit: - next_edit = i.frame_final_start - if not i.mute: - striplist.append(i) - except AttributeError: - pass - - if next_edit == 300000: - return {'FINISHED'} - ripple_length = next_edit - cut_frame - for i in range(len(striplist)): - str = striplist[i] - try: - if str.frame_final_start > cut_frame: - str.frame_start = str.frame_start - ripple_length - except AttributeError: - pass - bpy.ops.sequencer.reload() - return {'FINISHED'} - - -# Ripple cut -class Sequencer_Extra_RippleCut(Operator): - bl_label = "Ripple Cut" - bl_idname = "sequencerextra.ripplecut" - bl_description = "Move a strip to buffer and shift back following ones" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return True - else: - return False - - def execute(self, context): - scn = context.scene - seq = scn.sequence_editor - meta_level = len(seq.meta_stack) - if meta_level > 0: - seq = seq.meta_stack[meta_level - 1] - strip = functions.act_strip(context) - bpy.ops.sequencer.select_all(action='DESELECT') - strip.select = True - temp_cf = scn.frame_current - scn.frame_current = strip.frame_final_start - bpy.ops.sequencer.copy() - scn.frame_current = temp_cf - - bpy.ops.sequencerextra.rippledelete() - return {'FINISHED'} - - -# Insert -class Sequencer_Extra_Insert(Operator): - bl_label = "Insert" - bl_idname = "sequencerextra.insert" - bl_description = ("Move active strip to current frame and shift " - "forward following ones") - bl_options = {'REGISTER', 'UNDO'} - - singlechannel: BoolProperty( - name="Single Channel", - default=False - ) - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return True - else: - return False - - def execute(self, context): - scn = context.scene - seq = scn.sequence_editor - meta_level = len(seq.meta_stack) - if meta_level > 0: - seq = seq.meta_stack[meta_level - 1] - strip = functions.act_strip(context) - gap = strip.frame_final_duration - bpy.ops.sequencer.select_all(action='DESELECT') - current_frame = scn.frame_current - - striplist = [] - for i in seq.sequences: - try: - if (i.frame_final_start >= current_frame and - not i.mute): - if self.singlechannel is True: - if i.channel == strip.channel: - striplist.append(i) - else: - striplist.append(i) - except AttributeError: - pass - try: - bpy.ops.sequencerextra.selectcurrentframe('EXEC_DEFAULT', - mode='AFTER') - except: - self.report({'ERROR_INVALID_INPUT'}, "Execution Error, " - "check your Blender version") - return {'CANCELLED'} - - for i in range(len(striplist)): - str = striplist[i] - try: - if str.select is True: - str.frame_start += gap - except AttributeError: - pass - try: - diff = current_frame - strip.frame_final_start - strip.frame_start += diff - except AttributeError: - pass - - strip = functions.act_strip(context) - scn.frame_current += strip.frame_final_duration - bpy.ops.sequencer.reload() - - return {'FINISHED'} - - -# Copy strip properties -class Sequencer_Extra_CopyProperties(Operator): - bl_label = "Copy Properties" - bl_idname = "sequencerextra.copyproperties" - bl_description = "Copy properties of active strip to selected strips" - bl_options = {'REGISTER', 'UNDO'} - - prop: EnumProperty( - name="Property", - items=[ - # common - ('name', 'Name', ''), - ('blend_alpha', 'Opacity', ''), - ('blend_type', 'Blend Mode', ''), - ('animation_offset', 'Input - Trim Duration', ''), - # non-sound - ('use_translation', 'Input - Image Offset', ''), - ('crop', 'Input - Image Crop', ''), - ('proxy', 'Proxy / Timecode', ''), - ('strobe', 'Filter - Strobe', ''), - ('color_multiply', 'Filter - Multiply', ''), - ('color_saturation', 'Filter - Saturation', ''), - ('deinterlace', 'Filter - De-Interlace', ''), - ('flip', 'Filter - Flip', ''), - ('float', 'Filter - Convert Float', ''), - ('alpha_mode', 'Filter - Alpha Mode', ''), - ('reverse', 'Filter - Backwards', ''), - # sound - ('pan', 'Sound - Pan', ''), - ('pitch', 'Sound - Pitch', ''), - ('volume', 'Sound - Volume', ''), - ('cache', 'Sound - Caching', ''), - # image - ('directory', 'Image - Directory', ''), - # movie - ('mpeg_preseek', 'Movie - MPEG Preseek', ''), - ('stream_index', 'Movie - Stream Index', ''), - # wipe - ('wipe', 'Effect - Wipe', ''), - # transform - ('transform', 'Effect - Transform', ''), - # color - ('color', 'Effect - Color', ''), - # speed - ('speed', 'Effect - Speed', ''), - # multicam - ('multicam_source', 'Effect - Multicam Source', ''), - # effect - ('effect_fader', 'Effect - Effect Fader', ''), - ], - default='blend_alpha' - ) - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return True - else: - return False - - def execute(self, context): - strip = functions.act_strip(context) - - scn = context.scene - seq = scn.sequence_editor - meta_level = len(seq.meta_stack) - if meta_level > 0: - seq = seq.meta_stack[meta_level - 1] - - for i in seq.sequences: - if (i.select is True and not i.mute): - try: - if self.prop == 'name': - i.name = strip.name - elif self.prop == 'blend_alpha': - i.blend_alpha = strip.blend_alpha - elif self.prop == 'blend_type': - i.blend_type = strip.blend_type - elif self.prop == 'animation_offset': - i.animation_offset_start = strip.animation_offset_start - i.animation_offset_end = strip.animation_offset_end - elif self.prop == 'use_translation': - i.use_translation = strip.use_translation - i.transform.offset_x = strip.transform.offset_x - i.transform.offset_y = strip.transform.offset_y - elif self.prop == 'crop': - i.use_crop = strip.use_crop - i.crop.min_x = strip.crop.min_x - i.crop.min_y = strip.crop.min_y - i.crop.max_x = strip.crop.max_x - i.crop.max_y = strip.crop.max_y - elif self.prop == 'proxy': - i.use_proxy = strip.use_proxy - p = strip.proxy.use_proxy_custom_directory # pep80 - i.proxy.use_proxy_custom_directory = p - i.proxy.use_proxy_custom_file = strip.proxy.use_proxy_custom_file - i.proxy.build_100 = strip.proxy.build_100 - i.proxy.build_25 = strip.proxy.build_25 - i.proxy.build_50 = strip.proxy.build_50 - i.proxy.build_75 = strip.proxy.build_75 - i.proxy.directory = strip.proxy.directory - i.proxy.filepath = strip.proxy.filepath - i.proxy.quality = strip.proxy.quality - i.proxy.timecode = strip.proxy.timecode - i.proxy.use_overwrite = strip.proxy.use_overwrite - elif self.prop == 'strobe': - i.strobe = strip.strobe - elif self.prop == 'color_multiply': - i.color_multiply = strip.color_multiply - elif self.prop == 'color_saturation': - i.color_saturation = strip.color_saturation - elif self.prop == 'deinterlace': - i.use_deinterlace = strip.use_deinterlace - elif self.prop == 'flip': - i.use_flip_x = strip.use_flip_x - i.use_flip_y = strip.use_flip_y - elif self.prop == 'float': - i.use_float = strip.use_float - elif self.prop == 'alpha_mode': - i.alpha_mode = strip.alpha_mode - elif self.prop == 'reverse': - i.use_reverse_frames = strip.use_reverse_frames - elif self.prop == 'pan': - i.pan = strip.pan - elif self.prop == 'pitch': - i.pitch = strip.pitch - elif self.prop == 'volume': - i.volume = strip.volume - elif self.prop == 'cache': - i.use_memory_cache = strip.use_memory_cache - elif self.prop == 'directory': - i.directory = strip.directory - elif self.prop == 'mpeg_preseek': - i.mpeg_preseek = strip.mpeg_preseek - elif self.prop == 'stream_index': - i.stream_index = strip.stream_index - elif self.prop == 'wipe': - i.angle = strip.angle - i.blur_width = strip.blur_width - i.direction = strip.direction - i.transition_type = strip.transition_type - elif self.prop == 'transform': - i.interpolation = strip.interpolation - i.rotation_start = strip.rotation_start - i.use_uniform_scale = strip.use_uniform_scale - i.scale_start_x = strip.scale_start_x - i.scale_start_y = strip.scale_start_y - i.translation_unit = strip.translation_unit - i.translate_start_x = strip.translate_start_x - i.translate_start_y = strip.translate_start_y - elif self.prop == 'color': - i.color = strip.color - elif self.prop == 'speed': - i.use_default_fade = strip.use_default_fade - i.speed_factor = strip.speed_factor - i.use_as_speed = strip.use_as_speed - i.scale_to_length = strip.scale_to_length - i.multiply_speed = strip.multiply_speed - i.use_frame_blend = strip.use_frame_blend - elif self.prop == 'multicam_source': - i.multicam_source = strip.multicam_source - elif self.prop == 'effect_fader': - i.use_default_fade = strip.use_default_fade - i.effect_fader = strip.effect_fader - except: - pass - - bpy.ops.sequencer.reload() - return {'FINISHED'} - - -# Fade in and out -class Sequencer_Extra_FadeInOut(Operator): - bl_idname = "sequencerextra.fadeinout" - bl_label = "Fade..." - bl_description = "Fade volume or opacity of active strip" - bl_options = {'REGISTER', 'UNDO'} - - mode: EnumProperty( - name='Direction', - items=( - ('IN', "Fade In...", ""), - ('OUT', "Fade Out...", ""), - ('INOUT', "Fade In and Out...", "")), - default='IN', - ) - - fade_duration: IntProperty( - name='Duration', - description='Number of frames to fade', - min=1, max=250, - default=25) - fade_amount: FloatProperty( - name='Amount', - description='Maximum value of fade', - min=0.0, - max=100.0, - default=1.0) - - @classmethod - def poll(cls, context): - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return True - else: - return False - - def execute(self, context): - seq = context.scene.sequence_editor - scn = context.scene - strip = seq.active_strip - tmp_current_frame = context.scene.frame_current - - if strip.type == 'SOUND': - if(self.mode) == 'OUT': - scn.frame_current = strip.frame_final_end - self.fade_duration - strip.volume = self.fade_amount - strip.keyframe_insert('volume') - scn.frame_current = strip.frame_final_end - strip.volume = 0 - strip.keyframe_insert('volume') - elif(self.mode) == 'INOUT': - scn.frame_current = strip.frame_final_start - strip.volume = 0 - strip.keyframe_insert('volume') - scn.frame_current += self.fade_duration - strip.volume = self.fade_amount - strip.keyframe_insert('volume') - scn.frame_current = strip.frame_final_end - self.fade_duration - strip.volume = self.fade_amount - strip.keyframe_insert('volume') - scn.frame_current = strip.frame_final_end - strip.volume = 0 - strip.keyframe_insert('volume') - else: - scn.frame_current = strip.frame_final_start - strip.volume = 0 - strip.keyframe_insert('volume') - scn.frame_current += self.fade_duration - strip.volume = self.fade_amount - strip.keyframe_insert('volume') - - else: - if(self.mode) == 'OUT': - scn.frame_current = strip.frame_final_end - self.fade_duration - strip.blend_alpha = self.fade_amount - strip.keyframe_insert('blend_alpha') - scn.frame_current = strip.frame_final_end - strip.blend_alpha = 0 - strip.keyframe_insert('blend_alpha') - elif(self.mode) == 'INOUT': - scn.frame_current = strip.frame_final_start - strip.blend_alpha = 0 - strip.keyframe_insert('blend_alpha') - scn.frame_current += self.fade_duration - strip.blend_alpha = self.fade_amount - strip.keyframe_insert('blend_alpha') - scn.frame_current = strip.frame_final_end - self.fade_duration - strip.blend_alpha = self.fade_amount - strip.keyframe_insert('blend_alpha') - scn.frame_current = strip.frame_final_end - strip.blend_alpha = 0 - strip.keyframe_insert('blend_alpha') - else: - scn.frame_current = strip.frame_final_start - strip.blend_alpha = 0 - strip.keyframe_insert('blend_alpha') - scn.frame_current += self.fade_duration - strip.blend_alpha = self.fade_amount - strip.keyframe_insert('blend_alpha') - - scn.frame_current = tmp_current_frame - - scn.kr_default_fade_duration = self.fade_duration - scn.kr_default_fade_amount = self.fade_amount - return{'FINISHED'} - - def invoke(self, context, event): - scn = context.scene - functions.initSceneProperties(context) - self.fade_duration = scn.kr_default_fade_duration - self.fade_amount = scn.kr_default_fade_amount - return context.window_manager.invoke_props_dialog(self) - - -# Extend to fill -class Sequencer_Extra_ExtendToFill(Operator): - bl_idname = "sequencerextra.extendtofill" - bl_label = "Extend to Fill" - bl_description = "Extend active strip forward to fill adjacent space" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(cls, context): - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return True - else: - return False - - def execute(self, context): - scn = context.scene - seq = scn.sequence_editor - meta_level = len(seq.meta_stack) - if meta_level > 0: - seq = seq.meta_stack[meta_level - 1] - strip = functions.act_strip(context) - chn = strip.channel - stf = strip.frame_final_end - enf = 300000 - - for i in seq.sequences: - ffs = i.frame_final_start - if (i.channel == chn and ffs > stf): - if ffs < enf: - enf = ffs - if enf == 300000 and stf < scn.frame_end: - enf = scn.frame_end - - if enf == 300000 or enf == stf: - self.report({'ERROR_INVALID_INPUT'}, 'Unable to extend') - return {'CANCELLED'} - else: - strip.frame_final_end = enf - - bpy.ops.sequencer.reload() - return {'FINISHED'} - - -# Place from file browser -class Sequencer_Extra_PlaceFromFileBrowser(Operator): - bl_label = "Place" - bl_idname = "sequencerextra.placefromfilebrowser" - bl_description = "Place or insert active file from File Browser" - bl_options = {'REGISTER', 'UNDO'} - - insert: BoolProperty( - name="Insert", - default=False - ) - - def execute(self, context): - scn = context.scene - for a in context.window.screen.areas: - if a.type == 'FILE_BROWSER': - params = a.spaces[0].params - break - try: - params - except UnboundLocalError: - self.report({'ERROR_INVALID_INPUT'}, 'No visible File Browser') - return {'CANCELLED'} - - if params.filename == '': - self.report({'ERROR_INVALID_INPUT'}, 'No file selected') - return {'CANCELLED'} - - path = os.path.join(params.directory, params.filename) - frame = context.scene.frame_current - strip_type = functions.detect_strip_type(params.filename) - - try: - if strip_type == 'IMAGE': - image_file = [] - filename = {"name": params.filename} - image_file.append(filename) - f_in = scn.frame_current - f_out = f_in + scn.render.fps - 1 - bpy.ops.sequencer.image_strip_add(files=image_file, - directory=params.directory, frame_start=f_in, - frame_end=f_out, relative_path=False) - elif strip_type == 'MOVIE': - bpy.ops.sequencer.movie_strip_add(filepath=path, - frame_start=frame, relative_path=False) - elif strip_type == 'SOUND': - bpy.ops.sequencer.sound_strip_add(filepath=path, - frame_start=frame, relative_path=False) - else: - self.report({'ERROR_INVALID_INPUT'}, 'Invalid file format') - return {'CANCELLED'} - except: - self.report({'ERROR_INVALID_INPUT'}, 'Error loading file') - return {'CANCELLED'} - - if self.insert is True: - try: - striplist = [] - for i in bpy.context.selected_editable_sequences: - if (i.select is True and i.type == "SOUND"): - striplist.append(i) - bpy.ops.sequencerextra.insert() - if striplist[0]: - striplist[0].frame_start = frame - except: - self.report({'ERROR_INVALID_INPUT'}, "Execution Error, " - "check your Blender version") - return {'CANCELLED'} - else: - strip = functions.act_strip(context) - scn.frame_current += strip.frame_final_duration - bpy.ops.sequencer.reload() - - return {'FINISHED'} - - -# Select strips on same channel -class Sequencer_Extra_SelectSameChannel(Operator): - bl_label = "Select Strips on the Same Channel" - bl_idname = "sequencerextra.selectsamechannel" - bl_description = "Select strips on the same channel as active one" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return True - else: - return False - - def execute(self, context): - scn = context.scene - seq = scn.sequence_editor - meta_level = len(seq.meta_stack) - if meta_level > 0: - seq = seq.meta_stack[meta_level - 1] - bpy.ops.sequencer.select_active_side(side="LEFT") - bpy.ops.sequencer.select_active_side(side="RIGHT") - - return {'FINISHED'} - - -# Current-frame-aware select -class Sequencer_Extra_SelectCurrentFrame(Operator): - bl_label = "Current-Frame-Aware Select" - bl_idname = "sequencerextra.selectcurrentframe" - bl_description = "Select strips according to current frame" - bl_options = {'REGISTER', 'UNDO'} - - mode: EnumProperty( - name='Mode', - items=( - ('BEFORE', 'Before Current Frame', ''), - ('AFTER', 'After Current Frame', ''), - ('ON', 'On Current Frame', '')), - default='BEFORE', - ) - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor: - return scn.sequence_editor.sequences - else: - return False - - def execute(self, context): - mode = self.mode - scn = context.scene - seq = scn.sequence_editor - cf = scn.frame_current - meta_level = len(seq.meta_stack) - if meta_level > 0: - seq = seq.meta_stack[meta_level - 1] - - if mode == 'AFTER': - for i in seq.sequences: - try: - if (i.frame_final_start >= cf and not i.mute): - i.select = True - except AttributeError: - pass - elif mode == 'ON': - for i in seq.sequences: - try: - if (i.frame_final_start <= cf and - i.frame_final_end > cf and - not i.mute): - i.select = True - except AttributeError: - pass - else: - for i in seq.sequences: - try: - if (i.frame_final_end < cf and not i.mute): - i.select = True - except AttributeError: - pass - - return {'FINISHED'} - - -# Select by type -class Sequencer_Extra_SelectAllByType(Operator): - bl_label = "All by Type" - bl_idname = "sequencerextra.select_all_by_type" - bl_description = "Select all the strips of the same type" - bl_options = {'REGISTER', 'UNDO'} - - type: EnumProperty( - name="Strip Type", - items=( - ('ACTIVE', 'Same as Active Strip', ''), - ('IMAGE', 'Image', ''), - ('META', 'Meta', ''), - ('SCENE', 'Scene', ''), - ('MOVIE', 'Movie', ''), - ('SOUND', 'Sound', ''), - ('TRANSFORM', 'Transform', ''), - ('COLOR', 'Color', '')), - default='ACTIVE', - ) - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor: - return scn.sequence_editor.sequences - else: - return False - - def execute(self, context): - strip_type = self.type - scn = context.scene - seq = scn.sequence_editor - meta_level = len(seq.meta_stack) - if meta_level > 0: - seq = seq.meta_stack[meta_level - 1] - active_strip = functions.act_strip(context) - if strip_type == 'ACTIVE': - if active_strip is None: - self.report({'ERROR_INVALID_INPUT'}, - 'No active strip') - return {'CANCELLED'} - strip_type = active_strip.type - - striplist = [] - for i in seq.sequences: - try: - if (i.type == strip_type and not i.mute): - striplist.append(i) - except AttributeError: - pass - for i in range(len(striplist)): - str = striplist[i] - try: - str.select = True - except AttributeError: - pass - - return {'FINISHED'} - - -# Open in movie clip editor from file browser -class Clip_Extra_OpenFromFileBrowser(Operator): - bl_label = "Open from File Browser" - bl_idname = "clipextra.openfromfilebrowser" - bl_description = "Load a Movie or Image Sequence from File Browser" - bl_options = {'REGISTER', 'UNDO'} - - def execute(self, context): - for a in context.window.screen.areas: - if a.type == 'FILE_BROWSER': - params = a.spaces[0].params - break - try: - params - except: - self.report({'ERROR_INVALID_INPUT'}, 'No visible File Browser') - return {'CANCELLED'} - - if params.filename == '': - self.report({'ERROR_INVALID_INPUT'}, 'No file selected') - return {'CANCELLED'} - - path = params.directory + params.filename - strip_type = functions.detect_strip_type(params.filename) - data_exists = False - - if strip_type in ('MOVIE', 'IMAGE'): - for i in bpy.data.movieclips: - if i.filepath == path: - data_exists = True - data = i - - if data_exists is False: - try: - data = bpy.data.movieclips.load(filepath=path) - except: - self.report({'ERROR_INVALID_INPUT'}, 'Error loading file') - return {'CANCELLED'} - else: - self.report({'ERROR_INVALID_INPUT'}, 'Invalid file format') - return {'CANCELLED'} - - for a in context.window.screen.areas: - if a.type == 'CLIP_EDITOR': - a.spaces[0].clip = data - - return {'FINISHED'} - - -# Open in movie clip editor from sequencer -class Clip_Extra_OpenActiveStrip(Operator): - bl_label = "Open Active Strip" - bl_idname = "clipextra.openactivestrip" - bl_description = "Load a Movie or Image Sequence from Sequence Editor" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(cls, context): - scn = context.scene - strip = functions.act_strip(context) - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return strip.type in ('MOVIE', 'IMAGE') - else: - return False - - def execute(self, context): - strip = functions.act_strip(context) - data_exists = False - - if strip.type == 'MOVIE': - path = strip.filepath - elif strip.type == 'IMAGE': - base_dir = bpy.path.relpath(strip.directory) - filename = strip.elements[0].filename - path = base_dir + '/' + filename - else: - self.report({'ERROR_INVALID_INPUT'}, 'Invalid file format') - return {'CANCELLED'} - - for i in bpy.data.movieclips: - if i.filepath == path: - data_exists = True - data = i - if data_exists is False: - try: - data = bpy.data.movieclips.load(filepath=path) - except: - self.report({'ERROR_INVALID_INPUT'}, 'Error loading file') - return {'CANCELLED'} - - for a in context.window.screen.areas: - if a.type == 'CLIP_EDITOR': - a.spaces[0].clip = data - - return {'FINISHED'} - - -# Jog / Shuttle -class Sequencer_Extra_JogShuttle(Operator): - bl_label = "Jog/Shuttle" - bl_idname = "sequencerextra.jogshuttle" - bl_description = ("Jog through the current sequence\n" - "Left Mouse button to confirm, Right mouse\Esc to cancel") - - def execute(self, context): - scn = context.scene - start_frame = scn.frame_start - end_frame = scn.frame_end - duration = end_frame - start_frame - diff = self.x - self.init_x - diff /= 5 - diff = int(diff) - extended_frame = diff + (self.init_current_frame - start_frame) - looped_frame = extended_frame % (duration + 1) - target_frame = start_frame + looped_frame - context.scene.frame_current = target_frame - - def modal(self, context, event): - if event.type == 'MOUSEMOVE': - self.x = event.mouse_x - self.execute(context) - elif event.type == 'LEFTMOUSE': - return {'FINISHED'} - elif event.type in ('RIGHTMOUSE', 'ESC'): - return {'CANCELLED'} - - return {'RUNNING_MODAL'} - - def invoke(self, context, event): - scn = context.scene - self.x = event.mouse_x - self.init_x = self.x - self.init_current_frame = scn.frame_current - self.execute(context) - context.window_manager.modal_handler_add(self) - - return {'RUNNING_MODAL'} diff --git a/sequencer_kinoraw_tools/proxy_tools.py b/sequencer_kinoraw_tools/proxy_tools.py deleted file mode 100644 index ba8c1454..00000000 --- a/sequencer_kinoraw_tools/proxy_tools.py +++ /dev/null @@ -1,344 +0,0 @@ -# gpl: authors Carlos Padial, Turi Scandurra - -import bpy -import os -from bpy.types import ( - Operator, - Panel, - ) -from bpy.props import IntProperty -import subprocess -from . import functions - - -proxy_qualities = [ - ("1", "25%", ""), ("2", "50%", ""), - ("3", "75%", ""), ("4", "100%", ""), - ("5", "none", "") - ] - - -# Functions -def setup_proxy(context, strip, size): - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - - # set up proxy settings - strip.use_proxy = True - - if prefs.use_bi_custom_directory: - strip.use_proxy_custom_directory = True - filename = strip.filepath.rpartition("/")[2].rpartition(".")[0] - strip.proxy.directory = bpy.path.relpath(prefs.proxy_dir + filename) - else: - strip.use_proxy_custom_directory = False - - if strip.use_proxy_custom_file is True: - strip.use_proxy_custom_file = False - - strip.proxy.quality = prefs.quality - strip.proxy.timecode = prefs.timecode - - if size == 5: - strip.use_proxy = False - strip.proxy.build_25 = False - strip.proxy.build_50 = False - strip.proxy.build_75 = False - strip.proxy.build_100 = False - - else: - proxysuffix = proxy_qualities[size - 1][1].split("%")[0] - - if (proxysuffix == "25"): - strip.proxy.build_25 = True - if (proxysuffix == "50"): - strip.proxy.build_50 = True - if (proxysuffix == "75"): - strip.proxy.build_75 = True - if (proxysuffix == "100"): - strip.proxy.build_100 = True - - return {"FINISHED"} - - -def create_proxy(context, strip, size, res): - # calculate proxy resolution - div = 4 / size - newres = (int(int(res[0]) / div), int(int(res[1]) / div)) - - preferences = context.preferences - proxy_dir = preferences.addons[__package__].preferences.proxy_dir - scripts = preferences.addons[__package__].preferences.proxy_scripts - ffmpeg_command = preferences.addons[__package__].preferences.ffmpeg_command - - functions.create_folder(proxy_dir) - - if scripts: - commands = [] - - # get filename - if strip.type == "MOVIE": - filename = bpy.path.abspath(strip.filepath) - proxysuffix = proxy_qualities[size - 1][1].split("%")[0] - proxy_dir = bpy.path.abspath(proxy_dir) - newfilename = os.path.join(proxy_dir, filename.rpartition("/")[2]) - fileoutput = newfilename.rpartition(".")[0] + "-" + proxysuffix + ".avi" - - # default value for ffmpeg_command = "fmpeg -i {} -vcodec mjpeg -qv 1 -s {}x{} -y {}" - - command = ffmpeg_command.format(filename, newres[0], newres[1], fileoutput) - print(command) - - if scripts: - commands.append(command) - else: - # check for existing file - if not os.path.isfile(fileoutput): - subprocess.call(command, shell=True) - else: - print("File already exists") - - # set up proxy settings - strip.use_proxy = True - try: - strip.use_proxy_custom_file = True - strip.proxy.filepath = bpy.path.relpath(fileoutput) - except: - pass - - if (proxysuffix == "25"): - strip.proxy.build_25 = True - if (proxysuffix == "50"): - strip.proxy.build_50 = True - if (proxysuffix == "75"): - strip.proxy.build_75 = True - if (proxysuffix == "100"): - strip.proxy.build_100 = True - - if scripts: - return commands - else: - return None - - -def create_proxy_scripts(scripts_dir, commands, strip_name=None): - - functions.create_folder(bpy.path.abspath(scripts_dir)) - for i in commands: - # print(i) - filename = "{}/proxy_script_{}.sh".format(scripts_dir, strip_name) - text_file = open(bpy.path.abspath(filename), "w") - # print(filename) - text_file.write(i) - text_file.close() - - -# classes -class CreateProxyOperator(Operator): - bl_idname = "sequencer.create_proxy_operator" - bl_label = "Create Proxy" - bl_description = ("Use ffmpeg to create a proxy from video\n" - "and setup proxies for selected strip") - bl_options = {'REGISTER', 'UNDO'} - - size: IntProperty( - name="Proxy Size", - default=1 - ) - - @classmethod - def poll(self, context): - strip = functions.act_strip(context) - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return strip.type in ('MOVIE') - else: - return False - - def execute(self, context): - preferences = context.preferences - proxy_scripts_path = preferences.addons[__package__].preferences.proxy_scripts_path - - for strip in context.selected_editable_sequences: - # get resolution from active strip - try: - bpy.ops.sequencerextra.read_exif() - except: - pass - - sce = context.scene - try: - res = sce['metadata'][0]['Composite:ImageSize'].split("x") - except: - res = (sce.render.resolution_x, sce.render.resolution_y) - - commands = create_proxy(context, strip, self.size, res) - - if commands is None: - # Update view_layer - context.view_layer.update() - newstrip = context.scene.sequence_editor.active_strip - - # deselect all other strips - for i in context.selected_editable_sequences: - if i.name != newstrip.name: - i.select = False - - # Update view_layer - context.view_layer.update() - else: - create_proxy_scripts(proxy_scripts_path, commands, strip.name) - - return {'FINISHED'} - - -class CreateBIProxyOperator(Operator): - bl_idname = "sequencer.create_bi_proxy_operator" - bl_label = "Create proxy with Blender Internal" - bl_description = "Use BI system to create a proxy" - bl_options = {'REGISTER', 'UNDO'} - - size: IntProperty( - name="Proxy Size", - default=1 - ) - - @classmethod - def poll(self, context): - strip = functions.act_strip(context) - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return strip.type in ('MOVIE') - else: - return False - - def execute(self, context): - try: - strips = functions.get_selected_strips(context) - - for strip in strips: - # deselect all other strips - for i in strips: - i.select = False - # select current strip - strip.select = True - if strip.type == "MOVIE": - setup_proxy(context, strip, self.size) - except Exception as e: - functions.error_handlers( - self, - "sequencer.create_bi_proxy_operator", e, - "Create proxy with blender internal" - ) - return {"CANCELLED"} - - # select all strips again - for strip in strips: - try: - strip.select = True - except ReferenceError: - pass - bpy.ops.sequencer.reload() - - return {'FINISHED'} - - -class CreateProxyToolPanel(Panel): - bl_label = "Proxy Tools" - bl_idname = "OBJECT_PT_ProxyTool" - bl_space_type = 'SEQUENCE_EDITOR' - bl_region_type = 'UI' - - @classmethod - def poll(self, context): - if context.space_data.view_type in {'SEQUENCER', - 'SEQUENCER_PREVIEW'}: - strip = functions.act_strip(context) - scn = context.scene - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - if prefs.use_proxy_tools: - return strip.type in ('MOVIE') - else: - return False - - def draw_header(self, context): - layout = self.layout - layout.label(text="", icon="AUTO") - - def draw(self, context): - - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - - layout = self.layout - layout.prop(prefs, "use_internal_proxy", text="Use BI proxy builder") - - strip = functions.act_strip(context) - - if prefs.use_internal_proxy: - layout = self.layout - row = layout.row(align=True) - row.prop(prefs, "use_bi_custom_directory") - - if prefs.use_bi_custom_directory: - row.prop(prefs, "proxy_dir", text="") - filename = strip.filepath.rpartition("/")[2].rpartition(".")[0] - layout.label(text="sample dir: //" + bpy.path.abspath(prefs.proxy_dir + filename)) - - layout = self.layout - col = layout.column() - col.label(text="Build JPEG quality") - col.prop(prefs, "quality") - - if strip.type == 'MOVIE': - col = layout.column() - col.label(text="Use timecode index:") - - col.prop(prefs, "timecode") - - layout = self.layout - layout.label(text="Setup and create BI proxy:") - row = layout.row(align=True) - - for i in range(4): - proxysuffix = proxy_qualities[i][1] - row.operator("sequencer.create_bi_proxy_operator", - text=proxysuffix).size = i + 1 - - layout = self.layout - layout.operator("sequencer.create_bi_proxy_operator", - text="Clear proxy sizes").size = 5 - - else: - layout = self.layout - layout.prop(prefs, "proxy_dir", text="Path for proxies") - - layout = self.layout - layout.label(text="Create and import proxy from clip:") - row = layout.row(align=True) - - layout = self.layout - layout.prop(prefs, "ffmpeg_command", text="command") - - layout.label(text="{} = filename, with, height, fileoutput") - label = prefs.ffmpeg_command.format("filename", "with", "height", "fileoutput") - layout.label(label) - - for i in range(4): - proxysuffix = proxy_qualities[i][1] - row.operator("sequencer.create_proxy_operator", - text=proxysuffix).size = i + 1 - - layout = self.layout - layout.prop(prefs, "proxy_scripts") - - if prefs.proxy_scripts: - layout = self.layout - layout.prop(prefs, "proxy_scripts_path", text="Path for scripts") - - layout = self.layout - box = layout.box() - box.prop(context.space_data, "proxy_render_size") - box.operator("sequencer.rebuild_proxy", text="Rebuild Proxies and TC") diff --git a/sequencer_kinoraw_tools/random_editor.py b/sequencer_kinoraw_tools/random_editor.py deleted file mode 100644 index 654136fd..00000000 --- a/sequencer_kinoraw_tools/random_editor.py +++ /dev/null @@ -1,138 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -# Note: the Operator LoadRandomEditOperator was removed since is not -# working. If it is fixed, reimplemented it can be reintroduced later - -import bpy -from bpy.types import ( - Operator, - Panel, - ) -from . import functions - - -# classes -class RandomScratchOperator(Operator): - bl_idname = "sequencer.randomscratchoperator" - bl_label = "Random Scratch Operator" - bl_description = "Random Scratch Operator" - - @classmethod - def poll(self, context): - strip = functions.act_strip(context) - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return strip.type in ('META') - else: - return False - - def invoke(self, context, event): - preferences = context.preferences - random_frames = preferences.addons[__package__].preferences.random_frames - - sce = context.scene - seq = sce.sequence_editor - markers = sce.timeline_markers - - if seq: - strip = seq.active_strip - if strip is not None: - if "IN" and "OUT" in markers: - sin = markers["IN"].frame - sout = markers["OUT"].frame - - # select active strip - strip = context.scene.sequence_editor.active_strip - stripname = strip.name - # collect strip names inside the meta - stripnames = [] - stripnames.append(strip.name) - for i in seq.active_strip.sequences: - stripnames.append(i.name) - # get strip channel - channel = strip.channel - repeat = range(int((sout - sin) / random_frames)) - print(sin, sout, sout - sin, (sout - sin) / random_frames, repeat) - - for i in repeat: - # select all related strips - for j in stripnames: - strip = seq.sequences_all[j] - strip.select = True - strip = seq.sequences_all[stripname] - seq.active_strip = strip - # deselect all other strips - for j in context.selected_editable_sequences: - if j.name not in stripnames: - j.select = False - a = bpy.ops.sequencer.duplicate_move() - # select new strip - newstrip = seq.active_strip - # deselect all other strips - - for j in context.selected_editable_sequences: - if j.name != newstrip.name: - j.select = False - # random cut - newstrip.frame_start = sin + i * random_frames - rand = functions.randomframe(newstrip) - functions.triminout(newstrip, rand, rand + random_frames) - newstrip.frame_start = i * random_frames + sin - newstrip.frame_offset_start - newstrip.channel = channel + 1 - else: - self.report({'WARNING'}, "There is no IN and OUT Markers") - bpy.ops.sequencer.reload() - - return {'FINISHED'} - - -class RandomEditorPanel(Panel): - bl_label = "Random Editor" - bl_idname = "OBJECT_PT_RandomEditor" - bl_space_type = 'SEQUENCE_EDITOR' - bl_region_type = 'UI' - - @classmethod - def poll(self, context): - if context.space_data.view_type in {'SEQUENCER', - 'SEQUENCER_PREVIEW'}: - strip = functions.act_strip(context) - scn = context.scene - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - if prefs.use_random_editor: - return strip.type in ('META') - else: - return False - - def draw_header(self, context): - layout = self.layout - layout.label(text="", icon="MOD_BUILD") - - def draw(self, context): - - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - - layout = self.layout - col = layout.column(align=True) - col.label(text="Cut duration:") - col.prop(prefs, "random_frames") - col.operator("sequencer.randomscratchoperator") diff --git a/sequencer_kinoraw_tools/recursive_loader.py b/sequencer_kinoraw_tools/recursive_loader.py deleted file mode 100644 index 07cc1e8e..00000000 --- a/sequencer_kinoraw_tools/recursive_loader.py +++ /dev/null @@ -1,266 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -import bpy -import os -from bpy.types import ( - Operator, - Panel, - ) -from bpy.props import ( - EnumProperty, - BoolProperty, - ) -from . import functions -from . import exiftool - - -class Sequencer_Extra_RecursiveLoader(Operator): - bl_idname = "sequencerextra.recursiveload" - bl_label = "Recursive Load" - bl_options = {'REGISTER', 'UNDO'} - - recursive: BoolProperty( - name="Recursive", - description="Load in recursive folders", - default=False - ) - recursive_select_by_extension: BoolProperty( - name="Select by extension", - description="Load only clips with selected extension", - default=False - ) - ext: EnumProperty( - items=functions.movieextdict, - name="Extension", - default='3' - ) - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor: - return (scn.sequence_editor) - else: - return False - - def invoke(self, context, event): - scn = context.scene - try: - self.recursive = scn.kr_recursive - self.recursive_select_by_extension = scn.kr_recursive_select_by_extension - self.ext = scn.kr_default_ext - except AttributeError: - functions.initSceneProperties(context) - self.recursive = scn.kr_recursive - self.recursive_select_by_extension = scn.kr_recursive_select_by_extension - self.ext = scn.kr_default_ext - - return context.window_manager.invoke_props_dialog(self) - - def loader(self, context, filelist): - scn = context.scene - if filelist: - for i in filelist: - functions.setpathinbrowser(context, i[0], i[1]) - try: - bpy.ops.sequencerextra.placefromfilebrowser() - except: - print("Error loading file (recursive loader error): ", i[1]) - functions.add_marker(context, i[1], scn.frame_current) - self.report({'ERROR_INVALID_INPUT'}, 'Error loading file ') - pass - - def execute(self, context): - scn = context.scene - if self.recursive is True: - # recursive - self.loader( - context, functions.sortlist( - functions.recursive(context, self.recursive_select_by_extension, - self.ext) - ) - ) - else: - # non recursive - self.loader( - context, functions.sortlist(functions.onefolder( - context, self.recursive_select_by_extension, - self.ext) - ) - ) - try: - scn.kr_recursive = self.recursive - scn.kr_recursive_select_by_extension = self.recursive_select_by_extension - scn.kr_default_ext = self.ext - except AttributeError: - functions.initSceneProperties(context) - self.recursive = scn.kr_recursive - self.recursive_select_by_extension = scn.kr_recursive_select_by_extension - self.ext = scn.kr_default_ext - - return {'FINISHED'} - - -# Read exif data -# load exifdata from strip to scene['metadata'] property - -class Sequencer_Extra_ReadExifData(Operator): - bl_label = "Read EXIF Data" - bl_idname = "sequencerextra.read_exif" - bl_description = "Load exifdata from strip to metadata property in scene" - bl_options = {'REGISTER', 'UNDO'} - - @classmethod - def poll(self, context): - scn = context.scene - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - return scn.sequence_editor.active_strip.type in ('IMAGE', 'MOVIE') - else: - return False - - def execute(self, context): - try: - exiftool.ExifTool().start() - except: - self.report({'ERROR_INVALID_INPUT'}, "exiftool not found in PATH") - - return {'CANCELLED'} - - def getexifdata(strip): - - def getexifvalues_image(lista): - metadata = [] - with exiftool.ExifTool() as et: - try: - metadata = et.get_metadata_batch(lista) - except UnicodeDecodeError as Err: - print(Err) - # print(metadata[0]) - print(len(metadata)) - return metadata - - def getexifvalues_movie(path): - metadata = [] - with exiftool.ExifTool() as et: - try: - metadata = et.get_metadata_batch([path]) - except UnicodeDecodeError as Err: - print(Err) - print(metadata[0]) - print(len(metadata)) - return metadata - - def getlist(lista): - for root, dirs, files in os.walk(path): - for f in files: - if "." + f.rpartition(".")[2].lower() in \ - functions.imb_ext_image: - lista.append(f) - """ - if "." + f.rpartition(".")[2] in imb_ext_movie: - lista.append(f) - """ - strip.elements - lista.sort() - return lista - - if strip.type == "IMAGE": - path = bpy.path.abspath(strip.directory) - os.chdir(path) - # get a list of files - lista = [] - for i in strip.elements: - lista.append(i.filename) - print(lista) - return getexifvalues_image(lista) - - if strip.type == "MOVIE": - path = bpy.path.abspath(strip.filepath) - print([path]) - return getexifvalues_movie(path) - - sce = bpy.context.scene - strip = context.scene.sequence_editor.active_strip - sce['metadata'] = getexifdata(strip) - - return {'FINISHED'} - - -# TODO: fix poll to hide when useless - -class ExifInfoPanel(Panel): - """Creates a Panel in the Object properties window""" - bl_label = "EXIF Info Panel" - bl_space_type = 'SEQUENCE_EDITOR' - bl_region_type = 'UI' - - @classmethod - def poll(self, context): - if context.space_data.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}: - strip = functions.act_strip(context) - scn = context.scene - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - - if scn and scn.sequence_editor and scn.sequence_editor.active_strip: - if prefs.use_exif_panel: - return strip.type in ('MOVIE', 'IMAGE') - else: - return False - - def draw_header(self, context): - layout = self.layout - layout.label(text="", icon="RADIO") - - def draw(self, context): - layout = self.layout - sce = context.scene - row = layout.row() - row.operator("sequencerextra.read_exif") - row = layout.row() - row.label(text="Exif Data", icon='RENDER_REGION') - row = layout.row() - - try: - strip = context.scene.sequence_editor.active_strip - - f = strip.frame_start - frame = sce.frame_current - try: - if len(sce['metadata']) == 1: - for d in sce['metadata'][0]: - split = layout.split(factor=0.5) - col = split.column() - row = col.row() - col.label(text=d) - col = split.column() - col.label(text=str(sce['metadata'][0][d])) - else: - for d in sce['metadata'][frame - f]: - split = layout.split(factor=0.5) - col = split.column() - row = col.row() - col.label(text=d) - col = split.column() - col.label(text=str(sce['metadata'][frame - f][d])) - - except (IndexError, KeyError): - pass - except AttributeError: - pass diff --git a/sequencer_kinoraw_tools/ui.py b/sequencer_kinoraw_tools/ui.py deleted file mode 100644 index a2721cac..00000000 --- a/sequencer_kinoraw_tools/ui.py +++ /dev/null @@ -1,765 +0,0 @@ -# ##### BEGIN GPL LICENSE BLOCK ##### -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# ##### END GPL LICENSE BLOCK ##### - -import bpy -from bpy.types import ( - Menu, - Panel, - ) -from . import functions - - -# UI -class SEQUENCER_EXTRA_MT_input(Menu): - bl_label = "Input" - - def draw(self, context): - self.layout.label(text="Kinoraw Input") - self.layout.separator() - - self.layout.operator_context = "INVOKE_REGION_WIN" - self.layout.operator("sequencerextra.striprename", - text="File Name to Strip Name") - self.layout.operator("sequencerextra.editexternally", - text="Open with External Editor") - self.layout.operator("sequencerextra.edit", - text="Open with Editor") - self.layout.operator("sequencerextra.createmovieclip", - text="Create Movieclip strip") - - -def sequencer_header_func(self, context): - self.layout.menu("SEQUENCER_EXTRA_MT_input") - - -def sequencer_add_menu_func(self, context): - self.layout.operator("sequencerextra.placefromfilebrowser", - text="Place from File Browser").insert = False - self.layout.operator("sequencerextra.placefromfilebrowser", - text="Insert from File Browser").insert = True - self.layout.operator("sequencerextra.recursiveload", - text="Recursive Load from Browser") - self.layout.separator() - - -def sequencer_select_menu_func(self, context): - self.layout.operator_menu_enum('sequencerextra.select_all_by_type', - 'type', text='All by Type') - self.layout.separator() - self.layout.operator('sequencerextra.selectcurrentframe', - text='Before Current Frame').mode = 'BEFORE' - self.layout.operator('sequencerextra.selectcurrentframe', - text='After Current Frame').mode = 'AFTER' - self.layout.operator('sequencerextra.selectcurrentframe', - text='On Current Frame').mode = 'ON' - self.layout.separator() - self.layout.operator('sequencerextra.selectsamechannel', - text='Same Channel') - - -def sequencer_strip_menu_func(self, context): - self.layout.operator('sequencerextra.extendtofill', - text='Extend to Fill') - self.layout.operator_menu_enum('sequencerextra.fadeinout', - 'mode', text='Fade') - self.layout.operator_menu_enum('sequencerextra.copyproperties', - 'prop') - - self.layout.operator("sequencerextra.insert", - text="Insert (Single Channel)").singlechannel = True - self.layout.operator("sequencerextra.insert", - text="Insert").singlechannel = False - self.layout.operator("sequencerextra.ripplecut", - text="Ripple Cut") - self.layout.operator("sequencerextra.rippledelete", - text="Ripple Delete") - self.layout.separator() - - -def time_frame_menu_func(self, context): - self.layout.operator('timeextra.trimtimelinetoselection', - text='Trim to Selection') - self.layout.operator('timeextra.trimtimeline', - text='Trim to Timeline Content') - self.layout.separator() - self.layout.operator('screenextra.frame_skip', - text='Skip Forward One Second').back = False - self.layout.operator('screenextra.frame_skip', - text='Skip Back One Second').back = True - self.layout.separator() - - -def time_header_func(self, context): - self.layout.operator('sequencerextra.jogshuttle', - text='Jog/Shuttle', icon='NDOF_TURN') - - -def clip_header_func(self, context): - self.layout.operator('sequencerextra.jogshuttle', - text='Jog/Shuttle', icon='NDOF_TURN') - - -def clip_clip_menu_func(self, context): - self.layout.operator('clipextra.openactivestrip', - text='Open Active Strip') - self.layout.operator('clipextra.openfromfilebrowser', - text='Open from File Browser') - self.layout.separator() - - -def draw_color_balance(layout, color_balance): - layout = layout.split(factor=0.33) - col = layout.column() - col.label(text="Lift:") - col.template_color_picker(color_balance, "lift", value_slider=True, cubic=True) - row = col.row() - row.prop(color_balance, "lift", text="") - row.prop(color_balance, "invert_lift", text="Invert") - - col = layout.column() - col.label(text="Gamma:") - col.template_color_picker(color_balance, "gamma", value_slider=True, - lock_luminosity=True, cubic=True) - row = col.row() - row.prop(color_balance, "gamma", text="") - row.prop(color_balance, "invert_gamma", text="Invert") - - col = layout.column() - col.label(text="Gain:") - col.template_color_picker(color_balance, "gain", value_slider=True, - lock_luminosity=True, cubic=True) - row = col.row() - row.prop(color_balance, "gain", text="") - row.prop(color_balance, "invert_gain", text="Invert") - - -class JumptoCut(Panel): - bl_space_type = "SEQUENCE_EDITOR" - bl_region_type = "UI" - bl_label = "Jump to Cut" - - COMPAT_ENGINES = {'BLENDER_RENDER'} - - _frame_rate_args_prev = None - _preset_class = None - - @staticmethod - def _draw_framerate_label(*args): - # avoids re-creating text string each draw - if JumptoCut._frame_rate_args_prev == args: - return JumptoCut._frame_rate_ret - - fps, fps_base, preset_label = args - - if fps_base == 1.0: - fps_rate = round(fps) - else: - fps_rate = round(fps / fps_base, 2) - - # TODO: Change the following to iterate over existing presets - custom_framerate = (fps_rate not in {23.98, 24, 25, 29.97, 30, 50, 59.94, 60}) - - if custom_framerate is True: - fps_label_text = "Custom (%r fps)" % fps_rate - show_framerate = True - else: - fps_label_text = "%r fps" % fps_rate - show_framerate = (preset_label == "Custom") - - JumptoCut._frame_rate_args_prev = args - JumptoCut._frame_rate_ret = args = (fps_label_text, show_framerate) - return args - - @staticmethod - def draw_framerate(sub, rd): - if JumptoCut._preset_class is None: - JumptoCut._preset_class = bpy.types.RENDER_MT_framerate_presets - - args = rd.fps, rd.fps_base, JumptoCut._preset_class.bl_label - fps_label_text, show_framerate = JumptoCut._draw_framerate_label(*args) - - sub.menu("RENDER_MT_framerate_presets", text=fps_label_text) - - if show_framerate: - sub.prop(rd, "fps") - sub.prop(rd, "fps_base", text="/") - - @classmethod - def poll(self, context): - if context.space_data.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}: - scn = context.scene - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - if scn and scn.sequence_editor: - if prefs.use_jumptocut: - return True - else: - return False - - def draw_header(self, context): - layout = self.layout - layout.label(text="", icon="RENDER_ANIMATION") - - def draw(self, context): - scn = context.scene - strip = functions.act_strip(context) - - preferences = context.preferences - prefs = preferences.addons[__package__].preferences - - layout = self.layout - layout = layout.box() - # jump to cut main controls - col = layout.column(align=True) - row = col.row(align=True) - split = row.split(factor=0.33, align=True) - box = split.box() - - row = box.row(align=True) - row.label(icon='TIME', text="Jump(sec)") - row.operator('screenextra.frame_skip', - text="", icon='TRIA_LEFT').back = True - row.operator('screenextra.frame_skip', - text="", icon='TRIA_RIGHT').back = False - - box = split.box() - row = box.row(align=True) - row.label(icon='IPO_BOUNCE', text="Cuts") - row.operator("sequencer.strip_jump", icon="PLAY_REVERSE", text="").next = False - row.operator("sequencer.strip_jump", icon='PLAY', text="").next = True - - box = split.box() - row = box.row(align=True) - row.label(icon='MARKER_HLT', text="Marker") - row.operator("screen.marker_jump", icon="TRIA_LEFT", text="").next = False - row.operator("screen.marker_jump", icon='TRIA_RIGHT', text="").next = True - - rd = scn.render - screen = context.screen - row = col.row(align=True) - split = row.split(factor=0.33, align=True) - sub_box = split.box() - sub_row = sub_box.row(align=True) - sub_row.alignment = "CENTER" - - sub_row.operator("screen.frame_jump", text="", icon='REW').end = False - sub_row.operator("screen.keyframe_jump", text="", icon='PREV_KEYFRAME').next = False - - if not screen.is_animation_playing: - # if using JACK and A/V sync: - # hide the play-reversed button - # since JACK transport doesn't support reversed playback - if scn.sync_mode == 'AUDIO_SYNC' and \ - context.preferences.system.audio_device == 'JACK': - sub = sub_row.row(align=True) - sub.scale_x = 2.0 - sub.operator("screen.animation_play", text="", icon='PLAY') - else: - sub_row.operator("screen.animation_play", text="", - icon='PLAY_REVERSE').reverse = True - sub_row.operator("screen.animation_play", text="", icon='PLAY') - else: - sub = sub_row.row(align=True) - sub.scale_x = 2.0 - sub.operator("screen.animation_play", text="", icon="PAUSE") - sub_row.operator("screen.keyframe_jump", text="", icon="NEXT_KEYFRAME").next = True - sub_row.operator("screen.frame_jump", text="", icon="FF").end = True - - sub_box = split.box() - sub_box.prop(scn, "sync_mode", text="") - sub_box = split.box() - self.draw_framerate(sub_box, rd) - - row = layout.row(align=True) - row.operator("sequencer.refresh_all") - row.operator("sequencer.rendersize", text="Set Render size") - - row = layout.row(align=True) - row.operator("sequencerextra.setstartend", icon="PREVIEW_RANGE", text="IN/OUT") - row.operator("timeextra.trimtimelinetoselection", - text="Selection", icon="PREVIEW_RANGE") - row.operator("timeextra.trimtimeline", text="All", icon="PREVIEW_RANGE") - - layout = self.layout - - # panel setup - row = layout.row(align=True) - split = row.split(factor=0.5) - sub_row = split.row(align=True) - sub_row.prop(prefs, "kr_show_tools", text="Tools", icon='SEQ_SEQUENCER') - if prefs.kr_show_tools: - sub_row.prop(prefs, "kr_mini_ui", text="Compact UI", toggle=True) - - row = split.row() - row = row.split(factor=0.33) - row.prop(prefs, "kr_show_info", text="", icon='VIEWZOOM') - row = row.split(factor=0.5) - row.prop(prefs, "kr_extra_info", text="", icon='BORDERMOVE') - row = row.split(factor=1) - row.prop(prefs, "kr_show_modifiers", text="", icon='RESTRICT_VIEW_OFF') - - if prefs.kr_show_tools: - layout = self.layout - layout = layout.box() - # snap, handler selector and meta tools - - if prefs.kr_mini_ui: - row = layout.row(align=True) - row.operator("sequencerextra.extrasnap", text="", icon="SNAP_ON").align = 0 - row.operator("sequencerextra.extrasnap", text="", icon="NONE").align = 1 - row.operator("sequencerextra.extrasnap", text="", icon="SNAP_ON").align = 2 - - row.separator() - row.operator("sequencerextra.extrahandles", text="", icon="TRIA_LEFT").side = 0 - row.operator("sequencerextra.extrahandles", text="", icon="PMARKER").side = 1 - row.operator("sequencerextra.extrahandles", text="", icon="TRIA_RIGHT").side = 2 - - row.separator() - row.operator("sequencerextra.metacopy", icon="COPYDOWN", text="") - row.operator("sequencerextra.metapaste", icon="PASTEDOWN", text="") - row.separator() - row.operator("sequencerextra.meta_separate_trim", text="", icon="ALIGN") - row.separator() - row.prop(prefs, "use_io_tools", text="I/O Tools") - - # In / Out tools - if prefs.use_io_tools: - row = layout.row(align=True) - if scn.kr_auto_markers is True: - row.prop(scn, "kr_auto_markers", text="", toggle=True, icon="SPACE2") - - row.separator() - row.operator("sequencerextra.sourcein", icon="MARKER_HLT", text="") - row.prop(scn, "kr_in_marker") - row.operator("sequencerextra.sourceout", icon='MARKER_HLT', text="") - row.prop(scn, "kr_out_marker") - else: - row.prop(scn, "kr_auto_markers", text="Auto I/O", toggle=True, icon="SPACE2") - row.operator("sequencerextra.sourcein", icon="MARKER_HLT", text="IN") - row.operator("sequencerextra.sourceout", icon='MARKER_HLT', text="OUT") - - row.separator() - row.operator("sequencerextra.setinout", icon='ARROW_LEFTRIGHT', text="") - row.operator("sequencerextra.triminout", icon="FULLSCREEN_EXIT", text="") - - # miniUI extra actions - row = layout.row(align=True) - row.operator("sequencerextra.jogshuttle", - text="", icon="NDOF_TURN") - row.operator("sequencerextra.navigateup", - text="", icon="FILE_PARENT") - row.operator("sequencerextra.extendtofill", - text="", icon="STYLUS_PRESSURE") - row.operator("sequencerextra.placefromfilebrowser", - text="", icon="TRIA_DOWN").insert = False - row.operator("sequencerextra.placefromfilebrowser", - text="", icon="TRIA_RIGHT").insert = True - row.operator("sequencer.slip", - text="", icon="MOD_SHRINKWRAP") - row.operator_menu_enum("sequencerextra.fadeinout", - "mode", text="Fade", icon="MOD_ARRAY") - row.operator_menu_enum("sequencerextra.copyproperties", - "prop", text="Copy", icon="SCRIPT") - - else: - row = layout.row(align=True) - row.label(text="Snap:") - - row.operator("sequencerextra.extrasnap", text="Left", icon="SNAP_ON").align = 0 - row.operator("sequencerextra.extrasnap", text="Center", icon="SNAP_SURFACE").align = 1 - row.operator("sequencerextra.extrasnap", text="Right", icon="SNAP_ON").align = 2 - - row = layout.row(align=True) - row.label(text="Handlers:") - row.operator("sequencerextra.extrahandles", - text="Left", icon="TRIA_LEFT").side = 0 - row.operator("sequencerextra.extrahandles", - text="Both", icon="PMARKER").side = 1 - row.operator("sequencerextra.extrahandles", - text="Right", icon="TRIA_RIGHT").side = 2 - - box = layout.box() - col = box.column_flow(columns=3, align=True) - row1 = col.row(align=True) - row1.operator("sequencerextra.metacopy", icon="COPYDOWN", text="Meta Copy") - row2 = col.row(align=True) - row2.operator("sequencerextra.metapaste", icon='PASTEDOWN', text="Paste Snap") - row3 = col.row() - row3.operator("sequencerextra.meta_separate_trim", - text="unMeta & Trim", icon="ALIGN") - - # in /out tools - box = layout.box() - col = box.column_flow(columns=3, align=True) - row1 = col.row(align=True) - row1.operator("sequencerextra.sourcein", icon="MARKER_HLT", text="Set IN") - row2 = col.row(align=True) - row2.operator("sequencerextra.sourceout", icon='MARKER_HLT', text="Set OUT") - row3 = col.row() - row3.operator("sequencerextra.setinout", icon='ARROW_LEFTRIGHT', text="Selected") - - sub_col = box.split(factor=0.67, align=True) - row4 = sub_col.row(align=True) - - if scn.kr_auto_markers is False: - row4.prop(scn, "kr_auto_markers", - text="Auto Markers", toggle=True, icon="SPACE2") - else: - row4.prop(scn, "kr_auto_markers", text="", icon="SPACE2") - row4.prop(scn, "kr_in_marker") - row4.prop(scn, "kr_out_marker") - box4 = row4.box() - box4.scale_x = 0.25 - box4.scale_y = 0.5 - box4.label(text="", icon="BLANK1") - - row5 = sub_col.row() - row5.operator("sequencerextra.triminout", icon="FULLSCREEN_EXIT", - text="Trim", emboss=True) - - # UI extra actions - box = layout.box() - row = box.row(align=True) - row.operator("sequencerextra.jogshuttle", - text="Jog/Shuttle", icon="NDOF_TURN") - row.operator("sequencerextra.navigateup", - text="Navigate Up", icon="FILE_PARENT") - row.operator("sequencerextra.extendtofill", - text="Extend to Fill", icon="STYLUS_PRESSURE") - - row = box.row(align=True) - row.operator("sequencerextra.placefromfilebrowser", - text="File Place", icon="TRIA_DOWN").insert = False - row.operator("sequencerextra.placefromfilebrowser", - text="File Insert", icon="TRIA_RIGHT").insert = True - row.operator("sequencer.slip", - text="Slip", icon="MOD_SHRINKWRAP") - row = layout.row(align=True) - row.operator_menu_enum("sequencerextra.fadeinout", - "mode", text="Fade", icon="MOD_ARRAY") - row.operator_menu_enum("sequencerextra.copyproperties", - "prop", icon="SCRIPT") - - # INFO boxes - if strip is not None: - if prefs.kr_show_info: - layout = layout.box() - row = layout.split(factor=0.075) - row.prop(prefs, "kr_show_info", text="", icon='VIEWZOOM', emboss=True) - row = row.split(factor=0.3) - row.prop(strip, "type", text="") - row = row.split(factor=1) - row.prop(strip, "name", text="") - - # mute information - layout.active = (not strip.mute) - - # basic info - row = layout.row() - row.prop(strip, "channel") - row.prop(strip, "frame_start") - row.prop(strip, "frame_final_duration") - - # source info - row = layout.split(factor=0.8) - - if strip.type == 'MOVIE': - row.prop(strip, "filepath", text="") - - if strip.type == 'SOUND': - # Note: sound strip has a different structure - sound = strip.sound - if sound is not None: - row.prop(sound, "filepath", text="") - - if strip.type == 'IMAGE': - row.prop(strip, "directory", text="") - # Current element for the filename - elem = strip.strip_elem_from_frame(context.scene.frame_current) - if elem: - row = layout.row() - # strip.elements[0] could be a fallback - row.prop(elem, "filename", text="File") - row.operator("sequencer.change_path", text="change files") - - if strip.type == 'COLOR': - row.prop(strip, "color", text="") - - # trim info - if strip.type not in {"SPEED", "WIPE", "CROSS", "ADJUSTMENT"}: - row = row.split(factor=1) - row.prop(prefs, "kr_show_trim", text="Trim", toggle=True) - if prefs.kr_show_trim: - box = layout.box() - if not isinstance(strip, bpy.types.EffectSequence): - row = box.row(align=True) - row.label(text="Hard:") - row.prop(strip, "animation_offset_start", text="Start") - row.prop(strip, "animation_offset_end", text="End") - row = box.row(align=True) - row.label(text="Soft:") - row.prop(strip, "frame_offset_start", text="Start") - row.prop(strip, "frame_offset_end", text="End") - - row = layout.row() - - # special strips info - if strip.type == 'SPEED': - row.prop(strip, "multiply_speed") - - if strip.type in {'CROSS', 'GAMMA_CROSS', 'WIPE', - 'ALPHA_OVER', 'ALPHA_UNDER', 'OVER_DROP'}: - row.prop(strip, "use_default_fade", "Default Fade") - if not strip.use_default_fade: - row.prop(strip, "effect_fader", text="Effect fader") - - if strip.type == 'GAUSSIAN_BLUR': - row.prop(strip, "size_x") - row.prop(strip, "size_y") - - if strip.type == 'WIPE': - row = layout.row() - row.prop(strip, "transition_type", expand=True) - row = layout.row() - row.prop(strip, "direction", expand=True) - row.prop(strip, "blur_width", slider=True) - if strip.transition_type in {'SINGLE', 'DOUBLE'}: - row.prop(strip, "angle") - - if strip.type == 'GLOW': - flow = layout.column_flow() - flow.prop(strip, "threshold", slider=True) - flow.prop(strip, "clamp", slider=True) - flow.prop(strip, "boost_factor") - flow.prop(strip, "blur_radius") - - row = layout.row() - row.prop(strip, "quality", slider=True) - row.prop(strip, "use_only_boost") - - if strip.type == 'SPEED': - row = layout.row() - row.prop(strip, "use_default_fade", "Stretch to input strip length") - if not strip.use_default_fade: - row.prop(strip, "use_as_speed") - if strip.use_as_speed: - layout.prop(strip, "speed_factor") - else: - layout.prop(strip, "speed_factor", text="Frame number") - layout.prop(strip, "scale_to_length") - - if strip.type == 'TRANSFORM': - row = layout.row(align=True) - row.prop(strip, "interpolation") - row.prop(strip, "translation_unit") - row = layout.row(align=True) - row.prop(strip, "translate_start_x", text="Pos X") - row.prop(strip, "translate_start_y", text="Pos Y") - - row = layout.row(align=True) - if strip.use_uniform_scale: - row.prop(strip, "scale_start_x", text="Scale") - else: - row.prop(strip, "scale_start_x", text="Scale X") - row.prop(strip, "scale_start_y", text="Scale Y") - row = layout.row(align=True) - row.prop(strip, "use_uniform_scale") - row.prop(strip, "rotation_start", text="Rotation") - - if strip.type == 'MULTICAM': - layout.prop(strip, "multicam_source") - - row = layout.row(align=True) - sub = row.row(align=True) - sub.scale_x = 2.0 - - sub.operator("screen.animation_play", text="", icon='PAUSE' if - context.screen.is_animation_playing else 'PLAY') - - row.label(text="Cut To") - for i in range(1, strip.channel): - row.operator("sequencer.cut_multicam", text="%d" % i).camera = i - - try: - if strip.input_count > 0: - col = layout.column() - col.prop(strip, "input_1") - if strip.input_count > 1: - col.prop(strip, "input_2") - except AttributeError: - pass - - # extra info box: - if prefs.kr_extra_info: - layout = self.layout - box = layout.box() - if strip.type not in {'SOUND'}: - row = box.row(align=True) - sub = row.row(align=True) - # mute this box - box.active = (not strip.mute) - sub.prop(prefs, "kr_extra_info", text="", icon='BORDERMOVE', emboss=True) - sub.separator() - sub.prop(strip, "blend_alpha", text="Opacity", slider=True) - row.prop(strip, "mute", toggle=True, icon_only=True) - row.prop(strip, "lock", toggle=True, icon_only=True) - - split = box.split(factor=0.5) - left_box = split.box() - row = left_box.row() - row.prop(strip, "strobe") - - col = left_box.column(align=True) - col.separator() - col.prop(strip, "use_flip_x", text="Flip X", toggle=True) - col.prop(strip, "use_flip_y", text="Flip Y", toggle=True) - col.prop(strip, "use_reverse_frames", text="Backwards", toggle=True) - col.prop(strip, "use_deinterlace", toggle=True) - - right_box = split.box() - col = right_box.column() - col.prop(strip, "blend_type", icon='COLOR') - col.prop(strip, "alpha_mode") - - col = right_box.column() - col.prop(strip, "color_saturation", text="Saturation") - col.prop(strip, "color_multiply", text="Multiply") - col.prop(strip, "use_float", text="Convert Float") - - row = box.row(align=True) - row.prop(strip, "use_translation", text="Image Offset", icon="AXIS_TOP") - row.prop(strip, "use_crop", text="Image Crop", icon="BORDER_RECT") - if strip.use_translation: - row = box.row(align=True) - row.prop(strip.transform, "offset_x", text="X") - row.prop(strip.transform, "offset_y", text="Y") - if strip.use_crop: - row = box.row(align=True) - row.prop(strip.crop, "max_y") - row.prop(strip.crop, "min_x") - row.prop(strip.crop, "min_y") - row.prop(strip.crop, "max_x") - - else: - # sound type - row = box.row() - row.prop(prefs, "kr_extra_info", text="", icon='BORDERMOVE', emboss=True) - sub = row.row(align=True) - sub.prop(strip, "volume") - sub.prop(strip, "mute", toggle=True, icon_only=True) - sub.prop(strip, "lock", toggle=True, icon_only=True) - - sound = strip.sound - if sound is not None: - row = box.row() - if sound.packed_file: - row.operator("sound.unpack", icon='PACKAGE', text="Unpack") - else: - row.operator("sound.pack", icon='UGLYPACKAGE', text="Pack") - - row.prop(sound, "use_memory_cache", toggle=True, icon="DISK_DRIVE") - - row.prop(strip, "show_waveform", toggle=True, icon="RNDCURVE") - - row = box.row(align=True) - row.prop(strip, "pitch") - row.prop(strip, "pan") - - # modifiers - if strip.type != 'SOUND' and prefs.kr_show_modifiers: - sequencer = context.scene.sequence_editor - layout = self.layout - layout = layout.box() - # mute this box - layout.active = (not strip.mute) - row = layout.split(factor=0.075) - row.prop(prefs, "kr_show_modifiers", text="", - icon='RESTRICT_VIEW_OFF', emboss=True) - row = row.split(factor=0.40) - row.prop(strip, "use_linear_modifiers", text="Linear") - row = row.split(factor=1) - row.operator_menu_enum("sequencer.strip_modifier_add", "type") - - for mod in strip.modifiers: - box = layout.box() - - row = box.row() - row.prop(mod, "show_expanded", text="", emboss=False) - row.prop(mod, "name", text="") - - row.prop(mod, "mute", text="") - - sub = row.row(align=True) - props = sub.operator("sequencer.strip_modifier_move", text="", icon='TRIA_UP') - props.name = mod.name - props.direction = 'UP' - props = sub.operator("sequencer.strip_modifier_move", text="", icon='TRIA_DOWN') - props.name = mod.name - props.direction = 'DOWN' - - row.operator("sequencer.strip_modifier_remove", text="", icon='X', - emboss=False).name = mod.name - - if mod.show_expanded: - row = box.row() - row.prop(mod, "input_mask_type", expand=True) - - if mod.input_mask_type == 'STRIP': - sequences_object = sequencer - if sequencer.meta_stack: - sequences_object = sequencer.meta_stack[-1] - box.prop_search(mod, "input_mask_strip", - sequences_object, "sequences", text="Mask") - else: - box.prop(mod, "input_mask_id") - row = box.row() - row.prop(mod, "mask_time", expand=True) - - if mod.type == 'COLOR_BALANCE': - box.prop(mod, "color_multiply") - draw_color_balance(box, mod.color_balance) - elif mod.type == 'CURVES': - box.template_curve_mapping(mod, "curve_mapping", type='COLOR') - elif mod.type == 'HUE_CORRECT': - box.template_curve_mapping(mod, "curve_mapping", type='HUE') - elif mod.type == 'BRIGHT_CONTRAST': - col = box.column() - col.prop(mod, "bright") - col.prop(mod, "contrast") - elif mod.type == 'WHITE_BALANCE': - col = box.column() - col.prop(mod, "white_value") - elif mod.type == 'TONEMAP': - col = box.column() - col.prop(mod, "tonemap_type") - if mod.tonemap_type == 'RD_PHOTORECEPTOR': - col.prop(mod, "intensity") - col.prop(mod, "contrast") - col.prop(mod, "adaptation") - col.prop(mod, "correction") - elif mod.tonemap_type == 'RH_SIMPLE': - col.prop(mod, "key") - col.prop(mod, "offset") - col.prop(mod, "gamma") - - if "copy_modifiers" in dir(bpy.ops.sequencer): - row = layout.row(align=True) - row.operator("sequencer.copy_modifiers", - text="Copy Modifiers", icon='COPYDOWN') - row.operator("sequencer.paste_modifiers", - text="Paste Modifiers", icon='PASTEDOWN') |