diff options
-rw-r--r-- | kinoraw_tools/__init__.py | 392 | ||||
-rw-r--r-- | kinoraw_tools/audio_tools.py | 158 | ||||
-rw-r--r-- | kinoraw_tools/datamosh.py | 123 | ||||
-rw-r--r-- | kinoraw_tools/eco.py | 95 | ||||
-rw-r--r-- | kinoraw_tools/functions.py | 362 | ||||
-rw-r--r-- | kinoraw_tools/jumptocut.py | 497 | ||||
-rw-r--r-- | kinoraw_tools/operators_extra_actions.py | 570 | ||||
-rw-r--r-- | kinoraw_tools/proxy_tools.py | 183 | ||||
-rw-r--r-- | kinoraw_tools/random_editor.py | 152 | ||||
-rw-r--r-- | kinoraw_tools/recursive_loader.py | 145 | ||||
-rw-r--r-- | kinoraw_tools/ui.py | 644 |
11 files changed, 1663 insertions, 1658 deletions
diff --git a/kinoraw_tools/__init__.py b/kinoraw_tools/__init__.py index b55dd464..c029281b 100644 --- a/kinoraw_tools/__init__.py +++ b/kinoraw_tools/__init__.py @@ -19,26 +19,28 @@ bl_info = { "name": "Kinoraw Tools", "author": "Carlos Padial, Turi Scandurra", - "version": (0, 5), + "version": (0, 5, 1), "blender": (2, 74, 0), "location": "Sequencer", - "description": "compilation of tools to improve video editing with blender's VSE", - "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/Py/Scripts/Sequencer/Kinoraw_Tools", + "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 imp - imp.reload(jumptocut) - imp.reload(operators_extra_actions) - imp.reload(audio_tools) - imp.reload(proxy_tools) - imp.reload(recursive_loader) - imp.reload(eco) - imp.reload(random_editor) - imp.reload(ui) - imp.reload(datamosh) + 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 @@ -51,194 +53,265 @@ else: from . import datamosh import bpy -import os.path -from bpy.types import Menu -from bpy.types import Header - -from bpy.props import IntProperty, StringProperty, BoolProperty, EnumProperty - - -class KinorawToolsAddon(bpy.types.AddonPreferences): +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'} - + + print("package is ", __package__) + # extra_actions kr_show_tools = BoolProperty( - name = "show tools" , - description = 'show extra tools in the panel', - default = False) + 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) + 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) + name="Show info", + description="Show basic info from selected strip", + default=False + ) kr_show_trim = BoolProperty( - name = 'show trim', - default = False) + name="Show trim", + default=False + ) kr_show_modifiers = BoolProperty( - name = 'show modifiers', - default = False) + name="Show modifiers", + description="Show modifiers from selected strip", + default=False + ) kr_extra_info = BoolProperty( - name = 'show extra info', - default = False) - + 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) - + 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) + name="Glitch panel | depends on external programs, see Documentation", + default=False + ) all_keyframes = BoolProperty( - name = 'remove all keyframes', - default = True) + name="Remove all keyframes", + default=True + ) load_glitch = BoolProperty( - name = 'load glitch after conversion > UNSTABLE!!!', - default = True) - + name="Load glitch after conversion > UNSTABLE!!!", + default=True + ) # jump to cut use_jumptocut = BoolProperty( - name = 'jumptocut panel', - default = True) + name="Jump to Cut Panel", + default=True + ) use_io_tools = BoolProperty( - name = 'enable in and out tools in jumptocut panel', - default = False) - + 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) + name="Proxy tools Panel | depends on external programs, see Documentation", + default=False + ) proxy_dir = StringProperty( - name = 'Proxy Custom Directory', - default = "//proxies/") + name="Proxy Custom Directory", + default="//proxies/" + ) proxy_scripts_path = StringProperty( - name = 'directory to store proxy scripts', - default = "//proxy_scripts/") + name="Directory to store proxy scripts", + default="//proxy_scripts/" + ) proxy_scripts = BoolProperty( - name = 'generate ffmpeg scritps', - default = False) + 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 {}''') + 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 proxy system', - default = True) + name="Use internal Blender's proxy system", + default=True + ) use_bi_custom_directory = BoolProperty( - name = 'Proxy Custom Directory', - default = True) + 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", "" )] + 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" ) - + 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) + name="Audio tools Panel | depends on external programs, see Documentation", + default=False + ) audio_dir = StringProperty( - name='path to store extracted audio', - default="//audio/") + name="Path to store extracted audio", + default="//audio/" + ) audio_scripts_path = StringProperty( - name='path to store audio scripts', - default="//audio_scripts/") + name="Path to store audio scripts", + default="//audio_scripts/" + ) audio_scripts = BoolProperty( - name='generate ffmpeg scritps', - default=False) - + 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) + 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") - + 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", "" )] - + 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" ) - + name="Meter type", + items=meterbridge, + default="DPM", + description="Meterbridge meter type" + ) # eco use_eco_tools = BoolProperty( - name='eco tools panel', - default=True) + name="Eco tools Panel", + default=True + ) eco_value = IntProperty( - name = 'number of echoes', - default = 5, - min = 1, max = 25) + name="Number of echoes", + default=5, + min=1, max=25 + ) eco_offset = IntProperty( - name = 'Echo Offset', - default = 1, - min = -25000, max = 25000) + name="Echo Offset", + default=1, + min=-25000, max=25000 + ) eco_use_add_blend_mode = BoolProperty( - name = 'use_add_blend_mode', - default = False) - + name='use_add_blend_mode', + default=False + ) # random editor use_random_editor = BoolProperty( - name='random editor panel | Experimental', - default=False) + name="Random editor Panel | Experimental", + default=False + ) random_frames = IntProperty( - name='frames', + name="Frames", default=1, - min = 1, max = 1000) + min=1, max=1000 + ) random_selected_scene = StringProperty( - name = 'selected_scene', - default = '') + name="Selected Scene", + default="" + ) random_use_marker_subsets = BoolProperty( - name = 'use_marker_subsets', - default = True) + name="Use_Marker subsets", + default=True + ) random_number_of_subsets = IntProperty( - name = 'number_of_subsets', - default = 3, - min = 1, max = 5) + 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 - layout.prop(self, "use_jumptocut") - layout = self.layout - layout.prop(self, "use_proxy_tools") - layout = self.layout - layout.prop(self, "use_audio_tools") - layout = self.layout - layout.prop(self, "use_exif_panel") - layout = self.layout - layout.prop(self, "use_eco_tools") - layout = self.layout - layout.prop(self, "use_random_editor") layout = self.layout - layout.prop(self, "use_glitch_panel") - + 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) @@ -255,50 +328,47 @@ def register(): # jump 1 second kmi = km.keymap_items.new('screenextra.frame_skip', - 'RIGHT_ARROW', 'PRESS', ctrl=True, shift=True) + '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) + '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 + '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 + 'W', 'PRESS', ctrl=False, shift=False) + kmi.properties.next = True + kmi.properties.center = False - # in and out + # in and out kmi = km.keymap_items.new("sequencerextra.sourcein", - 'I', 'PRESS', ctrl=True, shift=True) + 'I', 'PRESS', ctrl=True, shift=True) kmi = km.keymap_items.new("sequencerextra.sourceout", - 'O', 'PRESS', ctrl=True, shift=True) + 'O', 'PRESS', ctrl=True, shift=True) - #markers + # 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 + '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 + '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) @@ -309,7 +379,6 @@ def unregister(): 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'] @@ -322,12 +391,11 @@ def unregister(): 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/kinoraw_tools/audio_tools.py b/kinoraw_tools/audio_tools.py index d0278de0..bf615d5a 100644 --- a/kinoraw_tools/audio_tools.py +++ b/kinoraw_tools/audio_tools.py @@ -1,29 +1,32 @@ -import bpy, os -from bpy.props import IntProperty, StringProperty, BoolProperty +# 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%", "" )] - +proxy_qualities = [ + ("1", "25%", ""), ("2", "50%", ""), + ("3", "75%", ""), ("4", "100%", "")] + # # ls *.sh | parallel -j 8 sh {} # -# functions - - - +# 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 + f.writelines(data) # Write a sequence of strings to a file finally: f.close() @@ -45,7 +48,7 @@ def writesyncfile(filename, data): f = open(bpy.path.abspath(filename), "w") try: for line in data: - f.writelines(line) # Write a sequence of strings to a file + f.writelines(line) # Write a sequence of strings to a file finally: f.close() @@ -55,16 +58,15 @@ def writesyncfile(filename, data): # classes - -class ExtractWavOperator(bpy.types.Operator): - """ Use ffmpeg to extract audio from video and import it synced""" +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'}) + return (context.space_data.view_type in + {'SEQUENCER', 'SEQUENCER_PREVIEW'}) @classmethod def poll(self, context): @@ -75,8 +77,6 @@ class ExtractWavOperator(bpy.types.Operator): else: return False - - def execute(self, context): preferences = context.user_preferences @@ -91,61 +91,64 @@ class ExtractWavOperator(bpy.types.Operator): 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" + 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 + # 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("ya existe") + 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) + 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 scene context.scene.update() newstrip = context.scene.sequence_editor.active_strip - # deselect all other strips + # deselect all other strips for i in context.selected_editable_sequences: if i.name != newstrip.name: - i.select=False + i.select = False # Update scene context.scene.update() - #Match the original clip's length - + # Match the original clip's length newstrip.frame_start = strip.frame_start - strip.animation_offset_start - #print(newstrip.name) functions.triminout(newstrip, strip.frame_start + strip.frame_offset_start, - strip.frame_start + strip.frame_offset_start + \ + strip.frame_start + strip.frame_offset_start + strip.frame_final_duration) return {'FINISHED'} - -class ExternalAudioSetSyncOperator(bpy.types.Operator): - """get sync info from selected audio and video strip and store it into a text file """ +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'}) + return (context.space_data.view_type in + {'SEQUENCER', 'SEQUENCER_PREVIEW'}) @classmethod def poll(cls, context): @@ -159,7 +162,6 @@ class ExternalAudioSetSyncOperator(bpy.types.Operator): else: return False - def execute(self, context): preferences = context.user_preferences @@ -177,7 +179,7 @@ class ExternalAudioSetSyncOperator(bpy.types.Operator): data2 = [] newline = moviestrip.filepath + " " + soundstrip.filepath + " " + offset + "\n" - if data1 != None: + if data1 is not None: repeated = False for line in data1: if line.split()[0] == moviestrip.filepath and line.split()[1] == soundstrip.filepath: @@ -196,15 +198,16 @@ class ExternalAudioSetSyncOperator(bpy.types.Operator): return {'FINISHED'} -class ExternalAudioReloadOperator(bpy.types.Operator): - """ reload external audio synced to selected movie strip acording to info from a text file """ +class ExternalAudioReloadOperator(Operator): bl_idname = "sequencer.external_audio_reload" - bl_label = "reload external audio" + bl_label = "Reload External audio" + bl_description = ("Reload external audio synced to selected movie strip " + "acording to info from a text file") @staticmethod def has_sequencer(context): - return (context.space_data.view_type\ - in {'SEQUENCER', 'SEQUENCER_PREVIEW'}) + return (context.space_data.view_type in + {'SEQUENCER', 'SEQUENCER_PREVIEW'}) @classmethod def poll(cls, context): @@ -215,17 +218,15 @@ class ExternalAudioReloadOperator(bpy.types.Operator): else: return False - def execute(self, context): - preferences = context.user_preferences filename = preferences.addons[__package__].preferences.audio_external_filename data = readsyncfile(filename) for strip in context.selected_editable_sequences: + sounds = [] - sounds = [] for line in data: if line.split()[0] == strip.filepath: moviefile = bpy.path.abspath(line.split()[0]) @@ -233,27 +234,30 @@ class ExternalAudioReloadOperator(bpy.types.Operator): offset = int(line.split()[2]) sounds.append((soundfile, offset)) - for soundfile, offset in sounds: - print(soundfile,offset) + 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) + 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 scene context.scene.update() newstrip = context.scene.sequence_editor.active_strip - # deselect all other strips + # deselect all other strips for i in context.selected_editable_sequences: if i.name != newstrip.name: - i.select=False + i.select = False # Update scene context.scene.update() @@ -261,14 +265,14 @@ class ExternalAudioReloadOperator(bpy.types.Operator): # 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) + strip.frame_start + strip.frame_offset_start + + strip.frame_final_duration + ) return {'FINISHED'} -class AudioToolPanel(bpy.types.Panel): - """ """ +class AudioToolPanel(Panel): bl_label = "Audio Tools" bl_idname = "OBJECT_PT_AudioTool" bl_space_type = 'SEQUENCE_EDITOR' @@ -277,7 +281,6 @@ class AudioToolPanel(bpy.types.Panel): @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.user_preferences prefs = preferences.addons[__package__].preferences @@ -292,7 +295,6 @@ class AudioToolPanel(bpy.types.Panel): layout.label(text="", icon="PLAY_AUDIO") def draw(self, context): - preferences = context.user_preferences prefs = preferences.addons[__package__].preferences @@ -300,42 +302,40 @@ class AudioToolPanel(bpy.types.Panel): if strip.type == "MOVIE": layout = self.layout - layout.prop(prefs, "audio_dir", text="path for audio files") - + 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.prop(prefs, "audio_scripts_path", text="Path for scripts") layout = self.layout - layout.prop(prefs, "audio_use_external_links", text="external audio sync") - + 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") + 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") + 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") + row.operator("sequencer.openmeterbridge", + text="Launch Audio Meter", icon="SOUND") -class OpenMeterbridgeOperator(bpy.types.Operator): - """ """ +class OpenMeterbridgeOperator(Operator): bl_idname = "sequencer.openmeterbridge" - bl_label = "open external vu meter to work with jack" + bl_label = "External VU meter" + bl_description = "Open external VU meter to work with Jack" @staticmethod def has_sequencer(context): @@ -346,15 +346,13 @@ class OpenMeterbridgeOperator(bpy.types.Operator): if cls.has_sequencer(context): if len(context.selected_editable_sequences) == 1: return True - def execute(self, context): preferences = context.user_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'} - + 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/kinoraw_tools/datamosh.py b/kinoraw_tools/datamosh.py index 0dc9d015..be6ea89d 100644 --- a/kinoraw_tools/datamosh.py +++ b/kinoraw_tools/datamosh.py @@ -1,23 +1,29 @@ -import bpy, os -from bpy.props import IntProperty, StringProperty, BoolProperty -import subprocess - +# 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", "" )] +proxy_qualities = [ + ("1", "25%", ""), ("2", "50%", ""), + ("3", "75%", ""), ("4", "100%", ""), + ("5", "none", "") + ] # functions - def createdatamosh(context, strip): preferences = context.user_preferences prefs = preferences.addons[__package__].preferences fileinput = bpy.path.abspath(strip.filepath) - fileoutput = fileinput.rpartition(".")[0]+"_datamosh.avi" + fileoutput = fileinput.rpartition(".")[0] + "_datamosh.avi" if prefs.all_keyframes: command = "datamosh '{}' -a -o '{}'".format(fileinput, fileoutput) @@ -27,41 +33,42 @@ def createdatamosh(context, strip): os.system(command) return fileoutput -def createavi(context, strip): - preferences = context.user_preferences - prefs = preferences.addons[__package__].preferences +def createavi(context, strip): fileinput = bpy.path.abspath(strip.filepath) - fileoutput = fileinput.rpartition(".")[0]+"_.avi" + fileoutput = fileinput.rpartition(".")[0] + "_.avi" command = "ffmpeg -i '{}' -vcodec copy '{}'".format(fileinput, fileoutput) print(command) os.system(command) + return fileoutput -def createavimjpeg(context, strip): - preferences = context.user_preferences - prefs = preferences.addons[__package__].preferences +def createavimjpeg(context, strip): fileinput = bpy.path.abspath(strip.filepath) - fileoutput = fileinput.rpartition(".")[0]+"_mjpeg.avi" + fileoutput = fileinput.rpartition(".")[0] + "_mjpeg.avi" command = "ffmpeg -i '{}' -vcodec mjpeg -q:v 1 '{}'".format(fileinput, fileoutput) print(command) os.system(command) - return fileoutput - + return fileoutput # classes - -class CreateAvi(bpy.types.Operator): - """ """ +class CreateAvi(Operator): bl_idname = "sequencer.createavi" - bl_label = "create avi file" + 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): @@ -72,20 +79,14 @@ class CreateAvi(bpy.types.Operator): else: return False - size = IntProperty( - name='proxysize', - default=1) - bl_options = {'REGISTER', 'UNDO'} - def execute(self, context): - - preferences = context.user_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 + # 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: @@ -93,20 +94,23 @@ class CreateAvi(bpy.types.Operator): elif self.size == 2: fileoutput = createavimjpeg(context, strip) strip.filepath = fileoutput - #select all strips again + + # select all strips again for strip in strips: - try: - strip.select=True + try: + strip.select = True except ReferenceError: pass + bpy.ops.sequencer.reload() + return {'FINISHED'} -class CreateDatamosh(bpy.types.Operator): - """ """ +class CreateDatamosh(Operator): bl_idname = "sequencer.createdatamosh" - bl_label = "create datamosh" + bl_label = "Create Datamosh" + bl_description = "Create Datamosh" @classmethod def poll(self, context): @@ -118,42 +122,43 @@ class CreateDatamosh(bpy.types.Operator): return False def execute(self, context): - preferences = context.user_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 + # 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 + + # select all strips again for strip in strips: - try: - strip.select=True + try: + strip.select = True except ReferenceError: pass + bpy.ops.sequencer.reload() + return {'FINISHED'} -class CreateGlitchToolPanel(bpy.types.Panel): - """ """ +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'}: + 'SEQUENCER_PREVIEW'}: strip = functions.act_strip(context) scn = context.scene preferences = context.user_preferences @@ -175,20 +180,10 @@ class CreateGlitchToolPanel(bpy.types.Panel): layout = self.layout - layout.operator("sequencer.createavi", text="create avi (same codec)") - layout.operator("sequencer.createavi", text="create avi (mjpeg)").size=2 - - strip = functions.act_strip(context) + 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.prop(prefs, "all_keyframes") + layout.prop(prefs, "load_glitch") layout.operator("sequencer.createdatamosh") - - - - - - - - diff --git a/kinoraw_tools/eco.py b/kinoraw_tools/eco.py index 01d13f71..62382389 100644 --- a/kinoraw_tools/eco.py +++ b/kinoraw_tools/eco.py @@ -1,6 +1,4 @@ -#---------------------------------------------------------- # File sequencer_slide_strip.py -#---------------------------------------------------------- # ##### BEGIN GPL LICENSE BLOCK ##### # @@ -21,14 +19,15 @@ # ##### END GPL LICENSE BLOCK ##### - import bpy -from bpy.props import IntProperty, BoolProperty - +from bpy.types import ( + Operator, + Panel, + ) from . import functions - - -class EcoPanel(bpy.types.Panel): + + +class EcoPanel(Panel): bl_label = "Eco Tool" bl_idname = "OBJECT_PT_EcoTool" bl_space_type = "SEQUENCE_EDITOR" @@ -36,8 +35,8 @@ class EcoPanel(bpy.types.Panel): @staticmethod def has_sequencer(context): - return (context.space_data.view_type\ - in {'SEQUENCER', 'SEQUENCER_PREVIEW'}) + return (context.space_data.view_type in + {'SEQUENCER', 'SEQUENCER_PREVIEW'}) @classmethod def poll(self, context): @@ -51,45 +50,38 @@ class EcoPanel(bpy.types.Panel): 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): - scn = bpy.context.scene strip = functions.act_strip(context) seq_type = strip.type preferences = context.user_preferences prefs = preferences.addons[__package__].preferences - - if seq_type in ( 'MOVIE', 'IMAGE', 'META', 'MOVIECLIP', 'SCENE') : - active_strip = functions.act_strip(context) + + if seq_type in ('MOVIE', 'IMAGE', 'META', 'MOVIECLIP', 'SCENE'): layout = self.layout - row=layout.row() - row.prop(prefs, 'eco_value', text="Ecos") - row=layout.row() - row.prop(prefs, 'eco_offset', text="Offset") - row=layout.row() - row.prop(prefs, 'eco_use_add_blend_mode', text="use_add_blend_mode") - row=layout.row() - row.operator('sequencer.eco') - - - - -class OBJECT_OT_EcoOperator(bpy.types.Operator): - + 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_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'}) + return (context.space_data.view_type in + {'SEQUENCER', 'SEQUENCER_PREVIEW'}) @classmethod def poll(self, context): @@ -99,42 +91,37 @@ class OBJECT_OT_EcoOperator(bpy.types.Operator): return strip.type in ('META') else: return False - + def execute(self, context): - - active_strip=functions.act_strip(context) - + active_strip = functions.act_strip(context) + preferences = context.user_preferences prefs = preferences.addons[__package__].preferences - - scn = bpy.context.scene - sel_strips = bpy.context.selected_sequences - cur_camera = scn.camera + eco = prefs.eco_value - offset = prefs.eco_offset - + 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) - + 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 + active_strip.blend_alpha = 1 - 1 / eco else: active_strip.blend_type = 'ALPHA_OVER' - active_strip.blend_alpha = 1/eco - - + 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/kinoraw_tools/functions.py b/kinoraw_tools/functions.py index cdbac3de..2722f321 100644 --- a/kinoraw_tools/functions.py +++ b/kinoraw_tools/functions.py @@ -17,13 +17,16 @@ # ##### END GPL LICENSE BLOCK ##### import bpy -import os.path, operator, subprocess, random - -from bpy.props import IntProperty -from bpy.props import FloatProperty -from bpy.props import EnumProperty -from bpy.props import BoolProperty -from bpy.props import StringProperty +import os.path +import operator +import subprocess +import random +from bpy.props import ( + IntProperty, + FloatProperty, + EnumProperty, + BoolProperty, + ) imb_ext_image = [ # IMG @@ -31,124 +34,145 @@ imb_ext_image = [ ".rgba", ".tif", ".tiff", ".tx", ".jp2", ".hdr", ".dds", ".dpx", ".cin", ".exr", ".rw2", # IMG QT - ".gif", ".psd", ".pct", ".pict", ".pntg", ".qtif"] - + ".gif", ".psd", ".pct", ".pict", ".pntg", ".qtif" + ] imb_ext_audio = [ ".wav", ".ogg", ".oga", ".mp3", ".mp2", ".ac3", ".aac", - ".flac", ".wma", ".eac3", ".aif", ".aiff", ".m4a"] - + ".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", "")] + ".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 varaibles that should + # initSceneProperties is ONLY for varaibles 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 == True: + if context.scene.kr_scn_init is True: return False except AttributeError: pass scn = context.scene - # JUMP TO CUT + # jump to cut bpy.types.Scene.kr_auto_markers = BoolProperty( - name='kr_auto_markers', - description='activate auto markers', - default=False) + 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) + 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) + name="Out", + description="Out frame position", + min=scn.kr_in_marker, max=30000, + default=75 + ) scn.kr_out_marker = 75 - - # SEQUENCER EXTRA ACTIONS + + # 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) + 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) + 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 + # recursive loader bpy.types.Scene.kr_recursive = BoolProperty( - name='Recursive', - description='Load in recursive folders', - default=False) + 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) + 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") + items=movieextdict, + name="ext enum", + default="3" + ) scn.kr_default_ext = "3" - + bpy.types.Scene.kr_scn_init = BoolProperty( - name='Init', - default=False) + name="Init", + default=False + ) scn.kr_scn_init = True return True + def get_selected_strips(context): "return a list of selected strips" - strips=[] + strips = [] for i in context.scene.sequence_editor.sequences_all: - if i.select == True: + 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) + command = "mkdir " + folder + subprocess.call(command, shell=True) + def add_marker(context, text, frame): scn = context.scene @@ -156,12 +180,14 @@ def add_marker(context, text, frame): 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() @@ -176,13 +202,12 @@ def detect_strip_type(filepath): return type -# recursive load functions +# recursive load functions def getpathfrombrowser(context): ''' returns path from filebrowser ''' - scn = context.scene for a in context.window.screen.areas: if a.type == 'FILE_BROWSER': params = a.spaces[0].params @@ -190,17 +215,16 @@ def getpathfrombrowser(context): try: params except UnboundLocalError: - #print("no browser") - self.report({'ERROR_INVALID_INPUT'}, 'No visible File Browser') return {'CANCELLED'} + path = params.directory return path + def getfilepathfrombrowser(context): - ''' + """ returns path and file from filebrowser - ''' - scn = context.scene + """ for a in context.window.screen.areas: if a.type == 'FILE_BROWSER': params = a.spaces[0].params @@ -208,23 +232,20 @@ def getfilepathfrombrowser(context): try: params except UnboundLocalError: - #print("no browser") - #self.report({'ERROR_INVALID_INPUT'}, 'No visible File Browser') return {'CANCELLED'} if params.filename == '': - #print("no file selected") - #self.report({'ERROR_INVALID_INPUT'}, 'No file selected') return {'CANCELLED'} + path = params.directory filename = params.filename return path, filename + def setpathinbrowser(context, path, file): ''' set path and file in the filebrowser ''' - scn = context.scene for a in context.window.screen.areas: if a.type == 'FILE_BROWSER': params = a.spaces[0].params @@ -232,14 +253,14 @@ def setpathinbrowser(context, path, file): try: params except UnboundLocalError: - #print("no browser") - self.report({'ERROR_INVALID_INPUT'}, 'No visible File Browser') + 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 @@ -247,74 +268,75 @@ def sortlist(filelist): 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: + + for i in movieextdict: if i[0] == ext: extension = i[1].rpartition(".")[2] break - scn = context.scene - if detect_strip_type(path + filename) == 'MOVIE': - if recursive_select_by_extension == True: - #filtering by extension... + 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 + # 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 - - scn = context.scene + for root, dirs, files in os.walk(path): for file in files: - if recursive_select_by_extension == True: - #filtering by extension... + 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 + # looking for all known extensions for i in movieextdict: if file.rpartition(".")[2].lower() == i[1].rpartition(".")[2]: filelist.append((root, file)) - return filelist + return filelist -# jump to cut functions +# jump to cut functions def triminout(strip, sin, sout): - """trim the strip to in and out, and returns + """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: + remove = True + if start > sout: + remove = True + if end > sin: if start < sin: strip.select_right_handle = False @@ -331,109 +353,103 @@ def triminout(strip, sin, sout): return remove -#------------ random editor functions. +# random editor functions -def randompartition(lst,n,rand): +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 + 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=[] + 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]) + # 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 + # random frame between a and b a = strip.frame_start b = strip.frame_final_duration - rand = a+int(random.random()*b) - #print(a, a+b, rand) + 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=[] + ''' + 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==None: + # 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 + # generate marker subsets list subset_list = [] - subset_names = ['A','B','C','D','E','F'] + 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''' - #get markers from scene - markers = scene.timeline_markers + """ + 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 + # generate dict with a list for each subset marker_dict = {} + for subset in subset_list: - list=get_matching_markers(scene, subset) - marker_dict[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 - - list=get_matching_markers(scene) - list.append(scene.frame_start) - list.append(scene.frame_end) - list.sort() - #print("lista:",len(list),list) - cut_dict ={} - for i, j in enumerate(list): + """ + 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: - #print(j,list[i+1]-1-j) - cut_dict[j] = list[i+1]-j + cut_dict[j] = lists[i + 1] - j except IndexError: - continue + continue return cut_dict - - -def random_edit_from_random_subset(cut_dict, sources_dict): - '''return a random edit from random subsets''' - #generate subset list (strings) - subset_list = generate_subsets_list(number_of_subsets) - # copy sources_dict - random_edit = [] - for cut in sorted(cut_dict.keys()): - #escoge un subset al azar: - rand = random.randrange(number_of_subsets) - subset = subset_list[rand] - #check if source subset is empty - print(len(sources_dict[subset]),subset) - if len(sources_dict[subset]) == 0: - sources_dict[subset] = get_matching_markers(selected_scene, subset) - print("repeating "+ subset + " clips") - marker = sources_dict[subset].pop() - random_edit.append((cut, cut_dict[cut], subset, marker)) - return random_edit diff --git a/kinoraw_tools/jumptocut.py b/kinoraw_tools/jumptocut.py index 0ccd05e0..d0be54a6 100644 --- a/kinoraw_tools/jumptocut.py +++ b/kinoraw_tools/jumptocut.py @@ -18,20 +18,21 @@ import bpy - from . import functions -from bpy.props import IntProperty, BoolProperty - +from bpy.types import ( + Operator, + ) +from bpy.props import ( + IntProperty, + ) from bpy.app.handlers import persistent - -class OBJECT_OT_Setinout(bpy.types.Operator): - bl_label = "set IN and OUT to selected" +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'} + bl_description = "Set IN and OUT markers to the selected strips limits" + bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(self, context): @@ -43,29 +44,28 @@ class OBJECT_OT_Setinout(bpy.types.Operator): def execute(self, context): functions.initSceneProperties(context) - + scn = context.scene - markers =scn.timeline_markers + 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 + # search for timeline limits tl_start = 300000 tl_end = -300000 for i in context.selected_editable_sequences: - if i.select == True: + 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) + # print(tl_start,tl_end) - if scn.kr_auto_markers: scn.kr_in_marker = tl_start scn.kr_out_marker = tl_end @@ -74,85 +74,87 @@ class OBJECT_OT_Setinout(bpy.types.Operator): scn.kr_out_marker = tl_end if "IN" in markers: - mark=markers["IN"] - mark.frame=scn.kr_in_marker + mark = markers["IN"] + mark.frame = scn.kr_in_marker else: - mark=markers.new(name="IN") - mark.frame=scn.kr_in_marker + mark = markers.new(name="IN") + mark.frame = scn.kr_in_marker if "OUT" in markers: - mark=markers["OUT"] - mark.frame=scn.kr_out_marker + mark = markers["OUT"] + mark.frame = scn.kr_out_marker else: - mark=markers.new(name="OUT") - mark.frame=scn.kr_in_marker + mark = markers.new(name="OUT") + mark.frame = scn.kr_in_marker return {'FINISHED'} -class OBJECT_OT_Triminout(bpy.types.Operator): +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'} + 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 + 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 + 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 + + markers = scene.timeline_markers + sin = markers["IN"].frame + sout = markers["OUT"].frame strips = context.selected_editable_sequences - #(triminout function only works fine + + # (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 + # 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 == True: + remove = functions.triminout(strip, sin, sout) + if remove is True: bpy.ops.sequencer.delete() - #select all strips again + + # select all strips again for strip in strips: - try: - strip.select=True + try: + strip.select = True except ReferenceError: pass + bpy.ops.sequencer.reload() - return {'FINISHED'} -# SOURCE IN OUT + return {'FINISHED'} + -class OBJECT_OT_Sourcein(bpy.types.Operator): #Operator source in +# 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'} + bl_description = "Add or move a marker named IN" + bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(self, context): - strip = functions.act_strip(context) scn = context.scene if scn: return scn.sequence_editor @@ -161,30 +163,28 @@ class OBJECT_OT_Sourcein(bpy.types.Operator): #Operator source in def execute(self, context): functions.initSceneProperties(context) - scn=context.scene - seq = scn.sequence_editor - markers=scn.timeline_markers - + 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 + mark = markers["IN"] + mark.frame = scn.kr_in_marker else: - mark=markers.new(name="IN") - mark.frame=scn.kr_in_marker + mark = markers.new(name="IN") + mark.frame = scn.kr_in_marker - #limit OUT marker position with 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 - + mark = markers["OUT"] + mark.frame = scn.kr_out_marker for m in markers: m.select = False @@ -194,16 +194,15 @@ class OBJECT_OT_Sourcein(bpy.types.Operator): #Operator source in return {'FINISHED'} -class OBJECT_OT_Sourceout(bpy.types.Operator): #Operator source out + +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'} + bl_description = "Add or move a marker named OUT" + bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(self, context): - strip = functions.act_strip(context) scn = context.scene if scn: return scn.sequence_editor @@ -211,28 +210,27 @@ class OBJECT_OT_Sourceout(bpy.types.Operator): #Operator source out return False def execute(self, context): - scn=context.scene + scn = context.scene functions.initSceneProperties(context) - seq = scn.sequence_editor - markers=scn.timeline_markers - + 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 + # 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 + mark = markers["OUT"] + mark.frame = scn.kr_out_marker else: - mark=markers.new(name="OUT") - mark.frame=scn.kr_out_marker - + mark = markers.new(name="OUT") + mark.frame = scn.kr_out_marker + for m in markers: m.select = False if m.name in {"IN", "OUT"}: @@ -240,17 +238,17 @@ class OBJECT_OT_Sourceout(bpy.types.Operator): #Operator source out bpy.ops.sequencer.reload() return {'FINISHED'} -class OBJECT_OT_Setstartend(bpy.types.Operator): #Operator set start & end - bl_label = "set Start & End" - bl_idname = "sequencerextra.setstartend" - bl_description = "set Start and End to IN and OUT marker values" - bl_options = {'REGISTER', 'UNDO'} +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 + markers = scn.timeline_markers if "IN" and "OUT" in markers: return True else: @@ -258,38 +256,45 @@ class OBJECT_OT_Setstartend(bpy.types.Operator): #Operator set start & end def execute(self, context): functions.initSceneProperties(context) - scn=context.scene - markers=scn.timeline_markers - sin=markers["IN"] - sout=markers["OUT"] + 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 +# Copy paste -class OBJECT_OT_Metacopy(bpy.types.Operator): #Operator copy source in/out - bl_label = "Trim & Meta-Copy" +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 (if available) and copy it to clipboard" + bl_description = ("Make meta from selected strips, trim it to in / out\n" + "(if available) and copy it to clipboard") - bl_options = {'REGISTER', 'UNDO'} + bl_options = {'REGISTER', 'UNDO'} def execute(self, context): - # rehacer - scene =bpy.context.scene - seq = scene.sequence_editor - markers =scene.timeline_markers - strip1 = seq.active_strip - if strip1 != None: + 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 + sin = markers["IN"].frame + sout = markers["OUT"].frame bpy.ops.sequencer.meta_make() - strip2= seq.active_strip - functions.triminout(strip2,sin,sout) + strip2 = seq.active_strip + functions.triminout(strip2, sin, sout) bpy.ops.sequencer.copy() bpy.ops.sequencer.meta_separate() self.report({'INFO'}, "META2 has been trimed and copied") @@ -297,36 +302,42 @@ class OBJECT_OT_Metacopy(bpy.types.Operator): #Operator copy source in/out bpy.ops.sequencer.meta_make() bpy.ops.sequencer.copy() bpy.ops.sequencer.meta_separate() - self.report({'WARNING'}, "No In & Out!! META has been copied") - else: - self.report({'ERROR'}, "No strip selected") + 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(bpy.types.Operator): #Operator paste source in/out + +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'} + bl_description = "Paste source from clipboard to current frame" + bl_options = {'REGISTER', 'UNDO'} def execute(self, context): - # rehacer - scene=bpy.context.scene + # 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.scene.sequence_editor.active_strip = strips[0] context.scene.update() + return {'FINISHED'} -class OBJECT_OT_Unmetatrim(bpy.types.Operator): #Operator paste source in/out +# 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'} - + bl_description = "Unmeta and trim the content to meta duration" + bl_options = {'REGISTER', 'UNDO'} + @classmethod def poll(self, context): scn = context.scene @@ -337,18 +348,18 @@ class OBJECT_OT_Unmetatrim(bpy.types.Operator): #Operator paste source in/out return False def execute(self, context): - scn=context.scene - seq=scn.sequence_editor - markers=scn.timeline_markers + 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 + + borrarin = False + borrarout = False original_in = 0 original_out = 0 @@ -356,59 +367,61 @@ class OBJECT_OT_Unmetatrim(bpy.types.Operator): #Operator paste source in/out original_in = markers["IN"].frame markers["IN"].frame = sin else: - mark=markers.new(name="IN") - mark.frame=sin - borrarin=True + mark = markers.new(name="IN") + mark.frame = sin + borrarin = True if "OUT" in markers: original_out = markers["OUT"].frame - markers["OUT"].frame=sout + markers["OUT"].frame = sout else: - mark= markers.new(name="OUT") - mark.frame=sout - borrarout=True + mark = markers.new(name="OUT") + mark.frame = sout + borrarout = True - # here starts the operator... - - #get all META from selected strips - metastrips=[] + + # get all META from selected strips + metastrips = [] for i in context.selected_editable_sequences: if i.type == "META": - metastrips.append(i) - + metastrips.append(i) + for meta in metastrips: - bpy.ops.sequencer.reload() + bpy.ops.sequencer.reload() - # deselect all strips + # deselect all strips for i in context.selected_editable_sequences: i.select = False - #make active current meta + # make active current meta meta.select = True seq.active_strip = meta bpy.ops.sequencer.reload() - #set in and out to meta + # set in and out to meta sin = meta.frame_start + meta.frame_offset_start sout = sin + meta.frame_final_duration - #print("meta: ", sin, sout) + # print("meta: ", sin, sout) - #grab meta content + # grab meta content newstrips = [] for i in meta.sequences: newstrips.append(i) - #store meta channel + # store meta channel basechan = meta.channel - #look for upper and lower channels used by strips inside the meta + # 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 + 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 @@ -417,68 +430,76 @@ class OBJECT_OT_Unmetatrim(bpy.types.Operator): #Operator paste source in/out chandict = {} for i in newstrips: i.channel = i.channel + deltachan - delta - chandict[i.name]=i.channel - #for i in chandict: print(i,chandict[i]) + chandict[i.name] = i.channel - #go inside meta to trim strips + """ + 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 + # 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 + # 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: + # 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"}: + if i.type in {"CROSS", "SPEED", "WIPE"}: i.select = True - remove = functions.triminout(i,sin,sout) - if remove == True: - #print("checked: ",i.name, i.type) + remove = functions.triminout(i, sin, sout) + if remove is True: + # print("checked: ",i.name, i.type) rmlist.append(i) - i.select=False + i.select = False + # now for the rest of strips for i in newstrips: i.select = True - remove = functions.triminout(i,sin,sout) - if remove == True: - #print("checked: ",i.name, i.type) + remove = functions.triminout(i, sin, sout) + if remove is True: + # print("checked: ",i.name, i.type) rmlist.append(i) - i.select=False + 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 + seq = scn.sequence_editor - #remove strips from outside the meta duration + # 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 + # 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 + # 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 + scn.sequence_editor.active_strip = i bpy.ops.sequencer.reload() - #restore original IN and OUT values + # restore original IN and OUT values if borrarin: markers.remove(markers['IN']) else: @@ -488,27 +509,25 @@ class OBJECT_OT_Unmetatrim(bpy.types.Operator): #Operator paste source in/out else: markers["OUT"].frame = original_out scn.update() - - return {'FINISHED'} -class OBJECT_OT_Extrasnap(bpy.types.Operator): #Operator paste source in/out - bl_label = "extrasnap" + +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_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) - - bl_options = {'REGISTER', 'UNDO'} + name="Align", + min=0, max=2, + default=1 + ) @classmethod def poll(self, context): - strip = functions.act_strip(context) scn = context.scene if scn and scn.sequence_editor: return scn.sequence_editor.active_strip @@ -516,35 +535,35 @@ class OBJECT_OT_Extrasnap(bpy.types.Operator): #Operator paste source in/out return False def execute(self, context): - scene=bpy.context.scene + 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 + 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(bpy.types.Operator): #Operator paste source in/out - bl_label = "extrahandles" + +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_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) - - bl_options = {'REGISTER', 'UNDO'} + name="Side", + min=0, max=2, + default=1 + ) @classmethod def poll(self, context): - strip = functions.act_strip(context) scn = context.scene if scn and scn.sequence_editor: return scn.sequence_editor.active_strip @@ -552,94 +571,86 @@ class OBJECT_OT_Extrahandles(bpy.types.Operator): #Operator paste source in/out return False def execute(self, context): - scn=context.scene 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: + 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: + 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: + resetRight = False + + if ((len(changelistRight) != len(strips)) or + (len(changelistRight) != len(strips))) and \ + self.side == 1: resetLeft = True - resetRight = 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'} - - - -#----------------------------------------------------------------------------------------------------- + return {'FINISHED'} @persistent def marker_handler(scn): - context=bpy.context + context = bpy.context functions.initSceneProperties(context) - #preferences = context.user_preferences - #prefs = preferences.addons[__package__].preferences + if scn.kr_auto_markers: - #scn = context.scene - - markers =scn.timeline_markers - + markers = scn.timeline_markers + if "IN" in markers: - mark=markers["IN"] - mark.frame=scn.kr_in_marker + mark = markers["IN"] + mark.frame = scn.kr_in_marker else: - mark=markers.new(name="IN") - mark.frame=scn.kr_in_marker + mark = markers.new(name="IN") + mark.frame = scn.kr_in_marker if "OUT" in markers: - mark=markers["OUT"] - mark.frame=scn.kr_out_marker + mark = markers["OUT"] + mark.frame = scn.kr_out_marker else: - mark= markers.new(name="OUT") - mark.frame=scn.kr_out_marker + mark = markers.new(name="OUT") + mark.frame = scn.kr_out_marker - #limit OUT marker position with 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 - return {'FINISHED'} + return {'FINISHED'} else: return {'CANCELLED'} -bpy.app.handlers.scene_update_post.append(marker_handler) - - - - - - +bpy.app.handlers.scene_update_post.append(marker_handler) diff --git a/kinoraw_tools/operators_extra_actions.py b/kinoraw_tools/operators_extra_actions.py index cae4a5d4..1b52e3f2 100644 --- a/kinoraw_tools/operators_extra_actions.py +++ b/kinoraw_tools/operators_extra_actions.py @@ -17,45 +17,43 @@ # ##### END GPL LICENSE BLOCK ##### import bpy - -import random -import math -import os, sys - -from bpy.props import IntProperty -from bpy.props import FloatProperty -from bpy.props import EnumProperty -from bpy.props import BoolProperty -from bpy.props import StringProperty - +import os +from bpy.types import Operator +from bpy.props import ( + IntProperty, + FloatProperty, + EnumProperty, + BoolProperty, + ) from . import functions -from . import exiftool -# ------------------------------ -# SKIP ONE SECOND -class Sequencer_Extra_FrameSkip(bpy.types.Operator): - bl_label = 'Skip One Second' - bl_idname = 'screenextra.frame_skip' - bl_description = 'Skip through the Timeline by one-second increments' +# 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) + name="Back", + default=False + ) def execute(self, context): one_second = bpy.context.scene.render.fps - if self.back == True: + if self.back is True: one_second *= -1 bpy.ops.screen.frame_offset(delta=one_second) + return {'FINISHED'} - -# TRIM TIMELINE -class Sequencer_Extra_TrimTimeline(bpy.types.Operator): - bl_label = 'Trim to Timeline Content' - bl_idname = 'timeextra.trimtimeline' - bl_description = 'Automatically set start and end frames' + +# 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 @@ -88,17 +86,17 @@ class Sequencer_Extra_TrimTimeline(bpy.types.Operator): 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(bpy.types.Operator): - bl_label = 'Trim to Selection' - bl_idname = 'timeextra.trimtimelinetoselection' - bl_description = 'Set start and end frames to selection' +# 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 @@ -120,9 +118,9 @@ class Sequencer_Extra_TrimTimelineToSelection(bpy.types.Operator): frame_end = -300000 for i in seq.sequences: try: - if i.frame_final_start < frame_start and i.select == True: + 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 == True: + if i.frame_final_end > frame_end and i.select is True: frame_end = i.frame_final_end - 1 except AttributeError: pass @@ -131,26 +129,25 @@ class Sequencer_Extra_TrimTimelineToSelection(bpy.types.Operator): 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 -class Sequencer_Extra_CreateMovieclip(bpy.types.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' - """ +# 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): @@ -166,26 +163,27 @@ class Sequencer_Extra_CreateMovieclip(bpy.types.Operator): scn = context.scene if strip.type == 'MOVIE': - #print("movie", strip.frame_start) path = strip.filepath - #print(path) data_exists = False + for i in bpy.data.movieclips: if i.filepath == path: data_exists = True data = i newstrip = None - if data_exists == False: + 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 = 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) + # print(newstrip.frame_start, strip.frame_start, tin, tout) functions.triminout(newstrip, tin, tout) except: self.report({'ERROR_INVALID_INPUT'}, 'Error loading file') @@ -193,84 +191,91 @@ class Sequencer_Extra_CreateMovieclip(bpy.types.Operator): else: try: - newstrip = bpy.ops.sequencer.movieclip_strip_add(\ - replace_sel=True, overlap=False, clip=data.name) + 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] + 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 + # 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) + # 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") + # print("image") base_dir = bpy.path.abspath(strip.directory) - scn.frame_current = strip.frame_start -\ - strip.animation_offset_start + 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) + # print(path) data_exists = False for i in bpy.data.movieclips: - #print(i.filepath, path) + # print(i.filepath, path) if i.filepath == path: data_exists = True data = i - #print(data_exists) - if data_exists == False: + # 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 = 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] + 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) + # 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 = 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] + clip = bpy.context.scene.sequence_editor.sequences[ + newstrip.name + ] # cannot change this atributes 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 + # 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) + # print(newstrip.frame_start, strip.frame_start, tin, tout) functions.triminout(clip, tin, tout) except: self.report({'ERROR_INVALID_INPUT'}, 'Error loading file') @@ -285,11 +290,11 @@ class Sequencer_Extra_CreateMovieclip(bpy.types.Operator): return {'FINISHED'} -# OPEN IMAGE WITH EDITOR -class Sequencer_Extra_Edit(bpy.types.Operator): - bl_label = 'Open with Editor' - bl_idname = 'sequencerextra.edit' - bl_description = 'Open with Movie Clip or Image Editor' +# 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): @@ -313,11 +318,11 @@ class Sequencer_Extra_Edit(bpy.types.Operator): data_exists = True data = i - if data_exists == False: + if data_exists is False: try: data = bpy.data.movieclips.load(filepath=path) except: - self.report({'ERROR_INVALID_INPUT'}, 'Error loading file') + self.report({'ERROR_INVALID_INPUT'}, "Error loading file") return {'CANCELLED'} elif strip.type == 'IMAGE': @@ -331,7 +336,7 @@ class Sequencer_Extra_Edit(bpy.types.Operator): data_exists = True data = i - if data_exists == False: + if data_exists is False: try: data = bpy.data.images.load(filepath=path) except: @@ -350,11 +355,11 @@ class Sequencer_Extra_Edit(bpy.types.Operator): return {'FINISHED'} -# OPEN IMAGE WITH EXTERNAL EDITOR -class Sequencer_Extra_EditExternally(bpy.types.Operator): - bl_label = 'Open with External Editor' - bl_idname = 'sequencerextra.editexternally' - bl_description = 'Open with the default external image editor' +# 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): @@ -376,17 +381,17 @@ class Sequencer_Extra_EditExternally(bpy.types.Operator): bpy.ops.image.external_edit(filepath=path) except: self.report({'ERROR_INVALID_INPUT'}, - 'Please specify an Image Editor in Preferences > File') + "Please specify an Image Editor in Preferences > File") return {'CANCELLED'} return {'FINISHED'} -# FILE NAME TO STRIP NAME -class Sequencer_Extra_FileNameToStripName(bpy.types.Operator): - bl_label = 'File Name to Selected Strips Name' - bl_idname = 'sequencerextra.striprename' - bl_description = 'Set strip name to input file name' +# 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 @@ -405,37 +410,32 @@ class Sequencer_Extra_FileNameToStripName(bpy.types.Operator): seq = seq.meta_stack[meta_level - 1] selection = False for i in seq.sequences: - if i.select == True: + 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 == False: + if selection is False: self.report({'ERROR_INVALID_INPUT'}, - 'No image or movie strip selected') + "No image or movie strip selected") return {'CANCELLED'} return {'FINISHED'} -# ------------------------------ - - -# NAVIGATE UP -class Sequencer_Extra_NavigateUp(bpy.types.Operator): - bl_label = 'Navigate Up' - bl_idname = 'sequencerextra.navigateup' - bl_description = 'Move to Parent Timeline' +# 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): - strip = functions.act_strip(context) try: if context.scene.sequence_editor.meta_stack: return True - else: - return False + return False except: return False @@ -450,19 +450,15 @@ class Sequencer_Extra_NavigateUp(bpy.types.Operator): return {'FINISHED'} -# ------------------------------ - - -# RIPPLE DELETE -class Sequencer_Extra_RippleDelete(bpy.types.Operator): - bl_label = 'Ripple Delete' - bl_idname = 'sequencerextra.rippledelete' - bl_description = 'Delete a strip and shift back following ones' +# 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): - strip = functions.act_strip(context) scn = context.scene if scn and scn.sequence_editor and scn.sequence_editor.active_strip: return True @@ -475,7 +471,7 @@ class Sequencer_Extra_RippleDelete(bpy.types.Operator): meta_level = len(seq.meta_stack) if meta_level > 0: seq = seq.meta_stack[meta_level - 1] - #strip = functions.act_strip(context) + # strip = functions.act_strip(context) for strip in context.selected_editable_sequences: cut_frame = strip.frame_final_start next_edit = 300000 @@ -485,8 +481,8 @@ class Sequencer_Extra_RippleDelete(bpy.types.Operator): striplist = [] for i in seq.sequences: try: - if (i.frame_final_start > cut_frame - and not i.mute): + 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: @@ -508,16 +504,15 @@ class Sequencer_Extra_RippleDelete(bpy.types.Operator): return {'FINISHED'} -# RIPPLE CUT -class Sequencer_Extra_RippleCut(bpy.types.Operator): - bl_label = 'Ripple Cut' - bl_idname = 'sequencerextra.ripplecut' - bl_description = 'Move a strip to buffer and shift back following ones' +# 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): - strip = functions.act_strip(context) scn = context.scene if scn and scn.sequence_editor and scn.sequence_editor.active_strip: return True @@ -542,20 +537,21 @@ class Sequencer_Extra_RippleCut(bpy.types.Operator): return {'FINISHED'} -# INSERT -class Sequencer_Extra_Insert(bpy.types.Operator): - bl_label = 'Insert' - bl_idname = 'sequencerextra.insert' - bl_description = 'Move active strip to current frame and shift '\ - 'forward following ones' - singlechannel = BoolProperty( - name='Single Channel', - default=False) +# 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): - strip = functions.act_strip(context) scn = context.scene if scn and scn.sequence_editor and scn.sequence_editor.active_strip: return True @@ -576,9 +572,9 @@ class Sequencer_Extra_Insert(bpy.types.Operator): striplist = [] for i in seq.sequences: try: - if (i.frame_final_start >= current_frame - and not i.mute): - if self.singlechannel == True: + 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: @@ -589,14 +585,14 @@ class Sequencer_Extra_Insert(bpy.types.Operator): bpy.ops.sequencerextra.selectcurrentframe('EXEC_DEFAULT', mode='AFTER') except: - self.report({'ERROR_INVALID_INPUT'}, 'Execution Error, '\ - 'check your Blender version') + 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 == True: + if str.select is True: str.frame_start += gap except AttributeError: pass @@ -613,61 +609,61 @@ class Sequencer_Extra_Insert(bpy.types.Operator): return {'FINISHED'} -# COPY STRIP PROPERTIES -class Sequencer_Extra_CopyProperties(bpy.types.Operator): - bl_label = 'Copy Properties' - bl_idname = 'sequencerextra.copyproperties' - bl_description = 'Copy properties of active strip to selected strips' +# 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') + 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): - strip = functions.act_strip(context) scn = context.scene if scn and scn.sequence_editor and scn.sequence_editor.active_strip: return True @@ -676,7 +672,6 @@ class Sequencer_Extra_CopyProperties(bpy.types.Operator): def execute(self, context): strip = functions.act_strip(context) - selectedstrips = context.selected_editable_sequences scn = context.scene seq = scn.sequence_editor @@ -685,7 +680,7 @@ class Sequencer_Extra_CopyProperties(bpy.types.Operator): seq = seq.meta_stack[meta_level - 1] for i in seq.sequences: - if (i.select == True and not i.mute): + if (i.select is True and not i.mute): try: if self.prop == 'name': i.name = strip.name @@ -786,21 +781,22 @@ class Sequencer_Extra_CopyProperties(bpy.types.Operator): return {'FINISHED'} -# FADE IN AND OUT -class Sequencer_Extra_FadeInOut(bpy.types.Operator): - bl_idname = 'sequencerextra.fadeinout' - bl_label = 'Fade...' - bl_description = 'Fade volume or opacity of active strip' +# 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...', '')), + ('IN', "Fade In...", ""), + ('OUT', "Fade Out...", ""), + ('INOUT', "Fade In and Out...", "")), default='IN', ) - bl_options = {'REGISTER', 'UNDO'} - + fade_duration = IntProperty( name='Duration', description='Number of frames to fade', @@ -899,11 +895,11 @@ class Sequencer_Extra_FadeInOut(bpy.types.Operator): return context.window_manager.invoke_props_dialog(self) -# EXTEND TO FILL -class Sequencer_Extra_ExtendToFill(bpy.types.Operator): - bl_idname = 'sequencerextra.extendtofill' - bl_label = 'Extend to Fill' - bl_description = 'Extend active strip forward to fill adjacent space' +# 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 @@ -943,18 +939,17 @@ class Sequencer_Extra_ExtendToFill(bpy.types.Operator): 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'} -# PLACE FROM FILE BROWSER -class Sequencer_Extra_PlaceFromFileBrowser(bpy.types.Operator): - bl_label = 'Place' - bl_idname = 'sequencerextra.placefromfilebrowser' - bl_description = 'Place or insert active file from File Browser' insert = BoolProperty( - name='Insert', - default=False) - bl_options = {'REGISTER', 'UNDO'} + name="Insert", + default=False + ) def execute(self, context): scn = context.scene @@ -999,18 +994,18 @@ class Sequencer_Extra_PlaceFromFileBrowser(bpy.types.Operator): self.report({'ERROR_INVALID_INPUT'}, 'Error loading file') return {'CANCELLED'} - if self.insert == True: + if self.insert is True: try: striplist = [] for i in bpy.context.selected_editable_sequences: - if (i.select == True and i.type == "SOUND"): + 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') + self.report({'ERROR_INVALID_INPUT'}, "Execution Error, " + "check your Blender version") return {'CANCELLED'} else: strip = functions.act_strip(context) @@ -1020,19 +1015,15 @@ class Sequencer_Extra_PlaceFromFileBrowser(bpy.types.Operator): return {'FINISHED'} -# ------------------------------ - - -# SELECT STRIPS ON SAME CHANNEL -class Sequencer_Extra_SelectSameChannel(bpy.types.Operator): - bl_label = 'Select Strips on the Same Channel' - bl_idname = 'sequencerextra.selectsamechannel' - bl_description = 'Select strips on the same channel as active one' +# 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): - strip = functions.act_strip(context) scn = context.scene if scn and scn.sequence_editor and scn.sequence_editor.active_strip: return True @@ -1051,11 +1042,13 @@ class Sequencer_Extra_SelectSameChannel(bpy.types.Operator): return {'FINISHED'} -# CURRENT-FRAME-AWARE SELECT -class Sequencer_Extra_SelectCurrentFrame(bpy.types.Operator): - bl_label = 'Current-Frame-Aware Select' - bl_idname = 'sequencerextra.selectcurrentframe' - bl_description = 'Select strips according to current frame' +# 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=( @@ -1064,7 +1057,6 @@ class Sequencer_Extra_SelectCurrentFrame(bpy.types.Operator): ('ON', 'On Current Frame', '')), default='BEFORE', ) - bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(self, context): @@ -1086,25 +1078,23 @@ class Sequencer_Extra_SelectCurrentFrame(bpy.types.Operator): if mode == 'AFTER': for i in seq.sequences: try: - if (i.frame_final_start >= cf - and not i.mute): + 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): + 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): + if (i.frame_final_end < cf and not i.mute): i.select = True except AttributeError: pass @@ -1112,25 +1102,26 @@ class Sequencer_Extra_SelectCurrentFrame(bpy.types.Operator): return {'FINISHED'} -# SELECT BY TYPE -class Sequencer_Extra_SelectAllByType(bpy.types.Operator): - bl_label = 'All by Type' - bl_idname = 'sequencerextra.select_all_by_type' - bl_description = 'Select all the strips of the same type' +# 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', + name="Strip Type", items=( - ('ACTIVE', 'Same as Active Strip', ''), - ('IMAGE', 'Image', ''), - ('META', 'Meta', ''), - ('SCENE', 'Scene', ''), - ('MOVIE', 'Movie', ''), - ('SOUND', 'Sound', ''), - ('TRANSFORM', 'Transform', ''), - ('COLOR', 'Color', '')), + ('ACTIVE', 'Same as Active Strip', ''), + ('IMAGE', 'Image', ''), + ('META', 'Meta', ''), + ('SCENE', 'Scene', ''), + ('MOVIE', 'Movie', ''), + ('SOUND', 'Sound', ''), + ('TRANSFORM', 'Transform', ''), + ('COLOR', 'Color', '')), default='ACTIVE', ) - bl_options = {'REGISTER', 'UNDO'} @classmethod def poll(self, context): @@ -1149,7 +1140,7 @@ class Sequencer_Extra_SelectAllByType(bpy.types.Operator): seq = seq.meta_stack[meta_level - 1] active_strip = functions.act_strip(context) if strip_type == 'ACTIVE': - if active_strip == None: + if active_strip is None: self.report({'ERROR_INVALID_INPUT'}, 'No active strip') return {'CANCELLED'} @@ -1158,8 +1149,7 @@ class Sequencer_Extra_SelectAllByType(bpy.types.Operator): striplist = [] for i in seq.sequences: try: - if (i.type == strip_type - and not i.mute): + if (i.type == strip_type and not i.mute): striplist.append(i) except AttributeError: pass @@ -1173,13 +1163,11 @@ class Sequencer_Extra_SelectAllByType(bpy.types.Operator): return {'FINISHED'} -# ------------------------------ - -# OPEN IN MOVIE CLIP EDITOR FROM FILE BROWSER -class Clip_Extra_OpenFromFileBrowser(bpy.types.Operator): - bl_label = 'Open from File Browser' - bl_idname = 'clipextra.openfromfilebrowser' - bl_description = 'Load a Movie or Image Sequence from File Browser' +# 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): @@ -1197,7 +1185,6 @@ class Clip_Extra_OpenFromFileBrowser(bpy.types.Operator): self.report({'ERROR_INVALID_INPUT'}, 'No file selected') return {'CANCELLED'} - strip = functions.act_strip(context) path = params.directory + params.filename strip_type = functions.detect_strip_type(params.filename) data_exists = False @@ -1208,7 +1195,7 @@ class Clip_Extra_OpenFromFileBrowser(bpy.types.Operator): data_exists = True data = i - if data_exists == False: + if data_exists is False: try: data = bpy.data.movieclips.load(filepath=path) except: @@ -1225,11 +1212,11 @@ class Clip_Extra_OpenFromFileBrowser(bpy.types.Operator): return {'FINISHED'} -# OPEN IN MOVIE CLIP EDITOR FROM SEQUENCER -class Clip_Extra_OpenActiveStrip(bpy.types.Operator): - bl_label = 'Open Active Strip' - bl_idname = 'clipextra.openactivestrip' - bl_description = 'Load a Movie or Image Sequence from Sequence Editor' +# 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 @@ -1259,7 +1246,7 @@ class Clip_Extra_OpenActiveStrip(bpy.types.Operator): if i.filepath == path: data_exists = True data = i - if data_exists == False: + if data_exists is False: try: data = bpy.data.movieclips.load(filepath=path) except: @@ -1273,14 +1260,12 @@ class Clip_Extra_OpenActiveStrip(bpy.types.Operator): return {'FINISHED'} -# ------------------------------ - - -# JOG/SHUTTLE -class Sequencer_Extra_JogShuttle(bpy.types.Operator): - bl_label = 'Jog/Shuttle' - bl_idname = 'sequencerextra.jogshuttle' - bl_description = 'Jog through current sequence' +# 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 @@ -1313,4 +1298,5 @@ class Sequencer_Extra_JogShuttle(bpy.types.Operator): self.init_current_frame = scn.frame_current self.execute(context) context.window_manager.modal_handler_add(self) + return {'RUNNING_MODAL'} diff --git a/kinoraw_tools/proxy_tools.py b/kinoraw_tools/proxy_tools.py index 099dda60..33804241 100644 --- a/kinoraw_tools/proxy_tools.py +++ b/kinoraw_tools/proxy_tools.py @@ -1,17 +1,24 @@ -import bpy, os -from bpy.props import IntProperty, StringProperty, BoolProperty +# 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", "" )] - +proxy_qualities = [ + ("1", "25%", ""), ("2", "50%", ""), + ("3", "75%", ""), ("4", "100%", ""), + ("5", "none", "") + ] -# functions +# Functions def setup_proxy(context, strip, size): preferences = context.user_preferences prefs = preferences.addons[__package__].preferences @@ -22,11 +29,11 @@ def setup_proxy(context, strip, size): 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) + strip.proxy.directory = bpy.path.relpath(prefs.proxy_dir + filename) else: strip.use_proxy_custom_directory = False - if strip.use_proxy_custom_file == True: + if strip.use_proxy_custom_file is True: strip.use_proxy_custom_file = False strip.proxy.quality = prefs.quality @@ -40,7 +47,7 @@ def setup_proxy(context, strip, size): strip.proxy.build_100 = False else: - proxysuffix = proxy_qualities[size-1][1].split("%")[0] + proxysuffix = proxy_qualities[size - 1][1].split("%")[0] if (proxysuffix == "25"): strip.proxy.build_25 = True @@ -51,14 +58,13 @@ def setup_proxy(context, strip, size): 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)) + div = 4 / size + newres = (int(int(res[0]) / div), int(int(res[1]) / div)) preferences = context.user_preferences proxy_dir = preferences.addons[__package__].preferences.proxy_dir @@ -73,12 +79,12 @@ def create_proxy(context, strip, size, res): # get filename if strip.type == "MOVIE": filename = bpy.path.abspath(strip.filepath) - proxysuffix = proxy_qualities[size-1][1].split("%")[0] + 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" + 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 {}" + # 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) @@ -90,12 +96,16 @@ def create_proxy(context, strip, size, res): if not os.path.isfile(fileoutput): subprocess.call(command, shell=True) else: - print("ya existe") + print("File already exists") # set up proxy settings strip.use_proxy = True - strip.use_proxy_custom_file = True - strip.proxy.filepath = bpy.path.relpath(fileoutput) + 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"): @@ -111,32 +121,30 @@ def create_proxy(context, strip, size, res): return None -def create_proxy_scripts(scripts_dir, commands, strip_name = 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) + # print(i) filename = "{}/proxy_script_{}.sh".format(scripts_dir, strip_name) text_file = open(bpy.path.abspath(filename), "w") - #print(filename) + # print(filename) text_file.write(i) text_file.close() - # classes - -class CreateProxyOperator(bpy.types.Operator): - """ Use ffmpeg to create a proxy from video and setup proxies \ - for selected strip""" +class CreateProxyOperator(Operator): bl_idname = "sequencer.create_proxy_operator" - bl_label = " Create proxy" + 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='proxysize', - default=1) - bl_options = {'REGISTER', 'UNDO'} + name="Proxy Size", + default=1 + ) @classmethod def poll(self, context): @@ -148,25 +156,25 @@ class CreateProxyOperator(bpy.types.Operator): return False def execute(self, context): - preferences = context.user_preferences - proxy_dir = preferences.addons[__package__].preferences.proxy_dir - scripts = preferences.addons[__package__].preferences.proxy_scripts proxy_scripts_path = preferences.addons[__package__].preferences.proxy_scripts_path - for strip in context.selected_editable_sequences: + for strip in context.selected_editable_sequences: # get resolution from active strip - bpy.ops.sequencerextra.read_exif() + 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) - #print(res) + res = (sce.render.resolution_x, sce.render.resolution_y) commands = create_proxy(context, strip, self.size, res) - if commands == None: + if commands is None: # Update scene context.scene.update() newstrip = context.scene.sequence_editor.active_strip @@ -174,26 +182,26 @@ class CreateProxyOperator(bpy.types.Operator): # deselect all other strips for i in context.selected_editable_sequences: if i.name != newstrip.name: - i.select=False + i.select = False # Update scene context.scene.update() else: create_proxy_scripts(proxy_scripts_path, commands, strip.name) - return {'FINISHED'} -class CreateBIProxyOperator(bpy.types.Operator): - """ Use BI system to create a proxy""" +class CreateBIProxyOperator(Operator): bl_idname = "sequencer.create_bi_proxy_operator" - bl_label = " Create proxy with blender internal" + bl_label = "Create proxy with Blender Internal" + bl_description = "Use BI system to create a proxy" + bl_options = {'REGISTER', 'UNDO'} size = IntProperty( - name='proxysize', - default=1) - bl_options = {'REGISTER', 'UNDO'} + name="Proxy Size", + default=1 + ) @classmethod def poll(self, context): @@ -205,39 +213,46 @@ class CreateBIProxyOperator(bpy.types.Operator): return False def execute(self, context): + try: + strips = functions.get_selected_strips(context) - preferences = context.user_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": - setup_proxy(context, strip, self.size) - #select all strips again + 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 + try: + strip.select = True except ReferenceError: pass bpy.ops.sequencer.reload() + return {'FINISHED'} -class CreateProxyToolPanel(bpy.types.Panel): - """ """ +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'}: + 'SEQUENCER_PREVIEW'}: strip = functions.act_strip(context) scn = context.scene preferences = context.user_preferences @@ -258,7 +273,7 @@ class CreateProxyToolPanel(bpy.types.Panel): prefs = preferences.addons[__package__].preferences layout = self.layout - layout.prop(prefs, "use_internal_proxy", text="use BI proxy builder") + layout.prop(prefs, "use_internal_proxy", text="Use BI proxy builder") strip = functions.act_strip(context) @@ -270,7 +285,7 @@ class CreateProxyToolPanel(bpy.types.Panel): if prefs.use_bi_custom_directory: row.prop(prefs, "proxy_dir", text="") filename = strip.filepath.rpartition("/")[2].rpartition(".")[0] - layout.label("sample dir: //"+bpy.path.abspath(prefs.proxy_dir+filename)) + layout.label("sample dir: //" + bpy.path.abspath(prefs.proxy_dir + filename)) layout = self.layout col = layout.column() @@ -284,24 +299,24 @@ class CreateProxyToolPanel(bpy.types.Panel): col.prop(prefs, "timecode") layout = self.layout - layout.label("setup and create BI proxy:") - row = layout.row(align=True) + layout.label("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 + text=proxysuffix).size = i + 1 layout = self.layout - layout.operator("sequencer.create_bi_proxy_operator", - text="Clear proxy sizes").size=5 + 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.prop(prefs, "proxy_dir", text="Path for proxies") layout = self.layout - layout.label("create and import proxy from clip:") + layout.label("Create and import proxy from clip:") row = layout.row(align=True) layout = self.layout @@ -310,24 +325,20 @@ class CreateProxyToolPanel(bpy.types.Panel): layout.label("{} = 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 + 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.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") - - - - + box.operator("sequencer.rebuild_proxy", text="Rebuild Proxies and TC") diff --git a/kinoraw_tools/random_editor.py b/kinoraw_tools/random_editor.py index 5735bb3e..e52f3fc4 100644 --- a/kinoraw_tools/random_editor.py +++ b/kinoraw_tools/random_editor.py @@ -16,17 +16,22 @@ # # ##### END GPL LICENSE BLOCK ##### -import bpy, os, random -from bpy.props import IntProperty, BoolProperty, StringProperty - +# 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(bpy.types.Operator): - """ Random Scratch Operator """ +# classes +class RandomScratchOperator(Operator): bl_idname = "sequencer.randomscratchoperator" bl_label = "Random Scratch Operator" + bl_description = "Random Scratch Operator" @classmethod def poll(self, context): @@ -38,21 +43,21 @@ class RandomScratchOperator(bpy.types.Operator): return False def invoke(self, context, event): - preferences = context.user_preferences random_frames = preferences.addons[__package__].preferences.random_frames sce = context.scene - seq=sce.sequence_editor - markers=sce.timeline_markers + seq = sce.sequence_editor + markers = sce.timeline_markers + if seq: - strip= seq.active_strip - if strip != None: + 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 + 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 @@ -62,120 +67,42 @@ class RandomScratchOperator(bpy.types.Operator): 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) + 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] + 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 + 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 + 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") - bpy.ops.sequencer.reload() - return {'FINISHED'} - + self.report({'WARNING'}, "There is no IN and OUT Markers") + bpy.ops.sequencer.reload() -class LoadRandomEditOperator(bpy.types.Operator): - """ Random Editor Operator """ - bl_idname = "sequencer.loadrandomeditoperator" - bl_label = "Random Editor 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 + return {'FINISHED'} - def invoke(self, context, event): - - #generate sources_dict - sources_dict = functions.get_marker_dict(random_selected_scene, random_number_of_subsets) - print("sources: ",sources_dict) - - #generate cut_list - cut_dict = functions.get_cut_dict(currentscene, random_number_of_subsets) - print("cuts: ",cut_dict) - - #generate random_edit - random_edit = functions.random_edit_from_random_subset(cut_dict, sources_dict) - print("random edit") - for i in random_edit: print("fr {}: dur: {} / {} {}".format(i[0],i[1],i[2],i[3])) - - sce = bpy.context.scene - seq=sce.sequence_editor - markers=sce.timeline_markers - strip= seq.active_strip - stripname = strip.name - if "IN" and "OUT" in markers: - sin=markers["IN"].frame - sout=markers["OUT"].frame - # 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 random_edit: - # 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 bpy.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 bpy.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, MARKER, MARKER+DURATION) - 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") - bpy.ops.sequencer.reload() - return {'FINISHED'} - -class RandomEditorPanel(bpy.types.Panel): - """-_-_-""" +class RandomEditorPanel(Panel): bl_label = "Random Editor" bl_idname = "OBJECT_PT_RandomEditor" bl_space_type = 'SEQUENCE_EDITOR' @@ -184,7 +111,7 @@ class RandomEditorPanel(bpy.types.Panel): @classmethod def poll(self, context): if context.space_data.view_type in {'SEQUENCER', - 'SEQUENCER_PREVIEW'}: + 'SEQUENCER_PREVIEW'}: strip = functions.act_strip(context) scn = context.scene preferences = context.user_preferences @@ -205,14 +132,7 @@ class RandomEditorPanel(bpy.types.Panel): prefs = preferences.addons[__package__].preferences layout = self.layout - layout.label("______ cut duration:)") - layout = self.layout - layout.prop(prefs, "random_frames") - layout = self.layout - layout.operator("sequencer.randomscratchoperator") - layout = self.layout - layout.operator("sequencer.loadrandomeditoperator") - - - - + col = layout.column(align=True) + col.label("Cut duration:") + col.prop(prefs, "random_frames") + col.operator("sequencer.randomscratchoperator") diff --git a/kinoraw_tools/recursive_loader.py b/kinoraw_tools/recursive_loader.py index 82e4820e..22b34754 100644 --- a/kinoraw_tools/recursive_loader.py +++ b/kinoraw_tools/recursive_loader.py @@ -17,42 +17,40 @@ # ##### END GPL LICENSE BLOCK ##### import bpy - -import random -import math -import os, sys - -from bpy.props import IntProperty -from bpy.props import FloatProperty -from bpy.props import EnumProperty -from bpy.props import BoolProperty -from bpy.props import StringProperty - +import os +from bpy.types import ( + Operator, + Panel, + ) +from bpy.props import ( + EnumProperty, + BoolProperty, + ) from . import functions from . import exiftool -class Sequencer_Extra_RecursiveLoader(bpy.types.Operator): +class Sequencer_Extra_RecursiveLoader(Operator): bl_idname = "sequencerextra.recursiveload" - bl_label = "recursive load" + bl_label = "Recursive Load" bl_options = {'REGISTER', 'UNDO'} - + recursive = BoolProperty( - name='recursive', - description='Load in recursive folders', - default=False) - + 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) - + name="Select by extension", + description="Load only clips with selected extension", + default=False + ) ext = EnumProperty( - items=functions.movieextdict, - name="extension", - default="3") + items=functions.movieextdict, + name="Extension", + default='3' + ) - @classmethod def poll(self, context): scn = context.scene @@ -60,21 +58,21 @@ class Sequencer_Extra_RecursiveLoader(bpy.types.Operator): 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 + 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) - + self.ext = scn.kr_default_ext + + return context.window_manager.invoke_props_dialog(self) + def loader(self, context, filelist): scn = context.scene if filelist: @@ -88,54 +86,60 @@ class Sequencer_Extra_RecursiveLoader(bpy.types.Operator): self.report({'ERROR_INVALID_INPUT'}, 'Error loading file ') pass - def execute(self, context): scn = context.scene - if self.recursive == True: - #recursive - self.loader(context, functions.sortlist(\ - functions.recursive(context, self.recursive_select_by_extension,\ - self.ext))) + 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 + # 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 -class Sequencer_Extra_ReadExifData(bpy.types.Operator): - # load exifdata from strip to scene['metadata'] property - bl_label = 'Read EXIF Data' - bl_idname = 'sequencerextra.read_exif' - bl_description = 'Load exifdata from strip to metadata property in scene' +# 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 + 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') + self.report({'ERROR_INVALID_INPUT'}, "exiftool not found in PATH") + return {'CANCELLED'} def getexifdata(strip): @@ -147,7 +151,7 @@ class Sequencer_Extra_ReadExifData(bpy.types.Operator): metadata = et.get_metadata_batch(lista) except UnicodeDecodeError as Err: print(Err) - #print(metadata[0]) + # print(metadata[0]) print(len(metadata)) return metadata @@ -165,11 +169,13 @@ class Sequencer_Extra_ReadExifData(bpy.types.Operator): 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: + if "." + f.rpartition(".")[2].lower() in \ + functions.imb_ext_image: lista.append(f) - #if "."+f.rpartition(".")[2] in imb_ext_movie: - # lista.append(f) + """ + if "." + f.rpartition(".")[2] in imb_ext_movie: + lista.append(f) + """ strip.elements lista.sort() return lista @@ -177,7 +183,7 @@ class Sequencer_Extra_ReadExifData(bpy.types.Operator): if strip.type == "IMAGE": path = bpy.path.abspath(strip.directory) os.chdir(path) - #get a list of files + # get a list of files lista = [] for i in strip.elements: lista.append(i.filename) @@ -188,20 +194,18 @@ class Sequencer_Extra_ReadExifData(bpy.types.Operator): path = bpy.path.abspath(strip.filepath) print([path]) return getexifvalues_movie(path) - - sce = bpy.context.scene - frame = sce.frame_current - text = bpy.context.active_object strip = context.scene.sequence_editor.active_strip sce['metadata'] = getexifdata(strip) + return {'FINISHED'} -class ExifInfoPanel(bpy.types.Panel): +# TODO: fix poll to hide when unuseful + +class ExifInfoPanel(Panel): """Creates a Panel in the Object properties window""" - """ TODO: fix poll to hide when unuseful""" bl_label = "EXIF Info Panel" bl_space_type = 'SEQUENCE_EDITOR' bl_region_type = 'UI' @@ -213,7 +217,7 @@ class ExifInfoPanel(bpy.types.Panel): scn = context.scene preferences = context.user_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') @@ -255,7 +259,8 @@ class ExifInfoPanel(bpy.types.Panel): col.label(text=d) col = split.column() col.label(str(sce['metadata'][frame - f][d])) + except (IndexError, KeyError): pass except AttributeError: - pass
\ No newline at end of file + pass diff --git a/kinoraw_tools/ui.py b/kinoraw_tools/ui.py index d9be3042..51b5de42 100644 --- a/kinoraw_tools/ui.py +++ b/kinoraw_tools/ui.py @@ -17,106 +17,109 @@ # ##### END GPL LICENSE BLOCK ##### import bpy - +from bpy.types import ( + Menu, + Panel, + ) from . import functions - # UI -class SEQUENCER_EXTRA_MT_input(bpy.types.Menu): +class SEQUENCER_EXTRA_MT_input(Menu): bl_label = "Input" def draw(self, context): - self.layout.operator_context = 'INVOKE_REGION_WIN' - self.layout.operator('sequencerextra.striprename', - text='File Name to Strip Name', icon='PLUGIN') - self.layout.operator('sequencerextra.editexternally', - text='Open with External Editor', icon='PLUGIN') - self.layout.operator('sequencerextra.edit', - text='Open with Editor', icon='PLUGIN') - self.layout.operator('sequencerextra.createmovieclip', - text='Create Movieclip strip', icon='PLUGIN') + self.layout.label("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', icon='PLUGIN').insert = False - self.layout.operator('sequencerextra.placefromfilebrowser', - text='insert from file browser', icon='PLUGIN').insert = True - self.layout.operator('sequencerextra.recursiveload', - text='recursive load from browser', icon='PLUGIN') + 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', icon='PLUGIN') + 'type', text='All by Type') self.layout.separator() self.layout.operator('sequencerextra.selectcurrentframe', - text='Before Current Frame', icon='PLUGIN').mode = 'BEFORE' + text='Before Current Frame').mode = 'BEFORE' self.layout.operator('sequencerextra.selectcurrentframe', - text='After Current Frame', icon='PLUGIN').mode = 'AFTER' + text='After Current Frame').mode = 'AFTER' self.layout.operator('sequencerextra.selectcurrentframe', - text='On Current Frame', icon='PLUGIN').mode = 'ON' + text='On Current Frame').mode = 'ON' self.layout.separator() self.layout.operator('sequencerextra.selectsamechannel', - text='Same Channel', icon='PLUGIN') + text='Same Channel') def sequencer_strip_menu_func(self, context): self.layout.operator('sequencerextra.extendtofill', - text='Extend to Fill', icon='PLUGIN') + text='Extend to Fill') self.layout.operator_menu_enum('sequencerextra.fadeinout', - 'mode', text='Fade', icon='PLUGIN') + 'mode', text='Fade') self.layout.operator_menu_enum('sequencerextra.copyproperties', - 'prop', icon='PLUGIN') - - self.layout.operator('sequencerextra.insert', - text='Insert (Single Channel)', icon='PLUGIN').singlechannel = True - self.layout.operator('sequencerextra.insert', - text='Insert', icon='PLUGIN').singlechannel = False - self.layout.operator('sequencerextra.ripplecut', - text='Ripple Cut', icon='PLUGIN') - self.layout.operator('sequencerextra.rippledelete', - text='Ripple Delete', icon='PLUGIN') + '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', icon='PLUGIN') + text='Trim to Selection') self.layout.operator('timeextra.trimtimeline', - text='Trim to Timeline Content', icon='PLUGIN') + text='Trim to Timeline Content') self.layout.separator() self.layout.operator('screenextra.frame_skip', - text='Skip Forward One Second', icon='PLUGIN').back = False + text='Skip Forward One Second').back = False self.layout.operator('screenextra.frame_skip', - text='Skip Back One Second', icon='PLUGIN').back = True + 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') + text='Jog/Shuttle', icon='NDOF_TURN') def clip_header_func(self, context): self.layout.operator('sequencerextra.jogshuttle', - text='Jog/Shuttle', icon='NDOF_TURN') + text='Jog/Shuttle', icon='NDOF_TURN') def clip_clip_menu_func(self, context): self.layout.operator('clipextra.openactivestrip', - text='Open Active Strip', icon='PLUGIN') + text='Open Active Strip') self.layout.operator('clipextra.openfromfilebrowser', - text='Open from File Browser', icon='PLUGIN') + text='Open from File Browser') self.layout.separator() - - - -############################### def draw_color_balance(layout, color_balance): @@ -130,30 +133,28 @@ def draw_color_balance(layout, color_balance): col = layout.column() col.label(text="Gamma:") - col.template_color_picker(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True) + 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) + 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(bpy.types.Panel): +class JumptoCut(Panel): bl_space_type = "SEQUENCE_EDITOR" bl_region_type = "UI" - bl_label = "Jump to Cut 6" + bl_label = "Jump to Cut" COMPAT_ENGINES = {'BLENDER_RENDER'} - + _frame_rate_args_prev = None _preset_class = None @@ -201,7 +202,6 @@ class JumptoCut(bpy.types.Panel): @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.user_preferences prefs = preferences.addons[__package__].preferences @@ -218,250 +218,255 @@ class JumptoCut(bpy.types.Panel): def draw(self, context): scn = context.scene strip = functions.act_strip(context) - + preferences = context.user_preferences prefs = preferences.addons[__package__].preferences - + layout = self.layout layout = layout.box() # jump to cut main controls - - row=layout.row(align=True) - - row.label(icon='TIME', text="Secs") + col = layout.column(align=True) + row = col.row(align=True) + split = row.split(percentage=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 + text="", icon='TRIA_LEFT').back = True row.operator('screenextra.frame_skip', - text="", icon='TRIA_RIGHT').back = False - - row.separator() - - 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 - - row.separator() - + 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 - - + 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 = layout.row(align=True) - row.operator("screen.frame_jump", text="", icon='REW').end = False - row.operator("screen.keyframe_jump", text="", icon='PREV_KEYFRAME').next = False + row = col.row(align=True) + split = row.split(percentage=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.user_preferences.system.audio_device == 'JACK': - sub = row.row(align=True) + # hide the play-reversed button + # since JACK transport doesn't support reversed playback + if scn.sync_mode == 'AUDIO_SYNC' and \ + context.user_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: - row.operator("screen.animation_play", text="", icon='PLAY_REVERSE').reverse = True - row.operator("screen.animation_play", text="", icon='PLAY') + sub_row.operator("screen.animation_play", text="", + icon='PLAY_REVERSE').reverse = True + sub_row.operator("screen.animation_play", text="", icon='PLAY') else: - sub = row.row(align=True) + sub = sub_row.row(align=True) sub.scale_x = 2.0 - sub.operator("screen.animation_play", text="", icon='PAUSE') - row.operator("screen.keyframe_jump", text="", icon='NEXT_KEYFRAME').next = True - row.operator("screen.frame_jump", text="", icon='FF').end = True - - row.separator() - row.prop(scn, "sync_mode", text="") - row.separator() - self.draw_framerate(row, rd) - - row=layout.row(align=True) + 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', icon='PLUGIN') + row.operator("sequencer.rendersize", text="Set Render size") - row=layout.row(align=True) + 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 - # layout = layout.box() - # panel setup ------------------------------------------------------ - row=layout.row(align=True) - row = row.split(percentage=0.25) - row.prop(prefs, "kr_show_tools", text="Tools", icon='SEQ_SEQUENCER') + 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(percentage=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: - row = row.split(percentage=0.25) - row.prop(prefs, "kr_mini_ui", text="mini") - else: - row = row.split(percentage=0.25) - row.label(text = "") - - row = row.split(percentage=0.25) - row.label(text = "") - row = row.split(percentage=0.25) - row.label(text = "") - row = row.split(percentage=0.33) + sub_row.prop(prefs, "kr_mini_ui", text="Compact UI", toggle=True) + + row = split.row() + row = row.split(percentage=0.33) row.prop(prefs, "kr_show_info", text="", icon='VIEWZOOM') - row = row.split(percentage=0.5) + row = row.split(percentage=0.5) row.prop(prefs, "kr_extra_info", text="", icon='BORDERMOVE') - row = row.split(percentage=1) + row = row.split(percentage=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='SNAP_SURFACE').align=1 - row.operator('sequencerextra.extrasnap', text='', icon='SNAP_ON').align=2 + row = layout.row(align=True) + row.operator("sequencerextra.extrasnap", text="", icon="SNAP_ON").align = 0 + row.operator("sequencerextra.extrasnap", text="", icon="SNAP_SURFACE").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.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.operator("sequencerextra.metapaste", icon="PASTEDOWN", text="") row.separator() - row.operator('sequencerextra.meta_separate_trim', text='', icon='ALIGN') + row.operator("sequencerextra.meta_separate_trim", text="", icon="ALIGN") row.separator() - row.prop(prefs, "use_io_tools", text="I/O tools") - - # IN /OUT TOOLS - - + 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 == True: - row.prop(scn, "kr_auto_markers", text="") - + 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") + 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: # NOT prefs.kr_mini_ui: - - row=layout.row(align=True) - row.label("Snap:") - #row=layout.row(align=True) - 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 = 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("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("Handlers:") - #row=layout.row(align=True) - 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 - - row=layout.row() - row=layout.row(align=True) - split = row.split(percentage=0.99) - colR2 = split.column() - row1 = colR2.row(align=True) - row1.operator("sequencerextra.metacopy", icon="COPYDOWN", text="meta-copy") - row1.operator("sequencerextra.metapaste", icon='PASTEDOWN', text="paste-snap") - split = row.split(percentage=0.99) - colR3 = split.column() - colR3.operator('sequencerextra.meta_separate_trim', text='unMeta & Trim', icon='ALIGN') - - - - # IN /OUT TOOLS - row=layout.box() - split=row.split(percentage=0.7) - colR1 = split.column() - row1=colR1.row(align=True) - row1.operator("sequencerextra.sourcein", icon="MARKER_HLT", text="set IN") - row1.operator("sequencerextra.sourceout", icon='MARKER_HLT', text="set OUT") - colR3 = split.column() - colR3.operator("sequencerextra.setinout", icon="ARROW_LEFTRIGHT", text="selected") - - split=row.split(percentage=0.7) - colR1 = split.column() - row1=colR1.row(align=True) - if scn.kr_auto_markers == False: - row1.prop(scn, "kr_auto_markers", text="auto markers") + 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(percentage=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: - row1.prop(scn, "kr_auto_markers", text="") - row1.prop(scn, "kr_in_marker") - row1.prop(scn, "kr_out_marker") - row1.active = scn.kr_auto_markers - colR3 = split.column() - colR3.operator("sequencerextra.triminout", icon="FULLSCREEN_EXIT", text="trim",emboss=True) - - + 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 - row=layout.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=layout.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') + 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 - # INFO boxes - # INFO boxes - if strip != None: + if strip is not None: if prefs.kr_show_info: layout = layout.box() row = layout.split(percentage=0.075) - row.prop(prefs, "kr_show_info", text="",icon='VIEWZOOM', emboss=True) + row.prop(prefs, "kr_show_info", text="", icon='VIEWZOOM', emboss=True) row = row.split(percentage=0.3) row.prop(strip, "type", text="") row = row.split(percentage=1) row.prop(strip, "name", text="") - - # MUTE INFORMATION + + # mute information layout.active = (not strip.mute) # basic info @@ -473,51 +478,60 @@ class JumptoCut(bpy.types.Panel): # source info row = layout.split(percentage=0.8) - if strip.type in {'MOVIE', 'SOUND'}: + 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() - row.prop(elem, "filename", text="File") # strip.elements[0] could be a fallback + # 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 = "") + row.prop(strip, "color", text="") # trim info if strip.type not in {"SPEED", "WIPE", "CROSS", "ADJUSTMENT"}: - row = row.split(percentage=1) - row.prop(prefs, "kr_show_trim", text="Trim") + row = row.split(percentage=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 = layout.row(align=True) - row.label(text="hard:") + 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 = layout.row(align=True) - row.label(text="soft:") + 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'}: + + 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) @@ -574,22 +588,22 @@ class JumptoCut(bpy.types.Panel): 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') + sub.operator("screen.animation_play", text="", icon='PAUSE' if + context.screen.is_animation_playing else 'PLAY') row.label("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") + col.prop(strip, "input_2") except AttributeError: pass - + # extra info box: if prefs.kr_extra_info: layout = self.layout @@ -597,53 +611,59 @@ class JumptoCut(bpy.types.Panel): if strip.type not in {'SOUND'}: row = box.row(align=True) sub = row.row(align=True) - # MUTE THIS BOX + # mute this box box.active = (not strip.mute) - sub.prop(prefs, "kr_extra_info", text = "", icon='BORDERMOVE', emboss = True) + 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) - row = box.row(align=True) - - col = row.column() - col.prop(strip, "strobe") - col.prop(strip, "use_flip_x", text="flip X") - col.prop(strip, "use_flip_y", text="flip Y") - col.prop(strip, "use_reverse_frames", text="Backwards") - col.prop(strip, "use_deinterlace") - - col = row.column() - col.prop(strip, "blend_type", icon='COLOR', text = "") + split = box.split(percentage=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") - col.prop(strip, "alpha_mode") - + 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") + 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") + 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") - - - #sound type + else: - row = box.row(align=True) - row.prop(strip, "volume") - row.prop(strip, "mute", toggle=True, icon_only=True) - row.prop(strip, "lock", toggle=True, icon_only=True) - + # 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() @@ -652,28 +672,29 @@ class JumptoCut(bpy.types.Panel): else: row.operator("sound.pack", icon='UGLYPACKAGE', text="Pack") - row.prop(sound, "use_memory_cache") + row.prop(sound, "use_memory_cache", toggle=True, icon="DISK_DRIVE") - row.prop(strip, "show_waveform") - - row = box.row() + row.prop(strip, "show_waveform", toggle=True, icon="RNDCURVE") + + row = box.row(align=True) row.prop(strip, "pitch") row.prop(strip, "pan") - - - ## modifiers + + # modifiers if strip.type != 'SOUND' and prefs.kr_show_modifiers: sequencer = context.scene.sequence_editor layout = self.layout layout = layout.box() - # MUTE THIS BOX + # mute this box layout.active = (not strip.mute) row = layout.split(percentage=0.075) - row.prop(prefs, "kr_show_modifiers", text = "", icon='RESTRICT_VIEW_OFF', emboss = True) + row.prop(prefs, "kr_show_modifiers", text="", + icon='RESTRICT_VIEW_OFF', emboss=True) row = row.split(percentage=0.40) row.prop(strip, "use_linear_modifiers", text="Linear") row = row.split(percentage=1) row.operator_menu_enum("sequencer.strip_modifier_add", "type") + for mod in strip.modifiers: box = layout.box() @@ -691,7 +712,8 @@ class JumptoCut(bpy.types.Panel): props.name = mod.name props.direction = 'DOWN' - row.operator("sequencer.strip_modifier_remove", text="", icon='X', emboss=False).name = mod.name + row.operator("sequencer.strip_modifier_remove", text="", icon='X', + emboss=False).name = mod.name if mod.show_expanded: row = box.row() @@ -701,7 +723,8 @@ class JumptoCut(bpy.types.Panel): 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") + box.prop_search(mod, "input_mask_strip", + sequences_object, "sequences", text="Mask") else: box.prop(mod, "input_mask_id") row = box.row() @@ -733,25 +756,10 @@ class JumptoCut(bpy.types.Panel): 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') - - - - - - - - - - - - - - - - - + row.operator("sequencer.copy_modifiers", + text="Copy Modifiers", icon='COPYDOWN') + row.operator("sequencer.paste_modifiers", + text="Paste Modifiers", icon='PASTEDOWN') |